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