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 <filesystem>
19 #include <memory>
20 #include <ranges>
21 #include <source_location>
22 #include <string>
23 #include <vector>
24 
25 namespace Darwin::Tools {
26 
27 enum BranchMode {
28  mandatory ,
30 };
31 
32 using enum BranchMode;
33 
55 class Flow {
56 
57  int steering;
58 
59  std::unique_ptr<ChainSlice> tIn;
60  std::shared_ptr<TFile> fOut;
61  std::unique_ptr<TTree> tOut;
62 
63  std::map<std::string, std::any> branches;
64 
67  template<typename T>
68  std::shared_ptr<T*> GetBranch (const std::string& name) const
69  try {
70  using namespace std;
71  if (steering & verbose)
72  cout << "Flow: retrieving an existing branch" << endl;
73  auto& branch = branches.at(name);
74  return any_cast<shared_ptr<T*>>(branch);
75  }
76  catch (const std::bad_any_cast& e) {
77  BOOST_THROW_EXCEPTION(e);
78  }
79 
80  template<typename T> T * NoBranch (const std::string& name, BranchMode mode)
81  {
82  if (mode == facultative)
83  return nullptr;
84 
85  namespace DE = Darwin::Exceptions;
86  std::string what = name + " branch could not be found";
87  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
88  }
89 
90 public:
93  inline std::string DumpActiveBranches () const
94  {
95  auto keys = branches | std::views::keys;
96  return std::accumulate(keys.begin(), keys.end(), std::string(),
97  [](const std::string& str, const std::string& branch_name) {
98  return str + ' ' + branch_name;
99  });
100  }
101 
106  Flow (int = none);
107 
112  ~Flow ();
113 
117  (std::vector<std::filesystem::path> = {},
118  const Slice = {1, 0},
119  const std::string& = "events");
120 
134  TTree * GetOutputTree (std::shared_ptr<TFile> = {},
135  const std::source_location = std::source_location::current());
136 
139  TTree * GetOutputTree (const std::filesystem::path&,
140  const std::source_location = std::source_location::current());
141 
144  inline void SetOutputFile (std::shared_ptr<TFile> fOut) { this->fOut = fOut; }
145 
148  inline TFile * GetOutputFile () { return fOut.get(); }
149 
152  std::pair<TFile *, TTree *> GetOutput (const std::filesystem::path&,
153  const std::source_location = std::source_location::current());
154 
165  template<typename T>
167  const std::string& name,
168  BranchMode mode = mandatory)
169  {
170  using namespace std;
171 
172  if (!tIn)
173  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
174  "be called before declaring a read-only branch") );
175 
176  namespace DE = Darwin::Exceptions;
177 
178  shared_ptr<T*> t;
179 
180  if (branches.contains(name))
181  t = GetBranch<T>(name);
182  else {
183  t = make_shared<T*>();
184  if (steering & verbose)
185  cout << "Flow: loading branch `" << name << "`" << endl;
186 
187  if (tIn->GetBranch(name.c_str()) == nullptr)
188  return NoBranch<T>(name, mode);
189 
190  int err = tIn->SetBranchAddress(name.c_str(), t.get());
191  if (steering & verbose)
192  cout << "Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
193  << " (check `TTree::ESetBranchAddressStatus` for the meaning)."
194  << endl;
195  if (err < 0) {
196  string what = "`"s + name + "` branch could not be set. "s;
197  if (mode == facultative) {
198  if (steering & verbose)
199  cout << orange << "Flow: " << what << def << endl;
200  return nullptr;
201  }
202  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
203  }
204  branches.insert({name, t});
205  }
206  return *t;
207  }
208 
217  template<typename T>
218  T * GetBranchWriteOnly (const std::string& name)
219  {
220  using namespace std;
221 
222  if (!tOut)
223  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
224  "be called before") );
225 
226  shared_ptr<T*> t;
227 
228  if (branches.contains(name))
229  t = GetBranch<T>(name);
230  else
231  t = make_shared<T*>();
232 
233  if (steering & verbose)
234  cout << "Flow: setting up new branch for `" << name << "`" << endl;
235  if (tOut->Branch(name.c_str(), t.get()) == nullptr) {
236  namespace DE = Darwin::Exceptions;
237  string what = name + " branch could not be set up";
238  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tOut) );
239  }
240 
241  if (!branches.contains(name))
242  branches.insert({name, t});
243  return *t;
244  }
245 
254  template<typename T>
255  T * GetBranchReadWrite (const std::string& name,
256  BranchMode mode = mandatory)
257  {
258  using namespace std;
259 
260  if (!tIn)
261  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
262  "be called before declaring a read-write branch") );
263 
264  if (!tOut)
265  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
266  "be called before declaring a read-write branch") );
267 
268  shared_ptr<T*> t;
269 
270  if (branches.contains(name))
271  t = GetBranch<T>(name);
272  else {
273  if (GetBranchReadOnly<T>(name, mode) == nullptr)
274  return NoBranch<T>(name, mode);
275  if (steering & Friend)
276  GetBranchWriteOnly<T>(name);
277  t = any_cast<shared_ptr<T*>>(branches[name]);
278  }
279  return *t;
280  }
281 };
282 
283 } // namespace Darwin::Tools
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:63
Darwin::Tools::mandatory
@ mandatory
mounting branch is mandatory
Definition: Flow.h:28
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
Darwin::Tools::Flow::GetBranchWriteOnly
T * GetBranchWriteOnly(const std::string &name)
Wrapper to initialise write-only branches.
Definition: Flow.h:218
Darwin::Tools::Flow::tOut
std::unique_ptr< TTree > tOut
output tree
Definition: Flow.h:61
Darwin::Tools::Flow::fOut
std::shared_ptr< TFile > fOut
output ROOT file
Definition: Flow.h:60
Darwin::Tools::BranchMode
BranchMode
Definition: Flow.h:27
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:255
Looper.h
Darwin::Tools::Flow::NoBranch
T * NoBranch(const std::string &name, BranchMode mode)
Definition: Flow.h:80
Darwin::Tools::Flow::GetOutputTree
TTree * GetOutputTree(const std::filesystem::path &, const std::source_location=std::source_location::current())
Create an output TTree object.
Darwin::Tools::Slice
std::pair< unsigned, unsigned > Slice
current slice (>=0) / total number of slices (>0)
Definition: Looper.h:20
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
FriendUtils.h
Darwin::Tools::Flow::DumpActiveBranches
std::string DumpActiveBranches() const
Returns a list of all active branches, formatted as a string.
Definition: Flow.h:93
Darwin::Tools::Flow::Flow
Flow(int=none)
Constructor.
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:68
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:166
Darwin::Tools::Flow::GetInputTree
ChainSlice * GetInputTree(std::vector< std::filesystem::path >={}, const Slice={1, 0}, const std::string &="events")
Load chain from a list of files.
Darwin::Tools::Flow::steering
int steering
steering from Options, mostly useful for friends
Definition: Flow.h:57
Darwin::Tools::Flow::~Flow
~Flow()
Destructor.
Darwin::Tools::Flow::tIn
std::unique_ptr< ChainSlice > tIn
input chain
Definition: Flow.h:59
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:144
Darwin::Tools::Flow::GetOutputFile
TFile * GetOutputFile()
Get a raw pointer to the output file.
Definition: Flow.h:148
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:29