42 if (!
m_looper.loop_particles().empty() || !
m_looper.loop_vertices().empty()) {
45 ATH_MSG_DEBUG(
"Please use MC::Loops::findLoops for this event to obtain all particles and vertices in the loops");
47 auto old_momentum = evt->momentum_unit();
48 auto old_length = evt->length_unit();
59 auto newpid =
m_pidmap.find(ip->pdg_id());
60 if (newpid ==
m_pidmap.end())
continue;
61 ip->set_pdg_id(newpid->second);
70 auto cycles = std::make_shared<HepMC3::IntAttribute>(1);
75 if (evt->weights().empty()) {
76 ATH_MSG_DEBUG(
"Adding a unit weight to empty event weight vector");
77 evt->weights().push_back(1);
82 for (
auto iv: evt->vertices()) {
83 if (iv->position() == nullpos) {
84 ATH_MSG_DEBUG(
"Setting representative event position vertex");
92 std::vector<HepMC::GenParticlePtr> beams_t;
94 if (p->status() == 4) beams_t.push_back(p);
96 if (beams_t.size() > 2) {
97 ATH_MSG_INFO(
"Invalid number of beam particles " << beams_t.size() <<
". Will try to fix.");
98 std::vector<HepMC::GenParticlePtr> bparttoremove;
99 for (
const auto& bpart : beams_t) {
100 if (bpart->id() == 0 && bpart->production_vertex()) bparttoremove.push_back(bpart);
102 for (
auto bpart: bparttoremove) {
103 bpart->production_vertex()->remove_particle_out(bpart);
111 double units_problem = -1.;
113 if (beams_t.size() > 0 ){
115 if (p->momentum().pz() > 1e9) units_problem = p->momentum().pz();
120 if (p && p->momentum().pz() > 1e9) units_problem = p->momentum().pz();
123 if (units_problem>0){
124 ATH_MSG_INFO(
"Apparent units problem; beam particles have z-momentum " << units_problem <<
" in MeV. Will divide by 1000.");
130 std::vector<HepMC::GenParticlePtr> semi_disconnected, decay_loop_particles;
131 for (
auto ip : evt->particles()) {
134 bool particle_to_fix =
false;
135 int abspid = std::abs(ip->pdg_id());
136 auto vProd = ip->production_vertex();
137 auto vEnd = ip->end_vertex();
139 if ( (!vProd || vProd->id() == 0) && vEnd && ip->status() != 4) {
140 particle_to_fix =
true;
141 ATH_MSG_DEBUG(
"Found particle " << ip->pdg_id() <<
" without production vertex! HepMC status = " << ip->status());
144 if (vProd && !vEnd && ip->status() != 1) {
145 particle_to_fix =
true;
146 ATH_MSG_DEBUG(
"Found particle " << ip->pdg_id() <<
" without decay vertex! HepMC status = " << ip->status());
148 if (particle_to_fix) semi_disconnected.push_back(ip);
150 if (abspid == 43 || abspid == 44 || abspid == 30353 || abspid == 30343) {
151 decay_loop_particles.push_back(std::move(ip));
163 if ( !
m_ignoreSemiDisconnected && (semi_disconnected.size() == 4 || semi_disconnected.size() == 3 || semi_disconnected.size() == 2)) {
167 std::set<HepMC::GenVertexPtr> standalone;
168 for (
const auto& part : semi_disconnected) {
169 if (!part->production_vertex() || !part->production_vertex()->id()) {
170 no_prov++; sum += part->momentum();
172 if (!part->end_vertex()) {
173 no_endv++; sum -= part->momentum();
175 if (part->production_vertex()) standalone.insert(part->production_vertex());
176 if (part->end_vertex()) standalone.insert(part->end_vertex());
178 ATH_MSG_INFO(
"Heuristics: found " << semi_disconnected.size() <<
" semi-disconnected particles. Momentum sum is " << sum <<
" Standalone vertices " << standalone.size());
179 bool standalonevertex = (standalone.size() == 1 && (*standalone.begin())->particles_in().size() + (*standalone.begin())->particles_out().size() == semi_disconnected.size());
181 if (! standalonevertex && no_endv && no_prov && ( no_endv + no_prov == semi_disconnected.size() )) {
182 if (std::abs(sum.px()) < 1e-2 && std::abs(sum.py()) < 1e-2 && std::abs(sum.pz()) < 1e-2 ) {
183 ATH_MSG_INFO(
"Try " << no_endv <<
"->" << no_prov <<
" splitting/merging.");
185 for (
auto part : semi_disconnected) {
186 if (!part->production_vertex() || part->production_vertex()->id() == 0) v->add_particle_out(std::move(part));
188 for (
auto part : semi_disconnected) {
189 if (!part->end_vertex()) v->add_particle_in(std::move(part));
191 evt->add_vertex(std::move(v));
200 for (
auto part: decay_loop_particles) {
202 auto vend = part->end_vertex();
203 auto vprod = part->production_vertex();
204 if (!vprod || !vend)
continue;
205 bool loop_in_decay =
true;
208 auto sisters = vend->particles_in();
209 for (
auto sister: sisters) {
210 if (vprod != sister->production_vertex()) loop_in_decay =
false;
212 if (!loop_in_decay)
continue;
215 auto daughters = vend->particles_out();
216 for (
auto p : daughters) vprod->add_particle_out(std::move(p));
217 for (
auto sister : sisters) {
218 vprod->remove_particle_out(sister);
219 vend->remove_particle_in(sister);
220 evt->remove_particle(std::move(sister));
222 evt->remove_vertex(std::move(vend));
227 std::vector<HepMC::GenParticlePtr> toremove;
228 for (
auto ip: evt->particles()) {
233 bool bad_particle =
false;
239 if (
msgLvl( MSG::DEBUG ) ) HepMC::Print::line(ip);
246 if (
msgLvl( MSG::DEBUG ) )HepMC::Print::line(ip);
249 int abs_pdg_id = std::abs(ip->pdg_id());
250 bool is_decayed_weak_boson = ( abs_pdg_id == 23 || abs_pdg_id == 24 || abs_pdg_id == 25 ) && ip->end_vertex();
255 if (
msgLvl( MSG::DEBUG ) ) HepMC::Print::line(ip);
258 if (bad_particle) toremove.push_back(std::move(ip));
262 const int num_particles_orig = evt->particles().size();
265 if (!toremove.empty()) {
266 ATH_MSG_DEBUG(
"Cleaning event record of " << toremove.size() <<
" bad particles");
267 for (
auto part: toremove) evt->remove_particle(std::move(part));
274 const std::vector <HepMC::GenParticlePtr> allParticles=evt->particles();
275 for(
auto p : allParticles) {
277 if(p->status() == 2 && !end_v) {
278 evt->remove_particle(std::move(p));
287 const int num_particles_filt = evt->particles().size();
289 if(num_particles_orig!=num_particles_filt) {
291 ATH_MSG_INFO(
"Particles filtered: " << num_particles_orig <<
" -> " << num_particles_filt);
295 return StatusCode::SUCCESS;