From 3ea508e27629ac846df4838c920b9b4c93adfad7 Mon Sep 17 00:00:00 2001
From: Tim Martin <tim.martin@cern.ch>
Date: Thu, 19 Mar 2020 16:30:29 +0000
Subject: [PATCH] [ATR-21112] Input maker refactor - custom ROI Tools for
 EventViewCreator

---
 .../python/ComponentAccumulatorTest.py        |   6 +-
 .../python/UnifyProperties.py                 |   1 -
 .../TrigEFMissingET/doc/METMenuSequences.md   |   2 +-
 .../TrigT2CaloCommon/python/CaloDef.py        |   5 +-
 .../DecisionHandling/InputMakerBase.h         |  39 +--
 .../DecisionHandling/InputMakerBase.icc       |  40 +++
 .../DecisionHandling/TrigCompositeUtils.icc   | 194 -----------
 .../DecisionHandling/src/InputMakerBase.cxx   | 166 +++-------
 .../DecisionHandling/src/InputMakerForRoI.cxx |  71 ++--
 .../DecisionHandling/src/InputMakerForRoI.h   |   4 +-
 .../TrigCompositeUtils/CMakeLists.txt         |   5 +
 .../TrigCompositeUtils/TrigCompositeUtils.h   |  13 +-
 .../TrigCompositeUtils/TrigCompositeUtils.icc |  37 ++-
 .../ViewAlgs/ViewAlgs/IViewCreatorROITool.h   |  39 +++
 .../src/EventViewCreatorAlgorithm.cxx         | 304 +++++++-----------
 .../ViewAlgs/src/EventViewCreatorAlgorithm.h  |  75 +++--
 .../src/EventViewCreatorAlgorithm.icc         |  25 ++
 .../src/EventViewCreatorAlgorithmWithJets.cxx | 131 ++++----
 .../EventViewCreatorAlgorithmWithMuons.cxx    | 213 ++++++------
 .../src/ViewCreatorInitialROITool.cxx         |  31 ++
 .../ViewAlgs/src/ViewCreatorInitialROITool.h  |  35 ++
 .../src/ViewCreatorPreviousROITool.cxx        |  33 ++
 .../ViewAlgs/src/ViewCreatorPreviousROITool.h |  32 ++
 .../src/components/ViewAlgs_entries.cxx       |   7 +-
 .../share/q221_RDOtoRDOTrig_mt1_build.ref     |  19 +-
 .../share/ref_RDOtoRDOTrig_mt1_build.ref      |  19 +-
 .../TrigUpgradeTest/share/egammaRinger.py     |   7 +-
 .../TrigUpgradeTest/share/full_menu_build.ref |  17 +-
 .../TrigUpgradeTest/share/photon.withViews.py |  11 +-
 .../TrigUpgradeTest/src/TestInputMaker.cxx    | 100 +++---
 .../share/ref_data_v1Dev_build.ref            |  17 +-
 .../HLTMenuConfig/Bjet/BjetSequenceSetup.py   |   6 +-
 .../Bphysics/BphysicsSequenceSetup.py         |   7 +-
 .../BeamspotChainConfiguration.py             |   7 +-
 .../StreamingChainConfiguration.py            |   2 +-
 .../EventBuildingSequenceSetup.py             |   2 +-
 .../Egamma/ElectronSequenceSetup.py           |   5 +-
 .../Egamma/PhotonSequenceSetup.py             |   6 +-
 .../Egamma/PrecisionCaloSequenceSetup.py      |   3 +-
 .../Egamma/PrecisionElectronSequenceSetup.py  |   7 +-
 .../python/HLTMenuConfig/Menu/CFValidation.py |   3 +
 .../python/HLTMenuConfig/Menu/LS2_v1.py       |  14 +-
 .../HLTMenuConfig/Menu/MenuComponents.py      |   7 +-
 .../HLTMenuConfig/Menu/Physics_pp_run3_v1.py  |   5 +-
 .../MinBias/MinBiasChainConfiguration.py      |   2 +-
 .../HLTMenuConfig/Muon/MuonSequenceSetup.py   |  54 ++--
 .../HLTMenuConfig/Tau/TauRecoSequences.py     |  22 +-
 47 files changed, 897 insertions(+), 953 deletions(-)
 create mode 100644 Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.icc
 delete mode 100644 Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc
 create mode 100644 Trigger/TrigSteer/ViewAlgs/ViewAlgs/IViewCreatorROITool.h
 create mode 100644 Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.icc
 create mode 100644 Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.cxx
 create mode 100644 Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.h
 create mode 100644 Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.cxx
 create mode 100644 Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.h

diff --git a/Control/AthenaConfiguration/python/ComponentAccumulatorTest.py b/Control/AthenaConfiguration/python/ComponentAccumulatorTest.py
index ebed27dc89e..37cd271c226 100644
--- a/Control/AthenaConfiguration/python/ComponentAccumulatorTest.py
+++ b/Control/AthenaConfiguration/python/ComponentAccumulatorTest.py
@@ -445,7 +445,7 @@ class TestMergeComponentsFromDifferentBranches( unittest.TestCase ):
         seq2 = seqAND("seq2")
         innerSeq2 = seqAND("innerSeq2")
 
-        firstAlg = MergeableAlgorithm("alg1", InputMakerInputDecisions=["input1"], InputMakerOutputDecisions=["output1"])
+        firstAlg = MergeableAlgorithm("alg1", InputMakerInputDecisions=["input1"])
 
         ca.addSequence(seq1)
         ca.addSequence(innerSeq1, parentName=seq1.name())
@@ -458,7 +458,7 @@ class TestMergeComponentsFromDifferentBranches( unittest.TestCase ):
         innerSeqCopy = seqAND("innerSeq2")
         level2SeqCopy = seqAND("level2Seq2")
 
-        secondAlg = MergeableAlgorithm("alg1", InputMakerInputDecisions=["input2"], InputMakerOutputDecisions=["output2"])
+        secondAlg = MergeableAlgorithm("alg1", InputMakerInputDecisions=["input2"])
 
         secondCa = ComponentAccumulator()
         secondCa.addSequence(innerSeqCopy)
@@ -472,9 +472,7 @@ class TestMergeComponentsFromDifferentBranches( unittest.TestCase ):
         self.assertEqual(len(foundAlgs), 2)
 
         self.assertEqual(set(foundAlgs[0].InputMakerInputDecisions), {"input1", "input2"})
-        self.assertEqual(set(foundAlgs[0].InputMakerOutputDecisions), {"output1", "output2"})
         self.assertEqual(set(foundAlgs[1].InputMakerInputDecisions), {"input1", "input2"})
-        self.assertEqual(set(foundAlgs[1].InputMakerOutputDecisions), {"output1", "output2"})
 
         ca.printConfig()
         ca.wasMerged()
diff --git a/Control/AthenaConfiguration/python/UnifyProperties.py b/Control/AthenaConfiguration/python/UnifyProperties.py
index 10bc9541d32..97a96abbf0c 100644
--- a/Control/AthenaConfiguration/python/UnifyProperties.py
+++ b/Control/AthenaConfiguration/python/UnifyProperties.py
@@ -76,7 +76,6 @@ _propsToUnify={"GeoModelSvc.DetectorTools":unifySet,
                "dummyService.AList": unifySet,
                "dummyTool.BList" : unifySet,
                "*.InputMakerInputDecisions": unifySet,
-               "*.InputMakerOutputDecisions": unifySet,
                "AddressRemappingSvc.TypeKeyRenameMaps": unifySet,
                "AuditorSvc.Auditors": unifySet,
                "MetaDataSvc.MetaDataTools": unifySet,
diff --git a/Trigger/TrigAlgorithms/TrigEFMissingET/doc/METMenuSequences.md b/Trigger/TrigAlgorithms/TrigEFMissingET/doc/METMenuSequences.md
index 54dd7c3d373..8e4d09e5c77 100644
--- a/Trigger/TrigAlgorithms/TrigEFMissingET/doc/METMenuSequences.md
+++ b/Trigger/TrigAlgorithms/TrigEFMissingET/doc/METMenuSequences.md
@@ -24,7 +24,7 @@ from DecisionHandling.DecisionHandlingConf import InputMakerForRoI
 InputMakerAlg = InputMakerForRoI("MetCellInputMaker", RoIsLink="initialRoI")
 InputMakerAlg.RoIs='METCellRoI'
 InputMakerAlg.InputMakerInputDecisions=[mapThresholdToL1DecisionCollection("XE")]
-InputMakerAlg.InputMakerOutputDecisions=["InputMaker_from_L1MET"]
+InputMakerAlg.InputMakerOutputDecisions="InputMaker_from_L1MET"
 topSequence += InputMakerAlg
 
 from TriggerMenuMT.HLTMenuConfig.MET.METSequences import metCellRecoSequence
diff --git a/Trigger/TrigAlgorithms/TrigT2CaloCommon/python/CaloDef.py b/Trigger/TrigAlgorithms/TrigT2CaloCommon/python/CaloDef.py
index 9517d9cc50c..147e78c881b 100644
--- a/Trigger/TrigAlgorithms/TrigT2CaloCommon/python/CaloDef.py
+++ b/Trigger/TrigAlgorithms/TrigT2CaloCommon/python/CaloDef.py
@@ -1,6 +1,6 @@
 from AthenaCommon.Constants import ERROR
 from AthenaCommon.CFElements import seqAND, parOR
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 
 def setMinimalCaloSetup() :
   from AthenaCommon.AppMgr import ServiceMgr as svcMgr
@@ -76,6 +76,7 @@ def fastCaloEVCreator():
     fastCaloViewsMaker = EventViewCreatorAlgorithm( "IMfastCalo" )
     fastCaloViewsMaker.ViewFallThrough = True
     fastCaloViewsMaker.RoIsLink = "initialRoI"
+    fastCaloViewsMaker.RoITool = ViewCreatorInitialROITool()
     fastCaloViewsMaker.InViewRoIs = InViewRoIs
     fastCaloViewsMaker.Views = "EMCaloViews"
     fastCaloViewsMaker.ViewNodeName = "fastCaloInViewSequence"
@@ -87,7 +88,7 @@ def createFastCaloSequence(EMRoIDecisions, doRinger=False, ClustersName="HLT_L2C
     (fastCaloViewsMaker, InViewRoIs) = fastCaloEVCreator()
     # connect to RoIs
     fastCaloViewsMaker.InputMakerInputDecisions =  [ EMRoIDecisions ]         
-    fastCaloViewsMaker.InputMakerOutputDecisions = [ EMRoIDecisions + "IMOUTPUT"]
+    fastCaloViewsMaker.InputMakerOutputDecisions = EMRoIDecisions + "IMOUTPUT"
 
     (fastCaloInViewSequence, sequenceOut) = fastCaloRecoSequence(InViewRoIs, doRinger=doRinger, ClustersName=ClustersName, RingerKey=RingerKey)
      
diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h
index e56db192ed1..756d4de7603 100644
--- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h
+++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h
@@ -5,8 +5,7 @@
 #ifndef DECISIONHANDLING_INPUTMAKERBASE_H
 #define DECISIONHANDLING_INPUTMAKERBASE_H 1
 
-#include "DecisionHandling/TrigCompositeUtils.h"
-#include "AthenaBaseComps/AthAlgorithm.h"
+#include "TrigCompositeUtils/TrigCompositeUtils.h"
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
 #include "StoreGate/ReadHandleKeyArray.h"
 
@@ -30,41 +29,45 @@ This is a base class for HLT InputMakers to reduce boilerplate and enforce the c
   const SG::ReadHandleKeyArray<TrigCompositeUtils::DecisionContainer>& decisionInputs() const;
 
   /// methods for derived classes to access handles of the base class input and output decisions; other read/write handles may be implemented by derived classes
-  const SG::WriteHandleKeyArray<TrigCompositeUtils::DecisionContainer>& decisionOutputs() const;
+  const SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer>& decisionOutputs() const;
 
   // name of link to the RoI
-  StringProperty m_roisLink { this, "RoIsLink", "initialRoI", "Name of EL to RoI object linked to the decision" };
+  StringProperty m_roisLink {this, "RoIsLink", "initialRoI",
+    "Name of EL to RoI object linked to the decision, used in merging input Decision objects when mergeUsingFeature=False." };
   
+  Gaudi::Property<bool> m_mergeUsingFeature {this, "mergeUsingFeature", false,
+    "True=the IParicle-derived feature from the previous step is used to determine identical inputs. False=the ROI located with the RoIsLink property is used to determine identical inputs" };
+
   // helper methods for derived classes to reduce boiler plate code  //
   /////////////////////////////////////////////////////////////////////
   
   /// provides debug printout of the output of the algorithm
-  void debugPrintOut(const EventContext& context, const std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> >& outputHandles) const;
-
-   /// does the standard handling of input decisions: read from handles with all the checks, create corresponding output handles and link them, copies links and return outputHandles
-  StatusCode decisionInputToOutput(const EventContext& context, std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > & outputHandles) const;
+  void debugPrintOut(const EventContext& context, SG::WriteHandle<TrigCompositeUtils::DecisionContainer>& outputHandle) const;
 
   /// does the standard handling of input decisions: read from handles with all the checks, create merged output handles and link them, copies links and return outputHandles
-  StatusCode decisionInputToMergedOutput(const EventContext& context, std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > & outputHandles) const;
+  StatusCode decisionInputToOutput(const EventContext& context, SG::WriteHandle<TrigCompositeUtils::DecisionContainer>& outputHandle) const;
 
-  /// counts valid input decisions
-  size_t countInputHandles( const EventContext& context ) const;
+  /// Checks for merge-able Decision objects coming from N upstream filters. Check based on stored element link in typed CONTAINER with 'linkNameToMatch'
+  template<typename CONTAINER>
+  size_t matchDecision(const TrigCompositeUtils::DecisionContainer* outDecisions, 
+    const TrigCompositeUtils::Decision* toMatch, 
+    const std::string& linkNameToMatch) const;
 
-    // setting strategy for output creation: merged means one decision per ROI
-  Gaudi::Property<bool>  m_mergeOutputs { this, "mergeOutputs", true, "true=outputs are merged, false=one output per input" };
+  /// Wrapper around matchDecision. Returns boolean if the match was successful.
+  bool matchInCollection(const TrigCompositeUtils::DecisionContainer* toMatchAgainst, 
+    const TrigCompositeUtils::Decision* toMatch,
+    size_t& matchIndex) const;
 
-  
  private:
   
-  /// input decisions, will be implicit (renounced).
+  /// input decisions array, will be implicit (renounced).
   SG::ReadHandleKeyArray<TrigCompositeUtils::DecisionContainer> m_inputs { this, "InputMakerInputDecisions", {}, "Input Decisions (implicit)" };
 
   /// output decisions
-  SG::WriteHandleKeyArray<TrigCompositeUtils::DecisionContainer> m_outputs { this, "InputMakerOutputDecisions", {}, "Ouput Decisions" };
-
-  
+  SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer> m_outputs { this, "InputMakerOutputDecisions", "", "Output Decisions" };
   
 };
 
+#include "InputMakerBase.icc"
 
 #endif // DECISIONHANDLING_INPUTMAKERBASE_H
diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.icc b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.icc
new file mode 100644
index 00000000000..496914524d5
--- /dev/null
+++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.icc
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+template<typename CONTAINER>
+size_t InputMakerBase::matchDecision(const TrigCompositeUtils::DecisionContainer* outDecisions, 
+  const TrigCompositeUtils::Decision* toMatch, 
+  const std::string& linkNameToMatch) const
+{
+  const std::vector<TrigCompositeUtils::LinkInfo<CONTAINER>> myObject = TrigCompositeUtils::findLinks<CONTAINER>(toMatch, linkNameToMatch, TrigDefs::lastFeatureOfType);
+  
+  if (myObject.size() != 1) {
+    ATH_MSG_ERROR("InputMakerBase::matchDecision Did not locate exactly one object of type '" << ClassID_traits<CONTAINER>::typeName() << "' having searched for a link named '" << linkNameToMatch 
+      << "', found " << myObject.size() << ". Unable to match this Decision object.");
+    for (const auto& li : myObject) {
+      ATH_MSG_ERROR("  -- " << li.link.dataID() << ":" << li.link.index() << ". Dump:" << *(li.source)); 
+    }
+    return std::numeric_limits<std::size_t>::max();
+  }
+
+  // Look for match
+  for (size_t index = 0; index < outDecisions->size(); ++index) {
+    const TrigCompositeUtils::Decision* checkDecision = outDecisions->at(index);
+    if (checkDecision == nullptr) {
+      ATH_MSG_ERROR("Failed to get Decision object " << index << " of " << outDecisions->size());
+      return std::numeric_limits<std::size_t>::max();
+    }
+    const std::vector<TrigCompositeUtils::LinkInfo<CONTAINER>> checkObject = TrigCompositeUtils::findLinks<CONTAINER>(checkDecision, linkNameToMatch, TrigDefs::lastFeatureOfType);
+    if (checkObject.size() != 1) {
+      ATH_MSG_ERROR("Logic error. Expect myObject().size() == 1 and checkObject.size() == 1."
+        << " But have checkObject.size() = " << checkObject.size() << ". Unable to match this Decision object.");
+      return std::numeric_limits<std::size_t>::max();
+    }
+    if (myObject.at(0).link == checkObject.at(0).link) {
+      return index;
+    }
+  }
+
+  return std::numeric_limits<std::size_t>::max();
+}
diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc
deleted file mode 100644
index 0bb2f6f8c6e..00000000000
--- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "AthenaKernel/getMessageSvc.h"
-
-namespace TrigCompositeUtils {
-
-  /**
-   * @brief Creates and right away records the Container CONT with the key.
-   * No Aux store.
-   * Returns the WriteHandle. 
-   * If possible provide the context that comes via an argument to execute otherwise it will default to looking it up which is slower.
-   **/
-  template<class CONT>
-  SG::WriteHandle<CONT> createAndStoreNoAux( const SG::WriteHandleKey<CONT>& key, const EventContext& ctx ) {
-    SG::WriteHandle<CONT> handle( key, ctx );
-    auto data = std::make_unique<CONT>() ;
-    if (handle.record( std::move( data ) ).isFailure()) {
-      throw std::runtime_error( "ERROR in TrigCompositeUtils::createAndStoreNoAux Unable to record " + key.key());
-    }
-    return handle;
-  }
-
-  /**
-   * @brief Creates and right away records the Container CONT with the key.
-   * With Aux store.
-   * Returns the WriteHandle. 
-   * If possible provide the context that comes via an argument to execute otherwise it will default to looking it up which is slower.
-   **/
-  template<class CONT, class AUX>
-  SG::WriteHandle<CONT> createAndStoreWithAux( const SG::WriteHandleKey<CONT>& key, const EventContext& ctx ) {
-    SG::WriteHandle<CONT> handle( key, ctx );
-    auto data = std::make_unique<CONT>() ;
-    auto aux = std::make_unique<AUX>() ;
-    data->setStore( aux.get() );
-    if (handle.record( std::move( data ), std::move( aux )  ).isFailure()) {
-      throw std::runtime_error( "ERROR in TrigCompositeUtils::createAndStoreWithAux Unable to record " + key.key());
-    }
-    return handle;
-  }
-
-  template<typename T>
-  void
-  findLinks(const xAOD::TrigComposite* start, const std::string& linkName, std::vector<LinkInfo<T>>& links) {
-    ElementLinkVector<T> featureLinks;
-    if (start->hasObjectCollectionLinks(linkName, ClassID_traits<T>::ID())) {
-      featureLinks = start->objectCollectionLinks<T>(linkName);
-    }
-    if (start->hasObjectLink(linkName, ClassID_traits<T>::ID())) {
-      featureLinks.push_back(start->objectLink<T>(linkName));
-    }
-    for (const ElementLink<T>& featureLink : featureLinks) {
-      // Check for duplicates
-      if (std::none_of(links.begin(), links.end(), [&](const auto& li) { return (li.link == featureLink); } ))
-      {
-        links.emplace_back(start, featureLink);
-      }
-    }
-    // Recursive
-    for (const auto& seed : getLinkToPrevious(start)) {
-      findLinks<T>(*seed, linkName, links);
-    }
-  }
-
-  template<typename T>
-  std::vector<LinkInfo<T>>
-  findLinks(const xAOD::TrigComposite* start, const std::string& linkName) {
-    std::vector<LinkInfo<T>> links;
-    findLinks(start, linkName, links);
-    return links;
-  }
-
-  template<typename T>
-  LinkInfo<T>
-  findLink(const xAOD::TrigComposite* start, const std::string& linkName, const bool suppressMultipleLinksWarning) {
-    std::vector<LinkInfo<T>> links = findLinks<T>(start, linkName);
-    if (links.size() > 1 && !suppressMultipleLinksWarning) {
-      MsgStream(Athena::getMessageSvc(), "TrigCompositeUtils::findLink") << MSG::WARNING
-        << links.size() << " links found for " << linkName
-        << " returning the first link, consider using findLinks." << endmsg;
-    }
-    if (links.size() > 0) {
-      return links.at(0);
-    }
-    return LinkInfo<T>(); // invalid link
-  }
-
-  template<class CONTAINER>
-  void filterLinkVectorByContainerKey(const std::string& containerSGKey, ElementLinkVector<CONTAINER>& vector) {
-    if (containerSGKey == "") {
-      return;
-    }
-    auto it = std::remove_if(vector.begin(), vector.end(), [&](const ElementLink<CONTAINER>& el) {
-      return (el.dataID().find(containerSGKey) == std::string::npos);
-    });
-    // Collection has been re-ordered to put the bad elements at the end
-    vector.erase(it, vector.end());
-  }
-
-  template<class CONTAINER>
-  const std::vector< LinkInfo<CONTAINER> > getFeaturesOfType(
-    const std::vector<ElementLinkVector<DecisionContainer>>& linkVector,
-    const std::string containerSGKey,
-    const bool lastFeatureOfType,
-    const std::string& navElementLinkKey,
-    const DecisionIDContainer chainIDs) {
-
-    std::vector< LinkInfo<CONTAINER> > features;
-    // For each unique path through the navigation for a given chain
-    for (const ElementLinkVector<DecisionContainer>& decisionPath : linkVector) {
-      // For each step along this path, starting at the terminus and working back towards L1
-      for (const ElementLink<DecisionContainer>& decisionObjLink : decisionPath) {
-        const Decision* decisionObj = (*decisionObjLink);
-        ElementLinkVector<CONTAINER> featureLinks;
-
-        // Look up what named links are available in the Decision Object
-        std::vector<std::string> availableLinkNames;
-        if (navElementLinkKey == "") { 
-          const std::vector<std::string> getSingleLinkNames = decisionObj->getObjectNames<CONTAINER>();
-          const std::vector<std::string> getCollectionLinkNames = decisionObj->getObjectCollectionNames<CONTAINER>();
-          std::copy(getSingleLinkNames.begin(), getSingleLinkNames.end(), std::back_inserter(availableLinkNames));
-          std::copy(getCollectionLinkNames.begin(), getCollectionLinkNames.end(), std::back_inserter(availableLinkNames));
-        } else { // Just looking for an explicitly named feature
-          availableLinkNames.push_back( navElementLinkKey );
-        }
-
-        // Fetch the named links that we're interested in
-        for (const std::string& featureNameToGet : availableLinkNames) {
-          // This try block protects against ExcCLIDMismatch throws from
-          // features which do not derive from IParticle, when an IParticle interface is requested.
-          try {
-            // Slices may have added link collections. These links may have been to objects in different containers.
-            if (decisionObj->hasObjectCollectionLinks(featureNameToGet, ClassID_traits< CONTAINER >::ID())) {
-              ElementLinkVector<CONTAINER> collectionLinks = decisionObj->objectCollectionLinks<CONTAINER>( featureNameToGet );
-              filterLinkVectorByContainerKey<CONTAINER>(containerSGKey, collectionLinks);
-              std::copy(collectionLinks.begin(), collectionLinks.end(), std::back_inserter(featureLinks));
-            }
-          } catch (SG::ExcCLIDMismatch&) {
-            // This is in place to catch the exception caused by non-IParticle features when an IParticle interface is requested.
-            // We're fine to catch this silently and cary on looking at the next Decision object in the graph
-          }
-          try {
-            // Slices may have added single links. Note: the framework-specified "feature" link is always a single link.
-            if (decisionObj->hasObjectLink(featureNameToGet, ClassID_traits< CONTAINER >::ID())) {
-              ElementLinkVector<CONTAINER> singleEntryVector; // Filtering function operates on a vector
-              singleEntryVector.push_back( decisionObj->objectLink<CONTAINER>( featureNameToGet ) );
-              filterLinkVectorByContainerKey<CONTAINER>(containerSGKey, singleEntryVector);
-              std::copy(singleEntryVector.begin(), singleEntryVector.end(), std::back_inserter(featureLinks));
-            }
-          } catch (SG::ExcCLIDMismatch&) {
-            // Silently. As above.
-          }
-        }
-
-        // Check if the Decsision object is active for a specific set of Chains-of-interest (as supplied by the TDT)
-        ActiveState state = ActiveState::UNSET;
-        if (chainIDs.size() > 0) {
-          // If we were given a list of chains to consider then we start assuming none passed this decisionObj
-          state = ActiveState::INACTIVE;
-          for (DecisionID id : chainIDs) {
-            if (std::count(decisionObj->decisions().begin(), decisionObj->decisions().end(), id) == 1) {
-              state = ActiveState::ACTIVE;
-              break;
-            }
-          }
-        }
-
-        // Copy the fetched links into the return vector
-        for (const ElementLink<CONTAINER>& featureLink : featureLinks) {
-          typename std::vector<LinkInfo<CONTAINER>>::iterator vecIt = std::find_if(features.begin(), features.end(), [&](const auto& li) { return li.link == featureLink; } );
-          if (vecIt == features.end()) {
-            // Link did not already exist - add it to the output
-            features.emplace_back( decisionObj, featureLink, state );
-          } else {
-            // Link already existed - if the link's state in the return vector is INACTIVE but is ACTIVE here,
-            // then we need to change it to ACTIVE as this denotes one-or-more of the requested chains were active for the object.
-            if (vecIt->state == ActiveState::INACTIVE) {
-              vecIt->state = ActiveState::ACTIVE;
-            }
-          }
-        }
-
-        // Stop processing this path through the navigation if the lastFeatureOfType flag is set
-        if (featureLinks.size() && lastFeatureOfType) {
-          break;
-        }
-
-      } // for (decisionLink : decisionPath)
-    } // for (decisionPath : linkVector)
-    return features;
-  }
-
-}
diff --git a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
index 249351a5aee..42dd49638ff 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
@@ -18,13 +18,12 @@ const SG::ReadHandleKeyArray<TrigCompositeUtils::DecisionContainer>& InputMakerB
   return m_inputs;
 }
 
-const SG::WriteHandleKeyArray<TrigCompositeUtils::DecisionContainer>& InputMakerBase::decisionOutputs() const{
+const SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer>& InputMakerBase::decisionOutputs() const{
   return m_outputs;
 }
 
 StatusCode InputMakerBase::sysInitialize() {
   CHECK( AthReentrantAlgorithm::sysInitialize() ); // initialise base class
-  ATH_MSG_DEBUG("mergeOutputs is "<<m_mergeOutputs);
   CHECK( m_inputs.initialize() );
   renounceArray(m_inputs); // make inputs implicit, i.e. not required by scheduler
   ATH_MSG_DEBUG("Will consume implicit decisions:" );
@@ -32,120 +31,72 @@ StatusCode InputMakerBase::sysInitialize() {
     ATH_MSG_DEBUG( " "<<input.key() );
   }
   CHECK( m_outputs.initialize() );
-  ATH_MSG_DEBUG(" and produce decisions: ");
-  for (auto& output: m_outputs){  
-    ATH_MSG_DEBUG( " "<<output.key() );
-  }
-  return StatusCode::SUCCESS;
+  ATH_MSG_DEBUG(" and produce decisions: " << m_outputs.key());
+  return StatusCode::SUCCESS; 
 }
 
-
-// For each input Decision in the input container, create an output Decision in the corresponding output container and link them.
+// Create one output container and merge all inputs into this, using heuristics to identify equal Decision objects.
 // If the input is invalid or empty, the output is not created, resulting as invalid
-StatusCode InputMakerBase::decisionInputToOutput(const EventContext& context, std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > & outputHandles) const{
-
-  if (!m_mergeOutputs)   ATH_MSG_DEBUG("Creating one output per input");
-  else                   ATH_MSG_DEBUG("Creating one merged output per RoI");
-
-  outputHandles = decisionOutputs().makeHandles(context);
-  //size_t tot_inputs = countInputHandles( context );
-  size_t outputIndex = 0;
-  TrigCompositeUtils::DecisionContainer* outDecisions  = nullptr;
-  if (m_mergeOutputs){
-    TrigCompositeUtils::createAndStore(outputHandles[outputIndex]); // one only
-    outDecisions = outputHandles[outputIndex].ptr();
-  }
+StatusCode InputMakerBase::decisionInputToOutput(const EventContext& context, SG::WriteHandle<TrigCompositeUtils::DecisionContainer>& outputHandle) const{
 
-  // If using m_mergeOutputs, then collate all RoIs that are stored in this input container
-  ElementLinkVector<TrigRoiDescriptorCollection> RoIsFromDecision;
+  ATH_MSG_DEBUG("Creating one merged output per Decision object");
+  ATH_CHECK( outputHandle.isValid() );
+  TrigCompositeUtils::DecisionContainer* outDecisions  = outputHandle.ptr();
 
-  
   for ( auto inputKey: decisionInputs() ) {
     auto inputHandle = SG::makeHandle( inputKey, context );
 
     if( not inputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from input "<< inputKey.key() << " because handle not valid");
-      outputIndex++;
+      ATH_MSG_DEBUG( "Got no decisions from input "<< inputKey.key() << " because implicit handle not valid");
       continue;
     }
-    if( inputHandle->size() == 0){ // input filtered out
-      ATH_MSG_DEBUG( "Got no decisions from input "<< inputKey.key()<<": handle is valid but container is empty.");
-      outputIndex++;
+    if( inputHandle->size() == 0){
+      ATH_MSG_DEBUG( "Got no decisions from input "<< inputKey.key()<<": implicit handle is valid but container is empty.");
       continue;
     }
     ATH_MSG_DEBUG( "Running on input "<< inputKey.key()<<" with " << inputHandle->size() << " elements" );
     
-    // We have an input container with >= 1 Decision objects. Create an output container with the same index.
-    if (! m_mergeOutputs){
-      TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
-      outDecisions = outputHandles[outputIndex].ptr();
-    }
 
+    size_t input_counter = 0;
+    for (const TrigCompositeUtils::Decision* inputDecision : *inputHandle){
+      ATH_MSG_DEBUG( " -- Input Decision " << input_counter <<": has " <<TrigCompositeUtils::getLinkToPrevious(inputDecision).size()<<" previous links");
 
-    // loop over decisions retrieved from this input
-    size_t input_counter =0;
+      size_t alreadyAddedIndex = std::numeric_limits<std::size_t>::max();
+      const bool alreadyAdded = matchInCollection(outDecisions, inputDecision, alreadyAddedIndex);
 
-    for (const TrigCompositeUtils::Decision* inputDecision : *inputHandle){
-      ATH_MSG_DEBUG( "  - Input Decision "<<input_counter <<": has " <<TrigCompositeUtils::getLinkToPrevious(inputDecision).size()<<" previous links");
       TrigCompositeUtils::Decision* newDec = nullptr;
-      bool addDecision = false;
-      ElementLink<TrigRoiDescriptorCollection> roiEL = ElementLink<TrigRoiDescriptorCollection>();
-      
-      if (m_mergeOutputs){
-        // Get RoI from this input decision 
-        const auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( inputDecision,  m_roisLink.value());
-        CHECK( roiELInfo.isValid() );      
-        roiEL = roiELInfo.link;
-        const auto roiIt = std::find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
-        addDecision = (roiIt == RoIsFromDecision.end());
-        // addDecision is positive here if we have *not* before encountered this RoI within this input collection.
-        if (addDecision) {
-          RoIsFromDecision.push_back(roiEL); // To keep track of which we have used
-          ATH_MSG_DEBUG( "  -- Found new RoI:" << **roiEL <<": creating new decision");
-        }
-	else{
-	  ATH_MSG_DEBUG( "  -- Found old RoI:" << **roiEL <<": merging to this one");
-	}
-      } else { // Not merging, keep a 1-to-1 mapping of Decisions in Input & Output containers
-        addDecision=true;
-      }
-
-      if ( addDecision ){
-        // Create a new Decision in the Output container to mirror one in the Input container
+      if (alreadyAdded) { // Already added, at alreadyAddedIndex
+        newDec = outDecisions->at( alreadyAddedIndex );
+        ATH_MSG_DEBUG( "  -- Matched to existing, " << inputKey.key() << " index " << input_counter << " is merged into existing output index " << alreadyAddedIndex);
+      } else { // Not already added, make new
         newDec = TrigCompositeUtils::newDecisionIn( outDecisions );
-      } else{
-        // addDecision can only be false if m_mergeOutputs was true and roiEL was found within RoIsFromDecision
-        // Re-use a Decision already added to the Output container 
-        const auto roiIt = std::find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
-        if (roiIt == RoIsFromDecision.end()) {
-          ATH_MSG_ERROR("Logic error in decisionInputToOutput. Cannot find existing RoI.");
-          return StatusCode::FAILURE;
-        }
-        const size_t roiCounter = std::distance( RoIsFromDecision.begin(), roiIt );
-        newDec = outDecisions->at(roiCounter);
-	ATH_MSG_DEBUG("Merging with output decision n. "<< roiCounter);
+        ATH_MSG_DEBUG( "  -- Did not match to existing, " << inputKey.key() << " index " << input_counter << " creates output index " << outDecisions->size()-1);
       }
 
-      // if merged output, there are more than one seed: is it ok?
+      // Note: We will call linkToPrevious and insertDecisionIDs N times on a single "newDec", where N is the number of inputDecision which checkExisting determines are the same object.
       TrigCompositeUtils::linkToPrevious( newDec, inputDecision, context ); // Link inputDecision object as the 'seed' of newDec
       TrigCompositeUtils::insertDecisionIDs( inputDecision, newDec ); // Copy decision IDs from inputDecision into newDec
-      TrigCompositeUtils::DecisionIDContainer objDecisions;      
-      TrigCompositeUtils::decisionIDs( newDec, objDecisions );    
-      ATH_MSG_DEBUG("  -- This output decision has now "<< (TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( newDec,  m_roisLink.value())).isValid() <<" valid "<<m_roisLink.value() <<", "<< TrigCompositeUtils::getLinkToPrevious(newDec).size() <<" seeds and "<<objDecisions.size()<<" decisionIds");     
+      ATH_MSG_DEBUG("      -- This output decision now has " << TrigCompositeUtils::getLinkToPrevious(newDec).size() << " seeds and "<< newDec->decisions().size() << " decisionIds");           
       input_counter++;  
     } // loop over input decisions
 
-    if (! m_mergeOutputs)
-      ATH_MSG_DEBUG( "Filled output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<<outDecisions->size()  <<" at index "<< outputIndex);
-    outputIndex++;
-  } // end of first loop over input keys
+  } // end of: for ( auto inputKey: decisionInputs() )
 
   return StatusCode::SUCCESS;
 }
 
 
+bool InputMakerBase::matchInCollection(const DecisionContainer* toMatchAgainst, const Decision* toMatch, size_t& matchIndex) const {
+  if ( m_mergeUsingFeature ) {
+    matchIndex = matchDecision<xAOD::IParticleContainer>(toMatchAgainst, toMatch, featureString());
+  } else {
+    matchIndex = matchDecision<TrigRoiDescriptorCollection>(toMatchAgainst, toMatch, m_roisLink.value());
+  }
+  return (matchIndex != std::numeric_limits<std::size_t>::max());
+}
+
 
-void InputMakerBase::debugPrintOut(const EventContext& context, const std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> >& outputHandles) const{
+void InputMakerBase::debugPrintOut(const EventContext& context, SG::WriteHandle<TrigCompositeUtils::DecisionContainer>& outputHandle) const{
   size_t validInput=0;
   for ( auto inputKey: decisionInputs() ) {
     auto inputHandle = SG::makeHandle( inputKey, context );
@@ -158,47 +109,16 @@ void InputMakerBase::debugPrintOut(const EventContext& context, const std::vecto
       }
     }
   }
-  ATH_MSG_DEBUG( "number of implicit ReadHandles for input decisions is " << decisionInputs().size() << ", " << validInput << " are valid/notempty" );
+  ATH_MSG_DEBUG( "Number of implicit ReadHandles for input decisions is " << decisionInputs().size() << ", " << validInput << " are valid/not-empty" );
   
-  size_t validOutput=0;
-  for ( auto outHandle: outputHandles ) {
-    if( not outHandle.isValid() ) continue;
-    validOutput++;
-  }
-  ATH_MSG_DEBUG("Produced " << validOutput << " valid/notempty output decisions containers");
-  if (! m_mergeOutputs){
-    if(validInput != validOutput) {
-      ATH_MSG_ERROR("Found valid/notempty: " << validInput << " inputs and " << validOutput << " outputs");
-    }
-  }
-  
-  for ( auto outHandle: outputHandles ) {
-    if( not outHandle.isValid() ) continue;
-    ATH_MSG_DEBUG(outHandle.key() <<" with "<< outHandle->size() <<" decisions:");
-    for (auto outdecision:  *outHandle){
-      TrigCompositeUtils::DecisionIDContainer objDecisions;      
-      TrigCompositeUtils::decisionIDs( outdecision, objDecisions );    
-      ATH_MSG_DEBUG("Number of positive decisions for this output: " << objDecisions.size() );
-      for ( TrigCompositeUtils::DecisionID id : objDecisions ) {
-        ATH_MSG_DEBUG( " ---  decision " << HLT::Identifier( id ) );
-      }  
-    }
+  ATH_MSG_DEBUG("Output " << outputHandle.key() <<" with "<< outputHandle->size() <<" decisions:");
+  for (const auto outdecision : *outputHandle){
+    TrigCompositeUtils::DecisionIDContainer objDecisions;      
+    TrigCompositeUtils::decisionIDs( outdecision, objDecisions );    
+    ATH_MSG_DEBUG("Number of positive decisions for this output: " << objDecisions.size() );
+    for ( TrigCompositeUtils::DecisionID id : objDecisions ) {
+      ATH_MSG_DEBUG( " ---  decision " << HLT::Identifier( id ) );
+    }  
   }
 }
 
-
-
-size_t InputMakerBase::countInputHandles( const EventContext& context ) const {
-  size_t validInputCount=0;
-  for ( auto &inputKey: decisionInputs() ) {
-    auto inputHandle = SG::makeHandle( inputKey, context );
-    ATH_MSG_DEBUG(" "<<inputKey.key()<<(inputHandle.isValid()? " is valid": " is not valid" ) );
-    if (inputHandle.isValid()) validInputCount++;
-  }
-  ATH_MSG_DEBUG( "number of implicit ReadHandles is " << decisionInputs().size() <<", "<< validInputCount<<" are valid" );
-  return validInputCount;
-}
-
-
-
-
diff --git a/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.cxx b/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.cxx
index 1907b463a2e..eb4be8cb27c 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.cxx
@@ -13,6 +13,7 @@ using TrigCompositeUtils::Decision;
 using TrigCompositeUtils::linkToPrevious;
 using TrigCompositeUtils::getLinkToPrevious;
 using TrigCompositeUtils::findLink;
+using TrigCompositeUtils::createAndStore;
 
 InputMakerForRoI:: InputMakerForRoI( const std::string& name, 
  ISvcLocator* pSvcLocator )    
@@ -28,9 +29,10 @@ StatusCode  InputMakerForRoI::initialize() {
 StatusCode  InputMakerForRoI::execute( const EventContext& context ) const {
   ATH_MSG_DEBUG( "Executing " << name() << "..." );
   
-  // call base class helper method to read input decisions, loop over them create outputs and connect them, returns with outputHandles filled
-  std::vector< SG::WriteHandle<DecisionContainer> > outputHandles;
-  ATH_CHECK (decisionInputToOutput(context, outputHandles));
+  // create the output decisions from the input collections
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore( decisionOutputs(), context );
+  ATH_CHECK(decisionInputToOutput(context, outputHandle));
+  ATH_CHECK(outputHandle.isValid());
   
   // Prepare Outputs
   std::unique_ptr< TrigRoiDescriptorCollection > oneRoIColl( new TrigRoiDescriptorCollection() );
@@ -38,39 +40,34 @@ StatusCode  InputMakerForRoI::execute( const EventContext& context ) const {
   // use also this:    ElementLinkVector<xAOD::MuonRoIContainer> getMuonRoILinks = obj->objectCollectionLinks<xAOD::MuonRoIContainer>("ManyMuonRoIs");
   std::vector <ElementLink<TrigRoiDescriptorCollection> > RoIsFromDecision;  // used to check for duplicate features linked to different inputHandles
 
-  // loop over output decisions, navigate to inputs
-  for (auto outputHandle: outputHandles) {
-    if( not outputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key() << " because handle not valid");
-      continue;
-    }
-    if( outputHandle->size() == 0){ // input filtered out
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty.");
-      continue;
-    }
-    ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
-    // loop over output decisions in container of outputHandle, follow link to inputDecision
-    for ( auto outputDecision : *outputHandle){ 
-      ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
-      for (auto input: inputLinks){
-        const Decision* inputDecision = *input;
-        auto roiELInfo = findLink<TrigRoiDescriptorCollection>( inputDecision, m_roisLink.value() );
-        auto roiEL = roiELInfo.link;
-        ATH_CHECK( roiEL.isValid() );
+  if( outputHandle->size() == 0) {
+    ATH_MSG_WARNING( "Have no decisions in output handle "<< outputHandle.key() << ". Handle is valid but container is empty. "
+      << "Check why this EventViewCreatorAlgorithm was unlocked by a Filter, if the Filter then gave it no inputs.");
+    return StatusCode::SUCCESS;
+  }
 
-        // avoid adding the same feature multiple times: check if not in container, if not add it
-        if ( find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL) == RoIsFromDecision.end() ) {
-          RoIsFromDecision.push_back(roiEL); // just to keep track of which we have used 
-          const TrigRoiDescriptor* roi = *roiEL;
-          ATH_MSG_DEBUG("Found RoI:" <<*roi<<" FS="<<roi->isFullscan());
-          //make a new one:
-          TrigRoiDescriptor* newroi= new TrigRoiDescriptor(*roi); //use copy constructor
-          oneRoIColl->push_back(newroi);
-          ATH_MSG_DEBUG("Added RoI:" <<*newroi<<" FS="<<newroi->isFullscan());
-        }
-      } // loop over previous input links           
-    } // loop over decisions      
-  } // loop over output keys
+  ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
+  // loop over output decisions in container of outputHandle, follow link to inputDecision
+  for ( auto outputDecision : *outputHandle){ 
+    ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
+    for (auto input: inputLinks){
+      const Decision* inputDecision = *input;
+      auto roiELInfo = findLink<TrigRoiDescriptorCollection>( inputDecision, m_roisLink.value() );
+      auto roiEL = roiELInfo.link;
+      ATH_CHECK( roiEL.isValid() );
+
+      // avoid adding the same feature multiple times: check if not in container, if not add it
+      if ( find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL) == RoIsFromDecision.end() ) {
+        RoIsFromDecision.push_back(roiEL); // just to keep track of which we have used 
+        const TrigRoiDescriptor* roi = *roiEL;
+        ATH_MSG_DEBUG("Found RoI:" <<*roi<<" FS="<<roi->isFullscan());
+        //make a new one:
+        TrigRoiDescriptor* newroi= new TrigRoiDescriptor(*roi); //use copy constructor
+        oneRoIColl->push_back(newroi);
+        ATH_MSG_DEBUG("Added RoI:" <<*newroi<<" FS="<<newroi->isFullscan());
+      }
+    } // loop over previous input links           
+  } // loop over decisions      
   
   
     // Finally, record output
@@ -79,7 +76,9 @@ StatusCode  InputMakerForRoI::execute( const EventContext& context ) const {
   ATH_CHECK( roi_outputHandle.record(std::move(oneRoIColl)) );
   
   // call base class helper method to print some debug messages summarising the content of the outputHandles.
-  if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandles);
+  if (msgLvl(MSG::DEBUG)) {
+    debugPrintOut(context, outputHandle);
+  }
 
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h b/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h
index 3cea7e6f60f..e3de1291347 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h
@@ -26,9 +26,7 @@
     virtual StatusCode  execute(const EventContext&) const override;
 
   private: 
-    SG::WriteHandleKey<TrigRoiDescriptorCollection> m_RoIs {this,"RoIs", "Unspecified", "Nam eof the RoIs extracted from the decisions"};
-    // want to try also const?
-    //SG::WriteHandleKey< ConstDataVector<TrigRoiDescriptorCollection> > m_RoIs{ this, "RoIs", "Unspecified", "Name of the RoIs extracted from the decisions" };
+    SG::WriteHandleKey<TrigRoiDescriptorCollection> m_RoIs {this,"RoIs", "Unspecified", "Name of the RoIs extracted from the decisions"};
 
   }; 
 
diff --git a/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt b/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt
index e1fc6e80028..8b226cf74b3 100644
--- a/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt
+++ b/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt
@@ -3,6 +3,11 @@
 # Declare the package name.
 atlas_subdir( TrigCompositeUtils )
 
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Trigger/TrigEvent/TrigDecisionInterface 
+                        )
+
 # Set up the (non-)standalone compilation.
 set( extra_srcs )
 set( extra_libs )
diff --git a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h
index 335d7e29ed2..fa3fff465c6 100644
--- a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h
+++ b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h
@@ -22,6 +22,8 @@
 #include "xAODTrigger/TrigCompositeContainer.h"
 #include "xAODTrigger/TrigCompositeAuxContainer.h"
 
+#include "TrigDecisionInterface/Conditions.h"
+
 #include "HLTIdentifier.h"
 
 namespace TrigCompositeUtils {
@@ -294,19 +296,20 @@ namespace TrigCompositeUtils {
       : source{s}, link{l}, state{as} {}
 
     bool isValid() const {
-      return source && link.isValid(); }
+      return source && link.isValid();
+    }
     /**
      * @brief helper conversion to make it usable with CHECK macro expecting StatusCode
      */
     operator StatusCode () {
-      return (isValid() ? StatusCode::SUCCESS : StatusCode::FAILURE); }
+      return (isValid() ? StatusCode::SUCCESS : StatusCode::FAILURE);
+    }
 
     const xAOD::TrigComposite *source;
     ElementLink<T> link;
     ActiveState state;
   };
 
-
   /// @name Constant string literals used within the HLT
   /// @{
   const std::string& initialRoIString();
@@ -362,7 +365,7 @@ namespace TrigCompositeUtils {
    */
   template<typename T>
   void
-  findLinks(const xAOD::TrigComposite* start, const std::string& linkName, std::vector<LinkInfo<T>>& links);
+  findLinks(const xAOD::TrigComposite* start, const std::string& linkName, std::vector<LinkInfo<T>>& links, unsigned int behaviour = TrigDefs::allFeaturesOfType);
 
   /**
    * @brief search back the TC links for the object of type T linked to the one of TC (recursively)
@@ -373,7 +376,7 @@ namespace TrigCompositeUtils {
    */
   template<typename T>
   std::vector<LinkInfo<T>>
-  findLinks(const xAOD::TrigComposite* start, const std::string& linkName);
+  findLinks(const xAOD::TrigComposite* start, const std::string& linkName, unsigned int behaviour = TrigDefs::allFeaturesOfType);
 
 
   /**
diff --git a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.icc b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.icc
index f80bcc6ebb3..7233c3560bf 100644
--- a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.icc
+++ b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.icc
@@ -42,7 +42,7 @@ namespace TrigCompositeUtils {
 
   template<typename T>
   void
-  findLinks(const xAOD::TrigComposite* start, const std::string& linkName, std::vector<LinkInfo<T>>& links) {
+  findLinks(const xAOD::TrigComposite* start, const std::string& linkName, std::vector<LinkInfo<T>>& links, unsigned int behaviour) {
     ElementLinkVector<T> featureLinks;
     if (start->hasObjectCollectionLinks(linkName, ClassID_traits<T>::ID())) {
       featureLinks = start->objectCollectionLinks<T>(linkName);
@@ -50,24 +50,49 @@ namespace TrigCompositeUtils {
     if (start->hasObjectLink(linkName, ClassID_traits<T>::ID())) {
       featureLinks.push_back(start->objectLink<T>(linkName));
     }
+    const bool linkFound = (featureLinks.size() > 0);
     for (const ElementLink<T>& featureLink : featureLinks) {
       // Check for duplicates
-      if (std::none_of(links.begin(), links.end(), [&](const auto& li) { return (li.link == featureLink); } ))
+      if (std::none_of(links.begin(), links.end(), 
+        [&](const auto& li) { 
+          if (li.link == featureLink) {
+            if (li.source != start && linkName != initialRoIString() && linkName != roiString()) {
+              // Leaving this warning in for now, but there are known cases of the FS ROI being re-used
+              // in multiple outputs from the L1 decoder. E.g. HLTNav_L1J:0 and HLTNav_L1MET:0
+              // so supressing for initialRoIString().
+              // Similar case for tau, just with an ROI created in Step1
+              const auto A = decisionToElementLink(start);
+              const auto B = decisionToElementLink(li.source);
+              MsgStream(Athena::getMessageSvc(), "TrigCompositeUtils::findLink") << MSG::WARNING
+                << "Found '" << linkName << "' by multiple paths, but "
+                << "the links are coming from different places in the navigation graph. " << std::endl
+                << "From A:" << A.dataID() << ":" << A.index() << " Dump:" << std::endl << *start << std::endl
+                << "From B:" << B.dataID() << ":" << B.index() << " Dump:" << std::endl << *(li.source) << endmsg;
+            }
+            return true;
+          }
+          return false;
+        }
+        ))
       {
         links.emplace_back(start, featureLink);
       }
     }
-    // Recursive
+    // Early exit
+    if (linkFound && behaviour == TrigDefs::lastFeatureOfType) {
+      return;
+    }
+    // If not Early Exit, then recurse
     for (const auto& seed : getLinkToPrevious(start)) {
-      findLinks<T>(*seed, linkName, links);
+      findLinks<T>(*seed, linkName, links, behaviour);
     }
   }
 
   template<typename T>
   std::vector<LinkInfo<T>>
-  findLinks(const xAOD::TrigComposite* start, const std::string& linkName) {
+  findLinks(const xAOD::TrigComposite* start, const std::string& linkName, unsigned int behaviour) {
     std::vector<LinkInfo<T>> links;
-    findLinks(start, linkName, links);
+    findLinks(start, linkName, links, behaviour);
     return links;
   }
 
diff --git a/Trigger/TrigSteer/ViewAlgs/ViewAlgs/IViewCreatorROITool.h b/Trigger/TrigSteer/ViewAlgs/ViewAlgs/IViewCreatorROITool.h
new file mode 100644
index 00000000000..a9df7caa588
--- /dev/null
+++ b/Trigger/TrigSteer/ViewAlgs/ViewAlgs/IViewCreatorROITool.h
@@ -0,0 +1,39 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef VIEWALGS_IVIEWCREATORROITOOL_H
+#define VIEWALGS_IVIEWCREATORROITOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/StatusCode.h"
+#include "GaudiKernel/Property.h"
+#include "DecisionHandling/TrigCompositeUtils.h"
+
+/**
+ * @class IViewCreatorROITool
+ * MT Trigger Tool interface used to determine the correct ROI to spawn an EventView on for a given Decision object.
+ **/
+class IViewCreatorROITool : virtual public IAlgTool
+{
+public:
+
+  DeclareInterfaceID(IViewCreatorROITool, 1, 0);
+
+  virtual ~IViewCreatorROITool() = default;
+
+/**
+ * @brief Supply ROIs for the Decision objects in the mutable decisions container.
+ * For each entry in decisions, the tool is expected to either locate an existing ROI in the history of the Decision object
+ * (e.g. the initialRoI). Or, to create a new ROIDescriptor (e.g. by getting the "feature" from the Decision object and 
+ * constructing an ROI around it) and to store this new ROI in an output collection. In this later case, the concrete tool
+ * should register a SG::WriteHandle<TrigRoiDescriptorCollection> in which to store these new ROI.
+ *
+ * Either way, the new ROI should be linked to the Decision object for use in the parent EventViewCreatorAlgorithm via
+ * decision->setObjectLink(TrigCompositeUtils::roiString(), roiElementLink);
+ **/
+  virtual StatusCode attachROILinks(TrigCompositeUtils::DecisionContainer& decisions, const EventContext& ctx) const = 0;
+
+};
+
+#endif //> !VIEWALGS_IVIEWCREATORROITOOL_H
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
index d40074bceb0..e4dd872746f 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
@@ -10,6 +10,8 @@
 #include "AthViews/View.h"
 #include "DecisionHandling/TrigCompositeUtils.h"
 
+#include <sstream>
+
 using namespace TrigCompositeUtils;
 
 EventViewCreatorAlgorithm::EventViewCreatorAlgorithm( const std::string& name, ISvcLocator* pSvcLocator )
@@ -21,213 +23,155 @@ StatusCode EventViewCreatorAlgorithm::initialize() {
   ATH_MSG_DEBUG("Will produce views=" << m_viewsKey << " roIs=" << m_inViewRoIs );
   ATH_CHECK( m_viewsKey.initialize() );
   ATH_CHECK( m_inViewRoIs.initialize() );
+  ATH_CHECK( m_roiTool.retrieve() );
+  ATH_CHECK( m_cachedViewsKey.initialize(SG::AllowEmpty) );
   return StatusCode::SUCCESS;
 }
 
 
 StatusCode EventViewCreatorAlgorithm::execute( const EventContext& context ) const {
 
-   if (m_mergeOutputs)
-    return executeMerged(context);
-
-  // create the output decisions, similar to inputs (copy basic links)
-  std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > outputHandles;
-  ATH_CHECK (decisionInputToOutput(context, outputHandles));
+   // create the output decisions from the input collections
+  ATH_MSG_DEBUG("Starting to merge " << decisionInputs().size() << " inputs to the " << decisionOutputs().key() << " output.");
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore( decisionOutputs(), context );
+  ATH_CHECK(outputHandle.isValid());
+  ATH_CHECK(decisionInputToOutput(context, outputHandle));
+  ATH_MSG_DEBUG("Merging complete");
 
- 
   // make the views
-  auto viewsHandle = SG::makeHandle( m_viewsKey, context );
-  auto viewVector1 = std::make_unique< ViewContainer >();
-  ATH_CHECK( viewsHandle.record(  std::move( viewVector1 ) ) );
+  auto viewsHandle = SG::makeHandle( m_viewsKey, context ); 
+  ATH_CHECK( viewsHandle.record( std::make_unique<ViewContainer>() ) );
   auto viewVector = viewsHandle.ptr();
-  unsigned int viewCounter = 0;
-
-  //map all RoIs that are stored
-  ElementLinkVector<TrigRoiDescriptorCollection> RoIsFromDecision;
-
-  // loop over decisions
-  for (auto outputHandle: outputHandles) {
-    if( not outputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key() << " because handle not valid");
-      continue;
-    }
-
-    if( outputHandle->size() == 0){ // input filtered out
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty.");
-      continue;
-    }
-    ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
-    // loop over output decisions in container of outputHandle, follow link to inputDecision
-    for ( auto outputDecision : *outputHandle){ 
-      ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
-      ATH_MSG_DEBUG( "Got inputLinks with " << inputLinks.size() << " elements" );
-      // loop over input links as predecessors
-      for (auto input: inputLinks){
-        const Decision* inputDecision = *input;
-        // find the RoI
-        const auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( inputDecision, m_roisLink.value() );
-        const auto roiEL = roiELInfo.link;
-        ATH_CHECK( roiEL.isValid() );
-        // check if already found
-        auto roiIt=find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
-        if ( roiIt == RoIsFromDecision.end() ){
-          RoIsFromDecision.push_back(roiEL); // just to keep track of which we have used
-          ATH_MSG_DEBUG("Found RoI:" <<**roiEL<<" FS="<<(*roiEL)->isFullscan());
-          ATH_MSG_DEBUG("Positive decisions on RoI, making view" );
-	  // make the view
-          auto newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough ); //pointer to the view
-
-          // Use a fall-through filter if one is provided
-          if ( m_viewFallFilter.size() ) {
-            newView->setFilter( m_viewFallFilter );
-          }
-
-          viewVector->push_back( newView );
-          
-          // link decision to this view
-          outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
-          ATH_MSG_DEBUG( "Adding new view to new decision; storing view in viewVector component " << viewVector->size()-1 );
-          ATH_CHECK( linkViewToParent( inputDecision, viewVector->back() ) );
-          ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
-        }
-        else {
-          int iview = roiIt - RoIsFromDecision.begin();
-          auto theview = viewVector->at(iview);
-	  // check that this view is not already linked to this decision (this is true if the mergerd output is enabled)
-	  const auto existView = TrigCompositeUtils::findLink<ViewContainer> (outputDecision, TrigCompositeUtils::viewString());
-	  const auto existViewLink= existView.link;
-	  if (existViewLink.isValid() && existViewLink == ElementLink< ViewContainer >(m_viewsKey.key(), iview )){
-	    ATH_MSG_DEBUG( "View  already linked, doing nothing");
-	  } else if (existViewLink.isValid()){
-	    ATH_MSG_ERROR( "View already linked, but it is the wrong view! Configuration problem. Got " << existViewLink.index() << ", expected " << iview);
-            return StatusCode::FAILURE;
-          } else {
-	    outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), iview ) ); //adding view to TC
-	    ATH_MSG_DEBUG( "Adding already mapped view " << iview << " in ViewVector , to new decision");
-	    ATH_CHECK( linkViewToParent( inputDecision, theview ) );
-	  }
-        }
-      }// loop over previous inputs
-    } // loop over decisions
-  }// loop over output keys
-
-  // launch view execution
-  ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
-  ATH_CHECK( ViewHelper::scheduleViews( viewVector,           // Vector containing views
-					m_viewNodeName,       // CF node to attach views to
-					context,              // Source context
-					getScheduler(),
-					m_reverseViews ) );
-  
-  // report number of views, stored already when container was created
-  // auto viewsHandle = SG::makeHandle( m_viewsKey );
-  // ATH_CHECK( viewsHandle.record(  std::move( viewVector ) ) );
-  ATH_MSG_DEBUG( "Store "<< viewsHandle->size() <<" Views");
 
-  if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandles);
-  return StatusCode::SUCCESS;
-}
+  // Check for an optional input handle to use as a source of cached, already-executed, views.
+  const DecisionContainer* cachedViews = nullptr;
+  if (!m_cachedViewsKey.empty()) {
+    SG::ReadHandle<DecisionContainer> cachedRH = SG::makeHandle(m_cachedViewsKey, context);
+    ATH_CHECK(cachedRH.isValid());
+    cachedViews = cachedRH.ptr();
+  }
 
+  // Keep track of the ROIs we spwan a View for, do not spawn duplicates.
+  // For many cases, this will be covered by the Merging operation preceding this.
+  ElementLinkVector<TrigRoiDescriptorCollection> RoIsFromDecision;
 
+  if( outputHandle->size() == 0) {
+    ATH_MSG_WARNING( "Have no decisions in output handle "<< outputHandle.key() << ". Handle is valid but container is empty. "
+      << "Check why this EventViewCreatorAlgorithm was unlocked by a Filter, if the Filter then gave it no inputs.");
+  } else {
+    ATH_MSG_DEBUG( "Have output " << outputHandle.key() << " with " << outputHandle->size() << " elements" );
+  }
 
-StatusCode EventViewCreatorAlgorithm::executeMerged( const EventContext& context ) const {
+  // Find and link to the output Decision objects the ROIs to run over
+  ATH_CHECK( m_roiTool->attachROILinks(*outputHandle, context) );
 
-   // create the output decisions, similar to inputs (copy basic links)
-  std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > outputHandles;
-  ATH_CHECK (decisionInputToOutput(context, outputHandles));
+  for ( Decision* outputDecision : *outputHandle ) { 
 
-  // make the views
-  auto viewsHandle = SG::makeHandle( m_viewsKey, context ); 
-  auto viewVector1 = std::make_unique< ViewContainer >();
-  ATH_CHECK( viewsHandle.record(  std::move( viewVector1 ) ) );
-  auto viewVector = viewsHandle.ptr();
-  unsigned int viewCounter = 0;
+    if (!outputDecision->hasObjectLink(roiString(), ClassID_traits<TrigRoiDescriptorCollection>::ID())) {
+      ATH_MSG_ERROR("No '" << roiString() << "'link was attached by the ROITool. Decision object dump:" << *outputDecision);
+      return StatusCode::FAILURE;
+    }
+    const ElementLink<TrigRoiDescriptorCollection> roiEL = outputDecision->objectLink<TrigRoiDescriptorCollection>(roiString());
+    ATH_CHECK(roiEL.isValid());
+
+    // We do one of three things here, either... 
+    // a) We realise that an identically configured past EVCA has already run a View on an equivilant ROI. If so we can re-use this.
+    // b) We encounter a new ROI and hence need to spawn a new view.
+    // c) We encounter a ROI that we have already seen in looping over this outputHandle, we can re-use a view.
+      
+    // cachedIndex and useCached are to do with a)
+    size_t cachedIndex = std::numeric_limits<std::size_t>::max();
+    const bool useCached = checkCache(cachedViews, outputDecision, cachedIndex);
+
+    // roiIt is to do with b) and c)
+    auto roiIt = find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
+
+    if (useCached) {
+
+      // Re-use an aready processed view from a previously executed EVCA instance
+      const Decision* cached = cachedViews->at(cachedIndex);
+      ElementLink<ViewContainer> cachedViewEL = cached->objectLink<ViewContainer>(viewString());
+      ElementLink<TrigRoiDescriptorCollection> cachedROIEL = cached->objectLink<TrigRoiDescriptorCollection>(roiString());
+      ATH_CHECK(cachedViewEL.isValid());
+      ATH_CHECK(cachedROIEL.isValid());
+      ATH_MSG_DEBUG("Re-using cached existing view from " << cachedViewEL.dataID() << ", index:" << cachedViewEL.index() 
+        << " on ROI " << **cachedROIEL);
+      outputDecision->setObjectLink( viewString(), cachedViewEL );
+      outputDecision->setObjectLink( roiString(), cachedROIEL );
+      // Note: This overwrites the link created in the above tool with what should be a spatially identical ROI (check?)
+
+    } else if ( roiIt == RoIsFromDecision.end() ) {
+
+      // We have not yet spawned an ROI on this View. Do it now.
+      RoIsFromDecision.push_back(roiEL);
+      ATH_MSG_DEBUG("Found RoI:" << **roiEL << " FS=" << (*roiEL)->isFullscan() << ". Making View.");
+      SG::View* newView = ViewHelper::makeView( name()+"_view", viewVector->size() /*view counter*/, m_viewFallThrough );
+      viewVector->push_back( newView );
+      // Use a fall-through filter if one is provided
+      if ( m_viewFallFilter.size() ) {
+        newView->setFilter( m_viewFallFilter );
+      }
+      // Set parent view, if required. Note: Must be called before we link the new view to outputDecision.
+      ATH_CHECK(linkViewToParent(outputDecision, newView));
+      // Add the single ROI into the view to seed it.
+      ATH_CHECK(placeRoIInView(roiEL, viewVector->back(), context));
+      // Link the view to the Decision object
+      outputDecision->setObjectLink( viewString(), ElementLink<ViewContainer>(m_viewsKey.key(), viewVector->size()-1 ));
+      ATH_MSG_DEBUG( "Made new View, storing view in viewVector " << m_viewsKey.key() << " index:" << viewVector->size()-1 );
 
-  //map all RoIs that are stored
-  ElementLinkVector<TrigRoiDescriptorCollection> RoIsFromDecision;
+    } else {
 
-  // loop over decisions
-  for (auto outputHandle: outputHandles) {
-    if( not outputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key() << " because handle not valid");
-      continue;
-    }
+      // We have already spawned a ROI in this View. Link it here too.
+      const size_t existingIndex = std::distance(RoIsFromDecision.begin(), roiIt);
+      ATH_MSG_DEBUG("Found existing View, stored in view in viewVector " << m_viewsKey.key() << " index:" << existingIndex );
+      outputDecision->setObjectLink( viewString(), ElementLink<ViewContainer>(m_viewsKey.key(), existingIndex )); //adding View link to Decision
 
-    if( outputHandle->size() == 0){ // input filtered out
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty.");
-      continue;
     }
-    ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
-    // loop over output decisions in container of outputHandle, follow link to inputDecision
-    for ( auto outputDecision : *outputHandle){ 
-      const auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( outputDecision, m_roisLink.value() );
-      const auto roiEL = roiELInfo.link;
-      ATH_CHECK( roiEL.isValid() );
-      // check if already found
-      auto roiIt=find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
-      if ( roiIt == RoIsFromDecision.end() ){
-	RoIsFromDecision.push_back(roiEL); // just to keep track of which we have used 
-	ATH_MSG_DEBUG("Found RoI:" <<**roiEL<<" FS="<<(*roiEL)->isFullscan());
-	ATH_MSG_DEBUG("Positive decisions on RoI, making view" );
-	// make the view
-	auto newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough ); //pointer to the view
-
-        // Use a fall-through filter if one is provided
-        if ( m_viewFallFilter.size() ) {
-          newView->setFilter( m_viewFallFilter );
-        }
-
-	viewVector->push_back( newView );
-	
-	// link decision to this view
-	outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
-	ATH_MSG_DEBUG( "Adding new view to new decision; storing view in viewVector component " << viewVector->size()-1 );
-	ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
-	ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
-	ATH_MSG_DEBUG( "Got inputLinks with " << inputLinks.size() << " elements" );
-	for (auto input: inputLinks){
-	  const Decision* inputDecision = *input;
-	  ATH_CHECK( linkViewToParent( inputDecision, viewVector->back() ) );
-	}
-      }
-      else {          
-	ATH_MSG_DEBUG( "View  already linked, doing nothing");	
-      }
-    } // loop over decisions   
-  }// loop over output keys
+  } // loop over output decisions   
 
   // launch view execution
-  ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
-  ATH_CHECK( ViewHelper::scheduleViews( viewVector,           // Vector containing views
-					m_viewNodeName,       // CF node to attach views to
-					context,              // Source context
-					getScheduler(),
-					m_reverseViews ) );
+  ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " unique views" );
+  ATH_CHECK( ViewHelper::scheduleViews( viewVector, // Vector containing views
+    m_viewNodeName,                                 // CF node to attach views to
+    context,                                        // Source context
+    getScheduler(),                                 // Scheduler to launch with
+    m_reverseViews ) );                             // Debug option
   
-  if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandles);
+  if (msgLvl(MSG::DEBUG)) {
+    debugPrintOut(context, outputHandle);
+  }
   return StatusCode::SUCCESS;
 }
 
+bool EventViewCreatorAlgorithm::checkCache(const DecisionContainer* cachedViews, const Decision* outputDecision, size_t& cachedIndex) const {
+  if (cachedViews == nullptr) {
+    return false; // No cached input configured, which is fine.
+  }
+  return matchInCollection(cachedViews, outputDecision, cachedIndex);
+}
 
 
-StatusCode EventViewCreatorAlgorithm::linkViewToParent( const TrigCompositeUtils::Decision* inputDecision, SG::View* newView ) const {
-  if ( m_requireParentView ) {
-    // see if there is a view linked to the decision object, if so link it to the view that is just made
-    LinkInfo<ViewContainer> parentViewLinkInfo = findLink<ViewContainer>(inputDecision, viewString(), /*suppressMultipleLinksWarning*/ true );
-    if ( parentViewLinkInfo.isValid() ) {
-      ATH_CHECK( parentViewLinkInfo.link.isValid() );
-      auto parentView = *parentViewLinkInfo.link;
-      newView->linkParent( parentView );
-      ATH_MSG_DEBUG( "Parent view linked" );
-    } else {
-      ATH_MSG_ERROR( "Parent view not linked because it could not be found" );
-      ATH_MSG_ERROR( TrigCompositeUtils::dump( inputDecision, [](const xAOD::TrigComposite* tc){
-        return "TC " + tc->name() + ( tc->hasObjectLink("view") ? " has view " : " has no view " );
-      } ) );
-      return StatusCode::FAILURE;
-    }
-  } else {
-    ATH_MSG_DEBUG( "Parent view linking not required" );
+StatusCode EventViewCreatorAlgorithm::linkViewToParent( const TrigCompositeUtils::Decision* outputDecision, SG::View* newView ) const {
+  if (!m_requireParentView) {
+    ATH_MSG_DEBUG("Parent view linking not required");
+    return StatusCode::SUCCESS;
+  }
+  // We must call this BEFORE having added the new link, check
+  if (outputDecision->hasObjectLink(viewString())) {
+    ATH_MSG_ERROR("Called linkViewToParent on a Decision object which already has been given a '" 
+      << viewString << "' link. Call this fn BEFORE linking the new View.");
+    return StatusCode::FAILURE;
+  }
+  std::vector<LinkInfo<ViewContainer>> parentViews = findLinks<ViewContainer>(outputDecision, viewString(), TrigDefs::lastFeatureOfType);
+  if (parentViews.size() == 0) {
+    ATH_MSG_ERROR("Could not find the parent View, but 'RequireParentView' is true.");
+    return StatusCode::FAILURE;
+  }
+  ATH_MSG_DEBUG( "Will link " << parentViews.size() << " parent view(s)" );
+  for (const LinkInfo<ViewContainer>& parentViewLI : parentViews) {
+    ATH_CHECK(parentViewLI.isValid());
+    newView->linkParent( *(parentViewLI.link) );
+    ATH_MSG_DEBUG( "Parent view linked (" << parentViewLI.link.dataID() << ", index:" << parentViewLI.link.index() << ")" );
   }
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h
index ef230e5c700..d0d42d3b816 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h
@@ -21,11 +21,15 @@
 #include "GaudiKernel/IScheduler.h"
 #include "AthViews/View.h"
 
- /**
-   * @class EventViewCreatorAlgorithm
-   * @brief Used at the start of a sequence to create the EventViews: retrieves filtered collection via menu decision from previous step and writes it out directly so it can be used as input by the reco alg that follows in sequence.
-   **/
+#include "ViewAlgs/IViewCreatorROITool.h"
 
+/**
+  * @class EventViewCreatorAlgorithm
+  * @brief Used at the start of a sequence to create the EventViews: retrieves filtered collections via menu decision from previous 
+  * step, merges them and writes out a merged collection to be consumed by HypoAlg(s).
+  * Spawns EventViews for each unique ROI associated to each Decision object in the merged output.
+  * Links the EventView and the ROI to each Decision object in the merged output.
+  **/
 
 
 class EventViewCreatorAlgorithm : public ::InputMakerBase
@@ -39,35 +43,60 @@ class EventViewCreatorAlgorithm : public ::InputMakerBase
  protected:
 
     EventViewCreatorAlgorithm();
-    
-    // Used instead of execute, when mergeOutputs is true
-    // Note: if we enforce the merging beahviour this will become the default execute()
-    StatusCode executeMerged(const EventContext&) const;
 
-    //Output views for merging
-    SG::WriteHandleKey< ViewContainer > m_viewsKey{ this, "Views", "Unspecified", "The key of views collection produced" };
+    SG::WriteHandleKey< ViewContainer > m_viewsKey{ this, "Views", "Unspecified",
+      "The key of views collection produced" };
 
-    // same handles as inputMakerForRoI
-    SG::WriteHandleKey< ConstDataVector<TrigRoiDescriptorCollection> > m_inViewRoIs{ this, "InViewRoIs", "Unspecified", "Name with which the RoIs shoudl be inserted into the views" };
+    SG::WriteHandleKey< ConstDataVector<TrigRoiDescriptorCollection> > m_inViewRoIs{ this, "InViewRoIs", "Unspecified",
+      "Name of the collection which should be inserted into the just-spawned views to seed them with their ROI" };
 
     // needs for views
     Gaudi::Property< std::string > m_schedulerName { this, "SchedulerName", "AvalancheSchedulerSvc", "Name of the scheduler" };
-    Gaudi::Property< std::string > m_viewNodeName{ this, "ViewNodeName", "", "Name of the CF node to attach a view to" };
+    Gaudi::Property< std::string > m_viewNodeName{ this, "ViewNodeName", "", "Name of the ControlFlow node to attach new views to" };
 
-    Gaudi::Property< bool > m_viewFallThrough { this, "ViewFallThrough", false, "Set whether views may accesas StoreGate directly to retrieve data" };
-    Gaudi::Property< bool > m_requireParentView { this, "RequireParentView", false, "Fail if the parent view can not be found" };
-    Gaudi::Property< bool > m_reverseViews { this, "ReverseViewsDebug", false, "Reverse order of views, as a debugging option" };
-    Gaudi::Property< std::vector< std::string > > m_viewFallFilter { this, "FallThroughFilter", {}, "A list of SG keys (or parts of them) that can come from StoreGate" };
+    Gaudi::Property< bool > m_viewFallThrough { this, "ViewFallThrough", false,
+      "Set whether views may access StoreGate directly to retrieve data" };
+    Gaudi::Property< std::vector< std::string > > m_viewFallFilter { this, "FallThroughFilter", {}, 
+      "An optional list of SG keys (or parts of them) that can come from StoreGate via FallThrough" };
 
+    Gaudi::Property< bool > m_requireParentView { this, "RequireParentView", false,
+      "For each new view, locate and link a parent view (previous step). Fail if the parent view can not be found." };
 
-    // methods
-  /**
-   * @brief makes sure the views are linked, if configuration requireParentView is set, failure to set the parent is an error
-   **/
-    StatusCode linkViewToParent( const TrigCompositeUtils::Decision* inputDecsion, SG::View* newView ) const;
+    Gaudi::Property< bool > m_reverseViews { this, "ReverseViewsDebug", false, 
+      "Reverse order of views, as a debugging option" };
+
+    SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer> m_cachedViewsKey { this, "InputCachedViews", "",
+      "Optional ReadHandle on the output (InputMakerOutputDecisions) of an EVCA in a previous Step, whose Views can be re-used" };
+
+    ToolHandle<IViewCreatorROITool> m_roiTool{this, "RoITool", "",
+      "Tool used to supply per-Decision Object the RoI on which the Decision Object's view is to be spawned"};
+
+    /**
+     * @brief Makes sure the views are linked, if configuration requireParentView is set. Failure to set the parent is an error
+     **/
+    StatusCode linkViewToParent( const TrigCompositeUtils::Decision* outputDecision, SG::View* newView ) const;
+
+    /**
+     * @brief Seeds a newly created view with an ROI collection containing the single seeding ROI
+     **/
     StatusCode placeRoIInView( const ElementLink<TrigRoiDescriptorCollection>& roi, SG::View* view, const EventContext& context ) const;
-    inline SmartIF<IScheduler> getScheduler() const {return svcLoc()->service<IScheduler>(m_schedulerName,false);}
+
+    /**
+     * @brief Obtain smart pointer to scheduler in order to schedule newly spawned views
+     **/
+    SmartIF<IScheduler> getScheduler() const;
+
+    /**
+     * @brief Allow for the re-use of EventViews run in a previous Step in another EVCA instance configured
+     * to spawn EventViews using the same reconstruction sequence (i.e. both algs should share a common ViewNodeName).
+     **/
+    bool checkCache(const TrigCompositeUtils::DecisionContainer* cachedViews, 
+      const TrigCompositeUtils::Decision* outputDecision, 
+      size_t& cachedIndex) const;
+
 };
 
+#include "EventViewCreatorAlgorithm.icc"
+
 #endif
 
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.icc b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.icc
new file mode 100644
index 00000000000..b8b44539b41
--- /dev/null
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.icc
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+inline SmartIF<IScheduler> EventViewCreatorAlgorithm::getScheduler() const {
+  return svcLoc()->service<IScheduler>(m_schedulerName, false);
+}
+
+// NOTE: This is TODO
+
+// template<class OBJECT>
+// StatusCode EventViewCreatorAlgorithm::placeFeatureInView( const OBJECT* theObject, SG::View* view, const EventContext& context ) const {
+//   ATH_MSG_ALWAYS( "Adding Feature of type " << ClassID_traits<OBJECT>::typeName() << " To View : " << m_inViewFeatureKey.key() );
+//   auto oneObjectCollection = std::make_unique< ConstDataVector< OBJECT > >();
+//   oneObjectCollection->clear( SG::VIEW_ELEMENTS );
+//   oneObjectCollection->push_back( theObject );
+
+//   //store in the view
+//   auto handle = SG::makeHandle( m_inViewFeatureKey,context );
+//   ATH_CHECK( handle.setProxyDict( view ) );
+//   ATH_CHECK( handle.record( std::move( oneObjectCollection ) ) );
+//   return StatusCode::SUCCESS;
+// }
+
+
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
index 3661fd9d0ee..571777458ce 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
@@ -29,9 +29,9 @@ StatusCode EventViewCreatorAlgorithmWithJets::initialize() {
 }
 
 StatusCode EventViewCreatorAlgorithmWithJets::execute( const EventContext& context ) const {
-  // create the output decisions, similar to inputs (copy basic links)
-  std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > outputHandles;
-  ATH_CHECK (decisionInputToOutput(context, outputHandles));
+  // create the output decisions from the input collections
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore( decisionOutputs(), context );
+  ATH_CHECK (decisionInputToOutput(context, outputHandle));
 
   // make the views
   auto viewsHandle = SG::makeHandle( m_viewsKey, context );
@@ -43,70 +43,69 @@ StatusCode EventViewCreatorAlgorithmWithJets::execute( const EventContext& conte
   //map all RoIs that are stored
   std::vector <ElementLink<TrigRoiDescriptorCollection> > RoIsFromDecision;
 
-  for (auto outputHandle: outputHandles) {
-    if( not outputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key() << " because handle not valid");
-      continue;
-    }
-    if( outputHandle->size() == 0){ // input filtered out
-      ATH_MSG_ERROR( "Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty. Is this expected?");
-      return StatusCode::FAILURE;
-    }
-
-    ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
-    // loop over output decisions in container of outputHandle, follow link to inputDecision
-    for ( auto outputDecision : *outputHandle){ 
-      ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
-      // loop over input links as predecessors
-      for (auto input: inputLinks){
-        const Decision* inputDecision = *input;
-
-        // Retrieve jets ...
-        ATH_MSG_DEBUG( "Checking there are jets linked to decision object" );
-        TrigCompositeUtils::LinkInfo< xAOD::JetContainer > jetELInfo = TrigCompositeUtils::findLink< xAOD::JetContainer >( inputDecision,TrigCompositeUtils::featureString() );
-        ATH_CHECK( jetELInfo.isValid() );
-        const xAOD::Jet *jet = *jetELInfo.link;
-        ATH_MSG_DEBUG( "Placing xAOD::JetContainer " );
-        ATH_MSG_DEBUG( "   -- pt="<< jet->p4().Et() <<" eta="<< jet->eta() << " phi="<< jet->phi() );
+  if( not outputHandle.isValid() ) {
+    ATH_MSG_ERROR( "Got no decisions from output "<< outputHandle.key() << " because handle not valid");
+    return StatusCode::FAILURE;
+  }
+  if( outputHandle->size() == 0){ // input filtered out
+    ATH_MSG_ERROR( "Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty. Is this expected?");
+    return StatusCode::FAILURE;
+  }
+
+  ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
+  // loop over output decisions in container of outputHandle, follow link to inputDecision
+  for ( auto outputDecision : *outputHandle){ 
+    ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
+    // loop over input links as predecessors
+    for (auto input: inputLinks){
+      const Decision* inputDecision = *input;
+
+      // Retrieve jets ...
+      ATH_MSG_DEBUG( "Checking there are jets linked to decision object" );
+      TrigCompositeUtils::LinkInfo< xAOD::JetContainer > jetELInfo = TrigCompositeUtils::findLink< xAOD::JetContainer >( inputDecision,TrigCompositeUtils::featureString() );
+      ATH_CHECK( jetELInfo.isValid() );
+      const xAOD::Jet *jet = *jetELInfo.link;
+      ATH_MSG_DEBUG( "Placing xAOD::JetContainer " );
+      ATH_MSG_DEBUG( "   -- pt="<< jet->p4().Et() <<" eta="<< jet->eta() << " phi="<< jet->phi() );
+      
+      // find the RoI
+      auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( inputDecision, m_roisLink.value() );
+      auto roiEL = roiELInfo.link;
+      ATH_CHECK( roiEL.isValid() );
+      // check if already found
+      auto roiIt=find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
+      if ( roiIt == RoIsFromDecision.end() ){
+        RoIsFromDecision.push_back(roiEL); // just to keep track of which we have used
+        const TrigRoiDescriptor* roi = *roiEL;
+        ATH_MSG_DEBUG("Found RoI:" <<*roi<<" FS="<<roi->isFullscan());
+        ATH_MSG_DEBUG( "Positive decisions on RoI, preparing view" );
         
-        // find the RoI
-        auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( inputDecision, m_roisLink.value() );
-        auto roiEL = roiELInfo.link;
-        ATH_CHECK( roiEL.isValid() );
-        // check if already found
-        auto roiIt=find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
-        if ( roiIt == RoIsFromDecision.end() ){
-          RoIsFromDecision.push_back(roiEL); // just to keep track of which we have used
-          const TrigRoiDescriptor* roi = *roiEL;
-          ATH_MSG_DEBUG("Found RoI:" <<*roi<<" FS="<<roi->isFullscan());
-          ATH_MSG_DEBUG( "Positive decisions on RoI, preparing view" );
-          
-          // make the view
-          ATH_MSG_DEBUG( "Making the View" );
-          auto newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough ); //pointer to the view
-
-          // Use a fall-through filter if one is provided
-          if ( m_viewFallFilter.size() ) {
-            newView->setFilter( m_viewFallFilter );
-          }
-
-          viewVector->push_back( newView );
-          
-          // link decision to this view
-          outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
-          ATH_MSG_DEBUG( "Adding new view to new decision; storing view in viewVector component " << viewVector->size()-1 );
-          ATH_CHECK( linkViewToParent( inputDecision, viewVector->back() ) );
-          ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
-          ATH_CHECK( placeJetInView( jet, viewVector->back(), context ) );
-        }
-        else {
-          int iview = roiIt-RoIsFromDecision.begin();
-          outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), iview ) ); //adding view to TC
-          ATH_MSG_DEBUG( "Adding already mapped view " << iview << " in ViewVector , to new decision");
+        // make the view
+        ATH_MSG_DEBUG( "Making the View" );
+        auto newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough ); //pointer to the view
+
+        // Use a fall-through filter if one is provided
+        if ( m_viewFallFilter.size() ) {
+          newView->setFilter( m_viewFallFilter );
         }
-      }// loop over previous inputs
-    } // loop over decisions
-  }// loop over output keys
+
+        viewVector->push_back( newView );
+        ATH_CHECK( linkViewToParent( inputDecision, viewVector->back() ) );
+
+        // link decision to this view
+
+        outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
+        ATH_MSG_DEBUG( "Adding new view to new decision; storing view in viewVector component " << viewVector->size()-1 );
+        ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
+        ATH_CHECK( placeJetInView( jet, viewVector->back(), context ) );
+      }
+      else {
+        int iview = roiIt-RoIsFromDecision.begin();
+        outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), iview ) ); //adding view to TC
+        ATH_MSG_DEBUG( "Adding already mapped view " << iview << " in ViewVector , to new decision");
+      }
+    }// loop over previous inputs
+  } // loop over decisions
 
   ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
   ATH_CHECK( ViewHelper::scheduleViews( viewVector,           // Vector containing views
@@ -119,7 +118,7 @@ StatusCode EventViewCreatorAlgorithmWithJets::execute( const EventContext& conte
   // auto viewsHandle = SG::makeHandle( m_viewsKey );
   // ATH_CHECK( viewsHandle.record(  std::move( viewVector ) ) );
   ATH_MSG_DEBUG( "Store "<< viewsHandle->size() <<" Views");
-  if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandles);
+  if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandle);
 
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithMuons.cxx b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithMuons.cxx
index dc3ba9a9bef..fe10424f982 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithMuons.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithMuons.cxx
@@ -35,9 +35,9 @@ StatusCode EventViewCreatorAlgorithmWithMuons::initialize() {
 }
 
 StatusCode EventViewCreatorAlgorithmWithMuons::execute( const EventContext& context ) const {
-  // create the output decisions, similar to inputs (copy basic links)
-  std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > outputHandles;
-  ATH_CHECK (decisionInputToOutput(context, outputHandles));
+  // create the output decisions from the input collections
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore( decisionOutputs(), context );
+  ATH_CHECK (decisionInputToOutput(context, outputHandle));
 
   // make the views
   auto viewsHandle = SG::makeHandle( m_viewsKey, context ); 
@@ -58,112 +58,115 @@ StatusCode EventViewCreatorAlgorithmWithMuons::execute( const EventContext& cont
   std::vector <ElementLink<TrigRoiDescriptorCollection> > RoIsFromDecision;
 
   // Store new ROI Descriptors
-  SG::WriteHandle<TrigRoiDescriptorCollection> roisWriteHandle = TrigCompositeUtils::createAndStoreNoAux(m_roisWriteHandleKey, context);
+  SG::WriteHandle<TrigRoiDescriptorCollection> roisWriteHandle = createAndStoreNoAux(m_roisWriteHandleKey, context);
 
-  for (auto outputHandle: outputHandles) {
-    if( not outputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from output "<< outputHandle.key() << " because handle not valid");
-      continue;
-    }
-    if( outputHandle->size() == 0){ // input filtered out
-      ATH_MSG_ERROR( "Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty. Is this expected?");
-      return StatusCode::FAILURE;
-    }
 
-    ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
+  if( not outputHandle.isValid() ) {
+    ATH_MSG_ERROR( "Got no decisions from output "<< outputHandle.key() << " because handle not valid");
+    return StatusCode::FAILURE;
+  }
 
-    if(m_doFSRoI){
-      //create one RoI over full detector
-      auto roi = new TrigRoiDescriptor(true);
-      roisWriteHandle->push_back( roi );
-      const auto roiEL = ElementLink<TrigRoiDescriptorCollection>(*roisWriteHandle, roisWriteHandle->size() - 1, context);
-
-      // make the view
-      ATH_MSG_DEBUG( "Making the View "<<name()<<"_view" );
-      auto newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough );
-
-      // Use a fall-through filter if one is provided
-      if ( m_viewFallFilter.size() ) {
-        newView->setFilter( m_viewFallFilter );
-      }
-
-      viewVector->push_back( newView );
-      ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
+  if( outputHandle->size() == 0){ // input filtered out
+    ATH_MSG_ERROR( "Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty. Is this expected?");
+    return StatusCode::FAILURE;
+  }
+
+  ATH_MSG_DEBUG( "Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
+
+  if(m_doFSRoI){
+    //create one RoI over full detector
+    auto roi = new TrigRoiDescriptor(true);
+    roisWriteHandle->push_back( roi );
+    const auto roiEL = ElementLink<TrigRoiDescriptorCollection>(*roisWriteHandle, roisWriteHandle->size() - 1, context);
+
+    // make the view
+    ATH_MSG_DEBUG( "Making the View "<<name()<<"_view" );
+    auto newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough );
+
+    // Use a fall-through filter if one is provided
+    if ( m_viewFallFilter.size() ) {
+      newView->setFilter( m_viewFallFilter );
     }
 
-    // loop over output decisions in container of outputHandle, follow link to inputDecision
-    for ( auto outputDecision : *outputHandle){ 
-      ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
-
-      if(m_doFSRoI){
-	// link decision to this view
-	outputDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
-      }
-      else{
-
-	//create one RoI per muon
-
-	// loop over input links as predecessors
-	for (auto input: inputLinks){
-	  const Decision* inputDecision = *input;
-
-	  if(m_doLateMu){
-	    // Retrieve late muon rois ...
-	    ATH_MSG_DEBUG( "Checking there are out-of-time rois linked to decision object" );
-	    TrigCompositeUtils::LinkInfo< TrigRoiDescriptorCollection > lateRoIELInfo = TrigCompositeUtils::findLink< TrigRoiDescriptorCollection >( inputDecision,m_lateRoIsLink );
-	    ATH_CHECK( lateRoIELInfo.isValid() );
-	    const TrigRoiDescriptor *lateRoI = *lateRoIELInfo.link;
-	    // parameters for RoI to record
-	    reta = lateRoI->eta();
-	    retap = lateRoI->etaPlus();
-	    retam = lateRoI->etaMinus();
-	    rphi = lateRoI->phi();
-	    rphip = lateRoI->phiPlus();
-	    rphim = lateRoI->phiMinus();
-	  }
-	  else{
-	    // Retrieve muons ...
-	    ATH_MSG_DEBUG( "Checking there are muons linked to decision object" );
-	    TrigCompositeUtils::LinkInfo< xAOD::MuonContainer > muonELInfo = TrigCompositeUtils::findLink< xAOD::MuonContainer >( inputDecision,m_muonsLink );
-	    ATH_CHECK( muonELInfo.isValid() );
-	    muon = *muonELInfo.link;
-	    ATH_MSG_DEBUG( "Placing xAOD::MuonContainer " );
-	    ATH_MSG_DEBUG( "   -- pt="<< muon->p4().Et() <<" eta="<< muon->eta() << " muon="<< muon->phi() );
-
-	    // parameters for RoI around muon
-	    reta = muon->eta();
-	    retap = muon->eta()+m_roiEtaWidth;
-	    retam = muon->eta()-m_roiEtaWidth;
-	    rphi = muon->phi();
-	    rphip = muon->phi()+m_roiPhiWidth;
-	    rphim = muon->phi()-m_roiPhiWidth;
-	  }
-	  auto roi = new TrigRoiDescriptor(reta, retam, retap, rphi, rphim, rphip);
-	  roisWriteHandle->push_back( roi );
-	  const auto roiEL = ElementLink<TrigRoiDescriptorCollection>(*roisWriteHandle, roisWriteHandle->size() - 1, context);
-	  ATH_CHECK( roiEL.isValid() );
-	  ATH_MSG_DEBUG("Created roi around muon: "<<*roi);
-	  // make the view
-	  ATH_MSG_DEBUG( "Making the View "<<name()<<"_view" );
-	  auto newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough ); //pointer to the view
-
-          // Use a fall-through filter if one is provided
-          if ( m_viewFallFilter.size() ) {
-            newView->setFilter( m_viewFallFilter );
-          }
-
-	  viewVector->push_back( newView );
-
-	  // link decision to this view
-	  outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
-	  ATH_MSG_DEBUG( "Adding new view to new decision; storing view in viewVector component " << viewVector->size()-1 );
-	  ATH_CHECK( linkViewToParent( inputDecision, viewVector->back() ) );
-	  ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
-	  if(!m_doLateMu) ATH_CHECK( placeMuonInView( muon, viewVector->back(), context ) );
-	}// loop over previous inputs
-      }//Not FS view
-    } // loop over decisions   
-  }// loop over output keys
+    viewVector->push_back( newView );
+    ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
+  }
+
+  // loop over output decisions in container of outputHandle, follow link to inputDecision
+  for ( auto outputDecision : *outputHandle){ 
+    ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
+
+    if(m_doFSRoI){
+      // link decision to this view
+      outputDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
+    } else{
+
+      //create one RoI per muon
+
+      // loop over input links as predecessors
+      for (auto input: inputLinks){
+        const Decision* inputDecision = *input;
+
+        if(m_doLateMu){
+
+          // Retrieve late muon rois ...
+          ATH_MSG_DEBUG( "Checking there are out-of-time rois linked to decision object" );
+          TrigCompositeUtils::LinkInfo< TrigRoiDescriptorCollection > lateRoIELInfo = TrigCompositeUtils::findLink< TrigRoiDescriptorCollection >( inputDecision,m_lateRoIsLink );
+          ATH_CHECK( lateRoIELInfo.isValid() );
+          const TrigRoiDescriptor *lateRoI = *lateRoIELInfo.link;
+          // parameters for RoI to record
+          reta = lateRoI->eta();
+          retap = lateRoI->etaPlus();
+          retam = lateRoI->etaMinus();
+          rphi = lateRoI->phi();
+          rphip = lateRoI->phiPlus();
+          rphim = lateRoI->phiMinus();
+
+        } else{
+
+          // Retrieve muons ...
+          ATH_MSG_DEBUG( "Checking there are muons linked to decision object" );
+          TrigCompositeUtils::LinkInfo< xAOD::MuonContainer > muonELInfo = TrigCompositeUtils::findLink< xAOD::MuonContainer >( inputDecision,m_muonsLink );
+          ATH_CHECK( muonELInfo.isValid() );
+          muon = *muonELInfo.link;
+          ATH_MSG_DEBUG( "Placing xAOD::MuonContainer " );
+          ATH_MSG_DEBUG( "   -- pt="<< muon->p4().Et() <<" eta="<< muon->eta() << " muon="<< muon->phi() );
+
+          // parameters for RoI around muon
+          reta = muon->eta();
+          retap = muon->eta()+m_roiEtaWidth;
+          retam = muon->eta()-m_roiEtaWidth;
+          rphi = muon->phi();
+          rphip = muon->phi()+m_roiPhiWidth;
+          rphim = muon->phi()-m_roiPhiWidth;
+        
+        } 
+
+        auto roi = new TrigRoiDescriptor(reta, retam, retap, rphi, rphim, rphip);
+        roisWriteHandle->push_back( roi );
+        const auto roiEL = ElementLink<TrigRoiDescriptorCollection>(*roisWriteHandle, roisWriteHandle->size() - 1, context);
+        ATH_CHECK( roiEL.isValid() );
+        ATH_MSG_DEBUG("Created roi around muon: "<<*roi);
+        // make the view
+        ATH_MSG_DEBUG( "Making the View "<<name()<<"_view" );
+        SG::View* newView = ViewHelper::makeView( name()+"_view", viewCounter++, m_viewFallThrough ); //pointer to the view
+        viewVector->push_back( newView );
+        // Use a fall-through filter if one is provided
+        if ( m_viewFallFilter.size() ) {
+          newView->setFilter( m_viewFallFilter );
+        }
+        ATH_CHECK( linkViewToParent( inputDecision, newView ) );
+        // link decision to this view
+        outputDecision->setObjectLink( TrigCompositeUtils::viewString(), ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
+        
+        ATH_MSG_DEBUG( "Adding new view to new decision; storing view in viewVector component " << viewVector->size()-1 );
+        ATH_CHECK( placeRoIInView( roiEL, viewVector->back(), context ) );
+        if(!m_doLateMu) {
+          ATH_CHECK( placeMuonInView( muon, viewVector->back(), context ) );
+        }
+      }// loop over previous inputs
+    }//Not FS view
+  } // loop over decisions   
 
   ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
   ATH_CHECK( ViewHelper::scheduleViews( viewVector,           // Vector containing views
@@ -172,7 +175,7 @@ StatusCode EventViewCreatorAlgorithmWithMuons::execute( const EventContext& cont
                                         getScheduler(),
                                         m_reverseViews ) );
 
-  if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandles);
+  if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandle);
   return StatusCode::SUCCESS;
 }
 
diff --git a/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.cxx b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.cxx
new file mode 100644
index 00000000000..b92b2cf1d11
--- /dev/null
+++ b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.cxx
@@ -0,0 +1,31 @@
+
+/*
+Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigSteeringEvent/TrigRoiDescriptorCollection.h"
+#include "ViewCreatorInitialROITool.h"
+
+using namespace TrigCompositeUtils;
+
+ViewCreatorInitialROITool::ViewCreatorInitialROITool(const std::string& type, const std::string& name, const IInterface* parent)
+  : base_class(type, name, parent) 
+  {}
+
+StatusCode ViewCreatorInitialROITool::attachROILinks(TrigCompositeUtils::DecisionContainer& decisions, const EventContext&) const {
+  // Locate "initialRoI" for each Decision object, re-attach the ElementLink as "roi" to the current Decision object.
+  for ( Decision* outputDecision : decisions ) { 
+    const std::vector<LinkInfo<TrigRoiDescriptorCollection>> myROI = findLinks<TrigRoiDescriptorCollection>(outputDecision, initialRoIString(), TrigDefs::lastFeatureOfType);
+
+    if (myROI.size() != 1) {
+      ATH_MSG_ERROR("Did not find exactly one '" << initialRoIString() << "' for Decision object index " << outputDecision->index()
+        << ", found " << myROI.size() << ". Unable to supply single ROI to spawn EventView on.");
+      for (const auto& li : myROI) {
+        ATH_MSG_ERROR("  -- " << li.link.dataID() << ":" << li.link.index() << ". Dump:" << *(li.source)); 
+      }
+    }
+
+    outputDecision->setObjectLink(roiString(), myROI.at(0).link);
+  }
+	return StatusCode::SUCCESS;
+}
diff --git a/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.h b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.h
new file mode 100644
index 00000000000..bb297e595e3
--- /dev/null
+++ b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorInitialROITool.h
@@ -0,0 +1,35 @@
+/*
+Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef VIEWALGS_VIEWCREATORINITIALROITOOL_H
+#define VIEWALGS_VIEWCREATORINITIALROITOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "ViewAlgs/IViewCreatorROITool.h"
+
+/**
+ * @class ViewCreatorInitialROITool
+ * Basic ROI provider tool which retrieves and re-attaches an existing "initialRoI" ElementLink.
+ * This implies running the EventView spawned for the Decision object on the ROIDescriptor originating from L1.
+ *
+ * Every Decision object in decisions must have a single "initialRoI" element link added at the root of 
+ * the navigation graph for the Decision object.
+ *
+ * This basic tool should be replaced with more advanced slice-specific ones where appropriate.
+ **/
+class ViewCreatorInitialROITool: public extends<AthAlgTool, IViewCreatorROITool>
+{
+public:
+  ViewCreatorInitialROITool(const std::string& type, const std::string& name, const IInterface* parent);
+
+  virtual ~ViewCreatorInitialROITool() = default;
+
+/**
+ * @brief Tool interface method. Context not used in this tool implementation.
+ **/
+  virtual StatusCode attachROILinks(TrigCompositeUtils::DecisionContainer& decisions, const EventContext& ctx) const override;
+
+};
+
+#endif //> !VIEWALGS_VIEWCREATORINITIALROITOOL_H
diff --git a/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.cxx b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.cxx
new file mode 100644
index 00000000000..f7724e8438e
--- /dev/null
+++ b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.cxx
@@ -0,0 +1,33 @@
+
+/*
+Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigSteeringEvent/TrigRoiDescriptorCollection.h"
+#include "ViewCreatorPreviousROITool.h"
+
+using namespace TrigCompositeUtils;
+
+ViewCreatorPreviousROITool::ViewCreatorPreviousROITool(const std::string& type, const std::string& name, const IInterface* parent)
+  : base_class(type, name, parent) 
+  {}
+
+StatusCode ViewCreatorPreviousROITool::attachROILinks(TrigCompositeUtils::DecisionContainer& decisions, const EventContext&) const {
+  // Locate "roi" for each Decision object from previous step, re-attach the ElementLink as "roi" to the current Decision object.
+  // I.e. don't update the "roi", just re-use the one from the previous Step.
+  for ( Decision* outputDecision : decisions ) { 
+    const std::vector<LinkInfo<TrigRoiDescriptorCollection>> myROI = findLinks<TrigRoiDescriptorCollection>(outputDecision, roiString(), TrigDefs::lastFeatureOfType);
+
+    if (myROI.size() != 1) {
+      ATH_MSG_ERROR("Did not find exactly one '" << roiString() << "' for Decision object index " << outputDecision->index()
+        << ", found " << myROI.size() << ". Unable to supply single ROI to spawn EventView on.");
+      for (const auto& li : myROI) {
+        ATH_MSG_ERROR("  -- " << li.link.dataID() << ":" << li.link.index() << ". Dump:" << *(li.source)); 
+      }
+      return StatusCode::FAILURE;
+    }
+
+    outputDecision->setObjectLink(roiString(), myROI.at(0).link);
+  }
+	return StatusCode::SUCCESS;
+}
diff --git a/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.h b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.h
new file mode 100644
index 00000000000..3f8d022df75
--- /dev/null
+++ b/Trigger/TrigSteer/ViewAlgs/src/ViewCreatorPreviousROITool.h
@@ -0,0 +1,32 @@
+/*
+Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef VIEWALGS_VIEWCREATORPREVIOUSROITOOL_H
+#define VIEWALGS_VIEWCREATORPREVIOUSROITOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "ViewAlgs/IViewCreatorROITool.h"
+
+/**
+ * @class ViewCreatorPreviousROITool
+ * Basic ROI provider tool which retrieves and re-attaches an existing "roi" ElementLink.
+ * This implies running the EventView spawned for the Decision object on the ROIDescriptor originating from the previous step.
+ *
+ * This basic tool should be replaced with more advanced slice-specific ones where appropriate.
+ **/
+class ViewCreatorPreviousROITool: public extends<AthAlgTool, IViewCreatorROITool>
+{
+public:
+  ViewCreatorPreviousROITool(const std::string& type, const std::string& name, const IInterface* parent);
+
+  virtual ~ViewCreatorPreviousROITool() = default;
+
+/**
+ * @brief Tool interface method. Context not used in this tool implementation.
+ **/
+  virtual StatusCode attachROILinks(TrigCompositeUtils::DecisionContainer& decisions, const EventContext& ctx) const override;
+
+};
+
+#endif //> !VIEWALGS_VIEWCREATORPREVIOUSROITOOL_H
diff --git a/Trigger/TrigSteer/ViewAlgs/src/components/ViewAlgs_entries.cxx b/Trigger/TrigSteer/ViewAlgs/src/components/ViewAlgs_entries.cxx
index b2d16b8ea8b..f6731ff406b 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/components/ViewAlgs_entries.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/components/ViewAlgs_entries.cxx
@@ -4,11 +4,12 @@
 #include "../EventViewCreatorAlgorithmWithJets.h"
 #include "../EventViewCreatorAlgorithmWithMuons.h"
 #include "../MergeViews.h"
-
-
+#include "../ViewCreatorInitialROITool.h"
+#include "../ViewCreatorPreviousROITool.h"
 
 DECLARE_COMPONENT( EventViewCreatorAlgorithm )
 DECLARE_COMPONENT( EventViewCreatorAlgorithmWithJets )
 DECLARE_COMPONENT( EventViewCreatorAlgorithmWithMuons )
 DECLARE_COMPONENT( MergeViews )
-
+DECLARE_COMPONENT( ViewCreatorInitialROITool )
+DECLARE_COMPONENT( ViewCreatorPreviousROITool )
diff --git a/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref b/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref
index c64272ee5bc..78ad2ae88dc 100644
--- a/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref
+++ b/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref
@@ -19,27 +19,12 @@ TrigSignatureMoniMT                                INFO -- #3965466087 Features
 TrigSignatureMoniMT                                INFO HLT_2j330_a10t_lcw_jes_35smcINF_L1J100 #1295975955
 TrigSignatureMoniMT                                INFO -- #1295975955 Events         3          3          0          -          -          -          -          0
 TrigSignatureMoniMT                                INFO -- #1295975955 Features                             0          -          -          -          -
-TrigSignatureMoniMT                                INFO HLT_2mu10_bJpsimumu_L12MU10 #3498558358
-TrigSignatureMoniMT                                INFO -- #3498558358 Events         3          3          3          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #3498558358 Features                             12         0          0          0          0
-TrigSignatureMoniMT                                INFO HLT_2mu10_bUpsimumu_L12MU10 #234102568
-TrigSignatureMoniMT                                INFO -- #234102568 Events          3          3          3          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #234102568 Features                              12         0          0          0          0
 TrigSignatureMoniMT                                INFO HLT_2mu14_L12MU10 #2619091790
 TrigSignatureMoniMT                                INFO -- #2619091790 Events         3          3          3          1          1          1          -          1
 TrigSignatureMoniMT                                INFO -- #2619091790 Features                             12         4          4          4          -
 TrigSignatureMoniMT                                INFO HLT_2mu15_L12MU10 #557204938
 TrigSignatureMoniMT                                INFO -- #557204938 Events          3          3          3          1          1          1          -          1
 TrigSignatureMoniMT                                INFO -- #557204938 Features                              12         4          4          4          -
-TrigSignatureMoniMT                                INFO HLT_2mu4_bDimu_L12MU4 #1730084172
-TrigSignatureMoniMT                                INFO -- #1730084172 Events         4          4          4          1          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #1730084172 Features                             16         9          0          0          0
-TrigSignatureMoniMT                                INFO HLT_2mu4_bJpsimumu_L12MU4 #4276347155
-TrigSignatureMoniMT                                INFO -- #4276347155 Events         4          4          4          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #4276347155 Features                             16         0          0          0          0
-TrigSignatureMoniMT                                INFO HLT_2mu4_bUpsimumu_L12MU4 #4008168535
-TrigSignatureMoniMT                                INFO -- #4008168535 Events         4          4          4          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #4008168535 Features                             16         0          0          0          0
 TrigSignatureMoniMT                                INFO HLT_2mu4_muonqual_L12MU4 #1584776935
 TrigSignatureMoniMT                                INFO -- #1584776935 Events         4          4          4          4          4          4          -          4
 TrigSignatureMoniMT                                INFO -- #1584776935 Features                             16         16         24         20         -
@@ -123,7 +108,7 @@ TrigSignatureMoniMT                                INFO -- #3534544568 Events
 TrigSignatureMoniMT                                INFO -- #3534544568 Features                             0          0          0          0          -
 TrigSignatureMoniMT                                INFO HLT_g20_etcut_LArPEB_L1EM15 #2706532790
 TrigSignatureMoniMT                                INFO -- #2706532790 Events         14         14         14         14         12         12         -          12
-TrigSignatureMoniMT                                INFO -- #2706532790 Features                             24         24         22         22         -
+TrigSignatureMoniMT                                INFO -- #2706532790 Features                             24         24         22         20         -
 TrigSignatureMoniMT                                INFO HLT_g35_medium_g25_medium_L12EM20VH #1158879722
 TrigSignatureMoniMT                                INFO -- #1158879722 Events         2          2          -          -          -          -          -          0
 TrigSignatureMoniMT                                INFO -- #1158879722 Features                             -          -          -          -          -
@@ -132,7 +117,7 @@ TrigSignatureMoniMT                                INFO -- #471243435 Events
 TrigSignatureMoniMT                                INFO -- #471243435 Features                              140        140        190        -          -
 TrigSignatureMoniMT                                INFO HLT_g5_etcut_LArPEB_L1EM3 #3486231698
 TrigSignatureMoniMT                                INFO -- #3486231698 Events         20         20         20         20         20         20         -          20
-TrigSignatureMoniMT                                INFO -- #3486231698 Features                             140        140        190        190        -
+TrigSignatureMoniMT                                INFO -- #3486231698 Features                             140        140        190        120        -
 TrigSignatureMoniMT                                INFO HLT_g5_loose_L1EM3 #3230088967
 TrigSignatureMoniMT                                INFO -- #3230088967 Events         20         20         17         17         17         9          -          9
 TrigSignatureMoniMT                                INFO -- #3230088967 Features                             57         57         117        14         -
diff --git a/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_mt1_build.ref b/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_mt1_build.ref
index d204d01db4a..823a9af7718 100644
--- a/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_mt1_build.ref
+++ b/Trigger/TrigValidation/TrigAnalysisTest/share/ref_RDOtoRDOTrig_mt1_build.ref
@@ -19,27 +19,12 @@ TrigSignatureMoniMT                                INFO -- #3965466087 Features
 TrigSignatureMoniMT                                INFO HLT_2j330_a10t_lcw_jes_35smcINF_L1J100 #1295975955
 TrigSignatureMoniMT                                INFO -- #1295975955 Events         3          3          0          -          -          -          -          0
 TrigSignatureMoniMT                                INFO -- #1295975955 Features                             0          -          -          -          -
-TrigSignatureMoniMT                                INFO HLT_2mu10_bJpsimumu_L12MU10 #3498558358
-TrigSignatureMoniMT                                INFO -- #3498558358 Events         3          3          3          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #3498558358 Features                             12         0          0          0          0
-TrigSignatureMoniMT                                INFO HLT_2mu10_bUpsimumu_L12MU10 #234102568
-TrigSignatureMoniMT                                INFO -- #234102568 Events          3          3          3          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #234102568 Features                              12         0          0          0          0
 TrigSignatureMoniMT                                INFO HLT_2mu14_L12MU10 #2619091790
 TrigSignatureMoniMT                                INFO -- #2619091790 Events         3          3          3          1          1          1          -          1
 TrigSignatureMoniMT                                INFO -- #2619091790 Features                             12         4          4          4          -
 TrigSignatureMoniMT                                INFO HLT_2mu15_L12MU10 #557204938
 TrigSignatureMoniMT                                INFO -- #557204938 Events          3          3          3          1          1          1          -          1
 TrigSignatureMoniMT                                INFO -- #557204938 Features                              12         4          4          4          -
-TrigSignatureMoniMT                                INFO HLT_2mu4_bDimu_L12MU4 #1730084172
-TrigSignatureMoniMT                                INFO -- #1730084172 Events         4          4          4          1          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #1730084172 Features                             16         9          0          0          0
-TrigSignatureMoniMT                                INFO HLT_2mu4_bJpsimumu_L12MU4 #4276347155
-TrigSignatureMoniMT                                INFO -- #4276347155 Events         4          4          4          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #4276347155 Features                             16         0          0          0          0
-TrigSignatureMoniMT                                INFO HLT_2mu4_bUpsimumu_L12MU4 #4008168535
-TrigSignatureMoniMT                                INFO -- #4008168535 Events         4          4          4          0          0          0          0          0
-TrigSignatureMoniMT                                INFO -- #4008168535 Features                             16         0          0          0          0
 TrigSignatureMoniMT                                INFO HLT_2mu4_muonqual_L12MU4 #1584776935
 TrigSignatureMoniMT                                INFO -- #1584776935 Events         4          4          4          4          4          4          -          4
 TrigSignatureMoniMT                                INFO -- #1584776935 Features                             16         16         24         20         -
@@ -123,7 +108,7 @@ TrigSignatureMoniMT                                INFO -- #3534544568 Events
 TrigSignatureMoniMT                                INFO -- #3534544568 Features                             0          0          0          0          -
 TrigSignatureMoniMT                                INFO HLT_g20_etcut_LArPEB_L1EM15 #2706532790
 TrigSignatureMoniMT                                INFO -- #2706532790 Events         14         14         14         14         12         12         -          12
-TrigSignatureMoniMT                                INFO -- #2706532790 Features                             24         24         22         22         -
+TrigSignatureMoniMT                                INFO -- #2706532790 Features                             24         24         22         20         -
 TrigSignatureMoniMT                                INFO HLT_g35_medium_g25_medium_L12EM20VH #1158879722
 TrigSignatureMoniMT                                INFO -- #1158879722 Events         2          2          -          -          -          -          -          0
 TrigSignatureMoniMT                                INFO -- #1158879722 Features                             -          -          -          -          -
@@ -132,7 +117,7 @@ TrigSignatureMoniMT                                INFO -- #471243435 Events
 TrigSignatureMoniMT                                INFO -- #471243435 Features                              137        137        190        -          -
 TrigSignatureMoniMT                                INFO HLT_g5_etcut_LArPEB_L1EM3 #3486231698
 TrigSignatureMoniMT                                INFO -- #3486231698 Events         20         20         20         20         20         20         -          20
-TrigSignatureMoniMT                                INFO -- #3486231698 Features                             137        137        190        190        -
+TrigSignatureMoniMT                                INFO -- #3486231698 Features                             137        137        190        118        -
 TrigSignatureMoniMT                                INFO HLT_g5_loose_L1EM3 #3230088967
 TrigSignatureMoniMT                                INFO -- #3230088967 Events         20         20         17         17         17         9          -          9
 TrigSignatureMoniMT                                INFO -- #3230088967 Features                             56         56         116        12         -
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/egammaRinger.py b/Trigger/TrigValidation/TrigUpgradeTest/share/egammaRinger.py
index 9db33913147..5f6cdba46bf 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/share/egammaRinger.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/share/egammaRinger.py
@@ -4,7 +4,7 @@
 
 from AthenaCommon.Constants import ERROR, DEBUG
 from AthenaCommon.CFElements import seqAND
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 
 
 doWriteRDOTrigger = False
@@ -56,10 +56,11 @@ fastCaloViewsMaker = EventViewCreatorAlgorithm( "fastCaloViewsMaker", OutputLeve
 fastCaloViewsMaker.ViewFallThrough = True
 fastCaloViewsMaker.InputMakerInputDecisions =  [ "FilteredEMRoIDecisions" ]
 fastCaloViewsMaker.RoIsLink = "initialRoI"
+fastCaloViewsMaker.RoITool = ViewCreatorInitialROITool()
 fastCaloViewsMaker.InViewRoIs = InViewRoIs
 fastCaloViewsMaker.Views = "EMCaloViews"
 fastCaloViewsMaker.ViewNodeName = "fastCaloInViewSequence"
-fastCaloViewsMaker.InputMakerOutputDecisions = [ "L2CaloLinks"]
+fastCaloViewsMaker.InputMakerOutputDecisions = "L2CaloLinks"
 clusterMaker.OutputLevel=FATAL
 
 if doRinger:
@@ -80,7 +81,7 @@ for t in fastCaloHypo.HypoTools:
 
 fastCaloHypo.HypoOutputDecisions = "EgammaCaloDecisions"
 fastCaloHypo.OutputLevel= DEBUG
-fastCaloHypo.HypoInputDecisions =  fastCaloViewsMaker.InputMakerOutputDecisions[0] #   __l1RoIDecisions
+fastCaloHypo.HypoInputDecisions =  fastCaloViewsMaker.InputMakerOutputDecisions #   __l1RoIDecisions
 
 
 fastCaloSequence = seqAND("fastCaloSequence", [fastCaloViewsMaker, fastCaloInViewSequence, fastCaloHypo ])
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref
index a864297a165..a9c40f9d240 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref
+++ b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref
@@ -19,27 +19,12 @@ TrigSignatureMoniMT                                 INFO -- #3965466087 Features
 TrigSignatureMoniMT                                 INFO HLT_2j330_a10t_lcw_jes_35smcINF_L1J100 #1295975955
 TrigSignatureMoniMT                                 INFO -- #1295975955 Events         20         20         0          -          -          -          -          0          
 TrigSignatureMoniMT                                 INFO -- #1295975955 Features                             0          -          -          -          -          
-TrigSignatureMoniMT                                 INFO HLT_2mu10_bJpsimumu_L12MU10 #3498558358
-TrigSignatureMoniMT                                 INFO -- #3498558358 Events         20         20         0          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #3498558358 Features                             0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO HLT_2mu10_bUpsimumu_L12MU10 #234102568
-TrigSignatureMoniMT                                 INFO -- #234102568 Events          20         20         0          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #234102568 Features                              0          0          0          0          0          
 TrigSignatureMoniMT                                 INFO HLT_2mu14_L12MU10 #2619091790
 TrigSignatureMoniMT                                 INFO -- #2619091790 Events         20         20         0          0          0          0          -          0          
 TrigSignatureMoniMT                                 INFO -- #2619091790 Features                             0          0          0          0          -          
 TrigSignatureMoniMT                                 INFO HLT_2mu15_L12MU10 #557204938
 TrigSignatureMoniMT                                 INFO -- #557204938 Events          20         20         0          0          0          0          -          0          
 TrigSignatureMoniMT                                 INFO -- #557204938 Features                              0          0          0          0          -          
-TrigSignatureMoniMT                                 INFO HLT_2mu4_bDimu_L12MU4 #1730084172
-TrigSignatureMoniMT                                 INFO -- #1730084172 Events         20         20         1          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #1730084172 Features                             4          0          0          0          0          
-TrigSignatureMoniMT                                 INFO HLT_2mu4_bJpsimumu_L12MU4 #4276347155
-TrigSignatureMoniMT                                 INFO -- #4276347155 Events         20         20         1          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #4276347155 Features                             4          0          0          0          0          
-TrigSignatureMoniMT                                 INFO HLT_2mu4_bUpsimumu_L12MU4 #4008168535
-TrigSignatureMoniMT                                 INFO -- #4008168535 Events         20         20         1          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #4008168535 Features                             4          0          0          0          0          
 TrigSignatureMoniMT                                 INFO HLT_2mu4_muonqual_L12MU4 #1584776935
 TrigSignatureMoniMT                                 INFO -- #1584776935 Events         20         20         1          0          0          0          -          0          
 TrigSignatureMoniMT                                 INFO -- #1584776935 Features                             4          0          0          0          -          
@@ -138,7 +123,7 @@ TrigSignatureMoniMT                                 INFO -- #471243435 Events
 TrigSignatureMoniMT                                 INFO -- #471243435 Features                              41         41         50         -          -          
 TrigSignatureMoniMT                                 INFO HLT_g5_etcut_LArPEB_L1EM3 #3486231698
 TrigSignatureMoniMT                                 INFO -- #3486231698 Events         20         20         13         13         13         13         -          13         
-TrigSignatureMoniMT                                 INFO -- #3486231698 Features                             41         41         50         50         -          
+TrigSignatureMoniMT                                 INFO -- #3486231698 Features                             41         41         50         36         -          
 TrigSignatureMoniMT                                 INFO HLT_g5_loose_L1EM3 #3230088967
 TrigSignatureMoniMT                                 INFO -- #3230088967 Events         20         20         10         10         10         2          -          2          
 TrigSignatureMoniMT                                 INFO -- #3230088967 Features                             15         15         31         2          -          
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/photon.withViews.py b/Trigger/TrigValidation/TrigUpgradeTest/share/photon.withViews.py
index ae7b2636702..e6728c83928 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/share/photon.withViews.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/share/photon.withViews.py
@@ -18,7 +18,7 @@ trigL2CaloRingerFexMT = init_ringer()
 
 from AthenaCommon.CFElements import parOR, seqOR, seqAND, stepSeq, findAlgorithm
 from DecisionHandling.DecisionHandlingConf import RoRSeqFilter, DumpDecisions
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 
 
 def createFastCaloSequence(rerun=False):
@@ -40,17 +40,18 @@ def createFastCaloSequence(rerun=False):
    fastCaloViewsMaker = EventViewCreatorAlgorithm( __prefix+"fastCaloViewsMaker" )
    fastCaloViewsMaker.ViewFallThrough = True
    fastCaloViewsMaker.InputMakerInputDecisions =  [ __forViewDecsions ]
-   fastCaloViewsMaker.RoIsLink = "initialRoI" # -||-
-   fastCaloViewsMaker.InViewRoIs = "EMCaloRoIs" # contract with the fastCalo
+   fastCaloViewsMaker.RoIsLink = "initialRoI"
+   fastCaloViewsMaker.RoITool = ViewCreatorInitialROITool()
+   fastCaloViewsMaker.InViewRoIs = "EMCaloRoIs" 
    fastCaloViewsMaker.Views = __prefix+"EMCaloViews"
    fastCaloViewsMaker.ViewNodeName = __prefix+"fastCaloInViewAlgs"
-   fastCaloViewsMaker.InputMakerOutputDecisions = [ "L2CaloLinks"]
+   fastCaloViewsMaker.InputMakerOutputDecisions = "L2CaloLinks"
    clusterMaker.RoIs = fastCaloViewsMaker.InViewRoIs
 
    from TrigEgammaHypo.TrigEgammaHypoConf import TrigL2CaloHypoAlgMT
    from TrigEgammaHypo.TrigL2CaloHypoTool import TrigL2CaloHypoToolFromName
    fastCaloHypo = TrigL2CaloHypoAlgMT( __prefix+"L2CaloHypo" )
-   fastCaloHypo.HypoInputDecisions =  fastCaloViewsMaker.InputMakerOutputDecisions[0] #   __l1RoIDecisions
+   fastCaloHypo.HypoInputDecisions =  fastCaloViewsMaker.InputMakerOutputDecisions #   __l1RoIDecisions
 #   fastCaloHypo.Views = fastCaloViewsMaker.Views
    fastCaloHypo.CaloClusters = clusterMaker.ClustersName
 #   fastCaloHypo.RoIs = fastCaloViewsMaker.InViewRoIs
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx
index 4644a942119..33936a0e6c7 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx
@@ -38,8 +38,8 @@ namespace HLTTest {
     ATH_MSG_DEBUG( "Executing " << name() << "..." );
 
     // call base class helper method to read input decisions, loop over them create outputs and connect them, returns with outputHandles filled
-    std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > outputHandles;
-    CHECK (decisionInputToOutput(context, outputHandles));
+    SG::WriteHandle<DecisionContainer> outputHandle = createAndStore( decisionOutputs(), context );
+    CHECK (decisionInputToOutput(context, outputHandle));
 
     // output collection, as a view container so it can be given const features
     auto reco_output = std::make_unique<xAOD::TrigCompositeContainer>();
@@ -48,54 +48,52 @@ namespace HLTTest {
     std::vector<const FeatureOBJ*> featuresFromDecision; // used to check for duplicate features linked to different inputHandles
     
     // loop over output decisions, navigate to inputs
-    for (auto outputHandle: outputHandles) {
-      if( not outputHandle.isValid() ) {
-        ATH_MSG_DEBUG( "TestInputMaker: Got no decisions from output "<< outputHandle.key() << " because handle not valid");
-        continue;
-      }
-      if( outputHandle->size() == 0){ // input filtered out
-        ATH_MSG_ERROR( "TestInputMaker: Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty. Is this expected?");
-        return StatusCode::FAILURE;
-      }
-
-      ATH_MSG_DEBUG( "TestInputMaker: Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
-      // loop over output decisions in container of outputHandle, follow link to inputDecision
-      int count =0;
-      for (const  auto outputDecision : *outputHandle){ 
-        const ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
-	ATH_MSG_DEBUG("Element "<< count << " has " << inputLinks.size() <<" previous links");
-        for (const auto input: inputLinks){
-          ATH_MSG_DEBUG( " -- Got seed link to input  "<<input.dataID() <<" and index "<< input.index() );
-          const Decision* inputDecision = *input;
-          const auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( inputDecision,  m_roisLink.value());
-          CHECK( roiELInfo.isValid() );
-
-          // retrieve input feature from input decision (TrigComposite), will in this case be a TrigRoiDescriptor   
-          const auto featureLinkInfo = TrigCompositeUtils::findLink<FeatureContainer>( inputDecision,  m_linkName.value());
-          CHECK( featureLinkInfo.isValid() );
-
-          // link input reco object to outputDecision
-          const auto featureLink = featureLinkInfo.link;
-          const FeatureOBJ* feature = *featureLink;
-          ATH_MSG_DEBUG(" --  Found feature " <<m_linkName.value() <<":" << **featureLink);
-
-          // merge reco outputs that are linked to the same feature (RoI): this avoids processing the same RoI from TC decisions from different chains
-
-          // avoid adding the same feature multiple times: check if not in container, if not add it
-          if ( find(featuresFromDecision.begin(), featuresFromDecision.end(), feature) == featuresFromDecision.end() ){
-            featuresFromDecision.push_back(feature); // just to keep track of which we have used 
-            // create the "reco" output: this would normally be a copy of the reco input or something derived from it, e.g. detector data inside a RoI. A TrigComposite is used here just for a trivial example.
-            auto newFeature = new xAOD::TrigComposite;
-            reco_output->push_back(newFeature); 
-            newFeature->setObjectLink(m_linkName.value(), featureLink);
-            ATH_MSG_DEBUG(" --  Added " <<m_linkName.value() << " and " << m_roisLink.value() << " to reco object");
-          }
-        }//loop over previous inputs
-        // For early tests, create TC, link to RoiD, push back onto TCC.
-        // Later will output RoID collection directly via tool.        
-	count++;
-      } // loop over decisions
-    } // loop over output keys
+    if( not outputHandle.isValid() ) {
+      ATH_MSG_ERROR( "TestInputMaker: Got no decisions from output "<< outputHandle.key() << " because handle not valid");
+      return StatusCode::FAILURE;
+    }
+    if( outputHandle->size() == 0){ // input filtered out
+      ATH_MSG_ERROR( "TestInputMaker: Got no decisions from output "<< outputHandle.key()<<": handle is valid but container is empty.");
+      return StatusCode::FAILURE;
+    }
+
+    ATH_MSG_DEBUG( "TestInputMaker: Got output "<< outputHandle.key()<<" with " << outputHandle->size() << " elements" );
+    // loop over output decisions in container of outputHandle, follow link to inputDecision
+    int count =0;
+    for (const  auto outputDecision : *outputHandle){ 
+      const ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
+      ATH_MSG_DEBUG("Element "<< count << " has " << inputLinks.size() <<" previous links");
+      for (const auto input: inputLinks){
+        ATH_MSG_DEBUG( " -- Got seed link to input  "<<input.dataID() <<" and index "<< input.index() );
+        const Decision* inputDecision = *input;
+        const auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( inputDecision,  m_roisLink.value());
+        CHECK( roiELInfo.isValid() );
+
+        // retrieve input feature from input decision (TrigComposite), will in this case be a TrigRoiDescriptor   
+        const auto featureLinkInfo = TrigCompositeUtils::findLink<FeatureContainer>( inputDecision,  m_linkName.value());
+        CHECK( featureLinkInfo.isValid() );
+
+        // link input reco object to outputDecision
+        const auto featureLink = featureLinkInfo.link;
+        const FeatureOBJ* feature = *featureLink;
+        ATH_MSG_DEBUG(" --  Found feature " <<m_linkName.value() <<":" << **featureLink);
+
+        // merge reco outputs that are linked to the same feature (RoI): this avoids processing the same RoI from TC decisions from different chains
+
+        // avoid adding the same feature multiple times: check if not in container, if not add it
+        if ( find(featuresFromDecision.begin(), featuresFromDecision.end(), feature) == featuresFromDecision.end() ){
+          featuresFromDecision.push_back(feature); // just to keep track of which we have used 
+          // create the "reco" output: this would normally be a copy of the reco input or something derived from it, e.g. detector data inside a RoI. A TrigComposite is used here just for a trivial example.
+          auto newFeature = new xAOD::TrigComposite;
+          reco_output->push_back(newFeature); 
+          newFeature->setObjectLink(m_linkName.value(), featureLink);
+          ATH_MSG_DEBUG(" --  Added " <<m_linkName.value() << " and " << m_roisLink.value() << " to reco object");
+        }
+      }//loop over previous inputs
+      // For early tests, create TC, link to RoiD, push back onto TCC.
+      // Later will output RoID collection directly via tool.        
+      count++;
+    } // loop over decisions
    
     // Finally, record output
     ATH_MSG_DEBUG("Produced "<<reco_output->size() <<" reco objects and stored in "<<m_recoOutput);
@@ -103,7 +101,7 @@ namespace HLTTest {
     CHECK( reco_outputHandle.record(std::move(reco_output), std::move(aux)) );
 
     // call base class helper method to print some debug messages summarising the content of the outputHandles.
-    if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandles);
+    if (msgLvl(MSG::DEBUG)) debugPrintOut(context, outputHandle);
 
     return StatusCode::SUCCESS;
   }
diff --git a/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref b/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref
index a864297a165..a9c40f9d240 100644
--- a/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref
+++ b/Trigger/TrigValidation/TriggerTest/share/ref_data_v1Dev_build.ref
@@ -19,27 +19,12 @@ TrigSignatureMoniMT                                 INFO -- #3965466087 Features
 TrigSignatureMoniMT                                 INFO HLT_2j330_a10t_lcw_jes_35smcINF_L1J100 #1295975955
 TrigSignatureMoniMT                                 INFO -- #1295975955 Events         20         20         0          -          -          -          -          0          
 TrigSignatureMoniMT                                 INFO -- #1295975955 Features                             0          -          -          -          -          
-TrigSignatureMoniMT                                 INFO HLT_2mu10_bJpsimumu_L12MU10 #3498558358
-TrigSignatureMoniMT                                 INFO -- #3498558358 Events         20         20         0          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #3498558358 Features                             0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO HLT_2mu10_bUpsimumu_L12MU10 #234102568
-TrigSignatureMoniMT                                 INFO -- #234102568 Events          20         20         0          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #234102568 Features                              0          0          0          0          0          
 TrigSignatureMoniMT                                 INFO HLT_2mu14_L12MU10 #2619091790
 TrigSignatureMoniMT                                 INFO -- #2619091790 Events         20         20         0          0          0          0          -          0          
 TrigSignatureMoniMT                                 INFO -- #2619091790 Features                             0          0          0          0          -          
 TrigSignatureMoniMT                                 INFO HLT_2mu15_L12MU10 #557204938
 TrigSignatureMoniMT                                 INFO -- #557204938 Events          20         20         0          0          0          0          -          0          
 TrigSignatureMoniMT                                 INFO -- #557204938 Features                              0          0          0          0          -          
-TrigSignatureMoniMT                                 INFO HLT_2mu4_bDimu_L12MU4 #1730084172
-TrigSignatureMoniMT                                 INFO -- #1730084172 Events         20         20         1          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #1730084172 Features                             4          0          0          0          0          
-TrigSignatureMoniMT                                 INFO HLT_2mu4_bJpsimumu_L12MU4 #4276347155
-TrigSignatureMoniMT                                 INFO -- #4276347155 Events         20         20         1          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #4276347155 Features                             4          0          0          0          0          
-TrigSignatureMoniMT                                 INFO HLT_2mu4_bUpsimumu_L12MU4 #4008168535
-TrigSignatureMoniMT                                 INFO -- #4008168535 Events         20         20         1          0          0          0          0          0          
-TrigSignatureMoniMT                                 INFO -- #4008168535 Features                             4          0          0          0          0          
 TrigSignatureMoniMT                                 INFO HLT_2mu4_muonqual_L12MU4 #1584776935
 TrigSignatureMoniMT                                 INFO -- #1584776935 Events         20         20         1          0          0          0          -          0          
 TrigSignatureMoniMT                                 INFO -- #1584776935 Features                             4          0          0          0          -          
@@ -138,7 +123,7 @@ TrigSignatureMoniMT                                 INFO -- #471243435 Events
 TrigSignatureMoniMT                                 INFO -- #471243435 Features                              41         41         50         -          -          
 TrigSignatureMoniMT                                 INFO HLT_g5_etcut_LArPEB_L1EM3 #3486231698
 TrigSignatureMoniMT                                 INFO -- #3486231698 Events         20         20         13         13         13         13         -          13         
-TrigSignatureMoniMT                                 INFO -- #3486231698 Features                             41         41         50         50         -          
+TrigSignatureMoniMT                                 INFO -- #3486231698 Features                             41         41         50         36         -          
 TrigSignatureMoniMT                                 INFO HLT_g5_loose_L1EM3 #3230088967
 TrigSignatureMoniMT                                 INFO -- #3230088967 Events         20         20         10         10         10         2          -          2          
 TrigSignatureMoniMT                                 INFO -- #3230088967 Features                             15         15         31         2          -          
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bjet/BjetSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bjet/BjetSequenceSetup.py
index e8fb8a48611..f5451678be4 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bjet/BjetSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bjet/BjetSequenceSetup.py
@@ -31,8 +31,9 @@ def bJetStep1Sequence():
     jetsKey = "HLT_AntiKt4EMTopoJets_subjesgscIS_ftf"
     prmVtxKey = "HLT_EFHistoPrmVtx"
 
-    from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+    from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
     InputMakerAlg = EventViewCreatorAlgorithm( "IMBJet_step2", RoIsLink="initialRoI" )
+    InputMakerAlg.RoITool = ViewCreatorInitialROITool()
     InputMakerAlg.Views = "FullScanBjetView"
     InputMakerAlg.InViewRoIs = "FullScanRoI"
     InputMakerAlg.ViewFallThrough = True
@@ -80,10 +81,11 @@ def bJetStep2Sequence():
     roisLink = "step1RoI"
     prmVtxKey = "HLT_EFHistoPrmVtx"
 
-    from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithmWithJets
+    from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithmWithJets, ViewCreatorInitialROITool
     InputMakerAlg = EventViewCreatorAlgorithmWithJets( "IMBJet_step3",RoIsLink=roisLink )
     InputMakerAlg.ViewFallThrough = True
     InputMakerAlg.RequireParentView = True
+    InputMakerAlg.RoITool = ViewCreatorInitialROITool() # NOT USED! TO BE REPLACED WITH NEW TOOL ON CONVERTING EventViewCreatorAlgorithmWithJets -> EventViewCreatorAlgorithm
     InputMakerAlg.Views = "BTagViews"
     InputMakerAlg.InViewRoIs = "InViewRoIs"
     InputMakerAlg.InViewJets = "InViewJets"
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsSequenceSetup.py
index a1a09560664..d20b32d7a32 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsSequenceSetup.py
@@ -25,7 +25,7 @@ def dimuL2Sequence(name = 'Dimu'):
 def dimuEFSequence(name = 'Dimu'):
     from AthenaCommon import CfgMgr
     from AthenaCommon.CFElements import parOR, seqAND
-    from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+    from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
     from TriggerMenuMT.HLTMenuConfig.Muon.MuonSetup import muonNames
 
     muNames = muonNames().getNames('RoI')
@@ -34,8 +34,9 @@ def dimuEFSequence(name = 'Dimu'):
 
     dimuefViewsMaker = EventViewCreatorAlgorithm('IMdimuef')
     dimuefViewsMaker.ViewFallThrough = True
-    dimuefViewsMaker.RoIsLink = 'initialRoI' # -||-
-    dimuefViewsMaker.InViewRoIs = 'DimuEFRoIs' # contract with the consumer
+    dimuefViewsMaker.RoIsLink = 'initialRoI'
+    dimuefViewsMaker.RoITool = ViewCreatorInitialROITool()
+    dimuefViewsMaker.InViewRoIs = 'DimuEFRoIs'
     dimuefViewsMaker.Views = 'DimuEFViewRoIs'
     dimuefViewsMaker.ViewNodeName = dimuefRecoSequence.name()
     dimuefViewsMaker.RequireParentView = True
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/BeamspotChainConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/BeamspotChainConfiguration.py
index 1fb9bbcb10b..59fddf42bc7 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/BeamspotChainConfiguration.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/BeamspotChainConfiguration.py
@@ -9,7 +9,7 @@ from TrigStreamerHypo.TrigStreamerHypoConfigMT import StreamerHypoToolMTgenerato
 from TrigStreamerHypo.TrigStreamerHypoConf import TrigStreamerHypoAlgMT
 from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import MenuSequence
 from AthenaCommon.CFElements import seqAND
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 
 
 #----------------------------------------------------------------
@@ -25,8 +25,9 @@ def allTE_trkfast_Cfg( flags ):
 def allTE_trkfast():
         inputMakerAlg = EventViewCreatorAlgorithm("IM_beamspot")
         inputMakerAlg.ViewFallThrough = True
-        inputMakerAlg.RoIsLink = "initialRoI" # -||-
-        inputMakerAlg.InViewRoIs = "beamspotInputRoIs" # contract with the consumer
+        inputMakerAlg.RoIsLink = "initialRoI"
+        inputMakerAlg.RoITool = ViewCreatorInitialROITool()
+        inputMakerAlg.InViewRoIs = "beamspotInputRoIs"
         inputMakerAlg.Views = "beamspotViewRoIs"
 
         from TrigInDetConfig.InDetSetup import makeInDetAlgs
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/StreamingChainConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/StreamingChainConfiguration.py
index fbe4ee4bfc4..c8ffd0373c1 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/StreamingChainConfiguration.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CalibCosmicMon/StreamingChainConfiguration.py
@@ -22,7 +22,7 @@ def StreamingSequenceCfg( flags ):
 
 def StreamingMenuSequence():
 
-    inputMakerAlg = InputMakerForRoI("IM_streamerInputMaker", mergeOutputs=False)
+    inputMakerAlg = InputMakerForRoI("IM_streamerInputMaker")
     inputMakerAlg.RoIs="streamerInputRoIs"
     streamingSequence = seqAND("streamerSequence", [inputMakerAlg])
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CommonSequences/EventBuildingSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CommonSequences/EventBuildingSequenceSetup.py
index eb25a96e8ed..75772095f5e 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CommonSequences/EventBuildingSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/CommonSequences/EventBuildingSequenceSetup.py
@@ -81,7 +81,7 @@ def pebInfoWriterTool(name, eventBuildType):
 
 
 def pebInputMaker(eventBuildType):
-    maker = InputMakerForRoI("IMpeb_"+eventBuildType, mergeOutputs=False)
+    maker = InputMakerForRoI("IMpeb_"+eventBuildType)
     maker.RoIs = "pebInputRoI_" + eventBuildType
     return maker
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/ElectronSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/ElectronSequenceSetup.py
index b4cd900b24d..037e16318f5 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/ElectronSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/ElectronSequenceSetup.py
@@ -11,7 +11,7 @@ from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import MenuSequence, RecoFr
 # Until such time as FS and RoI collections do not interfere, a hacky fix
 #from AthenaCommon.CFElements import parOR, seqAND
 from AthenaCommon.CFElements import seqAND
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 from TrigEDMConfig.TriggerEDMRun3 import recordable
 
 def fastElectronSequence(ConfigFlags):
@@ -42,7 +42,8 @@ def fastElectronSequence(ConfigFlags):
 
     # EVCreator:
     l2ElectronViewsMaker = EventViewCreatorAlgorithm("IMl2Electron")
-    l2ElectronViewsMaker.RoIsLink = "initialRoI" # -||-
+    l2ElectronViewsMaker.RoIsLink = "initialRoI"
+    l2ElectronViewsMaker.RoITool = ViewCreatorInitialROITool()
     l2ElectronViewsMaker.InViewRoIs = RoIs
     l2ElectronViewsMaker.Views = "EMElectronViews"
     l2ElectronViewsMaker.ViewFallThrough = True
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PhotonSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PhotonSequenceSetup.py
index db780b12566..bdfc11fa958 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PhotonSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PhotonSequenceSetup.py
@@ -3,7 +3,7 @@
 # menu components   
 from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import MenuSequence, RecoFragmentsPool
 from AthenaCommon.CFElements import parOR, seqAND
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 import AthenaCommon.CfgMgr as CfgMgr
 from TrigEDMConfig.TriggerEDMRun3 import recordable
 
@@ -29,6 +29,7 @@ def fastPhotonMenuSequence():
     l2PhotonViewsMaker.RoIsLink = "initialRoI"
     l2PhotonViewsMaker.InViewRoIs = "EMIDRoIs" 
     #l2PhotonViewsMaker.InViewRoIs = "EMCaloRoIs"
+    l2PhotonViewsMaker.RoITool = ViewCreatorInitialROITool()
     l2PhotonViewsMaker.Views = "EMPhotonViews"
     l2PhotonViewsMaker.ViewFallThrough = True
     l2PhotonViewsMaker.RequireParentView = True
@@ -67,7 +68,8 @@ def precisionPhotonSequence(ConfigFlags):
     precisionPhotonViewsMaker = EventViewCreatorAlgorithm( "IMprecisionPhoton") 
     precisionPhotonViewsMaker.ViewFallThrough = True                          
     precisionPhotonViewsMaker.RequireParentView = True
-    precisionPhotonViewsMaker.RoIsLink = "initialRoI"            # 
+    precisionPhotonViewsMaker.RoIsLink = "initialRoI"            # ROI link used to merge inputs
+    precisionPhotonViewsMaker.RoITool = ViewCreatorInitialROITool() # Tool used to supply ROIs for EventViews
     precisionPhotonViewsMaker.InViewRoIs = InViewRoIs            # names to use for the collection of which the RoIs are picked up
     precisionPhotonViewsMaker.Views = "precisionPhotonViews"     # Output container which has the view objects
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionCaloSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionCaloSequenceSetup.py
index fd30c985f25..16ffb099d64 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionCaloSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionCaloSequenceSetup.py
@@ -5,7 +5,7 @@
 # menu components   
 from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import MenuSequence, RecoFragmentsPool
 from AthenaCommon.CFElements import seqAND
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 from AthenaConfiguration.AllConfigFlags import ConfigFlags
 from TrigEDMConfig.TriggerEDMRun3 import recordable
       
@@ -20,6 +20,7 @@ def precisionCaloSequence(ConfigFlags):
     precisionCaloViewsMaker = EventViewCreatorAlgorithm( "IMprecisionCalo")
     precisionCaloViewsMaker.ViewFallThrough = True
     precisionCaloViewsMaker.RoIsLink = "initialRoI"
+    precisionCaloViewsMaker.RoITool = ViewCreatorInitialROITool()
     precisionCaloViewsMaker.InViewRoIs = InViewRoIs
     precisionCaloViewsMaker.Views = "precisionCaloViews"
     precisionCaloViewsMaker.RequireParentView = True
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionElectronSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionElectronSequenceSetup.py
index a4cd9177ae0..ef6f786ca71 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionElectronSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Egamma/PrecisionElectronSequenceSetup.py
@@ -7,7 +7,7 @@ from AthenaConfiguration.AllConfigFlags import ConfigFlags
 # menu components   
 from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import MenuSequence, RecoFragmentsPool
 from AthenaCommon.CFElements import parOR, seqAND
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
 
 
 def precisionElectronSequence(ConfigFlags):
@@ -15,8 +15,9 @@ def precisionElectronSequence(ConfigFlags):
     InViewRoIs = "precisionElectron"
     # EVCreator:
     precisionTrackViewsMaker = EventViewCreatorAlgorithm("IMprecisionTrack")
-    precisionTrackViewsMaker.RoIsLink = "initialRoI" # -||-
-    precisionTrackViewsMaker.InViewRoIs = InViewRoIs # contract with the precisionCalo
+    precisionTrackViewsMaker.RoIsLink = "initialRoI"
+    precisionTrackViewsMaker.RoITool = ViewCreatorInitialROITool()
+    precisionTrackViewsMaker.InViewRoIs = InViewRoIs
     precisionTrackViewsMaker.Views = "precisionElectronViews" #precisionTrackViews
     precisionTrackViewsMaker.ViewFallThrough = True
     precisionTrackViewsMaker.RequireParentView = True
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/CFValidation.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/CFValidation.py
index 948cca5d5ca..7425df5cdff 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/CFValidation.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/CFValidation.py
@@ -76,6 +76,9 @@ def checkVDV( inputNodes, ancestorNames, allEVCAs ):
                     raise RuntimeError( "Found duplicate view node name " + node.ViewNodeName + " configured for EVCAs " + node.name() + " and " + allEVCAs[ node.ViewNodeName ].name() )
             allEVCAs[ node.ViewNodeName ] = node
 
+            if not hasattr(node, "RoITool"):
+                raise RuntimeError( "Node name " + node.name() + " was not supplied with a RoITool" )
+
         # Explore nested CF
         if isSequence( node ):
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
index 577b0256e59..e9be877863f 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1.py
@@ -14,7 +14,8 @@ from TriggerMenuMT.HLTMenuConfig.Menu.MenuPrescaleConfig import addSliceChainsTo
 import TriggerMenuMT.HLTMenuConfig.Menu.MC_pp_run3_v1 as mc_menu
 import TriggerMenuMT.HLTMenuConfig.Menu.PhysicsP1_pp_run3_v1 as p1_menu
 
-from TriggerMenuMT.HLTMenuConfig.Menu.Physics_pp_run3_v1 import PhysicsStream,SingleMuonGroup,MultiMuonGroup,SingleElectronGroup,MultiElectronGroup,SinglePhotonGroup,MultiPhotonGroup,SingleMETGroup,MultiMETGroup,SingleJetGroup,MultiJetGroup,SingleBjetGroup,SingleTauGroup,EgammaStreamersGroup,MinBiasGroup,BphysicsGroup
+from TriggerMenuMT.HLTMenuConfig.Menu.Physics_pp_run3_v1 import PhysicsStream,SingleMuonGroup,MultiMuonGroup,SingleElectronGroup,MultiElectronGroup,SinglePhotonGroup,MultiPhotonGroup,SingleMETGroup,MultiMETGroup,SingleJetGroup,MultiJetGroup,SingleBjetGroup,SingleTauGroup,EgammaStreamersGroup,MinBiasGroup
+#BphysicsGroup (re-add to the preceding line when putting bphys back in)
 
 
 def setupMenu():
@@ -179,12 +180,13 @@ def setupMenu():
         ChainProp(name="HLT_tau160_perf_tracktwoMVA_L1TAU100",groups=SingleTauGroup),
 
     ]
+    # TimM temporary disable due to !31039
     TriggerFlags.BphysicsSlice.signatures = TriggerFlags.BphysicsSlice.signatures() + [
-        #ATR 20603
-        ChainProp(name='HLT_2mu4_bJpsimumu_L12MU4',     groups=BphysicsGroup),
-        ChainProp(name='HLT_2mu4_bUpsimumu_L12MU4',     groups=BphysicsGroup),
-        #ATR-20839
-        ChainProp(name='HLT_2mu4_bDimu_L12MU4',     groups=BphysicsGroup),    
+        # #ATR 20603
+        # ChainProp(name='HLT_2mu4_bJpsimumu_L12MU4',     groups=BphysicsGroup),
+        # ChainProp(name='HLT_2mu4_bUpsimumu_L12MU4',     groups=BphysicsGroup),
+        # #ATR-20839
+        # ChainProp(name='HLT_2mu4_bDimu_L12MU4',     groups=BphysicsGroup),    
     ]
     TriggerFlags.CombinedSlice.signatures = TriggerFlags.CombinedSlice.signatures() + [
    ]
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py
index e68b209822c..16c8845094e 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py
@@ -872,13 +872,14 @@ class InViewReco( ComponentAccumulator ):
         self.mainSeq = seqAND( name )
         self.addSequence( self.mainSeq )
 
-        from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+        from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool
         if viewMaker:
             self.viewMakerAlg = viewMaker
         else:
             self.viewMakerAlg = EventViewCreatorAlgorithm("IM"+name,
                                                           ViewFallThrough = True,
-                                                          RoIsLink        = 'initialRoI', # -||-
+                                                          RoIsLink        = 'initialRoI',
+                                                          RoITool         = ViewCreatorInitialROITool(),
                                                           InViewRoIs      = name+'RoIs',
                                                           Views           = name+'Views',
                                                           ViewNodeName    = name+"InView")
@@ -894,7 +895,7 @@ class InViewReco( ComponentAccumulator ):
     def addInput(self, inKey, outKey ):
         """Adds input (DecisionsContainer) from which the views should be created """
         self.viewMakerAlg.InputMakerInputDecisions += [ inKey ]
-        self.viewMakerAlg.InputMakerOutputDecisions += [ outKey ]
+        self.viewMakerAlg.InputMakerOutputDecisions = outKey
 
     def mergeReco( self, ca ):
         """ Merged CA movnig reconstruction algorithms into the right sequence """
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py
index b99541be336..b0b1833308e 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/Physics_pp_run3_v1.py
@@ -102,10 +102,11 @@ def setupMenu():
         #ATR-20049
         ChainProp(name="HLT_tau160_mediumRNN_tracktwoMVA_L1TAU100", groups=SingleTauGroup),
     ]
+    # TimM temporary disable due to !31039
     TriggerFlags.BphysicsSlice.signatures = [
         #ATR-20049
-        ChainProp(name='HLT_2mu10_bJpsimumu_L12MU10',     groups=BphysicsGroup),
-        ChainProp(name='HLT_2mu10_bUpsimumu_L12MU10',     groups=BphysicsGroup),
+        # ChainProp(name='HLT_2mu10_bJpsimumu_L12MU10',     groups=BphysicsGroup),
+        # ChainProp(name='HLT_2mu10_bUpsimumu_L12MU10',     groups=BphysicsGroup),
     ]
     TriggerFlags.CombinedSlice.signatures = [
         ChainProp(name='HLT_e3_etcut1step_mu6fast_L1EM8I_MU10', l1SeedThresholds=['EM8I', 'MU10'], stream=[PhysicsStream], groups=MultiElectronGroup),    #L1 item thresholds in wrong order (EM first, then MU)
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MinBias/MinBiasChainConfiguration.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MinBias/MinBiasChainConfiguration.py
index 68621f9d2e3..91bfb8e08cb 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MinBias/MinBiasChainConfiguration.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/MinBias/MinBiasChainConfiguration.py
@@ -17,7 +17,7 @@ def MinBiasSequenceCfg( flags ):
 
 def MinBiasMenuSequence():
 
-    inputMakerAlg = InputMakerForRoI("IM_minbiasInputMaker", mergeOutputs=False)
+    inputMakerAlg = InputMakerForRoI("IM_minbiasInputMaker")
     inputMakerAlg.RoIs="minbiasInputRoIs"
 
 class MinBiasChainConfig(ChainConfigurationBase):
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py
index 0ef2d6c50e0..155dcc12e10 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py
@@ -24,7 +24,7 @@ muonCombinedRecFlags.doStatisticalCombination = False
 muonCombinedRecFlags.doCombinedFit = True
 muonRecFlags.enableErrorTuning = False
 
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool, ViewCreatorPreviousROITool
 
 #muon container names (for RoI based sequences)
 from TriggerMenuMT.HLTMenuConfig.Muon.MuonSetup import muonNames
@@ -37,8 +37,9 @@ def muFastAlgSequence(ConfigFlags):
     ### set the EVCreator ###
     l2MuViewsMaker = EventViewCreatorAlgorithm("IMl2Mu")
     l2MuViewsMaker.ViewFallThrough = True
-    l2MuViewsMaker.RoIsLink = "initialRoI" # -||-
-    l2MuViewsMaker.InViewRoIs = "MURoIs" # contract with the consumer
+    l2MuViewsMaker.RoIsLink = "initialRoI"
+    l2MuViewsMaker.RoITool = ViewCreatorInitialROITool()
+    l2MuViewsMaker.InViewRoIs = "MURoIs"
     l2MuViewsMaker.Views = "MUViewRoIs"
 
     ### get muFast reco sequence ###    
@@ -102,7 +103,8 @@ def muCombAlgSequence(ConfigFlags):
     ### set the EVCreator ###
     l2muCombViewsMaker = EventViewCreatorAlgorithm("IMl2muComb")
     l2muCombViewsMaker.ViewFallThrough = True #if this needs to access anything from the previous step, from within the view
-    l2muCombViewsMaker.RoIsLink = "roi" # setting to RoI updated L2MuonSA
+    l2muCombViewsMaker.RoIsLink = "roi" # setting to RoI updated L2MuonSA. Used in merging to determin identical Decision objects
+    l2muCombViewsMaker.RoITool = ViewCreatorPreviousROITool() # Use the "roi" link from the previous step when spawning new view
     l2muCombViewsMaker.InViewRoIs = "MUIDRoIs" #name of the RoIS inside of the view, because in principle we can have more than one RoI/view
     l2muCombViewsMaker.Views = "MUCombViewRoIs" #output of the views maker (key in "storegate")
     l2muCombViewsMaker.RequireParentView = True
@@ -117,7 +119,8 @@ def muCombAlgSequence(ConfigFlags):
     muonChainFilter = MuonChainFilterAlg("FilterBphysChains")
     bphysChains =getBphysChainNames()
     muonChainFilter.ChainsToFilter=bphysChains
-    muonChainFilter.InputDecisions = l2muCombViewsMaker.InputMakerOutputDecisions
+    if hasattr(l2muCombViewsMaker, "InputMakerOutputDecisions"):
+        muonChainFilter.InputDecisions = [ l2muCombViewsMaker.InputMakerOutputDecisions ]
     muonChainFilter.L2MuCombContainer = sequenceOut
 
     muCombFilterSequence = seqAND("l2muCombFilterSequence", [muonChainFilter, muCombRecoSequence])
@@ -182,8 +185,9 @@ def muEFSAAlgSequence(ConfigFlags):
 
     efsaViewsMaker = EventViewCreatorAlgorithm("IMefsa")
     efsaViewsMaker.ViewFallThrough = True
-    efsaViewsMaker.RoIsLink = "roi" # -||-
-    efsaViewsMaker.InViewRoIs = "MUEFSARoIs" # contract with the consumer
+    efsaViewsMaker.RoIsLink = "initialRoI" # Note: This is for L1-seeded muons, can use the "initialRoI" for input maker merging
+    efsaViewsMaker.RoITool = ViewCreatorPreviousROITool() # Use "roi" link to spawn views
+    efsaViewsMaker.InViewRoIs = "MUEFSARoIs"
     efsaViewsMaker.Views = "MUEFSAViewRoIs"
     efsaViewsMaker.RequireParentView = True
    
@@ -244,8 +248,9 @@ def muEFCBAlgSequence(ConfigFlags):
     
     efcbViewsMaker = EventViewCreatorAlgorithm("IMefcbtotal")
     efcbViewsMaker.ViewFallThrough = True
-    efcbViewsMaker.RoIsLink = "roi" # -||-
-    efcbViewsMaker.InViewRoIs = "MUEFCBRoIs" # contract with the consumer
+    efcbViewsMaker.RoIsLink = "roi"
+    efcbViewsMaker.RoITool = ViewCreatorPreviousROITool() # Use "roi" link to spawn views
+    efcbViewsMaker.InViewRoIs = "MUEFCBRoIs"
     efcbViewsMaker.Views = "MUEFCBViewRoIs"
     efcbViewsMaker.RequireParentView = True
 
@@ -306,8 +311,9 @@ def muEFCBInvMassSequence():
     
     invMViewsMaker = EventViewCreatorAlgorithm("IMmuinvm")
     invMViewsMaker.ViewFallThrough = True
-    invMViewsMaker.RoIsLink = "initialRoI" # -||-
-    invMViewsMaker.InViewRoIs = "muInvMRoIs" # contract with the consumer
+    invMViewsMaker.RoIsLink = "initialRoI"
+    invMViewsMaker.RoITool = ViewCreatorInitialROITool()
+    invMViewsMaker.InViewRoIs = "muInvMRoIs"
     invMViewsMaker.Views = "muInvMViewRoIs"
     invMViewsMaker.ViewNodeName = invMassRecoSequence.name()
     invMViewsMaker.RequireParentView = True
@@ -336,6 +342,7 @@ def muEFSAFSAlgSequence(ConfigFlags):
     from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithmWithMuons
     efsafsInputMaker = EventViewCreatorAlgorithmWithMuons("IMMuonFS", RoIsLink="initialRoI")
     efsafsInputMaker.InViewRoIs = "MUFSRoIs"
+    efsafsInputMaker.RoITool = ViewCreatorInitialROITool() # NOT USED! TO BE REPLACED WITH NEW TOOL ON CONVERTING EventViewCreatorAlgorithmWithMuons -> EventViewCreatorAlgorithm
     efsafsInputMaker.Views = "MUFSViewRoI"
     efsafsInputMaker.ViewFallThrough=True
     efsafsInputMaker.CreateFSRoI=True
@@ -376,10 +383,11 @@ def muEFCBFSAlgSequence(ConfigFlags):
     from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithmWithMuons
     efcbfsInputMaker = EventViewCreatorAlgorithmWithMuons("IMEFCBFS") 
     efcbfsInputMaker.ViewFallThrough = True
-    efcbfsInputMaker.mergeOutputs = False
+    efcbfsInputMaker.mergeUsingFeature = True
     efcbfsInputMaker.Views = "MUCBFSViews"
     efcbfsInputMaker.InViewRoIs = "MUCBFSRoIs"
     efcbfsInputMaker.RoIsLink = "initialRoI"
+    efcbfsInputMaker.RoITool = ViewCreatorInitialROITool() # NOT USED! TO BE REPLACED WITH NEW TOOL ON CONVERTING EventViewCreatorAlgorithmWithMuons -> EventViewCreatorAlgorithm
     efcbfsInputMaker.InViewMuons = "InViewMuons"
     efcbfsInputMaker.MuonsLink = "feature"
     efcbfsInputMaker.RequireParentView = True
@@ -417,8 +425,9 @@ def efLateMuRoIAlgSequence(ConfigFlags):
     
     eflateViewsMaker = EventViewCreatorAlgorithm("IMeflatemuroi")
     eflateViewsMaker.ViewFallThrough = True
-    eflateViewsMaker.RoIsLink = "initialRoI" # -||-
-    eflateViewsMaker.InViewRoIs = "MULATERoIs" # contract with the consumer
+    eflateViewsMaker.RoIsLink = "initialRoI"
+    eflateViewsMaker.RoITool = ViewCreatorInitialROITool()
+    eflateViewsMaker.InViewRoIs = "MULATERoIs"
     eflateViewsMaker.Views = "MULATEViewRoIs"
 
 
@@ -454,8 +463,9 @@ def efLateMuAlgSequence(ConfigFlags):
     from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithmWithMuons
     eflateViewsMaker = EventViewCreatorAlgorithmWithMuons("IMeflatemu")
     eflateViewsMaker.ViewFallThrough = True
-    eflateViewsMaker.RoIsLink = "initialRoI" # -||-
-    eflateViewsMaker.InViewRoIs = "MUEFLATERoIs" # contract with the consumer
+    eflateViewsMaker.RoIsLink = "initialRoI"
+    eflateViewsMaker.InViewRoIs = "MUEFLATERoIs"
+    eflateViewsMaker.RoITool = ViewCreatorInitialROITool() # NOT USED! TO BE REPLACED WITH NEW TOOL ON CONVERTING EventViewCreatorAlgorithmWithMuons -> EventViewCreatorAlgorithm
     eflateViewsMaker.Views = "MUEFLATEViewRoIs"
     eflateViewsMaker.DoLateMu = True
     eflateViewsMaker.LateRoIsLink = "feature"
@@ -501,8 +511,9 @@ def muIsoAlgSequence(ConfigFlags):
 
     l2muIsoViewsMaker = EventViewCreatorAlgorithm("IMl2muIso")
     l2muIsoViewsMaker.ViewFallThrough = True
-    l2muIsoViewsMaker.RoIsLink = "initialRoI" # -||-
-    l2muIsoViewsMaker.InViewRoIs = "MUIsoRoIs" # contract with the consumer
+    l2muIsoViewsMaker.RoIsLink = "initialRoI"
+    l2muIsoViewsMaker.RoITool = ViewCreatorInitialROITool()
+    l2muIsoViewsMaker.InViewRoIs = "MUIsoRoIs"
     l2muIsoViewsMaker.Views = "MUIsoViewRoIs"
     l2muIsoViewsMaker.RequireParentView = True
 
@@ -542,14 +553,15 @@ def muEFIsoAlgSequence(ConfigFlags):
     from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithmWithMuons
     efmuIsoViewsMaker = EventViewCreatorAlgorithmWithMuons("IMefmuIso")
     efmuIsoViewsMaker.ViewFallThrough = True
-    efmuIsoViewsMaker.RoIsLink = "initialRoI" # -||-
-    efmuIsoViewsMaker.InViewRoIs = "MUEFIsoRoIs" # contract with the consumer
+    efmuIsoViewsMaker.RoIsLink = "initialRoI"
+    efmuIsoViewsMaker.RoITool = ViewCreatorInitialROITool() # NOT USED! TO BE REPLACED WITH NEW TOOL ON CONVERTING EventViewCreatorAlgorithmWithMuons -> EventViewCreatorAlgorithm
+    efmuIsoViewsMaker.InViewRoIs = "MUEFIsoRoIs"
     efmuIsoViewsMaker.Views = "MUEFIsoViewRoIs"
     efmuIsoViewsMaker.InViewMuons = "IsoViewMuons"
     efmuIsoViewsMaker.MuonsLink = "feature"
     efmuIsoViewsMaker.RoIEtaWidth=0.15
     efmuIsoViewsMaker.RoIPhiWidth=0.15
-    efmuIsoViewsMaker.mergeOutputs = False
+    efmuIsoViewsMaker.mergeUsingFeature = True
     efmuIsoViewsMaker.RoisWriteHandleKey = "IsoMuRoIs"
     efmuIsoViewsMaker.InViewMuonCandidates = "IsoMuonCandidates"
 
diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Tau/TauRecoSequences.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Tau/TauRecoSequences.py
index 9dfcf702fac..fb1e6c239bb 100644
--- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Tau/TauRecoSequences.py
+++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Tau/TauRecoSequences.py
@@ -3,7 +3,7 @@
 #
 
 from AthenaCommon.CFElements import parOR, seqAND
-from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm
+from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithm, ViewCreatorInitialROITool, ViewCreatorPreviousROITool
 from TrigT2CaloCommon.CaloDef import HLTLCTopoRecoSequence
 from TrigEDMConfig.TriggerEDMRun3 import recordable
 from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import RecoFragmentsPool
@@ -130,6 +130,7 @@ def tauCaloSequence(ConfigFlags):
     tauCaloViewsMaker                    = EventViewCreatorAlgorithm( "IMtauCalo")
     tauCaloViewsMaker.ViewFallThrough    = True
     tauCaloViewsMaker.RoIsLink           = "initialRoI"
+    tauCaloViewsMaker.RoITool            = ViewCreatorInitialROITool()
     tauCaloViewsMaker.InViewRoIs         = InViewRoIs
     tauCaloViewsMaker.Views              = "TAUCaloViews"
     tauCaloViewsMaker.ViewNodeName       = RecoSequenceName
@@ -147,6 +148,7 @@ def tauCaloMVASequence(ConfigFlags):
     tauCaloMVAViewsMaker                    = EventViewCreatorAlgorithm( "IMtauCaloMVA")
     tauCaloMVAViewsMaker.ViewFallThrough    = True
     tauCaloMVAViewsMaker.RoIsLink           = "initialRoI"
+    tauCaloMVAViewsMaker.RoITool            = ViewCreatorInitialROITool()
     tauCaloMVAViewsMaker.InViewRoIs         = InViewRoIs
     tauCaloMVAViewsMaker.Views              = "TAUCaloMVAViews"
     tauCaloMVAViewsMaker.ViewNodeName       = RecoSequenceName
@@ -291,7 +293,8 @@ def tauFTFTrackTwoSequence(ConfigFlags):
     RecoSequenceName = "tauFTFTrackTwoInViewSequence"
 
     ftfTrackTwoViewsMaker                   = EventViewCreatorAlgorithm("IMFTFTrackTwo")
-    ftfTrackTwoViewsMaker.RoIsLink          = "roi" # -||-
+    ftfTrackTwoViewsMaker.RoIsLink          = "roi"
+    ftfTrackTwoViewsMaker.RoITool           = ViewCreatorPreviousROITool()
     ftfTrackTwoViewsMaker.InViewRoIs        = "TIsoViewRoIs" # contract with the fast track core
     ftfTrackTwoViewsMaker.Views             = "TAUFTFTrackTwoViews"
     ftfTrackTwoViewsMaker.ViewFallThrough   = True
@@ -308,7 +311,8 @@ def tauFTFTrackSequence(ConfigFlags):
     RecoSequenceName = "tauFTFTrackInViewSequence"
 
     ftfTrackViewsMaker                   = EventViewCreatorAlgorithm("IMFTFTrack")
-    ftfTrackViewsMaker.RoIsLink          = "roi" # -||-                                                                          
+    ftfTrackViewsMaker.RoIsLink          = "roi"
+    ftfTrackViewsMaker.RoITool           = ViewCreatorPreviousROITool()
     ftfTrackViewsMaker.InViewRoIs        = "TIdViewRoIs" # contract with the fast track core                                     
     ftfTrackViewsMaker.Views             = "TAUFTFTrackViews"
     ftfTrackViewsMaker.ViewFallThrough   = True
@@ -325,7 +329,8 @@ def tauFTFIdSequence(ConfigFlags):
     RecoSequenceName = "tauFTFIdInViewSequence"
 
     ftfIdViewsMaker                   = EventViewCreatorAlgorithm("IMFTFId")
-    ftfIdViewsMaker.RoIsLink          = "roi" # -||-                                                                                          
+    ftfIdViewsMaker.RoIsLink          = "roi"
+    ftfIdViewsMaker.RoITool           = ViewCreatorPreviousROITool()
     ftfIdViewsMaker.InViewRoIs        = "TIdViewRoIs" # contract with the fast track core                                                    
     ftfIdViewsMaker.Views             = "TAUFTFIdViews"
     ftfIdViewsMaker.ViewFallThrough   = True
@@ -342,8 +347,9 @@ def tauFTFCoreSequence(ConfigFlags):
     RecoSequenceName = "tauFTFCoreInViewSequence"
 
     ftfCoreViewsMaker                   = EventViewCreatorAlgorithm("IMFTFCore")
-    ftfCoreViewsMaker.RoIsLink          = "roi" # -||-
+    ftfCoreViewsMaker.RoIsLink          = "roi"
     ftfCoreViewsMaker.InViewRoIs        = "TCoreViewRoIs" # contract with the fastCalo
+    ftfCoreViewsMaker.RoITool           = ViewCreatorPreviousROITool()
     ftfCoreViewsMaker.Views             = "TAUFTFCoreViews"
     ftfCoreViewsMaker.ViewFallThrough   = True
     ftfCoreViewsMaker.RequireParentView = True
@@ -359,7 +365,8 @@ def tauFTFIsoSequence(ConfigFlags):
     RecoSequenceName = "tauFTFIsoInViewSequence"
 
     ftfIsoViewsMaker                   = EventViewCreatorAlgorithm("IMFTFIso")
-    ftfIsoViewsMaker.RoIsLink          = "roi" # -||-                                                                            
+    ftfIsoViewsMaker.RoIsLink          = "roi"
+    ftfIsoViewsMaker.RoITool           = ViewCreatorPreviousROITool()
     ftfIsoViewsMaker.InViewRoIs        = "TIsoViewRoIs" # contract with the fast track core
     ftfIsoViewsMaker.Views             = "TAUFTFIsoViews"
     ftfIsoViewsMaker.ViewFallThrough   = True
@@ -376,7 +383,8 @@ def tauEFSequence(ConfigFlags):
     RecoSequenceName = "tauEFInViewSequence"
 
     efViewsMaker                   = EventViewCreatorAlgorithm("IMTauEF")
-    efViewsMaker.RoIsLink          = "roi" # -||-                                                                                                         
+    efViewsMaker.RoIsLink          = "roi"  
+    efViewsMaker.RoITool           = ViewCreatorPreviousROITool()
     efViewsMaker.InViewRoIs        = "TIsoViewRoIs" # contract with the fast track core                                                                   
     efViewsMaker.Views             = "TAUEFViews"
     efViewsMaker.ViewFallThrough   = True
-- 
GitLab