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