diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypo.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypo.h
index 26baf88ccee9d2a7b0f64ec6ccd355ca47682742..3dab2d53593a5c61ef0e3d8cee25f377b3810b83 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypo.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypo.h
@@ -15,12 +15,12 @@
  *
  *********************************************************************/
 
-// #include <memory>
 #include "TrigInterfaces/HypoAlgo.h"
 #include "TrigTimeAlgs/TrigTimerSvc.h"
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcherFactory.h"
 
 class TriggerElement;
+class CleanerMatcher;
 
 class TrigHLTJetHypo : public HLT::HypoAlgo {
 
@@ -40,11 +40,12 @@ class TrigHLTJetHypo : public HLT::HypoAlgo {
                      const xAOD::JetContainer*&);
   void bumpCounters(bool, int);
   void monitorLeadingJet(const xAOD::Jet* jet);
-  void writeDebug(bool, int,
+  void writeDebug(bool,
                   const std::pair<JetCIter, JetCIter>&,
-                  const std::pair<JetCIter, JetCIter>& ) const;
+                  const std::pair<JetCIter, JetCIter>&,
+		  const CleanerMatcher&) const;
 
-  CleanerMatcher getCleanerMatcher() const;
+  // CleanerMatcher getCleanerMatcher() const;
   
   HLT::ErrorCode 
     markAndStorePassingJets(const CleanerMatcher&,
@@ -57,7 +58,17 @@ class TrigHLTJetHypo : public HLT::HypoAlgo {
   std::vector<double> m_EtThresholds;
   std::vector<double> m_etaMins;
   std::vector<double> m_etaMaxs;
-  Conditions m_conditions;
+
+  // vector of indices find ofssets into the jet vector,
+  // and other Condition variables used for TLA style hypos.
+  std::vector<unsigned int> m_jetvec_indices;
+  std::vector<double> m_ystarMins;
+  std::vector<double> m_ystarMaxs;
+  std::vector<double> m_massMins;
+  std::vector<double> m_massMaxs;
+
+  // Conditions m_conditions;
+  std::shared_ptr<CleanerMatcherFactory> m_cleanerMatcherFactory;
 
   int m_accepted;
   int m_rejected;
@@ -82,7 +93,7 @@ class TrigHLTJetHypo : public HLT::HypoAlgo {
   
   std::string m_cleaningAlg;  // determines cleaner obj
   std::string m_matchingAlg;  // determines matcher obj;
-  
+
   //basic cleaning
   float m_n90Threshold;
   float m_presamplerThreshold;
@@ -111,6 +122,7 @@ class TrigHLTJetHypo : public HLT::HypoAlgo {
   float m_hecqLlpThreshold;
   float m_avLarQFLlpThreshold;
 
+  // std::shared_ptr<ICleaner> m_cleaner;
 
   // Timing:
 
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerBridge.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerBridge.h
new file mode 100644
index 0000000000000000000000000000000000000000..dee47b654b5f553255e3cb2644c2fd2d81f1cc4d
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerBridge.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CLEANERBRIDGE_H
+#define TRIGJETHYPO_CLEANERBRIDGE_H
+#define TRIGJETHYPO_TRIGHLTJETHYPOUTILS_H
+/********************************************************************
+ *
+ * NAME:     CleanerBridge.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include <string>
+#include <memory>
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
+
+class CleanerBridge{
+  // Bridge object: convert polymorphic pointer to monomorthic class
+  // can be passed to STL algs.
+ public:
+ CleanerBridge(const std::shared_ptr<ICleaner>& cleaner):
+  m_pCleaner(cleaner){}
+
+  bool operator()(const xAOD::Jet* jet) const{
+    return m_pCleaner -> operator()(jet);
+  }
+
+  std::string toString() const {
+    return m_pCleaner -> toString();
+  }
+
+ private:
+  std::shared_ptr<ICleaner> m_pCleaner;
+};
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..4253f3ae7ac9969c3afe4db83d8c610d8618b012
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h
@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CLEANERFACTORY_H
+#define TRIGJETHYPO_CLEANERFACTORY_H
+
+
+// ********************************************************************
+//
+// NAME:     cleanerFactory.h
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:  P Sherwood
+//
+// ********************************************************************
+//
+
+#include <memory>
+#include <string>
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
+class CleanerFactory{
+ public:
+  CleanerFactory (double, 
+		  double, 
+		  double,
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double, 
+		  double,
+		  const std::string& key);
+
+  std::shared_ptr<ICleaner> make() const noexcept;
+  
+ private:
+
+  //run 1 cleaning
+  double m_n90Threshold;
+  double m_presamplerThreshold;
+  double m_negativeEThreshold;
+  
+  //loose cleaning
+  double m_fSampMaxLooseThreshold;
+  double m_etaLooseThreshold;
+  double m_emfLowLooseThreshold;
+  double m_emfHighLooseThreshold;
+  double m_hecfLooseThreshold;
+
+  //tight cleaning
+  double m_fSampMaxTightThreshold;
+  double m_etaTightThreshold;
+  double m_emfLowTightThreshold;
+  double m_emfHighTightThreshold;
+  double m_hecfTightThreshold;
+
+  //long-lived particle cleaning
+  double m_fSampMaxLlpThreshold;
+  double m_negELlpThreshold;
+  double m_hecfLlpThreshold;
+  double m_hecqLlpThreshold;
+  double m_avLarQFLlpThreshold;
+
+  void make_();
+  std::shared_ptr<ICleaner> m_cleaner;
+
+  std::string m_name;
+};
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcher.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..1115c9e1c5c58112ae839b6cc71dadf669d2184a
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcher.h
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CLEANERMATCHER_H
+#define TRIGJETHYPO_CLEANERMATCHER_H
+/********************************************************************
+ *
+ * NAME:     CleanerMatcher.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include <string>
+#include <memory>
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerBridge.h"
+
+class CleanerMatcher{
+  /*
+    Object that takes a jet cleaner and a matcher.
+    A matcher checks whether there is a subset of the jets
+    that fulfill the hypo conditions.
+  */
+ public:
+ CleanerMatcher(const std::shared_ptr<ICleaner>& cleaner,
+                const std::shared_ptr<IMatcher>& matcher):
+  m_cleaner(CleanerBridge(cleaner)), m_matcher(matcher){}
+  
+  void process(JetIter begin, JetIter end) {
+    JetIter cleanEnd = std::partition(begin, end, m_cleaner);
+    m_matcher->match(begin, cleanEnd);
+  }
+
+  bool pass() const{return m_matcher->pass();}
+
+  std::pair<JetCIter, JetCIter> 
+  passedJetIters() const {return m_matcher->passed_iters();}
+
+  std::pair<JetCIter, JetCIter> 
+  failedJetIters() const {return m_matcher->failed_iters();}
+
+  std::string toString() const{
+    return  "CleanerMatcher start\n" + 
+      m_cleaner.toString() + 
+      '\n' + m_matcher->toString() +
+      "CleanerMatcher end";
+  }
+
+  const Conditions& getConditions() const {  //for debug print eg
+    return m_matcher->getConditions();
+  }
+
+private:
+  CleanerBridge m_cleaner;
+  std::shared_ptr<IMatcher> m_matcher;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcherFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcherFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef78864e142c6aaf9f0240f78a7468594d19947b
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcherFactory.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CLEANERMATCHERFACTORY_H
+#define TRIGJETHYPO_CLEANERMATCHERFACTORY_H
+/********************************************************************
+ *
+ * NAME:     CleanerMatcherFactory.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include <string>
+#include <memory>
+#include "TrigJetHypo/TrigHLTJetHypoUtils/matcherFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcher.h"
+
+// class CleanerMatcher;
+
+class CleanerMatcherFactory {
+ public: 
+  CleanerMatcherFactory(const CleanerFactory& cf,
+			const std::shared_ptr<IMatcherFactory>& mf);
+
+  CleanerMatcher make() const;
+ 
+ private:
+  CleanerFactory m_cleanerFactory;
+  std::shared_ptr<IMatcherFactory>  m_matcherFactory;
+};
+
+#endif
+
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionBridge.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionBridge.h
new file mode 100644
index 0000000000000000000000000000000000000000..5728a2da916cfbdd7d8008d2d7c7728fbc003de9
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionBridge.h
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CONDITIONBRIDGE_H
+#define TRIGJETHYPO_CONDITIONBRIDGE_H
+/********************************************************************
+ *
+ * NAME:     ConditionBridge.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICondition.h"
+#include <string>
+#include <memory>
+#include <ostream>
+
+class ConditionBridge{
+  // Bridge object: convert polymorphic pointer to monomorthic class
+  // can be passed to STL algs.
+ public:
+ ConditionBridge(std::shared_ptr<ICondition>& condition):
+  m_pCondition(condition){}
+  
+  bool isSatisfied(const std::vector<const xAOD::IParticle*>& ips) const{
+    return m_pCondition -> isSatisfied(ips);
+  }
+  
+  bool isSatisfied(const xAOD::IParticle* ip) const {
+    return m_pCondition -> isSatisfied(ip);
+  }
+  
+  std::string toString() const noexcept{
+    return m_pCondition -> toString();
+  }
+
+  double orderingParameter() const noexcept{
+    return m_pCondition -> orderingParameter();
+  }
+
+ private:
+  std::shared_ptr<ICondition> m_pCondition;
+};
+
+/*
+std::ostream& operator<< (std::ostream& os, const ConditionBridge& c){
+  return os << c.toString() <<'\n';
+}
+*/
+
+// Define a class to hold etaMin, etaMax and threshold (Et in MeV)
+// that jets will be matched against
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h
new file mode 100644
index 0000000000000000000000000000000000000000..f8741581aa88162422e355b9c92ac3e2f971fb01
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CONDITIONSDEFS_H
+#define TRIGJETHYPO_CONDITIONSDEFS_H
+/********************************************************************
+ *
+ * NAME:     ConditionsDefs.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include <string>
+#include <memory>
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionBridge.h"
+
+using Conditions = std::vector<ConditionBridge>;
+using ConditionsIter = Conditions::iterator;
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionsSorter.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionsSorter.h
new file mode 100644
index 0000000000000000000000000000000000000000..78189ba66e7454a1f1e1d534ee41c326017b7a2c
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ConditionsSorter.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CONDITIONSSORTER_H
+#define TRIGJETHYPO_CONDITIONSSORTER_H
+
+/********************************************************************
+ *
+ * NAME:     ConditionsSorter.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+class ConditionBridge;
+
+struct ConditionsSorter{
+  bool operator()(const ConditionBridge& l, const ConditionBridge& r);
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/EtaEtCondition.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/EtaEtCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..4db93036dc263cff920b0972bc65c699029b5ee4
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/EtaEtCondition.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_ETAETCONDITION_H
+#define TRIGJETHYPO_ETAETCONDITION_H
+
+/********************************************************************
+ *
+ * NAME:     TrigHLTJetHypo.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include <string>
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICondition.h"
+
+
+class EtaEtCondition: public ICondition{
+ public:
+  EtaEtCondition(double etaMin, double etaMax, double threshold);
+  ~EtaEtCondition() override {}
+
+  bool isSatisfied(const std::vector<const xAOD::IParticle*>&) const override;
+
+  bool isSatisfied(const xAOD::IParticle*) const override;
+
+  double orderingParameter() const noexcept override;
+
+  std::string toString() const noexcept override;
+
+ private:
+  double m_etaMin;
+  double m_etaMax;
+  double m_threshold;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd6df800b54a5ca49cb9e29f577d129a616af5eb
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_ICLEANER_H
+#define TRIGJETHYPO_ICLEANER_H
+/********************************************************************
+ *
+ * NAME:     ICleaner.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include <string>
+
+class ICleaner{
+ public:
+  // Abstract interface used by a factory function
+  virtual bool operator()(const xAOD::Jet* jet) const = 0;
+  virtual std::string toString() const noexcept = 0;
+  virtual std::string getName() const noexcept= 0;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ICondition.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ICondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..aac73b476855a18ba03f01f5e5a76333cc17b464
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/ICondition.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_ICONDITION_H
+#define TRIGJETHYPO_ICONDITION_H
+/********************************************************************
+ *
+ * NAME:     ICondition.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include <string>
+
+
+class ICondition {
+ public:
+  virtual ~ICondition(){}
+  virtual bool 
+    isSatisfied(const std::vector<const xAOD::IParticle*>&) const = 0;
+  virtual bool isSatisfied(const xAOD::IParticle*) const = 0;
+  virtual std::string toString() const noexcept = 0;
+  virtual double orderingParameter() const noexcept = 0;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e4c2df4439fd43065fdb0170d1a1640e9212018
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_IMATCHER_H
+#define TRIGJETHYPO_IMATCHER_H
+/********************************************************************
+ *
+ * NAME:     IMatcher.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
+#include <string>
+#include <memory>
+
+using JetVector = std::vector<const xAOD::Jet*>;
+using JetIter = JetVector::iterator;
+using JetCIter = JetVector::const_iterator;
+
+
+
+class IMatcher{
+ public:
+// Abstract interface used by a factory function
+  virtual void match(JetIter b, JetIter e) = 0;
+  virtual bool pass() const = 0;
+  virtual std::pair<JetCIter, JetCIter> passed_iters() const = 0;
+  virtual std::pair<JetCIter, JetCIter> failed_iters() const = 0;
+  virtual const Conditions& getConditions() const noexcept = 0;
+  virtual std::string toString() const noexcept = 0;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/IMatcherFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/IMatcherFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9e66a0163e5f3c256fde431558e8d03baab6477
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/IMatcherFactory.h
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_IMATCHERFACTORY_H
+#define TRIGJETHYPO_IMATCHERFACTORY_H
+/********************************************************************
+ *
+ * NAME:     MactcherFactory.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h"
+#include <memory>
+
+class IMatcherFactory{
+ public:
+  virtual  std::shared_ptr<IMatcher> make() const =0;
+  virtual  ~IMatcherFactory(){};
+};
+
+#endif
+
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/Matcher.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/Matcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..718112400ed19f3ab0e471874412c43575b88cea
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/Matcher.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_MATCHER_H
+#define TRIGJETHYPO_MATCHER_H
+
+
+// ********************************************************************
+//
+// NAME:     MatcherImp.h
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:  P Sherwood
+//
+// ********************************************************************
+//
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h"
+
+class Matcher: virtual public IMatcher {
+ public:
+  Matcher(const std::string& name);
+  std::string toString() const noexcept override;
+ private:
+  std::string m_name;
+};
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/MaximumBipartiteMatcher.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/MaximumBipartiteMatcher.h
similarity index 70%
rename from Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/MaximumBipartiteMatcher.h
rename to Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/MaximumBipartiteMatcher.h
index b325302665bafeb5dbf78ad796dfde475a822f72..59d17bd01ad9416d2056423556bd6de3480ca7da 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/MaximumBipartiteMatcher.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/MaximumBipartiteMatcher.h
@@ -17,12 +17,14 @@
 //
 
 #include <utility>  // std::pair
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // IMatcher...
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/Matcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
 #include "xAODJet/Jet.h"
 
 using JetSet = std::set<const xAOD::Jet*>;
 
-class MaximumBipartiteMatcher: public IMatcher {
+class MaximumBipartiteMatcher: virtual public IMatcher, private Matcher {
 
   /* Used to find jets pass multithreshold,
      possibly overlapping eta regions
@@ -31,12 +33,14 @@ class MaximumBipartiteMatcher: public IMatcher {
      See Algorithms, Sedgewick and Wayne 4th edition */
 
 public:
-  MaximumBipartiteMatcher(const Conditions& cs);
+  MaximumBipartiteMatcher(const Conditions& cs, const std::string& name);
+  ~MaximumBipartiteMatcher(){}
   void match(JetIter b, JetIter e) override;
   bool pass() const  override;
   std::pair<JetCIter, JetCIter> passed_iters() const override;
   std::pair<JetCIter, JetCIter> failed_iters() const override;
-
+  std::string toString() const noexcept override;
+  const Conditions& getConditions() const noexcept override;
 private:
   Conditions m_conditions;
   bool m_pass;
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/OrderedCollectionsMatcher.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/OrderedCollectionsMatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..adb952397839f8261f916be1c0d87d0c452a15cd
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/OrderedCollectionsMatcher.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_ORDEREDCOLLECTIONSMATCHER_H
+#define TRIGJETHYPO_ORDEREDCOLLECTIONSMATCHER_H
+
+
+// ********************************************************************
+//
+// NAME:     OrderedCollectionsMatcher.h
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:  P Sherwood
+//
+// ********************************************************************
+//
+
+#include <utility>
+
+#include "xAODJet/Jet.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/Matcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICondition.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsSorter.h"
+
+class OrderedCollectionsMatcher: virtual public IMatcher, private Matcher{
+  /* Match by ordering all jets in the single eta region
+     in Et, pair of with the Conditions objects also ordered
+     in Et. Event pass if the Et of each jet >= to the threshold
+     of the paired Condition.
+   */
+public:
+  ConditionsSorter sorterPred;
+  OrderedCollectionsMatcher(const Conditions& cs, const std::string& name);
+  ~OrderedCollectionsMatcher(){}
+  void match(JetIter b, JetIter e) override;
+  bool pass() const override;
+  std::pair<JetCIter, JetCIter> passed_iters() const override;
+  std::pair<JetCIter, JetCIter> failed_iters() const override;
+  std::string toString() const noexcept override;
+  const Conditions& getConditions() const noexcept override;
+
+private:
+  Conditions m_conditions;
+  bool m_pass;
+
+  JetVector m_passed_jets;
+  JetVector m_failed_jets;
+  
+  std::string m_name;
+};
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SingleEtaRegionMatcher.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/SelectedJetsMatcher.h
similarity index 57%
rename from Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SingleEtaRegionMatcher.h
rename to Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/SelectedJetsMatcher.h
index 673e401bfb920aed3026270b3adfd596db349f63..11c43fa0bd8a2c1cbb533d19cefb6eba67e3b63a 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SingleEtaRegionMatcher.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/SelectedJetsMatcher.h
@@ -2,13 +2,13 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-#ifndef TRIGJETHYPO_SINGLEETAREGIONMATCHER_H
-#define TRIGJETHYPO_SINGLEETAREGIONMATCHER_H
+#ifndef TRIGJETHYPO_SELECTEDJETSMATCHER_H
+#define TRIGJETHYPO_SELECTEDJETSMATCHER_H
 
 
 // ********************************************************************
 //
-// NAME:     SingleEtaRegionMatcher.h
+// NAME:     SelectedJetsMatcher.h
 // PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
 //
 // AUTHOR:  P Sherwood
@@ -19,27 +19,33 @@
 #include <utility>
 
 #include "xAODJet/Jet.h"
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/Matcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
 
-class SingleEtaRegionMatcher: public IMatcher{
+
+class SelectedJetsMatcher: virtual public IMatcher, private Matcher{
   /* Match by ordering all jets in the single eta region
      in Et, pair of with the Conditions objects also ordered
      in Et. Event pass if the Et of each jet >= to the threshold
      of the paired Condition.
    */
 public:
-  ConditionsSorter sorterPred;
-  SingleEtaRegionMatcher(const Conditions& cs);
+  SelectedJetsMatcher(const Conditions& cs, 
+		      const std::vector<unsigned int>& indices,
+		      const std::string& name);
+  ~SelectedJetsMatcher(){}
   void match(JetIter b, JetIter e) override;
   bool pass() const override;
   std::pair<JetCIter, JetCIter> passed_iters() const override;
   std::pair<JetCIter, JetCIter> failed_iters() const override;
-
+  std::string toString() const noexcept override;
+  const Conditions& getConditions() const noexcept override;
 private:
   Conditions m_conditions;
-  bool m_pass;
-
+  std::vector<unsigned int> m_indices;
   JetVector m_passed_jets;
   JetVector m_failed_jets;
+  bool m_pass;
 };
 #endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/TLACondition.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/TLACondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..463fc282bc7b7242fa708eed07c5e241430ace73
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/TLACondition.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_TLACONDITION_H
+#define TRIGJETHYPO_TLACONDITION_H
+/********************************************************************
+ *
+ * NAME:     TLACondition.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJEtHypo
+ *********************************************************************/
+
+#include "xAODJet/Jet.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICondition.h"
+
+
+class TLACondition: public ICondition{
+ public:
+  TLACondition(double etaMin,
+	       double etaMax,
+	       double ystarMin,
+	       double ystarMax,
+	       double massMin,
+	       double massMax);
+
+  ~TLACondition() override {}
+
+  bool isSatisfied(const std::vector<const xAOD::IParticle*>&) const override;
+
+  bool isSatisfied(const xAOD::IParticle*) const override;
+
+  double orderingParameter() const noexcept override;
+
+  std::string toString() const noexcept override;
+
+ private:
+  double m_etaMin;
+  double m_etaMax;
+  double m_ystarMin;
+  double m_ystarMax;
+  double m_massMin;
+  double m_massMax;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h
deleted file mode 100644
index e954ff2807794de0fc064d1d3a98545ccb422294..0000000000000000000000000000000000000000
--- a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TRIGJETHYPO_TRIGHLTJETHYPOUTILS_H
-#define TRIGJETHYPO_TRIGHLTJETHYPOUTILS_H
-/********************************************************************
- *
- * NAME:     TrigHLTJetHypo.h
- * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
- *
- * AUTHOR:   P. Sherwood
- * CREATED:  March 21, 2015
- *           
- *
- *  Headers file for visible classes used by TrigHLTJEtHypo
- *********************************************************************/
-
-/* WORK IN PROGRESS _ DO NOT USE ! */
-// #include "TrigJetHypo/TrigHLTJetHypo.h"
-#include "xAODJet/Jet.h"
-
-using JetVector = std::vector<const xAOD::Jet*>;
-using JetIter = JetVector::iterator;
-using JetCIter = JetVector::const_iterator;
-
-
-//////////////////////////////////////
-
-/*
-class ICleanerMatcher{
-  // Abstract interface used by a factory function
- public:
-  virtual void process(JetIter, JetIter) = 0;
-  virtual bool pass() const = 0;
-  virtual std::pair<JetCIter, JetCIter> passedJetIters() const = 0;
-  virtual std::pair<JetCIter, JetCIter> failedJetIters() const = 0;
-};
-*/
-//////////////////////////////////////
-
-class ICleaner{
- public:
-  // Abstract interface used by a factory function
-  virtual bool operator()(const xAOD::Jet* jet) const = 0;
-};
-
-//////////////////////////////////////
-
-class IMatcher{
- public:
-// Abstract interface used by a factory function
-  virtual void match(JetIter b, JetIter e) = 0;
-  virtual bool pass() const = 0;
-  virtual std::pair<JetCIter, JetCIter> passed_iters() const = 0;
-  virtual std::pair<JetCIter, JetCIter> failed_iters() const = 0;
-};
-
-//////////////////////////////////////
-/*
-class MatcherBridge{
-  // Bridge object: convert polymorphic pointer to monomorthic class
-  // can be passed to STL algs.
- public:
- MatcherBridge(const std::shared_ptr<IMatcher>& matcher):
-  m_pMatcher(matcher){}
-  
-  bool match(JetIter b, JetIter e) const {
-    return m_pMatcher->match(b, e);
-  }
-  bool pass() const{return m_pMatcher->pass();}
-  
-  std::pair<JetCIter, JetCIter> passed_iters() const{
-    return m_pMatcher->passed_iters();}
-  
-  std::pair<JetCIter, JetCIter> failed_iters() const{
-    return m_pMatcher->failed_iters();}
-
- private:
-  std::shared_ptr<IMatcher> m_pMatcher;
-
-};
-*/
-
-//////////////////////////////////////
-class CleanerBridge{
-  // Bridge object: convert polymorphic pointer to monomorthic class
-  // can be passed to STL algs.
- public:
- CleanerBridge(const std::shared_ptr<ICleaner>& cleaner):
-  m_pCleaner(cleaner){}
-
-  bool operator()(const xAOD::Jet* jet) const{
-    return m_pCleaner -> operator()(jet);
-  }
-
- private:
-  std::shared_ptr<ICleaner> m_pCleaner;
-};
-
-//////////////////////////////////////
-
-class CleanerMatcher{
-  /*
-    Object that takes a jet cleaner and a matcher.
-    A matcher checks whether there is a subset of the jets
-    that fulfill the hypo conditions.
-  */
- public:
- CleanerMatcher(const std::shared_ptr<ICleaner>& cleaner,
-                const std::shared_ptr<IMatcher>& matcher):
-  m_cleaner(CleanerBridge(cleaner)), m_matcher(matcher){}
-  
-  void process(JetIter begin, JetIter end) {
-    JetIter cleanEnd = std::partition(begin, end, m_cleaner);
-    m_matcher->match(begin, cleanEnd);
-  }
-
-  bool pass() const{return m_matcher->pass();}
-
-  std::pair<JetCIter, JetCIter> 
-  passedJetIters() const {return m_matcher->passed_iters();}
-
-  std::pair<JetCIter, JetCIter> 
-  failedJetIters() const {return m_matcher->failed_iters();}
-  
-private:
-  CleanerBridge m_cleaner;
-  std::shared_ptr<IMatcher> m_matcher;
-};
-
-// Define a class to hold etaMin, etaMax and threshold (Et in MeV)
-// that jets will be matched against
-class Condition{
- public:
-  Condition(double etaMin, double etaMax, double threshold);
-
-  bool etaOK(const xAOD::IParticle* ip) const noexcept;
-
-  bool etOK(const xAOD::IParticle* ip) const noexcept;
-  bool allOK(const xAOD::IParticle* ip) const noexcept;
-
-  double etaMin() const noexcept;
-  double etaMax() const noexcept;
-  double threshold() const noexcept;
-
- private:
-  double m_etaMin;
-  double m_etaMax;
-  double m_threshold;
-};
-
-std::ostream& operator<< (std::ostream& os, const Condition& c);
-
-using Conditions = std::vector<Condition>;
-using ConditionsIter = std::vector<Condition>::iterator;
-
-struct ConditionsSorter{
-  bool operator()(const Condition& l, const Condition& r);
-};
-
-#endif
-
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/lineSplitter.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/lineSplitter.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4124cc7755dde7b298333d3e54c8f6116091792
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/lineSplitter.h
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_LINESPLITTER_H
+#define TRIGJETHYPO_LINESPLITTER_H
+/********************************************************************
+ *
+ * NAME:     LineSplitter.h
+ * PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+ *
+ * AUTHOR:   P. Sherwood
+ * CREATED:  March 21, 2015
+ *           
+ *
+ *  Headers file for visible classes used by TrigHLTJetHypo
+ *********************************************************************/
+
+#include <string>
+#include <vector>
+
+std::vector<std::string> lineSplitter(const std::string&, char delimiter='\n');
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/matcherFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/matcherFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..b82f586c70e1095fae466ef63888ea5d71aabe32
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/matcherFactory.h
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_MATCHERFACTORY_H
+#define TRIGJETHYPO_MATCHERFACTORY_H
+
+// ********************************************************************
+//
+// NAME:     matcherFactory.h
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:  P Sherwood
+//
+// ********************************************************************
+//
+
+#include <memory>
+#include <string>
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcherFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
+
+// matcherFactory instances return IMatcher instances.
+
+class MaximumBipartiteMatcherFactory: public IMatcherFactory {
+ public:
+  MaximumBipartiteMatcherFactory(const Conditions&, const std::string&);
+  std::shared_ptr<IMatcher> make() const override;
+ private:
+  Conditions m_conditions;
+  std::string m_name;
+};
+
+
+class OrderedCollectionsMatcherFactory: public IMatcherFactory {
+ public:
+  OrderedCollectionsMatcherFactory(const Conditions&, const std::string&);
+  std::shared_ptr<IMatcher> make() const override;
+ private:
+  Conditions m_conditions;
+  std::string m_name;
+};
+
+
+class SelectedJetsMatcherFactory: public IMatcherFactory {
+ public:
+  SelectedJetsMatcherFactory(const Conditions&, 
+			     const std::vector<unsigned int>& indices,
+			     const std::string&);
+
+  std::shared_ptr<IMatcher> make() const override;
+ private:
+  Conditions m_conditions;
+  std::vector<unsigned int> m_indices;
+  std::string m_name;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/matcherFactoryFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/matcherFactoryFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..931df0358690ca4b44beae2ea63338eba3c4b281
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/TrigJetHypo/TrigHLTJetHypoUtils/matcherFactoryFactory.h
@@ -0,0 +1,39 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_MATCHERMATCHERFACTORY_H
+#define TRIGJETHYPO_MATCHERMATCHERFACTORY_H
+
+// ********************************************************************
+//
+// NAME:     matcherMatcherFactory.h
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:  P Sherwood
+//
+// ********************************************************************
+//
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcherFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
+
+
+// matcherFactoryFactory functions return IMatcher factory instances.
+// The function overloads are used to differntiate the different
+// matcher factories to instantiate.
+// the extra level of indiretion allows the Factory classes to store
+// only the information needed to instantiate their particular Matcher
+std::shared_ptr<IMatcherFactory> matcherFactoryFactory(const Conditions&,
+						       const std::string&);
+
+std::shared_ptr<IMatcherFactory> matcherFactoryFactory(const Conditions&,
+						       const std::vector<unsigned int>,
+						       const std::string&);
+
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypo.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypo.cxx
index 0d1095de3d59b4db3a4eb73599fbcab215364b10..bb086368ef2798340be3f5e1237321fa4c2c207d 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypo.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypo.cxx
@@ -14,7 +14,6 @@
 
 #include <algorithm>
 #include <sstream>
-// #include <cmath>
 #include <stdexcept>
 #include <memory>
 //
@@ -24,7 +23,6 @@
 
 #include "TrigSteeringEvent/Enums.h"
 #include "TrigJetHypo/TrigHLTJetHypo.h"
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
 
 #include "xAODJet/JetContainer.h"
 #include "xAODJet/Jet.h"
@@ -33,13 +31,19 @@
 #include "CLHEP/Units/SystemOfUnits.h"
 
 #include "TrigSteeringEvent/TrigPassBits.h"
-#include "./TrigHLTJetHypoHelpers/matcherFactory.h"
-#include "./TrigHLTJetHypoHelpers/cleanerFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/matcherFactoryFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h"
+#include "./TrigHLTJetHypoHelpers/conditionsFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsSorter.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/lineSplitter.h"
 
 
-TrigHLTJetHypo::TrigHLTJetHypo(const std::string& name, ISvcLocator* pSvcLocator):
-  HLT::HypoAlgo(name, pSvcLocator) {
+#include <memory>
 
+TrigHLTJetHypo::TrigHLTJetHypo(const std::string& name,
+			       ISvcLocator* pSvcLocator):
+  HLT::HypoAlgo(name, pSvcLocator) {
   
   m_accepted=0;
   m_rejected=0;
@@ -53,11 +57,21 @@ TrigHLTJetHypo::TrigHLTJetHypo(const std::string& name, ISvcLocator* pSvcLocator
   declareProperty("EtThresholds",   m_EtThresholds ); // Default: 40 GeV
   declareProperty("eta_mins",   m_etaMins);
   declareProperty("eta_maxs",   m_etaMaxs);
- 
+
+  //TLA style jet indices
+  declareProperty("ystar_mins", m_ystarMins);
+  declareProperty("ystar_maxs", m_ystarMaxs);
+  declareProperty("mass_mins", m_massMins);
+  declareProperty("mass_maxs", m_massMaxs);
+  declareProperty("jetvec_indices",   m_jetvec_indices);
+
   // cleaning
   declareProperty("cleaningAlg", m_cleaningAlg = "noCleaning");
+
+  // matching. Legal: maximumBipartite, orderedCollections, selectedJets
   declareProperty("matchingAlg", m_matchingAlg = "maximumBipartite");
-  //basic cleaning  
+ 
+ //basic cleaning  
   declareProperty("n90CleaningThreshold", m_n90Threshold = 2 );
   declareProperty("presamplerCleaningThreshold", m_presamplerThreshold = 0.9 );
   declareProperty("negativeECleaningThreshold", m_negativeEThreshold = -60e3 ); // 60 GeV
@@ -80,11 +94,11 @@ TrigHLTJetHypo::TrigHLTJetHypo(const std::string& name, ISvcLocator* pSvcLocator
   declareProperty("HECfTightThreshold", m_hecfTightThreshold = 0.85 );
   //long-lived particle cleaning
   declareProperty("fracSamplingMaxLlpThreshold", m_fSampMaxLlpThreshold = 0.85 );
-  declareProperty("negativeELlpThreshold", m_negELlpThreshold = -10e3 ); // 10 GeV
+  declareProperty("negativeELlpThreshold", m_negELlpThreshold = 10e3 ); // 10 GeV
   declareProperty("HECfLlpThreshold", m_hecfLlpThreshold = 0.5 );
-  declareProperty("HECQLlpThreshold", m_hecfLlpThreshold = 0.5 );
+  declareProperty("HECQLlpThreshold", m_hecqLlpThreshold = 0.5 );
   declareProperty("AverageLArQFLlpThreshold", m_avLarQFLlpThreshold = 0.8*65535 );
-
+ 
 
   declareMonitoredVariable("CutCounter", m_cutCounter);
 
@@ -114,46 +128,127 @@ HLT::ErrorCode TrigHLTJetHypo::hltInitialize()
     m_timers.push_back(tmp);
   }
 
-  if (m_EtThresholds.size() != m_etaMins.size() or
-      m_EtThresholds.size() != m_etaMaxs.size()){
+  std::vector<std::string> v {"orderedCollections", "maximumBipartite"};
+  if (std::find(v.begin(), v.end(), m_matchingAlg) != v.end()){
+
+    if (m_EtThresholds.size() != m_etaMins.size() or
+	m_EtThresholds.size() != m_etaMaxs.size()){
+
+      msg() << MSG::ERROR
+	    << name()
+	    << ": mismatch between number of thresholds and eta min, max boundaries: "
+	    << m_EtThresholds.size() << " "
+	    << m_etaMins.size() << " "
+	    << m_etaMaxs.size() << " "
+	    << endreq;
+      return HLT::ErrorCode(HLT::Action::ABORT_JOB,HLT::Reason::BAD_JOB_SETUP);
+    }
+  }
+
+  if (m_matchingAlg == "selectedJets") {
+    if (m_etaMins.size() != m_etaMaxs.size() or
+	m_etaMins.size() != m_ystarMins.size() or
+	m_etaMins.size() != m_ystarMaxs.size() or
+	m_etaMins.size() != m_massMins.size() or
+	m_etaMins.size() != m_massMaxs.size()){
+
+
+      msg() << MSG::ERROR
+	    << name()
+	    << ": size mismatch: "
+	    << "eta_mins" <<  m_etaMins.size() << " "
+	    << "eta_maxs"  <<  m_etaMaxs.size() << " "
+	    << "ystar_mins" <<  m_ystarMins.size() << " "
+	    << "ystar_maxs" <<  m_ystarMaxs.size() << " "
+	    << "mass_mins" <<  m_massMins.size() << " "
+	    << "mass_maxs" <<  m_massMaxs.size() << " "
+	    << endreq;
+      return HLT::ErrorCode(HLT::Action::ABORT_JOB,HLT::Reason::BAD_JOB_SETUP);
+    }
+  }
+
+  if(m_matchingAlg == "orderedCollections"){
+    if (std::set<double>(m_etaMins.cbegin(), m_etaMins.cend()).size() != 1){
+      return HLT::ErrorCode(HLT::Action::ABORT_JOB,HLT::Reason::BAD_JOB_SETUP);
+    }      
+    if (std::set<double>(m_etaMaxs.cbegin(), m_etaMaxs.cend()).size() != 1){
+      return HLT::ErrorCode(HLT::Action::ABORT_JOB,HLT::Reason::BAD_JOB_SETUP);
+    }      
+  }
 
+  std::vector<std::string> vv {"orderedCollections", "maximumBipartite"};
+
+  Conditions conditions;
+  std::shared_ptr<IMatcherFactory> matcherFactory;
+
+  if (std::find(vv.begin(), vv.end(), m_matchingAlg) != vv.end()){
+    conditions =  conditionsFactory(m_etaMins,
+				    m_etaMaxs,
+				    m_EtThresholds);
+    std::sort(conditions.begin(), conditions.end(), ConditionsSorter());
+    matcherFactory = matcherFactoryFactory(conditions, m_matchingAlg);
+  } else if (m_matchingAlg == "selectedJets") {
+    conditions =  conditionsFactory(m_etaMins, m_etaMaxs,
+				    m_ystarMins, m_ystarMaxs,
+				    m_massMins, m_massMaxs);
+    std::sort(conditions.begin(), conditions.end(), ConditionsSorter());
+    matcherFactory = matcherFactoryFactory(conditions,
+					   m_jetvec_indices,
+					   m_matchingAlg);
+  } else {
     msg() << MSG::ERROR
           << name()
-          << ": mismatch between number of thresholds and eta min, max boundaries: "
-          << m_EtThresholds.size() << " "
-          << m_etaMins.size() << " "
-          << m_etaMaxs.size() << " "
+          << ": unknown key to set up the matcher factory: "
+	  << m_matchingAlg
           << endreq;
     return HLT::ErrorCode(HLT::Action::ABORT_JOB,HLT::Reason::BAD_JOB_SETUP);
-  }   
-  
-  for (std::size_t i = 0; i != m_EtThresholds.size(); ++i){
-    m_conditions.push_back(Condition(m_etaMins[i],
-                                     m_etaMaxs[i],
-                                     m_EtThresholds[i]));
   }
 
-  std::sort(m_conditions.begin(), m_conditions.end(), ConditionsSorter());
+   CleanerFactory cleanerFactory(//basic cleaning
+				 m_n90Threshold, 
+				 m_presamplerThreshold,
+				 m_negativeEThreshold,
+				 //loose cleaning
+				 m_fSampMaxLooseThreshold,
+				 m_etaLooseThreshold,
+				 m_emfLowLooseThreshold,
+				 m_emfHighLooseThreshold,
+				 m_hecfLooseThreshold,
+				 //tight cleaning
+				 m_fSampMaxTightThreshold,
+				 m_etaTightThreshold,
+				 m_emfLowTightThreshold,
+				 m_emfHighTightThreshold,
+				 m_hecfTightThreshold,
+				 //long-lived particle cleaning
+				 m_fSampMaxLlpThreshold,
+				 m_negELlpThreshold,
+				 m_hecfLlpThreshold,
+				 m_hecqLlpThreshold,
+				 m_avLarQFLlpThreshold,
+				 m_cleaningAlg);
+   
+   // m_cleaner = cleanerFactory.make();
 
-  /*
-  std::string msg = 'JetHypo conditions (threshold, eta min, eta max): \n';
-  for(auto c : m_conditions){
-    msg += c.threshold() + " " + c.etaMin() + " " + c.etaMax() + '\n';
-  }
-  ATH_MSG_INFO(msg);
-  */
+   m_cleanerMatcherFactory = 
+     std::make_shared<CleanerMatcherFactory>(cleanerFactory,
+					     matcherFactory);
 
   // Later code assumes conditions vector is not empty.
-  if (m_conditions.empty()){
+  if (conditions.empty()){
     ATH_MSG_ERROR("TrigHLTJetHypo bad configuration, no conditions given");
     return HLT::ERROR;
   }
     
-  ATH_MSG_INFO("TrigHLTJetHypo conditions: "<< m_conditions.size());
-  for(auto c: m_conditions){ATH_MSG_INFO(c);}
-  ATH_MSG_INFO("TrigHLTJetHypo cleaner: "<< m_cleaningAlg);
-  ATH_MSG_INFO("TrigHLTJetHypo matcher: "<< m_matchingAlg);
 
+  // print out the CleanerMatcher configuration
+  ATH_MSG_INFO("TrigHLTJetHypo cleanerMatcher: ");
+  std::string line = (m_cleanerMatcherFactory->make()).toString();
+  std::vector<std::string> lines = lineSplitter(line, '\n');
+
+  for(auto l : lines){
+    ATH_MSG_INFO(l);
+  }
 
   return HLT::OK;
   
@@ -189,21 +284,13 @@ HLT::ErrorCode TrigHLTJetHypo::hltExecute(const HLT::TriggerElement* outputTE,
   /* copy the jets to a non-constant container */
   std::vector<const xAOD::Jet*> theJets(outJets->begin(), outJets->end());
 
-  /* set up jet cleaning and hypothesis algorithm according to the user
-     set flags */
-
-  CleanerMatcher cleanerMatcher(std::shared_ptr<ICleaner>{},
-                                std::shared_ptr<IMatcher>{});
 
-  try{
-    cleanerMatcher = getCleanerMatcher();
-  } catch (std::invalid_argument& e){
-    ATH_MSG_ERROR("Exception raised creating cleanerMatcher: " << e.what());
-    return HLT::ERROR;
-  }
+  // auto cleanerMatcher = getCleanerMatcher();
+  auto cleanerMatcher = m_cleanerMatcherFactory->make();
 
    /* apply cleaning and hypotheis alg */
   ATH_MSG_DEBUG("cleaning and Matching start... " << name() << "...");
+  ATH_MSG_DEBUG("no of jets ... " << theJets.size() << "...");
   try{
     cleanerMatcher.process(theJets.begin(), theJets.end());
   } catch(std::exception& e){
@@ -262,8 +349,9 @@ HLT::ErrorCode TrigHLTJetHypo::checkJets(const xAOD::JetContainer* outJets){
      monitorLeadingJet(*leading_jet);
    }
 
+   writeDebug(pass, passedJetIters, failedJetIters, cm);
+
    int multiplicity = passedJetIters.second - passedJetIters.first;
-   writeDebug(pass, multiplicity, passedJetIters, failedJetIters);
    bumpCounters(pass, multiplicity);
  }
 
@@ -288,22 +376,15 @@ void TrigHLTJetHypo::monitorLeadingJet(const xAOD::Jet* jet){
 
 void 
  TrigHLTJetHypo::writeDebug(bool pass,
-                            int multiplicity,
                             const std::pair<JetCIter, JetCIter>& passedJetIters,
-                            const std::pair<JetCIter, JetCIter>& failedJetIters
+                            const std::pair<JetCIter, JetCIter>& failedJetIters,
+			    const CleanerMatcher& cm
                             ) const{
     ATH_MSG_DEBUG("Writing debug " << name() << "...");
    // Et Cut
     if(pass){ATH_MSG_DEBUG("Event accepted");}
     else { ATH_MSG_DEBUG("Event rejected");}
 
-
-   ATH_MSG_DEBUG("found multiplicity: "
-                 << multiplicity
-                 << "\t multiplicity cut: "
-                 << m_conditions.size()
-                 << ("passed Jets:"));
-
    for (JetCIter j = passedJetIters.first; j != passedJetIters.second; ++j) {
      ATH_MSG_DEBUG((*j)->p4().Et() << " " << (*j) -> eta());
    }
@@ -314,48 +395,11 @@ void
    }
 
    ATH_MSG_DEBUG("conditions: ");
-   for (auto c = m_conditions.begin(); c != m_conditions.end(); ++c) {
-     ATH_MSG_DEBUG(*c);
+   for (auto c : cm.getConditions()) {
+     ATH_MSG_DEBUG(c.toString());
    }
-  }
 
- CleanerMatcher TrigHLTJetHypo::getCleanerMatcher() const{
-   /* initalise a Cleaner Matcher.
-      Cleaning: according to the user set flags.
-
-      Match conditions: SingleEtaRegion and MaximumBipartite matchers are 
-      available. For now only hardwire the MaximumBipartite matcher.
-
-   */
-
-   auto cleaner = cleanerFactory(//basic cleaning
-				 m_n90Threshold, 
-				 m_presamplerThreshold,
-				 m_negativeEThreshold,
-				 //loose cleaning
-				 m_fSampMaxLooseThreshold,
-				 m_etaLooseThreshold,
-				 m_emfLowLooseThreshold,
-				 m_emfHighLooseThreshold,
-				 m_hecfLooseThreshold,
-				 //tight cleaning
-				 m_fSampMaxTightThreshold,
-				 m_etaTightThreshold,
-				 m_emfLowTightThreshold,
-				 m_emfHighTightThreshold,
-				 m_hecfTightThreshold,
-				 //long-lived particle cleaning
-				 m_fSampMaxLlpThreshold,
-				 m_negELlpThreshold,
-				 m_hecfLlpThreshold,
-				 m_hecqLlpThreshold,
-				 m_avLarQFLlpThreshold,
-				//cleaning mode
-                                 m_cleaningAlg);
-   auto matcher = matcherFactory(m_conditions, m_matchingAlg);
-
-   return CleanerMatcher(cleaner, matcher);
- }
+  }
 
 
 HLT::ErrorCode
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.cxx
index bfe9aaeb6310d201f9ce2245d58fe15d3cba4ed2..b3de94237df7c6e55e337d03574af317e83044f5 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.cxx
@@ -15,8 +15,6 @@
 #include "./AntiBasicCleaner.h"
 #include "xAODJet/Jet.h"  //ICleaner
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
-
 AntiBasicCleaner::AntiBasicCleaner(float n90Threshold,
                                    float presamplerThreshold,
                                    float negativeEThreshold):
@@ -26,7 +24,8 @@ bool AntiBasicCleaner::operator()(const xAOD::Jet* jet) const{
   return !BasicCleaner::operator()(jet);
 }
 
-
+std::string
+AntiBasicCleaner::getName() const noexcept {return "AntiBasicCleaner";}
 
 
 
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.h
index cf29bbbe60e437e0db09b87ee1e0dcdd52125758..c6b95d8b9462687a0e3d6ab67337dcba387c6c64 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiBasicCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "./BasicCleaner.h"
 #include "xAODJet/Jet.h"
 
@@ -26,8 +26,10 @@ public:
   AntiBasicCleaner(float n90Threshold,
                    float presamplerThreshold,
                    float negativeEThreshold);
+  ~AntiBasicCleaner(){}
   
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string getName() const noexcept override;
 };
 
 #endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.cxx
index 3b5faff5ac0c2b7ad2b0a5eeeb4f0b7fc5ea05e8..dd66db545d573daadb47301f5047dc34ade6904b 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.cxx
@@ -13,9 +13,8 @@
 //
 
 #include "./AntiLlpCleaner.h"
-#include "xAODJet/Jet.h"  //ICleaner
+#include "xAODJet/Jet.h"
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
 
 AntiLlpCleaner::AntiLlpCleaner(float fSampMaxLlpThreshold,
                                float negELlpThreshold,
@@ -32,7 +31,8 @@ bool AntiLlpCleaner::operator()(const xAOD::Jet* jet) const{
   return !LlpCleaner::operator()(jet);
 }
 
-
+std::string
+AntiLlpCleaner::getName() const noexcept {return "AntiLlpCleaner";}
 
 
 
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.h
index a8d5f62ced2e4ca945c2e5cbcb303cfd93be3432..0b5516267ca1e7032416c6fd56cc132959db953f 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLlpCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "./LlpCleaner.h"
 #include "xAODJet/Jet.h"
 
@@ -29,7 +29,10 @@ public:
                  float hecqLlpThreshold,
                  float avLarQFLlpThreshold);
 
+  ~AntiLlpCleaner(){}
+
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string getName() const noexcept override;
 };
 
 #endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.cxx
index 8da32f74f614db8186c5119fe4a8edf5e28758e7..fb4d0667b00adaf69ea33f6fd480896d189327b6 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.cxx
@@ -15,8 +15,6 @@
 #include "./AntiLooseCleaner.h"
 #include "xAODJet/Jet.h"  //ICleaner
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
-
 AntiLooseCleaner::AntiLooseCleaner(float fSampMaxLooseThreshold,
                                    float etaLooseThreshold,
                                    float emfLowLooseThreshold,
@@ -33,6 +31,8 @@ bool AntiLooseCleaner::operator()(const xAOD::Jet* jet) const{
 }
 
 
+std::string  
+AntiLooseCleaner::getName() const noexcept {return "AntiLooseCleaner";}
 
 
 
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.h
index 564636894ef63ba30fd63b8fda3ec5edca301bab..521ed1f50a72f181482cef33a7b693430073e0de 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiLooseCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "./LooseCleaner.h"
 #include "xAODJet/Jet.h"
 
@@ -29,7 +29,11 @@ public:
                    float emfHighLooseThreshold,
                    float hecfLooseThreshold);
 
+  ~AntiLooseCleaner(){}
+
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string getName() const noexcept override;
+
 };
 
 #endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.cxx
index 981eafdc85e70a8f92dee05dc3bdfd38f3bdc49b..d8c1265381d5a49ef09aafeb44e0840b980c1c7e 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.cxx
@@ -13,9 +13,7 @@
 //
 
 #include "./AntiTightCleaner.h"
-#include "xAODJet/Jet.h"  //ICleaner
-
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
+#include "xAODJet/Jet.h"
 
 AntiTightCleaner::AntiTightCleaner(float fSampMaxTightThreshold,
                                    float etaTightThreshold,
@@ -32,6 +30,8 @@ bool AntiTightCleaner::operator()(const xAOD::Jet* jet) const{
   return TightCleaner::operator()(jet);
 }
 
+std::string 
+AntiTightCleaner::getName() const noexcept {return "AntiTightCleaner";}
 
 
 
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.h
index 0f519be2ea376ada3d82491d7235220a1e7e807c..1dab85ec92ba1b6a3a8bee1bb4ccf19f6ff7f67d 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/AntiTightCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "./TightCleaner.h"
 #include "xAODJet/Jet.h"
 
@@ -29,7 +29,10 @@ public:
                    float emfHighTightThreshold,
                    float hecfTightThreshold);
 
+  ~AntiTightCleaner() {}
+
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string getName() const noexcept override;
 };
 
 #endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.cxx
index 498a8499d46a1f208edefa6b944a15bfbda3dba4..fe4d260c7bb7f54b4d9b760c76b8454d9dd87090 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.cxx
@@ -16,6 +16,7 @@
 #include "./UncleanableJet.h"  // exception class
 
 #include "CaloGeoHelpers/CaloSampling.h"
+#include <sstream>
 
 BasicCleaner::BasicCleaner(float n90Threshold,
                            float presamplerThreshold,
@@ -91,3 +92,19 @@ bool BasicCleaner::operator()(const xAOD::Jet* jet) const {
   return isClean;
 
 }
+
+std::string BasicCleaner::toString() const noexcept{
+  std::stringstream ss;
+  ss << getName() 
+     <<  ": n90Threshold: "
+     <<  m_n90Threshold
+     <<  " m_presamplerThreshold: " 
+     <<  m_presamplerThreshold
+     <<  "m_negativeEThreshold: "
+     <<  m_negativeEThreshold 
+     << '\n';
+  return ss.str();
+}
+
+std::string 
+BasicCleaner::getName() const noexcept {return "BasicCleaner";}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.h
index e73b8af93c598735be98c5eb6804a6e47a187640..7e39ffadd4e715d1d9dd8079908e7e3ef1517231 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/BasicCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" //ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "xAODJet/Jet.h"
 
 class BasicCleaner: public ICleaner{
@@ -26,7 +26,12 @@ class BasicCleaner: public ICleaner{
                float presamplerThreshold,
                float negativeEThreshold);
   
+  ~BasicCleaner() {}
+
+
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string toString() const noexcept override;
+  std::string getName() const noexcept override;
 
  private:
   float m_n90Threshold;
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/CleanerFactory.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/CleanerFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..aa947562c81f842d74838b20806f0e94ec5f3eed
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/CleanerFactory.cxx
@@ -0,0 +1,143 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ********************************************************************
+//
+// NAME:     cleanerFactory.cxx
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:   N Anjos, P Sherwood
+//
+// ********************************************************************
+//
+
+
+#include <stdexcept>
+#include <memory>
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h"
+
+#include "./BasicCleaner.h"
+#include "./AntiBasicCleaner.h"
+#include "./LooseCleaner.h"
+#include "./AntiLooseCleaner.h"
+#include "./TightCleaner.h"
+#include "./AntiTightCleaner.h"
+#include "./LlpCleaner.h"
+#include "./AntiLlpCleaner.h"
+#include "./NullCleaner.h"
+
+using pIC = std::shared_ptr<ICleaner>;
+
+CleanerFactory::CleanerFactory(//basic cleaning
+			       double n90Threshold,
+			       double presamplerThreshold,
+			       double negativeEThreshold,
+			       //loose cleaning
+			       double fSampMaxLooseThreshold,
+			       double etaLooseThreshold,
+			       double emfLowLooseThreshold,
+			       double emfHighLooseThreshold,
+			       double hecfLooseThreshold,
+			       //tight cleaning
+			       double fSampMaxTightThreshold,
+			       double etaTightThreshold,
+			       double emfLowTightThreshold,
+			       double emfHighTightThreshold,
+			       double hecfTightThreshold,
+			       //long-lived particle cleaning
+			       double fSampMaxLlpThreshold,
+			       double negELlpThreshold,
+			       double hecfLlpThreshold,
+			       double hecqLlpThreshold,
+			       double avLarQFLlpThreshold,
+			       const std::string& key):
+  m_n90Threshold(n90Threshold),
+  m_presamplerThreshold(presamplerThreshold),
+  m_negativeEThreshold(negativeEThreshold),
+  m_fSampMaxLooseThreshold(fSampMaxLooseThreshold),
+  m_etaLooseThreshold(etaLooseThreshold),
+  m_emfLowLooseThreshold(emfLowLooseThreshold),
+  m_emfHighLooseThreshold(emfHighLooseThreshold),
+  m_hecfLooseThreshold(hecfLooseThreshold),
+  m_fSampMaxTightThreshold(fSampMaxTightThreshold),
+  m_etaTightThreshold(etaTightThreshold),
+  m_emfLowTightThreshold(emfLowTightThreshold),
+  m_emfHighTightThreshold(emfHighTightThreshold),
+  m_hecfTightThreshold(hecfTightThreshold),
+  m_fSampMaxLlpThreshold(fSampMaxLlpThreshold),
+  m_negELlpThreshold(negELlpThreshold),
+  m_hecfLlpThreshold(hecfLlpThreshold),
+  m_hecqLlpThreshold(hecqLlpThreshold),
+  m_avLarQFLlpThreshold(avLarQFLlpThreshold),
+  m_name(key){
+  //cleaners have no state, so can be cached.
+  make_();
+  }
+
+
+pIC CleanerFactory::make() const noexcept{
+  return m_cleaner;
+}
+
+
+void CleanerFactory::make_() {
+
+  if (m_name == "basicCleaning"){
+    m_cleaner =  pIC (new BasicCleaner(m_n90Threshold, 
+				       m_presamplerThreshold,
+				       m_negativeEThreshold));
+    
+  } else if (m_name == "antiBasicCleaning"){
+    m_cleaner =  pIC (new AntiBasicCleaner(m_n90Threshold, 
+					   m_presamplerThreshold,
+					   m_negativeEThreshold));
+  } else if (m_name == "looseCleaning"){
+    m_cleaner =  pIC (new LooseCleaner(m_fSampMaxLooseThreshold,
+				       m_etaLooseThreshold,
+				       m_emfLowLooseThreshold,
+				       m_emfHighLooseThreshold,
+				       m_hecfLooseThreshold));
+  } else if (m_name == "antiLooseCleaning"){
+    m_cleaner =  pIC (new AntiLooseCleaner(m_fSampMaxLooseThreshold,
+					   m_etaLooseThreshold,
+					   m_emfLowLooseThreshold,
+					   m_emfHighLooseThreshold,
+					   m_hecfLooseThreshold));
+  } else if (m_name == "tightCleaning"){
+    m_cleaner =  pIC (new TightCleaner(m_fSampMaxTightThreshold,
+				       m_etaTightThreshold,
+				       m_emfLowTightThreshold,
+				       m_emfHighTightThreshold,
+				       m_hecfTightThreshold));
+  } else if (m_name == "antiTightCleaning"){
+    m_cleaner =  pIC (new AntiTightCleaner(m_fSampMaxTightThreshold,
+					   m_etaTightThreshold,
+					   m_emfLowTightThreshold,
+					   m_emfHighTightThreshold,
+					   m_hecfTightThreshold));
+  } else if (m_name == "llpCleaning"){
+    m_cleaner =  pIC (new LlpCleaner(m_fSampMaxLlpThreshold,
+				     m_negELlpThreshold,
+				     m_hecfLlpThreshold,
+				     m_hecqLlpThreshold,
+				     m_avLarQFLlpThreshold));
+  } else if (m_name == "antiLlpCleaning"){
+    m_cleaner =  pIC (new AntiLlpCleaner(m_fSampMaxLlpThreshold,
+					 m_negELlpThreshold,
+					 m_hecfLlpThreshold,
+					 m_hecqLlpThreshold,
+					 m_avLarQFLlpThreshold));
+    } else if (m_name == "noCleaning"){
+    m_cleaner =  pIC (new NullCleaner);
+    
+  } else {
+    throw std::invalid_argument{"Unknown cleaner specified :" + m_name};
+    
+  }
+}
+  
+
+
+
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/CleanerMatcherFactory.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/CleanerMatcherFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..38b083bedb898410f03ca510f2130039f868b0a4
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/CleanerMatcherFactory.cxx
@@ -0,0 +1,18 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerMatcherFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/CleanerFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcherFactory.h"
+
+CleanerMatcherFactory::CleanerMatcherFactory(const CleanerFactory& cf,
+					     const std::shared_ptr<IMatcherFactory>& mf):
+
+  m_cleanerFactory(cf), m_matcherFactory(mf){
+}
+
+CleanerMatcher CleanerMatcherFactory::make() const {
+  return CleanerMatcher(m_cleanerFactory.make(),
+			m_matcherFactory->make());
+}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/ConditionsSorter.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/ConditionsSorter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5a06f3df62144702912eaab7583b3b668fefabb8
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/ConditionsSorter.cxx
@@ -0,0 +1,12 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsSorter.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionBridge.h"
+
+bool ConditionsSorter::operator()(const ConditionBridge& l,
+				  const ConditionBridge& r){
+  // return l.threshold() > r.threshold();
+  return l.orderingParameter() > r.orderingParameter();
+}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/EtaEtCondition.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/EtaEtCondition.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cbc2b139d9dc64de20431b39c8fde8b88f2f4d96
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/EtaEtCondition.cxx
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/EtaEtCondition.h"
+#include <sstream>
+#include <cmath>
+
+
+EtaEtCondition::EtaEtCondition(double etaMin, double etaMax, double threshold): 
+  m_etaMin(etaMin), m_etaMax(etaMax), m_threshold(threshold){}
+
+
+bool EtaEtCondition::isSatisfied(const xAOD::IParticle* ip) const {
+  auto abseta = std::abs((ip->p4()).Eta());
+  auto et = (ip->p4()).Et();
+  return 
+    m_etaMin <= abseta and
+    m_etaMax > abseta and
+    m_threshold <= et;
+}
+
+
+bool 
+EtaEtCondition::isSatisfied(const std::vector<const xAOD::IParticle*>& ips) 
+  const {
+  return isSatisfied(ips[0]);
+}
+
+
+std::string EtaEtCondition::toString() const noexcept {
+  std::stringstream ss;
+  ss << "Condition: etaMin "
+     <<  m_etaMin 
+     << " etaMax " 
+     << m_etaMax 
+     << " threshold: " 
+     << m_threshold
+     <<'\n';
+
+  return ss.str();
+}
+
+
+double EtaEtCondition::orderingParameter() const noexcept {return m_threshold;}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.cxx
index 1a2b5a05127d5924b89b64fe6f4ef4ef0f121c2c..66e68bee03698670091c81374e0714c2f0380621 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.cxx
@@ -15,6 +15,7 @@
 #include "./LlpCleaner.h"
 #include "./UncleanableJet.h"  // exception class
 
+#include <sstream>
 #include <cmath>
 
 LlpCleaner::LlpCleaner(float fSampMaxLlpThreshold,
@@ -69,3 +70,18 @@ bool LlpCleaner::operator()(const xAOD::Jet* jet) const {
   return isClean;
 
 }
+
+std::string LlpCleaner::toString() const noexcept {
+  std::stringstream ss;
+  ss << getName() 
+     <<  ":"
+     << " fSampMaxLlpThreshold " << m_fSampMaxLlpThreshold
+     << " negELlpThreshold " << m_negELlpThreshold
+     << " hecfLlpThreshold " << m_hecfLlpThreshold
+     << " hecqLlpThreshold " << m_hecqLlpThreshold
+     << " avLarQFLlpThreshold " << m_avLarQFLlpThreshold
+     << '\n';
+  return ss.str();
+}
+
+std::string LlpCleaner::getName() const noexcept {return "LlpCleaner";}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.h
index 489e3f5311d11144ecc3371b540de4319d9c636f..b9212f7798c852d9a7eba32077cf52b3907e760b 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LlpCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" //ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h" //ICleaner
 #include "xAODJet/Jet.h"
 
 class LlpCleaner: public ICleaner{
@@ -28,7 +28,11 @@ class LlpCleaner: public ICleaner{
              float hecqLlpThreshold,
              float avLarQFLlpThreshold);
   
+  ~LlpCleaner() {}
+
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string toString() const noexcept override;
+  std::string getName() const noexcept override;
 
  private:
   float m_fSampMaxLlpThreshold;
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.cxx
index b48b71946582a473167d88b46dd698697ce8eb0e..5dd6bdd13bff45859a3ec6c470a58f6606641a52 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.cxx
@@ -16,6 +16,7 @@
 #include "./UncleanableJet.h"  // exception class
 
 #include <cmath>
+#include <sstream>
 
 LooseCleaner::LooseCleaner(float fSampMaxLooseThreshold,
                            float etaLooseThreshold,
@@ -58,3 +59,18 @@ bool LooseCleaner::operator()(const xAOD::Jet* jet) const {
   return isClean;
 
 }
+
+std::string LooseCleaner::toString() const noexcept {
+  std::stringstream ss;
+  ss << getName() 
+     <<  ":"
+     << " fSampMaxLooseThreshold " << m_fSampMaxLooseThreshold
+     << " etaLooseThreshold " << m_etaLooseThreshold
+     << " emfLowLooseThreshold " << m_emfLowLooseThreshold
+     << " emfHighLooseThreshold " << m_emfHighLooseThreshold
+     << " hecfLooseThreshold " << m_hecfLooseThreshold
+     << '\n';
+  return ss.str();
+}
+
+std::string LooseCleaner::getName() const noexcept {return "LooseCleaner";}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.h
index 29329f089a5b5d38d92ab5d0001fcab2a4d6da03..560d8f8055651318bd6ed3227d25f9f171ca7cb9 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/LooseCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" //ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "xAODJet/Jet.h"
 
 class LooseCleaner: public ICleaner{
@@ -28,7 +28,11 @@ class LooseCleaner: public ICleaner{
                float emfHighLooseThreshold,
                float hecfLooseThreshold);
   
+  ~LooseCleaner() {}
+
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string toString() const noexcept override;
+  std::string getName() const noexcept override;
 
  private:
   float m_fSampMaxLooseThreshold;
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/Matcher.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/Matcher.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..01e2323482e3ee567837c888544a1f4754b64295
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/Matcher.cxx
@@ -0,0 +1,11 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/Matcher.h"
+
+Matcher::Matcher(const std::string& name):m_name(name){}
+
+std::string Matcher::toString() const noexcept{
+  return "Matcher: " + m_name + "\n";
+}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/MaximumBipartiteMatcher.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/MaximumBipartiteMatcher.cxx
index 0e861e7138f400bbbd1498654972d93332e6897b..d545342e47f514f2446dbf273a76e0d669f1a43f 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/MaximumBipartiteMatcher.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/MaximumBipartiteMatcher.cxx
@@ -13,14 +13,13 @@
 //
 
 #include <stdexcept>
-#include "./MaximumBipartiteMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/MaximumBipartiteMatcher.h"
 #include "./FlowNetwork.h"
 #include "./FordFulkerson.h"
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
-
-MaximumBipartiteMatcher::MaximumBipartiteMatcher(const Conditions& cs):
-  m_conditions(cs), m_pass(false){}
+MaximumBipartiteMatcher::MaximumBipartiteMatcher(const Conditions& cs,
+						 const std::string& name):
+  Matcher(name), m_conditions(cs), m_pass(false){}
   
 void MaximumBipartiteMatcher::match(JetIter b, JetIter e){
 
@@ -45,7 +44,7 @@ void MaximumBipartiteMatcher::match(JetIter b, JetIter e){
 
   // add in edges - source node to each condition node
   // the condition labels start at 1. 0 is reserved for the source node.  
-  std::map<int, const Condition*> conditionsmap;
+  std::map<int, Conditions::value_type*> conditionsmap;
   int inode = 1;
   for(auto c = m_conditions.begin(); c != m_conditions.end(); ++c){
     G.addEdge(std::make_shared<FlowEdge>(0, inode, capacity));
@@ -88,7 +87,7 @@ void MaximumBipartiteMatcher::match(JetIter b, JetIter e){
 
   for(auto c : conditionsmap){
     for (auto j : jetmap){
-      if (c.second->allOK(j.second)){
+      if (c.second->isSatisfied(j.second)){
         G.addEdge(std::make_shared<FlowEdge>(c.first, j.first, capacity));
       }
     }
@@ -119,10 +118,10 @@ void MaximumBipartiteMatcher::match(JetIter b, JetIter e){
   JetSet passing_jets;
   
   if(m_pass){
-    for(auto e : G.edges()){
-      auto it = jetmap.find(e->to());  // label corresponds ot jet?
+    for(auto edge : G.edges()){
+      auto it = jetmap.find(edge->to());  // label corresponds ot jet?
       if (it == mapend){continue;}  
-      if (std::round(e->flow()) == 1){ // jet participates in hypo decision?
+      if (std::round(edge->flow()) == 1){ // jet participates in hypo decision?
         passing_jets.insert(it->second);
         jetmap.erase(it);  // remove passing jets from map
       }
@@ -176,3 +175,15 @@ MaximumBipartiteMatcher::failed_iters() const {
   return  std::pair<JetCIter, JetCIter> (m_failed_jets.begin(),
                                          m_failed_jets.end());}
 
+
+std::string MaximumBipartiteMatcher::toString() const noexcept {
+  std::string s = Matcher::toString();
+  for(auto c : m_conditions){ s += "\n" + c.toString();}
+  return s;
+}
+
+
+const Conditions& MaximumBipartiteMatcher::getConditions() const noexcept {
+  return m_conditions;
+}
+    
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.cxx
index 4acf8052c026676119f9972870933e03eb0e4c4e..e7f6a7ace705876ce23c5b9786d96b644ca0e71f 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.cxx
@@ -15,3 +15,11 @@
 #include "./NullCleaner.h"
 
 bool NullCleaner::operator()(const xAOD::Jet*) const {return true;}    
+
+std::string NullCleaner::toString() const noexcept {
+  std::stringstream ss;
+  ss << getName() << '\n';
+  return ss.str();
+}
+
+std::string NullCleaner::getName() const noexcept  {return "NullCleaner";}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.h
index a8bd95da33ed5d2e6d908d79ddf66b384172cec4..f032e4816a1df4f1ea8683891c4c1aa27d68951a 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/NullCleaner.h
@@ -17,7 +17,7 @@
 //
 
 #include "xAODJet/Jet.h"
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "./FlowNetwork.h"
 
 namespace AOD{
@@ -27,7 +27,11 @@ namespace AOD{
 class NullCleaner: public ICleaner{
   /* apply no cleaning cuts */
 public:
+  ~NullCleaner(){}
+
   bool operator()(const xAOD::Jet*) const override;
+  std::string toString() const noexcept override;
+  std::string getName() const noexcept override;
 };
 
 
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/OrderedCollectionsMatcher.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/OrderedCollectionsMatcher.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a9e8d1d9c7f0c37692ca9b7e592eaf18e00af1f9
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/OrderedCollectionsMatcher.cxx
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ********************************************************************
+//
+// NAME:     OrderedCollectionsMatcher.cxx
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:   P Sherwood
+//
+// ********************************************************************
+//
+
+#include <algorithm>
+#include <stdexcept>
+#include <vector>
+#include <queue>
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/OrderedCollectionsMatcher.h"
+#include "xAODJet/Jet.h"
+#include "./DescendingEt.h"
+
+OrderedCollectionsMatcher::OrderedCollectionsMatcher(const Conditions& cs,
+						     const std::string& name):
+  Matcher(name), m_conditions(cs),m_pass(false){
+  ConditionsSorter sorterPred;
+
+  if(not std::is_sorted(m_conditions.begin(), m_conditions.end(), sorterPred))
+    {
+      std::sort(m_conditions.begin(), m_conditions.end(), sorterPred);
+    }
+}
+  
+void OrderedCollectionsMatcher::match(JetIter b, JetIter e){
+  
+  m_passed_jets.clear(); // allow monitoring of the jets that pass conditions.
+  m_failed_jets.clear();
+  if (b == e){
+    m_pass = false;
+    return;
+  }
+  
+  m_pass = true;
+  
+  // sort jets by descending eta
+  std::sort (b, e, DescendingEt());
+
+  std::queue<Conditions::value_type>  c_q;
+
+
+  std::queue<const xAOD::Jet*>  j_q;
+  for(auto i = b; i!=e; i++){j_q.push(*i);}
+
+  while (!c_q.empty()){
+    if (j_q.empty()){break;}
+    auto jet = j_q.front();
+    j_q.pop();
+    if (c_q.front().isSatisfied(jet)){
+      m_passed_jets.push_back(jet);
+      c_q.pop();
+    } else {
+      m_failed_jets.push_back(jet);
+    }
+  }
+
+  /* to pass , all conditions need to have been matched */
+
+  if (!c_q.empty()){m_pass = false;}  
+}
+
+bool OrderedCollectionsMatcher::pass() const {return m_pass;}
+
+std::pair<JetCIter, JetCIter> OrderedCollectionsMatcher::passed_iters() const {
+  return  std::pair<JetCIter, JetCIter> (m_passed_jets.begin(),
+                                         m_passed_jets.end());}
+
+std::pair<JetCIter, JetCIter> OrderedCollectionsMatcher::failed_iters() const {
+  return  std::pair<JetCIter, JetCIter> (m_failed_jets.begin(),
+                                         m_failed_jets.end());}
+
+
+
+std::string OrderedCollectionsMatcher::toString() const noexcept {
+  auto s = Matcher::toString();
+  for(auto c : m_conditions){ s += "\n" + c.toString();}
+  return s;
+}
+
+
+const Conditions& OrderedCollectionsMatcher::getConditions() const noexcept {
+  return m_conditions;
+}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SelectedJetsMatcher.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SelectedJetsMatcher.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7acca87be0d6029c45c57350a6c5df43c89343f5
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SelectedJetsMatcher.cxx
@@ -0,0 +1,104 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ********************************************************************
+//
+// NAME:     SelectedJetsMatcher.cxx
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:   P Sherwood
+//
+// Takes a vector of the indices used to select the jets from
+// the total jet collection, and pass them to the Conditions object.
+// This matcher was first used for the TLA analysis which
+// used TLAConditions objects.
+// ********************************************************************
+//
+
+#include <algorithm>
+#include <stdexcept>
+#include <vector>
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/SelectedJetsMatcher.h"
+#include "xAODJet/Jet.h"
+#include "./DescendingEt.h"
+
+SelectedJetsMatcher::SelectedJetsMatcher(const Conditions& cs,
+					 const std::vector<unsigned int>& indices,
+					 const std::string& name
+					 ):
+  Matcher(name), m_conditions(cs), m_indices(indices), m_pass(false){
+  
+  //sort the indices because the last one will be used to 
+  // check there are enough jets to process;
+  std::sort(m_indices.begin(), m_indices.end());
+}
+
+  
+void SelectedJetsMatcher::match(JetIter b, JetIter e){
+  
+  m_passed_jets.clear(); // allow monitoring of the jets that pass conditions.
+  m_failed_jets.clear();
+  if (b == e){
+    m_pass = false;
+    return;
+  }
+
+  // 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((e - b -1) < m_indices.back()){
+    unsigned int i = -1;
+    while (b + (++i) < e) {m_failed_jets.push_back(*(b+i));}
+    m_pass = false;
+    return;
+  }
+
+
+  // sort jets by descending eta
+  std::partial_sort (b, b + m_indices.size(),  e, DescendingEt());
+
+  std::vector<const xAOD::IParticle*> selected_jets;
+  for (auto i : m_indices){selected_jets.push_back(*(b+i));}
+  
+  //  Hypo passes if at least one condition object accepts the
+  // selected jets.
+  m_pass = false;
+  for(auto c : m_conditions){
+    if (c.isSatisfied(selected_jets)){
+      m_pass = true;
+      break;
+    }
+  }
+  
+  if(m_pass){
+    m_passed_jets.insert(m_passed_jets.end(), b, e);
+  } else {
+    m_failed_jets.insert(m_failed_jets.end(), b, e);
+  }
+}
+
+
+bool SelectedJetsMatcher::pass() const {return m_pass;}
+
+std::pair<JetCIter, JetCIter> SelectedJetsMatcher::passed_iters() const {
+  return  std::pair<JetCIter, JetCIter> (m_passed_jets.begin(),
+                                         m_passed_jets.end());}
+
+std::pair<JetCIter, JetCIter> SelectedJetsMatcher::failed_iters() const {
+  return  std::pair<JetCIter, JetCIter> (m_failed_jets.begin(),
+                                         m_failed_jets.end());}
+
+std::string SelectedJetsMatcher::toString() const noexcept{
+  std::stringstream ss;
+  ss <<  Matcher::toString();
+  for(auto c : m_conditions){ ss << "\n" <<  c.toString();}
+  ss << "\n indices[" << m_indices.size() <<"]: ";
+  for(auto i : m_indices){ss << i << " ";}
+  return ss.str();
+}
+
+
+const Conditions& SelectedJetsMatcher::getConditions() const noexcept {
+  return m_conditions;
+}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SingleEtaRegionMatcher.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SingleEtaRegionMatcher.cxx
deleted file mode 100644
index 1f6d4783b65261a72337529989714b30a51e726a..0000000000000000000000000000000000000000
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/SingleEtaRegionMatcher.cxx
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-// ********************************************************************
-//
-// NAME:     SingleEtaRegionMatcher.cxx
-// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
-//
-// AUTHOR:   P Sherwood
-//
-// ********************************************************************
-//
-
-#include <algorithm>
-#include <stdexcept>
-#include <vector>
-
-#include "./SingleEtaRegionMatcher.h"
-#include "xAODJet/Jet.h"
-#include "./DescendingEt.h"
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
-
-SingleEtaRegionMatcher::SingleEtaRegionMatcher(const Conditions& cs):m_conditions(cs), m_pass(false){
-  ConditionsSorter sorterPred;
-
-  if(not std::is_sorted(m_conditions.begin(), m_conditions.end(), sorterPred))
-    {
-      std::sort(m_conditions.begin(), m_conditions.end(), sorterPred);
-    }
-  
-  Condition first = m_conditions[0];
-  for (auto c : m_conditions) {
-    if (c.etaMin() != first.etaMin()){
-      throw std::runtime_error("more than 1 eta region");
-    }
-    if (c.etaMax() != first.etaMax()){
-      throw std::runtime_error("more than 1 eta region");
-    }
-  }
-}
-  
-void SingleEtaRegionMatcher::match(JetIter b, JetIter e){
-  // sort jets by descending eta
-  
-  m_passed_jets.clear(); // allow monitoring of the jets that pass conditions.
-  m_failed_jets.clear();
-  if (b == e){
-    m_pass = false;
-    return;
-  }
-  
-  m_pass = true;
-  
-  // select jets in the eta range - which is common for all conditions
-  // caller guarantees m_conditions.size() > 0 
-  const Condition& c = m_conditions[0];
-
-  e = std::partition(b, e, [&](const xAOD::Jet* j){return c.etaOK(j);});
-  
-  int n_conds = m_conditions.size();
-  int n_jets = e - b;
-  
-  bool not_enough_jets = n_jets < n_conds;
-
-  /* continue processing even if the number of jets is less
-     than the number of conditions to allow debug of good and bad jets */
-  if (not_enough_jets){
-    std::sort (b, e, DescendingEt());
-    }else{
-    /* Only the first n_conds jets from the ordered jet vector
-       can contribute to the success of the event. Copy the rest to 
-       the bad jet vector */
-    std::partial_sort (b, b + n_conds, e, DescendingEt());
-    m_failed_jets.assign(b + n_conds,  e);
-    }
-  
-  // zip the conditions and jet collection iterators
-  // with length being the shorter of the two collections.
-  using IterPair = std::pair<ConditionsIter, JetCIter>;
-  
-  std::vector<IterPair> zip;
-  std::size_t zipLen = std::min(n_conds, n_jets);
-
-  for(std::size_t i = 0; i != zipLen; ++i) {
-    zip.push_back(IterPair(m_conditions.begin() + i, b + i));}
-  
-  /* while there are are more jet-condition pairs, check whether
-     the jet matches the condition. If it does, and there has
-     been no previous failure, add it to the good jets vector.
-     Otherwise add it to the bad jets vector */
-
-  for(auto iters : zip){
-    auto ci = iters.first; auto ji = iters.second;
-    if(m_pass){
-
-      if (ci->allOK((*ji))){m_passed_jets.push_back(*ji);
-      } else {
-        m_pass = false;
-        m_failed_jets.push_back(*ji);
-      }
-
-    } else {
-      m_failed_jets.push_back(*ji);
-    }
-  }
-
-  /* to pass , all thresholds in zipped jets - conditions need to pass
-     and there have to be enough jets */
-  if (not_enough_jets){m_pass = false;}  
-}
-
-bool SingleEtaRegionMatcher::pass() const {return m_pass;}
-
-std::pair<JetCIter, JetCIter> SingleEtaRegionMatcher::passed_iters() const {
-  return  std::pair<JetCIter, JetCIter> (m_passed_jets.begin(),
-                                         m_passed_jets.end());}
-
-std::pair<JetCIter, JetCIter> SingleEtaRegionMatcher::failed_iters() const {
-  return  std::pair<JetCIter, JetCIter> (m_failed_jets.begin(),
-                                         m_failed_jets.end());}
-
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TLACondition.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TLACondition.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4fcb1dd08ce64bafb7173c12371467e7ba7eb7dd
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TLACondition.cxx
@@ -0,0 +1,74 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/TLACondition.h"
+#include <sstream>
+#include <exception>
+
+
+TLACondition::TLACondition(double etaMin, double etaMax,
+			   double ystarMin, double ystarMax,
+			   double massMin, double massMax): 
+  m_etaMin(etaMin), m_etaMax(etaMax), 
+  m_ystarMin(ystarMin), m_ystarMax(ystarMax), 
+  m_massMin(massMin), m_massMax(massMax){
+}
+
+bool TLACondition::isSatisfied(const xAOD::IParticle*) const {
+  std::stringstream ss;
+  ss << "TLA::isSatisfied must see exactly 2 particles, but recieved 1\n";
+  throw std::runtime_error(ss.str());
+}
+
+bool
+TLACondition::isSatisfied(const std::vector<const xAOD::IParticle*>& ips) const{
+  if(ips.size() != 2){
+    std::stringstream ss;
+    ss << "TLA::isSatisfied must see exactly 2 particles, but recieved "
+       << ips.size()
+       << '\n';
+    
+    throw std::runtime_error(ss.str());
+  }
+
+  auto p4_0 = ips[0]->p4();
+  auto p4_1 = ips[1]->p4();
+  auto mass = (p4_0 + p4_1).M();
+  auto eta0 =  p4_0.Eta();
+  auto eta1 =  p4_1.Eta();
+  auto ystar = std::abs(eta0 - eta1);
+
+    
+  return 
+    m_etaMin <= eta0 and
+    m_etaMin <= eta1 and
+    m_etaMax > eta0 and
+    m_etaMax  > eta1 and
+    m_ystarMin <= ystar and
+    m_ystarMax > ystar and
+    m_massMin <= mass and
+    m_massMax > mass;
+}
+
+std::string TLACondition::toString() const noexcept {
+  std::stringstream ss;
+  ss << "Condition: etaMin "
+     <<  m_etaMin 
+     << " etaMax " 
+     << m_etaMax 
+     << " ystart min: " 
+     << m_ystarMin
+     << " ystart max: " 
+     << m_ystarMax
+     << " mass min: " 
+     << m_massMin
+     << " mass max: " 
+     << m_massMax
+     <<'\n';
+
+  return ss.str();
+}
+
+
+double TLACondition::orderingParameter() const noexcept {return m_massMin;}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.cxx
index b7b003d3d9c69b8d5f881bc5dd11605d84c1d09b..7c3d1a17fe8ffc30ddf8e781de385e64a416351a 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.cxx
@@ -58,3 +58,19 @@ bool TightCleaner::operator()(const xAOD::Jet* jet) const {
   return isClean;
 
 }
+
+std::string TightCleaner::toString() const noexcept {
+  std::stringstream ss;
+  ss << getName() 
+     <<  ":"
+     << " fSampMaxTightThreshold " << m_fSampMaxTightThreshold
+     << " etaTightThreshold " << m_etaTightThreshold
+     << " emfLowTightThreshold " << m_emfLowTightThreshold
+     << " emfHighTightThreshold " << m_emfHighTightThreshold
+     << " hecfTightThreshold " << m_hecfTightThreshold
+     << '\n';
+  return ss.str();
+}
+
+
+std::string TightCleaner::getName() const noexcept {return "TightCleaner";}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.h
index 76d8e4c263c16d665befe71207a3154c5a82b5f2..be144b72e512bc190c6f3e82c2a4381312080ac9 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.h
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TightCleaner.h
@@ -16,7 +16,7 @@
 // ********************************************************************
 //
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" //ICleaner
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ICleaner.h"
 #include "xAODJet/Jet.h"
 
 class TightCleaner: public ICleaner{
@@ -28,7 +28,11 @@ class TightCleaner: public ICleaner{
                float emfHighTightThreshold,
                float hecfTightThreshold);
   
+  ~TightCleaner() {}
+
   bool operator()(const xAOD::Jet* jet) const override;
+  std::string toString() const noexcept override;
+  std::string getName() const noexcept override;
 
  private:
   float m_fSampMaxTightThreshold;
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TrigHLTJetHypoUtils.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TrigHLTJetHypoUtils.cxx
deleted file mode 100644
index 0a23d17ceeadff80f33161340082205e0b9269d0..0000000000000000000000000000000000000000
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/TrigHLTJetHypoUtils.cxx
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h"
-
-/* WORK IN PROGRESS _ DO NOT USE ! */
-
-Condition::Condition(double etaMin, double etaMax, double threshold): 
-  m_etaMin(etaMin), m_etaMax(etaMax), m_threshold(threshold){}
-
-bool Condition::etaOK(const xAOD::IParticle* ip) const noexcept {
-  if (std::abs(ip->eta()) < m_etaMin){return false;}
-  if (std::abs(ip->eta()) >= m_etaMax){return false;}
-  return true;
-}
-
-bool Condition::etOK(const xAOD::IParticle* ip) const noexcept {
-  if ((ip->p4()).Et() < threshold()){return false;}
-  return true;
-}
-
-bool Condition::allOK(const xAOD::IParticle* ip) const noexcept {
-  return etaOK(ip) && etOK(ip);
-}
-
-double Condition::etaMin() const noexcept {return m_etaMin;}
-double Condition::etaMax() const noexcept {return m_etaMax;}
-double Condition::threshold() const noexcept {return m_threshold;}
-
-//////////////////////////////////////////////////////////////////
-std::ostream& operator<< (std::ostream& os, const Condition& c){
-  return os << "Condition: etaMin "
-            << c.etaMin() 
-            << " etaMax " 
-            << c.etaMax() 
-            << " threshold: " 
-            << c.threshold()
-            <<'\n';
-}
-
-
-bool ConditionsSorter::operator()(const Condition& l, const Condition& r){
-  return l.threshold() > r.threshold();
-}
-
-
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/cleanerFactory.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/cleanerFactory.cxx
deleted file mode 100644
index 1c47a22b722fadb5bf5f8f7f2715f8f6de7028b3..0000000000000000000000000000000000000000
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/cleanerFactory.cxx
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-// ********************************************************************
-//
-// NAME:     cleanerFactory.cxx
-// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
-//
-// AUTHOR:   P Sherwood
-//
-// ********************************************************************
-//
-
-
-#include <stdexcept>
-#include <memory>
-
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // ICleaner
-#include "./cleanerFactory.h"
-
-#include "./BasicCleaner.h"
-#include "./AntiBasicCleaner.h"
-#include "./LooseCleaner.h"
-#include "./AntiLooseCleaner.h"
-#include "./TightCleaner.h"
-#include "./AntiTightCleaner.h"
-#include "./LlpCleaner.h"
-#include "./AntiLlpCleaner.h"
-#include "./NullCleaner.h"
-
-std::shared_ptr<ICleaner>
-cleanerFactory(//basic cleaning
-	       double m_n90Threshold,
-               double m_presamplerThreshold,
-               double m_negativeEThreshold,
-               //loose cleaning
-               double m_fSampMaxLooseThreshold,
-               double m_etaLooseThreshold,
-               double m_emfLowLooseThreshold,
-               double m_emfHighLooseThreshold,
-               double m_hecfLooseThreshold,
-               //tight cleaning
-               double m_fSampMaxTightThreshold,
-               double m_etaTightThreshold,
-               double m_emfLowTightThreshold,
-               double m_emfHighTightThreshold,
-               double m_hecfTightThreshold,
-               //long-lived particle cleaning
-               double m_fSampMaxLlpThreshold,
-               double m_negELlpThreshold,
-               double m_hecfLlpThreshold,
-               double m_hecqLlpThreshold,
-               double m_avLarQFLlpThreshold,
-               //cleaning mode
-               const std::string& key){
-
-  using pIC = std::shared_ptr<ICleaner>;
-
-  if (key == "basicCleaning"){
-    return pIC (new BasicCleaner(m_n90Threshold, 
-                                 m_presamplerThreshold,
-                                 m_negativeEThreshold));
-
-  } else if (key == "antiBasicCleaning"){
-    return pIC (new AntiBasicCleaner(m_n90Threshold, 
-                                     m_presamplerThreshold,
-                                     m_negativeEThreshold));
-  } else if (key == "looseCleaning"){
-    return pIC (new LooseCleaner(m_fSampMaxLooseThreshold,
-                                 m_etaLooseThreshold,
-                                 m_emfLowLooseThreshold,
-                                 m_emfHighLooseThreshold,
-                                 m_hecfLooseThreshold));
-  } else if (key == "antiLooseCleaning"){
-    return pIC (new AntiLooseCleaner(m_fSampMaxLooseThreshold,
-                                     m_etaLooseThreshold,
-                                     m_emfLowLooseThreshold,
-                                     m_emfHighLooseThreshold,
-                                     m_hecfLooseThreshold));
-  } else if (key == "tightCleaning"){
-    return pIC (new TightCleaner(m_fSampMaxTightThreshold,
-                                 m_etaTightThreshold,
-                                 m_emfLowTightThreshold,
-                                 m_emfHighTightThreshold,
-                                 m_hecfTightThreshold));
-  } else if (key == "antiTightCleaning"){
-    return pIC (new AntiTightCleaner(m_fSampMaxTightThreshold,
-                                     m_etaTightThreshold,
-                                     m_emfLowTightThreshold,
-                                     m_emfHighTightThreshold,
-                                     m_hecfTightThreshold));
-  } else if (key == "llpCleaning"){
-    return pIC (new LlpCleaner(m_fSampMaxLlpThreshold,
-                               m_negELlpThreshold,
-                               m_hecfLlpThreshold,
-                               m_hecqLlpThreshold,
-                               m_avLarQFLlpThreshold));
-  } else if (key == "antiLlpCleaning"){
-    return pIC (new AntiLlpCleaner(m_fSampMaxLlpThreshold,
-                                   m_negELlpThreshold,
-                                   m_hecfLlpThreshold,
-                                   m_hecqLlpThreshold,
-                                   m_avLarQFLlpThreshold));
-  } else if (key == "noCleaning"){
-    return pIC (new NullCleaner);
-
-  } else {
-    throw std::invalid_argument{"Unknown cleaner specified :" + key};
-
-  }
-}
-
-
-
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/cleanerFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/cleanerFactory.h
deleted file mode 100644
index fc6b7927947d00366db090dba98899616f082a9e..0000000000000000000000000000000000000000
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/cleanerFactory.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TRIGJETHYPO_CLEANERFACTORY_H
-#define TRIGJETHYPO_CLEANERFACTORY_H
-
-
-// ********************************************************************
-//
-// NAME:     cleanerFactory.h
-// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
-//
-// AUTHOR:  P Sherwood
-//
-// ********************************************************************
-//
-
-#include <memory>
-#include <string>
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // ICleaner
-
-std::shared_ptr<ICleaner> cleanerFactory(double, double, double,
-					 double, double, double, double, double, 
-					 double, double, double, double, double, 
-					 double, double, double, double, double, 
-                                         const std::string&);
-#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/conditionsFactory.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/conditionsFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2505a4637c1e6b9390bc133f368f40e1e3e45ec5
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/conditionsFactory.cxx
@@ -0,0 +1,61 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ********************************************************************
+//
+// NAME:     conditionsFactory.cxx
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:   P Sherwood
+//
+// ********************************************************************
+//
+
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/EtaEtCondition.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/TLACondition.h"
+#include "./conditionsFactory.h"
+
+
+Conditions conditionsFactory(const std::vector<double>& etaMins,
+			     const std::vector<double>& etaMaxs,
+			     const std::vector<double>& thresholds){
+
+  Conditions conditions;
+  for (std::size_t i = 0; i != thresholds.size(); ++i){
+    
+    std::shared_ptr<ICondition> pCondition(new EtaEtCondition(etaMins[i],
+							      etaMaxs[i], 
+							      thresholds[i]));
+    
+      conditions.push_back(ConditionBridge(pCondition));
+  }
+  return conditions;
+}
+
+
+Conditions conditionsFactory(const std::vector<double>& etaMins,
+			     const std::vector<double>& etaMaxs,
+			     const std::vector<double>& ystarMins,
+			     const std::vector<double>& ystarMaxs,
+			     const std::vector<double>& massMins,
+			     const std::vector<double>& massMaxs){
+  
+  Conditions conditions;
+  for (std::size_t i = 0; i != etaMins.size(); ++i){
+    
+    std::shared_ptr<ICondition> pCondition(new TLACondition(etaMins[i],
+							    etaMaxs[i], 
+							    ystarMins[i],
+							    ystarMaxs[i],
+							    massMins[i],
+							    massMaxs[i]));
+    
+    conditions.push_back(ConditionBridge(pCondition));
+  }
+  return conditions;
+}
+
+
+
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/conditionsFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/conditionsFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..f24afc6e88f583f77a1ccfaa285ed0841e674ed7
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/conditionsFactory.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_CONDITIONSFACTORY_H
+#define TRIGJETHYPO_CONDITIONSFACTORY_H
+
+// ********************************************************************
+//
+// NAME:     conditionsFactory.h
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:  P Sherwood
+//
+// ********************************************************************
+//
+
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/ConditionsDefs.h"
+
+Conditions conditionsFactory(const std::vector<double>& etasMin,
+			     const std::vector<double>& etasMax,
+			     const std::vector<double>& thresholds);
+
+Conditions conditionsFactory(const std::vector<double>& etasMin,
+			     const std::vector<double>& etasMax,
+			     const std::vector<double>& ystarsMin,
+			     const std::vector<double>& ystarsMax,
+			     const std::vector<double>& massesMin,
+			     const std::vector<double>& massesMax);
+
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/lineSplitter.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/lineSplitter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6195d8a3730d9c1d9a349c508a388ea502f6e814
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/lineSplitter.cxx
@@ -0,0 +1,20 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/lineSplitter.h"
+#include <sstream>
+
+std::vector<std::string> lineSplitter(const std::string& s, 
+				      char delimiter){
+  
+  std::stringstream line (s);
+  std::string seg;
+  std::vector<std::string> segs;
+
+  while(std::getline(line, seg, delimiter)){
+    segs.push_back(seg);
+  }
+  
+  return segs;
+}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactory.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactory.cxx
index ff5c63b0644b00001ebde616aca270e894a55e96..ba2c4ae987284d634592a6f3c2cc26aa62690973 100644
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactory.cxx
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactory.cxx
@@ -4,40 +4,58 @@
 
 // ********************************************************************
 //
-// NAME:     cleanerFactory.cxx
+// NAME:     matcherFactory.cxx
 // PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
 //
 // AUTHOR:   P Sherwood
 //
+// IMatcherFactoryFactory - returns a Factory that creates a concrete Factory
+//                          and returns it as an IMatcherFactory.
+// IMatcherFactory - returns a Matcher as an IMatcher.The IMatcherFactory will
+//                   be used each event to create a fresh  IMatcher
+// MaximumBipartiteMatcher - concrete matcher type
+// OrderedCollectionsMatcher - concrete matcher type
+// SelectedJetsMatcher - concrete matcher type
 // ********************************************************************
 //
 
 
 #include <stdexcept>
+#include <sstream>
 #include <memory>
 
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // IMatcher
-#include "./matcherFactory.h"
-#include "./MaximumBipartiteMatcher.h"
-#include "./SingleEtaRegionMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/IMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/matcherFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/MaximumBipartiteMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/OrderedCollectionsMatcher.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/SelectedJetsMatcher.h"
 
-std::shared_ptr<IMatcher> 
-matcherFactory(const Conditions & conditions,
-               const std::string& key){
+using pIM = std::shared_ptr<IMatcher>;
 
-  using pIM = std::shared_ptr<IMatcher>;
-
-  if (key == "maximumBipartite"){
-    return pIM(new MaximumBipartiteMatcher(conditions));
-
-  } else if (key == "singleEtaRegion") {
-    return pIM(new SingleEtaRegionMatcher(conditions));
+MaximumBipartiteMatcherFactory::MaximumBipartiteMatcherFactory(const Conditions & conditions,
+							       const std::string& key): 
+  m_conditions(conditions), m_name(key){
+}
 
-  } else {
-     throw std::invalid_argument{"Unknown matcher specified :" + key};
+pIM MaximumBipartiteMatcherFactory::make() const { 
+  return pIM(new MaximumBipartiteMatcher(m_conditions, m_name));
+}
 
-  }
+OrderedCollectionsMatcherFactory::OrderedCollectionsMatcherFactory(const Conditions & conditions,
+								   const std::string& key): 
+  m_conditions(conditions), m_name(key){
 }
 
+pIM OrderedCollectionsMatcherFactory::make() const { 
+  return pIM(new OrderedCollectionsMatcher(m_conditions, m_name));
+}
 
+SelectedJetsMatcherFactory::SelectedJetsMatcherFactory(const Conditions& conditions,
+						       const std::vector<unsigned int>& indices,
+						       const std::string& key) : 
+  m_conditions(conditions), m_indices(indices), m_name(key){
+}
 
+pIM SelectedJetsMatcherFactory::make() const { 
+  return pIM(new SelectedJetsMatcher(m_conditions, m_indices, m_name));
+}
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactory.h b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactory.h
deleted file mode 100644
index b2285594a1db2acd3eab7f4e2f9acc561ba806f5..0000000000000000000000000000000000000000
--- a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactory.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef TRIGJETHYPO_MATCHERFACTORY_H
-#define TRIGJETHYPO_MATCHERFACTORY_H
-
-// ********************************************************************
-//
-// NAME:     matcherFactory.h
-// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
-//
-// AUTHOR:  P Sherwood
-//
-// ********************************************************************
-//
-
-#include <memory>
-#include <string>
-
-#include "TrigJetHypo/TrigHLTJetHypoUtils/TrigHLTJetHypoUtils.h" // IMatcher
-
-std::shared_ptr<IMatcher> matcherFactory(const Conditions&,
-                                         const std::string&);
-
-
-#endif
diff --git a/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactoryFactory.cxx b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactoryFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..50f9e2b675cc3f56a2853a90cda6226f7d90c607
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigJetHypo/src/TrigHLTJetHypoHelpers/matcherFactoryFactory.cxx
@@ -0,0 +1,63 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ********************************************************************
+//
+// NAME:     matcherFactoryFactory.cxx
+// PACKAGE:  Trigger/TrigHypothesis/TrigJetHypo
+//
+// AUTHOR:   P Sherwood
+//
+// IMatcherFactoryFactory - returns a Factory that creates a concrete Factory
+//                          and returns it as an IMatcherFactory.
+// ********************************************************************
+//
+
+
+#include <stdexcept>
+#include <memory>
+
+#include "TrigJetHypo/TrigHLTJetHypoUtils/matcherFactoryFactory.h"
+#include "TrigJetHypo/TrigHLTJetHypoUtils/matcherFactory.h"
+
+
+std::shared_ptr<IMatcherFactory> 
+matcherFactoryFactory(const Conditions & conditions,
+		      const std::string& key){
+
+  if (key == "maximumBipartite"){
+    IMatcherFactory* imf = new MaximumBipartiteMatcherFactory(conditions, key);
+    return std::shared_ptr<IMatcherFactory>(imf);
+  } else if (key == "orderedCollections"){
+    IMatcherFactory* imf = new OrderedCollectionsMatcherFactory(conditions,
+								key);
+    return std::shared_ptr<IMatcherFactory>(imf);
+  } else {
+    std::stringstream ss;
+    auto m =  "matcherFactory: unknown key to make a matcher factory" + key;
+    throw std::runtime_error(m);
+  }
+}
+
+
+std::shared_ptr<IMatcherFactory> 
+matcherFactoryFactory(const Conditions & conditions,
+		      const std::vector<unsigned int> indices,
+		      const std::string& key){
+
+  if (key == "selectedJets"){
+    IMatcherFactory* imf = new SelectedJetsMatcherFactory(conditions,
+							  indices,
+							  key);
+    return std::shared_ptr<IMatcherFactory>(imf);
+  } else {
+    std::stringstream ss;
+    ss << "matcherFactory: unknown key to make a matcher factory" 
+       << key 
+       << '\n';
+    
+    throw std::runtime_error(ss.str());
+  }
+}
+