Looping over the bins of two 2D hists in a root file

So I have a root file named histfile.root that has two histograms named myhist1 and myhist2. So what I want to do now is loop over the bins of first histogram. Then, loop over the bins of the second histogram in the same order and add these two numbers on a bin-by-bin basis. I know the easier way is to probably just add these two histograms and then look at the bin contents. However, this is a practice exercise for me to understand how to loop over the bins of one histogram and then move on to the second histogram and loop over its bins again.

histfile.root (4.4 KB)

ROOT Version: 5.18
Platform: Ubuntu 18.04
Compiler: Not Provided


Hi,

if the histograms have identical binning, it’s as easy as:

for (auto x=0; ...) {
  for (auto y=0; ...) {
    histo1->GetBinContent(x, y);
    histo2->GetBinContent(x, y);
  }
}

Note that bin #0 is the underflow, bin #nBins+1 is the overflow bin (see TH1 docs I link below). Maybe you want to skip those.

If the binning is not identical, you need to use histo...->GetXaxis()->FindBin(coordinate) link to find the bin index on the x or y axis that corresponds to a certain x or y coordinate.

Helpful resources are:

Hi @StephanH, thank you for your reply. In terms of the things inside the nested loop, I don’t think this is what I want. Perhaps, I phrased the question poorly. So let me ask here what I actually wanted to ask. Let’s say I have 4 histograms with identical binning. Let’s call them hist1, hist2, hist3, hist4. What I want to do is take the first hist, grab all of its bin contents using the

GetBinContent()

method. Then, let’s stay do some operations on those numbers. And only then, move on to the next hist until all the hists are completed. So my rough idea is to have a vector where those four hists are stored and then have a triple nested loop. But I am not sure if what I am thinking of makes sense.

With identical binning, it’s much easier, because you can use single-value bin numbers. The code would look something like:

std::vector<double> bins(histo1->GetNcells());
for (auto histo : std::initializer_list<TH2*>{histo1, histo2, histo3, histo4}) {
  for (int bin = 0; bin < histo->GetNcells(); ++i) {
    const double binContent = histo->GetBinContent(i);
    ... do stuff with each bin, e.g.
    bins[bin] += binContent;
  }
}
1 Like

Hi @StephanH, do you mind explaining what the part

histo1->GetNcells()

is supposed to do? Cause when I load the root file and try something like this:

Int_t x = histo1->GetNcells()

it gives me an error saying

Error: Can’t call TH2D::GetNcells() in current scope (tmpfile):1:
Possible candidates are…
(in TH2D)
(in TH2)
(in TH1)
*** Interpreter error recovered ***

Thanks a lot.

It literally gets the number of cells in the histogram. Every histogram (TH1x, TH2x, …) has it:
https://root.cern.ch/doc/master/classTH1.html#a588785f73495e46d76064496254347c7

If it doesn’t work, this indicates that you tried to call this method on something that’s not a histogram.

1 Like

The root file that I attached in the main question does have two histograms, and I even tried plotting them, which works. The GetNcells() method,however, gives the same error.

And I also tried just drawing a 1D hist in ROOT and calling the function to see what happens. Still the same error.

Which ROOT version?

root [0] TH1D histo("x", "x", 10, 0, 10)
(TH1D &) Name: x Title: x NbinsX: 10
root [1] histo.GetN<Invoke Tab completion>
GetName
GetNbinsX
GetNbinsY
GetNbinsZ
GetNcells
GetNdivisions
GetNormFactor
root [1] histo.GetNcells()
(int) 12

Oh, I saw it now. 5.18 …

That’s probably more than 10 years old, so a lot might have changed in the mean time. You can probably try to do histo->GetNbinsX() * histo->GetNbinsY() * histo->GetNbinsZ() etc instead, but you have to manually keep track of how many dimensions the histogram has.