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.
Files changed (147) hide show
  1. {essreduce-25.5.2/src/essreduce.egg-info → essreduce-25.5.3}/PKG-INFO +1 -1
  2. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/__init__.py +3 -14
  3. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/eto_to_tof.py +3 -60
  4. essreduce-25.5.3/src/ess/reduce/time_of_flight/resample.py +97 -0
  5. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/types.py +0 -40
  6. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/workflow.py +1 -0
  7. {essreduce-25.5.2 → essreduce-25.5.3/src/essreduce.egg-info}/PKG-INFO +1 -1
  8. {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/SOURCES.txt +2 -2
  9. essreduce-25.5.3/tests/time_of_flight/resample_tests.py +477 -0
  10. {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/unwrap_test.py +3 -6
  11. essreduce-25.5.2/src/ess/reduce/time_of_flight/to_events.py +0 -111
  12. essreduce-25.5.2/tests/time_of_flight/to_events_test.py +0 -166
  13. {essreduce-25.5.2 → essreduce-25.5.3}/.copier-answers.ess.yml +0 -0
  14. {essreduce-25.5.2 → essreduce-25.5.3}/.copier-answers.yml +0 -0
  15. {essreduce-25.5.2 → essreduce-25.5.3}/.github/ISSUE_TEMPLATE/blank.md +0 -0
  16. {essreduce-25.5.2 → essreduce-25.5.3}/.github/ISSUE_TEMPLATE/high-level-requirement.yml +0 -0
  17. {essreduce-25.5.2 → essreduce-25.5.3}/.github/dependabot.yml +0 -0
  18. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/ci.yml +0 -0
  19. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/docs.yml +0 -0
  20. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/nightly_at_main.yml +0 -0
  21. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/nightly_at_release.yml +0 -0
  22. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/python-version-ci +0 -0
  23. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/release.yml +0 -0
  24. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/test.yml +0 -0
  25. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/unpinned.yml +0 -0
  26. {essreduce-25.5.2 → essreduce-25.5.3}/.github/workflows/weekly_windows_macos.yml +0 -0
  27. {essreduce-25.5.2 → essreduce-25.5.3}/.gitignore +0 -0
  28. {essreduce-25.5.2 → essreduce-25.5.3}/.pre-commit-config.yaml +0 -0
  29. {essreduce-25.5.2 → essreduce-25.5.3}/.python-version +0 -0
  30. {essreduce-25.5.2 → essreduce-25.5.3}/CODE_OF_CONDUCT.md +0 -0
  31. {essreduce-25.5.2 → essreduce-25.5.3}/CONTRIBUTING.md +0 -0
  32. {essreduce-25.5.2 → essreduce-25.5.3}/LICENSE +0 -0
  33. {essreduce-25.5.2 → essreduce-25.5.3}/MANIFEST.in +0 -0
  34. {essreduce-25.5.2 → essreduce-25.5.3}/README.md +0 -0
  35. {essreduce-25.5.2 → essreduce-25.5.3}/conda/meta.yaml +0 -0
  36. {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/anaconda-icon.js +0 -0
  37. {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/favicon.svg +0 -0
  38. {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/logo-dark.svg +0 -0
  39. {essreduce-25.5.2 → essreduce-25.5.3}/docs/_static/logo.svg +0 -0
  40. {essreduce-25.5.2 → essreduce-25.5.3}/docs/_templates/class-template.rst +0 -0
  41. {essreduce-25.5.2 → essreduce-25.5.3}/docs/_templates/doc_version.html +0 -0
  42. {essreduce-25.5.2 → essreduce-25.5.3}/docs/_templates/module-template.rst +0 -0
  43. {essreduce-25.5.2 → essreduce-25.5.3}/docs/about/index.md +0 -0
  44. {essreduce-25.5.2 → essreduce-25.5.3}/docs/api-reference/index.md +0 -0
  45. {essreduce-25.5.2 → essreduce-25.5.3}/docs/conf.py +0 -0
  46. {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/coding-conventions.md +0 -0
  47. {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/dependency-management.md +0 -0
  48. {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/getting-started.md +0 -0
  49. {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/gui.ipynb +0 -0
  50. {essreduce-25.5.2 → essreduce-25.5.3}/docs/developer/index.md +0 -0
  51. {essreduce-25.5.2 → essreduce-25.5.3}/docs/index.md +0 -0
  52. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/index.md +0 -0
  53. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/installation.md +0 -0
  54. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/reduction-workflow-guidelines.md +0 -0
  55. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/dream.ipynb +0 -0
  56. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/frame-unwrapping.ipynb +0 -0
  57. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/index.md +0 -0
  58. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/tof/wfm.ipynb +0 -0
  59. {essreduce-25.5.2 → essreduce-25.5.3}/docs/user-guide/widget.md +0 -0
  60. {essreduce-25.5.2 → essreduce-25.5.3}/pyproject.toml +0 -0
  61. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/base.in +0 -0
  62. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/base.txt +0 -0
  63. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/basetest.in +0 -0
  64. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/basetest.txt +0 -0
  65. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/ci.in +0 -0
  66. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/ci.txt +0 -0
  67. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/dev.in +0 -0
  68. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/dev.txt +0 -0
  69. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/docs.in +0 -0
  70. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/docs.txt +0 -0
  71. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/make_base.py +0 -0
  72. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/mypy.in +0 -0
  73. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/mypy.txt +0 -0
  74. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/nightly.in +0 -0
  75. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/nightly.txt +0 -0
  76. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/static.in +0 -0
  77. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/static.txt +0 -0
  78. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/test.in +0 -0
  79. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/test.txt +0 -0
  80. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/wheels.in +0 -0
  81. {essreduce-25.5.2 → essreduce-25.5.3}/requirements/wheels.txt +0 -0
  82. {essreduce-25.5.2 → essreduce-25.5.3}/resources/logo.svg +0 -0
  83. {essreduce-25.5.2 → essreduce-25.5.3}/setup.cfg +0 -0
  84. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/__init__.py +0 -0
  85. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/data.py +0 -0
  86. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/__init__.py +0 -0
  87. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/raw.py +0 -0
  88. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/roi.py +0 -0
  89. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/live/workflow.py +0 -0
  90. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/logging.py +0 -0
  91. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/__init__.py +0 -0
  92. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/_nexus_loader.py +0 -0
  93. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/json_generator.py +0 -0
  94. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/json_nexus.py +0 -0
  95. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/types.py +0 -0
  96. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/nexus/workflow.py +0 -0
  97. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/parameter.py +0 -0
  98. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/py.typed +0 -0
  99. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/scripts/grow_nexus.py +0 -0
  100. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/streaming.py +0 -0
  101. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/fakes.py +0 -0
  102. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/interpolator_numba.py +0 -0
  103. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/interpolator_scipy.py +0 -0
  104. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/time_of_flight/simulation.py +0 -0
  105. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/ui.py +0 -0
  106. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/uncertainty.py +0 -0
  107. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/__init__.py +0 -0
  108. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_base.py +0 -0
  109. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_binedges_widget.py +0 -0
  110. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_bounds_widget.py +0 -0
  111. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_config.py +0 -0
  112. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_filename_widget.py +0 -0
  113. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_linspace_widget.py +0 -0
  114. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_optional_widget.py +0 -0
  115. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_spinner.py +0 -0
  116. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_string_widget.py +0 -0
  117. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_switchable_widget.py +0 -0
  118. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/widgets/_vector_widget.py +0 -0
  119. {essreduce-25.5.2 → essreduce-25.5.3}/src/ess/reduce/workflow.py +0 -0
  120. {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/dependency_links.txt +0 -0
  121. {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/entry_points.txt +0 -0
  122. {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/requires.txt +0 -0
  123. {essreduce-25.5.2 → essreduce-25.5.3}/src/essreduce.egg-info/top_level.txt +0 -0
  124. {essreduce-25.5.2 → essreduce-25.5.3}/tests/accumulators_test.py +0 -0
  125. {essreduce-25.5.2 → essreduce-25.5.3}/tests/live/raw_test.py +0 -0
  126. {essreduce-25.5.2 → essreduce-25.5.3}/tests/live/roi_test.py +0 -0
  127. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_generator_test.py +0 -0
  128. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/array_dataset.json +0 -0
  129. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/dataset.json +0 -0
  130. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/detector.json +0 -0
  131. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/entry.json +0 -0
  132. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/event_data.json +0 -0
  133. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/instrument.json +0 -0
  134. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_examples/log.json +0 -0
  135. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/json_nexus_test.py +0 -0
  136. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/nexus_loader_test.py +0 -0
  137. {essreduce-25.5.2 → essreduce-25.5.3}/tests/nexus/workflow_test.py +0 -0
  138. {essreduce-25.5.2 → essreduce-25.5.3}/tests/package_test.py +0 -0
  139. {essreduce-25.5.2 → essreduce-25.5.3}/tests/scripts/test_grow_nexus.py +0 -0
  140. {essreduce-25.5.2 → essreduce-25.5.3}/tests/streaming_test.py +0 -0
  141. {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/interpolator_test.py +0 -0
  142. {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/wfm_test.py +0 -0
  143. {essreduce-25.5.2 → essreduce-25.5.3}/tests/time_of_flight/workflow_test.py +0 -0
  144. {essreduce-25.5.2 → essreduce-25.5.3}/tests/uncertainty_test.py +0 -0
  145. {essreduce-25.5.2 → essreduce-25.5.3}/tests/widget_test.py +0 -0
  146. {essreduce-25.5.2 → essreduce-25.5.3}/tools/shrink_nexus.py +0 -0
  147. {essreduce-25.5.2 → essreduce-25.5.3}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: essreduce
3
- Version: 25.5.2
3
+ Version: 25.5.3
4
4
  Summary: Common data reduction tools for the ESS facility
5
5
  Author: Scipp contributors
6
6
  License: BSD 3-Clause License
@@ -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 .to_events import to_events
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
- return _time_of_flight_data_histogram(da=da, lookup=lookup, ltotal=ltotal)
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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: essreduce
3
- Version: 25.5.2
3
+ Version: 25.5.3
4
4
  Summary: Common data reduction tools for the ESS facility
5
5
  Author: Scipp contributors
6
6
  License: BSD 3-Clause License
@@ -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/to_events_test.py
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