-
Sergei Zharko authoredSergei Zharko authored
Options.cxx 7.41 KiB
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#include "Options.h"
#include "util/StlUtils.h"
#include <boost/program_options.hpp>
#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace cbm::algo;
namespace po = boost::program_options;
using fles::Subsystem;
namespace std
{
template<class T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
copy(v.begin(), v.end(), std::ostream_iterator<T>(os, " "));
return os;
}
} // namespace std
#ifndef CBM_ONLINE_USE_FAIRLOGGER
void validate(boost::any& v, const std::vector<std::string>& values, severity_level*, int)
{
static const std::unordered_map<std::string, severity_level> levels{
{"trace", severity_level::trace}, {"debug", severity_level::debug}, {"status", severity_level::status},
{"info", severity_level::info}, {"warning", severity_level::warning}, {"error", severity_level::error},
{"fatal", severity_level::fatal}};
po::validators::check_first_occurrence(v);
const std::string& s = po::validators::get_single_string(values);
auto it = levels.find(s);
if (it == levels.end()) throw po::validation_error(po::validation_error::invalid_option_value);
v = it->second;
}
#endif // Not CBM_ONLINE_USE_FAIRLOGGER
Options::Options(int argc, char** argv)
{
po::options_description required("Required options");
// clang-format off
required.add_options()
("param-dir,p", po::value(&fParamsDir)->value_name("<folder>")->required(),
"read program options from this folder")
("input-locator,i", po::value(&fInputLocator)->value_name("<locator>")->required(),
"URI specifying input timeslice source")
;
// clang-format on
po::options_description generic("Other options");
// clang-format off
generic.add_options()
("output,o", po::value(&fOutputFile)->default_value("")->value_name("<file>"),
"write results to file")
("device,d", po::value(&fDevice)->default_value("cpu")->value_name("<device>"),
"select device (cpu, cuda0, cuda1, hip0, ...)")
#ifndef CBM_ONLINE_USE_FAIRLOGGER
("log-level,l", po::value(&fLogLevel)->default_value(info)->value_name("<level>"),
"set log level (debug, info, warning, error, fatal)")
#endif // Not CBM_ONLINE_USE_FAIRLOGGER
("monitor,m", po::value(&fMonitorUri)->value_name("<uri>")->implicit_value("file:cout"),
"URI specifying monitor output (e.g. file:/tmp/monitor.txt, influx1:login:8086:cbmreco_status). Prints to cout when no argument is given. Monitor is disabled when flag is not set.")
("histogram", po::value(&fHistogramUri)->value_name("<uri>"), "URI to specify histogram server")
("histoshwm", po::value(&fHistogramHwm)->default_value(1)->value_name("<num>"),
"High-Water Mark for ZMQ socket to histogram server in messages:\n"
" 0 = no buffering, num = nb updates kept in buffer if not pulled by server \n"
" Tune to avoid too high memory usage but also adapt to server load!")
("aux-data", po::value(&fCollectAuxData)->implicit_value(true), "Enables collecting of auxiliary data from algorithms")
("qa", po::value(&fQaSteps)->multitoken()->default_value({QaStep::UnpackSts, QaStep::EventBuilding, QaStep::Tracking})->value_name("<qa steps>"),
"space separated list of QA Steps to enable (BeamBmon, UnpackSts, EventBuilding, Tracking, ...)")
#ifdef BOOST_IOS_HAS_ZSTD
("hist-compr", po::bool_switch(&fCompressHistograms)->default_value(false),
"enables ZSTD compression of the outgoing histograms stream (decompression needed in target server!)")
#endif
("log-file,L", po::value(&fLogFile)->value_name("<file>"),
"write log messages to file")
("output-types,O", po::value(&fOutputTypes)->multitoken()->value_name("<types>"),
"space separated list of reconstruction output types (Hit, Tracks, DigiTimeslice, DigiEvent, ...)")
("compress-archive", po::bool_switch(&fCompressArchive)->default_value(false), "Enable compression for output archives")
("steps", po::value(&fRecoSteps)->multitoken()->default_value({Step::Unpack, Step::DigiTrigger, Step::LocalReco, Step::Tracking})->value_name("<steps>"),
"space separated list of reconstruction steps (unpack, digitrigger, localreco, ...)")
("event-reco", po::bool_switch(&fReconstructDigiEvents)->default_value(false), "runs digi event reconstruction (local reco, tracking, trigger)")
("systems,s", po::value(&fDetectors)->multitoken()->default_value({Subsystem::STS, Subsystem::TOF, Subsystem::BMON, Subsystem::MUCH, Subsystem::RICH, Subsystem::TRD, Subsystem::TRD2D})->value_name("<detectors>"),
"space separated list of detectors to process (sts, mvd, ...)")
("child-id,c", po::value(&fChildId)->default_value("00")->value_name("<id>"), "online process id on node")
("run-id,r", po::value(&fRunId)->default_value(2391)->value_name("<RunId>"), "Run ID, for now flesctl run index, later run start time")
("run-start", po::value(&fRunStartTime)->default_value(0)->value_name("<RunStart >"), "Run start time in ns, can be fles start or online start")
("num-ts,n", po::value(&fNumTimeslices)->default_value(-1)->value_name("<num>"),
"Stop after <num> timeslices (-1 = all)")
("skip-ts", po::value(&fSkipTimeslices)->default_value(0)->value_name("<num>"),
"Skip first <num> timeslices")
("omp", po::value(&fNumOMPThreads)->default_value(-1)->value_name("<num>"),
"Set number of OpenMP threads (-1 = use OMP_NUM_THREADS environment variable)")
("times,t", po::value(&fProfilingLevel)->default_value(ProfilingNone)->implicit_value(ProfilingPerTS),
"Print kernel times (Can opt. be given a value: Use none to disable or summary to only print aggregated times.)")
("timings-file", po::value(&fTimingsFile)->value_name("<file>"),
"Write profiling times to yaml file (only when '-t' is set)")
("dump-archive", po::bool_switch(&fDumpArchive)->default_value(false),
"Dump archive content to stdout and exit. Provide archive with '-i'. (This is a hack to quick check archive content until we have proper tooling.)")
("release-mode,R",po::value<bool>(&fReleaseMode)->implicit_value(true),
"Copy and release each timeslice immediately after receiving it")
("help,h",
"produce help message")
;
// clang-format on
po::options_description cmdline_options;
cmdline_options.add(required).add(generic);
po::variables_map vm;
po::command_line_parser parser{argc, argv};
parser.options(cmdline_options);
try {
auto result = parser.run();
po::store(result, vm);
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
std::cerr << "Use '-h' to display all valid options." << std::endl;
std::exit(EXIT_FAILURE);
}
if (vm.count("help") > 0) {
std::cout << cmdline_options << std::endl;
std::exit(EXIT_SUCCESS);
}
try {
po::notify(vm);
}
catch (const po::required_option& e) {
std::cerr << "Error: " << e.what() << std::endl;
std::cerr << "Use '-h' to display all valid options." << std::endl;
std::exit(EXIT_FAILURE);
}
}
bool Options::HasOutput(RecoData recoData) const { return Contains(fOutputTypes, recoData); }
bool Options::Has(fles::Subsystem detector) const { return Contains(fDetectors, detector); }
bool Options::Has(Step step) const { return Contains(fRecoSteps, step); }
bool Options::Has(QaStep qastep) const { return Contains(fQaSteps, qastep); }