while I have been using python to analyse existing ROOT trees for quite a while now (a big THANK YOU is in order for the great work!), I was trying to build a TTree inside a python macro for the first time and ran into trouble:
I want to fill a Tree with a single branch containing a relatively simple Data container class (“TpcWaveform”) deriving from TObject. A dictionary has been built into a library and is loaded at startup. I fill the tree like this:
tree = ROOT.TTree("waveforms", "GEM-TPC Waveforms")
tpcWF = ROOT.TpcWaveform()
tree.TpcWaveform = tpcWF
Then inside the loop over my data, I set the data fields of my tpcWF handle and call tree.Fill(). The filling of the trees seems to run fine.
However, when reading them, I immediately run into problems. Most of the trees (but not all!) give me segfaults when accessing the entries (e.g. with tree->GetEntry(i) in CINT).
Is the way I am filling the tree correct? My ROOT version is 5.32
in principle yes, although the Branch() call does not need that second argument (the class name), as the reflection layer can figure out the type from the object. Is the dictionary loaded (or auto-loadable) when reading back in root.exe? Any pointer data members, or arrays, in the TpcWaveform? Also, do you have a stack trace of the segfault?
thanks for the fast reply!
However, I think the problem has been resolved. I was being sloppy and had a char* member that was not initialized in the default constructor, which I call once for pinning down the branchAddress in my tree reading script:
wf = ROOT.TpcWaveform() #!!!!!!
… sigh. Would that explain the problems when reading objects with already set char arrays? At least this explanation fits the randomness of my problems.
Sorry for stirring the waters on this one. I fixed my constructors and banished the char* in favor of an stl string, what I should have done in the first place.
It seems to run now (and fast! So far I have always used the “for e in tree” looping style instead of the old CINT-Style SetBranchAddress).
yes, I’d expect an uninitialized char* to spell trouble.
As for “for e in tree”, that’s slow in CPython b/c I’ve never found a way of reliably caching the results, and for non-object data, there’s AFAIK now way of caching in the first place. This is a different matter in pypy-c, where that idiom runs at speeds of optimized, compiled C++.