File indexing completed on 2025-07-12 07:55:13
0001 #ifndef UTILITYAPPS_SRC_RUN_PLUGIN_H
0002 #define UTILITYAPPS_SRC_RUN_PLUGIN_H
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "DD4hep/Detector.h"
0019 #include "DD4hep/Printout.h"
0020 #include "TTimeStamp.h"
0021
0022
0023 #include <iostream>
0024 #include <cstdlib>
0025 #include <vector>
0026 #include <cerrno>
0027 #include <string>
0028 #include <memory>
0029
0030
0031 #include "TRint.h"
0032
0033 namespace {
0034
0035
0036 dd4hep::Detector& dd4hep_instance(const char* ="") {
0037 #if 0
0038 #include "DD4hep/PluginService.h"
0039 try {
0040 union { void* p; Detector* l; } v;
0041 v.p = ::dd4hep::PluginService::Create<void*>("Detector_constructor",name);
0042 if ( v.p ) {
0043 return *v.l;
0044 }
0045 dd4hep::except("RunPlugin","++ Failed to locate plugin to create Detector instance");
0046 }
0047 catch(const std::exception& e) {
0048 dd4hep::except("RunPlugin","++ Exception: %s", e.what());
0049 }
0050 catch(...) {
0051 dd4hep::except("RunPlugin","++ UNKNOWN Exception while creating Detector instance.");
0052 }
0053 dd4hep::except("RunPlugin","++ UNKNOWN Exception while creating Detector instance.");
0054 #endif
0055 return dd4hep::Detector::getInstance();
0056 }
0057
0058
0059 long run_plugin(dd4hep::Detector& description, const char* name, int argc, char** argv) {
0060 try {
0061 description.apply(name,argc,argv);
0062 return 0;
0063 }
0064 catch(const std::exception& e) {
0065 dd4hep::except("RunPlugin","++ Exception while executing plugin %s:\n\t\t%s",
0066 name ? name : "<unknown>", e.what());
0067 }
0068 catch(...) {
0069 dd4hep::except("RunPlugin","++ UNKNOWN Exception while executing plugin %s.",name ? name : "<unknown>");
0070 }
0071 ::exit(EINVAL);
0072 return EINVAL;
0073 }
0074
0075
0076 std::ostream& print_default_args() {
0077 std::cout <<
0078 " -build_type <number/string> Specify the build type \n"
0079 " [OPTIONAL] MUST come immediately after the -compact input.\n"
0080 " Default for each file is: BUILD_DEFAULT [=1] \n"
0081 " Allowed: BUILD_SIMU [=1], BUILD_RECO [=2], \n"
0082 " BUILD_DISPLAY [=3] or BUILD_ENVELOPE [=4] \n"
0083 " -destroy [OPTIONAL] Force destruction of the Detector instance \n"
0084 " before exiting the application \n"
0085 " -no-destroy [OPTIONAL] Inhibit destruction of the Detector instance \n"
0086 " -volmgr [OPTIONAL] Load and populate phys.volume manager to \n"
0087 " check the volume ids for duplicates etc. \n"
0088 " -no-volmgr [OPTIONAL] Inhibit loading phys.volume manager \n"
0089 " -interpreter [OPTIONAL] Start ROOT C++ interpreter after execution. \n"
0090 " -interactive [OPTIONAL] Alias for -interpreter argument. \n"
0091 " -no-interpreter [OPTIONAL] Inhibit ROOT C++ interpreter. \n"
0092 " -print <number/string> Specify output level. Default: INFO(=3) \n"
0093 " [OPTIONAL] Allowed values: VERBOSE(=1), DEBUG(=2), \n"
0094 " INFO(=3), WARNING(=4), ERROR(=5), FATAL(=6) \n"
0095 " The lower the level, the more printout... \n"
0096 " -dry-run [OPTIONAL] Only load description. No execution. \n"
0097 " -ui [OPTIONAL] Install ROOT interpreter UI for dd4hep \n"
0098 " Will show up in the global interpreter variable\n"
0099 " 'dd4hep::ROOTUI* gdd4hepUI' and allows the user\n"
0100 " to interact with the the Detector instance from the\n"
0101 " ROOT interactive prompt. \n"
0102 " -plugin <name> <args> Execute plugin <name> after loading geometry. \n"
0103 " All arguments following until the next \n"
0104 " '-plugin' tag are considered as arguments \n"
0105 " to the current plugin. \n"
0106 " ";
0107 return std::cout;
0108 }
0109
0110
0111 void usage_default(const char* name) {
0112 std::cout << " " << name << " -opt [-opt] \n"
0113 " -compact <file> Specify the compact geometry file \n"
0114 " [REQUIRED] At least one compact geo file is required! \n";
0115 print_default_args() <<
0116 " -load_only [OPTIONAL] Dry-run to only load geometry without \n"
0117 " starting the display. \n"
0118 << std::endl;
0119 std::exit(EINVAL);
0120 }
0121
0122
0123 struct Args {
0124 bool volmgr, dry_run, destroy, interpreter, ui, help;
0125 dd4hep::PrintLevel print;
0126 std::vector<const char*> geo_files, build_types;
0127 std::vector<std::vector<const char*> > plugins;
0128
0129
0130 Args() {
0131 help = false;
0132 ui = false;
0133 volmgr = false;
0134 dry_run = false;
0135 destroy = false;
0136 interpreter = true;
0137 print = dd4hep::INFO;
0138 }
0139
0140
0141 int handle(int& i, int argc, char** argv) {
0142 if ( ::strncmp(argv[i],"-compact",5)==0 || ::strncmp(argv[i],"-input",4)==0 ) {
0143 geo_files.emplace_back(argv[++i]);
0144 if ( argc>i+2 && ::strncmp(argv[i+1],"-build_type",6)==0 ) {
0145 build_types.emplace_back(argv[i+2]);
0146 i += 2;
0147 }
0148 else {
0149 build_types.emplace_back("BUILD_DEFAULT");
0150 }
0151 }
0152 else if ( ::strncmp(argv[i],"-help",5)==0 )
0153 help = true;
0154 else if ( ::strncmp(argv[i],"--help",6)==0 )
0155 help = true;
0156 else if ( ::strncmp(argv[i],"-load_only",5)==0 )
0157 dry_run = true;
0158 else if ( ::strncmp(argv[i],"-dry-run",5)==0 )
0159 dry_run = true;
0160 else if ( ::strncmp(argv[i],"-print",4)==0 )
0161 dd4hep::setPrintLevel(dd4hep::PrintLevel(print = dd4hep::decodePrintLevel(argv[++i])));
0162 else if ( ::strncmp(argv[i],"-destroy",5)==0 )
0163 destroy = true;
0164 else if ( ::strncmp(argv[i],"-no-destroy",8)==0 )
0165 destroy = false;
0166 else if ( ::strncmp(argv[i],"-volmgr",4)==0 )
0167 volmgr = true;
0168 else if ( ::strncmp(argv[i],"-no-volmgr",7)==0 )
0169 volmgr = false;
0170 else if ( ::strncmp(argv[i],"-interpreter",6)==0 )
0171 interpreter = true;
0172 else if ( ::strncmp(argv[i],"-no-interpreter",7)==0 )
0173 interpreter = false;
0174 else if ( ::strncmp(argv[i],"-interactive",6)==0 )
0175 interpreter = true;
0176 else if ( ::strncmp(argv[i],"-no-interactive",7)==0 )
0177 interpreter = false;
0178 else if ( ::strncmp(argv[i],"-ui",3)==0 )
0179 ui = true;
0180 else if ( ::strncmp(argv[i],"-no-ui",6)==0 )
0181 ui = false;
0182 else if ( ::strncmp(argv[i],"-plugin",5)==0 ) {
0183
0184 plugins.emplace_back(std::vector<const char*>());
0185 plugins.back().emplace_back(argv[++i]);
0186 for( ++i; i < argc; ++i ) {
0187 if ( ::strncmp(argv[i],"-plugin",5)==0 ) { --i; break; }
0188 if ( ::strncmp(argv[i],"-end-plugin",4)==0 ) { break; }
0189 plugins.back().emplace_back(argv[i]);
0190 }
0191 plugins.back().emplace_back(nullptr);
0192 }
0193 else
0194 return 0;
0195 return 1;
0196 }
0197
0198
0199 long run(dd4hep::Detector& description, const char* name) {
0200 std::pair<int, char**> a(0,0);
0201 long result;
0202 for(size_t i=0; i<plugins.size(); ++i) {
0203 std::vector<const char*>& plug = plugins[i];
0204
0205 size_t num_args = plug.size()>2 ? plug.size()-2 : 0;
0206 TTimeStamp start;
0207 char text[32];
0208 result = run_plugin(description,plug[0],plug.size()-1,(char**)(num_args>0 ? &plug[1] : 0));
0209 TTimeStamp stop;
0210 ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
0211 if ( result == EINVAL ) {
0212 std::cout << "FAILED to execute dd4hep plugin: '" << plug[0]
0213 << "' with args (" << num_args << ") :[ ";
0214 for( std::size_t j = 1; j < plug.size(); ++j ) {
0215 if ( plug[j] ) std::cout << plug[j] << " ";
0216 }
0217 std::cout << "]" << std::endl << std::flush;
0218 usage_default(name);
0219 }
0220 std::cout << "run_plugin: " << text << " Executed dd4hep plugin: '" << plug[0]
0221 << "' with args (" << num_args << ") :[ ";
0222 for( std::size_t j=1; j<plug.size(); ++j ) {
0223 if ( plug[j] ) std::cout << plug[j] << " ";
0224 }
0225 std::cout << "]" << std::endl << std::flush;
0226 }
0227 if ( name && name[0] ) {
0228 result = run_plugin(description, name, a.first, a.second);
0229 return result;
0230 }
0231 std::cout << "WARNING: run_plugin: No plugin name supplied. "
0232 << "Implicitly assuming execution steered by XML." << std::endl;
0233 return ENOENT;
0234 }
0235 };
0236
0237
0238 void load_compact(dd4hep::Detector& description, Args& args) {
0239
0240 for( std::size_t i=0; i<args.geo_files.size(); ++i ) {
0241 const char* argv[] = { args.geo_files[i], args.build_types[i], 0 };
0242 run_plugin(description,"DD4hep_CompactLoader",2,(char**)argv);
0243 }
0244 }
0245 }
0246
0247
0248 namespace dd4hep {
0249 namespace execute {
0250
0251
0252 int main_wrapper(const char* name, int argc, char** argv) {
0253 Args args;
0254 for( int i=1; i<argc;++i ) {
0255 if ( argv[i][0]=='-' ) {
0256 if ( args.handle(i, argc, argv) )
0257 continue;
0258 else
0259 usage_default(name);
0260 }
0261 else {
0262 args.geo_files.emplace_back(argv[i]);
0263 args.build_types.emplace_back("BUILD_DEFAULT");
0264 }
0265 }
0266 if ( args.geo_files.empty() )
0267 usage_default(name);
0268
0269 dd4hep::Detector& description = dd4hep_instance();
0270
0271 load_compact(description, args);
0272 if ( args.ui ) run_plugin(description,"DD4hep_InteractiveUI",0,0);
0273
0274 if ( args.volmgr ) run_plugin(description,"DD4hep_VolumeManager",0,0);
0275
0276
0277 if ( !args.dry_run ) {
0278 long result = 0;
0279 std::pair<int, char**> a(0,0);
0280 if ( args.interpreter ) {
0281 TRint app(name, &a.first, a.second);
0282 result = args.run(description, name);
0283 if ( result != EINVAL ) app.Run();
0284 }
0285 else {
0286 result = args.run(description, name);
0287 }
0288 if ( result == EINVAL ) usage_default(name);
0289 }
0290 else {
0291 dd4hep::printout(INFO,"Application","The geometry was loaded. Application now exiting.");
0292 }
0293 try {
0294 if ( args.destroy ) description.destroyInstance();
0295 }
0296 catch(const std::exception& e) {
0297 dd4hep::printout(ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
0298 throw;
0299 }
0300 catch (...) {
0301 dd4hep::printout(ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
0302 throw;
0303 }
0304 return 0;
0305 }
0306
0307 void usage_plugin_runner(const char* runner="geoPluginRun", bool exit_program=true) {
0308 std::cout << runner << " -opt [-opt] \n"
0309 " -input <file> [OPTIONAL] Specify geometry input file. \n"
0310 " -plugin <name> <args> [args] [-end-plugin] \n"
0311 " [REQUIRED] Plugin to be executed and applied. \n"
0312 " -plugin <name> <args> [args] -end-plugin \n"
0313 " [OPTIONAL] Next plugin with arguments. \n";
0314 print_default_args() << std::endl;
0315 if ( exit_program ) ::exit(EINVAL);
0316 }
0317
0318
0319 int invoke_plugin_runner(const char* name, int argc,char** argv) {
0320 Args arguments;
0321 arguments.interpreter = false;
0322
0323 for( int i=1; i < argc; ++i ) {
0324 if( argv[i][0]=='-' ) {
0325 if ( arguments.handle(i,argc,argv) )
0326 continue;
0327 }
0328 else {
0329 usage_plugin_runner();
0330 }
0331 }
0332 if( !arguments.dry_run &&
0333 !arguments.ui &&
0334 !arguments.interpreter &&
0335 arguments.plugins.empty() &&
0336 arguments.geo_files.empty() )
0337 {
0338 usage_plugin_runner();
0339 }
0340 if( arguments.help ) {
0341 usage_plugin_runner();
0342 }
0343 std::unique_ptr<TRint> interpreter;
0344 dd4hep::Detector& description = dd4hep_instance();
0345
0346 if( !arguments.geo_files.empty() ) {
0347 load_compact(description, arguments);
0348 }
0349 else {
0350 std::cout << "geoPluginRun: No geometry input supplied. "
0351 << "No geometry will be loaded." << std::endl << std::flush;
0352 }
0353
0354 if( arguments.ui ) {
0355 run_plugin(description,"DD4hep_InteractiveUI",0,0);
0356 }
0357
0358 if( arguments.volmgr ) {
0359 run_plugin(description,"DD4hep_VolumeManager",0,0);
0360 }
0361 if( arguments.interpreter ) {
0362 std::pair<int, char**> a(0,0);
0363 interpreter.reset(new TRint("geoPluginRun", &a.first, a.second));
0364 }
0365
0366 for( size_t i=0; i < arguments.plugins.size(); ++i ) {
0367 std::vector<const char*>& plug = arguments.plugins[i];
0368 int num_args = int(plug.size())-2;
0369 TTimeStamp start;
0370 char text[32];
0371 long result = run_plugin(description, plug[0], num_args, (char**)&plug[1]);
0372 TTimeStamp stop;
0373 ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
0374 if (result == EINVAL ) {
0375 std::cout << "geoPluginRun: FAILED to execute dd4hep plugin: '" << plug[0]
0376 << "' with args (" << num_args << ") :[ ";
0377 for(size_t j = 1; j < plug.size(); ++j) {
0378 if ( plug[j] ) std::cout << plug[j] << " ";
0379 }
0380 std::cout << "]" << std::endl;
0381 usage_plugin_runner();
0382 }
0383 std::cout << "geoPluginRun: " << text <<" Executed dd4hep plugin: '" << plug[0]
0384 << "' with args (" << num_args << ") :[ ";
0385 for( size_t j=1; j < plug.size(); ++j ) {
0386 if ( plug[j] ) std::cout << plug[j] << " ";
0387 }
0388 std::cout << "]" << std::endl << std::flush;
0389 }
0390 if( arguments.plugins.empty() ) {
0391
0392 if( !arguments.dry_run ) {
0393 long result = 0;
0394 std::pair<int, char**> a(0,0);
0395 if( arguments.interpreter ) {
0396 TRint app(name, &a.first, a.second);
0397 result = arguments.run(description, name);
0398 if( result != EINVAL ) app.Run();
0399 }
0400 else
0401 result = arguments.run(description, name);
0402 if( result == EINVAL ) usage_default(name);
0403 }
0404 else {
0405 std::cout << "The geometry was loaded. Application now exiting." << std::endl;
0406 }
0407 }
0408 if ( !arguments.dry_run && interpreter.get() ) {
0409 interpreter->Run();
0410 }
0411 try {
0412 if ( arguments.destroy ) description.destroyInstance();
0413 }
0414 catch(const std::exception& e) {
0415 dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
0416 throw;
0417 }
0418 catch (...) {
0419 dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
0420 throw;
0421 }
0422 return 0;
0423 }
0424
0425
0426 int main_plugins(const char* name, int argc, char** argv) {
0427 try {
0428 return invoke_plugin_runner(name, argc, argv);
0429 }
0430 catch(const std::exception& e) {
0431 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
0432 }
0433 catch (...) {
0434 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
0435 }
0436 return EINVAL;
0437 }
0438
0439
0440 int main_default(const char* name, int argc, char** argv) {
0441 try {
0442 return main_wrapper(name,argc,argv);
0443 }
0444 catch(const std::exception& e) {
0445 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
0446 }
0447 catch (...) {
0448 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
0449 }
0450 return EINVAL;
0451 }
0452 }
0453 }
0454
0455 #endif