Source code for adcorr.corrections.deadtime
from typing import Any, cast
from numpy import (
atleast_1d,
complexfloating,
dtype,
expand_dims,
floating,
ndarray,
number,
)
from scipy.special import lambertw
from ..utils.typing import FrameHeight, Frames, FrameWidth, NumFrames, VectorOrSingle
[docs]
def correct_deadtime(
frames: Frames[NumFrames, FrameWidth, FrameHeight, dtype[number]],
count_times: ndarray[VectorOrSingle[NumFrames], dtype[floating]],
minimum_pulse_separation: float,
minimum_arrival_separation: float,
) -> Frames[NumFrames, FrameWidth, FrameHeight, dtype[number]]:
"""Correct for detector deadtime by accounting for overlapping events.
Correct for detector deadtime by iteratively solving for the number of incident
photons required to produce the observed value in a given time period subject to
detector characteristics, as detailed in section 3.3.4 of 'Everything SAXS: small-
angle scattering pattern collection and correction'
[https://doi.org/10.1088/0953-8984/25/38/383201].
Args:
frames: A stack of frames to be corrected.
count_times: The period over which photons are counted for each frame.
minimum_pulse_separation: The minimum time difference required between a prior
pulse and the current pulse for the current pulse to be recorded correctly.
minimum_arrival_separation: The minimum time difference required between the
current pulse and a subsequent pulse for the current pulse to be recorded
correctly.
Returns:
The corrected stack of frames.
"""
if (count_times <= 0).any():
raise ValueError("Count times must be positive.")
if minimum_pulse_separation < 0:
raise ValueError("Minimum Pulse Separation must be non-negative.")
if minimum_arrival_separation < 0:
raise ValueError("Minimum Arrival Separation must be non-negative.")
if minimum_pulse_separation == 0 and minimum_arrival_separation == 0:
return frames
deadtime_proportion = expand_dims(
atleast_1d(
(minimum_pulse_separation + minimum_arrival_separation) / count_times
),
(1, 2),
)
return (
-cast(
ndarray[Any, dtype[complexfloating]],
lambertw(-deadtime_proportion * frames),
).real
/ deadtime_proportion
)