DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
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;
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  ui = false;
132  volmgr = false;
133  dry_run = false;
134  destroy = false;
135  interpreter = true;
136  print = dd4hep::INFO;
137  }
138 
139  //____________________________________________________________________________
140  int handle(int& i, int argc, char** argv) {
141  if ( ::strncmp(argv[i],"-compact",5)==0 || ::strncmp(argv[i],"-input",4)==0 ) {
142  geo_files.emplace_back(argv[++i]);
143  if ( argc>i+2 && ::strncmp(argv[i+1],"-build_type",6)==0 ) {
144  build_types.emplace_back(argv[i+2]);
145  i += 2;
146  }
147  else {
148  build_types.emplace_back("BUILD_DEFAULT");
149  }
150  }
151  else if ( ::strncmp(argv[i],"-load_only",5)==0 )
152  dry_run = true;
153  else if ( ::strncmp(argv[i],"-dry-run",5)==0 )
154  dry_run = true;
155  else if ( ::strncmp(argv[i],"-print",4)==0 )
156  dd4hep::setPrintLevel(dd4hep::PrintLevel(print = dd4hep::decodePrintLevel(argv[++i])));
157  else if ( ::strncmp(argv[i],"-destroy",5)==0 )
158  destroy = true;
159  else if ( ::strncmp(argv[i],"-no-destroy",8)==0 )
160  destroy = false;
161  else if ( ::strncmp(argv[i],"-volmgr",4)==0 )
162  volmgr = true;
163  else if ( ::strncmp(argv[i],"-no-volmgr",7)==0 )
164  volmgr = false;
165  else if ( ::strncmp(argv[i],"-interpreter",6)==0 )
166  interpreter = true;
167  else if ( ::strncmp(argv[i],"-no-interpreter",7)==0 )
168  interpreter = false;
169  else if ( ::strncmp(argv[i],"-interactive",6)==0 )
170  interpreter = true;
171  else if ( ::strncmp(argv[i],"-no-interactive",7)==0 )
172  interpreter = false;
173  else if ( ::strncmp(argv[i],"-ui",3)==0 )
174  ui = true;
175  else if ( ::strncmp(argv[i],"-no-ui",6)==0 )
176  ui = false;
177  else if ( ::strncmp(argv[i],"-plugin",5)==0 ) {
178  // Need to interprete plugin args here locally.....
179  plugins.emplace_back(std::vector<const char*>());
180  plugins.back().emplace_back(argv[++i]);
181  for( ++i; i < argc; ++i ) {
182  if ( ::strncmp(argv[i],"-plugin",5)==0 ) { --i; break; }
183  if ( ::strncmp(argv[i],"-end-plugin",4)==0 ) { break; }
184  plugins.back().emplace_back(argv[i]);
185  }
186  plugins.back().emplace_back(nullptr);
187  }
188  else
189  return 0;
190  return 1;
191  }
192 
193  //____________________________________________________________________________
194  long run(dd4hep::Detector& description, const char* name) {
195  std::pair<int, char**> a(0,0);
196  long result;
197  for(size_t i=0; i<plugins.size(); ++i) {
198  std::vector<const char*>& plug = plugins[i];
199  // Remove plugin name and trailing 0x0 from args.
200  size_t num_args = plug.size()>2 ? plug.size()-2 : 0;
201  TTimeStamp start;
202  char text[32];
203  result = run_plugin(description,plug[0],plug.size()-1,(char**)(num_args>0 ? &plug[1] : 0));
204  TTimeStamp stop;
205  ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
206  if ( result == EINVAL ) {
207  std::cout << "FAILED to execute dd4hep plugin: '" << plug[0]
208  << "' with args (" << num_args << ") :[ ";
209  for( std::size_t j = 1; j < plug.size(); ++j ) {
210  if ( plug[j] ) std::cout << plug[j] << " ";
211  }
212  std::cout << "]" << std::endl << std::flush;
213  usage_default(name);
214  }
215  std::cout << "run_plugin: " << text << " Executed dd4hep plugin: '" << plug[0]
216  << "' with args (" << num_args << ") :[ ";
217  for( std::size_t j=1; j<plug.size(); ++j ) {
218  if ( plug[j] ) std::cout << plug[j] << " ";
219  }
220  std::cout << "]" << std::endl << std::flush;
221  }
222  if ( name && name[0] ) {
223  result = run_plugin(description, name, a.first, a.second);
224  return result;
225  }
226  std::cout << "WARNING: run_plugin: No plugin name supplied. "
227  << "Implicitly assuming execution steered by XML." << std::endl;
228  return ENOENT;
229  }
230  };
231 
232  //______________________________________________________________________________
233  void load_compact(dd4hep::Detector& description, Args& args) {
234  // Load all compact files
235  for( std::size_t i=0; i<args.geo_files.size(); ++i ) {
236  const char* argv[] = { args.geo_files[i], args.build_types[i], 0 };
237  run_plugin(description,"DD4hep_CompactLoader",2,(char**)argv);
238  }
239  }
240 }
241 
242 
243 namespace dd4hep {
244  namespace execute {
245 
246  //______________________________________________________________________________
247  int main_wrapper(const char* name, int argc, char** argv) {
248  Args args;
249  for( int i=1; i<argc;++i ) {
250  if ( argv[i][0]=='-' ) {
251  if ( args.handle(i, argc, argv) )
252  continue;
253  else
254  usage_default(name);
255  }
256  else { // This is the default
257  args.geo_files.emplace_back(argv[i]);
258  args.build_types.emplace_back("BUILD_DEFAULT");
259  }
260  }
261  if ( args.geo_files.empty() )
262  usage_default(name);
263 
264  dd4hep::Detector& description = dd4hep_instance();
265  // Load all compact files
266  load_compact(description, args);
267  if ( args.ui ) run_plugin(description,"DD4hep_InteractiveUI",0,0);
268  // Create volume manager and populate it required
269  if ( args.volmgr ) run_plugin(description,"DD4hep_VolumeManager",0,0);
270 
271  // Create an interactive ROOT application
272  if ( !args.dry_run ) {
273  long result = 0;
274  std::pair<int, char**> a(0,0);
275  if ( args.interpreter ) {
276  TRint app(name, &a.first, a.second);
277  result = args.run(description, name);
278  if ( result != EINVAL ) app.Run();
279  }
280  else {
281  result = args.run(description, name);
282  }
283  if ( result == EINVAL ) usage_default(name);
284  }
285  else {
286  dd4hep::printout(INFO,"Application","The geometry was loaded. Application now exiting.");
287  }
288  try {
289  if ( args.destroy ) description.destroyInstance();
290  }
291  catch(const std::exception& e) {
292  dd4hep::printout(ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
293  throw;
294  }
295  catch (...) {
296  dd4hep::printout(ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
297  throw;
298  }
299  return 0;
300  }
301 
302  void usage_plugin_runner(const char* runner="geoPluginRun", bool exit_program=true) {
303  std::cout << runner << " -opt [-opt] \n"
304  " -input <file> [OPTIONAL] Specify geometry input file. \n"
305  " -plugin <name> <args> [args] [-end-plugin] \n"
306  " [REQUIRED] Plugin to be executed and applied. \n"
307  " -plugin <name> <args> [args] -end-plugin \n"
308  " [OPTIONAL] Next plugin with arguments. \n";
309  print_default_args() << std::endl;
310  if ( exit_program ) ::exit(EINVAL);
311  }
312 
313  //______________________________________________________________________________
314  int invoke_plugin_runner(const char* name, int argc,char** argv) {
315  Args arguments;
316  arguments.interpreter = false;
317 
318  for(int i=1; i<argc;++i) {
319  if ( argv[i][0]=='-' ) {
320  if ( arguments.handle(i,argc,argv) )
321  continue;
322  }
323  else {
325  }
326  }
327  if ( !arguments.dry_run &&
328  !arguments.ui &&
329  !arguments.interpreter &&
330  arguments.plugins.empty() &&
331  arguments.geo_files.empty() )
332  {
334  }
335  std::unique_ptr<TRint> interpreter;
336  dd4hep::Detector& description = dd4hep_instance();
337  // Load compact files if required by plugin
338  if ( !arguments.geo_files.empty() ) {
339  load_compact(description, arguments);
340  }
341  else {
342  std::cout << "geoPluginRun: No geometry input supplied. "
343  << "No geometry will be loaded." << std::endl << std::flush;
344  }
345  // Attach UI instance if requested to ease interaction from the ROOT prompt
346  if ( arguments.ui ) {
347  run_plugin(description,"DD4hep_InteractiveUI",0,0);
348  }
349  // Create volume manager and populate it required
350  if ( arguments.volmgr ) {
351  run_plugin(description,"DD4hep_VolumeManager",0,0);
352  }
353  if ( arguments.interpreter ) {
354  std::pair<int, char**> a(0,0);
355  interpreter.reset(new TRint("geoPluginRun", &a.first, a.second));
356  }
357  // Execute plugin
358  for(size_t i=0; i<arguments.plugins.size(); ++i) {
359  std::vector<const char*>& plug = arguments.plugins[i];
360  int num_args = int(plug.size())-2;
361  TTimeStamp start;
362  char text[32];
363  long result = run_plugin(description, plug[0], num_args, (char**)&plug[1]);
364  TTimeStamp stop;
365  ::snprintf(text,sizeof(text),"[%8.3f sec]",stop.AsDouble()-start.AsDouble());
366  if ( result == EINVAL ) {
367  std::cout << "geoPluginRun: FAILED to execute dd4hep plugin: '" << plug[0]
368  << "' with args (" << num_args << ") :[ ";
369  for(size_t j = 1; j < plug.size(); ++j) {
370  if ( plug[j] ) std::cout << plug[j] << " ";
371  }
372  std::cout << "]" << std::endl;
374  }
375  std::cout << "geoPluginRun: " << text <<" Executed 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 << std::flush;
381  }
382  if ( arguments.plugins.empty() ) {
383  // Create an interactive ROOT application
384  if ( !arguments.dry_run ) {
385  long result = 0;
386  std::pair<int, char**> a(0,0);
387  if ( arguments.interpreter ) {
388  TRint app(name, &a.first, a.second);
389  result = arguments.run(description, name);
390  if ( result != EINVAL ) app.Run();
391  }
392  else
393  result = arguments.run(description, name);
394  if ( result == EINVAL ) usage_default(name);
395  }
396  else {
397  std::cout << "The geometry was loaded. Application now exiting." << std::endl;
398  }
399  }
400  if ( !arguments.dry_run && interpreter.get() ) {
401  interpreter->Run();
402  }
403  try {
404  if ( arguments.destroy ) description.destroyInstance();
405  }
406  catch(const std::exception& e) {
407  dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: Uncaught exception: %s",e.what());
408  throw;
409  }
410  catch (...) {
411  dd4hep::printout(dd4hep::ERROR,"Application","destroyInstance: UNKNOWN uncaught exception.");
412  throw;
413  }
414  return 0;
415  }
416 
418  int main_plugins(const char* name, int argc, char** argv) {
419  try {
420  return invoke_plugin_runner(name, argc, argv);
421  }
422  catch(const std::exception& e) {
423  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
424  }
425  catch (...) {
426  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
427  }
428  return EINVAL;
429  }
430 
431  //______________________________________________________________________________
432  int main_default(const char* name, int argc, char** argv) {
433  try {
434  return main_wrapper(name,argc,argv);
435  }
436  catch(const std::exception& e) {
437  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: Uncaught exception: %s",e.what());
438  }
439  catch (...) {
440  dd4hep::printout(dd4hep::ERROR,"Application","geoPluginRun: UNKNOWN uncaught exception.");
441  }
442  return EINVAL;
443  }
444  }
445 }
446 
447 #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:432
dd4hep::execute::main_wrapper
int main_wrapper(const char *name, int argc, char **argv)
Definition: run_plugin.h:247
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:314
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:302
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:418
Printout.h
handle
void handle(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1105