Skip to content

Commit 2706ec5

Browse files
authored
Merge pull request #108 from scipp/estia
Estia McStas workflow
2 parents 91be8ba + 413ed1a commit 2706ec5

38 files changed

+1404
-156
lines changed

docs/api-reference/index.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
types
3535
tools
3636
workflow
37+
figures
3738
```
3839

3940
## Amor
@@ -48,11 +49,33 @@
4849
4950
conversions
5051
data
51-
instrument_view
5252
load
5353
orso
5454
resolution
5555
types
5656
utils
57-
figures
57+
normalization
58+
workflow
59+
```
60+
61+
## Estia
62+
63+
```{eval-rst}
64+
.. currentmodule:: ess.estia
65+
66+
.. autosummary::
67+
:toctree: ../generated/modules
68+
:template: module-template.rst
69+
:recursive:
70+
71+
conversions
72+
maskings
73+
corrections
74+
data
75+
mcstas
76+
load
77+
resolution
78+
types
79+
normalization
80+
workflow
5881
```

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@
299299
"metadata": {},
300300
"outputs": [],
301301
"source": [
302-
"from ess.amor.figures import wavelength_theta_figure\n",
302+
"from ess.reflectometry.figures import wavelength_theta_figure\n",
303303
"\n",
304304
"wavelength_theta_figure(\n",
305305
" [result[ReflectivityOverZW] for result in diagnostics.values()],\n",
@@ -329,7 +329,7 @@
329329
"metadata": {},
330330
"outputs": [],
331331
"source": [
332-
"from ess.amor.figures import q_theta_figure\n",
332+
"from ess.reflectometry.figures import q_theta_figure\n",
333333
"\n",
334334
"q_theta_figure(\n",
335335
" [res[ReflectivityOverZW] for res in diagnostics.values()],\n",
@@ -355,7 +355,7 @@
355355
"metadata": {},
356356
"outputs": [],
357357
"source": [
358-
"from ess.amor.figures import wavelength_z_figure\n",
358+
"from ess.reflectometry.figures import wavelength_z_figure\n",
359359
"\n",
360360
"workflow[Filename[SampleRun]] = runs['608'][Filename[SampleRun]]\n",
361361
"workflow[SampleRotation[SampleRun]] = runs['608'][SampleRotation[SampleRun]]\n",
Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "0",
6+
"metadata": {},
7+
"source": [
8+
"# Reduction of ESTIA McStas data"
9+
]
10+
},
11+
{
12+
"cell_type": "markdown",
13+
"id": "1",
14+
"metadata": {},
15+
"source": [
16+
"This notebook demonstrates how to run the data reduction on the output of McStas simulations of the instrument.\n",
17+
"\n",
18+
"Essentially this looks very similar to how one would do data reduction on real data files from the physical instrument,\n",
19+
"but we replace the default loader with the `load_mcstas_events` provider."
20+
]
21+
},
22+
{
23+
"cell_type": "code",
24+
"execution_count": null,
25+
"id": "2",
26+
"metadata": {},
27+
"outputs": [],
28+
"source": [
29+
"#%matplotlib widget\n",
30+
"import scipp as sc\n",
31+
"\n",
32+
"from ess.estia.load import load_mcstas_events\n",
33+
"from ess.estia.data import estia_mcstas_example, estia_mcstas_groundtruth\n",
34+
"from ess.estia import EstiaWorkflow\n",
35+
"from ess.reflectometry.types import *\n",
36+
"from ess.reflectometry.figures import wavelength_z_figure, wavelength_theta_figure, q_theta_figure"
37+
]
38+
},
39+
{
40+
"cell_type": "markdown",
41+
"id": "3",
42+
"metadata": {},
43+
"source": [
44+
"The Estia reduction workflow is created and we set parameters such as region of interest, wavelengthbins, and q-bins."
45+
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": null,
50+
"id": "4",
51+
"metadata": {},
52+
"outputs": [],
53+
"source": [
54+
"\n",
55+
"wf = EstiaWorkflow()\n",
56+
"wf.insert(load_mcstas_events)\n",
57+
"wf[Filename[ReferenceRun]] = estia_mcstas_example('reference')\n",
58+
"\n",
59+
"wf[YIndexLimits] = sc.scalar(35), sc.scalar(64)\n",
60+
"wf[ZIndexLimits] = sc.scalar(0), sc.scalar(14 * 32)\n",
61+
"wf[BeamDivergenceLimits] = sc.scalar(-0.75, unit='deg'), sc.scalar(0.75, unit='deg')\n",
62+
"wf[WavelengthBins] = sc.geomspace('wavelength', 3.5, 12, 2001, unit='angstrom')\n",
63+
"wf[QBins] = 1000\n",
64+
"\n",
65+
"# There is no proton current data in the McStas files, here we just add some fake proton current\n",
66+
"# data to make the workflow run.\n",
67+
"wf[ProtonCurrent[SampleRun]] = sc.DataArray(\n",
68+
" sc.array(dims=('time',), values=[]),\n",
69+
" coords={'time': sc.array(dims=('time',), values=[], unit='s')})\n",
70+
"wf[ProtonCurrent[ReferenceRun]] = sc.DataArray(\n",
71+
" sc.array(dims=('time',), values=[]),\n",
72+
" coords={'time': sc.array(dims=('time',), values=[], unit='s')})\n",
73+
"\n",
74+
"\n",
75+
"def compute_reflectivity_curve_for_mcstas_data(wf, results):\n",
76+
" R, ref, da = w.compute((ReflectivityOverQ, Reference, ReducibleData[SampleRun])).values()\n",
77+
" # In the McStas simulation the reference has quite low intensity.\n",
78+
" # To make the reflectivity curve a bit more clean\n",
79+
" # we filter out the Q-points where the reference has too large uncertainties.\n",
80+
" ref = ref.hist(Q=R.coords['Q'])\n",
81+
" too_large_uncertainty_in_reference = sc.stddevs(ref).data > 0.3 * ref.data\n",
82+
" R = R.hist()\n",
83+
" R.data = sc.where(too_large_uncertainty_in_reference, sc.scalar(float('nan'), unit=R.unit), R.data)\n",
84+
" results[f\"{da.coords['sample_rotation'].value} {da.coords['sample_rotation'].unit}\"] = R\n"
85+
]
86+
},
87+
{
88+
"cell_type": "markdown",
89+
"id": "5",
90+
"metadata": {},
91+
"source": [
92+
"## Ni/Ti multilayer sample\n",
93+
"\n",
94+
"Below is a comparison between the reflectivity curve obtained using the reduction workflow and the ground truth reflectivity curve that was used in the McStas simulation.\n",
95+
"The sample was simulated at different sample rotation settings, each settings produces a separate reflectivity curve covering a higher Q-range, and that is the angle in the legend of the figure."
96+
]
97+
},
98+
{
99+
"cell_type": "code",
100+
"execution_count": null,
101+
"id": "6",
102+
"metadata": {},
103+
"outputs": [],
104+
"source": [
105+
"results = {}\n",
106+
"for path in estia_mcstas_example('Ni/Ti-multilayer'):\n",
107+
" w = wf.copy()\n",
108+
" w[Filename[SampleRun]] = path\n",
109+
" compute_reflectivity_curve_for_mcstas_data(w, results)\n",
110+
"\n",
111+
"ground_truth = estia_mcstas_groundtruth('Ni/Ti-multilayer')\n",
112+
"\n",
113+
"sc.plot({'ground_truth': ground_truth} | results, norm='log', vmin=1e-8)"
114+
]
115+
},
116+
{
117+
"cell_type": "markdown",
118+
"id": "7",
119+
"metadata": {},
120+
"source": [
121+
"Below are a number of figures displaying different projections of the measured intensity distribution."
122+
]
123+
},
124+
{
125+
"cell_type": "code",
126+
"execution_count": null,
127+
"id": "8",
128+
"metadata": {},
129+
"outputs": [],
130+
"source": [
131+
"results = []\n",
132+
"for path in estia_mcstas_example('Ni/Ti-multilayer'):\n",
133+
" w = wf.copy()\n",
134+
" w[Filename[SampleRun]] = path\n",
135+
" results.append(w.compute(Sample))"
136+
]
137+
},
138+
{
139+
"cell_type": "code",
140+
"execution_count": null,
141+
"id": "9",
142+
"metadata": {},
143+
"outputs": [],
144+
"source": [
145+
"wavelength_z_figure(results[3], wavelength_bins=400)"
146+
]
147+
},
148+
{
149+
"cell_type": "code",
150+
"execution_count": null,
151+
"id": "10",
152+
"metadata": {},
153+
"outputs": [],
154+
"source": [
155+
"wavelength_theta_figure(results, wavelength_bins=400, theta_bins=200, q_edges_to_display=[sc.scalar(0.016, unit='1/angstrom'), sc.scalar(0.19, unit='1/angstrom')])"
156+
]
157+
},
158+
{
159+
"cell_type": "code",
160+
"execution_count": null,
161+
"id": "11",
162+
"metadata": {},
163+
"outputs": [],
164+
"source": [
165+
"q_theta_figure(results, q_bins=300, theta_bins=200)"
166+
]
167+
},
168+
{
169+
"cell_type": "markdown",
170+
"id": "12",
171+
"metadata": {},
172+
"source": [
173+
"## Ni on Silicon"
174+
]
175+
},
176+
{
177+
"cell_type": "code",
178+
"execution_count": null,
179+
"id": "13",
180+
"metadata": {},
181+
"outputs": [],
182+
"source": [
183+
"results = {}\n",
184+
"for path in estia_mcstas_example('Ni-film on silicon'):\n",
185+
" w = wf.copy()\n",
186+
" w[Filename[SampleRun]] = path\n",
187+
" compute_reflectivity_curve_for_mcstas_data(w, results)\n",
188+
"\n",
189+
"ground_truth = estia_mcstas_groundtruth('Ni-film on silicon')\n",
190+
"sc.plot({'ground_truth': ground_truth} | results, norm='log', vmin=1e-9)"
191+
]
192+
},
193+
{
194+
"cell_type": "code",
195+
"execution_count": null,
196+
"id": "14",
197+
"metadata": {},
198+
"outputs": [],
199+
"source": [
200+
"results = []\n",
201+
"for path in estia_mcstas_example('Ni-film on silicon'):\n",
202+
" w = wf.copy()\n",
203+
" w[Filename[SampleRun]] = path\n",
204+
" results.append(w.compute(ReducibleData[SampleRun]))"
205+
]
206+
},
207+
{
208+
"cell_type": "code",
209+
"execution_count": null,
210+
"id": "15",
211+
"metadata": {},
212+
"outputs": [],
213+
"source": [
214+
"wavelength_z_figure(results[3], wavelength_bins=400)"
215+
]
216+
},
217+
{
218+
"cell_type": "code",
219+
"execution_count": null,
220+
"id": "16",
221+
"metadata": {},
222+
"outputs": [],
223+
"source": [
224+
"wavelength_theta_figure(results, wavelength_bins=400, theta_bins=200, q_edges_to_display=[sc.scalar(0.016, unit='1/angstrom'), sc.scalar(0.19, unit='1/angstrom')])"
225+
]
226+
},
227+
{
228+
"cell_type": "code",
229+
"execution_count": null,
230+
"id": "17",
231+
"metadata": {},
232+
"outputs": [],
233+
"source": [
234+
"q_theta_figure(results, q_bins=300, theta_bins=200)"
235+
]
236+
},
237+
{
238+
"cell_type": "markdown",
239+
"id": "18",
240+
"metadata": {},
241+
"source": [
242+
"## SiO2 on Silicon"
243+
]
244+
},
245+
{
246+
"cell_type": "code",
247+
"execution_count": null,
248+
"id": "19",
249+
"metadata": {},
250+
"outputs": [],
251+
"source": [
252+
"results = {}\n",
253+
"for path in estia_mcstas_example('Natural SiO2 on silicon'):\n",
254+
" w = wf.copy()\n",
255+
" w[Filename[SampleRun]] = path\n",
256+
" compute_reflectivity_curve_for_mcstas_data(w, results)\n",
257+
"\n",
258+
"ground_truth = estia_mcstas_groundtruth('Natural SiO2 on silicon')\n",
259+
"sc.plot({'ground_truth': ground_truth} | results, norm='log', vmin=1e-9)"
260+
]
261+
},
262+
{
263+
"cell_type": "code",
264+
"execution_count": null,
265+
"id": "20",
266+
"metadata": {},
267+
"outputs": [],
268+
"source": [
269+
"results = []\n",
270+
"for path in estia_mcstas_example('Natural SiO2 on silicon'):\n",
271+
" w = wf.copy()\n",
272+
" w[Filename[SampleRun]] = path\n",
273+
" results.append(w.compute(ReducibleData[SampleRun]))"
274+
]
275+
},
276+
{
277+
"cell_type": "code",
278+
"execution_count": null,
279+
"id": "21",
280+
"metadata": {},
281+
"outputs": [],
282+
"source": [
283+
"wavelength_z_figure(results[3], wavelength_bins=400)"
284+
]
285+
},
286+
{
287+
"cell_type": "code",
288+
"execution_count": null,
289+
"id": "22",
290+
"metadata": {},
291+
"outputs": [],
292+
"source": [
293+
"wavelength_theta_figure(results, wavelength_bins=400, theta_bins=200, q_edges_to_display=[sc.scalar(0.016, unit='1/angstrom')])"
294+
]
295+
},
296+
{
297+
"cell_type": "code",
298+
"execution_count": null,
299+
"id": "23",
300+
"metadata": {},
301+
"outputs": [],
302+
"source": [
303+
"q_theta_figure(results, q_bins=300, theta_bins=200)"
304+
]
305+
}
306+
],
307+
"metadata": {
308+
"kernelspec": {
309+
"display_name": "Python 3 (ipykernel)",
310+
"language": "python",
311+
"name": "python3"
312+
},
313+
"language_info": {
314+
"codemirror_mode": {
315+
"name": "ipython",
316+
"version": 3
317+
},
318+
"file_extension": ".py",
319+
"mimetype": "text/x-python",
320+
"name": "python",
321+
"nbconvert_exporter": "python",
322+
"pygments_lexer": "ipython3",
323+
"version": "3.10.14"
324+
}
325+
},
326+
"nbformat": 4,
327+
"nbformat_minor": 5
328+
}

0 commit comments

Comments
 (0)