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>
52 struct ProcessorArgs {
54 int start = 0, end = 0, argc = 0, count=0;
55 std::vector<char*> argv;
56 ProcessorArgs(
int ac,
char** av) {
57 for(
int i=0; i<ac; ++i) {
58 if ( 0 == ::strncmp(av[i],
"-processor",6) ) {
63 ++argc; ++count; end = i;
64 if ( 0 == ::strncmp(av[i],
"-end-processor",6) ) {
65 argv.emplace_back(av[i]);
68 else if ( 0 == ::strncmp(av[i],
"-end-plugin",4) ) {
69 argv.emplace_back((
char*)
"-end-processor");
72 else if ( 0 == ::strncmp(av[i],
"-plugin",4) ) {
73 argv.emplace_back((
char*)
"-end-processor");
76 argv.emplace_back(av[i]);
91 static long dummy_plugin(
Detector& ,
int,
char**) {
104 static void* create_description_instance(
const char* ) {
118 static long display(
Detector& description,
int argc,
char** argv) {
119 TGeoManager& mgr = description.
manager();
120 int vislevel = 6, visopt = 1;
121 std::string detector =
"/world";
122 const char* opt =
"ogl";
123 for(
int i = 0; i < argc && argv[i]; ++i ) {
124 if ( 0 == ::strncmp(
"-option",argv[i],4) )
126 else if ( 0 == ::strncmp(
"-level",argv[i],4) )
127 vislevel = ::atol(argv[++i]);
128 else if ( 0 == ::strncmp(
"-visopt",argv[i],4) )
129 visopt = ::atol(argv[++i]);
130 else if ( 0 == ::strncmp(
"-detector",argv[i],4) )
131 detector = argv[++i];
134 "Usage: -plugin DD4hep_GeometryDisplay -arg [-arg] \n\n"
135 " Invoke the ROOT geometry display using the factory mechanism. \n\n"
136 " -detector <string> Top level DetElement path. Default: '/world' \n"
137 " -option <string> ROOT Draw option. Default: 'ogl' \n"
138 " -level <number> Visualization level [TGeoManager::SetVisLevel] Default: 4 \n"
139 " -visopt <number> Visualization option [TGeoManager::SetVisOption] Default: 1\n"
140 " -load Only load the geometry. Do not invoke the display \n"
141 " -help Print this help output \n"
142 " Arguments given: " << arguments(argc,argv) << std::endl << std::flush;
146 mgr.SetVisLevel(vislevel);
147 mgr.SetVisOption(visopt);
148 TGeoVolume* vol = mgr.GetTopVolume();
149 if ( detector !=
"/world" ) {
152 except(
"DD4hep_GeometryDisplay",
"+++ Invalid DetElement path: %s",detector.c_str());
155 except(
"DD4hep_GeometryDisplay",
"+++ Invalid DetElement placement: %s",detector.c_str());
175 static long run_function(
Detector&,
int argc,
char** argv) {
176 std::string lib, func;
177 std::vector<char*> args;
178 for(
int i = 0; i < argc && argv[i]; ++i) {
179 if ( 0 == ::strncmp(
"-library",argv[i],4) )
181 else if ( 0 == ::strncmp(
"-function",argv[i],4) )
184 args.emplace_back(argv[i]);
186 if ( lib.empty() || func.empty() ) {
188 "Usage: -plugin DD4hep_Function -arg [-arg] \n\n"
189 " Execute a function without arguments inside a library. \n\n"
190 " -library <string> Library to be loaded \n"
191 " -function <string> name of the entry point to be executed. \n"
192 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
195 Func_t f = gSystem->DynFindSymbol(
"*",func.c_str());
198 ret = gSystem->Load(lib.c_str());
200 except(
"DD4hep_Function",
"+++ Failed to load library: %s",lib.c_str());
202 f = gSystem->DynFindSymbol(
"*",func.c_str());
204 except(
"DD4hep_Function",
"+++ Failed to find function %s in library: %s",
205 func.c_str(),lib.c_str());
208 typedef int (*call_t)(int,
char**);
209 call_t ff = (call_t)f;
210 ret = (*ff)(args.size(),&args[0]);
224 if ( 0 == gApplication ) {
225 std::pair<int, char**> a(argc,argv);
226 gApplication =
new TRint(
"DD4hepRint", &a.first, a.second);
227 printout(INFO,
"DD4hepRint",
"++ Created ROOT interpreter instance for DD4hepUI.");
229 for(
int i=0; i<argc; ++i) {
230 printout(INFO,
"DD4hepRint",
"Excecute[%d]: %s", i, argv[i]);
231 gInterpreter->ProcessLine(argv[i]);
233 if ( !gApplication->IsRunning() ) {
252 static long root_ui(
Detector& description,
int ,
char** ) {
254 std::snprintf(cmd,
sizeof(cmd),
255 "dd4hep::detail::DD4hepUI* gDD4hepUI = new "
256 "dd4hep::detail::DD4hepUI(*(dd4hep::Detector*)%p);",
257 (
void*)&description);
258 gInterpreter->ProcessLine(cmd);
259 printout(ALWAYS,
"DD4hepUI",
260 "Use the ROOT interpreter variable gDD4hepUI "
261 "to interact with the detector description.");
275 static long root_dump_gdml_tables(
Detector& description,
int ,
char** ) {
276 size_t num_tables = 0;
277 size_t num_elements = 0;
278 const TObjArray* c = description.
manager().GetListOfGDMLMatrices();
279 TObjArrayIter arr(c);
280 printout(INFO,
"Dump_GDMLTables",
"+++ Dumping known GDML tables from TGeoManager.");
281 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
282 TGDMLMatrix* gdmlMat = (TGDMLMatrix*)i;
283 num_elements += (gdmlMat->GetRows()*gdmlMat->GetCols());
287 printout(INFO,
"Dump_GDMLTables",
288 "+++ Successfully dumped %ld GDML tables with %ld elements.",
289 num_tables, num_elements);
303 static long root_dump_optical_surfaces(
Detector& description,
int ,
char** ) {
304 size_t num_surfaces = 0;
305 printout(ALWAYS,
"",
"");
306 const TObjArray* c = description.
manager().GetListOfOpticalSurfaces();
307 TObjArrayIter arr(c);
308 printout(ALWAYS,
"Dump_OpticalSurfaces",
"+++ Dumping known Optical Surfaces from TGeoManager.");
309 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
310 TGeoOpticalSurface* optSurt = (TGeoOpticalSurface*)i;
314 printout(ALWAYS,
"Dump_OpticalSurfaces",
315 "+++ Successfully dumped %ld Optical surfaces.",num_surfaces);
318 DECLARE_APPLY(DD4hep_Dump_OpticalSurfaces,root_dump_optical_surfaces)
329 static long root_dump_skin_surfaces(
Detector& description,
int ,
char** ) {
330 size_t num_surfaces = 0;
331 printout(ALWAYS,
"",
"");
332 const TObjArray* c = description.
manager().GetListOfSkinSurfaces();
333 TObjArrayIter arr(c);
334 printout(ALWAYS,
"Dump_SkinSurfaces",
"+++ Dumping known Skin Surfaces from TGeoManager.");
335 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
336 TGeoSkinSurface* skinSurf = (TGeoSkinSurface*)i;
340 printout(ALWAYS,
"Dump_SkinSurfaces",
341 "+++ Successfully dumped %ld Skin surfaces.",num_surfaces);
344 DECLARE_APPLY(DD4hep_Dump_SkinSurfaces,root_dump_skin_surfaces)
355 static long root_dump_border_surfaces(
Detector& description,
int ,
char** ) {
356 size_t num_surfaces = 0;
357 printout(ALWAYS,
"",
"");
358 const TObjArray* c = description.
manager().GetListOfBorderSurfaces();
359 TObjArrayIter arr(c);
360 printout(ALWAYS,
"Dump_BorderSurfaces",
"+++ Dumping known Border Surfaces from TGeoManager.");
361 for(
TObject* i = arr.Next(); i; i=arr.Next()) {
362 TGeoBorderSurface* bordSurt = (TGeoBorderSurface*)i;
366 printout(ALWAYS,
"Dump_BorderSurfaces",
367 "+++ Successfully dumped %ld Border surfaces.",num_surfaces);
370 DECLARE_APPLY(DD4hep_Dump_BorderSurfaces,root_dump_border_surfaces)
382 static long root_elements(
Detector& description,
int argc,
char** argv) {
391 struct ElementPrint {
393 ElementPrint() =
default;
395 virtual ~ElementPrint() =
default;
397 virtual void operator()(TGeoElement* elt) { elt->Print(); }
399 virtual void operator()(TGeoIsotope* iso) { iso->Print(); }
408 struct ElementPrintXML :
public ElementPrint {
412 ElementPrintXML(elt_h r) : root(r) {}
414 virtual ~ElementPrintXML() {}
416 virtual void operator()(TGeoElement* element) {
417 elt_h elt = root.addChild(
_U(element));
418 elt.setAttr(
_U(Z),element->Z());
419 elt.setAttr(
_U(N),element->N());
420 elt.setAttr(
_U(formula),element->GetName());
421 elt.setAttr(
_U(name),element->GetName());
422 elt_h atom = elt.addChild(
_U(atom));
423 atom.setAttr(
_U(type),
"A");
424 atom.setAttr(
_U(unit),
"g/mole");
425 atom.setAttr(
_U(value),element->A());
428 virtual void operator()(TGeoIsotope* isotope) {
429 elt_h iso = root.addChild(
_U(isotope));
430 iso.setAttr(
_U(Z),isotope->GetZ());
431 iso.setAttr(
_U(N),isotope->GetN());
432 iso.setAttr(
_U(formula),isotope->GetName());
433 iso.setAttr(
_U(name),isotope->GetName());
434 elt_h atom = iso.addChild(
_U(atom));
435 atom.setAttr(
_U(type),
"A");
436 atom.setAttr(
_U(unit),
"g/mole");
437 atom.setAttr(
_U(value),isotope->GetA());
441 std::string type =
"text", output =
"";
442 for(
int i=0; i<argc; ++i) {
443 if ( argv[i][0] ==
'-' ) {
444 char c = ::tolower(argv[i][1]);
445 if ( c ==
't' && i+1<argc ) type = argv[++i];
446 else if ( c ==
'o' && i+1<argc ) output = argv[++i];
448 ::printf(
"DD4hep_ElementTable -opt [-opt] \n"
449 " -type <string> Output format: text or xml \n"
450 " -output <file-name> Output file specifier (xml only) \n"
460 if ( type ==
"xml" ) {
461 const char comment[] =
"\n"
462 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
463 " ++++ Generic detector description in C++ ++++\n"
464 " ++++ dd4hep Detector description generator. ++++\n"
470 " ++++ Table of elements as defined in ROOT: " ROOT_RELEASE
" ++++\n"
472 " ++++ M.Frank CERN/LHCb ++++\n"
473 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n ";
474 doc = docH.
create(
"materials", comment);
475 element = doc.
root();
478 ?
new ElementPrintXML(element)
479 :
new ElementPrint());
480 TGeoElementTable* table = description.
manager().GetElementTable();
481 for(Int_t i=0, n=table->GetNelements(); i < n; ++i)
482 (*printer)(table->GetElement(i));
484 for(Int_t i=0, n=table->GetNelements(); i < n; ++i) {
485 TGeoElement* elt = table->GetElement(i);
486 Int_t niso = elt->GetNisotopes();
488 for(Int_t j=0; j < niso; ++j)
489 (*printer)(elt->GetIsotope(j));
510 static long root_materials(
Detector& description,
int argc,
char** argv) {
520 struct MaterialPrint {
527 MaterialPrint(
Detector& desc) : description(desc) {}
529 virtual ~MaterialPrint() =
default;
531 virtual elt_h print(TGeoMaterial* mat) {
532 const char* st =
"Undefined";
533 switch( mat->GetState() ) {
534 case TGeoMaterial::kMatStateSolid: st =
"solid";
break;
535 case TGeoMaterial::kMatStateLiquid: st =
"liquid";
break;
536 case TGeoMaterial::kMatStateGas: st =
"gas";
break;
537 case TGeoMaterial::kMatStateUndefined:
538 default: st =
"Undefined";
break;
540 ::printf(
"%-32s %-8s\n", mat->GetName(), mat->IsMixture() ?
"Mixture" :
"Material");
541 ::printf(
" Aeff=%7.3f Zeff=%7.4f rho=%8.3f [g/mole] radlen=%8.3g [cm] intlen=%8.3g [cm] index=%3d\n",
542 mat->GetA(), mat->GetZ(), mat->GetDensity(),
543 mat->GetRadLen(), mat->GetIntLen(), mat->GetIndex());
544 ::printf(
" Temp=%.3g [Kelvin] Pressure=%.5g [hPa] state=%s\n",
545 mat->GetTemperature(), mat->GetPressure()/dd4hep::pascal/100.0, st);
549 virtual void print(elt_h, TGeoElement* elt,
double frac) {
550 ::printf(
" %-6s Fraction: %7.3f Z=%3d A=%6.2f N=%3d Neff=%6.2f\n",
551 elt->GetName(), frac, elt->Z(), elt->A(), elt->N(), elt->Neff());
554 virtual void printProperty(elt_h,
TNamed* prop, TGDMLMatrix* matrix) {
556 ::printf(
" Property: %-20s [%ld x %ld] --> %s\n",
557 prop->GetName(),
long(matrix->GetRows()),
long(matrix->GetCols()), prop->GetTitle());
559 ::printf(
" Property: %-20s [ERROR: NO TABLE!] --> %s\n",
560 prop->GetName(), prop->GetTitle());
562 virtual void operator()(TGeoMaterial* mat) {
563 Double_t*
mix = mat->IsMixture() ? ((TGeoMixture*)mat)->GetWmixt() : 0;
564 elt_h mh = print(mat);
565 for(
int n=mat->GetNelements(), i=0; i<n; ++i ) {
566 TGeoElement* elt = mat->GetElement(i);
567 print(mh, elt,
mix ?
mix[i] : 1);
569 TListIter mat_iter(&mat->GetProperties());
570 for(
TObject* i = mat_iter.Next(); i; i=mat_iter.Next() ) {
571 printProperty(mh, (
TNamed*)i, description.
manager().GetGDMLMatrix(i->GetTitle()));
581 struct MaterialPrintXML :
public MaterialPrint {
583 MaterialPrintXML(elt_h elt,
Detector& desc) : MaterialPrint(desc), root(elt) {}
584 virtual ~MaterialPrintXML() {}
585 virtual elt_h print(TGeoMaterial* mat) {
586 elt_h elt = root.addChild(
_U(material));
587 elt.setAttr(
_U(name),mat->GetName());
588 if ( ::strlen(mat->GetTitle())>0 ) {
589 elt.setAttr(
_U(formula),mat->GetTitle());
591 else if ( mat->GetNelements() == 1 ) {
592 elt.setAttr(
_U(formula),mat->GetElement(0)->GetName());
595 elt_h RL = elt.addChild(
_U(RL));
596 RL.setAttr(
_U(type),
"X0");
597 RL.setAttr(
_U(value), mat->GetRadLen());
598 RL.setAttr(
_U(unit),
"cm");
599 elt_h NIL = elt.addChild(
_U(NIL));
600 NIL.setAttr(
_U(type),
"lambda");
601 NIL.setAttr(
_U(value), mat->GetIntLen());
602 NIL.setAttr(
_U(unit),
"cm");
605 elt_h D = elt.addChild(
_U(D));
606 D.setAttr(
_U(type),
"density");
607 D.setAttr(
_U(value), mat->GetDensity());
608 D.setAttr(
_U(unit),
"g/cm3");
610 elt_h T = elt.addChild(
_U(T));
611 T.setAttr(
_U(type),
"temperature");
612 T.setAttr(
_U(value), mat->GetTemperature());
613 T.setAttr(
_U(unit),
"kelvin");
616 elt_h P = elt.addChild(
_U(P));
617 P.setAttr(
_U(type),
"pressure");
618 P.setAttr(
_U(value), mat->GetPressure());
619 P.setAttr(
_U(unit),
"pascal");
623 virtual void print(elt_h mat, TGeoElement* element,
double frac) {
624 elt_h elt = mat.addChild(
_U(composite));
625 elt.setAttr(
_U(n),frac);
626 elt.setAttr(
_U(ref),element->GetName());
628 virtual void printProperty(elt_h mat,
TNamed* prop, TGDMLMatrix* ) {
629 elt_h elt = mat.addChild(
_U(property));
630 elt.setAttr(
_U(name),prop->GetName());
631 elt.setAttr(
_U(ref), prop->GetTitle());
635 std::string type =
"text", output =
"", name =
"";
636 for(
int i=0; i<argc; ++i) {
637 if ( argv[i][0] ==
'-' ) {
638 char c = ::tolower(argv[i][1]);
639 if ( c ==
't' && i+1<argc ) type = argv[++i];
640 else if ( c ==
'n' && i+1<argc ) name = argv[++i];
641 else if ( c ==
'o' && i+1<argc ) output = argv[++i];
643 ::printf(
"DD4hep_MaterialTable -opt [-opt] \n"
644 " -type <string> Output format: text or xml \n"
645 " -output <file-name> Output file specifier (xml only) \n"
655 if ( type ==
"xml" ) {
656 const char comment[] =
"\n"
657 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
658 " ++++ Generic detector description in C++ ++++\n"
659 " ++++ dd4hep Detector description generator. ++++\n"
665 " ++++ Table of elements as defined in ROOT: " ROOT_RELEASE
" ++++\n"
667 " ++++ M.Frank CERN/LHCb ++++\n"
668 " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n ";
669 doc = docH.
create(
"materials", comment);
670 element = doc.
root();
673 ?
new MaterialPrintXML(element, description)
674 :
new MaterialPrint(description));
676 TList* mats = description.
manager().GetListOfMaterials();
678 while( (obj=iter->Next()) != 0 ) {
679 TGeoMaterial* mat = (TGeoMaterial*)obj;
680 if ( name.empty() || name == mat->GetName() )
704 static long load_compact(
Detector& description,
int argc,
char** argv) {
707 std::string input = argv[0];
710 printout(INFO,
"CompactLoader",
"+++ Processing compact file: %s with flag %s",
711 input.c_str(), argv[1]);
715 printout(INFO,
"CompactLoader",
"+++ Processing compact file: %s",input.c_str());
738 static long load_xml(
Detector& description,
int argc,
char** argv) {
741 std::string input = argv[0];
744 printout(INFO,
"XMLLoader",
"+++ Processing XML file: %s with flag %s",
745 input.c_str(), argv[1]);
746 description.
fromXML(input, type);
749 printout(INFO,
"XMLLoader",
"+++ Processing XML file: %s",input.c_str());
772 static long process_xml_doc(
Detector& description,
int argc,
char** argv) {
777 xml::XmlElement* h = (xml::XmlElement*)argv[0];
782 printout(INFO,
"XMLLoader",
"+++ Processing XML element: %s with flag %s",
783 input.tag().c_str(), argv[1]);
788 except(
"DD4hepXMLProcessor",
789 "++ The passed reference to the parsed XML document is invalid.");
804 static long load_volmgr(
Detector& description,
int,
char**) {
805 printout(INFO,
"DD4hepVolumeManager",
"**** running plugin DD4hepVolumeManager ! " );
810 printout(INFO,
"VolumeManager",
"+++ Volume manager populated and loaded.");
815 except(
"DD4hep_VolumeManager",
"Exception: %s\n %s", e.what(),
816 "dd4hep: while programming VolumeManager. Are your volIDs correct?");
819 except(
"DD4hep_VolumeManager",
820 "UNKNOWN exception while programming VolumeManager. Are your volIDs correct?");
835 static long dump_geometry2root(
Detector& description,
int argc,
char** argv) {
838 for(
int i = 0; i < argc && argv[i]; ++i) {
839 if ( 0 == ::strncmp(
"-output",argv[i],4) )
842 if ( output.empty() ) {
844 "Usage: -plugin DD4hep_Geometry2ROOT -arg [-arg] \n\n"
845 " Output DD4hep detector description object to a ROOT file. \n\n"
846 " -output <string> Output file name. \n"
847 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
850 printout(INFO,
"Geometry2ROOT",
"+++ Dump geometry to root file:%s",output.c_str());
856 printout(ERROR,
"Geometry2ROOT",
"+++ No output file name given.");
869 static long load_geometryFromroot(
Detector& description,
int argc,
char** argv) {
871 std::string input = argv[0];
872 for(
int i = 0; i < argc && argv[i]; ++i) {
873 if ( 0 == ::strncmp(
"-input",argv[i],4) )
876 if ( input.empty() ) {
878 "Usage: DD4hep_RootLoader -arg [-arg] \n\n"
879 " Load DD4hep detector description from ROOT file to memory. \n\n"
880 " -input <string> Input file name. \n"
881 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
884 printout(INFO,
"DD4hepRootLoader",
"+++ Read geometry from root file:%s",input.c_str());
889 printout(ERROR,
"DD4hep_RootLoader",
"+++ No input file name given.");
902 static long dump_geometry2tgeo(
Detector& description,
int argc,
char** argv) {
904 std::string output( argc == 1 ? argv[0] :
"" );
905 printout(INFO,
"Geometry2TGeo",
"+++ output: %d %s", argc, output.c_str());
906 for(
int i = 0; i < argc && argv[i]; ++i) {
907 if ( 0 == ::strncmp(
"-output",argv[i],4) )
910 if ( output.empty() ) {
912 "Usage: -plugin <name> -arg [-arg] \n"
913 " Output TGeo information to a ROOT file. \n\n"
914 " name: factory name DD4hepGeometry2TGeo \n"
915 " -output <string> Output file name. \n"
916 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
919 printout(INFO,
"Geometry2TGeo",
"+++ Dump geometry to root file:%s",output.c_str());
920 if ( description.
manager().Export(output.c_str()) > 1 ) {
924 printout(ERROR,
"Geometry2TGeo",
"+++ No output file name given.");
938 static long check_detectors(
Detector& description,
int ,
char** ) {
940 auto ret = check.checkDetectors();
941 return ret.first > 0 && ret.second == 0 ? 1 : 0;
953 static long check_sensitives(
Detector& description,
int ,
char** ) {
955 auto ret = check.checkSensitives();
956 return ret.first > 0 && ret.second == 0 ? 1 : 0;
968 static long check_segmentations(
Detector& description,
int ,
char** ) {
970 auto ret = check.checkSegmentations();
971 return ret.first > 0 && ret.second == 0 ? 1 : 0;
983 static long check_readouts(
Detector& description,
int ,
char** ) {
985 auto ret = check.checkReadouts();
986 return ret.first > 0 && ret.second == 0 ? 1 : 0;
998 static long check_idspecs(
Detector& description,
int ,
char** ) {
1000 auto ret = check.checkIdSpecs();
1001 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1013 static long check_volumemanager(
Detector& description,
int ,
char** ) {
1015 auto ret = check.checkVolManager();
1016 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1018 DECLARE_APPLY(DD4hep_CheckVolumeManager,check_volumemanager)
1028 static long check_nominals(
Detector& description,
int ,
char** ) {
1030 auto ret = check.checkNominals();
1031 return ret.first > 0 && ret.second == 0 ? 1 : 0;
1043 static long dump_volume_tree(
Detector& description,
int argc,
char** argv) {
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;
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]);
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 ) {
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;
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));
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);
1121 if ( m_printShapes ) {
1122 printout(ALWAYS,
"VolumeDump",
"+++ Checked %ld shapes.", m_numShapes);
1125 for(
const auto& t : top_counts) {
1127 printout(ALWAYS,
"VolumeDump",
1128 "+++ Top node: %-32s %8ld placements.",t.first.c_str(),t.second);
1133 long dump(std::string prefix, TGeoNode* ideal, TGeoNode* aligned,
int level,
PlacedVolume::VolIDs volids) {
1135 std::stringstream log;
1137 bool sensitive =
false;
1138 std::string opt_info, pref = std::move(prefix);
1140 if ( level >= m_printMaxLevel ) {
1146 else if ( level == 1 ) {
1147 currTop = ideal->GetVolume()->GetName();
1148 ++top_counts[currTop];
1150 else if ( level > 1 ) {
1151 ++top_counts[currTop];
1154 if ( m_printPathes ) {
1156 pref += aligned->GetName();
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);
1166 std::snprintf(fmt,
sizeof(fmt),
"Ideal:%p MotherVol:%p",
1167 (
void*)ideal, (
void*)mother);
1171 if ( m_printVolIDs && ideal && ideal->GetMotherVolume() ) {
1173 if ( !vid.empty() ) {
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);
1181 if ( !vid.empty() || pv.volume().isSensitive() ) {
1186 log << std::hex <<
" (0x" << std::setfill(
'0') << std::setw(8)
1188 << std::setfill(
' ') << std::dec <<
") ";
1194 opt_info = log.str();
1198 if ( m_printVis && pv.volume().visAttributes().isValid() ) {
1199 log <<
" Vis:" << pv.volume().visAttributes().name();
1200 opt_info += log.str();
1203 TGeoVolume* volume = ideal ? ideal->GetVolume() : 0;
1204 if ( !m_printSensitivesOnly || (m_printSensitivesOnly && sensitive) ) {
1205 Volume vol = pv.volume();
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);
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);
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);
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);
1227 const auto* sh = volume ? volume->GetShape() :
nullptr;
1228 printout(INFO,
"VolumeDump",fmt,pref.c_str(),
"",
1231 sh ? sh->IsA()->GetName() :
"[Invalid Shape]",
1233 if ( sens ==
'S' ) ++m_numSensitive;
1235 if ( m_printMaterials ) {
1236 Volume vol = pv.volume();
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",
1243 if ( !ok ) ++m_numMaterialERR;
1244 printout(ok ? INFO : ERROR,
"VolumeDump", fmt,
1245 " ->",
"", mat.
name(), mat.
A(), mptr->GetA(), mat.
Z(), mptr->GetZ());
1248 if ( m_printShapes ) {
1249 log <<
"Shape: " <<
toStringSolid(pv.volume().solid()) <<
" \t";
1251 if ( m_printPositions ) {
1253 const double* trans = ideal->GetMatrix()->GetTranslation();
1254 std::snprintf(fmt,
sizeof(fmt),
"Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]);
1257 std::snprintf(fmt,
sizeof(fmt),
" <ERROR: INVALID Translation matrix> ");
1259 log << fmt <<
" \t";
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());
1265 for (Int_t idau = 0, ndau = aligned->GetNdaughters(); idau < ndau; ++idau) {
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);
1273 printout(ERROR,
"VolumeDump",
" <ERROR: INVALID IDEAL Translation matrix>: %s",aligned->GetName());
1284 if ( m_detector !=
"/world" ) {
1287 except(
"VolumeDump",
"+++ Invalid DetElement path: %s",m_detector.c_str());
1291 except(
"VolumeDump",
"+++ Invalid DetElement placement: %s",m_detector.c_str());
1297 except(
"VolumeDump",
"+++ Invalid placement verification for placement:%s",place.c_str());
1302 Actor actor(description, argc, argv);
1320 static int detelement_processor(
Detector& description,
int argc,
char** argv) {
1321 bool recursive =
true;
1322 ProcessorArgs args(argc, argv);
1324 std::unique_ptr<DetectorProcessor>
1325 proc(dd4hep::createProcessor<DetectorProcessor>(description, args.argc, &args.argv[0]));
1327 for(
int i=0; i<argc; ++i) {
1328 if ( i >= args.start && i <= args.end )
1330 else if ( 0 == ::strncmp(argv[i],
"-recursive",4) )
1332 else if ( 0 == ::strncmp(argv[i],
"-no-recursive",7) )
1334 else if ( 0 == ::strncmp(argv[i],
"-detector",4) ) {
1335 std::string path = argv[++i];
1337 if (
det.isValid() ) {
1340 except(
"DetElementProcessor",
1341 "++ The detector element path:%s is not part of this description!",
1345 except(
"DetElementProcessor",
"++ Unknown plugin argument: %s",argv[i]);
1350 DECLARE_APPLY(DD4hep_DetElementProcessor,detelement_processor)
1365 static int placed_volume_processor(
Detector& description,
int argc,
char** argv) {
1366 bool recursive =
true;
1368 ProcessorArgs args(argc, argv);
1369 std::unique_ptr<PlacedVolumeProcessor>
1370 proc(dd4hep::createProcessor<PlacedVolumeProcessor>(description, args.argc, &args.argv[0]));
1372 std::string path =
"/world";
1373 for(
int i=0; i<argc; ++i) {
1374 if ( i >= args.start && i <= args.end )
1376 else if ( 0 == ::strncmp(argv[i],
"-recursive",4) )
1378 else if ( 0 == ::strncmp(argv[i],
"--recursive",5) )
1380 else if ( 0 == ::strncmp(argv[i],
"-no-recursive",7) )
1382 else if ( 0 == ::strncmp(argv[i],
"--no-recursive",8) )
1384 else if ( 0 == ::strncmp(argv[i],
"-detector",4) )
1386 else if ( 0 == ::strncmp(argv[i],
"--detector",5) )
1389 except(
"PlacedVolumeProcessor",
"++ Unknown plugin argument: %s",argv[i]);
1392 if (
det.isValid() ) {
1393 pv =
det.placement();
1397 except(
"PlacedVolumeProcessor",
1398 "++ The detector element with path:%s has no valid placement!",
1401 except(
"PlacedVolumeProcessor",
1402 "++ The detector element path:%s is not part of this description!",
1406 DECLARE_APPLY(DD4hep_PlacedVolumeProcessor,placed_volume_processor)
1421 std::string path { };
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;
1434 det_world = descr.
world();
1438 printout(ALWAYS,
"DetectorDump",
"+++ Scanned a total of %ld elements.",count);
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]); }
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"
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"
1479 "\tArguments given: " << arguments(ac,av) << std::endl << std::flush;
1490 if ( dsc.
isValid() )
return dsc;
1492 for (Int_t idau = 0, ndau =
v->GetNdaughters(); idau < ndau; ++idau) {
1494 if ( dsc.
isValid() )
return dsc;
1508 bool use_elt = path.empty() || de.
path().find(path) != std::string::npos;
1510 if ( have_match < 0 && use_elt ) {
1514 use_elt &= ((level-have_match) <= analysis_level);
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());
1521 if ( place.
isValid() && de != det_world ) {
1525 if ( !sensitive_only || 0 != de.
volumeID() ) {
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);
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()),
1540 (
void*)place.
ptr(), sens);
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());
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);
1551 std::snprintf(fmt,
sizeof(fmt),
"%03d %%-%ds Placement: %%s [ideal:%%p aligned:%%p] %%c",
1553 printout(INFO,
"DetectorDump",fmt,
"", de.
placementPath().c_str(),
1559 if ( (dump_materials || dump_shapes) && place.
isValid() ) {
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());
1565 if ( dump_positions && place.
isValid() ) {
1568 double loc[3] = {0,0,0}, world[3] = {0,0,0};
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]);
1578 if ( dump_volids && !place.
volIDs().empty() ) {
1579 std::stringstream log;
1581 for(
const auto& i : chain )
1582 log <<
" " << i.first <<
':' << std::dec << std::setw(2) << i.second;
1584 log <<
" (encoded:0x" << std::setfill(
'0') << std::setw(8) << std::hex
1586 << std::setfill(
' ') << std::dec <<
") ";
1588 std::snprintf(fmt,
sizeof(fmt),
"%03d %%-%ds %%s", level+1, 2*level+1);
1589 printout(INFO,
"DetectorDump", fmt,
"", log.str().c_str());
1593 for (
const auto& c : children ) {
1594 validate_id_descriptor(c.second, id_desc);
1595 dump(c.second, level+1, id_desc, chain);
1602 Actor actor(description);
1603 actor.parse_args(argc, argv);
1604 return actor.dump(description.world(), 0, id_descriptor, std::move(chain));
1607 DECLARE_APPLY(DD4hep_DetectorVolumeDump,dump_detelement_tree<1>)
1617 static long detelement_cache(
Detector& description,
int argc,
char** argv) {
1625 for(
const auto& i : c ) cache(i.second);
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];
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;
1647 if ( detector !=
"/world" ) {
1650 except(
"VolumeDump",
"+++ Invalid DetElement path: %s", detector.c_str());
1653 return actor.cache(element);
1665 #include "../GeometryTreeDump.h"
1666 static long exec_GeometryTreeDump(
Detector& description,
int,
char** ) {
1671 DECLARE_APPLY(DD4hep_GeometryTreeDump,exec_GeometryTreeDump)
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]);
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;
1697 if ( types.empty() ) {
1700 printout(INFO,
"DetectorTypes",
"Detector type dump: %ld types:",
long(types.size()));
1701 for(
const auto& type : types ) {
1703 printout(INFO,
"DetectorTypes",
"\t --> %ld %s detectors:",
long(
detectors.size()), type.c_str());
1705 printout(INFO,
"DetectorTypes",
"\t\t %-16s --> %s [%s]",type.c_str(),d.name(),d.type().c_str());
1720 #include <DD4hep/SurfaceInstaller.h>
1732 #include <DD4hep/PluginTester.h>
1733 static long install_plugin_tester(
Detector& description,
int ,
char** ) {
1737 printout(INFO,
"PluginTester",
1738 "+++ Successfully installed PluginTester instance to Detector.");