CMS 3D CMS Logo

IO_EPOS.cc
Go to the documentation of this file.
1 
2 // EPOS IO class
3 
5 #include "HepMC/GenEvent.h"
6 #include <cstdio> // needed for formatted output using sprintf
7 
8 using namespace HepMC;
9 
10 namespace EPOS {
11 
12  unsigned int EPOS_Wrapper::s_sizeof_int = 4;
13  unsigned int EPOS_Wrapper::s_sizeof_real = sizeof(double);
14  unsigned int EPOS_Wrapper::s_max_number_entries = 99900;
15 
16  IO_EPOS::IO_EPOS()
17  : m_trust_mothers_before_daughters(true),
18  m_trust_both_mothers_and_daughters(false),
19  m_print_inconsistency_errors(true),
20  m_trust_beam_particles(true),
21  m_skip_nucl_frag(false) {}
22 
24 
25  void IO_EPOS::print(std::ostream& ostr) const {
26  ostr << "IO_EPOS: reads an event from the FORTRAN EPOS g "
27  << "common block. \n"
28  << " trust_mothers_before_daughters = " << m_trust_mothers_before_daughters
29  << " trust_both_mothers_and_daughters = " << m_trust_both_mothers_and_daughters
30  << ", print_inconsistency_errors = " << m_print_inconsistency_errors << std::endl;
31  }
32 
34  //
35  // 1. test that evt pointer is not null and set event number
36  if (!evt) {
37  std::cerr << "IO_EPOS::fill_next_event error - passed null event." << std::endl;
38  return false;
39  }
40  evt->set_event_number(EPOS_Wrapper::event_number());
41  //
42  // 2. create a particle instance for each EPOS entry and fill a map
43  // create a vector which maps from the EPOS particle index to the
44  // GenParticle address
45  // (+1 in size accounts for hepevt_particle[0] which is unfilled)
46  std::vector<HepMC::GenParticle*> hepevt_particle(EPOS_Wrapper::number_entries() + 1);
47  hepevt_particle[0] = nullptr;
48  for (int i1 = 1; i1 <= EPOS_Wrapper::number_entries(); ++i1) {
49  hepevt_particle[i1] = build_particle(i1);
50  }
51 
52  HepMC::GenVertex* primaryVertex = new HepMC::GenVertex(HepMC::FourVector(0, 0, 0, 0), 0);
53  evt->add_vertex(primaryVertex);
54  if (!evt->signal_process_vertex())
55  evt->set_signal_process_vertex(primaryVertex);
56 
57  std::set<HepMC::GenVertex*> new_vertices;
58  //
59  // Here we assume that the first two particles in the list
60  // are the incoming beam particles.
61  if (trust_beam_particles()) {
62  evt->set_beam_particles(hepevt_particle[1], hepevt_particle[2]);
63  }
64  //
65  // 3.+4. loop over EPOS particles AGAIN, this time creating vertices
66  //MODIFICATION FROM HEPMC!! skipping nuclear fragments in event if option is set
67  for (int i = 1; i <= EPOS_Wrapper::number_entries(); ++i) {
68  if (m_skip_nucl_frag && abs(hepevt_particle[i]->pdg_id()) >= 1000000000)
69  continue;
70  // We go through and build EITHER the production or decay
71  // vertex for each entry in hepevt, depending on the switch
72  // m_trust_mothers_before_daughters (new 2001-02-28)
73  // Note: since the EPOS pointers are bi-directional, it is
74  //
75  // 3. Build the production_vertex (if necessary)
77  build_production_vertex(i, hepevt_particle, evt);
78  }
79  //
80  // 4. Build the end_vertex (if necessary)
81  // Identical steps as for production vertex
83  build_end_vertex(i, hepevt_particle, evt);
84  }
85  }
86  // 5. 01.02.2000
87  // handle the case of particles in EPOS which come from nowhere -
88  // i.e. particles without mothers or daughters.
89  // These particles need to be attached to a vertex, or else they
90  // will never become part of the event. check for this situation
91  //MODIFICATION FROM HEPMC!! skipping nuclear fragments in event if option is set
92  for (int i3 = 1; i3 <= EPOS_Wrapper::number_entries(); ++i3) {
93  if (m_skip_nucl_frag && abs(hepevt_particle[i3]->pdg_id()) >= 1000000000)
94  continue;
95  if (!hepevt_particle[i3]->end_vertex() && !hepevt_particle[i3]->production_vertex()) {
96  HepMC::GenVertex* prod_vtx = new GenVertex();
97  prod_vtx->add_particle_out(hepevt_particle[i3]);
98  evt->add_vertex(prod_vtx);
99  }
100  }
101  return true;
102  }
103 
104  void IO_EPOS::write_event(const GenEvent* evt) {
105  //
106  if (!evt)
107  return;
108  //
109  // map all particles onto a unique index
110  std::vector<HepMC::GenParticle*> index_to_particle(EPOS_Wrapper::max_number_entries() + 1);
111  index_to_particle[0] = nullptr;
112  std::map<HepMC::GenParticle*, int> particle_to_index;
113  int particle_counter = 0;
114  for (HepMC::GenEvent::vertex_const_iterator v = evt->vertices_begin(); v != evt->vertices_end(); ++v) {
115  // all "mothers" or particles_in are kept adjacent in the list
116  // so that the mother indices in hepevt can be filled properly
117  for (HepMC::GenVertex::particles_in_const_iterator p1 = (*v)->particles_in_const_begin();
118  p1 != (*v)->particles_in_const_end();
119  ++p1) {
120  ++particle_counter;
121  if (particle_counter > EPOS_Wrapper::max_number_entries())
122  break;
123  index_to_particle[particle_counter] = *p1;
124  particle_to_index[*p1] = particle_counter;
125  }
126  // daughters are entered only if they aren't a mother of
127  // another vtx
128  for (HepMC::GenVertex::particles_out_const_iterator p2 = (*v)->particles_out_const_begin();
129  p2 != (*v)->particles_out_const_end();
130  ++p2) {
131  if (!(*p2)->end_vertex()) {
132  ++particle_counter;
133  if (particle_counter > EPOS_Wrapper::max_number_entries()) {
134  break;
135  }
136  index_to_particle[particle_counter] = *p2;
137  particle_to_index[*p2] = particle_counter;
138  }
139  }
140  }
141  if (particle_counter > EPOS_Wrapper::max_number_entries()) {
142  particle_counter = EPOS_Wrapper::max_number_entries();
143  }
144  //
145  // fill the EPOS event record
146  EPOS_Wrapper::set_event_number(evt->event_number());
147  EPOS_Wrapper::set_number_entries(particle_counter);
148  for (int i = 1; i <= particle_counter; ++i) {
149  EPOS_Wrapper::set_status(i, index_to_particle[i]->status());
150  EPOS_Wrapper::set_id(i, index_to_particle[i]->pdg_id());
151  FourVector m = index_to_particle[i]->momentum();
152  EPOS_Wrapper::set_momentum(i, m.px(), m.py(), m.pz(), m.e());
153  EPOS_Wrapper::set_mass(i, index_to_particle[i]->generatedMass());
154  // there should ALWAYS be particles in any vertex, but some generators
155  // are making non-kosher HepMC events
156  if (index_to_particle[i]->production_vertex() && index_to_particle[i]->production_vertex()->particles_in_size()) {
157  FourVector p = index_to_particle[i]->production_vertex()->position();
158  EPOS_Wrapper::set_position(i, p.x(), p.y(), p.z(), p.t());
159  int num_mothers = index_to_particle[i]->production_vertex()->particles_in_size();
160  int first_mother =
161  find_in_map(particle_to_index, *(index_to_particle[i]->production_vertex()->particles_in_const_begin()));
162  int last_mother = first_mother + num_mothers - 1;
163  if (first_mother == 0)
164  last_mother = 0;
165  EPOS_Wrapper::set_parents(i, first_mother, last_mother);
166  } else {
167  EPOS_Wrapper::set_position(i, 0, 0, 0, 0);
169  }
171  }
172  }
173 
174  void IO_EPOS::build_production_vertex(int i, std::vector<HepMC::GenParticle*>& hepevt_particle, GenEvent* evt) {
175  HepMC::GenParticle* p = hepevt_particle[i];
176  // a. search to see if a production vertex already exists
177  int mother = EPOS_Wrapper::first_parent(i);
178  HepMC::GenVertex* prod_vtx = p->production_vertex();
179  while (!prod_vtx && mother > 0) {
180  prod_vtx = hepevt_particle[mother]->end_vertex();
181  if (prod_vtx)
182  prod_vtx->add_particle_out(p);
183  // increment mother for next iteration
184  if (++mother > EPOS_Wrapper::last_parent(i))
185  mother = 0;
186  }
187  // b. if no suitable production vertex exists - and the particle
188  // has atleast one mother or position information to store -
189  // make one
190  HepMC::FourVector prod_pos(EPOS_Wrapper::x(i), EPOS_Wrapper::y(i), EPOS_Wrapper::z(i), EPOS_Wrapper::t(i));
191  if (!prod_vtx && (EPOS_Wrapper::number_parents(i) > 0 || prod_pos != FourVector(0, 0, 0, 0))) {
192  prod_vtx = new HepMC::GenVertex();
193  prod_vtx->add_particle_out(p);
194  evt->add_vertex(prod_vtx);
195  }
196  // c. if prod_vtx doesn't already have position specified, fill it
197  if (prod_vtx && prod_vtx->position() == FourVector(0, 0, 0, 0)) {
198  prod_vtx->set_position(prod_pos);
199  }
200  // d. loop over mothers to make sure their end_vertices are
201  // consistent
202  mother = EPOS_Wrapper::first_parent(i);
203  while (prod_vtx && mother > 0) {
204  if (!hepevt_particle[mother]->end_vertex()) {
205  // if end vertex of the mother isn't specified, do it now
206  prod_vtx->add_particle_in(hepevt_particle[mother]);
207  } else if (hepevt_particle[mother]->end_vertex() != prod_vtx) {
208  // problem scenario --- the mother already has a decay
209  // vertex which differs from the daughter's produciton
210  // vertex. This means there is internal
211  // inconsistency in the EPOS event record. Print an
212  // error
213  // Note: we could provide a fix by joining the two
214  // vertices with a dummy particle if the problem
215  // arrises often with any particular generator.
217  std::cerr << "HepMC::IO_EPOS: inconsistent mother/daugher "
218  << "information in EPOS event " << EPOS_Wrapper::event_number() << ". \n I recommend you try "
219  << "inspecting the event first with "
220  << "\n\tEPOS_Wrapper::check_hepevt_consistency()"
221  << "\n This warning can be turned off with the "
222  << "IO_EPOS::print_inconsistency_errors switch." << std::endl;
223  }
224  if (++mother > EPOS_Wrapper::last_parent(i))
225  mother = 0;
226  }
227  }
228 
229  void IO_EPOS::build_end_vertex(int i, std::vector<HepMC::GenParticle*>& hepevt_particle, GenEvent* evt) {
230  // Identical steps as for build_production_vertex
231  HepMC::GenParticle* p = hepevt_particle[i];
232  // a.
233  int daughter = EPOS_Wrapper::first_child(i);
234  HepMC::GenVertex* end_vtx = p->end_vertex();
235  while (!end_vtx && daughter > 0) {
236  end_vtx = hepevt_particle[daughter]->production_vertex();
237  if (end_vtx)
238  end_vtx->add_particle_in(p);
239  if (++daughter > EPOS_Wrapper::last_child(i))
240  daughter = 0;
241  }
242  // b. (different from 3c. because EPOS particle can not know its
243  // decay position )
244  if (!end_vtx && EPOS_Wrapper::number_children(i) > 0) {
245  end_vtx = new GenVertex();
246  end_vtx->add_particle_in(p);
247  evt->add_vertex(end_vtx);
248  }
249  // c+d. loop over daughters to make sure their production vertices
250  // point back to the current vertex.
251  // We get the vertex position from the daughter as well.
252  daughter = EPOS_Wrapper::first_child(i);
253  while (end_vtx && daughter > 0) {
254  if (!hepevt_particle[daughter]->production_vertex()) {
255  // if end vertex of the mother isn't specified, do it now
256  end_vtx->add_particle_out(hepevt_particle[daughter]);
257  //
258  // 2001-03-29 M.Dobbs, fill vertex the position.
259  if (end_vtx->position() == FourVector(0, 0, 0, 0)) {
260  // again mm to cm conversion
261  FourVector prod_pos(EPOS_Wrapper::x(daughter),
262  EPOS_Wrapper::y(daughter),
263  EPOS_Wrapper::z(daughter),
264  EPOS_Wrapper::t(daughter));
265  if (prod_pos != FourVector(0, 0, 0, 0)) {
266  end_vtx->set_position(prod_pos);
267  }
268  }
269  } else if (hepevt_particle[daughter]->production_vertex() != end_vtx) {
270  // problem scenario --- the daughter already has a prod
271  // vertex which differs from the mother's end
272  // vertex. This means there is internal
273  // inconsistency in the EPOS event record. Print an
274  // error
276  std::cerr << "HepMC::IO_EPOS: inconsistent mother/daugher "
277  << "information in EPOS event " << EPOS_Wrapper::event_number() << ". \n I recommend you try "
278  << "inspecting the event first with "
279  << "\n\tEPOS_Wrapper::check_hepevt_consistency()"
280  << "\n This warning can be turned off with the "
281  << "IO_EPOS::print_inconsistency_errors switch." << std::endl;
282  }
283  if (++daughter > EPOS_Wrapper::last_child(i))
284  daughter = 0;
285  }
286  if (!p->end_vertex() && !p->production_vertex()) {
287  // Added 2001-11-04, to try and handle Isajet problems.
288  build_production_vertex(i, hepevt_particle, evt);
289  }
290  }
291 
293  //
298  p->setGeneratedMass(EPOS_Wrapper::m(index));
299  p->suggest_barcode(index);
300  return p;
301  }
302 
303  int IO_EPOS::find_in_map(const std::map<HepMC::GenParticle*, int>& m, HepMC::GenParticle* p) const {
304  std::map<HepMC::GenParticle*, int>::const_iterator iter = m.find(p);
305  if (iter == m.end())
306  return 0;
307  return iter->second;
308  }
309 
310 } // namespace EPOS
bool m_skip_nucl_frag
Definition: IO_EPOS.h:53
bool fill_next_event(HepMC::GenEvent *) override
Definition: IO_EPOS.cc:33
static void set_children(int index, int firstchild, int lastchild)
define children of a particle
Definition: EPOS_Wrapper.h:436
static void set_mass(int index, double mass)
set particle mass
Definition: EPOS_Wrapper.h:452
HepMC::GenParticle * build_particle(int index)
Definition: IO_EPOS.cc:292
static double m(int index)
generated mass
Definition: EPOS_Wrapper.h:389
static void set_status(int index, int status)
set particle status
Definition: EPOS_Wrapper.h:417
void build_end_vertex(int i, std::vector< HepMC::GenParticle *> &hepevt_particle, HepMC::GenEvent *evt)
Definition: IO_EPOS.cc:229
static void set_id(int index, int id)
set particle ID
Definition: EPOS_Wrapper.h:423
static double e(int index)
Energy.
Definition: EPOS_Wrapper.h:385
static double t(int index)
production time
Definition: EPOS_Wrapper.h:408
static void set_number_entries(int noentries)
set number of entries in EPOS
Definition: EPOS_Wrapper.h:415
static int number_parents(int index)
number of parents
Definition: EPOS_Wrapper.h:343
static void set_event_number(int evtno)
set event number
Definition: EPOS_Wrapper.h:413
static void set_momentum(int index, double px, double py, double pz, double e)
set particle momentum
Definition: EPOS_Wrapper.h:443
static int first_child(int index)
index of 1st daughter
Definition: EPOS_Wrapper.h:348
static int first_parent(int index)
index of 1st mother
Definition: EPOS_Wrapper.h:323
~IO_EPOS() override
Definition: IO_EPOS.cc:23
bool m_print_inconsistency_errors
Definition: IO_EPOS.h:51
bool m_trust_mothers_before_daughters
Definition: IO_EPOS.h:49
bool m_trust_both_mothers_and_daughters
Definition: IO_EPOS.h:50
static double y(int index)
Y Production vertex.
Definition: EPOS_Wrapper.h:398
void write_event(const HepMC::GenEvent *) override
Definition: IO_EPOS.cc:104
static double py(int index)
Y momentum.
Definition: EPOS_Wrapper.h:377
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static int event_number()
event number
Definition: EPOS_Wrapper.h:310
bool trust_beam_particles() const
Definition: IO_EPOS.h:69
static int status(int index)
status code
Definition: EPOS_Wrapper.h:317
static void set_position(int index, double x, double y, double z, double t)
set particle production vertex
Definition: EPOS_Wrapper.h:458
static int number_entries()
num entries in current evt
Definition: EPOS_Wrapper.h:312
int find_in_map(const std::map< HepMC::GenParticle *, int > &m, HepMC::GenParticle *p) const
Definition: IO_EPOS.cc:303
static double pz(int index)
Z momentum.
Definition: EPOS_Wrapper.h:381
static double z(int index)
Z Production vertex.
Definition: EPOS_Wrapper.h:403
static int number_children(int index)
number of children
Definition: EPOS_Wrapper.h:368
static int id(int index)
PDG particle id.
Definition: EPOS_Wrapper.h:319
static int max_number_entries()
size of common block
Definition: EPOS_Wrapper.h:218
void build_production_vertex(int i, std::vector< HepMC::GenParticle *> &hepevt_particle, HepMC::GenEvent *evt)
Definition: IO_EPOS.cc:174
void print(std::ostream &ostr=std::cout) const override
Definition: IO_EPOS.cc:25
static int last_child(int index)
index of last daughter
Definition: EPOS_Wrapper.h:353
static int last_parent(int index)
index of last mother
Definition: EPOS_Wrapper.h:328
static double x(int index)
X Production vertex.
Definition: EPOS_Wrapper.h:393
static double px(int index)
X momentum.
Definition: EPOS_Wrapper.h:373
primaryVertex
hltOfflineBeamSpot for HLTMON
static void set_parents(int index, int firstparent, int lastparent)
define parents of a particle
Definition: EPOS_Wrapper.h:429