I want to apply some selections on the PV positions (x,y,z) using filter in RDataFrame.
The variable in the DecayTree is called PVX[nPV]/F
however when I do:
error: static_assert failed due to requirement ‘std::is_convertible<ROOT::VecOps::RVec,bool>::value’ “filter
expression returns a type that is not convertible to bool”
I tried to fix it by using:
sel_pvx ="(for (auto x :PVX){if(x>0.3) return true;}return false;)"
or
sel_pvx ="(for (int i=0;i<PVX;i++){ if (PVX[i]>0.3)return true;}return false;)"
h=df.Filter(sel_pvx).Histo1D(var)
h.GetEntries()
but it didn’t work.
is there anything else I can do to fix it ?
This would create a new variable array in your RDataFrame called good_PVX with elements which are PVX[i]>0.3
If you plan to use more variables related to the same physical object, like PVY, PVZ be careful to apply the same selection on all of them e.g. more general code would look something like this:
you can see tutorial on how RDataFrame works with arrays e.g. here1 or here2.
It maybe a bit clumsy to rename all the columns related to the same physical object if you have a lot of them, but root team currently looking on how to improve this in the recent versions…
Dear Bohdan,
Thank u very much for your reply what u suggested is exactly what I need.
Do you have any idea what to do if I need a Histogram of pT or p with the selections above ?
I understand that
gives u a Histogram of PVX with those selections.
what to do if we want Histo1D(“ple_PT”) instead, with the same selections?
PS: ple_PT is not an array .
you need to be more specific on what do you mean by: “the events that only have a PVX >0.3”, as your events have manyPVXes.
Do you want to select events that have:
at least one PVX > 0.3?
all must be PVX > 0.3?
for both cases you could define a custom c++ functions which would do the selection.
Here is an example:
ROOT.gInterpreter.Declare('''
using namespace ROOT::VecOps;
bool selection1(RVec<double> PVX){
// if at least one element is larger than 0.3 - pass the event
for (int i=0; i < PVX.size() ; i++){
if( PVX[i] > 0.3 ) return true;
}
return false;
}
bool selection2(RVec<double> PVX){
// if all elements are larger than 0.3 - pass the event
for (int i=0; i < PVX.size() ; i++){
if( PVX[i] < 0.3 ) return false;
}
return true;
}
''')
h1=df.Filter("selection1(PVX)").Histo1D("ple_PT")
h2=df.Filter("selection2(PVX)").Histo1D("ple_PT")
I believe you could do it as one line using C++ lambda functions imidiatly inside Filter() as well.