StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
IO_HEPEVT.cc
1 // Matt.Dobbs@Cern.CH, January 2000
3 // HEPEVT IO class
5 
6 #include "HepMC/IO_HEPEVT.h"
7 #include "HepMC/GenEvent.h"
8 #include <cstdio> // needed for formatted output using sprintf
9 
10 namespace HepMC {
11 
12  IO_HEPEVT::IO_HEPEVT() : m_trust_mothers_before_daughters(1),
13  m_trust_both_mothers_and_daughters(0),
14  m_print_inconsistency_errors(1),
15  m_trust_beam_particles(true)
16  {}
17 
18  IO_HEPEVT::~IO_HEPEVT(){}
19 
20  void IO_HEPEVT::print( std::ostream& ostr ) const {
21  ostr << "IO_HEPEVT: reads an event from the FORTRAN HEPEVT "
22  << "common block. \n"
23  << " trust_mothers_before_daughters = "
24  << m_trust_mothers_before_daughters
25  << " trust_both_mothers_and_daughters = "
26  << m_trust_both_mothers_and_daughters
27  << ", print_inconsistency_errors = "
28  << m_print_inconsistency_errors << std::endl;
29  }
30 
31  bool IO_HEPEVT::fill_next_event( GenEvent* evt ) {
45  //
46  // 1. test that evt pointer is not null and set event number
47  if ( !evt ) {
48  std::cerr
49  << "IO_HEPEVT::fill_next_event error - passed null event."
50  << std::endl;
51  return false;
52  }
53  evt->set_event_number( HEPEVT_Wrapper::event_number() );
54  //
55  // 2. create a particle instance for each HEPEVT entry and fill a map
56  // create a vector which maps from the HEPEVT particle index to the
57  // GenParticle address
58  // (+1 in size accounts for hepevt_particle[0] which is unfilled)
59  std::vector<GenParticle*> hepevt_particle(
60  HEPEVT_Wrapper::number_entries()+1 );
61  hepevt_particle[0] = 0;
62  for ( int i1 = 1; i1 <= HEPEVT_Wrapper::number_entries(); ++i1 ) {
63  hepevt_particle[i1] = build_particle(i1);
64  }
65  std::set<GenVertex*> new_vertices;
66  //
67  // Here we assume that the first two particles in the list
68  // are the incoming beam particles.
69  if( trust_beam_particles() ) {
70  evt->set_beam_particles( hepevt_particle[1], hepevt_particle[2] );
71  }
72  //
73  // 3.+4. loop over HEPEVT particles AGAIN, this time creating vertices
74  for ( int i = 1; i <= HEPEVT_Wrapper::number_entries(); ++i ) {
75  // We go through and build EITHER the production or decay
76  // vertex for each entry in hepevt, depending on the switch
77  // m_trust_mothers_before_daughters (new 2001-02-28)
78  // Note: since the HEPEVT pointers are bi-directional, it is
80  //
81  // 3. Build the production_vertex (if necessary)
82  if ( m_trust_mothers_before_daughters ||
83  m_trust_both_mothers_and_daughters ) {
84  build_production_vertex( i, hepevt_particle, evt );
85  }
86  //
87  // 4. Build the end_vertex (if necessary)
88  // Identical steps as for production vertex
89  if ( !m_trust_mothers_before_daughters ||
90  m_trust_both_mothers_and_daughters ) {
91  build_end_vertex( i, hepevt_particle, evt );
92  }
93  }
94  // 5. 01.02.2000
95  // handle the case of particles in HEPEVT which come from nowhere -
96  // i.e. particles without mothers or daughters.
97  // These particles need to be attached to a vertex, or else they
98  // will never become part of the event. check for this situation
99  for ( int i3 = 1; i3 <= HEPEVT_Wrapper::number_entries(); ++i3 ) {
100  if ( !hepevt_particle[i3]->end_vertex() &&
101  !hepevt_particle[i3]->production_vertex() ) {
102  GenVertex* prod_vtx = new GenVertex();
103  prod_vtx->add_particle_out( hepevt_particle[i3] );
104  evt->add_vertex( prod_vtx );
105  }
106  }
107  return true;
108  }
109 
110  void IO_HEPEVT::write_event( const GenEvent* evt ) {
116  //
117  if ( !evt ) return;
118  //
119  // map all particles onto a unique index
120  std::vector<GenParticle*> index_to_particle(
121  HEPEVT_Wrapper::max_number_entries()+1 );
122  index_to_particle[0]=0;
123  std::map<GenParticle*,int> particle_to_index;
124  int particle_counter=0;
126  v != evt->vertices_end(); ++v ) {
127  // all "mothers" or particles_in are kept adjacent in the list
128  // so that the mother indices in hepevt can be filled properly
130  = (*v)->particles_in_const_begin();
131  p1 != (*v)->particles_in_const_end(); ++p1 ) {
132  ++particle_counter;
133  if ( particle_counter >
134  HEPEVT_Wrapper::max_number_entries() ) break;
135  index_to_particle[particle_counter] = *p1;
136  particle_to_index[*p1] = particle_counter;
137  }
138  // daughters are entered only if they aren't a mother of
139  // another vtx
141  = (*v)->particles_out_const_begin();
142  p2 != (*v)->particles_out_const_end(); ++p2 ) {
143  if ( !(*p2)->end_vertex() ) {
144  ++particle_counter;
145  if ( particle_counter >
146  HEPEVT_Wrapper::max_number_entries() ) {
147  break;
148  }
149  index_to_particle[particle_counter] = *p2;
150  particle_to_index[*p2] = particle_counter;
151  }
152  }
153  }
154  if ( particle_counter > HEPEVT_Wrapper::max_number_entries() ) {
155  particle_counter = HEPEVT_Wrapper::max_number_entries();
156  }
157  //
158  // fill the HEPEVT event record
159  HEPEVT_Wrapper::set_event_number( evt->event_number() );
160  HEPEVT_Wrapper::set_number_entries( particle_counter );
161  for ( int i = 1; i <= particle_counter; ++i ) {
162  HEPEVT_Wrapper::set_status( i, index_to_particle[i]->status() );
163  HEPEVT_Wrapper::set_id( i, index_to_particle[i]->pdg_id() );
164  FourVector m = index_to_particle[i]->momentum();
165  HEPEVT_Wrapper::set_momentum( i, m.px(), m.py(), m.pz(), m.e() );
166  HEPEVT_Wrapper::set_mass( i, index_to_particle[i]->generatedMass() );
167  // there should ALWAYS be particles in any vertex, but some generators
168  // are making non-kosher HepMC events
169  if ( index_to_particle[i]->production_vertex() &&
170  index_to_particle[i]->production_vertex()->particles_in_size()) {
171  FourVector p = index_to_particle[i]->
172  production_vertex()->position();
173  HEPEVT_Wrapper::set_position( i, p.x(), p.y(), p.z(), p.t() );
174  int num_mothers = index_to_particle[i]->production_vertex()->
175  particles_in_size();
176  int first_mother = find_in_map( particle_to_index,
177  *(index_to_particle[i]->
178  production_vertex()->
179  particles_in_const_begin()));
180  int last_mother = first_mother + num_mothers - 1;
181  if ( first_mother == 0 ) last_mother = 0;
182  HEPEVT_Wrapper::set_parents( i, first_mother, last_mother );
183  } else {
184  HEPEVT_Wrapper::set_position( i, 0, 0, 0, 0 );
185  HEPEVT_Wrapper::set_parents( i, 0, 0 );
186  }
187  HEPEVT_Wrapper::set_children( i, 0, 0 );
188  }
189  }
190 
191  void IO_HEPEVT::build_production_vertex(int i,
192  std::vector<HepMC::GenParticle*>&
193  hepevt_particle,
194  GenEvent* evt ) {
198  GenParticle* p = hepevt_particle[i];
199  // a. search to see if a production vertex already exists
200  int mother = HEPEVT_Wrapper::first_parent(i);
201  GenVertex* prod_vtx = p->production_vertex();
202  while ( !prod_vtx && mother > 0 ) {
203  prod_vtx = hepevt_particle[mother]->end_vertex();
204  if ( prod_vtx ) prod_vtx->add_particle_out( p );
205  // increment mother for next iteration
206  if ( ++mother > HEPEVT_Wrapper::last_parent(i) ) mother = 0;
207  }
208  // b. if no suitable production vertex exists - and the particle
209  // has atleast one mother or position information to store -
210  // make one
211  FourVector prod_pos( HEPEVT_Wrapper::x(i), HEPEVT_Wrapper::y(i),
212  HEPEVT_Wrapper::z(i), HEPEVT_Wrapper::t(i)
213  );
214  if ( !prod_vtx && (HEPEVT_Wrapper::number_parents(i)>0
215  || prod_pos!=FourVector(0,0,0,0)) )
216  {
217  prod_vtx = new GenVertex();
218  prod_vtx->add_particle_out( p );
219  evt->add_vertex( prod_vtx );
220  }
221  // c. if prod_vtx doesn't already have position specified, fill it
222  if ( prod_vtx && prod_vtx->position()==FourVector(0,0,0,0) ) {
223  prod_vtx->set_position( prod_pos );
224  }
225  // d. loop over mothers to make sure their end_vertices are
226  // consistent
227  mother = HEPEVT_Wrapper::first_parent(i);
228  while ( prod_vtx && mother > 0 ) {
229  if ( !hepevt_particle[mother]->end_vertex() ) {
230  // if end vertex of the mother isn't specified, do it now
231  prod_vtx->add_particle_in( hepevt_particle[mother] );
232  } else if (hepevt_particle[mother]->end_vertex() != prod_vtx ) {
233  // problem scenario --- the mother already has a decay
234  // vertex which differs from the daughter's produciton
235  // vertex. This means there is internal
236  // inconsistency in the HEPEVT event record. Print an
237  // error
238  // Note: we could provide a fix by joining the two
239  // vertices with a dummy particle if the problem
240  // arrises often with any particular generator.
241  if ( m_print_inconsistency_errors ) std::cerr
242  << "HepMC::IO_HEPEVT: inconsistent mother/daugher "
243  << "information in HEPEVT event "
244  << HEPEVT_Wrapper::event_number()
245  << ". \n I recommend you try "
246  << "inspecting the event first with "
247  << "\n\tHEPEVT_Wrapper::check_hepevt_consistency()"
248  << "\n This warning can be turned off with the "
249  << "IO_HEPEVT::print_inconsistency_errors switch."
250  << std::endl;
251  }
252  if ( ++mother > HEPEVT_Wrapper::last_parent(i) ) mother = 0;
253  }
254  }
255 
256  void IO_HEPEVT::build_end_vertex
257  ( int i, std::vector<HepMC::GenParticle*>& hepevt_particle, GenEvent* evt )
258  {
262  // Identical steps as for build_production_vertex
263  GenParticle* p = hepevt_particle[i];
264  // a.
265  int daughter = HEPEVT_Wrapper::first_child(i);
266  GenVertex* end_vtx = p->end_vertex();
267  while ( !end_vtx && daughter > 0 ) {
268  end_vtx = hepevt_particle[daughter]->production_vertex();
269  if ( end_vtx ) end_vtx->add_particle_in( p );
270  if ( ++daughter > HEPEVT_Wrapper::last_child(i) ) daughter = 0;
271  }
272  // b. (different from 3c. because HEPEVT particle can not know its
273  // decay position )
274  if ( !end_vtx && HEPEVT_Wrapper::number_children(i)>0 ) {
275  end_vtx = new GenVertex();
276  end_vtx->add_particle_in( p );
277  evt->add_vertex( end_vtx );
278  }
279  // c+d. loop over daughters to make sure their production vertices
280  // point back to the current vertex.
281  // We get the vertex position from the daughter as well.
282  daughter = HEPEVT_Wrapper::first_child(i);
283  while ( end_vtx && daughter > 0 ) {
284  if ( !hepevt_particle[daughter]->production_vertex() ) {
285  // if end vertex of the mother isn't specified, do it now
286  end_vtx->add_particle_out( hepevt_particle[daughter] );
287  //
288  // 2001-03-29 M.Dobbs, fill vertex the position.
289  if ( end_vtx->position()==FourVector(0,0,0,0) ) {
290  FourVector prod_pos( HEPEVT_Wrapper::x(daughter),
291  HEPEVT_Wrapper::y(daughter),
292  HEPEVT_Wrapper::z(daughter),
293  HEPEVT_Wrapper::t(daughter)
294  );
295  if ( prod_pos != FourVector(0,0,0,0) ) {
296  end_vtx->set_position( prod_pos );
297  }
298  }
299  } else if (hepevt_particle[daughter]->production_vertex()
300  != end_vtx){
301  // problem scenario --- the daughter already has a prod
302  // vertex which differs from the mother's end
303  // vertex. This means there is internal
304  // inconsistency in the HEPEVT event record. Print an
305  // error
306  if ( m_print_inconsistency_errors ) std::cerr
307  << "HepMC::IO_HEPEVT: inconsistent mother/daugher "
308  << "information in HEPEVT event "
309  << HEPEVT_Wrapper::event_number()
310  << ". \n I recommend you try "
311  << "inspecting the event first with "
312  << "\n\tHEPEVT_Wrapper::check_hepevt_consistency()"
313  << "\n This warning can be turned off with the "
314  << "IO_HEPEVT::print_inconsistency_errors switch."
315  << std::endl;
316  }
317  if ( ++daughter > HEPEVT_Wrapper::last_child(i) ) daughter = 0;
318  }
319  if ( !p->end_vertex() && !p->production_vertex() ) {
320  // Added 2001-11-04, to try and handle Isajet problems.
321  build_production_vertex( i, hepevt_particle, evt );
322  }
323  }
324 
325  GenParticle* IO_HEPEVT::build_particle( int index ) {
327  //
328  GenParticle* p
329  = new GenParticle( FourVector( HEPEVT_Wrapper::px(index),
330  HEPEVT_Wrapper::py(index),
331  HEPEVT_Wrapper::pz(index),
332  HEPEVT_Wrapper::e(index) ),
333  HEPEVT_Wrapper::id(index),
334  HEPEVT_Wrapper::status(index) );
335  p->setGeneratedMass( HEPEVT_Wrapper::m(index) );
336  p->suggest_barcode( index );
337  return p;
338  }
339 
340  int IO_HEPEVT::find_in_map( const std::map<HepMC::GenParticle*,int>& m,
341  GenParticle* p) const {
342  std::map<GenParticle*,int>::const_iterator iter = m.find(p);
343  if ( iter == m.end() ) return 0;
344  return iter->second;
345  }
346 
347 } // HepMC
348 
349 
350 
double z() const
return z
Definition: SimpleVector.h:77
std::vector< HepMC::GenParticle * >::const_iterator particles_in_const_iterator
const iterator for incoming particles
Definition: GenVertex.h:152
void add_particle_in(GenParticle *inparticle)
add incoming particle
Definition: GenVertex.cc:273
std::vector< HepMC::GenParticle * >::const_iterator particles_out_const_iterator
const iterator for outgoing particles
Definition: GenVertex.h:155
double e() const
return E
Definition: SimpleVector.h:73
double y() const
return y
Definition: SimpleVector.h:76
void set_position(const FourVector &position=FourVector(0, 0, 0, 0))
set vertex position and time
Definition: GenVertex.h:424
void set_event_number(int eventno)
set event number
Definition: GenEvent.h:733
double px() const
return px
Definition: SimpleVector.h:70
GenVertex * production_vertex() const
pointer to the production vertex
Definition: GenParticle.h:218
GenVertex contains information about decay vertices.
Definition: GenVertex.h:52
bool suggest_barcode(int the_bar_code)
In general there is no reason to &quot;suggest_barcode&quot;.
Definition: GenParticle.cc:153
The GenEvent class is the core of HepMC.
Definition: GenEvent.h:155
double pz() const
return pz
Definition: SimpleVector.h:72
void add_particle_out(GenParticle *outparticle)
add outgoing particle
Definition: GenVertex.cc:284
bool add_vertex(GenVertex *vtx)
adds to evt and adopts
Definition: GenEvent.cc:334
vertex_const_iterator vertices_end() const
end vertex iteration
Definition: GenEvent.h:381
double x() const
return x
Definition: SimpleVector.h:75
bool set_beam_particles(GenParticle *, GenParticle *)
set incoming beam particles
Definition: GenEvent.cc:586
const FourVector & position() const
vertex position and time
Definition: GenVertex.h:406
FourVector is a simple representation of a physics 4 vector.
Definition: SimpleVector.h:42
vertex_const_iterator vertices_begin() const
begin vertex iteration
Definition: GenEvent.h:377
GenVertex * end_vertex() const
pointer to the decay vertex
Definition: GenParticle.h:221
int event_number() const
event number
Definition: GenEvent.h:682
void setGeneratedMass(const double &m)
setGeneratedMass() is included for backwards compatibility with CLHEP HepMC
Definition: GenParticle.h:173
double py() const
return py
Definition: SimpleVector.h:71
double t() const
return t
Definition: SimpleVector.h:78
The GenParticle class contains information about generated particles.
Definition: GenParticle.h:60