This shows you the differences between two versions of the page.
en:prog:asyroot [2015/04/24 19:27] kaspi [Status] |
en:prog:asyroot [2015/05/07 21:47] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== ROOT extension to Asymptote ====== | ||
- | |||
- | [[en:prog:asyroot#download_and_installation|Get me quickly to download]] | ||
- | |||
- | |||
- | |||
- | ===== Goal ===== | ||
- | |||
- | The goal is to extend the [[http://asymptote.sourceforge.net/|Asymptote]] language such that it can read-in and visualize [[http://root.cern.ch|ROOT]] objects. | ||
- | |||
- | |||
- | |||
- | ===== Status ===== | ||
- | |||
- | I believe that the project has become mature enough to be used by a larger community. | ||
- | |||
- | The current version is 1.1 | ||
- | (patch against Asymptote | ||
- | SVN revision 5548). | ||
- | Here is the [[http://artax.karlin.mff.cuni.cz/~kaspj0am/data/media/en/prog/asy|patch history]]. | ||
- | |||
- | |||
- | ===== Why ===== | ||
- | |||
- | (These are my personal opinions, others may perceive it differently) | ||
- | |||
- | - The ROOT plotting interface is far from convenient and satisfactory. | ||
- | * **The ROOT interface is clumsy** and requires **a lot of typing**. Few examples: | ||
- | - Changing color to red. In ROOT one has to write <code>myObject->SetLineColor(2);</code>In Asymptote one just adds <code>, red</code> to the draw command. | ||
- | - 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. | ||
- | - 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 [[#the_structure_of_a_scientific_plot|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 [[http://root.cern.ch/phpBB2/viewtopic.php?t=6505&highlight=|discussion regarding the axis labels]]. The last posting from the developers reads //You don't agree, but it is how it is implemented//. | ||
- | - It perfectly fits the "standard" work-flow: | ||
- | - a study performed within a ROOT-based framework | ||
- | - results of the study are saved as a ROOT file | ||
- | - script to produce the final graphics - the elementary objects from the ROOT file are combined into plots, given desired colors, labels etc. | ||
- | - 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 | ||
- | - 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. | ||
- | {{ en:prog:structure.png }} | ||
- | |||
- | |||
- | |||
- | |||
- | ==== 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 | ||
- | - 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. | ||
- | - All the parameters are passed into a low-level piece of code. | ||
- | - The code seeks for a ROOT function with the signature given by types of the passed parameters. | ||
- | - If the ROOT function/method is found, it is executed. | ||
- | - 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 ==== | ||
- | |||
- | See the [[http://artax.karlin.mff.cuni.cz/~kaspj0am/doxygen/asymptote|Doxygen documentation]]. | ||
- | |||
- | |||
- | ==== 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 [[en:prog:asy_root_interface|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_structure_of_a_scientific_plot|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 [[en:prog:asy_root_drawing|commented examples]] that demonstrates the available options. | ||
- | |||
- | |||
- | |||
- | |||
- | === Layout routines (pad_layout.asy) === | ||
- | |||
- | Following [[#the_structure_of_a_scientific_plot|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 [[en:prog:asy_pad_layout|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 | ||
- | * either in directory ''examples/kaspi'' that is shipped with the ''.diff'' file (see the download section) | ||
- | * or at one of these pages: [[en:prog:asy_root_interface|ROOT interface]], [[en:prog:asy_root_drawing|ROOT drawing]] and [[en:prog:asy_pad_layout|pad lyaout]]. | ||
- | |||
- | My [[http://jkaspar.web.cern.ch/jkaspar/thesis/thesis_corr2_display.pdf|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: | ||
- | |||
- | {{en:prog:example1.png?350 }} | ||
- | {{en:prog:example2.png?250 }} | ||
- | |||
- | |||
- | |||
- | ===== Download and installation ===== | ||
- | |||
- | The current version is 1.1 | ||
- | (patch against Asymptote | ||
- | SVN revision 5548). | ||
- | |||
- | - Download the latest patch {{en:prog:asy:asymptote_root_extension_1.1_5548.diff}}. | ||
- | - Apply the patch. In your Asymptote directory do: <code>patch -p0 -i asymptote_root_extension_xx_yy.diff</code> | ||
- | - Follow as usual, etc. <code> | ||
- | autoconf; autoheader # if needed | ||
- | ./configure # if you have $ROOTSYS properly set, it will automatically enable the ROOT extension | ||
- | make | ||
- | </code> | ||