DAS  3.0
Das Analysis System
Flow

Description

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

A flow consists of input and output 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, const std::string &="events")
 
ChainSliceGetInputTree (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, const std::string &="events")
 
ChainSliceGetInputTree (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
265  {
266  using namespace std;
267 
268  if (!tIn)
269  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
270  "be called before declaring a read-only branch") );
271 
272  namespace DE = Darwin::Exceptions;
273 
274  shared_ptr<T*> t;
275 
276  if (branches.contains(name))
277  t = GetBranch<T>(name);
278  else {
279  t = make_shared<T*>();
280  if (steering & verbose)
281  cout << "Flow: loading branch `" << name << "`" << endl;
282 
283  if (tIn->GetBranch(name.c_str()) == nullptr)
284  return NoBranch<T>(name, mode);
285 
286  int err = tIn->SetBranchAddress(name.c_str(), t.get());
287  if (steering & verbose)
288  cout << "Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
289  << " (check `TTree::ESetBranchAddressStatus` for the meaning)."
290  << endl;
291  if (err < 0) {
292  string what = "`"s + name + "` branch could not be set. "s;
293  if (mode == facultative) {
294  if (steering & verbose)
295  cout << orange << "Flow: " << what << def << endl;
296  return nullptr;
297  }
298  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
299  }
300  branches.insert({name, t});
301  }
302  return *t;
303  }

◆ 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
265  {
266  using namespace std;
267 
268  if (!tIn)
269  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
270  "be called before declaring a read-only branch") );
271 
272  namespace DE = Darwin::Exceptions;
273 
274  shared_ptr<T*> t;
275 
276  if (branches.contains(name))
277  t = GetBranch<T>(name);
278  else {
279  t = make_shared<T*>();
280  if (steering & verbose)
281  cout << "Flow: loading branch `" << name << "`" << endl;
282 
283  if (tIn->GetBranch(name.c_str()) == nullptr)
284  return NoBranch<T>(name, mode);
285 
286  int err = tIn->SetBranchAddress(name.c_str(), t.get());
287  if (steering & verbose)
288  cout << "Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
289  << " (check `TTree::ESetBranchAddressStatus` for the meaning)."
290  << endl;
291  if (err < 0) {
292  string what = "`"s + name + "` branch could not be set. "s;
293  if (mode == facultative) {
294  if (steering & verbose)
295  cout << orange << "Flow: " << what << def << endl;
296  return nullptr;
297  }
298  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
299  }
300  branches.insert({name, t});
301  }
302  return *t;
303  }

◆ 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
353  {
354  using namespace std;
355 
356  if (!tIn)
357  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
358  "be called before declaring a read-write branch") );
359 
360  if (!tOut)
361  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
362  "be called before declaring a read-write branch") );
363 
364  shared_ptr<T*> t;
365 
366  if (branches.contains(name))
367  t = GetBranch<T>(name);
368  else {
369  if (GetBranchReadOnly<T>(name, mode) == nullptr)
370  return NoBranch<T>(name, mode);
371  if (steering & Friend)
372  GetBranchWriteOnly<T>(name);
373  t = any_cast<shared_ptr<T*>>(branches[name]);
374  }
375  return *t;
376  }

◆ 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
353  {
354  using namespace std;
355 
356  if (!tIn)
357  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
358  "be called before declaring a read-write branch") );
359 
360  if (!tOut)
361  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
362  "be called before declaring a read-write branch") );
363 
364  shared_ptr<T*> t;
365 
366  if (branches.contains(name))
367  t = GetBranch<T>(name);
368  else {
369  if (GetBranchReadOnly<T>(name, mode) == nullptr)
370  return NoBranch<T>(name, mode);
371  if (steering & Friend)
372  GetBranchWriteOnly<T>(name);
373  t = any_cast<shared_ptr<T*>>(branches[name]);
374  }
375  return *t;
376  }

◆ 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
315  {
316  using namespace std;
317 
318  if (!tOut)
319  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
320  "be called before") );
321 
322  shared_ptr<T*> t;
323 
324  if (branches.contains(name))
325  t = GetBranch<T>(name);
326  else
327  t = make_shared<T*>();
328 
329  if (steering & verbose)
330  cout << "Flow: setting up new branch for `" << name << "`" << endl;
331  if (tOut->Branch(name.c_str(), t.get()) == nullptr) {
332  namespace DE = Darwin::Exceptions;
333  string what = name + " branch could not be set up";
334  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tOut) );
335  }
336 
337  if (!branches.contains(name))
338  branches.insert({name, t});
339  return *t;
340  }

◆ 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
315  {
316  using namespace std;
317 
318  if (!tOut)
319  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
320  "be called before") );
321 
322  shared_ptr<T*> t;
323 
324  if (branches.contains(name))
325  t = GetBranch<T>(name);
326  else
327  t = make_shared<T*>();
328 
329  if (steering & verbose)
330  cout << "Flow: setting up new branch for `" << name << "`" << endl;
331  if (tOut->Branch(name.c_str(), t.get()) == nullptr) {
332  namespace DE = Darwin::Exceptions;
333  string what = name + " branch could not be set up";
334  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tOut) );
335  }
336 
337  if (!branches.contains(name))
338  branches.insert({name, t});
339  return *t;
340  }

◆ 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
211  {
212  auto hists = GetInputHists<THX,1>({name});
213  THX * hist = hists.front().release();
214  return std::unique_ptr<THX>(hist);
215  }

◆ 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
211  {
212  auto hists = GetInputHists<THX,1>({name});
213  THX * hist = hists.front().release();
214  return std::unique_ptr<THX>(hist);
215  }

◆ 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).

198  {
199  constexpr const size_t N = sizeof...(args);
200  std::array<std::string, N> names {{ args... }};
201  return GetInputHists<THX, N>(names);
202  }

◆ 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).

198  {
199  constexpr const size_t N = sizeof...(args);
200  std::array<std::string, N> names {{ args... }};
201  return GetInputHists<THX, N>(names);
202  }

◆ 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
159  {}
160  )
161  {
162  using namespace std;
163  namespace fs = filesystem;
164 
165  if (inputs.size() == 0)
166  BOOST_THROW_EXCEPTION( runtime_error("Empty input list") );
167 
168  array<unique_ptr<THX>, N> sums;
169  for (const fs::path& input: inputs) {
170  auto fIn = make_unique<TFile>(input.c_str(), "READ");
171  for (size_t i = 0; i < N; ++i) {
172  const string& name = names[i];
173  unique_ptr<THX> h(fIn->Get<THX>(name.c_str()));
174  if (!h) {
175  namespace DE = Darwin::Exceptions;
176  BOOST_THROW_EXCEPTION(
177  DE::BadInput(Form("`%s` cannot be found in (one of) the "
178  " file(s).", name.c_str()), fIn));
179  }
180  if (sums[i])
181  sums[i]->Add(h.get());
182  else {
183  sums[i] = std::move(h);
184  sums[i]->SetDirectory(nullptr);
185  }
186  }
187  }
188  return sums;
189  }

◆ 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
159  {}
160  )
161  {
162  using namespace std;
163  namespace fs = filesystem;
164 
165  if (inputs.size() == 0)
166  BOOST_THROW_EXCEPTION( runtime_error("Empty input list") );
167 
168  array<unique_ptr<THX>, N> sums;
169  for (const fs::path& input: inputs) {
170  auto fIn = make_unique<TFile>(input.c_str(), "READ");
171  for (size_t i = 0; i < N; ++i) {
172  const string& name = names[i];
173  unique_ptr<THX> h(fIn->Get<THX>(name.c_str()));
174  if (!h) {
175  namespace DE = Darwin::Exceptions;
176  BOOST_THROW_EXCEPTION(
177  DE::BadInput(Form("`%s` cannot be found in (one of) the "
178  " file(s).", name.c_str()), fIn));
179  }
180  if (sums[i])
181  sums[i]->Add(h.get());
182  else {
183  sums[i] = std::move(h);
184  sums[i]->SetDirectory(nullptr);
185  }
186  }
187  }
188  return sums;
189  }

◆ GetInputTree() [1/4]

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

Load chain from a list of files with non-empty trees.

internal path to TTree

Parameters
slicenumber and index of slice
69 {
71 
72  if (tIn->GetEntries() == 0) {
73  tIn.reset();
74  BOOST_THROW_EXCEPTION(invalid_argument("Empty trees in input!"));
75  }
76 
77  if (slice.first == 0 || slice.first <= slice.second)
78  BOOST_THROW_EXCEPTION(invalid_argument("The number of slices " + to_string(slice.first)
79  + " must be larger than the index of the current slice " + to_string(slice.second)));
80 
81  // Restrict the tIn to the entries for the slice
82  const auto entries = tIn->GetEntries();
83  tIn->SetBegin(entries * ((slice.second + 0.) / slice.first));
84  tIn->SetEnd(entries * ((slice.second + 1.) / slice.first));
85 
86  return tIn.get();
87 }

◆ GetInputTree() [2/4]

ChainSlice* GetInputTree ( const  Slice,
const std::string &  = "events" 
)

Load chain from a list of files with non-empty trees.

internal path to TTree

Parameters
Slicenumber and index of slice

◆ GetInputTree() [3/4]

ChainSlice * GetInputTree ( const std::string &  name = "events")

Load chain from a list of files with possibly empty trees.

internal path to TTree

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.empty())
49  BOOST_THROW_EXCEPTION( invalid_argument("Empty list of input files") );
50 
51  tIn = make_unique<ChainSlice>(name.c_str());
52  for (const auto& input: inputs) {
53  int code = tIn->Add(input.c_str(), 0);
54  // "If nentries<=0 and wildcarding is not used,
55  // returns 1 if the file exists and contains the correct tree
56  // and 0 otherwise" (ROOT Doxygen)
57  if (code == 1) continue; // i.e. the tree was found successfully
58  tIn.reset();
59  auto fIn = make_unique<TFile>(input.c_str(), "READ");
60  BOOST_THROW_EXCEPTION(DE::BadInput("The tree cannot be "
61  "found in (one of) the input file(s).", fIn));
62  }
63 
64  return tIn.get();
65 }

◆ GetInputTree() [4/4]

ChainSlice* GetInputTree ( const std::string &  = "events")

Load chain from a list of files with possibly empty trees.

internal path to TTree

◆ 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
166 {
167  shared_ptr<TFile> fOut = Darwin::Tools::GetOutputFile(fOutName, location);
168  return {fOut.get(), GetOutputTree(fOut, location)};
169 }

◆ 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.

244 { return fOut.get(); }

◆ GetOutputFile() [2/2]

TFile* GetOutputFile ( )
inline

Get a raw pointer to the output file.

244 { return fOut.get(); }

◆ GetOutputTree() [1/4]

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

Create an output TTree object.

upstream function

◆ GetOutputTree() [2/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
159 {
160  shared_ptr<TFile> fOut = Darwin::Tools::GetOutputFile(fOutName, location);
161  return GetOutputTree(fOut, location);
162 }

◆ GetOutputTree() [3/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
91 {
92  if (tOut) {
93  if (steering & verbose)
94  cout << "Flow: returning the existing output tree" << endl;
95 
96  return tOut.get();
97  }
98 
99  if (fOut)
101 
102  const auto title = fs::path(location.file_name()).stem().string();
103 
104  if (!tIn) {
105  if (steering & verbose)
106  cout << "Flow: creating a new output tree" << endl;
107 
108  tOut = make_unique<TTree>("events", title.c_str());
109  }
110  else if (steering & Friend) {
116  if (steering & verbose)
117  cout << "Flow: creating a friend tree" << endl;
118 
119  tOut = make_unique<TTree>("events", title.c_str());
120  tIn->GetEntry(0); // necessary to load a(ny) TTree
121 
122  // find the name of the previous command
123  string lastFunc = tIn->GetTree()->GetTitle();
124  // -> this is supposed to store the name of the last command
125  if (lastFunc == "") {
126  cerr << orange << "Unable to identify the command used to "
127  "obtain the input from the title.\n" << def;
128  lastFunc = "previous";
129  }
130  else if (lastFunc == title) {
131  cerr << orange << "Running twice the same command in a row. "
132  "Adding `previous2` ahead of the title.\n" << def;
133  lastFunc = "previous2"s + title;
134  }
135 
136  // add friend
137  SlicedFriendElement::AddTo(tOut.get(), tIn.get(), lastFunc.c_str());
138 
139  // copy metainfo
140  TList * userinfo = tIn->GetTree()->GetUserInfo();
141  tOut->GetUserInfo()->AddAll(userinfo);
142  userinfo->Clear(); // necessary to prevent the TTree destructor from deleting
143  // all elements in the list (avoid double deletion)
144  }
145  else {
146  if (steering & verbose)
147  cout << "Flow: creating a clone tree" << endl;
148 
149  tOut = unique_ptr<TTree>(tIn->CloneTree(0));
150  tOut->SetTitle(title.c_str());
151  }
152  if (fOut)
153  tOut->SetDirectory(fOut.get());
154  return tOut.get();
155 }

◆ GetOutputTree() [4/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

◆ 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.

240 { 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.

240 { 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:101
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::GetInputTree
ChainSlice * GetInputTree(const Slice, const std::string &="events")
Load chain from a list of files with non-empty trees.
Definition: Flow.cc:67
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:89
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:210
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:240
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