diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py index b255d5cc77defe3f2b4dd7041b880f6fb4bed7ff..8d4942a7a588ed9821d241ccbf33cec705b07ad6 100644 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/python/ExtendedJetCommon.py @@ -265,7 +265,7 @@ def applyJetCalibration(jetalg,algname,sequence,largeRjetconfig = 'comb', suffix 'AntiKt4LCTopo':('JES_data2016_data2015_Recommendation_Dec2016_rel21.config', 'JetArea_Residual_EtaJES_GSC'), 'AntiKt4EMPFlow':('JES_MC16Recommendation_Consolidated_PFlow_Apr2019_Rel21.config', - 'JetArea_Residual_EtaJES_GSC_Smear'), + 'JetArea_Residual_EtaJES_GSC'), 'AntiKt10LCTopoTrimmedPtFrac5SmallR20':('JES_MC15recommendation_FatJet_Nov2016_QCDCombinationUncorrelatedWeights.config', 'EtaJES_JMS'), 'AntiKt2LCTopo':('JES_2015_2016_data_Rscan2LC_18Dec2018_R21.config', @@ -448,6 +448,79 @@ def addJetTruthLabel(jetalg,algname,labelname,sequence): extjetlog.info('ExtendedJetCommon: Applying JetTruthLabel augmentation to jet collection: ' + jetalg + 'Jets' + ' using ' + labelname +' definition') applyJetAugmentation(jetalg,algname,sequence,jetaugtool) +################################################################## + +def getPFlowfJVT(jetalg,algname,sequence,primaryVertexCont="PrimaryVertices",trackVertexAssociation="JetTrackVtxAssoc",overlapLabel="",outLabel="fJvt",includePV=False): + supportedJets = ['AntiKt4EMPFlow','AntiKt4PFlowCustomVtxHgg'] + if jetalg not in supportedJets: + extjetlog.error('*** PFlow fJvt augmentation requested for unsupported jet collection {}! ***'.format(jetalg)) + return + else: + from AthenaCommon.AppMgr import ToolSvc + jetaugtool = getJetAugmentationTool(jetalg,suffix=algname) + + #Check if the calibration and JVT tools exist already + jetcalibtoolname_default = 'DFJetCalib_'+jetalg + jetjvttoolname_default = 'DFJetJvt_'+jetalg + + if '_BTagging' in jetalg: + jetalg_basename = jetalg[:jetalg.find('_BTagging')] + elif 'PFlowCustomVtx' in jetalg: + jetalg_basename = 'AntiKt4EMPFlow' + else: + jetalg_basename = jetalg + + jvtefftoolname = getJvtEffToolName(jetalg_basename) + + #Jet calibration tool + if hasattr(ToolSvc, jetcalibtoolname_default): + jetaugtool.JetCalibTool = getattr(ToolSvc, jetcalibtoolname_default) + else: + applyJetCalibration(jetalg,algname,sequence,suffix=algname) + + #JVT tool + if hasattr(ToolSvc, jetjvttoolname_default) and hasattr(ToolSvc, jvtefftoolname): + jetaugtool.JetJvtTool = getattr(ToolSvc, jetjvttoolname_default) + jetaugtool.JetJvtEffTool = getattr(ToolSvc, jvtefftoolname) + else: + updateJVT(jetalg,algname,sequence,customVxColl=primaryVertexCont,suffix=algname) + + # Calibration tool specific for pFlow fJVT: without GSC and smearing + jetcalibtoolname = 'DFJetCalib_PFfJvt_'+jetalg + if hasattr(ToolSvc, jetcalibtoolname): + jetaugtool.JetCalibToolfJvt = getattr(ToolSvc,jetcalibtoolname) + else: + jetcalibrationtool = CfgMgr.JetCalibrationTool(jetcalibtoolname, + JetCollection=jetalg, + ConfigFile="JES_MC16Recommendation_Consolidated_PFlow_Apr2019_Rel21.config", + CalibSequence="JetArea_Residual_EtaJES", + CalibArea="00-04-82", + IsData=False) + + ToolSvc += jetcalibrationtool + + wpfotoolname = "DFwPFO_"+jetalg+algname + wpfotool = CfgMgr.CP__WeightPFOTool(wpfotoolname) + + pffjvttoolname = 'DFJetPFfJvt_'+jetalg+algname + jetCont = jetalg+"Jets" + + if hasattr(ToolSvc,pffjvttoolname): + jetaugtool.JetForwardPFlowJvtTool = getattr(ToolSvc,pffjvttoolname) + jetaugtool.fJvtMomentKey = outLabel + else: + pffjvttool = CfgMgr.JetForwardPFlowJvtTool(pffjvttoolname, + verticesName=primaryVertexCont, JetContainer=jetCont, + TrackVertexAssociation=jtm.tvassoc.TrackVertexAssociation, + WeightPFOTool=wpfotool, JetCalibrationTool=jetcalibrationtool, + ORName=overlapLabel, FjvtRawName='DFCommonJets_'+outLabel, includePV=includePV) + ToolSvc += pffjvttool + jetaugtool.JetForwardPFlowJvtTool = pffjvttool + jetaugtool.fJvtMomentKey = outLabel + + extjetlog.info('ExtendedJetCommon: Applying PFlow fJvt augmentation to jet collection: '+jetalg+'Jets') + applyJetAugmentation(jetalg,algname,sequence,jetaugtool) + ################################################################## def applyBTaggingAugmentation(jetalg,algname='default',sequence=DerivationFrameworkJob,btagtooldict={}): @@ -787,6 +860,8 @@ def addCHSPFlowObjects(): ################################################################## applyJetCalibration_xAODColl("AntiKt4EMTopo") updateJVT_xAODColl("AntiKt4EMTopo") +applyJetCalibration_xAODColl("AntiKt4EMPFlow") +updateJVT_xAODColl("AntiKt4EMPFlow") applyOverlapRemoval() eventCleanLoose_xAODColl("AntiKt4EMTopo") diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx index dba95878b6dfac5f9acd1d202a1e04cc57b32c11..ce917ddba396d1e21bfeff1b53e0838f3715f256 100644 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.cxx @@ -23,6 +23,7 @@ namespace DerivationFramework { m_jvtTool(""), m_jetJvtEfficiencyTool(""), m_dojvt(false), + m_dofjvt(false), m_dobtag(false), m_jetTrackSumMomentsTool(""), m_decoratetracksum(false), @@ -44,6 +45,8 @@ namespace DerivationFramework { declareProperty("JvtMomentKey", m_jvtMomentKey = "Jvt"); declareProperty("JetJvtTool", m_jvtTool); declareProperty("JetJvtEffTool", m_jetJvtEfficiencyTool); + declareProperty("fJvtMomentKey", m_fjvtMomentKey = "fJvt"); + declareProperty("JetForwardPFlowJvtTool", m_fjvtTool); declareProperty("JetBtagTools", m_btagSelTools); declareProperty("JetBtagWPs", m_btagWP); declareProperty("JetTrackSumMomentsTool", m_jetTrackSumMomentsTool); @@ -58,6 +61,9 @@ namespace DerivationFramework { { ATH_MSG_INFO("Initialising JetAugmentationTool"); + m_container_key = m_containerName; + ATH_CHECK(m_container_key.initialize()); + if(!m_jetCalibTool.empty()) { CHECK(m_jetCalibTool.retrieve()); ATH_MSG_INFO("Augmenting jets with calibration \"" << m_momentPrefix+m_calibMomentKey << "\""); @@ -79,12 +85,27 @@ namespace DerivationFramework { ATH_MSG_INFO("Augmenting jets with updated JVT \"" << m_momentPrefix+m_jvtMomentKey << "\""); m_dojvt = true; + m_acc_JVT = std::make_unique< SG::AuxElement::ConstAccessor<float> >(m_momentPrefix+m_jvtMomentKey); + m_acc_passJVT = std::make_unique< SG::AuxElement::ConstAccessor<char> >(m_momentPrefix+"pass"+m_jvtMomentKey); + m_jvt_key = m_containerName + "." + m_momentPrefix + m_jvtMomentKey; m_passJvt_key = m_containerName + "." + m_momentPrefix + "pass" + m_jvtMomentKey; ATH_CHECK(m_jvt_key.initialize()); ATH_CHECK(m_passJvt_key.initialize()); + // PFlow fJVT tool + if(!m_fjvtTool.empty()) { + CHECK(m_fjvtTool.retrieve()); + ATH_MSG_INFO("Augmenting (PFlow) jets with fJVT \"" << m_momentPrefix+m_fjvtMomentKey << "\""); + m_dofjvt = true; + + m_acc_fJVT = std::make_unique< SG::AuxElement::ConstAccessor<float> >(m_momentPrefix+m_fjvtMomentKey); + + m_fjvt_key = m_containerName + "." + m_momentPrefix + m_fjvtMomentKey; + ATH_CHECK(m_fjvt_key.initialize()); + } + if(!m_btagSelTools.empty()) { size_t ibtag(0); for(const auto& tool : m_btagSelTools) { @@ -106,6 +127,7 @@ namespace DerivationFramework { } if(!m_jetTrackSumMomentsTool.empty()) { + ATH_MSG_INFO("Augmenting jets with track sum moments \"" << m_momentPrefix << "TrackSumMass,Pt\""); CHECK(m_jetTrackSumMomentsTool.retrieve()); ATH_MSG_INFO("Augmenting jets with track sum moments \"" << m_momentPrefix << "TrackSumMass,Pt\""); m_decoratetracksum = true; @@ -168,7 +190,7 @@ namespace DerivationFramework { } } } - + if(!m_jetTruthLabelingTool.empty()) { CHECK(m_jetTruthLabelingTool.retrieve()); ATH_MSG_INFO("Augmenting jets with truthlabeling"); @@ -211,10 +233,11 @@ namespace DerivationFramework { StatusCode JetAugmentationTool::addBranches() const { + // retrieve container - const xAOD::JetContainer* jets(0); - if( evtStore()->retrieve( jets, m_containerName ).isFailure() ) { - ATH_MSG_WARNING ("Couldn't retrieve jets with key: " << m_containerName ); + SG::ReadHandle<xAOD::JetContainer> jets(m_container_key); + if( !jets.isValid() ) { + ATH_MSG_WARNING ("Couldn't retrieve jets with key: " << m_container_key.key() ); return StatusCode::FAILURE; } @@ -229,6 +252,31 @@ namespace DerivationFramework { ATH_MSG_WARNING("Problem applying jet calibration"); return StatusCode::FAILURE; } + + if(m_dojvt){ + + SG::WriteDecorHandle<xAOD::JetContainer, float> jvt_handle(m_jvt_key); + SG::WriteDecorHandle<xAOD::JetContainer, char> passJvt_handle(m_passJvt_key); + + //First update the Jvt criteria (needed for fJVT) + for(const xAOD::Jet *jet : *jets_copy) { + + float jvt_value = m_jvtTool->updateJvt(*jet); + jvt_handle(*jet)= jvt_value; + ATH_MSG_VERBOSE("Calibrated JVT: " << jvt_value); + + bool passJVT = m_jetJvtEfficiencyTool->passesJvtCut(*jet); + passJvt_handle(*jet) = passJVT; + } + + // pFlow fJVT + if(m_dofjvt){ + if((m_fjvtTool->modify(*jets_copy)).isFailure()){ + ATH_MSG_ERROR("Problem computing fJVT"); + return StatusCode::FAILURE; + } + } + } } if(m_decoratetracksum){ @@ -291,16 +339,28 @@ namespace DerivationFramework { if(m_dojvt) { - SG::WriteDecorHandle<xAOD::JetContainer, float> jvt_handle(m_jvt_key); - SG::WriteDecorHandle<xAOD::JetContainer, char> passJvt_handle(m_passJvt_key); + SG::WriteDecorHandle<xAOD::JetContainer, float> jvt_handle(m_jvt_key); + SG::WriteDecorHandle<xAOD::JetContainer, char> passJvt_handle(m_passJvt_key); + + if(m_acc_JVT->isAvailable(*jet)){ + jvt_handle(jet_orig) = (*m_acc_JVT)(*jet); + } + + bool passJVT = false; + + if(m_acc_passJVT->isAvailable(*jet)){ + passJVT = (*m_acc_passJVT)(*jet); + passJvt_handle(jet_orig) = passJVT; + } + + if(m_dofjvt){ + + SG::WriteDecorHandle<xAOD::JetContainer, float> fjvt_handle(m_fjvt_key); + if(m_acc_fJVT->isAvailable(*jet)){ + fjvt_handle(jet_orig) = (*m_acc_fJVT)(*jet); + } + } - float jvt_value = m_jvtTool->updateJvt(*jet); - jvt_handle(jet_orig)= jvt_value; - ATH_MSG_VERBOSE("Calibrated JVT: " << jvt_value); - - bool passJVT = m_jetJvtEfficiencyTool->passesJvtCut(jet_orig); - passJvt_handle(jet_orig) = passJVT; - if(m_dobtag) { size_t ibtag(0); for(const auto& tool : m_btagSelTools) { @@ -332,14 +392,14 @@ namespace DerivationFramework { if(m_acc_GhostTruthAssociationFraction->isAvailable(*jet)){ ghostTruthAssocFrac_handle(jet_orig) = (*m_acc_GhostTruthAssociationFraction)(*jet); - ATH_MSG_INFO("GhostTruthAssociationFraction: " << (*m_acc_GhostTruthAssociationFraction)(jet_orig) ); + ATH_MSG_VERBOSE("GhostTruthAssociationFraction: " << (*m_acc_GhostTruthAssociationFraction)(jet_orig) ); } if(m_acc_GhostTruthAssociationLink->isAvailable(*jet)){ ghostTruthAssocLink_handle(jet_orig) = (*m_acc_GhostTruthAssociationLink)(*jet); - ATH_MSG_INFO("GhostTruthAssociationLink: " << (*m_acc_GhostTruthAssociationLink)(jet_orig) ); + ATH_MSG_VERBOSE("GhostTruthAssociationLink: " << (*m_acc_GhostTruthAssociationLink)(jet_orig) ); } } - + if(m_decoratetruthlabel){ SG::WriteDecorHandle<xAOD::JetContainer, float> truthLabel_dRW_handle(m_truthLabel_dRW_key); @@ -376,9 +436,12 @@ namespace DerivationFramework { if(m_acc_Associated_truthjet_pt->isAvailable(*jet)) associated_truthjet_pt_handle(jet_orig) = (*m_acc_Associated_truthjet_pt)(*jet); if(m_acc_Associated_truthjet_eta->isAvailable(*jet)) associated_truthjet_eta_handle(jet_orig) = (*m_acc_Associated_truthjet_eta)(*jet); } - + } return StatusCode::SUCCESS; } + } + + diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h index 9363efa601c402bd1d846b771ea68e48277aaa19..ff38519d9af77965cccec4eb6e4326bc64a44f7c 100644 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkJetEtMiss/src/JetAugmentationTool.h @@ -43,6 +43,7 @@ namespace DerivationFramework { private: std::string m_momentPrefix; std::string m_containerName; + SG::ReadHandleKey<xAOD::JetContainer> m_container_key {this, "InputJetsKey", "", "Accessor for input JetContainer"}; // // implement augmentations explicitly to avoid need to parse lists of moments to copy // @@ -63,10 +64,15 @@ namespace DerivationFramework { ToolHandle<CP::IJetJvtEfficiency> m_jetJvtEfficiencyTool; std::string m_jvtMomentKey; bool m_dojvt; + std::unique_ptr< SG::AuxElement::ConstAccessor<float> > m_acc_JVT; + std::unique_ptr< SG::AuxElement::ConstAccessor<char> > m_acc_passJVT; //PFlow fJVT - std::unique_ptr< SG::AuxElement::ConstAccessor<float> > m_acc_fjvt; + SG::WriteDecorHandleKey<xAOD::JetContainer> m_fjvt_key {this, "fJVTKey", "", "Decoration for fJVT"}; + ToolHandle<IJetModifier> m_fjvtTool; std::string m_fjvtMomentKey; + bool m_dofjvt; + std::unique_ptr< SG::AuxElement::ConstAccessor<float> > m_acc_fJVT; // b-tagging @author tripiana@cern.ch std::vector<std::string> m_btagWP; diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py index e9e483b64cb86705e744435bbcf275589041544c..64a386f315ec1ed2b8bd09390d8b8d5ffc3924a6 100644 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYS.py @@ -14,7 +14,7 @@ from DerivationFrameworkEGamma import EGammaCommon from DerivationFrameworkEGamma import ElectronsCPDetailedContent from DerivationFrameworkMuons import MuonsCommon from DerivationFrameworkJetEtMiss.JetCommon import OutputJets -from DerivationFrameworkJetEtMiss.ExtendedJetCommon import replaceAODReducedJets, addDefaultTrimmedJets, addJetTruthLabel, addQGTaggerTool +from DerivationFrameworkJetEtMiss.ExtendedJetCommon import replaceAODReducedJets, addDefaultTrimmedJets, addJetTruthLabel, addQGTaggerTool, getPFlowfJVT from DerivationFrameworkJetEtMiss import METCommon from TriggerMenu.api.TriggerAPI import TriggerAPI from TriggerMenu.api.TriggerEnums import TriggerPeriod, TriggerType @@ -189,7 +189,7 @@ addQGTaggerTool(jetalg="AntiKt4EMTopo",sequence=SeqPHYS,algname="QGTaggerToolAlg addQGTaggerTool(jetalg="AntiKt4EMPFlow",sequence=SeqPHYS,algname="QGTaggerToolPFAlg") # fJVT -# getPFlowfJVT(jetalg='AntiKt4EMPFlow',sequence=SeqPHYS, algname='PHYSJetForwardPFlowJvtToolAlg') +getPFlowfJVT(jetalg='AntiKt4EMPFlow',sequence=SeqPHYS, algname='PHYSJetForwardPFlowJvtToolAlg') #==================================================================== # EGAMMA diff --git a/Reconstruction/Jet/JetMomentTools/CMakeLists.txt b/Reconstruction/Jet/JetMomentTools/CMakeLists.txt index 3380b03d56bbe875b6b5c67ece4ba8a3b4f41d62..832412f363214f985b1eec465fbb37088995a27f 100644 --- a/Reconstruction/Jet/JetMomentTools/CMakeLists.txt +++ b/Reconstruction/Jet/JetMomentTools/CMakeLists.txt @@ -13,7 +13,7 @@ atlas_add_library( JetMomentToolsLib JetMomentTools/*.h Root/*.cxx PUBLIC_HEADERS JetMomentTools INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgDataHandlesLib AsgTools InDetTrackSelectionToolLib JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib TrackVertexAssociationToolLib xAODCaloEvent xAODEventInfo xAODJet xAODMissingET xAODTracking xAODTruth + LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgDataHandlesLib AsgTools InDetTrackSelectionToolLib JetCalibToolsLib JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib TrackVertexAssociationToolLib xAODCaloEvent xAODEventInfo xAODJet xAODMissingET xAODTracking xAODTruth PRIVATE_LINK_LIBRARIES CaloGeoHelpers xAODMetaData xAODPFlow PathResolver ) if( NOT XAOD_STANDALONE ) @@ -24,7 +24,7 @@ if( NOT XAOD_STANDALONE ) atlas_add_component( JetMomentTools src/*.h src/*.cxx src/components/*.cxx INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgTools CaloIdentifier xAODCaloEvent xAODJet GaudiKernel JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib PathResolver JetMomentToolsLib ${extra_libs} ) + LINK_LIBRARIES ${Boost_LIBRARIES} ${FASTJET_LIBRARIES} ${ROOT_LIBRARIES} AsgTools CaloIdentifier xAODCaloEvent xAODJet GaudiKernel JetCalibToolsLib JetEDM JetInterface JetRecLib JetUtils PFlowUtilsLib PathResolver JetMomentToolsLib ${extra_libs} ) endif() #if( XAOD_STANDALONE ) diff --git a/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardPFlowJvtTool.h b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardPFlowJvtTool.h new file mode 100644 index 0000000000000000000000000000000000000000..7936f747f7bd0635d9a42fa0ec7c324f4d0f5f53 --- /dev/null +++ b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardPFlowJvtTool.h @@ -0,0 +1,170 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// JetForwardPFlowJvtTool.h +// Header file for class JetForwardPFlowJvtTool +// Author: Anastasia Kotsokechagia <anastasia.kotsokechagia@cern.ch> + +// Tool for calculating fjvt values for pflow jets. +// Short describtion of the tool; +// First central PU jets are built per vertex. +// Reconstructed calibrated jets are then used to calculate the per vertex missing momentum (miss-mom). +// The per vertex missing momentum is defined as: The vector some of the calibrated jet momenta (for jets with pt>20GeV && Rpt>0.1 wrt to the vertex) + tracks assosiated to the vertex (otherwise). +// PU Jets closeby (dR<0.3) to a HS jet are not considered. +// The fJVT value for every forward jet (fj) of the event is then calculated choosing the vertex with the largest negative miss-mom projection on the fj. +// User action: After initializing the tool the user has to call the modify(xAOD::JetContainer& jetCont) function. Argument in this fuction is the PFlow jet container of the event. +// The fjvt value for every forward jet of the container is then calculated and can be retrieved. +/////////////////////////////////////////////////////////////////// + //Parameters + // m_orLabel: "" + // m_jetsName : "Container name for the output reconstructed PU jets " + // m_tightOP: "If true a tight fjvt threshold value is applied" + // m_outLabelFjvt: "Decorator for passing fJVT threshold (tight or loose)" + // m_jetchargedp4: "Name of the jet charged momentum 4-vector" + // m_etaThresh: "Maximum eta value for considering a jet as central" + // m_forwardMinPt: "Minimum forward jet pt" + // m_forwardMaxPt: "Maximum forward jet pt. If -1 no threshold is applied" + // m_centerMinPt: "Minimum central jet pt" + // m_centerMaxPt: "Maximum central jet pt. If -1 no threshold is applied" + // m_pvind: "Hard-Scatter primary vertex index of the event. If -1 it's automatically retrieved from the event" + // m_rptCut: "Rpt cut value for central PU jets contributing in the missing momentum calculation" + // m_jvtCut: "JVT threshold value for considering a central PU jet as HS" + // m_dzCut: "Dz=z-z0 cut value for pfo objects participating in the HS vertex jet reco" + // m_vertices: "Number of vertices for which the missing momentum is calculated" + // m_maxRap: "Maximum rapidity value in fastjet::AreaDefinition" + // m_neutMaxRap: "Maximum rapidity value for neutral pfos participating in jet reco" + // m_weight: "PFO weight value" + // m_pfoToolName: "Name of PFO retriever tool" + // m_wpfoToolName: "Name of PFO weighting tool" + // m_pfoJESName: "Name of jet calibration tool" + // m_jetAlgo: "Jet calibration collection name" + // m_calibconfig: "Calibration config for PFlow jets, need to be updated with latest one" + // m_calibSeq: "Calibration sequence to be applied" + // m_calibArea: "Calibration area" + // m_isdata: "True if data" + + +#ifndef FORWARDPFLOWJVTTOOL_JVT_FORWARDPFLOWJVTTOOL_H +#define FORWARDPFLOWJVTTOOL_JVT_FORWARDPFLOWJVTTOOL_H 1 + +// STL includes +#include <string> + +// FrameWork includes +#include "AsgTools/ToolHandle.h" +#include "AsgTools/AsgTool.h" +#include "AsgTools/PropertyWrapper.h" +#include "JetInterface/IJetDecorator.h" +#include "JetEDM/TrackVertexAssociation.h" +#include "xAODJet/JetContainer.h" +#include "xAODJet/JetAuxContainer.h" + +#include "AsgDataHandles/ReadDecorHandleKey.h" +#include "AsgDataHandles/ReadDecorHandle.h" +#include "AsgDataHandles/WriteDecorHandleKey.h" +#include "AsgDataHandles/WriteDecorHandle.h" + +// Pflow tools +#include "PFlowUtils/IWeightPFOTool.h" +#include "PFlowUtils/WeightPFOTool.h" +#include "JetCalibTools/IJetCalibrationTool.h" + +#include "AsgTools/ToolHandle.h" +#include "JetCalibTools/IJetCalibrationTool.h" + +namespace pflow { + struct puJets { + std::shared_ptr<xAOD::JetContainer> jetCont; + std::shared_ptr<xAOD::JetAuxContainer> jetAuxCont; + }; +} + + class JetForwardPFlowJvtTool + : public asg::AsgTool, + virtual public IJetDecorator{ + ASG_TOOL_CLASS(JetForwardPFlowJvtTool,IJetDecorator) + + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// + public: + + /// Constructor with parameters: + JetForwardPFlowJvtTool(const std::string& name); + + /// Destructor: + virtual ~JetForwardPFlowJvtTool(); + + virtual StatusCode initialize() override; + + + virtual StatusCode decorate(const xAOD::JetContainer& jetCont) const override; + + float getFJVT(const xAOD::Jet *jet,std::vector<TVector2> pileupMomenta) const; + bool isForwardJet(const xAOD::Jet *jet) const; + bool isCentralJet(const xAOD::Jet *jet) const; + + StatusCode tagTruth(const xAOD::JetContainer *jets,const xAOD::JetContainer *truthJets); + std::vector<TVector2> calculateVertexMomenta(const xAOD::JetContainer *jets,int pvind, int vertices) const; + pflow::puJets buildPFlowPUjets(const xAOD::Vertex &vx) const; + bool hasCloseByHSjet(const xAOD::Jet *jet, const xAOD::JetContainer *pjets ) const; + double getRpt(const xAOD::Jet *jet) const; + fastjet::PseudoJet pfoToPseudoJet(const xAOD::PFO* pfo, const CP::PFO_JetMETConfig_charge& theCharge, const xAOD::Vertex *vx) const; + + private: + + SG::ReadHandleKey<jet::TrackVertexAssociation> m_tvaKey{this, "TrackVertexAssociation", "", "Input track-vertex association"}; + Gaudi::Property<std::string> m_jetContainerName{this, "JetContainer", "", "SG key for the input jet container"}; + Gaudi::Property<std::string> m_jetsName{this, "jetsName", "AntiKt4PUPFlowJets", "Container name for the output reconstructed PU jets"}; + Gaudi::Property<std::string> m_jetchargedp4{this, "jetchargedp4", "JetChargedScaleMomentum", "Name of the jet charged momentum 4-vector"}; + Gaudi::Property<std::string> m_pfoToolName{this, "pfoToolName", "PFOTool", "Name of PFO retriever tool"}; + Gaudi::Property<std::string> m_wpfoToolName{this, "wpfoToolName", "WPFOTool", "Name of PFO weighting tool"}; + Gaudi::Property<std::string> m_pfoJESName{this, "pfoJESName", "pfoJES", "Name of jet claibration tool"}; + Gaudi::Property<std::string> m_jetAlgo{this, "jetAlgo", "AntiKt4EMPFlow", "Jet calibration collection name"}; + Gaudi::Property<std::string> m_calibconfig{this, "calibconfig", "JES_MC16Recommendation_Consolidated_PFlow_Apr2019_Rel21.config", "Calibration config for PFlow jets, need to be updated with latest one"}; + Gaudi::Property<std::string> m_calibSeq{this, "calibSeq", "JetArea_Residual_EtaJES", "Calibration sequence to be applied"}; + Gaudi::Property<std::string> m_calibArea{this, "calibArea", "00-04-82", "Calibration area"}; + + Gaudi::Property<bool> m_isdata{this, "isdata", false, "True if data"}; + Gaudi::Property<int> m_pvind{this, "pvind", -1, "Hard-Scatter primary vertex index of the event. If -1 it will be automatically retrieved from the event"}; + Gaudi::Property<int> m_vertices{this, "vertices", 10, "Number of vertices for which the missing momentum is calculated"}; + Gaudi::Property<bool> m_includePV{this, "includePV", false, "Flag to include jets and tracks associated to PV in the calculation"}; + Gaudi::Property<double> m_etaThresh{this, "etaThresh", 2.5, "Maximum eta value for considering a jet as central"}; + Gaudi::Property<double> m_forwardMinPt{this, "forwardMinPt", 20e3, "Minimum forward jet pt"}; + Gaudi::Property<double> m_forwardMaxPt{this, "forwardMaxPt", -1, "Maximum forward jet pt. If -1 no threshold is applied"}; + Gaudi::Property<double> m_centerMinPt{this, "centralMinPt", 20e3, "Minimum central jet pt"}; + Gaudi::Property<double> m_centerMaxPt{this, "centralMaxPt", -1, "Maximum central jet pt. If -1 no threshold is applied"}; + Gaudi::Property<double> m_fjvtThresh{this, "fjvtThresh", 15e3, "fjvt threshold value"}; + Gaudi::Property<double> m_rptCut{this, "rptCut", 0.1, "Rpt cut value for central PU jets contributing in the missing momentum calculation"}; + Gaudi::Property<double> m_jvtCut{this, "jvtCut", 0.2, "JVT threshold value for considering a central PU jet as HS"}; + Gaudi::Property<double> m_dzCut{this, "dzCut", 2.0, "Dz=z=-z0 cut for pfo objects participating in the HS vertex jet reco"}; + Gaudi::Property<double> m_maxRap{this, "maxRap", 2.5, "Maximum rapidity value in fastjet::AreaDefinition"}; + Gaudi::Property<double> m_neutMaxRap{this, "neutMaxRap", 2.5, "Maximum rapidity value for neutral pfos participating in jet reco"}; + Gaudi::Property<float> m_weight{this, "weight", 0, "PFO weight value"}; + Gaudi::Property<bool> m_tightOP{this, "tightOP", false, "If true a tight fjvt threshold value is applied"}; + + // not used? + //Gaudi::Property<std::string> m_jvtMomentName{"jvtMomentName", "", ""}; + //Gaudi::Property<double> m_centerJvtThresh{"", 0, ""}; + + SG::ReadHandleKey<xAOD::VertexContainer> m_vxContKey{this, "verticesName", "PrimaryVertices", "Container name of vertices to be retrieved"}; + SG::ReadHandleKey<xAOD::PFOContainer> m_PFOKey{this, "PFOName", "CHSParticleFlowObjects", "SG Key for CHS PFO Container"}; + + SG::ReadDecorHandleKey<xAOD::JetContainer> m_jvtKey{this, "jvtName", "Jvt", "SG key for the Jvt decoration"}; + SG::ReadDecorHandleKey<xAOD::PFO> m_orKey{this, "ORName", "", "OR label"}; + + SG::WriteDecorHandleKey<xAOD::JetContainer> m_fjvtKey{this, "FjvtName", "passOnlyFJVT", "Decorator for passing fJVT threshold (tight or loose)"}; + SG::WriteDecorHandleKey<xAOD::JetContainer> m_fjvtRawKey{this, "FjvtRawName", "fJvt", "Decorator for raw fJVT variable"}; + SG::WriteDecorHandleKey<xAOD::JetContainer> m_isHSKey{this, "isHSName", "isJVTHS", "SG key for output isJVTHS decoration"}; + SG::WriteDecorHandleKey<xAOD::JetContainer> m_isPUKey{this, "isPUName", "isJvtPU", "SG key for output isJVTPU decoration"}; + + ToolHandle<CP::WeightPFOTool> m_wpfotool{this,"WeightPFOTool", "", "Weight PFO tool name"}; + ToolHandle<IJetCalibrationTool> m_pfoJES{this,"JetCalibrationTool", "", "Jet calibration tool name"}; + + std::size_t getPV() const; + + }; +#endif //> !FORWARDJVTTOOL_JVT_FORWARDJVTTOOL_H diff --git a/Reconstruction/Jet/JetMomentTools/Root/JetForwardPFlowJvtTool.cxx b/Reconstruction/Jet/JetMomentTools/Root/JetForwardPFlowJvtTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..18d25c6833317959d6ce707eb8b247d023e34f43 --- /dev/null +++ b/Reconstruction/Jet/JetMomentTools/Root/JetForwardPFlowJvtTool.cxx @@ -0,0 +1,328 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// JetForwardPFlowJvtTool.cxx +// Implementation file for class JetForwardPFlowJvtTool +// Author: Anastasia Kotsokechagia <anastasia.kotsokechagia@cern.ch> +/////////////////////////////////////////////////////////////////// + +// JetForwardPFlowJvtTool includes +#include "JetMomentTools/JetForwardPFlowJvtTool.h" + +// Jet EDM +#include "xAODJet/JetAttributes.h" + +// FastJet +#include "fastjet/ClusterSequence.hh" +#include "fastjet/ClusterSequenceArea.hh" +#include <fastjet/AreaDefinition.hh> + +// Jet +#include "JetRec/JetFromPseudojet.h" + + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// + + // Constructors + //////////////// + JetForwardPFlowJvtTool::JetForwardPFlowJvtTool(const std::string& name) : + AsgTool(name) { + } + + // Destructor + /////////////// + JetForwardPFlowJvtTool::~JetForwardPFlowJvtTool() + {} + + // Athena algtool's Hooks + //////////////////////////// + StatusCode JetForwardPFlowJvtTool::initialize() + { + ATH_MSG_INFO ("Initializing " << name() << "..."); + if (m_tightOP) m_fjvtThresh = 0.53; + else m_fjvtThresh = 0.72; + + ATH_CHECK( m_tvaKey.initialize() ); + + if(m_jetContainerName.empty()){ + ATH_MSG_ERROR("JetForwardPFlowJvtTool needs to have its input jet container configured!"); + return StatusCode::FAILURE; + } + + if(!m_orKey.key().empty()){ + m_orKey = m_jetContainerName + "." + m_orKey.key(); + ATH_CHECK(m_orKey.initialize()); + } + m_fjvtKey = m_jetContainerName + "." + m_fjvtKey.key(); + m_fjvtRawKey = m_jetContainerName + "." + m_fjvtRawKey.key(); + m_isHSKey = m_jetContainerName + "." + m_isHSKey.key(); + m_isPUKey = m_jetContainerName + "." + m_isPUKey.key(); + m_jvtKey = m_jetContainerName + "." + m_jvtKey.key(); + + ATH_CHECK(m_fjvtKey.initialize()); + ATH_CHECK(m_fjvtRawKey.initialize()); + ATH_CHECK(m_isHSKey.initialize()); + ATH_CHECK(m_isPUKey.initialize()); + ATH_CHECK(m_jvtKey.initialize()); + + ATH_CHECK(m_vxContKey.initialize()); + ATH_CHECK(m_PFOKey.initialize()); + + return StatusCode::SUCCESS; + } + + StatusCode JetForwardPFlowJvtTool::decorate(const xAOD::JetContainer& jetCont) const { + std::vector<TVector2> pileupMomenta; + + pileupMomenta=calculateVertexMomenta(&jetCont,m_pvind, m_vertices); + + SG::WriteDecorHandle<xAOD::JetContainer, char> fjvtHandle(m_fjvtKey); + SG::WriteDecorHandle<xAOD::JetContainer, float> fjvtRawHandle(m_fjvtRawKey); + if(pileupMomenta.size()==0) { + ATH_MSG_DEBUG( "pileupMomenta is empty, this can happen for events with no PU vertices." + <<" fJVT won't be computed for this event and will be set to 0 instead." ); + for(const xAOD::Jet* jetF : jetCont) { + fjvtHandle(*jetF) = 1; + fjvtRawHandle(*jetF) = 0; + } + return StatusCode::SUCCESS; + } + + for(const xAOD::Jet* jetF : jetCont) { + fjvtHandle(*jetF) = 1; + fjvtRawHandle(*jetF) = 0; + + if (isForwardJet(jetF)){ + double fjvt = getFJVT(jetF,pileupMomenta); + if (fjvt>m_fjvtThresh) fjvtHandle(*jetF) = 0; + fjvtRawHandle(*jetF) = fjvt; + } + } + return StatusCode::SUCCESS; + } + + float JetForwardPFlowJvtTool::getFJVT(const xAOD::Jet *jet, std::vector<TVector2> pileupMomenta) const { + TVector2 fjet(jet->pt()*cos(jet->phi()),jet->pt()*sin(jet->phi())); + double fjvt = 0; + for (const TVector2& pu : pileupMomenta) { + double projection = pu*fjet/fjet.Mod(); + if (projection<fjvt) fjvt = projection; + } + return -1*fjvt/fjet.Mod(); + } + + std::vector<TVector2> JetForwardPFlowJvtTool::calculateVertexMomenta(const xAOD::JetContainer *pjets, + int pvind, int vertices) const { + std::vector<TVector2> pileupMomenta; + // -- Retrieve PV index if not provided by user + const std::size_t pv_index = (pvind==-1) ? getPV() : std::size_t(pvind); + + SG::ReadHandle<xAOD::VertexContainer> vxContHandle(m_vxContKey); + + for(const xAOD::Vertex* vx: *vxContHandle) { + if(vx->vertexType()!=xAOD::VxType::PriVtx && vx->vertexType()!=xAOD::VxType::PileUp) continue; + if(vx->index()==(size_t)pv_index) continue; + + TString jname = m_jetsName.value(); + jname += vx->index(); + + pflow::puJets vertjets = buildPFlowPUjets(*vx); + if( !vertjets.jetCont || !vertjets.jetAuxCont ){ + ATH_MSG_WARNING(" Some issue appeared while building the pflow pileup jets for vertex " + << vx->index() << " (vxType = " << vx->vertexType()<<" )!" ); + return pileupMomenta; + } + + TVector2 vertex_met; + for( const xAOD::Jet *jet : *(vertjets.jetCont) ) { + + // Remove jets which are close to hs + if (!m_includePV && hasCloseByHSjet(jet,pjets)) continue; + + // Calculate vertex missing momentum + if (isCentralJet(jet) && getRpt(jet)> m_rptCut) + { + vertex_met += TVector2(jet->pt()*cos(jet->phi()),jet->pt()*sin(jet->phi()) ) ; + } + else{ + vertex_met += TVector2(jet->jetP4(m_jetchargedp4).Pt()*cos(jet->jetP4(m_jetchargedp4).Phi()), + jet->jetP4(m_jetchargedp4).Pt()*sin(jet->jetP4(m_jetchargedp4).Phi()) ); + } + } + + pileupMomenta.push_back(vertex_met); + if(vertices!=-1 && int(vx->index())==vertices) break; + } + return pileupMomenta; + } + + bool JetForwardPFlowJvtTool::hasCloseByHSjet(const xAOD::Jet *jet, const xAOD::JetContainer *pjets ) const { + for (const xAOD::Jet* pjet : *pjets) { + float jet_jvt=0; + SG::ReadDecorHandle<xAOD::JetContainer, float> jvtHandle(m_jvtKey); + jet_jvt = jvtHandle(*pjet); + if (pjet->p4().DeltaR(jet->p4())<0.3 && jet_jvt>m_jvtCut && isCentralJet(pjet) ) return true; + } + return false; + } + + pflow::puJets JetForwardPFlowJvtTool::buildPFlowPUjets(const xAOD::Vertex &vx) const { + pflow::puJets pu_jets; + const std::size_t pv_index = (m_pvind==-1) ? getPV() : std::size_t (m_pvind); + + std::vector<fastjet::PseudoJet> input_pfo; + std::set<int> charged_pfo; + + SG::ReadHandle<jet::TrackVertexAssociation> tvaHandle(m_tvaKey); + SG::ReadHandle<xAOD::PFOContainer> PFOHandle(m_PFOKey); + + if (!tvaHandle.isValid()){ + ATH_MSG_ERROR("Could not retrieve the TrackVertexAssociation: " + << m_tvaKey.key()); + return pu_jets; + } + for(const xAOD::PFO* pfo : *PFOHandle){ + if (m_orKey.key().empty()) continue; + SG::ReadDecorHandle<xAOD::PFO, char> orHandle(m_orKey); + if (!orHandle(*pfo)) continue; + if (pfo->isCharged()) { + if (vx.index()==pv_index && std::abs((vx.z()-pfo->track(0)->z0())*sin(pfo->track(0)->theta()))>m_dzCut) + continue; + if (vx.index()!=pv_index + && (!tvaHandle->associatedVertex(pfo->track(0)) + || vx.index()!=tvaHandle->associatedVertex(pfo->track(0))->index()) + ) continue; + input_pfo.push_back(pfoToPseudoJet(pfo, CP::charged, &vx) ); + charged_pfo.insert(pfo->index()); + } + else if (std::abs(pfo->eta())<m_neutMaxRap && !pfo->isCharged() && pfo->eEM()>0) + { + input_pfo.push_back(pfoToPseudoJet(pfo, CP::neutral, &vx) ); + } + } + std::shared_ptr<xAOD::JetContainer> vertjets = std::make_shared<xAOD::JetContainer>(); + std::shared_ptr<xAOD::JetAuxContainer> vertjetsAux = std::make_shared<xAOD::JetAuxContainer>(); + + vertjets->setStore(vertjetsAux.get()); + TString newname = m_jetsName.value(); + newname += vx.index(); + + fastjet::JetDefinition jet_def(fastjet::antikt_algorithm,0.4); + fastjet::AreaDefinition area_def(fastjet::active_area_explicit_ghosts, + fastjet::GhostedAreaSpec(fastjet::SelectorAbsRapMax(m_maxRap))); + fastjet::ClusterSequenceArea clust_pfo(input_pfo,jet_def,area_def); + std::vector<fastjet::PseudoJet> inclusive_jets = sorted_by_pt(clust_pfo.inclusive_jets(5000.)); + + for (size_t i = 0; i < inclusive_jets.size(); i++) { + xAOD::Jet* jet= new xAOD::Jet(); + xAOD::JetFourMom_t tempjetp4(inclusive_jets[i].pt(), + inclusive_jets[i].eta(), + inclusive_jets[i].phi(), + inclusive_jets[i].m()); + xAOD::JetFourMom_t newArea(inclusive_jets[i].area_4vector().perp(), + inclusive_jets[i].area_4vector().eta(), + inclusive_jets[i].area_4vector().phi(), + inclusive_jets[i].area_4vector().m()); + vertjets->push_back(jet); + jet->setJetP4(tempjetp4); + jet->setJetP4("JetConstitScaleMomentum",tempjetp4); + jet->setJetP4("JetPileupScaleMomentum",tempjetp4); + jet->setAttribute("ActiveArea4vec",newArea); + jet->setAttribute("DetectorEta",jet->eta()); + std::vector<fastjet::PseudoJet> constituents = inclusive_jets[i].constituents(); + float chargedpart = 0; + for (size_t j = 0; j < constituents.size(); j++) { + if (charged_pfo.count(constituents[j].user_index())>=1) { + chargedpart += constituents[j].perp(); + } + } + xAOD::JetFourMom_t chargejetp4(chargedpart,inclusive_jets[i].eta(),inclusive_jets[i].phi(),inclusive_jets[i].m()); + jet->setJetP4(m_jetchargedp4,chargejetp4); + } + + if((m_pfoJES->modify(*vertjets)).isFailure()){ + ATH_MSG_ERROR(" Failed to calibrate PU jet container "); + return pu_jets; + } + + pu_jets.jetCont = vertjets; + pu_jets.jetAuxCont = vertjetsAux; + return pu_jets; + } + + fastjet::PseudoJet JetForwardPFlowJvtTool::pfoToPseudoJet(const xAOD::PFO* pfo, const CP::PFO_JetMETConfig_charge& theCharge, const xAOD::Vertex *vx) const { + TLorentzVector pfo_p4; + if (CP::charged == theCharge){ + float pweight = m_weight; + if( (m_wpfotool->fillWeight(*pfo,pweight)).isSuccess() ){ + // Create a PSeudojet with the momentum of the selected IParticle + pfo_p4= TLorentzVector(pfo->p4().Px()*pweight,pfo->p4().Py()*pweight,pfo->p4().Pz()*pweight,pfo->e()*pweight); + } + } else if (CP::neutral == theCharge){ + pfo_p4= pfo->GetVertexCorrectedEMFourVec(*vx); + } + fastjet::PseudoJet psj(pfo_p4); + // User index is used to identify the xAOD object used for the PSeudoJet + if (CP::charged == theCharge){ + psj.set_user_index(pfo->index()); + }else{ + psj.set_user_index(-1); + } + + return psj; + } + + bool JetForwardPFlowJvtTool::isForwardJet(const xAOD::Jet *jet) const { + if (std::abs(jet->eta())<m_etaThresh) return false; + if (jet->pt()<m_forwardMinPt || (m_forwardMaxPt>0 && jet->pt()>m_forwardMaxPt) ) return false; + return true; + } + + bool JetForwardPFlowJvtTool::isCentralJet(const xAOD::Jet *jet) const { + if (std::abs(jet->eta())>m_etaThresh) return false; + if (jet->pt()<m_centerMinPt || (m_centerMaxPt>0 && jet->pt()>m_centerMaxPt)) return false; + return true; + } + + double JetForwardPFlowJvtTool::getRpt(const xAOD::Jet *jet) const { + double Rpt; + Rpt= jet->jetP4(m_jetchargedp4).Pt()/ jet->pt(); + return Rpt; + } + + std::size_t JetForwardPFlowJvtTool::getPV() const{ + if (m_includePV) return -1; + + //const xAOD::VertexContainer *vxCont = 0; + SG::ReadHandle<xAOD::VertexContainer> vxContHandle(m_vxContKey); + ATH_MSG_DEBUG("Successfully retrieved primary vertex container"); + for(const xAOD::Vertex *vx : *vxContHandle) { + if(vx->vertexType()==xAOD::VxType::PriVtx) return vx->index(); + } + ATH_MSG_WARNING("Couldn't identify the hard-scatter primary vertex (no vertex with \"vx->vertexType()==xAOD::VxType::PriVtx\" in the container)!"); + // this almost certainly isn't what we should do here, the + // caller doesn't check this for errors + return 0; + } + + StatusCode JetForwardPFlowJvtTool::tagTruth(const xAOD::JetContainer *jets,const xAOD::JetContainer *truthJets) { + SG::WriteDecorHandle<xAOD::JetContainer, bool> isHSHandle(m_isHSKey); + SG::WriteDecorHandle<xAOD::JetContainer, bool> isPUHandle(m_isPUKey); + + for(const xAOD::Jet *jet : *jets) { + bool ishs = false; + bool ispu = true; + for(const xAOD::Jet *tjet : *truthJets) { + if (tjet->p4().DeltaR(jet->p4())<0.3 && tjet->pt()>10e3) ishs = true; + if (tjet->p4().DeltaR(jet->p4())<0.6) ispu = false; + } + isHSHandle(*jet)=ishs; + isPUHandle(*jet)=ispu; + } + return StatusCode::SUCCESS; + } + diff --git a/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx b/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx index e9286347a60537436517cceb7cabfe81abe004fc..674e1747036892b52be33ae7661bf7aafc257992 100644 --- a/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx +++ b/Reconstruction/Jet/JetMomentTools/src/components/JetMomentTools_entries.cxx @@ -5,6 +5,7 @@ #include "JetMomentTools/JetVertexFractionTool.h" #include "JetMomentTools/JetVertexTaggerTool.h" #include "JetMomentTools/JetForwardJvtTool.h" +#include "JetMomentTools/JetForwardPFlowJvtTool.h" #include "JetMomentTools/JetTrackMomentsTool.h" #include "JetMomentTools/JetTrackSumMomentsTool.h" #include "JetMomentTools/JetClusterMomentsTool.h" @@ -29,6 +30,7 @@ DECLARE_COMPONENT( JetWidthTool ) DECLARE_COMPONENT( JetVertexFractionTool ) DECLARE_COMPONENT( JetVertexTaggerTool ) DECLARE_COMPONENT( JetForwardJvtTool ) +DECLARE_COMPONENT(JetForwardPFlowJvtTool) DECLARE_COMPONENT( JetTrackMomentsTool ) DECLARE_COMPONENT( JetTrackSumMomentsTool ) DECLARE_COMPONENT( JetClusterMomentsTool )