TTimer and PyRoot

I was wondering today if it is possible to use the TTimer class in pyroot. I would like to make a progress bar for TTree draw.

I was attempting to use the Notify() function, making a python class which inherits of TTimer, but this did not work for me

import ROOT

class MyTimer(ROOT.TTimer):
   def __init__(self):
      ROOT.TTimer.__init__(self, 1000, True)
      self.counter = 0
      ROOT.gSystem.AddTimer(self)
      self.Notify()
   def Notify(self):
      print self.counter
      self.counter +=1
      self.Reset()
      return False

t = MyTimer()
t.TurnOn()


raw_input()

any ideas what the best way to do this in python is?

1 Like

This example works.

Inspiration is here.

I am not sure if it has the correct return value.

import ROOT
code = """
#include "TTimer.h"
#include "Python.h"
#include <stdexcept>
Bool_t call_python_method(PyObject* self, const char* method)
{
   // check arguments
   if ( 0 == self || 0 == method ) { throw std::runtime_error("Invalid Python object and method"); }
   // call Python
   PyObject* r = PyObject_CallMethod(self, const_cast<char*>(method), const_cast<char*>(""));
   if ( 0 == r ) { PyErr_Print(); return false;}
   // release used objects
   Py_XDECREF( r ) ;
   //
   return r;
}

class PyTimer : public TTimer {
 public:
   PyTimer(PyObject* self, Float_t ms, Bool_t mode) : TTimer(ms, mode), fSelf(self) {}
   virtual ~PyTimer() {}
   virtual Bool_t Notify() { return call_python_method(fSelf,"Notify"); }
 private:
   PyObject* fSelf;
};
"""

ROOT.gInterpreter.ProcessLine(code)

class MyTimer(ROOT.PyTimer):
   def __init__(self):
      super(MyTimer, self).__init__(self, 1000, True)
      self.counter = 0
      ROOT.gSystem.AddTimer(self)
      self.Notify()
   def Notify(self):
      print self.counter
      self.counter +=1
      self.Reset()
      return True

t = MyTimer()
#t.TurnOn()


raw_input()

The following is wrong:

   if ( 0 == r ) { PyErr_Print(); return false;}
// release used objects
   Py_XDECREF( r ) ;
   //
   return r;

First, if r == 0, that doesn’t mean false. It means there is some problem in your python code and you may want to let the code return a python exception instead (throw TPyException, from $ROOTSYS/include/TPyException.h).

Second, you don’t need Py_XDECREF, as you just checked for nullptr, so use Py_DECREF.

Third, technically you can’t rely on what ‘r’ is anymore when returning as the macro could have set it to nullptr. It doesn’t, but you can’t know, so you should consider ‘r’ undefined after the DECREF.

Fourth, ‘r’ will be C++ non-zero if there is no python error, but that just means it will be Py_True or Py_False. You should either pointer-compare it directly or check for Python non-zero using PyObject_IsTrue().

Thanks. I can give it some improvments based on that.

I am having problems with this in different environments. Could someone confirm this works with
it works with

/cvmfs/cms.cern.ch/slc6_amd64_gcc493/cms/cmssw-patch/CMSSW_8_0_24_patch1/external/slc6_amd64_gcc493/bin/python

but not
/cvmfs/cms.cern.ch/slc6_amd64_gcc530/cms/cmssw-patch/CMSSW_8_0_24_patch1/external/slc6_amd64_gcc530/bin/python

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.