Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:16:48

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework includes
0015 #include "LCDDConverter.h"
0016 #include <DD4hep/Plugins.h>
0017 #include <DD4hep/Printout.h>
0018 #include <DD4hep/Volumes.h>
0019 #include <DD4hep/FieldTypes.h>
0020 #include <DD4hep/DD4hepUnits.h>
0021 #include <DD4hep/Segmentations.h>
0022 #include <DD4hep/detail/ObjectsInterna.h>
0023 #include <DD4hep/detail/DetectorInterna.h>
0024 #include <XML/DocumentHandler.h>
0025 
0026 // ROOT includes
0027 #include <TROOT.h>
0028 #include <TColor.h>
0029 #include <TGeoShape.h>
0030 
0031 #include <TGeoArb8.h>
0032 #include <TGeoBoolNode.h>
0033 #include <TGeoCompositeShape.h>
0034 #include <TGeoCone.h>
0035 #include <TGeoEltu.h>
0036 #include <TGeoHype.h>
0037 #include <TGeoMatrix.h>
0038 #include <TGeoParaboloid.h>
0039 #include <TGeoPara.h>
0040 #include <TGeoPcon.h>
0041 #include <TGeoPgon.h>
0042 #include <TGeoShapeAssembly.h>
0043 #include <TGeoSphere.h>
0044 #include <TGeoTorus.h>
0045 #include <TGeoTrd1.h>
0046 #include <TGeoTrd2.h>
0047 #include <TGeoTube.h>
0048 #include <TGeoScaledShape.h>
0049 
0050 #include <TGeoNode.h>
0051 #include <TClass.h>
0052 #include <TMath.h>
0053 
0054 /// C/C++ include files
0055 #include <fstream>
0056 #include <iostream>
0057 #include <sstream>
0058 #include <iomanip>
0059 
0060 using namespace dd4hep;
0061 using namespace dd4hep::detail;
0062 
0063 namespace {
0064   typedef Position XYZRotation;
0065 
0066   XYZRotation getXYZangles(const Double_t* r) {
0067     Double_t cosb = std::sqrt(r[0]*r[0] + r[1]*r[1]);
0068     if (cosb > 0.00001) {
0069       return XYZRotation(atan2(r[5], r[8]), atan2(-r[2], cosb), atan2(r[1], r[0]));
0070     }
0071     return XYZRotation(atan2(-r[7], r[4]),atan2(-r[2], cosb),0);
0072   }
0073 
0074 #if 0
0075   XYZRotation getXYZangles(const Double_t* rotationMatrix) {
0076     Double_t a, b, c;
0077     Double_t rad = 1.0;   // RAD by default! 180.0 / TMath::ACos(-1.0);
0078     const Double_t *r = rotationMatrix;
0079     Double_t cosb = TMath::Sqrt(r[0] * r[0] + r[1] * r[1]);
0080     if (cosb > 0.00001) {
0081       a = TMath::ATan2(r[5], r[8]) * rad;
0082       b = TMath::ATan2(-r[2], cosb) * rad;
0083       c = TMath::ATan2(r[1], r[0]) * rad;
0084     }
0085     else {
0086       a = TMath::ATan2(-r[7], r[4]) * rad;
0087       b = TMath::ATan2(-r[2], cosb) * rad;
0088       c = 0;
0089     }
0090     XYZRotation rr(a, b, c);
0091     std::cout << " X:" << a << " " << rr.X() << " Y:" << b << " " << rr.Y() << " Z:" << c << " " << rr.Z()
0092               << " lx:" << r[0] << " ly:" << r[4] << " lz:" << r[8] << std::endl;
0093     return XYZRotation(a, b, c);
0094   }
0095 #endif
0096 
0097   bool is_volume(const TGeoVolume* volume)  {
0098     Volume v(volume);
0099     return v.data() != 0;
0100   }
0101   bool is_placement(PlacedVolume node)  {
0102     return node.data() != 0;
0103   }
0104 
0105   std::string genName(const std::string& n)  {  return n; }
0106   std::string genName(const std::string& n, const void* ptr)  {
0107     std::string nn = genName(n);
0108     char text[32];
0109     ::snprintf(text,sizeof(text),"%p",ptr);
0110     nn += "_";
0111     nn += text;
0112     return nn;
0113   }
0114 }
0115 
0116 void LCDDConverter::GeometryInfo::check(const std::string& name, const TNamed* _n, std::map<std::string, const TNamed*>& _m) const {
0117   std::map<std::string, const TNamed*>::const_iterator i = _m.find(name);
0118   if (i != _m.end()) {
0119     const char* isa = _n ? _n->IsA()->GetName() : (*i).second ? (*i).second->IsA()->GetName() : "Unknown";
0120     std::cout << isa << "(position):  duplicate entry with name:" << name << " " << (void*) _n << " " << (void*) (*i).second << std::endl;
0121   }
0122   _m.insert(make_pair(name, _n));
0123 }
0124 
0125 /// Initializing Constructor
0126 LCDDConverter::LCDDConverter(Detector& description)
0127   : m_detDesc(description), m_dataPtr(0) {
0128 }
0129 
0130 LCDDConverter::~LCDDConverter() {
0131   if (m_dataPtr)
0132     delete m_dataPtr;
0133   m_dataPtr = 0;
0134 }
0135 
0136 /// Dump element in GDML format to output stream
0137 xml_h LCDDConverter::handleElement(const std::string& /* name */, Atom element) const {
0138   GeometryInfo& geo = data();
0139   xml_h e = geo.xmlElements[element];
0140   if (!e) {
0141     int Z = element->Z();
0142     double A = element->A();
0143     xml_elt_t atom(geo.doc, _U(atom));
0144     // If we got an unphysical material (Z<1 or A<1)
0145     // We pretend it is hydrogen and force Z=1 or A=1.00794 g/mole
0146     geo.doc_materials.append(e = xml_elt_t(geo.doc, _U(element)));
0147     e.append(atom);
0148     e.setAttr(_U(name), element->GetName());
0149     e.setAttr(_U(formula), element->GetName());
0150     e.setAttr(_U(Z), Z>0 ? Z : 1);
0151     atom.setAttr(_U(type), "A");
0152     atom.setAttr(_U(unit), "g/mol");
0153     atom.setAttr(_U(value), A>0.99 ? A : 1.00794 /* *(g/mole) */);
0154     geo.xmlElements[element] = e;
0155   }
0156   return e;
0157 }
0158 
0159 /// Dump material in GDML format to output stream
0160 xml_h LCDDConverter::handleMaterial(const std::string& name, Material medium) const {
0161   GeometryInfo& geo = data();
0162   xml_h mat = geo.xmlMaterials[medium];
0163   if (!mat) {
0164     xml_h obj;
0165     TGeoMaterial* geo_mat = medium->GetMaterial();
0166     double d = geo_mat->GetDensity();   //*(gram/cm3);
0167     if (d < 1e-10) d = 1e-10;
0168     mat = xml_elt_t(geo.doc, _U(material));
0169     mat.setAttr(_U(name), medium->GetName());
0170     mat.append(obj = xml_elt_t(geo.doc, _U(D)));
0171     obj.setAttr(_U(value), d /*  *(g/cm3)  */);
0172     obj.setAttr(_U(unit), "g/cm3");
0173     obj.setAttr(_U(type), "density");
0174 
0175     geo.checkMaterial(name, medium);
0176 
0177     if (geo_mat->IsMixture()) {
0178       TGeoMixture   *mix = (TGeoMixture*)geo_mat;
0179       const double *wmix = mix->GetWmixt();
0180       const int    *nmix = mix->GetNmixt();
0181       double sum = 0e0;
0182       for (int i = 0, n = mix->GetNelements(); i < n; i++) {
0183         TGeoElement *elt = mix->GetElement(i);
0184         handleElement(elt->GetName(), Atom(elt));
0185         sum += wmix[i];
0186       }
0187       for (int i = 0, n = mix->GetNelements(); i < n; i++) {
0188         TGeoElement *elt = mix->GetElement(i);
0189         //std::string formula = elt->GetTitle() + std::string("_elm");
0190         if (nmix) {
0191           mat.append(obj = xml_elt_t(geo.doc, _U(composite)));
0192           obj.setAttr(_U(n), nmix[i]);
0193         }
0194         else {
0195           mat.append(obj = xml_elt_t(geo.doc, _U(fraction)));
0196           obj.setAttr(_U(n), wmix[i] / sum);
0197         }
0198         obj.setAttr(_U(ref), elt->GetName());
0199       }
0200     }
0201     else if ( name != "dummy" )   {  
0202       // Do not exactly know where dummy comes from,
0203       // but it causes havoc in Geant4 later
0204       TGeoElement *elt = geo_mat->GetElement(0);
0205       printout(INFO,"++ Converting non mixing material: %s",name.c_str());
0206       xml_elt_t atom(geo.doc, _U(atom));
0207       handleElement(elt->GetName(), Atom(elt));
0208       mat.append(atom);
0209       mat.setAttr(_U(Z), geo_mat->GetZ());
0210       atom.setAttr(_U(type), "A");
0211       atom.setAttr(_U(unit), "g/mol");
0212       atom.setAttr(_U(value), geo_mat->GetA() /*  *(g/mole)  */);
0213     }
0214     geo.doc_materials.append(mat);
0215     geo.xmlMaterials[medium] = mat;
0216   }
0217   return mat;
0218 }
0219 
0220 /// Dump solid in GDML format to output stream
0221 xml_h LCDDConverter::handleSolid(const std::string& name, const TGeoShape* shape) const {
0222   GeometryInfo& geo = data();
0223   SolidMap::iterator sit = geo.xmlSolids.find(shape);
0224   if (!shape) {
0225     // This is an invalid volume. Let's pray returning nothing will work,
0226     // and the non-existing solid is also nowhere referenced in the GDML.
0227     return xml_h(0);
0228   }
0229   else if (sit != geo.xmlSolids.end()) {
0230     // The solidis already registered. Return the reference
0231     return (*sit).second;
0232   }
0233   else if (shape->IsA() == TGeoShapeAssembly::Class()) {
0234     // Assemblies have no shape in GDML. Hence, return nothing.
0235     return xml_h(0);
0236   }
0237   else {
0238     xml_h solid(0);
0239     xml_h zplane(0);
0240     TClass* isa = shape->IsA();
0241     std::string shape_name = shape->GetName(); //genName(shape->GetName(),shape);
0242     geo.checkShape(name, shape);
0243     if (isa == TGeoBBox::Class()) {
0244       const TGeoBBox* sh = (const TGeoBBox*) shape;
0245       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(box)));
0246       solid.setAttr(_U(name), Unicode(shape_name));
0247       solid.setAttr(_U(x), 2 * sh->GetDX());
0248       solid.setAttr(_U(y), 2 * sh->GetDY());
0249       solid.setAttr(_U(z), 2 * sh->GetDZ());
0250       solid.setAttr(_U(lunit), "cm");
0251     }
0252     else if (isa == TGeoTube::Class()) {
0253       const TGeoTube* sh = (const TGeoTube*) shape;
0254       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(tube)));
0255       solid.setAttr(_U(name), Unicode(shape_name));
0256       solid.setAttr(_U(rmin), sh->GetRmin());
0257       solid.setAttr(_U(rmax), sh->GetRmax());
0258       solid.setAttr(_U(z), 2 * sh->GetDz());
0259       solid.setAttr(_U(startphi), 0e0);
0260       solid.setAttr(_U(deltaphi), 360.0);
0261       solid.setAttr(_U(aunit), "deg");
0262       solid.setAttr(_U(lunit), "cm");
0263     }
0264     else if (isa == TGeoTubeSeg::Class()) {
0265       const TGeoTubeSeg* sh = (const TGeoTubeSeg*) shape;
0266       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(tube)));
0267       solid.setAttr(_U(name), Unicode(shape_name));
0268       solid.setAttr(_U(rmin), sh->GetRmin());
0269       solid.setAttr(_U(rmax), sh->GetRmax());
0270       solid.setAttr(_U(z), 2 * sh->GetDz());   // Full zlen in GDML, half zlen in TGeo
0271       solid.setAttr(_U(startphi), sh->GetPhi1());
0272       solid.setAttr(_U(deltaphi), sh->GetPhi2());
0273       solid.setAttr(_U(aunit), "deg");
0274       solid.setAttr(_U(lunit), "cm");
0275     }
0276     else if (isa == TGeoEltu::Class()) {
0277       const TGeoEltu* sh = (const TGeoEltu*) shape;
0278       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(eltube)));
0279       solid.setAttr(_U(name), Unicode(shape_name));
0280       solid.setAttr(_U(dx), sh->GetA());
0281       solid.setAttr(_U(dy), sh->GetB());
0282       solid.setAttr(_U(dz), sh->GetDz());
0283       solid.setAttr(_U(lunit), "cm");
0284     }
0285     else if (isa == TGeoTrd1::Class()) {
0286       const TGeoTrd1* sh = (const TGeoTrd1*) shape;
0287       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(trd)));
0288       solid.setAttr(_U(name), Unicode(shape_name));
0289       solid.setAttr(_U(x1), 2 * sh->GetDx1());
0290       solid.setAttr(_U(x2), 2 * sh->GetDx2());
0291       solid.setAttr(_U(y1), 2 * sh->GetDy());
0292       solid.setAttr(_U(y2), 2 * sh->GetDy());
0293       solid.setAttr(_U(z),  2 * sh->GetDz());   // Full zlen in GDML, half zlen in TGeo
0294       solid.setAttr(_U(lunit), "cm");
0295     }
0296     else if (isa == TGeoTrd2::Class()) {
0297       const TGeoTrd2* sh = (const TGeoTrd2*) shape;
0298       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(trd)));
0299       solid.setAttr(_U(name), Unicode(shape_name));
0300       solid.setAttr(_U(x1), 2 * sh->GetDx1());
0301       solid.setAttr(_U(x2), 2 * sh->GetDx2());
0302       solid.setAttr(_U(y1), 2 * sh->GetDy1());
0303       solid.setAttr(_U(y2), 2 * sh->GetDy2());
0304       solid.setAttr(_U(z),  2 * sh->GetDz());   // Full zlen in GDML, half zlen in TGeo
0305       solid.setAttr(_U(lunit), "cm");
0306     }
0307     else if (isa == TGeoHype::Class()) {
0308       const TGeoHype* sh = (const TGeoHype*) shape;
0309       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(hype)));
0310       solid.setAttr(_U(name), Unicode(shape_name));
0311       solid.setAttr(_U(rmin),  sh->GetRmin());
0312       solid.setAttr(_U(rmax),  sh->GetRmax());
0313       solid.setAttr(Unicode("inst"),  sh->GetStIn());
0314       solid.setAttr(_U(outst), sh->GetStOut());
0315       solid.setAttr(_U(z),     sh->GetDz());   // Full zlen in GDML, half zlen in TGeo
0316       solid.setAttr(_U(aunit), "deg");
0317       solid.setAttr(_U(lunit), "cm");
0318     }
0319     else if (isa == TGeoPgon::Class()) {
0320       const TGeoPgon* sh = (const TGeoPgon*) shape;
0321       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(polyhedra)));
0322       solid.setAttr(_U(name), Unicode(shape_name));
0323       solid.setAttr(_U(startphi), sh->GetPhi1());
0324       solid.setAttr(_U(deltaphi), sh->GetDphi());
0325       solid.setAttr(_U(numsides), sh->GetNedges());
0326       solid.setAttr(_U(aunit), "deg");
0327       solid.setAttr(_U(lunit), "cm"); 
0328       for (Int_t i = 0; i < sh->GetNz(); ++i) {
0329         zplane = xml_elt_t(geo.doc, _U(zplane));
0330         zplane.setAttr(_U(z), sh->GetZ(i));
0331         zplane.setAttr(_U(rmin), sh->GetRmin(i));
0332         zplane.setAttr(_U(rmax), sh->GetRmax(i));
0333         solid.append(zplane);
0334       }
0335     }
0336     else if (isa == TGeoPcon::Class()) {
0337       const TGeoPcon* sh = (const TGeoPcon*) shape;
0338       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(polycone)));
0339       solid.setAttr(_U(name), Unicode(shape_name));
0340       solid.setAttr(_U(startphi), sh->GetPhi1());
0341       solid.setAttr(_U(deltaphi), sh->GetDphi());
0342       solid.setAttr(_U(aunit), "deg");
0343       solid.setAttr(_U(lunit), "cm"); 
0344       for (Int_t i = 0; i < sh->GetNz(); ++i) {
0345         zplane = xml_elt_t(geo.doc, _U(zplane));
0346         zplane.setAttr(_U(z), sh->GetZ(i));
0347         zplane.setAttr(_U(rmin), sh->GetRmin(i));
0348         zplane.setAttr(_U(rmax), sh->GetRmax(i));
0349         solid.append(zplane);
0350       }
0351       solid.setAttr(_U(lunit), "cm");
0352     }
0353     else if (isa == TGeoCone::Class()) {
0354       const TGeoCone* sh = (const TGeoCone*) shape;
0355       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(cone)));
0356       solid.setAttr(_U(name), Unicode(shape_name));
0357       solid.setAttr(_U(z),     2 * sh->GetDz());
0358       solid.setAttr(_U(rmin1), sh->GetRmin1());
0359       solid.setAttr(_U(rmax1), sh->GetRmax1());
0360       solid.setAttr(_U(rmin2), sh->GetRmin2());
0361       solid.setAttr(_U(rmax2), sh->GetRmax2());
0362       solid.setAttr(_U(startphi), 0e0);
0363       solid.setAttr(_U(deltaphi), 360.0);
0364       solid.setAttr(_U(aunit), "deg");
0365       solid.setAttr(_U(lunit), "cm");
0366     }
0367     else if (isa == TGeoConeSeg::Class()) {
0368       const TGeoConeSeg* sh = (const TGeoConeSeg*) shape;
0369       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(cone)));
0370       solid.setAttr(_U(name), Unicode(shape_name));
0371       solid.setAttr(_U(z), 2*sh->GetDz());
0372       solid.setAttr(_U(rmin1), sh->GetRmin1());
0373       solid.setAttr(_U(rmin2), sh->GetRmin2());
0374       solid.setAttr(_U(rmax1), sh->GetRmax1());
0375       solid.setAttr(_U(rmax2), sh->GetRmax2());
0376       solid.setAttr(_U(startphi), sh->GetPhi1());
0377       solid.setAttr(_U(deltaphi), sh->GetPhi2() - sh->GetPhi1());
0378       solid.setAttr(_U(aunit), "deg");
0379       solid.setAttr(_U(lunit), "cm");
0380     }
0381     else if (isa == TGeoParaboloid::Class()) {
0382       const TGeoParaboloid* sh = (const TGeoParaboloid*) shape;
0383       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(paraboloid)));
0384       solid.setAttr(_U(name), Unicode(shape_name));
0385       solid.setAttr(_U(rlo), sh->GetRlo());
0386       solid.setAttr(_U(rhi), sh->GetRhi());
0387       solid.setAttr(_U(dz),  sh->GetDz());
0388       solid.setAttr(_U(lunit), "cm");
0389     }
0390 #if 0
0391     else if (isa == TGeoEllipsoid::Class()) {
0392       const TGeoEllipsoid* sh = (const TGeoEllipsoid*) shape;
0393       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(ellipsoid)));
0394       solid.setAttr(_U(lunit), "cm");
0395     }
0396 #endif
0397     else if (isa == TGeoSphere::Class()) {
0398       const TGeoSphere* sh = (const TGeoSphere*) shape;
0399       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(sphere)));
0400       solid.setAttr(_U(name), Unicode(shape_name));
0401       solid.setAttr(_U(rmin),        sh->GetRmin());
0402       solid.setAttr(_U(rmax),        sh->GetRmax());
0403       solid.setAttr(_U(startphi),    sh->GetPhi1());
0404       solid.setAttr(_U(deltaphi),   (sh->GetPhi2() - sh->GetPhi1()));
0405       solid.setAttr(_U(starttheta),  sh->GetTheta1());
0406       solid.setAttr(_U(deltatheta), (sh->GetTheta2() - sh->GetTheta1()));
0407       solid.setAttr(_U(aunit), "deg");
0408       solid.setAttr(_U(lunit), "cm");
0409     }
0410     else if (isa == TGeoTorus::Class()) {
0411       const TGeoTorus* sh = (const TGeoTorus*) shape;
0412       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(torus)));
0413       solid.setAttr(_U(name), Unicode(shape_name));
0414       solid.setAttr(_U(rtor),     sh->GetR());
0415       solid.setAttr(_U(rmin),     sh->GetRmin());
0416       solid.setAttr(_U(rmax),     sh->GetRmax());
0417       solid.setAttr(_U(startphi), sh->GetPhi1());
0418       solid.setAttr(_U(deltaphi), sh->GetDphi());
0419       solid.setAttr(_U(aunit), "deg");
0420       solid.setAttr(_U(lunit), "cm");
0421     }
0422     else if (isa == TGeoTrap::Class()) {
0423       const TGeoTrap* sh = (const TGeoTrap*) shape;
0424       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(trap)));
0425       solid.setAttr(_U(name), Unicode(shape_name));
0426       solid.setAttr(_U(z),  2 * sh->GetDz());   // Full zlen in GDML, half zlen in TGeo
0427       solid.setAttr(_U(x1), 2 * sh->GetBl1());
0428       solid.setAttr(_U(x2), 2 * sh->GetTl1());
0429       solid.setAttr(_U(x3), 2 * sh->GetBl2());
0430       solid.setAttr(_U(x4), 2 * sh->GetTl2());
0431       solid.setAttr(_U(y1), 2 * sh->GetH1());
0432       solid.setAttr(_U(y2), 2 * sh->GetH2());
0433       solid.setAttr(_U(alpha1), sh->GetAlpha1());
0434       solid.setAttr(_U(alpha2), sh->GetAlpha2());
0435       solid.setAttr(_U(theta),  sh->GetTheta());
0436       solid.setAttr(_U(phi),    sh->GetPhi());
0437       solid.setAttr(_U(aunit), "deg");
0438       solid.setAttr(_U(lunit), "cm");
0439     }
0440     else if (isa == TGeoPara::Class()) {
0441       const TGeoPara* sh = (const TGeoPara*) shape;
0442       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(para)));
0443       solid.setAttr(_U(name), Unicode(shape_name));
0444       solid.setAttr(_U(x), sh->GetX());
0445       solid.setAttr(_U(y), sh->GetY());
0446       solid.setAttr(_U(z), sh->GetZ());
0447       solid.setAttr(_U(alpha), sh->GetAlpha());
0448       solid.setAttr(_U(theta), sh->GetTheta());
0449       solid.setAttr(_U(phi),   sh->GetPhi());
0450       solid.setAttr(_U(aunit), "deg");
0451       solid.setAttr(_U(lunit), "cm");
0452     }
0453     else if (isa == TGeoArb8::Class()) {
0454       TGeoArb8* sh = (TGeoArb8*) shape;
0455       const double* vtx = sh->GetVertices();
0456       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(arb8)));
0457       solid.setAttr(_U(name), Unicode(shape_name));
0458       solid.setAttr(_U(v1x), vtx[0]);
0459       solid.setAttr(_U(v1y), vtx[1]);
0460       solid.setAttr(_U(v2x), vtx[2]);
0461       solid.setAttr(_U(v2y), vtx[3]);
0462       solid.setAttr(_U(v3x), vtx[4]);
0463       solid.setAttr(_U(v3y), vtx[5]);
0464       solid.setAttr(_U(v4x), vtx[6]);
0465       solid.setAttr(_U(v4y), vtx[7]);
0466       solid.setAttr(_U(v5x), vtx[8]);
0467       solid.setAttr(_U(v5y), vtx[9]);
0468       solid.setAttr(_U(v6x), vtx[10]);
0469       solid.setAttr(_U(v6y), vtx[11]);
0470       solid.setAttr(_U(v7x), vtx[12]);
0471       solid.setAttr(_U(v7y), vtx[13]);
0472       solid.setAttr(_U(v8x), vtx[14]);
0473       solid.setAttr(_U(v8y), vtx[15]);
0474       solid.setAttr(_U(dz),  sh->GetDz());
0475       solid.setAttr(_U(lunit), "cm");
0476     }
0477     else if (isa == TGeoScaledShape::Class())  {
0478       TGeoScaledShape* sh = (TGeoScaledShape*) shape;
0479       const double*    vals = sh->GetScale()->GetScale();
0480       Solid            s_sh(sh->GetShape());
0481       handleSolid(s_sh.name(), s_sh.ptr());
0482       geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(scale)));
0483       solid.setAttr(_U(name), Unicode(shape_name));
0484       solid.setAttr(_U(shape), s_sh.name());
0485       solid.setAttr(_U(x),     vals[0]);
0486       solid.setAttr(_U(y),     vals[1]);
0487       solid.setAttr(_U(z),     vals[2]);
0488       solid.setAttr(_U(aunit), "deg");
0489       solid.setAttr(_U(lunit), "cm");
0490     }
0491     else if (isa == TGeoCompositeShape::Class() ||
0492              isa == TGeoUnion::Class() ||
0493              isa == TGeoIntersection::Class() ||
0494              isa == TGeoSubtraction::Class() )  {
0495       const TGeoCompositeShape* sh = (const TGeoCompositeShape*) shape;
0496       const TGeoBoolNode* boolean = sh->GetBoolNode();
0497       TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator();
0498       TGeoMatrix* rm = boolean->GetRightMatrix();
0499       TGeoMatrix* lm = boolean->GetLeftMatrix();
0500       TGeoShape* ls = boolean->GetLeftShape();
0501       TGeoShape* rs = boolean->GetRightShape();
0502       xml_h left    = handleSolid(ls->GetName(), ls);
0503       xml_h right   = handleSolid(rs->GetName(), rs);
0504       xml_h first_solid(0), second_solid(0);
0505       if (!left) {
0506         throw std::runtime_error("G4Converter: No left Detector Solid present for composite shape:" + name);
0507       }
0508       if (!right) {
0509         throw std::runtime_error("G4Converter: No right Detector Solid present for composite shape:" + name);
0510       }
0511 
0512       //specific case!
0513       //Ellipsoid tag preparing
0514       //if left == TGeoScaledShape AND right  == TGeoBBox
0515       //   AND if TGeoScaledShape->GetShape == TGeoSphere
0516       if (strcmp(ls->ClassName(), "TGeoScaledShape") == 0 &&
0517           strcmp(rs->ClassName(), "TGeoBBox") == 0) {
0518         if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(), "TGeoSphere") == 0) {
0519           if (oper == TGeoBoolNode::kGeoIntersection) {
0520             TGeoScaledShape* lls = (TGeoScaledShape *)ls;
0521             TGeoBBox* rrs = (TGeoBBox*)rs;
0522             solid = xml_elt_t(geo.doc,Unicode("ellipsoid"));
0523             solid.setAttr(_U(name), Unicode(shape_name));
0524             double sx = lls->GetScale()->GetScale()[0];
0525             double sy = lls->GetScale()->GetScale()[1];
0526             double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
0527             double dz = rrs->GetDZ();
0528             double zorig = rrs->GetOrigin()[2];
0529             double zcut2 = dz + zorig;
0530             double zcut1 = 2 * zorig - zcut2;
0531             solid.setAttr(Unicode("ax"),sx * radius);
0532             solid.setAttr(Unicode("by"),sy * radius);
0533             solid.setAttr(Unicode("cz"),radius);
0534             solid.setAttr(Unicode("zcut1"),zcut1);
0535             solid.setAttr(Unicode("zcut2"),zcut2);
0536             solid.setAttr(_U(lunit), "cm");
0537             return data().xmlSolids[shape] = solid;
0538           }
0539         }
0540       }
0541 
0542       if ( oper == TGeoBoolNode::kGeoSubtraction )
0543         solid = xml_elt_t(geo.doc,_U(subtraction));
0544       else if ( oper == TGeoBoolNode::kGeoUnion )
0545         solid = xml_elt_t(geo.doc,_U(union));
0546       else if ( oper == TGeoBoolNode::kGeoIntersection )
0547         solid = xml_elt_t(geo.doc,_U(intersection));
0548 
0549       xml_h obj;
0550       std::string lnam = left.attr<std::string>(_U(name));
0551       std::string rnam = right.attr<std::string>(_U(name));
0552 
0553       geo.doc_solids.append(solid);
0554       solid.append(first_solid = xml_elt_t(geo.doc, _U(first)));
0555       solid.setAttr(_U(name), Unicode(shape_name));
0556       first_solid.setAttr(_U(ref),  lnam);
0557       const double *tr = lm->GetTranslation();
0558 
0559       if ((tr[0] != 0.0) || (tr[1] != 0.0) || (tr[2] != 0.0)) {
0560         first_solid.append(obj = xml_elt_t(geo.doc, _U(firstposition)));
0561         obj.setAttr(_U(name), name+"_"+lnam+"_pos");
0562         obj.setAttr(_U(x), tr[0]);
0563         obj.setAttr(_U(y), tr[1]);
0564         obj.setAttr(_U(z), tr[2]);
0565         obj.setAttr(_U(unit), "cm");
0566       }
0567       if (lm->IsRotation()) {
0568         TGeoMatrix const & linv = lm->Inverse();
0569         XYZRotation  rot = getXYZangles(linv.GetRotationMatrix());
0570         if ((rot.X() != 0.0) || (rot.Y() != 0.0) || (rot.Z() != 0.0)) {
0571           first_solid.append(obj = xml_elt_t(geo.doc, _U(firstrotation)));
0572           obj.setAttr(_U(name), name+"_"+lnam+"_rot");
0573           obj.setAttr(_U(x), rot.X());
0574           obj.setAttr(_U(y), rot.Y());
0575           obj.setAttr(_U(z), rot.Z());
0576           obj.setAttr(_U(unit), "rad");
0577         }
0578       }
0579       tr = rm->GetTranslation();
0580       solid.append(second_solid = xml_elt_t(geo.doc, _U(second)));
0581       second_solid.setAttr(_U(ref), rnam);
0582       if ((tr[0] != 0.0) || (tr[1] != 0.0) || (tr[2] != 0.0)) {
0583         xml_ref_t pos = handlePosition(rnam+"_pos", rm);
0584         solid.setRef(_U(positionref), pos.name());
0585       }
0586       if (rm->IsRotation()) {
0587         TGeoMatrix const & rinv = rm->Inverse();
0588         XYZRotation rot = getXYZangles(rinv.GetRotationMatrix());
0589         if ((rot.X() != 0.0) || (rot.Y() != 0.0) || (rot.Z() != 0.0)) {
0590           xml_ref_t xml_rot = handleRotation(rnam+"_rot", &rinv);
0591           solid.setRef(_U(rotationref), xml_rot.name());
0592         }
0593       }
0594     }
0595     if (!solid) {
0596       std::string err = "Failed to handle unknown solid shape:" + name + " of type " + std::string(shape->IsA()->GetName());
0597       throw std::runtime_error(err);
0598     }
0599     return data().xmlSolids[shape] = solid;
0600   }
0601 }
0602 
0603 /// Convert the Position into the corresponding Xml object(s).
0604 xml_h LCDDConverter::handlePosition(const std::string& name, const TGeoMatrix* trafo) const {
0605   GeometryInfo& geo = data();
0606   xml_h pos = geo.xmlPositions[trafo];
0607   if (!pos) {
0608     const double* tr = trafo->GetTranslation();
0609     if (tr[0] != 0.0 || tr[1] != 0.0 || tr[2] != 0.0) {
0610       std::string gen_name = genName(name,trafo);
0611       geo.checkPosition(gen_name, trafo);
0612       geo.doc_define.append(pos = xml_elt_t(geo.doc, _U(position)));
0613       pos.setAttr(_U(name), gen_name);
0614       pos.setAttr(_U(x), tr[0]);
0615       pos.setAttr(_U(y), tr[1]);
0616       pos.setAttr(_U(z), tr[2]);
0617       pos.setAttr(_U(unit), "cm");
0618     }
0619     else if (geo.identity_pos) {
0620       pos = geo.identity_pos;
0621     }
0622     else {
0623       geo.doc_define.append(geo.identity_pos = xml_elt_t(geo.doc, _U(position)));
0624       geo.identity_pos.setAttr(_U(name), "identity_pos");
0625       geo.identity_pos.setAttr(_U(x), 0);
0626       geo.identity_pos.setAttr(_U(y), 0);
0627       geo.identity_pos.setAttr(_U(z), 0);
0628       geo.identity_pos.setAttr(_U(unit), "cm");
0629       pos = geo.identity_pos;
0630       geo.checkPosition("identity_pos", 0);
0631     }
0632     geo.xmlPositions[trafo] = pos;
0633   }
0634   return pos;
0635 }
0636 
0637 /// Convert the Rotation into the corresponding Xml object(s).
0638 xml_h LCDDConverter::handleRotation(const std::string& name, const TGeoMatrix* trafo) const {
0639   GeometryInfo& geo = data();
0640   xml_h rot = geo.xmlRotations[trafo];
0641   if (!rot) {
0642     XYZRotation r = getXYZangles(trafo->GetRotationMatrix());
0643     if (!(r.X() == 0.0 && r.Y() == 0.0 && r.Z() == 0.0)) {
0644       std::string gen_name = genName(name,trafo);
0645       geo.checkRotation(gen_name, trafo);
0646       geo.doc_define.append(rot = xml_elt_t(geo.doc, _U(rotation)));
0647       rot.setAttr(_U(name), gen_name);
0648       rot.setAttr(_U(x), r.X());
0649       rot.setAttr(_U(y), r.Y());
0650       rot.setAttr(_U(z), r.Z());
0651       rot.setAttr(_U(unit), "rad");
0652     }
0653     else if (geo.identity_rot) {
0654       rot = geo.identity_rot;
0655     }
0656     else {
0657       geo.doc_define.append(geo.identity_rot = xml_elt_t(geo.doc, _U(rotation)));
0658       geo.identity_rot.setAttr(_U(name), "identity_rot");
0659       geo.identity_rot.setAttr(_U(x), 0);
0660       geo.identity_rot.setAttr(_U(y), 0);
0661       geo.identity_rot.setAttr(_U(z), 0);
0662       geo.identity_rot.setAttr(_U(unit), "rad");
0663       rot = geo.identity_rot;
0664       geo.checkRotation("identity_rot", 0);
0665     }
0666     geo.xmlRotations[trafo] = rot;
0667   }
0668   return rot;
0669 }
0670 
0671 /// Dump logical volume in GDML format to output stream
0672 xml_h LCDDConverter::handleVolume(const std::string& /* name */, Volume volume) const {
0673   GeometryInfo& geo = data();
0674   xml_h vol = geo.xmlVolumes[volume];
0675   if (!vol) {
0676     const TGeoVolume* v = volume;
0677     Volume      _v(v);
0678     std::string n      = genName(v->GetName(),v);
0679     TGeoMedium* medium = v->GetMedium();
0680     TGeoShape*  sh     = v->GetShape();
0681     xml_ref_t   sol    = handleSolid(sh->GetName(), sh);
0682 
0683     geo.checkVolume(n, volume);
0684     if (v->IsAssembly()) {
0685       vol = xml_elt_t(geo.doc, _U(assembly));
0686       vol.setAttr(_U(name), n);
0687     }
0688     else {
0689       if (!sol)
0690         throw std::runtime_error("G4Converter: No Detector Solid present for volume:" + n);
0691       else if (!m)
0692         throw std::runtime_error("G4Converter: No Detector material present for volume:" + n);
0693 
0694       vol = xml_elt_t(geo.doc, _U(volume));
0695       vol.setAttr(_U(name), n);
0696       if (m) {
0697         std::string mat_name = medium->GetName();
0698         xml_ref_t   med      = handleMaterial(mat_name, Material(medium));
0699         vol.setRef(_U(materialref), med.name());
0700       }
0701       vol.setRef(_U(solidref), sol.name());
0702     }
0703     geo.doc_structure.append(vol);
0704     geo.xmlVolumes[v] = vol;
0705     const TObjArray* dau = const_cast<TGeoVolume*>(v)->GetNodes();
0706     if (dau && dau->GetEntries() > 0) {
0707       for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
0708         TGeoNode* node = reinterpret_cast<TGeoNode*>(dau->At(i));
0709         handlePlacement(node->GetName(), node);
0710       }
0711     }
0712     if (geo.doc_header && is_volume(volume)) {
0713       Region   reg = _v.region();
0714       LimitSet lim = _v.limitSet();
0715       VisAttr  vis = _v.visAttributes();
0716       SensitiveDetector det = _v.sensitiveDetector();
0717       if (det.isValid()) {
0718         xml_ref_t xml_data = handleSensitive(det.name(), det);
0719         vol.setRef(_U(sdref), xml_data.name());
0720       }
0721       if (reg.isValid()) {
0722         xml_ref_t xml_data = handleRegion(reg.name(), reg);
0723         vol.setRef(_U(regionref), xml_data.name());
0724       }
0725       if (lim.isValid()) {
0726         xml_ref_t xml_data = handleLimitSet(lim.name(), lim);
0727         vol.setRef(_U(limitsetref), xml_data.name());
0728       }
0729       if (vis.isValid()) {
0730         xml_ref_t xml_data = handleVis(vis.name(), vis);
0731         vol.setRef(_U(visref), xml_data.name());
0732       }
0733     }
0734   }
0735   return vol;
0736 }
0737 
0738 /// Dump logical volume in GDML format to output stream
0739 xml_h LCDDConverter::handleVolumeVis(const std::string& /* name */, const TGeoVolume* volume) const {
0740   GeometryInfo& geo = data();
0741   xml_h         vol = geo.xmlVolumes[volume];
0742   if (!vol) {
0743     const TGeoVolume* v = volume;
0744     Volume _v(volume);
0745     if (is_volume(volume)) {
0746       VisAttr vis = _v.visAttributes();
0747       if (vis.isValid()) {
0748         geo.doc_structure.append(vol = xml_elt_t(geo.doc, _U(volume)));
0749         vol.setAttr(_U(name), v->GetName());
0750         xml_ref_t xml_data = handleVis(vis.name(), vis);
0751         vol.setRef(_U(visref), xml_data.name());
0752         geo.xmlVolumes[v] = vol;
0753       }
0754     }
0755   }
0756   return vol;
0757 }
0758 
0759 /// Dump logical volume in GDML format to output stream
0760 void LCDDConverter::collectVolume(const std::string& /* name */, const TGeoVolume* volume) const {
0761   Volume v(volume);
0762   if ( is_volume(volume) )     {
0763     GeometryInfo&     geo = data();
0764     Region            reg = v.region();
0765     LimitSet          lim = v.limitSet();
0766     SensitiveDetector det = v.sensitiveDetector();
0767     if (lim.isValid())
0768       geo.limits.insert(lim);
0769     if (reg.isValid())
0770       geo.regions.insert(reg);
0771     if (det.isValid())
0772       geo.sensitives.insert(det);
0773   }
0774   else {
0775     printout(WARNING,"LCDDConverter","++ CollectVolume: Skip volume: %s",volume->GetName());
0776   }
0777 }
0778 
0779 void LCDDConverter::checkVolumes(const std::string& /* name */, Volume v) const {
0780   std::string n = v.name()+_toString(v.ptr(),"_%p");
0781   NameSet::const_iterator i = m_checkNames.find(n);
0782   if (i != m_checkNames.end()) {
0783     std::stringstream str;
0784     str << "++ CheckVolumes: Volume " << n << " ";
0785     if (is_volume(v.ptr()))     {
0786       SensitiveDetector sd = v.sensitiveDetector();
0787       VisAttr vis = v.visAttributes();
0788       if (sd.isValid()) {
0789         str << "of " << sd.name() << " ";
0790       }
0791       else if (vis.isValid()) {
0792         str << "with VisAttrs " << vis.name() << " ";
0793       }
0794     }
0795     str << "has duplicate entries." << std::endl;
0796     printout(ERROR,"LCDDConverter",str.str().c_str());
0797     return;
0798   }
0799   m_checkNames.insert(n);
0800 }
0801 
0802 /// Dump volume placement in GDML format to output stream
0803 xml_h LCDDConverter::handlePlacement(const std::string& name,PlacedVolume node) const {
0804   GeometryInfo& geo = data();
0805   xml_h place = geo.xmlPlacements[node];
0806   if (!place) {
0807     TGeoMatrix* matrix = node->GetMatrix();
0808     TGeoVolume* volume = node->GetVolume();
0809     xml_ref_t   vol    = xml_h(geo.xmlVolumes[volume]);
0810     xml_h mot = geo.xmlVolumes[node->GetMotherVolume()];
0811 
0812     place = xml_elt_t(geo.doc, _U(physvol));
0813     if (mot) {   // Beware of top level volume!
0814       mot.append(place);
0815     }
0816     place.setRef(_U(volumeref), vol.name());
0817     if (m) {
0818       xml_ref_t pos = handlePosition(name+"_pos", matrix);
0819       place.setRef(_U(positionref), pos.name());
0820       if ( matrix->IsRotation() )  {
0821         xml_ref_t rot = handleRotation(name+"_rot", matrix);
0822         place.setRef(_U(rotationref), rot.name());
0823       }
0824     }
0825     if (geo.doc_root.tag() != "gdml") {
0826       if (is_placement(node)) {
0827         const PlacedVolume::VolIDs& ids = node.volIDs();
0828         for (PlacedVolume::VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
0829           xml_h pvid = xml_elt_t(geo.doc, _U(physvolid));
0830           pvid.setAttr(_U(field_name), (*i).first);
0831           pvid.setAttr(_U(value), (*i).second);
0832           place.append(pvid);
0833         }
0834       }
0835     }
0836     geo.xmlPlacements[node] = place;
0837   }
0838   else {
0839     std::cout << "Attempt to DOUBLE-place physical volume:" << name << " No:" << node->GetNumber() << std::endl;
0840   }
0841   return place;
0842 }
0843 
0844 /// Convert the geometry type region into the corresponding Detector object(s).
0845 xml_h LCDDConverter::handleRegion(const std::string& /* name */, Region region) const {
0846   GeometryInfo& geo = data();
0847   xml_h reg = geo.xmlRegions[region];
0848   if (!reg) {
0849     geo.doc_regions.append(reg = xml_elt_t(geo.doc, _U(region)));
0850     reg.setAttr(_U(name), region.name());
0851     reg.setAttr(_U(cut), region.cut());
0852     reg.setAttr(_U(eunit), "GeV");  // TGeo has energy in GeV
0853     reg.setAttr(_U(lunit), "cm");   // TGeo has lengths in cm
0854     reg.setAttr(_U(store_secondaries), region.storeSecondaries());
0855     geo.xmlRegions[region] = reg;
0856   }
0857   return reg;
0858 }
0859 
0860 /// Convert the geometry type LimitSet into the corresponding Detector object(s)
0861 xml_h LCDDConverter::handleLimitSet(const std::string& /* name */, LimitSet lim) const {
0862   GeometryInfo& geo = data();
0863   xml_h xml = geo.xmlLimits[lim];
0864   if (!xml) {
0865     geo.doc_limits.append(xml = xml_elt_t(geo.doc, _U(limitset)));
0866     xml.setAttr(_U(name), lim.name());
0867     const std::set<Limit>& obj = lim.limits();
0868     for (std::set<Limit>::const_iterator i = obj.begin(); i != obj.end(); ++i) {
0869       xml_h x = xml_elt_t(geo.doc, _U(limit));
0870       const Limit& l = *i;
0871       xml.append(x);
0872       x.setAttr(_U(name), l.name);
0873       x.setAttr(_U(unit), l.unit);
0874       x.setAttr(_U(value), l.value);
0875       x.setAttr(_U(particles), l.particles);
0876     }
0877     geo.xmlLimits[lim] = xml;
0878   }
0879   return xml;
0880 }
0881 
0882 /// Convert the segmentation of a SensitiveDetector into the corresponding Detector object
0883 xml_h LCDDConverter::handleSegmentation(Segmentation seg) const {
0884   xml_h xml;
0885   if (seg.isValid()) {
0886     typedef DDSegmentation::Parameters _P;
0887     std::string typ = seg.type();
0888     _P p = seg.parameters();
0889     xml = xml_elt_t(data().doc, Unicode(typ));
0890     for (_P::const_iterator i = p.begin(); i != p.end(); ++i) {
0891       const _P::value_type& v = *i;
0892       if (v->name() == "lunit") {
0893         std::string val = v->value() == _toDouble("mm") ? "mm" : v->value() == _toDouble("cm") ? "cm" :
0894           v->value() == _toDouble("m") ? "m" : v->value() == _toDouble("micron") ? "micron" :
0895           v->value() == _toDouble("nanometer") ? "namometer" : "??";
0896         xml.setAttr(Unicode(v->name()), Unicode(val));
0897         continue;
0898       }
0899       // translate from TGeo units to Geant4 units if necessary
0900       if (v->unitType() == DDSegmentation::SegmentationParameter::LengthUnit) {
0901         double value = _toDouble(v->value()) / dd4hep::mm;
0902         xml.setAttr(Unicode(v->name()), value);
0903       } else if (v->unitType() == DDSegmentation::SegmentationParameter::AngleUnit) {
0904         double value = _toDouble(v->value()) * DEGREE_2_RAD;
0905         xml.setAttr(Unicode(v->name()), value);
0906       } else {
0907         xml.setAttr(Unicode(v->name()), v->value());
0908       }
0909     }
0910   }
0911   return xml;
0912 }
0913 
0914 /// Convert the geometry type SensitiveDetector into the corresponding Detector object(s).
0915 xml_h LCDDConverter::handleSensitive(const std::string& /* name */, SensitiveDetector sd) const {
0916   GeometryInfo& geo = data();
0917   xml_h sensdet = geo.xmlSensDets[sd];
0918   if (!sensdet) {
0919     geo.doc_detectors.append(sensdet = xml_elt_t(geo.doc, Unicode(sd.type())));
0920     sensdet.setAttr(_U(name), sd.name());
0921     sensdet.setAttr(_U(ecut), sd.energyCutoff());
0922     sensdet.setAttr(_U(eunit), "MeV");
0923     sensdet.setAttr(_U(verbose), int(sd.verbose() ? 1 : 0));
0924     sensdet.setAttr(_U(hits_collection), sd.hitsCollection());
0925     if (sd.combineHits())
0926       sensdet.setAttr(_U(combine_hits), sd.combineHits());
0927     Readout ro = sd.readout();
0928     if (ro.isValid()) {
0929       xml_ref_t ref = handleIdSpec(ro.idSpec().name(), ro.idSpec());
0930       sensdet.setRef(_U(idspecref), ref.name());
0931       xml_h seg = handleSegmentation(ro.segmentation());
0932       if (seg)
0933         sensdet.append(seg);
0934     }
0935     geo.xmlSensDets[sd] = sensdet;
0936   }
0937   return sensdet;
0938 }
0939 
0940 /// Convert the geometry id dictionary entry to the corresponding Xml object(s).
0941 xml_h LCDDConverter::handleIdSpec(const std::string& name, IDDescriptor id_spec) const {
0942   GeometryInfo& geo = data();
0943   xml_h id = geo.xmlIdSpecs[id_spec];
0944   if (!id) {
0945     int length = 0, start = 0;
0946     IDDescriptor desc = id_spec;
0947     geo.doc_idDict.append(id = xml_elt_t(geo.doc, _U(idspec)));
0948     id.setAttr(_U(name), name);
0949     const IDDescriptor::FieldMap& fm = desc.fields();
0950     for (const auto& i : fm )  {
0951       xml_h idfield = xml_elt_t(geo.doc, _U(idfield));
0952 #if 0
0953       const BitFieldElement* f = i.second;
0954       start = f.first;
0955       length = f.second<0 ? -f.second : f.second;
0956       idfield.setAttr(_U(signed),f.second<0 ? true : false);
0957       idfield.setAttr(_U(label),(*i).first);
0958       idfield.setAttr(_U(length),length);
0959       idfield.setAttr(_U(start),start);
0960 #else
0961       const BitFieldElement* f = i.second;
0962       idfield.setAttr(_U(signed),f->isSigned() ? true : false);
0963       idfield.setAttr(_U(label), f->name());
0964       idfield.setAttr(_U(length), (int) f->width());
0965       idfield.setAttr(_U(start), (int) f->offset());
0966 #endif
0967       id.append(idfield);
0968     }
0969     id.setAttr(_U(length), length + start);
0970     geo.xmlIdSpecs[id_spec] = id;
0971   }
0972   return id;
0973 }
0974 
0975 /// Convert the geometry visualisation attributes to the corresponding Detector object(s).
0976 xml_h LCDDConverter::handleVis(const std::string& /* name */, VisAttr attr) const {
0977   GeometryInfo& geo = data();
0978   xml_h vis = geo.xmlVis[attr];
0979   if (!vis) {
0980     float red = 0, green = 0, blue = 0;
0981     int style = attr.lineStyle();
0982     int draw = attr.drawingStyle();
0983 
0984     geo.doc_display.append(vis = xml_elt_t(geo.doc, _U(vis)));
0985     vis.setAttr(_U(name), attr.name());
0986     vis.setAttr(_U(visible), attr.visible());
0987     vis.setAttr(_U(show_daughters), attr.showDaughters());
0988     if (style == VisAttr::SOLID)
0989       vis.setAttr(_U(line_style), "unbroken");
0990     else if (style == VisAttr::DASHED)
0991       vis.setAttr(_U(line_style), "broken");
0992     if (draw == VisAttr::SOLID)
0993       vis.setAttr(_U(drawing_style), "solid");
0994     else if (draw == VisAttr::WIREFRAME)
0995       vis.setAttr(_U(drawing_style), "wireframe");
0996 
0997     xml_h col = xml_elt_t(geo.doc, _U(color));
0998     attr.rgb(red, green, blue);
0999     col.setAttr(_U(alpha), attr.alpha());
1000     col.setAttr(_U(R), red);
1001     col.setAttr(_U(B), blue);
1002     col.setAttr(_U(G), green);
1003     vis.append(col);
1004     geo.xmlVis[attr] = vis;
1005   }
1006   return vis;
1007 }
1008 
1009 /// Convert the electric or magnetic fields into the corresponding Xml object(s).
1010 xml_h LCDDConverter::handleField(const std::string& /* name */, OverlayedField f) const {
1011   GeometryInfo& geo = data();
1012   xml_h field = geo.xmlFields[f];
1013   if (!field) {
1014     Handle<NamedObject> fld(f);
1015     std::string type = f->GetTitle();
1016     field = xml_elt_t(geo.doc, Unicode(type));
1017     field.setAttr(_U(name), f->GetName());
1018     fld = PluginService::Create<NamedObject*>(type + "_Convert2Detector", &m_detDesc, &field, &fld);
1019     printout(ALWAYS,"LCDDConverter","++ %s electromagnetic field:%s of type %s",
1020              (fld.isValid() ? "Converted" : "FAILED    to convert "), f->GetName(), type.c_str());
1021     if (!fld.isValid()) {
1022       PluginDebug dbg;
1023       PluginService::Create<NamedObject*>(type + "_Convert2Detector", &m_detDesc, &field, &fld);
1024       except("LCDDConverter", "Failed to locate plugin to convert electromagnetic field:"
1025              + std::string(f->GetName()) + " of type " + type + ". "
1026              + dbg.missingFactory(type));
1027     }
1028     geo.doc_fields.append(field);
1029   }
1030   return field;
1031 }
1032 
1033 /// Handle the geant 4 specific properties
1034 void LCDDConverter::handleProperties(Detector::Properties& prp) const {
1035   std::map<std::string, std::string> processors;
1036   static int s_idd = 9999999;
1037   std::string id;
1038   for (Detector::Properties::const_iterator i = prp.begin(); i != prp.end(); ++i) {
1039     const std::string& nam = (*i).first;
1040     const Detector::PropertyValues& vals = (*i).second;
1041     if (nam.substr(0, 6) == "geant4") {
1042       Detector::PropertyValues::const_iterator id_it = vals.find("id");
1043       if (id_it != vals.end()) {
1044         id = (*id_it).second;
1045       }
1046       else {
1047         char text[32];
1048         ::snprintf(text, sizeof(text), "%d", ++s_idd);
1049         id = text;
1050       }
1051       processors.insert(make_pair(id, nam));
1052     }
1053   }
1054   for (std::map<std::string, std::string>::const_iterator i = processors.begin(); i != processors.end(); ++i) {
1055     const GeoHandler* ptr = this;
1056     std::string nam = (*i).second;
1057     const Detector::PropertyValues& vals = prp[nam];
1058     auto iter = vals.find("type");
1059     if ( iter != vals.end() )  {
1060       std::string type = iter->second;
1061       std::string tag = type + "_Geant4_action";
1062       long result = PluginService::Create<long>(tag, &m_detDesc, ptr, &vals);
1063       if (0 == result) {
1064         PluginDebug dbg;
1065         result = PluginService::Create<long>(tag, &m_detDesc, ptr, &vals);
1066         if (0 == result) {
1067           except("LCDDConverter", "Failed to locate plugin to interprete files of type"
1068                  " \"" + tag + "\" - no factory:" + type + ". " +
1069                  dbg.missingFactory(tag));
1070         }
1071       }
1072       result = *(long*) result;
1073       if (result != 1) {
1074         except("LCDDConverter", "Failed to invoke the plugin " + tag + " of type " + type);
1075       }
1076       printout(INFO,"","+++ Executed Successfully Detector setup module %s.", type.c_str());
1077       continue;
1078     }
1079     printout(INFO,"","+++ FAILED to execute Detector setup module %s.", nam.c_str());    
1080   }
1081 }
1082 
1083 /// Add header information in Detector format
1084 void LCDDConverter::handleHeader() const {
1085   GeometryInfo& geo = data();
1086   Header hdr = m_detDesc.header();
1087   if ( hdr.isValid() )  {
1088     xml_h obj;
1089     geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(detector)));
1090     obj.setAttr(_U(name), hdr.name());
1091     geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(generator)));
1092     obj.setAttr(_U(name), "LCDDConverter");
1093     obj.setAttr(_U(version), hdr.version());
1094     obj.setAttr(_U(file), hdr.url());
1095     obj.setAttr(_U(checksum), Unicode(m_detDesc.constantAsString("compact_checksum")));
1096     geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(author)));
1097     obj.setAttr(_U(name), hdr.author());
1098     geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(comment)));
1099     obj.setText(hdr.comment());
1100     return;
1101   }
1102   printout(WARNING,"LCDDConverter","+++ No Detector header information availible from the geometry description.");
1103 }
1104 
1105 template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) {
1106   for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
1107     std::string n = (*i)->GetName();
1108     (o->*pmf)(n, *i);
1109   }
1110 }
1111 
1112 template <typename O, typename C, typename F> void handleMap(const O* o, const C& c, F pmf) {
1113   for (typename C::const_iterator i = c.begin(); i != c.end(); ++i)
1114     (o->*pmf)((*i).first, (*i).second);
1115 }
1116 
1117 template <typename O, typename C, typename F> void handleRMap(const O* o, const C& c, F pmf) {
1118   for (typename C::const_reverse_iterator i = c.rbegin(); i != c.rend(); ++i)
1119     handle(o, (*i).second, pmf);
1120 }
1121 
1122 /// Create geometry conversion
1123 xml_doc_t LCDDConverter::createGDML(DetElement top) {
1124   Detector& description = m_detDesc;
1125   if (!top.isValid()) {
1126     throw std::runtime_error("Attempt to call createGDML with an invalid geometry!");
1127   }
1128   GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
1129   m_data->clear();
1130   collect(top, geo);
1131 
1132   printout(ALWAYS,"LCDDConverter","++ ==> Converting in memory detector description to GDML format...");
1133   xml::DocumentHandler docH;
1134   geo.doc = docH.create("gdml", docH.defaultComment());
1135   geo.doc_root = geo.doc.root();
1136   geo.doc_root.setAttr(Unicode("xmlns:xs"), "http://www.w3.org/2001/XMLSchema-instance");
1137   geo.doc_root.setAttr(Unicode("xs:noNamespaceSchemaLocation"),
1138                        "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd");
1139   // geo.doc = docH.create("gdml_simple_extension",comment);
1140   // geo.doc_root.setAttr(Unicode("xmlns:gdml_simple_extension"),"http://www.example.org");
1141   // geo.doc_root.setAttr(Unicode("xs:noNamespaceSchemaLocation"),
1142   //     "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd");
1143   Volume world_vol = description.worldVolume();
1144   geo.doc_root.append(geo.doc_define = xml_elt_t(geo.doc, _U(define)));
1145   geo.doc_root.append(geo.doc_materials = xml_elt_t(geo.doc, _U(materials)));
1146   geo.doc_root.append(geo.doc_solids = xml_elt_t(geo.doc, _U(solids)));
1147   geo.doc_root.append(geo.doc_structure = xml_elt_t(geo.doc, _U(structure)));
1148   geo.doc_root.append(geo.doc_setup = xml_elt_t(geo.doc, _U(setup)));
1149   geo.doc_setup.setRef(_U(world), genName(world_vol.name(),world_vol.ptr()));
1150   geo.doc_setup.setAttr(_U(name), Unicode("default"));
1151   geo.doc_setup.setAttr(_U(version), Unicode("1.0"));
1152 
1153   // Ensure that all required materials are present in the Detector material table
1154 #if 0
1155   const Detector::HandleMap& mat = description.materials();
1156   for(Detector::HandleMap::const_iterator i=mat.begin(); i!=mat.end(); ++i)
1157     geo.materials.insert(dynamic_cast<TGeoMedium*>((*i).second.ptr()));
1158 #endif
1159 
1160   // Start creating the objects for materials, solids and log volumes.
1161   handle(this, geo.materials, &LCDDConverter::handleMaterial);
1162   printout(ALWAYS,"LCDDConverter","++ Handled %ld materials.",geo.materials.size());
1163 
1164   handle(this, geo.volumes, &LCDDConverter::collectVolume);
1165   printout(ALWAYS,"LCDDConverter","++ Collected %ld volumes.",geo.volumes.size());
1166 
1167   handle(this, geo.solids, &LCDDConverter::handleSolid);
1168   printout(ALWAYS,"LCDDConverter","++ Handled %ld solids.",geo.solids.size());
1169 
1170   handle(this, geo.volumes, &LCDDConverter::handleVolume);
1171   printout(ALWAYS,"LCDDConverter","++ Handled %ld volumes.",geo.volumes.size());
1172 
1173   m_checkNames.clear();
1174   handle(this, geo.volumes, &LCDDConverter::checkVolumes);
1175   return geo.doc;
1176 }
1177 
1178 /// Create geometry conversion
1179 xml_doc_t LCDDConverter::createVis(DetElement top) {
1180   if (!top.isValid()) {
1181     throw std::runtime_error("Attempt to call createDetector with an invalid geometry!");
1182   }
1183 
1184   GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
1185   m_data->clear();
1186   collect(top, geo);
1187   printout(ALWAYS,"LCDDConverter","++ ==> Dump visualisation attributes "
1188            "from in memory detector description...");
1189   xml::DocumentHandler docH;
1190   xml_elt_t elt(0);
1191   geo.doc = docH.create("visualization", docH.defaultComment());
1192   geo.doc_root = geo.doc.root();
1193   geo.doc_root.append(geo.doc_display = xml_elt_t(geo.doc, _U(display)));
1194   geo.doc_root.append(geo.doc_structure = xml_elt_t(geo.doc, _U(structure)));
1195 
1196   handle(this, geo.volumes, &LCDDConverter::collectVolume);
1197   handle(this, geo.volumes, &LCDDConverter::handleVolumeVis);
1198   printout(ALWAYS,"LCDDConverter","++ Handled %ld volumes.",geo.volumes.size());
1199   return geo.doc;
1200 }
1201 
1202 /// Create geometry conversion
1203 xml_doc_t LCDDConverter::createDetector(DetElement top) {
1204   Detector& description = m_detDesc;
1205   if (!top.isValid()) {
1206     throw std::runtime_error("Attempt to call createDetector with an invalid geometry!");
1207   }
1208 
1209   GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
1210   m_data->clear();
1211   collect(top, geo);
1212   xml::DocumentHandler docH;
1213   xml_elt_t elt(0);
1214   Volume world_vol = description.worldVolume();
1215   geo.doc = docH.create("description", docH.defaultComment());
1216   geo.doc_root = geo.doc.root();
1217   geo.doc_root.setAttr(Unicode("xmlns:description"), "http://www.lcsim.org/schemas/description/1.0");
1218   geo.doc_root.setAttr(Unicode("xmlns:xs"), "http://www.w3.org/2001/XMLSchema-instance");
1219   geo.doc_root.setAttr(Unicode("xs:noNamespaceSchemaLocation"), 
1220                        "http://www.lcsim.org/schemas/description/1.0/description.xsd");
1221 
1222   geo.doc_root.append(geo.doc_header = xml_elt_t(geo.doc, _U(header)));
1223   geo.doc_root.append(geo.doc_idDict = xml_elt_t(geo.doc, _U(iddict)));
1224   geo.doc_root.append(geo.doc_detectors = xml_elt_t(geo.doc, _U(sensitive_detectors)));
1225   geo.doc_root.append(geo.doc_limits = xml_elt_t(geo.doc, _U(limits)));
1226   geo.doc_root.append(geo.doc_regions = xml_elt_t(geo.doc, _U(regions)));
1227   geo.doc_root.append(geo.doc_display = xml_elt_t(geo.doc, _U(display)));
1228   geo.doc_root.append(geo.doc_gdml = xml_elt_t(geo.doc, _U(gdml)));
1229   geo.doc_root.append(geo.doc_fields = xml_elt_t(geo.doc, _U(fields)));
1230 
1231   geo.doc_gdml.append(geo.doc_define = xml_elt_t(geo.doc, _U(define)));
1232   geo.doc_gdml.append(geo.doc_materials = xml_elt_t(geo.doc, _U(materials)));
1233   geo.doc_gdml.append(geo.doc_solids = xml_elt_t(geo.doc, _U(solids)));
1234   geo.doc_gdml.append(geo.doc_structure = xml_elt_t(geo.doc, _U(structure)));
1235   geo.doc_gdml.append(geo.doc_setup = xml_elt_t(geo.doc, _U(setup)));
1236   geo.doc_setup.setRef(_U(world), genName(world_vol.name(),world_vol.ptr()));
1237   geo.doc_setup.setAttr(_U(name), Unicode("default"));
1238   geo.doc_setup.setAttr(_U(version), Unicode("1.0"));
1239 
1240   // Ensure that all required materials are present in the Detector material table
1241   const Detector::HandleMap& fld = description.fields();
1242   for (Detector::HandleMap::const_iterator i = fld.begin(); i != fld.end(); ++i)
1243     geo.fields.insert((*i).second);
1244 
1245   printout(ALWAYS,"LCDDConverter","++ ==> Converting in memory detector description to Detector format...");
1246   handleHeader();
1247   // Start creating the objects for materials, solids and log volumes.
1248   handle(this, geo.materials, &LCDDConverter::handleMaterial);
1249   printout(ALWAYS,"LCDDConverter","++ Handled %ld materials.",geo.materials.size());
1250 
1251   handle(this, geo.volumes, &LCDDConverter::collectVolume);
1252   printout(ALWAYS,"LCDDConverter","++ Collected %ld volumes.",geo.volumes.size());
1253 
1254   handle(this, geo.solids, &LCDDConverter::handleSolid);
1255   printout(ALWAYS,"LCDDConverter","++ Handled %ld solids.",geo.solids.size());
1256 
1257   handle(this, geo.vis, &LCDDConverter::handleVis);
1258   printout(ALWAYS,"LCDDConverter","++ Handled %ld visualization attributes.",geo.vis.size());
1259 
1260   handle(this, geo.sensitives, &LCDDConverter::handleSensitive);
1261   printout(ALWAYS,"LCDDConverter","++ Handled %ld sensitive detectors.",geo.sensitives.size());
1262 
1263   handle(this, geo.limits, &LCDDConverter::handleLimitSet);
1264   printout(ALWAYS,"LCDDConverter","++ Handled %ld limit sets.",geo.limits.size());
1265 
1266   handle(this, geo.regions, &LCDDConverter::handleRegion);
1267   printout(ALWAYS,"LCDDConverter","++ Handled %ld regions.",geo.regions.size());
1268 
1269   handle(this, geo.volumes, &LCDDConverter::handleVolume);
1270   printout(ALWAYS,"LCDDConverter","++ Handled %ld volumes.",geo.volumes.size());
1271 
1272   handle(this, geo.fields, &LCDDConverter::handleField);
1273   printout(ALWAYS,"LCDDConverter","++ Handled %ld fields.",geo.fields.size());
1274 
1275   m_checkNames.clear();
1276   handle(this, geo.volumes, &LCDDConverter::checkVolumes);
1277 #if 0
1278   //==================== Fields
1279   handleProperties(m_detDesc.properties());
1280 #endif
1281   return geo.doc;
1282 }
1283 
1284 /// Helper constructor
1285 LCDDConverter::GeometryInfo::GeometryInfo()
1286   : doc(0), doc_root(0), doc_header(0), doc_idDict(0), doc_detectors(0), doc_limits(0), 
1287     doc_regions(0), doc_display(0), doc_gdml(0), doc_fields(0), doc_define(0),
1288     doc_materials(0), doc_solids(0), doc_structure(0), doc_setup(0)
1289 {
1290 }
1291 
1292 static long dump_output(xml_doc_t doc, int argc, char** argv) {
1293   xml::DocumentHandler docH;
1294   return docH.output(doc, argc > 0 ? argv[0] : "");
1295 }
1296 
1297 long create_gdml_from_dd4hep(Detector& description, int argc, char** argv) {
1298   LCDDConverter wr(description);
1299   return dump_output(wr.createGDML(description.world()), argc, argv);
1300 }
1301 
1302 static long create_description(Detector& description, int argc, char** argv) {
1303   LCDDConverter wr(description);
1304   return dump_output(wr.createDetector(description.world()), argc, argv);
1305 }
1306 
1307 static long create_vis(Detector& description, int argc, char** argv) {
1308   LCDDConverter wr(description);
1309   return dump_output(wr.createVis(description.world()), argc, argv);
1310 }
1311 
1312 static long create_visASCII(Detector& description, int /* argc */, char** argv) {
1313   LCDDConverter wr(description);
1314   /* xml_doc_t doc = */ wr.createVis(description.world());
1315   LCDDConverter::GeometryInfo& geo = wr.data();
1316   std::map<std::string, xml_comp_t> vis_map;
1317   for (xml_coll_t c(geo.doc_display, _U(vis)); c; ++c)
1318     vis_map.insert(make_pair(xml_comp_t(c).nameStr(), xml_comp_t(c)));
1319 
1320   const char* sep = ";";
1321   std::ofstream os(argv[0]);
1322   for (xml_coll_t c(geo.doc_structure, _U(volume)); c; ++c) {
1323     xml_comp_t vol = c;
1324     xml_comp_t ref = c.child(_U(visref));
1325     auto iter = vis_map.find(ref.refStr());
1326     if ( iter != vis_map.end() )  {
1327       xml_comp_t vis = iter->second;
1328       xml_comp_t col = vis.child(_U(color));
1329       os << "vol:" << vol.nameStr() << sep << "vis:" << vis.nameStr() << sep 
1330          << "visible:" << vis.visible() << sep << "r:"
1331          << col.R() << sep << "g:" << col.G() << sep << "b:" << col.B() << sep 
1332          << "alpha:" << col.alpha() << sep << "line_style:"
1333          << vis.attr < std::string > (_U(line_style)) << sep 
1334          << "drawing_style:" << vis.attr < std::string> (_U(drawing_style)) << sep 
1335          << "show_daughters:" << vis.show_daughters() << sep << std::endl;
1336     }
1337   }
1338   os.close();
1339   return 1;
1340 }
1341 
1342 DECLARE_APPLY(DD4hepGeometry2VIS, create_vis)
1343 DECLARE_APPLY(DD4hepGeometry2VISASCII, create_visASCII)
1344 //DECLARE_APPLY(DD4hepGeometry2GDML, create_gdml_from_dd4hep)
1345 DECLARE_APPLY(DD4hepGeometry2Detector, create_description)