diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/data/trkAnaConfigs_example.json b/InnerDetector/InDetValidation/InDetTrackPerfMon/data/trkAnaConfigs_example.json index cd245cc18d357fe7692cd7cc5179f266389be66d..dba349eb08ebb40fe07052de9ee7f08961cdd447 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/data/trkAnaConfigs_example.json +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/data/trkAnaConfigs_example.json @@ -24,14 +24,15 @@ "TrkAnaTrigEle" : { "enabled" : true, "TestType" : "Trigger", - "RefType" : "OfflineElectron", + "RefType" : "Offline", "TrigTrkKey" : "HLT_IDTrack_Electron_IDTrig", "ChainNames" : [ "HLT_e.*_idperf_.*" ], "MatchingType" : "DeltaRMatch", "dRmax" : 0.05, "pTResMax" : -9.9, "SubFolder" : "TrkAnaTrigEle/", - "ObjectQuality" : "Tight", + "SelectOfflineObject" : "Electron", + "ObjectQuality" : "Tight", "doOfflineElectrons" : true }, "TrkAnaOffl1" : { diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetAlgorithmConfig.py b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetAlgorithmConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..be97ac9825423c1376053ad48abd003a2e0e04b9 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetAlgorithmConfig.py @@ -0,0 +1,130 @@ +# +# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +# + +'''@file InDetAlgorithmConfig.py +@author M. Aparo +@date 02-10-2023 +@brief CA-based python configurations for the event algorithms in this package +''' + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + + +def TruthHitDecoratorAlgCfg( flags, name="TruthHitDecoratorAlg", **kwargs ): + ''' + create decoration algorithm which decorates + truth particles with track parameters at the perigee. + ''' + acc = ComponentAccumulator() + + from TrkConfig.AtlasExtrapolatorConfig import AtlasExtrapolatorCfg + extrapolator = acc.popToolsAndMerge( AtlasExtrapolatorCfg(flags) ) + acc.addPublicTool( extrapolator ) + kwargs.setdefault( "Extrapolator", extrapolator ) + + acc.addEventAlgo( CompFactory.IDTPM.TruthHitDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineElectronDecoratorAlgCfg( flags, name="OfflineElectronDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + acc.addEventAlgo( CompFactory.IDTPM.OfflineElectronDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineElectronGSFDecoratorAlgCfg( flags, name="OfflineElectronGSFDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + kwargs.setdefault( "OfflineTrkParticleContainerName", "GSFTrackParticles" ) + kwargs.setdefault( "useGSF", True ) + acc.addEventAlgo( CompFactory.IDTPM.OfflineElectronDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineMuonDecoratorAlgCfg( flags, name="OfflineMuonDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + acc.addEventAlgo( CompFactory.IDTPM.OfflineMuonDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineMuonCombDecoratorAlgCfg( flags, name="OfflineMuonDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + kwargs.setdefault( "OfflineTrkParticleContainerName", "CombinedMuonTrackParticles" ) + kwargs.setdefault( "useCombinedMuonTracks", True ) + acc.addEventAlgo( CompFactory.IDTPM.OfflineMuonDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineTauBDT1prongDecoratorAlgCfg( flags, name="OfflineTauBDT1prongDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + kwargs.setdefault( "Prefix", "LinkedTauBDT1prong_" ) + kwargs.setdefault( "TauType", "BDT" ) + kwargs.setdefault( "TauNprongs", 1 ) + acc.addEventAlgo( CompFactory.IDTPM.OfflineTauDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineTauBDT3prongDecoratorAlgCfg( flags, name="OfflineTauBDT3prongDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + kwargs.setdefault( "Prefix", "LinkedTauBDT3prong_" ) + kwargs.setdefault( "TauType", "BDT" ) + kwargs.setdefault( "TauNprongs", 3 ) + acc.addEventAlgo( CompFactory.IDTPM.OfflineTauDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineTauRNN1prongDecoratorAlgCfg( flags, name="OfflineTauRNN1prongDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + kwargs.setdefault( "Prefix", "LinkedTauRNN1prong_" ) + kwargs.setdefault( "TauType", "RNN" ) + kwargs.setdefault( "TauNprongs", 1 ) + acc.addEventAlgo( CompFactory.IDTPM.OfflineTauDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineTauRNN3prongDecoratorAlgCfg( flags, name="OfflineTauRNN3prongDecoratorAlg", **kwargs ): + acc = ComponentAccumulator() + kwargs.setdefault( "Prefix", "LinkedTauRNN3prong_" ) + kwargs.setdefault( "TauType", "RNN" ) + kwargs.setdefault( "TauNprongs", 3 ) + acc.addEventAlgo( CompFactory.IDTPM.OfflineTauDecoratorAlg( name, **kwargs ) ) + return acc + + +def OfflineObjectDecoratorAlgCfg( flags, name="OfflineObjectDecoratorAlg", **kwargs ): + ''' + create decoration algorithm(s) to decorate offline tracks with a link to + the offline object they correspond to in the event reconstruction + ''' + acc = ComponentAccumulator() + + objStrList = [] + tauTypeList = [] + for trkAnaName in flags.PhysVal.IDTPM.trkAnaNames: + objStr = getattr( flags.PhysVal.IDTPM, trkAnaName+".SelectOfflineObject" ) + if objStr : objStrList.append( objStr ) + tauType = getattr( flags.PhysVal.IDTPM, trkAnaName+".TauType" ) + if tauType : tauTypeList.append( tauType ) + + if "Electron" in objStrList: + acc.merge( OfflineElectronDecoratorAlgCfg(flags) ) + + if "ElectronGSF" in objStrList: + acc.merge( OfflineElectronGSFDecoratorAlgCfg(flags) ) + + if "Muon" in objStrList: + acc.merge( OfflineMuonDecoratorAlgCfg(flags) ) + + if "MuonComb" in objStrList: + acc.merge( OfflineMuonCombDecoratorAlgCfg(flags) ) + + if "Tau" in objStrList: + if "BDT" in tauTypeList: + acc.merge( OfflineTauBDT1prongDecoratorAlgCfg(flags) ) + acc.merge( OfflineTauBDT3prongDecoratorAlgCfg(flags) ) + if "RNN" in tauTypeList: + acc.merge( OfflineTauRNN1prongDecoratorAlgCfg(flags) ) + acc.merge( OfflineTauRNN3prongDecoratorAlgCfg(flags) ) + + return acc diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetSelectionConfig.py b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetSelectionConfig.py index 5be95a37c936442212a9dbb3117b4f036e1e7f95..73ff69e103b2ad17446ba22b0aa5c5e3f60b7fd4 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetSelectionConfig.py +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetSelectionConfig.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration # '''@file InDetSelectionConfig.py @@ -40,35 +40,32 @@ def TrackRoiSelectionToolCfg( flags, name="TrackRoiSelectionTool", **kwargs ): return acc +def TrackObjectSelectionToolCfg( flags, name="TrackObjectSelectionTool", **kwargs ): + acc = ComponentAccumulator() + + objStr = flags.PhysVal.IDTPM.currentTrkAna.SelectOfflineObject + kwargs.setdefault( "ObjectType", objStr ) + kwargs.setdefault( "ObjectQuality", flags.PhysVal.IDTPM.currentTrkAna.ObjectQuality ) + + if "Tau" in objStr: + kwargs.setdefault( "TauType", flags.PhysVal.IDTPM.currentTrkAna.TauType ) + kwargs.setdefault( "TauNprongs", flags.PhysVal.IDTPM.currentTrkAna.TauNprongs ) + + acc.setPrivateTools( CompFactory.IDTPM.TrackObjectSelectionTool( name, **kwargs ) ) + return acc + + def TrackQualitySelectionToolCfg( flags, name="TrackQualitySelectionTool", **kwargs ): acc = ComponentAccumulator() - ## TODO - to be uncommented in later MRs ## offline track-object selection - #from InDetTrackPerfMon.ConfigUtils import getObjectStr - #if getObjectStr( flags ): - # kwargs.setdefault( "DoObjectSelection", True ) - # - # if "TrackObjectSelectionTool" not in kwargs: - # kwargs.setdefault( "TrackObjectSelectionTool", acc.popToolsAndMerge( - # InDetTrackObjectSelectionToolCfg( flags, - # name="TrackObjectSelectionTool" + flags.PhysVal.IDTPM.currentTrkAna.anaTag ) ) ) + if flags.PhysVal.IDTPM.currentTrkAna.SelectOfflineObject: + kwargs.setdefault( "DoObjectSelection", True ) + + if "TrackObjectSelectionTool" not in kwargs: + kwargs.setdefault( "TrackObjectSelectionTool", acc.popToolsAndMerge( + TrackObjectSelectionToolCfg( flags, + name="TrackObjectSelectionTool" + flags.PhysVal.IDTPM.currentTrkAna.anaTag ) ) ) acc.setPrivateTools( CompFactory.IDTPM.TrackQualitySelectionTool( name, **kwargs ) ) return acc - - -## TODO - to be uncommented in later MRs -#def InDetTrackObjectSelectionToolCfg( flags, name="TrackObjectSelectionTool", **kwargs ): -# acc = ComponentAccumulator() -# -# from InDetTrackPerfMon.ConfigUtils import getObjectStr -# objectStr = getObjectStr( flags ) -# kwargs.setdefault( "ObjectType", objectStr ) -# kwargs.setdefault( "ObjectQuality", flags.PhysVal.IDTPM.currentTrkAna.ObjectQuality ) -# if "Tau" in objectStr: -# kwargs.setdefault( "TauType", flags.PhysVal.IDTPM.currentTrkAna.TauType ) -# kwargs.setdefault( "TauNprongs", flags.PhysVal.IDTPM.currentTrkAna.TauNprongs ) -# -# acc.setPrivateTools( CompFactory.IDTPM.InDetTrackObjectSelectionTool( name, **kwargs ) ) -# return acc diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonConfig.py b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonConfig.py index 88d367a05f3e763cfb00602462edff4a6fbfeec4..3c25188b77aee98db5d997b9eac8b413c24d0ecf 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonConfig.py +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonConfig.py @@ -128,19 +128,27 @@ def InDetTrackPerfMonCfg( flags ): ## Configuring IDTPM tool instances tools = [] - ## TODO - to be uncommented in future MRs - #useTruth = False - #for trkAnaName in flags.PhysVal.IDTPM.trkAnaNames : - # if "Truth" in getattr( flags.PhysVal.IDTPM, trkAnaName+".RefType" ) : - # useTruth = True - #if useTruth: - # acc.merge( InDetTruthDecoratorAlgCfg(flags) ) - - ## TODO - to be uncommented in future MRs - ## true only if offline objects are requested in any scheduled trkAnalysis - #if getObjectStrList(flags): - # from InDetTrackPerfMon.InDetOfflineObjectDecoratorAlgConfig import InDetOfflineObjectDecoratorAlgCfg - # acc.merge( InDetOfflineObjectDecoratorAlgCfg(flags) ) + useTruth = False + useOfflineObject = False + for trkAnaName in flags.PhysVal.IDTPM.trkAnaNames : + if "Truth" in getattr( flags.PhysVal.IDTPM, trkAnaName+".RefType" ): + useTruth = True + break + if getattr( flags.PhysVal.IDTPM, trkAnaName+".SelectOfflineObject" ): + if "Truth" in getattr( flags.PhysVal.IDTPM, trkAnaName+".SelectOfflineObject" ): + continue # Do not schedule algorithm for Truth-match offline selection + useOfflineObject = True + break + + ## Truth-hit decorator + if useTruth: + from InDetTrackPerfMon.InDetAlgorithmConfig import TruthHitDecoratorAlgCfg + acc.merge( TruthHitDecoratorAlgCfg(flags) ) + + ## Offline track-object decorator + if useOfflineObject: + from InDetTrackPerfMon.InDetAlgorithmConfig import OfflineObjectDecoratorAlgCfg + acc.merge( OfflineObjectDecoratorAlgCfg(flags) ) for trkAnaName in flags.PhysVal.IDTPM.trkAnaNames: ## cloning flags of current TrackAnalysis to PhysVal.IDTPM.currentTrkAna diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonFlags.py b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonFlags.py index 607803e358f72f02f3fc143933086717b6875083..3eece2d72c3df760e71bff3ef8077425ddb3e0e9 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonFlags.py +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/python/InDetTrackPerfMonFlags.py @@ -7,12 +7,12 @@ def createIDTPMConfigFlags(): from AthenaConfiguration.AthConfigFlags import AthConfigFlags icf = AthConfigFlags() - icf.addFlag("DirName", "InDetTrackPerfMonPlots/") - icf.addFlag("trkAnaNames", ["Default"]) - icf.addFlag("unpackTrigChains", False) - icf.addFlag("histoDefFormat", "JSON") - icf.addFlag("HistoDefFileList" , "InDetTrackPerfMon/HistoDefFileList_default.txt") - icf.addFlag("plotsCommonValuesFile", "InDetTrackPerfMon/IDTPMPlotCommonValues.json") + icf.addFlag( "DirName", "InDetTrackPerfMonPlots/" ) + icf.addFlag( "trkAnaNames", ["Default"] ) + icf.addFlag( "unpackTrigChains", False ) + icf.addFlag( "histoDefFormat", "JSON" ) + icf.addFlag( "HistoDefFileList" , "InDetTrackPerfMon/HistoDefFileList_default.txt" ) + icf.addFlag( "plotsCommonValuesFile", "InDetTrackPerfMon/IDTPMPlotCommonValues.json" ) return icf @@ -24,39 +24,39 @@ def createIDTPMTrkAnaConfigFlags(): icf = AthConfigFlags() # General properties - icf.addFlag("enabled", True) - icf.addFlag("anaTag", "") - icf.addFlag("SubFolder", "IDTPM/") + icf.addFlag( "enabled", True ) + icf.addFlag( "anaTag", "" ) + icf.addFlag( "SubFolder", "IDTPM/" ) # Test-Reference collections properties - icf.addFlag("TestType", "Offline") - icf.addFlag("RefType", "Truth") - icf.addFlag("TrigTrkKey" , "HLT_IDTrack_Electron_IDTrig") - icf.addFlag("OfflineTrkKey" , "InDetTrackParticles") - icf.addFlag("TruthPartKey" , "TruthParticles") + icf.addFlag( "TestType", "Offline" ) + icf.addFlag( "RefType", "Truth" ) + icf.addFlag( "TrigTrkKey" , "HLT_IDTrack_Electron_IDTrig" ) + icf.addFlag( "OfflineTrkKey" , "InDetTrackParticles" ) + icf.addFlag( "TruthPartKey" , "TruthParticles" ) # Matching properties - icf.addFlag("MatchingType" , "DeltaRMatch") - icf.addFlag("dRmax" , 0.05) - icf.addFlag("pTResMax" , -9.9) + icf.addFlag( "MatchingType" , "DeltaRMatch" ) + icf.addFlag( "dRmax" , 0.05 ) + icf.addFlag( "pTResMax" , -9.9 ) # Trigger-specific properties - icf.addFlag("ChainNames" , []) - icf.addFlag("RoiKey" , "") - icf.addFlag("ChainLeg" , -1) - icf.addFlag("doTagNProbe" , False) - icf.addFlag("RoiKeyTag" , "") - icf.addFlag("ChainLegTag" , 0) - icf.addFlag("RoiKeyProbe" , "") - icf.addFlag("ChainLegProbe" , 1) + icf.addFlag( "ChainNames" , [] ) + icf.addFlag( "RoiKey" , "" ) + icf.addFlag( "ChainLeg" , -1 ) + icf.addFlag( "doTagNProbe" , False ) + icf.addFlag( "RoiKeyTag" , "" ) + icf.addFlag( "ChainLegTag" , 0 ) + icf.addFlag( "RoiKeyProbe" , "" ) + icf.addFlag( "ChainLegProbe" , 1 ) # Offline tracks selection properties - icf.addFlag("ObjectQuality" , "Medium") - icf.addFlag("TauType" , "RNN") - icf.addFlag("TauNprongs" , 1) - icf.addFlag("TruthMatchedOnly" , False) + icf.addFlag( "SelectOfflineObject", "" ) + icf.addFlag( "ObjectQuality" , "Medium" ) + icf.addFlag( "TauType" , "RNN" ) + icf.addFlag( "TauNprongs" , 1 ) # ... # Truth particles selection properties # ... # Histogram properties - icf.addFlag("doTrackParameters" , True) - icf.addFlag("doEfficiencies" , True) - icf.addFlag("doOfflineElectrons" , False) + icf.addFlag( "doTrackParameters" , True ) + icf.addFlag( "doEfficiencies" , True ) + icf.addFlag( "doOfflineElectrons" , False ) return icf diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/InDetTrackPerfMonTool.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/InDetTrackPerfMonTool.cxx index 2ee8a2134d3d3348b4d925353d16fcf53eba9de5..a0e105c41cec115067bab6ea5b67103b9634fb50 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/InDetTrackPerfMonTool.cxx +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/InDetTrackPerfMonTool.cxx @@ -8,7 +8,7 @@ **/ /// local include -#include "InDetTrackPerfMon/InDetTrackPerfMonTool.h" +#include "InDetTrackPerfMonTool.h" /// gaudi includes #include "GaudiKernel/SystemOfUnits.h" @@ -231,7 +231,7 @@ StatusCode InDetTrackPerfMonTool::fillHistograms() { unsigned decisionType = TrigDefs::Physics; // TrigDefs::includeFailedDecisions; /// skipping TrkAnalysis if chain is not passed for this event - if( thisChain != "" and thisChain != "Offline" and m_trkAnaDefSvc->useTrigger() ) { + if( !thisChain.empty() and thisChain != "Offline" and m_trkAnaDefSvc->useTrigger() ) { if( not m_trigDecTool->isPassed( thisChain, decisionType ) ) { ATH_MSG_DEBUG( "Trigger chain " << thisChain << " is not fired. Skipping" ); continue; diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/InDetTrackPerfMonTool.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/InDetTrackPerfMonTool.h similarity index 95% rename from InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/InDetTrackPerfMonTool.h rename to InnerDetector/InDetValidation/InDetTrackPerfMon/src/InDetTrackPerfMonTool.h index 7d41950ae1c2c4781708111840755adc327aacfc..939bb090996f76c28fa2bfa4fafd58b7a20da174 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/InDetTrackPerfMonTool.h +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/InDetTrackPerfMonTool.h @@ -25,12 +25,10 @@ /// local includes #include "InDetTrackPerfMon/ITrackAnalysisDefinitionSvc.h" -#include "InDetTrackPerfMon/TrackAnalysisCollections.h" -#include "InDetTrackPerfMon/RoiSelectionTool.h" +#include "../src/TrackAnalysisCollections.h" +#include "../src/RoiSelectionTool.h" #include "InDetTrackPerfMon/ITrackSelectionTool.h" /// TODO - To be included in later MRs -//#include "InDetTrackPerfMon/InDetObjectDecorHelper.h" -//#include "InDetTrackPerfMon/TrackRoiSelectionTool.h" //#include "InDetTrackPerfMon/ITrackMatchingTool.h" //#include "InDetTrackPerfMon/TrackAnalysisPlotsMgr.h" diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineElectronDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineElectronDecoratorAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a8dfbe7acd215d0bd7dddb593ffde7069e4d1afd --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineElectronDecoratorAlg.cxx @@ -0,0 +1,154 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file OfflineElectronDecoratorAlg.cxx + * @author Marco Aparo <marco.aparo@cern.ch> + **/ + +/// Local includes +#include "OfflineElectronDecoratorAlg.h" + +/// xAOD includes +#include "xAODEgamma/ElectronxAODHelpers.h" // xAOD::EgammaHelpers::getOriginalTrackParticle + + +///---------------------------------------- +///------- Parametrized constructor ------- +///---------------------------------------- +IDTPM::OfflineElectronDecoratorAlg::OfflineElectronDecoratorAlg( + const std::string& name, + ISvcLocator* pSvcLocator ) : + AthReentrantAlgorithm( name, pSvcLocator ) { } + + +///-------------------------- +///------- initialize ------- +///-------------------------- +StatusCode IDTPM::OfflineElectronDecoratorAlg::initialize() { + + ATH_CHECK( m_offlineTrkParticlesName.initialize( + not m_offlineTrkParticlesName.key().empty() ) ); + + ATH_CHECK( m_electronsName.initialize( not m_electronsName.key().empty() ) ); + + /// Create decorations for original (non GSF) ID tracks + IDTPM::createDecoratorKeysAndAccessor( + *this, m_offlineTrkParticlesName, + m_prefix.value(), m_decor_ele_names, m_decor_ele ); + + if( m_decor_ele.size() != NDecorations ) { + ATH_MSG_ERROR( "Incorrect booking of electron decorations" ); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + + +///----------------------- +///------- execute ------- +///----------------------- +StatusCode IDTPM::OfflineElectronDecoratorAlg::execute( const EventContext& ctx ) const { + + /// retrieve offline track particle container + SG::ReadHandle< xAOD::TrackParticleContainer > ptracks( m_offlineTrkParticlesName, ctx ); + if( not ptracks.isValid() ) { + ATH_MSG_ERROR( "Failed to retrieve track particles container" ); + return StatusCode::FAILURE; + } + + /// retrieve electron container + SG::ReadHandle< xAOD::ElectronContainer > pelectrons( m_electronsName, ctx ); + if( not pelectrons.isValid() ) { + ATH_MSG_ERROR( "Failed to retrieve electrons container" ); + return StatusCode::FAILURE; + } + + std::vector< IDTPM::OptionalDecoration<xAOD::TrackParticleContainer, ElementElectronLink_t> > + ele_decor( IDTPM::createDecoratorsIfNeeded( *ptracks, m_decor_ele, ctx ) ); + + if( ele_decor.empty() ) { + ATH_MSG_ERROR( "Failed to book electron decorations" ); + return StatusCode::FAILURE; + } + + for( const xAOD::TrackParticle* track : *ptracks ) { + /// decorate current track with electron ElementLink(s) + ATH_CHECK( decorateElectronTrack( *track, ele_decor, *pelectrons.ptr() ) ); + } + + return StatusCode::SUCCESS; +} + + +///------------------------------- +///---- decorateElectronTrack ---- +///------------------------------- +StatusCode IDTPM::OfflineElectronDecoratorAlg::decorateElectronTrack( + const xAOD::TrackParticle& track, + std::vector< IDTPM::OptionalDecoration< xAOD::TrackParticleContainer, + ElementElectronLink_t > >& ele_decor, + const xAOD::ElectronContainer& electrons ) const { + + /// loop electron container to look for electron reconstructed with track + for( const xAOD::Electron* electron : electrons ) { + + /// retrieve TrackParticle from electron + const xAOD::TrackParticle* eleTrack = m_useGSF.value() ? + electron->trackParticle() : // with GSF + xAOD::EgammaHelpers::getOriginalTrackParticle( electron ); // no GSF + + if( not eleTrack ) { + ATH_MSG_ERROR( "Corrupted matching electron ID track" ); + return StatusCode::FAILURE; + } + + if( eleTrack == &track ) { + /// Create electron element link + ElementElectronLink_t eleLink; + eleLink.toContainedElement( electrons, electron ); + + ATH_MSG_DEBUG( "Found matching electron (e=" << electron->e() << "). Decorating track." ); + + /// Decoration for All electron (no quality selection) + IDTPM::decorateOrRejectQuietly( track, ele_decor[All], eleLink ); + + /// Decoration for Tight electron + if( electron->passSelection("Tight") ) { + IDTPM::decorateOrRejectQuietly( track, ele_decor[Tight], eleLink ); + } + + /// Decoration for Medium electron + if( electron->passSelection("Medium") ) { + IDTPM::decorateOrRejectQuietly( track, ele_decor[Medium], eleLink ); + } + + /// Decoration for Loose electron + if( electron->passSelection("Loose") ) { + IDTPM::decorateOrRejectQuietly( track, ele_decor[Loose], eleLink ); + } + + /// Decoration for LHTight electron + if( electron->passSelection("LHTight") ) { + IDTPM::decorateOrRejectQuietly( track, ele_decor[LHTight], eleLink ); + } + + /// Decoration for LHMedium electron + if( electron->passSelection("LHMedium") ) { + IDTPM::decorateOrRejectQuietly( track, ele_decor[LHMedium], eleLink ); + } + + /// Decoration for LHLoose electron + if( electron->passSelection("LHLoose") ) { + IDTPM::decorateOrRejectQuietly( track, ele_decor[LHLoose], eleLink ); + } + + return StatusCode::SUCCESS; + } // if( eleTrack == &track ) + + } // close electron loop + + return StatusCode::SUCCESS; +} diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineElectronDecoratorAlg.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineElectronDecoratorAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..a02f6f70d2b21b83c9cec683ee8244c07aeead25 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineElectronDecoratorAlg.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_OFFLINEELECTRONDECORATORALG_H +#define INDETTRACKPERFMON_OFFLINEELECTRONDECORATORALG_H + +/** + * @file OfflineElectronDecoratorAlg.h + * @brief Algorithm to decorate offline tracks with the corresponding + * offline electron object (if required for trigger analysis) + * @author Marco Aparo <marco.aparo@cern.ch> + * @date 25 September 2023 + **/ + +/// Athena includes +#include "AthenaBaseComps/AthReentrantAlgorithm.h" + +/// xAOD includes +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODEgamma/ElectronContainer.h" + +/// STL includes +#include <string> +#include <vector> + +/// Local includes +#include "SafeDecorator.h" + + +namespace IDTPM { + + class OfflineElectronDecoratorAlg : + public AthReentrantAlgorithm { + + public: + + typedef ElementLink<xAOD::ElectronContainer> ElementElectronLink_t; + + OfflineElectronDecoratorAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + virtual ~OfflineElectronDecoratorAlg() = default; + + virtual StatusCode initialize() override; + + virtual StatusCode execute( const EventContext& ctx ) const override; + + private: + + SG::ReadHandleKey<xAOD::TrackParticleContainer> m_offlineTrkParticlesName { + this, "OfflineTrkParticleContainerName", "InDetTrackParticles", "Name of container of offline tracks" }; + + StringProperty m_prefix{ this, "Prefix", "LinkedElectron_", "Decoration prefix to avoid clashes" }; + + StatusCode decorateElectronTrack( + const xAOD::TrackParticle& track, + std::vector< IDTPM::OptionalDecoration< xAOD::TrackParticleContainer, + ElementElectronLink_t > >& ele_decor, + const xAOD::ElectronContainer& electrons ) const; + + SG::ReadHandleKey<xAOD::ElectronContainer> m_electronsName { + this, "ElectronContainerName", "Electrons", "Name of container of offline electrons" }; + + BooleanProperty m_useGSF { this, "useGSF", false, "Match electron with original ID track after GSF" }; + + enum ElectronDecorations : size_t { + All, + Tight, + Medium, + Loose, + LHTight, + LHMedium, + LHLoose, + NDecorations + }; + + const std::vector< std::string > m_decor_ele_names { + "All", + "Tight", + "Medium", + "Loose", + "LHTight", + "LHMedium", + "LHLoose" + }; + + std::vector< IDTPM::WriteKeyAccessorPair< xAOD::TrackParticleContainer, + ElementElectronLink_t > > m_decor_ele{}; + +}; + +} // namespace IDTPM + +#endif // > !INDETTRACKPERFMON_OFFLINEELECTRONDECORATORALG_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineMuonDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineMuonDecoratorAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3f802ac778bc961f0896803e1e7043fcb22ced87 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineMuonDecoratorAlg.cxx @@ -0,0 +1,145 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file OfflineMuonDecoratorAlg.cxx + * @author Marco Aparo <marco.aparo@cern.ch> + **/ + +/// Local includes +#include "OfflineMuonDecoratorAlg.h" + + +///---------------------------------------- +///------- Parametrized constructor ------- +///---------------------------------------- +IDTPM::OfflineMuonDecoratorAlg::OfflineMuonDecoratorAlg( + const std::string& name, + ISvcLocator* pSvcLocator ) : + AthReentrantAlgorithm( name, pSvcLocator ) { } + + +///---------------------------------- +///------- General initialize ------- +///---------------------------------- +StatusCode IDTPM::OfflineMuonDecoratorAlg::initialize() { + + ATH_CHECK( m_offlineTrkParticlesName.initialize( + not m_offlineTrkParticlesName.key().empty() ) ); + + /// Muon collection, if required + ATH_CHECK( m_muonsName.initialize( not m_muonsName.key().empty() ) ); + + /// Create decorations for original ID tracks + IDTPM::createDecoratorKeysAndAccessor( + *this, m_offlineTrkParticlesName, + m_prefix.value(), m_decor_mu_names, m_decor_mu ); + + if( m_decor_mu.size() != NDecorations ) { + ATH_MSG_ERROR( "Incorrect booking of muon decorations" ); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + + +///----------------------- +///------- execute ------- +///----------------------- +StatusCode IDTPM::OfflineMuonDecoratorAlg::execute( const EventContext& ctx ) const { + + /// retrieve offline track particle container + SG::ReadHandle< xAOD::TrackParticleContainer > ptracks( m_offlineTrkParticlesName, ctx ); + if( not ptracks.isValid() ) { + ATH_MSG_ERROR( "Failed to retrieve track particles container" ); + return StatusCode::FAILURE; + } + + /// retrieve muon container + SG::ReadHandle< xAOD::MuonContainer > pmuons( m_muonsName, ctx ); + if( not pmuons.isValid() ) { + ATH_MSG_ERROR( "Failed to retrieve muons container" ); + return StatusCode::FAILURE; + } + + std::vector< IDTPM::OptionalDecoration<xAOD::TrackParticleContainer, ElementMuonLink_t> > + mu_decor( IDTPM::createDecoratorsIfNeeded( *ptracks, m_decor_mu, ctx ) ); + + if( mu_decor.empty() ) { + ATH_MSG_ERROR( "Failed to book muon decorations" ); + return StatusCode::FAILURE; + } + + for( const xAOD::TrackParticle* track : *ptracks ) { + /// decorate current track with muon ElementLink(s) + ATH_CHECK( decorateMuonTrack( *track, mu_decor, *pmuons.ptr() ) ); + } + + return StatusCode::SUCCESS; +} + + +///--------------------------- +///---- decorateMuonTrack ---- +///--------------------------- +StatusCode IDTPM::OfflineMuonDecoratorAlg::decorateMuonTrack( + const xAOD::TrackParticle& track, + std::vector< IDTPM::OptionalDecoration< xAOD::TrackParticleContainer, + ElementMuonLink_t > >& mu_decor, + const xAOD::MuonContainer& muons ) const { + + /// loop muon container to look for muon reconstructed with current ID track + for( const xAOD::Muon* muon : muons ) { + + /// Exclude non-Combined muons + if( muon->muonType() != xAOD::Muon::Combined ) continue; + + /// retrieve ID TrackParticle from muon + const xAOD::TrackParticle* muTrack = m_useCombinedMuonTracks.value() ? + *( muon->combinedTrackParticleLink() ) : // Combined track + *( muon->inDetTrackParticleLink() ); // ID track + + if( not muTrack ) { + ATH_MSG_ERROR( "Corrupted matched muon ID track" ); + return StatusCode::FAILURE; + } + + if( muTrack == &track ) { + /// Create muon element link + ElementMuonLink_t muLink; + muLink.toContainedElement( muons, muon ); + + ATH_MSG_DEBUG( "Found matched muon (pt=" << muon->pt() << "). Decorating track." ); + + /// Decoration for All muon (no quality selection) + IDTPM::decorateOrRejectQuietly( track, mu_decor[All], muLink ); + + /// Decoration for Tight muon + if( muon->quality() <= xAOD::Muon::Tight ) { + IDTPM::decorateOrRejectQuietly( track, mu_decor[Tight], muLink ); + } + + /// Decoration for Medium muon + if( muon->quality() <= xAOD::Muon::Medium ) { + IDTPM::decorateOrRejectQuietly( track, mu_decor[Medium], muLink ); + } + + /// Decoration for Loose muon + if( muon->quality() <= xAOD::Muon::Loose ) { + IDTPM::decorateOrRejectQuietly( track, mu_decor[Loose], muLink ); + } + + /// Decoration for VeryLoose muon + if( muon->quality() <= xAOD::Muon::VeryLoose ) { + IDTPM::decorateOrRejectQuietly( track, mu_decor[VeryLoose], muLink ); + } + + return StatusCode::SUCCESS; + } // if( muTrack == &track ) + + } // close muon loop + + return StatusCode::SUCCESS; +} diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineMuonDecoratorAlg.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineMuonDecoratorAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..da39a658d4a11647e43e74fd238e63554b1a4103 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineMuonDecoratorAlg.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_OFFLINEMUONDECORATORALG_H +#define INDETTRACKPERFMON_OFFLINEMUONDECORATORALG_H + +/** + * @file OfflineMuonDecoratorAlg.h + * @brief Algorithm to decorate offline tracks with the corresponding + * offline muon object (if required for trigger analysis) + * @author Marco Aparo <marco.aparo@cern.ch> + * @date 25 September 2023 + **/ + +/// Athena includes +#include "AthenaBaseComps/AthReentrantAlgorithm.h" + +/// xAOD includes +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODMuon/MuonContainer.h" + +/// STL includes +#include <string> +#include <vector> + +/// Local includes +#include "SafeDecorator.h" + + +namespace IDTPM { + + class OfflineMuonDecoratorAlg : + public AthReentrantAlgorithm { + + public: + + typedef ElementLink<xAOD::MuonContainer> ElementMuonLink_t; + + OfflineMuonDecoratorAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + virtual ~OfflineMuonDecoratorAlg() = default; + + virtual StatusCode initialize() override; + + virtual StatusCode execute( const EventContext& ctx ) const override; + + private: + + SG::ReadHandleKey<xAOD::TrackParticleContainer> m_offlineTrkParticlesName { + this, "OfflineTrkParticleContainerName", "InDetTrackParticles", "Name of container of offline tracks" }; + + StringProperty m_prefix { this, "Prefix", "LinkedMuon_", "Decoration prefix to avoid clashes" }; + + StatusCode decorateMuonTrack( + const xAOD::TrackParticle& track, + std::vector< IDTPM::OptionalDecoration< xAOD::TrackParticleContainer, + ElementMuonLink_t > >& mu_decor, + const xAOD::MuonContainer& muons ) const; + + SG::ReadHandleKey<xAOD::MuonContainer> m_muonsName { + this, "MuonContainerName", "Muons", "Name of container of offline muons" }; + + BooleanProperty m_useCombinedMuonTracks { + this, "useCombinedMuonTracks", false, "Match combined muon track to muons instead of ID tracks" }; + + enum MuonDecorations : size_t { + All, + Tight, + Medium, + Loose, + VeryLoose, + NDecorations + }; + + const std::vector< std::string > m_decor_mu_names { + "All", + "Tight", + "Medium", + "Loose", + "VeryLoose" + }; + + std::vector< IDTPM::WriteKeyAccessorPair< xAOD::TrackParticleContainer, + ElementMuonLink_t > > m_decor_mu{}; + + }; + +} // namespace IDTPM + +#endif // > ! INDETTRACKPERFMON_OFFLINEMUONDECORATORALG_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineObjectDecorHelper.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineObjectDecorHelper.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a295e76b0a505a98a4225c9e787ddc4638480e2f --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineObjectDecorHelper.cxx @@ -0,0 +1,67 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file OfflineObjectDecorHelper.cxx + * @author Marco Aparo <marco.aparo@cern.ch> + **/ + +/// local includes +#include "OfflineObjectDecorHelper.h" + + +namespace IDTPM { + + /// getLinkedElectron + const xAOD::Electron* getLinkedElectron( const xAOD::TrackParticle& track, + const std::string& quality ) { + std::string decoName = "LinkedElectron_" + quality; + return getLinkedObject< xAOD::ElectronContainer >( track, decoName ); + } + + + /// getLinkedMuon + const xAOD::Muon* getLinkedMuon( const xAOD::TrackParticle& track, + const std::string& quality ) { + std::string decoName = "LinkedMuon_" + quality; + return getLinkedObject< xAOD::MuonContainer >( track, decoName ); + } + + + /// getLinkedTau + const xAOD::TauJet* getLinkedTau( const xAOD::TrackParticle& track, + const int requiredNtracks, + const std::string& type, + const std::string& quality ) { + std::string decoName = "LinkedTau" + type + + std::to_string( requiredNtracks ) + "_" + quality; + return getLinkedObject< xAOD::TauJetContainer >( track, decoName ); + } + + + /// isUnlinkedTruth + bool isUnlinkedTruth( const xAOD::TrackParticle& track ) { + return isUnlinkedObject< xAOD::TruthParticleContainer >( + track, "truthParticleLink" ); + } + + + /// getTruthMatchProb + float getTruthMatchProb( const xAOD::TrackParticle& track ) { + return ( track.isAvailable< float >( "truthMatchProbability" ) ? + track.auxdata< float >( "truthMatchProbability" ) : -1. ); + } + + + /// getLinkedTruth + const xAOD::TruthParticle* getLinkedTruth( const xAOD::TrackParticle& track, + const float truthProbCut ) { + float prob = getTruthMatchProb( track ); + if( prob < truthProbCut ) return nullptr; + + return getLinkedObject< xAOD::TruthParticleContainer >( + track, "truthParticleLink" ); + } + +} // namespace IDTPM diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineObjectDecorHelper.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineObjectDecorHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..8583e9239f4db4048efa03b4b547ceb6bdcda047 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineObjectDecorHelper.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_OFFLINEOBJECTDECORHELPER_H +#define INDETTRACKPERFMON_OFFLINEOBJECTDECORHELPER_H + +/** + * @file OfflineObjectDecorHelper.h + * @brief Utility methods to access + * offline object decorations + * @author Marco Aparo <marco.aparo@cern.ch> + * @date 25 September 2023 + **/ + +/// xAOD includes +#include "xAODTracking/TrackParticle.h" +#include "xAODEgamma/ElectronContainer.h" +#include "xAODMuon/MuonContainer.h" +#include "xAODTau/TauJetContainer.h" +#include "xAODTruth/TruthParticleContainer.h" + +/// STL includes +#include <string> + + +namespace IDTPM { + + /// Templated method to check if a track is not linked to an object + template < typename container_t > + bool isUnlinkedObject( const xAOD::TrackParticle& track, + const std::string& decoName ) { + using elementLink_t = ElementLink< container_t >; + return ( not track.isAvailable< elementLink_t >( decoName ) ); + } + + /// Templated method to retrieve object linked to a track + template < typename container_t > + typename container_t::const_value_type getLinkedObject( + const xAOD::TrackParticle& track, + const std::string& decoName ) + { + using elementLink_t = ElementLink< container_t >; + + if( isUnlinkedObject< container_t >( track, decoName ) ) return nullptr; + + elementLink_t eleLink = track.auxdata< elementLink_t >( decoName ); + + if( not eleLink.isValid() ) return nullptr; + + return *eleLink; + } + + /// Non-templated methods + /// For offline electrons + const xAOD::Electron* getLinkedElectron( const xAOD::TrackParticle& track, + const std::string& quality="All" ); + + /// For offline muons + const xAOD::Muon* getLinkedMuon( const xAOD::TrackParticle& track, + const std::string& quality="All" ); + + /// For offline hadronic taus + const xAOD::TauJet* getLinkedTau( const xAOD::TrackParticle& track, + const int requiredNtracks, + const std::string& type="RNN", + const std::string& quality="" ); + + /// For truth particles + bool isUnlinkedTruth( const xAOD::TrackParticle& track ); + + float getLinkedTruthMatchProb( const xAOD::TrackParticle& track ); + + const xAOD::TruthParticle* getLinkedTruth( const xAOD::TrackParticle& track, + const float truthProbCut=0. ); + +} // namespace IDTPM + +#endif // > ! INDETTRACKPERFMON_OFFLINEOBJECTDECORHELPER_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineTauDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineTauDecoratorAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..030a1212de3b5f8d3c14f6ec4def269a082c7176 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineTauDecoratorAlg.cxx @@ -0,0 +1,194 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file OfflineTauDecoratorAlg.cxx + * @author Marco Aparo <marco.aparo@cern.ch> + **/ + +/// Local includes +#include "OfflineTauDecoratorAlg.h" + + +///---------------------------------------- +///------- Parametrized constructor ------- +///---------------------------------------- +IDTPM::OfflineTauDecoratorAlg::OfflineTauDecoratorAlg( + const std::string& name, + ISvcLocator* pSvcLocator ) : + AthReentrantAlgorithm( name, pSvcLocator ) { } + + +///-------------------------- +///------- initialize ------- +///-------------------------- +StatusCode IDTPM::OfflineTauDecoratorAlg::initialize() { + + ATH_CHECK( m_offlineTrkParticlesName.initialize( + not m_offlineTrkParticlesName.key().empty() ) ); + + ATH_CHECK( m_tausName.initialize( not m_tausName.key().empty() ) ); + + /// Create decorations for original ID tracks + IDTPM::createDecoratorKeysAndAccessor( + *this, m_offlineTrkParticlesName, + m_prefix.value(), m_decor_tau_names, m_decor_tau ); + + if( m_decor_tau.size() != NDecorations ) { + ATH_MSG_ERROR( "Incorrect booking of tau " << + m_tauType.value() << " " << + m_tauNprongs.value() << + "prong decorations" ); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + + +///----------------------- +///------- execute ------- +///----------------------- +StatusCode IDTPM::OfflineTauDecoratorAlg::execute( const EventContext& ctx ) const { + + /// retrieve offline track particle container + SG::ReadHandle< xAOD::TrackParticleContainer > ptracks( m_offlineTrkParticlesName, ctx ); + if( not ptracks.isValid() ) { + ATH_MSG_ERROR( "Failed to retrieve track particles container" ); + return StatusCode::FAILURE; + } + + /// retrieve tau container + SG::ReadHandle< xAOD::TauJetContainer > ptaus( m_tausName, ctx ); + if( not ptaus.isValid() ) { + ATH_MSG_ERROR( "Failed to retrieve taus container" ); + return StatusCode::FAILURE; + } + + std::vector< IDTPM::OptionalDecoration<xAOD::TrackParticleContainer, ElementTauLink_t> > + tau_decor( IDTPM::createDecoratorsIfNeeded( *ptracks, m_decor_tau, ctx ) ); + + if( tau_decor.empty() ) { + ATH_MSG_ERROR( "Failed to book tau " << + m_tauType.value() << " " << + m_tauNprongs.value() << + "prong decorations" ); + return StatusCode::FAILURE; + } + + for( const xAOD::TrackParticle* track : *ptracks ) { + /// decorate current track with tau ElementLink(s) + ATH_CHECK( decorateTauTrack( *track, tau_decor, *ptaus.ptr() ) ); + } + + return StatusCode::SUCCESS; +} + + +///-------------------------- +///---- decorateTauTrack ---- +///-------------------------- +StatusCode IDTPM::OfflineTauDecoratorAlg::decorateTauTrack( + const xAOD::TrackParticle& track, + std::vector< IDTPM::OptionalDecoration< xAOD::TrackParticleContainer, + ElementTauLink_t > >& tau_decor, + const xAOD::TauJetContainer& taus ) const { + + /// loop muon container to look for muon reconstructed with current ID track + for( const xAOD::TauJet* tau : taus ) { + + /// Select number of tau tracks (1prong or 3prong) + int NTauTracks = tau->nTracks(); + if( m_tauNprongs.value() > 0 and NTauTracks != (int)m_tauNprongs.value() ) continue; + + /// retrieve ID TrackParticles from jet + std::vector< const xAOD::TrackParticle* > tauTracks; + for( size_t iprong=0; iprong<(size_t)NTauTracks; iprong++ ) { + + std::vector< ElementTrackLink_t > tracklink = tau->track( iprong )->trackLinks(); + ATH_MSG_DEBUG( "TauLinkVec size (" << m_tauNprongs.value() << + "prong " << m_tauType.value() << "tau) = " << tracklink.size() ); + + /// adding found tau tracks to tauTracks vector + for( size_t ilink=0; ilink<tracklink.size() ; ilink++ ) { + if( tracklink.at(ilink).isValid() ) tauTracks.push_back( *(tracklink.at(ilink)) ); + } + + } // close NTauTracks loop + + ATH_MSG_DEBUG( "TauVec size (" << m_tauNprongs.value() << "prong " << + m_tauType.value() << "tau) = " << tauTracks.size() ); + + /// Loop over all the ID tracks of this hadronic tau + for( const xAOD::TrackParticle* tauTrack : tauTracks ) { + + if( not tauTrack ) { + ATH_MSG_ERROR( "Corrupted matching tau ID track" ); + continue; + } + + if( tauTrack == &track ) { + /// Createn tau element link + ElementTauLink_t tauLink; + tauLink.toContainedElement( taus, tau ); + + bool isTight( false ), isMedium( false ); + bool isLoose( false ), isVeryLoose( false ); + + if( m_tauType.value() == "BDT" ) { + isTight = tau->isTau( xAOD::TauJetParameters::JetBDTSigTight ); + isMedium = tau->isTau( xAOD::TauJetParameters::JetBDTSigMedium ); + isLoose = tau->isTau( xAOD::TauJetParameters::JetBDTSigLoose ); + isVeryLoose = tau->isTau( xAOD::TauJetParameters::JetBDTSigVeryLoose ); + + } else if( m_tauType.value() == "RNN" ) { + isTight = tau->isTau( xAOD::TauJetParameters::JetRNNSigTight ); + isMedium = tau->isTau( xAOD::TauJetParameters::JetRNNSigMedium ); + isLoose = tau->isTau( xAOD::TauJetParameters::JetRNNSigLoose ); + isVeryLoose = tau->isTau( xAOD::TauJetParameters::JetRNNSigVeryLoose ); + + } else { + ATH_MSG_ERROR( "Unknown Tau type: " << m_tauType.value() ); + return StatusCode::FAILURE; + } + + /// Decoration for All tau (no quality selection) + if( isTight or isMedium or isLoose or isVeryLoose ) { + ATH_MSG_DEBUG( "Found matching tau " << + m_tauType.value() << " " << + m_tauNprongs.value() << + "prong (pt=" << tau->pt() << + "). Decorating track." ); + IDTPM::decorateOrRejectQuietly( track, tau_decor[All], tauLink ); + return StatusCode::SUCCESS; + } + + /// Decoration for Tight tau + if( isTight ) { + IDTPM::decorateOrRejectQuietly( track, tau_decor[Tight], tauLink ); + } + + /// Decoration for Medium tau + if( isMedium ) { + IDTPM::decorateOrRejectQuietly( track, tau_decor[Medium], tauLink ); + } + + /// Decoration for Loose tau + if( isLoose ) { + IDTPM::decorateOrRejectQuietly( track, tau_decor[Loose], tauLink ); + } + + /// Decoration for VeryLoose tau + if( isVeryLoose ) { + IDTPM::decorateOrRejectQuietly( track, tau_decor[VeryLoose], tauLink ); + } + + } // if( tauTrack == &track ) + + } // close tauTracks loop + + } // close tau loop + + return StatusCode::SUCCESS; +} diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineTauDecoratorAlg.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineTauDecoratorAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..3eef241ab07a2d7df4c92322f5c4f7d8f64fced1 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/OfflineTauDecoratorAlg.h @@ -0,0 +1,93 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_OFFLINETAUDECORATORALG_H +#define INDETTRACKPERFMON_OFFLINETAUDECORATORALG_H + +/** + * @file OfflineTauDecoratorAlg.h + * @brief Algorithm to decorate offline tracks with the corresponding + * offline tau object (if required for trigger analysis) + * @author Marco Aparo <marco.aparo@cern.ch> + * @date 25 September 2023 + **/ + +/// Athena includes +#include "AthenaBaseComps/AthReentrantAlgorithm.h" + +/// xAOD includes +#include "xAODTracking/TrackParticleContainer.h" +#include "xAODTau/TauJetContainer.h" + +/// STL includes +#include <string> +#include <vector> + +/// Local includes +#include "SafeDecorator.h" + + +namespace IDTPM { + + class OfflineTauDecoratorAlg : + public AthReentrantAlgorithm { + + public: + + typedef ElementLink<xAOD::TauJetContainer> ElementTauLink_t; + typedef ElementLink<xAOD::TrackParticleContainer> ElementTrackLink_t; + + OfflineTauDecoratorAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + virtual ~OfflineTauDecoratorAlg() = default; + + virtual StatusCode initialize() override; + + virtual StatusCode execute( const EventContext& ctx ) const override; + + private: + + SG::ReadHandleKey<xAOD::TrackParticleContainer> m_offlineTrkParticlesName { + this, "OfflineTrkParticleContainerName", "InDetTrackParticles", "Name of container of offline tracks" }; + + StringProperty m_prefix { this, "Prefix", "LinkedTau_", "Decoration prefix to avoid clashes" }; + + StringProperty m_tauType { this, "TauType", "RNN", "Type of reconstructed hadronic Tau (BDT or RNN)" }; + + UnsignedIntegerProperty m_tauNprongs { this, "TauNprongs", 1, "Number of prongs in hadronic Tau decay (1 or 3)" }; + + StatusCode decorateTauTrack( + const xAOD::TrackParticle& track, + std::vector< IDTPM::OptionalDecoration< xAOD::TrackParticleContainer, + ElementTauLink_t > >& tau_decor, + const xAOD::TauJetContainer& taus ) const; + + SG::ReadHandleKey<xAOD::TauJetContainer> m_tausName { + this, "TauContainerName", "TauJets", "Name of container of offline hadronic taus" }; + + enum TauDecorations : size_t { + All, + Tight, + Medium, + Loose, + VeryLoose, + NDecorations + }; + + const std::vector< std::string > m_decor_tau_names { + "All", + "Tight", + "Medium", + "Loose", + "VeryLoose" + }; + + std::vector< IDTPM::WriteKeyAccessorPair< xAOD::TrackParticleContainer, + ElementTauLink_t > > m_decor_tau{}; + + }; + +} // namespace IDTPM + +#endif // > ! INDETTRACKPERFMON_OFFLINETAUDECORATORALG_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/RoiSelectionTool.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/RoiSelectionTool.cxx index 28e7f371962580a6eb0da6c700c71a86c10d4674..fd249d2028651712a73225f387538f482e0acf47 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/RoiSelectionTool.cxx +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/RoiSelectionTool.cxx @@ -7,7 +7,7 @@ * @author marco aparo **/ -#include "InDetTrackPerfMon/RoiSelectionTool.h" +#include "RoiSelectionTool.h" ///---------------------------------------- diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/RoiSelectionTool.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/RoiSelectionTool.h similarity index 97% rename from InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/RoiSelectionTool.h rename to InnerDetector/InDetValidation/InDetTrackPerfMon/src/RoiSelectionTool.h index 51e635a7bf4ccfce4c281f971b354c62d692717f..41b71f83ff5610c3ca6255449a5f374344298b37 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/RoiSelectionTool.h +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/RoiSelectionTool.h @@ -11,7 +11,7 @@ #include "TrigSteeringEvent/TrigRoiDescriptor.h" /// local includes -//#include "InDetTrackPerfMon/TrackRoiSelectionTool.h" +//#include "TrackRoiSelectionTool.h" // TODO - to be included in later MRs /// STL includes #include <string> diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/SafeDecorator.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/SafeDecorator.h new file mode 100644 index 0000000000000000000000000000000000000000..bf0d6c9bd45c01857adf6b2b72920ab6a6dd8c18 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/SafeDecorator.h @@ -0,0 +1,219 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_SAFEDECORATOR_H +#define INDETTRACKPERFMON_SAFEDECORATOR_H + +/** + * @file SafeDecorator.h + * header file for function of same name + * adapted from original IDPVM implementation + * @author shaun roe + * @date 20 July 2016 + * @brief Helper functions to perform safe decoration + * of xAOD objects in this package + */ + +#include "AthContainers/AuxElement.h" +#include "StoreGate/WriteDecorHandleKey.h" +#include "StoreGate/WriteDecorHandle.h" +#include "StoreGate/ReadDecorHandleKey.h" +#include "StoreGate/ReadDecorHandle.h" +#include "GaudiKernel/EventContext.h" +#include "CxxUtils/fpcompare.h" // for equal + +#include <iostream> +#include <utility> +#include <vector> +#include <cmath> +#include <cstdlib> + +namespace IDTPM { + + /// Useful declarations + template< class ContainerType, class VariableType > + using WriteKeyAccessorPair = + std::pair< SG::WriteDecorHandleKey<ContainerType>, + SG::AuxElement::ConstAccessor<VariableType> >; + // + template< class ContainerType, class VariableType > + using WriteAccessorRefPair = + std::pair< SG::WriteDecorHandle<ContainerType, VariableType>, + SG::AuxElement::ConstAccessor<VariableType>& >; + // + template< class ContainerType, class VariableType > + using OptionalDecoration = + std::pair< SG::WriteDecorHandle<ContainerType, VariableType>, bool >; + + /// create a pair composed of a WriteDecorHandleKey to create a decorator handle + /// and an accessor to check the availablilty of a decoration + template< class T_Parent, class T_Cont, class T > + void createDecoratorKeysAndAccessor( + T_Parent& parent, + const SG::ReadHandleKey< T_Cont >& container_key, + const std::string& prefix, + const std::vector< std::string >& decor_names, + std::vector< WriteKeyAccessorPair<T_Cont, T > >& decor_out ) + { + decor_out.clear(); + decor_out.reserve( decor_names.size() ); + for( const std::string& a_decor_name: decor_names ) { + decor_out.emplace_back( + SG::WriteDecorHandleKey< T_Cont >( container_key.key()+"."+prefix+a_decor_name ), + SG::AuxElement::ConstAccessor<T>( prefix+a_decor_name ) + ); + parent.declare( decor_out.back().first ); + decor_out.back().first.setOwner( &parent ); + decor_out.back().first.initialize().ignore(); + } + } + + /// like createDecoratorKeysAndAccessor but without the accessor + /// to check the availablilty of a decoration + template< class T_Parent, class T_Cont > + void createDecoratorKeys( + T_Parent& parent, + const SG::ReadHandleKey< T_Cont >& container_key, + const std::string& prefix, + const std::vector< std::string >& decor_names, + std::vector< SG::WriteDecorHandleKey< T_Cont > >& decor_out) + { + decor_out.clear(); + decor_out.reserve( decor_names.size() ); + for (const std::string &a_decor_name : decor_names) { + assert( !a_decor_name.empty() ); + decor_out.emplace_back( container_key.key()+"."+prefix+a_decor_name ); + // need to declare handles, otherwise the scheduler would not + // pick up the data dependencies introduced by the decorations + parent.declare( decor_out.back() ); + decor_out.back().setOwner(&parent); + decor_out.back().initialize().ignore(); + } + } + + /// Like above - FIXME: maybe not needed + /*template<class T_Parent, class T_Cont> + void addReadDecoratorHandleKeys(T_Parent &parent, + const SG::ReadHandleKey<T_Cont> &container_key, + const std::string &prefix, + const std::vector<std::string> &decor_names, + std::vector<SG::ReadDecorHandleKey<T_Cont> > &decor_out) { + decor_out.reserve(decor_out.size() + decor_names.size()); + for (const std::string &a_decor_name : decor_names) { + decor_out.emplace_back( container_key.key()+"."+prefix+a_decor_name); + parent.declare(decor_out.back()); + decor_out.back().setOwner(&parent); + decor_out.back().initialize().ignore(); + } + }*/ + + /// create/book the decorations if they do not exist already + template< class T_Cont, class T > + std::vector< OptionalDecoration< T_Cont,T > > + createDecoratorsIfNeeded( + const T_Cont& container, + const std::vector< WriteKeyAccessorPair<T_Cont, T > >& keys, + const EventContext& ctx, + bool verbose=false ) + { + std::vector< OptionalDecoration< T_Cont, T > > out; + bool all_available = true; + if( !container.empty() ) { + std::vector<bool> decorate; + decorate.reserve( keys.size() ); + for( const WriteKeyAccessorPair< T_Cont, T >& a_key : keys ) { + decorate.push_back( !a_key.second.isAvailable( *container[0] ) ); + all_available &= !decorate.back(); + if( verbose && !decorate.back() ) { + std::cout << "WARNING IDTPM::createDecoratorsIfNeeded: Decoration " + << a_key.first.key() << " already exists; reject update." + << std::endl; + } // close if( verbose && !decorate.back() ) + } // close WriteKeyAccessorPair loop + + if( !all_available ) { + std::size_t idx = 0; + out.reserve( keys.size() ); + for( const WriteKeyAccessorPair< T_Cont, T >& a_key : keys ) { + assert( idx < decorate.size() ); + out.emplace_back( + SG::WriteDecorHandle< T_Cont,T >( a_key.first, ctx ), + decorate[idx++] + ); + if( not out.back().first.isPresent() ) { + std::stringstream msg; + msg << "Container " << a_key.first.key() + << " to be decorated does not exist."; + throw std::runtime_error( msg.str() ); + } // close if( not out.back().first.isPresent() ) + } // close WriteKeyAccessorPair loop + } // close if( !all_available ) + } // close if( !container.empty() ) + return out; + } + + /// similar to createDecoratorsIfNeeded, but without the checking if decorations already exist + template< class T_Cont, class T > + std::vector< SG::WriteDecorHandle< T_Cont, T > > + createDecorators( + const std::vector< SG::WriteDecorHandleKey< T_Cont > >& keys, + const EventContext& ctx ) + { + std::vector< SG::WriteDecorHandle< T_Cont, T > > out; + out.reserve( keys.size() ); + for( const SG::WriteDecorHandleKey< T_Cont >& a_key : keys ) { + out.emplace_back( a_key, ctx ); + if( not out.back().isValid() ) { + std::stringstream msg; + msg << "Failed to create decorator handle " << a_key.key(); + throw std::runtime_error( msg.str() ); + } + } // close SG::WriteDecorHandleKey loop + return out; + } + + /// Fill the decoration if it deas not exist or it has a different value + template< class T_Cont, class T_Cont_Elm, class T > + void decorateOrWarnIfUnequal( + const T_Cont_Elm& particle, + WriteAccessorRefPair< T_Cont, T >& decorator, + const T& value ) + { + if( !decorator.second.isAvailable( particle ) ) { + const T existing = decorator.second( particle ); + if( not CxxUtils::fpcompare::equal( existing, value ) ) { + std::cout << "WARNING IDTPM::safeDecorator: " << decorator.first.decorKey() + << " Already exists on this object with a different value." + << std::endl; + } + } else { + decorator.first( particle ) = value; + } + } + + /// Safe method to fill the decoration if decor flag is true + template< class T_Cont, class T_Cont_Elm, class T > + void decorateOrRejectQuietly( + const T_Cont_Elm& particle, + OptionalDecoration< T_Cont, T >& decorator, + const T& value) + { + if( decorator.second ) { + decorator.first( particle ) = value; + } + } + + /// unsafe fill decoration method for convenience + template< class T_Cont, class T_Cont_Elm, class T > + void decorate( + const T_Cont_Elm& particle, + OptionalDecoration< T_Cont, T >& decorator, + const T& value) + { + decorator.first( particle ) = value; + } + +} // namespace IDTPM + +#endif // > !INDETTRACKPERFMON_SAFEDECORATOR_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisCollections.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisCollections.cxx index d3f2f13147716b4c3831b5f991b20c9dc25e6e2d..9905e93aa3ca55b0cd36b984862b29ad8c86eaa8 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisCollections.cxx +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisCollections.cxx @@ -7,7 +7,8 @@ * @author Marco Aparo <marco.aparo@cern.ch> */ -#include "InDetTrackPerfMon/TrackAnalysisCollections.h" +#include "TrackAnalysisCollections.h" +#include "TrackParmetersHelper.h" /// ------------------- /// --- Constructor --- @@ -500,9 +501,9 @@ std::string IDTPM::TrackAnalysisCollections::printInfo( size_t it(0); for( const xAOD::TrackParticle* thisOfflineTrack : m_offlTrackVec[ stage ] ) { ss << "Offline track" - << " : pt = " << thisOfflineTrack->pt() - << " : eta = " << thisOfflineTrack->eta() - << " : phi = " << thisOfflineTrack->phi() + << " : pt = " << pT( *thisOfflineTrack ) + << " : eta = " << eta( *thisOfflineTrack ) + << " : phi = " << phi( *thisOfflineTrack ) << std::endl; if( it > 20 ) { ss << "et al...." << std::endl; break; } it++; @@ -514,9 +515,9 @@ std::string IDTPM::TrackAnalysisCollections::printInfo( it = 0; for( const xAOD::TruthParticle* thisTruthParticle : m_truthTrackVec[ stage ] ) { ss << "Truth particle" - << " : pt = " << thisTruthParticle->pt() - << " : eta = " << thisTruthParticle->eta() - << " : phi = " << thisTruthParticle->phi() + << " : pt = " << pT( *thisTruthParticle ) + << " : eta = " << eta( *thisTruthParticle ) + << " : phi = " << phi( *thisTruthParticle ) << std::endl; if( it > 20 ) { ss << "et al...." << std::endl; break; } it++; @@ -528,9 +529,9 @@ std::string IDTPM::TrackAnalysisCollections::printInfo( it = 0; for( const xAOD::TrackParticle* thisTriggerTrack : m_trigTrackVec[ stage ] ) { ss << "Trigger track" - << " : pt = " << thisTriggerTrack->pt() - << " : eta = " << thisTriggerTrack->eta() - << " : phi = " << thisTriggerTrack->phi() + << " : pt = " << pT( *thisTriggerTrack ) + << " : eta = " << eta( *thisTriggerTrack ) + << " : phi = " << phi( *thisTriggerTrack ) << std::endl; if( it > 20 ) { ss << "et al...." << std::endl; break; } it++; diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackAnalysisCollections.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisCollections.h similarity index 100% rename from InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackAnalysisCollections.h rename to InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisCollections.h diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisDefinitionSvc.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisDefinitionSvc.cxx index d603f0536571418e5a6bfeba48fa2f9e8843af9b..98b95a01736d27a349b6494829d9e114f75ac2ca 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisDefinitionSvc.cxx +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisDefinitionSvc.cxx @@ -9,7 +9,7 @@ **/ /// local includes -#include "InDetTrackPerfMon/TrackAnalysisDefinitionSvc.h" +#include "TrackAnalysisDefinitionSvc.h" /// STL includes #include <algorithm> diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackAnalysisDefinitionSvc.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisDefinitionSvc.h similarity index 100% rename from InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackAnalysisDefinitionSvc.h rename to InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackAnalysisDefinitionSvc.h diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackObjectSelectionTool.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackObjectSelectionTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b02aa4775c674e980493b270e2dc1d297ade9622 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackObjectSelectionTool.cxx @@ -0,0 +1,134 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file InDetTrackObjectSelectionTool.cxx + * @author Marco Aparo <marco.aparo@cern.ch> + **/ + +/// Local include(s) +#include "TrackObjectSelectionTool.h" +#include "TrackAnalysisCollections.h" +#include "OfflineObjectDecorHelper.h" +#include "TrackParmetersHelper.h" + + +///---------------------------------------- +///------- Parametrized constructor ------- +///---------------------------------------- +IDTPM::TrackObjectSelectionTool::TrackObjectSelectionTool( + const std::string& name ) : + asg::AsgTool( name ) { } + + +///-------------------------- +///------- Initialize ------- +///-------------------------- +StatusCode IDTPM::TrackObjectSelectionTool::initialize() { + + ATH_CHECK( asg::AsgTool::initialize() ); + + ATH_MSG_INFO( "Initializing " << name() << "..." ); + + return StatusCode::SUCCESS; +} + + +///------------------------- +///----- selectTracks ------ +///------------------------- +StatusCode IDTPM::TrackObjectSelectionTool::selectTracks( + IDTPM::TrackAnalysisCollections& trkAnaColls ) { + + ATH_MSG_DEBUG( "Selecting offline tracks matched to an offline " << m_objectType.value() ); + + ITrackAnalysisDefinitionSvc* trkAnaDefSvc( nullptr ); + ISvcLocator* svcLoc = Gaudi::svcLocator(); + ATH_CHECK( svcLoc->service( "TrkAnaDefSvc" + trkAnaColls.anaTag(), trkAnaDefSvc ) ); + + if( not trkAnaDefSvc->useOffline() ) { + ATH_MSG_DEBUG( "Tool not enabled if offline tracks are not used." ); + return StatusCode::SUCCESS; + } + + /// started loop over offline tracks + std::vector< const xAOD::TrackParticle* > newVec; + for( const xAOD::TrackParticle* thisTrack : + trkAnaColls.offlTrackVec( IDTPM::TrackAnalysisCollections::FS ) ) { + if( accept( *thisTrack ) ) newVec.push_back( thisTrack ); + } + + /// update selected Full-Scan offline track vector + ATH_CHECK( trkAnaColls.fillOfflTrackVec( newVec, + IDTPM::TrackAnalysisCollections::FS ) ); + + /// Debug printout + ATH_MSG_DEBUG( "Tracks after offline object-matching: " << + trkAnaColls.printInfo( IDTPM::TrackAnalysisCollections::FS ) ); + + return StatusCode::SUCCESS; +} + + +///----------------------- +///------- accept -------- +///----------------------- +bool IDTPM::TrackObjectSelectionTool::accept( + const xAOD::TrackParticle& offTrack ) const { + + /// Electron + if( m_objectType.value().find("Electron") != std::string::npos ) { + + const xAOD::Electron* ele = IDTPM::getLinkedElectron( + offTrack, m_objectQuality.value() ); + + if( not ele ) return false; + + ATH_MSG_DEBUG( "Offline Track with pt = " << pT( offTrack ) << + " matches with " << m_objectQuality.value() << + " Electron with transverse energy = " << ET( *ele ) ); + } + + /// Muon + if( m_objectType.value().find("Muon") != std::string::npos ) { + const xAOD::Muon* mu = IDTPM::getLinkedMuon( + offTrack, m_objectQuality.value() ); + + if( not mu ) return false; + + ATH_MSG_DEBUG( "Offline Track with pt = " << pT( offTrack ) << + " matches with " << m_objectQuality.value() << + " Muon with transverse energy = " << ET( *mu ) ); + } + + /// Tau + if( m_objectType.value().find("Tau") != std::string::npos ) { + + const xAOD::TauJet* tau = IDTPM::getLinkedTau( + offTrack, m_tauNprongs.value(), + m_tauType.value(), m_objectQuality.value() ); + + if( not tau ) return false; + + ATH_MSG_DEBUG( "Offline Track with pt = " << pT( offTrack ) << + " matches with " << m_objectQuality.value() << + " hadronic " << m_tauNprongs.value() << "prong " << + m_tauType.value() << " Tau with transverse energy = " << + ET( *tau ) ); + } + + /// Truth + if( m_objectType.value().find("Truth") != std::string::npos ) { + + const xAOD::TruthParticle* truth = IDTPM::getLinkedTruth( + offTrack, m_truthProbCut.value() ); + + if( not truth ) return false; + + ATH_MSG_DEBUG( "Offline Track with pt = " << pT( offTrack ) << + " matches with truth particle with pt = " << pT( *truth ) ); + } + + return true; +} diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackObjectSelectionTool.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackObjectSelectionTool.h new file mode 100644 index 0000000000000000000000000000000000000000..f94af828e138ea8099e9c6f3aa9e0fc4ced6656e --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackObjectSelectionTool.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_TRACKOBJECTSELECTIONTOOL_H +#define INDETTRACKPERFMON_TRACKOBJECTSELECTIONTOOL_H + +/** + * @file TrackObjectSelectionTool.h + * @author Marco Aparo <marco.aparo@cern.ch> + * @date 02 October 2023 + * @brief Tool to select offline ID tracks which asociated + * with fully-reconstructed object with specific + * quality criteria + */ + +/// Athena include(s) +#include "AsgTools/AsgTool.h" +#include "TrigSteeringEvent/TrigRoiDescriptor.h" + +/// Local include(s) +#include "InDetTrackPerfMon/ITrackSelectionTool.h" + +/// EDM includes +#include "xAODTracking/TrackParticle.h" + + +namespace IDTPM { + + class TrackObjectSelectionTool : + public virtual IDTPM::ITrackSelectionTool, + public asg::AsgTool { + + public: + + ASG_TOOL_CLASS( TrackObjectSelectionTool, ITrackSelectionTool ); + + /// Constructor + TrackObjectSelectionTool( const std::string& name ); + + /// Destructor + virtual ~TrackObjectSelectionTool() = default; + + /// Initialize + virtual StatusCode initialize() override; + + /// Main Track selection method + virtual StatusCode selectTracks( + IDTPM::TrackAnalysisCollections& trkAnaColls ) override; + + /// Dummy method - unused + virtual StatusCode selectTracksInRoI( + IDTPM::TrackAnalysisCollections&, + const ElementLink< TrigRoiDescriptorCollection >& ) override { + ATH_MSG_WARNING( "selectTracksInRoI method is disabled" ); + return StatusCode::SUCCESS; + } + + bool accept( const xAOD::TrackParticle& offTrack ) const; + + private: + + StringProperty m_objectType { + this, "ObjectType", "Electron", "Offline object type requested" }; + + StringProperty m_objectQuality { + this, "ObjectQuality", "", "Quality-based object selection" }; + + StringProperty m_tauType { + this, "TauType", "RNN", "Request RNN or BDT taus" }; + + IntegerProperty m_tauNprongs { + this, "TauNprongs", 1, "Request 1- or 3- prong taus" }; + + FloatProperty m_truthProbCut { + this, "MatchingTruthProb", 0.5, "Minimal truthProbability for valid matching" }; + + }; // class TrackObjectSelectionTool + +} // namespace IDTPM + + + +#endif // > ! INDETTRACKPERFMON_INDETTRACKOBJECTSELECTIONTOOL_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackParmetersHelper.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackParmetersHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..212252040f8235436c31eee262bc8a536375f962 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackParmetersHelper.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_TRKPARAMETERSHELPER_H +#define INDETTRACKPERFMON_TRKPARAMETERSHELPER_H + +/** + * @file TrackParmetersHelper.h + * @brief Utility methods to access + * track/truth particles parmeters in + * a consitent way in this package + * @author Marco Aparo <marco.aparo@cern.ch> + * @date 25 September 2023 + **/ + +/// xAOD includes +#include "xAODTracking/TrackParticle.h" +#include "xAODTruth/TruthParticle.h" + +/// STD includes +#include <cmath> // std::fabs + + +namespace IDTPM { + + /// Accessor utility function for getting the value of pT + template< class U > + inline float pT( const U& p ) { return p.pt(); } + + /// Accessor utility function for getting the value of signed pT + template< class U > + inline float pTsig( const U& p ) { + float pT = std::fabs( p.pt() ); + if( p.charge() < 0 ) pT *= -1; + if( p.charge() == 0 ) pT = 0.; + return pT; + } + + /// Accessor utility function for getting the value of eta + template< class U > + inline float eta( const U& p ) { return p.eta(); } + + /// Accessor utility function for getting the value of phi + template< class U > + inline float phi( const U& p ) { return p.phi(); } + + /// Accessor utility function for getting the value of z0 + inline float getZ0( const xAOD::TrackParticle& p ) { return p.z0(); } + /// + inline float getZ0( const xAOD::TruthParticle& p ) { + return ( p.isAvailable<float>("z0") ) ? + p.auxdata<float>("z0") : -9999.; + } + /// + template< class U > + inline float z0( const U& p ) { return getZ0( p ); } + + /// Accessor utility function for getting the value of d0 + inline float getD0( const xAOD::TrackParticle& p ) { return p.d0(); } + /// + inline float getD0( const xAOD::TruthParticle& p ) { + return ( p.isAvailable<float>("d0") ) ? + p.auxdata<float>("d0") : -9999.; + } + /// + template< class U > + inline float d0( const U& p ) { return getD0( p ); } + + /// Accessor utility function for getting the value of qOverP + inline float getQoverP( const xAOD::TrackParticle& p ) { return p.qOverP(); } + /// + inline float getQoverP( const xAOD::TruthParticle& p ) { + return ( p.isAvailable<float>("qOverP") ) ? + p.auxdata<float>("qOverP") : -9999.; + } + /// + template< class U > + inline float qOverP( const U& p ) { return getQoverP( p ); } + + /// Accessor utility function for getting the value of Energy + template< class U > + inline float Etot( const U& p ) { return p.e(); } + + /// Accessor utility function for getting the value of Tranverse energy + template< class U > + inline float ET( const U& p ) { return p.p4().Et(); } + +} // namespace IDTPM + +#endif // > ! INDETTRACKPERFMON_TRKPARAMETERSHELPER_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackQualitySelectionTool.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackQualitySelectionTool.cxx index 158831e826acac5870198a6d6ba1866146ad22a3..3bc590b071c6309b6680d0cdb1b6cf6aa73fb372 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackQualitySelectionTool.cxx +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackQualitySelectionTool.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ /** @@ -8,8 +8,8 @@ **/ /// Local include(s) -#include "InDetTrackPerfMon/TrackQualitySelectionTool.h" -#include "InDetTrackPerfMon/TrackAnalysisCollections.h" +#include "TrackQualitySelectionTool.h" +#include "TrackAnalysisCollections.h" ///---------------------------------------- @@ -29,8 +29,7 @@ StatusCode IDTPM::TrackQualitySelectionTool::initialize() { ATH_MSG_INFO( "Initializing " << name() ); - /// TODO - to be included in later MRs - //ATH_CHECK( m_objSelectionTool.retrieve( EnableTool{ m_doObjSelection.value() } ) ); + ATH_CHECK( m_objSelectionTool.retrieve( EnableTool{ m_doObjSelection.value() } ) ); return StatusCode::SUCCESS; } @@ -65,11 +64,10 @@ StatusCode IDTPM::TrackQualitySelectionTool::selectTracks( ATH_MSG_DEBUG( "Tracks after initial FullScan copy: " << trkAnaColls.printInfo( IDTPM::TrackAnalysisCollections::FS ) ); - /// TODO - To be included in later MRs /// Select offline tracks matched to offline objects - //if( trkAnaDefSvc->useOffline() and m_doObjSelection.value() ) { - // ATH_CHECK( m_objSelectionTool->selectTracks( trkAnaColls ) ); - //} + if( trkAnaDefSvc->useOffline() and m_doObjSelection.value() ) { + ATH_CHECK( m_objSelectionTool->selectTracks( trkAnaColls ) ); + } /// TODO - put offline and truth selections here... diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackQualitySelectionTool.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackQualitySelectionTool.h similarity index 82% rename from InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackQualitySelectionTool.h rename to InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackQualitySelectionTool.h index 969984f5523f8ea4d7569fc52a67da5c3bc852d4..da48c49a4938ac0c2e9ed9bad3c69728f61c4c50 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackQualitySelectionTool.h +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackQualitySelectionTool.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #ifndef INDETTRACKPERFMON_TRACKQUALITYSELECTIONTOOL_H @@ -56,15 +56,14 @@ namespace IDTPM { return StatusCode::SUCCESS; } -/* TODO - To be included in later MRs private: - BooleanProperty m_doObjSelection{ this, "DoObjectSelection", false, "Perform track-object selection" }; + BooleanProperty m_doObjSelection { + this, "DoObjectSelection", false, "Perform track-object selection" }; - ToolHandle< IDTPM::IInDetSelectionTool > m_objSelectionTool{ - this, "TrackObjectSelectionTool", "IDTPM::InDetTrackPerfMon/IInDetSelectionTool", - "Tool to perform track-object quality selection" }; -*/ + ToolHandle< IDTPM::ITrackSelectionTool > m_objSelectionTool { + this, "TrackObjectSelectionTool", "IDTPM::InDetTrackPerfMon/ITrackSelectionTool", + "Tool to perform track-object selection" }; }; // class InDetGeneralSelectionTool diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackRoiSelectionTool.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackRoiSelectionTool.cxx index a017eac89476b41a32c07285db1133576bea99ca..beef82bc6d9ccdea229f4887937dcb12a15916b3 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackRoiSelectionTool.cxx +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackRoiSelectionTool.cxx @@ -11,65 +11,14 @@ #include "TrigSteeringEvent/TrigRoiDescriptor.h" /// Local include(s) -#include "InDetTrackPerfMon/TrackRoiSelectionTool.h" -#include "InDetTrackPerfMon/TrackAnalysisCollections.h" +#include "TrackRoiSelectionTool.h" +#include "TrackAnalysisCollections.h" +#include "TrackParmetersHelper.h" /// STD includes #include <cmath> // std::fabs -///--------------------------------------------------- -/// Placing utility functions in anonymous namespace -///--------------------------------------------------- -namespace { - - /// Accessor utility function for getting the value of pT - template< class U > - float pT( const U* p ) { - return p->pt(); - } - - /// Accessor utility function for getting the value of pTsig - template< class U > - float pTsig( const U* p ) { - float pT = std::fabs( p->pt() ); - if( p->charge() < 0 ) pT *= -1; - if( p->charge() == 0 ) pT = 0.; - return pT; - } - - /// Accessor utility function for getting the value of eta - template< class U > - float eta( const U* p ) { - return p->eta(); - } - - /// Accessor utility function for getting the value of phi - template< class U > - float phi( const U* p ) { - return p->phi(); - } - - /// Accessor utility function for getting the value of z0 - float getZ0( const xAOD::TrackParticle* p ) { - return p->z0(); - } - /// - float getZ0( const xAOD::TruthParticle* /*p*/ ) { - /// TODO - To be included in later MRs - //return ( p->isAvailable<float>("z0") ) ? - // p->auxdata<float>("z0") : -9999.; - return 0.; // TODO - to be removed in later MRs - } - /// - template< class U > - float z0( const U* p ) { - return getZ0( p ); - } - -} // namespace - - ///---------------------------------------- ///------- Parametrized constructor ------- ///---------------------------------------- @@ -101,7 +50,7 @@ StatusCode IDTPM::TrackRoiSelectionTool::initialize() { ///----------------------- template< class T > bool IDTPM::TrackRoiSelectionTool::accept( - const T* t, const TrigRoiDescriptor* r ) const { + const T& t, const TrigRoiDescriptor* r ) const { if( r==0 ) { ATH_MSG_ERROR( "Called with null RoiDescriptor" ); @@ -119,7 +68,7 @@ bool IDTPM::TrackRoiSelectionTool::accept( if( r->isFullscan() ) return true; /// NB: This isn't actually correct - the tracks can bend out of the - /// RoI even if the perigee phi is withing the Roi + /// RoI even if the perigee phi is within the Roi bool contained_phi = ( r->phiMinus() < r->phiPlus() ) ? ( phi(t) > r->phiMinus() && phi(t) < r->phiPlus() ) : ( phi(t) > r->phiMinus() || phi(t) < r->phiPlus() ); @@ -242,7 +191,7 @@ std::vector< const T* > IDTPM::TrackRoiSelectionTool::getTracks( for( size_t it=0 ; it<tvec.size() ; it++ ) { const T* thisTrack = tvec.at(it); - if( accept<T>( thisTrack, r ) ) { + if( accept<T>( *thisTrack, r ) ) { selectedTracks.push_back( thisTrack ); } } diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackRoiSelectionTool.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackRoiSelectionTool.h similarity index 97% rename from InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackRoiSelectionTool.h rename to InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackRoiSelectionTool.h index 56aa366ef341834f339d72e2765e155f22da1023..51dc37f1c5e4566cf200c98e7b819aa39ba49157 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/InDetTrackPerfMon/TrackRoiSelectionTool.h +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TrackRoiSelectionTool.h @@ -65,7 +65,7 @@ namespace IDTPM { /// geometric RoI filters - for non-trigger tracks (e.g. offline, truth, etc.) template< class T > - bool accept( const T* t, const TrigRoiDescriptor* r ) const; + bool accept( const T& t, const TrigRoiDescriptor* r ) const; /// track getter function (for offline tracks or truth particles) template< class T > diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TruthHitDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TruthHitDecoratorAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ce3c63880f8a4cec96c740575107d803d22e6137 --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TruthHitDecoratorAlg.cxx @@ -0,0 +1,233 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file TruthHitDecoratorAlg.cxx + * @author shaun roe + **/ + +/// Local includes +#include "TruthHitDecoratorAlg.h" + +/// EDM includes +#include "xAODTruth/TruthVertex.h" +#include "TrkParameters/TrackParameters.h" // Contains typedef to Trk::CurvilinearParameters + +/// ROOT includes +#include "TDatabasePDG.h" +#include "TParticlePDG.h" + +/// STD includes +#include <cmath> +//#include <limits> + + +///--------------------------- +///------- Constructor ------- +///--------------------------- +IDTPM::TruthHitDecoratorAlg::TruthHitDecoratorAlg( + const std::string& name, + ISvcLocator* pSvcLocator) : + AthReentrantAlgorithm( name, pSvcLocator ) { } + + +///-------------------------- +///------- initialize ------- +///-------------------------- +StatusCode IDTPM::TruthHitDecoratorAlg::initialize() { + + ATH_CHECK( m_extrapolator.retrieve() ); + ATH_CHECK( m_beamSpotDecoKey.initialize() ); + ATH_CHECK( m_truthPixelClusterName.initialize() ); + ATH_CHECK( m_truthSCTClusterName.initialize() ); + ATH_CHECK( m_truthParticleName.initialize() ); + + /// Creating/booking decorations for truth particles + IDTPM::createDecoratorKeysAndAccessor( + *this, m_truthParticleName, + m_prefix.value(), m_decor_names, m_decor ); + + if( m_decor.size() != NDecorations ) { + ATH_MSG_ERROR( "Incorrect booking of truth hits decorations" ); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + + +///----------------------- +///------- execute ------- +///----------------------- +StatusCode IDTPM::TruthHitDecoratorAlg::execute( + const EventContext& ctx ) const { + + /// retrieve truth particle container + SG::ReadHandle< xAOD::TruthParticleContainer > ptruth( m_truthParticleName, ctx ); + if( not ptruth.isValid() ) { + ATH_MSG_ERROR( "Failed to retrieve truth particle container" ); + return StatusCode::FAILURE; + } + + std::vector< IDTPM::OptionalDecoration< xAOD::TruthParticleContainer, float > > + float_decor( IDTPM::createDecoratorsIfNeeded( + *ptruth, m_decor, ctx, msgLvl(MSG::DEBUG) ) ); + + /// truthbarcode-cluster maps to be pre-stored at event level + std::unordered_map< int, float > barcodeSCTclustercount; + std::unordered_map< int, float > barcodePIXclustercount; + + /// Loop over the pixel and sct clusters + /// to fill the truth barcode - cluster count maps + SG::ReadHandle< xAOD::TrackMeasurementValidationContainer > sctClusters( m_truthSCTClusterName, ctx ); + SG::ReadHandle< xAOD::TrackMeasurementValidationContainer > pixelClusters( m_truthPixelClusterName, ctx ); + + //only decorate the truth particles with truth silicon hits if both containers are available + if( sctClusters.isValid() && pixelClusters.isValid() ) { + + static const SG::AuxElement::ConstAccessor< std::vector<int> > barcodeAcc( "truth_barcode" ); + + /// Loop over truth SCT clusters + for( const xAOD::TrackMeasurementValidation* sctCluster : *sctClusters ) { + std::vector<int> truth_barcode; + if( barcodeAcc.isAvailable( *sctCluster ) ) { + truth_barcode = barcodeAcc( *sctCluster ); + for( const int& barcode : truth_barcode ) { + auto result = barcodeSCTclustercount.emplace( std::pair<int, float>(barcode, 0.0) ); + if( !result.second ) ++( result.first->second ); + } + } + } // close loop over truth SCT clusters + + /// Loop over truth Pixel clusters + for( const xAOD::TrackMeasurementValidation* pixCluster : *pixelClusters ) { + std::vector<int> truth_barcode; + if( barcodeAcc.isAvailable( *pixCluster ) ) { + truth_barcode = barcodeAcc( *pixCluster ); + for( const int& barcode : truth_barcode ) { + auto result = barcodePIXclustercount.emplace( std::pair<int, float>(barcode, 0.0) ); + if( !result.second ) ++( result.first->second ); + } + } + } // close loop over truth Pixel clusters + } // close if sctClusters and pixelClusters isValid + + if( float_decor.empty() ) { + ATH_MSG_ERROR( "Failed to book Truth particles Hit decorations" ); + return StatusCode::FAILURE; + } + + /// Retrieving BeamSpot info + SG::ReadDecorHandle< xAOD::EventInfo, float > beamPosX( m_beamSpotDecoKey[0], ctx ); + SG::ReadDecorHandle< xAOD::EventInfo, float > beamPosY( m_beamSpotDecoKey[1], ctx ); + SG::ReadDecorHandle< xAOD::EventInfo, float > beamPosZ( m_beamSpotDecoKey[2], ctx ); + if( (not beamPosX.isValid()) or (not beamPosY.isValid()) or (not beamPosZ.isValid()) ) { + ATH_MSG_WARNING( "Failed to retrieve beam position" ); + return StatusCode::RECOVERABLE; + } + Amg::Vector3D beamPos = Amg::Vector3D( beamPosX(0), beamPosY(0), beamPosZ(0) ); + + for( const xAOD::TruthParticle* truth_particle : *ptruth ) { + /// decorate current truth particle with hit info + ATH_CHECK( decorateTruth( + *truth_particle, float_decor, beamPos, + barcodePIXclustercount, barcodeSCTclustercount, ctx ) ); + } + + return StatusCode::SUCCESS; +} + + +///----------------------- +///---- decorateTruth ---- +///----------------------- +StatusCode IDTPM::TruthHitDecoratorAlg::decorateTruth( + const xAOD::TruthParticle& particle, + std::vector< IDTPM::OptionalDecoration< xAOD::TruthParticleContainer, float > >& float_decor, + const Amg::Vector3D& beamPos, + std::unordered_map<int, float>& pixelMap, + std::unordered_map<int, float>& sctMap, + const EventContext& ctx ) const { + + /// Skip neutral truth particles + if( particle.isNeutral() ) { + return StatusCode::SUCCESS; + } + + const Amg::Vector3D momentum( particle.px(), particle.py(), particle.pz() ); + const int pid( particle.pdgId() ); + double charge = particle.charge(); + + if( std::isnan(charge) ) { + ATH_MSG_DEBUG( "Charge not found on particle with pid " << pid ); + return StatusCode::SUCCESS; + } + + /// Retrieve the cluster count from the pre-filled maps + std::unordered_map< int, float >::iterator it1, it2; + it1 = pixelMap.find( particle.barcode() ); + it2 = sctMap.find( particle.barcode() ); + float nSiHits = 0; + if( it1 !=pixelMap.end() ) nSiHits += (*it1).second; + if( it2 !=sctMap.end() ) nSiHits += (*it2).second; + + /// Decoration for NSiHits + IDTPM::decorateOrRejectQuietly( particle, float_decor[NSilHits], nSiHits ); + + const xAOD::TruthVertex* ptruthVertex(nullptr); + try { + ptruthVertex = particle.prodVtx(); + } catch( const std::exception& e ) { + if ( not m_errorEmitted ) { + ATH_MSG_WARNING( "A non existent production vertex was requested in calculating the track parameters d0 etc" ); + } + m_errorEmitted = true; + return StatusCode::RECOVERABLE; //SUCCESS; + } + + if( not ptruthVertex ) { + ATH_MSG_DEBUG( "A production vertex pointer was retrieved, but it is NULL" ); + return StatusCode::SUCCESS; + } + + const auto xPos = ptruthVertex->x(); + const auto yPos = ptruthVertex->y(); + const auto z_truth = ptruthVertex->z(); + const Amg::Vector3D position( xPos, yPos, z_truth ); + const float prodR_truth = std::sqrt( xPos * xPos + yPos * yPos ); + const Trk::CurvilinearParameters cParameters( position, momentum, charge ); + + Trk::PerigeeSurface persf( beamPos ); + + std::unique_ptr< const Trk::TrackParameters > tP( + m_extrapolator->extrapolate( ctx, cParameters, + persf, Trk::anyDirection, false ) ); + if( not tP ) { + ATH_MSG_DEBUG( "The TrackParameters pointer for this TruthParticle is NULL" ); + return StatusCode::SUCCESS; + } + + /// Other hit decorations + float d0_truth = tP->parameters()[ Trk::d0 ]; + float theta_truth = tP->parameters()[ Trk::theta ]; + float z0_truth = tP->parameters()[ Trk::z0 ]; + float phi_truth = tP->parameters()[ Trk::phi ]; + float qOverP_truth = tP->parameters()[ Trk::qOverP ]; // P or Pt ?? + float z0st_truth = z0_truth * std::sin( theta_truth ); + + ATH_MSG_DEBUG( "Truth particle (pT = " << particle.pt() << + " has impact parameter (d0, z0) = (" << d0_truth << + " ," << z0_truth << ")" ); + + IDTPM::decorateOrRejectQuietly( particle, float_decor[D0], d0_truth ); + IDTPM::decorateOrRejectQuietly( particle, float_decor[Z0], z0_truth ); + IDTPM::decorateOrRejectQuietly( particle, float_decor[Phi], phi_truth ); + IDTPM::decorateOrRejectQuietly( particle, float_decor[Theta], theta_truth ); + IDTPM::decorateOrRejectQuietly( particle, float_decor[Z0st], z0st_truth ); + IDTPM::decorateOrRejectQuietly( particle, float_decor[QOverP], qOverP_truth ); + IDTPM::decorateOrRejectQuietly( particle, float_decor[ProdR], prodR_truth ); + IDTPM::decorateOrRejectQuietly( particle, float_decor[ProdZ], z_truth ); + + return StatusCode::SUCCESS; +} diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TruthHitDecoratorAlg.h b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TruthHitDecoratorAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..48bf7b8c053f109ba9c407689a23041c7acf5eed --- /dev/null +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/TruthHitDecoratorAlg.h @@ -0,0 +1,122 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef INDETTRACKPERFMON_TRUTHHITDECORATORALG_H +#define INDETTRACKPERFMON_TRUTHHITDECORATORALG_H + +/** + * @file TruthHitDecoratorAlg.h + * header file for class of same name + * adapted from original IDPVM InDetPhysValTruthDecoratorAlg + * @author shaun roe + * @date 27 March 2014 + * @brief Algorithm to decorate xAOD::TruthParticles with additional + * information regarding the corresponding track hits + * required for validation + **/ + +/// Gaudi includes +#include "GaudiKernel/ToolHandle.h" +#include "StoreGate/ReadDecorHandleKeyArray.h" + +/// Athena includes +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "TrkExInterfaces/IExtrapolator.h" + +/// EDM includes +#include "xAODTruth/TruthParticleContainer.h" +#include "xAODEventInfo/EventInfo.h" +#include "xAODTracking/TrackMeasurementValidationContainer.h" + +/// STD includes +#include <string> +#include <atomic> +#include <unordered_map> +#include <vector> + +/// Local includes +#include "SafeDecorator.h" + + +namespace IDTPM { + + class TruthHitDecoratorAlg : + public AthReentrantAlgorithm { + + public: + + TruthHitDecoratorAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + virtual ~TruthHitDecoratorAlg() = default; + + virtual StatusCode initialize() override; + + virtual StatusCode execute( const EventContext& ctx ) const override; + + private: + + StatusCode decorateTruth( + const xAOD::TruthParticle& particle, + std::vector< IDTPM::OptionalDecoration< xAOD::TruthParticleContainer, + float > >& float_decor, + const Amg::Vector3D& beamPos, + std::unordered_map< int, float >& pixelMap, + std::unordered_map< int, float >& sctMap, + const EventContext& ctx ) const; + + PublicToolHandle< Trk::IExtrapolator > m_extrapolator { + this, "Extrapolator", "Trk::Extrapolator/AtlasExtrapolator", "" }; + + SG::ReadDecorHandleKeyArray< xAOD::EventInfo > m_beamSpotDecoKey { + this, "BeamSpotDecoKeys", + { "EventInfo.beamPosX", "EventInfo.beamPosY", "EventInfo.beamPosZ" }, + "Beamspot position decoration keys" }; + + mutable std::atomic<bool> m_errorEmitted{ false }; + + ///TruthParticle container's name needed to create decorators + SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleName { + this, "TruthParticleContainerName", "TruthParticles", "" }; + + StringProperty m_prefix { this, "Prefix", "", "Decoration prefix to avoid clashes." }; + + SG::ReadHandleKey< xAOD::TrackMeasurementValidationContainer > m_truthPixelClusterName { + this, "PixelClusterContainerName", "PixelClusters", "" }; + + SG::ReadHandleKey< xAOD::TrackMeasurementValidationContainer > m_truthSCTClusterName { + this, "SCTClusterContainerName", "SCT_Clusters", "" }; + + enum TruthDecorations { + D0, + Z0, + Phi, + Theta, + Z0st, + QOverP, + ProdR, + ProdZ, + NSilHits, + NDecorations + }; + + const std::vector< std::string > m_decor_names { + "d0", + "z0", + "phi", + "theta", + "z0st", + "qOverP", + "prodR", + "prodZ", + "nSilHits" + }; + + std::vector< std::pair< + SG::WriteDecorHandleKey< xAOD::TruthParticleContainer >, + SG::AuxElement::ConstAccessor< float > > > m_decor{}; + }; + +} // namespace IDTPM + +#endif // > !INDETTRACKPERFMON_TRUTHHITDECORATORALG_H diff --git a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/components/InDetTrackPerfMon_entries.cxx b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/components/InDetTrackPerfMon_entries.cxx index 48400ad798fe9f335336fc33460ff609a0a57f69..79c7e4340ffc107cb9ba9debf3ab84a20c9f624d 100644 --- a/InnerDetector/InDetValidation/InDetTrackPerfMon/src/components/InDetTrackPerfMon_entries.cxx +++ b/InnerDetector/InDetValidation/InDetTrackPerfMon/src/components/InDetTrackPerfMon_entries.cxx @@ -2,36 +2,36 @@ Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ -#include "InDetTrackPerfMon/InDetTrackPerfMonTool.h" -#include "InDetTrackPerfMon/TrackAnalysisDefinitionSvc.h" -#include "InDetTrackPerfMon/TrackQualitySelectionTool.h" -#include "InDetTrackPerfMon/RoiSelectionTool.h" -#include "InDetTrackPerfMon/TrackRoiSelectionTool.h" +#include "../InDetTrackPerfMonTool.h" +#include "../TrackAnalysisDefinitionSvc.h" +#include "../TrackQualitySelectionTool.h" +#include "../RoiSelectionTool.h" +#include "../TrackRoiSelectionTool.h" +#include "../TruthHitDecoratorAlg.h" +#include "../OfflineElectronDecoratorAlg.h" +#include "../OfflineMuonDecoratorAlg.h" +#include "../OfflineTauDecoratorAlg.h" +#include "../TrackObjectSelectionTool.h" /// TODO - To be included in later MRs -//#include "InDetTrackPerfMon/InDetTrackObjectSelectionTool.h" //#include "InDetTrackPerfMon/DeltaRtrackMatchingTool_trk.h" //#include "InDetTrackPerfMon/DeltaRtrackMatchingTool_trkTruth.h" //#include "InDetTrackPerfMon/TrackTruthMatchingTool.h" //#include "InDetTrackPerfMon/HistogramDefinitionSvc.h" //#include "InDetTrackPerfMon/ReadJsonHistoDefTool.h" -//#include "InDetTrackPerfMon/InDetTruthDecoratorAlg.h" -//#include "InDetTrackPerfMon/InDetOfflineElectronDecoratorAlg.h" -//#include "InDetTrackPerfMon/InDetOfflineMuonDecoratorAlg.h" -//#include "InDetTrackPerfMon/InDetOfflineTauDecoratorAlg.h" DECLARE_COMPONENT( InDetTrackPerfMonTool ) DECLARE_COMPONENT( TrackAnalysisDefinitionSvc ) DECLARE_COMPONENT( IDTPM::TrackQualitySelectionTool ) DECLARE_COMPONENT( IDTPM::RoiSelectionTool ) DECLARE_COMPONENT( IDTPM::TrackRoiSelectionTool ) +DECLARE_COMPONENT( IDTPM::TruthHitDecoratorAlg ) +DECLARE_COMPONENT( IDTPM::OfflineElectronDecoratorAlg ) +DECLARE_COMPONENT( IDTPM::OfflineMuonDecoratorAlg ) +DECLARE_COMPONENT( IDTPM::OfflineTauDecoratorAlg ) +DECLARE_COMPONENT( IDTPM::TrackObjectSelectionTool ) /// TODO - To be included in later MRs //DECLARE_COMPONENT( ReadJsonHistoDefTool ) //DECLARE_COMPONENT( IDTPM::HistogramDefinitionSvc ) -//DECLARE_COMPONENT( IDTPM::InDetTrackObjectSelectionTool ) //DECLARE_COMPONENT( IDTPM::DeltaRtrackMatchingTool_trk ) //DECLARE_COMPONENT( IDTPM::DeltaRtrackMatchingTool_trkTruth ) //DECLARE_COMPONENT( IDTPM::TrackTruthMatchingTool ) -//DECLARE_COMPONENT( InDetTruthDecoratorAlg ) -//DECLARE_COMPONENT( InDetOfflineElectronDecoratorAlg ) -//DECLARE_COMPONENT( InDetOfflineMuonDecoratorAlg ) -//DECLARE_COMPONENT( InDetOfflineTauDecoratorAlg )