Preserving histograms from rdataframe in named macro

ROOT Version: 6.20.04
Platform: Linux
Compiler: gcc


I’m just having my first foray into RDataFrames and it has taken me some time to work out how to prevent histograms produced this way from disappearing when a named macro ends. My solution is

  1. Save a copy of the histogram on the heap AND
  2. Save a pointer to the histogram in a TFolder before leaving the macro

Is this the correct way to do this? Is there a better solution? Is it documented somewhere that I’ve not found?
Here is a sketch of what I am doing

void draw(TString parameter)
{
    ROOT::RDataFrame df("myTTree","analyse.root");
	TString Cuts("Distance>1000&&Distance<6000");
	TString AndNeutron("&&PDG==2112");
	auto Neutrons= df.Filter((Cuts+AndNeutron).Data()).Histo1D(parameter.Data());
	Neutrons->Draw();
	TH1D* NeutronH=new TH1D;
    Neutrons->Copy(*NeutronH);
    NeutronH->Draw();

    TFolder *histograms=gROOT->GetRootFolder()->AddFolder("Histograms","Saved Histograms");
    gROOT->GetListOfBrowsables()->Add(histograms,"histograms");
    histograms->Add(NeutronH);
}

I think @eguiraud can help you.

Hi @ajfinch ,
the following certainly apply to v6.24 and v6.26 and I think it applies to v6.20 as well, but I would strongly recommend to update to a more recent ROOT version: RDataFrame has improved a lot in the last few years.

The histograms returned by RDataFrame are not associated to ROOT’s memory management and are held by an owning pointer. To make them survive the scope of a macro, you have two options:

  1. return them from the macro:
auto foo() { // in C++11, must return a RDF::RResultPtr<TH1D> instead of auto
   auto h = ROOT::RDataFrame(10).Histo1D("rdfentry_");
   return h;
}

and then e.g.

/tmp root -l                                                                  (cern-root-6.26)
root [0] .L foo.C
root [1] auto myhist = foo()
(ROOT::RDF::RResultPtr<TH1D> &) @0x7fbaabe85010
root [2] myhist->Draw()

Similarly, if you have multiple histograms, you can return them in a std::vector.

  1. copy the histograms in ones that ROOT manages and that you leak out of the macro scope
void foo() {
  auto h = ROOT::RDataFrame(10).Histo1D({"myhist", "myhist", 100, 0, 10},
                                        "rdfentry_");
  TH1D *hist = new TH1D(*h);
}

and then e.g.

/tmp root -l                  (cern-root-6.26)
root [0] .x foo.C
root [1] auto h = gDirectory->Get<TH1D>("myhist(TH1D *) @0x7ffe13828348

I hope this helps! gDirectory->Get<TH1D>(...) is probably not available in v6.20, you probably need static_cast<TH1D*>(gDirectory->Get(...).

Cheers,
Enrico

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