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
12#include <algorithm>
13#include <unordered_map>
14#include <vector>
15
16#include <fairlogger/Logger.h>
17
34
35namespace o2
36{
37
38template <typename T>
39using BranchDefinition = framework::MakeRootTreeWriterSpec::BranchDefinition<T>;
40
41namespace emcal
42{
43
44namespace reco_workflow
45{
46
48 bool askDISTSTF,
49 bool enableDigitsPrinter,
50 int subspecificationIn,
51 int subspecificationOut,
52 std::string const& cfgInput,
53 std::string const& cfgOutput,
54 bool disableRootInput,
55 bool disableRootOutput,
56 bool disableDecodingErrors,
57 bool disableTriggerReconstruction)
58{
59
60 const std::unordered_map<std::string, InputType> InputMap{
61 {"digits", InputType::Digits},
62 {"cells", InputType::Cells},
63 {"raw", InputType::Raw},
64 {"clusters", InputType::Clusters},
65 };
66
67 const std::unordered_map<std::string, OutputType> OutputMap{
68 {"digits", OutputType::Digits},
69 {"cells", OutputType::Cells},
70 {"raw", OutputType::Raw},
71 {"clusters", OutputType::Clusters},
72 {"analysisclusters", OutputType::AnalysisClusters}};
73
74 std::unordered_map<InputType, std::vector<OutputType>> allowedIO;
77 allowedIO[InputType::Raw] = std::vector<OutputType>{OutputType::Cells};
78
79 InputType inputType;
80
81 try {
82 inputType = InputMap.at(cfgInput);
83 } catch (std::out_of_range&) {
84 throw std::invalid_argument(std::string("invalid input type: ") + cfgInput);
85 }
86 std::vector<OutputType> outputTypes;
87 try {
88 outputTypes = RangeTokenizer::tokenize<OutputType>(cfgOutput, [&](std::string const& token) { return OutputMap.at(token); });
89 } catch (std::out_of_range&) {
90 throw std::invalid_argument(std::string("invalid output type: ") + cfgOutput);
91 }
92 auto isEnabled = [&outputTypes](OutputType type) {
93 return std::find(outputTypes.begin(), outputTypes.end(), type) != outputTypes.end();
94 };
95
96 auto isAllowedIOCombination = [&allowedIO](InputType inp, OutputType out) {
97 const auto& vout = allowedIO[inp];
98 return std::find(vout.begin(), vout.end(), out) != vout.end();
99 };
100
101 auto getOutputTypeName = [&OutputMap](OutputType out) {
102 std::string str;
103 for (const auto& o : OutputMap) {
104 if (o.second == out) {
105 str = std::string(o.first);
106 }
107 }
108 return str;
109 };
110
111 // make sure inputs/outputs combinatios are enabled
112 for (const auto outType : outputTypes) {
113 if (!isAllowedIOCombination(inputType, outType)) {
114 throw std::runtime_error(fmt::format("Input {:s} is not allowed with output {:s}", cfgInput, getOutputTypeName(outType)));
115 }
116 }
117
118 if (inputType == InputType::Raw) {
119 propagateMC = false;
120 }
121
123
124 if (inputType == InputType::Digits) {
125 using digitInputType = std::vector<o2::emcal::Digit>;
126 if (!disableRootInput) {
127 specs.emplace_back(o2::emcal::getPublisherSpec<digitInputType>(PublisherConf{
128 "emcal-digit-reader",
129 "o2sim",
130 "emcdigits.root",
131 {"digitbranch", "EMCALDigit", "Digit branch"},
132 {"digittriggerbranch", "EMCALDigitTRGR", "Trigger record branch"},
133 {"mcbranch", "EMCALDigitMCTruth", "MC label branch"},
134 o2::framework::OutputSpec{"EMC", "DIGITS"},
135 o2::framework::OutputSpec{"EMC", "DIGITSTRGR"},
136 o2::framework::OutputSpec{"EMC", "DIGITSMCTR"}},
137 0, propagateMC));
138 }
139
140 if (enableDigitsPrinter) {
141 try {
142 specs.emplace_back(o2::emcal::reco_workflow::getEmcalDigitsPrinterSpec("digits"));
143 } catch (std::runtime_error& e) {
144 LOG(error) << "Cannot create digits printer spec: " << e.what();
145 }
146 }
147 } else if (inputType == InputType::Cells) {
148 using cellInputType = std::vector<o2::emcal::Cell>;
149 if (!disableRootInput) {
150 specs.emplace_back(o2::emcal::getPublisherSpec<cellInputType>(PublisherConf{
151 "emcal-cell-reader",
152 "o2sim",
153 "emccells.root",
154 {"cellbranch", "EMCALCell", "Cell branch"},
155 {"celltriggerbranch", "EMCALCellTRGR", "Trigger record branch"},
156 {"mcbranch", "EMCALCellMCTruth", "MC label branch"},
157 o2::framework::OutputSpec{"EMC", "CELLS"},
158 o2::framework::OutputSpec{"EMC", "CELLSTRGR"},
159 o2::framework::OutputSpec{"EMC", "CELLSMCTR"}},
160 0, propagateMC));
161 }
162 if (enableDigitsPrinter) {
163 try {
164 specs.emplace_back(o2::emcal::reco_workflow::getEmcalDigitsPrinterSpec("cells"));
165 } catch (std::runtime_error& e) {
166 LOG(error) << "Cannot create digits printer spec: " << e.what();
167 }
168 }
169 }
170
171 if (isEnabled(OutputType::Cells)) {
172 // add converter for cells
173 if (inputType == InputType::Digits) {
174 specs.emplace_back(o2::emcal::reco_workflow::getCellConverterSpec(propagateMC, subspecificationIn, subspecificationOut));
175 } else if (inputType == InputType::Raw) {
176 // raw data will come from upstream
177 specs.emplace_back(o2::emcal::reco_workflow::getRawToCellConverterSpec(askDISTSTF, disableDecodingErrors, disableTriggerReconstruction, subspecificationOut));
178 }
179 }
180
181 if (isEnabled(OutputType::Clusters)) {
182 // add clusterizer
183 specs.emplace_back(o2::emcal::reco_workflow::getClusterizerSpec(inputType == InputType::Digits));
184 }
185
186 if (isEnabled(OutputType::AnalysisClusters)) {
187 // add clusters from cells
189 }
190
191 auto makeWriterSpec = [propagateMC](const char* processName, const char* defaultFileName, const char* defaultTreeName,
192 auto&& databranch, auto&& triggerbranch, auto&& mcbranch) {
193 // depending on the MC propagation flag, the RootTreeWriter spec is created with two
194 // or one branch definition
195 if (propagateMC) {
196 return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
197 std::move(databranch),
198 std::move(triggerbranch),
199 std::move(mcbranch)));
200 }
201 return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
202 std::move(databranch),
203 std::move(triggerbranch)));
204 };
205
206 // TODO: Write comment in push comment @matthiasrichter
207 auto makeWriterSpec_Cluster = [](const char* processName, const char* defaultFileName, const char* defaultTreeName,
208 auto&& clusterbranch, auto&& digitindicesbranch, auto&& clustertriggerbranch, auto&& indicestriggerbranch) {
209 // RootTreeWriter spec is created with one branch definition
210 return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
211 std::move(clusterbranch),
212 std::move(digitindicesbranch),
213 std::move(clustertriggerbranch),
214 std::move(indicestriggerbranch)));
215 };
216
217 auto makeWriterSpec_AnalysisCluster = [](const char* processName, const char* defaultFileName, const char* defaultTreeName,
218 auto&& analysisclusterbranch) {
219 // RootTreeWriter spec is created with one branch definition
220 return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
221 std::move(analysisclusterbranch)));
222 };
223
224 auto makeWriterSpec_CellsTR = [disableDecodingErrors](const char* processName, const char* defaultFileName, const char* defaultTreeName,
225 auto&& CellsBranch, auto&& TriggerRecordBranch, auto&& DecoderErrorsBranch) {
226 return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
227 std::move(CellsBranch),
228 std::move(TriggerRecordBranch),
229 std::move(DecoderErrorsBranch)));
230 };
231
232 auto makeWriterSpec_CellsTR_noerrors = [](const char* processName, const char* defaultFileName, const char* defaultTreeName,
233 auto&& CellsBranch, auto&& TriggerRecordBranch) {
234 return std::move(o2::framework::MakeRootTreeWriterSpec(processName, defaultFileName, defaultTreeName,
235 std::move(CellsBranch),
236 std::move(TriggerRecordBranch)));
237 };
238 /*
239 // RS getting input digits and outputing them under the same outputspec will create dependency loop when piping the workflows
240 if (isEnabled(OutputType::Digits) && !disableRootOutput) {
241 using DigitOutputType = std::vector<o2::emcal::Digit>;
242 using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>;
243 specs.push_back(makeWriterSpec("emcal-digits-writer",
244 inputType == InputType::Digits ? "emc-filtered-digits.root" : "emcdigits.root",
245 "o2sim",
246 BranchDefinition<DigitOutputType>{o2::framework::InputSpec{"data", "EMC", "DIGITS", 0},
247 "EMCDigit",
248 "digit-branch-name"},
249 BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"trigger", "EMC", "DIGITSTRGR", 0},
250 "EMCALDigitTRGR",
251 "digittrigger-branch-name"},
252 BranchDefinition<o2::dataformats::MCTruthContainer<o2::emcal::MCLabel>>{o2::framework::InputSpec{"mc", "EMC", "DIGITSMCTR", 0},
253 "EMCDigitMCTruth",
254 "digitmc-branch-name"})());
255 }
256 */
257 if (isEnabled(OutputType::Cells) && !disableRootOutput) {
258 if ((inputType == InputType::Digits) || (inputType == InputType::Cells)) {
259 using DigitOutputType = std::vector<o2::emcal::Cell>;
260 using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>;
261 specs.push_back(makeWriterSpec("emcal-cells-writer", "emccells.root", "o2sim",
263 "EMCALCell",
264 "cell-branch-name"},
265 BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"trigger", "EMC", "CELLSTRGR", 0},
266 "EMCALCellTRGR",
267 "celltrigger-branch-name"},
269 "EMCALCellMCTruth",
270 "cellmc-branch-name"})());
271 } else {
272 using CellsDataType = std::vector<o2::emcal::Cell>;
273 using TriggerRecordDataType = std::vector<o2::emcal::TriggerRecord>;
274 if (disableDecodingErrors) {
275 specs.push_back(makeWriterSpec_CellsTR_noerrors("emcal-cells-writer",
276 "emccells.root",
277 "o2sim",
279 "EMCALCell",
280 "cell-branch-name"},
282 "EMCALCellTRGR",
283 "celltrigger-branch-name"})());
284
285 } else {
286 using DecoderErrorsDataType = std::vector<o2::emcal::ErrorTypeFEE>;
287 specs.push_back(makeWriterSpec_CellsTR("emcal-cells-writer",
288 "emccells.root",
289 "o2sim",
291 "EMCALCell",
292 "cell-branch-name"},
294 "EMCALCellTRGR",
295 "celltrigger-branch-name"},
297 "EMCALDECODERERR",
298 "decodererror-branch-name"})());
299 }
300 }
301 }
302
303 if (isEnabled(OutputType::Clusters) && !disableRootOutput) {
304 using ClusterOutputType = std::vector<o2::emcal::Cluster>;
305 using ClusterIndicesOutputType = std::vector<o2::emcal::ClusterIndex>;
306 using TriggerOutputType = std::vector<o2::emcal::TriggerRecord>;
307
308 specs.push_back(makeWriterSpec_Cluster("emcal-clusters-writer",
309 "emcclusters.root",
310 "o2sim",
311 BranchDefinition<ClusterOutputType>{o2::framework::InputSpec{"clusters", "EMC", "CLUSTERS", 0},
312 "EMCALCluster",
313 "cluster-branch-name"},
314 BranchDefinition<ClusterIndicesOutputType>{o2::framework::InputSpec{"clusterindices", "EMC", "INDICES", 0},
315 "EMCALClusterInputIndex",
316 "clusterdigitindices-branch-name"},
317 BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"clusterTRGR", "EMC", "CLUSTERSTRGR", 0},
318 "EMCALClusterTRGR",
319 "clustertrigger-branch-name"},
320 BranchDefinition<TriggerOutputType>{o2::framework::InputSpec{"indicesTRGR", "EMC", "INDICESTRGR", 0},
321 "EMCIndicesTRGR",
322 "indicestrigger-branch-name"})());
323 }
324
325 if (isEnabled(OutputType::AnalysisClusters) && !disableRootOutput) {
326 using AnalysisClusterOutputType = std::vector<o2::emcal::AnalysisCluster>;
327
328 specs.push_back(makeWriterSpec_AnalysisCluster("emcal-analysis-clusters-writer",
329 "emcAnalysisClusters.root",
330 "o2sim",
331 BranchDefinition<AnalysisClusterOutputType>{o2::framework::InputSpec{"analysisclusters", "EMC", "ANALYSISCLUSTERS", 0},
332 "EMCAnalysisCluster",
333 "cluster-branch-name"})());
334 }
335
336 return std::move(specs);
337}
338
339} // namespace reco_workflow
340
341} // namespace emcal
342
343} // namespace o2
const std::unordered_map< std::string, InputType > InputMap
bool o
Definition of a container to keep Monte Carlo truth external to simulation objects.
Configurable generator for RootTreeWriter processor spec.
Helper function to tokenize sequences and ranges of integral numbers.
Generate a processor spec for the RootTreeWriter utility.
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
framework::DataProcessorSpec getClusterizerSpec(bool useDigits)
Creating DataProcessorSpec for the EMCAL Clusterizer Spec.
o2::framework::DataProcessorSpec getEmcalDigitsPrinterSpec(std::string inputtype)
Creating digits printer spec.
framework::DataProcessorSpec getCellConverterSpec(bool propagateMC, int inputSubsepc=0, int outputSubspec=0)
Creating DataProcessorSpec for the EMCAL Cell Converter Spec.
framework::DataProcessorSpec getAnalysisClusterSpec(bool useDigits)
Creating DataProcessorSpec for the EMCAL Analysis Cluster Spec.
framework::WorkflowSpec getWorkflow(bool propagateMC=true, bool askDISTSTF=true, bool enableDigitsPrinter=false, int subspecificationIn=0, int subspecificationOut=0, std::string const &cfgInput="digits", std::string const &cfgOutput="clusters", bool disableRootInput=false, bool disableRootOutput=false, bool disableDecodingErrors=false, bool disableTriggerReconstruction=false)
create the workflow for EMCAL reconstruction
@ Digits
read digits from file
@ Cells
read compressed cells from file
@ Raw
read data in raw page format from file
@ Clusters
read native clusters from file
framework::DataProcessorSpec getRawToCellConverterSpec(bool askDISTSTF, bool disableDecodingError, bool disableTriggerReconstruction, int subspecification)
Creating DataProcessorSpec for the EMCAL Cell Converter Spec.
@ AnalysisClusters
EMCAL analysis clusters.
std::vector< DataProcessorSpec > WorkflowSpec
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
const std::string str