Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-03-13 08:19:38

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 #define DD4HEP_MUST_USE_DETECTORIMP_H 1
0015 
0016 // Framework include files
0017 #include <DD4hep/Plugins.h>
0018 #include <DD4hep/Printout.h>
0019 #include <DD4hep/GeoHandler.h>
0020 #include <DD4hep/DetectorHelper.h>
0021 #include <DD4hep/DetectorTools.h>
0022 
0023 #include <DD4hep/InstanceCount.h>
0024 #include <DD4hep/detail/ObjectsInterna.h>
0025 #include <DD4hep/detail/DetectorInterna.h>
0026 #include <DD4hep/detail/VolumeManagerInterna.h>
0027 #include <DD4hep/detail/OpticalSurfaceManagerInterna.h>
0028 #include <DD4hep/DetectorImp.h>
0029 #include <DD4hep/DD4hepUnits.h>
0030 
0031 // C/C++ include files
0032 #include <iostream>
0033 #include <stdexcept>
0034 #include <cerrno>
0035 #include <mutex>
0036 
0037 // ROOT inlcude files
0038 #include <TGeoSystemOfUnits.h>
0039 #include <TGeoCompositeShape.h>
0040 #include <TGeoBoolNode.h>
0041 #include <TGeoManager.h>
0042 #include <TGeoMatrix.h>
0043 #include <TGeoVolume.h>
0044 #include <TGeoShape.h>
0045 #include <TClass.h>
0046 
0047 #include <XML/DocumentHandler.h>
0048 
0049 #ifndef __TIXML__
0050 #include <xercesc/dom/DOMException.hpp>
0051 namespace dd4hep {
0052   namespace xml {
0053     typedef xercesc::DOMException XmlException;
0054   }
0055 }
0056 #endif
0057 
0058 using namespace dd4hep;
0059 
0060 ClassImp(DetectorImp)
0061 
0062 namespace {
0063 
0064   std::recursive_mutex  s_detector_apply_lock;
0065 
0066   struct TypePreserve {
0067     DetectorBuildType& m_t;
0068     TypePreserve(DetectorBuildType& t)
0069       : m_t(t) {
0070     }
0071     ~TypePreserve() {
0072       m_t = BUILD_NONE;
0073     }
0074   };
0075 
0076   struct Instances  {
0077     std::recursive_mutex  lock;
0078     std::map<std::string, Detector*> detectors;
0079     Instances() = default;
0080     ~Instances()  {
0081     }
0082     Detector* get(const std::string& name)   {
0083       auto i = detectors.find(name);
0084       return i == detectors.end() ? 0 : (*i).second;
0085     }
0086     void insert(const std::string& name, Detector* detector)   {
0087       auto i = detectors.find(name);
0088       if ( i == detectors.end() )   {
0089         detectors.emplace(name,detector);
0090         return;
0091       }
0092       except("DD4hep","Cannot insert detector instance %s [Already present]",name.c_str());
0093     }
0094     Detector* remove(const std::string& name)   {
0095       auto i = detectors.find(name);
0096       if ( i != detectors.end() )  {
0097         Detector* det = (*i).second;
0098         detectors.erase(i);
0099         return det;
0100       }
0101       return 0;
0102     }
0103   };
0104   
0105   class DetectorGuard  final  {
0106   protected:
0107     static std::pair<std::recursive_mutex, std::map<DetectorImp*, TGeoManager*> >& detector_lock()   {
0108       static std::pair<std::recursive_mutex, std::map<DetectorImp*, TGeoManager*> > s_inst;
0109       return s_inst;
0110     }
0111     DetectorImp* detector {nullptr};
0112   public:
0113     DetectorGuard(DetectorImp* imp) : detector(imp) {}
0114     ~DetectorGuard() = default;
0115     void lock(TGeoManager* mgr)   const  {
0116       auto& lock = detector_lock();
0117       lock.first.lock();
0118       lock.second[detector] = mgr;
0119     }
0120     TGeoManager* unlock()  const  {
0121       TGeoManager* mgr = nullptr;
0122       auto& lock = detector_lock();
0123       auto i = lock.second.find(detector);
0124       if ( i != lock.second.end() )   {
0125         mgr = (*i).second;
0126         lock.second.erase(i);
0127       }
0128       lock.first.unlock();
0129       return mgr;
0130     }
0131   };
0132   
0133   Instances& detector_instances()    {
0134     static Instances s_inst;
0135     return s_inst;
0136   }
0137 }
0138 
0139 std::string dd4hep::versionString(){
0140   char vsn[32];
0141   std::snprintf(vsn, sizeof(vsn), "v%2.2d-%2.2d", DD4HEP_MAJOR_VERSION, DD4HEP_MINOR_VERSION);
0142   return { vsn };
0143 }
0144 
0145 std::unique_ptr<Detector> Detector::make_unique(const std::string& name)   {
0146   Detector* description = new DetectorImp(name);
0147   return std::unique_ptr<Detector>(description);
0148 }
0149 
0150 Detector& Detector::getInstance(const std::string& name)   {
0151   std::lock_guard<std::recursive_mutex> lock(detector_instances().lock);
0152   Detector* description = detector_instances().get(name);
0153   if ( 0 == description )   {
0154     gGeoManager = 0;
0155     description = new DetectorImp(name);
0156     detector_instances().insert(name,description);
0157   }
0158   return *description;
0159 }
0160 
0161 /// Destroy the instance
0162 void Detector::destroyInstance(const std::string& name) {
0163   std::lock_guard<std::recursive_mutex> lock(detector_instances().lock);
0164   Detector* description = detector_instances().remove(name);
0165   if (description)
0166     delete description;
0167 }
0168 
0169 /// Default constructor used by ROOT I/O
0170 DetectorImp::DetectorImp()
0171   : TNamed(), DetectorData(), DetectorLoad(this), m_buildType(BUILD_NONE)
0172 {
0173   m_surfaceManager = new detail::OpticalSurfaceManagerObject(*this);
0174   m_std_conditions.convention  = STD_Conditions::NTP;
0175   m_std_conditions.pressure    = Pressure_NTP;
0176   m_std_conditions.temperature = Temperature_NTP;
0177 }
0178 
0179 /// Initializing constructor
0180 DetectorImp::DetectorImp(const std::string& name)
0181   : TNamed(), DetectorData(), DetectorLoad(this), m_buildType(BUILD_NONE)
0182 {
0183 #if defined(DD4HEP_USE_GEANT4_UNITS)
0184   printout(INFO,"DD4hep","++ Using globally Geant4 unit system (mm,ns,MeV)");
0185   if ( TGeoManager::GetDefaultUnits() != TGeoManager::kG4Units )  {
0186     TGeoManager::LockDefaultUnits(kFALSE);
0187     TGeoManager::SetDefaultUnits(TGeoManager::kG4Units);
0188     TGeoManager::LockDefaultUnits(kTRUE);
0189   }
0190 #else
0191   if ( TGeoManager::GetDefaultUnits() != TGeoManager::kRootUnits )  {
0192     TGeoManager::LockDefaultUnits(kFALSE);
0193     TGeoManager::SetDefaultUnits(TGeoManager::kRootUnits);
0194     TGeoManager::LockDefaultUnits(kTRUE);
0195   }
0196 #endif
0197 
0198   SetName(name.c_str());
0199   SetTitle("DD4hep detector description object");
0200   //DetectorGuard(this).lock(gGeoManager);
0201   gGeoManager = nullptr;
0202   InstanceCount::increment(this);
0203   m_manager = new TGeoManager(name.c_str(), "Detector Geometry");
0204   {
0205     m_manager->AddNavigator();
0206     m_manager->SetCurrentNavigator(0);
0207     gGeoManager = m_manager;
0208 #if 1 //FIXME: eventually this should be set to 1 - needs fixes in examples ...
0209     TGeoElementTable* table = m_manager->GetElementTable();
0210     table->TGeoElementTable::~TGeoElementTable();
0211     new(table) TGeoElementTable();
0212     // This will initialize the table without filling:
0213     table->AddElement("VACUUM","VACUUM", 1, 1, 1e-15);
0214 #endif
0215   }
0216   if ( 0 == gGeoIdentity )
0217   {
0218     gGeoIdentity = new TGeoIdentity();
0219   }
0220   m_surfaceManager = new detail::OpticalSurfaceManagerObject(*this);
0221   m_std_conditions.convention  = STD_Conditions::NTP;
0222   m_std_conditions.pressure    = Pressure_NTP;
0223   m_std_conditions.temperature = Temperature_NTP;
0224   
0225   VisAttr attr("invisible");
0226   attr.setColor(1.0, 0.5, 0.5, 0.5);
0227   attr.setLineStyle(VisAttr::SOLID);
0228   attr.setDrawingStyle(VisAttr::SOLID);
0229   attr.setVisible(false);
0230   attr.setShowDaughters(true);
0231   addVisAttribute(attr);
0232   m_invisibleVis = attr;
0233 }
0234 
0235 /// Standard destructor
0236 DetectorImp::~DetectorImp() {
0237   DetectorGuard(this).lock(gGeoManager);
0238   if ( m_manager )  {
0239     std::lock_guard<std::recursive_mutex> lock(detector_instances().lock);
0240     if ( m_manager == gGeoManager ) gGeoManager = 0;
0241     Detector* description = detector_instances().get(GetName());
0242     if ( 0 != description )   {
0243       detector_instances().remove(m_manager->GetName());
0244     }
0245   }
0246   if ( m_surfaceManager )   {
0247     delete m_surfaceManager;
0248     m_surfaceManager = nullptr;
0249   }
0250   destroyData(false);
0251   m_extensions.clear();
0252   m_detectorTypes.clear();
0253   InstanceCount::decrement(this);
0254   DetectorGuard(this).unlock();
0255 }
0256 
0257 /// ROOT I/O call
0258 Int_t DetectorImp::saveObject(const char *name, Int_t option, Int_t bufsize) const   {
0259   Int_t nbytes = 0;
0260   try  {
0261     DetectorData::patchRootStreamer(TGeoVolume::Class());
0262     DetectorData::patchRootStreamer(TGeoNode::Class());
0263     nbytes = TNamed::Write(name, option, bufsize);
0264     DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0265     DetectorData::unpatchRootStreamer(TGeoNode::Class());
0266     return nbytes;
0267   }
0268   catch (const std::exception& e) {
0269     DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0270     DetectorData::unpatchRootStreamer(TGeoNode::Class());
0271     except("Detector","Exception %s while saving dd4hep::Detector object", e.what());
0272   }
0273   catch (...) {
0274     DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0275     DetectorData::unpatchRootStreamer(TGeoNode::Class());
0276     except("Detector","UNKNOWN exception while saving dd4hep::Detector object.");
0277   }
0278   return nbytes;
0279 }
0280 
0281 // Load volume manager
0282 void DetectorImp::imp_loadVolumeManager()   {
0283   detail::destroyHandle(m_volManager);
0284   m_volManager = VolumeManager(*this, "World", world(), Readout(), VolumeManager::TREE);
0285 }
0286 
0287 /// Add an extension object to the Detector instance
0288 void* DetectorImp::addUserExtension(unsigned long long int key, ExtensionEntry* entry) {
0289   return m_extensions.addExtension(key,entry);
0290 }
0291 
0292 /// Remove an existing extension object from the Detector instance
0293 void* DetectorImp::removeUserExtension(unsigned long long int key, bool destroy)  {
0294   return m_extensions.removeExtension(key,destroy);
0295 }
0296 
0297 /// Access an existing extension object from the Detector instance
0298 void* DetectorImp::userExtension(unsigned long long int key, bool alert) const {
0299   return m_extensions.extension(key,alert);
0300 }
0301 
0302 /// Register new mother volume using the detector name.
0303 void DetectorImp::declareParent(const std::string& detector_name, const DetElement& parent)  {
0304   if ( !detector_name.empty() )  {
0305     if ( parent.isValid() )  {
0306       auto i = m_detectorParents.find(detector_name);
0307       if (i == m_detectorParents.end())   {
0308         Volume parent_volume = parent.placement().volume();
0309         if ( parent_volume.isValid() )   {
0310           m_detectorParents.emplace(detector_name,parent);
0311           return;
0312         }
0313         except("DD4hep","+++ Failed to access valid parent volume of %s from %s",
0314                detector_name.c_str(), parent.name());
0315       }
0316       except("DD4hep",
0317              "+++ A parent to the detector %s was already registered.",
0318              detector_name.c_str());
0319     }
0320     except("DD4hep",
0321            "+++ Attempt to register invalid parent for detector: %s [Invalid-Handle].",
0322            detector_name.c_str());
0323   }
0324   except("DD4hep",
0325          "+++ Attempt to register parent to invalid detector [Invalid-detector-name].");
0326 }
0327 
0328 /// Access mother volume by detector element
0329 Volume DetectorImp::pickMotherVolume(const DetElement& de) const {
0330   if ( de.isValid() )   {
0331     std::string de_name = de.name();
0332     auto i = m_detectorParents.find(de_name);
0333     if (i == m_detectorParents.end())   {
0334       if ( m_worldVol.isValid() )  {
0335         return m_worldVol;
0336       }
0337       except("DD4hep",
0338              "+++ The world volume is not (yet) valid. "
0339              "Are you correctly building detector %s?",
0340              de.name());
0341     }
0342     if ( (*i).second.isValid() )  {
0343       Volume vol = (*i).second.volume();
0344       if ( vol.isValid() )  {
0345         return vol;
0346       }
0347     }
0348     except("DD4hep",
0349            "+++ The mother volume of %s is not valid. "
0350            "Are you correctly building detectors?",
0351            de.name());
0352   }
0353   except("DD4hep","Detector: Attempt access mother volume of invalid detector [Invalid-handle]");
0354   return 0;
0355 }
0356 
0357 /// Access default conditions (temperature and pressure
0358 const STD_Conditions& DetectorImp::stdConditions()   const   {
0359   if ( (m_std_conditions.convention&STD_Conditions::USER_SET) == 0 &&
0360        (m_std_conditions.convention&STD_Conditions::USER_NOTIFIED) == 0 )
0361   {
0362     printout(WARNING,"DD4hep","++ STD conditions NOT defined by client. NTP defaults taken.");
0363     m_std_conditions.convention |= STD_Conditions::USER_NOTIFIED;
0364   }
0365   return m_std_conditions;
0366 }
0367 /// Set the STD temperature and pressure
0368 void DetectorImp::setStdConditions(double temp, double pressure)  {
0369   m_std_conditions.temperature = temp;
0370   m_std_conditions.pressure = pressure;
0371   m_std_conditions.convention = STD_Conditions::USER_SET;
0372   if      ( std::abs(temp-Temperature_NTP) < 1e-10 && std::abs(pressure-Pressure_NTP) < 1e-10 )
0373     m_std_conditions.convention |= STD_Conditions::NTP;
0374   else if ( std::abs(temp-Temperature_STP) < 1e-10 && std::abs(pressure-Pressure_STP) < 1e-10 )
0375     m_std_conditions.convention |= STD_Conditions::STP;
0376   else
0377     m_std_conditions.convention |= STD_Conditions::USER;
0378 }
0379 
0380 /// Set the STD conditions according to defined types (STP or NTP)
0381 void DetectorImp::setStdConditions(const std::string& type)   {
0382   if ( type == "STP" )   {
0383     m_std_conditions.temperature = Temperature_STP;
0384     m_std_conditions.pressure    = Pressure_STP;
0385     m_std_conditions.convention  = STD_Conditions::STP|STD_Conditions::USER_SET;
0386   }
0387   else if ( type == "NTP" )   {
0388     m_std_conditions.temperature = Temperature_NTP;
0389     m_std_conditions.pressure    = Pressure_NTP;
0390     m_std_conditions.convention  = STD_Conditions::NTP|STD_Conditions::USER_SET;
0391   }
0392   else   {
0393     except("DD4hep",
0394            "++ Attempt to set standard conditions to "
0395            "unknown conventions (Only STP and NTP allowed).");
0396   }
0397 }
0398 
0399 /// Retrieve a subdetector element by its name from the detector description
0400 DetElement DetectorImp::detector(const std::string& name) const  {
0401   HandleMap::const_iterator i = m_detectors.find(name);
0402   if (i != m_detectors.end()) {
0403     return (*i).second;
0404   }
0405   DetElement de = detail::tools::findElement(*this,name);
0406   return de;
0407 }
0408 
0409 Detector& DetectorImp::addDetector(const Handle<NamedObject>& ref_det) {
0410   DetElement     det_element(ref_det);
0411   DetectorHelper helper(this);
0412   DetElement     existing_det = helper.detectorByID(det_element.id());
0413 
0414   if ( existing_det.isValid() )   {
0415     SensitiveDetector sd = helper.sensitiveDetector(existing_det);
0416     if ( sd.isValid() )   {
0417       std::stringstream str;
0418       str << "Detector: The sensitive sub-detectors " << det_element.name() << " and "
0419           << existing_det.name() << " have the identical ID:" << det_element.id() << ".";
0420       except("DD4hep",str.str());
0421     }
0422   }
0423   m_detectors.append(ref_det);
0424   det_element->flag |= DetElement::Object::IS_TOP_LEVEL_DETECTOR;
0425   PlacedVolume pv = det_element.placement();
0426   if ( !pv.isValid() )   {
0427     std::stringstream str;
0428     str << "Detector: Adding subdetectors with no valid placement is not allowed: "
0429         << det_element.name() << " ID:" << det_element.id() << ".";
0430     except("DD4hep",str.str());
0431   }
0432   Volume volume = pv->GetMotherVolume();
0433   if ( volume == m_worldVol )  {
0434     printout(DEBUG,"DD4hep","+++ Detector: Added detector %s to the world instance.",
0435              det_element.name());
0436     m_world.add(det_element);
0437     return *this;
0438   }
0439   /// Check if the parent is part of the compounds
0440   auto ipar = m_detectorParents.find(det_element.name());
0441   if (ipar != m_detectorParents.end())   {
0442     DetElement parent = (*ipar).second;
0443     parent.add(det_element);
0444     printout(DEBUG,"DD4hep","+++ Detector: Added detector %s to parent %s.",
0445              det_element.name(), parent.name());
0446     return *this;
0447   }
0448 
0449   // The detector's placement must be one of the existing detectors
0450   for(HandleMap::iterator idet = m_detectors.begin(); idet != m_detectors.end(); ++idet)  {
0451     DetElement parent((*idet).second);
0452     Volume     vol = parent.placement().volume();
0453     if ( vol == volume )  {
0454       printout(INFO,"DD4hep","+++ Detector: Added detector %s to the parent:%s.",
0455                det_element.name(),parent.name());
0456       parent.add(det_element);
0457       return *this;
0458     }
0459   }
0460   except("DD4hep","+++ Detector: The detector %s has no known parent.", det_element.name());
0461   throw std::runtime_error("Detector-Error"); // Never called....
0462 }
0463 
0464 /// Add a new constant by named reference to the detector description
0465 Detector& DetectorImp::addConstant(const Handle<NamedObject>& x) {
0466   if ( strcmp(x.name(),"Detector_InhibitConstants") == 0 )   {
0467     const char* title = x->GetTitle();
0468     char c = ::toupper(title[0]);
0469     m_inhibitConstants = (c=='Y' || c=='T' || c=='1');
0470   }
0471   m_define.append(x, false);
0472   return *this;
0473 }
0474 
0475 /// Retrieve a constant by its name from the detector description
0476 Constant DetectorImp::constant(const std::string& name) const {
0477   if ( !m_inhibitConstants )   {
0478     return getRefChild(m_define, name);
0479   }
0480   throw std::runtime_error("Detector:constant("+name+"): Access to global constants is inhibited.");
0481 }
0482 
0483 /// Typed access to constants: access string values
0484 std::string DetectorImp::constantAsString(const std::string& name) const {
0485   if ( !m_inhibitConstants )   {
0486     Handle<NamedObject> c = constant(name);
0487     if (c.isValid())
0488       return c->GetTitle();
0489     throw std::runtime_error("Detector:constantAsString: The constant " + name + " is not known to the system.");
0490   }
0491   throw std::runtime_error("Detector:constantAsString("+name+"):: Access to global constants is inhibited.");
0492 }
0493 
0494 /// Typed access to constants: long values
0495 long DetectorImp::constantAsLong(const std::string& name) const {
0496   if ( !m_inhibitConstants )   {
0497     return _toLong(constantAsString(name));
0498   }
0499   throw std::runtime_error("Detector:constantAsLong("+name+"): Access to global constants is inhibited.");
0500 }
0501 
0502 /// Typed access to constants: double values
0503 double DetectorImp::constantAsDouble(const std::string& name) const {
0504   if ( !m_inhibitConstants )   {
0505     return _toDouble(constantAsString(name));
0506   }
0507   throw std::runtime_error("Detector:constantAsDouble("+name+"): Access to global constants is inhibited.");
0508 }
0509 
0510 /// Add a field component by named reference to the detector description
0511 Detector& DetectorImp::addField(const Handle<NamedObject>& x) {
0512   m_field.add(x);
0513   m_fields.append(x);
0514   return *this;
0515 }
0516 
0517 /// Retrieve a matrial by its name from the detector description
0518 Material DetectorImp::material(const std::string& name) const {
0519   TGeoMedium* mat = m_manager->GetMedium(name.c_str());
0520   if (mat) {
0521     return Material(mat);
0522   }
0523   throw std::runtime_error("Cannot find a material referenced by name:" + name);
0524 }
0525 
0526 /// Internal helper to map detector types once the geometry is closed
0527 void DetectorImp::mapDetectorTypes()  {
0528   m_detectorTypes[""] = {};
0529   for( const auto& i : m_detectors )   {
0530     DetElement det(i.second);
0531     if ( det.parent().isValid() )  { // Exclude 'world'
0532       HandleMap::const_iterator j=m_sensitive.find(det.name());
0533       if ( j != m_sensitive.end() )  {
0534         SensitiveDetector sd((*j).second);
0535         m_detectorTypes[sd.type()].emplace_back(det);
0536       }
0537       else if ( det.type() == "compound" )  {
0538         m_detectorTypes[det.type()].emplace_back(det);      
0539       }
0540       else  {
0541         m_detectorTypes["passive"].emplace_back(det);      
0542       }
0543     }
0544   }
0545 }
0546 
0547 /// Access the availible detector types
0548 std::vector<std::string> DetectorImp::detectorTypes() const  {
0549   if ( m_manager->IsClosed() ) {
0550     std::vector<std::string> v;
0551     v.reserve(m_detectorTypes.size());
0552     for(const auto& t : m_detectorTypes )
0553       v.emplace_back(t.first);
0554     return v;
0555   }
0556   throw std::runtime_error("detectorTypes: Call only available once the geometry is closed!");
0557 }
0558 
0559 /// Access a set of subdetectors according to the sensitive type.
0560 const std::vector<DetElement>& DetectorImp::detectors(const std::string& type, bool throw_exc) const {
0561   if ( m_manager->IsClosed() ) {
0562     DetectorTypeMap::const_iterator i=m_detectorTypes.find(type);
0563     if ( i != m_detectorTypes.end() ) return (*i).second;
0564     if ( throw_exc )  {
0565       throw std::runtime_error("detectors("+type+"): Detectors of this type do not exist in the current setup!");
0566     }
0567     // return empty vector instead of exception
0568     return m_detectorTypes.at("") ;
0569   }
0570   throw std::runtime_error("detectors("+type+"): Detectors can only selected by type once the geometry is closed!");
0571 }
0572 
0573 std::vector<DetElement> DetectorImp::detectors(unsigned int includeFlag, unsigned int excludeFlag ) const  {
0574   if( ! m_manager->IsClosed() ) {
0575     throw std::runtime_error("detectors(typeFlag): Detectors can only selected by typeFlag once the geometry is closed!");
0576   }
0577   std::vector<DetElement> dets ;
0578   dets.reserve( m_detectors.size() ) ;
0579   
0580   for(HandleMap::const_iterator i=m_detectors.begin(); i!=m_detectors.end(); ++i)   {
0581     DetElement det((*i).second);
0582     if ( det.parent().isValid() )  { // Exclude 'world'
0583       
0584       //fixme: what to do with compounds - add their daughters  ?
0585       // ...
0586 
0587       if( ( det.typeFlag() &  includeFlag ) == includeFlag &&
0588           ( det.typeFlag() &  excludeFlag ) ==  0 )
0589         dets.emplace_back( det ) ;
0590     }
0591   }
0592   return dets ;
0593 }
0594 
0595 /// Access a set of subdetectors according to several sensitive types.
0596 std::vector<DetElement> DetectorImp::detectors(const std::string& type1,
0597                                                const std::string& type2,
0598                                                const std::string& type3,
0599                                                const std::string& type4,
0600                                                const std::string& type5 )  {
0601   if ( m_manager->IsClosed() ) {
0602     std::vector<DetElement> v;
0603     DetectorTypeMap::const_iterator i, end=m_detectorTypes.end();
0604     if ( !type1.empty() && (i=m_detectorTypes.find(type1)) != end )
0605       v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0606     if ( !type2.empty() && (i=m_detectorTypes.find(type2)) != end )
0607       v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0608     if ( !type3.empty() && (i=m_detectorTypes.find(type3)) != end )
0609       v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0610     if ( !type4.empty() && (i=m_detectorTypes.find(type4)) != end )
0611       v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0612     if ( !type5.empty() && (i=m_detectorTypes.find(type5)) != end ) 
0613       v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0614     return v;
0615   }
0616   throw std::runtime_error("detectors("+type1+","+type2+",...): Detectors can only selected by type once the geometry is closed!");
0617 }
0618 
0619 Handle<NamedObject> DetectorImp::getRefChild(const HandleMap& e, const std::string& name, bool do_throw) const {
0620   HandleMap::const_iterator it = e.find(name);
0621   if (it != e.end()) {
0622     return it->second;
0623   }
0624   if (do_throw) {
0625     union ptr {
0626       const ObjectHandleMap* omap;
0627       const char* c;
0628       const void* other;
0629       ptr(const void* p) { other = p; }
0630     };
0631     std::string nam = "";
0632     ptr mptr(&e), ref(this);
0633     if ( ref.c > mptr.c && mptr.c < ref.c+sizeof(*this) )  {
0634       nam = mptr.omap->name;
0635     }
0636     std::stringstream err;
0637     err << "getRefChild: Failed to find child with name: " << name
0638         << " Map " << nam << " contains " << e.size() << " elements: {";
0639     for (it = e.begin(); it != e.end(); ++it) {
0640       if (it != e.begin()) {
0641         err << ", ";
0642       }
0643       err << it->first;
0644     }
0645     err << "}";
0646     throw std::runtime_error(err.str());
0647   }
0648   return 0;
0649 }
0650 
0651 namespace {
0652   struct ShapePatcher: public detail::GeoScan {
0653     VolumeManager m_volManager;
0654     DetElement m_world;
0655     ShapePatcher(VolumeManager m, DetElement e)
0656       : detail::GeoScan(e), m_volManager(m), m_world(e) {
0657     }
0658     void patchShapes() {
0659       auto&  data = *m_data;
0660       char   text[32];
0661       std::string nam;
0662       printout(INFO,"Detector","+++ Patching names of anonymous shapes....");
0663       for (auto i = data.rbegin(); i != data.rend(); ++i) {
0664         for( const TGeoNode* n : (*i).second )  {
0665           TGeoVolume* vol = n->GetVolume();
0666           TGeoShape*  s   = vol->GetShape();
0667           const char* sn  = s->GetName();
0668           ::snprintf(text,sizeof(text),"_shape_%p",(void*)s);
0669           if (0 == sn || 0 == ::strlen(sn)) {
0670             nam = vol->GetName();
0671             nam += text;
0672             s->SetName(nam.c_str());
0673           }
0674           else if (0 == ::strcmp(sn, s->IsA()->GetName())) {
0675             nam = vol->GetName();
0676             nam += text;
0677             s->SetName(nam.c_str());
0678           }
0679           else {
0680             nam = sn;
0681             if (nam.find("_shape") == std::string::npos)
0682               nam += text;
0683             s->SetName(nam.c_str());
0684           }
0685           if (s->IsA() == TGeoCompositeShape::Class()) {
0686             TGeoCompositeShape* c = (TGeoCompositeShape*) s;
0687             const TGeoBoolNode* boolean = c->GetBoolNode();
0688             s = boolean->GetLeftShape();
0689             sn = s->GetName();
0690             if (0 == sn || 0 == ::strlen(sn)) {
0691               s->SetName((nam + "_left").c_str());
0692             }
0693             else if (0 == ::strcmp(sn, s->IsA()->GetName())) {
0694               s->SetName((nam + "_left").c_str());
0695             }
0696             s = boolean->GetRightShape();
0697             sn = s->GetName();
0698             if (0 == sn || 0 == ::strlen(sn)) {
0699               s->SetName((nam + "_right").c_str());
0700             }
0701             else if (0 == ::strcmp(s->GetName(), s->IsA()->GetName())) {
0702               s->SetName((nam + "_right").c_str());
0703             }
0704           }
0705         }
0706       }
0707     }
0708   };
0709 }
0710 
0711 /// Finalize/close the geometry
0712 void DetectorImp::endDocument(bool close_geometry)    {
0713   TGeoManager* mgr = m_manager;
0714   std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0715   if ( close_geometry && !mgr->IsClosed() )  {
0716 #if 0
0717     Region trackingRegion("TrackingRegion");
0718     trackingRegion.setThreshold(1);
0719     trackingRegion.setStoreSecondaries(true);
0720     add(trackingRegion);
0721     m_trackingVol.setRegion(trackingRegion);
0722     // Set the tracking volume to invisible.
0723     VisAttr trackingVis("TrackingVis");
0724     trackingVis.setVisible(false);
0725     m_trackingVol.setVisAttributes(trackingVis);
0726     add(trackingVis);
0727 #endif
0728     m_worldVol.solid()->ComputeBBox();
0729     // Propagating reflections: This is useless now and unused!!!!
0730     // Since we allow now for anonymous shapes,
0731     // we will rename them to use the name of the volume they are assigned to
0732     mgr->CloseGeometry();
0733     PlacedVolume pv = mgr->GetTopNode();
0734     auto* extension = pv->GetUserExtension();
0735     if ( nullptr == extension )   {
0736       extension = new PlacedVolume::Object();
0737       pv->SetUserExtension(extension);
0738     }
0739     m_world.setPlacement(pv);
0740   }
0741   // Patching shape names of anaonymous shapes
0742   ShapePatcher patcher(m_volManager, m_world);
0743   patcher.patchShapes();
0744   mapDetectorTypes();
0745   m_state = READY;
0746   //DetectorGuard(this).unlock();
0747 }
0748 
0749 /// Initialize the geometry and set the bounding box of the world volume
0750 void DetectorImp::init() {
0751   if (!m_world.isValid()) {
0752     TGeoManager* mgr = m_manager;
0753     std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0754     Constant     air_const = getRefChild(m_define, "Air", false);
0755     Constant     vac_const = getRefChild(m_define, "Vacuum", false);
0756     Box          worldSolid;
0757     
0758     m_materialVacuum = material(vac_const.isValid() ? vac_const->GetTitle() : "Vacuum");
0759 
0760     m_worldVol = m_manager->GetTopVolume();
0761     if ( m_worldVol.isValid() )   {
0762       worldSolid    = m_worldVol.solid();
0763       m_materialAir = m_worldVol.material();
0764       printout(INFO,"Detector", "*********** Use Top Node from manager as "
0765                "world volume [%s].  Material: %s BBox: %4.0f %4.0f %4.0f",
0766                worldSolid->IsA()->GetName(), m_materialAir.name(),
0767                worldSolid->GetDX(), worldSolid->GetDY(), worldSolid->GetDZ());
0768     }
0769     else   {
0770       /// Construct the top level world element
0771       Solid parallelWorldSolid = Box("world_x", "world_y", "world_z");
0772       worldSolid    = Box("world_x", "world_y", "world_z");
0773       m_materialAir = material(air_const.isValid() ? air_const->GetTitle() : "Air");
0774       m_worldVol    = Volume("world_volume", worldSolid, m_materialAir);
0775       parallelWorldSolid->SetName("parallel_world_solid");
0776       printout(INFO,"Detector","*********** Created World volume with size: %4.0f %4.0f %4.0f",
0777                worldSolid->GetDX(), worldSolid->GetDY(), worldSolid->GetDZ());
0778     }
0779     m_world = DetElement(new WorldObject(*this,"world"));
0780     /// Set the world volume to invisible.
0781     VisAttr worldVis = visAttributes("WorldVis");
0782     if ( !worldVis.isValid() )  {
0783       worldVis = VisAttr("WorldVis");
0784       worldVis.setVisible(false);
0785       worldVis.setShowDaughters(true);
0786       worldVis.setColor(1., 1., 1., 1.);
0787       worldVis.setLineStyle(VisAttr::SOLID);
0788       worldVis.setDrawingStyle(VisAttr::WIREFRAME);
0789       //m_worldVol.setVisAttributes(worldVis);
0790       m_worldVol->SetVisibility(kFALSE);
0791       m_worldVol->SetVisDaughters(kTRUE);
0792       m_worldVol->SetVisContainers(kTRUE);
0793       add(worldVis);
0794     }
0795     m_worldVol.setVisAttributes(worldVis);
0796     m_manager->SetTopVolume(m_worldVol.ptr());
0797 
0798     /// Set the top level volume to the TGeomanager
0799     m_detectors.append(m_world);
0800     m_world.setPlacement(mgr->GetTopNode());
0801 
0802     /// Construct the parallel world
0803     m_parallelWorldVol = Volume("parallel_world_volume", worldSolid, m_materialAir);
0804 
0805     /// Construct the field envelope
0806     m_field = OverlayedField("global");
0807     m_state = LOADING;
0808   }
0809 }
0810 
0811 /// Read any geometry description or alignment file
0812 void DetectorImp::fromXML(const std::string& xmlfile, DetectorBuildType build_type) {
0813   std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0814   m_buildType = build_type;
0815   processXML(xmlfile, 0);
0816 }
0817 
0818 /// Read any geometry description or alignment file with external XML entity resolution
0819 void DetectorImp::fromXML(const std::string& fname, xml::UriReader* entity_resolver, DetectorBuildType build_type)  {
0820   std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0821   m_buildType = build_type;
0822   processXML(fname, entity_resolver);
0823 }
0824 
0825 void DetectorImp::dump() const {
0826   TGeoManager* mgr = m_manager;
0827   mgr->SetVisLevel(4);
0828   mgr->SetVisOption(1);
0829   m_worldVol->Draw("ogl");
0830 }
0831 
0832 /// Manipulate geometry using facroy converter
0833 long DetectorImp::apply(const char* factory_type, int argc, char** argv)   const   {
0834   std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0835   std::string fac = factory_type;
0836   try {
0837     Detector* thisPtr = const_cast<DetectorImp*>(this);
0838     long result = PluginService::Create<long>(fac, thisPtr, argc, argv);
0839     if (0 == result) {
0840       PluginDebug dbg;
0841       result = PluginService::Create<long>(fac, thisPtr, argc, argv);
0842       if ( 0 == result )  {
0843         throw std::runtime_error("dd4hep: apply-plugin: Failed to locate plugin " +
0844                                  fac + ". " + dbg.missingFactory(fac));
0845       }
0846     }
0847     result = *(long*) result;
0848     if (result != 1) {
0849       throw std::runtime_error("dd4hep: apply-plugin: Failed to execute plugin " + fac);
0850     }
0851     return result;
0852   }
0853   catch (const xml::XmlException& e) {
0854     throw std::runtime_error(xml::_toString(e.msg) + "\ndd4hep: XML-DOM Exception with plugin:" + fac);
0855   }
0856   catch (const std::exception& e) {
0857     throw std::runtime_error(std::string(e.what()) + "\ndd4hep: with plugin:" + fac);
0858   }
0859   catch (...) {
0860     throw std::runtime_error("UNKNOWN exception from plugin:" + fac);
0861   }
0862   return EINVAL;
0863 }