Skip to content

Commit 449ed90

Browse files
authored
Merge pull request #51 from scipp/amor-guidelines
Apply workflow guidelines to Amor
2 parents dee4263 + 8163b42 commit 449ed90

File tree

19 files changed

+356
-294
lines changed

19 files changed

+356
-294
lines changed

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ See the [Amor data reduction](examples/amor) example for a quick start.
1717
maxdepth: 2
1818
---
1919
20-
examples/index
20+
user-guide/index
2121
api-reference/index
2222
developer/index
2323
about/index

docs/examples/amor.ipynb renamed to docs/user-guide/amor/amor-reduction.ipynb

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,34 +31,52 @@
3131
"from ess.amor.types import *"
3232
]
3333
},
34+
{
35+
"cell_type": "markdown",
36+
"metadata": {},
37+
"source": [
38+
"## Create and configure the workflow\n",
39+
"\n",
40+
"We begin by creating the Amor workflow object which is a skeleton for reducing Amor data,\n",
41+
"with pre-configured steps."
42+
]
43+
},
3444
{
3545
"cell_type": "code",
3646
"execution_count": null,
3747
"metadata": {},
3848
"outputs": [],
3949
"source": [
40-
"pl = sciline.Pipeline(\n",
41-
" (\n",
42-
" *amor.providers,\n",
43-
" *amor.data.providers,\n",
44-
" ),\n",
45-
" params=amor.default_parameters,\n",
46-
")\n",
47-
"\n",
48-
"pl[SampleSize[Sample]] = sc.scalar(10.0, unit='mm')\n",
49-
"pl[SampleSize[Reference]] = sc.scalar(10.0, unit='mm')\n",
50+
"workflow = amor.AmorWorkflow()"
51+
]
52+
},
53+
{
54+
"cell_type": "markdown",
55+
"metadata": {},
56+
"source": [
57+
"We then need to set the missing parameters which are specific to each experiment:"
58+
]
59+
},
60+
{
61+
"cell_type": "code",
62+
"execution_count": null,
63+
"metadata": {},
64+
"outputs": [],
65+
"source": [
66+
"workflow[SampleSize[SampleRun]] = sc.scalar(10.0, unit='mm')\n",
67+
"workflow[SampleSize[ReferenceRun]] = sc.scalar(10.0, unit='mm')\n",
5068
"\n",
51-
"pl[ChopperPhase[Reference]] = sc.scalar(-7.5, unit='deg')\n",
52-
"pl[ChopperPhase[Sample]] = sc.scalar(-7.5, unit='deg')\n",
69+
"workflow[ChopperPhase[ReferenceRun]] = sc.scalar(-7.5, unit='deg')\n",
70+
"workflow[ChopperPhase[SampleRun]] = sc.scalar(-7.5, unit='deg')\n",
5371
"\n",
54-
"pl[QBins] = sc.geomspace(dim='Q', start=0.005, stop=0.3, num=391, unit='1/angstrom')\n",
55-
"pl[WavelengthBins] = sc.geomspace('wavelength', 2.8, 12, 301, unit='angstrom')\n",
72+
"workflow[QBins] = sc.geomspace(dim='Q', start=0.005, stop=0.3, num=391, unit='1/angstrom')\n",
73+
"workflow[WavelengthBins] = sc.geomspace('wavelength', 2.8, 12, 301, unit='angstrom')\n",
5674
"\n",
5775
"# The YIndexLimits and ZIndexLimits define ranges on the detector where\n",
5876
"# data is considered to be valid signal.\n",
5977
"# They represent the lower and upper boundaries of a range of pixel indices.\n",
60-
"pl[YIndexLimits] = sc.scalar(11, unit=None), sc.scalar(41, unit=None)\n",
61-
"pl[ZIndexLimits] = sc.scalar(80, unit=None), sc.scalar(370, unit=None)"
78+
"workflow[YIndexLimits] = sc.scalar(11, unit=None), sc.scalar(41, unit=None)\n",
79+
"workflow[ZIndexLimits] = sc.scalar(80, unit=None), sc.scalar(370, unit=None)"
6280
]
6381
},
6482
{
@@ -67,7 +85,7 @@
6785
"metadata": {},
6886
"outputs": [],
6987
"source": [
70-
"pl.visualize(NormalizedIofQ, graph_attr={'rankdir': 'LR'})"
88+
"workflow.visualize(NormalizedIofQ, graph_attr={'rankdir': 'LR'})"
7189
]
7290
},
7391
{
@@ -88,13 +106,13 @@
88106
"metadata": {},
89107
"outputs": [],
90108
"source": [
91-
"pl[TutorialFilename[Reference]] = \"amor2023n000614.hdf\"\n",
109+
"workflow[Filename[ReferenceRun]] = amor.data.amor_reference_run()\n",
92110
"# The sample rotation value in the file is slightly off, so we set it manually\n",
93-
"pl[SampleRotation[Reference]] = sc.scalar(0.65, unit='deg')\n",
111+
"workflow[SampleRotation[ReferenceRun]] = sc.scalar(0.65, unit='deg')\n",
94112
"\n",
95-
"reference_result = pl.compute(IdealReferenceIntensity)\n",
113+
"reference_result = workflow.compute(IdealReferenceIntensity)\n",
96114
"# Set the result back onto the pipeline to cache it\n",
97-
"pl[IdealReferenceIntensity] = reference_result"
115+
"workflow[IdealReferenceIntensity] = reference_result"
98116
]
99117
},
100118
{
@@ -110,7 +128,7 @@
110128
"metadata": {},
111129
"outputs": [],
112130
"source": [
113-
"pl.visualize(NormalizedIofQ, graph_attr={'rankdir': 'LR'})"
131+
"workflow.visualize(NormalizedIofQ, graph_attr={'rankdir': 'LR'})"
114132
]
115133
},
116134
{
@@ -129,17 +147,17 @@
129147
"metadata": {},
130148
"outputs": [],
131149
"source": [
132-
"pl[TutorialFilename[Sample]] = \"amor2023n000608.hdf\"\n",
133-
"pl[SampleRotation[Sample]] = sc.scalar(0.85, unit='deg')\n",
134-
"ioq8 = pl.compute(NormalizedIofQ).hist()\n",
150+
"workflow[Filename[SampleRun]] = amor.data.amor_sample_run(608)\n",
151+
"workflow[SampleRotation[SampleRun]] = sc.scalar(0.85, unit='deg')\n",
152+
"ioq8 = workflow.compute(NormalizedIofQ).hist()\n",
135153
"\n",
136-
"pl[TutorialFilename[Sample]] = \"amor2023n000609.hdf\"\n",
137-
"pl[SampleRotation[Sample]] = sc.scalar(2.25, unit='deg')\n",
138-
"ioq9 = pl.compute(NormalizedIofQ).hist()\n",
154+
"workflow[Filename[SampleRun]] = amor.data.amor_sample_run(609)\n",
155+
"workflow[SampleRotation[SampleRun]] = sc.scalar(2.25, unit='deg')\n",
156+
"ioq9 = workflow.compute(NormalizedIofQ).hist()\n",
139157
"\n",
140-
"pl[TutorialFilename[Sample]] = \"amor2023n000610.hdf\"\n",
141-
"pl[SampleRotation[Sample]] = sc.scalar(3.65, unit='deg')\n",
142-
"ioq10 = pl.compute(NormalizedIofQ).hist()\n",
158+
"workflow[Filename[SampleRun]] = amor.data.amor_sample_run(610)\n",
159+
"workflow[SampleRotation[SampleRun]] = sc.scalar(3.65, unit='deg')\n",
160+
"ioq10 = workflow.compute(NormalizedIofQ).hist()\n",
143161
"\n",
144162
"sc.plot({'608': ioq8, '609': ioq9, '610': ioq10}, norm='log', vmin=1e-4)"
145163
]
@@ -157,9 +175,9 @@
157175
"metadata": {},
158176
"outputs": [],
159177
"source": [
160-
"pl[TutorialFilename[Sample]] = \"amor2023n000608.hdf\"\n",
161-
"pl[SampleRotation[Sample]] = sc.scalar(0.85, unit='deg')\n",
162-
"pl.compute(ReflectivityDiagnosticsView)"
178+
"workflow[Filename[SampleRun]] = amor.data.amor_sample_run(608)\n",
179+
"workflow[SampleRotation[SampleRun]] = sc.scalar(0.85, unit='deg')\n",
180+
"workflow.compute(ReflectivityDiagnosticsView)"
163181
]
164182
},
165183
{
@@ -176,7 +194,7 @@
176194
"metadata": {},
177195
"outputs": [],
178196
"source": [
179-
"pl.compute(WavelengthThetaFigure)"
197+
"workflow.compute(WavelengthThetaFigure)"
180198
]
181199
},
182200
{
@@ -215,7 +233,7 @@
215233
"metadata": {},
216234
"outputs": [],
217235
"source": [
218-
"pl[orso.OrsoCreator] = orso.OrsoCreator(\n",
236+
"workflow[orso.OrsoCreator] = orso.OrsoCreator(\n",
219237
" fileio.base.Person(\n",
220238
" name='Max Mustermann',\n",
221239
" affiliation='European Spallation Source ERIC',\n",
@@ -230,7 +248,7 @@
230248
"metadata": {},
231249
"outputs": [],
232250
"source": [
233-
"pl.visualize(orso.OrsoIofQDataset, graph_attr={'rankdir': 'LR'})"
251+
"workflow.visualize(orso.OrsoIofQDataset, graph_attr={'rankdir': 'LR'})"
234252
]
235253
},
236254
{
@@ -246,7 +264,7 @@
246264
"metadata": {},
247265
"outputs": [],
248266
"source": [
249-
"iofq_dataset = pl.compute(orso.OrsoIofQDataset)\n",
267+
"iofq_dataset = workflow.compute(orso.OrsoIofQDataset)\n",
250268
"iofq_dataset"
251269
]
252270
},
@@ -282,7 +300,7 @@
282300
"outputs": [],
283301
"source": [
284302
"iofq_dataset.info.reduction.corrections = orso.find_corrections(\n",
285-
" pl.get(orso.OrsoIofQDataset)\n",
303+
" workflow.get(orso.OrsoIofQDataset)\n",
286304
")"
287305
]
288306
},

docs/examples/compare-to-eos.ipynb renamed to docs/user-guide/amor/compare-to-eos.ipynb

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
{
22
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "b97647a4-29ab-45a3-870e-aa49fbddb0c5",
6+
"metadata": {},
7+
"source": [
8+
"# Comparison with PSI reduction software\n",
9+
"\n",
10+
"This notebook is for validating the results from the `essreflectometry` packages by comparing them\n",
11+
"to the ones obtained by the PSI software at the Amor beamline."
12+
]
13+
},
314
{
415
"cell_type": "code",
516
"execution_count": null,
@@ -62,34 +73,31 @@
6273
"metadata": {},
6374
"outputs": [],
6475
"source": [
65-
"pl = sciline.Pipeline(\n",
66-
" (*amor.providers, *amor.data.providers),\n",
67-
" params=amor.default_parameters,\n",
68-
")\n",
76+
"workflow = amor.AmorWorkflow()\n",
6977
"\n",
70-
"pl[SampleSize[Sample]] = sc.scalar(10.0, unit='mm')\n",
71-
"pl[SampleSize[Reference]] = sc.scalar(10.0, unit='mm')\n",
72-
"pl[ChopperPhase[Sample]] = sc.scalar(-7.5, unit='deg')\n",
78+
"workflow[SampleSize[SampleRun]] = sc.scalar(10.0, unit='mm')\n",
79+
"workflow[SampleSize[ReferenceRun]] = sc.scalar(10.0, unit='mm')\n",
80+
"workflow[ChopperPhase[SampleRun]] = sc.scalar(-7.5, unit='deg')\n",
7381
"\n",
7482
"# In Jochens workflow:\n",
7583
"# * divergence mask: [-0.7, 0.7]\n",
7684
"# * note, divergence relative to beam center\n",
77-
"pl[WavelengthBins] = sc.geomspace('wavelength', 2.8, 12.5, 300, unit='angstrom')\n",
78-
"pl[QBins] = sc.geomspace(\n",
85+
"workflow[WavelengthBins] = sc.geomspace('wavelength', 2.8, 12.5, 301, unit='angstrom')\n",
86+
"workflow[QBins] = sc.geomspace(\n",
7987
" dim='Q', start=0.00505, stop=2.93164766e-01, num=391, unit='1/angstrom'\n",
8088
")\n",
81-
"pl[YIndexLimits] = sc.scalar(11, unit=None), sc.scalar(41, unit=None)\n",
82-
"pl[ZIndexLimits] = sc.scalar(80, unit=None), sc.scalar(370, unit=None)\n",
89+
"workflow[YIndexLimits] = sc.scalar(11, unit=None), sc.scalar(41, unit=None)\n",
90+
"workflow[ZIndexLimits] = sc.scalar(80, unit=None), sc.scalar(370, unit=None)\n",
8391
"\n",
8492
"# Chopper phase value in the file is wrong, so we set it manually\n",
85-
"pl[ChopperPhase[Reference]] = sc.scalar(-7.5, unit='deg')\n",
93+
"workflow[ChopperPhase[ReferenceRun]] = sc.scalar(-7.5, unit='deg')\n",
8694
"# The sample rotation value in the file is slightly off, so we set it manually\n",
87-
"pl[SampleRotation[Reference]] = sc.scalar(0.65, unit='deg')\n",
88-
"pl[TutorialFilename[Reference]] = \"amor2023n000614.hdf\"\n",
95+
"workflow[SampleRotation[ReferenceRun]] = sc.scalar(0.65, unit='deg')\n",
96+
"workflow[Filename[ReferenceRun]] = amor.data.amor_reference_run()\n",
8997
"\n",
90-
"reference_result = pl.compute(IdealReferenceIntensity)\n",
98+
"reference_result = workflow.compute(IdealReferenceIntensity)\n",
9199
"# Set the result back onto the pipeline to cache it\n",
92-
"pl[IdealReferenceIntensity] = reference_result"
100+
"workflow[IdealReferenceIntensity] = reference_result"
93101
]
94102
},
95103
{
@@ -113,9 +121,9 @@
113121
"# ESS results\n",
114122
"for key, angle in mu.items():\n",
115123
" print(key, '... ', end='')\n",
116-
" pl[SampleRotation[Sample]] = sc.scalar(angle + 0.05, unit='deg')\n",
117-
" pl[TutorialFilename[Sample]] = f\"amor2023n000{key}.hdf\"\n",
118-
" da = pl.compute(NormalizedIofQ).hist()\n",
124+
" workflow[SampleRotation[SampleRun]] = sc.scalar(angle + 0.05, unit='deg')\n",
125+
" workflow[Filename[SampleRun]] = amor.data.amor_sample_run(key)\n",
126+
" da = workflow.compute(NormalizedIofQ).hist()\n",
119127
" da.coords['Q'] = sc.midpoints(da.coords['Q'], dim='Q')\n",
120128
" results['ess'][key] = da\n",
121129
" print('Done!')"
@@ -130,7 +138,7 @@
130138
"source": [
131139
"# PSI results\n",
132140
"for key, angle in mu.items():\n",
133-
" d = orsopy.fileio.load_orso(amor.data.get_path(f'{key}.Rqz.ort'))[0].data\n",
141+
" d = orsopy.fileio.load_orso(amor.data.amor_psi_software_result(key))[0].data\n",
134142
" y = sc.array(dims=['Q'], values=d[:, 1], variances=d[:, 2] ** 2)\n",
135143
" results['psi'][key] = sc.DataArray(\n",
136144
" data=y, coords={'Q': sc.array(dims=['Q'], values=d[:, 0], unit='1/angstrom')}\n",
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
# Examples
1+
# Amor
22

33
```{toctree}
44
---
5-
maxdepth: 2
5+
maxdepth: 1
66
---
7-
8-
amor
7+
amor-reduction
98
compare-to-eos
109
```
11-

docs/user-guide/index.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# User guide
2+
3+
```{toctree}
4+
---
5+
maxdepth: 1
6+
---
7+
amor/index
8+
```
9+

src/ess/amor/__init__.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
33
import importlib.metadata
44

5+
import sciline
56
import scipp as sc
67

78
from ..reflectometry import providers as reflectometry_providers
@@ -11,7 +12,7 @@
1112
DetectorSpatialResolution,
1213
Gravity,
1314
NeXusDetectorName,
14-
Run,
15+
RunType,
1516
SamplePosition,
1617
)
1718
from . import conversions, data, load, orso, resolution, utils
@@ -50,20 +51,28 @@
5051
This provides a default Amor workflow including providers for loadings files.
5152
"""
5253

53-
default_parameters = {
54-
supermirror.MValue: sc.scalar(5, unit=sc.units.dimensionless),
55-
supermirror.CriticalEdge: 0.022 * sc.Unit("1/angstrom"),
56-
supermirror.Alpha: sc.scalar(0.25 / 0.088, unit=sc.units.angstrom),
57-
BeamSize[Run]: 2.0 * sc.units.mm,
58-
DetectorSpatialResolution[Run]: 0.0025 * sc.units.m,
59-
Gravity: sc.vector(value=[0, -1, 0]) * sc.constants.g,
60-
SamplePosition[Run]: sc.vector([0, 0, 0], unit="m"),
61-
NeXusDetectorName[Run]: "detector",
62-
ChopperPhase[Run]: sc.scalar(-5.0, unit="deg"),
63-
ChopperFrequency[Run]: sc.scalar(8.333, unit="Hz"),
64-
}
6554

66-
del sc
55+
def default_parameters() -> dict:
56+
return {
57+
supermirror.MValue: sc.scalar(5, unit=sc.units.dimensionless),
58+
supermirror.CriticalEdge: 0.022 * sc.Unit("1/angstrom"),
59+
supermirror.Alpha: sc.scalar(0.25 / 0.088, unit=sc.units.angstrom),
60+
BeamSize[RunType]: 2.0 * sc.units.mm,
61+
DetectorSpatialResolution[RunType]: 0.0025 * sc.units.m,
62+
Gravity: sc.vector(value=[0, -1, 0]) * sc.constants.g,
63+
SamplePosition[RunType]: sc.vector([0, 0, 0], unit="m"),
64+
NeXusDetectorName[RunType]: "detector",
65+
ChopperPhase[RunType]: sc.scalar(-5.0, unit="deg"),
66+
ChopperFrequency[RunType]: sc.scalar(8.333, unit="Hz"),
67+
}
68+
69+
70+
def AmorWorkflow() -> sciline.Pipeline:
71+
"""
72+
Workflow with default parameters for the Amor PSI instrument.
73+
"""
74+
return sciline.Pipeline(providers=providers, params=default_parameters())
75+
6776

6877
__all__ = [
6978
"supermirror",
@@ -88,4 +97,5 @@
8897
"WavelengthZIndexFigure",
8998
"QThetaFigure",
9099
"ReflectivityDiagnosticsView",
100+
"AmorWorkflow",
91101
]

src/ess/amor/conversions.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
33
import scipp as sc
44

5-
from ..reflectometry.types import IncidentBeam, Run, SamplePosition
5+
from ..reflectometry.types import IncidentBeam, RunType, SamplePosition
66
from .types import Chopper1Position, Chopper2Position
77

88

99
def incident_beam(
10-
source_chopper_1_position: Chopper1Position[Run],
11-
source_chopper_2_position: Chopper2Position[Run],
12-
sample_position: SamplePosition[Run],
13-
) -> IncidentBeam[Run]:
10+
source_chopper_1_position: Chopper1Position[RunType],
11+
source_chopper_2_position: Chopper2Position[RunType],
12+
sample_position: SamplePosition[RunType],
13+
) -> IncidentBeam[RunType]:
1414
"""
1515
Compute the incident beam vector from the source chopper position vector,
1616
instead of the source_position vector.

0 commit comments

Comments
 (0)