27#include "CLHEP/Random/RandFlat.h"
40 : base_class(
type,name,parent)
46 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] ==>" << name() <<
"::initialize()");
51 ATH_MSG_WARNING(
"[PunchThroughG4Tool] unable to open or read the inverse CDF config");
52 return StatusCode::FAILURE;
58 ATH_MSG_WARNING(
"[PunchThroughG4Tool] unable to open or read the inverse PCA config");
59 return StatusCode::FAILURE;
65 ATH_MSG_WARNING(
"[PunchThroughG4Tool] size of infoMap for PCA and CDF differs! Something is wrong with input xml files.");
66 return StatusCode::FAILURE;
69 ATH_MSG_INFO(
"[PunchThroughG4Tool] initialization is successful" );
70 return StatusCode::SUCCESS;
74 G4ParticleTable *ptable = G4ParticleTable::GetParticleTable();
94 ATH_MSG_VERBOSE(
"VERBOSE: [PunchThroughG4Tool] registering punch-through particle type with pdg = " << pdg );
95 if (
registerPunchThroughParticle( *ptable, pdg, doAnti, minEnergy, maxNum, numFactor, energyFactor, posAngleFactor, momAngleFactor ) != StatusCode::SUCCESS)
97 ATH_MSG_ERROR(
"[PunchThroughG4Tool] unable to register punch-through particle type with pdg = " << pdg);
98 return StatusCode::FAILURE;
102 return StatusCode::SUCCESS;
108 ATH_MSG_INFO(
"[PunchThroughG4Tool] PunchThroughG4Tool::initializePhysics() called");
110 if (resolvedFileName.empty()) {
112 return StatusCode::FAILURE;
114 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] Parametrisation file found: " << resolvedFileName );
118 ATH_MSG_WARNING(
"[PunchThroughG4Tool] unable to open the lookup-table for the punch-through simulation (file does not exist)");
119 return StatusCode::FAILURE;
123 ATH_MSG_WARNING(
"[PunchThroughG4Tool] unable to open the lookup-table for the punch-through simulation (wrong or empty file?)");
124 return StatusCode::FAILURE;
142 ATH_MSG_FATAL (
"[PunchThroughG4Tool] Could not retrieve GeometryIdentifier Service. Abort");
143 return StatusCode::FAILURE;
150 return StatusCode::FAILURE;
156 const std::vector<std::pair<double, double>>* rzMS = &(
m_envDefSvc->getMuonRZBoundary());
157 const std::vector<std::pair<double, double>>* rzCalo = &(
m_envDefSvc->getCaloRZBoundary());
159 return StatusCode::SUCCESS;
172 ATH_MSG_WARNING(
"[PunchThroughG4Tool] more punch-through particle correlations are given, than punch-through particle types are registered (skipping the last ones)");
177 for (
unsigned int num = 0; num < numCorrelations; num++ )
185 if ( ! pdg2)
continue;
187 if (
registerCorrelation(pdg1, pdg2, minCorrEnergy, fullCorrEnergy) != StatusCode::SUCCESS )
189 ATH_MSG_ERROR(
"[PunchThroughG4Tool] unable to register punch-through particle correlation for pdg1=" << pdg1 <<
" pdg2=" << pdg2 );
190 return StatusCode::FAILURE;
194 return StatusCode::SUCCESS;
200 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] getCaloMSVars()==> m_R1 = "<< caloMSVarsVect[0] <<
", m_R2 = " << caloMSVarsVect[1] <<
", m_z1 = " << caloMSVarsVect[2] <<
", m_z2 = " << caloMSVarsVect[3]);
202 return caloMSVarsVect;
206 const std::vector<std::pair<double, double>>* rzCalo)
209 found1=
false; found2=
false;
213 for (
const auto & [r_tempCalo , z_tempCalo] : *rzCalo )
218 for (
const auto & [r_tempMS , z_tempMS] : *rzMS )
221 if (r_tempCalo==r_tempMS && z_tempCalo==z_tempMS && found1==
false )
224 m_z1=std::fabs(z_tempMS);
229 else if (r_tempCalo==r_tempMS && z_tempCalo==z_tempMS && r_tempCalo!=
m_R1 && std::fabs(z_tempCalo)!=
m_z1)
232 m_z2=std::fabs(z_tempMS);
237 if (found1==
true && found2==
true)
break;
242 if (found1 ==
false){
243 ATH_MSG_ERROR (
"[PunchThroughG4Tool] first coordinate of calo-MS border not found");
244 return StatusCode::FAILURE;
246 if (found2 ==
false){
247 ATH_MSG_ERROR (
"[PunchThroughG4Tool] second coordinate of calo-MS border not found; first one is: R1 ="<<
m_R1<<
" z1 ="<<
m_z1);
248 return StatusCode::FAILURE;
257 return StatusCode::FAILURE;
262 return StatusCode::SUCCESS;
272 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] finalize() successful" );
274 return StatusCode::SUCCESS;
279 G4ParticleDefinition* secG4Particle = ptable.FindParticle(secondarySignedPDG);
280 double mass = secG4Particle->GetPDGMass();
281 ATH_MSG_DEBUG(
"[PunchThroughG4Tool::checkParticleTable] secondarySignedPDG = " << secondarySignedPDG <<
", mass = "<< mass);
286 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] starting punch-through simulation");
289 std::vector<std::map<std::string, double>> secKinematicsMapVect;
292 const G4Track * g4PrimaryTrack = fastTrack.GetPrimaryTrack();
295 const G4ParticleDefinition * mainG4Particle = g4PrimaryTrack->GetDefinition();
298 ATH_MSG_DEBUG(
"PunchThroughG4Tool::computePunchThroughParticles Debug:"
299 <<
" Incoming particle:"
300 <<
" E=" << g4PrimaryTrack->GetKineticEnergy()/CLHEP::GeV <<
" GeV"
301 <<
" theta=" << g4PrimaryTrack->GetMomentumDirection().theta()
302 <<
" phi=" << g4PrimaryTrack->GetMomentumDirection().phi()
303 <<
" PDG=" << (mainG4Particle ? mainG4Particle->GetPDGEncoding() : -999)
304 <<
" Name=" << (mainG4Particle ? mainG4Particle->GetParticleName() :
"UNKNOWN"));
307 int pdgID = mainG4Particle->GetPDGEncoding();
308 float mainPartMass = mainG4Particle->GetPDGMass();
309 float mainMomMag2 = g4PrimaryTrack->GetMomentum().mag2();
310 float mainPartEta = g4PrimaryTrack->GetPosition().eta();
312 const G4ThreeVector mainMomentumDir = g4PrimaryTrack->GetMomentumDirection();
313 const G4ThreeVector mainMomentum = g4PrimaryTrack->GetMomentum();
314 const G4ThreeVector mainPosition = g4PrimaryTrack->GetPosition();
317 const double initEnergy = std::sqrt( mainMomMag2 + mainPartMass*mainPartMass );
318 const double initEta = mainPartEta;
320 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] position of the input particle: r"<<mainPosition.perp()<<
" z= "<<mainPosition.z() );
324 const Amg::Vector3D amg3DPosVec(mainPosition.x(), mainPosition.y(), mainPosition.z());
325 const Amg::Vector3D amg3DMomDirVec(mainMomentumDir.x(), mainMomentumDir.y(), mainMomentumDir.z());
326 const Amg::Vector3D amg3DMomVec(mainMomentum.x(), mainMomentum.y(), mainMomentum.z());
331 ATH_MSG_DEBUG(
"[PunchThroughG4Tool](GeoIDSvc) input particle doesn't point to calorimeter"<<
"Next GeoID: "<< nextGeoID );
343 for ( ; pdgIt != pdgItEnd; ++pdgIt, ++minEnergyIt)
345 if (std::abs(pdgID) == *pdgIt){
346 if(initEnergy < *minEnergyIt){
347 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] particle does not meet initiator min energy requirement. Dropping it in the calo.");
356 if (pdgIt == pdgItEnd)
358 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] particle is not registered as punch-through initiator. Dropping it in the calo.");
365 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] particle does not meet initiator eta range requirement. Dropping it in the calo.");
370 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] punchThroughProbability output: " << punchThroughProbability <<
" RandFlat: " << punchThroughClassifierRand );
373 if( punchThroughClassifierRand > punchThroughProbability){
374 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] particle not classified to create punch through. Dropping it in the calo.");
392 std::map<int, int> corrPdgNumDone;
398 ATH_MSG_DEBUG(
"[DEBUG] Enter computePunchThroughParticles: starting while (retry) loop");
399 while(secKinematicsMapVect.empty() && nTries < maxTries) {
401 ATH_MSG_DEBUG(
"[DEBUG] Retry " << nTries <<
", secKinematicsMapVect.size=" << secKinematicsMapVect.size());
405 int doPdg = currentParticle.first;
407 int corrPdg = currentParticle.second->getCorrelatedPdg();
413 std::map<int,int>::iterator itPdgPos = corrPdgNumDone.find(doPdg);
416 if ( itPdgPos == corrPdgNumDone.end() ) itPdgPos = corrPdgNumDone.find(corrPdg);
420 if ( itPdgPos == corrPdgNumDone.end() )
423 if ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) doPdg = corrPdg;
426 corrPdgNumDone[doPdg] =
getAllParticles(*g4PrimaryTrack, secKinematicsMapVect, rndmEngine, doPdg, interpEnergy, interpEta);
435 const int donePdg = itPdgPos->first;
436 const int doneNumPart = itPdgPos->second;
438 if (donePdg == doPdg) doPdg = corrPdg;
441 getCorrelatedParticles(*g4PrimaryTrack, secKinematicsMapVect, doPdg, doneNumPart, rndmEngine, interpEnergy, interpEta);
451 getAllParticles(*g4PrimaryTrack, secKinematicsMapVect, rndmEngine, doPdg, interpEnergy, interpEta);
456 if (msgLvl(MSG::DEBUG) && !secKinematicsMapVect.empty()) {
457 for (
size_t i = 0; i < secKinematicsMapVect.size(); ++i) {
459 for (
const auto& kv : secKinematicsMapVect[i]) {
469 return secKinematicsMapVect;
472int PunchThroughG4Tool::getAllParticles(
const G4Track& g4PrimaryTrack, std::vector<std::map<std::string, double>> &secKinematicsMapVect, CLHEP::HepRandomEngine* rndmEngine,
int pdg,
double interpEnergy,
double interpEta,
int numParticles)
475 float initParticleTheta = g4PrimaryTrack.GetPosition().theta();
476 float initParticlePhi = g4PrimaryTrack.GetPosition().phi();
480 double minAllowedEnergy = p->getMinEnergy();
484 if ( numParticles < 0 )
487 std::vector<int> parameters;
488 parameters.push_back( std::round(interpEnergy) );
489 parameters.push_back( std::round(interpEta*100) );
492 int maxParticles = p->getMaxNumParticles();
498 numParticles = int( p->getNumParticlesPDF()->getRand(rndmEngine, parameters) );
501 numParticles = lround( numParticles *= p->getNumParticlesFactor() );
503 while ( (maxParticles >= 0.) && (numParticles > maxParticles) );
506 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] adding " << numParticles <<
" punch-through particles with pdg code: " << pdg);
509 for (
int numCreated = 0; numCreated < numParticles; numCreated++ )
512 std::map<std::string, double> secondaryKinematicsMap =
getOneParticleKinematics(rndmEngine, pdg, initParticleTheta, initParticlePhi, interpEnergy, interpEta);
515 double energy = secondaryKinematicsMap.at(
"energy");
516 if(energy > minAllowedEnergy){
518 secKinematicsMapVect.push_back(secondaryKinematicsMap);
523 std::size_t numSecondaries = secKinematicsMapVect.size();
526 return (numSecondaries);
529int PunchThroughG4Tool::getCorrelatedParticles(
const G4Track& g4PrimaryTrack, std::vector<std::map<std::string, double>> &secKinematicsMapVect,
int pdg,
int corrParticles, CLHEP::HepRandomEngine* rndmEngine,
double interpEnergy,
double interpEta)
532 const G4ParticleDefinition * mainG4Particle = g4PrimaryTrack.GetDefinition();
534 float mainMomMag2 = g4PrimaryTrack.GetMomentum().mag2();
535 float mainPartMass = mainG4Particle->GetPDGMass();
540 const double initEnergy = std::sqrt( mainMomMag2 + mainPartMass*mainPartMass );
543 double rand = CLHEP::RandFlat::shoot(rndmEngine)
544 *(p->getFullCorrelationEnergy() - p->getMinCorrelationEnergy())
545 + p->getMinCorrelationEnergy();
548 if ( initEnergy < rand )
551 return getAllParticles(g4PrimaryTrack, secKinematicsMapVect, rndmEngine, pdg, interpEnergy, interpEta);
556 double *histDomains = p->getCorrelationHistDomains();
557 TH2F *hist2d =
nullptr;
560 if ( initEnergy < histDomains[1])
564 hist2d = p->getCorrelationLowEHist();
568 double rand = CLHEP::RandFlat::shoot(rndmEngine)*(histDomains[2]-histDomains[1]) + histDomains[1];
569 hist2d = ( initEnergy < rand) ? p->getCorrelationLowEHist() : p->getCorrelationHighEHist();
575 Int_t xbin = hist2d->GetXaxis()->FindFixBin(corrParticles);
576 int numParticles = 0;
577 int maxParticles = p->getMaxNumParticles();
582 double rand = CLHEP::RandFlat::shoot(rndmEngine);
584 for (
int ybin = 1; ybin <= hist2d->GetNbinsY(); ybin++ )
586 sum += hist2d->GetBinContent(xbin, ybin);
590 numParticles = ybin - 1;
595 numParticles = lround( numParticles * p->getNumParticlesFactor() );
597 while ( (maxParticles >= 0.) && (numParticles > maxParticles) );
600 return getAllParticles(g4PrimaryTrack, secKinematicsMapVect, rndmEngine, pdg, interpEnergy, interpEta, numParticles);
611 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] passedPCAIterator ==> pcaCdfIterator = "<< pcaCdfIterator <<
" , pdg = "<< secondaryPDG <<
" , interpEnergy = "<< interpEnergy <<
" MeV, interpEta(*100) = "<< interpEta*100);
616 if ( p->getdoAnti() )
619 double rand = CLHEP::RandFlat::shoot(rndmEngine);
621 if (rand > 0.5) anti = -1;
626 std::vector<int> parInitEnergyEta;
627 parInitEnergyEta.push_back( std::round(interpEnergy) );
628 parInitEnergyEta.push_back( std::round(interpEta*100) );
632 double deltaTheta = 0.;
634 double momDeltaTheta = 0.;
635 double momDeltaPhi = 0.;
637 double principal_component_0 = 0.;
638 double principal_component_1 = 0.;
639 double principal_component_2 = 0.;
640 double principal_component_3 = 0.;
641 double principal_component_4 = 0.;
642 std::vector<double> transformed_variables;
644 principal_component_0 = p->getPCA0PDF()->getRand(rndmEngine, parInitEnergyEta);
645 principal_component_1 = p->getPCA1PDF()->getRand(rndmEngine, parInitEnergyEta);
646 principal_component_2 = p->getPCA2PDF()->getRand(rndmEngine, parInitEnergyEta);
647 principal_component_3 = p->getPCA3PDF()->getRand(rndmEngine, parInitEnergyEta);
648 principal_component_4 = p->getPCA4PDF()->getRand(rndmEngine, parInitEnergyEta);
650 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] Drawn punch through kinematics PCA components: PCA0 = "<< principal_component_0 <<
" PCA1 = "<< principal_component_1 <<
" PCA2 = "<< principal_component_2 <<
" PCA3 = "<< principal_component_3 <<
" PCA4 = "<< principal_component_4 );
652 std::vector<double> principal_components {
653 principal_component_0,
654 principal_component_1,
655 principal_component_2,
656 principal_component_3,
657 principal_component_4
660 transformed_variables =
inversePCA(pcaCdfIterator,principal_components);
668 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] Transformed punch through kinematics: energy = "<< energy <<
" MeV deltaTheta = "<< deltaTheta <<
" deltaPhi = "<<
deltaPhi <<
" momDeltaTheta = "<< momDeltaTheta <<
" momDeltaPhi = "<< momDeltaPhi );
670 energy *= p->getEnergyFactor();
673 if (energy < p->getMinEnergy()) {
674 energy = p->getMinEnergy() + 10;
683 deltaTheta *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
687 theta = initParticleTheta + deltaTheta*p->getPosAngleFactor();
692 deltaPhi *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
695 double phi = initParticlePhi +
deltaPhi*p->getPosAngleFactor();
703 double momTheta = 0.;
707 momDeltaTheta *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
710 momTheta =
theta + momDeltaTheta*p->getMomAngleFactor();
712 while ( (momTheta >
M_PI) || (momTheta < 0.) );
715 momDeltaPhi *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
717 double momPhi =
phi + momDeltaPhi*p->getMomAngleFactor();
719 while ( std::fabs(momPhi) > 2*
M_PI) momPhi /= 2.;
720 while (momPhi >
M_PI) momPhi -= 2*
M_PI;
721 while (momPhi < -
M_PI) momPhi += 2*
M_PI;
724 std::map<std::string, double> secondaryKinematicsMap;
725 secondaryKinematicsMap.insert({
"anti" , anti });
726 secondaryKinematicsMap.insert({
"secondaryPDG" , secondaryPDG });
727 secondaryKinematicsMap.insert({
"energy" , energy });
728 secondaryKinematicsMap.insert({
"theta" ,
theta });
729 secondaryKinematicsMap.insert({
"phi" ,
phi });
730 secondaryKinematicsMap.insert({
"momTheta" , momTheta });
731 secondaryKinematicsMap.insert({
"momPhi" , momPhi });
733 return secondaryKinematicsMap;
739 double totEnergySecondaries = 0;
743 for (std::size_t i = 0; i < secKinematicsMapVect.size(); i++) {
744 energy = secKinematicsMapVect[i].at(
"energy");
745 totEnergySecondaries += energy;
750 secKinematicsMapVect.begin(),
751 secKinematicsMapVect.end(),
752 [](
const std::map<std::string, double>& lhs,
const std::map<std::string, double>& rhs) {
753 return lhs.at(
"energy") > rhs.at(
"energy");
758 if(totEnergySecondaries > mainEnergyInit){
759 ATH_MSG_DEBUG(
"[PunchThroughG4Tool::checkEnergySumFromSecondaries] Case where energy of created secondaries more than parent track identified! ");
760 ATH_MSG_DEBUG(
"[PunchThroughG4Tool::checkEnergySumFromSecondaries] ==> TotalSecondariesEnergy = " << totEnergySecondaries <<
", ParentEnergy = "<< mainEnergyInit);
764 while (totEnergySecondaries > mainEnergyInit && !secKinematicsMapVect.empty()) {
766 std::map<std::string, double> lastMap = secKinematicsMapVect.back();
769 double lastEnergy = lastMap.at(
"energy");
772 secKinematicsMapVect.pop_back();
775 totEnergySecondaries -= lastEnergy;
779 return secKinematicsMapVect;
782void PunchThroughG4Tool::createAllSecondaryTracks(G4ParticleTable &ptable, G4FastStep& fastStep,
const G4Track& g4PrimaryTrack, std::vector<std::map<std::string, double>> &secKinematicsMapVect, G4TrackVector& secTrackCont,
const std::vector<double> &caloMSVars){
784 const G4ParticleDefinition* mainG4Particle = g4PrimaryTrack.GetDefinition();
785 float mainMomMag2 = g4PrimaryTrack.GetMomentum().mag2();
786 float mainPartMass = mainG4Particle->GetPDGMass();
787 double mainEnergyInit = std::sqrt(mainMomMag2 + mainPartMass * mainPartMass);
793 int numSecondaries = secKinematicsMapVect.size();
795 if(numSecondaries>0){
797 fastStep.SetNumberOfSecondaryTracks(numSecondaries);
800 double currentTime = g4PrimaryTrack.GetGlobalTime();
803 for(
int i=0;i < numSecondaries; i++){
804 int anti = (int)(secKinematicsMapVect[i].at(
"anti"));
805 int secondaryPDG = (int)(secKinematicsMapVect[i].at(
"secondaryPDG"));
806 int signedPDG = secondaryPDG*anti;
807 double energy = secKinematicsMapVect[i].at(
"energy");
808 double theta = secKinematicsMapVect[i].at(
"theta");
809 double phi = secKinematicsMapVect[i].at(
"phi");
810 double momTheta = secKinematicsMapVect[i].at(
"momTheta");
811 double momPhi = secKinematicsMapVect[i].at(
"momPhi");
814 ATH_MSG_DEBUG(
"[PunchThroughG4Tool::createAllSecondaryTracks] createSecondaryTrack input parameters: currentTime = " << currentTime <<
" anti? = "<< anti <<
" signedPDG = "<< signedPDG <<
" energy = "<< energy <<
" theta = "<<
theta <<
" phi = "<<
phi <<
" momTheta = "<< momTheta <<
" momPhi " << momPhi);
815 G4Track* newSecTrack =
createSecondaryTrack( ptable, fastStep, currentTime, signedPDG, energy,
theta,
phi, momTheta, momPhi, caloMSVars);
820 G4Exception(
"[PunchThroughG4Tool::createAllSecondaryTracks]",
"ExceptionError", FatalException,
"something went wrong while creating punch-through particle tracks");
825 secTrackCont.push_back( newSecTrack );
833 double energy,
double theta,
double phi,
double momTheta,
double momPhi,
const std::vector<double> &caloMSVars)
836 G4Track *newSecTrack =
nullptr;
838 G4ParticleDefinition* secG4Particle = ptable.FindParticle(secondarySignedPDG);
839 double mass = secG4Particle->GetPDGMass();
848 G4ThreeVector momVec;
849 double momMag = std::sqrt(energy*energy - mass*mass);
850 momVec.setRThetaPhi(momMag,momTheta,momPhi);
851 ATH_MSG_DEBUG(
"[PunchThroughG4Tool]::createSecondaryTrack] setRThetaPhi pre input parameters: energy = " << energy <<
" mass = "<< mass);
852 ATH_MSG_DEBUG(
"[PunchThroughG4Tool]::createSecondaryTrack] setRThetaPhi input parameters: std::sqrt(energy*energy - mass*mass) = " << std::sqrt(energy*energy - mass*mass) <<
" momTheta = "<< momTheta <<
" momPhi = "<< momPhi);
855 G4DynamicParticle dynParticle(secG4Particle,momVec);
856 newSecTrack = fastStep.CreateSecondaryTrack(dynParticle, posVec, currentTime,
false);
862 return 0.5 * TMath::Erfc(-
x * M_SQRT1_2);
867 std::vector<double>
result;
869 for (
const auto&
r : m){
870 result.push_back(std::inner_product(v.begin(), v.end(),
r.begin(), 0.0));
879 constexpr char delimiters =
',';
880 std::vector<T> tokens;
882 std::string_view::size_type lastPos =
str.find_first_not_of(delimiters, 0);
884 std::string_view::size_type pos =
str.find_first_of(delimiters, lastPos);
886 while (std::string_view::npos != pos || std::string_view::npos != lastPos) {
888 std::string_view numbStr =
str.substr(lastPos, pos - lastPos);
890 std::from_chars(numbStr.data(), numbStr.data() + numbStr.size(), num);
891 tokens.push_back(num);
893 lastPos =
str.find_first_not_of(delimiters, pos);
895 pos =
str.find_first_of(delimiters, lastPos);
903 int pidStrSingle = std::abs(pid);
907 for (
unsigned int i = 0; i < mapvect.size(); i++){
908 const std::string &pidStr = mapvect[i].at(
"pidStr");
910 if(std::find(v.begin(), v.end(),pidStrSingle)==v.end())
continue;
911 const std::string &etaMinsStr = mapvect[i].at(
"etaMins");
912 const std::string &etaMaxsStr = mapvect[i].at(
"etaMaxs");
915 assert(etaMaxsVect.size() == etaMinsVect.size());
916 for (
unsigned int j = 0; j < etaMinsVect.size(); j++){
917 double etaMinToCompare = etaMinsVect[j];
918 double etaMaxToCompare = etaMaxsVect[j];
919 if((
eta >= etaMinToCompare) && (
eta < etaMaxToCompare)){
934 std::vector<std::map<std::string, std::string>> xml_info;
935 doc = xmlParseFile( xmlFilePath.c_str() );
938 for( xmlNodePtr nodeRoot = doc->children; nodeRoot !=
nullptr; nodeRoot = nodeRoot->next) {
939 if (xmlStrEqual( nodeRoot->name, BAD_CAST mainNode.c_str() )) {
940 for( xmlNodePtr nodeRootChild = nodeRoot->children; nodeRootChild !=
nullptr; nodeRootChild = nodeRootChild->next ) {
941 if (xmlStrEqual( nodeRootChild->name, BAD_CAST
"info" )) {
942 if (nodeRootChild->children != NULL) {
943 for( xmlNodePtr infoNode = nodeRootChild->children; infoNode !=
nullptr; infoNode = infoNode->next) {
944 if(xmlStrEqual( infoNode->name, BAD_CAST
"item" )){
945 std::map<std::string, std::string> xml_info_item;
947 if ((xmlBuff = xmlGetProp(infoNode, BAD_CAST
"name")) !=
nullptr) {
948 xml_info_item.insert({
"name",
reinterpret_cast<const char*
>(xmlBuff)});
950 if ((xmlBuff = xmlGetProp(infoNode, BAD_CAST
"etaMins")) !=
nullptr) {
951 xml_info_item.insert({
"etaMins",
reinterpret_cast<const char*
>(xmlBuff)});
953 if ((xmlBuff = xmlGetProp(infoNode, BAD_CAST
"etaMaxs")) !=
nullptr) {
954 xml_info_item.insert({
"etaMaxs",
reinterpret_cast<const char*
>(xmlBuff)});
956 if ((xmlBuff = xmlGetProp(infoNode, BAD_CAST
"pidStr")) !=
nullptr) {
957 xml_info_item.insert({
"pidStr",
reinterpret_cast<const char*
>(xmlBuff)});
960 xml_info.push_back(xml_info_item);
979 std::transform (transformed_variables.begin(), transformed_variables.end(),
m_PCA_means[pcaCdfIterator].begin(), transformed_variables.begin(), std::plus<double>());
981 return transformed_variables;
989 doc = xmlParseFile( inversePCAConfigFile.c_str() );
991 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] Loading inversePCA: " << inversePCAConfigFile);
998 std::vector<std::vector<double>> PCA_matrix;
1001 for( xmlNodePtr nodeRoot = doc->children; nodeRoot !=
nullptr; nodeRoot = nodeRoot->next) {
1002 if (xmlStrEqual( nodeRoot->name, BAD_CAST
"PCAinverse" )) {
1003 for( xmlNodePtr nodePCAinverse = nodeRoot->children; nodePCAinverse !=
nullptr; nodePCAinverse = nodePCAinverse->next ) {
1005 if (xmlStrEqual( nodePCAinverse->name, BAD_CAST
m_xml_info_pca[i].at(
"name").c_str() )) {
1006 if (nodePCAinverse->children != NULL) {
1007 for( xmlNodePtr pcaNode = nodePCAinverse->children; pcaNode !=
nullptr; pcaNode = pcaNode->next) {
1009 if (xmlStrEqual( pcaNode->name, BAD_CAST
"PCAmatrix" )) {
1010 std::vector<double> PCA_matrix_row;
1011 for (
int i = 0; i <= 4; ++i) {
1012 std::string propName =
"comp_" + std::to_string(i);
1013 if ((xmlBuff = xmlGetProp(pcaNode, BAD_CAST propName.c_str())) !=
nullptr) {
1014 PCA_matrix_row.push_back(atof(
reinterpret_cast<const char*
>(xmlBuff)));
1017 PCA_matrix.push_back(PCA_matrix_row);
1019 else if (xmlStrEqual( pcaNode->name, BAD_CAST
"PCAmeans" )) {
1020 std::vector<double> PCA_means_row;
1021 for (
int i = 0; i <= 4; ++i) {
1022 std::string propName =
"mean_" + std::to_string(i);
1023 if ((xmlBuff = xmlGetProp(pcaNode, BAD_CAST propName.c_str())) !=
nullptr) {
1024 PCA_means_row.push_back(atof(
reinterpret_cast<const char*
>(xmlBuff)));
1044 return StatusCode::SUCCESS;
1048 std::map<double, double> variable0_inverse_cdf_row;
1049 std::map<double, double> variable1_inverse_cdf_row;
1050 std::map<double, double> variable2_inverse_cdf_row;
1051 std::map<double, double> variable3_inverse_cdf_row;
1052 std::map<double, double> variable4_inverse_cdf_row;
1059 doc = xmlParseFile( inverseCdfConfigFile.c_str() );
1061 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] Loading inverse CDF: " << inverseCdfConfigFile);
1070 for( xmlNodePtr nodeRoot = doc->children; nodeRoot !=
nullptr; nodeRoot = nodeRoot->next) {
1071 if (xmlStrEqual( nodeRoot->name, BAD_CAST
"CDFMappings" )) {
1072 for( xmlNodePtr typeMappings = nodeRoot->children; typeMappings !=
nullptr; typeMappings = typeMappings->next ) {
1073 if (xmlStrEqual( typeMappings->name, BAD_CAST
m_xml_info_cdf[i].at(
"name").c_str() )) {
1074 if (typeMappings->children != NULL) {
1075 for( xmlNodePtr nodeMappings = typeMappings->children; nodeMappings !=
nullptr; nodeMappings = nodeMappings->next) {
1077 if (xmlStrEqual( nodeMappings->name, BAD_CAST
"variable0" )) {
1080 else if (xmlStrEqual( nodeMappings->name, BAD_CAST
"variable1" )) {
1083 else if (xmlStrEqual( nodeMappings->name, BAD_CAST
"variable2" )) {
1086 else if (xmlStrEqual( nodeMappings->name, BAD_CAST
"variable3" )) {
1089 else if (xmlStrEqual( nodeMappings->name, BAD_CAST
"variable4" )) {
1109 return StatusCode::SUCCESS;
1113 std::map<double, double> mappings;
1117 for( xmlNodePtr
node = nodeParent->children;
node !=
nullptr;
node =
node->next ) {
1119 if (xmlStrEqual(
node->
name, BAD_CAST
"CDFmap" )) {
1120 if ((xmlBuff = xmlGetProp(
node, BAD_CAST
"ref")) !=
nullptr) {
1121 ref = atof(
reinterpret_cast<const char*
> (xmlBuff) );
1123 if ((xmlBuff = xmlGetProp(
node, BAD_CAST
"quant")) !=
nullptr) {
1124 quant = atof(
reinterpret_cast<const char*
> (xmlBuff) );
1126 mappings.insert(std::pair<double, double>(
ref,
quant) );
1137 auto upper = inverse_cdf_map.upper_bound(norm_cdf);
1138 auto lower =
upper--;
1140 double m = (
upper->second - lower->second)/(
upper->first - lower->first);
1141 double c = lower->second - m * lower->first;
1142 double transformed = m * norm_cdf + c;
1150 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] interpolating incoming energy: " << energy);
1152 std::string energyPointsString;
1154 energyPointsString += std::to_string(element) +
" ";
1157 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] available energy points: " << energyPointsString);
1162 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] incoming energy > largest energy point, returning greatest energy point: " <<
m_energyPoints.back());
1166 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] incoming energy < smallest energy point, returning smallest energy point: " << *upperEnergy);
1167 return *upperEnergy;
1170 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] energy points upper_bound: "<< *upperEnergy);
1172 double randomShoot = CLHEP::RandFlat::shoot(rndmEngine);
1174 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] Shooting random number: "<< randomShoot);
1176 double midPoint = *std::prev(upperEnergy)*M_SQRT2;
1178 if(energy < midPoint){
1180 double distance = std::abs(energy - *std::prev(upperEnergy))/((midPoint) - *std::prev(upperEnergy));
1182 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] incoming energy is closest to prev(upper_bound) in log(energy), distance: " << distance );
1184 if(randomShoot < distance){
1185 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot < distance, returning upper_bound " << *upperEnergy );
1186 return *upperEnergy;
1188 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot > distance, returning prev(upper_bound) " << *std::prev(upperEnergy) );
1190 return *std::prev(upperEnergy);
1192 else if(energy > midPoint){
1194 double distance = std::abs(energy - *upperEnergy)/((*upperEnergy - midPoint));
1196 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] incoming energy is closest to upper_bound in log(energy), distance: " << distance );
1198 if(randomShoot < distance){
1199 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot < distance, returning prev(upper_bound) " << *std::prev(upperEnergy) );
1200 return *std::prev(upperEnergy);
1202 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot > distance, returning upper_bound " << *upperEnergy );
1203 return *upperEnergy;
1206 return *upperEnergy;
1211 double absEta = std::abs(
eta);
1213 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] interpolating incoming abs(eta): " << absEta);
1215 std::string etaPointsString;
1217 etaPointsString += std::to_string(element) +
" ";
1220 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] available eta points: " << etaPointsString);
1225 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] incoming abs(eta) > largest eta point, returning greatest eta point: " <<
m_etaPoints.back());
1230 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] eta points upper_bound: "<< *upperEta);
1232 double randomShoot = CLHEP::RandFlat::shoot(rndmEngine);
1234 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] Shooting random number: "<< randomShoot);
1236 if(std::abs(absEta - *upperEta) < std::abs(absEta - *std::prev(upperEta))){
1238 double distance = std::abs(absEta - *upperEta)/((*upperEta - *std::prev(upperEta))/2);
1240 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] abs(eta) is closer to eta points upper_bound, distance: " << distance );
1242 if(randomShoot > distance){
1243 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot > distance, returning upper_bound " << *upperEta );
1247 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot < distance, returning prev(upper_bound) " << *std::prev(upperEta) );
1249 return *std::prev(upperEta);
1251 else if(std::abs(absEta - *std::prev(upperEta)) < std::abs(absEta - *upperEta)){
1254 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] prev of upper bound is begin, returning that: " << *std::prev(upperEta) );
1255 return *std::prev(upperEta);
1258 double distance = std::abs(absEta - *std::prev(upperEta))/((*std::prev(upperEta) - *std::prev(std::prev(upperEta)))/2);
1260 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] abs(eta) is closer to eta points prev(upper_bound), distance: " << distance );
1262 if(randomShoot > distance){
1263 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot > distance, returning prev(prev(upper_bound)) " << *std::prev(std::prev(upperEta)) );
1265 return *std::prev(std::prev(upperEta));
1267 ATH_MSG_DEBUG(
"[PunchThroughG4Tool] randomShoot < distance, returning prev(upper_bound) " << *std::prev(upperEta) );
1269 return *std::prev(upperEta);
1272 return *std::prev(upperEta);
1277 double minEnergy,
int maxNumParticles,
double numParticlesFactor,
1278 double energyFactor,
double posAngleFactor,
double momAngleFactor)
1280 G4ParticleDefinition* secG4Particle = ptable.FindParticle(std::abs(pdg));
1281 double restMass = secG4Particle->GetPDGMass();
1286 if (!pdf_num )
return StatusCode::FAILURE;
1292 return StatusCode::FAILURE;
1300 return StatusCode::FAILURE;
1308 return StatusCode::FAILURE;
1315 return StatusCode::FAILURE;
1322 return StatusCode::FAILURE;
1327 particle->setNumParticlesPDF(std::move(pdf_num));
1328 particle->setPCA0PDF(std::move(pdf_pca0));
1329 particle->setPCA1PDF(std::move(pdf_pca1));
1330 particle->setPCA2PDF(std::move(pdf_pca2));
1331 particle->setPCA3PDF(std::move(pdf_pca3));
1332 particle->setPCA4PDF(std::move(pdf_pca4));
1335 minEnergy = ( minEnergy > restMass ) ? minEnergy : restMass;
1336 particle->setMinEnergy(minEnergy);
1337 particle->setMaxNumParticles(maxNumParticles);
1338 particle->setNumParticlesFactor(numParticlesFactor);
1339 particle->setEnergyFactor(energyFactor);
1340 particle->setPosAngleFactor(posAngleFactor);
1341 particle->setMomAngleFactor(momAngleFactor);
1346 return StatusCode::SUCCESS;
1350 double minCorrEnergy,
double fullCorrEnergy)
1353 std::map<int, PunchThroughParticle*>::iterator location1 =
m_particles.find(pdgID1);
1354 std::map<int, PunchThroughParticle*>::iterator location2 =
m_particles.find(pdgID2);
1358 return StatusCode::FAILURE;
1361 std::stringstream name;
1362 name <<
"NumExitCorrelations/x_PDG" << std::abs(pdgID1) <<
"__y_PDG" << std::abs(pdgID2) <<
"__lowE";
1365 name <<
"NumExitCorrelations/x_PDG" << std::abs(pdgID1) <<
"__y_PDG" << std::abs(pdgID2) <<
"__highE";
1368 name <<
"NumExitCorrelations/x_PDG" << std::abs(pdgID2) <<
"__y_PDG" << std::abs(pdgID1) <<
"__lowE";
1371 name <<
"NumExitCorrelations/x_PDG" << std::abs(pdgID2) <<
"__y_PDG" << std::abs(pdgID1) <<
"__highE";
1374 if ( (!hist1_2_lowE) || (!hist2_1_lowE) || (!hist1_2_highE) || (!hist2_1_highE) )
1376 ATH_MSG_ERROR(
"[PunchThroughG4Tool] unable to retrieve the correlation data for PDG IDs " << pdgID1 <<
" and " << pdgID2);
1377 return StatusCode::FAILURE;
1388 m_particles[pdgID1]->setCorrelation(pdgID2, hist2_1_lowE, hist2_1_highE,
1389 minCorrEnergy, fullCorrEnergy,
1390 lowE, midE, upperE);
1391 m_particles[pdgID2]->setCorrelation(pdgID1, hist1_2_lowE, hist1_2_highE,
1392 minCorrEnergy, fullCorrEnergy,
1393 lowE, midE, upperE);
1394 return StatusCode::SUCCESS;
1404 std::unique_ptr<PunchThroughPDFCreator> pdf = std::make_unique<PunchThroughPDFCreator>();
1407 std::stringstream dirName;
1408 dirName << folderName << pdg;
1409 pdf->setName(dirName.str());
1411 TDirectory * dir = (TDirectory*)fileLookupTable->Get(dirName.str().c_str());
1414 ATH_MSG_ERROR(
"[PunchThroughG4Tool] unable to retrieve directory object ("<< folderName << pdg <<
")" );
1419 TIter keyList(dir->GetListOfKeys());
1422 while ((key = (TKey*)keyList())) {
1425 TH1* hist =
nullptr;
1427 std::string histName;
1428 if(strcmp(key->GetClassName(),
"TH1F") == 0){
1429 hist = (TH1*)key->ReadObj();
1430 histName = hist->GetName();
1434 std::string strEnergy = histName.substr( histName.find_first_of(
'E') + 1, histName.find_first_of(
'_')-histName.find_first_of(
'E') - 1 );
1435 histName.erase(0, histName.find_first_of(
'_') + 1);
1436 std::string strEtaMin = histName.substr( histName.find(
"etaMin") + 6, histName.find_first_of(
'_') - histName.find(
"etaMin") - 6 );
1437 histName.erase(0, histName.find(
'_') + 1);
1438 std::string strEtaMax = histName.substr( histName.find(
"etaMax") + 6, histName.length());
1441 const int energy = std::stoi(strEnergy);
1442 const int etaMin = std::stoi(strEtaMin);
1445 pdf->addToEnergyEtaHist1DMap(energy, etaMin, hist);
1448 const double energyDbl =
static_cast<double>(energy);
1449 const double etaDbl =
static_cast<double>(etaMin)/100.;
1468 const std::string_view
str( cstr);
1469 const std::string_view pattern( cpattern);
1470 const size_t pos =
str.find(pattern);
1472 if ( pos == std::string::npos)
1474 ATH_MSG_WARNING(
"[PunchThroughG4Tool] unable to retrieve floating point number from string");
1475 return -999999999999.;
1477 const std::string_view substring =
str.substr(pos+pattern.length());
1478 std::from_chars(substring.data(), substring.data() + substring.size(), num);
1492 const double theta1 = atan (R1 / z1);
1493 const double theta2 = atan (R1 / z2);
1494 const double theta3 = atan (R2 / z2);
1500 r = std::fabs (z1 * tan(
theta));
1510 r = std::fabs(z2 * tan(
theta));;
1512 else if (
theta >= theta3 &&
theta < (TMath::Pi() - theta3) )
1517 else if (
theta >= (TMath::Pi() - theta3) &&
theta < (TMath::Pi() - theta2) )
1520 r = std::fabs(z2 * tan(
theta));
1522 else if (
theta >= (TMath::Pi() - theta2) &&
theta < (TMath::Pi() - theta1) )
1527 else if (
theta >= (TMath::Pi() - theta1) &&
theta <= TMath::Pi() )
1530 r = std::fabs(z1 * tan(
theta));
1536 ATH_MSG_WARNING(
"[PunchThroughG4Tool::punchTroughPosPropagator] Given theta angle is incorrect, setting particle position to (0, 0, 0)");
1537 x = 0.0;
y = 0.0;
z = 0.0;
r = 0.0;
1542 G4ThreeVector posVec(
x,
y,
z);
1544 ATH_MSG_DEBUG(
"[PunchThroughG4Tool::punchTroughPosPropagator] position of produced punch-through particle: x = " <<
x <<
" y = "<<
y <<
" z = "<<
z<<
" r = "<< posVec.perp() <<
"std::sqrt(x^2+y^2) = "<< std::sqrt(
x *
x +
y *
y));
const boost::regex ref(r_ef)
Scalar eta() const
pseudorapidity method
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
This class holds information for different properties of a punch-through particle (energy,...
void name(const std::string &n)
Eigen::Matrix< double, 3, 1 > Vector3D
AtlasRegion
A simple enum of ATLAS regions and sub-detectors.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)