Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-18 09:29:55

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 // DDCMS is a detector description convention developed by the CMS experiment.
0015 //
0016 //==========================================================================
0017 
0018 // Framework includes
0019 #include "DD4hep/DetFactoryHelper.h"
0020 #include "DD4hep/DetectorHelper.h"
0021 #include "DD4hep/DD4hepUnits.h"
0022 #include "DD4hep/GeoHandler.h"
0023 #include "DD4hep/Printout.h"
0024 #include "DD4hep/Plugins.h"
0025 #include "DD4hep/detail/SegmentationsInterna.h"
0026 #include "DD4hep/detail/DetectorInterna.h"
0027 #include "DD4hep/detail/ObjectsInterna.h"
0028 
0029 #include "XML/Utilities.h"
0030 #include "DDCMS/DDCMS.h"
0031 
0032 // Root/TGeo include files
0033 #include "TSystem.h"
0034 #include "TGeoManager.h"
0035 #include "TGeoMaterial.h"
0036 
0037 // C/C++ include files
0038 #include <climits>
0039 #include <iostream>
0040 #include <iomanip>
0041 #include <set>
0042 #include <map>
0043 
0044 using namespace std;
0045 using namespace dd4hep;
0046 using namespace dd4hep::cms;
0047 
0048 /// Namespace for the AIDA detector description toolkit
0049 namespace dd4hep {
0050 
0051   namespace {
0052 
0053     static UInt_t unique_mat_id = 0xAFFEFEED;
0054     double convertRadToDeg(double r)   {
0055       return r*360e0/(2e0*M_PI);
0056     }
0057     class disabled_algo;
0058     class include_constants;
0059     class include_load;
0060     class include_unload;
0061     class print_xml_doc;
0062     class constantssection;
0063     class constant;
0064     class resolve   {
0065     public:
0066       std::vector<xml::Document> includes;
0067       std::map<std::string,std::string>  unresolvedConst, allConst, originalConst;
0068     };
0069 
0070     class materialsection;
0071     class elementaryelement;
0072     class elementarymaterial;
0073     class compositematerial;
0074   
0075     class rotationsection;
0076     class rotation;
0077     class transform3d;
0078 
0079     class pospartsection;
0080     class division;
0081     class pospart;
0082 
0083     class logicalpartsection;
0084     class logicalpart;
0085 
0086     class solidsection;
0087     class extrudedpolygon;
0088     class shapeless;
0089     class trapezoid;
0090     class ellipsoid;
0091     class ellipticaltube;
0092     class pseudotrap;
0093     class polyhedra;
0094     class polycone;
0095     class torus;
0096     class trd1;
0097     class trunctubs;
0098     class cuttubs;
0099     class tubs;
0100     class orb;
0101     class box;
0102     class cone;
0103     class sphere;
0104     class unionsolid;
0105     class intersectionsolid;
0106     class subtractionsolid;
0107     
0108     class algorithm;    
0109 
0110     class vissection;
0111     class vis;
0112     class debug;
0113   }
0114 
0115   /// Converter instances implemented in this compilation unit
0116   template <> void Converter<debug>::operator()(xml_h element) const;
0117   template <> void Converter<print_xml_doc>::operator()(xml_h element) const;
0118   template <> void Converter<disabled_algo>::operator()(xml_h element) const;
0119   
0120   /// Converter for <ConstantsSection/> tags
0121   template <> void Converter<constantssection>::operator()(xml_h element) const;
0122   template <> void Converter<constant>::operator()(xml_h element) const;
0123   template <> void Converter<resolve>::operator()(xml_h element) const;
0124 
0125   /// Converter for <VisSection/> tags
0126   template <> void Converter<vissection>::operator()(xml_h element) const;
0127   /// Convert compact visualization attributes
0128   template <> void Converter<vis>::operator()(xml_h element) const;
0129 
0130   /// Converter for <MaterialSection/> tags
0131   template <> void Converter<materialsection>::operator()(xml_h element) const;
0132   template <> void Converter<elementaryelement>::operator()(xml_h element) const;
0133   template <> void Converter<elementarymaterial>::operator()(xml_h element) const;
0134   template <> void Converter<compositematerial>::operator()(xml_h element) const;
0135 
0136   /// Converter for <RotationSection/> tags
0137   template <> void Converter<rotationsection>::operator()(xml_h element) const;
0138   /// Converter for <Rotation/> tags
0139   template <> void Converter<rotation>::operator()(xml_h element) const;
0140   template <> void Converter<transform3d>::operator()(xml_h element) const;
0141 
0142   /// Generic converter for  <LogicalPartSection/> tags
0143   template <> void Converter<logicalpartsection>::operator()(xml_h element) const;
0144   template <> void Converter<logicalpart>::operator()(xml_h element) const;
0145 
0146   /// Converter for <PosPartSection/> tags
0147   template <> void Converter<pospartsection>::operator()(xml_h element) const;
0148   /// Converter for <PosPart/> tags
0149   template <> void Converter<pospart>::operator()(xml_h element) const;
0150   /// Converter for <Division/> tags
0151   template <> void Converter<division>::operator()(xml_h element) const;
0152 
0153   /// Generic converter for solids: <SolidSection/> tags
0154   template <> void Converter<solidsection>::operator()(xml_h element) const;
0155   /// Converter for <UnionSolid/> tags
0156   template <> void Converter<unionsolid>::operator()(xml_h element) const;
0157   /// Converter for <SubtractionSolid/> tags
0158   template <> void Converter<subtractionsolid>::operator()(xml_h element) const;
0159   /// Converter for <IntersectionSolid/> tags
0160   template <> void Converter<intersectionsolid>::operator()(xml_h element) const;
0161   /// Converter for <PseudoTrap/> tags
0162   template <> void Converter<pseudotrap>::operator()(xml_h element) const;
0163   /// Converter for <ExtrudedPolygon/> tags
0164   template <> void Converter<extrudedpolygon>::operator()(xml_h element) const;
0165   /// Converter for <ShapelessSolid/> tags
0166   template <> void Converter<shapeless>::operator()(xml_h element) const;
0167   /// Converter for <Trapezoid/> tags
0168   template <> void Converter<trapezoid>::operator()(xml_h element) const;
0169   /// Converter for <Polyhedra/> tags
0170   template <> void Converter<polyhedra>::operator()(xml_h element) const;
0171   /// Converter for <Polycone/> tags
0172   template <> void Converter<polycone>::operator()(xml_h element) const;
0173   /// Converter for <Ellipsoid/> tags
0174   template <> void Converter<ellipsoid>::operator()(xml_h element) const;
0175   /// Converter for <EllipticalTube/> tags
0176   template <> void Converter<ellipticaltube>::operator()(xml_h element) const;
0177   /// Converter for <Torus/> tags
0178   template <> void Converter<torus>::operator()(xml_h element) const;
0179   /// Converter for <Tubs/> tags
0180   template <> void Converter<tubs>::operator()(xml_h element) const;
0181   /// Converter for <CutTubs/> tags
0182   template <> void Converter<cuttubs>::operator()(xml_h element) const;
0183   /// Converter for <TruncTubs/> tags
0184   template <> void Converter<trunctubs>::operator()(xml_h element) const;
0185   /// Converter for <Sphere/> tags
0186   template <> void Converter<sphere>::operator()(xml_h element) const;
0187   /// Converter for <Trd1/> tags
0188   template <> void Converter<trd1>::operator()(xml_h element) const;
0189   /// Converter for <Cone/> tags
0190   template <> void Converter<cone>::operator()(xml_h element) const;
0191   /// Converter for <Box/> tags
0192   template <> void Converter<box>::operator()(xml_h element) const;
0193   /// Converter for <Orb/> tags
0194   template <> void Converter<orb>::operator()(xml_h element) const;
0195 
0196   /// Converter for <Algorithm/> tags
0197   template <> void Converter<algorithm>::operator()(xml_h element) const;
0198 
0199   /// DD4hep specific: Load include file
0200   template <> void Converter<include_load>::operator()(xml_h element) const;
0201   /// DD4hep specific: Unload include file
0202   template <> void Converter<include_unload>::operator()(xml_h element) const;
0203   /// DD4hep specific: Process constants objects
0204   template <> void Converter<include_constants>::operator()(xml_h element) const;
0205 }
0206 
0207 /// Converter for <ConstantsSection/> tags
0208 template <> void Converter<constantssection>::operator()(xml_h element) const  {
0209   Namespace _ns(_param<ParsingContext>(), element);
0210   xml_coll_t(element, _CMU(Constant)).for_each(Converter<constant>(description,_ns.context,optional));
0211 }
0212 
0213 /// Converter for <VisSection/> tags
0214 template <> void Converter<vissection>::operator()(xml_h element) const  {
0215   Namespace _ns(_param<ParsingContext>(), element);
0216   xml_coll_t(element, _CMU(vis)).for_each(Converter<vis>(description,_ns.context,optional));
0217 }
0218 
0219 /// Converter for <MaterialSection/> tags
0220 template <> void Converter<materialsection>::operator()(xml_h element) const   {
0221   Namespace _ns(_param<ParsingContext>(), element);
0222   xml_coll_t(element, _CMU(ElementaryMaterial)).for_each(Converter<elementaryelement>(description,_ns.context,optional));
0223   xml_coll_t(element, _CMU(ElementaryMaterial)).for_each(Converter<elementarymaterial>(description,_ns.context,optional));
0224   xml_coll_t(element, _CMU(CompositeMaterial)).for_each(Converter<compositematerial>(description,_ns.context,optional));
0225 }
0226 
0227 template <> void Converter<rotationsection>::operator()(xml_h element) const   {
0228   Namespace _ns(_param<ParsingContext>(), element);
0229   xml_coll_t(element, _CMU(Rotation)).for_each(Converter<rotation>(description,_ns.context,optional));
0230   xml_coll_t(element, _CMU(ReflectionRotation)).for_each(Converter<rotation>(description,_ns.context,optional));
0231 }
0232 
0233 template <> void Converter<pospartsection>::operator()(xml_h element) const   {
0234   Namespace _ns(_param<ParsingContext>(), element);
0235   xml_coll_t(element, _CMU(Division)).for_each(Converter<division>(description,_ns.context,optional));
0236   xml_coll_t(element, _CMU(PosPart)).for_each(Converter<pospart>(description,_ns.context,optional));
0237   xml_coll_t(element, _CMU(Algorithm)).for_each(Converter<algorithm>(description,_ns.context,optional));
0238 }
0239 
0240 /// Generic converter for  <LogicalPartSection/> tags
0241 template <> void Converter<logicalpartsection>::operator()(xml_h element) const   {
0242   Namespace _ns(_param<ParsingContext>(), element);
0243   xml_coll_t(element, _CMU(LogicalPart)).for_each(Converter<logicalpart>(description,_ns.context,optional));
0244 }
0245 
0246 template <> void Converter<disabled_algo>::operator()(xml_h element) const   {
0247   ParsingContext* c = _param<ParsingContext>();
0248   c->disabledAlgs.insert(element.attr<string>(_U(name)));
0249 }
0250 
0251 /// Generic converter for  <SolidSection/> tags
0252 template <> void Converter<solidsection>::operator()(xml_h element) const   {
0253   Namespace _ns(_param<ParsingContext>(), element);
0254   for(xml_coll_t solid(element, _U(star)); solid; ++solid)   {
0255     string tag = solid.tag();
0256     if ( tag == "Box" )
0257       Converter<box>(description,_ns.context,optional)(solid);
0258     else if ( tag == "Polycone" )
0259       Converter<polycone>(description,_ns.context,optional)(solid);
0260     else if ( tag == "Polyhedra" )
0261       Converter<polyhedra>(description,_ns.context,optional)(solid);
0262     else if ( tag == "Tubs" )
0263       Converter<tubs>(description,_ns.context,optional)(solid);
0264     else if ( tag == "CutTubs" )
0265       Converter<cuttubs>(description,_ns.context,optional)(solid);
0266     else if ( tag == "TruncTubs" )
0267       Converter<trunctubs>(description,_ns.context,optional)(solid);
0268     else if ( tag == "Tube" )
0269       Converter<tubs>(description,_ns.context,optional)(solid);
0270     else if ( tag == "Trd1" )
0271       Converter<trd1>(description,_ns.context,optional)(solid);
0272     else if ( tag == "Cone" )
0273       Converter<cone>(description,_ns.context,optional)(solid);
0274     else if ( tag == "Sphere" )
0275       Converter<sphere>(description,_ns.context,optional)(solid);
0276     else if ( tag == "Ellipsoid" )
0277       Converter<ellipsoid>(description,_ns.context,optional)(solid);
0278     else if ( tag == "EllipticalTube" )
0279       Converter<ellipticaltube>(description,_ns.context,optional)(solid);
0280     else if ( tag == "Orb" )
0281       Converter<orb>(description,_ns.context,optional)(solid);
0282     else if ( tag == "Torus" )
0283       Converter<torus>(description,_ns.context,optional)(solid);
0284     else if ( tag == "PseudoTrap" )
0285       Converter<pseudotrap>(description,_ns.context,optional)(solid);
0286     else if ( tag == "ExtrudedPolygon" )
0287       Converter<extrudedpolygon>(description,_ns.context,optional)(solid);
0288     else if ( tag == "Trapezoid" )
0289       Converter<trapezoid>(description,_ns.context,optional)(solid);
0290     else if ( tag == "UnionSolid" )
0291       Converter<unionsolid>(description,_ns.context,optional)(solid);
0292     else if ( tag == "SubtractionSolid" )
0293       Converter<subtractionsolid>(description,_ns.context,optional)(solid);
0294     else if ( tag == "IntersectionSolid" )
0295       Converter<intersectionsolid>(description,_ns.context,optional)(solid);
0296     else if ( tag == "ShapelessSolid" )
0297       Converter<shapeless>(description,_ns.context,optional)(solid);
0298     else  {
0299       string nam = xml_dim_t(solid).nameStr();
0300       printout(ERROR,"DDCMS","+++ Request to process unknown shape '%s' [%s]",
0301                nam.c_str(), tag.c_str());
0302     }
0303   }
0304 }
0305 
0306 /// Converter for <Constant/> tags
0307 template <> void Converter<constant>::operator()(xml_h element) const  {
0308   Namespace _ns(_param<ParsingContext>());
0309   resolve*  res  = _option<resolve>();
0310   xml_dim_t constant = element;
0311   xml_dim_t par  = constant.parent();
0312   bool      eval = par.hasAttr(_U(eval)) ? par.attr<bool>(_U(eval)) : false;
0313   string    val  = constant.valueStr();
0314   string    nam  = constant.nameStr();
0315   string    real = _ns.prepend(nam);
0316   string    typ  = eval ? "number" : "string";
0317   size_t    idx  = val.find('[');
0318   
0319   if ( constant.hasAttr(_U(type)) )
0320     typ = constant.typeStr();
0321 
0322   if ( idx == string::npos || typ == "string" )  {
0323     try  {
0324       _ns.addConstant(nam, val, typ);
0325       res->allConst[real] = val;
0326       res->originalConst[real] = val;
0327     }
0328     catch(const exception& e)   {
0329       printout(INFO,"DDCMS","++ Unresolved constant: %s = %s [%s]. Try to resolve later. [%s]",
0330                real.c_str(), val.c_str(), typ.c_str(), e.what());
0331     }
0332     return;
0333   }
0334   // Setup the resolution mechanism in Converter<resolve>
0335   while ( idx != string::npos )  {
0336     ++idx;
0337     size_t idp = val.find(':',idx);
0338     size_t idq = val.find(']',idx);
0339     if ( idp == string::npos || idp > idq )
0340       val.insert(idx,_ns.name);
0341     else if ( idp != string::npos && idp < idq )
0342       val[idp] = NAMESPACE_SEP;
0343     idx = val.find('[',idx);
0344   }
0345   //MSF NS while ( (idx=val.find(':')) != string::npos ) val[idx]=NAMESPACE_SEP;
0346   printout(_ns.context->debug.constants ? ALWAYS : DEBUG,
0347            "Constant","Unresolved: %s -> %s",real.c_str(),val.c_str());
0348   res->allConst[real] = val;
0349   res->originalConst[real] = val;
0350   res->unresolvedConst[real] = val;
0351 }
0352 
0353 /** Convert compact visualization attribute to Detector visualization attribute
0354  *
0355  *  <vis name="SiVertexBarrelModuleVis"
0356  *       alpha="1.0" r="1.0" g="0.75" b="0.76"
0357  *       drawingStyle="wireframe"
0358  *       showDaughters="false"
0359  *       visible="true"/>
0360  */
0361 template <> void Converter<vis>::operator()(xml_h e) const   {
0362   Namespace _ns(_param<ParsingContext>());
0363   VisAttr attr(e.attr<string>(_U(name)));
0364   xml_dim_t dim(e);
0365   float alpha = dim.alpha(1.0);
0366   float red   = dim.r(1.0);
0367   float green = dim.g(1.0);
0368   float blue  = dim.b(1.0);
0369 
0370   printout(_ns.context->debug.visattr ? ALWAYS : DEBUG, "Compact",
0371            "++ Converting VisAttr  structure: %-16s. R=%.3f G=%.3f B=%.3f",
0372            attr.name(), red, green, blue);
0373   attr.setColor(alpha, red, green, blue);
0374   if ( e.hasAttr(_U(visible)) )
0375     attr.setVisible(e.attr<bool>(_U(visible)));
0376   if ( e.hasAttr(_U(lineStyle)) ) {
0377     string ls = e.attr<string>(_U(lineStyle));
0378     if (ls == "unbroken")
0379       attr.setLineStyle(VisAttr::SOLID);
0380     else if (ls == "broken")
0381       attr.setLineStyle(VisAttr::DASHED);
0382   }
0383   else {
0384     attr.setLineStyle(VisAttr::SOLID);
0385   }
0386   if (e.hasAttr(_U(drawingStyle))) {
0387     string ds = e.attr<string>(_U(drawingStyle));
0388     if (ds == "wireframe")
0389       attr.setDrawingStyle(VisAttr::WIREFRAME);
0390     else if (ds == "solid")
0391       attr.setDrawingStyle(VisAttr::SOLID);
0392   }
0393   else {
0394     attr.setDrawingStyle(VisAttr::SOLID);
0395   }
0396   if (e.hasAttr(_U(showDaughters)))
0397     attr.setShowDaughters(e.attr<bool>(_U(showDaughters)));
0398   else
0399     attr.setShowDaughters(true);
0400   description.addVisAttribute(attr);
0401 }
0402 
0403 /// Converter for <ElementaryMaterial/> tags
0404 template <> void Converter<elementaryelement>::operator()(xml_h element) const   {
0405   Namespace     _ns(_param<ParsingContext>());
0406   xml_dim_t     xmat(element);
0407   string        nam = _ns.prepend(xmat.nameStr());
0408   TGeoManager&  mgr = description.manager();
0409   TGeoElementTable* tab = mgr.GetElementTable();
0410   TGeoElement*      elt1 = tab->FindElement(xmat.nameStr().c_str());
0411   TGeoElement*      elt2 = tab->FindElement(nam.c_str());
0412   static bool first = true;
0413   if ( first && _ns.context->debug.materials )   {
0414     first = false;
0415     printout(ALWAYS, "DDCMS"," +++ Units: gram:   %7.3f ",dd4hep::g);
0416     printout(ALWAYS, "DDCMS"," +++ Units: cm3:    %7.3f ",dd4hep::cm3);
0417     printout(ALWAYS, "DDCMS"," +++ Units: cm:     %7.3f ",dd4hep::cm);
0418     printout(ALWAYS, "DDCMS"," +++ Units: mole:   %7.3f ",dd4hep::mole);
0419     printout(ALWAYS, "DDCMS"," +++ Units: g/cm3:  %7.3f ",dd4hep::g/dd4hep::cm3);
0420     printout(ALWAYS, "DDCMS"," +++ Units: g/mole: %7.3f ",dd4hep::g/dd4hep::mole);    
0421   }
0422   if ( !elt1 || !elt2 )  {
0423     double atomicNumber = xmat.attr<double>(_CMU(atomicNumber));
0424     double atomicWeight = xmat.attr<double>(_CMU(atomicWeight))/(dd4hep::g/dd4hep::mole);
0425     int n = int(atomicNumber);
0426     printout(_ns.context->debug.materials ? ALWAYS : DEBUG, "DDCMS",
0427              "+++ Converting element  %-32s  atomic number: %3d  weight: %8.3f   [g/mol]",
0428              ('"'+nam+'"').c_str(), n, atomicWeight);
0429     elt1 = new TGeoElement(nam.c_str(),"CMS element", n, atomicWeight);
0430     tab->AddElement(elt1);
0431   }
0432 }
0433 
0434 /// Converter for <ElementaryMaterial/> tags
0435 template <> void Converter<elementarymaterial>::operator()(xml_h element) const   {
0436   Namespace     _ns(_param<ParsingContext>());
0437   xml_dim_t     xmat(element);
0438   string        nam = _ns.prepend(xmat.nameStr());
0439   TGeoManager&  mgr = description.manager();
0440   TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
0441   if ( 0 == mat )   {
0442     const char* matname = nam.c_str();
0443     double density      = xmat.density() / (dd4hep::g/dd4hep::cm3);
0444     //double atomicWeight = xmat.attr<double>(_CMU(atomicWeight));
0445     //double atomicNumber = xmat.attr<double>(_CMU(atomicNumber));
0446     TGeoElementTable* tab = mgr.GetElementTable();
0447     TGeoMixture*      mix = new TGeoMixture(nam.c_str(), 1, density);
0448     TGeoElement*      elt = tab->FindElement(nam.c_str());
0449 
0450     printout(_ns.context->debug.materials ? ALWAYS : DEBUG, "DDCMS",
0451              "+++ Converting material %-48s  Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
0452              ('"'+nam+'"').c_str(), density, mix->GetDensity());
0453 
0454     if ( !elt )  {
0455       printout(WARNING,"DDCMS",
0456                "+++ Converter<ElementaryMaterial> No element present with name:%s  [FAKE IT]",
0457                matname);
0458     }
0459 #if 0
0460     if ( !elt )  {
0461       printout(WARNING,"DDCMS",
0462                "+++ Converter<ElementaryMaterial> No element present with name:%s  [FAKE IT]",
0463                matname);
0464       int n = int(atomicNumber/2e0);
0465       if ( n < 2 ) n = 2;
0466       elt = new TGeoElement(xmat.nameStr().c_str(),"CMS element",n,atomicNumber);
0467       //return;
0468     }
0469     if ( elt->Z() == 0 )   {
0470       int n = int(atomicNumber/2e0);
0471       if ( n < 2 ) n = 2;
0472       elt = new TGeoElement((xmat.nameStr()+"-CMS").c_str(),"CMS element", n, atomicNumber);
0473     }
0474 #endif
0475     mix->AddElement(elt, 1.0);
0476     mix->SetRadLen(0e0);
0477     mix->ComputeDerivedQuantities();
0478     /// Create medium from the material
0479     TGeoMedium* medium = mgr.GetMedium(matname);
0480     if (0 == medium) {
0481       --unique_mat_id;
0482       medium = new TGeoMedium(matname, unique_mat_id, mix);
0483       medium->SetTitle("material");
0484       medium->SetUniqueID(unique_mat_id);
0485     }
0486   }
0487 }
0488 
0489 /// Converter for <CompositeMaterial/> tags
0490 template <> void Converter<compositematerial>::operator()(xml_h element) const   {
0491   Namespace     _ns(_param<ParsingContext>());
0492   xml_dim_t     xmat(element);
0493   string        nam = _ns.prepend(xmat.nameStr());
0494   TGeoManager&  mgr = description.manager();
0495   TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
0496   if ( 0 == mat )   {
0497     const char*  matname = nam.c_str();
0498     double       density = xmat.density() / (dd4hep::g/dd4hep::cm3);
0499     xml_coll_t   composites(xmat,_CMU(MaterialFraction));
0500     TGeoMixture* mix = new TGeoMixture(nam.c_str(), composites.size(), density);
0501 
0502     for (composites.reset(); composites; ++composites)   {
0503       xml_dim_t xfrac(composites);
0504       xml_dim_t xfrac_mat(xfrac.child(_CMU(rMaterial)));
0505       double    fraction = xfrac.fraction();
0506       string    fracname = _ns.real_name(xfrac_mat.nameStr());
0507 
0508       TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
0509       if ( frac_mat )  {
0510         mix->AddElement(frac_mat, fraction);
0511         continue;
0512       }
0513       printout(WARNING,"DDCMS","+++ Composite material \"%s\" not present!",
0514                fracname.c_str());
0515     }
0516     mix->SetRadLen(0e0);
0517     mix->ComputeDerivedQuantities();
0518     printout(_ns.context->debug.materials ? ALWAYS : DEBUG, "DDCMS",
0519              "++  Converting material %-48s  Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
0520              ('"'+nam+'"').c_str(), density, mix->GetDensity());
0521     
0522     /// Create medium from the material
0523     TGeoMedium* medium = mgr.GetMedium(matname);
0524     if (0 == medium) {
0525       --unique_mat_id;
0526       medium = new TGeoMedium(matname, unique_mat_id, mix);
0527       medium->SetTitle("material");
0528       medium->SetUniqueID(unique_mat_id);
0529     }
0530     
0531   }
0532 }
0533 
0534 /// Converter for <Rotation/> tags
0535 template <> void Converter<rotation>::operator()(xml_h element) const  {
0536   ParsingContext* ctx = _param<ParsingContext>();
0537   Namespace  _ns(ctx);
0538   xml_dim_t  xrot(element);
0539   string     nam    = xrot.nameStr();
0540   PrintLevel lvl = ctx->debug.rotations ? ALWAYS : DEBUG;
0541   double     thetaX = xrot.hasAttr(_CMU(thetaX)) ? _ns.attr<double>(xrot,_CMU(thetaX)) : 0e0;
0542   double     phiX   = xrot.hasAttr(_CMU(phiX))   ? _ns.attr<double>(xrot,_CMU(phiX))   : 0e0;
0543   double     thetaY = xrot.hasAttr(_CMU(thetaY)) ? _ns.attr<double>(xrot,_CMU(thetaY)) : 0e0;
0544   double     phiY   = xrot.hasAttr(_CMU(phiY))   ? _ns.attr<double>(xrot,_CMU(phiY))   : 0e0;
0545   double     thetaZ = xrot.hasAttr(_CMU(thetaZ)) ? _ns.attr<double>(xrot,_CMU(thetaZ)) : 0e0;
0546   double     phiZ   = xrot.hasAttr(_CMU(phiZ))   ? _ns.attr<double>(xrot,_CMU(phiZ))   : 0e0;
0547   Rotation3D rot = make_rotation3D(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
0548 
0549   _ns.addRotation(nam, rot);
0550   if ( isActivePrintLevel(lvl) )   {
0551     double det;
0552     Position x, y, z;
0553     stringstream str;
0554     rot.GetComponents(x,y,z);
0555     det = (x.Cross(y)).Dot(z);
0556     str << "+++ rotation: " << nam
0557     << " " << ((det>=0) ? "RIGHT" : "LEFT") << "-handed "
0558     << scientific << setprecision(2) << setw(9) << x << y << z << rot;
0559     printout(lvl, "DDCMS",
0560          "+++ Adding rotation: %-18s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
0561          _ns.prepend(nam).c_str(),thetaX,phiX,thetaY,phiY,thetaZ,phiZ);
0562     printout(lvl, "DDCMS", str.str().c_str());
0563   }
0564 }
0565 
0566 /// Converter for <Logicalpart/> tags
0567 template <> void Converter<logicalpart>::operator()(xml_h element) const {
0568   Namespace _ns(_param<ParsingContext>());
0569   xml_dim_t e(element);
0570   string    sol = e.child(_CMU(rSolid)).attr<string>(_U(name));
0571   string    mat = e.child(_CMU(rMaterial)).attr<string>(_U(name));
0572   _ns.addVolume(Volume(e.nameStr(), _ns.solid(sol), _ns.material(mat)));
0573 }
0574 
0575 /// Helper converter
0576 template <> void Converter<transform3d>::operator()(xml_h element) const {
0577   Namespace    _ns(_param<ParsingContext>());
0578   Transform3D* tr = _option<Transform3D>();
0579   xml_dim_t   e(element);
0580   xml_dim_t   translation = e.child(_CMU(Translation),false);
0581   xml_dim_t   rotation    = e.child(_CMU(Rotation),false);
0582   xml_dim_t   rRotation   = e.child(_CMU(rRotation),false);
0583   xml_dim_t   rReflectionRotation = e.child(_CMU(rReflectionRotation),false);
0584   Position    pos;
0585   Rotation3D  rot;
0586 
0587   if ( translation.ptr() )   {
0588     double x = _ns.attr<double>(translation,_U(x));
0589     double y = _ns.attr<double>(translation,_U(y));
0590     double z = _ns.attr<double>(translation,_U(z));
0591     pos = Position(x,y,z);
0592   }
0593   if ( rotation.ptr() )   {
0594     double x = _ns.attr<double>(rotation,_U(x));
0595     double y = _ns.attr<double>(rotation,_U(y));
0596     double z = _ns.attr<double>(rotation,_U(z));
0597     rot = RotationZYX(z,y,x);
0598   }
0599   else if ( rRotation.ptr() )   {
0600     rot = _ns.rotation(rRotation.nameStr());
0601   }
0602   else if ( rReflectionRotation.ptr() )   {
0603     rot = _ns.rotation(rReflectionRotation.nameStr());
0604   }
0605   *tr = Transform3D(rot,pos);
0606 }
0607 
0608 /// Converter for <PosPart/> tags
0609 template <> void Converter<pospart>::operator()(xml_h element) const {
0610   Namespace  _ns(_param<ParsingContext>());
0611   xml_dim_t  e(element);
0612   int        copy        = e.attr<int>(_CMU(copyNumber));
0613   string     parent_nam  = _ns.attr<string>(e.child(_CMU(rParent)),_U(name));
0614   string     child_nam   = _ns.attr<string>(e.child(_CMU(rChild)),_U(name));
0615   Volume     parent      = _ns.volume(parent_nam);
0616   Volume     child       = _ns.volume(child_nam, false);
0617   PrintLevel lvl         = _ns.context->debug.placements ? ALWAYS : DEBUG;
0618   bool       dbg         = isActivePrintLevel(lvl);
0619 
0620   if ( dbg )   {
0621     printout(lvl, "DDCMS", "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
0622            e.tag().c_str(),
0623            parent_nam.c_str(), parent.isValid() ? "VALID" : "INVALID",
0624            child_nam.c_str(),  child.isValid()  ? "VALID" : "INVALID",
0625            copy);
0626   }
0627   PlacedVolume pv;
0628   if ( child.isValid() )   {
0629     Transform3D trafo;
0630     Converter<transform3d>(description,param,&trafo)(element);
0631     pv = parent.placeVolume(child, copy, trafo);
0632     if ( dbg )   {
0633       stringstream str;
0634       Rotation3D   r;
0635       Position     p, x, y, z;
0636       xml_dim_t    rRotation = e.child(_CMU(rRotation),false);
0637       xml_dim_t    rReflectionRotation = e.child(_CMU(rReflectionRotation),false);
0638       trafo.GetDecomposition(r, p);
0639       r.GetComponents(x,y,z);
0640       double det = (x.Cross(y)).Dot(z);
0641       str << "+++ Rotation: " << (const char*)((det >=0) ? "RIGHT" : "LEFT") << "-handed  ";
0642       if ( rRotation.ptr() ) str << rRotation.nameStr();
0643       if ( rReflectionRotation.ptr() ) str << rReflectionRotation.nameStr();
0644       str << "  Pos: " << p << "  Rotation:" << r;
0645       printout(lvl, "DDCMS", str.str().c_str());
0646     }
0647   }
0648   if ( !pv.isValid() )   {
0649     printout(ERROR,"DDCMS","+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
0650              parent.name(), child_nam.c_str(), yes_no(child.isValid()));
0651   }
0652 }
0653 
0654 template <typename TYPE>
0655 static void convert_boolean(ParsingContext* ctx, xml_h element)   {
0656   Namespace   _ns(ctx);
0657   xml_dim_t   e(element);
0658   string      nam = e.nameStr();
0659   Solid       solids[2];
0660   Solid       boolean;
0661   int         cnt = 0;
0662 
0663   if ( e.hasChild(_CMU(rSolid)) )  {   // Old version
0664     for(xml_coll_t c(element, _CMU(rSolid)); cnt<2 && c; ++c, ++cnt)
0665       solids[cnt] = _ns.solid(c.attr<string>(_U(name)));
0666   }
0667   else  {
0668     if ( (solids[0] = _ns.solid(e.attr<string>(_CMU(firstSolid)))).isValid() ) ++cnt;
0669     if ( (solids[1] = _ns.solid(e.attr<string>(_CMU(secondSolid)))).isValid() ) ++cnt;
0670   }
0671   if ( cnt != 2 )   {
0672     except("DDCMS","+++ Failed to create boolean solid %s. Found only %d parts.",nam.c_str(), cnt);
0673   }
0674   printout(_ns.context->debug.placements ? ALWAYS : DEBUG, "DDCMS",
0675            "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
0676            nam.c_str(), solids[0]->GetName(), solids[1]->GetName());
0677 
0678   if ( solids[0].isValid() && solids[1].isValid() )  {
0679     Transform3D trafo;
0680     Converter<transform3d>(*ctx->description,ctx,&trafo)(element);
0681     boolean = TYPE(solids[0],solids[1],trafo);
0682   }
0683   if ( !boolean.isValid() )
0684     except("DDCMS","+++ FAILED to construct subtraction solid: %s",nam.c_str());
0685   _ns.addSolid(nam,boolean);
0686 }
0687 
0688 /// Converter for <SubtractionSolid/> tags
0689 template <> void Converter<unionsolid>::operator()(xml_h element) const   {
0690   convert_boolean<UnionSolid>(_param<ParsingContext>(),element);
0691 }
0692 
0693 /// Converter for <SubtractionSolid/> tags
0694 template <> void Converter<subtractionsolid>::operator()(xml_h element) const   {
0695   convert_boolean<SubtractionSolid>(_param<ParsingContext>(),element);
0696 }
0697 
0698 /// Converter for <SubtractionSolid/> tags
0699 template <> void Converter<intersectionsolid>::operator()(xml_h element) const   {
0700   convert_boolean<IntersectionSolid>(_param<ParsingContext>(),element);
0701 }
0702 
0703 /// Converter for <Polycone/> tags
0704 template <> void Converter<polycone>::operator()(xml_h element) const {
0705   Namespace _ns(_param<ParsingContext>());
0706   xml_dim_t e(element);
0707   string nam      = e.nameStr();
0708   double startPhi = _ns.attr<double>(e,_CMU(startPhi));
0709   double deltaPhi = _ns.attr<double>(e,_CMU(deltaPhi));
0710   vector<double> z, rmin, rmax;
0711   
0712   for(xml_coll_t zplane(element, _CMU(RZPoint)); zplane; ++zplane)   {
0713     rmin.push_back(0.0);
0714     rmax.push_back(_ns.attr<double>(zplane,_U(r)));
0715     z.push_back(_ns.attr<double>(zplane,_U(z)));
0716   }
0717   for(xml_coll_t zplane(element, _CMU(ZSection)); zplane; ++zplane)   {
0718     rmin.push_back(_ns.attr<double>(zplane,_CMU(rMin)));
0719     rmax.push_back(_ns.attr<double>(zplane,_CMU(rMax)));
0720     z.push_back(_ns.attr<double>(zplane,_U(z)));
0721   }
0722   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0723            "+   Polycone: startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]  %4ld z-planes",
0724            startPhi, deltaPhi, z.size());
0725   _ns.addSolid(nam, Polycone(startPhi,deltaPhi,rmin,rmax,z));
0726 }
0727 
0728 /// Converter for <ExtrudedPolygon/> tags
0729 template <> void Converter<extrudedpolygon>::operator()(xml_h element) const  {
0730   Namespace _ns(_param<ParsingContext>());
0731   xml_dim_t e(element);
0732   string nam      = e.nameStr();
0733   vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
0734   
0735   for(xml_coll_t sec(element, _CMU(ZXYSection)); sec; ++sec)   {
0736     sec_z.push_back(_ns.attr<double>(sec,_U(z)));
0737     sec_x.push_back(_ns.attr<double>(sec,_U(x)));
0738     sec_y.push_back(_ns.attr<double>(sec,_U(y)));
0739     sec_scale.push_back(_ns.attr<double>(sec,_CMU(scale),1.0));
0740   }
0741   for(xml_coll_t pt(element, _CMU(XYPoint)); pt; ++pt)   {
0742     pt_x.push_back(_ns.attr<double>(pt,_U(x)));
0743     pt_y.push_back(_ns.attr<double>(pt,_U(y)));
0744   }
0745   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0746            "+   ExtrudedPolygon: %4ld points %4ld zxy sections",
0747            pt_x.size(), sec_z.size());
0748   _ns.addSolid(nam,ExtrudedPolygon(pt_x,pt_y,sec_z,sec_x,sec_y,sec_scale));
0749 }
0750 
0751 /// Converter for <Polyhedra/> tags
0752 template <> void Converter<polyhedra>::operator()(xml_h element) const {
0753   Namespace _ns(_param<ParsingContext>());
0754   xml_dim_t e(element);
0755   string nam      = e.nameStr();
0756   double numSide  = _ns.attr<int>(e,_CMU(numSide));
0757   double startPhi = _ns.attr<double>(e,_CMU(startPhi));
0758   double deltaPhi = _ns.attr<double>(e,_CMU(deltaPhi));
0759   vector<double> z, rmin, rmax;
0760   
0761   for(xml_coll_t zplane(element, _CMU(RZPoint)); zplane; ++zplane)   {
0762     rmin.push_back(0.0);
0763     rmax.push_back(_ns.attr<double>(zplane,_U(r)));
0764     z.push_back(_ns.attr<double>(zplane,_U(z)));
0765   }
0766   for(xml_coll_t zplane(element, _CMU(ZSection)); zplane; ++zplane)   {
0767     rmin.push_back(_ns.attr<double>(zplane,_CMU(rMin)));
0768     rmax.push_back(_ns.attr<double>(zplane,_CMU(rMax)));
0769     z.push_back(_ns.attr<double>(zplane,_U(z)));
0770   }
0771   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0772            "+   Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]  %4d sides %4ld z-planes",
0773            startPhi, deltaPhi, numSide, z.size());
0774   _ns.addSolid(nam, Polyhedra(numSide,startPhi,deltaPhi,z,rmin,rmax));
0775 }
0776 
0777 /// Converter for <Sphere/> tags
0778 template <> void Converter<sphere>::operator()(xml_h element) const {
0779   Namespace _ns(_param<ParsingContext>());
0780   xml_dim_t e(element);
0781   string nam      = e.nameStr();
0782   double rinner   = _ns.attr<double>(e,_CMU(innerRadius));
0783   double router   = _ns.attr<double>(e,_CMU(outerRadius));
0784   double startPhi = _ns.attr<double>(e,_CMU(startPhi));
0785   double deltaPhi = _ns.attr<double>(e,_CMU(deltaPhi));
0786   double startTheta = _ns.attr<double>(e,_CMU(startTheta));
0787   double deltaTheta = _ns.attr<double>(e,_CMU(deltaTheta));
0788   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0789            "+   Sphere:   r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
0790            " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
0791            rinner, router, startPhi, deltaPhi, startTheta, deltaTheta);
0792   _ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
0793 }
0794 
0795 /// Converter for <Ellipsoid/> tags: Same as sphere, but with scale
0796 template <> void Converter<ellipsoid>::operator()(xml_h element) const   {
0797   Namespace _ns(_param<ParsingContext>());
0798   xml_dim_t e(element);
0799   string nam  = e.nameStr();
0800   double dx   = _ns.attr<double>(e,_CMU(xSemiAxis));
0801   double dy   = _ns.attr<double>(e,_CMU(ySemiAxis));
0802   double dz   = _ns.attr<double>(e,_CMU(zSemiAxis));
0803   double zBot = _ns.attr<double>(e,_CMU(zBottomCut),0.0);
0804   double zTop = _ns.attr<double>(e,_CMU(zTopCut),0.0);
0805 
0806   printout(WARNING, "DDCMS",
0807            "+   Ellipsoid UNSUPPORTED. '%s' REPLACED BY BOX "
0808            " xSemiAxis=%8.3f ySemiAxis=%8.3f zSemiAxis=%8.3f zBottomCut=%8.3f zTopCut=%8.3f [cm]",
0809            nam.c_str(), dx, dy, dz, zBot, zTop);
0810   _ns.addSolid(nam, Box(1,1,1));
0811 }
0812 
0813 /// Converter for <Torus/> tags
0814 template <> void Converter<torus>::operator()(xml_h element) const   {
0815   Namespace _ns(_param<ParsingContext>());
0816   xml_dim_t e(element);
0817   string nam      = e.nameStr();
0818   double r        = _ns.attr<double>(e,_CMU(torusRadius));
0819   double rinner   = _ns.attr<double>(e,_CMU(innerRadius));
0820   double router   = _ns.attr<double>(e,_CMU(outerRadius));
0821   double startPhi = _ns.attr<double>(e,_CMU(startPhi));
0822   double deltaPhi = _ns.attr<double>(e,_CMU(deltaPhi));
0823   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0824            "+   Torus:    r=%8.3f [cm] r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
0825            " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
0826            r, rinner, router, startPhi, deltaPhi);
0827   _ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
0828 }
0829 
0830 /// Converter for <Pseudotrap/> tags
0831 template <> void Converter<pseudotrap>::operator()(xml_h element) const {
0832   Namespace _ns(_param<ParsingContext>());
0833   xml_dim_t e(element);
0834   string nam      = e.nameStr();
0835   double dx1      = _ns.attr<double>(e,_CMU(dx1));
0836   double dy1      = _ns.attr<double>(e,_CMU(dy1));
0837   double dx2      = _ns.attr<double>(e,_CMU(dx2));
0838   double dy2      = _ns.attr<double>(e,_CMU(dy2));
0839   double dz       = _ns.attr<double>(e,_U(dz));
0840   double r        = _ns.attr<double>(e,_U(radius));
0841   bool   atMinusZ = _ns.attr<bool>  (e,_CMU(atMinusZ));
0842   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0843            "+   Pseudotrap:  dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
0844            dz, dx1, dy1, dx2, dy2, r, yes_no(atMinusZ));
0845   _ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
0846 }
0847 
0848 /// Converter for <Trapezoid/> tags
0849 template <> void Converter<trapezoid>::operator()(xml_h element) const {
0850   Namespace _ns(_param<ParsingContext>());
0851   xml_dim_t e(element);
0852   string nam      = e.nameStr();
0853   double dz       = _ns.attr<double>(e,_U(dz));
0854   double alp1     = _ns.attr<double>(e,_CMU(alp1));
0855   double bl1      = _ns.attr<double>(e,_CMU(bl1));
0856   double tl1      = _ns.attr<double>(e,_CMU(tl1));
0857   double h1       = _ns.attr<double>(e,_CMU(h1));
0858   double alp2     = _ns.attr<double>(e,_CMU(alp2));
0859   double bl2      = _ns.attr<double>(e,_CMU(bl2));
0860   double tl2      = _ns.attr<double>(e,_CMU(tl2));
0861   double h2       = _ns.attr<double>(e,_CMU(h2));
0862   double phi      = _ns.attr<double>(e,_U(phi),0.0);
0863   double theta    = _ns.attr<double>(e,_U(theta),0.0);
0864   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0865            "+   Trapezoid:  dz=%8.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f theta=%.3f",
0866            dz, alp1, bl1, tl1, h1, alp2, bl2, tl2, h2, phi, theta);
0867   _ns.addSolid(nam, Trap(dz, theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
0868 }
0869 
0870 /// Converter for <Trd1/> tags
0871 template <> void Converter<trd1>::operator()(xml_h element) const {
0872   Namespace _ns(_param<ParsingContext>());
0873   xml_dim_t e(element);
0874   string nam      = e.nameStr();
0875   double dx1      = _ns.attr<double>(e,_CMU(dx1));
0876   double dy1      = _ns.attr<double>(e,_CMU(dy1));
0877   double dx2      = _ns.attr<double>(e,_CMU(dx2),0.0);
0878   double dy2      = _ns.attr<double>(e,_CMU(dy2),0.0);
0879   double dz       = _ns.attr<double>(e,_CMU(dz));
0880   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0881            "+   Trd1:       dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
0882            dz, dx1, dy1, dx2, dy2);
0883   if ( dy1 == dy2 )
0884     _ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
0885   else
0886     _ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
0887 }
0888 
0889 /// Converter for <Tubs/> tags
0890 template <> void Converter<tubs>::operator()(xml_h element) const {
0891   Namespace _ns(_param<ParsingContext>());
0892   xml_dim_t e(element);
0893   string nam      = e.nameStr();
0894   double dz       = _ns.attr<double>(e,_CMU(dz));
0895   double rmin     = _ns.attr<double>(e,_CMU(rMin));
0896   double rmax     = _ns.attr<double>(e,_CMU(rMax));
0897   double startPhi = _ns.attr<double>(e,_CMU(startPhi),0.0);
0898   double deltaPhi = _ns.attr<double>(e,_CMU(deltaPhi),2*M_PI);
0899   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0900            "+   Tubs:     dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
0901            " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]", dz, rmin, rmax, startPhi, deltaPhi);
0902   _ns.addSolid(nam, Tube(rmin,rmax,dz,startPhi,deltaPhi));
0903 }
0904 
0905 /// Converter for <CutTubs/> tags
0906 template <> void Converter<cuttubs>::operator()(xml_h element) const {
0907   Namespace _ns(_param<ParsingContext>());
0908   xml_dim_t e(element);
0909   string nam      = e.nameStr();
0910   double dz       = _ns.attr<double>(e,_CMU(dz));
0911   double rmin     = _ns.attr<double>(e,_CMU(rMin));
0912   double rmax     = _ns.attr<double>(e,_CMU(rMax));
0913   double startPhi = _ns.attr<double>(e,_CMU(startPhi));
0914   double deltaPhi = _ns.attr<double>(e,_CMU(deltaPhi));
0915   double lx       = _ns.attr<double>(e,_CMU(lx));
0916   double ly       = _ns.attr<double>(e,_CMU(ly));
0917   double lz       = _ns.attr<double>(e,_CMU(lz));
0918   double tx       = _ns.attr<double>(e,_CMU(tx));
0919   double ty       = _ns.attr<double>(e,_CMU(ty));
0920   double tz       = _ns.attr<double>(e,_CMU(tz));
0921   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0922            "+   CutTube:  dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
0923            " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
0924            dz, rmin, rmax, startPhi, deltaPhi);
0925   _ns.addSolid(nam, CutTube(rmin,rmax,dz,startPhi,deltaPhi,lx,ly,lz,tx,ty,tz));
0926 }
0927 
0928 /// Converter for <TruncTubs/> tags
0929 template <> void Converter<trunctubs>::operator()(xml_h element) const {
0930   Namespace _ns(_param<ParsingContext>());
0931   xml_dim_t e(element);
0932   string nam        = e.nameStr();
0933   double zhalf      = _ns.attr<double>(e,_CMU(zHalf));
0934   double rmin       = _ns.attr<double>(e,_CMU(rMin));
0935   double rmax       = _ns.attr<double>(e,_CMU(rMax));
0936   double startPhi   = _ns.attr<double>(e,_CMU(startPhi));
0937   double deltaPhi   = _ns.attr<double>(e,_CMU(deltaPhi));
0938   double cutAtStart = _ns.attr<double>(e,_CMU(cutAtStart));
0939   double cutAtDelta = _ns.attr<double>(e,_CMU(cutAtDelta));
0940   bool   cutInside  = _ns.attr<bool>(e,_CMU(cutInside));
0941   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0942            "+   TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
0943            " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
0944            zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, yes_no(cutInside));
0945   _ns.addSolid(nam, TruncatedTube(zhalf,rmin,rmax,startPhi,deltaPhi,cutAtStart,cutAtDelta,cutInside));
0946 }
0947 
0948 /// Converter for <EllipticalTube/> tags
0949 template <> void Converter<ellipticaltube>::operator()(xml_h element) const   {
0950   Namespace _ns(_param<ParsingContext>());
0951   xml_dim_t e(element);
0952   string nam = e.nameStr();
0953   double dx  = _ns.attr<double>(e,_CMU(xSemiAxis));
0954   double dy  = _ns.attr<double>(e,_CMU(ySemiAxis));
0955   double dz  = _ns.attr<double>(e,_CMU(zHeight));
0956   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0957            "+   EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",dx,dy,dz);
0958   _ns.addSolid(nam, EllipticalTube(dx,dy,dz));
0959 }
0960 
0961 /// Converter for <Cone/> tags
0962 template <> void Converter<cone>::operator()(xml_h element) const {
0963   Namespace _ns(_param<ParsingContext>());
0964   xml_dim_t e(element);
0965   string nam      = e.nameStr();
0966   double dz       = _ns.attr<double>(e,_CMU(dz));
0967   double rmin1    = _ns.attr<double>(e,_CMU(rMin1));
0968   double rmin2    = _ns.attr<double>(e,_CMU(rMin2));
0969   double rmax1    = _ns.attr<double>(e,_CMU(rMax1));
0970   double rmax2    = _ns.attr<double>(e,_CMU(rMax2));
0971   double startPhi = _ns.attr<double>(e,_CMU(startPhi));
0972   double deltaPhi = _ns.attr<double>(e,_CMU(deltaPhi));
0973   double phi2     = startPhi + deltaPhi;
0974   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0975            "+   Cone:     dz=%8.3f [cm]"
0976            " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
0977            " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
0978            " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
0979            dz, rmin1, rmax1, rmin2, rmax2, startPhi, deltaPhi);
0980   _ns.addSolid(nam, ConeSegment(dz,rmin1,rmax1,rmin2,rmax2,startPhi,phi2));
0981 }
0982 
0983 /// Converter for </> tags
0984 template <> void Converter<shapeless>::operator()(xml_h element) const {
0985   Namespace _ns(_param<ParsingContext>());
0986   xml_dim_t e(element);
0987   string nam = e.nameStr();
0988   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0989            "+   Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Assembly%s", nam.c_str());
0990   _ns.addSolid(nam, Box(1,1,1));
0991 }
0992 
0993 /// Converter for <Box/> tags
0994 template <> void Converter<box>::operator()(xml_h element) const {
0995   Namespace _ns(_param<ParsingContext>());
0996   xml_dim_t e(element);
0997   string nam = e.nameStr();
0998   double dx  = _ns.attr<double>(e,_CMU(dx));
0999   double dy  = _ns.attr<double>(e,_CMU(dy));
1000   double dz  = _ns.attr<double>(e,_CMU(dz));
1001   printout(_ns.context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
1002            "+   Box:      dx=%8.3f [cm] dy=%8.3f [cm] dz=%8.3f [cm]", dx, dy, dz);
1003   _ns.addSolid(nam, Box(dx,dy,dz));
1004 }
1005 
1006 /// Converter for <Box/> tags
1007 template <> void Converter<orb>::operator()(xml_h element) const {
1008   Namespace _ns(_param<ParsingContext>());
1009   xml_dim_t e(element);
1010   string nam = e.nameStr();
1011   double r = _ns.attr<double>(e,_U(radius));
1012   printout(WARNING, "DDCMS",
1013            "+   Orb UNSUPPORTED. %s REPLACED BY BOX:      r=%8.3f [cm]", nam.c_str(), r);
1014   _ns.addSolid(nam, Box(r,r,r));
1015 }
1016 
1017 /// DD4hep specific Converter for <Include/> tags: process only the constants
1018 template <> void Converter<include_load>::operator()(xml_h element) const   {
1019   TString fname = element.attr<string>(_U(ref)).c_str();
1020   const char* path = gSystem->Getenv("DDCMS_XML_PATH");
1021   xml::Document doc;
1022   if ( path && gSystem->FindFile(path,fname) )
1023     doc = xml::DocumentHandler().load(fname.Data());
1024   else
1025     doc = xml::DocumentHandler().load(element, element.attr_value(_U(ref)));
1026   fname = xml::DocumentHandler::system_path(doc.root());
1027   printout(_param<ParsingContext>()->debug.includes ? ALWAYS : DEBUG,
1028            "DDCMS","+++ Processing the CMS detector description %s",fname.Data());
1029   _option<resolve>()->includes.push_back(doc);
1030 }
1031 
1032 /// DD4hep specific Converter for <Include/> tags: process only the constants
1033 template <> void Converter<include_unload>::operator()(xml_h element) const   {
1034   string fname = xml::DocumentHandler::system_path(element);
1035   xml::DocumentHolder(xml_elt_t(element).document()).assign(0);
1036   printout(_param<ParsingContext>()->debug.includes ? ALWAYS : DEBUG,
1037            "DDCMS","+++ Finished processing %s",fname.c_str());
1038 }
1039 
1040 /// DD4hep specific Converter for <Include/> tags: process only the constants
1041 template <> void Converter<include_constants>::operator()(xml_h element) const   {
1042   xml_coll_t(element, _CMU(ConstantsSection)).for_each(Converter<constantssection>(description,param,optional));
1043 }
1044 
1045 namespace {
1046 
1047   //  The meaning of the axis index is the following:
1048   //    for all volumes having shapes like box, trd1, trd2, trap, gtra or para - 1,2,3 means X,Y,Z;
1049   //    for tube, tubs, cone, cons - 1 means Rxy, 2 means phi and 3 means Z;
1050   //    for pcon and pgon - 2 means phi and 3 means Z;
1051   //    for spheres 1 means R and 2 means phi.
1052 
1053   enum class DDAxes { x = 1, y = 2, z = 3, rho = 1, phi = 2, undefined };
1054   const std::map<std::string, DDAxes> axesmap{{"x", DDAxes::x},
1055                                               {"y", DDAxes::y},
1056                                               {"z", DDAxes::z},
1057                                               {"rho", DDAxes::rho},
1058                                               {"phi", DDAxes::phi},
1059                                               {"undefined", DDAxes::undefined}};
1060 }  // namespace
1061 
1062 /// Converter for <Division/> tags
1063 template <>
1064 void Converter<division>::operator()(xml_h element) const {
1065   Namespace _ns(_param<ParsingContext>());
1066   xml_dim_t e(element);
1067   string childName = e.nameStr();
1068   if (strchr(childName.c_str(), NAMESPACE_SEP) == nullptr)
1069     childName = _ns.prepend(childName);
1070 
1071   string parentName = _ns.attr<string>(e, _CMU(parent));
1072   if (strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr)
1073     parentName = _ns.prepend(parentName);
1074   string axis = _ns.attr<string>(e, _CMU(axis));
1075 
1076   // If you divide a tube of 360 degrees the offset displaces
1077   // the starting angle, but you still fill the 360 degrees
1078   double offset = e.hasAttr(_CMU(offset)) ? _ns.attr<double>(e, _CMU(offset)) : 0e0;
1079   double width = e.hasAttr(_CMU(width)) ? _ns.attr<double>(e, _CMU(width)) : 0e0;
1080   int nReplicas = e.hasAttr(_CMU(nReplicas)) ? _ns.attr<int>(e, _CMU(nReplicas)) : 0;
1081 
1082   printout(_ns.context->debug.placements ? ALWAYS : DEBUG,
1083            "DD4CMS",
1084            "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1085            parentName.c_str(),
1086            axis.c_str(),
1087            axesmap.at(axis),
1088            offset,
1089            width,
1090            childName.c_str());
1091 
1092   Volume parent = _ns.volume(parentName);
1093 
1094   const TGeoShape* shape = parent.solid();
1095   TClass* cl = shape->IsA();
1096   if (cl == TGeoTubeSeg::Class()) {
1097     const TGeoTubeSeg* sh = (const TGeoTubeSeg*)shape;
1098     double widthInDeg = convertRadToDeg(width);
1099     double startInDeg = convertRadToDeg(offset);
1100     int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1101 
1102     printout(_ns.context->debug.placements ? ALWAYS : DEBUG,
1103              "DD4CMS",
1104              "+++    ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1105              parent.solid().type(),
1106              axis.c_str(),
1107              axesmap.at(axis),
1108              startInDeg,
1109              widthInDeg,
1110              numCopies);
1111     Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1112 
1113     _ns.context->volumes[childName] = child;
1114     printout(_ns.context->debug.placements ? ALWAYS : DEBUG,
1115              "DD4CMS",
1116              "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1117              e.tag().c_str(),
1118              parentName.c_str(),
1119              parent.isValid() ? "VALID" : "INVALID",
1120              child.name(),
1121              child.isValid() ? "VALID" : "INVALID",
1122              child->IsVolumeMulti() ? "YES" : "NO");
1123   } else if (cl == TGeoTrd1::Class() ) {
1124     double dy = static_cast<const TGeoTrd1*>(shape)->GetDy();
1125     printout(_ns.context->debug.placements ? ALWAYS : DEBUG,
1126              "DD4CMS",
1127              "+++    ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1128              parent.solid().type(),
1129              axis.c_str(),
1130              axesmap.at(axis),
1131              -dy + offset + width,
1132              width,
1133              nReplicas,
1134              dy);
1135 
1136     Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1137 
1138     _ns.context->volumes[childName] = child;
1139     printout(_ns.context->debug.placements ? ALWAYS : DEBUG,
1140              "DD4CMS",
1141              "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1142              e.tag().c_str(),
1143              parentName.c_str(),
1144              parent.isValid() ? "VALID" : "INVALID",
1145              child.name(),
1146              child.isValid() ? "VALID" : "INVALID",
1147              child->IsVolumeMulti() ? "YES" : "NO");
1148   } else {
1149     printout(ERROR, "DD4CMS", "++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1150   }
1151 }
1152 
1153 /// Converter for <Algorithm/> tags
1154 template <> void Converter<algorithm>::operator()(xml_h element) const  {
1155   Namespace _ns(_param<ParsingContext>());
1156   xml_dim_t e(element);
1157   string name = e.nameStr();
1158   if ( _ns.context->disabledAlgs.find(name) != _ns.context->disabledAlgs.end() )   {
1159     printout(INFO,"DDCMS","+++ Skip disabled algorithms: %s",name.c_str());
1160     return;
1161   }
1162   try {
1163     size_t            idx;
1164     SensitiveDetector sd;
1165     string            type = "DDCMS_"+_ns.real_name(name);
1166     while ( (idx=type.find(NAMESPACE_SEP)) != string::npos ) type[idx]='_';
1167 
1168     // SensitiveDetector and Segmentation currently are undefined. Let's keep it like this
1169     // until we found something better.....
1170     printout(_ns.context->debug.algorithms ? ALWAYS : DEBUG,
1171              "DDCMS","+++ Start executing algorithm %s....",type.c_str());
1172     LogDebug context(e.nameStr(),true);
1173     long ret = PluginService::Create<long>(type, &description, _ns.context, &element, &sd);
1174     if ( ret == 1 )    {
1175       printout(_ns.context->debug.algorithms ? ALWAYS : DEBUG,
1176                "DDCMS", "+++ Executed algorithm: %08lX = %s", ret, name.c_str());
1177       return;      
1178     }
1179 #if 0
1180     DetElement det(PluginService::Create<NamedObject*>(type, &description, _ns.context, &element, &sd));
1181     if (det.isValid())   {
1182       // setChildTitles(make_pair(name, det));
1183       if ( sd.isValid() )   {
1184         det->flag |= DetElement::Object::HAVE_SENSITIVE_DETECTOR;
1185       }
1186       if ( seg.isValid() )   {
1187         seg->sensitive = sd;
1188         seg->detector  = det;
1189       }
1190     }
1191     if (!det.isValid())   {
1192       PluginDebug dbg;
1193       PluginService::Create<NamedObject*>(type, &description, _ns.context, &element, &sd);
1194       except("DDCMS","Failed to execute subdetector creation plugin. " + dbg.missingFactory(type));
1195     }
1196     description.addDetector(det);
1197 #endif
1198     ///description.addDetector(det);
1199     printout(ERROR, "DDCMS", "++ FAILED  NOT ADDING SUBDETECTOR %08lX = %s",ret, name.c_str());
1200     return;
1201   }
1202   catch (const exception& exc)   {
1203     printout(ERROR, "DDCMS", "++ FAILED    to convert subdetector: %s: %s", name.c_str(), exc.what());
1204     terminate();
1205   }
1206   catch (...)   {
1207     printout(ERROR, "DDCMS", "++ FAILED    to convert subdetector: %s: %s", name.c_str(), "UNKNONW Exception");
1208     terminate();
1209   }
1210 }
1211 
1212 template <> void Converter<debug>::operator()(xml_h dbg) const {
1213   Namespace _ns(_param<ParsingContext>());
1214   if ( dbg.hasChild(_CMU(debug_visattr))    ) _ns.context->debug.visattr    = true;
1215   if ( dbg.hasChild(_CMU(debug_constants))  ) _ns.context->debug.constants  = true;
1216   if ( dbg.hasChild(_CMU(debug_materials))  ) _ns.context->debug.materials  = true;
1217   if ( dbg.hasChild(_CMU(debug_rotations))  ) _ns.context->debug.rotations  = true;
1218   if ( dbg.hasChild(_CMU(debug_shapes))     ) _ns.context->debug.shapes     = true;
1219   if ( dbg.hasChild(_CMU(debug_volumes))    ) _ns.context->debug.volumes    = true;
1220   if ( dbg.hasChild(_CMU(debug_placements)) ) _ns.context->debug.placements = true;
1221   if ( dbg.hasChild(_CMU(debug_namespaces)) ) _ns.context->debug.namespaces = true;
1222   if ( dbg.hasChild(_CMU(debug_includes))   ) _ns.context->debug.includes   = true;
1223   if ( dbg.hasChild(_CMU(debug_algorithms)) ) _ns.context->debug.algorithms = true;
1224   LogDebug::setDebugAlgorithms(_ns.context->debug.algorithms);
1225 }
1226 
1227 template <> void Converter<resolve>::operator()(xml_h /* element */) const {
1228   ParsingContext* ctx = _param<ParsingContext>();
1229   resolve*        res = _option<resolve>();
1230   Namespace       _ns(ctx);
1231   int count = 0;
1232 
1233   printout(ctx->debug.constants ? ALWAYS : DEBUG,
1234            "DDCMS","+++ RESOLVING %ld unknown constants.....",res->unresolvedConst.size());
1235   while ( !res->unresolvedConst.empty() )   {
1236     for(auto i=res->unresolvedConst.begin(); i!=res->unresolvedConst.end(); ++i )   {
1237       const string& n = (*i).first;
1238       string  rep;
1239       string& v   = (*i).second;
1240       size_t idx, idq;
1241       for(idx=v.find('[',0); idx != string::npos; idx = v.find('[',idx+1) )   {
1242         idq = v.find(']',idx+1);
1243         rep = v.substr(idx+1,idq-idx-1);
1244         auto r = res->allConst.find(rep);
1245         if ( r != res->allConst.end() )  {
1246           rep = "("+(*r).second+")";
1247           v.replace(idx,idq-idx+1,rep);
1248         }
1249       }
1250       if ( v.find(']') == string::npos )  {
1251         if ( v.find("-+") != string::npos || v.find("+-") != string::npos )   {
1252           while ( (idx=v.find("-+")) != string::npos )
1253             v.replace(idx,2,"-");
1254           while ( (idx=v.find("+-")) != string::npos )
1255             v.replace(idx,2,"-");
1256         }
1257         printout(ctx->debug.constants ? ALWAYS : DEBUG,
1258                  "DDCMS","+++ [%06ld] ----------  %-40s = %s",
1259                  res->unresolvedConst.size()-1,n.c_str(),res->originalConst[n].c_str());
1260         _ns.addConstantNS(n, v, "number");
1261         res->unresolvedConst.erase(i);
1262         break;
1263       }
1264     }
1265     if ( ++count > 1000 ) break;
1266   }
1267   if ( !res->unresolvedConst.empty() )   {
1268     for(const auto& e : res->unresolvedConst )
1269       printout(ERROR,"DDCMS","+++ Unresolved constant: %-40s = %s.",e.first.c_str(), e.second.c_str());
1270     except("DDCMS","++ FAILED to resolve %ld constant entries:",res->unresolvedConst.size());
1271   }
1272   res->unresolvedConst.clear();
1273   res->originalConst.clear();
1274   res->allConst.clear();
1275 }
1276 
1277 template <> void Converter<print_xml_doc>::operator()(xml_h element) const {
1278   string fname = xml::DocumentHandler::system_path(element);
1279   printout(_param<ParsingContext>()->debug.includes ? ALWAYS : DEBUG,
1280            "DDCMS","+++ Processing data from: %s",fname.c_str());
1281 }
1282 
1283 /// Converter for <DDDefinition/> tags
1284 static long load_dddefinition(Detector& det, xml_h element) {
1285   xml_elt_t dddef(element);
1286   if ( dddef )    {
1287     static ParsingContext ctxt(&det);
1288     Namespace _ns(ctxt);
1289     string fname = xml::DocumentHandler::system_path(element);
1290     bool open_geometry  = dddef.hasChild(_CMU(open_geometry));
1291     bool close_geometry = dddef.hasChild(_CMU(close_geometry));
1292 
1293     xml_coll_t(dddef, _U(debug)).for_each(Converter<debug>(det,&ctxt));
1294 
1295     // Here we define the order how XML elements are processed.
1296     // Be aware of dependencies. This can only defined once.
1297     // At the end it is a limitation of DOM....
1298     printout(INFO,"DDCMS","+++ Processing the CMS detector description %s",fname.c_str());
1299 
1300     xml::Document doc;
1301     Converter<print_xml_doc> print_doc(det,&ctxt);
1302     try  {
1303       resolve res;
1304       print_doc((doc=dddef.document()).root());
1305       xml_coll_t(dddef, _CMU(DisabledAlgo)).for_each(Converter<disabled_algo>(det,&ctxt,&res));
1306       xml_coll_t(dddef, _CMU(ConstantsSection)).for_each(Converter<constantssection>(det,&ctxt,&res));
1307       xml_coll_t(dddef, _CMU(VisSection)).for_each(Converter<vissection>(det,&ctxt));
1308       xml_coll_t(dddef, _CMU(RotationSection)).for_each(Converter<rotationsection>(det,&ctxt));
1309       xml_coll_t(dddef, _CMU(MaterialSection)).for_each(Converter<materialsection>(det,&ctxt));
1310 
1311       xml_coll_t(dddef, _CMU(IncludeSection)).for_each(_CMU(Include), Converter<include_load>(det,&ctxt,&res));
1312 
1313       for(xml::Document d : res.includes )   {
1314         print_doc((doc=d).root());
1315         Converter<include_constants>(det,&ctxt,&res)((doc=d).root());
1316       }
1317       // Before we continue, we have to resolve all constants NOW!
1318       Converter<resolve>(det,&ctxt,&res)(dddef);
1319       // Now we can process the include files one by one.....
1320       for(xml::Document d : res.includes )   {
1321         print_doc((doc=d).root());
1322         xml_coll_t(d.root(),_CMU(MaterialSection)).for_each(Converter<materialsection>(det,&ctxt));
1323       }
1324       if ( open_geometry )  {
1325         ctxt.geo_inited = true;
1326         det.init();
1327         _ns.addVolume(det.worldVolume());
1328       }
1329       for(xml::Document d : res.includes )  {
1330         print_doc((doc=d).root());
1331         xml_coll_t(d.root(),_CMU(RotationSection)).for_each(Converter<rotationsection>(det,&ctxt));
1332       }
1333       for(xml::Document d : res.includes )  {
1334         print_doc((doc=d).root());
1335         xml_coll_t(d.root(), _CMU(SolidSection)).for_each(Converter<solidsection>(det,&ctxt));
1336       }
1337       for(xml::Document d : res.includes )  {
1338         print_doc((doc=d).root());
1339         xml_coll_t(d.root(), _CMU(LogicalPartSection)).for_each(Converter<logicalpartsection>(det,&ctxt));
1340       }
1341       for(xml::Document d : res.includes )  {
1342         print_doc((doc=d).root());
1343         xml_coll_t(d.root(), _CMU(Algorithm)).for_each(Converter<algorithm>(det,&ctxt));
1344       }
1345       for(xml::Document d : res.includes )  {
1346         print_doc((doc=d).root());
1347         xml_coll_t(d.root(), _CMU(PosPartSection)).for_each(Converter<pospartsection>(det,&ctxt));
1348       }
1349 
1350       /// Unload all XML files after processing
1351       for(xml::Document d : res.includes ) Converter<include_unload>(det,&ctxt,&res)(d.root());
1352 
1353       print_doc((doc=dddef.document()).root());
1354       // Now process the actual geometry items
1355       xml_coll_t(dddef, _CMU(SolidSection)).for_each(Converter<solidsection>(det,&ctxt));
1356       xml_coll_t(dddef, _CMU(LogicalPartSection)).for_each(Converter<logicalpartsection>(det,&ctxt));
1357       xml_coll_t(dddef, _CMU(Algorithm)).for_each(Converter<algorithm>(det,&ctxt));
1358       xml_coll_t(dddef, _CMU(PosPartSection)).for_each(Converter<pospartsection>(det,&ctxt));
1359 
1360     }
1361     catch(const exception& e)   {
1362       printout(ERROR,"DDCMS","Exception while processing xml source:%s",doc.uri().c_str());
1363       printout(ERROR,"DDCMS","----> %s", e.what());
1364       throw;
1365     }
1366 
1367     /// This should be the end of all processing....close the geometry
1368     if ( close_geometry )  {
1369       det.endDocument();
1370     }
1371     printout(INFO,"DDDefinition","+++ Finished processing %s",fname.c_str());
1372     return 1;
1373   }
1374   except("DDDefinition","+++ FAILED to process unknown DOM tree [Invalid Handle]");
1375   return 0;
1376 }
1377 
1378 // Now declare the factory entry for the plugin mechanism
1379 DECLARE_XML_DOC_READER(DDDefinition,load_dddefinition)