RDataFrame crashes with generic unsplit TObject branch

I’ve created TTree with a branch that holds a generic TObject. To do this, I must declare the branch as unsplit (otherwise I can’t hold objects of different types in the branch).

However, it appears that declaring the branch as unsplit causes RDataFrame to crash when I try to interact with that branch with a lambda function (e.g. Foreach(...))

Are unsplit object-type branches unsupported?

Here’s a reproducer:

https://cernbox.cern.ch/index.php/s/1PDYLcjDp35XCO6

Hi,
I’m afraid you are hitting a known bug: TTreeReader, which RDataFrame uses to read ROOT data, does not support TBranchObjects, and your unsplit branch is indeed a TBranchObject. Relaxing this limitation is very high on my to-do list. In the meanwhile, a dirty workaround that might give you some mileage is to manually instantiate a TBranchElement instead of a TBranchObject:

instead of

t->Branch("o", "TObject", &o, 32000, 0);

you can use the (ugly, temporary) hack:

 TBranchElement* branch = new TBranchElement(t, "o", (TStreamerInfo*)TObject::Class()->GetStreamerInfo(), -1, (char*)o, 32000, 0);
 t->GetListOfBranches()->Add(branch);                                                                                 
 t->SetBranchAddress("o", &o);

Cheers,
Enrico

Thanks, this does prevent the crash, but with some further playing, I see it isn’t letting me access the object as anything other than a TObject? I cannot cast it to its true type, and I note that the 'ClassName()` of the object is always ‘TObject’, unlike when I used a proper TObject branch when it would be whatever the actual type of the object is.

Is this something I just will have to live without until RDataFrame /TTreeReader can be fixed to truly support this branch type?

Let’s see until where we can push RDF+arbitrary TObject-inheriting things :smiley:

The following code prints "RooFitResult" when asked the ClassName or the IsA()->GetName() of the TObjects, so I cannot reproduce the problems you mentioned.

#include <ROOT/RDataFrame.hxx>
#include <TTree.h>
#include <TObject.h>
#include <RooFitResult.h>
#include <TBranchElement.h>
#include <iostream>

int main()
{
   // make a tree with a couple of branches - one branch will hold a generic TObject (must be unsplit because could be anything!)
   auto t = new TTree("tree", "tree");
   double d = 0;
   TObject *o = 0;
   t->Branch("d", &d);
   TBranchElement* branch = new TBranchElement(t, "o", (TStreamerInfo*)TObject::Class()->GetStreamerInfo(), -1, (char*)&o, 32000, 0);
   t->GetListOfBranches()->Add(branch);
   t->SetBranchAddress("o", &o);

   // fill it with some 'data'
   o = new RooFitResult("myFit");
   d = 5;
   t->Fill();
   o = new RooFitResult("anotherFit");
   d = 2;
   t->Fill();
   t->Scan();

   ROOT::RDataFrame(*t).Foreach([] (const TObject &obj) { std::cout << obj.IsA()->GetName() << std::endl; }, {"o"});
   ROOT::RDataFrame(*t).Foreach([] (const TObject &obj) { std::cout << obj.ClassName() << std::endl; }, {"o"});
   ROOT::RDataFrame(*t).Foreach([] (const TObject &obj) { std::cout << static_cast<const RooFitResult&>(obj).status() << std::endl; }, {"o"});

   return 0;
}

prints

~ ./repro

RooFit v3.60 -- Developed by Wouter Verkerke and David Kirkby 
                Copyright (C) 2000-2013 NIKHEF, University of California & Stanford University
                All rights reserved, please read http://roofit.sourceforge.net/license.txt

************************************
*    Row   *       d.d *         o *
************************************
*        0 *         5 *         0 *
*        1 *         2 *         0 *
************************************
RooFitResult
RooFitResult
RooFitResult
RooFitResult
-1717986919
-1717986919

I’d be interested to see what and where breaks exactly.

Cheers,
Enrico

Does it still work if you write a different object type (e.g. a TH1D) in between some of those RooFitResults? It crashes for me …

Oof, indeed it crashes already in TTree::Scan when the object type changes between events.
Well, that’s how far the hack goes I gues :sweat: @pcanal might be able to suggest a more robust way to force the unsplit branch to a TBranchElement.

Meanwhile, I guess I really have to fix TTreeReader+TBranchObject…

Hi @will_cern,
any chance you can try out this patch and see if it fixes RDF/TTreeReader+TBranchObject for all cases you care about? :slight_smile:

It works for me for the case with unsplit object with RooFitResult and TH1D inside (and ROOT tests are running, but I’m pretty confident it does not break any).

That fix is now in master (future ROOT v6.24) it will also be part of v6.22/02.

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