User Tools

Site Tools


en:prog:asyroot

This is an old revision of the document!


ROOT extension to Asymptote

Goal

The goal is to extend the Asymptote language such that it can read-in and visualize ROOT objects.

Status

I believe that the project has become mature and is ready to be used by a larger community.

The current version is 1.1 (patch against Asymptote SVN revision 5548). Here is the patch history.

Why

(These are my personal opinions, others may perceive it differently)

  1. The ROOT plotting interface is far from convenient and satisfactory.
    • The ROOT interface is clumsy and requires a lot of typing. Few examples:
      1. Changing color to red. In ROOT one has to write
        myObject->SetLineColor(2);

        In Asymptote one just adds

        , red

        to the draw command.

      2. Changing x-axis label. This is a challenge. When only given a pointer to TCanvas, one has to go through the list of primitives, find the first convenient object and use GetXaxis()→SetName(“…”). This is simply unacceptable for such a primitive and usual operation.
      3. Plotting several objects to the same canvas (figure). Mostly, one has to specify a flag depending on whether you are plotting the first object or not. For instance, when plotting histograms: one must give “” flag for the first one, while “same” for the others. However, when working with graphs, the flag for the first one reads “A” and is empty for the others. Why should a user bother about all those things?
    • In my opinion, it is contradictory to a natural structure of a scientific plot. In ROOT, a canvas/pad has no axes itself. In contrast, every graphical object has a set of axes. So when, e.g. 5 graphs are plotted in a canvas, there are 5 sets of axes which can be, in principle, drawn. This leads to confusion and awkward behavior.
    • The developers of ROOT don't seem to have any will to improve the situation. You may have a look at a discussion regarding the axis labels. The last posting from the developers reads You don't agree, but it is how it is implemented.
  2. It perfectly fits the “standard” work-flow:
    1. a study performed within a ROOT-based framework
    2. results of the study are saved as a ROOT file
    3. script to produce the final graphics - the elementary objects from the ROOT file are combined into plots, given desired colors, labels etc.
  3. Generally speaking, Asymptote is capable of producing a better quality output. Especially in cooperation with (La)TeX. A few points I like:
    • you can produce a plot of a given size, exactly as you wish
    • you can use all the fonts as you do in you (La)TeX document, hence fonts in plots and text can match!
      • indeed, font sizes can be given in pt and can be easily be made compatible with your (La)TeX document
  4. In Asymptote, it is much easier to add additional elements like arrows, lines, …

Concept

The structure of a scientific plot

  • a plot may consist of several pads, aligned in a way (in a line, in a grid, etc.)
  • each pad comprises
    • (up to one) set of axes: x, y, and optionally z
      • each axis has a label
    • several graphical objects (histograms, graphs, …)
    • a legend

An example: A plot (the light blue area) with 6 pads (drawn in light yellow) aligned in a grid. The green dots show alignment control points.

The concept of the interface

I tried to make the ROOT–Asymptote interface as flexible as possible. However, there are some limitations - read the documentation for more information.

Currently, ROOT methods are called from Asymptote via CINT API, namely G_CallFunc::Execute. It works basically in these steps

  1. The ?Exec functions (see documentation) have open signature, i.e. they can take whatever parameters. Consequently, the Asymptote parser/compiler would never report an error.
  2. All the parameters are passed into a low-level piece of code.
  3. The code seeks for a ROOT function with the signature given by types of the passed parameters.
  4. If the ROOT function/method is found, it is executed.
  5. The return G_value is converted into an Asymptote variable, according to which one of the ?Exec functions was called.

Documentation

Implementation of the ROOT interface

ROOT interface user's guide

A generic ROOT object (any descendant of TObject) is represented in Asymptote as a rObject object:

rObject obj;

One can check the validity (i.e. non-emptiness) of a rObject, test its inheritance path and print the related information:

bool valid = obj.valid;
bool inherits = obj.InheritsFrom("some ROOT class name");
obj.Print();
write(obj);
write("object properties: ", obj);

A rObject can be loaded from a ROOT file by

rObject rGetObj(string file, string object_name, bool error=true, bool search=true)

The interface is capable of calling an arbitrary method of a ROOT object. It is implemented via the set of functions:

void rObject.vExec(string method_name, ...);
bool rObject.bExec(string method_name, ...);
int rObject.iExec(string method_name, ...);
real rObject.rExec(string method_name, ...);
string rObject.sExec(string method_name, ...);
rObject rObject.oExec(string method_name, ...);

All the functions take the method name as the first parameter. Parameters of the method are to follow (they're abbreviated by …). The recognized types are bool, int, real and string. All parameters are passed by value. If you want to pass a parameter by reference, create an array with just one element and pass the array, e.g.

real[] x = {2.};
real[] y = {2.};
obj.vExec("GetPoint", 1, x, y);

Currently, only int and real parameters can be passed by reference.

Here is a set of commented examples the covers and explains the complete functionality.

ROOT Asymptote macros

The asymptote macros/routines are split into 2 files:

  • base/root.asy: contains routines to draw ROOT objects
  • base/pad_layout.asy: pad layout management tools (see the suggested plot structure).

Drawing routines (root.asy)

To draw an rObject, use

void draw(picture pic=currentpicture, rObject obj, string options="", pen pen=currentpen, marker marker=nomarker, Label legend="")

Here is a set of commented examples that demonstrates the available options.

Layout routines (pad_layout.asy)

Following the suggested plot structure, all graphics is organized in pads. To create a new pad (with axes labels), you may use

pad NewPad(bool drawAxes = true,
           bool axesAbove = false,
           string xLabel = "", string yLabel = "",
           ticks xTicks = xTicksDef, ticks yTicks = yTicksDef,
           bool autoSize = true,
           explicit real xSize = xSizeDef, explicit real ySize = ySizeDef,
           explicit int xGridHint, int yGridHint)

The GridHint parameters can be used to place a pad in given position with a grid. If not specified, the pads placed in a horizontal line (from left to right). Use NewRow() to start a new row. NewPage() starts a new page.

The pads are laid out during the shipout procedure (when the output files are created). The default Asymptote's shipout command outputs just the current picture. That is why this module brings another shipout routine (and makes it default):

void GShipout(string prefix=defaultfilename, pair alignment=(0, 0), real hSkip=1cm, real vSkip=1cm, real margin=1mm,
              pen p = nullpen, filltype filltype = Fill(white))

All parameters are facultative, so you can just type GShipout(). And even that is not needed since Asymptote would append it automatically if there is some material to be shiped out. The alignment parameter gives the point that is used to align pads in rows and columns. For example, if NE is used, the top left left-hand side corner of your pads would be used for alignment. The Skip parameters give spacing between rows and columns. All the output is placed into a frame that is by margin larger that the grid of pads, that is draw by pen p and filled by filltype.

Here are some commented examples that may serve as a tutorial.

Examples

There is a comprehensive set of commented examples that would guide you through the available features. These examples can be found

My PhD thesis can serve as an example too (all figures have been made with Asymptote).

A couple of examples of embedding ROOT data into more complex graphics:

Download and installation

The current version is 1.1 (patch against Asymptote SVN revision 5548).

  1. Download the latest patch asymptote_root_extension_1.1_5548.diff.
  2. Apply the patch. In your Asymptote directory do:
    patch -p0 -i asymptote_root_extension_xx_yy.diff
  3. Follow as usual, etc.
    autoconf; autoheader  # if needed
    ./configure # if you have $ROOTSYS properly set, it will automatically enable the ROOT extension
    make
en/prog/asyroot.1366729829.txt.gz · Last modified: 2015/04/24 19:27 (external edit)