Project
Loading...
Searching...
No Matches
RecoWorkflow.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
16
19#include "Framework/Logger.h"
29#include "TPCWorkflow/ZSSpec.h"
48#include <string>
49#include <stdexcept>
50#include <fstream>
51#include <sstream>
52#include <iomanip>
53#include <unordered_map>
54#include <stdexcept>
55#include <algorithm> // std::find
56#include <tuple> // make_tuple
57#include <array>
58#include <gsl/span>
59
60using namespace o2::dataformats;
61
62namespace o2
63{
64namespace tpc
65{
66namespace reco_workflow
67{
68
69static std::shared_ptr<o2::gpu::GPURecoWorkflowSpec> gTask;
70
71using namespace framework;
72
73template <typename T>
75
76const std::unordered_map<std::string, InputType> InputMap{
77 {"pass-through", InputType::PassThrough},
78 {"digitizer", InputType::Digitizer},
79 {"digits", InputType::Digits},
80 {"clustershardware", InputType::ClustersHardware},
81 {"clusters", InputType::Clusters},
82 {"zsraw", InputType::ZSRaw},
83 {"compressed-clusters", InputType::CompClusters},
84 {"compressed-clusters-ctf", InputType::CompClustersCTF},
85 {"compressed-clusters-flat", InputType::CompClustersFlat}};
86
87const std::unordered_map<std::string, OutputType> OutputMap{
88 {"digits", OutputType::Digits},
89 {"clustershardware", OutputType::ClustersHardware},
90 {"clusters", OutputType::Clusters},
91 {"tracks", OutputType::Tracks},
92 {"compressed-clusters", OutputType::CompClusters},
93 {"encoded-clusters", OutputType::EncodedClusters},
94 {"disable-writer", OutputType::DisableWriter},
95 {"send-clusters-per-sector", OutputType::SendClustersPerSector},
96 {"zsraw", OutputType::ZSRaw},
97 {"qa", OutputType::QA},
98 {"no-shared-cluster-map", OutputType::NoSharedClusterMap},
99 {"tpc-triggers", OutputType::TPCTriggers}};
100
101framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vector<int> const& tpcSectors, unsigned long tpcSectorMask, std::vector<int> const& laneConfiguration,
102 const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, bool propagateMC, unsigned nLanes, std::string const& cfgInput, std::string const& cfgOutput, bool disableRootInput,
103 int caClusterer, int zsOnTheFly, bool askDISTSTF, bool selIR, bool filteredInp, int deadMapSources, bool useMCTimeGain)
104{
105 InputType inputType;
106 try {
107 inputType = InputMap.at(cfgInput);
108 } catch (std::out_of_range&) {
109 throw std::invalid_argument(std::string("invalid input type: ") + cfgInput);
110 }
111 std::vector<OutputType> outputTypes;
112 try {
113 outputTypes = RangeTokenizer::tokenize<OutputType>(cfgOutput, [](std::string const& token) { return OutputMap.at(token); });
114 } catch (std::out_of_range&) {
115 throw std::invalid_argument(std::string("invalid output type: ") + cfgOutput);
116 }
117 auto isEnabled = [&outputTypes](OutputType type) {
118 return std::find(outputTypes.begin(), outputTypes.end(), type) != outputTypes.end();
119 };
120
121 if (filteredInp && !(inputType == InputType::PassThrough && isEnabled(OutputType::Tracks) && isEnabled(OutputType::Clusters) && isEnabled(OutputType::SendClustersPerSector))) {
122 throw std::invalid_argument("filtered-input option must be provided only with pass-through input and clusters,tracks,send-clusters-per-sector output");
123 }
124
125 bool decompressTPC = inputType == InputType::CompClustersCTF || inputType == InputType::CompClusters;
126 // Disable not applicable settings depending on TPC input, no need to disable manually
127 if (decompressTPC && (isEnabled(OutputType::Clusters) || isEnabled(OutputType::Tracks))) {
128 caClusterer = false;
129 zsOnTheFly = false;
130 propagateMC = false;
131 }
132 if (inputType == InputType::ZSRaw || inputType == InputType::CompClustersFlat) {
133 caClusterer = true;
134 zsOnTheFly = false;
135 propagateMC = false;
136 }
137 if (inputType == InputType::PassThrough || inputType == InputType::ClustersHardware || inputType == InputType::Clusters) {
138 caClusterer = false;
139 }
140 if (!caClusterer) {
141 zsOnTheFly = false;
142 }
143
144 if (inputType == InputType::ClustersHardware && isEnabled(OutputType::Digits)) {
145 throw std::invalid_argument("input/output type mismatch, can not produce 'digits' from 'clustershardware'");
146 }
147 if (inputType == InputType::Clusters && (isEnabled(OutputType::Digits) || isEnabled(OutputType::ClustersHardware))) {
148 throw std::invalid_argument("input/output type mismatch, can not produce 'digits', nor 'clustershardware' from 'clusters'");
149 }
150 if (inputType == InputType::ZSRaw && isEnabled(OutputType::ClustersHardware)) {
151 throw std::invalid_argument("input/output type mismatch, can not produce 'clustershardware' from 'zsraw'");
152 }
153 if (caClusterer && (inputType == InputType::Clusters || inputType == InputType::ClustersHardware)) {
154 throw std::invalid_argument("ca-clusterer requires digits as input");
155 }
156 if (caClusterer && (isEnabled(OutputType::ClustersHardware))) {
157 throw std::invalid_argument("ca-clusterer cannot produce clustershardware output");
158 }
159
160 WorkflowSpec specs;
161
162 // We provide a special publishing method for labels which have been stored in a split format and need
163 // to be transformed into a contiguous shareable container before publishing. For other branches/types this returns
164 // false and the generic RootTreeWriter publishing proceeds
165 static Reader::SpecialPublishHook hook{[](std::string_view name, ProcessingContext& context, o2::framework::Output const& output, char* data) -> bool {
166 if (TString(name.data()).Contains("TPCDigitMCTruth") || TString(name.data()).Contains("TPCClusterHwMCTruth") || TString(name.data()).Contains("TPCClusterNativeMCTruth")) {
167 auto storedlabels = reinterpret_cast<o2::dataformats::IOMCTruthContainerView const*>(data);
169 storedlabels->copyandflatten(flatlabels);
170 // LOG(info) << "PUBLISHING CONST LABELS " << flatlabels.getNElements();
171 context.outputs().snapshot(output, flatlabels);
172 return true;
173 }
174 return false;
175 }};
176 if (!disableRootInput || inputType == InputType::PassThrough) {
177 // The OutputSpec of the PublisherSpec is configured depending on the input
178 // type. Note that the configuration of the dispatch trigger in the main file
179 // needs to be done in accordance. This means, if a new input option is added
180 // also the dispatch trigger needs to be updated.
181 if (inputType == InputType::Digits) {
182 using Type = std::vector<o2::tpc::Digit>;
183
184 specs.emplace_back(o2::tpc::getPublisherSpec<Type>(PublisherConf{
185 "tpc-digit-reader",
186 "tpcdigits.root",
187 "o2sim",
188 {"digitbranch", "TPCDigit", "Digit branch"},
189 {"mcbranch", "TPCDigitMCTruth", "MC label branch"},
190 OutputSpec{"TPC", "DIGITS"},
191 OutputSpec{"TPC", "DIGITSMCTR"},
192 tpcSectors,
193 laneConfiguration,
194 &hook},
195 propagateMC));
196 if (sclOpts.needTPCScalersWorkflow()) { // for standalone tpc-reco workflow
197 specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpts.lumiType == 2, sclOpts.enableMShapeCorrection));
198 }
199 if (sclOpts.requestCTPLumi) { // need CTP digits (lumi) reader
200 specs.emplace_back(o2::ctp::getDigitsReaderSpec(false));
201 }
202 } else if (inputType == InputType::ClustersHardware) {
203 specs.emplace_back(o2::tpc::getPublisherSpec(PublisherConf{
204 "tpc-clusterhardware-reader",
205 "tpc-clusterhardware.root",
206 "tpcclustershardware",
207 {"databranch", "TPCClusterHw", "Branch with TPC ClustersHardware"},
208 {"mcbranch", "TPCClusterHwMCTruth", "MC label branch"},
209 OutputSpec{"TPC", "CLUSTERHW"},
210 OutputSpec{"TPC", "CLUSTERHWMCLBL"},
211 tpcSectors,
212 laneConfiguration,
213 &hook},
214 propagateMC));
215 } else if (inputType == InputType::Clusters) {
216 specs.emplace_back(o2::tpc::getClusterReaderSpec(propagateMC, &tpcSectors, &laneConfiguration));
217 if (!getenv("DPL_DISABLE_TPC_TRIGGER_READER") || atoi(getenv("DPL_DISABLE_TPC_TRIGGER_READER")) != 1) {
218 specs.emplace_back(o2::tpc::getTPCTriggerReaderSpec());
219 }
220 if (sclOpts.needTPCScalersWorkflow()) { // for standalone tpc-reco workflow
221 specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpts.lumiType == 2, sclOpts.enableMShapeCorrection));
222 }
223 if (sclOpts.requestCTPLumi) { // need CTP digits (lumi) reader
224 specs.emplace_back(o2::ctp::getDigitsReaderSpec(false));
225 }
226 } else if (inputType == InputType::CompClusters) {
227 // TODO: need to check if we want to store the MC labels alongside with compressed clusters
228 // for the moment reading of labels is disabled (last parameter is false)
229 // TODO: make a different publisher spec for only one output spec, for now using the
230 // PublisherSpec with only sector 0, '_0' is thus appended to the branch name
231 specs.emplace_back(o2::tpc::getPublisherSpec(PublisherConf{
232 "tpc-compressed-cluster-reader",
233 "tpc-compclusters.root",
234 "tpcrec",
235 {"clusterbranch", "TPCCompClusters", "Branch with TPC compressed clusters"},
236 {"", "", ""}, // No MC labels
237 OutputSpec{"TPC", "COMPCLUSTERS"},
238 OutputSpec{"", ""}, // No MC labels
239 std::vector<int>(1, 0),
240 std::vector<int>(1, 0),
241 &hook},
242 false));
243 }
244 }
245
246 // output matrix
247 // Note: the ClusterHardware format is probably a deprecated legacy format and also the
248 // ClusterDecoderRawSpec
249 bool produceCompClusters = isEnabled(OutputType::CompClusters);
250 bool produceTracks = isEnabled(OutputType::Tracks);
251 bool runGPUReco = (produceTracks || produceCompClusters || (isEnabled(OutputType::Clusters) && caClusterer) || inputType == InputType::CompClustersCTF) && inputType != InputType::CompClustersFlat;
252 bool runHWDecoder = !caClusterer && (runGPUReco || isEnabled(OutputType::Clusters));
253 bool runClusterer = !caClusterer && (runHWDecoder || isEnabled(OutputType::ClustersHardware));
254 bool zsDecoder = inputType == InputType::ZSRaw;
255 bool runClusterEncoder = isEnabled(OutputType::EncodedClusters);
256
257 // input matrix
258 runClusterer &= inputType == InputType::Digitizer || inputType == InputType::Digits;
259 runHWDecoder &= runClusterer || inputType == InputType::ClustersHardware;
260 runGPUReco &= caClusterer || runHWDecoder || inputType == InputType::Clusters || decompressTPC;
261
262 bool outRaw = inputType == InputType::Digits && isEnabled(OutputType::ZSRaw) && !isEnabled(OutputType::DisableWriter);
263 // bool runZSDecode = inputType == InputType::ZSRaw;
264 bool zsToDigit = inputType == InputType::ZSRaw && isEnabled(OutputType::Digits);
265
266 if (inputType == InputType::PassThrough) {
267 runGPUReco = runHWDecoder = runClusterer = runClusterEncoder = zsToDigit = false;
268 }
269
270 WorkflowSpec parallelProcessors;
272 //
273 // clusterer process(es)
274 //
275 //
276 if (runClusterer) {
277 parallelProcessors.push_back(o2::tpc::getClustererSpec(propagateMC));
278 }
279
281 //
282 // cluster decoder process(es)
283 //
284 //
285 if (runHWDecoder) {
286 parallelProcessors.push_back(o2::tpc::getClusterDecoderRawSpec(propagateMC));
287 }
288
290 //
291 // set up parallel TPC lanes
292 //
293 // the parallelPipeline helper distributes the subspec ids from the lane configuration
294 // among the pipelines. All inputs and outputs of processors of one pipeline will be
295 // cloned by the number of subspecs served by this pipeline and amended with the subspecs
296 parallelProcessors = parallelPipeline(
297 parallelProcessors, nLanes,
298 [&laneConfiguration]() { return laneConfiguration.size(); },
299 [&laneConfiguration](size_t index) { return laneConfiguration[index]; });
300 specs.insert(specs.end(), parallelProcessors.begin(), parallelProcessors.end());
301
303 //
304 // generation of processor specs for various types of outputs
305 // based on generic RootTreeWriter and MakeRootTreeWriterSpec generator
306 //
307 // -------------------------------------------------------------------------------------------
308 // the callbacks for the RootTreeWriter
309 //
310 // The generic writer needs a way to associate incoming data with the individual branches for
311 // the TPC sectors. The sector number is transmitted as part of the sector header, the callback
312 // finds the corresponding index in the vector of configured sectors
313 auto getIndex = [tpcSectors](o2::framework::DataRef const& ref) {
314 auto const* tpcSectorHeader = o2::framework::DataRefUtils::getHeader<o2::tpc::TPCSectorHeader*>(ref);
315 if (!tpcSectorHeader) {
316 throw std::runtime_error("TPC sector header missing in header stack");
317 }
318 if (tpcSectorHeader->sector() < 0) {
319 // special data sets, don't write
320 return ~(size_t)0;
321 }
322 size_t index = 0;
323 for (auto const& sector : tpcSectors) {
324 if (sector == tpcSectorHeader->sector()) {
325 return index;
326 }
327 ++index;
328 }
329 throw std::runtime_error("sector " + std::to_string(tpcSectorHeader->sector()) + " not configured for writing");
330 };
331 auto getName = [tpcSectors](std::string base, size_t index) {
332 return base + "_" + std::to_string(tpcSectors.at(index));
333 };
334
335 // -------------------------------------------------------------------------------------------
336 // helper to create writer specs for different types of output
337 auto fillLabels = [](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& /*ref*/) {
340 auto ptr = &outputcontainer;
342 outputcontainer.adopt(labelbuffer);
343 br->Fill();
344 br->ResetAddress();
345 };
346
347 auto makeWriterSpec = [tpcSectors, laneConfiguration, propagateMC, getIndex, getName](const char* processName,
348 const char* defaultFileName,
349 const char* defaultTreeName,
350 auto&& databranch,
351 auto&& mcbranch,
352 bool singleBranch = false) {
353 if (tpcSectors.size() == 0) {
354 throw std::invalid_argument(std::string("writer process configuration needs list of TPC sectors"));
355 }
356
357 auto amendInput = [tpcSectors, laneConfiguration](InputSpec& input, size_t index) {
358 input.binding += std::to_string(laneConfiguration[index]);
359 DataSpecUtils::updateMatchingSubspec(input, laneConfiguration[index]);
360 };
361 auto amendBranchDef = [laneConfiguration, amendInput, tpcSectors, getIndex, getName, singleBranch](auto&& def, bool enableMC = true) {
362 if (!singleBranch) {
363 def.keys = mergeInputs(def.keys, laneConfiguration.size(), amendInput);
364 // the branch is disabled if set to 0
365 def.nofBranches = enableMC ? tpcSectors.size() : 0;
366 def.getIndex = getIndex;
367 def.getName = getName;
368 } else {
369 // instead of the separate sector branches only one is going to be written
370 def.nofBranches = enableMC ? 1 : 0;
371 }
372 return std::move(def);
373 };
374
375 return std::move(MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
376 std::move(amendBranchDef(databranch)),
377 std::move(amendBranchDef(mcbranch, propagateMC)))());
378 };
379
381 //
382 // a writer process for digits
383 //
384 // selected by output type 'difits'
385 if (isEnabled(OutputType::Digits) && !isEnabled(OutputType::DisableWriter)) {
386 using DigitOutputType = std::vector<o2::tpc::Digit>;
387 specs.push_back(makeWriterSpec("tpc-digits-writer",
388 inputType == InputType::ZSRaw ? "tpc-zs-digits.root" : inputType == InputType::Digits ? "tpc-filtered-digits.root"
389 : "tpcdigits.root",
390 "o2sim",
391 BranchDefinition<DigitOutputType>{InputSpec{"data", "TPC", "DIGITS", 0},
392 "TPCDigit",
393 "digit-branch-name"},
394 BranchDefinition<MCLabelContainer>{InputSpec{"mc", "TPC", "DIGITSMCTR", 0},
395 "TPCDigitMCTruth",
396 "digitmc-branch-name"}));
397 }
398
400 //
401 // a writer process for hardware clusters
402 //
403 // selected by output type 'clustershardware'
404 if (isEnabled(OutputType::ClustersHardware) && !isEnabled(OutputType::DisableWriter)) {
405 specs.push_back(makeWriterSpec("tpc-clusterhardware-writer",
406 inputType == InputType::ClustersHardware ? "tpc-filtered-clustershardware.root" : "tpc-clustershardware.root",
407 "tpcclustershardware",
408 BranchDefinition<const char*>{InputSpec{"data", "TPC", "CLUSTERHW", 0},
409 "TPCClusterHw",
410 "databranch"},
411 BranchDefinition<MCLabelContainer>{InputSpec{"mc", "TPC", "CLUSTERHWMCLBL", 0},
412 "TPCClusterHwMCTruth",
413 "mcbranch"}));
414 }
415
417 //
418 // a writer process for TPC native clusters
419 //
420 // selected by output type 'clusters'
421 if (isEnabled(OutputType::Clusters) && !isEnabled(OutputType::DisableWriter)) {
422 // if the caClusterer is enabled, only one data set with the full TPC is produced, and the writer
423 // is configured to write one single branch
424 specs.push_back(makeWriterSpec(filteredInp ? "tpc-native-cluster-writer_filtered" : "tpc-native-cluster-writer",
425 (inputType == InputType::Clusters || filteredInp) ? "tpc-filtered-native-clusters.root" : "tpc-native-clusters.root",
426 "tpcrec",
427 BranchDefinition<const char*>{InputSpec{"data", ConcreteDataTypeMatcher{"TPC", filteredInp ? o2::header::DataDescription("CLUSTERNATIVEF") : o2::header::DataDescription("CLUSTERNATIVE")}},
428 "TPCClusterNative",
429 "databranch"},
431 "TPCClusterNativeMCTruth",
432 "mcbranch", fillLabels},
433 (caClusterer || decompressTPC || inputType == InputType::PassThrough) && !isEnabled(OutputType::SendClustersPerSector)));
434 }
435
436 if ((isEnabled(OutputType::TPCTriggers) || caClusterer) && !isEnabled(OutputType::DisableWriter)) {
437 specs.push_back(o2::tpc::getTPCTriggerWriterSpec());
438 }
439
440 if (zsOnTheFly) {
441 specs.emplace_back(o2::tpc::getZSEncoderSpec(tpcSectors, outRaw, tpcSectorMask));
442 }
443
444 if (zsToDigit) {
445 specs.emplace_back(o2::tpc::getZStoDigitsSpec(tpcSectors));
446 }
447
449 //
450 // tracker process
451 //
452 // selected by output type 'tracks'
453 if (runGPUReco) {
455 cfg.runTPCTracking = true;
456 cfg.lumiScaleType = sclOpts.lumiType;
457 cfg.lumiScaleMode = sclOpts.lumiMode;
459 cfg.enableCTPLumi = sclOpts.requestCTPLumi;
460 cfg.decompressTPC = decompressTPC;
461 cfg.decompressTPCFromROOT = decompressTPC && inputType == InputType::CompClusters;
462 cfg.caClusterer = caClusterer;
463 cfg.zsDecoder = zsDecoder;
464 cfg.zsOnTheFly = zsOnTheFly;
465 cfg.outputTracks = produceTracks;
466 cfg.outputCompClusters = produceCompClusters;
467 cfg.outputCompClustersFlat = runClusterEncoder;
468 cfg.outputCAClusters = isEnabled(OutputType::Clusters) && (caClusterer || decompressTPC);
469 cfg.outputQA = isEnabled(OutputType::QA);
470 cfg.outputSharedClusterMap = (isEnabled(OutputType::Clusters) || inputType == InputType::Clusters) && isEnabled(OutputType::Tracks) && !isEnabled(OutputType::NoSharedClusterMap);
471 cfg.processMC = propagateMC;
473 cfg.askDISTSTF = askDISTSTF;
475 cfg.tpcDeadMapSources = deadMapSources;
476 cfg.tpcUseMCTimeGain = useMCTimeGain;
477
478 Inputs ggInputs;
479 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, true, false, true, true, o2::base::GRPGeomRequest::Aligned, ggInputs, true);
480
481 auto task = std::make_shared<o2::gpu::GPURecoWorkflowSpec>(policyData, cfg, tpcSectors, tpcSectorMask, ggRequest);
482 gTask = task;
483 Inputs taskInputs = task->inputs();
484 Options taskOptions = task->options();
485 std::move(ggInputs.begin(), ggInputs.end(), std::back_inserter(taskInputs));
486
487 specs.emplace_back(DataProcessorSpec{
488 "tpc-tracker",
489 taskInputs,
490 task->outputs(),
491 AlgorithmSpec{adoptTask<o2::gpu::GPURecoWorkflowSpec>(task)},
492 taskOptions});
493 }
494
496 //
497 // tracker process
498 //
499 // selected by output type 'encoded-clusters'
500 if (runClusterEncoder) {
501 specs.emplace_back(o2::tpc::getEntropyEncoderSpec(!runGPUReco && inputType != InputType::CompClustersFlat, selIR));
502 }
503
505 //
506 // a writer process for tracks
507 //
508 // selected by output type 'tracks'
509 if (produceTracks && !isEnabled(OutputType::DisableWriter)) {
510 // defining the track writer process using the generic RootTreeWriter and generator tool
511 //
512 // defaults
513 const char* processName = filteredInp ? "tpc-track-writer_filtered" : "tpc-track-writer";
514 const char* defaultFileName = filteredInp ? "tpctracks_filtered.root" : "tpctracks.root";
515 const char* defaultTreeName = "tpcrec";
516
517 // branch definitions for RootTreeWriter spec
518 using TrackOutputType = std::vector<o2::tpc::TrackTPC>;
519
520 using ClusRefsOutputType = std::vector<o2::tpc::TPCClRefElem>;
521 // a spectator callback which will be invoked by the tree writer with the extracted object
522 // we are using it for printing a log message
523 auto logger = BranchDefinition<TrackOutputType>::Spectator([](TrackOutputType const& tracks) {
524 LOG(info) << "writing " << tracks.size() << " track(s)";
525 });
526 auto tracksdef = BranchDefinition<TrackOutputType>{InputSpec{"inputTracks", "TPC", filteredInp ? o2::header::DataDescription("TRACKSF") : o2::header::DataDescription("TRACKS"), 0}, //
527 "TPCTracks", "track-branch-name", //
528 1, //
529 logger}; //
530 auto clrefdef = BranchDefinition<ClusRefsOutputType>{InputSpec{"inputClusRef", "TPC", filteredInp ? o2::header::DataDescription("CLUSREFSF") : o2::header::DataDescription("CLUSREFS"), 0}, //
531 "ClusRefs", "trackclusref-branch-name"}; //
532 auto mcdef = BranchDefinition<std::vector<o2::MCCompLabel>>{InputSpec{"mcinput", "TPC", filteredInp ? o2::header::DataDescription("TRACKSMCLBLF") : o2::header::DataDescription("TRACKSMCLBL"), 0}, //
533 "TPCTracksMCTruth", //
534 (propagateMC ? 1 : 0), //
535 "trackmc-branch-name"}; //
536
537 // depending on the MC propagation flag, branch definition for MC labels is disabled
538 specs.push_back(MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
539 std::move(tracksdef), std::move(clrefdef),
540 std::move(mcdef))());
541 }
542
544 //
545 // a writer process for compressed clusters container
546 //
547 // selected by output type 'compressed-clusters'
548 if (produceCompClusters && !isEnabled(OutputType::DisableWriter)) {
549 // defining the track writer process using the generic RootTreeWriter and generator tool
550 //
551 // defaults
552 const char* processName = "tpc-compcluster-writer";
553 const char* defaultFileName = "tpc-compclusters.root";
554 const char* defaultTreeName = "tpcrec";
555
556 // branch definitions for RootTreeWriter spec
557 using CCluSerializedType = ROOTSerialized<CompressedClustersROOT>;
558 auto ccldef = BranchDefinition<CCluSerializedType>{InputSpec{"inputCompCl", "TPC", "COMPCLUSTERS"}, //
559 "TPCCompClusters_0", "compcluster-branch-name"}; //
560
561 specs.push_back(MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName, //
562 std::move(ccldef))()); //
563 }
564
565 return std::move(specs);
566}
567
569{
570 if (gTask) {
571 gTask->deinitialize();
572 }
573}
574
575} // end namespace reco_workflow
576} // end namespace tpc
577} // end namespace o2
Processor spec for decoder of TPC raw cluster data.
Meta data for a group describing it by sector number and global padrow.
Container to store compressed TPC cluster data.
std::string getName(const TDataMember *dm, int index, int size)
A const (ready only) version of MCTruthContainer.
Helper class to access load maps from CCDB.
Definition of the TPC Digit.
Helper class for memory management of TPC Data Formats, external from the actual data type classes to...
Helper for geometry and GRP related CCDB requests.
A special IO container - splitting a given vector to enable ROOT IO.
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
Configurable generator for RootTreeWriter processor spec.
Helper function to tokenize sequences and ranges of integral numbers.
spec definition for a TPC clusterer process
ProcessorSpec for the TPC cluster entropy encoding.
Workflow definition for the TPC reconstruction.
TBranch * ptr
Definitions of TPC Zero Suppression Data Headers.
A read-only version of MCTruthContainer allowing for storage optimisation.
void adopt(gsl::span< const char > const input)
"adopt" (without taking ownership) from an existing buffer
Generate a processor spec for the RootTreeWriter utility.
static TBranch * remapBranch(TBranch &branchRef, T **newdata)
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
GLint ref
Definition glcorearb.h:291
framework::DataProcessorSpec getDigitsReaderSpec(bool propagateMC=true, const std::string &defFile="ctpdigits.root")
Definition of a container to keep/associate and arbitrary number of labels associated to an index wit...
WorkflowSpec parallelPipeline(const WorkflowSpec &specs, size_t nPipelines, std::function< size_t()> getNumberOfSubspecs, std::function< size_t(size_t)> getSubSpec)
Inputs mergeInputs(InputSpec original, size_t maxIndex, std::function< void(InputSpec &, size_t)> amendCallback)
std::vector< DataProcessorSpec > WorkflowSpec
std::vector< ConfigParamSpec > Options
std::vector< InputSpec > Inputs
Descriptor< gSizeDataDescriptionString > DataDescription
Definition DataHeader.h:551
std::vector< framework::InputSpec > CompletionPolicyData
InputType
define input and output types of the workflow
const std::unordered_map< std::string, InputType > InputMap
framework::WorkflowSpec getWorkflow(CompletionPolicyData *policyData, std::vector< int > const &tpcSectors, unsigned long tpcSectorMask, std::vector< int > const &laneConfiguration, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts, bool propagateMC=true, unsigned nLanes=1, std::string const &cfgInput="digitizer", std::string const &cfgOutput="tracks", bool disableRootInput=false, int caClusterer=0, int zsOnTheFly=0, bool askDISTSTF=true, bool selIR=false, bool filteredInp=false, int deadMapSources=-1, bool useMCTimeGain=false)
create the workflow for TPC reconstruction
const std::unordered_map< std::string, OutputType > OutputMap
framework::DataProcessorSpec getEntropyEncoderSpec(bool inputFromFile, bool selIR=false)
create a processor spec
framework::DataProcessorSpec getClusterReaderSpec(bool useMC, const std::vector< int > *tpcSectors=nullptr, const std::vector< int > *laneConfiguration=nullptr)
o2::framework::DataProcessorSpec getTPCScalerSpec(bool enableIDCs, bool enableMShape)
framework::DataProcessorSpec getZSEncoderSpec(std::vector< int > const &tpcSectors, bool outRaw, unsigned long tpcSectorMask)
create a processor spec
Definition ZSSpec.cxx:61
o2::framework::DataProcessorSpec getTPCTriggerWriterSpec()
framework::DataProcessorSpec getZStoDigitsSpec(std::vector< int > const &tpcSectors)
Definition ZSSpec.cxx:211
framework::DataProcessorSpec getClustererSpec(bool sendMC)
framework::DataProcessorSpec getPublisherSpec(PublisherConf const &config, bool propagateMC=true)
framework::DataProcessorSpec getTPCTriggerReaderSpec()
framework::DataProcessorSpec getClusterDecoderRawSpec(bool sendMC=false)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
static void updateMatchingSubspec(InputSpec &in, header::DataHeader::SubSpecificationType subSpec)
int lumiType
what estimator to used for corrections scaling: 0: no scaling, 1: CTP, 2: IDC
int lumiMode
what corrections method to use: 0: classical scaling, 1: Using of the derivative map,...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"