Coverage for polars_analysis / plotting / frame_plotting.py: 58%
170 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-13 13:37 -0400
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-13 13:37 -0400
1import logging
2from pathlib import Path
4import matplotlib
6matplotlib.use("agg")
7import matplotlib.pyplot as plt
8import numpy as np
10from polars_analysis.analysis import constants
11from polars_analysis.plotting import helper
13# Instantiate logger
14log = logging.getLogger(__name__)
16"""
17Functions for frame analysis plotting.
18"""
21def plot_mean_v_time(
22 x,
23 y,
24 plot_dir,
25 info,
26):
27 # Mean v time
28 plt.figure(figsize=(15, 4))
29 plt.plot(x, y.T)
30 plt.title(helper.plot_summary_string(name="Pedestal Mean vs Time", info=info))
31 plt.xlabel("Time [s]")
32 plt.ylabel("Mean ADC Counts")
33 plt.tight_layout()
34 plt.savefig(Path(plot_dir / f"mean_v_time_{info.gain}.png"))
35 plt.cla()
36 plt.clf()
37 plt.close()
40def plot_60hz_power(
41 freq,
42 psd,
43 plot_dir,
44 info,
45 channels,
46):
47 # Power in 60 Hz
48 plt.figure(figsize=(15, 4))
49 min = np.where(freq > 59)[0][0]
50 max = np.where(freq < 61)[0][-1]
51 if np.abs(max - min) < 2:
52 log.error("60 Hz not found")
53 return
54 sixtyhz = psd[:, min:max].max(axis=1)
56 arr = np.zeros(128)
57 for index, channel in enumerate(channels):
58 arr[channel] = sixtyhz[index]
60 plt.xticks(np.arange(0, 128, 4), rotation=70)
61 plt.bar(np.arange(128), arr, fill=False)
62 plt.xlabel("Channel")
63 plt.ylabel("Power [ADC Counts ^ 2 / Hz]")
64 plt.title(helper.plot_summary_string(name="60 Hz Power", info=info))
65 plt.grid()
66 plt.tight_layout()
67 plt.yscale("log")
68 plt.savefig(plot_dir / f"fft_60hz_{info.gain}.png")
69 plt.cla()
70 plt.clf()
71 plt.close()
74def plot_adc_full_bcid(
75 channel,
76 h_bcid,
77 plot_dir,
78 info,
79):
80 # vs BCID plot
81 plt.figure(figsize=(15, 4))
83 plt.plot(np.arange(constants.N_BCID), h_bcid[0], ".")
84 plt.title(helper.plot_summary_string(name="Histogram of ADC BCIDs", info=info))
85 plt.xlabel("BCID")
86 plt.ylabel("Count")
87 # plt.xlim(0, 64)
88 plt.grid()
89 plt.tight_layout()
90 plt.savefig(Path(plot_dir / f"adc_bcid_histo_ch{channel}_{info.gain}.png"))
91 plt.cla()
92 plt.clf()
93 plt.close()
96def plot_mean_v_bcid(
97 channel,
98 x_bcid,
99 h_bcid,
100 h_weighted,
101 plot_dir,
102 info,
103):
104 # mean vs bcid
105 plt.figure(figsize=(15, 4))
107 plt.plot(x_bcid, h_weighted / h_bcid)
108 plt.title(helper.plot_summary_string(name="Pedestal mean vs ADC BCID", info=info))
109 plt.xlabel("BCID")
110 plt.ylabel("Mean ADC Counts")
111 plt.tight_layout()
112 plt.savefig(Path(plot_dir / f"mean_v_bcid_ch{channel}_{info.gain}.png"))
113 plt.cla()
114 plt.clf()
115 plt.close()
118def plot_fft_mean_v_bcid(
119 channel,
120 freq_bcid,
121 psd_bcid,
122 plot_dir,
123 info,
124):
125 # FFT of mean vs bcid
126 plt.figure(figsize=(15, 4))
128 plt.plot(freq_bcid, psd_bcid)
129 plt.title(helper.plot_summary_string(name="FFT of pedestal mean vs ADC BCID", info=info))
130 plt.xlabel("Freq. [1/BCID]")
131 plt.ylabel("Power")
132 plt.tight_layout()
133 plt.savefig(Path(plot_dir / f"fft_bcid_ch{channel}_{info.gain}.png"))
134 plt.cla()
135 plt.clf()
136 plt.close()
139def plot_mean_v_time_ch(
140 channel,
141 x,
142 y,
143 plot_dir,
144 info,
145):
146 # mean v time
147 plt.figure(figsize=(15, 4))
148 plt.plot(x, y)
149 plt.title(helper.plot_summary_string(name="Pedestal mean vs time", info=info))
150 plt.xlabel("Time [s]")
151 plt.ylabel("Mean ADC Counts")
152 plt.tight_layout()
153 plt.savefig(Path(plot_dir / f"mean_v_time_ch{channel}_{info.gain}.png"))
154 plt.cla()
155 plt.clf()
156 plt.close()
159def plot_mean_v_time_ch_zoom(
160 channel,
161 x,
162 y,
163 plot_dir,
164 info,
165 time_window=5, # seconds
166):
167 cutoff = int(np.abs(time_window - x).argmin())
168 # mean v time zoom to first Ns
169 plt.figure(figsize=(15, 4))
170 plt.plot(x[:cutoff], y[:cutoff])
171 plt.title(helper.plot_summary_string(name=f"Pedestal mean vs time: {time_window}s", info=info))
172 plt.xlabel("Time [s]")
173 plt.ylabel("Mean ADC Counts")
174 plt.tight_layout()
175 plt.savefig(Path(plot_dir / f"mean_v_time_ch{channel}_{info.gain}_zoom{time_window}s.png"))
176 plt.cla()
177 plt.clf()
178 plt.close()
181def plot_std_v_time_ch(
182 channel,
183 x,
184 y,
185 plot_dir,
186 info,
187):
188 # std v time
189 plt.figure(figsize=(15, 4))
190 plt.plot(x, y)
191 plt.title(helper.plot_summary_string(name="Pedestal std vs time", info=info))
192 plt.xlabel("Time [s]")
193 plt.ylabel("Mean ADC Counts")
194 plt.tight_layout()
195 plt.savefig(Path(plot_dir / f"std_v_time_ch{channel}_{info.gain}.png"))
196 plt.cla()
197 plt.clf()
198 plt.close()
201def plot_std_v_time_ch_zoom(
202 channel,
203 x,
204 y,
205 plot_dir,
206 info,
207 time_window=5, # seconds
208):
209 cutoff = int(np.abs(time_window - x).argmin())
211 # std v time zoom to first 5s
212 plt.figure(figsize=(15, 4))
213 plt.plot(x[:cutoff], y[:cutoff])
214 plt.title(helper.plot_summary_string(name=f"Pedestal std vs time: {time_window}s", info=info))
215 plt.xlabel("Time [s]")
216 plt.ylabel("Mean ADC Counts")
217 plt.tight_layout()
218 plt.savefig(Path(plot_dir / f"std_v_time_ch{channel}_{info.gain}_zoom{time_window}s.png"))
219 plt.cla()
220 plt.clf()
221 plt.close()
224def plot_fft_mean_v_time(
225 channel,
226 freq,
227 psd,
228 plot_dir,
229 info,
230):
231 # FFT
232 plt.figure(figsize=(15, 4))
233 plt.plot(freq, psd)
234 # plt.ylim(1e-5, 15)
235 plt.yscale("log")
236 plt.title(helper.plot_summary_string(name="FFT of mean vs time", info=info))
237 plt.xlabel("Freq. [Hz]")
238 plt.ylabel("Power")
239 plt.tight_layout()
240 plt.savefig(Path(plot_dir / f"fft_mean_v_time_ch{channel}_{info.gain}.png"))
241 plt.cla()
242 plt.clf()
243 plt.close()
246def plot_window_stds(channel, plot_dir, stds, samples_rms, info):
247 plt.figure(figsize=(15, 4))
248 plt.title(helper.plot_summary_string(name="Window STD vs Total STD", info=info))
250 bins = np.arange(0, 20, 1)
251 _ = plt.hist(stds, bins=bins.tolist(), align="mid", edgecolor="black", label="Window STDs")
253 plt.text(0.8, 0.8, f"Window STD mu={np.mean(stds)}\nSamples STD={samples_rms}", transform=plt.gca().transAxes)
255 plt.xlabel("ADC Counts")
256 plt.ylabel("Bin Count")
258 plt.tight_layout()
259 plt.savefig(Path(plot_dir / f"window_std_total_std_ch{channel}_{info.gain}.png"))
260 plt.cla()
261 plt.clf()
262 plt.close()
265def plot_window_means(channel, plot_dir, window_means, stds, samples_rms, trigger_window, info):
266 plt.figure(figsize=(10, 4))
267 plt.title(helper.plot_summary_string(name="Window Means - Global Mean", info=info))
269 mean_of_stds = np.mean(stds)
270 mean_of_means = np.mean(window_means)
271 window_means -= mean_of_means
273 bins = np.arange(-10, 10, 0.2)
274 _ = plt.hist(window_means, bins=bins.tolist(), align="mid", edgecolor="black", label="Window Means - Global Mean")
276 plt.text(
277 0.7,
278 0.6,
279 f"""N Windows = {len(window_means)}
280Window size = {trigger_window}
281[1]: STD(Window Means) = {np.std(window_means):.2f}
282[2]: STD(Samples) = {samples_rms:.2f}
283[3]: Mean(Indiv. Window STD) = {mean_of_stds:.2f}
284√([2]²-[3]²)={np.sqrt(samples_rms**2 - mean_of_stds**2):.2f}
285""",
286 transform=plt.gca().transAxes,
287 )
289 # with open("baseline_variation.csv", "a") as f:
290 # f.write(f"{channel},{info.gain},{np.sqrt(samples_rms**2 - mean_of_stds**2):.2f}\n")
292 bin_centers = 0.5 * (bins[1:] + bins[:-1])
293 fit_pars = helper.calc_gaussian(window_means, bins)
294 gauss_fit = helper.gauss(bin_centers, mu=fit_pars[0], sigma=fit_pars[2], N=fit_pars[4])
296 plt.plot(
297 bin_centers,
298 gauss_fit,
299 color="r",
300 label=rf"""$\mu$ = {fit_pars[0]:.03f} $\pm$ {fit_pars[1]:.03f},
301$\sigma$ = {fit_pars[2]:.03f} $\pm$ {fit_pars[3]:.03f}""",
302 )
303 plt.legend(loc="upper left")
305 plt.xlabel("ADC Counts")
306 plt.ylabel("Bin Count")
308 plt.tight_layout()
309 plt.savefig(Path(plot_dir / f"window_means_ch{channel}_{info.gain}.png"))
310 plt.cla()
311 plt.clf()
312 plt.close()