Project
Loading...
Searching...
No Matches
AnalysisSupportHelpers.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
17#include "WorkflowHelpers.h"
18
19template class std::vector<o2::framework::OutputObjectInfo>;
20template class std::vector<o2::framework::OutputTaskInfo>;
21
22namespace o2::framework
23{
24
25std::shared_ptr<DataOutputDirector> AnalysisSupportHelpers::getDataOutputDirector(ConfigContext const& ctx)
26{
27 auto const& options = ctx.options();
28 auto const& OutputsInputs = ctx.services().get<DanglingEdgesContext>().outputsInputs;
29 auto const& isDangling = ctx.services().get<DanglingEdgesContext>().isDangling;
30
31 std::shared_ptr<DataOutputDirector> dod = std::make_shared<DataOutputDirector>();
32
33 // analyze options and take actions accordingly
34 // default values
35 std::string rdn, resdir("./");
36 std::string fnb, fnbase("AnalysisResults_trees");
37 float mfs, maxfilesize(-1.);
38 std::string fmo, filemode("RECREATE");
39 int ntfm, ntfmerge = 1;
40
41 // values from json
42 if (options.isSet("aod-writer-json")) {
43 auto fnjson = options.get<std::string>("aod-writer-json");
44 if (!fnjson.empty()) {
45 std::tie(rdn, fnb, fmo, mfs, ntfm) = dod->readJson(fnjson);
46 if (!rdn.empty()) {
47 resdir = rdn;
48 }
49 if (!fnb.empty()) {
50 fnbase = fnb;
51 }
52 if (!fmo.empty()) {
53 filemode = fmo;
54 }
55 if (mfs > 0.) {
56 maxfilesize = mfs;
57 }
58 if (ntfm > 0) {
59 ntfmerge = ntfm;
60 }
61 }
62 }
63
64 // values from command line options, information from json is overwritten
65 if (options.isSet("aod-writer-resdir")) {
66 rdn = options.get<std::string>("aod-writer-resdir");
67 if (!rdn.empty()) {
68 resdir = rdn;
69 }
70 }
71 if (options.isSet("aod-writer-resfile")) {
72 fnb = options.get<std::string>("aod-writer-resfile");
73 if (!fnb.empty()) {
74 fnbase = fnb;
75 }
76 }
77 if (options.isSet("aod-writer-resmode")) {
78 fmo = options.get<std::string>("aod-writer-resmode");
79 if (!fmo.empty()) {
80 filemode = fmo;
81 }
82 }
83 if (options.isSet("aod-writer-maxfilesize")) {
84 mfs = options.get<float>("aod-writer-maxfilesize");
85 if (mfs > 0) {
86 maxfilesize = mfs;
87 }
88 }
89 if (options.isSet("aod-writer-ntfmerge")) {
90 ntfm = options.get<int>("aod-writer-ntfmerge");
91 if (ntfm > 0) {
92 ntfmerge = ntfm;
93 }
94 }
95 // parse the keepString
96 if (options.isSet("aod-writer-keep")) {
97 auto keepString = options.get<std::string>("aod-writer-keep");
98 if (!keepString.empty()) {
99 dod->reset();
100 std::string d("dangling");
101 if (keepString.starts_with(d)) {
102 // use the dangling outputs
103 std::vector<InputSpec> danglingOutputs;
104 for (auto ii = 0u; ii < OutputsInputs.size(); ii++) {
105 if (DataSpecUtils::partialMatch(OutputsInputs[ii], writableAODOrigins) && isDangling[ii]) {
106 danglingOutputs.emplace_back(OutputsInputs[ii]);
107 }
108 }
109 dod->readSpecs(danglingOutputs);
110 } else {
111 // use the keep string
112 dod->readString(keepString);
113 }
114 }
115 }
116 dod->setResultDir(resdir);
117 dod->setFilenameBase(fnbase);
118 dod->setFileMode(filemode);
119 dod->setMaximumFileSize(maxfilesize);
120 dod->setNumberTimeFramesToMerge(ntfmerge);
121
122 return dod;
123}
124
125void AnalysisSupportHelpers::addMissingOutputsToReader(std::vector<OutputSpec> const& providedOutputs,
126 std::vector<InputSpec> const& requestedInputs,
127 DataProcessorSpec& publisher)
128{
129 requestedInputs |
130 views::filter_not_matching(providedOutputs) | // filter the inputs that are already provided
131 views::filter_not_matching(publisher.outputs) | // filter the inputs that are already covered
132 views::input_to_output_specs() |
133 sinks::append_to{publisher.outputs}; // append them to the publisher outputs
134}
135
136void AnalysisSupportHelpers::addMissingOutputsToSpawner(std::vector<OutputSpec> const& providedSpecials,
137 std::vector<InputSpec> const& requestedSpecials,
138 std::vector<InputSpec>& requestedAODs,
139 DataProcessorSpec& publisher)
140{
141 requestedSpecials |
142 views::filter_not_matching(providedSpecials) | // filter the inputs that are already provided
143 views::input_to_output_specs() |
144 sinks::append_to{publisher.outputs}; // append them to the publisher outputs
145
146 std::vector<InputSpec> additionalInputs;
147 for (auto const& input : requestedSpecials | views::filter_not_matching(providedSpecials)) {
148 input.metadata |
149 views::filter_string_params_with("input:") |
150 views::params_to_input_specs() |
151 sinks::update_input_list{additionalInputs}; // store into a temporary
152 }
153 additionalInputs | sinks::update_input_list{requestedAODs}; // update requestedAODs
154 additionalInputs | sinks::update_input_list{publisher.inputs}; // update publisher inputs
155}
156
157void AnalysisSupportHelpers::addMissingOutputsToBuilder(std::vector<InputSpec> const& requestedSpecials,
158 std::vector<InputSpec>& requestedAODs,
159 std::vector<InputSpec>& requestedDYNs,
160 DataProcessorSpec& publisher)
161{
162 requestedSpecials |
163 views::input_to_output_specs() |
164 sinks::append_to{publisher.outputs}; // append them to the publisher outputs
165
166 std::vector<InputSpec> additionalInputs;
167 for (auto const& input : requestedSpecials) {
168 input.metadata |
169 views::filter_string_params_with("input:") |
170 views::params_to_input_specs() |
171 sinks::update_input_list{additionalInputs}; // store into a temporary
172 }
173
174 additionalInputs | sinks::update_input_list{publisher.inputs}; // update publisher inputs
175 // FIXME: until we have a single list of pairs
176 additionalInputs |
177 std::ranges::views::filter([](InputSpec const& input) {
178 return DataSpecUtils::partialMatch(input, AODOrigins) || std::ranges::any_of(input.metadata, checks::has_params_with_name_starting("aod-origin-replaced"));
179 }) |
180 std::ranges::views::filter([](InputSpec const& input) {
181 return std::ranges::none_of(input.metadata, [](ConfigParamSpec const& p) { return (p.name.compare("projectors") == 0) || (p.name.compare("index-records") == 0); });
182 }) |
183 sinks::update_input_list{requestedAODs}; // update requestedAODs
184 additionalInputs |
185 std::ranges::views::filter([](InputSpec const& input) {
186 return std::ranges::any_of(input.metadata, [](ConfigParamSpec const& p) { return p.name.compare("projectors") == 0; });
187 }) |
188 sinks::update_input_list{requestedDYNs}; // update requestedDYNs
189}
190
191// =============================================================================
192DataProcessorSpec AnalysisSupportHelpers::getOutputObjHistSink(ConfigContext const& ctx)
193{
194 // Lifetime is sporadic because we do not ask each analysis task to send its
195 // results every timeframe.
197 .name = "internal-dpl-aod-global-analysis-file-sink",
198 .inputs = {InputSpec("x", DataSpecUtils::dataDescriptorMatcherFrom(header::DataOrigin{"ATSK"}), Lifetime::Sporadic)},
199 .outputs = {OutputSpec{OutputLabel{"dummy"}, o2::header::DataOrigin{"DUMM"}, o2::header::DataDescription{"DUMMY"}, 0, Lifetime::Sporadic}},
200 .algorithm = PluginManager::loadAlgorithmFromPlugin("O2FrameworkAnalysisSupport", "ROOTObjWriter", ctx),
201 };
202
203 return spec;
204}
205
206// add sink for the AODs
208 AnalysisSupportHelpers::getGlobalAODSink(ConfigContext const& ctx)
209{
210 auto& ac = ctx.services().get<DanglingEdgesContext>();
211
212 // the command line options relevant for the writer are global
213 // see runDataProcessing.h
215 .name = "internal-dpl-aod-writer",
216 .inputs = ac.outputsInputsAOD,
217 .outputs = {},
218 .algorithm = PluginManager::loadAlgorithmFromPlugin("O2FrameworkAnalysisSupport", "ROOTTTreeWriter", ctx),
219 };
220
221 return spec;
222}
223} // namespace o2::framework
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events d
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
o2::framework::InputSpec InputSpec
std::vector< ConfigParamSpec > metadata
A set of configurables which can be used to customise the InputSpec.
Definition InputSpec.h:76