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