From b44d5ccadcbddf05ea75ee6dc30f3e43afc721d9 Mon Sep 17 00:00:00 2001
From: Goetz Gaycken <goetz.gaycken@cern.ch>
Date: Fri, 16 Oct 2020 14:25:19 +0200
Subject: [PATCH] Propagate TrackingGeometry conditions data to
 TrackingGeometrySvc and detector store.

In some places TrackingVolume identity comparisons are performbed by comparing
pointers. This fails in case the volumes originate from different instances of
otherwise identical TrackingGeoemtries. To mitigate this problem, the conditions
algorithm will now propagate the conditions data to the service and the detector
store.
---
 .../TrackingGeometryCondAlg/CMakeLists.txt    |  2 +
 .../TrackingGeometryCondAlg.h                 |  2 +
 .../src/TrackingGeometryCondAlg.cxx           | 21 ++++-
 .../TrkDetDescrSvc/TrackingGeometryMirror.h   | 88 +++++++++++++++++++
 .../TrkDetDescrSvc/TrackingGeometrySvc.h      | 13 +--
 .../src/TrackingGeometrySvc.cxx               | 81 ++++++++++++++---
 .../TrkGeometry/TrackingGeometry.h            | 10 ++-
 7 files changed, 197 insertions(+), 20 deletions(-)
 create mode 100644 Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometryMirror.h

diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt b/Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt
index fcae79acc82..03917148f91 100644
--- a/Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt
+++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt
@@ -16,6 +16,7 @@ atlas_depends_on_subdirs(
    Tracking/TrkDetDescr/TrkGeometry
    InnerDetector/InDetDetDescr/InDetReadoutGeometry
    PRIVATE
+   Tracking/TrkDetDescr/TrkDetDescrSvc
     )
 
 find_package( Eigen )
@@ -33,6 +34,7 @@ atlas_add_component( TrackingGeometryCondAlg
    TrkDetDescrUtils
    TrkGeometry
    InDetReadoutGeometry
+   TrkDetDescrSvcLib
     )
 
 # Install files from the package:
diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h b/Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h
index b450935f4c7..8cb72f154db 100644
--- a/Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h
+++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h
@@ -15,6 +15,7 @@
 #include "TrkDetDescrInterfaces/IGeometryBuilderCond.h"
 #include "TrkDetDescrInterfaces/IGeometryProcessor.h"
 #include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "TrkDetDescrInterfaces/ITrackingGeometrySvc.h"
 
 #include "GaudiKernel/ICondSvc.h"
 #include "GaudiKernel/ToolHandle.h"
@@ -40,6 +41,7 @@ private:
   ServiceHandle<ICondSvc> m_condSvc{this, "CondSvc", "CondSvc"};
   ToolHandle<Trk::IGeometryBuilderCond>           m_trackingGeometryBuilder {this, "GeometryBuilder", ""};
   ToolHandleArray<Trk::IGeometryProcessor>    m_geometryProcessors ;
+  ServiceHandle<ITrackingGeometrySvc>         m_trackingGeometrySvc {this,"TrackingGeometrySvc",""};
 };
 }
 #endif //TRACKINGGEOMETRYCONDALG_H
diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx b/Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx
index 1a2dad69db8..7eb5799f3ca 100644
--- a/Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx
+++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx
@@ -6,13 +6,14 @@
 // Trk includes
 #include "TrkGeometry/TrackingGeometry.h"
 #include "AthenaKernel/IOVSvcDefs.h"
+#include "TrkDetDescrSvc/TrackingGeometrySvc.h"
 
 #include "TrackingGeometryCondAlg/TrackingGeometryCondAlg.h"
-
+#include "TrkDetDescrSvc/TrackingGeometryMirror.h"
 
 Trk::TrackingGeometryCondAlg::TrackingGeometryCondAlg(const std::string& name, ISvcLocator* pSvcLocator)
   : AthReentrantAlgorithm(name, pSvcLocator),
-    m_geometryProcessors(this) 
+    m_geometryProcessors(this)
 {
   declareProperty("GeometryProcessors", m_geometryProcessors);
 }
@@ -33,6 +34,9 @@ StatusCode Trk::TrackingGeometryCondAlg::initialize()
     ATH_MSG_FATAL( "Could not retrieve " << m_geometryProcessors );
     return StatusCode::FAILURE;
   }
+  if (!m_trackingGeometrySvc.name().empty()) {
+     ATH_CHECK( m_trackingGeometrySvc.retrieve() );
+  }
 
   return StatusCode::SUCCESS;
 }
@@ -66,5 +70,18 @@ StatusCode Trk::TrackingGeometryCondAlg::execute(const EventContext& ctx) const{
       }
   }
   ATH_CHECK(writeHandle.record(trackingGeometryPair.first,trackingGeometry));
+  if (msgLvl(MSG::VERBOSE)) {
+     Trk::TrackingGeometryMirror dumper(trackingGeometry);
+     dumper.dump(msg(MSG::VERBOSE), name() + " TrackingGeometry dump " );
+  }
+  if (!m_trackingGeometrySvc.name().empty()) {
+     Trk::TrackingGeometrySvc *the_service = dynamic_cast<Trk::TrackingGeometrySvc *>(&(*m_trackingGeometrySvc));
+     if (!the_service) {
+        ATH_MSG_FATAL("Expected a special TrackingGeometrySvc implementation derived from Trk::TrackingGeometrySvc but got " << typeid(the_service).name() );
+     }
+     ATH_MSG_DEBUG("Set TrackingGeometry " << static_cast<const void *>(trackingGeometry) << " in svc " << m_trackingGeometrySvc.name() );
+     the_service->setTrackingGeometry(trackingGeometry);
+  }
+
   return StatusCode::SUCCESS;
 }
diff --git a/Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometryMirror.h b/Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometryMirror.h
new file mode 100644
index 00000000000..8ae68a04577
--- /dev/null
+++ b/Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometryMirror.h
@@ -0,0 +1,88 @@
+#ifndef _Trk_TrackingGeometryMirror_h_
+#define _Trk_TrackingGeometryMirror_h_
+namespace Trk {
+   class TrackingGeometryMirror;
+}
+#include "TrkGeometry/TrackingGeometry.h"
+#include "AthenaKernel/CLASS_DEF.h"
+
+#include "TrkGeometry/Layer.h"
+#include "TrkVolumes/VolumeBounds.h"
+#include "TrkGeometry/TrackingVolume.h"
+#include "TrkDetDescrUtils/BinnedArray.h"
+#include <iostream>
+
+namespace Trk {
+
+   /// Helper class to provide the same objects as an existing TrackingGeometry without claiming ownership over these objects.
+   /// The class is solely meant to allow using the TrackingGeometry conditions data and the TrackingGeometrySvc at the same time.
+   class TrackingGeometryMirror : public Trk::TrackingGeometry {
+   public:
+      TrackingGeometryMirror(TrackingGeometry *src) : TrackingGeometry(nullptr,src->m_navigationLevel) {
+         update(src);
+      }
+
+      ~TrackingGeometryMirror() {
+         cleanup();
+      }
+
+      void update(TrackingGeometry *src) {
+         m_world = src->m_world;
+         m_beam = src->m_beam;
+         /** The unique boundary Layers */
+         m_boundaryLayers = src->m_boundaryLayers;
+         /** The Volumes in a map for later finding */
+         m_trackingVolumes = src->m_trackingVolumes;
+      }
+
+      void cleanup() {
+         m_world=nullptr;
+         m_beam=nullptr;
+         m_boundaryLayers.clear();
+         m_trackingVolumes.clear();
+      }
+
+      template <class T_Ostream>
+      void dump(T_Ostream &out, const std::string &head) const {
+         for(const std::pair<const Layer*,int> &bound_layers : m_boundaryLayers) {
+            out << head << " [" << bound_layers.second  << "] ";
+            dumpLayer(out, "",bound_layers.first);
+         }
+         int counter=0;
+         for (const std::pair<const std::string, const TrackingVolume*> &volume : m_trackingVolumes) {
+            out << head << " [" << counter++  << "] " << volume.first << " volumeBound=" << volume.second->volumeBounds() << std::endl;
+            if (volume.second->confinedArbitraryLayers()) {
+               int j=0;
+               for(const Layer* confined_layer :  *volume.second->confinedArbitraryLayers()) {
+                  out << head << " [" << counter++  << "] " << volume.first << " confinedArbitrary layer " << j++ << " ";
+                  dumpLayer(out, "",confined_layer);
+               }
+            }
+            if (volume.second->confinedLayers()) {
+               int j=0;
+               for(const Layer* confined_layer :  volume.second->confinedLayers()->arrayObjects()) {
+                  out << head << " [" << counter++  << "] " << volume.first << " confined layer" << j++ << " ";
+                  dumpLayer(out,"",confined_layer);
+               }
+            }
+         }
+      }
+
+   protected:
+      template <class T_Ostream>
+      static void dumpLayer(T_Ostream &out, const std::string &head, const Layer *layer) {
+         if (layer) {
+            out << head
+                << layer->layerIndex().value() << " [t=" << layer->layerType() << "] d=" << layer->thickness();
+            if (layer->representingVolume()) {
+               out << " vol=" << layer->representingVolume()->volumeBounds();
+            }
+            out << layer->surfaceRepresentation();
+         }
+         out << std::endl;
+
+      }
+   };
+}
+
+#endif
diff --git a/Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometrySvc.h b/Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometrySvc.h
index 22f57382df0..2a7bf6788b1 100755
--- a/Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometrySvc.h
+++ b/Tracking/TrkDetDescr/TrkDetDescrSvc/TrkDetDescrSvc/TrackingGeometrySvc.h
@@ -21,7 +21,7 @@
 
 #ifdef TRKDETDESCR_MEMUSAGE   
 #include "TrkDetDescrUtils/MemoryLogger.h"
-#endif    
+#endif
 
 
 class StoreGateSvc;
@@ -76,8 +76,10 @@ namespace Trk {
       //!< Standard Destructor
       virtual ~TrackingGeometrySvc();
   
-    
+      void setTrackingGeometry(const Trk::TrackingGeometry *ptr);
+
     private:
+      void trackingGeometryNotSet() const;
       //!< cached pointers:
       ISvcLocator*                                m_pSvcLocator {nullptr};
       StoreGateSvc*                               m_pDetStore   {nullptr};
@@ -85,6 +87,7 @@ namespace Trk {
       ToolHandle<Trk::IGeometryBuilder>           m_trackingGeometryBuilder {this, "GeometryBuilder", ""};
       //!< the actual building tool
       mutable const Trk::TrackingGeometry*        m_trackingGeometry     {nullptr};
+
       //!< the cached TrackingGeometry
       Gaudi::Property<std::string>                m_trackingGeometryName {this, "TrackingGeometryName", "AtlasTrackingGeometry"};
       //!< the name of the TrackingGeometry
@@ -103,13 +106,13 @@ namespace Trk {
       Gaudi::Property<bool>                       m_rerunOnCallback {this, "RerunOnCallback", false};
       //!< enables the callback
       Gaudi::Property<bool>                       m_buildGeometryFromTagInfo {this, "BuildGeometryFromTagInfo", true};
-  
-          
+      Gaudi::Property<bool>                       m_useConditionsData {this, "UseExternalConditionsData", false};
   };
 }
 
 inline const Trk::TrackingGeometry* Trk::TrackingGeometrySvc::trackingGeometry() const
-  { return m_trackingGeometry; }
+{  if (!m_trackingGeometry) { trackingGeometryNotSet(); }
+   return m_trackingGeometry; }
 
 inline const std::string& Trk::TrackingGeometrySvc::trackingGeometryName() const
   { return m_trackingGeometryName; }
diff --git a/Tracking/TrkDetDescr/TrkDetDescrSvc/src/TrackingGeometrySvc.cxx b/Tracking/TrkDetDescr/TrkDetDescrSvc/src/TrackingGeometrySvc.cxx
index 1b1899bda7a..f4444202dba 100755
--- a/Tracking/TrkDetDescr/TrkDetDescrSvc/src/TrackingGeometrySvc.cxx
+++ b/Tracking/TrkDetDescr/TrkDetDescrSvc/src/TrackingGeometrySvc.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -7,6 +7,7 @@
 ///////////////////////////////////////////////////////////////////
 
 // Trk
+#include "TrkDetDescrSvc/TrackingGeometryMirror.h"
 #include "TrkGeometry/TrackingGeometry.h"
 #include "TrkGeometry/TrackingVolume.h"
 #include "TrkGeometry/Layer.h"
@@ -44,18 +45,23 @@ Trk::TrackingGeometrySvc::~TrackingGeometrySvc()
 /** Initialize Service */
 StatusCode Trk::TrackingGeometrySvc::initialize()
 {
+  // get the DetectorStore
+  ATH_CHECK( service("DetectorStore", m_pDetStore ) );
+
+  // alternative mode which only uses an externally provided TrackingGeometry rather than building its own
+  if (m_useConditionsData) {
+     for (auto &handle : m_geometryProcessors ) {
+         handle.disable();
+     }
+     m_trackingGeometryBuilder.disable();
+     return StatusCode::SUCCESS;
+  }
+
   if (m_geometryProcessors.retrieve().isFailure()){
       ATH_MSG_FATAL( "Could not retrieve " << m_geometryProcessors );
       return StatusCode::FAILURE;
   }
 
-  // get the DetectorStore
-  if (service("DetectorStore", m_pDetStore ).isFailure()) 
-  {
-    ATH_MSG_FATAL( "DetectorStore service not found!" );
-    return StatusCode::FAILURE;
-  }
-
   // get the key -- from StoreGate (DetectorStore)
   std::vector< std::string > tagInfoKeys = m_pDetStore->keys<TagInfo> ();
   std::string tagInfoKey = "";
@@ -93,6 +99,9 @@ StatusCode Trk::TrackingGeometrySvc::initialize()
 
 StatusCode Trk::TrackingGeometrySvc::trackingGeometryInit(IOVSVC_CALLBACK_ARGS_P(I,keys))
 {
+    if (m_useConditionsData) {
+       ATH_MSG_FATAL("Logic error: TrackingGeometry init callback called despite being configured to use external TrackingGeometries provided by a conditions algorithm.");
+    }
     // Retrieve the tracking geometry builder tool   ----------------------------------------------------    
     if (!m_trackingGeometryBuilder.empty() && m_trackingGeometryBuilder.retrieve().isFailure()) {
         ATH_MSG_FATAL( "Failed to retrieve tool '" << m_trackingGeometryBuilder << "'. Aborting." );
@@ -125,7 +134,7 @@ StatusCode Trk::TrackingGeometrySvc::trackingGeometryInit(IOVSVC_CALLBACK_ARGS_P
     if (needsInit || !m_callbackStringCheck) {
         // cleanup the geometry if you have one 
         // (will delete what is in detector store, because new one will overwrite old one)
-        delete m_trackingGeometry; m_trackingGeometry = 0;
+        m_trackingGeometry = nullptr;
     
 #ifdef TRKDETDESCR_MEMUSAGE           
         // memory monitoring    
@@ -179,7 +188,12 @@ StatusCode Trk::TrackingGeometrySvc::trackingGeometryInit(IOVSVC_CALLBACK_ARGS_P
 #endif            
           }
       }
-    
+
+      if (msgLvl(MSG::VERBOSE)) {
+         Trk::TrackingGeometryMirror mirror(atlasTrackingGeometry);
+         mirror.dump(msg(MSG::VERBOSE), name()+" TrackingGeometry dump ");
+         mirror.cleanup();
+      }
       // record the resulting TrackingGeometry 
       if (m_pDetStore->record(atlasTrackingGeometry, m_trackingGeometryName, false).isFailure() ){
          ATH_MSG_WARNING( "Couldn't write TrackingGeometry to DetectorStore." );
@@ -189,6 +203,41 @@ StatusCode Trk::TrackingGeometrySvc::trackingGeometryInit(IOVSVC_CALLBACK_ARGS_P
     return StatusCode::SUCCESS;
 }
 
+void Trk::TrackingGeometrySvc::setTrackingGeometry(const Trk::TrackingGeometry *ptr) {
+   if (!m_useConditionsData) {
+      ATH_MSG_FATAL("Logic error:  external TrackingGeometry provided despite being configured to build an internal one.");
+   }
+   if (m_pDetStore->contains<Trk::TrackingGeometry>(m_trackingGeometryName)) {
+      const TrackingGeometry *mirror;
+      if (m_pDetStore->retrieve(mirror, m_trackingGeometryName).isFailure()) {
+         ATH_MSG_FATAL("TrackingGeometry " << m_trackingGeometryName << " exists, but cannot be retrieved.");
+      }
+      TrackingGeometry *non_const_mirror ATLAS_NOT_THREAD_SAFE = const_cast<TrackingGeometry *>(mirror);
+      static_cast<Trk::TrackingGeometryMirror *>(non_const_mirror)->update(const_cast<TrackingGeometry *>(ptr));
+      if (msgLvl(MSG::VERBOSE)) {
+         ATH_MSG_VERBOSE( "Setting TrackingGeometry from cond alg ptr="  << static_cast<const void *>(ptr));
+         static_cast<const Trk::TrackingGeometryMirror *>(mirror)->dump(msg(MSG::VERBOSE), "external TrackingGeometry dump ");
+      }
+   }
+   else {
+      std::unique_ptr<Trk::TrackingGeometryMirror> mirror=std::make_unique<Trk::TrackingGeometryMirror>(const_cast<TrackingGeometry *>(ptr));
+      if (msgLvl(MSG::VERBOSE)) {
+         ATH_MSG_VERBOSE( "Setting TrackingGeometry from cond alg ptr="  << static_cast<const void *>(ptr));
+         mirror->dump(msg(MSG::VERBOSE), "external TrackingGeometry dump ");
+      }
+
+      // record the resulting TrackingGeometry
+      if (m_pDetStore->record(static_cast<TrackingGeometry *>(mirror.release()), m_trackingGeometryName, false).isFailure() ){
+         ATH_MSG_WARNING( "Couldn't write TrackingGeometry to DetectorStore." );
+      } else {
+         ATH_MSG_DEBUG( "initialize() successful: TrackingGeometry '" << m_trackingGeometryName << "' built and written to DetectorStore." );
+      }
+   }
+   m_trackingGeometry=ptr;
+}
+void Trk::TrackingGeometrySvc::trackingGeometryNotSet() const {
+   ATH_MSG_WARNING( "TrackingGeometry not set  ptr="  << static_cast<const void *>(m_trackingGeometry));
+}
 
 /** Finalize Service */
 StatusCode Trk::TrackingGeometrySvc::finalize()
@@ -201,6 +250,17 @@ StatusCode Trk::TrackingGeometrySvc::finalize()
     ATH_MSG_INFO( "[ memory usage ] ---------------------------------------------------------"  );
 #endif
 
+    if (m_useConditionsData) {
+       const TrackingGeometry *clone=nullptr;
+       if (m_pDetStore->retrieve(clone, m_trackingGeometryName).isFailure() ){
+          ATH_MSG_WARNING( "Failed to retrieve TrackingGeometry " << m_trackingGeometryName << " from DetectorStore." );
+       }
+       if (clone) {
+          static_cast<Trk::TrackingGeometryMirror *>(const_cast<TrackingGeometry *>(clone))->cleanup();
+          ATH_MSG_WARNING( "Cleaned TrackingGeometryMirror " << m_trackingGeometryName << "." );
+       }
+    }
+
     ATH_MSG_INFO( "finalize() successful." );
     return StatusCode::SUCCESS;
 }
@@ -217,4 +277,3 @@ StatusCode Trk::TrackingGeometrySvc::queryInterface(const InterfaceID& riid, voi
   addRef();
   return StatusCode::SUCCESS;
 }
-
diff --git a/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h b/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h
index 48d2fea91fc..0527ad54dfc 100755
--- a/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h
+++ b/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h
@@ -63,13 +63,19 @@ namespace Trk {
     
     friend class GeometryBuilderCond;
     friend class IGeometryBuilderCond;
-  
+
+    // give access to private members to allow the  class below to mirror a TrackingGeometry.
+    // This is needed for a temporary workaround to allow using the TrackingGeometryCondAlg and
+    // TrackingGeometrySvc at the same time.
+    // @TODO revert once the TrackingGeometrySvc is completly replaced
+    friend class TrackingGeometryMirror;
+
     public :
       /** Constructor */
       TrackingGeometry(const TrackingVolume* highestVolume, NavigationLevel navlevel=globalSearch);
       
       /** Destructor */
-      ~TrackingGeometry();
+      virtual ~TrackingGeometry();
       
       /** return the world */
       const TrackingVolume* highestTrackingVolume() const;
-- 
GitLab