Histograms in ROOT

Welcome to hands-on session dedicated on working with the histograms in ROOT. We assume now that you are now more familiar in writing C++ code and working with the ROOT prompt and writing ROOT macros.

Exercise 1: Working with the histogram bins

Create an histogram with 200 bins between 0 and 10. Fill then the histogram with 1000 gaussian random numbers with mean 5 and sigma 0.3 and 10000 uniform number between 0 and 10. Plot this histogram. Find the bin number of the histogram with the maximum content. What is its bin content ? What is the bin center and the bin error ? Afterwards zoom the histogram plot between 4 and 6 using either TAxis::SetRange or the mouse (clicking on the axis).

To find the maxim bin you can use TH1::GetMaximumBin if you don't want to loop at the bins yourself.

For zooming an histogram you can use TAxis::SetRange(firstbin,last bin) or TAxis::SetRangeUser(x1,x2). You can also do it with the GUI by selecting the axis range with the mouse.

#include "TH1.h"
#include "TRandom.h"
#include "TPad.h"
#include <iostream>

void exerciseHistogram1() { 


   TH1D * h1 = new TH1D("h1","flat+gaus histogram",200,0,10);

   for (int i = 0; i < 10000; ++i) { 
      h1->Fill( gRandom->Uniform(0,10) ); 
   }
   for (int i = 0; i < 1000; ++i) { 
      h1->Fill( gRandom->Gaus(5,0.2) ); 
   }

   h1->Draw();

   double ibinMax = h1->GetMaximumBin();
   std::cout << "Bin with maximum is " << ibinMax << " at x = " << h1->GetBinCenter(ibinMax) << std::endl;
   std::cout << "Maximum Content  is " << h1->GetBinContent(ibinMax) << " +/- " << h1->GetBinError(ibinMax) << std::endl;

   TAxis * axis = h1->GetXaxis();
   axis->SetRange( axis->FindBin(4.0001), axis->FindBin(5.9999) ); // add or subtract a small eps to avoid being at the edge of the bin
   // axis->SetRangeUser(4.,6. );   // alternativly you can use SetRangeUser

   gPad->Update();

}

Pointing hand Instead of zooming create a sub-histogram between 4 and 6 using TH1::GetBinContent on the original histogram and TH1::SetBinContent on the new histogram. How many bins has the new histogram ?

To create the sub-histogram, you need first to find the bin numbers in the original histogram corresponding to 4 and 6. You can use for this TAxis:FindBin for this. Then you create the sub-histogram using as lower value for the axis, the lower edge of the bin corresponding to 4, and, as upper value, the upper edge of the bin corresponding to 6. Afterwards, by looping on the bins, you can copy the bin content from the original histogram into the new one. It is better to use a slightly value larger than 4 (e.g. 4.0001) and a value a little bit smaller than 6 (e.g. 5.999) to avoid the bin edges.

#include "TH1.h"
#include "TRandom.h"
#include "TPad.h"
#include <iostream>



void exerciseHistogram1b() { 


   TH1D * h1 = new TH1D("h1","flat+gaus histogram",200,0,10);

   for (int i = 0; i < 10000; ++i) { 
      h1->Fill( gRandom->Uniform(0,10) ); 
   }
   for (int i = 0; i < 1000; ++i) { 
      h1->Fill( gRandom->Gaus(5,0.2) ); 
   }

   h1->Draw();

   double ibinMax = h1->GetMaximumBin();
   std::cout << "Bin with maximum is " << ibinMax << " at x = " << h1->GetBinCenter(ibinMax) << std::endl;
   std::cout << "Maximum Content  is " << h1->GetBinContent(ibinMax) << " +/- " << h1->GetBinError(ibinMax) << std::endl;

   TAxis * axis = h1->GetXaxis();
   int ifirst =  axis->FindBin(4.001);
   int ilast =  axis->FindBin(5.9999);
   int nbins =  ilast - ifirst; 
   TH1D * h2 = new TH1D("h2","flat+gaus zoomed histogram",nbins, axis->GetBinLowEdge(ifirst), axis->GetBinUpEdge(ilast));
   std::cout << " Number of bins of zoomed histogram is " << nbins << std::endl;
   for (int i1 = ifirst; i1 <= ilast; ++i1) { 
      int i2 = i1 - ifirst + 1;
      //std::cout << " setting content for bin " << i2 << " from " << i1 << " c = " << h1->GetBinContent(i1) << std::endl;
      h2->SetBinContent( i2, h1->GetBinContent(i1) ); 
   }
   h2->Draw(); 
   gPad->Update();

   // to check if we did not screw-up,  we recompute maximum position
   double ibinMax2 = h2->GetMaximumBin();
   std::cout << "Bin with maximum is " << ibinMax2 << " at x = " << h2->GetBinCenter(ibinMax2) << std::endl; 

}

Exercise 2: Histograms Operations

We will work in this exercise on the histogram operations like addition, subtraction and scaling.

  • Make a gaussian filled histogram between 0 and 10 with 100 bis and 1000 entries with mean 5 and sigma 1.
  • Make another histogram uniformly distributed between 0 and 10 with 100 bins and 10000 entries.
  • Add the two histogram into a new one using TH1::Add
  • Make another histogram, still with 100 bins but with 100000 entries. Normalize this histogram to have a total integral of 10000 using TH1::Scale.
  • Subtract now from the histogram which contains the sum of the flat and the gaussian histograms, the flat normalised histogram, using TH1::Add
  • Plot the result using the error option (h1->Draw("E")). Do the error make sense ? If not, how can you get the correct bin errors ?

  • Use TH1::Add to add the two histogram.
  • Use TH1::Scale(10000/ 100000) to re-normalise the histogram.
  • Use again TH1::Add to subtract the histogram, but with a second coefficient equal to -1. (TH1::Add(h1,h2,1,-1)).
  • For getting the right errors you must call TH1::Sumw2= before doing the operations on the histograms (i.e. before scaling and before subtracting them)

#include "TH1.h"
#include "TRandom.h"
#include "TCanvas.h"
#include "TLine.h"
#include <iostream>

void exerciseHistogram2() { 


   TH1D * h1 = new TH1D("h1","flat histogram",100,0,10);
   for (int i = 0; i < 10000; ++i) { 
      h1->Fill( gRandom->Uniform(0,10) ); 
   }

   TH1D * h2 = new TH1D("h2","gaus histogram",100,0,10);
   for (int i = 0; i < 1000; ++i) { 
      h2->Fill( gRandom->Gaus(5,1) ); 
   }

   TH1D * h3 = new TH1D("h3","flat+gaus histogram",100,0,10);
   h3->Add(h1,h2);

   h3->Draw();


   TH1D * h4 = new TH1D("h4","second flat histogram",100,0,10);
   for (int i = 0; i < 100000; ++i) { 
      h4->Fill( gRandom->Uniform(0,10) ); 
   }

   // renormalize histogram
   //!! VERY IMPORTANT - NEED TO CALL Sumw2() to get right ERRORS!!!
   h4->Sumw2();
   h3->Sumw2();
   h4->Scale(0.1);

   // plot in a new Canvas
   new TCanvas("c2","c2");


  TH1D * h5 = new TH1D("h5","(flat+gaus) histogram - flat histogram",100,0,10);
  h5->Add(h3,h4,1.,-1.);
  h5->Draw("E");

  TLine * line = new TLine(0,0,10,0);
  line->Draw();
   

}

Pointing hand Rebin now of the histogram (e.g. the one resulting at the end from the subtraction) in a new histogram with bins 4 times larger.

For rebinning in 4 times larger bins, use TH1::Rebin with ngroup=4.

Add these lines of code at the end of the macro
new TCanvas("c2","c2");

  TH1 * h6 = h5->Rebin(4,"h6");
  h6->SetTitle("Rebinned histogram");
  h6->Draw();

Exercise 3: Multi-Dimensional Histograms and Profiles

Create a 2 dimensional histogram with x and y in the range [-5,5] and [-5,5] and 40 bins in each axis. Fill the histogram with correlated random normal numbers. To do this generate 2 random normal numbers (mean=0, sigma=1) u and w. Then use x = u and y=w+0.5*u for filling the histogram. Plot the histogram using color boxes (See documentation in THistPainter class) or choose what-ever option you prefer After having filled the histogram compute the correlation using TH1::GetCorrelationFactor.

The option for plotting colour boxes is "COLZ" which draws also a palette for the scale on the Z axis (the bin content)

#include "TH2.h"
#include "TProfile.h"
#include "TRandom.h"
#include "TCanvas.h"
#include <iostream>

void exerciseHistogram3() { 


   TH2D * h2d = new TH2D("h2d","2d histogram",40,-5,5, 40, -5, 5);
   for (int i = 0; i < 100000; ++i) { 
      double u =  gRandom->Gaus(0,1);
      double w =  gRandom->Gaus(0,1);      
      double x = u; 
      double y = w + 0.5 * u;
      h2d->Fill( x,y ); 
   }

   h2d->Draw("COLZ");

   std::cout << "correlation factor " << h2d->GetCorrelationFactor() << std::endl;


}

Make then a projection of the 2-dimensional histogram on the x. Make also a projection of the y axis into a profile. Plot the resulting projected histograms in a new canvas separated in 2 pads.

For making the projection call TH1::ProjectionX and for making the profile call TH1::ProfileX

For dividing the canvas call TCanvas::Divide(1,2) and navigate in the pad contained in the canvas by calling TCanvas::cd(pad_number).

Add these lines of code at the end of the macro
TH1 * hx = h2d->ProjectionX(); 
   TH1 * px = h2d->ProfileX(); 

   TCanvas * c2 = new TCanvas("c2","c2"); 
   // divide in 2 pad in x and one in y
   c2->Divide(2,1);
   c2->cd(1); 
   hx->Draw(); 

   c2->cd(2);
   px->Draw();

Pointing hand Look at the bin error of the profile. Do you know how it is computed ? You can find this answer in the TProfile reference documentation.

Pointing hand If you have still time, after having finished the exercises you can look at some of the tutorials in the ROOT distribution directory, $ROOTSYS/tutorials/hist. They are available on the Web at this location. For example look at:

Edit | Attach | Watch | Print version | History: r6 < r5 < r4 < r3 < r2 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r6 - 2013-02-26 - LorenzoMoneta
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright &© 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback