Coverage for src/pyhiperta/calibration.py: 100%

6 statements  

« prev     ^ index     » next       coverage.py v7.15.3, created at 2026-08-07 14:41 +0000

1# Copyright 2026 CNRS 

2# This software is distributed under the terms of the CeCILL-C free software license. 

3 

4"""Calibration of R0 data: going from 2 gain ADC counts to number of photo-electrons.""" 

5 

6 

7import numpy as np 

8 

9 

10def select_channel( 

11 waveform_high: np.ndarray, 

12 waveform_low: np.ndarray, 

13 gains: np.ndarray, 

14 pedestals: np.ndarray, 

15 window_integration_correction: np.ndarray, 

16 threshold: float, 

17) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: 

18 """Select values to use in waveforms high/low gain and corresponding gains and pedestals based on threshold. 

19 

20 The choice is independent per shower and per pixel, but shared in time for a given pixel: 

21 For each pixel, if any value of `waveform_high` is above `threshold` then the low gain and 

22 corresponding waveform channel and pedestal is chosen. Otherwise the high gain is chosen. 

23 

24 Parameters 

25 ---------- 

26 waveform_high : np.ndarray 

27 R0 waveform high gain. Shape: (N_batch, N_frames, N_pixels) 

28 waveform_low : np.ndarray 

29 R0 waveform low gain. Shape: (N_batch, N_frames, N_pixels) 

30 gains : np.ndarray 

31 Per-pixel high and low gains. `gains[0]` is high gain, `gains[1]` is low gains. shape (2, N_pixels) 

32 pedestals : np.ndarray 

33 Per-pixel pedestal for low and high gains. `pedestals[0]` corresponds to high gain, `pedestals[1]` 

34 corresponds to low gain. Shape (2, N_pixels) 

35 window_integration_correction : np.ndarray 

36 Array of shape (2,) containing the correction to apply after a windowed integration, for each gain. 

37 threshold : float 

38 Threshold to chose the waveform channel. A value above `threshold` indicates that the high gain waveform 

39 saturated and low gain should be used. 

40 

41 Returns 

42 ------- 

43 Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray] 

44 The waveform selected from each gains based on `threshold`, associated gains, pedestals and integration 

45 correction to used. The order is: 

46 - waveform : np.ndarray 

47 waveform where the appropriate gain has been selected. Shape (N_batch, N_frames, N_pixels) 

48 - gains : np.ndarray 

49 Gain to use to calibrate `waveform` (high gain when waveform_high wasn't above `threshold` and 

50 low gain otherwise). Shape (N_batch, N_pixels) 

51 - pedestals : np.ndarray 

52 Pedestals to use to calibrate `waveform`. Shape (N_batch, N_pixels) 

53 - window_integration_correction : np.ndarray 

54 Correction to use after the integration. Shape(N_batch, N_pixels) 

55 """ 

56 idx_saturated = (waveform_high > threshold).any(axis=-2, keepdims=True) 

57 return ( 

58 np.where(idx_saturated, waveform_low, waveform_high), 

59 np.where(np.squeeze(idx_saturated, -2), gains[1], gains[0]), 

60 np.where(np.squeeze(idx_saturated, -2), pedestals[1], pedestals[0]), 

61 np.where(np.squeeze(idx_saturated, -2), window_integration_correction[1], window_integration_correction[0]), 

62 ) 

63 

64 

65def calibrate(waveform: np.ndarray, gains: np.ndarray, pedestals: np.ndarray) -> np.ndarray: 

66 """Apply pedestal and gain calibration to waveforms. 

67 

68 Parameters 

69 ---------- 

70 waveform : np.ndarray 

71 Batch or single video samples of the shower events. Shape: (N_batch, N_frames, N_pixels) 

72 gains : np.ndarray 

73 For each waveform, the gains to apply to each pixel. The same gain is applied for all 

74 frames of a shower pixel. Shape: (N_batch, N_pixels). 

75 pedestals : np.ndarray 

76 For each waveform, the pedestals to apply to each pixel. The same pedestal is applied for 

77 all frames of a shower pixel. Shape (N_batch, N_pixels) 

78 

79 Returns 

80 ------- 

81 np.ndarray 

82 Calibrated waveforms (number of photo-electrons). Shape is identical to `waveform`. 

83 """ 

84 return (waveform - pedestals[..., np.newaxis, :]) * gains[..., np.newaxis, :]