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)
109 }
catch (std::out_of_range&) {
110 throw std::invalid_argument(std::string(
"invalid input type: ") + cfgInput);
112 std::vector<OutputType> outputTypes;
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);
119 return std::find(outputTypes.begin(), outputTypes.end(),
type) != outputTypes.end();
123 throw std::invalid_argument(
"filtered-input option must be provided only with pass-through input");
151 throw std::invalid_argument(
"input/output type mismatch, can not produce 'digits' from 'clustershardware'");
154 throw std::invalid_argument(
"input/output type mismatch, can not produce 'digits', nor 'clustershardware' from 'clusters'");
157 throw std::invalid_argument(
"input/output type mismatch, can not produce 'clustershardware' from 'zsraw'");
160 throw std::invalid_argument(
"ca-clusterer requires digits as input");
163 throw std::invalid_argument(
"ca-clusterer cannot produce clustershardware output");
174 if (TString(
name.data()).Contains(
"TPCDigitMCTruth") || TString(
name.data()).Contains(
"TPCClusterHwMCTruth") || TString(
name.data()).Contains(
"TPCClusterNativeMCTruth")) {
177 storedlabels->copyandflatten(flatlabels);
179 context.outputs().snapshot(
output, flatlabels);
190 using Type = std::vector<o2::tpc::Digit>;
192 specs.emplace_back(o2::tpc::getPublisherSpec<Type>(
PublisherConf{
196 {
"digitbranch",
"TPCDigit",
"Digit branch"},
197 {
"mcbranch",
"TPCDigitMCTruth",
"MC label branch"},
210 "tpc-clusterhardware-reader",
211 "tpc-clusterhardware.root",
212 "tpcclustershardware",
213 {
"databranch",
"TPCClusterHw",
"Branch with TPC ClustersHardware"},
214 {
"mcbranch",
"TPCClusterHwMCTruth",
"MC label branch"},
223 if (!getenv(
"DPL_DISABLE_TPC_TRIGGER_READER") || atoi(getenv(
"DPL_DISABLE_TPC_TRIGGER_READER")) != 1) {
236 "tpc-compressed-cluster-reader",
237 "tpc-compclusters.root",
239 {
"clusterbranch",
"TPCCompClusters",
"Branch with TPC compressed clusters"},
243 std::vector<int>(1, 0),
244 std::vector<int>(1, 0),
264 runGPUReco &= caClusterer || runHWDecoder || inputType ==
InputType::Clusters || decompressTPC;
271 runGPUReco = runHWDecoder = runClusterer = runClusterEncoder = zsToDigit =
false;
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());
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");
322 if (tpcSectorHeader->sector() < 0) {
327 for (
auto const& sector : tpcSectors) {
328 if (sector == tpcSectorHeader->sector()) {
333 throw std::runtime_error(
"sector " +
std::to_string(tpcSectorHeader->sector()) +
" not configured for writing");
335 auto getName = [tpcSectors](std::string base,
size_t index) {
341 auto fillLabels = [](TBranch& branch, std::vector<char>
const& labelbuffer,
DataRef const& ) {
344 auto ptr = &outputcontainer;
346 outputcontainer.
adopt(labelbuffer);
351 auto makeWriterSpec = [tpcSectors, laneConfiguration, propagateMC, getIndex,
getName](
const char* processName,
352 const char* defaultFileName,
353 const char* defaultTreeName,
356 bool singleBranch =
false) {
357 if (tpcSectors.size() == 0) {
358 throw std::invalid_argument(std::string(
"writer process configuration needs list of TPC sectors"));
361 auto amendInput = [tpcSectors, laneConfiguration](
InputSpec& input,
size_t index) {
365 auto amendBranchDef = [laneConfiguration, amendInput, tpcSectors, getIndex,
getName, singleBranch](
auto&& def,
bool enableMC =
true) {
367 def.keys =
mergeInputs(def.keys, laneConfiguration.size(), amendInput);
369 def.nofBranches = enableMC ? tpcSectors.size() : 0;
370 def.getIndex = getIndex;
374 def.nofBranches = enableMC ? 1 : 0;
376 return std::move(def);
380 std::move(amendBranchDef(databranch)),
381 std::move(amendBranchDef(mcbranch, propagateMC)))());
390 using DigitOutputType = std::vector<o2::tpc::Digit>;
391 specs.push_back(makeWriterSpec(
"tpc-digits-writer",
397 "digit-branch-name"},
400 "digitmc-branch-name"}));
409 specs.push_back(makeWriterSpec(
"tpc-clusterhardware-writer",
411 "tpcclustershardware",
416 "TPCClusterHwMCTruth",
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",
435 "TPCClusterNativeMCTruth",
436 "mcbranch", fillLabels},
481 auto task = std::make_shared<o2::gpu::GPURecoWorkflowSpec>(policyData, cfg, tpcSectors, tpcSectorMask, ggRequest);
483 Inputs taskInputs = task->inputs();
484 Options taskOptions = task->options();
485 std::move(ggInputs.begin(), ggInputs.end(), std::back_inserter(taskInputs));
491 AlgorithmSpec{adoptTask<o2::gpu::GPURecoWorkflowSpec>(task)},
500 if (runClusterEncoder) {
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";
518 using TrackOutputType = std::vector<o2::tpc::TrackTPC>;
520 using ClusRefsOutputType = std::vector<o2::tpc::TPCClRefElem>;
524 LOG(info) <<
"writing " << tracks.size() <<
" track(s)";
527 "TPCTracks",
"track-branch-name",
531 "ClusRefs",
"trackclusref-branch-name"};
534 (propagateMC ? 1 : 0),
535 "trackmc-branch-name"};
539 std::move(tracksdef), std::move(clrefdef),
540 std::move(mcdef))());
552 const char* processName =
"tpc-compcluster-writer";
553 const char* defaultFileName =
"tpc-compclusters.root";
554 const char* defaultTreeName =
"tpcrec";
559 "TPCCompClusters_0",
"compcluster-branch-name"};
562 std::move(ccldef))());
565 return std::move(specs);
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