From 6ca50515e710538c3281f405568d3214b336d0be Mon Sep 17 00:00:00 2001 From: Teng Jian Khoo <teng.jian.khoo@cern.ch> Date: Wed, 3 Jul 2019 13:54:55 +0000 Subject: [PATCH] Add trimmed jet triggers --- .../python/JetCalibToolsConfig.py | 1 + .../Jet/JetRecConfig/python/JetDefinition.py | 36 +++-- .../Jet/JetRecConfig/python/JetGroomConfig.py | 121 ++++++++++++++++ .../Jet/JetRecConfig/python/JetGrooming.py | 133 ++++++++++++++++++ .../Jet/JetRecConfig/python/JetRecConfig.py | 48 ++++++- .../JetRecConfig/python/StandardJetMods.py | 4 +- .../python/chainDict2jetLabel.py | 4 +- .../TrigUpgradeTest/share/full_menu_build.ref | 4 + .../TrigUpgradeTest/share/slice_jet.ref | 4 + .../HLTMenuConfig/Jet/JetRecoConfiguration.py | 96 +++++++++++++ .../HLTMenuConfig/Jet/JetRecoSequences.py | 101 +++++-------- .../HLTMenuConfig/Jet/TriggerJetMods.py | 19 +++ .../python/HLTMenuConfig/Jet/generateJet.py | 2 +- .../python/HLTMenuConfig/Menu/LS2_v1.py | 12 +- .../HLTMenuConfig/Menu/SignatureDicts.py | 4 +- 15 files changed, 492 insertions(+), 97 deletions(-) create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetGrooming.py create mode 100644 Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py create mode 100644 Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py diff --git a/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py b/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py index d0756da2af0..7330ed9761b 100644 --- a/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py +++ b/Reconstruction/Jet/JetCalibTools/python/JetCalibToolsConfig.py @@ -47,6 +47,7 @@ fatjetcontexts = { "CaloMass": ("JES_MC16recommendation_FatJet_JMS_calo_29Nov2017.config","00-04-81","EtaJES_JMS"), "TAMass": ("JES_MC16recommendation_FatJet_JMS_TA_29Nov2017.config","00-04-81","EtaJES_JMS"), "TrigUngroomed": ("JES_Full2012dataset_Rscan_June2014.config","00-04-77","JetArea_EtaJES"), + "TrigTrimmed": ("JES_MC15recommendation_FatJet_June2015.config","00-04-77","EtaJES_JMS"), } # List AFII config files separately, to avoid needing to specify a different context diff --git a/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py b/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py index 9f60833da7d..d867c74e834 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetDefinition.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration ######################################################################## # # @@ -47,7 +47,11 @@ def buildJetAlgName(finder, mainParam, variableRMassScale=None, variableRMinRadi # Normally defaults to standard offline input containers, but # can be overridden. class JetConstit(object): - def __init__(self, objtype, modifiers=[], rawname=None, inputname=None): + def __init__(self, + objtype, # The type of xAOD object from which to build the jets + modifiers=[], # Modifications to be applied to constituents prior to jet finding + rawname=None, # Override the default input collection + inputname=None): # Override the default output collection (not to be used with modifiers) self.__basetype = objtype self.__modifiers = modifiers # Override for unmodified container name @@ -193,12 +197,18 @@ class JetGhost(object): # Need to override __repr__ for printing in lists etc __repr__ = __str__ +from AthenaCommon.SystemOfUnits import MeV class JetDefinition(object): - def __init__(self, algorithm, radius, inputdef, - ptmin=5000., ptminfilter=5000., - ghostdefs=[], modifiers=[], - extrainputs=[]): + def __init__(self, + algorithm, # The fastjet clustering algorithm + 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 + extrainputs=[]): # The list of additional input types needed for jet finding # Should add some type checking here # Could use JetContainerInfo conversion @@ -209,7 +219,7 @@ class JetDefinition(object): self.__radius = radius self.__inputdef = inputdef - self.defineName() + 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 @@ -220,9 +230,6 @@ class JetDefinition(object): self.modifiers = modifiers # Tools to modify the jet self.extrainputs = extrainputs # Any extra input dependencies - # Should this be a derived class? - self.grooming = None - # These should probably go in a derived class self.VRMinRadius = None self.VRMassScale = None @@ -247,7 +254,7 @@ class JetDefinition(object): @algorithm.setter def algorithm(self,algorithm): self.__algorithm = algorithm - self.defineName() + self.__defineName() @property def radius(self): @@ -255,7 +262,7 @@ class JetDefinition(object): @radius.setter def radius(self,radius): self.__radius = radius - self.defineName() + self.__defineName() @property def inputdef(self): @@ -263,9 +270,9 @@ class JetDefinition(object): @inputdef.setter def inputdef(self,inputdef): self.__inputdef = inputdef - self.defineName() + self.__defineName() - def defineName(self): + def __defineName(self): self.basename = buildJetAlgName(self.__algorithm,self.__radius)+self.__inputdef.label if self.inputdef.basetype == xAODType.CaloCluster: # Omit cluster origin correction from jet name @@ -280,6 +287,7 @@ class JetDefinition(object): # Need to override __repr__ for printing in lists etc __repr__ = __str__ + ######################################################################## # Helper to instantiate a generic jet modifier # Tools that typically have more complex properties set should have diff --git a/Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py new file mode 100644 index 00000000000..7e790b62991 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetGroomConfig.py @@ -0,0 +1,121 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +######################################################################## +# # +# JetGroomConfig: A helper module for configuring jet grooming # +# Author: TJ Khoo # +# # +######################################################################## + +from AthenaCommon import Logging +jetlog = Logging.logging.getLogger('JetGroomConfig') + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + +# CfgMgr is more convenient but it helps to be explicit about where +# things are defined. +# So, import package conf modules rather than a dozen individual classes +from JetRec import JetRecConf + +######################################################################## +# Get a jet groomer class given a tool name and the grooming definition object +# +def getJetGroomer(groomdef): + tooltype = groomdef.groomspec["ToolType"] + toolprops = {key:val for key,val in groomdef.groomspec.iteritems() if key not in ["groomalg","ToolType"]} + return tooltype(groomdef.basename,**toolprops) + + +######################################################################## +# Function for configuring the jet algorithm and groomers, given the +# set of dependencies +# +def getJetGroomAlg(jetname,groomdef,modlist): + jetlog.debug("Configuring JetAlgorithm \"jetalg_{0}\"".format(jetname)) + + import JetRecConfig + builder = JetRecConfig.getJetBuilder() + + groomer = getJetGroomer(groomdef) + groomer.JetBuilder = builder + + import JetModConfig + mods = [] + # Dependency resolution should be done externally + for moddef,modspec in modlist: + mod = JetModConfig.getModifier(groomdef,moddef,modspec) + mods.append(mod) + + rectool = JetRecConf.JetRecTool(jetname, + JetGroomer=groomer, + InputContainer=groomdef.ungroomedname, + OutputContainer=jetname, + JetPseudojetRetriever=JetRecConf.JetPseudojetRetriever("jpjretriever"), + JetModifiers=mods) + + jetalg = JetRecConf.JetAlgorithm("jetalg_"+jetname) + jetalg.Tools = [rectool] + + return jetalg + +######################################################################## +# Top-level function for running jet grooming +# Will first run the jet finder, unless the input jets are +# found in the input file +def JetGroomCfg(groomdef, configFlags, jetnameprefix="",jetnamesuffix=""): + jetsfullname = jetnameprefix+groomdef.basename+jetnamesuffix+"Jets" + jetlog.info("Setting up to find {0}".format(jetsfullname)) + + sequencename = jetsfullname + + components = ComponentAccumulator() + from AthenaCommon.AlgSequence import AthSequencer + components.addSequence( AthSequencer(sequencename) ) + + # Check if the ungroomed jets exist in the input file. + # If not, we need to configure their reconstruction. + filecontents = configFlags.Input.Collections + if not groomdef.ungroomedname in filecontents: + from JetRecConfig import JetRecCfg + components.merge(JetRecCfg(groomdef.ungroomeddef, configFlags, + jetnameoverride=groomdef.ungroomedname)) + else: + # FIXME: Need to schedule rebuilding of pseudojets + pass + + # FIXME: Add calls to JetModConfig.getFinalModifierListAndPrereqs + components.addEventAlgo(getJetGroomAlg(jetsfullname,groomdef,groomdef.modifiers)) + + return components + +if __name__=="__main__": + + # Setting needed for the ComponentAccumulator to do its thing + from AthenaCommon.Configurable import Configurable + Configurable.configurableRun3Behavior=True + + # Config flags steer the job at various levels + from AthenaConfiguration.AllConfigFlags import ConfigFlags + ConfigFlags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/ASG/mc16_13TeV.410501.PowhegPythia8EvtGen_A14_ttbar_hdamp258p75_nonallhad.merge.AOD.e5458_s3126_r9364_r9315/AOD.11182705._000001.pool.root.1"] + ConfigFlags.Concurrency.NumThreads = 1 + ConfigFlags.Concurrency.NumConcurrentEvents = 1 + ConfigFlags.lock() + + # Get a ComponentAccumulator setting up the fundamental Athena job + from AthenaConfiguration.MainServicesConfig import MainServicesThreadedCfg + cfg=MainServicesThreadedCfg(ConfigFlags) + + # Add the components for reading in pool files + from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + cfg.merge(PoolReadCfg(ConfigFlags)) + + # Add the components from our jet reconstruction job + from StandardJetDefs import AntiKt10LCTopo + from JetGrooming import JetTrimming + AntiKt10LCTopo.ptminfilter = 100e3 + AntiKt10LCTopoTrimmedPtFrac5SmallR20 = JetTrimming(AntiKt10LCTopo,"AntiKt10LCTopoJets",smallR=0.2,ptfrac=0.05) + cfg.merge(JetGroomCfg(AntiKt10LCTopoTrimmedPtFrac5SmallR20,ConfigFlags)) + + cfg.printConfig(withDetails=False,summariseProps=True) + + cfg.run(maxEvents=10) diff --git a/Reconstruction/Jet/JetRecConfig/python/JetGrooming.py b/Reconstruction/Jet/JetRecConfig/python/JetGrooming.py new file mode 100644 index 00000000000..53c9d6d866b --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetGrooming.py @@ -0,0 +1,133 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +######################################################################## +# # +# JetGrooming: A module for classes encoding definitions of objects # +# for configuring jet grooming # +# Author: TJ Khoo # +# # +######################################################################## + +__all__ = ["GroomingDefinition","JetTrimming"] + +from AthenaCommon import Logging +jetlog = Logging.logging.getLogger('JetGrooming') + +class GroomingDefinition(object): + def __init__(self, + ungroomeddef, # Ungroomed JetDefinition + ungroomedname, # Input collection name (cannot be determined uniquely from inputdef) + groomspec, # Dict describing the grooming settings + modifiers=[]): # JetModifiers to run after grooming + + self.ungroomedname = ungroomedname + + # Dedicated setter/getter + self.__ungroomeddef = ungroomeddef + self.__groomspec = groomspec + + self.__checkGroomSpec(groomspec) + self.__groomspec = groomspec + + self.__defineName() + + self.modifiers = modifiers # Tools to modify the jet + + pass + + def __hash__(self): + return hash("") + + def __eq__(self,rhs): + return self.__hash__() == rhs.__hash__() + + def __ne__(self,rhs): + return (not __eq__(self,rhs)) + + # Define core attributes as properties, with + # custom setter/getter such that if changed, these + # force resetting of the jet name + @property + def ungroomeddef(self): + return self.__ungroomeddef + @ungroomeddef.setter + def ungroomeddef(self,ungroomeddef): + self.__ungroomeddef = ungroomeddef + self.defineName() + + def __checkGroomSpec(self,groomspec): + # Check if options are supported (implemented) + groomalg = groomspec["groomalg"] + supportedGrooming = ["Trim"] + if not groomspec["groomalg"] in supportedGrooming: + jetlog.error("Unsupported grooming algorithm specification \"{}\"! Allowable options:") + for groomalg in supportedGrooming: + jetlog.error(groomalg) + raise KeyError("Invalid grooming algorithm choice: {0}".format(groomtype)) + + @property + def groomspec(self): + return self.__groomspec + @groomspec.setter + def groomspec(self,groomspec): + self.__groomspec = groomspec + self.defineName() + + @property + def inputdef(self): + return self.__inputdef + @inputdef.setter + def inputdef(self,inputdef): + self.__inputdef = inputdef + self.defineName() + + # To override in derived classes + def groomSpecAsStr(self): + return "Groomed" + + def __defineName(self): + ungroomedNameBase = self.ungroomeddef.basename + # chop the label off so we can insert the trimming spec + groomedName = ungroomedNameBase + self.groomSpecAsStr() + self.basename = groomedName + pass + + # Define a string conversion for printing + def __str__(self): + return "JetGrooming({0})".format(self.basename) + # Need to override __repr__ for printing in lists etc + __repr__ = __str__ + + +class JetTrimming(GroomingDefinition): + def __init__(self, + ungroomeddef, # Ungroomed JetDefinition + ungroomedname, # Input collection name (cannot be determined uniquely from inputdef) + smallR, # Subjet radius + ptfrac, # Minimum subjet pt fraction + modifiers=[]): # JetModifiers to run after grooming + + # Apart from groomalg and ToolType, these correspond to the + # grooming tool property values + from JetRec.JetRecConf import JetTrimmer + groomspec = { + # Type of groomer + "groomalg": "Trim", + # Configurable class + "ToolType": JetTrimmer, + # Tool properties to set + "RClus": smallR, + "PtFrac": ptfrac, + } + + super(JetTrimming,self).__init__(ungroomeddef,ungroomedname,groomspec,modifiers) + + def groomSpecAsStr(self): + ptfrac = self.groomspec["PtFrac"] + ptfracstr = int(ptfrac*100) # Not usually smaller than % + smallR = self.groomspec["RClus"] + from JetDefinition import formatRvalue + smallRstr = formatRvalue(smallR*10) + + groomstr = "TrimmedPtFrac{}SmallR{}".format(ptfracstr,smallRstr) + return groomstr diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py index 50b09e6a6df..b1cb1db19e5 100644 --- a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py @@ -40,8 +40,15 @@ __all__ = ["xAOD", "JetRecCfg", "resolveDependencies"] # Receives the jet definition and input flags, mainly for input file # peeking such that we don't attempt to reproduce stuff that's already # in the input file -def JetRecCfg(jetdef, configFlags, jetnameprefix="",jetnamesuffix=""): - jetsfullname = jetnameprefix+jetdef.basename+jetnamesuffix+"Jets" +def JetRecCfg(jetdef, configFlags, jetnameprefix="",jetnamesuffix="", jetnameoverride=None): + # Ordinarily we want to have jet collection names be descriptive and derived from + # the configured reconstruction. + # Nevertheless, we allow an explicit specification when necessary + # e.g. to ensure that the correct name is used in grooming operations + if jetnameoverride: + jetsfullname = jetnameoverride + else: + jetsfullname = jetnameprefix+jetdef.basename+jetnamesuffix+"Jets" jetlog.info("Setting up to find {0}".format(jetsfullname)) sequencename = jetsfullname @@ -233,11 +240,6 @@ def JetInputCfg(inputdeps, configFlags, sequenceName): components = ComponentAccumulator(sequenceName) jetlog.info("Inspecting input file contents") - # Get the list of SG keys for the first input file - # I consider it silly to run on a set of mixed file types - firstinput = configFlags.Input.Files[0] - import os, pickle - # PeekFiles returns a dict for each input file filecontents = configFlags.Input.Collections constit = inputdeps[0] @@ -466,3 +468,35 @@ def getJetRecTool(jetname, finder, pjs, mods): JetModifiers = mods ) return jetrec + + +if __name__=="__main__": + + # Setting needed for the ComponentAccumulator to do its thing + from AthenaCommon.Configurable import Configurable + Configurable.configurableRun3Behavior=True + + # Config flags steer the job at various levels + from AthenaConfiguration.AllConfigFlags import ConfigFlags + ConfigFlags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/ASG/mc16_13TeV.410501.PowhegPythia8EvtGen_A14_ttbar_hdamp258p75_nonallhad.merge.AOD.e5458_s3126_r9364_r9315/AOD.11182705._000001.pool.root.1"] + ConfigFlags.Concurrency.NumThreads = 1 + ConfigFlags.Concurrency.NumConcurrentEvents = 1 + ConfigFlags.lock() + + # Get a ComponentAccumulator setting up the fundamental Athena job + from AthenaConfiguration.MainServicesConfig import MainServicesThreadedCfg + cfg=MainServicesThreadedCfg(ConfigFlags) + + # Add the components for reading in pool files + from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + cfg.merge(PoolReadCfg(ConfigFlags)) + + # Add the components from our jet reconstruction job + from StandardJetDefs import AntiKt4EMTopo + AntiKt4EMTopo.ptminfilter = 15e3 + AntiKt4EMTopo.modifiers = ["Calib:T0:mc","Sort"] + ["JVT"] + ["PartonTruthLabel"] + cfg.merge(JetRecCfg(AntiKt4EMTopo,ConfigFlags,jetnameprefix="New")) + + cfg.printConfig(withDetails=False,summariseProps=True) + + cfg.run(maxEvents=10) diff --git a/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py b/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py index f285cdf171c..8ece35d4205 100644 --- a/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py +++ b/Reconstruction/Jet/JetRecConfig/python/StandardJetMods.py @@ -62,12 +62,12 @@ jetmomentmods = { # More complex cases here "CaloQuality": JetModifier("JetCaloQualityTool", "caloqual", helperfn=JetMomentToolsConfig.getCaloQualityTool), - "ConstitFourMom": JetModifier("JetConstitFourMomTool", "jetconstitfourmom_basename", + "ConstitFourMom": JetModifier("JetConstitFourMomTool", "constitfourmom_basename", helperfn=JetMomentToolsConfig.getConstitFourMomTool, passJetDef=True), "JVF": JetModifier("JetVertexFractionTool", "jvf", helperfn=JetMomentToolsConfig.getJVFTool, - prereqs = ["mod:TrackSumMoments"] ), + prereqs = ["mod:TrackMoments"] ), "JVT": JetModifier("JetVertexTaggerTool", "jvt", prereqs = [ "mod:JVF" ]), "OriginSetPV": JetModifier("JetOriginCorrectionTool", "origin_setpv", diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py index 8aea10bbaae..edfbb29d848 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py @@ -54,8 +54,8 @@ def make_simple_label(chain_dict): # smcstr,) condition_str = '(%set,%s' % (str(cp['threshold']), str(cp['etaRange']),) - if smcstr: - condition_str += ',%s)' + if smcstr: # Run 2 chains have "INF" in the SMC substring + condition_str += ',%s)' % smcstr.replace('INF','') else: condition_str += ')' label += condition_str diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref index e381eef91a9..b41eab9723e 100644 --- a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref @@ -280,6 +280,8 @@ TriggerSummaryStep3 19 0 DEBUG +++ HLT_e5_etcut_L1EM3 TriggerSummaryStep3 19 0 DEBUG +++ HLT_g5_etcut_L1EM3 ID#471243435 TriggerSummaryStep3 19 0 DEBUG +++ HLT_e3_etcut_L1EM3 ID#683953566 TriggerSummaryStep3 19 0 DEBUG +++ HLT_e7_etcut_L1EM3 ID#1959043579 +TrigSignatureMoniMT INFO HLT_2j330_a10t_lcw_jes_30smcINF_L1J2020 20 0 0 0 0 0 0 +TrigSignatureMoniMT INFO HLT_2j330_a10t_lcw_jes_30smcINF_L1J20 decisions 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_2mu4_bBmumu_L12MU4 20 20 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_2mu4_bBmumu_L12MU4 decisions 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_2mu4_bDimu_L12MU4 20 20 0 0 0 0 0 0 @@ -316,6 +318,8 @@ TrigSignatureMoniMT INFO HLT_j260_320eta490_L1J20 TrigSignatureMoniMT INFO HLT_j260_320eta490_L1J20 decisions 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_j420_L1J20 20 20 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_j420_L1J20 decisions 0 0 0 0 0 +TrigSignatureMoniMT INFO HLT_j420_a10t_lcw_jes_30smcINF_L1J2020 20 0 0 0 0 0 0 +TrigSignatureMoniMT INFO HLT_j420_a10t_lcw_jes_30smcINF_L1J20 decisions 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_j45_L1J20 20 20 5 0 0 0 0 5 TrigSignatureMoniMT INFO HLT_j45_L1J20 decisions 5 0 0 0 0 TrigSignatureMoniMT INFO HLT_j460_a10_lcw_subjes_L1J20 20 20 0 0 0 0 0 0 diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/slice_jet.ref b/Trigger/TrigValidation/TrigUpgradeTest/share/slice_jet.ref index d8f9d385408..7a3a98271c0 100644 --- a/Trigger/TrigValidation/TrigUpgradeTest/share/slice_jet.ref +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/slice_jet.ref @@ -1,3 +1,5 @@ +TrigSignatureMoniMT INFO HLT_2j330_a10t_lcw_jes_30smcINF_L1J2020 20 0 0 +TrigSignatureMoniMT INFO HLT_2j330_a10t_lcw_jes_30smcINF_L1J20 decisions 0 TrigSignatureMoniMT INFO HLT_3j200_L1J20 20 20 0 0 TrigSignatureMoniMT INFO HLT_3j200_L1J20 decisions 0 TrigSignatureMoniMT INFO HLT_5j70_0eta240_L1J20 20 20 0 0 @@ -8,6 +10,8 @@ TrigSignatureMoniMT INFO HLT_j260_320eta490_L1J20 TrigSignatureMoniMT INFO HLT_j260_320eta490_L1J20 decisions 0 TrigSignatureMoniMT INFO HLT_j420_L1J20 20 20 0 0 TrigSignatureMoniMT INFO HLT_j420_L1J20 decisions 0 +TrigSignatureMoniMT INFO HLT_j420_a10t_lcw_jes_30smcINF_L1J2020 20 0 0 +TrigSignatureMoniMT INFO HLT_j420_a10t_lcw_jes_30smcINF_L1J20 decisions 0 TrigSignatureMoniMT INFO HLT_j45_L1J20 20 20 5 5 TrigSignatureMoniMT INFO HLT_j45_L1J20 decisions 5 TrigSignatureMoniMT INFO HLT_j460_a10_lcw_subjes_L1J20 20 20 0 0 diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py new file mode 100644 index 00000000000..c4858141eaa --- /dev/null +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoConfiguration.py @@ -0,0 +1,96 @@ +# +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# + +########################################################################################## +# Helper functions to digest the reconstruction options dictionary +# and translate it into the python configuration objects used by +# jet reco code. + +from JetRecConfig.JetDefinition import JetConstit, xAODType, JetDefinition + +# Define the jet constituents to be interpreted by JetRecConfig +# When actually specifying the reco, clustersKey should be +# set, but default to None to allow certain checks, in particular +# grooming configuration +def defineJetConstit(jetRecoDict,clustersKey=None): + # Get the details of the constituent definition: + # type, mods and the input container name + if "tc" in jetRecoDict["dataType"]: + # apply this scale + if jetRecoDict["calib"] == "em": + constitMods = ["EM"] + elif jetRecoDict["calib"] == "lcw": + constitMods = ["LC"] + # read from this cluster collection, + # overriding the standard offline collection + jetConstit = JetConstit( xAODType.CaloCluster, constitMods ) + if clustersKey is not None: + jetConstit.rawname = clustersKey + # apply constituent pileup suppression + if "sk" in jetRecoDict["dataType"]: + constitMods.append("SK") + elif clustersKey is not None: + jetConstit.inputname = clustersKey + return jetConstit + +# Arbitrary min pt for fastjet, set to be low enough for MHT(?) +# Could/should adjust higher for large-R +def defineJets(jetRecoDict,clustersKey=None): + radius = float(jetRecoDict["recoAlg"].lstrip("a").rstrip("tr"))/10 + jetConstit = defineJetConstit(jetRecoDict,clustersKey) + jetDef = JetDefinition( "AntiKt", radius, jetConstit, ptmin=5000.) + return jetDef + +def defineReclusteredJets(jetRecoDict): + rcJetConstit = JetConstit( xAODType.Jet, []) + rcJetDef = JetDefinition( "AntiKt", 1.0, rcJetConstit) + return rcJetDef + +def defineGroomedJets(jetRecoDict,ungroomedDef,ungroomedJetsName): + from JetRecConfig.JetGrooming import JetTrimming + # Only actually one type now, but leave open possibility of others + groomDef = { + "t":JetTrimming(ungroomedDef,ungroomedJetsName,smallR=0.2,ptfrac=0.05) + }[jetRecoDict["recoAlg"][-1]] + return groomDef + +########################################################################################## +# 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=''): + return (jetmoddict[modname],str(modspec)) + +# Translate calib specification into something understood by +# the calibration config helper +def defineCalibFilterMods(jetRecoDict,dataSource): + # Minimum modifier set for calibration w/o track GSC + # Should eventually build in more mods, depend on track info etc + jetalg = jetRecoDict["recoAlg"] + if jetRecoDict["jetCalib"] == "nojcalib" or jetalg=="a10r": + calibMods = [] + else: + calibContext,calibSeq = { + ("a4","subjes"): ("TrigRun2","JetArea_EtaJES_GSC"), # Calo GSC only + ("a4","subjesIS"): ("TrigRun2","JetArea_EtaJES_GSC_Insitu"), # Calo GSC only + ("a10","subjes"): ("TrigUngroomed","JetArea_EtaJES"), + ("a10t","jes"): ("TrigTrimmed","EtaJES_JMS"), + }[(jetRecoDict["recoAlg"],jetRecoDict["jetCalib"])] + + calibSpec = calibContext+":"+dataSource+":"+calibSeq + from TriggerJetMods import ConstitFourMom_copy + if jetalg=="a4": + calibMods = [(ConstitFourMom_copy,""), + getModSpec("CaloEnergies"), # Needed for GSC + getModSpec("Calib",calibSpec), + getModSpec("Sort")] + else: + calibMods = [(ConstitFourMom_copy,""), + getModSpec("Calib",calibSpec), + getModSpec("Sort")] + + filtercut = {"a4":5000, "a10":50000, "a10r": 50000, "a10t":100000}[jetalg] + return calibMods + [getModSpec("Filter",filtercut)] diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py index b1a42b68239..9c95ebac720 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/JetRecoSequences.py @@ -2,10 +2,11 @@ # Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration # - from AthenaCommon.CFElements import parOR, seqAND from TriggerMenuMT.HLTMenuConfig.Menu.ChainConfigurationBase import RecoFragmentsPool +import JetRecoConfiguration + # Translate the reco dict to a string for suffixing etc def jetRecoDictToString(jetRecoDict): strtemp = "{recoAlg}_{dataType}_{calib}_{jetCalib}" @@ -38,27 +39,24 @@ def jetRecoSequence( dummyFlags, dataSource, RoIs = 'FSJETRoI', **jetRecoDict): recoAlg = jetRecoDict["recoAlg"] doGrooming = recoAlg.endswith("t") # Maybe other grooming strategies doRecluster = recoAlg.endswith("r") - radius = float(recoAlg.lstrip("a").rstrip("tr"))/10 jetNamePrefix = "Trig" - from JetRecConfig.JetDefinition import JetConstit, xAODType, JetDefinition from JetRecConfig.JetRecConfig import getConstitPJGAlg, getJetAlgorithm if doRecluster: # Reclustering -- recursively call the basic jet reco and add this to the sequence, # then add another jet algorithm to run the reclustering step basicJetRecoDict = dict(jetRecoDict) - basicJetRecoDict["recoAlg"] = "a4" + basicJetRecoDict["recoAlg"] = "a4" # Standard size for reclustered (basicJetRecoSequence,basicJetsName) = RecoFragmentsPool.retrieve(jetRecoSequence,None,dataSource=dataSource, **basicJetRecoDict) recoSeq += basicJetRecoSequence - rcJetConstit = JetConstit( xAODType.Jet, []) - rcJetDef = JetDefinition( "AntiKt", 1.0, rcJetConstit) + rcJetDef = JetRecoConfiguration.defineReclusteredJets(jetRecoDict) + rcJetDef.inputdef.inputname = basicJetsName rcJetsFullName = jetNamePrefix+rcJetDef.basename+"RCJets_"+jetRecoDict["jetCalib"] + rcModList = [] # Could set substructure mods + rcJetDef.modifiers = rcModList - rcModList= [] - rcJetConstit.inputname = basicJetsName - - rcConstitPJAlg = getConstitPJGAlg( rcJetConstit ) + rcConstitPJAlg = getConstitPJGAlg( rcJetDef.inputdef ) rcConstitPJKey = rcConstitPJAlg.PJGetter.OutputContainer recoSeq += rcConstitPJAlg @@ -71,8 +69,29 @@ def jetRecoSequence( dummyFlags, dataSource, RoIs = 'FSJETRoI', **jetRecoDict): elif doGrooming: # Grooming needs to be set up similarly to reclustering - # --> build ungroomed jets, then add a grooming alg - pass + # --> build ungroomed jets, then add a grooming alg + # Reclustering -- recursively call the basic jet reco and add this to the sequence, + # then add another jet algorithm to run the reclustering step + ungroomedJetRecoDict = dict(jetRecoDict) + ungroomedJetRecoDict["recoAlg"] = ungroomedJetRecoDict["recoAlg"].rstrip("t") # Drop grooming spec + ungroomedJetRecoDict["jetCalib"] = "nojcalib" # No need to calibrate + (ungroomedJetRecoSequence,ungroomedJetsName) = RecoFragmentsPool.retrieve(jetRecoSequence,None,dataSource=dataSource, **ungroomedJetRecoDict) + recoSeq += ungroomedJetRecoSequence + + ungroomedDef = JetRecoConfiguration.defineJets(ungroomedJetRecoDict) + ungroomedDef.ptmin = 50e3 + + groomDef = JetRecoConfiguration.defineGroomedJets(jetRecoDict,ungroomedDef,ungroomedJetsName) + groomedJetsFullName = jetNamePrefix+groomDef.basename+"Jets_"+jetRecoDict["jetCalib"] + + groomedModList = JetRecoConfiguration.defineCalibFilterMods(jetRecoDict,dataSource) + # Can add substructure mods here + + from JetRecConfig.JetGroomConfig import getJetGroomAlg + groomalg = getJetGroomAlg(groomedJetsFullName,groomDef,groomedModList) + recoSeq += groomalg + + sequenceOut = groomedJetsFullName else: # Normal jet reconstruction, no reclustering or grooming @@ -90,36 +109,11 @@ def jetRecoSequence( dummyFlags, dataSource, RoIs = 'FSJETRoI', **jetRecoDict): pfseq = RecoFragmentsPool.retrieve(PFHLTSequence,clustersKey) recoSeq += pfseq - # Define the jet constituents to be interpreted by JetRecConfig - def defineJetConstit(jetRecoDict,clustersKey): - # Get the details of the constituent definition: - # type, mods and the input container name - if "tc" in jetRecoDict["dataType"]: - # apply this scale - if jetRecoDict["calib"] == "em": - constitMods = ["EM"] - elif jetRecoDict["calib"] == "lcw": - constitMods = ["LC"] - # read from this cluster collection, - # overriding the standard offline collection - jetConstit = JetConstit( xAODType.CaloCluster, constitMods ) - jetConstit.rawname = clustersKey - # apply constituent pileup suppression - if "sk" in jetRecoDict["dataType"]: - constitMods.append("SK") - else: - jetConstit.inputname = clustersKey - return jetConstit - - jetConstit = defineJetConstit(jetRecoDict,clustersKey) + jetDef = JetRecoConfiguration.defineJets(jetRecoDict,clustersKey) doConstitMods = ("sk" in jetRecoDict["dataType"]) if doConstitMods: from JetRecConfig.ConstModHelpers import getConstitModAlg - recoSeq += getConstitModAlg(jetConstit,"HLT") - - # Arbitrary min pt for fastjet, set to be low enough for MHT(?) - # Could/should adjust higher for large-R - jetDef = JetDefinition( "AntiKt", radius, jetConstit, ptmin=5000.) + recoSeq += getConstitModAlg(jetDef.inputdef,"HLT") # chosen jet collection jetsFullName = jetNamePrefix+jetDef.basename+"Jets_"+jetRecoDict["jetCalib"] @@ -130,32 +124,11 @@ def jetRecoSequence( dummyFlags, dataSource, RoIs = 'FSJETRoI', **jetRecoDict): # We can add/configure these differently if desired. In particular, # we could define a TriggerJetMods module if settings need to # diverge substantially e.g. track/vertex collections - from JetRecConfig.StandardJetMods import jetmoddict - # Make generating the list a bit more comprehensible - def getModSpec(modname,modspec=''): - return (jetmoddict[modname],str(modspec)) - # Minimum modifier set for calibration w/o track GSC - # Should eventually build in more mods, depend on track info etc - calibMods = [] - - if jetRecoDict["jetCalib"] != "nojcalib": - # Translate calib specification into something understood by - # the calibration config helper - calibContext,calibSeq = { - ("a4","subjes"): ("TrigRun2","JetArea_EtaJES_GSC"), # Calo GSC only - ("a4","subjesIS"): ("TrigRun2","JetArea_EtaJES_GSC_Insitu"), # Calo GSC only - ("a10","subjes"): ("TrigUngroomed","JetArea_EtaJES"), - }[(jetRecoDict["recoAlg"],jetRecoDict["jetCalib"])] - - calibSpec = calibContext+":"+dataSource+":"+calibSeq - calibMods = [getModSpec("ConstitFourMom"), - getModSpec("CaloEnergies"), - getModSpec("Calib",calibSpec), - getModSpec("Sort")] - jetModList = calibMods + [getModSpec("Filter",5000)] + calibMods = JetRecoConfiguration.defineCalibFilterMods(jetRecoDict,dataSource) + jetModList = calibMods # Add the PseudoJetGetter alg to the sequence - constitPJAlg = getConstitPJGAlg( jetConstit ) + constitPJAlg = getConstitPJGAlg( jetDef.inputdef ) constitPJKey = constitPJAlg.PJGetter.OutputContainer recoSeq += constitPJAlg # Basic list of PseudoJets is just the constituents @@ -165,7 +138,7 @@ def jetRecoSequence( dummyFlags, dataSource, RoIs = 'FSJETRoI', **jetRecoDict): if "sub" in jetRecoDict["jetCalib"]: # Add the event shape alg if needed for area subtraction from JetRecConfig.JetRecConfig import getEventShapeAlg - eventShapeAlg = getEventShapeAlg( jetConstit, constitPJKey, "TrigJet" ) + eventShapeAlg = getEventShapeAlg( jetDef.inputdef, constitPJKey, "TrigJet" ) recoSeq += eventShapeAlg # Generate a JetAlgorithm to run the jet finding and modifiers diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py new file mode 100644 index 00000000000..15d86d8f0b3 --- /dev/null +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/TriggerJetMods.py @@ -0,0 +1,19 @@ +from JetRecConfig.JetDefinition import JetModifier + +######################################################################## +# Special modifier setups used by jet trigger, but not in offline + +# 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 JetMomentTools import JetMomentToolsConf +def getConstitFourMomTool_copy(): + cfourmom = JetMomentToolsConf.JetConstitFourMomTool("constitfourmom_copy", + JetScaleNames = ["DetectorEtaPhi"], + AltConstitColls = [""], + AltConstitScales = [0], + AltJetScales = ["JetConstitScaleMomentum"]) + return cfourmom + +ConstitFourMom_copy = JetModifier("JetConstitFourMomTool", "constitfourmom_copy", + helperfn=getConstitFourMomTool_copy) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py index 13b6ec6e5c2..11d280d5072 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py @@ -49,9 +49,9 @@ def generateChains( flags, chainDict ): TrigAntiKt4EMTopoSubJES = JetDefinition( "AntiKt", 0.4, TrigEMTopo, ptmin=trigMinPt,ptminfilter=trigMinPt) TrigAntiKt4EMTopoSubJES.modifiers = ["Calib:TrigRun2:data:JetArea_EtaJES_GSC_Insitu","Sort"] + clustermods - #TODO: modify jet constituent configs to override offline configs for trigger calo cluster input. jetprefix="Trig" jetsuffix="subjesIS" + # May need a switch to disable automatic modifier prerequisite generation jetRecoComps = JetRecConfig.JetRecCfg(TrigAntiKt4EMTopoSubJES, flags, jetprefix, jetsuffix) inEventReco.mergeReco(jetRecoComps) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py index e440fa9f855..d8c33254eed 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py @@ -86,16 +86,18 @@ def setupMenu(): TriggerFlags.JetSlice.signatures = [ ChainProp(name='HLT_j85_L1J20', groups=SingleJetGroup), ChainProp(name='HLT_j45_L1J20', groups=SingleJetGroup), - ChainProp(name='HLT_j420_L1J20', groups=SingleJetGroup), + ChainProp(name='HLT_j420_L1J20', groups=SingleJetGroup), - #ChainProp(name='HLT_j225_gsc420_boffperf_split_L1J20', groups=SingleJetGroup), + #ChainProp(name='HLT_j225_gsc420_boffperf_split_L1J20', groups=SingleJetGroup), ChainProp(name='HLT_j260_320eta490_L1J20', groups=SingleJetGroup), - ChainProp(name='HLT_j460_a10_lcw_subjes_L1J20', groups=SingleJetGroup), - ChainProp(name='HLT_j460_a10r_L1J20', groups=SingleJetGroup), + ChainProp(name='HLT_j460_a10_lcw_subjes_L1J20', groups=SingleJetGroup), + ChainProp(name='HLT_j460_a10r_L1J20', groups=SingleJetGroup), + ChainProp(name='HLT_j420_a10t_lcw_jes_30smcINF_L1J20', groups=SingleJetGroup), + ChainProp(name='HLT_2j330_a10t_lcw_jes_30smcINF_L1J20', groups=SingleJetGroup), ChainProp(name='HLT_3j200_L1J20', groups=MultiJetGroup), - ChainProp(name='HLT_j0_vbenfSEP30etSEP34mass35SEP50fbet_L1J20', groups=SingleJetGroup), + ChainProp(name='HLT_j0_vbenfSEP30etSEP34mass35SEP50fbet_L1J20', groups=SingleJetGroup), ChainProp(name='HLT_5j70_0eta240_L1J20', groups=MultiJetGroup), # this chain is supposed to be seeded off L1_4J15 in principle, needs CF fix diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py index 3cd957698d9..44ebb2f26e2 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py @@ -107,10 +107,10 @@ JetChainParts = { 'trigType' : ['j'], 'extra' : [], 'cleaning' : ['noCleaning',], - 'recoAlg' : ['a4', 'a10', 'a10r'], + 'recoAlg' : ['a4', 'a10', 'a10r', 'a10t'], 'dataType' : ['tc'], 'calib' : ['em', 'lcw'], - 'jetCalib' : ['subjes', 'subjesIS', 'nojcalib'], + 'jetCalib' : ['jes', 'subjes', 'subjesIS', 'nojcalib'], 'scan' : ['FS',], 'addInfo' : ['perf'], -- GitLab