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)
 
template<Plugin P, std::ranges::range R>
std::vector< P * > GetPlugins (R &&plugin_paths)
 
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)
 
template<Plugin P, std::ranges::range R>
std::vector< P * > GetPlugins (R &&plugin_paths)
 

Private Member Functions

template<typename T >
requires std::is_compound< T >::value std::shared_ptr< T * > branch_cast (std::any &a)
 
template<typename T >
requires std::is_fundamental< T >::value std::shared_ptr< T > branch_cast (std::any &a)
 
template<typename T >
requires std::is_compound< T >::value T * GetBranchAddress (std::shared_ptr< T * > ptr)
 
template<typename T >
requires std::is_fundamental< T >::value T * GetBranchAddress (std::shared_ptr< T > ptr)
 
template<typename T >
T * GetBranchAddress (const std::string &name)
 
template<typename T >
T * NoBranch (const std::string &name, BranchMode mode)
 
template<typename T >
requires std::is_compound< T >::value std::shared_ptr< T * > branch_cast (std::any &a)
 
template<typename T >
requires std::is_fundamental< T >::value std::shared_ptr< T > branch_cast (std::any &a)
 
template<typename T >
requires std::is_compound< T >::value T * GetBranchAddress (std::shared_ptr< T * > ptr)
 
template<typename T >
requires std::is_fundamental< T >::value T * GetBranchAddress (std::shared_ptr< T > ptr)
 
template<typename T >
T * GetBranchAddress (const std::string &name)
 
template<typename T >
T * NoBranch (const std::string &name, BranchMode mode)
 

Private Attributes

int steering
 
std::vector< PluginLoaderplugin_loaders
 
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

◆ branch_cast() [1/4]

requires std::is_compound<T>::value std::shared_ptr<T*> branch_cast ( std::any &  a)
inlineprivate

Casts from std::any to shared_ptr

97  {
98  return std::any_cast<std::shared_ptr<T*>>(a);
99  }
100  catch (const std::bad_any_cast& e) {
101  BOOST_THROW_EXCEPTION(e);
102  }

◆ branch_cast() [2/4]

requires std::is_compound<T>::value std::shared_ptr<T*> branch_cast ( std::any &  a)
inlineprivate

Casts from std::any to shared_ptr

97  {
98  return std::any_cast<std::shared_ptr<T*>>(a);
99  }
100  catch (const std::bad_any_cast& e) {
101  BOOST_THROW_EXCEPTION(e);
102  }

◆ branch_cast() [3/4]

requires std::is_fundamental<T>::value std::shared_ptr<T> branch_cast ( std::any &  a)
inlineprivate

Casts from std::any to shared_ptr

108  {
109  return std::any_cast<std::shared_ptr<T>>(a);
110  }
111  catch (const std::bad_any_cast& e) {
112  BOOST_THROW_EXCEPTION(e);
113  }

◆ branch_cast() [4/4]

requires std::is_fundamental<T>::value std::shared_ptr<T> branch_cast ( std::any &  a)
inlineprivate

Casts from std::any to shared_ptr

108  {
109  return std::any_cast<std::shared_ptr<T>>(a);
110  }
111  catch (const std::bad_any_cast& e) {
112  BOOST_THROW_EXCEPTION(e);
113  }

◆ DumpActiveBranches() [1/2]

std::string DumpActiveBranches ( ) const
inline

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

158  {
159  auto keys = branches | std::views::keys;
160  return std::accumulate(keys.begin(), keys.end(), std::string(),
161  [](const std::string& str, const std::string& branch_name) {
162  return str + ' ' + branch_name;
163  });
164  }

◆ DumpActiveBranches() [2/2]

std::string DumpActiveBranches ( ) const
inline

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

158  {
159  auto keys = branches | std::views::keys;
160  return std::accumulate(keys.begin(), keys.end(), std::string(),
161  [](const std::string& str, const std::string& branch_name) {
162  return str + ' ' + branch_name;
163  });
164  }

◆ GetBranchAddress() [1/6]

T* GetBranchAddress ( const std::string &  name)
inlineprivate

Get branch address from name (universal)

135  {
136  using namespace std;
137  any& a = branches[name];
138  shared_ptr ptr = branch_cast<T>(a);
139  return GetBranchAddress<T>(ptr);
140  }

◆ GetBranchAddress() [2/6]

T* GetBranchAddress ( const std::string &  name)
inlineprivate

Get branch address from name (universal)

135  {
136  using namespace std;
137  any& a = branches[name];
138  shared_ptr ptr = branch_cast<T>(a);
139  return GetBranchAddress<T>(ptr);
140  }

◆ GetBranchAddress() [3/6]

requires std::is_compound<T>::value T* GetBranchAddress ( std::shared_ptr< T * >  ptr)
inlineprivate

Get branch address for compound types.

119  {
120  return *ptr;
121  }

◆ GetBranchAddress() [4/6]

requires std::is_compound<T>::value T* GetBranchAddress ( std::shared_ptr< T * >  ptr)
inlineprivate

Get branch address for compound types.

119  {
120  return *ptr;
121  }

◆ GetBranchAddress() [5/6]

requires std::is_fundamental<T>::value T* GetBranchAddress ( std::shared_ptr< T >  ptr)
inlineprivate

Get branch address for fundamental types.

127  {
128  return ptr.get();
129  }

◆ GetBranchAddress() [6/6]

requires std::is_fundamental<T>::value T* GetBranchAddress ( std::shared_ptr< T >  ptr)
inlineprivate

Get branch address for fundamental types.

127  {
128  return ptr.get();
129  }

◆ 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
304  {
305  using namespace std;
306 
307  if (!tIn)
308  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
309  "be called before declaring a read-only branch") );
310 
311  if (!branches.contains(name)) {
312 
313  any branch;
314  if constexpr (is_compound<T>::value)
315  branch = make_shared<T*>();
316  else
317  branch = make_shared<T>();
318 
319  if (steering & verbose)
320  cout << "Flow: loading read-only branch `" << name << "`" << endl;
321 
322  if (tIn->GetBranch(name.c_str()) == nullptr)
323  return NoBranch<T>(name, mode);
324 
325  int err = tIn->SetBranchAddress(name.c_str(), branch_cast<T>(branch).get());
326  if (steering & verbose)
327  cout << "Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
328  << " (check `TTree::ESetBranchAddressStatus` for the meaning)."
329  << endl;
330  if (err < 0) {
331  string what = "`"s + name + "` branch could not be set. "s;
332  if (mode == facultative) {
333  if (steering & verbose)
334  cout << orange << "Flow: " << what << def << endl;
335  return nullptr;
336  }
337 
338  namespace DE = Darwin::Exceptions;
339  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
340  }
341  branches.emplace(name, branch);
342  }
343 
344  return GetBranchAddress<T>(name);
345  }

◆ 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
304  {
305  using namespace std;
306 
307  if (!tIn)
308  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
309  "be called before declaring a read-only branch") );
310 
311  if (!branches.contains(name)) {
312 
313  any branch;
314  if constexpr (is_compound<T>::value)
315  branch = make_shared<T*>();
316  else
317  branch = make_shared<T>();
318 
319  if (steering & verbose)
320  cout << "Flow: loading read-only branch `" << name << "`" << endl;
321 
322  if (tIn->GetBranch(name.c_str()) == nullptr)
323  return NoBranch<T>(name, mode);
324 
325  int err = tIn->SetBranchAddress(name.c_str(), branch_cast<T>(branch).get());
326  if (steering & verbose)
327  cout << "Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
328  << " (check `TTree::ESetBranchAddressStatus` for the meaning)."
329  << endl;
330  if (err < 0) {
331  string what = "`"s + name + "` branch could not be set. "s;
332  if (mode == facultative) {
333  if (steering & verbose)
334  cout << orange << "Flow: " << what << def << endl;
335  return nullptr;
336  }
337 
338  namespace DE = Darwin::Exceptions;
339  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
340  }
341  branches.emplace(name, branch);
342  }
343 
344  return GetBranchAddress<T>(name);
345  }

◆ 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
397  {
398  using namespace std;
399 
400  if (!tIn)
401  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
402  "be called before declaring a read-write branch") );
403 
404  if (!tOut)
405  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
406  "be called before declaring a read-write branch") );
407 
408  if (!branches.contains(name)) {
409  if (GetBranchReadOnly<T>(name, mode) == nullptr)
410  return NoBranch<T>(name, mode);
411  if (steering & Friend)
412  GetBranchWriteOnly<T>(name);
413  }
414 
415  return GetBranchAddress<T>(name);
416  }

◆ 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
397  {
398  using namespace std;
399 
400  if (!tIn)
401  BOOST_THROW_EXCEPTION( invalid_argument("`GetInputTree()` should "
402  "be called before declaring a read-write branch") );
403 
404  if (!tOut)
405  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
406  "be called before declaring a read-write branch") );
407 
408  if (!branches.contains(name)) {
409  if (GetBranchReadOnly<T>(name, mode) == nullptr)
410  return NoBranch<T>(name, mode);
411  if (steering & Friend)
412  GetBranchWriteOnly<T>(name);
413  }
414 
415  return GetBranchAddress<T>(name);
416  }

◆ 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
357  {
358  using namespace std;
359 
360  if (!tOut)
361  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
362  "be called before") );
363 
364  if (!branches.contains(name)) {
365  if constexpr (is_compound<T>::value)
366  branches.emplace(name, make_shared<T*>());
367  else
368  branches.emplace(name, make_shared<T>());
369  }
370 
371  any branch = branches[name];
372  shared_ptr ptr = branch_cast<T>(branch);
373 
374  if (steering & verbose)
375  cout << "Flow: setting up a write-only branch for `" << name << "`" << endl;
376 
377  if (tOut->Branch(name.c_str(), ptr.get()) == nullptr) {
378  namespace DE = Darwin::Exceptions;
379  string what = name + " branch could not be set up";
380  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tOut) );
381  }
382 
383  return GetBranchAddress<T>(ptr);
384  }

◆ 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
357  {
358  using namespace std;
359 
360  if (!tOut)
361  BOOST_THROW_EXCEPTION( invalid_argument("`GetOutputTree()` should "
362  "be called before") );
363 
364  if (!branches.contains(name)) {
365  if constexpr (is_compound<T>::value)
366  branches.emplace(name, make_shared<T*>());
367  else
368  branches.emplace(name, make_shared<T>());
369  }
370 
371  any branch = branches[name];
372  shared_ptr ptr = branch_cast<T>(branch);
373 
374  if (steering & verbose)
375  cout << "Flow: setting up a write-only branch for `" << name << "`" << endl;
376 
377  if (tOut->Branch(name.c_str(), ptr.get()) == nullptr) {
378  namespace DE = Darwin::Exceptions;
379  string what = name + " branch could not be set up";
380  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tOut) );
381  }
382 
383  return GetBranchAddress<T>(ptr);
384  }

◆ 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
250  {
251  auto hists = GetInputHists<THX,1>({name});
252  THX * hist = hists.front().release();
253  return std::unique_ptr<THX>(hist);
254  }

◆ 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
250  {
251  auto hists = GetInputHists<THX,1>({name});
252  THX * hist = hists.front().release();
253  return std::unique_ptr<THX>(hist);
254  }

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

237  {
238  constexpr const size_t N = sizeof...(args);
239  std::array<std::string, N> names {{ args... }};
240  return GetInputHists<THX, N>(names);
241  }

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

237  {
238  constexpr const size_t N = sizeof...(args);
239  std::array<std::string, N> names {{ args... }};
240  return GetInputHists<THX, N>(names);
241  }

◆ 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
198  {}
199  )
200  {
201  using namespace std;
202  namespace fs = filesystem;
203 
204  if (inputs.size() == 0)
205  BOOST_THROW_EXCEPTION( invalid_argument("Empty list of input files") );
206 
207  array<unique_ptr<THX>, N> sums;
208  for (const fs::path& input: inputs) {
209  auto fIn = make_unique<TFile>(input.c_str(), "READ");
210  for (size_t i = 0; i < N; ++i) {
211  const string& name = names[i];
212  unique_ptr<THX> h(fIn->Get<THX>(name.c_str()));
213  if (!h) {
214  namespace DE = Darwin::Exceptions;
215  BOOST_THROW_EXCEPTION(
216  DE::BadInput(Form("`%s` cannot be found in (one of) the "
217  " file(s).", name.c_str()), fIn));
218  }
219  if (sums[i])
220  sums[i]->Add(h.get());
221  else {
222  sums[i] = std::move(h);
223  sums[i]->SetDirectory(nullptr);
224  }
225  }
226  }
227  return sums;
228  }

◆ 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
198  {}
199  )
200  {
201  using namespace std;
202  namespace fs = filesystem;
203 
204  if (inputs.size() == 0)
205  BOOST_THROW_EXCEPTION( invalid_argument("Empty list of input files") );
206 
207  array<unique_ptr<THX>, N> sums;
208  for (const fs::path& input: inputs) {
209  auto fIn = make_unique<TFile>(input.c_str(), "READ");
210  for (size_t i = 0; i < N; ++i) {
211  const string& name = names[i];
212  unique_ptr<THX> h(fIn->Get<THX>(name.c_str()));
213  if (!h) {
214  namespace DE = Darwin::Exceptions;
215  BOOST_THROW_EXCEPTION(
216  DE::BadInput(Form("`%s` cannot be found in (one of) the "
217  " file(s).", name.c_str()), fIn));
218  }
219  if (sums[i])
220  sums[i]->Add(h.get());
221  else {
222  sums[i] = std::move(h);
223  sums[i]->SetDirectory(nullptr);
224  }
225  }
226  }
227  return sums;
228  }

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

283 { return fOut.get(); }

◆ GetOutputFile() [2/2]

TFile* GetOutputFile ( )
inline

Get a raw pointer to the output file.

283 { 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 >  = {},
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
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 }

◆ GetPlugins() [1/2]

std::vector<P*> GetPlugins ( R &&  plugin_paths)
inline

Load and get plugins.

Todo:
Clarify order in which the plugins should be destroyed in case of non-trivial interplay between plugins (GitLab).
425  {
426  using namespace std;
427  namespace fs = filesystem;
428 
429  for (fs::path file: plugin_paths)
430  plugin_loaders.emplace_back(file, steering);
431 
432  auto plugins = plugin_loaders | views::transform(&PluginLoader::Get<P>)
433  | views::join
434  | views::common;
435  return vector<P*>(plugins.begin(), plugins.end());
436  }

◆ GetPlugins() [2/2]

std::vector<P*> GetPlugins ( R &&  plugin_paths)
inline

Load and get plugins.

Todo:
Clarify order in which the plugins should be destroyed in case of non-trivial interplay between plugins (GitLab).
425  {
426  using namespace std;
427  namespace fs = filesystem;
428 
429  for (fs::path file: plugin_paths)
430  plugin_loaders.emplace_back(file, steering);
431 
432  auto plugins = plugin_loaders | views::transform(&PluginLoader::Get<P>)
433  | views::join
434  | views::common;
435  return vector<P*>(plugins.begin(), plugins.end());
436  }

◆ NoBranch() [1/2]

T* NoBranch ( const std::string &  name,
BranchMode  mode 
)
inlineprivate

Wrapper either to return a nullptr or to throw an error.

145  {
146  if (mode == facultative)
147  return nullptr;
148 
149  namespace DE = Darwin::Exceptions;
150  std::string what = name + " branch could not be found";
151  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
152  }

◆ NoBranch() [2/2]

T* NoBranch ( const std::string &  name,
BranchMode  mode 
)
inlineprivate

Wrapper either to return a nullptr or to throw an error.

145  {
146  if (mode == facultative)
147  return nullptr;
148 
149  namespace DE = Darwin::Exceptions;
150  std::string what = name + " branch could not be found";
151  BOOST_THROW_EXCEPTION( DE::BadInput(what.c_str(), *tIn) );
152  }

◆ SetOutputFile() [1/2]

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

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

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

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

◆ plugin_loaders

std::vector< PluginLoader > plugin_loaders
private
See also
PluginLoader

◆ 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:91
Ntupliser_cfg.cerr
cerr
Definition: Ntupliser_cfg.py:105
Darwin::Tools::Flow::plugin_loaders
std::vector< PluginLoader > plugin_loaders
Definition: Flow.h:84
Darwin::Tools::Flow
User-friendly handling of input and output n-tuples.
Definition: Flow.h:80
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:33
Ntupliser_cfg.args
args
Definition: Ntupliser_cfg.py:11
Darwin::Tools::Flow::tOut
std::unique_ptr< TTree > tOut
output tree
Definition: Flow.h:89
Darwin::Tools::Flow::fOut
std::shared_ptr< TFile > fOut
output ROOT file
Definition: Flow.h:88
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:147
plugins
PluginsVec * plugins()
Definition: IPlugin.h:77
Darwin::Exceptions
Handling of exceptions.
Definition: darwin.h:37
Darwin::Tools::verbose
@ verbose
bit for debug mode (-v is always available)
Definition: Options.h:29
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:85
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:82
Darwin::Tools::GetROOTfiles
std::vector< std::filesystem::path > GetROOTfiles(std::vector< std::filesystem::path > inputs)
ROOT files or directories.
Definition: FileUtils.cc:85
join
PseudoJet join(const std::vector< PseudoJet > &pieces)
Definition: fjcore.hh:1245
Darwin::Tools::Flow::steering
int steering
steering from Options, mostly useful for friends
Definition: Flow.h:82
Darwin::Tools::Flow::tIn
std::unique_ptr< ChainSlice > tIn
input chain
Definition: Flow.h:87
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:249
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:279
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:33