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