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