Overlaying histograms with pyROOT

Hi Danilo,

Thanks for your reply! I have made some progress since my initial post. I feel I am very close to getting the result I need, but have been hung up on one problem.

To clarify, I have multiple ROOT files. Each file contains a canvas with several histograms like in the first post. From each canvas of the different ROOT files, I am trying to extract the same histogram and overlay them on one another. I am using pyROOT to accomplish this. My code currently looks like:

import ROOT

def overlay():

    # List of predefined ROOT color constants
    '''color_constants = [
    ROOT.kBlack, ROOT.kWhite, ROOT.kRed, ROOT.kGreen, ROOT.kBlue,
    ROOT.kYellow, ROOT.kMagenta, ROOT.kCyan, ROOT.kOrange, ROOT.kPink,
    ROOT.kGray, ROOT.kAzure
    ]'''

    i = 0
    for run in range(1050, 1054, 2):
        path = f"Baylor/root/local_runs/{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(26)
        # Get the histogram
        hist = pad.GetPrimitive("ChargeHB3-2-3-1")

        # Print histogram statistics to verify content
        print(f"Histogram entries: {hist.GetEntries()} for run {run}")
        if hist.GetEntries() == 0:
            print(f"Histogram is empty for run {run}")
            continue

        if i == 0:
            new_canvas = ROOT.TCanvas("overlay_canvas", "Overlay of Histograms", 800,600)
            hist.Draw()
        else:
            hist.Draw("SAME")

        i += 1
        file.Close()
    
    new_canvas.Update()
    new_canvas.SaveAs("testCanvas.jpg")
    new_canvas.SaveAs("testCanvas.png")
    new_canvas.SaveAs("testCanvas.pdf")

overlay()

What results is only the first histogram:

However, if I were to avoid using the loop and hard code the different root files, I (basically) get the kind of plot I’m looking for:

What is the deal here? For reference the code for the correct plot is:

import ROOT

def overlaytest():
    file1 = ROOT.TFile.Open("Baylor/root/local_runs/1050_2023_HB3_ped.root")
    file2 = ROOT.TFile.Open("Baylor/root/local_runs/1052_2023_HB3_ped.root")
    
    canvas = file1.Get("HB3Charge/HB3/HB3-2-Charge") # HB3Charge/HB3/HB3-2-Charge_1/ChargeHB3-2-0-0     HB3Trend/HB_ADCvsBX
    pad = canvas.GetPad(26)
    h1 = pad.GetPrimitive("ChargeHB3-2-3-1")
    h1.SetLineColor(ROOT.kRed)

    canvas2 = file2.Get("HB3Charge/HB3/HB3-2-Charge")
    pad2 = canvas2.GetPad(26)
    h2 = pad2.GetPrimitive("ChargeHB3-2-3-1")
    h2.SetLineColor(ROOT.kBlue)

    # Check the type of the retrieved object
    if isinstance(h1, ROOT.TH1):
        print("The object retrieved is a histogram.")

    new_canvas = ROOT.TCanvas("TEST", "imported canvas", 800,600)
    h1.Draw()
    h2.Draw("SAME")

    # Legend things
    legend = ROOT.TLegend(0.7, 0.7, 0.9, 0.9)
    legend.AddEntry(h1, "Histogram 1", "l")
    legend.AddEntry(h2, "Histogram 2", "l")
    legend.Draw()

    new_canvas.Update()
    new_canvas.SaveAs("testCanvas1.jpg")
    new_canvas.SaveAs("testCanvas1.png")
    new_canvas.SaveAs("testCanvas1.pdf")
    file1.Close()

overlaytest()

I could hardcode all the files, but there are many and I would much prefer to make the code more modular by using a loop, especially since all the file names are standardized.

Thanks!
–Ben