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_stream(nullptr), m_isstream(false) {
27 if ( !m_file.is_open() ) {
28 HEPMC3_ERROR("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("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("ReaderAsciiHepMC2: could not open input stream ")
49 }
50 set_run_info(std::make_shared<GenRunInfo>());
51}
52
53
55
56bool ReaderAsciiHepMC2::skip(const int n)
57{
58 std::array<char, 262144> buf;
59 int nn = n;
60 while (!failed()) {
61 char peek(0);
62 if ( (!m_file.is_open()) && (!m_isstream) ) return false;
63 m_isstream ? peek = m_stream->peek() : peek = m_file.peek();
64 if ( peek =='E' ) nn--;
65 if (nn < 0) { return true; }
66 m_isstream ? m_stream->getline(buf.data(), buf.size()) : m_file.getline(buf.data(), buf.size());
67 }
68 return true;
69}
70
72 if ( (!m_file.is_open()) && (!m_isstream) ) return false;
73
74 char peek = 0;
75 std::array<char, 262144> buf;
76 bool parsed_event_header = false;
77 bool is_parsing_successful = true;
78 int parsing_result = 0;
79 unsigned int vertices_count = 0;
80 unsigned int current_vertex_particles_count = 0;
81 unsigned int current_vertex_particles_parsed = 0;
82
83 evt.clear();
85
86 // Empty cache
87 m_vertex_cache.clear();
88 m_vertex_barcodes.clear();
89
90 m_particle_cache.clear();
94 //
95 // Parse event, vertex and particle information
96 //
97 while (!failed()) {
98 m_isstream ? m_stream->getline(buf.data(), buf.size()) : m_file.getline(buf.data(), buf.size());
99 if ( strlen(buf.data()) == 0 ) continue;
100 // Check for IO_GenEvent header/footer
101 if ( strncmp(buf.data(), "HepMC", 5) == 0 ) {
102 if ( strncmp(buf.data(), "HepMC::Version", 14) != 0 && strncmp(buf.data(), "HepMC::IO_GenEvent", 18) != 0 )
103 {
104 HEPMC3_WARNING("ReaderAsciiHepMC2: found unsupported expression in header. Will close the input.")
105 std::cout <<buf.data() << std::endl;
106 m_isstream ? m_stream->clear(std::ios::eofbit) : m_file.clear(std::ios::eofbit);
107 }
108 if (parsed_event_header) {
109 is_parsing_successful = true;
110 break;
111 }
112 continue;
113 }
114 switch (buf[0]) {
115 case 'E':
116 parsing_result = parse_event_information(evt, buf.data());
117 if (parsing_result < 0) {
118 is_parsing_successful = false;
119 HEPMC3_ERROR("ReaderAsciiHepMC2: HEPMC3_ERROR parsing event information")
120 }
121 else {
122 vertices_count = parsing_result;
123 m_vertex_cache.reserve(vertices_count);
124 m_particle_cache.reserve(vertices_count*3);
125 m_vertex_cache_ghost.reserve(vertices_count);
126 m_particle_cache_ghost.reserve(vertices_count*3);
127 m_vertex_barcodes.reserve(vertices_count);
128 m_end_vertex_barcodes.reserve(vertices_count*3);
129 // Here we make a trick: reserve for this event the vertices_count*3 or the number of particles in the prev. event.
130 evt.reserve(vertices_count, m_particle_cache_ghost.capacity());
131 is_parsing_successful = true;
132 }
133 parsed_event_header = true;
134 break;
135 case 'V':
136 // If starting new vertex: verify if previous was fully parsed
137
138 /** @bug HepMC2 files produced with Pythia8 are known to have wrong
139 information about number of particles in vertex. Hence '<' sign */
140 if (current_vertex_particles_parsed < current_vertex_particles_count) {
141 is_parsing_successful = false;
142 break;
143 }
144 current_vertex_particles_parsed = 0;
145
146 parsing_result = parse_vertex_information(buf.data());
147
148 if (parsing_result < 0) {
149 is_parsing_successful = false;
150 HEPMC3_ERROR("ReaderAsciiHepMC2: HEPMC3_ERROR parsing vertex information")
151 }
152 else {
153 current_vertex_particles_count = parsing_result;
154 is_parsing_successful = true;
155 }
156 break;
157 case 'P':
158
159 parsing_result = parse_particle_information(buf.data());
160
161 if (parsing_result < 0) {
162 is_parsing_successful = false;
163 HEPMC3_ERROR("ReaderAsciiHepMC2: HEPMC3_ERROR parsing particle information")
164 }
165 else {
166 ++current_vertex_particles_parsed;
167 is_parsing_successful = true;
168 }
169 break;
170 case 'U':
171 is_parsing_successful = parse_units(evt, buf.data());
172 break;
173 case 'F':
174 is_parsing_successful = parse_pdf_info(evt, buf.data());
175 break;
176 case 'H':
177 is_parsing_successful = parse_heavy_ion(evt, buf.data());
178 break;
179 case 'N':
180 is_parsing_successful = parse_weight_names(buf.data());
181 break;
182 case 'C':
183 is_parsing_successful = parse_xs_info(evt, buf.data());
184 break;
185 default:
186 HEPMC3_WARNING("ReaderAsciiHepMC2: skipping unrecognised prefix: " << buf[0])
187 is_parsing_successful = true;
188 break;
189 }
190
191 if ( !is_parsing_successful ) break;
192
193 // Check for next event
194 m_isstream ? peek = m_stream->peek() : peek = m_file.peek();
195 if ( parsed_event_header && peek == 'E' ) break;
196 }
197
198 // Check if all particles in last vertex were parsed
199 /** @bug HepMC2 files produced with Pythia8 are known to have wrong
200 information about number of particles in vertex. Hence '<' sign */
201 if (is_parsing_successful && current_vertex_particles_parsed < current_vertex_particles_count) {
202 HEPMC3_ERROR("ReaderAsciiHepMC2: not all particles parsed")
203 is_parsing_successful = false;
204 }
205 // Check if all vertices were parsed
206 else if (is_parsing_successful && m_vertex_cache.size() != vertices_count) {
207 HEPMC3_ERROR("ReaderAsciiHepMC2: not all vertices parsed")
208 is_parsing_successful = false;
209 }
210
211 if ( !is_parsing_successful ) {
212 HEPMC3_ERROR("ReaderAsciiHepMC2: event parsing failed. Returning empty event")
213 HEPMC3_DEBUG(1, "Parsing failed at line:" << std::endl << buf.data())
214 evt.clear();
215 m_isstream ? m_stream->clear(std::ios::badbit) : m_file.clear(std::ios::badbit);
216 return false;
217 }
218 if (run_info() && run_info()->weight_names().empty() ) {
219 run_info()->set_weight_names(std::vector<std::string> {"Default"});
220 }
221 if (evt.weights().empty()) {
222 HEPMC3_WARNING("ReaderAsciiHepMC2: weights are empty, an event weight 1.0 will be added.")
223 evt.weights().push_back(1.0);
224 }
225
226 // Restore production vertex pointers
227 for (unsigned int i = 0; i < m_particle_cache.size(); ++i) {
228 if ( !m_end_vertex_barcodes[i] ) continue;
229
230 for (unsigned int j = 0; j < m_vertex_cache.size(); ++j) {
232 m_vertex_cache[j]->add_particle_in(m_particle_cache[i]);
233 break;
234 }
235 }
236 }
237
238 // Remove vertices with no incoming particles or no outgoing particles
239 for (unsigned int i = 0; i < m_vertex_cache.size(); ++i) {
240 if ( m_vertex_cache[i]->particles_in().empty() ) {
241 HEPMC3_DEBUG(30, "ReaderAsciiHepMC2::read_event - found a vertex without incoming particles: " << m_vertex_cache[i]->id() );
242 //Sometimes the root vertex has no incoming particles. Here we try to save the event.
243 std::vector<GenParticlePtr> beams;
244 beams.reserve(2);
245 for (const auto& p: m_vertex_cache[i]->particles_out()) if (p->status() == 4 && !(p->end_vertex())) beams.emplace_back(p);
246 for (auto& p: beams)
247 {
248 m_vertex_cache[i]->add_particle_in(p);
249 m_vertex_cache[i]->remove_particle_out(p);
250 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());
251 }
252 if (beams.empty()) {
253 HEPMC3_DEBUG(30, "ReaderAsciiHepMC2::read_event - removed vertex without incoming particles: " << m_vertex_cache[i]->id() );
254 m_vertex_cache[i] = nullptr;
255 }
256 }
257 else if ( m_vertex_cache[i]->particles_out().empty() ) {
258 m_vertex_cache[i] = nullptr;
259 HEPMC3_DEBUG(30, "ReaderAsciiHepMC2::read_event - removed vertex without outgoing particles: " << m_vertex_cache[i]->id());
260 }
261 }
262
263 // Reserve memory for the event
264 evt.reserve(m_particle_cache.size(), m_vertex_cache.size());
265
266 // Add whole event tree in topological order
268
269 if (m_options.count("event_random_states_are_separated") != 0)
270 {
271 std::shared_ptr<VectorLongIntAttribute> random_states_a = evt.attribute<VectorLongIntAttribute>("random_states");
272 if (random_states_a) {
273 std::vector<long int> random_states_v = random_states_a->value();
274 for (size_t i = 0; i < random_states_v.size(); ++i ) {
275 evt.add_attribute("random_states" + std::to_string((long long unsigned int)i), std::make_shared<IntAttribute>(random_states_v[i]));
276 }
277 evt.remove_attribute("random_states");
278 }
279
280 }
281
282 std::map< std::string, std::map<int, std::shared_ptr<Attribute> > > cached_attributes = m_event_ghost->attributes();
283 if (cached_attributes.count("flows") != 0) {
284 const std::map<int, std::shared_ptr<Attribute> >& flows = cached_attributes.at("flows");
285 if (m_options.count("particle_flows_are_separated") == 0) {
286 for (const auto& f: flows) if (f.first > 0 && f.first <= (int)m_particle_cache.size()) { m_particle_cache[f.first-1]->add_attribute("flows", f.second);}
287 } else {
288 for (const auto& f: flows) {
289 if (f.first > 0 && f.first <= (int)m_particle_cache.size()) {
290 std::shared_ptr<VectorIntAttribute> casted = std::dynamic_pointer_cast<VectorIntAttribute>(f.second);
291 if (!casted) continue;//Should not happen
292 std::vector<int> this_p_flow = casted->value();
293 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]));
294 }
295 }
296 }
297 }
298
299 if (cached_attributes.count("phi") != 0) {
300 const std::map<int, std::shared_ptr<Attribute> >& phi = cached_attributes.at("phi");
301 for (const auto& f: phi) if (f.first > 0 &&f.first <= (int)m_particle_cache.size()) m_particle_cache[f.first-1]->add_attribute("phi", f.second);
302 }
303
304 if (cached_attributes.count("theta") != 0) {
305 const std::map<int, std::shared_ptr<Attribute> >& theta = cached_attributes.at("theta");
306 for (const auto& f: theta) if (f.first > 0 && f.first <= (int)m_particle_cache.size()) m_particle_cache[f.first-1]->add_attribute("theta", f.second);
307 }
308
309 if (cached_attributes.count("weights") != 0) {
310 const std::map<int, std::shared_ptr<Attribute> >& weights = cached_attributes.at("weights");
311 if (m_options.count("vertex_weights_are_separated") == 0) {
312 for (const auto& f: weights) { if (f.first < 0 && f.first >= -(int)m_vertex_cache.size()) m_vertex_cache[-f.first-1]->add_attribute("weights", f.second);}
313 } else {
314 for (const auto& f: weights) {
315 if (f.first < 0 && f.first >= -(int)m_vertex_cache.size()) {
316 std::shared_ptr<VectorDoubleAttribute> casted = std::dynamic_pointer_cast<VectorDoubleAttribute>(f.second);
317 if (!casted) continue;//Should not happen
318 std::vector<double> this_v_weight = casted->value();
319 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]));
320 }
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();
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: " << -(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 ( end_vtx == m_vertex_barcodes.back() ) {
586 m_vertex_cache.back()->add_particle_in(data);
587 end_vtx = 0;
588 }
589 else {
590 m_vertex_cache.back()->add_particle_out(data);
591 }
592
593 m_particle_cache.emplace_back(data);
594 m_particle_cache_ghost.emplace_back(data_ghost);
595 m_end_vertex_barcodes.emplace_back(end_vtx);
596
597 HEPMC3_DEBUG(10, "ReaderAsciiHepMC2: P: " << m_particle_cache.size() << " ( pid: " << data->pid() << ") end vertex: " << end_vtx)
598
599 return 0;
600}
601
602bool ReaderAsciiHepMC2::parse_xs_info(GenEvent &evt, const char *buf) {
603 const char *cursor = buf;
604 std::shared_ptr<GenCrossSection> xs = std::make_shared<GenCrossSection>();
605
606 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
607 const double xs_val = atof(cursor);
608
609 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
610 const double xs_err = atof(cursor);
611 const size_t all = m_options.count("disable_pad_cross_sections") ? size_t{1} : std::max(evt.weights().size(),size_t{1});
612 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;
613 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;
614 xs->set_cross_section(std::vector<double>(all,xs_val_dummy), std::vector<double>(all,xs_err_dummy));
615 xs->set_xsec(0,xs_val);
616 xs->set_xsec_err(0,xs_err);
617 evt.add_attribute("GenCrossSection", xs);
618 return true;
619}
620
622 const char *cursor = buf;
623 const char *cursor2 = buf;
624 int w_count = 0;
625 std::vector<std::string> w_names;
626
627 // Ignore weight names if no GenRunInfo object
628 if ( !run_info() ) return true;
629
630 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
631 w_count = atoi(cursor);
632
633 if ( w_count <= 0 ) return false;
634
635 w_names.resize(w_count);
636
637 for ( int i=0; i < w_count; ++i ) {
638 // Find pair of '"' characters
639 if ( !(cursor = strchr(cursor+1, '"')) ) return false;
640 if ( !(cursor2 = strchr(cursor+1, '"')) ) return false;
641
642 // Strip cursor of leading '"' character
643 ++cursor;
644
645 w_names[i].assign(cursor, cursor2-cursor);
646
647 cursor = cursor2;
648 }
649
650 run_info()->set_weight_names(w_names);
651
652 return true;
653}
654
655bool ReaderAsciiHepMC2::parse_heavy_ion(GenEvent &evt, const char *buf) {
656 std::shared_ptr<GenHeavyIon> hi = std::make_shared<GenHeavyIon>();
657 const char *cursor = buf;
658
659 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
660 hi->Ncoll_hard = atoi(cursor);
661
662 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
663 hi->Npart_proj = atoi(cursor);
664
665 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
666 hi->Npart_targ = atoi(cursor);
667
668 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
669 hi->Ncoll = atoi(cursor);
670
671 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
672 hi->spectator_neutrons = atoi(cursor);
673
674 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
675 hi->spectator_protons = atoi(cursor);
676
677 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
678 hi->N_Nwounded_collisions = atoi(cursor);
679
680 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
681 hi->Nwounded_N_collisions = atoi(cursor);
682
683 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
684 hi->Nwounded_Nwounded_collisions = atoi(cursor);
685
686 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
687 hi->impact_parameter = atof(cursor);
688
689 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
690 hi->event_plane_angle = atof(cursor);
691
692 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
693 hi->eccentricity = atof(cursor);
694
695 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
696 hi->sigma_inel_NN = atof(cursor);
697
698 // Not in HepMC2:
699 hi->centrality = 0.0;
700
701 evt.add_attribute("GenHeavyIon", hi);
702
703 return true;
704}
705
706bool ReaderAsciiHepMC2::parse_pdf_info(GenEvent &evt, const char *buf) {
707 std::shared_ptr<GenPdfInfo> pi = std::make_shared<GenPdfInfo>();
708 const char *cursor = buf;
709
710 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
711 pi->parton_id[0] = atoi(cursor);
712
713 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
714 pi->parton_id[1] = atoi(cursor);
715
716 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
717 pi->x[0] = atof(cursor);
718
719 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
720 pi->x[1] = atof(cursor);
721
722 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
723 pi->scale = atof(cursor);
724
725 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
726 pi->xf[0] = atof(cursor);
727
728 if ( !(cursor = strchr(cursor+1, ' ')) ) return false;
729 pi->xf[1] = atof(cursor);
730
731 //For compatibility with original HepMC2
732 bool pdfids = true;
733 if ( !(cursor = strchr(cursor+1, ' ')) ) pdfids = false;
734 if (pdfids) {pi->pdf_id[0] = atoi(cursor);}
735 else {pi->pdf_id[0] = 0;}
736
737 if (pdfids) if ( !(cursor = strchr(cursor+1, ' ')) ) pdfids = false;
738 if (pdfids) { pi->pdf_id[1] = atoi(cursor);}
739 else {pi->pdf_id[1] = 0;}
740
741 evt.add_attribute("GenPdfInfo", pi);
742
743 return true;
744}
745bool ReaderAsciiHepMC2::failed() { return m_isstream ? (bool)m_stream->rdstate() :(bool)m_file.rdstate(); }
746
748 if (m_event_ghost) { m_event_ghost->clear(); delete m_event_ghost; m_event_ghost=nullptr;}
749 if ( !m_file.is_open() ) return;
750 m_file.close();
751}
752
753} // namespace HepMC3
#define HEPMC3_WARNING(MESSAGE)
Macro for printing HEPMC3_HEPMC3_WARNING messages.
Definition: Errors.h:27
#define HEPMC3_DEBUG(LEVEL, MESSAGE)
Macro for printing debug messages with appropriate debug level.
Definition: Errors.h:33
#define HEPMC3_ERROR(MESSAGE)
Macro for printing error messages.
Definition: Errors.h:24
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:41
std::shared_ptr< T > attribute(const std::string &name, const int &id=0) const
Get attribute of type T.
Definition: GenEvent.h:417
void add_vertex(GenVertexPtr v)
Add vertex.
Definition: GenEvent.cc:97
int event_number() const
Get event number.
Definition: GenEvent.h:148
void add_particle(GenParticlePtr p)
Add particle.
Definition: GenEvent.cc:48
void set_units(Units::MomentumUnit new_momentum_unit, Units::LengthUnit new_length_unit)
Change event units Converts event from current units to new ones.
Definition: GenEvent.cc:391
void reserve(const size_t &parts, const size_t &verts=0)
Reserve memory for particles and vertices.
Definition: GenEvent.cc:385
void set_event_number(const int &num)
Set event number.
Definition: GenEvent.h:150
void set_run_info(std::shared_ptr< GenRunInfo > run)
Set the GenRunInfo object by smart pointer.
Definition: GenEvent.h:141
const Units::MomentumUnit & momentum_unit() const
Get momentum unit.
Definition: GenEvent.h:153
const Units::LengthUnit & length_unit() const
Get length unit.
Definition: GenEvent.h:155
std::map< std::string, std::map< int, std::shared_ptr< Attribute > > > attributes() const
Get a copy of the list of attributes.
Definition: GenEvent.h:261
void add_attribute(const std::string &name, const std::shared_ptr< Attribute > &att, const int &id=0)
Definition: GenEvent.cc:810
void remove_attribute(const std::string &name, const int &id=0)
Remove attribute.
Definition: GenEvent.cc:608
const std::vector< double > & weights() const
Get event weight values as a vector.
Definition: GenEvent.h:98
void clear()
Remove contents of this event.
Definition: GenEvent.cc:598
void add_tree(const std::vector< GenParticlePtr > &parts)
Add whole tree in topological order.
Definition: GenEvent.cc:262
Attribute that holds an Integer implemented as an int.
Definition: Attribute.h:157
int value() const
get the value associated to this Attribute.
Definition: Attribute.h:180
bool m_isstream
toggles usage of m_file or m_stream
bool read_event(GenEvent &evt) override
Implementation of Reader::read_event.
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.
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.
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::vector< GenVertexPtr > m_vertex_cache_ghost
Vertex cache for attributes.
int parse_vertex_information(const char *buf)
Parse vertex.
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
std::vector< long int > value() const
get the value associated to this Attribute.
Definition: Attribute.h:1114
HepMC3 main namespace.