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-root", InputType::CompClustersRoot},
84 {"compressed-clusters-flat", InputType::CompClustersFlat},
85 {"compressed-clusters-flat-for-encode", InputType::CompClustersFlatForEncode}};
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-root", OutputType::CompClustersRoot},
93 {"compressed-clusters-flat", OutputType::CompClustersFlat},
94 {"encoded-clusters", OutputType::EncodedClusters},
95 {"disable-writer", OutputType::DisableWriter},
96 {"send-clusters-per-sector", OutputType::SendClustersPerSector},
97 {"zsraw", OutputType::ZSRaw},
98 {"qa", OutputType::QA},
99 {"no-shared-cluster-map", OutputType::NoSharedClusterMap},
100 {"tpc-triggers", OutputType::TPCTriggers}};
101
102framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vector<int> const& tpcSectors, unsigned long tpcSectorMask, std::vector<int> const& laneConfiguration,
103 const o2::tpc::CorrectionMapsGloOpts& sclOpts, bool propagateMC, unsigned nLanes, std::string const& cfgInput, std::string const& cfgOutput, bool disableRootInput,
104 int caClusterer, int zsOnTheFly, bool askDISTSTF, const std::string& ctfdictOpt, bool selIR, bool filteredInp, int deadMapSources, bool useMCTimeGain)
105{
106 InputType inputType;
107 try {
108 inputType = InputMap.at(cfgInput);
109 } catch (std::out_of_range&) {
110 throw std::invalid_argument(std::string("invalid input type: ") + cfgInput);
111 }
112 std::vector<OutputType> outputTypes;
113 try {
114 outputTypes = RangeTokenizer::tokenize<OutputType>(cfgOutput, [](std::string const& token) { return OutputMap.at(token); });
115 } catch (std::out_of_range&) {
116 throw std::invalid_argument(std::string("invalid output type: ") + cfgOutput);
117 }
118 auto isEnabled = [&outputTypes](OutputType type) {
119 return std::find(outputTypes.begin(), outputTypes.end(), type) != outputTypes.end();
120 };
121
122 if (filteredInp && !(inputType == InputType::PassThrough)) {
123 throw std::invalid_argument("filtered-input option must be provided only with pass-through input");
124 }
125
126 bool decompressTPC = inputType == InputType::CompClustersFlat || inputType == InputType::CompClustersRoot;
127 // Disable not applicable settings depending on TPC input, no need to disable manually
128 if (decompressTPC && (isEnabled(OutputType::Clusters) || isEnabled(OutputType::Tracks))) {
129 caClusterer = false;
130 zsOnTheFly = false;
131 propagateMC = false;
132 }
134 caClusterer = false;
135 zsOnTheFly = false;
136 propagateMC = false;
137 }
138 if (inputType == InputType::ZSRaw) {
139 caClusterer = true;
140 zsOnTheFly = false;
141 propagateMC = false;
142 }
143 if (inputType == InputType::PassThrough || inputType == InputType::ClustersHardware || inputType == InputType::Clusters) {
144 caClusterer = false;
145 }
146 if (!caClusterer) {
147 zsOnTheFly = false;
148 }
149
150 if (inputType == InputType::ClustersHardware && isEnabled(OutputType::Digits)) {
151 throw std::invalid_argument("input/output type mismatch, can not produce 'digits' from 'clustershardware'");
152 }
153 if (inputType == InputType::Clusters && (isEnabled(OutputType::Digits) || isEnabled(OutputType::ClustersHardware))) {
154 throw std::invalid_argument("input/output type mismatch, can not produce 'digits', nor 'clustershardware' from 'clusters'");
155 }
156 if (inputType == InputType::ZSRaw && isEnabled(OutputType::ClustersHardware)) {
157 throw std::invalid_argument("input/output type mismatch, can not produce 'clustershardware' from 'zsraw'");
158 }
159 if (caClusterer && (inputType == InputType::Clusters || inputType == InputType::ClustersHardware)) {
160 throw std::invalid_argument("ca-clusterer requires digits as input");
161 }
162 if (caClusterer && (isEnabled(OutputType::ClustersHardware))) {
163 throw std::invalid_argument("ca-clusterer cannot produce clustershardware output");
164 }
165
166 WorkflowSpec specs;
167
168 bool produceTracks = isEnabled(OutputType::Tracks);
169
170 // We provide a special publishing method for labels which have been stored in a split format and need
171 // to be transformed into a contiguous shareable container before publishing. For other branches/types this returns
172 // false and the generic RootTreeWriter publishing proceeds
173 static Reader::SpecialPublishHook hook{[](std::string_view name, ProcessingContext& context, o2::framework::Output const& output, char* data) -> bool {
174 if (TString(name.data()).Contains("TPCDigitMCTruth") || TString(name.data()).Contains("TPCClusterHwMCTruth") || TString(name.data()).Contains("TPCClusterNativeMCTruth")) {
175 auto storedlabels = reinterpret_cast<o2::dataformats::IOMCTruthContainerView const*>(data);
177 storedlabels->copyandflatten(flatlabels);
178 // LOG(info) << "PUBLISHING CONST LABELS " << flatlabels.getNElements();
179 context.outputs().snapshot(output, flatlabels);
180 return true;
181 }
182 return false;
183 }};
184 if (!disableRootInput || inputType == InputType::PassThrough) {
185 // The OutputSpec of the PublisherSpec is configured depending on the input
186 // type. Note that the configuration of the dispatch trigger in the main file
187 // needs to be done in accordance. This means, if a new input option is added
188 // also the dispatch trigger needs to be updated.
189 if (inputType == InputType::Digits) {
190 using Type = std::vector<o2::tpc::Digit>;
191
192 specs.emplace_back(o2::tpc::getPublisherSpec<Type>(PublisherConf{
193 "tpc-digit-reader",
194 "tpcdigits.root",
195 "o2sim",
196 {"digitbranch", "TPCDigit", "Digit branch"},
197 {"mcbranch", "TPCDigitMCTruth", "MC label branch"},
198 OutputSpec{"TPC", "DIGITS"},
199 OutputSpec{"TPC", "DIGITSMCTR"},
200 tpcSectors,
201 laneConfiguration,
202 &hook},
203 propagateMC));
204 specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpts.lumiType == o2::tpc::LumiScaleType::TPCScaler, sclOpts.enableMShapeCorrection, sclOpts));
205 if (produceTracks && sclOpts.requestCTPLumi) { // need CTP digits (lumi) reader
206 specs.emplace_back(o2::ctp::getDigitsReaderSpec(false));
207 }
208 } else if (inputType == InputType::ClustersHardware) {
209 specs.emplace_back(o2::tpc::getPublisherSpec(PublisherConf{
210 "tpc-clusterhardware-reader",
211 "tpc-clusterhardware.root",
212 "tpcclustershardware",
213 {"databranch", "TPCClusterHw", "Branch with TPC ClustersHardware"},
214 {"mcbranch", "TPCClusterHwMCTruth", "MC label branch"},
215 OutputSpec{"TPC", "CLUSTERHW"},
216 OutputSpec{"TPC", "CLUSTERHWMCLBL"},
217 tpcSectors,
218 laneConfiguration,
219 &hook},
220 propagateMC));
221 } else if (inputType == InputType::Clusters) {
222 specs.emplace_back(o2::tpc::getClusterReaderSpec(propagateMC, &tpcSectors, &laneConfiguration));
223 if (!getenv("DPL_DISABLE_TPC_TRIGGER_READER") || atoi(getenv("DPL_DISABLE_TPC_TRIGGER_READER")) != 1) {
224 specs.emplace_back(o2::tpc::getTPCTriggerReaderSpec());
225 }
226 specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpts.lumiType == o2::tpc::LumiScaleType::TPCScaler, sclOpts.enableMShapeCorrection, sclOpts));
227 if (sclOpts.requestCTPLumi) { // need CTP digits (lumi) reader
228 specs.emplace_back(o2::ctp::getDigitsReaderSpec(false));
229 }
230 } else if (inputType == InputType::CompClustersRoot) {
231 // TODO: need to check if we want to store the MC labels alongside with compressed clusters
232 // for the moment reading of labels is disabled (last parameter is false)
233 // TODO: make a different publisher spec for only one output spec, for now using the
234 // PublisherSpec with only sector 0, '_0' is thus appended to the branch name
235 specs.emplace_back(o2::tpc::getPublisherSpec(PublisherConf{
236 "tpc-compressed-cluster-reader",
237 "tpc-compclusters.root",
238 "tpcrec",
239 {"clusterbranch", "TPCCompClusters", "Branch with TPC compressed clusters"},
240 {"", "", ""}, // No MC labels
241 OutputSpec{"TPC", "COMPCLUSTERS"},
242 OutputSpec{"", ""}, // No MC labels
243 std::vector<int>(1, 0),
244 std::vector<int>(1, 0),
245 &hook},
246 false));
247 }
248 }
249
250 // output matrix
251 // Note: the ClusterHardware format is probably a deprecated legacy format and also the
252 // ClusterDecoderRawSpec
253 bool produceCompClustersRoot = isEnabled(OutputType::CompClustersRoot);
254 bool produceCompClustersFlat = isEnabled(OutputType::CompClustersFlat);
255 bool runGPUReco = (produceTracks || produceCompClustersRoot || produceCompClustersFlat || (isEnabled(OutputType::Clusters) && caClusterer) || inputType == InputType::CompClustersFlat) && inputType != InputType::CompClustersFlatForEncode;
256 bool runHWDecoder = !caClusterer && (runGPUReco || isEnabled(OutputType::Clusters));
257 bool runClusterer = !caClusterer && (runHWDecoder || isEnabled(OutputType::ClustersHardware));
258 bool zsDecoder = inputType == InputType::ZSRaw;
259 bool runClusterEncoder = isEnabled(OutputType::EncodedClusters);
260
261 // input matrix
262 runClusterer &= inputType == InputType::Digitizer || inputType == InputType::Digits;
263 runHWDecoder &= runClusterer || inputType == InputType::ClustersHardware;
264 runGPUReco &= caClusterer || runHWDecoder || inputType == InputType::Clusters || decompressTPC;
265
266 bool outRaw = inputType == InputType::Digits && isEnabled(OutputType::ZSRaw) && !isEnabled(OutputType::DisableWriter);
267 // bool runZSDecode = inputType == InputType::ZSRaw;
268 bool zsToDigit = inputType == InputType::ZSRaw && isEnabled(OutputType::Digits);
269
270 if (inputType == InputType::PassThrough) {
271 runGPUReco = runHWDecoder = runClusterer = runClusterEncoder = zsToDigit = false;
272 }
273
274 WorkflowSpec parallelProcessors;
276 //
277 // clusterer process(es)
278 //
279 //
280 if (runClusterer) {
281 parallelProcessors.push_back(o2::tpc::getClustererSpec(propagateMC));
282 }
283
285 //
286 // cluster decoder process(es)
287 //
288 //
289 if (runHWDecoder) {
290 parallelProcessors.push_back(o2::tpc::getClusterDecoderRawSpec(propagateMC));
291 }
292
294 //
295 // set up parallel TPC lanes
296 //
297 // the parallelPipeline helper distributes the subspec ids from the lane configuration
298 // among the pipelines. All inputs and outputs of processors of one pipeline will be
299 // cloned by the number of subspecs served by this pipeline and amended with the subspecs
300 parallelProcessors = parallelPipeline(
301 parallelProcessors, nLanes,
302 [&laneConfiguration]() { return laneConfiguration.size(); },
303 [&laneConfiguration](size_t index) { return laneConfiguration[index]; });
304 specs.insert(specs.end(), parallelProcessors.begin(), parallelProcessors.end());
305
307 //
308 // generation of processor specs for various types of outputs
309 // based on generic RootTreeWriter and MakeRootTreeWriterSpec generator
310 //
311 // -------------------------------------------------------------------------------------------
312 // the callbacks for the RootTreeWriter
313 //
314 // The generic writer needs a way to associate incoming data with the individual branches for
315 // the TPC sectors. The sector number is transmitted as part of the sector header, the callback
316 // finds the corresponding index in the vector of configured sectors
317 auto getIndex = [tpcSectors](o2::framework::DataRef const& ref) {
318 auto const* tpcSectorHeader = o2::framework::DataRefUtils::getHeader<o2::tpc::TPCSectorHeader*>(ref);
319 if (!tpcSectorHeader) {
320 throw std::runtime_error("TPC sector header missing in header stack");
321 }
322 if (tpcSectorHeader->sector() < 0) {
323 // special data sets, don't write
324 return ~(size_t)0;
325 }
326 size_t index = 0;
327 for (auto const& sector : tpcSectors) {
328 if (sector == tpcSectorHeader->sector()) {
329 return index;
330 }
331 ++index;
332 }
333 throw std::runtime_error("sector " + std::to_string(tpcSectorHeader->sector()) + " not configured for writing");
334 };
335 auto getName = [tpcSectors](std::string base, size_t index) {
336 return base + "_" + std::to_string(tpcSectors.at(index));
337 };
338
339 // -------------------------------------------------------------------------------------------
340 // helper to create writer specs for different types of output
341 auto fillLabels = [](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& /*ref*/) {
344 auto ptr = &outputcontainer;
346 outputcontainer.adopt(labelbuffer);
347 br->Fill();
348 br->ResetAddress();
349 };
350
351 auto makeWriterSpec = [tpcSectors, laneConfiguration, propagateMC, getIndex, getName](const char* processName,
352 const char* defaultFileName,
353 const char* defaultTreeName,
354 auto&& databranch,
355 auto&& mcbranch,
356 bool singleBranch = false) {
357 if (tpcSectors.size() == 0) {
358 throw std::invalid_argument(std::string("writer process configuration needs list of TPC sectors"));
359 }
360
361 auto amendInput = [tpcSectors, laneConfiguration](InputSpec& input, size_t index) {
362 input.binding += std::to_string(laneConfiguration[index]);
363 DataSpecUtils::updateMatchingSubspec(input, laneConfiguration[index]);
364 };
365 auto amendBranchDef = [laneConfiguration, amendInput, tpcSectors, getIndex, getName, singleBranch](auto&& def, bool enableMC = true) {
366 if (!singleBranch) {
367 def.keys = mergeInputs(def.keys, laneConfiguration.size(), amendInput);
368 // the branch is disabled if set to 0
369 def.nofBranches = enableMC ? tpcSectors.size() : 0;
370 def.getIndex = getIndex;
371 def.getName = getName;
372 } else {
373 // instead of the separate sector branches only one is going to be written
374 def.nofBranches = enableMC ? 1 : 0;
375 }
376 return std::move(def);
377 };
378
379 return std::move(MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
380 std::move(amendBranchDef(databranch)),
381 std::move(amendBranchDef(mcbranch, propagateMC)))());
382 };
383
385 //
386 // a writer process for digits
387 //
388 // selected by output type 'difits'
389 if (isEnabled(OutputType::Digits) && !isEnabled(OutputType::DisableWriter)) {
390 using DigitOutputType = std::vector<o2::tpc::Digit>;
391 specs.push_back(makeWriterSpec("tpc-digits-writer",
392 inputType == InputType::ZSRaw ? "tpc-zs-digits.root" : inputType == InputType::Digits ? "tpc-filtered-digits.root"
393 : "tpcdigits.root",
394 "o2sim",
395 BranchDefinition<DigitOutputType>{InputSpec{"data", "TPC", "DIGITS", 0},
396 "TPCDigit",
397 "digit-branch-name"},
398 BranchDefinition<MCLabelContainer>{InputSpec{"mc", "TPC", "DIGITSMCTR", 0},
399 "TPCDigitMCTruth",
400 "digitmc-branch-name"}));
401 }
402
404 //
405 // a writer process for hardware clusters
406 //
407 // selected by output type 'clustershardware'
408 if (isEnabled(OutputType::ClustersHardware) && !isEnabled(OutputType::DisableWriter)) {
409 specs.push_back(makeWriterSpec("tpc-clusterhardware-writer",
410 inputType == InputType::ClustersHardware ? "tpc-filtered-clustershardware.root" : "tpc-clustershardware.root",
411 "tpcclustershardware",
412 BranchDefinition<const char*>{InputSpec{"data", "TPC", "CLUSTERHW", 0},
413 "TPCClusterHw",
414 "databranch"},
415 BranchDefinition<MCLabelContainer>{InputSpec{"mc", "TPC", "CLUSTERHWMCLBL", 0},
416 "TPCClusterHwMCTruth",
417 "mcbranch"}));
418 }
419
421 //
422 // a writer process for TPC native clusters
423 //
424 // selected by output type 'clusters'
425 if (isEnabled(OutputType::Clusters) && !isEnabled(OutputType::DisableWriter)) {
426 // if the caClusterer is enabled, only one data set with the full TPC is produced, and the writer
427 // is configured to write one single branch
428 specs.push_back(makeWriterSpec(filteredInp ? "tpc-native-cluster-writer_filtered" : "tpc-native-cluster-writer",
429 (inputType == InputType::Clusters || filteredInp) ? "tpc-filtered-native-clusters.root" : "tpc-native-clusters.root",
430 "tpcrec",
431 BranchDefinition<const char*>{InputSpec{"data", ConcreteDataTypeMatcher{"TPC", filteredInp ? o2::header::DataDescription("CLUSTERNATIVEF") : o2::header::DataDescription("CLUSTERNATIVE")}},
432 "TPCClusterNative",
433 "databranch"},
435 "TPCClusterNativeMCTruth",
436 "mcbranch", fillLabels},
437 (caClusterer || decompressTPC || inputType == InputType::PassThrough) && !isEnabled(OutputType::SendClustersPerSector)));
438 }
439
440 if ((isEnabled(OutputType::TPCTriggers) || (caClusterer && runGPUReco)) && !isEnabled(OutputType::DisableWriter)) {
441 specs.push_back(o2::tpc::getTPCTriggerWriterSpec());
442 }
443
444 if (zsOnTheFly) {
445 specs.emplace_back(o2::tpc::getZSEncoderSpec(tpcSectors, outRaw, tpcSectorMask));
446 }
447
448 if (zsToDigit) {
449 specs.emplace_back(o2::tpc::getZStoDigitsSpec(tpcSectors));
450 }
451
453 //
454 // tracker process
455 //
456 // selected by output type 'tracks'
457 if (runGPUReco) {
459 cfg.runTPCTracking = true;
460 cfg.decompressTPC = decompressTPC;
461 cfg.decompressTPCFromROOT = decompressTPC && inputType == InputType::CompClustersRoot;
462 cfg.caClusterer = caClusterer;
463 cfg.zsDecoder = zsDecoder;
464 cfg.zsOnTheFly = zsOnTheFly;
465 cfg.outputTracks = produceTracks;
466 cfg.outputCompClustersRoot = produceCompClustersRoot;
467 cfg.outputCompClustersFlat = produceCompClustersFlat || 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::CompClustersFlatForEncode, selIR, ctfdictOpt));
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-root'
548 if (produceCompClustersRoot && !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
std::vector< std::string > labels
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::CorrectionMapsGloOpts &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, const std::string &ctfdictOpt="none", 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 getClusterReaderSpec(bool useMC, const std::vector< int > *tpcSectors=nullptr, const std::vector< int > *laneConfiguration=nullptr)
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)
@ TPCScaler
use TPC scaler for scaling
framework::DataProcessorSpec getPublisherSpec(PublisherConf const &config, bool propagateMC=true)
framework::DataProcessorSpec getEntropyEncoderSpec(bool inputFromFile, bool selIR=false, const std::string &ctfdictOpt="none")
create a processor spec
o2::framework::DataProcessorSpec getTPCScalerSpec(bool enableIDCs, bool enableMShape, const o2::tpc::CorrectionMapsGloOpts &sclOpts)
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)
LumiScaleType lumiType
what estimator to used for corrections scaling: 0: no scaling, 1: CTP, 2: IDC
bool requestCTPLumi
request CTP Lumi regardless of what is used for corrections scaling
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"