From 93c59a6cc94457b6f841f5960220cf8f6dd5b1e8 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Delsart <delsart@in2p3.fr> Date: Fri, 13 Nov 2020 18:05:08 +0000 Subject: [PATCH] Implement standard small R jet definition in new style jet config --- .../xAODJet/xAODJet/test_utils/JetFactory.h | 173 ++++++++++++++++++ .../Root/JetParticleAssociation.cxx | 2 +- .../python/ParticleJetToolsConfig.py | 10 +- .../python/JetCalibToolsConfig.py | 2 +- .../JetMomentTools/JetForwardJvtTool.h | 1 + .../JetMomentTools/JetForwardJvtToolBDT.h | 1 + .../python/JetMomentToolsConfig.py | 68 +++---- .../Jet/JetRecConfig/python/JetDefinition.py | 146 ++++++++++++--- .../Jet/JetRecConfig/python/JetInputConfig.py | 3 +- .../Jet/JetRecConfig/python/JetModConfig.py | 19 +- .../Jet/JetRecConfig/python/JetRecConfig.py | 105 ++++++----- .../python/StandardJetConstits.py | 24 ++- .../JetRecConfig/python/StandardJetMods.py | 50 ++--- .../JetRecConfig/python/StandardSmallRJets.py | 67 +++++-- .../Jet/JetRecConfig/share/JetRecTestCfg.py | 57 +++--- .../JetRecTools/python/JetRecToolsConfig.py | 6 +- .../HLTMenuConfig/Jet/JetRecoConfiguration.py | 6 +- .../HLTMenuConfig/Jet/TriggerJetMods.py | 28 ++- .../python/HLTMenuConfig/Jet/generateJet.py | 8 +- 19 files changed, 537 insertions(+), 239 deletions(-) create mode 100644 Event/xAOD/xAODJet/xAODJet/test_utils/JetFactory.h diff --git a/Event/xAOD/xAODJet/xAODJet/test_utils/JetFactory.h b/Event/xAOD/xAODJet/xAODJet/test_utils/JetFactory.h new file mode 100644 index 00000000000..46963860e39 --- /dev/null +++ b/Event/xAOD/xAODJet/xAODJet/test_utils/JetFactory.h @@ -0,0 +1,173 @@ +// this file is -*- C++ -*- +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef XAODJET_TEST_JETFACTORY_H +#define XAODJET_TEST_JETFACTORY_H + +#include <map> +#include <vector> +#include "xAODJet/JetContainer.h" +#include "xAODJet/JetAuxContainer.h" + +#include "xAODCaloEvent/CaloClusterContainer.h" +#include "xAODCaloEvent/CaloClusterAuxContainer.h" + +#ifndef XAOD_STANDALONE +// allows to test EL +#include "AthLinks/ElementLink.h" +#include "SGTools/TestStore.h" +using namespace SGTest; +#else +#include "xAODRootAccess/Init.h" +#include "xAODRootAccess/TEvent.h" +#include "xAODRootAccess/TStore.h" +#include "xAODRootAccess/TActiveStore.h" +#endif + + +namespace xAOD { + namespace JetTests { + + + template<typename T> + void record ATLAS_NOT_THREAD_SAFE (T* cont, const std::string & name) { +#ifndef XAOD_STANDALONE + // *********************** init in Athena +# ifdef SGTOOLS_CURRENTEVENTSTORE_H + initTestStore(); +# else + SG::getDataSourcePointerFunc = getTestDataSourcePointer; +# endif + store.record(cont, name); + store.record((xAOD::IParticleContainer*)cont, name); // also store the container as an IParticleContainer +#else + // *********************** init in standalone + + gErrorIgnoreLevel = kWarning; + assert( xAOD::Init() ); + // Create a TEvent object: + xAOD::TEvent eventstore(xAOD::TEvent::kClassAccess); + + xAOD::TStore tds; + xAOD::TStore* transDataStore = xAOD::TActiveStore::store(); + + assert( transDataStore != 0 ); + + tds.record(cont, name).ignore(); + +#endif + + } + + + + /// Create and return an empty JetContainer. JetContainer has an AuxContainer associated and is recorded in an event store so its elements can be used as ElementLink. + JetContainer * createEmptyJetContainer ATLAS_NOT_THREAD_SAFE (const std::string & name) { + JetContainer * jetCont = new JetContainer(); + JetAuxContainer* aux = new xAOD::JetAuxContainer(); + jetCont->setStore(aux); + record(jetCont, name); + return jetCont; + } + + + + /// Fill input JetContainer with new jets which 4-momentum are given by jet4moms + void fillJets(JetContainer & jetCont, const std::vector<xAOD::JetFourMom_t>& jet4moms ){ + for( const xAOD::JetFourMom_t &v : jet4moms ){ + jetCont.push_back(new xAOD::Jet()); + xAOD::Jet *jet = jetCont.back(); + jet->setJetP4( v ); // set the P4 of the last inserted jet + } + + } + + /// Fill input JetContainer with new jets which 4-momentum are given by jet4moms and with attributes as given by the map "jetAttMap". It is expected that vectors in this map have same lenght as jet4moms + void fillJets(JetContainer & jetCont, const std::vector<xAOD::JetFourMom_t>& jet4moms, + const std::map<std::string, std::vector<float>> jetAttMap + ){ + int i=0; + for( const xAOD::JetFourMom_t &v : jet4moms ){ + jetCont.push_back(new xAOD::Jet()); + xAOD::Jet *jet = jetCont.back(); + jet->setJetP4( v ); // set the P4 of the last inserted jet + for( const auto& attpair : jetAttMap) { jet->setAttribute<float>(attpair.first, attpair.second[i]);} + i++; + } + + } + + + /// Fill input JetContainer with a list of test jets + void fillStandardTestJets(JetContainer& jetCont){ + static const std::vector<xAOD::JetFourMom_t> jet4moms = + { + xAOD::JetFourMom_t(40000, 0, 1, 10000 ), + xAOD::JetFourMom_t(40000, 0.01, 2, 10000 ), + xAOD::JetFourMom_t(40000, 0.01, 2, 0.), + xAOD::JetFourMom_t(40000, 0.2, 2, 10000.), + xAOD::JetFourMom_t(40000, 1.0, 2, 10000.), + xAOD::JetFourMom_t(40000, 1.001, 2, 10000.), + xAOD::JetFourMom_t(40000, 2., 2, 10000.), + xAOD::JetFourMom_t(40000, 3., 2, 10000.), + xAOD::JetFourMom_t(40000, 3.22, 2, 10000.), + xAOD::JetFourMom_t(40000, 4., 2, 10000.), + xAOD::JetFourMom_t(40000, 5., 2, 10000.), + xAOD::JetFourMom_t(40000, 5.5, 2, 10000.), + + xAOD::JetFourMom_t(0.1, 1.0, 2, 10000.), + xAOD::JetFourMom_t(100000, 1.0, 2, 10000.), + xAOD::JetFourMom_t(500000, 1.0, 2, 10000.), + xAOD::JetFourMom_t(1000000, 1.0, 2, 10000.), + xAOD::JetFourMom_t(10000000, 1.0, 2, 10000.), + + xAOD::JetFourMom_t(100000, 1.0, 2, 100000.), + xAOD::JetFourMom_t(100000, 1.0, 2, 1000000.) + }; + + std::map< std::string, std::vector<float> > jetAttMap = + { { "Width", std::vector<float>(jet4moms.size(), 0.123 )} }; + fillJets(jetCont, jet4moms, jetAttMap); + + // also set scales : + for(Jet* jet: jetCont){ + jet->setJetP4(xAOD::JetScale::JetConstitScaleMomentum, 0.9*jet->jetP4()); + jet->setJetP4(xAOD::JetScale::JetEMScaleMomentum, 0.7*jet->jetP4()); + } + } + + + + /// Create and return an empty CaloClusterAuxContainer. CaloClusterAuxContainer has an AuxContainer associated and is recorded in an event store so its elements can be used as ElementLink. + CaloClusterContainer * createEmptyCaloClusterContainer ATLAS_NOT_THREAD_SAFE (const std::string & name) { + CaloClusterContainer * clustCont = new CaloClusterContainer(); + xAOD::CaloClusterAuxContainer* aux = new xAOD::CaloClusterAuxContainer(); + clustCont->setStore(aux); + record(clustCont, name); + return clustCont; + } + + + /// Fill input CaloClusterAuxContainer with a list of test clusters (with only their default and Raw 4-momentum set) + void fillStandardTestClusters ATLAS_NOT_THREAD_SAFE (CaloClusterContainer & clustCont){ + + for(int i=0; i<10; i++){ + xAOD::CaloCluster *cl = new xAOD::CaloCluster(); + clustCont.push_back(cl); + +#define SETCLUSTERMOM( E, eta, phi ) cl->setE(E);cl->setEta(eta);cl->setPhi(phi);cl->setM(0) +#define SETCLUSTERRAWMOM( E, eta, phi ) cl->setRawE(E);cl->setRawEta(eta);cl->setRawPhi(phi);cl->setRawM(0) + SETCLUSTERMOM( 1000+i*1.1, -5+i*0.1, 0); + SETCLUSTERRAWMOM( 500+i*2.2, -5+i*0.1, 0); + + } + } + + + } +} + +#endif + diff --git a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetParticleAssociation.cxx b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetParticleAssociation.cxx index 49f28af9b1b..cc54bbce726 100644 --- a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetParticleAssociation.cxx +++ b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/Root/JetParticleAssociation.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ // author: cpollard@cern.ch diff --git a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/python/ParticleJetToolsConfig.py b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/python/ParticleJetToolsConfig.py index c35dfe4c54e..12ed1504396 100644 --- a/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/python/ParticleJetToolsConfig.py +++ b/PhysicsAnalysis/AnalysisCommon/ParticleJetTools/python/ParticleJetToolsConfig.py @@ -41,6 +41,7 @@ def getCopyTruthLabelParticles(truthtype): truthcategory = "Partons" elif truthtype in ["WBosons", "ZBosons", "HBosons", "TQuarksFinal"]: truthcategory = "BosonTop" + toolProperties['ParticleType'] = truthtype else: truthcategory = "FlavourLabel" toolProperties['ParticleType'] = truthtype @@ -89,8 +90,13 @@ def getJetConeLabeling(): ) return truthpartonlabel - # Cone matching for B, C and tau truth for all but track jets. -def getJetDeltaRLabelTool(modspec): +def getJetDeltaRLabelTool(jetdef, modspec): + """returns a ParticleJetDeltaRLabelTool + Cone matching for B, C and tau truth for all but track jets. + + This function is meant to be used as callback from JetRecConfig where + it is called as func(jetdef, modspec). Hence the jetdef argument even if not used in this case. + """ jetptmin = float(modspec) jetdrlabeler = CompFactory.ParticleJetDeltaRLabelTool( "jetdrlabeler_jetpt{0}GeV".format(int(jetptmin/1000)), diff --git a/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py b/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py index 61e9cca8e9c..53cc8da8690 100644 --- a/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py +++ b/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py @@ -187,6 +187,6 @@ def getCalibSpecsFromString(modspec): return calibcontext, data_type, calibseq, rhoname, pvname, gscdepth # This method instantiates the JetCalibTool given the input mod specification -def getJetCalibToolFromString(modspec,jetdef): +def getJetCalibToolFromString(jetdef, modspec): calibcontext, data_type, calibseq, rhoname, pvname, gscdepth = getCalibSpecsFromString(modspec) return getJetCalibTool(jetdef.basename,calibcontext,data_type,calibseq,rhoname,pvname,gscdepth) diff --git a/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtTool.h b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtTool.h index 479f898a884..6982167a924 100644 --- a/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtTool.h +++ b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtTool.h @@ -27,6 +27,7 @@ #include "xAODTracking/VertexContainer.h" #include "xAODMissingET/MissingETContainer.h" #include "xAODCaloEvent/CaloCluster.h" +#include "xAODTracking/VertexContainer.h" #include "JetInterface/IJetDecorator.h" #include "AsgTools/IAsgTool.h" diff --git a/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtToolBDT.h b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtToolBDT.h index 300f7db52b4..87ba3dd0fc0 100644 --- a/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtToolBDT.h +++ b/Reconstruction/Jet/JetMomentTools/JetMomentTools/JetForwardJvtToolBDT.h @@ -38,6 +38,7 @@ #include "AsgDataHandles/ReadDecorHandle.h" #include "AsgDataHandles/WriteDecorHandleKey.h" #include "AsgDataHandles/WriteDecorHandle.h" +#include "xAODTracking/VertexContainer.h" namespace TMVA{ class Reader; } diff --git a/Reconstruction/Jet/JetMomentTools/python/JetMomentToolsConfig.py b/Reconstruction/Jet/JetMomentTools/python/JetMomentToolsConfig.py index dfab14517e7..cff7c264dee 100644 --- a/Reconstruction/Jet/JetMomentTools/python/JetMomentToolsConfig.py +++ b/Reconstruction/Jet/JetMomentTools/python/JetMomentToolsConfig.py @@ -1,12 +1,17 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration -######################################################################## -# # -# JetMomentToolsConfig: A helper module for configuring jet moment # -# tools, in support of JetRecConfig.JetModConfig. # -# Author: TJ Khoo # -# # -######################################################################## +""" + + JetMomentToolsConfig: A helper module for configuring jet moment + tools, in support of JetRecConfig.JetModConfig. + Author: TJ Khoo + + +IMPORTANT : all the getXYZTool(jetdef, modspec) functions are meant to be used as callback from the main JetRecConfig module +when we need to convert definitions of tools into the actual tools. At this point the functions are invoked as + func(jetdef, modspec) +Hence they have jetdef and modspec arguments even if not needed in every case. +""" from AthenaCommon import Logging jetmomentlog = Logging.logging.getLogger('JetMomentToolsConfig') @@ -17,15 +22,8 @@ from AthenaConfiguration.ComponentFactory import CompFactory from xAODBase.xAODType import xAODType -def getCaloQualityTool(): - caloqual = CompFactory.JetCaloQualityTool( - "caloqual", - TimingCuts = [5, 10], - Calculations = ["LArQuality", "N90Constituents", "FracSamplingMax", "NegativeE", "Timing", "HECQuality", "Centroid", "AverageLArQF", "BchCorrCell"], - ) - return caloqual -def getEMScaleMomTool(jetdef): +def getEMScaleMomTool(jetdef, modspec=""): # This may need updating e.g. for evolving trigger cluster container names # We do the non-trivial summation over constituents unless the jets were # built directly from EM-scale topoclusters, in which case we can just @@ -46,7 +44,7 @@ def getEMScaleMomTool(jetdef): return emscalemom -def getConstitFourMomTool(jetdef): +def getConstitFourMomTool(jetdef, modspec=""): ### Not ideal, but because CaloCluster.Scale is an internal class ### it makes the dict load really slow. ### So just copy the enum to a dict... @@ -93,22 +91,23 @@ def getConstitFourMomTool(jetdef): return cfourmom # Jet vertex fraction with selection. -def getJVFTool(modspec=""): +def getJVFTool(jetdec, modspec): jettrackselloose = JetRecToolsConfig.getTrackSelTool(modspec) - + # retrieve the tracking keys to be used with modspec : + trackingKeys = trackcollectionmap[modspec] jvf = CompFactory.JetVertexFractionTool( "jvf", - VertexContainer = trackcollectionmap[modspec]["Vertices"], - AssociatedTracks = trackcollectionmap[modspec]["GhostTracksLabel"], - TrackVertexAssociation = trackcollectionmap[modspec]["TVA"], - TrackParticleContainer = trackcollectionmap[modspec]["Tracks"], + VertexContainer = trackingKeys["Vertices"], + AssociatedTracks = trackingKeys["GhostTracksLabel"], + TrackVertexAssociation = trackingKeys["TVA"], + TrackParticleContainer = trackingKeys["Tracks"], TrackSelector = jettrackselloose, ) return jvf # Jet vertex fraction with selection. -def getJVTTool(modspec=""): +def getJVTTool(jetdef, modspec): jvt = CompFactory.JetVertexTaggerTool( "jvt", VertexContainer = trackcollectionmap[modspec]["Vertices"], @@ -116,27 +115,30 @@ def getJVTTool(modspec=""): return jvt -def getTrackMomentsTool(modspec=""): +def getTrackMomentsTool(jetdef, modspec): jettrackselloose = JetRecToolsConfig.getTrackSelTool(modspec) + # retrieve the tracking keys to be used with modspec : + trackingKeys = trackcollectionmap[modspec] trackmoments = CompFactory.JetTrackMomentsTool( "trkmoms", - VertexContainer = trackcollectionmap[modspec]["Vertices"], - AssociatedTracks = trackcollectionmap[modspec]["GhostTracksLabel"], - TrackVertexAssociation = trackcollectionmap[modspec]["TVA"], + VertexContainer = trackingKeys["Vertices"], + AssociatedTracks = trackingKeys["GhostTracksLabel"], + TrackVertexAssociation = trackingKeys["TVA"], TrackMinPtCuts = [500, 1000], TrackSelector = jettrackselloose ) return trackmoments -def getTrackSumMomentsTool(modspec=""): +def getTrackSumMomentsTool(jetdef, modspec): jettrackselloose = JetRecToolsConfig.getTrackSelTool(modspec) - + # retrieve the tracking keys to be used with modspec : + trackingKeys = trackcollectionmap[modspec] tracksummoments = CompFactory.JetTrackSumMomentsTool( "trksummoms", - VertexContainer = trackcollectionmap[modspec]["Vertices"], - AssociatedTracks = trackcollectionmap[modspec]["GhostTracksLabel"], - TrackVertexAssociation = trackcollectionmap[modspec]["TVA"], + VertexContainer = trackingKeys["Vertices"], + AssociatedTracks = trackingKeys["GhostTracksLabel"], + TrackVertexAssociation = trackingKeys["TVA"], RequireTrackPV = True, TrackSelector = jettrackselloose ) @@ -144,7 +146,7 @@ def getTrackSumMomentsTool(modspec=""): # This tool sets a decoration saying which the nominal HS PV was. # Historically it did the origin correction, but now we do this to constituents -def getOriginCorrVxTool(modspec=""): +def getOriginCorrVxTool(jetdef, modspec): origin_setpv = CompFactory.JetOriginCorrectionTool( "jetorigin_setpv", VertexContainer = trackcollectionmap[modspec]["Vertices"], diff --git a/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py b/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py index b762ff29784..9142d30d879 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py @@ -5,6 +5,18 @@ JetDefinition: A module for classes encoding definitions of jets and related objects for configuring jet reconstruction +Various classes encode definitions of different types of components used in Jet Reco. +They are : + + - JetInputDef : describes how to build a source container, typically external to the jet domain. This includes input to jet finding (ex: CaloCluster, Track) but also other sources like EventDensity... + + - JetConstitSource : describes specifically a input constituents source (an input to a PseudoJetAlgorithm), thus referring to a JetInputDef. + - JetConstitSeq : a subclass of JetConstitSource, describing how the constituents are modified by a JetConstituentModSequence (ex: PU or Origin correction). + - JetConstitModifier : describes a constituent modifier tool to be used in a JetConstituentModSequence + + - JetDefinition : describes a full jet reco sequence. Uses a JetConstitSource and a list of JetModifier + - JetModifier : describes a JetModifier c++ tool. + Author: TJ Khoo, P-A Delsart """ @@ -17,10 +29,11 @@ jetlog = Logging.logging.getLogger('JetDefinition') from xAODBase.xAODType import xAODType from .Utilities import make_lproperty, onlyAttributesAreProperties, clonable, make_alias -# Code from JetRecUtils -# define the convention that we write R truncating the decimal point -# if R>=1, then we write R*10 def formatRvalue(parameter): + """Define the convention that we write R truncating the decimal point + if R>=1, then we write R*10. + (Code from JetRecUtils ) + """ # impose precision limits where there could be ambiguity if int(10*parameter)>=1 and int(100*parameter % 10): #jetlog.warning('Radius parameter {0} exceeds allowable precision of 0.1'.format(parameter)) @@ -53,9 +66,8 @@ class JetDefinition(object): radius, # The jet radius specifier (clustering cutoff) inputdef, # The input JetConstit ptmin=5e3*MeV, # The pt cutoff for fastjet in MeV - ptminfilter=5e3*MeV, # The minimum pt to retain xAOD jets after calibration in MeV - ghostdefs=[], # The list of JetGhosts to ghost-associate - modifiers=[], # The list of JetModifiers to execute after jet finding + ghostdefs=[], # The list of alias to JetGhosts to ghost-associate + modifiers=[], # The list of alias to JetModifiers to execute after jet finding extrainputs=[], # The list of additional input types needed for jet finding standardRecoMode = False, # prefix = "", # allows to tune the full JetContainer name @@ -78,9 +90,6 @@ class JetDefinition(object): self._defineName() self.ptmin = ptmin # The pt down to which FastJet is run - self.ptminfilter = ptminfilter # The pt above which xAOD::Jets are kept, may include calibration - if ptmin<1000.*MeV or ptminfilter<1000.*MeV: - jetlog.warning("Very low filter threshold set: ptmin {0:.0f} MeV, ptminfilter {1:.0f} MeV. Are you sure?") self.ghostdefs = ghostdefs # Objects to ghost-associate self.modifiers = modifiers # Tools to modify the jet @@ -100,7 +109,7 @@ class JetDefinition(object): def __hash__(self): - return hash((self.__radius,self.__inputdef,self.ptmin,self.ptminfilter,str(self.ghostdefs),str(self.modifiers),str(self.extrainputs))) + return hash((self.__radius,self.__inputdef,self.ptmin,str(self.ghostdefs),str(self.modifiers),str(self.extrainputs))) def __eq__(self,rhs): return self.__hash__() == rhs.__hash__() @@ -198,14 +207,15 @@ class JetDefinition(object): @clonable @onlyAttributesAreProperties class JetModifier(object): - """Helper to instantiate a generic jet modifier + """Helper to define the config of a IJetModifier tool. Tools that typically have more complex properties set should have their own dedicated helper 'createfn' functions defined""" def __init__(self,tooltype,toolname, createfn=None, filterfn=_condAlwaysPass, - prereqs=[],modspec=None,passJetDef=False, + prereqs=[],modspec=None, + **properties ): # For the easy cases where no helper function is needed. # They will be ignored in the case of a helper, @@ -214,11 +224,10 @@ class JetModifier(object): self.tooltype = tooltype self.toolname = toolname - # The helper function may take up to 2 parameters: + # The helper function may take 2 parameters: # a "modifier specification" string and the jet - # definition, which will be passed in based - # on the values of modspec and passJetDef. - # + # definition + # The helper function always returns the desired # modifier, and a ComponentAccumulator instance, # in case additional supporting tools/services @@ -228,7 +237,6 @@ class JetModifier(object): else: self.createfn = createfn self.modspec = modspec - self.passJetDef = passJetDef # Prereqs is normally a list. # However, in special cases, the prereqs may @@ -241,6 +249,9 @@ class JetModifier(object): # The function must return a tuple : (bool, "reason of failure") self.filterfn = filterfn + # These will be set as the Gaudi properties of the C++ tool + self.properties = properties + self._instanceMap = {} #self._locked = lock @@ -255,16 +266,16 @@ class JetModifier(object): @make_lproperty def modspec(self):pass @make_lproperty - def passJetDef(self):pass - @make_lproperty def prereqs(self):pass @make_lproperty def filterfn(self):pass + @make_lproperty + def properties(self):pass def __hash__(self): - return hash((self.toolname,self.tooltype,self.createfn.__name__,self.modspec,self.passJetDef,str(self.prereqs))) + return hash((self.toolname,self.tooltype,self.createfn.__name__,self.modspec,str(self.prereqs))) def __eq__(self,rhs): return self.__hash__() == rhs.__hash__() @@ -278,9 +289,15 @@ class JetModifier(object): # Need to override __repr__ for printing in lists etc __repr__ = __str__ - def getGenericModifier(self,**kwargs): + def getGenericModifier(self,jetdef, modspec): + """returns a real tool instance accoding to this definition : simply instantiating from + class self.tooltype and with name self.toolname ( actually : self.toolname.format(modspec) ) + Since this function will be called as a callback from JetRecConfig as 'func(jetdef, modspec)', it must accept + the jetdef argument, even if unused in this case. + """ from AthenaConfiguration.ComponentFactory import CompFactory - tool = CompFactory.getComp(self.tooltype)(self.toolname) + name = self.toolname.format(modspec=modspec) + tool = CompFactory.getComp(self.tooltype)(name) return tool @@ -310,7 +327,7 @@ class JetInputDef(object): - filterfn : a function taking a CondFlags as argument and deciding if this JetModifier is compatible with the conditions (same as JetModifier.filterfn ) The function must return a tuple : (bool, "reason of failure") - - prereqs : a list of prerequisites for this input definition. + - prereqs : a list of prerequisites (str) for this input definition. """ def __init__(self, name, objtype, algoBuilder=None, specs=None, filterfn= _condAlwaysPass, prereqs=[]): self.name = name @@ -374,8 +391,73 @@ class JetConstitModifier(object): def tooltype(self): pass @make_lproperty def properties(self): pass - + + + +from enum import IntEnum, auto +class JetInputType(IntEnum): + """We reproduce the Enum from in xAODJet/​JetContainerInfo.h, xAOD::JetInput : loading the C++ library + can slow down a lot the configuration. + Note : this is different from the xAODType which describes *only* c++ types whereas JetInputType describes + categories of inputs to jets. + """ + LCTopo=0 + EMTopo=auto() + TopoTower=auto() + Tower=auto() + Truth=auto() + TruthWZ=auto() + Track=auto() + PFlow=auto() + LCPFlow=auto() # LC PFlow + EMPFlow=auto() # EM Pflow at EM scale + EMCPFlow=auto() # EM Pflow calibrated to LC scale + Jet=auto() + LCTopoOrigin=auto() + EMTopoOrigin=auto() + TrackCaloCluster=auto() + TruthDressedWZ=auto() # Truth jets without prompt e/mu (or dressed photons) or prompt gammas + EMTopoOriginSK=auto() + EMTopoOriginCS=auto() + EMTopoOriginVor=auto() + EMTopoOriginCSSK=auto() + EMTopoOriginVorSK=auto() + LCTopoOriginSK=auto() + LCTopoOriginCS=auto() + LCTopoOriginVor=auto() + LCTopoOriginCSSK=auto() + LCTopoOriginVorSK=auto() + EMPFlowSK=auto() + EMPFlowCS=auto() + EMPFlowVor=auto() + EMPFlowCSSK=auto() + EMPFlowVorSK=auto() + TruthCharged=auto() # Truth jets with only charged particles + EMTopoOriginTime=auto() + EMTopoOriginSKTime=auto() + EMTopoOriginCSSKTime=auto() + EMTopoOriginVorSKTime=auto() + EMPFlowTime=auto() + EMPFlowSKTime=auto() + EMPFlowCSSKTime=auto() + EMPFlowVorSKTime=auto() + HI=auto() + HIClusters=auto() + Other = 100 + EMPFlowFE = 200 # Temporary, until xAOD::PFO is phased out and replaced with xAOD::FlowElement + Uncategorized= 1000 + + def fromxAODType(xt): + """Returns a default JetInputType for a given xAODType """ + _xaodTojetinputMap = { + xAODType.CaloCluster : JetInputType.LCTopo, + xAODType.ParticleFlow : JetInputType.EMPFlow, + xAODType.TrackParticle : JetInputType.Track, + xAODType.TruthParticle : JetInputType.Truth, + } + return _xaodTojetinputMap.get(xt, JetInputType.Other) + @clonable @onlyAttributesAreProperties class JetConstitSource(object): @@ -390,9 +472,11 @@ class JetConstitSource(object): containername, # The key of the source container in the event store. prereqs = [], # will contain references to JetInputDef label = None, # used to describe a category for these constits. if None, will default to name + jetinputtype=None, # The JetInputType category. Can be passed as a string. + # if None, set according to objtype. filterfn=_condAlwaysPass, lock = False, # lock all properties of this instance - ): + ): self.name = name self.containername = containername @@ -403,6 +487,10 @@ class JetConstitSource(object): self.basetype = objtype self.filterfn = filterfn + jetinputtype = jetinputtype or JetInputType.fromxAODType( objtype ) + if isinstance(jetinputtype, str): jetinputtype = JetInputType[jetinputtype] + self.jetinputtype = jetinputtype + self._locked = lock @make_lproperty @@ -417,6 +505,9 @@ class JetConstitSource(object): @make_lproperty def filterfn(self):pass + @make_lproperty + def jetinputtype(self): pass + # make an alias on containername so JetConstitSource and JetConstitSeq share an interface inputname = make_alias("containername") @@ -434,12 +525,13 @@ class JetConstitSeq(JetConstitSource): inputname=None, # input collection which will be transformed into the source constituents outputname=None, # output collection, will be set to self.containername prereqs = [], # will contain references to JetInputDef - label = None, + label = None, + jetinputtype=None, filterfn=_condAlwaysPass, lock = False, # lock all properties of this instance ): - JetConstitSource.__init__(self,name, objtype, outputname, prereqs=prereqs, filterfn=filterfn,label=label,lock=False, finalinit=False, ) + JetConstitSource.__init__(self,name, objtype, outputname, prereqs=prereqs, jetinputtype=jetinputtype, filterfn=filterfn,label=label,lock=False, finalinit=False, ) self.inputname = inputname or name self.modifiers = modifiers diff --git a/Reconstruction/Jet/JetRecConfig/python/JetInputConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetInputConfig.py index 6c9e48d3f66..8d088449776 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetInputConfig.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetInputConfig.py @@ -19,7 +19,8 @@ def _buildJetAlgForInput(suffix, tools ): def buildJetSelectedTracks( parentjetdef, inputspec ): from JetRecTools import JetRecToolsConfig # Jet track selection - t = JetRecToolsConfig.getTrackSelTool(doWriteTracks=True) + t = JetRecToolsConfig.getTrackSelTool(doWriteTracks=True, + cutLevel="NoCut", minPt=500) return _buildJetAlgForInput("JetSelectedTrack", tools = [ t ] ) diff --git a/Reconstruction/Jet/JetRecConfig/python/JetModConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetModConfig.py index 9d157f17c2b..13ec64fcc86 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetModConfig.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetModConfig.py @@ -13,25 +13,26 @@ modlog = Logging.logging.getLogger('JetModConfig') def getModifier(jetdef, moddef, modspec): """Translate JetModifier into a concrete tool""" - modtool = None modlog.verbose("Retrieving modifier {0}".format(str(moddef))) - # Define some optional keyword arguments - kwargs = {} - if moddef.passJetDef: - kwargs["jetdef"] = jetdef - if modspec!="": - kwargs["modspec"] = modspec - # Get the modifier tool try: - modtool = moddef.createfn(**kwargs) + modtool = moddef.createfn(jetdef, modspec) except Exception as e: modlog.error( "Unhandled modifier specification {0} for mod {1} acting on jet def {2}!".format(modspec,moddef,jetdef.basename) ) modlog.error( "Received exception \"{0}\"".format(e) ) modlog.error( "Helper function is \"{0}\"".format(moddef.createfn) ) raise ValueError( "JetModConfig unable to handle mod {0} with spec \"{1}\"".format(moddef,modspec) ) + + # now we overwrite the default properties of the tool, by those + # set in the moddef : + for k,v in moddef.properties.items(): + if callable(v) : + # The value we got is a function : we call it to get the actual value we want to set on the tool + v = v(jetdef, modspec) + setattr(modtool, k, v) + return modtool diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py index 88b0b327b36..80ffcc3bda1 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py @@ -45,11 +45,11 @@ def JetRecCfg(jetdef0, configFlags): jetsfullname = jetdef.fullname() jetlog.info("Setting up to find {0}".format(jetsfullname)) - sequencename = jetsfullname + sequenceName = jetsfullname components = ComponentAccumulator() from AthenaCommon.CFElements import parOR - components.addSequence( parOR(sequencename) ) + components.addSequence( parOR(sequenceName) ) # create proper config instances for each input and ghost aliases in this jetdef # this implicitely calculates and adds the dependencies. @@ -59,38 +59,62 @@ def JetRecCfg(jetdef0, configFlags): # if in standardRecoMode we will remove whatever is incompatible and still try to run # if not, we raise an exception removeComponentFailingConditions(jetdef, configFlags, raiseOnFailure= not jetdef.standardRecoMode) - + # Schedule the various input collections. # We don't have to worry about ordering, as the scheduler # will handle the details. Just merge the components. - inputcomps = JetInputCfg(jetdef, configFlags, sequenceName=jetsfullname) + inputcomps = JetInputCfg(jetdef, configFlags, sequenceName) components.merge(inputcomps) + + # schedule the algs to create fastjet::PseudoJet objects out of the inputs + pjCompo, pjContainer = PseudoJetCfg(jetdef, configFlags, sequenceName) + components.merge(pjCompo) + + # Generate a JetRecAlg to run the jet finding and modifiers + jetrecalg = getJetRecAlg( jetdef, pjContainer) + components.addEventAlgo(jetrecalg, sequenceName) + jetlog.info("Scheduled JetAlgorithm instance \"jetalg_{0}\"".format(jetsfullname)) + return components + +def PseudoJetCfg(jetdef, configFlags, sequenceName): + """Builds a ComponentAccumulator for creating PseudoJetContainer needed by jetdef. + IMPORTANT returns a tuple : (components, finalPJContainerName) """ + + components = ComponentAccumulator(sequenceName) # Schedule the constituent PseudoJetAlg constitpjalg = getConstitPJGAlg( jetdef.inputdef ) - constitpjkey = constitpjalg.OutputContainer - components.addEventAlgo( constitpjalg, jetsfullname ) - - pjContNames = [constitpjkey] - + components.addEventAlgo( constitpjalg, sequenceName ) + finalPJContainer = constitpjalg.OutputContainer + # Schedule the ghost PseudoJetAlgs ghostlist = [ key for key in jetdef._prereqOrder if key.startswith('ghost:')] - for ghostkey in ghostlist: - ghostdef = jetdef._prereqDic[ghostkey] - ghostpjalg = getGhostPJGAlg( ghostdef ) - components.addEventAlgo( ghostpjalg, sequencename ) - ghostpjkey = ghostpjalg.OutputContainer - pjContNames.append( ghostpjkey ) - - # Generate a JetAlgorithm to run the jet finding and modifiers - # (via a JetRecTool instance). - jetrecalg = getJetAlgorithm(jetsfullname, jetdef, pjContNames) - components.addEventAlgo(jetrecalg, sequencename) + if ghostlist != []: + pjContNames = [finalPJContainer] + for ghostkey in sorted(ghostlist): + ghostdef = jetdef._prereqDic[ghostkey] + ghostpjalg = getGhostPJGAlg( ghostdef ) + components.addEventAlgo( ghostpjalg, sequenceName ) + pjContNames.append( ghostpjalg.OutputContainer ) + + mergeId = mergedPJId( pjContNames ) + finalPJContainer = constitpjalg.OutputContainer+"_merged"+mergeId + mergerName = "PJMerger_id"+mergeId + mergeAlg =CompFactory.PseudoJetMerger( + mergerName, + InputPJContainers = pjContNames, + OutputContainer = finalPJContainer, + ) + components.addEventAlgo( mergeAlg, sequenceName) - jetlog.info("Scheduled JetAlgorithm instance \"jetalg_{0}\"".format(jetsfullname)) - return components + return components, finalPJContainer +_mergedPJContainers = dict() +def mergedPJId(pjList): + t = tuple(pjList) + currentSize = len(_mergedPJContainers) + return str(_mergedPJContainers.setdefault(t, currentSize)) ######################################################################## @@ -138,9 +162,9 @@ def JetInputCfg(jetOrConstitdef, configFlags, sequenceName='AthAlgSeq'): constitalg = ConstModHelpers.getConstitModAlg(inputInstance) if constitalg: components.addEventAlgo(constitalg, primary=isprimary) - else: + else: # it must be a JetInputDef jetlog.debug("Requesting input {} with function {} and specs {}".format(inputInstance.name, inputInstance.algoBuilder, inputInstance.specs) ) - # inputInstance must be a JetInputDef + # check if it has something to build an Algorithm if inputInstance.algoBuilder: components.addEventAlgo( inputInstance.algoBuilder( jetdef, inputInstance.specs ), primary=isprimary ) else: @@ -230,22 +254,21 @@ def getJetAlgorithm(jetname, jetdef, pjContNames, monTool = None): ######################################################################## # Function that substitues JetRecTool + JetAlgorithm # -def getJetRecAlg(jetname, jetdef, pjContNames, modlist): - - jclust = CompFactory.JetClusterer("builder") - jclust.JetAlgorithm = jetdef.algorithm - jclust.JetRadius = jetdef.radius - jclust.PtMin = jetdef.ptmin - jclust.InputPseudoJets = pjContNames - jclust.GhostArea = 0.01 # In which cases do we not want areas? - jclust.JetInputType = jetdef.inputdef.basetype +def getJetRecAlg( jetdef, pjContNames): + """ """ + jclust = CompFactory.JetClusterer( + "builder", + JetAlgorithm = jetdef.algorithm, + JetRadius = jetdef.radius, + PtMin = jetdef.ptmin, + InputPseudoJets = pjContNames, + GhostArea = 0.01, # In which cases do we not want areas? + JetInputType = jetdef.inputdef.jetinputtype, + ) - from . import JetModConfig - mods = [] - for moddef,modspec in modlist: - mod = JetModConfig.getModifier(jetdef,moddef,modspec) - mods.append(mod) + mods = buildJetModifierList(jetdef) + jetname = jetdef.fullname() jra = CompFactory.JetRecAlg( "jetrecalg_"+jetname, Provider = jclust, @@ -442,13 +465,9 @@ if __name__=="__main__": # Add the components from our jet reconstruction job from StandardJetDefs import AntiKt4EMTopo - AntiKt4EMTopo.ptminfilter = 15e3 - AntiKt4EMTopo.modifiers = ["Calib:T0:mc","Sort"] + ["JVT"] + ["PartonTruthLabel"] + AntiKt4EMTopo.modifiers = ["Calib:T0:mc","Filter:15000","Sort"] + ["JVT"] + ["PartonTruthLabel"] cfg.merge(JetRecCfg(AntiKt4EMTopo,ConfigFlags,jetnameprefix="New")) cfg.printConfig(withDetails=False,summariseProps=True) - cfg.run(maxEvents=10) - import sys - sys.exit(0) diff --git a/Reconstruction/Jet/JetRecConfig/python/StandardJetConstits.py b/Reconstruction/Jet/JetRecConfig/python/StandardJetConstits.py index 13005ce8aa2..ae888b49029 100644 --- a/Reconstruction/Jet/JetRecConfig/python/StandardJetConstits.py +++ b/Reconstruction/Jet/JetRecConfig/python/StandardJetConstits.py @@ -78,10 +78,10 @@ _stdInputList = [ _truthFlavours = ["BHadronsInitial", "BHadronsFinal", "BQuarksFinal", - "CHadronsInitial", "CHadronsFinal", "CQuarksFinal", - "TausFinal", - "WBosons", "ZBosons", "HBosons", "TQuarksFinal", - "Partons",] + "CHadronsInitial", "CHadronsFinal", "CQuarksFinal", + "TausFinal", + "WBosons", "ZBosons", "HBosons", "TQuarksFinal", + "Partons",] for label in _truthFlavours: # re-use the main truth input definition : _stdInputList.append( JetInputDef("TruthLabel"+label, xAODType.TruthParticle, @@ -150,7 +150,7 @@ for ji in _stdModList: ## List of standard constituent sequences ## This sequences uses the above constit modifiers _stdSeqList = [ - # Format is : + # Format is typically : # JetConstitSeq( name , input_cont_type, list_of_modifiers, inputcontainer, outputcontainer ) # or # JetConstitSource( name, input_cont_type, containername) @@ -158,9 +158,12 @@ _stdSeqList = [ # ***************************** # Cluster constituents - JetConstitSeq("EMTopoOrigin", xAODType.CaloCluster, ["EM","Origin"], "CaloCalTopoClusters", "EMOriginTopoClusters"), - JetConstitSeq("LCTopoOrigin",xAODType.CaloCluster, ["LC","Origin"],"CaloCalTopoClusters", "LCOriginTopoClusters"), - JetConstitSeq("LCTopoCSSK", xAODType.CaloCluster, ["LC","Origin","CS","SK"],"CaloCalTopoClusters", "LCOriginTopoCSSK"), + JetConstitSeq("EMTopoOrigin", xAODType.CaloCluster, ["EM","Origin"], + "CaloCalTopoClusters", "EMOriginTopoClusters", jetinputtype="EMTopo"), + JetConstitSeq("LCTopoOrigin",xAODType.CaloCluster, ["LC","Origin"], + "CaloCalTopoClusters", "LCOriginTopoClusters", jetinputtype="LCTopo"), + JetConstitSeq("LCTopoCSSK", xAODType.CaloCluster, ["LC","Origin","CS","SK"], + "CaloCalTopoClusters", "LCOriginTopoCSSK", jetinputtype="LCTopo"), @@ -172,7 +175,8 @@ _stdSeqList = [ JetConstitSeq("EMPFlow", xAODType.ParticleFlow,["CorrectPFO", "CHS"] , 'JetETMissParticleFlowObjects', 'CHSParticleFlowObjects'), # Particle Flow Objects with Constituent Subtraction + SoftKiller - JetConstitSeq("EMPFlowCSSK", xAODType.ParticleFlow,["CorrectPFO", "CS","SK", "CHS"] , 'JetETMissParticleFlowObjects', 'CSSKParticleFlowObjects'), + JetConstitSeq("EMPFlowCSSK", xAODType.ParticleFlow,["CorrectPFO", "CS","SK", "CHS"] , + 'JetETMissParticleFlowObjects', 'CSSKParticleFlowObjects', jetinputtype="EMPFlow"), # ***************************** @@ -192,7 +196,7 @@ _stdSeqList = [ # Truth particles (see JetInputDef declarations above for more details) JetConstitSource("Truth", xAODType.TruthParticle, "JetInputTruthParticles" ), - JetConstitSource("TruthWZ", xAODType.TruthParticle, "JetInputTruthParticlesNoWZ" ), + JetConstitSource("TruthWZ", xAODType.TruthParticle, "JetInputTruthParticlesNoWZ", jetinputtype="TruthWZ"), ] for label in _truthFlavours: diff --git a/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py b/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py index a0f3d4017a9..c2ec26f1a02 100644 --- a/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py +++ b/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py @@ -13,32 +13,29 @@ The JetModifier config class is defined in JetDefinition.py 2. Tool Name (ignored if the helper is a custom one) [3.] Config helper [4.] Prereqs (default to []). Can also be a function. - [5.] Flag passJetDef specifying if the helper needs the jet definition + --> should this be by default? prefer to avoid ignored args """ from .JetDefinition import JetModifier +from AthenaConfiguration.ComponentFactory import CompFactory jetmoddict = {} ######################################################################## # Define the simple modifier setups here -- those defined in JetRec. -from AthenaConfiguration.ComponentFactory import CompFactory -def getJetFilterTool(modspec): - threshold = int(modspec) - jetptfilter = CompFactory.JetFilterTool("jetptfilter_{0}mev".format(threshold)) - jetptfilter.PtMin = threshold - return jetptfilter jetrecmods = { "Sort": JetModifier("JetSorter","jetsort"), - "Filter": JetModifier("JetFilterTool","jetptfilter",createfn=getJetFilterTool), + "Filter": JetModifier("JetFilterTool","jetptfilter_{modspec}", + # we give a function as PtMin : it will be evaluated when instantiating the tool (modspec will come alias usage like "Filter:10000" --> PtMin=100000) + PtMin = lambda _,modspec: int(modspec) ) # } jetmoddict.update (jetrecmods) ######################################################################## # Below, we populate the jetmoddict with modifier definitions for tools # that are defined in other packages. -# The helper functions for tools in PackageName live in modules called +# When necessary, the helper functions 'createfn' for tools in PackageName live in modules called # PackageName.PackageConfig (modules to be moved) # Calibration @@ -46,7 +43,7 @@ from JetCalibTools import JetCalibToolsConfig jetcalibmods = { "Calib": JetModifier("JetCalibrationTool","jetcalib_jetcoll_calibseq", createfn=JetCalibToolsConfig.getJetCalibToolFromString, - prereqs=JetCalibToolsConfig.getJetCalibToolPrereqs,passJetDef=True) + prereqs=JetCalibToolsConfig.getJetCalibToolPrereqs) } jetmoddict.update(jetcalibmods) @@ -67,15 +64,16 @@ jetmomentmods = { # More complex cases here "CaloEnergies": JetModifier("JetCaloEnergies", "jetens", prereqs=["mod:EMScaleMom"] - ), + ), "CaloQuality": JetModifier("JetCaloQualityTool", "caloqual", - createfn=JetMomentToolsConfig.getCaloQualityTool), + TimingCuts = [5,10], + Calculations = ["LArQuality", "N90Constituents", "FracSamplingMax", "NegativeE", "Timing", "HECQuality", "Centroid", "AverageLArQF", "BchCorrCell"],), + "ConstitFourMom": JetModifier("JetConstitFourMomTool", "constitfourmom_basename", - createfn=JetMomentToolsConfig.getConstitFourMomTool, - passJetDef=True), + createfn=JetMomentToolsConfig.getConstitFourMomTool,), "EMScaleMom": JetModifier("JetEMScaleMomTool", "emscalemom_basename", - createfn=JetMomentToolsConfig.getEMScaleMomTool, - passJetDef=True), + createfn=JetMomentToolsConfig.getEMScaleMomTool,), + "JVF": JetModifier("JetVertexFractionTool", "jvf", createfn=JetMomentToolsConfig.getJVFTool, prereqs = ["mod:TrackMoments"] ), @@ -93,6 +91,8 @@ jetmomentmods = { "TrackSumMoments": JetModifier("JetTrackSumMomentsTool", "trksummoms", createfn=JetMomentToolsConfig.getTrackSumMomentsTool, prereqs = [ "input:JetTrackVtxAssoc","ghost:Track" ]), + "Charge" : JetModifier("JetChargeTool", "jetcharge", + prereqs = [ "ghost:Track" ]), } jetmoddict.update(jetmomentmods) @@ -105,7 +105,9 @@ particlejetmods = { # More complex cases here "TruthPartonDR": JetModifier("Analysis::JetConeLabeling","truthpartondr", - createfn=ParticleJetToolsConfig.getJetConeLabeling), + JetTruthMatchTool = lambda *l : CompFactory.Analysis.JetQuarkLabel("jetquarklabel", McEventCollection='TruthEvents') ), + + "JetDeltaRLabel": JetModifier("ParticleJetDeltaRLabelTool","jetdrlabeler_jetptmin", createfn=ParticleJetToolsConfig.getJetDeltaRLabelTool, prereqs=["ghost:BHadronsFinal", @@ -116,17 +118,3 @@ jetmoddict.update(particlejetmods) # Todo: jet substructure moment tools -# This can also be expanded by users if they would rather do this than -# pass in JetModifier instances in the JetDefinition - - -## TEMPORARY HACK (change the names of ghost tracks ) -from JetRecTools.JetRecToolsConfig import trackcollectionmap -trackcollectionmap[""] = { - "Tracks": "InDetTrackParticles", - "JetTracks": "JetSelectedTracks", - "Vertices": "PrimaryVertices", - "TVA": "JetTrackVtxAssoc", - "GhostTracks": "PseudoJetGhostTrack", - "GhostTracksLabel": "GhostTrack", - } diff --git a/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py b/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py index 54f83e59704..af23c0a965e 100644 --- a/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py +++ b/Reconstruction/Jet/JetRecConfig/python/StandardSmallRJets.py @@ -12,13 +12,13 @@ from xAODBase.xAODType import xAODType standardghosts = ["Track","MuonSegment","Truth"] -flavourghosts = ["TruthLabel"+ghosttype for ghosttype in [ - "BHadronsInitial", "BHadronsFinal", "BQuarksFinal", - "CHadronsInitial", "CHadronsFinal", "CQuarksFinal", - "TausFinal", - "WBosons", "ZBosons", "HBosons", "TQuarksFinal", - "Partons",] -] +#flavourghosts = ["TruthLabel"+ghosttype for ghosttype in [ +flavourghosts = [ "BHadronsInitial", "BHadronsFinal", "BQuarksFinal", + "CHadronsInitial", "CHadronsFinal", "CQuarksFinal", + "TausFinal", + "WBosons", "ZBosons", "HBosons", "TQuarksFinal", + "Partons",] + @@ -27,10 +27,16 @@ flavourghosts = ["TruthLabel"+ghosttype for ghosttype in [ # Modifiers for the standard small R jets # ********************************************************* # (use tuples rather than lists to prevent accidental modification) -standardrecomods = ( "Filter:10000","Width","TrackMoments","TrackSumMoments","JVF","JVT","OriginSetPV", - "CaloEnergies", ) -clustermods = ("ECPSFrac","ClusterMoments",)# "LArHVCorr" ) -truthmods = ("PartonTruthLabel","TruthPartonDR","JetDeltaRLabel:5000" ) # not working well yet ? +standardrecomods = ( + "ConstitFourMom", "CaloEnergies", + "Calib:T0:mc", + "Sort","Filter:10000", + "LArHVCorr", "Width", + "CaloQuality", "TrackMoments","TrackSumMoments", + "JVF","JVT","OriginSetPV", "Charge", +) +clustermods = ("ECPSFrac","ClusterMoments",) +truthmods = ("PartonTruthLabel","TruthPartonDR","JetDeltaRLabel:5000" ) pflowmods = () @@ -41,8 +47,8 @@ pflowmods = () AntiKt4EMPFlow = JetDefinition("AntiKt",0.4,cst.EMPFlow, - ghostdefs = standardghosts , # not working well yet : flavourghosts, - modifiers = ("Calib:T0:mc",)+standardrecomods+truthmods, + ghostdefs = standardghosts+flavourghosts , # not working well yet : flavourghosts, + modifiers = standardrecomods+truthmods, standardRecoMode = True, lock = True ) @@ -50,9 +56,8 @@ AntiKt4EMPFlow = JetDefinition("AntiKt",0.4,cst.EMPFlow, - AntiKt4LCTopo = JetDefinition("AntiKt",0.4,cst.LCTopoOrigin, - ghostdefs = standardghosts, # not working well yet : flavourghosts,, + ghostdefs = standardghosts+flavourghosts, modifiers = standardrecomods+truthmods+clustermods, standardRecoMode = True, lock = True, @@ -60,20 +65,42 @@ AntiKt4LCTopo = JetDefinition("AntiKt",0.4,cst.LCTopoOrigin, AntiKt4EMTopo = JetDefinition("AntiKt",0.4,cst.EMTopoOrigin, - ghostdefs = standardghosts, # not working well yet : flavourghosts,, + ghostdefs = standardghosts+flavourghosts, modifiers = standardrecomods+truthmods+clustermods, standardRecoMode = True, lock = True, ) AntiKt4Truth = JetDefinition("AntiKt",0.4, cst.Truth, - modifiers = [], - standardRecoMode = True, - lock = True, + ghostdefs = flavourghosts, + modifiers = ("Sort","Filter:10000", "Width")+truthmods, + standardRecoMode = True, + lock = True, ) AntiKt4TruthWZ = JetDefinition("AntiKt",0.4, cst.TruthWZ, - modifiers = [], + ghostdefs = flavourghosts, + modifiers = ("Sort","Filter:10000", "Width")+truthmods, standardRecoMode = True, lock = True, ) + + + + + +def StandardSmallRJetCfg(configFlags): + from JetRecConfig.JetRecConfig import JetRecCfg + + standarSmallRList = [ + AntiKt4EMPFlow, + AntiKt4LCTopo, + AntiKt4Truth, + ] + + compacc = JetRecCfg( standarSmallRList[0], configFlags) + for jetdef in standarSmallRList[1:]: + compacc.merge( JetRecCfg(jetdef, configFlags) ) + + return compacc + diff --git a/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py b/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py index 4ce98c12c40..518ea15ad8d 100755 --- a/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py +++ b/Reconstruction/Jet/JetRecConfig/share/JetRecTestCfg.py @@ -7,44 +7,21 @@ from pprint import pprint, pformat from AthenaCommon import Logging jetlog = Logging.logging.getLogger("testJetRecDeps") -def JetRecTestCfg(jetdefs,configFlags,args): - - if args.printDependencies: - for jetdef in jetdefs: - deps = JetRecConfig.resolveDependencies(jetdef) - jetlog.info("Dumping dependency dict for {0}".format(jetdef)) - depstr = pformat(deps) - jetlog.info(depstr) - - if args.printAccumulators: - jetlog.info("Printing component accumulators for each jet collection") - jetcas = [] - for jetdef in jetdefs: - jetcomps = JetRecConfig.JetRecCfg(jetdef,configFlags) - if args.printAccumulators: - jetcomps.printConfig(withDetails=args.verboseAccumulators,summariseProps=True) - jetcas.append(jetcomps) - - jetlog.info("Printing component accumulator for entire sequence") - components = ComponentAccumulator() - for ca in jetcas: - components.merge(ca) - components.printConfig(withDetails=args.verboseAccumulators,summariseProps=True) - - return components - def DefineJetCollections(configFlags): - from JetRecConfig.StandardSmallRJets import standardrecomods, clustermods, truthmods, standardghosts, AntiKt4EMPFlow, AntiKt4Truth, AntiKt4TruthWZ - ######################################################################## + # import the standard definitions + from JetRecConfig.StandardSmallRJets import AntiKt4EMPFlow, AntiKt4EMTopo, AntiKt4Truth, AntiKt4TruthWZ + # Example for defining a custom definition from JetRecConfig.JetDefinition import JetConstitSeq, JetDefinition, xAODType + from JetRecConfig.StandardSmallRJets import standardrecomods, clustermods, truthmods, standardghosts EMTopoCSSK = JetConstitSeq("EMTopoOriginCSSK", xAODType.CaloCluster, ["EM","Origin","CS","SK"], "CaloCalTopoClusters", "EMOriginTopoCSSK", label="EMTopoOriginCSSK") - AntiKt4EMTopoCSSK = JetDefinition("AntiKt",0.4,EMTopoCSSK,ptmin=2e3,ptminfilter=2e3,prefix="New") - AntiKt4EMTopoCSSK.modifiers = ["ConstitFourMom"] - AntiKt4EMTopoCSSK.modifiers += standardrecomods + clustermods + truthmods - AntiKt4EMTopoCSSK.ghostdefs = standardghosts + AntiKt4EMTopoCSSK = JetDefinition("AntiKt",0.4,EMTopoCSSK,ptmin=2e3,prefix="New") + recomods = tuple( mod for mod in standardrecomods if not mod.startswith("Calib") ) # remove calib modifier : no calib exists for EMTopoCSSK + AntiKt4EMTopoCSSK.modifiers = ["Filter:2000","ConstitFourMom"] + AntiKt4EMTopoCSSK.modifiers += recomods + clustermods + truthmods + AntiKt4EMTopoCSSK.ghostdefs = standardghosts AntiKt4EMTopoCSSK.extrainputs = ["EventDensity"] ######################################################################## @@ -52,16 +29,19 @@ def DefineJetCollections(configFlags): from JetRecConfig.StandardJetConstits import jetconstitdic AntiKt4EMPFlowCSSK = AntiKt4EMPFlow.clone(prefix="New") AntiKt4EMPFlowCSSK.inputdef = jetconstitdic["EMPFlowCSSK"] - AntiKt4EMPFlowCSSK.modifiers = ["ConstitFourMom"] + AntiKt4EMPFlowCSSK.modifiers = ["Filter:2000","ConstitFourMom"] AntiKt4EMPFlowCSSK.extrainputs = ["EventDensity"] jetdefs = [ + # we re-clone the standard with a prefix to avoid conflicts with pre-existing in-file collections + AntiKt4EMTopo.clone(prefix="New"), + AntiKt4EMPFlow.clone(prefix="New"), AntiKt4EMTopoCSSK, AntiKt4EMPFlowCSSK, ] if configFlags.Input.isMC: - jetdefs += [AntiKt4Truth, - AntiKt4TruthWZ] + jetdefs += [AntiKt4Truth.clone(prefix="New"), + AntiKt4TruthWZ.clone(prefix="New"),] return jetdefs @@ -136,7 +116,12 @@ if __name__=="__main__": jetdefs = DefineJetCollections(ConfigFlags) # Add the components from our jet reconstruction job - cfg.merge(JetRecTestCfg(jetdefs,ConfigFlags,args)) + from JetRecConfig.JetRecConfig import JetRecCfg + for jetdef in jetdefs: + comp = JetRecCfg(jetdef,ConfigFlags) + comp.printConfig(withDetails=args.verboseAccumulators,summariseProps=True) + + cfg.merge(comp) # Write what we produced to AOD # First define the output list diff --git a/Reconstruction/Jet/JetRecTools/python/JetRecToolsConfig.py b/Reconstruction/Jet/JetRecTools/python/JetRecToolsConfig.py index 85753fe040b..73d36b3410a 100644 --- a/Reconstruction/Jet/JetRecTools/python/JetRecToolsConfig.py +++ b/Reconstruction/Jet/JetRecTools/python/JetRecToolsConfig.py @@ -29,13 +29,13 @@ trackcollectionmap = { } } -def getTrackSelTool(trkopt="",doWriteTracks=False): +def getTrackSelTool(trkopt="",doWriteTracks=False, cutLevel="Loose", minPt=500): # Track selector needs its own hierarchical config getter in JetRecTools? idtrackselloose = CompFactory.getComp("InDet::InDetTrackSelectionTool")( "idtrackselloose", - CutLevel = "Loose", - minPt = 500, + CutLevel = cutLevel, + minPt = minPt, UseTrkTrackTools = False, Extrapolator = "", TrackSummaryTool = "" diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py index d02b8838e59..1e775defaf4 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py @@ -8,8 +8,9 @@ # jet reco code. from JetRecConfig.JetDefinition import JetConstitSeq,JetConstitSource, xAODType, JetDefinition -from . import TriggerJetMods # this is to define the ConstitFourMom_copy JetModifierC -TriggerJetMods.ConstitFourMom_copy +# this is to define trigger specific JetModifiers (ex: ConstitFourMom_copy) : +from .TriggerJetMods import jetmoddict # noqa: F401 + from AthenaCommon.Logging import logging log = logging.getLogger("TriggerMenuMT.HLTMenuConfig.Jet.JetRecoConfiguration") @@ -180,7 +181,6 @@ def defineGroomedJets(jetRecoDict,ungroomedDef):#,ungroomedJetsName): ########################################################################################## # Generation of modifier lists. So far only calib, but can add track, substructure mods -from JetRecConfig.StandardJetMods import jetmoddict # Make generating the list a bit more comprehensible def getModSpec(modname,modspec=''): diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py index 89531ab3a85..24f760f7a0f 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py @@ -3,20 +3,18 @@ from JetRecConfig.JetDefinition import JetModifier ######################################################################## # Special modifier setups used by jet trigger, but not in offline +# We just extend the jetmoddict from the standard config. -# No need for the special momentum scales, just copy the basic four-vec -# to "DetectorEtaPhi", because we're not doing origin correction -# and certainly not with the offline collection names -from AthenaConfiguration.ComponentFactory import CompFactory -def getConstitFourMomTool_copy(): - cfourmom = CompFactory.JetConstitFourMomTool("constitfourmom_copy", - JetScaleNames = ["DetectorEtaPhi"], - AltConstitColls = [""], - AltConstitScales = [0], - AltJetScales = ["JetConstitScaleMomentum"]) - return cfourmom - -ConstitFourMom_copy = JetModifier("JetConstitFourMomTool", "constitfourmom_copy", - createfn=getConstitFourMomTool_copy) from JetRecConfig.StandardJetMods import jetmoddict -jetmoddict['ConstitFourMom_copy'] = ConstitFourMom_copy +jetmoddict.update( + + # No need for the special momentum scales, just copy the basic four-vec + # to "DetectorEtaPhi", because we're not doing origin correction + # and certainly not with the offline collection names + ConstitFourMom_copy = JetModifier("JetConstitFourMomTool", "constitfourmom_copy", + JetScaleNames = ["DetectorEtaPhi"], + AltConstitColls = [""], + AltConstitScales = [0], + AltJetScales = ["JetConstitScaleMomentum"] + ) +) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py index e84e9cf305a..11a1e9117e5 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py @@ -64,14 +64,14 @@ def generateChains( flags, chainDict ): jetinputdefdic.setdefault(clustersname , JetInputDef(clustersname, xAODType.CaloCluster) ) #hardcoded jet collection for now clustermods = ["ECPSFrac","ClusterMoments"] - trigMinPt = 7e3 + trigMinPt = 7000 HLT_EMTopo = JetConstitSeq( "HLT_EMTopo",xAODType.CaloCluster, ["EM"], clustersname, clustersname,label="EMTopo") - HLT_AntiKt4EMTopo_subjesIS = JetDefinition( "AntiKt", 0.4, HLT_EMTopo, ptmin=trigMinPt,ptminfilter=trigMinPt, + HLT_AntiKt4EMTopo_subjesIS = JetDefinition( "AntiKt", 0.4, HLT_EMTopo, ptmin=trigMinPt, prefix="HLT_", suffix = "_subjesIS", ) - HLT_AntiKt4EMTopo_subjesIS.modifiers = ["Calib:TrigRun2:data:JetArea_EtaJES_GSC_Insitu:HLT_Kt4EMTopoEventShape","Sort"] + clustermods + HLT_AntiKt4EMTopo_subjesIS.modifiers = ["Calib:TrigRun2:data:JetArea_EtaJES_GSC_Insitu:HLT_Kt4EMTopoEventShape","Sort", "Filter:"+str(trigMinPt)] + clustermods # May need a switch to disable automatic modifier prerequisite generation jetRecoComps = JetRecConfig.JetRecCfg(HLT_AntiKt4EMTopo_subjesIS, flags) @@ -93,7 +93,7 @@ def generateChains( flags, chainDict ): CA = acc) jetStep = ChainStep(name=stepName, Sequences=[jetSequence], chainDicts=[chainDict]) - + l1Thresholds=[] for part in chainDict['chainParts']: l1Thresholds.append(part['L1threshold']) -- GitLab