DAS  3.0
Das Analysis System
Flow

Description

User-friendly handling of input and output n-tuples.

A flow consists of input and outputs path to n-tuples and of a slice:

auto tIn = flow.GetInputTree(slice);
auto tOut = flow.GetOutputTree(output);
auto fOut = flow.GetOutputFile();

The last two lines can be condensed as follows:

auto [fOut, tOut] = flow.GetOutput(output);

The steering is use for the verbosity and the friendship. Setting up branches reduces to the following:

auto recEvent = flow.GetBranchReadOnly<RecEvent>("recEvent");
auto recJets = flow.GetBranchReadWrite<vector<RecJet>>("recJets");
auto recDijet = flow.GetBranchWriteOnly<RecDijet>("recDijet");

Furthermore, as it is frequent to produce histograms along the n-tuple (e.g. control plots), a flow allows to sum on the fly a histogram:

auto hIn = flow.GetInputHist<TH2>("h");
auto hIns = flow.GetInputHists("h1", "h2"); // default is TH1
Note
A one-liner is also possible:

#include <Flow.h>

+ Collaboration diagram for Flow:

Public Member Functions

std::string DumpActiveBranches () const
 
 Flow (int=none, const std::vector< std::filesystem::path > &={})
 
 ~Flow ()
 
ChainSliceGetInputTree (const Slice={1, 0}, const std::string &="events")
 
template<typename THX = TH1, size_t N>
std::array< std::unique_ptr< THX >, N > GetInputHists (const std::array< std::string, N > &names={})
 
template<typename THX = TH1, typename... Args>
auto GetInputHists (const Args... args)
 
template<typename THX = TH1>
std::unique_ptr< THX > GetInputHist (const std::string &name)
 
TTree * GetOutputTree (std::shared_ptr< TFile >={}, const std::source_location=std::source_location::current())
 
TTree * GetOutputTree (const std::filesystem::path &, const std::source_location=std::source_location::current())
 
void SetOutputFile (std::shared_ptr< TFile > fOut)
 
TFile * GetOutputFile ()
 
std::pair< TFile *, TTree * > GetOutput (const std::filesystem::path &, const std::source_location=std::source_location::current())
 
template<typename T >
T * GetBranchReadOnly (const std::string &name, BranchMode mode=mandatory)
 
template<typename T >
T * GetBranchWriteOnly (const std::string &name)
 
template<typename T >
T * GetBranchReadWrite (const std::string &name, BranchMode mode=mandatory)
 
std::string DumpActiveBranches () const
 
 Flow (int=none, const std::vector< std::filesystem::path > &={})
 
 ~Flow ()
 
ChainSliceGetInputTree (const Slice={1, 0}, const std::string &="events")
 
template<typename THX = TH1, size_t N>
std::array< std::unique_ptr< THX >, N > GetInputHists (const std::array< std::string, N > &names={})
 
template<typename THX = TH1, typename... Args>
auto GetInputHists (const Args... args)
 
template<typename THX = TH1>
std::unique_ptr< THX > GetInputHist (const std::string &name)
 
TTree * GetOutputTree (std::shared_ptr< TFile >={}, const std::source_location=std::source_location::current())
 
TTree * GetOutputTree (const std::filesystem::path &, const std::source_location=std::source_location::current())
 
void SetOutputFile (std::shared_ptr< TFile > fOut)
 
TFile * GetOutputFile ()
 
std::pair< TFile *, TTree * > GetOutput (const std::filesystem::path &, const std::source_location=std::source_location::current())
 
template<typename T >
T * GetBranchReadOnly (const std::string &name, BranchMode mode=mandatory)
 
template<typename T >
T * GetBranchWriteOnly (const std::string &name)
 
template<typename T >
T * GetBranchReadWrite (const std::string &name, BranchMode mode=mandatory)
 

Private Member Functions

template<typename T >
std::shared_ptr< T * > GetBranch (const std::string &name) const
 
template<typename T >
T * NoBranch (const std::string &name, BranchMode mode)
 
template<typename T >
std::shared_ptr< T * > GetBranch (const std::string &name) const
 
template<typename T >
T * NoBranch (const std::string &name, BranchMode mode)
 

Private Attributes

int steering
 
std::vector< std::filesystem::path > inputs
 
std::unique_ptr< ChainSlicetIn
 
std::shared_ptr< TFile > fOut
 
std::unique_ptr< TTree > tOut
 
std::map< std::string, std::any > branches
 

Constructor & Destructor Documentation

◆ Flow() [1/2]

Flow ( int  steering = none,
const std::vector< std::filesystem::path > &  short_inputs = {} 
)

Constructor.

Determines the command in which Flow is called.

Parameters
steeringsteering bitfield
short_inputsROOT files or directories
12  : steering(steering), inputs(GetROOTfiles(short_inputs))
13 {
14  if (short_inputs.size() > 0 && inputs.size() == 0)
15  BOOST_THROW_EXCEPTION(fs::filesystem_error("No input was found!",
16  make_error_code(errc::no_such_file_or_directory)));
17 }

◆ ~Flow() [1/2]

~Flow ( )

Destructor.

Saves the output tree (if declared) to the output file (if open).

20 {
21  if (fOut) {
22  if (tOut) {
23  if (steering & verbose)
24  cout << "Flow: saving output tree" << endl;
25 
26  fOut->cd();
27  tOut->Write();
28  }
29  else if (steering & verbose)
30  cout << "Flow: no output tree to save" << endl;
31  }
32  else if (tOut && (steering & verbose))
33  cout << "Flow: no file to save the output tree" << endl;
34 
35  if (tIn) tIn->ResetBranchAddresses();
36  if (tOut) tOut->ResetBranchAddresses();
37 }

◆ Flow() [2/2]

Flow ( int  = none,
const std::vector< std::filesystem::path > &  = {} 
)

Constructor.

Determines the command in which Flow is called.

◆ ~Flow() [2/2]

~Flow ( )

Destructor.

Saves the output tree (if declared) to the output file (if open).

Member Function Documentation

◆ DumpActiveBranches() [1/2]

std::string DumpActiveBranches ( ) const
inline

Returns a list of all active branches, formatted as a string.

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  }

◆ DumpActiveBranches() [2/2]

std::string DumpActiveBranches ( ) const
inline

Returns a list of all active branches, formatted as a string.

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  }

◆ GetBranch() [1/2]

std::shared_ptr<T*> GetBranch ( const std::string &  name) const
inlineprivate

Get address of branch address in a shared pointer.

< branch type < branch name

94  {
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  }

◆ GetBranch() [2/2]

std::shared_ptr<T*> GetBranch ( const std::string &  name) const
inlineprivate

Get address of branch address in a shared pointer.

< branch type < branch name

94  {
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  }

◆ GetBranchReadOnly() [1/2]

T* GetBranchReadOnly ( const std::string &  name,
BranchMode  mode = mandatory 
)
inline

Wrapper to initialise read-only branches.

The existence of the branch is checked before setting the address.

In practice, loading a branch whose contents should be accessed but not modified reduces to a single line:

auto recEvent = flow.GetBranchReadOnly<RecEvent>("recEvent");

< branch type (e.g. RecEvent, vector<RecJet>)

Parameters
namebranch name
modebranch may not exist
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  }

◆ GetBranchReadOnly() [2/2]

T* GetBranchReadOnly ( const std::string &  name,
BranchMode  mode = mandatory 
)
inline

Wrapper to initialise read-only branches.

The existence of the branch is checked before setting the address.

In practice, loading a branch whose contents should be accessed but not modified reduces to a single line:

auto recEvent = flow.GetBranchReadOnly<RecEvent>("recEvent");

< branch type (e.g. RecEvent, vector<RecJet>)

Parameters
namebranch name
modebranch may not exist
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  }

◆ GetBranchReadWrite() [1/2]

T* GetBranchReadWrite ( const std::string &  name,
BranchMode  mode = mandatory 
)
inline

Wrapper to initialise read-write branches.

In practice, setting up a branch to modify its contents reduces to a single line:

auto recEvent = flow.GetBranchReadWrite<RecEvent>("recEvent");

< branch type (e.g. RecEvent, vector<RecJet>)

Parameters
namebranch name
modebranch may not exist
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  }

◆ GetBranchReadWrite() [2/2]

T* GetBranchReadWrite ( const std::string &  name,
BranchMode  mode = mandatory 
)
inline

Wrapper to initialise read-write branches.

In practice, setting up a branch to modify its contents reduces to a single line:

auto recEvent = flow.GetBranchReadWrite<RecEvent>("recEvent");

< branch type (e.g. RecEvent, vector<RecJet>)

Parameters
namebranch name
modebranch may not exist
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  }

◆ GetBranchWriteOnly() [1/2]

T* GetBranchWriteOnly ( const std::string &  name)
inline

Wrapper to initialise write-only branches.

In practice, setting up a new branch in a n-tuple reduces to a single line:

auto recEvent = flow.GetBranchWriteOnly<RecEvent>("recEvent");

< branch type (e.g. RecEvent, vector<RecJet>)

Parameters
namebranch 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  }

◆ GetBranchWriteOnly() [2/2]

T* GetBranchWriteOnly ( const std::string &  name)
inline

Wrapper to initialise write-only branches.

In practice, setting up a new branch in a n-tuple reduces to a single line:

auto recEvent = flow.GetBranchWriteOnly<RecEvent>("recEvent");

< branch type (e.g. RecEvent, vector<RecJet>)

Parameters
namebranch 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  }

◆ GetInputHist() [1/2]

std::unique_ptr<THX> GetInputHist ( const std::string &  name)
inline

Load a single ROOT histogram from a list of files.

Todo:
Can we rather use a node handle to extract the unique pointer?
Parameters
nameinternal path to ROOT histogram
206  {
207  auto hists = GetInputHists<THX,1>({name});
208  THX * hist = hists.front().release();
209  return std::unique_ptr<THX>(hist);
210  }

◆ GetInputHist() [2/2]

std::unique_ptr<THX> GetInputHist ( const std::string &  name)
inline

Load a single ROOT histogram from a list of files.

Todo:
Can we rather use a node handle to extract the unique pointer?
Parameters
nameinternal path to ROOT histogram
206  {
207  auto hists = GetInputHists<THX,1>({name});
208  THX * hist = hists.front().release();
209  return std::unique_ptr<THX>(hist);
210  }

◆ GetInputHists() [1/4]

auto GetInputHists ( const Args...  args)
inline

Load ROOT histograms from a list of files.

In many cases, this spares from running an intermediate hadd (which can be very slow if there is a TTree in the same ROOT file).

193  {
194  constexpr const size_t N = sizeof...(args);
195  std::array<std::string, N> names {{ args... }};
196  return GetInputHists<THX, N>(names);
197  }

◆ GetInputHists() [2/4]

auto GetInputHists ( const Args...  args)
inline

Load ROOT histograms from a list of files.

In many cases, this spares from running an intermediate hadd (which can be very slow if there is a TTree in the same ROOT file).

193  {
194  constexpr const size_t N = sizeof...(args);
195  std::array<std::string, N> names {{ args... }};
196  return GetInputHists<THX, N>(names);
197  }

◆ GetInputHists() [3/4]

std::array<std::unique_ptr<THX>, N> GetInputHists ( const std::array< std::string, N > &  names = {})
inline

Load ROOT histograms from a list of files.

In many cases, this spares from running an intermediate hadd (which can be very slow if there is a TTree in the same ROOT file).

Parameters
namespath to ROOT histograms
154  {}
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  }

◆ GetInputHists() [4/4]

std::array<std::unique_ptr<THX>, N> GetInputHists ( const std::array< std::string, N > &  names = {})
inline

Load ROOT histograms from a list of files.

In many cases, this spares from running an intermediate hadd (which can be very slow if there is a TTree in the same ROOT file).

Parameters
namespath to ROOT histograms
154  {}
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  }

◆ GetInputTree() [1/2]

ChainSlice* GetInputTree ( const  Slice = {1, 0},
const std::string &  = "events" 
)

Load chain from a list of files.

internal path to TTree

Parameters
Slicenumber and index of slice

◆ GetInputTree() [2/2]

ChainSlice * GetInputTree ( const Slice  slice = {1, 0},
const std::string &  name = "events" 
)

Load chain from a list of files.

internal path to TTree

Parameters
slicenumber and index of slice
40 {
41  if (tIn) {
42  if (steering & verbose)
43  cout << "Flow: returning the existing input tree "
44  "(arguments are ignored)" << endl;
45  return tIn.get();
46  }
47 
48  if (inputs.size() == 0)
49  BOOST_THROW_EXCEPTION( runtime_error("Empty input list") );
50 
51  if (slice.first == 0 || slice.first <= slice.second)
52  BOOST_THROW_EXCEPTION(invalid_argument("The number of slices " + to_string(slice.first)
53  + " must be larger than the index of the current slice " + to_string(slice.second)));
54 
55  if (inputs.empty())
56  BOOST_THROW_EXCEPTION( invalid_argument("Empty list of input files") );
57 
58  tIn = make_unique<ChainSlice>(name.c_str());
59  for (const auto& input: inputs) {
60  int code = tIn->Add(input.c_str(), 0);
61  // "If nentries<=0 and wildcarding is not used,
62  // returns 1 if the file exists and contains the correct tree
63  // and 0 otherwise" (ROOT Doxygen)
64  if (code == 1) continue; // i.e. the tree was found successfully
65  tIn.reset();
66  auto fIn = make_unique<TFile>(input.c_str(), "READ");
67  BOOST_THROW_EXCEPTION(DE::BadInput("The tree cannot be "
68  "found in (one of) the input file(s).", fIn));
69  }
70  if (tIn->GetEntries() == 0) {
71  tIn.reset();
72  BOOST_THROW_EXCEPTION(invalid_argument("Empty trees in input!"));
73  }
74 
75  // Restrict the tIn to the entries for the slice
76  const auto entries = tIn->GetEntries();
77  tIn->SetBegin(entries * ((slice.second + 0.) / slice.first));
78  tIn->SetEnd(entries * ((slice.second + 1.) / slice.first));
79 
80  return tIn.get();
81 }

◆ GetOutput() [1/2]

std::pair< TFile *, TTree * > GetOutput ( const std::filesystem::path &  fOutName,
const std::source_location  location = std::source_location::current() 
)

Get both the output file and the output tree in one go.

upstream function

Parameters
fOutNameoutput directory
160 {
161  shared_ptr<TFile> fOut = Darwin::Tools::GetOutputFile(fOutName, location);
162  return {fOut.get(), GetOutputTree(fOut, location)};
163 }

◆ GetOutput() [2/2]

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.

upstream function

◆ GetOutputFile() [1/2]

TFile* GetOutputFile ( )
inline

Get a raw pointer to the output file.

239 { return fOut.get(); }

◆ GetOutputFile() [2/2]

TFile* GetOutputFile ( )
inline

Get a raw pointer to the output file.

239 { return fOut.get(); }

◆ GetOutputTree() [1/4]

TTree * GetOutputTree ( const std::filesystem::path &  fOutName,
const std::source_location  location = std::source_location::current() 
)

Create an output TTree object.

upstream function

Parameters
fOutNameoutput directory
153 {
154  shared_ptr<TFile> fOut = Darwin::Tools::GetOutputFile(fOutName, location);
155  return GetOutputTree(fOut, location);
156 }

◆ GetOutputTree() [2/4]

TTree* GetOutputTree ( const std::filesystem::path &  ,
const std::source_location  = std::source_location::current() 
)

Create an output TTree object.

upstream function

◆ GetOutputTree() [3/4]

TTree* GetOutputTree ( std::shared_ptr< TFile >  = {},
const std::source_location  = std::source_location::current() 
)

Create an output TTree object.

If the TTree already exists, either clone the input TChain or define the input TChain as a friend of the new TTree. Else a brand new TTree is stored.

The title of the TTree is used to store (retrieve) the name of the present (previous) command. When loading a tree with friends, one can refer to old versions of the branches by prefixing them with the corresponding command name.

Todo:
TTree::BuildIndex() to preserve the association despite skipped events?

upstream function

◆ GetOutputTree() [4/4]

TTree * GetOutputTree ( std::shared_ptr< TFile >  fOut = {},
const std::source_location  location = std::source_location::current() 
)

Create an output TTree object.

If the TTree already exists, either clone the input TChain or define the input TChain as a friend of the new TTree. Else a brand new TTree is stored.

The title of the TTree is used to store (retrieve) the name of the present (previous) command. When loading a tree with friends, one can refer to old versions of the branches by prefixing them with the corresponding command name.

Todo:
TTree::BuildIndex() to preserve the association despite skipped events?

upstream function

Note
We use the title to store the current command. When the present tree is used as a friend, this title will supsersede its name. Exceptions:
  • no title was found,
  • or the present name is the same as the last title (i.e. running twice the same command).
Parameters
fOutoutput file
85 {
86  if (tOut) {
87  if (steering & verbose)
88  cout << "Flow: returning the existing output tree" << endl;
89 
90  return tOut.get();
91  }
92 
93  if (fOut)
95 
96  const char * title = fs::path(location.file_name()).stem().c_str();
97 
98  if (!tIn) {
99  if (steering & verbose)
100  cout << "Flow: creating a new output tree" << endl;
101 
102  tOut = make_unique<TTree>("events", title);
103  }
104  else if (steering & Friend) {
110  if (steering & verbose)
111  cout << "Flow: creating a friend tree" << endl;
112 
113  tOut = make_unique<TTree>("events", title);
114  tIn->GetEntry(0); // necessary to load a(ny) TTree
115 
116  // find the name of the previous command
117  string lastFunc = tIn->GetTree()->GetTitle();
118  // -> this is supposed to store the name of the last command
119  if (lastFunc == "") {
120  cerr << orange << "Unable to identify the command used to "
121  "obtain the input from the title.\n" << def;
122  lastFunc = "previous";
123  }
124  else if (lastFunc == title) {
125  cerr << orange << "Running twice the same command in a row. "
126  "Adding `previous2` ahead of the title.\n" << def;
127  lastFunc = "previous2"s + title;
128  }
129 
130  // add friend
131  SlicedFriendElement::AddTo(tOut.get(), tIn.get(), lastFunc.c_str());
132 
133  // copy metainfo
134  TList * userinfo = tIn->GetTree()->GetUserInfo();
135  tOut->GetUserInfo()->AddAll(userinfo);
136  userinfo->Clear(); // necessary to prevent the TTree destructor from deleting
137  // all elements in the list (avoid double deletion)
138  }
139  else {
140  if (steering & verbose)
141  cout << "Flow: creating a clone tree" << endl;
142 
143  tOut = unique_ptr<TTree>(tIn->CloneTree(0));
144  tOut->SetTitle(title);
145  }
146  if (fOut)
147  tOut->SetDirectory(fOut.get());
148  return tOut.get();
149 }

◆ NoBranch() [1/2]

T* NoBranch ( const std::string &  name,
BranchMode  mode 
)
inlineprivate
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  }

◆ NoBranch() [2/2]

T* NoBranch ( const std::string &  name,
BranchMode  mode 
)
inlineprivate
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  }

◆ SetOutputFile() [1/2]

void SetOutputFile ( std::shared_ptr< TFile >  fOut)
inline

Set the output file where the output TTree should be saved.

235 { this->fOut = fOut; }

◆ SetOutputFile() [2/2]

void SetOutputFile ( std::shared_ptr< TFile >  fOut)
inline

Set the output file where the output TTree should be saved.

235 { this->fOut = fOut; }

Member Data Documentation

◆ branches

std::map< std::string, std::any > branches
private

pointers to mounted branches

◆ fOut

std::shared_ptr< TFile > fOut
private

output ROOT file

◆ inputs

std::vector< std::filesystem::path > inputs
private

ROOT files or directories.

◆ steering

int steering
private

steering from Options, mostly useful for friends

◆ tIn

std::unique_ptr< ChainSlice > tIn
private

input chain

◆ tOut

std::unique_ptr< TTree > tOut
private

output tree


The documentation for this class was generated from the following files:
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
Ntupliser_cfg.cerr
cerr
Definition: Ntupliser_cfg.py:98
Darwin::Tools::Flow
User-friendly handling of input and output n-tuples.
Definition: Flow.h:78
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::tOut
std::unique_ptr< TTree > tOut
output tree
Definition: Flow.h:86
Darwin::Tools::Flow::fOut
std::shared_ptr< TFile > fOut
output ROOT file
Definition: Flow.h:85
Darwin::Tools::GetOutputFile
std::shared_ptr< TFile > GetOutputFile(const std::filesystem::path &, const std::source_location=std::source_location::current())
Shortcut to create a reproducible output file (see ROOT Doxygen for details)
Definition: FileUtils.cc:141
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
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::Flow::inputs
std::vector< std::filesystem::path > inputs
ROOT files or directories.
Definition: Flow.h:82
Darwin::Tools::Flow::GetOutputTree
TTree * GetOutputTree(std::shared_ptr< TFile >={}, const std::source_location=std::source_location::current())
Create an output TTree object.
Definition: Flow.cc:83
DAS::RecDijet
Di< RecJet, RecJet > RecDijet
Definition: Di.h:80
Darwin::Tools::GetROOTfiles
std::vector< std::filesystem::path > GetROOTfiles(std::vector< std::filesystem::path > inputs)
ROOT files or directories.
Definition: FileUtils.cc:79
Darwin::Tools::Flow::steering
int steering
steering from Options, mostly useful for friends
Definition: Flow.h:80
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::SlicedFriendElement::AddTo
static SlicedFriendElement * AddTo(TTree *tree, ChainSlice *chain, const char *alias)
Adds a ChainSlice as a friend to a TTree.
Definition: FriendUtils.cc:80
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::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