CMS 3D CMS Logo

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