essreduce 25.2.3__tar.gz → 25.2.5__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 (137) hide show
  1. {essreduce-25.2.3/src/essreduce.egg-info → essreduce-25.2.5}/PKG-INFO +2 -2
  2. {essreduce-25.2.3 → essreduce-25.2.5}/pyproject.toml +1 -1
  3. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/base.in +1 -1
  4. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/base.txt +26 -5
  5. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/basetest.txt +2 -10
  6. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/ci.txt +0 -6
  7. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/dev.txt +1 -7
  8. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/docs.txt +1 -16
  9. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/nightly.txt +2 -9
  10. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/wheels.txt +0 -2
  11. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/nexus/_nexus_loader.py +26 -5
  12. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/nexus/types.py +8 -0
  13. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/nexus/workflow.py +21 -0
  14. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/streaming.py +56 -3
  15. {essreduce-25.2.3 → essreduce-25.2.5/src/essreduce.egg-info}/PKG-INFO +2 -2
  16. {essreduce-25.2.3 → essreduce-25.2.5}/src/essreduce.egg-info/requires.txt +1 -1
  17. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/nexus_loader_test.py +49 -15
  18. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/workflow_test.py +30 -0
  19. {essreduce-25.2.3 → essreduce-25.2.5}/tests/streaming_test.py +101 -5
  20. {essreduce-25.2.3 → essreduce-25.2.5}/.copier-answers.ess.yml +0 -0
  21. {essreduce-25.2.3 → essreduce-25.2.5}/.copier-answers.yml +0 -0
  22. {essreduce-25.2.3 → essreduce-25.2.5}/.github/ISSUE_TEMPLATE/blank.md +0 -0
  23. {essreduce-25.2.3 → essreduce-25.2.5}/.github/ISSUE_TEMPLATE/high-level-requirement.yml +0 -0
  24. {essreduce-25.2.3 → essreduce-25.2.5}/.github/dependabot.yml +0 -0
  25. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/ci.yml +0 -0
  26. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/docs.yml +0 -0
  27. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/nightly_at_main.yml +0 -0
  28. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/nightly_at_release.yml +0 -0
  29. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/python-version-ci +0 -0
  30. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/release.yml +0 -0
  31. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/test.yml +0 -0
  32. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/unpinned.yml +0 -0
  33. {essreduce-25.2.3 → essreduce-25.2.5}/.github/workflows/weekly_windows_macos.yml +0 -0
  34. {essreduce-25.2.3 → essreduce-25.2.5}/.gitignore +0 -0
  35. {essreduce-25.2.3 → essreduce-25.2.5}/.pre-commit-config.yaml +0 -0
  36. {essreduce-25.2.3 → essreduce-25.2.5}/.python-version +0 -0
  37. {essreduce-25.2.3 → essreduce-25.2.5}/CODE_OF_CONDUCT.md +0 -0
  38. {essreduce-25.2.3 → essreduce-25.2.5}/CONTRIBUTING.md +0 -0
  39. {essreduce-25.2.3 → essreduce-25.2.5}/LICENSE +0 -0
  40. {essreduce-25.2.3 → essreduce-25.2.5}/MANIFEST.in +0 -0
  41. {essreduce-25.2.3 → essreduce-25.2.5}/README.md +0 -0
  42. {essreduce-25.2.3 → essreduce-25.2.5}/conda/meta.yaml +0 -0
  43. {essreduce-25.2.3 → essreduce-25.2.5}/docs/_static/anaconda-icon.js +0 -0
  44. {essreduce-25.2.3 → essreduce-25.2.5}/docs/_static/favicon.svg +0 -0
  45. {essreduce-25.2.3 → essreduce-25.2.5}/docs/_static/logo-dark.svg +0 -0
  46. {essreduce-25.2.3 → essreduce-25.2.5}/docs/_static/logo.svg +0 -0
  47. {essreduce-25.2.3 → essreduce-25.2.5}/docs/_templates/class-template.rst +0 -0
  48. {essreduce-25.2.3 → essreduce-25.2.5}/docs/_templates/doc_version.html +0 -0
  49. {essreduce-25.2.3 → essreduce-25.2.5}/docs/_templates/module-template.rst +0 -0
  50. {essreduce-25.2.3 → essreduce-25.2.5}/docs/about/index.md +0 -0
  51. {essreduce-25.2.3 → essreduce-25.2.5}/docs/api-reference/index.md +0 -0
  52. {essreduce-25.2.3 → essreduce-25.2.5}/docs/conf.py +0 -0
  53. {essreduce-25.2.3 → essreduce-25.2.5}/docs/developer/coding-conventions.md +0 -0
  54. {essreduce-25.2.3 → essreduce-25.2.5}/docs/developer/dependency-management.md +0 -0
  55. {essreduce-25.2.3 → essreduce-25.2.5}/docs/developer/getting-started.md +0 -0
  56. {essreduce-25.2.3 → essreduce-25.2.5}/docs/developer/gui.ipynb +0 -0
  57. {essreduce-25.2.3 → essreduce-25.2.5}/docs/developer/index.md +0 -0
  58. {essreduce-25.2.3 → essreduce-25.2.5}/docs/index.md +0 -0
  59. {essreduce-25.2.3 → essreduce-25.2.5}/docs/user-guide/index.md +0 -0
  60. {essreduce-25.2.3 → essreduce-25.2.5}/docs/user-guide/reduction-workflow-guidelines.md +0 -0
  61. {essreduce-25.2.3 → essreduce-25.2.5}/docs/user-guide/tof/dream.ipynb +0 -0
  62. {essreduce-25.2.3 → essreduce-25.2.5}/docs/user-guide/tof/frame-unwrapping.ipynb +0 -0
  63. {essreduce-25.2.3 → essreduce-25.2.5}/docs/user-guide/tof/index.md +0 -0
  64. {essreduce-25.2.3 → essreduce-25.2.5}/docs/user-guide/tof/wfm.ipynb +0 -0
  65. {essreduce-25.2.3 → essreduce-25.2.5}/docs/user-guide/widget.md +0 -0
  66. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/basetest.in +0 -0
  67. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/ci.in +0 -0
  68. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/dev.in +0 -0
  69. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/docs.in +0 -0
  70. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/make_base.py +0 -0
  71. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/mypy.in +0 -0
  72. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/mypy.txt +0 -0
  73. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/nightly.in +0 -0
  74. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/static.in +0 -0
  75. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/static.txt +0 -0
  76. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/test.in +0 -0
  77. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/test.txt +0 -0
  78. {essreduce-25.2.3 → essreduce-25.2.5}/requirements/wheels.in +0 -0
  79. {essreduce-25.2.3 → essreduce-25.2.5}/resources/logo.svg +0 -0
  80. {essreduce-25.2.3 → essreduce-25.2.5}/setup.cfg +0 -0
  81. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/__init__.py +0 -0
  82. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/data.py +0 -0
  83. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/live/__init__.py +0 -0
  84. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/live/raw.py +0 -0
  85. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/live/roi.py +0 -0
  86. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/live/workflow.py +0 -0
  87. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/logging.py +0 -0
  88. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/nexus/__init__.py +0 -0
  89. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/nexus/json_generator.py +0 -0
  90. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/nexus/json_nexus.py +0 -0
  91. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/parameter.py +0 -0
  92. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/py.typed +0 -0
  93. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/scripts/grow_nexus.py +0 -0
  94. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/time_of_flight/__init__.py +0 -0
  95. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/time_of_flight/fakes.py +0 -0
  96. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/time_of_flight/simulation.py +0 -0
  97. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/time_of_flight/to_events.py +0 -0
  98. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/time_of_flight/toa_to_tof.py +0 -0
  99. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/time_of_flight/types.py +0 -0
  100. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/ui.py +0 -0
  101. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/uncertainty.py +0 -0
  102. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/__init__.py +0 -0
  103. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_base.py +0 -0
  104. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_binedges_widget.py +0 -0
  105. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_bounds_widget.py +0 -0
  106. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_config.py +0 -0
  107. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_filename_widget.py +0 -0
  108. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_linspace_widget.py +0 -0
  109. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_optional_widget.py +0 -0
  110. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_spinner.py +0 -0
  111. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_string_widget.py +0 -0
  112. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_switchable_widget.py +0 -0
  113. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/widgets/_vector_widget.py +0 -0
  114. {essreduce-25.2.3 → essreduce-25.2.5}/src/ess/reduce/workflow.py +0 -0
  115. {essreduce-25.2.3 → essreduce-25.2.5}/src/essreduce.egg-info/SOURCES.txt +0 -0
  116. {essreduce-25.2.3 → essreduce-25.2.5}/src/essreduce.egg-info/dependency_links.txt +0 -0
  117. {essreduce-25.2.3 → essreduce-25.2.5}/src/essreduce.egg-info/entry_points.txt +0 -0
  118. {essreduce-25.2.3 → essreduce-25.2.5}/src/essreduce.egg-info/top_level.txt +0 -0
  119. {essreduce-25.2.3 → essreduce-25.2.5}/tests/live/raw_test.py +0 -0
  120. {essreduce-25.2.3 → essreduce-25.2.5}/tests/live/roi_test.py +0 -0
  121. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_generator_test.py +0 -0
  122. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_examples/array_dataset.json +0 -0
  123. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_examples/dataset.json +0 -0
  124. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_examples/detector.json +0 -0
  125. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_examples/entry.json +0 -0
  126. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_examples/event_data.json +0 -0
  127. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_examples/instrument.json +0 -0
  128. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_examples/log.json +0 -0
  129. {essreduce-25.2.3 → essreduce-25.2.5}/tests/nexus/json_nexus_test.py +0 -0
  130. {essreduce-25.2.3 → essreduce-25.2.5}/tests/package_test.py +0 -0
  131. {essreduce-25.2.3 → essreduce-25.2.5}/tests/scripts/test_grow_nexus.py +0 -0
  132. {essreduce-25.2.3 → essreduce-25.2.5}/tests/time_of_flight/to_events_test.py +0 -0
  133. {essreduce-25.2.3 → essreduce-25.2.5}/tests/time_of_flight/unwrap_test.py +0 -0
  134. {essreduce-25.2.3 → essreduce-25.2.5}/tests/time_of_flight/wfm_test.py +0 -0
  135. {essreduce-25.2.3 → essreduce-25.2.5}/tests/uncertainty_test.py +0 -0
  136. {essreduce-25.2.3 → essreduce-25.2.5}/tests/widget_test.py +0 -0
  137. {essreduce-25.2.3 → essreduce-25.2.5}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: essreduce
3
- Version: 25.2.3
3
+ Version: 25.2.5
4
4
  Summary: Common data reduction tools for the ESS facility
5
5
  Author: Scipp contributors
6
6
  License: BSD 3-Clause License
@@ -53,7 +53,7 @@ Description-Content-Type: text/markdown
53
53
  License-File: LICENSE
54
54
  Requires-Dist: sciline>=24.06.2
55
55
  Requires-Dist: scipp>=25.01.0
56
- Requires-Dist: scippneutron>=24.11.0
56
+ Requires-Dist: scippneutron>=25.02.0
57
57
  Requires-Dist: scippnexus>=24.11.0
58
58
  Provides-Extra: test
59
59
  Requires-Dist: ipywidgets; extra == "test"
@@ -33,7 +33,7 @@ requires-python = ">=3.10"
33
33
  dependencies = [
34
34
  "sciline>=24.06.2",
35
35
  "scipp>=25.01.0",
36
- "scippneutron>=24.11.0",
36
+ "scippneutron>=25.02.0",
37
37
  "scippnexus>=24.11.0",
38
38
  ]
39
39
 
@@ -4,5 +4,5 @@
4
4
  # The following was generated by 'tox -e deps', DO NOT EDIT MANUALLY!
5
5
  sciline>=24.06.2
6
6
  scipp>=25.01.0
7
- scippneutron>=24.11.0
7
+ scippneutron>=25.02.0
8
8
  scippnexus>=24.11.0
@@ -1,24 +1,34 @@
1
- # SHA1:d18487328be0c30ec0a6929501d1c4a58c71bd48
1
+ # SHA1:0aac37186f254abb39dbd8f3c3c6ad52bafc0553
2
2
  #
3
3
  # This file is autogenerated by pip-compile-multi
4
4
  # To update, run:
5
5
  #
6
6
  # pip-compile-multi
7
7
  #
8
+ annotated-types==0.7.0
9
+ # via pydantic
8
10
  contourpy==1.3.1
9
11
  # via matplotlib
10
12
  cyclebane==24.10.0
11
13
  # via sciline
12
14
  cycler==0.12.1
13
15
  # via matplotlib
16
+ dnspython==2.7.0
17
+ # via email-validator
18
+ email-validator==2.2.0
19
+ # via scippneutron
14
20
  fonttools==4.56.0
15
21
  # via matplotlib
16
22
  h5py==3.12.1
17
23
  # via
18
24
  # scippneutron
19
25
  # scippnexus
26
+ idna==3.10
27
+ # via email-validator
20
28
  kiwisolver==1.4.8
21
29
  # via matplotlib
30
+ lazy-loader==0.4
31
+ # via scippneutron
22
32
  matplotlib==3.10.0
23
33
  # via
24
34
  # mpltoolbox
@@ -27,7 +37,7 @@ mpltoolbox==24.5.1
27
37
  # via scippneutron
28
38
  networkx==3.4.2
29
39
  # via cyclebane
30
- numpy==2.2.2
40
+ numpy==2.2.3
31
41
  # via
32
42
  # contourpy
33
43
  # h5py
@@ -37,16 +47,23 @@ numpy==2.2.2
37
47
  # scippneutron
38
48
  # scipy
39
49
  packaging==24.2
40
- # via matplotlib
50
+ # via
51
+ # lazy-loader
52
+ # matplotlib
41
53
  pillow==11.1.0
42
54
  # via matplotlib
43
55
  plopp==24.10.0
44
56
  # via scippneutron
57
+ pydantic==2.10.6
58
+ # via scippneutron
59
+ pydantic-core==2.27.2
60
+ # via pydantic
45
61
  pyparsing==3.2.1
46
62
  # via matplotlib
47
63
  python-dateutil==2.9.0.post0
48
64
  # via
49
65
  # matplotlib
66
+ # scippneutron
50
67
  # scippnexus
51
68
  sciline==24.10.0
52
69
  # via -r base.in
@@ -55,15 +72,19 @@ scipp==25.2.0
55
72
  # -r base.in
56
73
  # scippneutron
57
74
  # scippnexus
58
- scippneutron==25.1.0
75
+ scippneutron==25.2.0
59
76
  # via -r base.in
60
77
  scippnexus==24.11.1
61
78
  # via
62
79
  # -r base.in
63
80
  # scippneutron
64
- scipy==1.15.1
81
+ scipy==1.15.2
65
82
  # via
66
83
  # scippneutron
67
84
  # scippnexus
68
85
  six==1.17.0
69
86
  # via python-dateutil
87
+ typing-extensions==4.12.2
88
+ # via
89
+ # pydantic
90
+ # pydantic-core
@@ -19,10 +19,6 @@ cycler==0.12.1
19
19
  # via matplotlib
20
20
  decorator==5.1.1
21
21
  # via ipython
22
- exceptiongroup==1.2.2
23
- # via
24
- # ipython
25
- # pytest
26
22
  executing==2.2.0
27
23
  # via stack-data
28
24
  fonttools==4.56.0
@@ -47,7 +43,7 @@ matplotlib==3.10.0
47
43
  # via plopp
48
44
  matplotlib-inline==0.1.7
49
45
  # via ipython
50
- numpy==2.2.2
46
+ numpy==2.2.3
51
47
  # via
52
48
  # contourpy
53
49
  # matplotlib
@@ -90,7 +86,7 @@ requests==2.32.3
90
86
  # via pooch
91
87
  scipp==25.2.0
92
88
  # via tof
93
- scipy==1.15.1
89
+ scipy==1.15.2
94
90
  # via
95
91
  # -r basetest.in
96
92
  # tof
@@ -100,16 +96,12 @@ stack-data==0.6.3
100
96
  # via ipython
101
97
  tof==25.2.0
102
98
  # via -r basetest.in
103
- tomli==2.2.1
104
- # via pytest
105
99
  traitlets==5.14.3
106
100
  # via
107
101
  # comm
108
102
  # ipython
109
103
  # ipywidgets
110
104
  # matplotlib-inline
111
- typing-extensions==4.12.2
112
- # via ipython
113
105
  urllib3==2.3.0
114
106
  # via requests
115
107
  wcwidth==0.2.13
@@ -44,14 +44,8 @@ requests==2.32.3
44
44
  # via -r ci.in
45
45
  smmap==5.0.2
46
46
  # via gitdb
47
- tomli==2.2.1
48
- # via
49
- # pyproject-api
50
- # tox
51
47
  tox==4.24.1
52
48
  # via -r ci.in
53
- typing-extensions==4.12.2
54
- # via tox
55
49
  urllib3==2.3.0
56
50
  # via requests
57
51
  virtualenv==20.29.2
@@ -12,8 +12,6 @@
12
12
  -r static.txt
13
13
  -r test.txt
14
14
  -r wheels.txt
15
- annotated-types==0.7.0
16
- # via pydantic
17
15
  anyio==4.8.0
18
16
  # via
19
17
  # httpx
@@ -32,7 +30,7 @@ click==8.1.8
32
30
  # via
33
31
  # pip-compile-multi
34
32
  # pip-tools
35
- copier==9.4.1
33
+ copier==9.5.0
36
34
  # via -r dev.in
37
35
  dunamai==1.23.0
38
36
  # via copier
@@ -91,10 +89,6 @@ prometheus-client==0.21.1
91
89
  # via jupyter-server
92
90
  pycparser==2.22
93
91
  # via cffi
94
- pydantic==2.10.6
95
- # via copier
96
- pydantic-core==2.27.2
97
- # via pydantic
98
92
  python-json-logger==3.2.1
99
93
  # via jupyter-events
100
94
  questionary==2.1.0
@@ -10,8 +10,6 @@ accessible-pygments==0.0.5
10
10
  # via pydata-sphinx-theme
11
11
  alabaster==1.0.0
12
12
  # via sphinx
13
- appnope==0.1.4
14
- # via ipykernel
15
13
  asttokens==3.0.0
16
14
  # via stack-data
17
15
  attrs==25.1.0
@@ -48,16 +46,12 @@ docutils==0.21.2
48
46
  # nbsphinx
49
47
  # pydata-sphinx-theme
50
48
  # sphinx
51
- exceptiongroup==1.2.2
52
- # via ipython
53
49
  executing==2.2.0
54
50
  # via stack-data
55
51
  fastjsonschema==2.21.1
56
52
  # via nbformat
57
53
  graphviz==0.20.3
58
54
  # via -r docs.in
59
- idna==3.10
60
- # via requests
61
55
  imagesize==1.4.1
62
56
  # via sphinx
63
57
  importlib-resources==6.5.2
@@ -141,7 +135,7 @@ platformdirs==4.3.6
141
135
  # via jupyter-core
142
136
  prompt-toolkit==3.0.50
143
137
  # via ipython
144
- psutil==6.1.1
138
+ psutil==7.0.0
145
139
  # via ipykernel
146
140
  ptyprocess==0.7.0
147
141
  # via pexpect
@@ -209,8 +203,6 @@ tinycss2==1.4.0
209
203
  # via bleach
210
204
  tof==25.2.0
211
205
  # via -r docs.in
212
- tomli==2.2.1
213
- # via sphinx
214
206
  tornado==6.4.2
215
207
  # via
216
208
  # ipykernel
@@ -228,13 +220,6 @@ traitlets==5.14.3
228
220
  # nbconvert
229
221
  # nbformat
230
222
  # nbsphinx
231
- typing-extensions==4.12.2
232
- # via
233
- # beautifulsoup4
234
- # ipython
235
- # mistune
236
- # pydata-sphinx-theme
237
- # referencing
238
223
  urllib3==2.3.0
239
224
  # via requests
240
225
  wcwidth==0.2.13
@@ -32,10 +32,6 @@ dnspython==2.7.0
32
32
  # via email-validator
33
33
  email-validator==2.2.0
34
34
  # via scippneutron
35
- exceptiongroup==1.2.2
36
- # via
37
- # ipython
38
- # pytest
39
35
  executing==2.2.0
40
36
  # via stack-data
41
37
  fonttools==4.56.0
@@ -74,7 +70,7 @@ mpltoolbox==24.5.1
74
70
  # via scippneutron
75
71
  networkx==3.4.2
76
72
  # via cyclebane
77
- numpy==2.2.2
73
+ numpy==2.2.3
78
74
  # via
79
75
  # contourpy
80
76
  # h5py
@@ -142,7 +138,7 @@ scippnexus @ git+https://github.com/scipp/scippnexus@main
142
138
  # via
143
139
  # -r nightly.in
144
140
  # scippneutron
145
- scipy==1.15.1
141
+ scipy==1.15.2
146
142
  # via
147
143
  # -r nightly.in
148
144
  # scippneutron
@@ -154,8 +150,6 @@ stack-data==0.6.3
154
150
  # via ipython
155
151
  tof @ git+https://github.com/scipp/tof@main
156
152
  # via -r nightly.in
157
- tomli==2.2.1
158
- # via pytest
159
153
  traitlets==5.14.3
160
154
  # via
161
155
  # comm
@@ -164,7 +158,6 @@ traitlets==5.14.3
164
158
  # matplotlib-inline
165
159
  typing-extensions==4.12.2
166
160
  # via
167
- # ipython
168
161
  # pydantic
169
162
  # pydantic-core
170
163
  urllib3==2.3.0
@@ -11,5 +11,3 @@ packaging==24.2
11
11
  # via build
12
12
  pyproject-hooks==1.2.0
13
13
  # via build
14
- tomli==2.2.1
15
- # via build
@@ -8,14 +8,16 @@ from collections.abc import Generator, Mapping
8
8
  from contextlib import AbstractContextManager, contextmanager, nullcontext
9
9
  from dataclasses import dataclass
10
10
  from math import prod
11
- from typing import cast
11
+ from typing import TypeVar, cast
12
12
 
13
13
  import scipp as sc
14
14
  import scippnexus as snx
15
15
 
16
16
  from ..logging import get_logger
17
17
  from .types import (
18
+ Beamline,
18
19
  FilePath,
20
+ Measurement,
19
21
  NeXusAllLocationSpec,
20
22
  NeXusEntryName,
21
23
  NeXusFile,
@@ -27,6 +29,8 @@ from .types import (
27
29
  class NoNewDefinitionsType: ...
28
30
 
29
31
 
32
+ _Model = TypeVar('_Model', Beamline, Measurement)
33
+
30
34
  NoNewDefinitions = NoNewDefinitionsType()
31
35
 
32
36
 
@@ -74,6 +78,18 @@ def load_all_components(
74
78
  return components
75
79
 
76
80
 
81
+ def load_metadata(
82
+ file_path: FilePath | NeXusFile | NeXusGroup,
83
+ model: type[_Model],
84
+ *,
85
+ entry_name: NeXusEntryName | None = None,
86
+ definitions: Mapping | NoNewDefinitionsType = NoNewDefinitions,
87
+ ) -> _Model:
88
+ with _open_nexus_file(file_path, definitions=definitions) as f:
89
+ entry = _unique_child_group(f, snx.NXentry, entry_name)
90
+ return model.from_nexus_entry(entry)
91
+
92
+
77
93
  def compute_component_position(dg: sc.DataGroup) -> sc.DataGroup:
78
94
  # In some downstream packages we use some of the Nexus components which attempt
79
95
  # to compute positions without having actual Nexus data defining depends_on chains.
@@ -164,10 +180,15 @@ def _attempt_to_open_without_locking(
164
180
  # HDF5 tracks file locking flags internally within a single process.
165
181
  # If the same file is opened multiple times, we can get a flag mismatch.
166
182
  # We can try opening without locking, maybe this matches the original flags.
167
- if "file locking flag values don't match" in err.args[0]:
168
- return True
169
- if "file locking 'ignore disabled locks' flag values don't match" in err.args[0]:
170
- return True
183
+ error_message = err.args[0]
184
+ if isinstance(error_message, str):
185
+ if "file locking flag values don't match" in error_message:
186
+ return True
187
+ if (
188
+ "file locking 'ignore disabled locks' flag values don't match"
189
+ in error_message
190
+ ):
191
+ return True
171
192
  return False
172
193
 
173
194
 
@@ -7,6 +7,7 @@ from typing import Any, BinaryIO, Generic, NewType, TypeVar
7
7
  import sciline
8
8
  import scipp as sc
9
9
  import scippnexus as snx
10
+ from scippneutron import metadata as scn_meta
10
11
 
11
12
  FilePath = NewType('FilePath', Path)
12
13
  """Full path to a NeXus file on disk."""
@@ -177,6 +178,13 @@ Component = TypeVar(
177
178
  UniqueComponent = TypeVar('UniqueComponent', snx.NXsample, snx.NXsource)
178
179
  """Components that can be identified by their type as there will only be one."""
179
180
 
181
+ Beamline = scn_meta.Beamline
182
+ """Beamline metadata."""
183
+ Measurement = scn_meta.Measurement
184
+ """measurement metadata."""
185
+ Source = scn_meta.Source
186
+ """Neutron source metadata."""
187
+
180
188
 
181
189
  class NeXusName(sciline.Scope[Component, str], str):
182
190
  """Name of a component in a NeXus file."""
@@ -19,6 +19,7 @@ from . import _nexus_loader as nexus
19
19
  from .types import (
20
20
  AllNeXusComponents,
21
21
  Analyzers,
22
+ Beamline,
22
23
  CalibratedBeamline,
23
24
  CalibratedDetector,
24
25
  CalibratedMonitor,
@@ -29,6 +30,7 @@ from .types import (
29
30
  DetectorPositionOffset,
30
31
  Filename,
31
32
  GravityVector,
33
+ Measurement,
32
34
  MonitorData,
33
35
  MonitorPositionOffset,
34
36
  MonitorType,
@@ -45,6 +47,7 @@ from .types import (
45
47
  Position,
46
48
  PreopenNeXusFile,
47
49
  RunType,
50
+ SampleRun,
48
51
  TimeInterval,
49
52
  UniqueComponent,
50
53
  )
@@ -586,6 +589,18 @@ def _add_variances(da: sc.DataArray) -> sc.DataArray:
586
589
  return out
587
590
 
588
591
 
592
+ def load_beamline_metadata_from_nexus(file_spec: NeXusFileSpec[SampleRun]) -> Beamline:
593
+ """Load beamline metadata from a sample NeXus file."""
594
+ return nexus.load_metadata(file_spec.value, Beamline)
595
+
596
+
597
+ def load_measurement_metadata_from_nexus(
598
+ file_spec: NeXusFileSpec[SampleRun],
599
+ ) -> Measurement:
600
+ """Load measurement metadata from a sample NeXus file."""
601
+ return nexus.load_metadata(file_spec.value, Measurement)
602
+
603
+
589
604
  definitions = snx.base_definitions()
590
605
  definitions["NXdetector"] = _StrippedDetector
591
606
  definitions["NXmonitor"] = _StrippedMonitor
@@ -631,6 +646,11 @@ _chopper_providers = (parse_disk_choppers,)
631
646
 
632
647
  _analyzer_providers = (parse_analyzers,)
633
648
 
649
+ _metadata_providers = (
650
+ load_beamline_metadata_from_nexus,
651
+ load_measurement_metadata_from_nexus,
652
+ )
653
+
634
654
 
635
655
  def LoadMonitorWorkflow() -> sciline.Pipeline:
636
656
  """Generic workflow for loading monitor data from a NeXus file."""
@@ -689,6 +709,7 @@ def GenericNeXusWorkflow(
689
709
  *_detector_providers,
690
710
  *_chopper_providers,
691
711
  *_analyzer_providers,
712
+ *_metadata_providers,
692
713
  )
693
714
  )
694
715
  wf[DetectorBankSizes] = DetectorBankSizes({})
@@ -68,7 +68,18 @@ class Accumulator(ABC, Generic[T]):
68
68
  def _do_push(self, value: T) -> None: ...
69
69
 
70
70
  @property
71
- @abstractmethod
71
+ def is_empty(self) -> bool:
72
+ """
73
+ Check if the accumulator is empty.
74
+
75
+ Returns
76
+ -------
77
+ :
78
+ True if the accumulator is empty, False otherwise.
79
+ """
80
+ return False
81
+
82
+ @property
72
83
  def value(self) -> T:
73
84
  """
74
85
  Get the accumulated value.
@@ -77,6 +88,24 @@ class Accumulator(ABC, Generic[T]):
77
88
  -------
78
89
  :
79
90
  Accumulated value.
91
+
92
+ Raises
93
+ ------
94
+ ValueError
95
+ If the accumulator is empty.
96
+ """
97
+ if self.is_empty:
98
+ raise ValueError("Cannot get value from empty accumulator")
99
+ return self._get_value()
100
+
101
+ @abstractmethod
102
+ def _get_value(self) -> T:
103
+ """Return the accumulated value, assuming it exists."""
104
+
105
+ @abstractmethod
106
+ def clear(self) -> None:
107
+ """
108
+ Clear the accumulator, resetting it to its initial state.
80
109
  """
81
110
 
82
111
 
@@ -92,7 +121,10 @@ class EternalAccumulator(Accumulator[T]):
92
121
  self._value: T | None = None
93
122
 
94
123
  @property
95
- def value(self) -> T:
124
+ def is_empty(self) -> bool:
125
+ return self._value is None
126
+
127
+ def _get_value(self) -> T:
96
128
  return deepcopy(self._value)
97
129
 
98
130
  def _do_push(self, value: T) -> None:
@@ -101,6 +133,10 @@ class EternalAccumulator(Accumulator[T]):
101
133
  else:
102
134
  self._value += value
103
135
 
136
+ def clear(self) -> None:
137
+ """Clear the accumulated value."""
138
+ self._value = None
139
+
104
140
 
105
141
  class RollingAccumulator(Accumulator[T]):
106
142
  """
@@ -121,7 +157,10 @@ class RollingAccumulator(Accumulator[T]):
121
157
  self._values: list[T] = []
122
158
 
123
159
  @property
124
- def value(self) -> T:
160
+ def is_empty(self) -> bool:
161
+ return len(self._values) == 0
162
+
163
+ def _get_value(self) -> T:
125
164
  # Naive and potentially slow implementation if values and/or window are large!
126
165
  return sc.reduce(self._values).sum()
127
166
 
@@ -130,6 +169,10 @@ class RollingAccumulator(Accumulator[T]):
130
169
  if len(self._values) > self._window:
131
170
  self._values.pop(0)
132
171
 
172
+ def clear(self) -> None:
173
+ """Clear the accumulated values."""
174
+ self._values = []
175
+
133
176
 
134
177
  class StreamProcessor:
135
178
  """
@@ -299,6 +342,16 @@ class StreamProcessor:
299
342
  self._finalize_workflow[key] = self._accumulators[key].value
300
343
  return self._finalize_workflow.compute(self._target_keys)
301
344
 
345
+ def clear(self) -> None:
346
+ """
347
+ Clear all accumulators, resetting them to their initial state.
348
+
349
+ This is useful for restarting a streaming computation without
350
+ creating a new StreamProcessor instance.
351
+ """
352
+ for accumulator in self._accumulators.values():
353
+ accumulator.clear()
354
+
302
355
 
303
356
  def _find_descendants(
304
357
  workflow: sciline.Pipeline, keys: tuple[sciline.typing.Key, ...]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: essreduce
3
- Version: 25.2.3
3
+ Version: 25.2.5
4
4
  Summary: Common data reduction tools for the ESS facility
5
5
  Author: Scipp contributors
6
6
  License: BSD 3-Clause License
@@ -53,7 +53,7 @@ Description-Content-Type: text/markdown
53
53
  License-File: LICENSE
54
54
  Requires-Dist: sciline>=24.06.2
55
55
  Requires-Dist: scipp>=25.01.0
56
- Requires-Dist: scippneutron>=24.11.0
56
+ Requires-Dist: scippneutron>=25.02.0
57
57
  Requires-Dist: scippnexus>=24.11.0
58
58
  Provides-Extra: test
59
59
  Requires-Dist: ipywidgets; extra == "test"
@@ -1,6 +1,6 @@
1
1
  sciline>=24.06.2
2
2
  scipp>=25.01.0
3
- scippneutron>=24.11.0
3
+ scippneutron>=25.02.0
4
4
  scippnexus>=24.11.0
5
5
 
6
6
  [test]
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: BSD-3-Clause
2
2
  # Copyright (c) 2024 Scipp contributors (https://github.com/scipp)
3
-
3
+ import os
4
+ import sys
4
5
  from contextlib import contextmanager
5
6
  from io import BytesIO
6
7
  from pathlib import Path
@@ -661,17 +662,34 @@ def test_open_nexus_file_multiple_times(tmp_path: Path, locks: tuple[Any, Any])
661
662
  assert f1.name == f2.name
662
663
 
663
664
 
665
+ def _in_conda_env():
666
+ return 'CONDA_PREFIX' in os.environ
667
+
668
+
669
+ def _test_open_nexus_file_with_mismatched_locking(
670
+ tmp_path: Path, locks: tuple[Any, Any]
671
+ ) -> None:
672
+ from ess.reduce.nexus._nexus_loader import _open_nexus_file
673
+
674
+ path = FilePath(tmp_path / "file.nxs")
675
+ with snx.File(path, "w"):
676
+ pass
677
+
678
+ with _open_nexus_file(path, locking=locks[0]):
679
+ with pytest.raises(OSError, match="flag values don't match"):
680
+ _ = _open_nexus_file(path, locking=locks[1])
681
+
682
+
683
+ @pytest.mark.skipif(
684
+ sys.platform in ("darwin", "win32")
685
+ or (sys.platform == "linux" and _in_conda_env()),
686
+ reason="HDF5 has different file locking flags on MacOS, Windows and Linux(conda)",
687
+ )
664
688
  @pytest.mark.parametrize(
665
689
  "locks",
666
690
  [
667
- (True, False),
668
691
  (True, None),
669
- (False, True),
670
- (False, None),
671
692
  (None, True),
672
- (None, False),
673
- # On a read-only filesystem, this would work:
674
- (NoLockingIfNeeded, False),
675
693
  # This could be supported, but it could cause problems because the first
676
694
  # user expects the file to be locked.
677
695
  (True, NoLockingIfNeeded),
@@ -679,15 +697,31 @@ def test_open_nexus_file_multiple_times(tmp_path: Path, locks: tuple[Any, Any])
679
697
  (NoLockingIfNeeded, True),
680
698
  ],
681
699
  )
682
- def test_open_nexus_file_with_mismatched_locking(
700
+ def test_open_nexus_file_with_mismatched_locking_pypi_linux(
683
701
  tmp_path: Path, locks: tuple[Any, Any]
684
702
  ) -> None:
685
- from ess.reduce.nexus._nexus_loader import _open_nexus_file
703
+ _test_open_nexus_file_with_mismatched_locking(tmp_path, locks)
686
704
 
687
- path = FilePath(tmp_path / "file.nxs")
688
- with snx.File(path, "w"):
689
- pass
690
705
 
691
- with _open_nexus_file(path, locking=locks[0]):
692
- with pytest.raises(OSError, match="flag values don't match"):
693
- _ = _open_nexus_file(path, locking=locks[1])
706
+ @pytest.mark.parametrize(
707
+ "locks",
708
+ [
709
+ (True, False),
710
+ (False, True),
711
+ (False, None),
712
+ (None, False),
713
+ # On a read-only filesystem, this would work:
714
+ (NoLockingIfNeeded, False),
715
+ ],
716
+ )
717
+ def test_open_nexus_file_with_mismatched_locking_all(
718
+ tmp_path: Path, locks: tuple[Any, Any]
719
+ ) -> None:
720
+ _test_open_nexus_file_with_mismatched_locking(tmp_path, locks)
721
+
722
+
723
+ def test_open_nonexisting_file_raises_filenotfounderror():
724
+ from ess.reduce.nexus._nexus_loader import _open_nexus_file
725
+
726
+ with pytest.raises(FileNotFoundError):
727
+ _open_nexus_file(nexus.types.FilePath(Path("doesnotexist.hdf")))