File indexing completed on 2025-03-13 08:19:38
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 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
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
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
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
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
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
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
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");
0462 }
0463
0464
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
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
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
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
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
0511 Detector& DetectorImp::addField(const Handle<NamedObject>& x) {
0512 m_field.add(x);
0513 m_fields.append(x);
0514 return *this;
0515 }
0516
0517
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
0527 void DetectorImp::mapDetectorTypes() {
0528 m_detectorTypes[""] = {};
0529 for( const auto& i : m_detectors ) {
0530 DetElement det(i.second);
0531 if ( det.parent().isValid() ) {
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
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
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
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() ) {
0583
0584
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
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
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
0723 VisAttr trackingVis("TrackingVis");
0724 trackingVis.setVisible(false);
0725 m_trackingVol.setVisAttributes(trackingVis);
0726 add(trackingVis);
0727 #endif
0728 m_worldVol.solid()->ComputeBBox();
0729
0730
0731
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
0742 ShapePatcher patcher(m_volManager, m_world);
0743 patcher.patchShapes();
0744 mapDetectorTypes();
0745 m_state = READY;
0746
0747 }
0748
0749
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
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
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
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
0799 m_detectors.append(m_world);
0800 m_world.setPlacement(mgr->GetTopNode());
0801
0802
0803 m_parallelWorldVol = Volume("parallel_world_volume", worldSolid, m_materialAir);
0804
0805
0806 m_field = OverlayedField("global");
0807 m_state = LOADING;
0808 }
0809 }
0810
0811
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
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
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 }