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
225void customize(std::vector<o2::framework::DispatchPolicy>& policies)
226{
228 // we customize all devices to dispatch data immediately
229 auto matcher = [](auto const& spec) {
230 return spec.name == "SimReader";
231 };
232 policies.push_back({"prompt-for-simreader", matcher, DispatchOp::WhenReady});
233}
234
236{
237 const auto& hbfu = o2::raw::HBFUtils::Instance();
238 const auto offset = int64_t(hbfu.getFirstIRofTF({0, hbfu.orbitFirstSampled}).orbit);
239 const auto increment = int64_t(hbfu.nHBFPerTF);
240 const auto startTime = hbfu.startTime;
241 const auto orbitFirst = hbfu.orbitFirst;
242 dh.firstTForbit = offset + increment * dh.tfCounter;
243 dh.runNumber = hbfu.runNumber;
244 dph.creation = startTime + (dh.firstTForbit - orbitFirst) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
245}
246
247void customize(std::vector<o2::framework::CallbacksPolicy>& policies)
248{
249 // we customize the time information sent in DPL headers
250 policies.push_back(o2::framework::CallbacksPolicy{
251 [](o2::framework::DeviceSpec const& spec, o2::framework::ConfigContext const& context) -> bool {
252 return true;
253 },
255 // simple linear enumeration from already updated HBFUtils (set via config key values)
258 setTimingInfoInHeaders(dh, dph);
259 LOG(info) << "Setting DPL-header firstTForbit to " << dh.firstTForbit;
260 LOG(info) << "Setting DPL-header runNumber to " << dh.runNumber;
261 LOG(info) << "Setting DPL-header timeframe creation time to " << dph.creation;
262 });
263 }} // end of struct
264 );
265}
266
267// ------------------------------------------------------------------
268
270
271// extract num TPC lanes, a lane is a streaming line of processors (digitizer-clusterizer-etc)
272// by default this will be std::max(the number of physical cores, numberofsectors)
273// as a temporary means to fully use a machine and as a way to play with different topologies
274int getNumTPCLanes(std::vector<int> const& sectors, ConfigContext const& configcontext)
275{
276 auto lanes = configcontext.options().get<int>("tpc-lanes");
277 if (lanes < 0) {
278 if (gIsMaster) {
279 LOG(fatal) << "tpc-lanes needs to be positive\n";
280 }
281 return 0;
282 }
283 // crosscheck with sectors
284 return std::min(lanes, (int)sectors.size());
285}
286
287// ------------------------------------------------------------------
288
289void initTPC(long timestamp)
290{
291 // We only want to do this for the DPL master
292 // I am not aware of an easy way to query if "I am DPL master" so
293 // using for the moment a mechanism defining/setting an environment variable
294 // with the parent ID and query inside forks if this environment variable exists
295 // (it assumes fundamentally that the master executes this function first)
296 std::stringstream streamthis;
297 std::stringstream streamparent;
298
299 streamthis << "TPCGEMINIT_PID" << getpid();
300 streamparent << "TPCGEMINIT_PID" << getppid();
301 if (getenv(streamparent.str().c_str())) {
302 LOG(debug) << "GEM ALREADY INITIALIZED ... SKIPPING HERE";
303 return;
304 }
305
306 LOG(debug) << "INITIALIZING TPC GEMAmplification";
307 setenv(streamthis.str().c_str(), "ON", 1);
308
310 cdb.setUseDefaults();
311
312 // IMPORTANT: load ParameterGEM, ParameterGas and CalPadGainFull from CCDB to correctly init GEMAmplification
313 auto& ccdbManager = o2::ccdb::BasicCCDBManager::instance();
314 ccdbManager.getSpecific<o2::tpc::ParameterGEM>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::ParGEM), timestamp);
315 LOGP(info, "initTPC: TPC GEM param, Gas param + CalPadGainFull updated for time {}", timestamp);
316 ccdbManager.getSpecific<o2::tpc::CalPad>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::CalPadGainFull), timestamp);
317 ccdbManager.getSpecific<o2::tpc::ParameterGas>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::ParGas), timestamp);
318
320 o2::tpc::ParameterGas::Instance().printKeyValues(true, true);
321
322 // by invoking this constructor we make sure that a common file will be created
323 // in future we should take this from OCDB and just forward per message
324 const static auto& ampl = o2::tpc::GEMAmplification::instance();
325}
326
327// ------------------------------------------------------------------
328void publish_master_env(const char* key, const char* value)
329{
330 // publish env variables as process master
331 std::stringstream str;
332 str << "O2SIMDIGIINTERNAL_" << getpid() << "_" << key;
333 LOG(info) << "Publishing master key " << str.str();
334 setenv(str.str().c_str(), value, 1);
335}
336
337const char* get_master_env(const char* key)
338{
339 // access internal env variables published by master process
340 std::stringstream str;
341 str << "O2SIMDIGIINTERNAL_" << getppid() << "_" << key;
342 // LOG(info) << "Looking up master key " << str.str();
343 return getenv(str.str().c_str());
344}
345
346std::shared_ptr<o2::parameters::GRPObject> readGRP(std::string const& inputGRP)
347{
348 auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
349 if (!grp) {
350 LOG(error) << "This workflow needs a valid GRP file to start";
351 return nullptr;
352 }
353 if (gIsMaster) {
354 grp->print();
355 }
356 return std::shared_ptr<o2::parameters::GRPObject>(grp);
357}
358
359// ------------------------------------------------------------------
360
361// Split a given string on a separator character
362std::vector<std::string> splitString(std::string const& src, char sep)
363{
364 std::vector<std::string> fields;
365 std::string token;
366 std::istringstream ss(src);
367
368 while (std::getline(ss, token, sep)) {
369 if (!token.empty()) {
370 fields.push_back(token);
371 }
372 }
373
374 return fields;
375}
376// ------------------------------------------------------------------
377
378// Filters detectors based on a white/black list provided via the onlyDet/skipDet CLI args
380 // detlist: A character-separated list of detectors
381 // unsetVal: The value when the option is unset
382 // separator: The character that separates the list of detectors defined in option
383 // mustContain: The nature of this DetFilterer. If true, it is a white lister
384 // i.e. option defines the list of allowed detectors. If false
385 // it is a black lister i.e defines the list of disallowed detectors.
386 DetFilterer(std::string const& detlist, std::string const& unsetVal, char separator, bool doWhiteListing)
387 {
388 // option is not set, nothing to do
389 if (detlist.compare(unsetVal) == 0) {
390 return;
391 }
392
393 std::vector<std::string> tokens = splitString(detlist, separator);
394
395 // Convert a vector of strings to one of o2::detectors::DetID
396 for (auto& token : tokens) {
397 ids.emplace_back(token.c_str());
398 }
399
400 isWhiteLister = doWhiteListing;
401 }
402
403 // isSet determines if a detector list was provided
404 // against which to filter
405 bool isSet()
406 {
407 return ids.size() > 0;
408 }
409
410 // accept determines if a given detector should be accepted
412 {
413 bool found = std::find(ids.begin(), ids.end(), id) != ids.end();
414 return found == isWhiteLister;
415 }
416
417 private:
418 std::vector<o2::detectors::DetID> ids;
419 bool isWhiteLister; // true = accept only detectors in the ids vector
420};
421
422// Helper function to define a white listing DetFilterer
423DetFilterer whitelister(std::string optionVal, std::string unsetValue, char separator)
424{
425 return DetFilterer(optionVal, unsetValue, separator, true);
426}
427
428// Helper function to define a black listing DetFilterer
429DetFilterer blacklister(std::string optionVal, std::string unsetValue, char separator)
430{
431 return DetFilterer(optionVal, unsetValue, separator, false);
432}
433
434// ------------------------------------------------------------------
435
439{
440 // check if we merely construct the topology to create help options
441 // if this is the case we don't need to read from GRP
442 bool helpasked = configcontext.helpOnCommandLine();
443 bool ismaster = isMasterWorkflowDefinition(configcontext);
444 gIsMaster = ismaster;
445
446 std::string dplProcessName = whoAmI(configcontext);
447 bool isDPLinternal = isInternalDPL(dplProcessName);
448 bool isDumpWorkflow = isDumpWorkflowInvocation(configcontext);
449 bool initServices = !isDPLinternal && !isDumpWorkflow && !ismaster;
450 // Reserve one entry which will be filled with the SimReaderSpec
451 // at the end. This places the processor at the beginning of the
452 // workflow in the upper left corner of the GUI.
453 WorkflowSpec specs(1);
454 WorkflowSpec digitizerSpecs; // collecting everything producing digits
455 WorkflowSpec writerSpecs; // collecting everything writing digits to files
456
457 using namespace o2::conf;
458 ConfigurableParam::updateFromFile(configcontext.options().get<std::string>("configFile"));
459
460 // Update the (declared) parameters if changed from the command line
461 // Note: In the future this should be done only on a dedicated processor managing
462 // the parameters and then propagated automatically to all devices
463 ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues"));
464 const auto& hbfu = o2::raw::HBFUtils::Instance();
465
466 // which sim productions to overlay and digitize
467 auto simPrefixes = splitString(configcontext.options().get<std::string>("sims"), ',');
468 // First, read the GRP to detect which components need instantiations
469 std::shared_ptr<o2::parameters::GRPObject const> grp(nullptr);
470
471 // lambda to access the GRP time start
472 auto getGRPStartTime = [](o2::parameters::GRPObject const* grp) {
473 const auto GRPTIMEKEY = "GRPTIMESTART";
474 if (gIsMaster && grp) {
475 // we publish a couple of things as environment variables
476 // this saves loading from ROOT file and hence duplicated file reading and
477 // initialization of the ROOT engine in each DPL device
478 auto t = grp->getTimeStart();
479 publish_master_env(GRPTIMEKEY, std::to_string(t).c_str());
480 return t;
481 } else {
482 auto tstr = get_master_env(GRPTIMEKEY);
483 if (!tstr) {
484 LOG(fatal) << "Expected env value not found";
485 }
486 // LOG(info) << "Found entry " << tstr;
487 return boost::lexical_cast<uint64_t>(tstr);
488 }
489 };
490
491 if (!helpasked) {
492 if (gIsMaster) {
493 grp = readGRP(simPrefixes[0]);
494 if (!grp) {
495 return WorkflowSpec{};
496 }
497 getGRPStartTime(grp.get());
498 }
499 if (!hbfu.startTime) { // HBFUtils.startTime was not set from the command line, set it from GRP
500 hbfu.setValue("HBFUtils.startTime", std::to_string(getGRPStartTime(grp.get())));
501 }
502 }
503
504 auto grpfile = o2::base::NameConf::getGRPFileName(simPrefixes[0]);
505 if (initServices) {
506 // init on a high level, the time for the CCDB queries
507 // we expect that digitizers do not play with the manager themselves
508 // this will only be needed until digitizers take CCDB objects via DPL mechanism
509
510 // fix the timestamp for CCDB manager in the same way as for DPL-CCDB-fetcher
513 setTimingInfoInHeaders(dh, dph);
514 LOG(info) << "Setting timestamp of BasicCCDBManager to " << dph.creation;
516 // activate caching
518 // this is asking the manager to check validity only locally - no further query to server done
520 }
521 // update the digitization configuration with the right geometry file
522 // we take the geometry from the first simPrefix (could actually check if they are
523 // all compatible)
524 ConfigurableParam::setValue("DigiParams.digitizationgeometry_prefix", simPrefixes[0]);
525 ConfigurableParam::setValue("DigiParams.grpfile", grpfile);
526
527 LOG(info) << "MC-TRUTH " << !configcontext.options().get<bool>("disable-mc");
528 bool mctruth = !configcontext.options().get<bool>("disable-mc");
529 ConfigurableParam::setValue("DigiParams", "mctruth", mctruth);
530
531 // write the configuration used for the digitizer workflow
532 // (In the case, in which we call multiple processes to do digitization,
533 // only one of them should write this file ... but take the complete configKeyValue line)
534 if (ismaster) {
535 if (!configcontext.options().get<bool>("disable-write-ini")) {
537 }
538 }
539
540 // onlyDet takes precedence on skipDet
541 DetFilterer filterers[2] = {
542 whitelister(configcontext.options().get<std::string>("onlyDet"), "none", ','),
543 blacklister(configcontext.options().get<std::string>("skipDet"), "none", ',')};
544
545 auto accept = [&configcontext, &filterers](o2::detectors::DetID id) {
546 for (auto& f : filterers) {
547 if (f.isSet()) {
548 return f.accept(id);
549 }
550 }
551 // accept all if neither onlyDet/skipDet are provided
552 return true;
553 };
554
555 // lambda to extract detectors which are enabled in the workflow
556 // will complain if user gave wrong input in construction of DetID
557 auto isEnabled = [&configcontext, &filterers, accept, grp, helpasked](o2::detectors::DetID id) {
558 auto isInGRPReadout = [grp](o2::detectors::DetID id) {
559 std::stringstream str;
560 str << "GRPDETKEY_" << id.getName();
561 if (gIsMaster and grp.get() != nullptr) {
562 auto ok = grp->isDetReadOut(id);
563 if (ok) {
564 publish_master_env(str.str().c_str(), "ON");
565 }
566 return ok;
567 } else {
568 // we should have published important GRP info as
569 // environment variables in order to not having to read GRP via ROOT
570 // in all the processes
571 return get_master_env(str.str().c_str()) != nullptr;
572 }
573 };
574
575 if (helpasked) {
576 return true;
577 }
578 if (configcontext.options().get<bool>("only-context")) {
579 // no detector necessary if we are asked to produce only the digitization context
580 return false;
581 }
582 auto accepted = accept(id);
583
584 // always comply with the filter choice?
585 auto forceAccepted = configcontext.options().get<bool>("forceSelectedDets");
586 bool is_ingrp = isInGRPReadout(id);
587 // final decision on whether or not this detector will be digitized
588 auto isRun = accepted && (forceAccepted || is_ingrp);
589 if (gIsMaster) {
590 LOG(info) << id.getName()
591 << " is in grp? " << (is_ingrp ? "yes" : "no") << ";"
592 << " is taken although not in grp? " << (!is_ingrp && (accepted && forceAccepted) ? "yes" : "no") << ";"
593 << " is skipped? " << (!accepted ? "yes" : "no") << ";"
594 << " is run? " << (isRun ? "yes" : "no");
595 }
596 return isRun;
597 };
598
599 std::vector<o2::detectors::DetID> detList; // list of participating detectors
600
601 // keeps track of which tpc sectors to process
602 std::vector<int> tpcsectors;
603
604 if (isEnabled(o2::detectors::DetID::TPC)) {
605 if (!helpasked && ismaster) {
606 initTPC(hbfu.startTime);
607 }
608
609 tpcsectors = o2::RangeTokenizer::tokenize<int>(configcontext.options().get<std::string>("tpc-sectors"));
610 // only one lane for the help printout
611 auto lanes = helpasked ? 1 : getNumTPCLanes(tpcsectors, configcontext);
612 detList.emplace_back(o2::detectors::DetID::TPC);
613
614 auto internalwrite = configcontext.options().get<bool>("tpc-chunked-writer");
615 auto distortionType = configcontext.options().get<int>("tpc-distortion-type");
616 WorkflowSpec tpcPipelines = o2::tpc::getTPCDigitizerSpec(lanes, tpcsectors, mctruth, internalwrite, distortionType);
617 specs.insert(specs.end(), tpcPipelines.begin(), tpcPipelines.end());
618
619 if (configcontext.options().get<std::string>("tpc-reco-type").empty() == false) {
620 throw std::runtime_error("option 'tpc-reco-type' is deprecated, please connect workflows on the command line by pipe");
621 }
622 if (!internalwrite) {
623 // for writing digits to disc
624 specs.emplace_back(o2::tpc::getTPCDigitRootWriterSpec(tpcsectors, mctruth));
625 }
626 }
627
628 // first 36 channels are reserved for the TPC
629 const int firstOtherChannel = 36;
630 int fanoutsize = firstOtherChannel;
631
632 // the ITS part
633 if (isEnabled(o2::detectors::DetID::ITS)) {
634 detList.emplace_back(o2::detectors::DetID::ITS);
635 // connect the ITS digitization
636 digitizerSpecs.emplace_back(o2::itsmft::getITSDigitizerSpec(fanoutsize++, mctruth));
637 // connect ITS digit writer
638 writerSpecs.emplace_back(o2::itsmft::getITSDigitWriterSpec(mctruth));
639 }
640
641#ifdef ENABLE_UPGRADES
642 // the ITS3 part
643 if (isEnabled(o2::detectors::DetID::IT3)) {
644 detList.emplace_back(o2::detectors::DetID::IT3);
645 // connect the ITS digitization
646 specs.emplace_back(o2::its3::getITS3DigitizerSpec(fanoutsize++, mctruth));
647 // // connect ITS digit writer
648 specs.emplace_back(o2::its3::getITS3DigitWriterSpec(mctruth));
649 }
650
651 // the ALICE 3 TRK part
652 if (isEnabled(o2::detectors::DetID::TRK)) {
653 detList.emplace_back(o2::detectors::DetID::TRK);
654 // connect the ALICE 3 TRK digitization
655 specs.emplace_back(o2::trk::getTRKDigitizerSpec(fanoutsize++, mctruth));
656 // connect the ALICE 3 TRK digit writer
657 specs.emplace_back(o2::trk::getTRKDigitWriterSpec(mctruth));
658 }
659#endif
660
661 // the MFT part
662 if (isEnabled(o2::detectors::DetID::MFT)) {
663 detList.emplace_back(o2::detectors::DetID::MFT);
664 // connect the MFT digitization
665 digitizerSpecs.emplace_back(o2::itsmft::getMFTDigitizerSpec(fanoutsize++, mctruth));
666 // connect MFT digit writer
667 writerSpecs.emplace_back(o2::itsmft::getMFTDigitWriterSpec(mctruth));
668 }
669
670 // the TOF part
671 if (isEnabled(o2::detectors::DetID::TOF)) {
672 auto useCCDB = configcontext.options().get<bool>("use-ccdb-tof");
673 useCCDB |= configcontext.options().get<bool>("ccdb-tof-sa");
674 auto ccdb_url_tof = o2::base::NameConf::getCCDBServer();
675 auto timestamp = o2::raw::HBFUtils::Instance().startTime / 1000;
676 detList.emplace_back(o2::detectors::DetID::TOF);
677 // connect the TOF digitization
678 // printf("TOF Setting: use-ccdb = %d ---- ccdb url=%s ---- timestamp=%ld\n", useCCDB, ccdb_url_tof.c_str(), timestamp);
679
680 digitizerSpecs.emplace_back(o2::tof::getTOFDigitizerSpec(fanoutsize++, useCCDB, mctruth, ccdb_url_tof.c_str(), timestamp));
681 // add TOF digit writer
682 writerSpecs.emplace_back(o2::tof::getTOFDigitWriterSpec(mctruth));
683 }
684
685 // the FT0 part
686 if (isEnabled(o2::detectors::DetID::FT0)) {
687 auto useCCDB = configcontext.options().get<bool>("use-ccdb-ft0");
688 auto timestamp = o2::raw::HBFUtils::Instance().startTime;
689 detList.emplace_back(o2::detectors::DetID::FT0);
690 // connect the FT0 digitization
691 specs.emplace_back(o2::ft0::getFT0DigitizerSpec(fanoutsize++, mctruth, useCCDB));
692 // connect the FIT digit writer
693 writerSpecs.emplace_back(o2::ft0::getFT0DigitWriterSpec(mctruth));
694 }
695
696 // the FV0 part
697 if (isEnabled(o2::detectors::DetID::FV0)) {
698 detList.emplace_back(o2::detectors::DetID::FV0);
699 // connect the FV0 digitization
700 digitizerSpecs.emplace_back(o2::fv0::getFV0DigitizerSpec(fanoutsize++, mctruth));
701 // connect the FV0 digit writer
702 writerSpecs.emplace_back(o2::fv0::getFV0DigitWriterSpec(mctruth));
703 }
704
705 // the EMCal part
706 if (isEnabled(o2::detectors::DetID::EMC)) {
707 auto useCCDB = !configcontext.options().get<bool>("no-use-ccdb-emc");
708 bool requireCTPInputs = !configcontext.options().get<bool>("no-require-ctpinputs-emc");
709 detList.emplace_back(o2::detectors::DetID::EMC);
710 // connect the EMCal digitization
711 digitizerSpecs.emplace_back(o2::emcal::getEMCALDigitizerSpec(fanoutsize++, requireCTPInputs, mctruth, useCCDB));
712 // connect the EMCal digit writer
713 writerSpecs.emplace_back(o2::emcal::getEMCALDigitWriterSpec(mctruth));
714 }
715
716 // add HMPID
717 if (isEnabled(o2::detectors::DetID::HMP)) {
718 detList.emplace_back(o2::detectors::DetID::HMP);
719 // connect the HMP digitization
720 digitizerSpecs.emplace_back(o2::hmpid::getHMPIDDigitizerSpec(fanoutsize++, mctruth));
721 // connect the HMP digit writer
722 writerSpecs.emplace_back(o2::hmpid::getHMPIDDigitWriterSpec(mctruth));
723 }
724
725 // add ZDC
726 if (isEnabled(o2::detectors::DetID::ZDC)) {
727 detList.emplace_back(o2::detectors::DetID::ZDC);
728 // connect the ZDC digitization
729 digitizerSpecs.emplace_back(o2::zdc::getZDCDigitizerSpec(fanoutsize++, mctruth));
730 // connect the ZDC digit writer
731 writerSpecs.emplace_back(o2::zdc::getZDCDigitWriterDPLSpec(mctruth, true));
732 }
733
734 // add TRD
735 if (isEnabled(o2::detectors::DetID::TRD)) {
736 detList.emplace_back(o2::detectors::DetID::TRD);
737 // connect the TRD digitization
738 specs.emplace_back(o2::trd::getTRDDigitizerSpec(fanoutsize++, mctruth));
739 auto disableTrapSim = configcontext.options().get<bool>("disable-trd-trapsim");
740 auto trdDigitDownscaling = configcontext.options().get<int>("trd-digit-downscaling");
741 if (!disableTrapSim) {
742 // connect the TRD TRAP simulator
743 specs.emplace_back(o2::trd::getTRDTrapSimulatorSpec(mctruth, trdDigitDownscaling));
744 // connect to the device to write out the tracklets.
745 specs.emplace_back(o2::trd::getTRDTrackletWriterSpec(mctruth));
746 // connect the TRD digit writer expecting input from TRAP simulation
747 specs.emplace_back(o2::trd::getTRDDigitWriterSpec(mctruth, false));
748 } else {
749 // connect the TRD digit writer expecting input from TRD digitizer
750 specs.emplace_back(o2::trd::getTRDDigitWriterSpec(mctruth, true));
751 }
752 }
753
754 // add MUON MCH
755 if (isEnabled(o2::detectors::DetID::MCH)) {
756 detList.emplace_back(o2::detectors::DetID::MCH);
757 // connect the MUON MCH digitization
758 digitizerSpecs.emplace_back(o2::mch::getMCHDigitizerSpec(fanoutsize++, mctruth));
759 // connect the MUON MCH digit writer
760 writerSpecs.emplace_back(o2::mch::getMCHDigitWriterSpec(mctruth));
761 }
762
763 // add MID
764 if (isEnabled(o2::detectors::DetID::MID)) {
765 detList.emplace_back(o2::detectors::DetID::MID);
766 // connect the MID digitization
767 digitizerSpecs.emplace_back(o2::mid::getMIDDigitizerSpec(fanoutsize++, mctruth));
768 // connect the MID digit writer
769 writerSpecs.emplace_back(o2::mid::getMIDDigitWriterSpec(mctruth));
770 }
771
772 // add FDD
773 if (isEnabled(o2::detectors::DetID::FDD)) {
774 detList.emplace_back(o2::detectors::DetID::FDD);
775 // connect the FDD digitization
776 digitizerSpecs.emplace_back(o2::fdd::getFDDDigitizerSpec(fanoutsize++, mctruth));
777 // connect the FDD digit writer
778 writerSpecs.emplace_back(o2::fdd::getFDDDigitWriterSpec(mctruth));
779 }
780
781 // the PHOS part
782 if (isEnabled(o2::detectors::DetID::PHS)) {
783 detList.emplace_back(o2::detectors::DetID::PHS);
784 // connect the PHOS digitization
785 digitizerSpecs.emplace_back(o2::phos::getPHOSDigitizerSpec(fanoutsize++, mctruth));
786 // add PHOS writer
787 writerSpecs.emplace_back(o2::phos::getPHOSDigitWriterSpec(mctruth));
788 }
789
790 // the CPV part
791 if (isEnabled(o2::detectors::DetID::CPV)) {
792 detList.emplace_back(o2::detectors::DetID::CPV);
793 // connect the CPV digitization
794 digitizerSpecs.emplace_back(o2::cpv::getCPVDigitizerSpec(fanoutsize++, mctruth));
795 // add PHOS writer
796 writerSpecs.emplace_back(o2::cpv::getCPVDigitWriterSpec(mctruth));
797 }
798 // the CTP part
799 if (isEnabled(o2::detectors::DetID::CTP)) {
800 detList.emplace_back(o2::detectors::DetID::CTP);
801 // connect the CTP digitization
802 specs.emplace_back(o2::ctp::getCTPDigitizerSpec(fanoutsize++, detList));
803 // connect the CTP digit writer
804 specs.emplace_back(o2::ctp::getDigitWriterSpec(false));
805 }
806 // GRP updater: must come after all detectors since requires their list
807 if (!configcontext.options().get<bool>("only-context")) {
808 writerSpecs.emplace_back(o2::parameters::getGRPUpdaterSpec(simPrefixes[0], detList));
809 }
810
811 bool combine = configcontext.options().get<bool>("combine-devices");
812 if (!combine) {
813 for (auto& s : digitizerSpecs) {
814 specs.push_back(s);
815 }
816 for (auto& s : writerSpecs) {
817 specs.push_back(s);
818 }
819 } else {
820 std::vector<DataProcessorSpec> remaining;
821 specs.push_back(specCombiner("Digitizations", digitizerSpecs, remaining));
822 specs.push_back(specCombiner("Writers", writerSpecs, remaining));
823 for (auto& s : remaining) {
824 specs.push_back(s);
825 }
826 }
827
828 // For reasons of offering homegenous behaviour (consistent options to outside scripts),
829 // we require that at least one of the devices above listens to the DPL CCDB fetcher.
830 // Verify this or insert a dummy channel in one of the devices. (This cannot be done in the SimReader
831 // as the SimReader is the source device injecting the timing information).
832 // In future this code can serve as a check that all digitizers access CCDB via the DPL fetcher.
833 bool haveCCDBInputSpec = false;
834 for (auto spec : specs) {
835 for (auto in : spec.inputs) {
836 if (in.lifetime == Lifetime::Condition) {
837 haveCCDBInputSpec = true;
838 break;
839 }
840 }
841 }
842 if (!haveCCDBInputSpec && specs.size() > 0) {
843 LOG(info) << "No one uses DPL CCDB .. injecting a dummy CCDB query into " << specs.back().name;
844 specs.back().inputs.emplace_back("_dummyOrbitReset", "CTP", "ORBITRESET", 0, Lifetime::Condition,
845 ccdbParamSpec("CTP/Calib/OrbitReset"));
846 }
847
848 // The SIM Reader. NEEDS TO BE LAST
849 bool withTrigger = configcontext.options().get<bool>("with-trigger");
850 LOG(info) << " TRIGGER " << withTrigger;
851 specs[0] = o2::steer::getSimReaderSpec({firstOtherChannel, fanoutsize}, simPrefixes, tpcsectors, withTrigger);
852 return specs;
853}
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, 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)
DataProcessorSpec getTPCDigitRootWriterSpec(std::vector< int > const &laneConfiguration, bool mctruth)
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 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