File indexing completed on 2025-01-18 09:15:00
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;
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 ui = false;
0132 volmgr = false;
0133 dry_run = false;
0134 destroy = false;
0135 interpreter = true;
0136 print = dd4hep::INFO;
0137 }
0138
0139
0140 int handle(int& i, int argc, char** argv) {
0141 if ( ::strncmp(argv[i],"-compact",5)==0 || ::strncmp(argv[i],"-input",4)==0 ) {
0142 geo_files.emplace_back(argv[++i]);
0143 if ( argc>i+2 && ::strncmp(argv[i+1],"-build_type",6)==0 ) {
0144 build_types.emplace_back(argv[i+2]);
0145 i += 2;
0146 }
0147 else {
0148 build_types.emplace_back("BUILD_DEFAULT");
0149 }
0150 }
0151 else if ( ::strncmp(argv[i],"-load_only",5)==0 )
0152 dry_run = true;
0153 else if ( ::strncmp(argv[i],"-dry-run",5)==0 )
0154 dry_run = true;
0155 else if ( ::strncmp(argv[i],"-print",4)==0 )
0156 dd4hep::setPrintLevel(dd4hep::PrintLevel(print = dd4hep::decodePrintLevel(argv[++i])));
0157 else if ( ::strncmp(argv[i],"-destroy",5)==0 )
0158 destroy = true;
0159 else if ( ::strncmp(argv[i],"-no-destroy",8)==0 )
0160 destroy = false;
0161 else if ( ::strncmp(argv[i],"-volmgr",4)==0 )
0162 volmgr = true;
0163 else if ( ::strncmp(argv[i],"-no-volmgr",7)==0 )
0164 volmgr = false;
0165 else if ( ::strncmp(argv[i],"-interpreter",6)==0 )
0166 interpreter = true;
0167 else if ( ::strncmp(argv[i],"-no-interpreter",7)==0 )
0168 interpreter = false;
0169 else if ( ::strncmp(argv[i],"-interactive",6)==0 )
0170 interpreter = true;
0171 else if ( ::strncmp(argv[i],"-no-interactive",7)==0 )
0172 interpreter = false;
0173 else if ( ::strncmp(argv[i],"-ui",3)==0 )
0174 ui = true;
0175 else if ( ::strncmp(argv[i],"-no-ui",6)==0 )
0176 ui = false;
0177 else if ( ::strncmp(argv[i],"-plugin",5)==0 ) {
0178
0179 plugins.emplace_back(std::vector<const char*>());
0180 plugins.back().emplace_back(argv[++i]);
0181 for( ++i; i < argc; ++i ) {
0182 if ( ::strncmp(argv[i],"-plugin",5)==0 ) { --i; break; }
0183 if ( ::strncmp(argv[i],"-end-plugin",4)==0 ) { break; }
0184 plugins.back().emplace_back(argv[i]);
0185 }
0186 plugins.back().emplace_back(nullptr);
0187 }
0188 else
0189 return 0;
0190 return 1;
0191 }
0192
0193
0194 long run(dd4hep::Detector& description, const char* name) {
0195 std::pair<int, char**> a(0,0);
0196 long result;
0197 for(size_t i=0; i<plugins.size(); ++i) {
0198 std::vector<const char*>& plug = plugins[i];
0199
0200 size_t num_args = plug.size()>2 ? plug.size()-2 : 0;
0201 TTimeStamp start;
0202 char text[32];
0203 result = run_plugin(description,plug[0],plug.size()-1,(char**)(num_args>0 ? &plug[1] : 0));
0204 TTimeStamp stop;
0205 ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
0206 if ( result == EINVAL ) {
0207 std::cout << "FAILED to execute dd4hep plugin: '" << plug[0]
0208 << "' with args (" << num_args << ") :[ ";
0209 for( std::size_t j = 1; j < plug.size(); ++j ) {
0210 if ( plug[j] ) std::cout << plug[j] << " ";
0211 }
0212 std::cout << "]" << std::endl << std::flush;
0213 usage_default(name);
0214 }
0215 std::cout << "run_plugin: " << text << " Executed dd4hep plugin: '" << plug[0]
0216 << "' with args (" << num_args << ") :[ ";
0217 for( std::size_t j=1; j<plug.size(); ++j ) {
0218 if ( plug[j] ) std::cout << plug[j] << " ";
0219 }
0220 std::cout << "]" << std::endl << std::flush;
0221 }
0222 if ( name && name[0] ) {
0223 result = run_plugin(description, name, a.first, a.second);
0224 return result;
0225 }
0226 std::cout << "WARNING: run_plugin: No plugin name supplied. "
0227 << "Implicitly assuming execution steered by XML." << std::endl;
0228 return ENOENT;
0229 }
0230 };
0231
0232
0233 void load_compact(dd4hep::Detector& description, Args& args) {
0234
0235 for( std::size_t i=0; i<args.geo_files.size(); ++i ) {
0236 const char* argv[] = { args.geo_files[i], args.build_types[i], 0 };
0237 run_plugin(description,"DD4hep_CompactLoader",2,(char**)argv);
0238 }
0239 }
0240 }
0241
0242
0243 namespace dd4hep {
0244 namespace execute {
0245
0246
0247 int main_wrapper(const char* name, int argc, char** argv) {
0248 Args args;
0249 for( int i=1; i<argc;++i ) {
0250 if ( argv[i][0]=='-' ) {
0251 if ( args.handle(i, argc, argv) )
0252 continue;
0253 else
0254 usage_default(name);
0255 }
0256 else {
0257 args.geo_files.emplace_back(argv[i]);
0258 args.build_types.emplace_back("BUILD_DEFAULT");
0259 }
0260 }
0261 if ( args.geo_files.empty() )
0262 usage_default(name);
0263
0264 dd4hep::Detector& description = dd4hep_instance();
0265
0266 load_compact(description, args);
0267 if ( args.ui ) run_plugin(description,"DD4hep_InteractiveUI",0,0);
0268
0269 if ( args.volmgr ) run_plugin(description,"DD4hep_VolumeManager",0,0);
0270
0271
0272 if ( !args.dry_run ) {
0273 long result = 0;
0274 std::pair<int, char**> a(0,0);
0275 if ( args.interpreter ) {
0276 TRint app(name, &a.first, a.second);
0277 result = args.run(description, name);
0278 if ( result != EINVAL ) app.Run();
0279 }
0280 else {
0281 result = args.run(description, name);
0282 }
0283 if ( result == EINVAL ) usage_default(name);
0284 }
0285 else {
0286 dd4hep::printout(INFO,"Application","The geometry was loaded. Application now exiting.");
0287 }
0288 try {
0289 if ( args.destroy ) description.destroyInstance();
0290 }
0291 catch(const std::exception& e) {
0292 dd4hep::printout(ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
0293 throw;
0294 }
0295 catch (...) {
0296 dd4hep::printout(ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
0297 throw;
0298 }
0299 return 0;
0300 }
0301
0302 void usage_plugin_runner(const char* runner="geoPluginRun", bool exit_program=true) {
0303 std::cout << runner << " -opt [-opt] \n"
0304 " -input <file> [OPTIONAL] Specify geometry input file. \n"
0305 " -plugin <name> <args> [args] [-end-plugin] \n"
0306 " [REQUIRED] Plugin to be executed and applied. \n"
0307 " -plugin <name> <args> [args] -end-plugin \n"
0308 " [OPTIONAL] Next plugin with arguments. \n";
0309 print_default_args() << std::endl;
0310 if ( exit_program ) ::exit(EINVAL);
0311 }
0312
0313
0314 int invoke_plugin_runner(const char* name, int argc,char** argv) {
0315 Args arguments;
0316 arguments.interpreter = false;
0317
0318 for(int i=1; i<argc;++i) {
0319 if ( argv[i][0]=='-' ) {
0320 if ( arguments.handle(i,argc,argv) )
0321 continue;
0322 }
0323 else {
0324 usage_plugin_runner();
0325 }
0326 }
0327 if ( !arguments.dry_run &&
0328 !arguments.ui &&
0329 !arguments.interpreter &&
0330 arguments.plugins.empty() &&
0331 arguments.geo_files.empty() )
0332 {
0333 usage_plugin_runner();
0334 }
0335 std::unique_ptr<TRint> interpreter;
0336 dd4hep::Detector& description = dd4hep_instance();
0337
0338 if ( !arguments.geo_files.empty() ) {
0339 load_compact(description, arguments);
0340 }
0341 else {
0342 std::cout << "geoPluginRun: No geometry input supplied. "
0343 << "No geometry will be loaded." << std::endl << std::flush;
0344 }
0345
0346 if ( arguments.ui ) {
0347 run_plugin(description,"DD4hep_InteractiveUI",0,0);
0348 }
0349
0350 if ( arguments.volmgr ) {
0351 run_plugin(description,"DD4hep_VolumeManager",0,0);
0352 }
0353 if ( arguments.interpreter ) {
0354 std::pair<int, char**> a(0,0);
0355 interpreter.reset(new TRint("geoPluginRun", &a.first, a.second));
0356 }
0357
0358 for(size_t i=0; i<arguments.plugins.size(); ++i) {
0359 std::vector<const char*>& plug = arguments.plugins[i];
0360 int num_args = int(plug.size())-2;
0361 TTimeStamp start;
0362 char text[32];
0363 long result = run_plugin(description, plug[0], num_args, (char**)&plug[1]);
0364 TTimeStamp stop;
0365 ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
0366 if ( result == EINVAL ) {
0367 std::cout << "geoPluginRun: FAILED to execute dd4hep plugin: '" << plug[0]
0368 << "' with args (" << num_args << ") :[ ";
0369 for(size_t j = 1; j < plug.size(); ++j) {
0370 if ( plug[j] ) std::cout << plug[j] << " ";
0371 }
0372 std::cout << "]" << std::endl;
0373 usage_plugin_runner();
0374 }
0375 std::cout << "geoPluginRun: " << text <<" Executed 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 << std::flush;
0381 }
0382 if ( arguments.plugins.empty() ) {
0383
0384 if ( !arguments.dry_run ) {
0385 long result = 0;
0386 std::pair<int, char**> a(0,0);
0387 if ( arguments.interpreter ) {
0388 TRint app(name, &a.first, a.second);
0389 result = arguments.run(description, name);
0390 if ( result != EINVAL ) app.Run();
0391 }
0392 else
0393 result = arguments.run(description, name);
0394 if ( result == EINVAL ) usage_default(name);
0395 }
0396 else {
0397 std::cout << "The geometry was loaded. Application now exiting." << std::endl;
0398 }
0399 }
0400 if ( !arguments.dry_run && interpreter.get() ) {
0401 interpreter->Run();
0402 }
0403 try {
0404 if ( arguments.destroy ) description.destroyInstance();
0405 }
0406 catch(const std::exception& e) {
0407 dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
0408 throw;
0409 }
0410 catch (...) {
0411 dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
0412 throw;
0413 }
0414 return 0;
0415 }
0416
0417
0418 int main_plugins(const char* name, int argc, char** argv) {
0419 try {
0420 return invoke_plugin_runner(name, argc, argv);
0421 }
0422 catch(const std::exception& e) {
0423 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
0424 }
0425 catch (...) {
0426 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
0427 }
0428 return EINVAL;
0429 }
0430
0431
0432 int main_default(const char* name, int argc, char** argv) {
0433 try {
0434 return main_wrapper(name,argc,argv);
0435 }
0436 catch(const std::exception& e) {
0437 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
0438 }
0439 catch (...) {
0440 dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
0441 }
0442 return EINVAL;
0443 }
0444 }
0445 }
0446
0447 #endif