File indexing completed on 2025-12-17 09:23:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #define DD4HEP_MUST_USE_DETECTORIMP_H
0016 #include <DD4hep/Detector.h>
0017 #include <DD4hep/DetectorImp.h>
0018 #include <DD4hep/Memory.h>
0019 #include <DD4hep/DD4hepUI.h>
0020 #include <DD4hep/Factories.h>
0021 #include <DD4hep/Printout.h>
0022 #include <DD4hep/DD4hepUnits.h>
0023 #include <DD4hep/DetectorTools.h>
0024 #include <DD4hep/PluginCreators.h>
0025 #include <DD4hep/VolumeProcessor.h>
0026 #include <DD4hep/DetectorProcessor.h>
0027 #include <DD4hep/DD4hepRootPersistency.h>
0028 #include <XML/DocumentHandler.h>
0029 #include <XML/XMLElements.h>
0030 #include <XML/XMLTags.h>
0031
0032
0033 #include <TInterpreter.h>
0034 #include <TGeoElement.h>
0035 #include <TGeoManager.h>
0036 #include <TGeoVolume.h>
0037 #include <TSystem.h>
0038 #include <TClass.h>
0039 #include <TRint.h>
0040 #include <TGDMLMatrix.h>
0041
0042
0043 #include <cerrno>
0044 #include <cstdlib>
0045 #include <sstream>
0046
0047 using namespace dd4hep;
0048 using namespace dd4hep::detail;
0049
0050 namespace {
0051
0052 struct ProcessorArgs {
0053 bool use = false;
0054 int start = 0, end = 0, argc = 0, count=0;
0055 std::vector<char*> argv;
0056 ProcessorArgs(int ac, char** av) {
0057 for(int i=0; i<ac; ++i) {
0058 if ( 0 == ::strncmp(av[i],"-processor",6) ) {
0059 use = true;
0060 start = i;
0061 }
0062 if ( use ) {
0063 ++argc; ++count; end = i;
0064 if ( 0 == ::strncmp(av[i],"-end-processor",6) ) {
0065 argv.emplace_back(av[i]);
0066 return;
0067 }
0068 else if ( 0 == ::strncmp(av[i],"-end-plugin",4) ) {
0069 argv.emplace_back((char*)"-end-processor");
0070 return;
0071 }
0072 else if ( 0 == ::strncmp(av[i],"-plugin",4) ) {
0073 argv.emplace_back((char*)"-end-processor");
0074 return;
0075 }
0076 argv.emplace_back(av[i]);
0077 }
0078 }
0079 }
0080 };
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 static long dummy_plugin(Detector& , int, char**) {
0092 return 1;
0093 }
0094 DECLARE_APPLY(DD4hep_DummyPlugin,dummy_plugin)
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 static void* create_description_instance(const char* ) {
0105 return &Detector::getInstance();
0106 }
0107 DECLARE_CONSTRUCTOR(Detector_constructor,create_description_instance)
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 static long display(Detector& description, int argc, char** argv) {
0119 TGeoManager& mgr = description.manager();
0120 int vislevel = 6, visopt = 1;
0121 std::string detector = "/world";
0122 const char* opt = "ogl";
0123 for( int i = 0; i < argc && argv[i]; ++i ) {
0124 if ( 0 == ::strncmp("-option",argv[i],4) )
0125 opt = argv[++i];
0126 else if ( 0 == ::strncmp("-level",argv[i],4) )
0127 vislevel = ::atol(argv[++i]);
0128 else if ( 0 == ::strncmp("-visopt",argv[i],4) )
0129 visopt = ::atol(argv[++i]);
0130 else if ( 0 == ::strncmp("-detector",argv[i],4) )
0131 detector = argv[++i];
0132 else {
0133 std::cout <<
0134 "Usage: -plugin DD4hep_GeometryDisplay -arg [-arg] \n\n"
0135 " Invoke the ROOT geometry display using the factory mechanism. \n\n"
0136 " -detector <string> Top level DetElement path. Default: '/world' \n"
0137 " -option <string> ROOT Draw option. Default: 'ogl' \n"
0138 " -level <number> Visualization level [TGeoManager::SetVisLevel] Default: 4 \n"
0139 " -visopt <number> Visualization option [TGeoManager::SetVisOption] Default: 1\n"
0140 " -load Only load the geometry. Do not invoke the display \n"
0141 " -help Print this help output \n"
0142 " Arguments given: " << arguments(argc,argv) << std::endl << std::flush;
0143 ::exit(EINVAL);
0144 }
0145 }
0146 mgr.SetVisLevel(vislevel);
0147 mgr.SetVisOption(visopt);
0148 TGeoVolume* vol = mgr.GetTopVolume();
0149 if ( detector != "/world" ) {
0150 DetElement elt = detail::tools::findElement(description,detector);
0151 if ( !elt.isValid() ) {
0152 except("DD4hep_GeometryDisplay","+++ Invalid DetElement path: %s",detector.c_str());
0153 }
0154 if ( !elt.placement().isValid() ) {
0155 except("DD4hep_GeometryDisplay","+++ Invalid DetElement placement: %s",detector.c_str());
0156 }
0157 vol = elt.placement().volume();
0158 }
0159 if ( vol ) {
0160 vol->Draw(opt);
0161 return 1;
0162 }
0163 return 0;
0164 }
0165 DECLARE_APPLY(DD4hep_GeometryDisplay,display)
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 static long run_function(Detector&, int argc, char** argv) {
0176 std::string lib, func;
0177 std::vector<char*> args;
0178 for(int i = 0; i < argc && argv[i]; ++i) {
0179 if ( 0 == ::strncmp("-library",argv[i],4) )
0180 lib = argv[++i];
0181 else if ( 0 == ::strncmp("-function",argv[i],4) )
0182 func = argv[++i];
0183 else
0184 args.emplace_back(argv[i]);
0185 }
0186 if ( lib.empty() || func.empty() ) {
0187 std::cout <<
0188 "Usage: -plugin DD4hep_Function -arg [-arg] \n\n"
0189 " Execute a function without arguments inside a library. \n\n"
0190 " -library <string> Library to be loaded \n"
0191 " -function <string> name of the entry point to be executed. \n"
0192 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
0193 ::exit(EINVAL);
0194 }
0195 Func_t f = gSystem->DynFindSymbol("*",func.c_str());
0196 int ret;
0197 if ( !f ) {
0198 ret = gSystem->Load(lib.c_str());
0199 if ( ret != 0 ) {
0200 except("DD4hep_Function","+++ Failed to load library: %s",lib.c_str());
0201 }
0202 f = gSystem->DynFindSymbol("*",func.c_str());
0203 if ( !f ) {
0204 except("DD4hep_Function","+++ Failed to find function %s in library: %s",
0205 func.c_str(),lib.c_str());
0206 }
0207 }
0208 typedef int (*call_t)(int, char**);
0209 call_t ff = (call_t)f;
0210 ret = (*ff)(args.size(),&args[0]);
0211 return ret;
0212 }
0213 DECLARE_APPLY(DD4hep_Function,run_function)
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223 static long run_interpreter(Detector& , int argc, char** argv) {
0224 if ( 0 == gApplication ) {
0225 std::pair<int, char**> a(argc,argv);
0226 gApplication = new TRint("DD4hepRint", &a.first, a.second);
0227 printout(INFO,"DD4hepRint","++ Created ROOT interpreter instance for DD4hepUI.");
0228 }
0229 for(int i=0; i<argc; ++i) {
0230 printout(INFO,"DD4hepRint","Excecute[%d]: %s", i, argv[i]);
0231 gInterpreter->ProcessLine(argv[i]);
0232 }
0233 if ( !gApplication->IsRunning() ) {
0234 gApplication->Run();
0235 }
0236 return 1;
0237 }
0238 DECLARE_APPLY(DD4hep_Rint,run_interpreter)
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 static long root_ui(Detector& description, int , char** ) {
0253 char cmd[256];
0254 std::snprintf(cmd, sizeof(cmd),
0255 "dd4hep::detail::DD4hepUI* gDD4hepUI = new "
0256 "dd4hep::detail::DD4hepUI(*(dd4hep::Detector*)%p);",
0257 (void*)&description);
0258 gInterpreter->ProcessLine(cmd);
0259 printout(ALWAYS,"DD4hepUI",
0260 "Use the ROOT interpreter variable gDD4hepUI "
0261 "to interact with the detector description.");
0262 return 1;
0263 }
0264 DECLARE_APPLY(DD4hep_InteractiveUI,root_ui)
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 static long root_dump_gdml_tables(Detector& description, int , char** ) {
0276 size_t num_tables = 0;
0277 size_t num_elements = 0;
0278 const TObjArray* c = description.manager().GetListOfGDMLMatrices();
0279 TObjArrayIter arr(c);
0280 printout(INFO,"Dump_GDMLTables","+++ Dumping known GDML tables from TGeoManager.");
0281 for(TObject* i = arr.Next(); i; i=arr.Next()) {
0282 TGDMLMatrix* gdmlMat = (TGDMLMatrix*)i;
0283 num_elements += (gdmlMat->GetRows()*gdmlMat->GetCols());
0284 ++num_tables;
0285 gdmlMat->Print();
0286 }
0287 printout(INFO,"Dump_GDMLTables",
0288 "+++ Successfully dumped %ld GDML tables with %ld elements.",
0289 num_tables, num_elements);
0290 return 1;
0291 }
0292 DECLARE_APPLY(DD4hep_Dump_GDMLTables,root_dump_gdml_tables)
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 static long root_dump_optical_surfaces(Detector& description, int , char** ) {
0304 size_t num_surfaces = 0;
0305 printout(ALWAYS,"","");
0306 const TObjArray* c = description.manager().GetListOfOpticalSurfaces();
0307 TObjArrayIter arr(c);
0308 printout(ALWAYS,"Dump_OpticalSurfaces","+++ Dumping known Optical Surfaces from TGeoManager.");
0309 for(TObject* i = arr.Next(); i; i=arr.Next()) {
0310 TGeoOpticalSurface* optSurt = (TGeoOpticalSurface*)i;
0311 ++num_surfaces;
0312 optSurt->Print();
0313 }
0314 printout(ALWAYS,"Dump_OpticalSurfaces",
0315 "+++ Successfully dumped %ld Optical surfaces.",num_surfaces);
0316 return 1;
0317 }
0318 DECLARE_APPLY(DD4hep_Dump_OpticalSurfaces,root_dump_optical_surfaces)
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329 static long root_dump_skin_surfaces(Detector& description, int , char** ) {
0330 size_t num_surfaces = 0;
0331 printout(ALWAYS,"","");
0332 const TObjArray* c = description.manager().GetListOfSkinSurfaces();
0333 TObjArrayIter arr(c);
0334 printout(ALWAYS,"Dump_SkinSurfaces","+++ Dumping known Skin Surfaces from TGeoManager.");
0335 for(TObject* i = arr.Next(); i; i=arr.Next()) {
0336 TGeoSkinSurface* skinSurf = (TGeoSkinSurface*)i;
0337 ++num_surfaces;
0338 skinSurf->Print();
0339 }
0340 printout(ALWAYS,"Dump_SkinSurfaces",
0341 "+++ Successfully dumped %ld Skin surfaces.",num_surfaces);
0342 return 1;
0343 }
0344 DECLARE_APPLY(DD4hep_Dump_SkinSurfaces,root_dump_skin_surfaces)
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 static long root_dump_border_surfaces(Detector& description, int , char** ) {
0356 size_t num_surfaces = 0;
0357 printout(ALWAYS,"","");
0358 const TObjArray* c = description.manager().GetListOfBorderSurfaces();
0359 TObjArrayIter arr(c);
0360 printout(ALWAYS,"Dump_BorderSurfaces","+++ Dumping known Border Surfaces from TGeoManager.");
0361 for(TObject* i = arr.Next(); i; i=arr.Next()) {
0362 TGeoBorderSurface* bordSurt = (TGeoBorderSurface*)i;
0363 ++num_surfaces;
0364 bordSurt->Print();
0365 }
0366 printout(ALWAYS,"Dump_BorderSurfaces",
0367 "+++ Successfully dumped %ld Border surfaces.",num_surfaces);
0368 return 1;
0369 }
0370 DECLARE_APPLY(DD4hep_Dump_BorderSurfaces,root_dump_border_surfaces)
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382 static long root_elements(Detector& description, int argc, char** argv) {
0383 using elt_h = xml::Element;
0384
0385
0386
0387
0388
0389
0390
0391 struct ElementPrint {
0392
0393 ElementPrint() = default;
0394
0395 virtual ~ElementPrint() = default;
0396
0397 virtual void operator()(TGeoElement* elt) { elt->Print(); }
0398
0399 virtual void operator()(TGeoIsotope* iso) { iso->Print(); }
0400 };
0401
0402
0403
0404
0405
0406
0407
0408 struct ElementPrintXML : public ElementPrint {
0409
0410 elt_h root;
0411
0412 ElementPrintXML(elt_h r) : root(r) {}
0413
0414 virtual ~ElementPrintXML() {}
0415
0416 virtual void operator()(TGeoElement* element) {
0417 elt_h elt = root.addChild(_U(element));
0418 elt.setAttr(_U(Z),element->Z());
0419 elt.setAttr(_U(N),element->N());
0420 elt.setAttr(_U(formula),element->GetName());
0421 elt.setAttr(_U(name),element->GetName());
0422 elt_h atom = elt.addChild(_U(atom));
0423 atom.setAttr(_U(type),"A");
0424 atom.setAttr(_U(unit),"g/mole");
0425 atom.setAttr(_U(value),element->A());
0426 }
0427
0428 virtual void operator()(TGeoIsotope* isotope) {
0429 elt_h iso = root.addChild(_U(isotope));
0430 iso.setAttr(_U(Z),isotope->GetZ());
0431 iso.setAttr(_U(N),isotope->GetN());
0432 iso.setAttr(_U(formula),isotope->GetName());
0433 iso.setAttr(_U(name),isotope->GetName());
0434 elt_h atom = iso.addChild(_U(atom));
0435 atom.setAttr(_U(type),"A");
0436 atom.setAttr(_U(unit),"g/mole");
0437 atom.setAttr(_U(value),isotope->GetA());
0438 }
0439 };
0440
0441 std::string type = "text", output = "";
0442 for(int i=0; i<argc; ++i) {
0443 if ( argv[i][0] == '-' ) {
0444 char c = ::tolower(argv[i][1]);
0445 if ( c == 't' && i+1<argc ) type = argv[++i];
0446 else if ( c == 'o' && i+1<argc ) output = argv[++i];
0447 else {
0448 ::printf("DD4hep_ElementTable -opt [-opt] \n"
0449 " -type <string> Output format: text or xml \n"
0450 " -output <file-name> Output file specifier (xml only) \n"
0451 "\n");
0452 exit(EINVAL);
0453 }
0454 }
0455 }
0456
0457 xml::Document doc(0);
0458 xml::DocumentHandler docH;
0459 xml::Element element(0);
0460 if ( type == "xml" ) {
0461 const char comment[] = "\n"
0462 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
0463 " ++++ Generic detector description in C++ ++++\n"
0464 " ++++ dd4hep Detector description generator. ++++\n"
0465 " ++++ ++++\n"
0466 " ++++ Parser:"
0467 XML_IMPLEMENTATION_TYPE
0468 " ++++\n"
0469 " ++++ ++++\n"
0470 " ++++ Table of elements as defined in ROOT: " ROOT_RELEASE " ++++\n"
0471 " ++++ ++++\n"
0472 " ++++ M.Frank CERN/LHCb ++++\n"
0473 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n ";
0474 doc = docH.create("materials", comment);
0475 element = doc.root();
0476 }
0477 dd4hep_ptr<ElementPrint> printer(element
0478 ? new ElementPrintXML(element)
0479 : new ElementPrint());
0480 TGeoElementTable* table = description.manager().GetElementTable();
0481 for(Int_t i=0, n=table->GetNelements(); i < n; ++i)
0482 (*printer)(table->GetElement(i));
0483
0484 for(Int_t i=0, n=table->GetNelements(); i < n; ++i) {
0485 TGeoElement* elt = table->GetElement(i);
0486 Int_t niso = elt->GetNisotopes();
0487 if ( niso > 0 ) {
0488 for(Int_t j=0; j < niso; ++j)
0489 (*printer)(elt->GetIsotope(j));
0490 }
0491 }
0492 if ( element ) {
0493 xml::DocumentHandler dH;
0494 dH.output(doc, output);
0495 }
0496 return 1;
0497 }
0498 DECLARE_APPLY(DD4hep_ElementTable,root_elements)
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510 static long root_materials(Detector& description, int argc, char** argv) {
0511
0512 using elt_h = xml::Element;
0513
0514
0515
0516
0517
0518
0519
0520 struct MaterialPrint {
0521 public:
0522
0523 Detector& description;
0524
0525 public:
0526
0527 MaterialPrint(Detector& desc) : description(desc) {}
0528
0529 virtual ~MaterialPrint() = default;
0530
0531 virtual elt_h print(TGeoMaterial* mat) {
0532 const char* st = "Undefined";
0533 switch( mat->GetState() ) {
0534 case TGeoMaterial::kMatStateSolid: st = "solid"; break;
0535 case TGeoMaterial::kMatStateLiquid: st = "liquid"; break;
0536 case TGeoMaterial::kMatStateGas: st = "gas"; break;
0537 case TGeoMaterial::kMatStateUndefined:
0538 default: st = "Undefined"; break;
0539 }
0540 ::printf("%-32s %-8s\n", mat->GetName(), mat->IsMixture() ? "Mixture" : "Material");
0541 ::printf(" Aeff=%7.3f Zeff=%7.4f rho=%8.3f [g/mole] radlen=%8.3g [cm] intlen=%8.3g [cm] index=%3d\n",
0542 mat->GetA(), mat->GetZ(), mat->GetDensity(),
0543 mat->GetRadLen(), mat->GetIntLen(), mat->GetIndex());
0544 ::printf(" Temp=%.3g [Kelvin] Pressure=%.5g [hPa] state=%s\n",
0545 mat->GetTemperature(), mat->GetPressure()/dd4hep::pascal/100.0, st);
0546 return elt_h(0);
0547 }
0548
0549 virtual void print(elt_h, TGeoElement* elt, double frac) {
0550 ::printf(" %-6s Fraction: %7.3f Z=%3d A=%6.2f N=%3d Neff=%6.2f\n",
0551 elt->GetName(), frac, elt->Z(), elt->A(), elt->N(), elt->Neff());
0552 }
0553
0554 virtual void printProperty(elt_h, TNamed* prop, TGDMLMatrix* matrix) {
0555 if ( matrix )
0556 ::printf(" Property: %-20s [%ld x %ld] --> %s\n",
0557 prop->GetName(), long(matrix->GetRows()), long(matrix->GetCols()), prop->GetTitle());
0558 else
0559 ::printf(" Property: %-20s [ERROR: NO TABLE!] --> %s\n",
0560 prop->GetName(), prop->GetTitle());
0561 }
0562 virtual void operator()(TGeoMaterial* mat) {
0563 Double_t* mix = mat->IsMixture() ? ((TGeoMixture*)mat)->GetWmixt() : 0;
0564 elt_h mh = print(mat);
0565 for( int n=mat->GetNelements(), i=0; i<n; ++i ) {
0566 TGeoElement* elt = mat->GetElement(i);
0567 print(mh, elt, mix ? mix[i] : 1);
0568 }
0569 TListIter mat_iter(&mat->GetProperties());
0570 for( TObject* i = mat_iter.Next(); i; i=mat_iter.Next() ) {
0571 printProperty(mh, (TNamed*)i, description.manager().GetGDMLMatrix(i->GetTitle()));
0572 }
0573 }
0574 };
0575
0576
0577
0578
0579
0580
0581 struct MaterialPrintXML : public MaterialPrint {
0582 elt_h root;
0583 MaterialPrintXML(elt_h elt, Detector& desc) : MaterialPrint(desc), root(elt) {}
0584 virtual ~MaterialPrintXML() {}
0585 virtual elt_h print(TGeoMaterial* mat) {
0586 elt_h elt = root.addChild(_U(material));
0587 elt.setAttr(_U(name),mat->GetName());
0588 if ( ::strlen(mat->GetTitle())>0 ) {
0589 elt.setAttr(_U(formula),mat->GetTitle());
0590 }
0591 else if ( mat->GetNelements() == 1 ) {
0592 elt.setAttr(_U(formula),mat->GetElement(0)->GetName());
0593 #if 0
0594
0595 elt_h RL = elt.addChild(_U(RL));
0596 RL.setAttr(_U(type), "X0");
0597 RL.setAttr(_U(value), mat->GetRadLen());
0598 RL.setAttr(_U(unit), "cm");
0599 elt_h NIL = elt.addChild(_U(NIL));
0600 NIL.setAttr(_U(type), "lambda");
0601 NIL.setAttr(_U(value), mat->GetIntLen());
0602 NIL.setAttr(_U(unit), "cm");
0603 #endif
0604 }
0605 elt_h D = elt.addChild(_U(D));
0606 D.setAttr(_U(type), "density");
0607 D.setAttr(_U(value), mat->GetDensity());
0608 D.setAttr(_U(unit), "g/cm3");
0609 if ( mat->GetTemperature() != description.stdConditions().temperature ) {
0610 elt_h T = elt.addChild(_U(T));
0611 T.setAttr(_U(type), "temperature");
0612 T.setAttr(_U(value), mat->GetTemperature());
0613 T.setAttr(_U(unit), "kelvin");
0614 }
0615 if ( mat->GetPressure() != description.stdConditions().pressure ) {
0616 elt_h P = elt.addChild(_U(P));
0617 P.setAttr(_U(type), "pressure");
0618 P.setAttr(_U(value), mat->GetPressure());
0619 P.setAttr(_U(unit), "pascal");
0620 }
0621 return elt;
0622 }
0623 virtual void print(elt_h mat, TGeoElement* element, double frac) {
0624 elt_h elt = mat.addChild(_U(composite));
0625 elt.setAttr(_U(n),frac);
0626 elt.setAttr(_U(ref),element->GetName());
0627 }
0628 virtual void printProperty(elt_h mat, TNamed* prop, TGDMLMatrix* ) {
0629 elt_h elt = mat.addChild(_U(property));
0630 elt.setAttr(_U(name),prop->GetName());
0631 elt.setAttr(_U(ref), prop->GetTitle());
0632 }
0633 };
0634
0635 std::string type = "text", output = "", name = "";
0636 for(int i=0; i<argc; ++i) {
0637 if ( argv[i][0] == '-' ) {
0638 char c = ::tolower(argv[i][1]);
0639 if ( c == 't' && i+1<argc ) type = argv[++i];
0640 else if ( c == 'n' && i+1<argc ) name = argv[++i];
0641 else if ( c == 'o' && i+1<argc ) output = argv[++i];
0642 else {
0643 ::printf("DD4hep_MaterialTable -opt [-opt] \n"
0644 " -type <string> Output format: text or xml \n"
0645 " -output <file-name> Output file specifier (xml only) \n"
0646 "\n");
0647 exit(EINVAL);
0648 }
0649 }
0650 }
0651
0652 xml::Document doc(0);
0653 xml::DocumentHandler docH;
0654 xml::Element element(0);
0655 if ( type == "xml" ) {
0656 const char comment[] = "\n"
0657 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
0658 " ++++ Generic detector description in C++ ++++\n"
0659 " ++++ dd4hep Detector description generator. ++++\n"
0660 " ++++ ++++\n"
0661 " ++++ Parser:"
0662 XML_IMPLEMENTATION_TYPE
0663 " ++++\n"
0664 " ++++ ++++\n"
0665 " ++++ Table of elements as defined in ROOT: " ROOT_RELEASE " ++++\n"
0666 " ++++ ++++\n"
0667 " ++++ M.Frank CERN/LHCb ++++\n"
0668 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n ";
0669 doc = docH.create("materials", comment);
0670 element = doc.root();
0671 }
0672 dd4hep_ptr<MaterialPrint> printer(element
0673 ? new MaterialPrintXML(element, description)
0674 : new MaterialPrint(description));
0675 TObject* obj = 0;
0676 TList* mats = description.manager().GetListOfMaterials();
0677 dd4hep_ptr<TIterator> iter(mats->MakeIterator());
0678 while( (obj=iter->Next()) != 0 ) {
0679 TGeoMaterial* mat = (TGeoMaterial*)obj;
0680 if ( name.empty() || name == mat->GetName() )
0681 (*printer)(mat);
0682 }
0683 if ( element ) {
0684 xml::DocumentHandler dH;
0685 dH.output(doc, output);
0686 }
0687 return 1;
0688 }
0689 DECLARE_APPLY(DD4hep_MaterialTable,root_materials)
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704 static long load_compact(Detector& description, int argc, char** argv) {
0705 if ( argc > 0 ) {
0706 DetectorBuildType type = BUILD_DEFAULT;
0707 std::string input = argv[0];
0708 if ( argc > 1 ) {
0709 type = buildType(argv[1]);
0710 printout(INFO,"CompactLoader","+++ Processing compact file: %s with flag %s",
0711 input.c_str(), argv[1]);
0712 description.fromCompact(input,type);
0713 return 1;
0714 }
0715 printout(INFO,"CompactLoader","+++ Processing compact file: %s",input.c_str());
0716 description.fromCompact(input);
0717 return 1;
0718 }
0719 return 0;
0720 }
0721 DECLARE_APPLY(DD4hep_CompactLoader,load_compact)
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738 static long load_xml(Detector& description, int argc, char** argv) {
0739 if ( argc > 0 ) {
0740 DetectorBuildType type = BUILD_DEFAULT;
0741 std::string input = argv[0];
0742 if ( argc > 1 ) {
0743 type = buildType(argv[1]);
0744 printout(INFO,"XMLLoader","+++ Processing XML file: %s with flag %s",
0745 input.c_str(), argv[1]);
0746 description.fromXML(input, type);
0747 return 1;
0748 }
0749 printout(INFO,"XMLLoader","+++ Processing XML file: %s",input.c_str());
0750 description.fromXML(input, description.buildType());
0751 return 1;
0752 }
0753 return 0;
0754 }
0755 DECLARE_APPLY(DD4hep_XMLLoader,load_xml)
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772 static long process_xml_doc(Detector& description, int argc, char** argv) {
0773 if ( argc > 0 ) {
0774 DetectorBuildType type = BUILD_DEFAULT;
0775 DetectorImp* imp = dynamic_cast<DetectorImp*>(&description);
0776 if ( imp ) {
0777 xml::XmlElement* h = (xml::XmlElement*)argv[0];
0778 xml::Handle_t input(h);
0779 if ( input.ptr() ) {
0780 if ( argc > 1 ) {
0781 type = buildType(argv[1]);
0782 printout(INFO,"XMLLoader","+++ Processing XML element: %s with flag %s",
0783 input.tag().c_str(), argv[1]);
0784 }
0785 imp->processXMLElement(input, type);
0786 return 1;
0787 }
0788 except("DD4hepXMLProcessor",
0789 "++ The passed reference to the parsed XML document is invalid.");
0790 }
0791 }
0792 return 0;
0793 }
0794 DECLARE_APPLY(DD4hep_XMLProcessor,process_xml_doc)
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804 static long load_volmgr(Detector& description, int, char**) {
0805 printout(INFO,"DD4hepVolumeManager","**** running plugin DD4hepVolumeManager ! " );
0806 try {
0807 DetectorImp* imp = dynamic_cast<DetectorImp*>(&description);
0808 if ( imp ) {
0809 imp->imp_loadVolumeManager();
0810 printout(INFO,"VolumeManager","+++ Volume manager populated and loaded.");
0811 return 1;
0812 }
0813 }
0814 catch (const std::exception& e) {
0815 except("DD4hep_VolumeManager", "Exception: %s\n %s", e.what(),
0816 "dd4hep: while programming VolumeManager. Are your volIDs correct?");
0817 }
0818 catch (...) {
0819 except("DD4hep_VolumeManager",
0820 "UNKNOWN exception while programming VolumeManager. Are your volIDs correct?");
0821 }
0822 return 0;
0823 }
0824 DECLARE_APPLY(DD4hep_VolumeManager,load_volmgr)
0825 DECLARE_APPLY(DD4hepVolumeManager,load_volmgr)
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835 static long dump_geometry2root(Detector& description, int argc, char** argv) {
0836 if ( argc > 0 ) {
0837 std::string output;
0838 for(int i = 0; i < argc && argv[i]; ++i) {
0839 if ( 0 == ::strncmp("-output",argv[i],4) )
0840 output = argv[++i];
0841 }
0842 if ( output.empty() ) {
0843 std::cout <<
0844 "Usage: -plugin DD4hep_Geometry2ROOT -arg [-arg] \n\n"
0845 " Output DD4hep detector description object to a ROOT file. \n\n"
0846 " -output <string> Output file name. \n"
0847 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
0848 ::exit(EINVAL);
0849 }
0850 printout(INFO,"Geometry2ROOT","+++ Dump geometry to root file:%s",output.c_str());
0851
0852 if ( DD4hepRootPersistency::save(description,output.c_str(),"Geometry") > 1 ) {
0853 return 1;
0854 }
0855 }
0856 printout(ERROR,"Geometry2ROOT","+++ No output file name given.");
0857 return 0;
0858 }
0859 DECLARE_APPLY(DD4hep_Geometry2ROOT,dump_geometry2root)
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869 static long load_geometryFromroot(Detector& description, int argc, char** argv) {
0870 if ( argc > 0 ) {
0871 std::string input = argv[0];
0872 for(int i = 0; i < argc && argv[i]; ++i) {
0873 if ( 0 == ::strncmp("-input",argv[i],4) )
0874 input = argv[++i];
0875 }
0876 if ( input.empty() ) {
0877 std::cout <<
0878 "Usage: DD4hep_RootLoader -arg [-arg] \n\n"
0879 " Load DD4hep detector description from ROOT file to memory. \n\n"
0880 " -input <string> Input file name. \n"
0881 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
0882 ::exit(EINVAL);
0883 }
0884 printout(INFO,"DD4hepRootLoader","+++ Read geometry from root file:%s",input.c_str());
0885 if ( 1 == DD4hepRootPersistency::load(description,input.c_str(),"Geometry") ) {
0886 return 1;
0887 }
0888 }
0889 printout(ERROR,"DD4hep_RootLoader","+++ No input file name given.");
0890 return 0;
0891 }
0892 DECLARE_APPLY(DD4hep_RootLoader,load_geometryFromroot)
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902 static long dump_geometry2tgeo(Detector& description, int argc, char** argv) {
0903 if ( argc > 0 ) {
0904 std::string output( argc == 1 ? argv[0] : "" );
0905 printout(INFO,"Geometry2TGeo","+++ output: %d %s", argc, output.c_str());
0906 for(int i = 0; i < argc && argv[i]; ++i) {
0907 if ( 0 == ::strncmp("-output",argv[i],4) )
0908 output = argv[++i];
0909 }
0910 if ( output.empty() ) {
0911 std::cout <<
0912 "Usage: -plugin <name> -arg [-arg] \n"
0913 " Output TGeo information to a ROOT file. \n\n"
0914 " name: factory name DD4hepGeometry2TGeo \n"
0915 " -output <string> Output file name. \n"
0916 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
0917 ::exit(EINVAL);
0918 }
0919 printout(INFO,"Geometry2TGeo","+++ Dump geometry to root file:%s",output.c_str());
0920 if ( description.manager().Export(output.c_str()) > 1 ) {
0921 return 1;
0922 }
0923 }
0924 printout(ERROR,"Geometry2TGeo","+++ No output file name given.");
0925 return 0;
0926 }
0927 DECLARE_APPLY(DD4hep_Geometry2TGeo,dump_geometry2tgeo)
0928 DECLARE_APPLY(DD4hepGeometry2TGeo,dump_geometry2tgeo)
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938 static long check_detectors(Detector& description, int , char** ) {
0939 DD4hepRootCheck check(&description);
0940 auto ret = check.checkDetectors();
0941 return ret.first > 0 && ret.second == 0 ? 1 : 0;
0942 }
0943 DECLARE_APPLY(DD4hep_CheckDetectors,check_detectors)
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953 static long check_sensitives(Detector& description, int , char** ) {
0954 DD4hepRootCheck check(&description);
0955 auto ret = check.checkSensitives();
0956 return ret.first > 0 && ret.second == 0 ? 1 : 0;
0957 }
0958 DECLARE_APPLY(DD4hep_CheckSensitives,check_sensitives)
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968 static long check_segmentations(Detector& description, int , char** ) {
0969 DD4hepRootCheck check(&description);
0970 auto ret = check.checkSegmentations();
0971 return ret.first > 0 && ret.second == 0 ? 1 : 0;
0972 }
0973 DECLARE_APPLY(DD4hep_CheckSegmentations,check_segmentations)
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983 static long check_readouts(Detector& description, int , char** ) {
0984 DD4hepRootCheck check(&description);
0985 auto ret = check.checkReadouts();
0986 return ret.first > 0 && ret.second == 0 ? 1 : 0;
0987 }
0988 DECLARE_APPLY(DD4hep_CheckReadouts,check_readouts)
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998 static long check_idspecs(Detector& description, int , char** ) {
0999 DD4hepRootCheck check(&description);
1000 auto ret = check.checkIdSpecs();
1001 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1002 }
1003 DECLARE_APPLY(DD4hep_CheckIdspecs,check_idspecs)
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013 static long check_volumemanager(Detector& description, int , char** ) {
1014 DD4hepRootCheck check(&description);
1015 auto ret = check.checkVolManager();
1016 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1017 }
1018 DECLARE_APPLY(DD4hep_CheckVolumeManager,check_volumemanager)
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028 static long check_nominals(Detector& description, int , char** ) {
1029 DD4hepRootCheck check(&description);
1030 auto ret = check.checkNominals();
1031 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1032 }
1033 DECLARE_APPLY(DD4hep_CheckNominals,check_nominals)
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043 static long dump_volume_tree(Detector& description, int argc, char** argv) {
1044 struct Actor {
1045 Detector& description;
1046 bool m_printPathes = false;
1047 bool m_printVolIDs = false;
1048 bool m_printShapes = false;
1049 bool m_printPointers = false;
1050 bool m_printPositions = false;
1051 bool m_printVis = false;
1052 bool m_printMaterials = false;
1053 bool m_printSensitivesOnly = false;
1054 long m_printMaxLevel = 999999;
1055 long m_numNodes = 0;
1056 long m_numShapes = 0;
1057 long m_numSensitive = 0;
1058 long m_numMaterial = 0;
1059 long m_numMaterialERR = 0;
1060 bool m_topStat = false;
1061 std::string m_detector;
1062 std::string currTop;
1063 std::map<std::string,long> top_counts;
1064
1065 Actor(Detector& desc, int ac, char** av) : description(desc) {
1066 m_detector = "/world";
1067 for(int i=0; i<ac; ++i) {
1068 char c = ::tolower(av[i][0]);
1069 char* p = av[i];
1070 if ( c == '-' ) { ++p; c = ::tolower(av[i][1]); }
1071 if ( c == '-' ) { ++p; c = ::tolower(av[i][1]); }
1072 if ( ::strncmp(p,"volume_ids",3) == 0 ) m_printVolIDs = true;
1073 else if ( ::strncmp(p,"level",3) == 0 ) m_printMaxLevel = ::atol(av[++i]);
1074 else if ( ::strncmp(p,"materials",3) == 0 ) m_printMaterials = true;
1075 else if ( ::strncmp(p,"pathes",3) == 0 ) m_printPathes = true;
1076 else if ( ::strncmp(p,"positions",3) == 0 ) m_printPositions = true;
1077 else if ( ::strncmp(p,"pointers",3) == 0 ) m_printPointers = true;
1078 else if ( ::strncmp(p,"shapes",3) == 0 ) m_printShapes = true;
1079 else if ( ::strncmp(p,"sensitive",3) == 0 ) m_printSensitivesOnly = true;
1080 else if ( ::strncmp(p,"topstats",3) == 0 ) m_topStat = true;
1081 else if ( ::strncmp(p,"vis",3) == 0 ) m_printVis = true;
1082 else if ( ::strncmp(p,"detector",3) == 0 ) m_detector = av[++i];
1083 else if ( ::strncmp(p,"help",3) == 0 ) {
1084 std::cout <<
1085 "Usage: -plugin <name> -arg [-arg] \n"
1086 " -detector <string> Top level DetElement path. Default: '/world' \n"
1087 " -pathes Print DetElement pathes \n"
1088 " -level <number> Maximal depth to be explored by the scan \n"
1089 " -positions Print placement positions \n"
1090 " -volume_ids Print placement volume IDs \n"
1091 " -materials Print volume materials \n"
1092 " -pointers Debug: Print pointer values \n"
1093 " -shapes Print shape information \n"
1094 " -vis Print visualisation attribute name(s) if present \n"
1095 " -sensitive Only print information for sensitive volumes \n"
1096 " -topstats Print statistics about top level node \n"
1097 "\tArguments given: " << arguments(ac,av) << std::endl << std::flush;
1098 _exit(0);
1099 }
1100 }
1101 if ( m_printMaxLevel < 999999 )
1102 printout(ALWAYS,"VolumeDump","+++ Maximal print level: %ld",m_printMaxLevel);
1103 if ( !m_detector.empty() )
1104 printout(ALWAYS,"VolumeDump","+++ Subdetector path: %s",m_detector.c_str());
1105 printout(ALWAYS,"VolumeDump","+++ Printing positions: %s",yes_no(m_printPositions));
1106 printout(ALWAYS,"VolumeDump","+++ Printing shapes: %s",yes_no(m_printShapes));
1107 printout(ALWAYS,"VolumeDump","+++ Printing materials: %s",yes_no(m_printMaterials));
1108 printout(ALWAYS,"VolumeDump","+++ Printing volume ids: %s",yes_no(m_printVolIDs));
1109 printout(ALWAYS,"VolumeDump","+++ Printing visattrs: %s",yes_no(m_printVis));
1110 printout(ALWAYS,"VolumeDump","+++ Print only sensitives: %s",yes_no(m_printSensitivesOnly));
1111 }
1112 ~Actor() {
1113 printout(ALWAYS,"VolumeDump",
1114 "+++ Checked %ld physical volume placements. %3ld are sensitive.",
1115 m_numNodes, m_numSensitive);
1116 if ( m_printMaterials ) {
1117 printout(ALWAYS,"VolumeDump",
1118 "+++ Checked %ld materials in volume placements. %3ld are BAD.",
1119 m_numMaterial, m_numMaterialERR);
1120 }
1121 if ( m_printShapes ) {
1122 printout(ALWAYS,"VolumeDump","+++ Checked %ld shapes.", m_numShapes);
1123 }
1124 if ( m_topStat ) {
1125 for(const auto& t : top_counts) {
1126 if ( t.second > 1 )
1127 printout(ALWAYS,"VolumeDump",
1128 "+++ Top node: %-32s %8ld placements.",t.first.c_str(),t.second);
1129 }
1130 }
1131 }
1132
1133 long dump(std::string prefix, TGeoNode* ideal, TGeoNode* aligned, int level, PlacedVolume::VolIDs volids) {
1134 char fmt[128];
1135 std::stringstream log;
1136 PlacedVolume pv(ideal);
1137 bool sensitive = false;
1138 std::string opt_info, pref = std::move(prefix);
1139
1140 if ( level >= m_printMaxLevel ) {
1141 return 1;
1142 }
1143 ++m_numNodes;
1144 if ( level == 0 )
1145 currTop = "";
1146 else if ( level == 1 ) {
1147 currTop = ideal->GetVolume()->GetName();
1148 ++top_counts[currTop];
1149 }
1150 else if ( level > 1 ) {
1151 ++top_counts[currTop];
1152 }
1153
1154 if ( m_printPathes ) {
1155 pref += "/";
1156 pref += aligned->GetName();
1157 }
1158
1159 TGeoVolume* mother = ideal ? ideal->GetMotherVolume() : nullptr;
1160 if ( m_printPositions || m_printVolIDs ) {
1161 if ( m_printPointers ) {
1162 if ( ideal != aligned )
1163 std::snprintf(fmt,sizeof(fmt),"Ideal:%p Aligned:%p ",
1164 (void*)ideal,(void*)aligned);
1165 else
1166 std::snprintf(fmt,sizeof(fmt),"Ideal:%p MotherVol:%p",
1167 (void*)ideal, (void*)mother);
1168 log << fmt;
1169 }
1170
1171 if ( m_printVolIDs && ideal && ideal->GetMotherVolume() ) {
1172 PlacedVolume::VolIDs vid = pv.volIDs();
1173 if ( !vid.empty() ) {
1174 sensitive = true;
1175 log << " VolID: ";
1176 volids.insert(volids.end(),vid.begin(),vid.end());
1177 for( const auto& i : volids ) {
1178 std::snprintf(fmt, sizeof(fmt), "%s:%2d ",i.first.c_str(),i.second);
1179 log << fmt;
1180 }
1181 if ( !vid.empty() || pv.volume().isSensitive() ) {
1182 SensitiveDetector sd = pv.volume().sensitiveDetector();
1183 if ( sd.isValid() ) {
1184 IDDescriptor dsc = sd.readout().idSpec();
1185 if ( dsc.isValid() ) {
1186 log << std::hex << " (0x" << std::setfill('0') << std::setw(8)
1187 << dsc.encode(volids)
1188 << std::setfill(' ') << std::dec << ") ";
1189 }
1190 }
1191 }
1192 }
1193 }
1194 opt_info = log.str();
1195 log.str("");
1196 }
1197
1198 if ( m_printVis && pv.volume().visAttributes().isValid() ) {
1199 log << " Vis:" << pv.volume().visAttributes().name();
1200 opt_info += log.str();
1201 log.str("");
1202 }
1203 TGeoVolume* volume = ideal ? ideal->GetVolume() : 0;
1204 if ( !m_printSensitivesOnly || (m_printSensitivesOnly && sensitive) ) {
1205 Volume vol = pv.volume();
1206 char sens = vol.isSensitive() ? 'S' : ' ';
1207 if ( m_printPointers ) {
1208 if ( ideal == aligned ) {
1209 std::snprintf(fmt,sizeof(fmt),"%03d %%s [Ideal:%p Vol:%p MotherVol:%p] %%-%ds %%-16s Vol:%%s shape:%%s \t %c %%s",
1210 level+1,(void*)ideal,(void*)vol, (void*)mother, 2*level+1, sens);
1211 }
1212 else {
1213 std::snprintf(fmt,sizeof(fmt),"%03d %%s Ideal:%p Aligned:%p %%-%ds %%-16s Vol:%%s shape:%%s %c %%s",
1214 level+1,(void*)ideal,(void*)aligned,2*level+1,sens);
1215 }
1216 }
1217 else {
1218 if ( ideal == aligned ) {
1219 std::snprintf(fmt,sizeof(fmt),"%03d %%s %%-%ds %%-16s Vol:%%s shape:%%s \t %c %%s",
1220 level+1,2*level+1,sens);
1221 }
1222 else {
1223 std::snprintf(fmt,sizeof(fmt),"%03d %%s Ideal:%p Aligned:%p %%-%ds %%-16s Vol:%%s shape:%%s %c %%s",
1224 level+1,(void*)ideal,(void*)aligned,2*level+1,sens);
1225 }
1226 }
1227 const auto* sh = volume ? volume->GetShape() : nullptr;
1228 printout(INFO,"VolumeDump",fmt,pref.c_str(),"",
1229 aligned->GetName(),
1230 vol.name(),
1231 sh ? sh->IsA()->GetName() : "[Invalid Shape]",
1232 opt_info.c_str());
1233 if ( sens == 'S' ) ++m_numSensitive;
1234 }
1235 if ( m_printMaterials ) {
1236 Volume vol = pv.volume();
1237 Material mat = vol.material();
1238 TGeoMaterial* mptr = mat->GetMaterial();
1239 bool ok = mat.A() == mptr->GetA() && mat.Z() == mptr->GetZ();
1240 std::snprintf(fmt,sizeof(fmt),"%03d %%s %%-%ds Material: %%-16s A:%%6.2f %%6.2f Z:%%6.2f %%6.2f",
1241 level+1,2*level+1);
1242 ++m_numMaterial;
1243 if ( !ok ) ++m_numMaterialERR;
1244 printout(ok ? INFO : ERROR, "VolumeDump", fmt,
1245 " ->", "", mat.name(), mat.A(), mptr->GetA(), mat.Z(), mptr->GetZ());
1246 }
1247 log.str("");
1248 if ( m_printShapes ) {
1249 log << "Shape: " << toStringSolid(pv.volume().solid()) << " \t";
1250 }
1251 if ( m_printPositions ) {
1252 if ( ideal ) {
1253 const double* trans = ideal->GetMatrix()->GetTranslation();
1254 std::snprintf(fmt, sizeof(fmt), "Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]);
1255 }
1256 else {
1257 std::snprintf(fmt, sizeof(fmt), " <ERROR: INVALID Translation matrix> ");
1258 }
1259 log << fmt << " \t";
1260 }
1261 if ( !log.str().empty() ) {
1262 std::snprintf(fmt,sizeof(fmt),"%03d %%s %%-%ds %%s",level+1,2*level+1);
1263 printout(INFO, "VolumeDump", fmt, " ->", "", log.str().c_str());
1264 }
1265 for (Int_t idau = 0, ndau = aligned->GetNdaughters(); idau < ndau; ++idau) {
1266 if ( ideal ) {
1267 TGeoNode* ideal_daughter = ideal->GetDaughter(idau);
1268 const char* daughter_name = ideal_daughter->GetName();
1269 TGeoNode* aligned_daughter = volume->GetNode(daughter_name);
1270 dump(pref, ideal_daughter, aligned_daughter, level+1, volids);
1271 }
1272 else {
1273 printout(ERROR,"VolumeDump"," <ERROR: INVALID IDEAL Translation matrix>: %s",aligned->GetName());
1274 }
1275 }
1276 return 1;
1277 }
1278
1279 int operator()() {
1280 PlacedVolume pv;
1281 DetElement top = description.world();
1282 detail::tools::PlacementPath path;
1283
1284 if ( m_detector != "/world" ) {
1285 top = detail::tools::findElement(description,m_detector);
1286 if ( !top.isValid() ) {
1287 except("VolumeDump","+++ Invalid DetElement path: %s",m_detector.c_str());
1288 }
1289 }
1290 if ( !top.placement().isValid() ) {
1291 except("VolumeDump","+++ Invalid DetElement placement: %s",m_detector.c_str());
1292 }
1293 std::string place = top.placementPath();
1294 detail::tools::placementPath(top, path);
1295 pv = detail::tools::findNode(description.world().placement(),place);
1296 if ( !pv.isValid() ) {
1297 except("VolumeDump","+++ Invalid placement verification for placement:%s",place.c_str());
1298 }
1299 return this->dump("", top.placement().ptr(), pv.ptr(), 0, PlacedVolume::VolIDs());
1300 }
1301 };
1302 Actor actor(description, argc, argv);
1303 return actor();
1304 }
1305 DECLARE_APPLY(DD4hep_VolumeDump,dump_volume_tree)
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320 static int detelement_processor(Detector& description, int argc, char** argv) {
1321 bool recursive = true;
1322 ProcessorArgs args(argc, argv);
1323 DetElement det = description.world();
1324 std::unique_ptr<DetectorProcessor>
1325 proc(dd4hep::createProcessor<DetectorProcessor>(description, args.argc, &args.argv[0]));
1326
1327 for(int i=0; i<argc; ++i) {
1328 if ( i >= args.start && i <= args.end )
1329 continue;
1330 else if ( 0 == ::strncmp(argv[i],"-recursive",4) )
1331 recursive = true;
1332 else if ( 0 == ::strncmp(argv[i],"-no-recursive",7) )
1333 recursive = false;
1334 else if ( 0 == ::strncmp(argv[i],"-detector",4) ) {
1335 std::string path = argv[++i];
1336 det = detail::tools::findElement(description, path);
1337 if ( det.isValid() ) {
1338 continue;
1339 }
1340 except("DetElementProcessor",
1341 "++ The detector element path:%s is not part of this description!",
1342 path.c_str());
1343 }
1344 else {
1345 except("DetElementProcessor","++ Unknown plugin argument: %s",argv[i]);
1346 }
1347 }
1348 return DetectorScanner().scan(*proc, det, 0, recursive) > 0 ? 1 : 0;
1349 }
1350 DECLARE_APPLY(DD4hep_DetElementProcessor,detelement_processor)
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 static int placed_volume_processor(Detector& description, int argc, char** argv) {
1366 bool recursive = true;
1367 PlacedVolume pv = description.world().placement();
1368 ProcessorArgs args(argc, argv);
1369 std::unique_ptr<PlacedVolumeProcessor>
1370 proc(dd4hep::createProcessor<PlacedVolumeProcessor>(description, args.argc, &args.argv[0]));
1371
1372 std::string path = "/world";
1373 for(int i=0; i<argc; ++i) {
1374 if ( i >= args.start && i <= args.end )
1375 continue;
1376 else if ( 0 == ::strncmp(argv[i],"-recursive",4) )
1377 recursive = true;
1378 else if ( 0 == ::strncmp(argv[i],"--recursive",5) )
1379 recursive = true;
1380 else if ( 0 == ::strncmp(argv[i],"-no-recursive",7) )
1381 recursive = false;
1382 else if ( 0 == ::strncmp(argv[i],"--no-recursive",8) )
1383 recursive = false;
1384 else if ( 0 == ::strncmp(argv[i],"-detector",4) )
1385 path = argv[++i];
1386 else if ( 0 == ::strncmp(argv[i],"--detector",5) )
1387 path = argv[++i];
1388 else
1389 except("PlacedVolumeProcessor","++ Unknown plugin argument: %s",argv[i]);
1390 }
1391 DetElement det = detail::tools::findElement(description, path);
1392 if ( det.isValid() ) {
1393 pv = det.placement();
1394 if ( pv.isValid() ) {
1395 return PlacedVolumeScanner().scanPlacements(*proc, pv, 0, recursive) > 0 ? 1 : 0;
1396 }
1397 except("PlacedVolumeProcessor",
1398 "++ The detector element with path:%s has no valid placement!",
1399 path.c_str());
1400 }
1401 except("PlacedVolumeProcessor",
1402 "++ The detector element path:%s is not part of this description!",
1403 path.c_str());
1404 return 0;
1405 }
1406 DECLARE_APPLY(DD4hep_PlacedVolumeProcessor,placed_volume_processor)
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416 template <int flag> long dump_detelement_tree(Detector& description, int argc, char** argv) {
1417 using VolIDs = PlacedVolume::VolIDs;
1418
1419 struct Actor {
1420 Detector& descr;
1421 std::string path { };
1422 DetElement det_world { };
1423 long count = 0;
1424 int have_match = -1;
1425 int analysis_level = 999999;
1426 bool dump_materials = false;
1427 bool dump_shapes = false;
1428 bool dump_positions = false;
1429 bool dump_volids = false;
1430 bool sensitive_only = false;
1431
1432
1433 Actor(Detector& det) : descr(det) {
1434 det_world = descr.world();
1435 }
1436
1437 ~Actor() {
1438 printout(ALWAYS,"DetectorDump", "+++ Scanned a total of %ld elements.",count);
1439 }
1440 void parse_args(int ac, char** av) {
1441 for(int i=0; i<ac; ++i) {
1442 if ( ::strncmp(av[i],"--sensitive", 5)==0 ) { sensitive_only = true; }
1443 else if ( ::strncmp(av[i], "-sensitive", 5)==0 ) { sensitive_only = true; }
1444 else if ( ::strncmp(av[i], "--no-sensitive", 8)==0 ) { sensitive_only = false; }
1445 else if ( ::strncmp(av[i], "-materials", 4)==0 ) { dump_materials = true; }
1446 else if ( ::strncmp(av[i], "--materials", 5)==0 ) { dump_materials = true; }
1447 else if ( ::strncmp(av[i], "-shapes", 4)==0 ) { dump_shapes = true; }
1448 else if ( ::strncmp(av[i], "--shapes", 5)==0 ) { dump_shapes = true; }
1449 else if ( ::strncmp(av[i], "-positions", 4)==0 ) { dump_positions = true; }
1450 else if ( ::strncmp(av[i], "--positions", 5)==0 ) { dump_positions = true; }
1451 else if ( ::strncmp(av[i], "-no-sensitive", 7)==0 ) { sensitive_only = false; }
1452 else if ( ::strncmp(av[i], "--volids", 5)==0 ) { dump_volids = true; }
1453 else if ( ::strncmp(av[i], "-volids", 5)==0 ) { dump_volids = true; }
1454 else if ( ::strncmp(av[i], "--detector", 5)==0 ) { path = av[++i]; }
1455 else if ( ::strncmp(av[i], "-detector", 5)==0 ) { path = av[++i]; }
1456 else if ( ::strncmp(av[i], "--level", 5)==0 ) { analysis_level = ::atol(av[++i]); }
1457 else if ( ::strncmp(av[i], "-level", 5)==0 ) { analysis_level = ::atol(av[++i]); }
1458 else {
1459 std::cout << " "
1460 << (flag==0 ? "DD4hep_DetectorDump" : "DD4hep_DetectorVolumeDump") << " -arg [-arg] \n\n"
1461 << " Dump " << (flag==0 ? "DetElement" : "Detector volume") << " tree. \n"
1462 << " Configure produced output information using the following options: \n\n"
1463 " --sensitive Process only sensitive volumes. \n"
1464 " -sensitive dto. \n"
1465 " --no-sensitive Invert sensitive only flag. \n"
1466 " -no-sensitive dto. \n"
1467 " --shapes Print shape information. \n"
1468 " -shapes dto. \n"
1469 " --positions Print position information. \n"
1470 " -positions dto. \n"
1471 " --materials Print material information. \n"
1472 " -materials dto. \n"
1473 " --detector <path> Process elements only if <path> is part of the DetElement path.\n"
1474 " -detector <path> dto. \n"
1475 " -level <number> Maximal depth to be explored by the scan \n"
1476 " --level <number> dto. \n"
1477 " -volids Print volume identifiers of placements. \n"
1478 " --volids dto. \n"
1479 "\tArguments given: " << arguments(ac,av) << std::endl << std::flush;
1480 ::exit(EINVAL);
1481 }
1482 }
1483 }
1484 IDDescriptor get_id_descriptor(PlacedVolume pv) {
1485 if ( pv.isValid() ) {
1486 Volume v = pv.volume();
1487 SensitiveDetector sd = v.sensitiveDetector();
1488 if ( sd.isValid() ) {
1489 IDDescriptor dsc = sd.readout().idSpec();
1490 if ( dsc.isValid() ) return dsc;
1491 }
1492 for (Int_t idau = 0, ndau = v->GetNdaughters(); idau < ndau; ++idau) {
1493 IDDescriptor dsc = get_id_descriptor(v->GetNode(idau));
1494 if ( dsc.isValid() ) return dsc;
1495 }
1496 }
1497 return IDDescriptor();
1498 }
1499 void validate_id_descriptor(DetElement de, IDDescriptor& desc) {
1500 desc = (!de.parent() || de.parent() == det_world)
1501 ? IDDescriptor() : get_id_descriptor(de.placement());
1502 }
1503
1504 long dump(DetElement de, int level, IDDescriptor& id_desc, VolIDs chain) {
1505 char fmt[256];
1506 PlacedVolume place = de.placement();
1507 const DetElement::Children& children = de.children();
1508 bool use_elt = path.empty() || de.path().find(path) != std::string::npos;
1509
1510 if ( have_match < 0 && use_elt ) {
1511 have_match = level;
1512 }
1513
1514 use_elt &= ((level-have_match) <= analysis_level);
1515 if ( !place.isValid() ) {
1516 std::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s DetElement with INVALID PLACEMENT!", level+1, 2*level+1);
1517 printout(ERROR,"DetectorDump", fmt, "", de.path().c_str());
1518 use_elt = false;
1519 }
1520
1521 if ( place.isValid() && de != det_world ) {
1522 chain.insert(chain.end(), place.volIDs().begin(), place.volIDs().end());
1523 }
1524 if ( use_elt ) {
1525 if ( !sensitive_only || 0 != de.volumeID() ) {
1526 char sens = place.isValid() && place.volume().isSensitive() ? 'S' : ' ';
1527 switch( flag ) {
1528 case 0:
1529 ++count;
1530 if ( de.placement() == de.idealPlacement() ) {
1531 std::snprintf(fmt, sizeof(fmt), "%03d %%-%ds %%s NumDau:%%d VolID:%%08X Place:%%p %%c", level+1, 2*level+1);
1532 printout(INFO, "DetectorDump", fmt, "", de.path().c_str(), int(children.size()),
1533 (unsigned long)de.volumeID(), (void*)place.ptr(), sens);
1534 break;
1535 }
1536 std::snprintf(fmt, sizeof(fmt), "%03d %%-%ds %%s NumDau:%%d VolID:%%08X Place:%%p [ideal:%%p aligned:%%p] %%c",
1537 level+1, 2*level+1);
1538 printout(INFO, "DetectorDump", fmt, "", de.path().c_str(), int(children.size()),
1539 (unsigned long)de.volumeID(), (void*)de.idealPlacement().ptr(),
1540 (void*)place.ptr(), sens);
1541 break;
1542 case 1:
1543 ++count;
1544 std::snprintf(fmt, sizeof(fmt), "%03d %%-%ds Detector: %%s NumDau:%%d VolID:%%p", level+1, 2*level+1);
1545 printout(INFO, "DetectorDump", fmt, "", de.path().c_str(), int(children.size()), (void*)de.volumeID());
1546 if ( de.placement() == de.idealPlacement() ) {
1547 std::snprintf(fmt, sizeof(fmt), "%03d %%-%ds Placement: %%s %%c", level+1, 2*level+3);
1548 printout(INFO,"DetectorDump",fmt,"", de.placementPath().c_str(), sens);
1549 break;
1550 }
1551 std::snprintf(fmt,sizeof(fmt), "%03d %%-%ds Placement: %%s [ideal:%%p aligned:%%p] %%c",
1552 level+1,2*level+3);
1553 printout(INFO,"DetectorDump",fmt,"", de.placementPath().c_str(),
1554 (void*)de.idealPlacement().ptr(), (void*)place.ptr(), sens);
1555 break;
1556 default:
1557 break;
1558 }
1559 if ( (dump_materials || dump_shapes) && place.isValid() ) {
1560 Volume vol = place.volume();
1561 Material mat = vol.material();
1562 std::snprintf(fmt,sizeof(fmt), "%03d %%-%ds Material: %%-12s Shape: %%s", level+1,2*level+3);
1563 printout(INFO,"DetectorDump",fmt,"", mat.name(), toStringSolid(vol->GetShape()).c_str());
1564 }
1565 if ( dump_positions && place.isValid() ) {
1566 Position pos = place.position();
1567 Box box = place.volume().solid();
1568 double loc[3] = {0,0,0}, world[3] = {0,0,0};
1569 TGeoHMatrix tr = de.nominal().worldTransformation();
1570 tr.LocalToMaster(loc, world);
1571 std::snprintf(fmt,sizeof(fmt), "%03d %%-%ds BBox: (%%9.4f,%%9.4f,%%9.4f) [cm]", level+1,2*level+3);
1572 printout(INFO,"DetectorDump",fmt,"", box.x(), box.y(), box.z());
1573 std::snprintf(fmt,sizeof(fmt), "%03d %%-%ds Position: (%%9.4f,%%9.4f,%%9.4f) [cm] w/r to mother", level+1,2*level+3);
1574 printout(INFO,"DetectorDump",fmt,"", pos.X(), pos.Y(), pos.Z());
1575 std::snprintf(fmt,sizeof(fmt), "%03d %%-%ds Position: (%%9.4f,%%9.4f,%%9.4f) [cm] w/r to world", level+1,2*level+3);
1576 printout(INFO,"DetectorDump",fmt,"", world[0], world[1], world[2]);
1577 }
1578 if ( dump_volids && !place.volIDs().empty() ) {
1579 std::stringstream log;
1580 log << " VID:";
1581 for( const auto& i : chain )
1582 log << " " << i.first << ':' << std::dec << std::setw(2) << i.second;
1583 if ( id_desc.isValid() ) {
1584 log << " (encoded:0x" << std::setfill('0') << std::setw(8) << std::hex
1585 << id_desc.encode(chain)
1586 << std::setfill(' ') << std::dec << ") ";
1587 }
1588 std::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s", level+1, 2*level+1);
1589 printout(INFO,"DetectorDump", fmt, "", log.str().c_str());
1590 }
1591 }
1592 }
1593 for ( const auto& c : children ) {
1594 validate_id_descriptor(c.second, id_desc);
1595 dump(c.second, level+1, id_desc, chain);
1596 }
1597 return 1;
1598 }
1599 };
1600 VolIDs chain;
1601 IDDescriptor id_descriptor;
1602 Actor actor(description);
1603 actor.parse_args(argc, argv);
1604 return actor.dump(description.world(), 0, id_descriptor, std::move(chain));
1605 }
1606 DECLARE_APPLY(DD4hep_DetectorDump,dump_detelement_tree<0>)
1607 DECLARE_APPLY(DD4hep_DetectorVolumeDump,dump_detelement_tree<1>)
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617 static long detelement_cache(Detector& description, int argc, char** argv) {
1618 struct Actor {
1619 long cache(DetElement de) {
1620 const DetElement::Children& c = de.children();
1621 de.nominal().worldTransformation();
1622 de.nominal().detectorTransformation();
1623 de.placementPath();
1624 de.path();
1625 for( const auto& i : c ) cache(i.second);
1626 return 1;
1627 }
1628 } actor;
1629 std::string detector = "/world";
1630 for(int i = 0; i < argc && argv[i]; ++i) {
1631 if ( 0 == ::strncmp("-detector",argv[i],4) )
1632 detector = argv[++i];
1633 else if ( 0 == ::strncmp("--detector",argv[i],5) )
1634 detector = argv[++i];
1635 else {
1636 std::cout <<
1637 "Usage: -plugin DD4hep_DetElementCache -arg [-arg] \n\n"
1638 " Fill cache with transformation information in DetElements. \n\n"
1639 " -detector <string> Top level DetElement path. Default: '/world'\n"
1640 " --detector <string> dto. \n"
1641 " -help Print this help. \n"
1642 " Arguments given: " << arguments(argc,argv) << std::endl << std::flush;
1643 ::exit(EINVAL);
1644 }
1645 }
1646 DetElement element = description.world();
1647 if ( detector != "/world" ) {
1648 element = detail::tools::findElement(description, detector);
1649 if ( !element.isValid() ) {
1650 except("VolumeDump","+++ Invalid DetElement path: %s", detector.c_str());
1651 }
1652 }
1653 return actor.cache(element);
1654 }
1655 DECLARE_APPLY(DD4hep_DetElementCache,detelement_cache)
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665 #include "../GeometryTreeDump.h"
1666 static long exec_GeometryTreeDump(Detector& description, int, char** ) {
1667 GeometryTreeDump dmp;
1668 dmp.create(description.world());
1669 return 1;
1670 }
1671 DECLARE_APPLY(DD4hep_GeometryTreeDump,exec_GeometryTreeDump)
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681 static long detectortype_cache(Detector& description, int argc, char** argv) {
1682 std::vector<std::string> types;
1683 for(int i = 0; i < argc && argv[i]; ++i) {
1684 if ( 0 == ::strncmp("-type",argv[i],4) )
1685 types.push_back(argv[++i]);
1686 else if ( 0 == ::strncmp("--type",argv[i],4) )
1687 types.push_back(argv[++i]);
1688 else {
1689 std::cout <<
1690 "Usage: DD4hep_DetectorTypes -type <type> -arg [-arg] \n"
1691 " Dump detector types from detector description. \n\n"
1692 " -type <string> Add new type to be listed. Multiple possible. \n"
1693 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
1694 ::exit(EINVAL);
1695 }
1696 }
1697 if ( types.empty() ) {
1698 types = description.detectorTypes();
1699 }
1700 printout(INFO,"DetectorTypes","Detector type dump: %ld types:", long(types.size()));
1701 for( const auto& type : types ) {
1702 const std::vector<DetElement>& detectors = description.detectors(type);
1703 printout(INFO,"DetectorTypes","\t --> %ld %s detectors:",long(detectors.size()), type.c_str());
1704 for( const auto& d : detectors ) {
1705 printout(INFO,"DetectorTypes","\t\t %-16s --> %s [%s]",type.c_str(),d.name(),d.type().c_str());
1706 }
1707 }
1708 return 1;
1709 }
1710 DECLARE_APPLY(DD4hep_DetectorTypes,detectortype_cache)
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720 #include <DD4hep/SurfaceInstaller.h>
1721 typedef SurfaceInstaller TestSurfacesPlugin;
1722 DECLARE_SURFACE_INSTALLER(TestSurfaces,TestSurfacesPlugin)
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732 #include <DD4hep/PluginTester.h>
1733 static long install_plugin_tester(Detector& description, int , char** ) {
1734 PluginTester* test = description.extension<PluginTester>(false);
1735 if ( !test ) {
1736 description.addExtension<PluginTester>(new PluginTester());
1737 printout(INFO,"PluginTester",
1738 "+++ Successfully installed PluginTester instance to Detector.");
1739 }
1740 return 1;
1741 }
1742 DECLARE_APPLY(DD4hep_PluginTester,install_plugin_tester)
1743