From bee18ced8826a7207b29b2e74ab4d286d267d57b Mon Sep 17 00:00:00 2001
From: Shaun Roe <shaun.roe@cern.ch>
Date: Mon, 30 Nov 2020 15:15:50 +0000
Subject: [PATCH] 22.0-new_alg-TrkTrackSummaryUpdater

---
 .../TrkTrackSummaryUpdater/CMakeLists.txt     |  43 ++++
 .../TrackSummaryUpdater.h                     |  48 ++++
 .../share/TrackSummaryUpdater_test.txt        |   8 +
 .../src/TrackSummaryUpdater.cxx               |  83 ++++++
 .../TrkTrackSummaryUpdater_entries.cxx        |  10 +
 .../test/PutTrackCollectionsInSG.cxx          |  63 +++++
 .../test/PutTrackCollectionsInSG.h            |  38 +++
 .../test/SummaryToolStub.cxx                  | 111 ++++++++
 .../test/SummaryToolStub.h                    |  72 ++++++
 .../test/TrackSummaryUpdater_test.cxx         | 238 ++++++++++++++++++
 10 files changed, 714 insertions(+)
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/CMakeLists.txt
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/TrkTrackSummaryUpdater/TrackSummaryUpdater.h
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/share/TrackSummaryUpdater_test.txt
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/TrackSummaryUpdater.cxx
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/components/TrkTrackSummaryUpdater_entries.cxx
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.cxx
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.h
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.cxx
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.h
 create mode 100644 Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/TrackSummaryUpdater_test.cxx

diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/CMakeLists.txt b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/CMakeLists.txt
new file mode 100644
index 00000000000..0df7b32ae7f
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/CMakeLists.txt
@@ -0,0 +1,43 @@
+################################################################################
+# Package: TrkTrackSummaryUpdater
+################################################################################
+
+# Declare the package name:
+atlas_subdir( TrkTrackSummaryUpdater )
+                
+# External dependencies:
+find_package( Boost COMPONENTS unit_test_framework )
+find_package( ROOT COMPONENTS Core )
+          
+# Component(s) in the package:
+atlas_add_library( TrkTrackSummaryUpdaterLib
+                   src/*.cxx
+                   test/PutTrackCollectionsInSG.cxx
+                   test/SummaryToolStub.cxx
+                   PUBLIC_HEADERS TrkTrackSummaryUpdater
+                   LINK_LIBRARIES AthenaBaseComps GaudiKernel StoreGateLib TrkTrack TrkEventUtils TrkToolInterfaces TrkTrackSummary
+                   PRIVATE_LINK_LIBRARIES TrkPrepRawData )
+                   
+atlas_add_library( TrkTrackSummaryUpdaterTestLib
+                   test/PutTrackCollectionsInSG.cxx
+                   test/SummaryToolStub.cxx
+                   NO_PUBLIC_HEADERS
+                   LINK_LIBRARIES TrkTrackSummaryUpdaterLib 
+                   PRIVATE_LINK_LIBRARIES TrkPrepRawData )
+
+# Component(s) in the package:
+atlas_add_component( TrkTrackSummaryUpdater
+                     src/components/*.cxx
+                     LINK_LIBRARIES TrkTrackSummaryUpdaterLib)
+
+atlas_add_test(TrackSummaryUpdater_test
+                SOURCES test/TrackSummaryUpdater_test.cxx 
+                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} 
+                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES}  TrkTrackSummaryUpdaterTestLib
+                POST_EXEC_SCRIPT "nopost.sh" )
+
+# Install files from the package:
+atlas_install_joboptions( share/*.txt )
+
+# Install files from the package:
+atlas_install_headers( TrkTrackSummaryUpdater )
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/TrkTrackSummaryUpdater/TrackSummaryUpdater.h b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/TrkTrackSummaryUpdater/TrackSummaryUpdater.h
new file mode 100644
index 00000000000..93967b3a40e
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/TrkTrackSummaryUpdater/TrackSummaryUpdater.h
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#ifndef TrackSummaryUpdater_H
+#define TrackSummaryUpdater_H
+
+#include <string>
+#include <map>
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "TrkTrack/TrackCollection.h"
+
+#include "TrkToolInterfaces/IExtendedTrackSummaryTool.h"
+#include "TrkToolInterfaces/IPRDtoTrackMapTool.h"
+#include "TrkEventUtils/PRDtoTrackMap.h"
+
+#include "StoreGate/WriteHandleKey.h"
+#include "StoreGate/ReadHandleKeyArray.h"
+
+namespace Trk {
+
+  /** @brief Algorithm for updating the track summary of a track collection */
+  class TrackSummaryUpdater : public AthAlgorithm{
+    public:
+      TrackSummaryUpdater(const std::string &name, ISvcLocator *pSvcLocator);
+      virtual ~TrackSummaryUpdater() {}
+      StatusCode initialize() override;
+      StatusCode execute() override;
+      StatusCode finalize() override;
+      
+    protected:
+      SG::ReadHandleKey<TrackCollection>           m_inputTracksStoregateKey  ;  /** Input track collection.   */
+      SG::WriteHandleKey<TrackCollection>          m_updatedTracksStoregateKey  ;  /** Input track collection with updated summary.   */
+      SG::WriteHandleKey<Trk::PRDtoTrackMap>       m_assoMapName{this,"AssociationMapName",""};  ///< the key given to the newly created association map
+      ToolHandle<Trk::IPRDtoTrackMapTool>          m_assoTool{this, "AssociationTool", "InDet::InDetPRDtoTrackMapToolGangedPixels" };
+      ToolHandle< Trk::IExtendedTrackSummaryTool > m_trkSummaryTool    ;  /** summary tool with shared hits enabled */
+
+    private:
+      bool  m_createViewCollection;     //!< option to create a view collection and not deep-copy tracks
+      bool  m_updateSharedHits; //!< do not create the track summary again, but only update shared hits
+      bool  m_updateAdditionalInfo;     //!< do not create the track summary again, but only update necessary things
+    };
+}
+#endif // TrackSummaryUpdater_H
+
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/share/TrackSummaryUpdater_test.txt b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/share/TrackSummaryUpdater_test.txt
new file mode 100644
index 00000000000..2992965a1a9
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/share/TrackSummaryUpdater_test.txt
@@ -0,0 +1,8 @@
+EventDataSvc.ForceLeaves = true;
+EventDataSvc.RootCLID    = 1;
+ApplicationMgr.Dlls += { "AthenaServices" };
+ApplicationMgr.ExtSvc = {"StoreGateSvc"};
+ApplicationMgr.EvtMax = 1;
+ApplicationMgr.EvtSel = "TestEvtSelector";
+ApplicationMgr.HistogramPersistency = "NONE";
+MessageSvc.OutputLevel = 5;
\ No newline at end of file
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/TrackSummaryUpdater.cxx b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/TrackSummaryUpdater.cxx
new file mode 100644
index 00000000000..098bee3bd0a
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/TrackSummaryUpdater.cxx
@@ -0,0 +1,83 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "GaudiKernel/MsgStream.h"
+#include "TrkPrepRawData/PrepRawData.h"
+#include "TrkTrackSummaryUpdater/TrackSummaryUpdater.h"
+
+///////////////////////////////////////////////////////////////////
+// Constructor
+///////////////////////////////////////////////////////////////////
+
+Trk::TrackSummaryUpdater::TrackSummaryUpdater
+(const std::string& name, ISvcLocator* pSvcLocator  ) :
+  AthAlgorithm(name, pSvcLocator ),
+  m_createViewCollection(true),
+  m_updateSharedHits(true),
+  m_updateAdditionalInfo(false){
+  m_inputTracksStoregateKey = "CombinedInDetTracks";
+  declareProperty("InputTracksKey",            m_inputTracksStoregateKey);
+  declareProperty("OutputTracksKey",           m_updatedTracksStoregateKey); 
+  declareProperty("SummaryTool" ,              m_trkSummaryTool);
+  declareProperty("UpdateSharedHits" ,         m_updateSharedHits);
+  declareProperty("UpdateAdditionalInfo" ,     m_updateAdditionalInfo);
+}
+
+///////////////////////////////////////////////////////////////////
+// Initialisation
+///////////////////////////////////////////////////////////////////
+
+StatusCode 
+Trk::TrackSummaryUpdater::initialize(){
+  ATH_MSG_DEBUG("Initializing TrackSummaryUpdater");
+  ATH_CHECK( m_inputTracksStoregateKey.initialize() );
+  ATH_CHECK( m_updatedTracksStoregateKey.initialize() );
+  ATH_CHECK( m_trkSummaryTool.retrieve() ); //..so needs at least a TrackSummaryTool to be configured
+  if (not m_assoTool.empty())  ATH_CHECK( m_assoTool.retrieve() );
+  ATH_CHECK( m_assoMapName.initialize( !m_assoMapName.key().empty() ));
+  return StatusCode::SUCCESS;
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Execute
+///////////////////////////////////////////////////////////////////
+StatusCode 
+Trk::TrackSummaryUpdater::execute(){
+  std::unique_ptr<Trk::PRDtoTrackMap> prdToTrackMap (m_assoTool ? m_assoTool->createPRDtoTrackMap(): std::make_unique<Trk::PRDtoTrackMap>());
+  std::unique_ptr<TrackCollection> updatedCollection = std::make_unique<TrackCollection>(SG::VIEW_ELEMENTS);
+  SG::ReadHandle<TrackCollection> inputTrackCollection(m_inputTracksStoregateKey);
+  updatedCollection->reserve(inputTrackCollection->size());
+  ATH_MSG_DEBUG("Update summaries");  
+  const bool createNewSummary = (not m_updateAdditionalInfo) and (not m_updateSharedHits);
+  for (const auto pThisTrack : *inputTrackCollection) {
+    auto nonConstTrackPtr = const_cast<Trk::Track *>(pThisTrack);
+    if (m_updateAdditionalInfo)  m_trkSummaryTool->updateAdditionalInfo(*nonConstTrackPtr);
+    if (m_updateSharedHits) m_trkSummaryTool->updateSharedHitCount(*nonConstTrackPtr, prdToTrackMap.get());
+    if (createNewSummary) m_trkSummaryTool->computeAndReplaceTrackSummary(*nonConstTrackPtr, prdToTrackMap.get(), false /* DO NOT suppress hole search*/);
+    updatedCollection->push_back(nonConstTrackPtr);
+  }
+  SG::WriteHandle<TrackCollection> sgTargetWriteHandle(m_updatedTracksStoregateKey);
+  ATH_CHECK(sgTargetWriteHandle.record(std::move(updatedCollection)));	     
+  if (m_assoTool and (not m_assoMapName.key().empty())) {
+     SG::WriteHandle<Trk::PRDtoTrackMap> storegateWriter(m_assoMapName);
+     if (storegateWriter.record( m_assoTool->reduceToStorableMap(std::move(prdToTrackMap))).isFailure()) {
+        ATH_MSG_FATAL("Failed to add PRD to track association map.");
+     }
+  }
+  
+  ATH_MSG_DEBUG("Done !");  
+  return StatusCode::SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+// Finalize
+///////////////////////////////////////////////////////////////////
+
+StatusCode 
+Trk::TrackSummaryUpdater::finalize(){
+   return StatusCode::SUCCESS;
+}
+
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/components/TrkTrackSummaryUpdater_entries.cxx b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/components/TrkTrackSummaryUpdater_entries.cxx
new file mode 100644
index 00000000000..40c34fef6ad
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/src/components/TrkTrackSummaryUpdater_entries.cxx
@@ -0,0 +1,10 @@
+
+#include "TrkTrackSummaryUpdater/TrackSummaryUpdater.h"
+#include "test/SummaryToolStub.h"
+#include "test/PutTrackCollectionsInSG.h"
+
+DECLARE_COMPONENT( Trk::TrackSummaryUpdater )
+DECLARE_COMPONENT(SummaryToolStub)
+DECLARE_COMPONENT( PutTrackCollectionsInSG )
+
+
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.cxx b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.cxx
new file mode 100644
index 00000000000..40790cc9b7d
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.cxx
@@ -0,0 +1,63 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * @file PutTrackCollectionsInSG.cxx
+ *
+ * @brief Implementation file for the PutTrackCollectionsInSG class 
+ *
+ * @author Shaun Roe
+ **/
+
+#include "PutTrackCollectionsInSG.h"
+#include "TrkTrack/TrackCollection.h"
+#include <memory>
+
+
+PutTrackCollectionsInSG::PutTrackCollectionsInSG(const std::string& name, ISvcLocator* pSvcLocator) : 
+  AthAlgorithm(name, pSvcLocator)
+{
+  //nop
+}
+
+//Initialize
+StatusCode 
+PutTrackCollectionsInSG::initialize() {
+  ATH_MSG_INFO("Calling initialize");
+  return StatusCode::SUCCESS;
+}
+
+//Execute
+StatusCode 
+PutTrackCollectionsInSG::execute()  {
+  auto collection1 = std::make_unique<TrackCollection>(SG::VIEW_ELEMENTS);
+  //note that the default c'tor should normally *not* be used and results in an invalid Track
+  //however, it suffices for unit testing purposes
+  Trk::Track *t1 = new Trk::Track();
+  Trk::Track *t2 = new Trk::Track();
+  collection1->push_back(t1);
+  collection1->push_back(t2);
+  auto collection2 = std::make_unique<TrackCollection>(SG::VIEW_ELEMENTS);
+  Trk::Track *t3 =  new Trk::Track();
+  collection2->push_back(t3);
+  //
+  std::string collectionKey1("StoreGateSvc+TrackCollectionKey1");
+  SG::WriteHandle<TrackCollection> sgTrackCollectionWriter1(collectionKey1);
+  ATH_MSG_INFO("Record track collection1 in SG");
+  ATH_CHECK(sgTrackCollectionWriter1.record(std::move(collection1)));	
+  //
+  std::string collectionKey2("StoreGateSvc+TrackCollectionKey2");
+  SG::WriteHandle<TrackCollection> sgTrackCollectionWriter2(collectionKey2);
+  ATH_MSG_INFO("Record track collection2 in SG");
+  ATH_CHECK(sgTrackCollectionWriter2.record(std::move(collection2)));
+  //
+  return StatusCode::SUCCESS;
+}
+
+//Finalize
+StatusCode
+PutTrackCollectionsInSG::finalize() {
+  ATH_MSG_INFO("Calling finalize");
+  return StatusCode::SUCCESS;
+}
\ No newline at end of file
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.h b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.h
new file mode 100644
index 00000000000..47fe6a2a441
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/PutTrackCollectionsInSG.h
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+* @file PutTrackCollectionsInSG.h
+*
+* @brief Header file for the PutTrackCollectionsInSG class 
+*  for testing the TrkTrackCollectionMerger
+*
+* @author Shaun Roe
+**/
+
+#ifndef PutTrackCollectionsInSG_H
+#define PutTrackCollectionsInSG_H 
+
+//Athena
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+//Gaudi
+
+//STL
+#include <string>
+
+///Example algorithm to show calling the SCT_ModuleVetoSvc to exclude bad components
+class PutTrackCollectionsInSG : public AthAlgorithm {
+ public:
+  PutTrackCollectionsInSG(const std::string &name,ISvcLocator *pSvcLocator) ;
+  virtual ~PutTrackCollectionsInSG() = default;
+  virtual StatusCode initialize() override;
+  virtual StatusCode execute() override;
+  virtual StatusCode finalize() override;
+  virtual bool isClonable() const override { return false; };
+
+ private:
+}; //end of class
+
+#endif // PutTrackCollectionsInSG_H
\ No newline at end of file
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.cxx b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.cxx
new file mode 100644
index 00000000000..b56a5732a9b
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.cxx
@@ -0,0 +1,111 @@
+/*
+   Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SummaryToolStub.h"
+
+#include "TrkTrack/Track.h"
+#include "TrkTrackSummary/TrackSummary.h"
+#include <vector>
+#include <bitset>
+
+SummaryToolStub::SummaryToolStub(const std::string& t, const std::string& n, const IInterface*  p ):base_class(t,n,p){
+  declareInterface<ITrackSummaryTool>(this);
+  //just for fun, lets make a TrackSummary out of its components
+  //I'm using 19 components, which is not a full set, but encompasses the element which 
+  //would give SCT Shared Hits (which I use in the test)
+  std::vector<int> information{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18, -1};
+  std::vector<float> eProbability{0.1,0.1,0.1};
+  std::bitset<Trk::DetectorType::numberOfDetectorTypes> hitPattern{};
+  hitPattern.set(3);
+  float dedx=0.2;
+  int nhitsuseddedx=3;
+  int nhitsoverflowdedx=1;
+  m_pTrackSummaryRef = std::make_unique<Trk::TrackSummary>(information, eProbability, hitPattern, dedx, nhitsuseddedx, nhitsoverflowdedx);
+}
+
+StatusCode 
+SummaryToolStub::initialize() {
+  return StatusCode::SUCCESS;
+}
+
+StatusCode 
+SummaryToolStub::finalize() {
+  return StatusCode::SUCCESS;
+}
+//methods inherited from the IExtendedTrackSummaryTool and the ITrackSummaryTool.
+//
+void 
+SummaryToolStub::updateSharedHitCount(Trk::Track& ) const {}
+//
+void 
+SummaryToolStub::computeAndReplaceTrackSummary(const EventContext&  ,Trk::Track& track,const Trk::PRDtoTrackMap* , bool ) const {
+  //copy the reference summary
+  auto p = std::make_unique<Trk::TrackSummary>(*m_pTrackSummaryRef);
+  track.setTrackSummary(std::move(p));
+}
+//
+void 
+SummaryToolStub::updateTrackSummary(const EventContext&  ,Trk::Track&) const {
+
+}
+//
+void 
+SummaryToolStub::updateTrackSummary(const EventContext&  ,Trk::Track&, const Trk::PRDtoTrackMap* , bool) const {
+
+}
+//
+void 
+SummaryToolStub::updateTrack(const EventContext&  ,Trk::Track& ) const {
+
+}
+//
+std::unique_ptr<Trk::TrackSummary> 
+SummaryToolStub::summaryNoHoleSearch( const EventContext&  ,const Trk::Track& , const Trk::PRDtoTrackMap* ) const {
+ return std::make_unique<Trk::TrackSummary>();
+}
+//
+std::unique_ptr<Trk::TrackSummary> 
+SummaryToolStub::summaryNoHoleSearch(const EventContext&  ,const Trk::Track&)const {
+ return std::make_unique<Trk::TrackSummary>();
+}
+//
+std::unique_ptr<Trk::TrackSummary> 
+SummaryToolStub::summary(const EventContext&  ,const Trk::Track& ) const {
+ return std::make_unique<Trk::TrackSummary>();
+}
+//
+std::unique_ptr<Trk::TrackSummary> 
+SummaryToolStub::summary(const EventContext&  ,const Trk::Track&, const Trk::PRDtoTrackMap*) const {
+ return std::make_unique<Trk::TrackSummary>();
+}
+//
+void 
+SummaryToolStub::updateSharedHitCount(const Trk::Track& ,const Trk::PRDtoTrackMap* , Trk::TrackSummary& ) const {}
+//
+void 
+SummaryToolStub::updateSharedHitCount(Trk::Track& track,const Trk::PRDtoTrackMap* ) const  {
+  auto updatedSummary = *m_pTrackSummaryRef;
+  updatedSummary.update(Trk::SummaryType::numberOfSCTSharedHits, 20);
+  auto p = std::make_unique<Trk::TrackSummary>(updatedSummary);
+  track.setTrackSummary(std::move(p));
+}
+//
+void 
+SummaryToolStub::updateAdditionalInfo(const Trk::Track& , Trk::TrackSummary& ) const {
+  //
+}
+//
+void 
+SummaryToolStub::updateAdditionalInfo(Trk::Track& track) const {
+  //just for fun, lets make a TrackSummary out of its components
+  std::vector<int> information{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18, -1};
+  std::vector<float> eProbability{0.1,0.1,0.1};
+  std::bitset<Trk::DetectorType::numberOfDetectorTypes> hitPattern{};
+  hitPattern.set(3);
+  float dedx=0.2;
+  int nhitsuseddedx=4;
+  int nhitsoverflowdedx=1;
+  auto t = std::make_unique<Trk::TrackSummary>(information, eProbability, hitPattern, dedx, nhitsuseddedx, nhitsoverflowdedx);
+  track.setTrackSummary(std::move(t));
+}
\ No newline at end of file
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.h b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.h
new file mode 100644
index 00000000000..85e6a44997c
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/SummaryToolStub.h
@@ -0,0 +1,72 @@
+/*
+   Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef TRKSummaryToolStub_H
+#define TRKSummaryToolStub_H
+
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "TrkToolInterfaces/IExtendedTrackSummaryTool.h" //baseclass
+
+#include <string>
+#include <memory> //unique_ptr
+
+namespace Trk{
+  class Track;
+  class PRDtoTrackMap;
+  class TrackSummary;
+}
+ 
+ class 
+ SummaryToolStub : public extends<AthAlgTool, Trk::IExtendedTrackSummaryTool>{
+   public:
+   SummaryToolStub(const std::string& t, const std::string& n, const IInterface*  p );
+   
+   ~SummaryToolStub(){}
+   StatusCode initialize() override;
+   StatusCode finalize() override;
+   //methods inherited from the IExtendedTrackSummaryTool and the ITrackSummaryTool.
+   //
+   void 
+   updateSharedHitCount(Trk::Track& ) const override;
+   //
+   void 
+   computeAndReplaceTrackSummary(const EventContext& ctx, Trk::Track& ,const Trk::PRDtoTrackMap* , bool ) const override;
+   //
+   void 
+   updateTrackSummary(const EventContext& ctx,Trk::Track&) const override;
+   //
+   void 
+   updateTrackSummary(const EventContext& ctx, Trk::Track&, const Trk::PRDtoTrackMap* , bool) const override;
+   //
+   void 
+   updateTrack(const EventContext& ctx,Trk::Track& ) const override;
+    //
+   std::unique_ptr<Trk::TrackSummary> 
+   summaryNoHoleSearch( const EventContext& ctx,const Trk::Track& , const Trk::PRDtoTrackMap* ) const override;
+   //
+   std::unique_ptr<Trk::TrackSummary> 
+   summaryNoHoleSearch(const EventContext& ctx, const Trk::Track&)const override;
+   //
+   std::unique_ptr<Trk::TrackSummary> 
+   summary(const EventContext& ctx,const Trk::Track& ) const override;
+   //
+   std::unique_ptr<Trk::TrackSummary> 
+   summary(const EventContext& ctx,const Trk::Track&, const Trk::PRDtoTrackMap*) const override;
+   //
+   void 
+   updateSharedHitCount(const Trk::Track& ,const Trk::PRDtoTrackMap* , Trk::TrackSummary& ) const override;
+   //
+   void 
+   updateSharedHitCount(Trk::Track& ,const Trk::PRDtoTrackMap* ) const  override;
+   //
+   void 
+   updateAdditionalInfo(const Trk::Track& , Trk::TrackSummary& ) const override;
+   //
+   void 
+   updateAdditionalInfo(Trk::Track& ) const override;
+   
+   private:
+   std::unique_ptr<Trk::TrackSummary> m_pTrackSummaryRef{};
+ };
+#endif
diff --git a/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/TrackSummaryUpdater_test.cxx b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/TrackSummaryUpdater_test.cxx
new file mode 100644
index 00000000000..f0c29831a0e
--- /dev/null
+++ b/Tracking/TrkAlgorithms/TrkTrackSummaryUpdater/test/TrackSummaryUpdater_test.cxx
@@ -0,0 +1,238 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+/*
+ */
+/**
+ * @file TrkTrackSummaryUpdater/test/TrackSummaryUpdater_test.cxx
+ * @author Shaun Roe
+ * @date Nov, 2020
+ * @brief Some tests for TrackSummaryUpdater algorithm in the Boost framework
+ */
+ 
+ 
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_MODULE TEST_TRKTRACKSUMMARYUPDATER
+//
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Woverloaded-virtual"
+#include <boost/test/unit_test.hpp>
+
+#pragma GCC diagnostic pop
+
+//
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "CxxUtils/checker_macros.h"
+#include "TInterpreter.h"
+//
+#include "GaudiKernel/IAppMgrUI.h"
+#include "GaudiKernel/SmartIF.h"
+#include "GaudiKernel/SystemOfUnits.h"
+#include "GaudiKernel/PhysicalConstants.h"
+#include "GaudiKernel/EventContext.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "CxxUtils/ubsan_suppress.h"
+#include "PutTrackCollectionsInSG.h"
+
+#include "TrkToolInterfaces/IExtendedTrackSummaryTool.h"
+#include "StoreGate/ReadHandleKey.h"
+#include "TrkTrack/TrackCollection.h"
+#include "../TrkTrackSummaryUpdater/TrackSummaryUpdater.h"
+#include "TrkTrackSummary/TrackSummary.h"
+#include <vector>
+#include "test/SummaryToolStub.h"
+
+ATLAS_NO_CHECK_FILE_THREAD_SAFETY; // This test uses global svcLoc.
+
+// Gaudi fixture
+class GaudiFixture {
+ public:
+   ISvcLocator * 
+   svcLoc(){
+     return m_svcLoc;
+   }
+   
+   IToolSvc *
+   toolSvc(){
+     return m_toolSvc;
+   }
+   
+   StoreGateSvc* 
+   storeGateSvc(){
+    return m_sg;
+   }
+
+   GaudiFixture(const std::string & joPath = "TrkTrackSummaryUpdater/TrackSummaryUpdater_test.txt") {
+     setUpGaudi(joPath);
+   }
+ 
+   ~GaudiFixture() {
+     tearDownGaudi();
+   }
+   
+ private:
+   void 
+   setUpGaudi(const std::string & joPath) {
+     CxxUtils::ubsan_suppress ([]() { TInterpreter::Instance(); } );
+     m_appMgr = Gaudi::createApplicationMgr();
+     m_svcLoc = m_appMgr;
+     m_svcMgr = m_appMgr;
+     m_propMgr = m_appMgr;
+     m_propMgr->setProperty( "EvtSel",         "NONE" ).ignore() ;
+     m_propMgr->setProperty( "JobOptionsType", "FILE" ).ignore();
+     m_propMgr->setProperty( "JobOptionsPath", joPath ).ignore();
+     m_toolSvc = m_svcLoc->service("ToolSvc");
+     m_appMgr->configure().ignore();
+     m_appMgr->initialize().ignore();
+     m_sg = nullptr;
+     m_svcLoc->service ("StoreGateSvc", m_sg).ignore();
+   }
+ 
+   void 
+   tearDownGaudi() {
+     m_svcMgr->finalize().ignore();
+     m_appMgr->finalize().ignore();
+     m_appMgr->terminate().ignore();
+     m_svcLoc->release();
+     m_svcMgr->release();
+     Gaudi::setInstance( static_cast<IAppMgrUI*>(nullptr) );
+   }
+ 
+   StoreGateSvc* 
+   evtStore(){
+     return m_sg;
+   }
+ 
+   //member variables for Core Gaudi components
+   IAppMgrUI*               m_appMgr{nullptr};
+   SmartIF<ISvcLocator>     m_svcLoc;
+   SmartIF<ISvcManager>     m_svcMgr;
+   SmartIF<IToolSvc>        m_toolSvc;
+   SmartIF<IProperty>       m_propMgr;
+   StoreGateSvc*            m_sg{ nullptr };
+ };
+ 
+
+
+ 
+BOOST_AUTO_TEST_SUITE(TrackSummaryUpdaterTest)
+  
+  GaudiFixture g("TrkTrackSummaryUpdater/TrackSummaryUpdater_test.txt");
+  auto  pSvcLoc=g.svcLoc();
+  auto  pToolSvc=g.toolSvc();
+
+  BOOST_AUTO_TEST_CASE( sanityCheck ){
+    const bool svcLocatorIsOk=(pSvcLoc != nullptr);
+    BOOST_TEST(svcLocatorIsOk);
+    const bool toolSvcIsOk = ( pToolSvc != nullptr);
+    BOOST_TEST(toolSvcIsOk);
+  }
+  
+  BOOST_AUTO_TEST_CASE(execute){
+    auto pAlg = new PutTrackCollectionsInSG("PutCollectionsInSG",pSvcLoc);
+    pAlg->addRef();
+    BOOST_TEST(pAlg->execute().isSuccess());
+    std::string collectionKey1("StoreGateSvc+TrackCollectionKey1");
+    SG::ReadHandle<TrackCollection> thisTrackCollection1 (collectionKey1);
+    BOOST_TEST(thisTrackCollection1->size() == 2);
+    //
+    IAlgTool* toolInterface{};
+    //SummaryToolStub is in this package, it is a dummy SummaryTool with the appropriate
+    //interface (inheriting from IExtendedTrackSummaryTool)
+    BOOST_TEST(pToolSvc->retrieveTool("SummaryToolStub", toolInterface).isSuccess());
+    //Create TrackSummary in the output collection
+    auto pUpdateAlg = new Trk::TrackSummaryUpdater("Updater1",pSvcLoc);
+    pUpdateAlg->addRef();
+    BOOST_TEST_MESSAGE("Testing Summary Creation on the track");
+    BOOST_TEST(pUpdateAlg->setProperty("InputTracksKey","TrackCollectionKey1").isSuccess());
+    BOOST_TEST(pUpdateAlg->setProperty("OutputTracksKey","SummaryCreation").isSuccess());
+    BOOST_TEST(pUpdateAlg->setProperty("SummaryTool", "SummaryToolStub").isSuccess());
+    //The following means that "computeAndReplaceTrackSummary" should be called
+    BOOST_TEST(pUpdateAlg->setProperty("UpdateSharedHits", false).isSuccess());
+    //initialize() is necessary here
+    BOOST_TEST(pUpdateAlg->initialize().isSuccess());
+    BOOST_TEST(pUpdateAlg->execute().isSuccess());
+    std::vector<std::string> keysPresent{};
+    g.storeGateSvc()->keys<TrackCollection>(keysPresent);
+    BOOST_TEST_MESSAGE("StoreGate now contains the following entries: ");
+    for (auto & n: keysPresent){
+      BOOST_TEST_MESSAGE(n);
+    }
+    std::string createdCollectionKey("SummaryCreation");
+    SG::ReadHandle<TrackCollection> createdCollection (createdCollectionKey);
+    BOOST_TEST(createdCollection->size() == 2);
+    //
+    const std::vector<std::string> expectedKeys{"SummaryCreation","TrackCollectionKey1", "TrackCollectionKey2"};
+    g.storeGateSvc()->keys<TrackCollection>(keysPresent);
+    BOOST_TEST(keysPresent == expectedKeys, boost::test_tools::per_element());
+    //
+    const int valueSetForNHitsUsed{3};
+    for (const auto & aTrack: *createdCollection){
+      const auto & pThisSummary = aTrack->trackSummary();
+      const auto valueReadBackForNHitsUsed = pThisSummary->numberOfUsedHitsdEdx();
+      BOOST_TEST(valueReadBackForNHitsUsed == valueSetForNHitsUsed);
+    }
+    //Update the Additional Info on the existing track summary, using numberOfUsedHitsdEdx
+    //as an example of a value to update. The update values are hard coded in the 
+    //SummaryToolStub code in this package, which is a mock SummaryTool
+    BOOST_TEST_MESSAGE("Testing Summary UpdateAdditionalInfo on the track");
+    auto pUpdateAlg2 = new Trk::TrackSummaryUpdater("Updater2",pSvcLoc);
+    pUpdateAlg2->addRef();
+    pUpdateAlg2->setProperty("InputTracksKey","SummaryCreation").ignore();
+    pUpdateAlg2->setProperty("OutputTracksKey","AdditionalInfoUpdated").ignore();
+    pUpdateAlg2->setProperty("SummaryTool", "SummaryToolStub").ignore();
+    //The following means that "updateAdditionalInfo" should be called
+    BOOST_TEST(pUpdateAlg2->setProperty("UpdateSharedHits", false).isSuccess());
+    BOOST_TEST(pUpdateAlg2->setProperty("UpdateAdditionalInfo", true).isSuccess());
+    BOOST_TEST(pUpdateAlg2->initialize().isSuccess());
+    BOOST_TEST(pUpdateAlg2->execute().isSuccess());
+    keysPresent.clear();
+    g.storeGateSvc()->keys<TrackCollection>(keysPresent);
+    BOOST_TEST_MESSAGE("StoreGate now contains the following entries: ");
+    for (auto & n: keysPresent){
+      BOOST_TEST_MESSAGE(n);
+    }
+    std::string updatedCollectionKey("AdditionalInfoUpdated");
+    SG::ReadHandle<TrackCollection> updatedCollection(createdCollectionKey);
+    const int updatedValueForNHitsUsed{4};
+    for (const auto & aTrack: *updatedCollection){
+      const auto & pThisSummary = aTrack->trackSummary();
+      const auto valueReadBackForNHitsUsed = pThisSummary->numberOfUsedHitsdEdx();
+      BOOST_TEST(valueReadBackForNHitsUsed == updatedValueForNHitsUsed);
+    }
+    //Update Shared Hits on an existing track summary
+    BOOST_TEST_MESSAGE("Testing Summary UpdateSharedHits on the track");
+    auto pUpdateAlg3 = new Trk::TrackSummaryUpdater("Updater3",pSvcLoc);
+    pUpdateAlg3->addRef();
+    pUpdateAlg3->setProperty("InputTracksKey","SummaryCreation").ignore();
+    pUpdateAlg3->setProperty("OutputTracksKey","SharedInfoUpdated").ignore();
+    pUpdateAlg3->setProperty("SummaryTool", "SummaryToolStub").ignore();
+    //The following means that "UpdateSharedHits" should be called
+    BOOST_TEST(pUpdateAlg3->setProperty("UpdateSharedHits", true).isSuccess());
+    BOOST_TEST(pUpdateAlg3->setProperty("UpdateAdditionalInfo", false).isSuccess());
+    BOOST_TEST(pUpdateAlg3->initialize().isSuccess());
+    BOOST_TEST(pUpdateAlg3->execute().isSuccess());
+    keysPresent.clear();
+    g.storeGateSvc()->keys<TrackCollection>(keysPresent);
+    BOOST_TEST_MESSAGE("StoreGate now contains the following entries: ");
+    for (auto & n: keysPresent){
+      BOOST_TEST_MESSAGE(n);
+    }
+    std::string updatedSharedCollectionKey("SharedInfoUpdated");
+    SG::ReadHandle<TrackCollection> updatedSharedCollection(createdCollectionKey);
+    const int updatedSharedHitCount{20};
+    for (const auto & aTrack: *updatedCollection){
+      const auto & pThisSummary = aTrack->trackSummary();
+      const auto valueReadBackSharedHits = pThisSummary->get(Trk::SummaryType::numberOfSCTSharedHits);
+      const auto valueReadBackForNHitsUsed = pThisSummary->numberOfUsedHitsdEdx();
+      BOOST_TEST(valueReadBackForNHitsUsed == valueSetForNHitsUsed);
+      BOOST_TEST(valueReadBackSharedHits == updatedSharedHitCount);
+    }
+  }
+  
+BOOST_AUTO_TEST_SUITE_END()
+
+
-- 
GitLab