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