Coverage for src/km3dq_common/lw_db_signoff_library.py: 0%
64 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-07 10:42 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-07 10:42 +0000
1#! /usr/bin/env python
2###############################################################################
3import re
4import urllib.request
6from .common_library import create_ttree_from_qaqc
8from .config_library import configure_dataquality_tag
9from .config_library import configure_defect
11from .lw_db_defect_library import decode_defect_diag_byte
14###############################################################################
15def get_unsignedoff_runs(det, level = "detailed", dq_tag_name="operation"):
16 """
17 Return the unsignedoff PHYS runs based on the defect files stored on SFTP
18 ("signoff" defect type)
20 === Arguments ===
21 - det : detector name - [string] - Ex: "D0ARCA021", "D0ORCA018"...
22 - dq_tag_name : data quality tag name - [string] - Ex: "default", "neutrino2024"
24 === Output ===
25 - Dictionnary with def_[defect] as keys and a value for each affected run.
26 This value will be decoded by the decode_defect_diag_byte function.
27 Ex: {'def_daq': {}, 'def_operation': {16501: 1, 16503: 2}...}
29 """
30 # The DQ tag is needed as the signoff depends on the QAQC file that
31 # depends itself on the DQ tag
32 dq_tag = configure_dataquality_tag(dq_tag_name)
33 defects0 = configure_defect()
35 if "ORCA" in det:
36 site = "ORCA"
37 else:
38 site = "ARCA"
40 (n1, _) = create_ttree_from_qaqc(det, ["run"], "qaqc_sftp", dq_tag)
42 re_line = re.compile(r"\s*([0-9]+)\s*\|.*")
44 res = {}
45 # Initialize the output for all runs as not yet signed off
46 for _, irun in n1.iterrows(): # One entry per run
47 res[irun["run"]] = []
48 for i_diag in defects0["bit"]["signoff"].keys():
49 res[irun["run"]].append(i_diag)
51 # Now scan the defect files and removed the run signed off
52 for i_diag in defects0["bit"]["signoff"].keys():
53 lines = []
54 defect_url = (
55 "https://sftp.km3net.de/data/km3dq_lw_db/"
56 f"{site}/{det}/Defects/{dq_tag['def_tag']}/"
57 f"signoff_{i_diag}.txt"
58 )
59 try:
60 with urllib.request.urlopen(defect_url) as def_file:
61 tmp = (def_file.read()).split(b"\n")
62 for i_line in tmp:
63 if i_line != "":
64 lines.append(i_line.decode("utf-8"))
65 except urllib.error.URLError:
66 # No defect file found
67 continue
69 for i_line in lines:
70 r_m = re_line.match(i_line)
71 if r_m is not None:
72 run_nb = int(r_m.group(1))
73 # Run signed off not (yet?) in QAQC
74 if run_nb not in res.keys():
75 continue
76 signoff_nature_bit = 1 << defects0["bit"]["signoff"][i_diag]
77 signoff_nature = decode_defect_diag_byte(signoff_nature_bit, "signoff")
78 for i_nature in signoff_nature.split(" / "):
79 if i_nature != "":
80 res[run_nb].remove(i_nature)
82 if len(res[run_nb]) == 0:
83 res.pop(run_nb)
85 if level == "detailed": # Return all unsigned run
86 return res
88 if level == "compact": # Returns intervals
89 unsign = list(res.keys())
90 unsign.sort()
91 res_str = ""
93 for i_r in unsign:
94 try:
95 if i_r == interv_upp + 1:
96 interv_upp = i_r
97 else:
98 res_str += F"{interv_low} - {interv_upp} / "
99 interv_low = i_r
100 interv_upp = i_r
101 except NameError:
102 interv_low = i_r
103 interv_upp = i_r
105 try:
106 res_str += F"{interv_low} - {interv_upp} / "
107 except NameError:
108 pass
110 return res_str