Coverage for src/km3dq_common/detector_status_library.py: 0%
83 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-16 14:13 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-16 14:13 +0000
1#!/usr/bin/env python3
2import sys
3import re
4import datetime
5import pandas
6import tomli
7import urllib.request
9from .common_library import get_run_properties_from_db
12###############################################################################
13def date_to_datetime(d):
14 """
15 Convert a date-string "yyyy-mm-dd hh:mm" into a datetime
16 """
17 re_time = re.compile(r"(\d\d\d\d)-(\d\d)-(\d\d)\s(\d\d):(\d\d)")
19 spl_time = re_time.match(d)
20 if spl_time:
21 output = datetime.datetime(int(spl_time.group(1)),
22 int(spl_time.group(2)),
23 int(spl_time.group(3)),
24 int(spl_time.group(4)),
25 int(spl_time.group(5)))
26 else:
27 print(f"Wrong datetime format {d}")
28 sys.exit()
30 return output
33###############################################################################
34def get_det_run_timerange(site, dq_tag="operation"):
35 """
36 Return all the start/end of time/run for all detectors of a site
37 Data read from the lw_db/Common sftp area
38 This script is mainly used:
39 - to bypass the request to KM3DB that can be problematic for nicegui website
40 - to define the extended ranges for the operation plots
42 NB: this can be tag dependant when an analysis tag does not contain the
43 whole detector
44 """
46 tr = {}
48 tr["Any"] = {"det_start": "",
49 "first_run": 0}
51 with urllib.request.urlopen(f"https://sftp.km3net.de/data/km3dq_lw_db/{site}/detector_status_config.toml") as s_f:
52 toml = tomli.loads(s_f.read().decode("utf-8"))
54 for i_det in toml.keys():
55 # det_start: detector start - A priori equal to the previous-detector end
56 # This is the only mandatory characteristics
57 tr[i_det] = {"det_start": toml[i_det]["det_start"]}
58 # det_end: detector end - Undefined only for the current detector
59 try:
60 tr[i_det]["det_end"] = toml[i_det]["det_end"]
61 except KeyError:
62 tr[i_det]["det_end"] = "2035-01-01 00:00"
63 # det_id: detector id
64 try:
65 tr[i_det]["det_id"] = toml[i_det]["det_id"]
66 except KeyError:
67 tr[i_det]["det_id"] = "Unknown"
69 # first_run / last_run: First/last run
70 try:
71 tr[i_det]["first_run"] = toml[i_det]["first_run"]
72 try:
73 tr[i_det]["last_run"] = toml[i_det]["last_run"]
74 except KeyError:
75 tr[i_det]["last_run"] = 1e6
76 except KeyError:
77 tr[i_det]["first_run"] = 1e6
78 tr[i_det]["last_run"] = 0
79 # first_comm_run / last_comm_run: First/last commissioning run
80 try:
81 tr[i_det]["first_comm_run"] = toml[i_det]["first_comm_run"]
82 try:
83 tr[i_det]["last_comm_run"] = toml[i_det]["last_comm_run"]
84 except KeyError:
85 tr[i_det]["last_comm_run"] = 1e6
86 except KeyError:
87 tr[i_det]["first_comm_run"] = 1e6
88 tr[i_det]["last_comm_run"] = 0
89 # first_phys_run / last_phys_run: First/last commissioning run
90 try:
91 tr[i_det]["first_phys_run"] = toml[i_det]["first_phys_run"]
92 try:
93 tr[i_det]["last_phys_run"] = toml[i_det]["last_phys_run"]
94 except KeyError:
95 tr[i_det]["last_phys_run"] = 1e6
96 except KeyError:
97 tr[i_det]["first_phys_run"] = 1e6
98 tr[i_det]["last_phys_run"] = 0
100 # first/last (any) run now defined explicitly
101 # tr[i_det]["first_run"] = min(tr[i_det]["first_comm_run"], tr[i_det]["first_phys_run"])
102 # tr[i_det]["last_run"] = max(tr[i_det]["last_comm_run"], tr[i_det]["last_phys_run"])
104 # Reminder: the detector facts are chronologically ordered
105 if tr["Any"]["first_run"] == 0:
106 tr["Any"]["first_run"] = tr[i_det]["first_run"]
107 if tr["Any"]["det_start"] == "":
108 tr["Any"]["det_start"] = tr[i_det]["det_start"]
110 tr["Any"]["last_run"] = tr[i_det]["last_run"]
111 tr["Any"]["det_end"] = tr[i_det]["det_end"]
113 if ("D0ORCA018" in tr.keys()) and ("mp1" in dq_tag):
114 tr["D0ORCA018"]["det_end"] = "2023-09-01 00:00"
115 tr["D0ORCA018"]["last_run"] = 18298
117 return tr
120###############################################################################
121def get_det_run_from_date(site, date_str):
122 """
123 Input:
124 - site: ARCA/ORCA
125 - date/time with the format "yyyy-mm-dd hh:mm"
126 Output:
127 - Detector name / run number corresponding to this date/time.
128 """
129 out = {"detector": "",
130 "run": 1e5}
131 tr = get_det_run_timerange(site)
133 date_time = date_to_datetime(date_str)
134 date_time_epoch = date_time.replace(tzinfo=datetime.timezone.utc).timestamp()
136 for i_det in tr.keys():
137 d_t_0 = date_to_datetime(tr[i_det]["start"])
138 d_t_1 = date_to_datetime(tr[i_det]["end"])
140 if d_t_0 <= date_time < d_t_1:
141 out["detector"] = i_det
142 continue
143 run_prop = get_run_properties_from_db(out["detector"], "PHYS")
145 for i_run in run_prop.keys():
146 if all((date_time_epoch < float(run_prop[i_run]['UNIXSTARTTIME'])/1000.,
147 i_run < out["run"])):
148 out["run"] = i_run
150 return out