TDataFrame histograms

Hello, I’m learning to use TDataFrame at the moment. It’s pretty nifty. I have an analysis class that I’d like to use on several different root files so I want to be able to access the histograms which are output from TDataFrame as members of my analysis class.

Usually I would do something like this

#Class definition
public:
    TH1D* h1_;

#Class Constructor
MyClass::MyClass() {
ROOT::Experimental::TDataFrame df("T", "myfile.root");

h1_ = df.Histo1D<double>("my_branch");
};

So that later when I use this analysis class I can do something like this:

MyClass analyzer();
analyzer.h1_->Draw();

But the output of TDataFrame.Histo1D() is this strange TDF::TResultProxy. Is there a way to do what I’d like?

Thanks!

Hi,

don’t worry. TResultProxy is just a wrapper class, owning its “result” and able to trigger the event loop of the TDF upon usage of the “result” by the user (myRes->Draw(), for example)

I am not sure I get the full picture of the analysis you are trying to put up but what is stopping you from having data members of type TResultProxy ? You can access all the methods of the underlying histo via the -> operator (e.g. myProxy->GetName(), myProxy->Write()) and even can get the reference to the histo with the GetValue method.

Cheers,
D

Thanks for the response. I tried to make my data member of type TResultProxy but I’m not sure the exact syntax/what includes that requires…

In the class definition I tried

ROOT::Experimental::TDF::TResultProxy<TH1D> *h1_;
....
....
....
h1_ = myDataFrame.Histo1D<double>(TH1D("h1_", "h1_", 80, 0, 2), "my_branch");
....
....
h1_->Draw()

But I get

././Analyzer.C:120:8: error: assigning to 'ROOT::Experimental::TDF::TResultProxy<TH1D> *' from incompatible type 'TResultProxy< ::TH1D>'
        h1_ = selected_reco.Histo1D<double>(TH1D("h1", "h1", 80, 0, 2), "recon_theta", "weight");
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
././Analyzer.C:139:8: error: no member named 'DrawClone' in 'ROOT::Experimental::TDF::TResultProxy<TH1D>'
  h1_->DrawClone();

So I managed to find a work around, I’m not sure if there is a smarter way to do it.

TH1D* h1_;
....
....
auto h1 = myDataFrame.Histo1D<double>(TH1D("h1", "h1", 80, 0, 2), "my_branch");
h1_ = (TH1D*)h1.GetValue().Clone("h1_");

I didn’t realize that you had to use “.” to access the TResultProxy, I kept using “->” and I was instead accessing the underlying histogram.
If there’s a more beautiful way to do it, it would still be appreciated. Thanks for the help!

Hi,

you need to use a data member of type ROOT::Experimental::TDF::TResultProxy and not ROOT::Experimental::TDF::TResultProxy*. The second attempt for sure works, but implies a copy, which is less than optimal. Why did you clone?

Cheers,
D

To further clarify: TResultProxy<TH1D> is a type that acts as a smart pointer to a TH1D. All results of TDataFrame actions are of type TResultProxy<T>; in terms of usage, you can think of it as a std::shared_ptr<T>, or even just a T*.

Its only particular feature is that this is a pointer that is smart enough to trigger the TDataFrame event loop when you try to access its contents for the first time, although for most applications (yours included) one can safely ignore this under-the-hood details.

Anyway, since TResultProxy<T> already acts like a pointer, you don’t need to store a pointer to a TResultProxy<T> in your class, just use TResultProxy<TH1D> as you would use a TH1D*.

Hope this helps,
Enrico

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