2. Overview

The python dynamic language is widely used for scientific programming, including high performance and distributed parallel code (for reference, see the projects on http://www.scipy.org). It is the second most popular dynamic language (after perl) and enjoys a wide-spread use as a "glue language": practically every library and application these days comes with python bindings (and if not, they can be easily written or generated, see e.g. http://www.swig.org).

PyROOT, a python extension module, provides the bindings for the ROOT class library in a generic way using the CINT dictionary. This design choice allows the use of any ROOT classes from the python interpreter, and thus the "glue-ing" of ROOT libraries with any non-ROOT library or application that provide python bindings. Furthermore, PyROOT can be loaded into the CINT interpreter to allow (as of now still rudimentary) access to python classes, and direct access to the python interpreter.

The best way to get a flavor of what PyROOT is, can do, and to understand what benefits it brings, is through a few examples.

2.1. Glue-ing applications

The PyQt library, see http://www.riverbankcomputing.co.uk/pyqt, provides python bindings for the Qt cross-platform GUI framework (http://www.trolltech.com). With PyROOT and PyQt, adding ROOT application layer code to a Qt GUI, becomes child's play.

The following example shows how a python class can be used to have ROOT code respond to a click on a Qt widget.

Example 1. Glue-ing Qt and ROOT through python

import sys, ROOT
from qt import *

theApp = QApplication( sys.argv )
box = QVBox()
box.resize( QSize( 40, 10 ).expandedTo( box.minimumSizeHint() ) )

class myButton( QPushButton ):
   def __init__( self, label, master ):
      QPushButton.__init__( self, label, master )
      self.setFont( QFont( 'Times', 18, QFont.Bold ) )

   def browse( self ):
      self.b = ROOT.TBrowser()

bb = myButton( 'browser', box )
QObject.connect( bb, SIGNAL( 'clicked()' ), bb.browse )

theApp.setMainWidget( box )
box.show()
theApp.exec_loop()


[Note]Note

GUI frameworks are a special case, as ROOT has its own GUI classes. For a full seamless integration, one would want to be able to frame ROOT windows in Qt and vice versa. This can be done by retrieving the window handles and a bit of lower level code (which tends to be non-portable), but is not so straightforward, unless you know how windowing systems work.

When the example is run, a Qt button is displayed, and when the button is clicked, a TBrowser instance is created and will appear on the screen. PyROOT takes care of feeding system events to ROOT widgets, so the TBrowser instance and the button behave properly when you interact with them.

2.2. Access to ROOT from python

There are several tools for scientific analysis that come with bindings that allow the use of these tools from the python interpreter. PyROOT provides this for users who want to do analysis in python with ROOT.

The following example shows how to fill and display a ROOT histogram while working in python. Of course, actual data for histogramming and display may come from anywhere else (instead of from gRandom) through other bindings, e.g. from a C++ program, or an ATHENA algorithm.

Example 2. Displaying a ROOT histogram from python

from ROOT import gRandom, TCanvas, TH1F

c1 = TCanvas( 'c1', 'Example', 200, 10, 700, 500 )
hpx = TH1F( 'hpx', 'px', 100, -4, 4 )

for i in xrange( 25000 ):
   px = gRandom.Gaus()
   hpx.Fill( px )

hpx.Draw()
c1.Update()


When run, the code above will display a 1-dimensional histogram showing a Gaussian distribution. More examples like the one above are distributed with ROOT under the tutorials directory.

2.3. Access to python from ROOT

Access to python objects from CINT is not completely fleshed out. Currently, ROOT objects and builtin types can freely cross the boundary between the two interpreters, but other objects are much more restricted. For example, for a python object to cross, it has to be a class instance, and its class has to be known to CINT first (i.e. the class has to cross first, before the instance can). All other cross-coding is based on strings that are run on the python interpreter and vice versa.

Example 3. Accessing the python interpreter from ROOT

// either load PyROOT explicitly or rely on auto-loading
gSystem->Load( "libPyROOT" );

TPython::Exec( "print 1 + 1" );     // prints '2'

// create a TBrowser on the python side, and transfer it back and forth
TBrowser* b = (void*)TPython::Eval( "ROOT.TBrowser()" );
TPython::Bind( b, "b" );

// builtin variables can cross-over (after the call i == 2)
int i = TPython::Eval( "1 + 1" );


It is possible to switch between interpreters by calling "TPython::Prompt()" from CINT side, while returning back to it by "exiting" the python interpreter with ^D (EOF). State is preserved between successive switches, and string based cross calls can nest as long as shared resources are properly handled.

This concludes the quick overview. All examples are fleshed out in more detail in the following sections.