diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx
index b76a04d1788087882d799b0391eac5df3c957d97..3be67843f23e973cc7a8d573cbd055fb88ee9edb 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx
@@ -76,7 +76,9 @@ StatusCode TrigMufastHypoAlg::execute( const EventContext& context ) const
   size_t counter=0;
   for ( auto previousDecision: *previousDecisionsHandle ) {
     //get RoI
-    auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+    auto roiInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( previousDecision, "initialRoI"  );
+    auto roiEL = roiInfo.link;
+    //    auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
     ATH_CHECK( roiEL.isValid() );
     const TrigRoiDescriptor* roi = *roiEL;
 
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx
index 6deee0ce7584e916bfe5dce1896bae4c39b9e1ad..d05c606b61d62826d7f189d13002ecbb92b6abb7 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx
@@ -77,7 +77,9 @@ StatusCode TrigMuonEFCombinerHypoAlg::execute( const EventContext& context ) con
   // loop over previous decisions
   for ( auto previousDecision: *previousDecisionsHandle ) {
      // get RoIs
-    auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+    auto roiInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( previousDecision, "initialRoI"  );
+    auto roiEL = roiInfo.link;
+    //    auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
     ATH_CHECK( roiEL.isValid() );
     const TrigRoiDescriptor* roi = *roiEL;
 
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx
index c301fbfa3f472c3d63d8eb17ddd917bf0f36dcb4..1c9ddf33e41a1cb11d6de4d081ecb50774036f72 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx
@@ -77,7 +77,9 @@ StatusCode TrigMuonEFMSonlyHypoAlg::execute( const EventContext& context ) const
   // loop over previous decisions
   for ( auto previousDecision: *previousDecisionsHandle ) {
      // get RoIs
-    auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+    auto roiInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( previousDecision, "initialRoI"  );
+    auto roiEL = roiInfo.link;
+    //auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
     ATH_CHECK( roiEL.isValid() );
     const TrigRoiDescriptor* roi = *roiEL;
 
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx
index f3826e60d652084cbd3da065d67563566e1bdb14..d4c867e04959f83367392632a45a6c11de61217a 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx
@@ -73,7 +73,9 @@ StatusCode TrigMuonEFTrackIsolationHypoAlg::execute( const EventContext& context
   size_t counter = 0;
   for ( auto previousDecision: *previousDecisionsHandle ) {
     // get RoIs
-    auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>("roi");
+    auto roiInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( previousDecision, "initialRoI"  );
+    auto roiEL = roiInfo.link;
+    //    auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>("roi");
     ATH_CHECK( roiEL.isValid() );
     const TrigRoiDescriptor *roi = *roiEL;
 
diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h
index 7c5ce693f4f061d0005e5f68cc32201194d7d26a..10d56a39c905e6f62cdd9cf5dd687950d68b8466 100644
--- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h
+++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/InputMakerBase.h
@@ -10,6 +10,7 @@
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
 #include "StoreGate/ReadHandleKeyArray.h"
 
+
 class InputMakerBase : public ::AthReentrantAlgorithm {
   /**
    * @class InputMakerBase
@@ -26,22 +27,45 @@ This is a base class for HLT InputMakers to reduce boilerplate and enforce the c
   /// execute to be implemented in derived clas
   virtual StatusCode execute(const EventContext&) const override = 0;
   virtual StatusCode finalize() override = 0;
-  virtual StatusCode initialize() override = 0;  
+  virtual StatusCode initialize() override = 0;
+  
  protected:
   /// 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::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;
-  // helper methods for derived classes to reduce boiler plate code
+
+  // name of link to the RoI
+  StringProperty m_roisLink { this, "RoIsLink", "initialRoI", "Name of EL to RoI object linked to the decision" };
+  
+  // helper methods for derived classes to reduce boiler plate code  //
+  /////////////////////////////////////////////////////////////////////
+  
   /// provides debug printout of the output of the algorithm
   StatusCode 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, return outputHandles
+
+   /// 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;
+
+  /// 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;
+
+  /// counts valid input decisions
+  size_t countInputHandles( const EventContext& context ) const;
+  
  private:
+  
   /// input decisions, 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" };
+
+  // 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" };
+  
+  
 };
 
 
diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h
index c78f3be5a1193b14b2f8f79edd2ea02f7d56ee58..f72f8f21b16729e9981b021606b7afc0a7101ac9 100644
--- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h
+++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h
@@ -87,6 +87,20 @@ Decision* newDecisionIn( DecisionContainer* dc, const Decision* dOld, const std:
    **/
   void addDecisionID( DecisionID id,  Decision* d);
 
+ /**
+   * @brief Appends the decision IDs of src to the dest decision object
+   * @warning Performing merging of IDs and solving the duples (via set)
+   * This helps when making copies of Decision obejcts
+   **/
+  void insertDecisionIDs( const Decision* src, Decision* dest );
+
+ /**
+   * @brief Make unique list of decision IDs of dest Decision object
+   * @warning Use vector->set->vector
+   * This helps solving multiple inserts of the Decision obejcts
+   **/
+  void uniqueDecisionIDs( Decision* dest);
+
       
   /**
    * @brief Extracts DecisionIDs stored in the Decision object 
@@ -133,7 +147,7 @@ Decision* newDecisionIn( DecisionContainer* dc, const Decision* dOld, const std:
   /**
    * @brief returns link to previous decision object
    **/
-  ElementLink<DecisionContainer> linkToPrevious(const Decision*);
+  ElementLinkVector<DecisionContainer> getLinkToPrevious(const Decision*);
 
   /**
    * @brief copy all links from src to dest TC objects
@@ -141,8 +155,8 @@ Decision* newDecisionIn( DecisionContainer* dc, const Decision* dOld, const std:
    * @ret true if success
    **/
   bool copyLinks(const Decision* src, Decision* dest);
-  
- /**
+
+  /**
    * @brief traverses TC links for another TC fufilling the prerequisite specified by the filter
    * @return matching TC or nullptr
    **/
@@ -196,8 +210,8 @@ Decision* newDecisionIn( DecisionContainer* dc, const Decision* dOld, const std:
   };
 
   /**
-   * @brief search back the TC links for the object of type T linked to the one of TC
-   * @arg start the TC where from where the link back is to be looked for
+   * @brief search back the TC links for the object of type T linked to the one of TC (recursively)
+   * @arg start the TC  from where the link back is to be looked for
    * @arg linkName the name with which the Link was added to the source TC
    * @return pair of link and TC with which it was associated, 
    */
@@ -205,8 +219,21 @@ Decision* newDecisionIn( DecisionContainer* dc, const Decision* dOld, const std:
   LinkInfo<T>
   findLink(const xAOD::TrigComposite* start, const std::string& linkName) {
     auto source = find(start, HasObject(linkName) );
-    if ( not source )
+    //
+    if ( not source ){
+      auto seeds = getLinkToPrevious(start);
+      // std::cout<<"Looking for seeds: found " <<seeds.size()<<std::endl;
+      for (auto seed: seeds){
+	const xAOD::TrigComposite* dec = *seed;//deference
+	LinkInfo<T> link= findLink<T>( dec, linkName );
+	// return the first found
+	if (link.isValid()) return link;
+      }
       return LinkInfo<T>(); // invalid link
+    }
+
+    //std::cout<<"Found source for "<<linkName<<std::endl;
+
     return LinkInfo<T>( source, source->objectLink<T>( linkName ) );
   }
 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
index 3627d105deada3a356aaa43b695f2e4b4adf65a8..02488db94d84359d669f5d1ac3bc075fe5ea2606 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
@@ -87,28 +87,17 @@ StatusCode ComboHypo::copyDecisions( const DecisionIDContainer& passing, const E
 	std::set_intersection( inputDecisionIDs.begin(), inputDecisionIDs.end(), passing.begin(), passing.end(),
 			       std::inserter( common, common.end() ) );
 	
+
 	Decision*  newDec = newDecisionIn( outDecisions );
-	linkToPrevious( newDec, inputHandle.key(), i );      
+	linkToPrevious( newDec, inputHandle.key(), i );
+	ATH_MSG_DEBUG("New decision has "<< (TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( newDec, "initialRoI")).isValid()
+		      <<" valid initialRoI and "<< TrigCompositeUtils::getLinkToPrevious(newDec).size() <<" previous decisions");   
+
 	for ( auto id: common ) {
 	  addDecisionID( id, newDec );
 	}
-	// add RoI: at least one RoI link must exist
-	if ( inputDecision->hasObjectLink("roi" ) ){
-	  auto roiEL = inputDecision->objectLink<TrigRoiDescriptorCollection>( "roi" );
-	  CHECK( roiEL.isValid() );
-	  newDec->setObjectLink( "roi", roiEL );
-	}
-	else if ( inputDecision->hasObjectLink("initialRoI" ) ){
-	  auto roiEL = inputDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
-	  CHECK( roiEL.isValid() );
-	  newDec->setObjectLink( "initialRoI", roiEL );
-	}
-	else {
-	  ATH_MSG_ERROR( "Input decision " << i <<" from "<<inputHandle.key() <<" does not link any RoI");
-	  return StatusCode::FAILURE;
-	}
 	
-	// add View
+	// add View?
 	if ( inputDecision->hasObjectLink( "view" ) ) {
 	   auto viewEL = inputDecision->objectLink< ViewContainer >( "view" );
 	   CHECK( viewEL.isValid() );
diff --git a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
index c36fc5a9658909c4cb83558d9ba34a81720a913d..34e8daff94ef8b8512f7772a1db49870f88b440e 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
@@ -6,6 +6,9 @@
 #include "DecisionHandling/HLTIdentifier.h"
 #include "TrigSteeringEvent/TrigRoiDescriptorCollection.h"
 
+using namespace TrigCompositeUtils;
+
+
 InputMakerBase::InputMakerBase( const std::string& name, ISvcLocator* pSvcLocator )
   : ::AthReentrantAlgorithm( name, pSvcLocator ) {}
 
@@ -21,6 +24,7 @@ const SG::WriteHandleKeyArray<TrigCompositeUtils::DecisionContainer>& InputMaker
 
 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:" );
@@ -36,22 +40,14 @@ StatusCode InputMakerBase::sysInitialize() {
 }
 
 
+// For each input Decision in the input container, create an output Decision in the corresponding output container and link them.
 StatusCode InputMakerBase::decisionInputToOutput(const EventContext& context, std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> > & outputHandles) const{
 
-  outputHandles = decisionOutputs().makeHandles(context);
+  if (!m_mergeOutputs)   ATH_MSG_DEBUG("Creating one output per input");
+  else                   ATH_MSG_DEBUG("Creating one merged output per RoI");
 
-  // check inputs
-  size_t validInput=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()) validInput++;
-  }
-  ATH_MSG_DEBUG( "number of implicit ReadHandles is " << decisionInputs().size() <<", "<< validInput<<" are valid" );
-  
-  // Input is array of input decision containers
-  // Loop over them. For each input decision container, create an output decision container
-  // For each input Decision in the input container, create and output Decision in the corresponding output container and link them.
+  outputHandles = decisionOutputs().makeHandles(context);
+  //size_t tot_inputs = countInputHandles( context );
   size_t outputIndex = 0;
   for ( auto inputKey: decisionInputs() ) {
     auto inputHandle = SG::makeHandle( inputKey, context );
@@ -65,34 +61,62 @@ StatusCode InputMakerBase::decisionInputToOutput(const EventContext& context, st
       outputIndex++;
       continue;
     }
-    ATH_MSG_DEBUG( "Got input "<< inputKey.key()<<" with " << inputHandle->size() << " elements" );
+    ATH_MSG_DEBUG( "Running on input "<< inputKey.key()<<" with " << inputHandle->size() << " elements" );
+    
     // create the output container
     TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
     auto outDecisions = outputHandles[outputIndex].ptr();
 
-    // loop over input decisions retrieved from this input handle
+    //map all RoIs that are stored in this input container
+    std::vector <ElementLink<TrigRoiDescriptorCollection> > RoIsFromDecision;
+       
+    // loop over decisions retrieved from this input
     size_t input_counter =0;
-    for ( auto inpDecision : *inputHandle){
-      // create new decision for each input	
-      TrigCompositeUtils::Decision*  newDec = TrigCompositeUtils::newDecisionIn( outDecisions, inpDecision, "", context );
-      {
-        //copy decisions ID
-        TrigCompositeUtils::DecisionIDContainer objDecisions;      
-        TrigCompositeUtils::decisionIDs( inpDecision, objDecisions );
-        for ( const HLT::Identifier& id: objDecisions ){
-          TrigCompositeUtils::addDecisionID( id, newDec );
-        }
+    size_t output_counter =0;
+   
+    for ( auto decision : *inputHandle){
+      ATH_MSG_DEBUG( "Input Decision "<<input_counter <<" has " <<TrigCompositeUtils::getLinkToPrevious(decision).size()<<" previous links");
+      TrigCompositeUtils::Decision*  newDec;
+      bool addDecision=false;
+      int roi_counter=0;
+      if (m_mergeOutputs){
+	auto roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( decision,  m_roisLink.value());
+	CHECK( roiELInfo.isValid() );      
+	auto roiEL = roiELInfo.link;
+	auto roiIt=find(RoIsFromDecision.begin(), RoIsFromDecision.end(), roiEL);
+	addDecision = (roiIt == RoIsFromDecision.end());
+	if (addDecision) {
+	  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());
+	  roi_counter = roiIt-RoIsFromDecision.begin();
+	}
+      } else
+	addDecision=true;
+
+      if ( addDecision ){
+	newDec = TrigCompositeUtils::newDecisionIn( outDecisions );
+	output_counter++;
+      }
+      else{
+	newDec = outDecisions[outputIndex][roi_counter];
       }
+      
+      TrigCompositeUtils::linkToPrevious( newDec, inputKey.key(), input_counter );
+      TrigCompositeUtils::insertDecisionIDs( decision, newDec );     	
+      ATH_MSG_DEBUG("New decision has "<< (TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( newDec,  m_roisLink.value())).isValid() <<" valid "<<m_roisLink.value() <<" and "<< TrigCompositeUtils::getLinkToPrevious(newDec).size() <<" previous decisions");     
       input_counter++;	
     } // loop over input decisions
 
-    ATH_MSG_DEBUG( "Recorded output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<<outDecisions->size()  <<" at index "<< outputIndex);
+    ATH_MSG_DEBUG( "Filled output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<<outDecisions->size()  <<" at index "<< outputIndex);
     outputIndex++;	       
   } // end of first loop over input keys
 
   return StatusCode::SUCCESS;
 }
 
+
+
 StatusCode InputMakerBase::debugPrintOut(const EventContext& context, const std::vector< SG::WriteHandle<TrigCompositeUtils::DecisionContainer> >& outputHandles) const{
   size_t validInput=0;
   for ( auto inputKey: decisionInputs() ) {
@@ -125,3 +149,20 @@ StatusCode InputMakerBase::debugPrintOut(const EventContext& context, const std:
   }
   return StatusCode::SUCCESS;
 }
+
+
+
+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 b116703641bbbc165852500111ca7c3dbae898b0..2b4e32176d6405021bef99ebc593558704812158 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.cxx
@@ -57,24 +57,27 @@ StatusCode  InputMakerForRoI::execute( const EventContext& context ) const {
     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){ 
-      ElementLink<DecisionContainer> inputLink = linkToPrevious(outputDecision);
-      const Decision* inputDecision = *inputLink;
-      auto roiEL = inputDecision->objectLink<TrigRoiDescriptorCollection>(m_linkName.value() ); //"initialRoI" 
-      ATH_CHECK( roiEL.isValid() );
+      ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
+      for (auto input: inputLinks){
+	const Decision* inputDecision = *input;
+	auto roiELInfo = TrigCompositeUtils::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());
-      }            
+	// 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 input keys
+  } // loop over output keys
   
   
     // Finally, record output
@@ -83,7 +86,7 @@ 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.
-  CHECK( debugPrintOut(context, outputHandles) );
+  ATH_CHECK( debugPrintOut(context, outputHandles) );
   
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h b/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h
index 0f015a07614229406e243ff30bbbfbd95ad724fd..a18bd505d6e84892d40e28b51cbc85a511252cd2 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerForRoI.h
@@ -30,14 +30,9 @@
   private: 
      InputMakerForRoI();
  
-    // Use this to customise the example for a different input feature
-    typedef TrigRoiDescriptor FeatureOBJ;
-    typedef TrigRoiDescriptorCollection FeatureContainer;
-
     SG::WriteHandleKey<TrigRoiDescriptorCollection> m_RoIs {this,"RoIs", "Unspecified", "Nam eof the RoIs extracted from the decisions"};
-
-    StringProperty m_linkName   {this, "LinkName", "initialRoI",  "name of the link to the features in the decision, e.g. 'feature', 'initialRoI'"};
-
+    // want to try also const?
+    //SG::WriteHandleKey< ConstDataVector<TrigRoiDescriptorCollection> > m_RoIs{ this, "RoIs", "Unspecified", "Name of the RoIs extracted from the decisions" };
 
   }; 
 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx
index 2fd9a93e8dac98bc85cb80fc0a60e0289e5ac5ad..cfffdd294b14595d45e7f00c80736dc1f0d70dea 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx
@@ -89,6 +89,21 @@ namespace TrigCompositeUtils {
     return readWriteAccessor( *d );
   }
 
+  void insertDecisionIDs( const Decision* src, Decision* dest ){
+    DecisionIDContainer ids;
+    decisionIDs( src, ids );
+    decisionIDs( dest, ids );
+    decisionIDs( dest ).clear(); 
+    decisionIDs( dest ).insert( decisionIDs(dest).end(), ids.begin(), ids.end() );
+  }
+
+  void uniqueDecisionIDs( Decision* dest){
+    DecisionIDContainer ids;
+    decisionIDs( dest, ids );
+    decisionIDs( dest ).clear(); 
+    decisionIDs( dest ).insert( decisionIDs(dest).end(), ids.begin(), ids.end() );
+  }
+
   bool allFailed( const Decision* d ) {
     const std::vector<int>& decisions = readOnlyAccessor( *d );    
     return decisions.empty();
@@ -107,15 +122,30 @@ namespace TrigCompositeUtils {
   }
 
   void linkToPrevious( Decision* d, const std::string& previousCollectionKey, size_t previousIndex ) {
-    d->setObjectLink( "seed", ElementLink<DecisionContainer>( previousCollectionKey, previousIndex ) );
+    ElementLinkVector<DecisionContainer> seeds;
+    ElementLink<DecisionContainer> new_seed= ElementLink<DecisionContainer>( previousCollectionKey, previousIndex );
+    // do we need this link to self link?
+    if ( (*new_seed)->hasObjectLink("self" ) )
+      seeds.push_back( (*new_seed)->objectLink<DecisionContainer>("self")); // make use of self-link 
+    else
+      seeds.push_back(ElementLink<DecisionContainer>( previousCollectionKey, previousIndex ));
+    
+    if (hasLinkToPrevious(d) ){
+      ElementLinkVector<DecisionContainer> oldseeds = d->objectCollectionLinks<DecisionContainer>( "seed" );
+      seeds.reserve( seeds.size() + oldseeds.size() );
+      std::move( oldseeds.begin(), oldseeds.end(), std::back_inserter( seeds ) );
+    }
+
+    d->addObjectCollectionLinks("seed", seeds);
+    
   }
 
   bool hasLinkToPrevious( const Decision* d ) {
     return d->hasObjectLink( "seed" );
   }
 
-  ElementLink<DecisionContainer> linkToPrevious( const Decision* d ) {
-    return d->objectLink<DecisionContainer>( "seed" );
+  ElementLinkVector <DecisionContainer> getLinkToPrevious( const Decision* d ) {
+    return d->objectCollectionLinks<DecisionContainer>( "seed" );
   }
 
 
@@ -123,7 +153,8 @@ namespace TrigCompositeUtils {
     return dest->copyAllLinksFrom(src);
   }
 
-
+ 
+  
   const xAOD::TrigComposite* find( const xAOD::TrigComposite* start, const std::function<bool( const xAOD::TrigComposite* )>& filter ) {
     if ( filter( start ) ) return start;
 
diff --git a/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx b/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx
index 9ea3c5c422ca01dd2cc39d00d4720b2c8bab976f..0fc1f102fedf8da4bbbc872bdc5d19084272e3b6 100644
--- a/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx
@@ -105,14 +105,9 @@ StatusCode JRoIsUnpackingTool::unpack( const EventContext& ctx,
 
     }     
   }
-  TrigCompositeUtils::DecisionIDContainer uniqueDecisions; // this is set
-  std::vector<int>& storedIDs = TrigCompositeUtils::decisionIDs( decision );
-  TrigCompositeUtils::decisionIDs( decision, uniqueDecisions ); // copy to set -> unique
-  storedIDs.clear();
-  storedIDs.insert( storedIDs.end(), uniqueDecisions.begin(), uniqueDecisions.end() );
-  //copy back
-  
 
+  TrigCompositeUtils::uniqueDecisionIDs( decision);
+ 
 
   if ( msgLvl(MSG::DEBUG) ) {
     for ( auto roi: *trigRoIs ) {
diff --git a/Trigger/TrigSteer/L1Decoder/test/test_l1decoder.sh b/Trigger/TrigSteer/L1Decoder/test/test_l1decoder.sh
index bad6514e2009c2c7e2b28a8a3dd511316b84bc48..0baa8ad104982b6409cbfc9f2cf58c69a94d3124 100755
--- a/Trigger/TrigSteer/L1Decoder/test/test_l1decoder.sh
+++ b/Trigger/TrigSteer/L1Decoder/test/test_l1decoder.sh
@@ -1,5 +1,6 @@
 #!/bin/sh
 # art-type: build
 # art-ci: master
+# art-include: master/Athena
 
 athena --threads=1 --skipEvents=5 --evtMax=20 --filesInput="/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigP1Test/data17_13TeV.00327265.physics_EnhancedBias.merge.RAW._lb0100._SFO-1._0001.1" L1Decoder/testL1Decoder.py
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
index 6b9f57f656147e8895f6f02394f7c8299b4b715a..e4c97ab6141cfc20d83d6abfd31af51f17683308 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
@@ -9,8 +9,8 @@
 #include "AthViews/ViewHelper.h"
 #include "AthViews/View.h"
 #include "DecisionHandling/TrigCompositeUtils.h"
-#include "DecisionHandling/HLTIdentifier.h"
 
+using namespace TrigCompositeUtils;
 
 EventViewCreatorAlgorithm::EventViewCreatorAlgorithm( const std::string& name, ISvcLocator* pSvcLocator )
   : InputMakerBase( name, pSvcLocator ) {}
@@ -25,99 +25,83 @@ StatusCode EventViewCreatorAlgorithm::initialize() {
   return StatusCode::SUCCESS;
 }
 
-StatusCode EventViewCreatorAlgorithm::execute( const EventContext& context ) const { 
-  auto outputHandles = decisionOutputs().makeHandles( context );     
-  // make and store the views
+
+StatusCode EventViewCreatorAlgorithm::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));
+ 
+  // make the views
   auto viewsHandle = SG::makeHandle( m_viewsKey ); 
   auto viewVector1 = std::make_unique< ViewContainer >();
   ATH_CHECK( viewsHandle.record(  std::move( viewVector1 ) ) );
   auto viewVector = viewsHandle.ptr();
-  
+
+
+
+    // auto viewVector = std::make_unique< ViewContainer >();
   auto contexts = std::vector<EventContext>( );
   unsigned int viewCounter = 0;
   unsigned int conditionsRun = context.getExtension<Atlas::ExtendedEventContext>().conditionsRun();
 
-  //  const TrigRoiDescriptor* previousRoI = 0;
-  // mapping RoI with index of the View in the vector
-  // This is used to link the same view to differnt decisions that come from the same RoI
-  std::map <const TrigRoiDescriptor*, int> viewMap;
-  std::map <const TrigRoiDescriptor*, int>::iterator itViewMap;
-  int outputIndex = -1;
- // Loop over all input containers, which are of course TrigComposites, and request their features
-  // this is the same as InputMaker, apart from the view creation. The loop can be splitted in two loops, to have one common part
-  for ( auto inputKey: decisionInputs() ) {
-    outputIndex++;
-    auto inputHandle = SG::makeHandle( inputKey, context );
-    if( not inputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from input " << inputKey.key() );
-      continue;
-    }
-    if( inputHandle->size() == 0 ) { // input filtered out
-      ATH_MSG_DEBUG( "Got no decisions from input " << inputKey.key() );
+  //map all RoIs that are stored
+  std::vector <ElementLink<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;
     }
-    ATH_MSG_DEBUG( "Got input " << inputKey.key() << " with " << inputHandle->size() << " elements" );
-    
-     // prepare output decisions
-    TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
-    TrigCompositeUtils::DecisionContainer* outputDecisions = outputHandles[outputIndex].ptr();
-
-    const TrigRoiDescriptor* prevRoIDescriptor = nullptr;
-    int inputCounter = -1;
-    for ( auto inputDecision: *inputHandle ) {
-      inputCounter++;      
-      // pull RoI descriptor
-      TrigCompositeUtils::LinkInfo<TrigRoiDescriptorCollection> roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>(inputDecision, m_roisLink );
-      ATH_CHECK( roiELInfo.isValid() );
-      // associate this RoI to output decisions
-      auto roiDescriptor = *roiELInfo.link;
-      ATH_MSG_DEBUG( "Placing TrigRoiDescriptor " << *roiDescriptor );
-
-      TrigCompositeUtils::Decision* newDecision = nullptr;      
-      if ( prevRoIDescriptor != roiDescriptor ) {
-	//make one TC decision output per input and connect to previous
-	newDecision = TrigCompositeUtils::newDecisionIn( outputDecisions, name() );
-	TrigCompositeUtils::linkToPrevious( newDecision, inputKey.key(), inputCounter );
-	insertDecisions( inputDecision, newDecision );
-	newDecision->setObjectLink( "initialRoI", roiELInfo.link );
-	prevRoIDescriptor = roiDescriptor;
-      } else {
-	newDecision = outputDecisions->back();
-	newDecision->setObjectLink( "seedEnd", ElementLink<TrigCompositeUtils::DecisionContainer>( inputHandle.key(), inputCounter ) );
-	insertDecisions( inputDecision, newDecision );
-	ATH_MSG_DEBUG("No need to create another output decision object, just adding decision IDs");
-      }
-      
-      // search for existing view
-      itViewMap = viewMap.find(roiDescriptor);
-      if ( itViewMap != viewMap.end() ) {
-	int iview = itViewMap->second;
-	newDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), iview ) ); //adding view to TC
-	ATH_MSG_DEBUG( "Adding already mapped view " << iview << " in ViewVector , to new decision");
-	//	need to check if this View has parent views? can we have more than one parent views?
-      } else {
-	
-	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
-	viewVector->push_back( newView );
-	contexts.emplace_back( context );
-	contexts.back().setExtension( Atlas::ExtendedEventContext( viewVector->back(), conditionsRun ) );
-	
-	// link decision to this view
-	newDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
-      	viewMap[roiDescriptor]=viewVector->size()-1;
-	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( roiDescriptor, viewVector->back(), contexts.back() ) );	
-      }
+
+    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( "Recorded output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<< outputDecisions->size()  <<" at index "<< outputIndex);
-  }
+    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;
+	// 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
+	  viewVector->push_back( newView );
+	  contexts.emplace_back( context );
+	  contexts.back().setExtension( Atlas::ExtendedEventContext( viewVector->back(), conditionsRun ) );
+	  
+	  // link decision to this view
+	  outputDecision->setObjectLink( "view", 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( roi, viewVector->back(), contexts.back() ) );	
+	}
+	else {
+	  int iview = roiIt-RoIsFromDecision.begin();
+	  outputDecision->setObjectLink( "view", 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   
+  }// loop over output keys
+
+
+  // launch view execution
 
   ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
   ATH_CHECK( ViewHelper::ScheduleViews( viewVector,           // Vector containing views
@@ -126,65 +110,15 @@ StatusCode EventViewCreatorAlgorithm::execute( const EventContext& context ) con
 					m_scheduler.get() ) );
   
   // 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");
-
-  size_t validInputCount = countInputHandles( context );  
-  size_t validOutputCount = 0;
-  for ( auto outHandle: outputHandles ) {
-    if( not outHandle.isValid() ) continue;
-    validOutputCount++;
-  }
   
-  ATH_MSG_DEBUG("Produced " << validOutputCount << " decisions containers");
-  if(validInputCount != validOutputCount ) {
-    ATH_MSG_ERROR("Found " << validInputCount << " inputs and " << validOutputCount << " outputs");
-    return StatusCode::FAILURE;
-  }
-  printDecisions( outputHandles );     
+  ATH_CHECK( debugPrintOut(context, outputHandles) );
   return StatusCode::SUCCESS;
 }
 
-size_t EventViewCreatorAlgorithm::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()? "valid": "not valid" ) );
-    if (inputHandle.isValid() and inputHandle->size() > 0 ) validInputCount++;
-  }
-  ATH_MSG_DEBUG( "number of implicit ReadHandles is " << decisionInputs().size() << ", " << validInputCount << " are valid" );
-  
-  return validInputCount;
-}
-
-
-void EventViewCreatorAlgorithm::printDecisions( const std::vector<SG::WriteHandle<TrigCompositeUtils::DecisionContainer>>& outputHandles ) const {
-  if ( not msgLvl( MSG::DEBUG ) )
-    return;
-      
-  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 : TrigCompositeUtils::decisionIDs(outDecision) ) {
-	ATH_MSG_DEBUG( " ---  decision " << HLT::Identifier( id ) );
-      }  
-    }
-  }    
-}
 
-void EventViewCreatorAlgorithm::insertDecisions( const TrigCompositeUtils::Decision* src, TrigCompositeUtils::Decision* dest ) const  {
-  using namespace TrigCompositeUtils;
-  DecisionIDContainer ids;
-  decisionIDs( dest, ids );
-  decisionIDs( src, ids );
-  decisionIDs( dest ).clear(); 
-  decisionIDs(dest).insert( decisionIDs(dest).end(), ids.begin(), ids.end() );
-}	
 
 StatusCode EventViewCreatorAlgorithm::linkViewToParent( const TrigCompositeUtils::Decision* inputDecision, SG::View* newView ) const {
   // see if there is a view linked to the decision object, if so link it to the view that is just made
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h
index 4e2b4974950b65f7857545ddf1bac53225ed9b5c..0950e60efffb9aa30fd06aed9d0b509fd09eb82f 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.h
@@ -26,6 +26,8 @@
    * @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.
    **/
 
+
+
 class EventViewCreatorAlgorithm : public ::InputMakerBase
 {
  public:
@@ -41,21 +43,20 @@ class EventViewCreatorAlgorithm : public ::InputMakerBase
     //Output views for merging
     SG::WriteHandleKey< ViewContainer > m_viewsKey{ this, "Views", "Unspecified", "The key of views collection produced" };
 
-    // auxiliary handles
+    // same handles as inputMakerForRoI
     SG::WriteHandleKey< ConstDataVector<TrigRoiDescriptorCollection> > m_inViewRoIs{ this, "InViewRoIs", "Unspecified", "Name with which the RoIs shoudl be inserted into the views" };
 
-
+    // needs for views
     ServiceHandle< IScheduler > m_scheduler{ this, "Scheduler", "AvalancheSchedulerSvc", "The Athena scheduler" };
     Gaudi::Property<bool> m_viewPerRoI{ this, "ViewPerRoI", false, "Create one View per RoI as opposed to one View per Decision object, needs to be true when multiple decisions per RoI exists" };
     Gaudi::Property< std::string > m_viewNodeName{ this, "ViewNodeName", "", "Name of the CF node to attach a view to" };
-    Gaudi::Property< std::string > m_roisLink{ this, "RoIsLink", "initialRoI", "Name of EL to RoI object lined to the decision" };
+
     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" };
 
 
-    size_t countInputHandles( const EventContext& context ) const;
-    void   printDecisions( const std::vector<SG::WriteHandle<TrigCompositeUtils::DecisionContainer>>& outputHandles ) const;
-    void insertDecisions( const TrigCompositeUtils::Decision* src, TrigCompositeUtils::Decision* dest ) const;
+
+    // methods
   /**
    * @brief makes sure the views are linked, if configuration requireParentView is set, failure to set the parent is an error
    **/
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
index 0dc87e50cfa84d057e8e147022fc41185d2d14e0..c9ec14c5bb42cba252d63cb93a2c603cb027bc5e 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
@@ -11,6 +11,7 @@
 #include "DecisionHandling/TrigCompositeUtils.h"
 #include "DecisionHandling/HLTIdentifier.h"
 
+using namespace TrigCompositeUtils;
 
 EventViewCreatorAlgorithmWithJets::EventViewCreatorAlgorithmWithJets( const std::string& name, ISvcLocator* pSvcLocator )
   : EventViewCreatorAlgorithm( name, pSvcLocator ) {}
@@ -25,111 +26,90 @@ StatusCode EventViewCreatorAlgorithmWithJets::initialize() {
   return StatusCode::SUCCESS;
 }
 
-StatusCode EventViewCreatorAlgorithmWithJets::execute( const EventContext& context ) const { 
-  auto outputHandles = decisionOutputs().makeHandles( context );     
-  // make and store the views
+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));
+
+    // make the views
   auto viewsHandle = SG::makeHandle( m_viewsKey ); 
   auto viewVector1 = std::make_unique< ViewContainer >();
   ATH_CHECK( viewsHandle.record(  std::move( viewVector1 ) ) );
   auto viewVector = viewsHandle.ptr();
 
+    //  auto viewVector = std::make_unique< ViewContainer >();
   auto contexts = std::vector<EventContext>( );
   unsigned int viewCounter = 0;
   unsigned int conditionsRun = context.getExtension<Atlas::ExtendedEventContext>().conditionsRun();
 
-  //  const TrigRoiDescriptor* previousRoI = 0;
-  // mapping RoI with index of the View in the vector
-  // This is used to link the same view to differnt decisions that come from the same RoI
-  std::map <const TrigRoiDescriptor*, int> viewMap;
-  std::map <const TrigRoiDescriptor*, int>::iterator itViewMap;
-  int outputIndex = -1;
- // Loop over all input containers, which are of course TrigComposites, and request their features
-  // this is the same as InputMaker, apart from the view creation. The loop can be splitted in two loops, to have one common part
-  for ( auto inputKey: decisionInputs() ) {
-    outputIndex++;
-    auto inputHandle = SG::makeHandle( inputKey, context );
-    if( not inputHandle.isValid() ) {
-      ATH_MSG_DEBUG( "Got no decisions from input " << inputKey.key() );
+   //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( inputHandle->size() == 0 ) { // input filtered out
-      ATH_MSG_ERROR( "Got 0 decisions from valid input "<< inputKey.key()<<". Is it expected?");
+    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 input " << inputKey.key() << " with " << inputHandle->size() << " elements" );
-    
-     // prepare output decisions
-    TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
-    TrigCompositeUtils::DecisionContainer* outputDecisions = outputHandles[outputIndex].ptr();
-    
-    const TrigRoiDescriptor* prevRoIDescriptor = nullptr;
-    int inputCounter = -1;
-    for ( auto inputDecision: *inputHandle ) {
-      inputCounter++;      
-      // Retrieve jets ...
-      ATH_MSG_DEBUG( "Checking there are jets linked to decision object" );
-      TrigCompositeUtils::LinkInfo< xAOD::JetContainer > jetELInfo = TrigCompositeUtils::findLink< xAOD::JetContainer >( inputDecision,m_jetsLink );
-      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() );
-
-      // pull RoI descriptor
-      TrigCompositeUtils::LinkInfo<TrigRoiDescriptorCollection> roiELInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>(inputDecision, m_roisLink );
-      ATH_CHECK( roiELInfo.isValid() );
-      // associate this RoI to output decisions
-      auto roiDescriptor = *roiELInfo.link;
-      ATH_MSG_DEBUG( "Placing TrigRoiDescriptor " );
-      ATH_MSG_DEBUG( "   " << *roiDescriptor );
-
-      TrigCompositeUtils::Decision* newDecision = nullptr;      
-      if ( prevRoIDescriptor != roiDescriptor ) {
-	//make one TC decision output per input and connect to previous
-	newDecision = TrigCompositeUtils::newDecisionIn( outputDecisions, name() );
-	TrigCompositeUtils::linkToPrevious( newDecision, inputKey.key(), inputCounter );
-	insertDecisions( inputDecision, newDecision );
-	newDecision->setObjectLink( "initialRoI", roiELInfo.link );
-	newDecision->setObjectLink( "jets", jetELInfo.link );
-	prevRoIDescriptor = roiDescriptor;
-      } else {
-	newDecision = outputDecisions->back();
-	newDecision->setObjectLink( "seedEnd", ElementLink<TrigCompositeUtils::DecisionContainer>( inputHandle.key(), inputCounter ) );
-	insertDecisions( inputDecision, newDecision );
-	ATH_MSG_DEBUG("No need to create another output decision object, just adding decision IDs");
-      }
-      
-      // search for existing view
-      itViewMap = viewMap.find(roiDescriptor);
-      if ( itViewMap != viewMap.end() ) {
-	int iview = itViewMap->second;
-	newDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), iview ) ); //adding view to TC
-	ATH_MSG_DEBUG( "Adding already mapped view " << iview << " in ViewVector , to new decision");
-	//	need to check if this View has parent views? can we have more than one parent views?
-      } else {
-	
-	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
-	viewVector->push_back( newView );
-	contexts.emplace_back( context );
-	contexts.back().setExtension( Atlas::ExtendedEventContext( viewVector->back(), conditionsRun ) );
+
+    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,m_jetsLink );
+	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() );
+
 	
-	// link decision to this view
-	newDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
-      	viewMap[roiDescriptor]=viewVector->size()-1;
-	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( roiDescriptor, viewVector->back(), contexts.back() ) );	
-	ATH_CHECK( placeJetInView( jet, viewVector->back(), contexts.back() ) );
-      }
-    }
-    
-    ATH_MSG_DEBUG( "Recording output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<< outputDecisions->size()  <<" at index "<< outputIndex);
-  }
+	// 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
+	  viewVector->push_back( newView );
+	  contexts.emplace_back( context );
+	  contexts.back().setExtension( Atlas::ExtendedEventContext( viewVector->back(), conditionsRun ) );
+	  
+	  // link decision to this view
+	  outputDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), viewVector->size()-1 ));//adding view to TC
+	  outputDecision->setObjectLink( "jets", jetELInfo.link );
+	  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( roi, viewVector->back(), contexts.back() ) );
+	  ATH_CHECK( placeJetInView( jet, viewVector->back(), contexts.back() ) );
+	}
+	else {
+	  int iview = roiIt-RoIsFromDecision.begin();
+	  outputDecision->setObjectLink( "view", ElementLink< ViewContainer >(m_viewsKey.key(), iview ) ); //adding view to TC
+	  outputDecision->setObjectLink( "jets", jetELInfo.link );
+	  ATH_MSG_DEBUG( "Adding already mapped view " << iview << " in ViewVector , to new decision");
+	}
+      }// loop over previous inputs
+    } // loop over decisions   
+  }// loop over output keys
+
+ 
 
   ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
   ATH_CHECK( ViewHelper::ScheduleViews( viewVector,           // Vector containing views
@@ -137,22 +117,12 @@ StatusCode EventViewCreatorAlgorithmWithJets::execute( const EventContext& conte
 					context,                    // Source context
 					m_scheduler.get() ) );
   
-  // report number of views, stored already when container was created
+  // store views
+  // auto viewsHandle = SG::makeHandle( m_viewsKey );
+  // ATH_CHECK( viewsHandle.record(  std::move( viewVector ) ) );
   ATH_MSG_DEBUG( "Store "<< viewsHandle->size() <<" Views");
 
-  size_t validInputCount = countInputHandles( context );  
-  size_t validOutputCount = 0;
-  for ( auto outHandle: outputHandles ) {
-    if( not outHandle.isValid() ) continue;
-    validOutputCount++;
-  }
-  
-  ATH_MSG_DEBUG("Produced " << validOutputCount << " decisions containers");
-  if(validInputCount != validOutputCount ) {
-    ATH_MSG_ERROR("Found " << validInputCount << " inputs and " << validOutputCount << " outputs");
-    return StatusCode::FAILURE;
-  }
-  printDecisions( outputHandles );     
+  ATH_CHECK( debugPrintOut(context, outputHandles) );
   return StatusCode::SUCCESS;
 }
 
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/python/HLTSignatureConfig.py b/Trigger/TrigValidation/TrigUpgradeTest/python/HLTSignatureConfig.py
index 4504157e24ff17e72abbc20b484f2fe4052eda0c..d291d5c2cde2c7a250eab123222df175ac8a22f6 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/python/HLTSignatureConfig.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/python/HLTSignatureConfig.py
@@ -5,10 +5,19 @@ from TrigUpgradeTest.TrigUpgradeTestConf import HLTTest__TestComboHypoAlg
 from AthenaCommon.Constants import VERBOSE,DEBUG
 from TrigUpgradeTest.HLTSignatureHypoTools import *
 
+
+
+
+UseThisLinkName="initialRoI"
+#UseThisLinkName="feature"
+
+
 from TrigUpgradeTest.TrigUpgradeTestConf import HLTTest__TestInputMaker
-def InputMakerAlg(name):
-    return HLTTest__TestInputMaker(name, OutputLevel = DEBUG, LinkName="initialRoI")
+def InputMakerForInitialRoIAlg(name):
+    return HLTTest__TestInputMaker(name, OutputLevel = DEBUG, RoIsLink="initialRoI", LinkName="initialRoI")
 
+def InputMakerForFeatureAlg(name):
+    return HLTTest__TestInputMaker(name, OutputLevel = DEBUG, RoIsLink="initialRoI", LinkName=UseThisLinkName)
 
 # here define the sequences from the signatures
 # signatures do this:
@@ -19,9 +28,6 @@ from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import MenuSequence
 from AthenaCommon.CFElements import parOR, seqAND, stepSeq
 
 
-UseThisLinkName="initialRoI"
-#UseThisLinkName="feature"
-
 #### muon signatures
 #####################
 
@@ -36,7 +42,7 @@ def MuHypo(name):
 
 
 
-muIM= InputMakerAlg(name="Step1MuInputMaker")
+muIM= InputMakerForInitialRoIAlg(name="Step1MuInputMaker")
 muIM.Output='muIM_out'
 
 #print muIM
@@ -56,7 +62,7 @@ def muStep1Sequence():
     return MenuSequence(Sequence=mustep1_sequence, Maker=muIM, Hypo=muHypo, HypoToolGen=MuTestHypoTool)
 
 # mu step2
-muIM2= InputMakerAlg(name="Step2MuInputMaker")
+muIM2= InputMakerForFeatureAlg(name="Step2MuInputMaker")
 muIM2.Output='muIM2_out'
 
 muAlg2 = muMSRecAlg(name="muMSRecAlg2", FileName="msmu.dat")
@@ -87,7 +93,7 @@ def ElGamHypo(name):
 
 
 
-elIM= InputMakerAlg(name="Step1ElInputMaker")
+elIM= InputMakerForInitialRoIAlg(name="Step1ElInputMaker")
 elIM.Output='elIM_out'
 
 elAlg = CaloClustering(name="CaloClustering", FileName="emclusters.dat")
@@ -112,7 +118,7 @@ def gammStep1Sequence():
 
 
 #step2
-elIM2= InputMakerAlg(name="Step2ElInputMaker")
+elIM2= InputMakerForFeatureAlg(name="Step2ElInputMaker")
 elIM2.Output='elIM2_out'
 
 elAlg2 = CaloClustering(name="CaloClustering2", FileName="emclusters.dat")
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/python/PhotonMenuConfig.py b/Trigger/TrigValidation/TrigUpgradeTest/python/PhotonMenuConfig.py
index 535a6cf7a17294f47c6a461abbcdcd9f64dc303c..2007bddf05faf7e99d3b3209fa19ad7002b06e3b 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/python/PhotonMenuConfig.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/python/PhotonMenuConfig.py
@@ -23,6 +23,7 @@ def l2PhotonRecoCfg( flags ):
 
     reco = InViewReco("L2PhotonReco")
     reco.inputMaker().RequireParentView = True
+    reco.inputMaker().RoIsLink="roi"
     import AthenaCommon.CfgMgr as CfgMgr
 
     moveClusters = CfgMgr.AthViews__ViewDataVerifier("photonViewDataVerifier")
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/python/bjetMenuDefs.py b/Trigger/TrigValidation/TrigUpgradeTest/python/bjetMenuDefs.py
index e6201785dd50f52116a92e2a825e555c06a10706..9d97e72155d69af5b56596d259bdcb80a862c629 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/python/bjetMenuDefs.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/python/bjetMenuDefs.py
@@ -48,9 +48,10 @@ def bJetStep1Sequence():
 
     # input maker
     from DecisionHandling.DecisionHandlingConf import InputMakerForRoI
-    InputMakerAlg = InputMakerForRoI("JetInputMaker",OutputLevel=INFO)
-    InputMakerAlg.LinkName = "initialRoI"
+    InputMakerAlg = InputMakerForRoI("JetInputMaker", OutputLevel = DEBUG, RoIsLink="initialRoI")
     InputMakerAlg.RoIs='FSJETRoI'
+    InputMakerAlg.OutputLevel = DEBUG
+
 
     # Construct jets
     from TrigUpgradeTest.jetDefs import jetRecoSequence
@@ -122,8 +123,7 @@ def bJetStep1SequenceALLTE():
 
     # input maker
     from DecisionHandling.DecisionHandlingConf import InputMakerForRoI
-    InputMakerAlg = InputMakerForRoI("JetInputMaker",OutputLevel=INFO)
-    InputMakerAlg.LinkName="initialRoI"
+    InputMakerAlg = InputMakerForRoI("JetInputMaker",OutputLevel=INFO, RoIsLink="initialRoI")
     InputMakerAlg.RoIs='FSJETRoI'
 
     # Construct jets
@@ -198,7 +198,7 @@ def bJetStep2Sequence():
 
     # Event View Creator Algorithm
     from ViewAlgs.ViewAlgsConf import EventViewCreatorAlgorithmWithJets
-    InputMakerAlg = EventViewCreatorAlgorithmWithJets("BJetInputMaker_step2")
+    InputMakerAlg = EventViewCreatorAlgorithmWithJets("BJetInputMaker_step2", RoIsLink="initialRoI")
     InputMakerAlg.OutputLevel = DEBUG
     InputMakerAlg.ViewFallThrough = True # Access Store Gate for retrieving data
     InputMakerAlg.ViewPerRoI = True # If True it creates one view per RoI
@@ -251,9 +251,8 @@ def bJetStep2SequenceALLTE():
 
     # input maker
     from DecisionHandling.DecisionHandlingConf import InputMakerForRoI
-    InputMakerAlg = InputMakerForRoI("BJetInputMaker_step2_ALLTE")
+    InputMakerAlg = InputMakerForRoI("BJetInputMaker_step2_ALLTE", RoIsLink="initialRoI")
     InputMakerAlg.OutputLevel = DEBUG
-    InputMakerAlg.LinkName="initialRoI"
 #    InputMakerAlg.RoIs="SplitJets" # TMP commenting
     
     # gsc correction
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/python/jetMenuDefs.py b/Trigger/TrigValidation/TrigUpgradeTest/python/jetMenuDefs.py
index 64c49d0301353eb1d167add3e4a1ca12fbc3c731..57d2592e6890581b9b8b8006dde1a2c7aba8e093 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/python/jetMenuDefs.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/python/jetMenuDefs.py
@@ -11,13 +11,14 @@ def jetSequence():
 
     #input maker
     from DecisionHandling.DecisionHandlingConf import InputMakerForRoI
-    InputMakerAlg = InputMakerForRoI("JetInputMaker", OutputLevel = DEBUG, LinkName="initialRoI")
+    InputMakerAlg = InputMakerForRoI("JetInputMaker", OutputLevel = DEBUG, RoIsLink="initialRoI")
     InputMakerAlg.RoIs='FSJETRoI'
     
     #reco sequence
     from TrigUpgradeTest.jetDefs import jetRecoSequence
     (recoSequence, sequenceOut) = jetRecoSequence(InputMakerAlg.RoIs)
 
+     
     #hypo
     from TrigHLTJetHypo.TrigHLTJetHypoConf import TrigJetHypoAlgMT
     from TrigHLTJetHypo.TrigJetHypoToolConfig import trigJetHypoToolFromName
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/simpleJetJob.py b/Trigger/TrigValidation/TrigUpgradeTest/share/simpleJetJob.py
index 856b55d284317a82b5f0a85a51810d53f7fbf7e6..4775d3ff7c97ef5a3e5f4c7dea6532a2529df2fa 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/share/simpleJetJob.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/share/simpleJetJob.py
@@ -55,7 +55,7 @@ if TriggerFlags.doCalo:
          
          #inputmaker
          from DecisionHandling.DecisionHandlingConf import InputMakerForRoI
-         InputMakerAlg = InputMakerForRoI("JetInputMaker", OutputLevel = DEBUG, LinkName="initialRoI")
+         InputMakerAlg = InputMakerForRoI("JetInputMaker", OutputLevel = DEBUG, RoIsLink="initialRoI")
          InputMakerAlg.RoIs='FSJETRoI'
          InputMakerAlg.InputMakerInputDecisions = filterL1RoIsAlg.Output 
          InputMakerAlg.InputMakerOutputDecisions = ["JETRoIDecisionsOutput"]
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx
index 0bba744bd22dc28934c2946c9ca5aaf5a30d8e7a..73fae66a2c04cb923d8b435c48888e110cbfb85c 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx
@@ -13,15 +13,10 @@ namespace HLTTest {
   TestComboHypoAlg::TestComboHypoAlg( const std::string& name, 
 				      ISvcLocator* pSvcLocator ) : 
     ::AthReentrantAlgorithm( name, pSvcLocator )  {
-    //declareProperty( "Property", m_nProperty );
-    // declareProperty( "Input1", m_recoInput1 ); 
-    // declareProperty( "Input2", m_recoInput2 );
     declareProperty( "Property1", m_property1 );
     declareProperty( "Property2", m_property2 );
     declareProperty( "Threshold1", m_threshold1 = 0);
     declareProperty( "Threshold2", m_threshold2 = 0);
-    // declareProperty( "Output1", m_output1 );
-    // declareProperty( "Output2", m_output2 );
     declareProperty( "DecisionLabel", m_decisionLabel );
   }
 
@@ -57,10 +52,12 @@ namespace HLTTest {
 
   bool TestComboHypoAlg::passed( const Decision* d1, const Decision* d2 ) const {
     {
-      auto feature1 = d1->objectLink<xAOD::TrigCompositeContainer>( "feature" );
+      auto featureInfo = TrigCompositeUtils::findLink<xAOD::TrigCompositeContainer>( d1, "feature"  );
+      auto feature1 = featureInfo.link;
+
       if ( not feature1.isValid() )  {
 	ATH_MSG_ERROR( "Can not find reference to the object from the decision1" );
-	return false; //StatusCode::FAILURE;
+	return false; 
       }
       if ( (*feature1)->hasDetail<float>(m_property1 ) ){
 	float v = (*feature1)->getDetail<float>( m_property1 );
@@ -71,8 +68,10 @@ namespace HLTTest {
       else ATH_MSG_ERROR( "Cannot find detail "<<m_property1<<" in feature1");
     }
     
-    {      
-      auto feature2 = d2->objectLink<xAOD::TrigCompositeContainer>( "feature" );
+    {
+      auto featureInfo = TrigCompositeUtils::findLink<xAOD::TrigCompositeContainer>( d2, "feature"  );
+      auto feature2 = featureInfo.link;
+
       if ( not feature2.isValid() )  {
 	ATH_MSG_ERROR( "Can not find reference to the object from the decision2" );
 	return false;//StatusCode::FAILURE;
@@ -89,79 +88,6 @@ namespace HLTTest {
   }
 
 
-  // StatusCode TestComboHypoAlg::execute_oninput( int inputCounter, const EventContext& context ) const {
-  //   ReadHandle<DecisionContainer> previousDecisionsHandle;
-  //   if (inputCounter==0)       previousDecisionsHandle = SG::makeHandle( m_previousDecisions1, context );
-  //   else if (inputCounter==1)  previousDecisionsHandle = SG::makeHandle( m_previousDecisions2, context );
-
-  //   if( not previousDecisionsHandle.isValid() ) {//implicit
-  //     ATH_MSG_ERROR( "No implicit RH for previous decisions on input "<<inputCounter<<": is this expected?" );
-  //     return StatusCode::SUCCESS;      
-  //   }
-    
-  //   ATH_MSG_DEBUG( "Running on input "<<inputCounter<<" with "<< previousDecisionsHandle->size() <<" implicit ReadHandles for previous decisions");
-
-  //   ReadHandle<DecisionContainer> recoInput;
-  //   if (inputCounter==0)  recoInput = SG::makeHandle(m_recoInput1, context);
-  //   else if (inputCounter==1)  recoInput = SG::makeHandle(m_recoInput2, context);
-  //   ATH_MSG_DEBUG( "and with "<< recoInput->size() <<" reco inputs");
-    
-  //   // new output decisions
-  //   auto decisions = std::make_unique<DecisionContainer>();
-  //   auto aux = std::make_unique<DecisionAuxContainer>();
-  //   decisions->setStore( aux.get() );
-
-    
-  //   std::vector<const FeatureOBJ*> featureFromDecision;
-  //   for ( auto previousDecision: *previousDecisionsHandle ) {     
-  //     auto featurelink = (previousDecision)->objectLink<FeatureContainer>( m_linkName.value() );
-  //     CHECK( featurelink.isValid() );
-  //     const FeatureOBJ* feature = *featurelink;
-  //     featureFromDecision.push_back( feature);
-  //   }
-
-  //   // reduce if same feature is found
-  //   //
-    
-  //   ATH_MSG_DEBUG("Found "<<featureFromDecision.size()<<" features "<<m_linkName.value() <<" mapped from previous decisions");
-    
-  //   size_t counter = 0;
-  //   //map reco object and decision: find in reco obejct the initial RoI and map it to the correct decision
-  //   for (auto recoobj: *recoInput){
-  //     auto roiEL = recoobj->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
-  //     CHECK( roiEL.isValid() );
-  //     auto featurelink = (recoobj)->objectLink<FeatureContainer>( m_linkName.value() );
-  //     CHECK( featurelink.isValid() );
-  //     if ( not featurelink.isValid() )  {
-  // 	ATH_MSG_ERROR( " Can not find reference to " + m_linkName.value() + " from the decision" );
-  // 	return StatusCode::FAILURE;
-  //     }
-      
-  //     ATH_MSG_DEBUG("Found link from the reco object to feature "<<m_linkName.value() );
-  //     const FeatureOBJ* feature = *featurelink;
-  //     // find the same roi in the previous decisions
-  //     bool foundRoIInDecision=false;
-  //      size_t pos=distance(featureFromDecision.begin(), find(featureFromDecision.begin(), featureFromDecision.end(), feature));
-  //      if (pos < featureFromDecision.size()){
-  // 	 foundRoIInDecision=true;	 
-  //      }
-       
-  //      if (foundRoIInDecision){
-  // 	 ATH_MSG_DEBUG("Found link from the reco object to the previous decision at position "<<pos);
-  // 	 auto d = newDecisionIn(decisions.get());
-  // 	 d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>(m_recoInput.key(), counter) );// feature used by the Tool
-  // 	 d->setObjectLink( "initialRoI", featurelink );// this is used by the InputMaker
-  // 	 d->setObjectLink( "previousDecisions", ElementLink<DecisionContainer>(m_previousDecisions.key(), pos) );// link to previous decision object
-  //      }
-  //      else{
-  // 	 ATH_MSG_ERROR( " Can not find reference to previous decision from feature " + m_linkName.value() + " from reco object " << counter );
-  // 	 return StatusCode::FAILURE;
-  //      }
-  //      counter++;
-  //   }
-    
-
-  // }
 
   StatusCode TestComboHypoAlg::execute( const EventContext& context ) const {  
 
@@ -194,7 +120,9 @@ namespace HLTTest {
     // find RoIs from previous decisions
     std::vector<const FeatureOBJ*> featureFromDecision1;
     for ( auto previousDecision: *previousDecisionsHandle1 ) {
-      auto featurelink = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+      auto featureInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( previousDecision, "initialRoI"  );
+      auto featurelink = featureInfo.link;
+
       CHECK( featurelink.isValid() );
       const FeatureOBJ* feature = *featurelink;
       featureFromDecision1.push_back( feature);
@@ -203,7 +131,9 @@ namespace HLTTest {
 
    std::vector<const FeatureOBJ*> featureFromDecision2;
     for ( auto previousDecision: *previousDecisionsHandle2 ) {
-      auto featurelink = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+      auto featureInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( previousDecision, "initialRoI"  );
+      auto featurelink = featureInfo.link;
+
       CHECK( featurelink.isValid() );
       const FeatureOBJ* feature = *featurelink;
       featureFromDecision2.push_back( feature);
@@ -213,7 +143,8 @@ namespace HLTTest {
     //map reco object and decision: find in reco obejct the initial RoI and map it to the correct decision
     size_t counter1 = 0;
     for (auto recoobj: *recoInput1){
-      auto featurelink = recoobj->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+      auto featureInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( recoobj, "initialRoI"  );
+      auto featurelink = featureInfo.link;
       CHECK( featurelink.isValid() );      
       ATH_MSG_DEBUG("Found link from the reco object1 to RoI" );
       const FeatureOBJ* feature = *featurelink;
@@ -241,7 +172,9 @@ namespace HLTTest {
 
     size_t counter2 = 0;
      for (auto recoobj: *recoInput2){
-      auto featurelink = recoobj->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+       auto featureInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( recoobj, "initialRoI"  );
+       auto featurelink = featureInfo.link;
+
       CHECK( featurelink.isValid() );      
       ATH_MSG_DEBUG("Found link from the reco object2 to RoI" );
       const FeatureOBJ* feature = *featurelink;
@@ -266,36 +199,8 @@ namespace HLTTest {
        counter2++;
     }
     
-    // // pre-recate decision objects for each container
-    // size_t counter1 = 0;
-    // for ( auto previousDecision: *previousDecisionsHandle1 ) {
-    //   auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
-    //   CHECK( roiEL.isValid() );
-    //   auto d = newDecisionIn( decisions1 );
-    //   if (counter1<input1->size())
-    // 	d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>( m_recoInput1.key(),  counter1) );
-    //   else
-    // 	ATH_MSG_DEBUG( "Feature not added to the new decision of type 1: counter =" << counter1<<" list size = "<<input1->size());
-    //   d->setObjectLink( "initialRoI", roiEL );
-    //   d->setObjectLink( "previousDecisions", ElementLink<DecisionContainer>(m_previousDecisions1.key(), counter1) );
-    //   counter1++;
-    // }
-    ATH_MSG_DEBUG( "Found  "<<counter1<<" rois from input 1 " );
-    
-    // size_t counter2 = 0;
-    // for ( auto previousDecision: *previousDecisionsHandle2 ) {
-    //   auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
-    //   CHECK( roiEL.isValid() );    
-    //   auto d = newDecisionIn( decisions2 );
-    //   //get the feature
-    //   if (counter2<input2->size())
-    // 	d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>( m_recoInput2.key(),  counter2) );
-    //   else
-    // 	ATH_MSG_DEBUG( "Feature not added to the new decision of type 2");      
-    //   d->setObjectLink( "initialRoI", roiEL );// this is used by the InputMaker
-    //   d->setObjectLink( "previousDecisions", ElementLink<DecisionContainer>(m_previousDecisions2.key(), counter2) );
-    //   counter2++;
-    // }
+  
+    ATH_MSG_DEBUG( "Found  "<<counter1<<" rois from input 1 " );       
     ATH_MSG_DEBUG( "Found  "<<counter2<<" rois from input 2 " );
 
     // this is the tool
@@ -365,7 +270,6 @@ namespace HLTTest {
       }
     }
     
-    //    ATH_MSG_DEBUG ( "Exit with "<<decisions1->size() <<" decision from input 1 and " <<decisions2->size()<<" form input 2");
     return StatusCode::SUCCESS;
   }
 
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
index 3df9f4318bd666bd15b82d1ae6274ae3a598a033..94b86c7dfa59afef4fd0b43da787a54b6971f267 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
@@ -52,9 +52,8 @@ namespace HLTTest {
     // find features:
     std::vector<const FeatureOBJ*> featureFromDecision;
     for ( auto previousDecision: *previousDecisionsHandle ) {
-      TrigCompositeUtils::LinkInfo<FeatureContainer> linkInfo = TrigCompositeUtils::findLink<FeatureContainer>(previousDecision, m_linkName.value());
-      ElementLink<FeatureContainer> featureLink = linkInfo.link;
-      //auto featureLink = (previousDecision)->objectLink<FeatureContainer>( m_linkName.value() );
+      auto linkInfo = TrigCompositeUtils::findLink<FeatureContainer>(previousDecision, m_linkName.value());
+      auto featureLink = linkInfo.link;
       CHECK( featureLink.isValid() );
       const FeatureOBJ* feature = *featureLink;
       featureFromDecision.push_back( feature);
@@ -64,9 +63,12 @@ namespace HLTTest {
     //map reco object and decision: find in reco obejct the initial RoI and map it to the correct decision
     size_t reco_counter = 0;
     for (auto recoobj: *recoInput){
-      auto roiEL = recoobj->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+      auto roiInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( recoobj, "initialRoI"  );
+      auto roiEL = roiInfo.link;
       CHECK( roiEL.isValid() );
-      auto featurelink = (recoobj)->objectLink<FeatureContainer>( m_linkName.value() );
+      
+      auto featureInfo = TrigCompositeUtils::findLink<FeatureContainer>( recoobj, m_linkName.value()  );
+      auto featurelink = featureInfo.link;
       CHECK( featurelink.isValid() );
       if ( not featurelink.isValid() )  {
 	ATH_MSG_ERROR( " Can not find reference to " + m_linkName.value() + " from the decision" );
@@ -87,7 +89,6 @@ namespace HLTTest {
 	 auto d = newDecisionIn(decisions);
 	 d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>(m_recoInput.key(), reco_counter) );// feature used by the Tool
 	 d->setObjectLink( m_linkName.value(), featurelink );
-	 d->setObjectLink( "initialRoI", roiEL );
 	 linkToPrevious( d, decisionInput().key(), pos );
        }
        else{
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoTool.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoTool.cxx
index b5344725153ef79dc807dafba7ea86d93db97259..cac352bfc086e1737d36e2117255d525f33b91bd 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoTool.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoTool.cxx
@@ -38,36 +38,40 @@ namespace HLTTest {
     size_t counter = 0;
     for ( auto d: *decisions )  {
       //get previous decisions
-      auto previousDecisions = linkToPrevious( d);
-      TrigCompositeUtils::DecisionIDContainer objDecisions;      
-      TrigCompositeUtils::decisionIDs( *previousDecisions, objDecisions );
+      ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(d);
+      ATH_MSG_DEBUG("Got "<<inputLinks.size()<<" previous decisions");
+      for (auto previousDecisions: inputLinks){
+	
+	//auto previousDecisions = linkToPrevious( d);
+	TrigCompositeUtils::DecisionIDContainer objDecisions;      
+	TrigCompositeUtils::decisionIDs( *previousDecisions, objDecisions );
       
-      ATH_MSG_DEBUG("Number of previous decisions for input "<< counter <<"= " << objDecisions.size() );
+	ATH_MSG_DEBUG("Number of previous decisions ID for input "<< counter <<"= " << objDecisions.size() );
       
-      for ( TrigCompositeUtils::DecisionID id : objDecisions ) {
-	ATH_MSG_DEBUG( " -- found decision " << HLT::Identifier( id ) );
-      }
-
-      auto it= find(objDecisions.begin(), objDecisions.end(),  m_decisionId);
-      if (it != objDecisions.end()){
-      
-	auto feature = d->objectLink<xAOD::TrigCompositeContainer>( "feature" );
-	//auto feature = d->objectLink<xAOD::TrigCompositeContainer>( m_linkName.value() );
-	if ( not feature.isValid() )  {
-	  ATH_MSG_ERROR( " Can not find reference to the object from the decision" );
-	  return StatusCode::FAILURE;
+	for ( TrigCompositeUtils::DecisionID id : objDecisions ) {
+	  ATH_MSG_DEBUG( " -- found decision " << HLT::Identifier( id ) );
 	}
-	float v = (*feature)->getDetail<float>( m_property );
-	if ( v > m_threshold ) { // actual cut will be more complex of course
-	  ATH_MSG_DEBUG( "  threshold " << m_threshold << " passed by value: " << v );	
-	  addDecisionID(  m_decisionId, d );
+
+	auto it= find(objDecisions.begin(), objDecisions.end(),  m_decisionId);
+	if (it != objDecisions.end()){      
+	  auto feature = d->objectLink<xAOD::TrigCompositeContainer>( "feature" );
+	  //auto feature = d->objectLink<xAOD::TrigCompositeContainer>( m_linkName.value() );
+	  if ( not feature.isValid() )  {
+	    ATH_MSG_ERROR( " Can not find reference to the object from the decision" );
+	    return StatusCode::FAILURE;
+	  }
+	  float v = (*feature)->getDetail<float>( m_property );
+	  if ( v > m_threshold ) { // actual cut will be more complex of course
+	    ATH_MSG_DEBUG( "  threshold " << m_threshold << " passed by value: " << v );	
+	    addDecisionID(  m_decisionId, d );
+	  }
+	  else ATH_MSG_DEBUG( "  threshold " << m_threshold << " not passed by value " << v );
 	}
-	else ATH_MSG_DEBUG( "  threshold " << m_threshold << " not passed by value " << v );
-      }
-      else {
-	ATH_MSG_DEBUG("No Input decisions requested by active chain "<< m_decisionId);
+	else {
+	  ATH_MSG_DEBUG("No Input decisions requested by active chain "<< m_decisionId);
+	}       
+	counter++;
       }
-      counter++;
     }
     
     return StatusCode::SUCCESS;
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx
index 4a4a72d69bbf0f460a4fc2abca8e31476e2f760f..3d7b76d870f9b2df38d784cfebf4933b5fe119ef 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.cxx
@@ -60,39 +60,35 @@ namespace HLTTest {
       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){ 
-        ElementLink<DecisionContainer> inputLink = linkToPrevious(outputDecision);
-        ATH_MSG_DEBUG( "followed seed link to input "<< inputLink.key() );
-        const Decision* inputDecision = *inputLink;
- 	auto roiEL = inputDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
- 	CHECK( roiEL.isValid() );
+        ElementLinkVector<DecisionContainer> inputLinks = getLinkToPrevious(outputDecision);
+	for (auto input: inputLinks){
+	  ATH_MSG_DEBUG( "followed seed link to input "<< input.key() );
+	  const Decision* inputDecision = *input;
+	  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
- 	auto featureLink = inputDecision->objectLink<FeatureContainer>( m_linkName.value() );
- 	if ( not featureLink.isValid() )  {
- 	  ATH_MSG_ERROR( " Can not find reference to " + m_linkName.value() + " from the decision" );
- 	  return StatusCode::FAILURE;
- 	}
-        
-        // link input reco object to outputDecision
-        outputDecision->setObjectLink(m_linkName.value(), featureLink);
-
- 	const FeatureOBJ* feature = *featureLink;
- 	ATH_MSG_DEBUG(" Found feature " <<m_linkName.value() );
-        
-        // 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("initialRoI", roiEL);
- 	  newFeature->setObjectLink(m_linkName.value(), featureLink);
- 	  ATH_MSG_DEBUG(" Added " <<m_linkName.value() << " and initialRoI " << " to reco object");
- 	}
+	  // retrieve input feature from input decision (TrigComposite), will in this case be a TrigRoiDescriptor	  
+	  auto featureLinkInfo = TrigCompositeUtils::findLink<FeatureContainer>( inputDecision,  m_linkName.value());
+	  CHECK( featureLinkInfo.isValid() );
+	
+	  // link input reco object to outputDecision
+	  auto featureLink = featureLinkInfo.link;
+	  const FeatureOBJ* feature = *featureLink;
+	  ATH_MSG_DEBUG(" Found feature " <<m_linkName.value() );
+	  
+	  // 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.        
       } // loop over decisions      
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.h b/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.h
index 8039db3e582bd1bf61614fff7fac982395c05d42..04c586d370e5c2ee038ad16d1d87c9318252cd2c 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.h
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestInputMaker.h
@@ -43,7 +43,7 @@ namespace HLTTest {
     SG::WriteHandleKey<xAOD::TrigCompositeContainer> m_recoOutput { this, "Output", "undefined", "name of the output collection for input to next reco alg in sequence" };
    
     StringProperty m_linkName   {this, "LinkName", "initialRoI",  "name of the link to the features in the decision, e.g. 'feature', 'initialRoI'"};
-    StringProperty m_outputType {this, "OutputType","outputType", "reserved for future use"};
+    //StringProperty m_outputType {this, "OutputType","outputType", "reserved for future use"};
 
   }; 
 
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestRecoAlg.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestRecoAlg.cxx
index 79b595587596a175d0e5ab50802b7865bc7a6eb5..b9cd0a9016896a41ad2f3eb116e628eb4fb9bc2f 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestRecoAlg.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestRecoAlg.cxx
@@ -96,14 +96,11 @@ namespace HLTTest {
     
     auto inputHandle = SG::makeHandle(m_input);
     ATH_MSG_DEBUG("Input " << m_input.key() << " has "<<inputHandle->size() <<" elements, scanning it");
-    for ( auto i: *inputHandle.cptr() ) {
-      //      auto roiLink = findLink<TrigRoiDescriptorCollection>(i, "initialRoI");
-      auto roiLink = i->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
+    for ( auto i: *inputHandle.cptr() ) {     
+      auto featureInfo = TrigCompositeUtils::findLink<TrigRoiDescriptorCollection>( i, "initialRoI"  );
+      auto roiLink = featureInfo.link;
       CHECK( roiLink.isValid() );
-
       if ( roiLink.isValid() ) {
-	//	const FeatureOBJ* feature = *featurelink;
-	//	auto roiPtr(roiLink.link.cptr());
 	auto roiPtr(roiLink.cptr());
 	ATH_MSG_DEBUG("RoI" << **roiPtr );
 	// create new outpu objects and add the properties
@@ -114,13 +111,6 @@ namespace HLTTest {
 	  // maintain link to previous collections
 	  xobj->setObjectLink( "initialRoI", roiLink );// this is used by the HypoAlg
 
-
-	  // auto tc = new xAOD::TrigComposite;
-	  // reco_output->push_back(tc);	  
-	  // // copy all features to a single output collection 
-	  // tc->setObjectLink(m_linkName.value(), featurelink);
-
-	  
 	  ATH_MSG_DEBUG( "Reconstructed object" );
 	  for ( auto prop : object )  {
 	    xobj->setDetail( prop.first, prop.second );
@@ -134,9 +124,6 @@ namespace HLTTest {
 	ATH_MSG_DEBUG("RoI information missing");
       }
     }
-
-      
-    
   
 
     ATH_MSG_DEBUG("Reconstructed "<<output->size() <<" objects");
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/test/test_calo_only_data.sh b/Trigger/TrigValidation/TrigUpgradeTest/test/test_calo_only_data.sh
index a95fa6097d5f49dad21ec00de4cd76249587503e..9d4f63da1c55a343ab85d0bd3765e8624a07bdd4 100755
--- a/Trigger/TrigValidation/TrigUpgradeTest/test/test_calo_only_data.sh
+++ b/Trigger/TrigValidation/TrigUpgradeTest/test/test_calo_only_data.sh
@@ -1,5 +1,6 @@
 #!/bin/sh
 # art-type: build
 # art-ci: master
+# art-include: master/Athena
 
 athena.py --threads=1 --evtMax=10 --filesInput="/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigP1Test/data17_13TeV.00327265.physics_EnhancedBias.merge.RAW._lb0100._SFO-1._0001.1" -c 'doID=False' TrigUpgradeTest/Calo.py
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/test/test_jet.sh b/Trigger/TrigValidation/TrigUpgradeTest/test/test_jet.sh
index b106306eabe4f9ebc2e084e0f5ae0078524992da..14a88ef8e08aa8c7c962e8670e581d271dd6fc25 100755
--- a/Trigger/TrigValidation/TrigUpgradeTest/test/test_jet.sh
+++ b/Trigger/TrigValidation/TrigUpgradeTest/test/test_jet.sh
@@ -1,7 +1,9 @@
 #!/bin/sh
 # art-type: build
 # art-ci: master
+# art-include: master/Athena
+
 # 10 events
 athena.py --threads=1 --evtMax=10 --skipEvents=5 --filesInput="/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigP1Test/data17_13TeV.00327265.physics_EnhancedBias.merge.RAW._lb0100._SFO-1._0001.1" -c 'doID=False' TrigUpgradeTest/simpleJetJob.py 
 
-#athena   --threads=1  --evtMax=15  --filesInput="/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/TrigP1Test/data17_13TeV.00327265.physics_EnhancedBias.merge.RAW._lb0100._SFO-1._0001.1" TrigUpgradeTest/simpleJetJob.py 
+