HepMC3 event record library
ReaderAsciiHepMC2.cc
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
5//
6/**
7 * @file ReaderAsciiHepMC2.cc
8 * @brief Implementation of \b class ReaderAsciiHepMC2
9 *
10 */
11#include <array>
12#include <cstdlib>
13#include <cstring>
14
15#include "HepMC3/GenEvent.h"
16#include "HepMC3/GenHeavyIon.h"
17#include "HepMC3/GenParticle.h"
18#include "HepMC3/GenPdfInfo.h"
19#include "HepMC3/GenVertex.h"
21#include "HepMC3/Setup.h"
22
23namespace HepMC3 {
24
25ReaderAsciiHepMC2::ReaderAsciiHepMC2(const std::string& filename):
26 m_file(filename), m_isstream(false) {
27 if ( !m_file.is_open() ) {
28 HEPMC3_ERROR_LEVEL(100,"ReaderAsciiHepMC2: could not open input file: " << filename )
29 }
30 set_run_info(std::make_shared<GenRunInfo>());
31 m_event_ghost = new GenEvent();
32}
33
35 : m_stream(&stream), m_isstream(true)
36{
37 if ( !m_stream->good() ) {
38 HEPMC3_ERROR_LEVEL(100,"ReaderAsciiHepMC2: could not open input stream ")
39 }
40 set_run_info(std::make_shared<GenRunInfo>());
41 m_event_ghost = new GenEvent();
42}
43
44ReaderAsciiHepMC2::ReaderAsciiHepMC2(std::shared_ptr<std::istream> s_stream)
45 : m_shared_stream(s_stream), m_stream(s_stream.get()), m_isstream(true)
46{
47 if ( !m_stream->good() ) {
48 HEPMC3_ERROR_LEVEL(100,"ReaderAsciiHepMC2: could not open input stream ")
49 }
50 set_run_info(std::make_shared<GenRunInfo>());
51 m_event_ghost = new GenEvent();
52}
53
54
56
57bool ReaderAsciiHepMC2::skip(const int n)
58{
59 std::array<char, 262144> buf{};
60 int nn = n;
61 while (!failed()) {
62 char peek(0);
63 if ( (!m_file.is_open()) && (!m_isstream) ) return false;
64 m_isstream ? peek = m_stream->peek() : peek = m_file.peek();
65 if ( peek =='E' ) nn--;
66 if (nn < 0) { return true; }
67 m_isstream ? m_stream->getline(buf.data(), buf.size()) : m_file.getline(buf.data(), buf.size());
68 }
69 return true;
70}
71
73 if ( (!m_file.is_open()) && (!m_isstream) ) return false;
74
75 char peek = 0;
76 std::array<char, 262144> buf{};
77 bool parsed_event_header = false;
78 bool is_parsing_successful = true;
79 int parsing_result = 0;
80 unsigned int vertices_count = 0;
81 unsigned int current_vertex_particles_count = 0;
82 unsigned int current_vertex_particles_parsed = 0;
83
84 evt.clear();
86
87 // Empty cache
88 m_vertex_cache.clear();
89 m_vertex_barcodes.clear();
90
91 m_particle_cache.clear();
95 //
96 // Parse event, vertex and particle information
97 //
98 while (!failed()) {
99 m_isstream ? m_stream->getline(buf.data(), buf.size()) : m_file.getline(buf.data(), buf.size());
100 if ( strlen(buf.data()) == 0 ) continue;
101 // Check for IO_GenEvent header/footer
102 if ( strncmp(buf.data(), "HepMC", 5) == 0 ) {
103 if ( strncmp(buf.data(), "HepMC::Version", 14) != 0 && strncmp(buf.data(), "HepMC::IO_GenEvent", 18) != 0 )
104 {
105 HEPMC3_WARNING_LEVEL(500,"ReaderAsciiHepMC2: found unsupported expression in header. Will close the input.")
106 std::cout <<buf.data() << std::endl;
107 m_isstream ? m_stream->clear(std::ios::eofbit) : m_file.clear(std::ios::eofbit);
108 }
109 if (parsed_event_header) {
110 is_parsing_successful = true;
111 break;
112 }
113 continue;
114 }
115 switch (buf[0]) {
116 case 'E':
117 parsing_result = parse_event_information(evt, buf.data());
118 if (parsing_result < 0) {
119 is_parsing_successful = false;
120 HEPMC3_ERROR_LEVEL(600,"ReaderAsciiHepMC2: HEPMC3_ERROR parsing event information")
121 }
122 else {
123 vertices_count = parsing_result;
124 m_vertex_cache.reserve(vertices_count);
125 m_particle_cache.reserve(vertices_count*3);
126 m_vertex_cache_ghost.reserve(vertices_count);
127 m_particle_cache_ghost.reserve(vertices_count*3);
128 m_vertex_barcodes.reserve(vertices_count);
129 m_end_vertex_barcodes.reserve(vertices_count*3);
130 // Here we make a trick: reserve for this event the vertices_count*3 or the number of particles in the prev. event.
131 evt.reserve(vertices_count, m_particle_cache_ghost.capacity());
132 is_parsing_successful = true;
133 }
134 parsed_event_header = true;
135 break;
136 case 'V':
137 // If starting new vertex: verify if previous was fully parsed
138
139 /** HepMC2 files produced with Pythia8 are known to have wrong
140 information about number of particles in vertex. Hence '<' sign */
141 if (current_vertex_particles_parsed < current_vertex_particles_count) {
142 is_parsing_successful = false;
143 break;
144 }
145 current_vertex_particles_parsed = 0;
146
147 parsing_result = parse_vertex_information(buf.data());
148
149 if (parsing_result < 0) {
150 is_parsing_successful = false;
151 HEPMC3_ERROR_LEVEL(600,"ReaderAsciiHepMC2: HEPMC3_ERROR parsing vertex information")
152 }
153 else {
154 current_vertex_particles_count = parsing_result;
155 is_parsing_successful = true;
156 }
157 break;
158 case 'P':
159
160 parsing_result = parse_particle_information(buf.data());
161
162 if (parsing_result < 0) {
163 is_parsing_successful = false;
164 HEPMC3_ERROR_LEVEL(600,"ReaderAsciiHepMC2: HEPMC3_ERROR parsing particle information")
165 }
166 else {
167 ++current_vertex_particles_parsed;
168 is_parsing_successful = true;
169 }
170 break;
171 case 'U':
172 is_parsing_successful = parse_units(evt, buf.data());
173 break;
174 case 'F':
175 is_parsing_successful = parse_pdf_info(evt, buf.data());
176 break;
177 case 'H':
178 is_parsing_successful = parse_heavy_ion(evt, buf.data());
179 break;
180 case 'N':
181 is_parsing_successful = parse_weight_names(buf.data());
182 break;
183 case 'C':
184 is_parsing_successful = parse_xs_info(evt, buf.data());
185 break;
186 default:
187 HEPMC3_WARNING_LEVEL(500,"ReaderAsciiHepMC2: skipping unrecognised prefix: " << buf[0])
188 is_parsing_successful = true;
189 break;
190 }
191
192 if ( !is_parsing_successful ) break;
193
194 // Check for next event
195 m_isstream ? peek = m_stream->peek() : peek = m_file.peek();
196 if ( parsed_event_header && peek == 'E' ) break;
197 }
198
199 // Check if all particles in last vertex were parsed
200 /** HepMC2 files produced with Pythia8 are known to have wrong
201 information about number of particles in vertex. Hence '<' sign */
202 if (is_parsing_successful && current_vertex_particles_parsed < current_vertex_particles_count) {
203 HEPMC3_ERROR_LEVEL(600,"ReaderAsciiHepMC2: not all particles parsed")
204 is_parsing_successful = false;
205 }
206 // Check if all vertices were parsed
207 else if (is_parsing_successful && m_vertex_cache.size() != vertices_count) {
208 HEPMC3_ERROR_LEVEL(600,"ReaderAsciiHepMC2: not all vertices parsed")
209 is_parsing_successful = false;
210 }
211
212 if ( !is_parsing_successful ) {
213 HEPMC3_ERROR_LEVEL(600,"ReaderAsciiHepMC2: event parsing failed. Returning empty event")
214 HEPMC3_DEBUG(1, "Parsing failed at line:" << std::endl << buf.data())
215 evt.clear();
216 m_isstream ? m_stream->clear(std::ios::badbit) : m_file.clear(std::ios::badbit);
217 return false;
218 }
219 if (run_info() && run_info()->weight_names().empty() ) {
220 run_info()->set_weight_names(std::vector<std::string> {"Default"});
221 }
222 if (evt.weights().empty()) {
223 HEPMC3_WARNING_LEVEL(600,"ReaderAsciiHepMC2: weights are empty, an event weight 1.0 will be added.")
224 evt.weights().push_back(1.0);
225 }
226
227 // Restore production vertex pointers
228 for (unsigned int i = 0; i < m_particle_cache.size(); ++i) {
229 if ( !m_end_vertex_barcodes[i] ) continue;
230
231 for (unsigned int j = 0; j < m_vertex_cache.size(); ++j) {
233 m_vertex_cache[j]->add_particle_in(m_particle_cache[i]);
234 break;
235 }
236 }
237 }
238
239 // Remove vertices with no incoming particles or no outgoing particles
240 for (unsigned int i = 0; i < m_vertex_cache.size(); ++i) {
241 if ( m_vertex_cache[i]->particles_in().empty() ) {
242 HEPMC3_DEBUG(30, "ReaderAsciiHepMC2::read_event - found a vertex without incoming particles: " << m_vertex_cache[i]->id() );
243 //Sometimes the root vertex has no incoming particles. Here we try to save the event.
244 std::vector<GenParticlePtr> beams;
245 beams.reserve(2);
246 for (const auto& p: m_vertex_cache[i]->particles_out()) if (p->status() == 4 && !(p->end_vertex())) beams.emplace_back(p);
247 for (auto& p: beams)
248 {
249 m_vertex_cache[i]->add_particle_in(p);
250 m_vertex_cache[i]->remove_particle_out(p);
251 HEPMC3_DEBUG(30, "ReaderAsciiHepMC2::read_event - moved particle with status=4 from the outgoing to the incoming particles of vertex: " << m_vertex_cache[i]->id());
252 }
253 if (beams.empty()) {
254 HEPMC3_DEBUG(30, "ReaderAsciiHepMC2::read_event - removed vertex without incoming particles: " << m_vertex_cache[i]->id() );
255 m_vertex_cache[i] = nullptr;
256 }
257 }
258 else if ( m_vertex_cache[i]->particles_out().empty() ) {
259 m_vertex_cache[i] = nullptr;
260 HEPMC3_DEBUG(30, "ReaderAsciiHepMC2::read_event - removed vertex without outgoing particles: " << m_vertex_cache[i]->id());
261 }
262 }
263
264 // Reserve memory for the event
265 evt.reserve(m_particle_cache.size(), m_vertex_cache.size());
266
267 // Add whole event tree in topological order
269
270 if (m_options.count("event_random_states_are_separated") != 0)
271 {
272 std::shared_ptr<VectorLongIntAttribute> random_states_a = evt.attribute<VectorLongIntAttribute>("random_states");
273 if (random_states_a) {
274 std::vector<long int> random_states_v = random_states_a->value();
275 for (size_t i = 0; i < random_states_v.size(); ++i ) {
276 evt.add_attribute("random_states" + std::to_string(static_cast<long long unsigned int>(i)), std::make_shared<IntAttribute>(random_states_v[i]));
277 }
278 evt.remove_attribute("random_states");
279 }
280
281 }
282
283 std::map< std::string, std::map<int, std::shared_ptr<Attribute> > > cached_attributes = m_event_ghost->attributes();
284 if (cached_attributes.count("flows") != 0) {
285 const std::map<int, std::shared_ptr<Attribute> >& flows = cached_attributes.at("flows");
286 if (m_options.count("particle_flows_are_separated") == 0) {
287 for (const auto& f: flows) if (f.first > 0 && f.first <= static_cast<int>(m_particle_cache.size())) { m_particle_cache[f.first-1]->add_attribute("flows", f.second);}
288 } else {
289 for (const auto& f: flows) {
290 if (f.first > 0 && f.first <= static_cast<int>(m_particle_cache.size())) {
291 std::shared_ptr<VectorIntAttribute> casted = std::dynamic_pointer_cast<VectorIntAttribute>(f.second);
292 if (!casted) continue;//Should not happen
293 std::vector<int> this_p_flow = casted->value();
294 for (size_t i = 0; i<this_p_flow.size(); i++) m_particle_cache[f.first-1]->add_attribute("flow" + std::to_string(i + 1), std::make_shared<IntAttribute>(this_p_flow[i]));
295 }
296 }
297 }
298 }
299
300 if (cached_attributes.count("phi") != 0) {
301 const std::map<int, std::shared_ptr<Attribute> >& phi = cached_attributes.at("phi");
302 for (const auto& f: phi) if (f.first > 0 &&f.first <= static_cast<int>(m_particle_cache.size())) m_particle_cache[f.first-1]->add_attribute("phi", f.second);
303 }
304
305 if (cached_attributes.count("theta") != 0) {
306 const std::map<int, std::shared_ptr<Attribute> >& theta = cached_attributes.at("theta");
307 for (const auto& f: theta) if (f.first > 0 && f.first <= static_cast<int>(m_particle_cache.size())) m_particle_cache[f.first-1]->add_attribute("theta", f.second);
308 }
309
310 if (cached_attributes.count("weights") != 0) {
311 const std::map<int, std::shared_ptr<Attribute> >& weights = cached_attributes.at("weights");
312 if (m_options.count("vertex_weights_are_separated") == 0) {
313 for (const auto& f: weights) { if (f.first < 0 && f.first >= -static_cast<int>(m_vertex_cache.size())) m_vertex_cache[-f.first-1]->add_attribute("weights", f.second);}
314 } else {
315 for (const auto& f: weights) {
316 if (f.first < 0 && f.first >= -static_cast<int>(m_vertex_cache.size())) {
317 std::shared_ptr<VectorDoubleAttribute> casted = std::dynamic_pointer_cast<VectorDoubleAttribute>(f.second);
318 if (!casted) continue;//Should not happen
319 std::vector<double> this_v_weight = casted->value();
320 for (size_t i = 0; i < this_v_weight.size(); i++) m_particle_cache[-f.first-1]->add_attribute("weight"+std::to_string(i), std::make_shared<DoubleAttribute>(this_v_weight[i]));
321 }
322 }
323 }
324 }
325 std::shared_ptr<IntAttribute> signal_process_vertex_barcode = evt.attribute<IntAttribute>("signal_process_vertex");
326 if (signal_process_vertex_barcode) {
327 int signal_process_vertex_barcode_value = signal_process_vertex_barcode->value();
328 for (unsigned int i = 0; i < m_vertex_cache.size(); ++i)
329 {
330 if (i >= m_vertex_barcodes.size()) continue;//this should not happen!
331 if (signal_process_vertex_barcode_value != m_vertex_barcodes.at(i)) continue;
332 std::shared_ptr<IntAttribute> signal_process_vertex = std::make_shared<IntAttribute>(m_vertex_cache.at(i)->id());
333 evt.add_attribute("signal_process_vertex", signal_process_vertex);
334 break;
335 }
336 }
338 m_vertex_cache_ghost.clear();
339 m_event_ghost->clear();
340 return true;
341}
342
344 const char *cursor = buf;
345 size_t vertices_count = 0;
346 int random_states_size = 0;
347 int weights_size = 0;
348 std::vector<long> random_states(0);
349 std::vector<double> weights(0);
350
351 // event number
352 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
353 evt.set_event_number(atoi(cursor));
354
355 //mpi
356 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
357 evt.add_attribute("mpi", std::make_shared<IntAttribute>(atoi(cursor)));
358
359 //event scale
360 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
361 evt.add_attribute("event_scale", std::make_shared<DoubleAttribute>(atof(cursor)));
362
363 //alpha_qcd
364 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
365 evt.add_attribute("alphaQCD", std::make_shared<DoubleAttribute>(atof(cursor)));
366
367 //alpha_qed
368 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
369 evt.add_attribute("alphaQED", std::make_shared<DoubleAttribute>(atof(cursor)));
370
371 //signal_process_id
372 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
373 evt.add_attribute("signal_process_id", std::make_shared<IntAttribute>(atoi(cursor)));
374
375 //signal_process_vertex
376 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
377 evt.add_attribute("signal_process_vertex", std::make_shared<IntAttribute>(atoi(cursor)));
378
379 // num_vertices
380 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
381 vertices_count = atoi(cursor);
382
383 // SKIPPED: beam 1
384 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
385
386 // SKIPPED: beam 2
387 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
388
389 //random states
390 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
391 random_states_size = atoi(cursor);
392 if (random_states_size >= 0 ) {
393 random_states.resize(random_states_size);
394 } else {
395 HEPMC3_DEBUG(0, "ReaderAsciiHepMC2: E: " << evt.event_number() << " (" << vertices_count << "V, " << random_states_size << "RS)")
396 }
397 for ( int i = 0; i < random_states_size; ++i ) {
398 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
399 random_states[i] = atoi(cursor);
400 }
401
402 if (!random_states.empty()) evt.add_attribute("random_states", std::make_shared<VectorLongIntAttribute>(random_states));
403
404 // weights
405 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
406 weights_size = atoi(cursor);
407 if (weights_size >= 0 ) {
408 weights.resize(weights_size);
409 } else {
410 HEPMC3_DEBUG(0, "ReaderAsciiHepMC2: E: " << evt.event_number() << " (" << vertices_count << "V, " << weights_size << "WS)")
411 }
412 for ( int i = 0; i < weights_size; ++i ) {
413 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
414 weights[i] = atof(cursor);
415 }
416
417 evt.weights() = weights;
418
419 HEPMC3_DEBUG(10, "ReaderAsciiHepMC2: E: " << evt.event_number() << " (" << vertices_count << "V, " << weights_size << "W, " << random_states_size << "RS)")
420
421 return vertices_count;
422}
423
424bool ReaderAsciiHepMC2::parse_units(GenEvent &evt, const char *buf) {
425 const char *cursor = buf;
426
427 // momentum
428 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
429 ++cursor;
430 Units::MomentumUnit momentum_unit = Units::momentum_unit(cursor);
431
432 // length
433 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
434 ++cursor;
435 Units::LengthUnit length_unit = Units::length_unit(cursor);
436
437 evt.set_units(momentum_unit, length_unit);
438
439 HEPMC3_DEBUG(10, "ReaderAsciiHepMC2: U: " << Units::name(evt.momentum_unit()) << " " << Units::name(evt.length_unit()))
440
441 return true;
442}
443
445 GenVertexPtr data = std::make_shared<GenVertex>();
446 GenVertexPtr data_ghost = std::make_shared<GenVertex>();
447 const char *cursor = buf;
448 int barcode = 0;
449 int num_particles_out = 0;
450 int weights_size = 0;
451 std::vector<double> weights(0);
452 // barcode
453 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
454 barcode = atoi(cursor);
455
456 // status
457 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
458 data->set_status(atoi(cursor));
459
460 // x
461 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
462 double X(atof(cursor));
463
464 // y
465 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
466 double Y(atof(cursor));
467
468 // z
469 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
470 double Z(atof(cursor));
471
472 // t
473 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
474 double T(atof(cursor));
475 data->set_position(FourVector(X,Y,Z,T));
476
477 // SKIPPED: num_orphans_in
478 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
479
480 // num_particles_out
481 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
482 num_particles_out = atoi(cursor);
483
484 // weights
485 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
486 weights_size = atoi(cursor);
487 weights.resize(weights_size);
488
489 for ( int i = 0; i < weights_size; ++i ) {
490 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
491 weights[i] = atof(cursor);
492 }
493
494
495
496 // Add original vertex barcode to the cache
497 m_vertex_cache.emplace_back(data);
498 m_vertex_barcodes.emplace_back(barcode);
499
500 m_event_ghost->add_vertex(data_ghost);
501
502 if (!weights.empty()) data_ghost->add_attribute("weights", std::make_shared<VectorDoubleAttribute>(weights));
503
504 m_vertex_cache_ghost.emplace_back(data_ghost);
505
506 HEPMC3_DEBUG(10, "ReaderAsciiHepMC2: V: " << -static_cast<int>(m_vertex_cache.size()) << " (old barcode " << barcode << ") " << num_particles_out << " particles)")
507
508 return num_particles_out;
509}
510
512 GenParticlePtr data = std::make_shared<GenParticle>();
513 GenParticlePtr data_ghost = std::make_shared<GenParticle>();
514 m_event_ghost->add_particle(data_ghost);
515 const char *cursor = buf;
516 int end_vtx = 0;
517
518 /// @note barcode is ignored
519 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
520
521 // id
522 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
523 data->set_pid(atoi(cursor));
524
525 // px
526 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
527 double Px(atof(cursor));
528
529 // py
530 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
531 double Py(atof(cursor));
532
533 // pz
534 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
535 double Pz(atof(cursor));
536
537 // pe
538 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
539 double E(atof(cursor));
540 data->set_momentum(FourVector(Px,Py,Pz,E));
541
542 // m
543 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
544 data->set_generated_mass(atof(cursor));
545
546 // status
547 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
548 data->set_status(atoi(cursor));
549
550 //theta
551 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
552 double theta_v = atof(cursor);
553 if (theta_v != 0.0) data_ghost->add_attribute("theta", std::make_shared<DoubleAttribute>(theta_v));
554
555 //phi
556 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
557 double phi_v = atof(cursor);
558 if (phi_v != 0.0) data_ghost->add_attribute("phi", std::make_shared<DoubleAttribute>(phi_v));
559
560 // end_vtx_code
561 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
562 end_vtx = atoi(cursor);
563
564 //flow
565 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
566 int flowsize = atoi(cursor);
567
568 std::map<int, int> flows;
569 for (int i = 0; i < flowsize; i++)
570 {
571 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
572 int flowindex = atoi(cursor);
573 if ( !(cursor = strchr(cursor+1, ' ')) ) return -1;
574 int flowvalue = atoi(cursor);
575 flows[flowindex] = flowvalue;
576 }
577 if (flowsize)
578 {
579 std::vector<int> vectorflows;
580 vectorflows.reserve(flows.size());
581 for (const auto& f: flows) { vectorflows.emplace_back(f.second); }
582 data_ghost->add_attribute("flows", std::make_shared<VectorIntAttribute>(vectorflows));
583 }
584 // Set prod_vtx link
585 if (m_vertex_cache.empty()) {HEPMC3_DEBUG(1, "The first particle in event appears before the first vertex"); return -1;}
586 if ( end_vtx == m_vertex_barcodes.back() ) {
587 m_vertex_cache.back()->add_particle_in(data);
588 end_vtx = 0;
589 }
590 else {
591 m_vertex_cache.back()->add_particle_out(data);
592 }
593
594 m_particle_cache.emplace_back(data);
595 m_particle_cache_ghost.emplace_back(data_ghost);
596 m_end_vertex_barcodes.emplace_back(end_vtx);
597
598 HEPMC3_DEBUG(10, "ReaderAsciiHepMC2: P: " << m_particle_cache.size() << " ( pid: " << data->pid() << ") end vertex: " << end_vtx)
599
600 return 0;
601}
602
603bool ReaderAsciiHepMC2::parse_xs_info(GenEvent &evt, const char *buf) {
604 const char *cursor = buf;
605 std::shared_ptr<GenCrossSection> xs = std::make_shared<GenCrossSection>();
606
607 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
608 const double xs_val = atof(cursor);
609
610 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
611 const double xs_err = atof(cursor);
612 const size_t all = m_options.count("disable_pad_cross_sections") ? size_t{1} :
613 std::max(evt.weights().size(),size_t{1});
614 const double xs_val_dummy = m_options.count("pad_cross_section_value") ? std::strtod(m_options.at("pad_cross_section_value").c_str(),nullptr) : 0.0;
615 const double xs_err_dummy = m_options.count("pad_cross_section_error") ? std::strtod(m_options.at("pad_cross_section_error").c_str(),nullptr) : 0.0;
616 xs->set_cross_section(std::vector<double>(all,xs_val_dummy), std::vector<double>(all,xs_err_dummy));
617 xs->set_xsec(0,xs_val);
618 xs->set_xsec_err(0,xs_err);
619 evt.add_attribute("GenCrossSection", xs);
620 return true;
621}
622
624 const char *cursor = buf;
625 const char *cursor2 = buf;
626 int w_count = 0;
627 std::vector<std::string> w_names;
628
629 // Ignore weight names if no GenRunInfo object
630 if ( !run_info() ) return true;
631
632 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
633 w_count = atoi(cursor);
634
635 if ( w_count <= 0 ) return false;
636
637 w_names.resize(w_count);
638
639 for ( int i=0; i < w_count; ++i ) {
640 // Find pair of '"' characters
641 if ( !(cursor = strchr(cursor+1, '"')) ) return false;
642 if ( !(cursor2 = strchr(cursor+1, '"')) ) return false;
643
644 // Strip cursor of leading '"' character
645 ++cursor;
646
647 w_names[i].assign(cursor, cursor2-cursor);
648
649 cursor = cursor2;
650 }
651
652 run_info()->set_weight_names(w_names);
653
654 return true;
655}
656
657bool ReaderAsciiHepMC2::parse_heavy_ion(GenEvent &evt, const char *buf) {
658 std::shared_ptr<GenHeavyIon> hi = std::make_shared<GenHeavyIon>();
659 const char *cursor = buf;
660
661 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
662 hi->Ncoll_hard = atoi(cursor);
663
664 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
665 hi->Npart_proj = atoi(cursor);
666
667 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
668 hi->Npart_targ = atoi(cursor);
669
670 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
671 hi->Ncoll = atoi(cursor);
672
673 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
674 hi->spectator_neutrons = atoi(cursor);
675
676 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
677 hi->spectator_protons = atoi(cursor);
678
679 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
680 hi->N_Nwounded_collisions = atoi(cursor);
681
682 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
683 hi->Nwounded_N_collisions = atoi(cursor);
684
685 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
686 hi->Nwounded_Nwounded_collisions = atoi(cursor);
687
688 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
689 hi->impact_parameter = atof(cursor);
690
691 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
692 hi->event_plane_angle = atof(cursor);
693
694 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
695 hi->eccentricity = atof(cursor);
696
697 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
698 hi->sigma_inel_NN = atof(cursor);
699
700 // Not in HepMC2:
701 hi->centrality = 0.0;
702
703 evt.add_attribute("GenHeavyIon", hi);
704
705 return true;
706}
707
708bool ReaderAsciiHepMC2::parse_pdf_info(GenEvent &evt, const char *buf) {
709 std::shared_ptr<GenPdfInfo> pi = std::make_shared<GenPdfInfo>();
710 const char *cursor = buf;
711
712 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
713 pi->parton_id[0] = atoi(cursor);
714
715 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
716 pi->parton_id[1] = atoi(cursor);
717
718 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
719 pi->x[0] = atof(cursor);
720
721 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
722 pi->x[1] = atof(cursor);
723
724 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
725 pi->scale = atof(cursor);
726
727 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
728 pi->xf[0] = atof(cursor);
729
730 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
731 pi->xf[1] = atof(cursor);
732
733 //For compatibility with original HepMC2
734 bool pdfids = true;
735 if ( !(cursor = strchr(cursor+1, ' ')) ) pdfids = false;
736 if (pdfids) {pi->pdf_id[0] = atoi(cursor);}
737 else {pi->pdf_id[0] = 0;}
738
739 if (pdfids) if ( !(cursor = strchr(cursor+1, ' ')) ) pdfids = false;
740 if (pdfids) { pi->pdf_id[1] = atoi(cursor);}
741 else {pi->pdf_id[1] = 0;}
742
743 evt.add_attribute("GenPdfInfo", pi);
744
745 return true;
746}
747bool ReaderAsciiHepMC2::failed() { return m_isstream ? static_cast<bool>(m_stream->rdstate()) : static_cast<bool>(m_file.rdstate()); }
748
750 if (m_event_ghost) { m_event_ghost->clear(); delete m_event_ghost; m_event_ghost = nullptr;}
751 if ( !m_file.is_open() ) return;
752 m_file.close();
753}
754
755} // namespace HepMC3
#define HEPMC3_WARNING_LEVEL(LEVEL, MESSAGE)
Macro for printing HEPMC3_HEPMC3_WARNING messages.
Definition Errors.h:34
#define HEPMC3_ERROR_LEVEL(LEVEL, MESSAGE)
Macro for printing error messages.
Definition Errors.h:27
#define HEPMC3_DEBUG(LEVEL, MESSAGE)
Macro for printing debug messages with appropriate debug level.
Definition Errors.h:41
Definition of class GenEvent.
Definition of attribute class GenHeavyIon.
Definition of class GenParticle.
Definition of event attribute class GenPdfInfo.
Definition of class GenVertex.
Definition of class ReaderAsciiHepMC2.
Definition of class Setup.
Generic 4-vector.
Definition FourVector.h:36
Stores event-related information.
Definition GenEvent.h:47
std::shared_ptr< T > attribute(const std::string &name, const int &id=0) const
Get attribute of type T.
Definition GenEvent.h:420
int event_number() const
Get event number.
Definition GenEvent.h:155
void set_units(Units::MomentumUnit new_momentum_unit, Units::LengthUnit new_length_unit)
Change event units Converts event from current units to new ones.
Definition GenEvent.cc:397
void reserve(const size_t &parts, const size_t &verts=0)
Reserve memory for particles and vertices.
Definition GenEvent.cc:391
void set_event_number(const int &num)
Set event number.
Definition GenEvent.h:157
void set_run_info(std::shared_ptr< GenRunInfo > run)
Set the GenRunInfo object by smart pointer.
Definition GenEvent.h:148
const Units::MomentumUnit & momentum_unit() const
Get momentum unit.
Definition GenEvent.h:160
const Units::LengthUnit & length_unit() const
Get length unit.
Definition GenEvent.h:162
void add_attribute(const std::string &name, const std::shared_ptr< Attribute > &att, const int &id=0)
Definition GenEvent.cc:797
void remove_attribute(const std::string &name, const int &id=0)
Remove attribute.
Definition GenEvent.cc:602
const std::vector< double > & weights() const
Get event weight values as a vector.
Definition GenEvent.h:105
void clear()
Remove contents of this event.
Definition GenEvent.cc:592
void add_tree(const std::vector< GenParticlePtr > &parts)
Add whole tree in topological order.
Definition GenEvent.cc:268
Attribute that holds an Integer implemented as an int.
Definition Attribute.h:157
bool m_isstream
toggles usage of m_file or m_stream
bool read_event(GenEvent &evt) override
Implementation of Reader::read_event.
static int parse_event_information(GenEvent &evt, const char *buf)
Parse event.
std::vector< int > m_vertex_barcodes
Old vertex barcodes.
bool failed() override
Return status of the stream.
static bool parse_pdf_info(GenEvent &evt, const char *buf)
Parse pdf information.
bool skip(const int) override
skip events
std::ifstream m_file
Input file.
static bool parse_units(GenEvent &evt, const char *buf)
Parse units.
int parse_particle_information(const char *buf)
Parse particle.
std::vector< GenParticlePtr > m_particle_cache_ghost
Particle cache for attributes.
void close() override
Close file stream.
std::vector< GenVertexPtr > m_vertex_cache
Vertex cache.
ReaderAsciiHepMC2(const std::string &filename)
Default constructor.
std::vector< GenParticlePtr > m_particle_cache
Particle cache.
bool parse_weight_names(const char *buf)
Parse weight names.
bool parse_xs_info(GenEvent &evt, const char *buf)
Parse pdf information.
std::istream * m_stream
For ctor when reading from stream.
std::shared_ptr< std::istream > m_shared_stream
For ctor when reading from temp stream.
std::vector< GenVertexPtr > m_vertex_cache_ghost
Vertex cache for attributes.
int parse_vertex_information(const char *buf)
Parse vertex.
static bool parse_heavy_ion(GenEvent &evt, const char *buf)
Parse heavy ion information.
GenEvent * m_event_ghost
To save particle and verstex attributes.
std::vector< int > m_end_vertex_barcodes
Old end vertex barcodes.
virtual void set_run_info(std::shared_ptr< GenRunInfo > run)
Set the global GenRunInfo object.
Definition Reader.h:56
virtual std::shared_ptr< GenRunInfo > run_info() const
Get the global GenRunInfo object.
Definition Reader.h:44
std::map< std::string, std::string > m_options
Options.
Definition Reader.h:60
static LengthUnit length_unit(const std::string &name)
Get length unit based on its name.
Definition Units.h:46
LengthUnit
Position units.
Definition Units.h:32
static std::string name(MomentumUnit u)
Get name of momentum unit.
Definition Units.h:56
MomentumUnit
Momentum units.
Definition Units.h:29
static MomentumUnit momentum_unit(const std::string &name)
Get momentum unit based on its name.
Definition Units.h:36
Attribute that holds a vector of integers of type long int.
Definition Attribute.h:1087
HepMC3 main namespace.