LCIO  02.17
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LCStdHepRdrNew.cc
Go to the documentation of this file.
1 #include "UTIL/LCStdHepRdrNew.h"
2 #include "EVENT/MCParticle.h"
3 #include "IMPL/MCParticleImpl.h"
4 #include "IMPL/LCEventImpl.h"
5 #include "lcio.h"
6 #include "EVENT/LCIO.h"
7 #include <sstream>
8 //#include <stdlib.h>
9 #include <cmath> // for pow()
10 #include <algorithm>
11 #include "Exceptions.h"
12 
13 using namespace EVENT;
14 using namespace IMPL;
15 
16 #define IDRUP_NAME "_idrup"
17 #define EVTWGT_NAME "_weight"
18 
19 namespace UTIL {
20 
21 LCStdHepRdrNew::LCStdHepRdrNew(const char* evfile) {
22  //
23  // Use Willie's reader from LELAPS, and open the input file
24  //
25  _reader = new UTIL::lStdHep(evfile, false);
26  if (_reader->getError()) {
27  std::stringstream description;
28  description << "LCStdHepRdrNew: no stdhep file: " << evfile << std::ends;
29  throw IO::IOException(description.str());
30  }
31 
32  // _reader->printFileHeader() ;
33 
34 }
35 LCStdHepRdrNew::~LCStdHepRdrNew() {
36 
37  delete _reader;
38 }
39 
40 void LCStdHepRdrNew::printHeader(std::ostream& os) {
41 
42  if (&os == &std::cout) {
43 
44  _reader->printFileHeader();
45  }
46 
47 }
48 
49 void LCStdHepRdrNew::updateNextEvent(IMPL::LCEventImpl* evt, const char* colName) {
50 
51  if (evt == 0) {
52  throw EVENT::Exception(" LCStdHepRdrNew::updateEvent - null pointer for event ");
53  }
54 
55  IMPL::LCCollectionVec* mcpCol = readEvent();
56 
57  if (mcpCol == 0) {
58 
59  throw IO::EndOfDataException(" LCStdHepRdrNew::updateEvent: EOF ");
60  }
61 
62  // copy event parameters from the collection to the event:
63  // FIXME: make this more efficient - not going through paramer map twice....
64 
65  int idrup = mcpCol->getParameters().getIntVal( IDRUP_NAME);
66 
67  evt->parameters().setValue( IDRUP_NAME, idrup);
68 
69  double evtwgt = mcpCol->getParameters().getFloatVal( EVTWGT_NAME);
70 
71  evt->setWeight(evtwgt);
72 
73  // ---- end event parameters ------------------
74 
75  evt->addCollection(mcpCol, colName);
76 
77  if (_writeEventNumber) {
78  std::cout << "LCStdHepRdrNew: setting event number " << _reader->evtNum()
79  << " from StdHep event" << std::endl;
80  evt->setEventNumber(_reader->evtNum());
81  }
82 }
83 
84 //
85 // Read an event and return a LCCollectionVec of MCParticles
86 //
87 IMPL::LCCollectionVec * LCStdHepRdrNew::readEvent() {
88  IMPL::LCCollectionVec * mcVec = 0;
89  double c_light = 299.792; // mm/ns
90  //
91  // Read the event, check for errors
92  //
93 // if( _reader->more() ){
94 
95  int errorcode = _reader->readEvent();
96 
97  if (errorcode != LSH_SUCCESS) {
98 
99  if (errorcode != LSH_ENDOFFILE) {
100 
101  std::stringstream description;
102  description << "LCStdHepRdrNew::readEvent: error when reading event: " << errorcode << std::ends;
103 
104  throw IO::IOException(description.str());
105  }
106 
107  else {
108 
109  return 0;
110  // throw IO::EndOfDataException( " LCStdHepRdrNew::readEvent EOF " ) ;
111  }
112  }
113 
114 // } else {
115 // //
116 // // End of File :: ??? Exception ???
117 // // -> FG: EOF is not an exception as it happens for every file at the end !
118 // //
119 // return mcVec; // == null !
120 // }
121 
122  //
123  // Create a Collection Vector
124  //
125  mcVec = new IMPL::LCCollectionVec(LCIO::MCPARTICLE);
126  MCParticleImpl* p;
127  MCParticleImpl* d;
128  //
129  // Loop over particles
130  //
131  int NHEP = _reader->nTracks();
132 
133  // user defined process id
134  long idrup = _reader->idrup();
135 
136 // static int counter = 0 ;
137 // bool isCritical = false ;
138 // std::cout << " ----- readEvent " << counter << " err: " << errorcode
139 // << " nhep : " << NHEP
140 // << std::endl ;
141 // if( counter++ == 3850 ) {
142 // std::cout << " - critical event read !!! " << std::endl ;
143 // isCritical = true ;
144 // _reader->printEvent() ;
145 // _reader->printEventHeader() ;
146 // for(int bla=0;bla<NHEP;bla++){
147 // _reader->printTrack( bla ) ;
148 // }
149 // }
150 
151  if (idrup != 0) {
152 
153  mcVec->parameters().setValue( IDRUP_NAME, (int) idrup);
154  }
155 
156  double evtWeight = _reader->eventweight();
157 
158  mcVec->parameters().setValue( EVTWGT_NAME, (float) evtWeight);
159 
160  mcVec->resize(NHEP);
161 
162  for (int IHEP = 0; IHEP < NHEP; IHEP++) {
163  //
164  // Create a MCParticle and fill it from stdhep info
165  //
166  MCParticleImpl* mcp = new MCParticleImpl();
167 
168  // and add it to the collection (preserving the order of the hepevt block)
169  mcVec->at(IHEP) = mcp;
170 
171  //
172  // PDGID
173  //
174  mcp->setPDG(_reader->pid(IHEP));
175 
176  //
177  // charge
178  //
179  mcp->setCharge(threeCharge(mcp->getPDG()) / 3.);
180 
181  //
182  // Momentum vector
183  //
184  float p0[3] = {(float)_reader->Px(IHEP),(float)_reader->Py(IHEP),(float)_reader->Pz(IHEP)};
185  mcp->setMomentum(p0);
186  //
187  // Mass
188  //
189  mcp->setMass(_reader->M(IHEP));
190  //
191  // Vertex
192  //
193  double v0[3] = { _reader->X(IHEP), _reader->Y(IHEP), _reader->Z(IHEP) };
194  mcp->setVertex(v0);
195  //
196  // Generator status
197  //
198  mcp->setGeneratorStatus(_reader->status(IHEP));
199  //
200  // Simulator status 0 until simulator acts on it
201  //
202  mcp->setSimulatorStatus(0);
203  //
204  // Creation time (note the units)
205  //
206  mcp->setTime(_reader->T(IHEP) / c_light);
207 
208  // add spin and color flow information if available
209  if (_reader->isStdHepEv4()) {
210 
211  float spin[3] = {(float) _reader->spinX( IHEP ) ,(float) _reader->spinY( IHEP ) , (float) _reader->spinZ( IHEP ) } ;
212  mcp->setSpin(spin);
213 
214  int colorFlow[2] = { (int)_reader->colorflow( IHEP , 0 ) , (int)_reader->colorflow( IHEP , 1 ) } ;
215  mcp->setColorFlow(colorFlow);
216 
217  }
218 
219 // ------
220 // fg 20071120 - ignore mother relation ship altogether and use only daughter relationship
221 // - this is neede to avoid double counting in Mokka geant4 simulation
222 // - however some information might be lost here if encoded in inconsistent parent
223 // daughter relationships...
224 
225 //
226 //
227 // //
228 // // Add the parent information. The implicit assumption here is that
229 // // no particle is read in before its parents.
230 // //
231 // int fp = _reader->mother1(IHEP) - 1;
232 // int lp = _reader->mother2(IHEP) - 1;
233 
234 // // if( isCritical ) {
235 // // std::cout << " parents: fp : " << fp << " lp : " << lp << std::endl ;
236 // // }
237 
238 // //
239 // // If both first parent and second parent > 0, and second parent >
240 // // first parent, assume a range
241 // //
242 // if( (fp > -1) && (lp > -1) )
243 // {
244 // if(lp >= fp)
245 // {
246 // for(int ip=fp;ip<lp+1;ip++)
247 // {
248 // p = dynamic_cast<MCParticleImpl*>
249 // (mcVec->getElementAt(ip));
250 // mcp->addParent(p);
251 // }
252 // }
253 // //
254 // // If first parent < second parent, assume 2 discreet parents
255 // //
256 // else
257 // {
258 // p = dynamic_cast<MCParticleImpl*>
259 // (mcVec->getElementAt(fp));
260 // mcp->addParent(p);
261 // p = dynamic_cast<MCParticleImpl*>
262 // (mcVec->getElementAt(lp));
263 // mcp->addParent(p);
264 // }
265 // }
266 // //
267 // // Only 1 parent > 0, set it
268 // //
269 // else if(fp > -1)
270 // {
271 // p = dynamic_cast<MCParticleImpl*>
272 // (mcVec->getElementAt(fp));
273 // mcp->addParent(p);
274 // }
275 // else if(lp > -1)
276 // {
277 // p = dynamic_cast<MCParticleImpl*>
278 // (mcVec->getElementAt(lp));
279 // mcp->addParent(p);
280 // }
281 
282  } // End loop over particles
283 
284 // fg 20071120 - as we ignore mother relation ship altogether this loop now
285 // creates the parent-daughter
286 
287  //
288  // Now make a second loop over the particles, checking the daughter
289  // information. This is not always consistent with parent
290  // information, and this utility assumes all parents listed are
291  // parents and all daughters listed are daughters
292  //
293  for (int IHEP = 0; IHEP < NHEP; IHEP++) {
294  //
295  // Get the MCParticle
296  //
297  MCParticleImpl* mcp = dynamic_cast<MCParticleImpl*>(mcVec->getElementAt(IHEP));
298  //
299  // Get the daughter information, discarding extra information
300  // sometimes stored in daughter variables.
301  //
302  int fd = _reader->daughter1(IHEP) % 10000 - 1;
303  int ld = _reader->daughter2(IHEP) % 10000 - 1;
304 
305 // if( isCritical ) {
306 // std::cout << "daughters fd : " << fd << " ld : " << ld << std::endl ;
307 // }
308 
309  //
310  // As with the parents, look for range, 2 discreet or 1 discreet
311  // daughter.
312  //
313  if ((fd > -1) && (ld > -1)) {
314  if (ld >= fd) {
315  for (int id = fd; id < ld + 1; id++) {
316  //
317  // Get the daughter, and see if it already lists this particle as
318  // a parent.
319  //
320  d = dynamic_cast<MCParticleImpl*>(mcVec->getElementAt(id));
321  int np = d->getParents().size();
322  bool gotit = false;
323  for (int ip = 0; ip < np; ip++) {
324  p = dynamic_cast<MCParticleImpl*>(d->getParents()[ip]);
325  if (p == mcp)
326  gotit = true;
327  }
328  //
329  // If not already listed, add this particle as a parent
330  //
331  if (!gotit)
332  d->addParent(mcp);
333  }
334  }
335  //
336  // Same logic, discreet cases
337  //
338  else {
339  d = dynamic_cast<MCParticleImpl*>(mcVec->getElementAt(fd));
340  int np = d->getParents().size();
341  bool gotit = false;
342  for (int ip = 0; ip < np; ip++) {
343  p = dynamic_cast<MCParticleImpl*>(d->getParents()[ip]);
344  if (p == mcp)
345  gotit = true;
346  }
347  if (!gotit)
348  d->addParent(mcp);
349  d = dynamic_cast<MCParticleImpl*>(mcVec->getElementAt(ld));
350  np = d->getParents().size();
351  gotit = false;
352  for (int ip = 0; ip < np; ip++) {
353  p = dynamic_cast<MCParticleImpl*>(d->getParents()[ip]);
354  if (p == mcp)
355  gotit = true;
356  }
357  if (!gotit)
358  d->addParent(mcp);
359  }
360  } else if (fd > -1) {
361 
362  if (fd < NHEP) {
363  d = dynamic_cast<MCParticleImpl*>(mcVec->getElementAt(fd));
364  int np = d->getParents().size();
365  bool gotit = false;
366  for (int ip = 0; ip < np; ip++) {
367  p = dynamic_cast<MCParticleImpl*>(d->getParents()[ip]);
368  if (p == mcp)
369  gotit = true;
370  }
371  if (!gotit)
372  d->addParent(mcp);
373 
374  } else {
375  //FIXME: whizdata has lots of of illegal daughter indices 21 < NHEP
376 // std::cout << " WARNING: LCStdhepReader: invalid index in stdhep : " << fd
377 // << " NHEP = " << NHEP << " - ignored ! " << std::endl ;
378  }
379 
380  }
381 // --------- fg: ignore daughters if the first daughter index is illegal (0 in stdhep, -1 here)
382 // else if(ld > -1 )
383 // {
384 // std::cout << " WARNING: LCStdhepReader: illegal daughter index in stdhep : " << ld
385 // << " NHEP = " << NHEP << " - ignored ! " << std::endl ;
386  // if( ld < NHEP ){
387  // d = dynamic_cast<MCParticleImpl*>
388  // (mcVec->getElementAt(ld));
389  // int np = d->getParents().size();
390  // bool gotit = false;
391  // for(int ip=0;ip < np;ip++)
392  // {
393  // p = dynamic_cast<MCParticleImpl*>
394  // (d->getParents()[ip]);
395  // if(p == mcp)gotit = true;
396  // }
397  // if(!gotit)d->addParent(mcp);
398 
399  // } else {
400  // //FIXME: whizdata has lots of of illegal daughter indices 21 < NHEP
401  // // std::cout << " WARNING: LCStdhepReader: invalid index in stdhep : " << ld
402  // // << " NHEP = " << NHEP << " - ignored ! " << std::endl ;
403 
404  // }
405 
406  // }
407 
408  } // End second loop over particles
409 
410  // ==========================================================================
411  // This code looks for entries with generator status 2, which do not have daughters assigned and tests if
412  // these inconsistencies are repairable with following 94 state. (B. Vormwald)
413  int nic = 0;
414  for (int IHEP = 0; IHEP < NHEP; IHEP++) {
415 
416  MCParticleImpl* mcp = dynamic_cast<MCParticleImpl*>(mcVec->getElementAt(IHEP));
417 
418  // find inconsistencies
419  if ((mcp->getGeneratorStatus() == 2) && (mcp->getDaughters().size() == 0)) {
420  //printf("inconsistency found in line %i (nic: %i->%i)\n", IHEP,nic,nic+1);
421  nic++;
422  }
423 
424  //try to repair inconsistencies when a 94 is present!
425  if ((nic > 0) && (mcp->getPDG() == 94)) {
426  //printf("generator status 94 found in line %i\n",IHEP);
427 
428  int parentid = _reader->mother1(IHEP) % 10000 - 1;
429  int firstdau = _reader->daughter1(IHEP) % 10000 - 1;
430  int lastdau = _reader->daughter2(IHEP) % 10000 - 1;
431  unsigned outn = ( ( lastdau-firstdau +1 ) > 0 ? lastdau-firstdau +1 : 0 ) ;
432  //printf("found first parent in line %i\n",parentid);
433  MCParticleImpl* parent;
434 
435  //check if inconsistency appeared within lines [firstparent -> (IHEP-1)]
436  //if yes, fix relation!
437  for (unsigned int nextparentid = parentid; IHEP - nextparentid > 0; nextparentid++) {
438  //printf(" check line %i ", nextparentid);
439  parent = dynamic_cast<MCParticleImpl*>(mcVec->getElementAt(nextparentid));
440  if ((parent->getGeneratorStatus() == 2) && (parent->getDaughters().size() == 0)
441  && mcp->getParents().size() < outn) {
442  mcp->addParent(parent);
443  //printf(" -> relation fixed\n");
444  nic--;
445  }
446  //else {
447  // if (parent->getDaughters()[0]==mcp){
448  // printf(" -> relation checked\n");
449  // }
450  // else {
451  // printf(" -> other relation\n");
452  // }
453  //}
454  }
455  }
456  }
457  //if (nic>0) printf("WARNING: %i inconsistencies in event\n", nic);
458  // ==========================================================================
459 
460  // Handle daughter particles pointing to parent where relationship is not already present. --JM
461  for (int IHEP = 0; IHEP < NHEP; IHEP++) {
462  int mom1 = _reader->mother1(IHEP) - 1;
463  int mom2 = _reader->mother2(IHEP) - 1;
464  // int dau1 = _reader->daughter1(IHEP) - 1;
465  // int dau2 = _reader->daughter1(IHEP) - 1;
466  MCParticleImpl* mcDau = (MCParticleImpl*) mcVec->getElementAt(IHEP);
467  if (mom1 > 0 && mom2 == -1) {
468  MCParticleImpl* mcPar = (MCParticleImpl*) mcVec->getElementAt(mom1);
469  EVENT::MCParticleVec dauVec = mcPar->getDaughters();
470  bool hasDau = (std::find(dauVec.begin(), dauVec.end(), mcDau) != dauVec.end());
471  if (!hasDau) {
472  mcDau->addParent(mcPar);
473  }
474  } else if (mom1 > -1 && mom2 > -1) {
475  for (int i = mom1; i <= mom2; i++) {
476  MCParticleImpl* mcPar = (MCParticleImpl*) mcVec->getElementAt(i);
477  EVENT::MCParticleVec dauVec = mcPar->getDaughters();
478  bool hasDau = (std::find(dauVec.begin(), dauVec.end(), mcDau) != dauVec.end());
479  if (!hasDau) {
480  mcDau->addParent(mcPar);
481  }
482  }
483  }
484  }
485 
486  return mcVec;
487 }
488 
489 int LCStdHepRdrNew::threeCharge(int pdgID) const {
490  //
491  // code copied from HepPDT package, author L.Garren
492  // modified to take pdg
493 
496  enum location {
497  nj = 1, nq3, nq2, nq1, nl, nr, n, n8, n9, n10
498  };
499 
500  int charge = 0;
501  int ida, sid;
502  unsigned short q1, q2, q3;
503  static const int ch100[100] = { -1, 2, -1, 2, -1, 2, -1, 2, 0, 0, -3, 0, -3, 0, -3, 0, -3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
504  0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
505  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
506  0 };
507 
508  ida = (pdgID < 0) ? -pdgID : pdgID;
509 
510  // q1 = digit(nq1);
511  // q2 = digit(nq2);
512  // q3 = digit(nq3);
513 
514  q1 = (ida / ((int) std::pow(10.0, (nq1 - 1)))) % 10;
515  q2 = (ida / ((int) std::pow(10.0, (nq2 - 1)))) % 10;
516  q3 = (ida / ((int) std::pow(10.0, (nq3 - 1)))) % 10;
517 
518 // sid = fundamentalID();
519  //---- ParticleID::fundamentalID -------
520  short dig_n9 = (ida / ((int) std::pow(10.0, (n9 - 1)))) % 10;
521  short dig_n10 = (ida / ((int) std::pow(10.0, (n10 - 1)))) % 10;
522 
523  if ((dig_n10 == 1) && (dig_n9 == 0)) {
524 
525  sid = 0;
526  } else if (q2 == 0 && q1 == 0) {
527 
528  sid = ida % 10000;
529  } else if (ida <= 102) {
530 
531  sid = ida;
532  } else {
533 
534  sid = 0;
535  }
536  //----------------
537 
538  int extraBits = ida / 10000000;
539  // everything beyond the 7th digit (e.g. outside the numbering scheme)
540 
541  short dig_nj = (ida / ((int) std::pow(10.0, (nj - 1)))) % 10;
542 
543  if (ida == 0 || extraBits > 0) { // ion or illegal
544  return 0;
545  } else if (sid > 0 && sid <= 100) { // use table
546  charge = ch100[sid - 1];
547  if (ida == 1000017 || ida == 1000018) {
548  charge = 0;
549  }
550  if (ida == 1000034 || ida == 1000052) {
551  charge = 0;
552  }
553  if (ida == 1000053 || ida == 1000054) {
554  charge = 0;
555  }
556  if (ida == 5100061 || ida == 5100062) {
557  charge = 6;
558  }
559  } else if (dig_nj == 0) { // KL, Ks, or undefined
560  return 0;
561  } else if (q1 == 0) { // mesons
562  if (q2 == 3 || q2 == 5) {
563  charge = ch100[q3 - 1] - ch100[q2 - 1];
564  } else {
565  charge = ch100[q2 - 1] - ch100[q3 - 1];
566  }
567  } else if (q3 == 0) { // diquarks
568  charge = ch100[q2 - 1] + ch100[q1 - 1];
569  } else { // baryons
570  charge = ch100[q3 - 1] + ch100[q2 - 1] + ch100[q1 - 1];
571  }
572  if (charge == 0) {
573  return 0;
574  } else if (pdgID < 0) {
575  charge = -charge;
576  }
577  return charge;
578 }
579 
580 } // namespace UTIL
581 
Base exception class for LCIO - all other exceptions extend this.
Definition: Exceptions.h:21
virtual EVENT::LCParameters & parameters()
Parameters defined for this run.
virtual EVENT::LCObject * getElementAt(int index) const
Returns pointer to element at index - no range check !.
void setWeight(double w)
Set the event weight.
Definition: LCEventImpl.cc:168
void setTime(float time)
Sets the createion time.
Implementation of the LCCollection using (inheriting from) an STL vector of LCObjects.
Implementation of the main event class.
Definition: LCEventImpl.h:31
T endl(T...args)
virtual const EVENT::LCParameters & getParameters() const
Parameters defined for this run.
virtual const EVENT::MCParticleVec & getParents() const
Returns the parents of this particle.
T end(T...args)
virtual int getGeneratorStatus() const
Returns the status for particles from the generator 0 empty line 1 undecayed particle, stable in the generator 2 particle decayed in the generator 3 documentation line.
void setGeneratorStatus(int status)
Sets the Generator status.
void addParent(EVENT::MCParticle *mom)
Adds a parent particle.
T resize(T...args)
virtual void addCollection(EVENT::LCCollection *col, const std::string &name)
Adds a collection with the given name (has to be a valid C/C++ variable name).
Definition: LCEventImpl.cc:107
T at(T...args)
#define IDRUP_NAME
void setColorFlow(const int cflow[2])
Sets the color flow.
void setSimulatorStatus(int status)
Sets the Simulator status.
#define LSH_ENDOFFILE
Definition: lStdHep.hh:60
void setEventNumber(int en)
Sets the event number.
Definition: LCEventImpl.cc:150
void setMass(float m)
Sets the mass.
void setMomentum(const float p[3])
Sets the momentum.
T str(T...args)
IOException used for reading/writing errors.
Definition: Exceptions.h:92
void setVertex(const double vtx[3])
Sets the production vertex.
virtual void setValue(const std::string &key, int value)=0
Set integer value for the given key.
virtual float getFloatVal(const std::string &key) const =0
Returns the first float value for the given key.
void setCharge(float c)
Sets the charge.
virtual const EVENT::MCParticleVec & getDaughters() const
Returns the daughters of this particle.
virtual EVENT::LCParameters & parameters()
Parameters defined for this run.
Definition: LCEventImpl.h:135
void setPDG(int pdg)
Sets the parent.
T find(T...args)
T size(T...args)
T ends(T...args)
T begin(T...args)
T pow(T...args)
virtual int getIntVal(const std::string &key) const =0
Returns the first integer value for the given key.
EndOfDataException for signaling the end of a data stream.
Definition: Exceptions.h:108
#define LSH_SUCCESS
Definition: lStdHep.hh:54
void setSpin(const float spin[3])
Sets the spin.
virtual int getPDG() const
Returns the number of daughters of this particle.
STL class.
Implementation of MCParticle.
#define EVTWGT_NAME