Non-linearity injection#
Non-linearity is the effect of a non-ideal TES detector response, where the responsivity \(S\) is not constant as the optical power varies. The LiteBIRD Simulation Framework provides a non-linearity simulation module to simulate the effect of non-linearity on TODs.
The framework provides the simplest case, which is quadratic non-linearity. This case is described in Micheli+2024, where the effect of non-linearity is propagated to the estimation of the tensor-to-scalar ratio.
Considering a first order correction of the usual linear gain, a TOD \(d(t)\) is modified according to:
where \(g_1\) is the detector non-linearity factor in units of \(K^{-1}\).
Examples#
To simulate a quadratic non-linearity, one can use the method of
Simulation class
Simulation.apply_quadratic_nonlin(), or any of the low-level
functions: apply_quadratic_nonlin_to_observations(),
apply_quadratic_nonlin_for_one_detector().
The examples below skip the simulation and observation creation for brevity. If needed, the implementation for those parts is explained in other sections of the docs.
(... importing modules, creating simulation, setting scanning strategy, instrument, etc...)
# creating the detectors (two mock detectors here)
dets = [
lbs.DetectorInfo(name="det_A", sampling_rate_hz=sampling_hz),
lbs.DetectorInfo(name="det_B", sampling_rate_hz=sampling_hz),
]
(obs,) = sim.create_observations(
detectors=dets,
)
sim.prepare_pointings()
(... fill your TOD scanning a map, or add dipole, noise, etc...)
# Define nonlinearity amplitude distribution for the detectors, in 1/K units.
# The value is randomized for each detector, using either a user-provided seed or a list of
# pre-initialized RNGs.
nl_params = lbs.NonLinParams(sampling_gaussian_loc=-1.0, sampling_gaussian_scale=0.01)
# Applying nonlinearity using the `Simulation` class method
# By default, it modifies the ``Observation.tod``. If you want to apply it to some
# other field of the :class:`.Observation` class, use `component`
sim.apply_quadratic_nonlin(nl_params = nl_params)
API reference#
- class litebird_sim.non_linearity.NonLinParams(sampling_gaussian_loc: float = 0.0, sampling_gaussian_scale: float = 0.1)#
Bases:
objectA class to store the non-lineairty injection parameters.
sampling_gaussian_loc(float): Mean of the Gaussian distribution.sampling_gaussian_scale(float): Standard deviation of the Gaussian distribution.
- sampling_gaussian_loc: float = 0.0#
- sampling_gaussian_scale: float = 0.1#
- litebird_sim.non_linearity.apply_quadratic_nonlin(tod: ndarray, nl_params: NonLinParams | None = None, dets_random: list[Generator] | None = None)#
Apply a quadratic nonlinearity to some time-ordered data
This functions modifies the values in tod by adding a parabolic function of the TOD itself.
- litebird_sim.non_linearity.apply_quadratic_nonlin_for_one_detector(tod_det, nl_params: NonLinParams | None = None, random: Generator | None = None)#
This function applies the quadratic non-linearity on the TOD corresponding to only one detector.
- Parameters:
det_tod (np.ndarray) – The TOD array corresponding to only one detector.
det_name (str) – The name of the detector to which the TOD belongs. This name is used with
user_seedto generate hash. This hash is used to set random slope in case of linear drift, and randomized detector mismatch in case of thermal gain drift.nl_params (
NonLinParams, optional) – The non-linearity injection parameters object. Defaults to None.user_seed (int, optional) – A seed provided by the user. Defaults to None.
random (np.random.Generator, optional) – A random number generator. Defaults to None.
- litebird_sim.non_linearity.apply_quadratic_nonlin_for_one_sample(data, det_name: str | None = None, nl_params: NonLinParams | None = None, g_one_over_k: float | None = None, random: Generator | None = None)#
- litebird_sim.non_linearity.apply_quadratic_nonlin_to_observations(observations: Observation | list[Observation], nl_params: NonLinParams | None = None, component: str = 'tod', user_seed: int | None = None, dets_random: list[Generator] | None = None)#
Apply a quadratic nonlinearity to some time-ordered data
This is a wrapper around the
apply_quadratic_nonlin()function that applies to the TOD stored in observations, which can either be oneObservationinstance or a list of observations. It ensures proper setup of per-detector random number generators using either a user-provided seed or a list of pre-initialized RNGs.By default, the modified TOD is
Observation.tod. If you want to modify some other field of theObservationclass, use component:for cur_obs in sim.observations: # Allocate a new TOD for the nonlinear TOD alone cur_obs.nl_tod = np.zeros_like(cur_obs.tod) # Ask `apply_quadratic_nonlin_to_observations` to store the nonlinear TOD # in `observations.nl_tod` apply_quadratic_nonlin_to_observations(sim.observations, component="nl_tod")
- Parameters:
observations (Observation or list of Observation) – A single Observation instance or a list of them.
nl_params (NonLinParams, optional) – Parameters defining the quadratic non-linearity model. If not provided, a default configuration is used.
component (str, optional) – Name of the TOD attribute to modify. Defaults to “tod”.
user_seed (int, optional) – Base seed to build the RNG hierarchy and generate detector-level RNGs that overwrite any eventual dets_random. Required if dets_random is not provided.
dets_random (list of np.random.Generator, optional) – List of per-detector random number generators. If not provided, and user_seed is given, generators are created internally. One of user_seed or dets_random must be provided.
- Raises:
TypeError – If observations is neither an Observation nor a list of them.
ValueError – If neither user_seed nor dets_random is provided.
AssertionError – If the number of random generators does not match the number of detectors.