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");
- Note
- A one-liner is also possible:
|
std::string | DumpActiveBranches () const |
|
| Flow (int=none, const std::vector< std::filesystem::path > &={}) |
|
| ~Flow () |
|
ChainSlice * | GetInputTree (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 () |
|
ChainSlice * | GetInputTree (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) |
|
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
-
name | branch name |
mode | branch may not exist |
264 BOOST_THROW_EXCEPTION( invalid_argument(
"`GetInputTree()` should "
265 "be called before declaring a read-only branch") );
272 t = GetBranch<T>(
name);
274 t = make_shared<T*>();
276 cout <<
"Flow: loading branch `" <<
name <<
"`" << endl;
278 if (
tIn->GetBranch(
name.c_str()) ==
nullptr)
279 return NoBranch<T>(
name, mode);
281 int err =
tIn->SetBranchAddress(
name.c_str(), t.get());
283 cout <<
"Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
284 <<
" (check `TTree::ESetBranchAddressStatus` for the meaning)."
287 string what =
"`"s +
name +
"` branch could not be set. "s;
290 cout <<
orange <<
"Flow: " << what <<
def << endl;
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
-
name | branch name |
mode | branch may not exist |
264 BOOST_THROW_EXCEPTION( invalid_argument(
"`GetInputTree()` should "
265 "be called before declaring a read-only branch") );
272 t = GetBranch<T>(
name);
274 t = make_shared<T*>();
276 cout <<
"Flow: loading branch `" <<
name <<
"`" << endl;
278 if (
tIn->GetBranch(
name.c_str()) ==
nullptr)
279 return NoBranch<T>(
name, mode);
281 int err =
tIn->SetBranchAddress(
name.c_str(), t.get());
283 cout <<
"Flow: `TTree::SetBranchAddress()` returned " << to_string(err)
284 <<
" (check `TTree::ESetBranchAddressStatus` for the meaning)."
287 string what =
"`"s +
name +
"` branch could not be set. "s;
290 cout <<
orange <<
"Flow: " << what <<
def << endl;
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
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
-
88 cout <<
"Flow: returning the existing output tree" << endl;
96 const char * title = fs::path(location.file_name()).stem().c_str();
100 cout <<
"Flow: creating a new output tree" << endl;
102 tOut = make_unique<TTree>(
"events", title);
111 cout <<
"Flow: creating a friend tree" << endl;
113 tOut = make_unique<TTree>(
"events", title);
117 string lastFunc =
tIn->GetTree()->GetTitle();
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";
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;
134 TList * userinfo =
tIn->GetTree()->GetUserInfo();
135 tOut->GetUserInfo()->AddAll(userinfo);
141 cout <<
"Flow: creating a clone tree" << endl;
143 tOut = unique_ptr<TTree>(
tIn->CloneTree(0));
144 tOut->SetTitle(title);