File indexing completed on 2026-07-25 08:26:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #define DETECTORTOOLS_CPP
0016 #include <DD4hep/DetectorTools.h>
0017 #include <DD4hep/Printout.h>
0018 #include <DD4hep/Detector.h>
0019 #include <DD4hep/detail/DetectorInterna.h>
0020
0021
0022 #include <stdexcept>
0023 #include <sstream>
0024 #include <string>
0025
0026
0027 #include <TGeoMatrix.h>
0028
0029
0030 namespace dd4hep {
0031
0032
0033
0034
0035
0036
0037 namespace detail { namespace tools {
0038
0039 std::string elementPath(const PlacementPath& nodes, bool reverse);
0040
0041 void elementPath(DetElement parent, DetElement elt, ElementPath& detectors);
0042
0043 void elementPath(DetElement elt, PlacementPath& nodes);
0044
0045 void elementPath(DetElement parent, DetElement element, PlacementPath& nodes);
0046
0047 bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path);
0048
0049
0050
0051 static void makePlacementPath(PlacementPath det_nodes, PlacementPath& all_nodes);
0052 }}
0053 }
0054
0055 using namespace dd4hep;
0056
0057
0058 bool detail::tools::isParentElement(DetElement parent, DetElement child) {
0059 if ( parent.isValid() && child.isValid() ) {
0060 if ( parent.ptr() == child.ptr() ) return true;
0061 for(DetElement par=child; par.isValid(); par=par.parent()) {
0062 if ( par.ptr() == parent.ptr() ) return true;
0063 }
0064 }
0065 throw std::runtime_error("Search for parent detector element with invalid handles not allowed.");
0066 }
0067
0068
0069 bool detail::tools::findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path) {
0070 if ( parent.isValid() && child.isValid() ) {
0071
0072 if ( parent.ptr() == child.ptr() ) {
0073 path.emplace_back(child);
0074 return true;
0075 }
0076 TIter next(parent->GetVolume()->GetNodes());
0077
0078 for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
0079 if ( daughter == child.ptr() ) {
0080 path.emplace_back(daughter);
0081 return true;
0082 }
0083 }
0084 next.Reset();
0085
0086 for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
0087 PlacementPath sub_path;
0088 bool res = findChild(daughter, child, sub_path);
0089 if (res) {
0090 path.insert(path.end(), sub_path.begin(), sub_path.end());
0091 path.emplace_back(daughter);
0092 return res;
0093 }
0094 }
0095 }
0096 return false;
0097 }
0098
0099
0100 static bool findChildByName(PlacedVolume parent, PlacedVolume child, detail::tools::PlacementPath& path) {
0101 if ( parent.isValid() && child.isValid() ) {
0102
0103 if ( 0 == ::strcmp(parent.ptr()->GetName(),child.ptr()->GetName()) ) {
0104 path.emplace_back(child);
0105 return true;
0106 }
0107 TIter next(parent->GetVolume()->GetNodes());
0108
0109 for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
0110 if ( 0 == ::strcmp(daughter->GetName(),child.ptr()->GetName()) ) {
0111 path.emplace_back(daughter);
0112 return true;
0113 }
0114 }
0115 next.Reset();
0116
0117 for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
0118 detail::tools::PlacementPath sub_path;
0119 bool res = findChildByName(daughter, child, sub_path);
0120 if (res) {
0121 path.insert(path.end(), sub_path.begin(), sub_path.end());
0122 path.emplace_back(daughter);
0123 return res;
0124 }
0125 }
0126 }
0127 return false;
0128 }
0129
0130
0131 void detail::tools::elementPath(DetElement element, ElementPath& detectors) {
0132 for(DetElement par = element; par.isValid(); par = par.parent())
0133 detectors.emplace_back(par);
0134 }
0135
0136
0137 void detail::tools::elementPath(DetElement parent, DetElement child, ElementPath& detectors) {
0138 detectors.clear();
0139 if ( parent.isValid() && child.isValid() ) {
0140 if ( parent.ptr() == child.ptr() ) {
0141 detectors.emplace_back(child);
0142 return;
0143 }
0144 ElementPath elements;
0145 for(DetElement par = child; par.isValid(); par = par.parent()) {
0146 elements.emplace_back(par);
0147 if ( par.ptr() == parent.ptr() ) {
0148 detectors = elements;
0149 return;
0150 }
0151 }
0152 throw std::runtime_error(std::string("The detector element ")+parent.name()+std::string(" is no parent of ")+child.name());
0153 }
0154 throw std::runtime_error("Search for parent detector element with invalid handles not allowed.");
0155 }
0156
0157
0158 void detail::tools::elementPath(DetElement parent, DetElement element, PlacementPath& det_nodes) {
0159 if( element.isValid() ) {
0160 if( !parent.isValid() ) {
0161 parent = element.world();
0162 }
0163 for( DetElement par = element; par.isValid(); par = par.parent() ) {
0164 PlacedVolume pv = par.placement();
0165 if ( pv.isValid() ) {
0166 det_nodes.emplace_back(pv);
0167 }
0168 if ( par.ptr() == parent.ptr() ) return;
0169 }
0170 throw std::runtime_error(("The detector element "+std::string(parent.name())+" is no parent of ")+element.name());
0171 }
0172 throw std::runtime_error("Cannot access element path [Invalid DetElement]");
0173 }
0174
0175
0176 void detail::tools::elementPath(DetElement element, PlacementPath& det_nodes) {
0177 for(DetElement par = element; par.isValid(); par = par.parent()) {
0178 PlacedVolume pv = par.placement();
0179 if ( pv.isValid() ) {
0180 det_nodes.emplace_back(pv);
0181 }
0182 }
0183 }
0184
0185
0186 std::string detail::tools::elementPath(const PlacementPath& nodes, bool reverse) {
0187 std::string path = "";
0188 if ( reverse ) {
0189 for(auto i=nodes.rbegin(); i != nodes.rend(); ++i)
0190 path += "/" + std::string((*i).name());
0191 }
0192 else {
0193 for(auto i=begin(nodes); i != end(nodes); ++i)
0194 path += "/" + std::string((*i)->GetName());
0195 }
0196 return path;
0197 }
0198
0199
0200 std::string detail::tools::elementPath(const ElementPath& nodes, bool reverse) {
0201 std::string path = "";
0202 if ( reverse ) {
0203 for(ElementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
0204 path += "/" + std::string((*i)->GetName());
0205 }
0206 else {
0207 for(ElementPath::const_iterator i=nodes.begin();i!=nodes.end();++i)
0208 path += "/" + std::string((*i)->GetName());
0209 }
0210 return path;
0211 }
0212
0213
0214 std::string detail::tools::elementPath(DetElement element) {
0215 ElementPath nodes;
0216 elementPath(element,nodes);
0217 return elementPath(nodes);
0218 }
0219
0220
0221 DetElement detail::tools::findElement(const Detector& description, const std::string& path) {
0222 return findDaughterElement(description.world(),path);
0223 }
0224
0225
0226 DetElement detail::tools::findDaughterElement(DetElement parent, const std::string& subpath) {
0227 if ( parent.isValid() ) {
0228 size_t idx = subpath.find('/',1);
0229 if ( subpath[0] == '/' ) {
0230 DetElement top = topElement(parent);
0231 if ( idx == std::string::npos ) return top;
0232 return findDaughterElement(top,subpath.substr(idx+1));
0233 }
0234 if ( idx == std::string::npos )
0235 return parent.child(subpath);
0236 std::string name = subpath.substr(0,idx);
0237 DetElement node = parent.child(name);
0238 if ( node.isValid() ) {
0239 return findDaughterElement(node,subpath.substr(idx+1));
0240 }
0241 throw std::runtime_error("dd4hep: DetElement "+parent.path()+" has no child named:"+name+" [No such child]");
0242 }
0243 throw std::runtime_error("dd4hep: Cannot determine child with path "+subpath+" from invalid parent [invalid handle]");
0244 }
0245
0246
0247 DetElement detail::tools::topElement(DetElement child) {
0248 if ( child.isValid() ) {
0249 if ( child.parent().isValid() )
0250 return topElement(child.parent());
0251 return child;
0252 }
0253 throw std::runtime_error("dd4hep: DetElement cannot determine top parent (world) [invalid handle]");
0254 }
0255
0256 static void detail::tools::makePlacementPath(PlacementPath det_nodes, PlacementPath& all_nodes) {
0257 for (size_t i = 0, n = det_nodes.size(); n > 0 && i < n-1; ++i) {
0258 if (!findChildByName(det_nodes[i + 1], det_nodes[i], all_nodes)) {
0259 throw std::runtime_error("dd4hep: DetElement cannot determine placement path of "
0260 + std::string(det_nodes[i].name()) + " [internal error]");
0261 }
0262 }
0263 if ( det_nodes.size() > 0 ) {
0264 all_nodes.emplace_back(det_nodes.back());
0265 }
0266 }
0267
0268
0269 void detail::tools::placementPath(DetElement element, PlacementPath& all_nodes) {
0270 PlacementPath det_nodes;
0271 elementPath(element,det_nodes);
0272 makePlacementPath(std::move(det_nodes), all_nodes);
0273 }
0274
0275
0276 void detail::tools::placementPath(DetElement parent, DetElement element, PlacementPath& all_nodes) {
0277 PlacementPath det_nodes;
0278 elementPath(parent,element,det_nodes);
0279 makePlacementPath(std::move(det_nodes), all_nodes);
0280 }
0281
0282
0283 std::string detail::tools::placementPath(DetElement element) {
0284 PlacementPath path;
0285 placementPath(element,path);
0286 return placementPath(std::move(path));
0287 }
0288
0289
0290 std::string detail::tools::placementPath(const PlacementPath& nodes, bool reverse) {
0291 std::string path = "";
0292 if ( reverse ) {
0293 for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
0294 path += "/" + std::string((*i)->GetName());
0295 }
0296 else {
0297 for(PlacementPath::const_iterator i=nodes.begin();i!=nodes.end();++i)
0298 path += "/" + std::string((*i)->GetName());
0299 }
0300 return path;
0301 }
0302
0303
0304 std::string detail::tools::placementPath(const std::vector<const TGeoNode*>& nodes, bool reverse) {
0305 std::string path = "";
0306 if ( reverse ) {
0307 for(std::vector<const TGeoNode*>::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
0308 path += "/" + std::string((*i)->GetName());
0309 return path;
0310 }
0311 for( const auto* n : nodes )
0312 path += "/" + std::string(n->GetName());
0313 return path;
0314 }
0315
0316
0317 void detail::tools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix*& mat) {
0318 if ( !mat ) mat = new TGeoHMatrix(*gGeoIdentity);
0319 placementTrafo(nodes,inverse,*mat);
0320 }
0321
0322
0323 void detail::tools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix& mat) {
0324 mat = *gGeoIdentity;
0325 if (nodes.size() > 0) {
0326 for (size_t i = 0, n=nodes.size(); n>0 && i < n-1; ++i) {
0327 const PlacedVolume& p = nodes[i];
0328 mat.MultiplyLeft(p->GetMatrix());
0329 }
0330 if ( inverse ) mat = mat.Inverse();
0331 }
0332 }
0333
0334
0335 PlacedVolume detail::tools::findNode(PlacedVolume top_place, const std::string& place) {
0336 TGeoNode* top = top_place.ptr();
0337 const char* path = place.c_str();
0338
0339 Int_t length = strlen(path);
0340 if (!length) return 0;
0341 TString spath = path;
0342 TGeoVolume *vol;
0343
0344 Int_t ind1 = spath.Index("/");
0345 if (ind1<0) {
0346
0347 if ( strcmp(path,top->GetName()) ) return 0;
0348 return top;
0349 }
0350 Int_t ind2 = ind1;
0351 Bool_t end = kFALSE;
0352 if (ind1>0) ind1 = -1;
0353 else ind2 = spath.Index("/", ind1+1);
0354
0355 if (ind2<0) ind2 = length;
0356 TString name(spath(ind1+1, ind2-ind1-1));
0357 if ( name == top->GetName() ) {
0358 if (ind2>=length-1) return top;
0359 ind1 = ind2;
0360 }
0361 else {
0362 return 0;
0363 }
0364 TGeoNode *node = top;
0365
0366 while (!end) {
0367 ind2 = spath.Index("/", ind1+1);
0368 if (ind2<0) {
0369 ind2 = length;
0370 end = kTRUE;
0371 }
0372 vol = node->GetVolume();
0373 name = spath(ind1+1, ind2-ind1-1);
0374 node = vol->GetNode(name.Data());
0375 if (!node)
0376 return 0;
0377 else if (ind2>=length-1)
0378 return node;
0379 ind1 = ind2;
0380 }
0381 return node;
0382 }
0383
0384
0385 std::string detail::tools::toString(const PlacedVolume::VolIDs& ids) {
0386 std::stringstream log;
0387 for( const auto& v : ids )
0388 log << v.first << "=" << v.second << "; ";
0389 return log.str();
0390 }
0391
0392
0393 std::string detail::tools::toString(const IDDescriptor& dsc, const PlacedVolume::VolIDs& ids, VolumeID code) {
0394 std::stringstream log;
0395 for( const auto& id : ids ) {
0396 const BitFieldElement* f = dsc.field(id.first);
0397 VolumeID value = f->value(code);
0398 log << id.first << "=" << id.second << "," << value << " [" << f->offset() << "," << f->width() << "] ";
0399 }
0400 return log.str();
0401 }
0402
0403
0404 std::vector<std::string> detail::tools::pathElements(const std::string& path) {
0405 std::vector<std::string> result;
0406 if ( !path.empty() ) {
0407 std::string tmp = path[0]=='/' ? path.substr(1) : path;
0408 for(size_t idx=tmp.find('/'); idx != std::string::npos; idx=tmp.find('/')) {
0409 std::string val = tmp.substr(0,idx);
0410 result.emplace_back(val);
0411 tmp = tmp.length()>idx ? tmp.substr(idx+1) : std::string();
0412 }
0413 if ( !tmp.empty() ) {
0414 result.emplace_back(tmp);
0415 }
0416 }
0417 return result;
0418 }