ATLAS Offline Software
Loading...
Searching...
No Matches
FPGATrackSimValidateAODOutput.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3
4import ROOT
5import sys
6import argparse
7import numpy as np
8
9
10def get_cluster_branches(use_itk_names):
11 if use_itk_names:
12 return [
13 'ITkPixelClusters',
14 'ITkStripClusters'
15 ]
16 return [
17 'xAODPixelClustersFromFPGACluster',
18 'xAODStripClustersFromFPGACluster'
19 ]
20
21
22def get_track_branch(use_itk_names):
23 if use_itk_names:
24 return 'InDetTrackParticles'
25 return 'FPGATrackParticles'
26
27
28def validate_expected_branches(tree, expected_branches):
29 available_branches = {branch.GetName() for branch in tree.GetListOfBranches()}
30 missing_branches = [branch for branch in expected_branches if branch not in available_branches]
31 if missing_branches:
32 raise KeyError(
33 f"missing expected branches in CollectionTree: {', '.join(missing_branches)}"
34 )
35
36
37def main():
38 parser = argparse.ArgumentParser(
39 description="Validate AOD Output from FPGATrackSim."
40 )
41 parser.add_argument(
42 "input_root_file",
43 help="Path to the input ROOT file"
44 )
45 parser.add_argument(
46 "--useITkNames",
47 dest="use_itk_names",
48 action="store_true",
49 help="Validate ITk cluster and track container names instead of the default FPGA names"
50 )
51 args = parser.parse_args()
52
53 input_root_file = args.input_root_file
54 rootFile = ROOT.TFile.Open(input_root_file)
55 if not rootFile or rootFile.IsZombie():
56 print(f"Error: Could not open file {input_root_file}")
57 sys.exit(1)
58
59 tree = rootFile.Get("CollectionTree")
60 if not tree:
61 raise ValueError("could not find CollectionTree in input file")
62
63 clustersToCheck = get_cluster_branches(args.use_itk_names)
64 trackBranchToCheck = get_track_branch(args.use_itk_names)
65 validate_expected_branches(tree, clustersToCheck + [trackBranchToCheck])
66
67 # Work around for ATEAM-1000
68 import cppyy.ll
69 cppyy.ll.cast["xAOD::PixelClusterContainer_v1"](0)
70
71 for branch in clustersToCheck:
72 averageClustersPerEvent = np.mean([getattr(evt, branch).size() for evt in tree])
73 if np.isclose(averageClustersPerEvent, 0):
74 raise ValueError(f"no recorded clusters in {branch}")
75 else:
76 print(f"there are on average {averageClustersPerEvent} clusters per event in {branch}")
77
78 averageNumberOfTracksPerEvent = np.mean([getattr(evt, trackBranchToCheck).size() for evt in tree])
79 if np.isclose(averageNumberOfTracksPerEvent, 0):
80 raise ValueError(f"no recorded tracks in {trackBranchToCheck}")
81 else:
82 print(f"there are on average {averageNumberOfTracksPerEvent} tracks per event in {trackBranchToCheck}")
83
84if __name__ == "__main__":
85 main()
void print(char *figname, TCanvas *c1)
validate_expected_branches(tree, expected_branches)