Source code for adcorr.corrections.self_absorption

from typing import Tuple, cast

from numpy import (
    broadcast_to,
    cos,
    divide,
    dtype,
    expand_dims,
    floating,
    log,
    logical_and,
    ndarray,
    number,
    ones_like,
    power,
)

from ..utils.geometry import scattering_angles
from ..utils.typing import FrameHeight, Frames, FrameWidth, NumFrames, VectorOrSingle


[docs] def correct_self_absorption( frames: Frames[NumFrames, FrameWidth, FrameHeight, dtype[number]], incident_flux: ndarray[VectorOrSingle[NumFrames], dtype[number]], transmitted_flux: ndarray[VectorOrSingle[NumFrames], dtype[number]], beam_center: Tuple[float, float], pixel_sizes: Tuple[float, float], distance: float, ) -> Frames[NumFrames, FrameWidth, FrameHeight, dtype[number]]: """Correct for transmission loss due to differences in observation angle. Correct for transmission loss due to differences in observation angle, as detailed in section 3.4.7 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. incident_flux: The flux intensity observed upstream of the sample. transmitted_flux: The flux intensity observed downstream of the sample. beam_center: The center position of the beam in pixels. pixel_sizes: The real space size of a detector pixel. distance: The distance between the detector and the sample. Returns: The corrected stack of frames. """ angles = scattering_angles( cast(Tuple[int, int], frames.shape[-2:]), beam_center, pixel_sizes, distance ) transmissibility = transmitted_flux / incident_flux transmissibility = ( transmissibility if transmissibility.shape == (1,) else expand_dims(transmissibility, (1, 2)) ) secangles: ndarray[Tuple[int, int], dtype[floating]] = broadcast_to( 1 / cos(angles), frames.shape ) correction_factors: ndarray[Tuple[int, int, int], dtype[floating]] = divide( 1 - power(transmissibility, secangles - 1), log(transmissibility) * (1 - secangles), out=ones_like(secangles), where=logical_and(secangles != 1.0, transmissibility != 1.0), ) return frames * correction_factors