Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:13:39

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