ATLAS Offline Software
Loading...
Searching...
No Matches
chainDump Namespace Reference

Functions

 get_parser ()
 open_root_file (file_path)
 load_histograms (root_file, hist_paths)
 get_counts (hist, rowLabel='Output')
 get_2D_counts (hist)
 make_counts_json_dict (in_counts, ref_counts)
 parse_name_dict (name_dict_as_list)
 get_text_name (hist_name, name_dict)
 count_diff (count_in, count_ref, total_in, total_ref, thr_frac, thr_num)
 compare_ref (json_dict, thr_frac, thr_num)
 print_counts (json_dict)
 format_txt_count (count)
 write_txt_output (json_dict, diff_only=False, printHeader=False)
 make_light_dict (full_dict, includeL1Counts)
 main ()

Variables

str total_events_key = 'TotalEventsProcessed'
int column_width = 10
int name_width = 50

Detailed Description

Script to dump trigger counts to a text file

Function Documentation

◆ compare_ref()

chainDump.compare_ref ( json_dict,
thr_frac,
thr_num )

Definition at line 228 of file chainDump.py.

228def compare_ref(json_dict, thr_frac, thr_num):
229 results = []
230 in_total = json_dict[total_events_key]['count']
231 ref_total = json_dict[total_events_key]['ref_count']
232 for text_name in sorted(json_dict):
233 if text_name == total_events_key:
234 continue
235 diff_val = [] # different counts in input and reference
236 missing_ref = [] # input count exists but reference is n/a
237 missing_val = [] # input count is n/a but reference exists
238 for item_name, item_counts in json_dict[text_name]['counts'].items():
239 v = item_counts['count']
240 ref_v = item_counts['ref_count']
241 if v == 'n/a':
242 missing_val.append([item_name, v, ref_v])
243 item_counts['ref_diff'] = True
244 elif ref_v == 'n/a':
245 missing_ref.append([item_name, v, ref_v])
246 item_counts['ref_diff'] = True
247 elif count_diff(v, ref_v, in_total, ref_total, thr_frac, thr_num):
248 diff_val.append([item_name, v, ref_v])
249 item_counts['ref_diff'] = True
250 else:
251 item_counts['ref_diff'] = False
252 good = True
253 if len(diff_val) > 0:
254 good = False
255 dump = '\n'.join(
256 [' {e[0]:{nw}s} {e[1]:>{w}d} {e[2]:>{w}d}'.format(
257 e=element, nw=name_width, w=column_width) for element in diff_val])
258 logging.info('%s has %d item(s) out of tolerance:\n%s',
259 text_name, len(diff_val), dump)
260 if (len(missing_ref)) > 0:
261 good = False
262 dump = '\n'.join([' {e[0]:s}'.format(e=element) for element in missing_ref])
263 logging.info('%s has %d item(s) missing in the reference:\n%s',
264 text_name, len(missing_ref), dump)
265 if (len(missing_val)) > 0:
266 good = False
267 dump = '\n'.join([' {e[0]:s}'.format(e=element) for element in missing_val])
268 logging.info('%s has %d item(s) missing with respect to the reference:\n%s',
269 text_name, len(missing_val), dump)
270 if good:
271 logging.info('%s is matching the reference', text_name)
272 results.append(0)
273 else:
274 results.append(1)
275 return max(results)
276
277
#define max(a, b)
Definition cfImp.cxx:41

◆ count_diff()

chainDump.count_diff ( count_in,
count_ref,
total_in,
total_ref,
thr_frac,
thr_num )

Definition at line 217 of file chainDump.py.

217def count_diff(count_in, count_ref, total_in, total_ref, thr_frac, thr_num):
218 # normalise input counts to total events in reference
219 count_in_norm = (count_in / float(total_in)) * total_ref
220 frac = count_in_norm / float(count_ref) if count_ref != 0 else None
221
222 num_diff = abs(count_in_norm - count_ref) > thr_num
223 frac_diff = abs(frac - 1.0) > thr_frac if frac else True
224
225 return num_diff and frac_diff
226
227

◆ format_txt_count()

chainDump.format_txt_count ( count)

Definition at line 304 of file chainDump.py.

304def format_txt_count(count):
305 if type(count) is int:
306 return '{val:>{w}d}'.format(val=count, w=column_width)
307 elif type(count) is not str:
308 logging.error('Unexpected count type %s', type(count))
309 count = 'ERROR'
310 if count == 'n/a':
311 count = '-'
312 return '{val:>{w}s}'.format(val=count, w=column_width)
313
314

◆ get_2D_counts()

chainDump.get_2D_counts ( hist)
Extract {xlabel_ylabel, value} dictionary from a histogram. Values are stored as integers.

Definition at line 160 of file chainDump.py.

160def get_2D_counts(hist):
161 '''
162 Extract {xlabel_ylabel, value} dictionary from a histogram. Values are stored as integers.
163 '''
164 nbinsx = hist.GetNbinsX()
165 nbinsy = hist.GetNbinsY()
166 counts = {}
167 for x in range(1, nbinsx+1):
168 label = hist.GetXaxis().GetBinLabel(x)
169 if not label:
170 logging.debug('Bin %d in histogram %s has no label, skipping', x, hist.GetName())
171 continue
172
173 for y in range(3, nbinsy):
174 rowName = hist.GetYaxis().GetBinLabel(y)
175 # Get only steps and skip the base rows
176 if rowName in ['Input','AfterPS','Output','Express']:
177 continue
178 name = label + '_' + rowName
179 name = name.replace(' ', '')
180 value = hist.GetBinContent(x, y)
181 counts[name] = int(value)
182
183 return counts
184

◆ get_counts()

chainDump.get_counts ( hist,
rowLabel = 'Output' )
Extract {xlabel, value} dictionary from a histogram. Values are stored as integers.
If histogram is 2D, the y-bin labelled rowLabel is used to extract the value.

Definition at line 134 of file chainDump.py.

134def get_counts(hist, rowLabel='Output'):
135 '''
136 Extract {xlabel, value} dictionary from a histogram. Values are stored as integers.
137 If histogram is 2D, the y-bin labelled rowLabel is used to extract the value.
138 '''
139
140 nbinsx = hist.GetNbinsX()
141 nbinsy = hist.GetNbinsY()
142 outputRow = None # Default to last row if 'Output' not found
143 for bin in range(1, nbinsy):
144 if hist.GetYaxis().GetBinLabel(bin) == rowLabel:
145 outputRow = bin
146 break
147
148 counts = {}
149 for b in range(1, nbinsx+1):
150 label = hist.GetXaxis().GetBinLabel(b)
151 if not label:
152 logging.debug('Bin %d in histogram %s has no label, skipping', b, hist.GetName())
153 continue
154
155 value = hist.GetBinContent(b) if hist.GetDimension() == 1 else hist.GetBinContent(b, outputRow or nbinsy)
156 counts[label] = int(value)
157
158 return counts
159

◆ get_parser()

chainDump.get_parser ( )

Definition at line 24 of file chainDump.py.

24def get_parser():
25 parser = argparse.ArgumentParser(usage='%(prog)s [options]',
26 description=__doc__)
27 parser.add_argument('-f', '--inputFile',
28 metavar='PATH',
29 default='expert-monitoring.root',
30 help='Name of input root file')
31 parser.add_argument('-r', '--referenceFile',
32 metavar='PATH',
33 help='Name of reference root file')
34 parser.add_argument('-v', '--verbose',
35 action='store_true',
36 help='Increase output verbosity')
37 parser.add_argument('-p', '--printOnly',
38 action='store_true',
39 default=False,
40 help='Print counts instead of saving to file')
41 parser.add_argument('-d', '--diffOnly',
42 action='store_true',
43 default=False,
44 help='Only store out of tolerance results (does not change JSON)')
45 parser.add_argument('--json',
46 metavar='PATH',
47 nargs='?',
48 const='chainDump.json',
49 help='Save outputs also to a json file with the given name or %(const)s if no name is given')
50 parser.add_argument('--yaml',
51 metavar='PATH',
52 nargs='?',
53 const='chainDump.yml',
54 help='Produce a small yaml file including condensed counts information for test file only '
55 '(no ref) with the given name or %(const)s if no name is given')
56 parser.add_argument('--yamlL1',
57 action='store_true',
58 help='Include the L1 count information to the yaml file')
59 parser.add_argument('--fracTolerance',
60 metavar='FRAC',
61 type=float,
62 default=0.001,
63 help='Tolerance as a fraction, default = %(default)s. '
64 'Flagged diffs must exceed all tolerances')
65 parser.add_argument('--intTolerance',
66 metavar='NUM',
67 type=int,
68 default=2,
69 help='Tolerance as a number of counts, default = %(default)s. '
70 'Flagged diffs must exceed all tolerances')
71 parser.add_argument('--countHists',
72 metavar='HISTS',
73 nargs='+',
74 default=[
75 'HLTFramework/TrigSignatureMoni/SignatureAcceptance',
76 'HLTFramework/TrigSignatureMoni/../TrigSignatureMoni/SignatureAcceptance',
77 'HLTFramework/../HLTFramework/TrigSignatureMoni/SignatureAcceptance',
78 'TrigSteer_HLT/ChainAcceptance',
79 'TrigSteer_HLT/NumberOfActiveTEs',
80 'HLTFramework/TrigSignatureMoni/DecisionCount',
81 'CTPSimulation/L1ItemsAV',
82 'L1/CTPSimulation/output/tavById'],
83 help='Histograms to use for counts dump. All existing '
84 'histograms from the list are used, default = %(default)s')
85 parser.add_argument('--totalHists',
86 metavar='HISTS',
87 nargs='+',
88 default=[
89 'TrigSteer_HLT/NInitialRoIsPerEvent',
90 'HLTFramework/HLTSeeding/RoIs_eEM/count'],
91 help='Histograms to use for total events. First existing '
92 'histogram from the list is used, default = %(default)s')
93 parser.add_argument('--histDict',
94 metavar='DICT',
95 nargs='+',
96 default=[
97 'HLTFramework/TrigSignatureMoni/SignatureAcceptance:HLTChain',
98 'HLTFramework/TrigSignatureMoni/../TrigSignatureMoni/SignatureAcceptance:HLTExpress',
99 'HLTFramework/../HLTFramework/TrigSignatureMoni/SignatureAcceptance:HLTStep',
100 'TrigSteer_HLT/ChainAcceptance:HLTChain',
101 'TrigSteer_HLT/NumberOfActiveTEs:HLTTE',
102 'HLTFramework/TrigSignatureMoni/DecisionCount:HLTDecision',
103 'CTPSimulation/L1ItemsAV:L1AV',
104 'L1/CTPSimulation/output/tavById:L1AV'],
105 help='Dictionary defining names of output text files for each '
106 'histogram, default = %(default)s')
107 parser.add_argument('--printHeader',
108 action='store_true',
109 default=False,
110 help='Add title of columns to the output txt (just for readability)')
111 return parser
112
113

◆ get_text_name()

chainDump.get_text_name ( hist_name,
name_dict )

Definition at line 210 of file chainDump.py.

210def get_text_name(hist_name, name_dict):
211 if hist_name in name_dict:
212 return name_dict[hist_name]
213 else:
214 return hist_name.replace('/', '_')
215
216

◆ load_histograms()

chainDump.load_histograms ( root_file,
hist_paths )

Definition at line 122 of file chainDump.py.

122def load_histograms(root_file, hist_paths):
123 hist_dict = {}
124 for hist_path in hist_paths:
125 h = root_file.Get(hist_path)
126 if not isinstance(h, ROOT.TH1):
127 logging.debug('Cannot open histogram %s, skipping', hist_path)
128 continue
129 logging.debug('Loaded histogram %s', hist_path)
130 hist_dict[hist_path] = h
131 return hist_dict
132
133

◆ main()

chainDump.main ( )

Definition at line 387 of file chainDump.py.

387def main():
388 args = get_parser().parse_args()
389 logging.basicConfig(stream=sys.stdout,
390 format='%(levelname)-8s %(message)s',
391 level=logging.DEBUG if args.verbose else logging.INFO)
392
393 name_dict = parse_name_dict(args.histDict)
394
395
398
399 in_file = open_root_file(args.inputFile)
400 if not in_file:
401 logging.error('Failed to open input file %s', args.inputFile)
402 return 1
403 logging.debug('Opened input file %s', args.inputFile)
404
405 if args.referenceFile:
406 ref_file = open_root_file(args.referenceFile)
407 if not ref_file:
408 logging.error('Failed to open input file %s', args.referenceFile)
409 return 1
410 logging.debug('Opened input file %s', args.referenceFile)
411
412
415
416 in_hists = load_histograms(in_file, args.countHists)
417 if len(in_hists) == 0:
418 logging.error('No count histograms could be loaded.')
419 return 1
420 logging.info('Loaded count histograms: %s', sorted(in_hists))
421
422 in_total_hists = load_histograms(in_file, args.totalHists)
423 if len(in_total_hists) == 0:
424 logging.error('No total-events histogram could be loaded')
425 return 1
426 items = list(in_total_hists.items())
427 in_total = items[0][1].GetEntries()
428 logging.info('Loaded total-events histogram %s, number of events: %d',
429 items[0][0], in_total)
430
431 ref_hists = None
432 ref_total_hists = None
433 ref_total = None
434 if args.referenceFile:
435 ref_hists = load_histograms(ref_file, args.countHists)
436 logging.info('Loaded reference count histograms: %s', sorted(ref_hists))
437 missing_refs = [k for k in in_hists if k not in ref_hists]
438 if len(missing_refs) > 0:
439 logging.error('Count histogram(s) %s missing in the reference', missing_refs)
440 return 1
441 ref_total_hists = load_histograms(ref_file, args.totalHists)
442 if len(ref_total_hists) == 0:
443 logging.error('No total-events reference histogram could be loaded')
444 return 1
445 ref_total = list(ref_total_hists.values())[0].GetEntries()
446 logging.info('Loaded total-events reference histogram %s, number of events: %d',
447 list(ref_total_hists.keys())[0], ref_total)
448
449
452
453 json_dict = {
454 total_events_key: {
455 'hist_name': list(in_total_hists.keys())[0],
456 'count': int(in_total),
457 'ref_count': int(ref_total) if ref_total else 'n/a'
458 }
459 }
460
461 for hist_name, hist in in_hists.items():
462 text_name = get_text_name(hist_name, name_dict)
463 if text_name in json_dict:
464 logging.error(
465 'Name "%s" assigned to more than one histogram, ', text_name,
466 'results would be overwritten. Use --countHists and ',
467 '--histDict options to avoid duplicates. Exiting.')
468
469 rowLabel = 'Express' if 'Express' in text_name else 'Output'
470 counts = get_2D_counts(hist) if text_name in ['HLTStep', 'HLTDecision'] else get_counts(hist, rowLabel)
471 ref_counts = {}
472 if ref_hists:
473 ref_hist = ref_hists[hist_name]
474 ref_counts = get_2D_counts(ref_hist) if text_name in ['HLTStep', 'HLTDecision'] else get_counts(ref_hist, rowLabel)
475 d = make_counts_json_dict(counts, ref_counts)
476
477 json_dict[text_name] = {
478 'hist_name': hist_name,
479 'counts': d
480 }
481
482
485
486 retcode = 0
487 if args.referenceFile:
488 logging.info('Comparing counts to reference')
489 retcode = compare_ref(json_dict, args.fracTolerance, args.intTolerance)
490
491 if args.printOnly and not args.diffOnly:
492 logging.info('Printing counts instead of dumping to files because of --printOnly option')
493 print_counts(json_dict)
494
495 if not args.printOnly:
496 write_txt_output(json_dict, args.diffOnly, args.printHeader)
497
498 if args.json:
499 logging.info('Writing results to %s', args.json)
500 with open(args.json, 'w') as outfile:
501 json.dump(json_dict, outfile, sort_keys=True)
502
503 if args.yaml:
504 logging.info('Writing results extract to %s', args.yaml)
505 light_dict = make_light_dict(json_dict, includeL1Counts = args.yamlL1)
506 with open(args.yaml, 'w') as outfile:
507 yaml.dump(light_dict, outfile, sort_keys=True)
508
509 return retcode
510
511
TGraphErrors * GetEntries(TH2F *histo)
int main()
Definition hello.cxx:18

◆ make_counts_json_dict()

chainDump.make_counts_json_dict ( in_counts,
ref_counts )

Definition at line 185 of file chainDump.py.

185def make_counts_json_dict(in_counts, ref_counts):
186 counts = {}
187 all_keys = set(in_counts)
188 all_keys.update(ref_counts)
189 for k in sorted(all_keys):
190 v = in_counts[k] if k in in_counts else 'n/a'
191 ref_v = ref_counts[k] if k in ref_counts else 'n/a'
192 counts[k] = {
193 'count': v,
194 'ref_count': ref_v,
195 'ref_diff': 'n/a' # Filled in compare_ref
196 }
197 return counts
198
199
STL class.

◆ make_light_dict()

chainDump.make_light_dict ( full_dict,
includeL1Counts )

Definition at line 353 of file chainDump.py.

353def make_light_dict(full_dict, includeL1Counts):
354 # 3 nested dictionaries of int
355 light_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
356
357 def extract_steps(in_name, out_name):
358 for name,c in full_dict[in_name]['counts'].items():
359 if c['count']==0:
360 continue
361 chain_name, chain_step = name.split('_Step')
362 light_dict[chain_name][out_name][int(chain_step)] = c['count']
363
364 # Change step dictionary to consecutive list of steps
365 for chain_name in light_dict:
366 steps = light_dict[chain_name][out_name]
367 light_dict[chain_name][out_name] = {i:steps[k] for i,k in enumerate(sorted(steps))}
368
369 extract_steps('HLTStep', 'stepCounts')
370 extract_steps('HLTDecision', 'stepFeatures')
371
372 # Add total chain count and skip total / groups / streams
373 for chain_name,c in full_dict['HLTChain']['counts'].items():
374 light_dict[chain_name]['eventCount'] = c['count']
375
376 if any(chain_name.startswith(s) for s in ['All', 'grp_', 'str_']):
377 del light_dict[chain_name]
378
379 if includeL1Counts and 'L1AV' in full_dict:
380 light_dict.update(
381 {name:{"eventCount": counts["count"]} for name,counts in full_dict["L1AV"]["counts"].items()}
382 )
383
384 return light_dict
385
386

◆ open_root_file()

chainDump.open_root_file ( file_path)

Definition at line 114 of file chainDump.py.

114def open_root_file(file_path):
115 f = ROOT.TFile(file_path)
116 if f.IsOpen() and not f.IsZombie():
117 return f
118 else:
119 return None
120
121

◆ parse_name_dict()

chainDump.parse_name_dict ( name_dict_as_list)

Definition at line 200 of file chainDump.py.

200def parse_name_dict(name_dict_as_list):
201 name_dict = {}
202 for kv in name_dict_as_list:
203 kv_split = kv.split(':')
204 if len(kv_split) < 2:
205 continue
206 name_dict[kv_split[0]] = kv_split[1]
207 return name_dict
208
209

◆ print_counts()

chainDump.print_counts ( json_dict)

Definition at line 278 of file chainDump.py.

278def print_counts(json_dict):
279 for text_name in json_dict:
280 if text_name == total_events_key:
281 logging.info('%s: %d', text_name, json_dict[text_name]['count'])
282 continue
283 hist_name = json_dict[text_name]['hist_name']
284 counts = json_dict[text_name]['counts']
285 no_ref = True
286 for item_counts in counts.values():
287 if item_counts['ref_count'] != 'n/a':
288 no_ref = False
289 break
290 dump_lines = []
291 for item_name, item_counts in counts.items():
292 v = item_counts['count']
293 line = ' {name:{nw}s} {val:>{w}s}'.format(name=item_name, val=str(v), nw=name_width, w=column_width)
294 if not no_ref:
295 ref_v = item_counts['ref_count']
296 diff = item_counts['ref_diff']
297 line += ' {val:>{w}s}'.format(val=str(ref_v), w=column_width)
298 if diff:
299 line += ' <<<<<<<<<<'
300 dump_lines.append(line)
301 logging.info('Writing %s counts from histogram %s:\n%s', text_name, hist_name, '\n'.join(dump_lines))
302
303

◆ write_txt_output()

chainDump.write_txt_output ( json_dict,
diff_only = False,
printHeader = False )

Definition at line 315 of file chainDump.py.

315def write_txt_output(json_dict, diff_only=False, printHeader=False):
316 for text_name in sorted(json_dict):
317 if text_name == total_events_key:
318 logging.info('Writing total event count to file %s.txt', text_name)
319 with open('{:s}.txt'.format(text_name), 'w') as outfile:
320 outfile.write('{:d}\n'.format(json_dict[text_name]['count']))
321 continue
322 hist_name = json_dict[text_name]['hist_name']
323 logging.info('Writing counts from histogram %s to file %s.txt', hist_name, text_name)
324 counts = json_dict[text_name]['counts']
325 no_ref = True
326 for item_counts in counts.values():
327 if item_counts['ref_count'] != 'n/a':
328 no_ref = False
329 break
330 with open('{:s}.txt'.format(text_name), 'w') as outfile:
331 if printHeader:
332 line = '{name:{nw}s}'.format(name='chain', nw=name_width)
333 if not no_ref:
334 line += '{name:{cw}s}'.format(name='test', cw=column_width) + 'ref \n'
335 else:
336 line += 'test \n'
337 outfile.write(line)
338 for item_name, item_counts in counts.items():
339 v = item_counts['count']
340 line = '{name:{nw}s} '.format(name=item_name, nw=name_width) + format_txt_count(v)
341 if not no_ref:
342 ref_v = item_counts['ref_count']
343 diff = item_counts['ref_diff']
344 line += ' ' + format_txt_count(ref_v)
345 if diff:
346 line += ' <<<<<<<<<<'
347 elif diff_only:
348 line = None
349 if line:
350 outfile.write(line+'\n')
351
352

Variable Documentation

◆ column_width

int chainDump.column_width = 10

Definition at line 17 of file chainDump.py.

◆ name_width

int chainDump.name_width = 50

Definition at line 18 of file chainDump.py.

◆ total_events_key

str chainDump.total_events_key = 'TotalEventsProcessed'

Definition at line 16 of file chainDump.py.