Variable bin width histogram


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.18/00
Platform: Ubuntu 20.04
Compiler: ROOT/CLANG


Dear expert,

I am trying to read a .root file and rebin the histogram.
I wanted to fill the histogram and rebin it with skipping bins and the skipped bin content(value) as the mean value.

I want to fill the new histogram hp2t2 using the new bins to be as below: Double_t bins[]={....} and set the bin value as the mean of the skipped bins whenever skipped. Also scale with the new bin width

Here is my attempted code
convert_to_text.C (1.2 KB)
and the root file:
test.root (4.4 KB).

Here is the code snippet:

void root_to_text()
{
 TFile* f = new TFile("test.root","READ");
 TH1D*  h = (TH1D*)f->Get("hprt");
        h->Sumw2();
 
 Double_t bins[] = {0. ,  0.0025,  0.005 ,  0.0075,  0.010  ,  0.015, 0.02 , 0.025, 0.03 , 0.035, 0.04 , 0.045, 0.05 , 0.055
, 0.06 , 0.07 , 0.08 , 0.09 ,  0.1  , 0.11 , 0.120, 0.130, 0.140, 0.150};
 Int_t   binN   = sizeof(bins)/sizeof(Double_t) - 1; // # of Bins
   
 TH1D* hp2t2 = new TH1D("hp2t2","",binN,bins); 

 Int_t nbin=h->GetNbinsX();
 for (Int_t i = 1; i<=nbin; i++)
     { 
       Double_t xmin  = h->GetBinLowEdge(i);
       Double_t value = h->GetBinContent(i);
       Double_t error = h->GetBinError(i);
       
      if (i<4){xmin = xmin ;hp2t2->Fill(xmin,value/0.0025);} 
        else if(i>=4 || i<=12){xmin = xmin+0.005;
              hp2t2->Fill(xmin,value/0.005);} 
        else if(i>=4 || i<=12){xmin = xmin+0.010; 
              hp2t2->Fill(xmin,value/0.010);}                                          
     }
hp2t2->Draw("hist");
gPad->SetLogy(1);
}

I guess @couet can help with that.

I see you code. It runs for me. The technique looks fine. Now it is up to you to make the you fill le bins as you wish.

Hi, Thanks a lot.
I made improvements in the code and got what I want. Can you please let me know how can I plot a histogram from the vector data stored, i.e edges(bins) and sigma(bin value).

Also, It will be great if you could suggest a better way/optimized than this.

Thanks in adance.

void root_to_text()
{

 TFile* f = new TFile("test.root","READ");
 TH1D*  h = (TH1D*)f->Get("hprt");
        h->Sumw2();
 
 Double_t bins[] = {0. ,  0.0025,  0.005 ,  0.0075,  0.010  ,  0.015, 0.02 , 0.025, 0.03 , 0.035, 0.04 , 0.045, 0.05 , 0.055
, 0.06 , 0.07 , 0.08 , 0.09 ,  0.1  , 0.11 , 0.120, 0.130, 0.140, 0.150};
 Int_t   binN   = sizeof(bins)/sizeof(Double_t) - 1; // # of Bins

     Double_t edges[] = {};
     Double_t sigma[] = {};
 
 std::vector<Double_t>xbins;
 std::vector<Double_t>xsigma;
  
 Int_t nbin=h->GetNbinsX();
 for (Int_t i = 1; i<=nbin; i++)
     { 
       Double_t xmin  = h->GetBinLowEdge(i);
       Double_t value = h->GetBinContent(i);
       Double_t error = h->GetBinError(i);
       
       Double_t value_mean = 0.5*(h->GetBinContent(i)+h->GetBinContent(i+1));
       Double_t value_error = 0.5*(h->GetBinError(i)+h->GetBinError(i+1));
       
      if (i<=5){xbins.push_back(xmin);
                xsigma.push_back(value/0.0025);} 
               
        else if(i>5 && i%2==0 && i<=20){
               xbins.push_back(h->GetBinLowEdge(i-1)+0.005);
               xsigma.push_back(((h->GetBinContent(i)+h->GetBinContent(i+1))/(2.0*0.0050)));} 
     
        else if(i>20 && i<=60){ 
             if((i-1)%4==0){
               xbins.push_back(h->GetBinLowEdge(i)+0.010);
               xsigma.push_back(((h->GetBinContent(i)+h->GetBinContent(i+1)+h->GetBinContent(i+2)+h->GetBinContent(i+3))/(4.0*0.010)));
                }
               }
                                                              
      }                                   
     
       for (int i = 0; i < xbins.size(); i++){
       cout << xbins[i] <<"\t"<<xsigma[i]<<endl;
       edges[i] = xbins[i];
       sigma[i] = xsigma[i];
       }
//hp2t2->Draw("hist");
//gPad->SetLogy(1);
}
hist->Draw()

But you commented in your macro …

Hi, Thanks!.

Please ignore the hp2t2->Draw(“hist”);

I was unsure about filling the histogram from the vectors (edges, sigma).

Can you tell me how can I define my histogram to fill the edges as the bins and sigma as the bin value?

Thanks in advance!

I am not sure I completelty undersyand you question. It looks like, at creation time, you should define the bins being what you call “edges” and at filling time the weight of each Fill should be the “sigma”? … Or may be you need a 2D histogram ? one axis being edges and the other one sigma ?

but as I said it is just guesses.

May be @moneta will understand better what you mean.

Hi,

I guess you want to fill your new histograms giving the two vectors:
edges and sigma. You can simply do:

std::vector<double> bins = {...............};
TH1D* hp2t2 = new TH1D("hp2t2","",bins.size()-1,bins); 

// assume you have before filled the vectors xbins and xsigma
// and they have the same size

for (unsigned int i = 0; i <  xbins.size() ; i++) {
     hp2t2->Fill(xbins[i],xsigma[i] );
}

Lorenzo

Hi,
Sorry for the late response. Thanks a lot for the help.

Your suggestions work but with a slight change: xbins &xbins[0]

       TH1D* hp2t2 = new TH1D("hp2t2","",xbins.size()-1,&xbins[0]); 
        for (unsigned int i = 0; i <  xbins.size(); i++) { 
            hp2t2->Fill(xbins[i],xsigma[i]);
          }

Note that the last element of “xbins” defines the overflow bin, so the last element of “xsigma” also goes there (in your “for” loop).

Hi, Thanks a lot for that. :slightly_smiling_face:

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