CMS 3D CMS Logo

NuclearInteractionSimulator.cc
Go to the documentation of this file.
1 //Framework Headers
4 
8 
10 
11 //#include "DQMServices/Core/interface/DaqMonitorBEInterface.h"
12 //#include "FWCore/ServiceRegistry/interface/Service.h"
13 
14 #include <iostream>
15 #include <sys/stat.h>
16 #include <cmath>
17 #include "TFile.h"
18 #include "TTree.h"
19 #include "TROOT.h"
20 
21 // Internal variable and vectors with name started frm "thePion" means
22 // vectors/variable not only for pions but for all type of hadrons
23 // treated inside this code
24 
26  std::vector<double>& hadronEnergies,
27  std::vector<int>& hadronTypes,
28  std::vector<std::string>& hadronNames,
29  std::vector<double>& hadronMasses,
30  std::vector<double>& hadronPMin,
31  double pionEnergy,
32  std::vector<double>& lengthRatio,
33  std::vector< std::vector<double> >& ratios,
34  std::map<int,int >& idMap,
36  unsigned int distAlgo,
37  double distCut)
38  :
40  thePionEN(hadronEnergies),
41  thePionID(hadronTypes),
42  thePionNA(hadronNames),
43  thePionMA(hadronMasses),
44  thePionPMin(hadronPMin),
45  thePionEnergy(pionEnergy),
46  theLengthRatio(lengthRatio),
47  theRatios(ratios),
48  theIDMap(idMap),
49  theDistAlgo(distAlgo),
50  theDistCut(distCut),
51  currentValuesWereSet(false)
52 {
53  std::string fullPath;
54 
55  // Prepare the map of files
56  // Loop over the particle names
57  TFile* aVFile=nullptr;
58  std::vector<TTree*> aVTree(thePionEN.size(),static_cast<TTree*>(nullptr));
59  std::vector<TBranch*> aVBranch(thePionEN.size(),static_cast<TBranch*>(nullptr));
60  std::vector<NUEvent*> aVNUEvents(thePionEN.size(),static_cast<NUEvent*>(nullptr));
61  std::vector<unsigned> aVCurrentEntry(thePionEN.size(),static_cast<unsigned>(0));
62  std::vector<unsigned> aVCurrentInteraction(thePionEN.size(),static_cast<unsigned>(0));
63  std::vector<unsigned> aVNumberOfEntries(thePionEN.size(),static_cast<unsigned>(0));
64  std::vector<unsigned> aVNumberOfInteractions(thePionEN.size(),static_cast<unsigned>(0));
65  std::vector<std::string> aVFileName(thePionEN.size(),static_cast<std::string>(""));
66  std::vector<double> aVPionCM(thePionEN.size(),static_cast<double>(0));
67 
68  theTrees.resize(thePionNA.size());
69  theBranches.resize(thePionNA.size());
70  theNUEvents.resize(thePionNA.size());
71  theCurrentEntry.resize(thePionNA.size());
72  theCurrentInteraction.resize(thePionNA.size());
73  theNumberOfEntries.resize(thePionNA.size());
74  theNumberOfInteractions.resize(thePionNA.size());
75  theFileNames.resize(thePionNA.size());
76  thePionCM.resize(thePionNA.size());
77  theFile = aVFile;
78  for ( unsigned iname=0; iname<thePionNA.size(); ++iname ) {
79  theTrees[iname] = aVTree;
80  theBranches[iname] = aVBranch;
81  theNUEvents[iname] = aVNUEvents;
82  theCurrentEntry[iname] = aVCurrentEntry;
83  theCurrentInteraction[iname] = aVCurrentInteraction;
84  theNumberOfEntries[iname] = aVNumberOfEntries;
85  theNumberOfInteractions[iname] = aVNumberOfInteractions;
86  theFileNames[iname] = aVFileName;
87  thePionCM[iname] = aVPionCM;
88  }
89 
90  // Read the information from a previous run (to keep reproducibility)
91  currentValuesWereSet = this->read(inputFile);
93  std::cout << "***WARNING*** You are reading nuclear-interaction information from the file "
94  << inputFile << " created in an earlier run."
95  << std::endl;
96 
97  // Open the file for saving the information of the current run
98  myOutputFile.open ("NuclearInteractionOutputFile.txt");
99  myOutputBuffer = 0;
100 
101 
102  // Open the root files
103  // for ( unsigned file=0; file<theFileNames.size(); ++file ) {
104  edm::FileInPath myDataFile("FastSimulation/MaterialEffects/data/NuclearInteractions.root");
105 
106  fullPath = myDataFile.fullPath();
107  theFile = TFile::Open(fullPath.c_str());
108 
109  unsigned fileNb = 0;
110  for ( unsigned iname=0; iname<thePionNA.size(); ++iname ) {
111  for ( unsigned iene=0; iene<thePionEN.size(); ++iene ) {
112  //std::cout << "iname/iene " << iname << " " << iene << std::endl;
113  std::ostringstream filename;
114  double theEne = thePionEN[iene];
115  filename << "NuclearInteractionsVal_" << thePionNA[iname] << "_E"<< theEne << ".root";
116  theFileNames[iname][iene] = filename.str();
117  //std::cout << "thePid/theEne " << thePionID[iname] << " " << theEne << std::endl;
118 
119  ++fileNb;
120  std::string treeName="NuclearInteractions_"+thePionNA[iname]+"_E"+std::to_string(int(theEne));
121  //
122  theTrees[iname][iene] = (TTree*) theFile->Get(treeName.c_str());
123  if ( !theTrees[iname][iene] ) throw cms::Exception("FastSimulation/MaterialEffects")
124  << "Tree with name " << treeName << " not found ";
125  //
126  theBranches[iname][iene] = theTrees[iname][iene]->GetBranch("nuEvent");
127  //std::cout << "The branch = " << theBranches[iname][iene] << std::endl;
128  if ( !theBranches[iname][iene] ) throw cms::Exception("FastSimulation/MaterialEffects")
129  << "Branch with name nuEvent not found in " << theFileNames[iname][iene];
130  //
131  theNUEvents[iname][iene] = new NUEvent();
132  //std::cout << "The branch = " << theBranches[iname][iene] << std::endl;
133  theBranches[iname][iene]->SetAddress(&theNUEvents[iname][iene]);
134  //
135  theNumberOfEntries[iname][iene] = theTrees[iname][iene]->GetEntries();
136 
138  theTrees[iname][iene]->GetEntry(theCurrentEntry[iname][iene]);
139  unsigned NInteractions = theNUEvents[iname][iene]->nInteractions();
140  theNumberOfInteractions[iname][iene] = NInteractions;
141  }
142 
143  //
144  // Compute the corresponding cm energies of the nuclear interactions
145  XYZTLorentzVector Proton(0.,0.,0.,0.986);
147  Reference(0.,
148  0.,
149  std::sqrt(thePionEN[iene]*thePionEN[iene]
150  -thePionMA[iname]*thePionMA[iname]),
151  thePionEN[iene]);
152  thePionCM[iname][iene] = (Reference+Proton).M();
153 
154  }
155 
156  }
157 
158  // Find the index for which EN = 4. (or thereabout)
159  ien4 = 0;
160  while ( thePionEN[ien4] < 4.0 ) ++ien4;
161 
162  gROOT->cd();
163 
164  // Information (Should be on LogInfo)
165 // std::cout << " ---> A total of " << fileNb
166 // << " nuclear-interaction files was sucessfully open" << std::endl;
167 
168  // dbe = edm::Service<DaqMonitorBEInterface>().operator->();
169  // htot = dbe->book1D("Total", "All particles",150,0.,150.);
170  // helas = dbe->book1D("Elastic", "Elastic interactions",150,0.,150.);
171  // hinel = dbe->book1D("Inelastic", "Inelastic interactions",150,0.,150.);
172  // hscatter = dbe->book1D("Scattering","Elastic Scattering angle",200,0.,2.);
173  // hscatter2 = dbe->book2D("Scattering2","Elastic Scattering angle vs p",100,0.,10.,200,0.,2.);
174  // hAfter = dbe->book1D("eAfter","Energy after collision",200,0.,4.);
175  // hAfter2 = dbe->book2D("eAfter2","Energy after collision",100,-2.5,2.5,100,0.,4);
176  // hAfter3 = dbe->book2D("eAfter3","Energy after collision",100,0.,1000.,100,0.,4);
177 
178 }
179 
181 
182  // Close all local files
183  // Among other things, this allows the TROOT destructor to end up
184  // without crashing, while trying to close these files from outside
185  theFile->Close();
186  delete theFile;
187 
188  for(auto& vEvents: theNUEvents) {
189  for(auto evtPtr: vEvents) {
190  delete evtPtr;
191  }
192  }
193 
194  // Close the output file
195  myOutputFile.close();
196 
197  // dbe->save("test.root");
198 
199 }
200 
202 {
203  if(!currentValuesWereSet) {
204  currentValuesWereSet = true;
205  for ( unsigned iname=0; iname<thePionNA.size(); ++iname ) {
206  for ( unsigned iene=0; iene<thePionEN.size(); ++iene ) {
207  theCurrentEntry[iname][iene] = (unsigned) (theNumberOfEntries[iname][iene] * random->flatShoot());
208 
209  theTrees[iname][iene]->GetEntry(theCurrentEntry[iname][iene]);
210  unsigned NInteractions = theNUEvents[iname][iene]->nInteractions();
211  theNumberOfInteractions[iname][iene] = NInteractions;
212 
213  theCurrentInteraction[iname][iene] = (unsigned) (theNumberOfInteractions[iname][iene] * random->flatShoot());
214  }
215  }
216  }
217 
218  // Read a Nuclear Interaction in a random manner
219 
220  double pHadron = std::sqrt(Particle.particle().Vect().Mag2());
221  // htot->Fill(pHadron);
222 
223  // The hadron has enough momentum to create some relevant final state
224  if ( pHadron > thePionEnergy ) {
225 
226  // The particle type
227  std::map<int,int>::const_iterator thePit = theIDMap.find(Particle.particle().pid());
228 
229  int thePid = thePit != theIDMap.end() ? thePit->second : Particle.particle().pid();
230 
231  // Is this particle type foreseen?
232  unsigned fPid = abs(thePid);
233  if ( fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212 ) {
234  return;
235  //std::cout << "Unknown particle type = " << thePid << std::endl;
236  //thePid = 211;
237  }
238 
239  // The inelastic interaction length at p(pion) = 5 GeV/c
240  unsigned thePidIndex = index(thePid);
241  double theInelasticLength = radLengths * theLengthRatio[thePidIndex];
242 
243  // The elastic interaction length
244  // The baroque parameterization is a fit to Fig. 40.13 of the PDG
245  double ee = pHadron > 0.6 ?
246  exp(-std::sqrt((pHadron-0.6)/1.122)) : exp(std::sqrt((0.6-pHadron)/1.122));
247  double theElasticLength = ( 0.8753 * ee + 0.15 )
248  // double theElasticLength = ( 0.15 + 0.195 / log(pHadron/0.4) )
249  // double theElasticLength = ( 0.15 + 0.305 / log(pHadron/0.35) )
250  * theInelasticLength;
251 
252  // The total interaction length
253  double theTotalInteractionLength = theInelasticLength + theElasticLength;
254 
255  // Probability to interact is dl/L0 (maximum for 4 GeV pion)
256  double aNuclInteraction = -std::log(random->flatShoot());
257  if ( aNuclInteraction < theTotalInteractionLength ) {
258 
259  // The elastic part
260  double elastic = random->flatShoot();
261  if ( elastic < theElasticLength/theTotalInteractionLength ) {
262 
263  // helas->Fill(pHadron);
264 
265  // Characteristic scattering angle for the elastic part
266  double theta0 = std::sqrt(3.)/ std::pow(theA(),1./3.) * Particle.particle().mass()/pHadron;
267 
268  // Draw an angle with theta/theta0*exp[(-theta/2theta0)**2] shape
269  double theta = theta0 * std::sqrt(-2.*std::log(random->flatShoot()));
270  double phi = 2. * 3.14159265358979323 * random->flatShoot();
271 
272  // Rotate the particle accordingly
273  RawParticle::Rotation rotation1(orthogonal(Particle.particle().Vect()),theta);
274  RawParticle::Rotation rotation2(Particle.particle().Vect(),phi);
275  Particle.particle().rotate(rotation1);
276  Particle.particle().rotate(rotation2);
277 
278  // Distance
279  double distance = std::sin(theta);
280 
281  // Create a daughter if the kink is large engough
282  if ( distance > theDistCut ) {
283  _theUpdatedState.reserve(1);
284  _theUpdatedState.clear();
285  _theUpdatedState.emplace_back(Particle.particle());
286  }
287 
288  // hscatter->Fill(myTheta);
289  // hscatter2->Fill(pHadron,myTheta);
290 
291  }
292 
293  // The inelastic part
294  else {
295 
296  // Avoid multiple map access
297  const std::vector<double>& aPionCM = thePionCM[thePidIndex];
298  const std::vector<double>& aRatios = theRatios[thePidIndex];
299  // Find the file with the closest c.m energy
300  // The target nucleon
301  XYZTLorentzVector Proton(0.,0.,0.,0.939);
302  // The current particle
303  const XYZTLorentzVector& Hadron = (const XYZTLorentzVector&)Particle;
304  // The smallest momentum for inelastic interactions
305  double pMin = thePionPMin[thePidIndex];
306  // The correspong smallest four vector
307  XYZTLorentzVector Hadron0(0.,0.,pMin,std::sqrt(pMin*pMin+Particle.particle().M2()));
308 
309  // The current centre-of-mass energy
310  double ecm = (Proton+Hadron).M();
311  //std::cout << "Proton = " << Proton << std::endl;
312  //std::cout << "Hadron = " << Hadron << std::endl;
313  //std::cout << "ecm = " << ecm << std::endl;
314  // Get the files of interest (closest c.m. energies)
315  unsigned ene1=0;
316  unsigned ene2=0;
317  // The smallest centre-of-mass energy
318  // double ecm1=1.63;
319  double ecm1= (Proton+Hadron0).M();
320  //std::cout << "ecm1 = " << ecm1 << std::endl;
321  //std::cout << "ecm[0] = " << aPionCM[0] << std::endl;
322  //std::cout << "ecm[11] = " << aPionCM [ aPionCM.size()-1 ] << std::endl;
323  double ecm2=aPionCM[0];
324  double ratio1=0.;
325  double ratio2=aRatios[0];
326  if ( ecm > aPionCM[0] && ecm < aPionCM [ aPionCM.size()-1 ] ) {
327  for ( unsigned ene=1;
328  ene < aPionCM.size() && ecm > aPionCM[ene-1];
329  ++ene ) {
330  if ( ecm<aPionCM[ene] ) {
331  ene2 = ene;
332  ene1 = ene2-1;
333  ecm1 = aPionCM[ene1];
334  ecm2 = aPionCM[ene2];
335  ratio1 = aRatios[ene1];
336  ratio2 = aRatios[ene2];
337  }
338  }
339  } else if ( ecm > aPionCM[ aPionCM.size()-1 ] ) {
340  ene1 = aPionCM.size()-1;
341  ene2 = aPionCM.size()-2;
342  ecm1 = aPionCM[ene1];
343  ecm2 = aPionCM[ene2];
344  ratio1 = aRatios[ene2];
345  ratio2 = aRatios[ene2];
346  }
347 
348 
349  // The inelastic part of the cross section depends cm energy
350  double slope = (std::log10(ecm )-std::log10(ecm1))
351  / (std::log10(ecm2)-std::log10(ecm1));
352  double inelastic = ratio1 + (ratio2-ratio1) * slope;
353  double inelastic4 = pHadron < 4. ? aRatios[ien4] : 1.;
354 
355  //std::cout << "Inelastic = " << ratio1 << " " << ratio2 << " " << inelastic << std::endl;
356  // std::cout << "Energy/Inelastic : "
357  // << Hadron.e() << " " << inelastic << std::endl;
358 
359  // Simulate an inelastic interaction
360  if ( elastic > 1.- (inelastic*theInelasticLength)
361  /theTotalInteractionLength ) {
362 
363  // Avoid mutliple map access
364  std::vector<unsigned>& aCurrentInteraction = theCurrentInteraction[thePidIndex];
365  std::vector<unsigned>& aNumberOfInteractions = theNumberOfInteractions[thePidIndex];
366  std::vector<NUEvent*>& aNUEvents = theNUEvents[thePidIndex];
367  // hinel->Fill(pHadron);
368  // std::cout << "INELASTIC INTERACTION ! "
369  // << pHadron << " " << theInelasticLength << " "
370  // << inelastic * theInelasticLength << std::endl;
371  // Choice of the file to read according the the log10(ecm) distance
372  // and protection against low momentum proton and neutron that never interacts
373  // (i.e., empty files)
374  unsigned ene;
375  if ( random->flatShoot() < slope || aNumberOfInteractions[ene1] == 0 )
376  ene = ene2;
377  else
378  ene = ene1;
379 
380  //std::cout << "Ecm1/2 = " << ecm1 << " " << ecm2 << std::endl;
381  //std::cout << "Ratio1/2 = " << ratio1 << " " << ratio2 << std::endl;
382  //std::cout << "Ene = " << ene << " slope = " << slope << std::endl;
383 
384  //std::cout << "Pion energy = " << Hadron.E()
385  // << "File chosen " << theFileNames[thePidIndex][ene]
386  // << std::endl;
387 
388  // The boost characteristics
389  XYZTLorentzVector theBoost = Proton + Hadron;
390  theBoost /= theBoost.e();
391 
392  // std::cout << "File chosen : " << thePid << "/" << ene
393  // << " Current interaction = " << aCurrentInteraction[ene]
394  // << " Total interactions = " << aNumberOfInteractions[ene]
395  // << std::endl;
396  // theFiles[thePidIndex][ene]->cd();
397  // gDirectory->ls();
398 
399  // Check we are not either at the end of an interaction bunch
400  // or at the end of a file
401  if ( aCurrentInteraction[ene] == aNumberOfInteractions[ene] ) {
402  // std::cout << "End of interaction bunch ! ";
403  std::vector<unsigned>& aCurrentEntry = theCurrentEntry[thePidIndex];
404  std::vector<unsigned>& aNumberOfEntries = theNumberOfEntries[thePidIndex];
405  std::vector<TTree*>& aTrees = theTrees[thePidIndex];
406  ++aCurrentEntry[ene];
407  // std::cerr << "Read the next entry "
408  // << aCurrentEntry[ene] << std::endl;
409  aCurrentInteraction[ene] = 0;
410  if ( aCurrentEntry[ene] == aNumberOfEntries[ene] ) {
411  aCurrentEntry[ene] = 0;
412  // std::cout << "End of file - Rewind! " << std::endl;
413  }
414  unsigned myEntry = aCurrentEntry[ene];
415  // std::cout << "The new entry " << myEntry
416  // << " is read ... in TTree " << aTrees[ene] << " ";
417  aTrees[ene]->GetEntry(myEntry);
418  // std::cout << "The number of interactions in the new entry is ... ";
419  aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
420  // std::cout << aNumberOfInteractions[ene] << std::endl;
421  }
422 
423  // Read the interaction
424  NUEvent::NUInteraction anInteraction
425  = aNUEvents[ene]->theNUInteractions()[aCurrentInteraction[ene]];
426 
427  unsigned firstTrack = anInteraction.first;
428  unsigned lastTrack = anInteraction.last;
429  // std::cout << "First and last tracks are " << firstTrack << " " << lastTrack << std::endl;
430 
431  _theUpdatedState.reserve(lastTrack-firstTrack+1);
432  _theUpdatedState.clear();
433 
434  double distMin = 1E99;
435 
436  // Some rotation around the boost axis, for more randomness
437  XYZVector theAxis = theBoost.Vect().Unit();
438  double theAngle = random->flatShoot() * 2. * 3.14159265358979323;
439  RawParticle::Rotation axisRotation(theAxis,theAngle);
440  RawParticle::Boost axisBoost(theBoost.x(),theBoost.y(),theBoost.z());
441 
442  // A rotation to bring the particles back to the pion direction
443  XYZVector zAxis(0.,0.,1.);
444  XYZVector orthAxis = (zAxis.Cross(theBoost.Vect())).Unit();
445  double orthAngle = acos(theBoost.Vect().Unit().Z());
446  RawParticle::Rotation orthRotation(orthAxis,orthAngle);
447 
448  // A few checks
449  // double eAfter = 0.;
450 
451  // Loop on the nuclear interaction products
452  for ( unsigned iTrack=firstTrack; iTrack<=lastTrack; ++iTrack ) {
453 
454  unsigned idaugh = iTrack - firstTrack;
455  NUEvent::NUParticle aParticle = aNUEvents[ene]->theNUParticles()[iTrack];
456  // std::cout << "Track " << iTrack
457  // << " id/px/py/pz/mass "
458  // << aParticle.id << " "
459  // << aParticle.px << " "
460  // << aParticle.py << " "
461  // << aParticle.pz << " "
462  // << aParticle.mass << " " << endl;
463 
464  // Add a RawParticle with the proper energy in the c.m frame of
465  // the nuclear interaction
466  double energy = std::sqrt( aParticle.px*aParticle.px
467  + aParticle.py*aParticle.py
468  + aParticle.pz*aParticle.pz
469  + aParticle.mass*aParticle.mass/(ecm*ecm) );
470 
471  RawParticle& aDaughter = _theUpdatedState.emplace_back(makeParticle(Particle.particleDataTable(),
472  aParticle.id,
474  aParticle.px*ecm,aParticle.py*ecm,
475  aParticle.pz*ecm,energy*ecm)));
476  // Rotate to the collision axis
477  aDaughter.rotate(orthRotation);
478 
479  // Rotate around the boost axis for more randomness
480  aDaughter.rotate(axisRotation);
481 
482  // Boost it in the lab frame
483  aDaughter.boost(axisBoost);
484 
485  // Store the closest daughter index (for later tracking purposes, so charged particles only)
486  double distance = distanceToPrimary(Particle.particle(),aDaughter);
487  // Find the closest daughter, if closer than a given upper limit.
488  if ( distance < distMin && distance < theDistCut ) {
489  distMin = distance;
491  }
492 
493  // eAfter += aDaughter.E();
494 
495  }
496 
497  /*
498  double eBefore = Particle.E();
499  double rapid = Particle.momentum().Eta();
500  if ( eBefore > 0. ) {
501  hAfter->Fill(eAfter/eBefore);
502  hAfter2->Fill(rapid,eAfter/eBefore);
503  hAfter3->Fill(eBefore,eAfter/eBefore);
504  }
505  */
506 
507  // ERROR The way this loops through the events breaks
508  // replay. Which events are retrieved depends on
509  // which previous events were processed.
510 
511  // Increment for next time
512  ++aCurrentInteraction[ene];
513 
514  // Simulate a stopping hadron (low momentum)
515  } else if ( pHadron < 4. &&
516  elastic > 1.- (inelastic4*theInelasticLength)
517  /theTotalInteractionLength ) {
518  // A fake particle with 0 momentum as a daughter!
519  _theUpdatedState.reserve(1);
520  _theUpdatedState.clear();
521  _theUpdatedState.emplace_back(makeParticle(Particle.particleDataTable(),
522  22, XYZTLorentzVector(0.,0.,0.,0.)));
523  }
524 
525  }
526 
527  }
528 
529  }
530 
531 }
532 
533 double
535  const RawParticle& aDaughter) const {
536 
537  double distance = 2E99;
538 
539  // Compute the distance only for charged primaries
540  if ( fabs(Particle.charge()) > 1E-12 ) {
541 
542  // The secondary must have the same charge
543  double chargeDiff = fabs(aDaughter.charge()-Particle.charge());
544  if ( fabs(chargeDiff) < 1E-12 ) {
545 
546  // Here are two distance definitions * to be tuned *
547  switch ( theDistAlgo ) {
548 
549  case 1:
550  // sin(theta12)
551  distance = (aDaughter.Vect().Unit().Cross(Particle.Vect().Unit())).R();
552  break;
553 
554  case 2:
555  // sin(theta12) * p1/p2
556  distance = (aDaughter.Vect().Cross(Particle.Vect())).R()
557  /aDaughter.Vect().Mag2();
558  break;
559 
560  default:
561  // Should not happen
562  distance = 2E99;
563  break;
564 
565  }
566 
567  }
568 
569  }
570 
571  return distance;
572 
573 }
574 
575 void
577 
578  // Size of buffer
579  ++myOutputBuffer;
580 
581  // Periodically close the current file and open a new one
582  if ( myOutputBuffer/1000*1000 == myOutputBuffer ) {
583  myOutputFile.close();
584  myOutputFile.open ("NuclearInteractionOutputFile.txt");
585  // myOutputFile.seekp(0); // No need to rewind in that case
586  }
587  //
588  unsigned size1 =
589  theCurrentEntry.size()*
590  theCurrentEntry.begin()->size();
591  std::vector<unsigned> theCurrentEntries;
592  theCurrentEntries.resize(size1);
593  size1*=sizeof(unsigned);
594  //
595  unsigned size2 =
596  theCurrentInteraction.size()*
597  theCurrentInteraction.begin()->size();
598  std::vector<unsigned> theCurrentInteractions;
599  theCurrentInteractions.resize(size2);
600  size2 *= sizeof(unsigned);
601 
602  // Save the current entries
603  std::vector< std::vector<unsigned> >::const_iterator aCurrentEntry = theCurrentEntry.begin();
604  std::vector< std::vector<unsigned> >::const_iterator lastCurrentEntry = theCurrentEntry.end();
605  unsigned allEntries=0;
606  for ( ; aCurrentEntry!=lastCurrentEntry; ++aCurrentEntry ) {
607  unsigned size = aCurrentEntry->size();
608  for ( unsigned iene=0; iene<size; ++iene )
609  theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
610  }
611 
612  // Save the current interactions
613  std::vector< std::vector<unsigned> >::const_iterator aCurrentInteraction = theCurrentInteraction.begin();
614  std::vector< std::vector<unsigned> >::const_iterator lastCurrentInteraction = theCurrentInteraction.end();
615  unsigned allInteractions=0;
616  for ( ; aCurrentInteraction!=lastCurrentInteraction; ++aCurrentInteraction ) {
617  unsigned size = aCurrentInteraction->size();
618  for ( unsigned iene=0; iene<size; ++iene )
619  theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
620  }
621  //
622  myOutputFile.write((const char*)(&theCurrentEntries.front()), size1);
623  myOutputFile.write((const char*)(&theCurrentInteractions.front()), size2);
624  myOutputFile.flush();
625 
626 }
627 
628 bool
630 
631  std::ifstream myInputFile;
632  struct stat results;
633  //
634  unsigned size1 =
635  theCurrentEntry.size()*
636  theCurrentEntry.begin()->size();
637  std::vector<unsigned> theCurrentEntries;
638  theCurrentEntries.resize(size1);
639  size1*=sizeof(unsigned);
640  //
641  unsigned size2 =
642  theCurrentInteraction.size()*
643  theCurrentInteraction.begin()->size();
644  std::vector<unsigned> theCurrentInteractions;
645  theCurrentInteractions.resize(size2);
646  size2 *= sizeof(unsigned);
647  //
648  unsigned size = 0;
649 
650 
651  // Open the file (if any)
652  myInputFile.open (inputFile.c_str());
653  if ( myInputFile.is_open() ) {
654 
655  // Get the size of the file
656  if ( stat(inputFile.c_str(), &results) == 0 ) size = results.st_size;
657  else return false; // Something is wrong with that file !
658 
659  // Position the pointer just before the last record
660  myInputFile.seekg(size-size1-size2);
661  myInputFile.read((char*)(&theCurrentEntries.front()),size1);
662  myInputFile.read((char*)(&theCurrentInteractions.front()),size2);
663  myInputFile.close();
664 
665  // Read the current entries
666  std::vector< std::vector<unsigned> >::iterator aCurrentEntry = theCurrentEntry.begin();
667  std::vector< std::vector<unsigned> >::iterator lastCurrentEntry = theCurrentEntry.end();
668  unsigned allEntries=0;
669  for ( ; aCurrentEntry!=lastCurrentEntry; ++aCurrentEntry ) {
670  unsigned size = aCurrentEntry->size();
671  for ( unsigned iene=0; iene<size; ++iene )
672  (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
673  }
674 
675  // Read the current interactions
676  std::vector< std::vector<unsigned> >::iterator aCurrentInteraction = theCurrentInteraction.begin();
677  std::vector< std::vector<unsigned> >::iterator lastCurrentInteraction = theCurrentInteraction.end();
678  unsigned allInteractions=0;
679  for ( ; aCurrentInteraction!=lastCurrentInteraction; ++aCurrentInteraction ) {
680  unsigned size = aCurrentInteraction->size();
681  for ( unsigned iene=0; iene<size; ++iene )
682  (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
683  }
684 
685  return true;
686  }
687 
688  return false;
689 
690 }
691 
692 unsigned
694 
695  unsigned myIndex=0;
696  while ( thePid != thePionID[myIndex] ) ++myIndex;
697  // std::cout << "pid/index = " << thePid << " " << myIndex << std::endl;
698  return myIndex;
699 
700 }
size
Write out results.
void boost(double bx, double by, double bz)
Definition: RawParticle.cc:111
const HepPDT::ParticleDataTable * particleDataTable() const
XYZVector Vect() const
the momentum threevector
Definition: RawParticle.h:342
double flatShoot(double xmin=0.0, double xmax=1.0) const
static const double slope[3]
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
void compute(ParticlePropagator &Particle, RandomEngineAndDistribution const *) override
Generate a nuclear interaction according to the probability that it happens.
Geom::Theta< T > theta() const
XYZVector orthogonal(const XYZVector &) const
A vector orthogonal to another one (because it&#39;s not in XYZTLorentzVector)
std::vector< std::vector< unsigned > > theNumberOfInteractions
std::vector< std::vector< TTree * > > theTrees
int pid() const
get the HEP particle ID number
Definition: RawParticle.h:296
TRandom random
Definition: MVATrainer.cc:138
RawParticle const & particle() const
The particle being propagated.
double mass() const
get the MEASURED mass
Definition: RawParticle.h:314
ROOT::Math::Boost Boost
Definition: RawParticle.h:52
std::vector< std::vector< unsigned > > theCurrentEntry
RawParticle makeParticle(HepPDT::ParticleDataTable const *, int id, const math::XYZTLorentzVector &p)
Definition: makeParticle.cc:29
std::vector< std::vector< std::string > > theFileNames
Definition: NUEvent.h:6
std::vector< std::vector< unsigned > > theNumberOfEntries
T sqrt(T t)
Definition: SSEVec.h:18
std::vector< std::vector< double > > thePionCM
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void rotate(double rphi, const XYZVector &raxis)
Definition: RawParticle.cc:83
bool read(std::string inputFile)
Read former nuclear interaction (from previous run)
double charge() const
get the MEASURED charge
Definition: RawParticle.h:313
unsigned index(int thePid)
Return a hashed index for a given pid.
std::vector< std::string > thePionNA
~NuclearInteractionSimulator() override
Default Destructor.
double M2() const
mass squared
Definition: RawParticle.h:337
std::vector< std::vector< TBranch * > > theBranches
std::vector< std::vector< unsigned > > theCurrentInteraction
std::vector< std::vector< double > > theRatios
NuclearInteractionSimulator(std::vector< double > &hadronEnergies, std::vector< int > &hadronTypes, std::vector< std::string > &hadronNames, std::vector< double > &hadronMasses, std::vector< double > &hadronPMin, double pionEnergy, std::vector< double > &lengthRatio, std::vector< std::vector< double > > &ratios, std::map< int, int > &idMap, std::string inputFile, unsigned int distAlgo, double distCut)
Constructor.
std::vector< RawParticle > _theUpdatedState
ROOT::Math::AxisAngle Rotation
Definition: RawParticle.h:47
std::string fullPath() const
Definition: FileInPath.cc:163
void save() override
Save current nuclear interaction (for later use)
std::vector< std::vector< NUEvent * > > theNUEvents
math::XYZVector XYZVector
Definition: RawParticle.h:28
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
double distanceToPrimary(const RawParticle &Particle, const RawParticle &aDaughter) const
Compute distance between secondary and primary.
math::XYZTLorentzVector XYZTLorentzVector
Definition: RawParticle.h:27