From 22510b55dbd1e02e3d9b79d6f56c8eb1afe05a40 Mon Sep 17 00:00:00 2001
From: Tim Martin <Tim.Martin@cern.ch>
Date: Tue, 3 Mar 2020 14:55:25 +0100
Subject: [PATCH] Use ElementLinkVector

---
 .../DecisionHandling/src/ComboHypo.cxx        | 61 ++++++++----------
 .../DecisionHandling/src/ComboHypo.h          | 11 ++--
 .../src/ComboHypoCombination.cxx              | 28 --------
 .../src/ComboHypoCombination.h                | 64 -------------------
 4 files changed, 30 insertions(+), 134 deletions(-)
 delete mode 100644 Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.cxx
 delete mode 100644 Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.h

diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
index 9b146ee19a5..06807962114 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
@@ -138,7 +138,7 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
   
   DecisionIDContainer passing;
   // this map is filled with the count of positive decisions from each input
-  CombinationMap dmap;
+  LegDecisionsMap dmap;
 
   ATH_CHECK( fillDecisionsMap( dmap, context ) );
 
@@ -153,7 +153,7 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
     allDecisionIds.insert(requiredDecisionID);
 
     bool overallDecision = true;
-    DecisionIDContainer uniqueDecisions;
+    std::set<uint32_t> uniqueDecisionFeatures;
 
     // Check multiplicity of each leg 
     for ( size_t legIndex = 0; legIndex <  multiplicityPerLeg.size(); ++legIndex ) {
@@ -171,7 +171,7 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
       const DecisionID requiredDecisionIDLeg = legId.numeric();
       ATH_MSG_DEBUG("Container " << legIndex << ", looking at leg : " << legId );
      
-      CombinationMap::const_iterator it = dmap.find(requiredDecisionIDLeg);
+      LegDecisionsMap::const_iterator it = dmap.find(requiredDecisionIDLeg);
       if ( it == dmap.end() ) {
         overallDecision = false;
         break;
@@ -179,7 +179,7 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
 
       //check this leg of the chain passes with required multiplicity
 
-      const size_t observedMultiplicity = it->second.getCombinations().size();
+      const size_t observedMultiplicity = it->second.size();
       ATH_MSG_DEBUG( "Required multiplicity " << requiredMultiplicity  << " for leg " << legId 
         << ": observed multiplicity " << observedMultiplicity << " in leg " << legIndex  );
 
@@ -189,22 +189,26 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
       }
 
       //keep track of the number of unique features
-
-      for (const auto& entry : it->second.getFeatures()){
-        if (entry.first == 0) {
+      for (const ElementLink<DecisionContainer>& dEL : it->second){
+        uint32_t featureKey = 0, roiKey = 0;
+        uint16_t featureIndex = 0, roiIndex = 0;
+        // NOTE: roiKey, roiIndex not currently used in this discrimination
+        ATH_CHECK( extractFeatureAndRoI(dEL, featureKey, featureIndex, roiKey, roiIndex) );
+        const uint32_t featureHash = (featureKey + featureIndex); 
+        if (featureHash == 0) {
           ATH_MSG_WARNING("Disregarding feature hash of zero");
           continue;
         }
-        uniqueDecisions.insert( entry.first );
-        // TODO - do something with entry.second (the ROI)
+        uniqueDecisionFeatures.insert( featureHash );
+        // TODO - do something with the ROI
       }
 
       allDecisionIds.insert(requiredDecisionIDLeg);
     }
 
     //check that the multiplicity of unique features is high enough
-    ATH_MSG_DEBUG("Number of unique decisions: " << uniqueDecisions.size() << ", number of required unique decisions: " << nRequiredUnique);
-    if ( uniqueDecisions.size() < nRequiredUnique ) {
+    ATH_MSG_DEBUG("Number of unique features: " << uniqueDecisionFeatures.size() << ", number of required unique decisions: " << nRequiredUnique);
+    if ( uniqueDecisionFeatures.size() < nRequiredUnique ) {
       overallDecision = false;
     }
 
@@ -223,30 +227,29 @@ StatusCode ComboHypo::execute(const EventContext& context ) const {
   return StatusCode::SUCCESS;
 }
 
-StatusCode ComboHypo::extractFeatureAndRoI(const Decision* d, const std::string& input,
+StatusCode ComboHypo::extractFeatureAndRoI(const ElementLink<DecisionContainer>& dEL,
   uint32_t& featureKey, uint16_t& featureIndex, uint32_t& roiKey, uint16_t& roiIndex) const 
 {
   uint32_t featureClid = 0; // Note: Unused. We don't care what the type of the feature is here
-  const bool result = d->typelessGetObjectLink(featureString(), featureKey, featureClid, featureIndex);
+  const bool result = (*dEL)->typelessGetObjectLink(featureString(), featureKey, featureClid, featureIndex);
   if (!result) {
-    ATH_MSG_ERROR("Did not find the feature for Input:" << input << " Element:" << d->index());
+    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
   if (m_requireUniqueROI) {
-    LinkInfo<TrigRoiDescriptorCollection> roiSeedLI = findLink<TrigRoiDescriptorCollection>(d, initialRoIString());
+    LinkInfo<TrigRoiDescriptorCollection> roiSeedLI = findLink<TrigRoiDescriptorCollection>((*dEL), initialRoIString());
     if (roiSeedLI.isValid()) {
       roiKey = roiSeedLI.link.key();
       roiIndex = roiSeedLI.link.index();
     }
     else {
-      ATH_MSG_ERROR("Did not find a seeding ROI for Input:" << input << " Element:" << d->index());
+      ATH_MSG_ERROR("Did not find a seeding ROI for " << dEL.dataID() << " index " << dEL.index());
     }
   }
   return StatusCode::SUCCESS;
 }
 
-StatusCode ComboHypo::fillDecisionsMap( CombinationMap &  dmap, const EventContext& context) const {
-
+StatusCode ComboHypo::fillDecisionsMap( LegDecisionsMap &  dmap, const EventContext& context) const {
   for ( size_t inputContainerIndex = 0; inputContainerIndex < m_inputs.size(); ++inputContainerIndex ) {   
     auto inputHandle = SG::makeHandle( m_inputs.at(inputContainerIndex), context );
     if ( !inputHandle.isValid() ) {
@@ -266,14 +269,7 @@ StatusCode ComboHypo::fillDecisionsMap( CombinationMap &  dmap, const EventConte
           }
           ATH_MSG_DEBUG( " +++ " << HLT::Identifier( id ) );
 
-          // Obtain unique but type-less key & index identifiers for this Decision node's "Feature" 
-          // and (if m_requireUniqueROI) its initialRoI.
-          // Allows us to check object uniqueness and prevent multiple objects from the same RoI satisfying one leg.
-          uint32_t featureKey = 0, roiKey = 0;
-          uint16_t featureIndex = 0, roiIndex = 0;
-          ATH_CHECK( extractFeatureAndRoI(decision, inputHandle.key(), featureKey, featureIndex, roiKey, roiIndex) );
-
-          dmap[id].add(inputContainerIndex, decision->index(), featureKey, featureIndex, roiKey, roiIndex);
+          dmap[id].push_back( TrigCompositeUtils::decisionToElementLink(decision, context) );
         }
       }
     }
@@ -284,15 +280,10 @@ StatusCode ComboHypo::fillDecisionsMap( CombinationMap &  dmap, const EventConte
     size_t legCount = 0;
     for (const auto& entry: dmap){
       ATH_MSG_DEBUG("leg ["<<legCount<<"]: ");
-      const std::vector<std::pair<uint32_t,uint16_t>>& combinations = entry.second.getCombinations();
-      ATH_MSG_DEBUG(" +++ " << HLT::Identifier( entry.first ) <<" mult: "<< combinations.size());
-      for (const auto& comb : combinations){
-        ATH_MSG_DEBUG("     Comb: (ContainerIndex:"<<comb.first<<", DecisionElementIndex:"<<comb.second<<")");
-      }
-      const std::vector<std::pair<uint32_t,uint32_t>>& featureMap = entry.second.getFeatures();
-      ATH_MSG_DEBUG("FeatureMap: found " << featureMap.size() << " entries");
-      for (const auto& feat : featureMap) {
-        ATH_MSG_DEBUG("    Unique Feature Identifier:" << feat.first << ", From ROI Identifier: " << feat.second);
+      const ElementLinkVector<DecisionContainer>& decisions = entry.second;
+      ATH_MSG_DEBUG(" +++ " << HLT::Identifier( entry.first ) <<" Number Decisions: "<< decisions.size());
+      for (const ElementLink<DecisionContainer>& d : decisions){
+        ATH_MSG_DEBUG("     Decision: (ContainerKey:"<<d.key()<<", DecisionElementIndex:"<<d.index()<<")");
       }
       legCount++;
     }
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h
index 04b4f704d75..2d2670a888d 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.h
@@ -8,8 +8,6 @@
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
 #include "DecisionHandling/TrigCompositeUtils.h"
 
-#include "ComboHypoCombination.h"
-
 // STL includes
 #include <string>
 #include <utility>  
@@ -55,21 +53,20 @@ private:
    * @brief For a given Decision node from a HypoAlg, extracts type-less identification data on the node's Feature and seeding ROI.
    * @param[in] d The Decision node from the HypoAlg, expected to have a "feature" link attached to it.
    *   Expected to be able to locate a "initialRoI" in its history if RequireUniqueROI=True.
-   * @param[in] input Name of the collection the Decision comes from, used for error printing only.
    * @param[out] featureKey Type-less SG Key hash of the collection hosting the Decision node's feature .
    * @param[out] featureIndex Index inside the featureKey collection. 
    * @param[out] roiKey Type-less SG Key hash of the collection hosting the Decision node's initial ROI collection. 
    * @param[out] roiIndex Index inside the roiKey collection. 
    **/
-  StatusCode extractFeatureAndRoI(const TrigCompositeUtils::Decision* d, const std::string& input,
+  StatusCode extractFeatureAndRoI(const ElementLink<TrigCompositeUtils::DecisionContainer>& EL,
     uint32_t& featureKey, uint16_t& featureIndex, uint32_t& roiKey, uint16_t& roiIndex) const; 
 
 
   /**
-   * @brief iterates over all inputs filling the multiplicity map for each input collection
+   * @brief iterates over all inputs, associating inputs to legs
    **/
-  typedef std::map<TrigCompositeUtils::DecisionID, ComboHypoCombination> CombinationMap;
-  StatusCode fillDecisionsMap( CombinationMap& dmap, const EventContext& context) const;
+  typedef std::map<TrigCompositeUtils::DecisionID, ElementLinkVector<TrigCompositeUtils::DecisionContainer>> LegDecisionsMap;
+  StatusCode fillDecisionsMap( LegDecisionsMap& dmap, const EventContext& context) const;
 
 };
 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.cxx b/Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.cxx
deleted file mode 100644
index 3ccebbd0641..00000000000
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.cxx
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "ComboHypoCombination.h"
-
-void ComboHypoCombination::add(const uint32_t inputContainerID, const uint16_t decisionElementID, 
-    const uint32_t featureContainerKey, const uint16_t featureIndex,
-    const uint32_t roiContainerKey, const uint16_t roiIndex)
-{
-  m_combinations.push_back( std::make_pair(inputContainerID, decisionElementID) );
-
-  const uint32_t featureMapLocation = combineKeyAndIndex(featureContainerKey, featureIndex);
-  const uint32_t roiPayload = combineKeyAndIndex(roiContainerKey, roiIndex);
-  m_features.push_back( std::make_pair(featureMapLocation, roiPayload) );
-}
-
-uint32_t ComboHypoCombination::combineKeyAndIndex(const uint32_t key, const uint16_t index) {
-  return (key + index);
-}
-
-const std::vector< std::pair<uint32_t,uint16_t> >& ComboHypoCombination::getCombinations() const {
-  return m_combinations;
-}
-
-const std::vector< std::pair<uint32_t,uint32_t> >& ComboHypoCombination::getFeatures() const {
-  return m_features;
-}
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.h b/Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.h
deleted file mode 100644
index 57d8f68da61..00000000000
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypoCombination.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
-*/
-#ifndef DECISIONHANDLING_COMBOHYPOCOMBINATION_H
-#define DECISIONHANDLING_COMBOHYPOCOMBINATION_H
-
-// STL includes
-#include <map>
-#include <utility> // std::pair  
-#include <vector>  
-
-/**
-* @brief Utility class to assist with the bookkeeping when counting Decision objects which pass 
-* specific chain-leg requirements. Here Decision nodes are identified by abstract key and index pairs, and these
-* node's "Feature" and "initialRoI" by hash values.
-* 
-* This suffices to perform Decision node multiplicity counting, and "Feature"/"initialRoI" uniqueness checks.
-**/
-class ComboHypoCombination {
-public:
-
-  /**
-  * @brief Compresses the Feature and ROI type-less ID data into single uint32_t hash values
-  * and stores this along with the Decision node's key & index in two parallel vectors.
-  **/
-  void add(const uint32_t inputContainerID, const uint16_t decisionElementID, 
-    const uint32_t featureContainerKey, const uint16_t featureIndex,
-    const uint32_t roiContainerKey, const uint16_t roiIndex);
-  
-  /**
-  * @brief Get the node vector. Each entry corresponds to a Decision node (first: key, second: index)
-  **/
-  const std::vector< std::pair<uint32_t,uint16_t> >& getCombinations() const;
-
-  /**
-  * @brief Get the features vector. Each entry corresponds to a Decision node's Feature & ROI (first: feature, second: roi)
-  **/
-  const std::vector< std::pair<uint32_t,uint32_t> >& getFeatures() const;
-
-private:
-
-  /**
-  * @brief key is a SG hash, so is already well distributed. The hash is incremented by the index 
-  * to create a new per-object hash
-  **/
-  uint32_t combineKeyAndIndex(const uint32_t key, const uint16_t index);
-
-  /**
-  * @brief Each entry corresponds to a Decision node.
-  * The first element in the pair is the SG key of the node's collection.
-  * The second element in the pair is the index inside the collection.
-  **/
-  std::vector< std::pair<uint32_t,uint16_t> > m_combinations;
-  /**
-  * @brief Each entry corresponds to the Feature of the node in the parallel m_combinations vector.
-  * The first element in the pair is a combined hash of the SG key & index of the node's Feature.
-  * The second element in the pair is a combined hash of the SG key & index of the node's initialRoI
-  **/
-  std::vector< std::pair<uint32_t,uint32_t> > m_features;
-
-};
-
-
-#endif // DECISIONHANDLING_COMBOHYPOCOMBINATION_H
-- 
GitLab