15 #define DD4HEP_MUST_USE_DETECTORIMP_H
33 #include <TInterpreter.h>
34 #include <TGeoElement.h>
35 #include <TGeoManager.h>
36 #include <TGeoVolume.h>
40 #include <TGDMLMatrix.h>
53 struct ProcessorArgs {
55 int start = 0, end = 0, argc = 0, count=0;
56 std::vector<char*> argv;
57 ProcessorArgs(
int ac,
char** av) {
58 for(
int i=0; i<ac; ++i) {
59 if ( 0 == ::strncmp(av[i],
"-processor",6) ) {
64 ++argc; ++count; end = i;
65 if ( 0 == ::strncmp(av[i],
"-end-processor",6) ) {
66 argv.emplace_back(av[i]);
69 else if ( 0 == ::strncmp(av[i],
"-end-plugin",4) ) {
70 argv.emplace_back((
char*)
"-end-processor");
73 else if ( 0 == ::strncmp(av[i],
"-plugin",4) ) {
74 argv.emplace_back((
char*)
"-end-processor");
77 argv.emplace_back(av[i]);
92 static long dummy_plugin(
Detector& ,
int,
char**) {
105 static void* create_description_instance(
const char* ) {
119 static long display(
Detector& description,
int argc,
char** argv) {
120 TGeoManager& mgr = description.
manager();
121 int vislevel = 6, visopt = 1;
122 std::string detector =
"/world";
123 const char* opt =
"ogl";
124 for(
int i = 0; i < argc && argv[i]; ++i ) {
125 if ( 0 == ::strncmp(
"-option",argv[i],4) )
127 else if ( 0 == ::strncmp(
"-level",argv[i],4) )
128 vislevel = ::atol(argv[++i]);
129 else if ( 0 == ::strncmp(
"-visopt",argv[i],4) )
130 visopt = ::atol(argv[++i]);
131 else if ( 0 == ::strncmp(
"-detector",argv[i],4) )
132 detector = argv[++i];
135 "Usage: -plugin DD4hep_GeometryDisplay -arg [-arg] \n\n"
136 " Invoke the ROOT geometry display using the factory mechanism. \n\n"
137 " -detector <string> Top level DetElement path. Default: '/world' \n"
138 " -option <string> ROOT Draw option. Default: 'ogl' \n"
139 " -level <number> Visualization level [TGeoManager::SetVisLevel] Default: 4 \n"
140 " -visopt <number> Visualization option [TGeoManager::SetVisOption] Default: 1\n"
141 " -load Only load the geometry. Do not invoke the display \n"
142 " -help Print this help output \n"
143 " Arguments given: " << arguments(argc,argv) << std::endl << std::flush;
147 mgr.SetVisLevel(vislevel);
148 mgr.SetVisOption(visopt);
149 TGeoVolume* vol = mgr.GetTopVolume();
150 if ( detector !=
"/world" ) {
153 except(
"DD4hep_GeometryDisplay",
"+++ Invalid DetElement path: %s",detector.c_str());
156 except(
"DD4hep_GeometryDisplay",
"+++ Invalid DetElement placement: %s",detector.c_str());
176 static long run_function(
Detector&,
int argc,
char** argv) {
177 std::string lib, func;
178 std::vector<char*> args;
179 for(
int i = 0; i < argc && argv[i]; ++i) {
180 if ( 0 == ::strncmp(
"-library",argv[i],4) )
182 else if ( 0 == ::strncmp(
"-function",argv[i],4) )
185 args.emplace_back(argv[i]);
187 if ( lib.empty() || func.empty() ) {
189 "Usage: -plugin DD4hep_Function -arg [-arg] \n\n"
190 " Execute a function without arguments inside a library. \n\n"
191 " -library <string> Library to be loaded \n"
192 " -function <string> name of the entry point to be executed. \n"
193 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
196 Func_t f = gSystem->DynFindSymbol(
"*",func.c_str());
199 ret = gSystem->Load(lib.c_str());
201 except(
"DD4hep_Function",
"+++ Failed to load library: %s",lib.c_str());
203 f = gSystem->DynFindSymbol(
"*",func.c_str());
205 except(
"DD4hep_Function",
"+++ Failed to find function %s in library: %s",
206 func.c_str(),lib.c_str());
209 typedef int (*call_t)(int,
char**);
210 call_t ff = (call_t)f;
211 ret = (*ff)(args.size(),&args[0]);
225 if ( 0 == gApplication ) {
226 std::pair<int, char**> a(argc,argv);
227 gApplication =
new TRint(
"DD4hepRint", &a.first, a.second);
228 printout(INFO,
"DD4hepRint",
"++ Created ROOT interpreter instance for DD4hepUI.");
230 for(
int i=0; i<argc; ++i) {
231 printout(INFO,
"DD4hepRint",
"Excecute[%d]: %s", i, argv[i]);
232 gInterpreter->ProcessLine(argv[i]);
234 if ( !gApplication->IsRunning() ) {
253 static long root_ui(
Detector& description,
int ,
char** ) {
255 std::snprintf(cmd,
sizeof(cmd),
256 "dd4hep::detail::DD4hepUI* gDD4hepUI = new "
257 "dd4hep::detail::DD4hepUI(*(dd4hep::Detector*)%p);",
258 (
void*)&description);
259 gInterpreter->ProcessLine(cmd);
260 printout(ALWAYS,
"DD4hepUI",
261 "Use the ROOT interpreter variable gDD4hepUI "
262 "to interact with the detector description.");
276 static long root_dump_gdml_tables(
Detector& description,
int ,
char** ) {
277 size_t num_tables = 0;
278 size_t num_elements = 0;
279 const TObjArray* c = description.
manager().GetListOfGDMLMatrices();
280 TObjArrayIter arr(c);
281 printout(INFO,
"Dump_GDMLTables",
"+++ Dumping known GDML tables from TGeoManager.");
282 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
283 TGDMLMatrix* gdmlMat = (TGDMLMatrix*)i;
284 num_elements += (gdmlMat->GetRows()*gdmlMat->GetCols());
288 printout(INFO,
"Dump_GDMLTables",
289 "+++ Successfully dumped %ld GDML tables with %ld elements.",
290 num_tables, num_elements);
304 static long root_dump_optical_surfaces(
Detector& description,
int ,
char** ) {
305 size_t num_surfaces = 0;
306 printout(ALWAYS,
"",
"");
307 const TObjArray* c = description.
manager().GetListOfOpticalSurfaces();
308 TObjArrayIter arr(c);
309 printout(ALWAYS,
"Dump_OpticalSurfaces",
"+++ Dumping known Optical Surfaces from TGeoManager.");
310 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
311 TGeoOpticalSurface* optSurt = (TGeoOpticalSurface*)i;
315 printout(ALWAYS,
"Dump_OpticalSurfaces",
316 "+++ Successfully dumped %ld Optical surfaces.",num_surfaces);
319 DECLARE_APPLY(DD4hep_Dump_OpticalSurfaces,root_dump_optical_surfaces)
330 static long root_dump_skin_surfaces(
Detector& description,
int ,
char** ) {
331 size_t num_surfaces = 0;
332 printout(ALWAYS,
"",
"");
333 const TObjArray* c = description.
manager().GetListOfSkinSurfaces();
334 TObjArrayIter arr(c);
335 printout(ALWAYS,
"Dump_SkinSurfaces",
"+++ Dumping known Skin Surfaces from TGeoManager.");
336 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
337 TGeoSkinSurface* skinSurf = (TGeoSkinSurface*)i;
341 printout(ALWAYS,
"Dump_SkinSurfaces",
342 "+++ Successfully dumped %ld Skin surfaces.",num_surfaces);
345 DECLARE_APPLY(DD4hep_Dump_SkinSurfaces,root_dump_skin_surfaces)
356 static long root_dump_border_surfaces(
Detector& description,
int ,
char** ) {
357 size_t num_surfaces = 0;
358 printout(ALWAYS,
"",
"");
359 const TObjArray* c = description.
manager().GetListOfBorderSurfaces();
360 TObjArrayIter arr(c);
361 printout(ALWAYS,
"Dump_BorderSurfaces",
"+++ Dumping known Border Surfaces from TGeoManager.");
362 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
363 TGeoBorderSurface* bordSurt = (TGeoBorderSurface*)i;
367 printout(ALWAYS,
"Dump_BorderSurfaces",
368 "+++ Successfully dumped %ld Border surfaces.",num_surfaces);
371 DECLARE_APPLY(DD4hep_Dump_BorderSurfaces,root_dump_border_surfaces)
383 static long root_elements(
Detector& description,
int argc,
char** argv) {
392 struct ElementPrint {
394 ElementPrint() =
default;
396 virtual ~ElementPrint() =
default;
398 virtual void operator()(TGeoElement* elt) { elt->Print(); }
400 virtual void operator()(TGeoIsotope* iso) { iso->Print(); }
409 struct ElementPrintXML :
public ElementPrint {
413 ElementPrintXML(elt_h r) : root(r) {}
415 virtual ~ElementPrintXML() {}
417 virtual void operator()(TGeoElement* element) {
418 elt_h elt = root.addChild(
_U(element));
419 elt.setAttr(
_U(Z),element->Z());
420 elt.setAttr(
_U(N),element->N());
421 elt.setAttr(
_U(formula),element->GetName());
422 elt.setAttr(
_U(name),element->GetName());
423 elt_h atom = elt.addChild(
_U(atom));
424 atom.setAttr(
_U(type),
"A");
425 atom.setAttr(
_U(unit),
"g/mole");
426 atom.setAttr(
_U(value),element->A());
429 virtual void operator()(TGeoIsotope* isotope) {
430 elt_h iso = root.addChild(
_U(isotope));
431 iso.setAttr(
_U(Z),isotope->GetZ());
432 iso.setAttr(
_U(N),isotope->GetN());
433 iso.setAttr(
_U(formula),isotope->GetName());
434 iso.setAttr(
_U(name),isotope->GetName());
435 elt_h atom = iso.addChild(
_U(atom));
436 atom.setAttr(
_U(type),
"A");
437 atom.setAttr(
_U(unit),
"g/mole");
438 atom.setAttr(
_U(value),isotope->GetA());
442 std::string type =
"text", output =
"";
443 for(
int i=0; i<argc; ++i) {
444 if ( argv[i][0] ==
'-' ) {
445 char c = ::tolower(argv[i][1]);
446 if ( c ==
't' && i+1<argc ) type = argv[++i];
447 else if ( c ==
'o' && i+1<argc ) output = argv[++i];
449 ::printf(
"DD4hep_ElementTable -opt [-opt] \n"
450 " -type <string> Output format: text or xml \n"
451 " -output <file-name> Output file specifier (xml only) \n"
461 if ( type ==
"xml" ) {
462 const char comment[] =
"\n"
463 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
464 " ++++ Generic detector description in C++ ++++\n"
465 " ++++ dd4hep Detector description generator. ++++\n"
471 " ++++ Table of elements as defined in ROOT: " ROOT_RELEASE
" ++++\n"
473 " ++++ M.Frank CERN/LHCb ++++\n"
474 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n ";
475 doc = docH.
create(
"materials", comment);
476 element = doc.
root();
479 ?
new ElementPrintXML(element)
480 :
new ElementPrint());
481 TGeoElementTable* table = description.
manager().GetElementTable();
482 for(Int_t i=0, n=table->GetNelements(); i < n; ++i)
483 (*printer)(table->GetElement(i));
485 for(Int_t i=0, n=table->GetNelements(); i < n; ++i) {
486 TGeoElement* elt = table->GetElement(i);
487 Int_t niso = elt->GetNisotopes();
489 for(Int_t j=0; j < niso; ++j)
490 (*printer)(elt->GetIsotope(j));
511 static long root_materials(
Detector& description,
int argc,
char** argv) {
521 struct MaterialPrint {
528 MaterialPrint(
Detector& desc) : description(desc) {}
530 virtual ~MaterialPrint() =
default;
532 virtual elt_h print(TGeoMaterial* mat) {
533 const char* st =
"Undefined";
534 switch( mat->GetState() ) {
535 case TGeoMaterial::kMatStateSolid: st =
"solid";
break;
536 case TGeoMaterial::kMatStateLiquid: st =
"liquid";
break;
537 case TGeoMaterial::kMatStateGas: st =
"gas";
break;
538 case TGeoMaterial::kMatStateUndefined:
539 default: st =
"Undefined";
break;
541 ::printf(
"%-32s %-8s\n", mat->GetName(), mat->IsMixture() ?
"Mixture" :
"Material");
542 ::printf(
" Aeff=%7.3f Zeff=%7.4f rho=%8.3f [g/mole] radlen=%8.3g [cm] intlen=%8.3g [cm] index=%3d\n",
543 mat->GetA(), mat->GetZ(), mat->GetDensity(),
544 mat->GetRadLen(), mat->GetIntLen(), mat->GetIndex());
545 ::printf(
" Temp=%.3g [Kelvin] Pressure=%.5g [hPa] state=%s\n",
546 mat->GetTemperature(), mat->GetPressure()/dd4hep::pascal/100.0, st);
550 virtual void print(elt_h, TGeoElement* elt,
double frac) {
551 ::printf(
" %-6s Fraction: %7.3f Z=%3d A=%6.2f N=%3d Neff=%6.2f\n",
552 elt->GetName(), frac, elt->Z(), elt->A(), elt->N(), elt->Neff());
555 virtual void printProperty(elt_h,
TNamed* prop, TGDMLMatrix* matrix) {
557 ::printf(
" Property: %-20s [%ld x %ld] --> %s\n",
558 prop->GetName(),
long(matrix->GetRows()),
long(matrix->GetCols()), prop->GetTitle());
560 ::printf(
" Property: %-20s [ERROR: NO TABLE!] --> %s\n",
561 prop->GetName(), prop->GetTitle());
563 virtual void operator()(TGeoMaterial* mat) {
564 Double_t*
mix = mat->IsMixture() ? ((TGeoMixture*)mat)->GetWmixt() : 0;
565 elt_h mh = print(mat);
566 for(
int n=mat->GetNelements(), i=0; i<n; ++i ) {
567 TGeoElement* elt = mat->GetElement(i);
568 print(mh, elt,
mix ?
mix[i] : 1);
570 TListIter mat_iter(&mat->GetProperties());
571 for(
TObject* i = mat_iter.Next(); i; i=mat_iter.Next() ) {
572 printProperty(mh, (
TNamed*)i, description.
manager().GetGDMLMatrix(i->GetTitle()));
582 struct MaterialPrintXML :
public MaterialPrint {
584 MaterialPrintXML(elt_h elt,
Detector& desc) : MaterialPrint(desc), root(elt) {}
585 virtual ~MaterialPrintXML() {}
586 virtual elt_h print(TGeoMaterial* mat) {
587 elt_h elt = root.addChild(
_U(material));
588 elt.setAttr(
_U(name),mat->GetName());
589 if ( ::strlen(mat->GetTitle())>0 ) {
590 elt.setAttr(
_U(formula),mat->GetTitle());
592 else if ( mat->GetNelements() == 1 ) {
593 elt.setAttr(
_U(formula),mat->GetElement(0)->GetName());
596 elt_h RL = elt.addChild(
_U(RL));
597 RL.setAttr(
_U(type),
"X0");
598 RL.setAttr(
_U(value), mat->GetRadLen());
599 RL.setAttr(
_U(unit),
"cm");
600 elt_h NIL = elt.addChild(
_U(NIL));
601 NIL.setAttr(
_U(type),
"lambda");
602 NIL.setAttr(
_U(value), mat->GetIntLen());
603 NIL.setAttr(
_U(unit),
"cm");
606 elt_h D = elt.addChild(
_U(D));
607 D.setAttr(
_U(type),
"density");
608 D.setAttr(
_U(value), mat->GetDensity());
609 D.setAttr(
_U(unit),
"g/cm3");
611 elt_h T = elt.addChild(
_U(T));
612 T.setAttr(
_U(type),
"temperature");
613 T.setAttr(
_U(value), mat->GetTemperature());
614 T.setAttr(
_U(unit),
"kelvin");
617 elt_h P = elt.addChild(
_U(P));
618 P.setAttr(
_U(type),
"pressure");
619 P.setAttr(
_U(value), mat->GetPressure());
620 P.setAttr(
_U(unit),
"pascal");
624 virtual void print(elt_h mat, TGeoElement* element,
double frac) {
625 elt_h elt = mat.addChild(
_U(composite));
626 elt.setAttr(
_U(n),frac);
627 elt.setAttr(
_U(ref),element->GetName());
629 virtual void printProperty(elt_h mat,
TNamed* prop, TGDMLMatrix* ) {
630 elt_h elt = mat.addChild(
_U(property));
631 elt.setAttr(
_U(name),prop->GetName());
632 elt.setAttr(
_U(ref), prop->GetTitle());
636 std::string type =
"text", output =
"", name =
"";
637 for(
int i=0; i<argc; ++i) {
638 if ( argv[i][0] ==
'-' ) {
639 char c = ::tolower(argv[i][1]);
640 if ( c ==
't' && i+1<argc ) type = argv[++i];
641 else if ( c ==
'n' && i+1<argc ) name = argv[++i];
642 else if ( c ==
'o' && i+1<argc ) output = argv[++i];
644 ::printf(
"DD4hep_MaterialTable -opt [-opt] \n"
645 " -type <string> Output format: text or xml \n"
646 " -output <file-name> Output file specifier (xml only) \n"
656 if ( type ==
"xml" ) {
657 const char comment[] =
"\n"
658 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
659 " ++++ Generic detector description in C++ ++++\n"
660 " ++++ dd4hep Detector description generator. ++++\n"
666 " ++++ Table of elements as defined in ROOT: " ROOT_RELEASE
" ++++\n"
668 " ++++ M.Frank CERN/LHCb ++++\n"
669 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n ";
670 doc = docH.
create(
"materials", comment);
671 element = doc.
root();
674 ?
new MaterialPrintXML(element, description)
675 :
new MaterialPrint(description));
677 TList* mats = description.
manager().GetListOfMaterials();
679 while( (obj=iter->Next()) != 0 ) {
680 TGeoMaterial* mat = (TGeoMaterial*)obj;
681 if ( name.empty() || name == mat->GetName() )
705 static long load_compact(
Detector& description,
int argc,
char** argv) {
708 std::string input = argv[0];
711 printout(INFO,
"CompactLoader",
"+++ Processing compact file: %s with flag %s",
712 input.c_str(), argv[1]);
716 printout(INFO,
"CompactLoader",
"+++ Processing compact file: %s",input.c_str());
739 static long load_xml(
Detector& description,
int argc,
char** argv) {
742 std::string input = argv[0];
745 printout(INFO,
"XMLLoader",
"+++ Processing XML file: %s with flag %s",
746 input.c_str(), argv[1]);
747 description.
fromXML(input, type);
750 printout(INFO,
"XMLLoader",
"+++ Processing XML file: %s",input.c_str());
773 static long process_xml_doc(
Detector& description,
int argc,
char** argv) {
778 xml::XmlElement* h = (xml::XmlElement*)argv[0];
783 printout(INFO,
"XMLLoader",
"+++ Processing XML element: %s with flag %s",
784 input.tag().c_str(), argv[1]);
789 except(
"DD4hepXMLProcessor",
790 "++ The passed reference to the parsed XML document is invalid.");
805 static long load_volmgr(
Detector& description,
int,
char**) {
806 printout(INFO,
"DD4hepVolumeManager",
"**** running plugin DD4hepVolumeManager ! " );
811 printout(INFO,
"VolumeManager",
"+++ Volume manager populated and loaded.");
816 except(
"DD4hep_VolumeManager",
"Exception: %s\n %s", e.what(),
817 "dd4hep: while programming VolumeManager. Are your volIDs correct?");
820 except(
"DD4hep_VolumeManager",
821 "UNKNOWN exception while programming VolumeManager. Are your volIDs correct?");
836 static long dump_geometry2root(
Detector& description,
int argc,
char** argv) {
839 for(
int i = 0; i < argc && argv[i]; ++i) {
840 if ( 0 == ::strncmp(
"-output",argv[i],4) )
843 if ( output.empty() ) {
845 "Usage: -plugin DD4hep_Geometry2ROOT -arg [-arg] \n\n"
846 " Output DD4hep detector description object to a ROOT file. \n\n"
847 " -output <string> Output file name. \n"
848 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
851 printout(INFO,
"Geometry2ROOT",
"+++ Dump geometry to root file:%s",output.c_str());
857 printout(ERROR,
"Geometry2ROOT",
"+++ No output file name given.");
870 static long load_geometryFromroot(
Detector& description,
int argc,
char** argv) {
872 std::string input = argv[0];
873 for(
int i = 0; i < argc && argv[i]; ++i) {
874 if ( 0 == ::strncmp(
"-input",argv[i],4) )
877 if ( input.empty() ) {
879 "Usage: DD4hep_RootLoader -arg [-arg] \n\n"
880 " Load DD4hep detector description from ROOT file to memory. \n\n"
881 " -input <string> Input file name. \n"
882 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
885 printout(INFO,
"DD4hepRootLoader",
"+++ Read geometry from root file:%s",input.c_str());
890 printout(ERROR,
"DD4hep_RootLoader",
"+++ No input file name given.");
903 static long dump_geometry2tgeo(
Detector& description,
int argc,
char** argv) {
905 std::string output( argc == 1 ? argv[0] :
"" );
906 printout(INFO,
"Geometry2TGeo",
"+++ output: %d %s", argc, output.c_str());
907 for(
int i = 0; i < argc && argv[i]; ++i) {
908 if ( 0 == ::strncmp(
"-output",argv[i],4) )
911 if ( output.empty() ) {
913 "Usage: -plugin <name> -arg [-arg] \n"
914 " Output TGeo information to a ROOT file. \n\n"
915 " name: factory name DD4hepGeometry2TGeo \n"
916 " -output <string> Output file name. \n"
917 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
920 printout(INFO,
"Geometry2TGeo",
"+++ Dump geometry to root file:%s",output.c_str());
921 if ( description.
manager().Export(output.c_str()) > 1 ) {
925 printout(ERROR,
"Geometry2TGeo",
"+++ No output file name given.");
939 static long check_detectors(
Detector& description,
int ,
char** ) {
941 auto ret = check.checkDetectors();
942 return ret.first > 0 && ret.second == 0 ? 1 : 0;
954 static long check_sensitives(
Detector& description,
int ,
char** ) {
956 auto ret = check.checkSensitives();
957 return ret.first > 0 && ret.second == 0 ? 1 : 0;
969 static long check_segmentations(
Detector& description,
int ,
char** ) {
971 auto ret = check.checkSegmentations();
972 return ret.first > 0 && ret.second == 0 ? 1 : 0;
984 static long check_readouts(
Detector& description,
int ,
char** ) {
986 auto ret = check.checkReadouts();
987 return ret.first > 0 && ret.second == 0 ? 1 : 0;
999 static long check_idspecs(
Detector& description,
int ,
char** ) {
1001 auto ret = check.checkIdSpecs();
1002 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1014 static long check_volumemanager(
Detector& description,
int ,
char** ) {
1016 auto ret = check.checkVolManager();
1017 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1019 DECLARE_APPLY(DD4hep_CheckVolumeManager,check_volumemanager)
1029 static long check_nominals(
Detector& description,
int ,
char** ) {
1031 auto ret = check.checkNominals();
1032 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1044 static long dump_volume_tree(
Detector& description,
int argc,
char** argv) {
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;
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]);
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 ) {
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;
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));
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);
1122 if ( m_printShapes ) {
1123 printout(ALWAYS,
"VolumeDump",
"+++ Checked %ld shapes.", m_numShapes);
1126 for(
const auto& t : top_counts) {
1128 printout(ALWAYS,
"VolumeDump",
1129 "+++ Top node: %-32s %8ld placements.",t.first.c_str(),t.second);
1134 long dump(std::string prefix, TGeoNode* ideal, TGeoNode* aligned,
int level,
PlacedVolume::VolIDs volids) {
1136 std::stringstream log;
1138 bool sensitive =
false;
1139 std::string opt_info, pref = std::move(prefix);
1141 if ( level >= m_printMaxLevel ) {
1147 else if ( level == 1 ) {
1148 currTop = ideal->GetVolume()->GetName();
1149 ++top_counts[currTop];
1151 else if ( level > 1 ) {
1152 ++top_counts[currTop];
1155 if ( m_printPathes ) {
1157 pref += aligned->GetName();
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);
1167 std::snprintf(fmt,
sizeof(fmt),
"Ideal:%p MotherVol:%p",
1168 (
void*)ideal, (
void*)mother);
1172 if ( m_printVolIDs && ideal && ideal->GetMotherVolume() ) {
1174 if ( !vid.empty() ) {
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);
1182 if ( !vid.empty() || pv.volume().isSensitive() ) {
1187 log << std::hex <<
" (0x" << std::setfill(
'0') << std::setw(8)
1189 << std::setfill(
' ') << std::dec <<
") ";
1195 opt_info = log.str();
1199 if ( m_printVis && pv.volume().visAttributes().isValid() ) {
1200 log <<
" Vis:" << pv.volume().visAttributes().name();
1201 opt_info += log.str();
1204 TGeoVolume* volume = ideal ? ideal->GetVolume() : 0;
1205 if ( !m_printSensitivesOnly || (m_printSensitivesOnly && sensitive) ) {
1206 Volume vol = pv.volume();
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);
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);
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);
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);
1228 const auto* sh = volume ? volume->GetShape() :
nullptr;
1229 printout(INFO,
"VolumeDump",fmt,pref.c_str(),
"",
1232 sh ? sh->IsA()->GetName() :
"[Invalid Shape]",
1234 if ( sens ==
'S' ) ++m_numSensitive;
1236 if ( m_printMaterials ) {
1237 Volume vol = pv.volume();
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",
1244 if ( !ok ) ++m_numMaterialERR;
1245 printout(ok ? INFO : ERROR,
"VolumeDump", fmt,
1246 " ->",
"", mat.
name(), mat.
A(), mptr->GetA(), mat.
Z(), mptr->GetZ());
1249 if ( m_printShapes ) {
1250 log <<
"Shape: " <<
toStringSolid(pv.volume().solid()) <<
" \t";
1252 if ( m_printPositions ) {
1254 const double* trans = ideal->GetMatrix()->GetTranslation();
1255 std::snprintf(fmt,
sizeof(fmt),
"Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]);
1258 std::snprintf(fmt,
sizeof(fmt),
" <ERROR: INVALID Translation matrix> ");
1260 log << fmt <<
" \t";
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());
1266 for (Int_t idau = 0, ndau = aligned->GetNdaughters(); idau < ndau; ++idau) {
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);
1274 printout(ERROR,
"VolumeDump",
" <ERROR: INVALID IDEAL Translation matrix>: %s",aligned->GetName());
1285 if ( m_detector !=
"/world" ) {
1288 except(
"VolumeDump",
"+++ Invalid DetElement path: %s",m_detector.c_str());
1292 except(
"VolumeDump",
"+++ Invalid DetElement placement: %s",m_detector.c_str());
1298 except(
"VolumeDump",
"+++ Invalid placement verification for placement:%s",place.c_str());
1303 Actor actor(description, argc, argv);
1321 static int detelement_processor(
Detector& description,
int argc,
char** argv) {
1322 bool recursive =
true;
1323 ProcessorArgs args(argc, argv);
1325 std::unique_ptr<DetectorProcessor>
1326 proc(dd4hep::createProcessor<DetectorProcessor>(description, args.argc, &args.argv[0]));
1328 for(
int i=0; i<argc; ++i) {
1329 if ( i >= args.start && i <= args.end )
1331 else if ( 0 == ::strncmp(argv[i],
"-recursive",4) )
1333 else if ( 0 == ::strncmp(argv[i],
"-no-recursive",7) )
1335 else if ( 0 == ::strncmp(argv[i],
"-detector",4) ) {
1336 std::string path = argv[++i];
1338 if (
det.isValid() ) {
1341 except(
"DetElementProcessor",
1342 "++ The detector element path:%s is not part of this description!",
1346 except(
"DetElementProcessor",
"++ Unknown plugin argument: %s",argv[i]);
1351 DECLARE_APPLY(DD4hep_DetElementProcessor,detelement_processor)
1366 static int placed_volume_processor(
Detector& description,
int argc,
char** argv) {
1367 bool recursive =
true;
1369 ProcessorArgs args(argc, argv);
1370 std::unique_ptr<PlacedVolumeProcessor>
1371 proc(dd4hep::createProcessor<PlacedVolumeProcessor>(description, args.argc, &args.argv[0]));
1373 std::string path =
"/world";
1374 for(
int i=0; i<argc; ++i) {
1375 if ( i >= args.start && i <= args.end )
1377 else if ( 0 == ::strncmp(argv[i],
"-recursive",4) )
1379 else if ( 0 == ::strncmp(argv[i],
"--recursive",5) )
1381 else if ( 0 == ::strncmp(argv[i],
"-no-recursive",7) )
1383 else if ( 0 == ::strncmp(argv[i],
"--no-recursive",8) )
1385 else if ( 0 == ::strncmp(argv[i],
"-detector",4) )
1387 else if ( 0 == ::strncmp(argv[i],
"--detector",5) )
1390 except(
"PlacedVolumeProcessor",
"++ Unknown plugin argument: %s",argv[i]);
1393 if (
det.isValid() ) {
1394 pv =
det.placement();
1398 except(
"PlacedVolumeProcessor",
1399 "++ The detector element with path:%s has no valid placement!",
1402 except(
"PlacedVolumeProcessor",
1403 "++ The detector element path:%s is not part of this description!",
1407 DECLARE_APPLY(DD4hep_PlacedVolumeProcessor,placed_volume_processor)
1422 std::string path { };
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;
1435 det_world = descr.
world();
1439 printout(ALWAYS,
"DetectorDump",
"+++ Scanned a total of %ld elements.",count);
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]); }
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"
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"
1480 "\tArguments given: " << arguments(ac,av) << std::endl << std::flush;
1491 if ( dsc.
isValid() )
return dsc;
1493 for (Int_t idau = 0, ndau =
v->GetNdaughters(); idau < ndau; ++idau) {
1495 if ( dsc.
isValid() )
return dsc;
1509 bool use_elt = path.empty() || de.
path().find(path) != std::string::npos;
1511 if ( have_match < 0 && use_elt ) {
1515 use_elt &= ((level-have_match) <= analysis_level);
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());
1522 if ( place.
isValid() && de != det_world ) {
1526 if ( !sensitive_only || 0 != de.
volumeID() ) {
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);
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()),
1541 (
void*)place.
ptr(), sens);
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());
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);
1552 std::snprintf(fmt,
sizeof(fmt),
"%03d %%-%ds Placement: %%s [ideal:%%p aligned:%%p] %%c",
1554 printout(INFO,
"DetectorDump",fmt,
"", de.
placementPath().c_str(),
1560 if ( (dump_materials || dump_shapes) && place.
isValid() ) {
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());
1566 if ( dump_positions && place.
isValid() ) {
1569 double loc[3] = {0,0,0}, world[3] = {0,0,0};
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]);
1579 if ( dump_volids && !place.
volIDs().empty() ) {
1580 std::stringstream log;
1582 for(
const auto& i : chain )
1583 log <<
" " << i.first <<
':' << std::dec << std::setw(2) << i.second;
1585 log <<
" (encoded:0x" << std::setfill(
'0') << std::setw(8) << std::hex
1587 << std::setfill(
' ') << std::dec <<
") ";
1589 std::snprintf(fmt,
sizeof(fmt),
"%03d %%-%ds %%s", level+1, 2*level+1);
1590 printout(INFO,
"DetectorDump", fmt,
"", log.str().c_str());
1594 for (
const auto& c : children ) {
1595 validate_id_descriptor(c.second, id_desc);
1596 dump(c.second, level+1, id_desc, chain);
1603 Actor actor(description);
1604 actor.parse_args(argc, argv);
1605 return actor.dump(description.world(), 0, id_descriptor, std::move(chain));
1608 DECLARE_APPLY(DD4hep_DetectorVolumeDump,dump_detelement_tree<1>)
1618 static long detelement_cache(
Detector& description,
int argc,
char** argv) {
1626 for(
const auto& i : c ) cache(i.second);
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];
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;
1648 if ( detector !=
"/world" ) {
1651 except(
"VolumeDump",
"+++ Invalid DetElement path: %s", detector.c_str());
1654 return actor.cache(element);
1666 #include "../GeometryTreeDump.h"
1667 static long exec_GeometryTreeDump(
Detector& description,
int,
char** ) {
1672 DECLARE_APPLY(DD4hep_GeometryTreeDump,exec_GeometryTreeDump)
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]);
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;
1698 if ( types.empty() ) {
1701 printout(INFO,
"DetectorTypes",
"Detector type dump: %ld types:",
long(types.size()));
1702 for(
const auto& type : types ) {
1704 printout(INFO,
"DetectorTypes",
"\t --> %ld %s detectors:",
long(
detectors.size()), type.c_str());
1706 printout(INFO,
"DetectorTypes",
"\t\t %-16s --> %s [%s]",type.c_str(),d.name(),d.type().c_str());
1721 #include <DD4hep/SurfaceInstaller.h>
1733 #include <DD4hep/PluginTester.h>
1734 static long install_plugin_tester(
Detector& description,
int ,
char** ) {
1738 printout(INFO,
"PluginTester",
1739 "+++ Successfully installed PluginTester instance to Detector.");