Add customisation hook for loading time-dependent transformations from NeXus#246
Conversation
021f15c to
fbd43c4
Compare
|
This causes an issue with the class Position(sciline.Scope[Component, RunType, sc.Variable | sc.DataArray], sc.Variable | sc.DataArray):But that is not possible because we can't inherit from unions. So I'm thinking we could always make positions data arrays. But that impacts a lot of downstream code that currently expects variables. But that code is anyway broken for dime dependent positions and might need an update. Alternatively, we could use a separate path through the workflow and add class MovingPosition(sciline.Scope[Component, RunType, sc.DataArray], sc.DataArray):and providers then have to request that type when they can deal with time dependence. The providers constructing Thoughts? (@SimonHeybrock, @nvaytet) |
2a49cd8 to
407d815
Compare
Lookup relative error threshold
251fd99 to
7a0234c
Compare
8720cee to
153a588
Compare
| def compute_dynamic_position( | ||
| transformation: NeXusTransformation[Component, RunType], | ||
| ) -> DynamicPosition[Component, RunType]: | ||
| """Compute the position of a component from a transformation matrix.""" |
There was a problem hiding this comment.
Nitpick: Should there also be an error message if we attempt here to compute a dynamic position from a scalar variable?
There was a problem hiding this comment.
I would say no. DynamicPosition can still be stationary. E.g., the BIFROST workflow should transparently handle moving and stationary detectors without changes to the graph.
| params={ | ||
| PreopenNeXusFile: PreopenNeXusFile(False), | ||
| TransformationTimeFilter: reject_time_dependent_transform, | ||
| }, |
There was a problem hiding this comment.
Can you explain/sketch out what the e.g. Loki workflow would look like if we need to load both moving and stationary monitors?
I didn't see where the DynamicPosition is being used.
There was a problem hiding this comment.
I didn't see where the DynamicPosition is being used.
It's unused here. But look at this PR: https://github.com/scipp/essspectroscopy/
As for Loki: You don't need to do anything for stationary monitors. Let's say, Monitor2 moves. Then you need to set
def monitor_time_filter(transform: sc.DataArray) -> sc.DataArray: ...
def get_calibrated_dmoving_monitor(
monitor: NeXusComponent[Monitor2, RunType],
*,
transform: NeXusTransformation[Monitor2, RunType],
) -> EmptyMonitor2[Monitor2, RunType]: ...
wf[TransformationTimeFilter[Monitor2, RunType]] = monitor_time_filter
wf.insert(get_calibrated_dmoving_monitor)This overrides the default for Monitor2 and allows you to specify how to handle the time-dependence.
There was a problem hiding this comment.
Why do we need to do 2 things to the workflow? (1. set TransformationTimeFilter, 2. insert a new provider)
Can the filtering just be done inside the provider?
Or maybe it's because inserting the provider might be something added in e.g. essspectroscopy inside the module, but the time filter may be tweaked by the user in the notebook, hence the separation?
There was a problem hiding this comment.
But look at this PR: https://github.com/scipp/essspectroscopy/
Can you provide a more specific link? 😉
There was a problem hiding this comment.
| 'source_position': lambda: source_position, | ||
| 'sample_position': lambda: sample_position, | ||
| 'source_position': lambda: source_position.position, | ||
| 'sample_position': lambda: sample_position.position, |
There was a problem hiding this comment.
I'm wondering if this can potentially break a lot of existing code?
There was a problem hiding this comment.
Yes. That should not have been there anymore. I guess I forgot to push something. See the update.
For context: This PR should not break any existing code. It loads 'static' positions as before using the Position type. It adds the DynamicPosition type that allows for potentially time-dependent data. But you need to explicitly request that in the workflow. (Used for BIFROST analysers)
b5cae84 to
f6ff090
Compare
| sizes=t.sizes, coord=time, index=interval.value | ||
| ) | ||
| t.value = _time_filter(t.value[idx]) | ||
| t.value = _time_filter(t.value[idx], time_filter) |
There was a problem hiding this comment.
Confusing near-duplicate variable naming. Should _time_filter by _apply_time_filter or something like that?
|
|
||
|
|
||
| def compute_dynamic_position( | ||
| transformation: NeXusTransformation[Component, RunType], |
There was a problem hiding this comment.
The to_transformation docstring returning this still claims it is time-independent?
There was a problem hiding this comment.
Which line are you referring to? to_transformation can indeed return a time-dependent transform. But that depends on TransformationTimeFilter.
| assert sc.identical(transform * origin, sc.vector([1.0, 3.0, 0.0], unit='m')) | ||
|
|
||
|
|
||
| def test_to_transform_raises_if_interval_does_not_yield_unique_value( |
There was a problem hiding this comment.
Do I remember correctly that there used to be some tests that you added in this PR, but now it seems they are gone?
Or am I somehow reading the wrong diff?
There was a problem hiding this comment.
They are gone. I could add them back but that requires implementing the custom function I outlined in the Loki comment which makes the tests somewhat complicated. Should I do that? Or is it enough to have the bifrost tests which will soon be in the monorepo?
There was a problem hiding this comment.
I guess if one day someone decides to remove the tests in Bifrost, we may forget that reduce was relying on those, and we would then no longer be testing this anywhere?
I guess it depends how complicated the tests get...
There was a problem hiding this comment.
True. I restored a test I accidentally removed and added one more. It only tests to_transformation. Do we need a full workflow test? That would mean making the input data.
Use a list as arg to drop_coords
|
@jl-wynen Before merging, please also update the PR description! |
0d47a53 to
782c18e
Compare
The previous attempt added the time as an event coord. This makes grouping by time-dependent coords more difficult down the line. It is not apparent which event coords depend on a slow timescale that we might later want to group or bin into and which coords truly depend on the events.
Needed for vector lookup.
782c18e to
74b33c0
Compare
This PR adds a hook to customise how time-dependent transformations are loaded from NeXus and merged with the data. This PR should not break any existing code. It only adds new options to the workflow.
See scipp/essspectroscopy#101 for a use case.