DD4hep  1.31.0
Detector Description Toolkit for High Energy Physics
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
run_plugin.h
Go to the documentation of this file.
1 #ifndef UTILITYAPPS_SRC_RUN_PLUGIN_H
2 #define UTILITYAPPS_SRC_RUN_PLUGIN_H
3 
4 //==========================================================================
5 // AIDA Detector description implementation
6 //--------------------------------------------------------------------------
7 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
8 // All rights reserved.
9 //
10 // For the licensing terms see $DD4hepINSTALL/LICENSE.
11 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
12 //
13 // Author : M.Frank
14 //
15 //==========================================================================
16 
17 // Framework include files
18 #include "DD4hep/Detector.h"
19 #include "DD4hep/Printout.h"
20 #include "TTimeStamp.h"
21 
22 // C/C++ include files
23 #include <iostream>
24 #include <cstdlib>
25 #include <vector>
26 #include <cerrno>
27 #include <string>
28 #include <memory>
29 
30 //________________________________________________________________________________
31 #include "TRint.h"
32 //________________________________________________________________________________
33 namespace {
34 
35  //______________________________________________________________________________
36  dd4hep::Detector& dd4hep_instance(const char* /* name */ ="") {
37 #if 0
38 #include "DD4hep/PluginService.h"
39  try {
40  union { void* p; Detector* l; } v;
41  v.p = ::dd4hep::PluginService::Create<void*>("Detector_constructor",name);
42  if ( v.p ) {
43  return *v.l;
44  }
45  dd4hep::except("RunPlugin","++ Failed to locate plugin to create Detector instance");
46  }
47  catch(const std::exception& e) {
48  dd4hep::except("RunPlugin","++ Exception: %s", e.what());
49  }
50  catch(...) {
51  dd4hep::except("RunPlugin","++ UNKNOWN Exception while creating Detector instance.");
52  }
53  dd4hep::except("RunPlugin","++ UNKNOWN Exception while creating Detector instance.");
54 #endif
56  }
57 
58  //______________________________________________________________________________
59  long run_plugin(dd4hep::Detector& description, const char* name, int argc, char** argv) {
60  try {
61  description.apply(name,argc,argv);
62  return 0;
63  }
64  catch(const std::exception& e) {
65  dd4hep::except("RunPlugin","++ Exception while executing plugin %s:\n\t\t%s",
66  name ? name : "<unknown>", e.what());
67  }
68  catch(...) {
69  dd4hep::except("RunPlugin","++ UNKNOWN Exception while executing plugin %s.",name ? name : "<unknown>");
70  }
71  ::exit(EINVAL);
72  return EINVAL;
73  }
74 
75  //______________________________________________________________________________
76  std::ostream& print_default_args() {
77  std::cout <<
78  " -build_type <number/string> Specify the build type \n"
79  " [OPTIONAL] MUST come immediately after the -compact input.\n"
80  " Default for each file is: BUILD_DEFAULT [=1] \n"
81  " Allowed: BUILD_SIMU [=1], BUILD_RECO [=2], \n"
82  " BUILD_DISPLAY [=3] or BUILD_ENVELOPE [=4] \n"
83  " -destroy [OPTIONAL] Force destruction of the Detector instance \n"
84  " before exiting the application \n"
85  " -no-destroy [OPTIONAL] Inhibit destruction of the Detector instance \n"
86  " -volmgr [OPTIONAL] Load and populate phys.volume manager to \n"
87  " check the volume ids for duplicates etc. \n"
88  " -no-volmgr [OPTIONAL] Inhibit loading phys.volume manager \n"
89  " -interpreter [OPTIONAL] Start ROOT C++ interpreter after execution. \n"
90  " -interactive [OPTIONAL] Alias for -interpreter argument. \n"
91  " -no-interpreter [OPTIONAL] Inhibit ROOT C++ interpreter. \n"
92  " -print <number/string> Specify output level. Default: INFO(=3) \n"
93  " [OPTIONAL] Allowed values: VERBOSE(=1), DEBUG(=2), \n"
94  " INFO(=3), WARNING(=4), ERROR(=5), FATAL(=6) \n"
95  " The lower the level, the more printout... \n"
96  " -dry-run [OPTIONAL] Only load description. No execution. \n"
97  " -ui [OPTIONAL] Install ROOT interpreter UI for dd4hep \n"
98  " Will show up in the global interpreter variable\n"
99  " 'dd4hep::ROOTUI* gdd4hepUI' and allows the user\n"
100  " to interact with the the Detector instance from the\n"
101  " ROOT interactive prompt. \n"
102  " -plugin <name> <args> Execute plugin <name> after loading geometry. \n"
103  " All arguments following until the next \n"
104  " '-plugin' tag are considered as arguments \n"
105  " to the current plugin. \n"
106  " ";
107  return std::cout;
108  }
109 
110  //______________________________________________________________________________
111  void usage_default(const char* name) {
112  std::cout << " " << name << " -opt [-opt] \n"
113  " -compact <file> Specify the compact geometry file \n"
114  " [REQUIRED] At least one compact geo file is required! \n";
115  print_default_args() <<
116  " -load_only [OPTIONAL] Dry-run to only load geometry without \n"
117  " starting the display. \n"
118  << std::endl;
119  std::exit(EINVAL);
120  }
121 
122  //______________________________________________________________________________
123  struct Args {
124  bool volmgr, dry_run, destroy, interpreter, ui, help;
125  dd4hep::PrintLevel print;
126  std::vector<const char*> geo_files, build_types;
127  std::vector<std::vector<const char*> > plugins;
128 
129  //____________________________________________________________________________
130  Args() {
131  help = false;
132  ui = false;
133  volmgr = false;
134  dry_run = false;
135  destroy = false;
136  interpreter = true;
137  print = dd4hep::INFO;
138  }
139 
140  //____________________________________________________________________________
141  int handle(int& i, int argc, char** argv) {
142  if ( ::strncmp(argv[i],"-compact",5)==0 || ::strncmp(argv[i],"-input",4)==0 ) {
143  geo_files.emplace_back(argv[++i]);
144  if ( argc>i+2 && ::strncmp(argv[i+1],"-build_type",6)==0 ) {
145  build_types.emplace_back(argv[i+2]);
146  i += 2;
147  }
148  else {
149  build_types.emplace_back("BUILD_DEFAULT");
150  }
151  }
152  else if ( ::strncmp(argv[i],"-help",5)==0 )
153  help = true;
154  else if ( ::strncmp(argv[i],"--help",6)==0 )
155  help = true;
156  else if ( ::strncmp(argv[i],"-load_only",5)==0 )
157  dry_run = true;
158  else if ( ::strncmp(argv[i],"-dry-run",5)==0 )
159  dry_run = true;
160  else if ( ::strncmp(argv[i],"-print",4)==0 )
161  dd4hep::setPrintLevel(dd4hep::PrintLevel(print = dd4hep::decodePrintLevel(argv[++i])));
162  else if ( ::strncmp(argv[i],"-destroy",5)==0 )
163  destroy = true;
164  else if ( ::strncmp(argv[i],"-no-destroy",8)==0 )
165  destroy = false;
166  else if ( ::strncmp(argv[i],"-volmgr",4)==0 )
167  volmgr = true;
168  else if ( ::strncmp(argv[i],"-no-volmgr",7)==0 )
169  volmgr = false;
170  else if ( ::strncmp(argv[i],"-interpreter",6)==0 )
171  interpreter = true;
172  else if ( ::strncmp(argv[i],"-no-interpreter",7)==0 )
173  interpreter = false;
174  else if ( ::strncmp(argv[i],"-interactive",6)==0 )
175  interpreter = true;
176  else if ( ::strncmp(argv[i],"-no-interactive",7)==0 )
177  interpreter = false;
178  else if ( ::strncmp(argv[i],"-ui",3)==0 )
179  ui = true;
180  else if ( ::strncmp(argv[i],"-no-ui",6)==0 )
181  ui = false;
182  else if ( ::strncmp(argv[i],"-plugin",5)==0 ) {
183  // Need to interprete plugin args here locally.....
184  plugins.emplace_back(std::vector<const char*>());
185  plugins.back().emplace_back(argv[++i]);
186  for( ++i; i < argc; ++i ) {
187  if ( ::strncmp(argv[i],"-plugin",5)==0 ) { --i; break; }
188  if ( ::strncmp(argv[i],"-end-plugin",4)==0 ) { break; }
189  plugins.back().emplace_back(argv[i]);
190  }
191  plugins.back().emplace_back(nullptr);
192  }
193  else
194  return 0;
195  return 1;
196  }
197 
198  //____________________________________________________________________________
199  long run(dd4hep::Detector& description, const char* name) {
200  std::pair<int, char**> a(0,0);
201  long result;
202  for(size_t i=0; i<plugins.size(); ++i) {
203  std::vector<const char*>& plug = plugins[i];
204  // Remove plugin name and trailing 0x0 from args.
205  size_t num_args = plug.size()>2 ? plug.size()-2 : 0;
206  TTimeStamp start;
207  char text[32];
208  result = run_plugin(description,plug[0],plug.size()-1,(char**)(num_args>0 ? &plug[1] : 0));
209  TTimeStamp stop;
210  ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
211  if ( result == EINVAL ) {
212  std::cout << "FAILED to execute dd4hep plugin: '" << plug[0]
213  << "' with args (" << num_args << ") :[ ";
214  for( std::size_t j = 1; j < plug.size(); ++j ) {
215  if ( plug[j] ) std::cout << plug[j] << " ";
216  }
217  std::cout << "]" << std::endl << std::flush;
218  usage_default(name);
219  }
220  std::cout << "run_plugin: " << text << " Executed dd4hep plugin: '" << plug[0]
221  << "' with args (" << num_args << ") :[ ";
222  for( std::size_t j=1; j<plug.size(); ++j ) {
223  if ( plug[j] ) std::cout << plug[j] << " ";
224  }
225  std::cout << "]" << std::endl << std::flush;
226  }
227  if ( name && name[0] ) {
228  result = run_plugin(description, name, a.first, a.second);
229  return result;
230  }
231  std::cout << "WARNING: run_plugin: No plugin name supplied. "
232  << "Implicitly assuming execution steered by XML." << std::endl;
233  return ENOENT;
234  }
235  };
236 
237  //______________________________________________________________________________
238  void load_compact(dd4hep::Detector& description, Args& args) {
239  // Load all compact files
240  for( std::size_t i=0; i<args.geo_files.size(); ++i ) {
241  const char* argv[] = { args.geo_files[i], args.build_types[i], 0 };
242  run_plugin(description,"DD4hep_CompactLoader",2,(char**)argv);
243  }
244  }
245 }
246 
247 
248 namespace dd4hep {
249  namespace execute {
250 
251  //______________________________________________________________________________
252  int main_wrapper(const char* name, int argc, char** argv) {
253  Args args;
254  for( int i=1; i<argc;++i ) {
255  if ( argv[i][0]=='-' ) {
256  if ( args.handle(i, argc, argv) )
257  continue;
258  else
259  usage_default(name);
260  }
261  else { // This is the default
262  args.geo_files.emplace_back(argv[i]);
263  args.build_types.emplace_back("BUILD_DEFAULT");
264  }
265  }
266  if ( args.geo_files.empty() )
267  usage_default(name);
268 
269  dd4hep::Detector& description = dd4hep_instance();
270  // Load all compact files
271  load_compact(description, args);
272  if ( args.ui ) run_plugin(description,"DD4hep_InteractiveUI",0,0);
273  // Create volume manager and populate it required
274  if ( args.volmgr ) run_plugin(description,"DD4hep_VolumeManager",0,0);
275 
276  // Create an interactive ROOT application
277  if ( !args.dry_run ) {
278  long result = 0;
279  std::pair<int, char**> a(0,0);
280  if ( args.interpreter ) {
281  TRint app(name, &a.first, a.second);
282  result = args.run(description, name);
283  if ( result != EINVAL ) app.Run();
284  }
285  else {
286  result = args.run(description, name);
287  }
288  if ( result == EINVAL ) usage_default(name);
289  }
290  else {
291  dd4hep::printout(INFO,"Application","The geometry was loaded. Application now exiting.");
292  }
293  try {
294  if ( args.destroy ) description.destroyInstance();
295  }
296  catch(const std::exception& e) {
297  dd4hep::printout(ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
298  throw;
299  }
300  catch (...) {
301  dd4hep::printout(ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
302  throw;
303  }
304  return 0;
305  }
306 
307  void usage_plugin_runner(const char* runner="geoPluginRun", bool exit_program=true) {
308  std::cout << runner << " -opt [-opt] \n"
309  " -input <file> [OPTIONAL] Specify geometry input file. \n"
310  " -plugin <name> <args> [args] [-end-plugin] \n"
311  " [REQUIRED] Plugin to be executed and applied. \n"
312  " -plugin <name> <args> [args] -end-plugin \n"
313  " [OPTIONAL] Next plugin with arguments. \n";
314  print_default_args() << std::endl;
315  if ( exit_program ) ::exit(EINVAL);
316  }
317 
318  //______________________________________________________________________________
319  int invoke_plugin_runner(const char* name, int argc,char** argv) {
320  Args arguments;
321  arguments.interpreter = false;
322 
323  for( int i=1; i < argc; ++i ) {
324  if( argv[i][0]=='-' ) {
325  if ( arguments.handle(i,argc,argv) )
326  continue;
327  }
328  else {
330  }
331  }
332  if( !arguments.dry_run &&
333  !arguments.ui &&
334  !arguments.interpreter &&
335  arguments.plugins.empty() &&
336  arguments.geo_files.empty() )
337  {
339  }
340  if( arguments.help ) {
342  }
343  std::unique_ptr<TRint> interpreter;
344  dd4hep::Detector& description = dd4hep_instance();
345  // Load compact files if required by plugin
346  if( !arguments.geo_files.empty() ) {
347  load_compact(description, arguments);
348  }
349  else {
350  std::cout << "geoPluginRun: No geometry input supplied. "
351  << "No geometry will be loaded." << std::endl << std::flush;
352  }
353  // Attach UI instance if requested to ease interaction from the ROOT prompt
354  if( arguments.ui ) {
355  run_plugin(description,"DD4hep_InteractiveUI",0,0);
356  }
357  // Create volume manager and populate it required
358  if( arguments.volmgr ) {
359  run_plugin(description,"DD4hep_VolumeManager",0,0);
360  }
361  if( arguments.interpreter ) {
362  std::pair<int, char**> a(0,0);
363  interpreter.reset(new TRint("geoPluginRun", &a.first, a.second));
364  }
365  // Execute plugin
366  for( size_t i=0; i < arguments.plugins.size(); ++i ) {
367  std::vector<const char*>& plug = arguments.plugins[i];
368  int num_args = int(plug.size())-2;
369  TTimeStamp start;
370  char text[32];
371  long result = run_plugin(description, plug[0], num_args, (char**)&plug[1]);
372  TTimeStamp stop;
373  ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
374  if (result == EINVAL ) {
375  std::cout << "geoPluginRun: FAILED to execute dd4hep plugin: '" << plug[0]
376  << "' with args (" << num_args << ") :[ ";
377  for(size_t j = 1; j < plug.size(); ++j) {
378  if ( plug[j] ) std::cout << plug[j] << " ";
379  }
380  std::cout << "]" << std::endl;
382  }
383  std::cout << "geoPluginRun: " << text <<" Executed dd4hep plugin: '" << plug[0]
384  << "' with args (" << num_args << ") :[ ";
385  for( size_t j=1; j < plug.size(); ++j ) {
386  if ( plug[j] ) std::cout << plug[j] << " ";
387  }
388  std::cout << "]" << std::endl << std::flush;
389  }
390  if( arguments.plugins.empty() ) {
391  // Create an interactive ROOT application
392  if( !arguments.dry_run ) {
393  long result = 0;
394  std::pair<int, char**> a(0,0);
395  if( arguments.interpreter ) {
396  TRint app(name, &a.first, a.second);
397  result = arguments.run(description, name);
398  if( result != EINVAL ) app.Run();
399  }
400  else
401  result = arguments.run(description, name);
402  if( result == EINVAL ) usage_default(name);
403  }
404  else {
405  std::cout << "The geometry was loaded. Application now exiting." << std::endl;
406  }
407  }
408  if ( !arguments.dry_run && interpreter.get() ) {
409  interpreter->Run();
410  }
411  try {
412  if ( arguments.destroy ) description.destroyInstance();
413  }
414  catch(const std::exception& e) {
415  dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
416  throw;
417  }
418  catch (...) {
419  dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
420  throw;
421  }
422  return 0;
423  }
424 
426  int main_plugins(const char* name, int argc, char** argv) {
427  try {
428  return invoke_plugin_runner(name, argc, argv);
429  }
430  catch(const std::exception& e) {
431  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
432  }
433  catch (...) {
434  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
435  }
436  return EINVAL;
437  }
438 
439  //______________________________________________________________________________
440  int main_default(const char* name, int argc, char** argv) {
441  try {
442  return main_wrapper(name,argc,argv);
443  }
444  catch(const std::exception& e) {
445  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
446  }
447  catch (...) {
448  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
449  }
450  return EINVAL;
451  }
452  }
453 }
454 
455 #endif
v
View * v
Definition: MultiView.cpp:28
Detector.h
dd4hep::exception
void exception(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:69
dd4hep::execute::main_default
int main_default(const char *name, int argc, char **argv)
Definition: run_plugin.h:440
help
void help(std::string argv0)
Definition: listcomponents.cpp:29
dd4hep::execute::main_wrapper
int main_wrapper(const char *name, int argc, char **argv)
Definition: run_plugin.h:252
dd4hep::Detector::getInstance
static Detector & getInstance(const std::string &name="default")
—Factory method----—
Definition: DetectorImp.cpp:150
dd4hep::Detector::apply
virtual long apply(const char *factory, int argc, char **argv) const =0
Manipulate geometry using factory converter.
dd4hep::execute::invoke_plugin_runner
int invoke_plugin_runner(const char *name, int argc, char **argv)
Definition: run_plugin.h:319
dd4hep::Detector::destroyInstance
static void destroyInstance(const std::string &name="default")
Destroy the singleton instance.
Definition: DetectorImp.cpp:162
dd4hep::execute::usage_plugin_runner
void usage_plugin_runner(const char *runner="geoPluginRun", bool exit_program=true)
Definition: run_plugin.h:307
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
dd4hep::execute::main_plugins
int main_plugins(const char *name, int argc, char **argv)
Main entry point as a program.
Definition: run_plugin.h:426
Printout.h
handle
void handle(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1104