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