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
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 std::map<int,int> ref_bc_to_id;
229 const auto& refvertices = refMcEvts->vertices();
230 for ( const auto& vtx: refvertices) {
231 // AV: this algorthm is not very correct
232 int partonsin = 0;
233 int showerout = 0;
234 for (auto& p: vtx->particles_in()) if (MC::isQuark(p) || MC::isGluon(p)) partonsin++;
235 for (auto& p: vtx->particles_out()) if (p->pdg_id() == 91||p->pdg_id() == 92||p->pdg_id() == 94) showerout++;
236 if ( partonsin >= 2 && showerout == 0 ) {
237 ref_bc_to_id[HepMC::barcode(vtx)] = vtx->id();
238 }
239 }
240 std::map<int,int> che_bc_to_id;
241 const auto& chevertices = checkMcEvts->vertices();
242 for (const auto& checkVtx: chevertices) {
243 che_bc_to_id[HepMC::barcode(checkVtx)] = checkVtx->id();
244 }
245 std::set<int> allbarcodes;
246 for (const auto &[bc,id]: ref_bc_to_id) allbarcodes.insert(bc);
247 for (const auto &[bc,id]: che_bc_to_id) allbarcodes.insert(bc);
248 for (const auto &bc: allbarcodes){
249 auto ref_it = ref_bc_to_id.find(bc);
250 auto che_it = che_bc_to_id.find(bc);
251 if (ref_it == ref_bc_to_id.end()) {ATH_MSG_WARNING("In Event [" << evtNbr << "]: got null ref-vertex (barcode: " << bc << ")"); continue; }
252 if (che_it == che_bc_to_id.end()) {ATH_MSG_WARNING("Output GenEvent is missing the selected HardScattering Vtx !!"<< " (" << bc << ")"); continue; }
253 if (-ref_it->second > int(refvertices.size()) ) { continue; }
254 if (-che_it->second > int(chevertices.size()) ) { continue; }
255 const auto& refvtx = refvertices[-ref_it->second-1];
256 const auto& chevtx = chevertices[-che_it->second-1];
257 (*m_outFile) << refvtx << std::endl;
258 (*m_outFile) << chevtx << std::endl;
259 (*m_outFile) << "---------" << std::endl;
260 if ( !compareVtx( refvtx, chevtx ) ) {
261 ATH_MSG_WARNING("Selected HardScattering vertices are NOT the same !!"<< " at Event [" << evtNbr << "]"<< " refVtx = " << refvtx<<" chevtx = " << chevtx);
262 }
263 }
264 (*m_outFile) << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
265
266 return StatusCode::SUCCESS;
267}
268
270{
271 if ( !vtx1 || !vtx2 ) {
272 ATH_MSG_ERROR("One of vertices is a NULL pointer !!" << endmsg
273 << " vtx1: " << vtx1 << endmsg
274 << " vtx2: " << vtx2);
275 return false;
276 }
277 auto inVtx1 = vtx1->particles_in();
278 auto inVtx2 = vtx2->particles_in();
279 if (inVtx1.size() != inVtx2.size()) {
280 ATH_MSG_ERROR("Not the same number of branches !!" << endmsg << " in: " << inVtx1.size() << "\t" << inVtx2.size());
281 return false;
282 }
283 std::sort(inVtx1.begin(), inVtx1.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
284 std::sort(inVtx2.begin(), inVtx2.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
285 for (size_t i=0; i<inVtx1.size(); ++i){
286 if ( compareParts( inVtx1.at(i), inVtx2.at(i) ) ) continue;
287 ATH_MSG_ERROR("In-going particles are NOT matching !!");
288 return false;
289 }
290 auto outVtx1 = vtx1->particles_out();
291 auto outVtx2 = vtx2->particles_out();
292 if (outVtx1.size() != outVtx2.size()) {
293 ATH_MSG_ERROR("Not the same number of branches !!" << endmsg << " out: " << outVtx1.size() << "\t" << outVtx2.size());
294 return false;
295 }
296 std::sort(outVtx1.begin(), outVtx1.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
297 std::sort(outVtx2.begin(), outVtx2.end(), [](auto& a, auto& b) -> bool{return a->momentum().pz() > b->momentum().pz(); });
298 for (size_t i=0; i<outVtx1.size(); ++i){
299 if ( compareParts( outVtx1.at(i), outVtx2.at(i) ) ) continue;
300 ATH_MSG_ERROR("Out-going particles are NOT matchiutg !!");
301 return false;
302 }
303 return true;
304}
305
306bool
308{
309 if ( !p1 || !p2 ) {
310 ATH_MSG_ERROR("One of particles is a NULL pointer !!" << endmsg
311 << " p1: " << p1 << endmsg
312 << " p2: " << p2);
313 return false;
314 }
315
316 if ( HepMC::barcode(p1) != HepMC::barcode(p2) ) {
317 return false;
318 }
319
320 const HepMC::FourVector hlv1 = p1->momentum();
321 const int id1 = p1->pdg_id();
322 const int status1 = p1->status();
323 auto flow1 = HepMC::flow(p1);
324 auto pol1 = HepMC::polarization(p1);
325
326 const HepMC::FourVector hlv2 = p2->momentum();
327 const int id2 = p2->pdg_id();
328 const int status2 = p2->status();
329 auto flow2 = HepMC::flow(p2);
330 auto pol2 = HepMC::polarization(p2);
331
332 const bool isOK = ( hlv1 == hlv2 &&
333 id1 == id2 &&
334 status1 == status2 &&
335 flow1 == flow2 &&
336 pol1 == pol2 );
337
338
339 if ( !isOK ) {
341 ("=============================" << endmsg
342 << "\thlv: " << std::boolalpha << (hlv1 == hlv2 ) << endmsg
343 << "\tid: " << std::boolalpha << (id1 == id2 ) << endmsg
344 << "\tstatus: " << std::boolalpha << (status1 == status2) << endmsg
345 << "\tflow: " << std::boolalpha << (flow1 == flow2 ) << endmsg
346 << "\tpolar: " << std::boolalpha << (pol1 == pol2 ) << endmsg
347 << "=============================");
348 }
349
350 return isOK;
351}
352
354{
355 ATH_CHECK( m_refMcEventWriter.retrieve() );
356 ATH_CHECK( m_checkMcEventWriter.retrieve() );
357
358 // now we configure the tools
359 SmartIF<IProperty> prop{m_refMcEventWriter.get()};
360 ATH_CHECK( prop.isValid() );
361 ATH_CHECK( prop->setProperty("McEvents", m_refMcEventsName.value()) );
362
363 prop = m_checkMcEventWriter.get();
364 ATH_CHECK( prop.isValid() );
365 ATH_CHECK( prop->setProperty("McEvents", m_checkMcEventsName.value()) );
366
367 return StatusCode::SUCCESS;
368}
#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
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:15
HepMC3::FourVector FourVector
Polarization polarization(const T &a)
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
Definition GenParticle.h:20
int flow(const HepMC3::GenParticlePtr &p, int i)
Definition Flow.h:13
HepMC3::ConstGenVertexPtr ConstGenVertexPtr
Definition GenVertex.h:24
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
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.