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, to_string(), and ticlDumper_cff::treeName.

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  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  std::string treeName = "NuclearInteractions_" + thePionNA[iname] + "_E" + std::to_string(int(theEne));
114  //
115  theTrees[iname][iene] = (TTree*)theFile->Get(treeName.c_str());
116  if (!theTrees[iname][iene])
117  throw cms::Exception("FastSimulation/MaterialEffects") << "Tree with name " << treeName << " not found ";
118  //
119  theBranches[iname][iene] = theTrees[iname][iene]->GetBranch("nuEvent");
120  //std::cout << "The branch = " << theBranches[iname][iene] << std::endl;
121  if (!theBranches[iname][iene])
122  throw cms::Exception("FastSimulation/MaterialEffects")
123  << "Branch with name nuEvent not found in " << theFileNames[iname][iene];
124  //
125  theNUEvents[iname][iene] = new NUEvent();
126  //std::cout << "The branch = " << theBranches[iname][iene] << std::endl;
127  theBranches[iname][iene]->SetAddress(&theNUEvents[iname][iene]);
128  //
129  theNumberOfEntries[iname][iene] = theTrees[iname][iene]->GetEntries();
130 
131  if (currentValuesWereSet) {
132  theTrees[iname][iene]->GetEntry(theCurrentEntry[iname][iene]);
133  unsigned NInteractions = theNUEvents[iname][iene]->nInteractions();
134  theNumberOfInteractions[iname][iene] = NInteractions;
135  }
136 
137  //
138  // Compute the corresponding cm energies of the nuclear interactions
139  XYZTLorentzVector Proton(0., 0., 0., 0.986);
140  XYZTLorentzVector Reference(
141  0., 0., std::sqrt(thePionEN[iene] * thePionEN[iene] - thePionMA[iname] * thePionMA[iname]), thePionEN[iene]);
142  thePionCM[iname][iene] = (Reference + Proton).M();
143  }
144  }
145 
146  // Find the index for which EN = 4. (or thereabout)
147  ien4 = 0;
148  while (thePionEN[ien4] < 4.0)
149  ++ien4;
150 
151  gROOT->cd();
152 
153  // dbe = edm::Service<DaqMonitorBEInterface>().operator->();
154  // htot = dbe->book1D("Total", "All particles",150,0.,150.);
155  // helas = dbe->book1D("Elastic", "Elastic interactions",150,0.,150.);
156  // hinel = dbe->book1D("Inelastic", "Inelastic interactions",150,0.,150.);
157  // hscatter = dbe->book1D("Scattering","Elastic Scattering angle",200,0.,2.);
158  // hscatter2 = dbe->book2D("Scattering2","Elastic Scattering angle vs p",100,0.,10.,200,0.,2.);
159  // hAfter = dbe->book1D("eAfter","Energy after collision",200,0.,4.);
160  // hAfter2 = dbe->book2D("eAfter2","Energy after collision",100,-2.5,2.5,100,0.,4);
161  // hAfter3 = dbe->book2D("eAfter3","Energy after collision",100,0.,1000.,100,0.,4);
162 }
std::vector< std::vector< NUEvent * > > theNUEvents
std::vector< std::vector< std::string > > theFileNames
static std::string to_string(const XMLCh *ch)
Definition: NUEvent.h:6
T sqrt(T t)
Definition: SSEVec.h:23
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 164 of file NuclearInteractionSimulator.cc.

References myOutputFile, theFile, and theNUEvents.

164  {
165  // Close all local files
166  // Among other things, this allows the TROOT destructor to end up
167  // without crashing, while trying to close these files from outside
168  theFile->Close();
169  delete theFile;
170 
171  for (auto& vEvents : theNUEvents) {
172  for (auto evtPtr : vEvents) {
173  delete evtPtr;
174  }
175  }
176 
177  // Close the output file
178  myOutputFile.close();
179 
180  // dbe->save("test.root");
181 }
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 183 of file NuclearInteractionSimulator.cc.

References MaterialEffectsSimulator::_theUpdatedState, funct::abs(), RawParticle::boost(), currentValuesWereSet, HLT_2024v14_cff::distance, distanceToPrimary(), muonTagProbeFilters_cff::distMin, hcalRecHitTable_cff::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_2024v14_cff::zAxis.

183  {
184  if (!currentValuesWereSet) {
185  currentValuesWereSet = true;
186  for (unsigned iname = 0; iname < thePionNA.size(); ++iname) {
187  for (unsigned iene = 0; iene < thePionEN.size(); ++iene) {
188  theCurrentEntry[iname][iene] = (unsigned)(theNumberOfEntries[iname][iene] * random->flatShoot());
189 
190  theTrees[iname][iene]->GetEntry(theCurrentEntry[iname][iene]);
191  unsigned NInteractions = theNUEvents[iname][iene]->nInteractions();
192  theNumberOfInteractions[iname][iene] = NInteractions;
193 
194  theCurrentInteraction[iname][iene] = (unsigned)(theNumberOfInteractions[iname][iene] * random->flatShoot());
195  }
196  }
197  }
198 
199  // Read a Nuclear Interaction in a random manner
200 
201  double pHadron = std::sqrt(Particle.particle().Vect().Mag2());
202  // htot->Fill(pHadron);
203 
204  // The hadron has enough momentum to create some relevant final state
205  if (pHadron > thePionEnergy) {
206  // The particle type
207  std::map<int, int>::const_iterator thePit = theIDMap.find(Particle.particle().pid());
208 
209  int thePid = thePit != theIDMap.end() ? thePit->second : Particle.particle().pid();
210 
211  // Is this particle type foreseen?
212  unsigned fPid = abs(thePid);
213  if (fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212) {
214  return;
215  //std::cout << "Unknown particle type = " << thePid << std::endl;
216  //thePid = 211;
217  }
218 
219  // The inelastic interaction length at p(pion) = 5 GeV/c
220  unsigned thePidIndex = index(thePid);
221  double theInelasticLength = radLengths * theLengthRatio[thePidIndex];
222 
223  // The elastic interaction length
224  // The baroque parameterization is a fit to Fig. 40.13 of the PDG
225  double ee = pHadron > 0.6 ? exp(-std::sqrt((pHadron - 0.6) / 1.122)) : exp(std::sqrt((0.6 - pHadron) / 1.122));
226  double theElasticLength = (0.8753 * ee + 0.15)
227  // double theElasticLength = ( 0.15 + 0.195 / log(pHadron/0.4) )
228  // double theElasticLength = ( 0.15 + 0.305 / log(pHadron/0.35) )
229  * theInelasticLength;
230 
231  // The total interaction length
232  double theTotalInteractionLength = theInelasticLength + theElasticLength;
233 
234  // Probability to interact is dl/L0 (maximum for 4 GeV pion)
235  double aNuclInteraction = -std::log(random->flatShoot());
236  if (aNuclInteraction < theTotalInteractionLength) {
237  // The elastic part
238  double elastic = random->flatShoot();
239  if (elastic < theElasticLength / theTotalInteractionLength) {
240  // helas->Fill(pHadron);
241 
242  // Characteristic scattering angle for the elastic part
243  double theta0 = std::sqrt(3.) / std::pow(theA(), 1. / 3.) * Particle.particle().mass() / pHadron;
244 
245  // Draw an angle with theta/theta0*exp[(-theta/2theta0)**2] shape
246  double theta = theta0 * std::sqrt(-2. * std::log(random->flatShoot()));
247  double phi = 2. * 3.14159265358979323 * random->flatShoot();
248 
249  // Rotate the particle accordingly
250  RawParticle::Rotation rotation1(orthogonal(Particle.particle().Vect()), theta);
251  RawParticle::Rotation rotation2(Particle.particle().Vect(), phi);
252  Particle.particle().rotate(rotation1);
253  Particle.particle().rotate(rotation2);
254 
255  // Distance
256  double distance = std::sin(theta);
257 
258  // Create a daughter if the kink is large engough
259  if (distance > theDistCut) {
260  _theUpdatedState.reserve(1);
261  _theUpdatedState.clear();
262  _theUpdatedState.emplace_back(Particle.particle());
263  }
264 
265  // hscatter->Fill(myTheta);
266  // hscatter2->Fill(pHadron,myTheta);
267 
268  }
269 
270  // The inelastic part
271  else {
272  // Avoid multiple map access
273  const std::vector<double>& aPionCM = thePionCM[thePidIndex];
274  const std::vector<double>& aRatios = theRatios[thePidIndex];
275  // Find the file with the closest c.m energy
276  // The target nucleon
277  XYZTLorentzVector Proton(0., 0., 0., 0.939);
278  // The current particle
279  const XYZTLorentzVector& Hadron = (const XYZTLorentzVector&)Particle;
280  // The smallest momentum for inelastic interactions
281  double pMin = thePionPMin[thePidIndex];
282  // The correspong smallest four vector
283  XYZTLorentzVector Hadron0(0., 0., pMin, std::sqrt(pMin * pMin + Particle.particle().M2()));
284 
285  // The current centre-of-mass energy
286  double ecm = (Proton + Hadron).M();
287  //std::cout << "Proton = " << Proton << std::endl;
288  //std::cout << "Hadron = " << Hadron << std::endl;
289  //std::cout << "ecm = " << ecm << std::endl;
290  // Get the files of interest (closest c.m. energies)
291  unsigned ene1 = 0;
292  unsigned ene2 = 0;
293  // The smallest centre-of-mass energy
294  // double ecm1=1.63;
295  double ecm1 = (Proton + Hadron0).M();
296  //std::cout << "ecm1 = " << ecm1 << std::endl;
297  //std::cout << "ecm[0] = " << aPionCM[0] << std::endl;
298  //std::cout << "ecm[11] = " << aPionCM [ aPionCM.size()-1 ] << std::endl;
299  double ecm2 = aPionCM[0];
300  double ratio1 = 0.;
301  double ratio2 = aRatios[0];
302  if (ecm > aPionCM[0] && ecm < aPionCM[aPionCM.size() - 1]) {
303  for (unsigned ene = 1; ene < aPionCM.size() && ecm > aPionCM[ene - 1]; ++ene) {
304  if (ecm < aPionCM[ene]) {
305  ene2 = ene;
306  ene1 = ene2 - 1;
307  ecm1 = aPionCM[ene1];
308  ecm2 = aPionCM[ene2];
309  ratio1 = aRatios[ene1];
310  ratio2 = aRatios[ene2];
311  }
312  }
313  } else if (ecm > aPionCM[aPionCM.size() - 1]) {
314  ene1 = aPionCM.size() - 1;
315  ene2 = aPionCM.size() - 2;
316  ecm1 = aPionCM[ene1];
317  ecm2 = aPionCM[ene2];
318  ratio1 = aRatios[ene2];
319  ratio2 = aRatios[ene2];
320  }
321 
322  // The inelastic part of the cross section depends cm energy
323  double slope = (std::log10(ecm) - std::log10(ecm1)) / (std::log10(ecm2) - std::log10(ecm1));
324  double inelastic = ratio1 + (ratio2 - ratio1) * slope;
325  double inelastic4 = pHadron < 4. ? aRatios[ien4] : 1.;
326 
327  //std::cout << "Inelastic = " << ratio1 << " " << ratio2 << " " << inelastic << std::endl;
328  // std::cout << "Energy/Inelastic : "
329  // << Hadron.e() << " " << inelastic << std::endl;
330 
331  // Simulate an inelastic interaction
332  if (elastic > 1. - (inelastic * theInelasticLength) / theTotalInteractionLength) {
333  // Avoid mutliple map access
334  std::vector<unsigned>& aCurrentInteraction = theCurrentInteraction[thePidIndex];
335  std::vector<unsigned>& aNumberOfInteractions = theNumberOfInteractions[thePidIndex];
336  std::vector<NUEvent*>& aNUEvents = theNUEvents[thePidIndex];
337  // hinel->Fill(pHadron);
338  // std::cout << "INELASTIC INTERACTION ! "
339  // << pHadron << " " << theInelasticLength << " "
340  // << inelastic * theInelasticLength << std::endl;
341  // Choice of the file to read according the the log10(ecm) distance
342  // and protection against low momentum proton and neutron that never interacts
343  // (i.e., empty files)
344  unsigned ene;
345  if (random->flatShoot() < slope || aNumberOfInteractions[ene1] == 0)
346  ene = ene2;
347  else
348  ene = ene1;
349 
350  //std::cout << "Ecm1/2 = " << ecm1 << " " << ecm2 << std::endl;
351  //std::cout << "Ratio1/2 = " << ratio1 << " " << ratio2 << std::endl;
352  //std::cout << "Ene = " << ene << " slope = " << slope << std::endl;
353 
354  //std::cout << "Pion energy = " << Hadron.E()
355  // << "File chosen " << theFileNames[thePidIndex][ene]
356  // << std::endl;
357 
358  // The boost characteristics
359  XYZTLorentzVector theBoost = Proton + Hadron;
360  theBoost /= theBoost.e();
361 
362  // std::cout << "File chosen : " << thePid << "/" << ene
363  // << " Current interaction = " << aCurrentInteraction[ene]
364  // << " Total interactions = " << aNumberOfInteractions[ene]
365  // << std::endl;
366  // theFiles[thePidIndex][ene]->cd();
367  // gDirectory->ls();
368 
369  // Check we are not either at the end of an interaction bunch
370  // or at the end of a file
371  if (aCurrentInteraction[ene] == aNumberOfInteractions[ene]) {
372  // std::cout << "End of interaction bunch ! ";
373  std::vector<unsigned>& aCurrentEntry = theCurrentEntry[thePidIndex];
374  std::vector<unsigned>& aNumberOfEntries = theNumberOfEntries[thePidIndex];
375  std::vector<TTree*>& aTrees = theTrees[thePidIndex];
376  ++aCurrentEntry[ene];
377  // std::cerr << "Read the next entry "
378  // << aCurrentEntry[ene] << std::endl;
379  aCurrentInteraction[ene] = 0;
380  if (aCurrentEntry[ene] == aNumberOfEntries[ene]) {
381  aCurrentEntry[ene] = 0;
382  // std::cout << "End of file - Rewind! " << std::endl;
383  }
384  unsigned myEntry = aCurrentEntry[ene];
385  // std::cout << "The new entry " << myEntry
386  // << " is read ... in TTree " << aTrees[ene] << " ";
387  aTrees[ene]->GetEntry(myEntry);
388  // std::cout << "The number of interactions in the new entry is ... ";
389  aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
390  // std::cout << aNumberOfInteractions[ene] << std::endl;
391  }
392 
393  // Read the interaction
394  NUEvent::NUInteraction anInteraction = aNUEvents[ene]->theNUInteractions()[aCurrentInteraction[ene]];
395 
396  unsigned firstTrack = anInteraction.first;
397  unsigned lastTrack = anInteraction.last;
398  // std::cout << "First and last tracks are " << firstTrack << " " << lastTrack << std::endl;
399 
400  _theUpdatedState.reserve(lastTrack - firstTrack + 1);
401  _theUpdatedState.clear();
402 
403  double distMin = 1E99;
404 
405  // Some rotation around the boost axis, for more randomness
406  XYZVector theAxis = theBoost.Vect().Unit();
407  double theAngle = random->flatShoot() * 2. * 3.14159265358979323;
408  RawParticle::Rotation axisRotation(theAxis, theAngle);
409  RawParticle::Boost axisBoost(theBoost.x(), theBoost.y(), theBoost.z());
410 
411  // A rotation to bring the particles back to the pion direction
412  XYZVector zAxis(0., 0., 1.);
413  XYZVector orthAxis = (zAxis.Cross(theBoost.Vect())).Unit();
414  double orthAngle = acos(theBoost.Vect().Unit().Z());
415  RawParticle::Rotation orthRotation(orthAxis, orthAngle);
416 
417  // A few checks
418  // double eAfter = 0.;
419 
420  // Loop on the nuclear interaction products
421  for (unsigned iTrack = firstTrack; iTrack <= lastTrack; ++iTrack) {
422  unsigned idaugh = iTrack - firstTrack;
423  NUEvent::NUParticle aParticle = aNUEvents[ene]->theNUParticles()[iTrack];
424  // std::cout << "Track " << iTrack
425  // << " id/px/py/pz/mass "
426  // << aParticle.id << " "
427  // << aParticle.px << " "
428  // << aParticle.py << " "
429  // << aParticle.pz << " "
430  // << aParticle.mass << " " << endl;
431 
432  // Add a RawParticle with the proper energy in the c.m frame of
433  // the nuclear interaction
434  double energy = std::sqrt(aParticle.px * aParticle.px + aParticle.py * aParticle.py +
435  aParticle.pz * aParticle.pz + aParticle.mass * aParticle.mass / (ecm * ecm));
436 
437  RawParticle& aDaughter = _theUpdatedState.emplace_back(makeParticle(
438  Particle.particleDataTable(),
439  aParticle.id,
440  XYZTLorentzVector(aParticle.px * ecm, aParticle.py * ecm, aParticle.pz * ecm, energy * ecm)));
441  // Rotate to the collision axis
442  aDaughter.rotate(orthRotation);
443 
444  // Rotate around the boost axis for more randomness
445  aDaughter.rotate(axisRotation);
446 
447  // Boost it in the lab frame
448  aDaughter.boost(axisBoost);
449 
450  // Store the closest daughter index (for later tracking purposes, so charged particles only)
451  double distance = distanceToPrimary(Particle.particle(), aDaughter);
452  // Find the closest daughter, if closer than a given upper limit.
453  if (distance < distMin && distance < theDistCut) {
454  distMin = distance;
456  }
457 
458  // eAfter += aDaughter.E();
459  }
460 
461  /*
462  double eBefore = Particle.E();
463  double rapid = Particle.momentum().Eta();
464  if ( eBefore > 0. ) {
465  hAfter->Fill(eAfter/eBefore);
466  hAfter2->Fill(rapid,eAfter/eBefore);
467  hAfter3->Fill(eBefore,eAfter/eBefore);
468  }
469  */
470 
471  // ERROR The way this loops through the events breaks
472  // replay. Which events are retrieved depends on
473  // which previous events were processed.
474 
475  // Increment for next time
476  ++aCurrentInteraction[ene];
477 
478  // Simulate a stopping hadron (low momentum)
479  } else if (pHadron < 4. && elastic > 1. - (inelastic4 * theInelasticLength) / theTotalInteractionLength) {
480  // A fake particle with 0 momentum as a daughter!
481  _theUpdatedState.reserve(1);
482  _theUpdatedState.clear();
483  _theUpdatedState.emplace_back(
484  makeParticle(Particle.particleDataTable(), 22, XYZTLorentzVector(0., 0., 0., 0.)));
485  }
486  }
487  }
488  }
489 }
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:23
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 491 of file NuclearInteractionSimulator.cc.

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

Referenced by compute().

491  {
492  double distance = 2E99;
493 
494  // Compute the distance only for charged primaries
495  if (fabs(Particle.charge()) > 1E-12) {
496  // The secondary must have the same charge
497  double chargeDiff = fabs(aDaughter.charge() - Particle.charge());
498  if (fabs(chargeDiff) < 1E-12) {
499  // Here are two distance definitions * to be tuned *
500  switch (theDistAlgo) {
501  case 1:
502  // sin(theta12)
503  distance = (aDaughter.Vect().Unit().Cross(Particle.Vect().Unit())).R();
504  break;
505 
506  case 2:
507  // sin(theta12) * p1/p2
508  distance = (aDaughter.Vect().Cross(Particle.Vect())).R() / aDaughter.Vect().Mag2();
509  break;
510 
511  default:
512  // Should not happen
513  distance = 2E99;
514  break;
515  }
516  }
517  }
518 
519  return distance;
520 }
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 625 of file NuclearInteractionSimulator.cc.

References thePionID.

Referenced by compute().

625  {
626  unsigned myIndex = 0;
627  while (thePid != thePionID[myIndex])
628  ++myIndex;
629  // std::cout << "pid/index = " << thePid << " " << myIndex << std::endl;
630  return myIndex;
631 }

◆ read()

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

Read former nuclear interaction (from previous run)

Definition at line 568 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().

568  {
569  std::ifstream myInputFile;
570  struct stat results;
571  //
572  unsigned size1 = theCurrentEntry.size() * theCurrentEntry.begin()->size();
573  std::vector<unsigned> theCurrentEntries;
574  theCurrentEntries.resize(size1);
575  size1 *= sizeof(unsigned);
576  //
577  unsigned size2 = theCurrentInteraction.size() * theCurrentInteraction.begin()->size();
578  std::vector<unsigned> theCurrentInteractions;
579  theCurrentInteractions.resize(size2);
580  size2 *= sizeof(unsigned);
581  //
582  unsigned size = 0;
583 
584  // Open the file (if any)
585  myInputFile.open(inputFile.c_str());
586  if (myInputFile.is_open()) {
587  // Get the size of the file
588  if (stat(inputFile.c_str(), &results) == 0)
589  size = results.st_size;
590  else
591  return false; // Something is wrong with that file !
592 
593  // Position the pointer just before the last record
594  myInputFile.seekg(size - size1 - size2);
595  myInputFile.read((char*)(&theCurrentEntries.front()), size1);
596  myInputFile.read((char*)(&theCurrentInteractions.front()), size2);
597  myInputFile.close();
598 
599  // Read the current entries
600  std::vector<std::vector<unsigned> >::iterator aCurrentEntry = theCurrentEntry.begin();
601  std::vector<std::vector<unsigned> >::iterator lastCurrentEntry = theCurrentEntry.end();
602  unsigned allEntries = 0;
603  for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
604  unsigned size = aCurrentEntry->size();
605  for (unsigned iene = 0; iene < size; ++iene)
606  (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
607  }
608 
609  // Read the current interactions
610  std::vector<std::vector<unsigned> >::iterator aCurrentInteraction = theCurrentInteraction.begin();
611  std::vector<std::vector<unsigned> >::iterator lastCurrentInteraction = theCurrentInteraction.end();
612  unsigned allInteractions = 0;
613  for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
614  unsigned size = aCurrentInteraction->size();
615  for (unsigned iene = 0; iene < size; ++iene)
616  (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
617  }
618 
619  return true;
620  }
621 
622  return false;
623 }
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 522 of file NuclearInteractionSimulator.cc.

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

522  {
523  // Size of buffer
524  ++myOutputBuffer;
525 
526  // Periodically close the current file and open a new one
527  if (myOutputBuffer / 1000 * 1000 == myOutputBuffer) {
528  myOutputFile.close();
529  myOutputFile.open("NuclearInteractionOutputFile.txt");
530  // myOutputFile.seekp(0); // No need to rewind in that case
531  }
532  //
533  unsigned size1 = theCurrentEntry.size() * theCurrentEntry.begin()->size();
534  std::vector<unsigned> theCurrentEntries;
535  theCurrentEntries.resize(size1);
536  size1 *= sizeof(unsigned);
537  //
538  unsigned size2 = theCurrentInteraction.size() * theCurrentInteraction.begin()->size();
539  std::vector<unsigned> theCurrentInteractions;
540  theCurrentInteractions.resize(size2);
541  size2 *= sizeof(unsigned);
542 
543  // Save the current entries
544  std::vector<std::vector<unsigned> >::const_iterator aCurrentEntry = theCurrentEntry.begin();
545  std::vector<std::vector<unsigned> >::const_iterator lastCurrentEntry = theCurrentEntry.end();
546  unsigned allEntries = 0;
547  for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
548  unsigned size = aCurrentEntry->size();
549  for (unsigned iene = 0; iene < size; ++iene)
550  theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
551  }
552 
553  // Save the current interactions
554  std::vector<std::vector<unsigned> >::const_iterator aCurrentInteraction = theCurrentInteraction.begin();
555  std::vector<std::vector<unsigned> >::const_iterator lastCurrentInteraction = theCurrentInteraction.end();
556  unsigned allInteractions = 0;
557  for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
558  unsigned size = aCurrentInteraction->size();
559  for (unsigned iene = 0; iene < size; ++iene)
560  theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
561  }
562  //
563  myOutputFile.write((const char*)(&theCurrentEntries.front()), size1);
564  myOutputFile.write((const char*)(&theCurrentInteractions.front()), size2);
565  myOutputFile.flush();
566 }
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().