HepMC event record
ReaderAscii.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // This file is part of HepMC
4 // Copyright (C) 2014-2015 The HepMC collaboration (see AUTHORS for details)
5 //
6 ///
7 /// @file ReaderAscii.cc
8 /// @brief Implementation of \b class ReaderAscii
9 ///
10 #include "HepMC/ReaderAscii.h"
11 
12 #include "HepMC/GenEvent.h"
13 #include "HepMC/GenParticle.h"
14 #include "HepMC/GenVertex.h"
15 #include "HepMC/Units.h"
16 #include <cstring>
17 #include <sstream>
18 
19 namespace HepMC {
20 
21 
22 ReaderAscii::ReaderAscii(const string &filename)
23  : m_file(filename), m_stream(0), m_isstream(false)
24 {
25  if( !m_file.is_open() ) {
26  ERROR( "ReaderAscii: could not open input file: "<<filename )
27  }
28  set_run_info(make_shared<GenRunInfo>());
29 }
30 
31 
32 // Ctor for reading from stdin
33 ReaderAscii::ReaderAscii(std::istream & stream)
34  : m_stream(&stream), m_isstream(true)
35 {
36  if( !m_stream ) {
37  ERROR( "ReaderAscii: could not open input stream " )
38  }
39  set_run_info(make_shared<GenRunInfo>());
40 }
41 
42 
43 
44 ReaderAscii::~ReaderAscii() { if (!m_isstream) close(); }
45 
46 
48  if ( !m_file.is_open() &! m_isstream ) return false;
49 
50  char peek;
51  char buf[512*512];
52  bool parsed_event_header = false;
53  bool is_parsing_successful = true;
54  pair<int,int> vertices_and_particles(0,0);
55 
56  evt.clear();
57  evt.set_run_info(run_info());
58 
59  //
60  // Parse event, vertex and particle information
61  //
62  while(!failed()) {
63 
64  m_isstream ? m_stream->getline(buf,512*512) : m_file.getline(buf,512*512);
65 
66  if( strlen(buf) == 0 ) continue;
67 
68  // Check for ReaderAscii header/footer
69  if( strncmp(buf,"HepMC",5) == 0 ) {
70  if(parsed_event_header) {
71  is_parsing_successful = true;
72  break;
73  }
74  continue;
75  }
76 
77  switch(buf[0]) {
78  /// @todo Should consider exceptions for reporting parsing problems more locally to the source of trouble
79  case 'E':
80  vertices_and_particles = parse_event_information(evt,buf);
81  if (vertices_and_particles.second < 0) {
82  is_parsing_successful = false;
83  } else {
84  is_parsing_successful = true;
85  parsed_event_header = true;
86  }
87  break;
88  case 'V':
89  is_parsing_successful = parse_vertex_information(evt,buf);
90  break;
91  case 'P':
92  is_parsing_successful = parse_particle_information(evt,buf);
93  break;
94  case 'W':
95  if ( parsed_event_header )
96  is_parsing_successful = parse_weight_values(evt,buf);
97  else
98  is_parsing_successful = parse_weight_names(buf);
99  break;
100  case 'U':
101  is_parsing_successful = parse_units(evt,buf);
102  break;
103  case 'T':
104  is_parsing_successful = parse_tool(buf);
105  break;
106  case 'A':
107  if ( parsed_event_header )
108  is_parsing_successful = parse_attribute(evt,buf);
109  else
110  is_parsing_successful = parse_run_attribute(buf);
111  break;
112  default:
113  WARNING( "ReaderAscii: skipping unrecognised prefix: " << buf[0] )
114  is_parsing_successful = true;
115  break;
116  }
117 
118  if( !is_parsing_successful ) break;
119 
120  // Check for next event
121  m_isstream ? peek = m_stream->peek() : peek = m_file.peek();
122  if( parsed_event_header && peek=='E' ) break;
123  }
124 
125 
126  // Check if all particles and vertices were parsed
127  if ((int)evt.particles().size() != vertices_and_particles.second ) {
128  ERROR( "ReaderAscii: too few or too many particles were parsed" )
129  is_parsing_successful = false;
130  }
131 
132  if ((int)evt.vertices().size() != vertices_and_particles.first) {
133  ERROR( "ReaderAscii: too few or too many vertices were parsed" )
134  is_parsing_successful = false;
135  }
136  // Check if there were errors during parsing
137  if( !is_parsing_successful ) {
138  ERROR( "ReaderAscii: event parsing failed. Returning empty event" )
139  DEBUG( 1, "Parsing failed at line:" << endl << buf )
140 
141  evt.clear();
142  m_isstream ? m_stream->clear(ios::badbit) : m_file.clear(ios::badbit);
143 
144  return false;
145  }
146 
147  return true;
148 }
149 
150 
151 pair<int,int> ReaderAscii::parse_event_information(GenEvent &evt, const char *buf) {
152  static const pair<int,int> err(-1,-1);
153  pair<int,int> ret(-1,-1);
154  const char *cursor = buf;
155  int event_no = 0;
156  FourVector position;
157 
158  // event number
159  if( !(cursor = strchr(cursor+1,' ')) ) return err;
160  event_no = atoi(cursor);
161  evt.set_event_number(event_no);
162 
163  // num_vertices
164  if( !(cursor = strchr(cursor+1,' ')) ) return err;
165  ret.first = atoi(cursor);
166 
167  // num_particles
168  if( !(cursor = strchr(cursor+1,' ')) ) return err;
169  ret.second = atoi(cursor);
170 
171  // check if there is position information
172  if( (cursor = strchr(cursor+1,'@')) ) {
173 
174  // x
175  if( !(cursor = strchr(cursor+1,' ')) ) return err;
176  position.setX(atof(cursor));
177 
178  // y
179  if( !(cursor = strchr(cursor+1,' ')) ) return err;
180  position.setY(atof(cursor));
181 
182  // z
183  if( !(cursor = strchr(cursor+1,' ')) ) return err;
184  position.setZ(atof(cursor));
185 
186  // t
187  if( !(cursor = strchr(cursor+1,' ')) ) return err;
188  position.setT(atof(cursor));
189  evt.shift_position_to( position );
190  }
191 
192  DEBUG( 10, "ReaderAscii: E: "<<event_no<<" ("<<ret.first<<"V, "<<ret.second<<"P)" )
193 
194  return ret;
195 }
196 
197 
198 bool ReaderAscii::parse_weight_values(GenEvent &evt, const char *buf) {
199 
200  std::istringstream iss(buf + 1);
201  vector<double> wts;
202  double w;
203  while ( iss >> w ) wts.push_back(w);
204  if ( run_info() && run_info()->weight_names().size()
205  && run_info()->weight_names().size() != wts.size() )
206  throw std::logic_error("ReaderAscii::parse_weight_values: "
207  "The number of weights does not match "
208  "the weight names in the GenRunInfo object");
209  evt.weights() = wts;
210 
211  return true;
212 }
213 
214 
215 bool ReaderAscii::parse_units(GenEvent &evt, const char *buf) {
216  const char *cursor = buf;
217 
218  // momentum
219  if( !(cursor = strchr(cursor+1,' ')) ) return false;
220  ++cursor;
221  Units::MomentumUnit momentum_unit = Units::momentum_unit(cursor);
222 
223  // length
224  if( !(cursor = strchr(cursor+1,' ')) ) return false;
225  ++cursor;
226  Units::LengthUnit length_unit = Units::length_unit(cursor);
227 
228  evt.set_units(momentum_unit,length_unit);
229 
230  DEBUG( 10, "ReaderAscii: U: " << Units::name(evt.momentum_unit()) << " " << Units::name(evt.length_unit()) )
231 
232  return true;
233 }
234 
235 
236 bool ReaderAscii::parse_vertex_information(GenEvent &evt, const char *buf) {
237  GenVertexPtr data = make_shared<GenVertex>();
238  FourVector position;
239  const char *cursor = buf;
240  const char *cursor2 = NULL;
241  int id = 0;
242  int particle_in = 0;
243  int highest_id = evt.particles().size();
244 
245  // id
246  if( !(cursor = strchr(cursor+1,' ')) ) return false;
247  id = atoi(cursor);
248 
249  // status
250  if( !(cursor = strchr(cursor+1,' ')) ) return false;
251  data->set_status( atoi(cursor) );
252 
253  // skip to the list of particles
254  if( !(cursor = strchr(cursor+1,'[')) ) return false;
255 
256  while(true) {
257  ++cursor; // skip the '[' or ',' character
258  cursor2 = cursor; // save cursor position
259  particle_in = atoi(cursor);
260 
261  // add incoming particle to the vertex
262  if( particle_in > 0 && particle_in <= highest_id) {
263  data->add_particle_in( evt.particles()[particle_in-1] );
264  }
265  else {
266  return false;
267  }
268 
269  // check for next particle or end of particle list
270  if( !(cursor = strchr(cursor+1,',')) ) {
271  if( !(cursor = strchr(cursor2+1,']')) ) return false;
272  break;
273  }
274  }
275 
276  // check if there is position information
277  if( (cursor = strchr(cursor+1,'@')) ) {
278 
279  // x
280  if( !(cursor = strchr(cursor+1,' ')) ) return false;
281  position.setX(atof(cursor));
282 
283  // y
284  if( !(cursor = strchr(cursor+1,' ')) ) return false;
285  position.setY(atof(cursor));
286 
287  // z
288  if( !(cursor = strchr(cursor+1,' ')) ) return false;
289  position.setZ(atof(cursor));
290 
291  // t
292  if( !(cursor = strchr(cursor+1,' ')) ) return false;
293  position.setT(atof(cursor));
294  data->set_position( position );
295 
296  }
297 
298  DEBUG( 10, "ReaderAscii: V: "<<id<<" with "<<data->particles_in().size()<<" particles)" )
299 
300  evt.add_vertex(data);
301 
302  return true;
303 }
304 
305 
307  GenParticlePtr data = make_shared<GenParticle>();
308  FourVector momentum;
309  const char *cursor = buf;
310  int mother_id = 0;
311 
312  // verify id
313  if( !(cursor = strchr(cursor+1,' ')) ) return false;
314 
315  if( atoi(cursor) != (int)evt.particles().size() + 1 ) {
316  /// @todo Should be an exception
317  ERROR( "ReaderAscii: particle ID mismatch" )
318  return false;
319  }
320 
321  // mother id
322  if( !(cursor = strchr(cursor+1,' ')) ) return false;
323  mother_id = atoi(cursor);
324 
325  // add particle to corresponding vertex
326  if( mother_id > 0 && mother_id <= (int)evt.particles().size() ) {
327 
328  GenParticlePtr mother = evt.particles()[ mother_id-1 ];
329  GenVertexPtr vertex = mother->end_vertex();
330 
331  // create new vertex if needed
332  if( !vertex ) {
333  vertex = make_shared<GenVertex>();
334  vertex->add_particle_in(mother);
335  }
336 
337  vertex->add_particle_out(data);
338  evt.add_vertex(vertex);
339  }
340  else if( mother_id < 0 && -mother_id <= (int)evt.vertices().size() ) {
341  evt.vertices()[ (-mother_id)-1 ]->add_particle_out(data);
342  }
343 
344  // pdg id
345  if( !(cursor = strchr(cursor+1,' ')) ) return false;
346  data->set_pid( atoi(cursor) );
347 
348  // px
349  if( !(cursor = strchr(cursor+1,' ')) ) return false;
350  momentum.setPx(atof(cursor));
351 
352  // py
353  if( !(cursor = strchr(cursor+1,' ')) ) return false;
354  momentum.setPy(atof(cursor));
355 
356  // pz
357  if( !(cursor = strchr(cursor+1,' ')) ) return false;
358  momentum.setPz(atof(cursor));
359 
360  // pe
361  if( !(cursor = strchr(cursor+1,' ')) ) return false;
362  momentum.setE(atof(cursor));
363  data->set_momentum(momentum);
364 
365  // m
366  if( !(cursor = strchr(cursor+1,' ')) ) return false;
367  data->set_generated_mass( atof(cursor) );
368 
369  // status
370  if( !(cursor = strchr(cursor+1,' ')) ) return false;
371  data->set_status( atoi(cursor) );
372 
373  evt.add_particle(data);
374 
375  DEBUG( 10, "ReaderAscii: P: "<<data->id()<<" ( mother: "<<mother_id<<", pid: "<<data->pid()<<")" )
376 
377  return true;
378 }
379 
380 
381 bool ReaderAscii::parse_attribute(GenEvent &evt, const char *buf) {
382  const char *cursor = buf;
383  const char *cursor2 = buf;
384  char name[64];
385  int id = 0;
386 
387  if( !(cursor = strchr(cursor+1,' ')) ) return false;
388  id = atoi(cursor);
389 
390  if( !(cursor = strchr(cursor+1,' ')) ) return false;
391  ++cursor;
392 
393  if( !(cursor2 = strchr(cursor,' ')) ) return false;
394  sprintf(name,"%.*s", (int)(cursor2-cursor), cursor);
395 
396  cursor = cursor2+1;
397 
398  shared_ptr<Attribute> att =
399  make_shared<StringAttribute>( StringAttribute(unescape(cursor)) );
400 
401  evt.add_attribute(string(name), att, id);
402 
403  return true;
404 }
405 
406 bool ReaderAscii::parse_run_attribute(const char *buf) {
407  const char *cursor = buf;
408  const char *cursor2 = buf;
409  char name[64];
410 
411  if( !(cursor = strchr(cursor+1,' ')) ) return false;
412  ++cursor;
413 
414  if( !(cursor2 = strchr(cursor,' ')) ) return false;
415  sprintf(name,"%.*s", (int)(cursor2-cursor), cursor);
416 
417  cursor = cursor2+1;
418 
419  shared_ptr<StringAttribute> att =
420  make_shared<StringAttribute>( StringAttribute(unescape(cursor)) );
421 
422  run_info()->add_attribute(string(name), att);
423 
424  return true;
425 
426 }
427 
428 
429 bool ReaderAscii::parse_weight_names(const char *buf) {
430  const char *cursor = buf;
431 
432  if( !(cursor = strchr(cursor+1,' ')) ) return false;
433  ++cursor;
434 
435  istringstream iss(unescape(cursor));
436  vector<string> names;
437  string name;
438  while ( iss >> name ) names.push_back(name);
439 
440  run_info()->set_weight_names(names);
441 
442  return true;
443 
444 }
445 
446 bool ReaderAscii::parse_tool(const char *buf) {
447  const char *cursor = buf;
448 
449  if( !(cursor = strchr(cursor+1,' ')) ) return false;
450  ++cursor;
451  string line = unescape(cursor);
453  string::size_type pos = line.find("\n");
454  tool.name = line.substr(0, pos);
455  line = line.substr(pos + 1);
456  pos = line.find("\n");
457  tool.version = line.substr(0, pos);
458  tool.description = line.substr(pos + 1);
459  run_info()->tools().push_back(tool);
460 
461  return true;
462 
463 }
464 
465 
466 string ReaderAscii::unescape(const string s) {
467  string ret;
468  ret.reserve(s.length());
469  for ( string::const_iterator it = s.begin(); it != s.end(); ++it ) {
470  if ( *it == '\\' ) {
471  ++it;
472  if ( *it == '|' )
473  ret += '\n';
474  else
475  ret += *it;
476  } else
477  ret += *it;
478  }
479 
480  return ret;
481 }
482 
483 
485  if( !m_file.is_open()) return;
486  m_file.close();
487 }
488 
489 
490 } // namespace HepMC
const std::vector< GenParticlePtr > & particles() const
Get list of particles (const)
string description
Other information about how the tool was used in the run.
const Units::MomentumUnit & momentum_unit() const
Get momentum unit.
bool parse_weight_names(const char *buf)
Parse run-level weight names.
Definition: ReaderAscii.cc:429
void add_vertex(GenVertexPtr v)
Add vertex.
Definition: GenEvent.cc:57
bool failed()
Return status of the stream.
ReaderAscii(const std::string &filename)
Constructor.
Definition: ReaderAscii.cc:22
void set_event_number(int num)
Set event number.
static std::string name(MomentumUnit u)
Get name of momentum unit.
bool read_event(GenEvent &evt)
Load event from file.
Definition: ReaderAscii.cc:47
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:335
std::pair< int, int > parse_event_information(GenEvent &evt, const char *buf)
Parse event.
Definition: ReaderAscii.cc:151
shared_ptr< GenRunInfo > run_info() const
Get the global GenRunInfo object.
void clear()
Remove contents of this event.
Definition: GenEvent.cc:374
~ReaderAscii()
Destructor.
Definition: ReaderAscii.cc:44
void close()
Close file stream.
Definition: ReaderAscii.cc:484
void set_run_info(shared_ptr< GenRunInfo > run)
Set the global GenRunInfo object.
Stores event-related information.
static MomentumUnit momentum_unit(const std::string &name)
Get momentum unit based on its name.
void setT(double tt)
Set time component of position/displacement.
void setX(double xx)
Set x-component of position/displacement.
void setZ(double zz)
Set z-component of position/displacement.
void add_attribute(const string &name, const shared_ptr< Attribute > &att, int id=0)
Add event attribute to event.
void add_particle(GenParticlePtr p)
Add particle.
Definition: GenEvent.cc:42
bool parse_run_attribute(const char *buf)
Parse run-level attribute.
Definition: ReaderAscii.cc:406
void shift_position_to(const FourVector &newpos)
Shift position of all vertices in the event to op.
bool parse_vertex_information(GenEvent &evt, const char *buf)
Parse vertex.
Definition: ReaderAscii.cc:236
bool parse_attribute(GenEvent &evt, const char *buf)
Parse attribute.
Definition: ReaderAscii.cc:381
const std::vector< GenVertexPtr > & vertices() const
Get list of vertices (const)
bool parse_units(GenEvent &evt, const char *buf)
Parse units.
Definition: ReaderAscii.cc:215
bool parse_tool(const char *buf)
Parse run-level tool information.
Definition: ReaderAscii.cc:446
bool parse_weight_values(GenEvent &evt, const char *buf)
Parse weight value lines.
Definition: ReaderAscii.cc:198
Definition of template class SmartPointer.
const Units::LengthUnit & length_unit() const
Get length unit.
Interrnal struct for keeping track of tools.
static LengthUnit length_unit(const std::string &name)
Get length unit based on its name.
void setY(double yy)
Set y-component of position/displacement.
bool parse_particle_information(GenEvent &evt, const char *buf)
Parse particle.
Definition: ReaderAscii.cc:306
void set_run_info(shared_ptr< GenRunInfo > run)
Set the GenRunInfo object by smart pointer.
const std::vector< double > & weights() const
Get event weight values as a vector.
std::string unescape(const std::string s)
Unsecape &#39;\&#39; and &#39; &#39; characters in string.
Definition: ReaderAscii.cc:466