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