Project
Loading...
Searching...
No Matches
SimpleDigitizerWorkflow.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 <boost/program_options.hpp>
13#include <boost/lexical_cast.hpp>
14
22#include "Framework/InputSpec.h"
24#include "SimReaderSpec.h"
30
31// for TPC
32#include "TPCDigitizerSpec.h"
34#include "TPCBase/Sector.h"
36// needed in order to init the **SHARED** polyadist file (to be done before the digitizers initialize)
38
39// for ITSMFT
40#include "ITSMFTDigitizerSpec.h"
42
43#ifdef ENABLE_UPGRADES
44// for ITS3
45#include "ITS3DigitizerSpec.h"
47
48// for alice 3 TRK
49#include "TRKDigitizerSpec.h"
51#endif
52
53// for TOF
54#include "TOFDigitizerSpec.h"
56
57// for FT0
58#include "FT0DigitizerSpec.h"
59#include "FT0DigitWriterSpec.h"
60
61// for CTP
62#include "CTPDigitizerSpec.h"
64
65// for FV0
66#include "FV0DigitizerSpec.h"
67#include "FV0DigitWriterSpec.h"
68
69// for FDD
70#include "FDDDigitizerSpec.h"
72
73// for EMCal
76
77// for HMPID
78#include "HMPIDDigitizerSpec.h"
80
81// for TRD
86
87// for MUON MCH
88#include "MCHDigitizerSpec.h"
90
91// for MID
92#include "MIDDigitizerSpec.h"
93#include "MIDDigitWriterSpec.h"
94
95// for PHOS
96#include "PHOSDigitizerSpec.h"
97#include "PHOSDigitWriterSpec.h"
98
99// for CPV
100#include "CPVDigitizerSpec.h"
101#include "CPVDigitWriterSpec.h"
102
103// for ZDC
104#include "ZDCDigitizerSpec.h"
106
107// GRP
109#include "GRPUpdaterSpec.h"
110
111#include <cstdlib>
112// this is somewhat assuming that a DPL workflow will run on one node
113#include <thread> // to detect number of hardware threads
114#include <string>
115#include <sstream>
116#include <cmath>
117#include <unistd.h> // for getppid
118#include <type_traits>
121
122using namespace o2::framework;
123
124bool gIsMaster = false; // a global variable indicating if this is the master workflow process
125 // (an individual DPL processor will still build the workflow but is not
126 // considered master)
127
128// ------------------------------------------------------------------
129
130// customize the completion policy
131void customize(std::vector<o2::framework::CompletionPolicy>& policies)
132{
134 // we customize the completion policy for the writer since it should stream immediately
135 policies.push_back(CompletionPolicyHelpers::defineByName("TPCDigitWriter", CompletionPolicy::CompletionOp::Consume));
136 policies.push_back(CompletionPolicyHelpers::consumeWhenAnyWithAllConditions("TPCDigitizer.*"));
137 policies.push_back(CompletionPolicyHelpers::defineByName("tpc-cluster-decoder.*", CompletionPolicy::CompletionOp::Consume));
138 policies.push_back(CompletionPolicyHelpers::defineByName("tpc-clusterer.*", CompletionPolicy::CompletionOp::Consume));
139}
140
141// ------------------------------------------------------------------
142
143// we need to add workflow options before including Framework/runDataProcessing
144void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
145{
146 // for the TPC it is useful to take at most half of the available (logical) cores due to memory requirements
147 int defaultlanes = std::max(1u, std::thread::hardware_concurrency() / 2);
148 std::string laneshelp("Number of tpc processing lanes. A lane is a pipeline of algorithms.");
149 workflowOptions.push_back(
150 ConfigParamSpec{"tpc-lanes", VariantType::Int, defaultlanes, {laneshelp}});
151
152 std::string sectorshelp("List of TPC sectors, comma separated ranges, e.g. 0-3,7,9-15");
153 std::string sectorDefault = "0-" + std::to_string(o2::tpc::Sector::MAXSECTOR - 1);
154 workflowOptions.push_back(
155 ConfigParamSpec{"tpc-sectors", VariantType::String, sectorDefault.c_str(), {sectorshelp}});
156
157 std::string onlyhelp("Comma separated list of detectors to accept. Takes precedence over the skipDet option. (Default is none)");
158 workflowOptions.push_back(
159 ConfigParamSpec{"onlyDet", VariantType::String, "none", {onlyhelp}});
160
161 std::string skiphelp("Comma separate list of detectors to skip/ignore. (Default is none)");
162 workflowOptions.push_back(
163 ConfigParamSpec{"skipDet", VariantType::String, "none", {skiphelp}});
164
165 // especially useful if digit files are required later on in a simulation chain.
166 // so if --onlyDet <detlist> is set, one can then be sure to find all those digi files, especially those for which the detector
167 // hit files do not exist (e.g. because the detector was not readout during data taking)
168 std::string forceaccepthelp("Whether or not to always rely on accept/skip filters for detectors, independent of GRP content");
169 workflowOptions.push_back(
170 ConfigParamSpec{"forceSelectedDets", VariantType::Bool, false, {forceaccepthelp}});
171
172 std::string onlyctxhelp("Produce only the digitization context; Don't actually digitize");
173 workflowOptions.push_back(ConfigParamSpec{"only-context", o2::framework::VariantType::Bool, false, {onlyctxhelp}});
174
175 // we support only output type 'tracks' for the moment
176 std::string tpcrthelp("deprecated option, please connect workflows on the command line by pipe");
177 workflowOptions.push_back(
178 ConfigParamSpec{"tpc-reco-type", VariantType::String, "", {tpcrthelp}});
179
180 // Option to write TPC digits internaly, without forwarding to a special writer instance.
181 // This is useful in GRID productions with small available memory.
182 workflowOptions.push_back(ConfigParamSpec{"tpc-chunked-writer", o2::framework::VariantType::Bool, false, {"Write independent TPC digit chunks as soon as they can be flushed."}});
183 workflowOptions.push_back(ConfigParamSpec{"tpc-distortion-type", o2::framework::VariantType::Int, 0, {"Simulate distortions in the TPC (0=no distortions, 1=distortions without scaling, 2=distortions with CTP scaling)"}});
184
185 std::string simhelp("Comma separated list of simulation prefixes (for background, signal productions)");
186 workflowOptions.push_back(
187 ConfigParamSpec{"sims", VariantType::String, "o2sim", {simhelp}});
188
189 // option allowing to set parameters
190 std::string keyvaluehelp("Semicolon separated key=value strings (e.g.: 'TPC.gasDensity=1;...')");
191 workflowOptions.push_back(
192 ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}});
193 workflowOptions.push_back(
194 ConfigParamSpec{"configFile", VariantType::String, "", {"configuration file for configurable parameters"}});
195
196 // option to disable MC truth
197 workflowOptions.push_back(ConfigParamSpec{"disable-mc", o2::framework::VariantType::Bool, false, {"disable mc-truth"}});
198
199 // option to disable INI file writing
200 workflowOptions.push_back(ConfigParamSpec{"disable-write-ini", o2::framework::VariantType::Bool, false, {"disable INI config write"}});
201
202 // option to use/not use CCDB for TOF
203 workflowOptions.push_back(ConfigParamSpec{"use-ccdb-tof", o2::framework::VariantType::Bool, false, {"enable access to ccdb tof calibration objects"}});
204 workflowOptions.push_back(ConfigParamSpec{"ccdb-tof-sa", o2::framework::VariantType::Bool, false, {"enable access to ccdb tof calibration objects via CCDBManager (obsolete remap to use-ccdb-tof)"}});
205
206 // option to use/not use CCDB for FT0
207 workflowOptions.push_back(ConfigParamSpec{"use-ccdb-ft0", o2::framework::VariantType::Bool, false, {"enable access to ccdb ft0 calibration objects"}});
208
209 // option to use/not use CCDB for EMCAL
210 workflowOptions.push_back(ConfigParamSpec{"no-use-ccdb-emc", o2::framework::VariantType::Bool, false, {"Disable access to ccdb EMCAL simulation objects"}});
211
212 // option to require/not require CTP MB inputs in EMCAL
213 workflowOptions.push_back(ConfigParamSpec{"no-require-ctpinputs-emc", o2::framework::VariantType::Bool, false, {"Disable requirement of CTP min. bias inputs in EMCAL simulation"}});
214
215 // option to use or not use the Trap Simulator after digitisation (debate of digitization or reconstruction is for others)
216 workflowOptions.push_back(ConfigParamSpec{"disable-trd-trapsim", VariantType::Bool, false, {"disable the trap simulation of the TRD"}});
217 workflowOptions.push_back(ConfigParamSpec{"trd-digit-downscaling", VariantType::Int, 1, {"only keep TRD digits for every n-th trigger"}});
218
219 workflowOptions.push_back(ConfigParamSpec{"combine-devices", VariantType::Bool, false, {"combined multiple DPL worker/writer devices"}});
220
221 // to enable distribution of triggers
222 workflowOptions.push_back(ConfigParamSpec{"with-trigger", VariantType::Bool, false, {"enable distribution of CTP trigger digits"}});
223
224 // option to propagate CTP Lumi scaler counts (if >=0) into the CTP digits
225 workflowOptions.push_back(ConfigParamSpec{"store-ctp-lumi", VariantType::Float, -1.f, {"store CTP lumi scaler in CTP digits (if >= 0)"}});
226}
227
228void customize(std::vector<o2::framework::DispatchPolicy>& policies)
229{
231 // we customize all devices to dispatch data immediately
232 auto matcher = [](auto const& spec) {
233 return spec.name == "SimReader";
234 };
235 policies.push_back({"prompt-for-simreader", matcher, DispatchOp::WhenReady});
236}
237
239{
240 const auto& hbfu = o2::raw::HBFUtils::Instance();
241 const auto offset = int64_t(hbfu.getFirstIRofTF({0, hbfu.orbitFirstSampled}).orbit);
242 const auto increment = int64_t(hbfu.nHBFPerTF);
243 const auto startTime = hbfu.startTime;
244 const auto orbitFirst = hbfu.orbitFirst;
245 dh.firstTForbit = offset + increment * dh.tfCounter;
246 dh.runNumber = hbfu.runNumber;
247 dph.creation = startTime + (dh.firstTForbit - orbitFirst) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
248}
249
250void customize(std::vector<o2::framework::CallbacksPolicy>& policies)
251{
252 // we customize the time information sent in DPL headers
253 policies.push_back(o2::framework::CallbacksPolicy{
254 [](o2::framework::DeviceSpec const& spec, o2::framework::ConfigContext const& context) -> bool {
255 return true;
256 },
258 // simple linear enumeration from already updated HBFUtils (set via config key values)
261 setTimingInfoInHeaders(dh, dph);
262 LOG(info) << "Setting DPL-header firstTForbit to " << dh.firstTForbit;
263 LOG(info) << "Setting DPL-header runNumber to " << dh.runNumber;
264 LOG(info) << "Setting DPL-header timeframe creation time to " << dph.creation;
265 });
266 }} // end of struct
267 );
268}
269
270// ------------------------------------------------------------------
271
273
274// extract num TPC lanes, a lane is a streaming line of processors (digitizer-clusterizer-etc)
275// by default this will be std::max(the number of physical cores, numberofsectors)
276// as a temporary means to fully use a machine and as a way to play with different topologies
277int getNumTPCLanes(std::vector<int> const& sectors, ConfigContext const& configcontext)
278{
279 auto lanes = configcontext.options().get<int>("tpc-lanes");
280 if (lanes < 0) {
281 if (gIsMaster) {
282 LOG(fatal) << "tpc-lanes needs to be positive\n";
283 }
284 return 0;
285 }
286 // crosscheck with sectors
287 return std::min(lanes, (int)sectors.size());
288}
289
290// ------------------------------------------------------------------
291
292void initTPC(long timestamp)
293{
294 // We only want to do this for the DPL master
295 // I am not aware of an easy way to query if "I am DPL master" so
296 // using for the moment a mechanism defining/setting an environment variable
297 // with the parent ID and query inside forks if this environment variable exists
298 // (it assumes fundamentally that the master executes this function first)
299 std::stringstream streamthis;
300 std::stringstream streamparent;
301
302 streamthis << "TPCGEMINIT_PID" << getpid();
303 streamparent << "TPCGEMINIT_PID" << getppid();
304 if (getenv(streamparent.str().c_str())) {
305 LOG(debug) << "GEM ALREADY INITIALIZED ... SKIPPING HERE";
306 return;
307 }
308
309 LOG(debug) << "INITIALIZING TPC GEMAmplification";
310 setenv(streamthis.str().c_str(), "ON", 1);
311
313 cdb.setUseDefaults();
314
315 // IMPORTANT: load ParameterGEM, ParameterGas and CalPadGainFull from CCDB to correctly init GEMAmplification
316 auto& ccdbManager = o2::ccdb::BasicCCDBManager::instance();
317 ccdbManager.getSpecific<o2::tpc::ParameterGEM>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::ParGEM), timestamp);
318 LOGP(info, "initTPC: TPC GEM param, Gas param + CalPadGainFull updated for time {}", timestamp);
319 ccdbManager.getSpecific<o2::tpc::CalPad>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::CalPadGainFull), timestamp);
320 ccdbManager.getSpecific<o2::tpc::ParameterGas>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::ParGas), timestamp);
321
323 o2::tpc::ParameterGas::Instance().printKeyValues(true, true);
324
325 // by invoking this constructor we make sure that a common file will be created
326 // in future we should take this from OCDB and just forward per message
327 const static auto& ampl = o2::tpc::GEMAmplification::instance();
328}
329
330// ------------------------------------------------------------------
331void publish_master_env(const char* key, const char* value)
332{
333 // publish env variables as process master
334 std::stringstream str;
335 str << "O2SIMDIGIINTERNAL_" << getpid() << "_" << key;
336 LOG(info) << "Publishing master key " << str.str();
337 setenv(str.str().c_str(), value, 1);
338}
339
340const char* get_master_env(const char* key)
341{
342 // access internal env variables published by master process
343 std::stringstream str;
344 str << "O2SIMDIGIINTERNAL_" << getppid() << "_" << key;
345 // LOG(info) << "Looking up master key " << str.str();
346 return getenv(str.str().c_str());
347}
348
349std::shared_ptr<o2::parameters::GRPObject> readGRP(std::string const& inputGRP)
350{
351 auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
352 if (!grp) {
353 LOG(error) << "This workflow needs a valid GRP file to start";
354 return nullptr;
355 }
356 if (gIsMaster) {
357 grp->print();
358 }
359 return std::shared_ptr<o2::parameters::GRPObject>(grp);
360}
361
362// ------------------------------------------------------------------
363
364// Split a given string on a separator character
365std::vector<std::string> splitString(std::string const& src, char sep)
366{
367 std::vector<std::string> fields;
368 std::string token;
369 std::istringstream ss(src);
370
371 while (std::getline(ss, token, sep)) {
372 if (!token.empty()) {
373 fields.push_back(token);
374 }
375 }
376
377 return fields;
378}
379// ------------------------------------------------------------------
380
381// Filters detectors based on a white/black list provided via the onlyDet/skipDet CLI args
383 // detlist: A character-separated list of detectors
384 // unsetVal: The value when the option is unset
385 // separator: The character that separates the list of detectors defined in option
386 // mustContain: The nature of this DetFilterer. If true, it is a white lister
387 // i.e. option defines the list of allowed detectors. If false
388 // it is a black lister i.e defines the list of disallowed detectors.
389 DetFilterer(std::string const& detlist, std::string const& unsetVal, char separator, bool doWhiteListing)
390 {
391 // option is not set, nothing to do
392 if (detlist.compare(unsetVal) == 0) {
393 return;
394 }
395
396 std::vector<std::string> tokens = splitString(detlist, separator);
397
398 // Convert a vector of strings to one of o2::detectors::DetID
399 for (auto& token : tokens) {
400 ids.emplace_back(token.c_str());
401 }
402
403 isWhiteLister = doWhiteListing;
404 }
405
406 // isSet determines if a detector list was provided
407 // against which to filter
408 bool isSet()
409 {
410 return ids.size() > 0;
411 }
412
413 // accept determines if a given detector should be accepted
415 {
416 bool found = std::find(ids.begin(), ids.end(), id) != ids.end();
417 return found == isWhiteLister;
418 }
419
420 private:
421 std::vector<o2::detectors::DetID> ids;
422 bool isWhiteLister; // true = accept only detectors in the ids vector
423};
424
425// Helper function to define a white listing DetFilterer
426DetFilterer whitelister(std::string optionVal, std::string unsetValue, char separator)
427{
428 return DetFilterer(optionVal, unsetValue, separator, true);
429}
430
431// Helper function to define a black listing DetFilterer
432DetFilterer blacklister(std::string optionVal, std::string unsetValue, char separator)
433{
434 return DetFilterer(optionVal, unsetValue, separator, false);
435}
436
437// ------------------------------------------------------------------
438
442{
443 // check if we merely construct the topology to create help options
444 // if this is the case we don't need to read from GRP
445 bool helpasked = configcontext.helpOnCommandLine();
446 bool ismaster = isMasterWorkflowDefinition(configcontext);
447 gIsMaster = ismaster;
448
449 std::string dplProcessName = whoAmI(configcontext);
450 bool isDPLinternal = isInternalDPL(dplProcessName);
451 bool isDumpWorkflow = isDumpWorkflowInvocation(configcontext);
452 bool initServices = !isDPLinternal && !isDumpWorkflow && !ismaster;
453 // Reserve one entry which will be filled with the SimReaderSpec
454 // at the end. This places the processor at the beginning of the
455 // workflow in the upper left corner of the GUI.
456 WorkflowSpec specs(1);
457 WorkflowSpec digitizerSpecs; // collecting everything producing digits
458 WorkflowSpec writerSpecs; // collecting everything writing digits to files
459
460 using namespace o2::conf;
461 ConfigurableParam::updateFromFile(configcontext.options().get<std::string>("configFile"));
462
463 // Update the (declared) parameters if changed from the command line
464 // Note: In the future this should be done only on a dedicated processor managing
465 // the parameters and then propagated automatically to all devices
466 ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues"));
467 const auto& hbfu = o2::raw::HBFUtils::Instance();
468
469 // which sim productions to overlay and digitize
470 auto simPrefixes = splitString(configcontext.options().get<std::string>("sims"), ',');
471 // First, read the GRP to detect which components need instantiations
472 std::shared_ptr<o2::parameters::GRPObject const> grp(nullptr);
473
474 // lambda to access the GRP time start
475 auto getGRPStartTime = [](o2::parameters::GRPObject const* grp) {
476 const auto GRPTIMEKEY = "GRPTIMESTART";
477 if (gIsMaster && grp) {
478 // we publish a couple of things as environment variables
479 // this saves loading from ROOT file and hence duplicated file reading and
480 // initialization of the ROOT engine in each DPL device
481 auto t = grp->getTimeStart();
482 publish_master_env(GRPTIMEKEY, std::to_string(t).c_str());
483 return t;
484 } else {
485 auto tstr = get_master_env(GRPTIMEKEY);
486 if (!tstr) {
487 LOG(fatal) << "Expected env value not found";
488 }
489 // LOG(info) << "Found entry " << tstr;
490 return boost::lexical_cast<uint64_t>(tstr);
491 }
492 };
493
494 if (!helpasked) {
495 if (gIsMaster) {
496 grp = readGRP(simPrefixes[0]);
497 if (!grp) {
498 return WorkflowSpec{};
499 }
500 getGRPStartTime(grp.get());
501 }
502 if (!hbfu.startTime) { // HBFUtils.startTime was not set from the command line, set it from GRP
503 hbfu.setValue("HBFUtils.startTime", std::to_string(getGRPStartTime(grp.get())));
504 }
505 }
506
507 auto grpfile = o2::base::NameConf::getGRPFileName(simPrefixes[0]);
508 if (initServices) {
509 // init on a high level, the time for the CCDB queries
510 // we expect that digitizers do not play with the manager themselves
511 // this will only be needed until digitizers take CCDB objects via DPL mechanism
512
513 // fix the timestamp for CCDB manager in the same way as for DPL-CCDB-fetcher
516 setTimingInfoInHeaders(dh, dph);
517 LOG(info) << "Setting timestamp of BasicCCDBManager to " << dph.creation;
519 // activate caching
521 // this is asking the manager to check validity only locally - no further query to server done
523 }
524 // update the digitization configuration with the right geometry file
525 // we take the geometry from the first simPrefix (could actually check if they are
526 // all compatible)
527 ConfigurableParam::setValue("DigiParams.digitizationgeometry_prefix", simPrefixes[0]);
528 ConfigurableParam::setValue("DigiParams.grpfile", grpfile);
529
530 LOG(info) << "MC-TRUTH " << !configcontext.options().get<bool>("disable-mc");
531 bool mctruth = !configcontext.options().get<bool>("disable-mc");
532 ConfigurableParam::setValue("DigiParams", "mctruth", mctruth);
533
534 // write the configuration used for the digitizer workflow
535 // (In the case, in which we call multiple processes to do digitization,
536 // only one of them should write this file ... but take the complete configKeyValue line)
537 if (ismaster) {
538 if (!configcontext.options().get<bool>("disable-write-ini")) {
540 }
541 }
542
543 // onlyDet takes precedence on skipDet
544 DetFilterer filterers[2] = {
545 whitelister(configcontext.options().get<std::string>("onlyDet"), "none", ','),
546 blacklister(configcontext.options().get<std::string>("skipDet"), "none", ',')};
547
548 auto accept = [&configcontext, &filterers](o2::detectors::DetID id) {
549 for (auto& f : filterers) {
550 if (f.isSet()) {
551 return f.accept(id);
552 }
553 }
554 // accept all if neither onlyDet/skipDet are provided
555 return true;
556 };
557
558 // lambda to extract detectors which are enabled in the workflow
559 // will complain if user gave wrong input in construction of DetID
560 auto isEnabled = [&configcontext, &filterers, accept, grp, helpasked](o2::detectors::DetID id) {
561 auto isInGRPReadout = [grp](o2::detectors::DetID id) {
562 std::stringstream str;
563 str << "GRPDETKEY_" << id.getName();
564 if (gIsMaster and grp.get() != nullptr) {
565 auto ok = grp->isDetReadOut(id);
566 if (ok) {
567 publish_master_env(str.str().c_str(), "ON");
568 }
569 return ok;
570 } else {
571 // we should have published important GRP info as
572 // environment variables in order to not having to read GRP via ROOT
573 // in all the processes
574 return get_master_env(str.str().c_str()) != nullptr;
575 }
576 };
577
578 if (helpasked) {
579 return true;
580 }
581 if (configcontext.options().get<bool>("only-context")) {
582 // no detector necessary if we are asked to produce only the digitization context
583 return false;
584 }
585 auto accepted = accept(id);
586
587 // always comply with the filter choice?
588 auto forceAccepted = configcontext.options().get<bool>("forceSelectedDets");
589 bool is_ingrp = isInGRPReadout(id);
590 // final decision on whether or not this detector will be digitized
591 auto isRun = accepted && (forceAccepted || is_ingrp);
592 if (gIsMaster) {
593 LOG(info) << id.getName()
594 << " is in grp? " << (is_ingrp ? "yes" : "no") << ";"
595 << " is taken although not in grp? " << (!is_ingrp && (accepted && forceAccepted) ? "yes" : "no") << ";"
596 << " is skipped? " << (!accepted ? "yes" : "no") << ";"
597 << " is run? " << (isRun ? "yes" : "no");
598 }
599 return isRun;
600 };
601
602 std::vector<o2::detectors::DetID> detList; // list of participating detectors
603
604 // keeps track of which tpc sectors to process
605 std::vector<int> tpcsectors;
606
607 if (isEnabled(o2::detectors::DetID::TPC)) {
608 if (!helpasked && ismaster) {
609 initTPC(hbfu.startTime);
610 }
611
612 tpcsectors = o2::RangeTokenizer::tokenize<int>(configcontext.options().get<std::string>("tpc-sectors"));
613 // only one lane for the help printout
614 auto lanes = helpasked ? 1 : getNumTPCLanes(tpcsectors, configcontext);
615 detList.emplace_back(o2::detectors::DetID::TPC);
616
617 auto internalwrite = configcontext.options().get<bool>("tpc-chunked-writer");
618 auto distortionType = configcontext.options().get<int>("tpc-distortion-type");
619 WorkflowSpec tpcPipelines = o2::tpc::getTPCDigitizerSpec(lanes, tpcsectors, mctruth, internalwrite, distortionType);
620 specs.insert(specs.end(), tpcPipelines.begin(), tpcPipelines.end());
621
622 if (configcontext.options().get<std::string>("tpc-reco-type").empty() == false) {
623 throw std::runtime_error("option 'tpc-reco-type' is deprecated, please connect workflows on the command line by pipe");
624 }
625 if (!internalwrite) {
626 // for writing digits to disc
627 specs.emplace_back(o2::tpc::getTPCDigitRootWriterSpec(tpcsectors, mctruth));
628 }
629 }
630
631 // first 36 channels are reserved for the TPC
632 const int firstOtherChannel = 36;
633 int fanoutsize = firstOtherChannel;
634
635 // the ITS part
636 if (isEnabled(o2::detectors::DetID::ITS)) {
637 detList.emplace_back(o2::detectors::DetID::ITS);
638 // connect the ITS digitization
639 digitizerSpecs.emplace_back(o2::itsmft::getITSDigitizerSpec(fanoutsize++, mctruth));
640 // connect ITS digit writer
641 writerSpecs.emplace_back(o2::itsmft::getITSDigitWriterSpec(mctruth));
642 }
643
644#ifdef ENABLE_UPGRADES
645 // the ITS3 part
646 if (isEnabled(o2::detectors::DetID::IT3)) {
647 detList.emplace_back(o2::detectors::DetID::IT3);
648 // connect the ITS digitization
649 specs.emplace_back(o2::its3::getITS3DigitizerSpec(fanoutsize++, mctruth));
650 // // connect ITS digit writer
651 specs.emplace_back(o2::its3::getITS3DigitWriterSpec(mctruth));
652 }
653
654 // the ALICE 3 TRK part
655 if (isEnabled(o2::detectors::DetID::TRK)) {
656 detList.emplace_back(o2::detectors::DetID::TRK);
657 // connect the ALICE 3 TRK digitization
658 specs.emplace_back(o2::trk::getTRKDigitizerSpec(fanoutsize++, mctruth));
659 // connect the ALICE 3 TRK digit writer
660 specs.emplace_back(o2::trk::getTRKDigitWriterSpec(mctruth));
661 }
662#endif
663
664 // the MFT part
665 if (isEnabled(o2::detectors::DetID::MFT)) {
666 detList.emplace_back(o2::detectors::DetID::MFT);
667 // connect the MFT digitization
668 digitizerSpecs.emplace_back(o2::itsmft::getMFTDigitizerSpec(fanoutsize++, mctruth));
669 // connect MFT digit writer
670 writerSpecs.emplace_back(o2::itsmft::getMFTDigitWriterSpec(mctruth));
671 }
672
673 // the TOF part
674 if (isEnabled(o2::detectors::DetID::TOF)) {
675 auto useCCDB = configcontext.options().get<bool>("use-ccdb-tof");
676 useCCDB |= configcontext.options().get<bool>("ccdb-tof-sa");
677 auto ccdb_url_tof = o2::base::NameConf::getCCDBServer();
678 auto timestamp = o2::raw::HBFUtils::Instance().startTime / 1000;
679 detList.emplace_back(o2::detectors::DetID::TOF);
680 // connect the TOF digitization
681 // printf("TOF Setting: use-ccdb = %d ---- ccdb url=%s ---- timestamp=%ld\n", useCCDB, ccdb_url_tof.c_str(), timestamp);
682
683 digitizerSpecs.emplace_back(o2::tof::getTOFDigitizerSpec(fanoutsize++, useCCDB, mctruth, ccdb_url_tof.c_str(), timestamp));
684 // add TOF digit writer
685 writerSpecs.emplace_back(o2::tof::getTOFDigitWriterSpec(mctruth));
686 }
687
688 // the FT0 part
689 if (isEnabled(o2::detectors::DetID::FT0)) {
690 auto useCCDB = configcontext.options().get<bool>("use-ccdb-ft0");
691 auto timestamp = o2::raw::HBFUtils::Instance().startTime;
692 detList.emplace_back(o2::detectors::DetID::FT0);
693 // connect the FT0 digitization
694 specs.emplace_back(o2::ft0::getFT0DigitizerSpec(fanoutsize++, mctruth, useCCDB));
695 // connect the FIT digit writer
696 writerSpecs.emplace_back(o2::ft0::getFT0DigitWriterSpec(mctruth));
697 }
698
699 // the FV0 part
700 if (isEnabled(o2::detectors::DetID::FV0)) {
701 detList.emplace_back(o2::detectors::DetID::FV0);
702 // connect the FV0 digitization
703 digitizerSpecs.emplace_back(o2::fv0::getFV0DigitizerSpec(fanoutsize++, mctruth));
704 // connect the FV0 digit writer
705 writerSpecs.emplace_back(o2::fv0::getFV0DigitWriterSpec(mctruth));
706 }
707
708 // the EMCal part
709 if (isEnabled(o2::detectors::DetID::EMC)) {
710 auto useCCDB = !configcontext.options().get<bool>("no-use-ccdb-emc");
711 bool requireCTPInputs = !configcontext.options().get<bool>("no-require-ctpinputs-emc");
712 detList.emplace_back(o2::detectors::DetID::EMC);
713 // connect the EMCal digitization
714 digitizerSpecs.emplace_back(o2::emcal::getEMCALDigitizerSpec(fanoutsize++, requireCTPInputs, mctruth, useCCDB));
715 // connect the EMCal digit writer
716 writerSpecs.emplace_back(o2::emcal::getEMCALDigitWriterSpec(mctruth));
717 }
718
719 // add HMPID
720 if (isEnabled(o2::detectors::DetID::HMP)) {
721 detList.emplace_back(o2::detectors::DetID::HMP);
722 // connect the HMP digitization
723 digitizerSpecs.emplace_back(o2::hmpid::getHMPIDDigitizerSpec(fanoutsize++, mctruth));
724 // connect the HMP digit writer
725 writerSpecs.emplace_back(o2::hmpid::getHMPIDDigitWriterSpec(mctruth));
726 }
727
728 // add ZDC
729 if (isEnabled(o2::detectors::DetID::ZDC)) {
730 detList.emplace_back(o2::detectors::DetID::ZDC);
731 // connect the ZDC digitization
732 digitizerSpecs.emplace_back(o2::zdc::getZDCDigitizerSpec(fanoutsize++, mctruth));
733 // connect the ZDC digit writer
734 writerSpecs.emplace_back(o2::zdc::getZDCDigitWriterDPLSpec(mctruth, true));
735 }
736
737 // add TRD
738 if (isEnabled(o2::detectors::DetID::TRD)) {
739 detList.emplace_back(o2::detectors::DetID::TRD);
740 // connect the TRD digitization
741 specs.emplace_back(o2::trd::getTRDDigitizerSpec(fanoutsize++, mctruth));
742 auto disableTrapSim = configcontext.options().get<bool>("disable-trd-trapsim");
743 auto trdDigitDownscaling = configcontext.options().get<int>("trd-digit-downscaling");
744 if (!disableTrapSim) {
745 // connect the TRD TRAP simulator
746 specs.emplace_back(o2::trd::getTRDTrapSimulatorSpec(mctruth, trdDigitDownscaling));
747 // connect to the device to write out the tracklets.
748 specs.emplace_back(o2::trd::getTRDTrackletWriterSpec(mctruth));
749 // connect the TRD digit writer expecting input from TRAP simulation
750 specs.emplace_back(o2::trd::getTRDDigitWriterSpec(mctruth, false));
751 } else {
752 // connect the TRD digit writer expecting input from TRD digitizer
753 specs.emplace_back(o2::trd::getTRDDigitWriterSpec(mctruth, true));
754 }
755 }
756
757 // add MUON MCH
758 if (isEnabled(o2::detectors::DetID::MCH)) {
759 detList.emplace_back(o2::detectors::DetID::MCH);
760 // connect the MUON MCH digitization
761 digitizerSpecs.emplace_back(o2::mch::getMCHDigitizerSpec(fanoutsize++, mctruth));
762 // connect the MUON MCH digit writer
763 writerSpecs.emplace_back(o2::mch::getMCHDigitWriterSpec(mctruth));
764 }
765
766 // add MID
767 if (isEnabled(o2::detectors::DetID::MID)) {
768 detList.emplace_back(o2::detectors::DetID::MID);
769 // connect the MID digitization
770 digitizerSpecs.emplace_back(o2::mid::getMIDDigitizerSpec(fanoutsize++, mctruth));
771 // connect the MID digit writer
772 writerSpecs.emplace_back(o2::mid::getMIDDigitWriterSpec(mctruth));
773 }
774
775 // add FDD
776 if (isEnabled(o2::detectors::DetID::FDD)) {
777 detList.emplace_back(o2::detectors::DetID::FDD);
778 // connect the FDD digitization
779 digitizerSpecs.emplace_back(o2::fdd::getFDDDigitizerSpec(fanoutsize++, mctruth));
780 // connect the FDD digit writer
781 writerSpecs.emplace_back(o2::fdd::getFDDDigitWriterSpec(mctruth));
782 }
783
784 // the PHOS part
785 if (isEnabled(o2::detectors::DetID::PHS)) {
786 detList.emplace_back(o2::detectors::DetID::PHS);
787 // connect the PHOS digitization
788 digitizerSpecs.emplace_back(o2::phos::getPHOSDigitizerSpec(fanoutsize++, mctruth));
789 // add PHOS writer
790 writerSpecs.emplace_back(o2::phos::getPHOSDigitWriterSpec(mctruth));
791 }
792
793 // the CPV part
794 if (isEnabled(o2::detectors::DetID::CPV)) {
795 detList.emplace_back(o2::detectors::DetID::CPV);
796 // connect the CPV digitization
797 digitizerSpecs.emplace_back(o2::cpv::getCPVDigitizerSpec(fanoutsize++, mctruth));
798 // add PHOS writer
799 writerSpecs.emplace_back(o2::cpv::getCPVDigitWriterSpec(mctruth));
800 }
801 // the CTP part
802 if (isEnabled(o2::detectors::DetID::CTP)) {
803 detList.emplace_back(o2::detectors::DetID::CTP);
804 float lumiScaler = configcontext.options().get<float>("store-ctp-lumi");
805 // connect the CTP digitization
806 specs.emplace_back(o2::ctp::getCTPDigitizerSpec(fanoutsize++, detList, lumiScaler));
807 // connect the CTP digit writer
808 specs.emplace_back(o2::ctp::getDigitWriterSpec(lumiScaler >= 0));
809 }
810 // GRP updater: must come after all detectors since requires their list
811 if (!configcontext.options().get<bool>("only-context")) {
812 writerSpecs.emplace_back(o2::parameters::getGRPUpdaterSpec(simPrefixes[0], detList));
813 }
814
815 bool combine = configcontext.options().get<bool>("combine-devices");
816 if (!combine) {
817 for (auto& s : digitizerSpecs) {
818 specs.push_back(s);
819 }
820 for (auto& s : writerSpecs) {
821 specs.push_back(s);
822 }
823 } else {
824 std::vector<DataProcessorSpec> remaining;
825 specs.push_back(specCombiner("Digitizations", digitizerSpecs, remaining));
826 specs.push_back(specCombiner("Writers", writerSpecs, remaining));
827 for (auto& s : remaining) {
828 specs.push_back(s);
829 }
830 }
831
832 // For reasons of offering homegenous behaviour (consistent options to outside scripts),
833 // we require that at least one of the devices above listens to the DPL CCDB fetcher.
834 // Verify this or insert a dummy channel in one of the devices. (This cannot be done in the SimReader
835 // as the SimReader is the source device injecting the timing information).
836 // In future this code can serve as a check that all digitizers access CCDB via the DPL fetcher.
837 bool haveCCDBInputSpec = false;
838 for (auto spec : specs) {
839 for (auto in : spec.inputs) {
840 if (in.lifetime == Lifetime::Condition) {
841 haveCCDBInputSpec = true;
842 break;
843 }
844 }
845 }
846 if (!haveCCDBInputSpec && specs.size() > 0) {
847 LOG(info) << "No one uses DPL CCDB .. injecting a dummy CCDB query into " << specs.back().name;
848 specs.back().inputs.emplace_back("_dummyOrbitReset", "CTP", "ORBITRESET", 0, Lifetime::Condition,
849 ccdbParamSpec("CTP/Calib/OrbitReset"));
850 }
851
852 // The SIM Reader. NEEDS TO BE LAST
853 bool withTrigger = configcontext.options().get<bool>("with-trigger");
854 LOG(info) << " TRIGGER " << withTrigger;
855 specs[0] = o2::steer::getSimReaderSpec({firstOtherChannel, fanoutsize}, simPrefixes, tpcsectors, withTrigger);
856 return specs;
857}
Simple interface to the CDB manager.
Definition of the GEM amplification.
Header of the General Run Parameters object.
Definition of the Names Generator class.
Helper function to tokenize sequences and ranges of integral numbers.
std::vector< std::string > splitString(std::string const &src, char sep)
const char * get_master_env(const char *key)
int getNumTPCLanes(std::vector< int > const &sectors, ConfigContext const &configcontext)
DetFilterer whitelister(std::string optionVal, std::string unsetValue, char separator)
WorkflowSpec defineDataProcessing(ConfigContext const &configcontext)
This function hooks up the the workflow specifications into the DPL driver.
void setTimingInfoInHeaders(o2::header::DataHeader &dh, o2::framework::DataProcessingHeader &dph)
DetFilterer blacklister(std::string optionVal, std::string unsetValue, char separator)
void customize(std::vector< o2::framework::CompletionPolicy > &policies)
void initTPC(long timestamp)
void publish_master_env(const char *key, const char *value)
std::shared_ptr< o2::parameters::GRPObject > readGRP(std::string const &inputGRP)
std::ostringstream debug
StringRef key
static std::string getGRPFileName(const std::string_view prefix=STANDARDSIMPREFIX)
Definition NameConf.cxx:58
static constexpr std::string_view DIGITIZATIONCONFIGFILE
Definition NameConf.h:89
static std::string getCCDBServer()
Definition NameConf.cxx:110
static BasicCCDBManager & instance()
void setCaching(bool v)
disable or enable caching
void setTimestamp(long t)
set timestamp cache for all queries
void setLocalObjectValidityChecking(bool v=true)
set the flag to check object validity before CCDB query
void printKeyValues(bool showProv=true, bool useLogger=false, bool withPadding=true, bool showHash=true) const final
static void writeINI(std::string const &filename, std::string const &keyOnly="")
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr ID CTP
Definition DetID.h:79
static constexpr ID FV0
Definition DetID.h:76
static constexpr ID PHS
Definition DetID.h:67
static constexpr ID MID
Definition DetID.h:73
static constexpr ID ITS
Definition DetID.h:63
static constexpr ID MFT
Definition DetID.h:71
static constexpr ID ZDC
Definition DetID.h:74
static constexpr ID FT0
Definition DetID.h:75
static constexpr ID CPV
Definition DetID.h:68
static constexpr ID TRD
Definition DetID.h:65
static constexpr ID TPC
Definition DetID.h:64
static constexpr ID EMC
Definition DetID.h:69
static constexpr ID FDD
Definition DetID.h:77
static constexpr ID MCH
Definition DetID.h:72
static constexpr ID HMP
Definition DetID.h:70
static constexpr ID TOF
Definition DetID.h:66
ConfigParamRegistry & options() const
static GRPObject * loadFrom(const std::string &grpFileName="")
static CDBInterface & instance()
static GEMAmplification & instance()
Default constructor.
static constexpr int MAXSECTOR
Definition Sector.h:44
GLenum src
Definition glcorearb.h:1767
GLuint * ids
Definition glcorearb.h:647
GLdouble f
Definition glcorearb.h:310
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLintptr offset
Definition glcorearb.h:660
GLuint id
Definition glcorearb.h:650
constexpr double LHCOrbitMUS
DataProcessorSpec getCPVDigitizerSpec(int channel, bool mctruth)
Create new digitizer spec.
o2::framework::DataProcessorSpec getCPVDigitWriterSpec(bool mctruth=true)
framework::DataProcessorSpec getDigitWriterSpec(bool raw=true)
o2::framework::DataProcessorSpec getCTPDigitizerSpec(int channel, std::vector< o2::detectors::DetID > &detList, float ctpLumiScaler, bool mctruth)
o2::framework::DataProcessorSpec getEMCALDigitWriterSpec(bool mctruth=true)
Create new digits writer spec.
o2::framework::DataProcessorSpec getEMCALDigitizerSpec(int channel, bool requireCTPInput, bool mctruth=true, bool useccdb=true)
Create new digitizer spec.
o2::framework::DataProcessorSpec getFDDDigitizerSpec(int channel, bool mctruth)
o2::framework::DataProcessorSpec getFDDDigitWriterSpec(bool mctruth=true, bool trigInp=true)
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
o2::framework::DataProcessorSpec specCombiner(std::string const &name, std::vector< DataProcessorSpec > const &speccollection, std::vector< DataProcessorSpec > &remaining)
bool isInternalDPL(std::string const &name)
bool isMasterWorkflowDefinition(ConfigContext const &configcontext)
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
bool isDumpWorkflowInvocation(ConfigContext const &configcontext)
std::string whoAmI(ConfigContext const &configcontext)
std::vector< DataProcessorSpec > WorkflowSpec
o2::framework::DataProcessorSpec getFT0DigitizerSpec(int channel, bool mctruth, bool useCCDB)
framework::DataProcessorSpec getFT0DigitWriterSpec(bool mctruth=true, bool trigInp=true)
create a processor spec
o2::framework::DataProcessorSpec getFV0DigitizerSpec(int channel, bool mctruth)
framework::DataProcessorSpec getFV0DigitWriterSpec(bool mctruth=true, bool trigInp=true)
create a processor spec
o2::framework::DataProcessorSpec getHMPIDDigitWriterSpec(bool mctruth=true)
o2::framework::DataProcessorSpec getHMPIDDigitizerSpec(int channel, bool mctruth)
o2::framework::DataProcessorSpec getITS3DigitWriterSpec(bool mctruth=true, bool dec=false, bool calib=false)
DataProcessorSpec getITS3DigitizerSpec(int channel, bool mctruth)
o2::framework::DataProcessorSpec getITSDigitWriterSpec(bool mctruth=true, bool dec=false, bool calib=false)
o2::framework::DataProcessorSpec getMFTDigitWriterSpec(bool mctruth=true, bool dec=false, bool calib=false)
DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth)
DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth)
o2::framework::DataProcessorSpec getMCHDigitWriterSpec(bool mctruth)
o2::framework::DataProcessorSpec getMCHDigitizerSpec(int channel, bool mctruth)
o2::framework::DataProcessorSpec getMIDDigitWriterSpec(bool mctruth)
o2::framework::DataProcessorSpec getMIDDigitizerSpec(int channel, bool mctruth)
o2::framework::DataProcessorSpec getGRPUpdaterSpec(const std::string &prefix, const std::vector< o2::detectors::DetID > &detList)
create the processor spec
o2::framework::DataProcessorSpec getPHOSDigitWriterSpec(bool mctruth)
DataProcessorSpec getPHOSDigitizerSpec(int channel, bool mctruth)
Create new digitizer spec.
DataProcessorSpec getSimReaderSpec(SubspecRange range, const std::vector< std::string > &simprefixes, const std::vector< int > &tpcsectors, bool withTrigger)
o2::framework::DataProcessorSpec getTOFDigitWriterSpec(bool useMC=1, bool writeErr=0)
DataProcessorSpec getTOFDigitizerSpec(int channel, bool useCCDB, bool mctruth, std::string ccdb_url, int timestamp)
const std::unordered_map< CDBType, const std::string > CDBTypeMap
Storage name in CCDB for each calibration and parameter type.
Definition CDBTypes.h:96
o2::framework::DataProcessorSpec getTPCDigitRootWriterSpec(std::vector< int > const &laneConfiguration, bool mctruth)
o2::framework::DataProcessorSpec getTPCDigitizerSpec(int channel, bool writeGRP, bool mctruth, bool internalwriter, int distortionType)
@ CalPadGainFull
Full pad gain calibration.
@ ParGas
Parameter for Gas.
o2::framework::DataProcessorSpec getTRDDigitWriterSpec(bool mctruth=true, bool inpFromDigitizer=true)
o2::framework::DataProcessorSpec getTRDDigitizerSpec(int channel, bool mctruth=true)
o2::framework::DataProcessorSpec getTRDTrapSimulatorSpec(bool useMC, int digitDownscaling)
o2::framework::DataProcessorSpec getTRDTrackletWriterSpec(bool useMC)
o2::framework::DataProcessorSpec getTRKDigitWriterSpec(bool mctruth=true, bool dec=false, bool calib=false)
DataProcessorSpec getTRKDigitizerSpec(int channel, bool mctruth)
o2::framework::DataProcessorSpec getZDCDigitizerSpec(int channel, bool mctruth)
framework::DataProcessorSpec getZDCDigitWriterDPLSpec(bool mctruth, bool simVersion)
create a processor spec
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
DetFilterer(std::string const &detlist, std::string const &unsetVal, char separator, bool doWhiteListing)
bool accept(o2::detectors::DetID id)
static CompletionPolicy defineByName(std::string const &name, CompletionPolicy::CompletionOp op)
static CompletionPolicy consumeWhenAnyWithAllConditions(const char *name, CompletionPolicy::Matcher matcher)
When any of the parts of the record have been received, consume them.
the main header struct
Definition DataHeader.h:618
TFCounterType tfCounter
Definition DataHeader.h:679
TForbitType firstTForbit
Definition DataHeader.h:674
RunNumberType runNumber
Definition DataHeader.h:684
uint64_t startTime
absolute time in ms corresponding to the start of the MC run
Definition HBFUtils.h:144
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
const std::string str