Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:52

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 // DDDB is a detector description convention developed by the LHCb experiment.
0015 // For further information concerning the DTD, please see:
0016 // http://lhcb-comp.web.cern.ch/lhcb-comp/Frameworks/DetDesc/Documents/lhcbDtd.pdf
0017 //
0018 //==========================================================================
0019 
0020 // Framework includes
0021 #include "DDDB/DDDBTags.h"
0022 #include "DDDB/DDDBHelper.h"
0023 #include "DDDB/DDDBReader.h"
0024 #include "DDDB/DDDBDimension.h"
0025 #include "DDDB/DDDBConversion.h"
0026 #include "DDDBConfig.h"
0027 
0028 #include "DD4hep/Detector.h"
0029 #include "DD4hep/Path.h"
0030 //#include "DD4hep/DetConditions.h"
0031 #include "DD4hep/ConditionsData.h"
0032 #include "DD4hep/DetectorTools.h"
0033 #include "DD4hep/InstanceCount.h"
0034 #include "DD4hep/detail/ConditionsInterna.h"
0035 
0036 #include "DDCond/ConditionsPool.h"
0037 
0038 // ROOT include files
0039 #include "TGeoManager.h"
0040 
0041 // C/C++ include files
0042 #include <climits>
0043 #include <iostream>
0044 #include <iomanip>
0045 #include <set>
0046 
0047 using namespace std;
0048 using namespace dd4hep;
0049 using namespace dd4hep::DDDB;
0050 
0051 /// Namespace for the AIDA detector description toolkit
0052 namespace dd4hep {
0053 
0054   /// Keep all in here anonymous. Does not have to be visible outside.
0055   namespace  {
0056     static DDDB2Objects::PrintConfig s_config;
0057   }
0058   
0059   /// Access global instance for xml configuration
0060   DDDB2Objects::PrintConfig& DDDB2Objects::PrintConfig::instance()   {
0061     return s_config;
0062   }
0063   
0064   /// Keep all in here anonymous. Does not have to be visible outside.
0065   namespace  {
0066 
0067     struct DDDBDetElem;
0068     typedef detail::ConditionObject GeoCondition;
0069     typedef cond::ConditionsManager ConditionsManager;
0070     typedef cond::ConditionsPool    ConditionsPool;
0071     typedef cond::AbstractMap       AbstractMap;
0072 
0073     /// Helper class to facilitate conversion. Purely local.
0074     struct Context  {
0075       typedef set<string> StringSet;
0076 
0077       Context(Detector& l, DDDB::DDDBHelper* h) : description(l), geo(h->detectorDescription()), helper(h)     {
0078         reader = h->reader<DDDB::DDDBReader>();
0079         print  = s_config;
0080       }
0081       ~Context()  {
0082         //printout(INFO,"Context","Destructor calling....");
0083       }
0084       template <typename T, typename Q> 
0085       static const Q find(const typename std::map<T,Q>& m, const T& match)    {
0086         typename std::map<T,Q>::const_iterator i = m.find(match);
0087         return (i != m.end()) ? (*i).second : 0;
0088       }
0089       template <typename T> void collect(const string& id, T* s);
0090       template <typename T,typename Q> void collect(const string& id, T* s, Q* c);
0091       Detector&   description;
0092       DDDB::dddb*       geo = 0;
0093       DDDB::DDDBHelper* helper = 0;
0094       DDDB::DDDBReader* reader = 0;
0095       typedef std::map<DDDBIsotope*,  TGeoIsotope*>   Isotopes;
0096       typedef std::map<DDDBElement*,  TGeoElement*>   Elements;
0097       typedef std::map<DDDBMaterial*, TGeoMedium*>    Materials;
0098       typedef std::map<DDDBShape*,    TGeoShape*>     Shapes;
0099       typedef std::map<DDDBLogVol*,   TGeoVolume*>    Volumes;
0100       typedef std::map<DDDBPhysVol*,  TGeoNode*>      Placements;
0101       typedef std::map<std::string,   DetElement>     DetectorMap;
0102       typedef std::map<std::string,   TGeoVolume*>    VolumeMap;
0103       typedef std::map<DetElement,    DDDBCatalog*>   DetectorElements;
0104 
0105       Isotopes          isotopes;
0106       Elements          elements;
0107       Materials         materials;
0108       Shapes            shapes;
0109       Volumes           volumes;
0110       VolumeMap         volumePaths;
0111       Placements        placements;
0112       DetElement        detectors;
0113       DetectorMap       catalogPaths;
0114       DetectorElements  detelements;
0115       Volume            lvDummy;
0116       ConditionsManager manager;
0117       const IOVType*    epoch = 0;
0118       DDDB2Objects::PrintConfig  print;
0119       int               unmatched_deltas = 0;
0120       int               delta_conditions = 0;
0121       int               matched_conditions = 0;
0122       int               unmatched_conditions = 0;
0123       int               badassigned_conditions = 0;
0124       bool              conditions_only  = false;
0125 
0126       static PlacedVolume placement(DetElement de)   {
0127         if ( de.isValid() )  {
0128           PlacedVolume p = de.placement();
0129           if ( p.isValid() ) return p;
0130           return placement(de.parent());
0131         }
0132         return PlacedVolume(0);
0133       }
0134       static bool volumePlaced(Volume par_vol, Volume vol)  {
0135         if ( par_vol.isValid() && vol.isValid() && par_vol.ptr() == vol.ptr() )   {
0136           for(int i=0; i < vol->GetNdaughters(); ++i)  {
0137             TGeoNode* dau = vol->GetNode(i);
0138             TGeoVolume* v = dau->GetVolume();
0139             if ( v == vol.ptr() ) return true;
0140           }
0141         }
0142         return false;
0143       }
0144 
0145       TGeoNode* supportPlacement(TGeoVolume* parent, const string& npath)    {
0146         if ( !npath.empty() )   {
0147           size_t idx = npath.find('/');
0148           if ( idx == string::npos )  {
0149             for(int i=0; i<parent->GetNdaughters(); ++i)  {
0150               TGeoNode* dau = parent->GetNode(i);
0151               if ( npath == dau->GetTitle() )   {
0152                 return dau;
0153               }
0154             }
0155             return 0;
0156           }
0157           TGeoNode* dau = supportPlacement(parent, npath.substr(0,idx));
0158           if ( dau )  {
0159             return supportPlacement(dau->GetVolume(), npath.substr(idx+1));
0160           }
0161         }
0162         return 0;
0163       }
0164 
0165       PlacedVolume supportPlacement(DetElement parent, const string& npath)    {
0166         Volume par_vol = parent.volume();
0167         return par_vol.isValid() ? supportPlacement(par_vol.ptr(), npath) : 0;
0168       }
0169     };
0170 
0171     template <typename T> struct CNV : public Converter<T,T*>  {
0172     public:
0173       typedef Converter<T,T*> Base_t;
0174       /// Initializing constructor of the functor with initialization of the user parameter
0175       CNV(Detector& l, void* p, void* o=0) : Converter<T,T*>(l,p,o) {}
0176       template<typename Q> CNV<Q> cnv() const {  return CNV<Q>(this->description,this->param,this->optional);   }
0177       void* convert(T* obj) const;
0178       template<typename Q> Q get(const string& /* obj */) const  {
0179         throw runtime_error("NOT implemented virtual call ! CNV<"+
0180                             typeName(typeid(T))+">::get<"+typeName(typeid(Q))+">(string)");
0181       }
0182       void operator()(T* obj) const   { convert(obj);  }
0183       void operator()(const pair<string,T*>& arg) const  {
0184         Increment<T> incr;
0185         try  {
0186           if ( arg.second )  {
0187             operator()(arg.second);
0188             return;
0189           }
0190           Context* c = (Context*)this->Base_t::param;//_param<Context>();
0191           if ( c && c->reader && c->reader->isBlocked(arg.first) )
0192             return;
0193           printout(INFO,typeName(typeid(T)),"SKIP invalid object: %s",arg.first.c_str());
0194         }
0195         catch(const exception& e)  {
0196           printout(INFO,typeName(typeid(T)),"Failed to convert object: %s",e.what());
0197         }
0198         catch(...)   {
0199           printout(INFO,typeName(typeid(T)),"Failed to convert object.");
0200         }
0201       }
0202     };
0203   }
0204 
0205   namespace {
0206     static UInt_t unique_mat_id = 0xAFFEFEED;
0207 
0208     template <> void* CNV<GeoCondition>::convert(GeoCondition *object) const;
0209     template <> void* CNV<DDDBIsotope>::convert(DDDBIsotope *object) const;
0210     template <> void* CNV<DDDBElement>::convert(DDDBElement *object) const;
0211     template <> void* CNV<DDDBMaterial>::convert(DDDBMaterial *object) const;
0212     template <> void* CNV<DDDBBooleanOperation>::convert(DDDBBooleanOperation *object) const;
0213     template <> void* CNV<DDDBShape>::convert(DDDBShape *object) const;
0214     template <> void* CNV<DDDBDetElem>::convert(DDDBDetElem *object) const;
0215     template <> void* CNV<DDDBLogVol>::convert(DDDBLogVol *object) const;
0216     template <> void* CNV<DDDBCatalog>::convert(DDDBCatalog *object) const;
0217     template <> void* CNV<dddb>::convert(dddb *obj) const;
0218 
0219     template <> template <> Material CNV<DDDBMaterial>::get<Material>(const string& material_name) const;
0220     template <> template <> DDDBLogVol* CNV<DDDBLogVol>::get<DDDBLogVol*>(const string& obj) const;
0221     template <> template <> Volume CNV<DDDBLogVol>::get<Volume>(const string& obj) const;
0222 
0223     /// Convert single condition objects
0224     template <> void* CNV<GeoCondition>::convert(GeoCondition *obj) const   {
0225       if ( obj )   {
0226         typedef IOV::Key _K;
0227         Context*      context = _param<Context>();
0228         Condition        cond = obj;
0229         AbstractMap&        d = cond.get<AbstractMap>();
0230         DDDBDocument*     doc = d.option<DDDBDocument>();
0231         _K::first_type  since = doc->context.valid_since;
0232         _K::second_type until = doc->context.valid_until;
0233         _K iov_key(since,until);
0234         auto e = context->helper->getConditionEntry(obj->value);
0235         /// We automatically convert here alignment deltas to the proper format...
0236         /// This will allow us to re-use all alignment utilities for DDDB.
0237         if ( obj->testFlag(Condition::ALIGNMENT_DELTA) )  {
0238           const pair<string,OpaqueDataBlock>& block = *(d.params.begin());
0239           Delta delta = block.second.get<Delta>();
0240           string typ = obj->type, add = obj->address, val = obj->value;
0241           int flg = obj->flags;
0242           // In-place replacement with Delta condition...
0243           obj->~ConditionObject();
0244           new(obj) Condition::Object(e.second,typ);
0245           cond.setFlag(flg);
0246           cond->address = add;
0247           cond->value   = val;
0248           cond.bind<Delta>() = delta;
0249           ++context->delta_conditions;
0250           if ( !e.first.isValid() )
0251             ++context->unmatched_deltas;
0252         }
0253         if ( e.first.isValid() )  {
0254           cond->SetName(e.second.c_str());
0255           cond->hash = ConditionKey::KeyMaker(e.first.key(),detail::hash32(cond.name())).hash;
0256           printout(DEBUG,"DDDB","Insert condition: %s # %s --> %16llX",
0257                    e.first.path().c_str(),cond.name(),cond.key());
0258           printout(DEBUG,"DDDB","       %s -> %s",cond->value.c_str(),cond->address.c_str());
0259           ++context->matched_conditions;
0260         }
0261         else   {
0262           //printout(WARNING,"DDDB","Cannot match condition %s to detector element!",cond.name());
0263           //printout(WARNING,"DDDB","      %s -> %s",obj->value.c_str(),obj->address.c_str());
0264           ++context->unmatched_conditions;
0265         }
0266         ConditionsPool* pool = context->manager.registerIOV(*(context->epoch), iov_key);
0267         context->manager.registerUnlocked(*pool, cond);
0268         //context->manager.registerKey(cond->hash, cond->name);
0269       }
0270       return obj;
0271     }
0272 
0273     /// Convert single isotope objects
0274     template <> void* CNV<DDDBIsotope>::convert(DDDBIsotope *o) const    {
0275       Context* context = _param<Context>();
0276       TGeoIsotope* iso = Context::find(context->isotopes, o);
0277       if ( !iso )  {
0278         iso = TGeoIsotope::FindIsotope(o->c_name());
0279         if ( !iso ) iso = new TGeoIsotope(o->c_name(),o->Z,o->A,o->density);
0280         context->isotopes.insert(make_pair(o,iso));
0281         if ( context->print.materials ) dddb_print(iso);
0282       }
0283       return iso;
0284     }
0285 
0286     /// Convert single element objects
0287     TGeoElement* createElement(const char* nam, Context* context, DDDBElement *o)   {
0288       TGeoElementTable* t = TGeoElement::GetElementTable();
0289       TGeoElement* e = t->FindElement(nam);
0290       if ( !e )  {
0291         size_t iso_count = 0;
0292         for(auto i = o->isotopes.begin(); i != o->isotopes.end(); ++i) ++iso_count;
0293         if ( 0 == iso_count )
0294           e = new TGeoElement(nam,o->symbol.c_str(),o->atom.Zeff,o->atom.A,o->density);
0295         else
0296           e = new TGeoElement(nam,o->symbol.c_str(), iso_count);
0297         /// Add the isotopes to the element
0298         for(auto i = o->isotopes.begin(); i != o->isotopes.end(); ++i)  {
0299           auto iso = context->geo->isotopes.find((*i).first);
0300           if ( iso == context->geo->isotopes.end() )  {
0301             printout(ERROR,"DDDB","++ Invalid isotope: %s [Ignore Isotope]",(*i).first.c_str());
0302             continue;
0303           }
0304           DDDBIsotope* isotope = (*iso).second;
0305           TGeoIsotope* geo_iso = 
0306             (TGeoIsotope*)CNV<DDDBIsotope>(context->description,context).convert(isotope);
0307           if ( !geo_iso )  {
0308             printout(ERROR,"DDDB","++ Invalid isotope: %s [Ignore Isotope]",(*iso).first.c_str());
0309             continue;
0310           }
0311           e->AddIsotope(geo_iso, (*i).second);
0312         }
0313         t->AddElement(e);
0314         e = t->FindElement(nam);
0315         if ( !e ) {
0316           except("Cnv<Element>","Failed to insert Element: %s into table!", nam);
0317           return 0;
0318         }
0319         if ( context->print.materials ) dddb_print(e);
0320       }
0321       DDDBMaterial* material = Context::find(context->geo->materials,string(nam));
0322       if ( !material )  {
0323         TGeoManager& mgr = context->description.manager();
0324         if ( !mgr.GetMaterial(nam) || !mgr.GetMedium(nam) )  {
0325           DDDBMaterialComponent comp;
0326           material          = new DDDBMaterial;
0327           material->name    = nam;
0328           material->density = o->density;
0329           comp.name         = nam;
0330           comp.fractionmass = 1.0;
0331           material->components.push_back(comp);
0332           context->geo->materials.insert(make_pair(nam,material));
0333           CNV<DDDBMaterial>(context->description,context)(material);
0334         }
0335       }
0336       return e;
0337     }
0338 
0339     /// Convert single element objects and the counterpart using the full name
0340     template <> void* CNV<DDDBElement>::convert(DDDBElement *object) const    {
0341       Context* context = _param<Context>();
0342       TGeoElement* e = Context::find(context->elements, object);
0343       if ( !e )  {
0344         e = createElement(object->c_name(), context, object);
0345         context->elements.insert(make_pair(object,e));
0346         if ( !object->symbol.empty() && object->symbol != object->name )  {
0347           DDDBElement* esym = Context::find(context->geo->elements, object->symbol);
0348           if ( !esym )  {
0349             esym = new DDDBElement(*object);
0350             esym->name = object->symbol;
0351             context->geo->elements.insert(make_pair(object->symbol,esym));
0352           }
0353           TGeoElement* es = Context::find(context->elements, esym);
0354           if ( !es )  {
0355             es = createElement(esym->c_name(), context, esym);
0356             context->elements.insert(make_pair(esym, es));
0357           }
0358         }
0359       }
0360       return e;
0361     }
0362 
0363     /// Convert single material objects
0364     template <> void* CNV<DDDBMaterial>::convert(DDDBMaterial *object) const    {
0365       Context* context = _param<Context>();
0366       TGeoMedium* medium = Context::find(context->materials, object);
0367       if ( !medium )  {
0368         const char*      name = object->c_name();
0369         TGeoManager&      mgr = description.manager();
0370         TGeoElementTable* tab = TGeoElement::GetElementTable();
0371         TGeoMaterial*     mat = mgr.GetMaterial(name);
0372         TGeoMixture*      mix = dynamic_cast<TGeoMixture*>(mat);
0373 
0374         medium = mgr.GetMedium(name);
0375         if ( 0 == mat )  {
0376           DDDBMaterial::Components& comp = object->components;
0377           //printout(INFO, "Cnv<Material>", "++ Converting material %s", name);
0378           mat = mix = new TGeoMixture(name, comp.size(), object->density);
0379           if ( object->radlen > 0 && object->lambda > 0 )
0380             mat->SetRadLen(object->radlen, object->lambda);
0381           else if ( object->radlen > 0 )
0382             mat->SetRadLen(object->radlen);
0383           if ( object->pressure > 0 )
0384             mat->SetPressure(object->pressure);
0385           if ( object->temperature > 0 )
0386             mat->SetTemperature(object->temperature);
0387           for(auto i = comp.begin(); i != comp.end(); ++i)  {
0388             DDDBMaterialComponent& c=(*i);
0389             TGeoElement* e = tab->FindElement(c.c_name());
0390             if ( e && c.natoms>0 )  {  // Add simple elements using atomic numbers
0391               mix->AddElement(e, c.natoms);
0392               continue;
0393             }
0394             else if ( e && c.fractionmass >= 0 )  { // Add other mixtures using fractional weights
0395               mix->AddElement(e, c.fractionmass);
0396               continue;
0397             }
0398             else if ( c.fractionmass >= 0 )  {
0399               Material mm = this->get<Material>(c.name);
0400               mix->AddElement(mm->GetMaterial(), c.fractionmass);
0401               continue;
0402             }
0403           }
0404         }
0405         // Now create the medium
0406         if (0 == medium) {
0407           --unique_mat_id;
0408           medium = new TGeoMedium(name, unique_mat_id, mat);
0409           medium->SetTitle("material");
0410           medium->SetUniqueID(unique_mat_id);
0411         }
0412         context->materials.insert(make_pair(object,medium));
0413         if ( context->print.materials ) dddb_print(medium);
0414       }
0415       return medium;
0416     }
0417 
0418     /// Access/on the fly convert material objects by name
0419     template <> template <>
0420     Material CNV<DDDBMaterial>::get<Material>(const string& material_name)  const {
0421       Context* context = _param<Context>();
0422       TGeoManager& mgr = description.manager();
0423       TGeoMedium*   gmed = mgr.GetMedium(material_name.c_str());
0424       if ( gmed )   {
0425         return Material(gmed);
0426       }
0427       TGeoMaterial* gmat = mgr.GetMaterial(material_name.c_str());
0428       if ( gmat )   {
0429         --unique_mat_id;
0430         gmed = new TGeoMedium(material_name.c_str(), unique_mat_id, gmat);
0431         gmed->SetTitle("material");
0432         gmed->SetUniqueID(unique_mat_id);
0433         if ( context->print.materials ) dddb_print(gmed);
0434         return Material(gmed);
0435       }
0436       DDDBMaterial* mat = Context::find(context->geo->materials,material_name);
0437       if ( !mat )  {
0438         string mat_name = material_name; // HACK! for bad material names in IT
0439         size_t idx;
0440         if ( mat_name.empty() )
0441           mat_name = "Air";
0442         else if ( (idx=mat_name.rfind('/')) != string::npos ) {
0443           mat_name = mat_name.substr(idx+1);
0444         }
0445         mat = Context::find(context->geo->materials,mat_name);
0446       }
0447       if ( !mat )  {
0448         if ( context->print.materials )   {
0449           printout(ERROR,"Cnv<Material>",
0450                    "++  Failed to find component material: %s "
0451                    "---> Material table dump.", material_name.c_str());
0452           for(auto im=context->geo->materials.begin(); im != context->geo->materials.end(); ++im)
0453             dddb_print((*im).second);
0454         }
0455         except("Materials","++ Undefined material %s",material_name.c_str());
0456       }
0457       TGeoMedium* medium = (TGeoMedium*)CNV<DDDBMaterial>(context->description,context).convert(mat);
0458       return Material(medium);
0459     }
0460 
0461     /// Convert shape entities
0462     template <> void* CNV<DDDBShape>::convert(DDDBShape *object) const    {
0463       Context* context = _param<Context>();
0464       Solid shape = Context::find(context->shapes, object);
0465       if ( !shape )  {
0466         if ( object->id == "/dd/Geometry/LHCb/lvLHCb" )  {
0467           shape = description.worldVolume().solid();
0468         }
0469         else if ( object->type == DDDBAssembly::type() )  {
0470           except("Cnv<Shape>","++ Assembly shapes cannot be converted!");
0471         }
0472         else if ( object->type == DDDBBox::type() )  {
0473           shape = Box(object->s.box.x, object->s.box.y, object->s.box.z).ptr();
0474         }
0475         else if ( object->type == DDDBCons::type() )  {
0476           const DDDBCons& c = object->s.cons;
0477           shape = Cone(c.sizeZ, 
0478                                  c.innerRadiusMZ, c.outerRadiusMZ,
0479                                  c.innerRadiusPZ, c.outerRadiusPZ).ptr();
0480         }
0481         else if ( object->type == DDDBConeSegment::type() )  {
0482           const DDDBConeSegment& o = object->s.coneSegment;
0483           shape = ConeSegment(o.sizeZ, 
0484                                         o.innerRadiusMZ, o.outerRadiusMZ,
0485                                         o.innerRadiusPZ, o.outerRadiusPZ,
0486                                         o.start, o.delta).ptr();
0487         }
0488         else if ( object->type == DDDBEllipticalTube::type() )  {
0489           const DDDBEllipticalTube& o = object->s.ellipticalTube;
0490           shape = EllipticalTube(o.a, o.b, o.dz).ptr();
0491         }
0492         else if ( object->type == DDDBTubs::type() )  {
0493           const DDDBTubs& t = object->s.tubs;
0494           shape = Tube(t.innerRadius, t.outerRadius, t.sizeZ, t.start, t.delta);
0495         }
0496         else if ( object->type == DDDBPolycone::type() )  {
0497           DDDBPolycone& o = object->s.polycone;
0498           TGeoPcon* pc = new TGeoPcon(o.start, o.delta, object->zplanes.size());
0499           for(size_t iz=0; iz< object->zplanes.size(); ++iz)  {
0500             const DDDBZPlane& plane = object->zplanes[iz];
0501             pc->DefineSection(iz, plane.z, plane.innerRadius, plane.outerRadius);
0502           }
0503           shape = pc;
0504         }
0505         else if ( object->type == DDDBPolygon::type() )  {
0506           DDDBPolygon& o = object->s.polygon;
0507           shape = PolyhedraRegular(o.nsides, o.start, o.innerRadius, o.outerRadius, o.z);
0508         }
0509         else if ( object->type == DDDBSphere::type() )  {
0510           const DDDBSphere& o = object->s.sphere;
0511           shape = Sphere(o.rmin, o.rmax, o.theta, o.theta+o.delta_theta, o.phi, o.phi+o.delta_phi);
0512         }
0513         //else if ( object->type == Ellipsoid::type() )  {
0514         //  const Ellipsoid& o = object->s.ellipsoid;
0515         //  shape = Ellipsoid(o.rlow, o.rhigh, o.dz).ptr();
0516         //}
0517         else if ( object->type == DDDBParaboloid::type() )  {
0518           const DDDBParaboloid& o = object->s.paraboloid;
0519           shape = Paraboloid(o.rlow, o.rhigh, o.dz).ptr();
0520         }
0521         else if ( object->type == DDDBHyperboloid::type() )  {
0522           const DDDBHyperboloid& o = object->s.hyperboloid;
0523           shape = Hyperboloid(o.rmin, o.rmax, o.stIn, o.stOut, o.dz).ptr();
0524         }
0525         else if ( object->type == DDDBTRD::type() )  {
0526           const DDDBTRD& o = object->s.trd;
0527           shape = Trapezoid(o.x1, o.x2, o.y1, o.y2, o.z).ptr();
0528         }
0529         else if ( object->type == DDDBTrap::type() )  {
0530           const DDDBTrap& o = object->s.trap;
0531           shape = Trap(o.dz, o.theta, o.phi,
0532                                  o.h1, o.bl1, o.tl1, o.alpha1, 
0533                                  o.h2, o.bl2, o.tl2, o.alpha2);
0534         }
0535         else if ( object->type == DDDBBooleanUnion::type() ||
0536                   object->type == DDDBBooleanSubtraction::type() ||
0537                   object->type == DDDBBooleanIntersection::type() )   {
0538           shape = context->lvDummy.solid();
0539           DDDBShape::Operations::const_iterator i;
0540           DDDBShape*   left_shape = object->s.boolean.first;
0541           Solid left_solid = (TGeoShape*)convert(left_shape);
0542           if ( !left_solid.isValid() )  { // Error ....
0543             except("Cnv<Shape>","++ %s: Unknown left boolean shape creation:%s -> %d",
0544                    object->c_name(), left_shape->c_name(), left_shape->type);
0545           }
0546           shape = left_solid;
0547           for(i=object->boolean_ops.begin(); i != object->boolean_ops.end(); ++i)  {
0548             DDDBShape* right_shape = (*i).shape;
0549             Solid right_solid = (TGeoShape*)convert(right_shape);
0550             const Transform3D& trafo = (*i).trafo;
0551             if ( !right_solid.isValid() )  { // Error ....
0552               except("Cnv<Shape>","++ %s: Unknown right boolean shape creation:%s -> %d",
0553                      object->c_name(), right_shape->c_name(), right_shape->type);
0554             }
0555             shape = Solid();
0556             if ( object->type == DDDBBooleanUnion::type() )
0557               shape = UnionSolid(left_solid, right_solid, trafo);
0558             else if ( object->type == DDDBBooleanSubtraction::type() )
0559               shape = SubtractionSolid(left_solid, right_solid, trafo);
0560             else if ( object->type == DDDBBooleanIntersection::type() )
0561               shape = IntersectionSolid(left_solid, right_solid, trafo);
0562             if ( !shape.isValid() )  {
0563               except("Cnv<Shape>","++ %s: Unknown boolean shape creation:%d",
0564                      object->c_name(), object->type);
0565             }
0566             left_solid = shape;
0567           }
0568         }
0569         if ( !shape )  {
0570           except("Cnv<Shape>","++ Undefined shape conversion %s [id:%d]",
0571                  object->c_id(), object->type);
0572         }
0573         shape->SetTitle(object->path.c_str());
0574         if ( context->print.shapes )  {
0575           printout(INFO,"Cnv<Shape>","++ Converted shape: %s",object->c_id());
0576         }
0577         context->shapes.insert(make_pair(object, shape));
0578       }
0579       return shape;
0580     }
0581 
0582     inline PlacedVolume place_daughter(const char* pv, Volume mother, Volume daughter, const Transform3D& tr)  {
0583       PlacedVolume place = mother.placeVolume(daughter, tr);
0584       // Use title for user defined physical volume name, since TGeo sets already the name!
0585       place->SetTitle(pv);
0586       return place;
0587     }
0588 
0589     inline void __check_physvol_instances__(int n)   {
0590       if ( n <= 0 )  {
0591         printout(WARNING,"Cnv<PhysVol>","++ Invalid replication constant in ParamPhysVolXD:%d",n);
0592       }
0593     }
0594 
0595     /// Convert logical volumes
0596     template <> void* CNV<DDDBLogVol>::convert(DDDBLogVol *object) const    {
0597       struct VolumeDepth {};
0598       Increment<VolumeDepth> depth;
0599       Context* context = _param<Context>();
0600       Volume mother = Context::find(context->volumes, object);
0601 
0602       if ( !mother.isValid() )  {
0603         if ( depth.counter() >= context->print.max_volume_depth )   {
0604           mother = context->lvDummy;
0605           context->volumes.insert(make_pair(object, mother.ptr()));
0606           context->volumePaths[object->path] = mother.ptr();
0607           printout(WARNING,"Cnv<LogVol>","++ Ignore placements below level:%d -> %s",
0608                    depth.counter(), object->path.c_str());
0609           return mother;
0610         }
0611         DDDBShape* shape = Context::find(context->geo->shapes,object->shape);
0612         if ( object->shape.empty() || shape->type == DDDBAssembly::type() )  {
0613           mother = Assembly(object->name);
0614         }
0615         else  {
0616           Solid s = (TGeoShape*)cnv<DDDBShape>().convert(shape);
0617           if ( s.isValid() )   {
0618             Material m = cnv<DDDBMaterial>().get<Material>(object->material);
0619             mother = Volume(object->name, s, m);
0620           }
0621         }
0622         mother->SetTitle(object->path.c_str());
0623         VisAttr vis = context->helper->visAttr(object->path);
0624         if ( vis.isValid() )  {
0625           if ( context->print.vis )  {
0626             printout(INFO,"Cnv<LogVol>","++ Vol:%s  Vis:%s",mother->GetTitle(), vis.name());
0627           }
0628           mother.setVisAttributes(vis);
0629         }
0630         else   {
0631           mother->SetVisibility(kTRUE);
0632           mother->SetVisLeaves(kTRUE);
0633           mother->SetVisContainers(kTRUE);
0634           mother->SetFillColor(kRed);
0635         }
0636         context->volumes.insert(make_pair(object, mother.ptr()));
0637         context->volumePaths[object->path] = mother.ptr();
0638         // Now place all daughter volumes
0639         for(auto i=object->physvols.begin(); i!=object->physvols.end(); ++i)  {
0640           DDDBPhysVol* pv = *i;
0641           PlacedVolume place = context->find(context->placements, pv);
0642           if ( !place.isValid() )  {
0643             Volume daughter = this->get<Volume>(pv->logvol);
0644             if ( !daughter.isValid() )  {
0645               if ( context->reader && context->reader->isBlocked(pv->c_id()) )
0646                 continue;
0647               printout(WARNING,"Cnv<PhysVol>","++ Failed to convert placement: %s."
0648                        " Unknown daughter vol:%s.",pv->c_id(), pv->logvol.c_str());
0649               continue;
0650             }
0651             int num_places = 0;
0652             const char* pv_name = pv->name.c_str();
0653             switch(pv->type)   {
0654             case DDDBPhysVol::PHYSVOL_REGULAR:   {
0655               place = place_daughter(pv_name, mother, daughter, pv->trafo);
0656               num_places = 1;
0657               break;
0658             }
0659             case DDDBPhysVol::PHYSVOL_PARAM1D:   {
0660               DDDBParamPhysVol* pDim = (DDDBParamPhysVol*)pv;
0661               Transform3D   tr;
0662               Position      pos1, p1;
0663               RotationZYX   rot1, r1;
0664               pDim->trafo1.GetDecomposition(r1,p1);
0665               pDim->trafo.GetDecomposition(rot1,pos1);
0666               __check_physvol_instances__(pDim->number1);
0667               for(int k=0; k<pDim->number1; ++k)   {
0668                 pos1 += p1;
0669                 rot1 *= r1;
0670                 tr    = Transform3D(rot1, pos1);
0671                 place = place_daughter(pv_name, mother, daughter, tr);
0672                 ++num_places;
0673               }
0674               break;
0675             }
0676             case DDDBPhysVol::PHYSVOL_PARAM2D:  {
0677               DDDBParamPhysVol2D* pDim = (DDDBParamPhysVol2D*)pv;
0678               Position        pos1, pos2, p1, p2;
0679               RotationZYX     rot1, rot2, r1, r2;
0680               Transform3D     tr;
0681               __check_physvol_instances__(pDim->number1);
0682               __check_physvol_instances__(pDim->number2);
0683               pDim->trafo1.GetDecomposition(r1, p1);
0684               pDim->trafo2.GetDecomposition(r2, p2);
0685               pDim->trafo.GetDecomposition(rot1,pos1);
0686               for(int k=0; k < pDim->number1; ++k)   {
0687                 pos1 += p1;
0688                 rot1 *= r1;
0689                 pos2  = pos1;
0690                 rot2  = rot1;
0691                 for(int l=0; l < pDim->number2; ++l)   {
0692                   pos2 += p2;
0693                   rot2 *= r2;
0694                   tr    = Transform3D(rot2, pos2);
0695                   place = place_daughter(pv_name, mother, daughter, tr);
0696                   ++num_places;
0697                 }
0698               }
0699               break;
0700             }
0701             case DDDBPhysVol::PHYSVOL_PARAM3D:  {
0702               DDDBParamPhysVol3D* pDim = (DDDBParamPhysVol3D*)pv;
0703               Position        pos1, pos2, pos3, p1, p2, p3;
0704               RotationZYX     rot1, rot2, rot3, r1, r2, r3;
0705               Transform3D     tr;
0706               __check_physvol_instances__(pDim->number1);
0707               __check_physvol_instances__(pDim->number2);
0708               __check_physvol_instances__(pDim->number3);
0709               pDim->trafo1.GetDecomposition(r1, p1);
0710               pDim->trafo2.GetDecomposition(r2, p2);
0711               pDim->trafo2.GetDecomposition(r3, p3);
0712               pDim->trafo.GetDecomposition(rot1,pos1);
0713               for(int k=0; k < pDim->number1; ++k)   {
0714                 pos1 += p1;
0715                 rot1 *= r1;
0716                 pos2  = pos1;
0717                 rot2  = rot1;
0718                 for(int l=0; l < pDim->number2; ++l)   {
0719                   pos2 += p2;
0720                   rot2 *= r2;
0721                   pos3  = pos2;
0722                   rot3  = rot2;
0723                   for(int m=0; m < pDim->number3; ++m)   {
0724                     pos3 += p3;
0725                     rot3 *= r3;
0726                     tr    = Transform3D(rot3, pos3);
0727                     place = place_daughter(pv_name, mother, daughter, tr);
0728                     ++num_places;
0729                   }
0730                 }
0731               }
0732               break;
0733             }
0734             default:
0735               printout(ERROR,"Cnv<PhysVol>","++ \tUnknown ParamPhysVol type: %d",pv->type);
0736               break;
0737             }
0738             context->placements.insert(make_pair(pv, place.ptr()));
0739             if ( context->print.physvol )    {
0740               Position pos;
0741               pv->trafo.GetTranslation(pos);
0742               printout(INFO,"Cnv<PhysVol>","++ Converted physVol: depth:%d typ:%d places:%d [%p lv:%p] %s",
0743                        depth.counter(), pv->type, num_places, (void*)place.ptr(), (void*)daughter.ptr(), 
0744                        mother->GetTitle());
0745               printout(INFO,"Cnv<PhysVol>","++ \tPosition: x=%f y=%f z=%f %p -> %s",
0746                        pos.X(), pos.Y(), pos.Z(), (void*)pv, pv->c_name());
0747             }
0748           }
0749         }
0750         if ( context->print.logvol )  {
0751           printout(INFO,"Cnv<LogVol>","++ Converted   logVol: [%p -> %p] %s NDau:%d",
0752                    (void*)object, (void*)mother.ptr(), object->path.c_str(),
0753                    mother->GetNdaughters());
0754         }
0755       }
0756       return mother.ptr();
0757     }
0758 
0759     /// Access logical volumes from string name
0760     template <> template <> 
0761     DDDBLogVol* CNV<DDDBLogVol>::get<DDDBLogVol*>(const string& nam) const    {
0762       Context* context = _param<Context>();
0763       DDDBLogVol* lv = Context::find(context->geo->volumes,nam);
0764       if ( lv )  {
0765         return lv;
0766       }
0767       lv = Context::find(context->geo->volumePaths,nam);
0768       if ( lv )  {
0769         return lv;
0770       }
0771       pair<const DDDBCatalog*,string> cat = context->geo->geometry->parent(nam);
0772       if ( cat.first )  {
0773         const DDDBCatalog* c = cat.first;
0774         dddb::Volumes::const_iterator iv = c->logvols.find(cat.second);
0775         if ( iv != c->logvols.end() )  {
0776           lv = (*iv).second;
0777           return lv;
0778         }
0779 #if 0
0780         for(iv = c->logvols.begin(); iv != c->logvols.end(); ++iv)
0781           printout(WARNING,"Cnv<LogVol>","++ %s --volume--> %s",
0782                    c->id.c_str(), (*iv).second->name.c_str());
0783 #endif
0784       }
0785       printout(WARNING,"Cnv<LogVol>","++ Undefined logical volume: %s", nam.c_str());
0786       return 0;
0787     }
0788 
0789     /// Convert logical volumes from string
0790     template <> template <> 
0791     Volume CNV<DDDBLogVol>::get<Volume>(const string& nam) const    {
0792       DDDBLogVol* lv = this->get<DDDBLogVol*>(nam);
0793       if ( lv )  {
0794         return (TGeoVolume*)this->convert(lv);
0795       }
0796       return Volume(0);
0797     }
0798 
0799     template <> void* CNV<DDDBCatalog>::convert(DDDBCatalog *object) const    {
0800       Context* context = _param<Context>();
0801       dddb*    geo     = context->geo;
0802       Context::DetectorMap::const_iterator j=context->catalogPaths.find(object->path);
0803       if ( j != context->catalogPaths.end() )  {
0804         return (*j).second.ptr();
0805       }
0806       Volume  vol;
0807       DDDBCatalog*   support = 0;
0808       DetElement det, parent_element;
0809       if ( context->print.detelem )  {
0810         printout(INFO,"CNV<Catalog>","++ Starting catalog %p %s [cref:%d/%d lref:%d/%d lv:%s sup:%s np:%s] Cond:%s ",
0811                  (void*)object,
0812                  object->path.c_str(),
0813                  int(object->catalogrefs.size()),
0814                  int(object->catalogs.size()),
0815                  int(object->logvolrefs.size()),
0816                  int(object->logvols.size()),
0817                  object->logvol.empty()  ? "--" : object->logvol.c_str(),
0818                  object->support.empty() ? "--" : object->support.c_str(),
0819                  object->npath.empty()   ? "--" : object->npath.c_str(),
0820                  object->condition.c_str());
0821       }
0822       if ( object->path == "/dd/Structure" )  {
0823         const DDDBBox& o = geo->world;
0824         printout(WARNING,"World","World: %g %g %g",o.x,o.y,o.z);
0825         _toDictionary("world_x",_toString(o.x));
0826         _toDictionary("world_y",_toString(o.y));
0827         _toDictionary("world_z",_toString(o.z));
0828         description.init();
0829         det = description.world();
0830         vol = description.worldVolume();
0831         context->detectors = det;
0832       }
0833       else if ( object->path.find("/dd/TrackfitGeometry") == 0 )  {
0834         return 0;
0835       }
0836       else if ( object->path.find("/dd/Geometry") == 0 )  {
0837         context->catalogPaths[object->path] = det;
0838       }
0839       else if ( object->path.find("/dd/Structure") == 0 )  {
0840         det = DetElement(object->name,object->type,0);
0841         det.addExtension<DDDBCatalog>(object->addRef());
0842         if ( !object->support.empty() )  {
0843           try  {
0844             j = context->catalogPaths.find(object->support);
0845             if ( j != context->catalogPaths.end() )  {
0846               parent_element = (*j).second;
0847               parent_element.add(det);
0848             }
0849             else  {
0850               dddb::Catalogs::const_iterator i=geo->catalogPaths.find(object->support);
0851               if ( i != geo->catalogPaths.end() )  {
0852                 support = (*i).second;
0853                 parent_element = (DetElement::Object*)this->convert(support);
0854                 parent_element.add(det);
0855               }
0856               else  {
0857                 pair<const DDDBCatalog*,string> cat = context->geo->structure->parent(object->support);
0858                 if ( cat.first )  {
0859                   const DDDBCatalog* c = cat.first;
0860                   dddb::Catalogs::const_iterator icc = c->catalogs.find(cat.second);
0861                   if ( icc != c->catalogs.end() )  {
0862                     support = (*icc).second;
0863                     parent_element = (DetElement::Object*)this->convert(support);
0864                     parent_element.add(det);
0865                   }
0866                 }
0867               }
0868             }
0869           }
0870           catch(const std::exception& e)   {
0871             printout(ERROR,"CNV<DetElem>","++ EXCEPTION: %s",e.what());
0872           }
0873         }
0874         if ( !parent_element.isValid() )   {
0875           printout(ERROR,"CNV<DetElem>","++ Unknown parent: %s",object->support.c_str());
0876         }
0877       }
0878       // Deal with true detector elements from /dd/Structure
0879       if ( det.isValid() )  { 
0880         if ( !object->logvol.empty() )  {
0881           CNV<DDDBLogVol> conv(description,param);
0882           // Convert the logical volume, so that all daughters are present!
0883           vol = conv.get<Volume>(object->logvol);
0884           //printout(INFO,"CNV<DetElem>","++ Set Placement: %s :  %s -> %s",
0885           //         object->path.c_str(), object->logvol.c_str(), object->npath.c_str());
0886           if ( !object->npath.empty() )  {
0887             PlacedVolume place = context->supportPlacement(parent_element, object->npath);
0888             if ( !place.isValid() )   {
0889               printout(WARNING,"CNV<DetElem>","++ %s Placement: %s",
0890                        object->path.c_str(), object->logvol.c_str());
0891               printout(WARNING,"CNV<DetElem>",
0892                "++     --> INVALID PLACEMENT... Vol.N-path: %s",
0893                        object->npath.c_str());
0894             }
0895             else   {
0896               det.setPlacement(place);
0897             }
0898           }
0899           else    {
0900             PlacedVolume par_place = context->placement(parent_element);
0901             Volume    par_vol   = par_place.volume();
0902             if ( context->volumePlaced(par_vol, vol) )  {
0903               printout(WARNING,"CNV<DetElem>","++ %s : Volume already placed %s -> %s",
0904                        det.path().c_str(), par_vol->GetTitle(), vol->GetTitle());
0905             }
0906             PlacedVolume det_place = par_vol.placeVolume(vol);
0907             det.setPlacement(det_place);
0908           }
0909         }
0910         if ( !det.placement().isValid() )  {
0911           //printout(ERROR,"CNV<DetElem>","++  DetElement %s has no placement!",det.path().c_str());
0912         }
0913       }
0914       if ( det.isValid() )  {
0915         context->detelements[det] = object;
0916         context->catalogPaths[object->path] = det;
0917       }
0918       for_each(object->logvolrefs.begin(), object->logvolrefs.end(), CNV<DDDBLogVol>(description,param,det.ptr()));
0919       for_each(object->catalogrefs.begin(), object->catalogrefs.end(), *this);
0920 
0921 #if 0
0922       for(DDDBCatalog::LvRefs::const_iterator i=object->logvolrefs.begin(); i!=object->logvolrefs.end(); ++i)   {
0923         DDDBLogVol* lv = (*i).second;
0924         string  lp = object->path+"/"+lv->name;
0925         Volume gv = Context::find(context->volumes, lv);
0926         context->volumePaths[lp] = gv.ptr();
0927       }
0928 #endif
0929       /// Attach conditions keys to the detector element if present
0930       if ( !object->condition.empty() )   {
0931         bool res;
0932         char text[64];
0933         ::snprintf(text,sizeof(text),"              %%%lds -> %%s",long(object->condition.length()));
0934         printout(DEBUG,"DDDB","+ Match Align %s -> %s",object->condition.c_str(), object->path.c_str());
0935         printout(DEBUG,"DDDB",text,"",det.path().c_str());
0936         res = context->helper->addConditionEntry(object->condition,det,align::Keys::deltaName);
0937         if ( !res )  {
0938           printout(DEBUG,"DDDB","++ Conditions entry with key:%s already exists!",
0939                    object->condition.c_str());
0940           ++context->badassigned_conditions;
0941         }
0942       }
0943       if ( !object->conditioninfo.empty() )  {
0944         bool res;
0945         for( const auto& i : object->conditioninfo )   {
0946           printout(DEBUG,"DDDB","+ Match Cond  %s -> %s",i.second.c_str(), object->path.c_str());
0947           res = context->helper->addConditionEntry(i.second, det, i.first);
0948           if ( !res )  {
0949             printout(DEBUG,"DDDB","++ Conditions entry with key:%s already exists!",
0950                      i.second.c_str());
0951             ++context->badassigned_conditions;
0952           }
0953         }
0954       }
0955       if ( context->print.detelem )  {
0956         printout(INFO,"CNV<Catalog>","++ Converting catalog %p -> %p [cref:%d/%d lref:%d/%d lv:%s [%p] sup:%s np:%s] %s ",
0957                  (void*)object, det.ptr(),
0958                  int(object->catalogrefs.size()),
0959                  int(object->catalogs.size()),
0960                  int(object->logvolrefs.size()),
0961                  int(object->logvols.size()),
0962                  object->logvol.empty()  ? "--" : object->logvol.c_str(),
0963                  vol.ptr(),
0964                  object->support.empty() ? "--" : object->support.c_str(),
0965                  object->npath.empty()   ? "--" : object->npath.c_str(),
0966                  object->path.c_str());
0967         int cnt = 0;
0968         for( const auto& v : object->catalogrefs )  {
0969           if ( v.second )
0970             printout(INFO,"CNV<DE>:cref","++ DE:%s ref[%2d]: %p -> %s",
0971                      object->path.c_str(), cnt, v.second, v.second->c_name());
0972           else
0973             printout(INFO,"CNV<DE>:cref","++ DE:%s ref[%2d]: ??????", object->path.c_str(), cnt);
0974           ++cnt;
0975         }
0976         cnt = 0;
0977         for( const auto& v : object->logvolrefs )  {
0978           DDDBLogVol* lv = v.second;
0979           Volume geoVol = Context::find(context->volumes, lv);
0980           if ( lv )
0981             printout(INFO,"CNV<DE>:lref","++ DE:%s ref[%2d]: %p / %s  -> %p [%s]",
0982                      object->path.c_str(), cnt, (void*)lv, lv->c_name(), 
0983                      (void*)geoVol.ptr(), geoVol.isValid() ? geoVol->GetName() : "????");
0984           else
0985             printout(INFO,"CNV<DE>:lref","++ DE:%s ref[%2d]: ??????", object->path.c_str(), cnt);
0986           ++cnt;
0987         }
0988         cnt = 0;
0989         for( const auto& v : object->logvols )  {
0990           DDDBLogVol* lv = v.second;
0991           if ( lv )  {
0992             Volume geoVol = Context::find(context->volumes, lv);
0993             printout(INFO,"CNV<DE>:lvol","++ DE:%s ref[%2d]: %p / %s  -> %p [%s]",
0994                      object->path.c_str(), cnt, (void*)lv, lv->c_id(), 
0995                      (void*)geoVol.ptr(), geoVol.isValid() ? geoVol->GetName() : "????");
0996           }
0997           else
0998             printout(INFO,"CNV<DE>:lvol","++ DE:%s ref[%2d]: ??????", object->path.c_str(), cnt);
0999           ++cnt;
1000         }
1001         if ( vol && !object->npath.empty() )   {
1002           for(int i=0; i<vol->GetNdaughters(); ++i)  {
1003             TGeoNode* dau = vol->GetNode(i);
1004             printout(INFO,"CNV<DE>:npath","++ DE:%s npath:%s Dau[%2d]: %s",
1005                      object->path.c_str(), object->npath.c_str(),
1006                      i, dau->GetName());
1007           }
1008         }
1009       }
1010       return det.ptr(); 
1011     }
1012 
1013     template <> void* CNV<dddb>::convert(dddb *obj) const   {
1014       Context*  context = _param<Context>();
1015       if ( !context->conditions_only )  {
1016         Volume world   = description.worldVolume();
1017 
1018         for_each(obj->isotopes.begin(),  obj->isotopes.end(),   cnv<DDDBIsotope>());
1019         printout(INFO,"DDDB2Object","++ Converted %d isotopes.",int(obj->isotopes.size()));
1020         for_each(obj->elements.begin(),  obj->elements.end(),   cnv<DDDBElement>());
1021         printout(INFO,"DDDB2Object","++ Converted %d elements.",int(obj->elements.size()));
1022         //for_each(obj->materials.begin(), obj->materials.end(),  cnv<DDDBMaterial>());
1023         //printout(INFO,"DDDB2Object","++ Converted %d materials.",int(obj->materials.size()));
1024         //for_each(obj->shapes.begin(),    obj->shapes.end(),     cnv<DDDBShape>());
1025         //printout(INFO,"DDDB2Object","++ Converted %d shapes.",int(obj->shapes.size()));
1026         //for_each(obj->volumes.begin(),   obj->volumes.end(),    cnv<DDDBLogVol>());
1027         //printout(INFO,"DDDB2Object","++ Converted %d volumes.",int(obj->volumes.size()));
1028         //for_each(obj->placements.begin(),obj->placements.end(), cnv<DDDBPhysVol>());
1029         //printout(INFO,"DDDB2Object","++ Converted %d placements.",int(obj->placements.size()));
1030 
1031         if ( obj->top )   {
1032           if ( !context->lvDummy.isValid() )   {
1033             description.manager().SetVisLevel(context->print.max_volume_depth);
1034             context->lvDummy = Volume("Dummy",Box(0.0001,0.0001, 0.0001),description.vacuum());
1035             context->lvDummy.setVisAttributes(description.invisible());
1036           }
1037           if ( !world.isValid() )  {
1038             string top = "/dd/Geometry/LHCb/lvLHCb";
1039             const DDDBLogVol* lv = Context::find(obj->volumePaths,top);
1040             if ( !lv )   {
1041               except("DDDB2dd4hep","++ No World volume defined.");
1042             }
1043             const DDDBShape* s = Context::find(obj->shapes,lv->id);
1044             if ( !s )  {
1045               except("DDDB2dd4hep","++ No Shape for the world volume defined.");
1046             }
1047             obj->world = s->s.box;
1048           }
1049           /// Main detector conversion invokation
1050           cnv<DDDBCatalog>().convert(obj->top);
1051           if ( !world.isValid() && description.worldVolume().isValid() )  {
1052             description.endDocument();
1053           }
1054           /// Now configure the conditions manager
1055           if ( !context->manager.isValid() )  {
1056             ConditionsManager manager = ConditionsManager::from(description);
1057             manager["PoolType"]       = "DD4hep_ConditionsLinearPool";
1058             manager["LoaderType"]     = "DD4hep_Conditions_dddb_Loader";
1059             manager["UserPoolType"]   = "DD4hep_ConditionsMapUserPool";
1060             manager["UpdatePoolType"] = "DD4hep_ConditionsLinearUpdatePool";
1061             manager.initialize();
1062             pair<bool,const IOVType*> e = manager.registerIOVType(0, "epoch");
1063             context->manager = manager;
1064             context->epoch   = e.second;
1065           }
1066         }
1067       }
1068       if ( !context->manager.isValid() )  {
1069         ConditionsManager manager = ConditionsManager::from(description);
1070         pair<bool,const IOVType*> e = manager.registerIOVType(0, "epoch");
1071         context->manager = manager;
1072         context->epoch   = e.second;
1073       }
1074       for_each(obj->conditions.begin(),obj->conditions.end(), cnv<GeoCondition>());
1075       //printout(INFO,"DDDB2Object","++ Converted %d conditions.",int(obj->conditions.size()));
1076       return obj;
1077     }
1078   }
1079 
1080   /// Namespace for implementation details of the AIDA detector description toolkit
1081   namespace DDDB  {
1082     long dddb_2_dd4hep(Detector& description, int , char** ) {
1083       DDDBHelper* helper = description.extension<DDDBHelper>(false);
1084       if ( helper )   {
1085         Context context(description, helper);
1086         CNV<dddb> cnv(description,&context);
1087         cnv(make_pair(string("World"),context.geo));
1088         printout(INFO,"DDDB","+========================= Conversion summary =========================+");
1089         printout(INFO,"DDDB","++ Converted %8d isotopes.",         int(context.isotopes.size()));
1090         printout(INFO,"DDDB","++ Converted %8d elements.",         int(context.elements.size()));
1091         printout(INFO,"DDDB","++ Converted %8d materials.",        int(context.materials.size()));
1092         printout(INFO,"DDDB","++ Converted %8d shapes.",           int(context.shapes.size()));
1093         printout(INFO,"DDDB","++ Converted %8d logical  volumes.", int(context.volumes.size()));
1094         printout(INFO,"DDDB","++ Converted %8d placements.",       int(context.placements.size()));
1095         printout(INFO,"DDDB","++ Converted %8d detector elements.",int(context.detelements.size()));
1096         printout(INFO,"DDDB","++ Converted %8d conditions.",
1097                  context.geo ? int(context.geo->conditions.size()) : 0);
1098         printout(INFO,"DDDB","++ MATCHED   %8d conditions.",       context.matched_conditions);
1099         printout(INFO,"DDDB","++ UNMATCHED %8d conditions. [Could not determine DetElement]",
1100                  context.unmatched_conditions);
1101         printout(INFO,"DDDB","++ BADASSIGN %8d conditions. [Could not determine DetElement]",
1102                  context.badassigned_conditions);
1103         printout(INFO,"DDDB","++ DELTAS    %8d conditions.",       context.delta_conditions);
1104         printout(INFO,"DDDB","++ DELTAS    %8d (unmatched).",      context.unmatched_deltas);
1105         printout(INFO,"DDDB","+======================================================================+");
1106         helper->setDetectorDescription(0);
1107         return 1;
1108       }
1109       except("DDDB","++ No DDDBHelper instance installed. Geometry conversion failed!");
1110       return 1;
1111     }
1112     long dddb_conditions_2_dd4hep(Detector& description, int , char** ) {
1113       DDDBHelper* helper = description.extension<DDDBHelper>(false);
1114       if ( helper )   {
1115         Context context(description, helper);
1116         context.print.condition = false;
1117         context.conditions_only = true;
1118         CNV<dddb> cnv(description,&context);
1119         cnv(make_pair(string(),context.geo));
1120         helper->setDetectorDescription(0);
1121         return 1;
1122       }
1123       except("DDDB","++ No DDDBHelper instance installed. Geometry conversion failed!");
1124       return 1;
1125     }
1126 
1127   } /* End namespace DDDB      */
1128 } /* End namespace dd4hep    */
1129 DECLARE_APPLY(DDDB_2dd4hep,dddb_2_dd4hep)
1130 DECLARE_APPLY(DDDB_Conditions2dd4hep,dddb_conditions_2_dd4hep)