Is there an easy way to create something like a shared pointer for e.g. a ROOT::RDF::RResultPtr<TH1D> and a TH1D* object? Sorry if the question does not make sense, I have started working with RDF only recently. Please let me know if I can clarify.
For most uses, using smart pointers has not been an issue, but there were some specific cases where it seemed to matter, in my case with TSpectrum::Search. It seems the object containing the data needs to have a viable conversion to TH1*, which seems was not possible with ROOT::RDF::RResultPtr<TH1D>. It seems there is no trivial way to typecast a ROOT::RDF::RResultPtr<TH1D> object as a TH1D* one, unless, of course, I dereference the object first and define a new pointer, which is my current solution. But that way I cannot exploit the advantages of pass by pointer anymore which would be quite useful to me.
What I first had actually was to define histograms already as TH1D*, but then I realised that this goes against the lazy action philosophy of RDF, essentially starting the event loop every time I defined a new histogram.
If I may ask, there was one thing I was wondering about. Is the inverse also possible? I.e. converting a TH1D* to a ROOT::RDF::RResultPtr<TH1D>. I did not realise before, but I use a TH2::ProjectionX somewhere in my code, which calls the same function in which I perform the peak finding, but the problem is that there is no method named TH1D::GetPtr so I get an error.
Edit: Removed a question about dot and arrow operators, as I realised that RResultPtr::GetPtr is a method of RResultPtr and not the histogram.
This is not possible since we are talking about two very different things. An RResultPtr is encapsulating a result of a particular operation inside of an RDataFrame computation graph. In particular, one such result could be a TH1D histogram. On the other hand, if you start from a TH1D histogram object there is no guarantee that this belongs to a certain RDataFrame grap. For example, you may have created it manually in some other way.
but I use a TH2::ProjectionX somewhere in my code, which calls the same function in which I perform the peak finding, but the problem is that there is no method named TH1D::GetPtr so I get an error
I don’t understand what is the problem here. If you need to create a TH2D object as a part of your RDataFrame computations, then you have the Histo2D operation. Then you can get the ProjectionX from the RResultPtr<TH2D> resulting from that call. But maybe you have something different in mind, let me know.
I see, that makes a lot of sense. Thanks a lot for the clarification.
Sorry, I think a simplified example may help demonstrate what i wanted to ask.
template<typeame T>
double getPeak(T hist){
TSpectrum s;
int npeaks = s.Search(h.GetPtr()); // works if T is ROOT::RDF::RResultPtr<TH1D>, fails if T is TH1D*
//int npeaks = s.Search(h); // works if T is TH1D*, fails if T is ROOT::RDF::RResultPtr<TH1D>
double peak = 0;
//peak = ...; //pick the desired peak, not relevant for issue
return peak;
}
template<typename T>
void build1dPlot(T hist){
TString name = hist->GetName();
double peak = getPeak(hist);
hist->Fit("f","gaus",peak-20,peak+20);
TCanvas * c = new TCanvas();
c->cd();
hist->Draw();
c->Update();
c->SaveAs(name+".png");
}
void main() {
ROOT::RDataFrame df{...};
auto h = df.Histo1D(...);
auto h2 = df.Histo2D('x','y');
build1dPlot(h); // WORKS
build1dPlot(h2->ProjectionX()); // Error: TH1D* has no member named GetPtr
}
So my problem comes from the fact that I use the same function for both h and h2->ProjectionX() to find the peak within my function that builds the plots. I do many customisations to the plots, so for me to have these functions is essential. If possible, I want to avoid as much as possible overloads to keep my code relatively clean, which is why I started using templates.
One simple solution is to simply define a new histo auto h2x = df.Histo1D('x') but using TH2::ProjectionX would be more handy for me.