@@ -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