From 96a31054078f37870349067199d48adf6a3d552c Mon Sep 17 00:00:00 2001
From: Chengdong Fu <fucd@ihep.ac.cn>
Date: Tue, 21 Jul 2020 13:51:12 +0800
Subject: [PATCH] add interface/convertor to get detector parameters/materials

---
 Detector/DetInterface/DetInterface/IGeoSvc.h |  29 +-
 Detector/GeoSvc/src/GeoSvc.cpp               | 533 ++++++++++++++++++-
 Detector/GeoSvc/src/GeoSvc.h                 |  66 ++-
 3 files changed, 600 insertions(+), 28 deletions(-)

diff --git a/Detector/DetInterface/DetInterface/IGeoSvc.h b/Detector/DetInterface/DetInterface/IGeoSvc.h
index 58df046d..7e26a243 100644
--- a/Detector/DetInterface/DetInterface/IGeoSvc.h
+++ b/Detector/DetInterface/DetInterface/IGeoSvc.h
@@ -11,12 +11,28 @@
 #define IGEOSVC_H
 
 #include "GaudiKernel/IService.h"
+#include "DDRec/DetectorData.h"
+#include <map>
 
 namespace dd4hep {
-class Detector;
-class DetElement;
+  class Detector;
+  class DetElement;
+  // if not include DDRec/DetectorData.h, can not compile, why? 
+  //namespace rec{
+    //struct StructExtension;
+    //struct ZPlanarStruct;
+    //typedef StructExtension<ZPlanarStruct> ZPlanarData;
+    //struct ConicalSupportStruct;
+    //typedef StructExtension<ConicalSupportStruct> ConicalSupportData;
 }
 
+class StructExtension;
+
+namespace gear{
+  class ZPlanarParametersImpl;
+  class GearParametersImpl;
+}
+class TMaterial;
 // class G4VUserDetectorConstruction;
 
 class GAUDI_API IGeoSvc : virtual public IService {
@@ -30,6 +46,15 @@ public:
   // receive Geant4 Geometry
   // virtual G4VUserDetectorConstruction* getGeant4Geo() = 0;
 
+  // obsolete parameter format, will remove once StructExtension<> validated
+  virtual const gear::ZPlanarParametersImpl*  getVXDParameters() = 0;
+
+  virtual const dd4hep::rec::ZPlanarData* getVXDData() = 0;
+  virtual const dd4hep::rec::ConicalSupportData* getBeamPipeData() =0;
+
+  virtual const std::map<std::string,double>& getDetParameters(std::string s) = 0;
+  virtual const double getDetParameter(std::string set_name, std::string par_name) = 0;
+  virtual TMaterial* getMaterial(std::string s) = 0;
   virtual ~IGeoSvc() {}
 };
 
diff --git a/Detector/GeoSvc/src/GeoSvc.cpp b/Detector/GeoSvc/src/GeoSvc.cpp
index 305896c4..42990b30 100644
--- a/Detector/GeoSvc/src/GeoSvc.cpp
+++ b/Detector/GeoSvc/src/GeoSvc.cpp
@@ -1,14 +1,28 @@
 #include "GeoSvc.h"
+#include "gearimpl/GearParametersImpl.h"
+#include "TMath.h"
+#include "TMaterial.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+#include "G4Box.hh"
+#include "G4Tubs.hh"
+#include "G4LogicalVolume.hh"
+#include "G4PVPlacement.hh"
+#include "G4NistManager.hh"
 
 #include "DD4hep/Detector.h"
 #include "DD4hep/Plugins.h"
 #include "DDG4/Geant4Converter.h"
 #include "DDG4/Geant4Mapping.h"
+#include "DDRec/DetectorData.h"
+
+#include <iomanip>
+#include <iostream>
 
 DECLARE_COMPONENT(GeoSvc)
 
 GeoSvc::GeoSvc(const std::string& name, ISvcLocator* svc)
-: base_class(name, svc), m_dd4hep_geo(nullptr) {
+: base_class(name, svc), m_dd4hep_geo(nullptr), m_vxdData(nullptr), m_beamData(nullptr){
 
 }
 
@@ -18,20 +32,40 @@ GeoSvc::~GeoSvc() {
 
 StatusCode
 GeoSvc::initialize() {
-    StatusCode sc = Service::initialize();
+  StatusCode sc = Service::initialize();
 
-    m_dd4hep_geo = &(dd4hep::Detector::getInstance());
-    // if failed to load the compact, a runtime error will be thrown.
-    m_dd4hep_geo->fromCompact(m_dd4hep_xmls.value());
-
-    return sc;
+  m_dd4hep_geo = &(dd4hep::Detector::getInstance());
+  // if failed to load the compact, a runtime error will be thrown.
+  m_dd4hep_geo->fromCompact(m_dd4hep_xmls.value());
+  
+  dd4hep::DetElement world = m_dd4hep_geo->world();
+  //info() << world.type() << " " << world.path() << " " << world.placementPath() << endmsg;
+  const std::map<std::string, dd4hep::DetElement>& subs = world.children();
+  for(std::map<std::string, dd4hep::DetElement>::const_iterator it=subs.begin();it!=subs.end();it++){
+    dd4hep::DetElement sub = it->second;
+    info() << it->first << " " << sub.path() << " " << sub.placementPath() << endmsg;
+    if(it->first=="Tube"){
+      dd4hep::Volume vol = sub.volume();
+      dd4hep::Solid  solid = vol.solid();
+      //info() << " " << solid.type() << " " << solid.name() << endmsg;
+      const std::map<std::string, dd4hep::DetElement>& pipes = sub.children();
+      for(std::map<std::string, dd4hep::DetElement>::const_iterator it=pipes.begin();it!=pipes.end();it++){
+	dd4hep::DetElement pipe = it->second;
+	//info() << " " << it->first << " " << pipe.id() << " " << pipe.path() << " " << pipe.placementPath() << endmsg;
+      }
+    }
+    if(it->first=="VXD"){
+      sc = convertVXD(sub);
+    }
+  }
+  return sc;
 }
 
 StatusCode
 GeoSvc::finalize() {
-    StatusCode sc;
-
-    return sc;
+  StatusCode sc;
+  if(m_vxdParameters) delete m_vxdParameters;
+  return sc;
 }
 
 dd4hep::DetElement
@@ -46,3 +80,482 @@ dd4hep::Detector*
 GeoSvc::lcdd() {
     return m_dd4hep_geo;
 }
+
+const std::map<std::string,double>& GeoSvc::getDetParameters(std::string name){
+  if(m_detParameters.find(name)!=m_detParameters.end()) return m_detParameters[name];
+  else{
+    char message[200];
+    sprintf(message,"GeoSvc has not the parameter set named %s", name); 
+    throw std::runtime_error(message);
+  }
+}
+
+const double GeoSvc::getDetParameter(std::string set_name, std::string par_name){
+  std::map<std::string, std::map<std::string,double> >::iterator it=m_detParameters.find(set_name);
+  if(it!=m_detParameters.end()){
+    if(it->second.find(par_name)!=it->second.end()) return it->second[par_name];  
+  }
+  char message[200];
+  sprintf(message,"GeoSvc has not the parameter named %s in set %s", par_name, set_name);
+  throw std::runtime_error(message);
+}
+
+StatusCode GeoSvc::convertVXD(dd4hep::DetElement& vxd){
+  StatusCode sc;
+  //fucd: another method to obtain parameters, but not fully for KalDet  
+  bool extensionDataValid = true;
+  try{
+    m_vxdData = vxd.extension<dd4hep::rec::ZPlanarData>();
+  }
+  catch(std::runtime_error& e){
+    extensionDataValid = false;
+    info() << e.what() << " " << m_vxdData << endmsg;
+  }
+  
+  std::vector<helpLayer> helpSensitives;
+  std::vector<helpLayer> helpLadders;
+  std::vector<int>       helpNumberLadders;
+  std::vector<double>    helpPhi0; 
+  int                    helpCount=0;
+  int                    type=0;
+  double shellInnerRadius, shellOuterRadius, shellHalfLength, gap, shellRadLength;
+  int    nLadders=0;
+  double phi0=0;
+  helpLayer thisLadder;
+  double beryllium_ladder_block_length=0,end_electronics_half_z=0,side_band_electronics_width=0;
+  double rAlu, drAlu, rSty, drSty, dzSty, rInner, aluEndcapZ, aluHalfZ, alu_RadLen, Cryostat_dEdx;
+  double VXDSupportDensity, VXDSupportZeff, VXDSupportAeff, VXDSupportRadLen;
+  dd4hep::Volume vxd_vol = vxd.volume();
+  for(int i=0;i<vxd_vol->GetNdaughters();i++){
+    TGeoNode* daughter = vxd_vol->GetNode(i);
+    std::string nodeName = daughter->GetName();
+    //info() << daughter->GetName() << endmsg; 
+    if(nodeName=="VXD_support_assembly_0"){
+      TGeoNode* shell = FindNode(daughter, "SupportShell");
+      if(shell){
+	const TGeoShape* shape_shell = shell->GetVolume()->GetShape();
+	//fucd: IsA() method does not always work for TGeoTube, sometimes, strange?
+	//if(shape_shell->IsA()==TGeoTube::Class()){
+	if(shape_shell->TestShapeBit(TGeoTube::kGeoTube)){
+	  const TGeoTube* tube = (const TGeoTube*) shape_shell;
+	  shellInnerRadius = tube->GetRmin()*CLHEP::cm;
+	  shellOuterRadius = tube->GetRmax()*CLHEP::cm;
+	  shellHalfLength  = tube->GetDz()*CLHEP::cm;
+	}
+	else{
+	  error() << shell->GetName() << " is not a TGeoTube!  Shape bits = " << shape_shell->TestShapeBits(0xFFFFFFFF) << endmsg; 
+	}
+	TGeoMaterial* mat = shell->GetMedium()->GetMaterial();
+	shellRadLength = mat->GetRadLen()*CLHEP::cm;
+      }
+      TGeoNode* block = FindNode(daughter, "BerylliumAnnulusBlock");
+      if(block){
+	const TGeoShape* shape_block = block->GetVolume()->GetShape();
+	if(shape_block->IsA()==TGeoBBox::Class()){
+	  const TGeoBBox* box = (const TGeoBBox*) shape_block;
+	  beryllium_ladder_block_length = box->GetDY()*CLHEP::cm;
+	}
+	else{
+	  error() << block->GetName() << " is not a TGeoTube!  Shape bits = " << shape_block->TestShapeBits(0xFFFFFFFF) << endmsg;
+	}
+      }
+      TGeoNode* skin = FindNode(daughter, "CryostatAluSkinBarrel");
+      if(skin){
+	const TGeoShape* shape_skin = skin->GetVolume()->GetShape();
+	if(shape_skin->TestShapeBit(TGeoTube::kGeoTube)){
+          const TGeoTube* tube = (const TGeoTube*) shape_skin;
+          rAlu  = tube->GetRmin()*CLHEP::cm;
+          drAlu = tube->GetRmax()*CLHEP::cm - rAlu;
+          aluHalfZ = tube->GetDz()*CLHEP::cm;
+	  //info() << rmin << "," << rmax << "," << zhalf << endmsg;
+        }
+        else{
+          error() << skin->GetName() << " is not a TGeoTube! Shape bits = " <<  shape_skin->TestShapeBits(0xFFFFFFFF) << endmsg;
+        }
+      }
+      TGeoNode* foam = FindNode(daughter, "CryostatFoamBarrel");
+      if(foam){
+        const TGeoShape* shape_foam = foam->GetVolume()->GetShape();
+        if(shape_foam->TestShapeBit(TGeoTube::kGeoTube)){
+          const TGeoTube* tube = (const TGeoTube*) shape_foam;
+          rSty = tube->GetRmin()*CLHEP::cm;
+          drSty = tube->GetRmax()*CLHEP::cm - rSty;
+          dzSty = tube->GetDz()*CLHEP::cm;
+	  //info() << rmin << "," << rmax << "," << zhalf << endmsg;
+        }
+        else{
+          error() << foam->GetName() << " is not a TGeoTube! Shape bits = " << shape_foam->TestShapeBits(0xFFFFFFFF) << endmsg;
+        }
+      }
+      TGeoNode* skinEnd = FindNode(daughter, "CryostatAluSkinEndPlateInner");
+      if(skinEnd){
+        const TGeoShape* shape_skinEnd = skinEnd->GetVolume()->GetShape();
+        if(shape_skinEnd->TestShapeBit(TGeoTube::kGeoTube)){
+          const TGeoTube* tube = (const TGeoTube*) shape_skinEnd;
+          rInner = tube->GetRmin()*CLHEP::cm;
+          double rmax = tube->GetRmax()*CLHEP::cm;
+          drAlu = tube->GetDz()*CLHEP::cm*2;
+	  //info() << rmin << "," << rmax << "," << zhalf << endmsg;
+        }
+        else{
+          error() << skinEnd->GetName() << " is not a TGeoTube! Shape bits = " << shape_skinEnd->TestShapeBits(0xFFFFFFFF) << endmsg;
+        }
+      }
+      TGeoNode* shellEnd = FindNode(daughter, "EndPlateShell_outer");
+      if(shellEnd){
+        const TGeoShape* shape_shellEnd = shellEnd->GetVolume()->GetShape();
+	if(shape_shellEnd->TestShapeBit(TGeoTube::kGeoTube)){
+	  const TGeoTube* tube = (const TGeoTube*) shape_shellEnd;
+          double rmin = tube->GetRmin()*CLHEP::cm;
+          double rmax = tube->GetRmax()*CLHEP::cm;
+          double zhalf = tube->GetDz()*CLHEP::cm;
+          //info() << rmin << "," << rmax << "," << zhalf << endmsg;
+	}
+	else{
+          error() << shellEnd->GetName() << " is not a TGeoTube! Shape bits = " << shape_shellEnd->TestShapeBits(0xFFFFFFFF) << endmsg;
+        }
+      }
+      
+    }
+    else if(nodeName=="layer_assembly_0_1"){
+      if(TGeoNode* side_band = FindNode(daughter, "ElectronicsBand")){
+	const TGeoShape* shape_band = side_band->GetVolume()->GetShape();
+	if(shape_band->IsA()==TGeoBBox::Class()){
+	  const TGeoBBox* box = (const TGeoBBox*) shape_band;
+	  side_band_electronics_width = box->GetDX()*CLHEP::cm*2;
+	  //info() << "fucd: "<< box->GetDX() << " " << box->GetDY() << " " << box->GetDZ() <<endmsg;
+	}
+	else{
+	  error() << "ElectronicsBand is not a TGeoBBox!!!"<< endmsg;
+	}
+      }
+      if(TGeoNode* end = FindNode(daughter, "ElectronicsEnd")){
+	const TGeoShape* shape_end = end->GetVolume()->GetShape();
+	if(shape_end->IsA()==TGeoBBox::Class()){
+	  const TGeoBBox* box = (const TGeoBBox*) shape_end;
+	  end_electronics_half_z = box->GetDY()*CLHEP::cm;
+	  //info() << "fucd: " << box->GetDX() << " " << box->GetDY() << " " << box->GetDZ() << endmsg;                                                                                                                              
+	}
+	else{
+	  error() << "ElectronicsEnd is not a TGeoBBox!!!"<< endmsg;
+	}
+      }
+    }
+    
+    /*
+    for(int j=0;j<daughter->GetNdaughters();j++){
+      TGeoNode* next = daughter->GetDaughter(j);
+      info() << "fucd:  " << next->GetName() << endmsg;
+    }
+    */
+  }
+  
+  const std::map<std::string, dd4hep::DetElement>& components = vxd.children();
+  for(std::map<std::string, dd4hep::DetElement>::const_iterator it=components.begin();it!=components.end();it++){
+    dd4hep::DetElement component = it->second;
+    dd4hep::Volume vol = component.volume();
+    dd4hep::PlacedVolume phys = component.placement();
+    TGeoMaterial* mat = vol->GetMaterial();
+    const TGeoShape* shape = vol->GetShape();
+    const dd4hep::PlacedVolumeExtension::VolIDs& ids = phys.volIDs();
+    //info() << " " << it->first << " " << vol->GetName() << " " << component.id() << " " << component.path() << " " << component.placementPath() << endmsg;
+    //info() << "   " << shape->GetName() << " " << vol.solid().name() << endmsg; 
+    //info() << "   " << mat->GetName() <<  " " << mat->GetRadLen() << endmsg;
+    //info() << "   " << ids.str() << endmsg;
+    //info() << "   " << vol->GetNdaughters() << endmsg; 
+    //double radL = mat->GetRadLen();
+    //dd4hep::Solid  solid = vol.solid();
+    //info() << "  " <<  sh->TestShapeBit(TGeoShape::kGeoBox) <<  " " << sh->GetName() << " " << phys.material().radLength() << endmsg;
+    if(vol.isSensitive()&&shape->IsA()==TGeoBBox::Class()){
+      int iLayer  = ids.find("layer")->second;
+      int iModule = ids.find("module")->second;
+      int iSide   = ids.find("side")->second;
+      //info() << "  layer=" << iLayer << " module=" << iModule << mat->GetName() << endmsg;
+      if(iModule==0&&iLayer==helpCount+1){
+	helpCount++;
+	helpSensitives.push_back(thisLadder);
+	helpLadders.push_back(thisLadder);
+	helpNumberLadders.push_back(nLadders);
+	helpPhi0.push_back(phi0);
+	nLadders = 0;
+	thisLadder.length = 0;
+      }
+      if(iLayer == helpCount){
+	if(iModule == 0){
+	  const TGeoBBox* box = (const TGeoBBox*) shape;
+	  double width     = box->GetDX()*CLHEP::cm;
+	  double length    = box->GetDY()*CLHEP::cm;
+	  double thickness = box->GetDZ()*CLHEP::cm;
+	  TGeoMatrix* matrix = phys->GetMatrix();
+	  const double* pos = matrix->GetTranslation();
+	  const double* rot_data = matrix->GetRotationMatrix();
+	  TGeoRotation rot;
+	  rot.SetMatrix(rot_data);
+	  double theta,phi,psi;
+	  rot.GetAngles(phi,theta,psi);
+	  phi *= TMath::DegToRad();
+	  theta *= TMath::DegToRad();
+	  psi *= TMath::DegToRad();
+	  phi0 = -TMath::PiOver2()+phi;
+	  double distance = fabs(cos(phi0)*sin(theta)*pos[0]+sin(phi0)*sin(theta)*pos[1]+cos(theta)*pos[2]);
+	  double offset = sqrt(pos[0]*pos[0]+pos[1]*pos[1]-distance*distance)*pos[0]/fabs(pos[0])*CLHEP::cm;
+	  distance *= CLHEP::cm;
+	  distance -= thickness;
+	  double radL = mat->GetRadLen()*CLHEP::cm;
+	  //info() << " ->   " << helpCount << ": " << distance << " " << cos(atan2(pos[1],pos[0])-phi)*sqrt(pos[0]*pos[0]+pos[1]*pos[1]) << endmsg;
+	  thisLadder.distance  = distance;
+	  thisLadder.offset    = offset;
+	  thisLadder.thickness = thickness;
+	  thisLadder.length   += length;
+	  thisLadder.width     = width;
+	  thisLadder.radLength = radL;
+	  thisLadder.z         = pos[2]*CLHEP::cm;
+	}
+	if(iModule==nLadders) nLadders++; 
+      }
+    }
+    //info() << "  " << vol.solid().type() << " " << vol.solid().name() << " " << vol->GetNdaughters() << endmsg;
+    else if(it->first=="VXD_support"){
+      helpCount++;
+      helpSensitives.push_back(thisLadder);
+      helpLadders.push_back(thisLadder);
+      helpNumberLadders.push_back(nLadders);
+      helpPhi0.push_back(phi0);
+      nLadders = 0;
+      if(vol->GetNdaughters()==0) error() << "!!!!!!!!!" << endmsg;
+
+      int nFlexCable = 0, nFoamSpacer=0, nMetalTraces=0;
+      int currentLayer = -1;
+      double tFlexCable, tFoamSpacer, tMetalTraces;
+      double radLFlexCable, radLFoamSpacer, radLMetalTraces;
+      double intLFlexCable, intLFoamSpacer, intLMetalTraces;
+      double dFlexCable, dFoamSpacer, dMetalTraces;
+      double metalZeff, metalZAeff, foamZeff, foamZAeff, flexZeff, flexZAeff;
+      for(int i=0;i<vol->GetNdaughters();i++){
+	TGeoNode* daughter = vol->GetNode(i);
+	TGeoMaterial* matDaughter = daughter->GetMedium()->GetMaterial();
+	const TGeoShape* shape_sup = daughter->GetVolume()->GetShape();
+	TGeoMatrix* matrix = daughter->GetMatrix();
+	const double* pos = matrix->GetTranslation();
+	const double* rot_data = matrix->GetRotationMatrix();
+	TGeoRotation rot;
+	rot.SetMatrix(rot_data);
+	double theta,phi,psi;
+	rot.GetAngles(phi,theta,psi);
+	phi *= TMath::DegToRad();
+	theta *= TMath::DegToRad();
+	psi *= TMath::DegToRad();
+	phi0 = -TMath::PiOver2()+phi;
+	std::string phy_name = daughter->GetName();
+	if(phy_name.find("FoamSpacer")==-1&&phy_name.find("FlexCable")==-1&&phy_name.find("MetalTraces")==-1){
+	  //info() << phy_name <<endmsg;
+	  continue;
+	}
+	int iLayer = atoi(phy_name.substr(phy_name.find("_")+1,2).c_str());
+	if(iLayer!=currentLayer){
+	  //info() << tFoamSpacer << "," << tFlexCable << "," << tMetalTraces << endmsg;
+	  helpLadders[currentLayer].thickness = tFoamSpacer+tFlexCable+tMetalTraces;
+	  helpLadders[currentLayer].radLength = helpLadders[currentLayer].thickness / (tFoamSpacer/radLFoamSpacer+tFlexCable/radLFlexCable+tMetalTraces/radLMetalTraces);
+	  nFlexCable = 0;
+	  nFoamSpacer=0;
+	  nMetalTraces=0;
+	  currentLayer=iLayer;
+	}
+	//info() << "ss   pos=" << pos[0] << "," << pos[1] << "," << pos[2] << " distance=" << sqrt(pos[0]*pos[0]+pos[1]*pos[1]) << endmsg;
+	//info() << "ss   rot=" << phi << "," << theta << "," << psi << endmsg;
+	//info() << "ss " << daughter->GetName() << " " << daughter->GetVolume()->GetName() << " " << endmsg;
+	if(shape_sup->IsA()==TGeoBBox::Class()&&(nFoamSpacer==0||nFlexCable==0||nMetalTraces==0)){
+	  const TGeoBBox* box = (const TGeoBBox*) shape_sup;
+	  //info() << phy_name.substr(phy_name.find("_")+1,2) << " " << iLayer << " " << box->GetDX() << "," << box->GetDY() << "," << box->GetDZ() << endmsg;
+	  //info() << "fucd: pos " << pos[0] << " " << pos[1] << " " << pos[2] << endmsg; 
+	  double distance = fabs(cos(phi0)*sin(theta)*pos[0]+sin(phi0)*sin(theta)*pos[1]+cos(theta)*pos[2]);
+          double offset = sqrt(pos[0]*pos[0]+pos[1]*pos[1]-distance*distance)*pos[0]/fabs(pos[0])*CLHEP::cm;
+          distance -= box->GetDZ();
+	  distance *= CLHEP::cm;
+	  if(helpLadders[iLayer].distance == helpSensitives[iLayer].distance) helpLadders[iLayer].distance = distance;
+	  else helpLadders[iLayer].distance = TMath::Min(helpLadders[iLayer].distance, distance);
+	  //info() << phy_name << " " << distance << " " << offset << endmsg;
+	  if(phy_name.find("FoamSpacer")!=-1&&nFoamSpacer==0){
+	    helpLadders[iLayer].offset    = offset;
+	    tFoamSpacer = box->GetDZ()*CLHEP::cm;
+	    radLFoamSpacer = matDaughter->GetRadLen()*CLHEP::cm;
+	    intLFoamSpacer = matDaughter->GetIntLen()*CLHEP::cm;
+	    dFoamSpacer = matDaughter->GetDensity()*CLHEP::g/CLHEP::cm3;
+	    //fucd: A calculated by TGeoMaterial class is not equal to Zeff/ZAeff, Zeff = sum(Zi*Ai/sumA), ZAeff = sum(Zi/Ai*A/totalA)
+	    //      use Zeff and ZAeff to keep same with Mokka case  
+	    //foamZ = matDaughter->GetZ();
+	    //foamA = matDaughter->GetA();
+	    double totalA = 0, Zeff = 0, ZAeff = 0; 
+	    for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){
+	      totalA += matDaughter->GetElement(iEle)->A();
+	    }
+	    for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){
+	      double A, Z, w;
+	      // by fucd: w!=A/totalA, strange! to fix
+	      matDaughter->GetElementProp(A,Z,w,iEle);
+              Zeff  += Z*w;
+	      ZAeff += Z/A*w;
+	      //info() << std::setprecision(16) << Z << " " << A << " " << A/totalA << " " << w << endmsg;
+            }
+	    foamZeff = Zeff;
+	    foamZAeff = ZAeff;
+	    nFoamSpacer++;
+	  }
+	  if(phy_name.find("FlexCable")!=-1&&nFlexCable==0){
+	    helpLadders[iLayer].width     = box->GetDX()*CLHEP::cm;
+            helpLadders[iLayer].length    = box->GetDY()*CLHEP::cm-beryllium_ladder_block_length*2-end_electronics_half_z*2;
+	    tFlexCable = box->GetDZ()*CLHEP::cm;
+	    radLFlexCable = matDaughter->GetRadLen()*CLHEP::cm;
+	    intLFlexCable = matDaughter->GetIntLen()*CLHEP::cm;
+	    dFlexCable = matDaughter->GetDensity()*CLHEP::g/CLHEP::cm3;
+	    double Zeff = 0, ZAeff = 0;
+            for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){
+              double A, Z, w;
+	      matDaughter->GetElementProp(A,Z,w,iEle);
+              Zeff  += Z*w;
+              ZAeff += Z/A*w;
+	      //std::cout << std::setprecision(16) << Z << " " << A << " " << w << std::endl;
+            }
+	    flexZeff  = Zeff;
+	    flexZAeff = ZAeff;
+	    nFlexCable++;
+	  }
+	  if(phy_name.find("MetalTraces")!=-1&&nMetalTraces==0){
+	    tMetalTraces = box->GetDZ()*CLHEP::cm;
+	    radLMetalTraces = matDaughter->GetRadLen()*CLHEP::cm;
+	    intLMetalTraces = matDaughter->GetIntLen()*CLHEP::cm;
+	    dMetalTraces = matDaughter->GetDensity()*CLHEP::g/CLHEP::cm3;
+	    double totalA = 0, Zeff = 0, ZAeff = 0;
+            for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){
+              totalA += matDaughter->GetElement(iEle)->A();
+            }
+            for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){
+              double A, Z, w;
+	      matDaughter->GetElementProp(A,Z,w,iEle);
+	      Zeff  += Z*w;
+              ZAeff += Z/A*w;
+	      //info() << Z << " " << A << " " << w << endmsg;
+            }
+            metalZeff  = Zeff;
+            metalZAeff = ZAeff;
+	    nMetalTraces++;
+	  }
+	}
+      }
+      {
+	//info() << tFoamSpacer << "," << tFlexCable << "," << tMetalTraces << endmsg;
+	double tSupport = tMetalTraces + tFoamSpacer + tFlexCable;
+	helpLadders[currentLayer].thickness = tSupport;
+	helpLadders[currentLayer].radLength = helpLadders[currentLayer].thickness / (tFoamSpacer/radLFoamSpacer+tFlexCable/radLFlexCable+tMetalTraces/radLMetalTraces);
+	nFlexCable = 0;
+	nFoamSpacer=0;
+	nMetalTraces=0;
+
+	//calculations of thickness fractions of each layer of the support
+	double metalTF = tMetalTraces / tSupport;
+	double foamTF = tFoamSpacer / tSupport;
+	double flexTF = tFlexCable / tSupport;
+	//info() << foamTF << "," << flexTF << "," << metalTF << endmsg;
+	//info() << dFoamSpacer/(CLHEP::kg/CLHEP::cm3) << "," << dFlexCable/(CLHEP::kg/CLHEP::cm3) << "," << dMetalTraces/(CLHEP::kg/CLHEP::cm3) << endmsg;
+	//info() << foamZeff << " " << flexZeff << " " << metalZeff << endmsg;
+	//info() << foamZAeff << " " << flexZAeff << " " << metalZAeff << endmsg;
+	G4double elemVol = 1*CLHEP::cm3;
+	G4double VXDSupportMass = (foamTF*dFoamSpacer + flexTF*dFlexCable + metalTF*dMetalTraces)*elemVol;
+	VXDSupportDensity = VXDSupportMass/elemVol;
+	
+	G4double foamFM = 100. * ((foamTF*(elemVol)*dFoamSpacer) / VXDSupportMass) ;
+	G4double kaptonFM = 100. * ((flexTF*(elemVol)*dFlexCable) / VXDSupportMass) ;
+	G4double metalFM = 100. * ((metalTF*(elemVol)*dMetalTraces) / VXDSupportMass) ;
+
+	VXDSupportRadLen = helpLadders[currentLayer].radLength;
+
+	VXDSupportZeff = (metalFM/100.)*metalZeff + (kaptonFM/100.)*flexZeff + (foamFM/100.)*foamZeff;
+	G4double VXDSupportZAeff = (metalFM/100.)*metalZAeff + (kaptonFM/100.)*flexZAeff + (foamFM/100.)*foamZAeff;
+	VXDSupportAeff = VXDSupportZeff / VXDSupportZAeff;
+	G4double VXDSupportIntLength = 1. / ((metalTF/intLMetalTraces) + (flexTF/intLFlexCable) + (foamTF/intLFoamSpacer));
+	VXDSupportDensity = 1000*VXDSupportDensity/(CLHEP::g/CLHEP::cm3);
+	//info() << "fucd: " << VXDSupportZeff << " " << VXDSupportAeff << " " << VXDSupportRadLen << " " << VXDSupportIntLength << " " << VXDSupportDensity << endmsg; 
+	//info() << intLMetalTraces << " " << intLFlexCable << " " << intLFoamSpacer <<endmsg;
+      }
+    }
+    //info() << it->first << endmsg; 
+  }
+  if(end_electronics_half_z>0 && side_band_electronics_width==0) type = gear::ZPlanarParametersImpl::CCD  ;
+  if(side_band_electronics_width>0 && end_electronics_half_z==0 ) type = gear::ZPlanarParametersImpl::CMOS ;
+  if(side_band_electronics_width>0 && end_electronics_half_z>0) type = gear::ZPlanarParametersImpl::HYBRID ;
+  
+  m_vxdParameters = new gear::ZPlanarParametersImpl(type, shellInnerRadius, shellOuterRadius, shellHalfLength, gap, shellRadLength );
+  // by fucd: debug info, if validated enough, merge them in future
+  info() << "=====================from convertor==============================" << endmsg;
+  info() << type << " " << shellInnerRadius << " " << shellOuterRadius << " " << shellHalfLength << " " << gap << " " << shellRadLength << endmsg;
+  for(int i=0;i<helpCount;i++){
+    m_vxdParameters->addLayer(helpNumberLadders[i] , helpPhi0[i] ,
+			    helpLadders[i].distance , helpLadders[i].offset, helpLadders[i].thickness*2 ,
+			    helpLadders[i].length , helpLadders[i].width*2 , helpLadders[i].radLength ,
+			    helpSensitives[i].distance, helpSensitives[i].offset , helpSensitives[i].thickness*2 ,
+			    helpSensitives[i].length , helpSensitives[i].width*2 , helpSensitives[i].radLength ) ;
+    info() << "fucd " << i << ": " << helpNumberLadders[i] << ", " << helpPhi0[i] << ", "
+	   << helpLadders[i].distance << ", " << helpLadders[i].offset << ", " << helpLadders[i].thickness*2 << ", " << helpLadders[i].length << ", "
+	   << helpLadders[i].width*2 << ", " << helpLadders[i].radLength << ", " << helpSensitives[i].distance << ", " << helpSensitives[i].offset << ", "
+	   << helpSensitives[i].thickness*2 << ", " << helpSensitives[i].length << ", " << helpSensitives[i].width*2 << ", " << helpSensitives[i].radLength << endmsg;
+  }
+  //m_vxdInfra = new gear::GearParametersImpl;
+  //CryostatAlRadius, CryostatAlThickness, CryostatAlInnerR, CryostatAlZEndCap, CryostatAlHalfZ
+  //m_vxdInfra->setDoubleVal("CryostatAlRadius",rAlu);
+  //m_vxdInfra->setDoubleVal("CryostatAlThickness",drAlu);
+  //m_vxdInfra->setDoubleVal("CryostatAlInnerR",rInner);
+  //m_vxdInfra->setDoubleVal("CryostatAlZEndCap",aluEndcapZ=dzSty + drSty + drAlu / 2);
+  //m_vxdInfra->setDoubleVal("CryostatAlHalfZ",aluHalfZ= dzSty + drSty);
+  // change GearParametersImpl to map
+  std::map<std::string,double> vxdInfra;
+  vxdInfra["CryostatAlRadius"]    = rAlu;
+  vxdInfra["CryostatAlThickness"] = drAlu;
+  vxdInfra["CryostatAlInnerR"]    = rInner;
+  vxdInfra["CryostatAlZEndCap"]   = dzSty+drSty+drAlu/2;
+  vxdInfra["CryostatAlHalfZ"]     = dzSty+drSty;
+  m_detParameters["VXDInfra"] = vxdInfra;
+  //effective A different with what in Mokka, fix them as Mokka's 
+  //m_materials["VXDSupportMaterial"] = new TMaterial("VXDSupportMaterial", "", VXDSupportAeff, VXDSupportZeff, VXDSupportDensity, VXDSupportRadLen, 0.);
+  m_materials["VXDSupportMaterial"] = new TMaterial("VXDSupportMaterial", "", 2.075865162e+01, 1.039383117e+01, 2.765900000e+02/1000, 1.014262421e+02, 0.);
+
+  info() << "=====================from ZPlanarData==============================" << endmsg;
+  if(m_vxdData){
+    info() << m_vxdData->rInnerShell << " " << m_vxdData->rOuterShell << " " << m_vxdData->zHalfShell << " " << m_vxdData->gapShell << endmsg;
+    const std::vector<dd4hep::rec::ZPlanarData::LayerLayout>& layers = m_vxdData->layers;
+    for(int i=0;i<layers.size();i++){
+      const dd4hep::rec::ZPlanarData::LayerLayout& thisLayer = layers[i];
+      info() << i << ": " << thisLayer.ladderNumber << "," << thisLayer.phi0 << "," << thisLayer.distanceSupport << "," << thisLayer.offsetSupport << ","
+	     << thisLayer.thicknessSupport << "," << thisLayer.zHalfSupport << "," << thisLayer.widthSupport << "," << "NULL," 
+	     << thisLayer.distanceSensitive << "," << thisLayer.offsetSensitive << "," << thisLayer.thicknessSensitive << "," << thisLayer.zHalfSensitive << ","
+	     << thisLayer.widthSensitive << ",NULL" << endmsg;
+    }
+  }
+  info() << rAlu << " " << drAlu << " " << rInner << " " << aluEndcapZ << " " << aluHalfZ << endmsg; 
+  //info() << m_materials["VXDSupportMaterial"] << endmsg; 
+  return sc;
+}
+
+TGeoNode* GeoSvc::FindNode(TGeoNode* mother, char* name){
+  TGeoNode* next = 0;
+  if(mother->GetNdaughters()!=0){ 
+    for(int i=0;i<mother->GetNdaughters();i++){
+      TGeoNode* daughter = mother->GetDaughter(i);
+      std::string s = daughter->GetName();
+      //info() << "current: " << s << " search for" << name << endmsg;
+      if(s.find(name)!=-1){
+	next = daughter;
+	break;
+      }
+      else{
+	next = FindNode(daughter, name);
+      }
+    }
+  }
+  return next;
+}
+
+TMaterial* GeoSvc::getMaterial(std::string name){
+  std::map<std::string, TMaterial*>::const_iterator it = m_materials.find(name);
+  if(it!=m_materials.end()) return it->second;
+  else return 0;     
+}
diff --git a/Detector/GeoSvc/src/GeoSvc.h b/Detector/GeoSvc/src/GeoSvc.h
index 9c98daa9..cc54142f 100644
--- a/Detector/GeoSvc/src/GeoSvc.h
+++ b/Detector/GeoSvc/src/GeoSvc.h
@@ -15,27 +15,61 @@
 // DD4Hep
 #include "DD4hep/Detector.h"
 
-class GeoSvc: public extends<Service, IGeoSvc> {
-public:
-    GeoSvc(const std::string& name, ISvcLocator* svc);
-    ~GeoSvc();
+#include <gear/GEAR.h>
+#include <gearimpl/ZPlanarParametersImpl.h>
+#include <gearimpl/GearParametersImpl.h>
+
+class dd4hep::DetElement;
+class TGeoNode;
 
-    // Service
-    StatusCode initialize() override;
-    StatusCode finalize() override;
+class GeoSvc: public extends<Service, IGeoSvc> {
+ public:
+  GeoSvc(const std::string& name, ISvcLocator* svc);
+  ~GeoSvc();
+  
+  // Service
+  StatusCode initialize() override;
+  StatusCode finalize() override;
+  
+  // IGeoSvc
+  dd4hep::DetElement getDD4HepGeo() override;
+  dd4hep::Detector* lcdd() override;
+  
+  const gear::ZPlanarParametersImpl*  getVXDParameters() override {return m_vxdParameters;};
+  const dd4hep::rec::ZPlanarData* getVXDData() override {return m_vxdData;};
+  const dd4hep::rec::ConicalSupportData* getBeamPipeData() override {return m_beamData;};
 
-    // IGeoSvc
-    dd4hep::DetElement getDD4HepGeo() override;
-    dd4hep::Detector* lcdd() override;
+  const std::map<std::string,double>& getDetParameters(std::string name) override;
+  const double getDetParameter(std::string set_name, std::string par_name) override;
+  TMaterial* getMaterial(std::string name);
+  
+ private:
+  StatusCode convertVXD(dd4hep::DetElement& sub);
 
-private:
+  TGeoNode* FindNode(TGeoNode* mother, char* name);
+  // DD4hep XML compact file path
+  Gaudi::Property<std::string> m_dd4hep_xmls{this, "compact"};
+  
+  // 
+  dd4hep::Detector* m_dd4hep_geo;
 
-    // DD4hep XML compact file path
-    Gaudi::Property<std::string> m_dd4hep_xmls{this, "compact"};
+  gear::ZPlanarParametersImpl* m_vxdParameters;
+  dd4hep::rec::ZPlanarData* m_vxdData;
+  dd4hep::rec::ConicalSupportData* m_beamData;
 
-    // 
-    dd4hep::Detector* m_dd4hep_geo;
+  //gear::GearParametersImpl* m_vxdInfra;
+  std::map<std::string, std::map<std::string,double> > m_detParameters;
+  std::map<std::string, TMaterial*> m_materials;
+  struct helpLayer {
+    double distance =0;
+    double offset =0;
+    double thickness =0;
+    double length =0;
+    double width =0;
+    double radLength =0;
+    double z =0;
+    double foam_spacer_radLength =0;
+  };
 };
 
-
 #endif GeoSvc_h
-- 
GitLab