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);
654 // connect the ITS digitization
655 specs.emplace_back(o2::its3::getITS3DigitizerSpec(fanoutsize++, mctruth, doStag));
656 // // connect ITS digit writer
657 specs.emplace_back(o2::its3::getITS3DigitWriterSpec(mctruth, doStag));
658 }
659
660 // the ALICE 3 TRK part
661 if (isEnabled(o2::detectors::DetID::TRK)) {
662 detList.emplace_back(o2::detectors::DetID::TRK);
663 // connect the ALICE 3 TRK digitization
664 specs.emplace_back(o2::trk::getTRKDigitizerSpec(fanoutsize++, mctruth));
665 // connect the ALICE 3 TRK digit writer
666 specs.emplace_back(o2::trk::getTRKDigitWriterSpec(mctruth));
667 }
668#endif
669
670 // the MFT part
671 if (isEnabled(o2::detectors::DetID::MFT)) {
672 detList.emplace_back(o2::detectors::DetID::MFT);
674 // connect the MFT digitization
675 digitizerSpecs.emplace_back(o2::itsmft::getMFTDigitizerSpec(fanoutsize++, mctruth, doStag));
676 // connect MFT digit writer
677 writerSpecs.emplace_back(o2::itsmft::getMFTDigitWriterSpec(mctruth, doStag));
678 }
679
680 // the TOF part
681 if (isEnabled(o2::detectors::DetID::TOF)) {
682 auto useCCDB = configcontext.options().get<bool>("use-ccdb-tof");
683 useCCDB |= configcontext.options().get<bool>("ccdb-tof-sa");
684 auto ccdb_url_tof = o2::base::NameConf::getCCDBServer();
685 auto timestamp = o2::raw::HBFUtils::Instance().startTime / 1000;
686 detList.emplace_back(o2::detectors::DetID::TOF);
687 auto maskDRM = (uint32_t)configcontext.options().get<int>("tof-drm-bitmask");
688 // connect the TOF digitization
689 // printf("TOF Setting: use-ccdb = %d ---- ccdb url=%s ---- timestamp=%ld\n", useCCDB, ccdb_url_tof.c_str(), timestamp);
690
691 digitizerSpecs.emplace_back(o2::tof::getTOFDigitizerSpec(fanoutsize++, useCCDB, mctruth, ccdb_url_tof.c_str(), timestamp, maskDRM));
692 // add TOF digit writer
693 writerSpecs.emplace_back(o2::tof::getTOFDigitWriterSpec(mctruth));
694 }
695
696 // the FT0 part
697 if (isEnabled(o2::detectors::DetID::FT0)) {
698 auto useCCDB = configcontext.options().get<bool>("use-ccdb-ft0");
699 auto timestamp = o2::raw::HBFUtils::Instance().startTime;
700 detList.emplace_back(o2::detectors::DetID::FT0);
701 // connect the FT0 digitization
702 specs.emplace_back(o2::ft0::getFT0DigitizerSpec(fanoutsize++, mctruth, useCCDB));
703 // connect the FIT digit writer
704 writerSpecs.emplace_back(o2::ft0::getFT0DigitWriterSpec(mctruth));
705 }
706
707 // the FV0 part
708 if (isEnabled(o2::detectors::DetID::FV0)) {
709 detList.emplace_back(o2::detectors::DetID::FV0);
710 // connect the FV0 digitization
711 digitizerSpecs.emplace_back(o2::fv0::getFV0DigitizerSpec(fanoutsize++, mctruth));
712 // connect the FV0 digit writer
713 writerSpecs.emplace_back(o2::fv0::getFV0DigitWriterSpec(mctruth));
714 }
715
716 // the EMCal part
717 if (isEnabled(o2::detectors::DetID::EMC)) {
718 auto useCCDB = !configcontext.options().get<bool>("no-use-ccdb-emc");
719 bool requireCTPInputs = !configcontext.options().get<bool>("no-require-ctpinputs-emc");
720 detList.emplace_back(o2::detectors::DetID::EMC);
721 // connect the EMCal digitization
722 digitizerSpecs.emplace_back(o2::emcal::getEMCALDigitizerSpec(fanoutsize++, requireCTPInputs, mctruth, useCCDB));
723 // connect the EMCal digit writer
724 writerSpecs.emplace_back(o2::emcal::getEMCALDigitWriterSpec(mctruth));
725 }
726
727 // add HMPID
728 if (isEnabled(o2::detectors::DetID::HMP)) {
729 detList.emplace_back(o2::detectors::DetID::HMP);
730 // connect the HMP digitization
731 digitizerSpecs.emplace_back(o2::hmpid::getHMPIDDigitizerSpec(fanoutsize++, mctruth));
732 // connect the HMP digit writer
733 writerSpecs.emplace_back(o2::hmpid::getHMPIDDigitWriterSpec(mctruth));
734 }
735
736 // add ZDC
737 if (isEnabled(o2::detectors::DetID::ZDC)) {
738 detList.emplace_back(o2::detectors::DetID::ZDC);
739 // connect the ZDC digitization
740 digitizerSpecs.emplace_back(o2::zdc::getZDCDigitizerSpec(fanoutsize++, mctruth));
741 // connect the ZDC digit writer
742 writerSpecs.emplace_back(o2::zdc::getZDCDigitWriterDPLSpec(mctruth, true));
743 }
744
745 // add TRD
746 if (isEnabled(o2::detectors::DetID::TRD)) {
747 detList.emplace_back(o2::detectors::DetID::TRD);
748 // connect the TRD digitization
749 specs.emplace_back(o2::trd::getTRDDigitizerSpec(fanoutsize++, mctruth));
750 auto disableTrapSim = configcontext.options().get<bool>("disable-trd-trapsim");
751 auto trdDigitDownscaling = configcontext.options().get<int>("trd-digit-downscaling");
752 if (!disableTrapSim) {
753 // connect the TRD TRAP simulator
754 specs.emplace_back(o2::trd::getTRDTrapSimulatorSpec(mctruth, trdDigitDownscaling));
755 // connect to the device to write out the tracklets.
756 specs.emplace_back(o2::trd::getTRDTrackletWriterSpec(mctruth));
757 // connect the TRD digit writer expecting input from TRAP simulation
758 specs.emplace_back(o2::trd::getTRDDigitWriterSpec(mctruth, false));
759 } else {
760 // connect the TRD digit writer expecting input from TRD digitizer
761 specs.emplace_back(o2::trd::getTRDDigitWriterSpec(mctruth, true));
762 }
763 }
764
765 // add MUON MCH
766 if (isEnabled(o2::detectors::DetID::MCH)) {
767 detList.emplace_back(o2::detectors::DetID::MCH);
768 // connect the MUON MCH digitization
769 digitizerSpecs.emplace_back(o2::mch::getMCHDigitizerSpec(fanoutsize++, mctruth));
770 // connect the MUON MCH digit writer
771 writerSpecs.emplace_back(o2::mch::getMCHDigitWriterSpec(mctruth));
772 }
773
774 // add MID
775 if (isEnabled(o2::detectors::DetID::MID)) {
776 detList.emplace_back(o2::detectors::DetID::MID);
777 // connect the MID digitization
778 digitizerSpecs.emplace_back(o2::mid::getMIDDigitizerSpec(fanoutsize++, mctruth));
779 // connect the MID digit writer
780 writerSpecs.emplace_back(o2::mid::getMIDDigitWriterSpec(mctruth));
781 }
782
783 // add FDD
784 if (isEnabled(o2::detectors::DetID::FDD)) {
785 detList.emplace_back(o2::detectors::DetID::FDD);
786 // connect the FDD digitization
787 digitizerSpecs.emplace_back(o2::fdd::getFDDDigitizerSpec(fanoutsize++, mctruth));
788 // connect the FDD digit writer
789 writerSpecs.emplace_back(o2::fdd::getFDDDigitWriterSpec(mctruth));
790 }
791
792 // the PHOS part
793 if (isEnabled(o2::detectors::DetID::PHS)) {
794 detList.emplace_back(o2::detectors::DetID::PHS);
795 // connect the PHOS digitization
796 digitizerSpecs.emplace_back(o2::phos::getPHOSDigitizerSpec(fanoutsize++, mctruth));
797 // add PHOS writer
798 writerSpecs.emplace_back(o2::phos::getPHOSDigitWriterSpec(mctruth));
799 }
800
801 // the CPV part
802 if (isEnabled(o2::detectors::DetID::CPV)) {
803 detList.emplace_back(o2::detectors::DetID::CPV);
804 // connect the CPV digitization
805 digitizerSpecs.emplace_back(o2::cpv::getCPVDigitizerSpec(fanoutsize++, mctruth));
806 // add PHOS writer
807 writerSpecs.emplace_back(o2::cpv::getCPVDigitWriterSpec(mctruth));
808 }
809 // the CTP part
810 if (isEnabled(o2::detectors::DetID::CTP)) {
811 detList.emplace_back(o2::detectors::DetID::CTP);
812 float lumiScaler = configcontext.options().get<float>("store-ctp-lumi");
813 // connect the CTP digitization
814 specs.emplace_back(o2::ctp::getCTPDigitizerSpec(fanoutsize++, detList, lumiScaler));
815 // connect the CTP digit writer
816 specs.emplace_back(o2::ctp::getDigitWriterSpec(lumiScaler >= 0));
817 }
818 // GRP updater: must come after all detectors since requires their list
819 if (!configcontext.options().get<bool>("only-context")) {
820 writerSpecs.emplace_back(o2::parameters::getGRPUpdaterSpec(simPrefixes[0], detList));
821 }
822
823 bool combine = configcontext.options().get<bool>("combine-devices");
824 if (!combine) {
825 for (auto& s : digitizerSpecs) {
826 specs.push_back(s);
827 }
828 for (auto& s : writerSpecs) {
829 specs.push_back(s);
830 }
831 } else {
832 std::vector<DataProcessorSpec> remaining;
833 specs.push_back(specCombiner("Digitizations", digitizerSpecs, remaining));
834 specs.push_back(specCombiner("Writers", writerSpecs, remaining));
835 for (auto& s : remaining) {
836 specs.push_back(s);
837 }
838 }
839
840 // For reasons of offering homegenous behaviour (consistent options to outside scripts),
841 // we require that at least one of the devices above listens to the DPL CCDB fetcher.
842 // Verify this or insert a dummy channel in one of the devices. (This cannot be done in the SimReader
843 // as the SimReader is the source device injecting the timing information).
844 // In future this code can serve as a check that all digitizers access CCDB via the DPL fetcher.
845 bool haveCCDBInputSpec = false;
846 for (auto spec : specs) {
847 for (auto in : spec.inputs) {
848 if (in.lifetime == Lifetime::Condition) {
849 haveCCDBInputSpec = true;
850 break;
851 }
852 }
853 }
854 if (!haveCCDBInputSpec && specs.size() > 0) {
855 LOG(info) << "No one uses DPL CCDB .. injecting a dummy CCDB query into " << specs.back().name;
856 specs.back().inputs.emplace_back("_dummyOrbitReset", "CTP", "ORBITRESET", 0, Lifetime::Condition,
857 ccdbParamSpec("CTP/Calib/OrbitReset"));
858 }
859
860 // The SIM Reader. NEEDS TO BE LAST
861 bool withTrigger = configcontext.options().get<bool>("with-trigger");
862 LOG(info) << " TRIGGER " << withTrigger;
863 specs[0] = o2::steer::getSimReaderSpec({firstOtherChannel, fanoutsize}, simPrefixes, tpcsectors, withTrigger);
864 return specs;
865}
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:115
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)
DataProcessorSpec getITS3DigitizerSpec(int channel, bool mctruth, bool doStag)
o2::framework::DataProcessorSpec getITS3DigitWriterSpec(bool mctruth=true, bool doStag=false, bool dec=false, bool calib=false)
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 isITSStaggeringEnabled(o2::framework::ConfigContext const &cfgc)
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