Store histogram from TTree::Draw()

_ROOT Version: 6
_Platform: lxplus

Hello,

I am trying to store in a vector some histograms created by TTree::Draw(). My code is like this:

TH1F* MakeHisto(TString path, TString Histo, TString Cut){
ch = new TChain("tree_incl_all");
ch->Add(path);
ch->Draw(Histo,Cut);
TH1F* h=new TH1F();
h=(TH1F*)gDirectory->Get("HISTO");
cout<<"---"<<h<<endl;
return h;}


void ex(){

vector <TH1F*> H;

TString path1 = "root://eosatlas//eos/atlas/atlascerngroupdisk/phys-higgs/HSG2/H4l/2018/MiniTrees/Prod_v17/mc16d/Nominal/mc16_13TeV.342556.PowhegPy8EG_CT10nloME_AZNLOCTEQ6L1_ZZllll_mll4_m4l_100_150.root";
TString path2 = "root://eosatlas//eos/atlas/atlascerngroupdisk/phys-higgs/HSG2/H4l/2018/MiniTrees/Prod_v17/mc16d/Nominal/mc16_13TeV.343232.PowhegPy8EG_CT10nloME_AZNLOCTEQ6L1_ZZllll_mll4_m4l_500_13000.root";


H.push_back(MakeHisto(path1,"phi>>+HISTO(1000,-4,4)", "weight*(phi<1)"));
H.push_back(MakeHisto(path2,"phi>>+HISTO(1000,-4,4)", "weight*(phi<1)"));

cout<<H[0]<<"---"<<H[1];

H[0]->Draw();
H[1]->Draw("same");
}

The strange is that If I draw only the last histogram everything is ok. But if I draw all the histograms the code crashes…
Can anybody help?

Thank you,
Panagiotis

1 Like

Hi,

the first pointer becomes invalid. Perhaps you could return from your function a copy of the histo?

Cheers,
D

Hi Panagiotis,

as an exercise, I re-expressed your code in terms of the modern RDataFrame (available in ROOT 6.14):

using HistPtr_t = ROOT::RDF::RResultPtr<TH1D>;

HistPtr_t MakeHisto(std::string_view path, std::string_view cut)
{
   ROOT::RDataFrame df("tree_incl_all", path);
   auto h = df.Filter(cut).Histo1D({"","",1000,-4,4}, "phi");
   *h;
   return h;
}

const auto path1 = "root://eosatlas//eos/atlas/atlascerngroupdisk/phys-higgs/HSG2/H4l/2018/MiniTrees/Prod_v17/mc16d/Nominal/mc16_13TeV.342556.PowhegPy8EG_CT10nloME_AZNLOCTEQ6L1_ZZllll_mll4_m4l_100_150.root";
const auto path2 = "root://eosatlas//eos/atlas/atlascerngroupdisk/phys-higgs/HSG2/H4l/2018/MiniTrees/Prod_v17/mc16d/Nominal/mc16_13TeV.343232.PowhegPy8EG_CT10nloME_AZNLOCTEQ6L1_ZZllll_mll4_m4l_500_13000.root";

void a()
{
   auto cut = "weight * ( phi < 1 )";
   std::vector<HistPtr_t> results {MakeHisto(path1, cut), MakeHisto(path2, cut)};
   results[0]->Draw();
   results[1]->Draw("Same");
}

Cheers,
D

1 Like

Thank you for your nice ideas Danilo!!

cheers,
Panagiotis

Thanks for the inspiration! :slight_smile:

Cheers,
D

TH1F* h=new TH1F();
h=(TH1F*)gDirectory->Get("HISTO");

The result of the operator new in this code snippet is ‘lost’ on the 2nd line. i.e. there is a memory leak. You probably meant:

TH1F* h = (TH1F*)gDirectory->Get("HISTO");

The histogram is associated with the ‘current’ directory which is the file opened by the TChain. Consequently when this file is closed (the next call to MakeHisto), the histogram is deleted.

The solution with RDataFrame is superior but for completeness the following might work:

gROOT->cd();
ch->Draw(Histo,Cut);
TH1F *h=(TH1F*)gDirectory->Get("HISTO");

Cheers,
Philippe.

I’m afraid I need to disagree with @pcanal.

The problem has nothing to do with the “current” directory, nor with the “TChain”.
It is generated by the “HISTO(1000,-4,4)” string in the “Draw” expression.

{
  // run this macro "as is", then replace "#if 1" with "#if 0" below and rerun
  // (note: this macro needs the "hsimple.root" from "${ROOTSYS}/tutorials/")
  TChain *t;
  TH1 *h;
  // ... first pass ...
  std::cout << "gDirectory = " << gDirectory->GetName() << std::endl;
  t = new TChain("ntuple");
  t->Add("hsimple.root");
  std::cout << "gDirectory = " << gDirectory->GetName() << std::endl;
  // note: this will CREATE a new "HISTO"
  t->Draw("px>>+HISTO(1000,-4,4)");
  std::cout << "gDirectory = " << gDirectory->GetName() << std::endl;
  h = (TH1*)gDirectory->Get("HISTO");
  std::cout << "h = " << h << std::endl;
  if (h) h->Print();
  // ... second pass ...
  std::cout << "gDirectory = " << gDirectory->GetName() << std::endl;
  t = new TChain("ntuple");
  t->Add("hsimple.root");
  std::cout << "gDirectory = " << gDirectory->GetName() << std::endl;
#if 1 /* 0 or 1 */
  // note: this will DELETE the existing "HISTO" and CREATE it anew
  t->Draw("px>>+HISTO(1000,-4,4)");
#elif 1 /* 0 or 1 */
  // note: this will REUSE and RESET the existing "HISTO"
  t->Draw("px>>HISTO");
#else /* 0 or 1 */
  // note: this will REUSE and ADD entries to the existing "HISTO"
  t->Draw("px>>+HISTO");
#endif /* 0 or 1 */
  std::cout << "gDirectory = " << gDirectory->GetName() << std::endl;
  h = (TH1*)gDirectory->Get("HISTO");
  std::cout << "h = " << h << std::endl;
  if (h) h->Print();
}
  // note: this will DELETE the existing "HISTO" and CREATE it anew
  t->Draw("px>>+HISTO(1000,-4,4)");

This sounds like a bug (either in the doc or the code) as this looks like it should ‘Append’ to the histo if it exist rather than recreate it (because of the ‘+’).

Well". the “+” is neglected in case you explicitly define the histogram binning.
Try my small test macro replacing “#if 1” with “#if 0” and “#elif 1” with “#elif 0”.

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