How to make custom binning

Hi

I am trying to hadd two ttree’s , ( I am using a modified version of $ROOTSYS/tutorials/io/hadd.C) but what I would like to have at the end, is a “merged” TH1F plot what a custom binning, for example specifying that each bin should include at least n events (TAxis for example ?)… Is there any way to do that ?

Thanks in advance

Hi,

you could simply post-process the result of the merging of the histograms, and combine adjacent bins until they satisfy your minimum entries requirement.

Cheers, Axel.

Hi Axel

Would it be possible to give me a small script how to implement this ?

Thanks in advance

So, I was looking on

root.cern.ch/root/html/tutorials … bin.C.html

but could not understand, where you define the #events per bin in the rebinned histo…

Furthermore, I tried to do exactly the same thing to another histo, using the above script, but it failed… You need some .root file ?

Thanks in advance

So, I was looking on

root.cern.ch/root/html/tutorials … bin.C.html

but could not understand, where you define the #events per bin in the rebinned histo…

Furthermore, I tried to do exactly the same thing to another histo, using the above script, but it failed…

#include "TH1.h"
#include "TCanvas.h"
#include "TFile.h"
#include "TH1F.h"
#include "TRoot.h"
#include <iostream>

using namespace std;
void rebin() {

   //open a fixed bin histogram
  TFile *  fout = new TFile ("jets.root", "read");

   TH1F *h = (TH1F*) fout->Get("AllJetsPt");
   
   Double_t xbins[100000];
   Int_t k=0;
   TAxis *axis = h->GetXaxis();
   for (Int_t i=1;i<=h->GetNbinsX();i++) {
      Int_t y = (Int_t)h->GetBinContent(i);
      if (y <=0) continue;
   
      Double_t dx = axis->GetBinWidth(i)/y;
      Double_t xmin = axis->GetBinLowEdge(i);
    // if (dx>0){
      for (Int_t j=0;j<y;j++) {
         xbins[k] = xmin +j*dx;
         k++;
         cout<<k<<"  "<<xbins[k]<<"  "<<dx<<"  "<<j<<"  "<<j*dx<<"  "<<xmin<<"  "<<h->GetNbinsX()<<endl;
      }
    //  }
   }
   //create a variable binwidth histogram out of fix bin histogram
   
      /
   TH1F *hnew = new TH1F("hnew","rebinned",k-1,xbins);

   hnew->Rebin(k-1,"h",xbins);
   //rebin hnew keepingonly 50% of the bins
   Double_t xbins2[100000];
   Int_t kk=0;
   for (Int_t j=0;j<k;j+=2) {
      xbins2[kk] = xbins[j];
      kk++;
   }
   
   xbins2[kk] = xbins[k];
   //TH1F *hnew2 = (TH1F*)hnew->Rebin(kk-1,"hnew2",xbins2);

   //draw the 3 histograms
   TCanvas *c1 = new TCanvas("c1","c1",800,600);
   c1->Divide(1,3);
   c1->cd(1);
   h->Draw();
   c1->cd(2);
   hnew->Draw();
   c1->cd(3);
  // hnew2->Draw();
   
}

Thanks in advance
jets.root (5.35 KB)

Hi,
that tutorial creates a binning with on average one entry per bin: a bin with a content of 4 gets split into four bins.

You want to merge bins and that’s different. It’s actually a common problem; I agree that it would be good to provide the optimal bin edges given a histogram - right now ROOT doesn’t. A good implementation isn’t completely trivial; I will post a script that does it once it’s ready.

Cheers, Axel.

Actually I am trying something like


TAxis* MergeBins(TH1F* h, Int_t minEntriesPerBin){
  Int_t nbins = (Int_t) (h->Integral() / minEntriesPerBin);

   Double_t xq[nbins+1];
   TAxis *axis = new TAxis(nbins,xq);
   axis = h->GetXaxis();

   Double_t xbins[1000];
   Int_t k=0;
   for (Int_t i=0; i<=nbins; i++)
   xq[i] = ((Double_t) i) / nbins;
  Double_t yq[nbins+1];
  yq[0] = h->GetBinLowEdge(1);
  yq[nbins] = h->GetBinLowEdge(h->GetNbinsX()+1);
  return axis;
}

but does not work as expected, ie merge bins with a requierment of minEvents/bin

Cheers

Hi,

TAxis *axis = new TAxis(nbins,xq);copies immediately the content of xq to the TAxis object.
Any modification to xq and yq done after this creation have no effect on the TAxis object.

Philippe.

Hi Philippe - So, if I understand well, you suggest something like

TAxis *axis; 
   axis = h->GetXaxis();

   Double_t xbins[1000];
   Int_t k=0;
   for (Int_t i=0; i<=nbins; i++)
   xq[i] = ((Double_t) i) / nbins;
  Double_t yq[nbins+1];
  yq[0] = h->GetBinLowEdge(1);
  yq[nbins] = h->GetBinLowEdge(h->GetNbinsX()+1);
  axis= TAxis(nbins,xq);
  return axis;

it will give correctly the bins I need ?

Thanks in advance!

[quote]it will give correctly the bins I need ?[/quote]I still don’t think so, but at least it is now because the algorithm might be wrong and not because there is no information passed to the TAxis.

I have no clue why you hav yq array that you set but do not use.
The xq array seems to ask for evenly spaced bins from 0 to 1.

Philippe.