31 std::string defaultGeomList{
"ALICE2"};
32 if (isUpgrade ==
true) {
33 defaultGeomList =
"ALICE3";
36 int nsimworkersdefault = std::max(1u, std::thread::hardware_concurrency() / 2);
37 options.add_options()(
38 "mcEngine,e", bpo::value<std::string>()->default_value(
"TGeant4"),
"VMC backend to be used.")(
39 "generator,g", bpo::value<std::string>()->default_value(
"boxgen"),
"Event generator to be used.")(
40 "trigger,t", bpo::value<std::string>()->default_value(
""),
"Event generator trigger to be used.")(
41 "modules,m", bpo::value<std::vector<std::string>>()->multitoken()->default_value(std::vector<std::string>({
"all"}),
"all modules"),
"list of modules included in geometry")(
42 "skipModules", bpo::value<std::vector<std::string>>()->multitoken()->default_value(std::vector<std::string>({
""}),
""),
"list of modules excluded in geometry (precendence over -m")(
43 "readoutDetectors", bpo::value<std::vector<std::string>>()->multitoken()->default_value(std::vector<std::string>(),
""),
"list of detectors creating hits, all if not given; added to to active modules")(
44 "skipReadoutDetectors", bpo::value<std::vector<std::string>>()->multitoken()->default_value(std::vector<std::string>(),
""),
"list of detectors to skip hit creation (precendence over --readoutDetectors")(
45 "detectorList", bpo::value<std::string>()->default_value(defaultGeomList),
46 "Use a specific version of ALICE, e.g., a predefined list."
47 "There is an 'official' list provided with:"
48 "\nALICE2 : The default configuration for Run 3"
49 "\nALICE2.1: The future configuration for Run 4"
50 "\nALICE3 : The far-future configuration for Run 5-6"
51 "\nAdditionally one can provide their own custom list of modules which should be included in the geometry."
52 "\nBy specifiying LIST:JSONFILE where LIST is a list present in JSONFILE.")(
53 "nEvents,n", bpo::value<unsigned int>()->default_value(0),
"number of events")(
54 "startEvent", bpo::value<unsigned int>()->default_value(0),
"index of first event to be used (when applicable)")(
55 "extKinFile", bpo::value<std::string>()->default_value(
"Kinematics.root"),
56 "name of kinematics file for event generator from file (when applicable)")(
57 "embedIntoFile", bpo::value<std::string>()->default_value(
""),
58 "filename containing the reference events to be used for the embedding")(
59 "bMax,b", bpo::value<float>()->default_value(0.),
"maximum value for impact parameter sampling (when applicable)")(
60 "isMT", bpo::value<bool>()->default_value(
false),
"multi-threaded mode (Geant4 only")(
61 "outPrefix,o", bpo::value<std::string>()->default_value(
"o2sim"),
"prefix of output files")(
62 "logseverity", bpo::value<std::string>()->default_value(
"INFO"),
"severity level for FairLogger")(
63 "logverbosity", bpo::value<std::string>()->default_value(
"medium"),
"level of verbosity for FairLogger (low, medium, high, veryhigh)")(
64 "configKeyValues", bpo::value<std::string>()->default_value(
""),
"semicolon separated key=value strings (e.g.: 'TPC.gasDensity=1;...")(
65 "configFile", bpo::value<std::string>()->default_value(
""),
"Path to an INI or JSON configuration file")(
66 "chunkSize", bpo::value<unsigned int>()->default_value(500),
"max size of primary chunk (subevent) distributed by server")(
67 "chunkSizeI", bpo::value<int>()->default_value(-1),
"internalChunkSize")(
68 "seed", bpo::value<ULong_t>()->default_value(0),
"initial seed as ULong_t (default: 0 == random)")(
69 "field", bpo::value<std::string>()->default_value(
"-5"),
"L3 field rounded to kGauss, allowed values +-2,+-5 and 0; +-<intKGaus>U for uniform field; \"ccdb\" for taking it from CCDB ")(
"vertexMode", bpo::value<std::string>()->default_value(
"kDiamondParam"),
"Where the beam-spot vertex should come from. Must be one of kNoVertex, kDiamondParam, kCCDB")(
70 "nworkers,j", bpo::value<int>()->default_value(nsimworkersdefault),
"number of parallel simulation workers (only for parallel mode)")(
71 "noemptyevents",
"only writes events with at least one hit")(
72 "CCDBUrl", bpo::value<std::string>()->default_value(
"http://alice-ccdb.cern.ch"),
"URL for CCDB to be used.")(
73 "timestamp", bpo::value<uint64_t>(),
"global timestamp value in ms (for anchoring) - default is now ... or beginning of run if ALICE run number was given")(
74 "run", bpo::value<int>()->default_value(-1),
"ALICE run number")(
75 "asservice", bpo::value<bool>()->default_value(
false),
"run in service/server mode")(
76 "noGeant", bpo::bool_switch(),
"prohibits any Geant transport/physics (by using tight cuts)")(
77 "forwardKine", bpo::bool_switch(),
"forward kinematics on a FairMQ channel")(
78 "noDiscOutput", bpo::bool_switch(),
"switch off writing sim results to disc (useful in combination with forwardKine)");
79 options.add_options()(
"fromCollContext", bpo::value<std::string>()->default_value(
""),
"Use a pregenerated collision context to infer number of events to simulate, how to embedd them, the vertex position etc. Takes precedence of other options such as \"--nEvents\". The format is COLLISIONCONTEXTFILE.root[:SIGNALNAME] where SIGNALNAME is the event part in the context which is relevant.");
82void SimConfig::determineActiveModules(std::vector<std::string>
const& inputargs, std::vector<std::string>
const& skippedModules, std::vector<std::string>& activeModules,
bool isUpgrade)
88 activeModules = inputargs;
90 if (activeModules[0] !=
"all") {
92 for (
int i = 0;
i < activeModules.size(); ++
i) {
93 if (activeModules[
i] !=
"A3IP" &&
94 activeModules[
i] !=
"IT3" &&
95 activeModules[
i] !=
"TRK" &&
96 activeModules[
i] !=
"FT3" &&
97 activeModules[
i] !=
"FCT" &&
98 activeModules[
i] !=
"TF3" &&
99 activeModules[
i] !=
"RCH" &&
100 activeModules[
i] !=
"MI3" &&
101 activeModules[
i] !=
"ECL" &&
102 activeModules[
i] !=
"FD3") {
103 LOGP(fatal,
"List of active modules contains {}, which is not a module from the upgrades.", activeModules[
i]);
108 for (
int i = 0;
i < activeModules.size(); ++
i) {
109 if (activeModules[
i] ==
"A3IP" ||
110 activeModules[
i] ==
"TRK" ||
111 activeModules[
i] ==
"FT3" ||
112 activeModules[
i] ==
"FCT" ||
113 activeModules[
i] ==
"TF3" ||
114 activeModules[
i] ==
"RCH" ||
115 activeModules[
i] ==
"MI3" ||
116 activeModules[
i] ==
"ECL" ||
117 activeModules[
i] ==
"FD3") {
118 LOGP(fatal,
"List of active modules contains {}, which is not a run 3 module", activeModules[
i]);
124 if (activeModules.size() == 1 && activeModules[0] ==
"all") {
125 activeModules.clear();
126#ifdef ENABLE_UPGRADES
129 if (d == DetID::TRK ||
140 activeModules.emplace_back(
"A3IP");
141 activeModules.emplace_back(
"A3ABSO");
142 activeModules.emplace_back(
"A3MAG");
146 activeModules.emplace_back(
"HALL");
147 activeModules.emplace_back(
"MAG");
148 activeModules.emplace_back(
"DIPO");
149 activeModules.emplace_back(
"COMP");
150 activeModules.emplace_back(
"PIPE");
151 activeModules.emplace_back(
"ABSO");
152 activeModules.emplace_back(
"SHIL");
154#ifdef ENABLE_UPGRADES
155 if (d != DetID::IT3 && d != DetID::TRK && d != DetID::FT3 && d != DetID::FCT && d != DetID::TF3 && d != DetID::RCH && d != DetID::ECL && d != DetID::FD3 && d != DetID::MI3) {
164 filterSkippedElements(activeModules, skippedModules);
171 if (
auto pos =
version.find(
':');
pos != std::string::npos) {
175 LOGP(error,
"Could not parse {}; check errors above!", ppath);
178 if (map.find(pversion) == map.end()) {
179 LOGP(error,
"List {} is not defined in custom JSON file!", pversion);
183 modules = map[pversion];
184 LOGP(info,
"Running with version {} from custom detector list '{}'", pversion, ppath);
187 auto o2env = std::getenv(
"O2_ROOT");
189 LOGP(error,
"O2_ROOT environment not defined");
192 const std::string rootpath(fmt::format(
"{}/share/config/o2simdefaultdetectorlist.json", o2env));
194 LOGP(error,
"Could not parse {} -> check errors above!", rootpath);
197 if (map.find(
version) == map.end()) {
198 LOGP(error,
"List {} is not defined in 'official' JSON file!",
version);
203 LOGP(info,
"Running with official detector version '{}'",
version);
206 if (inputargs.size() != 1 || inputargs[0] !=
"all") {
207 std::vector<std::string> diff;
208 for (
const auto& in : inputargs) {
209 if (std::find(modules.begin(), modules.end(), in) == std::end(modules)) {
210 diff.emplace_back(in);
214 LOGP(error,
"Modules specified that are not present in detector list {}",
version);
215 for (
int j{0};
const auto&
m : diff) {
216 LOGP(info,
" - {: <2}. {}",
j++,
m);
223 std::copy_if(modules.begin(), modules.end(), std::back_inserter(activeModules),
224 [&inputargs](
const auto& e) { return (inputargs.size() == 1 && inputargs[0] ==
"all") || (std::find(inputargs.begin(), inputargs.end(), e) != inputargs.end()); });
225 return filterSkippedElements(activeModules, skippedModules);
228void SimConfig::determineReadoutDetectors(std::vector<std::string>
const& activeModules, std::vector<std::string>
const& enableReadout, std::vector<std::string>
const& disableReadout, std::vector<std::string>& readoutDetectors)
232 readoutDetectors.clear();
234 auto isDet = [](std::string
const& s) {
238 if (enableReadout.empty()) {
240 for (
auto& am : activeModules) {
245 readoutDetectors.emplace_back(am);
248 for (
auto& er : enableReadout) {
251 LOG(fatal) <<
"Enabled readout for " << er <<
" which is not a detector.";
253 if (std::find(activeModules.begin(), activeModules.end(), er) == activeModules.end()) {
255 LOG(fatal) <<
"Module " << er <<
" not constructed and cannot be used for readout (make sure it is contained in -m option).";
257 readoutDetectors.emplace_back(er);
260 for (
auto& dr : disableReadout) {
263 LOG(fatal) <<
"Disabled readout for " << dr <<
" which is not a detector.";
265 if (std::find(activeModules.begin(), activeModules.end(), dr) == activeModules.end()) {
267 LOG(fatal) <<
"Module " << dr <<
" not constructed, makes no sense to disable its readout (make sure it is contained in -m option).";
269 auto iter = std::find(readoutDetectors.begin(), readoutDetectors.end(), dr);
270 if (iter != readoutDetectors.end()) {
271 readoutDetectors.erase(iter);
294 mConfigData.
mMCEngine = vm[
"mcEngine"].as<std::string>();
295 mConfigData.
mNoGeant = vm[
"noGeant"].as<
bool>();
302 if (!
determineActiveModulesList(vm[
"detectorList"].as<std::string>(), vm[
"modules"].as<std::vector<std::string>>(), vm[
"skipModules"].as<std::vector<std::string>>(), mConfigData.
mActiveModules)) {
310 mConfigData.
mMCEngine =
"O2TrivialMCEngine";
311 }
else if (mConfigData.
mMCEngine.compare(
"O2TrivialMCEngine") == 0) {
312 LOG(error) <<
"The O2TrivialMCEngine engine can only be used with --noGeant option";
321 mConfigData.
mGenerator = vm[
"generator"].as<std::string>();
322 mConfigData.
mTrigger = vm[
"trigger"].as<std::string>();
323 mConfigData.
mNEvents = vm[
"nEvents"].as<
unsigned int>();
326 mConfigData.
mStartEvent = vm[
"startEvent"].as<
unsigned int>();
327 mConfigData.
mBMax = vm[
"bMax"].as<
float>();
328 mConfigData.
mIsMT = vm[
"isMT"].as<
bool>();
329 mConfigData.
mOutputPrefix = vm[
"outPrefix"].as<std::string>();
330 mConfigData.
mLogSeverity = vm[
"logseverity"].as<std::string>();
331 mConfigData.
mLogVerbosity = vm[
"logverbosity"].as<std::string>();
333 mConfigData.
mConfigFile = vm[
"configFile"].as<std::string>();
336 mConfigData.
mStartSeed = vm[
"seed"].as<ULong_t>();
337 mConfigData.
mSimWorkers = vm[
"nworkers"].as<
int>();
338 if (vm.count(
"timestamp")) {
339 mConfigData.
mTimestamp = vm[
"timestamp"].as<uint64_t>();
342 mConfigData.
mTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
346 mConfigData.
mCCDBUrl = vm[
"CCDBUrl"].as<std::string>();
347 mConfigData.
mAsService = vm[
"asservice"].as<
bool>();
348 mConfigData.
mForwardKine = vm[
"forwardKine"].as<
bool>();
349 mConfigData.
mWriteToDisc = !vm[
"noDiscOutput"].as<
bool>();
350 if (vm.count(
"noemptyevents")) {
355 adjustFromCollContext(collcontext_simprefix.first, collcontext_simprefix.second);
364 auto& fieldstring = vm[
"field"].as<std::string>();
365 std::regex re(
"(ccdb)|([+-]?(0|[2-9]|[12][0-9]|20)U?)");
366 if (!std::regex_match(fieldstring, re)) {
367 LOG(error) <<
"Invalid field option " << fieldstring;
370 if (fieldstring ==
"ccdb") {
372 }
else if (fieldstring.find(
"U") != std::string::npos) {
375 if (fieldstring !=
"ccdb") {
376 mConfigData.
mField = std::stoi((vm[
"field"].as<std::string>()).substr(0, (vm[
"field"].as<std::string>()).rfind(
"U")));
542 bpo::options_description options(
"Allowed options");
544 options.add_options()(
545 "nEvents,n", bpo::value<unsigned int>(&
data.nEvents)->default_value(0),
"number of events")(
546 "generator,g", bpo::value<std::string>(&
data.generator)->default_value(
"boxgen"),
"Event generator to be used.")(
547 "trigger,t", bpo::value<std::string>(&
data.trigger)->default_value(
""),
"Event generator trigger to be used.")(
548 "startEvent", bpo::value<unsigned int>(&
data.startEvent)->default_value(0),
"index of first event to be used (when applicable)")(
549 "extKinFile", bpo::value<std::string>(&
data.extKinfileName)->default_value(
"Kinematics.root"),
550 "name of kinematics file for event generator from file (when applicable)")(
551 "embedIntoFile", bpo::value<std::string>(&
data.embedIntoFileName)->default_value(
""),
552 "filename containing the reference events to be used for the embedding")(
553 "bMax,b", bpo::value<float>(&
data.mBMax)->default_value(0.),
"maximum value for impact parameter sampling (when applicable)")(
554 "outPrefix,o", bpo::value<std::string>(&
data.outputPrefix)->default_value(
"o2sim"),
"prefix of output files")(
555 "outDir,d", bpo::value<std::string>(&
data.outputDir),
"directory where to put simulation output (created when non-existant")(
556 "configKeyValues", bpo::value<std::string>(&
data.keyValueTokens)->default_value(
""),
"semicolon separated key=value strings (e.g.: 'TPC.gasDensity=1;...")(
557 "configFile", bpo::value<std::string>(&
data.configFile)->default_value(
""),
"Path to an INI or JSON configuration file")(
558 "chunkSize", bpo::value<unsigned int>(&
data.primaryChunkSize)->default_value(500),
"max size of primary chunk (subevent) distributed by server")(
559 "seed", bpo::value<ULong_t>(&
data.startSeed)->default_value(0L),
"initial seed as ULong_t (default: 0 == random)")(
560 "stop", bpo::value<bool>(&
data.stop)->default_value(
false),
"control command to shut down daemon");
562 bpo::variables_map vm;
564 bpo::store(bpo::command_line_parser(bpo::split_unix(argumentstring))
569 }
catch (
const bpo::error& e) {
570 std::cerr << e.what() <<
"\n\n";
571 std::cerr <<
"Error parsing ReConfig data; Available options:\n";
572 std::cerr << options << std::endl;
static DigitizationContext * loadFromFile(std::string_view filename="")