OOP histogram plotting in pyROOT

I’m very new to OOP in python but I want to create the same series of plots for different root files, and I already had a python script which made the histograms I wanted so I decided to try to make the histogram definitions into a class and plot them from another program which calls the class.

My class is defined like this:

class RunAnalysis:
    def __init__(self,run_no):
        self.run_no = run_no
        self.file_path=os.path.join("/Users/bethlong/Downloads/", f"Run{self.run_no}_HistoFile.root")
        self.root_file = TFile(self.file_path,"read")

    def canvas_creator(self, canv_name):
        my_canvas = TCanvas(canv_name,canv_name,900,700)
        return my_canvas

and I call it like this:

from TargetRunAnalyser import RunAnalysis
import ROOT

def main():
    RunsToAnalyse = [50252,50305]
    Analysers = [RunAnalysis(run) for run in RunsToAnalyse]

    canvas_x_signals = [analyser.canvas_creator(f"x_signals_{analyser.run_no}") for analyser in Analysers]
    [canv.Update() for canv in canvas_x_signals]
    
if __name__ == '__main__':
    main()

The same thing happens if I use an explicit for loop:

    for canv in canvas_x_signals:
        canv.Modified()
        canv.Update()

But this doesn’t print anything when I run it in an interactive session - the root icon pops up but there aren’t any actual canvases shown.

Can anyone help me? It would kind of defeat the purpose of making the class if I had to draw each canvas separately…

Thanks in advance!

Hi,

Thanks for the interesting post.
A few questions to move forward:

  • Do you mean that when you run your python program you get the plots you are interested in and when you copy the code on the prompt you do not?
  • What ROOT version are you using on what platform?
  • Can you provide a standalone reproducer of the behaviour you’d like to avoid?

Cheers,
Danilo

I’m working on MacOS 14.4, python 3.12 root 6.30.04.

I’m not sure I understand the first question but in my python3.12 -i session I don’t see anything at all. The root icon pops up, but there are no root windows actually opened.

Here’s a MWE:

from ROOT import TCanvas

class myclass:
    def __init__(self,run_no):
        self.run_no = run_no

    def canvas_creator(self, canv_name):
        my_canvas = TCanvas(canv_name,canv_name,900,700)
        return my_canvas

def main():
    instances = [myclass(x) for x in range(2)]

    canvas_x_signals = [instance.canvas_creator(f"x_signals_{instance.run_no}") for instance in instances]
    for canv in canvas_x_signals:
        canv.Modified()
        canv.Update()
  
if __name__ == '__main__':
    main()

Maybe:

    for canv in canvas_x_signals:
        ROOT.SetOwnership(canv, False)
        canv.Modified()
        canv.Update()
2 Likes

Thank you!