ATLAS Offline Software
Functions
test-jet-constituents.cxx File Reference
#include "xAODRootAccess/Init.h"
#include "xAODRootAccess/tools/ReturnCheck.h"
#include "xAODRootAccess/TEvent.h"
#include "xAODJet/JetContainer.h"
#include "xAODPFlow/FlowElement.h"
#include "xAODPFlow/FlowElementContainer.h"
#include "xAODBase/IParticle.h"
#include "AthContainers/AuxElement.h"
#include "AsgMessaging/MessageCheck.h"
#include "TFile.h"
#include "TTree.h"
#include "TError.h"
#include <iostream>
#include <iomanip>

Go to the source code of this file.

Functions

int main ATLAS_NOT_THREAD_SAFE (int argc, char *argv[])
 

Function Documentation

◆ ATLAS_NOT_THREAD_SAFE()

int main ATLAS_NOT_THREAD_SAFE ( int  argc,
char *  argv[] 
)

Definition at line 22 of file test-jet-constituents.cxx.

22  {
23 
24  ANA_CHECK_SET_TYPE (int);
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  }
53  std::string file = argv[1];
54  std::string jets_name = argv[2];
55  long long maxEvents = -1;
56  if (argc == 4) {
57  maxEvents = std::stoll(argv[3]);
58  }
59 
60  // The name of the application:
61  const std::string APP_NAME = "TestJetConstituents";
62 
63  // Set up the environment:
64  ANA_CHECK( xAOD::Init() );
65 
66  // Set up the event object:
68 
69  // Open the file:
70  std::unique_ptr<TFile> ifile(TFile::Open(file.c_str(), "READ"));
71  if ( ! ifile.get() || ifile->IsZombie()) {
72  std::cerr << "Couldn't open file: " << file << std::endl;
73  return 1;
74  }
75 
76  // Connect the event object to it:
77  ANA_CHECK( event.readFrom(ifile.get()) );
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 
98  for (unsigned long long entry = 0; entry < entries; ++entry) {
99  // Load the event:
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 
106  const xAOD::JetContainer *jets = nullptr;
107  ANA_CHECK( event.retrieve(jets, jets_name) );
108 
109  for (const xAOD::Jet *const jet : *jets) {
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  // Check if link is valid
118  if (!link.isValid()) {
119  nInvalidLinks++;
120  continue;
121  }
122 
123  // Get the actual constituent - might need to follow originalObjectLink
124  const xAOD::IParticle* constituent = *link;
125 
126  // Check if this is a view container element that needs dereferencing
127  static SG::AuxElement::ConstAccessor<ElementLink<xAOD::IParticleContainer>> originalAcc("originalObjectLink");
128  if (originalAcc.isAvailable(*constituent)) {
129  const ElementLink<xAOD::IParticleContainer>& origLink = originalAcc(*constituent);
130  if (origLink.isValid()) {
131  constituent = *origLink;
132  nWithOriginalLink++;
133  }
134  }
135 
136  // Try to cast to FlowElement
137  const xAOD::FlowElement* flowElement = dynamic_cast<const xAOD::FlowElement*>(constituent);
138  if (!flowElement) {
139  nNotFlowElement++;
140  continue;
141  }
142 
143  // Check if charged or neutral
144  bool isCharged = flowElement->isCharged();
145  if (isCharged) {
146  nChargedTotal++;
147  } else {
148  nNeutralTotal++;
149  }
150 
151  // Check otherObjects and their validity
152  std::vector<const xAOD::IParticle*> others = flowElement->otherObjects();
153  for (const xAOD::IParticle* other : others) {
154  if (isCharged) {
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  // Print summary
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  // Return codes
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 }
covarianceToolsLibrary.gErrorIgnoreLevel
gErrorIgnoreLevel
Definition: covarianceToolsLibrary.py:21
xAOD::TEvent::kAthenaAccess
@ kAthenaAccess
Access containers/objects like Athena does.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:72
TRT::Track::event
@ event
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:74
defineDB.jets
jets
Definition: JetTagCalibration/share/defineDB.py:24
ANA_CHECK
#define ANA_CHECK(EXP)
check whether the given expression was successful
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:324
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
python.SCT_ByteStreamErrorsTestAlgConfig.maxEvents
maxEvents
Definition: SCT_ByteStreamErrorsTestAlgConfig.py:43
xAOD::FlowElement_v1::isCharged
bool isCharged() const
Definition: FlowElement_v1.cxx:56
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
lumiFormat.i
int i
Definition: lumiFormat.py:85
LArCellNtuple.argv
argv
Definition: LArCellNtuple.py:167
Analysis::kError
@ kError
Definition: CalibrationDataVariables.h:60
APP_NAME
#define APP_NAME
Definition: BoostedXbbTag.cxx:23
file
TFile * file
Definition: tile_monitor.h:29
DQHistogramMergeRegExp.argc
argc
Definition: DQHistogramMergeRegExp.py:19
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
DataVector
Derived DataVector<T>.
Definition: DataVector.h:795
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
isCharged
bool isCharged(const T &p)
Definition: AtlasPID.h:1004
ANA_CHECK_SET_TYPE
#define ANA_CHECK_SET_TYPE(TYPE)
set the type for ANA_CHECK to report failures
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:314
entries
double entries
Definition: listroot.cxx:49
LArCellNtuple.ifile
string ifile
Definition: LArCellNtuple.py:146
xAOD::TEvent
Tool for accessing xAOD files outside of Athena.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:57
xAOD::FlowElement_v1::otherObjects
std::vector< const xAOD::IParticle * > otherObjects() const
Definition: FlowElement_v1.cxx:163
xAOD::Init
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition: Init.cxx:31
xAOD::FlowElement_v1
A detector object made of other lower level object(s)
Definition: FlowElement_v1.h:25