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
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:
But the output of TDataFrame.Histo1D() is this strange TDF::TResultProxy. Is there a way to do what I’d like?
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.
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
h1_ = myDataFrame.Histo1D<double>(TH1D("h1_", "h1_", 80, 0, 2), "my_branch");
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>'
So I managed to find a work around, I’m not sure if there is a smarter way to do it.
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!
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?
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
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.
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
Hope this helps,
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.