Combine bins with same values while drawing with text in TH2 using "colz text error"

Dear experts,

I am trying to make a heat plot from a (50x50) TH2F. Of course, printing bin content and error in all 2500 bins using TH2F->Draw(“colz text error”) looks clumsy and illegible. However, the TH2F has the feature that several adjacent cells have the same content and error. These coalesced blocks appear randomly in the 2D mesh, so it is not possible to rebin the histogram.

Is there a way to print only one text (with error) for several neighbouring cells whenever they all have the same bin content and error?

Best,
Spandan


ROOT Version: 6.12
Platform: CentOS7
Compiler: Not Provided


Hi Spandan,

why do you want to print any values? For which purpose? Your TH2F is already a “heat plot”, what do you need the values for?

Hi Yus,

I primarily aim to quote the uncertainty in each bin, which I think can be achieved only by using “text err” along with “col”. In addition, printing the precise numbers in every (cluster of) bin would also help reading the data more easily.

I think “heat plot” may not be the right word to describe what I need, my apologies. I am trying to reproduce what one gets by using “colz text error” but with a large number of bins which are inter-mergeable.

Best,
Spandan

No, there is nothing implemented doing that. One would need to create a special script drawing the text that way. Thinking of it it might be a bit tricky. For instance when the adjacent bins do not make a square… imagine they make a line or any other shape… TH2Poly has the TEXT option also. The text is drawn next to the “bin barycentre”.

Hi couet,

thanks for the information. I wrote my own implementation on Python:

def plot(hist,flname,vertical=False):
    c = TCanvas("c","c",800,800)
    c.cd()
    hist.Draw("colz")
    taken = []
    text = TLatex()
    
    for ix in range(1,hist.GetNbinsX()+1):
        for iy in range(1,hist.GetNbinsY()+1):
            if (ix,iy) in taken: continue
            thisblock = [(ix,iy)]
            seed = hist.GetBinContent(ix,iy)
            seederr = hist.GetBinError(ix,iy)
            xend = ix
            
            for ix2 in range(ix+1,hist.GetNbinsX()+1):                
                if hist.GetBinContent(ix2,iy) == seed and hist.GetBinError(ix2,iy) == seederr:
                    thisblock.append((ix2,iy))
                    xend = ix2
                else:
                    break
                    
            reachedYEnd = False
            yend = iy
            
            for iy2 in range(iy+1,hist.GetNbinsY()+1):
                for ix3 in range(ix,xend+1):                
                    if not (hist.GetBinContent(ix3,iy2) == seed and hist.GetBinError(ix3,iy2) == seederr):
                        reachedYEnd = True
                        break
                if reachedYEnd: break
                for ix3 in range(ix,xend+1): thisblock.append((ix3,iy2))
                yend = iy2
                
            taken.extend(thisblock)            
            xcent = (hist.GetXaxis().GetBinLowEdge(ix)+hist.GetXaxis().GetBinLowEdge(xend+1))/2
            ycent = (hist.GetYaxis().GetBinLowEdge(iy)+hist.GetYaxis().GetBinLowEdge(yend+1))/2
            
            text.SetTextAlign(22)
            if vertical: text.SetTextAngle(90)
            text.SetTextSize(.022)
            text.DrawLatex(xcent,ycent,"%4.3f #scale[.8]{#pm %4.3f}"%(seed,seederr))
    
    c.SaveAs(flname)

It seems to work as long as the clusters are rectangular and that serves my purpose. However, having a native implementation in ROOT might be useful.

Thanks,
Spandan

Good. As you said it is a particular case which serves your purpose. To have it in ROOT itself one might need something more general. You are welcome to propose a PR on the ROOT code if you like.

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