MARLEY (Model of Argon Reaction Low Energy Yields) v2.0.0
A Monte Carlo event generator for tens-of-MeV neutrino interactions
Loading...
Searching...
No Matches
marley_hepmc3.cc
1// src/marley_hepmc3.cc
2//
3// Amalgamated built-in HepMC3 implementation for MARLEY.
4//
5// This translation unit is compiled when no system HepMC3 installation is
6// available (MARLEY_FOUND_HEPMC3 is not defined by the build system). When
7// a system installation is used, the preprocessor guard below renders this
8// file a no-op; it is still compiled and linked into libHepMC3 but
9// contributes no symbols.
10//
11// Provenance
12// ----------
13// Derived from the HepMC3 project: https://gitlab.cern.ch/hepmc/HepMC3
14// Authors: the HepMC3 collaboration.
15// Redistributed under the GNU Lesser General Public License, version 2.1
16// or later. Copyright (C) 2014-2023 the HepMC Collaboration.
17//
18// Only the subset of source files required for MARLEY's output support is
19// included (in compilation order):
20// hepmc3/Setup.cc
21// hepmc3/GenRunInfo.cc
22// hepmc3/GenParticle.cc
23// hepmc3/GenVertex.cc
24// hepmc3/GenEvent.cc
25// hepmc3/Print.cc
26// hepmc3/WriterAscii.cc
27// hepmc3/ReaderAscii.cc
28// The bundled header files live in include/builtin/HepMC3/ (see README there).
29
30#ifndef MARLEY_FOUND_HEPMC3
31
32// ============================================================
33// hepmc3/Setup.cc
34// Copyright (C) 2014-2023 The HepMC collaboration
35// ============================================================
36// -*- C++ -*-
37//
38// This file is part of HepMC
39// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
40//
46#include "HepMC3/Setup.h"
47
48namespace HepMC3 {
49
50const unsigned int Setup::DEFAULT_DOUBLE_ALMOST_EQUAL_MAXULPS = 10;
51const double Setup::DOUBLE_EPSILON = 10e-20;
52bool Setup::print_errors() { return m_is_printing_errors; }
53void Setup::set_print_errors(const bool flag) { m_is_printing_errors = flag; }
54bool Setup::print_warnings() { return m_is_printing_warnings; }
55void Setup::set_print_warnings(const bool flag) { m_is_printing_warnings = flag; }
56int Setup::debug_level() { return m_debug_level; }
57void Setup::set_debug_level(const int level) { m_debug_level = level; }
58int Setup::errors_level() { return m_errors_level; }
59void Setup::set_errors_level(const int level) { m_errors_level = level; }
60int Setup::warnings_level() { return m_warnings_level; }
61void Setup::set_warnings_level(const int level) { m_warnings_level = level;}
62bool Setup::m_is_printing_errors = true;
63bool Setup::m_is_printing_warnings = true;
64int Setup::m_debug_level = 5;
65int Setup::m_errors_level = 1000;
66int Setup::m_warnings_level = 750;
67
68} // namespace HepMC3
69
70// ============================================================
71// hepmc3/GenRunInfo.cc
72// Copyright (C) 2014-2023 The HepMC collaboration
73// ============================================================
74// -*- C++ -*-
75//
76// This file is part of HepMC
77// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
78//
84#include <sstream>
85
86#include "HepMC3/Data/GenRunInfoData.h"
87#include "HepMC3/GenRunInfo.h"
88
89
90namespace HepMC3 {
91
92
93void GenRunInfo::set_weight_names(const std::vector<std::string> & names) {
94 m_weight_indices.clear();
95 m_weight_names = names;
96 for ( int i = 0, N = names.size(); i < N; ++i ) {
97 std::string name = names[i];
98 if ( name.empty() ) {
99 std::ostringstream oss;
100 oss << i;
101 name = oss.str();
102 m_weight_names[i] = name;
103 }
104 if ( has_weight(name) ) {
105 throw std::logic_error("GenRunInfo::set_weight_names: "
106 "Duplicate weight name '" + name +
107 "' found.");
108 }
109 m_weight_indices[name] = i;
110 }
111}
112
113std::string GenRunInfo::attribute_as_string(const std::string &name) const {
114 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
115 auto i = m_attributes.find(name);
116 if ( i == m_attributes.end() ) return {};
117
118 if ( !i->second ) return {};
119
120 std::string ret;
121 i->second->to_string(ret);
122
123 return ret;
124}
125
127 // Weight names
128 data.weight_names = this->weight_names();
129
130 // Attributes
131 using att_val_t = std::map<std::string, std::shared_ptr<Attribute>>::value_type;
132
133 for (const att_val_t& vt: m_attributes) {
134 std::string att;
135 vt.second->to_string(att);
136
137 data.attribute_name. emplace_back(vt.first);
138 data.attribute_string.emplace_back(att);
139 }
140
141 // Tools
142 for ( const ToolInfo &tool: this->tools() ) {
143 data.tool_name. emplace_back(tool.name);
144 data.tool_version. emplace_back(tool.version);
145 data.tool_description.emplace_back(tool.description);
146 }
147}
148
149
150std::vector<std::string> GenRunInfo::attribute_names() const {
151 std::vector<std::string> results;
152 results.reserve(m_attributes.size());
153 for (const auto& vt1: m_attributes) {
154 results.emplace_back(vt1.first);
155 }
156 return results;
157}
158
160 // Weight names
162
163 // Attributes
164 for (unsigned int i = 0; i < data.attribute_name.size(); ++i) {
166 std::make_shared<StringAttribute>(data.attribute_string[i]));
167 }
168
169 // Tools
170 for (unsigned int i = 0; i < data.tool_name.size(); ++i) {
171 ToolInfo ti;
172 ti.name = data.tool_name[i];
173 ti.version = data.tool_version[i];
174 ti.description = data.tool_description[i];
175
176 this->tools().emplace_back(ti);
177 }
178}
179
181{
182 if (this != &r)
183 {
184 std::lock(m_lock_attributes, r.m_lock_attributes);
185 std::lock_guard<std::recursive_mutex> lhs_lk(m_lock_attributes, std::adopt_lock);
186 std::lock_guard<std::recursive_mutex> rhs_lk(r.m_lock_attributes, std::adopt_lock);
187 GenRunInfoData tdata;
188 r.write_data(tdata);
189 read_data(tdata);
190 }
191}
193{
194 if (this != &r)
195 {
196 std::lock(m_lock_attributes, r.m_lock_attributes);
197 std::lock_guard<std::recursive_mutex> lhs_lk(m_lock_attributes, std::adopt_lock);
198 std::lock_guard<std::recursive_mutex> rhs_lk(r.m_lock_attributes, std::adopt_lock);
199 GenRunInfoData tdata;
200 r.write_data(tdata);
201 read_data(tdata);
202 }
203 return *this;
204}
205
206} // namespace HepMC3
207
208// ============================================================
209// hepmc3/GenParticle.cc
210// Copyright (C) 2014-2023 The HepMC collaboration
211// ============================================================
212// -*- C++ -*-
213//
214// This file is part of HepMC
215// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
216//
222#include "HepMC3/Attribute.h"
223#include "HepMC3/GenEvent.h"
224#include "HepMC3/GenParticle.h"
225#include "HepMC3/GenVertex.h"
226#include "HepMC3/Setup.h"
227
228
229namespace HepMC3 {
230
231GenParticle::GenParticle(const FourVector &mom, int pidin, int stat):
232 m_event(nullptr),
233 m_id(0) {
234 m_data.pid = pidin;
235 m_data.momentum = mom;
236 m_data.status = stat;
237 m_data.is_mass_set = false;
238 m_data.mass = 0.0;
239}
240
242 m_event(nullptr),
243 m_id(0),
244 m_data(dat) {
245}
246
248 return m_data.is_mass_set ? m_data.mass : m_data.momentum.m();
249}
250
251void GenParticle::set_pid(int pidin) {
252 m_data.pid = pidin;
253}
254
256 m_data.status = stat;
257}
258
260 m_data.momentum = mom;
261}
262
264 m_data.mass = m;
265 m_data.is_mass_set = true;
266}
267
269 m_data.mass = 0.;
270 m_data.is_mass_set = false;
271}
272
274 return m_production_vertex.lock();
275}
276
277ConstGenVertexPtr GenParticle::production_vertex() const {
278 return std::const_pointer_cast<const GenVertex>(m_production_vertex.lock());
279}
280
282 return m_end_vertex.lock();
283}
284
285ConstGenVertexPtr GenParticle::end_vertex() const {
286 return std::const_pointer_cast<const GenVertex>(m_end_vertex.lock());
287}
288
289std::vector<GenParticlePtr> GenParticle::parents() {
290 return (m_production_vertex.expired())? std::vector<GenParticlePtr>() : production_vertex()->particles_in();
291}
292
293std::vector<ConstGenParticlePtr> GenParticle::parents() const {
294 return (m_production_vertex.expired()) ? std::vector<ConstGenParticlePtr>() : production_vertex()->particles_in();
295}
296
297std::vector<GenParticlePtr> GenParticle::children() {
298 return (m_end_vertex.expired())? std::vector<GenParticlePtr>() : end_vertex()->particles_out();
299}
300
301std::vector<ConstGenParticlePtr> GenParticle::children() const {
302 return (m_end_vertex.expired()) ? std::vector<ConstGenParticlePtr>() : end_vertex()->particles_out();
303}
304
305bool GenParticle::add_attribute(const std::string& name, std::shared_ptr<Attribute> att) {
306 if ( !parent_event() ) return false;
307 parent_event()->add_attribute(name, att, id());
308 return true;
309}
310
311std::vector<std::string> GenParticle::attribute_names() const {
312 if ( parent_event() ) return parent_event()->attribute_names(id());
313 return {};
314}
315
316void GenParticle::remove_attribute(const std::string& name) {
317 if ( parent_event() ) parent_event()->remove_attribute(name, id());
318}
319
320std::string GenParticle::attribute_as_string(const std::string& name) const {
321 return parent_event() ? parent_event()->attribute_as_string(name, id()) : std::string();
322}
323
324} // namespace HepMC3
325
326// ============================================================
327// hepmc3/GenVertex.cc
328// Copyright (C) 2014-2023 The HepMC collaboration
329// ============================================================
330// -*- C++ -*-
331//
332// This file is part of HepMC
333// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
334//
340#include <algorithm> // std::remove
341
342#include "HepMC3/Attribute.h"
343#include "HepMC3/GenEvent.h"
344#include "HepMC3/GenParticle.h"
345#include "HepMC3/GenVertex.h"
346#include "HepMC3/Setup.h"
347
348namespace HepMC3 {
349
350
352 m_event(nullptr),
353 m_id(0) {
354 m_data.status = 0;
355 m_data.position = pos;
356}
357
359 m_event(nullptr),
360 m_id(0),
361 m_data(dat) {
362}
363
364
365void GenVertex::add_particle_in(GenParticlePtr p) {
366 if (!p) return;
367
368 // Avoid duplicates
369 if (std::find(particles_in().begin(), particles_in().end(), p) != particles_in().end()) return;
370
371 m_particles_in.emplace_back(p);
372
373 if ( p->end_vertex() ) p->end_vertex()->remove_particle_in(p);
374
375 p->m_end_vertex = shared_from_this();
376
377 if (m_event) m_event->add_particle(p);
378}
379
380
381void GenVertex::add_particle_out(GenParticlePtr p) {
382 if (!p) return;
383
384 // Avoid duplicates
385 if (std::find(particles_out().begin(), particles_out().end(), p) != particles_out().end()) return;
386
387 m_particles_out.emplace_back(p);
388
389 if ( p->production_vertex() ) p->production_vertex()->remove_particle_out(p);
390
391 p->m_production_vertex = shared_from_this();
392
393 if (m_event) m_event->add_particle(p);
394}
395
396void GenVertex::remove_particle_in(GenParticlePtr p) {
397 if (!p) return;
398 if (std::find(m_particles_in.begin(), m_particles_in.end(), p) == m_particles_in.end()) return;
399 p->m_end_vertex.reset();
400 m_particles_in.erase(std::remove(m_particles_in.begin(), m_particles_in.end(), p), m_particles_in.end());
401}
402
403
404void GenVertex::remove_particle_out(GenParticlePtr p) {
405 if (!p) return;
406 if (std::find(m_particles_out.begin(), m_particles_out.end(), p) == m_particles_out.end()) return;
407 p->m_production_vertex.reset();
408 m_particles_out.erase(std::remove(m_particles_out.begin(), m_particles_out.end(), p), m_particles_out.end());
409}
410
411const std::vector<ConstGenParticlePtr>& GenVertex::particles_in()const {
412 return *(reinterpret_cast<const std::vector<ConstGenParticlePtr>*>(&m_particles_in));
413}
414
415const std::vector<ConstGenParticlePtr>& GenVertex::particles_out()const {
416 return *(reinterpret_cast<const std::vector<ConstGenParticlePtr>*>(&m_particles_out));
417}
418
420 if ( has_set_position() ) return m_data.position;
421
422 // No position information - look at event and/or search ancestors
423 if ( parent_event() )
424 {
425 std::shared_ptr<IntAttribute> cycles = parent_event()->attribute<IntAttribute>("cycles");
426 //This could be a recussive call. Try to prevent it.
427 if (!cycles || cycles->value() == 0)
428 {
429 for (const auto& p: m_particles_in) {
430 ConstGenVertexPtr v = p->production_vertex();
431 if (v) return v->position();
432 }
433 }
434 return parent_event()->event_pos();
435 }
437}
438
440 m_data.position = new_pos;
441}
442
443bool GenVertex::add_attribute(const std::string& name, std::shared_ptr<Attribute> att) {
444 if ( !parent_event() ) return false;
445 parent_event()->add_attribute(name, att, id());
446 return true;
447}
448
449void GenVertex::remove_attribute(const std::string& name) {
450 if ( parent_event() ) parent_event()->remove_attribute(name, id());
451}
452
453std::string GenVertex::attribute_as_string(const std::string& name) const {
454 return parent_event() ? parent_event()->attribute_as_string(name, id()) : std::string();
455}
456
457std::vector<std::string> GenVertex::attribute_names() const {
458 if ( parent_event() ) return parent_event()->attribute_names(id());
459
460 return {};
461}
462
463} // namespace HepMC3
464
465// ============================================================
466// hepmc3/GenEvent.cc
467// Copyright (C) 2014-2023 The HepMC collaboration
468// ============================================================
469// -*- C++ -*-
470//
471// This file is part of HepMC
472// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
473//
479#include <algorithm> // sort
480#include <deque>
481
482#include "HepMC3/Data/GenEventData.h"
483#include "HepMC3/GenEvent.h"
484#include "HepMC3/GenParticle.h"
485#include "HepMC3/GenVertex.h"
486
487
488namespace HepMC3 {
489
492 : m_momentum_unit(mu), m_length_unit(lu), //m_weights(std::vector<double>(1, 1.0)),//Prevent from different number of weights and names
493 m_rootvertex(std::make_shared<GenVertex>()) {}
494
495
496GenEvent::GenEvent(std::shared_ptr<GenRunInfo> run,
499 : m_momentum_unit(mu), m_length_unit(lu), //m_weights(std::vector<double>(1, 1.0)),//Prevent from different number of weights and names
500 m_rootvertex(std::make_shared<GenVertex>()),
501 m_run_info(run) {
502 if ( run && !run->weight_names().empty() ) {
503 m_weights = std::vector<double>(run->weight_names().size(), 1.0);
504 }
505}
506
507const std::vector<ConstGenParticlePtr>& GenEvent::particles() const {
508 return *(reinterpret_cast<const std::vector<ConstGenParticlePtr>*>(&m_particles));
509}
510
511const std::vector<ConstGenVertexPtr>& GenEvent::vertices() const {
512 return *(reinterpret_cast<const std::vector<ConstGenVertexPtr>*>(&m_vertices));
513}
514
515
516void GenEvent::add_particle(GenParticlePtr p) {
517 if ( !p || p->in_event() ) return;
518
519 m_particles.emplace_back(p);
520
521 p->m_event = this;
522 p->m_id = particles().size();
523
524 // Particles without production vertex are added to the root vertex
525 if ( !p->production_vertex() ) {
526 m_rootvertex->add_particle_out(p);
527 }
528}
529
530
532 if (this != &e)
533 {
534 std::lock(m_lock_attributes, e.m_lock_attributes);
535 std::lock_guard<std::recursive_mutex> lhs_lk(m_lock_attributes, std::adopt_lock);
536 std::lock_guard<std::recursive_mutex> rhs_lk(e.m_lock_attributes, std::adopt_lock);
537 GenEventData tdata;
538 e.write_data(tdata);
539 read_data(tdata);
540 m_run_info = e.m_run_info;
541 }
542}
543
545 for ( auto attm = m_attributes.begin(); attm != m_attributes.end(); ++attm) {
546 for ( auto att = attm->second.begin(); att != attm->second.end(); ++att) { if (att->second) att->second->m_event = nullptr;}
547 }
548 for ( auto v = m_vertices.begin(); v != m_vertices.end(); ++v ) if (*v) if ((*v)->m_event == this) (*v)->m_event = nullptr;
549 for ( auto p = m_particles.begin(); p != m_particles.end(); ++p ) if (*p) if ((*p)->m_event == this) (*p)->m_event = nullptr;
550}
551
553 if (this != &e)
554 {
555 std::lock(m_lock_attributes, e.m_lock_attributes);
556 std::lock_guard<std::recursive_mutex> lhs_lk(m_lock_attributes, std::adopt_lock);
557 std::lock_guard<std::recursive_mutex> rhs_lk(e.m_lock_attributes, std::adopt_lock);
558 GenEventData tdata;
559 e.write_data(tdata);
560 read_data(tdata);
561 m_run_info = e.m_run_info;
562 }
563 return *this;
564}
565
566
567void GenEvent::add_vertex(GenVertexPtr v) {
568 if ( !v|| v->in_event() ) return;
569 m_vertices.emplace_back(v);
570
571 v->m_event = this;
572 v->m_id = -(int)vertices().size();
573
574 // Add all incoming and outgoing particles and restore their production/end vertices
575 for (const auto& p: v->particles_in()) {
576 if (!p->in_event()) add_particle(p);
577 p->m_end_vertex = v->shared_from_this();
578 }
579
580 for (const auto& p: v->particles_out()) {
581 if (!p->in_event()) add_particle(p);
582 p->m_production_vertex = v;
583 }
584}
585
586
587void GenEvent::remove_particle(GenParticlePtr p) {
588 if ( !p || p->parent_event() != this ) return;
589
590 HEPMC3_DEBUG(30, "GenEvent::remove_particle - called with particle: " << p->id());
591 GenVertexPtr end_vtx = p->end_vertex();
592 if ( end_vtx ) {
593 end_vtx->remove_particle_in(p);
594
595 // If that was the only incoming particle, remove vertex from the event
596 if ( end_vtx->particles_in().empty() ) remove_vertex(end_vtx);
597 }
598
599 GenVertexPtr prod_vtx = p->production_vertex();
600 if ( prod_vtx ) {
601 prod_vtx->remove_particle_out(p);
602
603 // If that was the only outgoing particle, remove vertex from the event
604 if ( prod_vtx->particles_out().empty() ) remove_vertex(prod_vtx);
605 }
606
607 HEPMC3_DEBUG(30, "GenEvent::remove_particle - erasing particle: " << p->id())
608
609 int idx = p->id();
610 auto it = m_particles.erase(m_particles.begin() + idx-1);
611
612 // Remove attributes of this particle
613 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
614 for (att_key_t& vt1: m_attributes) {
615 auto vt2 = vt1.second.find(idx);
616 if (vt2 == vt1.second.end()) continue;
617 vt1.second.erase(vt2);
618 }
619
620 //
621 // Reassign id of attributes with id above this one
622 //
623 std::vector< std::pair< int, std::shared_ptr<Attribute> > > changed_attributes;
624
625 for (att_key_t& vt1: m_attributes) {
626 changed_attributes.clear();
627
628 for (auto vt2 = vt1.second.begin(); vt2 != vt1.second.end(); ++vt2) {
629 if ( (*vt2).first > p->id() ) {
630 changed_attributes.emplace_back(*vt2);
631 }
632 }
633
634 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; });
635 for ( const auto& val: changed_attributes ) {
636 vt1.second.erase(val.first);
637 vt1.second[val.first-1] = val.second;
638 }
639 }
640 // Reassign id of particles with id above this one
641 for (; it != m_particles.end(); ++it) {
642 --((*it)->m_id);
643 }
644
645 // Finally - set parent event and id of this particle to 0
646 p->m_event = nullptr;
647 p->m_id = 0;
648}
649
650void GenEvent::remove_particles(std::vector<GenParticlePtr> v) {
651 std::sort(v.begin(), v.end(), [](const GenParticlePtr& p1, const GenParticlePtr& p2) { return p1->id() > p2->id();});
652
653 for (auto p = v.begin(); p != v.end(); ++p) {
654 remove_particle(*p);
655 }
656}
657
658void GenEvent::remove_vertex(GenVertexPtr v) {
659 if ( !v || v->parent_event() != this ) return;
660
661 HEPMC3_DEBUG(30, "GenEvent::remove_vertex - called with vertex: " << v->id());
662 std::shared_ptr<GenVertex> null_vtx;
663
664 for (const auto& p: v->particles_in()) {
665 p->m_end_vertex = std::weak_ptr<GenVertex>();
666 }
667
668 for (const auto& p: v->particles_out()) {
669 p->m_production_vertex = std::weak_ptr<GenVertex>();
670
671 // recursive delete rest of the tree
673 }
674
675 // Erase this vertex from vertices list
676 HEPMC3_DEBUG(30, "GenEvent::remove_vertex - erasing vertex: " << v->id())
677
678 int idx = -v->id();
679 auto it = m_vertices.erase(m_vertices.begin() + idx-1);
680 // Remove attributes of this vertex
681 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
682 for (att_key_t& vt1: m_attributes) {
683 auto vt2 = vt1.second.find(-idx);
684 if (vt2 == vt1.second.end()) continue;
685 vt1.second.erase(vt2);
686 }
687
688 //
689 // Reassign id of attributes with id below this one
690 //
691
692 std::vector< std::pair< int, std::shared_ptr<Attribute> > > changed_attributes;
693
694 for ( att_key_t& vt1: m_attributes ) {
695 changed_attributes.clear();
696
697 for (auto vt2 = vt1.second.begin(); vt2 != vt1.second.end(); ++vt2) {
698 if ( (*vt2).first < v->id() ) {
699 changed_attributes.emplace_back(*vt2);
700 }
701 }
702
703 std::reverse(changed_attributes.begin(),changed_attributes.end());
704 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; });
705 for ( const auto& val: changed_attributes ) {
706 vt1.second.erase(val.first);
707 vt1.second[val.first+1] = val.second;
708 }
709 }
710
711 // Reassign id of particles with id above this one
712 for (; it != m_vertices.end(); ++it) {
713 ++((*it)->m_id);
714 }
715
716 // Finally - set parent event and id of this vertex to 0
717 v->m_event = nullptr;
718 v->m_id = 0;
719}
720/* This looks dangerously similar to the recusive event traversel that we forbade in the
721 Core library due to wories about generator dependence
722*/
723static bool visit_children(std::map<ConstGenVertexPtr, int> &a, const ConstGenVertexPtr& v)
724{
725 for (const ConstGenParticlePtr& p: v->particles_out()) {
726 if (p->end_vertex())
727 {
728 if (a[p->end_vertex()] != 0) { return true; }
729 a[p->end_vertex()]++;
730 if (visit_children(a, p->end_vertex())) return true;
731 }
732 }
733 return false;
734}
735
736void GenEvent::add_tree(const std::vector<GenParticlePtr> &parts) {
737 m_particles.reserve(m_particles.size() + parts.size());
738 m_vertices.reserve(m_vertices.size() + parts.size());
739 std::shared_ptr<IntAttribute> existing_hc = attribute<IntAttribute>("cycles");
740 bool has_cycles = false;
741 std::map<GenVertexPtr, int> sortingv;
742 std::vector<GenVertexPtr> noinv;
743 if (existing_hc) if (existing_hc->value() != 0) has_cycles = true;
744 if (!existing_hc)
745 {
746 for (const GenParticlePtr& p: parts) {
747 GenVertexPtr v = p->production_vertex();
748 if (v) sortingv[v]=0;
749 if ( !v || v->particles_in().empty()) {
750 GenVertexPtr v2 = p->end_vertex();
751 if (v2) {noinv.emplace_back(v2); sortingv[v2] = 0;}
752 }
753 }
754 for (const GenVertexPtr& v: noinv) {
755 std::map<ConstGenVertexPtr, int> sorting_temp(sortingv.begin(), sortingv.end());
756 has_cycles = (has_cycles || visit_children(sorting_temp, v));
757 }
758 }
759 if (has_cycles) {
760 add_attribute("cycles", std::make_shared<IntAttribute>(1));
761 /* Commented out as improvemnts allow us to do sorting in other way.
762 for ( std::map<GenVertexPtr,int>::iterator vi=sortingv.begin();vi!=sortingv.end();++vi) if ( !vi->first->in_event() ) add_vertex(vi->first);
763 return;
764 */
765 }
766
767 std::deque<GenVertexPtr> sorting;
768
769 // Find all starting vertices (end vertex of particles that have no production vertex)
770 for (const auto& p: parts) {
771 const GenVertexPtr &v = p->production_vertex();
772 if ( !v || v->particles_in().empty() ) {
773 const GenVertexPtr &v2 = p->end_vertex();
774 if (v2) sorting.emplace_back(v2);
775 }
776 }
777
778 HEPMC3_DEBUG_CODE_BLOCK(
779 unsigned int sorting_loop_count = 0;
780 unsigned int max_deque_size = 0;
781 )
782
783 // Add vertices to the event in topological order
784 while ( !sorting.empty() ) {
785 HEPMC3_DEBUG_CODE_BLOCK(
786 if ( sorting.size() > max_deque_size ) max_deque_size = sorting.size();
787 ++sorting_loop_count;
788 )
789
790 GenVertexPtr &v = sorting.front();
791
792 bool added = false;
793
794 // Add all mothers to the front of the list
795 for (const auto& p: v->particles_in() ) {
796 GenVertexPtr v2 = p->production_vertex();
797 if ( v2 && !v2->in_event() && find(sorting.begin(), sorting.end(), v2) == sorting.end() ) {
798 sorting.push_front(v2);
799 added = true;
800 }
801 }
802
803 // If we have added at least one production vertex,
804 // our vertex is not the first one on the list
805 if ( added ) continue;
806
807 // If vertex not yet added
808 if ( !v->in_event() ) {
809 add_vertex(v);
810
811 // Add all end vertices to the end of the list
812 for (const auto& p: v->particles_out()) {
813 GenVertexPtr v2 = p->end_vertex();
814 if ( v2 && !v2->in_event()&& find(sorting.begin(), sorting.end(), v2) == sorting.end() ) {
815 sorting.emplace_back(v2);
816 }
817 }
818 }
819
820 sorting.pop_front();
821 }
822
823 // LL: Make sure root vertex has index zero and is not written out
824 if ( m_rootvertex->id() != 0 ) {
825 const int vx = -1 - m_rootvertex->id();
826 const int rootid = m_rootvertex->id();
827 if ( vx >= 0 && vx < (int) m_vertices.size() && m_vertices[vx] == m_rootvertex ) {
828 auto next = m_vertices.erase(m_vertices.begin() + vx);
829 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
830 for (auto & vt1: m_attributes) {
831 std::vector< std::pair< int, std::shared_ptr<Attribute> > > changed_attributes;
832 for ( const auto& vt2 : vt1.second ) {
833 if ( vt2.first <= rootid ) {
834 changed_attributes.emplace_back(vt2);
835 }
836 }
837 for ( const auto& val : changed_attributes ) {
838 vt1.second.erase(val.first);
839 vt1.second[val.first == rootid? 0: val.first + 1] = val.second;
840 }
841 }
842 m_rootvertex->m_id = 0;
843 while ( next != m_vertices.end() ) {
844 ++((*next++)->m_id);
845 }
846 } else {
847 HEPMC3_WARNING_LEVEL(700,"GenEvent::add_tree Suspicious looking rootvertex found. Will try to cope.")
848 }
849 }
850
851 HEPMC3_DEBUG_CODE_BLOCK(
852 HEPMC3_DEBUG(6, "GenEvent - particles sorted: "
853 << this->particles().size() << ", max deque size: "
854 << max_deque_size << ", iterations: " << sorting_loop_count)
855 )
856}
857
858
859void GenEvent::reserve(const size_t& parts, const size_t& verts) {
860 m_particles.reserve(parts);
861 m_vertices.reserve(verts);
862}
863
864
865void GenEvent::set_units(Units::MomentumUnit new_momentum_unit, Units::LengthUnit new_length_unit) {
866 if ( new_momentum_unit != m_momentum_unit ) {
867 for ( GenParticlePtr& p: m_particles ) {
868 Units::convert(p->m_data.momentum, m_momentum_unit, new_momentum_unit);
869 Units::convert(p->m_data.mass, m_momentum_unit, new_momentum_unit);
870 }
871
872 m_momentum_unit = new_momentum_unit;
873 }
874
875 if ( new_length_unit != m_length_unit ) {
876 for (GenVertexPtr& v: m_vertices) {
877 FourVector &fv = v->m_data.position;
878 if ( !fv.is_zero() ) Units::convert( fv, m_length_unit, new_length_unit );
879 }
880
881 m_length_unit = new_length_unit;
882 }
883}
884
885
887 return m_rootvertex->data().position;
888}
889
890std::vector<ConstGenParticlePtr> GenEvent::beams(const int status) const {
891 if (!status) return std::const_pointer_cast<const GenVertex>(m_rootvertex)->particles_out();
892 std::vector<ConstGenParticlePtr> ret;
893 for (auto& p: m_rootvertex->particles_out()) if (p->status() == status) ret.emplace_back(p);
894 return ret;
895}
896
897std::vector<ConstGenParticlePtr> GenEvent::beams() const {
898 return std::const_pointer_cast<const GenVertex>(m_rootvertex)->particles_out();
899}
900
901
902const std::vector<GenParticlePtr> & GenEvent::beams() {
903 return m_rootvertex->particles_out();
904}
905
907 m_rootvertex->set_position(event_pos() + delta);
908
909 // Offset all vertices
910 for ( GenVertexPtr& v: m_vertices ) {
911 if ( v->has_set_position() ) {
912 v->set_position(v->position() + delta);
913 }
914 }
915}
916
917bool GenEvent::rotate(const FourVector& delta)
918{
919 long double cosa = std::cos(delta.x());
920 long double sina = std::sin(delta.x());
921 long double cosb = std::cos(delta.y());
922 long double sinb = std::sin(delta.y());
923 long double cosg = std::cos(delta.z());
924 long double sing = std::sin(delta.z());
925
926 for ( auto& p: m_particles)
927 {
928 const FourVector& mom = p->momentum();
929 long double tempX = mom.x();
930 long double tempY = mom.y();
931 long double tempZ = mom.z();
932
933 long double tempY_ = cosa*tempY+sina*tempZ;
934 long double tempZ_ = -sina*tempY+cosa*tempZ;
935 tempY = tempY_;
936 tempZ = tempZ_;
937
938 long double tempX_ = cosb*tempX-sinb*tempZ;
939 tempZ_ = sinb*tempX+cosb*tempZ;
940 tempX = tempX_;
941 tempZ = tempZ_;
942
943 tempX_ = cosg*tempX+sing*tempY;
944 tempY_ = -sing*tempX+cosg*tempY;
945 tempX = tempX_;
946 tempY = tempY_;
947
948 FourVector temp(tempX, tempY, tempZ, mom.e());
949 p->set_momentum(temp);
950 }
951 for (auto& v: m_vertices)
952 {
953 const FourVector& pos = v->position();
954 if (pos.is_zero()) continue;
955
956 long double tempX = pos.x();
957 long double tempY = pos.y();
958 long double tempZ = pos.z();
959
960 long double tempY_ = cosa*tempY+sina*tempZ;
961 long double tempZ_ = -sina*tempY+cosa*tempZ;
962 tempY = tempY_;
963 tempZ = tempZ_;
964
965 long double tempX_ = cosb*tempX-sinb*tempZ;
966 tempZ_ = sinb*tempX+cosb*tempZ;
967 tempX = tempX_;
968 tempZ = tempZ_;
969
970 tempX_ = cosg*tempX+sing*tempY;
971 tempY_ = -sing*tempX+cosg*tempY;
972 tempX = tempX_;
973 tempY = tempY_;
974
975 FourVector temp(tempX, tempY, tempZ, pos.t());
976 v->set_position(temp);
977 }
978
979
980 return true;
981}
982
983bool GenEvent::reflect(const int axis)
984{
985 if ( axis > 3 || axis < 0 )
986 {
987 HEPMC3_WARNING_LEVEL(400,"GenEvent::reflect: wrong axis")
988 return false;
989 }
990 switch (axis)
991 {
992 case 0:
993 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setX(-p->momentum().x()); p->set_momentum(temp);}
994 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setX(-v->position().x()); v->set_position(temp);}
995 break;
996 case 1:
997 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setY(-p->momentum().y()); p->set_momentum(temp);}
998 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setY(-v->position().y()); v->set_position(temp);}
999 break;
1000 case 2:
1001 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setZ(-p->momentum().z()); p->set_momentum(temp);}
1002 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setZ(-v->position().z()); v->set_position(temp);}
1003 break;
1004 case 3:
1005 for ( auto& p: m_particles) { FourVector temp = p->momentum(); temp.setT(-p->momentum().e()); p->set_momentum(temp);}
1006 for ( auto& v: m_vertices) { FourVector temp = v->position(); temp.setT(-v->position().t()); v->set_position(temp);}
1007 break;
1008 default:
1009 return false;
1010 }
1011
1012 return true;
1013}
1014
1015bool GenEvent::boost(const FourVector& delta)
1016{
1017 double deltalength2 = delta.length2();
1018 if (deltalength2 > 1.0)
1019 {
1020 HEPMC3_WARNING_LEVEL(400,"GenEvent::boost: wrong large boost vector. Will leave event as is.")
1021 return false;
1022 }
1023 if (std::abs(deltalength2-1.0) < std::numeric_limits<double>::epsilon())
1024 {
1025 HEPMC3_WARNING_LEVEL(400,"GenEvent::boost: too large gamma. Will leave event as is.")
1026 return false;
1027 }
1028 if (std::abs(deltalength2) < std::numeric_limits<double>::epsilon())
1029 {
1030 HEPMC3_WARNING_LEVEL(400,"GenEvent::boost: wrong small boost vector. Will leave event as is.")
1031 return true;
1032 }
1033 long double deltaX = delta.x();
1034 long double deltaY = delta.y();
1035 long double deltaZ = delta.z();
1036 long double deltalength = std::sqrt(deltalength2);
1037 long double gamma = 1.0/std::sqrt(1.0-deltalength2);
1038
1039 for ( auto& p: m_particles)
1040 {
1041 const FourVector& mom = p->momentum();
1042
1043 long double tempX = mom.x();
1044 long double tempY = mom.y();
1045 long double tempZ = mom.z();
1046 long double tempE = mom.e();
1047 long double nr = (deltaX*tempX+deltaY*tempY+deltaZ*tempZ)/deltalength;
1048 long double gfac = (gamma-1)*nr/deltalength-tempE*gamma;
1049 tempX+=(deltaX*gfac);
1050 tempY+=(deltaY*gfac);
1051 tempZ+=(deltaZ*gfac);
1052 tempE = gamma*(tempE-deltalength*nr);
1053 FourVector temp(tempX, tempY, tempZ, tempE);
1054 p->set_momentum(temp);
1055 }
1056
1057 return true;
1058}
1059
1061 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1062 m_event_number = 0;
1063 m_rootvertex = std::make_shared<GenVertex>();
1064 m_weights.clear();
1065 m_attributes.clear();
1066 m_particles.clear();
1067 m_vertices.clear();
1068}
1069
1070void GenEvent::remove_attribute(const std::string &name, const int& id) {
1071 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1072 auto i1 = m_attributes.find(name);
1073 if ( i1 == m_attributes.end() ) return;
1074
1075 auto i2 = i1->second.find(id);
1076 if ( i2 == i1->second.end() ) return;
1077
1078 i1->second.erase(i2);
1079}
1080
1081std::vector<std::string> GenEvent::attribute_names(const int& id) const {
1082 std::vector<std::string> results;
1083
1084 for (const att_key_t& vt1: m_attributes) {
1085 if ( vt1.second.count(id) == 1 ) {
1086 results.emplace_back(vt1.first);
1087 }
1088 }
1089
1090 return results;
1091}
1092
1094 // Reserve memory for containers
1095 data.particles.reserve(this->particles().size());
1096 data.vertices.reserve(this->vertices().size());
1097 data.links1.reserve(this->particles().size()*2);
1098 data.links2.reserve(this->particles().size()*2);
1099 data.attribute_id.reserve(m_attributes.size());
1100 data.attribute_name.reserve(m_attributes.size());
1101 data.attribute_string.reserve(m_attributes.size());
1102
1103 // Fill event data
1104 data.event_number = this->event_number();
1105 data.momentum_unit = this->momentum_unit();
1106 data.length_unit = this->length_unit();
1107 data.event_pos = this->event_pos();
1108
1109 // Fill containers
1110 data.weights = this->weights();
1111
1112 for (const ConstGenParticlePtr& p: this->particles()) {
1113 data.particles.emplace_back(p->data());
1114 }
1115
1116 for (const ConstGenVertexPtr& v: this->vertices()) {
1117 data.vertices.emplace_back(v->data());
1118 int v_id = v->id();
1119
1120 for (const ConstGenParticlePtr& p: v->particles_in()) {
1121 data.links1.emplace_back(p->id());
1122 data.links2.emplace_back(v_id);
1123 }
1124
1125 for (const ConstGenParticlePtr& p: v->particles_out()) {
1126 data.links1.emplace_back(v_id);
1127 data.links2.emplace_back(p->id());
1128 }
1129 }
1130
1131 for (const att_key_t& vt1: this->attributes()) {
1132 for (const att_val_t& vt2: vt1.second) {
1133 std::string st;
1134
1135 bool status = vt2.second->to_string(st);
1136
1137 if ( !status ) {
1138 HEPMC3_WARNING_LEVEL(300,"GenEvent::write_data: problem serializing attribute: " << vt1.first)
1139 }
1140 else {
1141 data.attribute_id.emplace_back(vt2.first);
1142 data.attribute_name.emplace_back(vt1.first);
1143 data.attribute_string.emplace_back(st);
1144 }
1145 }
1146 }
1147}
1148
1149
1151 this->clear();
1152 this->set_event_number(data.event_number);
1153 //Note: set_units checks the current unit of event, i.e. applicable only for fully constructed event.
1154 m_momentum_unit = data.momentum_unit;
1155 m_length_unit = data.length_unit;
1156 this->shift_position_to(data.event_pos);
1157
1158 // Fill weights
1159 this->weights() = data.weights;
1160 m_particles.reserve(data.particles.size());
1161 m_vertices.reserve(data.vertices.size());
1162
1163 // Fill particle information
1164 for ( const GenParticleData &pd: data.particles ) {
1165 m_particles.emplace_back(std::make_shared<GenParticle>(pd));
1166 m_particles.back()->m_event = this;
1167 m_particles.back()->m_id = m_particles.size();
1168 }
1169
1170 // Fill vertex information
1171 for ( const GenVertexData &vd: data.vertices ) {
1172 m_vertices.emplace_back(std::make_shared<GenVertex>(vd));
1173 m_vertices.back()->m_event = this;
1174 m_vertices.back()->m_id = -(int)m_vertices.size();
1175 }
1176
1177 // Restore links
1178 for (unsigned int i = 0; i < data.links1.size(); ++i) {
1179 const int id1 = data.links1[i];
1180 const int id2 = data.links2[i];
1181 /* @note:
1182 The meaningfull combinations for (id1,id2) are:
1183 (+-) -- particle has end vertex
1184 (-+) -- particle has production vertex
1185 */
1186 if ((id1 < 0 && id2 <0) || (id1 > 0 && id2 > 0)) {
1187 HEPMC3_WARNING_LEVEL(600,"GenEvent::read_data: wrong link: " << id1 << " " << id2);
1188 continue;
1189 }
1190
1191 if ( id1 > 0 ) { m_vertices[ (-id2)-1 ]->add_particle_in ( m_particles[ id1-1 ] ); continue; }
1192 if ( id1 < 0 ) { m_vertices[ (-id1)-1 ]->add_particle_out( m_particles[ id2-1 ] ); continue; }
1193 }
1194 for (auto& p: m_particles) if (!p->production_vertex()) m_rootvertex->add_particle_out(p);
1195
1196 // Read attributes
1197 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1198 for (unsigned int i = 0; i < data.attribute_id.size(); ++i) {
1200 const std::string name = data.attribute_name[i];
1201 if (name.length() == 0) continue;
1202 const int id = data.attribute_id[i];
1203 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
1204 auto att = std::make_shared<StringAttribute>(data.attribute_string[i]);
1205 att->m_event = this;
1206 if ( id > 0 && id <= int(m_particles.size()) ) {
1207 att->m_particle = m_particles[id - 1];
1208 }
1209 if ( id < 0 && -id <= int(m_vertices.size()) ) {
1210 att->m_vertex = m_vertices[-id - 1];
1211 }
1212 m_attributes[name][id] = att;
1213 }
1214}
1215
1216
1217//
1218// Deprecated functions
1219//
1220
1221void GenEvent::set_beam_particles(GenParticlePtr p1, GenParticlePtr p2) {
1222 m_rootvertex->add_particle_out(p1);
1223 m_rootvertex->add_particle_out(p2);
1224}
1225
1226void GenEvent::add_beam_particle(GenParticlePtr p1) {
1227 if (!p1)
1228 {
1229 HEPMC3_WARNING_LEVEL(700,"Attempting to add an empty particle as beam particle. Ignored.")
1230 return;
1231 }
1232 if (p1->in_event() && p1->parent_event() != this)
1233 {
1234 HEPMC3_WARNING_LEVEL(700,"Attempting to add particle from another event. Ignored.")
1235 return;
1236 }
1237 if (p1->production_vertex()) p1->production_vertex()->remove_particle_out(p1);
1238 //Particle w/o production vertex is added to root vertex.
1239 add_particle(p1);
1240 p1->set_status(4);
1241}
1242
1243
1244std::string GenEvent::attribute_as_string(const std::string &name, const int& id) const {
1245 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1246 auto i1 = m_attributes.find(name);
1247 if ( i1 == m_attributes.end() ) {
1248 if ( id == 0 && run_info() ) {
1249 return run_info()->attribute_as_string(name);
1250 }
1251 return {};
1252 }
1253
1254 auto i2 = i1->second.find(id);
1255 if (i2 == i1->second.end() ) return {};
1256
1257 if ( !i2->second ) return {};
1258
1259 std::string ret;
1260 i2->second->to_string(ret);
1261
1262 return ret;
1263}
1264
1265void GenEvent::add_attribute(const std::string &name, const std::shared_ptr<Attribute> &att, const int& id ) {
1267 if (name.length() == 0) return;
1268 if (!att) return;
1269 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1270 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
1271 m_attributes[name][id] = att;
1272 att->m_event = this;
1273 if ( id > 0 && id <= int(particles().size()) ) {
1274 att->m_particle = particles()[id - 1];
1275 }
1276 if ( id < 0 && -id <= int(vertices().size()) ) {
1277 att->m_vertex = vertices()[-id - 1];
1278 }
1279}
1280
1281
1282void GenEvent::add_attributes(const std::vector<std::string> &names, const std::vector<std::shared_ptr<Attribute> > &atts, const std::vector<int>& ids) {
1283 size_t N = names.size();
1284 if ( N == 0 ) return;
1285 if (N != atts.size()) return;
1286 if (N != ids.size()) return;
1287
1288 std::vector<std::string> unames = names;
1289 vector<std::string>::iterator ip;
1290 ip = std::unique(unames.begin(), unames.end());
1291 unames.resize(std::distance(unames.begin(), ip));
1292 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1293 for (const auto& name: unames) {
1294 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
1295 }
1296 const int particles_size = int(m_particles.size());
1297 const int vertices_size = int(m_vertices.size());
1298 for (size_t i = 0; i < N; i++) {
1300 if (names.at(i).length() == 0) continue;
1301 if (!atts[i]) continue;
1302 m_attributes[names.at(i)][ids.at(i)] = atts[i];
1303 atts[i]->m_event = this;
1304 if ( ids.at(i) > 0 && ids.at(i) <= particles_size )
1305 { atts[i]->m_particle = m_particles[ids.at(i) - 1]; }
1306 else {
1307 if ( ids.at(i) < 0 && -ids.at(i) <= vertices_size ) {
1308 atts[i]->m_vertex = m_vertices[-ids.at(i) - 1];
1309 }
1310 }
1311 }
1312}
1313
1314void GenEvent::add_attributes(const std::string& name, const std::vector<std::shared_ptr<Attribute> > &atts, const std::vector<int>& ids) {
1315 if (name.length() == 0) return;
1316 size_t N = ids.size();
1317 if(!N) return;
1318 if ( N != atts.size()) return;
1319
1320 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1321 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
1322 auto& tmap = m_attributes[name];
1323 const int particles_size = int(m_particles.size());
1324 const int vertices_size = int(m_vertices.size());
1325 for (size_t i = 0; i < N; i++) {
1327 if (!atts[i]) continue;
1328 tmap[ids.at(i)] = atts[i];
1329 atts[i]->m_event = this;
1330 if ( ids.at(i) > 0 && ids.at(i) <= particles_size )
1331 { atts[i]->m_particle = m_particles[ids.at(i) - 1]; }
1332 else {
1333 if ( ids.at(i) < 0 && -ids.at(i) <= vertices_size ) {
1334 atts[i]->m_vertex = m_vertices[-ids.at(i) - 1];
1335 }
1336 }
1337 }
1338}
1339void GenEvent::add_attributes(const std::string& name, const std::vector<std::pair<int, std::shared_ptr<Attribute> > > &atts) {
1340 if (name.length() == 0) return;
1341 if (atts.empty()) return;
1342 std::lock_guard<std::recursive_mutex> lock(m_lock_attributes);
1343 if (m_attributes.count(name) == 0) m_attributes[name] = std::map<int, std::shared_ptr<Attribute> >();
1344 auto& tmap = m_attributes[name];
1345 const int particles_size = int(m_particles.size());
1346 const int vertices_size = int(m_vertices.size());
1347 for (const auto& att: atts) {
1349 if (!att.second) continue;
1350 tmap.insert(att);
1351 att.second->m_event = this;
1352 if ( att.first > 0 && att.first <= particles_size )
1353 { att.second->m_particle = m_particles[att.first - 1]; }
1354 else {
1355 if ( att.first < 0 && -att.first <= vertices_size ) {
1356 att.second->m_vertex = m_vertices[-att.first - 1];
1357 }
1358 }
1359 }
1360}
1361
1362} // namespace HepMC3
1363
1364// ============================================================
1365// hepmc3/Print.cc
1366// Copyright (C) 2014-2023 The HepMC collaboration
1367// ============================================================
1368// -*- C++ -*-
1369//
1370// This file is part of HepMC
1371// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
1372//
1378#include "HepMC3/Print.h"
1379#include "HepMC3/Attribute.h"
1380
1381
1382namespace HepMC3 {
1383
1384void Print::content(std::ostream& os, const GenEvent &event) {
1385 os << "--------------------------------" << std::endl;
1386 os << "--------- EVENT CONTENT --------" << std::endl;
1387 os << "--------------------------------" << std::endl;
1388 os << std::endl;
1389
1390 os << "Weights (" << event.weights().size() << "): " << std::endl;
1391 for (const auto& w: event.weights()) {
1392 os << " " << w;
1393 }
1394
1395 os << "Attributes:" << std::endl;
1396
1397 for (const auto& vt1: event.attributes()) {
1398 for (const auto& vt2: vt1.second) {
1399 os << vt2.first << ": " << vt1.first << std::endl;
1400 }
1401 }
1402
1403 os << "GenParticlePtr (" << event.particles().size() << ")" << std::endl;
1404
1405 for (const ConstGenParticlePtr& p: event.particles()) {
1406 Print::line(os, p, true);
1407 os << std::endl;
1408 }
1409
1410 os << "GenVertexPtr (" << event.vertices().size() << ")" << std::endl;
1411 for ( const ConstGenVertexPtr& v: event.vertices() ) {
1412 Print::line(os, v, true);
1413 os << std::endl;
1414 }
1415
1416 os << "-----------------------------" << std::endl;
1417}
1418
1419void Print::listing(std::ostream& os, const GenEvent &event, unsigned short precision) {
1420 // Find the current stream state
1421 std::ios_base::fmtflags orig = os.flags();
1422 std::streamsize prec = os.precision();
1423
1424 // Set precision
1425 os.precision(precision);
1426
1427 os << "________________________________________________________________________" << std::endl;
1428 os << "GenEvent: #" << event.event_number() << std::endl;
1429 os << " Momentum units: " << Units::name(event.momentum_unit())
1430 << " Position units: " << Units::name(event.length_unit()) << std::endl;
1431 os << " Entries in this event: " << event.vertices().size() << " vertices, "
1432 << event.particles().size() << " particles, "
1433 << event.weights().size() << " weights." << std::endl;
1434
1435 const FourVector &pos = event.event_pos();
1436 os << " Position offset: " << pos.x() << ", " << pos.y() << ", " << pos.z() << ", " << pos.t() << std::endl;
1437
1438 // Print a legend to describe the particle info
1439 os << " GenParticle Legend" << std::endl;
1440 os << " ID PDG ID "
1441 << "( px, py, pz, E )"
1442 << " Stat ProdVtx" << std::endl;
1443 os << "________________________________________________________________________" << std::endl;
1444
1445 // Print all vertices
1446 for (const ConstGenVertexPtr& v: event.vertices()) {
1447 Print::listing(os, v);
1448 }
1449
1450 // Restore the stream state
1451 os.flags(orig);
1452 os.precision(prec);
1453 os << "________________________________________________________________________" << std::endl;
1454}
1455
1456void Print::listing(std::ostream& os, const GenRunInfo &ri, unsigned short precision) {
1457 // Find the current stream state
1458 std::ios_base::fmtflags orig = os.flags();
1459 std::streamsize prec = os.precision();
1460
1461 // Set precision
1462 os.precision(precision);
1463
1464 os << "________________________________________________________________________" << std::endl;
1465 os << "GenRunInfo:" << std::endl;
1466
1467 std::vector<std::string> names = ri.weight_names();
1468 os << " Names: ( ";
1469 for (const auto& n: names) os << n;
1470 os << " )" << std::endl;
1471
1472 os << " Tools: " << std::endl;
1473
1474 for (const auto& t: ri.tools()) {
1475 Print::line(os, t);
1476 }
1477 os << "Attributes:" << std::endl;
1478 for (const auto& att: ri.attributes()) {
1479 std::string st;
1480 if ( !att.second->to_string(st) ) {
1481 HEPMC3_WARNING_LEVEL(300,"Print::listing: problem serializing attribute: " << att.first)
1482 }
1483 else { os << att.first << " " << st;}
1484 os << std::endl;
1485 }
1486
1487 // Restore the stream state
1488 os.flags(orig);
1489 os.precision(prec);
1490 os << "________________________________________________________________________" << std::endl;
1491}
1492
1493void Print::listing(std::ostream& os, ConstGenVertexPtr v) {
1494 if (!v) { os << "Vtx: Empty vertex" << std::endl; return;}
1495 os << "Vtx: ";
1496 os.width(6);
1497 os << v->id() << " stat: ";
1498 os.width(3);
1499 os << v->status();
1500
1501 const FourVector &pos = v->position();
1502 if ( !pos.is_zero() ) {
1503 os << " (X,cT): " << pos.x() << " " << pos.y() << " " << pos.z() << " " << pos.t();
1504 }
1505 else os << " (X,cT): 0";
1506
1507 os << std::endl;
1508
1509 bool printed_header = false;
1510
1511 // Print out all the incoming particles
1512 for (const ConstGenParticlePtr& p: v->particles_in()) {
1513 if ( !printed_header ) {
1514 os << " I: ";
1515 printed_header = true;
1516 }
1517 else os << " ";
1518
1519 Print::listing(os, p);
1520 }
1521
1522 printed_header = false;
1523
1524 // Print out all the outgoing particles
1525 for (const ConstGenParticlePtr& p: v->particles_out()) {
1526 if ( !printed_header ) {
1527 os << " O: ";
1528 printed_header = true;
1529 }
1530 else os << " ";
1531
1532 Print::listing(os, p);
1533 }
1534}
1535
1536void Print::listing(std::ostream& os, ConstGenParticlePtr p) {
1537 if (!p) { os << " Empty particle" << std::endl; return;}
1538 os << " ";
1539 os.width(6);
1540 os << p->id();
1541 os.width(9);
1542 os << p->pid() << " ";
1543 os.width(9);
1544 os.setf(std::ios::scientific, std::ios::floatfield);
1545 os.setf(std::ios_base::showpos);
1546
1547 const FourVector &momentum = p->momentum();
1548
1549 os.width(9);
1550 os << momentum.px() << ",";
1551 os.width(9);
1552 os << momentum.py() << ",";
1553 os.width(9);
1554 os << momentum.pz() << ",";
1555 os.width(9);
1556 os << momentum.e() << " ";
1557 os.setf(std::ios::fmtflags(0), std::ios::floatfield);
1558 os.unsetf(std::ios_base::showpos);
1559 os.width(3);
1560 os << p->status();
1561
1562 ConstGenVertexPtr prod = p->production_vertex();
1563
1564 if ( prod ) {
1565 os.width(6);
1566 os << prod->id();
1567 }
1568
1569 os << std::endl;
1570}
1571void Print::line(std::ostream& os, const GenEvent &event, bool attributes) {
1572 os << "GenEvent: #" << event.event_number();
1573 if (attributes) {
1574 for (const std::string& s: event.attribute_names()) {
1575 os << " " << s << "=" <<event.attribute_as_string(s);
1576 }
1577 }
1578}
1579
1580void Print::line(std::ostream& os, const GenRunInfo &RunInfo, bool attributes) {
1581 os <<"GenRunInfo: Number of tools:" << RunInfo.tools().size();
1582
1583 if (attributes) {
1584 for (const std::string& s: RunInfo.attribute_names()) {
1585 os << " " << s << "=" << RunInfo.attribute_as_string(s);
1586 }
1587 }
1588}
1589
1590void Print::line(std::ostream& os, const GenRunInfo::ToolInfo& t) {
1591 os << "GenRunInfo::ToolInfo " << t.name<< " " << t.version << " " << t.description;
1592}
1593
1594template <class T>
1595void line_v(std::ostream& os, T v, bool attributes) {
1596 if (!v) { os << "GenVertex: Empty" << std::endl; return;}
1597 os << "GenVertex: " << v->id() << " stat: ";
1598 os.width(3);
1599 os << v->status();
1600 os << " in: " << v->particles_in().size();
1601 os.width(3);
1602 os << " out: " << v->particles_out().size();
1603
1604 const FourVector &pos = v->position();
1605 os << " has_set_position: ";
1606 if ( v->has_set_position() ) { os << "true"; }
1607 else { os << "false"; }
1608
1609 os << " (X,cT): " << pos.x() << ", " <<pos.y() << ", " << pos.z() << ", " << pos.t();
1610 if (attributes)
1611 {
1612 auto names = v->attribute_names();
1613 for (const auto& ss: names) {
1614 os << " " << ss << "=" << (*v).attribute_as_string(ss);
1615 }
1616 }
1617}
1618void Print::line(std::ostream& os, ConstGenVertexPtr v, bool attributes) { line_v(os,v,attributes); }
1619void Print::line(std::ostream& os, GenVertexPtr v, bool attributes) { line_v(os,v,attributes); }
1620
1621
1622
1623void Print::line(std::ostream& os, const FourVector& p) {
1624 os << "FourVector: ";
1625 // Find the current stream state
1626 std::ios_base::fmtflags orig = os.flags();
1627 os.setf(std::ios::scientific, std::ios::floatfield);
1628 os.setf(std::ios_base::showpos);
1629 std::streamsize prec = os.precision();
1630 // Set precision
1631 os.precision(2);
1632 os << " (P,E)=" << p.x()
1633 << "," << p.y()
1634 << "," << p.z()
1635 << "," << p.e();
1636
1637 // Restore the stream state
1638 os.flags(orig);
1639 os.precision(prec);
1640}
1641
1642template <class T>
1643void line_p(std::ostream& os, T p, bool attributes) {
1644 if (!p) { os << "GenParticle: Empty" << std::endl; return;}
1645 os << "GenParticle: ";
1646 os.width(3);
1647 os << p->id() <<" PDGID: ";
1648 os.width(5);
1649 os << p->pid();
1650
1651 // Find the current stream state
1652 std::ios_base::fmtflags orig = os.flags();
1653
1654 os.setf(std::ios::scientific, std::ios::floatfield);
1655 os.setf(std::ios_base::showpos);
1656 std::streamsize prec = os.precision();
1657
1658 // Set precision
1659 os.precision(2);
1660
1661 const FourVector &momentum = p->momentum();
1662
1663 os << " (P,E)=" << momentum.px()
1664 << "," << momentum.py()
1665 << "," << momentum.pz()
1666 << "," << momentum.e();
1667
1668 // Restore the stream state
1669 os.flags(orig);
1670 os.precision(prec);
1671
1672 const ConstGenVertexPtr prod = p->production_vertex();
1673 const ConstGenVertexPtr end = p->end_vertex();
1674 int prod_vtx_id = (prod) ? prod->id() : 0;
1675 int end_vtx_id = (end) ? end->id() : 0;
1676 auto names = p->attribute_names();
1677
1678 os << " Stat: " << p->status()
1679 << " PV: " << prod_vtx_id
1680 << " EV: " << end_vtx_id
1681 << " Attr: " << names.size();
1682
1683 if (attributes)
1684 {
1685 for (const auto& ss: names) {
1686 os << " " << ss << "=" << (*p).attribute_as_string(ss);
1687 }
1688 }
1689}
1690
1691void Print::line(std::ostream& os, ConstGenParticlePtr p, bool attributes) { line_p(os,p,attributes); }
1692void Print::line(std::ostream& os, GenParticlePtr p, bool attributes) { line_p(os,p,attributes); }
1693
1694void Print::line(std::ostream& os, std::shared_ptr<GenCrossSection> &cs) {
1695 if (!cs) {os << " GenCrossSection: Empty"; return;}
1696 os << " GenCrossSection: " << cs->xsec(0)
1697 << " " << cs->xsec_err(0)
1698 << " " << cs->get_accepted_events()
1699 << " " << cs->get_attempted_events();
1700}
1701
1702void Print::line(std::ostream& os, std::shared_ptr<GenHeavyIon> &hi) {
1703 if (!hi) {os << " GenHeavyIon: Empty"; return;}
1704 os << " GenHeavyIon: " << hi->Ncoll_hard
1705 << " " << hi->Npart_proj
1706 << " " << hi->Npart_targ
1707 << " " << hi->Ncoll
1708 << " " << hi->spectator_neutrons
1709 << " " << hi->spectator_protons
1710 << " " << hi->N_Nwounded_collisions
1711 << " " << hi->Nwounded_N_collisions
1712 << " " << hi->Nwounded_Nwounded_collisions
1713 << " " << hi->impact_parameter
1714 << " " << hi->event_plane_angle
1715 << " " << hi->eccentricity
1716 << " " << hi->sigma_inel_NN;
1717}
1718
1719void Print::line(std::ostream& os, std::shared_ptr<GenPdfInfo> &pi) {
1720 if (!pi) {os << " GenPdfInfo: Empty"; return;}
1721 os << " GenPdfInfo: " << pi->parton_id[0]
1722 << " " << pi->parton_id[1]
1723 << " " << pi->x[0]
1724 << " " << pi->x[1]
1725 << " " << pi->scale
1726 << " " << pi->xf[0]
1727 << " " << pi->xf[1]
1728 << " " << pi->pdf_id[0]
1729 << " " << pi->pdf_id[1];
1730}
1731
1732} // namespace HepMC3
1733
1734// ============================================================
1735// hepmc3/WriterAscii.cc
1736// Copyright (C) 2014-2023 The HepMC collaboration
1737// ============================================================
1738// -*- C++ -*-
1739//
1740// This file is part of HepMC
1741// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
1742//
1747
1748#include <algorithm>//min max for VS2017
1749#include <cstring>
1750
1751
1752#include "HepMC3/GenEvent.h"
1753#include "HepMC3/GenParticle.h"
1754#include "HepMC3/GenVertex.h"
1755#include "HepMC3/Units.h"
1756#include "HepMC3/Version.h"
1757#include "HepMC3/WriterAscii.h"
1758
1759namespace HepMC3 {
1760
1761
1762WriterAscii::WriterAscii(const std::string &filename, std::shared_ptr<GenRunInfo> run)
1763 : m_file(filename),
1764 m_stream(&m_file)
1765{
1766 set_run_info(run);
1767 if ( !m_file.is_open() ) {
1768 HEPMC3_ERROR_LEVEL(200,"WriterAscii: could not open output file: " << filename)
1769 } else {
1770 const std::string header = "HepMC::Version " + version() + "\nHepMC::Asciiv3-START_EVENT_LISTING\n";
1771 m_file.write(header.data(), header.length());
1772 if ( run_info() ) write_run_info();
1773 }
1774 m_float_printf_specifier = " %." + std::to_string(m_precision) + "e";
1775 m_particle_printf_specifier = "P %i %i %i"
1776 + m_float_printf_specifier
1777 + m_float_printf_specifier
1778 + m_float_printf_specifier
1779 + m_float_printf_specifier
1780 + m_float_printf_specifier + " %i\n";
1781 m_vertex_short_printf_specifier = "V %i %i [%s]\n";
1782 m_vertex_long_printf_specifier = "V %i %i [%s] @"+ m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + "\n";
1783}
1784
1785
1786WriterAscii::WriterAscii(std::ostream &stream, std::shared_ptr<GenRunInfo> run)
1787 : m_stream(&stream)
1788{
1789 set_run_info(run);
1790 const std::string header = "HepMC::Version " + version() + "\nHepMC::Asciiv3-START_EVENT_LISTING\n";
1791 m_stream->write(header.data(), header.length());
1792 if ( run_info() ) write_run_info();
1793 m_float_printf_specifier = " %." + std::to_string(m_precision) + "e";
1794 m_particle_printf_specifier = "P %i %i %i"
1795 + m_float_printf_specifier
1796 + m_float_printf_specifier
1797 + m_float_printf_specifier
1798 + m_float_printf_specifier
1799 + m_float_printf_specifier + " %i\n";
1800 m_vertex_short_printf_specifier = "V %i %i [%s]\n";
1801 m_vertex_long_printf_specifier = "V %i %i [%s] @"+ m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + "\n";
1802}
1803
1804WriterAscii::WriterAscii(std::shared_ptr<std::ostream> s_stream, std::shared_ptr<GenRunInfo> run)
1805 : m_shared_stream(s_stream),
1806 m_stream(s_stream.get())
1807{
1808 set_run_info(run);
1809 const std::string header = "HepMC::Version " + version() + "\nHepMC::Asciiv3-START_EVENT_LISTING\n";
1810 m_stream->write(header.data(), header.length());
1811 if ( run_info() ) write_run_info();
1812 m_float_printf_specifier = " %." + std::to_string(m_precision) + "e";
1813 m_particle_printf_specifier = "P %i %i %i"
1814 + m_float_printf_specifier
1815 + m_float_printf_specifier
1816 + m_float_printf_specifier
1817 + m_float_printf_specifier
1818 + m_float_printf_specifier + " %i\n";
1819 m_vertex_short_printf_specifier = "V %i %i [%s]\n";
1820 m_vertex_long_printf_specifier = "V %i %i [%s] @"+ m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + "\n";
1821}
1822
1824 close();
1825 delete[] m_buffer;
1826}
1827
1828
1830 allocate_buffer();
1831 if ( !m_buffer ) return;
1832 auto float_printf_specifier_option = m_options.find("float_printf_specifier");
1833 std::string letter=(float_printf_specifier_option != m_options.end())?float_printf_specifier_option->second.substr(0,2):"e";
1834 if (letter != "e" && letter != "E" && letter != "G" && letter != "g" && letter != "f" && letter != "F" ) letter = "e";
1835 m_float_printf_specifier = " %." + std::to_string(m_precision) + letter;
1836
1837
1838 m_particle_printf_specifier = "P %i %i %i"
1839 + m_float_printf_specifier
1840 + m_float_printf_specifier
1841 + m_float_printf_specifier
1842 + m_float_printf_specifier
1843 + m_float_printf_specifier + " %i\n";
1844 m_vertex_short_printf_specifier = "V %i %i [%s]\n";
1845 m_vertex_long_printf_specifier = "V %i %i [%s] @"+ m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + "\n";
1846
1847 // Make sure nothing was left from previous event
1848 flush();
1849
1850 if ( !run_info() ) {
1851 set_run_info(evt.run_info());
1853 } else {
1854 if ( evt.run_info() && (run_info() != evt.run_info()) ) {
1855 HEPMC3_WARNING_LEVEL(600,"WriterAscii::write_event: GenEvents contain different GenRunInfo objects from - only the first such object will be serialized.")
1856 }
1857 }
1858
1859 // Write event info
1860 flush();
1861 std::string especifier = "E " + std::to_string(evt.event_number()) + " "
1862 + std::to_string(evt.vertices().size()) + " "
1863 + std::to_string(evt.particles().size());
1864 // Write event position if not zero
1865 const FourVector &pos = evt.event_pos();
1866 if ( !pos.is_zero() ) {
1867 especifier += ( " @" + m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + m_float_printf_specifier + "\n" );
1868 m_cursor += sprintf(m_cursor, especifier.c_str(), pos.x(), pos.y(), pos.z(), pos.t());
1869 } else {
1870 m_cursor += sprintf(m_cursor, "%s\n", especifier.c_str());
1871 }
1872 flush();
1873
1874 // Write units
1875 m_cursor += sprintf(m_cursor, "U %s %s\n", Units::name(evt.momentum_unit()).c_str(), Units::name(evt.length_unit()).c_str());
1876 flush();
1877
1878 // Write weight values if present
1879 if ( !evt.weights().empty() ) {
1880 m_cursor += sprintf(m_cursor, "W");
1881 for (const auto& w: evt.weights())
1882 {
1883 m_cursor += sprintf(m_cursor, " %.*e", std::min(3*m_precision, 22), w);
1884 flush();
1885 }
1886 m_cursor += sprintf(m_cursor, "\n");
1887 flush();
1888 }
1889
1890 // Write attributes
1891 for ( const auto& vt1: evt.attributes() ) {
1892 for ( const auto& vt2: vt1.second ) {
1893 std::string st;
1894 bool status = vt2.second->to_string(st);
1895
1896 if ( !status ) {
1897 HEPMC3_WARNING_LEVEL(300,"WriterAscii::write_event: problem serializing attribute: " << vt1.first)
1898 }
1899 else {
1900 m_cursor += sprintf(m_cursor, "A %i ", vt2.first);
1901 write_string(escape(vt1.first));
1902 flush();
1903 m_cursor += sprintf(m_cursor, " ");
1904 write_string(escape(st));
1905 m_cursor += sprintf(m_cursor, "\n");
1906 flush();
1907 }
1908 }
1909 }
1910
1911
1912 // Print particles
1913 std::map<int, bool> alreadywritten;
1914 for (const ConstGenParticlePtr& p: evt.particles()) {
1915 // Check to see if we need to write a vertex first
1916 ConstGenVertexPtr v = p->production_vertex();
1917 int parent_object = 0;
1918
1919 if (v) {
1920 // Check if we need this vertex at all
1921 // Yes, use vertex as parent object
1922 if ( v->particles_in().size() > 1 || !v->data().is_zero() ) { parent_object = v->id(); }
1923 // No, use particle as parent object
1924 // Add check for attributes of this vertex
1925 else {
1926 if ( v->particles_in().size() == 1 ) { parent_object = v->particles_in().front()->id();}
1927 else {if ( v->particles_in().empty() ) {HEPMC3_DEBUG(30, "WriterAscii::write_event - found a vertex without incoming particles: " << v->id());}}
1928 }
1929 // Usage of map instead of simple counter helps to deal with events with random ids of vertices.
1930 if (alreadywritten.count(v->id()) == 0 && parent_object < 0)
1931 { write_vertex(v); alreadywritten[v->id()] = true; }
1932 }
1933
1934 write_particle(p, parent_object);
1935 }
1936 alreadywritten.clear();
1937
1938 // Flush rest of the buffer to file
1939 forced_flush();
1940}
1941
1942
1943void WriterAscii::allocate_buffer() {
1944 if ( m_buffer ) return;
1945 while ( m_buffer == nullptr && m_buffer_size >= 512 ) {
1946 try {
1947 m_buffer = new char[ m_buffer_size ]();
1948 } catch (const std::bad_alloc& e) {
1949 delete[] m_buffer;
1950 m_buffer_size /= 2;
1951 HEPMC3_WARNING_LEVEL(200,"WriterAscii::allocate_buffer:" << e.what() << " buffer size too large. Dividing by 2. New size: " << m_buffer_size)
1952 }
1953 }
1954
1955 if ( !m_buffer ) {
1956 HEPMC3_ERROR_LEVEL(200,"WriterAscii::allocate_buffer: could not allocate buffer!")
1957 return;
1958 }
1959 m_cursor = m_buffer;
1960}
1961
1962
1963std::string WriterAscii::escape(const std::string& s) {
1964 std::string ret;
1965 ret.reserve(s.length()*2);
1966 for ( std::string::const_iterator it = s.begin(); it != s.end(); ++it ) {
1967 switch ( *it ) {
1968 case '\\':
1969 ret += "\\\\";
1970 break;
1971 case '\n':
1972 ret += "\\|";
1973 break;
1974 default:
1975 ret += *it;
1976 }
1977 }
1978 return ret;
1979}
1980
1981void WriterAscii::write_vertex(const ConstGenVertexPtr& v) {
1982 flush();
1983 std::string vlist;
1984 std::vector<int> pids;
1985 pids.reserve(v->particles_in().size());
1986 for (const ConstGenParticlePtr& p: v->particles_in()) pids.emplace_back(p->id());
1987 //We order pids to be able to compare ascii files
1988 std::sort(pids.begin(), pids.end());
1989 for (const auto& p: pids) vlist.append( std::to_string(p).append(",") );
1990 if ( !pids.empty() ) vlist.pop_back();
1991 const FourVector &pos = v->position();
1992 if ( !pos.is_zero() ) {
1993 m_cursor += sprintf(m_cursor, m_vertex_long_printf_specifier.c_str(), v->id(), v->status(), vlist.c_str(), pos.x(), pos.y(), pos.z(), pos.t() );
1994 } else {
1995 m_cursor += sprintf(m_cursor, m_vertex_short_printf_specifier.c_str(), v->id(), v->status(), vlist.c_str());
1996 }
1997 flush();
1998}
1999
2000
2001inline void WriterAscii::flush() {
2002 // The maximum size of single add to the buffer (other than by
2003 // using WriterAscii::write_string) should not be larger than 256. This is a safe value as
2004 // we will not allow precision larger than 24 anyway
2005 if ( m_buffer + m_buffer_size < m_cursor + 512 ) {
2006 std::ptrdiff_t length = m_cursor - m_buffer;
2007 m_stream->write(m_buffer, length);
2008 m_cursor = m_buffer;
2009 }
2010}
2011
2012
2013inline void WriterAscii::forced_flush() {
2014 std::ptrdiff_t length = m_cursor - m_buffer;
2015 m_stream->write(m_buffer, length);
2016 m_cursor = m_buffer;
2017}
2018
2019
2021 allocate_buffer();
2022
2023 // If no run info object set, create a dummy one.
2024 if ( !run_info() ) set_run_info(std::make_shared<GenRunInfo>());
2025
2026 const std::vector<std::string> names = run_info()->weight_names();
2027
2028 if ( !names.empty() ) {
2029 std::string out = names[0];
2030 for ( int i = 1, N = names.size(); i < N; ++i ) {
2031 out += "\n" + names[i];
2032 }
2033 m_cursor += sprintf(m_cursor, "W ");
2034 flush();
2035 write_string(escape(out));
2036 m_cursor += sprintf(m_cursor, "\n");
2037 }
2038
2039 for (const auto& tool: run_info()->tools()) {
2040 std::string out = "T " + tool.name + "\n" + tool.version + "\n" + tool.description;
2041 write_string(escape(out));
2042 m_cursor += sprintf(m_cursor, "\n");
2043 }
2044
2045
2046 for ( const auto& att: run_info()->attributes() ) {
2047 std::string st;
2048 if ( !att.second->to_string(st) ) {
2049 HEPMC3_WARNING_LEVEL(300,"WriterAscii::write_run_info: problem serializing attribute: " << att.first)
2050 }
2051 else {
2052 m_cursor += sprintf(m_cursor, "A ");
2053 write_string(att.first);
2054 flush();
2055 m_cursor += sprintf(m_cursor, " ");
2056 write_string(escape(st));
2057 m_cursor += sprintf(m_cursor, "\n");
2058 flush();
2059 }
2060 }
2061}
2062
2063void WriterAscii::write_particle(const ConstGenParticlePtr& p, int second_field) {
2064 flush();
2065 m_cursor += sprintf(m_cursor, m_particle_printf_specifier.c_str(), p->id(), second_field, p->pid(), p->momentum().px(), p->momentum().py(), p->momentum().pz(), p->momentum().e(), p->generated_mass(), p->status());
2066 flush();
2067}
2068
2069
2070inline void WriterAscii::write_string(const std::string &str) {
2071 // First let's check if string will fit into the buffer
2072 if ( m_buffer + m_buffer_size > m_cursor + str.length() ) {
2073 strncpy(m_cursor, str.data(), str.length());
2074 m_cursor += str.length();
2075 flush();
2076 }
2077 // If not, flush the buffer and write the string directly
2078 else {
2079 forced_flush();
2080 m_stream->write(str.data(), str.length());
2081 }
2082}
2083
2084
2086 if (!m_stream) return;
2087 auto* ofs = dynamic_cast<std::ofstream*>(m_stream);
2088 if (ofs && !ofs->is_open()) return;
2089 forced_flush();
2090 const std::string footer("HepMC::Asciiv3-END_EVENT_LISTING\n\n");
2091 if (m_stream) m_stream->write(footer.data(),footer.length());
2092 m_stream = nullptr;
2093 if (ofs) ofs->close();
2094}
2095bool WriterAscii::failed() { return (bool)m_file.rdstate(); }
2096
2097void WriterAscii::set_precision(const int& prec ) {
2098 if (prec < 2 || prec > 24) return;
2099 m_precision = prec;
2100}
2101
2103 return m_precision;
2104}
2105
2106void WriterAscii::set_buffer_size(const size_t& size ) {
2107 if (m_buffer) return;
2108 if (size < 1024) return;
2109 m_buffer_size = size;
2110}
2111
2112
2113} // namespace HepMC3
2114
2115// ============================================================
2116// hepmc3/ReaderAscii.cc
2117// Copyright (C) 2014-2023 The HepMC collaboration
2118// ============================================================
2119// -*- C++ -*-
2120//
2121// This file is part of HepMC
2122// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
2123//
2128#include <array>
2129#include <cstring>
2130#include <sstream>
2131
2132#include "HepMC3/ReaderAscii.h"
2133
2134#include "HepMC3/GenEvent.h"
2135#include "HepMC3/GenParticle.h"
2136#include "HepMC3/GenVertex.h"
2137#include "HepMC3/Units.h"
2138
2139namespace HepMC3 {
2140
2141
2142ReaderAscii::ReaderAscii(const std::string &filename)
2143 : m_file(filename), m_isstream(false)
2144{
2145 if ( !m_file.is_open() ) {
2146 HEPMC3_ERROR_LEVEL(100,"ReaderAscii: could not open input file: " << filename)
2147 }
2148 set_run_info(std::make_shared<GenRunInfo>());
2149}
2150
2151ReaderAscii::ReaderAscii(std::istream & stream)
2152 : m_stream(&stream), m_isstream(true)
2153{
2154 if ( !m_stream->good() ) {
2155 HEPMC3_ERROR_LEVEL(100,"ReaderAscii: could not open input stream ")
2156 }
2157 set_run_info(std::make_shared<GenRunInfo>());
2158}
2159
2160
2161ReaderAscii::ReaderAscii(std::shared_ptr<std::istream> s_stream)
2162 : m_shared_stream(s_stream), m_stream(s_stream.get()), m_isstream(true)
2163{
2164 if ( !m_stream->good() ) {
2165 HEPMC3_ERROR_LEVEL(100,"ReaderAscii: could not open input stream ")
2166 }
2167 set_run_info(std::make_shared<GenRunInfo>());
2168}
2169
2170ReaderAscii::~ReaderAscii() { if (!m_isstream) close(); }
2171
2172bool ReaderAscii::skip(const int n)
2173{
2174 std::array<char, 262144> buf{};
2175 bool event_context = false;
2176 bool run_info_context = false;
2177 int nn = n;
2178 while (!failed()) {
2179 char peek(0);
2180 if ( (!m_file.is_open()) && (!m_isstream) ) return false;
2181 m_isstream ? peek = m_stream->peek() : peek = m_file.peek();
2182 if ( peek == 'E' ) { event_context = true; nn--; }
2183 //We have to read each run info.
2184 if ( !event_context && ( peek == 'W' || peek == 'A' || peek == 'T' ) ) {
2185 m_isstream ? m_stream->getline(buf.data(), buf.size()) : m_file.getline(buf.data(), buf.size());
2186 if (!run_info_context) {
2187 set_run_info(std::make_shared<GenRunInfo>());
2188 run_info_context = true;
2189 }
2190 if ( peek == 'W' ) {
2191 parse_weight_names(buf.data());
2192 }
2193 if ( peek == 'T' ) {
2194 parse_tool(buf.data());
2195 }
2196 if ( peek == 'A' ) {
2197 parse_run_attribute(buf.data());
2198 }
2199 }
2200 if ( event_context && ( peek == 'V' || peek == 'P' ) ) event_context=false;
2201 if (nn < 0) return true;
2202 m_isstream ? m_stream->getline(buf.data(), buf.size()) : m_file.getline(buf.data(), buf.size());
2203 }
2204 return true;
2205}
2206
2207
2209 if ( (!m_file.is_open()) && (!m_isstream) ) return false;
2210
2211 char peek(0);
2212 std::array<char, 262144> buf{};
2213 bool event_context = false;
2214 bool parsed_weights = false;
2215 bool parsed_particles_or_vertices = false;
2216 bool run_info_context = false;
2217 bool is_parsing_successful = true;
2218 std::pair<int, int> vertices_and_particles(0, 0);
2219
2220 evt.clear();
2221 evt.set_run_info(run_info());
2222 m_io_explicit.clear();
2223 m_io_implicit.clear();
2224 m_io_implicit_ids.clear();
2225 m_io_explicit_ids.clear();
2226 m_data.particles.clear();
2227 m_data.vertices.clear();
2228 m_data.links1.clear();
2229 m_data.links2.clear();
2230 m_data.attribute_id.clear();
2231 m_data.attribute_name.clear();
2232 m_data.attribute_string.clear();
2233 //
2234 // Parse event, vertex and particle information
2235 //
2236 while (!failed()) {
2237 m_isstream ? m_stream->getline(buf.data(), buf.size()) : m_file.getline(buf.data(), buf.size());
2238
2239 if ( strlen(buf.data()) == 0 ) continue;
2240
2241 // Check for ReaderAscii header/footer
2242 if ( strncmp(buf.data(), "HepMC", 5) == 0 ) {
2243 if ( strncmp(buf.data(), "HepMC::Version", 14) != 0 && strncmp(buf.data(), "HepMC::Asciiv3", 14) != 0 )
2244 {
2245 HEPMC3_WARNING_LEVEL(500,"ReaderAscii: found unsupported expression in header. Will close the input.")
2246 std::cout << buf.data() << std::endl;
2247 m_isstream ? m_stream->clear(std::ios::eofbit) : m_file.clear(std::ios::eofbit);
2248 }
2249 if (event_context) {
2250 is_parsing_successful = true;
2251 break;
2252 }
2253 continue;
2254 }
2255
2256 switch (buf[0]) {
2257 case 'E':
2258 vertices_and_particles = parse_event_information( buf.data());
2259 if (vertices_and_particles.second < 0) {
2260 is_parsing_successful = false;
2261 } else {
2262 is_parsing_successful = true;
2263 event_context = true;
2264 parsed_weights = false;
2265 parsed_particles_or_vertices = false;
2266 }
2267
2268
2269 run_info_context = false;
2270 break;
2271 case 'V':
2272 is_parsing_successful = parse_vertex_information( buf.data());
2273 parsed_particles_or_vertices = true;
2274 break;
2275 case 'P':
2276 is_parsing_successful = parse_particle_information( buf.data());
2277 parsed_particles_or_vertices = true;
2278 break;
2279 case 'W':
2280 if ( event_context ) {
2281 is_parsing_successful = parse_weight_values( buf.data());
2282 parsed_weights=true;
2283 } else {
2284 if ( !run_info_context ) {
2285 set_run_info(std::make_shared<GenRunInfo>());
2286 evt.set_run_info(run_info());
2287 }
2288 run_info_context = true;
2289 is_parsing_successful = parse_weight_names(buf.data());
2290 }
2291 break;
2292 case 'U':
2293 is_parsing_successful = parse_units( buf.data());
2294 break;
2295 case 'T':
2296 if ( event_context ) {
2297 //We ignore T in the event context
2298 } else {
2299 if ( !run_info_context ) {
2300 set_run_info(std::make_shared<GenRunInfo>());
2301 evt.set_run_info(run_info());
2302 }
2303 run_info_context = true;
2304 is_parsing_successful = parse_tool(buf.data());
2305 }
2306 break;
2307 case 'A':
2308 if ( event_context ) {
2309 is_parsing_successful = parse_attribute( buf.data());
2310 } else {
2311 if ( !run_info_context ) {
2312 set_run_info(std::make_shared<GenRunInfo>());
2313 evt.set_run_info(run_info());
2314 }
2315 run_info_context = true;
2316 is_parsing_successful = parse_run_attribute(buf.data());
2317 }
2318 break;
2319 default:
2320 HEPMC3_WARNING_LEVEL(500,"ReaderAscii: skipping unrecognised prefix: " << buf[0])
2321 is_parsing_successful = true;
2322 break;
2323 }
2324
2325 if ( !is_parsing_successful ) break;
2326
2327 // Check for next event or run info
2328 m_isstream ? peek = m_stream->peek() : peek = m_file.peek();
2329 //End of event. The next entry is event.
2330 if ( event_context && peek == 'E' ) break;
2331
2332 //End of event. The next entry is run info which starts from weight name.
2333 if ( event_context && peek == 'W' && parsed_weights ) break;
2334
2335 //End of event. The next entry is run info which starts from attribute.
2336 if ( event_context && peek == 'A' && parsed_particles_or_vertices ) break;
2337
2338 //End of event. The next entry is run info which starts from tool.
2339 if ( event_context && peek == 'T' ) break;
2340
2341 }
2342
2345 int currid = -static_cast<int>(m_data.vertices.size());
2346 auto fir = m_io_implicit_ids.rbegin();
2347 for (const auto& iofirst: m_io_explicit_ids) {
2348 for (; currid < iofirst; ++currid, ++fir) {
2349 if (fir == m_io_implicit_ids.rend()) {
2350 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: not enough implicit vertices")
2351 }
2353 m_io_explicit[currid] = std::move(m_io_implicit[*fir]);
2354 }
2355 ++currid;
2356 }
2357
2358 for (const auto& io: m_io_explicit) {
2359 for (const auto& i: io.second.first) { m_data.links1.push_back(i); m_data.links2.push_back(io.first); }
2360 for (const auto& o: io.second.second) { m_data.links1.push_back(io.first); m_data.links2.push_back(o); }
2361 }
2362 evt.read_data(m_data);
2363
2364 // Check if all particles and vertices were parsed
2365 if ((int)evt.particles().size() > vertices_and_particles.second) {
2366 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: too many particles were parsed")
2367 printf("%zu vs %i expected\n", evt.particles().size(), vertices_and_particles.second);
2368 is_parsing_successful = false;
2369 }
2370 if ((int)evt.particles().size() < vertices_and_particles.second) {
2371 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: too few particles were parsed")
2372 printf("%zu vs %i expected\n", evt.particles().size(), vertices_and_particles.second);
2373 is_parsing_successful = false;
2374 }
2375
2376 if ((int)evt.vertices().size() > vertices_and_particles.first) {
2377 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: too many vertices were parsed")
2378 printf("%zu vs %i expected\n", evt.vertices().size(), vertices_and_particles.first);
2379 is_parsing_successful = false;
2380 }
2381
2382 if ((int)evt.vertices().size() < vertices_and_particles.first) {
2383 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: too few vertices were parsed")
2384 printf("%zu vs %i expected\n", evt.vertices().size(), vertices_and_particles.first);
2385 is_parsing_successful = false;
2386 }
2387 // Check if there were HEPMC3_ERRORs during parsing
2388 if ( !is_parsing_successful ) {
2389 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: event parsing failed. Returning empty event")
2390 HEPMC3_DEBUG(1, "Parsing failed at line:" << std::endl << buf.data())
2391
2392 evt.clear();
2393 m_isstream ? m_stream->clear(std::ios::badbit) : m_file.clear(std::ios::badbit);
2394
2395 return false;
2396 }
2397
2398
2399 return true;
2400}
2401
2402
2403std::pair<int, int> ReaderAscii::parse_event_information(const char *buf) {
2404 static const std::pair<int, int> err(-1, -1);
2405 std::pair<int, int> ret(-1, -1);
2406 const char *cursor = buf;
2407 FourVector& position = m_data.event_pos;
2408
2409 // event number
2410 if ( !(cursor = strchr(cursor+1, ' ')) ) return err;
2411 m_data.event_number = atoi(cursor);
2412
2413 // num_vertices
2414 if ( !(cursor = strchr(cursor+1, ' ')) ) return err;
2415 ret.first = atoi(cursor);
2416
2417 // num_particles
2418 if ( !(cursor = strchr(cursor+1, ' ')) ) return err;
2419 ret.second = atoi(cursor);
2420 m_data.vertices = std::vector<GenVertexData>(ret.first);
2421 m_data.particles = std::vector<GenParticleData>(ret.second);
2422
2423 m_data.links1.reserve(ret.second*2);
2424 m_data.links2.reserve(ret.second*2);
2425 m_data.attribute_id.reserve(ret.second + ret.first);
2426 m_data.attribute_name.reserve(ret.second + ret.first);
2427 m_data.attribute_string.reserve(ret.second + ret.first);
2428 m_io_implicit_ids.reserve(ret.second);
2429 // check if there is position information
2430 if ( (cursor = strchr(cursor+1, '@')) ) {
2431 // x
2432 if ( !(cursor = strchr(cursor+1, ' ')) ) return err;
2433 position.setX(atof(cursor));
2434
2435 // y
2436 if ( !(cursor = strchr(cursor+1, ' ')) ) return err;
2437 position.setY(atof(cursor));
2438
2439 // z
2440 if ( !(cursor = strchr(cursor+1, ' ')) ) return err;
2441 position.setZ(atof(cursor));
2442
2443 // t
2444 if ( !(cursor = strchr(cursor+1, ' ')) ) return err;
2445 position.setT(atof(cursor));
2446 }
2447
2448 HEPMC3_DEBUG(10, "ReaderAscii: E: " << m_data.event_number << " (" <<ret.first << "V, " << ret.second << "P)")
2449
2450 return ret;
2451}
2452
2453
2454bool ReaderAscii::parse_weight_values(const char *buf) {
2455 std::istringstream iss(buf + 1);
2456 std::vector<double> wts;
2457 double w = 0.0;
2458 while (iss >> w) wts.emplace_back(w);
2459 if ( run_info() && !run_info()->weight_names().empty()
2460 && run_info()->weight_names().size() != wts.size() ) {
2461 throw std::logic_error("ReaderAscii::parse_weight_values: "
2462 "The number of weights ("+std::to_string((long long int)(wts.size()))+") does not match "
2463 "the number weight names("+std::to_string((long long int)(run_info()->weight_names().size()))+") in the GenRunInfo object");
2464 }
2465 m_data.weights = wts;
2466
2467 return true;
2468}
2469
2470
2471bool ReaderAscii::parse_units(const char *buf) {
2472 const char *cursor = buf;
2473
2474 // momentum
2475 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2476 ++cursor;
2477 m_data.momentum_unit = Units::momentum_unit(cursor);
2478
2479 // length
2480 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2481 ++cursor;
2482 m_data.length_unit = Units::length_unit(cursor);
2483
2484 HEPMC3_DEBUG(10, "ReaderAscii: U: " << Units::name(m_data.momentum_unit) << " " << Units::name(m_data.length_unit))
2485
2486 return true;
2487}
2488
2489
2490bool ReaderAscii::parse_vertex_information(const char *buf) {
2491 GenVertexPtr data = std::make_shared<GenVertex>();
2492 const char *cursor = buf;
2493 const char *cursor2 = nullptr;
2494 int id = 0;
2495
2496 // id
2497 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2498 id = atoi(cursor);
2499
2500 // status
2501 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2502 m_data.vertices[-id-1].status = atoi(cursor);
2503 FourVector& position = m_data.vertices[-id-1].position;
2504
2505 // skip to the list of particles
2506 if ( !(cursor = strchr(cursor+1, '[')) ) return false;
2507
2508 while (true) {
2509 ++cursor; // skip the '[' or ',' character
2510 cursor2 = cursor; // save cursor position
2511 int particle_in = atoi(cursor);
2512
2513 // add incoming particle to the vertex
2514 if (particle_in > 0) {
2515 //If the particle has not been red yet, we store its id to add the particle later.
2516 m_io_explicit[id].first.insert(particle_in);
2517 }
2518
2519 // check for next particle or end of particle list
2520 if ( !(cursor = strchr(cursor+1, ',')) ) {
2521 if ( !(cursor = strchr(cursor2+1, ']')) ) return false;
2522 break;
2523 }
2524 }
2525
2526 // check if there is position information
2527 if ( (cursor = strchr(cursor+1, '@')) ) {
2528 // x
2529 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2530 position.setX(atof(cursor));
2531
2532 // y
2533 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2534 position.setY(atof(cursor));
2535
2536 // z
2537 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2538 position.setZ(atof(cursor));
2539
2540 // t
2541 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2542 position.setT(atof(cursor));
2543 }
2544
2545 return true;
2546}
2547
2548
2549bool ReaderAscii::parse_particle_information(const char *buf) {
2550 const char *cursor = buf;
2551 int mother_id = 0;
2552
2553 // verify id
2554 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2555
2556 int id = atoi(cursor);
2557 if ( id < 1 || id > static_cast<int>(m_data.particles.size()) ) {
2558 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: particle ID is out of expected range.")
2559 return false;
2560 }
2561
2562 FourVector& momentum = m_data.particles[id-1].momentum;
2563 // mother id
2564 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2565 mother_id = atoi(cursor);
2566 if ( mother_id < -static_cast<int>(m_data.vertices.size()) || mother_id > static_cast<int>(m_data.particles.size()) ) {
2567 HEPMC3_ERROR_LEVEL(600,"ReaderAscii: ID of particle mother is out of expected range.")
2568 return false;
2569 }
2570
2571 if ( mother_id > 0) {
2574 if (m_io_implicit.count(mother_id) == 0) m_io_implicit_ids.push_back(mother_id);
2575 m_io_implicit[mother_id].first.insert(mother_id);
2576 m_io_implicit[mother_id].second.insert(id);
2577 } else {
2578 m_io_explicit[mother_id].second.insert(id);
2579 m_io_explicit_ids.insert(mother_id);
2580 }
2581 // pdg id
2582 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2583 m_data.particles[id-1].pid = atoi(cursor);
2584
2585 // px
2586 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2587 momentum.setPx(atof(cursor));
2588
2589 // py
2590 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2591 momentum.setPy(atof(cursor));
2592
2593 // pz
2594 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2595 momentum.setPz(atof(cursor));
2596
2597 // pe
2598 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2599 momentum.setE(atof(cursor));
2600
2601 // m
2602 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2603 m_data.particles[id-1].mass = atof(cursor);
2604 m_data.particles[id-1].is_mass_set = true;
2605
2606 // status
2607 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2608 m_data.particles[id-1].status = atoi(cursor);
2609
2610 return true;
2611}
2612
2613
2614bool ReaderAscii::parse_attribute(const char *buf) {
2615 const char *cursor = buf;
2616 const char *cursor2 = buf;
2617 std::array<char, 512> name{};
2618 int id = 0;
2619
2620 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2621 id = atoi(cursor);
2622
2623 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2624 ++cursor;
2625
2626 if ( !(cursor2 = strchr(cursor, ' ')) ) return false;
2627 snprintf(name.data(), name.size(), "%.*s", (int)(cursor2-cursor), cursor);
2628
2629 cursor = cursor2+1;
2630
2631 m_data.attribute_id.push_back(id);
2632 m_data.attribute_name.emplace_back(name.data());
2633 m_data.attribute_string.push_back(unescape(cursor));
2634
2635 return true;
2636}
2637
2638bool ReaderAscii::parse_run_attribute(const char *buf) {
2639 const char *cursor = buf;
2640 const char *cursor2 = buf;
2641 std::array<char, 512> name{};
2642
2643 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2644 ++cursor;
2645
2646 if ( !(cursor2 = strchr(cursor, ' ')) ) return false;
2647 snprintf(name.data(), name.size(), "%.*s", (int)(cursor2-cursor), cursor);
2648
2649 cursor = cursor2+1;
2650
2651 std::shared_ptr<StringAttribute> att =
2652 std::make_shared<StringAttribute>(StringAttribute(unescape(cursor)));
2653
2654 run_info()->add_attribute(std::string(name.data()), att);
2655
2656 return true;
2657}
2658
2659
2660bool ReaderAscii::parse_weight_names(const char *buf) {
2661 const char *cursor = buf;
2662
2663 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2664 ++cursor;
2665
2666 std::istringstream iss(unescape(cursor));
2667 std::vector<std::string> names;
2668 std::string name;
2669 while (iss >> name) names.emplace_back(name);
2670
2671 run_info()->set_weight_names(names);
2672
2673 return true;
2674}
2675
2676bool ReaderAscii::parse_tool(const char *buf) {
2677 const char *cursor = buf;
2678
2679 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
2680 ++cursor;
2681 std::string line = unescape(cursor);
2682 GenRunInfo::ToolInfo tool;
2683 std::string::size_type pos = line.find('\n');
2684 tool.name = line.substr(0, pos);
2685 line = line.substr(pos + 1);
2686 pos = line.find('\n');
2687 tool.version = line.substr(0, pos);
2688 tool.description = line.substr(pos + 1);
2689 run_info()->tools().emplace_back(tool);
2690
2691 return true;
2692}
2693
2694
2695std::string ReaderAscii::unescape(const std::string& s) {
2696 std::string ret;
2697 ret.reserve(s.length());
2698 for ( std::string::const_iterator it = s.begin(); it != s.end(); ++it ) {
2699 if ( *it == '\\' ) {
2700 ++it;
2701 if ( *it == '|' ) {
2702 ret += '\n';
2703 }
2704 else {
2705 ret += *it;
2706 }
2707 } else
2708 {ret += *it;}
2709 }
2710
2711 return ret;
2712}
2713
2714bool ReaderAscii::failed() { return m_isstream ? (bool)m_stream->rdstate() :(bool)m_file.rdstate(); }
2715
2717 if ( !m_file.is_open()) return;
2718 m_file.close();
2719}
2720
2721
2722} // namespace HepMC3
2723
2724#endif /* MARLEY_FOUND_HEPMC3 */
Generic 4-vector.
Definition FourVector.h:36
double z() const
z-component of position/displacement
Definition FourVector.h:99
static const FourVector & ZERO_VECTOR()
Static null FourVector = (0,0,0,0)
Definition FourVector.h:306
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
double x() const
x-component of position/displacement
Definition FourVector.h:85
double y() const
y-component of position/displacement
Definition FourVector.h:92
void setT(double tt)
Definition FourVector.h:110
double e() const
Energy component of momentum.
Definition FourVector.h:135
double length2() const
Squared magnitude of (x, y, z) 3-vector.
Definition FourVector.h:148
void setZ(double zz)
Definition FourVector.h:103
void setX(double xx)
Definition FourVector.h:89
void setY(double yy)
Definition FourVector.h:96
Stores event-related information.
Definition GenEvent.h:47
std::vector< std::string > attribute_names(const int &id=0) const
Get list of attribute names.
int vertices_size() const
Vertices size, HepMC2 compatibility.
Definition GenEvent.h:95
void set_beam_particles(GenParticlePtr p1, GenParticlePtr p2)
Set incoming beam particles.
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.
const std::vector< ConstGenParticlePtr > & particles() const
Get list of particles (const)
std::map< std::string, std::map< int, std::shared_ptr< Attribute > > > attributes() const
Get a copy of the list of attributes.
Definition GenEvent.h:268
const std::vector< double > & weights() const
Get event weight values as a vector.
Definition GenEvent.h:105
void remove_particles(std::vector< GenParticlePtr > v)
Remove a set of particles.
void shift_position_to(const FourVector &newpos)
Shift position of all vertices in the event to op.
Definition GenEvent.h:211
void add_particle(GenParticlePtr p)
Add particle.
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 velocities.
int event_number() const
Get event number.
Definition GenEvent.h:155
void add_tree(const std::vector< GenParticlePtr > &parts)
Add whole tree in topological order.
void set_units(Units::MomentumUnit new_momentum_unit, Units::LengthUnit new_length_unit)
Change event units Converts event from current units to new ones.
GenEvent & operator=(const GenEvent &)
Copy Assignment operator.
std::shared_ptr< T > attribute(const std::string &name, const int &id=0) const
Get attribute of type T.
Definition GenEvent.h:418
const Units::MomentumUnit & momentum_unit() const
Get momentum unit.
Definition GenEvent.h:160
void set_run_info(std::shared_ptr< GenRunInfo > run)
Set the GenRunInfo object by smart pointer.
Definition GenEvent.h:148
const std::vector< ConstGenVertexPtr > & vertices() const
Get list of vertices (const)
void clear()
Remove contents of this event.
void read_data(const GenEventData &data)
Fill GenEvent based on GenEventData.
void remove_vertex(GenVertexPtr v)
Remove vertex from the event.
GenEvent(Units::MomentumUnit mu=Units::GEV, Units::LengthUnit lu=Units::MM)
Event constructor without a run.
std::shared_ptr< GenRunInfo > run_info() const
Get a pointer to the the GenRunInfo object.
Definition GenEvent.h:144
bool rotate(const FourVector &delta)
Rotate event using x,y,z components of delta as rotation angles.
void remove_particle(GenParticlePtr p)
Remove particle from the event.
~GenEvent()
Destructor.
std::vector< ConstGenParticlePtr > beams() const
Vector of beam particles.
void write_data(GenEventData &data) const
Fill GenEventData object.
void reserve(const size_t &parts, const size_t &verts=0)
Reserve memory for particles and vertices.
void add_vertex(GenVertexPtr v)
Add vertex.
void add_beam_particle(GenParticlePtr p1)
Add particle to root vertex.
void remove_attribute(const std::string &name, const int &id=0)
Remove attribute.
const FourVector & event_pos() const
Vertex representing the overall event position.
std::string attribute_as_string(const std::string &name, const int &id=0) const
Get attribute of any type as string.
void shift_position_by(const FourVector &delta)
Shift position of all vertices in the event by delta.
void add_attribute(const std::string &name, const std::shared_ptr< Attribute > &att, const int &id=0)
const Units::LengthUnit & length_unit() const
Get length unit.
Definition GenEvent.h:162
int particles_size() const
Particles size, HepMC2 compatibility.
Definition GenEvent.h:91
bool reflect(const int axis)
Change sign of axis.
std::vector< std::string > attribute_names() const
Get list of names of attributes assigned to this particle.
bool add_attribute(const std::string &name, std::shared_ptr< Attribute > att)
Add an attribute to this particle.
void set_momentum(const FourVector &momentum)
Set momentum.
std::vector< GenParticlePtr > parents()
Convenience access to immediate incoming particles via production vertex.
void set_pid(int pid)
Set PDG ID.
void remove_attribute(const std::string &name)
Remove attribute.
std::vector< GenParticlePtr > children()
Convenience access to immediate outgoing particles via end vertex.
ConstGenVertexPtr end_vertex() const
Get end vertex (const version)
void set_generated_mass(double m)
Set generated mass.
std::string attribute_as_string(const std::string &name) const
Get attribute of any type as string.
double generated_mass() const
Get generated mass.
GenParticle(const FourVector &momentum=FourVector::ZERO_VECTOR(), int pid=0, int status=0)
Default constructor.
ConstGenVertexPtr production_vertex() const
Get production vertex (const version)
void unset_generated_mass()
Declare that generated mass is not set.
GenEvent * parent_event()
Get the parent event.
Definition GenParticle.h:63
void set_status(int status)
Set status code.
Stores run-related information.
Definition GenRunInfo.h:33
std::string version
The version of the tool.
Definition GenRunInfo.h:44
void add_attribute(const std::string &name, const std::shared_ptr< Attribute > &att)
add an attribute This will overwrite existing attribute if an attribute with the same name is present
Definition GenRunInfo.h:102
void read_data(const GenRunInfoData &data)
Fill GenRunInfo based on GenRunInfoData.
bool has_weight(const std::string &name) const
Check if a weight name is present.
Definition GenRunInfo.h:72
void set_weight_names(const std::vector< std::string > &names)
Set the names of the weights in this run.
GenRunInfo & operator=(const GenRunInfo &r)
Assignmet.
const std::vector< std::string > & weight_names() const
Get the vector of weight names.
Definition GenRunInfo.h:89
std::map< std::string, std::shared_ptr< Attribute > > attributes() const
Get a copy of the list of attributes.
Definition GenRunInfo.h:126
std::string description
Other information about how the tool was used in the run.
Definition GenRunInfo.h:48
const std::vector< ToolInfo > & tools() const
The vector of tools used to produce this run.
Definition GenRunInfo.h:63
GenRunInfo()
Default constructor.
Definition GenRunInfo.h:54
std::string attribute_as_string(const std::string &name) const
Get attribute of any type as string.
std::string name
The name of the tool.
Definition GenRunInfo.h:41
void write_data(GenRunInfoData &data) const
Fill GenRunInfoData object.
std::vector< std::string > attribute_names() const
Get list of attribute names.
Interrnal struct for keeping track of tools.
Definition GenRunInfo.h:38
Stores vertex-related information.
Definition GenVertex.h:29
std::vector< std::string > attribute_names() const
Get list of names of attributes assigned to this particle.
GenEvent * parent_event()
Get parent event.
Definition GenVertex.h:56
int id() const
Definition GenVertex.h:67
void add_particle_in(GenParticlePtr p)
Add incoming particle.
std::string attribute_as_string(const std::string &name) const
Get attribute of any type as string.
void remove_attribute(const std::string &name)
Remove attribute.
void remove_particle_in(GenParticlePtr p)
Remove incoming particle.
const std::vector< GenParticlePtr > & particles_out()
Get list of outgoing particles.
Definition GenVertex.h:97
void set_position(const FourVector &new_pos)
Set vertex position.
bool has_set_position() const
Check if position of this vertex is set.
Definition GenVertex.h:109
bool add_attribute(const std::string &name, std::shared_ptr< Attribute > att)
Add event attribute to this vertex.
const FourVector & position() const
Get vertex position.
const std::vector< GenParticlePtr > & particles_in()
Get list of incoming particles.
Definition GenVertex.h:93
void add_particle_out(GenParticlePtr p)
Add outgoing particle.
GenVertex(const FourVector &position=FourVector::ZERO_VECTOR())
Default constructor.
void remove_particle_out(GenParticlePtr p)
Remove outgoing particle.
Attribute that holds an Integer implemented as an int.
Definition Attribute.h:157
static void content(std::ostream &os, const GenEvent &event)
Print content of all GenEvent containers.
static void line(std::ostream &os, const GenEvent &event, bool attributes=false)
Print one-line info.
static void listing(std::ostream &os, const GenEvent &event, unsigned short precision=2)
Print event in listing (HepMC2) format.
ReaderAscii(const std::string &filename)
Constructor.
bool failed() override
Return status of the stream.
bool skip(const int) override
skip events
bool read_event(GenEvent &evt) override
Load event from file.
void close() override
Close file stream.
~ReaderAscii()
Destructor.
virtual std::shared_ptr< GenRunInfo > run_info() const
Get the global GenRunInfo object.
Definition Reader.h:44
virtual void set_run_info(std::shared_ptr< GenRunInfo > run)
Set the global GenRunInfo object.
Definition Reader.h:56
static int errors_level()
Get error messages printing level.
static const unsigned int DEFAULT_DOUBLE_ALMOST_EQUAL_MAXULPS
Default maxUlps for AlmostEqual2sComplement function (double precision)
Definition Setup.h:67
static int debug_level()
Get debug level.
static void set_debug_level(const int level)
Set debug level.
static bool print_warnings()
Get warning messages printing flag.
static void set_errors_level(const int flag)
set error messages printing level
static int warnings_level()
Get warning messages printing level.
static void set_print_errors(const bool flag)
set error messages printing flag
static void set_print_warnings(const bool flag)
Set warning messages printing flag.
static bool print_errors()
Get error messages printing flag.
static void set_warnings_level(const int flag)
Set warning messages printing level.
static const double DOUBLE_EPSILON
Default threshold for comparing double variables.
Definition Setup.h:70
LengthUnit
Position units.
Definition Units.h:32
static MomentumUnit momentum_unit(const std::string &name)
Get momentum unit based on its name.
Definition Units.h:36
static std::string name(MomentumUnit u)
Get name of momentum unit.
Definition Units.h:56
static LengthUnit length_unit(const std::string &name)
Get length unit based on its name.
Definition Units.h:46
MomentumUnit
Momentum units.
Definition Units.h:29
static void convert(T &m, MomentumUnit from, MomentumUnit to)
Convert FourVector to different momentum unit.
Definition Units.h:81
bool failed() override
Return status of the stream.
int precision() const
Return output precision.
~WriterAscii()
Destructor.
void write_event(const GenEvent &evt) override
Write event to file.
WriterAscii(const std::string &filename, std::shared_ptr< GenRunInfo > run=std::shared_ptr< GenRunInfo >())
Constructor.
void close() override
Close file stream.
void write_run_info()
Write the GenRunInfo object to file.
void set_precision(const int &prec)
Set output precision.
std::map< std::string, std::string > m_options
options
Definition Writer.h:59
virtual std::shared_ptr< GenRunInfo > run_info() const
Get the global GenRunInfo object.
Definition Writer.h:45
virtual void set_run_info(std::shared_ptr< GenRunInfo > run)
Set the global GenRunInfo object.
Definition Writer.h:42
Stores serializable event information.
std::vector< int > links2
Second id of the vertex links.
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.
FourVector event_pos
Event position.
int event_number
Event number.
std::vector< int > attribute_id
Attribute owner id.
Units::LengthUnit length_unit
Length unit.
std::vector< GenVertexData > vertices
Vertices.
std::vector< double > weights
Weights.
Units::MomentumUnit momentum_unit
Momentum unit.
Stores serializable particle information.
Stores serializable run information.
std::vector< std::string > weight_names
Weight names.
std::vector< std::string > tool_name
Tool names.
std::vector< std::string > attribute_string
Attribute serialized as string.
std::vector< std::string > tool_version
Tool versions.
std::vector< std::string > tool_description
Tool descriptions.
std::vector< std::string > attribute_name
Attribute name.
Stores serializable vertex information.