Saving histograms in a list using PyROOT

Hello, I am opening a number of root files and accessing one histogram per root file. I would like to saves these histograms in a list and then later draw them all on the same histogram (after normalising). The code I have below does not work. Does anyone see the problem or can anyone suggest an alternative way to do this?

import ROOT

run_numbers = [1378, 1439, 1530, 1573, 1614, 1655, 1712, 1762, 1826, 1876, 1910, 1942, 1973, 2014, 2098]
hist_array = []

for i in range(len(run_numbers)):
    path_to_file = "output/single_run_" + str(run_numbers[i]) + ".root"
    rootfile = ROOT.TFile.Open(path_to_file)
    hist = rootfile.Get("AnalysisDUT/tp2_0/clusterChargeAssociated")
    rebin_factor = 8
    hist_rebinned = hist.Rebin(rebin_factor)
    hist_name = "run "+str(i)
    c1 = ROOT.TCanvas("c1", "", 800, 600)
    hist_rebinned.Draw()
    c1.Print("check_plot"+hist_name+".png")
    hist_array.append(hist_rebinned)
    rootfile.Close()


output_file = ROOT.TFile("array.root", "RECREATE")
c2 = ROOT.TCanvas("c2", "", 800, 600)
for i in range(len(hist_array)):
    if i ==0:
        hist_array[i].Draw()
    else:
        hist_array[i].Draw("same")
c2.Write()
output_file.Close()

When I run this, I successfully get the png’s but I get the error below when it tried to plot them all on the same canvas when looping the list I created.
Traceback (most recent call last):
File “*.py”, line 24, in
hist_array[i].Draw()
AttributeError: ‘CPyCppyy_NoneType’ object has no attribute ‘Draw’

Instead of adding them to a list, add them to THStack (in that same loop), then just draw the THStack. See this recent post with a similar case:

Yes–I also attempted adding them to a list at first–didn’t work. The THStack solved the problem. Here is an excerpt from my working code (with the exception of the file path) to give you an idea:

    c_i = 0
    l_i = 0
    for run in runs:
        path = f"/path/to/files/{run}_2023_HB3_ped.root"
        print(f"Opening file: {path}")

        # Select the file from which to extract histogram
        file = ROOT.TFile.Open(path)
        # Get the correct canvas from the file
        canvas = file.Get("HB3Charge/HB3/HB3-2-Charge")
        # Get the correct pad
        pad = canvas.GetPad(pads[tileindex]) #26 for tile 1
        # Get the histogram
        hist = pad.GetPrimitive(padnames[tileindex]) #"ChargeHB3-2-3-1" for tile 1
        
        # For some reason, color corresponding to 10 is invisible.
        if c_i == 9:
            c_i += 1

        hist.SetLineColor(c_i+1)
        # Add histograms to stack
        stack.Add(hist)

        legendEntry = "Run " + str(run) + ", T = " + str(temps[l_i]) + " C"
        legend.AddEntry(hist, legendEntry, "f")

        c_i += 1
        l_i += 1

Note that in my case, the histograms I was pulling from were drawn on a pad, so I had to account for that whereas you may not.

After adding all your histograms to the stack, you will create a ROOT.TCanvas and then stack.Draw("hist"). I also did a lot of axis adjustments to ensure all the histograms would automatically fit comfortably in the viewing window.

Hope this helps!

Thank you for this suggestion. I have written the below code but when I plot the stack, there is only the axis and the plot is empty.

import ROOT

run_numbers = [1378, 1439, 1530, 1573, 1614, 1655, 1712, 1762, 1826, 1876, 1910, 1942, 1973, 2014, 2098]
hist_array = []

hs = ROOT.THStack("hs", "Stacked Histograms")

for i in range(len(run_numbers)):
    path_to_file = "output/single_run_" + str(run_numbers[i]) + ".root"
    rootfile = ROOT.TFile.Open(path_to_file)
    hist = rootfile.Get("AnalysisDUT/tp2_0/clusterChargeAssociated")
    rebin_factor = 8
    hist_rebinned = hist.Rebin(rebin_factor)
    hs.Add(hist_rebinned)
    rootfile.Close()


output_file = ROOT.TFile("output.root", "RECREATE")
c2 = ROOT.TCanvas("c2", "", 800, 600)
hs.Draw("nostack,e1p")
c2.Write()
output_file.Close()

If I plot within the loop for example, if i ==6: plot… as above. Then I do get a single histogram only for i==6 and the previous histograms are missing. Any ideas?

This code is basically the same you have for plotting a stack and saving, and works fine for me on ROOT 6.32/02:

import ROOT

hs = ROOT.THStack("hs","")

h1 = ROOT.TH1F("h1","test hstack",10,-4,4)
h1.FillRandom("gaus",20000)
h1.SetFillColor(2)
h2 = ROOT.TH1F("h2","test hstack",10,-4,4)
h2.FillRandom("gaus",15000)
h2.SetFillColor(4)

hs.Add(h1)
hs.Add(h2)

output_file = ROOT.TFile("output.root", "RECREATE")
c = ROOT.TCanvas("c","c",10,10,600,600)
hs.Draw("nostack")
c.Write()
output_file.Close()

Maybe you are not getting the histograms correctly from the file/s, or the binnings are not the same (or your input file is damaged, or something else!). Check one by one and make sure all is as you expect.

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