273 bool filter_pass =
true;
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;
289 if (!
m_looper.loop_particles().empty() || !
m_looper.loop_vertices().empty()) {
292 ATH_MSG_DEBUG(
"Please use MC::Loops::findLoops for this event to obtain all particles and vertices in the loops");
297 const auto xsec = evt->cross_section();
299 ATH_MSG_WARNING(
"WATCH OUT: event is missing the generator cross-section!");
302 ATH_MSG_WARNING(
"-> Adding a dummy cross-section for debugging purposes.");
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));
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);
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);
327 auto beams = evt->beam_particles();
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");
336 ATH_MSG_WARNING(
"Beam particles have incorrectly set status -- this generator interface should be fixed");
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);
346 if(beams.first->pdg_id() ==
MC::LEAD && beams.second->pdg_id() ==
MC::LEAD){
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);
378 return StatusCode::FAILURE;
383 int vtxDisplacedstatuscode12CheckRateCnt=0;
384 int vtxDisplacedstatuscodenot12CheckRateCnt=0;
385 int vtxDisplacedMoreThan_1m_CheckRateCnt=0;
387 for (
const auto& vtx: evt->vertices()) {
389 for (
auto vitr = evt->vertices_begin(); vitr != evt->vertices_end(); ++vitr ) {
390 const HepMC::GenVertex* vtx = *vitr;
392 const HepMC::FourVector pos = vtx->position();
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");
409 const double dist_trans2 = pos.x()*pos.x() + pos.y()*pos.y();
410 const double dist2 = dist_trans2 + pos.z()*pos.z();
411 const double dist_trans = std::sqrt(dist_trans2);
412 const double dist = std::sqrt(dist2);
415 ++vtxDisplacedMoreThan_1m_CheckRateCnt;
423 <<
"mm in transverse distance: " << dist_trans <<
"mm");
426 for (
const auto& part: vtx->particles_in()) {
428 for (
auto part_it = vtx->particles_in_const_begin(); part_it != vtx->particles_in_const_end(); ++part_it) {
429 auto part = (*part_it);
446 for (
const auto& part: vtx->particles_in()) {
448 for (
auto part_it = vtx->particles_in_const_begin(); part_it != vtx->particles_in_const_end(); ++part_it) {
449 auto part=(*part_it);
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());
458 if (part->production_vertex()) {
460 for(
const auto& p_parents: part->production_vertex()->particles_in()) {
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);
466 msg(MSG::WARNING) <<
"\t";
472 if (part->status() == 1 || part->status() == 2){
473 vtxDisplacedstatuscode12CheckRateCnt += 1;
475 vtxDisplacedstatuscodenot12CheckRateCnt += 1;
480 if (part->momentum().e()/Gaudi::Units::GeV < 10.) {
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);
513 for (
auto pitr: *evt) {
516 const HepMC::FourVector pmom = pitr->momentum();
517 const int pstatus = pitr->status();
518 const int ppdgid = pitr->pdg_id();
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");
535 if (ppdgid == 111 && !pitr->end_vertex() ) {
536 unDecPi0.push_back( pitr);
545 double plifetime = pd->lifetime()*1e+12;
546 if (plifetime != 0 && plifetime <
m_min_tau) {
547 ATH_MSG_WARNING(
"Stable particle found with lifetime = " << plifetime <<
"~ns!!");
559 std::vector<int>::size_type
count = 0;
568 ATH_MSG_WARNING(
"Stable particle not found in PDT, no lifetime check done");
576 const int first_dig = decodedPID(0);
581 std::vector<int>::size_type
count =0;
588 nonG4_energy += pmom.e();
589 ATH_MSG_WARNING(
"Interacting particle not known by Geant4 with ID " << ppdgid);
605 unstNoEnd.push_back(pitr);
612 totalPx += pmom.px();
613 totalPy += pmom.py();
614 totalPz += pmom.pz();
617 negEnPart.push_back(pitr);
620 const double aener = std::abs(pmom.e());
622 tachyons.push_back(pitr);
632 auto vtx = pitr->end_vertex();
636 for (
auto desc: HepMC::descendant_particles(vtx)) {
638 for (
auto desc_it = vtx->particles_begin(HepMC::descendants); desc_it != vtx->particles_end(HepMC::descendants); ++desc_it) {
639 auto desc=(*desc_it);
641 if (std::abs(desc->pdg_id()) ==
m_pdg) tau_child = 1;
642 if (
MC::isStable(desc) ) p_energy += desc->momentum().e();
644 if (std::abs( p_energy - pmom.e()) >
m_energy_diff && !tau_child) {
646 <<
"Energy (original particle) > " <<
m_energy_diff <<
" MeV, "
647 <<
"Event #" << evt->event_number() <<
", "
648 <<
"The original particle = " << pitr);
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();
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) {
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));
689 const double mass = pitr->generated_mass();
690 if (std::abs(mass) > 1.0) {
691 ATH_MSG_WARNING(
"Photon with non-zero mass found! Mass: " << mass <<
" MeV" << pitr);
700 ATH_MSG_WARNING(
"The energy of interacting particles not known by Geant4 is = " << nonG4_energy <<
" MeV");
708 double lostE = std::abs(totalE - cmenergy);
710 ATH_MSG_WARNING(
"ENERGY BALANCE FAILED : E-difference = " << lostE <<
" MeV");
712 ATH_MSG_WARNING(
"balance " << totalPx <<
" " << totalPy <<
" " << totalPz <<
" " << totalE);
726 ATH_MSG_WARNING(
"MOMENTUM BALANCE FAILED : SumPx = " << totalPx <<
" SumPy = " << totalPy <<
" SumPz = " << totalPz <<
" MeV");
740 if (!negEnPart.empty()) {
741 std::stringstream
ss;
742 ss <<
"NEGATIVE ENERGY PARTICLES FOUND :";
743 for (
const auto &b: negEnPart){
755 if (!tachyons.empty()) {
756 std::stringstream
ss;
757 ss <<
"PARTICLES WITH |E| < |Pi| (i=x,y,z) FOUND :";
758 for (
auto b: tachyons){
770 if (!unstNoEnd.empty()) {
771 std::stringstream
ss;
772 ss <<
"Unstable particle with no decay vertex found: ";
773 for (
auto b: unstNoEnd){
785 if (!unDecPi0.empty()) {
786 std::stringstream
ss;
787 ss <<
"pi0 with no decay vertex found:";
788 for (
auto b: unDecPi0){
800 if (!undisplaceds.empty()) {
801 std::stringstream
ss{
"Undisplaced decay vertices from displaced particle: "};
818 setFilterPassed(
false);
829 return StatusCode::FAILURE;
832 return StatusCode::SUCCESS;