essreduce 25.5.2__tar.gz → 25.5.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {essreduce-25.5.2/src/essreduce.egg-info → essreduce-25.5.3}/PKG-INFO +1 -1
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/__init__.py +3 -14
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/eto_to_tof.py +3 -60
- essreduce-25.5.3/src/ess/reduce/time_of_flight/resample.py +97 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/types.py +0 -40
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/workflow.py +1 -0
- {essreduce-25.5.2 → essreduce-25.5.3/src/essreduce.egg-info}/PKG-INFO +1 -1
- {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/SOURCES.txt +2 -2
- essreduce-25.5.3/tests/time_of_flight/resample_tests.py +477 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/unwrap_test.py +3 -6
- essreduce-25.5.2/src/ess/reduce/time_of_flight/to_events.py +0 -111
- essreduce-25.5.2/tests/time_of_flight/to_events_test.py +0 -166
- {essreduce-25.5.2 → essreduce-25.5.3}/.copier-answers.ess.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.copier-answers.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/ISSUE_TEMPLATE/blank.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/ISSUE_TEMPLATE/high-level-requirement.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/dependabot.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/ci.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/docs.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/nightly_at_main.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/nightly_at_release.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/python-version-ci +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/release.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/test.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/unpinned.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/weekly_windows_macos.yml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.gitignore +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.pre-commit-config.yaml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/.python-version +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/CODE_OF_CONDUCT.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/CONTRIBUTING.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/LICENSE +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/MANIFEST.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/README.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/conda/meta.yaml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/anaconda-icon.js +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/favicon.svg +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/logo-dark.svg +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/logo.svg +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/_templates/class-template.rst +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/_templates/doc_version.html +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/_templates/module-template.rst +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/about/index.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/api-reference/index.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/conf.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/coding-conventions.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/dependency-management.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/getting-started.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/gui.ipynb +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/index.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/index.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/index.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/installation.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/reduction-workflow-guidelines.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/dream.ipynb +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/frame-unwrapping.ipynb +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/index.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/wfm.ipynb +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/widget.md +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/pyproject.toml +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/base.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/base.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/basetest.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/basetest.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/ci.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/ci.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/dev.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/dev.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/docs.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/docs.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/make_base.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/mypy.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/mypy.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/nightly.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/nightly.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/static.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/static.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/test.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/test.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/wheels.in +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/requirements/wheels.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/resources/logo.svg +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/setup.cfg +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/__init__.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/data.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/__init__.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/raw.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/roi.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/workflow.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/logging.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/__init__.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/_nexus_loader.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/json_generator.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/json_nexus.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/types.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/workflow.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/parameter.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/py.typed +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/scripts/grow_nexus.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/streaming.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/fakes.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/interpolator_numba.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/interpolator_scipy.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/simulation.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/ui.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/uncertainty.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/__init__.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_base.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_binedges_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_bounds_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_config.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_filename_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_linspace_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_optional_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_spinner.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_string_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_switchable_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_vector_widget.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/workflow.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/dependency_links.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/entry_points.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/requires.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/top_level.txt +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/accumulators_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/live/raw_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/live/roi_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_generator_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/array_dataset.json +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/dataset.json +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/detector.json +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/entry.json +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/event_data.json +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/instrument.json +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/log.json +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/nexus_loader_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/workflow_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/package_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/scripts/test_grow_nexus.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/streaming_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/interpolator_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/wfm_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/workflow_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/uncertainty_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tests/widget_test.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tools/shrink_nexus.py +0 -0
- {essreduce-25.5.2 → essreduce-25.5.3}/tox.ini +0 -0
|
@@ -6,14 +6,8 @@ Utilities for computing real neutron time-of-flight from chopper settings and
|
|
|
6
6
|
neutron time-of-arrival at the detectors.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from .eto_to_tof import
|
|
10
|
-
default_parameters,
|
|
11
|
-
providers,
|
|
12
|
-
resample_detector_time_of_flight_data,
|
|
13
|
-
resample_monitor_time_of_flight_data,
|
|
14
|
-
)
|
|
9
|
+
from .eto_to_tof import default_parameters, providers
|
|
15
10
|
from .simulation import simulate_beamline
|
|
16
|
-
from .to_events import to_events
|
|
17
11
|
from .types import (
|
|
18
12
|
DetectorLtotal,
|
|
19
13
|
DetectorTofData,
|
|
@@ -25,8 +19,6 @@ from .types import (
|
|
|
25
19
|
PulsePeriod,
|
|
26
20
|
PulseStride,
|
|
27
21
|
PulseStrideOffset,
|
|
28
|
-
ResampledDetectorTofData,
|
|
29
|
-
ResampledMonitorTofData,
|
|
30
22
|
SimulationResults,
|
|
31
23
|
TimeOfFlightLookupTable,
|
|
32
24
|
TimeOfFlightLookupTableFilename,
|
|
@@ -37,17 +29,17 @@ from .workflow import GenericTofWorkflow, TofLutProvider
|
|
|
37
29
|
__all__ = [
|
|
38
30
|
"DetectorLtotal",
|
|
39
31
|
"DetectorTofData",
|
|
32
|
+
"DetectorTofData",
|
|
40
33
|
"DistanceResolution",
|
|
41
34
|
"GenericTofWorkflow",
|
|
42
35
|
"LookupTableRelativeErrorThreshold",
|
|
43
36
|
"LtotalRange",
|
|
44
37
|
"MonitorLtotal",
|
|
45
38
|
"MonitorTofData",
|
|
39
|
+
"MonitorTofData",
|
|
46
40
|
"PulsePeriod",
|
|
47
41
|
"PulseStride",
|
|
48
42
|
"PulseStrideOffset",
|
|
49
|
-
"ResampledDetectorTofData",
|
|
50
|
-
"ResampledMonitorTofData",
|
|
51
43
|
"SimulationResults",
|
|
52
44
|
"TimeOfFlightLookupTable",
|
|
53
45
|
"TimeOfFlightLookupTableFilename",
|
|
@@ -55,8 +47,5 @@ __all__ = [
|
|
|
55
47
|
"TofLutProvider",
|
|
56
48
|
"default_parameters",
|
|
57
49
|
"providers",
|
|
58
|
-
"resample_detector_time_of_flight_data",
|
|
59
|
-
"resample_monitor_time_of_flight_data",
|
|
60
50
|
"simulate_beamline",
|
|
61
|
-
"to_events",
|
|
62
51
|
]
|
|
@@ -27,7 +27,7 @@ from ..nexus.types import (
|
|
|
27
27
|
MonitorType,
|
|
28
28
|
RunType,
|
|
29
29
|
)
|
|
30
|
-
from .
|
|
30
|
+
from .resample import rebin_strictly_increasing
|
|
31
31
|
from .types import (
|
|
32
32
|
DetectorLtotal,
|
|
33
33
|
DetectorTofData,
|
|
@@ -39,8 +39,6 @@ from .types import (
|
|
|
39
39
|
PulsePeriod,
|
|
40
40
|
PulseStride,
|
|
41
41
|
PulseStrideOffset,
|
|
42
|
-
ResampledDetectorTofData,
|
|
43
|
-
ResampledMonitorTofData,
|
|
44
42
|
SimulationResults,
|
|
45
43
|
TimeOfFlightLookupTable,
|
|
46
44
|
TimeResolution,
|
|
@@ -586,7 +584,8 @@ def _compute_tof_data(
|
|
|
586
584
|
pulse_stride_offset: int,
|
|
587
585
|
) -> sc.DataArray:
|
|
588
586
|
if da.bins is None:
|
|
589
|
-
|
|
587
|
+
data = _time_of_flight_data_histogram(da=da, lookup=lookup, ltotal=ltotal)
|
|
588
|
+
return rebin_strictly_increasing(data, dim='tof')
|
|
590
589
|
else:
|
|
591
590
|
return _time_of_flight_data_events(
|
|
592
591
|
da=da,
|
|
@@ -664,62 +663,6 @@ def monitor_time_of_flight_data(
|
|
|
664
663
|
)
|
|
665
664
|
|
|
666
665
|
|
|
667
|
-
def _resample_tof_data(da: sc.DataArray) -> sc.DataArray:
|
|
668
|
-
"""
|
|
669
|
-
Histogrammed data that has been converted to `tof` will typically have
|
|
670
|
-
unsorted bin edges (due to either wrapping of `time_of_flight` or wavelength
|
|
671
|
-
overlap between subframes).
|
|
672
|
-
This function re-histograms the data to ensure that the bin edges are sorted.
|
|
673
|
-
It makes use of the ``to_events`` helper which generates a number of events in each
|
|
674
|
-
bin with a uniform distribution. The new events are then histogrammed using a set of
|
|
675
|
-
sorted bin edges.
|
|
676
|
-
|
|
677
|
-
WARNING:
|
|
678
|
-
This function is highly experimental, has limitations and should be used with
|
|
679
|
-
caution. It is a workaround to the issue that rebinning data with unsorted bin
|
|
680
|
-
edges is not supported in scipp.
|
|
681
|
-
As such, this function is not part of the default set of providers, and needs to be
|
|
682
|
-
inserted manually into the workflow.
|
|
683
|
-
|
|
684
|
-
Parameters
|
|
685
|
-
----------
|
|
686
|
-
da:
|
|
687
|
-
Histogrammed data with the time-of-flight coordinate.
|
|
688
|
-
"""
|
|
689
|
-
dim = next(iter(set(da.dims) & {"time_of_flight", "tof"}))
|
|
690
|
-
data = da.rename_dims({dim: "tof"}).drop_coords(
|
|
691
|
-
[name for name in da.coords if name != "tof"]
|
|
692
|
-
)
|
|
693
|
-
events = to_events(data, "event")
|
|
694
|
-
|
|
695
|
-
# Define a new bin width, close to the original bin width.
|
|
696
|
-
# TODO: this could be a workflow parameter
|
|
697
|
-
coord = da.coords["tof"]
|
|
698
|
-
bin_width = (coord[dim, 1:] - coord[dim, :-1]).nanmedian()
|
|
699
|
-
rehist = events.hist(tof=bin_width)
|
|
700
|
-
return rehist.assign_coords(
|
|
701
|
-
{key: var for key, var in da.coords.items() if dim not in var.dims}
|
|
702
|
-
)
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
def resample_detector_time_of_flight_data(
|
|
706
|
-
da: DetectorTofData[RunType],
|
|
707
|
-
) -> ResampledDetectorTofData[RunType]:
|
|
708
|
-
"""
|
|
709
|
-
Resample the detector time-of-flight data to ensure that the bin edges are sorted.
|
|
710
|
-
"""
|
|
711
|
-
return ResampledDetectorTofData(_resample_tof_data(da))
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
def resample_monitor_time_of_flight_data(
|
|
715
|
-
da: MonitorTofData[RunType, MonitorType],
|
|
716
|
-
) -> ResampledMonitorTofData[RunType, MonitorType]:
|
|
717
|
-
"""
|
|
718
|
-
Resample the monitor time-of-flight data to ensure that the bin edges are sorted.
|
|
719
|
-
"""
|
|
720
|
-
return ResampledMonitorTofData(_resample_tof_data(da))
|
|
721
|
-
|
|
722
|
-
|
|
723
666
|
def default_parameters() -> dict:
|
|
724
667
|
"""
|
|
725
668
|
Default parameters of the time-of-flight workflow.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
# Copyright (c) 2025 Scipp contributors (https://github.com/scipp)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import scipp as sc
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def find_strictly_increasing_sections(var: sc.Variable) -> list[slice]:
|
|
10
|
+
"""
|
|
11
|
+
Find strictly increasing sections in a coordinate dimension (minimum length 2).
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
var:
|
|
16
|
+
The variable to analyze, which should be one-dimensional.
|
|
17
|
+
|
|
18
|
+
Returns
|
|
19
|
+
-------
|
|
20
|
+
sections:
|
|
21
|
+
Slice objects that can be used extract strictly increasing sections.
|
|
22
|
+
"""
|
|
23
|
+
values = var.values
|
|
24
|
+
finite = np.isfinite(values)
|
|
25
|
+
increasing = (np.sign(np.diff(values)) > 0) & finite[:-1] & finite[1:]
|
|
26
|
+
# 1 marks the start of an increasing section, -1 marks the end
|
|
27
|
+
transitions = np.diff(np.concatenate(([False], increasing, [False])).astype(int))
|
|
28
|
+
section_starts = np.where(transitions == 1)[0]
|
|
29
|
+
section_ends = np.where(transitions == -1)[0] + np.array(1)
|
|
30
|
+
return [
|
|
31
|
+
slice(start, end)
|
|
32
|
+
for start, end in zip(section_starts, section_ends, strict=True)
|
|
33
|
+
if end - start >= 2 # Ensure section has at least 2 points
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_min_max(
|
|
38
|
+
var: sc.Variable, *, dim: str, slices: list[slice]
|
|
39
|
+
) -> tuple[sc.Variable, sc.Variable]:
|
|
40
|
+
if not slices:
|
|
41
|
+
raise ValueError("No strictly increasing sections found.")
|
|
42
|
+
combined = sc.concat([var[dim, slice] for slice in slices], dim)
|
|
43
|
+
return combined.min(), combined.max()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def make_regular_grid(
|
|
47
|
+
var: sc.Variable, *, dim: str, slices: list[slice]
|
|
48
|
+
) -> sc.Variable:
|
|
49
|
+
"""
|
|
50
|
+
Create a regular grid variable based on the min and max of the slices.
|
|
51
|
+
|
|
52
|
+
The grid is constructed such that it includes the minimum and maximum values
|
|
53
|
+
of the strictly increasing sections, with a step size equal to the difference
|
|
54
|
+
between the first two values of the section with the minimum start value (which is
|
|
55
|
+
not necessarily the first section).
|
|
56
|
+
"""
|
|
57
|
+
min_val, max_val = get_min_max(var, dim=dim, slices=slices)
|
|
58
|
+
first: sc.Variable | None = None
|
|
59
|
+
for s in slices:
|
|
60
|
+
first = var[dim, s]
|
|
61
|
+
if sc.identical(first[0], min_val):
|
|
62
|
+
break
|
|
63
|
+
if first is None:
|
|
64
|
+
# This should not happen if slices are correctly identified and passed from
|
|
65
|
+
# find_strictly_increasing_sections.
|
|
66
|
+
raise ValueError("Section is not strictly increasing.")
|
|
67
|
+
step = first[1] - first[0]
|
|
68
|
+
return sc.arange(
|
|
69
|
+
dim=dim,
|
|
70
|
+
start=min_val.value,
|
|
71
|
+
stop=max_val.value + step.value, # Ensure the last bin edge is included
|
|
72
|
+
step=step.value,
|
|
73
|
+
unit=step.unit,
|
|
74
|
+
dtype=step.dtype,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def rebin_strictly_increasing(da: sc.DataArray, dim: str) -> sc.DataArray:
|
|
79
|
+
"""
|
|
80
|
+
Find strictly monotonic sections in a coordinate dimension and rebin the data array
|
|
81
|
+
into a regular grid based on these sections.
|
|
82
|
+
"""
|
|
83
|
+
# Ensure the dimension is named like the coordinate.
|
|
84
|
+
da = da.rename_dims({da.coords[dim].dim: dim})
|
|
85
|
+
slices = find_strictly_increasing_sections(da.coords[dim])
|
|
86
|
+
if len(slices) == 1:
|
|
87
|
+
return da[dim, slices[0]]
|
|
88
|
+
if not slices:
|
|
89
|
+
raise ValueError("No strictly increasing sections found.")
|
|
90
|
+
if da.coords[dim].dtype not in (sc.DType.float64, sc.DType.float32):
|
|
91
|
+
# rebin does not like integer coords.
|
|
92
|
+
da = da.assign_coords({dim: da.coords[dim].to(dtype='float64')})
|
|
93
|
+
# Slices refer to the indices in the coord, which are bin edges. For slicing data
|
|
94
|
+
# we need to stop at the last index minus one.
|
|
95
|
+
sections = [da[dim, section.start : section.stop - 1] for section in slices]
|
|
96
|
+
edges = make_regular_grid(da.coords[dim], dim=dim, slices=slices)
|
|
97
|
+
return sc.reduce([sc.rebin(section, {dim: edges}) for section in sections]).sum()
|
|
@@ -130,43 +130,3 @@ class DetectorTofData(sl.Scope[RunType, sc.DataArray], sc.DataArray):
|
|
|
130
130
|
|
|
131
131
|
class MonitorTofData(sl.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray):
|
|
132
132
|
"""Monitor data with time-of-flight coordinate."""
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
class ResampledDetectorTofData(sl.Scope[RunType, sc.DataArray], sc.DataArray):
|
|
136
|
-
"""
|
|
137
|
-
Histogrammed detector data with time-of-flight coordinate, that has been resampled.
|
|
138
|
-
|
|
139
|
-
Histogrammed data that has been converted to `tof` will typically have
|
|
140
|
-
unsorted bin edges (due to either wrapping of `time_of_flight` or wavelength
|
|
141
|
-
overlap between subframes).
|
|
142
|
-
We thus resample the data to ensure that the bin edges are sorted.
|
|
143
|
-
It makes use of the ``to_events`` helper which generates a number of events in each
|
|
144
|
-
bin with a uniform distribution. The new events are then histogrammed using a set of
|
|
145
|
-
sorted bin edges to yield a new histogram with sorted bin edges.
|
|
146
|
-
|
|
147
|
-
WARNING:
|
|
148
|
-
This function is highly experimental, has limitations and should be used with
|
|
149
|
-
caution. It is a workaround to the issue that rebinning data with unsorted bin
|
|
150
|
-
edges is not supported in scipp.
|
|
151
|
-
"""
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class ResampledMonitorTofData(
|
|
155
|
-
sl.Scope[RunType, MonitorType, sc.DataArray], sc.DataArray
|
|
156
|
-
):
|
|
157
|
-
"""
|
|
158
|
-
Histogrammed monitor data with time-of-flight coordinate, that has been resampled.
|
|
159
|
-
|
|
160
|
-
Histogrammed data that has been converted to `tof` will typically have
|
|
161
|
-
unsorted bin edges (due to either wrapping of `time_of_flight` or wavelength
|
|
162
|
-
overlap between subframes).
|
|
163
|
-
We thus resample the data to ensure that the bin edges are sorted.
|
|
164
|
-
It makes use of the ``to_events`` helper which generates a number of events in each
|
|
165
|
-
bin with a uniform distribution. The new events are then histogrammed using a set of
|
|
166
|
-
sorted bin edges to yield a new histogram with sorted bin edges.
|
|
167
|
-
|
|
168
|
-
WARNING:
|
|
169
|
-
This function is highly experimental, has limitations and should be used with
|
|
170
|
-
caution. It is a workaround to the issue that rebinning data with unsorted bin
|
|
171
|
-
edges is not supported in scipp.
|
|
172
|
-
"""
|
|
@@ -34,6 +34,7 @@ def GenericTofWorkflow(
|
|
|
34
34
|
"""
|
|
35
35
|
Generic workflow for computing the neutron time-of-flight for detector and monitor
|
|
36
36
|
data.
|
|
37
|
+
|
|
37
38
|
This workflow builds on the ``GenericNeXusWorkflow`` and computes time-of-flight
|
|
38
39
|
from a lookup table that is created from the chopper settings, detector Ltotal and
|
|
39
40
|
the neutron time-of-arrival.
|
|
@@ -94,8 +94,8 @@ src/ess/reduce/time_of_flight/eto_to_tof.py
|
|
|
94
94
|
src/ess/reduce/time_of_flight/fakes.py
|
|
95
95
|
src/ess/reduce/time_of_flight/interpolator_numba.py
|
|
96
96
|
src/ess/reduce/time_of_flight/interpolator_scipy.py
|
|
97
|
+
src/ess/reduce/time_of_flight/resample.py
|
|
97
98
|
src/ess/reduce/time_of_flight/simulation.py
|
|
98
|
-
src/ess/reduce/time_of_flight/to_events.py
|
|
99
99
|
src/ess/reduce/time_of_flight/types.py
|
|
100
100
|
src/ess/reduce/time_of_flight/workflow.py
|
|
101
101
|
src/ess/reduce/widgets/__init__.py
|
|
@@ -136,7 +136,7 @@ tests/nexus/json_nexus_examples/instrument.json
|
|
|
136
136
|
tests/nexus/json_nexus_examples/log.json
|
|
137
137
|
tests/scripts/test_grow_nexus.py
|
|
138
138
|
tests/time_of_flight/interpolator_test.py
|
|
139
|
-
tests/time_of_flight/
|
|
139
|
+
tests/time_of_flight/resample_tests.py
|
|
140
140
|
tests/time_of_flight/unwrap_test.py
|
|
141
141
|
tests/time_of_flight/wfm_test.py
|
|
142
142
|
tests/time_of_flight/workflow_test.py
|