SLIC  6.1.1
Simulation for the Linear Collider (SLIC) - Geant4 simulation application
CommandLineProcessor.cc
Go to the documentation of this file.
1 // $Id: CommandLineProcessor.cc,v 1.14 2012-11-27 19:32:19 jeremy Exp $
2 
4 
5 // SLIC
6 #include "PackageInfo.hh"
7 #include "CommandQueue.hh"
8 #include "CommandLineOption.hh"
9 
10 // getopt
11 #include "getopt.h"
12 
13 // STL
14 #include <sstream>
15 #include <cassert>
16 
17 using std::stringstream;
18 using std::left;
19 
20 namespace slic {
22  Module("CommandLineProcessor"), m_help_flag(0), m_interactive_flag(0), m_version_flag(0) {
25 }
26 
28 }
29 
30 void CommandLineProcessor::process(int argc, char** argv) {
31 
32  // Description of SLIC's options in getopt's format.
33  static struct option long_options[] = {
34  { "help", no_argument, 0, 'h' },
35  { "help", no_argument, 0, '?' },
36  { "version", no_argument, 0, 'v' },
37  { "interactive", no_argument, 0, 'n' },
38  { "macro", required_argument, 0, 'm' },
39  { "event-file", required_argument, 0, 'i' },
40  { "lcdd-url", required_argument, 0, 'g' },
41  { "lcio-file", required_argument, 0, 'o' },
42  { "lcio-path", required_argument, 0, 'p' },
43  { "autoname", optional_argument, 0, 'O' },
44  { "lcio-delete", no_argument, 0, 'x' },
45  { "run-events", required_argument, 0, 'r' },
46  { "skip-events", required_argument, 0, 's' },
47  { "physics-list", required_argument, 0, 'l' },
48  { "log-file", required_argument, 0, 'L' },
49  { "seed", required_argument, 0, 'd' },
50  { "dump-gdml", required_argument, 0, 'G' },
51  { "optical", no_argument, 0, 'c' },
52  { "pdg-file", required_argument, 0, 'P' },
53  { "lcdd-version", required_argument, 0, 'V' },
54  { "lcdd-setup", required_argument, 0, 'S' },
55  { "quiet", no_argument, 0, 'q' },
56  { 0, 0, 0, 0 }
57  };
58 
59  const char* optstr = m_getoptOptions.c_str();
60 
61  while (1) {
62  int option_index = 0;
63  int c;
64 
65  // Call getopt for next option.
66  c = getopt_long(argc, argv, optstr, long_options, &option_index);
67 
68 #ifdef SLIC_LOG
69  log() << LOG::verbose << "Handling option <" << c << ">." << LOG::done;
70 #endif
71 
72  // Done.
73  if (c == -1)
74  break;
75 
76  // Handle options.
77  switch (c) {
78 
79  case 'h':
80  m_help_flag = 1;
81  break;
82 
83  case '?':
84  m_help_flag = 1;
85  break;
86 
87  case 'n':
89  break;
90 
91  case 'v':
92  m_version_flag = 1;
93  break;
94 
95  default:
96 
97  stringstream ostr;
98  char cc = (char) c;
99  ostr << cc;
100  string theopt = ostr.str();
101  if (optarg) {
102  m_commandline.push_back(OptionsPair(theopt, optarg));
103  } else {
104  m_commandline.push_back(OptionsPair(theopt, ""));
105  }
106 
107  break;
108  }
109  }
110 
111  //
112  // The processing flow...
113  //
114  // 1) If version flag is set, print version and exit.
115  //
116  // 2) If usage flag is set or no arguments were received,
117  // print the usage and exit.
118  //
119  // 3) If a single non-option command was received, treat
120  // it as a macro to execute.
121  //
122  // 4) If no options were received or the number of options
123  // is less than the number of arguments, print usage
124  // and exit (syntax incorrect).
125  //
126  // 5) Finally, process the options in order if the syntax
127  // appears to be okay.
128  //
129 
130  // Print the version information and abort.
131  if (m_version_flag) {
132  printVersion();
133  abort();
134  }
135  // Print the usage and abort if the help flag is set
136  // or no arguments were received.
137  else if (m_help_flag || argc == 1) {
138  printUsage();
139  abort();
140  }
141  // Single macro to execute, if got 1 argument that is a non-option.
142  else if (argc == 2 && optind < argc) {
143  stringstream str;
144  str << "/control/execute ";
145  str << argv[1];
146  m_g4q.add(str.str());
147  }
148  // Probably extra arguments or no options.
149  else if (optind == 1 || optind < argc) {
150  printUsage();
151  abort();
152  }
153  // Default is process all the options and build the CommandQueue.
154  else {
155  processOptions();
156  }
157 }
158 
160  printVersion();
161 
162  log() << LOG::okay << LOG::done;
163  log() << LOG::okay << "**************" << LOG::done;
164  log() << LOG::okay << "* SLIC Usage *" << LOG::done;
165  log() << LOG::okay << "**************" << LOG::done;
166 
167  log() << LOG::okay << LOG::done;
168  log() << LOG::okay << "Command line usage: " << LOG::done;
169  log() << LOG::okay << LOG::done;
170  log() << LOG::okay << "slic [single_macro_path]" << LOG::done;
171  log() << LOG::okay << "slic [options]" << LOG::done;
172 
173  log() << LOG::okay << LOG::done;
174 
175  log() << LOG::okay << "Interactive usage: " << LOG::done;
176  log() << LOG::okay << LOG::done;
177  log() << LOG::okay << "slic -n" << LOG::done;
178 
179  log() << LOG::okay << LOG::done;
180 
181  printOptions();
182 
183  log() << LOG::okay << LOG::done;
184 }
185 
187  exit(0);
188 }
189 
191 
192  // Print application usage.
193  addOption(new CommandLineOption("h", "help", "Print SLIC usage.", 0, 0, "/slic/usage"));
194 
195  // Usage is also activated with the '?' switch.
196  addOption(new CommandLineOption("?", "help", "Print SLIC usage.", 0, 0, "/slic/usage"));
197 
198  // Run in interactive mode.
199  addOption(new CommandLineOption("n", "interactive", "Start a Geant4 interactive session.", 0, 0, "/control/interactive"));
200 
201  // Print SLIC version info.
202  addOption(new CommandLineOption("v", "version", "Print SLIC version.", 0, 0, "/slic/version"));
203 
204  // Execute the commands from a macro file.
205  addOption(new CommandLineOption("m", "macro", "Execute Geant4 commands from a file.", 1, 1, "/control/execute"));
206 
207  // Set the URL of the input LCDD file.
208  addOption(new CommandLineOption("g", "lcdd-url", "Set LCDD geometry file URL.", 1, 1, "/lcdd/url"));
209 
210  // Set the path to a generator file, e.g. StdHep or LCIO.
211  addOption(new CommandLineOption("i", "event-file", "Set event input file full path.", 1, 1, "/generator/filename"));
212 
213  // Set the name of the LCIO output file.
214  addOption(new CommandLineOption("o", "lcio-file", "Set name of LCIO output file.", 1, 1, "/lcio/filename"));
215 
216  // Set the path of output files.
217  addOption(new CommandLineOption("p", "lcio-path", "Set directory for LCIO output.", 1, 1, "/lcio/path"));
218 
219  // Automatically name the LCIO output file.
220  addOption(new CommandLineOption("O", "autoname", "Automatically name the LCIO output file.", 0, 1, "/lcio/autoname"));
221 
222  // Overwrite an existing LCIO output file.
223  addOption(
224  new CommandLineOption("x", "lcio-delete", "Delete an existing LCIO file.", 0, 0,
225  "/lcio/fileExists delete"));
226 
227  // Number of events to run.
228  addOption(new CommandLineOption("r", "run-events", "Run # of events.", 1, 1, "/run/beamOn"));
229 
230  // Set number of events to skip from a file-based event source (e.g. StdHep).
231  addOption(new CommandLineOption("s", "skip-events", "Set number of events to skip.", 1, 1, "/generator/skipEvents"));
232 
233  // Set the physics list.
234  addOption(new CommandLineOption("l", "physics-list", "Set Geant4 physics list.", 1, 1, "/physics/select"));
235 
236  // Set the name of the log file.
237  addOption(new CommandLineOption("L", "log-file", "Set logfile name.", 0, 0, "/log/filename"));
238 
239  // Set the random seed.
240  addOption(new CommandLineOption("d", "seed", "Set the random seed. (No argument seeds with time.)", 0, 1, "/random/seed"));
241 
242  // Dump the loaded Geant4 geometry to a GDML file.
243  addOption(new CommandLineOption("G", "dump-gdml", "Dump geometry to GDML file.", 1, 1, "/lcdd/dumpGDML"));
244 
245  // Enable optical physics processes.
246  addOption(new CommandLineOption("c", "optical", "Enable optical physics processes.", 0, 0, "/physics/enableOptical"));
247 
248  // Set location of particle.tbl.
249  addOption(new CommandLineOption("P", "pdg-file", "Set location of particle.tbl file.", 1, 1, "/physics/setPDGFile"));
250 
251  // Set the version of the GDML setup.
252  addOption(new CommandLineOption("V", "lcdd-version", "Set the version of the GDML setup tag.", 1, 1, "/lcdd/version"));
253 
254  // Set the name of the GMDL setup.
255  addOption(new CommandLineOption("S", "lcdd-setup", "Set the name of the GDML setup tag.", 1, 1, "/lcdd/setupName"));
256 
257  // Activate quiet mode which suppresses stdout in the job.
258  addOption(new CommandLineOption("q", "quiet", "Quiet mode.", 0, 0, "/slic/quiet"));
259 
260 }
261 
262 void CommandLineProcessor::processOption(const string& opt) {
263 
264  // Loop over all input arguments to look for this option.
265  for (CommandLineArguments::iterator it = m_commandline.begin(); it != m_commandline.end(); it++) {
266 
267 
268  // Look for a matching switch in the arguments.
269  if (it->first == opt) {
270 
271  // Get the associated specification for this option.
272  CommandLineOption* cmdlineopt = getCommandLineOption(opt);
273 
274  // We must have a valid option!
275  assert(cmdlineopt != 0);
276 
277  // Get the associated Geant4 command string.
278  string cmdstr = cmdlineopt->getG4CommandString();
279 
280  // Add arguments to the command string, if some were passed.
281  if (it->second != "") {
282  cmdstr += " ";
283  cmdstr += it->second;
284  }
285 
286  // Add the command string to the CommandQueue.
287  m_g4q.add(cmdstr);
288  }
289  }
290 }
291 
293  m_cmds.push_back(opt);
294 }
295 
297 
298  // Quiet mode
299  processOption("q");
300 
301  // Logger.
302  processOption("L");
303 
304  // GDML file version in setup tag.
305  processOption("V");
306 
307  // GDML name in setup tag.
308  processOption("S");
309 
310  // Geometry file.
311  processOption("g");
312 
313  // Optical processes.
314  processOption("c");
315 
316  // SUSY data.
317  processOption("P");
318 
319  // Physics list.
320  processOption("l");
321 
322  // Add initialization after geometry and physics,
323  // but only if there was a geometry file argument.
324  // Otherwise, initialize is not called, and the
325  // user is given the PreInit prompt.
326  if (hasOption("g")) {
327  m_g4q.add("/run/initialize");
328  }
329 
330  // Dump gdml.
331  processOption("G");
332 
333  // Random seed.
334  processOption("d");
335 
336  // Event file.
337  processOption("i");
338 
339  // Output path.
340  processOption("p");
341 
342  // Delete existing LCIO file.
343  processOption("x");
344 
345  // Set LCIO file name.
346  processOption("o");
347 
348  // Autoname the LCIO file.
349  processOption("O");
350 
351  // Events to skip.
352  processOption("s");
353 
354  // Geant4 macro to run.
355  processOption("m");
356 
357  // Events to run.
358  processOption("r");
359 
360  // Interactive mode, if selected.
361  if (m_interactive_flag) {
362  m_g4q.add("/control/interactive");
363  }
364 }
365 
367  log() << LOG::okay << "************************" << LOG::done;
368  log() << LOG::okay << "* Command Line Options *" << LOG::done;
369  log() << LOG::okay << "************************" << LOG::done;
370  log() << LOG::okay << LOG::done;
371 
372  static const int opt_width = 8;
373  static const int descr_width = 15;
374  static const int name_width = 16;
375  static const int cmd_width = 24;
376  static const int sep_width = 60;
377 
378  log().getOutputStream().width(opt_width);
379  log().getOutputStream() << left;
380 
381  log().getOutputStream() << left;
382  log() << LOG::okay << "Option";
383 
384  log().getOutputStream().width(name_width);
385  log().getOutputStream() << left;
386  log() << LOG::okay << "Full Name";
387 
388  log().getOutputStream().width(cmd_width);
389  log().getOutputStream() << left;
390  log() << LOG::okay << "Macro Command";
391 
392  log().getOutputStream().width(descr_width);
393  log().getOutputStream() << left;
394  log() << LOG::okay << "Description";
395 
396  log().getOutputStream().fill('-');
397  log().getOutputStream().width(sep_width);
398 
399  log() << LOG::okay << LOG::done;
400  log() << LOG::okay << '-' << LOG::done;
401 
402  log().getOutputStream().fill(' ');
403 
404  for (OptionsList::const_iterator iter = m_cmds.begin(); iter != m_cmds.end(); iter++) {
405  CommandLineOption* cl_opt = (*iter);
406 
407  std::string opt_str = "-" + cl_opt->getShortName();
408  log().getOutputStream().width(opt_width);
409  log().getOutputStream() << left;
410  log() << LOG::okay << opt_str;
411 
412  std::string name_str = "--" + cl_opt->getLongName();
413  log().getOutputStream().width(name_width);
414  log().getOutputStream() << left;
415  log() << LOG::okay << name_str;
416 
417  log().getOutputStream().width(cmd_width);
418  log().getOutputStream() << left;
419  log() << LOG::okay << cl_opt->getG4CommandString();
420 
421  log().getOutputStream().width(descr_width);
422  log().getOutputStream() << left;
423  log() << LOG::okay << cl_opt->getDescription();
424 
425  log() << LOG::okay << LOG::done;
426  }
427 }
428 
430  CommandLineOption* clo = 0;
431  for (OptionsList::const_iterator iter = m_cmds.begin(); iter != m_cmds.end(); iter++) {
432  if ((*iter)->getShortName() == opt) {
433  clo = (*iter);
434  break;
435  }
436  }
437  return clo;
438 }
439 
440 bool CommandLineProcessor::hasOption(const std::string& opt) {
441  bool hasoption = false;
442  for (CommandLineArguments::iterator it = m_commandline.begin(); it != m_commandline.end(); it++) {
443  if ((*it).first == opt) {
444  hasoption = true;
445  break;
446  }
447  }
448  return hasoption;
449 }
450 
452  m_getoptOptions = "";
453  for (OptionsList::iterator it = m_cmds.begin(); it != m_cmds.end(); it++) {
454  CommandLineOption* opt = *it;
455  m_getoptOptions += opt->getShortName();
456  if (opt->getMinArgs()) {
457  m_getoptOptions += ":";
458  } else if (opt->getMaxArgs()) {
459  m_getoptOptions += "::";
460  }
461  }
462 }
463 } // namespace slic
Command-line option with a single letter, full name and description plus an associated Geant4 command...
unsigned int getMaxArgs() const
const std::string & getDescription() const
unsigned int getMinArgs() const
const std::string & getLongName() const
const std::string & getShortName() const
const std::string & getG4CommandString() const
CommandLineOption * getCommandLineOption(const std::string &option)
void processOption(const std::string &option)
CommandLineArguments m_commandline
void process(int argc, char **argv)
void addOption(CommandLineOption *option)
bool hasOption(const std::string &option)
std::pair< std::string, std::string > OptionsPair
void add(const CommandType &command)
Definition: CommandQueue.hh:44
ostream & getOutputStream() const
Definition: LogStream.hh:143
Base class for slic code modules that provides common functionality, such as logging to an output str...
Definition: Module.hh:25
LogStream & log()
Definition: Module.hh:99
@ okay
Definition: LogStream.hh:33
@ verbose
Definition: LogStream.hh:33
@ done
Definition: LogStream.hh:26