Back to home page

EIC code displayed by LXR

 
 

    


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 //  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;
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         // Need to interprete plugin args here locally.....
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         // Remove plugin name and trailing 0x0 from args.
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     // Load all compact files
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 {  // This is the default
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       // Load all compact files
0266       load_compact(description, args);
0267       if ( args.ui ) run_plugin(description,"DD4hep_InteractiveUI",0,0);
0268       // Create volume manager and populate it required
0269       if ( args.volmgr ) run_plugin(description,"DD4hep_VolumeManager",0,0);
0270 
0271       // Create an interactive ROOT application
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       // Load compact files if required by plugin
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       // Attach UI instance if requested to ease interaction from the ROOT prompt
0346       if ( arguments.ui )  {
0347         run_plugin(description,"DD4hep_InteractiveUI",0,0);
0348       }
0349       // Create volume manager and populate it required
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       // Execute plugin
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         // Create an interactive ROOT application
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     /// Main entry point as a program
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