RDataFrame with user-defined object columns containing RVec as class members

Hi experts,
I am analyzing some data using RDataFrame and I encountered a problem:
I am trying to extract some info from my data and I’d like to use Define to produce a TTree with branches and leaves (I want the leaves to be both containers (RVec) and normal types).
So I have tried to create both a class and a typedef struct to define columns but in my final TTree RVecs are also treated like objects and so in the TBrowser they appear as subbranches of my class and I also can see some of their methods (?) (I hope the screenshot will clarify). What I expected was just to see them as if I was just defining normal RVec columns or any other collection type associated to a contiguous storage in memory.

Here is the code I am using:

TUPLE_WITH_8_RVEC_DOUBLE analyze ( ROOT::VecOps::RVec<int> v ){
/*my calculation*/
class myClass
		int Nup;
		int Ndwn;
		ROOT::VecOps::RVec<double> timeUp;
		ROOT::VecOps::RVec<double> timeDwn;

int main(int argc, char** argv){
//code to obtain input directories...
    gInterpreter->Declare("class myClass { public: int Nup; int Ndwn; ROOT::VecOps::RVec<double> timeUp; ROOT::VecOps::RVec<double> timeDwn; };");
	auto g = [=]( TUPLE_WITH_8_RVEC_DOUBLE  WVF_dec )->myClass{ 
		myClass a;
		a.Nup = (int)get<0>(WVF_dec).size();  
		a.Ndwn = (int)get<1>(WVF_dec).size(); 
		a.timeUp = get<2>(WVF_dec);
		a.timeDwn = get<3>(WVF_dec);
		return a; };
	ROOT::RDataFrame d(treeInName.c_str(), rootIn.c_str());
    auto d0 = d.Define("WVFdecoded"    , []( ROOT::VecOps::RVec<int> ADC_ch     ){ return analyze(ADC_ch); }, {"ch0"} ) 
			   .Define("ch00"           , g , {"WVFdecoded" } );
	d0.Snapshot(treeOutName.c_str(), rootOut.c_str(), {"event","ch00"});
    return 0;

The easiest way out would be to give up using myClass and just call each column with a prefix but I think it would be more general using branches and leaves so I would appreciate any help to solve this.
Thanks in advance.

ROOT Version: 6.22/07
Platform: Ubuntu 20.10
Compiler: GCC 10.2.0

Hi Massimo,
I’m not sure I understand the issue, that’s the typical behavior of TBrowser when objects are written to file – you should see the data when you double-click on timeUp.fData. If you write RVecs “directly”, i.e. not as data members of your class, you should see the same kind of TBrowser output.

If you want to see fewer levels of branching you can try playing with the fSplitLevel attribute of RSnapshotOption (which you can pass to Snapshot to configure its behavior). Searching for “splitlevel” here should provide some more context.

Alternatively, you can simply use a size/array pair, such as int Nup; double *timeUp as data members of myClass.

As a side-note, we are going to introduce some optimizations in RVec soon that will change their data layout. We will of course do our very best to not break RVec I/O across ROOT versions (if that should ever happen, please report it as a bug) – just a heads-up that you might see slightly different output from TBrowser in v6.24 or v6.26.


I think that the fSplitLevel is what I was looking for, thanks a lot!
Btw if I write my RVecs “directly” I see a totally different behaviour: I do not see the RVecName.fData leaf and, assuming I have both RVec data and ints I just see the following leaves structure:
leaf #1: RVecName.RVecName
leaf#2: intName
leaf#3: …

and so on. I can post a pic of the TBrowser also in this case if you want.
Probably I am just not understanding how ROOT treats these type of data, I’m sorry.
Anyway now everything seems to work as I wanted to so thanks a lot!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.