Skip to content

Commit c1621cb

Browse files
committed
Update docstrings to new equations
1 parent 9c1326f commit c1621cb

File tree

1 file changed

+27
-52
lines changed

1 file changed

+27
-52
lines changed

src/ess/reduce/normalization.py

Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,51 +15,26 @@ def normalize_by_monitor_histogram(
1515
monitor: sc.DataArray,
1616
uncertainty_broadcast_mode: UncertaintyBroadcastMode,
1717
) -> sc.DataArray:
18-
"""Normalize detector data by a histogrammed monitor.
18+
"""Normalize detector data by a normalized histogrammed monitor.
1919
20-
First, the monitor is clipped to the range of the detector
20+
This normalization accounts for both the (wavelength) profile of the incident beam
21+
and the integrated neutron flux, meaning measurement duration and source strength.
2122
22-
.. math::
23-
24-
\\bar{m}_i = m_i I(x_i, x_{i+1}),
23+
- For *event* detectors, the monitor values are mapped to the detector
24+
using :func:`scipp.lookup`. That is, for detector event :math:`d_i`,
25+
:math:`m_i` is the monitor bin value at the same coordinate.
26+
- For *histogram* detectors, the monitor is rebinned using to the detector
27+
binning using :func:`scipp.rebin`. Thus, detector value :math:`d_i` and
28+
monitor value :math:`m_i` correspond to the same bin.
2529
26-
where :math:`m_i` is the monitor intensity in bin :math:`i`,
27-
:math:`x_i` is the lower bin edge of bin :math:`i`, and
28-
:math:`I(x_i, x_{i+1})` selects bins that are within the range of the detector.
30+
In both cases, let :math:`x_i` be the lower bound of monitor bin :math:`i`
31+
and let :math:`\\Delta x_i = x_{i+1} - x_i` be the width of that bin.
2932
30-
The detector bins :math:`d_i` are normalized according to
33+
The detector is normalized according to
3134
3235
.. math::
3336
34-
d_i^\\text{Norm} = \\frac{d_i}{\\bar{m}_i} \\Delta x_i
35-
\\frac{\\sum_j\\,\\bar{m}_j}{\\sum_j\\,\\Delta x_j}
36-
37-
where :math:`\\Delta x_i = x_{i+1} - x_i` is the width of
38-
monitor bin :math:`i` (see below).
39-
This normalization leads to a result that has the same
40-
unit as the input detector data.
41-
42-
Monitor bin :math:`i` is chosen according to:
43-
44-
- *Histogrammed detector*: The monitor is
45-
`rebinned <https://scipp.github.io/generated/functions/scipp.rebin.html>`_
46-
to the detector binning. This distributes the monitor weights to the
47-
detector bins.
48-
- *Binned detector*: The monitor value for bin :math:`i` is determined via
49-
:func:`scipp.lookup`. This means that for each event, the monitor value
50-
is obtained from the monitor histogram at that event coordinate value.
51-
52-
.. Attention::
53-
54-
Masked bins in ``detector`` are ignored when clipping the monitor and therefore
55-
impact the normalization factor.
56-
The output's masked bins are normalized using the same factor and may
57-
be incorrect and even contain NaN.
58-
You should only drop masks after normalization if you know what you are doing.
59-
60-
This function is based on the implementation of
61-
`NormaliseToMonitor <https://docs.mantidproject.org/nightly/algorithms/NormaliseToMonitor-v1.html>`_
62-
in Mantid.
37+
d_i^\\text{Norm} = \\frac{d_i}{m_i} \\Delta x_i
6338
6439
Parameters
6540
----------
@@ -88,8 +63,10 @@ def normalize_by_monitor_histogram(
8863
dim = monitor.dim
8964

9065
detector = _mask_detector_for_norm(detector=detector, monitor=monitor)
66+
# TODO do not clip
9167
clipped = _clip_monitor_to_detector_range(monitor=monitor, detector=detector)
9268
coord = clipped.coords[dim]
69+
# TODO fix equation
9370
delta_w = sc.DataArray(coord[1:] - coord[:-1], masks=clipped.masks)
9471
total_monitor_weight = broadcast_uncertainties(
9572
clipped.sum() / delta_w.sum(),
@@ -114,23 +91,21 @@ def normalize_by_monitor_integrated(
11491
) -> sc.DataArray:
11592
"""Normalize detector data by an integrated monitor.
11693
117-
The monitor is integrated according to
94+
This normalization accounts only for the integrated neutron flux,
95+
meaning measurement duration and source strength.
96+
It does *not* account for the (wavelength) profile of the incident beam.
97+
For that, see :func:`normalize_by_monitor_histogram`.
11898
119-
.. math::
99+
Let :math:`d_i` be a detector event or the counts in a detector bin.
100+
The normalized detector is
120101
121-
M = \\sum_{i=0}^{N-1}\\, m_i (x_{i+1} - x_i) I(x_i, x_{i+1}),
122-
123-
where :math:`m_i` is the monitor intensity in bin :math:`i`,
124-
:math:`x_i` is the lower bin edge of bin :math:`i`, and
125-
:math:`I(x_i, x_{i+1})` selects bins that are within the range of the detector.
102+
.. math::
126103
127-
.. Attention::
104+
d_i^\\text{Norm} &= d_i / M \\\\
105+
M &= \\sum_j\\, m_j (x_{j+1} - x_j)\\,,
128106
129-
Masked bins in ``detector`` are ignored when clipping the monitor and therefore
130-
impact the normalization factor.
131-
The output's masked bins are normalized using the same factor and may
132-
be incorrect and even contain NaN.
133-
You should only drop masks after normalization if you know what you are doing.
107+
where :math:`m_j` is the monitor counts in bin :math:`j` and
108+
:math:`x_j` is the lower bin edge of that bin.
134109
135110
Parameters
136111
----------
@@ -152,7 +127,7 @@ def normalize_by_monitor_integrated(
152127
See also
153128
--------
154129
normalize_by_monitor_histogram:
155-
Normalize by a monitor histogram without integration.
130+
Normalize by a monitor histogram.
156131
"""
157132
detector = _mask_detector_for_norm(detector=detector, monitor=monitor)
158133
clipped = _clip_monitor_to_detector_range(monitor=monitor, detector=detector)

0 commit comments

Comments
 (0)