Hi,
there’s currently no way to do that from PyROOT: the only OnPartialResult implementation accepts a C++ callable and there are no pythonizations that convert the python callable into a C++ callable.
You can of course make it work by embedding C++ code in your python code and jit it with ROOT.gInterpreter.ProcessLine. I realize this is awkward at best.
@etejedor or @swunsch might be able to comment about better ways to solve this problem that might be coming in the future.
Thank you for your reply. The main limitation, in this case, of ROOT.gInterpreter.ProcessLine is that I want my python variables to update during the loop. Is there any way to store variables such that both my python script and gInterpreter can access them? E.g., in the following, I want gInterpreter to recognize the symbol t:
f = ROOT.TFile('...')
t = f.Get('...')
ROOT.gInterpreter.ProcessLine('cout<<t.GetEntries()<<endl;')
ROOT.gInterpreter.ProcessLine('auto f = TFile::Open("..."); TTree *t; f.GetObject("....", t);')
ROOT.t.GetEntries() # works
ROOT.gInterpreter.ProcessLine('cout << t.GetEntries() << endl;') # also works
As a side note, remember that all python code is executed under the GIL and therefore sequentially even in multit-thread programs.
And: passing python callables to C++, or C++ callables to C++ from PyROOT is getting easier thanks to @swunsch, so maybe in the future we’ll have a simpler way to do it.
Note that depending on your use case, that progress bar might have a visible runtime cost: you are calling python 3 times per entry per thread, and those calls all hit the GIL. Or not: if 99.9% of the time is spent elsewhere, that callback might not impact runtimes at all.
In case you measure, please let us know whether that’s the case – I’m curious.
Done. I timed it by comparing the runtime when I call the python value vs. including it as part of the string.
Calling freq using TPython::Eval took 1.11219000816 s. Just using the string took just 0.444277048111 s.