ATLAS Offline Software
Loading...
Searching...
No Matches
GenAodValidationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// GenAodValidationTool.cxx
7// Implementation file for class GenAodValidationTool
8// Author: S.Binet<binet@cern.ch>
10
11
12// STL includes
13#include <sstream>
14
15// FrameWork includes
16#include "Gaudi/Property.h"
17
18// StoreGate
20
21// CLHEP/HepMC includes
23#include "AtlasHepMC/GenEvent.h"
26#include "AtlasHepMC/Flow.h"
28
30
31
32// McParticleTools includes
34
38
42 const std::string& name,
43 const IInterface* parent ) :
45 m_outFile( nullptr )
46{
47 //
48 // Property declaration
49 //
50
51 declareProperty( "RefMcEvents",
52 m_refMcEventsName = "TruthEvent",
53 "StoreGate location of the reference McEventCollection" );
54
55 declareProperty( "CheckMcEvents",
56 m_checkMcEventsName = "GEN_AOD",
57 "Location of the 'to-be-validated' McEventCollection" );
58
59 declareProperty( "HardScatteringVtxOutputFile",
60 m_hardVtxOutFileName = "hepmc.hard.vtx.txt",
61 "Name of the output text file which will contain the "
62 "hard-scattering vertices" );
63
64 declareProperty( "RefHepMcWriterTool",
65 m_refMcEventWriter = HepMcTool_t( "HepMcWriterTool",
66 this ),
67 "Tool to write the reference HepMC::GenEvent into a dedicated file" );
68
69 declareProperty( "CheckHepMcWriterTool",
70 m_checkMcEventWriter = HepMcTool_t( "HepMcWriterTool",
71 this ),
72 "Tool to write the \"to-be-checked\" HepMC::GenEvent "
73 "into a dedicated file" );
74
75}
76
80{
81 ATH_MSG_DEBUG("Calling destructor");
82
83 if ( m_outFile ) {
84 m_outFile->close();
85 delete m_outFile;
86 m_outFile = nullptr;
87 }
88
89}
90
91
95
97{
98 ATH_MSG_INFO("Initializing " << name() << "...");
99
100 if ( m_outFile ) {
101 delete m_outFile;
102 m_outFile = nullptr;
103 }
104 m_outFile = new std::ofstream( m_hardVtxOutFileName.value().c_str(),
105 std::ios::trunc );
106 if ( !m_outFile || !m_outFile->is_open() || m_outFile->bad() ) {
107 ATH_MSG_ERROR("Could not open output Hard-Scattering vertices file at : "
108 << m_hardVtxOutFileName.value());
109 if ( m_outFile ) {
110 delete m_outFile;
111 m_outFile = nullptr;
112 }
113 return StatusCode::FAILURE;
114 }
115
116 // retrieve and configure HepMC writer tools
117 if ( setupHepMcWriterTools().isFailure() ) {
118 ATH_MSG_ERROR("Could not configure the HepMC::GenEvent writer tools !!");
119 return StatusCode::FAILURE;
120 }
121
122 return StatusCode::SUCCESS;
123}
124
126{
127 ATH_MSG_INFO("Finalizing " << name() << "...");
128
129 return StatusCode::SUCCESS;
130}
131
133{
134 // retrieve reference McEventCollection
135 const McEventCollection * refMcEvents = nullptr;
136 if ( evtStore()->retrieve( refMcEvents, m_refMcEventsName ).isFailure() ||
137 nullptr == refMcEvents ) {
138 ATH_MSG_ERROR("Could not retrieve reference McEventCollection at ["
139 << m_refMcEventsName << "] !!");
140 return StatusCode::FAILURE;
141 } else {
142 ATH_MSG_VERBOSE("Successfully retrieved reference McEventCollection at ["
143 << m_refMcEventsName << "]");
144
145 if ( !m_refMcEventWriter ||
146 m_refMcEventWriter->execute().isFailure() ) {
147 ATH_MSG_WARNING("Failed to write the reference GenEvent !!");
148 }
149 }
150
151 // retrieve checking McEventCollection
152 const McEventCollection * checkMcEvents = nullptr;
153 if ( evtStore()->retrieve(checkMcEvents, m_checkMcEventsName).isFailure() ||
154 nullptr == checkMcEvents ) {
155 ATH_MSG_ERROR("Could not retrieve 'to-be-validated' McEventCollection at ["
156 << m_checkMcEventsName << "] !!");
157 return StatusCode::FAILURE;
158 } else {
160 ("Successfully retrieved 'to-be-validated' McEventCollection at ["
161 << m_checkMcEventsName << "]");
162
163 if ( !m_checkMcEventWriter ||
164 m_checkMcEventWriter->execute().isFailure() ) {
165 ATH_MSG_WARNING("Failed to write the reference GenEvent !!");
166 }
167 }
168
169 return executeTool( refMcEvents, checkMcEvents );
170}
171
172StatusCode
174 const McEventCollection* checkMcEvents )
175{
176 if ( nullptr == refMcEvents ) {
177 ATH_MSG_ERROR("NULL pointer to reference McEventCollection !!");
178 return StatusCode::FAILURE;
179 }
180
181 if ( nullptr == checkMcEvents ) {
182 ATH_MSG_ERROR("NULL pointer to the 'to-be-validated' McEventCollection !!");
183 return StatusCode::FAILURE;
184 }
185
186 if ( refMcEvents->size() != checkMcEvents->size() ) {
187 ATH_MSG_ERROR("McEventCollections to be compared don't have the same size !"
188 << endmsg
189 << "Ref: " << refMcEvents->size() << endmsg
190 << "Current: " << checkMcEvents->size());
191 }
192
193 const unsigned int nMaxEvts = std::min( refMcEvents->size(),
194 checkMcEvents->size() );
195 for ( unsigned int iEvt = 0; iEvt != nMaxEvts; ++iEvt ) {
196
197 if ( executeTool( (*refMcEvents)[iEvt],
198 (*checkMcEvents)[iEvt] ).isFailure() ) {
199 ATH_MSG_WARNING("Could not VALIDATE this event ["
200 << (*refMcEvents)[iEvt]->event_number()
201 << "] !!");
202 }
203 }
204
205 return StatusCode::SUCCESS;
206}
207
208StatusCode
209GenAodValidationTool::executeTool( const HepMC::GenEvent* refMcEvts,
210 const HepMC::GenEvent* checkMcEvts )
211{
212 if ( nullptr == refMcEvts ) {
213 ATH_MSG_ERROR("NULL pointer to reference HepMC::GenEvent !!");
214 return StatusCode::FAILURE;
215 }
216
217 if ( nullptr == checkMcEvts ) {
218 ATH_MSG_ERROR("NULL pointer to the 'to-be-validated' HepMC::GenEvent !!");
219 return StatusCode::FAILURE;
220 }
221
222 const unsigned int evtNbr = refMcEvts->event_number();
223 (*m_outFile) << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
224 << std::endl
225 << "Event: " << evtNbr
226 << std::endl;
227
228#ifdef HEPMC3
229 std::map<int,int> ref_bc_to_id;
230 const auto& refvertices = refMcEvts->vertices();
231 for ( const auto& vtx: refvertices) {
232 // AV: this algorthm is not very correct
233 int partonsin = 0;
234 int showerout = 0;
235 for (auto& p: vtx->particles_in()) if (MC::isQuark(p) || MC::isGluon(p)) partonsin++;
236 for (auto& p: vtx->particles_out()) if (p->pdg_id() == 91||p->pdg_id() == 92||p->pdg_id() == 94) showerout++;
237 if ( partonsin >= 2 && showerout == 0 ) {
238 ref_bc_to_id[HepMC::barcode(vtx)] = vtx->id();
239 }
240 }
241 std::map<int,int> che_bc_to_id;
242 const auto& chevertices = checkMcEvts->vertices();
243 for (const auto& checkVtx: chevertices) {
244 che_bc_to_id[HepMC::barcode(checkVtx)] = checkVtx->id();
245 }
246 std::set<int> allbarcodes;
247 for (const auto &[bc,id]: ref_bc_to_id) allbarcodes.insert(bc);
248 for (const auto &[bc,id]: che_bc_to_id) allbarcodes.insert(bc);
249 for (const auto &bc: allbarcodes){
250 auto ref_it = ref_bc_to_id.find(bc);
251 auto che_it = che_bc_to_id.find(bc);
252 if (ref_it == ref_bc_to_id.end()) {ATH_MSG_WARNING("In Event [" << evtNbr << "]: got null ref-vertex (barcode: " << bc << ")"); continue; }
253 if (che_it == che_bc_to_id.end()) {ATH_MSG_WARNING("Output GenEvent is missing the selected HardScattering Vtx !!"<< " (" << bc << ")"); continue; }
254 if (-ref_it->second > int(refvertices.size()) ) { continue; }
255 if (-che_it->second > int(chevertices.size()) ) { continue; }
256 const auto& refvtx = refvertices[-ref_it->second-1];
257 const auto& chevtx = chevertices[-che_it->second-1];
258 (*m_outFile) << refvtx << std::endl;
259 (*m_outFile) << chevtx << std::endl;
260 (*m_outFile) << "---------" << std::endl;
261 if ( !compareVtx( refvtx, chevtx ) ) {
262 ATH_MSG_WARNING("Selected HardScattering vertices are NOT the same !!"<< " at Event [" << evtNbr << "]"<< " refVtx = " << refvtx<<" chevtx = " << chevtx);
263 }
264 }
265 (*m_outFile) << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
266#else
267 std::set<int> ref_bc;
268 for ( auto vtxIt = refMcEvts->vertices_begin(); vtxIt != refMcEvts->vertices_end(); ++vtxIt ) {
269 auto vtx =*vtxIt;
270 int partonsin = 0;
271 int showerout = 0;
272#ifdef HEPMC3
273 for (auto p = vtx->particles_in_begin();p!=vtx->particles_in_end();++p ) if (MC::isQuark(*p) || MC::isGluon(*p)) partonsin++;
274#else
275 for (auto p = vtx->particles_in_const_begin();p!=vtx->particles_in_const_end();++p ) if (MC::isQuark(*p) || MC::isGluon(*p)) partonsin++;
276#endif
277 for (auto& p : *vtx) if (p->pdg_id() == 91||p->pdg_id() == 92||p->pdg_id() == 94) showerout++;
278 if ( partonsin >= 2 && showerout == 0 ) {
279 ref_bc.insert(vtx->barcode());
280 }
281 }
282 std::set<int> che_bc;
283 for ( auto vtxIt = checkMcEvts->vertices_begin(); vtxIt != checkMcEvts->vertices_end(); ++vtxIt ) {
284 auto vtx =*vtxIt;
285 che_bc.insert(vtx->barcode());
286 }
287 std::set<int> allbarcodes;
288 for (const auto &bc: ref_bc) allbarcodes.insert(bc);
289 for (const auto &bc: che_bc) allbarcodes.insert(bc);
290 for (const auto &bc: allbarcodes){
291 auto ref_it = ref_bc.find(bc);
292 auto che_it = che_bc.find(bc);
293 if (ref_it == ref_bc.end()) {ATH_MSG_WARNING("In Event [" << evtNbr << "]: got null ref-vertex (barcode: " << bc << ")"); continue; }
294 if (che_it == che_bc.end()) {ATH_MSG_WARNING("Output GenEvent is missing the selected HardScattering Vtx !!"<< " (" << bc << ")"); continue; }
295 const auto refvtx = refMcEvts->barcode_to_vertex(bc);
296 const auto chevtx = checkMcEvts->barcode_to_vertex(bc);
297 (*m_outFile) << refvtx << std::endl;
298 (*m_outFile) << chevtx << std::endl;
299 (*m_outFile) << "---------" << std::endl;
300 if ( !compareVtx( refvtx, chevtx ) ) {
301 ATH_MSG_WARNING("Selected HardScattering vertices are NOT the same !!"<< " at Event [" << evtNbr << "]"<< " refVtx = " << refvtx<<" chevtx = " << chevtx);
302 }
303 }
304 (*m_outFile) << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
305#endif
306
307 return StatusCode::SUCCESS;
308}
309
311{
312 if ( !vtx1 || !vtx2 ) {
313 ATH_MSG_ERROR("One of vertices is a NULL pointer !!" << endmsg
314 << " vtx1: " << vtx1 << endmsg
315 << " vtx2: " << vtx2);
316 return false;
317 }
318
319#ifdef HEPMC3
320 auto inVtx1 = vtx1->particles_in();
321 auto inVtx2 = vtx2->particles_in();
322 if (inVtx1.size() != inVtx2.size()) {
323 ATH_MSG_ERROR("Not the same number of branches !!" << endmsg << " in: " << inVtx1.size() << "\t" << inVtx2.size());
324 return false;
325 }
326 std::sort(inVtx1.begin(), inVtx1.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
327 std::sort(inVtx2.begin(), inVtx2.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
328 for (size_t i=0; i<inVtx1.size(); ++i){
329 if ( compareParts( inVtx1.at(i), inVtx2.at(i) ) ) continue;
330 ATH_MSG_ERROR("In-going particles are NOT matching !!");
331 return false;
332 }
333 auto outVtx1 = vtx1->particles_out();
334 auto outVtx2 = vtx2->particles_out();
335 if (outVtx1.size() != outVtx2.size()) {
336 ATH_MSG_ERROR("Not the same number of branches !!" << endmsg << " out: " << outVtx1.size() << "\t" << outVtx2.size());
337 return false;
338 }
339 std::sort(outVtx1.begin(), outVtx1.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
340 std::sort(outVtx2.begin(), outVtx2.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
341 for (size_t i=0; i<outVtx1.size(); ++i){
342 if ( compareParts( outVtx1.at(i), outVtx2.at(i) ) ) continue;
343 ATH_MSG_ERROR("Out-going particles are NOT matchiutg !!");
344 return false;
345 }
346#else
347 const int inVtx1 = vtx1->particles_in_size();
348 const int inVtx2 = vtx2->particles_in_size();
349
350 const int outVtx1 = vtx1->particles_out_size();
351 const int outVtx2 = vtx2->particles_out_size();
352
353 if ( inVtx1 != inVtx2 || outVtx1 != outVtx2 ) {
354 ATH_MSG_ERROR("Not the same number of branches !!" << endmsg
355 << " in: " << inVtx1 << "\t" << inVtx2 << endmsg
356 << " out: " << outVtx1 << "\t" << outVtx2);
357 return false;
358 }
359
360 for ( HepMC::GenVertex::particles_in_const_iterator inPart1 = vtx1->particles_in_const_begin();
361 inPart1 != vtx1->particles_in_const_end();
362 ++inPart1 ) {
363 bool inParticleOK = false;
364 for ( HepMC::GenVertex::particles_in_const_iterator inPart2 = vtx2->particles_in_const_begin();
365 inPart2 != vtx2->particles_in_const_end();
366 ++inPart2 ) {
367 if ( compareParts( *inPart1, *inPart2 ) ) {
368 inParticleOK = true;
369 break;
370 }
371 } //> end loop over in-part2
372
373 if ( !inParticleOK ) {
374 ATH_MSG_ERROR("In-going particles are NOT matching !!");
375 return false;
376 }
377
378 }//> end loop over in-part1
379
380
381 for ( HepMC::GenVertex::particles_out_const_iterator outPart1 = vtx1->particles_out_const_begin();
382 outPart1 != vtx1->particles_out_const_end();
383 ++outPart1 ) {
384 bool outParticleOK = false;
385 for ( HepMC::GenVertex::particles_out_const_iterator outPart2 = vtx2->particles_out_const_begin();
386 outPart2 != vtx2->particles_out_const_end();
387 ++outPart2 ) {
388 if ( compareParts( *outPart1, *outPart2 ) ) {
389 outParticleOK = true;
390 break;
391 }
392 } //> end loop over out-part2
393
394 if ( !outParticleOK ) {
395 ATH_MSG_ERROR("Out-going particles are NOT matching !!");
396 return false;
397 }
398
399 }//> end loop over out-part1
400#endif
401
402 return true;
403}
404
405bool
407{
408 if ( !p1 || !p2 ) {
409 ATH_MSG_ERROR("One of particles is a NULL pointer !!" << endmsg
410 << " p1: " << p1 << endmsg
411 << " p2: " << p2);
412 return false;
413 }
414
415 if ( HepMC::barcode(p1) != HepMC::barcode(p2) ) {
416 return false;
417 }
418
419 const HepMC::FourVector hlv1 = p1->momentum();
420 const int id1 = p1->pdg_id();
421 const int status1 = p1->status();
422 auto flow1 = HepMC::flow(p1);
423 auto pol1 = HepMC::polarization(p1);
424
425 const HepMC::FourVector hlv2 = p2->momentum();
426 const int id2 = p2->pdg_id();
427 const int status2 = p2->status();
428 auto flow2 = HepMC::flow(p2);
429 auto pol2 = HepMC::polarization(p2);
430
431 const bool isOK = ( hlv1 == hlv2 &&
432 id1 == id2 &&
433 status1 == status2 &&
434 flow1 == flow2 &&
435 pol1 == pol2 );
436
437
438 if ( !isOK ) {
440 ("=============================" << endmsg
441 << "\thlv: " << std::boolalpha << (hlv1 == hlv2 ) << endmsg
442 << "\tid: " << std::boolalpha << (id1 == id2 ) << endmsg
443 << "\tstatus: " << std::boolalpha << (status1 == status2) << endmsg
444 << "\tflow: " << std::boolalpha << (flow1 == flow2 ) << endmsg
445 << "\tpolar: " << std::boolalpha << (pol1 == pol2 ) << endmsg
446 << "=============================");
447 }
448
449 return isOK;
450}
451
453{
454 ATH_CHECK( m_refMcEventWriter.retrieve() );
455 ATH_CHECK( m_checkMcEventWriter.retrieve() );
456
457 // now we configure the tools
458 SmartIF<IProperty> prop{m_refMcEventWriter.get()};
459 ATH_CHECK( prop.isValid() );
460 ATH_CHECK( prop->setProperty("McEvents", m_refMcEventsName.value()) );
461
462 prop = m_checkMcEventWriter.get();
463 ATH_CHECK( prop.isValid() );
464 ATH_CHECK( prop->setProperty("McEvents", m_checkMcEventsName.value()) );
465
466 return StatusCode::SUCCESS;
467}
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ATLAS-specific HepMC functions.
static Double_t a
HWIdentifier id2
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
size_type size() const noexcept
Returns the number of elements in the collection.
virtual StatusCode initializeTool()
Non-const methods:
ToolHandle< IIOHepMcTool > HepMcTool_t
shorthand for lazy people (good coders are lazy people, aren't they ?)
bool compareParts(const HepMC::ConstGenParticlePtr &p1, const HepMC::ConstGenParticlePtr &p2) const
Check that 2 given particles are the same:
StatusCode setupHepMcWriterTools()
Request pointers to the HepMcWriterTools to be able to write out HepMC::GenEvent for further comparis...
virtual StatusCode executeTool()
Main method to perform the validation.
StringProperty m_hardVtxOutFileName
Name of the output text file which will contain the hard-scattering vertices.
virtual StatusCode finalizeTool()
HepMcTool_t m_checkMcEventWriter
Tool to write the 'to-be-checked' HepMC::GenEvent into a dedicated file.
bool compareVtx(const HepMC::ConstGenVertexPtr &vtx1, const HepMC::ConstGenVertexPtr &vtx2) const
Check that 2 given vertices are the same:
StringProperty m_checkMcEventsName
Location of the 'to-be-validated' McEventCollection.
std::ofstream * m_outFile
Pointer to the output text file containing hard-scattering vertices.
GenAodValidationTool()
Default constructor:
virtual ~GenAodValidationTool()
Destructor:
StringProperty m_refMcEventsName
Location of the reference McEventCollection.
HepMcTool_t m_refMcEventWriter
Tool to write the reference HepMC::GenEvent into a dedicated file.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
TruthParticleValidationBaseTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
int barcode(const T *p)
Definition Barcode.h:16
Polarization polarization(const T &a)
int flow(const T &a, int i)
Definition Flow.h:51
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
const HepMC::GenVertex * ConstGenVertexPtr
Definition GenVertex.h:60
bool isQuark(const T &p)
PDG rule 2: Quarks and leptons are numbered consecutively starting from 1 and 11 respectively; to do ...
bool isGluon(const T &p)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.