CMS 3D CMS Logo

List of all members | Public Member Functions | Private Member Functions | Private Attributes
NuclearInteractionSimulator Class Reference

#include <NuclearInteractionSimulator.h>

Inheritance diagram for NuclearInteractionSimulator:
MaterialEffectsSimulator

Public Member Functions

 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. More...
 
bool read (std::string inputFile)
 Read former nuclear interaction (from previous run) More...
 
void save () override
 Save current nuclear interaction (for later use) More...
 
 ~NuclearInteractionSimulator () override
 Default Destructor. More...
 
- Public Member Functions inherited from MaterialEffectsSimulator
RHEP_const_iter beginDaughters () const
 Returns const iterator to the beginning of the daughters list. More...
 
int closestDaughterId ()
 The id of the closest charged daughter (filled for nuclear interactions only) More...
 
double eMass () const
 Electron mass in GeV/c2. More...
 
RHEP_const_iter endDaughters () const
 Returns const iterator to the end of the daughters list. More...
 
double excitE () const
 Mean excitation energy (in GeV) More...
 
 MaterialEffectsSimulator (double A=28.0855, double Z=14.0000, double density=2.329, double radLen=9.360)
 
unsigned nDaughters () const
 Returns the number of daughters. More...
 
XYZVector orthogonal (const XYZVector &) const
 A vector orthogonal to another one (because it's not in XYZTLorentzVector) More...
 
double radLenIncm () const
 One radiation length in cm. More...
 
double rho () const
 Density in g/cm3. More...
 
void setNormalVector (const GlobalVector &normal)
 Sets the vector normal to the surface traversed. More...
 
double theA () const
 A. More...
 
double theZ () const
 Z. More...
 
void updateState (ParticlePropagator &myTrack, double radlen, RandomEngineAndDistribution const *)
 Compute the material effect (calls the sub class) More...
 
virtual ~MaterialEffectsSimulator ()
 

Private Member Functions

void compute (ParticlePropagator &Particle, RandomEngineAndDistribution const *) override
 Generate a nuclear interaction according to the probability that it happens. More...
 
double distanceToPrimary (const RawParticle &Particle, const RawParticle &aDaughter) const
 Compute distance between secondary and primary. More...
 
unsigned index (int thePid)
 Return a hashed index for a given pid. More...
 

Private Attributes

bool currentValuesWereSet
 
unsigned ien4
 
unsigned myOutputBuffer
 
std::ofstream myOutputFile
 
std::vector< std::vector< TBranch * > > theBranches
 
std::vector< std::vector< unsigned > > theCurrentEntry
 
std::vector< std::vector< unsigned > > theCurrentInteraction
 
unsigned theDistAlgo
 
double theDistCut
 
TFile * theFile
 
std::vector< std::vector< std::string > > theFileNames
 
std::map< int, int > theIDMap
 
std::vector< double > theLengthRatio
 
std::vector< std::vector< NUEvent * > > theNUEvents
 
std::vector< std::vector< unsigned > > theNumberOfEntries
 
std::vector< std::vector< unsigned > > theNumberOfInteractions
 
std::vector< std::vector< double > > thePionCM
 
std::vector< double > thePionEN
 
double thePionEnergy
 
std::vector< int > thePionID
 
std::vector< double > thePionMA
 
std::vector< std::string > thePionNA
 
std::vector< double > thePionPMin
 
std::vector< std::vector< double > > theRatios
 
std::vector< std::vector< TTree * > > theTrees
 

Additional Inherited Members

- Public Types inherited from MaterialEffectsSimulator
typedef std::vector< RawParticle >::const_iterator RHEP_const_iter
 
- Protected Attributes inherited from MaterialEffectsSimulator
std::vector< RawParticle_theUpdatedState
 
double A
 
double density
 
double radLen
 
double radLengths
 
int theClosestChargedDaughterId
 
GlobalVector theNormalVector
 
double Z
 

Detailed Description

Definition at line 33 of file NuclearInteractionSimulator.h.

Constructor & Destructor Documentation

◆ NuclearInteractionSimulator()

NuclearInteractionSimulator::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.

Definition at line 25 of file NuclearInteractionSimulator.cc.

References gather_cfg::cout, currentValuesWereSet, Exception, corrVsCorr::filename, contentValuesFiles::fullPath, edm::FileInPath::fullPath(), ien4, makeListRunsInFiles::inputFile, myOutputBuffer, myOutputFile, read(), mathSSE::sqrt(), AlCaHLTBitMon_QueryRunRegistry::string, theBranches, theCurrentEntry, theCurrentInteraction, theFile, theFileNames, theNUEvents, theNumberOfEntries, theNumberOfInteractions, thePionCM, thePionEN, thePionMA, thePionNA, theTrees, and cond::impl::to_string().

46  theIDMap(idMap),
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)
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 }
std::string to_string(const V &value)
Definition: OMSAccess.h:71
std::vector< std::vector< NUEvent * > > theNUEvents
std::vector< std::vector< std::string > > theFileNames
Definition: NUEvent.h:6
T sqrt(T t)
Definition: SSEVec.h:19
MaterialEffectsSimulator(double A=28.0855, double Z=14.0000, double density=2.329, double radLen=9.360)
std::vector< std::vector< unsigned > > theNumberOfEntries
bool read(std::string inputFile)
Read former nuclear interaction (from previous run)
std::vector< std::vector< unsigned > > theCurrentInteraction
std::vector< std::string > thePionNA
std::vector< std::vector< double > > thePionCM
std::vector< std::vector< TBranch * > > theBranches
std::vector< std::vector< unsigned > > theNumberOfInteractions
std::vector< std::vector< unsigned > > theCurrentEntry
std::vector< std::vector< double > > theRatios
lengthRatio
Default is 0.020 for algo 1;.
math::XYZTLorentzVector XYZTLorentzVector
Definition: RawParticle.h:25
std::vector< std::vector< TTree * > > theTrees

◆ ~NuclearInteractionSimulator()

NuclearInteractionSimulator::~NuclearInteractionSimulator ( )
override

Default Destructor.

Definition at line 170 of file NuclearInteractionSimulator.cc.

References myOutputFile, theFile, and theNUEvents.

170  {
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 }
std::vector< std::vector< NUEvent * > > theNUEvents

Member Function Documentation

◆ compute()

void NuclearInteractionSimulator::compute ( ParticlePropagator Particle,
RandomEngineAndDistribution const *  random 
)
overrideprivatevirtual

Generate a nuclear interaction according to the probability that it happens.

Implements MaterialEffectsSimulator.

Definition at line 189 of file NuclearInteractionSimulator.cc.

References MaterialEffectsSimulator::_theUpdatedState, funct::abs(), RawParticle::boost(), currentValuesWereSet, HLT_2022v15_cff::distance, distanceToPrimary(), muonTagProbeFilters_cff::distMin, HCALHighEnergyHPDFilter_cfi::energy, JetChargeProducer_cfi::exp, NUEvent::NUInteraction::first, RandomEngineAndDistribution::flatShoot(), NUEvent::NUParticle::id, ien4, index(), NUEvent::NUInteraction::last, dqm-mbProfile::log, makeParticle(), NUEvent::NUParticle::mass, MaterialEffectsSimulator::orthogonal(), phi, ALCARECOTkAlMinBias_cff::pMin, funct::pow(), NUEvent::NUParticle::px, NUEvent::NUParticle::py, NUEvent::NUParticle::pz, MaterialEffectsSimulator::radLengths, RawParticle::rotate(), funct::sin(), slope, mathSSE::sqrt(), MaterialEffectsSimulator::theA(), MaterialEffectsSimulator::theClosestChargedDaughterId, theCurrentEntry, theCurrentInteraction, theDistCut, theIDMap, theLengthRatio, theNUEvents, theNumberOfEntries, theNumberOfInteractions, thePionCM, thePionEN, thePionEnergy, thePionNA, thePionPMin, theRatios, theta(), theTrees, and HLT_2022v15_cff::zAxis.

189  {
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 }
void boost(double bx, double by, double bz)
Definition: RawParticle.cc:65
static const double slope[3]
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
std::vector< std::vector< NUEvent * > > theNUEvents
ROOT::Math::Boost Boost
Definition: RawParticle.h:49
RawParticle makeParticle(HepPDT::ParticleDataTable const *, int id, const math::XYZTLorentzVector &p)
Definition: makeParticle.cc:28
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
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
double distanceToPrimary(const RawParticle &Particle, const RawParticle &aDaughter) const
Compute distance between secondary and primary.
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
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

◆ distanceToPrimary()

double NuclearInteractionSimulator::distanceToPrimary ( const RawParticle Particle,
const RawParticle aDaughter 
) const
private

Compute distance between secondary and primary.

Definition at line 497 of file NuclearInteractionSimulator.cc.

References RawParticle::charge(), HLT_2022v15_cff::distance, theDistAlgo, and RawParticle::Vect().

Referenced by compute().

497  {
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 }
double charge() const
get the MEASURED charge
Definition: RawParticle.h:294
XYZVector Vect() const
the momentum threevector
Definition: RawParticle.h:323

◆ index()

unsigned NuclearInteractionSimulator::index ( int  thePid)
private

Return a hashed index for a given pid.

Definition at line 631 of file NuclearInteractionSimulator.cc.

References thePionID.

Referenced by compute(), and BeautifulSoup.PageElement::insert().

631  {
632  unsigned myIndex = 0;
633  while (thePid != thePionID[myIndex])
634  ++myIndex;
635  // std::cout << "pid/index = " << thePid << " " << myIndex << std::endl;
636  return myIndex;
637 }

◆ read()

bool NuclearInteractionSimulator::read ( std::string  inputFile)

Read former nuclear interaction (from previous run)

Definition at line 574 of file NuclearInteractionSimulator.cc.

References makeListRunsInFiles::inputFile, mysort::results, findQualityFiles::size, edm_modernize_messagelogger::stat, theCurrentEntry, and theCurrentInteraction.

Referenced by edmIntegrityCheck.PublishToFileSystem::get(), and NuclearInteractionSimulator().

574  {
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 }
size
Write out results.
std::vector< std::vector< unsigned > > theCurrentInteraction
std::vector< std::vector< unsigned > > theCurrentEntry
results
Definition: mysort.py:8

◆ save()

void NuclearInteractionSimulator::save ( )
overridevirtual

Save current nuclear interaction (for later use)

Reimplemented from MaterialEffectsSimulator.

Definition at line 528 of file NuclearInteractionSimulator.cc.

References myOutputBuffer, myOutputFile, findQualityFiles::size, theCurrentEntry, and theCurrentInteraction.

528  {
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 }
size
Write out results.
std::vector< std::vector< unsigned > > theCurrentInteraction
std::vector< std::vector< unsigned > > theCurrentEntry

Member Data Documentation

◆ currentValuesWereSet

bool NuclearInteractionSimulator::currentValuesWereSet
private

Definition at line 96 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().

◆ ien4

unsigned NuclearInteractionSimulator::ien4
private

Definition at line 89 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().

◆ myOutputBuffer

unsigned NuclearInteractionSimulator::myOutputBuffer
private

Definition at line 94 of file NuclearInteractionSimulator.h.

Referenced by NuclearInteractionSimulator(), and save().

◆ myOutputFile

std::ofstream NuclearInteractionSimulator::myOutputFile
private

◆ theBranches

std::vector<std::vector<TBranch*> > NuclearInteractionSimulator::theBranches
private

Definition at line 79 of file NuclearInteractionSimulator.h.

Referenced by NuclearInteractionSimulator().

◆ theCurrentEntry

std::vector<std::vector<unsigned> > NuclearInteractionSimulator::theCurrentEntry
private

Definition at line 81 of file NuclearInteractionSimulator.h.

Referenced by compute(), NuclearInteractionSimulator(), read(), and save().

◆ theCurrentInteraction

std::vector<std::vector<unsigned> > NuclearInteractionSimulator::theCurrentInteraction
private

Definition at line 82 of file NuclearInteractionSimulator.h.

Referenced by compute(), NuclearInteractionSimulator(), read(), and save().

◆ theDistAlgo

unsigned NuclearInteractionSimulator::theDistAlgo
private

Definition at line 90 of file NuclearInteractionSimulator.h.

Referenced by distanceToPrimary().

◆ theDistCut

double NuclearInteractionSimulator::theDistCut
private

Definition at line 91 of file NuclearInteractionSimulator.h.

Referenced by compute().

◆ theFile

TFile* NuclearInteractionSimulator::theFile
private

◆ theFileNames

std::vector<std::vector<std::string> > NuclearInteractionSimulator::theFileNames
private

Definition at line 85 of file NuclearInteractionSimulator.h.

Referenced by NuclearInteractionSimulator().

◆ theIDMap

std::map<int, int> NuclearInteractionSimulator::theIDMap
private

Definition at line 88 of file NuclearInteractionSimulator.h.

Referenced by compute().

◆ theLengthRatio

std::vector<double> NuclearInteractionSimulator::theLengthRatio
private

Definition at line 74 of file NuclearInteractionSimulator.h.

Referenced by compute().

◆ theNUEvents

std::vector<std::vector<NUEvent*> > NuclearInteractionSimulator::theNUEvents
private

◆ theNumberOfEntries

std::vector<std::vector<unsigned> > NuclearInteractionSimulator::theNumberOfEntries
private

Definition at line 83 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().

◆ theNumberOfInteractions

std::vector<std::vector<unsigned> > NuclearInteractionSimulator::theNumberOfInteractions
private

Definition at line 84 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().

◆ thePionCM

std::vector<std::vector<double> > NuclearInteractionSimulator::thePionCM
private

Definition at line 86 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().

◆ thePionEN

std::vector<double> NuclearInteractionSimulator::thePionEN
private

Definition at line 68 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().

◆ thePionEnergy

double NuclearInteractionSimulator::thePionEnergy
private

Definition at line 73 of file NuclearInteractionSimulator.h.

Referenced by compute().

◆ thePionID

std::vector<int> NuclearInteractionSimulator::thePionID
private

Definition at line 69 of file NuclearInteractionSimulator.h.

Referenced by index().

◆ thePionMA

std::vector<double> NuclearInteractionSimulator::thePionMA
private

Definition at line 71 of file NuclearInteractionSimulator.h.

Referenced by NuclearInteractionSimulator().

◆ thePionNA

std::vector<std::string> NuclearInteractionSimulator::thePionNA
private

Definition at line 70 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().

◆ thePionPMin

std::vector<double> NuclearInteractionSimulator::thePionPMin
private

Definition at line 72 of file NuclearInteractionSimulator.h.

Referenced by compute().

◆ theRatios

std::vector<std::vector<double> > NuclearInteractionSimulator::theRatios
private

Definition at line 75 of file NuclearInteractionSimulator.h.

Referenced by compute().

◆ theTrees

std::vector<std::vector<TTree*> > NuclearInteractionSimulator::theTrees
private

Definition at line 78 of file NuclearInteractionSimulator.h.

Referenced by compute(), and NuclearInteractionSimulator().