diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
index c940256da44619e516dd65a9bb909dad7e12914f..47727546e9e0ddf7e0721df28592dcdb4dc9571f 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
@@ -213,6 +213,7 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
         uint16_t featureIndex = 0, roiIndex = 0;
         // NOTE: roiKey, roiIndex not currently used in this discrimination
         ATH_CHECK( extractFeatureAndRoI(dEL, featureKey, featureIndex, roiKey, roiIndex) );
+	// TODO: move this to InitialRoI for serial merging
         const uint32_t featureHash = (featureKey + featureIndex); 
         if (featureHash == 0) {
           ATH_MSG_WARNING("Disregarding feature hash of zero");
@@ -237,7 +238,6 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
     ATH_MSG_DEBUG( "Chain " << chainId <<  ( overallDecision ? " is accepted" : " is rejected")  <<" after multiplicity requirements" );
     if ( overallDecision == true ) {
       for (auto decID: allDecisionIds) {
-	//        passing.insert( passing.end(), decID );
 	// saving the good combiantions
 	goodMultCombMap.insert (thisChainCombMap.begin(), thisChainCombMap.end());
         ATH_MSG_DEBUG("  Passing " << HLT::Identifier(decID)<<" after multiplicity test");
@@ -245,18 +245,18 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
     }      
   }
 
-  // launching the tools:
-  ///////////////////////
-    LegDecisionsMap  passingLegs;
+  LegDecisionsMap passingLegs;
+  if  (goodMultCombMap.size()!=0){
+    // launching the tools:
+    ///////////////////////
     if (m_hypoTools.size()>0){
       for ( auto& tool: m_hypoTools ) {
 	ATH_MSG_DEBUG( "Calling  tool "<<tool->name());
 	ATH_CHECK( tool->decide( goodMultCombMap, passingLegs ) );
       }
     }
-    else{
-      passingLegs = goodMultCombMap;
-     }
+    else  passingLegs=goodMultCombMap;
+  }
 
     // this is only for debug:
     if (msgLvl(MSG::DEBUG)){
@@ -281,6 +281,7 @@ StatusCode ComboHypo::extractFeatureAndRoI(const ElementLink<DecisionContainer>&
   uint32_t featureClid = 0; // Note: Unused. We don't care what the type of the feature is here
   const bool result = (*dEL)->typelessGetObjectLink(featureString(), featureKey, featureClid, featureIndex);
   if (!result) {
+    // WARNING?
     ATH_MSG_ERROR("Did not find the feature for " << dEL.dataID() << " index " << dEL.index());
   }
   // Try and get seeding ROI data too. Don't need to be type-less here
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h
index dcf85ccb7f343f48da785dcc102d2fa9edb7496e..e633649aa59efdcdbb0b4d5ed8c388e5e61d03c0 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h
@@ -11,7 +11,7 @@
 // STL includes
 #include <string>
 #include <utility>  
-#include "IComboHypoTool.h"
+#include "ComboHypoToolBase.h"
 
 /**
  * @class ComboHypo for combined hypotheses required only counting (multiplicity requirements)
@@ -73,7 +73,7 @@ private:
 
   StatusCode fillDecisionsMap( LegDecisionsMap& dmap, const EventContext& context) const;
 
-  ToolHandleArray< IComboHypoTool > m_hypoTools {this, "ComboHypoTools", {}, "Tools to perform selection"};
+  ToolHandleArray< ComboHypoToolBase > m_hypoTools {this, "ComboHypoTools", {}, "Tools to perform selection"};
 
 };
 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypoToolBase.cxx b/Trigger/TrigSteer/DecisionHandling/src/ComboHypoToolBase.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7f181f75667d5bbec43e8b9eda6eb33f13599d6b
--- /dev/null
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypoToolBase.cxx
@@ -0,0 +1,174 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ComboHypoToolBase.h"
+using namespace TrigCompositeUtils;
+
+
+ComboHypoToolBase::ComboHypoToolBase(const std::string& type, const std::string& name, const IInterface* parent) :
+  base_class(type, name, parent),
+  m_decisionId(  HLT::Identifier::fromToolName( name ) )
+{}
+
+
+StatusCode ComboHypoToolBase::decide(const LegDecisionsMap & IDCombMap, LegDecisionsMap & passingCombinations ) const
+{
+  // if no combinations passed, then exit 
+  size_t nLegs=IDCombMap.size();
+  if (nLegs==0)  return StatusCode::SUCCESS;
+  
+  //  check that no other toold have efilled the map with this id
+   ATH_CHECK( passingCombinations[decisionId()].empty() );
+ 
+   ATH_MSG_DEBUG( "Looking for "<< decisionId() <<" in the map. Map contains "<<nLegs<<" legs");
+
+   // select the leg decisions from  the map with this ID:
+   std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> leg_decisions;
+   ATH_CHECK( selectLegs(IDCombMap, leg_decisions) );
+
+   if (leg_decisions.size() == 0) {
+     ATH_MSG_INFO("Found 0 legs with this DecisionID: something failed?");
+     return StatusCode::SUCCESS;
+   }
+   
+   // create the combinations between the legs
+   std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> combinations;
+   createCombinations( leg_decisions, combinations,  nLegs, 2);
+
+   
+   // do the actual algorithm and select the decisions that passed
+   for (ElementLinkVector<TrigCompositeUtils::DecisionContainer> thecomb: combinations){
+     // to add: protection when the two decisions are the same object
+     bool pass = executeAlg(thecomb);
+     if (pass){
+       setDecisionIds(thecomb, passingCombinations);
+     }
+   }
+  
+   printExecute(passingCombinations);
+   return StatusCode::SUCCESS;
+
+}
+
+StatusCode ComboHypoToolBase::selectLegs(const LegDecisionsMap & IDCombMap, std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>>& leg_decisions) const
+{
+  size_t nLegs=IDCombMap.size();
+  if (nLegs==0)  return StatusCode::SUCCESS;
+  
+  // collect combinations from all the legs, searching both chain name and leg name
+  for (auto id: IDCombMap){
+    // get the Element links from the chainID (from all the legs)
+    HLT::Identifier chainId=0;
+    if (TrigCompositeUtils::isLegId(id.first))
+      chainId= TrigCompositeUtils::getIDFromLeg(id.first);
+    else
+      chainId=id.first;
+    if ( chainId != decisionId() ) continue;    
+    auto comb = id.second; 
+    leg_decisions.push_back(comb);
+  }
+
+  if (nLegs != leg_decisions.size()){
+    ATH_MSG_ERROR("Expecting "<<nLegs<<" legs, but found "<< leg_decisions.size() <<" legs to combine");
+    return StatusCode::FAILURE;
+  }
+  
+  ATH_MSG_DEBUG("Getting "<<leg_decisions.size()<<" legs to combine, for ID: "<< decisionId());
+  for (auto leg: leg_decisions){
+    ATH_MSG_DEBUG("Leg --");
+    for (auto dEL:leg) ATH_MSG_DEBUG(dEL.dataID() << " , " << dEL.index());
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+// Include case of one leg and multiple legs with mult=1 on each leg. Need to be exended to cover cases with multiple legs qith different multiplicities (2mu_3e)
+void ComboHypoToolBase::createCombinations(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & v_legs,
+			  std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & combinations, int nLegs, int nToGroup) const
+{
+  if (nLegs ==1) {
+    auto elements = v_legs[0];
+    std::vector<int> selector(elements.size());
+    fill(selector.begin(), selector.begin() + nToGroup, 1);
+    ElementLinkVector<TrigCompositeUtils::DecisionContainer> thecomb;
+    do {
+      for (u_int i = 0; i < elements.size(); i++) {
+	if (selector[i]) {
+	  thecomb.push_back(elements[i]);
+	}
+      }
+      combinations.push_back(thecomb);    
+      thecomb.clear();
+    }  while (std::prev_permutation(selector.begin(), selector.end()));
+  }
+
+  else {
+    ElementLinkVector<TrigCompositeUtils::DecisionContainer> local;
+    recursive_combine(v_legs, combinations, local, 0);
+  }
+
+  for (auto comb: combinations){
+    ATH_MSG_DEBUG("Combination");
+    for (auto dEL :comb){
+      ATH_MSG_DEBUG(dEL.dataID() << " , " << dEL.index());
+    }
+  }
+  return;
+}
+
+
+void ComboHypoToolBase::setDecisionIds(const ElementLinkVector<TrigCompositeUtils::DecisionContainer>& thecomb, LegDecisionsMap & passingCombinations) const {
+
+  for (ElementLink<TrigCompositeUtils::DecisionContainer> dEL: thecomb){
+    const TrigCompositeUtils:: Decision* decision= (*dEL);
+    // get back the decID of this element
+    const std::vector<DecisionID>& allDecIDs = TrigCompositeUtils::decisionIDs( decision );
+    ATH_MSG_DEBUG( dEL.dataID() << " , " << dEL.index() <<"  with "<<allDecIDs.size() <<" decisionIDs");
+    for (auto id: allDecIDs){
+      if ((HLT::Identifier(id).name()).find(decisionId().name())!=std::string::npos){
+	// we may have this element already stored, so there might be duplications
+	// add to both legID and chainID?
+	passingCombinations[id].push_back(dEL);
+	passingCombinations[ decisionId() ].push_back(dEL);
+      }
+    }
+  }
+
+  // remove duplicates?
+  return;
+}
+
+
+
+StatusCode ComboHypoToolBase::printExecute(const LegDecisionsMap & passingCombinations) const {
+  ATH_MSG_DEBUG("End of tool: Passing elments are: ");
+  for  (auto id: passingCombinations){
+    ATH_MSG_DEBUG("Id "<<HLT::Identifier(id.first)<<" with "<<id.second.size()<<" elements");
+    for (auto dEL: id.second){
+      ATH_MSG_DEBUG( dEL.dataID() << " , " << dEL.index());
+    }
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+void ComboHypoToolBase::recursive_combine(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> &all,
+			 std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & tocombine,
+			 ElementLinkVector<TrigCompositeUtils::DecisionContainer> & local, u_int lindex)  const
+{
+  
+  for (size_t leg =lindex; leg<all.size(); leg++){
+    for (size_t i=0; i<all[leg].size(); i++){
+      local.push_back(all[leg][i]);
+      recursive_combine(all, tocombine,local, leg+1);
+      local.pop_back(); 
+    }
+  }
+  if (local.size() == all.size())
+    tocombine.push_back(local);
+ 
+ return;
+ 
+}
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypoToolBase.h b/Trigger/TrigSteer/DecisionHandling/src/ComboHypoToolBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..b00ff90e018c937c36e255e2cd1db5ff5e19c6dc
--- /dev/null
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypoToolBase.h
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef DECISIONHANDLING_COMBOHYPOTOOLBASE_H
+#define DECISIONHANDLING_COMBOHYPOTOOLBASE_H
+
+// Package includes
+#include "IComboHypoTool.h"
+
+// Framework includes
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DecisionHandling/HLTIdentifier.h"
+#include "DecisionHandling/TrigCompositeUtils.h"
+
+// STL includes
+#include <string>
+
+/**
+ * @class ComboHypoToolBase
+ * @brief
+ **/
+
+
+class ComboHypoToolBase : public extends<AthAlgTool, IComboHypoTool> {
+
+public:
+  ComboHypoToolBase(const std::string& type, const std::string& name, const IInterface* parent);
+
+  
+  /**
+   * @brief retreives the decisions associated to this decId, make their combinations and apply the algorithm
+   @param[in]  InputDecisions
+   @param[in]  Cobminaiton map that lists all the decisions passing the multiplicity map of the ComboHypo
+   @param[out] Combination map that lists all the decisions passing the HypoTool algorithm
+  **/  
+  virtual StatusCode decide(const LegDecisionsMap & IDCombMap,LegDecisionsMap & passingCombinations ) const override;
+  
+  
+  /**
+   * @brief retrieves this decision Id
+   **/
+  virtual HLT::Identifier decisionId() const { return m_decisionId; } 
+
+    
+ protected:
+
+  /**
+  * @brief creates the decision legs starting from the initial LegDecision map, storing only those concerning this decisionID
+  **/
+  StatusCode selectLegs(const LegDecisionsMap & IDCombMap, std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>>& leg_decisions) const;
+    
+   /**
+  * @brief creates combinations of decisions starting from the legs vector of pairs, given the number of legs and the number of elements to combine
+    @param[in] v_legs: vector of legs (vector), each containing the corresponding decision pairs
+    @param[in] nLegs: number of legs to combine
+    @param[in] nToGroup: number of elements to group in a combination, in case one leg is used
+    @param[out] combinations: vector of combinations (vectors) of decision pairs
+  **/
+  void createCombinations(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & v_legs,
+			  std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & combinations, int nLegs, int nToGroup) const;
+
+  /**
+  * @brief recursively creates combinations of elements from differnt vectors
+    @param[in] all: initial vector of decision legs
+    @parma[in] local: temporary vector of combinations
+    @param[in] lindex: leg index
+    @param[out] tocombine: vector of combinations
+  **/
+  void recursive_combine(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> &all,
+			 std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & tocombine,
+			 ElementLinkVector<TrigCompositeUtils::DecisionContainer> & local, u_int lindex)  const;
+
+
+  /**
+  * @brief contains the real algorithm to apply on the given combination of decisions
+  **/
+  virtual bool executeAlg(ElementLinkVector<TrigCompositeUtils::DecisionContainer>& /* thecomb  */) const {return true;}
+
+  
+ /**
+  * @brief Retrieves the decisionIds from the passing combinations and produce a new LegDecisionMap
+  **/
+  void setDecisionIds(const ElementLinkVector<TrigCompositeUtils::DecisionContainer>& thecomb, LegDecisionsMap & passingCombinations) const;
+
+
+  /**
+  * @brief Print the Tool results stored in the passing combinations
+  **/
+
+  StatusCode printExecute(const LegDecisionsMap & passingCombinations) const;
+
+
+// add here WriteHandkles of combinations
+  
+private:
+
+    HLT::Identifier m_decisionId;
+    
+
+};
+
+#endif // DECISIONHANDLING_COMBOHYPOTOOLBASE_H
diff --git a/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.cxx b/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.cxx
index dfdc36f308fbff23e01f8a554174a025c5aee6cd..6ae343487d76f723c1f89c424c4cc76b9e478028 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.cxx
@@ -6,124 +6,47 @@
 using namespace TrigCompositeUtils;
 
 DeltaRRoIComboHypoTool::DeltaRRoIComboHypoTool(const std::string& type,
-					 const std::string& name,
-					 const IInterface* parent)
-  : IComboHypoTool( name ),
-    AthAlgTool( type, name, parent )
+					       const std::string& name,
+					       const IInterface* parent)
+  : ComboHypoToolBase(type, name, parent)
 { }
 
-DeltaRRoIComboHypoTool::~DeltaRRoIComboHypoTool(){}
-
 
 StatusCode DeltaRRoIComboHypoTool::initialize() {
   ATH_MSG_DEBUG("DR threshold set to " << m_DRcut );
   return StatusCode::SUCCESS;
 }
 
-StatusCode DeltaRRoIComboHypoTool::finalize() {
-  return StatusCode::SUCCESS;
-}
 
 
-StatusCode DeltaRRoIComboHypoTool::decide(const LegDecisionsMap & IDCombMap, LegDecisionsMap & passingCombinations ) const
+bool DeltaRRoIComboHypoTool::executeAlg(ElementLinkVector<TrigCompositeUtils::DecisionContainer>& combination) const
 {
-  size_t nLegs=IDCombMap.size();
-  ATH_MSG_DEBUG( "Looking for "<< m_decisionId <<" in the map. Map contains "<<nLegs<<" legs");
-  if (passingCombinations[ m_decisionId].size() >0){
-    ATH_MSG_ERROR("Passing combinations have "<< passingCombinations[ m_decisionId].size()<<" elements: what to do?");
-    return StatusCode::FAILURE;
-  }
-
-  std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> leg_decisions;// vector of decisions per leg, to combine
-  // collect combinations from all the legs, searching both chain name and leg name
-  for (auto id: IDCombMap){
-    // get the Element links from the chainID (from all the legs)
-    HLT::Identifier chainId=0;
-    if (TrigCompositeUtils::isLegId(id.first))
-      chainId= TrigCompositeUtils::getIDFromLeg(id.first);
-    else
-      chainId=id.first;
-    if ( chainId != m_decisionId ) continue;    
-    auto comb = id.second; 
-    leg_decisions.push_back(comb);
-  }
-
-  if (nLegs != leg_decisions.size()){
-    ATH_MSG_ERROR("Expecting "<<nLegs<<" legs, but found "<< leg_decisions.size() <<" legs to combine");
-    return StatusCode::FAILURE;
-  }
-  
-  ATH_MSG_DEBUG("Getting "<<leg_decisions.size()<<" legs to combine, for ID: "<< m_decisionId);
-  for (auto leg: leg_decisions){
-    ATH_MSG_DEBUG("Leg --");
-    for (auto dEL:leg) ATH_MSG_DEBUG(dEL.dataID() << " , " << dEL.index());
+  //retrieve the rois 
+  std::vector<ElementLink<TrigRoiDescriptorCollection>> selected_rois;
+  for (auto el: combination){
+    auto dec= (*el);
+    auto roiLink = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( dec, initialRoIString() ).link;
+    selected_rois.push_back(roiLink);
   }
+  ATH_MSG_DEBUG("Selected RoIs: "<<selected_rois.size());
+  auto roiLink1=selected_rois[0];
+  auto roiLink2=selected_rois[1];
 
-  // create the combinatios:
-  // If we have one leg, the combination is between the elements in that leg;
-  // if we have more leges, use recursive combinator
-  std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> combinations;
-  createCombinations( leg_decisions, combinations,  nLegs, 2);
-  for (auto comb: combinations){
-    ATH_MSG_DEBUG("Combination");
-    for (auto dEL :comb){
-      ATH_MSG_DEBUG(dEL.dataID() << " , " << dEL.index());
-    }
-  }
-    
+  // calucalte DeltaR
+  float Dr = deltaR((*roiLink1)->eta(), (*roiLink2)->eta(), (*roiLink1)->phi(), (*roiLink2)->phi());
+  ATH_MSG_DEBUG("Found two RoIs with eta/phi " << (*roiLink1)->eta() <<"/"<<(*roiLink1)->phi() <<" and "<< (*roiLink2)->eta()<<"/"<<(*roiLink2)->phi() <<" with Dr="<<Dr);
 
-  // do the actual algorithm:
-  // to add: protection when the two decisions are the same object
-  for (auto paircomb: combinations){
-    std::vector<ElementLink<TrigRoiDescriptorCollection>> selected_rois;
-    for (auto el: paircomb){
-      auto dec= (*el);
-      auto roiLink = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( dec, initialRoIString() ).link;
-      selected_rois.push_back(roiLink);
-    }
-    ATH_MSG_DEBUG("Selected RoIs: "<<selected_rois.size());
-    
-    //retrieve the rois and calcualte the Dr
-    auto roiLink1=selected_rois[0];
-    auto roiLink2=selected_rois[1];
-    float Dr = deltaR((*roiLink1)->eta(), (*roiLink2)->eta(), (*roiLink1)->phi(), (*roiLink2)->phi());
-    ATH_MSG_DEBUG("Found two RoIs with eta/phi " << (*roiLink1)->eta() <<"/"<<(*roiLink1)->phi() <<" and "<< (*roiLink2)->eta()<<"/"<<(*roiLink2)->phi() <<" with Dr="<<Dr);
-    if (Dr <= m_DRcut){
-      ATH_MSG_DEBUG( "  RoIs within DR<"<<m_DRcut<<". Insert elements for this combination: ");
+  // apply the cut
+  bool pass=true;
+  if (Dr > m_DRcut) pass=false;
 
-      for (auto dEL: paircomb){
-	auto decision= (*dEL);
-	// get back the decID of this element
-	auto allDec = decisionIDs( decision );
-     	ATH_MSG_DEBUG( dEL.dataID() << " , " << dEL.index() <<" size ="<<allDec.size());
-	for (auto id: allDec){
-	  if ((HLT::Identifier(id).name()).find(m_decisionId.name())!=std::string::npos){
-	    // we may have this element already stored, so there might be duplications
-	    // add to both legID and chainID?
-	    passingCombinations[id].push_back(dEL);
-	    passingCombinations[ m_decisionId ].push_back(dEL);
-	  }
-	}
-      }
-    }
-    
-  }
+  if (pass)
+    ATH_MSG_DEBUG( "  RoIs within DR<"<<m_DRcut<<". This seleciton passed! ");
   
-  // remove duplicates?
-
-  ATH_MSG_DEBUG("End of tool: Passing elments are: ");
-  for  (auto id: passingCombinations){
-    ATH_MSG_DEBUG("Id "<<HLT::Identifier(id.first)<<" with "<<id.second.size()<<" elements");
-     for (auto dEL: id.second){
-       ATH_MSG_DEBUG( dEL.dataID() << " , " << dEL.index());
-     }
-  }
-
-  return StatusCode::SUCCESS;
+  return pass;
 }
 
 
-
 double DeltaRRoIComboHypoTool::deltaR(double eta1, double eta2, double phi1, double phi2) const {
   double dPhi=std::remainder( phi1 - phi2, 2*M_PI );
   double dEta=std::fabs(eta1-eta2);
diff --git a/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.h b/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.h
index ce0fb512b3dff938b497d4cfb0e0b56a3c746b07..27fed3a23453026bb66281d172083d44fcf4c1d0 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.h
+++ b/Trigger/TrigSteer/DecisionHandling/src/DeltaRRoIComboHypoTool.h
@@ -9,27 +9,26 @@
 #include "DecisionHandling/HLTIdentifier.h"
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "DecisionHandling/TrigCompositeUtils.h"
-#include "IComboHypoTool.h"
+#include "ComboHypoToolBase.h"
 
-class DeltaRRoIComboHypoTool:  virtual public IComboHypoTool, public AthAlgTool {
+class DeltaRRoIComboHypoTool:  public ComboHypoToolBase {
 
  public:
   
   DeltaRRoIComboHypoTool(const std::string& type,
                     const std::string& name,
                     const IInterface* parent);
-  virtual ~DeltaRRoIComboHypoTool();
+  
+  virtual ~DeltaRRoIComboHypoTool() {};
   virtual StatusCode initialize() override;
-  virtual StatusCode finalize() override;
-  virtual StatusCode decide( const LegDecisionsMap & IDCombMap, LegDecisionsMap & passingCombinations ) const override;
 
   private:
-  
-  Gaudi::Property<float> m_DRcut{this, "DRcut", 0.1, "DR threshold" };
+
+  bool executeAlg(ElementLinkVector<TrigCompositeUtils::DecisionContainer>& thecomb) const override;
  
   double deltaR(double eta1, double eta2, double phi1, double phi2) const;
 
-
+  Gaudi::Property<float> m_DRcut{this, "DRcut", 0.1, "DR threshold" };
  
 
 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/IComboHypoTool.cxx b/Trigger/TrigSteer/DecisionHandling/src/IComboHypoTool.cxx
deleted file mode 100644
index f202a8eacf69d1d091584db3238d6d2dd65ce72c..0000000000000000000000000000000000000000
--- a/Trigger/TrigSteer/DecisionHandling/src/IComboHypoTool.cxx
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "IComboHypoTool.h"
-
-
-void IComboHypoTool::recursive_combine(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> &all,
-			 std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & tocombine,
-			 ElementLinkVector<TrigCompositeUtils::DecisionContainer> & local, u_int lindex)  const
-{
-  
-  for (size_t leg =lindex; leg<all.size(); leg++){
-    for (size_t i=0; i<all[leg].size(); i++){
-      local.push_back(all[leg][i]);
-      recursive_combine(all, tocombine,local, leg+1);
-      local.pop_back(); 
-    }
-  }
-  if (local.size() == all.size())
-    tocombine.push_back(local);
- 
- return;
- 
-}
-
-void IComboHypoTool::createCombinations(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & v_combinations,
-			  std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & tocombine, int nLegs, int nToGroup) const
-{
-
-  if (nLegs ==1) {
-    auto combinations = v_combinations[0];
-    std::vector<int> selector(combinations.size());
-    //    int nRoIsToCombine = 2;// use two RoIs, get this from theconfiguration?
-    fill(selector.begin(), selector.begin() + nToGroup, 1);
-    ElementLinkVector<TrigCompositeUtils::DecisionContainer> thecomb;
-    do {
-      for (u_int i = 0; i < combinations.size(); i++) {
-	if (selector[i]) {
-	  thecomb.push_back(combinations[i]);
-	}
-      }
-      tocombine.push_back(thecomb);    
-      thecomb.clear();
-    }  while (std::prev_permutation(selector.begin(), selector.end()));
-  }
-
-  else {
-    ElementLinkVector<TrigCompositeUtils::DecisionContainer> local;
-    recursive_combine(v_combinations, tocombine, local, 0);
-  }
-
-
-  return;
-}
diff --git a/Trigger/TrigSteer/DecisionHandling/src/IComboHypoTool.h b/Trigger/TrigSteer/DecisionHandling/src/IComboHypoTool.h
index 9895f1c1ddcff5ae14eb676c2bd5e6daecf14380..5299d7d7e1aa700379e9d28fdb58e41c93a6d095 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/IComboHypoTool.h
+++ b/Trigger/TrigSteer/DecisionHandling/src/IComboHypoTool.h
@@ -4,8 +4,7 @@
 #ifndef DECISIONHANDLING_ICOMBOHYPOTOOL_H
 #define DECISIONHANDLING_ICOMBOHYPOTOOL_H 1
 
-#include "DecisionHandling/HLTIdentifier.h"
-#include "DecisionHandling/TrigCompositeUtils.h"
+#include "DecisionHandling/TrigCompositeUtils.h" 
 #include "GaudiKernel/IAlgTool.h"
 
 
@@ -24,49 +23,10 @@ class IComboHypoTool: virtual public ::IAlgTool {
   
  public: 
   DeclareInterfaceID(IComboHypoTool, 1, 0);
-  
-  virtual ~IComboHypoTool() {};
-  IComboHypoTool(const std::string& name)   : m_decisionId(  HLT::Identifier::fromToolName( name ) ) {}
-
-  /**
-  * @brief retreives the decisions associated to this decId, make their combinations and apply the algorithm
-    @param[in]  InputDecisions
-    @param[in]  Cobminaiton map that lists all the decisions passing the multiplicity map of the ComboHypo
-    @param[out] Combination map that lists all the decisions passing the HypoTool algorithm
-  **/  
-  virtual StatusCode decide(const LegDecisionsMap & IDCombMap, LegDecisionsMap & passingCombinations ) const = 0;
-
-  /**
-  * @brief retrieves this decision Id
-  **/
-  virtual HLT::Identifier decisionId() const { return m_decisionId; }
-  
-  
- protected:
-  
-  HLT::Identifier m_decisionId;
 
-  /**
-  * @brief creates combinations of decisions starting from the legs vector of pairs, given the number of legs and the number of elements to combine
-    @param[in] v_combinations: vector of legs (vector), each containing the corresponding decision pairs
-    @param[in] nLegs: number of legs to combine
-    @param[in] nToGroup: number of elements to group in a combination, in case one leg is used
-    @param[out] tocombine: vector of combinations (vectors) of decision pairs
-  **/
-  void createCombinations(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & v_combinations,
-			  std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & tocombine, int nLegs, int nToGroup) const;
-
-  /**
-  * @brief recursively creates combinations of elements from differnt vectors
-    @param[in] all: initial vector of decision legs
-    @parma[in] local: temporary vector of combinations
-    @param[in] lindex: leg index
-    @param[out] tocombine: vector of combinations
-  **/
-  void recursive_combine(const std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> &all,
-			 std::vector<ElementLinkVector<TrigCompositeUtils::DecisionContainer>> & tocombine,
-			 ElementLinkVector<TrigCompositeUtils::DecisionContainer> & local, u_int lindex)  const;
+  virtual StatusCode decide( const LegDecisionsMap & IDCombMap, LegDecisionsMap & passingCombinations ) const = 0 ;
   
+ 
 }; 
 
 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx b/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx
index 8c49fa320d5c2fd447c63e63679f0ae9864bb6df..e55e57d985d6d54d53b9d19b229ec93a69b2abc0 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx
@@ -4,12 +4,14 @@
 #include "../ComboHypo.h"
 #include "../InputMakerForRoI.h"
 #include "../DeltaRRoIComboHypoTool.h"
+#include "../ComboHypoToolBase.h"
 
 DECLARE_COMPONENT( DumpDecisions )
 DECLARE_COMPONENT( RoRSeqFilter )
 DECLARE_COMPONENT( TriggerSummaryAlg )
 DECLARE_COMPONENT( ComboHypo )
 DECLARE_COMPONENT( InputMakerForRoI )
+DECLARE_COMPONENT( ComboHypoToolBase )
 DECLARE_COMPONENT( DeltaRRoIComboHypoTool )
 
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainConfigurationBase.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainConfigurationBase.py
index c55e0e1ac1b9e75f976140a0b87bd89239dc0665..97c90a6a1abf6d741490b8619841874e2e432135 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainConfigurationBase.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainConfigurationBase.py
@@ -39,13 +39,13 @@ class ChainConfigurationBase(object):
         mySequence = RecoFragmentsPool.retrieve(mySequenceCfg, None) # the None will be used for flags in future
         return mySequence
 
-    def getStep(self, stepID, stepPartName, sequenceCfgArray):
+    def getStep(self, stepID, stepPartName, sequenceCfgArray, comboTools=[]):
         stepName = 'Step%d'%stepID + '_%d'%self.mult + stepPartName
         log.debug("Configuring step " + stepName)
         seqArray = []
         for sequenceCfg in sequenceCfgArray:
             seqArray.append( RecoFragmentsPool.retrieve( sequenceCfg, None))
-        return ChainStep(stepName, seqArray, [self.mult])
+        return ChainStep(stepName, seqArray, [self.mult], comboToolConfs=comboTools)
 
     def buildChain(self, chainSteps):
         myChain = Chain(name = self.chainName,
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainMerging.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainMerging.py
index 6aa90b3a97f878943a89e654a2ca5262faccb5f0..f6380dae0c1d346a30496ac9a83f29bf1d60000a 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainMerging.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/ChainMerging.py
@@ -84,6 +84,7 @@ def makeChainSteps(steps):
     stepNumber = ''
     log.verbose(" steps %s ", steps)
     stepName = "merged"
+    comboHypoTools = []
     for step in steps:
         if step is None:
             continue
@@ -108,9 +109,11 @@ def makeChainSteps(steps):
             stepSeq.append(seq)
         # set the multiplicity of all the legs 
         stepMult.append(sum(step.multiplicity))
+        comboHypoTools.extend(step.comboToolConfs)
         
 
-    theChainStep = ChainStep(stepName, stepSeq, stepMult) 
+    comboHypoTools = list(set(comboHypoTools))
+    theChainStep = ChainStep(stepName, Sequences=stepSeq, multiplicity=stepMult, comboToolConfs=comboHypoTools) 
     log.debug("Merged step: \n %s", theChainStep)
   
     
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
index 8f3c82401a1c9bfa762c0e6dca289b08c4fca8e4..577b0256e59200dd4d9f1327df64b1ee8b050d03 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
@@ -50,6 +50,8 @@ def setupMenu():
         ChainProp(name='HLT_2mu6_10invm70_L1MU6', groups=SingleMuonGroup),
         ChainProp(name='HLT_mu10_lateMu_L1MU10', l1SeedThresholds=['FSNOSEED'], groups=SingleMuonGroup),
 
+        # this is for test only
+        ChainProp(name='HLT_2mu6_Dr_L12MU4',  groups=MultiMuonGroup),
         # ATR-20049
         ChainProp(name='HLT_mu6_mu4_L12MU4',  l1SeedThresholds=['MU4']*2, groups=MultiMuonGroup),
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py
index a5c82d5eb2d0d99ed9ce3a3efeb08fb46eb2f79f..b3d78c066b6a96ac7182ed339fa8ce0d237cb1c7 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py
@@ -758,18 +758,23 @@ class ChainStep(object):
         self.name = name
         self.sequences=Sequences
         self.multiplicity = multiplicity
+        self.comboToolConfs=comboToolConfs
         self.isCombo=sum(multiplicity)>1
         self.combo=None
         if self.isCombo:
-            self.makeCombo(Sequences, comboToolConfs )
-        self.decisions = []
+            self.makeCombo()
 
-    def makeCombo(self, Sequences, comboToolConfs=[]):
-        if len(Sequences)==0:
+
+    def addCombHypoTools(self,  tools):
+        self.comboToolConfs=tools
+        self.combo.addComboHypoToolConfs(self.comboToolConfs)
+
+    def makeCombo(self):
+        if len(self.sequences)==0:
             return
         hashableMult = tuple(self.multiplicity)
         self.combo =  RecoFragmentsPool.retrieve(createComboAlg, None, name=CFNaming.comboHypoName(self.name), multiplicity=hashableMult)
-        self.combo.addComboHypoToolConfs(comboToolConfs)
+        self.combo.addComboHypoToolConfs(self.comboToolConfs)
 
     def createComboHypoTools(self, chainName):
         if self.isCombo:
@@ -782,7 +787,7 @@ class ChainStep(object):
 
 
     def __repr__(self):
-        return "--- ChainStep %s ---\n + isCombo = %d, multiplicity = %d \n + MenuSequences = %s"%(self.name, self.isCombo,sum(self.multiplicity), ' '.join(map(str, [seq.name for seq in self.sequences]) ))
+        return "--- ChainStep %s ---\n + isCombo = %d, multiplicity = %d \n + MenuSequences = %s  \n + ComboHypoTools = %s"%(self.name, self.isCombo,sum(self.multiplicity), ' '.join(map(str, [seq.name for seq in self.sequences]) ),  ' '.join(map(str, [tool for tool in self.comboToolConfs]) ))
 
 
 def createComboAlg(dummyFlags, name, multiplicity):
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py
index d6a32a443552f13051b45bd941a8def4517bc5d6..a23e5cef356799be889027b88bdb9689b17c905a 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/SignatureDicts.py
@@ -184,7 +184,7 @@ MuonChainParts = {
     'trigType'       : ['mu'],
     'etaRange'       : ['0eta2550','0eta105'],
     'threshold'      : '',
-    'extra'          : ['noL1', 'Comb', 'fast', 'msonly','lateMu'],
+    'extra'          : ['noL1', 'Comb', 'fast', 'msonly','lateMu', "Dr"],
     'IDinfo'         : [],
     'isoInfo'        : ['ivar','ivarmedium'],
     'invMassInfo'    : ['10invm70'],
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py
index 5b7a6b77cb060921a02b1b3f021705a38878a359..c8df09a5c5cabf9641197aedc6edb60cafb40855 100755
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py
@@ -15,6 +15,13 @@ from TriggerMenuMT.HLTMenuConfig.Menu.ChainConfigurationBase import ChainConfigu
 
 from TriggerMenuMT.HLTMenuConfig.Muon.MuonSequenceSetup import muFastSequence, muFastOvlpRmSequence, muCombSequence, muCombOvlpRmSequence, muEFMSSequence, muEFSASequence, muIsoSequence, muEFCBSequence, muEFSAFSSequence, muEFCBFSSequence, muEFIsoSequence, muEFCBInvMassSequence, efLateMuRoISequence, efLateMuSequence
 
+# this must be moved to the HypoTool file:
+def dimuDrComboHypoToolFromDict(chainDict):
+    from DecisionHandling.DecisionHandlingConf import DeltaRRoIComboHypoTool
+    name = chainDict['chainName']
+    tool= DeltaRRoIComboHypoTool(name)
+    tool.DRcut=3.
+    return tool
 
 
 #--------------------------------------------------------
@@ -121,7 +128,8 @@ class MuonChainConfiguration(ChainConfigurationBase):
             "msonly":[['getmuFast', 'getmuMSEmpty'], ['getmuEFMS']],
             "ivarmedium":[['getmuFast', 'getmuComb'], ['getmuEFSA', 'getmuEFCB', 'getmuEFIso']],
             "invM":[[],['getmuInvM']],
-            "lateMu":[[],['getLateMuRoI','getLateMu']]
+            "lateMu":[[],['getLateMuRoI','getLateMu']],
+            "Dr": [['getmuFastDr', 'getmuCombDr']]
         }
 
         return stepDictionary
@@ -204,17 +212,18 @@ class MuonChainConfiguration(ChainConfigurationBase):
     def getmuMSEmptyAll(self, stepID):
         return self.getStep(stepID,'muMS_empty',[])
 
-        #--------------------
+    #--------------------
     def getmuMSEmpty(self):
         return self.getmuMSEmptyAll(2)
 
-       #--------------------
+    #--------------------
     def getmuFastEmpty(self):
         return self.getStep(1,'muFast_empty',[])
 
-
+    #--------------------
     def getEFCBEmpty(self):
         return self.getStep(6,'EFCBEmpty',[])
+    
     #--------------------
     def getmuInvM(self):
         return self.getStep(5,'muInvM',[muEFCBInvMSequenceCfg])
@@ -226,3 +235,18 @@ class MuonChainConfiguration(ChainConfigurationBase):
     #--------------------
     def getLateMu(self):
         return self.getStep(2,'muEFLate',[muEFLateSequenceCfg])
+
+    #--------------------
+    # FP:
+    # Here example of how to create steps with ComboHypoTools 
+    # tmp: the problem is that we create a differnt Alg, insetad of reusing the same ComboAlg
+    # need to be fixed!
+    def getmuCombDr(self):     
+        step=self.getStep(2, 'muCombDr', sequenceCfgArray=[muCombSequenceCfg])
+        step.addCombHypoTools([dimuDrComboHypoToolFromDict] )
+        return step
+
+    def getmuFastDr(self):     
+        step=self.getStep(1,"mufastDr", [muFastSequenceCfg] )
+        step.addCombHypoTools([dimuDrComboHypoToolFromDict] )
+        return step