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