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