diff --git a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/IInDetTrackTruthFilterTool.h b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/IInDetTrackTruthFilterTool.h index c64c78e1a7586c9c5fe1f19a717cd301fa2eb09b..80699eaa7450e1831473da58ab72adc37c0e1b73 100644 --- a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/IInDetTrackTruthFilterTool.h +++ b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/IInDetTrackTruthFilterTool.h @@ -31,13 +31,9 @@ namespace InDet { virtual StatusCode initialize() = 0; virtual void prepare() = 0; // not sure if/why this function is necessary - felix - // "standard" accept method - if appropriate systematic is activated, will call mu-dependent version (below) using mu value from EventInfo, otherwise will use truth info + // standard accept method to determine if a track should be kept or not virtual bool accept(const xAOD::TrackParticle* track) const = 0; - // This is a version of the accept method that takes a value of mu (i.e. mean interactions per crossing) in order to calculate a probability that a givent track at that mu is a fake, - // and so should be considered for being dropped for the fake systematic variation - this version does not rely on truth information - virtual bool accept(const xAOD::TrackParticle* track, float mu) const = 0; - // implement the CP::ISystematicTool interface /// returns: whether the tool is affected by the systematic diff --git a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackSystematics.h b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackSystematics.h index dcaaf3918387738e5ec6da843d9b38b02859ffd0..c84e8dd28ee1077bc7087f3eeb42c9911aac33e0 100644 --- a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackSystematics.h +++ b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackSystematics.h @@ -25,7 +25,7 @@ namespace InDet { TRK_BIAS_D0_WM, TRK_BIAS_Z0_WM, TRK_BIAS_QOVERP_SAGITTA_WM, - // a (currently 30%) uncertainty in the fake rate - this needs to be updated for Loose vs. TightPrimary + // uncertainties in the fake rate for Loose and TightPrimary TRK_FAKE_RATE_LOOSE, TRK_FAKE_RATE_TIGHT, // uncertainties in the efficiency for two cut levels, "Loose" and "TightPrimary" @@ -39,15 +39,15 @@ namespace InDet { TRK_EFF_TIGHT_PP0, TRK_EFF_TIGHT_PHYSMODEL, TRK_EFF_LARGED0_GLOBAL, - TRK_EFF_LARGED0_IBL, - TRK_EFF_LARGED0_PP0, - TRK_EFF_LARGED0_PHYSMODEL, // uncertainty for tracking efficiency in jets TRK_EFF_LOOSE_TIDE, // uncertainties for tracking fake rates in jets TRK_FAKE_RATE_TIGHT_TIDE, TRK_FAKE_RATE_LOOSE_TIDE, - TRK_FAKE_RATE_LOOSE_ROBUST + // combined efficiency systematics for use in downstream objects such as secondary vertexing ONLY + // this is not an additional systematic, but rather a replacement for the standard efficiencies in objects where four variations are prohibitive + TRK_EFF_LOOSE_COMBINED, + TRK_EFF_TIGHT_COMBINED, }; // without getting too crafty with macros, this map needs to be maintained with the enum above @@ -78,12 +78,10 @@ namespace InDet { DEF_SYST( EFF_TIGHT_PHYSMODEL ), DEF_SYST( EFF_LOOSE_TIDE ), DEF_SYST( EFF_LARGED0_GLOBAL ), - DEF_SYST( EFF_LARGED0_IBL ), - DEF_SYST( EFF_LARGED0_PP0 ), - DEF_SYST( EFF_LARGED0_PHYSMODEL ), DEF_SYST( FAKE_RATE_TIGHT_TIDE ), DEF_SYST( FAKE_RATE_LOOSE_TIDE ), - DEF_SYST( FAKE_RATE_LOOSE_ROBUST ) + DEF_SYST( EFF_LOOSE_COMBINED ), + DEF_SYST( EFF_TIGHT_COMBINED ), #undef DEF_SYST }; diff --git a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackTruthFilterTool.h b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackTruthFilterTool.h index 7a39ef623efec4be0182a96f19cc52c4b0605794..2b8b7b0a1323ec37afedf1f96851df2c6a3cfa73 100644 --- a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackTruthFilterTool.h +++ b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InDetTrackTruthFilterTool.h @@ -7,8 +7,10 @@ #define INDETTRACKSYSTEMATICSTOOLS_INDETTRACKTRUTHFILTERTOOL_H #include "InDetTrackSystematicsTools/IInDetTrackTruthFilterTool.h" +#include "InDetTrackSystematicsTools/IInDetTrackTruthOriginTool.h" #include "AsgTools/AsgTool.h" #include "AsgTools/ToolHandle.h" +#include "AsgTools/PropertyWrapper.h" #include "PATInterfaces/SystematicVariation.h" #include "PATInterfaces/SystematicSet.h" #include "InDetTrackSystematicsTools/InDetTrackSystematicsTool.h" @@ -22,8 +24,6 @@ class TFile; namespace InDet { - class IInDetTrackTruthOriginTool; - /// @class InDetTrackTruthFilterTool /// This class selects tracks based on their truth origin /// @author Remi Zaidan (remi.zaidan@cern.ch) @@ -50,13 +50,9 @@ namespace InDet { // right now this returns a bool; if we want to implement the ASG selection tool interface then this will need to change to a TAccept - // "standard" accept method - if appropriate systematic is activated, will call mu-dependent version (below) using mu value from EventInfo, otherwise will use truth info + // accept method to determine if a track should be kept or not virtual bool accept(const xAOD::TrackParticle* track) const override; - // This is a version of the accept method that takes a value of mu (i.e. mean interactions per crossing) in order to calculate a probability that a givent track at that mu is a fake, - // and so should be considered for being dropped for the fake systematic variation - this version does not rely on truth information - virtual bool accept(const xAOD::TrackParticle* track, float mu) const override; - /// returns: whether the tool is affected by the systematic virtual bool isAffectedBySystematic( const CP::SystematicVariation& ) const override; /// returns: list of systematics this tool can be affected by @@ -73,31 +69,15 @@ namespace InDet { StatusCode initTrkEffSystHistogram(float scale, TH2 *&histogram, std::string rootFileName, std::string histogramName) const; float getFractionDropped(float fDefault, const TH2 *histogram, float x, float y, bool xAxisIspT = true) const; - float pseudoFakeProbability(const xAOD::TrackParticle* track, float mu) const; - bool dropPseudoFake(float prob) const; - int m_seed = 0; + ToolHandle< IInDetTrackTruthOriginTool > m_trackOriginTool{this, "trackOriginTool", "InDet::InDetTrackTruthOriginTool", "Tool to get the truth origin of a track"}; + + Gaudi::Property<int> m_seed{this, "Seed", 0, "Random seed"}; std::unique_ptr<TRandom3> m_rnd; //! - float m_fPrim = 1.; - float m_fSec = 1.; - float m_fFakeLoose = 0.10; - float m_fFakeTight = 1.00; // this method breaks down for uncertainties > 1.00 (as was present in previous iterations) - float m_fPU = 1.; - float m_fFrag = 1.; - float m_fFromC = 1.; - float m_fFromB = 1.; - float m_trkEffSystScale = 1.; - bool m_doLRTSystematics = false; - - TH2 *m_fPrimHistogram = nullptr; - TH2 *m_fSecHistogram = nullptr; - //TH2 *m_fFakeHistogram = nullptr; - TH2 *m_fPUHistogram = nullptr; - TH2 *m_fFragHistogram = nullptr; - TH2 *m_fFromCHistogram = nullptr; - TH2 *m_fFromBHistogram = nullptr; - + Gaudi::Property<float> m_fFakeLoose{this, "fFakeLoose", -1.0, "Fake loose fraction"}; + Gaudi::Property<float> m_fFakeTight{this, "fFakeTight", -1.0, "Fake tight fraction"}; + Gaudi::Property<float> m_trkEffSystScale{this, "trkEffSystScale", 1.0, "Track efficiency systematic scale"}; TH2* m_trkEffHistLooseGlobal = nullptr; TH2* m_trkEffHistLooseIBL = nullptr; @@ -107,21 +87,13 @@ namespace InDet { TH2* m_trkEffHistTightIBL = nullptr; TH2* m_trkEffHistTightPP0 = nullptr; TH2* m_trkEffHistTightPhysModel = nullptr; - TH2* m_trkEffHistLRTGlobal = nullptr; - TH2* m_trkEffHistLRTIBL = nullptr; - TH2* m_trkEffHistLRTPP0 = nullptr; - TH2* m_trkEffHistLRTPhysModel = nullptr; std::unordered_map<std::string, TH2*> m_histMap; // allow the user to configure which calibration files to use if desired - std::string m_calibFileNomEff; - std::string m_calibFileLRTEff; - - ToolHandle< IInDetTrackTruthOriginTool > m_trackOriginTool; - + Gaudi::Property<std::string> m_calibFileNomEff{this, "calibFileNomEff", "", "Calibration file for nominal efficiency"}; -}; // class InDetTrackTruthFilterTool + }; // class InDetTrackTruthFilterTool } // namespace InDet diff --git a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InclusiveTrackFilterTool.h b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InclusiveTrackFilterTool.h index b25974cbf32c3a5e459f8b116cad9d2079bd4f26..4f629a8375b5c584b4bd80693be855d0c41096fa 100644 --- a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InclusiveTrackFilterTool.h +++ b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/InDetTrackSystematicsTools/InclusiveTrackFilterTool.h @@ -71,7 +71,7 @@ namespace InDet { Gaudi::Property<float> m_trkEffSystScale{this, "trkEffSystScale", 1.0, "Option to scale the effect of the systematic (default 1)"}; // Property: path to the root file containing the LRT efficiency histogram (note: uses PathResolver) - Gaudi::Property<std::string> m_calibFileLRTEff{this, "calibFileLRTEff", "InDetTrackSystematicsTools/CalibData_24.0_2023-v00/LargeD0TrackingRecommendations_20230824.root", "File containing the efficiency histogram (expert only)"}; + Gaudi::Property<std::string> m_calibFileLRTEff{this, "calibFileLRTEff", "", "File containing the efficiency histogram (expert only)"}; // Property: name of the efficiency histogram in m_calibFileLRTEff Gaudi::Property<std::string> m_calibHistLRTEff{this, "calibHistLRTEff", "OneMinusRatioEfficiencyVSRadiusOfFirstHitEta_Nominal", "Name of the efficiency histogram (expert only)"}; diff --git a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InDetTrackTruthFilterTool.cxx b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InDetTrackTruthFilterTool.cxx index fce30013cabc8a1ec92dee740557749d0d785ed5..cf5b814a4795daa2687442f4ac2e62820a6f79c8 100644 --- a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InDetTrackTruthFilterTool.cxx +++ b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InDetTrackTruthFilterTool.cxx @@ -33,45 +33,46 @@ namespace InDet { InDet::TrackSystematicMap.at(TRK_EFF_TIGHT_IBL), InDet::TrackSystematicMap.at(TRK_EFF_TIGHT_PP0), InDet::TrackSystematicMap.at(TRK_EFF_TIGHT_PHYSMODEL), - InDet::TrackSystematicMap.at(TRK_FAKE_RATE_LOOSE_ROBUST), - InDet::TrackSystematicMap.at(TRK_EFF_LARGED0_GLOBAL), - InDet::TrackSystematicMap.at(TRK_EFF_LARGED0_IBL), - InDet::TrackSystematicMap.at(TRK_EFF_LARGED0_PP0), - InDet::TrackSystematicMap.at(TRK_EFF_LARGED0_PHYSMODEL), + InDet::TrackSystematicMap.at(TRK_EFF_LOOSE_COMBINED), //combined systematics are to be used in downstream objects such as secondary vertexing ONLY + InDet::TrackSystematicMap.at(TRK_EFF_TIGHT_COMBINED), //they are not an "additional" systematic, but rather a replacement for the standard efficiencies where four variations are prohibitive }; InDetTrackTruthFilterTool::InDetTrackTruthFilterTool(const std::string& name) : - InDetTrackSystematicsTool(name), - m_trackOriginTool("InDet::InDetTrackTruthOriginTool", this) + InDetTrackSystematicsTool(name) { #ifndef XAOD_STANDALONE declareInterface<IInDetTrackTruthFilterTool>(this); #endif - declareProperty("trackOriginTool", m_trackOriginTool); - - declareProperty("Seed", m_seed); - - declareProperty("fPrim", m_fPrim); - declareProperty("fSec", m_fSec); - declareProperty("fFakeLoose", m_fFakeLoose); - declareProperty("fFakeTight", m_fFakeTight); - declareProperty("fPU", m_fPU); - declareProperty("fFrag", m_fFrag); - declareProperty("fFromC", m_fFromC); - declareProperty("fFromB", m_fFromB); - declareProperty("trkEffSystScale", m_trkEffSystScale); - declareProperty("doLRTSystematics", m_doLRTSystematics); - - declareProperty("calibFileNomEff", m_calibFileNomEff = "InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root"); - declareProperty("calibFileLRTEff", m_calibFileLRTEff = "InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root"); } StatusCode InDetTrackTruthFilterTool::initialize() { + ATH_CHECK ( m_trackOriginTool.retrieve() ); + m_rnd = std::make_unique<TRandom3>(m_seed); + bool anyEffSystActive = isActive(TRK_EFF_LOOSE_GLOBAL) || isActive(TRK_EFF_LOOSE_IBL) || isActive(TRK_EFF_LOOSE_PP0) || + isActive(TRK_EFF_LOOSE_PHYSMODEL) || isActive(TRK_EFF_TIGHT_GLOBAL) || isActive(TRK_EFF_TIGHT_IBL) || + isActive(TRK_EFF_TIGHT_PP0) || isActive(TRK_EFF_TIGHT_PHYSMODEL ) || isActive(TRK_EFF_LOOSE_COMBINED) || isActive(TRK_EFF_TIGHT_COMBINED); + + bool anyFakeRateActive = isActive(TRK_FAKE_RATE_LOOSE) || isActive(TRK_FAKE_RATE_TIGHT); + + if (anyEffSystActive) { + if (m_calibFileNomEff.empty()) { + ATH_MSG_ERROR("No calibration file for requested track efficiency set. You may be running an unsupported datataking period, please contact Tracking CP if you believe this message is in error."); + return StatusCode::FAILURE; + } + } + + if (anyFakeRateActive) { + if (m_fFakeLoose == -1.0 && m_fFakeTight == -1.0) { + ATH_MSG_ERROR("Requested fake rate is unavailable. You may be running an unsupported datataking period, please contact Tracking CP if you believe this message is in error."); + return StatusCode::FAILURE; + } + } + ATH_CHECK ( initTrkEffSystHistogram( m_trkEffSystScale, m_trkEffHistLooseGlobal, m_calibFileNomEff, @@ -107,26 +108,6 @@ namespace InDet { ATH_MSG_INFO( "Using for nominal track efficiency the calibration file " << PathResolverFindCalibFile(m_calibFileNomEff) ); - if(m_doLRTSystematics) { - ATH_CHECK ( initTrkEffSystHistogram( m_trkEffSystScale, - m_trkEffHistLRTGlobal, - m_calibFileLRTEff, - "OneMinusRatioEfficiencyVSEtaProdR_AfterRebinning_NominalVSp5Overall_LRT") ); - ATH_CHECK ( initTrkEffSystHistogram( m_trkEffSystScale, - m_trkEffHistLRTIBL, - m_calibFileLRTEff, - "OneMinusRatioEfficiencyVSEtaProdR_AfterRebinning_NominalVSp10IBL_LRT") ); - ATH_CHECK ( initTrkEffSystHistogram( m_trkEffSystScale, - m_trkEffHistLRTPP0, - m_calibFileLRTEff, - "OneMinusRatioEfficiencyVSEtaProdR_AfterRebinning_NominalVSp25PP0_LRT") ); - ATH_CHECK ( initTrkEffSystHistogram( m_trkEffSystScale, - m_trkEffHistLRTPhysModel, - m_calibFileLRTEff, - "OneMinusRatioEfficiencyVSEtaProdR_AfterRebinning_NominalVSQGSP_LRT") ); - ATH_MSG_INFO( "Using for LRT track efficiency the calibration file " << PathResolverFindCalibFile(m_calibFileLRTEff) ); - } - m_histMap = { {"TRK_EFF_LOOSE_GLOBAL", m_trkEffHistLooseGlobal}, {"TRK_EFF_LOOSE_IBL", m_trkEffHistLooseIBL}, @@ -138,8 +119,6 @@ namespace InDet { {"TRK_EFF_TIGHT_PHYSMODEL", m_trkEffHistTightPhysModel} }; - ATH_CHECK ( m_trackOriginTool.retrieve() ); - ATH_CHECK ( InDetTrackSystematicsTool::initialize() ); return StatusCode::SUCCESS; @@ -148,13 +127,6 @@ namespace InDet { InDetTrackTruthFilterTool::~InDetTrackTruthFilterTool() { - delete m_fPrimHistogram; - delete m_fSecHistogram; - //delete m_fFakeHistogram; - delete m_fPUHistogram; - delete m_fFragHistogram; - delete m_fFromCHistogram; - delete m_fFromBHistogram; delete m_trkEffHistLooseGlobal; delete m_trkEffHistLooseIBL; delete m_trkEffHistLoosePP0; @@ -163,20 +135,7 @@ namespace InDet { delete m_trkEffHistTightIBL; delete m_trkEffHistTightPP0; delete m_trkEffHistTightPhysModel; - if(m_doLRTSystematics) { - delete m_trkEffHistLRTGlobal; - delete m_trkEffHistLRTIBL; - delete m_trkEffHistLRTPP0; - delete m_trkEffHistLRTPhysModel; - } - - m_fPrimHistogram = nullptr; - m_fSecHistogram = nullptr; - // m_fFakeHistogram = nullptr; - m_fPUHistogram = nullptr; - m_fFragHistogram = nullptr; - m_fFromCHistogram = nullptr; - m_fFromBHistogram = nullptr; + m_trkEffHistLooseGlobal = nullptr; m_trkEffHistLooseIBL = nullptr; m_trkEffHistLoosePP0 = nullptr; @@ -185,28 +144,6 @@ namespace InDet { m_trkEffHistTightIBL = nullptr; m_trkEffHistTightPP0 = nullptr; m_trkEffHistTightPhysModel = nullptr; - m_trkEffHistLRTGlobal = nullptr; - m_trkEffHistLRTIBL = nullptr; - m_trkEffHistLRTPP0 = nullptr; - m_trkEffHistLRTPhysModel = nullptr; - } - - bool InDetTrackTruthFilterTool::accept(const xAOD::TrackParticle* track, float mu) const { - - // this is only really useful if you are using the "robust" systematic version, otherwise the mu set can't do anything - if(isActive( TRK_FAKE_RATE_LOOSE_ROBUST )){ - - // calcuate probability for this to be a fake, and then roll random numbers to decide if it is one, and if it should not be accepted - float fakeProb = pseudoFakeProbability(track,mu); - if(dropPseudoFake(fakeProb)) return false; - - // otherwise, pass the track - return true; - - } else { - ATH_MSG_ERROR("User-specified mu value cannot be applied due to using wrong systematic version - select TRK_FAKE_RATE_LOOSE_ROBUST is you want to use this"); - return true; // if you're not using the robust version, do nothing - } } bool InDetTrackTruthFilterTool::accept(const xAOD::TrackParticle* track) const { @@ -214,35 +151,8 @@ namespace InDet { float pt = track->pt(); float eta = track->eta(); - // Do robust version without using truth first if selected, as this is relatively decoupled from the rest - if(isActive( TRK_FAKE_RATE_LOOSE_ROBUST )) { - const xAOD::EventInfo* ei = 0; - float mu = 20; // sensible mu default - if ( ! evtStore()->retrieve( ei , "EventInfo" ).isSuccess() ) { // this will check data vs. MC and run number. - throw std::runtime_error("Error in InDetTrackTruthFilterTool::accept - failed to retrieve EventInfo."); - } - mu = ei->averageInteractionsPerCrossing(); - - if (not accept(track,mu)) return false; - } - // now, back to using truth... - int origin = m_trackOriginTool->getTrackOrigin(track); - // we unimplemented histograms for these, so only flat defaults will be used. - float fPrim = getFractionDropped(m_fPrim, m_fPrimHistogram, pt, eta); - if(InDet::TrkOrigin::isPrimary(origin) && m_rnd->Uniform(0, 1) > fPrim) return false; - float fSec = getFractionDropped(m_fSec, m_fSecHistogram, pt, eta); - if(InDet::TrkOrigin::isSecondary(origin) && m_rnd->Uniform(0, 1) > fSec) return false; - float fPU = getFractionDropped(m_fPU, m_fPUHistogram, pt, eta); - if(InDet::TrkOrigin::isPileup(origin) && m_rnd->Uniform(0, 1) > fPU) return false; - float fFrag = getFractionDropped(m_fFrag, m_fFragHistogram, pt, eta); - if(InDet::TrkOrigin::isFragmentation(origin) && m_rnd->Uniform(0, 1) > fFrag) return false; - float fFromC = getFractionDropped(m_fFromC, m_fFromCHistogram, pt, eta); - if(InDet::TrkOrigin::isFromD(origin) && m_rnd->Uniform(0, 1) > fFromC) return false; - float fFromB = getFractionDropped(m_fFromB, m_fFromBHistogram, pt, eta); - if(InDet::TrkOrigin::isFromB(origin) && m_rnd->Uniform(0, 1) > fFromB) return false; - if ( InDet::TrkOrigin::isFake(origin) ) { bool isActiveLoose = isActive( TRK_FAKE_RATE_LOOSE ); bool isActiveTight = isActive( TRK_FAKE_RATE_TIGHT ); @@ -250,7 +160,7 @@ namespace InDet { throw std::runtime_error( "Both Loose and TightPrimary versions of fake rate systematic are set." ); } if ( isActiveLoose ) { - //float fFake = getFractionDropped(m_fFake, m_fFakeHistogram, pt, eta); // there is no fake-rate histogram - just a flat uncertainty + // there is no fake-rate histogram - just a flat uncertainty if(m_rnd->Uniform(0, 1) < m_fFakeLoose) return false; } if ( isActiveTight ) { @@ -291,44 +201,21 @@ namespace InDet { float fTrkEffSyst = getFractionDropped(1, m_trkEffHistTightPhysModel, pt, eta); if(m_rnd->Uniform(0, 1) < fTrkEffSyst) return false; } - } - if(m_doLRTSystematics) { - static const SG::ConstAccessor<ElementLink< xAOD::TruthParticleContainer > > - truthParticleLinkAcc ("truthParticleLink"); - const ElementLink< xAOD::TruthParticleContainer > &truthParticleLink = - truthParticleLinkAcc (*track); - if(truthParticleLink.isValid()) { - const xAOD::TruthParticle *truthParticle = *truthParticleLink; - double eta = truthParticle->eta(); - - static const SG::ConstAccessor<ElementLink< xAOD::TruthVertexContainer > > - prodVtxLinkAcc ("prodVtxLink"); - const ElementLink< xAOD::TruthVertexContainer > &truthVertexLink = - prodVtxLinkAcc (*truthParticle); - if(truthVertexLink.isValid()) { - const xAOD::TruthVertex *truthVertex = *truthVertexLink; - double prodR = truthVertex->perp(); - if ( isActive( TRK_EFF_LARGED0_GLOBAL ) ) { - float fTrkEffSyst = getFractionDropped(1.0, m_trkEffHistLRTGlobal, eta, prodR, false); - if(m_rnd->Uniform(0, 1) < fTrkEffSyst) return false; - } - - if ( isActive( TRK_EFF_LARGED0_IBL ) ) { - float fTrkEffSyst = getFractionDropped(1.0, m_trkEffHistLRTIBL, eta, prodR, false); - if(m_rnd->Uniform(0, 1) < fTrkEffSyst) return false; - } - - if ( isActive( TRK_EFF_LARGED0_PP0 ) ) { - float fTrkEffSyst = getFractionDropped(1.0, m_trkEffHistLRTPP0, eta, prodR, false); - if(m_rnd->Uniform(0, 1) < fTrkEffSyst) return false; - } - - if ( isActive( TRK_EFF_LARGED0_PHYSMODEL ) ) { - float fTrkEffSyst = getFractionDropped(1.0, m_trkEffHistLRTPhysModel, eta, prodR, false); - if(m_rnd->Uniform(0, 1) < fTrkEffSyst) return false; - } - } + // combined systematics represent the sum in quadrature of the individual systematics + if ( isActive( TRK_EFF_LOOSE_COMBINED ) ) { + float fTrkEffSyst = sqrt( pow(getFractionDropped(1, m_trkEffHistLooseGlobal, pt, eta), 2) + + pow(getFractionDropped(1, m_trkEffHistLooseIBL, pt, eta), 2) + + pow(getFractionDropped(1, m_trkEffHistLoosePP0, pt, eta), 2) + + pow(getFractionDropped(1, m_trkEffHistLoosePhysModel, pt, eta), 2) ); + if(m_rnd->Uniform(0, 1) < fTrkEffSyst) return false; + } + if ( isActive( TRK_EFF_TIGHT_COMBINED ) ) { + float fTrkEffSyst = sqrt( pow(getFractionDropped(1, m_trkEffHistTightGlobal, pt, eta), 2) + + pow(getFractionDropped(1, m_trkEffHistTightIBL, pt, eta), 2) + + pow(getFractionDropped(1, m_trkEffHistTightPP0, pt, eta), 2) + + pow(getFractionDropped(1, m_trkEffHistTightPhysModel, pt, eta), 2) ); + if(m_rnd->Uniform(0, 1) < fTrkEffSyst) return false; } } @@ -402,62 +289,6 @@ namespace InDet { return hist->GetBinContent(hist->FindBin(pt, track->eta())); } - // this is where the calculation of the fake probability is done if you are not using truth info to determine whether a track is fake - - float InDetTrackTruthFilterTool::pseudoFakeProbability(const xAOD::TrackParticle* track, float mu) const { - - float pt = track->pt(); - float d0 = track->d0(); - - // make a function to determine which tracks we will classify as fake, parameters determined from fit to full-truth MC16e ttbar - float fakeProb = 0.01; - // this is the mu dependence part - if(mu>20) { - float p0 = 0.008645; - float p1 = 0.0001114; - float p2 = 9.299e-6; - fakeProb = p0 + (p1*mu) + (p2*mu*mu); - } - - // now we add the pT term - float pTcorr = 0.02; - if(pt<50000) { - float p0 = 0.02; - float p1 = -3.564; - float p2 = -0.0005982; - float param = p1 + (p2 * pt); - pTcorr = p0 + std::exp(param); - } - - fakeProb*=pTcorr; - - float d0corr = 1; - d0corr = std::tanh(std::abs(d0)); - - fakeProb*=d0corr; - - // multiply by empirical ad hoc rescaling factor - // to give correct overall probability - fakeProb*=309.602; - - return fakeProb; - - } - - bool InDetTrackTruthFilterTool::dropPseudoFake(float prob) const { - - bool isFake = false; - if(m_rnd->Uniform(0, 1) < prob) isFake=true; - - // Now, if we've decided if this is a fake, we apply the uncertainty - if(isFake){ - if(m_rnd->Uniform(0, 1) < m_fFakeLoose) return true; // drop this track - } - - return false; - - } - bool InDetTrackTruthFilterTool::isAffectedBySystematic( const CP::SystematicVariation& syst ) const { return InDetTrackSystematicsTool::isAffectedBySystematic( syst ); diff --git a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InclusiveTrackFilterTool.cxx b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InclusiveTrackFilterTool.cxx index b0a838b1b6ceb296ce362b0ebb30eaa4e8afcb15..8925697bd9a3b64c6fcc11bc5101395f3dd2ba4f 100644 --- a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InclusiveTrackFilterTool.cxx +++ b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/Root/InclusiveTrackFilterTool.cxx @@ -23,9 +23,13 @@ namespace InDet { StatusCode InclusiveTrackFilterTool::initialize() { - m_rnd = std::make_unique<TRandom3>(m_seed); + if (m_calibFileLRTEff.empty()) { + ATH_MSG_ERROR("No calibration file for requested LRT track efficiency set. You may be running an unsupported datataking period, please contact Tracking CP if you believe this message is in error."); + return StatusCode::FAILURE; + } + TH2* trkLRTEff_tmp = nullptr; ATH_CHECK( initObject<TH2>( trkLRTEff_tmp, m_calibFileLRTEff, diff --git a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/python/InDetTrackSystematicsToolsConfig.py b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/python/InDetTrackSystematicsToolsConfig.py index 37854067a34f1cb2b4172db853c08d5a995ca9c5..fdb4a3517f5173ff5e95d0a64f590090d90cdadb 100644 --- a/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/python/InDetTrackSystematicsToolsConfig.py +++ b/PhysicsAnalysis/TrackingID/InDetTrackSystematicsTools/python/InDetTrackSystematicsToolsConfig.py @@ -2,6 +2,8 @@ # Configuration of InDetTrackSystematicsTools package from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory +from Campaigns.Utils import Campaign +from AthenaCommon.Logging import logging def InDetTrackTruthOriginToolCfg(flags, name="InDetTrackTruthOriginTool", **kwargs): acc = ComponentAccumulator() @@ -18,9 +20,26 @@ def InDetTrackTruthOriginToolCfg(flags, name="InDetTrackTruthOriginTool", **kwar def InDetTrackTruthFilterToolCfg(flags, name="InDetTrackTruthFilterTool", **kwargs): acc = ComponentAccumulator() + log = logging.getLogger("InDetTrackTruthFilterToolCfg") + if "trackOriginTool" not in kwargs: kwargs.setdefault("trackOriginTool", acc.popToolsAndMerge( InDetTrackTruthOriginToolCfg(flags))) + + from AthenaConfiguration.Enums import LHCPeriod + # 2022 recommendations (MC23a) + if flags.GeoModel.Run == LHCPeriod.Run3: + if flags.Input.MCCampaign == Campaign.MC23a: + kwargs.setdefault("calibFileNomEff", "InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root") + kwargs.setdefault("fFakeLoose", 0.40) + kwargs.setdefault("fFakeTight", 1.00) + # Run 2 recommendations (MC20) + elif flags.GeoModel.Run == LHCPeriod.Run2: + kwargs.setdefault("calibFileNomEff", "InDetTrackSystematicsTools/CalibData_22.0_2022-v00/TrackingRecommendations_prelim_rel22.root") + kwargs.setdefault("fFakeLoose", 0.10) + kwargs.setdefault("fFakeTight", 1.00) + else: + log.warning("InDetTrackTruthFilterTool: Recommendations not yet available for this campaign! Please check the configuration and contact Tracking CP if you believe this message is in error.") acc.setPrivateTools( CompFactory.InDet.InDetTrackTruthFilterTool(name, **kwargs)) @@ -46,6 +65,20 @@ def JetTrackFilterToolCfg(flags, name="JetTrackFilterTool", **kwargs): def InclusiveTrackFilterToolCfg(flags, name="InclusiveTrackFilterTool", **kwargs): acc = ComponentAccumulator() + + log = logging.getLogger("InclusiveTrackFilterToolCfg") + + from AthenaConfiguration.Enums import LHCPeriod + # 2022 recommendations (MC23a) + if flags.GeoModel.Run == LHCPeriod.Run3: + if flags.Input.MCCampaign == Campaign.MC23a: + kwargs.setdefault("calibFileLRTEff", "InDetTrackSystematicsTools/CalibData_25.2_2025-v00/LargeD0TrackingRecommendations_mc23a.root") + # Run 2 recommendations (MC20) + elif flags.GeoModel.Run == LHCPeriod.Run2: + kwargs.setdefault("calibFileLRTEff", "InDetTrackSystematicsTools/CalibData_24.0_2023-v00/LargeD0TrackingRecommendations_20230824.root") + else: + log.warning("InclusiveTrackFilterTool: Recommendations not yet available for this campaign! Please check the configuration and contact Tracking CP if you believe this message is in error.") + acc.setPrivateTools( CompFactory.InDet.InclusiveTrackFilterTool(name, **kwargs)) return acc