Loop over all objects in a ROOT file

After having looked for a hint in the forum, I found this thread
http://root.cern.ch/phpBB3//viewtopic.php?f=3&t=7246&p=30333

Here I post my version of the small pyroot function, where you can specify a folder path inside the ROOT file.

def GetKeyNames( self, dir = "" ):
        self.cd(dir)
        return [key.GetName() for key in gDirectory.GetListOfKeys()]
TFile.GetKeyNames = GetKeyNames

keyList = f.GetKeyNames(internalPath)
print "\nKeys in file:", keyList

I post it here, with an explicit subject, since it might be useful to other users as well.

Cheers,

Ric.

1 Like

This is great, Thanks!

Today i needed somehow to have into a list all the objects’ paths so i can access any object with dDirectory.Get(‘path_to_object’)(in python code NOT in c++).

So i needed to have dynamically all the object’s path from the root file, that how you list all the objects’ path (directories,subdirectories etc all of them,not just the names of the keys in the current path)

[code]def getObjectsPaths(self):
mylist = []
for key in gDirectory.GetListOfKeys():
mypath = gDirectory.GetPathStatic()
self.filterKey(key,mypath,mylist)
gDirectory.cd(mypath)

return mylist

def filterKey( self, mykey , currentpath, tolist):
if mykey.IsFolder():
if not currentpath.endswith(’/’):
currentpath+=’/’

     topath =  currentpath+mykey.GetName()  
     self.cd(topath)
     for key in gDirectory.GetListOfKeys():
          self.filterKey(key,topath,tolist)
 else:
     tolist.append(gDirectory.GetPathStatic()+'/'+mykey.GetName())
     return

TFile.filterKey = filterKey
TFile.getObjectsPaths = getObjectsPaths

refFile = TFile( ‘my_file.root’ )

yo = refFile.getObjectsPaths()

for path in yo:
print path[/code]

I know maybe it’s a dirty way to do it , or maybe there is a simpler-better way to do it but i’m not willing to read documentation because i don’t really use ROOT( i just need it in some parts into my code) , i thought that maybe someone would find this piece of code useful , because there are no python example codes using pyROOT and for this simple thing i killed some hours just looking a way to do it just because there are no examples in python

I just found this thread and thought I’d post an alternative, I think neater solution. All the intelligence is in the ~7 line getall function. I’ve not checked whether it’s particularly memory efficient since it runs perfectly fast for my current need, which is to just list ROOT all file contents… but being a generator it at least doesn’t try to put all the objects in memory at the same time!

import ROOT

def getall(d, basepath="/"):
    "Generator function to recurse into a ROOT file/dir and yield (path, obj) pairs"
    for key in d.GetListOfKeys():
        kname = key.GetName()
        if key.IsFolder():
            # TODO: -> "yield from" in Py3
            for i in getall(d.Get(kname), basepath+kname+"/"):
                yield i
        else:
            yield basepath+kname, d.Get(kname)


# Demo
ROOT.gROOT.SetBatch(True)
f = ROOT.TFile("mydata.root")
for k, o in getall(f):
    print o.ClassName(), k

# Output
# TH1D /Nominal/Vertex/RawLeadPt0
# TH2D /Nominal/Vertex/RawSumPt_leadPt_To0
# ...
# TH1D /Nominal/Vertex/RawSumPt_DeltaPhi_lexc0
# TH2D /Nominal/Vertex/RawSumPt_Ramp_TrMin_TrMax0
# ...
# TH1D /Up_Material/Vertex/RawLeadPt0
# TH2D /Up_Material/Vertex/RawSumPt_leadPt_To0
# ...

I’ve expanded this into a “rootls” script at pastebin.com/GebcyHY9 (cf. YODA’s yodals).

Since I found both replies being broken in my case. In particular, IsFolder() returns True for TTree, GetListOfKeys() chokes with TTree, etc, so pasting my longer solution here:

import ROOT

def Map(tf, browsable_to, tpath=None):
    """
    Maps objets as dict[obj_name][0] using a TFile (tf) and TObject to browse.
    """
    m = {}
    for k in browsable_to.GetListOfKeys():
        n = k.GetName()
        if tpath == None:
            m[n] = [tf.Get(n)]
        else:
            m[n] = [tf.Get(tpath + "/" + n)]
    return m

def Expand_deep_TDirs(tf, to_map, tpath=None):
    """
    A recursive deep-mapping function that expands into TDirectory(ies)
    """
    names = sorted(to_map.keys())
    for n in names:
        if len(to_map[n]) != 1:
            continue
        if tpath == None:
            tpath_ = n
        else:
            tpath_ = tpath + "/" + n
        
        tobject = to_map[n][0]
        if type(tobject) is ROOT.TDirectoryFile:
            m = Map(tf, tobject, tpath_)
            to_map[n].append(m)
            Expand_deep_TDirs(tf, m, tpath_)

def Map_TFile(filename, deep_maps=None):
    """
    Maps an input file as TFile into a dictionary(ies) of objects and names.
    Structure: dict[name][0] == object, dict[name][1] == deeper dict.
    """
    if deep_maps == None:
        deep_maps = {}
    if not type(deep_maps) is dict:
        return deep_maps
    
    f = ROOT.TFile(filename)
    m = Map(f, f)
    Expand_deep_TDirs(f, m)

    deep_maps[filename] = [f]
    deep_maps[filename].append(m)
    
    return deep_maps