R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BNeulandApp.cxx
Go to the documentation of this file.
1#include "R3BNeulandApp.h"
2#include "R3BFileSource2.h"
3#include <CLI/CLI.hpp>
4#include <FairParRootFileIo.h>
5#include <FairRootFileSink.h>
6#include <FairRun.h>
7#include <FairRuntimeDb.h>
8#include <TGeoManager.h>
9#include <fmt/color.h>
10#include <fmt/format.h>
11#include <gsl/span>
12#ifdef HAS_MPI
13#include <mpi.h>
14#endif
15
16using gsl::span;
17namespace
18{
19 namespace fs = std::filesystem;
20 template <typename T>
21 auto get_partition_from(const std::vector<T>& elements, int num_of_partitions, int partition_num) -> span<const T>
22 {
23 const auto total_size = elements.size();
24 const auto step =
25 static_cast<int>(std::ceil(static_cast<float>(total_size) / static_cast<float>(num_of_partitions)));
26 if (step * partition_num >= total_size)
27 {
28 return {};
29 }
30 const auto span_size = step * (partition_num + 1) < total_size ? step : total_size - (step * partition_num);
31 return span<const T>{ &(elements.at(step * partition_num)), span_size };
32 }
33} // namespace
34
35namespace R3B::Neuland
36{
37 using json = nlohmann::ordered_json;
38 Application::Application(std::string_view name,
39 std::unique_ptr<FairRun> run,
40 std::reference_wrapper<Options> option)
41 : app_name_{ name }
42 , dump_json_filename_{ fmt::format("{}_{}", name, DEFAULT_JSON_FILENAME) }
43 , run_(std::move(run))
44 , option_{ option }
45 {
46 timer_.Start();
47 }
48
50 {
51 if (is_inited_)
52 {
53 R3BLOG(info, "Writting all parameters to files");
54 run_->GetRuntimeDb()->writeContainers();
55 run_->GetSink()->Close();
56 }
57
58 timer_.Stop();
59
60 if (is_inited_)
61 {
62 if (is_failed_)
63 {
64 fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
65 "\nNeuland Application finished with a failure!\n\n");
66 }
67 else
68 {
69 fmt::print(fmt::emphasis::bold | fg(fmt::color::green),
70 "\nNeuland Application finished successfully!\n\n");
71 }
72 fmt::print("Real time: {}s, cpu time: {}s\n", timer_.RealTime(), timer_.CpuTime());
73 }
74 }
75
77 {
78 R3BLOG(info, "Initializaing application ...");
79 is_inited_ = true;
80 FairLogger::GetLogger()->SetLogScreenLevel(option_.get().log_level.c_str());
81 add_inout_files();
82 add_inout_pars();
83 pre_init(run_.get());
84 run_->Init();
85 post_init(run_.get());
86 R3BLOG(info, "Application is initialized.");
87 }
88
89 void Application::setup_options(CLI::App& program_options)
90 {
91 setup_common_options(program_options);
92 setup_application_options(program_options);
93 }
94
95 void Application::setup_common_options(CLI::App& program_options)
96 {
97 auto dump_config_callback = [this](const std::string& filename)
98 {
99 is_dump_ = true;
100 dump_json_filename_ = filename;
101 };
102
103 auto use_config_callback = [this](const std::vector<std::string>& filename)
104 {
105 if (not is_already_parsed_)
106 {
107 ParseApplicationOption(filename);
108 is_already_parsed_ = true;
109 }
110 };
111
112 auto& options = option_.get();
113 program_options
114 .add_option_function<std::vector<std::string>>(
115 "-c, --config-file", use_config_callback, "Set the json config file")
116 ->default_val(fmt::format("{}_{}", app_name_, DEFAULT_JSON_FILENAME))
117 ->run_callback_for_default()
118 ->trigger_on_parse();
119 program_options.add_flag("--print-config", has_print_default_options_, "Print default option value");
120 program_options
121 .add_option_function<std::string>("--dump-config", dump_config_callback, "Dump the config into a json file")
122 ->default_val(dump_json_filename_)
123 ->run_callback_for_default()
124 ->expected(0, 1);
125 program_options.add_option("-v, --verbose", options.log_level, "Set the verbose level");
126 program_options.add_option("-n, --event-num", options.event_num, "Set the event number")->capture_default_str();
127 program_options.add_option("--run-id", options.run_id, "Set the run id")->capture_default_str();
128
129 program_options.add_option("-i, --input-file", options.input.data, "Set the input filenames (regex)")
130 ->capture_default_str()
131 ->group("Input options");
132 program_options
133 .add_option("--input-tree-file",
134 options.input.tree_data,
135 "Set the input filenames (regex) containing only root tree")
136 ->group("Input options");
137 program_options.add_option("--par-in", options.input.par, "Set the filename of the input parameter root file")
138 ->capture_default_str()
139 ->group("Input options");
140 program_options
141 .add_option(
142 "--par-in-second", options.input.par_2, "Set the filename of the second input parameter root file")
143 ->group("Input options");
144
145 program_options.add_option("-o, --output-file", options.output.data, "Set the output filename")
146 ->capture_default_str()
147 ->group("Output options");
148 program_options
149 .add_option("--par-out", options.output.par, "Set the filename of the output parameter root file")
150 ->capture_default_str()
151 ->group("Output options");
152 }
153
154 void Application::add_inout_files()
155 {
156 const auto& option = option_.get();
157
158 // output files:
159 const auto output_name =
160 option.enable_mpi ? fmt::format("{}.{}", option.output.data, rank_num_) : option.output.data;
161 if (not option_.get().output.data.empty())
162 {
163 // check if path if relative or full
164 auto file_path = option.output.working_dir.empty()
165 ? fs::path{ output_name }
166 : fs::path{ option.output.working_dir } / fs::path{ output_name };
167 auto file_sink = std::make_unique<FairRootFileSink>(file_path.c_str());
168 run_->SetSink(file_sink.release());
169 }
170
171 // input files:
172 auto file_source = std::make_unique<R3BFileSource2>();
173 if (option_.get().run_id >= 0)
174 {
175 file_source->SetInitRunID(option_.get().run_id);
176 run_->SetRunId(option_.get().run_id);
177 R3BLOG(info, fmt::format("Filesource2: Set to run id {}", option_.get().run_id));
178 }
179 add_input_filename(file_source.get());
180 if (not file_source->IsEmpty())
181 {
182 run_->SetSource(file_source.release());
183 }
184 }
185
186 void Application::add_inout_pars()
187 {
188 auto file_path = fs::path{};
189 const auto& input_option = option_.get().input;
190 const auto& output_option = option_.get().output;
191 const auto& input_wd = input_option.working_dir;
192 const auto& output_wd = output_option.working_dir;
193
194 if (not input_option.par.empty())
195 {
196 file_path =
197 input_wd.empty() ? fs::path{ input_option.par } : fs::path{ input_wd } / fs::path{ input_option.par };
198 auto fileio = std::make_unique<FairParRootFileIo>();
199 R3BLOG(info, fmt::format("Input first parameter file is {:?}", file_path.string()));
200 fileio->open(file_path.c_str(), "READ");
201 run_->GetRuntimeDb()->setFirstInput(fileio.release());
202 }
203
204 if (not input_option.par_2.empty())
205 {
206 file_path = input_wd.empty() ? fs::path{ input_option.par_2 }
207 : fs::path{ input_wd } / fs::path{ input_option.par_2 };
208 auto fileio = std::make_unique<FairParRootFileIo>();
209 R3BLOG(info, fmt::format("Input second parameter file is {:?}", file_path.string()));
210 fileio->open(file_path.c_str(), "READ");
211 run_->GetRuntimeDb()->setSecondInput(fileio.release());
212 }
213
214 if (not output_option.par.empty())
215 {
216 const auto& option = option_.get();
217 const auto output_name =
218 option.enable_mpi ? fmt::format("{}.{}", output_option.par, rank_num_) : output_option.par;
219 file_path = output_wd.empty() ? fs::path{ output_name } : fs::path{ output_wd } / fs::path{ output_name };
220 R3BLOG(info, fmt::format("Ouptut parameter file is {:?}", file_path.string()));
221 auto fileio = std::make_unique<FairParRootFileIo>(true);
222 fileio->open(file_path.c_str(), "RECREATE");
223 auto* rtdb = run_->GetRuntimeDb();
224 rtdb->setOutput(fileio.release());
225 }
226 }
227
229 {
230 auto max_event = option_.get().event_num;
231 max_event = max_event > 0 ? max_event : 0;
232 if (max_event > 0)
233 {
234 R3BLOG(info, fmt::format("{} is set to run with {} events", app_name_, max_event));
235 }
236 run_action(run_.get(), max_event);
237 }
238
239 void Application::run_action(FairRun* run, int num_of_events) { run->Run(0, num_of_events); }
240
241 void Application::add_input_filename(R3BFileSource2* filesource)
242 {
243 extract_input_files();
244 auto input_span = option_.get().enable_mpi ? get_partition_from(input_files_, num_of_procs_, rank_num_)
245 : span{ input_files_ };
246 for (const auto& [filename, is_tree] : input_span)
247 {
248 filesource->AddFile(filename, is_tree);
249 }
250 }
251
252 void Application::extract_input_files()
253 {
254 auto file_path = fs::path{};
255 const auto& working_dir = option_.get().input.working_dir;
256 for (const auto& filename : option_.get().input.data)
257 {
258 // check if path if relative or full
259 file_path = working_dir.empty() ? fs::path{ filename } : fs::path{ working_dir } / fs::path{ filename };
260 auto fairroot_input_files = R3B::GetFilesFromRegex(file_path.string());
261 for (const auto& fairroot_input_file : fairroot_input_files)
262 {
263 input_files_.emplace_back(fairroot_input_file, false);
264 }
265 }
266 for (const auto& filename : option_.get().input.tree_data)
267 {
268 auto tree_input_files = R3B::GetFilesFromRegex(filename);
269 for (const auto& tree_input_file : tree_input_files)
270 {
271 input_files_.emplace_back(tree_input_file, true);
272 }
273 }
274 }
275} // namespace R3B::Neuland
#define R3BLOG(severity, x)
Definition R3BLogger.h:35
virtual void run_action(FairRun *run, int num_of_events)
virtual void pre_init(FairRun *run)=0
Application(std::string_view name, std::unique_ptr< FairRun > run, std::reference_wrapper< Options > option)
void setup_options(CLI::App &program_options)
virtual void post_init(FairRun *run)
virtual void setup_application_options(CLI::App &program_options)
void setup_common_options(CLIAPP &program_options, OptionType &options)
virtual void ParseApplicationOption(const std::vector< std::string > &filename)=0
void AddFile(std::string file_name, bool is_tree_file=false)
Simulation of NeuLAND Bar/Paddle.
const auto DEFAULT_JSON_FILENAME
nlohmann::ordered_json json
auto GetFilesFromRegex(std::string_view filename_regex) -> std::vector< std::string >
Definition R3BShared.h:197