Coverage for polars_analysis / analysis / constants.py: 96%

71 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-04-30 10:50 -0400

1import logging 

2from pathlib import Path 

3from typing import List 

4 

5import numpy as np 

6 

7# Instantiate logger 

8log = logging.getLogger(__name__) 

9 

10# FIXME Need to have some documentation/docstring for these 

11# Put doc string under constant 

12 

13ROOTDIR = Path(__file__).parent.parent.parent 

14 

15N_SAMPLE_MAX = int(4.9 * 10**6) 

16OVERFLOW_BIT = 2**15 - 1 

17SATURATION_MARGIN = 150 

18 

19ADC_BITS = 15 

20HI = "hi" 

21LO = "lo" 

22GAINS = [HI, LO] 

23"""String values for high and low gain""" 

24 

25CUTOFF_RMS = dict(lo=4, hi=80) 

26 

27 

28# The ADC operates at 40MHz, and our AWG producing pulses operates at 1200MHz 

29# This means we can have pulses coming in at 1200/40 = 30 different phases relative to the ADC clock 

30# By design the phase 15 corresponds when the ADC samples closest to the peak of the pulse 

31N_PHASES = 30 

32PEAK_INDEX = 30 

33PHASE_SHIFT_PEAK = 15 

34PHASE_SHIFT0 = -PHASE_SHIFT_PEAK 

35PULSES_PER_TRAIN = 30 

36SAMPLES_PER_PULSE = 192 

37TRIGGER_OFFSET = 2432 

38PULSE_TRAIN_PERIOD = PULSES_PER_TRAIN * SAMPLES_PER_PULSE + TRIGGER_OFFSET 

39START = 0 

40START_MEAS = 0 

41TRIGGER_LEVEL = 0.3 

42LO_GAIN_AWG_AMP_VAL = 6.0 # Volts 

43LO_GAIN_AWG_AMP_STR = "6.0" # Volts 

44LO_GAIN_ATTN_VAL = 7.0 # dB 

45LO_GAIN_ATTN_STR = "7.0" # dB 

46 

47HI_GAIN_AWG_AMP_VAL = 1.5 # Volts 

48HI_GAIN_AWG_AMP_STR = "1.5" # Volts 

49HI_GAIN_ATTN_VAL = 20.0 # dB 

50HI_GAIN_ATTN_STR = "20.0" # dB 

51 

52# Attenuations to use as OFC source for multi-run linearity plots 

53MIDDLE_ATTENUATIONS = [30.0, 35.0] 

54 

55BASELINE_CUSHION = 20 # TODO is 0 viable? 

56 

57FLX_FRQ = 40.0789 # MHz JDL:Not sure where this comes from 

58"""Felix sampling frequency in MHz""" 

59 

60# From Victor (Feb 13, 2025) 

61FLX_FRQ_40MHZ = 40 # MHz 

62FLX_FRQ_EXT = 40.08016 # MHz 

63 

64# FELIX GUI int --> trigger rates (Hz) 

65# Use run dependent function below 

66FELIX_TRIGGER_RATE = { 

67 1: FLX_FRQ_40MHZ / 2**18 * 1e6, 

68 2: FLX_FRQ_40MHZ / 2**17 * 1e6, 

69 3: FLX_FRQ_40MHZ / 2**16 * 1e6, 

70 4: FLX_FRQ_40MHZ / 2**15 * 1e6, 

71 5: FLX_FRQ_40MHZ / 2**14 * 1e6, 

72 6: FLX_FRQ_40MHZ / 2**13 * 1e6, 

73} 

74 

75 

76def felix_trigger_rate(run_number: int, trigger_rate_bit: int, bnl_data: bool = False): 

77 """ 

78 Converts the trigger rate bit shift into Hz, which is FW (run number) 

79 dependent. 

80 """ 

81 

82 if trigger_rate_bit < 1 or trigger_rate_bit > len(FELIX_TRIGGER_RATE): 

83 log.error(f"Unknown trigger bit {trigger_rate_bit}, returning None.") 

84 return None 

85 

86 if run_number < 8284 and run_number != 8099 and not bnl_data: 

87 return FELIX_TRIGGER_RATE[trigger_rate_bit] 

88 else: 

89 return FELIX_TRIGGER_RATE[7 - trigger_rate_bit] 

90 

91 

92N_BCID = 3564 

93 

94AWG_FRQ = 1200.0 # MHz 

95SEC_PER_SAMPLE = (1.0 / FLX_FRQ_EXT) * 1000 # ns 

96OFFSET = SEC_PER_SAMPLE / N_PHASES # ns 

97 

98 

99# Pedestal 

100PED_MIN_CHAN_LIST = [0, 0, 64, 0, 16, 32, 48, 64, 80, 96, 112] 

101"""First channel to include in correlation matrix plot.""" 

102PED_N_CHAN_LIST = [128, 64, 64, 16, 16, 16, 16, 16, 16, 16, 16] 

103"""Number of channels to include in correlation matrix plot.""" 

104 

105FFT_SIZE = 2**10 

106 

107# For pedestal gaussian fit chi2 calculation: 

108CHI2_THRESHOLD = 0 # if 0, will compute using polars_analysis.plotting.pedestal_plotting calc_chi2_threshold 

109 

110# Cutoff to call a run an extended readout 

111EXTENDED_PEDESTAL_TRIGGER_WINDOW_N = 1000 

112 

113 

114def _calc_interleaved_times(): 

115 # initialize array of times 

116 times = np.zeros((N_PHASES, SAMPLES_PER_PULSE)) 

117 # loop through phases, assiging a finely spaced time to each sample using FLX + AWG frequencies 

118 for phase in range(N_PHASES): 

119 times[phase, :] = (np.arange(SAMPLES_PER_PULSE) * SEC_PER_SAMPLE + phase * OFFSET) % ( 

120 PULSES_PER_TRAIN * SEC_PER_SAMPLE * SAMPLES_PER_PULSE 

121 ) 

122 

123 time_indices_sorted = times.flatten().argsort() 

124 interleaved_times = times.flatten()[time_indices_sorted] 

125 

126 return time_indices_sorted, interleaved_times 

127 

128 

129TIME_INDICES_SORTED, INTERLEAVED_TIMES = _calc_interleaved_times() 

130 

131# Noise stability temperature correction analysis 

132TEMPERATURE_SOURCES: List[str] = [""] 

133ALL_TEMPERATURE_SOURCES: List[str] = ( 

134 ["", "lab_environment", "bpol48", "thermistors", "lab_temp", "crate_temp", "PAT1", "PAT2"] 

135 + [f"TEMP_T{i}" for i in range(1, 7)] 

136 + [f"TEMP_B{i}" for i in range(1, 7)] 

137) 

138TEMPERATURE_SOURCES_WWW: List[str] = [""] 

139ALL_TEMPERATURE_SOURCES_WWW: List[str] = ( 

140 ["", "_lab_environment", "_bpol48", "_thermistors", "_lab_temp", "_crate_temp", "_PAT1", "_PAT2"] 

141 + [f"_TEMP_T{i}" for i in range(1, 7)] 

142 + [f"_TEMP_B{i}" for i in range(1, 7)] 

143)