Source code for pyhiperta.calibration

"""Implements the "calibration" of R0 data: going from 2 gain ADC counts to number of photo-electrons"""

from typing import Tuple

import numpy as np


[docs] def select_channel( waveform_high: np.ndarray, waveform_low: np.ndarray, gains: np.ndarray, pedestals: np.ndarray, window_integration_correction: np.ndarray, threshold: float, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: """Select values to use in waveforms high/low gain and corresponding gains and pedestals based on threshold. The choice is independent per shower and per pixel, but shared in time for a given pixel: For each pixel, if any value of `waveform_high` is above `threshold` then the low gain and corresponding waveform channel and pedestal is chosen. Otherwise the high gain is chosen. Parameters ---------- waveforms_high : np.ndarray R0 waveform high gain. Shape: (N_batch, N_frames, N_pixels) waveform_low : np.ndarray R0 waveform low gain. Shape: (N_batch, N_frames, N_pixels) gains : np.ndarray Per-pixel high and low gains. `gains[0]` is high gain, `gains[1]` is low gains. shape (2, N_pixels) pedestals : np.ndarray Per-pixel pedestal for low and high gains. `pedestals[0]` corresponds to high gain, `pedestals[1]` corresponds to low gain. Shape (2, N_pixels) window_integration_correction : np.ndarray Array of shape (2,) containing the correction to apply after a windowed integration, for each gain. threshold : float Threshold to chose the waveform channel. A value above `threshold` indicates that the high gain waveform saturated and low gain should be used. Returns ------- Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray] The waveform selected from each gains based on `threshold`, associated gains, pedestals and integration correction to used. The order is: - waveform : np.ndarray waveform where the appropriate gain has been selected. Shape (N_batch, N_frames, N_pixels) - gains : np.ndarray Gain to use to calibrate `waveform` (high gain when waveform_high wasn't above `threshold` and low gain otherwise). Shape (N_batch, N_pixels) - pedestals : np.ndarray Pedestals to use to calibrate `waveform`. Shape (N_batch, N_pixels) - window_integration_correction : np.ndarray Correction to use after the integration. Shape(N_batch, N_pixels) """ idx_saturated = (waveform_high > threshold).any(axis=-2, keepdims=True) return ( np.where(idx_saturated, waveform_low, waveform_high), np.where(np.squeeze(idx_saturated, -2), gains[1], gains[0]), np.where(np.squeeze(idx_saturated, -2), pedestals[1], pedestals[0]), np.where(np.squeeze(idx_saturated, -2), window_integration_correction[1], window_integration_correction[0]), )
[docs] def calibrate(waveform: np.ndarray, gains: np.ndarray, pedestals: np.ndarray) -> np.ndarray: """Apply pedestal and gain calibration to waveforms. Parameters ---------- waveform : np.ndarray Batch or single video samples of the shower events. Shape: (N_batch, N_frames, N_pixels) gains : np.ndarray For each waveform, the gains to apply to each pixel. The same gain is applied for all frames of a shower pixel. Shape: (N_batch, N_pixels). pedestals : np.ndarray For each waveform, the pedestals to apply to each pixel. The same pedestal is applied for all frames of a shower pixel. Shape (N_batch, N_pixels) Returns ------- np.ndarray Calibrated waveforms (number of photo-electrons). Shape is identical to `waveform`. """ return (waveform - pedestals[..., np.newaxis, :]) * gains[..., np.newaxis, :]