DAS  3.0
Das Analysis System
Flow.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPLv3-or-later
2 //
3 // SPDX-FileCopyrightText: Patrick L.S. Connor <patrick.connor@desy.de>
4 // SPDX-FileCopyrightText: Louis Moureaux <louis.moureaux@cern.ch>
5 
6 #pragma once
7 
8 #include "exceptions.h"
9 #include "FriendUtils.h"
10 #include "Looper.h"
11 
12 #include <TChain.h>
13 #include <TFile.h>
14 #include <TH1.h>
15 #include <TTree.h>
16 
17 #include <any>
18 #include <array>
19 #include <filesystem>
20 #include <map>
21 #include <memory>
22 #include <ranges>
23 #include <source_location>
24 #include <string>
25 #include <vector>
26 
27 namespace Darwin::Tools {
28 
29 enum BranchMode {
30  mandatory ,
32 };
33 
34 using enum BranchMode;
35 
36 using Slice = std::pair<int, int>;
37 
40 inline std::ostream& operator<< (std::ostream& Stream, const Darwin::Tools::Slice& slice)
41 {
42  return Stream << slice.second << '/' << slice.first;
43 }
44 
78 class Flow {
79 
80  int steering;
81 
82  std::vector<std::filesystem::path> inputs;
83 
84  std::unique_ptr<ChainSlice> tIn;
85  std::shared_ptr<TFile> fOut;
86  std::unique_ptr<TTree> tOut;
87 
88  std::map<std::string, std::any> branches;
89 
92  template<typename T>
93  std::shared_ptr<T*> GetBranch (const std::string& name) const
94  try {
95  using namespace std;
96  if (steering & verbose)
97  cout << "Flow: retrieving an existing branch" << endl;
98  auto& branch = branches.at(name);
99  return any_cast<shared_ptr<T*>>(branch);
100  }
101  catch (const std::bad_any_cast& e) {
102  BOOST_THROW_EXCEPTION(e);
103  }
104 
105  template<typename T> T * NoBranch (const std::string& name, BranchMode mode)
106  {
107  if (mode == facultative)
108  return nullptr;
109 
110  namespace DE = Darwin::Exceptions;
111  std::string what = name + " branch could not be found";
112  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
113  }
114 
115 public:
118  inline std::string DumpActiveBranches () const
119  {
120  auto keys = branches | std::views::keys;
121  return std::accumulate(keys.begin(), keys.end(), std::string(),
122  [](const std::string& str, const std::string& branch_name) {
123  return str + ' ' + branch_name;
124  });
125  }
126 
131  Flow (int = none,
132  const std::vector<std::filesystem::path>& = {}
133  );
134 
139  ~Flow ();
140 
144  (const Slice = {1, 0},
145  const std::string& = "events");
146 
152  template<typename THX = TH1, size_t N>
153  std::array<std::unique_ptr<THX>, N> GetInputHists
154  (const std::array<std::string, N>& names = {}
155  )
156  {
157  using namespace std;
158  namespace fs = filesystem;
159 
160  if (inputs.size() == 0)
161  BOOST_THROW_EXCEPTION( runtime_error("Empty input list") );
162 
163  array<unique_ptr<THX>, N> sums;
164  for (const fs::path& input: inputs) {
165  auto fIn = make_unique<TFile>(input.c_str(), "READ");
166  for (size_t i = 0; i < N; ++i) {
167  const string& name = names[i];
168  unique_ptr<THX> h(fIn->Get<THX>(name.c_str()));
169  if (!h) {
170  namespace DE = Darwin::Exceptions;
171  BOOST_THROW_EXCEPTION(
172  DE::BadInput(Form("`%s` cannot be found in (one of) the "
173  " file(s).", name.c_str()), fIn));
174  }
175  if (sums[i])
176  sums[i]->Add(h.get());
177  else {
178  sums[i] = std::move(h);
179  sums[i]->SetDirectory(nullptr);
180  }
181  }
182  }
183  return sums;
184  }
185 
191  template<typename THX = TH1, typename... Args>
192  auto GetInputHists (const Args... args)
193  {
194  constexpr const size_t N = sizeof...(args);
195  std::array<std::string, N> names {{ args... }};
196  return GetInputHists<THX, N>(names);
197  }
198 
203  template<typename THX = TH1>
204  std::unique_ptr<THX> GetInputHist
205  (const std::string& name)
206  {
207  auto hists = GetInputHists<THX,1>({name});
208  THX * hist = hists.front().release();
209  return std::unique_ptr<THX>(hist);
210  }
211 
225  TTree * GetOutputTree (std::shared_ptr<TFile> = {},
226  const std::source_location = std::source_location::current());
227 
230  TTree * GetOutputTree (const std::filesystem::path&,
231  const std::source_location = std::source_location::current());
232 
235  inline void SetOutputFile (std::shared_ptr<TFile> fOut) { this->fOut = fOut; }
236 
239  inline TFile * GetOutputFile () { return fOut.get(); }
240 
243  std::pair<TFile *, TTree *> GetOutput (const std::filesystem::path&,
244  const std::source_location = std::source_location::current());
245 
256  template<typename T>
258  const std::string& name,
259  BranchMode mode = mandatory)
260  {
261  using namespace std;
262 
263  if (!tIn)
264  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
265  "be called before declaring a read-only branch") );
266 
267  namespace DE = Darwin::Exceptions;
268 
269  shared_ptr<T*> t;
270 
271  if (branches.contains(name))
272  t = GetBranch<T>(name);
273  else {
274  t = make_shared<T*>();
275  if (steering & verbose)
276  cout << "Flow: loading branch `" << name << "`" << endl;
277 
278  if (tIn->GetBranch(name.c_str()) == nullptr)
279  return NoBranch<T>(name, mode);
280 
281  int err = tIn->SetBranchAddress(name.c_str(), t.get());
282  if (steering & verbose)
283  cout << "Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
284  << " (check `TTree::ESetBranchAddressStatus` for the meaning)."
285  << endl;
286  if (err < 0) {
287  string what = "`"s + name + "` branch could not be set. "s;
288  if (mode == facultative) {
289  if (steering & verbose)
290  cout << orange << "Flow: " << what << def << endl;
291  return nullptr;
292  }
293  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
294  }
295  branches.insert({name, t});
296  }
297  return *t;
298  }
299 
308  template<typename T>
309  T * GetBranchWriteOnly (const std::string& name)
310  {
311  using namespace std;
312 
313  if (!tOut)
314  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
315  "be called before") );
316 
317  shared_ptr<T*> t;
318 
319  if (branches.contains(name))
320  t = GetBranch<T>(name);
321  else
322  t = make_shared<T*>();
323 
324  if (steering & verbose)
325  cout << "Flow: setting up new branch for `" << name << "`" << endl;
326  if (tOut->Branch(name.c_str(), t.get()) == nullptr) {
327  namespace DE = Darwin::Exceptions;
328  string what = name + " branch could not be set up";
329  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tOut) );
330  }
331 
332  if (!branches.contains(name))
333  branches.insert({name, t});
334  return *t;
335  }
336 
345  template<typename T>
346  T * GetBranchReadWrite (const std::string& name,
347  BranchMode mode = mandatory)
348  {
349  using namespace std;
350 
351  if (!tIn)
352  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
353  "be called before declaring a read-write branch") );
354 
355  if (!tOut)
356  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
357  "be called before declaring a read-write branch") );
358 
359  shared_ptr<T*> t;
360 
361  if (branches.contains(name))
362  t = GetBranch<T>(name);
363  else {
364  if (GetBranchReadOnly<T>(name, mode) == nullptr)
365  return NoBranch<T>(name, mode);
366  if (steering & Friend)
367  GetBranchWriteOnly<T>(name);
368  t = any_cast<shared_ptr<T*>>(branches[name]);
369  }
370  return *t;
371  }
372 };
373 
374 } // namespace Darwin::Tools
375 
376 using Darwin::Tools::operator<<;
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.name
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
Darwin::Tools::Flow::branches
std::map< std::string, std::any > branches
pointers to mounted branches
Definition: Flow.h:88
Darwin::Tools::mandatory
@ mandatory
mounting branch is mandatory
Definition: Flow.h:30
exceptions.h
Darwin::Tools::Flow::GetOutputTree
TTree * GetOutputTree(std::shared_ptr< TFile >={}, const std::source_location=std::source_location::current())
Create an output TTree object.
Step::def
static const char * def
Definition: Step.h:36
Darwin::Tools::Friend
@ Friend
activate -F to only fill the new branches
Definition: Options.h:28
Ntupliser_cfg.args
args
Definition: Ntupliser_cfg.py:11
Darwin::Tools::Flow::GetBranchWriteOnly
T * GetBranchWriteOnly(const std::string &name)
Wrapper to initialise write-only branches.
Definition: Flow.h:309
Darwin::Tools::Slice
std::pair< int, int > Slice
total number of slices (>0) / current slice index (>0)
Definition: Flow.h:36
Darwin::Tools::Flow::tOut
std::unique_ptr< TTree > tOut
output tree
Definition: Flow.h:86
Darwin::Tools::Flow::GetInputTree
ChainSlice * GetInputTree(const Slice={1, 0}, const std::string &="events")
Load chain from a list of files.
Darwin::Tools::Flow::fOut
std::shared_ptr< TFile > fOut
output ROOT file
Definition: Flow.h:85
Darwin::Tools::BranchMode
BranchMode
Definition: Flow.h:29
Darwin::Tools::none
@ none
default (for simple executables)
Definition: Options.h:24
Darwin::Tools::Flow::GetBranchReadWrite
T * GetBranchReadWrite(const std::string &name, BranchMode mode=mandatory)
Wrapper to initialise read-write branches.
Definition: Flow.h:346
Darwin::Tools::Flow::GetInputHists
std::array< std::unique_ptr< THX >, N > GetInputHists(const std::array< std::string, N > &names={})
Load ROOT histograms from a list of files.
Definition: Flow.h:154
Darwin::Tools::Flow::GetInputHists
auto GetInputHists(const Args... args)
Load ROOT histograms from a list of files.
Definition: Flow.h:192
Darwin::Tools::Flow::Flow
Flow(int=none, const std::vector< std::filesystem::path > &={})
Constructor.
Looper.h
Darwin::Tools::Flow::NoBranch
T * NoBranch(const std::string &name, BranchMode mode)
Definition: Flow.h:105
Darwin::Tools::Flow::GetOutputTree
TTree * GetOutputTree(const std::filesystem::path &, const std::source_location=std::source_location::current())
Create an output TTree object.
Darwin::Exceptions
Handling of exceptions.
Definition: darwin.h:36
Darwin::Tools::verbose
@ verbose
bit for debug mode (-v is always available)
Definition: Options.h:30
Darwin::Tools::Flow::GetOutput
std::pair< TFile *, TTree * > GetOutput(const std::filesystem::path &, const std::source_location=std::source_location::current())
Get both the output file and the output tree in one go.
orange
static const char * orange
Definition: colours.h:6
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.input
input
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:35
Darwin::Tools::operator<<
std::ostream & operator<<(std::ostream &Stream, const Darwin::Tools::Slice &slice)
Prints the current slice and the total number of slices.
Definition: Flow.h:40
FriendUtils.h
Darwin::Tools::Flow::DumpActiveBranches
std::string DumpActiveBranches() const
Returns a list of all active branches, formatted as a string.
Definition: Flow.h:118
Darwin::Tools::Flow::inputs
std::vector< std::filesystem::path > inputs
ROOT files or directories.
Definition: Flow.h:82
Darwin::Tools
Classes and functions related to the framework.
Definition: Dict_rdict.cxx:990
Darwin::Tools::Flow::GetBranch
std::shared_ptr< T * > GetBranch(const std::string &name) const
Get address of branch address in a shared pointer.
Definition: Flow.h:93
Darwin::Tools::ChainSlice
Wrapper around TChain that restricts available entries to a subset.
Definition: FriendUtils.h:35
Darwin::Tools::Flow::GetBranchReadOnly
T * GetBranchReadOnly(const std::string &name, BranchMode mode=mandatory)
Wrapper to initialise read-only branches.
Definition: Flow.h:257
Darwin::Tools::Flow::steering
int steering
steering from Options, mostly useful for friends
Definition: Flow.h:80
Darwin::Tools::Flow::~Flow
~Flow()
Destructor.
Darwin::Tools::Flow::tIn
std::unique_ptr< ChainSlice > tIn
input chain
Definition: Flow.h:84
Darwin::Tools::Flow::GetInputHist
std::unique_ptr< THX > GetInputHist(const std::string &name)
Load a single ROOT histogram from a list of files.
Definition: Flow.h:205
Darwin::Tools::Flow::SetOutputFile
void SetOutputFile(std::shared_ptr< TFile > fOut)
Set the output file where the output TTree should be saved.
Definition: Flow.h:235
Darwin::Tools::Flow::GetOutputFile
TFile * GetOutputFile()
Get a raw pointer to the output file.
Definition: Flow.h:239
Darwin::Exceptions::BadInput
Generic exception for ill-defined input (before the event loop).
Definition: exceptions.h:83
Darwin::Tools::facultative
@ facultative
mounting branch is facultative
Definition: Flow.h:31