22 {
23
25 using namespace asg::msgUserCode;
27
28 if (argc < 3 || argc > 4) {
29 std::cerr <<
"usage: " <<
argv[0] <<
": <DAOD> <jet collection> [max events]"
30 << "\n\n"
31 << "This test checks jet constituents and their thinning.\n"
32 << "It verifies that:\n"
33 << " 1. All jet constituent links are valid\n"
34 << " 2. All constituents can be cast to FlowElement\n"
35 << " 3. Counts charged vs neutral constituents\n"
36 << " 4. Checks originalObjectLink availability\n"
37 << " 5. Validates otherObjects pointers\n"
38 << "\n"
39 << "Arguments:\n"
40 << " <DAOD> : Input DAOD file path\n"
41 << " <jet collection>: Name of jet collection to check\n"
42 << " [max events] : Optional maximum number of events to process\n"
43 << "\n"
44 << "Return codes:\n"
45 << " -1: usage error\n"
46 << " 1: broken constituent links found\n"
47 << " 2: constituent not a FlowElement\n"
48 << " 3: invalid otherObjects in charged FlowElements\n"
49 << " 4: invalid otherObjects in neutral FlowElements\n"
50 << " 0: all constituents valid" << std::endl;
51 return -1;
52 }
54 std::string jets_name =
argv[2];
56 if (argc == 4) {
58 }
59
60
61 const std::string
APP_NAME =
"TestJetConstituents";
62
63
65
66
68
69
70 std::unique_ptr<TFile>
ifile(TFile::Open(
file.c_str(),
"READ"));
72 std::cerr <<
"Couldn't open file: " <<
file << std::endl;
73 return 1;
74 }
75
76
78
79 unsigned long long nJetsTotal = 0;
80 unsigned long long nConstituentsTotal = 0;
81 unsigned long long nChargedTotal = 0;
82 unsigned long long nNeutralTotal = 0;
83 unsigned long long nInvalidLinks = 0;
84 unsigned long long nNotFlowElement = 0;
85 unsigned long long nWithOriginalLink = 0;
86 unsigned long long nOtherObjectsCharged = 0;
87 unsigned long long nOtherObjectsNeutral = 0;
88 unsigned long long nInvalidOtherObjectsCharged = 0;
89 unsigned long long nInvalidOtherObjectsNeutral = 0;
90 unsigned long long nMissingSignalType = 0;
91
92 unsigned long long entries =
event.getEntries();
93 if (maxEvents > 0 && maxEvents < (
long long)
entries) {
95 }
96 std::cout <<
"Processing " <<
entries <<
" events..." << std::endl;
97
99
100 if (
event.getEntry(entry) < 0) {
101 std::cerr <<
"Couldn't load entry " <<
entry <<
" from file "
102 <<
file << std::endl;
103 return 1;
104 }
105
108
110 nJetsTotal++;
111 size_t nConstituents =
jet->numConstituents();
112 nConstituentsTotal += nConstituents;
113
114 for (
size_t i = 0;
i < nConstituents; ++
i) {
115 const auto& link =
jet->constituentLinks().at(i);
116
117
118 if (!link.isValid()) {
119 nInvalidLinks++;
120 continue;
121 }
122
123
125
126
128 if (originalAcc.isAvailable(*constituent)) {
131 constituent = *origLink;
132 nWithOriginalLink++;
133 }
134 }
135
136
138 if (!flowElement) {
139 nNotFlowElement++;
140 continue;
141 }
142
143
146 nChargedTotal++;
147 } else {
148 nNeutralTotal++;
149 }
150
151
152 std::vector<const xAOD::IParticle*> others = flowElement->
otherObjects();
155 nOtherObjectsCharged++;
156 if (!other) {
157 nInvalidOtherObjectsCharged++;
158 }
159 } else {
160 nOtherObjectsNeutral++;
161 if (!other) {
162 nInvalidOtherObjectsNeutral++;
163 }
164 }
165 }
166 }
167 }
168 }
169
170
171 std::cout << "\n========================================" << std::endl;
172 std::cout << "SUMMARY" << std::endl;
173 std::cout << "========================================" << std::endl;
174 std::cout <<
"Events processed: " <<
entries << std::endl;
175 std::cout << "Jets found: " << nJetsTotal << std::endl;
176 std::cout << "Total constituents: " << nConstituentsTotal << std::endl;
177 std::cout << " Charged: " << nChargedTotal
178 << " (" << std::fixed << std::setprecision(1)
179 << (nConstituentsTotal > 0 ? 100.0 * nChargedTotal / nConstituentsTotal : 0.0)
180 << "%)" << std::endl;
181 std::cout << " Neutral: " << nNeutralTotal
182 << " (" << std::fixed << std::setprecision(1)
183 << (nConstituentsTotal > 0 ? 100.0 * nNeutralTotal / nConstituentsTotal : 0.0)
184 << "%)" << std::endl;
185 std::cout << "Invalid constituent links: " << nInvalidLinks << std::endl;
186 std::cout << "Non-FlowElement constituents: " << nNotFlowElement << std::endl;
187 std::cout << "Missing signalType: " << nMissingSignalType << std::endl;
188 std::cout << "Constituents with originalObjectLink: " << nWithOriginalLink << std::endl;
189 std::cout << "\nOther Objects:" << std::endl;
190 std::cout << " Charged otherObjects: " << nOtherObjectsCharged;
191 if (nInvalidOtherObjectsCharged > 0) {
192 std::cout << " (INVALID: " << nInvalidOtherObjectsCharged << ")";
193 }
194 std::cout << std::endl;
195 std::cout << " Neutral otherObjects: " << nOtherObjectsNeutral;
196 if (nInvalidOtherObjectsNeutral > 0) {
197 std::cout << " (INVALID: " << nInvalidOtherObjectsNeutral << ")";
198 }
199 std::cout << std::endl;
200 std::cout << " Total otherObjects: " << (nOtherObjectsCharged + nOtherObjectsNeutral) << std::endl;
201
202 if (nConstituentsTotal > 0) {
203 std::cout << "\nAverage constituents/jet: " << std::fixed << std::setprecision(2)
204 << (
double)nConstituentsTotal / nJetsTotal << std::endl;
205 }
206 std::cout << "========================================\n" << std::endl;
207
208
209 if (nInvalidLinks > 0) {
210 std::cerr << "ERROR: Found " << nInvalidLinks << " invalid constituent links!" << std::endl;
211 return 1;
212 }
213 if (nNotFlowElement > 0) {
214 std::cerr << "ERROR: Found " << nNotFlowElement << " constituents that are not FlowElements!" << std::endl;
215 return 2;
216 }
217 if (nInvalidOtherObjectsCharged > 0) {
218 std::cerr << "ERROR: Found " << nInvalidOtherObjectsCharged << " invalid otherObjects in charged FlowElements!" << std::endl;
219 return 3;
220 }
221 if (nInvalidOtherObjectsNeutral > 0) {
222 std::cerr << "ERROR: Found " << nInvalidOtherObjectsNeutral << " invalid otherObjects in neutral FlowElements!" << std::endl;
223 return 4;
224 }
225
226 std::cout << "SUCCESS: All constituent links are valid!" << std::endl;
227 return 0;
228}
bool isCharged(const T &p)
ElementLink implementation for ROOT usage.
bool isValid() const
Test to see if the link can be dereferenced.
SG::ConstAccessor< T, ALLOC > ConstAccessor
std::vector< const xAOD::IParticle * > otherObjects() const
Class providing the definition of the 4-vector interface.
Tool for accessing xAOD files outside of Athena.
@ kAthenaAccess
Access containers/objects like Athena does.
Jet_v1 Jet
Definition of the current "jet version".
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
FlowElement_v1 FlowElement
Definition of the current "pfo version".
JetContainer_v1 JetContainer
Definition of the current "jet container version".