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
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
This is very useful but as far as I can make out it lists everything in the root file, ignoring the basepath.
I think if you add sd = d.Get(basepath) and then do for key in sd.GetListOfKeys(): it should work, although I then got an error with o.ClassName() (Iâm not sure what this was doingâŚ)
This works for me, anyway:
def getall(d, basepath="/"):
"Generator function to recurse into a ROOT file/dir and yield (path, obj) pairs"
sd = d.Get(basepath)
for key in sd.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)