From 0420320c1a35fb627db4e78714f208163d2025a0 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Mon, 28 May 2018 16:46:59 +0200
Subject: [PATCH] Improve selective handling of subdetectors in DDDB

---
 DDCore/include/DD4hep/DD4hepUI.h              | 27 +++++++-
 DDCore/include/DD4hep/Volumes.h               |  4 +-
 DDCore/src/DD4hepRootPersistency.cpp          | 58 ++++++++++-------
 DDCore/src/DD4hepUI.cpp                       | 64 ++++++++++++++++++-
 DDCore/src/plugins/StandardPlugins.cpp        | 40 ++++++++++--
 UtilityApps/src/plugin_runner.cpp             |  2 +-
 .../DDDB/include/DDDB/DDDBConditionsLoader.h  |  4 +-
 examples/DDDB/include/DDDB/DDDBConversion.h   |  5 ++
 examples/DDDB/include/DDDB/DDDBDimension.h    |  1 +
 examples/DDDB/include/DDDB/DDDBHelper.h       |  2 +-
 examples/DDDB/include/DDDB/DDDBReader.h       |  2 +-
 11 files changed, 167 insertions(+), 42 deletions(-)

diff --git a/DDCore/include/DD4hep/DD4hepUI.h b/DDCore/include/DD4hep/DD4hepUI.h
index 3517dcef9..7bd6e19c5 100644
--- a/DDCore/include/DD4hep/DD4hepUI.h
+++ b/DDCore/include/DD4hep/DD4hepUI.h
@@ -36,7 +36,9 @@ namespace dd4hep {
       Detector& m_detDesc;
       Handle<NamedObject> m_condMgr;
       Handle<NamedObject> m_alignMgr;
-    
+      /// Default visualiztion level
+      int visLevel = 4;
+
     public:
       /// Default constructor
       DD4hepUI(Detector& instance);
@@ -48,12 +50,20 @@ namespace dd4hep {
       Detector* detectorDescription()  const;
       /// Set the printout level from the interactive prompt
       PrintLevel setPrintLevel(PrintLevel level)   const;
+      /// Set the visualization level when invoking the display
+      int setVisLevel(int level);
 
       /// Install the dd4hep conditions manager object
       Handle<NamedObject> conditionsMgr()  const;
       /// Load conditions from file
       long loadConditions(const std::string& fname)  const;
-    
+
+      /// Dump the entire detector description object to a root file
+      long saveROOT(const char* file_name)    const;
+
+      /// Import the entire detector description object from a root file
+      long importROOT(const char* file_name)    const;
+
       /// Install the dd4hep alignment manager object
       Handle<NamedObject> alignmentMgr()  const;
 
@@ -66,12 +76,23 @@ namespace dd4hep {
       virtual long apply(const char* factory, int argc, char** argv) const;
       /// Detector interface: Read any geometry description or alignment file
       virtual void fromXML(const std::string& fname, DetectorBuildType type = BUILD_DEFAULT) const;
+
+      /// Detector interface: Draw the scene on a OpenGL pane
+      virtual void draw() const;
       /// Detector interface: Re-draw the entire scene
       virtual void redraw() const;
+
+      /// Detector interface: Draw detector sub-tree the scene on a OpenGL pane
+      virtual void drawSubtree(const char* path) const;
+      /// Detector interface: Re-draw the entire sub-tree scene
+      virtual void redrawSubtree(const char* path) const;
+
       /// Dump the volume tree
       virtual long dumpVols(int argc=0, char** argv=0)  const;
-      /// Dump the DetElement tree
+      /// Dump the DetElement tree with placement volumes
       virtual long dumpDet()  const;
+      /// Dump the raw DetElement tree 
+      virtual long dumpStructure()  const;
     };
     
   }  
diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h
index 6f730b9fa..64cd3c064 100644
--- a/DDCore/include/DD4hep/Volumes.h
+++ b/DDCore/include/DD4hep/Volumes.h
@@ -126,7 +126,7 @@ namespace dd4hep {
     /// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore
     virtual void Release() const  override;
     /// Enable ROOT persistency
-    ClassDefOverride(PlacedVolumeExtension,1);
+    ClassDefOverride(PlacedVolumeExtension,200);
   };
 
   /// Handle class holding a placed volume (also called physical volume)
@@ -235,7 +235,7 @@ namespace dd4hep {
     /// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore
     virtual void Release() const  override;
     /// Enable ROOT persistency
-    ClassDefOverride(VolumeExtension,1);
+    ClassDefOverride(VolumeExtension,200);
   };
 
   /// Handle class holding a placed volume (also called physical volume)
diff --git a/DDCore/src/DD4hepRootPersistency.cpp b/DDCore/src/DD4hepRootPersistency.cpp
index eddc3ba2e..2c8f6ed04 100644
--- a/DDCore/src/DD4hepRootPersistency.cpp
+++ b/DDCore/src/DD4hepRootPersistency.cpp
@@ -43,13 +43,20 @@ int DD4hepRootPersistency::save(Detector& description, const char* fname, const
         persist->m_segments[ro].second = ro.segmentation().segmentation();
       }
     }
-    for( const auto& mgr : persist->m_data->m_volManager->managers )  {
-      for( const auto& v : mgr.second->volumes )  {
-        persist->nominals[v.second->element] = v.second->element.nominal();
+    if ( persist->volumeManager().isValid() )   {
+      for( const auto& mgr : persist->m_data->m_volManager->managers )  {
+        for( const auto& v : mgr.second->volumes )  {
+          persist->nominals[v.second->element] = v.second->element.nominal();
+        }
       }
+      printout(ALWAYS,"DD4hepRootPersistency","+++ Saving %ld nominals....",persist->nominals.size());
     }
-    printout(ALWAYS,"DD4hepRootPersistency","+++ Saving %ld nominals....",persist->nominals.size());
-
+    else  {
+      printout(ALWAYS,
+               "DD4hepRootPersistency","+++ No valid Volume manager. No nominals saved.",
+               persist->nominals.size());
+    }
+    
     /// Now we write the object
     int nBytes = persist->Write(instance);
     f->Close();
@@ -95,28 +102,33 @@ int DD4hepRootPersistency::load(Detector& description, const char* fname, const
       printout(ALWAYS,"DD4hepRootPersistency",
                "+++ Fixed %ld segmentation objects.",persist->m_segments.size());
       persist->m_segments.clear();
-      const auto& sdets = persist->volumeManager()->subdetectors;
-      size_t num[3] = {0,0,0};
-      for( const auto& vm : sdets )  {
-        VolumeManager::Object* obj = vm.second.ptr();
-        obj->system = obj->id.field("system");
-        if ( 0 != obj->system )   {
+      if ( persist->volumeManager().isValid() )   {
+        const auto& sdets = persist->volumeManager()->subdetectors;
+        size_t num[3] = {0,0,0};
+        for( const auto& vm : sdets )  {
+          VolumeManager::Object* obj = vm.second.ptr();
+          obj->system = obj->id.field("system");
+          if ( 0 != obj->system )   {
+            printout(ALWAYS,"DD4hepRootPersistency",
+                     "+++ Fixed VolumeManager.system for %-24s  %6ld volumes %4ld sdets %4ld mgrs.",
+                     obj->detector.path().c_str(), obj->volumes.size(),
+                     obj->subdetectors.size(), obj->managers.size());
+            num[0] += obj->volumes.size();
+            num[1] += obj->subdetectors.size();
+            num[2] += obj->managers.size();
+            continue;
+          }
           printout(ALWAYS,"DD4hepRootPersistency",
-                   "+++ Fixed VolumeManager.system for %-24s  %6ld volumes %4ld sdets %4ld mgrs.",
-                   obj->detector.path().c_str(), obj->volumes.size(),
-                   obj->subdetectors.size(), obj->managers.size());
-          num[0] += obj->volumes.size();
-          num[1] += obj->subdetectors.size();
-          num[2] += obj->managers.size();
-          continue;
+                   "+++ FAILED to fix VolumeManager.system for '%s: %s'.",
+                   obj->detector.path().c_str(), "[No IDDescriptor field 'system']");
         }
         printout(ALWAYS,"DD4hepRootPersistency",
-                 "+++ FAILED to fix VolumeManager.system for '%s: %s'.",
-                 obj->detector.path().c_str(), "[No IDDescriptor field 'system']");
+                 "+++ Fixed VolumeManager TOTALS     %-24s  %6ld volumes %4ld sdets %4ld mgrs.","",num[0],num[1],num[2]);
+        printout(ALWAYS,"DD4hepRootPersistency","+++ loaded %ld nominals....",persist->nominals.size());
+      }
+      else   {
+        printout(ALWAYS,"DD4hepRootPersistency","+++ Volume manager NOT restored. [Was it ever up when saved?]");
       }
-      printout(ALWAYS,"DD4hepRootPersistency",
-               "+++ Fixed VolumeManager TOTALS     %-24s  %6ld volumes %4ld sdets %4ld mgrs.","",num[0],num[1],num[2]);
-      printout(ALWAYS,"DD4hepRootPersistency","+++ loaded %ld nominals....",persist->nominals.size());
       DetectorData* tar_data = dynamic_cast<DetectorData*>(&description);
       DetectorData* src_data = dynamic_cast<DetectorData*>(source);
       if( tar_data != nullptr && src_data != nullptr ){
diff --git a/DDCore/src/DD4hepUI.cpp b/DDCore/src/DD4hepUI.cpp
index 3ab5eb7b7..e42e9a6da 100644
--- a/DDCore/src/DD4hepUI.cpp
+++ b/DDCore/src/DD4hepUI.cpp
@@ -20,6 +20,14 @@ using namespace std;
 using namespace dd4hep;
 using namespace dd4hep::detail;
 
+namespace {
+  string _visLevel(int lvl)    {
+    char text[32];
+    ::snprintf(text,sizeof(text),"%d",lvl);
+    return text;
+  }
+}
+
 /// Default constructor
 DD4hepUI::DD4hepUI(Detector& instance) : m_detDesc(instance)  {
 }
@@ -43,6 +51,13 @@ PrintLevel DD4hepUI::setPrintLevel(PrintLevel level)   const   {
   return dd4hep::setPrintLevel(level);
 }
 
+/// Set the visualization level when invoking the display
+int DD4hepUI::setVisLevel(int value)     {
+  int old_value = visLevel;
+  visLevel = value;
+  return old_value;
+}
+
 /// Install the dd4hep conditions manager object
 Handle<NamedObject> DD4hepUI::conditionsMgr()  const  {
   if ( !m_condMgr.isValid() )  {
@@ -83,7 +98,7 @@ Handle<NamedObject> DD4hepUI::alignmentMgr()  const  {
 
 /// Detector interface: Manipulate geometry using facroy converter
 long DD4hepUI::apply(const char* factory, int argc, char** argv) const   {
-  return m_detDesc.apply(factory,argc,argv);
+  return m_detDesc.apply(factory, argc, argv);
 }
 
 /// Detector interface: Read any geometry description or alignment file
@@ -91,9 +106,26 @@ void DD4hepUI::fromXML(const std::string& fname, DetectorBuildType type) const
   return m_detDesc.fromXML(fname, type);
 }
 
+/// Detector interface: Draw the scene on a OpenGL pane
+void DD4hepUI::draw() const   {
+  drawSubtree("/world");
+}
+
 /// Detector interface: Re-draw the entire scene
 void DD4hepUI::redraw() const   {
-  m_detDesc.worldVolume()->Draw("oglsame");
+  redrawSubtree("/world");
+}
+
+/// Detector interface: Draw detector sub-tree the scene on a OpenGL pane
+void DD4hepUI::drawSubtree(const char* path) const    {
+  const void* av[] = {"-detector", path, "-option", "ogl", "-level", _visLevel(visLevel).c_str(), 0};
+  m_detDesc.apply("DD4hep_GeometryDisplay", 2, (char**)av);
+}
+
+/// Detector interface: Re-draw the entire sub-tree scene
+void DD4hepUI::redrawSubtree(const char* path) const    {
+  const void* av[] = {"-detector", path, "-option", "oglsame", "-level", _visLevel(visLevel).c_str(), 0};
+  m_detDesc.apply("DD4hep_GeometryDisplay", 4, (char**)av);
 }
 
 /// Dump the volume tree
@@ -105,11 +137,36 @@ long DD4hepUI::dumpVols(int argc, char** argv)  const   {
   return m_detDesc.apply("DD4hep_VolumeDump",argc,argv);
 }
 
-/// Dump the DetElement tree
+/// Dump the DetElement tree with placements
 long DD4hepUI::dumpDet()  const   {
   return m_detDesc.apply("DD4hep_DetectorVolumeDump",0,0);
 }
 
+/// Dump the DetElement tree with placements
+long DD4hepUI::dumpStructure()  const   {
+  return m_detDesc.apply("DD4hep_DetectorDump",0,0);
+}
+
+/// Dump the entire detector description object to a root file
+long DD4hepUI::saveROOT(const char* file_name)    const     {
+  if ( file_name )  {
+    const void* av[] = {"-output",file_name,0};
+    return m_detDesc.apply("DD4hep_Geometry2ROOT",2,(char**)av);
+  }
+  printout(WARNING,"DD4hepUI","++ saveROOT: No valid output file name supplied");
+  return 0;
+}
+
+/// Import the entire detector description object from a root file
+long DD4hepUI::importROOT(const char* file_name)    const    {
+  if ( file_name )  {
+    const void* av[] = {"-input",file_name,0};
+    return m_detDesc.apply("DD4hep_RootLoader",2,(char**)av);
+  }
+  printout(WARNING,"DD4hepUI","++ importROOT: No valid output file name supplied");
+  return 0;
+}
+
 /// Create ROOT interpreter instance
 long DD4hepUI::createInterpreter(int argc, char** argv)  {
   if ( 0 == gApplication )  {
@@ -135,3 +192,4 @@ long DD4hepUI::runInterpreter()  const   {
   except("DD4hepUI","++ No ROOT interpreter instance present!");
   return 0;
 }
+
diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp
index 0f45963a8..132341f03 100644
--- a/DDCore/src/plugins/StandardPlugins.cpp
+++ b/DDCore/src/plugins/StandardPlugins.cpp
@@ -117,6 +117,7 @@ DECLARE_CONSTRUCTOR(Detector_constructor,create_description_instance)
 static long display(Detector& description, int argc, char** argv) {
   TGeoManager& mgr = description.manager();
   int vislevel = 4, visopt = 1;
+  string detector = "/world";
   const char* opt = "ogl";
   for(int i = 0; i < argc && argv[i]; ++i)  {
     if ( 0 == ::strncmp("-option",argv[i],4) )
@@ -125,12 +126,15 @@ static long display(Detector& description, int argc, char** argv) {
       vislevel = ::atol(argv[++i]);
     else if ( 0 == ::strncmp("-visopt",argv[i],4) )
       visopt = ::atol(argv[++i]);
+    else if ( 0 == ::strncmp("-detector",argv[i],4) )
+      detector = argv[++i];
     else  {
       cout <<
-        "Usage: -plugin <name> -arg [-arg]                                                 \n"
-        "     -option <string> ROOT Draw option.    Default: 'ogl'                         \n"
-        "     -level  <number> Visualization level  [TGeoManager::SetVisLevel]  Default: 4 \n"
-        "     -visopt <number> Visualization option [TGeoManager::SetVisOption] Default: 1 \n"       
+        "Usage: -plugin <name> -arg [-arg]                                                   \n"
+        "     -detector <string> Top level DetElement path. Default: '/world'                \n"
+        "     -option   <string> ROOT Draw option.    Default: 'ogl'                         \n"
+        "     -level    <number> Visualization level  [TGeoManager::SetVisLevel]  Default: 4 \n"
+        "     -visopt   <number> Visualization option [TGeoManager::SetVisOption] Default: 1 \n"       
         "\tArguments given: " << arguments(argc,argv) << endl << flush;
       ::exit(EINVAL);
     }
@@ -138,7 +142,17 @@ static long display(Detector& description, int argc, char** argv) {
   mgr.SetVisLevel(vislevel);
   mgr.SetVisOption(visopt);
   TGeoVolume* vol = mgr.GetTopVolume();
-  if (vol) {
+  if ( detector != "/world" )   {
+    DetElement elt = detail::tools::findElement(description,detector);
+    if ( !elt.isValid() )  {
+      except("DD4hep_GeometryDisplay","+++ Invalid DetElement path: %s",detector.c_str());
+    }
+    if ( !elt.placement().isValid() )   {
+      except("DD4hep_GeometryDisplay","+++ Invalid DetElement placement: %s",detector.c_str());
+    }
+    vol = elt.placement().volume();
+  }
+  if ( vol )   {
     vol->Draw(opt);
     return 1;
   }
@@ -232,6 +246,8 @@ DECLARE_APPLY(DD4hep_Rint,run_interpreter)
  */
 static long root_ui(Detector& description, int /* argc */, char** /* argv */) {
   char cmd[256];
+  //DD4hepUI* ui = new DD4hepUI(description);
+  //::snprintf(cmd,sizeof(cmd),"dd4hep::detail::DD4hepUI* gDD4hepUI = (dd4hep::detail::DD4hepUI*)%p;",(void*)ui);
   ::snprintf(cmd,sizeof(cmd),
              "dd4hep::detail::DD4hepUI* gDD4hepUI = new "
              "dd4hep::detail::DD4hepUI(*(dd4hep::Detector*)%p);",
@@ -643,7 +659,19 @@ DECLARE_APPLY(DD4hep_Geometry2ROOT,dump_geometry2root)
  */
 static long load_geometryFromroot(Detector& description, int argc, char** argv) {
   if ( argc > 0 )   {
-    string input = argv[0];
+    string input = argv[0];  // <-- for backwards compatibility
+    for(int i = 0; i < argc && argv[i]; ++i)  {
+      if ( 0 == ::strncmp("-input",argv[i],4) )
+        input = argv[++i];
+    }
+    if ( input.empty() )   {
+      cout <<
+        "Usage: DD4hep_RootLoader -arg [-arg]                                          \n"
+        "     name:   factory name     DD4hepGeometry2ROOT                             \n"
+        "     -input  <string>         Input file name.                                \n"
+        "\tArguments given: " << arguments(argc,argv) << endl << flush;
+      ::exit(EINVAL);
+    }
     printout(INFO,"DD4hepRootLoader","+++ Read geometry from root file:%s",input.c_str());
     if ( 1 == DD4hepRootPersistency::load(description,input.c_str(),"Geometry") )  {
       return 1;
diff --git a/UtilityApps/src/plugin_runner.cpp b/UtilityApps/src/plugin_runner.cpp
index 07efbe5f1..99adfd167 100644
--- a/UtilityApps/src/plugin_runner.cpp
+++ b/UtilityApps/src/plugin_runner.cpp
@@ -48,7 +48,7 @@ namespace {
         usage();
       }
     }
-    if ( arguments.plugins.empty() )  {
+    if ( !arguments.ui && !arguments.interpreter && arguments.plugins.empty() )  {
       usage();
     }
     unique_ptr<TRint> interpreter;
diff --git a/examples/DDDB/include/DDDB/DDDBConditionsLoader.h b/examples/DDDB/include/DDDB/DDDBConditionsLoader.h
index ab6ac287a..cca8c8900 100644
--- a/examples/DDDB/include/DDDB/DDDBConditionsLoader.h
+++ b/examples/DDDB/include/DDDB/DDDBConditionsLoader.h
@@ -38,7 +38,7 @@ namespace dd4hep {
     /** 
      *  \author   M.Frank
      *  \version  1.0
-     *  \ingroup  DD4HEP_CONDITIONS
+     *  \ingroup  DD4HEP_DDDB
      */
     class DDDBConditionsLoader : public cond::ConditionsDataLoader  {
       typedef std::pair<std::string, std::string> Key;
@@ -46,7 +46,7 @@ namespace dd4hep {
       /** 
        *  \author   M.Frank
        *  \version  1.0
-       *  \ingroup  DD4HEP_CONDITIONS
+       *  \ingroup  DD4HEP_DDDB
        */
       class KeyCollector : public cond::ConditionsListener  {
       public:
diff --git a/examples/DDDB/include/DDDB/DDDBConversion.h b/examples/DDDB/include/DDDB/DDDBConversion.h
index f50b21e7a..913c218e0 100644
--- a/examples/DDDB/include/DDDB/DDDBConversion.h
+++ b/examples/DDDB/include/DDDB/DDDBConversion.h
@@ -610,8 +610,13 @@ namespace dd4hep {
     };
 
     /// Declaration of a tag-class to handle conditions
+    /**   \ingroup DD4HEP_DDDB
+     */
     class dddb_conditions  {};
 
+    /// Helper to implement reference counting depending on types.
+    /**   \ingroup DD4HEP_DDDB
+     */
     template <typename T> class Increment {
     public:
       static int& counter() { static int cnt=0; return cnt; }
diff --git a/examples/DDDB/include/DDDB/DDDBDimension.h b/examples/DDDB/include/DDDB/DDDBDimension.h
index 7e1fc49f6..b0e0efec2 100644
--- a/examples/DDDB/include/DDDB/DDDBDimension.h
+++ b/examples/DDDB/include/DDDB/DDDBDimension.h
@@ -54,6 +54,7 @@ namespace dd4hep {
      *  \author  M.Frank
      *  \version 1.0
      *  \ingroup DD4HEP_XML
+     *  \ingroup DD4HEP_DDDB
      */
     struct dddb_dim_t : public xml::Dimension {
       /// Default constructor
diff --git a/examples/DDDB/include/DDDB/DDDBHelper.h b/examples/DDDB/include/DDDB/DDDBHelper.h
index 803253227..7c81fc5e3 100644
--- a/examples/DDDB/include/DDDB/DDDBHelper.h
+++ b/examples/DDDB/include/DDDB/DDDBHelper.h
@@ -48,7 +48,7 @@ namespace dd4hep {
      *
      *  \author   M.Frank
      *  \version  1.0
-     *  \ingroup DD4HEP_XML
+     *  \ingroup  DD4HEP_DDDB
      */
     class DDDBHelper : public PropertyConfigurable  {
     public:
diff --git a/examples/DDDB/include/DDDB/DDDBReader.h b/examples/DDDB/include/DDDB/DDDBReader.h
index fc1a8b430..6997c0397 100644
--- a/examples/DDDB/include/DDDB/DDDBReader.h
+++ b/examples/DDDB/include/DDDB/DDDBReader.h
@@ -38,7 +38,7 @@ namespace dd4hep {
      *
      *  \author   M.Frank
      *  \version  1.0
-     *  \ingroup DD4HEP_XML
+     *  \ingroup  DD4HEP_DDDB
      */
     class DDDBReader : public dd4hep::xml::UriReader,
                        public PropertyConfigurable
-- 
GitLab