File indexing completed on 2024-04-06 12:05:29
0001 #include "DetectorDescription/DDCMS/interface/DDFilteredView.h"
0002 #include "DetectorDescription/DDCMS/interface/DDCompactView.h"
0003 #include "DetectorDescription/DDCMS/interface/DDDetector.h"
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 #include "DD4hep/Detector.h"
0006 #include "DD4hep/Shapes.h"
0007 #include <TGeoBBox.h>
0008 #include <TGeoBoolNode.h>
0009 #include <charconv>
0010
0011 using namespace cms;
0012 using namespace edm;
0013 using namespace std;
0014 using namespace cms::dd;
0015 using namespace dd4hep::dd;
0016
0017 dd4hep::Solid DDSolid::solidA() const {
0018 if (dd4hep::isA<dd4hep::SubtractionSolid>(solid_) or dd4hep::isA<dd4hep::UnionSolid>(solid_) or
0019 dd4hep::isA<dd4hep::IntersectionSolid>(solid_)) {
0020 const TGeoCompositeShape* sh = (const TGeoCompositeShape*)solid_.ptr();
0021 const TGeoBoolNode* boolean = sh->GetBoolNode();
0022 TGeoShape* solidA = boolean->GetLeftShape();
0023 return dd4hep::Solid(solidA);
0024 }
0025 return solid_;
0026 }
0027
0028 dd4hep::Solid DDSolid::solidB() const {
0029 if (dd4hep::isA<dd4hep::SubtractionSolid>(solid_) or dd4hep::isA<dd4hep::UnionSolid>(solid_) or
0030 dd4hep::isA<dd4hep::IntersectionSolid>(solid_)) {
0031 const TGeoCompositeShape* sh = static_cast<const TGeoCompositeShape*>(solid_.ptr());
0032 const TGeoBoolNode* boolean = sh->GetBoolNode();
0033 TGeoShape* solidB = boolean->GetRightShape();
0034 return dd4hep::Solid(solidB);
0035 }
0036 return solid_;
0037 }
0038
0039 const std::vector<double> DDSolid::parameters() const { return solid().dimensions(); }
0040
0041 DDFilteredView::DDFilteredView(const DDDetector* det, const Volume volume) : registry_(&det->specpars()) {
0042 it_.emplace_back(Iterator(volume));
0043 }
0044
0045 DDFilteredView::DDFilteredView(const DDCompactView& cpv, const cms::DDFilter& filter) : registry_(&cpv.specpars()) {
0046 it_.emplace_back(Iterator(cpv.detector()->worldVolume()));
0047 registry_->filter(refs_, filter.attribute(), filter.value());
0048 mergedSpecifics(refs_);
0049 LogVerbatim("Geometry").log([&](auto& log) {
0050 log << "Filtered by an attribute " << filter.attribute() << "==" << filter.value()
0051 << " DD SpecPar Registry size: " << refs_.size() << "\n";
0052 for (const auto& t : refs_) {
0053 log << "\nSpecPar " << std::string(t.first.data(), t.first.size()) << "\nRegExps { ";
0054 for (const auto& ki : t.second->paths)
0055 log << ki << " ";
0056 log << "};\n ";
0057 for (const auto& kl : t.second->spars) {
0058 log << kl.first << " = ";
0059 for (const auto& kil : kl.second) {
0060 log << kil << " ";
0061 }
0062 log << "\n ";
0063 }
0064 }
0065 });
0066 }
0067
0068 const PlacedVolume DDFilteredView::volume() const {
0069 assert(node_);
0070 return PlacedVolume(node_);
0071 }
0072
0073
0074
0075
0076 const std::string DDFilteredView::path() const {
0077 if (it_.empty()) {
0078 return std::string();
0079 }
0080 TString fullPath;
0081 it_.back().GetPath(fullPath);
0082 return std::string(fullPath.Data());
0083 }
0084
0085
0086
0087
0088
0089 const std::vector<int> DDFilteredView::copyNos() const {
0090 std::vector<int> result;
0091
0092 if (not it_.empty()) {
0093 for (int i = it_.back().GetLevel(); i > 0; --i) {
0094 result.emplace_back(it_.back().GetNode(i)->GetNumber());
0095 }
0096 }
0097
0098 return result;
0099 }
0100
0101 const Double_t* DDFilteredView::trans() const { return it_.back().GetCurrentMatrix()->GetTranslation(); }
0102
0103 const Translation DDFilteredView::translation() const {
0104 const Double_t* translation = it_.back().GetCurrentMatrix()->GetTranslation();
0105 assert(translation);
0106 return Translation(translation[0], translation[1], translation[2]);
0107 }
0108
0109 const Translation DDFilteredView::translation(const std::vector<Node*>& nodes) const {
0110 const TGeoMatrix* current = it_.back().GetCurrentMatrix();
0111 TGeoHMatrix matrix(*current);
0112 for (const auto& n : nodes) {
0113 matrix.Multiply(n->GetMatrix());
0114 }
0115 const Double_t* translation = matrix.GetTranslation();
0116 assert(translation);
0117 return Translation(translation[0], translation[1], translation[2]);
0118 }
0119
0120 const Double_t* DDFilteredView::rot() const { return it_.back().GetCurrentMatrix()->GetRotationMatrix(); }
0121
0122 const RotationMatrix DDFilteredView::rotation() const {
0123 const Double_t* rotation = it_.back().GetCurrentMatrix()->GetRotationMatrix();
0124 if (rotation == nullptr) {
0125 LogError("DDFilteredView") << "Current node has no valid rotation matrix.";
0126 return RotationMatrix();
0127 }
0128
0129 RotationMatrix rotMatrix;
0130 rotMatrix.SetComponents(rotation[0],
0131 rotation[1],
0132 rotation[2],
0133 rotation[3],
0134 rotation[4],
0135 rotation[5],
0136 rotation[6],
0137 rotation[7],
0138 rotation[8]);
0139 return rotMatrix;
0140 }
0141
0142 void DDFilteredView::rot(dd4hep::Rotation3D& matrixOut) const {
0143 const Double_t* rotation = it_.back().GetCurrentMatrix()->GetRotationMatrix();
0144 if (rotation == nullptr) {
0145 LogError("DDFilteredView") << "Current node has no valid rotation matrix.";
0146 return;
0147 }
0148 matrixOut.SetComponents(rotation[0],
0149 rotation[1],
0150 rotation[2],
0151 rotation[3],
0152 rotation[4],
0153 rotation[5],
0154 rotation[6],
0155 rotation[7],
0156 rotation[8]);
0157 }
0158
0159 void DDFilteredView::mergedSpecifics(DDSpecParRefs const& specPars) {
0160 currentSpecPar_ = nullptr;
0161 if (!filters_.empty()) {
0162 filters_.clear();
0163 filters_.shrink_to_fit();
0164 }
0165
0166 for (const auto& section : specPars) {
0167 for (const auto& partSelector : section.second->paths) {
0168 auto const& firstPartName = front(partSelector);
0169 auto const& filterMatch = find_if(begin(filters_), end(filters_), [&](auto const& it) {
0170 auto const& key =
0171 find_if(begin(it->skeys), end(it->skeys), [&](auto const& partName) { return firstPartName == partName; });
0172 if (key != end(it->skeys)) {
0173 currentFilter_ = it.get();
0174 return true;
0175 }
0176 return false;
0177 });
0178 if (filterMatch == end(filters_)) {
0179 filters_.emplace_back(make_unique<Filter>());
0180 filters_.back()->hasNamespace.emplace_back(dd4hep::dd::hasNamespace(firstPartName));
0181 if (dd4hep::dd::isRegex(firstPartName)) {
0182 filters_.back()->isRegex.emplace_back(true);
0183 filters_.back()->index.emplace_back(filters_.back()->keys.size());
0184 filters_.back()->keys.emplace_back(std::regex(std::begin(firstPartName), std::end(firstPartName)));
0185 } else {
0186 filters_.back()->isRegex.emplace_back(false);
0187 filters_.back()->index.emplace_back(filters_.back()->skeys.size());
0188 }
0189 filters_.back()->skeys.emplace_back(firstPartName);
0190 filters_.back()->up = nullptr;
0191 filters_.back()->next = nullptr;
0192 filters_.back()->spec = section.second;
0193
0194 if (currentFilter_ == nullptr) {
0195 currentFilter_ = filters_.back().get();
0196 }
0197 }
0198
0199 vector<string_view> toks = split(partSelector, "/");
0200 for (size_t pos = 1; pos < toks.size(); ++pos) {
0201 if (currentFilter_->next != nullptr) {
0202 currentFilter_ = currentFilter_->next.get();
0203 auto const& key = find_if(begin(currentFilter_->skeys), end(currentFilter_->skeys), [&](auto const& p) {
0204 return toks.front() == p;
0205 });
0206 if (key == end(currentFilter_->skeys)) {
0207 currentFilter_->hasNamespace.emplace_back(dd4hep::dd::hasNamespace(toks[pos]));
0208 if (dd4hep::dd::isRegex(toks[pos])) {
0209 currentFilter_->isRegex.emplace_back(true);
0210 currentFilter_->index.emplace_back(currentFilter_->keys.size());
0211 currentFilter_->keys.emplace_back(std::regex(std::begin(toks[pos]), std::end(toks[pos])));
0212 } else {
0213 currentFilter_->isRegex.emplace_back(false);
0214 currentFilter_->index.emplace_back(currentFilter_->skeys.size());
0215 }
0216 currentFilter_->skeys.emplace_back(toks[pos]);
0217 }
0218 } else {
0219 auto nextLevelFilter = std::make_unique<Filter>();
0220 bool isRegex = dd4hep::dd::isRegex(toks[pos]);
0221 nextLevelFilter->isRegex.emplace_back(isRegex);
0222 nextLevelFilter->hasNamespace.emplace_back(dd4hep::dd::hasNamespace(toks[pos]));
0223 if (isRegex) {
0224 nextLevelFilter->index.emplace_back(filters_.back()->keys.size());
0225 nextLevelFilter->keys.emplace_back(std::regex(toks[pos].begin(), toks[pos].end()));
0226 } else {
0227 nextLevelFilter->index.emplace_back(filters_.back()->skeys.size());
0228 }
0229 nextLevelFilter->skeys.emplace_back(toks[pos]);
0230 nextLevelFilter->next = nullptr;
0231 nextLevelFilter->up = currentFilter_;
0232 nextLevelFilter->spec = section.second;
0233
0234 currentFilter_->next = std::move(nextLevelFilter);
0235 }
0236 }
0237 }
0238 }
0239 }
0240
0241 void print(const Filter* filter) {
0242 edm::LogVerbatim("Geometry").log([&](auto& log) {
0243 for (const auto& it : filter->skeys) {
0244 log << it << ", ";
0245 }
0246 });
0247 }
0248
0249 void DDFilteredView::printFilter() const {
0250 for (const auto& f : filters_) {
0251 edm::LogVerbatim("Geometry").log([&](auto& log) {
0252 log << "\nFilter: ";
0253 for (const auto& it : f->skeys) {
0254 log << it << ", ";
0255 }
0256 if (f->next) {
0257 log << "\nNext: ";
0258 print(&*f->next);
0259 }
0260 if (f->up) {
0261 log << "Up: ";
0262 print(f->up);
0263 }
0264 });
0265 }
0266 }
0267
0268 bool DDFilteredView::firstChild() {
0269 currentSpecPar_ = nullptr;
0270
0271 if (it_.empty()) {
0272 LogVerbatim("DDFilteredView") << "Iterator vector has zero size.";
0273 return false;
0274 }
0275 it_.back().SetType(0);
0276 Node* node = nullptr;
0277 while ((node = it_.back().Next())) {
0278 if (accept(noNamespace(node->GetVolume()->GetName()))) {
0279 node_ = node;
0280 startLevel_ = it_.back().GetLevel();
0281 return true;
0282 }
0283 }
0284 LogVerbatim("DDFilteredView") << "Search for first child failed.";
0285 return false;
0286 }
0287
0288 bool DDFilteredView::nextChild() {
0289 currentSpecPar_ = nullptr;
0290
0291 if (it_.empty()) {
0292 LogVerbatim("DDFilteredView") << "Iterator vector has zero size.";
0293 return false;
0294 }
0295 it_.back().SetType(0);
0296 Node* node = nullptr;
0297 while ((node = it_.back().Next())) {
0298 if (it_.back().GetLevel() <= startLevel_) {
0299 return false;
0300 }
0301 if (accept(noNamespace(node->GetVolume()->GetName()))) {
0302 node_ = node;
0303 return true;
0304 }
0305 }
0306 LogVerbatim("DDFilteredView") << "Search for first child failed.";
0307 return false;
0308 }
0309
0310 int DDFilteredView::nodeCopyNo(const std::string_view copyNo) const {
0311 int result;
0312 if (auto [p, ec] = std::from_chars(copyNo.data(), copyNo.data() + copyNo.size(), result); ec == std::errc()) {
0313 return result;
0314 }
0315 return -1;
0316 }
0317
0318 std::vector<std::pair<std::string, int>> DDFilteredView::toNodeNames(const std::string& path) {
0319 std::vector<std::pair<std::string, int>> result;
0320 std::vector<string_view> names = split(path, "/");
0321 for (auto it : names) {
0322 auto name = noNamespace(it);
0323 int copyNo = -1;
0324 auto lpos = name.find_first_of('[');
0325 if (lpos != std::string::npos) {
0326 auto rpos = name.find_last_of(']');
0327 if (rpos != std::string::npos) {
0328 copyNo = nodeCopyNo(name.substr(lpos + 1, rpos - 1));
0329 }
0330 name.remove_suffix(name.size() - lpos);
0331 }
0332 result.emplace_back(std::string(name.data(), name.size()), copyNo);
0333 }
0334
0335 return result;
0336 }
0337
0338 bool DDFilteredView::match(const std::string& path, const std::vector<std::pair<std::string, int>>& names) const {
0339 std::vector<std::pair<std::string_view, int>> toks;
0340 std::vector<string_view> pnames = split(path, "/");
0341 for (const auto& i : pnames) {
0342 auto name = noNamespace(i);
0343 auto lpos = name.find_first_of('_');
0344 if (lpos != std::string::npos) {
0345 int copyNo = nodeCopyNo(name.substr(lpos + 1));
0346 toks.emplace_back(name.substr(0, lpos), copyNo);
0347 }
0348 }
0349 if (toks.size() != names.size()) {
0350 return false;
0351 }
0352
0353 for (unsigned int i = 0; i < names.size(); i++) {
0354 if (names[i].first != toks[i].first) {
0355 return false;
0356 } else {
0357 if (names[i].second != -1 and names[i].second != toks[i].second) {
0358 return false;
0359 }
0360 }
0361 }
0362 return true;
0363 }
0364
0365 std::vector<std::vector<Node*>> DDFilteredView::children(const std::string& selectPath) {
0366 currentSpecPar_ = nullptr;
0367
0368 std::vector<std::vector<Node*>> paths;
0369 if (it_.empty()) {
0370 LogVerbatim("DDFilteredView") << "Iterator vector has zero size.";
0371 return paths;
0372 }
0373 if (node_ == nullptr) {
0374 throw cms::Exception("DDFilteredView") << "Can't get children of a null node. Please, call firstChild().";
0375 }
0376 it_.back().SetType(0);
0377 std::vector<std::pair<std::string, int>> names = toNodeNames(selectPath);
0378 auto rit = names.rbegin();
0379 Node* node = it_.back().Next();
0380 while (node != nullptr) {
0381 if (node->GetVolume()->GetName() == rit->first) {
0382 std::string pathToNode = path();
0383 std::string::size_type n = pathToNode.find(node_->GetName());
0384 std::string pathFromParent = pathToNode.substr(n);
0385
0386 if (match(pathFromParent, names)) {
0387 std::vector<Node*> result;
0388 LogVerbatim("Geometry") << "Match found: " << pathFromParent;
0389 for (int i = startLevel_; i < it_.back().GetLevel(); i++) {
0390 result.emplace_back(it_.back().GetNode(i));
0391 }
0392 result.emplace_back(node);
0393 paths.emplace_back(result);
0394 }
0395 }
0396 node = it_.back().Next();
0397 }
0398 return paths;
0399 }
0400
0401 bool DDFilteredView::firstSibling() {
0402 currentSpecPar_ = nullptr;
0403
0404 assert(node_);
0405 if (it_.empty() or currentFilter_ == nullptr)
0406 return false;
0407 Node* node = nullptr;
0408 if (next(0) == false)
0409 return false;
0410 node = node_;
0411 it_.emplace_back(Iterator(it_.back()));
0412 it_.back().SetType(1);
0413 if (currentFilter_ != nullptr and currentFilter_->next != nullptr)
0414 currentFilter_ = currentFilter_->next.get();
0415 else
0416 return false;
0417 do {
0418 if (dd4hep::dd::accepted(currentFilter_, noNamespace(node->GetVolume()->GetName()))) {
0419 node_ = node;
0420 return true;
0421 }
0422 } while ((node = it_.back().Next()));
0423
0424 return false;
0425 }
0426
0427 bool DDFilteredView::nextSibling() {
0428 currentSpecPar_ = nullptr;
0429
0430 assert(node_);
0431 if (it_.empty() or currentFilter_ == nullptr)
0432 return false;
0433 if (it_.back().GetType() == 0)
0434 return firstSibling();
0435 else {
0436 up();
0437 it_.back().SetType(1);
0438 Node* node = node_;
0439 do {
0440 if (dd4hep::dd::accepted(currentFilter_, noNamespace(node->GetVolume()->GetName()))) {
0441 node_ = node;
0442 return true;
0443 }
0444 } while ((node = it_.back().Next()));
0445
0446 return false;
0447 }
0448 }
0449
0450 bool DDFilteredView::sibling() {
0451 currentSpecPar_ = nullptr;
0452
0453 if (it_.empty() or currentFilter_ == nullptr)
0454 return false;
0455 it_.back().SetType(1);
0456 Node* node = nullptr;
0457 while ((node = it_.back().Next())) {
0458 if (dd4hep::dd::accepted(currentFilter_, noNamespace(node->GetVolume()->GetName()))) {
0459 node_ = node;
0460 return true;
0461 }
0462 }
0463 return false;
0464 }
0465
0466 bool DDFilteredView::checkChild() {
0467 currentSpecPar_ = nullptr;
0468
0469 if (it_.empty() or currentFilter_ == nullptr)
0470 return false;
0471 it_.back().SetType(1);
0472 Node* node = nullptr;
0473 while ((node = it_.back().Next())) {
0474 if (dd4hep::dd::accepted(currentFilter_, noNamespace(node->GetVolume()->GetName()))) {
0475 return true;
0476 }
0477 }
0478 return false;
0479 }
0480
0481 bool DDFilteredView::parent() {
0482 currentSpecPar_ = nullptr;
0483 if (it_.empty() or currentFilter_ == nullptr)
0484 return false;
0485 up();
0486 it_.back().SetType(0);
0487
0488 return true;
0489 }
0490
0491 bool DDFilteredView::next(int type) {
0492 currentSpecPar_ = nullptr;
0493
0494 if (it_.empty())
0495 return false;
0496 it_.back().SetType(type);
0497 Node* node = nullptr;
0498 if ((node = it_.back().Next())) {
0499 node_ = node;
0500 return true;
0501 } else
0502 return false;
0503 }
0504
0505 void DDFilteredView::down() {
0506 currentSpecPar_ = nullptr;
0507
0508 if (it_.empty() or currentFilter_ == nullptr)
0509 return;
0510 it_.emplace_back(Iterator(it_.back()));
0511 next(0);
0512 if (currentFilter_->next)
0513 currentFilter_ = currentFilter_->next.get();
0514 }
0515
0516 void DDFilteredView::up() {
0517 currentSpecPar_ = nullptr;
0518
0519 if (it_.size() > 1 and currentFilter_ != nullptr) {
0520 it_.pop_back();
0521 it_.back().SetType(0);
0522 if (currentFilter_->up)
0523 currentFilter_ = currentFilter_->up;
0524 }
0525 }
0526
0527 bool DDFilteredView::accept(std::string_view name) {
0528 for (const auto& it : filters_) {
0529 currentFilter_ = it.get();
0530 if (dd4hep::dd::accepted(currentFilter_, name))
0531 return true;
0532 }
0533 return false;
0534 }
0535
0536 const std::vector<double> DDFilteredView::parameters() const {
0537 assert(node_);
0538 Volume currVol = node_->GetVolume();
0539
0540 if (currVol->GetShape()->IsA() == TGeoCompositeShape::Class() and
0541 not dd4hep::isA<dd4hep::PseudoTrap>(currVol.solid())) {
0542 const TGeoCompositeShape* shape = static_cast<const TGeoCompositeShape*>(currVol->GetShape());
0543 const TGeoBoolNode* boolean = shape->GetBoolNode();
0544 while (boolean->GetLeftShape()->IsA() == TGeoCompositeShape::Class()) {
0545 boolean = static_cast<const TGeoCompositeShape*>(boolean->GetLeftShape())->GetBoolNode();
0546 }
0547 if (boolean->GetLeftShape()->IsA() == TGeoBBox::Class()) {
0548 const TGeoBBox* box = static_cast<const TGeoBBox*>(boolean->GetLeftShape());
0549 return {box->GetDX(), box->GetDY(), box->GetDZ()};
0550 } else if (boolean->GetLeftShape()->IsA() == TGeoPcon::Class()) {
0551 const TGeoPcon* pcon = static_cast<const TGeoPcon*>(boolean->GetLeftShape());
0552 double param[4];
0553 pcon->GetBoundingCylinder(param);
0554 return {param[0], param[1], param[2], param[3]};
0555 } else {
0556 throw cms::Exception("DDFilteredView") << "Unknown boolean solid component";
0557 }
0558 } else
0559 return currVol.solid().dimensions();
0560 }
0561
0562 const cms::DDSolidShape DDFilteredView::shape() const {
0563 assert(node_);
0564 if ((volume().volume())->IsAssembly()) {
0565 return (cms::DDSolidShape::ddbox);
0566 }
0567 return cms::dd::value(cms::DDSolidShapeMap, std::string(node_->GetVolume()->GetShape()->GetTitle()));
0568 }
0569
0570 LegacySolidShape DDFilteredView::legacyShape(const cms::DDSolidShape shape) const {
0571 return cms::dd::value(cms::LegacySolidShapeMap, shape);
0572 }
0573
0574 template <>
0575 std::string_view DDFilteredView::get<string_view>(const string& key) {
0576 std::string_view result;
0577
0578 currentSpecPar_ = find(key);
0579 if (currentSpecPar_ != nullptr) {
0580 result = currentSpecPar_->strValue(key);
0581 }
0582 return result;
0583 }
0584
0585 template <>
0586 double DDFilteredView::get<double>(const string& key) {
0587 double result(0.0);
0588
0589 currentSpecPar_ = find(key);
0590 if (currentSpecPar_ != nullptr) {
0591 result = getNextValue(key);
0592 }
0593
0594 return result;
0595 }
0596
0597 template <>
0598 std::vector<double> DDFilteredView::get<std::vector<double>>(const string& name, const string& key) const {
0599 if (registry_->hasSpecPar(name))
0600 return registry_->specPar(name)->value<std::vector<double>>(key);
0601 else
0602 return std::vector<double>();
0603 }
0604
0605 template <>
0606 std::vector<int> DDFilteredView::get<std::vector<int>>(const string& name, const string& key) const {
0607 if (registry_->hasSpecPar(name))
0608 return registry_->specPar(name)->value<std::vector<int>>(key);
0609 else
0610 return std::vector<int>();
0611 }
0612
0613 template <>
0614 std::vector<std::string> DDFilteredView::get<std::vector<std::string>>(const string& name, const string& key) const {
0615 if (registry_->hasSpecPar(name))
0616 return registry_->specPar(name)->value<std::vector<std::string>>(key);
0617 else
0618 return std::vector<std::string>();
0619 }
0620
0621 std::vector<double> DDFilteredView::get(const string& name, const string& key) const {
0622 std::vector<std::string> stringVector = get<std::vector<std::string>>(name, key);
0623 std::vector<double> doubleVector(stringVector.size());
0624 std::transform(stringVector.begin(), stringVector.end(), doubleVector.begin(), [](const std::string& val) {
0625 return std::stod(val);
0626 });
0627 return doubleVector;
0628 }
0629
0630 std::string_view DDFilteredView::getString(const std::string& key) const {
0631 assert(currentFilter_);
0632 assert(currentFilter_->spec);
0633 return currentFilter_->spec->strValue(key);
0634 }
0635
0636 DDFilteredView::nav_type DDFilteredView::navPos() const {
0637 nav_type pos;
0638
0639 if (not it_.empty()) {
0640 int level = it_.back().GetLevel();
0641 for (int i = 1; i <= level; ++i)
0642 pos.emplace_back(it_.back().GetIndex(i));
0643 }
0644
0645 return pos;
0646 }
0647
0648 const int DDFilteredView::level() const {
0649 int level(0);
0650 if (not it_.empty()) {
0651 level = it_.back().GetLevel();
0652 }
0653 return level;
0654 }
0655
0656 bool DDFilteredView::goTo(const nav_type& newpos) {
0657 bool result(false);
0658 currentSpecPar_ = nullptr;
0659
0660
0661 it_.emplace_back(Iterator(it_.back().GetTopVolume()));
0662 Node* node = nullptr;
0663
0664
0665 for (auto const& i : newpos) {
0666 it_.back().SetType(0);
0667 node = it_.back().Next();
0668 for (int j = 1; j <= i; j++) {
0669 it_.back().SetType(1);
0670 node = it_.back().Next();
0671 }
0672 }
0673 if (node != nullptr) {
0674 node_ = node;
0675 result = true;
0676 } else {
0677 it_.pop_back();
0678 }
0679
0680 return result;
0681 }
0682
0683 const std::vector<const Node*> DDFilteredView::geoHistory() const {
0684 std::vector<const Node*> result;
0685 if (not it_.empty()) {
0686 int level = it_.back().GetLevel();
0687 for (int nit = level; nit > 0; --nit) {
0688 result.emplace_back(it_.back().GetNode(nit));
0689 }
0690 }
0691
0692 return result;
0693 }
0694
0695 const ExpandedNodes& DDFilteredView::history() {
0696 assert(registry_);
0697 nodes_.tags.clear();
0698 nodes_.offsets.clear();
0699 nodes_.copyNos.clear();
0700
0701 int level = it_.back().GetLevel();
0702 for (int nit = level; nit > 0; --nit) {
0703 for (auto const& i : registry_->specpars) {
0704 auto k = find_if(begin(i.second.paths), end(i.second.paths), [&](auto const& j) {
0705 return (isMatch(noNamespace(it_.back().GetNode(nit)->GetVolume()->GetName()), front(j))) and
0706 (i.second.hasValue("CopyNoTag") or i.second.hasValue("CopyNoOffset"));
0707 });
0708 if (k != end(i.second.paths)) {
0709 nodes_.tags.emplace_back(i.second.dblValue("CopyNoTag"));
0710 nodes_.offsets.emplace_back(i.second.dblValue("CopyNoOffset"));
0711 nodes_.copyNos.emplace_back(it_.back().GetNode(nit)->GetNumber());
0712 }
0713 }
0714 }
0715
0716 return nodes_;
0717 }
0718
0719 const DDSpecPar* DDFilteredView::find(const std::string& key) const {
0720 DDSpecParRefs specParRefs;
0721 filter(specParRefs, key);
0722
0723 for (auto const& specPar : specParRefs) {
0724 auto pos = find_if(begin(specPar.second->paths), end(specPar.second->paths), [&](auto const& partSelector) {
0725 return matchPath(partSelector);
0726 });
0727 if (pos != end(specPar.second->paths)) {
0728 return specPar.second;
0729 }
0730 }
0731
0732 return nullptr;
0733 }
0734
0735 void DDFilteredView::filter(DDSpecParRefs& refs, const std::string& key) const {
0736 for (auto const& it : registry_->specpars) {
0737 if (it.second.hasValue(key) || (it.second.spars.find(key) != end(it.second.spars))) {
0738 refs.emplace_back(it.first, &it.second);
0739 }
0740 }
0741 }
0742
0743
0744 std::string_view DDFilteredView::front(const std::string_view path) const {
0745 auto const& lpos = path.find_first_not_of('/');
0746 if (lpos != path.npos) {
0747 auto rpos = path.find_first_of('/', lpos);
0748 if (rpos == path.npos) {
0749 rpos = path.size();
0750 }
0751 return path.substr(lpos, rpos - lpos);
0752 }
0753
0754
0755 return path;
0756 }
0757
0758
0759 std::string_view DDFilteredView::back(const std::string_view path) const {
0760 if (auto const& lpos = path.rfind('/') != path.npos) {
0761 return path.substr(lpos, path.size());
0762 }
0763
0764
0765 return path;
0766 }
0767
0768
0769 std::string_view DDFilteredView::nodeNameAt(int level) const {
0770 assert(!it_.empty());
0771 assert(it_.back().GetLevel() >= level);
0772 return it_.back().GetNode(level)->GetVolume()->GetName();
0773 }
0774
0775
0776 const int DDFilteredView::nodeCopyNoAt(int level) const {
0777 assert(!it_.empty());
0778 assert(it_.back().GetLevel() >= level);
0779 return it_.back().GetNode(level)->GetNumber();
0780 }
0781
0782
0783
0784 bool DDFilteredView::compareEqualName(const std::string_view selection, const std::string_view name) const {
0785 return (!(dd4hep::dd::isRegex(selection))
0786 ? dd4hep::dd::compareEqual(name, selection)
0787 : regex_match(name.begin(), name.end(), regex(selection.begin(), selection.end())));
0788 }
0789
0790
0791
0792
0793 std::tuple<std::string_view, std::string_view> DDFilteredView::alignNamespaces(std::string_view selection,
0794 std::string_view name) const {
0795 auto pos = selection.find(':');
0796 if (pos == selection.npos) {
0797 name = noNamespace(name);
0798 } else {
0799 if (name.find(':') == name.npos) {
0800 selection.remove_prefix(pos + 1);
0801 }
0802 }
0803 return std::make_tuple(selection, name);
0804 }
0805
0806
0807
0808 bool DDFilteredView::compareEqualCopyNumber(const std::string_view name, int copy) const {
0809 auto pos = name.rfind('[');
0810 if (pos != name.npos) {
0811 if (std::stoi(std::string(name.substr(pos + 1, name.rfind(']')))) == copy) {
0812 return true;
0813 }
0814 }
0815
0816 return false;
0817 }
0818
0819 bool DDFilteredView::matchPath(const std::string_view path) const {
0820 assert(!it_.empty());
0821 int level = it_.back().GetLevel();
0822
0823 auto to = path.size();
0824 auto from = path.rfind('/');
0825 bool result = false;
0826 for (int it = level; from - 1 <= to and it > 0; --it) {
0827 std::string_view name = nodeNameAt(it);
0828 std::string_view refname{&path[from + 1], to - from - 1};
0829 to = from;
0830 from = path.substr(0, to).rfind('/');
0831
0832 std::tie(refname, name) = alignNamespaces(refname, name);
0833
0834 auto pos = refname.rfind('[');
0835 if (pos != refname.npos) {
0836 if (!compareEqualCopyNumber(refname, nodeCopyNoAt(it))) {
0837 result = false;
0838 break;
0839 } else {
0840 refname.remove_suffix(refname.size() - pos);
0841 }
0842 }
0843 if (!compareEqualName(refname, name)) {
0844 result = false;
0845 break;
0846 } else {
0847 result = true;
0848 }
0849 }
0850 return result;
0851 }
0852
0853 double DDFilteredView::getNextValue(const std::string& key) const {
0854 double result(0.0);
0855
0856 if (currentSpecPar_ != nullptr) {
0857 auto const& nitem = currentSpecPar_->numpars.find(key);
0858 if (nitem != end(currentSpecPar_->numpars)) {
0859 result = nitem->second[0];
0860 }
0861 }
0862
0863 return result;
0864 }
0865
0866 std::string_view DDFilteredView::name() const {
0867 return (node_ == nullptr ? std::string_view() : (dd4hep::dd::noNamespace(volume().volume().name())));
0868 }
0869
0870 std::string_view DDFilteredView::fullName() const {
0871 return (node_ == nullptr ? std::string_view() : (volume().volume().name()));
0872 }
0873
0874 dd4hep::Solid DDFilteredView::solid() const {
0875 if ((volume().volume())->IsAssembly()) {
0876 std::string solName(name());
0877
0878 return (dd4hep::Box(solName, 1., 1., 1.));
0879 }
0880 return (volume().volume().solid());
0881 }
0882
0883 unsigned short DDFilteredView::copyNum() const { return (volume().copyNumber()); }
0884
0885 std::string_view DDFilteredView::materialName() const { return (volume().material().name()); }
0886
0887 std::ostream& operator<<(std::ostream& os, const std::vector<const cms::Node*>& hst) {
0888 for (auto nd = hst.rbegin(); nd != hst.rend(); ++nd)
0889 os << "/" << (*nd)->GetName();
0890 return os;
0891 }