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
Checks for multioutput plugins and loop dependencies #312
Conversation
Looks good, maybe here an additional MWE since it took me quite some time to get deps initialized:
returns a dict
returns 'raw_records' |
strax/plugin.py
Outdated
@@ -608,6 +608,9 @@ def compute(self, **kwargs): | |||
loop_over = self.loop_over | |||
else: | |||
loop_over = self.deps[self.depends_on[0]].data_kind | |||
if isinstance(loop_over, dict): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to changes this line in isinstance(loop_over, (dict, immutabledict))
since the DAQReader has an immutable dict as data_kind. See
plugins = st._get_plugins(targets=('events',), run_id='0')
plugins['records'].deps[plugins['records'].depends_on[0]].data_kind
strax/plugin.py
Outdated
@@ -608,6 +608,9 @@ def compute(self, **kwargs): | |||
loop_over = self.loop_over | |||
else: | |||
loop_over = self.deps[self.depends_on[0]].data_kind | |||
if isinstance(loop_over, dict): | |||
loop_over = loop_over[self.depends_on[0]] | |||
# We can't have nested dictionaries here, can we? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you showed, that we cannot. So maybe remove this comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Darryl for spotting this, the error is indeed very non-instructive and unpacking it from a multioutput plugin like this will help recognizing when something is off / badly constructed.
Maybe it's good to add that the high-level problem is that this plugin wasn't designed for these kinds of low-level datatypes. You will (with anything below the non-overlapping peaklets) run into this assertion error:
Line 619 in a19cc21
assert np.all(base[1:]['time'] >= strax.endtime(base[:-1])), \ |
strax/plugin.py
Outdated
@@ -608,6 +608,9 @@ def compute(self, **kwargs): | |||
loop_over = self.loop_over | |||
else: | |||
loop_over = self.deps[self.depends_on[0]].data_kind | |||
if isinstance(loop_over, dict): | |||
loop_over = loop_over[self.depends_on[0]] | |||
# We can't have nested dictionaries here, can we? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps you can be on the safe side by making a check just below:
if not istinstance(loop_over, str):
raise TypeError(f'Trying to loop over {loop_over} which is not a string? Please add loop_over = <base> to your plugin')
So what's the high-level solution we want to aim for? Prevent loop plugins from depending on |
Hi Darryl, The lines I suggested were in addition to what you added before. Combining this would lead to : ...
if isinstance(loop_over, (dict, immutabledict)):
loop_over = loop_over[self.depends_on[0]]
if not isinstance(loop_over, str):
raise TypeError("Please add \"loop_over = <base>\""
" to your plugin definition")
... |
Would not your proposal the lines above obsolete?
Would always be raised when
is true. Hence we could remove it. |
No, you redefine loop_over the line just above it? |
If we do go for something that looks like this:
The second |
The first |
That's my point - the second |
There is nothing wrong with multi-output plugins per se but perhaps you are right that rather than doing the thinking for the analysts that just accepting a simple format is clearer (and throwing an error otherwise). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat
What is the problem / what does the code in this PR do
If the first dependency of a loop plugin is produced by a multi-output plugin, the automatic determination of
loop_over
fails. During the automatic determination of loop order,loop_over = self.deps[self.depends_on[0]].data_kind
(plugin.py L610) evaluates to a dictionary rather than a string, and this fails 4 lines down when it dereferenceskwargs
.Can you briefly describe how it works?
This PR checks to see if the
data_kind
of the plugin providing the first dependency is a multi-output plugin and asks the user to be more specific if it is. Fixes #311 .