MARLEY (Model of Argon Reaction Low Energy Yields) v2.0.0
A Monte Carlo event generator for tens-of-MeV neutrino interactions
Loading...
Searching...
No Matches
CommandHandler.cc
1
4//
5// This file is part of MARLEY (Model of Argon Reaction Low Energy Yields)
6//
7// MARLEY is free software: you can redistribute it and/or modify it under the
8// terms of version 3 of the GNU General Public License as published by the
9// Free Software Foundation.
10//
11// For the full text of the license please see COPYING or
12// visit http://opensource.org/licenses/GPL-3.0
13//
14// Please respect the MCnet academic usage guidelines. See GUIDELINES
15// or visit https://www.montecarlonet.org/GUIDELINES for details.
16
17// Standard library includes
18#include <iomanip>
19#include <iostream>
20
21// MARLEY includes
22#include "marley/CommandHandler.hh"
23#include "marley/Logger.hh"
24#include "marley/marley_utils.hh"
25
26namespace {
27
28 bool print_version( const std::deque< std::string >& /*dummy*/ ) {
29 std::cout << "MARLEY (Model of Argon Reaction Low Energy Yields) "
30 << MARLEY_VERSION << '\n';
31 std::cout << "Copyright (C) 2016-2026 Steven Gardiner\n";
32 std::cout << "License: GNU GPL version 3 "
33 << "<http://opensource.org/licenses/GPL-3.0>\n";
34 std::cout << "This is free software: you are free to change and"
35 << " redistribute it.\n";
36 return true;
37 }
38
39 void print_generate_help() {
40 std::cout << "Usage: marley generate CONFIG_FILE\n\n"
41 << "Simulate neutrino interaction events according to the\n"
42 << "settings in CONFIG_FILE.\n\n"
43 << "This is the default command: 'marley CONFIG_FILE' is equivalent to\n"
44 << "'marley generate CONFIG_FILE'.\n\n"
45 << "Options:\n"
46 << " -h, --help Print this help message\n";
47 }
48
49 void print_print_help() {
50 std::cout << "Usage: marley print [FORMAT] INPUT_FILES...\n\n"
51 << "Print events from one or more MARLEY output files.\n\n"
52 << " FORMAT Optional output format selector:\n"
53 << " pretty (default): human-readable event history\n"
54 << " hepmc3: text representation of HepMC3\n"
55 << " legacy: MARLEY v1 legacy event summary\n\n"
56 << "Options:\n"
57 << " -h, --help Print this help message\n";
58 }
59
60 void print_reweight_help() {
61 std::cout << "Usage: marley reweight CONFIG_FILE INPUT_FILE...\n\n"
62 << "Reweight previously generated MARLEY events in one or more INPUT_FILEs"
63 << " using the\n"
64 << "weight-calculation settings in CONFIG_FILE.\n\n"
65 << "Options:\n"
66 << " -h, --help Print this help message\n";
67 }
68
69 void print_xsec_help() {
70 std::cout << "Usage: marley xsec -o OUTPUT_FILE CONFIG_FILE\n\n"
71 << "Tabulate the total cross section versus projectile kinetic energy\n"
72 << "using the settings in CONFIG_FILE. Write the results to"
73 << " OUTPUT_FILE.\n\n"
74 << " -o OUTPUT_FILE Required: path to the output file\n"
75 << " -f, --force Overwrite the output file without prompting\n\n"
76 << "Options:\n"
77 << " -h, --help Print this help message\n";
78 }
79
80 void print_decay_help() {
81 std::cout << "Usage: marley decay CONFIG_FILE\n\n"
82 << "Simulate stand-alone nuclear de-excitations according to the\n"
83 << "settings in CONFIG_FILE.\n\n"
84 << "Options:\n"
85 << " -h, --help Print this help message\n";
86 }
87
88 void print_summarize_help() {
89 std::cout << "Usage: marley summarize -o OUTPUT_FILE INPUT_FILE...\n\n"
90 << "Convert one or more MARLEY event files into a"
91 << " summary file containing\n"
92 << "a flat TTree suitable for analysis with ROOT.\n\n"
93 << " -o OUTPUT_FILE Required: path to the output ROOT file\n"
94 << " -f, --force Overwrite the output file without prompting\n\n"
95 << "Options:\n"
96 << " -h, --help Print this help message\n\n"
97 << "Note: this command requires a ROOT-enabled build of MARLEY.\n";
98 }
99
100 void print_help_command_help() {
101 std::cout << "Usage: marley help [COMMAND]\n\n"
102 << "Show the top-level help message or detailed help for COMMAND.\n\n"
103 << "Options:\n"
104 << " -h, --help Print this help message\n";
105 }
106
107 void print_version_command_help() {
108 std::cout << "Usage: marley version\n\n"
109 << "Print version information.\n";
110 }
111
112 void print_convert_help() {
113 std::cout << "Usage: marley convert [--output-format FORMAT]"
114 << " -o OUTPUT_FILE INPUT_FILES...\n\n"
115 << "Convert MARLEY event files between supported formats.\n\n"
116 << " -o OUTPUT_FILE Required: path to the output file\n"
117 << " --output-format FORMAT Output format. Supported values:\n"
118 << " \"ascii\" (default), \"root\",\n"
119 << " \"legacy\", \"hepevt\"\n"
120 << " -f, --force Overwrite the output file without"
121 << " prompting\n\n"
122 << "Options:\n"
123 << " -h, --help Print this help message\n\n"
124 << "Note: ROOT format conversions require a ROOT-enabled build"
125 << " of MARLEY.\n"
126 << "The \"legacy\" and \"hepevt\" formats are one-way conversions"
127 << " from the\n"
128 << "current HepMC3-based format to the deprecated output formats"
129 << " used in\n"
130 << "MARLEY v1.2.1 and earlier.\n";
131 }
132
133}
134
135const marley::CommandHandler::CommandMap
137{
138 { "generate", { "Generate Monte Carlo events",
139 print_generate_help, cmd_generate } },
140
141 { "print", { "Print existing events in a human-readable format",
142 print_print_help, cmd_print } },
143
144 { "reweight", { "Reweight previously generated events",
145 print_reweight_help, cmd_reweight } },
146
147 { "xsec", { "Tabulate total cross section vs. projectile kinetic energy",
148 print_xsec_help, cmd_xsec } },
149
150 { "decay", { "Simulate nuclear de-excitations",
151 print_decay_help, cmd_decay } },
152
153 { "summarize", { "Create a ROOT TTree summary of event files",
154 print_summarize_help, cmd_summarize, true } },
155
156 // ASCII-to-ASCII conversion does not need ROOT; ROOT I/O is
157 // guarded by runtime checks in the implementation.
158 { "convert", { "Convert event files between supported formats",
159 print_convert_help, cmd_convert, false } },
160
161 { "help", { "Show this help message or help for a specific command",
162 print_help_command_help, cmd_help } },
163
164 { "version", { "Print version information",
165 print_version_command_help, print_version } },
166};
167
169 std::cout << "Usage: marley <command> [options]\n\n"
170 << "Commands:\n";
171
172 for ( const auto& [name, info] : command_map_ ) {
173 std::cout << " " << std::left << std::setw(12) << name
174 << info.summary_;
175 if ( info.requires_root_ ) std::cout << " [requires ROOT]";
176 std::cout << '\n';
177 }
178
179 std::cout << "\nOptions:\n"
180 << " -h, --help Show top-level help\n"
181 << " -v, --version Print version information\n";
182 std::cout << "\nRun 'marley help <command>' or 'marley <command> --help' for"
183 << " details.\n"
184 << "MARLEY home page: <https://www.marleygen.org>\n";
185 return true;
186}
187
189
190 // If we don't have any command-line arguments, then just print the
191 // standard top-level help message
192 if ( cmds_.empty() ) {
193 return this->print_top_level_help();
194 }
195
196 // Otherwise, get the first argument which should correspond to a command
197 // or one of the top-level options
198 std::string subcmd = cmds_.front();
199
200 // Reassign some synonyms to their corresponding commands that appear in the
201 // map of accepted values
202 if ( subcmd == "--version" || subcmd == "-v" ) {
203 subcmd = "version";
204 }
205 else if ( subcmd == "--help" || subcmd == "-h" ) {
206 subcmd = "help";
207 }
208
209 auto cmd_iter = command_map_.find( subcmd );
210 if ( cmd_iter != command_map_.end() ) {
211 // The user provided an explicit command, so drop it from the
212 // deque before delegating to the appropriate function. We no longer need to
213 // resolve the command name.
214 cmds_.pop_front();
215 // Call the function corresponding to the chosen command
216 try {
217 return cmd_iter->second.cmd_( cmds_ );
218 } catch ( const std::exception& e ) {
219 // If we encountered an uncaught exception, log the error message
220 MARLEY_LOG( ERROR, "app" ) << std::flush << e.what();
221 return false;
222 }
223 }
224
225 // The 'marley' command is an easter egg that doesn't appear in the official
226 // list
227 if ( subcmd == "marley" ) {
228 std::cout << marley_utils::marley_pic;
229 return true;
230 }
231
232 // The default command is 'generate', so if the user didn't explicitly
233 // provide it and didn't use an option prefix, then assume that the user
234 // intended 'generate'
235 if ( !subcmd.empty() && subcmd[0] != '-' ) {
236 return this->cmd_generate( cmds_ );
237 }
238
239 std::cerr << "marley: unknown option '" << subcmd << "'\n";
240 std::cerr << "Run 'marley help' for a list of available commands.\n";
241 return false;
242}
243
244marley::CommandHandler::CommandHandler( int argc, char* argv[] )
245 // Build a deque of the command-line arguments for passing to commands
246 : cmds_( argv, argv + argc )
247{
248 // Strip the executable name off of the front of the deque
249 cmds_.pop_front();
250}
static bool print_top_level_help()
static const CommandMap command_map_
std::deque< std::string > cmds_
static bool cmd_generate(std::deque< std::string > &args)
Generate Monte Carlo events.