Reading data from a ROOT file into a histogram

Hello everyone.

I am trying to read data from a ROOT file in order to draw some histograms.
What I have is the following. Inside of the ROOT file there is a TTree called summary, inside the tree there are two branches I need to read, injEnergy and nucEnergy. I need to read all data from each branch into a histogram. I am not sure how to do so. Below there is my code.

#include "TFile.h"
#include "TTree.h"


void ratioplot() {

   // open the file
   TFile *f = TFile::Open("/home/oscar/Downloads/v2r4/SimProp_N200000.root");
   if (f == 0) 
   {
      // if we cannot open the file, print an error message and return immediatly
      printf("Error: cannot open file!\n");
   }

   TTreeReader myReader("summary", f);

   // Define two histograms. Note the X and Y title are defined
   // at booking time using the convention "Hist_title ; X_title ; Y_title"
   TH1F *h1 = new TH1F("h1", "Initial and final energy spectrum for the arriving particles;x title; h1 and h2 gaussian histograms", 100, 0, 5e+19);
   TH1F *h2 = new TH1F("h2", "h2", 100, -5, 5);
   //h1->FillRandom("gaus"); //Here I think I should read the data from the ROOT file into the histograms
   //h2->FillRandom("gaus");

   // Define the Canvas
   TCanvas *c = new TCanvas("c", "canvas", 800, 800);

   // Upper plot will be in pad1
   TPad *pad1 = new TPad("pad1", "pad1", 0, 0.3, 1, 1.0);
   pad1->SetBottomMargin(0); // Upper and lower plot are joined
   pad1->SetGridx();         // Vertical grid
   pad1->Draw();             // Draw the upper pad: pad1
   pad1->cd();               // pad1 becomes the current pad
   h1->SetStats(0);          // No statistics on upper plot
   h1->Draw();               // Draw h1
   h2->Draw("same");         // Draw h2 on top of h1

   // Do not draw the Y axis label on the upper plot and redraw a small
   // axis instead, in order to avoid the first label (0) to be clipped.
   h1->GetYaxis()->SetLabelSize(0.);
   TGaxis *axis = new TGaxis( -5, 20, -5, 220, 20,220,510,"");
   axis->SetLabelFont(43); // Absolute font size in pixel (precision 3)
   axis->SetLabelSize(15);
   axis->Draw();

   // lower plot will be in pad
   c->cd();          // Go back to the main canvas before defining pad2
   TPad *pad2 = new TPad("pad2", "pad2", 0, 0.05, 1, 0.3);
   pad2->SetTopMargin(0);
   pad2->SetBottomMargin(0.2);
   pad2->SetGridx(); // vertical grid
   pad2->Draw();
   pad2->cd();       // pad2 becomes the current pad

   // Define the ratio plot
   TH1F *h3 = (TH1F*)h1->Clone("h3");
   h3->SetLineColor(kBlack);
   h3->SetMinimum(0.8);  // Define Y ..
   h3->SetMaximum(1.35); // .. range
   h3->Sumw2();
   h3->SetStats(0);      // No statistics on lower plot
   h3->Divide(h2);
   h3->SetMarkerStyle(21);
   h3->Draw("ep");       // Draw the ratio plot

   // h1 settings
   h1->SetLineColor(kBlue+1);
   h1->SetLineWidth(2);

   // Y axis h1 plot settings
   h1->GetYaxis()->SetTitleSize(20);
   h1->GetYaxis()->SetTitleFont(43);
   h1->GetYaxis()->SetTitleOffset(1.55);

   // h2 settings
   h2->SetLineColor(kRed);
   h2->SetLineWidth(2);

   // Ratio plot (h3) settings
   h3->SetTitle(""); // Remove the ratio title

   // Y axis ratio plot settings
   h3->GetYaxis()->SetTitle("Ratio of final and initial energy spectrum ");
   h3->GetYaxis()->SetNdivisions(505);
   h3->GetYaxis()->SetTitleSize(20);
   h3->GetYaxis()->SetTitleFont(43);
   h3->GetYaxis()->SetTitleOffset(1.55);
   h3->GetYaxis()->SetLabelFont(43); // Absolute font size in pixel (precision 3)
   h3->GetYaxis()->SetLabelSize(15);

   // X axis ratio plot settings
   h3->GetXaxis()->SetTitleSize(20);
   h3->GetXaxis()->SetTitleFont(43);
   h3->GetXaxis()->SetTitleOffset(4.);
   h3->GetXaxis()->SetLabelFont(43); // Absolute font size in pixel (precision 3)
   h3->GetXaxis()->SetLabelSize(15);
}

I would use the Project Function instead of the TTreeReader:

TTree* tree = (TTree*) f->Get("summary");

// Histogram declarations

tree->Project("h1", "injEnergy");
tree->Project("h2", "nucEnergy");

Hi @JohnyBoy

You almost have it, once you have created the TTreeReader you need to select the branches you want to read, this can be done with TTreeReaderValue:

// Create a TTreeReader for the tree
TTreeReader myReader("summary", f);

// If the branch "injEnergy" contains floats; access them as myInjEnergy.
TTreeReaderValue<Float_t> myInjEnergy(myReader, "injEnergy");
// If the branch "nucEnergy" contains floats, too; access those as myNucEnergy.
TTreeReaderValue<Float_t> myNucEnergy(myReader, "nucEnergy");

Now that we have access to the branch values we can fill the histograms with the values corresponding to each event. The following code fills h1 with values from injEnergy and h2 with values from nucEnergy:

// Loop over all entries of the TTree
while (myReader.Next()) {
   // Just access the data as if myInjEnergy and myNucEnergy were iterators 
   // (note the '*' in front of them):
   h1->Fill(*myInjEnergy);
   h2->Fill(*myNucEnergy);
}

Alternatively, you can use the new RDataFrame interface rather than TTreeReader, which makes your code less verbose and simpler:

// Create an RDataFrame for the tree "summary" and file "f'.
ROOT::RDataFrame rdf("summary", f);

// There is no need to create an specific reader, you can just create a 
// histogram out of each branch (note that histogram models can also be specified):
auto h1 = rdf.Histo1D({"h1", "Initial and final...", 100, 0, 5e+19}, "injEnergy")
auto h2 = rdf.Histo1D({"h2", "h2", 100, -5, 5}, "nucEnergy")

// Rest of your code does not change

Thank you all for your help. I have solved it.

@JohnyBoy

Is it possible that you could post your code with the changes ? I would like to see an example :smile:

Sorry. Here is my code.

// Example displaying two histograms and their ratio.
// Author: Olivier Couet.
#include "TFile.h"
#include "TTree.h"


void ratioplot() {

   // open the file
   TFile *f = TFile::Open("/home/oscar/File2.root");
   if (f == 0) 
   {
      // if we cannot open the file, print an error message and return immediatly
      printf("Error: cannot open http://lcg-heppkg.web.cern.ch/lcg-heppkg/ROOT/eventdata.root!\n");
   }

   TH1F *h1 = new TH1F("h1", "Injection and arrival energy spectrum and their ratio; Energy (eV); Number of particles", 1000, 1e+18, 1e+21);
   TH1F *h2 = new TH1F("h2", "h2", 1000, 1e+18, 1e+21);
   
   TTree* tree = (TTree*) f->Get("summary");
   // Histogram declarations

   tree->Project("h1", "nucEnergy");
   tree->Project("h2", "injEnergy");

   // Define the Canvas
   TCanvas *c = new TCanvas("c", "canvas", 800, 800);

   // Upper plot will be in pad1

   TPad *pad1 = new TPad("pad1", "pad1", 0, 0.3, 1, 1.0);
   pad1->SetLogx();
   pad1->SetLogy();
   pad1->SetBottomMargin(0); // Upper and lower plot are joined
   pad1->SetGridx();         // Vertical grid
   pad1->Draw();             // Draw the upper pad: pad1
   pad1->cd();               // pad1 becomes the current pad
   h1->SetStats(0);          // No statistics on upper plot
   h1->Draw();               // Draw h1
   h2->Draw("same");         // Draw h2 on top of h1

   // Do not draw the Y axis label on the upper plot and redraw a small
   // axis instead, in order to avoid the first label (0) to be clipped.
   h1->GetYaxis()->SetLabelSize(0.);
   TGaxis *axis = new TGaxis( -5, 20, -5, 220, 20,220,510,"");
   axis->SetLabelFont(43); // Absolute font size in pixel (precision 3)
   axis->SetLabelSize(15);
   axis->Draw();

   TLegend *legend = new TLegend(0.55,0.65,0.76,0.82);
   legend->AddEntry(h1,"Arrival energy","f");
   legend->AddEntry(h2,"Injection energy","f");
   legend->Draw();

   // lower plot will be in pad
   c->cd();          // Go back to the main canvas before defining pad2
   TPad *pad2 = new TPad("pad2", "pad2", 0, 0.05, 1, 1);
   pad2->SetLogx();
   pad2->SetLogy();
   pad2->SetTopMargin(0);
   pad2->SetBottomMargin(0.2);
   pad2->SetGridx(); // vertical grid
   pad2->Draw();
   pad2->cd();       // pad2 becomes the current pad

   // Define the ratio plot
   TH1F *h3 = (TH1F*)h1->Clone("h3");
   h3->SetLineColor(kBlack);
   h3->SetMinimum(0.001);  // Define Y ..
   h3->SetMaximum(3.6); // .. range
   h3->Sumw2();
   h3->SetStats(0);      // No statistics on lower plot
   h3->Divide(h2);
   h3->SetMarkerStyle(21);
   h3->Draw("HIST");       // Draw the ratio plot

   // h1 settings
   h1->SetLineColor(kBlue+1);
   h1->SetLineWidth(2);

   // Y axis h1 plot settings
   h1->GetYaxis()->SetTitleSize(20);
   h1->GetYaxis()->SetTitleFont(43);
   h1->GetYaxis()->SetTitleOffset(1.55);

   // h2 settings
   h2->SetLineColor(kRed);
   h2->SetLineWidth(2);

   // Ratio plot (h3) settings
   h3->SetTitle(""); // Remove the ratio title

   // Y axis ratio plot settings
   h3->GetYaxis()->SetTitle("Energy spectrum ratios");
   h3->GetYaxis()->SetNdivisions(505);
   h3->GetYaxis()->SetTitleSize(20);
   h3->GetYaxis()->SetTitleFont(43);
   h3->GetYaxis()->SetTitleOffset(1.55);
   h3->GetYaxis()->SetLabelFont(43); // Absolute font size in pixel (precision 3)
   h3->GetYaxis()->SetLabelSize(15);

   // X axis ratio plot settings
   h3->GetXaxis()->SetTitleSize(20);
   h3->GetXaxis()->SetTitleFont(43);
   h3->GetXaxis()->SetTitleOffset(2.);
   h3->GetXaxis()->SetLabelFont(43); // Absolute font size in pixel (precision 3)
   h3->GetXaxis()->SetLabelSize(15);

}
1 Like