I am currently trying to figure out the correct syntax for using the previous event in the filter for RDataFrame.
In our use case, the events are ordered in time and it is essential to check the previous event in order to satisfy an analysis cut, e.g.
presently data frame can only process one event at the time but you can implement the behaviour you are after. Below you find a macro, example.C, which shows how to offer for a certain variable at event n the value of event n-1. I made some assumptions, but it proves the point I hope:
// This template keeps a state which could be the
// value of a variable in the previous event
template<typename T>
class PrevValProducer {
T fVal;
public:
explicit PrevValProducer(const T& v) : fVal(v) {}
T operator()(T v)
{
std::swap(v, fVal);
return v;
}
};
void example()
{
PrevValProducer<int> prod(0);
auto foo = 100;
ROOT::RDataFrame r(4);
auto r2 = r.Define("v", [&foo](){return foo++;})
.Define("prev_v", prod, {"v"});
// This just to take out the values and print them
auto vals = r2.Take<int, ROOT::RVec<int>>("prev_v");
cout << *vals << endl;
}
one last caveat, which I am sure you already spot: the suggested procedure is not thread safe. It could be made such using some thread_local qualifier, or, even better, the slot index provided by dataframe. In this case the fVal datamember would become a std::vector with as many elements as slots.
And Define → DefineSlot and T operator()(T v) → T operator()(unsigned int slot, T v), right?
Is the number of slots available globally before the DataFrame is created (without calling ROOT::EnableImplicitMT (numthreads) with a specific number)?