diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/AllJetsGrouper.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/AllJetsGrouper.h
index 47cdba67e25b3dad7025dcccf721bae6d73f2e9d..ee90f693005753a07f5bdbc5faff623a626cc9ae 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/AllJetsGrouper.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/AllJetsGrouper.h
@@ -10,13 +10,13 @@
 class AllJetsGrouper: public IJetGrouper{
  public:
   AllJetsGrouper();
-  AllJetsGrouper(const HypoJetIter& b, const HypoJetIter& e);
+  AllJetsGrouper(const HypoJetCIter& b, const HypoJetCIter& e);
   AllJetsGrouper(const HypoJetVector&);
   
   std::vector<HypoJetGroupVector> group(HypoJetIter&,
 					HypoJetIter&) const override;
   
-  virtual std::optional<HypoJetGroupVector> next() override;
+  virtual std::optional<HypoJetVector> next() override;
   
   std::string getName() const override; 
   std::string toString() const override;
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/CombinationsGrouper.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/CombinationsGrouper.h
index 57f5f57d3a091299d112f793eaee4943df6a2a16..7f573fbb795ea22a97b6bb03b914fb4915cd9f47 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/CombinationsGrouper.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/CombinationsGrouper.h
@@ -22,7 +22,7 @@ class CombinationsGrouper: public IJetGrouper{
   
   std::vector<HypoJetGroupVector> group(HypoJetIter&,
 					HypoJetIter&) const override;
-  std::optional<HypoJetGroupVector> next() override;
+  std::optional<HypoJetVector> next() override;
 
   std::string getName() const override; 
   std::string toString() const override;
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IJetGrouper.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IJetGrouper.h
index 5830516dece0a3cebb3cfb0e2a479cd43f06e47e..02ff057f2e8891bf767fb075bbe8e16726376c93 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IJetGrouper.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IJetGrouper.h
@@ -25,7 +25,7 @@ class IJetGrouper{
    */
   virtual std::vector<HypoJetGroupVector> group(HypoJetIter&,
 						HypoJetIter&) const = 0;
-  virtual std::optional<HypoJetGroupVector> next() = 0;
+  virtual std::optional<HypoJetVector> next() = 0;
   virtual std::string toString() const = 0; 
   virtual std::string getName() const = 0; 
 };
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IndexedJetsGrouper.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IndexedJetsGrouper.h
index e26d29639fe834fea8aefe375a13160799005102..670478e06c8757ec3717334fc8dc4b4908ae1507 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IndexedJetsGrouper.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/IndexedJetsGrouper.h
@@ -36,7 +36,7 @@ public:
   std::vector<HypoJetGroupVector>
   group(HypoJetIter&, HypoJetIter&) const override;
   
-  std::optional<HypoJetGroupVector> next() override;
+  std::optional<HypoJetVector> next() override;
       
   std::string getName() const override;
   std::string toString() const override;
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/SingleJetGrouper.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/SingleJetGrouper.h
index 5d0b474276c72be54531855b3e134cd85978b2a1..11323f411f1a5cb63ef8e677daa9ec7f2e446925 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/SingleJetGrouper.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/TrigHLTJetHypo/TrigHLTJetHypoUtils/SingleJetGrouper.h
@@ -16,13 +16,13 @@ class SingleJetGrouper: public IJetGrouper{
   std::vector<HypoJetGroupVector> group(HypoJetIter&,
 					HypoJetIter&) const override;
 
-  std::optional<HypoJetGroupVector> next() override;
+  std::optional<HypoJetVector> next() override;
   std::string getName() const override; 
   std::string toString() const override;
 
 private:
-  HypoJetVector m_jets;
-  std::size_t m_size;
+  HypoJetVector m_jets{};
+  std::size_t m_size{0};
   std::size_t m_index{0};
 };
 #endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py
index 656f8236623fa0ee0a1a2347685f7bbf6e05ff69..9b3514a3d0386fb82cb1d320aafb817edff8e7d8 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/ConditionsToolSetterFastReduction.py
@@ -14,7 +14,7 @@ from AthenaCommon.Logging import logging
 log = logging.getLogger( 'ConditionsToolSetterFastReduction' )
 
 def is_leaf(node):
-    return node.scenario in  ('simple', 'etaet', 'dijet', 'qjet')
+    return node.scenario in  ('simple', 'etaet', 'dijet', 'qjet', 'agg')
 
 
 def is_inner(node):
@@ -46,11 +46,12 @@ class ConditionsToolSetterFastReduction(object):
             'qjmass': [CompFactory.TrigJetConditionConfig_qjet_mass, 0],
             'smc': [CompFactory.TrigJetConditionConfig_smc, 0],
             'jvt': [CompFactory.TrigJetConditionConfig_jvt, 0],
+            'ht': [CompFactory.TrigJetConditionConfig_htfr, 0],
             'all': [CompFactory.TrigJetConditionConfig_acceptAll, 0],
             'capacitychecked':
             [CompFactory.TrigJetConditionConfig_capacitychecked, 0],
             'fastreduction': [CompFactory.TrigJetHypoToolConfig_fastreduction, 0],
-            'helper': [CompFactory.TrigJetHypoToolHelperMT, 0],
+            'helper': [CompFactory.TrigJetHypoToolHelperNoGrouper, 0],
             }
         for var in self.JetMoments:
             self.tool_factories['mom'+var] = [CompFactory.TrigJetConditionConfig_moment, 0]
@@ -82,7 +83,63 @@ class ConditionsToolSetterFastReduction(object):
         self.tool_factories[key][1] += 1
         return tool
 
+    def _make_el_condition_tools(self, conf_dict):
+        """conf_dict: a dict containing names of elemental conditions 
+        and min, max valies. These will be used to instantiate
+        conditon building AlgTools, one for eac conditon 
+
+        for 2j80_2j60, the dictionaries are:
+        {'et': {'min': '80000.0', 'max': 'inf'}, 
+        'eta': {'min': '0.0', 'max': '3.2'}}
+
+        and 
+
+
+        {'et': {'min': '60000.0', 'max': 'inf'}, 
+        'eta': {'min': '0.0', 'max': '3.2'}})
+        
+        """
+
+        condition_tools = [] # a list of AlgTools that build elemental Conds.
+        
+        for k, v in conf_dict.items(): # loop over elemental conditions
+            # k in the condition name, v contains its min, max values.
+
+            # create the AlgTool that will build the elemental condition
+            condition_tool = self._get_tool_instance(k) 
+            for lim, val in v.items():  # lim: min, max
+                setattr(condition_tool, lim, val)
+
+            # SPECIAL CASE: Moment tool needs the name of the
+            # moment as well as the min. max cuts:
+            if (k.startswith ('mom')):
+                moment = k[len('mom'):]
+                if moment in self.JetMoments:
+                    condition_tool.moment = self.JetMoments[moment]
+                else: raise RuntimeError('%s not supported' % (moment))
+
+            # END SPECIAL CASE
+
+            condition_tools.append(condition_tool)
+
+        return condition_tools
+
+    
     def _make_compound_condition_tools(self, node):
+        """For each element of  node.conf_attrs, construct a 
+        CapacityChecledCondition. Example for chain HLT_2j80_3j60_L1J15:
+
+        First leaf node has 
+        conf_attrs [1]:
+        (defaultdict(<class 'dict'>, {
+        'et': {'min': '80000.0', 'max': 'inf'}, 
+        'eta': {'min': '0.0', 'max': '3.2'}}), 2)
+
+        Second leaf node has 
+        conf_attrs [1]:
+        (defaultdict(<class 'dict'>, {'et': {'min': '60000.0', 'max': 'inf'}, 
+        'eta': {'min': '0.0', 'max': '3.2'}}), 3)
+        """
 
         #  compound_condition_tools:
         # elemental condition maker AlgToolshelper by the compound condition
@@ -99,25 +156,9 @@ class ConditionsToolSetterFastReduction(object):
                 cpi = node.chainpartinds[i][0]
                 assert mult == node.chainpartinds[i][1]
                     
-                
-            condition_tools = [] # elemental conditions for this compounnd ct.
-            for k, v in c.items(): # loop over elemental conditions
-                condition_tool = self._get_tool_instance(k)
-                for lim, val in v.items():  # lim: min, max
-                    setattr(condition_tool, lim, val)
-
-                # SPECIAL CASE: Moment tool needs the name of the
-                # moment as well as the min. max cuts:
-                if (k.startswith ('mom')):
-                    moment = k[len('mom'):]
-                    if moment in self.JetMoments:
-                        condition_tool.moment = self.JetMoments[moment]
-                    else: raise RuntimeError('%s not supported' % (moment))
-
-                # END SPECIAL CASE
-
-                condition_tools.append(condition_tool)
 
+            el_condition_tools = self._make_el_condition_tools(c)
+ 
             # create capacitychecked condition from elemental condition
             condition_tool =self._get_tool_instance('capacitychecked')
 
@@ -126,16 +167,38 @@ class ConditionsToolSetterFastReduction(object):
                 # convert label from string to int for more efficient
                 # processing in C++ land.
                 condition_tool.chainPartInd = int(cpi[len('leg'):])
-            else:
-                condition_tool.chainPartInd = 0
             
-            condition_tool.conditionMakers = condition_tools
+            condition_tool.conditionMakers = el_condition_tools
             condition_tool.multiplicity = mult
             # add capacitychecked condition to list
             outer_condition_tools.append(condition_tool)
             
         return outer_condition_tools
 
+    
+    def _make_filter_tool(self, node):
+        """Condtion filters use a list of CompoundCondition containing
+        single jet elemental conditions  select a subset of the reco
+        jets to send to the a Condition"""
+        
+        el_condition_tools = []
+        for fc, mult in node.filter_conditions:
+            assert len(fc) == 1  # 1 elemental condition
+            assert mult == 1
+            el_condition_tools.extend(self._make_el_condition_tools(fc))
+
+        if not el_condition_tools:
+            el_condition_tools.append(self._get_tool_instance('all'))
+
+        capacitychecked_condition_tool = self._get_tool_instance(
+            'capacitychecked')
+
+        capacitychecked_condition_tool.conditionMakers = el_condition_tools
+        capacitychecked_condition_tool.multiplicity = 1
+        
+        return capacitychecked_condition_tool
+    
+
     def _mod_leaf(self, node):
         """ Add Condition tools to For a leaf node."""
 
@@ -155,6 +218,17 @@ class ConditionsToolSetterFastReduction(object):
         node.compound_condition_tools = self._make_compound_condition_tools(
             node)
 
+        # make condition builder AlgTools for the condition filters.
+        # condition filters select subsets of the input jets to present
+        # to a condition,
+        
+        node.filter_tool = self._make_filter_tool(node)
+
+    
+        # if node.scenario == 'agg':
+        #     print (node)
+        #    assert False
+            
     def report(self):
         wid = max(len(k) for k in self.tool_factories.keys())
         rep = '\n%s: ' % self.__class__.__name__
@@ -171,20 +245,27 @@ class ConditionsToolSetterFastReduction(object):
             self._fill_tree_map(cn, tmap)
 
             
-    def _fill_conditions_map(self, node, cmap):
+    def _fill_conditions_map(self, node, cmap, fmap):
         if is_leaf(node):
 
             assert (len(node.compound_condition_tools) == 1)
             cmap[node.node_id] = node.compound_condition_tools[0]
-
+            fmap[node.node_id] = node.filter_tool
+            
         else:
             # must have a tool for Gaudi to instantiate in
             cmap[node.node_id] = self._get_tool_instance('capacitychecked')
             cmap[node.node_id].conditionMakers = [self._get_tool_instance('all')]
             cmap[node.node_id].multiplicity = 1
+
+            fmap[node.node_id] = self._get_tool_instance('capacitychecked')
+            fmap[node.node_id].conditionMakers = [self._get_tool_instance('all')]
+            fmap[node.node_id].multiplicity = 1
+
+            
         
         for cn in node.children:
-            self._fill_conditions_map(cn, cmap)
+            self._fill_conditions_map(cn, cmap, fmap)
 
 
     def _map_2_vec(self, amap):
@@ -230,14 +311,17 @@ class ConditionsToolSetterFastReduction(object):
         treeVec = self._map_2_vec(tree_map)
 
         conditionsMap = {}
-        self._fill_conditions_map(tree, conditionsMap)
+        filterConditionsMap = {}
+        self._fill_conditions_map(tree, conditionsMap, filterConditionsMap)
         conditionsVec = self._map_2_vec(conditionsMap)
+        filterConditionsVec = self._map_2_vec(filterConditionsMap)
                
         # make a config tool and provide it with condition makers
         config_tool = self._get_tool_instance('fastreduction')
         config_tool.conditionMakers = conditionsVec
+        config_tool.filtConditionsMakers = filterConditionsVec
         config_tool.treeVector = treeVec
-
+        
         nodestr = 'n%dp%d' % (tree.node_id, tree.parent_id)
         helper_tool = self._get_tool_instance('helper', extra=nodestr)
         helper_tool.HypoConfigurer = config_tool
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py
index 431a17d5877d26550cdcc4e0487bb84d50a97e90..bb6155862780fa803d72df05450611faa85cd38d 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py
@@ -8,8 +8,6 @@ from TrigHLTJetHypo.ConditionsToolSetterFastReduction import (
     ConditionsToolSetterFastReduction,
 )
 
-from TrigHLTJetHypo.ConditionsToolSetterHT import ConditionsToolSetterHT
-
 from  TrigHLTJetHypo.chainDict2jetLabel import chainDict2jetLabel
 
 from  TrigHLTJetHypo.ChainLabelParser import ChainLabelParser
@@ -20,10 +18,10 @@ from TrigHLTJetHypo.NodeSplitterVisitor import NodeSplitterVisitor
 from AthenaCommon.Logging import logging
 log = logging.getLogger( 'TrigJetHypoToolConfig' )
 
-def  trigJetHypoToolHelperFromDict_(
+def  nodeTreeFromChainLabel(
         chain_label, # simple([(260et,320eta490, leg000)])
         chain_name, # HLT_j260_320eta490_L1J75_31ETA49
-        toolSetter=None):
+        toolSetter):
 
     parser = ChainLabelParser(chain_label, debug=False)
 
@@ -59,12 +57,23 @@ def  trigJetHypoToolHelperFromDict_(
     log.info('trigJetHypoToolFromDict chain_name %s', chain_name)
 
     toolSetter.mod(tree)
-    tool = toolSetter.tool
+    return tree
 
-    log.debug(toolSetter.report())
 
-    return tool
+def trigJetHypoToolHelperFromDict_(
+        chain_label, # simple([(260et,320eta490, leg000)])
+        chain_name, # HLT_j260_320eta490_L1J75_31ETA49
+        toolSetter):
 
+    nodeTreeFromChainLabel(
+        chain_label,
+        chain_name,
+        toolSetter)
+    
+    tool = toolSetter.tool
+    log.debug(toolSetter.report())
+    
+    return tool
 
 def  trigJetHypoToolHelperFromDict(chain_dict):
     """Produce  a jet trigger hypo tool helper from a chainDict
@@ -91,11 +100,7 @@ def  trigJetHypoToolHelperFromDict(chain_dict):
 
     chain_name = chain_dict['chainName']
 
-    toolSetter = None
-    if 'agg' in chain_name:
-        toolSetter=ConditionsToolSetterHT()
-    else:
-        toolSetter=ConditionsToolSetterFastReduction()
+    toolSetter = ConditionsToolSetterFastReduction()
 
     return trigJetHypoToolHelperFromDict_(chain_label,
                                           chain_name,
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py
index d01c48a6395663499eab149a73489f913a6efa31..b78bc88bce17470aa5b38a99c154a10e8a8fc974 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/chainDict2jetLabel.py
@@ -297,9 +297,9 @@ def _make_agg_label(chain_parts, leg_label):
 
     argvals['leg_label'] = leg_label
     result =  """
-    ht([(%(htlo).0fht, %(leg_label)s)
+    agg([(%(htlo).0fht, %(leg_label)s)
         (%(etlo).0fet)
-        (%(etalo).0feta%(etahi).0f)
+    (%(etalo).0feta%(etahi).0f)
     ])"""  % argvals
     print (result)
     return result
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/node.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/node.py
index 7b75c37525d04072399faa426506afecf2c9919d..9bc459c46b581f42844a33fecf5078a172767305 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/node.py
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/node.py
@@ -29,11 +29,14 @@ class Node(object):
 
         # filled in by a CondtionsTollSetter:
         self.compound_condition_tools = [] 
-        # self.tool = None
-        # self.compound_condition_tools = []
-        # self.tree_top kludge carensure top level tools get chain name
-        # as Tool name
         self.chainpartinds = []
+
+        # Condition objects may have filters
+        # eg HT may have an et filter. Filters are made up of conditions
+        # and are used to form jet subsets.
+        self.filter_conditions = []
+        self.filter_tool = None
+        
         self.tree_top = False
         self.tool = None
         
@@ -91,11 +94,17 @@ class Node(object):
         for ca in self.conf_attrs:
             s.append(indent + str(ca))
         
-            # this attribute added by flow network setter tool
-            s.append(indent + 'compound_condition_tools [%d]' % len(
-                self.compound_condition_tools))
+        s.append(indent + 'filter_conditions [%d]:' % (
+            len(self.filter_conditions),))
+                 
+        for fc in self.filter_conditions:
+            s.append(indent + str(fc))
+
+        s.append(indent + 'compoundConditionTools [%d]:' % len(
+            self.compound_condition_tools))
+
+        s.append(indent + 'filter_tool :' + str(self.filter_tool))
 
-        s.append(indent + 'AlgTool: %s' % str(self.tool))
         s.append(indent + 'No of children: %d\n' % len(self.children))
 
         return s
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py
index 21a0691446e324f9bfe6078a2373c848803a3c4e..3166c3197c77fef046ff107d10d2d0043f210df6 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/testChainDictMaker.py
@@ -11,7 +11,13 @@ from TriggerMenuMT.HLTMenuConfig.Menu.ChainDefInMenu import ChainProp
 from TriggerMenuMT.HLTMenuConfig.Menu.DictFromChainName import dictFromChainName
 
 from chainDict2jetLabel import chainDict2jetLabel 
-from TrigJetHypoToolConfig import trigJetHypoToolFromDict
+from TrigJetHypoToolConfig import (trigJetHypoToolFromDict,
+                                   nodeTreeFromChainLabel)
+
+from TrigHLTJetHypo.ConditionsToolSetterFastReduction import (
+    ConditionsToolSetterFastReduction,
+)
+
 
 def testChainDictMaker():
 
@@ -43,7 +49,7 @@ def testChainDictMaker():
 
         ChainProp(name='HLT_j0_aggSEP1000htSEP30etSEP0eta320_L1J20',
                   groups=SingleJetGroup),
-
+        
         # ChainProp(name='HLT_j70_j50 _0eta490_invm1000j50_dphi20_deta40_L1J20',
         #          l1SeedThresholds=['FSNOSEED']*2,
         #          groups=MultiJetGroup),
@@ -70,6 +76,22 @@ if __name__ == '__main__':
         print (chainDict2jetLabel(d[1]))
         print ()
 
+        
+    print ('\n node trees:\n')
+    
+    for d in dicts:
+        print (d[0])
+        label = chainDict2jetLabel(d[1])
+        chain_name = d[1]['chainName']
+        
+        toolSetter=ConditionsToolSetterFastReduction()
+            
+        print (nodeTreeFromChainLabel(chain_name=d[0],
+                                      chain_label=label,
+                                      toolSetter=toolSetter).dump())
+        print ()
+        
+
     print ('\nMaking TrigJetHypoTool for each dictiomary\n')
     for d in dicts:
         print (d[0])
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py
index 3133ab0191dbd3fb0f113c2a1f41fb9d3330eb66..a91db097e259da63274c673568464df9de136b9c 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/treeVisitors.py
@@ -34,13 +34,15 @@ def defaultParameters(parameter, default=''):  # default if parameter unknown
                 'smchi': 'inf',                
                 'jvtlo': '0',
                 'jvthi': 'inf',
+                'htlo' : '1000.',
+                'hthi' : 'inf',
     }
 
     if parameter.startswith('mom'):
         parameter = 'momCuts'
 
     if parameter not in  defaults:
-        print ('defaultParameters: unknown parameter, tryurning default ',
+        print ('defaultParameters: unknown parameter, returning default ',
                parameter)
 
     return defaults.get(parameter, default)
@@ -284,6 +286,47 @@ class TreeParameterExpander_simple(object):
         return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) 
 
 
+class TreeParameterExpander_agg(object):
+    """Convert parameter string into duction holding low, high window
+        cut vals, as for the  'simple' scenario. Then place conditions
+        not in the agg list in the filters dict. These conditions wil be used
+        to select the subset of the jet collection to be presented to the agg
+        conditions."""
+
+    agg_conditions = ('ht',)
+    
+    def __init__(self):
+        self.msgs = []
+
+    def mod(self, node):
+
+        simple_expander = TreeParameterExpander_simple()
+        simple_expander.mod(node)
+
+        # example conf_attrs:
+        # conf_attrs [3]:
+        # (defaultdict(<class 'dict'>,
+        #              {'ht': {'min': '1000000.0', 'max': 'inf'}}), 1)
+        # (defaultdict(<class 'dict'>,
+        #              {'et': {'min': '30000.0', 'max': 'inf'}}), 1)
+        # (defaultdict(<class 'dict'>,
+        #             {'eta': {'min': '0.0', 'max': '3.2'}}), 1)
+
+
+        for ca in node.conf_attrs:
+            assert len(ca) == 2  # (dict, mult)
+            assert len(ca[0]) == 1  # one entry in dict
+            ca_keys = ca[0].keys()
+            cond_name = list(ca_keys)[0]
+            if cond_name not in self.agg_conditions:
+                node.filter_conditions.append(ca)
+        for fc in node.filter_conditions:
+            node.conf_attrs.remove(fc)
+
+    def report(self):
+        return '%s: ' % self.__class__.__name__ + '\n'.join(self.msgs) 
+
+
 class TreeParameterExpander_dijet(object):
     """Convert parameter string into tuples holding low, high window
     cut vals. Specialistaion for the dijet scenario
@@ -360,7 +403,7 @@ class TreeParameterExpander(object):
         'z': TreeParameterExpander_null,
         'root': TreeParameterExpander_null,
         'simple': TreeParameterExpander_simple,
-        'ht': TreeParameterExpander_simple,
+        'agg': TreeParameterExpander_agg,
         'dijet': TreeParameterExpander_dijet,
         'qjet': TreeParameterExpander_simple,
         'all': TreeParameterExpander_all,
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ConditionFilter.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ConditionFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..04d82ce07394bcbf32635acd2e172bdd4b60b813
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ConditionFilter.cxx
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <algorithm>
+
+#include "./ConditionFilter.h"
+
+ConditionFilter::ConditionFilter(ConditionPtrs& conditions):
+  m_conditions(std::move(conditions)) {
+}
+
+struct FilterPred{
+  FilterPred(const ConditionPtr& cptr,
+	     const std::unique_ptr<ITrigJetHypoInfoCollector>& collector):
+    m_cptr(cptr), m_collector(collector) {
+  }
+
+  bool operator() (pHypoJet pjet) {
+    auto hjv = HypoJetVector{pjet};
+    return m_cptr->isSatisfied(hjv, m_collector);
+  }
+
+  const ConditionPtr& m_cptr;
+  const std::unique_ptr<ITrigJetHypoInfoCollector>& m_collector;
+};
+
+HypoJetVector
+ConditionFilter::filter (const HypoJetCIter& begin,
+			 const HypoJetCIter& end,
+			 const std::unique_ptr<ITrigJetHypoInfoCollector>& collector) const {
+
+  HypoJetVector in (begin, end);
+  auto new_end = in.end();
+  
+  for (const auto& cptr : m_conditions) {
+    new_end = std::partition(in.begin(),
+			 new_end,
+			 FilterPred(cptr, collector));
+  }
+  
+  return HypoJetVector(in.begin(), new_end);
+}
+
+std::string ConditionFilter::toString() const {
+  std::stringstream ss;
+  const void* address = static_cast<const void*>(this);
+  ss << "ConditionFilter: (" << address << ")\n"
+     << "Conditions [" << m_conditions.size() << "]:\n";
+  for (const auto& c : m_conditions) {
+     ss << " " << c->toString() << "\n\n";
+   }
+
+  return ss.str();
+}
+
+	   
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ConditionFilter.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ConditionFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..3911c3f5ff322a8c2d88407e9f8888d0e74fc20d
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ConditionFilter.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGHLTJETHYPO_CONDITIONFILTER_H
+#define TRIGHLTJETHYPO_CONDITIONFILTER_H
+
+#include "./CapacityCheckedConditionsDefs.h"
+
+class ConditionFilter {
+ public:
+  ConditionFilter(ConditionPtrs&);
+
+  // find the subset of jets which satisfy a sequence of conditions
+  HypoJetVector filter (const HypoJetCIter& b,
+			const HypoJetCIter& e,
+			const std::unique_ptr<ITrigJetHypoInfoCollector>&
+			) const;
+  
+  std::string toString() const;  
+ private:
+  ConditionPtrs m_conditions;
+
+  
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx
index 7e174e07d330c3df6b6781fd99feba301e4039f6..05dafc68253b9d7ca0ab55d6707ae87dd9e214ab 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx
@@ -3,6 +3,7 @@
 */
 
 #include "./FastReducer.h"
+#include "./GrouperByCapacityFactory.h"
 #include "./ITrigJetHypoInfoCollector.h"
 
 #include <map>
@@ -36,13 +37,14 @@ struct IndexVecComp{
 };
 
 
-FastReducer::FastReducer(const HypoJetGroupCIter& groups_b,
-                         const HypoJetGroupCIter& groups_e,
+FastReducer::FastReducer(const HypoJetCIter& jets_b,
+                         const HypoJetCIter& jets_e,
                          const ConditionPtrs& conditions,
+			 const ConditionFilters& filters,
                          const Tree& tree,
                          xAODJetCollector& jetCollector,
                          const Collector& collector):
-  m_conditions(conditions),  m_tree(tree) {
+  m_conditions(conditions),  m_conditionFilters(filters), m_tree(tree) {
 
   // create an empty vector of indices of satisfying jet groups
   // for each Condition.
@@ -52,8 +54,8 @@ FastReducer::FastReducer(const HypoJetGroupCIter& groups_b,
   }
 
 
-  if(!findInitialJetGroups(groups_b,
-			   groups_e,
+  if(!findInitialJetGroups(jets_b,
+			   jets_e,
 			   collector)){
     if(collector){
       collector->collect("FastReducer early return",
@@ -162,57 +164,57 @@ void FastReducer::collectLeafJets(xAODJetCollector& jetCollector,
 }
 
 
-bool FastReducer::findInitialJetGroups(const HypoJetGroupCIter& groups_b,
-				       const HypoJetGroupCIter& groups_e,
+bool FastReducer::findInitialJetGroups(const HypoJetCIter& jets_b,
+				       const HypoJetCIter& jets_e,
 				       const Collector& collector) {
   
 
   /*
-    Will now test the incoming jet groups against the leaf conditions.
+    Will now test the incoming jets against the leaf conditions.
   */
 
   std::size_t ijg{0};
   auto leaves = m_tree.leaves();
 
-  for(auto iter = groups_b; iter != groups_e; ++iter){
-    auto jg = *iter;
-    
-    if(jg.size() != 1){
-      collector->collect("FastReducer", "Initial jet group size != 1");
-      return false;
-    }
-    
-    // if a jet group satisfies a condition, note the fact,
-    // and store it by index
-    bool jg_used{false};
+  // if a jet group satisfies a condition, note the fact,
+  // and store it by index
+
+  for(const auto& leaf: leaves){
+
+    auto& filter = m_conditionFilters[leaf];
+    auto filtered_jets = filter->filter(jets_b, jets_e, collector);
+
+    recordFiltering(leaf, jets_e-jets_b, filtered_jets.size(), collector);
+
     
-    auto cur_jg = m_jgIndAllocator(std::vector<std::size_t>{ijg});
-    for(const auto& leaf: leaves){
-      
-      m_testedBy[leaf].insert(cur_jg);
+    auto grouper = grouperByCapacityFactory(m_conditions[leaf]->capacity(),
+					    filtered_jets.begin(),
+					    filtered_jets.end());
+
+    while(true){
+      auto ojg = grouper->next();
+      if (!ojg.has_value()) {break;}
+
+      auto jg = *ojg;
+      auto jg_ind = m_jgRegister.record(jg);
+      m_testedBy[leaf].insert(jg_ind);
       if (m_conditions[leaf]->isSatisfied(jg, collector)){
-	jg_used= true;
-	if(collector){recordJetGroup(cur_jg, jg, collector);}
+	if(collector){recordJetGroup(jg_ind, jg, collector);}
 	// do the following for each satisfied condition ...
-	m_satisfiedBy[leaf].push_back(cur_jg);
+	m_satisfiedBy[leaf].push_back(jg_ind);
+	m_jg2elemjgs[jg_ind] =  std::vector<std::size_t>{jg_ind};
+	m_indJetGroup.emplace(jg_ind, jg);
+	++ijg;
       }
     }
-    
-    if(jg_used){
-      m_jg2elemjgs[cur_jg] =  std::vector<std::size_t>{cur_jg};
-      m_indJetGroup.emplace(cur_jg, jg);
-      ++ijg;
-    }
-    
   }
-  
+    
   if(collector){
     for(const auto& p : m_indJetGroup){
       recordJetGroup(p.first, p.second, collector);
     }
   }
-
-
+  
   // check all leaf conditions are satisfied
   for (const auto& i : leaves) {
     if (!capacitySatisfied(i, collector)) {
@@ -220,47 +222,9 @@ bool FastReducer::findInitialJetGroups(const HypoJetGroupCIter& groups_b,
     }
   }
   
-  /*
-    For the special but important case where all leaf nodes have
-    the root node as a parent, check that there are enough jets
-    to pass the hypo. This prevents doing a long calculation 
-    to discover that the hypo will fail. For example, if the chain
-    requires 10j40, and there are 5 jets that pass the condition,
-    each condition will be satisfied by th 5 jets, and 5^10 combinations
-    will be attempted in th seach for a successful combination. As there
-    are only 5 jets involved, such a combination does not exist.
-
-    Such trees have a tree vector with all entries == 0.
-
-    This check cannot be applied in the general case. For example,
-    if the root condition requires 4 jets, and has three children,
-    two of which are leaf nodes, while the other is not, then the
-    check will fail the event as no jets have yet ben assigned to the
-    second child, while the full popagation through the tree may pass the
-    event.
-
-    A possible way to tighten the chck would be to forbid children to be
-    separated from thir parent by more than 1 generation.
-  */
-
-  if (std::all_of(m_tree.cbegin(),
-		  m_tree.cend(),
-		  [](std::size_t i){return i == 0;})) {
-    
-    if (m_conditions[0]->capacity() > ijg) {
-      
-      if (collector){
-	collector->collect("FastReducer", "too few children. root capacity "
-			   + std::to_string(m_conditions[0]->capacity()) +
-			   " no of children: " + std::to_string(ijg));
-      }
-
-      return false;
-    }
-  }
-  
   return true;
 }  
+  
 
 bool FastReducer::propagateJetGroups(const Collector& collector){
   
@@ -395,18 +359,20 @@ bool FastReducer::propagate_(std::size_t child,
     }
 
     HypoJetVector jg;
-
+    for(const auto& i : elem_jgs){
+      jg.push_back(m_indJetGroup.at(i)[0]);  // why [0]? assume elemental jg has size 1
+    }
+    
     // obtain an index for the new jet group.
-    auto cur_jg = m_jgIndAllocator(elem_jgs);
+    // auto cur_jg = m_jgIndAllocator(elem_jgs);
+    auto cur_jg = m_jgRegister.record(jg);
     if(m_testedBy[par].find(cur_jg) != m_testedBy[par].end()){
       next = jg_product.next(collector);
       continue;
     }
     m_testedBy[par].insert(cur_jg);
 	
-    for(const auto& i : elem_jgs){
-      jg.push_back(m_indJetGroup.at(i)[0]);  // why [0]? assume elemental jg has size 1
-    }
+
 
     if (m_conditions[par]->isSatisfied(jg, collector)){// par is a tree ind.
 
@@ -526,6 +492,22 @@ void FastReducer::recordJetGroup(std::size_t ind,
   collector->collect(ss0.str(), ss1.str());
 }
 
+void FastReducer::recordFiltering(std::size_t leaf_ind,
+				  std::size_t n_injets,
+				  int n_filteredjets,
+				  const Collector& collector) const {
+
+  if(!collector) {return;}
+  
+  std::stringstream ss0;
+  ss0  << "FastReducer filtering Condition index: "  << leaf_ind;
+  
+  std::stringstream ss1;
+  ss1  << "n jets. in: " << n_injets << " filtered: " << n_filteredjets << '\n';
+  
+  collector->collect(ss0.str(), ss1.str());
+}
+
 bool FastReducer::pass() const { return m_pass; }
 
 
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.h
index 7f3d1191fdd18e53c32bec702fa71b4bd4c992fb..99a374e9093c7235748d6ebd3eac69d0654bcdeb 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.h
@@ -11,7 +11,10 @@
 #include "./JetGroupIndAllocator.h"
 #include "./xAODJetCollector.h"
 #include "./ITrigJetHypoInfoCollector.h"
+#include "./JetGroupRegister.h"
+#include "./ConditionFilter.h"
 #include <string>
+#include <map>
 
 using TreeVec = std::vector<std::size_t>;
 using IDJetGroup = std::map<std::size_t, HypoJetVector>;
@@ -22,14 +25,16 @@ typedef std::unique_ptr<ITrigJetHypoInfoCollector> Collector;
 */
 
 using JetGroupInd2ElemInds = std::map<int, std::vector<std::size_t>>;
+using  ConditionFilters = std::vector<std::unique_ptr<ConditionFilter>>;
 
 
 class FastReducer {
  public:
 
-  FastReducer(const HypoJetGroupCIter& groups_b,
-              const HypoJetGroupCIter& groups_e,
+  FastReducer(const HypoJetCIter& jets_b,
+              const HypoJetCIter& jets_e,
               const ConditionPtrs& conditionObjects,
+	      const ConditionFilters& conditionFilters,
               const Tree& conditionsTree,
               xAODJetCollector& jetCollector,
               const Collector& collector);
@@ -45,8 +50,12 @@ class FastReducer {
 
  private:
 
+  // conditions owned by the matcher
   const ConditionPtrs& m_conditions;
 
+  // conditionFilters owned by the matcher
+  const ConditionFilters& m_conditionFilters;
+
   /** tree structure for Conditions objects.
    The conditions tree gives relations among conditions (eg parent-child
    and siblings-of)
@@ -75,15 +84,16 @@ class FastReducer {
 
   HypoJetVector m_passingJets;
 
-  JetGroupIndAllocator m_jgIndAllocator;
-  
+  //  JetGroupIndAllocator m_jgIndAllocator;
+
+  JetGroupRegister m_jgRegister;
   /** set up the data structures for propagation. Propagation is the
    act of combining jet groups satisfying children
    in preparration for testing against parent conditions.
   */
   
-  bool findInitialJetGroups(const HypoJetGroupCIter& groups_b,
-			    const HypoJetGroupCIter& groups_e,
+  bool findInitialJetGroups(const HypoJetCIter& jets_b,
+			    const HypoJetCIter& jets_e,
 			    const Collector& collector);
   
   
@@ -102,6 +112,11 @@ class FastReducer {
 		      const HypoJetVector& jg,
 		      const Collector& collector) const;
 
+  void recordFiltering(std::size_t leaf_ind,
+		       std::size_t n_inputjets,
+		       int n_filteredjets,
+		       const Collector& collector) const;
+
   void collectLeafJets(xAODJetCollector& jetCollector,
 		       const Collector& collector) const;
 
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx
index 81c85760c25499854dc9501ee5a2bc411c41a7a8..d30fb5d240ad9692cea125c2d7fa3d7ee02b7515 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx
@@ -10,9 +10,11 @@
 #include <algorithm>
 #include <sstream>
 
-FastReductionMatcher::FastReductionMatcher(ConditionPtrs conditions,
+FastReductionMatcher::FastReductionMatcher(ConditionPtrs& conditions,
+					   ConditionFilters& filters,
 					   const Tree& tree):
   m_conditions(std::move(conditions)),
+  m_conditionFilters(std::move(filters)),
   m_tree(tree){
 
   for (const auto& il : m_tree.leaves()){
@@ -20,12 +22,16 @@ FastReductionMatcher::FastReductionMatcher(ConditionPtrs conditions,
       throw std::runtime_error("Tree leaf condition  but not from ChainPart");
     }
   }
+  if (filters.size() != conditions.size()) {
+    throw std::runtime_error("Conditions and ConditionFilters sequence sizes differ");
+  }
+
 }
 	 
 
 std::optional<bool>
-FastReductionMatcher::match(const HypoJetGroupCIter& groups_b,
-			    const HypoJetGroupCIter& groups_e,
+FastReductionMatcher::match(const HypoJetCIter& jets_b,
+			    const HypoJetCIter& jets_e,
 			    xAODJetCollector& jetCollector,
 			    const std::unique_ptr<ITrigJetHypoInfoCollector>& collector,
 			    bool) const {
@@ -43,9 +49,10 @@ FastReductionMatcher::match(const HypoJetGroupCIter& groups_b,
    */
 
 
-  FastReducer reducer(groups_b,
-                      groups_e,
+  FastReducer reducer(jets_b,
+                      jets_e,
                       m_conditions,
+		      m_conditionFilters,
                       m_tree,
                       jetCollector,
                       collector);
@@ -68,5 +75,17 @@ std::string FastReductionMatcher::toString() const {
     ss << sc <<": "<< c->toString() + '\n';
   }
 
+  ss << "FastReductionMatcher ConditionFilters ["
+     << m_conditionFilters.size() << "]: \n";
+
+
+  count = 0;
+  for(const auto& c : m_conditionFilters){
+    auto sc = std::to_string(count++);
+    sc.insert(sc.begin(), 3-sc.length(), ' ');
+    ss << sc <<": "<< c->toString() + '\n';
+  }
+  
+
   return ss.str();
 }
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.h
index 9b1e68b8a6ff7639cc816a945e1b359d5f4863a1..ec33356e024576cf22ddc1e62731fcd26166086f 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.h
@@ -6,17 +6,21 @@
 #define TRIGHLTJETHYPO_FASTREDUCTIONMATCHER_H
 
 
-#include "./IGroupsMatcherMT.h"
+#include "./IJetsMatcherMT.h"
 #include "./CapacityCheckedConditionsDefs.h"
+#include "./ConditionFilter.h"
 #include "./Tree.h"
 
 using TreeVec = std::vector<std::size_t>;
 class ITrigJetHypoInfoCollector;
 
-class FastReductionMatcher: public IGroupsMatcherMT {
+using  ConditionFilters = std::vector<std::unique_ptr<ConditionFilter>>;
+
+class FastReductionMatcher: public IJetsMatcherMT {
  public:
 
-  FastReductionMatcher(ConditionPtrs,
+  FastReductionMatcher(ConditionPtrs&,
+		       ConditionFilters&,
 		       const Tree&);
 
 
@@ -30,8 +34,8 @@ class FastReductionMatcher: public IGroupsMatcherMT {
   */
   
   virtual std::optional<bool>
-    match(const HypoJetGroupCIter& groups_b,
-	  const HypoJetGroupCIter& groups_e,
+    match(const HypoJetCIter& jets_b,
+	  const HypoJetCIter& jets_e,
 	  xAODJetCollector&,
 	  const std::unique_ptr<ITrigJetHypoInfoCollector>& collector,
 	  bool
@@ -42,7 +46,7 @@ class FastReductionMatcher: public IGroupsMatcherMT {
  private:
 
   ConditionPtrs m_conditions;
-
+  std::vector<std::unique_ptr<ConditionFilter>> m_conditionFilters;
   /** tree structure for Conditions objects.
    The conditions tree gives relations among conditions (eg parent-child
    and siblings-of)
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/GrouperByCapacityFactory.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/GrouperByCapacityFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f2c7e5b8269880a05227b1b85b07b79086734b15
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/GrouperByCapacityFactory.cxx
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GrouperByCapacityFactory.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/AllJetsGrouper.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/SingleJetGrouper.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/CombinationsGrouper.h"
+
+
+std::unique_ptr<IJetGrouper> grouperByCapacityFactory(unsigned int cap,
+						      const HypoJetCIter& b,
+						      const HypoJetCIter& e){
+
+  std::unique_ptr<IJetGrouper> pGrouper(nullptr);
+  
+  if (cap == 0) {
+    throw std::runtime_error("groupByMultFactory - attempting ctrct grouper with mult == 0");
+  } else if (cap == 1) {
+    pGrouper.reset(new SingleJetGrouper(b, e));
+  } else if (cap == std::numeric_limits<int>::max()) {
+    pGrouper.reset(new AllJetsGrouper(b, e));
+  } else {
+    pGrouper.reset(new CombinationsGrouper(cap, b, e));
+  }
+
+  return pGrouper;
+}
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/GrouperByCapacityFactory.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/GrouperByCapacityFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf227df628d251b9a7fdba13eef6215ad561d0b3
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/GrouperByCapacityFactory.h
@@ -0,0 +1,15 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGHLTJETHYPO_GROUPERBYCAPACITYFACTORY_H
+#define TRIGHLTJETHYPO_GROUPERBYCAPACITYFACTORY_H
+
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/IJetGrouper.h"
+#include <memory>
+
+std::unique_ptr<IJetGrouper> grouperByCapacityFactory(unsigned int capacity,
+						      const HypoJetCIter& b,
+						      const HypoJetCIter& e);
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/HTConditionFastReduction.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/HTConditionFastReduction.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..639cb3f465d48009d3e006303399f707e037bb14
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/HTConditionFastReduction.cxx
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "./HTConditionFastReduction.h"
+#include "./ITrigJetHypoInfoCollector.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/HypoJetDefs.h"
+
+#include <sstream>
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+HTConditionFastReduction::HTConditionFastReduction(double ht_min,
+						   double ht_max):
+  m_htMin(ht_min), m_htMax(ht_max) {
+}
+
+
+bool
+HTConditionFastReduction::isSatisfied(const HypoJetVector& ips,
+				      const std::unique_ptr<ITrigJetHypoInfoCollector>& collector) const {
+  
+  auto htsum =  std::accumulate(ips.begin(),
+				ips.end(),
+				0.0,
+				[](double sum, const pHypoJet& jp){
+				  return sum + jp->et();});
+  bool pass = htsum > m_htMin;
+  
+  if(collector){
+    std::stringstream ss0;
+    const void* address = static_cast<const void*>(this);
+    ss0 << "HTCondition: (" << address << ") Sum(et) "
+	<< htsum << " "
+	<< std::boolalpha << pass <<  " jet group: \n";
+    
+    std::stringstream ss1;
+    
+    for(const auto& ip : ips){
+      address = static_cast<const void*>(ip.get());
+      ss1 << "    "  << address << " " << ip->eta() << " e " << ip->e() << '\n';
+    }
+    ss1 << '\n';
+    collector -> collect(ss0.str(), ss1.str());
+  }
+  
+  return pass;
+  
+}
+    
+
+std::string HTConditionFastReduction::toString() const {
+  std::stringstream ss;
+  ss << "HTConditionFastReduction: htMin: "
+     << m_htMin;
+
+  
+
+  ss <<'\n';
+
+  return ss.str();
+}
+
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/HTConditionFastReduction.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/HTConditionFastReduction.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec67e2b76765ff91b59731fd1e98bc5a65b803f6
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/HTConditionFastReduction.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGHLTJETHYPO_HTCONDITIONFASTREDUCTION_H
+#define TRIGHLTJETHYPO_HTCONDITIONFASTREDUCTION_H
+
+/********************************************************************
+ *
+ * NAME:     HTConditionFastReduction.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigHLTJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ *********************************************************************/
+
+#include "./IConditionMT.h"
+
+#include <string>
+#include <limits>
+// #include <memory>
+
+namespace HypoJet{
+  class IJet;
+}
+
+
+class ITrigJetHypoInfoCollector;
+
+class HTConditionFastReduction: public IConditionMT{
+ public:
+
+  
+  HTConditionFastReduction(double htMin, double htMax);
+
+  
+  ~HTConditionFastReduction() override {}
+
+  bool isSatisfied(const HypoJetVector&,
+                   const std::unique_ptr<ITrigJetHypoInfoCollector>&) const override;
+
+  std::string toString() const override;
+  virtual unsigned int capacity() const override {return s_capacity;}
+
+ private:
+  
+  double m_htMin;
+  double m_htMax;
+  
+  const static  unsigned int s_capacity{std::numeric_limits<int>::max()};
+  
+  
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/IJetsMatcherMT.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/IJetsMatcherMT.h
new file mode 100644
index 0000000000000000000000000000000000000000..14e38d363cb60af5be01e958a94173098a078835
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/IJetsMatcherMT.h
@@ -0,0 +1,43 @@
+
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGHLTJETHYPO_IJETSMATCHERMT_H
+#define TRIGHLTJETHYPO_IJETSMATCHERMT_H
+/********************************************************************
+ *
+ * NAME:     IJetsMatcherMT.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigHLTJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  PABC for matching gropups of jets with Conditions.
+ *********************************************************************/
+
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/IJet.h"
+#include "./ConditionsDefsMT.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/HypoJetDefs.h"
+#include <string>
+
+class ITrigJetHypoInfoCollector;
+class xAODJetCollector;
+
+class IJetsMatcherMT{
+ public:
+
+  virtual ~IJetsMatcherMT(){}
+  virtual std::optional<bool> match(const HypoJetCIter&,
+				    const HypoJetCIter&,
+				    xAODJetCollector&,
+				    const std::unique_ptr<ITrigJetHypoInfoCollector>&,
+				    bool debug=false) const = 0;
+  
+  virtual std::string toString() const = 0;
+};
+
+#endif
+
+
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ITrigJetHypoToolNoGrouperConfig.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ITrigJetHypoToolNoGrouperConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2b5b1974a991558ae91dbc002615f4db760cbbe
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/ITrigJetHypoToolNoGrouperConfig.h
@@ -0,0 +1,53 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef TRIGHLTJETHYPO_ITRIGJETHYPOTOOLNOGROUPERCONFIG_H
+#define TRIGHLTJETHYPO_ITRIGJETHYPOTOOLNOGROUPERCONFIG_H
+
+
+#include "GaudiKernel/IAlgTool.h"
+#include "./ConditionsDefsMT.h"
+#include "./IJetsMatcherMT.h"
+#include "./ConditionFilter.h"
+
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/CleanerBridge.h"
+#include <optional>
+
+class ITrigJetHypoToolNoGrouperConfig : virtual public ::IAlgTool {
+  /** PABC (Pure Abstract Base Class) for JetHypoTool Condiguration classes.
+   TrigJetHypoToolHelperMT is a general purpose class to run
+   parts of a jet hypo. The Condiguration tools supply them
+   with the components according to the hypo scenario. */
+public:
+  DeclareInterfaceID(ITrigJetHypoToolNoGrouperConfig, 1, 0);
+  virtual ~ITrigJetHypoToolNoGrouperConfig(){};
+
+
+  /** check the input values */
+  virtual StatusCode checkVals()  const = 0;
+
+
+  /** Provide cleaner objects to sdiscard "dirty" jets before preocessing. */
+  virtual std::vector<std::shared_ptr<ICleaner>> getCleaners() const = 0;
+
+  /** return an object that tests jet group - Conditions matching */
+  virtual std::unique_ptr<IJetsMatcherMT> getMatcher() const = 0;
+
+  /** return the Conditions (which check whether a jet group satisfies one
+      or more requirements 
+  */
+   virtual std::optional<ConditionsMT> getConditions() const = 0;
+
+  /** return the ConditionFilters. These reduce the input jet collection
+      before it is passed to a Condition. Example: HT conditions sometimes
+      need and eta - Et filtered vector on which to do the Et sum.
+  */
+  
+  virtual std::vector<std::unique_ptr<ConditionFilter>>
+  getConditionFilters() const = 0;
+
+  /*( Gives the minimum number of jets the helper using this Confiog
+   class will require to pass the event. */
+  virtual std::size_t requiresNJets() const =0;
+};
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupRegister.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupRegister.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..aa873c6764c6436bf7bcb5166bea714bd63f0505
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupRegister.cxx
@@ -0,0 +1,20 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "./JetGroupRegister.h"
+
+std::size_t JetGroupRegister::record(HypoJetVector v){
+
+  std::sort(v.begin(), v.end(), HypoJetLess());
+  
+  auto it = m_reg.find(v);
+  
+  if (it == m_reg.end()){
+    auto new_ind = m_reg.size();
+    m_reg[v] = new_ind;
+    return new_ind;
+  } else {
+    return it->second;
+  }
+}
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupRegister.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupRegister.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ca0aec6c1a2911ceb30990af1f7ec071ea3bd53
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupRegister.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGHLTJETHYPO_JETGROUPREGISTER_H
+#define TRIGHLTJETHYPO_JETGROUPREGISTER_H
+
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/HypoJetDefs.h"
+
+#include <map>
+#include <algorithm>
+
+// maintain a register of ordered vectors HypoJets 
+
+struct HypoJetLess{
+  bool operator() (const HypoJetVector::value_type& l,
+		   const HypoJetVector::value_type& r) const {
+    return l.get() < r.get();
+  }
+};
+
+struct HypoJetVectorLess{
+  bool operator() (const HypoJetVector& l,
+		   const HypoJetVector& r) const {
+    
+    return std::lexicographical_compare(l.begin(),
+					l.end(),
+					r.begin(),
+					r.end(),
+					HypoJetLess());
+  }
+};
+
+
+class JetGroupRegister {
+ public:
+
+  std::size_t record(HypoJetVector v);  // copy vector
+
+ private:
+  std::map<HypoJetVector, std::size_t, HypoJetVectorLess> m_reg;
+    
+};
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/AllJetsGrouper.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/AllJetsGrouper.cxx
index fcbfca501e77312285ce97dd51b1eae48480a0a6..17a701f3e9ff70af4eaaf14ba875be3f997dc7dd 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/AllJetsGrouper.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/AllJetsGrouper.cxx
@@ -7,8 +7,8 @@
 
 AllJetsGrouper:: AllJetsGrouper(){}
 
-AllJetsGrouper:: AllJetsGrouper(const HypoJetIter& b,
-				const HypoJetIter& e): m_jets(b, e){
+AllJetsGrouper:: AllJetsGrouper(const HypoJetCIter& b,
+				const HypoJetCIter& e): m_jets(b, e){
 }
 
 AllJetsGrouper:: AllJetsGrouper(const HypoJetVector& jets): m_jets{jets}{
@@ -23,14 +23,13 @@ std::vector<HypoJetGroupVector> AllJetsGrouper::group(HypoJetIter& begin,
   return std::vector<HypoJetGroupVector>{hjgv};
 }
 
-std::optional<HypoJetGroupVector> AllJetsGrouper::next(){
+std::optional<HypoJetVector> AllJetsGrouper::next(){
   if (m_done){
-    return std::optional<HypoJetGroupVector>();
+    return std::optional<HypoJetVector>();
   }
   
-  HypoJetGroupVector hjgv{HypoJetVector(m_jets)};
   m_done = true;
-  return std::make_optional<HypoJetGroupVector>(hjgv);
+  return std::make_optional<HypoJetVector>(m_jets);
 }
 
 std::string AllJetsGrouper::getName() const {
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/CombinationsGrouper.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/CombinationsGrouper.cxx
index e05b643e00c4e575c5bb3d70fa1dfebe2b2d97d8..31a4a8e367312fe38416e5d6d17df0a693ff3f35 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/CombinationsGrouper.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/CombinationsGrouper.cxx
@@ -46,7 +46,7 @@ CombinationsGrouper::group(HypoJetIter& begin, HypoJetIter& end) const {
   return std::vector<HypoJetGroupVector>{hjgv};
 }
 
-std::optional<HypoJetGroupVector>
+std::optional<HypoJetVector>
 CombinationsGrouper::next() {
   HypoJetGroupVector hjgv;
   
@@ -56,13 +56,13 @@ CombinationsGrouper::next() {
   
   auto combs = combgen.next();
   if (combs.second == false){
-    std::optional<HypoJetGroupVector>();
+    std::optional<HypoJetVector>();
   }
   
   HypoJetVector v;
   for(auto i : combs.first){ v.push_back(*(m_jets.begin() + i));}
   
-  return std::make_optional<HypoJetGroupVector>(hjgv);
+  return std::make_optional<HypoJetVector>(v);
 }
 
 std::string CombinationsGrouper::getName() const {
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/IndexedJetsGrouper.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/IndexedJetsGrouper.cxx
index 1abd209d030ccaf7b58acdac5423e6240711ba41..c905fc57409af698e93725b38b1b06482154c114 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/IndexedJetsGrouper.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/IndexedJetsGrouper.cxx
@@ -78,7 +78,7 @@ IndexedJetsGrouper::group(HypoJetIter& begin, HypoJetIter& end) const{
 }
 
 
-std::optional<HypoJetGroupVector>
+std::optional<HypoJetVector>
 IndexedJetsGrouper::next(){
 
   // exhausts after a single group
@@ -86,14 +86,13 @@ IndexedJetsGrouper::next(){
   // check if there are enough jets find the highest (last, as the vector is
   // ordered) and see if it lies within the jet vector
 
-  if (m_done) { return std::optional<HypoJetGroupVector>(); }
-  if (m_indices.empty()) { return std::optional<HypoJetGroupVector>(); }
+  if (m_done) { return std::optional<HypoJetVector>(); }
+  if (m_indices.empty()) { return std::optional<HypoJetVector>(); }
   
-  auto hjgv = HypoJetGroupVector();
   auto last_jet_pos =  m_indices.back();
   if (m_jets.size() <= last_jet_pos) {
     m_done = true;
-    return std::optional<HypoJetGroupVector>();
+    return std::optional<HypoJetVector>();
   }
   
   // sort jets by descending Et
@@ -103,13 +102,12 @@ IndexedJetsGrouper::next(){
                      DescendingEt());
   
   // place the jets at positions in the index vector into the inner vector
-  HypoJetVector inner;
-  for (auto i : m_indices){inner.push_back(*(m_jets.begin() + i));}
+  HypoJetVector hjv;
+  for (auto i : m_indices){hjv.push_back(*(m_jets.begin() + i));}
   
   // push the inner vector into the outer vector
-  hjgv.push_back(inner);
   m_done = true;
-  return std::make_optional<HypoJetGroupVector>(hjgv);
+  return std::make_optional<HypoJetVector>(hjv);
 }
 
 
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/SingleJetGrouper.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/SingleJetGrouper.cxx
index 80441003fc073e648cd432ff0d7c48e109d87be8..54de42f78560c4de5b97cbcb7d5a0723ef670be2 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/SingleJetGrouper.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigHLTJetHypoUtils/SingleJetGrouper.cxx
@@ -7,12 +7,13 @@
 
 SingleJetGrouper::SingleJetGrouper(){}
 
-SingleJetGrouper::SingleJetGrouper(const HypoJetVector& v): m_jets(v){
+SingleJetGrouper::SingleJetGrouper(const HypoJetVector& v):
+  m_jets(v), m_size{v.size()}{
 }
 
 SingleJetGrouper::SingleJetGrouper(const HypoJetCIter& b,
 				   const HypoJetCIter& e):
-  m_jets(b, e){
+  m_jets(b, e), m_size{m_jets.size()}{
 }
 
 std::vector<HypoJetGroupVector> SingleJetGrouper::group(HypoJetIter& begin,
@@ -28,15 +29,14 @@ std::vector<HypoJetGroupVector> SingleJetGrouper::group(HypoJetIter& begin,
   return std::vector<HypoJetGroupVector>{hjgv};
 }
 
-std::optional<HypoJetGroupVector>
+std::optional<HypoJetVector>
 SingleJetGrouper::next() {
   if (m_index == m_size){
-    return std::optional<HypoJetGroupVector>();
+    return std::optional<HypoJetVector>();
   }
   
-  HypoJetGroupVector result;
-  result.push_back(HypoJetVector{m_jets[m_index++]});
-  return std::make_optional<HypoJetGroupVector>(result);
+  HypoJetVector result{m_jets[m_index++]};
+  return std::make_optional<HypoJetVector>(result);
 }
 
 std::string SingleJetGrouper::getName() const {
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_capacitychecked.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_capacitychecked.h
index 77e0dcb6c7aaf661b561d70f7cdfdfb7a3d14d82..3daf31fa69706ea59502e8944f255b60ec6529f6 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_capacitychecked.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_capacitychecked.h
@@ -37,9 +37,9 @@ public extends<AthAlgTool, ITrigJetCapacityCheckedConditionConfig> {
 
   
 
-  Gaudi::Property<std::size_t> m_chainPartInd {this,
+  Gaudi::Property<int> m_chainPartInd {this,
     "chainPartInd",
-    {0},
+    {-1},
     "identifier for chain leg - used to group jets for jet hypo clients "};
 
 
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_htfr.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_htfr.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6f0878909c7b731b1e49c1c0bb84099afe874ca6
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_htfr.cxx
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+  Instantiator for Htfr Conditions
+ */
+#include "TrigJetConditionConfig_htfr.h"
+#include "GaudiKernel/StatusCode.h"
+#include "./HTConditionFastReduction.h"
+#include "./ArgStrToDouble.h"
+
+TrigJetConditionConfig_htfr::TrigJetConditionConfig_htfr(const std::string& type,
+                                                 const std::string& name,
+                                                 const IInterface* parent) :
+  base_class(type, name, parent){
+
+}
+
+
+StatusCode TrigJetConditionConfig_htfr::initialize() {
+  CHECK(checkVals());
+
+  return StatusCode::SUCCESS;
+}
+
+
+ConditionMT TrigJetConditionConfig_htfr::getCondition() const {
+  auto a2d = ArgStrToDouble();
+  return std::make_unique<HTConditionFastReduction>(a2d(m_min), a2d(m_max));
+}
+
+
+StatusCode TrigJetConditionConfig_htfr::checkVals() const {
+    auto a2d = ArgStrToDouble();
+  if (a2d(m_min) > a2d(m_max)){
+    ATH_MSG_ERROR("htMin > htMax");
+    return StatusCode::FAILURE;
+  }
+  return StatusCode::SUCCESS;
+}
+
+bool TrigJetConditionConfig_htfr::addToCapacity(std::size_t) {
+  return false;
+}
+
+std::size_t TrigJetConditionConfig_htfr::capacity() const {
+  return getCondition()->capacity();
+}
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_htfr.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_htfr.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f2f9ec067943a5c9819a24c7f47f766fd576e87
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetConditionConfig_htfr.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETCONDITIONCONFIG_HTFR_H
+#define TRIGJETCONDITIONCONFIG_HTFR_H
+
+/*
+Condiguration AlgTool for ht conditions to be run in FastReduction
+PS 
+*/
+
+#include "ITrigJetConditionConfig.h"
+#include "./ConditionsDefsMT.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
+
+class TrigJetConditionConfig_htfr:
+public extends<AthAlgTool, ITrigJetConditionConfig> {
+
+ public:
+  
+  TrigJetConditionConfig_htfr(const std::string& type,
+			      const std::string& name,
+			      const IInterface* parent);
+
+  virtual StatusCode initialize() override;
+  virtual ConditionMT getCondition() const override;
+
+  virtual bool addToCapacity(std::size_t) override;
+  virtual std::size_t capacity() const override;
+
+ private:
+
+
+  Gaudi::Property<std::string>
+    m_min{this, "min", {}, "min HT"};
+
+  Gaudi::Property<std::string>
+    m_max{this, "max", {}, "max HT"};
+
+  StatusCode checkVals()  const;
+};
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.cxx
index c819ee3580b170c7d76d5fd5fe25f403a6890a10..eb8b9b40796aa7dd45122ea4ef6325f2c4024a44 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.cxx
@@ -9,12 +9,12 @@
 
 #include "./conditionsFactoryMT.h"
 
-#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/SingleJetGrouper.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/xAODJetAsIJetFactory.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoHelper2.h"
-#include "./groupsMatcherFactoryMT.h"
 #include "./CapacityCheckedCondition.h"
+#include "./FastReductionMatcher.h"
+#include "./Tree.h"
 
 #include "TrigCompositeUtils/TrigCompositeUtils.h"
 
@@ -134,29 +134,49 @@ TrigJetHypoToolConfig_fastreduction::getConditions() const {
   return std::make_optional<ConditionsMT>(std::move(conditions));
 }
 
+
+std::vector<std::unique_ptr<ConditionFilter>>
+TrigJetHypoToolConfig_fastreduction::getConditionFilters() const {
+
+  auto filters = std::vector<std::unique_ptr<ConditionFilter>>();
+  
+  for(const auto& cm : m_filtConditionMakers){
+    ConditionPtrs filterConditions;  // will contain a single Condition
+    filterConditions.push_back(std::move(cm->getCapacityCheckedCondition()));
+    auto cf = std::make_unique<ConditionFilter>(filterConditions);
+    filters.push_back(std::move(cf));
+  }
+  
+  return filters;
+}
+
 // following function not used for treeless hypos
 std::size_t
 TrigJetHypoToolConfig_fastreduction::requiresNJets() const {
   return 0;
 }
 
- 
-std::unique_ptr<IJetGrouper>
-TrigJetHypoToolConfig_fastreduction::getJetGrouper() const {
-  return std::make_unique<SingleJetGrouper>();
-}
 
-std::unique_ptr<IGroupsMatcherMT>
+std::unique_ptr<IJetsMatcherMT>
 TrigJetHypoToolConfig_fastreduction::getMatcher () const {
 
   auto opt_conds = getCapacityCheckedConditions();
 
   if(!opt_conds.has_value()){
-    return std::unique_ptr<IGroupsMatcherMT>(nullptr);
+    return std::unique_ptr<IJetsMatcherMT>(nullptr);
   }
 
-  return groupsMatcherFactoryMT_FastReduction(std::move(*opt_conds),
-					      m_treeVec);
+  auto matcher =  std::unique_ptr<IJetsMatcherMT>();
+  //  matcher.reset(new FastReductionMatcher(std::move(*opt_conds),
+  //					 Tree(m_treeVec)));
+
+  auto conditions = std::move(*opt_conds);
+  auto filters = getConditionFilters();
+  auto fpm = new FastReductionMatcher(conditions,
+				      filters,
+				      Tree(m_treeVec));
+  matcher.reset(fpm);
+  return matcher;
 }
 
 StatusCode TrigJetHypoToolConfig_fastreduction::checkVals() const {
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.h
index 26a33fe89d6c5d78534ddfbd548e17c318e5e9e3..91622b23b5508e43bbb39d322e47f981670e0117 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolConfig_fastreduction.h
@@ -13,22 +13,23 @@
  *********************************************************************/
 
 
-#include "ITrigJetHypoToolConfig.h"
+#include "ITrigJetHypoToolNoGrouperConfig.h"
 #include "./CapacityCheckedConditionsDefs.h"
 #include "TrigCompositeUtils/HLTIdentifier.h"
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "TrigCompositeUtils/TrigCompositeUtils.h"
 #include "AthenaMonitoringKernel/GenericMonitoringTool.h"
 
+#include "./IJetsMatcherMT.h"
 #include "./ConditionsDefsMT.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
-#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/IJetGrouper.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/CleanerBridge.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
 #include "./ITrigJetCapacityCheckedConditionConfig.h"
+#include "./ConditionFilter.h"
 
 class TrigJetHypoToolConfig_fastreduction:
-public extends<AthAlgTool, ITrigJetHypoToolConfig> {
+public extends<AthAlgTool, ITrigJetHypoToolNoGrouperConfig> {
 
  public:
   
@@ -39,17 +40,24 @@ public extends<AthAlgTool, ITrigJetHypoToolConfig> {
 
   virtual StatusCode initialize() override;
   virtual std::vector<std::shared_ptr<ICleaner>> getCleaners() const override;
-  virtual std::unique_ptr<IJetGrouper> getJetGrouper() const override;
-  virtual std::unique_ptr<IGroupsMatcherMT> getMatcher() const override;
+  virtual std::unique_ptr<IJetsMatcherMT> getMatcher() const override;
   virtual std::optional<ConditionsMT> getConditions() const override;
+
+  virtual std::vector<std::unique_ptr<ConditionFilter>>
+  getConditionFilters() const override;
+
   virtual std::size_t requiresNJets() const override;
   virtual StatusCode checkVals() const override;
 
 
  private:
   ToolHandleArray<ITrigJetCapacityCheckedConditionConfig> m_conditionMakers{
-    this, "conditionMakers", {}, "hypo tree node to conditiionMaker map"};
+    this, "conditionMakers", {}, "hypo tree Condition builder AlgTools"};
 
+  ToolHandleArray<ITrigJetCapacityCheckedConditionConfig> m_filtConditionMakers{
+    this, "filtConditionsMakers", {},
+    "hypo tree Condition builder AlgTools for Condition filters"};
+  
   Gaudi::Property<std::vector<std::size_t>> m_treeVec{
     this, "treeVector", {}, "integer sequence representation of jet hypo tree"};
 
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolHelperNoGrouper.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolHelperNoGrouper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b7e7a202588907459fb220ebbc41c72a6cc51366
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolHelperNoGrouper.cxx
@@ -0,0 +1,134 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "./TrigJetHypoToolHelperNoGrouper.h"
+#include "./ITrigJetHypoInfoCollector.h"
+#include "./xAODJetCollector.h"
+#include "./JetTrigTimer.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/xAODJetAsIJet.h"  // TLorentzVec
+#include "./nodeIDPrinter.h"
+#include "./DebugInfoCollector.h"
+#include <algorithm>
+#include <sstream>
+
+TrigJetHypoToolHelperNoGrouper::TrigJetHypoToolHelperNoGrouper(const std::string& type,
+							       const std::string& name,
+							       const IInterface* parent) :
+  base_class(type, name, parent){
+}
+
+StatusCode TrigJetHypoToolHelperNoGrouper::initialize() {
+
+  m_matcher = m_config->getMatcher();
+  if(!m_matcher){
+    ATH_MSG_ERROR("Error setting matcher");
+    return StatusCode::FAILURE;
+  }
+		  
+  return StatusCode::SUCCESS;
+}
+
+void
+TrigJetHypoToolHelperNoGrouper::collectData(const std::string& exetime,
+					    const std::unique_ptr<ITrigJetHypoInfoCollector>& collector,
+					    const std::optional<bool>& pass) const {
+  if(!collector){return;}
+  auto helperInfo = nodeIDPrinter("TrigJetHypoToolHelperNoGrouper",
+                                  m_nodeID,
+                                  m_parentNodeID,
+                                  pass,
+                                  exetime
+                                  );
+  
+  collector->collect(name(), helperInfo);
+}
+
+
+bool
+TrigJetHypoToolHelperNoGrouper::pass(HypoJetVector& jets,
+				     xAODJetCollector& jetCollector,
+				     const std::unique_ptr<ITrigJetHypoInfoCollector>& collector) const {
+  
+  if(collector){
+    std::stringstream ss;
+    ss <<  "No of jets " + std::to_string(jets.size()) + '\n';
+    ss << jets; 
+    collector->collect(name(), ss.str());
+  }
+
+  JetTrigTimer timer;
+  timer.start();
+  
+  if(jets.empty()){   
+    timer.stop();
+    bool pass = false;
+    collectData(timer.readAndReset(), collector, pass);
+    return pass;
+  }
+
+  HypoJetIter jets_begin = jets.begin(); 
+  HypoJetIter jets_end = jets.end(); 
+  for(auto cleaner: m_cleaners){
+    jets_end = std::partition(jets_begin,
+			      jets_end,
+			      [cleaner](const pHypoJet& j){
+				return cleaner->select(j);}
+			      );
+  }
+  
+  auto pass = m_matcher->match(jets_begin,
+			       jets_end,
+			       jetCollector,
+			       collector);
+  
+  timer.stop();
+  
+  collectData(timer.readAndReset(), collector, pass);
+  
+  if(!pass.has_value()){
+    ATH_MSG_ERROR("Matcher cannot determine result. Config error?");
+    return false;
+  }
+    
+  return *pass;
+}
+
+std::string TrigJetHypoToolHelperNoGrouper::toString() const {
+  
+  
+  std::stringstream ss;
+  ss << nodeIDPrinter(name(),
+                      m_nodeID,
+                      m_parentNodeID);
+  
+  
+  ss << "Cleaners:\n No of cleaners: "  << m_cleaners.size() << '\n';
+  
+  for(auto cleaner : m_cleaners) {
+    ss << cleaner->toString() 
+       << '\n';
+  }
+  
+  ss << "\nMatcher:\n";
+  ss << m_matcher -> toString();
+  
+  return ss.str();
+}
+
+
+StatusCode
+TrigJetHypoToolHelperNoGrouper::getDescription(ITrigJetHypoInfoCollector& c) const {
+  c.collect(name(), toString());
+  return StatusCode::SUCCESS;
+}
+
+
+std::size_t TrigJetHypoToolHelperNoGrouper::requiresNJets() const {
+  return m_config->requiresNJets();
+}
+
+
+
+
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolHelperNoGrouper.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolHelperNoGrouper.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4e58f9a0ac0702985102e333c0027c1fc3f43c2
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolHelperNoGrouper.h
@@ -0,0 +1,87 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGHLTJETHYPO_TRIGJETHYPOHELPERNOGROUPER_H
+#define TRIGHLTJETHYPO_TRIGJETHYPOHELPERNOGROUPER_H
+
+/**
+ * A configurable helper class to implement Jet Trigger algorithms.
+ * Initial jet removal from incomming container is done using the ICleaner predicates.
+ * The surviving jets are grouped into subsets by the IJetGroup object.
+ *
+ * The IMatcher objector owns a set of Conditions objects. 
+ * The Matcher determines 
+ * whether the container of jet groups satisfies the Conditions. If so,
+ * the event passes, otherwise it fails.
+ *
+ */
+
+#include <vector>
+#include <memory>
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/ICleanerTool.h"
+#include "./IJetsMatcherMT.h"
+#include "./ConditionsDefsMT.h"
+
+#include "TrigHLTJetHypo/ITrigJetHypoToolHelperMT.h"
+#include "ITrigJetHypoToolNoGrouperConfig.h"
+
+class ITrigJetHypoInfoCollector;
+class xAODJetCollector;
+
+class TrigJetHypoToolHelperNoGrouper:
+public extends<AthAlgTool, ITrigJetHypoToolHelperMT> {
+
+ public:
+  TrigJetHypoToolHelperNoGrouper(const std::string& type,
+                          const std::string& name,
+                          const IInterface* parent);
+
+  StatusCode initialize() override;
+  virtual bool
+
+    // pass - tests wethewr a jet collection passes cuts, and collects
+    // information about the decision.
+    pass(HypoJetVector&,
+	 xAODJetCollector&,
+	 const std::unique_ptr<ITrigJetHypoInfoCollector>&) const override;
+  
+  virtual std::size_t requiresNJets() const override;
+  
+  virtual StatusCode getDescription(ITrigJetHypoInfoCollector&) const override;
+
+ private:
+
+  // Object that matches jet groups with Conditions
+  std::unique_ptr<IJetsMatcherMT> m_matcher;
+
+  // Bridge objects to ICleaner predicate function objects to allow polymorphic
+  // pointers to be used with the STL (pass by value).
+  ToolHandleArray<ICleanerTool> m_cleaners;
+
+  ///////////////////////////////
+
+ // Used to generate helper objects foe TrigHLTJetHelper
+ // from user supplied values
+ ToolHandle<ITrigJetHypoToolNoGrouperConfig> m_config {
+   this, "HypoConfigurer", {}, "Configurer to set up TrigHLTJetHypoHelper2"}; 
+
+ Gaudi::Property<int>
+  m_parentNodeID {this, "parent_id", {0}, "hypo tool tree parent node id"};
+
+Gaudi::Property<int>
+  m_nodeID {this, "node_id", {0}, "hypo tool tree node id"};
+
+Gaudi::Property<bool>
+  m_debug {this, "debug", false, "instantantiate helpers with this debug flag"};
+
+
+ void collectData(const std::string& exetime,
+                  const std::unique_ptr<ITrigJetHypoInfoCollector>&,
+                  const std::optional<bool>& pass) const;
+
+ virtual std::string toString() const override;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolMT.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolMT.cxx
index d573062d7aae581e9e1356d5d313398a4319eac6..05e2bf6d986d15330f14ea7b930e1c8463516803 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolMT.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoToolMT.cxx
@@ -42,17 +42,18 @@ TrigJetHypoToolMT::~TrigJetHypoToolMT(){
 }
 
 StatusCode TrigJetHypoToolMT::initialize(){
-  DebugInfoCollector collector(name());
-  CHECK(m_helper->getDescription(collector));
-  auto s = collector.toString();
-  
-  for(const auto& l : lineSplitter(s)){
-    ATH_MSG_INFO(l);
-  }
-  
+
   if (m_visitDebug){
-    collector.write();
+
+    DebugInfoCollector collector(name());
+    CHECK(m_helper->getDescription(collector));
+    auto s = collector.toString();
+  
+    for(const auto& l : lineSplitter(s)){
+      ATH_MSG_INFO(l);
+    }
   }
+
   return StatusCode::SUCCESS;
 }
 
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/components/TrigHLTJetHypo_entries.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/components/TrigHLTJetHypo_entries.cxx
index 2ef7d1045234acf52559225a1bf2dc2a29c6fe95..4974748f7260026bcd956dea9e4ad01c8ba1b568 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/components/TrigHLTJetHypo_entries.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/components/TrigHLTJetHypo_entries.cxx
@@ -20,6 +20,7 @@
 #include "../TrigJetConditionConfig_signed_eta.h"
 #include "../TrigJetConditionConfig_et.h"
 #include "../TrigJetConditionConfig_ht.h"
+#include "../TrigJetConditionConfig_htfr.h"
 #include "../TrigJetConditionConfig_dijet_mass.h"
 #include "../TrigJetConditionConfig_dijet_dphi.h"
 #include "../TrigJetConditionConfig_dijet_deta.h"
@@ -34,6 +35,7 @@
 //
 #include "../TrigJetHypoToolMT.h"
 #include "../TrigJetHypoToolHelperMT.h"
+#include "../TrigJetHypoToolHelperNoGrouper.h"
 #include "../TrigJetTLAHypoAlgMT.h"
 #include "../TrigJetTLAHypoToolMT.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/BasicCleanerTool.h"
@@ -64,6 +66,7 @@ DECLARE_COMPONENT(TrigJetConditionConfig_signed_eta)
 DECLARE_COMPONENT(TrigJetConditionConfig_abs_eta)
 DECLARE_COMPONENT(TrigJetConditionConfig_et)
 DECLARE_COMPONENT(TrigJetConditionConfig_ht)
+DECLARE_COMPONENT(TrigJetConditionConfig_htfr)
 DECLARE_COMPONENT(TrigJetConditionConfig_dijet_mass)
 DECLARE_COMPONENT(TrigJetConditionConfig_dijet_deta)
 DECLARE_COMPONENT(TrigJetConditionConfig_dijet_dphi)
@@ -80,6 +83,7 @@ DECLARE_COMPONENT(TrigJetHypoToolMT)
 DECLARE_COMPONENT(TrigJetTLAHypoAlgMT)
 DECLARE_COMPONENT(TrigJetTLAHypoToolMT)
 DECLARE_COMPONENT(TrigJetHypoToolHelperMT)
+DECLARE_COMPONENT(TrigJetHypoToolHelperNoGrouper)
 
 DECLARE_COMPONENT(BasicCleanerTool)
 DECLARE_COMPONENT(AntiCleanerTool)
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.cxx
index b34ebadffb584129d617aa6e72c7055113d2bee4..c7baef98e498f0081b9b07af021e768b1e972e8b 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.cxx
@@ -17,17 +17,6 @@ groupsMatcherFactoryMT_SingleCondition (ConditionsMT&& conditions){
 }
 
 
-std::unique_ptr<IGroupsMatcherMT> 
-groupsMatcherFactoryMT_FastReduction (ConditionPtrs&& conditions,
-				      const std::vector<std::size_t>& treeVec){
-  
-  if (conditions.size() == 1) {
-    return std::make_unique<SingleConditionMatcherMT>(std::move(conditions[0]));
-  } else {
-    return std::make_unique<FastReductionMatcher>(std::move(conditions),
-						  treeVec);
-  } 
-}
 
 
 
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.h
index b91b74c3df2786e801e0cf1f1c410097ed48a22b..cde9b776796e6d9c13459c6fc01563578aff7720 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/groupsMatcherFactoryMT.h
@@ -16,7 +16,4 @@ groupsMatcherFactoryMT_SingleCondition(ConditionsMT&&);
 std::unique_ptr<IGroupsMatcherMT>
 groupsMatcherFactoryMT_MaxBipartite(ConditionsMT&&);
 
-std::unique_ptr<IGroupsMatcherMT>
-groupsMatcherFactoryMT_FastReduction(ConditionPtrs&&,
-				     const std::vector<std::size_t>& treeVec);
 #endif
diff --git a/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref b/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref
index 3d09ef19cbbe49620dbe4e2ff277e36c281d67cd..201a8038ae0458148bd77cdd83b34d8300d47654 100644
--- a/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref
+++ b/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_v1Dev_build.ref
@@ -1469,7 +1469,7 @@ HLT_j0_aggSEP500htSEP30etSEP0eta320_L1J20:
   stepCounts:
     0: 1
   stepFeatures:
-    0: 50
+    0: 5
 HLT_j0_perf_L1J12_EMPTY:
   eventCount: 0
 HLT_j0_vbenfSEP30etSEP34mass35SEP50fbet_L1J20: