From d96cdd2de1db46ca1f75b0477265637e26d6e382 Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Thu, 19 Sep 2013 19:53:19 +0000
Subject: [PATCH] Improved volume manager test

---
 .../CLICSiD/compact/compact_polycones.xml     |  51 +++++
 .../src/PolyhedraBarrel_VolMgrTest.cpp        | 187 -----------------
 examples/CLICSiD/src/VolumeMgrTest.cpp        | 194 ++++++++++++++++++
 3 files changed, 245 insertions(+), 187 deletions(-)
 delete mode 100644 examples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp
 create mode 100644 examples/CLICSiD/src/VolumeMgrTest.cpp

diff --git a/examples/CLICSiD/compact/compact_polycones.xml b/examples/CLICSiD/compact/compact_polycones.xml
index 009310a22..94aa2bde2 100644
--- a/examples/CLICSiD/compact/compact_polycones.xml
+++ b/examples/CLICSiD/compact/compact_polycones.xml
@@ -782,6 +782,57 @@
     </detectors>
 
     <readouts>
+        <readout name="SiTrackerEndcapHits">
+            <id>system:6,barrel:3,layer:4,module:16,sensor:1,side:32:-2,strip:20</id>
+        </readout>        
+        <readout name="SiTrackerBarrelHits">
+            <id>system:6,barrel:3,layer:4,module:12,sensor:1,side:v32:-2,strip:20</id>
+        </readout>
+        <readout name="SiVertexBarrelHits">
+            <id>system:6,barrel:3,layer:4,module:12,sensor:1,side:32:-2,strip:24</id>
+        </readout>
+        <readout name="SiVertexEndcapHits">
+            <id>system:6,barrel:3,layer:4,wedge:6,module:6,sensor:1,side:32:-2,strip:26</id>
+        </readout>
+        <readout name="EcalBarrelHits">
+            <segmentation type="EcalBarrelCartesianGridXY" gridSizeX="3.5" gridSizeY="3.5" />
+            <id>system:6,barrel:3,module:4,layer:6,slice:5,x:32:-16,y:-16</id>
+        </readout>        
+        <readout name="EcalEndcapHits">
+            <segmentation type="GlobalGridXY" gridSizeX="3.5" gridSizeY="3.5" />
+            <id>system:6,barrel:3,module:4,layer:6,slice:5,x:32:-16,y:-16</id>
+        </readout>
+        <readout name="HcalBarrelHits">
+            <segmentation type="RegularNgonCartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
+        </readout>
+        <readout name="HcalEndcapHits">
+            <segmentation type="GlobalGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
+        </readout>
+        <readout name="HcalPlugHits">
+            <segmentation type="GlobalGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <id>system:8,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
+        </readout>
+        <readout name="MuonBarrelHits">
+            <segmentation type="RegularNgonCartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <id>system:8,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
+        </readout>
+        <readout name="MuonEndcapHits">
+            <segmentation type="GlobalGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <id>system:8,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
+        </readout>
+        <readout name="SiTrackerForwardHits">
+            <id>system:6,barrel:3,layer:4,wedge:6,module:6,sensor:1,side:32:-2,strip:28</id>
+        </readout>
+        <readout name="LumiCalHits">
+            <segmentation type="GridXYZ" gridSizeX="0.35*cm" gridSizeY="0.35*cm" />
+            <id>system:8,layer:8,barrel:3,x:32:-16,y:-16</id>
+        </readout>
+        <readout name="BeamCalHits">
+            <segmentation type="GridXYZ" gridSizeX="0.35*cm" gridSizeY="0.35*cm" />
+            <id>system:8,layer:8,barrel:3,x:32:-16,y:-16</id>
+        </readout>
     </readouts>
     <fields>
         <field name="GlobalSolenoid" type="solenoid" 
diff --git a/examples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp b/examples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp
deleted file mode 100644
index 6d772793a..000000000
--- a/examples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-// $Id: TubeSegment_geo.cpp 633 2013-06-21 13:50:50Z markus.frank $
-//====================================================================
-//  AIDA Detector description implementation for LCD
-//--------------------------------------------------------------------
-//
-//  Author     : M.Frank
-//
-//====================================================================
-
-// Framework include files
-#include "DD4hep/LCDD.h"
-#include "DD4hep/Printout.h"
-#include "DD4hep/Factories.h"
-#include "DD4hep/IDDescriptor.h"
-#include "DD4hep/VolumeManager.h"
-
-// C/C++ include files
-#include <stdexcept>
-
-using namespace std;
-using namespace DD4hep;
-using namespace DD4hep::Geometry;
-
-
-namespace DD4hep {
-  struct VolIDTest  {
-    typedef vector<PlacedVolume::VolID> VolIDs;
-    std::string   m_name;
-    IDDescriptor  m_iddesc;
-    VolumeManager m_mgr;
-    DetElement    m_det;
-    VolIDTest(LCDD& lcdd, const std::string& name, size_t depth);
-    virtual ~VolIDTest() {}
-    void walk(DetElement de, VolIDs ids, size_t depth, size_t mx_depth)  const;
-  };
-}
-
-VolIDTest::VolIDTest(LCDD& lcdd, const std::string& name, size_t depth) : m_name(name)  {
-  DetElement        sdet   = lcdd.detector(name);
-  SensitiveDetector sd     = lcdd.sensitiveDetector(name);
-  stringstream err, log;
-
-  if ( !sdet.isValid() )   {
-    err << "The subdetector " << name << " is not known to the geometry.";
-    printout(INFO,"VolIDTest",err.str().c_str());
-    throw runtime_error(err.str());
-  }
-  if ( !sdet.isValid() )   {
-    err << "The sensitive detector of subdetector " << name << " is not known to the geometry.";
-    printout(INFO,"VolIDTest",err.str().c_str());
-    throw runtime_error(err.str());
-  }
-  m_det    = sdet;
-  m_mgr    = lcdd.volumeManager();
-  m_iddesc = sd.readout().idSpec();
-  VolIDs sysIds;
-  walk(sdet,sysIds,0,depth);
-}
-
-void VolIDTest::walk(DetElement e, VolIDs ids, size_t depth, size_t mx_depth)  const   {
-  if ( depth <= mx_depth )  {
-    DetElement::Children::const_iterator i;
-    const DetElement::Children& children = e.children();  
-    PlacedVolume pv = e.placement();
-    VolIDs child_ids(ids);
-    child_ids.insert(child_ids.end(),pv.volIDs().begin(),pv.volIDs().end());
-    for (i=children.begin(); i!=children.end(); ++i)  {
-      walk((*i).second,child_ids,depth+1,mx_depth);
-    }
-    if ( pv.volume().isSensitive() )  {
-      stringstream err, log;
-      VolumeID vid = m_iddesc.encode(child_ids);
-      try {
-	DetElement det       = m_mgr.lookupDetector(vid);
-        DetElement det_elem  = m_mgr.lookupDetElement(vid);
-        PlacedVolume det_place = m_mgr.lookupPlacement(vid);
-	if ( pv.ptr() != det_place.ptr() )   {
-	  err << "Wrong placement "
-	      << " got "        << det_place.name() << " (" << (void*)det_place.ptr() << ")"
-	      << " instead of " << pv.name()        << " (" << (void*)pv.ptr()        << ") "
-	      << " vid:" << (void*)vid;
-	}
-	else if ( det_elem.ptr() != e.ptr() )   {
-	  err << "Wrong associated detector element vid="  << (void*)vid 
-	      << " got "        << det_elem.path() << " (" << (void*)det_elem.ptr() << ") "
-	      << " instead of " << e.path()        << " (" << (void*)e.ptr()        << ")"
-	      << " vid:" << (void*)vid;
-	}
-	else if ( det.ptr() != m_det.ptr() )   {
-	  err << "Wrong associated detector "
-	      << " vid:" << (void*)vid;
-	}
-      }
-      catch(const exception& ex) {
-	err << "Lookup " << pv.name() << " id:" << (void*)vid << " path:" << e.path() << " error:" << ex.what();
-      }
-      const IDDescriptor::FieldMap& m = m_iddesc.fields();
-      log << "IDS(" << pv.name() << "): ";
-      for(size_t fi=0; fi<mx_depth; ++fi)  {
-	IDDescriptor::Field fld = m_iddesc.field(fi);
-	log << fld->name() << "=" << fld->value(vid) << "  ";
-      }
-      log << " vid:" << (void*)vid;
-      if ( !err.str().empty() )   {
-	printout(ERROR,m_name+"_VolMgrTest",err.str()+" "+log.str());
-	throw runtime_error(err.str());
-      }
-      printout(INFO,m_name+"_VolMgrTest","Found Volume: "+log.str());
-    }
-  }
-}
-
-
-static long test(LCDD& lcdd,int argc,char** argv)    {
-  cout << "Processing plugin...CLICSid_VolMgrTest..." << endl;
-  //VolIDTest test(lcdd,"HcalBarrel",5);
-  for(int i=1; i<argc;++i)  {
-    string name = argv[i]+1;
-    DetElement sdet = lcdd.detector(name);
-    VolIDTest test(lcdd,name,5);
-  }
-#if 0
-  typedef vector<PlacedVolume::VolID> VolIDs;
-  VolumeManager     mgr    = lcdd.volumeManager();
-  DetElement        sdet   = lcdd.detector("HcalBarrel");
-  SensitiveDetector sd     = lcdd.sensitiveDetector("HcalBarrel");
-  IDDescriptor      iddesc = sd.readout().idSpec();
-
-  size_t ii, jj, kk;
-  VolIDs sysIds;
-  sysIds.push_back(PlacedVolume::VolID("system",sdet.id()));
-  sysIds.push_back(PlacedVolume::VolID("barrel",0));
-  DetElement::Children::const_iterator i, j, k;
-  const DetElement::Children& staves = sdet.children();  
-  for (i=staves.begin(), ii=1; i!=staves.end(); ++i, ++ii)  {
-    VolIDs staveIds(sysIds);
-    DetElement stave = (*i).second;
-    const DetElement::Children& layers = stave.children();
-    PlacedVolume stave_pv = stave.placement();
-    staveIds.insert(staveIds.end(),stave_pv.volIDs().begin(),stave_pv.volIDs().end());
-    for (j=layers.begin(), jj=1; j!=layers.end(); ++j, ++jj)  {
-      VolIDs layerIds(staveIds);
-      DetElement layer = (*j).second;
-      PlacedVolume layer_pv = layer.placement();
-      const DetElement::Children& slices = layer.children();
-      layerIds.insert(layerIds.end(),layer_pv.volIDs().begin(),layer_pv.volIDs().end());
-      for (k=slices.begin(), kk=1; k!=slices.end(); ++k, ++kk)  {
-	VolIDs sliceIds(layerIds);
-	DetElement slice = (*k).second;
-	PlacedVolume pv = slice.placement();
-	sliceIds.insert(sliceIds.end(),pv.volIDs().begin(),pv.volIDs().end());
-	if ( pv.volume().isSensitive() )  {
-	  stringstream err, log;
-	  VolumeManager::VolumeID vid = iddesc.encode(sliceIds);
-	  DetElement    det       = mgr.lookupDetector(vid);
-	  DetElement    det_elem  = mgr.lookupDetElement(vid);
-	  PlacedVolume  det_place = mgr.lookupPlacement(vid);
-	  if ( pv.ptr() != det_place.ptr() )   {
-	    err << "Wrong placement ";
-	  }
-	  else if ( det_elem.ptr() != slice.ptr() )   {
-	    err << "Wrong associated detector element vid=" << (void*)vid 
-		<< " got " << det_elem.path() << " (" << (void*)det_elem.ptr() << ") "
-		<< " instead of " << slice.path() << " (" << (void*)slice.ptr() << ")";
-	  }
-	  else if ( det.ptr() != sdet.ptr() )   {
-	    err << "Wrong associated detector ";
-	  }
-
-	  const IDDescriptor::FieldMap& m = iddesc.fields();
-	  log << "IDS(" << pv.name() << "): ";
-	  for(IDDescriptor::FieldMap::const_iterator l=m.begin(); l != m.end(); ++l)   {
-	    log << (*l).first << "=" << (*l).second->value(vid) << "  ";
-	  }
-	  if ( !err.str().empty() )   {
-	    printout(ERROR,"CLICSid_PolyhedraBarrel_VolMgrTest",(err.str()+" "+log.str()).c_str());
-	    throw runtime_error(err.str());
-	  }
-	  printout(INFO,"CLICSid_PolyhedraBarrel_VolMgrTest",("Found Volume: "+log.str()).c_str());	  
-	}
-      }
-    }
-  }
-#endif
-  return 1;
-}
-DECLARE_APPLY(CLICSid_PolyhedraBarrel_VolMgrTest,test);
diff --git a/examples/CLICSiD/src/VolumeMgrTest.cpp b/examples/CLICSiD/src/VolumeMgrTest.cpp
new file mode 100644
index 000000000..383c52039
--- /dev/null
+++ b/examples/CLICSiD/src/VolumeMgrTest.cpp
@@ -0,0 +1,194 @@
+// $Id: TubeSegment_geo.cpp 633 2013-06-21 13:50:50Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/Factories.h"
+#include "DD4hep/IDDescriptor.h"
+#include "DD4hep/VolumeManager.h"
+
+// C/C++ include files
+#include <stdexcept>
+#include <algorithm>
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+
+namespace  {
+  /** @class VolIDTest
+   *
+   *  Test the volume manager by scanning the sensitive 
+   *  volumes of one or several subdetectors.
+   *
+   *  @author  M.Frank
+   *  @version 1.0
+   */
+  struct VolIDTest  {
+    typedef vector<PlacedVolume::VolID> VolIDs;
+    /// Helper to scan volume ids
+    struct FND {
+      const string& test;
+      FND(const string& c) : test(c) {}
+      bool operator()(const VolIDs::value_type& c) const { return c.first == test; }
+    };
+    IDDescriptor  m_iddesc;
+    VolumeManager m_mgr;
+    DetElement    m_det;
+
+    /// Initializing constructor
+    VolIDTest(LCDD& lcdd, DetElement sdet, size_t depth);
+    /// Default destructor
+    virtual ~VolIDTest() {}
+    /// Check volume integrity
+    void checkVolume(DetElement e, PlacedVolume pv, const VolIDs& child_ids)  const;
+    /// Walk through tree of detector elements
+    void walk(DetElement de, VolIDs ids, size_t depth, size_t mx_depth)  const;
+    /// Walk through tree of volume placements
+    void walkVolume(DetElement e, PlacedVolume pv, VolIDs ids, size_t depth, size_t mx_depth)  const;
+
+    /// Action routine to execute the test
+    static long run(LCDD& lcdd,int argc,char** argv);
+  };
+}
+
+/// Initializing constructor
+VolIDTest::VolIDTest(LCDD& lcdd, DetElement sdet, size_t depth) : m_det(sdet) {
+  m_mgr    = lcdd.volumeManager();
+  if ( !m_det.isValid() )   {
+    stringstream err;
+    err << "The subdetector " << m_det.name() << " is not known to the geometry.";
+    printout(INFO,"VolIDTest",err.str().c_str());
+    throw runtime_error(err.str());
+  }
+  if ( !lcdd.sensitiveDetector(m_det.name()).isValid() )   {
+    stringstream err;
+    err << "The sensitive detector of subdetector " << m_det.name() 
+	<< " is not known to the geometry.";
+    printout(INFO,"VolIDTest",err.str().c_str());
+    throw runtime_error(err.str());
+  }
+  m_iddesc = lcdd.sensitiveDetector(m_det.name()).readout().idSpec();
+  walk(m_det,VolIDs(),0,depth);
+}
+
+/// Check volume integrity
+void VolIDTest::checkVolume(DetElement e, PlacedVolume pv, const VolIDs& child_ids)  const {
+  stringstream err, log;
+  VolumeID vid = m_iddesc.encode(child_ids);
+  VolumeID mask = 0xFFFFULL;
+  vid |= mask<<(31+16);
+  try {
+    DetElement det         = m_mgr.lookupDetector(vid);
+    DetElement det_elem    = m_mgr.lookupDetElement(vid);
+    PlacedVolume det_place = m_mgr.lookupPlacement(vid);
+    if ( pv.ptr() != det_place.ptr() )   {
+      err << "Wrong placement "
+	  << " got "        << det_place.name() << " (" << (void*)det_place.ptr() << ")"
+	  << " instead of " << pv.name()        << " (" << (void*)pv.ptr()        << ") "
+	  << " vid:" << (void*)vid;
+    }
+    else if ( det_elem.ptr() != e.ptr() )   {
+      err << "Wrong associated detector element vid="  << (void*)vid 
+	  << " got "        << det_elem.path() << " (" << (void*)det_elem.ptr() << ") "
+	  << " instead of " << e.path()        << " (" << (void*)e.ptr()        << ")"
+	  << " vid:" << (void*)vid;
+    }
+    else if ( det.ptr() != m_det.ptr() )   {
+      err << "Wrong associated detector "
+	  << " vid:" << (void*)vid;
+    }
+  }
+  catch(const exception& ex) {
+    err << "Lookup " << pv.name() << " id:" << (void*)vid << " path:" << e.path() << " error:" << ex.what();
+  }
+  const IDDescriptor::FieldMap& m = m_iddesc.fields();
+  log << "IDS(" << pv.name() << "): ";
+  for(size_t fi=0; fi<m.size(); ++fi)  {
+    IDDescriptor::Field fld = m_iddesc.field(fi);
+    if ( find_if(child_ids.begin(),child_ids.end(),FND(fld->name())) == child_ids.end() ) continue;
+    log << fld->name() << "=" << fld->value(vid) << "  ";
+  }
+  log << " vid:" << (void*)vid;
+  if ( !err.str().empty() )   {
+    printout(ERROR,m_det.name(),err.str()+" "+log.str());
+    throw runtime_error(err.str());
+  }
+  printout(INFO,m_det.name(),"OK: "+log.str());
+}
+
+/// Walk through tree of detector elements
+void VolIDTest::walkVolume(DetElement e, PlacedVolume pv, VolIDs ids, size_t depth, size_t mx_depth)  const   {
+  if ( depth <= mx_depth )  {
+    const TGeoNode* current = pv.ptr();
+    TObjArray*  nodes  = current->GetNodes();
+    int   num_children = nodes ? nodes->GetEntriesFast() : 0;
+    for(int i=0; i<num_children; ++i)   {
+      TGeoNode* node = (TGeoNode*)nodes->At(i);
+      PlacedVolume place(node);
+      VolIDs child_ids(ids);
+      stringstream err, log;
+
+      child_ids.insert(child_ids.end(),place.volIDs().begin(),place.volIDs().end());
+      bool is_sensitive = place.volume().isSensitive();
+      if ( is_sensitive )  {
+	checkVolume(e,place,child_ids);
+      }
+      walkVolume(e,place,child_ids,depth+1,mx_depth);
+    }
+  }
+}
+
+/// Walk through tree of volume placements
+void VolIDTest::walk(DetElement e, VolIDs ids, size_t depth, size_t mx_depth)  const   {
+  if ( depth <= mx_depth )  {
+    DetElement::Children::const_iterator i;
+    const DetElement::Children& children = e.children();  
+    PlacedVolume pv = e.placement();
+    VolIDs child_ids(ids);
+    bool is_sensitive = pv.volume().isSensitive();
+    child_ids.insert(child_ids.end(),pv.volIDs().begin(),pv.volIDs().end());
+    for (i=children.begin(); i!=children.end(); ++i)  {
+      walk((*i).second,child_ids,depth+1,mx_depth);
+    }
+    if ( !is_sensitive && children.empty() )  {
+      walkVolume(e,pv,child_ids,depth+1,mx_depth);
+    }
+    else if ( is_sensitive )  {
+      checkVolume(e, pv,child_ids);
+    }
+  }
+}
+
+/// Action routine to execute the test
+long VolIDTest::run(LCDD& lcdd,int argc,char** argv)    {
+  cout << "++ Processing plugin...CLICSid_VolMgrTest..." << endl;
+  for(int i=1; i<argc;++i)  {
+    string name = argv[i]+1;
+    if ( name == "all" || name == "All" || name == "ALL" )  {
+      const DetElement::Children& children = lcdd.world().children();  
+      for (DetElement::Children::const_iterator i=children.begin(); i!=children.end(); ++i)  {
+	DetElement sdet = (*i).second;
+	cout << "++ Processing subdetector: " << sdet.name() << endl;
+	VolIDTest test(lcdd,sdet,99);
+      }
+      return 1;
+    }
+    cout << "++ Processing subdetector: " << name << endl;
+    VolIDTest test(lcdd,lcdd.detector(name),99);
+  }
+  return 1;
+}
+
+namespace DD4hep {
+  using ::VolIDTest;
+}
+DECLARE_APPLY(CLICSiD_VolMgrTest,VolIDTest::run);
-- 
GitLab