14 #include <Math/AxisAngle.h> 15 #include "Math/Boost.h" 79 unsigned index(
int thePid);
127 const std::vector<double>
theHadronEN = {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};
132 const std::vector<int>
theHadronID = {211, -211, 130, 321, -321, 2212, -2212, 2112, -2112};
134 const std::vector<std::string>
theHadronNA = {
"piplus",
"piminus",
"K0L",
"Kplus",
"Kminus",
"p",
"pbar",
"n",
"nbar"};
136 const std::vector<double>
theHadronMA = {0.13957, 0.13957, 0.497648, 0.493677, 0.493677, 0.93827, 0.93827, 0.939565, 0.939565};
138 const std::vector<double>
theHadronPMin = {0.7, 0.0, 1.0, 1.0, 0.0, 1.1, 0.0, 1.1, 0.0};
143 0.2257, 0.2294, 0.3042, 0.2591, 0.2854, 0.3101, 0.5216, 0.3668, 0.4898
148 0.031390573,0.531842852,0.819614219,0.951251711,0.986382750,1.000000000,0.985087033,0.982996773,
149 0.990832192,0.992237923,0.994841580,0.973816742,0.967264815,0.971714258,0.969122824,0.978681792,
150 0.977312732,0.984255819,
152 0.035326512,0.577356403,0.857118809,0.965683504,0.989659360,1.000000000,0.989599240,0.980665408,
153 0.988384816,0.981038152,0.975002104,0.959996152,0.953310808,0.954705592,0.957615400,0.961150456,
154 0.965022184,0.960573304,
156 0.000000000,0.370261189,0.649793096,0.734342408,0.749079499,0.753360057,0.755790543,0.755872164,
157 0.751337674,0.746685288,0.747519634,0.739357554,0.735004444,0.803039922,0.832749896,0.890900187,
158 0.936734805,1.000000000,
160 0.000000000,0.175571717,0.391683394,0.528946472,0.572818635,0.614210280,0.644125538,0.670304050,
161 0.685144573,0.702870161,0.714708513,0.730805263,0.777711536,0.831090576,0.869267129,0.915747562,
162 0.953370523,1.000000000,
164 0.000000000,0.365353210,0.611663677,0.715315908,0.733498956,0.738361302,0.745253654,0.751459671,
165 0.750628335,0.746442657,0.750850669,0.744895986,0.735093960,0.791663444,0.828609543,0.889993040,
166 0.940897842,1.000000000,
168 0.000000000,0.042849136,0.459103223,0.666165343,0.787930873,0.890397011,0.920999533,0.937832788,
169 0.950920131,0.966595049,0.979542270,0.988061653,0.983260159,0.988958431,0.991723494,0.995273237,
170 1.000000000,0.999962634,
172 1.000000000,0.849956907,0.775625988,0.802018230,0.816207485,0.785899785,0.754998487,0.728977244,
173 0.710010673,0.670890339,0.665627872,0.652682888,0.613334247,0.647534574,0.667910938,0.689919693,
174 0.709200185,0.724199928,
176 0.000000000,0.059216484,0.437844536,0.610370629,0.702090648,0.780076890,0.802143073,0.819570432,
177 0.825829666,0.840079750,0.838435509,0.837529986,0.835687165,0.885205014,0.912450156,0.951451221,
178 0.973215562,1.000000000,
180 1.000000000,0.849573257,0.756479495,0.787147094,0.804572414,0.791806302,0.760234588,0.741109531,
181 0.724118186,0.692829761,0.688465897,0.671806061,0.636461171,0.675314029,0.699134460,0.724305037,
182 0.742556115,0.758504713
189 const std::vector<int>
protonsID = {2212, 3222, -101, -102, -103, -104};
191 const std::vector<int>
neutronsID = {2112, 3122, 3112, 3312, 3322, 3334, -3334};
193 const std::vector<int>
K0LsID = {130, 310};
250 TFile* aVFile=
nullptr;
252 std::vector<TBranch*> aVBranch(
theHadronEN.size());
253 std::vector<NUEvent*> aVNUEvents(
theHadronEN.size());
254 std::vector<unsigned> aVCurrentEntry(
theHadronEN.size());
255 std::vector<unsigned> aVCurrentInteraction(
theHadronEN.size());
256 std::vector<unsigned> aVNumberOfEntries(
theHadronEN.size());
257 std::vector<unsigned> aVNumberOfInteractions(
theHadronEN.size());
258 std::vector<std::string> aVFileName(
theHadronEN.size());
259 std::vector<double> aVHadronCM(
theHadronEN.size());
270 for(
unsigned iname=0; iname<
theHadronNA.size(); ++iname){
285 std::cout <<
"***WARNING*** You are reading nuclear-interaction information from the file " 286 << inputFile <<
" created in an earlier run." 294 edm::FileInPath myDataFile(
"FastSimulation/MaterialEffects/data/NuclearInteractions.root");
296 theFile = TFile::Open(fullPath.c_str());
300 for(
unsigned iname=0; iname<
theHadronNA.size(); ++iname){
301 for(
unsigned iene=0; iene<
theHadronEN.size(); ++iene){
304 filename <<
"NuclearInteractionsVal_" <<
theHadronNA[iname] <<
"_E"<< theEne <<
".root";
312 <<
"Tree with name " << treeName <<
" not found ";
315 <<
"Branch with name nuEvent not found in " <<
theFileNames[iname][iene];
323 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
352 for(
auto evtPtr: vEvents){
370 if(
abs(pdgId) <= 100 ||
abs(pdgId) >= 1000000)
381 if(radLengths < 1E-10)
389 for (
unsigned iname=0; iname<
theHadronNA.size(); ++iname ) {
390 for (
unsigned iene=0; iene<
theHadronEN.size(); ++iene ) {
394 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
413 std::map<int,int>::const_iterator thePit =
theIDMap.find(pdgId);
415 int thePid = (thePit !=
theIDMap.end() ? thePit->second :
pdgId);
418 unsigned fPid =
abs(thePid);
419 if(fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212)
425 unsigned thePidIndex =
index(thePid);
427 double theInelasticLength = radLengths *
theLengthRatio[thePidIndex];
432 double theElasticLength = (0.8753 * ee + 0.15) * theInelasticLength;
435 double theTotalInteractionLength = theInelasticLength + theElasticLength;
441 if(aNuclInteraction > theTotalInteractionLength)
448 if(elastic < theElasticLength/theTotalInteractionLength){
460 ROOT::Math::AxisAngle rotation2(particle.
momentum().Vect(),phi);
474 if(particle.
charge() != 0){
475 secondaries.back()->setMotherDeltaR(particle.
momentum());
476 secondaries.back()->setMotherPdgId(pdgId);
477 secondaries.back()->setMotherSimTrackIndex(particle.
simTrackIndex());
481 particle.
momentum().SetXYZT(0., 0., 0., 0.);
484 particle.
momentum().SetXYZT(rotated.X(),
492 const std::vector<double>& aHadronCM =
theHadronCM[thePidIndex];
493 const std::vector<double>& aRatios =
theRatiosMap[thePidIndex];
508 double ecm = (Proton+Hadron).M();
514 double ecm1= (Proton+Hadron0).M();
516 double ecm2=aHadronCM[0];
518 double ratio2=aRatios[0];
519 if(ecm > aHadronCM[0] && ecm < aHadronCM[aHadronCM.size()-1]){
520 for(
unsigned ene=1; ene < aHadronCM.size() && ecm > aHadronCM[ene-1]; ++ene){
521 if(ecm < aHadronCM[ene]){
524 ecm1 = aHadronCM[ene1];
525 ecm2 = aHadronCM[ene2];
526 ratio1 = aRatios[ene1];
527 ratio2 = aRatios[ene2];
530 }
else if(ecm > aHadronCM[aHadronCM.size()-1]){
531 ene1 = aHadronCM.size()-1;
532 ene2 = aHadronCM.size()-2;
533 ecm1 = aHadronCM[ene1];
534 ecm2 = aHadronCM[ene2];
535 ratio1 = aRatios[ene2];
536 ratio2 = aRatios[ene2];
540 double slope = (std::log10(ecm) - std::log10(ecm1)) / (std::log10(ecm2) - std::log10(ecm1));
541 double inelastic = ratio1 + (ratio2 - ratio1) * slope;
542 double inelastic4 = pHadron < 4. ? aRatios[
ien4] : 1.;
545 if(elastic > 1.- (inelastic*theInelasticLength) / theTotalInteractionLength){
549 std::vector<NUEvent*>& aNUEvents =
theNUEvents[thePidIndex];
555 if(random.
flatShoot() < slope || aNumberOfInteractions[ene1] == 0){
563 theBoost /= theBoost.e();
567 if(aCurrentInteraction[ene] == aNumberOfInteractions[ene]){
570 std::vector<TTree*>& aTrees =
theTrees[thePidIndex];
571 ++aCurrentEntry[ene];
573 aCurrentInteraction[ene] = 0;
574 if(aCurrentEntry[ene] == aNumberOfEntries[ene]){
575 aCurrentEntry[ene] = 0;
578 unsigned myEntry = aCurrentEntry[ene];
579 aTrees[ene]->GetEntry(myEntry);
580 aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
586 unsigned firstTrack = anInteraction.
first;
587 unsigned lastTrack = anInteraction.
last;
590 XYZVector theAxis = theBoost.Vect().Unit();
592 ROOT::Math::AxisAngle axisRotation(theAxis,theAngle);
593 ROOT::Math::Boost axisBoost(theBoost.x(),theBoost.y(),theBoost.z());
597 XYZVector orthAxis = (zAxis.Cross(theBoost.Vect())).Unit();
598 double orthAngle = acos(theBoost.Vect().Unit().Z());
599 ROOT::Math::AxisAngle orthRotation(orthAxis,orthAngle);
602 for(
unsigned iTrack=firstTrack; iTrack<=lastTrack; ++iTrack){
608 + aParticle.
py*aParticle.
py 609 + aParticle.
pz*aParticle.
pz 610 + aParticle.
mass*aParticle.
mass / (ecm * ecm));
615 XYZVector rotated = orthRotation(daugtherMomentum.Vect());
617 rotated = axisRotation(rotated);
620 daugtherMomentum.SetXYZT(rotated.X(), rotated.Y(), rotated.Z(), daugtherMomentum.E());
623 daugtherMomentum = axisBoost(daugtherMomentum);
632 if(particle.
charge() != 0){
633 secondaries.back()->setMotherDeltaR(particle.
momentum());
634 secondaries.back()->setMotherPdgId(pdgId);
635 secondaries.back()->setMotherSimTrackIndex(particle.
simTrackIndex());
640 particle.
momentum().SetXYZT(0., 0., 0., 0.);
648 ++aCurrentInteraction[ene];
651 }
else if(pHadron < 4. && elastic > 1.- (inelastic4*theInelasticLength) / theTotalInteractionLength){
653 particle.
momentum().SetXYZT(0., 0., 0., 0.);
671 std::vector<unsigned> theCurrentEntries;
672 theCurrentEntries.resize(size1);
673 size1*=
sizeof(unsigned);
676 std::vector<unsigned> theCurrentInteractions;
677 theCurrentInteractions.resize(size2);
678 size2 *=
sizeof(unsigned);
681 std::vector< std::vector<unsigned> >::const_iterator aCurrentEntry =
theCurrentEntry.begin();
682 std::vector< std::vector<unsigned> >::const_iterator lastCurrentEntry =
theCurrentEntry.end();
683 unsigned allEntries=0;
684 for(; aCurrentEntry!=lastCurrentEntry; ++aCurrentEntry){
685 unsigned size = aCurrentEntry->size();
686 for(
unsigned iene=0; iene<
size; ++iene)
687 theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
691 std::vector< std::vector<unsigned> >::const_iterator aCurrentInteraction =
theCurrentInteraction.begin();
692 std::vector< std::vector<unsigned> >::const_iterator lastCurrentInteraction =
theCurrentInteraction.end();
693 unsigned allInteractions=0;
694 for (; aCurrentInteraction!=lastCurrentInteraction; ++aCurrentInteraction){
695 unsigned size = aCurrentInteraction->size();
696 for(
unsigned iene=0; iene<
size; ++iene)
697 theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
700 myOutputFile.write((
const char*)(&theCurrentEntries.front()), size1);
701 myOutputFile.write((
const char*)(&theCurrentInteractions.front()), size2);
708 std::ifstream myInputFile;
712 std::vector<unsigned> theCurrentEntries;
713 theCurrentEntries.resize(size1);
714 size1*=
sizeof(unsigned);
717 std::vector<unsigned> theCurrentInteractions;
718 theCurrentInteractions.resize(size2);
719 size2 *=
sizeof(unsigned);
725 myInputFile.open (inputFile.c_str());
726 if(myInputFile.is_open()){
729 if(
stat(inputFile.c_str(), &
results) == 0) size = results.st_size;
733 myInputFile.seekg(size-size1-size2);
734 myInputFile.read((
char*)(&theCurrentEntries.front()),size1);
735 myInputFile.read((
char*)(&theCurrentInteractions.front()),size2);
739 std::vector< std::vector<unsigned> >::iterator aCurrentEntry =
theCurrentEntry.begin();
740 std::vector< std::vector<unsigned> >::iterator lastCurrentEntry =
theCurrentEntry.end();
741 unsigned allEntries=0;
742 for(; aCurrentEntry!=lastCurrentEntry; ++aCurrentEntry){
743 unsigned size = aCurrentEntry->size();
744 for(
unsigned iene=0; iene<
size; ++iene)
745 (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
751 unsigned allInteractions=0;
752 for(; aCurrentInteraction!=lastCurrentInteraction; ++aCurrentInteraction){
753 unsigned size = aCurrentInteraction->size();
754 for(
unsigned iene=0; iene<
size; ++iene)
755 (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
776 double x = fabs(aVector.X());
777 double y = fabs(aVector.Y());
778 double z = fabs(aVector.Z());
794 "fastsim::NuclearInteraction" const std::vector< int > antineutronsID
PdgID of anti-neutrons.
const std::vector< int > PiplussesID
PdgID of pt+.
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
Implementation of a generic detector layer (base class for forward/barrel layers).
const math::XYZTLorentzVector & position() const
Return position of the particle.
double theDistCut
Cut on deltaR for the FastSim Tracking (ClosestChargedDaughter algorithm)
const std::vector< int > KminussesID
PdgID of K-.
double flatShoot(double xmin=0.0, double xmax=1.0) const
std::vector< std::vector< TTree * > > theTrees
Necessary to read the FullSim interactions.
static const double slope[3]
Sin< T >::type sin(const T &t)
const double getNuclearInteractionThicknessFactor() const
Some layers have a different thickness for nuclear interactions.
Geom::Theta< T > theta() const
bool currentValuesWereSet
Read data from file that was created in a previous run.
std::vector< std::vector< unsigned > > theNumberOfEntries
Necessary to read the FullSim interactions.
const std::vector< int > KplussesID
PdgID of K+.
TFile * theFile
Necessary to read the FullSim interactions.
int pdgId() const
Return pdgId of the particle.
static std::vector< std::vector< double > > theRatiosMap
The evolution of the interaction lengths with energy.
Implementation of nuclear interactions of hadrons in the tracker layers (based on fully simulated int...
std::vector< std::vector< NUEvent * > > theNUEvents
Necessary to read the FullSim interactions.
const std::vector< int > protonsID
PdgID of protons.
const std::vector< double > theLengthRatio
Inelastic interaction length at p(Hadron) = 5 GeV/c (relativ to radionLength of material) ...
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Base class for any interaction model between a particle and a tracker layer.
const std::vector< double > theRatios
Filled into 'theRatiosMap' (evolution of the interaction lengths with energy)
void interact(fastsim::Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< fastsim::Particle > > &secondaries, const RandomEngineAndDistribution &random) override
Perform the interaction.
const std::vector< int > K0LsID
PdgID of K0.
std::vector< std::vector< std::string > > theFileNames
Necessary to read the FullSim interactions.
math::XYZVector XYZVector
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...)
std::vector< std::vector< unsigned > > theNumberOfInteractions
Necessary to read the FullSim interactions.
std::vector< std::vector< unsigned > > theCurrentInteraction
Necessary to read the FullSim interactions.
~NuclearInteraction() override
Default destructor.
unsigned index(int thePid)
Return a hashed index for a given particle ID.
Abs< T >::type abs(const T &t)
XYZVector orthogonal(const XYZVector &aVector) const
Return an orthogonal vector.
std::ofstream myOutputFile
Output file to save interactions.
math::XYZTLorentzVector XYZTLorentzVector
int simTrackIndex() const
Return index of the SimTrack.
const std::vector< int > neutronsID
PdgID of neutrons.
void save()
Save the nuclear interactions to a file, so you can reproduce the events (e.g. in case of a crash)...
std::vector< std::vector< double > > theHadronCM
Necessary to read the FullSim interactions.
double theHadronEnergy
Minimum energy for nuclear interaction.
math::XYZVector XYZVector
std::vector< std::vector< unsigned > > theCurrentEntry
Necessary to read the FullSim interactions.
NuclearInteraction(const std::string &name, const edm::ParameterSet &cfg)
Constructor.
std::vector< std::vector< TBranch * > > theBranches
Necessary to read the FullSim interactions.
XYZVectorD XYZVector
spatial vector with cartesian internal representation
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)...
const std::vector< double > theHadronPMin
Smallest momentum for inelastic interactions.
double charge() const
Return charge of the particle.
virtual const double getThickness(const math::XYZTLorentzVector &position) const =0
Return thickness of the layer at a given position.
unsigned ien4
Find the index for which EN = 4.
const std::vector< double > theHadronMA
Masses of the hadrons.
const std::vector< int > PiminussesID
PdgID of pi-.
const std::vector< double > theHadronEN
Filled into 'theRatiosMap' (evolution of the interaction lengths with energy)
static std::once_flag initializeOnce
const std::vector< int > theHadronID
ID of the hadrons.
std::string fullPath() const
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
#define DEFINE_EDM_PLUGIN(factory, type, name)
std::string inputFile
Directory/Name of input file in case you want to read interactions from file.
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
const std::vector< std::string > theHadronNA
Names of the hadrons.
Power< A, B >::type pow(const A &a, const B &b)
math::XYZTLorentzVector XYZTLorentzVector
unsigned myOutputBuffer
Needed to save interactions to file.