Warning, file /DD4hep/DDCore/src/plugins/DetectorCheck.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Detector.h>
0016 #include <DD4hep/Printout.h>
0017 #include <DD4hep/Factories.h>
0018 #include <DD4hep/IDDescriptor.h>
0019 #include <DD4hep/VolumeManager.h>
0020 #include <DD4hep/DetectorTools.h>
0021 #include <DD4hep/MatrixHelpers.h>
0022 #include <DD4hep/AlignmentsNominalMap.h>
0023 #include <DD4hep/detail/VolumeManagerInterna.h>
0024
0025
0026 #include <stdexcept>
0027 #include <algorithm>
0028 #include <cstdlib>
0029
0030 using namespace dd4hep;
0031
0032
0033 namespace dd4hep { namespace detail { namespace tools {
0034
0035 std::string elementPath(const PlacementPath& nodes, bool reverse= false);
0036 } } }
0037
0038 namespace {
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 struct DetectorCheck {
0060 using StructureElements = std::map<DetElement, size_t>;
0061 using Chain = detail::tools::PlacementPath;
0062 using VolIDs = PlacedVolume::VolIDs;
0063
0064
0065 struct FND {
0066 const std::string& test;
0067 FND(const std::string& c) : test(c) {}
0068 bool operator()(const VolIDs::value_type& c) const { return c.first == test; }
0069 };
0070 struct counters {
0071 size_t elements { 0 };
0072 size_t errors { 0 };
0073 void reset() { elements = errors = 0; }
0074 counters& operator+=(const counters& c) {
0075 elements += c.elements;
0076 errors += c.errors;
0077 return *this;
0078 }
0079 };
0080
0081 Detector& description;
0082 AlignmentsNominalMap m_mapping;
0083 DetElement m_current_detector;
0084 SensitiveDetector m_current_sensitive;
0085 IDDescriptor m_current_iddesc;
0086 VolumeManager m_volMgr;
0087 DetElement m_det;
0088 std::string m_name { "GeometryCheck" };
0089
0090 counters m_place_counters, m_sens_counters, m_geo_counters, m_struct_counters;
0091 StructureElements m_structure_elements;
0092
0093 bool check_structure { false };
0094 bool check_geometry { false };
0095 bool check_placements { false };
0096 bool check_volmgr { false };
0097 bool check_sensitive { false };
0098 bool ignore_detector { false };
0099
0100 SensitiveDetector get_current_sensitive_detector();
0101
0102
0103 DetectorCheck(Detector& description);
0104
0105 virtual ~DetectorCheck() = default;
0106
0107
0108 void checkManagerSingleVolume(DetElement e, PlacedVolume pv, const VolIDs& child_ids, const Chain& chain);
0109
0110 void checkManagerVolumeTree(DetElement e, PlacedVolume pv, VolIDs ids, const Chain& chain, size_t depth, size_t mx_depth);
0111
0112
0113 void checkSingleVolume(DetElement e, PlacedVolume pv);
0114
0115 void checkVolumeTree(DetElement e, PlacedVolume pv);
0116
0117
0118 bool checkDetElement(const std::string& path, DetElement detector, PlacedVolume pv);
0119
0120 bool checkDetElementTree(const std::string& path, DetElement detector, PlacedVolume pv);
0121
0122 void execute(DetElement sdet, size_t depth);
0123
0124
0125 static long run(Detector& description,int argc,char** argv);
0126 static void help(int argc,char** argv);
0127 };
0128 const char* tag_fail(size_t errs) {
0129 return errs==0 ? "PASSED" : "FAILED";
0130 }
0131 }
0132
0133
0134
0135 DetectorCheck::DetectorCheck(Detector& desc)
0136 : description(desc), m_mapping(desc.world())
0137 {
0138 }
0139
0140 SensitiveDetector DetectorCheck::get_current_sensitive_detector() {
0141 DetElement de = m_current_detector;
0142 m_current_sensitive = description.sensitiveDetector(de.name());
0143 m_current_iddesc = IDDescriptor();
0144 if ( m_current_sensitive.isValid() ) {
0145 m_current_iddesc = m_current_sensitive.readout().idSpec();
0146 }
0147 return m_current_sensitive;
0148 }
0149
0150 void DetectorCheck::execute(DetElement sdet, size_t depth) {
0151 const char* line = "============================";
0152 struct counters count_volmgr_sens, count_volmgr_place;
0153 struct counters total, count_struct;
0154 struct counters count_geo, count_geo_sens;
0155
0156 if ( !sdet.isValid() ) {
0157 ++m_place_counters.errors;
0158 except("VolumeMgrTest", "The detector element is not known to the geometry.");
0159 return;
0160 }
0161
0162 m_det = sdet;
0163 m_current_detector = m_det;
0164
0165
0166 if ( check_sensitive || check_volmgr ) {
0167 if ( m_det == m_det.world() ) {
0168 m_current_sensitive = SensitiveDetector();
0169 m_current_iddesc = IDDescriptor();
0170 }
0171 else {
0172 m_current_sensitive = description.sensitiveDetector(m_det.name());
0173 if ( !m_current_sensitive.isValid() ) {
0174 printout(ERROR, m_name,
0175 "The sensitive detector of subdetector %s "
0176 "is not known to the geometry.", m_det.name());
0177 return;
0178 }
0179 m_current_iddesc = m_current_sensitive.readout().idSpec();
0180 }
0181 }
0182
0183 if ( check_structure ) {
0184 printout(ALWAYS, m_name, "%s%s Executing STRUCTURE test %s%s", line, line, line, line);
0185 PlacedVolume pv = m_det.placement();
0186 checkDetElementTree(m_det.path(), m_det, pv);
0187 count_struct.elements = m_structure_elements.size();
0188 count_struct.errors = m_struct_counters.errors;
0189 total += count_struct;
0190 m_structure_elements.clear();
0191 m_struct_counters.reset();
0192 }
0193 if ( check_geometry ) {
0194 printout(ALWAYS, m_name, "%s%s Executing GEOMETRY test %s%s", line, line, line, line);
0195 PlacedVolume pv = m_det.placement();
0196 checkVolumeTree(m_det, pv);
0197 count_geo = m_geo_counters;
0198 count_geo_sens = m_sens_counters;
0199 total += count_geo_sens;
0200 total += count_geo;
0201 m_sens_counters.reset();
0202 m_geo_counters.reset();
0203 }
0204
0205 if ( check_volmgr ) {
0206 Chain chain;
0207 PlacedVolume pv = m_det.placement();
0208 VolIDs ids;
0209
0210 printout(ALWAYS, m_name, "%s%s Executing VOLUME MANAGER test %s%s", line, line, line, line);
0211 chain.emplace_back(pv);
0212 m_volMgr = description.volumeManager();
0213 if ( !m_volMgr.isValid() ) {
0214 printout(ERROR, m_name, "Volume manager is not instantiated. Required for test!");
0215 return;
0216 }
0217 if ( pv.volume() != description.worldVolume() ) {
0218 ids = pv.volIDs();
0219 }
0220 m_sens_counters.reset();
0221 m_current_detector = m_det;
0222 checkManagerVolumeTree(m_det, pv, std::move(ids), chain, 1, depth);
0223 count_volmgr_place = m_place_counters;
0224 count_volmgr_sens = m_sens_counters;
0225 total += count_volmgr_place;
0226 total += count_volmgr_sens;
0227 m_place_counters.reset();
0228 m_sens_counters.reset();
0229 }
0230
0231 if ( check_structure ) {
0232 printout(count_struct.errors > 0 ? ERROR : ALWAYS,
0233 m_name, "+++ %s: Checked %10ld structure elements. Num.Errors:%6ld (structure test)",
0234 tag_fail(count_struct.errors), count_struct.elements, count_struct.errors);
0235 }
0236 if ( check_geometry ) {
0237 if ( check_sensitive ) {
0238 printout(count_geo_sens.errors > 0 ? ERROR : ALWAYS,
0239 m_name, "+++ %s: Checked %10ld sensitive elements. Num.Errors:%6ld (geometry test)",
0240 tag_fail(count_geo_sens.errors), count_geo_sens.elements, count_geo_sens.errors);
0241 }
0242 printout(count_geo.errors > 0 ? ERROR : ALWAYS,
0243 m_name, "+++ %s: Checked %10ld placements. Num.Errors:%6ld (geometry test)",
0244 tag_fail(count_geo.errors), count_geo.elements, count_geo.errors);
0245 }
0246 if ( check_volmgr ) {
0247 if ( check_sensitive ) {
0248 printout(count_volmgr_sens.errors > 0 ? ERROR : ALWAYS,
0249 m_name, "+++ %s: Checked %10ld sensitive elements. Num.Errors:%6ld (phys.VolID test)",
0250 tag_fail(count_volmgr_sens.errors), count_volmgr_sens.elements, count_volmgr_sens.errors);
0251 }
0252 printout(count_volmgr_place.errors > 0 ? ERROR : ALWAYS,
0253 m_name, "+++ %s: Checked %10ld sensitive placements. Num.Errors:%6ld (phys.VolID test)",
0254 tag_fail(count_volmgr_place.errors), count_volmgr_sens.elements, count_volmgr_place.errors);
0255 }
0256 printout(ALWAYS, m_name, "+++ %s: Checked a total of %11ld elements. Num.Errors:%6ld (Some elements checked twice)",
0257 tag_fail(total.errors), total.elements, total.errors);
0258 }
0259
0260
0261 bool DetectorCheck::checkDetElement(const std::string& path, DetElement detector, PlacedVolume pv) {
0262 bool det_valid = true;
0263 bool parent_valid = true;
0264 bool place_valid = true;
0265 bool det_place_valid = true;
0266 bool vol_valid = true;
0267 auto nerrs = m_struct_counters.errors;
0268 const char* de_path = detector.path().c_str();
0269
0270 if ( !pv.isValid() ) {
0271 printout(ERROR, m_name, "Invalid DetElement placement: %s", de_path);
0272 ++m_struct_counters.errors;
0273 place_valid = false;
0274 }
0275 if ( detector.path() != path ) {
0276 printout(ERROR, m_name, "Invalid DetElement [path mismatch]: %s <> %s",
0277 de_path, path.c_str());
0278 ++m_struct_counters.errors;
0279 }
0280 if ( !detector.parent().isValid() && detector.world() != detector ) {
0281 printout(ERROR, m_name, "Invalid DetElement [No parent]: %s", de_path);
0282 ++m_struct_counters.errors;
0283 parent_valid = false;
0284 }
0285 if ( !detector.placement().isValid() ) {
0286 printout(ERROR, m_name, "Invalid DetElement [No placement]: %s", de_path);
0287 ++m_struct_counters.errors;
0288 det_place_valid = false;
0289 }
0290 else if ( !detector.volume().isValid() ) {
0291 printout(ERROR, m_name, "Invalid DetElement [No volume]: %s", de_path);
0292 ++m_struct_counters.errors;
0293 vol_valid = false;
0294 }
0295 if ( detector.placement().isValid() && detector.placement() != pv ) {
0296 printout(ERROR, m_name, "Invalid DetElement [Mismatched placement]: %s", de_path);
0297 ++m_struct_counters.errors;
0298 det_place_valid = false;
0299 }
0300 auto count = ++m_structure_elements[detector];
0301 if ( count > 1 ) {
0302 DetElement par = detector.parent();
0303 printout(ERROR, m_name, "DetElement %s parent: %s is placed %ld times! Only single placement allowed.",
0304 de_path, par.isValid() ? par.path().c_str() : "", m_structure_elements[detector]);
0305 ++m_struct_counters.errors;
0306 }
0307 Alignment ideal = detector.nominal();
0308 if ( !ideal.isValid() ) {
0309 printout(ERROR, m_name, "Invalid DetElement [No ideal alignment]: %s", de_path);
0310 ++m_struct_counters.errors;
0311 }
0312 Alignment survey = detector.survey();
0313 if ( !survey.isValid() ) {
0314 printout(ERROR, m_name, "Invalid DetElement [No survey alignment]: %s", de_path);
0315 ++m_struct_counters.errors;
0316 }
0317 if ( ideal.isValid() ) {
0318 const TGeoHMatrix& matrix = ideal.worldTransformation();
0319 if ( matrix.IsIdentity() ) {
0320 }
0321 }
0322 printout(nerrs != m_struct_counters.errors ? ERROR : INFO, m_name,
0323 "DetElement %s [%s] parent: %s placement: %s [%s] volume: %s",
0324 path.c_str(), yes_no(det_valid), yes_no(parent_valid), yes_no(det_place_valid),
0325 yes_no(place_valid), yes_no(vol_valid));
0326 return nerrs == m_struct_counters.errors;
0327 }
0328
0329
0330 bool DetectorCheck::checkDetElementTree(const std::string& path, DetElement detector, PlacedVolume pv) {
0331 auto nerrs = m_struct_counters.errors;
0332 if ( !detector.isValid() ) {
0333 printout(ERROR, m_name, "Invalid DetElement seen: %s", path.c_str());
0334 ++m_struct_counters.errors;
0335 return false;
0336 }
0337 bool is_world = detector == detector.world();
0338
0339 checkDetElement(path, detector, pv);
0340
0341 for ( const auto& c : detector.children() ) {
0342 DetElement de = c.second;
0343 if ( is_world ) {
0344 m_current_sensitive = SensitiveDetector();
0345 m_current_iddesc = IDDescriptor();
0346 m_current_detector = de;
0347 }
0348 if ( de.parent().isValid() && de.parent() != detector ) {
0349 printout(ERROR, m_name, "Invalid DetElement [Parent mismatch]: %s", de.path().c_str());
0350 printout(ERROR, m_name, " apparent parent: %s structural parent: %s",
0351 de.parent().path().c_str(), detector.path().c_str());
0352 ++m_struct_counters.errors;
0353 }
0354
0355 checkDetElementTree(path + "/" + c.first, de, de.placement());
0356 }
0357 return nerrs == m_struct_counters.errors;
0358 }
0359
0360
0361 void DetectorCheck::checkSingleVolume(DetElement e, PlacedVolume pv) {
0362
0363 ++m_geo_counters.elements;
0364
0365 if ( !e.isValid() ) {
0366 printout(ERROR, m_name, "Invalid DetElement [Invalid handle]");
0367 ++m_geo_counters.errors;
0368 }
0369
0370 if ( !pv.isValid() ) {
0371 printout(ERROR, m_name, "Invalid PlacedVolume [Invalid handle] DetElement: %s", e.path().c_str());
0372 ++m_geo_counters.errors;
0373 }
0374 Volume vol = pv.volume();
0375
0376 if ( !vol.isValid() ) {
0377 printout(ERROR, m_name, "Invalid Volume [Invalid handle] DetElement: %s", e.path().c_str());
0378 ++m_geo_counters.errors;
0379 return;
0380 }
0381
0382 if ( check_sensitive && vol.isSensitive() ) {
0383 SensitiveDetector sdv = vol.sensitiveDetector();
0384 ++m_sens_counters.elements;
0385 if ( !sdv.isValid() ) {
0386 printout(ERROR, m_name, "Invalid SensitiveDetector DetElement: %s", e.path().c_str());
0387 ++m_sens_counters.errors;
0388 }
0389 SensitiveDetector sdd = get_current_sensitive_detector();
0390 if ( sdd != sdv ) {
0391 printout(ERROR, m_name, "Inconsistent sensitive detectors for DetElement: %s", e.path().c_str());
0392 ++m_sens_counters.errors;
0393 }
0394 }
0395 }
0396
0397
0398 void DetectorCheck::checkVolumeTree(DetElement detector, PlacedVolume pv) {
0399 const TGeoNode* current = pv.ptr();
0400 TObjArray* nodes = current->GetNodes();
0401 int num_children = nodes ? nodes->GetEntriesFast() : 0;
0402 bool is_world = detector == description.world();
0403
0404
0405 checkSingleVolume(detector, pv);
0406
0407 for(int i=0; i < num_children; ++i) {
0408 TGeoNode* node = (TGeoNode*)nodes->At(i);
0409 PlacedVolume place(node);
0410 DetElement de = detector;
0411
0412 if ( is_world ) {
0413 m_current_detector = de;
0414 get_current_sensitive_detector();
0415 }
0416
0417
0418 for ( const auto& c : detector.children() ) {
0419 if ( c.second.placement() == place ) {
0420 de = c.second;
0421 break;
0422 }
0423 }
0424 checkVolumeTree(de, place);
0425 if ( is_world ) {
0426 m_current_sensitive = SensitiveDetector();
0427 m_current_iddesc = IDDescriptor();
0428 }
0429 }
0430 }
0431
0432
0433 void DetectorCheck::checkManagerSingleVolume(DetElement detector, PlacedVolume pv, const VolIDs& child_ids, const Chain& chain) {
0434 std::stringstream err, log;
0435 VolumeID det_vol_id = detector.volumeID();
0436 VolumeID vid = det_vol_id;
0437 DetElement top_sdet, det_elem;
0438 VolumeManagerContext* mgr_ctxt = 0;
0439
0440 ++m_place_counters.elements;
0441
0442 try {
0443 vid = m_current_iddesc.encode(child_ids);
0444 top_sdet = m_volMgr.lookupDetector(vid);
0445 det_elem = m_volMgr.lookupDetElement(vid);
0446 mgr_ctxt = m_volMgr.lookupContext(vid);
0447
0448 if ( pv.volume().isSensitive() ) {
0449 PlacedVolume det_place = m_volMgr.lookupDetElementPlacement(vid);
0450 ++m_sens_counters.elements;
0451 if ( !ignore_detector && pv.ptr() != det_place.ptr() ) {
0452 err << "VolumeMgrTest: Wrong placement "
0453 << " got " << det_place.name() << " (" << (void*)det_place.ptr() << ")"
0454 << " instead of " << pv.name() << " (" << (void*)pv.ptr() << ") "
0455 << " vid:" << volumeID(vid);
0456 ++m_place_counters.errors;
0457 }
0458 else if ( top_sdet.ptr() != detector.ptr() ) {
0459 top_sdet = m_volMgr.lookupDetector(vid);
0460 err << "VolumeMgrTest: Wrong associated sub-detector element vid=" << volumeID(vid)
0461 << " got " << top_sdet.path() << " (" << (void*)top_sdet.ptr() << ") "
0462 << " instead of " << detector.path() << " (" << (void*)detector.ptr() << ")"
0463 << " vid:" << volumeID(vid);
0464 ++m_place_counters.errors;
0465 }
0466 else if ( !detail::tools::isParentElement(detector,det_elem) ) {
0467
0468 err << "VolumeMgrTest: Wrong associated detector element vid=" << volumeID(vid)
0469 << " got " << det_elem.path() << " (" << (void*)det_elem.ptr() << ") "
0470 << " instead of " << detector.path() << " (" << (void*)detector.ptr() << ")"
0471 << " vid:" << volumeID(vid);
0472 ++m_place_counters.errors;
0473 }
0474 else if ( top_sdet.ptr() != m_det.ptr() ) {
0475 err << "VolumeMgrTest: Wrong associated detector "
0476 << " vid:" << volumeID(vid);
0477 ++m_place_counters.errors;
0478 }
0479 }
0480 }
0481 catch(const std::exception& ex) {
0482 err << "Lookup " << pv.name() << " id:" << volumeID(vid)
0483 << " path:" << detector.path() << " error:" << ex.what();
0484 ++m_place_counters.errors;
0485 }
0486
0487 if ( pv.volume().isSensitive() || (0 != det_vol_id) ) {
0488 std::string id_desc;
0489 log << "Volume:" << std::setw(50) << std::left << pv.name();
0490 if ( pv.volume().isSensitive() ) {
0491 IDDescriptor dsc = SensitiveDetector(pv.volume().sensitiveDetector()).readout().idSpec();
0492 log << " IDDesc:" << (char*)(dsc.ptr() == m_current_iddesc.ptr() ? "OK " : "BAD");
0493 if ( dsc.ptr() != m_current_iddesc.ptr() ) ++m_place_counters.errors;
0494 }
0495 else {
0496 log << std::setw(11) << " ";
0497 }
0498 id_desc = m_current_iddesc.str(vid);
0499 log << " [" << char(pv.volume().isSensitive() ? 'S' : 'N') << "] " << std::right
0500 << " vid:" << volumeID(vid)
0501 << " " << id_desc;
0502 if ( !err.str().empty() ) {
0503 printout(ERROR, m_det.name(),err.str()+" "+log.str());
0504
0505 return;
0506 }
0507 id_desc = m_current_iddesc.str(det_elem.volumeID());
0508 printout(INFO, m_det.name(),log.str());
0509 printout(INFO, m_det.name(), " Elt:%-64s vid:%s %s Parent-OK:%3s",
0510 det_elem.path().c_str(),volumeID(det_elem.volumeID()).c_str(),
0511 id_desc.c_str(),
0512 yes_no(detail::tools::isParentElement(detector,det_elem)));
0513
0514 try {
0515 if ( pv.volume().isSensitive() ) {
0516 TGeoHMatrix trafo;
0517 for (size_t i = chain.size()-1; i > 0; --i) {
0518
0519 const TGeoMatrix* mat = chain[i]->GetMatrix();
0520 trafo.MultiplyLeft(mat);
0521 }
0522 for (size_t i = chain.size(); i > 0; --i) {
0523 const TGeoMatrix* mat = chain[i-1]->GetMatrix();
0524 if ( printLevel() <= INFO ) {
0525 ::printf("Placement [%d] VolID:%s\t\t",int(i),chain[i-1].volIDs().str().c_str());
0526 mat->Print();
0527 }
0528 }
0529 det_elem = m_volMgr.lookupDetElement(vid);
0530 if ( printLevel() <= INFO ) {
0531 ::printf("Computed Trafo (from placements):\t\t");
0532 trafo.Print();
0533 ::printf("DetElement Trafo: %s [%s]\t\t",
0534 det_elem.path().c_str(),volumeID(det_elem.volumeID()).c_str());
0535 det_elem.nominal().worldTransformation().Print();
0536 ::printf("VolumeMgr Trafo: %s [%s]\t\t",det_elem.path().c_str(),volumeID(vid).c_str());
0537 m_volMgr.worldTransformation(m_mapping,vid).Print();
0538 }
0539
0540
0541 if ( 0 == mgr_ctxt ) {
0542 printout(ERROR, m_det.name(), "VOLUME_MANAGER FAILED: Could not find entry for vid:%s.",
0543 volumeID(vid).c_str());
0544 ++m_place_counters.errors;
0545 }
0546
0547
0548 if ( &det_elem.nominal().worldTransformation() != &m_volMgr.worldTransformation(m_mapping,det_elem.volumeID()) )
0549 {
0550 printout(ERROR, m_det.name(), "DETELEMENT_PERSISTENCY FAILED: World transformation have DIFFERET pointer!");
0551 ++m_place_counters.errors;
0552 }
0553
0554 if ( !ignore_detector ) {
0555 if ( pv.ptr() == det_elem.placement().ptr() ) {
0556
0557
0558 int res1 = detail::matrix::_matrixEqual(trafo, det_elem.nominal().worldTransformation());
0559 int res2 = detail::matrix::_matrixEqual(trafo, m_volMgr.worldTransformation(m_mapping,vid));
0560 if ( res1 != detail::matrix::MATRICES_EQUAL || res2 != detail::matrix::MATRICES_EQUAL ) {
0561 printout(ERROR, m_det.name(), "DETELEMENT_PLACEMENT FAILED: World transformation DIFFER.");
0562 ++m_place_counters.errors;
0563 }
0564 else {
0565 printout(INFO, m_det.name(), "DETELEMENT_PLACEMENT: PASSED. All matrices equal: %s",
0566 volumeID(vid).c_str());
0567 }
0568 }
0569 else {
0570
0571
0572
0573 int res2 = detail::matrix::_matrixEqual(trafo, m_volMgr.worldTransformation(m_mapping,vid));
0574 if ( res2 != detail::matrix::MATRICES_EQUAL ) {
0575 printout(ERROR, m_det.name(), "VOLUME_PLACEMENT FAILED: World transformation DIFFER.");
0576 ++m_place_counters.errors;
0577 }
0578 else {
0579 printout(INFO, m_det.name(), "VOLUME_PLACEMENT: PASSED. All matrices equal: %s",
0580 volumeID(vid).c_str());
0581 }
0582 }
0583 }
0584 }
0585 }
0586 catch(const std::exception& ex) {
0587 err << "Matrix " << pv.name() << " id:" << volumeID(vid)
0588 << " path:" << detector.path() << " error:" << ex.what();
0589 ++m_place_counters.errors;
0590 }
0591
0592 }
0593 }
0594
0595
0596 void DetectorCheck::checkManagerVolumeTree(DetElement detector, PlacedVolume pv, VolIDs ids, const Chain& chain,
0597 size_t depth, size_t mx_depth)
0598 {
0599 if ( depth <= mx_depth ) {
0600 const TGeoNode* current = pv.ptr();
0601 TObjArray* nodes = current->GetNodes();
0602 int num_children = nodes ? nodes->GetEntriesFast() : 0;
0603 bool is_world = detector == description.world();
0604
0605 for(int i=0; i<num_children; ++i) {
0606 TGeoNode* node = (TGeoNode*)nodes->At(i);
0607 PlacedVolume place(node);
0608 VolIDs child_ids(ids);
0609 Chain child_chain(chain);
0610 DetElement de = detector;
0611 if ( is_world ) {
0612
0613 for ( const auto& c : detector.children() ) {
0614 if ( c.second.placement() == place ) {
0615 de = c.second;
0616 break;
0617 }
0618 }
0619 m_current_detector = de;
0620 get_current_sensitive_detector();
0621 }
0622 place.access();
0623 child_chain.emplace_back(place);
0624 child_ids.insert(child_ids.end(), place.volIDs().begin(), place.volIDs().end());
0625 checkManagerSingleVolume(de, place, child_ids, child_chain);
0626 checkManagerVolumeTree(de, place, std::move(child_ids), child_chain, depth+1, mx_depth);
0627 }
0628 }
0629 }
0630
0631 void DetectorCheck::help(int argc,char** argv) {
0632 std::cout
0633 <<
0634 "DD4hep_DetectorCheck -option [-option] \n"
0635 " -help Print this help message \n"
0636 " -name <subdetector name> Name of the subdetector to be checked \n"
0637 " \"ALL\" or \"all\": loop over known subdetectors\n"
0638 " \"world\" start from the mother of all... \n"
0639 " -structure Check structural tree consistency \n"
0640 " -geometry Check geometry tree consistency \n"
0641 " -sensitve Check consistency between detector and volume \n"
0642 " settings of sensitive detectors. \n"
0643 " -volmgr Check volume manager entries against volIDs of \n"
0644 " sensitive volume placements. \n\n"
0645 " NOTE: Option requires proper PhysVolID setup \n"
0646 " of the sensitive volume placements ! \n"
0647 " -ignore_detector Ignore DetElement placement check for -volmgr \n"
0648 << std::endl;
0649 std::cout << "Arguments: " << std::endl;
0650 for(int iarg=0; iarg<argc;++iarg) {
0651 std::cout << "Argument[" << iarg << "] = " << argv[iarg] << std::endl;
0652 }
0653 ::exit(EINVAL);
0654 }
0655
0656
0657 long DetectorCheck::run(Detector& description,int argc,char** argv) {
0658 std::string name;
0659 bool volmgr = false;
0660 bool geometry = false;
0661 bool structure = false;
0662 bool sensitive = false;
0663 bool placements = false;
0664 bool ignore_de = false;
0665 printout(ALWAYS, "DetectorCheck", "++ Processing plugin...");
0666 for(int iarg=0; iarg<argc;++iarg) {
0667 if ( argv[iarg] == 0 ) break;
0668 if ( ::strncasecmp(argv[iarg], "-name",4) == 0 && (iarg+1) < argc )
0669 name = argv[++iarg];
0670 else if ( ::strncasecmp(argv[iarg], "-structure",4) == 0 )
0671 structure = true;
0672 else if ( ::strncasecmp(argv[iarg], "-placements",4) == 0 )
0673 placements = true;
0674 else if ( ::strncasecmp(argv[iarg], "-volmgr",4) == 0 )
0675 volmgr = true;
0676 else if ( ::strncasecmp(argv[iarg], "-geometry",4) == 0 )
0677 geometry = true;
0678 else if ( ::strncasecmp(argv[iarg], "-sensitive",4) == 0 )
0679 sensitive = true;
0680 else if ( ::strncasecmp(argv[iarg], "-ignore_detelement",4) == 0 )
0681 ignore_de = true;
0682 else if ( ::strncasecmp(argv[iarg], "-help",4) == 0 )
0683 help(argc, argv);
0684 else
0685 help(argc, argv);
0686 }
0687 if ( argc == 0 ) help(argc, argv);
0688 if ( !name.empty() ) {
0689 DetectorCheck test(description);
0690 if ( name == "all" || name == "All" || name == "ALL" ) {
0691 for (const auto& det : description.detectors() ) {
0692 printout(INFO, "DetectorCheck", "++ Processing subdetector: %s", det.second.name());
0693 test.check_structure = structure;
0694 test.check_placements = placements;
0695 test.check_volmgr = volmgr;
0696 test.check_geometry = geometry;
0697 test.check_sensitive = sensitive;
0698 test.ignore_detector = ignore_de;
0699 test.execute(det.second, 9999);
0700 }
0701 return 1;
0702 }
0703 DetElement det = (::strcasecmp(name.c_str(), "world") == 0)
0704 ? description.world() : description.detector(name);
0705 printout(INFO, "DetectorCheck", "++ Processing subdetector: %s",name.c_str());
0706 test.check_structure = structure;
0707 test.check_placements = placements;
0708 test.check_volmgr = volmgr;
0709 test.check_geometry = geometry;
0710 test.check_sensitive = sensitive;
0711 test.ignore_detector = ignore_de;
0712 test.execute(det, 9999);
0713 }
0714 return 1;
0715 }
0716
0717 DECLARE_APPLY(DD4hep_DetectorCheck,DetectorCheck::run)
0718
0719
0720 long run_VolumeMgrTest(Detector& description,int argc, const char*const* argv) {
0721 const char* args[] = {"-name", argc > 0 ? argv[0] : "world", "-structure", "-geometry", "-volmgr", 0 };
0722 return DetectorCheck::run(description, 6, (char**)args);
0723 }
0724 DECLARE_APPLY(DD4hep_VolumeMgrTest,run_VolumeMgrTest)