Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deal with case when inputs contains empty lists #4664

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

ArpegorPSGH
Copy link
Contributor

Addressed problem description

Sometimes, the List Mask Join (In) node can be used to switch between empty lists and non empty ones, in order to make sure no empty list get to the rest of the treatment. In this case, the chosen data with the mask is of course that of the non-empty lists, but the node outputed nothing because of the match length option.

Solution description

So, I changed how matching length was done so that it works fine even in this case, while preserving how the node works in other cases. While I was at it, I added ValueErrors when mask is empty, both true and false data are empty, or data from an empty list is selected with the mask.

Preflight checklist

  • Code changes complete.
  • Code documentation complete.
  • Manual testing done.
  • Ready for merge.

@satabol
Copy link
Collaborator

satabol commented Sep 16, 2022

What do you think about case when every list is empty? (Length of mask/data_t/data_f == 0). Your code rise exception but I think this case is not an error.

@Durman
Copy link
Collaborator

Durman commented Sep 16, 2022

It seems works perfectly normal with empty lists already.

image

Raising an error just makes the work more inconvenient. It's normal situation when some objects are empty lists and nodes should be able to handle them without blocking execution of next nodes.

@ArpegorPSGH
Copy link
Contributor Author

No it does not work fine, because whatever you do, you will never be able to get data from your list [1, 2, 3], but you definitely should be able to. So, instead of raising an error, maybe only picking the data which exists, and ignoring the rest is the way to go? However, if the mask is empty, it should still raise an error, since the node cannot do anything without a mask, right?

@Durman
Copy link
Collaborator

Durman commented Sep 16, 2022

The principles are next - any object can be an empty list, empty ojects should not prevent a node from handling nonempty objects. And I guess if an input is mandatory and it is an empty list then output also should be an empty list. I don't think we should make nodes too much clever. Users always can replace empty lists with something else if they need.

@ArpegorPSGH
Copy link
Contributor Author

ArpegorPSGH commented Sep 16, 2022

Currently, an empty mask does prevent the node from doing anything, so it should raise an error. Empty true or false data do also prevent dealing with this specific pair of inputs, and as I explained, sometimes the whole point of the node is to deal with empty lists on one of the inputs. I will perform the modifications so that the node works even in this case, and precise on the documentation how this case is handled.
What I think would be the simplest is to just have an error when the mask input is empty, and otherwise replace the empty list by a list of None objects the length ot the complementary list. This should solve my problem while absolutely not modyfying how it currently works.

@ArpegorPSGH
Copy link
Contributor Author

Is my pull request okay for merge, now, @Durman?

@Durman
Copy link
Collaborator

Durman commented Sep 19, 2022

The old version supported empty lists in the mask input too.

image

And I'm not sure about None values. As far as I know none of the nodes returns None. =)

image

Sverchok does not have tools to work with None values.

@ArpegorPSGH
Copy link
Contributor Author

The old version supported empty lists in the mask input too.

I did not see this use case, so I can remove the error raising, no problem.

And I'm not sure about None values.

What would you consider as default value instead of None? Maybe having None values crash following nodes could help detect that the mask used is wrong as it tries to choose data that does not exist.

@Durman
Copy link
Collaborator

Durman commented Sep 19, 2022

Empty lists are not something wrong. They should not break nodes work. I'm, actually, quite satisfied with how the node currently works without the proposed changes.

@ArpegorPSGH
Copy link
Contributor Author

You may be, but I am not, since it makes my node tree unusable in some cases, and there is no other way to circumvent the problem. Empty lists are not wrong, what is wrong is that when one list is empty, the output is automatically empty, even if the data of interest is in a non-empty list. So, non-empty data should be retrievable regardless of the other input list, and the only way, with the matching length mechanism, is to fill empty list with default data, and then, to either choose data as normal, or to ignore chosen default data, but I cannot imagine anyone would want the latter, and if it ever happened, there would be the risk of a silent problem arising.

@Durman
Copy link
Collaborator

Durman commented Sep 20, 2022

image
This is how you currently can handle your problem. I don't see the point of injecting None values since they break the work of next nodes.

@ArpegorPSGH
Copy link
Contributor Author

That is not my exact problem case : both my Data True and Data False are one level lists : [a, b, c, ...], and sometimes one of them is empty : []. In your example, the Switch node works by default on second level, so I would have to wrap and then unwrap my data. Moreover, the Switch seems to have a length matching function, so the same problem as with List Mask Join will arise.
I used None default values because it will make the problem apparent, but I could have put a 0 default value, or anything else. Remember, the default value should not be chosen, if it is, it indicates that the node tree malfunctions, so raising an error right after the node is better than staying silent and raising one further down the tree.

@Durman
Copy link
Collaborator

Durman commented Sep 20, 2022

One level lists are not supported even by List Mask Join node.

image

Nor rising an error nor inserting arbitrary values are not good solutions enough. If a node does not have enough input data the output is empty list. It's quite clear and simple rule.

Probably you can rather make a proposal of modifying Filter Empty Objects to make it work to solve your problem or make a proposal for new node which would replace empty lists with something else.

@ArpegorPSGH
Copy link
Contributor Author

One level lists are not supported even by List Mask Join node.

It supports one level lists for Data True and False, but not Mask.

Nor rising an error nor inserting arbitrary values are not good solutions enough.

There is a third solution : ignoring values that do not exist, which would mean that if Data True is [1, 2, 3] and Data False is [], and Mask is [1, 0, 1], the output would be [1, 3] instead of [1, default, 3]. Would that be good enough?

@Durman
Copy link
Collaborator

Durman commented Sep 21, 2022

Such solution is better because it does not break next nodes. But, at least in some cases, it can mix things up.

image

In the example there is an object which polygons have random colors. The task is to replace random colors with black one for some polygons and it's possible with List Mask Join node. But, for example, instead of black color there is an empty list for some reason. Now the output of List Mask Join node also will be an empty list and it will make all polygons to be black. With your proposal the output list won't be empty, order of values will be broken and polygons will lost their initial colors. So at least in this case your proposal does not have sense.

@ArpegorPSGH
Copy link
Contributor Author

Okay, new idea : instead of adding an arbitrary default value, add an input which value is used as default value. If no value is given it defaults to None or output empty lists, as currently. No need to create a new node, it would still be backward compatible.

@Durman
Copy link
Collaborator

Durman commented Sep 22, 2022

In this case the node have to get two new inputs I guess - default values for True and default values for False. I think this is not so frequent problem to expend the node interface like that. A separate node can handle this much better.

@ArpegorPSGH
Copy link
Contributor Author

Not frequent? It seems something really frequent to me, as it is there to deal with the case when you want to iterate with for each node on a list that is sometimes empty. If you know another way to deal with this easily, I'm all ears, as it is a problem I encounter in most of my trees. Creating a new node seems too much redundant, just for dealing with a corner case like this.

@Durman
Copy link
Collaborator

Durman commented Sep 22, 2022

I'm judging on number of reports about problems with empty objects. You probably can create an issue to describe your problem so it would be clear what is the motivation behind the PR and there might appear another solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants