DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
file_quality_checker.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3from hdf5libs import HDF5RawDataFile
4
5import detchannelmaps
6import daqdataformats
7import detdataformats
8import gc
9import glob
10import os
11from rawdatautils.unpack.wib2 import *
13import sys
14import time
15import traceback
16
17import click
18import time
19import numpy as np
20
21@click.command()
22@click.argument('filenames', nargs=-1)
23def main(filenames):
24 """
25This script provides a high-level summary of the records in an output HDF5 file and the fragments which they contain.
26
27It simply takes a filename, or list of filenames, as argument(s) and summarizes each one sequentially.
28
29For info on how to interpret the output, look at rawdatautils documentation:
30https://dune-daq-sw.readthedocs.io/en/latest/packages/rawdatautils/
31
32"""
33
34 for filename in filenames:
35
36 if not os.path.exists(filename):
37 sys.exit(f"ERROR: file \"{filename}\" doesn't appear to exist")
38
39 try:
40 h5file = HDF5RawDataFile(filename)
41 except:
42 print(traceback.format_exc())
43 sys.exit(f"ERROR: file \"{filename}\" couldn't be opened; is it an HDF5 file?")
44
45 print(f"Processing {filename}...")
46
47 is_trigger_records = True
48
49 try:
50 records = h5file.get_all_trigger_record_ids()
51 except RuntimeError:
52 is_trigger_records = False
53 except:
54 print(traceback.format_exc())
55 sys.exit("ERROR: Something went wrong when calling h5file.get_all_trigger_record_ids(); file may contain junk data or be corrupted. Exiting...\n")
56
57 if not is_trigger_records:
58 try:
59 records = h5file.get_all_timeslice_ids()
60 except RuntimeError:
61 sys.exit(f"Neither get_all_trigger_record_ids() nor get_all_timeslice_ids() returned records. Exiting...\n")
62 except:
63 print(traceback.format_exc())
64 sys.exit("ERROR: Something went wrong when calling h5file.get_all_timeslice_ids(); file may contain junk data or be corrupted. Exiting...\n")
65
66 if is_trigger_records:
67 print(f'Will process {len(records)} trigger records.')
68 else:
69 print(f'Will process {len(records)} timeslice records.')
70
71 sequence_ids = []
72 record_ids = []
73 tr_global_stats = {}
74
75 assumed_sequence_id_step = -1
76 assumed_record_id_step = -1
77 first_sequence_id = -1
78 first_record_id = -1
79
80 for i_r, r in enumerate(records):
81
82 for i_quadrant in range(1,4):
83 if i_r == i_quadrant * int(len(records)/4):
84 print(f"Processed {i_r} of {len(records)} records...")
85
86 record_ids.append(r[0])
87 sequence_ids.append(r[1])
88
89 if i_r == 0:
90 first_record_id = r[0]
91 first_sequence_id = r[1]
92 elif i_r == 1:
93 assumed_record_id_step = r[0] - first_record_id
94 assumed_sequence_id_step = r[1] - first_sequence_id
95
96 dset_paths = h5file.get_fragment_dataset_paths(r)
97 tr_stats = {}
98
99 for dset_path in dset_paths:
100 frag = h5file.get_frag(dset_path)
101 if frag.get_fragment_type() in tr_stats:
102 tr_stats[ frag.get_fragment_type()]["count" ] += 1
103 if frag.get_size() > tr_stats[ frag.get_fragment_type() ]["max_size" ]:
104 tr_stats[ frag.get_fragment_type() ][ "max_size" ] = frag.get_size()
105 if frag.get_size() < tr_stats[ frag.get_fragment_type()]["min_size" ]:
106 tr_stats[ frag.get_fragment_type()]["min_size" ] = frag.get_size()
107 else:
108 tr_stats[ frag.get_fragment_type() ] = { "count": 1, "nonzero_error_bits_count": 0, "max_size": frag.get_size(), "min_size": frag.get_size() }
109
110 if frag.get_header().error_bits != 0:
111 tr_stats[ frag.get_fragment_type() ]["nonzero_error_bits_count"] += 1
112
113
114 for frag_type in tr_stats:
115 if frag_type in tr_global_stats:
116 if tr_stats[frag_type]["count"] > tr_global_stats[frag_type]["max_count"]:
117 tr_global_stats[frag_type]["max_count"] = tr_stats[frag_type]["count"]
118 if tr_stats[frag_type]["count"] < tr_global_stats[frag_type]["min_count"]:
119 tr_global_stats[frag_type]["min_count"] = tr_stats[frag_type]["count"]
120 if tr_stats[frag_type]["nonzero_error_bits_count"] > tr_global_stats[frag_type]["nonzero_error_bits_max_count"]:
121 tr_global_stats[frag_type]["nonzero_error_bits_max_count"] = tr_stats[frag_type]["nonzero_error_bits_count"]
122 if tr_stats[frag_type]["nonzero_error_bits_count"] < tr_global_stats[frag_type]["nonzero_error_bits_min_count"]:
123 tr_global_stats[frag_type]["nonzero_error_bits_min_count"] = tr_stats[frag_type]["nonzero_error_bits_count"]
124
125 if tr_stats[frag_type]["max_size"] > tr_global_stats[frag_type]["max_size"]:
126 tr_global_stats[frag_type]["max_size"] = tr_stats[frag_type]["max_size"]
127 if tr_stats[frag_type]["min_size"] < tr_global_stats[frag_type]["min_size"]:
128 tr_global_stats[frag_type]["min_size"] = tr_stats[frag_type]["min_size"]
129
130 else:
131 tr_global_stats[frag_type] = { "max_count": tr_stats[frag_type]["count"],
132 "min_count": tr_stats[frag_type]["count"],
133 "max_size": tr_stats[frag_type]["max_size"],
134 "min_size": tr_stats[frag_type]["min_size"],
135 "nonzero_error_bits_min_count": tr_stats[frag_type]["nonzero_error_bits_count"],
136 "nonzero_error_bits_max_count": tr_stats[frag_type]["nonzero_error_bits_count"]
137 }
138
139 print(f"Processed {len(records)} of {len(records)} records...")
140 print("")
141
142 sequence_ids_ok = True
143 for i_s, seqid in enumerate(sequence_ids):
144 if i_s > 0:
145 if seqid - sequence_ids[i_s - 1] != assumed_sequence_id_step:
146 sequence_ids_ok = False
147
148 record_ids_ok = True
149 for i_r, recid in enumerate(record_ids):
150 if i_r > 0:
151 if recid - record_ids[i_r - 1] != assumed_record_id_step:
152 record_ids_ok = False
153
154 if record_ids_ok:
155 print(f"Progression of record ids over records looks ok (expected change of {assumed_record_id_step} for each new record)")
156 else:
157 print("Non-constant progression of record ids over records. This may or may not be a problem.")
158 print(" ".join([str(recid) for recid in record_ids]))
159
160 if sequence_ids_ok:
161 print(f"Progression of sequence ids over records looks ok (expected change of {assumed_sequence_id_step} for each new record)")
162 else:
163 print("Non-contant progression of sequence ids over records. This may or may not be a problem.")
164 print(" ".join([str(seqid) for seqid in sequence_ids]))
165
166 print("")
167
168
169 frag_type_phrase_length = max([len(str(fragname)) - len("FragmentType.") for fragname in tr_global_stats]) + 1
170 max_count_phrase = "max # in rec"
171 min_count_phrase = "min # in rec"
172 max_size_phrase = "largest (B)"
173 min_size_phrase = "smallest (B)"
174 max_errs_phrase = "max err in rec"
175 min_errs_phrase = "min err in rec"
176
177 fmtstring=f"%-{frag_type_phrase_length}s|%s|%s|%s|%s|%s|%s|"
178 print(fmtstring % (" FragType ", min_count_phrase, max_count_phrase, min_size_phrase, max_size_phrase, min_errs_phrase, max_errs_phrase))
179
180 divider = "-" * (frag_type_phrase_length + len(min_count_phrase) + len(max_count_phrase) +
181 len(min_size_phrase) + len(max_size_phrase) + len(max_errs_phrase) + len(min_errs_phrase) + 7)
182 print(divider)
183
184 for frag_type in tr_global_stats:
185 fmtstring = f"%-{frag_type_phrase_length}s|%-{len(min_count_phrase)}s|%-{len(max_count_phrase)}s|%-{len(min_size_phrase)}s|%-{len(max_size_phrase)}s|%-{len(min_errs_phrase)}s|%-{len(max_errs_phrase)}s|"
186 print(fmtstring % (str(frag_type).replace("FragmentType.",""),
187 tr_global_stats[frag_type]["min_count"],
188 tr_global_stats[frag_type]["max_count"],
189 tr_global_stats[frag_type]["min_size"],
190 tr_global_stats[frag_type]["max_size"],
191 tr_global_stats[frag_type]["nonzero_error_bits_min_count"],
192 tr_global_stats[frag_type]["nonzero_error_bits_max_count"])
193 )
194
195 print(divider)
196 print("")
197
198 del h5file
199 gc.collect()
200
201if __name__ == '__main__':
202 main()