File indexing completed on 2025-07-11 07:52:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #define DD4HEP_MUST_USE_DETECTORIMP_H 1
0015
0016
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
0032 #include <iostream>
0033 #include <stdexcept>
0034 #include <cerrno>
0035 #include <mutex>
0036
0037
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
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
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
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
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
0209 TGeoElementTable* table = m_manager->GetElementTable();
0210 table->TGeoElementTable::~TGeoElementTable();
0211 new(table) TGeoElementTable();
0212
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
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
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
0282 void DetectorImp::imp_loadVolumeManager() {
0283 detail::destroyHandle(m_volManager);
0284 m_volManager = VolumeManager(*this, "World", world(), Readout(), VolumeManager::TREE);
0285 }
0286
0287
0288 void* DetectorImp::addUserExtension(unsigned long long int key, ExtensionEntry* entry) {
0289 return m_extensions.addExtension(key,entry);
0290 }
0291
0292
0293 void* DetectorImp::removeUserExtension(unsigned long long int key, bool destroy) {
0294 return m_extensions.removeExtension(key,destroy);
0295 }
0296
0297
0298 void* DetectorImp::userExtension(unsigned long long int key, bool alert) const {
0299 return m_extensions.extension(key,alert);
0300 }
0301
0302
0303 DetectorBuildType DetectorImp::buildType() const {
0304 std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0305 DetectorBuildType temp = m_buildType;
0306 return temp;
0307 }
0308
0309
0310 void DetectorImp::declareParent(const std::string& detector_name, const DetElement& parent) {
0311 if ( !detector_name.empty() ) {
0312 if ( parent.isValid() ) {
0313 auto i = m_detectorParents.find(detector_name);
0314 if (i == m_detectorParents.end()) {
0315 Volume parent_volume = parent.placement().volume();
0316 if ( parent_volume.isValid() ) {
0317 m_detectorParents.emplace(detector_name,parent);
0318 return;
0319 }
0320 except("DD4hep","+++ Failed to access valid parent volume of %s from %s",
0321 detector_name.c_str(), parent.name());
0322 }
0323 except("DD4hep",
0324 "+++ A parent to the detector %s was already registered.",
0325 detector_name.c_str());
0326 }
0327 except("DD4hep",
0328 "+++ Attempt to register invalid parent for detector: %s [Invalid-Handle].",
0329 detector_name.c_str());
0330 }
0331 except("DD4hep",
0332 "+++ Attempt to register parent to invalid detector [Invalid-detector-name].");
0333 }
0334
0335
0336 Volume DetectorImp::pickMotherVolume(const DetElement& de) const {
0337 if ( de.isValid() ) {
0338 std::string de_name = de.name();
0339 auto i = m_detectorParents.find(de_name);
0340 if (i == m_detectorParents.end()) {
0341 if ( m_worldVol.isValid() ) {
0342 return m_worldVol;
0343 }
0344 except("DD4hep",
0345 "+++ The world volume is not (yet) valid. "
0346 "Are you correctly building detector %s?",
0347 de.name());
0348 }
0349 if ( (*i).second.isValid() ) {
0350 Volume vol = (*i).second.volume();
0351 if ( vol.isValid() ) {
0352 return vol;
0353 }
0354 }
0355 except("DD4hep",
0356 "+++ The mother volume of %s is not valid. "
0357 "Are you correctly building detectors?",
0358 de.name());
0359 }
0360 except("DD4hep","Detector: Attempt access mother volume of invalid detector [Invalid-handle]");
0361 return 0;
0362 }
0363
0364
0365 const STD_Conditions& DetectorImp::stdConditions() const {
0366 if ( (m_std_conditions.convention&STD_Conditions::USER_SET) == 0 &&
0367 (m_std_conditions.convention&STD_Conditions::USER_NOTIFIED) == 0 )
0368 {
0369 printout(WARNING,"DD4hep","++ STD conditions NOT defined by client. NTP defaults taken.");
0370 m_std_conditions.convention |= STD_Conditions::USER_NOTIFIED;
0371 }
0372 return m_std_conditions;
0373 }
0374
0375 void DetectorImp::setStdConditions(double temp, double pressure) {
0376 m_std_conditions.temperature = temp;
0377 m_std_conditions.pressure = pressure;
0378 m_std_conditions.convention = STD_Conditions::USER_SET;
0379 if ( std::abs(temp-Temperature_NTP) < 1e-10 && std::abs(pressure-Pressure_NTP) < 1e-10 )
0380 m_std_conditions.convention |= STD_Conditions::NTP;
0381 else if ( std::abs(temp-Temperature_STP) < 1e-10 && std::abs(pressure-Pressure_STP) < 1e-10 )
0382 m_std_conditions.convention |= STD_Conditions::STP;
0383 else
0384 m_std_conditions.convention |= STD_Conditions::USER;
0385 }
0386
0387
0388 void DetectorImp::setStdConditions(const std::string& type) {
0389 if ( type == "STP" ) {
0390 m_std_conditions.temperature = Temperature_STP;
0391 m_std_conditions.pressure = Pressure_STP;
0392 m_std_conditions.convention = STD_Conditions::STP|STD_Conditions::USER_SET;
0393 }
0394 else if ( type == "NTP" ) {
0395 m_std_conditions.temperature = Temperature_NTP;
0396 m_std_conditions.pressure = Pressure_NTP;
0397 m_std_conditions.convention = STD_Conditions::NTP|STD_Conditions::USER_SET;
0398 }
0399 else {
0400 except("DD4hep",
0401 "++ Attempt to set standard conditions to "
0402 "unknown conventions (Only STP and NTP allowed).");
0403 }
0404 }
0405
0406
0407 DetElement DetectorImp::detector(const std::string& name) const {
0408 HandleMap::const_iterator i = m_detectors.find(name);
0409 if (i != m_detectors.end()) {
0410 return (*i).second;
0411 }
0412 DetElement de = detail::tools::findElement(*this,name);
0413 return de;
0414 }
0415
0416 Detector& DetectorImp::addDetector(const Handle<NamedObject>& ref_det) {
0417 DetElement det_element(ref_det);
0418 DetectorHelper helper(this);
0419 DetElement existing_det = helper.detectorByID(det_element.id());
0420
0421 if ( existing_det.isValid() ) {
0422 SensitiveDetector sd = helper.sensitiveDetector(existing_det);
0423 if ( sd.isValid() ) {
0424 std::stringstream str;
0425 str << "Detector: The sensitive sub-detectors " << det_element.name() << " and "
0426 << existing_det.name() << " have the identical ID:" << det_element.id() << ".";
0427 except("DD4hep",str.str());
0428 }
0429 }
0430 m_detectors.append(ref_det);
0431 det_element->flag |= DetElement::Object::IS_TOP_LEVEL_DETECTOR;
0432 PlacedVolume pv = det_element.placement();
0433 if ( !pv.isValid() ) {
0434 std::stringstream str;
0435 str << "Detector: Adding subdetectors with no valid placement is not allowed: "
0436 << det_element.name() << " ID:" << det_element.id() << ".";
0437 except("DD4hep",str.str());
0438 }
0439 Volume volume = pv->GetMotherVolume();
0440 if ( volume == m_worldVol ) {
0441 printout(DEBUG,"DD4hep","+++ Detector: Added detector %s to the world instance.",
0442 det_element.name());
0443 m_world.add(det_element);
0444 return *this;
0445 }
0446
0447 auto ipar = m_detectorParents.find(det_element.name());
0448 if (ipar != m_detectorParents.end()) {
0449 DetElement parent = (*ipar).second;
0450 parent.add(det_element);
0451 printout(DEBUG,"DD4hep","+++ Detector: Added detector %s to parent %s.",
0452 det_element.name(), parent.name());
0453 return *this;
0454 }
0455
0456
0457 for(HandleMap::iterator idet = m_detectors.begin(); idet != m_detectors.end(); ++idet) {
0458 DetElement parent((*idet).second);
0459 Volume vol = parent.placement().volume();
0460 if ( vol == volume ) {
0461 printout(INFO,"DD4hep","+++ Detector: Added detector %s to the parent:%s.",
0462 det_element.name(),parent.name());
0463 parent.add(det_element);
0464 return *this;
0465 }
0466 }
0467 except("DD4hep","+++ Detector: The detector %s has no known parent.", det_element.name());
0468 throw std::runtime_error("Detector-Error");
0469 }
0470
0471
0472 Detector& DetectorImp::addConstant(const Handle<NamedObject>& x) {
0473 if ( strcmp(x.name(),"Detector_InhibitConstants") == 0 ) {
0474 const char* title = x->GetTitle();
0475 char c = ::toupper(title[0]);
0476 m_inhibitConstants = (c=='Y' || c=='T' || c=='1');
0477 }
0478 m_define.append(x, false);
0479 return *this;
0480 }
0481
0482
0483 Constant DetectorImp::constant(const std::string& name) const {
0484 if ( !m_inhibitConstants ) {
0485 return getRefChild(m_define, name);
0486 }
0487 throw std::runtime_error("Detector:constant("+name+"): Access to global constants is inhibited.");
0488 }
0489
0490
0491 std::string DetectorImp::constantAsString(const std::string& name) const {
0492 if ( !m_inhibitConstants ) {
0493 Handle<NamedObject> c = constant(name);
0494 if (c.isValid())
0495 return c->GetTitle();
0496 throw std::runtime_error("Detector:constantAsString: The constant " + name + " is not known to the system.");
0497 }
0498 throw std::runtime_error("Detector:constantAsString("+name+"):: Access to global constants is inhibited.");
0499 }
0500
0501
0502 long DetectorImp::constantAsLong(const std::string& name) const {
0503 if ( !m_inhibitConstants ) {
0504 return _toLong(constantAsString(name));
0505 }
0506 throw std::runtime_error("Detector:constantAsLong("+name+"): Access to global constants is inhibited.");
0507 }
0508
0509
0510 double DetectorImp::constantAsDouble(const std::string& name) const {
0511 if ( !m_inhibitConstants ) {
0512 return _toDouble(constantAsString(name));
0513 }
0514 throw std::runtime_error("Detector:constantAsDouble("+name+"): Access to global constants is inhibited.");
0515 }
0516
0517
0518 Detector& DetectorImp::addField(const Handle<NamedObject>& x) {
0519 m_field.add(x);
0520 m_fields.append(x);
0521 return *this;
0522 }
0523
0524
0525 Material DetectorImp::material(const std::string& name) const {
0526 TGeoMedium* mat = m_manager->GetMedium(name.c_str());
0527 if (mat) {
0528 return Material(mat);
0529 }
0530 throw std::runtime_error("Cannot find a material referenced by name:" + name);
0531 }
0532
0533
0534 void DetectorImp::mapDetectorTypes() {
0535 m_detectorTypes[""] = {};
0536 for( const auto& i : m_detectors ) {
0537 DetElement det(i.second);
0538 if ( det.parent().isValid() ) {
0539 HandleMap::const_iterator j=m_sensitive.find(det.name());
0540 if ( j != m_sensitive.end() ) {
0541 SensitiveDetector sd((*j).second);
0542 m_detectorTypes[sd.type()].emplace_back(det);
0543 }
0544 else if ( det.type() == "compound" ) {
0545 m_detectorTypes[det.type()].emplace_back(det);
0546 }
0547 else {
0548 m_detectorTypes["passive"].emplace_back(det);
0549 }
0550 }
0551 }
0552 }
0553
0554
0555 std::vector<std::string> DetectorImp::detectorTypes() const {
0556 if ( m_manager->IsClosed() ) {
0557 std::vector<std::string> v;
0558 v.reserve(m_detectorTypes.size());
0559 for(const auto& t : m_detectorTypes )
0560 v.emplace_back(t.first);
0561 return v;
0562 }
0563 throw std::runtime_error("detectorTypes: Call only available once the geometry is closed!");
0564 }
0565
0566
0567 const std::vector<DetElement>& DetectorImp::detectors(const std::string& type, bool throw_exc) const {
0568 if ( m_manager->IsClosed() ) {
0569 DetectorTypeMap::const_iterator i=m_detectorTypes.find(type);
0570 if ( i != m_detectorTypes.end() ) return (*i).second;
0571 if ( throw_exc ) {
0572 throw std::runtime_error("detectors("+type+"): Detectors of this type do not exist in the current setup!");
0573 }
0574
0575 return m_detectorTypes.at("") ;
0576 }
0577 throw std::runtime_error("detectors("+type+"): Detectors can only selected by type once the geometry is closed!");
0578 }
0579
0580 std::vector<DetElement> DetectorImp::detectors(unsigned int includeFlag, unsigned int excludeFlag ) const {
0581 if( ! m_manager->IsClosed() ) {
0582 throw std::runtime_error("detectors(typeFlag): Detectors can only selected by typeFlag once the geometry is closed!");
0583 }
0584 std::vector<DetElement> dets ;
0585 dets.reserve( m_detectors.size() ) ;
0586
0587 for(HandleMap::const_iterator i=m_detectors.begin(); i!=m_detectors.end(); ++i) {
0588 DetElement det((*i).second);
0589 if ( det.parent().isValid() ) {
0590
0591
0592
0593
0594 if( ( det.typeFlag() & includeFlag ) == includeFlag &&
0595 ( det.typeFlag() & excludeFlag ) == 0 )
0596 dets.emplace_back( det ) ;
0597 }
0598 }
0599 return dets ;
0600 }
0601
0602
0603 std::vector<DetElement> DetectorImp::detectors(const std::string& type1,
0604 const std::string& type2,
0605 const std::string& type3,
0606 const std::string& type4,
0607 const std::string& type5 ) {
0608 if ( m_manager->IsClosed() ) {
0609 std::vector<DetElement> v;
0610 DetectorTypeMap::const_iterator i, end=m_detectorTypes.end();
0611 if ( !type1.empty() && (i=m_detectorTypes.find(type1)) != end )
0612 v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0613 if ( !type2.empty() && (i=m_detectorTypes.find(type2)) != end )
0614 v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0615 if ( !type3.empty() && (i=m_detectorTypes.find(type3)) != end )
0616 v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0617 if ( !type4.empty() && (i=m_detectorTypes.find(type4)) != end )
0618 v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0619 if ( !type5.empty() && (i=m_detectorTypes.find(type5)) != end )
0620 v.insert(v.end(),(*i).second.begin(),(*i).second.end());
0621 return v;
0622 }
0623 throw std::runtime_error("detectors("+type1+","+type2+",...): Detectors can only selected by type once the geometry is closed!");
0624 }
0625
0626 Handle<NamedObject> DetectorImp::getRefChild(const HandleMap& e, const std::string& name, bool do_throw) const {
0627 HandleMap::const_iterator it = e.find(name);
0628 if (it != e.end()) {
0629 return it->second;
0630 }
0631 if (do_throw) {
0632 union ptr {
0633 const ObjectHandleMap* omap;
0634 const char* c;
0635 const void* other;
0636 ptr(const void* p) { other = p; }
0637 };
0638 std::string nam = "";
0639 ptr mptr(&e), ref(this);
0640 if ( ref.c > mptr.c && mptr.c < ref.c+sizeof(*this) ) {
0641 nam = mptr.omap->name;
0642 }
0643 std::stringstream err;
0644 err << "getRefChild: Failed to find child with name: " << name
0645 << " Map " << nam << " contains " << e.size() << " elements: {";
0646 for (it = e.begin(); it != e.end(); ++it) {
0647 if (it != e.begin()) {
0648 err << ", ";
0649 }
0650 err << it->first;
0651 }
0652 err << "}";
0653 throw std::runtime_error(err.str());
0654 }
0655 return 0;
0656 }
0657
0658 namespace {
0659 struct ShapePatcher: public detail::GeoScan {
0660 VolumeManager m_volManager;
0661 DetElement m_world;
0662 ShapePatcher(VolumeManager m, DetElement e)
0663 : detail::GeoScan(e), m_volManager(m), m_world(e) {
0664 }
0665 void patchShapes() {
0666 auto& data = *m_data;
0667 char text[32];
0668 std::string nam;
0669 printout(INFO,"Detector","+++ Patching names of anonymous shapes....");
0670 for (auto i = data.rbegin(); i != data.rend(); ++i) {
0671 for( const TGeoNode* n : (*i).second ) {
0672 TGeoVolume* vol = n->GetVolume();
0673 TGeoShape* s = vol->GetShape();
0674 const char* sn = s->GetName();
0675 ::snprintf(text,sizeof(text),"_shape_%p",(void*)s);
0676 if (0 == sn || 0 == ::strlen(sn)) {
0677 nam = vol->GetName();
0678 nam += text;
0679 s->SetName(nam.c_str());
0680 }
0681 else if (0 == ::strcmp(sn, s->IsA()->GetName())) {
0682 nam = vol->GetName();
0683 nam += text;
0684 s->SetName(nam.c_str());
0685 }
0686 else {
0687 nam = sn;
0688 if (nam.find("_shape") == std::string::npos)
0689 nam += text;
0690 s->SetName(nam.c_str());
0691 }
0692 if (s->IsA() == TGeoCompositeShape::Class()) {
0693 TGeoCompositeShape* c = (TGeoCompositeShape*) s;
0694 const TGeoBoolNode* boolean = c->GetBoolNode();
0695 s = boolean->GetLeftShape();
0696 sn = s->GetName();
0697 if (0 == sn || 0 == ::strlen(sn)) {
0698 s->SetName((nam + "_left").c_str());
0699 }
0700 else if (0 == ::strcmp(sn, s->IsA()->GetName())) {
0701 s->SetName((nam + "_left").c_str());
0702 }
0703 s = boolean->GetRightShape();
0704 sn = s->GetName();
0705 if (0 == sn || 0 == ::strlen(sn)) {
0706 s->SetName((nam + "_right").c_str());
0707 }
0708 else if (0 == ::strcmp(s->GetName(), s->IsA()->GetName())) {
0709 s->SetName((nam + "_right").c_str());
0710 }
0711 }
0712 }
0713 }
0714 }
0715 };
0716 }
0717
0718
0719 void DetectorImp::endDocument(bool close_geometry) {
0720 TGeoManager* mgr = m_manager;
0721 std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0722 if ( close_geometry && !mgr->IsClosed() ) {
0723 #if 0
0724 Region trackingRegion("TrackingRegion");
0725 trackingRegion.setThreshold(1);
0726 trackingRegion.setStoreSecondaries(true);
0727 add(trackingRegion);
0728 m_trackingVol.setRegion(trackingRegion);
0729
0730 VisAttr trackingVis("TrackingVis");
0731 trackingVis.setVisible(false);
0732 m_trackingVol.setVisAttributes(trackingVis);
0733 add(trackingVis);
0734 #endif
0735 m_worldVol.solid()->ComputeBBox();
0736
0737
0738
0739 mgr->CloseGeometry();
0740 PlacedVolume pv = mgr->GetTopNode();
0741 auto* extension = pv->GetUserExtension();
0742 if ( nullptr == extension ) {
0743 extension = new PlacedVolume::Object();
0744 pv->SetUserExtension(extension);
0745 }
0746 m_world.setPlacement(pv);
0747 }
0748
0749 ShapePatcher patcher(m_volManager, m_world);
0750 patcher.patchShapes();
0751 mapDetectorTypes();
0752 m_state = READY;
0753
0754 }
0755
0756
0757 void DetectorImp::init() {
0758 if (!m_world.isValid()) {
0759 TGeoManager* mgr = m_manager;
0760 std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0761 Constant air_const = getRefChild(m_define, "Air", false);
0762 Constant vac_const = getRefChild(m_define, "Vacuum", false);
0763 Box worldSolid;
0764
0765 m_materialVacuum = material(vac_const.isValid() ? vac_const->GetTitle() : "Vacuum");
0766
0767 m_worldVol = m_manager->GetTopVolume();
0768 if ( m_worldVol.isValid() ) {
0769 worldSolid = m_worldVol.solid();
0770 m_materialAir = m_worldVol.material();
0771 printout(INFO,"Detector", "*********** Use Top Node from manager as "
0772 "world volume [%s]. Material: %s BBox: %4.0f %4.0f %4.0f",
0773 worldSolid->IsA()->GetName(), m_materialAir.name(),
0774 worldSolid->GetDX(), worldSolid->GetDY(), worldSolid->GetDZ());
0775 }
0776 else {
0777
0778 Solid parallelWorldSolid = Box("world_x", "world_y", "world_z");
0779 worldSolid = Box("world_x", "world_y", "world_z");
0780 m_materialAir = material(air_const.isValid() ? air_const->GetTitle() : "Air");
0781 m_worldVol = Volume("world_volume", worldSolid, m_materialAir);
0782 parallelWorldSolid->SetName("parallel_world_solid");
0783 printout(INFO,"Detector","*********** Created World volume with size: %4.0f %4.0f %4.0f",
0784 worldSolid->GetDX(), worldSolid->GetDY(), worldSolid->GetDZ());
0785 }
0786 m_world = DetElement(new WorldObject(*this,"world"));
0787
0788 VisAttr worldVis = visAttributes("WorldVis");
0789 if ( !worldVis.isValid() ) {
0790 worldVis = VisAttr("WorldVis");
0791 worldVis.setVisible(false);
0792 worldVis.setShowDaughters(true);
0793 worldVis.setColor(1., 1., 1., 1.);
0794 worldVis.setLineStyle(VisAttr::SOLID);
0795 worldVis.setDrawingStyle(VisAttr::WIREFRAME);
0796
0797 m_worldVol->SetVisibility(kFALSE);
0798 m_worldVol->SetVisDaughters(kTRUE);
0799 m_worldVol->SetVisContainers(kTRUE);
0800 add(worldVis);
0801 }
0802 m_worldVol.setVisAttributes(worldVis);
0803 m_manager->SetTopVolume(m_worldVol.ptr());
0804
0805
0806 m_detectors.append(m_world);
0807 m_world.setPlacement(mgr->GetTopNode());
0808
0809
0810 m_parallelWorldVol = Volume("parallel_world_volume", worldSolid, m_materialAir);
0811
0812
0813 m_field = OverlayedField("global");
0814 m_state = LOADING;
0815 }
0816 }
0817
0818
0819 void DetectorImp::fromXML(const std::string& xmlfile, DetectorBuildType build_type) {
0820 std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0821 m_buildType = build_type;
0822 processXML(xmlfile, 0);
0823 }
0824
0825
0826 void DetectorImp::fromXML(const std::string& fname, xml::UriReader* entity_resolver, DetectorBuildType build_type) {
0827 std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0828 m_buildType = build_type;
0829 processXML(fname, entity_resolver);
0830 }
0831
0832 void DetectorImp::dump() const {
0833 TGeoManager* mgr = m_manager;
0834 mgr->SetVisLevel(4);
0835 mgr->SetVisOption(1);
0836 m_worldVol->Draw("ogl");
0837 }
0838
0839
0840 long DetectorImp::apply(const char* factory_type, int argc, char** argv) const {
0841 std::lock_guard<std::recursive_mutex> lock(s_detector_apply_lock);
0842 std::string fac = factory_type;
0843 try {
0844 Detector* thisPtr = const_cast<DetectorImp*>(this);
0845 long result = PluginService::Create<long>(fac, thisPtr, argc, argv);
0846 if (0 == result) {
0847 PluginDebug dbg;
0848 result = PluginService::Create<long>(fac, thisPtr, argc, argv);
0849 if ( 0 == result ) {
0850 throw std::runtime_error("dd4hep: apply-plugin: Failed to locate plugin " +
0851 fac + ". " + dbg.missingFactory(fac));
0852 }
0853 }
0854 result = *(long*) result;
0855 if (result != 1) {
0856 throw std::runtime_error("dd4hep: apply-plugin: Failed to execute plugin " + fac);
0857 }
0858 return result;
0859 }
0860 catch (const xml::XmlException& e) {
0861 throw std::runtime_error(xml::_toString(e.msg) + "\ndd4hep: XML-DOM Exception with plugin:" + fac);
0862 }
0863 catch (const std::exception& e) {
0864 throw std::runtime_error(std::string(e.what()) + "\ndd4hep: with plugin:" + fac);
0865 }
0866 catch (...) {
0867 throw std::runtime_error("UNKNOWN exception from plugin:" + fac);
0868 }
0869 return EINVAL;
0870 }