ATLAS Offline Software
Loading...
Searching...
No Matches
TestHepMC.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef XAOD_ANALYSIS
5
7#include "GaudiKernel/DataSvc.h"
8#include "GaudiKernel/SystemOfUnits.h"
11
12// For find
13#include <algorithm>
14
15
16
17TestHepMC::TestHepMC(const std::string& name, ISvcLocator* pSvcLocator)
18 : GenBase(name, pSvcLocator),
19 m_thistSvc("THistSvc", name)
20{
21 declareProperty("MaxLoops", m_maxloops = -1); //< Maximal number of particles allowed in the loops. -1 == any number
22 declareProperty("PdgToSearch", m_pdg = 15); //< @todo This test is a bit weirdly specific to taus
23 declareProperty("CmEnergy", m_cm_energy = -1); // in MeV, -1 = get from event
24 declareProperty("MinTransVtxDisp", m_min_dist_trans = 0.); // mm
25 declareProperty("MaxTransVtxDisp", m_max_dist_trans = 100.); // mm
26 declareProperty("MaxVtxDisp", m_max_dist = 1000.); // mm;
27 declareProperty("EnergyDifference", m_energy_diff = 1000.); // MeV
28 declareProperty("EnergyDifferenceError", m_max_energy_diff = 100000.); // MeV
29 declareProperty("CmeDifference", m_cme_diff = 1.); // MeV
30 declareProperty("DumpEvent", m_dumpEvent = false);
31 declareProperty("MinTau", m_min_tau = 1/300.); // ns; corresponds to 1mm
32 declareProperty("MaxNonG4Energy", m_nonG4_energy_threshold = 100.); //MeV
33 declareProperty("TauEffThreshold", m_tau_eff_threshold = 0.1); // fraction
34 declareProperty("EffWarnThreshold", m_eff_warn_threshold=0.99); // fraction
35 declareProperty("EffFailThreshold", m_eff_fail_threshold=0.98); // fraction
36 declareProperty("AccuracyMargin", m_accur_margin=0.); //MeV
37
38 declareProperty("G4ExtraWhiteFile", m_paramFile = "g4_extrawhite.param" );
39 // a list of allowed pdgid which however might not follow the official rules
40 declareProperty("UnknownPDGIDFile", m_unknownPDGIDFile = "pdgid_extras.txt" );
41
42 declareProperty("NoDecayVertexStatuses", m_vertexStatuses );
43
44 declareProperty("BeamEnergyTest", m_beamEnergyTest = true); //switching off inactive
45 declareProperty("VtxNaNTest", m_vtxNaNTest = true);
46 declareProperty("VtxDisplacedTest", m_vtxDisplacedTest = true);
47 declareProperty("MomNaNTest", m_momNaNTest = true);
48 declareProperty("LifeTimeTest", m_lifeTimeTest = true);
49 declareProperty("EnergyG4Test", m_energyG4Test = true);
50 declareProperty("EnergyImbalanceTest", m_energyImbalanceTest = true);
51 declareProperty("MomImbalanceTest", m_momImbalanceTest = true);
52 declareProperty("NegativeEnergyTest", m_negativeEnergyTest = true);
53 declareProperty("TachyonsTest", m_tachyonsTest = true);
54 declareProperty("UnstableNoVtxTest", m_unstableNoVtxTest = true);
55 declareProperty("Pi0NoVtxTest", m_pi0NoVtxTest = true);
56 declareProperty("UndisplacedDaughtersTest", m_undisplacedDaughtersTest = true);
57 declareProperty("UknownPDGIDTest", m_unknownPDGIDTest = true);
58 declareProperty("AllowMissingCrossSection", m_allowMissingXSec = false);
59
60 m_vertexStatuses.push_back( 1 );
61 m_vertexStatuses.push_back( 3 );
62 m_vertexStatuses.push_back( 4 );
63
64
65 declareProperty("THistSvc", m_thistSvc);
66
67 declareProperty("DoHist", m_doHist=false); //histograming yes/no true/false
68
69 m_nPass = 0;
70 m_nFail = 0;
71
72 m_TotalTaus = 0;
74
75 // Check counters
101 m_noXSECset = 0;
102
118 m_h_photon_mass = 0;
128}
129
130
133
134 if (m_doHist){
135 CHECK(m_thistSvc.retrieve());
136
137 m_h_energy_dispVtxCheck = new TH1F("h_energy_dispVtxCheck", "h_energy_dispVtxCheck", 2000, 0., 2000.);
138 m_h_energy_dispVtxCheck_lt10 = new TH1F("h_energy_dispVtxCheck_lt10", "h_energy_dispVtxCheck_lt10", 1000, 0., 10.);
139 m_h_pdgid_dispVtxCheck = new TH1F("h_pdgid_dispVtxCheck", "h_pdgid_dispVtxCheck", 10000, 0., 10000.);
140 m_h_status_dispVtxCheck = new TH1F("h_status_dispVtxCheck", "h_status_dispVtxCheck", 10000, 0., 10000.);
141 m_h_px_dispVtxCheck = new TH1F("h_px_dispVtxCheck", "h_px_dispVtxCheck", 4000, -2000., 2000.);
142 m_h_py_dispVtxCheck = new TH1F("h_py_dispVtxCheck", "h_py_dispVtxCheck", 4000, -2000., 2000.);
143 m_h_pz_dispVtxCheck = new TH1F("h_pz_dispVtxCheck", "h_pz_dispVtxCheck", 4000, -2000., 2000.);
144 m_h_vx_dispVtxCheck = new TH1F("h_vx_dispVtxCheck", "h_vx_dispVtxCheck", 40000, -200., 200);
145 m_h_vy_dispVtxCheck = new TH1F("h_vy_dispVtxCheck", "h_vy_dispVtxCheck", 40000, -200., 200);
146 m_h_vz_dispVtxCheck = new TH1F("h_vz_dispVtxCheck", "h_vz_dispVtxCheck", 40000, -200., 200);
147 m_h_vxprod_dispVtxCheck = new TH1F("h_vxprod_dispVtxCheck", "h_vxprod_dispVtxCheck", 40000, -200., 200.);
148 m_h_vyprod_dispVtxCheck = new TH1F("h_vyprod_dispVtxCheck", "h_vyprod_dispVtxCheck", 40000, -200., 200.);
149 m_h_vzprod_dispVtxCheck = new TH1F("h_vzprod_dispVtxCheck", "h_vzprod_dispVtxCheck", 40000, -200., 200.);
150 m_h_vtxprod_dispVtxCheck = new TH1F("h_vtxprod_dispVtxCheck", "h_vtxprod_dispVtxCheck", 20000, 0., 200.);
151 m_h_vtxend_dispVtxCheck = new TH1F("h_vtxend_dispVtxCheck", "h_vtxend_dispVtxCheck", 20000, 0., 200.);
152 m_h_photon_mass = new TH1F("h_photon_mass", "h_photon_mass", 20000, -10000., 10000);
153 m_h_photon_energy = new TH1F("h_photon_energy", "h_photon_energy", 20000, -10000., 10000);
154 m_h_photon_e2_p2_e2 = new TH1F("h_photon_e2_p2_e2", "h_photon_e2_p2_e2", 20000, -10., 10);
155 m_h_energyImbalance = new TH1F("h_energyImbalance", "h_energyImbalance", 2000, 0., 2000.);
156 m_h_momentumImbalance_px = new TH1F("h_momentumImbalance_px", "h_momentumImbalance_px", 2000,0., 2000.);
157 m_h_momentumImbalance_py = new TH1F("h_momentumImbalance_py", "h_momentumImbalance_py", 2000,0., 2000.);
158 m_h_momentumImbalance_pz = new TH1F("h_momentumImbalance_pz", "h_momentumImbalance_pz", 2000,0., 2000.);
159 m_h_beamparticle1_Energy = new TH1F("h_beamparticle1_Energy", "h_beamparticle1_Energy", 14000,0., 14000.);
160 m_h_beamparticle2_Energy = new TH1F("h_beamparticle2_Energy", "h_beamparticle2_Energy", 14000,0., 14000.);
161 m_h_cmEnergyDiff = new TH1F("h_cmEnergyDiff", "h_cmEnergyDiff", 8000, -4000., 4000.);
162
163 CHECK(m_thistSvc->regHist("/TestHepMCname/h_energy_dispVtxCheck", m_h_energy_dispVtxCheck));
164 CHECK(m_thistSvc->regHist("/TestHepMCname/h_energy_dispVtxCheck_lt10", m_h_energy_dispVtxCheck_lt10));
165 CHECK(m_thistSvc->regHist("/TestHepMCname/h_pdgid_dispVtxCheck", m_h_pdgid_dispVtxCheck));
166 CHECK(m_thistSvc->regHist("/TestHepMCname/h_status_dispVtxCheck", m_h_status_dispVtxCheck));
167 CHECK(m_thistSvc->regHist("/TestHepMCname/h_px_dispVtxCheck", m_h_px_dispVtxCheck));
168 CHECK(m_thistSvc->regHist("/TestHepMCname/h_py_dispVtxCheck", m_h_py_dispVtxCheck));
169 CHECK(m_thistSvc->regHist("/TestHepMCname/h_pz_dispVtxCheck", m_h_pz_dispVtxCheck));
170 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vx_dispVtxCheck", m_h_vx_dispVtxCheck));
171 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vy_dispVtxCheck", m_h_vy_dispVtxCheck));
172 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vz_dispVtxCheck", m_h_vz_dispVtxCheck));
173 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vxprod_dispVtxCheck", m_h_vxprod_dispVtxCheck));
174 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vyprod_dispVtxCheck", m_h_vyprod_dispVtxCheck));
175 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vzprod_dispVtxCheck", m_h_vzprod_dispVtxCheck));
176 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vtxprod_dispVtxCheck", m_h_vtxprod_dispVtxCheck));
177 CHECK(m_thistSvc->regHist("/TestHepMCname/h_vtxend_dispVtxCheck", m_h_vtxend_dispVtxCheck));
178 CHECK(m_thistSvc->regHist("/TestHepMCname/h_photon_mass", m_h_photon_mass));
179 CHECK(m_thistSvc->regHist("/TestHepMCname/h_photon_energy", m_h_photon_energy));
180 CHECK(m_thistSvc->regHist("/TestHepMCname/h_photon_e2_p2_e2", m_h_photon_e2_p2_e2));
181 CHECK(m_thistSvc->regHist("/TestHepMCname/h_energyImbalance", m_h_energyImbalance));
182 CHECK(m_thistSvc->regHist("/TestHepMCname/h_momentumImbalance_px", m_h_momentumImbalance_px));
183 CHECK(m_thistSvc->regHist("/TestHepMCname/h_momentumImbalance_py", m_h_momentumImbalance_py));
184 CHECK(m_thistSvc->regHist("/TestHepMCname/h_momentumImbalance_pz", m_h_momentumImbalance_pz));
185 CHECK(m_thistSvc->regHist("/TestHepMCname/h_beamparticle1_Energy", m_h_beamparticle1_Energy));
186 CHECK(m_thistSvc->regHist("/TestHepMCname/h_beamparticle2_Energy", m_h_beamparticle2_Energy));
187 CHECK(m_thistSvc->regHist("/TestHepMCname/h_cmEnergyDiff", m_h_cmEnergyDiff));
188
189 ATH_MSG_INFO("No decay vertex - is ignored for particles with status (list):" );
190 for ( unsigned int i = 0; i < m_vertexStatuses.size(); i++ ) ATH_MSG_INFO(" : " << m_vertexStatuses.at(i) );
191 ATH_MSG_INFO("Vertex statuses finished");
192
193 } // End of histogramming setup
194
195 // open the files and read G4particle_acceptlist.txt
196
197 const std::string& fileLocation = PathResolverFindDataFile ( "G4particle_acceptlist.txt" );
198 std::ifstream G4file;
199 G4file.open(fileLocation);
200 std::string line;
201 int G4pdgID;
202 if (!G4file.fail()){
203 while(std::getline(G4file,line)){
204 std::stringstream ss(line);
205 ss >> G4pdgID;
206 m_G4pdgID_tab.push_back(G4pdgID);
207 }
208 G4file.close();
209 }
210 else {
211 ATH_MSG_WARNING("Failed to open G4particle_acceptlist.txt, checking that all particles are known by Genat4 cannot be performed");
212 }
213
214 // Open the param file (G4 accept list)
215 G4file.open(m_paramFile.c_str());
216 if (!G4file.fail()){
217 ATH_MSG_INFO("extra accept list for G4 found " << m_paramFile.c_str());
218 while(std::getline(G4file,line)){
219 std::stringstream ss(line);
220 ss >> G4pdgID;
221 m_G4pdgID_tab.push_back(G4pdgID);
222 }
223 G4file.close();
224 }
225 else {
226 ATH_MSG_INFO("extra accept list for G4 not provided ");
227 }
228
229 // Open the files and read susyParticlePdgid.txt
230 std::ifstream susyFile;
231 susyFile.open("susyParticlePdgid.txt");
232 int susyPdgID;
233 if (!susyFile.fail()){
234 while(getline(susyFile,line)){
235 std::stringstream ss1(line);
236 ss1 >> susyPdgID;
237 m_SusyPdgID_tab.push_back(susyPdgID);
238 }
239 susyFile.close();
240 }
241 else{
242 ATH_MSG_WARNING("Failed to open susyParticlePdgid.txt, listing particles not present in PDTTable");
243 }
244
245 // Open the file of extra PDG IDs that don't need to obey the rules
246 std::ifstream pdgFile;
247 pdgFile.open(m_unknownPDGIDFile.c_str());
248 int pdgID;
249 if (!pdgFile.fail()){
250 ATH_MSG_INFO("extra accept list for PDG IDs found " << m_unknownPDGIDFile.c_str());
251 while(std::getline(pdgFile,line)){
252 std::stringstream ss(line);
253 ss >> pdgID;
254 m_uknownPDGID_tab.push_back(pdgID);
255 }
256 pdgFile.close();
257 }
258 else {
259 ATH_MSG_INFO("extra accept list for PDG IDs not provided");
260 }
261
262 // Print Efficiency warning and error thresholds
263 ATH_MSG_INFO("EffWarnThreshold = " << m_eff_warn_threshold * 100 << " %");
264 ATH_MSG_INFO("EffFailThreshold = " << m_eff_fail_threshold * 100 << " %");
265
266 return StatusCode::SUCCESS;
267}
268
269
270StatusCode TestHepMC::execute() {
271
272 // Holder for filter outcome; allows us to check all filters on each event and diagnose multiple problems at once
273 bool filter_pass = true;
274
275 // Loop over all events in McEventCollection
276 for(const HepMC::GenEvent* evt : *events_const()) {
277 double totalPx = 0;
278 double totalPy = 0;
279 double totalPz = 0;
280 double totalE = 0;
281 double nonG4_energy = 0;
282 std::vector<HepMC::ConstGenParticlePtr> negEnPart;
283 std::vector<HepMC::ConstGenParticlePtr> tachyons;
284 std::vector<HepMC::ConstGenParticlePtr> unstNoEnd;
285 std::vector<HepMC::ConstGenParticlePtr> unDecPi0;
286 std::vector<HepMC::ConstGenParticlePtr> undisplaceds;
287
288 m_looper.findLoops(evt,true);
289 if (!m_looper.loop_particles().empty() || !m_looper.loop_vertices().empty()) {
290 ATH_MSG_DEBUG("Found " << m_looper.loop_vertices().size() << " vertices in loops");
291 ATH_MSG_DEBUG("Found " << m_looper.loop_particles().size() << " particles in loops");
292 ATH_MSG_DEBUG("Please use MC::Loops::findLoops for this event to obtain all particles and vertices in the loops");
293 if (m_maxloops > 0 && m_looper.loop_particles().size() > static_cast<std::size_t>(m_maxloops) ) filter_pass = false;
294 }
295
296#ifdef HEPMC3
297 const auto xsec = evt->cross_section();
298 if (!xsec) {
299 ATH_MSG_WARNING("WATCH OUT: event is missing the generator cross-section!");
300 ++m_noXSECset;
301 if (m_allowMissingXSec) {
302 ATH_MSG_WARNING("-> Adding a dummy cross-section for debugging purposes.");
303 // for debugging purposes only -> set a dummy cross-section to make TestHepMC happy
304 std::shared_ptr<HepMC3::GenCrossSection> dummy_xsec = std::make_shared<HepMC3::GenCrossSection>();
305 dummy_xsec->set_cross_section(1.0,0.0);
306 HepMC::GenEvent* evt_nonconst = const_cast<HepMC::GenEvent*>(evt);
307 evt_nonconst->set_cross_section(std::move(dummy_xsec));
308 }
309 else {
310 ATH_MSG_WARNING("-> Will report this as failure.");
311 }
312 }
313
314 // Check beams and work out per-event beam energy
315 std::vector<std::shared_ptr<const HepMC3::GenParticle>> beams_t;
316 for (auto p : evt->beams()) { if (p->status() == 4) beams_t.push_back(std::move(p)); }
317 std::pair<std::shared_ptr<const HepMC3::GenParticle>,std::shared_ptr<const HepMC3::GenParticle>> beams;
318 if (beams_t.size() == 2) {
319 beams.first=beams_t.at(0);
320 beams.second=beams_t.at(1);
321 } else {
322 ATH_MSG_WARNING("Invalid number of beam particles " << beams_t.size() << " this generator interface should be fixed");
324 for (const auto& part: beams_t) HepMC3::Print::line(part);
325 }
326#else
327 auto beams = evt->beam_particles();
328#endif
329 double cmenergy = m_cm_energy;
330 if (!HepMC::valid_beam_particles(evt)) {
331 ATH_MSG_WARNING("Invalid beam particle pointers -- this generator interface should be fixed");
332 if (cmenergy < 0) ATH_MSG_WARNING("Invalid expected beam energy: " << cmenergy << " MeV");
334 } else {
335 if (!MC::isBeam(beams.first) || !MC::isBeam(beams.second)) {
336 ATH_MSG_WARNING("Beam particles have incorrectly set status -- this generator interface should be fixed");
338 }
339 const double sumE = beams.first->momentum().e() + beams.second->momentum().e();
340 const double sumP = beams.first->momentum().pz() + beams.second->momentum().pz();
341 cmenergy = std::sqrt(sumE*sumE - sumP*sumP);
342
343 if(beams.first->pdg_id() == MC::OXYGEN && beams.second->pdg_id() == MC::OXYGEN){//OO collisions
344 cmenergy /= MC::baryonNumber(MC::OXYGEN); // divided by the total number of nucleons per nucleus
345 }
346 if(beams.first->pdg_id() == MC::LEAD && beams.second->pdg_id() == MC::LEAD){//PbPb collisions
347 cmenergy /= MC::baryonNumber(MC::LEAD); // divided by the total number of nucleons per nucleus
348 }
349 if(beams.first->pdg_id() == MC::OXYGEN && beams.second->pdg_id() == MC::PROTON){//Op collisions
350 cmenergy = -2.0*beams.second->momentum().pz()*std::sqrt(static_cast<double>(MC::numberOfProtons(MC::OXYGEN))/MC::baryonNumber(MC::OXYGEN));
351 }
352 if(beams.first->pdg_id() == MC::PROTON && beams.second->pdg_id() == MC::OXYGEN){//pO collisions
353 cmenergy = 2.0*beams.first->momentum().pz()*std::sqrt(static_cast<double>(MC::numberOfProtons(MC::OXYGEN))/MC::baryonNumber(MC::OXYGEN));
354 }
355 if(beams.first->pdg_id() == MC::LEAD && beams.second->pdg_id() == MC::PROTON){//Pbp collisions
356 cmenergy = -2.0*beams.second->momentum().pz()*std::sqrt(static_cast<double>(MC::numberOfProtons(MC::LEAD))/MC::baryonNumber(MC::LEAD));
357 }
358 if(beams.first->pdg_id() == MC::PROTON && beams.second->pdg_id() == MC::LEAD){//pPb collisions
359 cmenergy = 2.0*beams.first->momentum().pz()*std::sqrt(static_cast<double>(MC::numberOfProtons(MC::LEAD))/MC::baryonNumber(MC::LEAD));
360 }
361 if(beams.first->pdg_id() == MC::OXYGEN && beams.second->pdg_id() == MC::HELIUM){//OHe collisions
362 cmenergy /= std::sqrt(static_cast<double>(MC::baryonNumber(MC::OXYGEN)*MC::baryonNumber(MC::HELIUM)));
363 }
364 if(beams.first->pdg_id() == MC::HELIUM && beams.second->pdg_id() == MC::OXYGEN){//HeO collisions
365 cmenergy /= std::sqrt(static_cast<double>(MC::baryonNumber(MC::OXYGEN)*MC::baryonNumber(MC::HELIUM)));
366 }
367
368 if (m_cm_energy > 0 && std::abs(cmenergy - m_cm_energy) > m_cme_diff) {
369 ATH_MSG_FATAL("Beam particles have incorrect energy: " << m_cm_energy/Gaudi::Units::GeV << " GeV expected, vs. " << cmenergy/Gaudi::Units::GeV << " GeV found");
370 setFilterPassed(false);
371 if (m_doHist){
372 m_h_beamparticle1_Energy->Fill(beams.first->momentum().e()/Gaudi::Units::GeV);
373 m_h_beamparticle2_Energy->Fill(beams.second->momentum().e()/Gaudi::Units::GeV);
374 m_h_cmEnergyDiff->Fill((cmenergy-m_cm_energy)/Gaudi::Units::GeV);
375 }
377 // Special case: this is so bad that we immediately fail out
378 return StatusCode::FAILURE;
379 }
380 }
381
382 // Check vertices
383 int vtxDisplacedstatuscode12CheckRateCnt=0;
384 int vtxDisplacedstatuscodenot12CheckRateCnt=0;
385 int vtxDisplacedMoreThan_1m_CheckRateCnt=0;
386#ifdef HEPMC3
387 for (const auto& vtx: evt->vertices()) {
388#else
389 for (auto vitr = evt->vertices_begin(); vitr != evt->vertices_end(); ++vitr ) {
390 const HepMC::GenVertex* vtx = *vitr;
391#endif
392 const HepMC::FourVector pos = vtx->position();
393
394 // Check for NaNs and infs in vertex position components
395 if ( std::isnan(pos.x()) || std::isinf(pos.x()) ||
396 std::isnan(pos.y()) || std::isinf(pos.y()) ||
397 std::isnan(pos.z()) || std::isinf(pos.z()) ) {
398 ATH_MSG_WARNING("NaN (Not A Number) or inf found in the event record vertex positions");
399
401 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
402 if (m_vtxNaNTest) {
403 filter_pass = false;
404 }
405 } // Done of checking for nans and infinities
406
407 // Check for too-far-displaced vertices
408 // Anything which propagates macroscopically should be set stable in evgen for G4 to handle
409 const double dist_trans2 = pos.x()*pos.x() + pos.y()*pos.y(); // in mm2
410 const double dist2 = dist_trans2 + pos.z()*pos.z(); // in mm2
411 const double dist_trans = std::sqrt(dist_trans2); // in mm
412 const double dist = std::sqrt(dist2); // in mm
413 if (dist2 > m_max_dist*m_max_dist) {
414 ATH_MSG_WARNING("Found vertex position displaced by more than " << m_max_dist << "mm: " << dist << "mm");
415 ++vtxDisplacedMoreThan_1m_CheckRateCnt;
416
417 if (m_vtxDisplacedTest) {
418 filter_pass = false;
419 }
420 }
421 if (dist_trans2 < m_min_dist_trans*m_min_dist_trans) {
422 ATH_MSG_WARNING("Found vertex position displaced by less than " << m_min_dist_trans
423 << "mm in transverse distance: " << dist_trans << "mm");
424
425#ifdef HEPMC3
426 for (const auto& part: vtx->particles_in()) {
427#else
428 for (auto part_it = vtx->particles_in_const_begin(); part_it != vtx->particles_in_const_end(); ++part_it) {
429 auto part = (*part_it);
430#endif
431 if (m_dumpEvent){
432 ATH_MSG_WARNING("Incoming particle : ");
433 HepMC::Print::line(msg( MSG::WARNING ).stream(), part);
434 }
435 }
436
437 if (m_vtxDisplacedTest) {
438 filter_pass = false;
439 }
440 }
441
442 if (dist_trans2 > m_max_dist_trans*m_max_dist_trans) {
443 ATH_MSG_WARNING("Found vertex position displaced by more than " << m_max_dist_trans << "mm in transverse distance: " << dist_trans << "mm");
444
445#ifdef HEPMC3
446 for (const auto& part: vtx->particles_in()) {
447#else
448 for (auto part_it = vtx->particles_in_const_begin(); part_it != vtx->particles_in_const_end(); ++part_it) {
449 auto part=(*part_it);
450#endif
451 if (m_dumpEvent){
452 ATH_MSG_WARNING("Outgoing particle : ");
453 HepMC::Print::line(msg( MSG::WARNING ).stream(),part);
454 }
455 ATH_MSG_WARNING("production vertex = " << part->production_vertex()->position().x() << ", " << part->production_vertex()->position().y() << ", " << part->production_vertex()->position().z());
456 ATH_MSG_WARNING("end vertex = " << part->end_vertex()->position().x() << ", " << part->end_vertex()->position().y() << ", " << part->end_vertex()->position().z());
457 if (m_dumpEvent) ATH_MSG_WARNING("parents info: ");
458 if (part->production_vertex()) {
459#ifdef HEPMC3
460 for(const auto& p_parents: part->production_vertex()->particles_in()) {
461#else
462 for(auto p_parents_it = part->production_vertex()->particles_in_const_begin(); p_parents_it != part->production_vertex()->particles_in_const_end(); ++p_parents_it) {
463 auto p_parents=(*p_parents_it);
464#endif
465 if (m_dumpEvent){
466 msg(MSG::WARNING) << "\t";
467 HepMC::Print::line( msg( MSG::WARNING ).stream() , p_parents );
468 }
469 }
470 } // Done with fancy print
471
472 if (part->status() == 1 || part->status() == 2){
473 vtxDisplacedstatuscode12CheckRateCnt += 1;
474 } else {
475 vtxDisplacedstatuscodenot12CheckRateCnt += 1;
476 }
477
478 if (m_doHist){
479 m_h_energy_dispVtxCheck->Fill(part->momentum().e()/Gaudi::Units::GeV);
480 if (part->momentum().e()/Gaudi::Units::GeV < 10.) {
481 m_h_energy_dispVtxCheck_lt10->Fill(part->momentum().e()/Gaudi::Units::GeV);
482 }
483 m_h_pdgid_dispVtxCheck->Fill(part->pdg_id());
484 m_h_status_dispVtxCheck->Fill(part->status());
485 m_h_px_dispVtxCheck->Fill(part->momentum().px()/Gaudi::Units::GeV);
486 m_h_py_dispVtxCheck->Fill(part->momentum().py()/Gaudi::Units::GeV);
487 m_h_pz_dispVtxCheck->Fill(part->momentum().pz()/Gaudi::Units::GeV);
488 m_h_vx_dispVtxCheck->Fill(part->end_vertex()->position().x());
489 m_h_vy_dispVtxCheck->Fill(part->end_vertex()->position().y());
490 m_h_vz_dispVtxCheck->Fill(part->end_vertex()->position().z());
491 m_h_vxprod_dispVtxCheck->Fill(part->production_vertex()->position().x());
492 m_h_vyprod_dispVtxCheck->Fill(part->production_vertex()->position().y());
493 m_h_vzprod_dispVtxCheck->Fill(part->production_vertex()->position().z());
494 double endvx = part->end_vertex()->position().x();
495 double endvy = part->end_vertex()->position().y();
496 double endvz = part->end_vertex()->position().z();
497 double prodvx = part->production_vertex()->position().x();
498 double prodvy = part->production_vertex()->position().y();
499 double prodvz = part->production_vertex()->position().z();
500 double enddis = std::sqrt(endvx*endvx + endvy*endvy + endvz*endvz);
501 double proddis = std::sqrt(prodvx*prodvx + prodvy*prodvy + prodvz*prodvz);
502 m_h_vtxend_dispVtxCheck->Fill(enddis);
503 m_h_vtxprod_dispVtxCheck->Fill(proddis);
504 } // End of the filling of histograms for bad vertices
505 } // End of a loop over theparents of the bad vertex
506 } // Found a bad vertex
507 } // Loop over all vertices
508 if (vtxDisplacedstatuscode12CheckRateCnt>0) ++m_vtxDisplacedstatuscode12CheckRate;
509 if (vtxDisplacedstatuscodenot12CheckRateCnt>0) ++m_vtxDisplacedstatuscodenot12CheckRate;
510 if (vtxDisplacedMoreThan_1m_CheckRateCnt>0) ++m_vtxDisplacedMoreThan_1m_CheckRate;
511
512 // Check particles
513 for (auto pitr: *evt) {
514
515 // Local loop variables to clean up the check code
516 const HepMC::FourVector pmom = pitr->momentum();
517 const int pstatus = pitr->status();
518 const int ppdgid = pitr->pdg_id();
519 // Check for NaNs and infs in momentum components
520 if ( std::isnan(pmom.px()) || std::isinf(pmom.px()) ||
521 std::isnan(pmom.py()) || std::isinf(pmom.py()) ||
522 std::isnan(pmom.pz()) || std::isinf(pmom.pz()) ||
523 std::isnan(pmom.e()) || std::isinf(pmom.e()) ) {
524 ATH_MSG_WARNING("NaN (Not A Number) or inf found in the event record momenta");
526
527 if (m_dumpEvent) HepMC::Print::line(std::cout,pitr);
528 if (m_momNaNTest) {
529 filter_pass = false;
530 }
531 } // End of check for NaNs and infinities
532
533 // Check for undecayed pi0s
534 if (MC::isStable(pstatus) || MC::isDecayed(pstatus)) {
535 if (ppdgid == 111 && !pitr->end_vertex() ) {
536 unDecPi0.push_back( pitr);
538 }
539 } // End of check for undecayed pi0s
540
541 //check stable particle lifetimes
542 if (MC::isStable(pstatus)) {
543 const HepPDT::ParticleData* pd = particleData(ppdgid);
544 if (pd != NULL) {
545 double plifetime = pd->lifetime()*1e+12; // why lifetime doesn't come in common units???
546 if (plifetime != 0 && plifetime < m_min_tau) { // particles with infinite lifetime get a 0 in the PDT
547 ATH_MSG_WARNING("Stable particle found with lifetime = " << plifetime << "~ns!!");
548 if (m_dumpEvent) HepMC::Print::line(std::cout,pitr);
549
551
552 if (m_lifeTimeTest) {
553 filter_pass = false;
554 }
555 } // Particle did not have infinite lifetime
556 } // The particle has a data table (so a lifetime)
557 else{
558 int susyPart = 0;
559 std::vector<int>::size_type count = 0;
560 while (susyPart==0 && (count < m_SusyPdgID_tab.size() )){
561 // no warning for SUSY particles from the list susyParticlePdgid.txt
562 if (m_SusyPdgID_tab[count] == std::abs(ppdgid)) {
563 susyPart=1;
564 }
565 count++;
566 } // Look through the SUSY table to see if this one should be counted
567 if (susyPart==0){
568 ATH_MSG_WARNING("Stable particle not found in PDT, no lifetime check done");
569 if (m_dumpEvent) HepMC::Print::line(std::cout,pitr);
570 } // It's a SUSY particle -- skip the lifetime check
571 } // The particle has no data table
572 } // Test if the particle is stable
573
574 //Check that stable particles are known by G4 or they are non-interacting
575 const MC::DecodedPID decodedPID(ppdgid);
576 const int first_dig = decodedPID(0);
577
578 if (MC::isStable(pstatus) && (!pitr->end_vertex()) && (MC::isSimInteracting(pitr)) && (!MC::isNucleus(ppdgid)) && (first_dig != 9) ) {
579
580 int known_byG4 = 0;
581 std::vector<int>::size_type count =0;
582
583 while (known_byG4==0 && count < m_G4pdgID_tab.size()){
584 if(ppdgid == m_G4pdgID_tab[count]) known_byG4=1;
585 count++;
586 }
587 if(known_byG4==0){
588 nonG4_energy += pmom.e();
589 ATH_MSG_WARNING("Interacting particle not known by Geant4 with ID " << ppdgid);
590 }
591 } // End of check that stable particles are known to G4 or are non-interacting
592
593 // Check for bad PDG IDs
594 if (!MC::isValid(ppdgid)){
595 ATH_MSG_DEBUG("Invalid PDG ID found: " << ppdgid);
596 if (m_unknownPDGIDTest && std::find(m_uknownPDGID_tab.begin(),m_uknownPDGID_tab.end(),ppdgid)==m_uknownPDGID_tab.end()){
597 ATH_MSG_WARNING("Invalid and unmasked PDG ID found: " << ppdgid);
598 filter_pass = false;
600 }
601 } // End of check for invalid PDG IDs
602
603 // Check for unstables with no end vertex,
604 if (!pitr->end_vertex() && MC::isDecayed(pstatus)) {
605 unstNoEnd.push_back(pitr);
607 } // End of check for unstable with no end vertex
608
609 // Sum final state mom/energy, and note negative energy / tachyonic particles
610 // std::cout << "status " << pstatus << " e " << pmom.e() << " pz " << pmom.pz()<< std::endl;
611 if ( MC::isStable(pstatus) && !pitr->end_vertex() ) {
612 totalPx += pmom.px();
613 totalPy += pmom.py();
614 totalPz += pmom.pz();
615 totalE += pmom.e();
616 if (pmom.e() < 0) {
617 negEnPart.push_back(pitr);
619 }
620 const double aener = std::abs(pmom.e());
621 if ( aener+m_accur_margin < std::abs(pmom.px()) || aener+m_accur_margin < std::abs(pmom.py()) || aener+m_accur_margin < std::abs(pmom.pz()) ) {
622 tachyons.push_back(pitr);
624 }
625 } // End of sums for momentum and energy conservation
626
627 // Decay checks (uses PdgToSearch attr value, for tau by default)
629 int tau_child = 0;
630 if (std::abs(ppdgid) == m_pdg && (MC::isStable(pstatus) || MC::isDecayed(pstatus))) {
631 ++m_TotalTaus;
632 auto vtx = pitr->end_vertex();
633 if (vtx) {
634 double p_energy = 0;
635#ifdef HEPMC3
636 for (auto desc: HepMC::descendant_particles(vtx)) {
637#else
638 for (auto desc_it = vtx->particles_begin(HepMC::descendants); desc_it != vtx->particles_end(HepMC::descendants); ++desc_it) {
639 auto desc=(*desc_it);
640#endif
641 if (std::abs(desc->pdg_id()) == m_pdg) tau_child = 1;
642 if ( MC::isStable(desc) ) p_energy += desc->momentum().e();
643 }
644 if (std::abs( p_energy - pmom.e()) > m_energy_diff && !tau_child) {
645 ATH_MSG_WARNING("Energy sum (decay products): "
646 << "Energy (original particle) > " << m_energy_diff << " MeV, "
647 << "Event #" << evt->event_number() << ", "
648 << "The original particle = " << pitr);
650 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
651 }
652 //most taus should not decay immediately
653 const HepMC::FourVector tau_decaypos = vtx->position();
654 const double tau_displacement = tau_decaypos.x()*tau_decaypos.x() + tau_decaypos.y()*tau_decaypos.y() + tau_decaypos.z()*tau_decaypos.z();
655 //tau_child != 1 exclude cases in which a tau is copied to another vertex or emits a photon
656 if ((tau_displacement < 1.e-6) && (tau_child!=1)) ++m_FastDecayedTau;
657 } else {
658 ATH_MSG_WARNING("UNDECAYED PARTICLE WITH PDG_ID = " << m_pdg);
660 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
661 }
662 } // End of checks for specific particle (tau by default)
663
664 // Check for undisplaced decay daughters from long-lived hadrons
665 if (pitr->end_vertex()) {
666 auto decayvtx = pitr->end_vertex();
667 const HepMC::FourVector decaypos = decayvtx->position();
668 const double displacement = decaypos.x()*decaypos.x() + decaypos.y()*decaypos.y() + decaypos.z()*decaypos.z();
669 if (displacement > 1e-6) {
670 for (auto ip: *decayvtx) {
671 const HepMC::FourVector pos2 = ip->production_vertex()->position();
672 const double displacement2 = pos2.x()*pos2.x() + pos2.y()*pos2.y() + pos2.z()*pos2.z();
673 if (displacement2 < 1e-6) {
674 ATH_MSG_WARNING("Decay child " << ip << " from " << pitr
675 << " has undisplaced vertex (" << ip->production_vertex()
676 << " @ " << displacement2 << "mm) "
677 << " but parent vertex is displaced (" << decayvtx
678 << " @ " << displacement << "mm)");
679 undisplaceds.push_back(std::move(ip));
681 } // Check for displacement below 1 um
682 } // Loop over all particles coming from the decay vertex
683 } // Displacement of greater than 1 um
684 } // End of check for undisplaced decay daughters from long-lived hadrons
685
686 // Check for photons with non-zero masses
688 if (MC::isPhoton(ppdgid) && MC::isStable(pstatus)) {
689 const double mass = pitr->generated_mass();
690 if (std::abs(mass) > 1.0) { // in MeV
691 ATH_MSG_WARNING("Photon with non-zero mass found! Mass: " << mass << " MeV" << pitr);
693 }
694 } // End check for photons with too-large a mass
695
696 } // End of loop over particles in the event
697
698 // Energy of interacting particles not known by Geant4
699 if(nonG4_energy > m_nonG4_energy_threshold) {
700 ATH_MSG_WARNING("The energy of interacting particles not known by Geant4 is = " << nonG4_energy << " MeV");
701 if (m_energyG4Test) {
702 filter_pass = false;
703 }
705 } // End of check for interacting particles not known by G4
706
707 // Energy balance
708 double lostE = std::abs(totalE - cmenergy);
709 if (lostE > m_energy_diff) {
710 ATH_MSG_WARNING("ENERGY BALANCE FAILED : E-difference = " << lostE << " MeV");
711
712 ATH_MSG_WARNING("balance " << totalPx << " " << totalPy << " " << totalPz << " " << totalE);
713
714 if (m_doHist){
715 m_h_energyImbalance->Fill(lostE/Gaudi::Units::GeV);
716 }
717 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
719 filter_pass = false;
720 }
722 } // End of energy balance check
723
724 // Momentum balance
725 if ( std::abs(totalPx) > m_energy_diff || std::abs(totalPy) > m_energy_diff || std::abs(totalPz) > m_energy_diff ) {
726 ATH_MSG_WARNING("MOMENTUM BALANCE FAILED : SumPx = " << totalPx << " SumPy = " << totalPy << " SumPz = " << totalPz << " MeV");
727 if (m_doHist){
728 m_h_momentumImbalance_px->Fill(std::abs(totalPx)/Gaudi::Units::GeV);
729 m_h_momentumImbalance_py->Fill(std::abs(totalPy)/Gaudi::Units::GeV);
730 m_h_momentumImbalance_pz->Fill(std::abs(totalPz)/Gaudi::Units::GeV);
731 }
732 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
733 if (m_momImbalanceTest) {
734 filter_pass = false;
735 }
737 } // End of momentum balance check
738
739 // Negative energy particles
740 if (!negEnPart.empty()) {
741 std::stringstream ss;
742 ss << "NEGATIVE ENERGY PARTICLES FOUND :";
743 for (const auto &b: negEnPart){
744 ss << " " << b;
745 }
746 ATH_MSG_WARNING(ss.str());
747 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
749 filter_pass = false;
750 }
752 } // End of negative energy particle chedk
753
754 // Tachyons
755 if (!tachyons.empty()) {
756 std::stringstream ss;
757 ss << "PARTICLES WITH |E| < |Pi| (i=x,y,z) FOUND :";
758 for (auto b: tachyons){
759 ss << " " << b;
760 }
761 ATH_MSG_WARNING(ss.str());
762 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
763 if (m_tachyonsTest) {
764 filter_pass = false;
765 }
767 } // End of tachyon check
768
769 // Unstable particles with no decay vertex
770 if (!unstNoEnd.empty()) {
771 std::stringstream ss;
772 ss << "Unstable particle with no decay vertex found: ";
773 for (auto b: unstNoEnd){
774 ss << " " << b;
775 }
776 ATH_MSG_WARNING(ss.str());
777 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
779 filter_pass = false;
780 }
782 } // End of unstable particle with no decay vertex check
783
784 // Undecayed pi0
785 if (!unDecPi0.empty()) {
786 std::stringstream ss;
787 ss << "pi0 with no decay vertex found:";
788 for (auto b: unDecPi0){
789 ss << " " << b;
790 }
791 ATH_MSG_WARNING(ss.str());
792 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
793 if (m_pi0NoVtxTest) {
794 filter_pass = false;
795 }
797 } // End of undecayed pi0 check
798
799 // Undisplaced decay daughters of displaced vertices
800 if (!undisplaceds.empty()) {
801 std::stringstream ss{"Undisplaced decay vertices from displaced particle: "};
802 for (HepMC::ConstGenParticlePtr b: undisplaceds){
803 // coverity[COPY_INSTEAD_OF_MOVE]
804 ss << " " << b;
805 }
806 ATH_MSG_WARNING(ss.str());
807 if (m_dumpEvent) HepMC::Print::content(std::cout,*evt);
809 filter_pass = false;
810 }
812 } // End of undisplaced decay daughter of displaced vertices check
813
814 } // End of loop over MCEventCollection
815
816 // End of execution for each event - update filter value
817 if (!filter_pass){
818 setFilterPassed(false);
819 ++m_nFail;
820 } else {
821 ++m_nPass;
822 }
823
824 // If the efficiency after 100 events is below 10%, there is an important bug going on:
825 // we fail the job immediately so it doesn't run for ever
826 const double tmp_efficiency = double(m_nPass) / double(m_nPass + m_nFail);
827 if ((m_nPass + m_nFail) > 100 && tmp_efficiency < 0.1) {
828 ATH_MSG_FATAL("The efficiency after " << m_nPass + m_nFail << " events is " << tmp_efficiency*100. << "% !!!");
829 return StatusCode::FAILURE;
830 }
831
832 return StatusCode::SUCCESS;
833}
834
835
837
838 ATH_MSG_INFO("Events passed = " << m_nPass << ", Events Failed = " << m_nFail);
839 // Keep a denominator for all the fractions, to ensure we don't get a bunch of nans.
840 // If nothing passed or failed, all the other counters should be zero; this is just avoiding FPEs etc.
841 double denom = m_nPass + m_nFail > 0. ? m_nPass + m_nFail : 1.;
842
843 ATH_MSG_INFO(" Event rate with invalid Beam Particles = " << m_invalidBeamParticlesCheckRate*100.0/denom << "% (not included in test efficiency)");
844 ATH_MSG_INFO(" Event rate with beam particles and status not equal to 4 = " << m_beamParticleswithStatusNotFourCheckRate*100.0/double(m_nPass + m_nFail) << "% (not included in test efficiency)");
845 ATH_MSG_INFO(" Event rate with incorrect beam particle energies = " << m_beamEnergyCheckRate*100.0/denom << "% (not included in test efficiency)");
846 ATH_MSG_INFO(" Configured minimum transverse vertex displacement = " << m_min_dist_trans << "~mm");
847 ATH_MSG_INFO(" Event rate with NaN (Not A Number) or inf found in the event record vertex positions = " << m_vtxNANandINFCheckRate*100.0/denom << "%");
848 if (!m_vtxNaNTest) ATH_MSG_INFO(" The check for NaN or inf in vtx. record is switched off, so is not included in the final TestHepMC efficiency ");
849 ATH_MSG_INFO(" Event rate with vertices displaced more than " << m_max_dist_trans << "~mm in transverse direction for particles with status code other than 1 and 2 = " << m_vtxDisplacedstatuscodenot12CheckRate*100.0/denom << "% (not included in test efficiency)");
850 ATH_MSG_INFO(" Event rate with vertices displaced more than " << m_max_dist << "~mm = " << m_vtxDisplacedMoreThan_1m_CheckRate*100.0/denom << "%");
851 if (!m_vtxDisplacedTest) ATH_MSG_INFO(" The check for displaced vertices is switched off, so is not included in the final TestHepMC efficiency ");
852 ATH_MSG_INFO(" Event rate with NAN (Not A Number) or inf found in particle momentum values = " << m_partMomentumNANandINFCheckRate*100.0/denom << "%");
853 if (!m_momNaNTest) ATH_MSG_INFO(" The check for NaN/inf in momentum record is switched off, so is not included in the final TestHepMC efficiency ");
854 ATH_MSG_INFO(" Event rate with undecayed pi0's with status 1 or 2 = " << m_undecayedPi0statuscode12CheckRate*100.0/denom << "% (not included in test efficiency)");
855 ATH_MSG_INFO(" Event rate with unstable particles with no end vertex = " << m_unstableNoEndVtxCheckRate*100.0/denom << "% (not included in test efficiency)");
856 ATH_MSG_INFO(" Event rate with negative total energy like for tachyonic particles = " << m_negativeEnergyTachyonicCheckRate*100.0/denom << "% (not included in test efficiency)");
857 ATH_MSG_INFO(" Event rate with particles with improper decay properties = " << m_decayCheckRate*100.0/denom << "% (not included in test efficiency)");
858 ATH_MSG_INFO(" Event rate with undisplaced daughters of long lived hadrons = " << m_undisplacedLLHdaughtersCheckRate*100.0/denom << "% (not included in test efficiency)");
859 ATH_MSG_INFO(" Event rate with non zero photon mass = " << m_nonZeroPhotonMassCheckRate*100.0/denom << "% (not included in test efficiency)");
860 ATH_MSG_INFO(" Event rate with no energy balance = " << m_energyBalanceCheckRate*100.0/denom << "%");
861 if (!m_energyImbalanceTest) ATH_MSG_INFO(" The check for energy imbalance is switched off, so is not included in the final TestHepMC efficiency ");
862 ATH_MSG_INFO(" Event rate with no momentum balance = " << m_momentumBalanceCheckRate*100.0/denom << "%");
863 if (!m_momImbalanceTest) ATH_MSG_INFO(" The check for momentum imbalance is switched off, so is not included in the final TestHepMC efficiency ");
864 ATH_MSG_INFO(" Event rate with negative energy particles = " << m_negativeEnergyCheckRate*100.0/denom << "%");
865 if (!m_negativeEnergyTest) ATH_MSG_INFO(" The check for particles with negative energy is switched off, so is not included in the final TestHepMC efficiency ");
866 ATH_MSG_INFO(" Event rate with tachyons = " << m_tachyonCheckRate*100.0/denom << "%");
867 if (!m_tachyonsTest) ATH_MSG_INFO(" The check for tachyons is switched off, so is not included in the final TestHepMC efficiency ");
868 ATH_MSG_INFO(" Event rate with stable or unstable particles with no parents = " << m_stableUnstableNoParentCheckRate*100.0/denom << "%");
869 ATH_MSG_INFO(" Event rate with unstable particle with no decay vertex = " << m_unstablePartNoDecayVtxCheckRate*100.0/denom << "%");
870 if (!m_unstableNoVtxTest) ATH_MSG_INFO(" The check for unstable part. without end vertex is switched off, so is not included in the final TestHepMC efficiency ");
871 ATH_MSG_INFO(" Event rate with undecayed Pi0's = " << m_undecayedPi0CheckRate*100.0/denom << "%");
872 if (!m_pi0NoVtxTest) ATH_MSG_INFO(" The check for undecayed pi0's is switched off, so is not included in the final TestHepMC efficiency ");
873 ATH_MSG_INFO(" Event rate with undisplaced decay daughters of displaced vertices = " << m_undisplacedDecayDaughtersOfDisplacedVtxCheckRate*100.0/denom << "%");
874 if (!m_undisplacedDaughtersTest) ATH_MSG_INFO(" The check for undisplaced daughters is switched off, so is not included in the final TestHepMC efficiency ");
875 ATH_MSG_INFO(" Event rate with particles with status 1 but lifetime < " << m_min_tau << "~ns = " << m_Status1ShortLifetime*100.0/denom << "%");
876 if (!m_lifeTimeTest) ATH_MSG_INFO(" The check for status 1 particles with too short lifetime is switched off, so is not included in the final TestHepMC efficiency ");
877 ATH_MSG_INFO(" Event rate with energy sum of interacting particles non known by Geant4 above " << m_nonG4_energy_threshold << " MeV = " << m_nonG4_energyCheckRate*100.0/denom << "%");
878 if (!m_energyG4Test) ATH_MSG_INFO(" The check for energy not known by G4 is switched off, so is not included in the final TestHepMC efficiency ");
879 ATH_MSG_INFO(" Event rate with unknown PDG IDs = " << m_unknownPDGIDCheckRate*100.0/denom << "%");
880 if (!m_unknownPDGIDTest) ATH_MSG_INFO(" The check for unknown PDG IDs is sitched off, so it is not included in the final TestHepMC efficiency ");
881
882 const double tau_fastDrate = double(m_FastDecayedTau) / double(m_TotalTaus);
883 if(tau_fastDrate > m_tau_eff_threshold){
884 ATH_MSG_FATAL("MORE THAN " << 100.*m_tau_eff_threshold << "% OF TAUS DECAYING IMMEDIATELY! " << m_FastDecayedTau << " found, out of: " << m_TotalTaus);
885 return StatusCode::FAILURE;
886 }
887
888 if (m_noXSECset) {
889 if (m_allowMissingXSec) {
890 ATH_MSG_WARNING(m_noXSECset << " EVENTS WITHOUT CROSS-SECTION!!! Added dummy cross-section instead.");
891 }
892 else {
893 ATH_MSG_FATAL(m_noXSECset << " EVENTS WITHOUT CROSS-SECTION!! Check the setup before production!");
894 return StatusCode::FAILURE;
895 }
896 }
897
898 const double efficiency = double(m_nPass) / double(m_nPass + m_nFail);
899 ATH_MSG_INFO("Efficiency = " << efficiency * 100 << "%");
900
901 // Check efficiency, and fail (to kill production jobs) if the pass rate is too low
903 ATH_MSG_FATAL("EFFICIENCY ABOVE ERROR THRESHOLD! " << 100*efficiency << "% found, but at least: " << 100*m_eff_fail_threshold << "% required");
904 return StatusCode::FAILURE;
905 } else if (efficiency <= m_eff_warn_threshold) {
906 ATH_MSG_WARNING("EFFICIENCY ABOVE WARNING THRESHOLD! " << 100*efficiency << "% found, but at least: " << 100*m_eff_warn_threshold << "% expected");
907 }
908
909 return StatusCode::SUCCESS;
910}
911
912
913#endif
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
ATLAS-specific HepMC functions.
static Double_t ss
std::string PathResolverFindDataFile(const std::string &logical_file_name)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const HepPDT::ParticleData * particleData(int pid) const
Access an element in the particle data table.
Definition GenBase.h:126
virtual StatusCode initialize() override
Definition GenBase.cxx:17
GenBase(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Definition GenBase.cxx:11
const McEventCollection * events_const() const
Access the current event's McEventCollection (const)
Definition GenBase.h:96
Implementation of classification functions according to PDG2022.
int m_momentumBalanceCheckRate
Definition TestHepMC.h:80
int m_tachyonCheckRate
Definition TestHepMC.h:82
bool m_energyImbalanceTest
Definition TestHepMC.h:53
double m_cm_energy
Definition TestHepMC.h:45
TH1F * m_h_py_dispVtxCheck
Definition TestHepMC.h:106
int m_nFail
Definition TestHepMC.h:59
int m_stableUnstableNoParentCheckRate
Definition TestHepMC.h:83
int m_nonZeroPhotonMassCheckRate
Definition TestHepMC.h:78
TH1F * m_h_vyprod_dispVtxCheck
Definition TestHepMC.h:112
TH1F * m_h_energyImbalance
Definition TestHepMC.h:121
int m_vtxDisplacedMoreThan_1m_CheckRate
Definition TestHepMC.h:71
ServiceHandle< ITHistSvc > m_thistSvc
Definition TestHepMC.h:99
TH1F * m_h_vz_dispVtxCheck
Definition TestHepMC.h:110
int m_unknownPDGIDCheckRate
Definition TestHepMC.h:89
double m_nonG4_energy_threshold
Definition TestHepMC.h:48
int m_vtxDisplacedstatuscodenot12CheckRate
Definition TestHepMC.h:70
int m_beamParticleswithStatusNotFourCheckRate
Definition TestHepMC.h:66
bool m_dumpEvent
Definition TestHepMC.h:47
TH1F * m_h_beamparticle1_Energy
Definition TestHepMC.h:126
int m_nPass
Definition TestHepMC.h:58
double m_eff_fail_threshold
Definition TestHepMC.h:49
TH1F * m_h_momentumImbalance_py
Definition TestHepMC.h:123
TH1F * m_h_vxprod_dispVtxCheck
Definition TestHepMC.h:111
int m_unstablePartNoDecayVtxCheckRate
Definition TestHepMC.h:84
std::string m_unknownPDGIDFile
Definition TestHepMC.h:92
double m_min_dist_trans
Definition TestHepMC.h:48
int m_vtxDisplacedstatuscode12CheckRate
Definition TestHepMC.h:69
TH1F * m_h_vx_dispVtxCheck
Definition TestHepMC.h:108
TH1F * m_h_pz_dispVtxCheck
Definition TestHepMC.h:107
double m_max_dist_trans
Definition TestHepMC.h:48
TH1F * m_h_pdgid_dispVtxCheck
Definition TestHepMC.h:103
bool m_doHist
Definition TestHepMC.h:51
int m_maxloops
Definition TestHepMC.h:43
int m_undisplacedLLHdaughtersCheckRate
Definition TestHepMC.h:77
bool m_tachyonsTest
Definition TestHepMC.h:53
std::vector< int > m_vertexStatuses
Definition TestHepMC.h:56
TH1F * m_h_vy_dispVtxCheck
Definition TestHepMC.h:109
StatusCode finalize()
bool m_momImbalanceTest
Definition TestHepMC.h:53
int m_beamEnergyCheckRate
Definition TestHepMC.h:67
TH1F * m_h_photon_mass
Definition TestHepMC.h:117
int m_Status1ShortLifetime
Definition TestHepMC.h:86
double m_eff_warn_threshold
Definition TestHepMC.h:49
int m_noXSECset
Definition TestHepMC.h:60
std::vector< int > m_uknownPDGID_tab
Definition TestHepMC.h:96
bool m_allowMissingXSec
Definition TestHepMC.h:47
double m_tau_eff_threshold
Definition TestHepMC.h:49
int m_undecayedPi0statuscode12CheckRate
Definition TestHepMC.h:73
bool m_undisplacedDaughtersTest
Definition TestHepMC.h:54
bool m_vtxNaNTest
Definition TestHepMC.h:52
int m_unstableNoEndVtxCheckRate
Definition TestHepMC.h:74
double m_energy_diff
Definition TestHepMC.h:46
StatusCode execute()
MC::Loops< HepMC::GenEvent, HepMC::ConstGenParticlePtr, HepMC::ConstGenVertexPtr > m_looper
member to detect loops
Definition TestHepMC.h:130
double m_accur_margin
Definition TestHepMC.h:50
bool m_lifeTimeTest
Definition TestHepMC.h:52
TH1F * m_h_energy_dispVtxCheck_lt10
Definition TestHepMC.h:102
TH1F * m_h_momentumImbalance_pz
Definition TestHepMC.h:124
bool m_negativeEnergyTest
Definition TestHepMC.h:53
TH1F * m_h_vtxprod_dispVtxCheck
Definition TestHepMC.h:115
std::vector< int > m_G4pdgID_tab
Definition TestHepMC.h:94
int m_pdg
Definition TestHepMC.h:44
TH1F * m_h_vzprod_dispVtxCheck
Definition TestHepMC.h:113
int m_partMomentumNANandINFCheckRate
Definition TestHepMC.h:72
bool m_momNaNTest
Definition TestHepMC.h:52
int m_negativeEnergyCheckRate
Definition TestHepMC.h:81
TH1F * m_h_photon_energy
Definition TestHepMC.h:118
int m_undecayedPi0CheckRate
Definition TestHepMC.h:85
TH1F * m_h_energy_dispVtxCheck
Definition TestHepMC.h:101
TH1F * m_h_momentumImbalance_px
Definition TestHepMC.h:122
int m_energyBalanceCheckRate
Definition TestHepMC.h:79
bool m_unknownPDGIDTest
Definition TestHepMC.h:54
int m_TotalTaus
Definition TestHepMC.h:62
bool m_energyG4Test
Definition TestHepMC.h:52
TH1F * m_h_vtxend_dispVtxCheck
Definition TestHepMC.h:114
int m_FastDecayedTau
Definition TestHepMC.h:63
TestHepMC(const std::string &name, ISvcLocator *pSvcLocator)
Definition TestHepMC.cxx:17
TH1F * m_h_beamparticle2_Energy
Definition TestHepMC.h:127
int m_decayCheckRate
Definition TestHepMC.h:76
double m_max_dist
Definition TestHepMC.h:48
double m_min_tau
Definition TestHepMC.h:48
int m_vtxNANandINFCheckRate
Definition TestHepMC.h:68
bool m_vtxDisplacedTest
Definition TestHepMC.h:52
std::vector< int > m_SusyPdgID_tab
Definition TestHepMC.h:95
int m_invalidBeamParticlesCheckRate
Definition TestHepMC.h:65
TH1F * m_h_status_dispVtxCheck
Definition TestHepMC.h:104
bool m_pi0NoVtxTest
Definition TestHepMC.h:54
double m_cme_diff
Definition TestHepMC.h:45
TH1F * m_h_px_dispVtxCheck
Definition TestHepMC.h:105
TH1F * m_h_cmEnergyDiff
Definition TestHepMC.h:128
TH1F * m_h_photon_e2_p2_e2
Definition TestHepMC.h:119
double m_max_energy_diff
Definition TestHepMC.h:46
int m_undisplacedDecayDaughtersOfDisplacedVtxCheckRate
Definition TestHepMC.h:87
bool m_unstableNoVtxTest
Definition TestHepMC.h:53
int m_negativeEnergyTachyonicCheckRate
Definition TestHepMC.h:75
int m_nonG4_energyCheckRate
Definition TestHepMC.h:88
StatusCode initialize()
std::string m_paramFile
Definition TestHepMC.h:91
bool m_beamEnergyTest
Definition TestHepMC.h:52
void efficiency(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
void line(std::ostream &os, const GenEvent &e)
Definition GenEvent.h:676
void content(std::ostream &os, const GenEvent &e)
Definition GenEvent.h:678
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
bool valid_beam_particles(const GenEvent *e)
Definition GenEvent.h:681
int numberOfProtons(const T &p)
static const int HELIUM
static const int OXYGEN
bool isPhoton(const T &p)
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
bool isSimInteracting(const T &p)
Identify if the particle could interact with the detector during the simulation, e....
static const int LEAD
bool isDecayed(const T &p)
Identify if the particle decayed.
bool isBeam(const T &p)
Identify if the particle is beam particle.
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
bool isNucleus(const T &p)
PDG rule 16 Nuclear codes are given as 10-digit numbers ±10LZZZAAAI.
double baryonNumber(const T &p)
static const int PROTON
MsgStream & msg
Definition testRead.cxx:32