import ROOT
Welcome to JupyROOT 6.07/07
Now we are ready to use PyROOT, the ROOT Python bindings. For example, we create a ROOT histogram and fill it with random numbers distributed according to a Gaussian.
h = ROOT.TH1F("gauss","Example histogram",64,-4,4)
h.FillRandom("gaus")
Now, we create a canvas, the entity which holds graphics primitives.
c = ROOT.TCanvas("myCanvasName","The Canvas Title",800,600)
h.Draw()
For the histogram to be displayed in the notebook, we need to draw the canvas.
c.Draw()
It is not active by default yet, but Javascript visualisation can be activated for testing purposes. The plot below will be interactive: click on it and discover the JSROOT capabilities!
%jsroot on
c.Draw()
Before moving forward, let's save our histogram on a file. All ROOT objects can be written to ROOT files out-of-the-box.
outputFile = ROOT.TFile("output.root","RECREATE")
h.Write()
outputFile.Close()
Let's check what is the content of the file with the rootls command line utility
%%bash
rootls -l output.root
TH1F Aug 26 17:34 gauss "Example histogram"
Thanks to ROOT, it is possibile to write cells in C++ within a Python notebook. This can be done using the %%cpp magic. Magics are a feature of Jupyter notebooks and when importing the ROOT module, the %%cpp magic was registered.
%%cpp
cout << "This is a C++ cell" << endl;
This is a C++ cell
Not bad. On the other hand, ROOT offers much more than this. Thanks to its interpreter and type system, entities such as functions, classes and variables, created in a C++ cell, can be accessed from within Python (and viceversa, partially).
%%cpp
class A{
public:
A(){cout << "Constructor of A!" << endl;}
};
a = ROOT.A()
Constructor of A!
The Python and C++ worlds are so entangled that we can find back in C++ the entities created in Python. To illustrate this, from within a C++ cell, we are going to fit a function in the gauss histogram displayed above and then re-draw the canvas.
%%cpp
gauss->Fit("gaus", "S");
myCanvasName->Draw();
FCN=47.4997 FROM MIGRAD STATUS=CONVERGED 53 CALLS 54 TOTAL EDM=8.44224e-09 STRATEGY= 1 ERROR MATRIX ACCURATE EXT PARAMETER STEP FIRST NO. NAME VALUE ERROR SIZE DERIVATIVE 1 Constant 2.46469e+02 4.31494e+00 1.19094e-02 -2.44811e-05 2 Mean 1.04782e-02 1.43576e-02 4.87656e-05 -6.34020e-03 3 Sigma 1.00315e+00 1.03818e-02 9.45504e-06 -2.70309e-02
Complete interoperability is possible. Let's move now to the options offered by the %%cpp magic.
The %%cpp magic accepts two options: -d and -a. Their documentation can be seen by typing:
%%cpp?
A window will appear at the bottom of the page, showing the documentation.
The -d option needs to be used when declaring functions: we must to be explicit.
%%cpp -d
void f() {
cout << "This is function f" << endl;
}
As usual, function f can also be accessed from Python.
print "This is again Python"
ROOT.f()
This is again Python This is function f
The implementation of the function can be inspected within a C++ cell:
%%cpp
f
(void (*)()) Function @0x7f500801f030 at :1: void f() { cout << "This is function f" << endl; }
The -a allows to compile the cell code with ACLiC. This is not so relevant for performance since the ROOT interpreter just in time compiles the C++ code. Nevertheless, ACLiC is most useful when the automatic creation of dictionaries is required, for example in presence of I/O operations.
%%cpp -a
class CompileMe {
public:
CompileMe() {}
void run() {}
};
Info in <TUnixSystem::ACLiC>: creating shared library /eos/user/x/xvallspl/SWAN_projects/rootbinder/notebooks/64a4a5eb_C.so
Let's verify that the dictionary is there:
ROOT.TClass.GetClass("CompileMe").HasDictionary()
True
Note that the class created previously A has no dictionary.
ROOT.TClass.GetClass("A").HasDictionary()
False