From d8bf5ce6e53fe00e8e471b07ba431b91fa311037 Mon Sep 17 00:00:00 2001
From: Simon George <s.george@rhul.ac.uk>
Date: Thu, 13 Dec 2018 06:42:29 +0000
Subject: [PATCH] Add functionality for decision creation to TrigCompositeUtils
 and migrate all clients

---
 .../xAODTrigger/Root/TrigComposite_v1.cxx     |  11 +
 .../ut_xaodtrigger_trigcomposite_test.cxx     |  32 +-
 .../xAODTrigger/versions/TrigComposite_v1.h   |   6 +
 .../xAODTrigger/versions/TrigComposite_v1.icc |  83 +++--
 .../TrigBjetHypo/src/TrigBjetEtHypoAlgMT.cxx  |  19 +-
 .../src/TrigL2CaloHypoAlgMT.cxx               |  12 +-
 .../src/TrigL2ElectronHypoAlgMT.cxx           |  13 +-
 .../src/TrigL2PhotonHypoAlgMT.cxx             |  13 +-
 .../TrigHLTJetHypo/src/TrigJetHypoAlgMT.cxx   |  16 +-
 .../TrigHLTJetHypo/src/TrigJetHypoAlgMT.h     |   2 +-
 .../TrigMuonHypo/src/TrigMufastHypoAlg.cxx    |  10 +-
 .../TrigMuonHypo/src/TrigMuisoHypoAlg.cxx     |  10 +-
 .../src/TrigMuonEFCombinerHypoAlg.cxx         |  12 +-
 .../src/TrigMuonEFMSonlyHypoAlg.cxx           |  12 +-
 .../src/TrigMuonEFTrackIsolationHypoAlg.cxx   |  11 +-
 .../TrigMuonHypo/src/TrigmuCombHypoAlg.cxx    |  12 +-
 .../TrigSteer/DecisionHandling/CMakeLists.txt |   2 +-
 .../DecisionHandling/TrigCompositeUtils.h     |  73 ++++-
 .../DecisionHandling/TrigCompositeUtils.icc   |  37 +++
 .../share/TrigCompositeUtils_test.ref         |  69 ++++
 .../DecisionHandling/src/ComboHypo.cxx        |  17 +-
 .../DecisionHandling/src/InputMakerBase.cxx   |  25 +-
 .../DecisionHandling/src/RoRSeqFilter.cxx     |  24 +-
 .../src/TrigCompositeUtils.cxx                |  52 ++-
 .../src/TriggerSummaryAlg.cxx                 |   9 +-
 .../test/TrigCompositeUtils_test.cxx          | 172 ++++++++--
 .../L1Decoder/src/CreateFullScanRoI.cxx       |  13 +-
 .../L1Decoder/src/EMRoIsUnpackingTool.cxx     |  31 +-
 .../TrigSteer/L1Decoder/src/FakeRoIView.cxx   | 303 ------------------
 Trigger/TrigSteer/L1Decoder/src/FakeRoIView.h |  76 -----
 .../L1Decoder/src/JRoIsUnpackingTool.cxx      |  37 +--
 Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx |  29 +-
 Trigger/TrigSteer/L1Decoder/src/L1Decoder.h   |   5 +-
 .../L1Decoder/src/METRoIsUnpackingTool.cxx    |  12 +-
 .../L1Decoder/src/MURoIsUnpackingTool.cxx     |  32 +-
 .../L1Decoder/src/RerunRoIsUnpackingTool.cxx  |  12 +-
 .../src/RoIsUnpackingEmulationTool.cxx        |  22 +-
 .../L1Decoder/src/TAURoIsUnpackingTool.cxx    |  31 +-
 .../src/components/L1Decoder_entries.cxx      |   2 -
 .../src/DecisionSummaryMakerAlg.cxx           |  10 +-
 .../src/EventViewCreatorAlgorithm.cxx         |  33 +-
 .../src/EventViewCreatorAlgorithmWithJets.cxx |  26 +-
 .../TrigUpgradeTest/src/TestComboHypoAlg.cxx  |  32 +-
 .../TrigUpgradeTest/src/TestHypoAlg.cxx       |  12 +-
 44 files changed, 654 insertions(+), 818 deletions(-)
 create mode 100644 Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc
 delete mode 100644 Trigger/TrigSteer/L1Decoder/src/FakeRoIView.cxx
 delete mode 100644 Trigger/TrigSteer/L1Decoder/src/FakeRoIView.h

diff --git a/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx b/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx
index 0816d22a001..1d691a39956 100644
--- a/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx
+++ b/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx
@@ -476,3 +476,14 @@ namespace xAOD {
    /////////////////////////////////////////////////////////////////////////////
 
 } // namespace xAOD
+
+std::ostream& operator<<(std::ostream& os, const xAOD::TrigComposite_v1& tc) {
+  os << "TrigComposite_v1 '" << tc.name() << "' link: name, key, index, CLID" << std::endl;
+  for (size_t i=0; i<tc.linkColNames().size(); ++i){
+    os << tc.linkColNames()[i] << ", ";
+    os << tc.linkColKeys()[i] << ", ";
+    os << tc.linkColIndices()[i] << ", ";
+    os << tc.linkColClids()[i] << std::endl;
+  }
+  return os;
+}
diff --git a/Event/xAOD/xAODTrigger/test/ut_xaodtrigger_trigcomposite_test.cxx b/Event/xAOD/xAODTrigger/test/ut_xaodtrigger_trigcomposite_test.cxx
index 37fc21fd3e8..85dbf283da0 100644
--- a/Event/xAOD/xAODTrigger/test/ut_xaodtrigger_trigcomposite_test.cxx
+++ b/Event/xAOD/xAODTrigger/test/ut_xaodtrigger_trigcomposite_test.cxx
@@ -61,14 +61,21 @@ int populateObject(xAOD::TrigComposite* obj) {
 
    std::cout << "Set detail ok." << std::endl;
 
+   // create a MuonRoIContainer in order to have "valid" ElementLinks
+   // they will have made up SG key hashes but they are internally "valid"
+   auto mrc = new xAOD::MuonRoIContainer();
+   for (unsigned int i = 0; i<20; i++){
+     xAOD::MuonRoI* roi = new xAOD::MuonRoI();
+     mrc->push_back( roi );
+   }
    // Now test the ElementLink functionality in a basic way:
    obj->setObjectLink( "MuonRoI",
-                       ElementLink<xAOD::MuonRoIContainer>( 123, 456 ) );
+                       ElementLink<xAOD::MuonRoIContainer>( 123, 11, mrc->at(11)) );
 
    // Test the ElementLinkVector functionality in a basic way:
    ElementLinkVector<xAOD::MuonRoIContainer> elementLinks;
-   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 789, 012 ) );
-   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 345, 678 ) );
+   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 789, 13, mrc->at(13) ) );
+   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 345, 17, mrc->at(17) ) );
    obj->addObjectCollectionLinks("ManyMuonRoIs", elementLinks);
 
    return 0;
@@ -179,19 +186,19 @@ int testLinks(const xAOD::TrigComposite* obj, const size_t expectedSize = 3) {
    SIMPLE_ASSERT( obj->linkColIndices().size() == expectedSize );
    SIMPLE_ASSERT( obj->linkColClids().size() == expectedSize );
    SIMPLE_ASSERT( obj->linkColKeys()[ 0 ] == 123 );
-   SIMPLE_ASSERT( obj->linkColIndices()[ 0 ] == 456 );
+   SIMPLE_ASSERT( obj->linkColIndices()[ 0 ] == 11 );
    SIMPLE_ASSERT( obj->linkColClids()[ 0 ] ==
                   ClassID_traits< xAOD::MuonRoIContainer >::ID() );
 
    std::cout << "Basic link functionality OK" << std::endl;
 
    ElementLink< xAOD::MuonRoIContainer > getMuonRoILink = obj->objectLink<xAOD::MuonRoIContainer>("MuonRoI");
-   SIMPLE_ASSERT(getMuonRoILink == ElementLink<xAOD::MuonRoIContainer>( 123, 456 ));
+   SIMPLE_ASSERT(getMuonRoILink == ElementLink<xAOD::MuonRoIContainer>( 123, 11 ));
 
    ElementLinkVector<xAOD::MuonRoIContainer> getMuonRoILinks = obj->objectCollectionLinks<xAOD::MuonRoIContainer>("ManyMuonRoIs");
    ElementLinkVector<xAOD::MuonRoIContainer> elementLinks;
-   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 789, 012 ) );
-   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 345, 678 ) );
+   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 789, 13 ) );
+   elementLinks.push_back( ElementLink<xAOD::MuonRoIContainer>( 345, 17 ) );
    SIMPLE_ASSERT(getMuonRoILinks == elementLinks);
 
    std::cout << "Link recovery OK" << std::endl;
@@ -254,7 +261,12 @@ int main() {
    // Copy over all other links
    SIMPLE_ASSERT( fullCopy->copyAllLinksFrom( obj ) == true );
    // Add another too
-   fullCopy->setObjectLink( "feature", ElementLink<xAOD::MuonRoIContainer>( 111, 222 ) );
+   auto mrc = new xAOD::MuonRoIContainer();
+   for (unsigned int i = 0; i<20; i++){
+     xAOD::MuonRoI* roi = new xAOD::MuonRoI();
+     mrc->push_back( roi );
+   }
+   fullCopy->setObjectLink( "feature", ElementLink<xAOD::MuonRoIContainer>( 111, 19, mrc->at(0) ) );
    SIMPLE_ASSERT( testLinks(fullCopy, 4) == 0 );
 
    std::cout << "Full-copy of element links OK" << std::endl;
@@ -285,7 +297,7 @@ int main() {
 
    // Check we can still access the element link unique to fullCopy
    ElementLink<xAOD::MuonRoIContainer> getFeatureLink = fullCopy->objectLink<xAOD::MuonRoIContainer>("feature");
-   SIMPLE_ASSERT(getFeatureLink == ElementLink<xAOD::MuonRoIContainer>( 111, 222 ));
+   SIMPLE_ASSERT(getFeatureLink == ElementLink<xAOD::MuonRoIContainer>( 111, 19, mrc->at(0) ));
 
    // Make new objects to test the manual link copy
    xAOD::TrigComposite* manualCopy = new xAOD::TrigComposite();
@@ -298,7 +310,7 @@ int main() {
    SIMPLE_ASSERT( testLinks(manualCopy, 4) == 0 );
 
    ElementLink<xAOD::MuonRoIContainer> getFeatureLinkAgain = manualCopy->objectLink<xAOD::MuonRoIContainer>("featureWithNewName");
-   SIMPLE_ASSERT(getFeatureLinkAgain == ElementLink<xAOD::MuonRoIContainer>( 111, 222 ));
+   SIMPLE_ASSERT(getFeatureLinkAgain == ElementLink<xAOD::MuonRoIContainer>( 111, 19, mrc->at(0) ));
 
    std::cout << "Copy link-by-link OK" << std::endl;
 
diff --git a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h
index 00f905da7e2..dd7ca44018b 100644
--- a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h
+++ b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h
@@ -233,4 +233,10 @@ namespace xAOD {
 // Include the template implementation:
 #include "TrigComposite_v1.icc"
 
+/**
+ * @brief print helper for TrigComposite
+ */
+std::ostream& operator<<(std::ostream& os, const xAOD::TrigComposite_v1& tc);
+
+
 #endif // XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_H
diff --git a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc
index 91ee5ef23f2..f3ba33b4680 100644
--- a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc
+++ b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc
@@ -50,41 +50,56 @@ namespace xAOD {
     bool result = getDetail(name, temp);
     return std::make_pair(result, temp);
   }
-
-   template< class CONTAINER >
-   bool
-   TrigComposite_v1::setObjectLink( const std::string& name,
-                                    const ElementLink< CONTAINER >& link ) {
-
-      // Do different things depending on whether this variable already
-      // exists or not:
-      if( hasObjectLink( name ) ) {
-         // Find the right object:
-         const std::vector< std::string >& names = linkColNames();
-         for( size_t i = 0; i < names.size(); ++i ) {
-            if( names[ i ] != name ) continue;
-            // Extract the information out of the ElementLink:
-            linkColKeysNC()[ i ] = link.key();
-            linkColIndicesNC()[ i ] = link.index();
-            linkColClidsNC()[ i ] = ClassID_traits< CONTAINER >::ID();
-            // We're done:
-            return true;
-         }
-         // Some error happened...
-         std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR Internal "
-                   << "logic error found" << std::endl;
-         return false;
-      } else {
-         // Add a new object:
-         linkColNamesNC().push_back( name );
-         linkColKeysNC().push_back( link.key() );
-         linkColIndicesNC().push_back( link.index() );
-         linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
-         // And we're done:
-         return true;
+  
+  template< class CONTAINER >
+  bool
+  TrigComposite_v1::setObjectLink( const std::string& name,
+                                   const ElementLink< CONTAINER >& link ) {
+    
+    // Check link has valid persistent state, i.e. hash key is not
+    // zero, otherwise attempting to access its string key will seg
+    // fault later, e.g. in remapping.
+    if( link.key() == 0 ) {
+      std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
+                << "link has invalid key hash of zero" << std::endl;
+      return false;
+    }
+       
+    if( ! link.isValid() ) {
+      std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
+                << "link is not valid" << std::endl;
+      return false;
+    }
+       
+    // Do different things depending on whether this variable already
+    // exists or not:
+    if( hasObjectLink( name ) ) {
+      // Find the right object:
+      const std::vector< std::string >& names = linkColNames();
+      for( size_t i = 0; i < names.size(); ++i ) {
+        if( names[ i ] != name ) continue;
+        // Extract the information out of the ElementLink:
+        linkColKeysNC()[ i ] = link.key();
+        linkColIndicesNC()[ i ] = link.index();
+        linkColClidsNC()[ i ] = ClassID_traits< CONTAINER >::ID();
+        // We're done:
+        return true;
       }
-   }
-
+      // Some error happened...
+      std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR Internal "
+                << "logic error found" << std::endl;
+      return false;
+    } else {
+      // Add a new object:
+      linkColNamesNC().push_back( name );
+      linkColKeysNC().push_back( link.key() );
+      linkColIndicesNC().push_back( link.index() );
+      linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
+      // And we're done:
+      return true;
+    }
+  }
+  
    template< class CONTAINER >
    ElementLink< CONTAINER >
    TrigComposite_v1::objectLink( const std::string& name ) const {
diff --git a/Trigger/TrigHypothesis/TrigBjetHypo/src/TrigBjetEtHypoAlgMT.cxx b/Trigger/TrigHypothesis/TrigBjetHypo/src/TrigBjetEtHypoAlgMT.cxx
index b6fe575d9da..b9c8b500004 100644
--- a/Trigger/TrigHypothesis/TrigBjetHypo/src/TrigBjetEtHypoAlgMT.cxx
+++ b/Trigger/TrigHypothesis/TrigBjetHypo/src/TrigBjetEtHypoAlgMT.cxx
@@ -97,9 +97,8 @@ StatusCode TrigBjetEtHypoAlgMT::execute_r( const EventContext& context ) const {
   // ========================================================================================================================== 
 
   // Decisions
-  std::unique_ptr< TrigCompositeUtils::DecisionContainer > outputDecision( new TrigCompositeUtils::DecisionContainer() );
-  std::unique_ptr< TrigCompositeUtils::DecisionAuxContainer > outputAuxDecision( new TrigCompositeUtils::DecisionAuxContainer() );
-  outputDecision->setStore( outputAuxDecision.get() );
+  SG::WriteHandle<TrigCompositeUtils::DecisionContainer> handle = TrigCompositeUtils::createAndStore( decisionOutput(), context ); 
+  auto outputDecisions = handle.ptr();
 
   // ==========================================================================================================================
   //    ** Compute Decisions
@@ -116,7 +115,7 @@ StatusCode TrigBjetEtHypoAlgMT::execute_r( const EventContext& context ) const {
     for ( unsigned int index(0); index<nDecisions; index++ ) {
       //      const std::string decisionName = name()+"_roi_"+std::to_string(index);
       //      ATH_MSG_DEBUG( "   ** " << decisionName );
-      newDecisions.push_back( TrigCompositeUtils::newDecisionIn( outputDecision.get() ) );//,decisionName ) );
+      newDecisions.push_back( TrigCompositeUtils::newDecisionIn( outputDecisions ) );//,decisionName ) );
     }
 
     bool pass = false;
@@ -140,18 +139,16 @@ StatusCode TrigBjetEtHypoAlgMT::execute_r( const EventContext& context ) const {
       ATH_MSG_DEBUG( "Linking Jets `" << m_jetLink.value() << "` to output decision." );
     }
     
-    for( unsigned int index(0); index<nDecisions; index++ )
-      TrigCompositeUtils::linkToPrevious( newDecisions.at(index),decisionInput().key(),counter );
+    for( unsigned int index(0); index<nDecisions; index++ ){
+      TrigCompositeUtils::linkToPrevious( newDecisions.at(index),decisionInput().key(),0 );
+    }
+
     counter++;
-  }
+    }
 
   // ==========================================================================================================================
   //    ** Store Output
   // ==========================================================================================================================
-
-  // Save Output Decisions
-  SG::WriteHandle< TrigCompositeUtils::DecisionContainer > handle =  SG::makeHandle( decisionOutput(), context );
-  CHECK( handle.record( std::move(outputDecision),std::move(outputAuxDecision) ) );
   ATH_MSG_DEBUG( "Exiting with " << handle->size() << " decisions" );
 
   return StatusCode::SUCCESS;
diff --git a/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2CaloHypoAlgMT.cxx b/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2CaloHypoAlgMT.cxx
index ec01a504f67..c85abd2c4bf 100644
--- a/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2CaloHypoAlgMT.cxx
+++ b/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2CaloHypoAlgMT.cxx
@@ -45,9 +45,10 @@ StatusCode TrigL2CaloHypoAlgMT::execute_r( const EventContext& context ) const {
 
 
   // new decisions
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore( aux.get() );
+
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
 
   // input for decision
   std::vector<ITrigL2CaloHypoTool::ClusterInfo> toolInput;
@@ -69,7 +70,7 @@ StatusCode TrigL2CaloHypoAlgMT::execute_r( const EventContext& context ) const {
     ATH_MSG_DEBUG ( "Cluster handle size: " << clusterHandle->size() << "..." );
 
     // create new decision
-    auto d = newDecisionIn( decisions.get(), name() );
+    auto d = newDecisionIn( decisions, name() );
 
 
     toolInput.emplace_back( d, roi, clusterHandle.cptr()->at(0), previousDecision );
@@ -95,8 +96,7 @@ StatusCode TrigL2CaloHypoAlgMT::execute_r( const EventContext& context ) const {
   }
  
   {// make output handle and debug
-    auto outputHandle = SG::makeHandle(decisionOutput(), context);
-    ATH_CHECK( outputHandle.record( std::move( decisions ), std::move( aux ) ) );
+
     ATH_MSG_DEBUG ( "Exit with "<<outputHandle->size() <<" decisions");
     TrigCompositeUtils::DecisionIDContainer allPassingIDs;
     if ( outputHandle.isValid() ) {
diff --git a/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2ElectronHypoAlgMT.cxx b/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2ElectronHypoAlgMT.cxx
index f7fdc12e90b..439a3922b24 100644
--- a/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2ElectronHypoAlgMT.cxx
+++ b/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2ElectronHypoAlgMT.cxx
@@ -7,6 +7,7 @@
 #include "AthViews/ViewHelper.h"
 
 
+using TrigCompositeUtils::createAndStore; 
 using TrigCompositeUtils::DecisionContainer;
 using TrigCompositeUtils::DecisionAuxContainer;
 using TrigCompositeUtils::DecisionIDContainer;
@@ -47,10 +48,9 @@ StatusCode TrigL2ElectronHypoAlgMT::execute_r( const EventContext& context ) con
 
   ATH_MSG_DEBUG( "Running with "<< previousDecisionsHandle->size() <<" implicit ReadHandles for previous decisions");
   
-  // new output
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore( aux.get() );
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
 
   // // extract mapping of cluster pointer to an index in the cluster decision collection
 
@@ -84,7 +84,7 @@ StatusCode TrigL2ElectronHypoAlgMT::execute_r( const EventContext& context ) con
     ATH_MSG_DEBUG ( "electron handle size: " << electronsHandle->size() << "..." );
 
     for ( auto electronIter = electronsHandle->begin(); electronIter != electronsHandle->end(); ++electronIter, electronCounter++ ) {
-      auto d = newDecisionIn( decisions.get() );
+      auto d = newDecisionIn( decisions );
       d->setObjectLink( "feature", ViewHelper::makeLink<xAOD::TrigElectronContainer>( *viewELInfo.link, electronsHandle, electronCounter ) );
       
       auto clusterPtr = (*electronIter)->emCluster();
@@ -111,9 +111,6 @@ StatusCode TrigL2ElectronHypoAlgMT::execute_r( const EventContext& context ) con
     ATH_CHECK( tool->decide( hypoToolInput ) );    
   } 
 
-  auto outputHandle = SG::makeHandle(decisionOutput(), context);
-  CHECK( outputHandle.record(std::move(decisions), std::move(aux) ) );
-  
   ATH_MSG_DEBUG( "Exiting with "<< outputHandle->size() <<" decisions");
   //debug
   for (auto outh: *outputHandle){
diff --git a/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2PhotonHypoAlgMT.cxx b/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2PhotonHypoAlgMT.cxx
index fe26291cb07..5eee805ee8a 100644
--- a/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2PhotonHypoAlgMT.cxx
+++ b/Trigger/TrigHypothesis/TrigEgammaHypo/src/TrigL2PhotonHypoAlgMT.cxx
@@ -7,7 +7,7 @@
 #include "AthViews/ViewHelper.h"
 
 
-
+using TrigCompositeUtils::createAndStore; 
 using TrigCompositeUtils::DecisionContainer;
 using TrigCompositeUtils::DecisionAuxContainer; 
 using TrigCompositeUtils::DecisionIDContainer; 
@@ -68,10 +68,9 @@ StatusCode TrigL2PhotonHypoAlgMT::execute_r( const EventContext& context ) const
   }
   ATH_MSG_DEBUG( "Cluster ptr to decision map has size " << clusterToIndexMap.size() );
 
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore( aux.get() );
-
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
 
   std::vector<TrigL2PhotonHypoTool::PhotonInfo> hypoToolInput;
  
@@ -89,7 +88,7 @@ StatusCode TrigL2PhotonHypoAlgMT::execute_r( const EventContext& context ) const
     ATH_MSG_DEBUG ( "electron handle size: " << photonsHandle->size() << "..." );
 
     for ( auto photonIter = photonsHandle->begin(); photonIter != photonsHandle->end(); ++photonIter, photonCounter++ ) {
-      auto d = newDecisionIn( decisions.get(), name() );
+      auto d = newDecisionIn( decisions, name() );
       d->setObjectLink( "feature", ViewHelper::makeLink<xAOD::TrigPhotonContainer>( *viewELInfo.link, photonsHandle, photonCounter ) );
       
       auto clusterPtr = (*photonIter)->emCluster();
@@ -116,8 +115,6 @@ StatusCode TrigL2PhotonHypoAlgMT::execute_r( const EventContext& context ) const
     ATH_CHECK( tool->decide( hypoToolInput ) );    
   } 
 
-  auto outputHandle = SG::makeHandle(decisionOutput(), context);
-  ATH_CHECK( outputHandle.record(std::move(decisions), std::move(aux) ) );
   
   ATH_MSG_DEBUG( "Exiting with "<< outputHandle->size() <<" decisions");
   //debug
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.cxx
index 13242dabd8c..b655c25ca09 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.cxx
@@ -53,11 +53,9 @@ StatusCode TrigJetHypoAlgMT::execute_r( const EventContext& context ) const {
 
   auto prevDecisions = h_prevDecisions.get();
 
-  // Make a new Decisions container which will contain the previous
-  // decisions, and the one for this hypo.
-  auto newDecisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  newDecisions->setStore(aux.get());
+  // new output decisions                                                      
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto newDecisions = outputHandle.ptr();
 
   // read in a jets collection, and obtain a bare pointer to it
   auto h_jets = SG::makeHandle(m_jetsKey, context );
@@ -77,8 +75,6 @@ StatusCode TrigJetHypoAlgMT::execute_r( const EventContext& context ) const {
  
 
   // output the decisions for all chains for this event.
-  auto outputHandle = SG::makeHandle(decisionOutput(), context);
-  CHECK( outputHandle.record( std::move( newDecisions ), std::move( aux ) ) );
   ATH_MSG_DEBUG ( "Exit with "<<outputHandle->size() <<" decisions"); 
 
 
@@ -100,12 +96,12 @@ StatusCode TrigJetHypoAlgMT::execute_r( const EventContext& context ) const {
 
 StatusCode
 TrigJetHypoAlgMT::decide(const xAOD::JetContainer* jets,
-                         std::unique_ptr<DecisionContainer>& nDecisions,
+                         DecisionContainer* nDecisions,
                          const DecisionContainer* oDecisions) const{
 
  
   auto previousDecision = (*oDecisions)[0];
-  auto newdecision = TrigCompositeUtils::newDecisionIn(nDecisions.get());
+  auto newdecision = TrigCompositeUtils::newDecisionIn(nDecisions);
 
   
   const TrigCompositeUtils::DecisionIDContainer previousDecisionIDs{
@@ -151,7 +147,7 @@ TrigJetHypoAlgMT::decide(const xAOD::JetContainer* jets,
 //     if (pass) {
 //       // create a new Decision object. This object has been placed in the
 //       // nDecisions container.
-//       auto decision = TrigCompositeUtils::newDecisionIn(nDecisions.get());
+//       auto decision = TrigCompositeUtils::newDecisionIn(nDecisions);
 //       TrigCompositeUtils::addDecisionID(decisionId, decision);
 //     }
 //     // what if does not pass?
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.h
index 12f6bde8781..c9284f39d28 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/TrigJetHypoAlgMT.h
@@ -32,7 +32,7 @@ class TrigJetHypoAlgMT : public ::HypoBase {
  private:
 
   StatusCode decide(const xAOD::JetContainer*,
-                    std::unique_ptr<TrigCompositeUtils::DecisionContainer>& newDecisions,
+                    TrigCompositeUtils::DecisionContainer* newDecisions,
                     const TrigCompositeUtils::DecisionContainer* previousDecisions
 		    /* , */
                     /* const ToolHandle<ITrigJetHypoToolMT>&xs */
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx
index c6fa2c52d67..66634e983a4 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMufastHypoAlg.cxx
@@ -65,9 +65,9 @@ StatusCode TrigMufastHypoAlg::execute_r( const EventContext& context ) const
   }  
   ATH_MSG_DEBUG( "Running with "<< previousDecisionsHandle->size() <<" implicit ReadHandles for previous decisions");
 
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore(aux.get());
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
   // end of common
  
 
@@ -94,7 +94,7 @@ StatusCode TrigMufastHypoAlg::execute_r( const EventContext& context ) const
     const xAOD::L2StandAloneMuon* muon = *muonEL;
 
     // create new decision
-    auto newd = newDecisionIn( decisions.get() );
+    auto newd = newDecisionIn( decisions );
 
     // push_back to toolInput
     toolInput.emplace_back( newd, roi, muon, previousDecision );
@@ -129,8 +129,6 @@ StatusCode TrigMufastHypoAlg::execute_r( const EventContext& context ) const
 
 
   {// make output handle and debug, in the base class
-    auto outputHandle = SG::makeHandle(decisionOutput(), context);
-    ATH_CHECK( outputHandle.record( std::move( decisions ), std::move( aux ) ) );
     ATH_MSG_DEBUG ( "Exit with "<<outputHandle->size() <<" decisions");
     TrigCompositeUtils::DecisionIDContainer allPassingIDs;
     if ( outputHandle.isValid() ) {
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuisoHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuisoHypoAlg.cxx
index 18222c06318..24be8036725 100644
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuisoHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuisoHypoAlg.cxx
@@ -61,9 +61,9 @@ StatusCode TrigMuisoHypoAlg::execute_r( const EventContext& context) const
   }  
   ATH_MSG_DEBUG( "Running with "<< previousDecisionsHandle->size() <<" implicit ReadHandles for previous decisions");
 
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore(aux.get());
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
   // end of common
  
   std::vector<TrigMuisoHypoTool::MuisoInfo> toolInput; 
@@ -83,7 +83,7 @@ StatusCode TrigMuisoHypoAlg::execute_r( const EventContext& context) const
     const xAOD::L2IsoMuon* muon = *muonEL;
 
     // create new decision
-    auto newd = newDecisionIn( decisions.get() );
+    auto newd = newDecisionIn( decisions );
 
     // push_back to toolInput
     toolInput.emplace_back( newd, muon, previousDecision );
@@ -115,8 +115,6 @@ StatusCode TrigMuisoHypoAlg::execute_r( const EventContext& context) const
 
 
   {// make output handle and debug, in the base class
-    auto outputHandle = SG::makeHandle(decisionOutput(), context);
-    ATH_CHECK( outputHandle.record( std::move( decisions ), std::move( aux ) ) );
     ATH_MSG_DEBUG ( "Exit with "<<outputHandle->size() <<" decisions");
     TrigCompositeUtils::DecisionIDContainer allPassingIDs;
     if ( outputHandle.isValid() ) {
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx
index dfc027b4d8d..1db2340bed6 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFCombinerHypoAlg.cxx
@@ -66,9 +66,9 @@ StatusCode TrigMuonEFCombinerHypoAlg::execute_r( const EventContext& context ) c
   }
   ATH_MSG_DEBUG( "Running with "<< previousDecisionsHandle->size() <<" implicit ReadHandles for previous decisions");
 
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore(aux.get());
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
   // end of common
   
   std::vector<TrigMuonEFCombinerHypoTool::MuonEFInfo> toolInput;
@@ -99,8 +99,8 @@ StatusCode TrigMuonEFCombinerHypoAlg::execute_r( const EventContext& context ) c
 
     const xAOD::Muon* muon = *muonEL;
 
-    // create new dicions
-    auto newd = newDecisionIn( decisions.get() );
+    // create new decisions
+    auto newd = newDecisionIn( decisions );
 
     // pussh_back to toolInput
     toolInput.emplace_back( newd, roi, muon, previousDecision );
@@ -133,8 +133,6 @@ StatusCode TrigMuonEFCombinerHypoAlg::execute_r( const EventContext& context ) c
   } // End of tool algorithms */	
 
   { // make output handle and debug, in the base class
-    auto outputHandle = SG::makeHandle( decisionOutput(), context );
-    ATH_CHECK( outputHandle.record( std::move(decisions), std::move(aux) ));
     ATH_MSG_DEBUG ( "Exit with " << outputHandle->size() << " decisions");
     TrigCompositeUtils::DecisionIDContainer allPassingIDs;
     if ( outputHandle.isValid() ) {
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx
index d296bf1d956..1a8f180b3e7 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFMSonlyHypoAlg.cxx
@@ -66,9 +66,9 @@ StatusCode TrigMuonEFMSonlyHypoAlg::execute_r( const EventContext& context ) con
   }
   ATH_MSG_DEBUG( "Running with "<< previousDecisionsHandle->size() <<" implicit ReadHandles for previous decisions");
 
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore(aux.get());
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
   // end of common
   
   std::vector<TrigMuonEFMSonlyHypoTool::MuonEFInfo> toolInput;
@@ -99,8 +99,8 @@ StatusCode TrigMuonEFMSonlyHypoAlg::execute_r( const EventContext& context ) con
 
     const xAOD::Muon* muon = *muonEL;
 
-    // create new dicions
-    auto newd = newDecisionIn( decisions.get() );
+    // create new decisions
+    auto newd = newDecisionIn( decisions );
 
     // pussh_back to toolInput
     toolInput.emplace_back( newd, roi, muon, previousDecision );
@@ -133,8 +133,6 @@ StatusCode TrigMuonEFMSonlyHypoAlg::execute_r( const EventContext& context ) con
   } // End of tool algorithms */	
 
   { // make output handle and debug, in the base class
-    auto outputHandle = SG::makeHandle( decisionOutput(), context );
-    ATH_CHECK( outputHandle.record( std::move(decisions), std::move(aux) ));
     ATH_MSG_DEBUG ( "Exit with " << outputHandle->size() << " decisions");
     TrigCompositeUtils::DecisionIDContainer allPassingIDs;
     if ( outputHandle.isValid() ) {
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx
index 4910d3ebf28..ab0f9afd912 100755
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigMuonEFTrackIsolationHypoAlg.cxx
@@ -66,9 +66,8 @@ StatusCode TrigMuonEFTrackIsolationHypoAlg::execute_r( const EventContext& conte
   ATH_MSG_DEBUG( "Running with "<< previousDecisionsHandle->size() <<" implicit ReadHandles for previous decisions");
 
   // prepare output decisions
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore(aux.get());
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
 
   std::vector<TrigMuonEFTrackIsolationHypoTool::EFIsolationMuonInfo> toolInput;
   size_t counter = 0;
@@ -96,7 +95,7 @@ StatusCode TrigMuonEFTrackIsolationHypoAlg::execute_r( const EventContext& conte
     const xAOD::Muon* muon = *muonEL;
 
     // create new dicions
-    auto newd = newDecisionIn( decisions.get() );
+    auto newd = newDecisionIn( decisions );
 
     toolInput.emplace_back( newd, roi, muon, previousDecision );
 
@@ -128,9 +127,7 @@ StatusCode TrigMuonEFTrackIsolationHypoAlg::execute_r( const EventContext& conte
     }
   } // End of tool algorithm
 
-  { // make output handle and debug, in the base class
-    auto outputHandle = SG::makeHandle( decisionOutput(), context );
-    ATH_CHECK( outputHandle.record( std::move( decisions ), std::move( aux ) ) );
+  { //  debu printout
     ATH_MSG_DEBUG ( "Exit with "<< outputHandle->size() <<" decisions");
     TrigCompositeUtils::DecisionIDContainer allPassingIDs;
     if ( outputHandle.isValid() ) {   
diff --git a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigmuCombHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigmuCombHypoAlg.cxx
index 54d9f58d7a3..9de510e8c80 100644
--- a/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigmuCombHypoAlg.cxx
+++ b/Trigger/TrigHypothesis/TrigMuonHypo/src/TrigmuCombHypoAlg.cxx
@@ -66,9 +66,9 @@ StatusCode TrigmuCombHypoAlg::execute_r(const EventContext& context) const
   }
   ATH_MSG_DEBUG( "Running with " << previousDecisionsHandle->size() << " implicit ReadHandles for previous decisions");
 
-  auto decisions = std::make_unique<DecisionContainer>();
-  auto aux = std::make_unique<DecisionAuxContainer>();
-  decisions->setStore(aux.get());
+  // new output decisions
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+  auto decisions = outputHandle.ptr();
   // end of common
 
   std::vector<TrigmuCombHypoTool::CombinedMuonInfo> toolInput;
@@ -98,7 +98,7 @@ StatusCode TrigmuCombHypoAlg::execute_r(const EventContext& context) const
     const xAOD::L2CombinedMuon* muComb = *muCombEL;
     
     // create new decisions
-    auto newd = newDecisionIn( decisions.get() );
+    auto newd = newDecisionIn( decisions );
 
     toolInput.emplace_back( TrigmuCombHypoTool::CombinedMuonInfo{ newd, muComb, muFast, previousDecision} );
 
@@ -120,9 +120,7 @@ StatusCode TrigmuCombHypoAlg::execute_r(const EventContext& context) const
     ATH_MSG_DEBUG("Go to " << tool);
     ATH_CHECK( tool->decide( toolInput ) );
   }
-  {// make output handle and debug, in the base class
-    auto outputHandle =  SG::makeHandle( decisionOutput(), context );
-    ATH_CHECK( outputHandle.record( std::move( decisions ), std::move( aux ) ) );
+  {// debug printout
     ATH_MSG_DEBUG( "Exit with " << outputHandle->size() << " decisions");
     TrigCompositeUtils::DecisionIDContainer allPassingIDs;
     if ( outputHandle.isValid() ) {
diff --git a/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt b/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt
index a599c31b901..c2ce23558e9 100644
--- a/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt
+++ b/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt
@@ -46,7 +46,7 @@ atlas_add_component( DecisionHandling
 atlas_add_test( TrigCompositeUtils_test
                 SOURCES test/TrigCompositeUtils_test.cxx
                 LINK_LIBRARIES  TestTools xAODTrigger DecisionHandlingLib
-                AthContainers )
+                AthContainers SGtests )
 
 atlas_add_test( Combinators_test
                 SOURCES test/Combinators_test.cxx
diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h
index b28e3cce3ff..dc0c230132d 100644
--- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h
+++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h
@@ -8,6 +8,7 @@
 #include <set>
 #include <memory>
 #include <functional>
+#include <iostream>
 
 #include "AthLinks/ElementLink.h"
 #include "AthLinks/ElementLinkVector.h"
@@ -15,6 +16,7 @@
 #include "StoreGate/WriteHandleKey.h"
 #include "StoreGate/ReadHandleKey.h"
 #include "StoreGate/WriteHandle.h"
+#include "GaudiKernel/ThreadLocalContext.h"
 
 #include "AthContainers/AuxElement.h"
 #include "xAODTrigger/TrigCompositeContainer.h"
@@ -22,25 +24,61 @@
 
 namespace TrigCompositeUtils {
 
-  // alias types, for readability and to simplify future evolution
+  /// alias types, for readability and to simplify future evolution
   typedef SG::WriteHandle<DecisionContainer> DecisionWriteHandle;
+
+  /**
+   * @brief Creates and right away records the Container CONT with the key.
+   * Returns the WriteHandle. 
+   * No Aux store.
+   * If possible provide the context that comes via an argument to execute_r 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 = Gaudi::Hive::currentContext());
+
+  /**
+   * @brief Creates and right away records the Container CONT with the key.
+   * Returns the WriteHandle. 
+   * With Aux store.
+   * If possible provide the context that comes via an argument to execute_r 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 = Gaudi::Hive::currentContext());
+
+  /**
+   * @brief Creates and right away records the DecisionContainer with the key.
+   * Returns the WriteHandle. 
+   * If possible provide the context that comes via an argument to execute_r otherwise it will default to looking it up which is slower.
+   **/
+  SG::WriteHandle<DecisionContainer> createAndStore( const SG::WriteHandleKey<DecisionContainer>& key, const EventContext& ctx = Gaudi::Hive::currentContext() );
+
   /**
-   * @brief creates and right away stores the DecisionContainer under the key
+   * @brief Creates and right away records the DecisionContainer using the provided WriteHandle.
    **/
-  DecisionWriteHandle createAndStore(const SG::WriteHandleKey<DecisionContainer>& key, const EventContext& ctx);
+
+  void createAndStore( SG::WriteHandle<DecisionContainer>& handle );
 
   /**
-   * @brief helper method to that created the Decision objects, places it in the container and returns
+   * @brief Helper method to create a Decision object, place it in the container and return a pointer to it.
    * This is to make this:
    * auto d = newDecisionIn(output);
    * instead of:
    * auto d = new Decision; 
    * output->push_back(d);    
-   * a version with the name assigns the name to the TC object
+   * If provided, the name is assigned to the TC object
+   * Note that the supplied DecisionContainer must have been recorded in the event store.
+   * If possible provide the context that comes via an argument to execute_r otherwise it will default to looking it up which is slower.
    **/  
-  Decision* newDecisionIn (DecisionContainer* dc);
-  Decision* newDecisionIn (DecisionContainer* dc, const std::string& name);
+  Decision* newDecisionIn ( DecisionContainer* dc, const std::string& name = "", const EventContext& ctx = Gaudi::Hive::currentContext() );
 
+  /**
+   * @brief Helper method to create a Decision object, place it in the container and return a pointer to it. RoI, view and feature links will be copied from the previous to the new decision and a "seed" link made between them
+   * @arg the container in which to place the new Decision
+   * @arg the previous decision to which the new one should be connected
+   * If provided, the name is assigned to the TC object
+   * Note that the supplied DecisionContainer must have been recorded in the event store.
+   **/ 
+Decision* newDecisionIn( DecisionContainer* dc, const Decision* dOld, const std::string& name = "", const EventContext& ctx = Gaudi::Hive::currentContext() );
 
   /**
    * @brief Appends the decision (given as ID) to the decision object
@@ -51,19 +89,24 @@ namespace TrigCompositeUtils {
 
       
   /**
-   * @brief Extracts DecisionIDs stored in the Decsion object 
+   * @brief Extracts DecisionIDs stored in the Decision object 
    **/
   void decisionIDs( const Decision* d, DecisionIDContainer& id );
 
   /**
-   * @brief Another variant of the above method
+   * @brief Another variant of the above method to access DecisionIDs stored in
+ the Decision object, returns const accessor
    **/
   const std::vector<int>& decisionIDs( const Decision* d ); 
+
+  /**
+   * @brief Another variant of the above method to access DecisionIDs stored in the Decision object, returns read/write accessor
+   **/ 
   std::vector<int>& decisionIDs( Decision* d );
 
   
   /**
-   * @brief return true if thre is no positive decision stored
+   * @brief return true if there is no positive decision stored
    **/
   bool allFailed( const Decision* d );
   
@@ -73,7 +116,7 @@ namespace TrigCompositeUtils {
   bool isAnyIDPassing( const Decision* d,  const DecisionIDContainer& required);
 
   /**
-   * @brief checks if required ID is in the set of the decisions
+   * @brief checks if required decision ID is in the set of IDs in the container
    **/
   bool passed( DecisionID id, const DecisionIDContainer& );
   
@@ -98,11 +141,8 @@ namespace TrigCompositeUtils {
    * @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
    **/
@@ -178,5 +218,6 @@ namespace TrigCompositeUtils {
 
 }
 
+#include "DecisionHandling/TrigCompositeUtils.icc"
 
 #endif // DecisionHandling_TrigCompositeUtils_h
diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc
new file mode 100644
index 00000000000..a11b4bb04e0
--- /dev/null
+++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc
@@ -0,0 +1,37 @@
+/*
+ *
+ */
+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_r 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>() ;
+    handle.record( std::move( data ) ).ignore();
+    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_r 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() );
+    handle.record( std::move( data ), std::move( aux )  ).ignore();
+    return handle;
+  }
+
+
+}
diff --git a/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref b/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref
index 5555caa3f91..c9d1c784d42 100644
--- a/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref
+++ b/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref
@@ -1,3 +1,36 @@
+ApplicationMgr    SUCCESS 
+====================================================================================================================================
+                                                   Welcome to ApplicationMgr (GaudiCoreSvc v30r3)
+                                          running on pc-tbed-pub-23.cern.ch on Thu Oct  4 17:39:52 2018
+====================================================================================================================================
+ApplicationMgr       INFO Application Manager Configured successfully
+EventLoopMgr      WARNING Unable to locate service "EventSelector" 
+EventLoopMgr      WARNING No events will be processed from external input.
+HistogramPersis...WARNING Histograms saving not required.
+ApplicationMgr       INFO Application Manager Initialized successfully
+ApplicationMgr Ready
+ClassIDSvc           INFO  getRegistryEntries: read 7465 CLIDRegistry entries for module ALL
+Context: s: 0  e: 0
+Current context: s: 0  e: 0
+ClassIDSvc           INFO  getRegistryEntries: read 372 CLIDRegistry entries for module ALL
+initialize SG::WriteHandleKey<DecisionContainer> whkT
+call createAndStore( whkT ) with default context, twice
+StoreGateSvc_Impl WARNING  setupProxy:: error setting up proxy for key arbitrary and clid 1333228823
+ Pre-existing valid DataProxy @0x29a4bd0 found in Store for key arbitrary with clid 1333228823
+StoreGateSvc_Impl WARNING record_impl: Problem setting up the proxy for object @0x29a50b0
+ recorded with key arbitrary of type xAOD::TrigCompositeContainer (CLID 1333228823) in DataObject @0x29a5400
+VarHandle(Store...  ERROR /build3/atnight/localbuilds/nightlies/master/athena/Control/StoreGate/src/VarHandleBase.cxx:734 (StatusCode SG::VarHandleBase::record_impl(std::unique_ptr<DataObject>, void*, bool, bool)): code 0: recordObject failed
+                    FATAL /cvmfs/atlas-nightlies.cern.ch/repo/sw/master/2018-09-25T2105/Athena/22.0.1/InstallArea/x86_64-slc6-gcc62-dbg/src/Control/StoreGate/StoreGate/WriteHandle.icc:887 (StatusCode SG::WriteHandle<T>::record(std::unique_ptr<_Tp>, std::unique_ptr<U>, bool) [with AUXSTORE = xAOD::TrigCompositeAuxContainer_v1; T = DataVector<xAOD::TrigComposite_v1>]): code 0: this->record(std::move(data))
+handle name "arbitrary" isPresent 1 isValid 1
+handle name "arbitrary" isPresent 1 isValid 0
+
+initialize SG::WriteHandleKey<DecisionContainer> whk1
+call createAndStore( whk1 ) with default context
+handle name myDecisions1 store StoreGateSvc_Impl
+initialize SG::WriteHandleKey<DecisionContainer> whk2
+call createAndStore( whk2, ctx )
+handle name myDecisions2 store StoreGateSvc_Impl container size 0
+testing insert decisions
 1 from d1
 2 from d1
 1 from d1 and d2
@@ -5,3 +38,39 @@
 3 from d1 and d2
  either 3 or 7 contained in d1 NO
  either 3 or 7 contained in d2 YES
+Call setObjectLink with a bad ElementLink that has no recorded collection. Expect cerr output to follow.
+xAOD::TrigComposite_v1::setObjectLink ERROR link has invalid key hash of zero
+Call setObjectLink with a bad ElementLink that has no corresponding collection. Expect cerr output to follow.
+xAOD::TrigComposite_v1::setObjectLink ERROR link is not valid
+
+New decision d3b with name & context 
+d3b: TrigComposite_v1 'd3b' link: name, key, index, CLID
+self, 1042135810, 3, 1333228823
+testlink, 1042135810, 1, 1333228823
+
+el2 1042135810 1
+d3: TrigComposite_v1 '' link: name, key, index, CLID
+self, 1042135810, 2, 1333228823
+seed, 1042135810, 1, 1333228823
+
+d4: TrigComposite_v1 '' link: name, key, index, CLID
+self, 1042135810, 4, 1333228823
+seed, 1042135810, 1, 1333228823
+
+el: key 1042135810 index 1
+create d5 
+set link 
+d5: TrigComposite_v1 'd5' link: name, key, index, CLID
+self, 1042135810, 5, 1333228823
+feature, 1042135810, 1, 1333228823
+
+create d6 
+d6: TrigComposite_v1 'd6' link: name, key, index, CLID
+self, 1042135810, 6, 1333228823
+feature, 1042135810, 1, 1333228823
+seed, 1042135810, 5, 1333228823
+
+get d5 feature link 
+get d6 feature link 
+compare feature links 
+get self and seed links 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
index 85740d83b60..0408728dccd 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/ComboHypo.cxx
@@ -68,10 +68,9 @@ StatusCode ComboHypo::copyDecisions( const DecisionIDContainer& passing, const E
   ATH_MSG_DEBUG( "Copying "<<passing.size()<<" positive decisions to outputs");
   for ( size_t input_counter = 0; input_counter < m_inputs.size(); ++input_counter ) {
 
-    auto outDecisions = std::make_unique<DecisionContainer>();
-    auto outDecAux = std::make_unique<DecisionAuxContainer>();
-    outDecisions->setStore( outDecAux.get() );
-    
+    // new output decisions
+    SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(m_outputs[input_counter], context ); 
+    auto outDecisions = outputHandle.ptr();    
 
     auto inputHandle = SG::makeHandle( m_inputs[input_counter], context );
     if ( inputHandle.isValid() ) {
@@ -88,7 +87,7 @@ 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.get() );
+	Decision*  newDec = newDecisionIn( outDecisions );
 	linkToPrevious( newDec, inputHandle.key(), i );      
 	for ( auto id: common ) {
 	  addDecisionID( id, newDec );
@@ -117,13 +116,11 @@ StatusCode ComboHypo::copyDecisions( const DecisionIDContainer& passing, const E
 	}
       }
     }
-    auto outHandle = SG::makeHandle( m_outputs[input_counter], context );
-    ATH_CHECK( outHandle.record( std::move( outDecisions ), std::move( outDecAux ) ) );
 
-    // debug:
+    // debug printout:
     if ( msgLvl(MSG::DEBUG)) {
-      ATH_MSG_DEBUG(outHandle.key() <<" with "<< outHandle->size() <<" decisions:");
-      for (auto outdecision:  *outHandle){
+      ATH_MSG_DEBUG(outputHandle.key() <<" with "<< outputHandle->size() <<" decisions:");
+      for (auto outdecision:  *outputHandle){
 	TrigCompositeUtils::DecisionIDContainer objDecisions;      
 	TrigCompositeUtils::decisionIDs( outdecision, objDecisions );    
 	ATH_MSG_DEBUG("Number of positive decisions for this output: " << objDecisions.size() );
diff --git a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
index cff14d6a26e..c36fc5a9658 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/InputMakerBase.cxx
@@ -67,33 +67,26 @@ StatusCode InputMakerBase::decisionInputToOutput(const EventContext& context, st
     }
     ATH_MSG_DEBUG( "Got input "<< inputKey.key()<<" with " << inputHandle->size() << " elements" );
     // create the output container
-    auto outDecisions = std::make_unique<TrigCompositeUtils::DecisionContainer>();
-    auto outDecAux = std::make_unique<TrigCompositeUtils::DecisionAuxContainer>();
-    outDecisions->setStore( outDecAux.get() );
-       
-    // loop over decisions retrieved from this input
+    TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
+    auto outDecisions = outputHandles[outputIndex].ptr();
+
+    // loop over input decisions retrieved from this input handle
     size_t input_counter =0;
-    for ( auto decision : *inputHandle){
+    for ( auto inpDecision : *inputHandle){
       // create new decision for each input	
-      TrigCompositeUtils::Decision*  newDec = TrigCompositeUtils::newDecisionIn( outDecisions.get() );
-      TrigCompositeUtils::linkToPrevious( newDec, inputKey.key(), input_counter );
+      TrigCompositeUtils::Decision*  newDec = TrigCompositeUtils::newDecisionIn( outDecisions, inpDecision, "", context );
       {
         //copy decisions ID
         TrigCompositeUtils::DecisionIDContainer objDecisions;      
-        TrigCompositeUtils::decisionIDs( decision, objDecisions );
+        TrigCompositeUtils::decisionIDs( inpDecision, objDecisions );
         for ( const HLT::Identifier& id: objDecisions ){
           TrigCompositeUtils::addDecisionID( id, newDec );
         }
       }
-      CHECK( decision->hasObjectLink("initialRoI" ) );  
-      auto roiEL = decision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
-      CHECK( roiEL.isValid() );
-      newDec->setObjectLink( "initialRoI", roiEL );
       input_counter++;	
-    } // loop over decisions
+    } // loop over input decisions
 
-    ATH_MSG_DEBUG( "Recording output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<<outDecisions->size()  <<" at index "<< outputIndex);
-    CHECK( outputHandles[outputIndex].record( std::move( outDecisions ), std::move( outDecAux ) ) );
+    ATH_MSG_DEBUG( "Recorded output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<<outDecisions->size()  <<" at index "<< outputIndex);
     outputIndex++;	       
   } // end of first loop over input keys
 
diff --git a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx
index a9de3c10881..2eb7027bc45 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx
@@ -65,6 +65,8 @@ StatusCode RoRSeqFilter::execute() {
 
   auto inputHandles  = m_inputKeys.makeHandles();
   auto outputHandles = m_outputKeys.makeHandles();
+  //std::vector<SG::ReadHandle<DecisionContainer>> inputHandles;
+  //std::vector<SG::WriteHandle<DecisionContainer>> outputHandles;
 
   bool validInputs=false;
   for ( auto inputHandle: inputHandles ) {
@@ -84,37 +86,32 @@ StatusCode RoRSeqFilter::execute() {
   size_t outputIndex = 0;
   if ( m_mergeInputs ) {
 
-    auto output    = std::make_unique< TrigCompositeUtils::DecisionContainer > ();
-    auto outputAux = std::make_unique< TrigCompositeUtils::DecisionAuxContainer > ();
-    output->setStore( outputAux.get() );
-
+    ATH_MSG_DEBUG( "Recording " <<  m_outputKeys[ 0 ].key() ); 
+    TrigCompositeUtils::createAndStore(outputHandles[0]);
+    TrigCompositeUtils::DecisionContainer* output = outputHandles[0].ptr();
     for ( auto inputKey: m_inputKeys ) {
       auto inputHandle = SG::makeHandle( inputKey );
       if( inputHandle.isValid() )
         passCounter += copyPassing( *inputHandle, inputKey.key(),  *output );
     }
-
-    ATH_MSG_DEBUG( "Recording " <<  m_outputKeys[ 0 ].key() ); 
-    CHECK( outputHandles[0].record( std::move(output), std::move(outputAux) ) );
     outputIndex++;
 
   } else {
 
     for ( auto inputKey: m_inputKeys ) {
+      // already made handles, so this code could be simplified to a loop over inputHandles.
       auto inputHandle = SG::makeHandle( inputKey );
 
       if( not inputHandle.isValid() ) continue;  // implicit
       
       ATH_MSG_DEBUG( "Checking inputHandle "<< inputKey.key() <<" with " << inputHandle->size() <<" elements");
-      auto output    = std::make_unique< TrigCompositeUtils::DecisionContainer > ();
-      auto outputAux = std::make_unique< TrigCompositeUtils::DecisionAuxContainer > ();
-      output->setStore( outputAux.get() );
-      
+      TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
+      TrigCompositeUtils::DecisionContainer* output = outputHandles[outputIndex].ptr();
       passCounter += copyPassing( *inputHandle, inputKey.key(), *output );
 
       if (output->size() >0){ // data handle reduction       
-        ATH_MSG_DEBUG( "Recording output key " <<  m_outputKeys[ outputIndex ].key() <<" of size "<<output->size()  <<" at index "<< outputIndex);
-        CHECK( outputHandles[outputIndex].record( std::move(output), std::move(outputAux) ) );
+        ATH_MSG_DEBUG( "Recorded output key " <<  m_outputKeys[ outputIndex ].key() <<" of size "<<output->size()  <<" at index "<< outputIndex);
+        // record done by createAndStore above
       }
       outputIndex++; // Keep the mapping of inputKey<->outputKey correct
     }
@@ -153,6 +150,7 @@ size_t RoRSeqFilter::copyPassing( const TrigCompositeUtils::DecisionContainer& i
     if ( not intersection.empty() ) {      
       TrigCompositeUtils::Decision* decisionCopy = TrigCompositeUtils::newDecisionIn( &output, name() );
       *decisionCopy = *inputDecision; // copies auxdata from one auxstore to the other
+      // future improvement: could use newDecisionIn(&output,input,name which internally does the linkToPrevious, then no longer need to pass the key
       TrigCompositeUtils::linkToPrevious(decisionCopy, inputKey, i); // Update seed
       passCounter ++;
       ATH_MSG_DEBUG("Input satisfied at least one active chain");
diff --git a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx
index 575d1888e71..2fd9a93e8da 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx
@@ -4,6 +4,8 @@
 #include "StoreGate/WriteHandle.h"
 #include "StoreGate/ReadHandle.h"
 #include "AthContainers/AuxElement.h"
+#include "GaudiKernel/EventContext.h"
+#include "GaudiKernel/GaudiException.h"
 
 #include "StoreGate/WriteHandle.h"
 #include "DecisionHandling/TrigCompositeUtils.h"
@@ -15,7 +17,7 @@ static SG::AuxElement::ConstAccessor< std::vector<int> > readOnlyAccessor( "deci
 
 namespace TrigCompositeUtils {  
 
-  DecisionWriteHandle createAndStore( const SG::WriteHandleKey<DecisionContainer>& key, const EventContext& ctx ) {
+  SG::WriteHandle<DecisionContainer> createAndStore( const SG::WriteHandleKey<DecisionContainer>& key, const EventContext& ctx ) {
     SG::WriteHandle<DecisionContainer> handle( key, ctx );
     auto data = std::make_unique<DecisionContainer>() ;
     auto aux = std::make_unique<DecisionAuxContainer>() ;
@@ -23,17 +25,49 @@ namespace TrigCompositeUtils {
     handle.record( std::move( data ), std::move( aux )  ).ignore();
     return handle;
   }
-  
-  Decision* newDecisionIn ( DecisionContainer* dc ) {
+
+  void createAndStore( SG::WriteHandle<DecisionContainer>& handle ) {
+    auto data = std::make_unique<DecisionContainer>() ;
+    auto aux = std::make_unique<DecisionAuxContainer>() ;
+    data->setStore( aux.get() );
+    handle.record( std::move( data ), std::move( aux )  ).ignore();
+  }
+
+  Decision* newDecisionIn ( DecisionContainer* dc, const std::string& name, const EventContext& ctx ) {
     Decision * x = new Decision;
     dc->push_back( x );
-    readWriteAccessor( *x ).size(); // fake operation just to make the decsions decoration
+    readWriteAccessor( *x ).size(); // fake operation just to make the decisions decoration
+    size_t index = dc->size() - 1;
+    // make self link, useful to copy for seed link in a successor, but requires that DecisionContainer is already recorded in SG.
+    ElementLink<DecisionContainer> el(*dc, index, ctx);
+    if ( ! x->setObjectLink( "self", el ) ){ 
+      std::cerr << "TrigCompositeUtils::newDecisionIn ERROR failed to set self EL with key, maybe the DecisionContainer is not yet recorded in the event store? " << el.key() << std::endl;
+      throw GaudiException(" failed to set self EL ", "TrigCompositeUtils::newDecisionIn", StatusCode::FAILURE);
+    }
+    if ( ! name.empty() ) {
+      x->setName( name );
+    }
     return x;
   }
-  Decision* newDecisionIn (DecisionContainer* dc, const std::string& name) {
-    Decision* d = newDecisionIn( dc );
-    d->setName( name );
-    return d;
+
+  Decision* newDecisionIn ( DecisionContainer* dc, const Decision* dOld, const std::string& name, const EventContext& ctx ) {
+    Decision* dNew =  newDecisionIn( dc, name, ctx);
+   if ( dOld->hasObjectLink("roi" ) ){
+     dNew->copyLinkFrom(dOld,"roi");
+   }
+   else if ( dOld->hasObjectLink("initialRoI") ){
+     dNew->copyLinkFrom(dOld,"initialRoI","roi");
+   }
+   if ( dOld->hasObjectLink("view" ) ){
+     dNew->copyLinkFrom(dOld,"view");
+   }
+   if ( dOld->hasObjectLink("feature" ) ){
+     dNew->copyLinkFrom(dOld,"feature");
+   }
+   if ( dOld->hasObjectLink("self" ) ){
+     dNew->copyLinkFrom(dOld,"self","seed"); // make use of self-link 
+   }
+   return dNew;
   }
 
   void addDecisionID( DecisionID id,  Decision* d ) {   
@@ -76,7 +110,6 @@ namespace TrigCompositeUtils {
     d->setObjectLink( "seed", ElementLink<DecisionContainer>( previousCollectionKey, previousIndex ) );
   }
 
-
   bool hasLinkToPrevious( const Decision* d ) {
     return d->hasObjectLink( "seed" );
   }
@@ -140,3 +173,4 @@ namespace TrigCompositeUtils {
   }
   
 }
+
diff --git a/Trigger/TrigSteer/DecisionHandling/src/TriggerSummaryAlg.cxx b/Trigger/TrigSteer/DecisionHandling/src/TriggerSummaryAlg.cxx
index 6ffa61ca983..5bdc223042b 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/TriggerSummaryAlg.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/TriggerSummaryAlg.cxx
@@ -71,11 +71,10 @@ StatusCode TriggerSummaryAlg::execute_r(const EventContext& context) const
   // check for an evident error, this is HLT chain not mentioned at the L1
   // that is the only reason we pull the L1 here
 
-  auto summaryCont = std::make_unique<TrigCompositeUtils::DecisionContainer>();
-  auto summaryAuxCont = std::make_unique<TrigCompositeUtils::DecisionAuxContainer>();
-  summaryCont->setStore( summaryAuxCont.get() );
+  SG::WriteHandle<TrigCompositeUtils::DecisionContainer> summaryHandle = TrigCompositeUtils::createAndStore(m_summaryKey, context ); 
+  auto summaryCont = summaryHandle.ptr();
 
-  auto summaryObj = TrigCompositeUtils::newDecisionIn( summaryCont.get() );
+  auto summaryObj = TrigCompositeUtils::newDecisionIn( summaryCont );
   summaryObj->setName( "passing" );
   for ( auto id: allPassingIDs ) {
     TrigCompositeUtils::addDecisionID( id, summaryObj );
@@ -86,8 +85,6 @@ StatusCode TriggerSummaryAlg::execute_r(const EventContext& context) const
   //   CHECK( buildHLTResult( result ) );
   // }
   
-  auto summaryHandle = SG::makeHandle( m_summaryKey, context );
-  CHECK( summaryHandle.record( std::move( summaryCont ), std::move( summaryAuxCont ) ) );
 
   for ( auto& tool: m_outputTools ) {
     CHECK( tool->createOutput( context ) );
diff --git a/Trigger/TrigSteer/DecisionHandling/test/TrigCompositeUtils_test.cxx b/Trigger/TrigSteer/DecisionHandling/test/TrigCompositeUtils_test.cxx
index e23d076d2f4..446e54a1e09 100644
--- a/Trigger/TrigSteer/DecisionHandling/test/TrigCompositeUtils_test.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/test/TrigCompositeUtils_test.cxx
@@ -3,26 +3,95 @@
 */
 
 #include <iostream>
+#include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/WriteHandle.h"
+#include "StoreGate/WriteHandleKey.h"
+#include "GaudiKernel/EventContext.h"
+#include "SGTools/TestStore.h"
+#include "TestTools/initGaudi.h"
 #include "TestTools/expect.h"
 #include "DecisionHandling/TrigCompositeUtils.h"
-
 #include "xAODTrigger/TrigCompositeAuxContainer.h"
 
 int main() {
+
   using namespace TrigCompositeUtils;
   xAOD::TrigComposite::s_throwOnCopyError = true;
 
-  auto dc = std::make_unique<DecisionContainer>();
-  auto decisionAux = std::make_unique<DecisionAuxContainer>();
-  dc->setStore( decisionAux.get() );  
-
-
+  // initialize Gaudi, SG
+  ISvcLocator* pSvcLoc;
+  Athena_test::initGaudi(pSvcLoc); 
+  StoreGateSvc* pSG(0);
+  assert( pSvcLoc->service("StoreGateSvc", pSG, true).isSuccess() );
+
+  // Create a context
+  IProxyDict* xdict = &*pSG;
+  xdict = pSG->hiveProxyDict();
+  EventContext ctx(0,0);
+  ctx.setExtension( Atlas::ExtendedEventContext(xdict) );
+  Gaudi::Hive::setCurrentContext (ctx);
+  std::cout << "Context: " << ctx << std::endl;
+
+
+  // check current context
+  const EventContext& ctx1 = Gaudi::Hive::currentContext();
+  std::cout << "Current context: " << ctx1 << std::endl;
+
+  // create handle and record tests
+
+  /* calling createAndStore is equivalent to:
+  SG::WriteHandle<DecisionContainer> wh1( whk1 );
+  auto data = std::make_unique<DecisionContainer>() ;
+  auto aux = std::make_unique<DecisionAuxContainer>() ;
+  data->setStore( aux.get() );
+  assert( wh1.record( std::move( data ), std::move( aux )  ).isSuccess());
+  DecisionContainer* dc =wh1.ptr()
+  */
+
+  // Test to cause and error in createAndStore by recording the same key twice
+  SG::WriteHandleKey<DecisionContainer> whkT ( "arbitrary" );
+  std::cout << "initialize SG::WriteHandleKey<DecisionContainer> whkT" << std::endl;
+  assert( whkT.initialize().isSuccess() );
+  std::cout << "call createAndStore( whkT ) with default context, twice" << std::endl;
+  SG::WriteHandle<DecisionContainer> whT1 = createAndStore( whkT );
+  SG::WriteHandle<DecisionContainer> whT2 = createAndStore( whkT );
+  // There will be WARNING ERROR and FATAL messages from the above line
+  std::cout << "handle name \"" << whT1.name() << "\" isPresent " << whT1.isPresent()<< " isValid " << whT1.isValid() << std::endl;
+  std::cout << "handle name \"" << whT2.name() << "\" isPresent " << whT2.isPresent()<< " isValid " << whT2.isValid() << std::endl;
+  assert( whT1.isValid() ); // it worked
+  assert( ! whT2.isValid() ); // it failed
+  std::cout << std::endl;
+
+  SG::WriteHandleKey<DecisionContainer> whk1 ( "myDecisions1" );
+  std::cout << "initialize SG::WriteHandleKey<DecisionContainer> whk1" << std::endl;
+  assert( whk1.initialize().isSuccess() );
+  std::cout << "call createAndStore( whk1 ) with default context" << std::endl;
+  SG::WriteHandle<DecisionContainer> wh1 = createAndStore( whk1 );
+  std::cout << "handle name " << wh1.name() << " store " << wh1.store() << std::endl;
+  VALUE( wh1.store() ) EXPECTED ( "StoreGateSvc_Impl" );
+  assert( wh1.isValid() );
+
+  SG::WriteHandleKey<DecisionContainer> whk2 ( "myDecisions2" );
+  std::cout << "initialize SG::WriteHandleKey<DecisionContainer> whk2" << std::endl;
+  assert( whk2.initialize().isSuccess() );
+  std::cout << "call createAndStore( whk2, ctx )" << std::endl;
+  SG::WriteHandle<DecisionContainer> wh2 = createAndStore( whk2, ctx );
+  DecisionContainer* dc2 = wh2.ptr();  
+  std::cout << "handle name " << wh2.name() << " store " << wh2.store() << " container size " << dc2->size() << std::endl;
+  VALUE( wh2.name() ) EXPECTED ( "myDecisions2" );
+  VALUE( wh2.store() ) EXPECTED ( "StoreGateSvc_Impl" );
+  VALUE( dc2->size() ) EXPECTED ( 0 );
+  assert( wh2.isValid() );
+
+  DecisionContainer* dc = dc2;
+
+  std::cout << "testing insert decisions" << std::endl;
   // try insertions
-  auto d1 = newDecisionIn( dc.get() );
+  auto d1 = newDecisionIn( dc, "d1" );
   addDecisionID( 1, d1 );
   addDecisionID( 2, d1 );
 
-  auto d2 = newDecisionIn( dc.get() );
+  auto d2 = newDecisionIn( dc );
   addDecisionID( 1, d2 );
   addDecisionID( 3, d2 );
 
@@ -30,8 +99,7 @@ int main() {
   decisionIDs( d1, ids );
 
   for ( auto id: ids )
-    std::cout << id << " from d1\n"; 
-  
+    std::cout << id << " from d1\n";   
 
   decisionIDs( d2, ids );
   for ( auto id: ids )
@@ -55,30 +123,82 @@ int main() {
   
   // double inserts
 
-  auto d3 = newDecisionIn( dc.get() );
+  auto d3 = newDecisionIn( dc );
   addDecisionID( 95, d3 );
   addDecisionID( 99, d3 );
   addDecisionID( 99, d3 );
   auto storedDecisions  = d3->getDetail<std::vector<int>>( "decisions" );
-  VALUE( storedDecisions.size() ) EXPECTED ( 2 );
-  VALUE( ( int )storedDecisions.front() ) EXPECTED ( 95 );
-  VALUE( ( int )storedDecisions.back() ) EXPECTED ( 99 );
-
-
-  
-  ElementLink<DecisionContainer> el("CollKey", 1);
-  d3->setObjectLink( "seed", el );
-  
+  VALUE ( storedDecisions.size() ) EXPECTED ( 2 );
+  VALUE ( ( int )storedDecisions.front() ) EXPECTED ( 95 );
+  VALUE ( ( int )storedDecisions.back() ) EXPECTED ( 99 );
+
+  // Make an EL with an invalid (zero) hash key and try to add it to a Decision
+  auto data1 = std::make_unique<DecisionContainer>() ;
+  auto aux1 = std::make_unique<DecisionAuxContainer>() ;
+  data1->setStore( aux1.get() );
+  data1->push_back(d1);
+  std::cout << "Call setObjectLink with a bad ElementLink that has no recorded collection. Expect cerr output to follow." << std::endl;
+  ElementLink<DecisionContainer> badEL1( *data1, 0 );
+  VALUE ( d3->setObjectLink( "bad", badEL1 ) ) EXPECTED ( false );
+  // this fails, and cerr output also expected
+
+  // Make an EL that is invalid, e.g. no container, and try to add it to a Decision
+  std::cout << "Call setObjectLink with a bad ElementLink that has no corresponding collection. Expect cerr output to follow." << std::endl; 
+  ElementLink<DecisionContainer> badEL2( "CollectionKeyThatDoesNotExist", 0 );
+  VALUE ( d3->setObjectLink( "bad", badEL2 ) ) EXPECTED ( false );
+  // this fails, and cerr output also expected
+
+  // Make, store and retrieve a "seed" link
+  ElementLink<DecisionContainer> el( *dc, 1 );
+  assert( d3->setObjectLink( "seed", el ) );
   ElementLink<DecisionContainer > resEl = d3->objectLink<DecisionContainer>("seed");
   VALUE( resEl.index() ) EXPECTED ( el.index() );
   VALUE( resEl.key() ) EXPECTED ( el.key() );
-  
-  auto d4 = newDecisionIn( dc.get() );
-  copyLinks(d3, d4);
-  ElementLink<DecisionContainer > resElCopied = d4->objectLink<DecisionContainer>("seed");
-  VALUE( resElCopied.index() ) EXPECTED ( el.index() );
-  VALUE( resElCopied.key() ) EXPECTED ( el.key() );
 
+  // Make a new decision, with name and context
+  std::cout << std::endl;
+  std::cout << "New decision d3b with name & context " << std::endl;
+  auto d3b = newDecisionIn( dc, "d3b", ctx );
+  // Make, store and retrieve a "seed" link, with context
+  ElementLink<DecisionContainer> el2( *dc, 1, ctx );
+  assert ( d3b->setObjectLink( "testlink", el2 ) );
+  std::cout << "d3b: " << *d3b << std::endl;
+  std::cout << "el2 " << el2.key() << " " << el2.index() << std::endl;
+  ElementLink<DecisionContainer > resEl2 = d3b->objectLink<DecisionContainer>("testlink");
+  VALUE( resEl2.index() ) EXPECTED ( el2.index() );
+  VALUE( resEl2.key() ) EXPECTED ( el2.key() );
+
+  // check copyLinks (copies all)
+  auto d4 = newDecisionIn( dc );
+  VALUE ( copyLinks(d3, d4) ) EXPECTED ( true );
+  std::cout << "d3: " << *d3 << std::endl;
+  std::cout << "d4: " << *d4 << std::endl;
+  std::cout << "el: key " << el.key() << " index " << el.index() << std::endl;
+  ElementLink<DecisionContainer > resElCopied = d4->objectLink<DecisionContainer>("seed");
+  VALUE ( resElCopied.index() ) EXPECTED ( el.index() );
+  VALUE ( resElCopied.key() ) EXPECTED ( el.key() );
+
+  // check new decision with automatically propagated links from previous decision 
+  std::cout << "create d5 " << std::endl;
+  auto d5 = newDecisionIn ( dc, "d5" );
+  std::cout << "set link " << std::endl;
+  assert( d5->setObjectLink( "feature", el ) );
+  std::cout << "d5: " << *d5 << std::endl;
+  std::cout << "create d6 " << std::endl;
+  auto d6 = newDecisionIn ( dc, d5, "d6" );
+  std::cout << "d6: " << *d6 << std::endl;
+  std::cout << "get d5 feature link " << std::endl;
+  ElementLink<DecisionContainer > d5feature = d5->objectLink<DecisionContainer>("feature");
+  std::cout << "get d6 feature link " << std::endl;
+  ElementLink<DecisionContainer > d6feature = d6->objectLink<DecisionContainer>("feature");
+  std::cout << "compare feature links " << std::endl;
+  VALUE ( d5feature.index() ) EXPECTED ( d6feature.index() );
+  VALUE ( d5feature.key() ) EXPECTED ( d6feature.key() );
+  std::cout << "get self and seed links " << std::endl;
+  auto d5self = d5->objectLink<DecisionContainer>("self");
+  auto d6seed = d6->objectLink<DecisionContainer>("seed");
+  VALUE ( d5self.index()  ) EXPECTED ( d6seed.index() );
+  VALUE ( d5self.key()  ) EXPECTED ( d6seed.key() );
 
   return 0;
   
diff --git a/Trigger/TrigSteer/L1Decoder/src/CreateFullScanRoI.cxx b/Trigger/TrigSteer/L1Decoder/src/CreateFullScanRoI.cxx
index bb8235213db..5dc84ebea37 100644
--- a/Trigger/TrigSteer/L1Decoder/src/CreateFullScanRoI.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/CreateFullScanRoI.cxx
@@ -3,6 +3,7 @@
 */
 
 #include "CreateFullScanRoI.h"
+#include "DecisionHandling/TrigCompositeUtils.h"
 
 CreateFullScanRoI::CreateFullScanRoI(const std::string& name, ISvcLocator* pSvcLocator) :
   AthReentrantAlgorithm(name, pSvcLocator)
@@ -26,16 +27,12 @@ StatusCode CreateFullScanRoI::finalize()
   return StatusCode::SUCCESS;
 }
 
-StatusCode CreateFullScanRoI::execute_r(const EventContext& context) const
+StatusCode CreateFullScanRoI::execute_r(const EventContext& ctx) const
 {
-
-  auto roisCollection = std::make_unique<TrigRoiDescriptorCollection>();
+  using namespace TrigCompositeUtils;
+  SG::WriteHandle<TrigRoiDescriptorCollection> handle1 = createAndStoreNoAux(m_roisKey, ctx ); 
+  auto roisCollection = handle1.ptr();
   auto roi = new TrigRoiDescriptor( true ); // this is FullScan RoI
   roisCollection->push_back( roi );
-
-
-  auto handle = SG::makeHandle( m_roisKey, context );
-  CHECK( handle.record( std::move( roisCollection ) ) );
   return StatusCode::SUCCESS;
 }
-
diff --git a/Trigger/TrigSteer/L1Decoder/src/EMRoIsUnpackingTool.cxx b/Trigger/TrigSteer/L1Decoder/src/EMRoIsUnpackingTool.cxx
index f49db042ae0..aa18cb8d7e5 100644
--- a/Trigger/TrigSteer/L1Decoder/src/EMRoIsUnpackingTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/EMRoIsUnpackingTool.cxx
@@ -76,12 +76,14 @@ StatusCode EMRoIsUnpackingTool::unpack( const EventContext& ctx,
 					const ROIB::RoIBResult& roib,
 					const HLT::IDSet& activeChains ) const {
   using namespace TrigCompositeUtils;
-  auto decisionOutput = std::make_unique<DecisionContainer>();
-  auto decisionAux    = std::make_unique<DecisionAuxContainer>();
-  decisionOutput->setStore( decisionAux.get() );  
-  auto trigRoIs = std::make_unique< TrigRoiDescriptorCollection >();
-  auto recRoIs  = std::make_unique< DataVector<LVL1::RecEmTauRoI> >();
 
+  // create and record the collections needed
+  SG::WriteHandle<TrigRoiDescriptorCollection> handle1 = createAndStoreNoAux(m_trigRoIsKey, ctx ); 
+  auto trigRoIs = handle1.ptr();
+  SG::WriteHandle< DataVector<LVL1::RecEmTauRoI> > handle2 = createAndStoreNoAux( m_recRoIsKey, ctx );
+  auto recRoIs = handle2.ptr();
+  SG::WriteHandle<DecisionContainer> handle3 = createAndStore(m_decisionsKey, ctx ); 
+  auto decisionOutput = handle3.ptr();
 
   // RoIBResult contains vector of EM fragments
   for ( auto& emTauFragment : roib.eMTauResult() ) {
@@ -102,7 +104,7 @@ StatusCode EMRoIsUnpackingTool::unpack( const EventContext& ctx,
 			  
       ATH_MSG_DEBUG( "RoI word: 0x" << MSG::hex << std::setw( 8 ) << roIWord << MSG::dec );      
 
-      auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput.get() );
+      auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput );
 
       std::vector<unsigned> passedThresholdIDs;
       for ( auto th: m_emThresholds ) {
@@ -131,25 +133,12 @@ StatusCode EMRoIsUnpackingTool::unpack( const EventContext& ctx,
   {
     using namespace Monitored;
     auto RoIsCount = MonitoredScalar::declare( "count", trigRoIs->size() );
-    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs.get(), &TrigRoiDescriptor::phi );
-    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs.get(), &TrigRoiDescriptor::eta );
+    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs, &TrigRoiDescriptor::phi );
+    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs, &TrigRoiDescriptor::eta );
     MonitoredScope::declare( m_monTool,  RoIsCount, RoIsEta, RoIsPhi );
   }
 
   ATH_MSG_DEBUG( "Unpacked " <<  trigRoIs->size() << " RoIs" );
-  // recording
-  {
-    SG::WriteHandle<TrigRoiDescriptorCollection> handle( m_trigRoIsKey, ctx );
-    CHECK( handle.record ( std::move( trigRoIs ) ) );
-  }
-  {
-    SG::WriteHandle<DataVector<LVL1::RecEmTauRoI>> handle( m_recRoIsKey, ctx );
-    CHECK( handle.record( std::move( recRoIs ) ) );    
-  }
-  {
-    auto handle = SG::makeHandle( m_decisionsKey, ctx );
-    CHECK ( handle.record( std::move( decisionOutput ), std::move( decisionAux )  ) );
-  }
 
   return StatusCode::SUCCESS; // what else
   
diff --git a/Trigger/TrigSteer/L1Decoder/src/FakeRoIView.cxx b/Trigger/TrigSteer/L1Decoder/src/FakeRoIView.cxx
deleted file mode 100644
index 767e7d94ad6..00000000000
--- a/Trigger/TrigSteer/L1Decoder/src/FakeRoIView.cxx
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-/*
- * Author: Piotr Sarna
- */
-
-#include <vector>
-#include <fstream>
-#include <stdexcept>
-#include <string>
-
-#include "CxxUtils/make_unique.h"
-#include "L1Decoder/TrigIdentifiers.h"
-#include "TrigT1Interfaces/RecEmTauRoI.h"
-#include "TrigSteeringEvent/TrigRoiDescriptorCollection.h"
-#include "TrigSteeringEvent/Lvl1Result.h"
-#include "TrigT1Result/RoIBResult.h"
-#include "TrigConfL1Data/L1DataDef.h"
-#include "TrigConfHLTData/HLTUtils.h"
-
-#include "./FakeRoIView.h"
-#include "AthViews/View.h"
-
-namespace AthViews {
-  FakeRoIView::FakeRoIView(const std::string& name, ISvcLocator* pSvcLocator):
-    ::AthAlgorithm( name, pSvcLocator ),
-    m_trigRoIs("OutputRoIs"),
-    m_recEMTauRoIs("OutputRecEMTauRoIs"),
-    m_decisions("OutputDecisions"),
-    m_decisionsAux("OutputDecisionsAux."),
-    m_views("all_views"),
-    m_configSvc("TrigConf::LVL1ConfigSvc/LVL1ConfigSvc", name)
-  {
-    // outputs
-    declareProperty("OutputRoIs", m_trigRoIs, "Name of the RoIs object produced by the unpacker");
-    declareProperty("OutputRecEMTauRoIs", m_recEMTauRoIs, "Name of the RoIs object produced by the unpacker");
-    declareProperty("OutputDecisions", m_decisions, "Name of the decisions object (wiht links to specific RoIs)");
-    declareProperty("OutputDecisionsAux", m_decisionsAux, "Name of the decisions object (wiht links to specific RoIs) - aux");
-
-    // input
-    declareProperty("InputFilename", m_inputFilename, "FakeROI input filename");
-
-    // views
-    declareProperty("Views", m_views, "Name prefix of the generated views");//name of colleciton of views
-    declareProperty("ViewName", m_viewName, "View name" ); //name of Views added to the collection
-    //    declareProperty( "ViewNames", m_viewNames, "View names" ); //name of Views added to the collection
-
-
-    // services
-    declareProperty("LVL1ConfigSvc", m_configSvc, "LVL1 Config Service");
-  }
-
-
-
-  StatusCode FakeRoIView::initialize() {
-    CHECK(m_configSvc.retrieve());
-
-    if ( m_viewName != "" )
-      {
-	std::string hackString;
-	//Make a view data dependency for each output handle
-	for ( auto handle : outputHandles() )
-	  {
-	    if (handle->fullKey().clid() != m_views.clid()){
-	      //Make a copy of the output dependency for this view
-	      std::string hackString = getProperty( "ExtraOutputs" ).toString();
-	      std::stringstream clidString;
-	      clidString << handle->fullKey().clid();
-	      hackString = hackString.substr( 0, hackString.size() - 1 ) + "(" + clidString.str() + ",'" + m_viewName + "_" + handle->objKey() + "'),]";
-	      CHECK( setProperty( "ExtraOutputs", hackString ) );
-	    }
-	  }
-      }
-
-
-    return StatusCode::SUCCESS;
-  }
-
-  StatusCode FakeRoIView::start() {
-    if (m_inputFilename.empty()) {
-      ATH_MSG_WARNING("Provided InputFilename parameter is empty");
-      return StatusCode::RECOVERABLE;
-    }
-
-    try
-      {
-	m_currentRowNumber = 0;
-	m_inputData = parseInputFile();
-      }
-    catch (const std::exception& ex)
-      {
-	ATH_MSG_WARNING(ex.what());
-	return StatusCode::RECOVERABLE;
-      }
-
-    ATH_MSG_DEBUG("Input file parsed successfully. Data:");
-
-    for (auto& fragment : m_inputData) {
-      for (auto& fakeRoI : fragment) {
-	const char* const delim = ", ";
-	std::ostringstream debugPassedTresholdIDs;
-	std::copy(fakeRoI.passedThresholdIDs.begin(), fakeRoI.passedThresholdIDs.end(), std::ostream_iterator<std::string>(debugPassedTresholdIDs, delim));
-
-	ATH_MSG_DEBUG("Eta: " + std::to_string(fakeRoI.eta) +
-		      ", Phi: " + std::to_string(fakeRoI.phi) +
-		      ", Word: " + std::to_string(fakeRoI.word) +
-		      ", PassedThresholdIDs: " + debugPassedTresholdIDs.str());
-      }
-    }
-
-    using namespace TrigConf;
-    const ThresholdConfig* thresholdConfig = m_configSvc->thresholdConfig();
-    for (auto caloType : std::vector<L1DataDef::TriggerType>{ L1DataDef::EM/*, L1DataDef::TAU*/ }) {
-      for (TriggerThreshold * th : thresholdConfig->getThresholdVector(caloType)) {
-	if (th != nullptr)
-	  ATH_MSG_DEBUG("Found threshold in the configuration: " << th->name() << " of ID: " << HLTUtils::string2hash(th->name(), "TE"));
-	m_emtauThresholds.push_back(th);
-      }
-    }
-
-    return StatusCode::SUCCESS;
-  }
-
-  StatusCode FakeRoIView::execute() {
-
-   //Create the view object
-    m_views.record( CxxUtils::make_unique< ViewContainer >() );
-    SG::View * newView = new SG::View( m_viewName, -1 );
-    m_views->push_back( newView );
-   
-
-  // redirect handles to that view
-    CHECK(m_trigRoIs.setProxyDict(newView));
-    CHECK(m_recEMTauRoIs.setProxyDict(newView));
-    CHECK(m_decisions.setProxyDict(newView));
-    CHECK(m_decisionsAux.setProxyDict(newView));
-
- 
-    // define output
-    //m_trigRoIs
-	auto trigRoIs     = new TrigRoiDescriptorCollection();
-    auto recEMTauRoIs = new DataVector<LVL1::RecEmTauRoI>();
-    auto decisions    = new xAOD::TrigCompositeContainer();
-    auto decisionsAux = new xAOD::TrigCompositeAuxContainer();
-    //decisions->setStore(decisionsAux.ptr());
-    decisions->setStore(decisionsAux);
-
-
-    //    m_trigRoIs.record( CxxUtils::make_unique< TrigRoiDescriptorCollection >());
-    // m_recEMTauRoIs.record ( CxxUtils::make_unique< DataVector<LVL1::RecEmTauRoI> >());
-    //m_decisions.record ( CxxUtils::make_unique< xAOD::TrigCompositeContainer >());
-    //m_decisionsAux.record (CxxUtils::make_unique< xAOD::TrigCompositeAuxContainer>());
-    //m_decisions->setStore(m_decisionsAux.ptr());
-
- 
-
-    for (auto& fakeRoI : m_inputData[m_currentRowNumber]) {
-      auto recRoI = new LVL1::RecEmTauRoI(fakeRoI.word, &m_emtauThresholds);
-      recEMTauRoIs->push_back(recRoI);
-
-      auto trigRoI = new TrigRoiDescriptor(fakeRoI.word, 0u, 0u,
-					   fakeRoI.eta, fakeRoI.eta - 0.1, fakeRoI.eta + 0.1,
-					   fakeRoI.phi, fakeRoI.phi - 0.1, fakeRoI.phi + 0.1);
-      trigRoIs->push_back(trigRoI);
-
-
-      ATH_MSG_DEBUG("RoI word: 0x" << MSG::hex << std::setw(8) << fakeRoI.word << ", threshold pattern " << MSG::dec);
-      std::vector<TriggerElementID> passedThresholdIDs;
-      for ( const auto& th: fakeRoI.passedThresholdIDs ) {
-	passedThresholdIDs.push_back(TrigConf::HLTUtils::string2hash(th, "TE"));
-	ATH_MSG_DEBUG("Threshold " << th << " id: " << MSG::hex << passedThresholdIDs.back() << MSG::dec);
-      }
-
-	
-      xAOD::TrigComposite * decision = new xAOD::TrigComposite();
-      decisions->push_back(decision);
-      decision->setDetail("Passed", passedThresholdIDs);
-      //auto el=ElementLink<TrigRoiDescriptorCollection>(m_trigRoIs.name(), m_trigRoIs->size() - 1,newView);
-    //  decision->setObjectLink("initialRoI", ElementLink<TrigRoiDescriptorCollection>(m_trigRoIs.name(), trigRoIs->size() - 1,newView));
-      //decision->setObjectLink("initialRecRoI", ElementLink<DataVector<LVL1::RecEmTauRoI>>(m_recEMTauRoIs.name(), recEMTauRoIs->size() - 1, newView));
-   
-    }
-
-    ATH_MSG_DEBUG("Found "<< trigRoIs->size() <<" RoIs and "<< decisions->size() <<" decisions in this event");
-    ++m_currentRowNumber;
-    m_currentRowNumber %= m_inputData.size();
-
-
-  //   auto trigRoIs = CxxUtils::make_unique< TrigRoiDescriptorCollection >();
-//     auto recEMTauRoIs = CxxUtils::make_unique< DataVector<LVL1::RecEmTauRoI> >();
-//	 auto decisions = CxxUtils::make_unique< xAOD::TrigCompositeContainer >();
-  //   auto decisionsAux = CxxUtils::make_unique< xAOD::TrigCompositeAuxContainer>();
-
-    m_trigRoIs.record (CxxUtils::make_unique< TrigRoiDescriptorCollection >(*trigRoIs));			     
-//    ATH_CHECK( m_trigRoIs.record (std::move(trigRoIs)).isSuccess());
-    m_recEMTauRoIs.record (CxxUtils::make_unique< DataVector<LVL1::RecEmTauRoI> >(*recEMTauRoIs));
-//	ATH_CHECK( m_recEMTauRoIs.record (std::move(recEMTauRoIs)).isSuccess());
-    m_decisions.record(CxxUtils::make_unique< xAOD::TrigCompositeContainer >(*decisions));
-    //ATH_CHECK( m_decisions.record(std::move(decisions)).isSuccess() );  
-	m_decisionsAux.record(CxxUtils::make_unique< xAOD::TrigCompositeAuxContainer>(*decisionsAux));
-//	ATH_CHECK( m_decisionsAux.record(std::move(decisionsAux)).isSuccess() );
-    unsigned int size=0;
-	for (auto dec: *m_decisions){
-      dec->setObjectLink("initialRoI", ElementLink<TrigRoiDescriptorCollection>(m_trigRoIs.name(),size ,newView));
-	  dec->setObjectLink("initialRecRoI", ElementLink<DataVector<LVL1::RecEmTauRoI>>(m_recEMTauRoIs.name(), size, newView));
-	  size++;
-    }
- //   (*(m_decisions->begin()))->setObjectLink("initialRoI", ElementLink<TrigRoiDescriptorCollection>(m_trigRoIs.name(), m_trigRoIs->size() - 1,newView));
-   // (*(m_decisions->begin()))->setObjectLink("initialRecRoI", ElementLink<DataVector<LVL1::RecEmTauRoI>>(m_recEMTauRoIs.name(), m_recEMTauRoIs->size() - 1, newView));
-    //m_trigRoIs.record( CxxUtils::make_unique< TrigRoiDescriptorCollection >());
-    //m_recEMTauRoIs.record ( CxxUtils::make_unique< DataVector<LVL1::RecEmTauRoI> >());
-    //m_decisions.record ( CxxUtils::make_unique< xAOD::TrigCompositeContainer >());
-    //m_decisionsAux.record (CxxUtils::make_unique< xAOD::TrigCompositeAuxContainer>());
-    //m_decisions->setStore(m_decisionsAux.ptr());
-
-
-    return StatusCode::SUCCESS;
-  }
-
-  StatusCode FakeRoIView::finalize() {
-    return StatusCode::SUCCESS;
-  }
-
-  std::vector<std::vector<FakeRoIView::SingleFakeRoIView>> FakeRoIView::parseInputFile() {
-    const char* whiteSpaceChars = " \t\n\r\f\v";
-    auto rtrim = [whiteSpaceChars](std::string& s) { s.erase(s.find_last_not_of(whiteSpaceChars) + 1); };
-    auto ltrim = [whiteSpaceChars](std::string& s) { s.erase(0, s.find_first_not_of(whiteSpaceChars)); };
-    auto trim = [&rtrim, &ltrim](std::string& s) { ltrim(s); rtrim(s); };
-
-    std::vector<std::vector<FakeRoIView::SingleFakeRoIView>> result;
-    unsigned lineNumber = 0;
-    std::string line;
-
-    std::ifstream inputFile(m_inputFilename);
-
-    if (!inputFile.good())
-      {
-	throw std::invalid_argument("File " + m_inputFilename + "does not exists or is corrupted");
-      }
-
-    while (getline(inputFile, line))
-      {
-	trim(line);
-
-	if (line.empty()) continue;
-
-	result.push_back(parseInputFileLine(line, ++lineNumber));
-      }
-
-    if (result.size() == 0) {
-      throw std::invalid_argument("File " + m_inputFilename + " does not contain any RoI");
-    }
-
-    return result;
-  }
-
-  std::vector<FakeRoIView::SingleFakeRoIView> FakeRoIView::parseInputFileLine(const std::string& line, unsigned lineNumber) {
-    std::vector<FakeRoIView::SingleFakeRoIView> result;
-    unsigned roiNumber = 0;
-    std::stringstream inputLine(line);
-    std::string roi;
-
-    while (getline(inputLine, roi, ';'))
-      {
-	result.push_back(parseInputRoI(roi, lineNumber, ++roiNumber));
-      }
-
-    return result;
-  }
-
-  FakeRoIView::SingleFakeRoIView FakeRoIView::parseInputRoI(const std::string& roi, unsigned lineNumber, unsigned roiNumber) {
-    FakeRoIView::SingleFakeRoIView result;
-    std::stringstream inputRoi(roi);
-    std::string roiElement;
-    unsigned roiElementNumber = 0;
-
-    std::vector<std::function<void(const std::string&)>> fillResultFunctors;
-    fillResultFunctors.push_back([&](const std::string& eta) { result.eta = stod(eta); });
-    fillResultFunctors.push_back([&](const std::string& phi) { result.phi = stod(phi); });
-    fillResultFunctors.push_back([&](const std::string& word) { result.word = stoul(word); });
-    fillResultFunctors.push_back([&](const std::string& passedThresholdID) { result.passedThresholdIDs.push_back(passedThresholdID); });
-
-    while (getline(inputRoi, roiElement, ','))
-      {
-	if (roiElementNumber > 2) { roiElementNumber = 3; }
-
-	try
-	  {
-	    fillResultFunctors[roiElementNumber++](roiElement);
-	  }
-	catch (const std::exception& ex)
-	  {
-	    throw std::invalid_argument("Exception encoruated while parsing line " + std::to_string(lineNumber) + ", roi " + std::to_string(roiNumber) + ". Exception: " + ex.what());
-	  }
-      }
-
-    return result;
-  }
-
-
-}
diff --git a/Trigger/TrigSteer/L1Decoder/src/FakeRoIView.h b/Trigger/TrigSteer/L1Decoder/src/FakeRoIView.h
deleted file mode 100644
index bfceadc6bf2..00000000000
--- a/Trigger/TrigSteer/L1Decoder/src/FakeRoIView.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-/*
- * Author: Piotr Sarna
- */
-
-#ifndef L1Decoder_FakeRoIView_h
-#define L1Decoder_FakeRoIView_h
-
-#include "AthenaBaseComps/AthAlgorithm.h"
-
-#include "TrigConfInterfaces/ILVL1ConfigSvc.h"
-#include "TrigConfL1Data/ThresholdConfig.h"
-#include "TrigConfL1Data/TriggerThreshold.h"
-
-#include "xAODTrigger/TrigCompositeContainer.h"
-#include "xAODTrigger/TrigCompositeAuxContainer.h"
-#include "TrigT1Interfaces/RecEmTauRoI.h"
-#include "TrigSteeringEvent/TrigRoiDescriptorCollection.h"
-#include "TrigT1Result/RoIBResult.h"
-
-//#include "AthViews/AthViewAlgorithm.h"
-#include "AthViews/View.h"
-//#include "EventInfo/EventInfo.h"
-
-namespace AthViews {
-
-  class FakeRoIView
-    : public ::AthAlgorithm 
-    {
-    public:
-      FakeRoIView(const std::string& name, ISvcLocator* pSvcLocator);
-      virtual StatusCode initialize() override;
-      virtual StatusCode start() override;
-      virtual StatusCode execute() override;
-      virtual StatusCode finalize() override;
-      
-    private:
-      
-      /// Default constructor: 
-      FakeRoIView();
-
-      struct SingleFakeRoIView {
-	double eta;
-	double phi;
-	uint32_t word;
-	std::vector<std::string> passedThresholdIDs;
-      };
-      
-      std::vector<std::vector<SingleFakeRoIView>> parseInputFile();
-      std::vector<SingleFakeRoIView> parseInputFileLine(const std::string& line, unsigned lineNumber);
-      SingleFakeRoIView parseInputRoI(const std::string& roi, unsigned lineNumber, unsigned roiNumber);
-      
-      std::vector<TrigConf::TriggerThreshold*> m_emtauThresholds;
-      
-      SG::WriteHandle< TrigRoiDescriptorCollection > m_trigRoIs;
-      SG::WriteHandle< DataVector<LVL1::RecEmTauRoI> > m_recEMTauRoIs;
-      SG::WriteHandle< xAOD::TrigCompositeContainer > m_decisions;
-      SG::WriteHandle< xAOD::TrigCompositeAuxContainer > m_decisionsAux;
-
-      SG::WriteHandle< ViewContainer > m_views;
-      std::string  m_viewName;
-      //      std::vector< std::string > m_viewNames;
-      ServiceHandle<TrigConf::ILVL1ConfigSvc> m_configSvc; //!< access to trigger menu
-      
-      // can demand objects 
-      
-      std::string m_inputFilename;
-      std::vector<std::vector<FakeRoIView::SingleFakeRoIView>> m_inputData;
-      unsigned m_currentRowNumber;
-    };
-  
-}//> end namespace AthViews
-#endif
diff --git a/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx b/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx
index 44bbfa04750..9ea3c5c422c 100644
--- a/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/JRoIsUnpackingTool.cxx
@@ -53,16 +53,17 @@ StatusCode JRoIsUnpackingTool::unpack( const EventContext& ctx,
 				       const ROIB::RoIBResult& roib,
 				       const HLT::IDSet& activeChains ) const {
   using namespace TrigCompositeUtils;
-  auto decisionOutput = std::make_unique<DecisionContainer>();
-  auto decisionAux    = std::make_unique<DecisionAuxContainer>();
-  decisionOutput->setStore( decisionAux.get() );  
-  auto trigRoIs = std::make_unique< TrigRoiDescriptorCollection >();
-  auto recRoIs  = std::make_unique< DataVector<LVL1::RecJetRoI> >();
+  // create and record the collections needed
+  SG::WriteHandle<TrigRoiDescriptorCollection> handle1 = createAndStoreNoAux(m_trigRoIsKey, ctx ); 
+  auto trigRoIs = handle1.ptr();
+  SG::WriteHandle< DataVector<LVL1::RecJetRoI> > handle2 = createAndStoreNoAux( m_recRoIsKey, ctx );
+  auto recRoIs = handle2.ptr();
+  SG::WriteHandle<DecisionContainer> handle3 = createAndStore(m_decisionsKey, ctx ); 
+  auto decisionOutput = handle3.ptr();
 
- 
-  auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput.get() );  
+
+  auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput );  
   decision->setObjectLink( "initialRoI", ElementLink<TrigRoiDescriptorCollection>( m_fsRoIKey, 0 ) );
-  
   auto roiEL = decision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
   CHECK( roiEL.isValid() );
   ATH_MSG_DEBUG("Linked new Decision to the FS roI");
@@ -88,8 +89,6 @@ StatusCode JRoIsUnpackingTool::unpack( const EventContext& ctx,
       trigRoIs->push_back( trigRoI );
       */
       ATH_MSG_DEBUG( "RoI word: 0x" << MSG::hex << std::setw( 8 ) << roIWord << MSG::dec );      
-
-
       
       for ( auto th: m_jetThresholds ) {
 	ATH_MSG_VERBOSE( "Checking if the threshold " << th->name() << " passed" );
@@ -125,27 +124,13 @@ StatusCode JRoIsUnpackingTool::unpack( const EventContext& ctx,
   {
     using namespace Monitored;
     auto RoIsCount = MonitoredScalar::declare( "count", trigRoIs->size() );
-    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs.get(), &TrigRoiDescriptor::phi );
-    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs.get(), &TrigRoiDescriptor::eta );
+    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs, &TrigRoiDescriptor::phi );
+    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs, &TrigRoiDescriptor::eta );
     MonitoredScope::declare( m_monTool,  RoIsCount, RoIsEta, RoIsPhi );
   }
 
   ATH_MSG_DEBUG( "Number of decision IDs associated with FS RoI: " <<  TrigCompositeUtils::decisionIDs( decision ).size()  );
 
 
-  // recording
-  {
-    SG::WriteHandle<TrigRoiDescriptorCollection> handle( m_trigRoIsKey, ctx );
-    ATH_CHECK( handle.record ( std::move( trigRoIs ) ) );
-  }
-  {
-    auto handle = SG::makeHandle( m_recRoIsKey, ctx );
-    ATH_CHECK( handle.record( std::move( recRoIs ) ) );    
-  }
-  {
-    auto handle = SG::makeHandle( m_decisionsKey, ctx );
-    ATH_CHECK ( handle.record( std::move( decisionOutput ), std::move( decisionAux )  ) );
-  }
-
   return StatusCode::SUCCESS; // what else
 }
diff --git a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
index 2ff51b5f360..69930d8318c 100644
--- a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.cxx
@@ -2,8 +2,11 @@
 /*
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
+#include "StoreGate/WriteHandle.h"
+#include "GaudiKernel/EventContext.h"
 #include "xAODTrigger/TrigCompositeAuxContainer.h"
 #include "TrigConfHLTData/HLTUtils.h"
+#include "DecisionHandling/TrigCompositeUtils.h"
 #include "L1Decoder.h"
 
 L1Decoder::L1Decoder(const std::string& name, ISvcLocator* pSvcLocator)
@@ -84,9 +87,18 @@ StatusCode L1Decoder::execute_r (const EventContext& ctx) const {
     ATH_CHECK( handle.record ( std::move( fsRoIsColl ) ) );
   }
 
+
+  SG::WriteHandle<DecisionContainer> handle = TrigCompositeUtils::createAndStore( m_chainsKey, ctx );
+  auto chainsInfo = handle.ptr();
+
+  /*
   auto chainsInfo = std::make_unique<DecisionContainer>();
   auto chainsAux = std::make_unique<DecisionAuxContainer>();
   chainsInfo->setStore(chainsAux.get());  
+  ATH_MSG_DEBUG("Recording chains");
+  auto handle = SG::makeHandle( m_chainsKey, ctx );
+  ATH_CHECK( handle.record( std::move( chainsInfo ), std::move( chainsAux ) ) );
+  */
 
   HLT::IDVec l1SeededChains;
   ATH_CHECK( m_ctpUnpacker->decode( *roib, l1SeededChains ) );
@@ -95,8 +107,8 @@ StatusCode L1Decoder::execute_r (const EventContext& ctx) const {
   HLT::IDVec activeChains;  
 
   ATH_CHECK( m_prescaler->prescaleChains( ctx, l1SeededChains, activeChains ) );    
-  ATH_CHECK( saveChainsInfo( l1SeededChains, chainsInfo.get(), "l1seeded" ) );
-  ATH_CHECK( saveChainsInfo( activeChains, chainsInfo.get(), "unprescaled" ) );
+  ATH_CHECK( saveChainsInfo( l1SeededChains, chainsInfo, "l1seeded", ctx ) );
+  ATH_CHECK( saveChainsInfo( activeChains, chainsInfo, "unprescaled", ctx ) );
 
   // for now all the chains that were pre-scaled are st to re-run
   HLT::IDVec rerunChains;  
@@ -104,7 +116,7 @@ StatusCode L1Decoder::execute_r (const EventContext& ctx) const {
 		       activeChains.begin(), activeChains.end(),
 		       std::back_inserter(rerunChains) );
 
-  ATH_CHECK( saveChainsInfo( rerunChains, chainsInfo.get(), "rerun" ) );
+  ATH_CHECK( saveChainsInfo( rerunChains, chainsInfo, "rerun", ctx ) );
 
   // Do cost monitoring, this utilises the HLT_costmonitor chain
   if (m_enableCostMonitoring) {
@@ -128,12 +140,6 @@ StatusCode L1Decoder::execute_r (const EventContext& ctx) const {
   }
 
 
-
-  ATH_MSG_DEBUG("Recording chains");
-
-  auto handle = SG::makeHandle( m_chainsKey, ctx );
-  ATH_CHECK( handle.record( std::move( chainsInfo ), std::move( chainsAux ) ) );
-
   return StatusCode::SUCCESS;  
 }
 
@@ -142,10 +148,9 @@ StatusCode L1Decoder::finalize() {
 }
 
 
-StatusCode L1Decoder::saveChainsInfo(const HLT::IDVec& chains, xAOD::TrigCompositeContainer* storage, const std::string& type) const {
+StatusCode L1Decoder::saveChainsInfo(const HLT::IDVec& chains, xAOD::TrigCompositeContainer* storage, const std::string& type, const EventContext& ctx) const {
   using namespace TrigCompositeUtils;
-  Decision* d = newDecisionIn( storage );
-  d->setName(type);
+  Decision* d = newDecisionIn( storage, type, ctx );
   for ( auto c: chains)
     addDecisionID(c.numeric(), d);
   return StatusCode::SUCCESS;
diff --git a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
index 0122671d98c..dff2b0dcbcf 100644
--- a/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
+++ b/Trigger/TrigSteer/L1Decoder/src/L1Decoder.h
@@ -39,8 +39,9 @@ protected: // protected to support unit testing
   virtual StatusCode readConfiguration(); 
   
   StatusCode saveChainsInfo(const HLT::IDVec& chains,
-			    xAOD::TrigCompositeContainer* storage,
-			    const std::string& type) const;
+                            xAOD::TrigCompositeContainer* storage,
+                            const std::string& type,
+                            const EventContext& ctx) const;
   
 private:
 
diff --git a/Trigger/TrigSteer/L1Decoder/src/METRoIsUnpackingTool.cxx b/Trigger/TrigSteer/L1Decoder/src/METRoIsUnpackingTool.cxx
index 27152f7cf24..58e50af7eac 100644
--- a/Trigger/TrigSteer/L1Decoder/src/METRoIsUnpackingTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/METRoIsUnpackingTool.cxx
@@ -65,9 +65,8 @@ StatusCode METRoIsUnpackingTool::unpack( const EventContext& ctx,
 					const ROIB::RoIBResult& roib,
 					const HLT::IDSet& activeChains ) const {
   using namespace TrigCompositeUtils;
-  auto decisionOutput = std::make_unique<DecisionContainer>();
-  auto decisionAux    = std::make_unique<DecisionAuxContainer>();
-  decisionOutput->setStore( decisionAux.get() );  
+  SG::WriteHandle<DecisionContainer> handle = createAndStore(m_decisionsKey, ctx ); 
+  auto decisionOutput = handle.ptr();
 
   HLT::IDSet activeMETchains;
   // see if any chain we care of is active
@@ -75,7 +74,7 @@ StatusCode METRoIsUnpackingTool::unpack( const EventContext& ctx,
 			m_allMETChains.begin(), m_allMETChains.end(), 
 			std::inserter(activeMETchains, activeMETchains.end() ) );
 			
-  auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput.get() );
+  auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput );
   for ( auto c: activeMETchains ) addDecisionID( c, decision );
   ATH_MSG_DEBUG("Unpacking MET RoI for " << activeMETchains.size() << " chains");
 
@@ -100,10 +99,5 @@ StatusCode METRoIsUnpackingTool::unpack( const EventContext& ctx,
   if ( (not activeMETchains.empty()) and not foundMETRoI) { 
     ATH_MSG_WARNING( "" << activeMETchains.size() << " active MET chains while missing  MET RoI" );
   }
-  {
-    auto handle = SG::makeHandle( m_decisionsKey, ctx );
-    CHECK ( handle.record( std::move( decisionOutput ), std::move( decisionAux )  ) );
-  }
-
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigSteer/L1Decoder/src/MURoIsUnpackingTool.cxx b/Trigger/TrigSteer/L1Decoder/src/MURoIsUnpackingTool.cxx
index b6885302232..379476043be 100644
--- a/Trigger/TrigSteer/L1Decoder/src/MURoIsUnpackingTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/MURoIsUnpackingTool.cxx
@@ -57,12 +57,13 @@ StatusCode MURoIsUnpackingTool::unpack( const EventContext& ctx,
                                         const ROIB::RoIBResult& roib,
                                         const HLT::IDSet& activeChains ) const {
   using namespace TrigCompositeUtils;
-  auto decisionOutput = std::make_unique<DecisionContainer>();
-  auto decisionAux    = std::make_unique<DecisionAuxContainer>();
-  decisionOutput->setStore( decisionAux.get() );
-
-  auto trigRoIs = std::make_unique< TrigRoiDescriptorCollection >();
-  auto recRoIs  = std::make_unique< DataVector<LVL1::RecMuonRoI> >();
+  // create and record the collections needed
+  SG::WriteHandle<TrigRoiDescriptorCollection> handle1 = createAndStoreNoAux(m_trigRoIsKey, ctx ); 
+  auto trigRoIs = handle1.ptr();
+  SG::WriteHandle< DataVector<LVL1::RecMuonRoI> > handle2 = createAndStoreNoAux( m_recRoIsKey, ctx );
+  auto recRoIs = handle2.ptr();
+  SG::WriteHandle<DecisionContainer> handle3 = createAndStore(m_decisionsKey, ctx ); 
+  auto decisionOutput = handle3.ptr();
 
   for ( auto& roi : roib.muCTPIResult().roIVec() ) {    
     const uint32_t roIWord = roi.roIWord();
@@ -82,7 +83,7 @@ StatusCode MURoIsUnpackingTool::unpack( const EventContext& ctx,
     
     ATH_MSG_DEBUG( "RoI word: 0x" << MSG::hex << std::setw( 8 ) << roIWord );
     
-    auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput.get() );
+    auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput );
     decision->setObjectLink( "initialRoI", ElementLink<TrigRoiDescriptorCollection>( m_trigRoIsKey.key(), trigRoIs->size()-1 ) );
     decision->setObjectLink( "initialRecRoI", ElementLink<DataVector<LVL1::RecMuonRoI>>( m_recRoIsKey.key(), recRoIs->size()-1 ) );
     
@@ -104,23 +105,10 @@ StatusCode MURoIsUnpackingTool::unpack( const EventContext& ctx,
   {
     using namespace Monitored;
     auto RoIsCount = MonitoredScalar::declare( "count", trigRoIs->size() );
-    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs.get(), &TrigRoiDescriptor::phi );
-    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs.get(), &TrigRoiDescriptor::eta );
+    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs, &TrigRoiDescriptor::phi );
+    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs, &TrigRoiDescriptor::eta );
     MonitoredScope::declare( m_monTool,  RoIsCount, RoIsEta, RoIsPhi );
   }
-  // recording
-  {
-    auto handle = SG::makeHandle( m_trigRoIsKey, ctx );
-    CHECK( handle.record( std::move( trigRoIs ) ) );
-  }
-  {
-    auto handle = SG::makeHandle( m_recRoIsKey, ctx );
-    CHECK( handle.record( std::move( recRoIs ) ) );
-  }
-  {
-    auto handle = SG::makeHandle(  m_decisionsKey, ctx );
-    CHECK( handle.record( std::move( decisionOutput ), std::move( decisionAux ) ) );
-  }
   return StatusCode::SUCCESS;
 }
 
diff --git a/Trigger/TrigSteer/L1Decoder/src/RerunRoIsUnpackingTool.cxx b/Trigger/TrigSteer/L1Decoder/src/RerunRoIsUnpackingTool.cxx
index b8efa0023ab..1b6b730c09b 100644
--- a/Trigger/TrigSteer/L1Decoder/src/RerunRoIsUnpackingTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/RerunRoIsUnpackingTool.cxx
@@ -38,10 +38,9 @@ StatusCode RerunRoIsUnpackingTool::unpack(const EventContext& ctx,
 					  const ROIB::RoIBResult& ,
 					  const HLT::IDSet& activeChains) const {
   using namespace TrigCompositeUtils;
-  auto decisionOutput = std::make_unique<DecisionContainer>();
-  auto decisionAux    = std::make_unique<DecisionAuxContainer>();
-  decisionOutput->setStore( decisionAux.get() );  
-  
+  SG::WriteHandle<DecisionContainer> outputHandle = createAndStore( m_decisionsKey, ctx );
+  auto decisionOutput = outputHandle.ptr();
+
   auto sourceHandle = SG::makeHandle( m_sourceKey, ctx );
 
   for ( auto sourceDecision: *sourceHandle.cptr() ) {
@@ -59,7 +58,7 @@ StatusCode RerunRoIsUnpackingTool::unpack(const EventContext& ctx,
       sourceDecision->getDetail( "thresholds", thresholds );
       
       ATH_MSG_DEBUG( "Thresholds in this RoI " << thresholds );
-      auto decision = newDecisionIn( decisionOutput.get() );
+      auto decision = newDecisionIn( decisionOutput );
       for ( auto th: thresholds ) {
 	ATH_MSG_DEBUG( "Activating because there are some chains to be rerun seeded from the threshold of ID " << th );
 	addChainsToDecision( th, decision, activeChains );    
@@ -72,9 +71,6 @@ StatusCode RerunRoIsUnpackingTool::unpack(const EventContext& ctx,
     }
   }
   
-  auto handle = SG::makeHandle( m_decisionsKey, ctx );
-  CHECK ( handle.record( std::move( decisionOutput ), std::move( decisionAux )  ) );
-  
 
 
   return StatusCode::SUCCESS;
diff --git a/Trigger/TrigSteer/L1Decoder/src/RoIsUnpackingEmulationTool.cxx b/Trigger/TrigSteer/L1Decoder/src/RoIsUnpackingEmulationTool.cxx
index 3755b1dac47..0d977e0fcb9 100644
--- a/Trigger/TrigSteer/L1Decoder/src/RoIsUnpackingEmulationTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/RoIsUnpackingEmulationTool.cxx
@@ -186,10 +186,12 @@ StatusCode RoIsUnpackingEmulationTool::unpack( const EventContext& ctx,
 					       const ROIB::RoIBResult& /*roib*/,
 					       const HLT::IDSet& activeChains ) const {
   using namespace TrigCompositeUtils;
-  auto decisionOutput = std::make_unique<DecisionContainer>();
-  auto decisionAux    = std::make_unique<DecisionAuxContainer>();
-  decisionOutput->setStore(decisionAux.get());  
-  auto trigRoIs = std::make_unique< TrigRoiDescriptorCollection >();
+
+  // create and record the collections needed
+  SG::WriteHandle<TrigRoiDescriptorCollection> handle1 = createAndStoreNoAux(m_trigRoIsKey, ctx ); 
+  auto trigRoIs = handle1.ptr();
+  SG::WriteHandle<DecisionContainer> handle3 = createAndStore(m_decisionsKey, ctx ); 
+  auto decisionOutput = handle3.ptr();
   
   // retrieve fake data for this event
   
@@ -212,7 +214,7 @@ StatusCode RoIsUnpackingEmulationTool::unpack( const EventContext& ctx,
     
     ATH_MSG_DEBUG( "RoI word: 0x" << MSG::hex << std::setw(8) << roIWord << MSG::dec );      
     
-    auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput.get() );
+    auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput );
     
     for ( auto th: roi.passedThresholdIDs ) {
       ATH_MSG_DEBUG( "Passed Threshold " << th << " enabling respective chains" );
@@ -228,16 +230,6 @@ StatusCode RoIsUnpackingEmulationTool::unpack( const EventContext& ctx,
     ATH_MSG_DEBUG("RoI Eta: " << roi->eta() << " Phi: " << roi->phi() << " RoIWord: " << roi->roiWord());
   }
   
-  // recording
-  {
-    SG::WriteHandle<TrigRoiDescriptorCollection> handle(m_trigRoIsKey, ctx);
-    CHECK( handle.record (std::move(trigRoIs)) );
-  }
-  
-  {
-    auto handle = SG::makeHandle(m_decisionsKey, ctx);
-    CHECK ( handle.record( std::move( decisionOutput ), std::move( decisionAux )  ) );
-  }
   return StatusCode::SUCCESS; // what else
  
 }
diff --git a/Trigger/TrigSteer/L1Decoder/src/TAURoIsUnpackingTool.cxx b/Trigger/TrigSteer/L1Decoder/src/TAURoIsUnpackingTool.cxx
index cbb9b0294d1..74ebc40b0fa 100644
--- a/Trigger/TrigSteer/L1Decoder/src/TAURoIsUnpackingTool.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/TAURoIsUnpackingTool.cxx
@@ -53,12 +53,12 @@ StatusCode TAURoIsUnpackingTool::unpack( const EventContext& ctx,
 					 const ROIB::RoIBResult& roib,
 					 const HLT::IDSet& activeChains ) const {
   using namespace TrigCompositeUtils;
-  auto decisionOutput = std::make_unique<DecisionContainer>();
-  auto decisionAux    = std::make_unique<DecisionAuxContainer>();
-  decisionOutput->setStore( decisionAux.get() );  
-  auto trigRoIs = std::make_unique< TrigRoiDescriptorCollection >();
-  auto recRoIs  = std::make_unique< DataVector<LVL1::RecEmTauRoI> >();
-
+  SG::WriteHandle<TrigRoiDescriptorCollection> handle1 = createAndStoreNoAux(m_trigRoIsKey, ctx ); 
+  auto trigRoIs = handle1.ptr();
+  SG::WriteHandle< DataVector<LVL1::RecEmTauRoI> > handle2 = createAndStoreNoAux( m_recRoIsKey, ctx );
+  auto recRoIs = handle2.ptr();
+  SG::WriteHandle<DecisionContainer> handle3 = createAndStore(m_decisionsKey, ctx ); 
+  auto decisionOutput = handle3.ptr();
 
   // RoIBResult contains vector of TAU fragments
   for ( auto& emTauFragment : roib.eMTauResult() ) {
@@ -79,7 +79,7 @@ StatusCode TAURoIsUnpackingTool::unpack( const EventContext& ctx,
         
       ATH_MSG_DEBUG( "RoI word: 0x" << MSG::hex << std::setw( 8 ) << roIWord << MSG::dec );      
 
-      auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput.get() );
+      auto decision  = TrigCompositeUtils::newDecisionIn( decisionOutput );
       
       for ( auto th: m_tauThresholds ) {
 	ATH_MSG_VERBOSE( "Checking if the threshold " << th->name() << " passed" );
@@ -106,25 +106,12 @@ StatusCode TAURoIsUnpackingTool::unpack( const EventContext& ctx,
   {
     using namespace Monitored;
     auto RoIsCount = MonitoredScalar::declare( "count", trigRoIs->size() );
-    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs.get(), &TrigRoiDescriptor::phi );
-    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs.get(), &TrigRoiDescriptor::eta );
+    auto RoIsPhi   = MonitoredCollection::declare( "phi", *trigRoIs, &TrigRoiDescriptor::phi );
+    auto RoIsEta   = MonitoredCollection::declare( "eta", *trigRoIs, &TrigRoiDescriptor::eta );
     MonitoredScope::declare( m_monTool,  RoIsCount, RoIsEta, RoIsPhi );
   }
 
   ATH_MSG_DEBUG( "Unpacked " <<  trigRoIs->size() << " RoIs" );
-  // recording
-  {
-    SG::WriteHandle<TrigRoiDescriptorCollection> handle( m_trigRoIsKey, ctx );
-    ATH_CHECK( handle.record ( std::move( trigRoIs ) ) );
-  }
-  {
-    SG::WriteHandle<DataVector<LVL1::RecEmTauRoI>> handle( m_recRoIsKey, ctx );
-    ATH_CHECK( handle.record( std::move( recRoIs ) ) );    
-  }
-  {
-    auto handle = SG::makeHandle( m_decisionsKey, ctx );
-    ATH_CHECK ( handle.record( std::move( decisionOutput ), std::move( decisionAux )  ) );
-  }
 
   return StatusCode::SUCCESS; // what else
   
diff --git a/Trigger/TrigSteer/L1Decoder/src/components/L1Decoder_entries.cxx b/Trigger/TrigSteer/L1Decoder/src/components/L1Decoder_entries.cxx
index 93cdece0d64..e25bb8cdfeb 100644
--- a/Trigger/TrigSteer/L1Decoder/src/components/L1Decoder_entries.cxx
+++ b/Trigger/TrigSteer/L1Decoder/src/components/L1Decoder_entries.cxx
@@ -1,6 +1,5 @@
 #include "../L1CaloDecoder.h"
 #include "../FakeRoI.h"
-#include "../FakeRoIView.h"
 #include "../L1Decoder.h"
 #include "../FakeCTP.h"
 #include "../CTPUnpackingToolBase.h"
@@ -22,7 +21,6 @@ DECLARE_COMPONENT( L1CaloDecoder )
 DECLARE_COMPONENT( FakeRoI )
 DECLARE_COMPONENT( FakeCTP )
 DECLARE_COMPONENT( L1Decoder )
-DECLARE_COMPONENT( AthViews::FakeRoIView )
 DECLARE_COMPONENT( CTPUnpackingToolBase )
 DECLARE_COMPONENT( CTPUnpackingTool )
 DECLARE_COMPONENT( CTPUnpackingEmulationTool )
diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx
index 73ff141f1f3..c1c18bdb09e 100644
--- a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx
+++ b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx
@@ -29,13 +29,10 @@ StatusCode DecisionSummaryMakerAlg::finalize() {
 }
 
 StatusCode DecisionSummaryMakerAlg::execute_r(const EventContext& context) const {
-  auto outputHandle{ SG::makeHandle( m_summaryKey, context) };
-  auto container = std::make_unique<TrigCompositeUtils::DecisionContainer>();
-  auto aux = std::make_unique<TrigCompositeUtils::DecisionAuxContainer>();
-  container->setStore( aux.get() );
+  SG::WriteHandle<TrigCompositeUtils::DecisionContainer> outputHandle = TrigCompositeUtils::createAndStore( m_summaryKey, context );
+  auto container = outputHandle.ptr();
 
-
-  TrigCompositeUtils::Decision* output = TrigCompositeUtils::newDecisionIn( container.get(), "HLTSummary" );
+  TrigCompositeUtils::Decision* output = TrigCompositeUtils::newDecisionIn( container, "HLTSummary" );
   
   for ( auto& key: m_finalDecisionKeys ) {
     auto handle{ SG::makeHandle(key, context) };
@@ -69,7 +66,6 @@ StatusCode DecisionSummaryMakerAlg::execute_r(const EventContext& context) const
       ATH_MSG_DEBUG( HLT::Identifier( d ) );
     }
   }
-  ATH_CHECK( outputHandle.record( std::move( container), std::move( aux )) );
 
   return StatusCode::SUCCESS;
 }
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
index c18021e98b7..f10503ada9c 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithm.cxx
@@ -27,8 +27,12 @@ StatusCode EventViewCreatorAlgorithm::initialize() {
 
 StatusCode EventViewCreatorAlgorithm::execute_r( const EventContext& context ) const { 
   auto outputHandles = decisionOutputs().makeHandles( context );     
-  // make the views
-  auto viewVector = std::make_unique< ViewContainer >();
+  // make and store 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 contexts = std::vector<EventContext>( );
   unsigned int viewCounter = 0;
   unsigned int conditionsRun = getContext().getExtension<Atlas::ExtendedEventContext>().conditionsRun();
@@ -48,17 +52,15 @@ StatusCode EventViewCreatorAlgorithm::execute_r( const EventContext& context ) c
       ATH_MSG_DEBUG( "Got no decisions from input " << inputKey.key() );
       continue;
     }
-    
     if( inputHandle->size() == 0 ) { // input filtered out
-      ATH_MSG_ERROR( "Got 0 decisions from valid input "<< inputKey.key()<<". Is it expected?");
-      return StatusCode::FAILURE;
+      ATH_MSG_DEBUG( "Got no decisions from input " << inputKey.key() );
+      continue;
     }
     ATH_MSG_DEBUG( "Got input " << inputKey.key() << " with " << inputHandle->size() << " elements" );
     
      // prepare output decisions
-    auto outputDecisions = std::make_unique<TrigCompositeUtils::DecisionContainer>();    
-    auto decAux = std::make_unique<TrigCompositeUtils::DecisionAuxContainer>();
-    outputDecisions->setStore( decAux.get() );
+    TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
+    TrigCompositeUtils::DecisionContainer* outputDecisions = outputHandles[outputIndex].ptr();
 
     const TrigRoiDescriptor* prevRoIDescriptor = nullptr;
     int inputCounter = -1;
@@ -74,13 +76,13 @@ StatusCode EventViewCreatorAlgorithm::execute_r( const EventContext& context ) c
       TrigCompositeUtils::Decision* newDecision = nullptr;      
       if ( prevRoIDescriptor != roiDescriptor ) {
 	//make one TC decision output per input and connect to previous
-	newDecision = TrigCompositeUtils::newDecisionIn( outputDecisions.get(), name() );
+	newDecision = TrigCompositeUtils::newDecisionIn( outputDecisions, name() );
 	TrigCompositeUtils::linkToPrevious( newDecision, inputKey.key(), inputCounter );
 	insertDecisions( inputDecision, newDecision );
 	newDecision->setObjectLink( "initialRoI", roiELInfo.link );
 	prevRoIDescriptor = roiDescriptor;
       } else {
-	newDecision = outputDecisions.get()->back();
+	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");
@@ -114,19 +116,16 @@ StatusCode EventViewCreatorAlgorithm::execute_r( const EventContext& context ) c
       }
     }
     
-    ATH_MSG_DEBUG( "Recording output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<< outputDecisions->size()  <<" at index "<< outputIndex);
-    ATH_CHECK( outputHandles[outputIndex].record( std::move( outputDecisions ), std::move( decAux ) ) );
+    ATH_MSG_DEBUG( "Recorded output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<< outputDecisions->size()  <<" at index "<< outputIndex);
   }
 
   ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
-  ATH_CHECK( ViewHelper::ScheduleViews( viewVector.get(),           // Vector containing views
+  ATH_CHECK( ViewHelper::ScheduleViews( viewVector,           // Vector containing views
 					m_viewNodeName,             // CF node to attach views to
 					context,                    // Source context
 					m_scheduler.get() ) );
   
-  // store views
-  auto viewsHandle = SG::makeHandle( m_viewsKey );
-  ATH_CHECK( viewsHandle.record(  std::move( viewVector ) ) );
+  // report number of views, stored already when container was created
   ATH_MSG_DEBUG( "Store "<< viewsHandle->size() <<" Views");
 
   size_t validInputCount = countInputHandles( context );  
@@ -150,7 +149,7 @@ size_t EventViewCreatorAlgorithm::countInputHandles( const EventContext& context
   for ( auto inputKey: decisionInputs() ) {
     auto inputHandle = SG::makeHandle( inputKey, context );
     ATH_MSG_DEBUG(" " << inputKey.key() << (inputHandle.isValid()? "valid": "not valid" ) );
-    if (inputHandle.isValid()) validInputCount++;
+    if (inputHandle.isValid() and inputHandle->size() > 0 ) validInputCount++;
   }
   ATH_MSG_DEBUG( "number of implicit ReadHandles is " << decisionInputs().size() << ", " << validInputCount << " are valid" );
   
diff --git a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
index 1406d3f89c8..21544ce9036 100644
--- a/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
+++ b/Trigger/TrigSteer/ViewAlgs/src/EventViewCreatorAlgorithmWithJets.cxx
@@ -27,8 +27,12 @@ StatusCode EventViewCreatorAlgorithmWithJets::initialize() {
 
 StatusCode EventViewCreatorAlgorithmWithJets::execute_r( const EventContext& context ) const { 
   auto outputHandles = decisionOutputs().makeHandles( context );     
-  // make the views
-  auto viewVector = std::make_unique< ViewContainer >();
+  // make and store 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 contexts = std::vector<EventContext>( );
   unsigned int viewCounter = 0;
   unsigned int conditionsRun = getContext().getExtension<Atlas::ExtendedEventContext>().conditionsRun();
@@ -56,10 +60,9 @@ StatusCode EventViewCreatorAlgorithmWithJets::execute_r( const EventContext& con
     ATH_MSG_DEBUG( "Got input " << inputKey.key() << " with " << inputHandle->size() << " elements" );
     
      // prepare output decisions
-    auto outputDecisions = std::make_unique<TrigCompositeUtils::DecisionContainer>();    
-    auto decAux = std::make_unique<TrigCompositeUtils::DecisionAuxContainer>();
-    outputDecisions->setStore( decAux.get() );
-
+    TrigCompositeUtils::createAndStore(outputHandles[outputIndex]);
+    TrigCompositeUtils::DecisionContainer* outputDecisions = outputHandles[outputIndex].ptr();
+    
     const TrigRoiDescriptor* prevRoIDescriptor = nullptr;
     int inputCounter = -1;
     for ( auto inputDecision: *inputHandle ) {
@@ -83,14 +86,14 @@ StatusCode EventViewCreatorAlgorithmWithJets::execute_r( const EventContext& con
       TrigCompositeUtils::Decision* newDecision = nullptr;      
       if ( prevRoIDescriptor != roiDescriptor ) {
 	//make one TC decision output per input and connect to previous
-	newDecision = TrigCompositeUtils::newDecisionIn( outputDecisions.get(), name() );
+	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.get()->back();
+	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");
@@ -126,18 +129,15 @@ StatusCode EventViewCreatorAlgorithmWithJets::execute_r( const EventContext& con
     }
     
     ATH_MSG_DEBUG( "Recording output key " <<  decisionOutputs()[ outputIndex ].key() <<" of size "<< outputDecisions->size()  <<" at index "<< outputIndex);
-    ATH_CHECK( outputHandles[outputIndex].record( std::move( outputDecisions ), std::move( decAux ) ) );
   }
 
   ATH_MSG_DEBUG( "Launching execution in " << viewVector->size() << " views" );
-  ATH_CHECK( ViewHelper::ScheduleViews( viewVector.get(),           // Vector containing views
+  ATH_CHECK( ViewHelper::ScheduleViews( viewVector,           // Vector containing views
 					m_viewNodeName,             // CF node to attach views to
 					context,                    // Source context
 					m_scheduler.get() ) );
   
-  // store views
-  auto viewsHandle = SG::makeHandle( m_viewsKey );
-  ATH_CHECK( viewsHandle.record(  std::move( viewVector ) ) );
+  // report number of views, stored already when container was created
   ATH_MSG_DEBUG( "Store "<< viewsHandle->size() <<" Views");
 
   size_t validInputCount = countInputHandles( context );  
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx b/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx
index 7c4be9140e9..6d125cd6ca5 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestComboHypoAlg.cxx
@@ -186,14 +186,10 @@ namespace HLTTest {
 
     ATH_MSG_DEBUG( "and with "<< recoInput1->size() <<" reco1 inputs, and "<<recoInput2->size() <<" reco2 inputs");
     
-    auto decisions1 = std::make_unique<DecisionContainer>();
-    auto aux1 = std::make_unique<DecisionAuxContainer>();
-    decisions1->setStore( aux1.get() );
-    
-    auto decisions2 = std::make_unique<DecisionContainer>();
-    auto aux2 = std::make_unique<DecisionAuxContainer>();
-    decisions2->setStore( aux2.get() );
-
+    SG::WriteHandle<DecisionContainer> outputHandle1 = createAndStore(m_output1, context ); 
+    auto decisions1 = outputHandle1.ptr();
+    SG::WriteHandle<DecisionContainer> outputHandle2 = createAndStore(m_output1, context ); 
+    auto decisions2 = outputHandle2.ptr();
 
     // find RoIs from previous decisions
     std::vector<const FeatureOBJ*> featureFromDecision1;
@@ -230,7 +226,7 @@ namespace HLTTest {
        
        if (foundRoIInDecision){
 	 ATH_MSG_DEBUG("Found the same RoI on decision at pos "<<pos);
-	 auto d = newDecisionIn(decisions1.get());
+	 auto d = newDecisionIn(decisions1);
 	 d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>(m_recoInput1.key(), counter1) );// feature used by the Tool
 	 d->setObjectLink( "initialRoI", featurelink );// this is used by the InputMaker
 	 d->setObjectLink( "previousDecisions", ElementLink<DecisionContainer>(m_previousDecisions1.key(), pos) );// link to previous decision object
@@ -258,7 +254,7 @@ namespace HLTTest {
        
        if (foundRoIInDecision){
 	 ATH_MSG_DEBUG("Found the same RoI on decision at pos "<<pos);
-	 auto d = newDecisionIn(decisions2.get());
+	 auto d = newDecisionIn(decisions2);
 	 d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>(m_recoInput2.key(), counter2) );// feature used by the Tool
 	 d->setObjectLink( "initialRoI", featurelink );// this is used by the InputMaker
 	 d->setObjectLink( "previousDecisions", ElementLink<DecisionContainer>(m_previousDecisions2.key(), pos) );// link to previous decision object
@@ -275,7 +271,7 @@ namespace HLTTest {
     // for ( auto previousDecision: *previousDecisionsHandle1 ) {
     //   auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
     //   CHECK( roiEL.isValid() );
-    //   auto d = newDecisionIn( decisions1.get() );
+    //   auto d = newDecisionIn( decisions1 );
     //   if (counter1<input1->size())
     // 	d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>( m_recoInput1.key(),  counter1) );
     //   else
@@ -290,7 +286,7 @@ namespace HLTTest {
     // for ( auto previousDecision: *previousDecisionsHandle2 ) {
     //   auto roiEL = previousDecision->objectLink<TrigRoiDescriptorCollection>( "initialRoI" );
     //   CHECK( roiEL.isValid() );    
-    //   auto d = newDecisionIn( decisions2.get() );
+    //   auto d = newDecisionIn( decisions2 );
     //   //get the feature
     //   if (counter2<input2->size())
     // 	d->setObjectLink( "feature", ElementLink<xAOD::TrigCompositeContainer>( m_recoInput2.key(),  counter2) );
@@ -359,8 +355,8 @@ namespace HLTTest {
 	      for ( const HLT::Identifier& did: intersection2 ){
 		//	      auto did = HLT::Identifier( m_decisionLabel ).numeric();
 		ATH_MSG_DEBUG("Adding "<<did<<" to both candaites");
-		addDecisionID( did,  decisions1.get()->at(counter1) );
-		addDecisionID( did,  decisions2.get()->at(counter2) );
+		addDecisionID( did,  decisions1->at(counter1) );
+		addDecisionID( did,  decisions2->at(counter2) );
 	      }
 	    }
 	    
@@ -369,14 +365,6 @@ namespace HLTTest {
       }
     }
     
-    {
-      auto h = SG::makeHandle( m_output1 );
-      CHECK( h.record( std::move( decisions1 ) , std::move( aux1 ) ) );
-    }
-    {
-      auto h = SG::makeHandle( m_output2 );
-      CHECK( h.record( std::move( decisions2 ) , std::move( aux2 ) ) );
-    }
     //    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 68897db31eb..eacfb63beaa 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
+++ b/Trigger/TrigValidation/TrigUpgradeTest/src/TestHypoAlg.cxx
@@ -46,9 +46,8 @@ namespace HLTTest {
     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() );
+    SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); 
+    auto decisions = outputHandle.ptr();
 
     // find features:
     std::vector<const FeatureOBJ*> featureFromDecision;
@@ -85,7 +84,7 @@ namespace HLTTest {
        
        if (foundFeatureInDecision){
 	 ATH_MSG_DEBUG(" Found link from the reco object to the previous decision at position "<<pos);
-	 auto d = newDecisionIn(decisions.get());
+	 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 );
@@ -102,13 +101,10 @@ namespace HLTTest {
 
     if (decisions->size()>0){
       for ( auto tool: m_tools ) {
-	CHECK( tool->decide( decisions.get() ) );
+	CHECK( tool->decide( decisions ) );
       }
     }
 
-    auto outputHandle = SG::makeHandle(decisionOutput(), context);
-    CHECK( outputHandle.record(std::move(decisions), std::move(aux) ) );
-  
     ATH_MSG_DEBUG( "Exiting with "<< outputHandle->size() <<" decisions");
     //debug
     for (auto outh: *outputHandle){
-- 
GitLab