I’m trying to use PyRoot to process a TChain, but am getting some weird results. Basically everything works fine for the first file in the chain, but after that the last event from the first file in the chain is loaded every time. The TChain object appears properly formed as chain.GetEntries() gives the correct number for total events in the chain.
In the following “test.C+” is a vanilla TSelector generated using MyTree->MakeSelector(“test”) from within root, modified only to print the event number for each event.
from ROOT import TChain, TSelector, TTree
chain = TChain("CollectionTree")
for line in file("input.list"):
print "Adding file: " + line
chain.AddFile(line[:-1])
#chain.Process("VBFcuts.C+")
selector = TSelector.GetSelector("test.C+")
selector.Init(chain)
selector.Begin(chain)
for i_event in range(0,chain.GetEntries()):
selector.Process(i_event)
selector.Terminate()
chain.Process(selector)[/code]but your code is also missing some significant part (in particular the part insuring a smooth transition from file to file).
doesn’t seem to work in PyRoot. The following error occurs:
Traceback (most recent call last):
File "runAnalysis.py", line 15, in ?
chain.Process(selector)
TypeError: Long64_t TChain::Process(const char* filename, Option_t* option = "", Long64_t nentries = kBigNumber, Long64_t firstentry = 0) =>
could not convert argument 1 (expected string or Unicode object, test found)
ie it seems PyRoot will only accept the name of a file containing a TSelector, rather than also accepting a TSelector object (as in ROOT).
The reason I’m doing it this way is I want to be able to call some extra member functions of the TSelector first.
I was under the impression that once one had added a list of files to a TChain, ROOT handled the file transition when looping over events? If not, how do I go about this?[/code]
[quote]I was under the impression that once one had added a list of files to a TChain, ROOT handled the file transition when looping over events? [/quote]Yes, it does. It is the use of TSelector that is not quite correct.
The following add a couple of essential calls (in particular note that the parameter to selector.Process is not supposed to be the entry in the chain but instead it should be the entry within the current TTree.
for i_event in range(0,chain.GetEntries()):
entryNumber = chain.GetEntryNumber(entry);
localEntry = fTree->LoadTree(entryNumber);
if (localEntry >= 0):
selector.Process(localEntry)
Incidentally, do you know why calling TChain::Process(TSelector* selector…) doesn’t work in pyroot? Is this a bug or something that hasn’t been implemented yet?
[quote]Incidentally, do you know why calling TChain::Process(TSelector* selector…) doesn’t work in pyroot? Is this a bug or something that hasn’t been implemented yet?[/quote]It is not implemented yet. In order to support the case of interpreted class that inherit from TSelector, we implemented a special treatment for TTree::Process in CINT and this special treatment prevent PyRoot from providing access to it with also special casing the support of TTree::Process in PyRoot.
TTree::Process() is added back to the dictionary, yes, but the normal TChain::Process() still hides it. Not sure why CINT can pick up the TTree one, since C++ rules say that the derived class method will hide the base one …
I’ll cover it in Pythonize.cxx (and just done so, by pretending that TChain has a “using TTree::Process”), but for now you can work around it by doing:c = TChain()
TTree.Process( c, myselector )
I.e. call the base class TTree::Process directly.