Project
Loading...
Searching...
No Matches
SimConfig.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <SimConfig/SimConfig.h>
16#include <boost/program_options.hpp>
17#include <iostream>
18#include <fairlogger/Logger.h>
19#include <thread>
20#include <cmath>
21#include <chrono>
22#include <regex>
23
24using namespace o2::conf;
25namespace bpo = boost::program_options;
26
27void SimConfig::initOptions(boost::program_options::options_description& options, bool isUpgrade)
28{
29 // some default args might depend on whether Run3 or Run5
30 // can be updated here:
31 std::string defaultGeomList{"ALICE2"};
32 if (isUpgrade == true) {
33 defaultGeomList = "ALICE3";
34 }
35
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.");
80}
81
82void SimConfig::determineActiveModules(std::vector<std::string> const& inputargs, std::vector<std::string> const& skippedModules, std::vector<std::string>& activeModules, bool isUpgrade)
83{
85
86 // input args is a vector of module strings as obtained from the -m,--modules options
87 // of SimConfig
88 activeModules = inputargs;
89#ifdef ENABLE_UPGRADES
90 if (activeModules[0] != "all") {
91 if (isUpgrade) {
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]);
104 }
105 }
106 }
107 if (!isUpgrade) {
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]);
119 }
120 }
121 }
122 }
123#endif
124 if (activeModules.size() == 1 && activeModules[0] == "all") {
125 activeModules.clear();
126#ifdef ENABLE_UPGRADES
127 if (isUpgrade) {
128 for (int d = DetID::First; d <= DetID::Last; ++d) {
129 if (d == DetID::TRK ||
130 d == DetID::FT3 ||
131 d == DetID::FCT ||
132 d == DetID::TF3 ||
133 d == DetID::RCH ||
134 d == DetID::ECL ||
135 d == DetID::FD3 ||
136 d == DetID::MI3) {
137 activeModules.emplace_back(DetID::getName(d));
138 }
139 }
140 activeModules.emplace_back("A3IP");
141 activeModules.emplace_back("A3ABSO");
142 activeModules.emplace_back("A3MAG");
143 } else {
144#endif
145 // add passive components manually (make a PassiveDetID for them!)
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");
153 for (int d = DetID::First; d <= DetID::Last; ++d) {
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) {
156 activeModules.emplace_back(DetID::getName(d));
157 }
158 }
159#else
160 activeModules.emplace_back(DetID::getName(d));
161#endif
162 }
163 }
164 filterSkippedElements(activeModules, skippedModules);
165}
166
167bool SimConfig::determineActiveModulesList(const std::string& version, std::vector<std::string> const& inputargs, std::vector<std::string> const& skippedModules, std::vector<std::string>& activeModules)
168{
169 DetectorList_t modules;
170 DetectorMap_t map;
171 if (auto pos = version.find(':'); pos != std::string::npos) {
172 auto pversion = version.substr(0, pos);
173 auto ppath = version.substr(pos + 1);
174 if (!parseDetectorMapfromJSON(ppath, map)) {
175 LOGP(error, "Could not parse {}; check errors above!", ppath);
176 return false;
177 }
178 if (map.find(pversion) == map.end()) {
179 LOGP(error, "List {} is not defined in custom JSON file!", pversion);
180 printDetMap(map);
181 return false;
182 }
183 modules = map[pversion];
184 LOGP(info, "Running with version {} from custom detector list '{}'", pversion, ppath);
185 } else {
186 // Otherwise check 'official' versions which provided in config
187 auto o2env = std::getenv("O2_ROOT");
188 if (!o2env) {
189 LOGP(error, "O2_ROOT environment not defined");
190 return false;
191 }
192 const std::string rootpath(fmt::format("{}/share/config/o2simdefaultdetectorlist.json", o2env));
193 if (!parseDetectorMapfromJSON(rootpath, map)) {
194 LOGP(error, "Could not parse {} -> check errors above!", rootpath);
195 return false;
196 }
197 if (map.find(version) == map.end()) {
198 LOGP(error, "List {} is not defined in 'official' JSON file!", version);
199 printDetMap(map);
200 return false;
201 }
202 modules = map[version];
203 static std::string last_version{}; // prevent multiple printouts of same message
204 if (last_version != version) {
205 LOGP(info, "Running with official detector version '{}'", version);
206 last_version = version;
207 }
208 }
209 // check if specified modules are in list
210 if (inputargs.size() != 1 || inputargs[0] != "all") {
211 std::vector<std::string> diff;
212 for (const auto& in : inputargs) {
213 if (std::find(modules.begin(), modules.end(), in) == std::end(modules)) {
214 diff.emplace_back(in);
215 }
216 }
217 if (!diff.empty()) {
218 LOGP(error, "Modules specified that are not present in detector list {}", version);
219 for (int j{0}; const auto& m : diff) {
220 LOGP(info, " - {: <2}. {}", j++, m);
221 }
222 printDetMap(map, version);
223 return false;
224 }
225 }
226 // Insert into active modules if module is built buy -m or insert all if default for -m is used ("all")
227 std::copy_if(modules.begin(), modules.end(), std::back_inserter(activeModules),
228 [&inputargs](const auto& e) { return (inputargs.size() == 1 && inputargs[0] == "all") || (std::find(inputargs.begin(), inputargs.end(), e) != inputargs.end()); });
229 return filterSkippedElements(activeModules, skippedModules);
230}
231
232void 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)
233{
235
236 readoutDetectors.clear();
237
238 auto isDet = [](std::string const& s) {
239 return DetID::nameToID(s.c_str()) >= DetID::First;
240 };
241
242 if (enableReadout.empty()) {
243 // if no readout explicitly given, use all detectors from active modules
244 for (auto& am : activeModules) {
245 if (!isDet(am)) {
246 // either we found a passive module or one with disabled readout ==> skip
247 continue;
248 }
249 readoutDetectors.emplace_back(am);
250 }
251 } else {
252 for (auto& er : enableReadout) {
253 if (!isDet(er)) {
254 // either we found a passive module or one with disabled readout ==> skip
255 LOG(fatal) << "Enabled readout for " << er << " which is not a detector.";
256 }
257 if (std::find(activeModules.begin(), activeModules.end(), er) == activeModules.end()) {
258 // add to active modules if not yet there
259 LOG(fatal) << "Module " << er << " not constructed and cannot be used for readout (make sure it is contained in -m option).";
260 }
261 readoutDetectors.emplace_back(er);
262 }
263 }
264 for (auto& dr : disableReadout) {
265 if (!isDet(dr)) {
266 // either we found a passive module or one with disabled readout ==> skip
267 LOG(fatal) << "Disabled readout for " << dr << " which is not a detector.";
268 }
269 if (std::find(activeModules.begin(), activeModules.end(), dr) == activeModules.end()) {
270 // add to active modules if not yet there
271 LOG(fatal) << "Module " << dr << " not constructed, makes no sense to disable its readout (make sure it is contained in -m option).";
272 }
273 auto iter = std::find(readoutDetectors.begin(), readoutDetectors.end(), dr);
274 if (iter != readoutDetectors.end()) {
275 readoutDetectors.erase(iter);
276 }
277 }
278}
279
280std::pair<std::string, std::string> SimConfig::getCollContextFilenameAndEventPrefix() const
281{
282 // we decompose the argument to fetch
283 // (a) collision contextfilename
284 // (b) sim prefix to use from the context
285 auto pos = mConfigData.mFromCollisionContext.find(':');
286 std::string collcontextfile{mConfigData.mFromCollisionContext};
287 std::string simprefix{mConfigData.mOutputPrefix};
288 if (pos != std::string::npos) {
289 collcontextfile = mConfigData.mFromCollisionContext.substr(0, pos);
290 simprefix = mConfigData.mFromCollisionContext.substr(pos + 1);
291 }
292 return std::make_pair(collcontextfile, simprefix);
293}
294
295bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& vm)
296{
298 mConfigData.mMCEngine = vm["mcEngine"].as<std::string>();
299 mConfigData.mNoGeant = vm["noGeant"].as<bool>();
300
301 // Reset modules and detectors as they are anyway re-parsed
302 mConfigData.mReadoutDetectors.clear();
303 mConfigData.mActiveModules.clear();
304
305 // Get final set of active Modules
306 if (!determineActiveModulesList(vm["detectorList"].as<std::string>(), vm["modules"].as<std::vector<std::string>>(), vm["skipModules"].as<std::vector<std::string>>(), mConfigData.mActiveModules)) {
307 return false;
308 }
309
310 if (mConfigData.mNoGeant) {
311 // CAVE is all that's needed (and that will be built either way), so clear all modules and set the O2TrivialMCEngine
312 mConfigData.mActiveModules.clear();
313 // force usage of O2TrivialMCEngine, no overhead from actual transport engine initialisation
314 mConfigData.mMCEngine = "O2TrivialMCEngine";
315 } else if (mConfigData.mMCEngine.compare("O2TrivialMCEngine") == 0) {
316 LOG(error) << "The O2TrivialMCEngine engine can only be used with --noGeant option";
317 return false;
318 }
319
320 const auto& activeModules = mConfigData.mActiveModules;
321
322 // get final set of detectors which are readout
323 determineReadoutDetectors(activeModules, vm["readoutDetectors"].as<std::vector<std::string>>(), vm["skipReadoutDetectors"].as<std::vector<std::string>>(), mConfigData.mReadoutDetectors);
324
325 mConfigData.mGenerator = vm["generator"].as<std::string>();
326 mConfigData.mTrigger = vm["trigger"].as<std::string>();
327 mConfigData.mNEvents = vm["nEvents"].as<unsigned int>();
328 mConfigData.mExtKinFileName = vm["extKinFile"].as<std::string>();
329 mConfigData.mEmbedIntoFileName = vm["embedIntoFile"].as<std::string>();
330 mConfigData.mStartEvent = vm["startEvent"].as<unsigned int>();
331 mConfigData.mBMax = vm["bMax"].as<float>();
332 mConfigData.mIsMT = vm["isMT"].as<bool>();
333 mConfigData.mOutputPrefix = vm["outPrefix"].as<std::string>();
334 mConfigData.mLogSeverity = vm["logseverity"].as<std::string>();
335 mConfigData.mLogVerbosity = vm["logverbosity"].as<std::string>();
336 mConfigData.mKeyValueTokens = vm["configKeyValues"].as<std::string>();
337 mConfigData.mConfigFile = vm["configFile"].as<std::string>();
338 mConfigData.mPrimaryChunkSize = vm["chunkSize"].as<unsigned int>();
339 mConfigData.mInternalChunkSize = vm["chunkSizeI"].as<int>();
340 mConfigData.mStartSeed = vm["seed"].as<ULong_t>();
341 mConfigData.mSimWorkers = vm["nworkers"].as<int>();
342 if (vm.count("timestamp")) {
343 mConfigData.mTimestamp = vm["timestamp"].as<uint64_t>();
345 } else {
346 mConfigData.mTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
348 }
349 mConfigData.mRunNumber = vm["run"].as<int>();
350 mConfigData.mCCDBUrl = vm["CCDBUrl"].as<std::string>();
351 mConfigData.mAsService = vm["asservice"].as<bool>();
352 mConfigData.mForwardKine = vm["forwardKine"].as<bool>();
353 mConfigData.mWriteToDisc = !vm["noDiscOutput"].as<bool>();
354 if (vm.count("noemptyevents")) {
355 mConfigData.mFilterNoHitEvents = true;
356 }
357 mConfigData.mFromCollisionContext = vm["fromCollContext"].as<std::string>();
358 auto collcontext_simprefix = getCollContextFilenameAndEventPrefix();
359 adjustFromCollContext(collcontext_simprefix.first, collcontext_simprefix.second);
360
361 // analyse vertex options
362 if (!parseVertexModeString(vm["vertexMode"].as<std::string>(), mConfigData.mVertexMode)) {
363 return false;
364 }
365
366 // analyse field options
367 // either: "ccdb" or +-2[U],+-5[U] and 0[U]; +-<intKGaus>U
368 auto& fieldstring = vm["field"].as<std::string>();
369 std::regex re("(ccdb)|([+-]?(0|[2-9]|[12][0-9]|20)U?)");
370 if (!std::regex_match(fieldstring, re)) {
371 LOG(error) << "Invalid field option " << fieldstring;
372 return false;
373 }
374 if (fieldstring == "ccdb") {
375 mConfigData.mFieldMode = SimFieldMode::kCCDB;
376 } else if (fieldstring.find("U") != std::string::npos) {
378 }
379 if (fieldstring != "ccdb") {
380 mConfigData.mField = std::stoi((vm["field"].as<std::string>()).substr(0, (vm["field"].as<std::string>()).rfind("U")));
381 }
382 if (!parseFieldString(fieldstring, mConfigData.mField, mConfigData.mFieldMode)) {
383 return false;
384 }
385
386 return true;
387}
388
389bool SimConfig::parseVertexModeString(std::string const& vertexstring, VertexMode& mode)
390{
391 // vertexstring must be either kNoVertex, kDiamondParam, kCCDB
392 if (vertexstring == "kNoVertex") {
394 return true;
395 } else if (vertexstring == "kDiamondParam") {
397 return true;
398 } else if (vertexstring == "kCCDB") {
400 return true;
401 } else if (vertexstring == "kCollContext") {
403 return true;
404 }
405 LOG(error) << "Vertex mode must be one of kNoVertex, kDiamondParam, kCCDB, kCollContext";
406 return false;
407}
408
409bool SimConfig::parseFieldString(std::string const& fieldstring, int& fieldvalue, SimFieldMode& mode)
410{
411 // analyse field options
412 // either: "ccdb" or +-2[U],+-5[U] and 0[U]; +-<intKGaus>U
413 std::regex re("(ccdb)|([+-]?(0|[2-9]|[12][0-9]|20)U?)");
414 if (!std::regex_match(fieldstring, re)) {
415 LOG(error) << "Invalid field option " << fieldstring;
416 return false;
417 }
418 if (fieldstring == "ccdb") {
420 } else if (fieldstring.find("U") != std::string::npos) {
422 }
423 if (fieldstring != "ccdb") {
424 fieldvalue = std::stoi(fieldstring.substr(0, fieldstring.rfind("U")));
425 }
426 return true;
427}
428
429bool SimConfig::filterSkippedElements(std::vector<std::string>& elements, std::vector<std::string> const& skipped)
430{
431 for (auto& s : skipped) {
432 if (s.empty()) { // nothing to skip here
433 continue;
434 }
435 auto iter = std::find(elements.begin(), elements.end(), s);
436 if (iter != elements.end()) {
437 // take it out
438 elements.erase(iter);
439 } else {
440 LOGP(error, "Skipped modules specified that are not present in built modules!");
441 LOGP(error, "Built modules:");
442 for (int j{0}; const auto& m : elements) {
443 LOGP(error, " + {: <2}. {}", j++, m);
444 }
445 std::vector<std::string> diff;
446 for (const auto& skip : skipped) {
447 if (std::find(elements.begin(), elements.end(), skip) == std::end(elements)) {
448 diff.emplace_back(skip);
449 }
450 }
451 LOGP(error, "Specified skipped modules not present in built modules:");
452 for (int j{0}; const auto& m : diff) {
453 LOGP(error, " - {: <2}. {}", j++, m);
454 }
455 return false;
456 }
457 }
458 return true;
459}
460
461void SimConfig::adjustFromCollContext(std::string const& collcontextfile, std::string const& prefix)
462{
463 // When we use pregenerated collision contexts, some options
464 // need to be auto-adjusted. Do so and inform about this in the logs.
465 if (collcontextfile == "") {
466 return;
467 }
468
469 auto context = o2::steer::DigitizationContext::loadFromFile(collcontextfile);
470 if (context) {
471 // find the events belonging to a source that corresponds to a sim prefix
472 LOG(info) << "Looking up simprefixes " << prefix;
473 int sourceid = context->findSimPrefix(prefix);
474 if (sourceid == -1) {
475 LOG(error) << "Could not find collisions with sim prefix " << prefix << " in the collision context. The collision context specifies the following prefixes:";
476 for (auto& sp : context->getSimPrefixes()) {
477 LOG(info) << sp;
478 }
479 LOG(fatal) << "Aborting due to prefix error";
480 } else {
481 auto collisionmap = context->getCollisionIndicesForSource(sourceid);
482 LOG(info) << "Found " << collisionmap.size() << " events in the collisioncontext for prefix " << prefix;
483
484 // check if collisionmap is dense (otherwise it will get screwed up with order/indexing in ROOT output)
485 bool good = true;
486 for (auto index = 0; index < collisionmap.size(); ++index) {
487 if (collisionmap.find(index) == collisionmap.end()) {
488 good = false;
489 }
490 }
491 if (!good) {
492 LOG(fatal) << "events in collisioncontext are non-compact ";
493 }
494
495 // do some adjustments based on the number of events to be simulated
496 if (mConfigData.mNEvents == 0 || mConfigData.mNEvents == collisionmap.size()) {
497 // we take what is specified in the context
498 mConfigData.mNEvents = collisionmap.size();
499 } else {
500 LOG(warning) << "The number of events on the command line " << mConfigData.mNEvents << " and in the collision context differ. We take the one from collision context " << collisionmap.size();
501 mConfigData.mNEvents = collisionmap.size();
502 }
503 LOG(info) << "Setting number of events to simulate to " << mConfigData.mNEvents;
504 }
505 } else {
506 LOG(fatal) << "Could not open collision context file " << collcontextfile;
507 }
508}
509
510bool SimConfig::resetFromArguments(int argc, char* argv[])
511{
512 // Arguments parsing
513 bpo::variables_map vm;
514 bpo::options_description desc("Allowed options");
515 desc.add_options()("help,h", "Produce help message.");
516 initOptions(desc, mConfigData.mIsUpgrade);
517
518 try {
519 bpo::store(parse_command_line(argc, argv, desc), vm);
520
521 // help
522 if (vm.count("help")) {
523 std::cout << desc << std::endl;
524 return false;
525 }
526
527 bpo::notify(vm);
528 } catch (const bpo::error& e) {
529 std::cerr << e.what() << "\n\n";
530 std::cerr << "Error parsing command line arguments; Available options:\n";
531
532 std::cerr << desc << std::endl;
533 return false;
534 }
535
536 return resetFromParsedMap(vm);
537}
538
539namespace o2::conf
540{
541// returns a reconfig struct given a configuration string (boost program options format)
542bool parseSimReconfigFromString(std::string const& argumentstring, SimReconfigData& data)
543{
544 namespace bpo = boost::program_options;
545
546 bpo::options_description options("Allowed options");
547
548 options.add_options()(
549 "nEvents,n", bpo::value<unsigned int>(&data.nEvents)->default_value(0), "number of events")(
550 "generator,g", bpo::value<std::string>(&data.generator)->default_value("boxgen"), "Event generator to be used.")(
551 "trigger,t", bpo::value<std::string>(&data.trigger)->default_value(""), "Event generator trigger to be used.")(
552 "startEvent", bpo::value<unsigned int>(&data.startEvent)->default_value(0), "index of first event to be used (when applicable)")(
553 "extKinFile", bpo::value<std::string>(&data.extKinfileName)->default_value("Kinematics.root"),
554 "name of kinematics file for event generator from file (when applicable)")(
555 "embedIntoFile", bpo::value<std::string>(&data.embedIntoFileName)->default_value(""),
556 "filename containing the reference events to be used for the embedding")(
557 "bMax,b", bpo::value<float>(&data.mBMax)->default_value(0.), "maximum value for impact parameter sampling (when applicable)")(
558 "outPrefix,o", bpo::value<std::string>(&data.outputPrefix)->default_value("o2sim"), "prefix of output files")(
559 "outDir,d", bpo::value<std::string>(&data.outputDir), "directory where to put simulation output (created when non-existant")(
560 "configKeyValues", bpo::value<std::string>(&data.keyValueTokens)->default_value(""), "semicolon separated key=value strings (e.g.: 'TPC.gasDensity=1;...")(
561 "configFile", bpo::value<std::string>(&data.configFile)->default_value(""), "Path to an INI or JSON configuration file")(
562 "chunkSize", bpo::value<unsigned int>(&data.primaryChunkSize)->default_value(500), "max size of primary chunk (subevent) distributed by server")(
563 "seed", bpo::value<ULong_t>(&data.startSeed)->default_value(0L), "initial seed as ULong_t (default: 0 == random)")(
564 "stop", bpo::value<bool>(&data.stop)->default_value(false), "control command to shut down daemon");
565
566 bpo::variables_map vm;
567 try {
568 bpo::store(bpo::command_line_parser(bpo::split_unix(argumentstring))
569 .options(options)
570 .run(),
571 vm);
572 bpo::notify(vm);
573 } catch (const bpo::error& e) {
574 std::cerr << e.what() << "\n\n";
575 std::cerr << "Error parsing ReConfig data; Available options:\n";
576 std::cerr << options << std::endl;
577 return false;
578 }
579 return true;
580}
581
582} // namespace o2::conf
583
int32_t i
ClassImp(IdPath)
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
uint32_t version
Definition RawData.h:8
bool resetFromParsedMap(boost::program_options::variables_map const &)
bool resetFromArguments(int argc, char *argv[])
static void determineActiveModules(std::vector< std::string > const &input, std::vector< std::string > const &skipped, std::vector< std::string > &active, bool isUpgrade=false)
Definition SimConfig.cxx:82
static bool parseVertexModeString(std::string const &vertexstring, o2::conf::VertexMode &mode)
static bool parseFieldString(std::string const &fieldstring, int &fieldvalue, o2::conf::SimFieldMode &mode)
static void determineReadoutDetectors(std::vector< std::string > const &active, std::vector< std::string > const &enabledRO, std::vector< std::string > const &skippedRO, std::vector< std::string > &finalRO)
static bool determineActiveModulesList(const std::string &version, std::vector< std::string > const &input, std::vector< std::string > const &skipped, std::vector< std::string > &active)
std::pair< std::string, std::string > getCollContextFilenameAndEventPrefix() const
static void initOptions(boost::program_options::options_description &, bool isUpgrade=false)
Definition SimConfig.cxx:27
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:146
static constexpr ID First
Definition DetID.h:95
static constexpr int nameToID(char const *name, int id=First)
Definition DetID.h:155
static constexpr ID Last
if extra detectors added, update this !!!
Definition DetID.h:93
static DigitizationContext * loadFromFile(std::string_view filename="")
const GLfloat * m
Definition glcorearb.h:4066
GLenum mode
Definition glcorearb.h:266
GLuint index
Definition glcorearb.h:781
GLboolean * data
Definition glcorearb.h:298
std::vector< std::string > DetectorList_t
bool parseSimReconfigFromString(std::string const &argumentstring, SimReconfigData &config)
void printDetMap(const DetectorMap_t &map, const std::string &list="")
std::unordered_map< std::string, DetectorList_t > DetectorMap_t
bool parseDetectorMapfromJSON(const std::string &path, DetectorMap_t &map)
std::string mFromCollisionContext
Definition SimConfig.h:86
std::vector< std::string > mActiveModules
Definition SimConfig.h:52
std::string mOutputPrefix
Definition SimConfig.h:63
std::string mExtKinFileName
Definition SimConfig.h:58
unsigned int mPrimaryChunkSize
Definition SimConfig.h:72
std::vector< std::string > mReadoutDetectors
Definition SimConfig.h:53
std::string mKeyValueTokens
Definition SimConfig.h:66
TimeStampMode mTimestampMode
Definition SimConfig.h:79
unsigned int mNEvents
Definition SimConfig.h:57
std::string mGenerator
Definition SimConfig.h:55
SimFieldMode mFieldMode
Definition SimConfig.h:82
std::string mLogSeverity
Definition SimConfig.h:64
std::string mConfigFile
Definition SimConfig.h:69
std::string mEmbedIntoFileName
Definition SimConfig.h:59
std::string mLogVerbosity
Definition SimConfig.h:65
unsigned int mStartEvent
Definition SimConfig.h:60
std::string mMCEngine
Definition SimConfig.h:54
TODO: Make this a base class of SimConfigData?
Definition SimConfig.h:203
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"