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