Slow Canvas with histo from rootFile

Hi everyone!

I have two scenarios for creating a histo:
a) get histo from .txt file with bin contets
b) storing the histo a) in a .root file for some reason and later on reading the histo from the .root file again.

The problem appears now when drawing the histo from scenario b) to a TCanvas. The graphics are very slow compared to creating the same histo from scenario a). For example zooming in takes like 3 seconds!

I tried many things to search for the reason, but none helped:

  1. h.SetDirectory(0) after creation
  2. h.Clone(“name”)
  3. closing the opened TFile before showing the histo in the TCanvas
  4. changing the directory, where the .root File is stored from server to local
  5. All permutaions from point 1) - 4)

If anyone has ideas …?! [-o<
Cheers,
Daniel

Loading the histogram from a ROOT file or building it from a txt file should not make any difference regarding the drawing speed. Do you have the same problem using the normal ROOT (not PyROOT) ?

Hi,

there may be reasons why responsiveness from PyROOT is less than from ROOT (GUI events are dispatched from a separate thread, which will give some extra overhead), but there should be no difference b/c of the source of the histogram.

Can you be more specific (e.g. with code or the file that you use)?

Cheers,
Wim

Hi! Even if I start a TBrowser (From real ROOT), this behaves as described.

I add some pseudo code, which will of course not run as it is. The two options a and b can be chosen here:

import ROOT
import input
import output
from someModule import getTH1FFromTxtFile

global inputPath
inputPath = "Test"

def getSpectrum(name,recreate = False):
    if not recreate:
        In = input.RootInput(inputPath)
        spectrum = In.getTH1F(name)
        spectrum.SetDirectory(0) #Keeps the spectrum allive after In.close()
        In.close()
        return spectrum
    else:
        #Build histo Class with filePath
        h = getTH1FFromTxtFile(name,filePath)
        h.Sumw2()

        #Calibrate each Histo with some routine

        #Scale each hist with some scale
        scale = 1.
        h.Scale(scale)
        #Than I also correct the bin Error, since scale has an uncertainty
        return h

Out = output.RootOutput()
Out.create(inputPath)
h = getSpectrum("foo",recreate = True)
Out.write(h)
Out.close()


if optionA:
    h = getSpectrum("foo", recreate = True)
elif optionB:
    h = getSpectrum("foo", recreate = False)

h.Draw()
raw_input("HISTO IS SHOWN")

where input.py is

import ROOT

class Input(object):
    def __init__(self,savePath):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement __init__")
    def getTH1F(self,name,path = None):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement getTH1F()")
    def getTF1(self,nam,path = None):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement getTF1()")
    def close(self):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement close()")


class RootInput(Input):
    def __init__(self,savePath):
        self.inputFile=ROOT.TFile(savePath + ".root", "READ")
        if self.inputFile.IsZombie():
            print "Input File is Zombie. Quit()!"
            quit()
    def getTH1F(self,name,path = None):
        if not path is None:
            name = path + "/" + name
        try:
            obj = self.inputFile.Get(name)
            if issubclass(obj.__class__,ROOT.TH1F):
                return obj
            else:
                raise
        except:
            print "Could not find TH1F with name %s" % name
        return None
    def getTF1(self,name = None,path = None):
        if not path is None:
            name = path + "/" + name
        try:
            obj = self.inputFile.Get(name)
            if issubclass(obj.__class__,ROOT.TF1):
                return obj
            else:
                raise
        except:
            print "Could not find TF1 with name %s" % name
        return None
    def close(self):
        self.inputFile.Close()
    def ls(self,selectType = None):
        return [key.GetName() for key in ROOT.gDirectory.GetListOfKeys()]
    def cd(self,directory = ""):
        self.inputFile.cd(directory)

where output.py is

import os
import numpy
from array import array
import ROOT
import shelve
import input

class Output(object):
    def create(self,savePath):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement create()")
    def open(self,savePath):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement open()")
    def write(self,content,path = None):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement write()")
        return False
    def close(self):
        raise NotImplementedError("Class " + self.__class__.__name__ + " must implement close()")


class RootOutput(Output):
    def create(self,savePath):
        self.outputFile=ROOT.TFile(savePath + ".root", "RECREATE")#Overwrites
    def open(self,savePath):
        self.outputFile=ROOT.TFile(savePath + ".root", "UPDATE")  #Appends
    def write(self,content = None,path = None):
        if not path is None:
            self.outputFile.mkdir(path)
            self.outputFile.cd(path)
        if content is None:
            self.outputFile.Write()
            self.outputFile.cd()
            return True
        try:
            content.Write()
            self.outputFile.cd()
            return True
        except:
            print "In ROOTOUTPUT: Content has no method \"Write\""
            self.outputFile.cd()
            return False
    def close(self):
        self.outputFile.Close()

I hope this was helpfull, but i could not imagine of a better way to break the whole thing down.
Cheers,
Daniel