CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
List of all members | Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes
fastsim::NuclearInteraction Class Reference

Implementation of nuclear interactions of hadrons in the tracker layers (based on fully simulated interactions). More...

Inheritance diagram for fastsim::NuclearInteraction:
fastsim::InteractionModel

Public Member Functions

void interact (fastsim::Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< fastsim::Particle > > &secondaries, const RandomEngineAndDistribution &random) override
 Perform the interaction. More...
 
 NuclearInteraction (const std::string &name, const edm::ParameterSet &cfg)
 Constructor. More...
 
 ~NuclearInteraction () override
 Default destructor. More...
 
- Public Member Functions inherited from fastsim::InteractionModel
const std::string getName ()
 Return (unique) name of this interaction. More...
 
 InteractionModel (std::string name)
 Constructor. More...
 
virtual void registerProducts (edm::ProducesCollector) const
 In case interaction produces and stores content in the event (e.g. TrackerSimHits). More...
 
virtual void storeProducts (edm::Event &iEvent)
 In case interaction produces and stores content in the event (e.g. TrackerSimHits). More...
 
virtual ~InteractionModel ()
 Default destructor. More...
 

Private Member Functions

unsigned index (int thePid)
 Return a hashed index for a given particle ID. More...
 
XYZVector orthogonal (const XYZVector &aVector) const
 Return an orthogonal vector. More...
 
bool read (std::string inputFile)
 Read the nuclear interactions from a file, so you can reproduce the events (e.g. in case of a crash). More...
 
void save ()
 Save the nuclear interactions to a file, so you can reproduce the events (e.g. in case of a crash). More...
 

Private Attributes

const std::vector< int > antineutronsID = {-2112, -3122, -3112, -3312, -3322}
 PdgID of anti-neutrons. More...
 
const std::vector< int > antiprotonsID = {-2212, -3222}
 PdgID of anti-protons. More...
 
bool currentValuesWereSet
 Read data from file that was created in a previous run. More...
 
unsigned ien4
 Find the index for which EN = 4. More...
 
std::string inputFile
 Directory/Name of input file in case you want to read interactions from file. More...
 
const std::vector< int > K0LsID = {130, 310}
 PdgID of K0. More...
 
const std::vector< int > KminussesID = {-321}
 PdgID of K-. More...
 
const std::vector< int > KplussesID = {321}
 PdgID of K+. More...
 
unsigned myOutputBuffer
 Needed to save interactions to file. More...
 
std::ofstream myOutputFile
 Output file to save interactions. More...
 
const std::vector< int > neutronsID = {2112, 3122, 3112, 3312, 3322, 3334, -3334}
 PdgID of neutrons. More...
 
const std::vector< int > PiminussesID = {-211}
 PdgID of pi-. More...
 
const std::vector< int > PiplussesID = {211}
 PdgID of pt+. More...
 
const std::vector< int > protonsID = {2212, 3222, -101, -102, -103, -104}
 PdgID of protons. More...
 
std::vector< std::vector
< TBranch * > > 
theBranches
 Necessary to read the FullSim interactions. More...
 
std::vector< std::vector
< unsigned > > 
theCurrentEntry
 Necessary to read the FullSim interactions. More...
 
std::vector< std::vector
< unsigned > > 
theCurrentInteraction
 Necessary to read the FullSim interactions. More...
 
double theDistCut
 Cut on deltaR for the FastSim Tracking (ClosestChargedDaughter algorithm) More...
 
TFile * theFile = nullptr
 Necessary to read the FullSim interactions. More...
 
std::vector< std::vector
< std::string > > 
theFileNames
 Necessary to read the FullSim interactions. More...
 
std::vector< std::vector
< double > > 
theHadronCM
 Necessary to read the FullSim interactions. More...
 
const std::vector< double > theHadronEN
 Filled into 'theRatiosMap' (evolution of the interaction lengths with energy) More...
 
double theHadronEnergy
 Minimum energy for nuclear interaction. More...
 
const std::vector< int > theHadronID = {211, -211, 130, 321, -321, 2212, -2212, 2112, -2112}
 ID of the hadrons. More...
 
const std::vector< double > theHadronMA
 Masses of the hadrons. More...
 
const std::vector< std::string > theHadronNA
 Names of the hadrons. More...
 
const std::vector< double > theHadronPMin = {0.7, 0.0, 1.0, 1.0, 0.0, 1.1, 0.0, 1.1, 0.0}
 Smallest momentum for inelastic interactions. More...
 
const std::vector< double > theLengthRatio
 Inelastic interaction length at p(Hadron) = 5 GeV/c (relativ to radionLength of material) More...
 
std::vector< std::vector
< NUEvent * > > 
theNUEvents
 Necessary to read the FullSim interactions. More...
 
std::vector< std::vector
< unsigned > > 
theNumberOfEntries
 Necessary to read the FullSim interactions. More...
 
std::vector< std::vector
< unsigned > > 
theNumberOfInteractions
 Necessary to read the FullSim interactions. More...
 
const std::vector< double > theRatios
 Filled into 'theRatiosMap' (evolution of the interaction lengths with energy) More...
 
std::vector< std::vector
< TTree * > > 
theTrees
 Necessary to read the FullSim interactions. More...
 

Static Private Attributes

static std::map< int, int > theIDMap
 Build the ID map (i.e., what is to be considered as a proton, etc...) More...
 
static std::vector
< std::vector< double > > 
theRatiosMap
 The evolution of the interaction lengths with energy. More...
 

Detailed Description

Implementation of nuclear interactions of hadrons in the tracker layers (based on fully simulated interactions).

Computes the probability for hadrons to interact with a nucleon of the tracker material (inelastically) and then reads a nuclear interaction randomly from multiple fully simulated files. Also, another implementation of nuclear interactions can be used that is based on G4 (NuclearInteractionFTF).

Definition at line 58 of file NuclearInteraction.cc.

Constructor & Destructor Documentation

fastsim::NuclearInteraction::NuclearInteraction ( const std::string &  name,
const edm::ParameterSet cfg 
)

Constructor.

Definition at line 348 of file NuclearInteraction.cc.

References looper::cfg, gather_cfg::cout, Exception, lut2db_cfg::filename, contentValuesFiles::fullPath, edm::FileInPath::fullPath(), mps_fire::i, gpuClustering::id, fastsim::initializeOnce, writeEcalDQMStatus::inputFile, dqmiolumiharvest::j, SiPixelLorentzAngle_cfi::read, mathSSE::sqrt(), AlCaHLTBitMon_QueryRunRegistry::string, interactiveExample::theFile, and cond::impl::to_string().

350  // Full path to FullSim root file
352 
353  // Read from config file
354  theDistCut = cfg.getParameter<double>("distCut");
355  theHadronEnergy = cfg.getParameter<double>("hadronEnergy");
356  inputFile = cfg.getUntrackedParameter<std::string>("inputFile", "");
357 
358  // The evolution of the interaction lengths with energy
359  // initialize once for all possible instances
360  std::call_once(initializeOnce, [this]() {
361  theRatiosMap.resize(theHadronID.size());
362  for (unsigned i = 0; i < theHadronID.size(); ++i) {
363  for (unsigned j = 0; j < theHadronEN.size(); ++j) {
364  theRatiosMap[i].push_back(theRatios[i * theHadronEN.size() + j]);
365  }
366  }
367 
368  // Build the ID map (i.e., what is to be considered as a proton, etc...)
369  // Protons
370  for (const auto& id : protonsID)
371  theIDMap[id] = 2212;
372  // Anti-Protons
373  for (const auto& id : antiprotonsID)
374  theIDMap[id] = -2212;
375  // Neutrons
376  for (const auto& id : neutronsID)
377  theIDMap[id] = 2112;
378  // Anti-Neutrons
379  for (const auto& id : antineutronsID)
380  theIDMap[id] = -2112;
381  // K0L's
382  for (const auto& id : K0LsID)
383  theIDMap[id] = 130;
384  // K+'s
385  for (const auto& id : KplussesID)
386  theIDMap[id] = 321;
387  // K-'s
388  for (const auto& id : KminussesID)
389  theIDMap[id] = -321;
390  // pi+'s
391  for (const auto& id : PiplussesID)
392  theIDMap[id] = 211;
393  // pi-'s
394  for (const auto& id : PiminussesID)
395  theIDMap[id] = -211;
396  });
397 
398  // Prepare the map of files
399  // Loop over the particle names
400  TFile* aVFile = nullptr;
401  std::vector<TTree*> aVTree(theHadronEN.size());
402  std::vector<TBranch*> aVBranch(theHadronEN.size());
403  std::vector<NUEvent*> aVNUEvents(theHadronEN.size());
404  std::vector<unsigned> aVCurrentEntry(theHadronEN.size());
405  std::vector<unsigned> aVCurrentInteraction(theHadronEN.size());
406  std::vector<unsigned> aVNumberOfEntries(theHadronEN.size());
407  std::vector<unsigned> aVNumberOfInteractions(theHadronEN.size());
408  std::vector<std::string> aVFileName(theHadronEN.size());
409  std::vector<double> aVHadronCM(theHadronEN.size());
410  theTrees.resize(theHadronNA.size());
411  theBranches.resize(theHadronNA.size());
412  theNUEvents.resize(theHadronNA.size());
413  theCurrentEntry.resize(theHadronNA.size());
414  theCurrentInteraction.resize(theHadronNA.size());
415  theNumberOfEntries.resize(theHadronNA.size());
416  theNumberOfInteractions.resize(theHadronNA.size());
417  theFileNames.resize(theHadronNA.size());
418  theHadronCM.resize(theHadronNA.size());
419  theFile = aVFile;
420  for (unsigned iname = 0; iname < theHadronNA.size(); ++iname) {
421  theTrees[iname] = aVTree;
422  theBranches[iname] = aVBranch;
423  theNUEvents[iname] = aVNUEvents;
424  theCurrentEntry[iname] = aVCurrentEntry;
425  theCurrentInteraction[iname] = aVCurrentInteraction;
426  theNumberOfEntries[iname] = aVNumberOfEntries;
427  theNumberOfInteractions[iname] = aVNumberOfInteractions;
428  theFileNames[iname] = aVFileName;
429  theHadronCM[iname] = aVHadronCM;
430  }
431 
432  // Read the information from a previous run (to keep reproducibility)
433  currentValuesWereSet = this->read(inputFile);
435  std::cout << "***WARNING*** You are reading nuclear-interaction information from the file " << inputFile
436  << " created in an earlier run." << std::endl;
437 
438  // Open the file for saving the information of the current run
439  myOutputFile.open("NuclearInteractionOutputFile.txt");
440  myOutputBuffer = 0;
441 
442  // Open the root file
443  edm::FileInPath myDataFile("FastSimulation/MaterialEffects/data/NuclearInteractions.root");
444  fullPath = myDataFile.fullPath();
445  theFile = TFile::Open(fullPath.c_str());
446 
447  // Open the trees
448  unsigned fileNb = 0;
449  for (unsigned iname = 0; iname < theHadronNA.size(); ++iname) {
450  for (unsigned iene = 0; iene < theHadronEN.size(); ++iene) {
451  std::ostringstream filename;
452  double theEne = theHadronEN[iene];
453  filename << "NuclearInteractionsVal_" << theHadronNA[iname] << "_E" << theEne << ".root";
454  theFileNames[iname][iene] = filename.str();
455 
456  ++fileNb;
457  std::string treeName = "NuclearInteractions_" + theHadronNA[iname] + "_E" + std::to_string(int(theEne));
458  theTrees[iname][iene] = (TTree*)theFile->Get(treeName.c_str());
459 
460  if (!theTrees[iname][iene])
461  throw cms::Exception("FastSimulation/MaterialEffects") << "Tree with name " << treeName << " not found ";
462  theBranches[iname][iene] = theTrees[iname][iene]->GetBranch("nuEvent");
463  if (!theBranches[iname][iene])
464  throw cms::Exception("FastSimulation/MaterialEffects")
465  << "Branch with name nuEvent not found in " << theFileNames[iname][iene];
466 
467  theNUEvents[iname][iene] = new NUEvent();
468  theBranches[iname][iene]->SetAddress(&theNUEvents[iname][iene]);
469  theNumberOfEntries[iname][iene] = theTrees[iname][iene]->GetEntries();
470 
471  if (currentValuesWereSet) {
472  theTrees[iname][iene]->GetEntry(theCurrentEntry[iname][iene]);
473  unsigned NInteractions = theNUEvents[iname][iene]->nInteractions();
474  theNumberOfInteractions[iname][iene] = NInteractions;
475  }
476 
477  // Compute the corresponding cm energies of the nuclear interactions
478  XYZTLorentzVector Proton(0., 0., 0., 0.986);
479  XYZTLorentzVector Reference(
480  0.,
481  0.,
482  std::sqrt(theHadronEN[iene] * theHadronEN[iene] - theHadronMA[iname] * theHadronMA[iname]),
483  theHadronEN[iene]);
484  theHadronCM[iname][iene] = (Reference + Proton).M();
485  }
486  }
487 
488  // Find the index for which EN = 4. (or thereabout)
489  ien4 = 0;
490  while (theHadronEN[ien4] < 4.0)
491  ++ien4;
492 
493  gROOT->cd();
494 }
const std::vector< int > antineutronsID
PdgID of anti-neutrons.
const std::vector< int > PiplussesID
PdgID of pt+.
T getUntrackedParameter(std::string const &, T const &) const
std::vector< std::vector< unsigned > > theCurrentInteraction
Necessary to read the FullSim interactions.
double theDistCut
Cut on deltaR for the FastSim Tracking (ClosestChargedDaughter algorithm)
uint16_t *__restrict__ id
const std::vector< int > KminussesID
PdgID of K-.
std::vector< std::vector< unsigned > > theNumberOfEntries
Necessary to read the FullSim interactions.
bool currentValuesWereSet
Read data from file that was created in a previous run.
std::string to_string(const V &value)
Definition: OMSAccess.h:71
const std::vector< int > KplussesID
PdgID of K+.
std::vector< std::vector< std::string > > theFileNames
Necessary to read the FullSim interactions.
TFile * theFile
Necessary to read the FullSim interactions.
static std::vector< std::vector< double > > theRatiosMap
The evolution of the interaction lengths with energy.
std::vector< std::vector< double > > theHadronCM
Necessary to read the FullSim interactions.
std::vector< std::vector< NUEvent * > > theNUEvents
Necessary to read the FullSim interactions.
const std::vector< int > protonsID
PdgID of protons.
Base class for any interaction model between a particle and a tracker layer.
const std::vector< double > theRatios
Filled into &#39;theRatiosMap&#39; (evolution of the interaction lengths with energy)
const std::vector< int > K0LsID
PdgID of K0.
Definition: NUEvent.h:6
const std::vector< int > antiprotonsID
PdgID of anti-protons.
static std::map< int, int > theIDMap
Build the ID map (i.e., what is to be considered as a proton, etc...)
T sqrt(T t)
Definition: SSEVec.h:19
std::ofstream myOutputFile
Output file to save interactions.
const std::vector< int > neutronsID
PdgID of neutrons.
double theHadronEnergy
Minimum energy for nuclear interaction.
bool read(std::string inputFile)
Read the nuclear interactions from a file, so you can reproduce the events (e.g. in case of a crash)...
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
unsigned ien4
Find the index for which EN = 4.
const std::vector< double > theHadronMA
Masses of the hadrons.
std::vector< std::vector< TBranch * > > theBranches
Necessary to read the FullSim interactions.
const std::vector< int > PiminussesID
PdgID of pi-.
const std::vector< double > theHadronEN
Filled into &#39;theRatiosMap&#39; (evolution of the interaction lengths with energy)
std::vector< std::vector< unsigned > > theNumberOfInteractions
Necessary to read the FullSim interactions.
tuple filename
Definition: lut2db_cfg.py:20
static std::once_flag initializeOnce
const std::vector< int > theHadronID
ID of the hadrons.
tuple cout
Definition: gather_cfg.py:144
std::string inputFile
Directory/Name of input file in case you want to read interactions from file.
std::vector< std::vector< TTree * > > theTrees
Necessary to read the FullSim interactions.
const std::vector< std::string > theHadronNA
Names of the hadrons.
math::XYZTLorentzVector XYZTLorentzVector
Definition: RawParticle.h:25
std::vector< std::vector< unsigned > > theCurrentEntry
Necessary to read the FullSim interactions.
unsigned myOutputBuffer
Needed to save interactions to file.
fastsim::NuclearInteraction::~NuclearInteraction ( )
override

Default destructor.

Definition at line 496 of file NuclearInteraction.cc.

References cuy::save, and interactiveExample::theFile.

496  {
497  // Close all local files
498  // Among other things, this allows the TROOT destructor to end up
499  // without crashing, while trying to close these files from outside
500  theFile->Close();
501  delete theFile;
502 
503  for (auto& vEvents : theNUEvents) {
504  for (auto evtPtr : vEvents) {
505  delete evtPtr;
506  }
507  }
508 
509  // Save data
510  save();
511  // Close the output file
512  myOutputFile.close();
513 }
TFile * theFile
Necessary to read the FullSim interactions.
std::vector< std::vector< NUEvent * > > theNUEvents
Necessary to read the FullSim interactions.
std::ofstream myOutputFile
Output file to save interactions.
void save()
Save the nuclear interactions to a file, so you can reproduce the events (e.g. in case of a crash)...

Member Function Documentation

unsigned fastsim::NuclearInteraction::index ( int  thePid)
private

Return a hashed index for a given particle ID.

Definition at line 899 of file NuclearInteraction.cc.

Referenced by BeautifulSoup.PageElement::_invert().

899  {
900  // Find hashed particle ID
901  unsigned myIndex = 0;
902  while (thePid != theHadronID[myIndex])
903  ++myIndex;
904  return myIndex;
905 }
const std::vector< int > theHadronID
ID of the hadrons.
void fastsim::NuclearInteraction::interact ( fastsim::Particle particle,
const SimplifiedGeometry layer,
std::vector< std::unique_ptr< fastsim::Particle > > &  secondaries,
const RandomEngineAndDistribution random 
)
overridevirtual

Perform the interaction.

Parameters
particleThe particle that interacts with the matter.
layerThe detector layer that interacts with the particle.
secondariesParticles that are produced in the interaction (if any).
randomThe Random Engine.

Implements fastsim::InteractionModel.

Definition at line 515 of file NuclearInteraction.cc.

References A, funct::abs(), fastsim::Particle::charge(), relval_parameters_module::energy, funct::exp(), NUEvent::NUInteraction::first, RandomEngineAndDistribution::flatShoot(), fastsim::SimplifiedGeometry::getNuclearInteractionThicknessFactor(), fastsim::SimplifiedGeometry::getThickness(), NUEvent::NUParticle::id, NUEvent::NUInteraction::last, log, M_PI, NUEvent::NUParticle::mass, fastsim::Particle::momentum(), fastsim::Particle::pdgId(), HLT_FULL_cff::pMin, fastsim::Particle::position(), funct::pow(), NUEvent::NUParticle::px, NUEvent::NUParticle::py, NUEvent::NUParticle::pz, fastsim::Particle::simTrackIndex(), funct::sin(), slope, mathSSE::sqrt(), theta(), and MetAnalyzer::zAxis.

518  {
519  int pdgId = particle.pdgId();
520  //
521  // no valid PDGid
522  //
523  if (abs(pdgId) <= 100 || abs(pdgId) >= 1000000) {
524  return;
525  }
526 
527  double radLengths = layer.getThickness(particle.position(), particle.momentum());
528  // TEC layers have some fudge factor for nuclear interactions
529  radLengths *= layer.getNuclearInteractionThicknessFactor();
530  //
531  // no material
532  //
533  if (radLengths < 1E-10) {
534  return;
535  }
536 
537  // In case the events are not read from (old) saved file, then pick a random event from FullSim file
538  if (!currentValuesWereSet) {
539  currentValuesWereSet = true;
540  for (unsigned iname = 0; iname < theHadronNA.size(); ++iname) {
541  for (unsigned iene = 0; iene < theHadronEN.size(); ++iene) {
542  theCurrentEntry[iname][iene] = (unsigned)(theNumberOfEntries[iname][iene] * random.flatShoot());
543 
544  theTrees[iname][iene]->GetEntry(theCurrentEntry[iname][iene]);
545  unsigned NInteractions = theNUEvents[iname][iene]->nInteractions();
546  theNumberOfInteractions[iname][iene] = NInteractions;
547 
548  theCurrentInteraction[iname][iene] = (unsigned)(theNumberOfInteractions[iname][iene] * random.flatShoot());
549  }
550  }
551  }
552 
553  // Momentum of interacting hadron
554  double pHadron = std::sqrt(particle.momentum().Vect().Mag2());
555 
556  //
557  // The hadron has not enough momentum to create some relevant final state
558  //
559  if (pHadron < theHadronEnergy) {
560  return;
561  }
562 
563  // The particle type
564  std::map<int, int>::const_iterator thePit = theIDMap.find(pdgId);
565  // Use map for unique ID (e.g. proton = {2212, 3222, -101, -102, -103, -104})
566  int thePid = (thePit != theIDMap.end() ? thePit->second : pdgId);
567 
568  // Is this particle type foreseen?
569  unsigned fPid = abs(thePid);
570  if (fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212) {
571  return;
572  }
573 
574  // The hashed ID
575  unsigned thePidIndex = index(thePid);
576  // The inelastic interaction length at p(Hadron) = 5 GeV/c
577  double theInelasticLength = radLengths * theLengthRatio[thePidIndex];
578 
579  // The elastic interaction length
580  // The baroque parameterization is a fit to Fig. 40.13 of the PDG
581  double ee = pHadron > 0.6 ? exp(-std::sqrt((pHadron - 0.6) / 1.122)) : exp(std::sqrt((0.6 - pHadron) / 1.122));
582  double theElasticLength = (0.8753 * ee + 0.15) * theInelasticLength;
583 
584  // The total interaction length
585  double theTotalInteractionLength = theInelasticLength + theElasticLength;
586 
587  //
588  // Probability to interact is dl/L0 (maximum for 4 GeV Hadron)
589  //
590  double aNuclInteraction = -std::log(random.flatShoot());
591  if (aNuclInteraction > theTotalInteractionLength) {
592  return;
593  }
594 
595  // The elastic part
596  double elastic = random.flatShoot();
597  if (elastic < theElasticLength / theTotalInteractionLength) {
598  // Characteristic scattering angle for the elastic part
599  // A of silicon
600  double A = 28.0855;
601  double theta0 = std::sqrt(3.) / std::pow(A, 1. / 3.) * particle.momentum().mass() / pHadron;
602 
603  // Draw an angle with theta/theta0*exp[(-theta/2theta0)**2] shape
604  double theta = theta0 * std::sqrt(-2. * std::log(random.flatShoot()));
605  double phi = 2. * M_PI * random.flatShoot();
606 
607  // Rotate the particle accordingly
608  ROOT::Math::AxisAngle rotation1(orthogonal(particle.momentum().Vect()), theta);
609  ROOT::Math::AxisAngle rotation2(particle.momentum().Vect(), phi);
610  // Rotate!
611  XYZVector rotated = rotation2((rotation1(particle.momentum().Vect())));
612 
613  // Create a daughter if the kink is large enough
614  if (std::sin(theta) > theDistCut) {
615  secondaries.emplace_back(
616  new fastsim::Particle(pdgId,
617  particle.position(),
618  XYZTLorentzVector(rotated.X(), rotated.Y(), rotated.Z(), particle.momentum().E())));
619 
620  // Set the ClosestCharged Daughter thing for tracking
621  if (particle.charge() != 0) {
622  secondaries.back()->setMotherDeltaR(particle.momentum());
623  secondaries.back()->setMotherPdgId(pdgId);
624  secondaries.back()->setMotherSimTrackIndex(particle.simTrackIndex());
625  }
626 
627  // The particle is destroyed
628  particle.momentum().SetXYZT(0., 0., 0., 0.);
629  } else {
630  // If kink is small enough just rotate particle
631  particle.momentum().SetXYZT(rotated.X(), rotated.Y(), rotated.Z(), particle.momentum().E());
632  }
633  // The inelastic part
634  } else {
635  // Avoid multiple map access
636  const std::vector<double>& aHadronCM = theHadronCM[thePidIndex];
637  const std::vector<double>& aRatios = theRatiosMap[thePidIndex];
638  // Find the file with the closest c.m energy
639  // The target nucleon
640  XYZTLorentzVector Proton(0., 0., 0., 0.939);
641  // The current particle
642  const XYZTLorentzVector& Hadron = (const XYZTLorentzVector&)particle.momentum();
643  // The smallest momentum for inelastic interactions
644  double pMin = theHadronPMin[thePidIndex];
645  // The corresponding smallest four vector
646  XYZTLorentzVector Hadron0(0., 0., pMin, std::sqrt(pMin * pMin + particle.momentum().M2()));
647 
648  // The current centre-of-mass energy
649  double ecm = (Proton + Hadron).M();
650 
651  // Get the files of interest (closest c.m. energies)
652  unsigned ene1 = 0;
653  unsigned ene2 = 0;
654  // The smallest centre-of-mass energy
655  double ecm1 = (Proton + Hadron0).M();
656 
657  double ecm2 = aHadronCM[0];
658  double ratio1 = 0.;
659  double ratio2 = aRatios[0];
660  if (ecm > aHadronCM[0] && ecm < aHadronCM[aHadronCM.size() - 1]) {
661  for (unsigned ene = 1; ene < aHadronCM.size() && ecm > aHadronCM[ene - 1]; ++ene) {
662  if (ecm < aHadronCM[ene]) {
663  ene2 = ene;
664  ene1 = ene2 - 1;
665  ecm1 = aHadronCM[ene1];
666  ecm2 = aHadronCM[ene2];
667  ratio1 = aRatios[ene1];
668  ratio2 = aRatios[ene2];
669  }
670  }
671  } else if (ecm > aHadronCM[aHadronCM.size() - 1]) {
672  ene1 = aHadronCM.size() - 1;
673  ene2 = aHadronCM.size() - 2;
674  ecm1 = aHadronCM[ene1];
675  ecm2 = aHadronCM[ene2];
676  ratio1 = aRatios[ene2];
677  ratio2 = aRatios[ene2];
678  }
679 
680  // The inelastic part of the cross section depends cm energy
681  double slope = (std::log10(ecm) - std::log10(ecm1)) / (std::log10(ecm2) - std::log10(ecm1));
682  double inelastic = ratio1 + (ratio2 - ratio1) * slope;
683  double inelastic4 = pHadron < 4. ? aRatios[ien4] : 1.;
684 
685  // Simulate an inelastic interaction
686  if (elastic > 1. - (inelastic * theInelasticLength) / theTotalInteractionLength) {
687  // Avoid mutliple map access
688  std::vector<unsigned>& aCurrentInteraction = theCurrentInteraction[thePidIndex];
689  std::vector<unsigned>& aNumberOfInteractions = theNumberOfInteractions[thePidIndex];
690  std::vector<NUEvent*>& aNUEvents = theNUEvents[thePidIndex];
691 
692  // Choice of the file to read according the the log10(ecm) distance
693  // and protection against low momentum proton and neutron that never interacts
694  // (i.e., empty files)
695  unsigned ene;
696  if (random.flatShoot() < slope || aNumberOfInteractions[ene1] == 0) {
697  ene = ene2;
698  } else {
699  ene = ene1;
700  }
701 
702  // The boost characteristics
703  XYZTLorentzVector theBoost = Proton + Hadron;
704  theBoost /= theBoost.e();
705 
706  // Check we are not either at the end of an interaction bunch
707  // or at the end of a file
708  if (aCurrentInteraction[ene] == aNumberOfInteractions[ene]) {
709  std::vector<unsigned>& aCurrentEntry = theCurrentEntry[thePidIndex];
710  std::vector<unsigned>& aNumberOfEntries = theNumberOfEntries[thePidIndex];
711  std::vector<TTree*>& aTrees = theTrees[thePidIndex];
712  ++aCurrentEntry[ene];
713 
714  aCurrentInteraction[ene] = 0;
715  if (aCurrentEntry[ene] == aNumberOfEntries[ene]) {
716  aCurrentEntry[ene] = 0;
717  }
718 
719  unsigned myEntry = aCurrentEntry[ene];
720  aTrees[ene]->GetEntry(myEntry);
721  aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
722  }
723 
724  // Read the interaction
725  NUEvent::NUInteraction anInteraction = aNUEvents[ene]->theNUInteractions()[aCurrentInteraction[ene]];
726 
727  unsigned firstTrack = anInteraction.first;
728  unsigned lastTrack = anInteraction.last;
729 
730  // Some rotation around the boost axis, for more randomness
731  XYZVector theAxis = theBoost.Vect().Unit();
732  double theAngle = random.flatShoot() * 2. * M_PI;
733  ROOT::Math::AxisAngle axisRotation(theAxis, theAngle);
734  ROOT::Math::Boost axisBoost(theBoost.x(), theBoost.y(), theBoost.z());
735 
736  // A rotation to bring the particles back to the Hadron direction
737  XYZVector zAxis(0., 0., 1.);
738  XYZVector orthAxis = (zAxis.Cross(theBoost.Vect())).Unit();
739  double orthAngle = acos(theBoost.Vect().Unit().Z());
740  ROOT::Math::AxisAngle orthRotation(orthAxis, orthAngle);
741 
742  // Loop on the nuclear interaction products
743  for (unsigned iTrack = firstTrack; iTrack <= lastTrack; ++iTrack) {
744  NUEvent::NUParticle aParticle = aNUEvents[ene]->theNUParticles()[iTrack];
745 
746  // Add a RawParticle with the proper energy in the c.m. frame of
747  // the nuclear interaction
748  double energy = std::sqrt(aParticle.px * aParticle.px + aParticle.py * aParticle.py +
749  aParticle.pz * aParticle.pz + aParticle.mass * aParticle.mass / (ecm * ecm));
750 
751  XYZTLorentzVector daugtherMomentum(aParticle.px * ecm, aParticle.py * ecm, aParticle.pz * ecm, energy * ecm);
752 
753  // Rotate to the collision axis
754  XYZVector rotated = orthRotation(daugtherMomentum.Vect());
755  // Rotate around the boost axis for more randomness
756  rotated = axisRotation(rotated);
757 
758  // Rotated the daughter
759  daugtherMomentum.SetXYZT(rotated.X(), rotated.Y(), rotated.Z(), daugtherMomentum.E());
760 
761  // Boost it in the lab frame
762  daugtherMomentum = axisBoost(daugtherMomentum);
763 
764  // Create secondary
765  secondaries.emplace_back(new fastsim::Particle(aParticle.id, particle.position(), daugtherMomentum));
766 
767  // The closestCharged Daughter thing for tracking
768  // BUT: 'aParticle' also has to be charged, only then the mother should be set
769  // Unfortunately, NUEvent::NUParticle does not contain any info about the charge
770  // Did some tests and effect is absolutely negligible!
771  if (particle.charge() != 0) {
772  secondaries.back()->setMotherDeltaR(particle.momentum());
773  secondaries.back()->setMotherPdgId(pdgId);
774  secondaries.back()->setMotherSimTrackIndex(particle.simTrackIndex());
775  }
776  }
777 
778  // The particle is destroyed
779  particle.momentum().SetXYZT(0., 0., 0., 0.);
780 
781  // This is a note from previous version of code but I don't understand it:
782  // ERROR The way this loops through the events breaks
783  // replay. Which events are retrieved depends on
784  // which previous events were processed.
785 
786  // Increment for next time
787  ++aCurrentInteraction[ene];
788 
789  // Simulate a stopping hadron (low momentum)
790  } else if (pHadron < 4. && elastic > 1. - (inelastic4 * theInelasticLength) / theTotalInteractionLength) {
791  // The particle is destroyed
792  particle.momentum().SetXYZT(0., 0., 0., 0.);
793  }
794  }
795 }
static std::vector< std::string > checklist log
std::vector< std::vector< unsigned > > theCurrentInteraction
Necessary to read the FullSim interactions.
const math::XYZTLorentzVector & position() const
Return position of the particle.
Definition: Particle.h:140
double theDistCut
Cut on deltaR for the FastSim Tracking (ClosestChargedDaughter algorithm)
double flatShoot(double xmin=0.0, double xmax=1.0) const
static const double slope[3]
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
std::vector< std::vector< unsigned > > theNumberOfEntries
Necessary to read the FullSim interactions.
Geom::Theta< T > theta() const
bool currentValuesWereSet
Read data from file that was created in a previous run.
Exp< T >::type exp(const T &t)
Definition: Exp.h:22
int pdgId() const
Return pdgId of the particle.
Definition: Particle.h:134
static std::vector< std::vector< double > > theRatiosMap
The evolution of the interaction lengths with energy.
std::vector< std::vector< double > > theHadronCM
Necessary to read the FullSim interactions.
std::vector< std::vector< NUEvent * > > theNUEvents
Necessary to read the FullSim interactions.
constexpr std::array< uint8_t, layerIndexSize > layer
const std::vector< double > theLengthRatio
Inelastic interaction length at p(Hadron) = 5 GeV/c (relativ to radionLength of material) ...
static std::map< int, int > theIDMap
Build the ID map (i.e., what is to be considered as a proton, etc...)
T sqrt(T t)
Definition: SSEVec.h:19
unsigned index(int thePid)
Return a hashed index for a given particle ID.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
XYZVector orthogonal(const XYZVector &aVector) const
Return an orthogonal vector.
int simTrackIndex() const
Return index of the SimTrack.
Definition: Particle.h:153
#define M_PI
double theHadronEnergy
Minimum energy for nuclear interaction.
const std::vector< double > theHadronPMin
Smallest momentum for inelastic interactions.
double charge() const
Return charge of the particle.
Definition: Particle.h:137
unsigned ien4
Find the index for which EN = 4.
const std::vector< double > theHadronEN
Filled into &#39;theRatiosMap&#39; (evolution of the interaction lengths with energy)
std::vector< std::vector< unsigned > > theNumberOfInteractions
Necessary to read the FullSim interactions.
tuple zAxis
Definition: MetAnalyzer.py:57
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:143
Definition: APVGainStruct.h:7
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:16
std::vector< std::vector< TTree * > > theTrees
Necessary to read the FullSim interactions.
math::XYZVector XYZVector
Definition: RawParticle.h:26
const std::vector< std::string > theHadronNA
Names of the hadrons.
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< unsigned > > theCurrentEntry
Necessary to read the FullSim interactions.
XYZVector fastsim::NuclearInteraction::orthogonal ( const XYZVector aVector) const
private

Return an orthogonal vector.

Definition at line 907 of file NuclearInteraction.cc.

References x, y, and z.

907  {
908  double x = fabs(aVector.X());
909  double y = fabs(aVector.Y());
910  double z = fabs(aVector.Z());
911 
912  if (x < y)
913  return x < z ? XYZVector(0., aVector.Z(), -aVector.Y()) : XYZVector(aVector.Y(), -aVector.X(), 0.);
914  else
915  return y < z ? XYZVector(-aVector.Z(), 0., aVector.X()) : XYZVector(aVector.Y(), -aVector.X(), 0.);
916 }
float float float z
uint16_t const *__restrict__ x
Definition: gpuClustering.h:43
math::XYZVector XYZVector
Definition: RawParticle.h:26
bool fastsim::NuclearInteraction::read ( std::string  inputFile)
private

Read the nuclear interactions from a file, so you can reproduce the events (e.g. in case of a crash).

Definition at line 842 of file NuclearInteraction.cc.

References bookConverter::results, findQualityFiles::size, and edm_modernize_messagelogger::stat.

Referenced by edmIntegrityCheck.PublishToFileSystem::get().

842  {
843  std::ifstream myInputFile;
844  struct stat results;
845  //
846  unsigned size1 = theCurrentEntry.size() * theCurrentEntry.begin()->size();
847  std::vector<unsigned> theCurrentEntries;
848  theCurrentEntries.resize(size1);
849  size1 *= sizeof(unsigned);
850  //
851  unsigned size2 = theCurrentInteraction.size() * theCurrentInteraction.begin()->size();
852  std::vector<unsigned> theCurrentInteractions;
853  theCurrentInteractions.resize(size2);
854  size2 *= sizeof(unsigned);
855  //
856  unsigned size = 0;
857 
858  // Open the file (if any), otherwise return false
859  myInputFile.open(inputFile.c_str());
860  if (myInputFile.is_open()) {
861  // Get the size of the file
862  if (stat(inputFile.c_str(), &results) == 0)
863  size = results.st_size;
864  else
865  return false; // Something is wrong with that file !
866 
867  // Position the pointer just before the last record
868  myInputFile.seekg(size - size1 - size2);
869  myInputFile.read((char*)(&theCurrentEntries.front()), size1);
870  myInputFile.read((char*)(&theCurrentInteractions.front()), size2);
871  myInputFile.close();
872 
873  // Read the current entries
874  std::vector<std::vector<unsigned> >::iterator aCurrentEntry = theCurrentEntry.begin();
875  std::vector<std::vector<unsigned> >::iterator lastCurrentEntry = theCurrentEntry.end();
876  unsigned allEntries = 0;
877  for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
878  unsigned size = aCurrentEntry->size();
879  for (unsigned iene = 0; iene < size; ++iene)
880  (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
881  }
882 
883  // Read the current interactions
884  std::vector<std::vector<unsigned> >::iterator aCurrentInteraction = theCurrentInteraction.begin();
885  std::vector<std::vector<unsigned> >::iterator lastCurrentInteraction = theCurrentInteraction.end();
886  unsigned allInteractions = 0;
887  for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
888  unsigned size = aCurrentInteraction->size();
889  for (unsigned iene = 0; iene < size; ++iene)
890  (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
891  }
892 
893  return true;
894  }
895 
896  return false;
897 }
std::vector< std::vector< unsigned > > theCurrentInteraction
Necessary to read the FullSim interactions.
dictionary results
std::string inputFile
Directory/Name of input file in case you want to read interactions from file.
tuple size
Write out results.
std::vector< std::vector< unsigned > > theCurrentEntry
Necessary to read the FullSim interactions.
void fastsim::NuclearInteraction::save ( )
private

Save the nuclear interactions to a file, so you can reproduce the events (e.g. in case of a crash).

Definition at line 797 of file NuclearInteraction.cc.

References findQualityFiles::size.

797  {
798  // Size of buffer
799  ++myOutputBuffer;
800 
801  // Periodically close the current file and open a new one
802  if (myOutputBuffer / 1000 * 1000 == myOutputBuffer) {
803  myOutputFile.close();
804  myOutputFile.open("NuclearInteractionOutputFile.txt");
805  }
806  //
807  unsigned size1 = theCurrentEntry.size() * theCurrentEntry.begin()->size();
808  std::vector<unsigned> theCurrentEntries;
809  theCurrentEntries.resize(size1);
810  size1 *= sizeof(unsigned);
811  //
812  unsigned size2 = theCurrentInteraction.size() * theCurrentInteraction.begin()->size();
813  std::vector<unsigned> theCurrentInteractions;
814  theCurrentInteractions.resize(size2);
815  size2 *= sizeof(unsigned);
816 
817  // Save the current entries
818  std::vector<std::vector<unsigned> >::const_iterator aCurrentEntry = theCurrentEntry.begin();
819  std::vector<std::vector<unsigned> >::const_iterator lastCurrentEntry = theCurrentEntry.end();
820  unsigned allEntries = 0;
821  for (; aCurrentEntry != lastCurrentEntry; ++aCurrentEntry) {
822  unsigned size = aCurrentEntry->size();
823  for (unsigned iene = 0; iene < size; ++iene)
824  theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
825  }
826 
827  // Save the current interactions
828  std::vector<std::vector<unsigned> >::const_iterator aCurrentInteraction = theCurrentInteraction.begin();
829  std::vector<std::vector<unsigned> >::const_iterator lastCurrentInteraction = theCurrentInteraction.end();
830  unsigned allInteractions = 0;
831  for (; aCurrentInteraction != lastCurrentInteraction; ++aCurrentInteraction) {
832  unsigned size = aCurrentInteraction->size();
833  for (unsigned iene = 0; iene < size; ++iene)
834  theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
835  }
836  // Write to file
837  myOutputFile.write((const char*)(&theCurrentEntries.front()), size1);
838  myOutputFile.write((const char*)(&theCurrentInteractions.front()), size2);
839  myOutputFile.flush();
840 }
std::vector< std::vector< unsigned > > theCurrentInteraction
Necessary to read the FullSim interactions.
std::ofstream myOutputFile
Output file to save interactions.
tuple size
Write out results.
std::vector< std::vector< unsigned > > theCurrentEntry
Necessary to read the FullSim interactions.
unsigned myOutputBuffer
Needed to save interactions to file.

Member Data Documentation

const std::vector<int> fastsim::NuclearInteraction::antineutronsID = {-2112, -3122, -3112, -3312, -3322}
private

PdgID of anti-neutrons.

Definition at line 333 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::antiprotonsID = {-2212, -3222}
private

PdgID of anti-protons.

Definition at line 331 of file NuclearInteraction.cc.

bool fastsim::NuclearInteraction::currentValuesWereSet
private

Read data from file that was created in a previous run.

Definition at line 115 of file NuclearInteraction.cc.

unsigned fastsim::NuclearInteraction::ien4
private

Find the index for which EN = 4.

Definition at line 110 of file NuclearInteraction.cc.

std::string fastsim::NuclearInteraction::inputFile
private

Directory/Name of input file in case you want to read interactions from file.

Definition at line 93 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::K0LsID = {130, 310}
private

PdgID of K0.

Definition at line 334 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::KminussesID = {-321}
private

PdgID of K-.

Definition at line 336 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::KplussesID = {321}
private

PdgID of K+.

Definition at line 335 of file NuclearInteraction.cc.

unsigned fastsim::NuclearInteraction::myOutputBuffer
private

Needed to save interactions to file.

Definition at line 113 of file NuclearInteraction.cc.

std::ofstream fastsim::NuclearInteraction::myOutputFile
private

Output file to save interactions.

Definition at line 112 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::neutronsID = {2112, 3122, 3112, 3312, 3322, 3334, -3334}
private

PdgID of neutrons.

Definition at line 332 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::PiminussesID = {-211}
private

PdgID of pi-.

Definition at line 338 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::PiplussesID = {211}
private

PdgID of pt+.

Definition at line 337 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::protonsID = {2212, 3222, -101, -102, -103, -104}
private

PdgID of protons.

Definition at line 330 of file NuclearInteraction.cc.

std::vector<std::vector<TBranch*> > fastsim::NuclearInteraction::theBranches
private

Necessary to read the FullSim interactions.

Definition at line 101 of file NuclearInteraction.cc.

std::vector<std::vector<unsigned> > fastsim::NuclearInteraction::theCurrentEntry
private

Necessary to read the FullSim interactions.

Definition at line 103 of file NuclearInteraction.cc.

std::vector<std::vector<unsigned> > fastsim::NuclearInteraction::theCurrentInteraction
private

Necessary to read the FullSim interactions.

Definition at line 104 of file NuclearInteraction.cc.

double fastsim::NuclearInteraction::theDistCut
private

Cut on deltaR for the FastSim Tracking (ClosestChargedDaughter algorithm)

Definition at line 91 of file NuclearInteraction.cc.

TFile* fastsim::NuclearInteraction::theFile = nullptr
private

Necessary to read the FullSim interactions.

Definition at line 99 of file NuclearInteraction.cc.

std::vector<std::vector<std::string> > fastsim::NuclearInteraction::theFileNames
private

Necessary to read the FullSim interactions.

Definition at line 107 of file NuclearInteraction.cc.

std::vector<std::vector<double> > fastsim::NuclearInteraction::theHadronCM
private

Necessary to read the FullSim interactions.

Definition at line 108 of file NuclearInteraction.cc.

const std::vector<double> fastsim::NuclearInteraction::theHadronEN
private
Initial value:
= {
1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 9.0, 12.0, 15.0, 20.0, 30.0, 50.0, 100.0, 200.0, 300.0, 500.0, 700.0, 1000.0}

Filled into 'theRatiosMap' (evolution of the interaction lengths with energy)

Definition at line 127 of file NuclearInteraction.cc.

double fastsim::NuclearInteraction::theHadronEnergy
private

Minimum energy for nuclear interaction.

Definition at line 92 of file NuclearInteraction.cc.

const std::vector<int> fastsim::NuclearInteraction::theHadronID = {211, -211, 130, 321, -321, 2212, -2212, 2112, -2112}
private

ID of the hadrons.

Definition at line 133 of file NuclearInteraction.cc.

const std::vector<double> fastsim::NuclearInteraction::theHadronMA
private
Initial value:
= {
0.13957, 0.13957, 0.497648, 0.493677, 0.493677, 0.93827, 0.93827, 0.939565, 0.939565}

Masses of the hadrons.

Definition at line 138 of file NuclearInteraction.cc.

const std::vector<std::string> fastsim::NuclearInteraction::theHadronNA
private
Initial value:
= {
"piplus", "piminus", "K0L", "Kplus", "Kminus", "p", "pbar", "n", "nbar"}

Names of the hadrons.

Definition at line 135 of file NuclearInteraction.cc.

const std::vector<double> fastsim::NuclearInteraction::theHadronPMin = {0.7, 0.0, 1.0, 1.0, 0.0, 1.1, 0.0, 1.1, 0.0}
private

Smallest momentum for inelastic interactions.

Definition at line 141 of file NuclearInteraction.cc.

std::map< int, int > fastsim::NuclearInteraction::theIDMap
staticprivate

Build the ID map (i.e., what is to be considered as a proton, etc...)

Definition at line 124 of file NuclearInteraction.cc.

const std::vector<double> fastsim::NuclearInteraction::theLengthRatio
private
Initial value:
= {
0.2257,
0.2294,
0.3042,
0.2591,
0.2854,
0.3101,
0.5216,
0.3668,
0.4898}

Inelastic interaction length at p(Hadron) = 5 GeV/c (relativ to radionLength of material)

Definition at line 143 of file NuclearInteraction.cc.

std::vector<std::vector<NUEvent*> > fastsim::NuclearInteraction::theNUEvents
private

Necessary to read the FullSim interactions.

Definition at line 102 of file NuclearInteraction.cc.

std::vector<std::vector<unsigned> > fastsim::NuclearInteraction::theNumberOfEntries
private

Necessary to read the FullSim interactions.

Definition at line 105 of file NuclearInteraction.cc.

std::vector<std::vector<unsigned> > fastsim::NuclearInteraction::theNumberOfInteractions
private

Necessary to read the FullSim interactions.

Definition at line 106 of file NuclearInteraction.cc.

const std::vector<double> fastsim::NuclearInteraction::theRatios
private

Filled into 'theRatiosMap' (evolution of the interaction lengths with energy)

Definition at line 154 of file NuclearInteraction.cc.

std::vector< std::vector< double > > fastsim::NuclearInteraction::theRatiosMap
staticprivate

The evolution of the interaction lengths with energy.

Definition at line 122 of file NuclearInteraction.cc.

std::vector<std::vector<TTree*> > fastsim::NuclearInteraction::theTrees
private

Necessary to read the FullSim interactions.

Definition at line 100 of file NuclearInteraction.cc.