Skip to content

Commit c518883

Browse files
authored
Merge pull request #127 from scipp/image-norm-wf
Image normalization workflow for TBL/Orca
2 parents 3a99ff7 + d9a06bd commit c518883

20 files changed

Lines changed: 959 additions & 50 deletions

docs/tbl/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ maxdepth: 1
66
---
77
88
tbl-data-reduction
9+
orca-image-normalization
910
tbl-make-tof-lookup-table
1011
```
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "0",
6+
"metadata": {},
7+
"source": [
8+
"# TBL: Orca image normalization workflow\n",
9+
"\n",
10+
"This notebook shows how to use the workflow to compute normalized images recorded by the Orca detector on the TBL instrument."
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": null,
16+
"id": "1",
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"import ess.tbl.data # noqa: F401\n",
21+
"from ess import tbl\n",
22+
"from ess.imaging.types import *\n",
23+
"import scipp as sc\n",
24+
"import plopp as pp\n",
25+
"\n",
26+
"%matplotlib widget"
27+
]
28+
},
29+
{
30+
"cell_type": "markdown",
31+
"id": "2",
32+
"metadata": {},
33+
"source": [
34+
"## Workflow setup"
35+
]
36+
},
37+
{
38+
"cell_type": "code",
39+
"execution_count": null,
40+
"id": "3",
41+
"metadata": {},
42+
"outputs": [],
43+
"source": [
44+
"wf = tbl.OrcaNormalizedImagesWorkflow()\n",
45+
"\n",
46+
"wf[Filename[SampleRun]] = tbl.data.tbl_lego_sample_run()\n",
47+
"wf[Filename[DarkBackgroundRun]] = tbl.data.tbl_lego_dark_run()\n",
48+
"wf[Filename[OpenBeamRun]] = tbl.data.tbl_lego_openbeam_run()\n",
49+
"wf[NeXusDetectorName] = 'orca_detector'\n",
50+
"\n",
51+
"wf[MaskingRules] = {} # No masks to begin with\n",
52+
"wf[UncertaintyBroadcastMode] = UncertaintyBroadcastMode.upper_bound"
53+
]
54+
},
55+
{
56+
"cell_type": "code",
57+
"execution_count": null,
58+
"id": "4",
59+
"metadata": {},
60+
"outputs": [],
61+
"source": [
62+
"wf.visualize(NormalizedImage, compact=True, graph_attr={\"rankdir\": \"LR\"})"
63+
]
64+
},
65+
{
66+
"cell_type": "markdown",
67+
"id": "5",
68+
"metadata": {},
69+
"source": [
70+
"## Run the workflow\n",
71+
"\n",
72+
"We compute the final normalized image:"
73+
]
74+
},
75+
{
76+
"cell_type": "code",
77+
"execution_count": null,
78+
"id": "6",
79+
"metadata": {},
80+
"outputs": [],
81+
"source": [
82+
"image = wf.compute(NormalizedImage)\n",
83+
"image"
84+
]
85+
},
86+
{
87+
"cell_type": "code",
88+
"execution_count": null,
89+
"id": "7",
90+
"metadata": {},
91+
"outputs": [],
92+
"source": [
93+
"pp.slicer(image, autoscale=False)"
94+
]
95+
},
96+
{
97+
"cell_type": "markdown",
98+
"id": "8",
99+
"metadata": {},
100+
"source": [
101+
"## Adding masks\n",
102+
"\n",
103+
"If we want to mask some part of the image, we update the masking rules.\n",
104+
"For example, here we mask the upper part of the image:"
105+
]
106+
},
107+
{
108+
"cell_type": "code",
109+
"execution_count": null,
110+
"id": "9",
111+
"metadata": {},
112+
"outputs": [],
113+
"source": [
114+
"wf[MaskingRules] = {'y_pixel_offset': lambda x: x > sc.scalar(0.082, unit='m')}\n",
115+
"\n",
116+
"pp.slicer(wf.compute(NormalizedImage), autoscale=False)"
117+
]
118+
},
119+
{
120+
"cell_type": "markdown",
121+
"id": "10",
122+
"metadata": {},
123+
"source": [
124+
"## Intermediate results\n",
125+
"\n",
126+
"We can also inspect intermediate results, which is useful for debugging:"
127+
]
128+
},
129+
{
130+
"cell_type": "code",
131+
"execution_count": null,
132+
"id": "11",
133+
"metadata": {},
134+
"outputs": [],
135+
"source": [
136+
"results = wf.compute([\n",
137+
" RawDetector[SampleRun],\n",
138+
" CorrectedDetector[SampleRun],\n",
139+
" BackgroundSubtractedDetector[SampleRun]\n",
140+
"])\n",
141+
"\n",
142+
"fig = pp.tiled(2, 2, hspace=0.3, wspace=0.3)\n",
143+
"fig[0, 0] = results[RawDetector[SampleRun]]['time', 0].plot(title='Raw data')\n",
144+
"fig[0, 1] = results[CorrectedDetector[SampleRun]]['time', 0].plot(title='Masks applied')\n",
145+
"fig[1, 0] = results[BackgroundSubtractedDetector[SampleRun]]['time', 0].plot(title='Background subtracted')\n",
146+
"fig[1, 1] = image['time', 0].plot(title='Final image')\n",
147+
"fig"
148+
]
149+
}
150+
],
151+
"metadata": {
152+
"kernelspec": {
153+
"display_name": "Python 3 (ipykernel)",
154+
"language": "python",
155+
"name": "python3"
156+
},
157+
"language_info": {
158+
"codemirror_mode": {
159+
"name": "ipython",
160+
"version": 3
161+
},
162+
"file_extension": ".py",
163+
"mimetype": "text/x-python",
164+
"name": "python",
165+
"nbconvert_exporter": "python",
166+
"pygments_lexer": "ipython3",
167+
"version": "3.12.7"
168+
}
169+
},
170+
"nbformat": 4,
171+
"nbformat_minor": 5
172+
}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ dependencies = [
3838
"scippneutron>=24.12.0",
3939
"scippnexus>=23.11.1",
4040
"tifffile>=2024.7.2",
41-
"essreduce>=25.11.0",
41+
"essreduce>=25.11.2",
4242
"scitiff>=25.7",
4343
]
4444

requirements/base.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ scipp>=25.4.0
1010
scippneutron>=24.12.0
1111
scippnexus>=23.11.1
1212
tifffile>=2024.7.2
13-
essreduce>=25.11.0
13+
essreduce>=25.11.2
1414
scitiff>=25.7

requirements/base.txt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SHA1:da99ba40cef426287cd34dd1a2b56aefd0cb24e6
1+
# SHA1:a1100845ace4b19ad8a759324efbe63c69022f7b
22
#
33
# This file was generated by pip-compile-multi.
44
# To update, run:
@@ -7,13 +7,13 @@
77
#
88
annotated-types==0.7.0
99
# via pydantic
10-
asttokens==3.0.0
10+
asttokens==3.0.1
1111
# via stack-data
1212
attrs==25.4.0
1313
# via
1414
# jsonschema
1515
# referencing
16-
click==8.3.0
16+
click==8.3.1
1717
# via dask
1818
cloudpickle==3.1.2
1919
# via dask
@@ -25,15 +25,15 @@ cyclebane==24.10.0
2525
# via sciline
2626
cycler==0.12.1
2727
# via matplotlib
28-
dask==2025.10.0
28+
dask==2025.11.0
2929
# via -r base.in
3030
decorator==5.2.1
3131
# via ipython
3232
dnspython==2.8.0
3333
# via email-validator
3434
email-validator==2.3.0
3535
# via scippneutron
36-
essreduce==25.11.0
36+
essreduce==25.11.2
3737
# via -r base.in
3838
executing==2.2.1
3939
# via stack-data
@@ -57,7 +57,7 @@ ipydatawidgets==4.3.5
5757
# via pythreejs
5858
ipympl==0.9.8
5959
# via plopp
60-
ipython==9.6.0
60+
ipython==9.7.0
6161
# via
6262
# ipympl
6363
# ipywidgets
@@ -98,7 +98,7 @@ mpltoolbox==25.10.0
9898
# scippneutron
9999
networkx==3.5
100100
# via cyclebane
101-
numpy==2.3.4
101+
numpy==2.3.5
102102
# via
103103
# contourpy
104104
# h5py
@@ -125,7 +125,7 @@ pillow==12.0.0
125125
# via
126126
# ipympl
127127
# matplotlib
128-
plopp[all]==25.10.0
128+
plopp[all]==25.11.0
129129
# via
130130
# -r base.in
131131
# scippneutron
@@ -135,11 +135,11 @@ ptyprocess==0.7.0
135135
# via pexpect
136136
pure-eval==0.2.3
137137
# via stack-data
138-
pydantic==2.12.3
138+
pydantic==2.12.4
139139
# via
140140
# scippneutron
141141
# scitiff
142-
pydantic-core==2.41.4
142+
pydantic-core==2.41.5
143143
# via pydantic
144144
pygments==2.19.2
145145
# via
@@ -151,7 +151,6 @@ python-dateutil==2.9.0.post0
151151
# via
152152
# matplotlib
153153
# scippneutron
154-
# scippnexus
155154
pythreejs==2.4.2
156155
# via plopp
157156
pyyaml==6.0.3
@@ -160,7 +159,7 @@ referencing==0.37.0
160159
# via
161160
# jsonschema
162161
# jsonschema-specifications
163-
rpds-py==0.28.0
162+
rpds-py==0.29.0
164163
# via
165164
# jsonschema
166165
# referencing
@@ -180,7 +179,7 @@ scippneutron==25.7.0
180179
# via
181180
# -r base.in
182181
# essreduce
183-
scippnexus==25.6.0
182+
scippnexus==25.11.0
184183
# via
185184
# -r base.in
186185
# essreduce

requirements/basetest.txt

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ attrs==25.4.0
1111
# via
1212
# jsonschema
1313
# referencing
14-
certifi==2025.10.5
14+
certifi==2025.11.12
1515
# via requests
1616
charset-normalizer==3.4.4
1717
# via requests
@@ -37,12 +37,11 @@ lazy-loader==0.4
3737
# tof
3838
matplotlib==3.10.7
3939
# via plopp
40-
numpy==2.3.4
40+
numpy==2.3.5
4141
# via
4242
# contourpy
4343
# matplotlib
4444
# scipp
45-
# scipy
4645
# tifffile
4746
packaging==25.0
4847
# via
@@ -54,21 +53,23 @@ pillow==12.0.0
5453
# via matplotlib
5554
platformdirs==4.5.0
5655
# via pooch
57-
plopp==25.10.0
56+
plopp==25.11.0
5857
# via tof
5958
pluggy==1.6.0
6059
# via pytest
6160
pooch==1.8.2
62-
# via -r basetest.in
63-
pydantic==2.12.3
61+
# via
62+
# -r basetest.in
63+
# tof
64+
pydantic==2.12.4
6465
# via scitiff
65-
pydantic-core==2.41.4
66+
pydantic-core==2.41.5
6667
# via pydantic
6768
pygments==2.19.2
6869
# via pytest
6970
pyparsing==3.2.5
7071
# via matplotlib
71-
pytest==8.4.2
72+
pytest==9.0.1
7273
# via -r basetest.in
7374
python-dateutil==2.9.0.post0
7475
# via matplotlib
@@ -78,23 +79,21 @@ referencing==0.37.0
7879
# jsonschema-specifications
7980
requests==2.32.5
8081
# via pooch
81-
rpds-py==0.28.0
82+
rpds-py==0.29.0
8283
# via
8384
# jsonschema
8485
# referencing
8586
scipp==25.11.0
8687
# via
8788
# scitiff
8889
# tof
89-
scipy==1.16.3
90-
# via tof
9190
scitiff==25.7.0
9291
# via -r basetest.in
9392
six==1.17.0
9493
# via python-dateutil
9594
tifffile==2025.10.16
9695
# via scitiff
97-
tof==25.10.1
96+
tof==25.12.0
9897
# via -r basetest.in
9998
typing-extensions==4.15.0
10099
# via

requirements/ci.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
#
66
# requirements upgrade
77
#
8-
cachetools==6.2.1
8+
cachetools==6.2.2
99
# via tox
10-
certifi==2025.10.5
10+
certifi==2025.11.12
1111
# via requests
1212
chardet==5.2.0
1313
# via tox

0 commit comments

Comments
 (0)