101 HepMC::GenEvent* evt =
const_cast<HepMC::GenEvent*
>(*ievt);
104 if (!
m_looper.loop_particles().empty() || !
m_looper.loop_vertices().empty()) {
107 ATH_MSG_DEBUG(
"Please use MC::Loops::findLoops for this event to obtain all particles and vertices in the loops");
110 auto old_momentum = evt->momentum_unit();
111 auto old_length = evt->length_unit();
118 std::string old_momentum = (evt->momentum_unit() == HepMC::Units::MomentumUnit::MEV ?
"MEV" :
"GEV" );
119 std::string old_length = (evt->length_unit() == HepMC::Units::LengthUnit::MM ?
"MM" :
"CM" );
128 for (
auto ip: *evt) {
131 auto newpid =
m_pidmap.find(ip->pdg_id());
132 if (newpid ==
m_pidmap.end())
continue;
133 ip->set_pdg_id(newpid->second);
143 auto cycles = std::make_shared<HepMC3::IntAttribute>(1);
144 evt->add_attribute(
"cycles",cycles);
150 if (evt->weights().empty()) {
151 ATH_MSG_DEBUG(
"Adding a unit weight to empty event weight vector");
152 evt->weights().push_back(1);
156 const HepMC::FourVector nullpos;
157 for (
auto iv: evt->vertices()) {
158 if (iv->position() == nullpos) {
159 ATH_MSG_DEBUG(
"Setting representative event position vertex");
167 std::vector<HepMC::GenParticlePtr> beams_t;
169 if (p->status() == 4) beams_t.push_back(p);
171 if (beams_t.size() > 2) {
172 ATH_MSG_INFO(
"Invalid number of beam particles " << beams_t.size() <<
". Will try to fix.");
173 std::vector<HepMC::GenParticlePtr> bparttoremove;
174 for (
const auto& bpart : beams_t) {
175 if (bpart->id() == 0 && bpart->production_vertex()) bparttoremove.push_back(bpart);
177 for (
auto bpart: bparttoremove) {
178 bpart->production_vertex()->remove_particle_out(bpart);
186 double units_problem = -1.;
188 if (beams_t.size() > 0 ){
190 if (p->momentum().pz() > 1e9) units_problem = p->momentum().pz();
195 if (p && p->momentum().pz() > 1e9) units_problem = p->momentum().pz();
198 if (units_problem>0){
199 ATH_MSG_INFO(
"Apparent units problem; beam particles have z-momentum " << units_problem <<
" in MeV. Will divide by 1000.");
205 std::vector<HepMC::GenParticlePtr> semi_disconnected, decay_loop_particles;
206 for (
auto ip : evt->particles()) {
209 bool particle_to_fix =
false;
210 int abspid = std::abs(ip->pdg_id());
211 auto vProd = ip->production_vertex();
212 auto vEnd = ip->end_vertex();
214 if ( (!vProd || vProd->id() == 0) && vEnd && ip->status() != 4) {
215 particle_to_fix =
true;
216 ATH_MSG_DEBUG(
"Found particle " << ip->pdg_id() <<
" without production vertex! HepMC status = " << ip->status());
219 if (vProd && !vEnd && ip->status() != 1) {
220 particle_to_fix =
true;
221 ATH_MSG_DEBUG(
"Found particle " << ip->pdg_id() <<
" without decay vertex! HepMC status = " << ip->status());
223 if (particle_to_fix) semi_disconnected.push_back(ip);
225 if (abspid == 43 || abspid == 44 || abspid == 30353 || abspid == 30343) {
226 decay_loop_particles.push_back(std::move(ip));
238 if ( !
m_ignoreSemiDisconnected && (semi_disconnected.size() == 4 || semi_disconnected.size() == 3 || semi_disconnected.size() == 2)) {
241 HepMC::FourVector sum(0,0,0,0);
242 std::set<HepMC::GenVertexPtr> standalone;
243 for (
const auto& part : semi_disconnected) {
244 if (!part->production_vertex() || !part->production_vertex()->id()) {
245 no_prov++; sum += part->momentum();
247 if (!part->end_vertex()) {
248 no_endv++; sum -= part->momentum();
250 if (part->production_vertex()) standalone.insert(part->production_vertex());
251 if (part->end_vertex()) standalone.insert(part->end_vertex());
253 ATH_MSG_INFO(
"Heuristics: found " << semi_disconnected.size() <<
" semi-disconnected particles. Momentum sum is " << sum <<
" Standalone vertices " << standalone.size());
254 bool standalonevertex = (standalone.size() == 1 && (*standalone.begin())->particles_in().size() + (*standalone.begin())->particles_out().size() == semi_disconnected.size());
256 if (! standalonevertex && no_endv && no_prov && ( no_endv + no_prov == semi_disconnected.size() )) {
257 if (std::abs(sum.px()) < 1e-2 && std::abs(sum.py()) < 1e-2 && std::abs(sum.pz()) < 1e-2 ) {
258 ATH_MSG_INFO(
"Try " << no_endv <<
"->" << no_prov <<
" splitting/merging.");
260 for (
auto part : semi_disconnected) {
261 if (!part->production_vertex() || part->production_vertex()->id() == 0) v->add_particle_out(std::move(part));
263 for (
auto part : semi_disconnected) {
264 if (!part->end_vertex()) v->add_particle_in(std::move(part));
266 evt->add_vertex(std::move(v));
275 for (
auto part: decay_loop_particles) {
277 auto vend = part->end_vertex();
278 auto vprod = part->production_vertex();
279 if (!vprod || !vend)
continue;
280 bool loop_in_decay =
true;
283 auto sisters = vend->particles_in();
284 for (
auto sister: sisters) {
285 if (vprod != sister->production_vertex()) loop_in_decay =
false;
287 if (!loop_in_decay)
continue;
290 auto daughters = vend->particles_out();
291 for (
auto p : daughters) vprod->add_particle_out(std::move(p));
292 for (
auto sister : sisters) {
293 vprod->remove_particle_out(sister);
294 vend->remove_particle_in(sister);
295 evt->remove_particle(std::move(sister));
297 evt->remove_vertex(std::move(vend));
302 std::vector<HepMC::GenParticlePtr> toremove;
303 for (
auto ip: evt->particles()) {
308 bool bad_particle =
false;
324 int abs_pdg_id = std::abs(ip->pdg_id());
325 bool is_decayed_weak_boson = ( abs_pdg_id == 23 || abs_pdg_id == 24 || abs_pdg_id == 25 ) && ip->end_vertex();
333 if (bad_particle) toremove.push_back(std::move(ip));
337 const int num_particles_orig = evt->particles().size();
340 if (!toremove.empty()) {
341 ATH_MSG_DEBUG(
"Cleaning event record of " << toremove.size() <<
" bad particles");
342 for (
auto part: toremove) evt->remove_particle(std::move(part));
349 const std::vector <HepMC::GenParticlePtr> allParticles=evt->particles();
350 for(
auto p : allParticles) {
352 if(p->status() == 2 && !end_v) {
353 evt->remove_particle(std::move(p));
362 const int num_particles_filt = evt->particles().size();
364 if(num_particles_orig!=num_particles_filt) {
366 ATH_MSG_INFO(
"Particles filtered: " << num_particles_orig <<
" -> " << num_particles_filt);
371 if (evt->weights().empty()) {
372 ATH_MSG_DEBUG(
"Adding a unit weight to empty event weight vector");
373 evt->weights().push_back(1);
377 if (evt->signal_process_vertex() == NULL) {
378 const HepMC::FourVector nullpos;
379 for (HepMC::GenEvent::vertex_const_iterator iv = evt->vertices_begin(); iv != evt->vertices_end(); ++iv) {
380 if ((*iv)->position() == nullpos) {
381 ATH_MSG_DEBUG(
"Setting representative event position vertex");
382 evt->set_signal_process_vertex(
const_cast<HepMC::GenVertex*
>(*iv));
390 std::vector<HepMC::GenParticlePtr> semi_disconnected, decay_loop_particles;
391 for (
auto ip : *evt) {
394 bool particle_to_fix =
false;
395 int abspid = std::abs(ip->pdg_id());
396 auto vProd = ip->production_vertex();
397 auto vEnd = ip->end_vertex();
399 if ( (!vProd || vProd->id() == 0) && vEnd && ip->status() != 4) {
400 particle_to_fix =
true;
401 ATH_MSG_DEBUG(
"Found particle " << ip->pdg_id() <<
" without production vertex! HepMC status = " << ip->status());
404 if (vProd && !vEnd && ip->status() != 1) {
405 particle_to_fix =
true;
406 ATH_MSG_DEBUG(
"Found particle " << ip->pdg_id() <<
" without decay vertex! HepMC status = " << ip->status());
408 if (particle_to_fix) semi_disconnected.push_back(ip);
410 if (abspid == 43 || abspid == 44 || abspid == 30353 || abspid == 30343) {
411 decay_loop_particles.push_back(ip);
417 if (semi_disconnected.size() == 4 ||semi_disconnected.size() == 3 || semi_disconnected.size() == 2) {
420 double vsum[4] = {0,0,0,0};
421 for (
auto part : semi_disconnected) {
422 if (!part->production_vertex() ) {
424 vsum[0] += part->momentum().px();
425 vsum[1] += part->momentum().py();
426 vsum[2] += part->momentum().pz();
427 vsum[3] += part->momentum().e();
429 if (!part->end_vertex()) {
431 vsum[0] -= part->momentum().px();
432 vsum[1] -= part->momentum().py();
433 vsum[2] -= part->momentum().pz();
434 vsum[3] -= part->momentum().e();
437 HepMC::FourVector sum(vsum[0],vsum[1],vsum[2],vsum[3]);
438 ATH_MSG_INFO(
"Heuristics: found " << semi_disconnected.size() <<
" semi-disconnected particles. Momentum sum is " << vsum[0] <<
" " << vsum[1] <<
" " << vsum[2] <<
" " << vsum[3]);
440 if (no_endv && no_prov && ( no_endv + no_prov == semi_disconnected.size() )) {
441 if (std::abs(sum.px()) < 1e-2 && std::abs(sum.py()) < 1e-2 && std::abs(sum.pz()) < 1e-2 ) {
442 ATH_MSG_INFO(
"Try " << no_endv <<
"->" << no_prov <<
" splitting/merging.");
444 for (
auto part : semi_disconnected) {
445 if (!part->production_vertex()) v->add_particle_out(part);
447 for (
auto part : semi_disconnected) {
448 if (!part->end_vertex()) v->add_particle_in(part);
459 for (
auto part: decay_loop_particles) {
461 auto vend = part->end_vertex();
462 auto vprod = part->production_vertex();
463 if (!vend || !vprod)
continue;
464 bool loop_in_decay =
true;
466 std::vector<HepMC::GenParticlePtr> sisters;
467 for (
auto p = vend->particles_begin(HepMC::parents); p!= vend->particles_end(HepMC::parents); ++p) sisters.push_back(*p);
468 for (
auto sister : sisters) {
469 if (vprod != sister->production_vertex()) loop_in_decay =
false;
471 if (!loop_in_decay)
continue;
473 std::vector<HepMC::GenParticlePtr> daughters;
474 for (
auto p = vend->particles_begin(HepMC::children); p!= vend->particles_end(HepMC::children); ++p) daughters.push_back(*p);
475 for (
auto p : daughters) vprod->add_particle_out(p);
476 for (
auto sister : sisters) {
477 vprod->remove_particle(sister);
478 vend->remove_particle(sister);
480 evt->remove_vertex(vend);
486 std::vector<HepMC::GenParticlePtr> toremove; toremove.reserve(10);
487 for (HepMC::GenEvent::particle_const_iterator ip = evt->particles_begin(); ip != evt->particles_end(); ++ip) {
489 if (*ip == NULL)
continue;
493 bool bad_particle =
false;
500 if (
msgLvl( MSG::DEBUG ) ) (*ip)->print();
508 if (
msgLvl( MSG::DEBUG ) ) (*ip)->print();
512 int abs_pdg_id = std::abs((*ip)->pdg_id());
513 bool is_decayed_weak_boson = ( abs_pdg_id == 23 || abs_pdg_id == 24 || abs_pdg_id == 25 ) && (*ip)->end_vertex();
518 if (
msgLvl( MSG::DEBUG ) ) (*ip)->print();
522 if (bad_particle) toremove.push_back(*ip);
526 const int num_particles_orig = evt->particles_size();
527 int num_orphan_vtxs_orig = 0;
528 int num_noparent_vtxs_orig = 0;
529 int num_nochild_vtxs_orig = 0;
530 for (
auto v = evt->vertices_begin(); v != evt->vertices_end(); ++v) {
531 if ((*v)->particles_in_size()==0&&(*v)->particles_out_size()==0) num_orphan_vtxs_orig++;
532 if ((*v)->particles_in_size()==0) num_noparent_vtxs_orig++;
533 if ((*v)->particles_out_size()==0) num_nochild_vtxs_orig++;
537 if (!toremove.empty()) {
538 ATH_MSG_DEBUG(
"Cleaning event record of " << toremove.size() <<
" bad particles");
540 int signal_vertex_bc = evt->signal_process_vertex() ? evt->signal_process_vertex()->barcode() : 0;
543 if (evt->barcode_to_vertex (signal_vertex_bc) ==
nullptr) {
544 evt->set_signal_process_vertex (
nullptr);
551 for (HepMC::GenParticle* p : *evt) {
553 if (p->status() == 2 && !end_v) {
554 delete p->production_vertex()->remove_particle(p);
564 const int num_particles_filt = evt->particles_size();
565 if(num_particles_orig!=num_particles_filt) {
566 int num_orphan_vtxs_filt = 0;
567 int num_noparent_vtxs_filt = 0;
568 int num_nochild_vtxs_filt = 0;
569 for (
auto v = evt->vertices_begin(); v != evt->vertices_end(); ++v) {
570 if ((*v)->particles_in_size()==0&&(*v)->particles_out_size()==0) num_orphan_vtxs_filt++;
571 if ((*v)->particles_in_size()==0) num_noparent_vtxs_filt++;
572 if ((*v)->particles_out_size()==0) num_nochild_vtxs_filt++;
576 ATH_MSG_INFO(
"Particles filtered: " << num_particles_orig <<
" -> " << num_particles_filt);
578 if (num_orphan_vtxs_filt != num_orphan_vtxs_orig)
579 ATH_MSG_WARNING(
"Change in orphaned vertices: " << num_orphan_vtxs_orig <<
" -> " << num_orphan_vtxs_filt);
580 if (num_noparent_vtxs_filt != num_noparent_vtxs_orig)
581 ATH_MSG_WARNING(
"Change in no-parent vertices: " << num_noparent_vtxs_orig <<
" -> " << num_noparent_vtxs_filt);
582 if (num_nochild_vtxs_filt != num_nochild_vtxs_orig)
583 ATH_MSG_WARNING(
"Change in no-parent vertices: " << num_nochild_vtxs_orig <<
" -> " << num_nochild_vtxs_filt);
588 return StatusCode::SUCCESS;