Skip to content

Commit 7fe8198

Browse files
authored
Merge pull request #170 from scipp/provider-for-qbins
Provider for qbins
2 parents 921532d + 9f43c3b commit 7fe8198

File tree

3 files changed

+93
-6
lines changed

3 files changed

+93
-6
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"metadata": {},
2525
"outputs": [],
2626
"source": [
27+
"%matplotlib widget\n",
2728
"import warnings\n",
2829
"import scipp as sc\n",
2930
"from ess import amor\n",
@@ -60,7 +61,6 @@
6061
"workflow[ChopperPhase[ReferenceRun]] = sc.scalar(-7.5, unit='deg')\n",
6162
"workflow[ChopperPhase[SampleRun]] = sc.scalar(-7.5, unit='deg')\n",
6263
"\n",
63-
"workflow[QBins] = sc.geomspace(dim='Q', start=0.005, stop=0.3, num=391, unit='1/angstrom')\n",
6464
"workflow[WavelengthBins] = sc.geomspace('wavelength', 2.8, 12.5, 2001, unit='angstrom')\n",
6565
"\n",
6666
"# The YIndexLimits and ZIndexLimits define ranges on the detector where\n",
@@ -235,7 +235,7 @@
235235
"outputs": [],
236236
"source": [
237237
"from ess.reflectometry.tools import combine_curves\n",
238-
"combined = combine_curves(scaled_reflectivity_curves, workflow.compute(QBins))\n",
238+
"combined = combine_curves(scaled_reflectivity_curves, sc.geomspace('Q', 0.005, 0.4, 499, unit='1/angstrom'))\n",
239239
"combined.plot(norm='log')"
240240
]
241241
},
@@ -336,7 +336,7 @@
336336
"q_theta_figure(\n",
337337
" [res[ReflectivityOverZW] for res in diagnostics.values()],\n",
338338
" theta_bins=[res[ThetaBins[SampleRun]] for res in diagnostics.values()],\n",
339-
" q_bins=workflow.compute(QBins)\n",
339+
" q_bins=sc.geomspace('Q', 0.005, 0.4, 499, unit='1/angstrom')\n",
340340
")"
341341
]
342342
},
@@ -527,7 +527,7 @@
527527
"name": "python",
528528
"nbconvert_exporter": "python",
529529
"pygments_lexer": "ipython3",
530-
"version": "3.10.14"
530+
"version": "3.10.18"
531531
}
532532
},
533533
"nbformat": 4,

src/ess/amor/utils.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
# Copyright (c) 2025 Scipp contributors (https://github.com/scipp)
22
import scipp as sc
33

4-
from ..reflectometry.types import DetectorRotation, RunType, SampleRotation, ThetaBins
4+
from ..reflectometry.conversions import reflectometry_q
5+
from ..reflectometry.types import (
6+
BeamDivergenceLimits,
7+
DetectorRotation,
8+
QBins,
9+
RunType,
10+
SampleRotation,
11+
SampleRun,
12+
ThetaBins,
13+
WavelengthBins,
14+
)
515
from .geometry import Detector
616

717

@@ -55,4 +65,33 @@ def theta_grid(
5565
return grid
5666

5767

58-
providers = (theta_grid,)
68+
def qgrid(
69+
detector_rotation: DetectorRotation[SampleRun],
70+
sample_rotation: SampleRotation[SampleRun],
71+
wbins: WavelengthBins,
72+
bdlims: BeamDivergenceLimits,
73+
) -> QBins:
74+
'''Generates a suitable Q-binnning from
75+
the limits on wavelength and divergence angle.
76+
77+
The binning is a geometric grid starting from
78+
the minimum achievable Q value or ``1e-3 A``, whichever is larger.
79+
'''
80+
theta_min = (
81+
bdlims[0].to(unit='rad', copy=False)
82+
+ detector_rotation.to(unit='rad', dtype='float64')
83+
- sample_rotation.to(unit='rad', dtype='float64')
84+
)
85+
theta_max = (
86+
bdlims[-1].to(unit='rad', copy=False)
87+
+ detector_rotation.to(unit='rad', dtype='float64')
88+
- sample_rotation.to(unit='rad', dtype='float64')
89+
)
90+
wmin, wmax = wbins[0], wbins[-1]
91+
qmin = reflectometry_q(wavelength=wmax, theta=theta_min)
92+
qmax = reflectometry_q(wavelength=wmin, theta=theta_max)
93+
qmin = max(qmin, sc.scalar(1e-3, unit='1/angstrom'))
94+
return QBins(sc.geomspace('Q', qmin, qmax, 501))
95+
96+
97+
providers = (theta_grid, qgrid)

tests/amor/utils_test.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
# Copyright (c) 2024 Scipp contributors (https://github.com/scipp)
3+
# flake8: noqa: F403, F405
4+
5+
import scipp as sc
6+
import scipp.constants
7+
import scipp.testing
8+
9+
from ess.amor.utils import qgrid
10+
11+
12+
def test_qgrid_provider():
13+
grid = qgrid(
14+
detector_rotation=sc.scalar(2, unit='deg'),
15+
sample_rotation=sc.scalar(0.9, unit='deg'),
16+
wbins=sc.linspace('wavelength', 3, 12, 10, unit='angstrom'),
17+
bdlims=(sc.scalar(-0.75, unit='deg'), sc.scalar(0.75, unit='deg')),
18+
)
19+
sc.testing.assert_allclose(
20+
grid[0],
21+
4
22+
* sc.constants.pi
23+
* sc.sin(
24+
sc.scalar(-0.75, unit='deg').to(unit='rad')
25+
+ sc.scalar(1.1, unit='deg').to(unit='rad')
26+
)
27+
/ sc.scalar(12, unit='angstrom'),
28+
)
29+
sc.testing.assert_allclose(
30+
grid[-1],
31+
4
32+
* sc.constants.pi
33+
* sc.sin(
34+
sc.scalar(0.75, unit='deg').to(unit='rad')
35+
+ sc.scalar(1.1, unit='deg').to(unit='rad')
36+
)
37+
/ sc.scalar(3, unit='angstrom'),
38+
)
39+
40+
41+
def test_qgrid_provider_minimum_q():
42+
grid = qgrid(
43+
detector_rotation=sc.scalar(1.2, unit='deg'),
44+
sample_rotation=sc.scalar(0.7, unit='deg'),
45+
wbins=sc.linspace('wavelength', 3, 12, 10, unit='angstrom'),
46+
bdlims=(sc.scalar(-0.75, unit='deg'), sc.scalar(0.75, unit='deg')),
47+
)
48+
sc.testing.assert_allclose(grid[0], sc.scalar(0.001, unit='1/angstrom'))

0 commit comments

Comments
 (0)