Skip to content

Commit 501a726

Browse files
authored
Merge pull request #170 from scipp/drop_variances_in_sans
Drop normalization variances in sans and reflectometry workflows
2 parents c8cceea + 4b043b2 commit 501a726

19 files changed

+427
-232
lines changed

docs/instruments/external/powgen/powgen_reduction.ipynb

+46-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
},
3030
"outputs": [],
3131
"source": [
32-
"%matplotlib widget\n",
3332
"import scipp as sc\n",
3433
"import scippneutron as scn\n",
3534
"import plopp as pp\n",
@@ -378,12 +377,53 @@
378377
},
379378
{
380379
"cell_type": "markdown",
381-
"id": "a8f39532-e0ee-48cc-8c49-40ac7427ded8",
380+
"id": "97ecaa8f-c905-4d02-aad6-dc7ef7c707a8",
382381
"metadata": {},
383382
"source": [
384383
"Currently, `load_and_preprocess_vanadium` uses a crude, preliminary event filtering mechanism which removed all events if the proton charge is too low.\n",
385384
"This happens with the empty instrument data in this case as can be seen in the log widget at the top of the notebook.\n",
386385
"\n",
386+
"### Removing the variances of the Vanadium data"
387+
]
388+
},
389+
{
390+
"cell_type": "markdown",
391+
"id": "3d41c537-40b1-4ea7-87b1-f0dc3929ef55",
392+
"metadata": {},
393+
"source": [
394+
"<div class=\"alert alert-warning\">\n",
395+
"\n",
396+
"**Warning**\n",
397+
" \n",
398+
"Heybrock et al. (2023) have shown that Scipp's uncertainty propagation is not suited for broadcast operations\n",
399+
"such as normalizing event counts by a scalar value, which is the case when normalizing by Vanadium counts.\n",
400+
"These operations are forbidden in recent versions of Scipp.\n",
401+
"Until an alternative method is found to satisfactorily track the variances in this workflow,\n",
402+
"we remove the variances in the Vanadium data.\n",
403+
"The issue is tracked [here](https://github.com/scipp/ess/issues/171).\n",
404+
"\n",
405+
"</div>"
406+
]
407+
},
408+
{
409+
"cell_type": "code",
410+
"execution_count": null,
411+
"id": "7ee60cf0-f2f5-426b-89e7-aa137a73b8c5",
412+
"metadata": {
413+
"tags": []
414+
},
415+
"outputs": [],
416+
"source": [
417+
"vana.bins.constituents['data'].variances = None"
418+
]
419+
},
420+
{
421+
"cell_type": "markdown",
422+
"id": "31a1525b-c5a2-4164-862d-5e2152d84c83",
423+
"metadata": {},
424+
"source": [
425+
"### Conversion to d-spacing\n",
426+
"\n",
387427
"Now, we compute d-spacing using the same calibration parameters as before."
388428
]
389429
},
@@ -459,7 +499,9 @@
459499
"metadata": {},
460500
"source": [
461501
"We start simple by combining all spectra using `data.bins.concat('spectrum')`.\n",
462-
"Then, we can normalize the same data by vanadium to get a d-spacing distribution."
502+
"Then, we can normalize the same data by vanadium to get a d-spacing distribution.\n",
503+
"\n",
504+
"**Note that because we removed the variances on the Vanadium data, after the following cell, the standard deviations on the result are underestimated.**"
463505
]
464506
},
465507
{
@@ -624,6 +666,7 @@
624666
},
625667
"outputs": [],
626668
"source": [
669+
"%matplotlib widget\n",
627670
"pp.superplot(normalized)"
628671
]
629672
}

docs/instruments/loki/sans2d_reduction.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
},
106106
"outputs": [],
107107
"source": [
108-
"direct_beam = sc.io.open_hdf5(loki.data.get_path('DIRECT_SANS2D_REAR_34327_4m_8mm_16Feb16.hdf5'))\n",
108+
"direct_beam = sc.io.load_hdf5(loki.data.get_path('DIRECT_SANS2D_REAR_34327_4m_8mm_16Feb16.hdf5'))\n",
109109
"sample = loki.io.load_sans2d(filename=loki.data.get_path('SANS2D00063114.hdf5'))\n",
110110
"direct = loki.io.load_sans2d(filename=loki.data.get_path('SANS2D00063091.hdf5'))\n",
111111
"background = loki.io.load_sans2d(filename=loki.data.get_path('SANS2D00063159.hdf5'))\n",

docs/instruments/loki/sans2d_to_I_of_Q.ipynb

+43-41
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"# Direct measurement is with the empty sample holder/cuvette\n",
118118
"direct = loki.io.load_sans2d(filename=loki.data.get_path('SANS2D00063091.hdf5'))\n",
119119
"# Load direct beam function for main detector\n",
120-
"direct_beam = sc.io.open_hdf5(loki.data.get_path('DIRECT_SANS2D_REAR_34327_4m_8mm_16Feb16.hdf5'))\n",
120+
"direct_beam = sc.io.load_hdf5(loki.data.get_path('DIRECT_SANS2D_REAR_34327_4m_8mm_16Feb16.hdf5'))\n",
121121
"# Inspect sample data\n",
122122
"sample"
123123
]
@@ -127,7 +127,7 @@
127127
"id": "c4569a53-a19a-440e-8aa0-63df29f67d05",
128128
"metadata": {},
129129
"source": [
130-
"## Inspect monitor data\n",
130+
"## Inspecting the monitor data\n",
131131
"\n",
132132
"The monitor counts play a major role in normalizing the detector counts.\n",
133133
"From the two loaded runs, we extract the data from the incident and transmission monitors."
@@ -261,18 +261,18 @@
261261
},
262262
"outputs": [],
263263
"source": [
264-
"monitors = sans.i_of_q.preprocess_monitor_data(\n",
264+
"processed_monitors = sans.i_of_q.preprocess_monitor_data(\n",
265265
" monitors,\n",
266266
" non_background_range=non_background_range,\n",
267267
" wavelength_bins=wavelength_bins)\n",
268268
"\n",
269269
"sample_monitors = {\n",
270-
" 'incident': monitors['sample-incident'],\n",
271-
" 'transmission': monitors['sample-transmission']\n",
270+
" 'incident': processed_monitors['sample-incident'],\n",
271+
" 'transmission': processed_monitors['sample-transmission']\n",
272272
"}\n",
273273
"direct_monitors = {\n",
274-
" 'incident': monitors['direct-incident'],\n",
275-
" 'transmission': monitors['direct-transmission']\n",
274+
" 'incident': processed_monitors['direct-incident'],\n",
275+
" 'transmission': processed_monitors['direct-transmission']\n",
276276
"}"
277277
]
278278
},
@@ -623,32 +623,6 @@
623623
"sc.plot(direct_beam)"
624624
]
625625
},
626-
{
627-
"cell_type": "markdown",
628-
"id": "894e8329-8987-4565-b070-5d262af746d8",
629-
"metadata": {},
630-
"source": [
631-
"### Solid Angle\n",
632-
"\n",
633-
"The `sans.normalization` module also provides a utility to compute the solid angles of rectangular detector pixels:"
634-
]
635-
},
636-
{
637-
"cell_type": "code",
638-
"execution_count": null,
639-
"id": "e126e749-3dad-4ad8-a6f9-2d446e0153e4",
640-
"metadata": {
641-
"tags": []
642-
},
643-
"outputs": [],
644-
"source": [
645-
"solid_angle = sans.normalization.solid_angle_of_rectangular_pixels(\n",
646-
" sample,\n",
647-
" pixel_width=sample.coords['pixel_width'],\n",
648-
" pixel_height=sample.coords['pixel_height'])\n",
649-
"solid_angle"
650-
]
651-
},
652626
{
653627
"cell_type": "markdown",
654628
"id": "92b7cba6-c4aa-458f-8564-a0c265cf4332",
@@ -657,23 +631,39 @@
657631
"### The denominator term\n",
658632
"\n",
659633
"We combine all the terms above to compute the `denominator`.\n",
660-
"We then attach to the denominator some coordinates required to perform the conversion to $Q$."
634+
"\n",
635+
"**Note:**\n",
636+
"\n",
637+
"[Heybrock et al. (2023)](#heybrock2023) describe how broadcasting operations introduce correlations which are not tracked by Scipp's uncertainty propagation.\n",
638+
"In the normalization term above, multiplying $M(\\lambda)T(\\lambda)D(\\lambda)$ (wavelength dependent) by the solid angle $\\Omega(R)$ (pixel dependent) is such a broadcasting operation.\n",
639+
"The article however states that for normalization operations, under the limit where the counts of the numerator a much smaller than that of the denominator,\n",
640+
"dropping the variances of the denominator is a satisfactory approximation.\n",
641+
"\n",
642+
"The helper function below internally calculates the solid angles of the detector pixels $\\Omega(R)$,\n",
643+
"and performs a verification that our data satisfies that condition.\n",
644+
"\n",
645+
"We are not able to perform this check earlier in the workflow, because the verification involves comparing integrated counts,\n",
646+
"and the integration needs to be performed over the same wavelength range for both the monitors and the detector counts.\n",
647+
"To be able to compute the wavelengths of the detector data, we needed to first run the beam center finder."
661648
]
662649
},
663650
{
664651
"cell_type": "code",
665652
"execution_count": null,
666-
"id": "30250d51-0d6f-4265-b372-881900a16e2a",
653+
"id": "fc07f7b3-73dd-410d-9c1c-905d579a97cf",
667654
"metadata": {
668655
"tags": []
669656
},
670657
"outputs": [],
671658
"source": [
672-
"denominator = sans.normalization.compute_denominator(\n",
673-
" direct_beam=direct_beam,\n",
674-
" data_incident_monitor=sample_monitors['incident'],\n",
675-
" transmission_fraction=transmission_fraction,\n",
676-
" solid_angle=solid_angle)\n",
659+
"denominator = sans.normalization.iofq_denominator(\n",
660+
" data=sample,\n",
661+
" data_transmission_monitor=sample_monitors['transmission'],\n",
662+
" direct_incident_monitor=direct_monitors['incident'],\n",
663+
" direct_transmission_monitor=direct_monitors['transmission'],\n",
664+
" direct_beam=direct_beam\n",
665+
" )\n",
666+
"\n",
677667
"# Insert a copy of coords needed for conversion to Q.\n",
678668
"# TODO: can this be avoided by copying the Q coords from the converted numerator?\n",
679669
"for coord in ['position', 'sample_position', 'source_position']:\n",
@@ -826,7 +816,7 @@
826816
},
827817
{
828818
"cell_type": "markdown",
829-
"id": "faf45578-6b6a-4046-82aa-4864a2e8bb8b",
819+
"id": "cf7ef2db-6ea0-4ea8-a0c4-04ef96831596",
830820
"metadata": {},
831821
"source": [
832822
"<div id='heenan1997'></div>\n",
@@ -836,6 +826,18 @@
836826
"[J. Appl. Cryst., 30, 1140-1147](https://doi.org/10.1107/S0021889897002173)"
837827
]
838828
},
829+
{
830+
"cell_type": "markdown",
831+
"id": "faf45578-6b6a-4046-82aa-4864a2e8bb8b",
832+
"metadata": {},
833+
"source": [
834+
"<div id='heybrock2023'></div>\n",
835+
"\n",
836+
"Heybrock S., Wynen J.-L., Vaytet N., **2023**,\n",
837+
"*Systematic underestimation of uncertainties by widespread neutron-scattering data-reduction software*,\n",
838+
"Journal of Neutron Research"
839+
]
840+
},
839841
{
840842
"cell_type": "markdown",
841843
"id": "4ca6948e-ed72-49de-8529-4faf1474535c",

docs/techniques/sans/i_of_q.rst

-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,5 @@ Building blocks
1818
:toctree: ../../generated
1919

2020
convert_to_q_and_merge_spectra
21-
normalization_denominator
2221
preprocess_monitor_data
2322
resample_direct_beam

docs/techniques/sans/reference.rst

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ Beam center finder
2121
beam_center_finder.center_of_mass
2222
beam_center_finder.cost
2323
beam_center_finder.iofq_in_quadrants
24-
beam_center_finder.iofq_normalization
2524
beam_center_finder.minimize
2625

2726
Conversions
@@ -41,7 +40,7 @@ Normalization
4140

4241
normalization.solid_angle_of_rectangular_pixels
4342
normalization.transmission_fraction
44-
normalization.compute_denominator
43+
normalization.iofq_denominator
4544
normalization.normalize
4645

4746
Common

docs/techniques/sans/sans-beam-center-finder.ipynb

+6-3
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,12 @@
341341
},
342342
"outputs": [],
343343
"source": [
344-
"norm = bcf.iofq_normalization(data=sample,\n",
345-
" data_monitors=sample_monitors,\n",
346-
" direct_monitors=direct_monitors)\n",
344+
"norm = sans.normalization.iofq_denominator(\n",
345+
" data=sample,\n",
346+
" data_transmission_monitor=sc.values(sample_monitors['transmission']),\n",
347+
" direct_incident_monitor=sc.values(direct_monitors['incident']),\n",
348+
" direct_transmission_monitor=sc.values(direct_monitors['transmission']))\n",
349+
"\n",
347350
"norm"
348351
]
349352
},

0 commit comments

Comments
 (0)