Skip to content

Commit e191524

Browse files
authored
Merge pull request #160 from scipp/sample-rotation-offset
Sample rotation offset
2 parents f0a93b2 + d923bbd commit e191524

File tree

10 files changed

+66
-17
lines changed

10 files changed

+66
-17
lines changed

docs/user-guide/amor/amor-reduction.ipynb

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
"source": [
101101
"workflow[Filename[ReferenceRun]] = amor.data.amor_run(614)\n",
102102
"# The sample rotation value in the file is slightly off, so we set it manually\n",
103-
"workflow[SampleRotation[ReferenceRun]] = sc.scalar(0.65, unit='deg')\n",
103+
"workflow[SampleRotationOffset[ReferenceRun]] = sc.scalar(0.05, unit='deg')\n",
104104
"\n",
105105
"reference_result = workflow.compute(ReducedReference)\n",
106106
"# Set the result back onto the pipeline to cache it\n",
@@ -167,29 +167,30 @@
167167
" '608': {\n",
168168
" # The sample rotation values in the files are slightly off, so we replace\n",
169169
" # them with corrected values.\n",
170-
" SampleRotation[SampleRun]: sc.scalar(0.85, unit='deg'),\n",
170+
" SampleRotationOffset[SampleRun]: sc.scalar(0.05, unit='deg'),\n",
171171
" Filename[SampleRun]: amor.data.amor_run(608),\n",
172172
" },\n",
173173
" '609': {\n",
174-
" SampleRotation[SampleRun]: sc.scalar(2.25, unit='deg'),\n",
174+
" SampleRotationOffset[SampleRun]: sc.scalar(0.05, unit='deg'),\n",
175175
" Filename[SampleRun]: amor.data.amor_run(609),\n",
176176
" },\n",
177177
" '610': {\n",
178-
" SampleRotation[SampleRun]: sc.scalar(3.65, unit='deg'),\n",
178+
" SampleRotationOffset[SampleRun]: sc.scalar(0.05, unit='deg'),\n",
179179
" Filename[SampleRun]: amor.data.amor_run(610),\n",
180180
" },\n",
181181
" '611': {\n",
182-
" SampleRotation[SampleRun]: sc.scalar(5.05, unit='deg'),\n",
182+
" SampleRotationOffset[SampleRun]: sc.scalar(0.05, unit='deg'),\n",
183183
" Filename[SampleRun]: amor.data.amor_run(611),\n",
184184
" },\n",
185185
"}\n",
186186
"\n",
187187
"\n",
188188
"reflectivity = {}\n",
189189
"for run_number, params in runs.items():\n",
190-
" workflow[Filename[SampleRun]] = params[Filename[SampleRun]]\n",
191-
" workflow[SampleRotation[SampleRun]] = params[SampleRotation[SampleRun]]\n",
192-
" reflectivity[run_number] = workflow.compute(ReflectivityOverQ).hist()\n",
190+
" wf = workflow.copy()\n",
191+
" for key, value in params.items():\n",
192+
" wf[key] = value\n",
193+
" reflectivity[run_number] = wf.compute(ReflectivityOverQ).hist()\n",
193194
"\n",
194195
"sc.plot(reflectivity, norm='log', vmin=1e-4)"
195196
]
@@ -267,9 +268,10 @@
267268
"# Start by computing the `ReflectivityData` for each of the files\n",
268269
"diagnostics = {}\n",
269270
"for run_number, params in runs.items():\n",
270-
" workflow[Filename[SampleRun]] = params[Filename[SampleRun]]\n",
271-
" workflow[SampleRotation[SampleRun]] = params[SampleRotation[SampleRun]]\n",
272-
" diagnostics[run_number] = workflow.compute((ReflectivityOverZW, ThetaBins[SampleRun]))\n",
271+
" wf = workflow.copy()\n",
272+
" for key, value in params.items():\n",
273+
" wf[key] = value\n",
274+
" diagnostics[run_number] = wf.compute((ReflectivityOverZW, ThetaBins[SampleRun]))\n",
273275
"\n",
274276
"# Scale the results using the scale factors computed earlier\n",
275277
"for run_number, scale_factor in zip(reflectivity.keys(), scale_factors, strict=True):\n",
@@ -358,7 +360,7 @@
358360
"from ess.reflectometry.figures import wavelength_z_figure\n",
359361
"\n",
360362
"workflow[Filename[SampleRun]] = runs['608'][Filename[SampleRun]]\n",
361-
"workflow[SampleRotation[SampleRun]] = runs['608'][SampleRotation[SampleRun]]\n",
363+
"workflow[SampleRotationOffset[SampleRun]] = runs['608'][SampleRotationOffset[SampleRun]]\n",
362364
"wavelength_z_figure(\n",
363365
" workflow.compute(Sample),\n",
364366
" wavelength_bins=workflow.compute(WavelengthBins),\n",

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
"# Chopper phase value in the file is wrong, so we set it manually\n",
9797
"workflow[ChopperPhase[ReferenceRun]] = sc.scalar(-7.5, unit='deg')\n",
9898
"# The sample rotation value in the file is slightly off, so we set it manually\n",
99-
"workflow[SampleRotation[ReferenceRun]] = sc.scalar(0.65, unit='deg')\n",
99+
"workflow[SampleRotationOffset[ReferenceRun]] = sc.scalar(0.05, unit='deg')\n",
100100
"workflow[Filename[ReferenceRun]] = amor.data.amor_run(614)\n",
101101
"\n",
102102
"reference_result = workflow.compute(ReducedReference)\n",
@@ -123,9 +123,9 @@
123123
"results = sc.DataGroup({'ess': sc.DataGroup(), 'psi': sc.DataGroup()})\n",
124124
"\n",
125125
"# ESS results\n",
126-
"for key, angle in mu.items():\n",
126+
"for key in mu:\n",
127127
" print(key, '... ', end='')\n",
128-
" workflow[SampleRotation[SampleRun]] = sc.scalar(angle + 0.05, unit='deg')\n",
128+
" workflow[SampleRotationOffset[SampleRun]] = sc.scalar(0.05, unit='deg')\n",
129129
" workflow[Filename[SampleRun]] = amor.data.amor_run(key)\n",
130130
" da = workflow.compute(ReflectivityOverQ).hist()\n",
131131
" da.coords['Q'] = sc.midpoints(da.coords['Q'], dim='Q')\n",

src/ess/amor/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
NeXusDetectorName,
1515
RunType,
1616
SamplePosition,
17+
SampleRotationOffset,
1718
)
1819
from . import (
1920
conversions,
@@ -71,6 +72,7 @@ def default_parameters() -> dict:
7172
sc.scalar(0.75, unit='deg'),
7273
),
7374
GravityToggle: True,
75+
SampleRotationOffset[RunType]: sc.scalar(0.0, unit='deg'),
7476
}
7577

7678

src/ess/amor/load.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
NeXusDetectorName,
1212
ProtonCurrent,
1313
RawDetectorData,
14+
RawSampleRotation,
1415
RunType,
1516
SampleRotation,
1617
SampleSize,
@@ -100,7 +101,7 @@ def load_amor_ch_frequency(ch: RawChopper[RunType]) -> ChopperFrequency[RunType]
100101
raise ValueError("No unit was found for the chopper frequency")
101102

102103

103-
def load_amor_sample_rotation(fp: Filename[RunType]) -> SampleRotation[RunType]:
104+
def load_amor_sample_rotation(fp: Filename[RunType]) -> RawSampleRotation[RunType]:
104105
(mu,) = load_nx(fp, "NXentry/NXinstrument/master_parameters/mu")
105106
# Jochens Amor code reads the first value of this log
106107
# see https://github.com/jochenstahn/amor/blob/140e3192ddb7e7f28acee87e2acaee65ce1332aa/libeos/file_reader.py#L272 # noqa: E501

src/ess/estia/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
NeXusDetectorName,
1515
RunType,
1616
SamplePosition,
17+
SampleRotationOffset,
1718
)
1819
from . import conversions, load, maskings, normalization, orso, resolution, workflow
1920
from .types import (
@@ -57,6 +58,7 @@ def default_parameters() -> dict:
5758
sc.scalar(-0.75, unit='deg'),
5859
sc.scalar(0.75, unit='deg'),
5960
),
61+
SampleRotationOffset[RunType]: sc.scalar(0.0, unit='deg'),
6062
}
6163

6264

src/ess/estia/load.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
Filename,
77
RawDetectorData,
88
RunType,
9+
SampleRotationOffset,
910
)
1011
from .mcstas import parse_events_ascii, parse_events_h5
1112

1213

1314
def load_mcstas_events(
1415
filename: Filename[RunType],
16+
sample_rotation_offset: SampleRotationOffset[RunType],
1517
) -> RawDetectorData[RunType]:
1618
"""
1719
Load event data from a McStas run and reshape it
@@ -31,6 +33,9 @@ def load_mcstas_events(
3133
da.coords['detector_rotation'] = 2 * da.coords['sample_rotation'] + sc.scalar(
3234
1.65, unit='deg'
3335
)
36+
da.coords['sample_rotation'] += sample_rotation_offset.to(
37+
unit=da.coords['sample_rotation'].unit
38+
)
3439

3540
xbins = sc.linspace('x', -0.25, 0.25, 14 * 32 + 1)
3641
ybins = sc.linspace('y', -0.25, 0.25, 65)

src/ess/reflectometry/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
__version__ = "0.0.0"
1111

1212

13-
from . import conversions, figures, normalization, orso
13+
from . import conversions, corrections, figures, normalization, orso
1414
from .load import load_reference, save_reference
1515

1616
providers = (
17+
*corrections.providers,
1718
*conversions.providers,
1819
*orso.providers,
1920
*normalization.providers,

src/ess/reflectometry/corrections.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import scipp as sc
33

44
from .tools import fwhm_to_std
5+
from .types import RawSampleRotation, RunType, SampleRotation, SampleRotationOffset
56

67

78
def footprint_on_sample(
@@ -45,3 +46,12 @@ def correct_by_footprint(da: sc.DataArray) -> sc.DataArray:
4546
def correct_by_proton_current(da: sc.DataArray) -> sc.DataArray:
4647
"Corrects the data by the proton current during the time of data collection"
4748
return da / da.bins.coords['proton_current']
49+
50+
51+
def correct_sample_rotation(
52+
mu: RawSampleRotation[RunType], mu_offset: SampleRotationOffset[RunType]
53+
) -> SampleRotation[RunType]:
54+
return mu + mu_offset.to(unit=mu.unit)
55+
56+
57+
providers = (correct_sample_rotation,)

src/ess/reflectometry/types.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,19 @@ class Filename(sciline.Scope[RunType, str], str):
7979
"""Filename of an event data nexus file."""
8080

8181

82+
class RawSampleRotation(sciline.Scope[RunType, sc.Variable], sc.Variable):
83+
"""The rotation of the sample registered in the NeXus file."""
84+
85+
8286
class SampleRotation(sciline.Scope[RunType, sc.Variable], sc.Variable):
8387
"""The rotation of the sample relative to the center of the incoming beam."""
8488

8589

90+
class SampleRotationOffset(sciline.Scope[RunType, sc.Variable], sc.Variable):
91+
"""The difference between the true slope of the sample surface
92+
and the sample rotation value in the file."""
93+
94+
8695
class DetectorRotation(sciline.Scope[RunType, sc.Variable], sc.Variable):
8796
"""The rotation of the detector relative to the horizon"""
8897

tests/amor/pipeline_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
Filename,
1818
ProtonCurrent,
1919
QBins,
20+
RawSampleRotation,
2021
ReducibleData,
2122
ReferenceRun,
2223
ReflectivityOverQ,
2324
SampleRotation,
25+
SampleRotationOffset,
2426
SampleRun,
2527
SampleSize,
2628
WavelengthBins,
@@ -226,3 +228,18 @@ def test_proton_current(amor_pipeline: sciline.Pipeline):
226228
np.testing.assert_allclose(
227229
proton_current[np.searchsorted(timestamps, t) - 1], w_without / w_with
228230
)
231+
232+
233+
@pytest.mark.filterwarnings("ignore:Failed to convert .* into a transformation")
234+
@pytest.mark.filterwarnings("ignore:Invalid transformation, missing attribute")
235+
def test_sample_rotation_offset(amor_pipeline: sciline.Pipeline):
236+
amor_pipeline[Filename[SampleRun]] = amor.data.amor_run(608)
237+
amor_pipeline[SampleRotationOffset[SampleRun]] = sc.scalar(1.0, unit='deg')
238+
mu, muoffset, muraw = amor_pipeline.compute(
239+
(
240+
SampleRotation[SampleRun],
241+
SampleRotationOffset[SampleRun],
242+
RawSampleRotation[SampleRun],
243+
)
244+
).values()
245+
assert mu == muoffset.to(unit=muraw.unit) + muraw

0 commit comments

Comments
 (0)