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