scipp / essdiffraction

Diffraction data reduction for the European Spallation Source
https://scipp.github.io/essdiffraction/
BSD 3-Clause "New" or "Revised" License
0 stars 2 forks source link

[Requirement] Normalise by monitor #76

Open jl-wynen opened 2 months ago

jl-wynen commented 2 months ago

Executive summary

Normalise data by monitor counts

Context and background knowledge

This issue is an alternative to #30. In some cases users want to normalise detector data by a monitor. This can be either

The user needs to be able to pick one or the other.

Inputs

Methodology

Normalisation by wavelength spectrum Either histogram the monitor into the same bins as the detector data and then divide. Or use sc.lookup to account for different binning. (See old WISH workflow.)

Normalisation by integrated monitor Divide detector data by sc.sum(monitor).

Outputs

Normalised data array.

We should probably ensure that the data array has the same units regardless of which monitor normalisation was used.

Which interfaces are required?

Integrated into reduction workflow, Python module / function

Test cases

Dummy test data.

Comments

No response

jl-wynen commented 1 week ago

With suitable pre-processing in the workflow, these should work:

def normalize_by_integrated_monitor(
    *, detector: sc.DataArray, monitor: sc.DataArray
) -> sc.DataArray:
    key = monitor.dim
    assert monitor.coords.is_edges(key)

    # Clip `monitor` to the range of `detector`.
    lo = detector.coords[key].min()
    hi = detector.coords[key].max()
    hi.value = np.nextafter(hi.value, np.inf)
    monitor = monitor[key, lo:hi]

    coord = monitor.coords[key]
    norm = sc.sum(monitor.data * (coord[1:] - coord[:-1]))
    return detector / norm

def normalize_by_monitor_histogram(
    *,
    detector: sc.DataArray,
    monitor: sc.DataArray,
) -> sc.DataArray:
    # Requires
    # - `detector` to be binned,
    # - `monitor` to be histogrammed
    return detector.bins / sc.lookup(monitor)