There is a topic from last year which seems to ask the same question (see below), but it never got a definite answer. Is there any way of knowing the current root file that is being processed in RDataframe?
The way our analysis is set up, each root file stores the raw data from a specific run together with the calibration parameters for that run. Since these parameters can change between runs, it would be necessary to read the calibration parameters from the current file when processing multiple runs at once. Ideally we would store a pointer to the current file, and then check if that pointer matches the result we get from RDataframe. It seems there is a method GetDataSource in RLoopManager, but I don’t know how to get the loop manager from RDataframe?
I would suggest to use DefinePerSample transformation.
It accepts a C++ callable with signature
(unsigned int slot, const ROOT::RDF::RSampleInfo &id)
You don’t need to retrieve RSampleInfo on your own.
Inside the callable body you can do whatever you want.
In particular, see method ROOT::RDF::RSampleInfo::AsString, which according to docs does
return a string representation… of the form <filename>/<treename> if the input data comes from a TTree or a TChain.
which allows you in principle even open a file, retrieve metadata and close it on the fly with some overhead.
Here is a simple test script, tested on ROOT v6.40.04
{
{ // create input files
ROOT::RDataFrame df(5);
auto df1 = df.Define("x", [x=double(0.0)]() mutable -> double { return x++; });
df1.Snapshot("Events", "test1.root"); // x = 0, ..., 4
df1.Snapshot("Events", "test2.root"); // x = 5, ..., 9
}
{ // read input files
TChain Events("Events");
Events.Add("test*.root");
ROOT::RDataFrame df(Events);
auto df1 = df.DefinePerSample("fileId",
[](unsigned int /*slot*/, const ROOT::RDF::RSampleInfo &id) -> int {
// get <filename>/<treename> string and strip <treename>
std::string filename_treename = id.AsString(); // /home/user/tmp/test<i>.root/Events
size_t pos = filename_treename.rfind(".root");
if (pos == std::string::npos) return 0;
std::string filename = filename_treename.substr(0, pos + 5); // /home/user/tmp/test<i>.root
// open file on the fly once per sample
auto *f = TFile::Open(filename.c_str());
f->ls();
f->Close();
return id.Contains("1") ? 1 : 2;
}
);
auto s = df1.Define("y", "x * fileId").Sum("y");
std::cout << "sum of x = " << s.GetValue() << std::endl; // 80
}
}
Output
Processing .\test.cxx...
TFile** /home/user/tmp/test1.root
TFile* /home/user/tmp/test1.root
KEY: TTree Events;1 Events
TFile** /home/user/tmp/test2.root
TFile* /home/user/tmp/test2.root
KEY: TTree Events;1 Events
sum of x = 80