HepMC3 event record library
GenEvent.cc
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
5//
6/**
7 * @file GenEvent.cc
8 * @brief Implementation of \b class GenEvent
9 *
10 */
11#include <algorithm> // sort
12#include <deque>
13
15#include "HepMC3/GenEvent.h"
16#include "HepMC3/GenParticle.h"
17#include "HepMC3/GenVertex.h"
18
19
20namespace HepMC3 {
21
24 : m_momentum_unit(mu), m_length_unit(lu), //m_weights(std::vector<double>(1, 1.0)),//Prevent from different number of weights and names
25 m_rootvertex(std::make_shared<GenVertex>()) {}
26
27
28GenEvent::GenEvent(std::shared_ptr<GenRunInfo> run,
31 : m_momentum_unit(mu), m_length_unit(lu), //m_weights(std::vector<double>(1, 1.0)),//Prevent from different number of weights and names
32 m_rootvertex(std::make_shared<GenVertex>()),
33 m_run_info(run) {
34 if ( run && !run->weight_names().empty() ) {
35 m_weights = std::vector<double>(run->weight_names().size(), 1.0);
36 }
37}
38
39const std::vector<ConstGenParticlePtr>& GenEvent::particles() const {
40 return *(reinterpret_cast<const std::vector<ConstGenParticlePtr>*>(&m_particles));
41}
42
43const std::vector<ConstGenVertexPtr>& GenEvent::vertices() const {
44 return *(reinterpret_cast<const std::vector<ConstGenVertexPtr>*>(&m_vertices));
45}
46
47
48void GenEvent::add_particle(GenParticlePtr p) {
49 if ( !p || p->in_event() ) return;
50
51 m_particles.emplace_back(p);
52
53 p->m_event = this;
54 p->m_id = particles().size();
55
56 // Particles without production vertex are added to the root vertex
57 if ( !p->production_vertex() ) {
58 m_rootvertex->add_particle_out(p);
59 }
60}
61
62
64 if (this != &e)
65 {
67 std::lock_guard<std::recursive_mutex> lhs_lk(m_lock_attributes, std::adopt_lock);
68 std::lock_guard<std::recursive_mutex> rhs_lk(e.m_lock_attributes, std::adopt_lock);
69 GenEventData tdata;
70 e.write_data(tdata);
71 read_data(tdata);
73 }
74}
75
77 for ( auto attm = m_attributes.begin(); attm != m_attributes.end(); ++attm) {
78 for ( auto att = attm->second.begin(); att != attm->second.end(); ++att) { if (att->second) att->second->m_event = nullptr;}
79 }
80 for ( auto v = m_vertices.begin(); v != m_vertices.end(); ++v ) if (*v) if ((*v)->m_event == this) (*v)->m_event = nullptr;
81 for ( auto p = m_particles.begin(); p != m_particles.end(); ++p ) if (*p) if ((*p)->m_event == this) (*p)->m_event = nullptr;
82}
83
85 if (this != &e)
86 {
88 std::lock_guard<std::recursive_mutex> lhs_lk(m_lock_attributes, std::adopt_lock);
89 std::lock_guard<std::recursive_mutex> rhs_lk(e.m_lock_attributes, std::adopt_lock);
90 GenEventData tdata;
91 e.write_data(tdata);
92 read_data(tdata);
94 }
95 return *this;
96}
97
98
99void GenEvent::add_vertex(GenVertexPtr v) {
100 if ( !v|| v->in_event() ) return;
101 m_vertices.emplace_back(v);
102
103 v->m_event = this;
104 v->m_id = -static_cast<int>(vertices().size());
105
106 // Add all incoming and outgoing particles and restore their production/end vertices
107 for (const auto& p: v->particles_in()) {
108 if (!p->in_event()) add_particle(p);
109 p->m_end_vertex = v->shared_from_this();
110 }
111
112 for (const auto& p: v->particles_out()) {
113 if (!p->in_event()) add_particle(p);
114 p->m_production_vertex = v;
115 }
116}
117
118
119void GenEvent::remove_particle(GenParticlePtr p) {
120 if ( !p || p->parent_event() != this ) return;
121
122 HEPMC3_DEBUG(30, "GenEvent::remove_particle - called with particle: " << p->id());
123 GenVertexPtr end_vtx = p->end_vertex();
124 if ( end_vtx ) {
125 end_vtx->remove_particle_in(p);
126
127 // If that was the only incoming particle, remove vertex from the event
128 if ( end_vtx->particles_in().empty() ) remove_vertex(end_vtx);
129 }
130
131 GenVertexPtr prod_vtx = p->production_vertex();
132 if ( prod_vtx ) {
133 prod_vtx->remove_particle_out(p);
134
135 // If that was the only outgoing particle, remove vertex from the event
136 if ( prod_vtx->particles_out().empty() ) remove_vertex(prod_vtx);
137 }
138
139 HEPMC3_DEBUG(30, "GenEvent::remove_particle - erasing particle: " << p->id())
140
141 int idx = p->id();
142 auto it = m_particles.erase(m_particles.begin() + idx-1);
143
144 // Remove attributes of this particle
145 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
146 for (att_key_t& vt1: m_attributes) {
147 auto vt2 = vt1.second.find(idx);
148 if (vt2 == vt1.second.end()) continue;
149 vt1.second.erase(vt2);
150 }
151
152 //
153 // Reassign id of attributes with id above this one
154 //
155 std::vector< std::pair< int, std::shared_ptr<Attribute> > > changed_attributes;
156
157 for (att_key_t& vt1: m_attributes) {
158 changed_attributes.clear();
159
160 for (auto vt2 = vt1.second.begin(); vt2 != vt1.second.end(); ++vt2) {
161 if ( (*vt2).first > p->id() ) {
162 changed_attributes.emplace_back(*vt2);
163 }
164 }
165
166 std::sort(changed_attributes.begin(),changed_attributes.end(), [](const std::pair< int, std::shared_ptr<Attribute> > &a, const std::pair< int, std::shared_ptr<Attribute> > &b) { return a.first < b.first; });
167 for ( const auto& val: changed_attributes ) {
168 vt1.second.erase(val.first);
169 vt1.second[val.first-1] = val.second;
170 }
171 }
172 // Reassign id of particles with id above this one
173 for (; it != m_particles.end(); ++it) {
174 --((*it)->m_id);
175 }
176
177 // Finally - set parent event and id of this particle to 0
178 p->m_event = nullptr;
179 p->m_id = 0;
180}
181
182void GenEvent::remove_particles(std::vector<GenParticlePtr> v) {
183 std::sort(v.begin(), v.end(), [](const GenParticlePtr& p1, const GenParticlePtr& p2) { return p1->id() > p2->id();});
184
185 for (auto p = v.begin(); p != v.end(); ++p) {
186 remove_particle(*p);
187 }
188}
189
190void GenEvent::remove_vertex(GenVertexPtr v) {
191 if ( !v || v->parent_event() != this ) return;
192
193 HEPMC3_DEBUG(30, "GenEvent::remove_vertex - called with vertex: " << v->id());
194 std::shared_ptr<GenVertex> null_vtx;
195
196 for (const auto& p: v->particles_in()) {
197 p->m_end_vertex = std::weak_ptr<GenVertex>();
198 }
199
200 for (const auto& p: v->particles_out()) {
201 p->m_production_vertex = std::weak_ptr<GenVertex>();
202
203 // recursive delete rest of the tree
205 }
206
207 // Erase this vertex from vertices list
208 HEPMC3_DEBUG(30, "GenEvent::remove_vertex - erasing vertex: " << v->id())
209
210 int idx = -v->id();
211 auto it = m_vertices.erase(m_vertices.begin() + idx-1);
212 // Remove attributes of this vertex
213 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
214 for (att_key_t& vt1: m_attributes) {
215 auto vt2 = vt1.second.find(-idx);
216 if (vt2 == vt1.second.end()) continue;
217 vt1.second.erase(vt2);
218 }
219
220 //
221 // Reassign id of attributes with id below this one
222 //
223
224 std::vector< std::pair< int, std::shared_ptr<Attribute> > > changed_attributes;
225
226 for ( att_key_t& vt1: m_attributes ) {
227 changed_attributes.clear();
228
229 for (auto vt2 = vt1.second.begin(); vt2 != vt1.second.end(); ++vt2) {
230 if ( (*vt2).first < v->id() ) {
231 changed_attributes.emplace_back(*vt2);
232 }
233 }
234
235 std::reverse(changed_attributes.begin(),changed_attributes.end());
236 std::sort(changed_attributes.begin(),changed_attributes.end(),[](const std::pair< int, std::shared_ptr<Attribute> > &a, const std::pair< int, std::shared_ptr<Attribute> > &b) { return a.first > b.first; });
237 for ( const auto& val: changed_attributes ) {
238 vt1.second.erase(val.first);
239 vt1.second[val.first+1] = val.second;
240 }
241 }
242
243 // Reassign id of particles with id above this one
244 for (; it != m_vertices.end(); ++it) {
245 ++((*it)->m_id);
246 }
247
248 // Finally - set parent event and id of this vertex to 0
249 v->m_event = nullptr;
250 v->m_id = 0;
251}
252/* This looks dangerously similar to the recusive event traversel that we forbade in the
253 Core library due to wories about generator dependence
254*/
255static bool visit_children(std::map<ConstGenVertexPtr, int> &a, const ConstGenVertexPtr& v)
256{
257 for (const ConstGenParticlePtr& p: v->particles_out()) {
258 if (p->end_vertex())
259 {
260 if (a[p->end_vertex()] != 0) { return true; }
261 a[p->end_vertex()]++;
262 if (visit_children(a, p->end_vertex())) return true;
263 }
264 }
265 return false;
266}
267
268void GenEvent::add_tree(const std::vector<GenParticlePtr> &parts) {
269 m_particles.reserve(m_particles.size() + parts.size());
270 m_vertices.reserve(m_vertices.size() + parts.size());
271 std::shared_ptr<IntAttribute> existing_hc = attribute<IntAttribute>("cycles");
272 bool has_cycles = false;
273 std::map<GenVertexPtr, int> sortingv;
274 std::vector<GenVertexPtr> noinv;
275 if (existing_hc) if (existing_hc->value() != 0) has_cycles = true;
276 if (!existing_hc)
277 {
278 for (const GenParticlePtr& p: parts) {
279 GenVertexPtr v = p->production_vertex();
280 if (v) sortingv[v]=0;
281 if ( !v || v->particles_in().empty()) {
282 GenVertexPtr v2 = p->end_vertex();
283 if (v2) {noinv.emplace_back(v2); sortingv[v2] = 0;}
284 }
285 }
286 for (const GenVertexPtr& v: noinv) {
287 std::map<ConstGenVertexPtr, int> sorting_temp(sortingv.begin(), sortingv.end());
288 has_cycles = (has_cycles || visit_children(sorting_temp, v));
289 }
290 }
291 if (has_cycles) {
292 add_attribute("cycles", std::make_shared<IntAttribute>(1));
293 /* Commented out as improvemnts allow us to do sorting in other way.
294 for ( std::map<GenVertexPtr,int>::iterator vi=sortingv.begin();vi!=sortingv.end();++vi) if ( !vi->first->in_event() ) add_vertex(vi->first);
295 return;
296 */
297 }
298
299 std::deque<GenVertexPtr> sorting;
300
301 // Find all starting vertices (end vertex of particles that have no production vertex)
302 for (const auto& p: parts) {
303 const GenVertexPtr &v = p->production_vertex();
304 if ( !v || v->particles_in().empty() ) {
305 const GenVertexPtr &v2 = p->end_vertex();
306 if (v2) sorting.emplace_back(v2);
307 }
308 }
309
311 unsigned int sorting_loop_count = 0;
312 unsigned int max_deque_size = 0;
313 )
314
315 // Add vertices to the event in topological order
316 while ( !sorting.empty() ) {
318 if ( sorting.size() > max_deque_size ) max_deque_size = sorting.size();
319 ++sorting_loop_count;
320 )
321
322 GenVertexPtr &v = sorting.front();
323
324 bool added = false;
325
326 // Add all mothers to the front of the list
327 for (const auto& p: v->particles_in() ) {
328 GenVertexPtr v2 = p->production_vertex();
329 if ( v2 && !v2->in_event() && find(sorting.begin(), sorting.end(), v2) == sorting.end() ) {
330 sorting.push_front(v2);
331 added = true;
332 }
333 }
334
335 // If we have added at least one production vertex,
336 // our vertex is not the first one on the list
337 if ( added ) continue;
338
339 // If vertex not yet added
340 if ( !v->in_event() ) {
341 add_vertex(v);
342
343 // Add all end vertices to the end of the list
344 for (const auto& p: v->particles_out()) {
345 GenVertexPtr v2 = p->end_vertex();
346 if ( v2 && !v2->in_event()&& find(sorting.begin(), sorting.end(), v2) == sorting.end() ) {
347 sorting.emplace_back(v2);
348 }
349 }
350 }
351
352 sorting.pop_front();
353 }
354
355 // LL: Make sure root vertex has index zero and is not written out
356 if ( m_rootvertex->id() != 0 ) {
357 const int vx = -1 - m_rootvertex->id();
358 const int rootid = m_rootvertex->id();
359 if ( vx >= 0 && vx < static_cast<int>(m_vertices.size()) && m_vertices[vx] == m_rootvertex ) {
360 auto next = m_vertices.erase(m_vertices.begin() + vx);
361 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
362 for (auto & vt1: m_attributes) {
363 std::vector< std::pair< int, std::shared_ptr<Attribute> > > changed_attributes;
364 for ( const auto& vt2 : vt1.second ) {
365 if ( vt2.first <= rootid ) {
366 changed_attributes.emplace_back(vt2);
367 }
368 }
369 for ( const auto& val : changed_attributes ) {
370 vt1.second.erase(val.first);
371 vt1.second[val.first == rootid? 0: val.first + 1] = val.second;
372 }
373 }
374 m_rootvertex->m_id = 0;
375 while ( next != m_vertices.end() ) {
376 ++((*next++)->m_id);
377 }
378 } else {
379 HEPMC3_WARNING_LEVEL(700,"GenEvent::add_tree Suspicious looking rootvertex found. Will try to cope.")
380 }
381 }
382
384 HEPMC3_DEBUG(6, "GenEvent - particles sorted: "
385 << this->particles().size() << ", max deque size: "
386 << max_deque_size << ", iterations: " << sorting_loop_count)
387 )
388}
389
390
391void GenEvent::reserve(const size_t& parts, const size_t& verts) {
392 m_particles.reserve(parts);
393 m_vertices.reserve(verts);
394}
395
396
397void GenEvent::set_units(Units::MomentumUnit new_momentum_unit, Units::LengthUnit new_length_unit) {
398 if ( new_momentum_unit != m_momentum_unit ) {
399 for ( GenParticlePtr& p: m_particles ) {
400 Units::convert(p->m_data.momentum, m_momentum_unit, new_momentum_unit);
401 Units::convert(p->m_data.mass, m_momentum_unit, new_momentum_unit);
402 }
403
404 m_momentum_unit = new_momentum_unit;
405 }
406
407 if ( new_length_unit != m_length_unit ) {
408 for (GenVertexPtr& v: m_vertices) {
409 FourVector &fv = v->m_data.position;
410 if ( !fv.is_zero() ) Units::convert( fv, m_length_unit, new_length_unit );
411 }
412
413 m_length_unit = new_length_unit;
414 }
415}
416
417
419 return m_rootvertex->data().position;
420}
421
422std::vector<ConstGenParticlePtr> GenEvent::beams(const int status) const {
423 if (!status) return std::const_pointer_cast<const GenVertex>(m_rootvertex)->particles_out();
424 std::vector<ConstGenParticlePtr> ret;
425 for (auto& p: m_rootvertex->particles_out()) if (p->status() == status) ret.emplace_back(p);
426 return ret;
427}
428
429std::vector<ConstGenParticlePtr> GenEvent::beams() const {
430 return std::const_pointer_cast<const GenVertex>(m_rootvertex)->particles_out();
431}
432
433
434const std::vector<GenParticlePtr> & GenEvent::beams() {
435 return m_rootvertex->particles_out();
436}
437
439 m_rootvertex->set_position(event_pos() + delta);
440
441 // Offset all vertices
442 for ( GenVertexPtr& v: m_vertices ) {
443 if ( v->has_set_position() ) {
444 v->set_position(v->position() + delta);
445 }
446 }
447}
448
449bool GenEvent::rotate(const FourVector& delta)
450{
451 long double cosa = std::cos(delta.x());
452 long double sina = std::sin(delta.x());
453 long double cosb = std::cos(delta.y());
454 long double sinb = std::sin(delta.y());
455 long double cosg = std::cos(delta.z());
456 long double sing = std::sin(delta.z());
457
458 for ( auto& p: m_particles)
459 {
460 const FourVector& mom = p->momentum();
461 long double tempX = mom.x();
462 long double tempY = mom.y();
463 long double tempZ = mom.z();
464
465 long double tempY_ = cosa*tempY+sina*tempZ;
466 long double tempZ_ = -sina*tempY+cosa*tempZ;
467 tempY = tempY_;
468 tempZ = tempZ_;
469
470 long double tempX_ = cosb*tempX-sinb*tempZ;
471 tempZ_ = sinb*tempX+cosb*tempZ;
472 tempX = tempX_;
473 tempZ = tempZ_;
474
475 tempX_ = cosg*tempX+sing*tempY;
476 tempY_ = -sing*tempX+cosg*tempY;
477 tempX = tempX_;
478 tempY = tempY_;
479
480 FourVector temp(tempX, tempY, tempZ, mom.e());
481 p->set_momentum(temp);
482 }
483 for (auto& v: m_vertices)
484 {
485 const FourVector& pos = v->position();
486 if (pos.is_zero()) continue;
487
488 long double tempX = pos.x();
489 long double tempY = pos.y();
490 long double tempZ = pos.z();
491
492 long double tempY_ = cosa*tempY+sina*tempZ;
493 long double tempZ_ = -sina*tempY+cosa*tempZ;
494 tempY = tempY_;
495 tempZ = tempZ_;
496
497 long double tempX_ = cosb*tempX-sinb*tempZ;
498 tempZ_ = sinb*tempX+cosb*tempZ;
499 tempX = tempX_;
500 tempZ = tempZ_;
501
502 tempX_ = cosg*tempX+sing*tempY;
503 tempY_ = -sing*tempX+cosg*tempY;
504 tempX = tempX_;
505 tempY = tempY_;
506
507 FourVector temp(tempX, tempY, tempZ, pos.t());
508 v->set_position(temp);
509 }
510
511
512 return true;
513}
514
515bool GenEvent::reflect(const int axis)
516{
517 if ( axis > 3 || axis < 0 )
518 {
519 HEPMC3_WARNING_LEVEL(400,"GenEvent::reflect: wrong axis")
520 return false;
521 }
522 switch (axis)
523 {
524 case 0:
525 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setX(-p->momentum().x()); p->set_momentum(temp);}
526 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setX(-v->position().x()); v->set_position(temp);}
527 break;
528 case 1:
529 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setY(-p->momentum().y()); p->set_momentum(temp);}
530 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setY(-v->position().y()); v->set_position(temp);}
531 break;
532 case 2:
533 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setZ(-p->momentum().z()); p->set_momentum(temp);}
534 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setZ(-v->position().z()); v->set_position(temp);}
535 break;
536 case 3:
537 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setT(-p->momentum().e()); p->set_momentum(temp);}
538 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setT(-v->position().t()); v->set_position(temp);}
539 break;
540 default:
541 return false;
542 }
543
544 return true;
545}
546
547bool GenEvent::boost(const FourVector& delta)
548{
549 double deltalength2 = delta.length2();
550 if (deltalength2 > 1.0)
551 {
552 HEPMC3_WARNING_LEVEL(400,"GenEvent::boost: wrong large boost vector. Will leave event as is.")
553 return false;
554 }
555 if (std::abs(deltalength2-1.0) < std::numeric_limits<double>::epsilon())
556 {
557 HEPMC3_WARNING_LEVEL(400,"GenEvent::boost: too large gamma. Will leave event as is.")
558 return false;
559 }
560 if (std::abs(deltalength2) < std::numeric_limits<double>::epsilon())
561 {
562 HEPMC3_WARNING_LEVEL(400,"GenEvent::boost: wrong small boost vector. Will leave event as is.")
563 return true;
564 }
565 long double deltaX = delta.x();
566 long double deltaY = delta.y();
567 long double deltaZ = delta.z();
568 long double deltalength = std::sqrt(deltalength2);
569 long double gamma = 1.0/std::sqrt(1.0-deltalength2);
570
571 for ( auto& p: m_particles)
572 {
573 const FourVector& mom = p->momentum();
574
575 long double tempX = mom.x();
576 long double tempY = mom.y();
577 long double tempZ = mom.z();
578 long double tempE = mom.e();
579 long double nr = (deltaX*tempX+deltaY*tempY+deltaZ*tempZ)/deltalength;
580 long double gfac = (gamma-1)*nr/deltalength-tempE*gamma;
581 tempX+=(deltaX*gfac);
582 tempY+=(deltaY*gfac);
583 tempZ+=(deltaZ*gfac);
584 tempE = gamma*(tempE-deltalength*nr);
585 FourVector temp(tempX, tempY, tempZ, tempE);
586 p->set_momentum(temp);
587 }
588
589 return true;
590}
591
593 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
594 m_event_number = 0;
595 m_rootvertex = std::make_shared<GenVertex>();
596 m_weights.clear();
597 m_attributes.clear();
598 m_particles.clear();
599 m_vertices.clear();
600}
601
602void GenEvent::remove_attribute(const std::string &name, const int& id) {
603 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
604 auto i1 = m_attributes.find(name);
605 if ( i1 == m_attributes.end() ) return;
606
607 auto i2 = i1->second.find(id);
608 if ( i2 == i1->second.end() ) return;
609
610 i1->second.erase(i2);
611}
612
613std::vector<std::string> GenEvent::attribute_names(const int& id) const {
614 std::vector<std::string> results;
615
616 for (const att_key_t& vt1: m_attributes) {
617 if ( vt1.second.count(id) == 1 ) {
618 results.emplace_back(vt1.first);
619 }
620 }
621
622 return results;
623}
624
626 // Reserve memory for containers
627 data.particles.reserve(this->particles().size());
628 data.vertices.reserve(this->vertices().size());
629 data.links1.reserve(this->particles().size()*2);
630 data.links2.reserve(this->particles().size()*2);
631 data.attribute_id.reserve(m_attributes.size());
632 data.attribute_name.reserve(m_attributes.size());
633 data.attribute_string.reserve(m_attributes.size());
634
635 // Fill event data
636 data.event_number = this->event_number();
637 data.momentum_unit = this->momentum_unit();
638 data.length_unit = this->length_unit();
639 data.event_pos = this->event_pos();
640
641 // Fill containers
642 data.weights = this->weights();
643
644 for (const ConstGenParticlePtr& p: this->particles()) {
645 data.particles.emplace_back(p->data());
646 }
647
648 for (const ConstGenVertexPtr& v: this->vertices()) {
649 data.vertices.emplace_back(v->data());
650 int v_id = v->id();
651
652 for (const ConstGenParticlePtr& p: v->particles_in()) {
653 data.links1.emplace_back(p->id());
654 data.links2.emplace_back(v_id);
655 }
656
657 for (const ConstGenParticlePtr& p: v->particles_out()) {
658 data.links1.emplace_back(v_id);
659 data.links2.emplace_back(p->id());
660 }
661 }
662
663 for (const att_key_t& vt1: this->attributes()) {
664 for (const att_val_t& vt2: vt1.second) {
665 std::string st;
666
667 bool status = vt2.second->to_string(st);
668
669 if ( !status ) {
670 HEPMC3_WARNING_LEVEL(300,"GenEvent::write_data: problem serializing attribute: " << vt1.first)
671 }
672 else {
673 data.attribute_id.emplace_back(vt2.first);
674 data.attribute_name.emplace_back(vt1.first);
675 data.attribute_string.emplace_back(st);
676 }
677 }
678 }
679}
680
681
682void GenEvent::read_data(const GenEventData &data) {
683 this->clear();
684 this->set_event_number(data.event_number);
685 //Note: set_units checks the current unit of event, i.e. applicable only for fully constructed event.
688 this->shift_position_to(data.event_pos);
689
690 // Fill weights
691 this->weights() = data.weights;
692 m_particles.reserve(data.particles.size());
693 m_vertices.reserve(data.vertices.size());
694
695 // Fill particle information
696 for ( const GenParticleData &pd: data.particles ) {
697 m_particles.emplace_back(std::make_shared<GenParticle>(pd));
698 m_particles.back()->m_event = this;
699 m_particles.back()->m_id = m_particles.size();
700 }
701
702 // Fill vertex information
703 for ( const GenVertexData &vd: data.vertices ) {
704 m_vertices.emplace_back(std::make_shared<GenVertex>(vd));
705 m_vertices.back()->m_event = this;
706 m_vertices.back()->m_id = -static_cast<int> (m_vertices.size());
707 }
708
709 // Restore links
710 for (unsigned int i = 0; i < data.links1.size(); ++i) {
711 const int id1 = data.links1[i];
712 const int id2 = data.links2[i];
713 /* @note:
714 The meaningfull combinations for (id1,id2) are:
715 (+-) -- particle has end vertex
716 (-+) -- particle has production vertex
717 */
718 if ((id1 < 0 && id2 <0) || (id1 > 0 && id2 > 0)) {
719 HEPMC3_WARNING_LEVEL(600,"GenEvent::read_data: wrong link: " << id1 << " " << id2);
720 continue;
721 }
722
723 if ( id1 > 0 ) { m_vertices[ (-id2)-1 ]->add_particle_in ( m_particles[ id1-1 ] ); continue; }
724 if ( id1 < 0 ) { m_vertices[ (-id1)-1 ]->add_particle_out( m_particles[ id2-1 ] ); continue; }
725 }
726 for (auto& p: m_particles) if (!p->production_vertex()) m_rootvertex->add_particle_out(p);
727
728 // Read attributes
729 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
730 for (unsigned int i = 0; i < data.attribute_id.size(); ++i) {
731 ///Disallow empty strings
732 const std::string name = data.attribute_name[i];
733 if (name.length() == 0) continue;
734 const int id = data.attribute_id[i];
735 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
736 auto att = std::make_shared<StringAttribute>(data.attribute_string[i]);
737 att->m_event = this;
738 if ( id > 0 && id <= static_cast<int>(m_particles.size()) ) {
739 att->m_particle = m_particles[id - 1];
740 }
741 if ( id < 0 && -id <= static_cast<int>(m_vertices.size()) ) {
742 att->m_vertex = m_vertices[-id - 1];
743 }
744 m_attributes[name][id] = att;
745 }
746}
747
748
749//
750// Deprecated functions
751//
752
753void GenEvent::set_beam_particles(GenParticlePtr p1, GenParticlePtr p2) {
754 m_rootvertex->add_particle_out(p1);
755 m_rootvertex->add_particle_out(p2);
756}
757
758void GenEvent::add_beam_particle(GenParticlePtr p1) {
759 if (!p1)
760 {
761 HEPMC3_WARNING_LEVEL(700,"Attempting to add an empty particle as beam particle. Ignored.")
762 return;
763 }
764 if (p1->in_event() && p1->parent_event() != this)
765 {
766 HEPMC3_WARNING_LEVEL(700,"Attempting to add particle from another event. Ignored.")
767 return;
768 }
769 if (p1->production_vertex()) p1->production_vertex()->remove_particle_out(p1);
770 //Particle w/o production vertex is added to root vertex.
771 add_particle(p1);
772 p1->set_status(4);
773}
774
775
776std::string GenEvent::attribute_as_string(const std::string &name, const int& id) const {
777 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
778 auto i1 = m_attributes.find(name);
779 if ( i1 == m_attributes.end() ) {
780 if ( id == 0 && run_info() ) {
781 return run_info()->attribute_as_string(name);
782 }
783 return {};
784 }
785
786 auto i2 = i1->second.find(id);
787 if (i2 == i1->second.end() ) return {};
788
789 if ( !i2->second ) return {};
790
791 std::string ret;
792 i2->second->to_string(ret);
793
794 return ret;
795}
796
797void GenEvent::add_attribute(const std::string &name, const std::shared_ptr<Attribute> &att, const int& id ) {
798 ///Disallow empty strings
799 if (name.length() == 0) return;
800 if (!att) return;
801 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
802 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
803 m_attributes[name][id] = att;
804 att->m_event = this;
805 if ( id > 0 && id <= static_cast<int>(particles().size()) ) {
806 att->m_particle = particles()[id - 1];
807 }
808 if ( id < 0 && -id <= static_cast<int>(vertices().size()) ) {
809 att->m_vertex = vertices()[-id - 1];
810 }
811}
812
813
814void GenEvent::add_attributes(const std::vector<std::string> &names, const std::vector<std::shared_ptr<Attribute> > &atts, const std::vector<int>& ids) {
815 size_t N = names.size();
816 if ( N == 0 ) return;
817 if (N != atts.size()) return;
818 if (N != ids.size()) return;
819
820 std::vector<std::string> unames = names;
821 vector<std::string>::iterator ip;
822 ip = std::unique(unames.begin(), unames.end());
823 unames.resize(std::distance(unames.begin(), ip));
824 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
825 for (const auto& name: unames) {
826 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
827 }
828 const int particles_size = static_cast<int>(m_particles.size());
829 const int vertices_size = static_cast<int>(m_vertices.size());
830 for (size_t i = 0; i < N; i++) {
831 ///Disallow empty strings
832 if (names.at(i).length() == 0) continue;
833 if (!atts[i]) continue;
834 m_attributes[names.at(i)][ids.at(i)] = atts[i];
835 atts[i]->m_event = this;
836 if ( ids.at(i) > 0 && ids.at(i) <= particles_size )
837 { atts[i]->m_particle = m_particles[ids.at(i) - 1]; }
838 else {
839 if ( ids.at(i) < 0 && -ids.at(i) <= vertices_size ) {
840 atts[i]->m_vertex = m_vertices[-ids.at(i) - 1];
841 }
842 }
843 }
844}
845
846void GenEvent::add_attributes(const std::string& name, const std::vector<std::shared_ptr<Attribute> > &atts, const std::vector<int>& ids) {
847 if (name.length() == 0) return;
848 size_t N = ids.size();
849 if(!N) return;
850 if ( N != atts.size()) return;
851
852 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
853 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
854 auto& tmap = m_attributes[name];
855 const int particles_size = static_cast<int>(m_particles.size());
856 const int vertices_size = static_cast<int>(m_vertices.size());
857 for (size_t i = 0; i < N; i++) {
858 ///Disallow empty strings
859 if (!atts[i]) continue;
860 tmap[ids.at(i)] = atts[i];
861 atts[i]->m_event = this;
862 if ( ids.at(i) > 0 && ids.at(i) <= particles_size )
863 { atts[i]->m_particle = m_particles[ids.at(i) - 1]; }
864 else {
865 if ( ids.at(i) < 0 && -ids.at(i) <= vertices_size ) {
866 atts[i]->m_vertex = m_vertices[-ids.at(i) - 1];
867 }
868 }
869 }
870}
871void GenEvent::add_attributes(const std::string& name, const std::vector<std::pair<int, std::shared_ptr<Attribute> > > &atts) {
872 if (name.length() == 0) return;
873 if (atts.empty()) return;
874 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
875 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
876 auto& tmap = m_attributes[name];
877 const int particles_size = static_cast<int>(m_particles.size());
878 const int vertices_size = static_cast<int>(m_vertices.size());
879 for (const auto& att: atts) {
880 ///Disallow empty strings
881 if (!att.second) continue;
882 tmap.insert(att);
883 att.second->m_event = this;
884 if ( att.first > 0 && att.first <= particles_size )
885 { att.second->m_particle = m_particles[att.first - 1]; }
886 else {
887 if ( att.first < 0 && -att.first <= vertices_size ) {
888 att.second->m_vertex = m_vertices[-att.first - 1];
889 }
890 }
891 }
892}
893
894} // namespace HepMC3
#define HEPMC3_WARNING_LEVEL(LEVEL, MESSAGE)
Macro for printing HEPMC3_HEPMC3_WARNING messages.
Definition Errors.h:34
#define HEPMC3_DEBUG_CODE_BLOCK(x)
Macro for storing code useful for debugging.
Definition Errors.h:43
#define HEPMC3_DEBUG(LEVEL, MESSAGE)
Macro for printing debug messages with appropriate debug level.
Definition Errors.h:41
Definition of struct GenEventData.
Definition of class GenEvent.
Definition of class GenParticle.
Definition of class GenVertex.
Generic 4-vector.
Definition FourVector.h:36
double e() const
Energy component of momentum.
Definition FourVector.h:135
void setT(double tt)
Definition FourVector.h:110
double t() const
Time component of position/displacement.
Definition FourVector.h:106
bool is_zero() const
Check if the length of this vertex is zero.
Definition FourVector.h:206
void setY(double yy)
Definition FourVector.h:96
void setX(double xx)
Definition FourVector.h:89
double x() const
x-component of position/displacement
Definition FourVector.h:85
double length2() const
Squared magnitude of (x, y, z) 3-vector.
Definition FourVector.h:148
double y() const
y-component of position/displacement
Definition FourVector.h:92
double z() const
z-component of position/displacement
Definition FourVector.h:99
void setZ(double zz)
Definition FourVector.h:103
GenEvent(Units::MomentumUnit mu=Units::GEV, Units::LengthUnit lu=Units::MM)
Event constructor without a run.
Definition GenEvent.cc:22
bool rotate(const FourVector &delta)
Rotate event using x,y,z components of delta as rotation angles.
Definition GenEvent.cc:449
std::shared_ptr< T > attribute(const std::string &name, const int &id=0) const
Get attribute of type T.
Definition GenEvent.h:420
std::recursive_mutex m_lock_attributes
Mutex lock for the m_attibutes map.
Definition GenEvent.h:406
void add_vertex(GenVertexPtr v)
Add vertex.
Definition GenEvent.cc:99
void shift_position_to(const FourVector &newpos)
Shift position of all vertices in the event to op.
Definition GenEvent.h:211
int vertices_size() const
Vertices size, HepMC2 compatibility.
Definition GenEvent.h:95
int event_number() const
Get event number.
Definition GenEvent.h:155
std::vector< std::string > attribute_names(const int &id=0) const
Get list of attribute names.
Definition GenEvent.cc:613
void write_data(GenEventData &data) const
Fill GenEventData object.
Definition GenEvent.cc:625
std::shared_ptr< GenRunInfo > run_info() const
Get a pointer to the the GenRunInfo object.
Definition GenEvent.h:144
void remove_particles(std::vector< GenParticlePtr > v)
Remove a set of particles.
Definition GenEvent.cc:182
void add_particle(GenParticlePtr p)
Add particle.
Definition GenEvent.cc:48
void set_units(Units::MomentumUnit new_momentum_unit, Units::LengthUnit new_length_unit)
Change event units Converts event from current units to new ones.
Definition GenEvent.cc:397
std::vector< double > m_weights
Event weights.
Definition GenEvent.h:381
std::map< int, std::shared_ptr< Attribute > >::value_type att_val_t
Attribute map value type.
Definition GenEvent.h:403
std::map< std::string, std::map< int, std::shared_ptr< Attribute > > >::value_type att_key_t
Attribute map key type.
Definition GenEvent.h:400
void shift_position_by(const FourVector &delta)
Shift position of all vertices in the event by delta.
Definition GenEvent.cc:438
void remove_vertex(GenVertexPtr v)
Remove vertex from the event.
Definition GenEvent.cc:190
void reserve(const size_t &parts, const size_t &verts=0)
Reserve memory for particles and vertices.
Definition GenEvent.cc:391
void set_event_number(const int &num)
Set event number.
Definition GenEvent.h:157
bool boost(const FourVector &delta)
Boost event using x,y,z components of delta as velocity fractions.
Definition GenEvent.cc:547
std::vector< ConstGenParticlePtr > beams() const
Vector of beam particles.
Definition GenEvent.cc:429
int m_event_number
Event number.
Definition GenEvent.h:378
const std::vector< ConstGenVertexPtr > & vertices() const
Get list of vertices (const)
Definition GenEvent.cc:43
~GenEvent()
Destructor.
Definition GenEvent.cc:76
const Units::MomentumUnit & momentum_unit() const
Get momentum unit.
Definition GenEvent.h:160
const Units::LengthUnit & length_unit() const
Get length unit.
Definition GenEvent.h:162
bool reflect(const int axis)
Change sign of axis.
Definition GenEvent.cc:515
const FourVector & event_pos() const
Vertex representing the overall event position.
Definition GenEvent.cc:418
std::map< std::string, std::map< int, std::shared_ptr< Attribute > > > attributes() const
Get a copy of the list of attributes.
Definition GenEvent.h:270
void add_attribute(const std::string &name, const std::shared_ptr< Attribute > &att, const int &id=0)
Definition GenEvent.cc:797
void read_data(const GenEventData &data)
Fill GenEvent based on GenEventData.
std::map< std::string, std::map< int, std::shared_ptr< Attribute > > > m_attributes
Map of event, particle and vertex attributes.
Definition GenEvent.h:397
Units::MomentumUnit m_momentum_unit
Momentum unit.
Definition GenEvent.h:384
void remove_attribute(const std::string &name, const int &id=0)
Remove attribute.
Definition GenEvent.cc:602
void remove_particle(GenParticlePtr p)
Remove particle from the event.
Definition GenEvent.cc:119
std::vector< GenVertexPtr > m_vertices
List of vertices.
Definition GenEvent.h:375
GenVertexPtr m_rootvertex
The root vertex is stored outside the normal vertices list to block user access to it.
Definition GenEvent.h:389
std::string attribute_as_string(const std::string &name, const int &id=0) const
Get attribute of any type as string.
Definition GenEvent.cc:776
const std::vector< double > & weights() const
Get event weight values as a vector.
Definition GenEvent.h:105
void clear()
Remove contents of this event.
Definition GenEvent.cc:592
int particles_size() const
Particles size, HepMC2 compatibility.
Definition GenEvent.h:91
Units::LengthUnit m_length_unit
Length unit.
Definition GenEvent.h:386
std::shared_ptr< GenRunInfo > m_run_info
Global run information.
Definition GenEvent.h:392
std::vector< GenParticlePtr > m_particles
List of particles.
Definition GenEvent.h:373
void add_beam_particle(GenParticlePtr p1)
Add particle to root vertex.
Definition GenEvent.cc:758
void add_attributes(const std::vector< std::string > &names, const std::vector< std::shared_ptr< Attribute > > &atts, const std::vector< int > &ids)
Add multiple attributes to event.
Definition GenEvent.cc:814
void set_beam_particles(GenParticlePtr p1, GenParticlePtr p2)
Set incoming beam particles.
Definition GenEvent.cc:753
const std::vector< ConstGenParticlePtr > & particles() const
Get list of particles (const)
Definition GenEvent.cc:39
void add_tree(const std::vector< GenParticlePtr > &parts)
Add whole tree in topological order.
Definition GenEvent.cc:268
GenEvent & operator=(const GenEvent &)
Copy Assignment operator.
Definition GenEvent.cc:84
Stores vertex-related information.
Definition GenVertex.h:29
static void convert(T &m, MomentumUnit from, MomentumUnit to)
Convert FourVector to different momentum unit.
Definition Units.h:81
LengthUnit
Position units.
Definition Units.h:32
MomentumUnit
Momentum units.
Definition Units.h:29
HepMC3 main namespace.
Stores serializable event information.
std::vector< GenVertexData > vertices
Vertices.
std::vector< int > links2
Second id of the vertex links.
int event_number
Event number.
std::vector< std::string > attribute_string
Attribute serialized as string.
std::vector< GenParticleData > particles
Particles.
std::vector< int > links1
First id of the vertex links.
std::vector< std::string > attribute_name
Attribute name.
Units::LengthUnit length_unit
Length unit.
std::vector< int > attribute_id
Attribute owner id.
FourVector event_pos
Event position.
std::vector< double > weights
Weights.
Units::MomentumUnit momentum_unit
Momentum unit.
Stores serializable particle information.