Skip to content

Commit 5d1980a

Browse files
vmarandonjlenain
andauthored
Add tools to read the DB infos (#293)
* Add tools to read the DB infos * Use `logging` instead of print * Fix docstrings for CI/docs * Overwrite `np.array.prod` wit custom docstring, to please Sphinx autodoc... * add a protection to ignore table that can't be properly read instead of crashing * correct typo * modification to please the pre-commit hooks * Example notebook to use the dbhandler * test * try to please flake8 --------- Co-authored-by: Jean-Philippe Lenain <jlenain@in2p3.fr>
1 parent 3eb9781 commit 5d1980a

3 files changed

Lines changed: 1255 additions & 0 deletions

File tree

notebooks/ExampleDBHandler.py

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
# ---
2+
# jupyter:
3+
# jupytext:
4+
# text_representation:
5+
# extension: .py
6+
# format_name: percent
7+
# format_version: '1.3'
8+
# jupytext_version: 1.14.6
9+
# kernelspec:
10+
# display_name: nectardev2
11+
# language: python
12+
# name: python3
13+
# ---
14+
15+
# %%
16+
try:
17+
import datetime
18+
import warnings
19+
20+
import matplotlib.pyplot as plt
21+
import numpy as np
22+
from ctapipe.coordinates import EngineeringCameraFrame
23+
from ctapipe.instrument import CameraGeometry
24+
from ctapipe.visualization import CameraDisplay
25+
from dateutil.parser import ParserError, parse
26+
from matplotlib import dates
27+
28+
# in vmarandon scripts at the moment
29+
from nectarchain.utils.dbhandler import DBInfos, to_datetime
30+
31+
# from CalibrationCameraDisplay import CalibrationCameraDisplay
32+
# from Utils import GetCamera
33+
34+
except ImportError as err:
35+
print(err)
36+
37+
try:
38+
from ctapipe.instrument.warnings import FromNameWarning
39+
40+
CTAPipeWarningExist = True
41+
except ImportError:
42+
CTAPipeWarningExist = False
43+
44+
45+
def GetCamera(cam_name="NectarCam-003"): # Copied from my Utils code
46+
if CTAPipeWarningExist:
47+
with warnings.catch_warnings():
48+
warnings.filterwarnings(action="ignore", category=FromNameWarning)
49+
# Let's ignore the warning for the moment
50+
cam = CameraGeometry.from_name(cam_name).transform_to(
51+
EngineeringCameraFrame()
52+
)
53+
else:
54+
cam = CameraGeometry.from_name(cam_name).transform_to(EngineeringCameraFrame())
55+
56+
return cam
57+
58+
59+
# %%
60+
# path where the data are if using a run number
61+
path = "/Users/vm273425/Programs/NectarCAM/data_ssd/camera2/"
62+
63+
# path of where is the sqlite file (can be in a sub-directory)
64+
db_data_path = "/Users/vm273425/Programs/NectarCAM/data_ssd/camera2/monitoring"
65+
66+
telid = 2
67+
68+
# %%
69+
# define the time interval
70+
try:
71+
# expected date in UTC
72+
begin_time = to_datetime(parse("2025-11-10 16:00:00"))
73+
end_time = to_datetime(parse("2025-11-11 14:00:00"))
74+
except ParserError as err:
75+
print(err)
76+
77+
print(begin_time, end_time)
78+
79+
# %%
80+
# Create DB Instance
81+
dbinfos = DBInfos.init_from_time(
82+
begin_time, end_time, dbpath=db_data_path, verbose=False
83+
)
84+
85+
# Could be done using a run number way also, it will look for a run:
86+
# dbinfos = DBInfos.init_from_run(run, path=path, dbpath=db_data_path,verbose=False)
87+
88+
# %%
89+
# show available tables
90+
dbinfos.show_available_tables()
91+
92+
# %%
93+
# Show available infos per table
94+
dbinfos.show_available_infos()
95+
96+
# %%
97+
# Load the information in memory (can be long :-( )
98+
dbinfos.connect(
99+
"monitoring_ffcls", "monitoring_drawer_temperatures", "monitoring_channel_voltages"
100+
) # Add any table that are present in the DB
101+
# dbinfos.connect("*") # Load everything
102+
103+
# %%
104+
# Retrieve temperature of the modules
105+
temperatures = dbinfos.tel[telid].monitoring_drawer_temperatures.tfeb1.datas
106+
temperatures_times = dbinfos.tel[telid].monitoring_drawer_temperatures.tfeb1.times
107+
print(type(temperatures))
108+
109+
# %%
110+
# Interpolation can be done with the method "at"
111+
delta_t = (end_time - begin_time).total_seconds()
112+
steps = 100
113+
114+
interp_times = [
115+
begin_time + n * datetime.timedelta(seconds=delta_t / steps) for n in range(steps)
116+
]
117+
interp_tfeb1_temps = dbinfos.tel[telid].monitoring_drawer_temperatures.tfeb1.at(
118+
interp_times
119+
)
120+
121+
pix = 1855 // 2
122+
central_interp_tfeb1 = interp_tfeb1_temps.to_pixel()[pix]
123+
central_datas_tfeb1 = dbinfos.tel[
124+
telid
125+
].monitoring_drawer_temperatures.tfeb1.datas.to_pixel()[pix]
126+
central_times_tfeb1 = dbinfos.tel[telid].monitoring_drawer_temperatures.tfeb1.times
127+
128+
plt.figure(figsize=(18, 6))
129+
plt.plot(central_times_tfeb1, central_datas_tfeb1)
130+
plt.plot(interp_times, central_interp_tfeb1, "o")
131+
132+
# %%
133+
nrows = 1
134+
ncols = 1
135+
size_y = 4
136+
size_x = 3 * size_y
137+
fig, axs = plt.subplots(
138+
nrows=nrows, ncols=ncols, figsize=(size_x * ncols, size_y * nrows)
139+
)
140+
141+
ax = axs
142+
modules = [124, 132, 140]
143+
for m in modules:
144+
ax.plot(temperatures_times, temperatures[m], label=f"Module: {m}")
145+
ax.set_xlabel("Time (UTC)")
146+
ax.set_ylabel("FEB 1 Temperature")
147+
ax.set_title("FEB 1 Temperature Evolution")
148+
ax.xaxis.set_major_formatter(dates.DateFormatter("%d/%m %H:%M"))
149+
ax.tick_params("x", rotation=30)
150+
ax.legend()
151+
ax.grid()
152+
fig.tight_layout()
153+
154+
# %%
155+
# Plot temperature in the camera
156+
157+
pix_temperature = np.nanmean(temperatures, axis=-1).to_pixel()
158+
# temperatures is of type ModuleArray
159+
# this is a numpy array with an additionnal function to convert to pixel
160+
161+
nrows = 1
162+
ncols = 1
163+
size = 6
164+
fig, axs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(size * ncols, size * nrows))
165+
cam = CameraDisplay(
166+
geometry=GetCamera(),
167+
cmap="turbo",
168+
image=pix_temperature,
169+
title="FEB 1 Temperature",
170+
ax=axs,
171+
show_frame=False,
172+
allow_pick=True,
173+
norm="lin",
174+
)
175+
cam.highlight_pixels(range(1855), color="grey", linewidth=0.2)
176+
# CalibrationCameraDisplay is an overload of the CameraDisplay
177+
# that can highlight differently pixels and easily add function
178+
# if pixels are clicked
179+
cam.add_colorbar()
180+
fig.tight_layout()
181+
# cam1.colorbar.set_label(f'%')
182+
183+
# %%
184+
# Retrieve hv of the pixels
185+
hvs = dbinfos.tel[telid].monitoring_channel_voltages.voltage.datas
186+
hvs_times = dbinfos.tel[telid].monitoring_channel_voltages.voltage.times
187+
print(type(hvs))
188+
189+
# %%
190+
nrows = 1
191+
ncols = 1
192+
size_y = 4
193+
size_x = 3 * size_y
194+
fig, axs = plt.subplots(
195+
nrows=nrows, ncols=ncols, figsize=(size_x * ncols, size_y * nrows)
196+
)
197+
198+
ax = axs
199+
pixels = [124 * 7 + 3, 132 * 7 + 3, 140 * 7 + 3]
200+
for p in pixels:
201+
ax.plot(hvs_times, hvs[p], label=f"Pixel: {p}")
202+
ax.set_xlabel("Time (UTC)")
203+
ax.set_ylabel("HV (V)")
204+
ax.set_title("HV Evolution")
205+
ax.xaxis.set_major_formatter(dates.DateFormatter("%d/%m %H:%M"))
206+
ax.tick_params("x", rotation=30)
207+
ax.legend()
208+
ax.grid()
209+
fig.tight_layout()
210+
211+
# %%
212+
# Plot HV in the camera
213+
214+
hv_means = np.nanmean(hvs, where=hvs > 400, axis=-1)
215+
hv_stds = np.nanstd(hvs, where=hvs > 400, axis=-1, ddof=1)
216+
217+
# hv is of type PixelArray which is a numpy array
218+
# with additionnal feature
219+
220+
nrows = 1
221+
ncols = 2
222+
size = 6
223+
fig, axs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(size * ncols, size * nrows))
224+
225+
ax = axs[0]
226+
cam = CameraDisplay(
227+
geometry=GetCamera(),
228+
cmap="turbo",
229+
image=hv_means,
230+
title="Average HV",
231+
ax=ax,
232+
show_frame=False,
233+
allow_pick=True,
234+
norm="lin",
235+
)
236+
cam.highlight_pixels(range(1855), color="grey", linewidth=0.2)
237+
cam.add_colorbar()
238+
239+
ax = axs[1]
240+
cams = CameraDisplay(
241+
geometry=GetCamera(),
242+
cmap="turbo",
243+
image=hv_stds,
244+
title="Std HV",
245+
ax=ax,
246+
show_frame=False,
247+
allow_pick=True,
248+
norm="lin",
249+
)
250+
cams.highlight_pixels(range(1855), color="grey", linewidth=0.2)
251+
cams.add_colorbar()
252+
# CalibrationCameraDisplay is an overload of the CameraDisplay
253+
# that can highlight differently pixels and easily add function
254+
# if pixels are clicked
255+
256+
257+
fig.tight_layout()
258+
259+
# %%

0 commit comments

Comments
 (0)