diff --git a/docs/api-reference/index.md b/docs/api-reference/index.md index c2b9c5ea..2aa969cd 100644 --- a/docs/api-reference/index.md +++ b/docs/api-reference/index.md @@ -33,6 +33,7 @@ supermirror types tools + workflow ``` ## Amor diff --git a/pyproject.toml b/pyproject.toml index 49861140..ad27d416 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,7 @@ dependencies = [ "scippneutron>=24.7.0", "scippnexus>=24.9.1", "essreduce", + "pandas", ] dynamic = ["version"] diff --git a/requirements/base.in b/requirements/base.in index d8b4110d..9a9b4305 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -13,3 +13,4 @@ scipp>=24.09.1 scippneutron>=24.7.0 scippnexus>=24.9.1 essreduce +pandas diff --git a/requirements/base.txt b/requirements/base.txt index 4d8a9710..3ca794a6 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,4 +1,4 @@ -# SHA1:3401cd389c29441d88f259ef065f189c2f02bfcb +# SHA1:e82c2f6f325de86a068c5252c20acc8ebeb12449 # # This file is autogenerated by pip-compile-multi # To update, run: @@ -9,21 +9,21 @@ asttokens==2.4.1 # via stack-data click==8.1.7 # via dask -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via dask comm==0.2.2 # via ipywidgets contourpy==1.3.0 # via matplotlib -cyclebane==24.6.0 +cyclebane==24.10.0 # via sciline cycler==0.12.1 # via matplotlib -dask==2024.9.0 +dask==2024.10.0 # via -r base.in decorator==5.1.1 # via ipython -essreduce==24.9.1 +essreduce==24.10.2 # via -r base.in exceptiongroup==1.2.2 # via ipython @@ -31,11 +31,11 @@ executing==2.1.0 # via stack-data fonttools==4.54.1 # via matplotlib -fsspec==2024.9.0 +fsspec==2024.10.0 # via dask graphviz==0.20.3 # via -r base.in -h5py==3.11.0 +h5py==3.12.1 # via # scippneutron # scippnexus @@ -43,7 +43,7 @@ importlib-metadata==8.5.0 # via dask ipydatawidgets==4.3.5 # via pythreejs -ipython==8.27.0 +ipython==8.28.0 # via ipywidgets ipywidgets==8.1.5 # via @@ -65,15 +65,16 @@ matplotlib-inline==0.1.7 # via ipython mpltoolbox==24.5.1 # via scippneutron -networkx==3.3 +networkx==3.4.2 # via cyclebane -numpy==2.1.1 +numpy==2.1.2 # via # contourpy # h5py # ipydatawidgets # matplotlib # mpltoolbox + # pandas # pythreejs # scipp # scippneutron @@ -84,13 +85,15 @@ packaging==24.1 # via # dask # matplotlib +pandas==2.2.3 + # via -r base.in parso==0.8.4 # via jedi partd==1.4.2 # via dask pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via matplotlib plopp==24.9.3 # via @@ -104,15 +107,18 @@ pure-eval==0.2.3 # via stack-data pygments==2.18.0 # via ipython -pyparsing==3.1.4 +pyparsing==3.2.0 # via matplotlib python-dateutil==2.9.0.post0 # via # -r base.in # matplotlib + # pandas # scippnexus pythreejs==2.4.2 # via -r base.in +pytz==2024.2 + # via pandas pyyaml==6.0.2 # via # dask @@ -129,7 +135,7 @@ scipp==24.9.1 # scippnexus scippneutron==24.9.0 # via -r base.in -scippnexus==24.9.1 +scippnexus==24.10.0 # via # -r base.in # essreduce @@ -144,7 +150,7 @@ six==1.16.0 # python-dateutil stack-data==0.6.3 # via ipython -toolz==0.12.1 +toolz==1.0.0 # via # dask # partd @@ -160,6 +166,8 @@ traittypes==0.2.1 # via ipydatawidgets typing-extensions==4.12.2 # via ipython +tzdata==2024.2 + # via pandas wcwidth==0.2.13 # via prompt-toolkit widgetsnbextension==4.0.13 diff --git a/requirements/basetest.txt b/requirements/basetest.txt index 6b41e80e..e3cc752b 100644 --- a/requirements/basetest.txt +++ b/requirements/basetest.txt @@ -7,7 +7,7 @@ # certifi==2024.8.30 # via requests -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests exceptiongroup==1.2.2 # via pytest @@ -29,7 +29,7 @@ pytest==8.3.3 # via -r basetest.in requests==2.32.3 # via pooch -tomli==2.0.1 +tomli==2.0.2 # via pytest urllib3==2.2.3 # via requests diff --git a/requirements/ci.txt b/requirements/ci.txt index af1677b2..b5cee138 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -11,11 +11,11 @@ certifi==2024.8.30 # via requests chardet==5.2.0 # via tox -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests colorama==0.4.6 # via tox -distlib==0.3.8 +distlib==0.3.9 # via virtualenv filelock==3.16.1 # via @@ -44,13 +44,15 @@ requests==2.32.3 # via -r ci.in smmap==5.0.1 # via gitdb -tomli==2.0.1 +tomli==2.0.2 # via # pyproject-api # tox -tox==4.20.0 +tox==4.23.1 # via -r ci.in +typing-extensions==4.12.2 + # via tox urllib3==2.2.3 # via requests -virtualenv==20.26.5 +virtualenv==20.27.0 # via tox diff --git a/requirements/dev.txt b/requirements/dev.txt index 292820d0..69864a36 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -14,7 +14,7 @@ -r wheels.txt annotated-types==0.7.0 # via pydantic -anyio==4.6.0 +anyio==4.6.2.post1 # via # httpx # jupyter-server @@ -28,7 +28,7 @@ async-lru==2.0.4 # via jupyterlab cffi==1.17.1 # via argon2-cffi-bindings -copier==9.3.1 +copier==9.4.1 # via -r dev.in dunamai==1.22.0 # via copier @@ -38,7 +38,7 @@ funcy==2.0 # via copier h11==0.14.0 # via httpcore -httpcore==1.0.5 +httpcore==1.0.6 # via httpx httpx==0.27.2 # via jupyterlab @@ -81,7 +81,7 @@ pip-compile-multi==2.6.4 # via -r dev.in pip-tools==7.4.1 # via pip-compile-multi -plumbum==1.8.3 +plumbum==1.9.0 # via copier prometheus-client==0.21.0 # via jupyter-server @@ -115,7 +115,7 @@ terminado==0.18.1 # jupyter-server-terminals toposort==1.10 # via pip-compile-multi -types-python-dateutil==2.9.0.20240906 +types-python-dateutil==2.9.0.20241003 # via arrow uri-template==1.3.0 # via jsonschema diff --git a/requirements/docs.txt b/requirements/docs.txt index 493a07c7..899a8659 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -26,9 +26,9 @@ bleach==6.1.0 # via nbconvert certifi==2024.8.30 # via requests -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 # via requests -debugpy==1.8.6 +debugpy==1.8.7 # via ipykernel defusedxml==0.7.1 # via nbconvert @@ -54,7 +54,7 @@ jinja2==3.1.4 # sphinx jsonschema==4.23.0 # via nbformat -jsonschema-specifications==2023.12.1 +jsonschema-specifications==2024.10.1 # via jsonschema jupyter-client==8.6.3 # via @@ -73,7 +73,7 @@ markdown-it-py==3.0.0 # via # mdit-py-plugins # myst-parser -markupsafe==2.1.5 +markupsafe==3.0.2 # via # jinja2 # nbconvert @@ -106,7 +106,7 @@ platformdirs==4.3.6 # pooch pooch==1.8.2 # via -r docs.in -psutil==6.0.0 +psutil==6.1.0 # via ipykernel pydata-sphinx-theme==0.15.4 # via -r docs.in @@ -130,7 +130,7 @@ snowballstemmer==2.2.0 # via sphinx soupsieve==2.6 # via beautifulsoup4 -sphinx==8.0.2 +sphinx==8.1.3 # via # -r docs.in # myst-parser @@ -139,7 +139,7 @@ sphinx==8.0.2 # sphinx-autodoc-typehints # sphinx-copybutton # sphinx-design -sphinx-autodoc-typehints==2.4.4 +sphinx-autodoc-typehints==2.5.0 # via -r docs.in sphinx-copybutton==0.5.2 # via -r docs.in @@ -159,7 +159,7 @@ sphinxcontrib-serializinghtml==2.0.0 # via sphinx tinycss2==1.3.0 # via nbconvert -tomli==2.0.1 +tomli==2.0.2 # via sphinx tornado==6.4.1 # via diff --git a/requirements/mypy.txt b/requirements/mypy.txt index c5815809..db2aac1e 100644 --- a/requirements/mypy.txt +++ b/requirements/mypy.txt @@ -6,7 +6,7 @@ # pip-compile-multi # -r test.txt -mypy==1.11.2 +mypy==1.12.1 # via -r mypy.in mypy-extensions==1.0.0 # via mypy diff --git a/requirements/nightly.in b/requirements/nightly.in index c4d3f4f1..b12e591d 100644 --- a/requirements/nightly.in +++ b/requirements/nightly.in @@ -7,6 +7,7 @@ graphviz pythreejs orsopy essreduce +pandas plopp @ git+https://github.com/scipp/plopp@main sciline @ git+https://github.com/scipp/sciline@main scippneutron @ git+https://github.com/scipp/scippneutron@main diff --git a/requirements/nightly.txt b/requirements/nightly.txt index 544e265c..0e64b1c3 100644 --- a/requirements/nightly.txt +++ b/requirements/nightly.txt @@ -1,4 +1,4 @@ -# SHA1:e9966047ff7ccde31021cec89e7c13d1677ca1b4 +# SHA1:640f58e5ad1febf91a7d33e8a1c093d0b73f18d0 # # This file is autogenerated by pip-compile-multi # To update, run: @@ -10,31 +10,31 @@ asttokens==2.4.1 # via stack-data click==8.1.7 # via dask -cloudpickle==3.0.0 +cloudpickle==3.1.0 # via dask comm==0.2.2 # via ipywidgets contourpy==1.3.0 # via matplotlib -cyclebane==24.6.0 +cyclebane==24.10.0 # via sciline cycler==0.12.1 # via matplotlib -dask==2024.9.0 +dask==2024.10.0 # via -r nightly.in decorator==5.1.1 # via ipython -essreduce==24.9.1 +essreduce==24.10.2 # via -r nightly.in executing==2.1.0 # via stack-data fonttools==4.54.1 # via matplotlib -fsspec==2024.9.0 +fsspec==2024.10.0 # via dask graphviz==0.20.3 # via -r nightly.in -h5py==3.11.0 +h5py==3.12.1 # via # scippneutron # scippnexus @@ -42,7 +42,7 @@ importlib-metadata==8.5.0 # via dask ipydatawidgets==4.3.5 # via pythreejs -ipython==8.27.0 +ipython==8.28.0 # via ipywidgets ipywidgets==8.1.5 # via @@ -64,28 +64,31 @@ matplotlib-inline==0.1.7 # via ipython mpltoolbox==24.5.1 # via scippneutron -networkx==3.3 +networkx==3.4.2 # via cyclebane -numpy==2.1.1 +numpy==2.1.2 # via # contourpy # h5py # ipydatawidgets # matplotlib # mpltoolbox + # pandas # pythreejs # scipp # scippneutron # scipy orsopy==1.2.1 # via -r nightly.in +pandas==2.2.3 + # via -r nightly.in parso==0.8.4 # via jedi partd==1.4.2 # via dask pexpect==4.9.0 # via ipython -pillow==10.4.0 +pillow==11.0.0 # via matplotlib plopp @ git+https://github.com/scipp/plopp@main # via @@ -99,15 +102,18 @@ pure-eval==0.2.3 # via stack-data pygments==2.18.0 # via ipython -pyparsing==3.1.4 +pyparsing==3.2.0 # via matplotlib python-dateutil==2.9.0.post0 # via # -r nightly.in # matplotlib + # pandas # scippnexus pythreejs==2.4.2 # via -r nightly.in +pytz==2024.2 + # via pandas pyyaml==6.0.2 # via # dask @@ -139,7 +145,7 @@ six==1.16.0 # python-dateutil stack-data==0.6.3 # via ipython -toolz==0.12.1 +toolz==1.0.0 # via # dask # partd @@ -155,6 +161,8 @@ traittypes==0.2.1 # via ipydatawidgets typing-extensions==4.12.2 # via ipython +tzdata==2024.2 + # via pandas wcwidth==0.2.13 # via prompt-toolkit widgetsnbextension==4.0.13 diff --git a/requirements/static.txt b/requirements/static.txt index d7f3ca42..f1d39822 100644 --- a/requirements/static.txt +++ b/requirements/static.txt @@ -7,7 +7,7 @@ # cfgv==3.4.0 # via pre-commit -distlib==0.3.8 +distlib==0.3.9 # via virtualenv filelock==3.16.1 # via virtualenv @@ -17,9 +17,9 @@ nodeenv==1.9.1 # via pre-commit platformdirs==4.3.6 # via virtualenv -pre-commit==3.8.0 +pre-commit==4.0.1 # via -r static.in pyyaml==6.0.2 # via pre-commit -virtualenv==20.26.5 +virtualenv==20.27.0 # via pre-commit diff --git a/requirements/wheels.txt b/requirements/wheels.txt index 24447442..d1c1063b 100644 --- a/requirements/wheels.txt +++ b/requirements/wheels.txt @@ -5,11 +5,11 @@ # # pip-compile-multi # -build==1.2.2 +build==1.2.2.post1 # via -r wheels.in packaging==24.1 # via build -pyproject-hooks==1.1.0 +pyproject-hooks==1.2.0 # via build -tomli==2.0.1 +tomli==2.0.2 # via build diff --git a/src/ess/reflectometry/conversions.py b/src/ess/reflectometry/conversions.py index 0e3bee04..494699ee 100644 --- a/src/ess/reflectometry/conversions.py +++ b/src/ess/reflectometry/conversions.py @@ -9,6 +9,7 @@ from .types import ( BeamDivergenceLimits, DataWithScatteringCoordinates, + DetectorRotation, Gravity, IncidentBeam, MaskedData, @@ -109,6 +110,7 @@ def specular_reflection( incident_beam: IncidentBeam[RunType], sample_position: SamplePosition[RunType], sample_rotation: SampleRotation[RunType], + detector_rotation: DetectorRotation[RunType], gravity: Gravity, ) -> SpecularReflectionCoordTransformGraph[RunType]: """ @@ -127,6 +129,7 @@ def specular_reflection( "incident_beam": lambda: incident_beam, "sample_position": lambda: sample_position, "sample_rotation": lambda: sample_rotation, + "detector_rotation": lambda: detector_rotation, "gravity": lambda: gravity, } return SpecularReflectionCoordTransformGraph(graph) @@ -136,7 +139,10 @@ def add_coords( da: ReducibleDetectorData[RunType], graph: SpecularReflectionCoordTransformGraph[RunType], ) -> DataWithScatteringCoordinates[RunType]: - da = da.transform_coords(["theta", "wavelength", "Q"], graph=graph) + da = da.transform_coords( + ["theta", "wavelength", "Q", "detector_rotation"], graph=graph + ) + da.coords.set_aligned('detector_rotation', False) da.coords["z_index"] = sc.arange( "row", 0, da.sizes["blade"] * da.sizes["wire"], unit=None ).fold("row", sizes={dim: da.sizes[dim] for dim in ("blade", "wire")}) diff --git a/src/ess/reflectometry/orso.py b/src/ess/reflectometry/orso.py index a421899c..6244f9b4 100644 --- a/src/ess/reflectometry/orso.py +++ b/src/ess/reflectometry/orso.py @@ -59,6 +59,9 @@ OrsoSample = NewType("OrsoSample", data_source.Sample) """ORSO sample.""" +OrsoSampleFilenames = NewType("OrsoSampleFilenames", list[orso_base.File]) +"""Collection of filenames used to create the ORSO file""" + def parse_orso_experiment(filename: Filename[SampleRun]) -> OrsoExperiment: """Parse ORSO experiment metadata from raw NeXus data.""" @@ -107,8 +110,13 @@ def parse_orso_sample(filename: Filename[SampleRun]) -> OrsoSample: ) +def orso_data_files(filename: Filename[SampleRun]) -> OrsoSampleFilenames: + '''Collects names of files used in the experiment''' + return [orso_base.File(file=os.path.basename(filename))] + + def build_orso_measurement( - sample_filename: Filename[SampleRun], + sample_filenames: OrsoSampleFilenames, reference_filename: Filename[ReferenceRun], instrument: OrsoInstrument, ) -> OrsoMeasurement: @@ -127,7 +135,7 @@ def build_orso_measurement( return OrsoMeasurement( data_source.Measurement( instrument_settings=instrument, - data_files=[orso_base.File(file=os.path.basename(sample_filename))], + data_files=sample_filenames, additional_files=additional_files, ) ) @@ -220,4 +228,5 @@ def find_corrections(task_graph: TaskGraph) -> list[str]: parse_orso_experiment, parse_orso_owner, parse_orso_sample, + orso_data_files, ) diff --git a/src/ess/reflectometry/workflow.py b/src/ess/reflectometry/workflow.py new file mode 100644 index 00000000..c489b2cb --- /dev/null +++ b/src/ess/reflectometry/workflow.py @@ -0,0 +1,93 @@ +from collections.abc import Hashable, Sequence +from itertools import chain + +import pandas as pd +import sciline +import scipp as sc + +from ess.amor.types import RawChopper +from ess.reflectometry.orso import ( + OrsoExperiment, + OrsoOwner, + OrsoSample, + OrsoSampleFilenames, +) +from ess.reflectometry.types import ( + Filename, + FootprintCorrectedData, + RunType, + SampleRotation, + SampleRun, +) + + +def _concatenate_event_lists(*das): + return ( + sc.reduce(das) + .bins.concat() + .assign_coords( + { + name: das[0].coords[name] + for name in ('position', 'sample_rotation', 'detector_rotation') + } + ) + ) + + +def _any_value(x, *_): + return x + + +def _concatenate_lists(*x): + return list(chain(*x)) + + +def with_filenames( + workflow, runtype: Hashable, runs: Sequence[Filename[RunType]] +) -> sciline.Pipeline: + '''Sets a number of :code:`Filename[runtype]` simultaneously. + The events from all listed files are concatenated in the workflow. + + Arguments + ---------- + workflow: + the workflow to copy and add the filenames to + runtype: + the kind of runtype to add the files as. + Example: :code:`SampleRun` or :code:`ReferenceRun`. + runs: + the list of filenames to map over + + Returns + --------- + A copy of the original workflow mapping over the provided files. + ''' + axis_name = f'{str(runtype).lower()}_runs' + df = pd.DataFrame({Filename[runtype]: runs}).rename_axis(axis_name) + wf = workflow.copy() + + mapped = wf.map(df) + + wf[FootprintCorrectedData[runtype]] = mapped[ + FootprintCorrectedData[runtype] + ].reduce(index=axis_name, func=_concatenate_event_lists) + wf[RawChopper[runtype]] = mapped[RawChopper[runtype]].reduce( + index=axis_name, func=_any_value + ) + wf[SampleRotation[runtype]] = mapped[SampleRotation[runtype]].reduce( + index=axis_name, func=_any_value + ) + + if runtype is SampleRun: + wf[OrsoSample] = mapped[OrsoSample].reduce(index=axis_name, func=_any_value) + wf[OrsoExperiment] = mapped[OrsoExperiment].reduce( + index=axis_name, func=_any_value + ) + wf[OrsoOwner] = mapped[OrsoOwner].reduce(index=axis_name, func=lambda x, *_: x) + wf[OrsoSampleFilenames] = mapped[OrsoSampleFilenames].reduce( + # When we don't map over filenames + # each OrsoSampleFilenames is a list with a single entry. + index=axis_name, + func=_concatenate_lists, + ) + return wf diff --git a/tests/amor/pipeline_test.py b/tests/amor/pipeline_test.py index 24fd5bfc..6961b0ef 100644 --- a/tests/amor/pipeline_test.py +++ b/tests/amor/pipeline_test.py @@ -7,6 +7,7 @@ import sciline import scipp as sc from orsopy import fileio +from scipp.testing import assert_allclose from ess import amor from ess.amor import data # noqa: F401 @@ -23,6 +24,7 @@ YIndexLimits, ZIndexLimits, ) +from ess.reflectometry.workflow import with_filenames @pytest.fixture @@ -34,6 +36,9 @@ def amor_pipeline() -> sciline.Pipeline: pl[WavelengthBins] = sc.geomspace("wavelength", 2.8, 12, 300, unit="angstrom") pl[YIndexLimits] = sc.scalar(11, unit=None), sc.scalar(41, unit=None) pl[ZIndexLimits] = sc.scalar(80, unit=None), sc.scalar(370, unit=None) + pl[QBins] = sc.geomspace( + dim="Q", start=0.005, stop=0.115, num=391, unit="1/angstrom" + ) # The sample rotation value in the file is slightly off, so we set it manually pl[SampleRotation[ReferenceRun]] = sc.scalar(0.65, unit="deg") @@ -46,19 +51,15 @@ def amor_pipeline() -> sciline.Pipeline: contact="max.mustermann@ess.eu", ) ) - - # The sample rotation value in the file is slightly off, so we set it manually - pl[SampleRotation[SampleRun]] = sc.scalar(0.85, unit="deg") - pl[Filename[SampleRun]] = amor.data.amor_sample_run(608) - pl[QBins] = sc.geomspace( - dim="Q", start=0.005, stop=0.115, num=391, unit="1/angstrom" - ) return pl @pytest.mark.filterwarnings("ignore:Failed to convert .* into a transformation") @pytest.mark.filterwarnings("ignore:Invalid transformation, missing attribute") def test_run_data_pipeline(amor_pipeline: sciline.Pipeline): + # The sample rotation value in the file is slightly off, so we set it manually + amor_pipeline[SampleRotation[SampleRun]] = sc.scalar(0.85, unit="deg") + amor_pipeline[Filename[SampleRun]] = amor.data.amor_sample_run(608) res = amor_pipeline.compute(ReflectivityOverQ) assert "Q" in res.coords assert "Q_resolution" in res.coords @@ -67,6 +68,8 @@ def test_run_data_pipeline(amor_pipeline: sciline.Pipeline): @pytest.mark.filterwarnings("ignore:Failed to convert .* into a transformation") @pytest.mark.filterwarnings("ignore:Invalid transformation, missing attribute") def test_run_full_pipeline(amor_pipeline: sciline.Pipeline): + amor_pipeline[SampleRotation[SampleRun]] = sc.scalar(0.85, unit="deg") + amor_pipeline[Filename[SampleRun]] = amor.data.amor_sample_run(608) res = amor_pipeline.compute(orso.OrsoIofQDataset) assert res.info.data_source.experiment.instrument == "Amor" assert res.info.reduction.software.name == "ess.reflectometry" @@ -75,7 +78,53 @@ def test_run_full_pipeline(amor_pipeline: sciline.Pipeline): assert np.all(res.data[:, 1] >= 0) +@pytest.mark.filterwarnings("ignore:Failed to convert .* into a transformation") +@pytest.mark.filterwarnings("ignore:Invalid transformation, missing attribute") +def test_pipeline_can_compute_reflectivity_merging_events_from_multiple_runs( + amor_pipeline: sciline.Pipeline, +): + sample_runs = [ + amor.data.amor_sample_run(608), + amor.data.amor_sample_run(609), + ] + pipeline = with_filenames(amor_pipeline, SampleRun, sample_runs) + pipeline[SampleRotation[SampleRun]] = pipeline.compute( + SampleRotation[SampleRun] + ) + sc.scalar(0.05, unit="deg") + result = pipeline.compute(ReflectivityOverQ) + assert result.dims == ('Q',) + + +@pytest.mark.filterwarnings("ignore:Failed to convert .* into a transformation") +@pytest.mark.filterwarnings("ignore:Invalid transformation, missing attribute") +def test_pipeline_merging_events_result_unchanged(amor_pipeline: sciline.Pipeline): + sample_runs = [ + amor.data.amor_sample_run(608), + ] + pipeline = with_filenames(amor_pipeline, SampleRun, sample_runs) + pipeline[SampleRotation[SampleRun]] = pipeline.compute( + SampleRotation[SampleRun] + ) + sc.scalar(0.05, unit="deg") + result = pipeline.compute(ReflectivityOverQ).hist() + sample_runs = [ + amor.data.amor_sample_run(608), + amor.data.amor_sample_run(608), + ] + pipeline = with_filenames(amor_pipeline, SampleRun, sample_runs) + pipeline[SampleRotation[SampleRun]] = pipeline.compute( + SampleRotation[SampleRun] + ) + sc.scalar(0.05, unit="deg") + result2 = pipeline.compute(ReflectivityOverQ).hist() + assert_allclose( + 2 * sc.values(result.data), sc.values(result2.data), rtol=sc.scalar(1e-6) + ) + assert_allclose( + 2 * sc.variances(result.data), sc.variances(result2.data), rtol=sc.scalar(1e-6) + ) + + def test_find_corrections(amor_pipeline: sciline.Pipeline): + amor_pipeline[Filename[SampleRun]] = amor.data.amor_sample_run(608) graph = amor_pipeline.get(orso.OrsoIofQDataset) # In topological order assert orso.find_corrections(graph) == [