Back to home page

EIC code displayed by LXR

 
 

    


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 //  AIDA Detector description implementation 
0006 //--------------------------------------------------------------------------
0007 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0008 // All rights reserved.
0009 //
0010 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0011 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0012 //
0013 // Author     : M.Frank
0014 //
0015 //==========================================================================
0016 
0017 // Framework include files
0018 #include "DD4hep/Detector.h"
0019 #include "DD4hep/Printout.h"
0020 #include "TTimeStamp.h"
0021 
0022 // C/C++ include files
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* /* name */ ="") {
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         // Need to interprete plugin args here locally.....
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         // Remove plugin name and trailing 0x0 from args.
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     // Load all compact files
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 {  // This is the default
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       // Load all compact files
0271       load_compact(description, args);
0272       if ( args.ui ) run_plugin(description,"DD4hep_InteractiveUI",0,0);
0273       // Create volume manager and populate it required
0274       if ( args.volmgr ) run_plugin(description,"DD4hep_VolumeManager",0,0);
0275 
0276       // Create an interactive ROOT application
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       // Load compact files if required by plugin
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       // Attach UI instance if requested to ease interaction from the ROOT prompt
0354       if( arguments.ui )  {
0355         run_plugin(description,"DD4hep_InteractiveUI",0,0);
0356       }
0357       // Create volume manager and populate it required
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       // Execute plugin
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         // Create an interactive ROOT application
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     /// Main entry point as a program
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