1 #ifndef CROMBIE_CONFIGREADER_H 2 #define CROMBIE_CONFIGREADER_H 37 std::string dirclean (
const std::string&
dir) {
38 if (dir.size() and dir.back() !=
'/')
64 std::string dirname {};
66 unsigned long size {};
80 const std::string& entry,
81 const std::string& cut,
83 : treename{treename}, legendentry{entry}, cut{cut}, style{style} {
84 std::replace(legendentry.begin(), legendentry.end(),
'_',
' ');
88 const std::string&
cut;
101 : name{getname(line)}, xs{getxs(line)}, type{type}, processes{processes} {
102 Debug::Debug(__PRETTY_FUNCTION__, line, name, xs, processes.size());
118 static std::string getname(
const std::string& line);
121 static double getxs(
const std::string& line) {
122 auto begin = line.find(
'{') + 1;
123 auto val = line.substr(begin, line.find(
'}') - begin);
124 return val.size() ? std::stod(val) : 0;
136 template<
typename M>
using MapFunc = std::function<M(const FileInfo&)>;
149 template<
typename R,
typename M>
using MergeFunc = std::function<R(const ToMerge<M>&)>;
159 FileConfig(
const std::string& inputdir,
const bool onedir =
true);
169 template <
typename M,
typename R>
173 const std::vector<DirectoryInfo>&
get_dirs ()
const {
return dirinfos; }
179 const bool has_mc ()
const {
return _has_mc; }
187 bool _has_mc {
false};
188 bool _has_data {
false};
198 std::ifstream
input {config};
207 : inputdir{onedir ?
"" : dirclean(inputdir)} {
217 if (
dir.name == dirname)
220 throw std::logic_error{dirname +
" does not seem to be a valid directory name"};
225 std::string
dir {line.substr(0, line.find(
' '))};
227 return (
dir.substr(
dir.size() - 5, 5) ==
".root") ?
dir : dirclean(
dir);
234 for (
auto& proc : processes)
235 cuts.push_back(proc.cut);
237 if (name.back() !=
'/')
238 files.push_back({type, name, name, cuts});
242 if (
file.find(
".root") != std::string::npos)
243 files.push_back({type, name, name + file, cuts});
249 throw std::runtime_error{
"Path " + name +
" does not exist"};
256 std::vector<Process> current_procs {{
"data_obs",
"Data",
"1.0", 1}};
274 if (default_lines.find(line) != default_lines.end()) {
275 default_type = default_lines.at(line);
279 if (line.find(
'{') == std::string::npos) {
282 current_procs.clear();
283 current_type = default_type;
288 if (tokens.size() > 1) {
290 cut = tokens.size() == 4 ? tokens[2] :
"1.0";
291 style = std::stoi(tokens.back());
293 current_procs.push_back({tokens[0], entry, cut, style});
301 config.
dirinfos.push_back({config.
inputdir + line, current_type, current_procs});
314 template <
typename M,
typename R>
316 unsigned nthreads = std::stoi(
Misc::env(
"nthreads",
"1"));
318 std::priority_queue<FileInfo> queue;
319 for (
const auto& dirinfo :
dirinfos) {
320 for (
const auto& fileinfo : dirinfo.files)
321 queue.push(fileinfo);
328 std::vector<std::thread> threads;
329 nthreads = std::max(nthreads, 1u);
331 auto total = queue.size();
332 auto divisor = total/100 + 1;
333 auto progress = total/divisor;
335 std::cout <<
"Using " << nthreads <<
" threads to run over " << total <<
" files" << std::endl;
339 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
341 for (
unsigned i = 0; i < nthreads; ++i) {
342 threads.push_back(std::thread([&] () {
348 running = !queue.empty();
351 auto done = total - queue.size();
352 if (done % divisor == 0) {
361 auto fileoutput =
map(info);
363 outputs[info.
dirname].push_back(std::move(fileoutput));
366 catch (
const std::exception& e) {
367 std::cerr <<
"Cannot run over file " << info.
name << std::endl;
368 std::cerr << e.what() << std::endl;
375 for (
auto& thread : threads)
379 std::cout << std::endl;
381 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
383 std::cout <<
"Ran over " << total <<
" files in " 384 << std::chrono::duration_cast<std::chrono::seconds>(end - start).
count()
385 <<
" seconds" << std::endl;
387 return reduce(outputs);