ATLAS Offline Software
Loading...
Searching...
No Matches
ISF::PunchThroughTool Class Reference

#include <PunchThroughTool.h>

Inheritance diagram for ISF::PunchThroughTool:

Public Member Functions

 PunchThroughTool (const std::string &, const std::string &, const IInterface *)
 Constructor.
virtual ~PunchThroughTool ()=default
 Destructor.
virtual StatusCode initialize ()
 AlgTool initialize method.
virtual StatusCode finalize ()
 AlgTool finalize method.
const ISF::ISFParticleVectorcomputePunchThroughParticles (const ISF::ISFParticle &isfp, const TFCSSimulationState &simulstate, CLHEP::HepRandomEngine *rndmEngine) const
 interface function: fill a vector with the punch-through particles

Private Member Functions

StatusCode registerParticle (int pdgID, bool doAntiparticle=false, double minEnergy=0., int maxNumParticles=-1, double numParticlesFactor=1., double energyFactor=1., double posAngleFactor=1., double momAngleFactor=1.)
 registers a type of punch-through particles which will be simulated
StatusCode registerCorrelation (int pdgID1, int pdgID2, double minCorrEnergy=0., double fullCorrEnergy=0.)
 register a correlation for the two given types of punch-through particles with a given energy threshold above which we will have full correlation
std::unique_ptr< ISF::PDFcreatorreadLookuptablePDF (int pdgID, const std::string &folderName)
 reads out the lookuptable for the given type of particle
int getAllParticles (const ISF::ISFParticle &isfp, ISFParticleVector &isfpCont, CLHEP::HepRandomEngine *rndmEngine, int pdg, double interpEnergy, double interpEta, int numParticles=-1) const
 create the right number of punch-through particles for the given pdg and return the number of particles which was created.
int getCorrelatedParticles (const ISF::ISFParticle &isfp, ISFParticleVector &isfpCont, int doPdg, int corrParticles, CLHEP::HepRandomEngine *rndmEngine, double interpEnergy, double interpEta) const
 get the right number of particles for the given pdg while considering the correlation to an other particle type, which has already created 'corrParticles' number of particles
ISF::ISFParticlegetOneParticle (const ISF::ISFParticle &isfp, int pdg, CLHEP::HepRandomEngine *rndmEngine, double interpEnergy, double interpEta) const
 create exactly one punch-through particle with the given pdg and the given max energy
ISF::ISFParticlecreateExitPs (const ISF::ISFParticle &isfp, int PDGcode, double energy, double theta, double phi, double momTheta, double momPhi) const
 create a ISF Particle state at the MS entrace containing a particle with the given properties
double getFloatAfterPatternInStr (const char *str, const char *pattern)
 get the floating point number in a string, after the given pattern
Amg::Vector3D propagator (double theta, double phi) const
 get particle through the calorimeter
std::vector< double > inversePCA (int pcaCdfIterator, std::vector< double > &variables) const
double interpolateEnergy (const double &energy, CLHEP::HepRandomEngine *rndmEngine) const
double interpolateEta (const double &eta, CLHEP::HepRandomEngine *rndmEngine) const
std::vector< std::map< std::string, std::string > > getInfoMap (const std::string &mainNode, const std::string &xmlFilePath)
int passedParamIterator (int pid, double eta, const std::vector< std::map< std::string, std::string > > &mapvect) const
StatusCode initializeInverseCDF (const std::string &quantileTransformerConfigFile)
StatusCode initializeInversePCA (const std::string &inversePCAConfigFile)

Static Private Member Functions

static double inverseCdfTransform (double variable, const std::map< double, double > &inverse_cdf_map)
static std::vector< double > dotProduct (const std::vector< std::vector< double > > &m, const std::vector< double > &v)
static double normal_cdf (double x)
static std::map< double, double > getVariableCDFmappings (xmlNodePtr &nodeParent)

Private Attributes

std::vector< double > m_energyPoints
 energy and eta points in param
std::vector< double > m_etaPoints
double m_R1 {0.}
 calo-MS borders
double m_R2 {0.}
double m_z1 {0.}
double m_z2 {0.}
const HepPDT::ParticleDataTable * m_particleDataTable {nullptr}
 ParticleDataTable needed to get connection pdg_code <-> charge.
TFile * m_fileLookupTable {nullptr}
 ROOT objects.
std::map< int, PunchThroughParticle * > m_particles
 needed to create punch-through particles with the right distributions
StringProperty m_filenameLookupTable {this, "FilenameLookupTable", "CaloPunchThroughParametrisation.root", "holds the filename of the lookup table"}
 Properties.
StringProperty m_filenameInverseCDF {this, "FilenameInverseCdf", "", "holds the filename of inverse quantile transformer config"}
StringProperty m_filenameInversePCA {this, "FilenameInversePca", "", "holds the filename of inverse PCA config"}
PublicToolHandle< IPunchThroughClassifierm_punchThroughClassifier {this, "PunchThroughClassifier", "ISF_PunchThroughClassifier", ""}
IntegerArrayProperty m_pdgInitiators {this, "PunchThroughInitiators", {}, "vector of punch-through initiator pgds"}
IntegerArrayProperty m_initiatorsMinEnergy {this, "InitiatorsMinEnergy", {}, "vector of punch-through initiator min energies to create punch through"}
DoubleArrayProperty m_initiatorsEtaRange {this, "InitiatorsEtaRange", {}, "vector of min and max abs eta range to allow punch through initiators"}
IntegerArrayProperty m_punchThroughParticles {this, "PunchThroughParticles", {}, "vector of pdgs of the particles produced in punch-throughs"}
BooleanArrayProperty m_doAntiParticles {this, "DoAntiParticles", {}, "vector of bools to determine if anti-particles are created for each punch-through particle type"}
IntegerArrayProperty m_correlatedParticle {this, "CorrelatedParticle", {}, "holds the pdg of the correlated particle for each given pdg"}
DoubleArrayProperty m_minCorrEnergy {this, "MinCorrelationEnergy", {}, "holds the energy threshold below which no particle correlation is computed"}
DoubleArrayProperty m_fullCorrEnergy {this, "FullCorrelationEnergy", {}, "holds the energy threshold above which a particle correlation is fully developed"}
DoubleArrayProperty m_posAngleFactor {this, "ScalePosDeflectionAngles", {}, "tuning parameter to scale the position deflection angles"}
DoubleArrayProperty m_momAngleFactor {this, "ScaleMomDeflectionAngles", {}, "tuning parameter to scale the momentum deflection angles"}
DoubleArrayProperty m_minEnergy {this, "MinEnergy", {}, "punch-through particles minimum energies"}
IntegerArrayProperty m_maxNumParticles {this, "MaxNumParticles", {}, "maximum number of punch-through particles for each particle type"}
DoubleArrayProperty m_numParticlesFactor {this, "NumParticlesFactor", {}, "scale the number of punch-through particles"}
DoubleArrayProperty m_energyFactor {this, "EnergyFactor", {}, "scale the energy of the punch-through particles"}
ServiceHandle< IPartPropSvc > m_particlePropSvc {this, "PartPropSvc", "PartPropSvc", "particle properties svc"}
ServiceHandle< IGeoIDSvcm_geoIDSvc {this, "GeoIDSvc", "ISF::GeoIDSvc"}
ServiceHandle< IEnvelopeDefSvcm_envDefSvc {this, "EnvelopeDefSvc", "AtlasGeometry_EnvelopeDefSvc"}
DoubleProperty m_beamPipe {this, "BeamPipeRadius", 500.}
 beam pipe radius
std::vector< std::vector< std::vector< double > > > m_inverse_PCA_matrix
 pca vectors
std::vector< std::vector< double > > m_PCA_means
std::vector< std::map< std::string, std::string > > m_xml_info_pca
 infoMaps
std::vector< std::map< std::string, std::string > > m_xml_info_cdf
std::vector< std::map< double, double > > m_variable0_inverse_cdf
 (vector of map) for CDF mappings
std::vector< std::map< double, double > > m_variable1_inverse_cdf
std::vector< std::map< double, double > > m_variable2_inverse_cdf
std::vector< std::map< double, double > > m_variable3_inverse_cdf
std::vector< std::map< double, double > > m_variable4_inverse_cdf

Detailed Description

Definition at line 55 of file PunchThroughTool.h.

Constructor & Destructor Documentation

◆ PunchThroughTool()

ISF::PunchThroughTool::PunchThroughTool ( const std::string & type,
const std::string & name,
const IInterface * parent )

Constructor.

Definition at line 62 of file PunchThroughTool.cxx.

65: base_class(type, name, parent)
66{
67}

◆ ~PunchThroughTool()

virtual ISF::PunchThroughTool::~PunchThroughTool ( )
virtualdefault

Destructor.

Member Function Documentation

◆ computePunchThroughParticles()

const ISF::ISFParticleVector * ISF::PunchThroughTool::computePunchThroughParticles ( const ISF::ISFParticle & isfp,
const TFCSSimulationState & simulstate,
CLHEP::HepRandomEngine * rndmEngine ) const

interface function: fill a vector with the punch-through particles

Definition at line 288 of file PunchThroughTool.cxx.

289{
290 ATH_MSG_DEBUG( "[ punchthrough ] starting punch-through simulation");
291
292 // create output particle collection
293 auto isfpCont = std::make_unique<ISF::ISFParticleVector>();
294
295 ATH_MSG_VERBOSE("[ punchthrough ] position of the input particle: r"<<isfp.position().perp()<<" z= "<<isfp.position().z() );
296
297 //check if it points to the calorimeter - if not, don't simulate
298
299 if ( m_geoIDSvc->identifyNextGeoID(isfp) != AtlasDetDescr::fAtlasCalo)
300 {
301 ATH_MSG_VERBOSE ("[ GeoIDSvc ] input particle doesn't point to calorimeter"<< "Next GeoID: "<<m_geoIDSvc->identifyNextGeoID(isfp) );
302 return nullptr;
303 }
304
305
306 // check if the particle's pdg is registered as a punch-through-causing type
307 {
308 std::vector<int>::const_iterator pdgIt = m_pdgInitiators.begin();
309 std::vector<int>::const_iterator pdgItEnd = m_pdgInitiators.end();
310
311 std::vector<int>::const_iterator minEnergyIt = m_initiatorsMinEnergy.begin();
312 // loop over all known punch-through initiators
313 for ( ; pdgIt != pdgItEnd; ++pdgIt, ++minEnergyIt)
314 {
315 if (std::abs(isfp.pdgCode()) == *pdgIt){
316 if(std::sqrt( isfp.momentum().mag2() + isfp.mass()*isfp.mass() ) < *minEnergyIt){
317 ATH_MSG_DEBUG("[ punchthrough ] particle does not meet initiator min energy requirement. Dropping it in the calo.");
318 return nullptr;
319 }
320 break;
321 }
322 }
323
324 // particle will not cause punch-through -> bail out
325 if (pdgIt == pdgItEnd)
326 {
327 ATH_MSG_DEBUG("[ punchthrough ] particle is not registered as punch-through initiator. Dropping it in the calo.");
328 return nullptr;
329 }
330 }
331
332 if(isfp.position().eta() < m_initiatorsEtaRange.value().at(0) || isfp.position().eta() > m_initiatorsEtaRange.value().at(1) ){
333 ATH_MSG_DEBUG("[ punchthrough ] particle does not meet initiator eta range requirement. Dropping it in the calo.");
334 return nullptr;
335 }
336
337 //Calculate probability of punch through using punchThroughClassifier
338 double punchThroughProbability = m_punchThroughClassifier->computePunchThroughProbability(isfp, simulstate);
339
340 //Draw random number to compare to probability
341 double punchThroughClassifierRand = CLHEP::RandFlat::shoot(rndmEngine);
342
343 ATH_MSG_DEBUG("[ punchthrough ] punchThroughProbability output: " << punchThroughProbability << " RandFlat: " << punchThroughClassifierRand );
344
345 //If probability < random number then don't simulate punch through
346 if( punchThroughClassifierRand > punchThroughProbability){
347 ATH_MSG_DEBUG("[ punchthrough ] particle not classified to create punch through. Dropping it in the calo.");
348 return nullptr;
349 }
350
351 //if initial particle is on ID surface, points to the calorimeter, is a punch-through initiator, meets initiator min enery and eta range
352
353 // this is the place where the magic is done:
354 // test for each registered punch-through pdg if a punch-through
355 // occures and create these particles
356 // -> therefore loop over all registered pdg ids
357 // to keep track of the correlated particles which were already simulated:
358 // first int is pdg, second int is number of particles created
359
360 // calculate incoming energy and eta
361 const double initEnergy = std::sqrt( isfp.momentum().mag2() + isfp.mass()*isfp.mass() );
362 const double initEta = isfp.position().eta();
363
364 // interpolate energy and eta
365 const double interpEnergy = interpolateEnergy(initEnergy, rndmEngine);
366 const double interpEta = interpolateEta(initEta, rndmEngine);
367
368 std::map<int, int> corrPdgNumDone;
369
370 int maxTries = 10;
371 int nTries = 0;
372
373 // loop over all particle pdgs
374 while(isfpCont->empty() && nTries < maxTries) { //ensure we always create at least one punch through particle, maxTries to catch very rare cases
375
376 for (const auto& currentParticle : m_particles)
377 {
378 // the pdg that is currently treated
379 int doPdg = currentParticle.first;
380 // get the current particle's correlated pdg
381 int corrPdg = currentParticle.second->getCorrelatedPdg();
382
383 // if there is a correlated particle type to this one
384 if (corrPdg)
385 {
386 // find out if the current pdg was already simulated
387 std::map<int,int>::iterator pos = corrPdgNumDone.find(doPdg);
388 // if the current pdg was not simulated yet, find out if
389 // it's correlated one was simulated
390 if ( pos == corrPdgNumDone.end() ) pos = corrPdgNumDone.find(corrPdg);
391
392 // neither this nor the correlated particle type was simulated
393 // so far:
394 if ( pos == corrPdgNumDone.end() )
395 {
396 // -> roll a dice if we create this particle or its correlated one
397 if ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) doPdg = corrPdg;
398 // now create the particles with the given pdg and note how many
399 // particles of this pdg are created
400 corrPdgNumDone[doPdg] = getAllParticles(isfp, *isfpCont, rndmEngine, doPdg, interpEnergy, interpEta);
401 }
402
403 // one of the two correlated particle types was already simulated
404 // 'pos' points to the already simulated one
405 else
406 {
407 // get the pdg of the already simulated particle and the number
408 // of these particles that were created
409 const int donePdg = pos->first;
410 const int doneNumPart = pos->second;
411 // set the pdg of the particle type that will be done
412 if (donePdg == doPdg) doPdg = corrPdg;
413
414 // now create the correlated particles
415 getCorrelatedParticles(isfp, *isfpCont, doPdg, doneNumPart, rndmEngine, interpEnergy, interpEta);
416 // note: no need to take note, that this particle type is now simulated,
417 // since this is the second of two correlated particles, which is
418 // simulated and we do not have correlations of more than two particles.
419 }
420
421 // if no correlation for this particle
422 // -> directly create all particles with the current pdg
423 }
424 else getAllParticles(isfp, *isfpCont, rndmEngine, doPdg, interpEnergy, interpEta);
425
426 } // for-loop over all particle pdgs
427
428 nTries++;
429 }
430
431 if (!isfpCont->empty()) ATH_MSG_DEBUG( "[ punchthrough ] returning ISFparticle vector , size: "<<isfpCont->size() );
432
433 for (ISF::ISFParticle *particle : *isfpCont) {
434 ATH_MSG_DEBUG("codes of produced punch through particle: pdg = "<< particle->pdgCode());
435 Amg::Vector3D position = particle->position();
436 ATH_MSG_DEBUG("position of produced punch-through particle: x = "<< position.x() <<" y = "<< position.y() <<" z = "<< position.z());
437 Amg::Vector3D momentum = particle->momentum();
438 ATH_MSG_DEBUG("momentum of produced punch-through particle: px = "<< momentum.x() <<" py = "<< momentum.x() <<" pz = "<< momentum.x() <<" e = "<< particle->ekin() << " mass = " << particle->mass());
439 }
440
441 return isfpCont.release();
442}
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
const Amg::Vector3D & momentum() const
The current momentum vector of the ISFParticle.
const Amg::Vector3D & position() const
The current position of the ISFParticle.
int pdgCode() const
PDG value.
double mass() const
mass of the particle
PublicToolHandle< IPunchThroughClassifier > m_punchThroughClassifier
int getAllParticles(const ISF::ISFParticle &isfp, ISFParticleVector &isfpCont, CLHEP::HepRandomEngine *rndmEngine, int pdg, double interpEnergy, double interpEta, int numParticles=-1) const
create the right number of punch-through particles for the given pdg and return the number of particl...
DoubleArrayProperty m_initiatorsEtaRange
std::map< int, PunchThroughParticle * > m_particles
needed to create punch-through particles with the right distributions
IntegerArrayProperty m_initiatorsMinEnergy
ServiceHandle< IGeoIDSvc > m_geoIDSvc
int getCorrelatedParticles(const ISF::ISFParticle &isfp, ISFParticleVector &isfpCont, int doPdg, int corrParticles, CLHEP::HepRandomEngine *rndmEngine, double interpEnergy, double interpEta) const
get the right number of particles for the given pdg while considering the correlation to an other par...
IntegerArrayProperty m_pdgInitiators
double interpolateEta(const double &eta, CLHEP::HepRandomEngine *rndmEngine) const
double interpolateEnergy(const double &energy, CLHEP::HepRandomEngine *rndmEngine) const
Eigen::Matrix< double, 3, 1 > Vector3D
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses

◆ createExitPs()

ISF::ISFParticle * ISF::PunchThroughTool::createExitPs ( const ISF::ISFParticle & isfp,
int PDGcode,
double energy,
double theta,
double phi,
double momTheta,
double momPhi ) const
private

create a ISF Particle state at the MS entrace containing a particle with the given properties

@TODO: fix

Definition at line 1318 of file PunchThroughTool.cxx.

1320{
1321 // the intersection point with Calo-MS surface
1322
1324
1325 // set up the real punch-through particle at this position
1326 // set up the momentum vector of this particle as a GlobalMomentum
1327 // by using the given energy and mass of the particle and also using
1328 // the given theta and phi
1329
1331 double mass = m_particleDataTable->particle(std::abs(pdg))->mass();
1332 Amg::setRThetaPhi( mom, std::sqrt(energy*energy - mass*mass), momTheta, momPhi);
1333 ATH_MSG_DEBUG("setRThetaPhi pre input parameters: energy = "<< energy <<" mass = "<< mass);
1334 ATH_MSG_DEBUG("setRThetaPhi input parameters: std::sqrt(energy*energy - mass*mass) = "<< std::sqrt(energy*energy - mass*mass) <<" momTheta = "<< momTheta <<" momPhi = "<< momPhi);
1335
1336
1337 double charge = m_particleDataTable->particle(std::abs(pdg))->charge();
1338 // since the PDT table only has abs(PID) values for the charge
1339 charge *= (pdg > 0.) ? 1. : -1.;
1340
1341 const double pTime = 0;
1342 const int status = 1 + HepMC::SIM_STATUS_THRESHOLD;
1343 const int id = HepMC::UNDEFINED_ID;
1344 // NB we are not considering the possibility that the punch-through
1345 // particle is the incoming particle having survived an interaction.
1346 ISF::ISFParticle* finalPar = new ISF::ISFParticle ( pos, mom, mass, charge, pdg, status, pTime, isfp, id);
1348
1349 // return the punch-through particle
1350 return finalPar;
1351}
Scalar phi() const
phi method
Scalar theta() const
theta method
double charge(const T &p)
Definition AtlasPID.h:997
void setNextGeoID(AtlasDetDescr::AtlasRegion geoID)
register the next AtlasDetDescr::AtlasRegion
Amg::Vector3D propagator(double theta, double phi) const
get particle through the calorimeter
const HepPDT::ParticleDataTable * m_particleDataTable
ParticleDataTable needed to get connection pdg_code <-> charge.
void setRThetaPhi(Amg::Vector3D &v, double r, double theta, double phi)
sets radius, the theta and phi angle of a vector.
constexpr int UNDEFINED_ID
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
status
Definition merge.py:16

◆ dotProduct()

std::vector< double > ISF::PunchThroughTool::dotProduct ( const std::vector< std::vector< double > > & m,
const std::vector< double > & v )
staticprivate

Definition at line 729 of file PunchThroughTool.cxx.

730{
731 std::vector<double> result;
732 result.reserve(m.size());
733 for (const auto& r : m){
734 result.push_back(std::inner_product(v.begin(), v.end(), r.begin(), 0.0));
735 }
736
737 return result;
738}
int r
Definition globals.cxx:22

◆ finalize()

StatusCode ISF::PunchThroughTool::finalize ( )
virtual

AlgTool finalize method.

Definition at line 271 of file PunchThroughTool.cxx.

272{
273 ATH_MSG_DEBUG( "[punchthrough] finalize() starting" );
274 for(auto & each : m_particles) {
275 delete each.second;
276 }
277
278 ATH_MSG_DEBUG( "[punchthrough] finalize() successful" );
279
280 return StatusCode::SUCCESS;
281}

◆ getAllParticles()

int ISF::PunchThroughTool::getAllParticles ( const ISF::ISFParticle & isfp,
ISFParticleVector & isfpCont,
CLHEP::HepRandomEngine * rndmEngine,
int pdg,
double interpEnergy,
double interpEta,
int numParticles = -1 ) const
private

create the right number of punch-through particles for the given pdg and return the number of particles which was created.

also create these particles with the right distributions (energy, theta, phi). if a second argument is given, create exactly this number of particles (also with the right energy,theta,phi distributions

Definition at line 448 of file PunchThroughTool.cxx.

449{
450
451 // get the current particle
452 PunchThroughParticle *p = m_particles.at(pdg);
453
454 // if no number of particles (=-1) was handed over as an argument
455 // -> get the number of particles from the pdf
456 if ( numParticles < 0 )
457 {
458 // prepare the function arguments for the PDFcreator class
459 std::vector<int> parameters;
460 parameters.push_back( std::round(interpEnergy) );
461 parameters.push_back( std::round(interpEta*100) );
462 // the maximum number of particles which should be produced
463 // if no maximum number is given, this is -1
464 int maxParticles = p->getMaxNumParticles();
465
466 // get the right number of punch-through particles
467 // and ensure that we do not create too many particles
468 do
469 {
470 numParticles = int( p->getNumParticlesPDF()->getRand(rndmEngine, parameters) );
471
472 // scale the number of particles if requested
473 numParticles = lround( numParticles *= p->getNumParticlesFactor() );
474 }
475 while ( (maxParticles >= 0.) && (numParticles > maxParticles) );
476 }
477
478 ATH_MSG_VERBOSE("[ punchthrough ] adding " << numParticles << " punch-through particles with pdg " << pdg);
479
480 // now create the exact number of particles which was just computed before
481 double energyRest = std::sqrt( isfp.momentum().mag2() + isfp.mass()*isfp.mass() );
482 double minEnergy = p->getMinEnergy();
483 int numCreated = 0;
484
485 for ( numCreated = 0; (numCreated < numParticles) && (energyRest > minEnergy); numCreated++ )
486 {
487 // create one particle which fullfills the right energy distribution
488 ISF::ISFParticle *par = getOneParticle(isfp, pdg, rndmEngine, interpEnergy, interpEta);
489
490 // if something went wrong
491 if (!par)
492 {
493 ATH_MSG_ERROR("[ punchthrough ] something went wrong while creating punch-through particles");
494 return 0;
495 }
496
497 // get the energy of the particle which was just created
498 const double restMass = m_particleDataTable->particle(std::abs(pdg))->mass();
499 double curEnergy = std::sqrt(par->momentum().mag2() + restMass*restMass);
500
501 // calculate the maximum energy to be available for all
502 // following punch-through particles created
503 energyRest -= curEnergy;
504
505 // add this ISFparticle to the vector
506 isfpCont.push_back( par );
507 }
508
509 // the number of particles which was created is numCreated
510 return (numCreated);
511}
#define ATH_MSG_ERROR(x)
ISF::ISFParticle * getOneParticle(const ISF::ISFParticle &isfp, int pdg, CLHEP::HepRandomEngine *rndmEngine, double interpEnergy, double interpEta) const
create exactly one punch-through particle with the given pdg and the given max energy
constexpr uint8_t maxParticles()

◆ getCorrelatedParticles()

int ISF::PunchThroughTool::getCorrelatedParticles ( const ISF::ISFParticle & isfp,
ISFParticleVector & isfpCont,
int doPdg,
int corrParticles,
CLHEP::HepRandomEngine * rndmEngine,
double interpEnergy,
double interpEta ) const
private

get the right number of particles for the given pdg while considering the correlation to an other particle type, which has already created 'corrParticles' number of particles

Definition at line 518 of file PunchThroughTool.cxx.

519{
520 // get the PunchThroughParticle class
521 PunchThroughParticle *p = m_particles.at(pdg);
522
523 const double initEnergy = std::sqrt( isfp.momentum().mag2() + isfp.mass()*isfp.mass() );
524
525 // (1.) decide if we do correlation or not
526 double rand = CLHEP::RandFlat::shoot(rndmEngine)
527 *(p->getFullCorrelationEnergy()-p->getMinCorrelationEnergy())
528 + p->getMinCorrelationEnergy();
529 if ( initEnergy < rand )
530 {
531 // here we do not do correlation
532 return getAllParticles(isfp, isfpCont, rndmEngine, pdg, interpEnergy, interpEta);
533 }
534
535 // (2.) if this point is reached, we do correlation
536 // decide which 2d correlation histogram to use
537 double *histDomains = p->getCorrelationHistDomains();
538 TH2F *hist2d = nullptr;
539 // compute the center values of the lowE and highE
540 // correlation histogram domains
541 if ( initEnergy < histDomains[1])
542 {
543 // initial energy lower than border between lowEnergy and highEnergy histogram domain
544 // --> choose lowEnergy correlation histogram
545 hist2d = p->getCorrelationLowEHist();
546 }
547 else
548 {
549 double rand = CLHEP::RandFlat::shoot(rndmEngine)*(histDomains[2]-histDomains[1])
550 + histDomains[1];
551 hist2d = ( initEnergy < rand) ? p->getCorrelationLowEHist()
552 : p->getCorrelationHighEHist();
553 }
554
555 // get the correlation 2d histogram
556
557 // now find out where on the x-axis the the bin for number of
558 // correlated particles is
559 Int_t xbin = hist2d->GetXaxis()->FindFixBin(corrParticles);
560 int numParticles = 0;
561 int maxParticles = p->getMaxNumParticles();
562 // now the distribution along the y-axis is a PDF for the number
563 // of 'pdg' particles
564 do
565 {
566 double rand = CLHEP::RandFlat::shoot(rndmEngine);
567 double sum = 0.;
568 for ( int ybin = 1; ybin <= hist2d->GetNbinsY(); ybin++ )
569 {
570 sum += hist2d->GetBinContent(xbin, ybin);
571 // check if we choose the current bin or not
572 if ( sum >= rand )
573 {
574 numParticles = ybin - 1;
575 break;
576 }
577 }
578 // scale the number of particles is requested
579 numParticles = lround( numParticles * p->getNumParticlesFactor() );
580 }
581 while ( (maxParticles >= 0.) && (numParticles > maxParticles) );
582
583 // finally create this exact number of particles
584 return getAllParticles(isfp, isfpCont, rndmEngine, pdg, interpEnergy, interpEta, numParticles);
585}
TH2F(name, title, nxbins, bins_par2, bins_par3, bins_par4, bins_par5=None, bins_par6=None, path='', **kwargs)

◆ getFloatAfterPatternInStr()

double ISF::PunchThroughTool::getFloatAfterPatternInStr ( const char * str,
const char * pattern )
private

get the floating point number in a string, after the given pattern

Definition at line 1358 of file PunchThroughTool.cxx.

1359{
1360 double num = 0.;
1361
1362 const std::string_view str( cstr);
1363 const std::string_view pattern( cpattern);
1364 const size_t pos = str.find(pattern);
1365
1366 if ( pos == std::string::npos)
1367 {
1368 ATH_MSG_WARNING("[ punchthrough ] unable to retrieve floating point number from string");
1369 return -999999999999.;
1370 }
1371 const std::string_view substring = str.substr(pos+pattern.length());
1372 std::from_chars(substring.data(), substring.data() + substring.size(), num);
1373 return num;
1374}
#define ATH_MSG_WARNING(x)

◆ getInfoMap()

std::vector< std::map< std::string, std::string > > ISF::PunchThroughTool::getInfoMap ( const std::string & mainNode,
const std::string & xmlFilePath )
private

Definition at line 793 of file PunchThroughTool.cxx.

793 {
794 std::vector<std::map<std::string, std::string>> xml_info;
795 xmlDocPtr doc = xmlParseFile( xmlFilePath.c_str() );
796
797 //check info first
798 for( xmlNodePtr nodeRoot = doc->children; nodeRoot != nullptr; nodeRoot = nodeRoot->next) {
799 if (xmlStrEqual( nodeRoot->name, BAD_CAST mainNode.c_str() )) {
800 for( xmlNodePtr nodeRootChild = nodeRoot->children; nodeRootChild != nullptr; nodeRootChild = nodeRootChild->next ) {
801 if (xmlStrEqual( nodeRootChild->name, BAD_CAST "info" )) {
802 if (nodeRootChild->children != NULL) {
803 for( xmlNodePtr infoNode = nodeRootChild->children; infoNode != nullptr; infoNode = infoNode->next) {
804 if(xmlStrEqual( infoNode->name, BAD_CAST "item" )){
805 std::map<std::string, std::string> xml_info_item;
806 xml_info_item.insert({ "name", (const char*) xmlGetProp( infoNode, BAD_CAST "name" ) });
807 xml_info_item.insert({ "etaMins", (const char*) xmlGetProp( infoNode, BAD_CAST "etaMins" ) });
808 xml_info_item.insert({ "etaMaxs", (const char*) xmlGetProp( infoNode, BAD_CAST "etaMaxs" ) });
809 xml_info_item.insert({ "pidStr", (const char*) xmlGetProp( infoNode, BAD_CAST "pidStr" ) });
810 xml_info.push_back(xml_info_item);
811 }
812 }
813 }
814 }
815 }
816 }
817 }
818 return xml_info;
819}

◆ getOneParticle()

ISF::ISFParticle * ISF::PunchThroughTool::getOneParticle ( const ISF::ISFParticle & isfp,
int pdg,
CLHEP::HepRandomEngine * rndmEngine,
double interpEnergy,
double interpEta ) const
private

create exactly one punch-through particle with the given pdg and the given max energy

Definition at line 592 of file PunchThroughTool.cxx.

593{
594 // get a local copy of the needed punch-through particle class
595 PunchThroughParticle *p = m_particles.at(pdg);
596
597 // (0.) get the pca / cdf group based on pdgId and eta, eta times 100, e.g eta -4 to 4 is from eta -400 to 400
598 int pcaCdfIterator = passedParamIterator(pdg, interpEta*100, m_xml_info_pca); //pca and cdf info should be of same size
599
600 ATH_MSG_DEBUG("[ punchthrough ] passedPCAIterator ==> pcaCdfIterator = "<< pcaCdfIterator <<" , pdg = "<< pdg <<" , interpEnergy = "<< interpEnergy <<" MeV, interpEta(*100) = "<< interpEta*100);
601
602 // (1.) decide if we create a particle or an anti-particle
603 int anti = 1;
604 if ( p->getdoAnti() )
605 {
606 // get a random-value
607 double rand = CLHEP::RandFlat::shoot(rndmEngine);
608 // 50/50 chance to be a particle or its anti-particle
609 if (rand > 0.5) anti = -1;
610 }
611
612 // (2.) get the right punch-through distributions
613 // prepare the function arguments for the PDFcreator class
614 std::vector<int> parInitEnergyEta;
615 parInitEnergyEta.push_back( std::round(interpEnergy) );
616 parInitEnergyEta.push_back( std::round(interpEta*100) );
617
618 //initialise variables to store punch through particle kinematics
619 double energy = 0.;
620 double deltaTheta = 0.;
621 double deltaPhi = 0.;
622 double momDeltaTheta = 0.;
623 double momDeltaPhi = 0.;
624
625 double principal_component_0 = 0.;
626 double principal_component_1 = 0.;
627 double principal_component_2 = 0.;
628 double principal_component_3 = 0.;
629 double principal_component_4 = 0.;
630 std::vector<double> transformed_variables;
631
632
633 principal_component_0 = p->getPCA0PDF()->getRand(rndmEngine, parInitEnergyEta);
634 principal_component_1 = p->getPCA1PDF()->getRand(rndmEngine, parInitEnergyEta);
635 principal_component_2 = p->getPCA2PDF()->getRand(rndmEngine, parInitEnergyEta);
636 principal_component_3 = p->getPCA3PDF()->getRand(rndmEngine, parInitEnergyEta);
637 principal_component_4 = p->getPCA4PDF()->getRand(rndmEngine, parInitEnergyEta);
638
639 ATH_MSG_DEBUG("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 );
640
641 std::vector<double> principal_components {
642 principal_component_0,
643 principal_component_1,
644 principal_component_2,
645 principal_component_3,
646 principal_component_4
647 };
648
649 transformed_variables = inversePCA(pcaCdfIterator,principal_components);
650
651 energy = inverseCdfTransform(transformed_variables.at(0), m_variable0_inverse_cdf[pcaCdfIterator]);
652 deltaTheta = inverseCdfTransform(transformed_variables.at(1), m_variable1_inverse_cdf[pcaCdfIterator]);
653 deltaPhi = inverseCdfTransform(transformed_variables.at(2), m_variable2_inverse_cdf[pcaCdfIterator]);
654 momDeltaTheta = inverseCdfTransform(transformed_variables.at(3), m_variable3_inverse_cdf[pcaCdfIterator]);
655 momDeltaPhi = inverseCdfTransform(transformed_variables.at(4), m_variable4_inverse_cdf[pcaCdfIterator]);
656
657 ATH_MSG_DEBUG("Transformed punch through kinematics: energy = "<< energy <<" MeV deltaTheta = "<< deltaTheta <<" deltaPhi = "<< deltaPhi <<" momDeltaTheta = "<< momDeltaTheta <<" momDeltaPhi = "<< momDeltaPhi );
658
659 energy *= p->getEnergyFactor(); // scale the energy if requested
660 if (energy < p->getMinEnergy()) {
661 energy = p->getMinEnergy() + 10;
662 }
663
664
665 // (2.2) get the particles delta theta relative to the incoming particle
666 double theta = 0;
667 // loop to keep theta within range [0,PI]
668 do
669 {
670 // decide if delta positive/negative
671 deltaTheta *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
672 // calculate the exact theta value of the later created
673 // punch-through particle
674 theta = isfp.position().theta() + deltaTheta*p->getPosAngleFactor();
675
676 }
677 while ( (theta > M_PI) || (theta < 0.) );
678 // (2.3) get the particle's delta phi relative to the incoming particle
679
680 deltaPhi *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
681
682 // keep phi within range [-PI,PI]
683 double phi = isfp.position().phi() + deltaPhi*p->getPosAngleFactor();
684 while ( std::fabs(phi) > 2*M_PI) phi /= 2.;
685 while (phi > M_PI) phi -= 2*M_PI;
686 while (phi < -M_PI) phi += 2*M_PI;
687
688 // (2.4) get the particle momentum delta theta, relative to its position
689 //
690 // loop to keep momTheta within range [0,PI]
691
692 double momTheta = 0.;
693 do
694 {
695 // decide if delta positive/negative
696 momDeltaTheta *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
697 // calculate the exact momentum theta value of the later created
698 // punch-through particle
699 momTheta = theta + momDeltaTheta*p->getMomAngleFactor();
700
701 }
702 while ( (momTheta > M_PI) || (momTheta < 0.) );
703
704 // (2.5) get the particle momentum delta phi, relative to its position
705
706 momDeltaPhi *= ( CLHEP::RandFlat::shoot(rndmEngine) > 0.5 ) ? 1. : -1.;
707
708 double momPhi = phi + momDeltaPhi*p->getMomAngleFactor();
709 // keep momPhi within range [-PI,PI]
710 while ( std::fabs(momPhi) > 2*M_PI) momPhi /= 2.;
711 while (momPhi > M_PI) momPhi -= 2*M_PI;
712 while (momPhi < -M_PI) momPhi += 2*M_PI;
713
714 // (**) finally create the punch-through particle as a ISFParticle
715
716 ATH_MSG_DEBUG("createExitPs input parameters: doAnti? = "<< pdg*anti <<" energy = "<< energy <<" theta = "<< theta <<" phi = "<< phi <<" momTheta = "<< momTheta << " momPhi " << momPhi );
717
718
719 ISF::ISFParticle *par = createExitPs( isfp, pdg*anti, energy, theta, phi, momTheta, momPhi);
720
721 return par;
722}
#define M_PI
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
std::vector< double > inversePCA(int pcaCdfIterator, std::vector< double > &variables) const
std::vector< std::map< double, double > > m_variable1_inverse_cdf
static double inverseCdfTransform(double variable, const std::map< double, double > &inverse_cdf_map)
std::vector< std::map< double, double > > m_variable3_inverse_cdf
std::vector< std::map< double, double > > m_variable2_inverse_cdf
std::vector< std::map< double, double > > m_variable0_inverse_cdf
(vector of map) for CDF mappings
std::vector< std::map< double, double > > m_variable4_inverse_cdf
ISF::ISFParticle * createExitPs(const ISF::ISFParticle &isfp, int PDGcode, double energy, double theta, double phi, double momTheta, double momPhi) const
create a ISF Particle state at the MS entrace containing a particle with the given properties
int passedParamIterator(int pid, double eta, const std::vector< std::map< std::string, std::string > > &mapvect) const
std::vector< std::map< std::string, std::string > > m_xml_info_pca
infoMaps

◆ getVariableCDFmappings()

std::map< double, double > ISF::PunchThroughTool::getVariableCDFmappings ( xmlNodePtr & nodeParent)
staticprivate

Definition at line 944 of file PunchThroughTool.cxx.

944 {
945
946 std::map<double, double> mappings;
947
948 for( xmlNodePtr node = nodeParent->children; node != nullptr; node = node->next ) {
949 //Get min and max values that we normalise values to
950 if (xmlStrEqual( node->name, BAD_CAST "CDFmap" )) {
951 double ref = atof( (const char*) xmlGetProp( node, BAD_CAST "ref" ) );
952 double quant = atof( (const char*) xmlGetProp( node, BAD_CAST "quant" ) );
953
954 mappings.insert(std::pair<double, double>(ref, quant) );
955
956 }
957 }
958
959 return mappings;
960}
const boost::regex ref(r_ef)
static int quant(double min, double max, unsigned nSteps, double val)
double atof(std::string_view str)
Converts a string into a double / float.

◆ initialize()

StatusCode ISF::PunchThroughTool::initialize ( )
virtual

AlgTool initialize method.

Definition at line 74 of file PunchThroughTool.cxx.

75{
76 ATH_MSG_DEBUG( "initialize()" );
77
78 // initialise punch through classifier
79 if (m_punchThroughClassifier.retrieve().isFailure() )
80 {
81 ATH_MSG_ERROR (m_punchThroughClassifier.propertyName() << ": Failed to retrieve tool " << m_punchThroughClassifier.type());
82 return StatusCode::FAILURE;
83 }
84
85 // resolving lookuptable file
86 std::string resolvedFileName = PathResolverFindCalibFile (m_filenameLookupTable);
87 if (resolvedFileName.empty()) {
88 ATH_MSG_ERROR( "[ punchthrough ] Parametrisation file '" << m_filenameLookupTable << "' not found" );
89 return StatusCode::FAILURE;
90 }
91 ATH_MSG_INFO( "[ punchthrough ] Parametrisation file found: " << resolvedFileName );
92
93 // open the LookupTable file
94 m_fileLookupTable = new TFile( resolvedFileName.c_str(), "READ");
95 if (!m_fileLookupTable) {
96 ATH_MSG_WARNING("[ punchthrough ] unable to open the lookup-table for the punch-through simulation (file does not exist)");
97 return StatusCode::FAILURE;
98 }
99
100 if (!m_fileLookupTable->IsOpen()) {
101 ATH_MSG_WARNING("[ punchthrough ] unable to open the lookup-table for the punch-through simulation (wrong or empty file?)");
102 return StatusCode::FAILURE;
103 }
104
105 //retrieve inverse CDF config file
107 {
108 ATH_MSG_WARNING("[ punchthrough ] unable to open or read the inverse CDF config");
109 return StatusCode::FAILURE;
110 }
111
112 //retrieve inverse PCA config file
114 {
115 ATH_MSG_WARNING("[ punchthrough ] unable to open or read the inverse PCA config");
116 return StatusCode::FAILURE;
117 }
118
119 //check first the size of infoMap for both PCA and CDF, they should be equal
120 if (!(m_xml_info_pca.size() == m_xml_info_cdf.size()))
121 {
122 ATH_MSG_WARNING("[ punchthrough ] size of infoMap for PCA and CDF differs! Something is wrong with input xml files.");
123 return StatusCode::FAILURE;
124 }
125
126 // retrieve the ParticleProperties handle
127 ATH_CHECK( m_particlePropSvc.retrieve() );
128
129 // and the particle data table
132 {
133 ATH_MSG_FATAL( " [ punchthrough ] Could not get ParticleDataTable! Cannot associate pdg code with charge! Abort. " );
134 return StatusCode::FAILURE;
135 }
136
137 // Geometry identifier service
138 if ( !m_geoIDSvc.empty() && m_geoIDSvc.retrieve().isFailure())
139 {
140 ATH_MSG_FATAL ( "[ punchthrough ] Could not retrieve GeometryIdentifier Service. Abort");
141 return StatusCode::FAILURE;
142 }
143
144 //envelope definition service
145 if (m_envDefSvc.retrieve().isFailure() )
146 {
147 ATH_MSG_ERROR( "[ punchthrough ] Could not retrieve " << m_envDefSvc );
148 return StatusCode::FAILURE;
149 }
150
151 //--------------------------------------------------------------------------------
152 // register all the punch-through particles which will be simulated
153 for ( unsigned int num = 0; num < m_punchThroughParticles.size(); num++ )
154 {
155 const int pdg = m_punchThroughParticles[num];
156 // if no information is given on the creation of anti-particles -> do not simulate anti-particles
157 const bool doAnti = ( num < m_doAntiParticles.size() ) ? m_doAntiParticles[num] : false;
158 // if no information is given on the minimum energy -> take 50. MeV as default
159 const double minEnergy = ( num < m_minEnergy.size() ) ? m_minEnergy[num] : 50.;
160 // if no information is given on the maximum number of punch-through particles -> take -1 as default
161 const int maxNum = ( num < m_minEnergy.size() ) ? m_maxNumParticles[num] : -1;
162 // if no information is given on the scale factor for the number of particles -> take 1. as defaulft
163 const double numFactor = ( num < m_numParticlesFactor.size() ) ? m_numParticlesFactor[num] : 1.;
164 // if no information is given on the position angle factor -> take 1.
165 const double posAngleFactor = ( num < m_posAngleFactor.size() ) ? m_posAngleFactor[num] : 1.;
166 // if no information is given on the momentum angle factor -> take 1.
167 const double momAngleFactor = ( num < m_momAngleFactor.size() ) ? m_momAngleFactor[num] : 1.;
168 // if no information is given on the scale factor for the energy -> take 1. as default
169 const double energyFactor = ( num < m_energyFactor.size() ) ? m_energyFactor[num] : 1.;
170
171 // register the particle
172 ATH_MSG_VERBOSE("[ punchthrough ] registering punch-through particle type with pdg = " << pdg );
173 if ( registerParticle( pdg, doAnti, minEnergy, maxNum, numFactor, energyFactor, posAngleFactor, momAngleFactor )
174 != StatusCode::SUCCESS)
175 {
176 ATH_MSG_ERROR("[ punchthrough ] unable to register punch-through particle type with pdg = " << pdg);
177 }
178 }
179
180 // TODO: implement punch-through parameters for different m_pdgInitiators
181 // currently m_pdgInitiators is only used to filter out particles
182
183 // check if more correlations were given than particle types were registered
184 unsigned int numCorrelations = m_correlatedParticle.size();
185 if ( numCorrelations > m_punchThroughParticles.size() )
186 {
187 ATH_MSG_WARNING("[ punchthrough ] more punch-through particle correlations are given, than punch-through particle types are registered (skipping the last ones)");
188 numCorrelations = m_punchThroughParticles.size();
189 }
190
191 // now register correlation between particles
192 for ( unsigned int num = 0; num < numCorrelations; num++ )
193 {
194 const int pdg1 = m_punchThroughParticles[num];
195 const int pdg2 = m_correlatedParticle[num];
196 const double fullCorrEnergy = ( num < m_fullCorrEnergy.size() ) ? m_fullCorrEnergy[num] : 0.;
197 const double minCorrEnergy = ( num < m_minCorrEnergy.size() ) ? m_minCorrEnergy[num] : 0.;
198
199 // if correlatedParticle==0 is given -> no correlation
200 if ( ! pdg2) continue;
201 // register it
202 if ( registerCorrelation(pdg1, pdg2, minCorrEnergy, fullCorrEnergy) != StatusCode::SUCCESS )
203 {
204 ATH_MSG_ERROR("[ punchthrough ] unable to register punch-through particle correlation for pdg1=" << pdg1 << " pdg2=" << pdg2 );
205 }
206 }
207
208 // get the calo-MS border coordinates. Look at calo and MS geometry definitions, if same R and Z -> boundary surface
209
210 const RZPairVector* rzMS = &(m_envDefSvc->getMuonRZBoundary());
211 const RZPairVector* rzCalo = &(m_envDefSvc->getCaloRZBoundary());
212
213 bool found1, found2;
214 found1=false; found2=false;
215
216 for ( size_t i=0; i<rzCalo->size();++i)
217 {
218 const double r_tempCalo = rzCalo->at(i).first;
219 const double z_tempCalo = rzCalo->at(i).second;
220
221 if (r_tempCalo> m_beamPipe)
222 {
223 for ( size_t j=0; j<rzMS->size();++j)
224 {
225 const double r_tempMS =rzMS->at(j).first;
226 const double z_tempMS =rzMS->at(j).second;
227
228 if (r_tempCalo==r_tempMS && z_tempCalo==z_tempMS && found1==false )
229 {
230 m_R1=r_tempMS;
231 m_z1=std::fabs(z_tempMS);
232 found1=true;
233 continue;
234 }
235 else if (r_tempCalo==r_tempMS && z_tempCalo==z_tempMS && r_tempCalo!=m_R1 && std::fabs(z_tempCalo)!=m_z1)
236 {
237 m_R2=r_tempMS;
238 m_z2=std::fabs(z_tempMS);
239 found2=true;
240 }
241 }
242
243 if (found1==true && found2==true) break;
244 }
245 }
246
247 //in case geometry description changes
248 if (found1 == false) ATH_MSG_ERROR ("first coordinate of calo-MS border not found");
249 if (found2 == false) ATH_MSG_ERROR ("second coordinate of calo-MS border not found; first one is: R1 ="<<m_R1<<" z1 ="<<m_z1);
250
251 //now order the found values
252 double r_temp, z_temp;
253 if (m_R1>m_R2) { r_temp=m_R1; m_R1=m_R2; m_R2=r_temp; } //m_R1 - smaller one
254 if (m_z1<m_z2) { z_temp=m_z1; m_z1=m_z2; m_z2=z_temp; } //m_z1 - bigger one
255
256 if (m_R1==m_R2 || m_z1==m_z2) ATH_MSG_ERROR ("[punch-though] Bug in propagation calculation! R1="<<m_R1<<" R2 = "<<m_R2<<" z1="<<m_z1<<" z2= "<<m_z2 );
257 else ATH_MSG_DEBUG ("calo-MS boundary coordinates: R1="<<m_R1<<" R2 = "<<m_R2<<" z1="<<m_z1<<" z2= "<<m_z2);
258
259 // close the file with the lookuptable
260 m_fileLookupTable->Close();
261
262 ATH_MSG_INFO( "punchthrough initialization is successful" );
263 return StatusCode::SUCCESS;
264}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
std::vector< RZPair > RZPairVector
Definition RZPair.h:18
StringProperty m_filenameInverseCDF
IntegerArrayProperty m_correlatedParticle
DoubleArrayProperty m_minCorrEnergy
ServiceHandle< IPartPropSvc > m_particlePropSvc
StringProperty m_filenameLookupTable
Properties.
StringProperty m_filenameInversePCA
std::vector< std::map< std::string, std::string > > m_xml_info_cdf
BooleanArrayProperty m_doAntiParticles
DoubleArrayProperty m_energyFactor
StatusCode registerCorrelation(int pdgID1, int pdgID2, double minCorrEnergy=0., double fullCorrEnergy=0.)
register a correlation for the two given types of punch-through particles with a given energy thresho...
DoubleProperty m_beamPipe
beam pipe radius
DoubleArrayProperty m_momAngleFactor
DoubleArrayProperty m_fullCorrEnergy
StatusCode registerParticle(int pdgID, bool doAntiparticle=false, double minEnergy=0., int maxNumParticles=-1, double numParticlesFactor=1., double energyFactor=1., double posAngleFactor=1., double momAngleFactor=1.)
registers a type of punch-through particles which will be simulated
DoubleArrayProperty m_numParticlesFactor
StatusCode initializeInverseCDF(const std::string &quantileTransformerConfigFile)
DoubleArrayProperty m_minEnergy
IntegerArrayProperty m_maxNumParticles
double m_R1
calo-MS borders
StatusCode initializeInversePCA(const std::string &inversePCAConfigFile)
TFile * m_fileLookupTable
ROOT objects.
ServiceHandle< IEnvelopeDefSvc > m_envDefSvc
DoubleArrayProperty m_posAngleFactor
IntegerArrayProperty m_punchThroughParticles

◆ initializeInverseCDF()

StatusCode ISF::PunchThroughTool::initializeInverseCDF ( const std::string & quantileTransformerConfigFile)
private

Definition at line 885 of file PunchThroughTool.cxx.

885 {
886 std::map<double, double> variable0_inverse_cdf_row;
887 std::map<double, double> variable1_inverse_cdf_row;
888 std::map<double, double> variable2_inverse_cdf_row;
889 std::map<double, double> variable3_inverse_cdf_row;
890 std::map<double, double> variable4_inverse_cdf_row;
891
892 //parse xml that contains config for inverse CDF for each of punch through particle kinematics
893
894 xmlDocPtr doc = xmlParseFile( inverseCdfConfigFile.c_str() );
895
896 ATH_MSG_INFO( "[ punchthrough ] Loading inverse CDF: " << inverseCdfConfigFile);
897
898 //check info first
899 m_xml_info_cdf = getInfoMap("CDFMappings",inverseCdfConfigFile);
900
901 //do the saving
902 for (unsigned int i = 0; i < m_xml_info_cdf.size(); i++) {
903 ATH_MSG_DEBUG( "[ punchthrough ] m_xml_info_cdf[" << i << "].at('name') = " << m_xml_info_cdf[i].at("name"));
904
905 for( xmlNodePtr nodeRoot = doc->children; nodeRoot != nullptr; nodeRoot = nodeRoot->next) {
906 if (xmlStrEqual( nodeRoot->name, BAD_CAST "CDFMappings" )) {
907 for( xmlNodePtr typeMappings = nodeRoot->children; typeMappings != nullptr; typeMappings = typeMappings->next ) {
908 if (xmlStrEqual( typeMappings->name, BAD_CAST m_xml_info_cdf[i].at("name").c_str() )) {
909 if (typeMappings->children != NULL) {
910 for( xmlNodePtr nodeMappings = typeMappings->children; nodeMappings != nullptr; nodeMappings = nodeMappings->next) {
911
912 if (xmlStrEqual( nodeMappings->name, BAD_CAST "variable0" )) {
913 variable0_inverse_cdf_row = getVariableCDFmappings(nodeMappings);
914 }
915 else if (xmlStrEqual( nodeMappings->name, BAD_CAST "variable1" )) {
916 variable1_inverse_cdf_row = getVariableCDFmappings(nodeMappings);
917 }
918 else if (xmlStrEqual( nodeMappings->name, BAD_CAST "variable2" )) {
919 variable2_inverse_cdf_row = getVariableCDFmappings(nodeMappings);
920 }
921 else if (xmlStrEqual( nodeMappings->name, BAD_CAST "variable3" )) {
922 variable3_inverse_cdf_row = getVariableCDFmappings(nodeMappings);
923 }
924 else if (xmlStrEqual( nodeMappings->name, BAD_CAST "variable4" )) {
925 variable4_inverse_cdf_row = getVariableCDFmappings(nodeMappings);
926 }
927 }
928
929 }
930 }
931 }
932 }
933 }
934 m_variable0_inverse_cdf.push_back(variable0_inverse_cdf_row);
935 m_variable1_inverse_cdf.push_back(variable1_inverse_cdf_row);
936 m_variable2_inverse_cdf.push_back(variable2_inverse_cdf_row);
937 m_variable3_inverse_cdf.push_back(variable3_inverse_cdf_row);
938 m_variable4_inverse_cdf.push_back(variable4_inverse_cdf_row);
939 }
940
941 return StatusCode::SUCCESS;
942}
std::vector< std::map< std::string, std::string > > getInfoMap(const std::string &mainNode, const std::string &xmlFilePath)
static std::map< double, double > getVariableCDFmappings(xmlNodePtr &nodeParent)

◆ initializeInversePCA()

StatusCode ISF::PunchThroughTool::initializeInversePCA ( const std::string & inversePCAConfigFile)
private

Definition at line 830 of file PunchThroughTool.cxx.

830 {
831
832 xmlDocPtr doc = xmlParseFile( inversePCAConfigFile.c_str() );
833
834 ATH_MSG_INFO( "[ punchthrough ] Loading inversePCA: " << inversePCAConfigFile);
835
836 //check info first
837 m_xml_info_pca = getInfoMap("PCAinverse",inversePCAConfigFile);
838
839 //do the saving
840 for (unsigned int i = 0; i < m_xml_info_pca.size(); i++) {
841 std::vector<std::vector<double>> PCA_matrix;
842 ATH_MSG_DEBUG( "[ punchthrough ] m_xml_info_pca[" << i << "].at('name') = " << m_xml_info_pca[i].at("name"));
843
844 for( xmlNodePtr nodeRoot = doc->children; nodeRoot != nullptr; nodeRoot = nodeRoot->next) {
845 if (xmlStrEqual( nodeRoot->name, BAD_CAST "PCAinverse" )) {
846 for( xmlNodePtr nodePCAinverse = nodeRoot->children; nodePCAinverse != nullptr; nodePCAinverse = nodePCAinverse->next ) {
847
848 if (xmlStrEqual( nodePCAinverse->name, BAD_CAST m_xml_info_pca[i].at("name").c_str() )) {
849 if (nodePCAinverse->children != NULL) {
850 for( xmlNodePtr pcaNode = nodePCAinverse->children; pcaNode != nullptr; pcaNode = pcaNode->next) {
851
852 if (xmlStrEqual( pcaNode->name, BAD_CAST "PCAmatrix" )) {
853 std::vector<double> PCA_matrix_row;
854 PCA_matrix_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "comp_0" ) ) );
855 PCA_matrix_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "comp_1" ) ) );
856 PCA_matrix_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "comp_2" ) ) );
857 PCA_matrix_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "comp_3" ) ) );
858 PCA_matrix_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "comp_4" ) ) );
859 PCA_matrix.push_back(PCA_matrix_row);
860 }
861 else if (xmlStrEqual( pcaNode->name, BAD_CAST "PCAmeans" )) {
862 std::vector<double> PCA_means_row;
863 PCA_means_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "mean_0" ) ) );
864 PCA_means_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "mean_1" ) ) );
865 PCA_means_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "mean_2" ) ) );
866 PCA_means_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "mean_3" ) ) );
867 PCA_means_row.push_back( atof( (const char*) xmlGetProp( pcaNode, BAD_CAST "mean_4" ) ) );
868 m_PCA_means.push_back(PCA_means_row);
869 }
870
871 }
872
873 }
874 }
875
876 }
877 }
878 }
879 m_inverse_PCA_matrix.push_back(PCA_matrix);
880 }
881
882 return StatusCode::SUCCESS;
883}
std::vector< std::vector< std::vector< double > > > m_inverse_PCA_matrix
pca vectors
std::vector< std::vector< double > > m_PCA_means

◆ interpolateEnergy()

double ISF::PunchThroughTool::interpolateEnergy ( const double & energy,
CLHEP::HepRandomEngine * rndmEngine ) const
private

Definition at line 977 of file PunchThroughTool.cxx.

977 {
978
979 ATH_MSG_DEBUG("[ punchthrough ] interpolating incoming energy: " << energy);
980
981 std::string energyPointsString;
982 for (auto element:m_energyPoints){
983 energyPointsString += std::to_string(element) + " ";
984 }
985
986 ATH_MSG_DEBUG("[ punchthrough ] available energy points: " << energyPointsString);
987
988 auto const upperEnergy = std::upper_bound(m_energyPoints.begin(), m_energyPoints.end(), energy);
989
990 if(upperEnergy == m_etaPoints.end()){ //if no energy greater than input energy, choose greatest energy
991 ATH_MSG_DEBUG("[ punchthrough ] incoming energy > largest energy point, returning greatest energy point: " << m_energyPoints.back());
992 return m_energyPoints.back();
993 }
994 else if(upperEnergy == m_etaPoints.begin()){ //if smallest energy greater than input energy, choose smallest energy
995 ATH_MSG_DEBUG("[ punchthrough ] incoming energy < smallest energy point, returning smallest energy point: " << *upperEnergy);
996 return *upperEnergy;
997 }
998
999 ATH_MSG_DEBUG("[ punchthrough ] energy points upper_bound: "<< *upperEnergy);
1000
1001 double randomShoot = CLHEP::RandFlat::shoot(rndmEngine);
1002
1003 ATH_MSG_DEBUG("[ punchthrough ] Shooting random number: "<< randomShoot);
1004
1005 double midPoint = *std::prev(upperEnergy)*M_SQRT2;
1006
1007 if(energy < midPoint){ //if energy smaller than mid point in log(energy)
1008
1009 double distance = std::abs(energy - *std::prev(upperEnergy))/((midPoint) - *std::prev(upperEnergy));
1010
1011 ATH_MSG_DEBUG( "[ punchthrough ] incoming energy is closest to prev(upper_bound) in log(energy), distance: " << distance );
1012
1013 if(randomShoot < distance){
1014 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot < distance, returning upper_bound " << *upperEnergy );
1015 return *upperEnergy;
1016 }
1017 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot > distance, returning prev(upper_bound) " << *std::prev(upperEnergy) );
1018
1019 return *std::prev(upperEnergy);
1020 }
1021 else if(energy > midPoint){ //if energy greater than mid point in log(energy)
1022
1023 double distance = std::abs(energy - *upperEnergy)/((*upperEnergy - midPoint));
1024
1025 ATH_MSG_DEBUG( "[ punchthrough ] incoming energy is closest to upper_bound in log(energy), distance: " << distance );
1026
1027 if(randomShoot < distance){
1028 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot < distance, returning prev(upper_bound) " << *std::prev(upperEnergy) );
1029 return *std::prev(upperEnergy);
1030 }
1031 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot > distance, returning upper_bound " << *upperEnergy );
1032 return *upperEnergy;
1033 }
1034
1035 return *upperEnergy;
1036}
std::vector< double > m_energyPoints
energy and eta points in param
std::vector< double > m_etaPoints
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space

◆ interpolateEta()

double ISF::PunchThroughTool::interpolateEta ( const double & eta,
CLHEP::HepRandomEngine * rndmEngine ) const
private

Definition at line 1038 of file PunchThroughTool.cxx.

1038 {
1039
1040 double absEta = std::abs(eta);
1041
1042 ATH_MSG_DEBUG("[ punchthrough ] interpolating incoming abs(eta): " << absEta);
1043
1044 std::string etaPointsString;
1045 for (auto element:m_etaPoints){
1046 etaPointsString += std::to_string(element) + " ";
1047 }
1048
1049 ATH_MSG_DEBUG("[ punchthrough ] available eta points: " << etaPointsString);
1050
1051 auto const upperEta = std::upper_bound(m_etaPoints.begin(), m_etaPoints.end(), absEta);
1052
1053 if(upperEta == m_etaPoints.end()){
1054 ATH_MSG_DEBUG("[ punchthrough ] incoming abs(eta) > largest eta point, returning greatest eta point: " << m_etaPoints.back());
1055 return m_etaPoints.back();
1056 }
1057
1058
1059 ATH_MSG_DEBUG("[ punchthrough ] eta points upper_bound: "<< *upperEta);
1060
1061 double randomShoot = CLHEP::RandFlat::shoot(rndmEngine);
1062
1063 ATH_MSG_DEBUG("[ punchthrough ] Shooting random number: "<< randomShoot);
1064
1065 if(std::abs(absEta - *upperEta) < std::abs(absEta - *std::prev(upperEta))){
1066
1067 double distance = std::abs(absEta - *upperEta)/((*upperEta - *std::prev(upperEta))/2);
1068
1069 ATH_MSG_DEBUG( "[ punchthrough ] abs(eta) is closer to eta points upper_bound, distance: " << distance );
1070
1071 if(randomShoot > distance){
1072 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot > distance, returning upper_bound " << *upperEta );
1073 return *upperEta;
1074 }
1075
1076 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot < distance, returning prev(upper_bound) " << *std::prev(upperEta) );
1077
1078 return *std::prev(upperEta);
1079 }
1080 else if(std::abs(absEta - *std::prev(upperEta)) < std::abs(absEta - *upperEta)){
1081
1082 if(std::prev(upperEta) == m_etaPoints.begin()){
1083 ATH_MSG_DEBUG( "[ punchthrough ] prev of upper bound is begin, returning that: " << *std::prev(upperEta) );
1084 return *std::prev(upperEta);
1085 }
1086
1087 double distance = std::abs(absEta - *std::prev(upperEta))/((*std::prev(upperEta) - *std::prev(std::prev(upperEta)))/2);
1088
1089 ATH_MSG_DEBUG( "[ punchthrough ] abs(eta) is closer to eta points prev(upper_bound), distance: " << distance );
1090
1091 if(randomShoot > distance){
1092 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot > distance, returning prev(prev(upper_bound)) " << *std::prev(std::prev(upperEta)) );
1093
1094 return *std::prev(std::prev(upperEta));
1095 }
1096 ATH_MSG_DEBUG( "[ punchthrough ] randomShoot < distance, returning prev(upper_bound) " << *std::prev(upperEta) );
1097
1098 return *std::prev(upperEta);
1099 }
1100
1101 return *std::prev(upperEta);
1102}
Scalar eta() const
pseudorapidity method
bool absEta(const xAOD::TauJet &tau, float &out)

◆ inverseCdfTransform()

double ISF::PunchThroughTool::inverseCdfTransform ( double variable,
const std::map< double, double > & inverse_cdf_map )
staticprivate

Definition at line 962 of file PunchThroughTool.cxx.

962 {
963
964 double norm_cdf = normal_cdf(variable);
965
966 auto upper = inverse_cdf_map.upper_bound(norm_cdf);
967 auto lower = upper--;
968
969 double m = (upper->second - lower->second)/(upper->first - lower->first);
970 double c = lower->second - m * lower->first;
971 double transformed = m * norm_cdf + c;
972
973 return transformed;
974
975}
int upper(int c)
static double normal_cdf(double x)

◆ inversePCA()

std::vector< double > ISF::PunchThroughTool::inversePCA ( int pcaCdfIterator,
std::vector< double > & variables ) const
private

Definition at line 821 of file PunchThroughTool.cxx.

822{
823 std::vector<double> transformed_variables = dotProduct(m_inverse_PCA_matrix[pcaCdfIterator], variables);
824
825 std::transform (transformed_variables.begin(), transformed_variables.end(), m_PCA_means[pcaCdfIterator].begin(), transformed_variables.begin(), std::plus<double>()); // + means
826
827 return transformed_variables;
828}
static std::vector< double > dotProduct(const std::vector< std::vector< double > > &m, const std::vector< double > &v)

◆ normal_cdf()

double ISF::PunchThroughTool::normal_cdf ( double x)
staticprivate

Definition at line 724 of file PunchThroughTool.cxx.

724 {
725
726 return 0.5 * TMath::Erfc(-x * M_SQRT1_2);
727}
#define x

◆ passedParamIterator()

int ISF::PunchThroughTool::passedParamIterator ( int pid,
double eta,
const std::vector< std::map< std::string, std::string > > & mapvect ) const
private

Definition at line 764 of file PunchThroughTool.cxx.

765{
766 //convert the pid to absolute value and string for query
767 int pidStrSingle = std::abs(pid);
768 //STEP 1
769 //filter items matching pid first
770
771 for (unsigned int i = 0; i < mapvect.size(); i++){
772 const std::string &pidStr = mapvect[i].at("pidStr");
773 auto v = str_to_list<int>(pidStr);
774 if(std::find(v.begin(), v.end(),pidStrSingle)==v.end()) continue;
775 const std::string &etaMinsStr = mapvect[i].at("etaMins");
776 const std::string &etaMaxsStr = mapvect[i].at("etaMaxs");
777 std::vector<double> etaMinsVect = str_to_list<double>(etaMinsStr);
778 std::vector<double> etaMaxsVect = str_to_list<double>(etaMaxsStr);
779 assert(etaMaxsVect.size() == etaMinsVect.size());
780 for (unsigned int j = 0; j < etaMinsVect.size(); j++){ // assume size etaMinsVect == etaMaxsVect
781 double etaMinToCompare = etaMinsVect[j];
782 double etaMaxToCompare = etaMaxsVect[j];
783 if((eta >= etaMinToCompare) && (eta < etaMaxToCompare)){
784 //PASS CONDITION
785 //then choose the passing one and note it's iterator
786 return (i); //in case more than 1 match (ambiguous case)
787 }
788 }
789 }
790 return 0;
791}
std::vector< T > str_to_list(const std::string_view str)

◆ propagator()

Amg::Vector3D ISF::PunchThroughTool::propagator ( double theta,
double phi ) const
private

get particle through the calorimeter

Definition at line 1376 of file PunchThroughTool.cxx.

1377{
1378 // phi, theta - direction of the punch-through particle coming into calo
1379 //particle propagates inside the calorimeter along the straight line
1380 //coordinates of this particles when exiting the calo (on calo-MS boundary)
1381
1382 double x, y, z, r;
1383
1384 // cylinders border angles
1385 const double theta1 = atan (m_R1/m_z1);
1386 const double theta2 = atan (m_R1/m_z2);
1387 const double theta3 = atan (m_R2/m_z2);
1388 //where is the particle
1389
1390 if (theta >= 0 && theta < theta1)
1391 {
1392 z = m_z1;
1393 r = std::fabs (m_z1*tan(theta));
1394 }
1395 else if (theta >= theta1 && theta < theta2)
1396 {
1397 z = m_R1/tan(theta);
1398 r = m_R1;
1399 }
1400 else if (theta >= theta2 && theta < theta3)
1401 {
1402 z = m_z2;
1403 r = std::fabs(m_z2*tan(theta));;
1404 }
1405 else if (theta >= theta3 && theta < (TMath::Pi()-theta3) )
1406 {
1407 z = m_R2/tan(theta);
1408 r = m_R2;
1409 }
1410 else if (theta >= (TMath::Pi()-theta3) && theta < (TMath::Pi()-theta2) )
1411 {
1412 z = -m_z2;
1413 r = std::fabs(m_z2*tan(theta));
1414 }
1415 else if (theta >= (TMath::Pi()-theta2) && theta < (TMath::Pi()-theta1) )
1416 {
1417 z = m_R1/tan(theta);
1418 r = m_R1;
1419 }
1420 else if (theta >= (TMath::Pi()-theta1) && theta <= TMath::Pi() )
1421 {
1422 z = -m_z1;
1423 r = std::fabs(m_z1*tan(theta));
1424 }
1425
1426 //parallel universe
1427 else
1428 {
1429 ATH_MSG_WARNING ( "Given theta angle is incorrect, setting particle position to (0, 0, 0)");
1430 x = 0.0; y = 0.0; z = 0.0; r = 0.0;
1431 }
1432
1433 x = r*cos(phi);
1434 y = r*sin(phi);
1435 Amg::Vector3D pos(x, y, z);
1436
1437 ATH_MSG_DEBUG("position of produced punch-through particle: x = "<< x <<" y = "<< y <<" z = "<< z<<" r = "<< pos.perp() <<"std::sqrt(x^2+y^2) = "<< std::sqrt(x*x+y*y) );
1438 ATH_MSG_DEBUG("GeoID thinks: Calo: "<< m_geoIDSvc->inside(pos, AtlasDetDescr::fAtlasCalo) <<" MS: "<< m_geoIDSvc->inside(pos,AtlasDetDescr::fAtlasMS));
1439
1440 return pos;
1441}
#define y
#define z

◆ readLookuptablePDF()

std::unique_ptr< ISF::PDFcreator > ISF::PunchThroughTool::readLookuptablePDF ( int pdgID,
const std::string & folderName )
private

reads out the lookuptable for the given type of particle

Definition at line 1242 of file PunchThroughTool.cxx.

1243{
1244
1245 // will hold the PDFcreator class which will be returned at the end
1246 // this will store the distributions for the punch through particles
1247 // (as map of energy & eta of the incoming particle)
1248 //PDFcreator *pdf = new PDFcreator();
1249 std::unique_ptr<ISF::PDFcreator> pdf = std::make_unique<ISF::PDFcreator>();
1250
1251 //Get directory object
1252 std::stringstream dirName;
1253 dirName << folderName << pdg;
1254 pdf->setName(dirName.str().c_str());
1255
1256 TDirectory * dir = (TDirectory*)m_fileLookupTable->Get(dirName.str().c_str());
1257 if(! dir)
1258 {
1259 ATH_MSG_ERROR( "[ punchthrough ] unable to retrieve directory object ("<< folderName << pdg << ")" );
1260 return nullptr;
1261 }
1262
1263
1264
1265 //Get list of all objects in directory
1266 TIter keyList(dir->GetListOfKeys());
1267 TKey *key;
1268
1269 while ((key = (TKey*)keyList())) {
1270
1271 //Get histogram object from key and its name
1272 TH1* hist = nullptr;
1273
1274 std::string histName;
1275 if(strcmp(key->GetClassName(), "TH1F") == 0){
1276 hist = (TH1*)key->ReadObj();
1277 histName = hist->GetName();
1278 }
1279
1280 //extract energy and eta from hist name 6 and 1 to position delimeters correctly
1281 std::string strEnergy = histName.substr( histName.find_first_of('E') + 1, histName.find_first_of('_')-histName.find_first_of('E') - 1 );
1282 histName.erase(0, histName.find_first_of('_') + 1);
1283 std::string strEtaMin = histName.substr( histName.find("etaMin") + 6, histName.find_first_of('_') - histName.find("etaMin") - 6 );
1284 histName.erase(0, histName.find('_') + 1);
1285 std::string strEtaMax = histName.substr( histName.find("etaMax") + 6, histName.length());
1286
1287 //create integers to store in map
1288 const int energy = std::stoi(strEnergy);
1289 const int etaMin = std::stoi(strEtaMin);
1290
1291 //Add entry to pdf map
1292 pdf->addToEnergyEtaHist1DMap(energy, etaMin, hist);
1293
1294 //create doubles to store energy and eta points for interpolation
1295 const double energyDbl = static_cast<double>(energy);
1296 const double etaDbl = static_cast<double>(etaMin)/100.;
1297
1298 //create vectors to store the eta and energy points, this allows us to interpolate
1299 if (std::find(m_energyPoints.begin(), m_energyPoints.end(), energyDbl) == m_energyPoints.end()) {
1300 m_energyPoints.push_back(energyDbl);
1301 }
1302 if (std::find(m_etaPoints.begin(), m_etaPoints.end(), etaDbl) == m_etaPoints.end()) {
1303 m_etaPoints.push_back(etaDbl);
1304 }
1305
1306 }
1307
1308
1309
1310 return pdf;
1311}

◆ registerCorrelation()

StatusCode ISF::PunchThroughTool::registerCorrelation ( int pdgID1,
int pdgID2,
double minCorrEnergy = 0.,
double fullCorrEnergy = 0. )
private

register a correlation for the two given types of punch-through particles with a given energy threshold above which we will have full correlation

Definition at line 1187 of file PunchThroughTool.cxx.

1189{
1190 // find the given pdgs in the registered particle ids
1191 std::map<int, PunchThroughParticle*>::iterator location1 = m_particles.find(pdgID1);
1192 std::map<int, PunchThroughParticle*>::iterator location2 = m_particles.find(pdgID2);
1193
1194 // if at least one of the given pdgs was not registered yet -> return an error
1195 if ( (location1 == m_particles.end()) || (location2 == m_particles.end()) )
1196 return StatusCode::FAILURE;
1197
1198 // now look for the correlation histograms
1199 std::stringstream name;
1200 name << "NumExitCorrelations/x_PDG" << std::abs(pdgID1) << "__y_PDG" << std::abs(pdgID2) << "__lowE";
1201 TH2F *hist1_2_lowE = (TH2F*)m_fileLookupTable->Get(name.str().c_str());
1202 name.str("");
1203 name << "NumExitCorrelations/x_PDG" << std::abs(pdgID1) << "__y_PDG" << std::abs(pdgID2) << "__highE";
1204 TH2F *hist1_2_highE = (TH2F*)m_fileLookupTable->Get(name.str().c_str());
1205 name.str("");
1206 name << "NumExitCorrelations/x_PDG" << std::abs(pdgID2) << "__y_PDG" << std::abs(pdgID1) << "__lowE";
1207 TH2F *hist2_1_lowE = (TH2F*)m_fileLookupTable->Get(name.str().c_str());
1208 name.str("");
1209 name << "NumExitCorrelations/x_PDG" << std::abs(pdgID2) << "__y_PDG" << std::abs(pdgID1) << "__highE";
1210 TH2F *hist2_1_highE = (TH2F*)m_fileLookupTable->Get(name.str().c_str());
1211 // check if the histograms exist
1212 if ( (!hist1_2_lowE) || (!hist2_1_lowE) || (!hist1_2_highE) || (!hist2_1_highE) )
1213 {
1214 ATH_MSG_ERROR("[ punchthrough ] unable to retrieve the correlation data for PDG IDs " << pdgID1 << " and " << pdgID2);
1215 return StatusCode::FAILURE;
1216 }
1217
1218 // TODO: if only one of the two histograms exists, create the other one
1219 // by mirroring the data
1220
1221 const double lowE = getFloatAfterPatternInStr( hist1_2_lowE->GetTitle(), "elow_");
1222 const double midE = getFloatAfterPatternInStr( hist1_2_lowE->GetTitle(), "ehigh_");
1223 //TODO: check if the same:
1224 // double midE = getFloatAfterPatternInStr( hist1_2_lowE->GetTitle(), "elow_");
1225 const double upperE = getFloatAfterPatternInStr( hist1_2_highE->GetTitle(), "ehigh_");
1226 // now store the correlation either way id1->id2 and id2->id1
1227 m_particles[pdgID1]->setCorrelation(pdgID2, hist2_1_lowE, hist2_1_highE,
1228 minCorrEnergy, fullCorrEnergy,
1229 lowE, midE, upperE);
1230
1231 m_particles[pdgID2]->setCorrelation(pdgID1, hist1_2_lowE, hist1_2_highE,
1232 minCorrEnergy, fullCorrEnergy,
1233 lowE, midE, upperE);
1234 return StatusCode::SUCCESS;
1235}
double getFloatAfterPatternInStr(const char *str, const char *pattern)
get the floating point number in a string, after the given pattern

◆ registerParticle()

StatusCode ISF::PunchThroughTool::registerParticle ( int pdgID,
bool doAntiparticle = false,
double minEnergy = 0.,
int maxNumParticles = -1,
double numParticlesFactor = 1.,
double energyFactor = 1.,
double posAngleFactor = 1.,
double momAngleFactor = 1. )
private

registers a type of punch-through particles which will be simulated

Definition at line 1110 of file PunchThroughTool.cxx.

1113{
1114 // read in the data needed to construct the distributions for the number of punch-through particles
1115
1116 // (1.) get the distribution function for the number of punch-through particles
1117 std::unique_ptr<ISF::PDFcreator> pdf_num(readLookuptablePDF(pdg, "FREQ_PDG"));
1118 if (!pdf_num ) return StatusCode::FAILURE; // return error if something went wrong
1119
1120 // (2.) get the PDF for the punch-through energy
1121 std::unique_ptr<PDFcreator> pdf_pca0 (readLookuptablePDF(pdg, "PCA0_PDG"));
1122 if (!pdf_pca0)
1123 {
1124 return StatusCode::FAILURE; // return error if something went wrong
1125 }
1126
1127 // (3.) get the PDF for the punch-through particles difference in
1128 // theta compared to the incoming particle
1129 std::unique_ptr<PDFcreator> pdf_pca1 (readLookuptablePDF(pdg, "PCA1_PDG"));
1130 if (!pdf_pca1)
1131 {
1132 return StatusCode::FAILURE;
1133 }
1134
1135 // (4.) get the PDF for the punch-through particles difference in
1136 // phi compared to the incoming particle
1137 std::unique_ptr<PDFcreator> pdf_pca2 (readLookuptablePDF(pdg, "PCA2_PDG"));
1138 if (!pdf_pca2)
1139 {
1140 return StatusCode::FAILURE;
1141 }
1142
1143 // (5.) get the PDF for the punch-through particle momentum delta theta angle
1144 std::unique_ptr<PDFcreator> pdf_pca3 (readLookuptablePDF(pdg, "PCA3_PDG"));
1145 if (!pdf_pca3)
1146 {
1147 return StatusCode::FAILURE;
1148 }
1149
1150 // (6.) get the PDF for the punch-through particle momentum delta phi angle
1151 std::unique_ptr<PDFcreator> pdf_pca4 (readLookuptablePDF(pdg, "PCA4_PDG"));
1152 if (!pdf_pca4)
1153 {
1154 return StatusCode::FAILURE;
1155 }
1156
1157 // (7.) now finally store all this in the right std::map
1158 PunchThroughParticle *particle = new PunchThroughParticle(pdg, doAntiparticle);
1159 particle->setNumParticlesPDF(std::move(pdf_num));
1160 particle->setPCA0PDF(std::move(pdf_pca0));
1161 particle->setPCA1PDF(std::move(pdf_pca1));
1162 particle->setPCA2PDF(std::move(pdf_pca2));
1163 particle->setPCA3PDF(std::move(pdf_pca3));
1164 particle->setPCA4PDF(std::move(pdf_pca4));
1165
1166 // (8.) set some additional particle and simulation properties
1167 const double restMass = m_particleDataTable->particle(std::abs(pdg))->mass();
1168 minEnergy = ( minEnergy > restMass ) ? minEnergy : restMass;
1169 particle->setMinEnergy(minEnergy);
1170 particle->setMaxNumParticles(maxNumParticles);
1171 particle->setNumParticlesFactor(numParticlesFactor);
1172 particle->setEnergyFactor(energyFactor);
1173 particle->setPosAngleFactor(posAngleFactor);
1174 particle->setMomAngleFactor(momAngleFactor);
1175
1176 // (9.) insert this PunchThroughParticle instance into the std::map class member
1177 m_particles[pdg] = particle;
1178
1179 return StatusCode::SUCCESS;
1180}
std::unique_ptr< ISF::PDFcreator > readLookuptablePDF(int pdgID, const std::string &folderName)
reads out the lookuptable for the given type of particle

Member Data Documentation

◆ m_beamPipe

DoubleProperty ISF::PunchThroughTool::m_beamPipe {this, "BeamPipeRadius", 500.}
private

beam pipe radius

Definition at line 203 of file PunchThroughTool.h.

203{this, "BeamPipeRadius", 500.};

◆ m_correlatedParticle

IntegerArrayProperty ISF::PunchThroughTool::m_correlatedParticle {this, "CorrelatedParticle", {}, "holds the pdg of the correlated particle for each given pdg"}
private

Definition at line 183 of file PunchThroughTool.h.

183{this, "CorrelatedParticle", {}, "holds the pdg of the correlated particle for each given pdg"};

◆ m_doAntiParticles

BooleanArrayProperty ISF::PunchThroughTool::m_doAntiParticles {this, "DoAntiParticles", {}, "vector of bools to determine if anti-particles are created for each punch-through particle type"}
private

Definition at line 182 of file PunchThroughTool.h.

182{this, "DoAntiParticles", {}, "vector of bools to determine if anti-particles are created for each punch-through particle type"};

◆ m_energyFactor

DoubleArrayProperty ISF::PunchThroughTool::m_energyFactor {this, "EnergyFactor", {}, "scale the energy of the punch-through particles"}
private

Definition at line 191 of file PunchThroughTool.h.

191{this, "EnergyFactor", {}, "scale the energy of the punch-through particles"};

◆ m_energyPoints

std::vector<double> ISF::PunchThroughTool::m_energyPoints
private

energy and eta points in param

Definition at line 150 of file PunchThroughTool.h.

◆ m_envDefSvc

ServiceHandle<IEnvelopeDefSvc> ISF::PunchThroughTool::m_envDefSvc {this, "EnvelopeDefSvc", "AtlasGeometry_EnvelopeDefSvc"}
private

Definition at line 200 of file PunchThroughTool.h.

200{this, "EnvelopeDefSvc", "AtlasGeometry_EnvelopeDefSvc"};

◆ m_etaPoints

std::vector<double> ISF::PunchThroughTool::m_etaPoints
private

Definition at line 151 of file PunchThroughTool.h.

◆ m_fileLookupTable

TFile* ISF::PunchThroughTool::m_fileLookupTable {nullptr}
private

ROOT objects.

the punch-through lookup table file

Definition at line 163 of file PunchThroughTool.h.

163{nullptr};

◆ m_filenameInverseCDF

StringProperty ISF::PunchThroughTool::m_filenameInverseCDF {this, "FilenameInverseCdf", "", "holds the filename of inverse quantile transformer config"}
private

Definition at line 174 of file PunchThroughTool.h.

174{this, "FilenameInverseCdf", "", "holds the filename of inverse quantile transformer config"};

◆ m_filenameInversePCA

StringProperty ISF::PunchThroughTool::m_filenameInversePCA {this, "FilenameInversePca", "", "holds the filename of inverse PCA config"}
private

Definition at line 175 of file PunchThroughTool.h.

175{this, "FilenameInversePca", "", "holds the filename of inverse PCA config"};

◆ m_filenameLookupTable

StringProperty ISF::PunchThroughTool::m_filenameLookupTable {this, "FilenameLookupTable", "CaloPunchThroughParametrisation.root", "holds the filename of the lookup table"}
private

Properties.

Definition at line 173 of file PunchThroughTool.h.

173{this, "FilenameLookupTable", "CaloPunchThroughParametrisation.root", "holds the filename of the lookup table"};

◆ m_fullCorrEnergy

DoubleArrayProperty ISF::PunchThroughTool::m_fullCorrEnergy {this, "FullCorrelationEnergy", {}, "holds the energy threshold above which a particle correlation is fully developed"}
private

Definition at line 185 of file PunchThroughTool.h.

185{this, "FullCorrelationEnergy", {}, "holds the energy threshold above which a particle correlation is fully developed"};

◆ m_geoIDSvc

ServiceHandle<IGeoIDSvc> ISF::PunchThroughTool::m_geoIDSvc {this, "GeoIDSvc", "ISF::GeoIDSvc"}
private

Definition at line 199 of file PunchThroughTool.h.

199{this, "GeoIDSvc", "ISF::GeoIDSvc"};

◆ m_initiatorsEtaRange

DoubleArrayProperty ISF::PunchThroughTool::m_initiatorsEtaRange {this, "InitiatorsEtaRange", {}, "vector of min and max abs eta range to allow punch through initiators"}
private

Definition at line 180 of file PunchThroughTool.h.

180{this, "InitiatorsEtaRange", {}, "vector of min and max abs eta range to allow punch through initiators"};

◆ m_initiatorsMinEnergy

IntegerArrayProperty ISF::PunchThroughTool::m_initiatorsMinEnergy {this, "InitiatorsMinEnergy", {}, "vector of punch-through initiator min energies to create punch through"}
private

Definition at line 179 of file PunchThroughTool.h.

179{this, "InitiatorsMinEnergy", {}, "vector of punch-through initiator min energies to create punch through"};

◆ m_inverse_PCA_matrix

std::vector<std::vector<std::vector<double> > > ISF::PunchThroughTool::m_inverse_PCA_matrix
private

pca vectors

Definition at line 206 of file PunchThroughTool.h.

◆ m_maxNumParticles

IntegerArrayProperty ISF::PunchThroughTool::m_maxNumParticles {this, "MaxNumParticles", {}, "maximum number of punch-through particles for each particle type"}
private

Definition at line 189 of file PunchThroughTool.h.

189{this, "MaxNumParticles", {}, "maximum number of punch-through particles for each particle type"};

◆ m_minCorrEnergy

DoubleArrayProperty ISF::PunchThroughTool::m_minCorrEnergy {this, "MinCorrelationEnergy", {}, "holds the energy threshold below which no particle correlation is computed"}
private

Definition at line 184 of file PunchThroughTool.h.

184{this, "MinCorrelationEnergy", {}, "holds the energy threshold below which no particle correlation is computed"};

◆ m_minEnergy

DoubleArrayProperty ISF::PunchThroughTool::m_minEnergy {this, "MinEnergy", {}, "punch-through particles minimum energies"}
private

Definition at line 188 of file PunchThroughTool.h.

188{this, "MinEnergy", {}, "punch-through particles minimum energies"};

◆ m_momAngleFactor

DoubleArrayProperty ISF::PunchThroughTool::m_momAngleFactor {this, "ScaleMomDeflectionAngles", {}, "tuning parameter to scale the momentum deflection angles"}
private

Definition at line 187 of file PunchThroughTool.h.

187{this, "ScaleMomDeflectionAngles", {}, "tuning parameter to scale the momentum deflection angles"};

◆ m_numParticlesFactor

DoubleArrayProperty ISF::PunchThroughTool::m_numParticlesFactor {this, "NumParticlesFactor", {}, "scale the number of punch-through particles"}
private

Definition at line 190 of file PunchThroughTool.h.

190{this, "NumParticlesFactor", {}, "scale the number of punch-through particles"};

◆ m_particleDataTable

const HepPDT::ParticleDataTable* ISF::PunchThroughTool::m_particleDataTable {nullptr}
private

ParticleDataTable needed to get connection pdg_code <-> charge.

Definition at line 160 of file PunchThroughTool.h.

160{nullptr};

◆ m_particlePropSvc

ServiceHandle<IPartPropSvc> ISF::PunchThroughTool::m_particlePropSvc {this, "PartPropSvc", "PartPropSvc", "particle properties svc"}
private

Definition at line 198 of file PunchThroughTool.h.

198{this, "PartPropSvc", "PartPropSvc", "particle properties svc"};

◆ m_particles

std::map<int, PunchThroughParticle*> ISF::PunchThroughTool::m_particles
private

needed to create punch-through particles with the right distributions

store all punch-through information for each particle id

Definition at line 166 of file PunchThroughTool.h.

◆ m_PCA_means

std::vector<std::vector<double> > ISF::PunchThroughTool::m_PCA_means
private

Definition at line 207 of file PunchThroughTool.h.

◆ m_pdgInitiators

IntegerArrayProperty ISF::PunchThroughTool::m_pdgInitiators {this, "PunchThroughInitiators", {}, "vector of punch-through initiator pgds"}
private

Definition at line 178 of file PunchThroughTool.h.

178{this, "PunchThroughInitiators", {}, "vector of punch-through initiator pgds"};

◆ m_posAngleFactor

DoubleArrayProperty ISF::PunchThroughTool::m_posAngleFactor {this, "ScalePosDeflectionAngles", {}, "tuning parameter to scale the position deflection angles"}
private

Definition at line 186 of file PunchThroughTool.h.

186{this, "ScalePosDeflectionAngles", {}, "tuning parameter to scale the position deflection angles"};

◆ m_punchThroughClassifier

PublicToolHandle<IPunchThroughClassifier> ISF::PunchThroughTool::m_punchThroughClassifier {this, "PunchThroughClassifier", "ISF_PunchThroughClassifier", ""}
private

Definition at line 177 of file PunchThroughTool.h.

177{this, "PunchThroughClassifier", "ISF_PunchThroughClassifier", ""};

◆ m_punchThroughParticles

IntegerArrayProperty ISF::PunchThroughTool::m_punchThroughParticles {this, "PunchThroughParticles", {}, "vector of pdgs of the particles produced in punch-throughs"}
private

Definition at line 181 of file PunchThroughTool.h.

181{this, "PunchThroughParticles", {}, "vector of pdgs of the particles produced in punch-throughs"};

◆ m_R1

double ISF::PunchThroughTool::m_R1 {0.}
private

calo-MS borders

Definition at line 154 of file PunchThroughTool.h.

154{0.};

◆ m_R2

double ISF::PunchThroughTool::m_R2 {0.}
private

Definition at line 155 of file PunchThroughTool.h.

155{0.};

◆ m_variable0_inverse_cdf

std::vector<std::map<double, double> > ISF::PunchThroughTool::m_variable0_inverse_cdf
private

(vector of map) for CDF mappings

Definition at line 214 of file PunchThroughTool.h.

◆ m_variable1_inverse_cdf

std::vector<std::map<double, double> > ISF::PunchThroughTool::m_variable1_inverse_cdf
private

Definition at line 215 of file PunchThroughTool.h.

◆ m_variable2_inverse_cdf

std::vector<std::map<double, double> > ISF::PunchThroughTool::m_variable2_inverse_cdf
private

Definition at line 216 of file PunchThroughTool.h.

◆ m_variable3_inverse_cdf

std::vector<std::map<double, double> > ISF::PunchThroughTool::m_variable3_inverse_cdf
private

Definition at line 217 of file PunchThroughTool.h.

◆ m_variable4_inverse_cdf

std::vector<std::map<double, double> > ISF::PunchThroughTool::m_variable4_inverse_cdf
private

Definition at line 218 of file PunchThroughTool.h.

◆ m_xml_info_cdf

std::vector<std::map<std::string, std::string> > ISF::PunchThroughTool::m_xml_info_cdf
private

Definition at line 211 of file PunchThroughTool.h.

◆ m_xml_info_pca

std::vector<std::map<std::string, std::string> > ISF::PunchThroughTool::m_xml_info_pca
private

infoMaps

Definition at line 210 of file PunchThroughTool.h.

◆ m_z1

double ISF::PunchThroughTool::m_z1 {0.}
private

Definition at line 156 of file PunchThroughTool.h.

156{0.};

◆ m_z2

double ISF::PunchThroughTool::m_z2 {0.}
private

Definition at line 157 of file PunchThroughTool.h.

157{0.};

The documentation for this class was generated from the following files: