From 4a960a6ad1c26ca4584f5a18247c57d7f49b3b42 Mon Sep 17 00:00:00 2001
From: Jon Burr <jon.burr@cern.ch>
Date: Tue, 15 Dec 2020 15:09:28 +0100
Subject: [PATCH] Move combination generation to TrigCompositeUtils

---
 .../Root/R3MatchingTool.cxx                   | 28 ++-----
 .../Root/TrigCompositeUtilsRoot.cxx           | 54 +++++++++++++
 .../TrigCompositeUtils/TrigCompositeUtils.h   | 75 ++++++++++++++++++-
 3 files changed, 133 insertions(+), 24 deletions(-)

diff --git a/Trigger/TrigAnalysis/TriggerMatchingTool/Root/R3MatchingTool.cxx b/Trigger/TrigAnalysis/TriggerMatchingTool/Root/R3MatchingTool.cxx
index aba7f08b401c..21bc331f19f3 100644
--- a/Trigger/TrigAnalysis/TriggerMatchingTool/Root/R3MatchingTool.cxx
+++ b/Trigger/TrigAnalysis/TriggerMatchingTool/Root/R3MatchingTool.cxx
@@ -81,29 +81,11 @@ namespace Trig
       // Now we have to build up combinations
       // TODO - right now we use a filter that passes everything that isn't pointer-equal.
       // This will probably need to be fixed to something else later - at least the unique RoI filter
-      TrigCompositeUtils::Combinations combinations(TrigCompositeUtils::FilterType::All);
-      const TrigConf::HLTChain *chainInfo = m_trigDecTool->ExperimentalAndExpertMethods()->getChainConfigurationDetails(chainName);
-      std::vector<std::size_t> multiplicities = chainInfo->leg_multiplicities();
-      combinations.reserve(multiplicities.size());
-      // Get all the features for the chain
-      VecLinkInfo_t chainFeatures = m_trigDecTool->features<xAOD::IParticleContainer>(chainName);
-      ATH_MSG_VERBOSE("Chain " << chainName << " has " << chainFeatures.size() << " features and " << multiplicities.size() << " legs with multiplicities, nFeatures: ");
-      if (multiplicities.size() == 1)
-      {
-        ATH_MSG_VERBOSE("  :" << multiplicities.at(0) << ", " << chainFeatures.size());
-        combinations.addLeg(multiplicities.at(0), std::move(chainFeatures));
-      }
-      else
-        for (std::size_t legIdx = 0; legIdx < multiplicities.size(); ++legIdx)
-        {
-          HLT::Identifier legID = TrigCompositeUtils::createLegName(chainName, legIdx);
-          VecLinkInfo_t legFeatures;
-          for (const IPartLinkInfo_t &info : chainFeatures)
-            if (TrigCompositeUtils::isAnyIDPassing(info.source, {legID.numeric()}))
-              legFeatures.push_back(info);
-          ATH_MSG_VERBOSE(legID.name() << " (" << legID.numeric() << "): " << multiplicities.at(legIdx) << ", " << legFeatures.size());
-          combinations.addLeg(multiplicities.at(legIdx), std::move(legFeatures));
-        }
+      TrigCompositeUtils::Combinations = TrigCompositeUtils::buildCombinations(
+        chainName,
+        m_trigDecTool->features<xAOD::IParticleContainer>(chainName),
+        m_trigDecTool->ExperimentalAndExpertMethods()->getChainConfigurationDetails(chainName),
+        TrigCompositeUtils::FilterType::UniqueObjects);
       // Warn once per call if one of the chain groups is too small to match anything
       if (combinations.size() < recoObjects.size())
       {
diff --git a/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtilsRoot.cxx b/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtilsRoot.cxx
index c22b1dc36611..e0435063afd6 100644
--- a/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtilsRoot.cxx
+++ b/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtilsRoot.cxx
@@ -417,6 +417,60 @@ namespace TrigCompositeUtils {
     return true; 
   }
 
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const std::vector<std::size_t>& legMultiplicities,
+    const std::function<bool(const std::vector<LinkInfo<xAOD::IParticleContainer>>&)>& filter)
+  {
+    Combinations combinations(filter);
+    combinations.reserve(legMultiplicities.size());
+    if (legMultiplicities.size() == 1)
+    {
+      combinations.addLeg(legMultiplicities.at(0), features);
+    }
+    else {
+      for (std::size_t legIdx = 0; legIdx < legMultiplicities.size(); ++legIdx)
+      {
+        HLT::Identifier legID = createLegName(chainName, legIdx);
+        std::vector<LinkInfo<xAOD::IParticleContainer>> legFeatures;
+        for (const LinkInfo<xAOD::IParticleContainer>& info : features)
+          if (isAnyPassing(info.source, {legID.numeric()}))
+            legFeatures.push_back(info);
+      }
+      combinations.addLeg(legMultiplicities.at(legIdx), std::move(legFeatures));
+    }
+    return combinations;
+  }
+
+
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const std::vector<std::size_t>& legMultiplicities,
+    FilterType filter = FilterType::UniqueObjects)
+  {
+    return buildCombinations(chainName, features, legMultiplicities, getFilter(filter));
+  }
+
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const TrigConf::HLTChain *chainInfo,
+    const std::function<bool(const std::vector<LinkInfo<xAOD::IParticleContainer>>&)>& filter)
+  {
+    return buildCombinations(chainName, features, chainInfo->leg_multiplicities(), filter);
+  }
+
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const TrigConf::HLTChain *chainInfo,
+    FilterType filter = FilterType::UniqueObjects)
+  {
+    return buildCombinations(chainName, features, chainInfo, getFilter(filter));
+  }
+
 
   std::string dump( const Decision* tc, std::function< std::string( const Decision* )> printerFnc ) {
     std::string ret; 
diff --git a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h
index 64ea8b34ea3e..8dd8e8bbe67f 100644
--- a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h
+++ b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h
@@ -33,6 +33,8 @@
 
 #include "HLTIdentifier.h"
 #include "NavGraph.h"
+#include "TrigCompositeUtils/IPartCombItr.h"
+#include "TrigCompositeUtils/Combinations.h"
 
 namespace TrigCompositeUtils {
 
@@ -465,7 +467,78 @@ namespace TrigCompositeUtils {
     const unsigned int behaviour = TrigDefs::allFeaturesOfType, 
     std::set<const xAOD::TrigComposite*>* visitedCache = nullptr);
 
-
+  /**
+   * @brief Produce the combinations for a set of features
+   * 
+   * Returns a TrigCompositeUtils::Combinations object that generates all valid
+   * combinations of features. This is a range object that returns on iterator
+   * which creates the combinations on the fly.
+   * 
+   * @param[in] chainName The name of the chain
+   * @param[in] features The IParticle features of the container
+   * @param[in] legMultiplicities The multiplicity of each chain leg
+   * @param[in] filter A function that returns true for all valid combinations
+   */
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const std::vector<std::size_t>& legMultiplicities,
+    const std::function<bool(const std::vector<LinkInfo<xAOD::IParticleContainer>>&)>& filter);
+
+  /**
+   * @brief Produce the combinations for a set of features
+   * 
+   * Returns a TrigCompositeUtils::Combinations object that generates all valid
+   * combinations of features. This is a range object that returns on iterator
+   * which creates the combinations on the fly.
+   * 
+   * @param[in] chainName The name of the chain
+   * @param[in] features The IParticle features of the container
+   * @param[in] legs legMultiplicities The multiplicity of each chain leg
+   * @param[in] filter A FilterType enum describing how to filter valid combinations
+   */
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const std::vector<std::size_t>& legMultiplicities,
+    FilterType filter = FilterType::UniqueObjects);
+
+  /**
+   * @brief Produce the combinations for a set of features
+   * 
+   * Returns a TrigCompositeUtils::Combinations object that generates all valid
+   * combinations of features. This is a range object that returns on iterator
+   * which creates the combinations on the fly.
+   * 
+   * @param[in] chainName The name of the chain
+   * @param[in] features The IParticle features of the container
+   * @param[in] chainInfo The chain info object read from the configuration
+   * @param[in] filter A function that returns true for all valid combinations
+   */
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const TrigConf::HLTChain *chainInfo,
+    const std::function<bool(const std::vector<LinkInfo<xAOD::IParticleContainer>>&)>& filter);
+
+  /**
+   * @brief Produce the combinations for a set of features
+   * 
+   * Returns a TrigCompositeUtils::Combinations object that generates all valid
+   * combinations of features. This is a range object that returns on iterator
+   * which creates the combinations on the fly.
+   * 
+   * @param[in] chainName The name of the chain
+   * @param[in] features The IParticle features of the container
+   * @param[in] chainInfo The chain info object read from the configuration
+   * @param[in] filter A FilterType enum describing how to filter valid combinations
+   */
+  Combinations buildCombinations(
+    const std::string& chainName,
+    const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
+    const TrigConf::HLTChain *chainInfo,
+    FilterType filter = FilterType::UniqueObjects);
+    
   /**
    * Prints the Decision object including the linked seeds
    * @warnign expensive call
-- 
GitLab