37 if (gp->parent_event() != ge)
return;
40 HepMC::GenVertex* vstart = gp->production_vertex();
41 HepMC::GenVertex* vend = gp->end_vertex();
44 if (vstart !=
nullptr) vstart->remove_particle(gp);
45 if (vend !=
nullptr) vend->remove_particle(gp);
53 if (vstart !=
nullptr && vend !=
nullptr && vend != vstart) {
54 bool is_only_link =
true;
55 for (
auto pchild=vstart->particles_out_const_begin();pchild!=vstart->particles_out_const_end();++pchild) {
56 if ((*pchild)->end_vertex() == vend) is_only_link =
false;
59 if (vend->position() != HepMC::FourVector())
60 vstart->set_position(vend->position());
61 while (vend->particles_out_size() > 0) {
62 vstart->add_particle_out(*vend->particles_out_const_begin());
64 while (vend->particles_in_size() > 0) {
65 vstart->add_particle_in(*vend->particles_in_const_begin());
75 std::vector<HepMC::GenVertex*> orphaned_vtxs;
76 for (HepMC::GenEvent::vertex_const_iterator vi = ge->vertices_begin(); vi != ge->vertices_end(); ++vi) {
77 if ((*vi)->particles_in_size() == 0 && (*vi)->particles_out_size() == 0) orphaned_vtxs.push_back(*vi);
79 for (HepMC::GenVertex* gv : orphaned_vtxs)
delete gv;
83 inline void reduce(HepMC::GenEvent* ge, std::vector<HepMC::GenParticlePtr> toremove) {
84 while (toremove.size()) {
85 auto gp = toremove.back();
96 HepMC::GenEvent*
evt =
const_cast<HepMC::GenEvent*
>(*ievt);
102 ATH_MSG_DEBUG(
"Please use MC::Loops::findLoops for this event to obtain all particles and vertices in the loops");
105 for (
auto ip: *
evt) {
109 if (newpid ==
m_pidmap.end())
continue;
110 ip->set_pdg_id(newpid->second);
115 if (
evt->weights().empty()) {
116 ATH_MSG_DEBUG(
"Adding a unit weight to empty event weight vector");
117 evt->weights().push_back(1);
121 const HepMC::FourVector nullpos;
122 for (
auto iv:
evt->vertices()) {
123 if (iv->position() == nullpos) {
124 ATH_MSG_DEBUG(
"Setting representative event position vertex");
132 std::vector<HepMC::GenParticlePtr> beams_t;
134 if (
p->status() == 4) beams_t.push_back(
p);
136 if (beams_t.size() > 2) {
137 ATH_MSG_INFO(
"Invalid number of beam particles " << beams_t.size() <<
". Will try to fix.");
138 std::vector<HepMC::GenParticlePtr> bparttoremove;
139 for (
const auto& bpart : beams_t) {
140 if (bpart->id() == 0 && bpart->production_vertex()) bparttoremove.push_back(bpart);
142 for (
auto bpart: bparttoremove) {
143 bpart->production_vertex()->remove_particle_out(bpart);
148 std::vector<HepMC::GenParticlePtr> semi_disconnected, decay_loop_particles;
149 for (
auto ip :
evt->particles()) {
152 bool particle_to_fix =
false;
153 int abspid = std::abs(
ip->pdg_id());
154 auto vProd =
ip->production_vertex();
155 auto vEnd =
ip->end_vertex();
157 if ( (!vProd || vProd->id() == 0) && vEnd &&
ip->status() != 4) {
158 particle_to_fix =
true;
159 ATH_MSG_DEBUG(
"Found particle " <<
ip->pdg_id() <<
" without production vertex! HepMC status = " <<
ip->status());
162 if (vProd && !vEnd &&
ip->status() != 1) {
163 particle_to_fix =
true;
164 ATH_MSG_DEBUG(
"Found particle " <<
ip->pdg_id() <<
" without decay vertex! HepMC status = " <<
ip->status());
166 if (particle_to_fix) semi_disconnected.push_back(
ip);
168 if (abspid == 43 || abspid == 44 || abspid == 30353 || abspid == 30343) {
169 decay_loop_particles.push_back(
ip);
176 if ( semi_disconnected.size() == 4 || semi_disconnected.size() == 3 || semi_disconnected.size() == 2) {
179 HepMC::FourVector
sum(0,0,0,0);
180 for (
const auto&
part : semi_disconnected) {
181 if (!
part->production_vertex() || !
part->production_vertex()->id()) {
182 no_prov++;
sum +=
part->momentum();
184 if (!
part->end_vertex()) {
185 no_endv++;
sum -=
part->momentum();
188 ATH_MSG_INFO(
"Heuristics: found " << semi_disconnected.size() <<
" semi-disconnected particles. Momentum sum is " <<
sum);
190 if (no_endv && no_prov && ( no_endv + no_prov == semi_disconnected.size() )) {
191 if (std::abs(
sum.px()) < 1
e-2 && std::abs(
sum.py()) < 1
e-2 && std::abs(
sum.pz()) < 1
e-2 ) {
192 ATH_MSG_INFO(
"Try " << no_endv <<
"->" << no_prov <<
" splitting/merging.");
194 for (
auto part : semi_disconnected) {
195 if (!
part->production_vertex() ||
part->production_vertex()->id() == 0)
v->add_particle_out(
part);
197 for (
auto part : semi_disconnected) {
198 if (!
part->end_vertex())
v->add_particle_in(
part);
209 for (
auto part: decay_loop_particles) {
211 auto vend =
part->end_vertex();
212 auto vprod =
part->production_vertex();
213 if (!vprod || !vend)
continue;
214 bool loop_in_decay =
true;
217 auto sisters = vend->particles_in();
218 for (
auto sister: sisters) {
219 if (vprod != sister->production_vertex()) loop_in_decay =
false;
221 if (!loop_in_decay)
continue;
224 auto daughters = vend->particles_out();
225 for (
auto p : daughters) vprod->add_particle_out(
p);
226 for (
auto sister : sisters) {
227 vprod->remove_particle_out(sister);
228 vend->remove_particle_in(sister);
229 evt->remove_particle(sister);
231 evt->remove_vertex(vend);
236 std::vector<HepMC::GenParticlePtr> toremove;
237 for (
auto ip:
evt->particles()) {
242 bool bad_particle =
false;
258 int abs_pdg_id = std::abs(
ip->pdg_id());
259 bool is_decayed_weak_boson = ( abs_pdg_id == 23 || abs_pdg_id == 24 || abs_pdg_id == 25 ) &&
ip->end_vertex();
267 if (bad_particle) toremove.push_back(
ip);
271 const int num_particles_orig =
evt->particles().size();
274 if (!toremove.empty()) {
275 ATH_MSG_DEBUG(
"Cleaning event record of " << toremove.size() <<
" bad particles");
276 for (
auto part: toremove)
evt->remove_particle(
part);
283 const std::vector <HepMC::GenParticlePtr> allParticles=
evt->particles();
284 for(
auto p : allParticles) {
286 if(
p->status() == 2 && !end_v) {
287 evt->remove_particle(
p);
296 const int num_particles_filt =
evt->particles().size();
298 if(num_particles_orig!=num_particles_filt) {
300 ATH_MSG_INFO(
"Particles filtered: " << num_particles_orig <<
" -> " << num_particles_filt);
305 if (
evt->weights().empty()) {
306 ATH_MSG_DEBUG(
"Adding a unit weight to empty event weight vector");
307 evt->weights().push_back(1);
311 if (
evt->signal_process_vertex() == NULL) {
312 const HepMC::FourVector nullpos;
313 for (HepMC::GenEvent::vertex_const_iterator iv =
evt->vertices_begin(); iv !=
evt->vertices_end(); ++iv) {
314 if ((*iv)->position() == nullpos) {
315 ATH_MSG_DEBUG(
"Setting representative event position vertex");
316 evt->set_signal_process_vertex(
const_cast<HepMC::GenVertex*
>(*iv));
324 std::vector<HepMC::GenParticlePtr> semi_disconnected, decay_loop_particles;
325 for (
auto ip : *
evt) {
328 bool particle_to_fix =
false;
329 int abspid = std::abs(
ip->pdg_id());
330 auto vProd =
ip->production_vertex();
331 auto vEnd =
ip->end_vertex();
333 if ( (!vProd || vProd->id() == 0) && vEnd &&
ip->status() != 4) {
334 particle_to_fix =
true;
335 ATH_MSG_DEBUG(
"Found particle " <<
ip->pdg_id() <<
" without production vertex! HepMC status = " <<
ip->status());
338 if (vProd && !vEnd &&
ip->status() != 1) {
339 particle_to_fix =
true;
340 ATH_MSG_DEBUG(
"Found particle " <<
ip->pdg_id() <<
" without decay vertex! HepMC status = " <<
ip->status());
342 if (particle_to_fix) semi_disconnected.push_back(
ip);
344 if (abspid == 43 || abspid == 44 || abspid == 30353 || abspid == 30343) {
345 decay_loop_particles.push_back(
ip);
351 if (semi_disconnected.size() == 4 ||semi_disconnected.size() == 3 || semi_disconnected.size() == 2) {
354 double vsum[4] = {0,0,0,0};
355 for (
auto part : semi_disconnected) {
356 if (!
part->production_vertex() ) {
358 vsum[0] +=
part->momentum().px();
359 vsum[1] +=
part->momentum().py();
360 vsum[2] +=
part->momentum().pz();
361 vsum[3] +=
part->momentum().e();
363 if (!
part->end_vertex()) {
365 vsum[0] -=
part->momentum().px();
366 vsum[1] -=
part->momentum().py();
367 vsum[2] -=
part->momentum().pz();
368 vsum[3] -=
part->momentum().e();
371 HepMC::FourVector
sum(vsum[0],vsum[1],vsum[2],vsum[3]);
372 ATH_MSG_INFO(
"Heuristics: found " << semi_disconnected.size() <<
" semi-disconnected particles. Momentum sum is " << vsum[0] <<
" " << vsum[1] <<
" " << vsum[2] <<
" " << vsum[3]);
374 if (no_endv && no_prov && ( no_endv + no_prov == semi_disconnected.size() )) {
375 if (std::abs(
sum.px()) < 1
e-2 && std::abs(
sum.py()) < 1
e-2 && std::abs(
sum.pz()) < 1
e-2 ) {
376 ATH_MSG_INFO(
"Try " << no_endv <<
"->" << no_prov <<
" splitting/merging.");
378 for (
auto part : semi_disconnected) {
379 if (!
part->production_vertex())
v->add_particle_out(
part);
381 for (
auto part : semi_disconnected) {
382 if (!
part->end_vertex())
v->add_particle_in(
part);
393 for (
auto part: decay_loop_particles) {
395 auto vend =
part->end_vertex();
396 auto vprod =
part->production_vertex();
397 if (!vend || !vprod)
continue;
398 bool loop_in_decay =
true;
400 std::vector<HepMC::GenParticlePtr> sisters;
402 for (
auto sister : sisters) {
403 if (vprod != sister->production_vertex()) loop_in_decay =
false;
405 if (!loop_in_decay)
continue;
407 std::vector<HepMC::GenParticlePtr> daughters;
409 for (
auto p : daughters) vprod->add_particle_out(
p);
410 for (
auto sister : sisters) {
411 vprod->remove_particle(sister);
412 vend->remove_particle(sister);
414 evt->remove_vertex(vend);
420 std::vector<HepMC::GenParticlePtr> toremove; toremove.reserve(10);
421 for (HepMC::GenEvent::particle_const_iterator
ip =
evt->particles_begin();
ip !=
evt->particles_end(); ++
ip) {
423 if (*
ip == NULL)
continue;
427 bool bad_particle =
false;
446 int abs_pdg_id = std::abs((*ip)->pdg_id());
447 bool is_decayed_weak_boson = ( abs_pdg_id == 23 || abs_pdg_id == 24 || abs_pdg_id == 25 ) && (*ip)->end_vertex();
456 if (bad_particle) toremove.push_back(*
ip);
460 const int num_particles_orig =
evt->particles_size();
461 int num_orphan_vtxs_orig = 0;
462 int num_noparent_vtxs_orig = 0;
463 int num_nochild_vtxs_orig = 0;
464 for (
auto v =
evt->vertices_begin();
v !=
evt->vertices_end(); ++
v) {
465 if ((*v)->particles_in_size()==0&&(*v)->particles_out_size()==0) num_orphan_vtxs_orig++;
466 if ((*v)->particles_in_size()==0) num_noparent_vtxs_orig++;
467 if ((*v)->particles_out_size()==0) num_nochild_vtxs_orig++;
471 if (!toremove.empty()) {
472 ATH_MSG_DEBUG(
"Cleaning event record of " << toremove.size() <<
" bad particles");
474 int signal_vertex_bc =
evt->signal_process_vertex() ?
evt->signal_process_vertex()->barcode() : 0;
477 if (
evt->barcode_to_vertex (signal_vertex_bc) ==
nullptr) {
478 evt->set_signal_process_vertex (
nullptr);
487 if (
p->status() == 2 && !end_v) {
488 delete p->production_vertex()->remove_particle(
p);
498 const int num_particles_filt =
evt->particles_size();
499 if(num_particles_orig!=num_particles_filt) {
500 int num_orphan_vtxs_filt = 0;
501 int num_noparent_vtxs_filt = 0;
502 int num_nochild_vtxs_filt = 0;
503 for (
auto v =
evt->vertices_begin();
v !=
evt->vertices_end(); ++
v) {
504 if ((*v)->particles_in_size()==0&&(*v)->particles_out_size()==0) num_orphan_vtxs_filt++;
505 if ((*v)->particles_in_size()==0) num_noparent_vtxs_filt++;
506 if ((*v)->particles_out_size()==0) num_nochild_vtxs_filt++;
510 ATH_MSG_INFO(
"Particles filtered: " << num_particles_orig <<
" -> " << num_particles_filt);
512 if (num_orphan_vtxs_filt != num_orphan_vtxs_orig)
513 ATH_MSG_WARNING(
"Change in orphaned vertices: " << num_orphan_vtxs_orig <<
" -> " << num_orphan_vtxs_filt);
514 if (num_noparent_vtxs_filt != num_noparent_vtxs_orig)
515 ATH_MSG_WARNING(
"Change in no-parent vertices: " << num_noparent_vtxs_orig <<
" -> " << num_noparent_vtxs_filt);
516 if (num_nochild_vtxs_filt != num_nochild_vtxs_orig)
517 ATH_MSG_WARNING(
"Change in no-parent vertices: " << num_nochild_vtxs_orig <<
" -> " << num_nochild_vtxs_filt);
521 return StatusCode::SUCCESS;
531 return StatusCode::SUCCESS;
540 return p->pdg_id() == 0;
545 if (!
p)
return false;
546 auto v=
p->production_vertex();
547 if (!
v)
return false;
549 for (
const auto& anc:
v->particles_in()) {
552 if (storage->find(
p->id()) != storage->end())
return false;
553 storage->insert(
p->id());
554 for (
const auto& anc:
v->particles_in()) {
555 if (
fromDecay(anc, storage))
return true;
558 for (
auto anc=
v->particles_in_const_begin(); anc !=
v->particles_in_const_end(); ++anc) {
561 if (storage->find(
p->barcode()) != storage->end())
return false;
562 storage->insert(
p->barcode());
563 for (
auto anc=
v->particles_in_const_begin(); anc !=
v->particles_in_const_end(); ++anc){
564 if (
fromDecay(*anc, storage))
return true;
572 auto storage = std::make_shared<std::set<int>>();
578 return (
p->production_vertex() ==
p->end_vertex() &&
p->end_vertex() !=
nullptr);