Create histogram with a varying binning knowing BinCenter


ROOT Version: 6.18/04
Platform: Ubuntu 18.04
Compiler: gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)


Dear co-rooters,

Is there a way to create a TH1 with variable binning when knowing only the bin centers?

I have a file with (x,y) values

1.0 55
1.1 100
1.5 2
1.6 14
1.7 33
1.9 88
2.0 53

In a TGraph the 1st column would be the x-values and the 2nd the y-values.
However, I’d ike to have a histogram with the above data where the 1st column should be the bin center and the 2nd the bin content.

Since the binning isn’t linear, the only way I can think of is to use the TH1::TH1 (const char* name, const char* title, Int_t nbins, const Float_t* xbins) constuctor. But then xbins are the low edges of the bins.

Trying to calculate the low edges in a way that the first column values, would be the bin centre isn’t straight forward because after a point data will be excluded:

Centre Low Edge Upper Edge
  1.0    0.95      1.05
  1.1    1.05      1.15
  1.5    1.15      1.85
  1.6    ???       ???

IAny idea on how to do that?

Thanks in advance!

If you don’t want to see empty bins, with the variable bins you cannot generally keep the original bin centres (which by deinition means symmetrical low/high edges around those centres), as you alreay found out when reaching 1.6

I’m not sure there’s a proper option other than either using new bin centres (and therefore some of your original points will probably get binned together), or just living with the empty bins :slight_smile:

If you define your own bin edges carefully (with the new bin centres different from your original centres, of course), then you could try hiding the axis labels and manually (TLatex or TText) printing your custom ‘bin labels’ at the correct positions, but then the bin edges will not be symmetrical around those labels, e.g.:
|_1.0_|_1.1________|____1.5_|...

If you don’t care about the statistics or other info on the histogram, as workaround you could try to hide or disguise the empty bins, e.g. filling 1.2 and 1.3 with the same value as 1.1 (100), and 1.4 with the same as 1.5 (2), so that they may seem to be the same bin.

1 Like

Hi,
maybe you could set the first low edge as center[0] - 0.1, the last edge as center[-1] + 0.1 (where with center[-1] I mean the last of the bin centers) and all other low edges as center[i] + center[i+1] / 2?

Thanks for your reply. The thing is that I do care about statistics and empty bins isn’t an option. I’m most probably limited.

Thanks for your reply.
It doesn’t seem to work.
I’ll provide a true file of what I’m trying to and a code snippet.

My code is

#include "TH1F.h"[data.txt|attachment](upload://wkEneYhpHHAyNb0bDTElptGNzUe.txt) (19.3 KB) 

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

void compare_data(){


	vector<double> En, XS;
	double         E,  xs;
	
	ifstream f_in;

// Open file
	f_in.open("data.txt");
	while(1){
  		f_in >> E >> xs ;
		if( !f_in.good() ) break;
		En.push_back(E);
		XS.push_back(xs);		
	}
	
	f_in.close();

	vector<double> En_low_edges( En.size() );
	En_low_edges[0]           = En[0] - (En[1]-En[0]);
	En_low_edges[En.size()-1] = En[En.size()-1] + (En[En.size()-1] - En[En.size()-2]);
	for (int i=1; i<En.size()-2; ++i){
		En_low_edges[i] = En[i] + En[i+1]/2.;
	}
	
    ofstream f_out("bins.txt", std::ofstream::out);

	TH1F *h = new TH1F("h", "", En_low_edges.size()+1, En_low_edges.data());
	for (int i=0; i<h->GetNbinsX(); ++i){
		h->SetBinContent(i+1, XS[i]);
        f_out << En[i] << "\t" << En_low_edges[i] << "\n";
	}

	h->Draw("histo");	
}

When I do that I get the following error in TAxis

Error in <TAxis::TAxis::Set>: bins must be in increasing order
Error in <TAxis::TAxis::Set>: bins must be in increasing order

And then the low edges are larger then the bin centers past a certain point.
I printed out the centers and the low edges in a file to inspect.

data.txt (19.3 KB)
bins.txt (11.1 KB)

Here

TH1F *h = new TH1F("h", "", En_low_edges.size()+1, En_low_edges.data());

the last parameter must have Nbins+1 elements, because you have to provide as last element the upper limit of the last bin.

Yes, you are right on that.

Also if you check the bins.txt file I uploaded it’s evident that this approach doesn’t work.
For instance the largest bin center is 100000 (line 700, 1st column) but the low bin edges exceed this number.

bins.txt (11.1 KB)

Sounds like a bug in the code?

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