25 std::vector<double>& hadronEnergies,
26 std::vector<int>& hadronTypes,
27 std::vector<std::string>& hadronNames,
28 std::vector<double>& hadronMasses,
29 std::vector<double>& hadronPMin,
31 std::vector<double>& lengthRatio,
32 std::vector< std::vector<double> >&
ratios,
33 std::map<int,int >& idMap,
35 unsigned int distAlgo,
39 thePionEN(hadronEnergies),
40 thePionID(hadronTypes),
41 thePionNA(hadronNames),
42 thePionMA(hadronMasses),
43 thePionPMin(hadronPMin),
44 thePionEnergy(pionEnergy),
45 theLengthRatio(lengthRatio),
48 theDistAlgo(distAlgo),
50 currentValuesWereSet(
false)
56 std::vector<TFile*> aVFile(
thePionEN.size(),
static_cast<TFile*
>(0));
57 std::vector<TTree*> aVTree(
thePionEN.size(),
static_cast<TTree*
>(0));
58 std::vector<TBranch*> aVBranch(
thePionEN.size(),
static_cast<TBranch*
>(0));
60 std::vector<unsigned> aVCurrentEntry(
thePionEN.size(),
static_cast<unsigned>(0));
61 std::vector<unsigned> aVCurrentInteraction(
thePionEN.size(),
static_cast<unsigned>(0));
62 std::vector<unsigned> aVNumberOfEntries(
thePionEN.size(),
static_cast<unsigned>(0));
63 std::vector<unsigned> aVNumberOfInteractions(
thePionEN.size(),
static_cast<unsigned>(0));
65 std::vector<double> aVPionCM(
thePionEN.size(),
static_cast<double>(0));
76 for (
unsigned iname=0; iname<
thePionNA.size(); ++iname ) {
92 std::cout <<
"***WARNING*** You are reading nuclear-interaction information from the file "
93 << inputFile <<
" created in an earlier run."
104 for (
unsigned iname=0; iname<
thePionNA.size(); ++iname ) {
105 for (
unsigned iene=0; iene<
thePionEN.size(); ++iene ) {
109 filename <<
"NuclearInteractionsVal_" <<
thePionNA[iname] <<
"_E"<< theEne <<
".root";
116 theFiles[iname][iene] = TFile::Open(fullPath.c_str());
118 <<
"File " <<
theFileNames[iname][iene] <<
" " << fullPath <<
" not found ";
121 theTrees[iname][iene] = (TTree*)
theFiles[iname][iene]->Get(
"NuclearInteractions");
123 <<
"Tree with name NuclearInteractions not found in " <<
theFileNames[iname][iene];
128 <<
"Branch with name nuEvent not found in " <<
theFileNames[iname][iene];
138 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
151 thePionCM[iname][iene] = (Reference+Proton).M();
185 for (
unsigned iene=0; iene<
theFiles[
ifile].size(); ++iene ) {
196 for(
auto evtPtr: vEvents) {
212 for (
unsigned iname=0; iname<
thePionNA.size(); ++iname ) {
213 for (
unsigned iene=0; iene<
thePionEN.size(); ++iene ) {
217 unsigned NInteractions =
theNUEvents[iname][iene]->nInteractions();
227 double pHadron =
std::sqrt(Particle.Vect().Mag2());
234 std::map<int,int>::const_iterator thePit =
theIDMap.find(Particle.
pid());
236 int thePid = thePit !=
theIDMap.end() ? thePit->second : Particle.
pid();
239 unsigned fPid =
abs(thePid);
240 if ( fPid != 211 && fPid != 130 && fPid != 321 && fPid != 2112 && fPid != 2212 ) {
247 unsigned thePidIndex =
index(thePid);
252 double ee = pHadron > 0.6 ?
254 double theElasticLength = ( 0.8753 * ee + 0.15 )
257 * theInelasticLength;
260 double theTotalInteractionLength = theInelasticLength + theElasticLength;
264 if ( aNuclInteraction < theTotalInteractionLength ) {
268 if ( elastic < theElasticLength/theTotalInteractionLength ) {
277 double phi = 2. * 3.14159265358979323 * random->
flatShoot();
282 Particle.
rotate(rotation1);
283 Particle.
rotate(rotation2);
292 Particle.Pz(), Particle.E());
305 const std::vector<double>& aPionCM =
thePionCM[thePidIndex];
306 const std::vector<double>& aRatios =
theRatios[thePidIndex];
318 double ecm = (Proton+Hadron).M();
327 double ecm1= (Proton+Hadron0).M();
331 double ecm2=aPionCM[0];
333 double ratio2=aRatios[0];
334 if ( ecm > aPionCM[0] && ecm < aPionCM [ aPionCM.size()-1 ] ) {
335 for (
unsigned ene=1;
336 ene < aPionCM.size() && ecm > aPionCM[ene-1];
338 if ( ecm<aPionCM[ene] ) {
341 ecm1 = aPionCM[ene1];
342 ecm2 = aPionCM[ene2];
343 ratio1 = aRatios[ene1];
344 ratio2 = aRatios[ene2];
347 }
else if ( ecm > aPionCM[ aPionCM.size()-1 ] ) {
348 ene1 = aPionCM.size()-1;
349 ene2 = aPionCM.size()-2;
350 ecm1 = aPionCM[ene1];
351 ecm2 = aPionCM[ene2];
352 ratio1 = aRatios[ene2];
353 ratio2 = aRatios[ene2];
358 double slope = (std::log10(ecm )-std::log10(ecm1))
359 / (std::log10(ecm2)-std::log10(ecm1));
360 double inelastic = ratio1 + (ratio2-ratio1) * slope;
361 double inelastic4 = pHadron < 4. ? aRatios[
ien4] : 1.;
368 if ( elastic > 1.- (inelastic*theInelasticLength)
369 /theTotalInteractionLength ) {
374 std::vector<NUEvent*>& aNUEvents =
theNUEvents[thePidIndex];
383 if ( random->
flatShoot() < slope || aNumberOfInteractions[ene1] == 0 )
398 theBoost /= theBoost.e();
409 if ( aCurrentInteraction[ene] == aNumberOfInteractions[ene] ) {
413 std::vector<TTree*>& aTrees =
theTrees[thePidIndex];
414 ++aCurrentEntry[ene];
417 aCurrentInteraction[ene] = 0;
418 if ( aCurrentEntry[ene] == aNumberOfEntries[ene] ) {
419 aCurrentEntry[ene] = 0;
422 unsigned myEntry = aCurrentEntry[ene];
425 aTrees[ene]->GetEntry(myEntry);
427 aNumberOfInteractions[ene] = aNUEvents[ene]->nInteractions();
433 = aNUEvents[ene]->theNUInteractions()[aCurrentInteraction[ene]];
435 unsigned firstTrack = anInteraction.
first;
436 unsigned lastTrack = anInteraction.
last;
441 double distMin = 1E99;
444 XYZVector theAxis = theBoost.Vect().Unit();
445 double theAngle = random->
flatShoot() * 2. * 3.14159265358979323;
451 XYZVector orthAxis = (zAxis.Cross(theBoost.Vect())).Unit();
452 double orthAngle = acos(theBoost.Vect().Unit().Z());
459 for (
unsigned iTrack=firstTrack; iTrack<=lastTrack; ++iTrack ) {
461 unsigned idaugh = iTrack - firstTrack;
474 + aParticle.
py*aParticle.
py
475 + aParticle.
pz*aParticle.
pz
476 + aParticle.
mass*aParticle.
mass/(ecm*ecm) );
479 aDaughter.SetXYZT(aParticle.
px*ecm,aParticle.
py*ecm,
480 aParticle.
pz*ecm,energy*ecm);
484 aDaughter.
rotate(orthRotation);
487 aDaughter.
rotate(axisRotation);
490 aDaughter.
boost(axisBoost);
495 if ( distance < distMin && distance <
theDistCut ) {
519 ++aCurrentInteraction[ene];
522 }
else if ( pHadron < 4. &&
523 elastic > 1.- (inelastic4*theInelasticLength)
524 /theTotalInteractionLength ) {
546 if ( fabs(Particle.
charge()) > 1E-12 ) {
549 double chargeDiff = fabs(aDaughter.
charge()-Particle.
charge());
550 if ( fabs(chargeDiff) < 1E-12 ) {
557 distance = (aDaughter.Vect().Unit().Cross(Particle.Vect().Unit())).R();
562 distance = (aDaughter.Vect().Cross(Particle.Vect())).R()
563 /aDaughter.Vect().Mag2();
597 std::vector<unsigned> theCurrentEntries;
598 theCurrentEntries.resize(size1);
599 size1*=
sizeof(unsigned);
604 std::vector<unsigned> theCurrentInteractions;
605 theCurrentInteractions.resize(size2);
606 size2 *=
sizeof(unsigned);
609 std::vector< std::vector<unsigned> >::const_iterator aCurrentEntry =
theCurrentEntry.begin();
610 std::vector< std::vector<unsigned> >::const_iterator lastCurrentEntry =
theCurrentEntry.end();
611 unsigned allEntries=0;
612 for ( ; aCurrentEntry!=lastCurrentEntry; ++aCurrentEntry ) {
613 unsigned size = aCurrentEntry->size();
614 for (
unsigned iene=0; iene<
size; ++iene )
615 theCurrentEntries[allEntries++] = (*aCurrentEntry)[iene];
619 std::vector< std::vector<unsigned> >::const_iterator aCurrentInteraction =
theCurrentInteraction.begin();
620 std::vector< std::vector<unsigned> >::const_iterator lastCurrentInteraction =
theCurrentInteraction.end();
621 unsigned allInteractions=0;
622 for ( ; aCurrentInteraction!=lastCurrentInteraction; ++aCurrentInteraction ) {
623 unsigned size = aCurrentInteraction->size();
624 for (
unsigned iene=0; iene<
size; ++iene )
625 theCurrentInteractions[allInteractions++] = (*aCurrentInteraction)[iene];
628 myOutputFile.write((
const char*)(&theCurrentEntries.front()), size1);
629 myOutputFile.write((
const char*)(&theCurrentInteractions.front()), size2);
637 std::ifstream myInputFile;
643 std::vector<unsigned> theCurrentEntries;
644 theCurrentEntries.resize(size1);
645 size1*=
sizeof(unsigned);
650 std::vector<unsigned> theCurrentInteractions;
651 theCurrentInteractions.resize(size2);
652 size2 *=
sizeof(unsigned);
658 myInputFile.open (inputFile.c_str());
659 if ( myInputFile.is_open() ) {
662 if ( stat(inputFile.c_str(), &
results) == 0 ) size = results.st_size;
666 myInputFile.seekg(size-size1-size2);
667 myInputFile.read((
char*)(&theCurrentEntries.front()),size1);
668 myInputFile.read((
char*)(&theCurrentInteractions.front()),size2);
672 std::vector< std::vector<unsigned> >::iterator aCurrentEntry =
theCurrentEntry.begin();
673 std::vector< std::vector<unsigned> >::iterator lastCurrentEntry =
theCurrentEntry.end();
674 unsigned allEntries=0;
675 for ( ; aCurrentEntry!=lastCurrentEntry; ++aCurrentEntry ) {
676 unsigned size = aCurrentEntry->size();
677 for (
unsigned iene=0; iene<
size; ++iene )
678 (*aCurrentEntry)[iene] = theCurrentEntries[allEntries++];
684 unsigned allInteractions=0;
685 for ( ; aCurrentInteraction!=lastCurrentInteraction; ++aCurrentInteraction ) {
686 unsigned size = aCurrentInteraction->size();
687 for (
unsigned iene=0; iene<
size; ++iene )
688 (*aCurrentInteraction)[iene] = theCurrentInteractions[allInteractions++];
702 while ( thePid !=
thePionID[myIndex] ) ++myIndex;
std::map< int, int > theIDMap
void boost(double bx, double by, double bz)
double flatShoot(double xmin=0.0, double xmax=1.0) const
static const double slope[3]
Sin< T >::type sin(const T &t)
std::vector< std::vector< TFile * > > theFiles
Geom::Theta< T > theta() const
XYZVector orthogonal(const XYZVector &) const
A vector orthogonal to another one (because it's not in XYZTLorentzVector)
std::vector< std::vector< unsigned > > theNumberOfInteractions
std::vector< double > thePionMA
std::vector< std::vector< TTree * > > theTrees
int pid() const
get the HEP particle ID number
std::vector< int > thePionID
double mass() const
get the MEASURED mass
std::vector< std::vector< unsigned > > theCurrentEntry
std::vector< std::vector< std::string > > theFileNames
void compute(ParticlePropagator &Particle, RandomEngineAndDistribution const *)
Generate a nuclear interaction according to the probability that it happens.
math::XYZVector XYZVector
std::vector< std::vector< unsigned > > theNumberOfEntries
bool currentValuesWereSet
std::vector< std::vector< double > > thePionCM
Abs< T >::type abs(const T &t)
void rotate(double rphi, const XYZVector &raxis)
bool read(std::string inputFile)
Read former nuclear interaction (from previous run)
double charge() const
get the MEASURED charge
unsigned index(int thePid)
Return a hashed index for a given pid.
std::vector< std::string > thePionNA
std::vector< std::vector< TBranch * > > theBranches
std::vector< std::vector< unsigned > > theCurrentInteraction
std::vector< std::vector< double > > theRatios
~NuclearInteractionSimulator()
Default Destructor.
NuclearInteractionSimulator(std::vector< double > &hadronEnergies, std::vector< int > &hadronTypes, std::vector< std::string > &hadronNames, std::vector< double > &hadronMasses, std::vector< double > &hadronPMin, double pionEnergy, std::vector< double > &lengthRatio, std::vector< std::vector< double > > &ratios, std::map< int, int > &idMap, std::string inputFile, unsigned int distAlgo, double distCut)
Constructor.
std::ofstream myOutputFile
std::vector< double > theLengthRatio
std::vector< RawParticle > _theUpdatedState
ROOT::Math::AxisAngle Rotation
std::vector< double > thePionEN
std::vector< std::vector< NUEvent * > > theNUEvents
volatile std::atomic< bool > shutdown_flag false
std::string fullPath() const
int theClosestChargedDaughterId
tuple size
Write out results.
Power< A, B >::type pow(const A &a, const B &b)
std::vector< double > thePionPMin
void save()
Save current nuclear interaction (for later use)
double distanceToPrimary(const RawParticle &Particle, const RawParticle &aDaughter) const
Compute distance between secondary and primary.
math::XYZTLorentzVector XYZTLorentzVector