From be1e90cda6e6d6ad26381a02cf895a5b01d0e8dd Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Tue, 2 Jul 2013 18:49:26 +0000
Subject: [PATCH] Fix uniqueness of volume identifiers.

---
 DDExamples/CLICSiD/compact/compact.xml        |   4 +-
 .../src/CylindricalEndcapCalorimeter_geo.cpp  |  14 +--
 DDExamples/CLICSiD/src/EcalBarrel_geo.cpp     |  13 ++-
 .../CLICSiD/src/ForwardDetector_geo.cpp       |  17 +--
 .../src/PolyhedraBarrelCalorimeter2_geo.cpp   |   8 +-
 .../src/PolyhedraBarrel_VolMgrTest.cpp        | 100 +++++++++++++++++-
 .../CLICSiD/src/SiTrackerBarrel_geo.cpp       |   2 +-
 7 files changed, 131 insertions(+), 27 deletions(-)

diff --git a/DDExamples/CLICSiD/compact/compact.xml b/DDExamples/CLICSiD/compact/compact.xml
index 0edd3c783..7c447314b 100644
--- a/DDExamples/CLICSiD/compact/compact.xml
+++ b/DDExamples/CLICSiD/compact/compact.xml
@@ -1568,11 +1568,11 @@
         </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>
+            <id>system:8,layer:8,barrel:3,layer:8,slice:5,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>
+            <id>system:8,layer:8,barrel:3,layer:8,slice:5,x:32:-16,y:-16</id>
         </readout>
     </readouts>
     <fields>
diff --git a/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp b/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
index ebcf3bddc..f2fcf4f69 100644
--- a/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
+++ b/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
@@ -27,7 +27,8 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
   double     totWidth  = Layering(x_det).totalThickness();
   double     z         = zmin;
   int        layer_num = 1;
-    
+  PlacedVolume pv;
+
   for(xml_coll_t c(x_det,_U(layer)); c; ++c)  {
     xml_comp_t x_layer = c;
     double layerWidth = 0;
@@ -41,7 +42,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
       for(xml_coll_t l(x_layer,_U(slice)); l; ++l, ++m)  {
 	xml_comp_t x_slice = l;
 	double     w = x_slice.thickness();
-	string     slice_name = layer_name + _toString(m,"slice%d");
+	string     slice_name = layer_name + _toString(m+1,"slice%d");
 	Material   slice_mat  = lcdd.material(x_slice.materialStr());
 	Volume     slice_vol (slice_name,Tube(rmin,rmax,w),slice_mat);
           
@@ -51,14 +52,15 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
 	}
 	// Set attributes of slice
 	slice_vol.setAttributes(lcdd,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
-	layer_vol.placeVolume(slice_vol,Position(0,0,z-zlayer-layerWidth/2+w/2));
+	pv = layer_vol.placeVolume(slice_vol,Position(0,0,z-zlayer-layerWidth/2+w/2));
+	pv.addPhysVolID("slice",m+1);
 	z += w;
       }
       layer_vol.setVisAttributes(lcdd,x_layer.visStr());
-        
+
       Position layer_pos(0,0,zlayer-zmin-totWidth/2+layerWidth/2);
-      PlacedVolume layer_phys = envelopeVol.placeVolume(layer_vol,layer_pos);
-      layer_phys.addPhysVolID("layer",layer_num);
+      pv = envelopeVol.placeVolume(layer_vol,layer_pos);
+      pv.addPhysVolID("layer",layer_num);
       ++layer_num;
     }
   }
diff --git a/DDExamples/CLICSiD/src/EcalBarrel_geo.cpp b/DDExamples/CLICSiD/src/EcalBarrel_geo.cpp
index 8eedebd43..e649cbc76 100644
--- a/DDExamples/CLICSiD/src/EcalBarrel_geo.cpp
+++ b/DDExamples/CLICSiD/src/EcalBarrel_geo.cpp
@@ -61,6 +61,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
 
   Volume mod_vol(det_name+"_module",trd,air);
 
+  sens.setType("calorimeter");
   { // =====  buildBarrelStave(lcdd, sens, module_volume) =====
     // Parameters for computing the layer X dimension:
     double stave_z  = trd_y1/2;
@@ -72,15 +73,15 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
     double l_pos_z  = -(layering.totalThickness() / 2);
 
     // Loop over the sets of layer elements in the detector.
-    int l_num = 0;
+    int l_num = 1;
     for(xml_coll_t li(x_det,_U(layer)); li; ++li)  {
       xml_comp_t x_layer = li;
       int repeat = x_layer.repeat();
       // Loop over number of repeats for this layer.
       for (int j=0; j<repeat; j++)    {
 	string l_name = _toString(l_num,"layer%d");
-	double l_thickness = layering.layer(l_num)->thickness();  // Layer's thickness.
-	double xcut = (l_thickness / tan_beta);                   // X dimension for this layer.
+	double l_thickness = layering.layer(l_num-1)->thickness();  // Layer's thickness.
+	double xcut = (l_thickness / tan_beta);                     // X dimension for this layer.
 	l_dim_x -= xcut/2;
 
 	Position   l_pos(0,0,l_pos_z+l_thickness/2);      // Position of the layer.
@@ -89,7 +90,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
 	DetElement layer(stave_det, l_name, det_id);
 
 	// Loop over the sublayers or slices for this layer.
-	int s_num = 0;
+	int s_num = 1;
 	double s_pos_z = -(l_thickness / 2);
 	for(xml_coll_t si(x_layer,_U(slice)); si; ++si)  {
 	  xml_comp_t x_slice = si;
@@ -100,14 +101,12 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
           DetElement slice(layer,s_name,det_id);
 
           if ( x_slice.isSensitive() ) {
-	    sens.setType("calorimeter");
 	    s_vol.setSensitiveDetector(sens);
 	  }
           slice.setAttributes(lcdd,s_vol,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
 
           // Slice placement.
           PlacedVolume slice_phv = l_vol.placeVolume(s_vol,Position(0,0,s_pos_z+s_thick/2));
-          //slice_phv.addPhysVolID("layer", l_num);
           slice_phv.addPhysVolID("slice", s_num);
           slice.setPlacement(slice_phv);
           // Increment Z position of slice.
@@ -148,7 +147,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
     PlacedVolume pv = envelope.placeVolume(mod_vol,tr);
     pv.addPhysVolID("system",det_id);
     pv.addPhysVolID("barrel",0);
-    pv.addPhysVolID("module",i);
+    pv.addPhysVolID("module",i+1);
     DetElement sd = i==0 ? stave_det : stave_det.clone(_toString(i,"stave%d"));
     sd.setPlacement(pv);
     sdet.add(sd);
diff --git a/DDExamples/CLICSiD/src/ForwardDetector_geo.cpp b/DDExamples/CLICSiD/src/ForwardDetector_geo.cpp
index 0873472a7..dd772b950 100644
--- a/DDExamples/CLICSiD/src/ForwardDetector_geo.cpp
+++ b/DDExamples/CLICSiD/src/ForwardDetector_geo.cpp
@@ -69,6 +69,8 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
   // Process each layer element.
   double layerPosZ   = -thickness / 2;
   double layerDisplZ = 0;
+  
+  int layerCount = 1;
   for(xml_coll_t c(x_det,_U(layer)); c; ++c)  {
     xml_comp_t x_layer = c;
     double layerThickness = layering.singleLayerThickness(x_layer);
@@ -77,8 +79,8 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
     // in the repeat loop below.
     Tube layerTube(rmin,rmax,layerThickness);
 
-    for(int i=0, m=0, repeat=x_layer.repeat(); i<repeat; ++i, m=0)  {
-      string layer_nam = _toString(i,"layer%d");
+    for(int i=0, repeat=x_layer.repeat(); i<repeat; ++i)  {
+      string layer_nam = _toString(layerCount,"layer%d");
       // Increment to new layer position.
       layerDisplZ += layerThickness / 2;
       layerPosZ   += layerThickness / 2;
@@ -97,10 +99,10 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
       Volume layerVol(det_name+"_"+layer_nam,layerSubtraction2,air);
       
       // Slice loop.
-      int sliceCount = 0;
+      int sliceCount = 1;
       double slicePosZ = -layerThickness / 2;
       double sliceDisplZ = 0;
-      for(xml_coll_t l(x_layer,_U(slice)); l; ++l, ++m)  {
+      for(xml_coll_t l(x_layer,_U(slice)); l; ++l)  {
 	xml_comp_t x_slice = l;
 	string slice_nam = _toString(sliceCount,"slice%d");
 	/** Get slice parameters. */
@@ -132,7 +134,9 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
 	slice.setAttributes(lcdd, sliceVol, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
 
 	// Place volume in layer
-	slice.setPlacement(layerVol.placeVolume(sliceVol,Position(0,0,slicePosZ)));
+	PlacedVolume pv = layerVol.placeVolume(sliceVol,Position(0,0,slicePosZ));
+	pv.addPhysVolID("slice",sliceCount);
+	slice.setPlacement(pv);
 
 	// Start of next slice.
 	sliceDisplZ += sliceThickness / 2;
@@ -144,12 +148,13 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
 
       // Layer PV.
       PlacedVolume layerPV = envelopeVol.placeVolume(layerVol,Position(0,0,layerPosZ));
-      layerPV.addPhysVolID("layer", i);
+      layerPV.addPhysVolID("layer", layerCount);
       layer.setPlacement(layerPV);
 
       // Increment to start of next layer.
       layerDisplZ += layerThickness / 2;
       layerPosZ   += layerThickness / 2;
+      ++layerCount;
     }
   }
   sdet.setVisAttributes(lcdd, x_det.visStr(), envelopeVol);
diff --git a/DDExamples/CLICSiD/src/PolyhedraBarrelCalorimeter2_geo.cpp b/DDExamples/CLICSiD/src/PolyhedraBarrelCalorimeter2_geo.cpp
index c0dc91582..294c89332 100644
--- a/DDExamples/CLICSiD/src/PolyhedraBarrelCalorimeter2_geo.cpp
+++ b/DDExamples/CLICSiD/src/PolyhedraBarrelCalorimeter2_geo.cpp
@@ -91,15 +91,15 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
   double layerInnerAngle = (M_PI/2 - layerOuterAngle);
   double layer_pos_z = -(staveThickness / 2);                        
   double layer_dim_x = innerFaceLen/2 - gap * 2;
-  int layer_num = 0;
+  int layer_num = 1;
 
   // Set envelope volume attributes.
   envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
 
   for(xml_coll_t c(x_det,_U(layer)); c; ++c)  {
     xml_comp_t   x_layer = c;
-    int          repeat = x_layer.repeat();          // Get number of times to repeat this layer.
-    const Layer* lay    = layering.layer(layer_num); // Get the layer from the layering engine.
+    int          repeat = x_layer.repeat();            // Get number of times to repeat this layer.
+    const Layer* lay    = layering.layer(layer_num-1); // Get the layer from the layering engine.
     // Loop over repeats for this layer.
     for (int j = 0; j < repeat; j++)    {
       string     layer_name      = det_name+_toString(layer_num,"_layer%d");
@@ -113,7 +113,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
 
       // Create the slices (sublayers) within the layer.
       double slice_pos_z = -(layer_thickness / 2);
-      int slice_number = 0;
+      int slice_number = 1;
       for(xml_coll_t k(x_layer,_U(slice)); k; ++k)  {
 	xml_comp_t x_slice = k;
 	string   slice_name      = layer_name + _toString(slice_number,"_slice%d");
diff --git a/DDExamples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp b/DDExamples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp
index fe3742ebc..20a9960e6 100644
--- a/DDExamples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp
+++ b/DDExamples/CLICSiD/src/PolyhedraBarrel_VolMgrTest.cpp
@@ -21,8 +21,105 @@ 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;
+      VolumeManager::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...." << endl;
+  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");
@@ -84,6 +181,7 @@ static long test(LCDD& lcdd,int argc,char** argv)    {
       }
     }
   }
+#endif
   return 1;
 }
 DECLARE_APPLY(CLICSid_PolyhedraBarrel_VolMgrTest,test);
diff --git a/DDExamples/CLICSiD/src/SiTrackerBarrel_geo.cpp b/DDExamples/CLICSiD/src/SiTrackerBarrel_geo.cpp
index fe27a5734..093700e21 100644
--- a/DDExamples/CLICSiD/src/SiTrackerBarrel_geo.cpp
+++ b/DDExamples/CLICSiD/src/SiTrackerBarrel_geo.cpp
@@ -76,7 +76,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens)  {
     int        lay_id   = x_layer.id();
     string     m_nam    = x_layer.moduleStr();
     Volume     m_env    = volumes[m_nam];
-    string     lay_nam  = det_name+"_"+m_nam;
+    string     lay_nam  = det_name+"_"+m_nam+_toString(x_layer.id(),"_layer%d");
     Tube       lay_tub   (x_barrel.inner_r(),x_barrel.outer_r(),x_barrel.z_length());
     Volume     lay_vol   (lay_nam,lay_tub,air);       // Create the layer envelope volume.
     double     phi0     = x_layout.phi0();            // Starting phi of first module.
-- 
GitLab