May 2018

WARNING: This documentation is not maintained anymore. Some part might be obsolete or wrong, some part might be missing but still some valuable information can be found there. Instead please refer to the ROOT Reference Guide and the ROOT Manual. If you think some information should be imported in the ROOT Reference Guide or in the ROOT Manual, please post your request to the ROOT Forum or via a Github Issue.

# Preface

In late 1994, we decided to learn and investigate Object Oriented programming and C++ to better judge the suitability of these relatively new techniques for scientific programming. We knew that there is no better way to learn a new programming environment than to use it to write a program that can solve a real problem. After a few weeks, we had our first histogramming package in C++. A few weeks later we had a rewrite of the same package using the, at that time, very new template features of C++. Again, a few weeks later we had another rewrite of the package without templates since we could only compile the version with templates on one single platform using a specific compiler. Finally, after about four months we had a histogramming package that was faster and more efficient than the well-known FORTRAN based HBOOK histogramming package. This gave us enough confidence in the new technologies to decide to continue the development. Thus was born ROOT. Since its first public release at the end of 1995, ROOT has enjoyed an ever-increasing popularity. Currently it is being used in all major High Energy and Nuclear Physics laboratories around the world to monitor, to store and to analyse data. In the other sciences as well as the medical and financial industries, many people are using ROOT. We estimate the current user base to be around several thousand people. In 1997, Eric Raymond analysed in his paper “The Cathedral and the Bazaar” the development method that makes Linux such a success. The essence of that method is: “release early, release often and listen to your customers”. This is precisely how ROOT is being developed. Over the last five years, many of our “customers” became co-developers. Here we would like to thank our main co-developers and contributors:

Masaharu Goto wrote the C++ interpreter CINT that was an essential part of ROOT before ROOT 6. Despite being 8 time zones ahead of us, we have the feeling he has been sitting in the room next door since 1995.

Andrei and Mihaela Gheata (Alice collaboration) are co-authors of the ROOT geometry classes and Virtual Monte-Carlo. They have been working with the ROOT team since 2000.

Olivier Couet, who after a successful development and maintenance of PAW, has joined the ROOT team in 2000 and has been working on the graphics sub-system.

Ilka Antcheva has been working on the Graphical User Interface classes. She is also responsible for this latest edition of the Users Guide with a better style, improved index and several new chapters (since 2002).

Bertrand Bellenot has been developing and maintaining the Win32GDK version of ROOT. Bertrand has also many other contributions like the nice RootShower example (since 2001).

Valeriy Onoutchin has been working on several ROOT packages, in particular the graphics sub-system for Windows and the GUI Builder (since 2000).

Gerri Ganis has been working on the authentication procedures to be used by the root daemons and the PROOF system (since 2002).

Maarten Ballintijn (MIT) is one of the main developers of the PROOF sub-system (since 1995).

Valeri Fine (now at BNL) ported ROOT to Windows and contributed largely to the 3-D graphics. He is currently working on the Qt layer of ROOT (since 1995).

Victor Perevoztchikov (BNL) worked on key elements of the I/O system, in particular the improved support for STL collections (1997-2001).

Nenad Buncic developed the HTML documentation generation system and integrated the X3D viewer inside ROOT (1995-1997).

Suzanne Panacek was the author of the first version of this User’s Guide and very active in preparing tutorials and giving lectures about ROOT (1999-2002).

Axel Naumann has been developing further the HTML Reference Guide and helps in porting ROOT under Windows (cygwin/gcc implementation) (since 2000).

Anna Kreshuk has developed the Linear Fitter and Robust Fitter classes as well as many functions in TMath, TF1, TGraph (since 2005).

Richard Maunder has contributed to the GL viewer classes (since 2004).

Timur Pocheptsov has contributed to the GL viewer classes and GL in pad classes (since 2004).

Sergei Linev has developed the XML driver and the TSQLFile classes (since 2003).

Stefan Roiser has been contributing to the reflex and cintex packages (since 2005).

Lorenzo Moneta has been contributing the MathCore, MathMore, Smatrix & Minuit2 packages (since 2005).

Wim Lavrijsen is the author of the PyRoot package (since 2004).

Further we would like to thank all the people mentioned in the $ROOTSYS/README/CREDITS file for their contributions, and finally, everybody who gave comments, reported bugs and provided fixes. Happy ROOTing! Rene Brun & Fons Rademakers Geneva, July 2007 # 1 Introduction In the mid 1990’s, René Brun and Fons Rademakers had many years of experience developing interactive tools and simulation packages. They had lead successful projects such as PAW, PIAF, and GEANT, and they knew PAW the twenty-year-old FORTRAN libraries had reached their limits. Although still very popular, these tools could not scale up to the challenges offered by the Large Hadron Collider, where the data is a few orders of magnitude larger than anything seen before. At the same time, computer science had made leaps of progress especially in the area of Object Oriented Design, and René and Fons were ready to take advantage of it. ROOT was developed in the context of the NA49 experiment at CERN. NA49 has generated an impressive amount of data, around 10 Terabytes per run. This rate provided the ideal environment to develop and test the next generation data analysis. ROOT was, and still is, developed in the “Bazaar style”, a term from the book “The Cathedral and the Bazaar” by Eric S. Raymond. It means a liberal, informal development style that heavily relies on the diverse and deep talent of the user community. The result is that physicists developed ROOT for themselves; this made it specific, appropriate, useful, and over time refined and very powerful. The development of ROOT is a continuous conversation between users and developers with the line between the two blurring at times and the users becoming co-developers. When it comes to storing and mining large amount of data, physics plows the way with its Terabytes, but other fields and industry follow close behind as they acquiring more and more data over time. They are ready to use the true and tested technologies physics has invented. In this way, other fields and industries have found ROOT useful and they have started to use it also. In the bazaar view, software is released early and frequently to expose it to thousands of eager co-developers to pound on, report bugs, and contribute possible fixes. More users find more bugs, because they stress the program in different ways. By now, after ten years, the age of ROOT is quite mature. Most likely, you will find the features you are looking for, and if you have found a hole, you are encouraged to participate in the dialog and post your suggestion or even implementation on the ROOT forum. ## 1.1 The ROOT forum If you have a question, it is likely that it has been asked, answered, and stored in the ROOT Forum. Please use the search engine to see if your question has already been answered before posting a topic in the Forum. You can access the ROOT forum at: https://root-forum.cern.ch. ## 1.2 Contact Information Several authors wrote this book and you may see a “change of voice” from one chapter to the next. We felt we could accept this in order to have the expert explain what they know best. If you would like to contribute a chapter or add to a section, please contact rootdoc@cern.ch. We count on you to send us suggestions on additional topics or on the topics that need more documentation. Please send your comments, corrections, questions, and suggestions to the rootdoc list: rootdoc@cern.ch We attempt to give the user insight into the many capabilities of ROOT. The book begins with the elementary functionality and progresses in complexity reaching the specialized topics at the end. The experienced user looking for special topics may find these chapters useful: see “Networking”, “Writing a Graphical User Interface”, “Threads”, and “PROOF: Parallel Processing”. ## 1.3 Conventions Used in This Book We tried to follow a style convention for the sake of clarity. The styles in used are described below. To show source code in scripts or source files: { cout << " Hello" << endl; float x = 3.; float y = 5.; int i = 101; cout <<" x = "<<x<<" y = "<<y<<" i = "<<i<< endl; } To show the ROOT command line, we show the ROOT prompt without numbers. In the interactive system, the ROOT prompt has a line number (root[12]); for the sake of simplicity, the line numbers are left off. root[] TLine l root[] l.Print() TLine X1=0.000000 Y1=0.000000 X2=0.000000 Y2=0.000000 Italic bold monotype font indicates a global variable, for example gDirectory. When a variable term is used, it is shown between angled brackets. In the example below the variable term <library> can be replaced with any library in the $ROOTSYS directory: $ROOTSYS/<library>/inc. ## 1.4 The Framework ROOT is an object-oriented framework aimed at solving the data analysis challenges of high-energy physics. There are two key words in this definition, object oriented and framework. First, we explain what we mean by a framework and then why it is an object-oriented framework. ### 1.4.1 What Is a Framework? Programming inside a framework is a little like living in a city. Plumbing, electricity, telephone, and transportation are services provided by the city. In your house, you have interfaces to the services such as light switches, electrical outlets, and telephones. The details, for example, the routing algorithm of the phone switching system, are transparent to you as the user. You do not care; you are only interested in using the phone to communicate with your collaborators to solve your domain specific problems. Programming outside of a framework may be compared to living in the country. In order to have transportation and water, you will have to build a road and dig a well. To have services like telephone and electricity you will need to route the wires to your home. In addition, you cannot build some things yourself. For example, you cannot build a commercial airport on your patch of land. From a global perspective, it would make no sense for everyone to build their own airport. You see you will be very busy building the infrastructure (or framework) before you can use the phone to communicate with your collaborators and have a drink of water at the same time. In software engineering, it is much the same way. In a framework, the basic utilities and services, such as I/O and graphics, are provided. In addition, ROOT being a HEP analysis framework, it provides a large selection of HEP specific utilities such as histograms and fitting. The drawback of a framework is that you are constrained to it, as you are constraint to use the routing algorithm provided by your telephone service. You also have to learn the framework interfaces, which in this analogy is the same as learning how to use a telephone. If you are interested in doing physics, a good HEP framework will save you much work. Next is a list of the more commonly used components of ROOT: Command Line Interpreter, Histograms and Fitting, Writing a Graphical User Interface, 2D Graphics, Input/Output , Collection Classes, Script Processor. There are also less commonly used components, as: 3D Graphics, Parallel Processing (PROOF), Run Time Type Identification (RTTI), Socket and Network Communication, Threads. #### 1.4.1.1 Advantages of Frameworks The benefits of frameworks can be summarized as follows: • Less code to write - the programmer should be able to use and reuse the majority of the existing code. Basic functionality, such as fitting and histogramming are implemented and ready to use and customize. • More reliable and robust code - the code inherited from a framework has already been tested and integrated with the rest of the framework. • More consistent and modular code - the code reuse provides consistency and common capabilities between programs, no matter who writes them. Frameworks make it easier to break programs into smaller pieces. • More focus on areas of expertise - users can concentrate on their particular problem domain. They do not have to be experts at writing user interfaces, graphics, or networking to use the frameworks that provide those services. ### 1.4.2 Why Object-Oriented? Object-Oriented Programming offers considerable benefits compared to Procedure-Oriented Programming: • Encapsulation enforces data abstraction and increases opportunity for reuse. • Sub classing and inheritance make it possible to extend and modify objects. • Class hierarchies and containment containment hierarchies provide a flexible mechanism for modeling real-world objects and the relationships among them. • Complexity is reduced because there is little growth of the global state, the state is contained within each object, rather than scattered through the program in the form of global variables. • Objects may come and go, but the basic structure of the program remains relatively static, increases opportunity for reuse of design. ## 1.5 Installing ROOT To install ROOT you will need to go to the ROOT website at: http://root.cern.ch/root/Availability.html. You have a choice to download the binaries or the source. The source is quicker to transfer since it is only ~22 MB, but you will need to compile and link it. The binaries compiled with no debug information range from ~35 MB to ~45 MB depending on the target platform. The installation and building of ROOT is described in Appendix A: Install and Build ROOT. You can download the binaries, or the source. The GNU g++ compiler on most UNIX platforms can compile ROOT. Before downloading a binary version make sure your machine contains the right run-time environment. In most cases it is not possible to run a version compiled with, e.g., gcc4.0 on a platform where only gcc 3.2 is installed. In such cases you’ll have to install ROOT from source. ROOT is currently running on the following platforms: supported platforms • GNU/Linux x86-32 (IA32) and x86-64 (AMD64)(GCC,Intel/icc, Portland/PGCC,KAI/KCC) • Intel Itanium (IA64) GNU/Linux (GCC, Intel/ecc, SGI/CC) • FreeBSD and OpenBSD (GCC) • GNU/Hurd (GCC) • HP HP-UX 10.x (IA32) and 11 (IA64) (HP CC, aCC, GCC) • IBM AIX 4.1 (xlC compiler, GCC) • Sun Solaris for SPARC (SUN C++ compiler, GCC) • Sun Solaris for x86 (SUN C++ compiler, KAI/KCC) • Compaq Alpha (GCC, KAI/KCC, DEC/CXX) • SGI Irix 32 and 64 bits (GCC, KAI/KCC, SGI C++ compiler) • Windows >= 95 (Microsoft Visual C++ compiler, Cygwin/GCC) • MacOS X PPC, x86-32, x86-64 (GCC, Intel/ICC, IBM/xl) • PowerPC with GNU/Linux and GCC, Debian v2 • PowerPC64 with GNU/Linux and GCC • ARM with GNU/Linux and GCC • LynxOS ## 1.6 The Organization of the ROOT Framework Now after we know in abstract terms what the ROOT framework is, let us look at the physical directories and files that come with the ROOT installation. You may work on a platform where your system administrator has already installed ROOT. You will need to follow the specific development environment for your setup and you may not have write access to the directories. In any case, you will need an environment variable called ROOTSYS, which holds the path of the top ROOT directory. > echo$ROOTSYS
/opt/root

In the ROOTSYS directory are examples, executables, tutorials, header tutorials files, and, if you opted to download it, the source is here. The directories of special interest to us are bin, tutorials, lib, test, andinclude. The next figure shows the contents of these directories.

### 1.6.1 $ROOTSYS/bin The bin directory contains several executables.  root shows the ROOT splash screen and calls root.exe root.exe the executable that root calls, if you use a debugger such as gdb, you will need to run root.exe directly rootcling is the utility ROOT uses to create a class dictionary for Cling rmkdepend a modified version of makedepend that is used by the ROOT build system root-config a script returning the needed compile flags and libraries for projects that compile and link with ROOT proofd a small daemon used to authenticate a user of ROOT parallel processing capability (PROOF) proofserv the actual PROOF process, which is started by proofd after a user, has successfully been authenticated rootd is the daemon for remote ROOT file access (see the TNetFile) ### 1.6.2$ROOTSYS/lib

There are several ways to use ROOT, one way is to run the executable by typing root at the system prompt another way is to link with the ROOT libraries and make the ROOT classes available in your own program.

Here is a short description of the most relevant libraries, the ones marked with a * are only installed when the options specified them.

• libAsImage is the image manipulation library

• libCling is the C++ interpreter (Cling)

• libCore is the Base classes

• libEG is the abstract event generator interface classes

• *libEGPythia is the Pythia5 event generator interface

• *libEGPythia6 is the Pythia6 event generator interface

• libFitPanel contains the GUI used for fitting

• libGed contains the GUI used for editing the properties of histograms, graphs, etc.

• libGeom is the geometry package (with builder and painter)

• libGpad is the pad and canvas classes which depend on low level graphics

• libGraf is the 2D graphics primitives (can be used independent of libGpad)

• libGraf3d is the 3D graphics primitives

• libGui is the GUI classes (depend on low level graphics)

• libGuiBld is the GUI designer

• libGuiHtml contains the embedded HTML browser

• libGX11 is the low level graphics interface to the X11 system

• *libGX11TTF is an add-on library to libGX11 providing TrueType fonts

• libHbook is for interface ROOT - HBOOK

• libHist is the histogram classes (with accompanying painter library)

• libHtml is the HTML documentation generation system

• libMatrix is the matrix and vector manipulation

• libMathCore contains the core mathematics and physics vector classes

• libMathMore contains additional functions, interfacing the GSL math library

• libMinuit is the MINUIT fitter

• libNet contains functionality related to network transfer

• libNew is the special global new/delete, provides extra memory checking and interface for shared memory (optional)

• libPhysics contains the legacy physics classes (TLorentzVector, etc.)

• libPostscript is the PostScript interface

• libProof is the parallel ROOT Facility classes

• libPython provides the interface to Python

• *libRFIO is the interface to CERN RFIO remote I/O system.

• *libRGL is the interface to OpenGL.

• libReflex is the runtime type database library used by Cling

• libRint is the interactive interface to ROOT (provides command prompt)

• libRIO provides the functionality to write and read objects to and from ROOT files

• libRooFit is the RooFit fitting framework

• libRuby is the interface to Ruby

• libSpectrum provides functionality for spectral analysis

• *libThread is the interface to TThread classes

• libTMVA contains the multivariate analysis toolkit

• libTree is the TTree object container system

• libTreePlayer is the TTree drawing classes

• libTreeViewer is the graphical TTree query interface

#### 1.6.2.1 Library Dependencies

The libraries are designed and organized to minimize dependencies, such that you can load just enough code for the task at hand rather than having to load all libraries or one monolithic chunk. The core library (libCore.so) contains the essentials; it is a part of all ROOT applications. In the Figure 1-2 you see that libCore.so is made up of base classes, container classes, meta information classes, operating system specific classes, and the ZIP algorithm used for compression of the ROOT files.

The Cling library (libCling.so) is also needed in all ROOT applications, and even by libCore. A program referencing only TObject only needs libCore; libCling will be opened automatically. To add the ability to read and write ROOT objects one also has to load libRIO. As one would expect, none of that depends on graphics or the GUI.

Library dependencies have different consequences; depending on whether you try to build a binary, or you just try to access a class that is defined in a library.

When building your own executable you will have to link against the libraries that contain the classes you use. The ROOT reference guide states the library a class is reference guide defined in. Almost all relevant classes can be found in libraries returned by root-config -glibs; the graphics libraries are retuned by root-config --libs. These commands are commonly used in Makefiles. Using root-config instead of enumerating the libraries by hand allows you to link them in a platform independent way. Also, if ROOT library names change you will not need to change your Makefile.

A batch program that does not have a graphic display, which creates, fills, and saves histograms and trees, only needs to link the core libraries (libCore, libRIO), libHist and libTree. If ROOT needs access to other libraries, it loads them dynamically. For example, if the TreeViewer is used, libTreePlayer and all libraries libTreePlayer depends on are loaded also. The dependent libraries are shown in the ROOT reference guide’s library dependency graph. The difference between reference guide libHist and libHistPainter is that the former needs to be explicitly linked and the latter will be loaded automatically at runtime when ROOT needs it, by means of the Plugin Manager. plugin manager

In the Figure 1-2, the libraries represented by green boxes outside of the core are loaded via the plugin manager plugin manager or equivalent techniques, while the white ones are not. Of course, if one wants to access a plugin library directly, it has to be explicitly linked. An example of a plugin library is libMinuit. To create and fill histograms you need to link libHist.so. If the code has a call to fit the histogram, the “fitter” will dynamically load libMinuit if it is not yet loaded.

#### 1.6.2.3 Plugins: Runtime Library Dependencies for Linking

plugin manager The Plugin Manager TPluginManager allows postponing library dependencies to runtime: a plugin library will only be loaded when it is needed. Non-plugins will need to be linked, and are thus loaded at start-up. Plugins are defined by a base class (e.g. TFile) that will be implemented in a plugin, a tag used to identify the plugin (e.g. ^rfio: as part of the protocol string), the plugin class of which an object will be created (e.g. TRFIOFile), the library to be loaded (in short libRFIO.so to RFIO), and the constructor to be called (e.g. “TRFIOFile()”). This can be specified in the .rootrc which already contains many plugin definitions, or by calls to gROOT->GetPluginManager()->AddHandler().

When using a class in Cling, e.g. in an interpreted source file, ROOT will automatically load the library that defines this class. On start-up, ROOT parses all files ending on .rootmap rootmap that are in one of the $LD_LIBRARY_PATH (or $DYLD_LIBRARY_PATH for MacOS, or $PATH for Windows). They contain class names and the library names that the class depends on. After reading them, ROOT knows which classes are available, and which libraries to load for them. When TSystem::Load("ALib") is called, ROOT uses this information to determine which libraries libALib.so depends on. It will load these libraries first. Otherwise, loading the requested library could cause a system (dynamic loader) error due to unresolved symbols. ### 1.6.3$ROOTSYS/tutorials

tutorials The tutorials directory contains many example example scripts. They assume some basic knowledge of ROOT, and for the new user we recommend reading the chapters: “Histograms” and “Input/Output” before trying the examples. The more experienced user can jump to chapter “The Tutorials and Tests” to find more explicit and specific information about how to build and run the examples.

The $ROOTSYS/tutorials/ directory include the following sub-directories: fft: Fast Fourier Transform with the fftw package fit: Several examples illustrating minimization/fitting foam: Random generator in multidimensional space geom: Examples of use of the geometry package (TGeo classes) gl: Visualisation with OpenGL graphics: Basic graphics graphs: Use of TGraph, TGraphErrors, etc. gui: Scripts to create Graphical User Interface hist: Histogramming image: Image Processing io: Input/Output math: Maths and Statistics functions matrix: Matrices (TMatrix) examples mlp: Neural networks with TMultiLayerPerceptron net: Network classes (client/server examples) physics: LorentzVectors, phase space pyroot: Python tutorials pythia: Example with pythia6 quadp: Quadratic Programming smatrix: Matrices with a templated package spectrum: Peak finder, background, deconvolutions splot: Example of the TSplot class (signal/background estimator) sql: Interfaces to SQL (mysql, oracle, etc) thread: Using Threads tmva: Examples of the MultiVariate Analysis classes tree: Creating Trees, Playing with Trees unuran: Interface with the unuram random generator library xml: Writing/Reading xml files You can execute the scripts in $ROOTSYS/tutorials (or sub-directories) by setting your current directory in the script directory or from any user directory with write access. Several tutorials create new files. If you have write access to the tutorials directory, the new files will be created in the tutorials directory, otherwise they will be created in the user directory.

### 1.6.5 $ROOTSYS/include The include directory contains all header files. It is especially important because the header files contain the class definitions. ### 1.6.6$ROOTSYS/<library>

The directories we explored above are available when downloading the binaries. When downloading the source you also get a directory for each library with the corresponding header and source files, located in the inc and src subdirectories. To see what classes are in a library, you can check the <library>/inc directory for the list of class definitions. For example, the physics library libPhysics.so contains these class definitions:

> ls -m $ROOTSYS/math/physics/inc/ LinkDef.h, TFeldmanCousins.h, TGenPhaseSpace.h, TLorentzRotation.h, TLorentzVector.h, TQuaternion.h, TRobustEstimator.h, TRolke.h, TRotation.h, TVector2.h, TVector3.h ## 1.7 How to Find More Information website The ROOT web site has up to date documentation. The ROOT source code automatically generates this documentation, so each class is explicitly documented on its own web page, which is always up to date with the latest official release of ROOT. The ROOT Reference Guide web pages can be found at class index reference guide http://root.cern.ch/root/html/ClassIndex.html. Each page contains a class description, and an explanation of each method. It shows the class inheritance tree and lets you jump to the parent class page by clicking on the class name. If you want more details, you can even see the source. There is a help page available in the little box on the upper right hand side of each class documentation page. You can see on the next page what a typical class documentation web page looks like. The ROOT web site also contains in addition to this Reference Guide, “How To’s”, a list of publications and example applications. ### 1.7.1 Class Reference Guide The top of any class reference page lets you jump to different parts of the documentation. The first line links to the class index and the index for the current module (a group of classes, often a library). The second line links to the ROOT homepage and the class overviews. The third line links the source information - a HTML version of the source and header file as well as the CVS (the source management system used for the ROOT development) information of the files. The last line links the different parts of the current pages. # 2 Getting Started We begin by showing you how to use ROOT interactively. There are two examples to click through and learn how to use the GUI. We continue by using the command line, and explaining the coding conventions, global variables and the environment setup. If you have not installed ROOT, you can do so by following the instructions in the appendix, or on the ROOT web site: http://root.cern.ch/root/Availability.html ## 2.1 Setting the Environment Variables Before you can run ROOT you need to set the environment variable ROOTSYS and change your path to include root/bin and library path variables to include root/lib. Please note: the syntax is for bash, if you are running tcsh you will have to use setenv instead of export. 1. Define the variable$ROOTSYS to the directory where you unpacked the ROOT:
$export ROOTSYS=$HOME/root
$export PATH=$PATH:$ROOTSYS/bin 1. Setting the Library Path On HP-UX, before executing the interactive module, you must set the library path: $ export SHLIB_PATH=$SHLIB_PATH:$ROOTSYS/lib

On AIX, before executing the interactive module, you must set the library path:

$[ -z "$LIBPATH" ] && export LIBPATH=/lib:/usr/lib
$export LIBPATH=$LIBPATH:$ROOTSYS/lib On Linux, Solaris, Alpha OSF and SGI, before executing the interactive module, you must set the library path: $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib

On Solaris, in case your LD_LIBRARY_PATH is empty, you should set it:

$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib:/usr/dt/lib If you use the afs version you should set (vers = version number, arch = architecture): $ export ROOTSYS=/afs/cern.ch/sw/lcg/external/root/vers/arch/root

If ROOT was installed in $HOME/myroot directory on a local machine, one can do: cd$HOME/myroot
. bin/thisroot.sh       // or source bin/thisroot.sh

The new $ROOTSYS/bin/thisroot.[c]sh scripts will set correctly the ROOTSYS, LD_LIBRARY_PATH or other paths depending on the platform and the MANPATH. To run the program just type: root. ## 2.2 Start and Quit a ROOT Session $ root
-------------------------------------------------------------------------
| Welcome to ROOT 6.10/01                             http://root.cern.ch |
|                                            (c) 1995-2017, The ROOT Team |
| Built for macosx64                                                      |
| From heads/v6-10-00-patches@v6-10-00-25-g9f78c3a, Jul 03 2017, 11:39:44 |
| Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'              |
-------------------------------------------------------------------------

root [0]

To start ROOT you can type root at the system prompt. This starts up Cling, the ROOT command line C/C++ interpreter, and it gives you the ROOT prompt (root[0]).

It is possible to launch ROOT with some command line options, as shown below:

%  root -?
Usage: root [-l] [-b] [-n] [-q] [dir] [[file:]data.root]
[file1.C ... fileN.C]
Options:
-b : run in batch mode without graphics
-n : do not execute logon and logoff macros as specified in .rootrc
-q : exit after processing command line macro files
-l : do not show splash screen
-x : exit on exception
dir : if dir is a valid directory cd to it before executing

-?       : print usage
-h       : print usage
--help   : print usage
-config  : print ./configure options
• -b ROOT session runs in batch mode, without graphics display. This mode is useful in case one does not want to set the DISPLAY or cannot do it for some reason.

• -n usually, launching a ROOT session will execute a logon script and quitting will execute a logoff script. This option prevents the execution of these two scripts.

• it is also possible to execute a script without entering a ROOT session. One simply adds the name of the script(s) after the ROOT command. Be warned: after finishing the execution of the script, ROOT will normally enter a new session.

• -q process command line script files and exit.

For example if you would like to run a script myMacro.C in the background, redirect the output into a file myMacro.log, and exit after the script execution, use the following syntax:

root -b -q myMacro.C > myMacro.log

If you need to pass a parameter to the script use:

root -b -q 'myMacro.C(3)' > myMacro.log

Be mindful of the quotes, i.e. if you need to pass a string as a parameter, the syntax is:

root -b -q 'myMacro.C("text")' > myMacro.log

You can build a shared library with ACLiC and then use this shared library on the command line for a quicker execution (i.e. the compiled speed rather than the interpreted speed). See also “Cling the C++ Interpreter”.

root -b -q myMacro.so > myMacro.log

ROOT has a powerful C/C++ interpreter giving you access to all available ROOT classes, global variables, and functions via the command line. By typing C++ statements at the prompt, you can create objects, call functions, execute scripts, etc. For example:

root[] 1+sqrt(9)
(const double)4.00000000000000000e+00
root[] for (int i = 0; i<4; i++) cout << "Hello" << i << endl
Hello 0
Hello 1
Hello 2
Hello 3
root[] .q

To exit the ROOT session, type .q.

root[] .q

## 2.3 Using the GUI

The basic whiteboard on which an object is drawn in ROOT is called a canvas (defined by the class TCanvas). Every object in the canvas is a graphical object in the sense that you can grab it, resize it, and change some characteristics using the mouse. The canvas area can be divided in several sub areas, so-called pads (the class TPad). A pad is a canvas sub area that can contain other pads or graphical objects. At any one time, just one pad is the so-called active pad. Any object at the moment of drawing will be drawn in the active pad. The obvious question is: what is the relation between a canvas and a pad? In fact, a canvas is a pad that spans through an entire window. This is nothing else than the notion of inheritance. The TPad class is the parent of the TCanvas class. In ROOT, most objects derive from a base class TObject. This class has a virtual method Draw() such as all objects are supposed to be able to be “drawn”. If several canvases are defined, there is only one active at a time. One draws an object in the active canvas by using the statement:

object.Draw()

This instructs the object “object” to draw itself. If no canvas is opened, a default one (named “c1”) is created. In the next example, the first statement defines a function and the second one draws it. A default canvas is created since there was no opened one. You should see the picture as shown in the next figure.

root[] TF1 f1("func1","sin(x)/x",0,10)
root[] f1.Draw()
<TCanvas::MakeDefCanvas>: created default TCanvas with name c1

The following components comprise the canvas window:

• Menu bar - contains main menus for global operations with files, print, clear canvas, inspect, etc.

• Tool bar - has buttons for global and drawing operations; such as arrow, ellipse, latex, pad, etc.

• Canvas - an area to draw objects.

• Status bar - displays descriptive messages about the selected object.

• Editor frame - responds dynamically and presents the user interface according to the selected object in the canvas.

At the top of the canvas window are File, Edit, View, Options, Inspect, Classes and Help menus.

• New Canvas: creates a new canvas window in the current ROOT session.

• Open…: popup a dialog to open a file.

• Close Canvas: close the canvas window.

• Save: save the drawing of the current canvas in a format selectable from the submenu. The current canvas name is used as a file name for various formats such as PostScript, GIF, JPEG, C macro file, root file.

• Save As…: popup a dialog for saving the current canvas drawing in a new filename.

• Print: popup a dialog to print the current canvas drawing

• Quit ROOT: exit the ROOT session

There is only one active menu entry in the Edit menu. The others menu entries will be implemented and will become active in the near future.

• Clear: delete all objects in the canvas or in the selected pad according to the selected entry in the submenu.

• Editor: toggles the view of the editor. If it is selected activates and shows up the editor on the left side of the canvas window. According to the selected object, the editor loads the corresponding user interface for easy change of the object’s attributes.

• Toolbar: toggles the view of the toolbar. If it is selected activates and shows up the toolbar. It contains buttons for easy and fast access to most frequently used commands and for graphics primitive drawing. Tool tips are provided for helping users.

• Status Bar: toggles the view of the status bar. If it is selected, the status bar below the canvas window shows up. There the identification of the objects is displayed when moving the mouse (such as the object’s name, the object’s type, its coordinates, etc.).

• Colors: creates a new canvas showing the color palette.

• Markers: creates a new canvas showing the various marker styles.

• Iconify: create the canvas window icon, does not close the canvas

• View With…: If the last selected pad contains a 3-d structure, a new canvas is created with a 3-D picture according to the selection made from the cascaded menu: X3D or OpenGL. The 3-D image can be interactively rotated, zoomed in wire-frame, solid, hidden line or stereo mode.

• Auto Resize Canvas: turns auto-resize of the canvas on/off:

• on - the canvas fits to the window when changing the window size;
• off - the canvas stays fixed when changing the window size.
• Resize Canvas: resizes and fits the canvas to the window size.

• Move Opaque: if selected, graphics objects are moved in opaque mode; otherwise, only the outline of objects is drawn when moving them. The option opaque produces the best effect but it requires a reasonably fast workstation or response time.

• Resize Opaque: if selected, graphics objects are resized in opaque mode; otherwise, only the outline of objects is drawn when resizing them.

• Interrupt: interrupts the current drawing process.

• Refresh: redraws the canvas contents.

• Pad Auto Exec: executes the list of TExecs in the current pad.

• Statistics: toggles the display of the histogram statistics box.

• Histogram Title: toggles the display of the histogram title.

• Fit Parameters: toggles the display of the histogram or graph fit parameters.

• Can Edit Histogram: enables/disables the possibility to edit histogram bin contents.

• ROOT: inspects the top-level gROOT object (in a new canvas).

• Start Browser: starts a new object browser (in a separate window).

• GUI Builder: starts the GUI builder application (in a separate window).

• Canvas: help on canvas as a whiteboard area for drawing.

• Graphics Editor: help on primitives’ drawing and objects’ editor.

• Browser: help on the ROOT objects’ and files’ browser.

• Objects: help on DrawClass, Inspect and Dump context menu items.

• PostScript: help on how to print a canvas to a PostScript file format.

• About ROOT: pops up the ROOT Logo with the version number.

• Classes: starts the ClassTree viewer that draws inheritance tree for a list of classes.

#### 2.3.1.8 Toolbar

The following menu shortcuts and utilities are available from the toolbar:

Create a new canvas window.

Popup the Open File dialog.

Popup the Save As… dialog.

Popup the Print dialog.

Interrupts the current drawing process.

Redraw the canvas.

Inspect the gROOT object.

Create a new objects’ browser.

You can create the following graphical objects using the toolbar buttons for primitive drawing. Tool tips are provided for helping your choice.

An Arc or circle: Click on the center of the arc, and then move the mouse. A rubber band circle is shown. Click again with the left button to freeze the arc.

A Line: Click with the left button at the point where you want to start the line, then move the mouse and click again with the left button to freeze the line.

An Arrow:Click with the left button at the point where you want to start the arrow, then move the mouse and click again with the left button to freeze the arrow.

A Diamond: Click with the left button and freeze again with the left button. The editor draws a rubber band box to suggest the outline of the diamond.

An Ellipse: Proceed like for an arc. You can grow/shrink the ellipse by pointing to the sensitive points. They are highlighted. You can move the ellipse by clicking on the ellipse, but not on the sensitive points. If, with the ellipse context menu, you have selected a fill area color, you can move a filled-ellipse by pointing inside the ellipse and dragging it to its new position.

A Pad: Click with the left button and freeze again with the left button. The editor draws a rubber band box to suggest the outline of the pad.

A PaveLabel: Proceed like for a pad. Type the text of label and finish with a carriage return. The text will appear in the box.

A Pave Text: Proceed like for a pad. You can then click on the TPaveText object with the right mouse button and select the option InsertText.

Paves Text: Proceed like for a TPaveText.

A Poly Line: Click with the left button for the first point, move the moose, click again with the left button for a new point. Close the poly-line with a double click. To edit one vertex point, pick it with the left button and drag to the new point position.

A Curly Line: Proceed as for the arrow or line. Once done, click with the third button to change the characteristics of the curly line, like transform it to wave, change the wavelength, etc.

A Curly Arc: Proceed like for an ellipse. The first click is located at the position of the center, the second click at the position of the arc beginning. Once done, one obtains a curly ellipse, for which one can click with the third button to change the characteristics, like transform it to wavy, change the wavelength, set the minimum and maximum angle to make an arc that is not closed, etc.

A Text/Latex string: Click with the left button where you want to draw the text and then type in the text terminated by carriage return. All TLatex expressions are valid. To move the text or formula, point on it keeping the left mouse button pressed and drag the text to its new position. You can grow/shrink the text if you position the mouse to the first top-third part of the string, then move the mouse up or down to grow or shrink the text respectively. If you position the mouse near the bottom-end of the text, you can rotate it.

A Marker: Click with the left button where to place the marker. The marker can be modified by using the method SetMarkerStyle() of TSystem.

A Graphical Cut: Click with the left button on each point of a polygon delimiting the selected area. Close the cut by double clicking on the last point. A TCutG object is created. It can be used as a selection for a TTree::Draw. You can get a pointer to this object with:

TCutG cut = (TCutG*)gPad->GetPrimitive("CUTG")

Once you are happy with your picture, you can select the Save as canvas.C item in the canvas File menu. This will automatically generate a script with the C++ statements corresponding to the picture. This facility also works if you have other objects not drawn with the graphics editor (histograms for example).

### 2.3.2 The Editor Frame

The ROOT graphics editor loads the corresponding object editor objEditor according to the selected object obj in the canvas respecting the class inheritance. An object in the canvas is selected after the left mouse click on it. For example, if the selected object is TAxis, the TAxisEditor will shows up in the editor frame giving the possibility for changing different axis attributes. The graphics editor can be:

Embedded - connected only with the canvas in the application window that appears on the left of the canvas window after been activated via View menu / Editor. It appears on the left side if the canvas window allowing users to edit the attributes of the selected object via provided user interface. The name of the selected object is displayed on the top of the editor frame in red color. If the user interface needs more space then the height of the canvas window, a vertical scroll bar appears for easer navigation.

Global - has own application window and can be connected to any created canvas in a ROOT session. It can be activated via the context menu entries for setting line, fill, text and marker attributes for backward compatibility, but there will be a unique entry in the near future.

The user interface for the following classes is available since ROOT v.4.04: TAttLine, TAttFill, TAttMarker, TAttText, TArrow, TAxis, TCurlyArc, TCurlyLine, TFrame, TH1, TH2, TGraph, TPad, TCanvas, TPaveStats. For more details, see “The Graphics Editor”, “The User Interface for Histograms”, “The User Interface for Graphs”.

### 2.3.3 Classes, Methods and Constructors

Object oriented programming introduces objects, which have data members and methods. The next line creates an object named f1 of the class TF1 that is a one-dimensional function. The type of an object is called a class. The object itself is called an instance of a class. When a method builds an object, it is called a constructor.

TF1 f1("func1","sin(x)/x",0,10)

In our constructor the function sin(x)/x is defined for use, and 0 and 10 are the limits. The first parameter, func1 is the name of the object f1. Most objects in ROOT have a name. ROOT maintains a list of objects that can be searched to find any object by its given name (in our example func1).

The syntax to call an object’s method, or if one prefers, to make an object to do something is:

object.method_name(parameters)

The dot can be replaced by “->” if object is a pointer. In compiled code, the dot MUST be replaced by a “->” if object is a pointer.

object_ptr->method_name(parameters)

So now, we understand the two lines of code that allowed us to draw our function. f1.Draw() stands for “call the method Draw() associated with the object f1 of the class TF1”. Other methods can be applied to the object f1 of the class TF1. For example, the evaluating and calculating the derivative and the integral are what one would expect from a function.

root[] f1.Eval(3)
(Double_t)4.70400026866224020e-02
root[] f1.Derivative(3)
(Double_t)(-3.45675056671992330e-01)
root[] f1.Integral(0,3)
(Double_t)1.84865252799946810e+00
root[] f1.Draw()

By default the method TF1::Paint(), that draws the function, computes 100 equidistant points to draw it. The number of points can be set to a higher value with:

root[] f1.SetNpx(2000);

Note that while the ROOT framework is an object-oriented framework, this does not prevent the user from calling plain functions.

### 2.3.4 User Interaction

Now we will look at some interactive capabilities. Try to draw the function sin(x)/x again. Every object in a window (which is called a canvas) is, in fact, a graphical object in the sense that you can grab it, resize it, and change its characteristics with a mouse click. For example, bring the cursor over the x-axis. The cursor changes to a hand with a pointing finger when it is over the axis. Now, left click and drag the mouse along the axis to the right. You have a very simple zoom.

When you move the mouse over any object, you can get access to selected methods by pressing the right mouse button and obtaining a context menu. If you try this on the function TF1, you will get a menu showing available methods. The other objects on this canvas are the title, a TPaveText object; the x and y-axis, TAxis objects, the frame, a TFrame object, and the canvas a TCanvas object. Try clicking on these and observe the context menu with their methods.

For example try selecting the SetRange() method and putting -10, 10 in the dialog box fields. This is equivalent to executing f1.SetRange(-10,10) from the command line, followed by f1.Draw(). Here are some other options you can try.

Once the picture suits your wishes, you may want to see the code you should put in a script to obtain the same result. To do that, choose Save / canvas.C entry of the File menu. This will generate a script showing the options set in the current canvas. Notice that you can also save the picture into various file formats such as PostScript, GIF, etc. Another interesting possibility is to save your canvas into the native ROOT format (.rootfile). This will enable you to open it again and to change whatever you like. All objects associated to the canvas (histograms, graphs) are saved at the same time.

### 2.3.5 Building a Multi-pad Canvas

Let us now try to build a canvas with several pads.

root[] TCanvas *MyC = new TCanvas("MyC","Test canvas",1)
root[] MyC->Divide(2,2)

Once again, we call the constructor of a class, this time the class TCanvas. The difference between this and the previous constructor call (TF1) is that here we are creating a pointer to an object. Next, we call the method Divide() of the TCanvas class (that is TCanvas::Divide()), which divides the canvas into four zones and sets up a pad in each of them. We set the first pad as the active one and than draw the functionf1there.

root[] MyC->cd(1)
root[] f1->Draw()

All objects will be drawn in that pad because it is the active one. The ways for changing the active pad are:

• Click the middle mouse button on a pad will set this pad as the active one.

• Use the method TCanvas::cd() with the pad number, as was done in the example above:

root[] MyC->cd(3)

Pads are numbered from left to right and from top to bottom. Each new pad created by TCanvas::Divide() has a name, which is the name of the canvas followed by _1, _2, etc. To apply the method cd() to the third pad, you would write:

root[] MyC_3->cd()
• Third pad will be selected since you called TPad::cd() for the object MyC_3. ROOT will find the pad that was namedMyC_3when you typed it on the command line (see ROOT/Cling Extensions to C++).

### 2.3.6 Saving the Canvas

Using the File menu / Save cascade menu users can save the canvas as one of the files from the list. Please note that saving the canvas this way will overwrite the file with the same name without a warning.

All supported file types can be saved via File menu / SaveAs… This dialog gives a choice to show or suppress the confirmation message for overwriting an existing file.

If the Overwrite check box is not selected, a message dialog appears asking the user to overwrite the file (Yes/No). The user choice is saved for the next time the Save As… dialog shows up.

### 2.3.7 Printing the Canvas

The Print command in the canvas File menu pops-up a print dialog where the user can specify a preferred print command and the printer name.

Both print parameters can be set via the new Print.Command and Print.Printer rootrc resources as follows:

# Printer settings.
WinNT.*.Print.Command:    AcroRd32.exe
Unix.*.Print.Command:     xprint -P%p %f
Print.Printer:            32-rb205-hp
Print.Directory:          .

If the %p and %f are specified as a part of the print command, they will be replaced by the specified printer name and the file name. All other parameters will be kept as they are written. A print button is available in the canvas toolbar (activated via View menu/Toolbar).

## 2.4 The ROOT Command Line

We have briefly touched on how to use the command line. There are different types of commands.

1. Cling commands start with “.
root[] .?  //this command will list all the Cling commands
root[] .x <filename>  //load and execute [filename]
1. SHELL commands start with “.!” for example:
root[] .! ls
1. C++ commands follow C++ syntax (almost)
root[] TBrowser *b = new TBrowser()

### 2.4.1 Multi-line Commands

You can use the command line to execute multi-line commands. To begin a multi-line command you must type a single left curly bracket {, and to end it you must type a single right curly bracket }. For example:

root[] {
end with '}'> Int_t j = 0;
end with '}'> for (Int_t i = 0; i < 3; i++)
end with '}'> {
end with '}'> j= j + i;
end with '}'> cout << "i = " << i << ", j = " << j << endl;
end with '}'> }
end with '}'> }
i = 0, j = 0
i = 1, j = 1
i = 2, j = 3

It is more convenient to edit a script than the command line, and if your multi line commands are getting unmanageable, you may want to start with a script instead.

### 2.4.2 Cling Extensions

We should say that some things are not standard C++. The Cling interpreter has several extensions. See “ROOT/Cling Extensions to C++”.

### 2.4.3 Helpful Hints for Command Line Typing

The interpreter knows all the classes, functions, variables, and user defined types. This enables ROOT to help users to complete the command line. For example, if we do not know anything about the TLine class, the Tab feature helps us to get a list of all classes starting with TL(where <TAB> means type the Tab key).

root[] l = new TLi<TAB>
TList
TListIter
TLine
TLimitDataSource
TLimit

To list the different constructors and parameters for TLine use the <TAB> key as follows:

root[] l = new TLine(<TAB>
TLine TLine()
TLine TLine(Double_t x1,Double_t y1,Double_t x2,Double_t y2)
TLine TLine(const TLine& line)

### 2.4.4 Regular Expression

The meta-characters below can be used in a regular expression:

• ^’ start-of-line anchor

• $’ end-of-line anchor • .’ matches any character • [’ start a character class • ]’end a character class • ^’negates character class if first character • *Kleene closure (matches 0 or more) • +’Positive closure (1 or more) • ?’ Optional closure (0 or 1) When using wildcards the regular expression is assumed to be preceded by a ‘^’ (BOL) and terminated by ‘$’ (EOL). All ‘*’ (closures) are assumed to be preceded by a ‘.’, i.e. any character, except slash _/_. Its special treatment allows the easy matching of pathnames. For example, _*.root_ will match _aap.root_, but not _pipo/aap.root_.

The escape characters are:

• \ backslash

• b backspace

• f form feed

• n new line

• r carriage return

• s space

• t tab

• e ASCII ESC character (‘033’)

• DDD number formed of 1-3 octal digits

• xDD number formed of 1-2 hex digits

• ^C C = any letter. Control code

The class TRegexp can be used to create a regular expression from an input string. If wildcard is true then the input string contains a wildcard expression.

TRegexp(const char *re, Bool_t wildcard)

Regular expression and wildcards can be easily used in methods like:

Ssiz_t Index(const TString& string,Ssiz_t* len,Ssiz_t i) const

The method finds the first occurrence of the regular expression in the string and returns its position.

## 2.5 Conventions

In this paragraph, we will explain some of the conventions used in ROOT source and examples.

### 2.5.1 Coding Conventions

From the first days of ROOT development, it was decided to use a set of coding conventions. This allows a consistency throughout the source code. Learning these will help you identify what type of information you are dealing with and enable you to understand the code better and quicker. Of course, you can use whatever convention you want but if you are going to submit some code for inclusion into the ROOT sources, you will need to use these.

These are the coding conventions:

• Classes begin with T: TLine, TTree

• Non-class types end with _t: Int_t

• Data members begin with f: fTree

• Member functions begin with a capital: Loop()

• Constants begin with k: kInitialSize, kRed

• Global variables begin with g: gEnv

• Static data members begin with fg: fgTokenClient

• Enumeration types begin with E: EColorLevel

• Locals and parameters begin with a lower case: nbytes

• Getters and setters begin with Get and Set: SetLast(), GetFirst()

### 2.5.2 Machine Independent Types

Different machines may have different lengths for the same type. The most famous example is the int type. It may be 16 bits on some old machines and 32 bits on some newer ones. To ensure the size of your variables, use these pre defined types in ROOT:

• Char_t Signed Character 1 byte

• UChar_t Unsigned Character 1 byte

• Short_t Signed Short integer 2 bytes

• UShort_t Unsigned Short integer 2 bytes

• Int_t Signed integer 4 bytes

• UInt_tUnsigned integer 4 bytes

• Long64_t Portable signed long integer 8 bytes

• ULong64_t Portable unsigned long integer 8 bytes

• Float_t Float 4 bytes

• Double_t Float 8 bytes

• Double32_t Double 8 bytes in memory, written as a Float 4 bytes

• Bool_t Boolean (0=false, 1=true)

If you do not want to save a variable on disk, you can use int or Int_t, the result will be the same and the interpreter or the compiler will treat them in exactly the same way.

### 2.5.3 TObject

In ROOT, almost all classes inherit from a common base class called TObject. This kind of architecture is also used in the Java language. The TObject class provides default behavior and protocol for all objects in the ROOT system. The main advantage of this approach is that it enforces the common behavior of the derived classes and consequently it ensures the consistency of the whole system. See “The Role of TObject”.

TObject provides protocol, i.e. (abstract) member functions, for:

• Object I/O (Read(), Write())

• Error handling (Warning(), Error(), SysError(), Fatal())

• Sorting (IsSortable(), Compare(), IsEqual(), Hash())

• Inspection (Dump(), Inspect())

• Printing (Print())

• Drawing (Draw(), Paint(), ExecuteEvent())

• Bit handling (SetBit(), TestBit())

• Memory allocation (operatornew and delete, IsOnHeap())

• Access to meta information (IsA(), InheritsFrom())

• Object browsing (Browse(), IsFolder())

## 2.6 Global Variables

ROOT has a set of global variables that apply to the session. For example, gDirectory always holds the current directory, and gStyle holds the current style.

All global variables begin with “g” followed by a capital letter.

### 2.6.1 gROOT

The single instance of TROOT is accessible via the global gROOT and holds information relative to the current session. By using the gROOT pointer, you get the access to every object created in a ROOT program. The TROOT object has several lists pointing to the main ROOT objects. During a ROOT session, the gROOT keeps a series of collections to manage objects. They can be accessed via gROOT::GetListOf... methods.

gROOT->GetListOfClasses()
gROOT->GetListOfColors()
gROOT->GetListOfTypes()
gROOT->GetListOfGlobals()
gROOT->GetListOfGlobalFunctions()
gROOT->GetListOfFiles()
gROOT->GetListOfMappedFiles()
gROOT->GetListOfSockets()
gROOT->GetListOfCanvases()
gROOT->GetListOfStyles()
gROOT->GetListOfFunctions()
gROOT->GetListOfSpecials()
gROOT->GetListOfGeometries()
gROOT->GetListOfBrowsers()
gROOT->GetListOfMessageHandlers()

These methods return a TSeqCollection, meaning a collection of objects, and they can be used to do list operations such as finding an object, or traversing the list and calling a method for each of the members. See the TCollection class description for the full set of methods supported for a collection. For example, to find a canvas called c1you can do:

root[] gROOT->GetListOfCanvases()->FindObject("c1")

This returns a pointer to a TObject, and before you can use it as a canvas you need to cast it to a TCanvas*.

### 2.6.2 gFile

gFile is the pointer to the current opened file in the ROOT session.

### 2.6.3 gDirectory

gDirectory is a pointer to the current directory. The concept and role of a directory is explained in the chapter “Input/Output”.

A graphic object is always drawn on the active pad. It is convenient to access the active pad, no matter what it is. For that, we have gPad that is always pointing to the active pad. For example, if you want to change the fill color of the active pad to blue, but you do not know its name, you can use gPad.

root[] gPad->SetFillColor(38)

To get the list of colors, if you have an open canvas, click in the “View” menu, selecting the “Colors” entry.

### 2.6.5 gRandom

gRandom is a pointer to the current random number generator. By default, it points to a TRandom3 object, based on the “Mersenne-Twister” generator. This generator is very fast and has very good random proprieties (a very long period of 10600). Setting the seed to 0 implies that the seed will be uniquely generated using the TUUID. Any other value will be used as a constant. The following basic random distributions are provided: Rndm() or Uniform(min,max), Gaus(mean,sigma), Exp(tau), BreitWigner(mean,sigma), Landau(mean,sigma), Poisson(mean), Binomial(ntot,prob). You can customize your ROOT session by replacing the random number generator. You can delete gRandom and recreate it with your own. For example:

root[] delete gRandom;
root[] gRandom = new TRandom2(0); //seed=0

TRandom2 is another generator, which is also very fast and uses only three words for its state.

gEnv is the global variable (of type TEnv) with all the environment settings for the current session. This variable is set by reading the contents of a .rootrc file (or $ROOTSYS/etc/system.rootrc) at the beginning of the root session. See Environment Setup below for more information. ## 2.7 Environment Setup The behavior of a ROOT session can be tailored with the options in the .rootrc file. At start-up, ROOT looks for a .rootrc file in the following order: • ./.rootrc //local directory • $HOME/.rootrc //user directory

• $ROOTSYS/etc/system.rootrc //global ROOT directory If more than one .rootrc files are found in the search paths above, the options are merged, with precedence local, user, global. While in a session, to see current settings, you can do: root[] gEnv->Print() The rootrc file typically looks like: # Path used by dynamic loader to find shared libraries Unix.*.Root.DynamicPath: .:~/rootlibs:$(ROOTSYS)/lib
Unix.*.Root.MacroPath:    .:~/rootmacros:$(ROOTSYS)/macros # Path where to look for TrueType fonts Unix.*.Root.UseTTFonts: true Unix.*.Root.TTFontPath: ... # Activate memory statistics Rint.Load: rootalias.C Rint.Logon: rootlogon.C Rint.Logoff: rootlogoff.C ... Rint.Canvas.MoveOpaque: false Rint.Canvas.HighLightColor: 5 The various options are explained in $ROOTSYS/etc/system.rootrc. The .rootrc file contents are combined. For example, if the flag to use true type fonts is set to true in the system.rootrc file, you have to set explicitly it false in your local .rootrc file if you do not want to use true type fonts. Removing the UseTTFontsstatement in the local .rootrc file will not disable true fonts. The value of the environment variable ROOTDEBUG overrides the value in the .rootrc file at startup. Its value is used to set gDebug and helps for quick turn on debug mode in TROOT startup.

ROOT looks for scripts in the path specified in the .rootrc file in the Root.Macro.Path variable. You can expand this path to hold your own directories.

### 2.7.1 Logon and Logoff Scripts

The rootlogon.C and rootlogoff.C files are scripts loaded and executed at start-up and shutdown. The rootalias.C file is loaded but not executed. It typically contains small utility functions. For example, the rootalias.C script that comes with the ROOT distributions (located in $ROOTSYS/tutorials) defines the function edit(char *file). This allows the user to call the editor from the command line. This particular function will start the VI editor if the environment variable EDITOR is not set. root[0] edit("c1.C") For more details, see $ROOTSYS/tutorials/rootalias.C.

You can use the up and down arrow at the command line, to access the previous and next command. The commands are recorded in the history file $HOME/.root_hist. It is a text file, and you can edit, cut, and paste from it. You can specify the history file in the system.rootrc file, by setting the Rint.Historyoption. You can also turn off the command logging in the system.rootrc file with the option: Rint.History: - The number of history lines to be kept can be set also in .rootrc by: Rint.HistSize: 500 Rint.HistSave: 400 The first value defines the maximum of lines kept; once it is reached all, the last HistSave lines will be removed. One can set HistSize to 0 to disable history line management. There is also implemented an environment variable called ROOT_HIST. By setting ROOT_HIST=300:200 the above values can be overriden - the first value corresponds to HistSize, the (optional) second one to HistSave. You can set ROOT_HIST=0 to disable the history. ### 2.7.3 Tracking Memory Leaks You can track memory usage and detect leaks by monitoring the number of objects that are created and deleted (see TObjectTable). To use this facility, edit the file $ROOTSYS/etc/system.rootrc or .rootrc if you have this file and add the two following lines:

Root.ObjectStat:         1

In your code or on the command line you can type the line:

gObjectTable->Print();

This line will print the list of all active classes and the number of instances for each class. By comparing consecutive print outs, you can see objects that you forgot to delete. Note that this method cannot show leaks coming from the allocation of non-objects or classes unknown to ROOT.

## 2.8 Converting from PAW to ROOT

The web page at: http://root.cern.ch/root/HowtoConvertFromPAW.html#TABLE gives the “translation” table of some commonly used PAW commands into ROOT. If you move the mouse cursor over the picture at: http://root.cern.ch/root/HowtoConvertFromPAW.html#SET, you will get the corresponding ROOT commands as tooltips.

### 2.8.1 Converting HBOOK/PAW Files

ROOT has a utility called h2root that you can use to convert your HBOOK/PAW histograms or ntuple files into ROOT files. To use this program, you type the shell script command:

h2root  <hbookfile>  <rootfile>

If you do not specify the second parameter, a file name is automatically generated for you. If hbookfile is of the form file.hbook, then the ROOT file will be called file.root. This utility converts HBOOK histograms into ROOT histograms of the class TH1F. HBOOK profile histograms are converted into ROOT profile histograms (see class TProfile). HBOOK row-wise and column-wise ntuples are automatically converted to ROOT Trees. See “Trees”. Some HBOOK column-wise ntuples may not be fully converted if the columns are an array of fixed dimension (e.g. var[6]) or if they are a multi-dimensional array.

HBOOK integer identifiers are converted into ROOT named objects by prefixing the integer identifier with the letter “h” if the identifier is a positive integer and by "h_" if it is a negative integer identifier. In case of row-wise or column-wise ntuples, each column is converted to a branch of a tree. Note that h2root is able to convert HBOOK files containing several levels of sub-directories. Once you have converted your file, you can look at it and draw histograms or process ntuples using the ROOT command line. An example of session is shown below:

// this connects the file hbookconverted.root
root[] TFile f("hbookconverted.root");

// display histogram named h10 (was HBBOK id 10)
root[] h10.Draw();

// display column "var" from ntuple h30
root[] h30.Draw("var");

You can also use the ROOT browser (see TBrowser) to inspect this file.

The chapter on trees explains how to read a tree. ROOT includes a function TTree::MakeClass to generate automatically the code for a skeleton analysis function. See “Example Analysis”.

In case one of the ntuple columns has a variable length (e.g. px(ntrack)), h.Draw("px") will histogram the px column for all tracks in the same histogram. Use the script quoted above to generate the skeleton function and create/fill the relevant histogram yourself.

# 3 Histograms

This chapter covers the functionality of the histogram classes. We begin with an overview of the histogram classes, after which we provide instructions and examples on the histogram features.

We have put this chapter ahead of the graphics chapter so that you can begin working with histograms as soon as possible. Some of the examples have graphics commands that may look unfamiliar to you. These are covered in the chapter “Input/Output”.

## 3.1 The Histogram Classes

ROOT supports histograms up to three dimensions. Separate concrete classes are provided for one-dimensional, two-dimensional and three-dimensional classes. The histogram classes are split into further categories, depending on the set of possible bin values:

• TH1C, TH2C and TH3C contain one byte per bin (maximum bin content = 255)

• TH1S, TH2S and TH3S contain one short per bin (maximum bin content = 65 535).

• TH1I, TH2I and TH3I contain one integer per bin (maximum bin content = 2 147 483 647).

• TH1F, TH2F and TH3F contain one float per bin (maximum precision = 7 digits).

• TH1D, TH2D and TH3D contain one double per bin (maximum precision = 14 digits).

ROOT also supports profile histograms, which constitute an elegant replacement of two-dimensional histograms in many cases. The inter-relation of two measured quantities X and Y can always be visualized with a two-dimensional histogram or scatter-plot. Profile histograms, on the other hand, are used to display the mean value of Y and its RMS for each bin in X. If Y is an unknown but single-valued approximate function of X, it will have greater precision in a profile histogram than in a scatter plot.

• TProfile : one dimensional profiles

• TProfile2D : two dimensional profiles

All ROOT histogram classes are derived from the base class TH1 (see figure above). This means that two-dimensional and three-dimensional histograms are seen as a type of a one-dimensional histogram, in the same way in which multidimensional C arrays are just an abstraction of a one-dimensional contiguous block of memory.

## 3.2 Creating Histograms

There are several ways in which you can create a histogram object in ROOT. The straightforward method is to use one of the several constructors provided for each concrete class in the histogram hierarchy. For more details on the constructor parameters, see the subsection “Constant or Variable Bin Width” below. Histograms may also be created by:

• Calling the Clone() method of an existing histogram

• Making a projection from a 2-D or 3-D histogram

• Reading a histogram from a file (see Input/Output chapter)

   // using various constructors
TH1* h1 = new TH1I("h1", "h1 title", 100, 0.0, 4.0);
TH2* h2 = new TH2F("h2", "h2 title", 40, 0.0, 2.0, 30, -1.5, 3.5);
TH3* h3 = new TH3D("h3", "h3 title", 80, 0.0, 1.0, 100, -2.0, 2.0,
50, 0.0, 3.0);

// cloning a histogram
TH1* hc = (TH1*)h1->Clone();

// projecting histograms
// the projections always contain double values !
TH1* hx = h2->ProjectionX(); // ! TH1D, not TH1F
TH1* hy = h2->ProjectionY(); // ! TH1D, not TH1F

### 3.2.1 Constant or Variable Bin Width

The histogram classes provide a variety of ways to construct a histogram, but the most common way is to provide the name and title of histogram and for each dimension: the number of bins, the minimum x (lower edge of the first bin) and the maximum x (upper edge of the last bin).

   TH2* h = new TH2D(
/* name */ "h2",
/* title */ "Hist with constant bin width",
/* X-dimension */ 100, 0.0, 4.0,
/* Y-dimension */ 200, -3.0, 1.5);

When employing this constructor, you will create a histogram with constant (fixed) bin width on each axis. For the example above, the interval [0.0, 4.0] is divided into 100 bins of the same width w X = 4.0 - 0.0 100 = 0.04 for the X axis (dimension). Likewise, for the Y axis (dimension), we have bins of equal width w Y = 1.5 - (-3.0) 200 = 0.0225.

If you want to create histograms with variable bin widths, ROOT provides another constructor suited for this purpose. Instead of passing the data interval and the number of bins, you have to pass an array (single or double precision) of bin edges. When the histogram has n bins, then there are n+1 distinct edges, so the array you pass must be of size n+1.

   const Int_t NBINS = 5;
Double_t edges[NBINS + 1] = {0.0, 0.2, 0.3, 0.6, 0.8, 1.0};
// Bin 1 corresponds to range [0.0, 0.2]
// Bin 2 corresponds to range [0.2, 0.3] etc...

TH1* h = new TH1D(
/* name */ "h1",
/* title */ "Hist with variable bin width",
/* number of bins */ NBINS,
/* edge array */ edges
);

Each histogram object contains three TAxis objects: fXaxis , fYaxis, and fZaxis, but for one-dimensional histograms only the X-axis is relevant, while for two-dimensional histograms the X-axis and Y-axis are relevant. See the class TAxis for a description of all the access methods. The bin edges are always stored internally in double precision.

You can examine the actual edges / limits of the histogram bins by accessing the axis parameters, like in the example below:

   const Int_t XBINS = 5; const Int_t YBINS = 5;
Double_t xEdges[XBINS + 1] = {0.0, 0.2, 0.3, 0.6, 0.8, 1.0};
Double_t yEdges[YBINS + 1] = {-1.0, -0.4, -0.2, 0.5, 0.7, 1.0};

TH2* h = new TH2D("h2", "h2", XBINS, xEdges, YBINS, yEdges);
TAxis* xAxis = h->GetXaxis(); TAxis* yAxis = h->GetYaxis();

cout << "Third bin on Y-dimension: " << endl; // corresponds to
// [-0.2, 0.5]
cout << "\tLower edge: " << yAxis->GetBinLowEdge(3) << endl;
cout << "\tCenter: " << yAxis->GetBinCenter(3) << endl;
cout << "\tUpper edge: " << yAxis->GetBinUpEdge(3) << endl;

## 3.3 Bin Numbering

All histogram types support fixed or variable bin sizes. 2-D histograms may have fixed size bins along X and variable size bins along Y or vice-versa. The functions to fill, manipulate, draw, or access histograms are identical in both cases.

### 3.3.1 Convention

For all histogram types: nbins , xlow , xup

Bin# 0 contains the underflow.

Bin# 1 contains the first bin with low-edge ( xlow INCLUDED).

The second to last bin (bin# nbins) contains the upper-edge (xup EXCLUDED).

The Last bin (bin# nbins+1) contains the overflow.

In case of 2-D or 3-D histograms, a “global bin” number is defined. For example, assuming a 3-D histogram h with binx, biny, binz, the function returns a global/linear bin number.

   Int_t bin = h->GetBin(binx, biny, binz);

This global bin is useful to access the bin information independently of the dimension.

### 3.3.2 Re-binning

At any time, a histogram can be re-binned via the TH1::Rebin() method. It returns a new histogram with the re-binned contents. If bin errors were stored, they are recomputed during the re-binning.

## 3.4 Filling Histograms

A histogram is typically filled with statements like:

   h1->Fill(x);
h1->Fill(x,w); // with weight
h2->Fill(x,y);
h2->Fill(x,y,w);
h3->Fill(x,y,z);
h3->Fill(x,y,z,w);

The Fill method computes the bin number corresponding to the given x, y or z argument and increments this bin by the given weight. The Fill() method returns the bin number for 1-D histograms or global bin number for 2-D and 3-D histograms. If TH1::Sumw2() has been called before filling, the sum of squares is also stored. One can increment a bin number directly by calling TH1::AddBinContent(), replace the existing content via TH1::SetBinContent() , and access the bin content of a given bin via TH1::GetBinContent() .

   Double_t binContent = h->GetBinContent(bin);

### 3.4.1 Automatic Re-binning Option

By default, the number of bins is computed using the range of the axis. You can change this to re-bin automatically by setting the automatic re-binning option:

   h->SetBit(TH1::kCanRebin);

Once this is set, the Fill() method will automatically extend the axis range to accommodate the new value specified in the Fill() argument. The used method is to double the bin size until the new value fits in the range, merging bins two by two. The TTree::Draw() method extensively uses this automatic binning option when drawing histograms of variables in TTree with an unknown range. The automatic binning option is supported for 1-D, 2-D and 3-D histograms. During filling, some statistics parameters are incremented to compute the mean value and root mean square with the maximum precision. In case of histograms of type TH1C, TH1S, TH2C, TH2S, TH3C, TH3S a check is made that the bin contents do not exceed the maximum positive capacity (127 or 65 535). Histograms of all types may have positive or/and negative bin contents.

## 3.5 Random Numbers and Histograms

TH1::FillRandom() can be used to randomly fill a histogram using the contents of an existing TF1 function or another TH1 histogram (for all dimensions). For example, the following two statements create and fill a histogram 10 000 times with a default Gaussian distribution of mean 0 and sigma 1 :

root[] TH1F h1("h1","Histo from a Gaussian",100,-3,3);
root[] h1.FillRandom("gaus",10000);

TH1::GetRandom() can be used to get a random number distributed according the contents of a histogram. To fill a histogram following the distribution in an existing histogram you can use the second signature of TH1::FillRandom(). Next code snipped assumes that h is an existing histogram (TH1 ).

root[] TH1F h2("h2","Histo from existing histo",100,-3,3);
root[] h2.FillRandom(&h1, 1000);

The distribution contained in the histogram h1 ( TH1 ) is integrated over the channel contents. It is normalized to one. The second parameter (1000) indicates how many random numbers are generated.

Getting 1 random number implies:

• Generating a random number between 0 and 1 (say r1 )

• Find the bin in the normalized integral for r1

• Fill histogram channel

You can see below an example of the TH1::GetRandom() method which can be used to get a random number distributed according the contents of a histogram.

void getrandomh() {
TH1F *source = new TH1F("source","source hist",100,-3,3);
source->FillRandom("gaus",1000);
TH1F *final = new TH1F("final","final hist",100,-3,3);

// continued...

for (Int_t i=0;i<10000;i++) {
final->Fill(source->GetRandom());
}
TCanvas *c1 = new TCanvas("c1","c1",800,1000);
c1->Divide(1,2);
c1->cd(1);
source->Draw();
c1->cd(2);
final->Draw();
c1->cd();
}

## 3.6 Adding, Dividing, and Multiplying

Many types of operations are supported on histograms or between histograms:

• Addition of a histogram to the current histogram

• Additions of two histograms with coefficients and storage into the current histogram

• Multiplications and divisions are supported in the same way as additions.

• The Add , Divide and Multiply methods also exist to add, divide or multiply a histogram by a function.

Histograms objects (not pointers) TH1F h1 can be multiplied by a constant using:

   h1.Scale(const)

A new histogram can be created without changing the original one by doing:

   TH1F h3 = 8*h1;

To multiply two histogram objects and put the result in a 3rd one do:

   TH1F h3 = h1*h2;

The same operations can be done with histogram pointers TH1F *h1, *h2 following way:

   h1->Scale(const) TH1F h3 = 8*(*h1); TH1F h3 = (*h1)*(*h2);

Of course, the TH1 methods Add , Multiply and Divide can be used instead of these operators.

If a histogram has associated error bars ( TH1::Sumw2() has been called), the resulting error bars are also computed assuming independent histograms. In case of divisions, binomial errors are also supported.

## 3.7 Projections

One can make:

• a 1-D projection of a 2-D histogram or profile. See TH2::ProfileX, TH2::ProfileY,TProfile::ProjectionX, TProfile2D::ProjectionXY, TH2::ProjectionX, TH2::ProjectionY .

• a 1-D, 2-D or profile out of a 3-D histogram see TH3::ProjectionZ, TH3::Project3D.

These projections can be fit via: TH2::FitSlicesX, TH2::FitSlicesY, TH3::FitSlicesZ.

## 3.8 Drawing Histograms

When you call the Draw method of a histogram ( TH1::Draw ) for the first time, it creates a THistPainter object and saves a pointer to painter as a data member of the histogram. The THistPainter class specializes in the drawing of histograms. It allows logarithmic axes (x, y, z) when the CONT drawing option is using. The THistPainter class is separated from the histogram so that one can have histograms without the graphics overhead, for example in a batch program. The choice to give each histogram has its own painter rather than a central singleton painter, allows two histograms to be drawn in two threads without overwriting the painter’s values. When a displayed histogram is filled again, you do not have to call the Draw method again. The image is refreshed the next time the pad is updated. A pad is updated after one of these three actions:

• A carriage control on the ROOT command line

• A click inside the pad

• A call to TPad::Update()

By default, the TH1::Draw clears the pad before drawing the new image of the histogram. You can use the "SAME" option to leave the previous display intact and superimpose the new histogram. The same histogram can be drawn with different graphics options in different pads. When a displayed histogram is deleted, its image is automatically removed from the pad. To create a copy of the histogram when drawing it, you can use TH1::DrawClone(). This will clone the histogram and allow you to change and delete the original one without affecting the clone. You can use TH1::DrawNormalized() to draw a normalized copy of a histogram.

TH1 *TH1::DrawNormalized(Option_t *option,Double_t norm) const

A clone of this histogram is normalized to norm and drawn with option. A pointer to the normalized histogram is returned. The contents of the histogram copy are scaled such that the new sum of weights (excluding under and overflow) is equal to norm .

Note that the returned normalized histogram is not added to the list of histograms in the current directory in memory. It is the user’s responsibility to delete this histogram. The kCanDelete bit is set for the returned object. If a pad containing this copy is cleared, the histogram will be automatically deleted. See “Draw Options” for the list of options.

### 3.8.1 Setting the Style

Histograms use the current style gStyle, which is the global object of class TStyle. To change the current style for histograms, the TStyle class provides a multitude of methods ranging from setting the fill color to the axis tick marks. Here are a few examples:

   void SetHistFillColor(Color_t color = 1)
void SetHistFillStyle(Style_t styl = 0)
void SetHistLineColor(Color_t color = 1)
void SetHistLineStyle(Style_t styl = 0)
void SetHistLineWidth(Width_t width = 1)

When you change the current style and would like to propagate the change to a previously created histogram you can call TH1::UseCurrentStyle(). You will need to call UseCurrentStyle() on each histogram. When reading many histograms from a file and you wish to update them to the current style, you can use gROOT::ForceStyle and all histograms read after this call will be updated to use the current style. See “Graphics and the Graphical User Interface”. When a histogram is automatically created as a result of a TTree::Draw , the style of the histogram is inherited from the tree attributes and the current style is ignored. The tree attributes are the ones set in the current TStyle at the time the tree was created. You can change the existing tree to use the current style, by calling TTree::UseCurrentStyle() .

### 3.8.2 Draw Options

The following draw options are supported on all histogram classes:

• AXIS”: Draw only the axis.

• HIST”: When a histogram has errors, it is visualized by default with error bars. To visualize it without errors use HIST together with the required option (e.g. “HIST SAME C”).

• SAME”: Superimpose on previous picture in the same pad.

• CYL”: Use cylindrical coordinates.

• POL”: Use polar coordinates.

• SPH”: Use spherical coordinates.

• PSR”: Use pseudo-rapidity/phi coordinates.

• LEGO”: Draw a lego plot with hidden line removal.

• LEGO1”: Draw a lego plot with hidden surface removal.

• LEGO2”: Draw a lego plot using colors to show the cell contents.

• SURF”: Draw a surface plot with hidden line removal.

• SURF1”: Draw a surface plot with hidden surface removal.

• SURF2”: Draw a surface plot using colors to show the cell contents.

• SURF3”: Same as SURF with a contour view on the top.

• SURF4”: Draw a surface plot using Gouraud shading.

• SURF5”: Same as SURF3 but only the colored contour is drawn. Used with option CYL , SPH or PSR it allows to draw colored contours on a sphere, a cylinder or in a pseudo rapidly space. In Cartesian or polar coordinates, option SURF3 is used.

The following options are supported for 1-D histogram classes:

• AH”: Draw the histogram, but not the axis labels and tick marks

• B”: Draw a bar chart

• C”: Draw a smooth curve through the histogram bins

• E”: Draw the error bars

• E0”: Draw the error bars including bins with 0 contents

• E1”: Draw the error bars with perpendicular lines at the edges

• E2”: Draw the error bars with rectangles

• E3”: Draw a fill area through the end points of the vertical error bars

• E4”: Draw a smoothed filled area through the end points of the error bars

• L”: Draw a line through the bin contents

• P”: Draw a (poly)marker at each bin using the histogram’s current marker style

• P0”: Draw current marker at each bin including empty bins

• PIE”: Draw a Pie Chart

• *H”: Draw histogram with a * at each bin

• LF2”: Draw histogram as with option “L” but with a fill area. Note that “L” also draws a fill area if the histogram fill color is set but the fill area corresponds to the histogram contour.

• 9”: Force histogram to be drawn in high resolution mode. By default, the histogram is drawn in low resolution in case the number of bins is greater than the number of pixels in the current pad

• ][”: Draw histogram without the vertical lines for the first and the last bin. Use it when superposing many histograms on the same picture.

The following options are supported for 2-D histogram classes:

• ARR”: Arrow mode. Shows gradient between adjacent cells

• BOX”: Draw a box for each cell with surface proportional to contents

• BOX1”: A sunken button is drawn for negative values, a raised one for positive values

• COL”: Draw a box for each cell with a color scale varying with contents

• COLZ”: Same as “COL” with a drawn color palette

• CONT”: Draw a contour plot (same as CONT0 )

• CONTZ”: Same as “CONT” with a drawn color palette

• CONT0”: Draw a contour plot using surface colors to distinguish contours

• CONT1”: Draw a contour plot using line styles to distinguish contours

• CONT2”: Draw a contour plot using the same line style for all contours

• CONT3”: Draw a contour plot using fill area colors

• CONT4”: Draw a contour plot using surface colors (SURF2 option at theta = 0)

• "CONT5": Use Delaunay triangles to compute the contours

• LIST”: Generate a list of TGraph objects for each contour

• FB”: To be used with LEGO or SURFACE , suppress the Front-Box

• BB”: To be used with LEGO or SURFACE , suppress the Back-Box

• A”: To be used with LEGO or SURFACE , suppress the axis

• SCAT”: Draw a scatter-plot (default)

• SPEC”: Use TSpectrum2Painter tool for drawing

• TEXT”: Draw bin contents as text (format set via gStyle->SetPaintTextFormat) .

• TEXTnn”: Draw bin contents as text at angle nn ( 0<nn<90 ).

• [cutg]”: Draw only the sub-range selected by the TCutG name “cutg”.

• Z”: The “Z” option can be specified with the options: BOX, COL, CONT, SURF, and LEGO to display the color palette with an axis indicating the value of the corresponding color on the right side of the picture.

The following options are supported for 3-D histogram classes:

• " " : Draw a 3D scatter plot.

• BOX”: Draw a box for each cell with volume proportional to contents

• LEGO”: Same as “BOX

• ISO”: Draw an iso surface

• FB”: Suppress the Front-Box

• BB”: Suppress the Back-Box

• A”: Suppress the axis

Most options can be concatenated without spaces or commas, for example, if h is a histogram pointer:

  h->Draw("E1SAME");
h->Draw("e1same");

The options are not case sensitive. The options BOX , COL and COLZ use the color palette defined in the current style (see TStyle::SetPalette). The options CONT , SURF , and LEGO have by default 20 equidistant contour levels, you can change the number of levels with TH1::SetContour. You can also set the default drawing option with TH1::SetOption . To see the current option use TH1::GetOption . For example:

   h->SetOption("lego");
h->Draw(); // will use the lego option
h->Draw("scat") // will use the scatter plot option

#### 3.8.2.1 The SCATter Plot Option

By default, 2D histograms are drawn as scatter plots. For each cell (i,j) a number of points proportional to the cell content are drawn. A maximum of 500 points per cell are drawn. If the maximum is above 500 contents are normalized to 500.

#### 3.8.2.2 The ARRow Option

The ARR option shows the gradient between adjacent cells. For each cell (i,j) an arrow is drawn. The orientation of the arrow follows the cell gradient.

#### 3.8.2.3 The BOX Option

For each cell (i,j) a box is drawn with surface proportional to contents. The size of the box is proportional to the absolute value of the cell contents. The cells with negative contents are drawn with an X on top of the boxes. With option BOX1 a button is drawn for each cell with surface proportional to contents’ absolute value. A sunken button is drawn for negative values, a raised one for positive values.

#### 3.8.2.4 The ERRor Bars Options

• "E" Default. Draw only error bars, without markers

• "E0" Draw also bins with 0 contents (turn off the symbols clipping).

• "E1" Draw small lines at the end of error bars

• "E2" Draw error rectangles

• "E3" Draw a fill area through the end points of vertical error bars

• "E4" Draw a smoothed filled area through the end points of error bars

Note that for all options, the line and fill attributes of the histogram are used for the errors or errors contours. Use gStyle->SetErrorX(dx) to control the size of the error along x. The parameter dx is a percentage of bin width for errors along X. Set dx=0 to suppress the error along X. Use gStyle->SetEndErrorSize(np) to control the size of the lines at the end of the error bars (when option 1 is used). By default np=1 (np represents the number of pixels).

#### 3.8.2.5 The Color Option

For each cell (i,j) a box is drawn with a color proportional to the cell content. The color table used is defined in the current style (gStyle ). The color palette in TStyle can be modified with TStyle::SetPalette .

#### 3.8.2.6 The TEXT Option

For each cell (i,j) the cell content is printed. The text attributes are:

• Text font = current font set by TStyle

• Text size= 0.02 * pad-height * marker-size

• Text color= marker color

#### 3.8.2.7 The CONTour Options

The following contour options are supported:

• "CONT": Draw a contour plot (same as CONT0)

• "CONT0": Draw a contour plot using surface colors to distinguish contours

• "CONT1": Draw a contour plot using line styles to distinguish contours

• "CONT2": Draw a contour plot using the same line style for all contours

• "CONT3": Draw a contour plot using fill area colors

• "CONT4":Draw a contour plot using surface colors (SURF2 option at theta = 0); see also options “AITOFF”, “MERCATOR”, etc. below

• "CONT5": Use Delaunay triangles to compute the contours

The default number of contour levels is 20 equidistant levels. It can be changed with TH1::SetContour. When option “LIST” is specified together with option “CONT”, all points used for contour drawing, are saved in the TGraph object and are accessible in the following way:

   TObjArray *contours =
gROOT->GetListOfSpecials()->FindObject("contours");
Int_t ncontours = contours->GetSize(); TList *list =
(TList*)contours->At(i);

Where “i” is a contour number and list contains a list of TGraph objects. For one given contour, more than one disjoint poly-line may be generated. The TGraph numbers per contour are given by list->GetSize(). Here we show how to access the first graph in the list.

   TGraph *gr1 = (TGraph*)list->First();
• AITOFF”: Draw a contour via an AITOFF projection

• MERCATOR”: Draw a contour via a Mercator projection

• SINUSOIDAL”: Draw a contour via a Sinusoidal projection

• PARABOLIC”: Draw a contour via a Parabolic projection

The tutorial macro earth.C uses these four options and produces the following picture:

#### 3.8.2.8 The LEGO Options

In a lego plot, the cell contents are drawn as 3D boxes, with the height of the box proportional to the cell content.

• LEGO”: Draw a lego plot with hidden line removal

• LEGO1”: Draw a lego plot with hidden surface removal

• LEGO2”: Draw a lego plot using colors to show the cell contents

A lego plot can be represented in several coordinate systems; the default system is Cartesian coordinates. Other possible coordinate systems are CYL , POL , SPH , and PSR .

• CYL”: Cylindrical coordinates: x-coordinate is mapped on the angle; y-coordinate - on the cylinder length.

• POL”: Polar coordinates: x-coordinate is mapped on the angle; y-coordinate - on the radius.

• SPH”: Spherical coordinates: x-coordinate is mapped on the latitude; y-coordinate - on the longitude.

• PSR”: PseudoRapidity/Phi coordinates: x-coordinate is mapped on Phi.

With TStyle::SetPalette the color palette can be changed. We suggest you use palette 1 with the call:

   gStyle->SetPalette(1);

#### 3.8.2.9 The SURFace Options

In a surface plot, cell contents are represented as a mesh. The height of the mesh is proportional to the cell content. A surface plot can be represented in several coordinate systems. The default is Cartesian coordinates, and the other possible systems are CYL, POL, SPH, and PSR . The following picture uses SURF1 . With TStyle::SetPalette the color palette can be changed. We suggest you use palette 1 with the call:

   gStyle->SetPalette(1);
• SURF”: Draw a surface plot with hidden line removal

• SURF1”: Draw a surface plot with hidden surface removal

• SURF2”: Draw a surface plot using colors to show the cell contents

• SURF3”: Same as SURF with a contour view on the top

• SURF4”: Draw a surface plot using Gouraud shading

• SURF5”: Same as SURF3 but only the colored contour is drawn. Used with options CYL , SPH or PSR it allows to draw colored contours on a sphere, a cylinder or in a pseudo rapidly space. In Cartesian or polar coordinates, option SURF3 is used.

#### 3.8.2.10 The BAR Options

When the option “bar” or “hbar” is specified, a bar chart is drawn.

The options for vertical bar chart are “bar”, “bar0”, “bar1”, “bar2”, “bar3”, “bar4”.

• The bar is filled with the histogram fill color.
• The left side of the bar is drawn with a light fill color.
• The right side of the bar is drawn with a dark fill color.
• The percentage of the bar drawn with either the light or dark color is:
• 0 per cent for option "bar" or "bar0"
• 10 per cent for option "bar1"
• 20 per cent for option "bar2"
• 30 per cent for option "bar3"
• 40 per cent for option "bar4"

Use TH1::SetBarWidth() to control the bar width (default is the bin width). Use TH1::SetBarOffset to control the bar offset (default is 0). See the example $ROOTSYS/tutorials/hist/hbars.C The options for the horizontal bar chart are “hbar”, “hbar0”, “hbar1”, “hbar2”, “hbar3”, and “hbar4”. • A horizontal bar is drawn for each bin. • The bar is filled with the histogram fill color. • The bottom side of the bar is drawn with a light fill color. • The top side of the bar is drawn with a dark fill color. • The percentage of the bar drawn with either the light or dark color is: • 0 per cent for option “hbar” or “hbar0 • 10 per cent for option “hbar1 • 20 per cent for option “hbar2 • 30 per cent for option “hbar3 • 40 per cent for option “hbar4 Use TH1::SetBarWidth to control the bar width (default is the bin width). Use TH1::SetBarOffset to control the bar offset (default is 0). See the example $ROOTSYS/tutorials/hist/hbars.C

#### 3.8.2.11 The Z Option: Display the Color Palette on the Pad

The “Z” option can be specified with the options: COL, CONT, SURF, and LEGO to display the color palette with an axis indicating the value of the corresponding color on the right side of the picture. If there is not enough space on the right side, you can increase the size of the right margin by calling TPad::SetRightMargin(). The attributes used to display the palette axis values are taken from the Z axis of the object. For example, you can set the labels size on the palette axis with:

   hist->GetZaxis()->SetLabelSize();

#### 3.8.2.12 Setting the Color Palette

You can set the color palette with TStyle::SetPalette , e.g.

   gStyle->SetPalette(ncolors,colors);

For example, the option COL draws a 2-D histogram with cells represented by a box filled with a color index, which is a function of the cell content. If the cell content is N, the color index used will be the color number in colors[N] . If the maximum cell content is greater than ncolors , all cell contents are scaled to ncolors. If ncolors<=0, a default palette of 50 colors is defined. This palette is recommended for pads, labels. It defines:

• Index 0 to 9: shades of gray
• Index 10 to 19:shades of brown
• Index 20 to 29:shades of blue
• Index 30 to 39: shades of red
• Index 40 to 49:basic colors

The color numbers specified in this palette can be viewed by selecting the menu entry Colors in the View menu of the canvas menu bar. The color’s red, green, and blue values can be changed via TColor::SetRGB.

If ncolors == 1 && colors == 0, then a Pretty Palette with a spectrum violet to red is created with 50 colors. That’s the default rain bow palette.

Other predefined palettes with 255 colors are available when colors == 0. The following value of ncolors (with colors = 0) give access to:

• ncolors = 51 : Deep Sea palette.
• ncolors = 52 : Grey Scale palette.
• ncolors = 53 : Dark Body Radiator palette.
• ncolors = 54 : Two-color hue palette palette. (dark blue through neutral gray to bright yellow)
• ncolors = 55 : Rain Bow palette.
• ncolors = 56 : Inverted Dark Body Radiator palette.

The color numbers specified in the palette can be viewed by selecting the item “colors” in the “VIEW” menu of the canvas toolbar. The color parameters can be changed via TColor::SetRGB.

Note that when drawing a 2D histogram h2 with the option “COL” or “COLZ” or with any “CONT” options using the color map, the number of colors used is defined by the number of contours n specified with: h2->SetContour(n)

#### 3.8.2.13 TPaletteAxis

A TPaletteAxisobject is used to display the color palette when drawing 2D histograms. The object is automatically created when drawing a 2D histogram when the option “z” is specified. It is added to the histogram list of functions. It can be retrieved and its attributes can be changed with:

   TPaletteAxis *palette=(TPaletteAxis*)h->FindObject("palette");

The palette can be interactively moved and resized. The context menu can be used to set the axis attributes. It is possible to select a range on the axis, to set the min/max in z.

#### 3.8.2.14 The SPEC Option

The “SPEC” option offers a large set of options/attributes to visualize 2D histograms thanks to “operators” following the “SPEC” keyword. For example, to draw the 2-D histogram h2 using all default attributes except the viewing angles, one can do:

   h2->Draw("SPEC a(30,30,0)");

The operators’ names are case insensitive (i.e. one can use “a” or “A”) and their parameters are separated by coma “,”. Operators can be put in any order in the option and must be separated by a space " ". No space characters should be put in an operator. All the available operators are described below.

The way how a 2D histogram will be painted is controlled by two parameters: the “Display modes groups” and the “Display Modes”. “Display modes groups” can take the following values:

• 0 = Simple - simple display modes using one color only
• 1 = Light - the shading is carried out according to the position of the fictive light source
• 2 = Height - the shading is carried out according to the channel contents
• 3 = LightHeight - combination of two previous shading algorithms (one can control the weight between both algorithms).

“Display modes” can take the following values:

• 1 = Points
• 2 = Grid
• 3 = Contours
• 4 = Bars
• 5 = LinesX
• 6 = LinesY
• 7 = BarsX
• 8 = BarsY
• 9 = Needles
• 10 = Surface
• 11 = Triangles

These parameters can be set by using the “dm” operator in the option.

   h2->Draw("SPEC dm(1,2)");

The above example draws the histogram using the “Light Display mode group” and the “Grid Display mode”. The following tables summarize all the possible combinations of both groups:

 Points Grid Contours Bars LinesX LinesY Simple x x x x x x Light x x x x Height x x x x x x LightHeight x x x x
 BarsX BarsY Needles Surface Triangles Simple x x x x Light x x Height x x x x LightHeight x x

The “Pen Attributes” can be changed using pa(color,style,width). Next example sets line color to 2, line type to 1 and line width to 2. Note that if pa() is not specified, the histogram line attributes are used:

   h2->Draw("SPEC dm(1,2) pa(2,1,2)");

The number of “Nodes” can be changed with n(nodesx,nodesy). Example:

   h2->Draw("SPEC n(40,40)");

Sometimes the displayed region is rather large. When displaying all channels the pictures become very dense and complicated. It is very difficult to understand the overall shape of data. “n(nx,ny)” allows to change the density of displayed channels. Only the channels coinciding with given nodes are displayed.

The visualization “Angles” can be changed with “a(alpha,beta,view)”: “alpha” is the angle between the bottom horizontal screen line and the displayed space on the right side of the picture and “beta” on the left side, respectively. One can rotate the 3-d space around the vertical axis using the “view” parameter. Allowed values are 0, 90, 180 and 270 degrees.

   h2->Draw("SPEC n(40,40) dm(0,1) a(30,30,0)");

The operator “zs(scale)” changes the scale of the Z-axis. The possible values are:

• 0 = Linear (default),
• 1 = Log,
• 2 = Sqrt.

If gPad->SetLogz() has been set, the log scale on Z-axis is set automatically, i.e. there is no need for using the zs() operator. Note that the X and Y axis are always linear.

The operator “ci(r,g,b)” defines the colors increments (r, g and b are floats). For sophisticated shading (Light, Height and LightHeight Display Modes Groups) the color palette starts from the basic pen color (see pa() function). There is a predefined number of color levels (256). Color in every level is calculated by adding the increments of the r , g , b components to the previous level. Using this function one can change the color increments between two neighboring color levels. The function does not apply on the Simple Display Modes Group. The default values are: (1,1,1).

The operator “ca(color_algorithm)” allows to choose the Color Algorithm. To define the colors one can use one of the following color algorithms (RGB, CMY, CIE, YIQ, HVS models). When the level of a component reaches the limit value one can choose either smooth transition (by decreasing the limit value) or a sharp modulo transition (continuing with 0 value). This allows various visual effects. One can choose from the following set of the algorithms:

• 0 = RGB Smooth,
• 1 = RGB Modulo,
• 2 = CMY Smooth,
• 3 = CMY Modulo,
• 4 = CIE Smooth
• 5 = CIE Modulo,
• 6 = YIQ Smooth,
• 7 = YIQ Modulo,
• 8 = HVS Smooth,
• 9 = HVS Modulo

This function does not apply on Simple display modes group. Default value is 0. Example choosing CMY Modulo to paint the 2D histogram:

   h2->Draw("SPEC c1(3) dm(0,1) a(30,30,0)");

The operator “lp(x,y,z)” sets the light position. In Light and LightHeight display modes groups the color palette is calculated according to the fictive light source position in 3-d space. Using this function one can change the source’s position and thus achieve various graphical effects. This function does not apply for Simple and Height display modes groups. Default is: lp(1000,1000,100) .

The operator “s(shading,shadow)” allows to set the shading. The surface picture is composed of triangles. The edges of the neighboring triangles can be smoothed (shaded). The shadow can be painted as well. The function does not apply on Simple display modes group. The possible values for shading are:

The possible values for shadow are:

• 0 = Shadows are not painted,
• 1 = Shadows are painted.

Default values: s(1,0) .

The operator “b(bezier)” sets the Bezier smoothing. For Simple display modes group and for Grid, LinesX and LinesY display modes one can smooth data using Bezier smoothing algorithm. The function does not apply on other display modes groups and display modes. Possible values are: 0 = No bezier smoothing, 1 = Bezier smoothing. Default value is: b(0).

The operator “cw(width)” sets the contour width. This function applies only on for the Contours display mode. One can change the width between horizontal slices and thus their density. Default value: cw(50) .

The operator “lhw(weight)” sets the light height weight. For LightHeight display modes group one can change the weight between both shading algorithms. The function does not apply on other display modes groups. Default value is lhw(0.5) .

The operator “cm(enable,color,width,height,style)” allows to draw a marker on each node. In addition to the surface drawn using any above given algorithm one can display channel marks. One can control the color as well as the width, height (in pixels) and the style of the marks. The parameter enable can be set to 0 = Channel marks are not drawn or 1 = Channel marks drawn. The possible styles are:

• 1 = Dot,
• 2 = Cross,
• 3 = Star,
• 4 = Rectangle,
• 5 = X,
• 6 = Diamond,
• 7 = Triangle.

The operator “cg(enable,color)” channel grid. In addition to the surface drawn using any above given algorithm one can display grid using the color parameter. The parameter enable can be set to:

• 0 = Grid not drawn,
• 1 = Grid drawn.

### 3.8.4 Superimposing Histograms with Different Scales

The following script creates two histograms; the second histogram is the bins integral of the first one. It shows a procedure to draw the two histograms in the same pad and it draws the scale of the second histogram using a new vertical axis on the right side.

void twoscales() {
TCanvas *c1 = new TCanvas("c1","different scales hists",600,400);
//create, fill and draw h1
gStyle->SetOptStat(kFALSE);
TH1F *h1 = new TH1F("h1","my histogram",100,-3,3);
for (Int_t i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
h1->Draw();
c1->Update();
//create hint1 filled with the bins integral of h1
TH1F *hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
Float_t sum = 0;
for (Int_t i=1;i<=100;i++) {
sum += h1->GetBinContent(i);
hint1->SetBinContent(i,sum);
}
//scale hint1 to the pad coordinates
Float_t rightmax = 1.1*hint1->GetMaximum();
hint1->SetLineColor(kRed);
hint1->Scale(scale);
hint1->Draw("same");
//draw an axis on the right side
0,rightmax,510,"+L");
axis->SetLineColor(kRed);
axis->SetLabelColor(kRed);
axis->Draw();
}

### 3.8.5 Statistics Display

By default, a histogram drawing includes the statistics box. Use TH1::SetStats(kFALSE) to eliminate the statistics box. If the statistics box is drawn, gStyle->SetOptStat(mode) allow you to select the type of displayed information . The parameter mode has up to nine digits that can be set OFF (0) or ON as follows:

mode = ksiourmen (default =000001111)

• n = 1 the name of histogram is printed
• e = 1 the number of entries
• m = 1 the mean value
• m = 2 the mean and mean error values
• r = 1 the root mean square (RMS)
• r = 2 the RMS and RMS error
• u = 1 the number of underflows
• o = 1 the number of overflows
• i = 1 the integral of bins
• s = 1 the skewness
• s = 2 the skewness and the skewness error
• k = 1 the kurtosis
• k = 2 the kurtosis and the kurtosis error

Never call SetOptStat(0001111) , but SetOptStat(1111) , because 0001111 will be taken as an octal number.

The method TStyle::SetOptStat(Option_t*option) can also be called with a character string as a parameter. The parameter option can contain:

• n for printing the name of histogram
• e the number of entries
• m the mean value
• M the mean and mean error values
• r the root mean square (RMS)
• R the RMS and RMS error
• u the number of underflows
• o the number of overflows
• i the integral of bins
• s the skewness
• S the skewness and the skewness error
• k the kurtosis
• K the kurtosis and the kurtosis error
   gStyle->SetOptStat("ne");   // prints the histogram name and number
// of entries
gStyle->SetOptStat("n");    // prints the histogram name
gStyle->SetOptStat("nemr"); // the default value

With the option "same", the statistic box is not redrawn. With the option "sames", it is re-drawn. If it hides the previous statistics box, you can change its position with the next lines (where h is the histogram pointer):

root[] TPaveStats *s =
(TPaveStats*)h->GetListOfFunctions()->FindObject("stats");
root[] s->SetX1NDC (newx1); // new x start position
root[] s->SetX2NDC (newx2); // new x end position

### 3.8.6 Setting Line, Fill, Marker, and Text Attributes

The histogram classes inherit from the attribute classes: TAttLine, TAttFill, TAttMarker and TAttText. See the description of these classes for the list of options.

### 3.8.7 Setting Tick Marks on the Axis

The TPad::SetTicks() method specifies the type of tick marks on the axis. Let tx=gPad->GetTickx() and ty=gPad->GetTicky().

• tx = 1; tick marks on top side are drawn (inside)
• tx = 2; tick marks and labels on top side are drawn
• ty = 1; tick marks on right side are drawn (inside)
• ty = 2; tick marks and labels on right side are drawn
• tx=ty=0 by default only the left Y axis and X bottom axis are drawn

Use TPad::SetTicks(tx,ty) to set these options. See also the methods of TAxis that set specific axis attributes. If multiple color-filled histograms are drawn on the same pad, the fill area may hide the axis tick marks. One can force the axis redrawing over all the histograms by calling:

   gPad->RedrawAxis();

### 3.8.8 Giving Titles to the X, Y and Z Axis

Because the axis title is an attribute of the axis, you have to get the axis first and then call TAxis::SetTitle.

   h->GetXaxis()->SetTitle("X axis title");
h->GetYaxis()->SetTitle("Y axis title");
h->GetZaxis()->SetTitle("Z axis title");

The histogram title and the axis titles can be any TLatex string. The titles are part of the persistent histogram. For example if you wanted to write E with a subscript (T) you could use this:

   h->GetXaxis()->SetTitle("E_{T}");

For a complete explanation of the Latex mathematical expressions, see “Graphics and the Graphical User Interface”. It is also possible to specify the histogram title and the axis titles at creation time. These titles can be given in the “title” parameter. They must be separated by “;”:

   TH1F* h=new TH1F("h","Histogram title;X Axis;Y Axis;Z Axis",
100,0,1);

Any title can be omitted:

   TH1F* h=new TH1F("h","Histogram title;;Y Axis",100,0,1);
TH1F* h=new TH1F("h",";;Y Axis",100,0,1);

The method SetTitle has the same syntax:

   h->SetTitle("Histogram title;An other X title Axis");

## 3.9 Making a Copy of an Histogram

Like for any other ROOT object derived from TObject , the Clone method can be used. This makes an identical copy of the original histogram including all associated errors and functions:

   TH1F *hnew = (TH1F*)h->Clone(); // renaming is recommended,
hnew->SetName("hnew");          // because otherwise you will have
// two histograms with the same
// name

## 3.10 Normalizing Histograms

You can scale a histogram ( TH1 *h ) such that the bins integral is equal to the normalization parameter norm:

   Double_t scale = norm/h->Integral();
h->Scale(scale);

## 3.11 Saving/Reading Histograms to/from a File

The following statements create a ROOT file and store a histogram on the file. Because TH1 derives from TNamed , the key identifier on the file is the histogram name:

   TFile f("histos.root","new");
TH1F h1("hgaus","histo from a gaussian",100,-3,3);
h1.FillRandom("gaus",10000);
h1->Write();

To read this histogram in another ROOT session, do:

   TFile f("histos.root");
TH1F *h = (TH1F*)f.Get("hgaus");

One can save all histograms in memory to the file by:

   file->Write();

For a more detailed explanation, see “Input/Output”.

## 3.12 Miscellaneous Operations

• TH1::KolmogorovTest( TH1* h2,Option_t *option) is statistical test of compatibility in shape between two histograms. The parameter option is a character string that specifies:

• U” include Underflows in test (also for 2-dim)

• O” include Overflows (also valid for 2-dim)

• N” include comparison of normalizations

• D” put out a line of “Debug” printout

• M” return the maximum Kolmogorov distance instead of prob

• X” run the pseudo experiments post-processor with the following procedure: it makes pseudo experiments based on random values from the parent distribution and compare the KS distance of the pseudo experiment to the parent distribution. Bin the KS distances in a histogram, and then take the integral of all the KS values above the value obtained from the original data to Monte Carlo distribution. The number of pseudo-experiments NEXPT is currently fixed at 1000. The function returns the integral. Note that this option “X” is much slower.

• TH1::Smooth - smoothes the bin contents of a 1D histogram.

• TH1::Integral(Option_t *opt)-returns the integral of bin contents in a given bin range. If the option “width” is specified, the integral is the sum of the bin contents multiplied by the bin width in x .

• TH1::GetMean(int axis) - returns the mean value along axis.

• TH1::GetStdDev(int axis) - returns the sigma distribution along axis.

• TH1::GetRMS(int axis) - returns the Root Mean Square along axis.

• TH1::GetEntries() - returns the number of entries.

• TH1::GetAsymmetry(TH1 *h2,Double_t c2,Double_tdc2)
• returns an histogram containing the asymmetry of this histogram with h2, where the asymmetry is defined as:
   Asymmetry = (h1 - h2)/(h1 + h2); //where h1 = this
• It works for 1D , 2D , etc. histograms. The parameter c2 is an optional argument that gives a relative weight between the two histograms, and dc 2 is the error on this weight. This is useful, for example, when forming an asymmetry between two histograms from two different data sets that need to be normalized to each other in some way. The function calculates the errors assuming Poisson statistics on h1 and h2 (that is, dh=sqrt(h)). In the next example we assume that h1 and h2 are already filled:
   h3 = h1->GetAsymmetry(h2);
• Then h3 is created and filled with the asymmetry between h1 and h2 ; h1 and h2 are left intact.

• Note that the user’s responsibility is to manage the created histograms.

• TH1::Reset() - resets the bin contents and errors of a histogram

## 3.13 Important note on returned statistics (GetMean, GetStdDev, etc.)

By default, histogram statistics are computed at fill time using the unbinned data used to update the bin content. This means the values returned by GetMean, GetStdDev, etc., are those of the dataset used to fill the histogram, not those of the binned content of the histogram itself, unless one of the axes has been zoomed. (See the documentation on TH1::GetStats().) This is useful if you want to keep track of the mean and standard deviation of the dataset you are visualizing with the histogram, but it can lead to some unintuitive results.

For example, suppose you have a histogram with one bin between 0 and 100, then you fill it with a Gaussian dataset with mean 20 and standard deviation 2:

TH1F * h = new TH1F("h", "h", 1, 0, 100);
for(int i=0; i<10000; i++) h->Fill(gRandom->Gaus(20, 2));

Right now, h->GetMean() will return 20 and h->GetStdDev() will return 2; ROOT calculated these values as we filled h. Next, zoom in on the Gaussian:

h->GetXaxis()->SetRangeUser(10, 30);

Now, h->GetMean() will return 50 and h->GetStdDev() will return 0. What happened? Well, GetMean and GetStdDev (and many other TH1 functions) return the statistics for bins in range; this is because the histogram only stores the contents of its bins, not the coordinates of the values used to fill it. So even though h has only one bin and it’s still included in the range, ROOT returns the binned statistics because SetRangeUser set the bit TAxis::kAxisRange to 1. This remains true even if you zoom out:

h->GetXaxis()->SetRangeUser(0, 100);

still results in GetMean and GetStdDev returning 50 and 0, respectively, because, even though this is the original range of the histogram, the X axis has still been assigned a range. To mark the X axis as having no range, you can call

h->GetXaxis()->SetRange();

without arguments or with arguments (0, 0). This sets the bit TAxis::kAxisRange to 0, and ROOT again uses the statistics calculated at fill time: GetMean and GetStdDev now return 20 and 2, respectively.

If you want ROOT to consistently return the statistics of the binned dataset stored in the histogram and not those of the dataset used to fill it, you can call TH1::ResetStats. This will delete the statistics originally calculated at fill time and replace them with those calculated from the bins; note that you cannot later retrieve the original statistics–they are lost. Continuing the example above,

h->ResetStats();
h->GetXaxis()->SetRange();

results in GetMean and GetStdDev returning 50 and 0, respectively. If you fill the histogram again, the statistics will be a mix of binned and unbinned:

h->ResetStats();
h->GetXaxis()->SetRange();
for(int i=0; i<10000; i++) h->Fill(85);

results in GetMean and GetStdDev returning 67.5 and 17.5, respectively; you must call TH1::ResetStats again to get consistent binned statistics.

## 3.14 Alphanumeric Bin Labels

By default, a histogram axis is drawn with its numeric bin labels. One can specify alphanumeric labels instead.

### 3.14.1 Option 1: SetBinLabel

To set an alphanumeric bin label call:

   TAxis::SetBinLabel(bin,label);

This can always be done before or after filling. Bin labels will be automatically drawn with the histogram.

See example in $ROOTSYS/tutorials/hist/hlabels1.C , hlabels2.C ### 3.14.2 Option 2: Fill You can also call a Fill() function with one of the arguments being a string:  hist1->Fill(somename,weigth); hist2->Fill(x,somename,weight); hist2->Fill(somename,y,weight); hist2->Fill(somenamex,somenamey,weight); ### 3.14.3 Option 3: TTree::Draw You can use a char* variable type to histogram strings with TTree::Draw().  // here "Nation" and "Division" are two char* branches of a Tree tree.Draw("Nation::Division", "", "text"); There is an example in $ROOTSYS/tutorials/tree/cernstaff.C.

If a variable is defined as char* it is drawn as a string by default. You change that and draw the value of char[0] as an integer by adding an arithmetic operation to the expression as shown below.

   // draw the integer value of MyChar[0] where "MyChar" is char[5]
tree.Draw("MyChar + 0");

### 3.14.4 Sort Options

When using the options 2 or 3 above, the labels are automatically added to the list (THashList) of labels for a given axis. By default, an axis is drawn with the order of bins corresponding to the filling sequence. It is possible to reorder the axis alphabetically or by increasing or decreasing values. The reordering can be triggered via the TAxis context menu by selecting the menu item “LabelsOption” or by calling directly.

   TH1::LabelsOption(option,axis);

Here axis may be X, Y, or Z. The parameter option may be:

• a” sort by alphabetic order
• >” sort by decreasing values
• <” sort by increasing values
• h” draw labels horizontal
• v” draw labels vertical
• u” draw labels up (end of label right adjusted)
• d” draw labels down (start of label left adjusted)

When using the option second above, new labels are added by doubling the current number of bins in case one label does not exist yet. When the filling is terminated, it is possible to trim the number of bins to match the number of active labels by calling:

   TH1::LabelsDeflate(axis);

Here axis may be X, Y, or Z. This operation is automatic when using TTree::Draw . Once bin labels have been created, they become persistent if the histogram is written to a file or when generating the C++ code via SavePrimitive .

## 3.15 Histogram Stacks

A THStack is a collection of TH1 (or derived) objects. Use THStack::Add( TH1 *h) to add a histogram to the stack. The THStack does not own the objects in the list.

By default, THStack::Draw draws the histograms stacked as shown in the left pad in the picture above. If the option "nostack" is used, the histograms are superimposed as if they were drawn one at a time using the "same" draw option . The right pad in this picture illustrates the THStack drawn with the "nostack" option.

   hs->Draw("nostack");

## 3.17 Profile Histograms

Profile histograms are in many cases an elegant replacement of two-dimensional histograms. The relationship of two quantities X and Y can be visualized by a two-dimensional histogram or a scatter-plot; its representation is not particularly satisfactory, except for sparse data. If Y is an unknown [but single-valued] function of X, it can be displayed by a profile histogram with much better precision than by a scatter-plot. Profile histograms display the mean value of Y and its RMS for each bin in X. The following shows the contents [capital letters] and the values shown in the graphics [small letters] of the elements for bin j. When you fill a profile histogram with TProfile.Fill(x,y) :

• H[j] will contain for each bin j the sum of the y values for this bin

• L[j] contains the number of entries in the bin j

• e[j] or s[j] will be the resulting error depending on the selected option. See “Build Options”.

E[j] = sum Y**2
L[j] = number of entries in bin J
H[j] = sum Y
h[j] = H[j] / L[j]
s[j] = sqrt[E[j] / L[j] - h[j]**2]
e[j] = s[j] / sqrt[L[j]]

In the special case where s[j] is zero, when there is only one entry per bin, e[j] is computed from the average of the s[j] for all bins. This approximation is used to keep the bin during a fit operation. The TProfile constructor takes up to eight arguments. The first five parameters are similar to TH1D constructor.

TProfile(const char *name,const char *title,Int_t nbinsx,
Double_t xlow, Double_t xup, Double_t ylow, Double_t yup,
Option_t *option)

All values of y are accepted at filling time. To fill a profile histogram, you must use TProfile::Fill function. Note that when filling the profile histogram the method TProfile::Fill checks if the variable y is between fYmin and fYmax. If a minimum or maximum value is set for the Y scale before filling, then all values below ylow or above yup will be discarded. Setting the minimum or maximum value for the Y scale before filling has the same effect as calling the special TProfile constructor above where ylow and yup are specified.

### 3.17.1 Build Options

The last parameter is the build option. If a bin has N data points all with the same value Y, which is the case when dealing with integers, the spread in Y for that bin is zero, and the uncertainty assigned is also zero, and the bin is ignored in making subsequent fits. If SQRT(Y) was the correct error in the case above, then SQRT(Y)/SQRT(N) would be the correct error here. In fact, any bin with non-zero number of entries N but with zero spread (spread = s[j]) should have an uncertainty SQRT(Y)/SQRT(N). Now, is SQRT(Y)/SQRT(N) really the correct uncertainty ? That it is only in the case where the Y variable is some sort of counting statistics, following a Poisson distribution. This is the default case. However, Y can be any variable from an original NTUPLE, and does not necessarily follow a Poisson distribution. The computation of errors is based on Y = values of data points; N = number of data points.

• ' ' - the default is blank, the errors are:

• spread/SQRT(N) for a non-zero spread

• SQRT(Y)/SQRT(N) for a spread of zero and some data points

• 0 for no data points

• s ’ - errors are:

• spread for a non-zero spread

• SQRT(Y) for a Spread of zero and some data points

• 0 for no data points

• i ’ - errors are:

• spread/SQRT(N) for a non-zero spread

• 1/SQRT(12*N) for a Spread of zero and some data points

• 0 for no data points

• G ’ - errors are:

• spread/SQRT(N) for a non-zero spread

• sigma/SQRT(N) for a spread of zero and some data points

• 0 for no data points

The option ’ i ’ is used for integer Y values with the uncertainty of $$\pm 0.5$$, assuming the probability that Y takes any value between Y-0.5 and Y+0.5 is uniform (the same argument for Y uniformly distributed between Y and Y+1). An example is an ADC measurement. The ‘G’ option is useful, if all Y variables are distributed according to some known Gaussian of standard deviation Sigma. For example when all Y’s are experimental quantities measured with the same instrument with precision Sigma. The next figure shows the graphic output of this simple example of a profile histogram.

{
// Create a canvas giving the coordinates and the size
TCanvas *c1 = new TCanvas("c1", "Profile example",200,10,700,500);

// Create a profile with the name, title, the number of bins,
// the low and high limit of the x-axis and the low and high
// limit of the y-axis.
// No option is given so the default is used.
hprof = new TProfile("hprof",
"Profile of pz versus px",100,-4,4,0,20);

// Fill the profile 25000 times with random numbers
Float_t px, py, pz;
for ( Int_t i=0; i<25000; i++) {
// Use the random number generator to get two numbers following
// a gaussian distribution with mean=0 and sigma=1
gRandom->Rannor(px,py);
pz = px*px + py*py;
hprof->Fill(px,pz,1);
}
hprof->Draw();
}

### 3.17.2 Drawing a Profile without Error Bars

To draw a profile histogram and not show the error bars use the “HIST” option in the TProfile::Draw method. This will draw the outline of the TProfile.

### 3.17.3 Create a Profile from a 2D Histogram

You can make a profile from a histogram using the methods TH2::ProfileX and TH2::ProfileY.

### 3.17.4 Create a Histogram from a Profile

To create a regular histogram from a profile histogram, use the method TProfile::ProjectionX .This example instantiates a TH1D object by copying the TH1D piece of TProfile.

   TH1D *sum = myProfile.ProjectionX();

You can do the same with a 2D profile using the method TProfile2D::ProjectionXY .

### 3.17.5 Generating a Profile from a TTree

The 'prof' and 'profs' options in the TTree::Draw method generate a profile histogram ( TProfile ), given a two dimensional expression in the tree, or a TProfile2D given a three dimensional expression. See “Trees”. Note that you can specify 'prof' or 'profs' : 'prof' generates a TProfile with error on the mean, 'profs' generates a TProfile with error on the spread.

### 3.17.6 2D Profiles

The class for a 2D Profile is called TProfile2D . It is in many cases an elegant replacement of a three-dimensional histogram. The relationship of three measured quantities X, Y and Z can be visualized by a three-dimensional histogram or scatter-plot; its representation is not particularly satisfactory, except for sparse data. If Z is an unknown (but single-valued) function of (X,Y), it can be displayed with a TProfile2D with better precision than by a scatter-plot. A TProfile2D displays the mean value of Z and its RMS for each cell in X, Y. The following shows the cumulated contents (capital letters) and the values displayed (small letters) of the elements for cell i,j.

When you fill a profile histogram with TProfile2D.Fill(x,y,z):

• E[i,j] contains for each bin i,j the sum of the z values for this bin

• L[i,j] contains the number of entries in the bin j

• e[j] or s[j] will be the resulting error depending on the selected option. See “Build Options”.

E[i,j] = sum z
L[i,j] = sum l
h[i,j] = H[i,j ] / L[i,j]
s[i,j] = sqrt[E[i,j] / L[i,j]- h[i,j]**2]
e[i,j] = s[i,j] / sqrt[L[i,j]]

In the special case where s[i,j] is zero, when there is only one entry per cell, e[i,j] is computed from the average of the s[i,j] for all cells. This approximation is used to keep the cell during a fit operation.

{
// Creating a Canvas and a TProfile2D
TCanvas *c1 = new TCanvas("c1",
"Profile histogram example",
200, 10,700,500);
hprof2d = new TProfile2D("hprof2d",
"Profile of pz versus px and py",
40,-4,4,40,-4,4,0,20);

// Filling the TProfile2D with 25000 points
Float_t px, py, pz;
for (Int_t i=0; i<25000; i++) {
gRandom->Rannor(px,py);
pz = px*px + py*py;
hprof2d->Fill(px,py,pz,1);
}
hprof2d->Draw();
}

## 3.18 Iso Surfaces

Paint one Gouraud shaded 3d iso surface though a 3d histogram at the value computed as follow: SumOfWeights/(NbinsX*NbinsY*NbinsZ).

void hist3d() {
TH3D *h3 = new TH3D("h3", "h3", 20, -2, 2, 20, -2, 2, 20, 0, 4);
Double_t x,y,z;
for (Int_t i=0; i<10000; i++) {
gRandom->
Rannor(x,y);
z=x*x+y*y;
h3->Fill(x,y,z);
}
h3->Draw("iso");
}

## 3.19 3D Implicit Functions

   TF3 *fun3 = new TF3("fun3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
fun3->Draw();

## 3.20 TPie

The TPie class allows to create a Pie Chart representation of a one dimensional data set. The data can come from an array of Double_t (or Float_t ) or from a 1D-histogram. The possible options to draw a TPie are:

• R” Paint the labels along the central “R”adius of slices.

• T” Paint the labels in a direction “T”angent to circle that describes the TPie.

• 3D” Draw the pie-chart with a pseudo 3D effect.

• NOL” No OutLine: do not draw the slices’ outlines; any property over the slices’ line is ignored.

The method SetLabelFormat() is used to customize the label format. The format string must contain one of these modifiers:

• %txt : to print the text label associated with the slice
• %val : to print the numeric value of the slice
• %frac : to print the relative fraction of this slice
• %perc : to print the % of this slice
   mypie->SetLabelFormat("%txt (%frac)");

See the macro $ROOTSYS/tutorials/graphics/piechart.C . ## 3.21 The User Interface for Histograms The classes T H1 Editor and T H2 Editor provides the user interface for setting histogram’s attributes and rebinning interactively. ### 3.21.1 TH1Editor #### 3.21.1.1 The Style Tab ##### 3.21.1.1.1 Title sets the title of the histogram. ##### 3.21.1.1.2 Plot draw a 2D or 3D plot; according to the dimension, different drawing possibilities can be set. ##### 3.21.1.1.3 Error add different error bars to the histogram (no errors, simple, etc.). ##### 3.21.1.1.4 Add further things which can be added to the histogram (None, simple/smooth line, fill area, etc.) #### 3.21.1.2 2-D Plot ##### 3.21.1.2.1 Simple Drawing draw a simple histogram without errors (= “HIST” draw option). In combination with some other draw options an outer line is drawn on top of the histogram ##### 3.21.1.2.2 Show markers draw a marker on to of each bin (=“P” draw option). ##### 3.21.1.2.3 Draw bar chart draw a bar chart (=“B” draw option). ##### 3.21.1.2.4 Bar option draw a bar chart (=“BAR” draw option); if selected, it will show an additional interface elements for bars: width, offset, percentage and the possibility to draw horizontal bars. #### 3.21.1.3 3-D Plot ##### 3.21.1.3.1 Add set histogram type Lego-Plot or Surface draw (Lego, Lego1.2, Surf, Surf1…5). ##### 3.21.1.3.2 Coords set the coordinate system (Cartesian, Spheric, etc.). ##### 3.21.1.3.3 Error same as for 2D plot. ##### 3.21.1.3.4 Bar set the bar attributes: width and offset. ##### 3.21.1.3.5 Horizontal Bar draw a horizontal bar chart. #### 3.21.1.4 The Binning tab The binning tab has two different layouts. One is for a histogram, which is not drawn from an ntuple. The other one is available for a histogram, which is drawn from an ntuple. In this case, the rebin algorithm can create a rebinned histogram from the original data i.e. the ntuple. To see the differences do:  TFile f("hsimple.root"); hpx->Draw("BAR1"); // non ntuple histogram ntuple->Draw("px");// ntuple histogram #### 3.21.1.5 Non ntuple histogram Rebin with a slider and the number of bins (shown in the field below the slider). The number of bins can be changed to any number, which divides the number of bins of the original histogram. A click on the Apply button will delete the origin histogram and will replace it by the rebinned one on the screen. A click on the Ignore button will restore the origin histogram. #### 3.21.1.6 Histogram drawn from an ntuple ##### 3.21.1.6.1 Rebin with the slider, the number of bins can be enlarged by a factor of 2, 3, 4, 5 (moving to the right) or reduced by a factor of $$\frac{1}{2}$$, $$\frac{1}{3}$$, $$\frac{1}{4}$$, $$\frac{1}{5}$$. ##### 3.21.1.6.2 BinOffset with a BinOffset slider the origin of the histogram can be changed within one binwidth. Using this slider the effect of binning the data into bins can be made visible (statistical fluctuations). ##### 3.21.1.6.3 Axis Range with a double slider it is possible to zoom into the specified axis range. It is also possible to set the upper and lower limit in fields below the slider. ##### 3.21.1.6.4 Delayed drawing all the Binning sliders can set to delay draw mode. Then the changes on the histogram are only updated, when the Slider is released. This should be activated if the redrawing of the histogram is time consuming. ### 3.21.2 TH2Editor #### 3.21.2.1 Style Tab: ##### 3.21.2.1.1 Title set the title of the histogram ##### 3.21.2.1.2 Histogram change the draw options of the histogram. ##### 3.21.2.1.3 Plot draw a 2D or 3D plot of the histogram; according to the dimension, the drawing possibilities are different. #### 3.21.2.2 2-D Plot ##### 3.21.2.2.1 Contour draw a contour plot (None, Cont0…5) ##### 3.21.2.2.2 Cont # set the number of Contours; ##### 3.21.2.2.3 Arrow set the arrow mode and shows the gradient between adjacent cells; ##### 3.21.2.2.4 Col a box is drawn for each cell with a color scale varying with contents; ##### 3.21.2.2.5 Text draw bin contents as text; ##### 3.21.2.2.6 Box a box is drawn for each cell with surface proportional to contents; ##### 3.21.2.2.7 Scat draw a scatter-plot (default); ##### 3.21.2.2.8 Palette the color palette is drawn. #### 3.21.2.3 3-D Plot ##### 3.21.2.3.1 Type set histogram type to Lego or surface plot; draw (Lego, Lego1.2, Surf, Surf1…5) ##### 3.21.2.3.2 Coords set the coordinate system (Cartesian, Spheric, etc.); ##### 3.21.2.3.3 Cont # set the number of Contours (for e.g. Lego2 draw option); ##### 3.21.2.3.4 Errors draw errors in a Cartesian lego plot; ##### 3.21.2.3.5 Palette draw the color palette; ##### 3.21.2.3.6 Front draw the front box of a Cartesian lego plot; ##### 3.21.2.3.7 Back draw the back box of a Cartesian lego plot; ##### 3.21.2.3.8 Bar change the bar attributes: the width and offset. #### 3.21.2.4 Rebinning Tab The Rebinning tab has two different layouts. One is for a histogram that is not drawn from an ntuple; the other one is available for a histogram, which is drawn from an ntuple. In this case, the rebin algorithm can create a rebinned histogram from the original data i.e. the ntuple. To see the differences do for example:  TFile f ("hsimple.root"); hpxpy->Draw("Lego2"); // non ntuple histogram ntuple->Draw("px:py","","Lego2"); // ntuple histogram #### 3.21.2.5 Non-ntuple histogram: Rebin with sliders (one for the x, one for the y-axis) and the number of bins (shown in the field below them can be changed to any number, which divides the number of bins of the original histogram. Selecting the Apply button will delete the origin histogram and will replace it by the rebinned one on the screen. Selecting the Ignore the origin histogram will be restored. #### 3.21.2.6 Histogram drawn from an ntuple ##### 3.21.2.6.1 Rebin with the sliders the number of bins can be enlarged by a factor of 2,3,4,5 (moving to the right) or reduced by a factor of $$\frac{1}{2}$$, $$\frac{1}{3}$$, $$\frac{1}{4}$$, $$\frac{1}{5}$$. ##### 3.21.2.6.2 BinOffset with the BinOffset slider the origin of the histogram can be changed within one binwidth. Using this slider the effect of binning the data into bins can be made visible (=> statistical fluctuations). ##### 3.21.2.6.3 Axis Range with a double slider that gives the possibility for zooming. It is also possible to set the upper and lower limit in fields below the slider. ##### 3.21.2.6.4 Delayed drawing all the binning sliders can be set to delay draw mode. Then the changes on the histogram are only updated, when the Slider is released. This should be activated if the redrawing of the histogram is too time consuming. # 4 Graphs A graph is a graphics object made of two arrays X and Y, holding the x,y coordinates of n points. There are several graph classes; they are TGraph, TGraphErrors, TGraphAsymmErrors, and TMultiGraph. ## 4.1 TGraph The TGraph class supports the general case with non-equidistant points, and the special case with equidistant points. Graphs are created with the TGraph constructor. First, we define the arrays of coordinates and then create the graph. The coordinates can be arrays of doubles or floats.  Int_t n = 20; Double_t x[n], y[n]; for (Int_t i=0; i<n; i++) { x[i] = i*0.1; y[i] = 10*sin(x[i]+0.2); } TGraph *gr1 = new TGraph (n, x, y); An alternative constructor takes only the number of points n. It is expected that the coordinates will be set later. TGraph *gr2 = new TGraph(n); The default constructor can also be used. Further calls to SetPoint() will extend the internal vectors. TGraph *gr3 = new TGraph(); ### 4.1.1 Graph Draw Options The various drawing options for a graph are explained in TGraph::PaintGraph. They are: • L” A simple poly-line between every points is drawn • F” A fill area is drawn • F1” Idem as “F” but fill area is no more repartee around X=0 or Y=0 • F2” draw a fill area poly line connecting the center of bins • A” Axis are drawn around the graph • C” A smooth curve is drawn • *” A star is plotted at each point • P” The current marker of the graph is plotted at each point • B” A bar chart is drawn at each point • []” Only the end vertical/horizontal lines of the error bars are drawn. This option only applies to the TGraphAsymmErrors. • 1ylow = rwymin The options are not case sensitive and they can be concatenated in most cases. Let us look at some examples. #### 4.1.1.1 Continuous Line, Axis and Stars (AC*) { Int_t n = 20; Double_t x[n], y[n]; for (Int_t i=0;i<n;i++) { x[i] = i*0.1; y[i] = 10*sin(x[i]+0.2); } // create graph TGraph *gr = new TGraph(n,x,y); TCanvas *c1 = new TCanvas("c1","Graph Draw Options", 200,10,600,400); // draw the graph with axis, continuous line, and put // a * at each point gr->Draw("AC*"); } #### 4.1.1.2 Bar Graphs (AB) root[] TGraph *gr1 = new TGraph(n,x,y); root[] gr1->SetFillColor(40); root[] gr1->Draw("AB"); This code will only work if n, x, and y is defined. The previous example defines these. You need to set the fill color, because by default the fill color is white and will not be visible on a white canvas. You also need to give it an axis, or the bar chart will not be displayed properly. #### 4.1.1.3 Filled Graphs (AF) root[] TGraph *gr3 = new TGraph(n,x,y); root[] gr3->SetFillColor(45); root[] gr3->Draw("AF") This code will only work if n, x, yare defined. The first example defines them. You need to set the fill color, because by default the fill color is white and will not be visible on a white canvas. You also need to give it an axis, or the filled polygon will not be displayed properly. #### 4.1.1.4 Marker Options { Int_t n = 20; Double_t x[n], y[n]; // build the arrays with the coordinate of points for (Int_t i=0; i<n; i++) { x[i] = i*0.1; y[i] = 10*sin(x[i]+0.2); } // create graphs TGraph *gr3 = new TGraph(n,x,y); TCanvas *c1 = new TCanvas ("c1","Graph Draw Options", 200,10,600,400); // draw the graph with the axis,contineous line, and put // a marker using the graph's marker style at each point gr3->SetMarkerStyle(21); c1->cd(4); gr3->Draw("APL"); // get the points in the graph and put them into an array Double_t *nx = gr3->GetX(); Double_t *ny = gr3->GetY(); // create markers of different colors for (Int_t j=2; j<n-1; j++) { TMarker *m = new TMarker(nx[j], 0.5*ny[j], 22); m->SetMarkerSize(2); m->SetMarkerColor(31+j); m->Draw(); } } ## 4.2 Superimposing Two Graphs To super impose two graphs you need to draw the axis only once, and leave out the “A” in the draw options for the second graph. Next is an example: { Int_t n = 20; Double_t x[n], y[n], x1[n], y1[n]; // create a blue graph with a cos function gr1->SetLineColor(4); gr1->Draw("AC*"); // superimpose the second graph by leaving out the axis option "A" gr2->SetLineWidth(3); gr2->SetMarkerStyle(21); gr2->SetLineColor(2); gr2->Draw("CP"); } ## 4.3 Graphs with Error Bars A TGraphErrors is a TGraph with error bars. The various draw format options of TGraphErrors::Paint() are derived from TGraph. void TGraphErrors::Paint(Option_t *option) In addition, it can be drawn with the “Z” option to leave off the small lines at the end of the error bars. If option contains “>”, an arrow is drawn at the end of the error bars. If option contains “|>”, a full arrow is drawn at the end of the error bars. The size of the arrow is set to 2/3 of the marker size. The option “[]” is interesting to superimpose systematic errors on top of the graph with the statistical errors. When it is specified, only the end vertical/horizontal lines of the error bars are drawn. To control the size of the lines at the end of the error bars (when option 1 is chosen) use SetEndErrorSize(np). By default np=1; np represents the number of pixels. gStyle->SetEndErrorSize(np); The four parameters of TGraphErrors are: X, Y (as in TGraph), X-errors, and Y-errors - the size of the errors in the x and y direction. Next example is $ROOTSYS/tutorials/graphs/gerrors.C.

{
c1 = new TCanvas("c1","A Simple Graph with error bars",200,10,700,500);
c1->SetGrid();

// create the coordinate arrays
Int_t n = 10;
Float_t x[n]  = {-.22,.05,.25,.35,.5,.61,.7,.85,.89,.95};
Float_t y[n]  = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};

// create the error arrays
Float_t ex[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
Float_t ey[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};

// create the TGraphErrors and draw it
gr = new TGraphErrors(n,x,y,ex,ey);
gr->SetTitle("TGraphErrors Example");
gr->SetMarkerColor(4);
gr->SetMarkerStyle(21);
gr->Draw("ALP");
c1->Update();
}

## 4.4 Graphs with Asymmetric Error Bars

A TGraphAsymmErrors is a TGraph with asymmetric error bars. It inherits the various draw format options from TGraph. Its method Paint(Option_t *option) paints the TGraphAsymmErrors with the current attributes. You can set the following additional options for drawing:

• z” or “Z”the horizontal and vertical small lines are not drawn at the end of error bars

• >”an arrow is drawn at the end of the error bars

• |>”a full arrow is drawn at the end of the error bar; its size is $$\frac{2}{3}$$ of the marker size

• []”only the end vertical/horizontal lines of the error bars are drawn; this option is interesting to superimpose systematic errors on top of a graph with statistical errors.

The constructor has six arrays as parameters: X and Y as TGraph and low X-errors and high X-errors, low Y-errors and high Y-errors. The low value is the length of the error bar to the left and down, the high value is the length of the error bar to the right and up.

{
c1 = new TCanvas("c1","A Simple Graph with error bars",
200,10,700,500);
c1->SetGrid();

// create the arrays for the points
Int_t n = 10;
Double_t x[n]  = {-.22,.05,.25,.35,.5, .61,.7,.85,.89,.95};
Double_t y[n]  = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};

// create the arrays with high and low errors
Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};
Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03};
Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6};

// create TGraphAsymmErrors with the arrays
gr = new TGraphAsymmErrors(n,x,y,exl,exh,eyl,eyh);
gr->SetTitle("TGraphAsymmErrors Example");
gr->SetMarkerColor(4);
gr->SetMarkerStyle(21);
gr->Draw("ALP");
}

## 4.5 Graphs with Asymmetric Bent Errors

A TGraphBentErrors is a TGraph with bent, asymmetric error bars. The various format options to draw a TGraphBentErrors are explained in TGraphBentErrors::Paint method. The TGraphBentErrors is drawn by default with error bars and small horizontal and vertical lines at the end of the error bars. If option “z” or “Z” is specified, these small lines are not drawn. If the option “X” is specified, the errors are not drawn (the TGraph::Paint method equivalent).

• if option contains “>”, an arrow is drawn at the end of the error bars

• if option contains “|>”, a full arrow is drawn at the end of the error bars

• the size of the arrow is set to 2/3 of the marker size

• if option “[]” is specified, only the end vertical/horizontal lines of the error bars are drawn. This option is interesting to superimpose systematic errors on top of a graph with statistical errors.

This figure has been generated by the following macro:

{
Int_t n = 10;
Double_t x[n] = {-0.22,0.05,0.25,0.35,0.5,0.61,0.7,0.85,0.89,0.95};
Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};
Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};
Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03};
Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6};
Double_t exld[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
Double_t eyld[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
Double_t exhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
Double_t eyhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.05,.0};
gr = new TGraphBentErrors(n,x,y,
exl,exh,eyl,eyh,exld,exhd,eyld,eyhd);
gr->SetTitle("TGraphBentErrors Example");
gr->SetMarkerColor(4);
gr->SetMarkerStyle(21);
gr->Draw("ALP");
}

## 4.6 TGraphPolar

The TGraphPolar class creates a polar graph (including error bars). A TGraphPolar is a TGraphErrors represented in polar coordinates. It uses the class TGraphPolargram to draw the polar axis.

{
TCanvas *CPol = new TCanvas("CPol","TGraphPolar Examples",700,700);
Double_t rmin=0;
Double_t rmax=TMath::Pi()*2;
Double_t r[1000];
Double_t theta[1000];
TF1 * fp1 = new TF1("fplot","cos(x)",rmin,rmax);
for (Int_t ipt = 0; ipt < 1000; ipt++) {
r[ipt] = ipt*(rmax-rmin)/1000+rmin;
theta[ipt] = fp1->Eval(r[ipt]);
}
TGraphPolar * grP1 = new TGraphPolar(1000,r,theta);
grP1->SetLineColor(2);
grP1->Draw("AOL");
}

The TGraphPolar drawing options are:

“O” Polar labels are paint orthogonally to the polargram radius.

“P” Polymarker are paint at each point position.

“E” Paint error bars.

“F” Paint fill area (closed polygon).

“A”Force axis redrawing even if a polagram already exists.

## 4.7 TGraph Exclusion Zone

When a graph is painted with the option “C” or “L”, it is possible to draw a filled area on one side of the line. This is useful to show exclusion zones. This drawing mode is activated when the absolute value of the graph line width (set thanks to SetLineWidth) is greater than 99. In that case the line width number is interpreted as 100*ff+ll = ffll. The two-digit numbers “ll” represent the normal line width whereas “ff” is the filled area width. The sign of “ffll” allows flipping the filled area from one side of the line to the other. The current fill area attributes are used to draw the hatched zone.

{
c1 = new TCanvas("c1","Exclusion graphs examples",200,10,700,500);
c1->SetGrid();

// create the multigraph
TMultiGraph *mg = new TMultiGraph();
mg->SetTitle("Exclusion graphs");

// create the graphs points
const Int_t n = 35;
Double_t x1[n], x2[n], x3[n], y1[n], y2[n], y3[n];
for (Int_t i=0;i<n;i++) {
x1[i] = i*0.1; y1[i] = 10*sin(x1[i]);
x2[i] = x1[i]; y2[i] = 10*cos(x1[i]);
x3[i] = x1[i]+.5; y3[i] = 10*sin(x1[i])-2;
}

// create the 1st TGraph
gr1 = new TGraph(n,x1,y1);
gr1->SetLineColor(2);
gr1->SetLineWidth(1504);
gr1->SetFillStyle(3005);

// create the 2nd TGraph
gr2 = new TGraph(n,x2,y2);
gr2->SetLineColor(4);
gr2->SetLineWidth(-2002);
gr2->SetFillStyle(3004);
gr2->SetFillColor(9);

// create the 3rd TGraph
gr3 = new TGraph(n,x3,y3);
gr3->SetLineColor(5);
gr3->SetLineWidth(-802);
gr3->SetFillStyle(3002);
gr3->SetFillColor(2);

// put the graphs in the multigraph

// draw the multigraph
mg->Draw("AC");
}

## 4.8 TGraphQQ

A TGraphQQ allows drawing quantile-quantile plots. Such plots can be drawn for two datasets, or for one dataset and a theoretical distribution function.

### 4.8.1 Two Datasets

Quantile-quantile plots are used to determine whether two samples come from the same distribution. A qq-plot draws the quantiles of one dataset against the quantile of the other. The quantiles of the dataset with fewer entries are on Y-axis, with more entries - on X-axis. A straight line, going through 0.25 and 0.75 quantiles is also plotted for reference. It represents a robust linear fit, not sensitive to the extremes of the datasets. If the datasets come from the same distribution, points of the plot should fall approximately on the 45 degrees line. If they have the same distribution function, but different parameters of location or scale, they should still fall on the straight line, but not the 45 degrees one.

The greater their departure from the straight line, the more evidence there is that the datasets come from different distributions. The advantage of qq-plot is that it not only shows that the underlying distributions are different, but, unlike the analytical methods, it also gives information on the nature of this difference: heavier tails, different location/scale, different shape, etc.

### 4.8.2 One Dataset

Quantile-quantile plots are used to determine if the dataset comes from the specified theoretical distribution, such as normal. A qq-plot draws quantiles of the dataset against quantiles of the specified theoretical distribution. Note, that density, not CDF should be specified a straight line, going through 0.25 and 0.75 quantiles could also be plotted for reference. It represents a robust linear fit, not sensitive to the extremes of the dataset. As in the two datasets case, departures from straight line indicate departures from the specified distribution. Next picture shows an example of a qq-plot of a dataset from N(3, 2) distribution and TMath::Gaus(0, 1) theoretical function. Fitting parameters are estimates of the distribution mean and sigma.

## 4.9 TMultiGraph

A TMultiGraph is a collection of TGraph (or derived) objects. Use TMultiGraph::Addto add a new graph to the list. The TMultiGraph owns the objects in the list. The drawing and fitting options are the same as for TGraph.

{
// create the points
Int_t n = 10;
Double_t x[n]  = {-.22,.05,.25,.35,.5,.61,.7,.85,.89,.95};
Double_t y[n]  = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};
Double_t x2[n]  = {-.12,.15,.35,.45,.6,.71,.8,.95,.99,1.05};
Double_t y2[n]  = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};

// create the width of errors in x and y direction
Double_t ex[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
Double_t ey[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};

// create two graphs
TGraph *gr1 = new TGraph(n,x2,y2);
TGraphErrors *gr2 = new TGraphErrors(n,x,y,ex,ey);

// create a multigraph and draw it
TMultiGraph  *mg  = new TMultiGraph();
mg->Draw("ALP");
}

## 4.10 TGraph2D

This class is a set of N points x[i], y[i], z[i] in a non-uniform grid. Several visualization techniques are implemented, including Delaunay triangulation. Delaunay triangulation is defined as follow: ‘for a set S of points in the Euclidean plane, the unique triangulation DT(S) of S such that no point in S is inside the circum-circle of any triangle in DT(S). DT(S) is the dual of the Voronoï diagram of S. If n is the number of points in S, the Voronoï diagram of S is the partitioning of the plane containing S points into n convex polygons such that each polygon contains exactly one point and every point in a given polygon is closer to its central point than to any other. A Voronoï diagram is sometimes also known as a Dirichlet tessellation.

The TGraph2D class has the following constructors:

• With an arrays’ dimension n and three arrays x, y, and z (can be arrays of doubles, floats, or integers):
   TGraph2D *g = new TGraph2D(n,x,y,z);
• With an array dimension only:
   TGraph2D *g = new TGraph2D(n);
• Internal arrays are filled with the method SetPoint at the position “i” with the values x, y, z:
   g->SetPoint(i,x,y,z);
• Without parameters; the method SetPoint must be used to fill the internal arrays.
   TGraph2D *g = new TGraph2D();
• From a file:
   TGraph2D *g = new TGraph2D("graph.dat");

The arrays are read from the ASCII file “graph.dat” according to a specified format. The format’s default value is “%lg %lg %lg”. Note that in any of last three cases, the SetPoint method can be used to change a data point or to add a new one. If the data point index (i) is greater than the size of the internal arrays, they are automatically extended.

Specific drawing options can be used to paint a TGraph2D:

• TRI” the Delaunay triangles are drawn using filled area. A hidden surface drawing technique is used. The surface is painted with the current fill area color. The edges of the triangles are painted with the current line color;

• TRIW”the Delaunay triangles are drawn as wire frame;

• TRI1” the Delaunay triangles are painted with color levels. The edges of the triangles are painted with the current line color;

• TRI2” the Delaunay triangles are painted with color levels;

• P”draws a marker at each vertex;

• P0” draws a circle at each vertex. Each circle background is white.

A TGraph2D can be also drawn with ANY options valid for 2D histogram drawing. In this case, an intermediate 2D histogram is filled using the Delaunay triangles technique to interpolate the data set. TGraph2D linearly interpolate a Z value for any (X,Y) point given some existing (X,Y,Z) points. The existing (X,Y,Z) points can be randomly scattered. The algorithm works by joining the existing points to make Delaunay triangles in (X,Y). These are then used to define flat planes in (X,Y,Z) over which to interpolate. The interpolated surface thus takes the form of tessellating triangles at various angles. Output can take the form of a 2D histogram or a vector. The triangles found can be drawn in 3D. This software cannot be guaranteed to work under all circumstances. It was originally written to work with a few hundred points in anXY space with similar X and Y ranges.

{
TCanvas *c = new TCanvas("c","Graph2D example",0,0,700,600);
Double_t x, y, z, P = 6.;
Int_t np = 200;
TGraph2D *dt = new TGraph2D();
TRandom *r = new TRandom();

for (Int_t N=0; N<np; N++) {
x = 2*P*(r->Rndm(N))-P;
y = 2*P*(r->Rndm(N))-P;
z = (sin(x)/x)*(sin(y)/y)+0.2;
dt->SetPoint(N,x,y,z);
}
gStyle->SetPalette(55);
dt->Draw("surf1");       // use "surf1" to generate the left picture
}                           // use "tri1 p0" to generate the right one

## 4.12 Fitting a Graph

The graph Fit method in general works the same way as the TH1::Fit. See “Fitting Histograms”.

## 4.13 Setting the Graph’s Axis Title

To give the axis of a graph a title you need to draw the graph first, only then does it actually have an axis object. Once drawn, you set the title by getting the axis and calling the TAxis::SetTitle method, and if you want to center it, you can call the TAxis::CenterTitle method.

Assuming that n, x, and y are defined. Next code sets the titles of the x and y axes.

root[] gr5 = new TGraph(n,x,y)
root[] gr5->Draw()
<TCanvas::MakeDefCanvas>: created default TCanvas with name c1
root[] gr5->Draw("ALP")
root[] gr5->GetXaxis()->SetTitle("X-Axis")
root[] gr5->GetYaxis()->SetTitle("Y-Axis")
root[] gr5->GetXaxis()->CenterTitle()
root[] gr5->GetYaxis()->CenterTitle()
root[] gr5->Draw("ALP")

For more graph examples see the scripts: $ROOTSYS/tutorials directory graph.C, gerrors.C, zdemo.C, and gerrors2.C. ## 4.14 Zooming a Graph To zoom a graph you can create a histogram with the desired axis range first. Draw the empty histogram and then draw the graph using the existing axis from the histogram. { c1 = new TCanvas("c1","A Zoomed Graph",200,10,700,500); hpx = new TH2F("hpx","Zoomed Graph Example",10,0,0.5,10,1.0,8.0); hpx->SetStats(kFALSE); // no statistics hpx->Draw(); Int_t n = 10; Double_t x[n] = {-.22,.05,.25,.35,.5,.61,.7,.85,.89,.95}; Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1}; gr = new TGraph(n,x,y); gr->SetMarkerColor(4); gr->SetMarkerStyle(20); gr->Draw("LP");// and draw it without an axis } The next example is the same graph as above with a zoom in the x and y directions. ## 4.15 The User Interface for Graphs The class TGraphEditor provides the user interface for setting the following graph attributes interactively: • Title text entry field … sets the title of the graph. • Shape radio button group - sets the graph shapes: • No Line: draw unconnected points; • Smooth Line: a smooth curve; • Simple Line: a simple poly-line; • Bart Chart: a bar chart at each point. • Fill Area: a fill area is drawn. • Show Marker - sets markers as visible or invisible. • Exclusion Zone - specifies the exclusion zone parameters : • ’+-‘ check button: sets on which side of the line the exclusion zone will be drawn; • Width combo box: defines the width of the zone. # 5 Fitting Histograms To fit a histogram you can use the Fit Panel on a visible histogram via the context menu, or you can use the TH1::Fit method. The Fit Panel, which is limited, is best for prototyping. The histogram needs to be drawn in a pad before the Fit Panel is invoked. The method TH1::Fit is more powerful and is used in scripts and programs. ## 5.1 The Fit Method The Fit method is implemented in ROOT for the histogram classes TH1, the sparse histogram classes, THnSparse, the graph classes, TGraph, TGraph2D and TMultiGraph for fitting a collection of Graphs with the same function. ### 5.1.1 The TH1::Fit Method To fit a histogram programmatically, you can use the TH1::Fit method. Here is the signatures of TH1::Fit and an explanation of the parameters:  TFitResultPtr Fit(TF1 *function, Option_t *option, Option_t *goption, Axis_t xxmin, Axis_t xxmax) • function a pointer to the fitted function (the fit model) object. One can also use the function name. This name may be one of ROOT pre-defined function names or a user-defined function. See the next paragraph for the list of pre-defined functions. • *option: The second parameter is the fitting option. Here is the list of fitting options: • W” Set all weights to 1 for non empty bins; ignore error bars • WW” Set all weights to 1 including empty bins; ignore error bars • I” Use integral of function in bin instead of value at bin center • L” Use log likelihood method (default is chi-square method). To be used when the histogram represents counts • WL” Weighted log likelihood method. To be used when the histogram has been filled with weights different than 1. • P” Use Pearson chi-square method, using expected errors instead of the observed one given by TH1::GetBinError (default case). The expected error is instead estimated from the the square-root of the bin function value. • Q” Quiet mode (minimum printing) • V” Verbose mode (default is between Q and V) • S” The result of the fit is returned in the TFitResultPtr. • E” Perform better errors estimation using the Minos technique • M” Improve fit results, by using the IMPROVE algorithm of TMinuit. • R” Use the range specified in the function range • N” Do not store the graphics function, do not draw • 0” Do not plot the result of the fit. By default the fitted function is drawn unless the option “N” above is specified. • +” Add this new fitted function to the list of fitted functions (by default, the previous function is deleted and only the last one is kept) • B”Use this option when you want to fix one or more parameters and the fitting function is a predefined one, like polN, expo, landau, gaus. Note that in case of pre-defined functions some default initial values and limits are set. • C”In case of linear fitting, don’t calculate the chisquare (saves time). • F”If fitting a linear function (e.g. polN), switch to use the default minimizer (e.g. Minuit). By default, polN functions are fitted by the linear fitter. • *goption:The third parameter is the graphics option that is the same as in the TH1::Draw (see the chapter Draw Options). • xxmin, xxmax:Thee fourth and fifth parameters specify the range over which to apply the fit. By default, the fitted function object is added to the histogram and is drawn in the current pad. ### 5.1.2 The TGraph::Fit Method The signature for fitting a TGraph is exactly the same as for the TH1. Only some options apply only for fitting histograms, these are the options “L”, “WL” and “I”. These options apply instead only for TGraph::Fit, the rest of options (appart from “L”, “WL” and “I” are the same) • TGraph specific options • EX0” When fitting a TGraphErrors or a TgraphAsymErrors the errors on the coordinates are not used in the fit • ROB” in case of linear fitting use the Robust fitting. Compute the LTS regression coefficients (robust (resistant) regression), using the default fraction of good points. • ROB=0.x” as above, but compute the LTS regression coefficients, using 0.x as a fraction of good points. ## 5.2 The TF1 function class Here we will show how to create the TF1 class that is used for fitting histograms and graphs. ### 5.2.1 Fit with a Predefined Function To fit a histogram with a predefined function, simply pass the name of the function in the first parameter of TH1::Fit. For example, this line fits histogram object hist with a Gaussian. root[] hist.Fit("gaus"); The initial parameter values (and eventual limits) for pre-defined functions are set automatically. For overriding the default limits values use the fit option B. The list of pre-defined functions that can be used with the Fit method is the following: • gaus” Gaussian function with 3 parameters: f(x) = p0*exp(-0.5*((x-p1)/p2)^2) • expo”An Exponential with 2 parameters: f(x) = exp(p0+p1*x) • polN” A polynomial of degree N, where N is a number between 0 and 9: f(x) = p0 + p1*x + p2*x2 +... • chebyshevN” A Chebyshev polynomial of degree N, where N is a number between 0 and 9: f(x) = p0 + p1*x + p2*(2*x2-1) +... • landau” Landau function with mean and sigma. This function has been adapted from the CERNLIB routine G110 denlan (see TMath::Landau). • gausn” Normalized form of the gaussian function with 3 parameters f(x) = p0*exp(-0.5*((x-p1)/p2)^2)/(p2 *sqrt(2PI)) ### 5.2.2 Creating User-Defined Functions (TF1) You can create a TF1 object and use it in the call the TH1::Fit. The parameter in to the Fit method is the NAME of the TF1 object. There are three ways to create a TF1. • Using C++ expression using x with a fixed set of operators and functions defined in TFormula. • Same as first one, with parameters • Using a function that you have defined. This can be a free function or a functor object or a particular member function of a class. #### 5.2.2.1 Creating a TF1 with a Formula Let’s look at the first case. Here we call the TF1 constructor by giving it the formula: sin(x)/x. root[] TF1 *f1 = new TF1("f1","sin(x)/x",0,10) You can also use a TF1 object in the constructor of another TF1. root[] TF1 *f2 = new TF1("f2","f1*2",0,10) #### 5.2.2.2 Creating a TF1 with Parameters The second way to construct a TF1 is to add parameters to the expression. Here we use two parameters: root[] TF1 *f1 = new TF1("f1","[0]*x*sin([1]*x)",-3,3); The parameter index is enclosed in square brackets. To set the initial parameters explicitly you can use: root[] f1->SetParameter(0,10); This sets parameter 0 to 10. You can also use SetParameters to set multiple parameters at once. root[] f1->SetParameters(10,5); This sets parameter 0 to 10 and parameter 1 to 5. We can now draw the TF1: root[] f1->Draw() #### 5.2.2.3 Creating a TF1 with a User Function The third way to build a TF1 is to define a function yourself and then pass the function pointer to the constructor. A function for a TF1 constructor needs to have this exact signature: Double_t fitf(Double_t *x,Double_t *par) The two parameters are: • x a pointer to the dimension array. Each element contains a dimension. For a 1D histogram only x[0] is used, for a 2D histogram x[0] and x[1] is used, and for a 3D histogram x[0], x[1], and x[2] are used. For histograms, only 3 dimensions apply, but this method is also used to fit other objects, for example an ntuple could have 10 dimensions. • par a pointer to the parameters array. This array contains the current values of parameters when it is called by the fitting function. The following script $ROOTSYS/tutorials/fit/myfit.C illustrates how to fit a 1D histogram with a user-defined function. First we declare the function.

   // define a function with 3 parameters
Double_t fitf(Double_t *x,Double_t *par) {
Double_t arg = 0;
if (par[2]!=0) arg = (x[0] - par[1])/par[2];
Double_t fitval = par[0]*TMath::Exp(-0.5*arg*arg);
return fitval;
}

Now we use the function:

   // this function uses fitf to fit a histogram
void fitexample() {

// open a file and get a histogram
TFile *f = new TFile("hsimple.root");
TH1F *hpx = (TH1F*)f->Get("hpx");

// Create a TF1 object using the function defined above.
// The last three parameters specify the number of parameters
// for the function.
TF1 *func = new TF1("fit",fitf,-3,3,3);
// set the parameters to the mean and RMS of the histogram
func->SetParameters(500,hpx->GetMean(),hpx->GetRMS());

// give the parameters meaningful names
func->SetParNames ("Constant","Mean_value","Sigma");

// call TH1::Fit with the name of the TF1 object
hpx->Fit("fit");
}

You can create a TF1 also from a C++ function object (functor) with parameters A TF1 can be created from any C++ class implementing this member function:

double operator()(double *x, double *p)

The advantage of the function object is that it can have a state and reference therefore what-ever other object the user needs, without using globals. This is an example to define first the function object

class  MyFunctionObject {
public:
// use constructor to customize your function object
MyFunctionObject(......) { ......}

double operator() (double *x, double *p) {
// function implementation using class data members
}
};

and then use it to create the TF1:

   MyFunctionObject fobj(....);       // create the function object
TF1 * f = new TF1("f",fobj,xmin,xmax,npar);    // create TF1 class with n-parameters and range [xmin,xmax]

If using C++11, one can create a TF1 also from a C++ lambda function:

// create TF1 class with 2 parameters and range [xmin,xmax] using a lambda
TF1 * f = new TF1("f",[](double*x,double*p){return p[0] + p[1]*x[0];},xmin,xmax,2);

## 5.3 Configuring the Fit

We will show here some configuration actions that can or must be done when fitting histogram or graph using the Fit method.

### 5.3.1 Fixing and Setting Parameters’ Bounds

Parameters must be initialized before invoking the Fit method. The setting of the parameter initial values is automatic for the predefined functions: poln, exp, gaus, and landau. You can fix one or more parameters by specifying the “B” option when calling the Fit method. When a function is not predefined, the fit parameters must be initialized to some value as close as possible to the expected values before calling the fit function.

To set bounds for one parameter, use TF1::SetParLimits:

   func->SetParLimits(0,-1,1);

When the lower and upper limits are equal, the parameter is fixed. Next two statements fix parameter 4 at 10.

   func->SetParameter(4,10);
func->SetParLimits(4,10,10);

However, to fix a parameter to 0, one must call the FixParameter function:

   func->SetParameter(4,0);
func->FixParameter(4,0);

Note that you are not forced to set the limits for all parameters. For example, if you fit a function with 6 parameters, you can:

   func->SetParameters(0,3.1,1.e-6,-1.5,0,100);
func->SetParLimits(3,-10,4);
func->FixParameter(4,0);

With this setup, parameters 0->2 can vary freely, parameter 3 has boundaries [-10, 4] with initial value -1.5, and parameter 4 is fixed to 0.

### 5.3.2 Fitting Sub Ranges

By default, TH1::Fit will fit the function on the defined histogram range. You can specify the option “R” in the second parameter of TH1::Fit to restrict the fit to the range specified in the TF1 constructor. In this example, the fit will be limited to -3 to 3, the range specified in the TF1 constructor.

root[] TF1 *f1 = new TF1("f1","[0]*x*sin([1]*x)",-3,3);
root[] hist->Fit("f1","R");

You can also specify a range in the call to TH1::Fit:

root[] hist->Fit("f1","","",-2,2)

See macros $ROOTSYS/tutorials/fit/myfit.C and multifit.C as more completed examples. ### 5.3.3 Fitting Multiple Sub Ranges The script for this example is $ROOTSYS/tutorials/fit/multifit.C. It shows how to use several Gaussian functions with different parameters on separate sub ranges of the same histogram. To use a Gaussian, or any other ROOT built in function, on a sub range you need to define a new TF1. Each is ‘derived’ from the canned function gaus.

First, four TF1 objects are created - one for each sub-range:

   g1 = new TF1("m1","gaus",85,95);
g2 = new TF1("m2","gaus",98,108);
g3 = new TF1("m3","gaus",110,121);
// The total is the sum of the three, each has 3 parameters
total = new TF1("mstotal","gaus(0)+gaus(3)+gaus(6)",85,125);

Next, we fill a histogram with bins defined in the array x.

   // Create a histogram and set it's contents
h = new TH1F("g1","Example of several fits in subranges",
np,85,134);
h->SetMaximum(7);
for (int i=0; i<np; i++) {
h->SetBinContent(i+1,x[i]);
}
// Define the parameter array for the total function
Double_t par[9];

When fitting simple functions, such as a Gaussian, the initial values of the parameters are automatically computed by ROOT. In the more complicated case of the sum of 3 Gaussian functions, the initial values of parameters must be set. In this particular case, the initial values are taken from the result of the individual fits. The use of the “+” sign is explained below:

   // Fit each function and add it to the list of functions
h->Fit(g1,"R");
h->Fit(g2,"R+");
h->Fit(g3,"R+");

// Get the parameters from the fit
g1->GetParameters(&par[0]);
g2->GetParameters(&par[3]);
g3->GetParameters(&par[6]);

// Use the parameters on the sum
total->SetParameters(par);
h->Fit(total,"R+");

The example $ROOTSYS/tutorials/fit/multifit.C also illustrates how to fit several functions on the same histogram. By default a Fit command deletes the previously fitted function in the histogram object. You can specify the option “+” in the second parameter to add the newly fitted function to the existing list of functions for the histogram. root[] hist->Fit("f1","+","",-2,2) Note that the fitted function(s) are saved with the histogram when it is written to a ROOT file. ## 5.4 Example of fit: Combining Functions You can combine functions to fit a histogram with their sum as it is illustrated in the macro FitDemo.C ($ROOTSYS/tutorials/fit/FittingDemo.C). We have a function that is the combination of a background and Lorentzian peak. Each function contributes 3 parameters:

$y(E) = a_{1} + a_{2}E + a_{3}E^{2} + \frac{A_{p}(\frac{G}{2p})} {(E-m)^{2} + (\frac{G}{2})^2 }$

BackgroundLorentzian Peak

par[0] = $$a_{1}$$ par[0] = $$A_{p}$$

par[1] = $$a_{2}$$ par[1] = $$G$$

par[2] = $$a_{3}$$ par[2] = $$m$$

The combination function (fitFunction) has six parameters:

fitFunction = background(x,par) + LorentzianPeak(x,&par[3])

par[0]=$$a_{1}$$ par[1]=$$a_{2}$$ par[2]=$$a_{3}$$ par[3]=$$A_{p}$$ par[4]=$$G$$ par[5]=$$m$$

This script creates a histogram and fits it with the combination of two functions. First we define the two functions and the combination function:

   // Quadratic background function
Double_t background(Double_t *x, Double_t *par) {
return par[0] + par[1]*x[0] + par[2]*x[0]*x[0];
}

// Lorentzian Peak function
Double_t lorentzianPeak(Double_t *x, Double_t *par) {
return (0.5*par[0]*par[1]/TMath::Pi()) / TMath::Max(1.e-10,
(x[0]-par[2])*(x[0]-par[2])+ .25*par[1]*par[1]);
}

// Sum of background and peak function
Double_t fitFunction(Double_t *x, Double_t *par) {
return background(x,par) + lorentzianPeak(x,&par[3]);
}

void FittingDemo() {
// bevington exercise by P. Malzacher, modified by R. Brun
const int nBins = 60;
Stat_t data[nBins] = {  6, 1,10,12, 6,13,23,22,15,21,
23,26,36,25,27,35,40,44,66,81,
75,57,48,45,46,41,35,36,53,32,
40,37,38,31,36,44,42,37,32,32,
43,44,35,33,33,39,29,41,32,44,
26,39,29,35,32,21,21,15,25,15};
TH1F *histo = new TH1F("example_9_1",

for(int i=0; i < nBins;  i++) {
// we use these methods to explicitly set the content
// and error instead of using the fill method.
histo->SetBinContent(i+1,data[i]);
histo->SetBinError(i+1,TMath::Sqrt(data[i]));
}
// create a TF1 with the range from 0 to 3 and 6 parameters
TF1 *fitFcn = new TF1("fitFcn",fitFunction,0,3,6);

// first try without starting values for the parameters
// this defaults to 1 for each param.
histo->Fit("fitFcn");
// this results in an ok fit for the polynomial function however
// the non-linear part (Lorentzian

## 5.5 Result of the fit

Here we will show how to obtain the result of the fit (fitted function, parameter values, errors and eventually the covariance and correlation matrix).

### 5.5.1 Associated Function

One or more objects (typically a TF1\*) can be added to the list of functions (fFunctions) associated to each histogram. A call to TH1::Fit adds the fitted function to this list. Given a histogram h, one can retrieve the associated function with:

   TF1 *myfunc = h->GetFunction("myfunc");

If the histogram (or graph) is made persistent, the list of associated functions is also persistent. Retrieve a pointer to the function with the TH1::GetFunction() method. Then you can retrieve the fit parameters from the function (TF1) with calls such as:

root[] TF1 *fit = hist->GetFunction(function_name);
root[] Double_t chi2 = fit->GetChisquare();
// value of the first parameter
root[] Double_t p1 = fit->GetParameter(0);
// error of the first parameter
root[] Double_t e1 = fit->GetParError(0);

Using the fit option S one can access the full result of the fit including the covariance and correlation matrix. See later the paragraph TFitResult.

### 5.5.3 Associated Errors

By default, for each bin, the sum of weights is computed at fill time. One can also call TH1::Sumw2 to force the storage and computation of the sum of the square of weights per bin. If Sumw2 has been called, the error per bin is computed as the sqrt(sum of squares of weights); otherwise, the error is set equal to the sqrt(bin content). To return the error for a given bin number, do:

   Double_t error = h->GetBinError(bin);

Empty bins are excluded in the fit when using the Chi-square fit method. When fitting an histogram representing counts (i.e with Poisson statistics) it is recommended to use the Log-Likelihood method (option ‘L’ or “WL”), particularly in case of low statistics. When the histogram has been filled with weights different than one, a weighted likelihood method can be used and the errors retrieved from the fit are corrected following a procedure described in paragraph 8.5.2 of the book, F. James, Statistical Methods in Experimental Physics, 2nd Edition.

### 5.5.4 Fit Statistics

You can change the statistics box to display the fit parameters with the TStyle::SetOptFit(mode) method. This parameter has four digits: mode = pcev (default = 0111)

• p = 1 print probability
• c = 1 print Chi-square/number of degrees of freedom
• e = 1 print errors (if e=1, v must be 1)
• v = 1 print name/values of parameters

For example, to print the fit probability, parameter names/values, and errors, use:

   gStyle->SetOptFit(1011);

## 5.6 The Fit Panel

To display the Fit Panel right click on a histogram to pop up the context menu, and then select the menu entry Fit Panel.

The new Fit Panel GUI is available in ROOT v5.14. Its goal is to replace the old Fit Panel and to provide more user friendly way for performing, exploring and comparing fits.

By design, this user interface is planned to contain two tabs: “General” and “Minimization”. Currently, the “General” tab provides user interface elements for setting the fit function, fit method and different fit, draw, print options. The “Minimization tab” provides the option to set the Minimizer to use in the fit and its specific options.

The new fit panel is a modeless dialog, i.e. when opened, it does not prevent users from interacting with other windows. Its first prototype is a singleton application. When the Fit Panel is activated, users can select an object for fitting in the usual way, i.e. by left-mouse click on it. If the selected object is suitable for fitting, the fit panel is connected with this object and users can perform fits by setting different parameters and options.

### 5.6.1 Function Choice and Settings

‘Predefined’ combo box - contains a list of predefined functions in ROOT. You have a choice of several polynomials, a Gaussian, a Landau, and an Exponential function. The default one is Gaussian.

‘Operation’ radio button group defines the selected operational mode between functions:

Nop - no operation (default);

Conv - convolution (will be implemented in the future).

Users can enter the function expression into the text entry field below the ‘Predefined’ combo box. The entered string is checked after the Enter key was pressed and an error message shows up, if the function string is not accepted.

Set Parameters’ button opens a dialog for parameters settings, which will be explained later.

### 5.6.2 Fitter Settings

‘Method’ combo box currently provides only two fit model choices: Chi-square and Binned Likelihood. The default one is Chi-square. The Binned Likelihood is recommended for bins with low statistics.

‘Linear Fit’ check button sets the use of Linear fitter when is selected. Otherwise the minimization is done by Minuit, i.e. fit option “F” is applied. The Linear fitter can be selected only for functions linear in parameters (for example - polN).

‘Robust’ number entry sets the robust value when fitting graphs.

‘No Chi-square’ check button switch On/Off the fit option “C” - do not calculate Chi-square (for Linear fitter).

‘Integral’ check button switch On/Off the option “I” - use integral of function instead of value in bin center.

‘Best Errors’ sets On/Off the option “E” - better errors estimation by using Minos technique.

‘All weights = 1’ sets On/Off the option “W”- all weights set to 1 excluding empty bins; error bars ignored.

‘Empty bins, weights=1’ sets On/Off the option “WW” - all weights equal to 1 including empty bins; error bars ignored.

‘Use range’ sets On/Off the option “R” - fit only data within the specified function range. Sliders settings are used if this option is set to On. Users can change the function range values by pressing the left mouse button near to the left/right slider edges. It is possible to change both values simultaneously by pressing the left mouse button near to the slider center and moving it to a new position.

‘Improve fit results’ sets On/Off the option “M”- after minimum is found, search for a new one.

‘Add to list’ sets On/Off the option “+”- add function to the list without deleting the previous one. When fitting a histogram, the function is attached to the histogram’s list of functions. By default, the previously fitted function is deleted and replaced with the most recent one, so the list only contains one function. Setting this option to On will add the newly fitted function to the existing list of functions for the histogram. Note that the fitted functions are saved with the histogram when it is written to a ROOT file. By default, the function is drawn on the pad displaying the histogram.

### 5.6.3 Draw Options

‘SAME’ sets On/Off function drawing on the same pad. When a fit is executed, the image of the function is drawn on the current pad.

‘No drawing’ sets On/Off the option “0”- do not draw the fit results.

‘Do not store/draw’ sets On/Off option “N”- do not store the function and do not draw it.

The advance option button is enabled only after having performed the fit and provides additional drawing options that can be used after having done the fit. These new drawing tools, which can be selected by the “Advanced Drawing Tool” panel that pops up when clicking the “Advanced” button, are:

• Contour: to plot the confidence contour of two chosen parameters. One can select the number of points to draw the contour (more points might require more time to compute it), the parameters and the desired confidence level .

• Scan : to plot a scan of the minimization function (likelihood or chi-squared) around the minimum as function of the chosen parameter.

• Conf Interval : to plot the confidence interval of the fitted function as a filled coloured band around its central value. One can select the desired confidence level for the band to be plotted.

This set of options specifies the amount of feedback printed on the root command line after performed fits.

‘Verbose’ - prints fit results after each iteration.

‘Quiet’ - no fit information is printed.

‘Default’ - between Verbose and Quiet.

### 5.6.6 Command Buttons

Fit button - performs a fit taking different option settings via the Fit Panel interface.

Reset - sets the GUI elements and related fit settings to the default ones.

Close - closes the Fit panel window.

### 5.6.7 Minimization Options

With this tab one can select specific options for minimization. These include

• The minimizer library ( Minuit, Minuit2, Fumili, GSL, Genetics )
• The method (algorithm) for minimization. For example for Minuit one can choose between (Migrad, Simplex or Scan)
• Error definition
• Minimization tolerance
• Number of iterations/function calls
• Print Level: (Default, Verbose or Quiet).

## 5.7 New ROOT::Fit classes

The fitting of the data objects in ROOT, histograms, graphs and tree is performed via some common classes, which are defined in the ROOT::Fit namespace. These classes can be classified in the following groups:

• User classes driving the fit: ROOT::Fit::Fitter for executing the fit, ROOT::Fit::FitConfig for configuring the fit, ROOT::Fit::ParameterSettings to define the properties of the fit parameters (initial values, bounds, etc..), ROOT::Fit::FitResult for storing the result of the fit.
• Data classes containing the data sets used in the fitting. These classes are theROOT::Fit::BinDatafor describing bin data sets, thus data points containing both coordinates and a corresponding value/weight with optionally an error on the value or the coordinate and the ROOT::Fit::UnBinData for un-binned data sets, which consists only of a vector of coordinate values. The coordinate values can be one-dimensional (i.e. one entry per event) or multi-dimensional (N entries per event).
• Function classes defining the type of fit (the objective function used for fitting):
• ROOT::Fit::Chi2FCN for chi2 (least-square fits),
• ROOT::Fit::PoissonLikelihoodFCN for binned likelihood fits of histograms,
• ROOT::Fit::LogLikelihoodFCN for generic un-binned likelihood fits. These classes are templated on the type of function interface they implement (see later). User convenient typedefs are also provided. They derive from the common generic interface multi-dimensional for function evaluation, ROOT::Math::IBaseFunctionMultiDim.

In addition the fitter classes make uses of the generic interfaces for parametric function evaluations, ROOT::Math::IParametricFunctionMultiDim to define the fit model function and use the ROOT::Math::Minimizer interface to perform the minimization of the objective function. More information about the function interface and the multi-dimensional minimization in ROOT is given in the Mathematical Library chapter.

Here we present a detailed description of the ROOT::Fit classes and how to use them. Using these classes instead of the interface provided directly in the ROOT data objects, like TH1::Fit allow are more fine control to configure and customise the fits. For example, using these classes a combined fit of several histograms can be performed.

To understand how these class work, let’s go through a simple example, such as fitting an histogram.

When fitting an histogram, instead of using TH1::Fit we will show in the following hot wo use the ROOT::Fit classes. We will show how to perform the following different type of fits with the histogram data: * a least square fit using the observed errors (Neyman chi-squared); * a least square fit using the expected errors from the function (Pearson chi-squared); * a binned likelihood fit; * an extended unbinned likelihood fits, if the histogram has been set to store in the buffer the original data used to fill it.

Let’s go through all the steps required for performing these fits using the ROOT::Fit::Fitter class. These steps are: 1. Create the input fit data object. 2. Create the input model function. 3. Configure the fit. 4. Perform the data fitting. 5. Examine the result.

### 5.7.1 Creating the input fit data

We have two types of input data, binned data (class ROOT::Fit::BinData) used for least square (chi-square) fits of histograms or TGraph objects or un-binned data (class ROOT::Fit::UnBinData) used for fitting vectors of data points (e.g. from a TTree).

#### 5.7.1.1 Using Binned data

Let’s suppose we have an histogram, represented as a TH1 type object (it can be one or multi-dimensional). The following shows how to create and fill a ROOT:Fit::BinData object.

   ROOT::Fit::DataOptions opt;
opt.fIntegral = true;
ROOT::Fit::BinData data(opt);
// fill the bin data using the histogram
// we can do this using the following helper function from the Hist library
TH1 * h1 = (TH1*) gDirectory->Get("myHistogram");
ROOT::Fit::FillData(data, h1);

In this code example, we have used the utility function of the Hist library, ROOT::Fit::FillData to fill the BinData object. The ROOT::Fit::FillData is defined in the headerfile HFitInterface.h and it has a signature for all different ROOT objects, like TH1, THnBase, TGraph, TGraph2D and TMultiGraph It is possible to specify, when creating the BinData object, the data range we want to use and some fitting options we want to apply to fill in the object and later when fitting. The fit data options are controlled by the ROOT::Fit::DataOptions class, the range by the ROOT::Fit::DataRange class.

Here is an example how to specify the input option to use the integral of the function value in the bin instead of using the function value evaluated at the bin center, when doing the fit and to use a range beween the ‘xmin’ and ‘xmax’ values.

   ROOT::Fit::DataOptions opt;
opt.fIntegral = true;
ROOT::Fit::DataRange range(xmin,xmax);
ROOT::Fit::BinData data(opt,range);
// fill the bin data using the histogram
// we can do this using the following helper function from the Hist library
TH1 * h1 = (TH1*) gDirectory->Get("myHistogram");
ROOT::Fit::FillData(data, h1);

The list of possible fit options available is the following:

   ROOT::Fit::DataOptions opt;
opt.fIntegral = true;      // use integral of bin content instead of bin center (default is false).
opt.fBinVolume = true;     // normalize data by the bin volume (default is false).
//  This is for fitting density functions in histograms with variable bin sizes.
opt.fUseRange  =true;      // use the function range when creating the fit data (default is false).
opt.fExpErrors = true;     // use the expected errors estimated from the function values
//  assuming Poisson statistics and not the observed errors (default is false).
opt.fUseEmpty = true;      // use empty bins when fitting (default is false). If fExpErrors
//  is not set an arbitrary error = 1 is assigned to those bins.
opt.fErrors1 = true;       // Set all measured errors to 1 (default is false).
opt.fCoordErrors = false;  // When available coordinate errors are not used in the fit
//  (default is true: the errors are used when they are available,
//  e.g. fitting a TGraphErrors).
opt.fAsymErrors = false;   // When available asymmetric errors are considered in the fit
//  (default is true, the asymmetric errors are used when they are available,
//  e.g. fitting a TGraphAsymmErrors).

The ROOT::Fit::DataRange class supports defining multiple rectangular ranges in each dimension, and supports n-dimension. The function DataRange::AddRange(icoord,xmin,xmax) adds a range in the coordinate icoord with lower value xmin and upper value xmax:

   ROOT::Fit::DataRange range;
range.AddRange(icoordinate, xmin, xmax);

#### 5.7.1.2 Using Un-Binned data

The unbinned data sets are represented with the ROOT::Fit::UnBinData class. For creating un-binned data sets, a ROOT::Fit::UnBinData object, one has two possibilities: 1. Copy the data inside ROOT::Fit::UnBinData. One can create an empty UnBinData object, iterate on the data and add the data point one by one, or directly create the UnBinData object from a data iterator. In this case an input ROOT::Fit::DataRange object is passed in order to copy the data according to the given range. 2. Use ROOT::Fit::UnBinData as a wrapper to an external data storage. In this case the UnBinData object is created from an iterator or pointers to the data and the data are not copied inside. In this case the data cannot be selected according to a specified range. All the data points will be included in the fit.

The ROOT::Fit::UnBinData class supports also weighted data. In addition to the data points (coordinates), which can be of arbitrary k dimensions, the class can be constructed from a vector of weights. This is an example of taking data from an histogram buffer of a TH1 object:

    double * buffer = histogram->GetBuffer();
// number of entry is first entry in the buffer
int n = buffer[0];
// when creating the data object it is important to create with the size of the data
ROOT::Fit::UnBinData data(n);
for (int i = 0; i < n; ++i)
data.add(buffer[2*i+1]);  // the buffer of 1D histogram contains nevt,x1,w1,x2,w2,......

Instead in this example we will create a 2-dim UnBinData object with the contents from a ROOT TTree

    TFile * file = TFile::Open("hsimple.root");
TTree *ntuple = 0; file->GetObject("ntuple",ntuple);
// select from the tree the data we want to use for fitting
// we use TTree::Draw  for this
int nevt = ntuple->Draw("px:py","","goff");
double * x = ntuple->GetV1();
double * y = ntuple->GetV2();
ROOT::Fit::UnBinData data(nevt, x, y );

### 5.7.2 Creating the Fit model

In order to fit a data sets we need a model to describe our data, e.g. a probability density function describing our observed data or an hypothetical function describing the relation between the independent variables X and the single dependent variable Y. We can have an arbitrary number k of independent variables. For example, when fitting a k-dimensional histogram, the independent variables X are the bin center coordinates and Y is the bin weight.

The model function needs to be expressed as function of some unknown parameters. The fitting will find the best parameter value to describe the observed data.

We can use the ROOT TF1 class, the parametric function class, to describe the model function. However the ROOT::Fit::Fitter class, to be independent of the ROOT Hist library, takes as input a more general parametric function object, the interface (abstract) class ROOT::Math::IParametricFunctionMultiDim, which describe a generic one or multi-dimensional function with parameters. This interface extends the abstract class ROOT::Math::IBaseFunctionMultiDim, with methods to set/retrieve parameter values and to evaluate the function given the independent vector of values X and vector of parameters P. More information about the different ROOT::Math function interfaces is available in the Mathematical Library chapter.

An end-user can convert a TF1 object in a ROOT::Math::IParametricFunctionMultiDim, using the wrapper class ROOT::Math::WrapperMultiTF1:

    TF1 * f1 = new TF1("f1","gaus");
ROOT::Math::WrappedMultiTF1 fitFunction(f1, f1->GetNdim() );
ROOT::Fit::Fitter fitter;
fitter.SetFunction( fitFunction, false);

When creating the wrapper, the parameter values stored in TF1 will be copied in the ROOT::Math::WrappedMultiTF1 object. The function object representing the model function is given to the ROOT::Fitter class using the Fitter::SetFunction method.

The user has also the possibility to provide a function object, which implements the derivatives of the function with respect to the parameters. This information might be useful for some types of fits. In this case he needs to provide the function object as a class deriving from the ROOT::Math::IParametricGradFunctionMultiDim interface. Note that the wrapper class ROOT::Math::WrappedMultiTF1 implements also the gradient interface, using internally TF1::GradientPar, which is based on numerical differentiation, apart for the case of linear functions (i.e. when TF1::IsLinear() is true). The parameter derivatives of the model function can be useful to some minimization algorithms, such as Fumili. However, in general is better to leave the minimization algorithm (e.g. Minuit) to compute the needed derivatives using its own customised numerical differentiation algorithm. In order to not provide to the fitter the parameter derivatives, we explicitly passed in Fitter::SetFunction a false value.

### 5.7.3 Fit Configuration

The configuration of the fit is done via the ROOT::Fit::FitConfig class and its contained ROOT::Fit::ParameterSettings class. These are the possible allowed fit configurations:

• setting the initial values of the parameters;
• setting the parameter step sizes;
• setting eventual parameter bounds;
• setting the minimizer library and the particular algorithm to use;
• setting different minimization options (print level, tolerance, max iterations, etc…)
• setting the type of parameter errors to compute (parabolic error, Minos errors, re-normalize errors using fitted chi2 values)

The initial parameter values can be set directly in the input model function object. However, for setting parameter bounds and step sizes to values different than the automatically computed ones, one needs to use the ROOT::Fit::ParameterSetting class. This example code will set the lower/upper bounds for the first parameter and a lower bound for the second parameter

  fitter.SetFunction( fitFunction, false);
fitter.Config().ParSettings(0).SetLimits(0,1.E6);
fitter.Config().ParSettings(2).SetLowerLimit(0);

Note that a ROOT::Fit::ParameterSettings objects exists for each fit parameter and it created by the ROOT::Fit::FitConfig class, after the model function has been set in the Fitter. Only when the function is set, the number of parameter is known and automatically the FitConfig creates the corresponding ParameterSetting objects.

When fitting, different minimizer can be used. The can be implemented in different libraries and loaded ar run time by the plug-in manager system of ROOT. Each different minimizer (e.g. Minuit, Minuit2, Fumili, etc.) consists of a different implementation of the ROOT::Math::Minimizer interface. Within the same minimizer, thus within the same class implementing the Minimizer interface, different algorithms can exist. For example in the case of Minuit, we have Migrad, Simplex or Minimize. The minimizer and its corresponding algorithm, when available, can be set by using the function FitConfig::SetMinimizer("minimizerName") or by using directly the ROOT:Math::MinimizerOptions class.

If the requested minimizer is not available in ROOT, the default one is used. The default minimizer type and algorithm can be specified by using the static function ROOT::Math::MinimizerOptions::SetDefaultMinimizer("minimizerName")

### 5.7.4 Minimizer Libraries and Algorithms

The list of available minimizer libraries currently available in ROOT, with their corresponding available algorithms is the following one. Some minimizers (e.g. Minuit) contain several algorithms that the user can choose. Others are based on a single algorithm (e.g. Fumili)

• Minuit (library libMinuit). Old version of Minuit, based on the TMinuit class. The list of possible algorithms are:
• Migrad (default one)
• Simplex
• Minimize (it is a combination of Migrad and Simplex)
• MigradImproved
• Scan
• Seek
• Minuit2 (library libMinuit2). New C++ version of Minuit. The list of possible algorithm is :
• Migrad (default)
• Simplex
• Minimize
• Scan
• Fumili . This is the same algorithm of TFumili, but implemented in the Minuit2 library.
• Fumili. Implement a dedicated minimization algorithm for least-square and likelihood fits. It has requirements on the type of method function to be used. No specific algorithm exists

• GSLMultiMin (library libMathMore). Minimizer based on the Multidimensional Minimization routines of the Gnu Scientific Library (GSL). The list of available algorithms is
• BFGS2 (default) : second version of the vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm;
• BFGS : old version of the vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm;
• ConjugateFR : Fletcher-Reeves conjugate gradient algorithm;
• ConjugatePR : Polak-Ribiere conjugate gradient algorithm;
• SteepestDescent: steepest descent algorithm;
• GSLMultiFit (library libMathMore). Minimizer based on the Non-Linear Least-Square routines of GSL. This minimizer can be used only for least-square fits.

• GSLSimAn (library libMathMore). Minimizer based on simulated annealing.

• Genetic (library libGenetic). Genetic minimizer based on an algorithm implemented in the TMVA package.

Each minimizer can be configured using the ROOT::Math::MinimizerOptions class. The list of possible option that can be set are:

• Minimizer type (MinimizerOptions::SetMinimizerType(const char *)) .
• Minimizer algorithm (MinimizerOptions::SetMinimizerAlgorithm(const char *)).
• Print Level (MinimizerOptions::SetPrintLevel(int )) to set the verbose printing level (default is 0).
• Tolerance (MinimizerOptions::SetTolerance(double )) tolerance used to control the iterations.
• Maximum number of function calls (MinimizerOptions::SetMaxFunctionCalls(int )).
• Maximum number of iterations (MinimizerOptions::SetMaxIterations(int )). Note that this is not used by Minuit
• FCN Upper value for Error Definition (MinimizerOptions::SetErrorDef(double )). Value in the minimization function used to compute the parameter errors. The default is to get the uncertainties at the 68% CL is a value of 1 for a chi-squared function minimization and 0.5 for a log-likelihood function.
• Strategy (MinimizerOptions::SetStrategy(int )), minimization strategy used. For each minimization strategy Minuit uses different configuration parameters (e.g. different requirements in computing derivatives, computing full Hessian (strategy = 2) or an approximate version. The default is a value of 1. In this case the full Hessian matrix is computed only after the minimization.
• Precision (MinimizerOptions::SetPrecision(double )). Precision value in the evaluation of the minimization function. Default is numerical double precision.

Note that not all the options are implemented by all the minimizers. For example in Minuit is possible to set the maximum number of function calls, but not the maximum number of iterations. The Strategy and the Precision options apply instead only for Minuit (and Minuit2).

The class supports also setting global default values for the options, by using the static functions MinimizerOptions::SetDefault... (for example MinimizerOptions::SetDefaultPrintLevel(int )). The static functions can be also used to set the minimizer options when using TH1::Fit or TGraph::Fit. The list of the current option values can be inspected by using MinimizerOptions::Print.

ROOT::Math::MinimizerOptions() opt;
// print the default minimizer option values
opt.Print();

In addition it is possible to provide extra options which might apply for a particular minimizer MinimizerOptions::SetExtraOptions(const IOptions & ). See the documentation of the particular minimizer to use for the list of possible additional options available.

### 5.7.5 Performing the Fit

Here we have now all the required input ingredients for the fit, the data and the function to fit. Depending on these we have now several different way to perform the fit, using the corresponding methods of the ROOT::Fit::Fitter class and depending on the type of input data.

#### 5.7.5.1 Available fit methods

• Least-square fit: Fitter::LeastSquare(const BinData & ) or Fitter::Fit(const Bindata &). It requires the user to pass a BinData object. It should be used when the data values follow a Gaussian distribution. This fit method is implemented using the class ROOT::Fit::Chi2FCN.
• Binned Likelihood fit : Fitter::LikelihoodFit(const Bindata & ). The user needs to pass a BinData object. It should be used when the data values follow a Poisson or a multinomial distribution. The Poisson case (extended fit) is the default and in this case the function normalization is also fit to the data. The Multi-nominal case can be selected by passing the optional extended boolean flag as false. This method is implemented by the class ROOT::Fit:::PoissonLikelihoodFCN.
• Un-Binned likelihood fit: Fitter::LikelihoodFit(const UnBindata &). The user needs to pass an UnBinData object. By default the fit is not extended (i.e. the normalization is not fitted to the data). As above the user can select an extended likelihood fit by passing the optional extended boolean flag as true. This method is implemented using the class LogLikelihoodFCN
• Linear Fit: A linear fit can be selected (no iterative minimization is needed in this case, but using linear algebra algorithms from the Matrix library), if the model function is linear in the parameters.

#### 5.7.5.2 Customised Fit methods

Above we described the pre-defined methods used for fitting. A user can also implement its own fitting methods, thus its version of the chi-square or likelihood function he wants to minimize. In this case, the user does not really need to build as input a ROOT::Fit data set and model function as we described before. He can implements its own version of the method function using on its own data set objects and functions.

In this case ROOT::Fit::Fitter::SetFCN is used to set the method function and ROOT::Fit::FitFCN is used for fitting. The method function can be passed also in ROOT::Fit::FitFCN, but in this case a previously defined fitting configuration is used.

The possible type of method functions that are based in ROOT::Fit::Fitter::SetFCN are:

• A generic functor object implementing operator()(const double * p) where p is the parameter vectors. In this case one needs to pass the number of parameters, the function object and optionally a vector of initial parameter values. Other optional parameter include the size of the data sets and a flag specifying if it is a chi2 (least-square fit). In the last two parameters are given, the chi2/ndf can be computed after fitting the data.
template <class Function>
bool Fitter::SetFCN(unsigned int npar, Function & f,
const double * initialParameters = 0,
unsigned int dataSize=0, bool isChi2Fit = false)
• A function object implementing the ROOT::Math::IBaseFunctionMultiDim interface:
bool Fitter::SetFCN(const ROOT::Math::IBaseFunctionMultiDim  & f,
const double * initialParameters = 0,
unsigned int dataSize=0, bool isChi2Fit = false)
• A function object implementing the ROOT::Math::FitMethodFunction interface. This is an interface class extending the ROOT::Math::IBaseFunctionMultiDim with some extra functionality which can be used when fitting. This extra functionality is required by dedicated fitting algorithms like Fumili or GSLMultiFit.
bool Fitter::SetFCN(const ROOT::Math::FitMethodFunction  & f,
const double * initialParameters = 0, unsigned int dataSize=0)
• A old-Minuit like FCN interface (i.e. a free function with the signature fcn(int &npar, double *gin, double &f, double *u, int flag).
typedef void(* MinuitFCN)(int &npar, double *gin, double &f, double *u, int flag)
bool Fitter::SetFCN(MinuitFCN fcn, int npar,
const double * initialParameters = 0,
unsigned int dataSize=0, bool isChi2Fit = false)

### 5.7.6 Fit Result

The result of the fit is contained in the ROOT::Fit::Result object. A reference to the result object is obtained with the function Fitter::Result(). The ROOT::Fit::FitResult class provides an API for retrieving parameter values, errors, covariance and correlation matrix from the fit, minimum chi2/likelihood values, etc…

A FitResult::Print method is also available to print the result of the fit.

The class has a self-explanatory API so, see its reference documentation for the possible information available after the fit.

One extra functionality offered by ROOT::Fit::FitResult is the possibility to compute the confidence intervals of the function after the fit. The function ROOT::Fit::FitResult::GetConfidenceInterval given an input data sets (e.g. a BinData object) and a confidence level value (e.g. 68%) computes the lower/upper band values of the model function at the given data points.

### 5.7.7 TFitResult

TFitResult is a class deriving from ROOT::Fit::Result and providing in addition some convenient methods to return a covariance or correlation matrix as a TMatrixDSym object. In addition TFitResult derives from TNamed and can be conveniently stored in a file.

When fitting an histogram ( a TH1 object) or a graph (a TGraph object) it is possible to return a TFitResult via the TFitResultPtr object, which behaves as a smart pointer to a TFitResult. TFitResultPtr is the return object by TH1::Fit or TGraph::Fit. By default the TFitResultPtr contains only the status of the fit and can be obtained by an automatic conversion of the TFitResultPtr to an integer.

If the fit option S is instead used, TFitResultPtr contains the TFitResult and behaves as a smart pointer to it. This is an example:

int fitStatus =  hist->Fit(myFunction);   // TFitResultPtr contains only the fit status

TFitResultPtr r = hist->Fit(myFunction,"S");  // TFitResultPtr contains the TFitResult
TMatrixDSym cov = r->GetCovarianceMatrix();   //  to access the covariance matrix
Double_t chi2   = r->Chi2();                  // to retrieve the fit chi2
Double_t par0   = r->Parameter(0);            // retrieve the value for the parameter 0
Double_t err0   = r->ParError(0);             // retrieve the error for the parameter 0
r->Print("V");                                // print full information of fit including covariance matrix
r->Write();                                   // store the result in a file

## 5.8 The Minimization packages

As explained before various minimization packages can be used when fitting in ROOT. We have seen before how to configure the Fitter class to use different minimization packages and different minimization options. When using the Fit method the minimization package (and its options) can be selected using the static methods of the ROOT::Math::MinimizerOptions class. For example to select Minuit2 instead of Minuit for fitting an histogram do:

ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2");
// fit the histogram histo with the gaussian pre-defined function
histo->Fit("gaus");

In the following we will give some brief description of the minimization packages. The packages all implement the ROOT::Math::Minimizer interface which can be use for finding the minimum of a multi-dimensional function. The interface is documented in the Mathematical Library Chapter.

In addition packages like Minuit or Minuit2 provide their own interfaces.

## 5.9 MINUIT (Old TMInuit Version)

This package was originally written in FORTRAN by Fred James and part of PACKLIB (patch D506). It has been converted to a C++ class by René Brun. The current implementation in C++ is a straightforward conversion of the original FORTRAN version. The main changes are:

• The variables in the various Minuit labeled common blocks have been changed to the TMinuit class data members

• The internal arrays with a maximum dimension depending on the maximum number of parameters are now data members’ arrays with a dynamic dimension such that one can fit very large problems by simply initializing the TMinuit constructor with the maximum number of parameters

• The include file Minuit.h has been commented as much as possible using existing comments in the code or the printed documentation

• The original Minuit subroutines are now member functions

• Constructors and destructor have been added

• Instead of passing the FCN function in the argument list, the addresses of this function is stored as pointer in the data members of the class. This is by far more elegant and flexible in an interactive environment. The member function SetFCN can be used to define this pointer

• The ROOT static function Printf is provided to replace all format statements and to print on currently defined output file

• The functions SetObjectFit/GetObjectFit can be used inside the FCN function to set/get a referenced object instead of using global variables

• By default fGraphicsMode is true. When calling the Minuit functions such as mncont, mnscan, or any Minuit command invoking mnplot, TMinuit::mnplot() produces a TGraph object pointed by fPlot. One can retrieve this object with TMinuit::GetPlot(). For example:

   h->Fit("gaus");
gMinuit->Command("SCAn 1");
TGraph *gr = (TGraph*)gMinuit->GetPlot();
gr->SetMarkerStyle(21);
gr->Draw("alp");
• To set Minuit in no graphics mode, call
   gMinuit->SetGraphicsMode(kFALSE);

### 5.9.1 Basic Concepts of Minuit

The Minuit package acts on a multi parameter FORTRAN function to which one must give the generic name FCN. In the ROOT implementation, the function FCN is defined via the Minuit SetFCN member function when an histogram fitting is invoked. The value of FCN will in general depend on one or more variable parameters.

### 5.9.2 The Transformation of Limited Parameters

For variable parameters with limits, Minuit uses the following transformation:

Pint = arcsin(2((Pext-a)/(b-a))-1)

Pext = a+((b-a)/(2))(sinPint+1)

so that the internal value Pint can take on any value, while the external value Pext can take on values only between the lower limit a and the ext upper limit b. Since the transformation is necessarily non-linear, it would transform a nice linear problem into a nasty non-linear one, which is the reason why limits should be avoided if not necessary. In addition, the transformation does require some computer time, so it slows down the computation a little bit, and more importantly, it introduces additional numerical inaccuracy into the problem in addition to what is introduced in the numerical calculation of the FCN value. The effects of non-linearity and numerical round off both become more important as the external value gets closer to one of the limits (expressed as the distance to nearest limit divided by distance between limits). The user must therefore be aware of the fact that, for example, if they put limits of (0, 1010) on a parameter, then the values 0.0 and 1. 0 will be indistinguishable to the accuracy of most machines.

The transformation also affects the parameter error matrix, of course, so Minuit does a transformation of the error matrix (and the ‘’parabolic’’ parameter errors) when there are parameter limits. Users should however realize that the transformation is only a linear approximation, and that it cannot give a meaningful result if one or more parameters is very close to a limit, where $$\frac{\partial Pext}{\partial Pint} \neq 0$$. Therefore, it is recommended that:

• Limits on variable parameters should be used only when needed in order to prevent the parameter from taking on unphysical values

• When a satisfactory minimum has been found using limits, the limits should then be removed if possible, in order to perform or re-perform the error analysis without limits

### 5.9.3 How to Get the Right Answer from Minuit

Minuit offers the user a choice of several minimization algorithms. The MIGRAD algorithm is in general the best minimized for nearly all functions. It is a variable-metric method with inexact line search, a stable metric updating scheme, and checks for positive-definiteness. Its main weakness is that it depends heavily on knowledge of the first derivatives, and fails miserably if they are very inaccurate.

If parameter limits are needed, in spite of the side effects, then the user should be aware of the following techniques to alleviate problems caused by limits:

#### 5.9.3.1 Getting the Right Minimum with Limits

If MIGRAD converges normally to a point where no parameter is near one of its limits, then the existence of limits has probably not prevented Minuit from finding the right minimum. On the other hand, if one or more parameters is near its limit at the minimum, this may be because the true minimum is indeed at a limit, or it may be because the minimized has become ‘’blocked’’ at a limit. This may normally happen only if the parameter is so close to a limit (internal value at an odd multiple of $$\pm \frac{\pi}{2}$$ that Minuit prints a warning to this effect when it prints the parameter values. The minimized can become blocked at a limit, because at a limit the derivative seen by the minimized $$\frac{\partial F}{\partial Pint}$$ is zero no matter what the real derivative $$\frac{\partial F}{\partial Pext}$$ is.

$\left(\frac{\partial F}{\partial Pint}\right) = \left(\frac{\partial F}{\partial Pext}\right) \left(\frac{\partial Pext}{\partial Pint}\right) = \left(\frac{\partial F}{\partial Pext}\right) = 0$

#### 5.9.3.2 Getting the Right Parameter Errors with Limits

In the best case, where the minimum is far from any limits, Minuit will correctly transform the error matrix, and the parameter errors it reports should be accurate and very close to those you would have got without limits. In other cases (which should be more common, since otherwise you would not need limits), the very meaning of parameter errors becomes problematic. Mathematically, since the limit is an absolute constraint on the parameter, a parameter at its limit has no error, at least in one direction. The error matrix, which can assign only symmetric errors, then becomes essentially meaningless.

#### 5.9.3.3 Interpretation of Parameter Errors

There are two kinds of problems that can arise: the reliability of Minuit’s error estimates, and their statistical interpretation, assuming they are accurate.

#### 5.9.3.4 Statistical Interpretation

For discussion of basic concepts, such as the meaning of the elements of the error matrix, or setting of exact confidence levels see the articles:

• F.James. Determining the statistical Significance of experimental Results. Technical Report DD/81/02 and CERN Report 81-03, CERN, 1981

• W.T.Eadie, D.Drijard, F.James, M.Roos, and B.Sadoulet. Statistical Methods in Experimental Physics. North-Holland, 1971

### 5.9.4 Reliability of Minuit Error Estimates

Minuit always carries around its own current estimates of the parameter errors, which it will print out on request, no matter how accurate they are at any given point in the execution. For example, at initialization, these estimates are just the starting step sizes as specified by the user. After a HESSE step, the errors are usually quite accurate, unless there has been a problem. Minuit, when it prints out error values, also gives some indication of how reliable it thinks they are. For example, those marked CURRENT GUESS ERROR are only working values not to be believed, and APPROXIMATE ERROR means that they have been calculated but there is reason to believe that they may not be accurate.

If no mitigating adjective is given, then at least Minuit believes the errors are accurate, although there is always a small chance that Minuit has been fooled. Some visible signs that Minuit may have been fooled:

• Warning messages produced during the minimization or error analysis

• Failure to find new minimum

• Value of EDM too big (estimated Distance to Minimum)

• Correlation coefficients exactly equal to zero, unless some parameters are known to be uncorrelated with the others

• Correlation coefficients very close to one (greater than 0.99). This indicates both an exceptionally difficult problem, and one which has been badly parameterized so that individual errors are not very meaningful because they are so highly correlated

• Parameter at limit. This condition, signaled by a Minuit warning message, may make both the function minimum and parameter errors unreliable. See the discussion above ‘Getting the right parameter errors with limits’

The best way to be absolutely sure of the errors is to use ‘’independent’’ calculations and compare them, or compare the calculated errors with a picture of the function. Theoretically, the covariance matrix for a ‘’physical’’ function must be positive-definite at the minimum, although it may not be so for all points far away from the minimum, even for a well-determined physical problem. Therefore, if MIGRAD reports that it has found a non-positive-definite covariance matrix, this may be a sign of one or more of the following:

#### 5.9.4.1 A Non-physical Region

On its way to the minimum, MIGRAD may have traversed a region that has unphysical behavior, which is of course not a serious problem as long as it recovers and leaves such a region.

#### 5.9.4.2 An Underdetermined Problem

If the matrix is not positive-definite even at the minimum, this may mean that the solution is not well defined, for example that there are more unknowns than there are data points, or that the parameterization of the fit contains a linear dependence. If this is the case, then Minuit (or any other program) cannot solve your problem uniquely. The error matrix will necessarily be largely meaningless, so the user must remove the under determinedness by reformulating the parameterization. Minuit cannot do this itself.

#### 5.9.4.3 Numerical Inaccuracies

It is possible that the apparent lack of positive-definiteness is due to excessive round off errors in numerical calculations (in the user function), or not enough precision. This is unlikely in general, but becomes more likely if the number of free parameters is very large, or if the parameters are badly scaled (not all of the same order of magnitude), and correlations are large. In any case, whether the non-positive-definiteness is real or only numerical is largely irrelevant, since in both cases the error matrix will be unreliable and the minimum suspicious.

#### 5.9.4.4 An Ill-posed Problem

For questions of parameter dependence, see the discussion above on positive-definiteness. Possible other mathematical problems are the following:

• Excessive numerical round off - be especially careful of exponential and factorial functions which get big very quickly and lose accuracy.

• Starting too far from the solution - the function may have unphysical local minima, especially at infinity in some variables.

## 5.10 Minuit2 Package

Minuit2 is a new object-oriented implementation, written in C++, of the popular MINUIT minimization package. Compared with the TMinuit class, which is a direct conversion from FORTRAN to C++, Minuit2 is a complete redesign and re-implementation of the package. This new version provides all the functionality present in the old FORTRAN version, with almost equivalent numerical accuracy and computational performances. Furthermore, it contains some fixes and small improvements and this new functionality: * The possibility to set single side parameter limits * the FUMILI algorithm (see the next paragraph “FUMILI Minimization Package”), which is an optimized method for least square and log likelihood minimizations.

Minuit2 has been originally developed by M. Winkler and F. James in the SEAL project. More information can be found on the MINUIT Web Site and in particular at the following documentation page at http://www.cern.ch/minuit/doc/doc.html.

A detailed User Guide for Minuit2 exists, describing the API of the internal classes. ROOT uses Minuit2 for fitting via the Minuit2Minimizer class which implements the ROOT::Math::Minimizer interface.

Minuit2 is also distributed as an independent package of ROOT and can be built without any other dependency on the ROOT libraries.

Examples on how to use the Minuit2 and Fumili2 plug-ins are provided in the tutorials’ directory $ROOTSYS/tutorials/fit: minuit2FitBench.C, minuit2FitBench2D.C and minuit2GausFit.C. More information on the classes and functions present in Minuit2 is available at online reference documentation. Useful information on MINUIT and minimization in general is provided in the following documents: F. James, Minuit Tutorial on Function Minimization ( http://seal.cern.ch/documents/minuit/mntutorial.pdf); F. James, The Interpretation of Errors in Minuit ( http://seal.cern.ch/documents/minuit/mnerror.pdf); ## 5.11 FUMILI Minimization Package FUMILI is used to minimize Chi-square function or to search maximum of likelihood function. Experimentally measured values $$F_{i}$$ are fitted with theoretical functions $$f_{i}(\vec{x_{i}},\vec{\theta})$$, where $$\vec{x_{i}}$$ are coordinates, and $$\vec{\theta}$$ - vector of parameters. For better convergence Chi-square function has to be the following form $\frac{\chi^2}{2} = \frac{1}{2} \sum_{i=1}^{n} \left(\frac{f_{i}(\vec{x_{i}},\vec{\theta}) - F_{i}} {\sigma_{i}}\right)^{2}$ where $$\sigma_{i}$$ are errors of the measured function. The minimum condition is: $\frac{\partial \chi^{2}}{\partial \theta_{i}} = \sum_{j=1}^{n} \frac{1}{\sigma_{j}^{2}} . \frac{\partial f_{i}}{\partial \theta_{i}} \left[ (\vec{x_{j}},\vec{\theta}) - F_{j}\right] = 0, i = 1 ... m$ where $$m$$ is the quantity of parameters. Expanding left part of this equation over parameter increments and retaining only linear terms one gets $\left(\frac{\partial \chi^{2}}{\theta_{i}}\right) _{\theta = \vec{\theta}^{0}} + \sum_{k} \left(\frac{\partial^{2} \chi^{2}}{\partial \theta_{i} \partial \theta_{k}}\right) _{\theta = \vec{\theta}^{0}} . (\theta_{k} - \theta_{k}^{0}) = 0$ here $$\vec{\theta}^{0}$$ is some initial value of parameters. In general case: ${\frac{\partial^2\chi^2}{\partial\theta_i\partial\theta_k}}= \sum^n_{j=1}{\frac{1}{\sigma^2_j}} {\frac{\partial f_j}{\theta_i}} {\frac{\partial f_j}{\theta_k}} + \sum^n_{j=1}{\frac{(f_j - F_j)}{\sigma^2_j}}\cdot {\frac{\partial^2f_j}{\partial\theta_i\partial\theta_k}}$ In FUMILI algorithm for second derivatives of Chi-square approximate expression is used when last term in previous equation is discarded. It is often done, not always wittingly, and sometimes causes troubles, for example, if user wants to limit parameters with positive values by writing down $$\theta_i^2$$ instead of $$\theta_i$$. FUMILI will fail if one tries minimize $$\chi^2 = g^2(\vec\theta)$$ where g is arbitrary function. Approximate value is: ${\frac{\partial^2\chi^2}{\partial\theta_i\partial\theta_k}}\approx Z_{ik}= \sum^n_{j=1}{\frac{1}{\sigma^2_j}}{\frac{\partial f_j}{\theta_i}} {\frac{\partial f_j}{\theta_k}}$ Then the equations for parameter increments are: $\left(\frac{\partial\chi^2}{\partial\theta_i}\right)_ {\vec\theta={\vec\theta}^0} +\sum_k Z_{ik}\cdot(\theta_k-\theta^0_k) = 0, \qquad i=1\ldots m$ Remarkable feature of algorithm is the technique for step restriction. For an initial value of parameter $${\vec\theta}^0$$ a parallelepiped $$P_0$$ is built with the center at $${\vec\theta}^0$$ and axes parallel to coordinate axes $$\theta_i$$. The lengths of parallelepiped sides along i-th axis is $$2b_i$$, where $$b_i$$ is such a value that the functions $$f_j(\vec\theta)$$ are quasi-linear all over the parallelepiped. FUMILI takes into account simple linear inequalities in the form: $\theta_i^{min}\le\theta_i\le\theta^{max}_i$ They form parallelepiped $$P$$ ($$P_0$$ may be deformed by $$P$$). Very similar step formulae are used in FUMILI for negative logarithm of the likelihood function with the same idea - linearization of function argument. ## 5.12 Neural Networks ### 5.12.1 Introduction Neural Networks are used in various fields for data analysis and classification, both for research and commercial institutions. Some randomly chosen examples are image analysis, financial movements’ predictions and analysis, or sales forecast and product shipping optimization. In particles physics neural networks are mainly used for classification tasks (signal over background discrimination). A vast majority of commonly used neural networks are multilayer perceptrons. This implementation of multilayer perceptrons is inspired from the MLPfit package, which remains one of the fastest tools for neural networks studies. ### 5.12.2 The MLP The multilayer perceptron is a simple feed-forward network with the following structure showed on the left. It is made of neurons characterized by a bias and weighted links in between - let’s call those links synapses. The input neurons receive the inputs, normalize them and forward them to the first hidden layer. Each neuron in any subsequent layer first computes a linear combination of the outputs of the previous layer. The output of the neuron is then function of that combination with f being linear for output neurons or a sigmoid for hidden layers. Such a structure is very useful because of two theorems: 1- A linear combination of sigmoids can approximate any continuous function. 2- Trained with output=1 for the signal and 0 for the background, the approximated function of inputs X is the probability of signal, knowing X. ### 5.12.3 Learning Methods The aim of all learning methods is to minimize the total error on a set of weighted examples. The error is defined as the sum in quadrate, divided by two, of the error on each individual output neuron. In all methods implemented in this library, one needs to compute the first derivative of that error with respect to the weights. Exploiting the well-known properties of the derivative, one can express this derivative as the product of the local partial derivative by the weighted sum of the outputs derivatives (for a neuron) or as the product of the input value with the local partial derivative of the output neuron (for a synapse). This computation is called “back-propagation of the errors”. Six learning methods are implemented. #### 5.12.3.1 Stochastic Minimization This is the most trivial learning method. The Robbins-Monro stochastic approximation is applied to multilayer perceptrons. The weights are updated after each example according to the formula: $w_{ij}(t+1) = w_{ij}(t) + \Delta w_{ij}(t)$ with: $\Delta w_{ij}(t) = - \eta \left( \frac{\partial e_p}{\partial w_{ij}} + \delta \right) + \epsilon \Delta w_{ij}(t-1)$ The parameters for this method are Eta, EtaDecay, Delta and Epsilon. #### 5.12.3.2 Steepest Descent With Fixed Step Size (Batch Learning) It is the same as the stochastic minimization, but the weights are updated after considering all the examples, with the total derivative dEdw. The parameters for this method are Eta, EtaDecay, Delta and Epsilon. #### 5.12.3.3 Steepest Descent Algorithm Weights are set to the minimum along the line defined by the gradient. The only parameter for this method is Tau. Lower Tau = higher precision = slower search. A value Tau=3 seems reasonable. #### 5.12.3.4 Conjugate Gradients With the Polak-Ribiere Updating Formula Weights are set to the minimum along the line defined by the conjugate gradient. Parameters are Tau and Reset, which defines the epochs where the direction is reset to the steepest descent (estimated by using the Polak-Ribiere formula). #### 5.12.3.5 Conjugate Gradients With the Fletcher-Reeves Updating Formula Weights are set to the minimum along the line defined by the conjugate gradient. Parameters are Tau and Reset, which defines the epochs where the direction is reset to the steepest descent (estimated by using the Fletcher-Reeves formula). #### 5.12.3.6 The Broyden, Fletcher, Goldfarb, Shanno (BFGS) Method It implies the computation of a NxN matrix, but seems more powerful at least for less than 300 weights. Parameters are Tau and Reset, which defines the epochs where the direction is reset to the steepest descent. ### 5.12.4 Using the Network Neural network are build from a set of “samples”. A sample is a set of values defining the inputs and the corresponding output that the network should ideally provide. In ROOT this is a TTree entry. The first thing to be decided is the network layout. This layout is described in a string where the layers are separated by semicolons. The input/output layers are defined by giving the expression for each neuron, separated by comas. Hidden layers are just described by the number of neurons. In addition, input and output layer formulas can be preceded by ‘@’ (e.g. “@out”) if one wants to normalize the corresponding value. Also, if the string ends with ‘!’, output neurons are set up for classification, i.e. with a sigmoid (1 neuron) or softmax (more neurons) activation function. Many questions on the good usage of neural network, including rules of dumb to determine the best network topology are addressed at ftp://ftp.sas.com/pub/neural/FAQ.html  // a simple network: 2 inputs, 10 hidden and 1 normalized // output neuron TMultiLayerPerceptron network("r,z:10:@Br",tree); Expressions are evaluated as for TTree::Draw(). Input and outputs are taken from the TTree associated with the network. This TTree can be given as argument of the constructor or defined later with TMultiLayerPerceptron::SetData(). Events can also be weighted. The weight expression can be given in the constructor or set later with the method SetWeight() of the class TMultiLayerPerceptron. Two datasets must be defined before learning the network: a training dataset that is used when minimizing the error, and a test dataset that will avoid bias. Those two datasets can be built aside and then given to the network, or can be built from a standard expression. By default, half of the events are put in both datasets.  // a more complex 4:8:1 network // the ptsumf branch is used as weigh; // default event lists are explicit TMultiLayerPerceptron network("m,pt,acol,acopl:8:type","pt",tree, "Entry$%2","Entry$/2"); The method TMultiLayerPerceptron::SetLearningMethod() defines the learning method. Learning methods are: TMultiLayerPerceptron::kStochastic, TMultiLayerPerceptron::kBatch, TMultiLayerPerceptron::kSteepestDescent, TMultiLayerPerceptron::kRibierePolak, TMultiLayerPerceptron::kFletcherReeves, TMultiLayerPerceptron::kBFGS // default The training can start with TMultiLayerPerceptron::Train(Int_t nepoch,Option_t* options). The first argument is the number of epochs while option is a string that can contain “text” (simple text output), “graph” (evaluating graphical training curves), “update = X” (step for the text/graph output update) or “+” (will skip the randomization and start from the previous values). All combinations are available.  network.Train(1000,"text,graph,update=10"); // full output every // 10 epochs network.Train(100,"text,+"); // 100 more epochs //starts with existing weights The weights can be saved to a file (DumpWeights) and then reloaded (LoadWeights) to a new compatible network. The output can also be evaluated (Evaluate) for a given output neuron and an array of double input parameters or the network can be exported (Export) as a standalone code. Up to now, this is only as a C++ or PYTHON class, but other languages could be implemented. ### 5.12.5 Examples An example of how to use TMultiLayerPerceptron is the macro mlpHiggs.C in$ROOTSYS/tutorials. Using some standard simulated information that could have been obtained at LEP, a neural network is build, which can make the difference between WW events and events containing a Higgs boson. Starting with a TFile containing two TTrees: one for the signal, the other for the background, a simple script is used:

   void mlpHiggs(Int_t ntrain=100) {
if (!gROOT->GetClass("TMultiLayerPerceptron"))
// prepare inputs - the 2 trees are merged into one, and a
// "type" branch, equal to 1 for the signal and 0 for the
TFile input("mlpHiggs.root");
TTree *signal = (TTree *)input.Get("sig_filtered");
TTree *background = (TTree *)input.Get("bg_filtered");
TTree *simu = new TTree("MonteCarlo",
"Filtered Monte Carlo Events");
...

Since the input is a TTree and we are starting from two different TTrees (with different names), they are first merged into one, and a “type” branch is added, that says whether there is a signal or a background event. Those irrelevant details are skipped here.

      ...
TMultiLayerPerceptron *mlp = new TMultiLayerPerceptron(
"msumf,ptsumf, acolin, acopl:8:type","ptsumf",simu,
"Entry$%2","Entry$/2");
mlp->Train(ntrain, "text,graph,update=10");

The neural network is instantiated and trained. “ptsumf” is used as a weight, and the standard event lists are explicit. The network that is then build has four input neurons, eight additional ones in the only hidden layer and one single output neuron.

      // Use the NN to plot the results for each sample
TH1F *bg = new TH1F("bgh","NN output",50,-.5,1.5);
TH1F *sig = new TH1F("sigh","NN output",50,-.5,1.5);
bg->SetDirectory(0);
sig->SetDirectory(0);
Double_t params[4];
for (i = 0; i < background->GetEntries(); i++) {
background->GetEntry(i);
params[0] = msumf;    params[1] = ptsumf;
params[2] = acolin;   params[3] = acopl;
bg->Fill(mlp->Evaluate(0,params));
}
for (i = 0; i < signal->GetEntries(); i++) {
signal->GetEntry(i);
params[0] = msumf;
params[1] = ptsumf;
params[2] = acolin;
params[3] = acopl;
sig->Fill(mlp->Evaluate(0,params));
}
TCanvas *cv = new TCanvas("NNout_cv","Neural net output");
bg->SetFillStyle(3008);
bg->SetFillColor(kBlue);
sig->SetFillStyle(3003);
sig->SetFillColor(kRed);
bg->SetStats(0);
sig->SetStats(0);
bg->Draw();
sig->Draw("same");
TLegend *legend = new TLegend(.75,.80,.95,.95);
legend->Draw();

The neural net output is then used to display the final difference between background and signal events. The figure “The neural net output” shows this plot.

As it can be seen, this is a quite efficient technique. As mentioned earlier, neural networks are also used for fitting function. For some application with a cylindrical symmetry, a magnetic field simulation gives as output the angular component of the potential vector A, as well as the radial and z components of the B field.

One wants to fit those distributions with a function in order to plug them into the Geant simulation code. Polynomial fits could be tried, but it seems difficult to reach the desired precision over the full range. One could also use a spline interpolation between known points. In all cases, the resulting field would not be C-infinite.

An example of output (for Br) is shown. First the initial function can be seen as the target. Then, the resulting (normalized) neural net output. In order to ease the learning, the “normalize output” was used here. The initial amplitude can be recovered by multiplying by the original RMS and then shifting by the original mean.

# 6 A Little C++

This chapter introduces you to some useful insights into C++, to allow you to use some of the most advanced features in ROOT. It is in no case a full course in C++.

## 6.1 Classes, Methods and Constructors

C++ extends C with the notion of a class. If you’re used to structures in C, a class is a struct that is a group of related variables, which is extended with functions and routines specific to this structure (class). What is the interest? Consider a struct that is defined this way:

   struct Line {
float x1;
float y1;
float x2;
float y2;
}

This structure represents a line to be drawn in a graphical window. (x1,y1) are the coordinates of the first point, (x2,y2) the coordinates of the second point. In the standard C, if you want to draw effectively such a line, you first have to define a structure and initialize the points (you can try this):

   Line firstline;
firstline.x1 = 0.2;
firstline.y1 = 0.2;
firstline.x2 = 0.8;
firstline.y2 = 0.9;

This defines a line going from the point (0.2,0.2) to the point (0.8,0.9). To draw this line, you will have to write a function, say LineDraw(Line l) and call it with your object as argument:

   LineDraw(firstline);

In C++, we would not do that. We would instead define a class like this:

   class TLine {
Double_t x1;
Double_t y1;
Double_t x2;
Double_t y2;
TLine(int x1, int y1, int x2, int y2);
void Draw();
}

Here we added two functions, that we will call methods or member functions, to the TLine class. The first method is used for initializing the line objects we would build. It is called a constructor. The second one is the Draw method itself. Therefore, to build and draw a line, we have to do:

   TLine l(0.2,0.2,0.8,0.9);
l.Draw();

The first line builds the object l by calling its constructor. The second line calls the TLine::Draw() method of this object. You don’t need to pass any parameters to this method since it applies to the object l, which knows the coordinates of the line. These are internal variables x1, y1, x2, y2 that were initialized by the constructor.

## 6.2 Inheritance and Data Encapsulation

We have defined a TLine class that contains everything necessary to draw a line. If we want to draw an arrow, is it so different from drawing a line? We just have to draw a triangle at one end. It would be very inefficient to define the class TArrow from scratch. Fortunately, inheritance allows a class to be defined from an existing class. We would write something like:

   class TArrow : public TLine {
void Draw();
void SetArrowSize(int arrowsize);
}

The keyword “public” will be explained later. The class TArrow now contains everything that the class TLine does, and a couple of more things, the size of the arrowhead and a function that can change it. The Draw method of TArrow will draw the head and call the draw method of TLine. We just have to write the code for drawing the head!

### 6.2.1 Method Overriding

Giving the same name to a method (remember: method = member function of a class) in the child class (TArrow) as in the parent (TLine) does not give any problem. This is called overriding a method. Draw in TArrow overrides Draw in TLine. There is no possible ambiguity since, when one calls the Draw() method; this applies to an object whose type is known. Suppose we have an object l of type TLine and an object a of type TArrow. When you want to draw the line, you do:

   l.Draw();

Draw() from TLine is called. If you do:

   a.Draw();

Draw() from TArrow is called and the arrow a is drawn.

### 6.2.2 Data Encapsulation

We have seen previously the keyword “public”. This keyword means that every name declared public is seen by the outside world. This is opposed to “private” that means only the class where the name was declared private could see this name. For example, suppose we declare in TArrow the variable ArrowHeadSize private.

   private:
int ArrowHeadSize;

Then, only the methods (i.e. member functions) of TArrow will be able to access this variable. Nobody else will see it. Even the classes that we could derive from TArrow will not see it. On the other hand, if we declare the method Draw() as public, everybody will be able to see it and use it. You see that the character public or private does not depend of the type of argument. It can be a data member, a member function, or even a class. For example, in the case of TArrow, the base class TLine is declared as public:

   class TArrow : public TLine { ...

This means that all methods of TArrow will be able to access all methods of TLine, but this will be also true for anybody in the outside world. Of course, this is true if TLine accepts the outside world to see its methods/data members. If something is declared private in TLine, nobody will see it, not even TArrow members, even if TLine is declared as a public base class.

What if TLine is declared “private” instead of “public” ? Well, it will behave as any other name declared private in TArrow: only the data members and methods of TArrow will be able to access TLine, its methods and data members, nobody else. This may seem a little bit confusing and readers should read a good C++ book if they want more details. Especially since, besides public and private, a member can be protected. Usually, one puts private the methods that the class uses internally, like some utilities classes, and that the programmer does not want to be seen in the outside world.

With “good” C++ practice (which we have tried to use in ROOT), all data members of a class are private. This is called data encapsulation and is one of the strongest advantages of Object Oriented Programming (OOP). Private data members of a class are not visible, except to the class itself. So, from the outside world, if one wants to access those data members, one should use so called “getters” and “setters” methods, which are special methods used only to get or set the data members. The advantage is that if the programmers want to modify the inner workings of their classes, they can do so without changing what the user sees. The user does not even have to know that something has changed (for the better, hopefully). For example, in our TArrow class, we would have set the data member ArrowHeadSize private. The setter method is SetArrowSize(), we do not need a getter method:

   class TArrow : public TLine {
private:
public:
void Draw();
void SetArrowSize(int arrowsize);
}

To define an arrow object you call the constructor. This will also call the constructor of TLine, which is the parent class of TArrow, automatically. Then we can call any of the line or arrow public methods:

root[] TArrow *myarrow = new TArrow(1,5,89,124);
root[] myarrow->SetArrowSize(10);
root[] myarrow->Draw();

To explain how objects are created on the stack and on the heap we will use the Quad class. You can find the definition in $ROOTSYS/tutorials/quadp/Quad.h and Quad.cxx. The Quad class has four methods. The constructor and destructor, Evaluate that evaluates ax**2 + bx +c, and Solve which solves the quadratic equation ax**2 + bx +c = 0. Quad.h :  class Quad { public: Quad(Float_t a, Float_t b, Float_t c); ~Quad(); Float_t Evaluate(Float_t x) const; void Solve() const; private: Float_t fA; Float_t fB; Float_t fC; }; Quad.cxx:  #include <iostream.h> #include <math.h> #include "Quad.h" Quad::Quad(Float_t a, Float_t b, Float_t c) { fA = a; fB = b; fC = c; } Quad::~Quad() { Cout <<"deleting object with coeffts: "<< fA << "," << fB << "," << fC << endl; } Float_t Quad::Evaluate(Float_t x) const { return fA*x*x + fB*x + fC; } void Quad::Solve() const { Float_t temp = fB*fB - 4.*fA*fC; if ( temp > 0. ) { temp = sqrt( temp ); cout << "There are two roots: " << ( -fB - temp ) / (2.*fA) << " and " << ( -fB + temp ) / (2.*fA) << endl; } else { if ( temp == 0. ) { cout << "There are two equal roots: " << -fB / (2.*fA) << endl; } else { cout << "There are no roots" << endl; } } } Let us first look how we create an object. When we create an object by: root[] Quad my_object(1.,2.,-3.); We are creating an object on the stack. A FORTRAN programmer may be familiar with the idea; it is not unlike a local variable in a function or subroutine. Although there are still a few old timers who do not know it, FORTRAN is under no obligation to save local variables once the function or subroutine returns unless the SAVE statement is used. If not then it is likely that FORTRAN will place them on the stack and they will “pop off” when the RETURN statement is reached. To give an object more permanence it has to be placed on the heap. root[] .L Quad.cxx root[] Quad *my_objptr = new Quad(1.,2.,-3.); The second line declares a pointer to Quad called my_objptr. From the syntax point of view, this is just like all the other declarations we have seen so far, i.e. this is a stack variable. The value of the pointer is set equal to new Quad(1.,2.,-3.); new, despite its looks, is an operator and creates an object or variable of the type that comes next, Quad in this case, on the heap. Just as with stack objects it has to be initialized by calling its constructor. The syntax requires that the argument list follows the type. This one statement has brought two items into existence, one on the heap and one on the stack. The heap object will live until the delete operator is applied to it. There is no FORTRAN parallel to a heap object; variables either come or go as control passes in and out of a function or subroutine, or, like a COMMON block variables, live for the lifetime of the program. However, most people in HEP who use FORTRAN will have experience of a memory manager and the act of creating a bank is a good equivalent of a heap object. For those who know systems like ZEBRA, it will come as a relief to learn that objects do not move, C++ does not garbage collect, so there is never a danger that a pointer to an object becomes invalid for that reason. However, having created an object, it is the user’s responsibility to ensure that it is deleted when no longer needed, or to pass that responsibility onto to some other object. Failing to do that will result in a memory leak, one of the most common and most hard-to-find C++ bugs. To send a message to an object via a pointer to it, you need to use the “->” operator e.g.: root[] my_objptr->Solve(); Although we chose to call our pointer my_objptr, to emphasize that it is a pointer, heap objects are so common in an object-oriented program that pointer names rarely reflect the fact - you have to be careful that you know if you are dealing with an object or its pointer! Fortunately, the compiler won’t tolerate an attempt to do something like: root[] my_objptr.Solve(); As we have seen, heap objects have to be accessed via pointers, whereas stack objects can be accessed directly. They can also be accessed via pointers: root[] Quad stack_quad(1.,2.,-3.); root[] Quad *stack_ptr = &stack_quad; root[] stack_ptr->Solve(); Here we have a Quad pointer that has been initialized with the address of a stack object. Be very careful if you take the address of stack objects. As we shall see soon, they are deleted automatically, which could leave you with an illegal pointer. Using it will corrupt and may as well crash the program! It is time to look at the destruction of objects. A destructor is a special C++ function that releases resources for (or destroys) an object of a class. It is the opposite of a constructor that creates the object of a class when it is called. The compiler will provide a destructor that does nothing if none is provided. We will add one to our Quad class so that we can see when it is called. The class names the destructor but with a prefix ~ which is the C++ one’s complement i.e. bit wise complement, and hence has destruction overtones! We declare it in the .h file and define it in the .cxx file. It does not do much except print out that it has been called (still a useful debug technique despite today’s powerful debuggers!). Now run root, load the Quad class and create a heap object: root[] .L Quad.cxx root[] Quad *my_objptr = new Quad(1.,2.,-3.); To delete the object: root[] delete my_objptr; root[] my_objptr = 0; You should see the print out from its destructor. Setting the pointer to zero afterwards is not strictly necessary (and Cling does it automatically), but the object is no more accessible, and any attempt to use the pointer again will, as has already been stated, cause grief. So much for heap objects, but how are stack objects deleted? In C++, a stack object is deleted as soon as control leaves the innermost compound statement that encloses it. Therefore, it is singularly futile to do something like: root[] { Quad my_object(1.,2.,-3.); } Cling does not follow this rule; if you type in the above line, you will not see the destructor message. As explained in the Script lesson, you can load in compound statements, which would be a bit pointless if everything disappeared as soon as it was loaded! Instead, to reset the stack you have to type: root[] gROOT->Reset(); This sends the Reset message via the global pointer to the ROOT object, which, amongst its many roles, acts as a resource manager. Start ROOT again and type in the following: root[] .L Quad.cxx root[] Quad my_object(1.,2.,-3.); root[] Quad *my_objptr = new Quad(4.,5.,-6.); root[] gROOT->Reset(); You will see that this deletes the first object but not the second. We have also painted ourselves into a corner, as my_objptr was also on the stack. This command will fail. root[] my_objptr->Solve(); Cling no longer knows what my_objptr is. This is a great example of a memory leak; the heap object exists but we have lost our way to access it. In general, this is not a problem. If any object will outlive the compound statement in which it was created then a more permanent pointer will point to it, which frequently is part of another heap object. See Resetting the Interpreter Environment in the chapter “Cling the C++ Interpreter”. # 7 The C++ Interpreter Cling ROOT has a C++ interpreter called cling built in. It is used for the prompt, both C++ and Python. It also serves as a source of information to store C++ objects, and provides the back-end for ROOT’s signal/slot and plug-in mechanisms. This chapter focuses on the parts of cling that you will encounter while interacting with ROOT. ## 7.1 The ROOT Prompt Start up a ROOT session by typing root at the system prompt. $ root
-------------------------------------------------------------------------
| Welcome to ROOT 6.10/01                             http://root.cern.ch |
|                                            (c) 1995-2017, The ROOT Team |
| Built for macosx64                                                      |
| From heads/v6-10-00-patches@v6-10-00-25-g9f78c3a, Jul 03 2017, 11:39:44 |
| Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'              |
-------------------------------------------------------------------------

root [0]

Now we create a TLine object:

root [1] TLine l;
root [2] l.Print()
TLine  X1=0.000000 Y1=0.000000 X2=0.000000 Y2=0.000000
root [3] l.SetX1(10)
root [4] l.SetY1(11)
root [5] l.Print()
TLine  X1=10.000000 Y1=11.000000 X2=0.000000 Y2=0.000000
root [6] .g l
.g l
ROOT_prompt_0     1 (address: NA) class TLine l, size = 72
root [7] l.GetX1();
root [8] l.GetX1()
(Double_t) 1.000000e+01

Note some of the features of the ROOT prompt: - Terminating with ‘;‘ is not required, see “C++ Extensions To Ease Scripting” below. - Emacs style command line editing. - Raw interpreter commands start with a dot; .g l for instance shows the interpreter information on the global called l. - To show the result of an expression just do not type the trailing ;.

For the further examples we will “abbreviate” root [0] etc by root [].

root [] .class TLine
===========================================================================
class TLine
SIZE: 72 FILE: TLine.h LINE: 39
Base classes: --------------------------------------------------------
0x20       public TAttBBox2D
List of member variables --------------------------------------------------
TLine.h          42 0x28       protected: Double_t fX1
TLine.h          43 0x30       protected: Double_t fY1
TLine.h          44 0x38       protected: Double_t fX2
TLine.h          45 0x40       protected: Double_t fY2
TLine.h          50 0x0      public: enum TLine::<anonymous at /home/axel/build/root/trunk/obj/include/TLine.h:49:4> kLineNDC
TLine.h          51 0x0      public: enum TLine::<anonymous at /home/axel/build/root/trunk/obj/include/TLine.h:49:4> kVertical
TLine.h          52 0x0      public: enum TLine::<anonymous at /home/axel/build/root/trunk/obj/include/TLine.h:49:4> kHorizontal
TLine.h          94 0x0      private: static class TClass *fgIsA
List of member functions :---------------------------------------------------
filename     line:size busy function type and name
(compiled)     (NA):(NA) 0 public: TLine();
(compiled)     (NA):(NA) 0 public: TLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2);
(compiled)     (NA):(NA) 0 public: TLine(const TLine &line);
(compiled)     (NA):(NA) 0 public: virtual ~TLine() noexcept;
(compiled)     (NA):(NA) 0 public: void Copy(class TObject &line) const;
(compiled)     (NA):(NA) 0 public: virtual Int_t DistancetoPrimitive(Int_t px, Int_t py);
(compiled)     (NA):(NA) 0 public: virtual class TLine *DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2);
(compiled)     (NA):(NA) 0 public: virtual class TLine *DrawLineNDC(Double_t x1, Double_t y1, Double_t x2, Double_t y2);
(compiled)     (NA):(NA) 0 public: virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py);
(compiled)     (NA):(NA) 0 public: Double_t GetX1() const;
(compiled)     (NA):(NA) 0 public: Double_t GetX2() const;
(compiled)     (NA):(NA) 0 public: Double_t GetY1() const;
(compiled)     (NA):(NA) 0 public: Double_t GetY2() const;
(compiled)     (NA):(NA) 0 public: Bool_t IsHorizontal();
(compiled)     (NA):(NA) 0 public: Bool_t IsVertical();
(compiled)     (NA):(NA) 0 public: virtual void ls(Option_t *option = "") const;
(compiled)     (NA):(NA) 0 public: virtual void Paint(Option_t *option = "");
(compiled)     (NA):(NA) 0 public: virtual void PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2);
(compiled)     (NA):(NA) 0 public: virtual void PaintLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2);
(compiled)     (NA):(NA) 0 public: virtual void Print(Option_t *option = "") const;
(compiled)     (NA):(NA) 0 public: virtual void SavePrimitive(std::ostream &out, Option_t *option = "");
(compiled)     (NA):(NA) 0 public: virtual void SetNDC(Bool_t isNDC = kTRUE);
(compiled)     (NA):(NA) 0 public: void SetHorizontal(Bool_t set = kTRUE);
(compiled)     (NA):(NA) 0 public: void SetVertical(Bool_t set = kTRUE);
(compiled)     (NA):(NA) 0 public: virtual void SetX1(Double_t x1);
(compiled)     (NA):(NA) 0 public: virtual void SetX2(Double_t x2);
(compiled)     (NA):(NA) 0 public: virtual void SetY1(Double_t y1);
(compiled)     (NA):(NA) 0 public: virtual void SetY2(Double_t y2);
(compiled)     (NA):(NA) 0 public: virtual struct Rectangle_t GetBBox();
(compiled)     (NA):(NA) 0 public: virtual class TPoint GetBBoxCenter();
(compiled)     (NA):(NA) 0 public: virtual void SetBBoxCenter(const class TPoint &p);
(compiled)     (NA):(NA) 0 public: virtual void SetBBoxCenterX(const Int_t x);
(compiled)     (NA):(NA) 0 public: virtual void SetBBoxCenterY(const Int_t y);
(compiled)     (NA):(NA) 0 public: virtual void SetBBoxX1(const Int_t x);
(compiled)     (NA):(NA) 0 public: virtual void SetBBoxX2(const Int_t x);
(compiled)     (NA):(NA) 0 public: virtual void SetBBoxY1(const Int_t y);
(compiled)     (NA):(NA) 0 public: virtual void SetBBoxY2(const Int_t y);
(compiled)     (NA):(NA) 0 public: static class TClass *Class();
(compiled)     (NA):(NA) 0 public: static const char *Class_Name();
(compiled)     (NA):(NA) 0 public: static Version_t Class_Version();
(compiled)     (NA):(NA) 0 public: static void Dictionary();
(compiled)     (NA):(NA) 0 public: virtual class TClass *IsA() const;
(compiled)     (NA):(NA) 0 public: virtual void ShowMembers(class TMemberInspector &insp) const;
(compiled)     (NA):(NA) 0 public: virtual void Streamer(class TBuffer &);
(compiled)     (NA):(NA) 0 public: void StreamerNVirtual(class TBuffer &ClassDef_StreamerNVirtual_b);
(compiled)     (NA):(NA) 0 public: static const char *DeclFileName();
(compiled)     (NA):(NA) 0 public: static int ImplFileLine();
(compiled)     (NA):(NA) 0 public: static const char *ImplFileName();
(compiled)     (NA):(NA) 0 public: static int DeclFileLine();
root [] .> test.log
root [] l.Dump();
root [] .>
root [] ?

Here we see:

• Use .class as quick help and reference
• Unix like I/O redirection using .> out.txt and unredirection with .>
• Use ? to get help on all ‘‘raw’’ interpreter commands
• Use @ to abort a multi-line command

Now let us execute a multi-line command:

root [] {
root [] ? TLine l;
root [] ? for (int i = 0; i < 5; i++) {
root [] ?    l.SetX1(i);
root [] ?    l.SetY1(i+1);
root [] ?    l.Print();
root [] ? }
root [] ? }
TLine  X1=0.000000 Y1=1.000000 X2=0.000000 Y2=0.000000
TLine  X1=1.000000 Y1=2.000000 X2=0.000000 Y2=0.000000
TLine  X1=2.000000 Y1=3.000000 X2=0.000000 Y2=0.000000
TLine  X1=3.000000 Y1=4.000000 X2=0.000000 Y2=0.000000
TLine  X1=4.000000 Y1=5.000000 X2=0.000000 Y2=0.000000
root [] .q

Here we note:

• A multi-line command starts with a { and ends with a }.
• Inside continuation, every line has to be correctly terminated with a ; (like in "real’’ C++).
• All objects are created in global scope.
• There is no way to back up; you are better off writing a script.
• Use .q to exit root.

## 7.2 Feeding Sources Files To ROOT: C++ Scripts

ROOT script files (often called “Macros”) contain pure C++ code. They can contain a simple sequence of statements like in the multi command line example given above, but also arbitrarily complex class and function definitions.

The most frequent interaction with the ROOT prompt uses .x to “run” a file:

root [] .x myScript.C

This loads myScript.C into the interpreter and calls the function myScript(). You can pass arguments using .x myScript.C(12, "A String").

Alternatively you can load the script and then run a function explicitly:

root [] .L myScript.C
root [] myScript()

The above is equivalent to .x myScript.C.

In a named script, the objects created on the stack are deleted when the function exits. In a common scenario you create a histogram in a named script on the stack. You draw the histogram, but when the function exits the canvas is empty and the histogram has disappeared. To avoid the histogram from disappearing you can create it on the heap (by using new). This will leave the histogram object intact, but the pointer in the named script scope will be “gone”. Since histograms (and trees) are added to the list of objects in the current directory, you can always retrieve them to delete them if needed.

root[] TH1F *h = (TH1F*)gDirectory->Get("myHist");              // or
root[] TH1F *h = (TH1F*)gDirectory->GetList()->FindObject("myHist");

In addition, histograms and trees are automatically deleted when the current directory is closed. This will automatically take care of the clean up. See “Input/Output”.

You may want to execute a script conditionally inside another script. To do it you need to call the interpreter and you can do that with TROOT::ProcessLine(). The example $ROOTSYS/tutorials/tree/cernstaff.C calls a script to build the root file if it does not exist: void cernstaff() { if (gSystem->AccessPathName("cernstaff.root")) { gROOT->ProcessLine(".x cernbuild.C"); } ProcessLine takes a parameter, which is a pointer to an int or to a TInterpreter::EErrorCode to let you access the interpreter error code after an attempt to interpret. This will contain the error as defined in enum TInterpreter::EErrorCode with TInterpreter::kSuccess being the value for a successful execution. ### 7.2.2 Executing a Script From the Invocation Instead if starting ROOT and running a script on the prompt you can also pass it to ROOT in its invocation: $ root -l -b 'myCode.C("some String", 12)'

The exact kind of quoting depends on your shell; the one shown here works for bash-like shells.

ROOT can evaluate any expression as part of the invocation; another version of the previous example can be spelled like this:

$root -l -b -e 'gROOT->ProcessLine(".x myCode.C(\"some String\", 12)");' ## 7.3 C++ Extensions To Ease Scripting In the next example, we demonstrate three of the most important extensions ROOT and Cling make to C++. Start ROOT in the directory $ROOTSYS/tutorials (make sure to have first run .x hsimple.C):

root [0] f = new TFile("hsimple.root")
(class TFile *) 0x4045e690
root [1] f->ls()
TFile**         hsimple.root
TFile*         hsimple.root
KEY: TH1F     hpx;1   This is the px distribution
KEY: TH2F     hpxpy;1 py ps px
KEY: THProfile        hprof;1 Profile of pz versus px
KEY: TNtuple  ntuple;1        Demo ntuple
root [2] hpx->Draw()
Warning in <MakeDefCanvas>: creating a default canvas with name c1
root [3] .q

The root [0] command shows the first extension; the declaration of f may be omitted as a shortcut for auto. Cling will correctly create f as pointer to object of class TFile. Nonetheless we recommend to use auto f = new TFile("hsimple.root").

The second extension is more important. In case Cling cannot find an object being referenced, it will ask ROOT to search for an object with an identical name in the search path defined by TROOT::FindObject(). If ROOT finds the object, it returns a pointer to this object to Cling and a pointer to its class definition and Cling will execute the requested member function. This shortcut is quite natural for an interactive system and saves much typing. In this example, ROOT searches for hpx and finds it in hsimple.root.

The next, fundamental extension is shown below. There is no need to put a semicolon at the end of a line. When you leave it off the value of the expression will be printed on the next line. For example:

root[] 23+5
(int)28
root[] 23+5;
root[] TMath::Sin
(Double_t (*)(Double_t)) Function @0x7ffff7ebb090
at include/TMath.h:418:
inline Double_t TMath::Sin(Double_t x)
{ return sin(x); }

Be aware that these extensions do not work when a compiler replaces the interpreter. Your code will not compile, hence when writing large scripts, it is best to stay away from these shortcuts. It will save you from having problems compiling your scripts using a real C++ compiler.

## 7.4 ACLiC: Compiling Scripts Into Libraries

Instead of having Cling interpret your script there is a way to have your scripts compiled, linked and dynamically loaded using the C++ compiler and linker. The advantage of this is that your scripts will run with the speed of compiled C++ and that you can use language constructs that are not fully supported by Cling. On the other hand, you cannot use any Cling shortcuts (see “C++ Extensions To Ease Scripting” above) and for small scripts, the overhead of the compile/link cycle might be larger than just executing the script in the interpreter.

ACLiC will build a dictionary and a shared library from your C++ script, using the compiler and the compiler options that were used to compile the ROOT executable. You do not have to write a Makefile remembering the correct compiler options, and you do not have to exit ROOT.

### 7.4.1 Usage

Before you can compile your interpreted script you need to add include statements for the classes used in the script. Once you did that, you can build and load a shared library containing your script. To load it use the command .L and append the file name with a +.

root[] .L MyScript.C+

The + option generates the shared library and names it by taking the name of the file “filename” but replacing the dot before the extension by an underscore and by adding the shared library extension for the current platform. For example on most platforms, hsimple.cxx will generate hsimple_cxx.so.

The + command rebuild the library only if the script or any of the files it includes are newer than the library. When checking the timestamp, ACLiC generates a dependency file which name is the same as the library name, just replacing the ‘so’ extension by the extension ‘d’. For example on most platforms, hsimple.cxx will generate hsimple_cxx.d.

To ensure that the shared library is rebuilt you can use the ++ syntax:

root[] .L MyScript.C++

To build, load, and execute the function with the same name as the file you can use the .x command. This is the same as executing a named script; you can also provide parameters. The only difference is you need to append a + or a ++.

root[] .x MyScript.C+(4000)
Creating shared library /home/./MyScript_C.so

You can select whether the script in compiled with debug symbol or with optimization by appending the letter ‘g’ or ‘O’ after the ‘+’ or ‘++’. Without the specification, the script is compiled with the same level of debugging symbol and optimization as the currently running ROOT executable. For example:

root[] .L MyScript.C++g

will compile MyScript.C with debug symbols; usually this means giving the -g option to compiler.

root[] .L MyScript.C++O

will compile MyScript.C with optimizations; usually this means giving the -O option to compiler. The syntax:

root[] .L MyScript.C++

is using the default optimization level. The initial default is to compile with the same level of optimization as the root executable itself. The default can be changed by:

root[] gSystem->SetAclicMode(TSystem::kDebug);
root[] gSystem->SetAclicMode(TSystem::kOpt);

Note that the commands:

root[] .L MyScript.C+g
root[] .L MyScript.C+O

respectively compile MyScript.C with debug and optimization if the library does not exist yet; they will not change the debug and the optimization level if the library already exist and it is up to date. To use ACLiC from compiled code or from inside another macro, we recommend using gROOT->ProcessLine(). For example, in one script you can use ACLiC to compile and load another script.

gROOT->ProcessLine(".L MyScript.C+")
gROOT->ProcessLine(".L MyScript.C++")

### 7.4.2 Setting the Include Path

You can get the include path by typing:

root[] .include

You can append to the include path by typing:

root[] .include $HOME/mypackage/include In a script you can append to the include path: gSystem->AddIncludePath(" -I$HOME/mypackage/include ")

You can also overwrite the existing include path:

gSystem->SetIncludePath(" -I$HOME/mypackage/include ") The $ROOTSYS/include directory is automatically appended to the include path, so you do not have to worry about including it. To add library that should be used during linking of the shared library use something like:

gSystem->AddLinkedLibs("-L/my/path -lanylib");

This is especially useful for static libraries. For shared ones you can also simply load them before trying to compile the script:

gSystem->Load("mydir/mylib");

ACLiC uses the directive fMakeSharedLibs to create the shared library. If loading the shared library fails, it tries to output a list of missing symbols by creating an executable (on some platforms like OSF, this does not HAVE to be an executable) containing the script. It uses the directive fMakeExe to do so. For both directives, before passing them to TSystem::Exec(), it expands the variables $SourceFiles, $SharedLib, $LibName, $IncludePath, $LinkedLibs, $ExeNameand$ObjectFiles. See SetMakeSharedLib() for more information on those variables. When the file being passed to ACLiC is on a read only file system, ACLiC warns the user and creates the library in a temporary directory: root[] .L readonly/t.C++ Warning in <ACLiC>: /scratch/aclic/subs/./readonly is not writable! Warning in <ACLiC>: Output will be written to /tmp Info in <TUnixSystem::ACLiC>: creating shared library /tmp//scratch/aclic/subs/./readonly/t_C.so To select the temporary directory ACLiC looks at $TEMP, $TEMP_DIR, $TEMPDIR, $TMP, $TMPDIR, $TMP_DIRor uses /tmp (or C:/). Also, a new interface TSystem::Get/SetBuildDir is introduced to let users select an alternative ‘root’ for building of the ACLiC libraries. For filename/full/path/name/macro.C, the library is created as fBuildDir/full/path/name/macro_C.so. ### 7.4.3 Dictionary Generation You can direct what is added to the dictionary generated by ACLiC in two ways. The simplest way is to add at the end of script (i.e. after the symbols have been defined) something like: #if defined(__ROOTCLING__) #pragma link C++ class MyOtherClass; #endif You can also write this portion of code in a file name MyScript_linkdef.h where the suffix '_linkdef'is the prefix defined by the key ‘ACLiC.Linkdef‘ in the currently used resource file (usually .rootrcor$ROOTSYS/etc/system.rootrc) and the prefix is the name of your script.

The default behavior of rootcling is to not link in (i.e. generate the dictionary for) any of the symbols. In particular, this means that the following lines are, in the general case, unnecessary.

#pragma link off all globals;
#pragma link off all functions;

This also means that linking the instantiation of a class template:

#pragma link C++ class mytemplate<int>;

ONLY links this specific class. You need to request the generation of the iterators explicitly.

See the documentation of rootcling for details how pragma can be used.

NOTE: You should not call ACLiC with a script that has a function called main().

### 7.4.4 Intermediate Steps and Files

ACLiC executes two steps and a third one if needed. These are:

• Calling rootcling to create a dictionary using rootcling.
• Calling the compiler to build the shared library from the script.
• If there are errors, it calls the compiler to build a dummy executable to clearly report unresolved symbols.

ACLiC makes a shared library with a dictionary containing the classes and functions declared in the script. It also adds the classes and functions declared in included files with the same name as the script file and any of the following extensions: .h, .hh, .hpp, .hxx, .hPP, .hXX. This means that, by default, you cannot combine scripts from different files into one library by using #include statements; you will need to compile each script separately. In a future release, we plan to add the global variables declared in the script to the dictionary also. If you are curious about the specific calls, you can raise the ROOT debug level: gDebug=3 and ACLiC will print these steps. If you need to keep the intermediate files around, for example when debugging the script using gdb, use gDebug=7.

### 7.4.5 Moving between Interpreter and Compiler

The best way to develop portable scripts is to make sure you can always run them with both, the interpreter and with ACLiC. To do so, do not use the Cling extensions and program around the Cling limitations. When it is not possible or desirable to program around the Cling limitations, you can use the C preprocessor symbols defined for Cling and rootcling.

The preprocessor symbol __CLING__ is defined for both ROOT and rootcling. The symbol __ROOTCLING__ (and __MAKECINT__ for backward compatibility) is only defined in rootcling.

Use !defined(__CLING__) || defined(__ROOTCLING__) to bracket code that needs to be seen by the compiler and rootcling, but will be invisible to the interpreter.

Use !defined(__CLING__)to bracket code that should be seen only by the compiler and not by Cling nor rootcling.For example, the following will hide the declaration and initialization of the array gArray from both Cling and rootcling.

#if !defined(__CLING__)
int gArray[] = { 2, 3, 4};
#endif

Because ACLiC calls rootcling to build a dictionary, the declaration of gArray will not be included in the dictionary, and consequently, gArray will not be available at the command line even if ACLiC is used. Cling and rootcling will ignore all statements between the "#if !defined (__CLING__)" and "#endif". If you want to use gArray in the same script as its declaration, you can do so. However, if you want use the script in the interpreter you have to bracket the usage of gArray between #if's, since the definition is not visible. If you add the following preprocessor statements:

#if !defined(__CLING__)
int gArray[] = { 2, 3, 4};
#elif defined(__ROOTCLING__)
int gArray[];
#endif

gArray will be visible to rootcling but still not visible to Cling. If you use ACLiC, gArray will be available at the command line and be initialized properly by the compiled code.

We recommend you always write scripts with the needed include statements. In most cases, the script will still run with the interpreter. However, a few header files are not handled very well by Cling.

These types of headers can be included in interpreted and compiled mode:

### 9.4.6 Text and Latex Mathematical Expressions

Text displayed in a pad may be embedded into boxes, called paves (TPaveLabel), or titles of graphs or many other objects but it can live a life of its own. All text displayed in ROOT graphics is an object of class TText. For a physicist, it will be most of the time a TLatex expression (which derives from TText). TLatex has been conceived to draw mathematical formulas or equations. Its syntax is very similar to the Latex in mathematical mode.

#### 9.4.6.1 Subscripts and Superscripts

Subscripts and superscripts are made with the _ and ^ commands. These commands can be combined to make complex subscript and superscript expressions. You may choose how to display subscripts and superscripts using the 2 functions SetIndiceSize(Double_t) and SetLimitIndiceSize(Int_t). Examples of what can be obtained using subscripts and superscripts:

 The expression Gives The expression Gives The expression Gives x^{2y} $$x^{2y}$$ x^{y^{2}} $$x^{y^{2}}$$ x_{1}^{y_{1}} $$x_{1}^{y_{1}}$$ x_{2y} $$x_{2y}$$ x^{y_{1}} $$x^{y_{1}}$$ x_{1}^{y} $$x_{1}^{y}$$

#### 9.4.6.2 Fractions

Fractions denoted by the / symbol are made in the obvious way. The #frac command is used for large fractions in displayed formula; it has two arguments: the numerator and the denominator. For example, the equation x = y + z 2 y 2 + 1 is obtained by following expression x=#frac{y+z/2}{y^{2}+1}.

#### 9.4.6.3 Roots

The #sqrt command produces the square ROOT of its argument; it has an optional first argument for other roots.

Example: #sqrt{10} #sqrt[3]{10}

#### 9.4.6.4 Delimiters

You can produce three kinds of proportional delimiters.

#[]{....} or “à la” Latex

#left[.....#right]big square brackets

#{}{....} or #left{.....#right}big curly brackets

#||{....} or #left|.....#right|big absolute value symbol

#(){....} or #left(.....#right)big parenthesis

#### 9.4.6.5 Changing Style in Math Mode

You can change the font and the text color at any moment using:

#font[font-number]{...} and #color[color-number]{...}

#### 9.4.6.6 Line Splitting

A TLatex string may be split in two with the following command: #splitline{top}{bottom}. TAxis and TGaxis objects can take advantage of this feature. For example, the date and time could be shown in the time axis over two lines with: #splitline{21 April 2003}{14:23:56}

### 9.4.7 Greek Letters

The command to produce a lowercase Greek letter is obtained by adding # to the name of the letter. For an uppercase Greek letter, just capitalize the first letter of the command name.

#alpha     #beta    #chi      #delta     #varepsilon  #phi
#gamma     #eta     #iota     #varphi    #kappa       #lambda
#mu        #nu      #omicron  #pi        #theta       #rho
#sigma     #tau     #upsilon  #varomega  #omega       #xi
#psi       #zeta    #Alpha    #Beta      #Chi         #Delta
#Epsilon   #Phi     #Gamma    #Eta       #Iota        #Kappa
#vartheta  #Lambda  #Mu       #Nu        #Omicron     #Pi
#Theta     #Rho     #Sigma    #Tau       #Upsilon     #Omega
#varsigma  #Xi      #Psi      #epsilon   #varUpsilon  #Zeta

### 9.4.8 Mathematical Symbols

TLatex can make mathematical and other symbols. A few of them, such as + and >, are produced by typing the corresponding keyboard character. Others are obtained with the commands as shown in the table above.

#### 9.4.8.1 Accents, Arrows and Bars

Symbols in a formula are sometimes placed one above another. TLatex provides special commands for that.

#hat{a} =hat

#check =inverted hat

#acute =acute

#grave =accent grave

#dot =derivative

#ddot =double derivative

#tilde =tilde

#slash =special sign. Draw a slash on top of the text between brackets for example

#slash{E}_{T}generates “Missing ET”

a _ is obtained with #bar{a}

a -> is obtained with #vec{a}

The script $ROOTSYS/tutorials/graphics/latex.C: { TCanvas c1("c1","Latex",600,700); TLatex l; l.SetTextAlign(12); l.SetTextSize(0.04); l.DrawLatex(0.1,0.8,"1) C(x) = d #sqrt{#frac{2}{#lambdaD}} #int^{x}_{0}cos(#frac{#pi}{2}t^{2})dt"); l.DrawLatex(0.1,0.6,"2) C(x) = d #sqrt{#frac{2}{#lambdaD}} #int^{x}cos(#frac{#pi}{2}t^{2})dt"); l.DrawLatex(0.1,0.4,"3) R = |A|^{2} = #frac{1}{2}(#[]{#frac{1}{2}+C(V)}^{2}+ #[]{#frac{1}{2}+S(V)}^{2})"); l.DrawLatex(0.1,0.2,"4) F(t) = #sum_{i= -#infty}^{#infty}A(i)cos#[]{#frac{i}{t+i}}"); } #### 9.4.8.3 Example 2 The script $ROOTSYS/tutorials/graphics/latex2.C:

{
TCanvas c1("c1","Latex",600,700);
TLatex l;
l.SetTextAlign(23);
l.SetTextSize(0.1);
l.DrawLatex(0.5,0.95,"e^{+}e^{-}#rightarrowZ^{0}
#rightarrowI#bar{I}, q#bar{q}");
l.DrawLatex(0.5,0.75,"|#vec{a}#bullet#vec{b}|=
#Sigmaa^{i}_{jk}+b^{bj}_{i}");
l.DrawLatex(0.5,0.5,"i(#partial_{#mu}#bar{#psi}#gamma^{#mu}
+m#bar{#psi}=0
#Leftrightarrow(#Box+m^{2})#psi=0");
l.DrawLatex(0.5,0.3,"L_{em}=eJ^{#mu}_{em}A_{#mu} ,
J^{#mu}_{em}=#bar{I}#gamma_{#mu}I
M^{j}_{i}=#SigmaA_{#alpha}#tau^{#alphaj}_{i}");
}

The script $ROOTSYS/tutorials/graphics/latex3.C: { TCanvas c1("c1"); TPaveText pt(.1,.5,.9,.9); pt.AddText("#frac{2s}{#pi#alpha^{2}} #frac{d#sigma}{dcos#theta} (e^{+}e^{-} #rightarrow f#bar{f} ) = "); pt.AddText("#left| #frac{1}{1 - #Delta#alpha} #right|^{2} (1+cos^{2}#theta"); pt.AddText("+ 4 Re #left{ #frac{2}{1 - #Delta#alpha} #chi(s) #[]{#hat{g}_{#nu}^{e}#hat{g}_{#nu}^{f} (1 + cos^{2}#theta) + 2 #hat{g}_{a}^{e} #hat{g}_{a}^{f} cos#theta) } #right}"); pt.SetLabel("Born equation"); pt.Draw(); } ### 9.4.9 Text in a Pad Text displayed in a pad may be embedded into boxes, called paves, or may be drawn alone. In any case, it is recommended to use a Latex expression, which is covered in the previous paragraph. Using TLatex is valid whether the text is embedded or not. In fact, you will use Latex expressions without knowing it since it is the standard for all the embedded text. A pave is just a box with a border size and a shadow option. The options common to all types of paves and used when building those objects are the following: option = "T" top frame option = "B" bottom frame option = "R" right frame option = "L" left frame option = "NDC" x1,y1,x2,y2 are given in NDC option = "ARC" corners are rounded We will see the practical use of these options in the description of the more functional objects like TPaveLabels. There are several categories of paves containing text: TPaveLabel, TPaveText and TPavesText. TPaveLabels are panels containing one line of text. They are used for labeling. TPaveLabel(Double_t x1, Double_t y1, Double_t x2, Double_t y2, const char *label, Option_t *option) Where (x1, y1) are the coordinates of the bottom left corner, (x2,y2) - coordinates of the upper right corner. “label” is the text to be displayed and “option” is the drawing option, described above. By default, the border size is 5 and the option is “br”. If one wants to set the border size to some other value, one may use the method SetBorderSize(). For example, suppose we have a histogram, which limits are (-100,100) in the x direction and (0, 1000) in the y direction. The following lines will draw a label in the center of the histogram, with no border. If one wants the label position to be independent of the histogram coordinates, or user coordinates, one can use the option “NDC”. See “The Coordinate Systems of a Pad”. root[] pl = new TPaveLabel(-50,0,50,200,"Some text") root[] pl->SetBorderSize(0) root[] pl->Draw() A TPaveLabel can contain only one line of text. A TPaveText may contain several lines. This is the only difference. This picture illustrates and explains some of the points of TPaveText. Once a TPaveText is drawn, a line can be added or removed by brining up the context menu with the mouse. A TPavesText is a stack of text panels (see TPaveText). One can set the number of stacked panels at building time. It has the following constructor: By default, the number of stacked panels is 5, option=br”. TPavesText(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Int_t npaves, Option_t* option) ### 9.4.10 The TeX Processor TMathText TMathText’s purpose is to write mathematical equations, exactly as TeX would do it. The syntax is the same as the TeX’s one. The script $ROOTSYS/tutorials/graphics/tmathtex.C:

gives the following output:

TMathText uses plain TeX syntax and uses “\” as control instead of “#”. If a piece of text containing “\” is given to TLatex then TMathText is automatically invoked. Therefore, as histograms’ titles, axis titles, labels etc … are drawn using TLatex, the TMathText syntax can be used for them also.

## 9.5 Axis

The axis objects are automatically built by various high level objects such as histograms or graphs. Once build, one may access them and change their characteristics. It is also possible, for some particular purposes to build axis on their own. This may be useful for example in the case one wants to draw two axis for the same plot, one on the left and one on the right.

For historical reasons, there are two classes representing axis. TAxis * axis is the axis object, which will be returned when calling the TH1::GetAxis() method.

TAxis *axis = histo->GetXaxis()

Of course, you may do the same for Y and Z-axis. The graphical representation of an axis is done with the TGaxis class. The histogram classes and TGraph generate instances of this class. This is internal and the user should not have to see it.

### 9.5.1 Axis Title

The axis title is set, as with all named objects, by

axis->SetTitle("Whatever title you want");

When the axis is embedded into a histogram or a graph, one has to first extract the axis object:

h->GetXaxis()->SetTitle("Whatever title you want")

### 9.5.2 Axis Options and Characteristics

The axis options are most simply set with the styles. The available style options controlling specific axis options are the following:

TAxis *axis = histo->GetXaxis();
axis->SetAxisColor(Color_t color = 1);
axis->SetLabelColor(Color_t color = 1);
axis->SetLabelFont(Style_t font = 62);
axis->SetLabelOffset(Float_t offset = 0.005);
axis->SetLabelSize(Float_t size = 0.04);
axis->SetNdivisions(Int_t n = 510, Bool_t optim = kTRUE);
axis->SetNoExponent(Bool_t noExponent = kTRUE);
axis->SetTickLength(Float_t length = 0.03);
axis->SetTitleOffset(Float_t offset = 1);
axis->SetTitleSize(Float_t size = 0.02);

The getters corresponding to the described setters are also available. The general options, not specific to axis, as for instance SetTitleTextColor() are valid and do have an effect on axis characteristics.

### 9.5.3 Setting the Number of Divisions

Use TAxis::SetNdivisions(ndiv,optim) to set the number of divisions for an axis. The ndiv and optim are as follows:

• ndiv = N1 + 100*N2 + 10000*N3

• N1 = number of first divisions.

• N2 = number of secondary divisions.

• N3 = number of tertiary divisions.

• optim = kTRUE (default), the divisions’ number will be optimized around the specified value.

• optim = kFALSE, or n < 0, the axis will be forced to use exactly n divisions.

For example:

ndiv = 0: no tick marks.

ndiv = 2: 2 divisions, one tick mark in the middle of the axis.

ndiv = 510: 10 primary divisions, 5 secondary divisions

ndiv = -10: exactly 10 primary divisions

### 9.5.4 Zooming the Axis

You can use TAxis::SetRange or TAxis::SetRangeUser to zoom the axis.

TAxis::SetRange(Int_t binfirst,Int_t binlast)

The SetRange method parameters are bin numbers. They are not axis. For example if a histogram plots the values from 0 to 500 and has 100 bins, SetRange(0,10) will cover the values 0 to 50. The parameters for SetRangeUser are user coordinates. If the start or end is in the middle of a bin the resulting range is approximation. It finds the low edge bin for the start and the high edge bin for the high.

TAxis::SetRangeUser(Axis_t ufirst,Axis_t ulast)

Both methods, SetRange and SetRangeUser, are in the context menu of any axis and can be used interactively. In addition, you can zoom an axis interactively: click on the axis on the start, drag the cursor to the end, and release the mouse button.

### 9.5.5 Drawing Axis Independently of Graphs or Histograms

An axis may be drawn independently of a histogram or a graph. This may be useful to draw for example a supplementary axis for a graph. In this case, one has to use the TGaxis class, the graphical representation of an axis. One may use the standard constructor for this kind of objects:

TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
Double_t wmin, Double_t wmax, Int_t ndiv = 510,
Option_t* chopt,Double_t gridlength = 0)

The arguments xmin, ymin are the coordinates of the axis’ start in the user coordinates system, and xmax, ymax are the end coordinates. The arguments wmin and wmax are the minimum (at the start) and maximum (at the end) values to be represented on the axis; ndiv is the number of divisions. The options, given by the “chopt” string are the following:

• chopt = 'G': logarithmic scale, default is linear.

• chopt = 'B': Blank axis (it is useful to superpose the axis).

Instead of the wmin,wmax arguments of the normal constructor, i.e. the limits of the axis, the name of a TF1 function can be specified. This function will be used to map the user coordinates to the axis values and ticks.

The constructor is the following:

TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
const char* funcname, Int_t ndiv=510,
Option_t* chopt, Double_t gridlength=0)

In such a way, it is possible to obtain exponential evolution of the tick marks position, or even decreasing. In fact, anything you like.

### 9.5.6 Orientation of Tick Marks on Axis

Tick marks are normally drawn on the positive side of the axis, however, if xmin = xmax, then negative.

• chopt = '+': tick marks are drawn on Positive side. (Default)

• chopt = '-': tick marks are drawn on the negative side.

• chopt = '+-': tick marks are drawn on both sides of the axis.

• chopt = ‘U': unlabeled axis, default is labeled.

### 9.5.7 Labels

#### 9.5.7.1 Position

Labels are normally drawn on side opposite to tick marks. However, chopt = '=': on Equal side. The function TAxis::CenterLabels() sets the bit kCenterLabels and it is visible from TAxis context menu. It centers the bin labels and it makes sense only when the number of bins is equal to the number of tick marks. The class responsible for drawing the axis TGaxis inherits this property.

#### 9.5.7.2 Orientation

Labels are normally drawn parallel to the axis. However, if xmin = xmax, then they are drawn orthogonal, and if ymin=ymax they are drawn parallel.

#### 9.5.7.3 Labels for Exponents

By default, an exponent of the form 10^N is used when the label values are either all very small or very large. One can disable the exponent by calling:

TAxis::SetNoExponent(kTRUE)

Note that this option is implicitly selected if the number of digits to draw a label is less than the fgMaxDigits global member. If the property SetNoExponent was set in TAxis (via TAxis::SetNoExponent), the TGaxis will inherit this property. TGaxis is the class responsible for drawing the axis. The method SetNoExponent is also available from the axis context menu.

#### 9.5.7.4 Number of Digits in Labels

TGaxis::fgMaxDigits is the maximum number of digits permitted for the axis labels above which the notation with 10^N is used. It must be greater than 0. By default fgMaxDigits is 5 and to change it use the TGaxis::SetMaxDigits method. For example to set fgMaxDigits to accept 6 digits and accept numbers like 900000 on an axis call:

TGaxis::SetMaxDigits(6)

#### 9.5.7.5 Tick Mark Positions

Labels are centered on tick marks. However, if xmin = xmax, then they are right adjusted.

• chopt = 'R': labels are right adjusted on tick mark (default is centered)

• chopt = 'L': labels are left adjusted on tick mark.

• chopt = 'C': labels are centered on tick mark.

• chopt = 'M': In the Middle of the divisions.

#### 9.5.7.6 Label Formatting

Blank characters are stripped, and then the label is correctly aligned. The dot, if last character of the string, is also stripped. In the following, we have some parameters, like tick marks length and characters height (in percentage of the length of the axis, in user coordinates). The default values are as follows:

• Primary tick marks: 3.0 %

• Secondary tick marks: 1.5 %

• Third order tick marks: .75 %

• Characters height for labels: 4%

• Labels offset: 1.0 %

#### 9.5.7.7 Stripping Decimals

Use the TStyle::SetStripDecimals to strip decimals when drawing axis labels. By default, the option is set to true, and TGaxis::PaintAxis removes trailing zeros after the dot in the axis labels, e.g. {0, 0.5, 1, 1.5, 2, 2.5, etc.}

TStyle::SetStripDecimals (Bool_t strip=kTRUE)

If this function is called with strip=kFALSE, TGaxis::PaintAxis() will draw labels with the same number of digits after the dot, e.g. {0.0, 0.5, 1.0, 1.5, 2.0, 2.5, etc.}

#### 9.5.7.8 Optional Grid

chopt = 'W': cross-Wire

#### 9.5.7.9 Axis Binning Optimization

By default, the axis binning is optimized.

• chopt = 'N': No binning optimization

• chopt = 'I': Integer labeling

### 9.5.8 Axis with Time Units

Histograms’ axis can be defined as “time axis”. To do that it is enough to activate the SetTimeDisplay attribute on a given axis. If h is a histogram, it is done the following way:

h->GetXaxis()->SetTimeDisplay(1);    // X axis is a time axis

Two parameters can be adjusted in order to define time axis: the time format and the time offset.

#### 9.5.8.1 Time Format

It defines the format of the labels along the time axis. It can be changed using the TAxis method SetTimeFormat. The time format is the one used by the C function strftime(). It is a string containing the following formatting characters:

 For the date: %a abbreviated weekday name %b abbreviated month name %d day of the month (01-31) %m month (01-12) %y year without century %Y year with century For the time: %H hour (24-hour clock) %I hour (12-hour clock) %p local equivalent of AM or PM %M minute (00-59) %S seconds (00-61) %% %

The other characters are output as is. For example to have a format like dd/mm/yyyy one should do:

h->GetXaxis()->SetTimeFormat("%d/%m/%Y");

If the time format is not defined, a default one will be computed automatically.

#### 9.5.8.2 Time Offset

This is a time in seconds in the UNIX standard UTC format (the universal time, not the local one), defining the starting date of a histogram axis. This date should be greater than 01/01/95 and is given in seconds. There are three ways to define the time offset:

1- By setting the global default time offset:

TDatime da(2003,02,28,12,00,00);
gStyle->SetTimeOffset(da.Convert());

If no time offset is defined for a particular axis, the default time offset will be used. In the example above, notice the usage of TDatime to translate an explicit date into the time in seconds required by SetTimeFormat.

2- By setting a time offset to a particular axis:

TDatime dh(2001,09,23,15,00,00);
h->GetXaxis()->SetTimeOffset(dh.Convert());

3- Together with the time format using SetTimeFormat. The time offset can be specified using the control character %F after the normal time format. %F is followed by the date in the format: yyyy-mm-dd hh:mm:ss.

h->GetXaxis()->SetTimeFormat("%d/%m/%y%F2000-02-28 13:00:01");

Notice that this date format is the same used by the TDatime function AsSQLString. If needed, this function can be used to translate a time in seconds into a character string which can be appended after %F. If the time format is not specified (before %F) the automatic one will be used. The following example illustrates the various possibilities.

{
gStyle->SetTitleH(0.08);
TDatime da(2003,02,28,12,00,00);
gStyle->SetTimeOffset(da.Convert());
ct = new TCanvas("ct","Time on axis",0,0,600,600);
ct->Divide(1,3);
ht1 = new TH1F("ht1","ht1",30000,0.,200000.);
ht2 = new TH1F("ht2","ht2",30000,0.,200000.);
ht3 = new TH1F("ht3","ht3",30000,0.,200000.);
for (Int_t i=1;i<30000;i++) {
Float_t noise = gRandom->Gaus(0,120);
ht1->SetBinContent(i,noise);
ht2->SetBinContent(i,noise*noise);
ht3->SetBinContent(i,noise*noise*noise);
}
ct->cd(1);
ht1->GetXaxis()->SetLabelSize(0.06);
ht1->GetXaxis()->SetTimeDisplay(1);
ht1->GetXaxis()->SetTimeFormat("%d/%m/%y%F2000-02-2813:00:01");
ht1->Draw();
ct->cd(2);
ht2->GetXaxis()->SetLabelSize(0.06);
ht2->GetXaxis()->SetTimeDisplay(1);
ht2->GetXaxis()->SetTimeFormat("%d/%m/%y");
ht2->Draw();
ct->cd(3);
ht3->GetXaxis()->SetLabelSize(0.06);
TDatime dh(2001,09,23,15,00,00);
ht3->GetXaxis()->SetTimeDisplay(1);
ht3->GetXaxis()->SetTimeOffset(dh.Convert());
ht3->Draw();
}

The output is shown in the figure below. If a time axis has no specified time offset, the global time offset will be stored in the axis data structure. The histogram limits are in seconds. If wmin and wmax are the histogram limits, the time axis will spread around the time offset value from TimeOffset+wmin to TimeOffset+wmax. Until now all examples had a lowest value equal to 0. The following example demonstrates how to define the histogram limits relatively to the time offset value.

{
// Define the time offset as 2003, January 1st
TDatime T0(2003,01,01,00,00,00);
int X0 = T0.Convert();
gStyle->SetTimeOffset(X0);

// Define the lowest histogram limit as 2002,September 23rd
TDatime T1(2002,09,23,00,00,00);
int X1 = T1.Convert()-X0;

// Define the highest histogram limit as 2003, March 7th
TDatime T2(2003,03,07,00,00,00);
int X2 = T2.Convert(1)-X0;

TH1F * h1 = new TH1F("h1","test",100,X1,X2);

TRandom r;
for (Int_t i=0;i<30000;i++) {
Double_t noise = r.Gaus(0.5*(X1+X2),0.1*(X2-X1));
h1->Fill(noise);
}

h1->GetXaxis()->SetTimeDisplay(1);
h1->GetXaxis()->SetLabelSize(0.03);
h1->GetXaxis()->SetTimeFormat("%Y/%m/%d");
h1->Draw();
}

The output is shown in the next figure. Usually time axes are created automatically via histograms, but one may also want to draw a time axis outside a “histogram context”. Therefore, it is useful to understand how TGaxis works for such axis. The time offset can be defined using one of the three methods described before. The time axis will spread around the time offset value. Actually, it will go from TimeOffset+wmin to TimeOffset+wmax where wmin and wmax are the minimum and maximum values (in seconds) of the axis. Let us take again an example. Having defined “2003, February 28 at 12h”, we would like to see the axis a day before and a day after.

A TGaxis can be created the following way (a day has 86400 seconds):

TGaxis *axis = new TGaxis(x1,y1,x2,y2,-100000,150000,2405,"t");

the “t” option (in lower case) means it is a “time axis”. The axis goes form 100000 seconds before TimeOffset and 150000 seconds after. So the complete macro is:

{
c1 = new TCanvas("c1","Examples of TGaxis",10,10,700,500);
c1->Range(-10,-1,10,1);
TGaxis *axis = new TGaxis(-8,-0.6,8,-0.6,-100000,150000,2405,"t");
axis->SetLabelSize(0.03);

TDatime da(2003,02,28,12,00,00);
axis->SetTimeOffset(da.Convert());
axis->SetTimeFormat("%d/%m/%Y");
axis->Draw();
}

The time format is specified with:

axis->SetTimeFormat("%d/%m/%Y");

The macro gives the following output:

Thanks to the TLatex directive #splitline it is possible to write the time labels on two lines. In the previous example changing the SetTimeFormat line by:

axis->SetLabelOffset(0.02);
axis->SetTimeFormat("#splitline{%Y}{%d/%m}");

will produce the following axis:

### 9.5.9 Axis Examples

To illustrate what was said, we provide two scripts. The first one creates the picture shown in the next figure.

The first script is:

{
c1 = new TCanvas("c1","Examples of Gaxis",10,10,700,500);
c1->Range(-10,-1,10,1);

TGaxis *axis1 = new TGaxis(-4.5,-0.2,5.5,-0.2,-6,8,510,"");
axis1->SetName("axis1");
axis1->Draw();
TGaxis *axis2 = new TGaxis(4.5,0.2,5.5,0.2,0.001,10000,510,"G");
axis2->SetName("axis2");
axis2->Draw();

TGaxis *axis3 = new TGaxis(-9,-0.8,-9,0.8,-8,8,50510,"");
axis3->SetName("axis3");
axis3->Draw();
TGaxis *axis4 = new TGaxis(-7,-0.8,7,0.8,1,10000,50510,"G");
axis4->SetName("axis4");
axis4->Draw();

TGaxis *axis5 = new TGaxis(-4.5,-6,5.5,-6,1.2,1.32,80506,"-+");
axis5->SetName("axis5");
axis5->SetLabelSize(0.03);
axis5->SetTextFont(72);
axis5->SetLabelOffset(0.025);
axis5->Draw();

TGaxis *axis6 = new TGaxis(-4.5,0.6,5.5,0.6,100,900,50510,"-");
axis6->SetName("axis6");
axis6->Draw();
TGaxis *axis7 = new TGaxis(8,-0.8,8,0.8,0,9000,50510,"+L");
axis7->SetName("axis7");
axis7->SetLabelOffset(0.01);
axis7->Draw();

// one can make axis top->bottom. However because of a problem,
// the two x values should not be equal
TGaxis *axis8 = new TGaxis(6.5,0.8,6.499,-0.8,0,90,50510,"-");
axis8->SetName("axis8");
axis8->Draw();
}

The second example shows the use of the second form of the constructor, with axis ticks position determined by a function TF1:

void gaxis3a()
{
gStyle->SetOptStat(0);

TH2F *h2 = new TH2F("h","Axes",2,0,10,2,-2,2);
h2->Draw();
TF1 *f1=new TF1("f1","-x",-10,10);
TGaxis *A1 = new TGaxis(0,2,10,2,"f1",510,"-");
A1->SetTitle("axis with decreasing values");
A1->Draw();

TF1 *f2=new TF1("f2","exp(x)",0,2);
TGaxis *A2 = new TGaxis(1,1,9,1,"f2");
A2->SetTitle("exponential axis");
A2->SetLabelSize(0.03);
A2->SetTitleSize(0.03);
A2->SetTitleOffset(1.2);
A2->Draw();

TF1 *f3=new TF1("f3","log10(x)",0,800);
TGaxis *A3 = new TGaxis(2,-2,2,0,"f3",505);
A3->SetTitle("logarithmic axis");
A3->SetLabelSize(0.03);
A3->SetTitleSize(0.03);
A3->SetTitleOffset(1.2);
A3->Draw();
}
// strip chart example
void seism() {

TStopwatch sw; sw.Start();
//set time offset
TDatime dtime;
gStyle->SetTimeOffset(dtime.Convert());
TCanvas *c1 = new TCanvas("c1","Time on axis",10,10,1000,500);
c1->SetFillColor(42);
c1->SetFrameFillColor(33);
c1->SetGrid();

Float_t bintime = 1;
// one bin = 1 second. change it to set the time scale
TH1F *ht = new TH1F("ht","The ROOT seism",10,0,10*bintime);
Float_t signal = 1000;
ht->SetMaximum(signal);
ht->SetMinimum(-signal);
ht->SetStats(0);
ht->SetLineColor(2);
ht->GetXaxis()->SetTimeDisplay(1);
ht->GetYaxis()->SetNdivisions(520);
ht->Draw();

for (Int_t i=1;i<2300;i++) {
// Build a signal : noisy damped sine
Float_t noise  = gRandom->Gaus(0,120);
if (i > 700)
noise += signal*sin((i-700.)*6.28/30)*exp((700.-i)/300.);
ht->SetBinContent(i,noise);
c1->Modified();
c1->Update();
gSystem->ProcessEvents();
//canvas can be edited during the loop
}
printf("Real Time = %8.3fs,Cpu Time = %8.3fsn",sw.RealTime(),
sw.CpuTime());
}

## 9.6 Graphical Objects Attributes

### 9.6.1 Text Attributes

When a class contains text or derives from a text class, it needs to be able to set text attributes like font type, size, and color. To do so, the class inherits from the TAttText class (a secondary inheritance), which defines text attributes. TLatex and TText inherit from TAttText.

#### 9.6.1.1 Setting Text Alignment

Text alignment may be set by a method call. What is said here applies to all objects deriving from TAttText, and there are many. We will take an example that may be transposed to other types. Suppose “la” is a TLatex object. The alignment is set with:

root[] la->SetTextAlign(align)

The parameter align is a short describing the alignment:

align = 10*HorizontalAlign + VerticalAlign

For horizontal alignment, the following convention applies:

• 1 = left

• 2 = centered

• 3 = right

For vertical alignment, the following convention applies:

• 1 = bottom

• 2 = centered

• 3 = top

For example, align: 11 = left adjusted and bottom adjusted; 32 = right adjusted and vertically centered.

#### 9.6.1.2 Setting Text Angle

Use TAttText::SetTextAngle to set the text angle. The angle is the degrees of the horizontal.

root[] la->SetTextAngle(angle)

#### 9.6.1.3 Setting Text Color

Use TAttText::SetTextColor to set the text color. The color is the color index. The colors are described in “Color and Color Palettes”.

root[] la->SetTextColor(color)

#### 9.6.1.4 Setting Text Font

Use TAttText::SetTextFont to set the font. The parameter font is the font code, combining the font and precision: font = 10 * fontID + precision

root[] la->SetTextFont(font)

The table below lists the available fonts. The font IDs must be between 1 and 14. The precision can be:

• Precision = 0 fast hardware fonts (steps in the size)

• Precision = 1 scalable and rotate-able hardware fonts (see below)

• Precision = 2 scalable and rotate-able hardware fonts

When precision 0 is used, only the original non-scaled system fonts are used. The fonts have a minimum (4) and maximum (37) size in pixels. These fonts are fast and are of good quality. Their size varies with large steps and they cannot be rotated. Precision 1 and 2 fonts have a different behavior depending if True Type Fonts (TTF) are used or not. If TTF are used, you always get very good quality scalable and rotate-able fonts. However, TTF are slow. Precision 1 and 2 fonts have a different behavior for PostScript in case of TLatex objects:

• With precision 1, the PostScript text uses the old convention (see TPostScript) for some special characters to draw sub and superscripts or Greek text.

• With precision 2, the “PostScript” special characters are drawn as such. To draw sub and superscripts it is highly recommended to use TLatex objects instead.

For example: font = 62 is the font with ID 6 and precision 2.

The available fonts are:

 Font ID X11 True Type name Is italic “boldness” 1 times-medium-i-normal “Times New Roman” Yes 4 2 times-bold-r-normal “Times New Roman” No 7 3 times-bold-i-normal “Times New Roman” Yes 7 4 helvetica-medium-r-norma l “Arial” No 4 5 helvetica-medium-o-norma l “Arial” Yes 4 6 helvetica-bold-r-normal “Arial” No 7 7 helvetica-bold-o-normal “Arial” Yes 7 8 courier-medium-r-normal “Courier New” No 4 9 courier-medium-o-normal “Courier New” Yes 4 10 courier-bold-r-normal “Courier New” No 7 11 courier-bold-o-normal “Courier New” Yes 7 12 symbol-medium-r-normal “Symbol” No 6 13 times-medium-r-normal “Times New Roman” No 4 14 “Wingdings” No 4

This script makes the image of the different fonts:

{
textc = new TCanvas("textc","Example of text",1);
for (int i=1;i<15;i++) {
cid = new char[8];
sprintf(cid,"ID %d :",i);
cid[7] = 0;
lid = new TLatex(0.1,1-(double)i/15,cid);
lid->SetTextFont(62);
lid->Draw();
l = new TLatex(.2,1-(double)i/15,
"The quick brown fox is not here anymore")
l->SetTextFont(i*10+2);
l->Draw();
}
}

#### 9.6.1.5 How to use True Type Fonts

You can activate the True Type Fonts by adding the following line in your .rootrc file.

Unix.*.Root.UseTTFonts:     true

You can check that you indeed use the TTF in your Root session. When the TTF is active, you get the following message at the start of a session: “Free Type Engine v1.x used to render TrueType fonts.” You can also check with the command:

gEnv->Print()

#### 9.6.1.6 Setting Text Size

Use TAttText::SetTextSize to set the text size.

root[] la->SetTextSize(size)

The size is the text size expressed in percentage of the current pad size.

The text size in pixels will be:

• If current pad is horizontal, the size in pixels = textsize * canvas_height

• If current pad is vertical, the size in pixels = textsize * canvas_width

The user interface for changing the text color, size, font and alignment looks like shown in this picture. It takes place in the editor frame anytime the selected object inherits the class TAttText.

### 9.6.2 Line Attributes

All classes manipulating lines have to deal with line attributes: color, style and width. This is done by using secondary inheritance of the class TAttLine. The line color may be set by a method call. What is said here applies to all objects deriving from TAttLine, and there are many (histograms, plots). We will take an example that may be transposed to other types. Suppose “li” is a TLine object. The line color is set with:

root[] li->SetLineColor(color)

The argument color is a color number. The colors are described in “Color and Color Palettes”

The line style may be set by a method call. What is said here applies to all objects deriving from TAttLine, and there are many (histograms, plots). We will take an example that may be transposed to other types. Suppose “li” is a TLine object. The line style is set with:

root[] li->SetLineStyle(style)

The argument style is one of: 1=solid, 2=dash, 3=dot, 4=dash-dot.

The line width may be set by a method call. What is said here applies to all objects deriving from TAttLine, and there are many (histograms, plots). We will take an example that may be transposed to other types. Suppose “li” is a TLine object. The line width is set with:

root[] li->SetLineWidth(width)

The width is the width expressed in pixel units.

The user interface for changing the line color, line width and style looks like shown in this picture. It takes place in the editor frame anytime the selected object inherits the class TAttLine.

### 9.6.3 Fill Attributes

Almost all graphics classes have a fill area somewhere. These classes have to deal with fill attributes. This is done by using secondary inheritance of the class TAttFill. Fill color may be set by a method call. What is said here applies to all objects deriving from TAttFill, and there are many (histograms, plots). We will take an example that may be transposed to other types. Suppose “h” is a TH1F (1 dim histogram) object. The histogram fill color is set with:

root[] h->SetFillColor(color)

The color is a color number. The colors are described in “Color and color palettes”

Fill style may be set by a method call. What is said here applies to all objects deriving from TAttFill, and there are many (histograms, plots). We will take an example that may be transposed to other types. Suppose “h” is a TH1F (1 dim histogram) object. The histogram fill style is set with:

root[] h->SetFillStyle(style)

The convention for style is: 0:hollow, 1001:solid, 2001:hatch style, 3000+pattern number:patterns, 4000 to 4100:transparency, 4000:fully transparent, 4100: fully opaque.

Fill styles >3100 and <3999 are hatches. They are defined according to the FillStyle=3ijk value as follows:

• i(1-9) specifies the space between each hatch (1=minimum space, 9=maximum). The final spacing is set by SetHatchesSpacing() method and it is*GetHatchesSpacing().

• j(0-9) specifies the angle between 0 and 90 degres as follows: 0=0, 1=10, 2=20, 3=30, 4=45, 5=not drawn, 6=60, 7=70, 8=80 and 9=90.

• k(0-9) specifies the angle between 0 and 90 degres as follows: 0=180, 1=170, 2=160, 3=150, 4=135, 5=not drawn, 6=120, 7=110, 8=100 and 9=90.

### 9.6.4 Color and Color Palettes

At initialization time, a table of basic colors is generated when the first Canvas constructor is called. This table is a linked list, which can be accessed from the gROOT object (see TROOT::GetListOfColors()). Each color has an index and when a basic color is defined, two “companion” colors are defined:

• the dark version (color index + 100)

• the bright version (color index + 150)

The dark and bright colors are used to give 3-D effects when drawing various boxes (see TWbox, TPave, TPaveText, TPaveLabel, etc). If you have a black and white copy of the manual, here are the basic colors and their indices.

The list of currently supported basic colors (here dark and bright colors are not shown) are shown. The color numbers specified in the basic palette, and the picture above, can be viewed by selecting the menu entry Colors in the View canvas menu. The user may define other colors. To do this, one has to build a new TColor:

TColor(Int_t color,Float_t r,Float_t g,Float_t b,const char* name)

One has to give the color number and the three Red, Green, Blue values, each being defined from 0 (min) to 1(max). An optional name may be given. When built, this color is automatically added to the existing list of colors. If the color number already exists, one has to extract it from the list and redefine the RGB values. This may be done for example with:

root[] color=(TColor*)(gROOT->GetListOfColors()->At(index_color))
root[] color->SetRGB(r,g,b)

Where r, g and b go from 0 to 1 and index_color is the color number you wish to change.

The user interface for changing the fill color and style looks like shown in this picture. It takes place in the editor frame anytime the selected object inherits the class TAttFill.

#### 9.6.4.1 Color Palette (for Histograms)

Defining one color at a time may be tedious. The histogram classes (see Draw Options) use the color palette. For example, TH1::Draw("col") draws a 2-D histogram with cells represented by a box filled with a color CI function of the cell content. If the cell content is N, the color CI used will be the color number in colors[N]. If the maximum cell content is >ncolors, all cell contents are scaled to ncolors. The current color palette does not have a class or global object of its own. It is defined in the current style as an array of color numbers. The current palette can be changed with:

TStyle::SetPalette(Int_t ncolors,Int_t*color_indexes).

By default, or if ncolors <= 0, a default palette (see above) of 50 colors is defined. The colors defined in this palette are good for coloring pads, labels, and other graphic objects. If ncolors > 0 and colors = 0, the default palette is used with a maximum of ncolors. If ncolors == 1 && colors == 0, then a pretty palette with a spectrum Violet->Red is created. It is recommended to use this pretty palette when drawing lego(s), surfaces or contours. For example, to set the current palette to the “pretty” one, do:

root[] gStyle->SetPalette(1)

A more complete example is shown below. It illustrates the definition of a custom palette. You can adapt it to suit your needs. In case you use it for contour coloring, with the current color/contour algorithm, always define two more colors than the number of contours.

void palette() {
// Example of creating new colors (purples)
const Int_t colNum = 10;    // and defining of a new palette
Int_t palette[colNum];
for (Int_t i=0; i<colNum; i++) {
// get the color and if it does not exist create it
if (! gROOT->GetColor(230+i) ){
TColor *color =
new TColor(230+i,1-(i/((colNum)*1.0)),0.3,0.5,"");
} else {
TColor *color = gROOT->GetColor(230+i);
color->SetRGB(1-(i/((colNum)*1.0)),0.3,0.5);
}
palette[i] = 230+i;
}
gStyle->SetPalette(colNum,palette);
TF2 *f2 = new TF2("f2","exp(-(x^2)-(y^2))",-3,3,-3,3);
// two contours less than the number of colors in palette
f2->SetContour(colNum-2);
f2->Draw("cont");
}

Since ROOT 6.26, you can also define a palette based on an ASCII text file, using TColor::CreateColorTableFromFile("filename.txt") or gStyle->SetPalette("filename.txt"). The input file contains one color per line in “r g b” float format. This function is useful to profit from a full set of colour-vision deficiency friendly and perceptually uniform colour maps that are available to download

## 9.7 The Graphics Editor

A new graphics editor took place in ROOT v4.0. The editor can be activated by selecting the Editor menu entry in the canvas View menu or one of the context menu entries for setting line, fill, marker or text attributes. The following object editors are available for the current ROOT version.

### 9.7.1 TAxisEditor

This user interface gives the possibility for changing the following axis attributes:

• color of the selected axis, the axis’ title and labels;

• the length of thick parameters and the possibility to set them on both axis sides (if +- is selected);

• to set logarithmic or linear scale along the selected axis with a choice for optimized or more logarithmic labels;

• primary, secondary and tertiary axis divisions can be set via the three number fields;

• the axis title can be added or edited and the title’s color, position, offset, size and font can be set interactively;

• the color, size, and offset of axis labels can be set similarly. In addition, there is a check box for no exponent choice, and another one for setting the same decimal part for all labels.

• It provides the following user interface:

• Fixed aspect ratio - can be set for pad resizing.

• Edit - sets pad or canvas as editable.

• Cross-hair - sets a cross hair on the pad.

• TickX - set ticks along the X axis.

• TickY - set ticks along the Y axis.

• GridX - set a grid along the X axis.

• GridY - set a grid along the Y axis.

• The pad or canvas border size can be set if a sunken or a raised border mode is

• selected; no border mode can be set too.

## 9.8 Copy and Paste

You can make a copy of a canvas using TCanvas::DrawClonePad. This method is unique to TCanvas. It clones the entire canvas to the active pad. There is a more general method TObject::DrawClone, which all objects descendent of TObject, specifically all graphic objects inherit. Below are two examples, one to show the use of DrawClonePad and the other to show the use of DrawClone.

### 9.8.1 Using the GUI

In this example we will copy an entire canvas to a new one with DrawClonePad. Run the script draw2dopt.C.

root[] .x tutorials/hist/draw2dopt.C

This creates a canvas with 2D histograms. To make a copy of the canvas follow the steps:

• Right-click on it to bring up the context menu

• Select DrawClonePad

This copies the entire canvas and all its sub-pads to a new canvas. The copied canvas is a deep clone, and all the objects on it are copies and independent of the original objects. For instance, change the fill on one of the original histograms, and the cloned histogram retains its attributes. DrawClonePad will copy the canvas to the active pad; the target does not have to be a canvas. It can also be a pad on a canvas.

If you want to copy and paste a graphic object from one canvas or pad to another canvas or pad, you can do so with DrawClone method inherited from TObject. All graphics objects inherit the TObject::DrawClone method. In this example, we create a new canvas with one histogram from each of the canvases from the script draw2dopt.C.

• Start a new ROOT session and execute the script draw2dopt.C

• Select a canvas displayed by the script, and create a new canvas c1 from the File menu.

• Make sure that the target canvas (c1) is the active one by middle clicking on it. If you do this step right after step 2, c1 will be active.

• Select the pad with the first histogram you want to copy and paste.

• Right click on it to show the context menu, and select DrawClone.

• Leave the option blank and hit OK.

Repeat these steps for one histogram on each of the canvases created by the script, until you have one pad from each type. If you wanted to put the same annotation on each of the sub pads in the new canvas, you could use DrawClone to do so. Here we added the date to each pad. The steps to this are:

• Create the label in on of the pads with the graphics editor.

• Middle-click on the target pad to make it the active pad

• Use DrawClone method of the label to draw it in each of the other panels.

The option in the DrawClone method argument is the Draw option for a histogram or graph. A call to TH1::DrawClone can clone the histogram with a different draw option.

### 9.8.2 Programmatically

To copy and paste the four pads from the command line or in a script you would execute the following statements:

root[] .x tutorials/hist/draw2dopt.C
root[] TCanvas c1("c1","Copy Paste",200,200,800,600);
root[] surfaces->cd(1); // get the first pad
root[] lego->cd(2);// get the next pad
root[] cont->cd(3);// get the next pad
root[] c2h->cd(4);// get the next pad
root[] // to draw the four clones
root[] c1->cd();
root[] p1->DrawClone();
root[] p2->DrawClone();
root[] p3->DrawClone();
root[] p4->DrawClone();

Note that the pad is copied to the new canvas in the same location as in the old canvas. For example if you were to copy the third pad of surf to the top left corner of the target canvas you would have to reset the coordinates of the cloned pad.

## 9.9 Legends

Legends for a graph are obtained with a TLegend object. This object points to markers, lines, boxes, histograms, graphs and represent their marker, line, fill attributes. Any object that has a marker or line or fill attribute may have an associated legend. A TLegend is a panel with several entries (class TLegendEntry) and is created by the constructor

TLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2,
const char *header, Option_t *option)

The legend is defined with default coordinates, border size and option. The legend coordinates (NDC) in the current pad are x1, y1, x2, y2. The default text attributes for the legend are:

• Alignment = 12 left adjusted and vertically centered

• Angle = 0 (degrees)

• Color = 1 (black)

• Size = calculate when number of entries is known

• Font = helvetica-medium-r-normal scalable font = 42, and bold = 62 for title

The title is a regular entry and supports TLatex. The default is no title (header = 0). The options are the same as for TPave; by default, they are “brand”. Once the legend box is created, one has to add the text with the AddEntry() method:

TLegendEntry* TLegend::AddEntry(TObject *obj,
const char *label,
Option_t *option)

The parameters are:

• *objis a pointer to an object having marker, line, or fill attributes (a histogram, or a graph)

• label is the label to be associated to the object

• option:

• “L” draw line associated with line attributes of obj, if obj inherits from TAttLine.

• “P” draw poly-marker associated with marker attributes of obj, if obj inherits TAttMarker.

• “F” draw a box with fill associated with fill attributes of obj, if obj inherits TAttFill.

One may also use the other form of the method AddEntry:

TLegendEntry* TLegend::AddEntry(const char *name,
const char *label,
Option_t *option)

Here name is the name of the object in the pad. Other parameters are as in the previous case. Next example shows how to create a legend:

leg = new TLegend(0.4,0.6,0.89,0.89);
leg->Draw();
// oops we forgot the blue line... add it after
"#sqrt{2#pi} P_{T} (#gamma) latex  formula","f");
leg->Draw();

Here fun1, fun2, fun3 and gr are pre-existing functions and graphs. You can edit the TLegend by right clicking on it.

## 9.10 The PostScript Interface

To generate a PostScript (or encapsulated PostScript) file for a single image in a canvas, you can:

• Select to print the canvas in the PostScript file format from the File menu / Save or Save As menu entries. By default, a PostScript file is generated, if you do not specify the file format.

• Click in the canvas area, near the edges, with the right mouse button and select the Print context menu entry. This will generate a file of canvas pointed to by c1. You can select the name of the PostScript file. If the file name is xxx.ps, you will generate a PostScript file named xxx.ps. If the file name is xxx.eps, you generate an encapsulated Postscript file instead. In your program (or script), you can type:

c1->Print("xxx.ps") // or
c1->Print("xxx.eps")

Next example prints the picture in the pad pointed by pad1.

pad1->Print("xxx.ps")

The TPad::Print method has a second parameter called option. Its value can be:

• 0 which is the default and is the same as “ps

• ps” a Postscript file is produced

• Portrait” a Postscript file is produced with Portrait orientation

• Landscape” a Postscript file is produced with Landscape orientation

• eps”an Encapsulated Postscript file

• Preview”an Encapsulated Postscript file with preview is produced

• gif” a Graphics Interchange Format file

• cxx” a C++ macro file is generated

• pdf”a Portable Document Format file

• xml” a eXtensible Mark-up Language file

• jpg”a Joint Photographic Experts Group file

• png” a Portable Network Graphics Format (PNG file)

• xpm” a X11 Pixel Map Format

• svg” a Scalable Vector Graphics file

• tiff” a Tagged-Image File Format

• root”a ROOT binary file is produced

You do not need to specify this second parameter; you can indicate by the filename extension what format you want to save a canvas in (i.e. canvas.ps, canvas.gif, canvas.C, etc).

The size of the PostScript picture, by default, is computed to keep the aspect ratio of the picture on the screen, where the size along x is always 20 cm. You can set the size of the PostScript picture before generating the picture with a command such as:

TPostScript myps("myfile.ps",111)
myps.Range(xsize,ysize);
object->Draw();
myps.Close();

The first parameter in the TPostScript constructor is the name of the file; the second one is the format option:

• 111 - ps portrait

• 112 - ps landscape

• 113 - eps

You can set the default paper size with:

gStyle->SetPaperSize(xsize,ysize);

You can resume writing again in this file with myps.Open(). Note that you may have several Post Script files opened simultaneously. Use TPostScript::Text(x,y,"string") to add text to a postscript file. This method writes the string in quotes into a PostScript file at position x, y in world coordinates.

### 9.10.1 Special Characters

The following characters have a special action on the PostScript file:

•  - go to Greek

• ' - go to special

• ~ - go to Zapf Dingbats

• ? - go to subscript

• ^ - go to superscript

• ! - go to normal level of script

• & - backspace one character

• # - end of Greek or end of ZapfDingbats

These special characters are printed as such on the screen. To generate one of these characters on the PostScript file, you must escape it with the escape character “@”. The use of these special characters is illustrated in several scripts referenced by the TPostScript constructor.

### 9.10.2 Writing Several Canvases to the Same PostScript File

The following sequence writes the canvas to “c1.ps” and closes the postscript file:

TCanvas c1("c1");
h1.Draw();
c1.Print("c1.ps");

If the Postscript file name finishes with “(”, the file remains opened (it is not closed). If the Postscript file name finishes with “)” and the file has been opened with “(”, the file is closed.

{
TCanvas c1("c1");
h1.Draw();
c1.Print("c1.ps("); // write canvas and keep the ps file open
h2.Draw();
c1.Print("c1.ps");  // canvas is added to "c1.ps"
h3.Draw();
c1.Print("c1.ps)"); // canvas is added to "c1.ps"
// and ps file is closed
}

The TCanvas::Print("file.ps(") mechanism is very useful, but it can be a little inconvenient to have the action of opening/closing a file being atomic with printing a page. Particularly if pages are being generated in some loop, one needs to detect the special cases of first and last page. The “[” and “]” can be used instead of “(” and “)” as shown in the next example.

c1.Print("file.ps[");      // no actual print; just open file.ps
for (i=0; i<10; ++i) {
// fill canvas for context i
...
c1.Print("file.ps");   // actually print canvas to file.ps
}  // end loop
c1.Print("file.ps]");     // no actual print; just close file.ps

The following script illustrates how to open a postscript file and draw several pictures. The generation of a new postscript page is automatic when TCanvas::Clear is called by object->Draw().

{
TFile f("hsimple.root");
TCanvas c1("c1","canvas",800,600);

//select PostScript  output type
Int_t type = 111;         //portrait  ps
// Int_t type = 112;      //landscape ps
// Int_t type = 113;      //eps

//create a PostScript  file and set the paper size
TPostScript ps("test.ps",type);
ps.Range(16,24);          //set x,y of printed page

//draw 3 histograms from file hsimple.root on separate pages
hpx->Draw();
c1.Update();              //force drawing in a script
hprof->Draw();
c1.Update();
hpx->Draw("lego1");
c1.Update();
ps.Close();
}

The next example does the same:

{
TFile f("hsimple.root");
TCanvas c1("c1","canvas",800,600);

//set x,y of printed page
gStyle->SetPaperSize(16,24);

//draw 3 histograms from file hsimple.root on separate pages
hpx->Draw();
c1->Print("test1.ps(", "Portrait");
hprof->Draw();
c1->Print("test1.ps");
hpx->Draw("lego1");
c1->Print("test1.ps)");
}

This following example shows two pages. The canvas is divided. TPostScript::NewPage must be called before starting a new picture. object->Draw does not clear the canvas in this case because we clear only the pads and not the main canvas. Note that c1->Update must be called at the end of the first picture.

{
TFile *f1 = new TFile("hsimple.root");
TCanvas *c1 = new TCanvas("c1");
TPostScript *ps = new TPostScript("file.ps",112);

// picture 1
c1->Divide(2,1);
ps->NewPage();
c1->cd(1);
hpx->Draw();
c1->cd(2);
hprof->Draw();

// picture 2
c1->Update();
ps->NewPage();
c1->cd(1);
hpxpy->Draw();
c1->cd(2);
ntuple->Draw("px");
c1->Update();
ps->Close();

// invoke PostScript  viewer
gSystem->Exec("gs file.ps");
}

The next one does the same:

{
TFile *f1 = new TFile("hsimple.root");
TCanvas *c1 = new TCanvas("c1");
c1->Divide(2,1);

// picture 1
c1->cd(1);
hpx->Draw();
c1->cd(2);
hprof->Draw();
c1->Print("test2.ps(", "Landscape");

// picture 2
c1->cd(1);
hpxpy->Draw();
c1->cd(2);
ntuple->Draw("px");
c1->Print("test2.ps)");
gSystem->Exec("gs file.ps");  // invoke PostScript  viewer
}

### 9.10.3 The Color Models

TPostScript (and TPDF) support two color models: RGB and CMYK. CMY and CMYK models are subtractive color models unlike RGB which is an additive. They are mainly used for printing purposes. CMY means Cyan Magenta Yellow to convert RGB to CMY it is enough to do: C=1-R, M=1-G and Y=1-B. CMYK has one more component K (black). The conversion from RGB to CMYK is:

 Double_t Black   = TMath::Min(TMath::Min(1-Red,1-Green),1-Blue);
Double_t Cyan    = (1-Red-Black)/(1-Black);
Double_t Magenta = (1-Green-Black)/(1-Black);
Double_t Yellow  = (1-Blue-Black)/(1-Black);

CMYK add the black component which allows to have a better quality for black printing. TPostScript (and TPDF) support the CMYK model. To change the color model use:

 gStyle->SetColorModelPS(c);
• c = 0 means TPostScript will use RGB color model (default)
• c = 1 means TPostScript will use CMYK color model

## 9.11 The PDF Interface

Like PostScript, PDF is a vector graphics output format allowing a very high graphics output quality. The functionalities provided by this class are very similar to those provided by TPostScript.

Compare to PostScript output, the PDF files are usually smaller because some parts of them can be compressed.

PDF also allows to define table of contents. This facility can be used in ROOT. The following example shows how to proceed:

{
TCanvas* canvas = new TCanvas("canvas");
TH1F* histo = new TH1F("histo","test 1",10,0.,10.);
histo->SetFillColor(2);
histo->Fill(2.);
histo->Draw();
canvas->Print("plots.pdf(","Title:One bin filled");
histo->Fill(4.);
histo->Draw();
canvas->Print("plots.pdf","Title:Two bins filled");
histo->Fill(6.);
histo->Draw();
canvas->Print("plots.pdf","Title:Three bins filled");
histo->Fill(8.);
histo->Draw();
canvas->Print("plots.pdf","Title:Four bins filled");
histo->Fill(8.);
histo->Draw();
canvas->Print("plots.pdf)","Title:The fourth bin content is 2");
}

## 9.12 Create or Modify a Style

All objects that can be drawn in a pad inherit from one or more attribute classes like TAttLine, TAttFill, TAttText, TAttMarker. When objects are created, their default attributes are taken from the current style. The current style is an object of the class TStyle and can be referenced via the global variable gStyle (in TStyle.h). See the class TStyle for a complete list of the attributes that can be set in one style.

ROOT provides several styles called:

• Default” - the default style

• Plain” - the simple style (black and white)

• Bold” - bolder lines

• Video” - suitable for html output or screen viewing

The “Default” style is created by:

TStyle *default = new TStyle("Default","Default Style");

The “Plain” style can be used if you want to get a “conventional” PostScript output or if you are working on a monochrome display. The following example shows how to create it.

TStyle *plain  = new TStyle("Plain",
"Plain Style(no colors/fill areas)");
plain->SetCanvasBorderMode(0);
plain->SetCanvasColor(0);
plain->SetTitleColor(0);
plain->SetStatColor(0);

You can set the current style by:

gROOT->SetStyle(style_name);

You can get a pointer to an existing style by:

TStyle *style = gROOT->GetStyle(style_name);

You can create additional styles by:

TStyle *st1 = new TStyle("st1","my style");
st1->Set...
st1->cd();  // this becomes now the current style gStyle

In your rootlogon.C file, you can redefine the default parameters via statements like:

gStyle->SetStatX(0.7);
gStyle->SetStatW(0.2);
gStyle->SetLabelOffset(1.2);
gStyle->SetLabelFont(72);

Note that when an object is created, its attributes are taken from the current style. For example, you may have created a histogram in a previous session and saved it in a file. Meanwhile, if you have changed the style, the histogram will be drawn with the old attributes. You can force the current style attributes to be set when you read an object from a file by calling ForceStyle before reading the objects from the file.

gROOT->ForceStyle();

When you call gROOT->ForceStyle() and read an object from a ROOT file, the object’s method UseCurrentStyle is called. The attributes saved with the object are replaced by the current style attributes. You call also call myObject->UseCurrentStyle() directly. For example if you have a canvas or pad with your histogram or any other object, you can force these objects to get the attributes of the current style by:

canvas->UseCurrentStyle();

The description of the style functions should be clear from the name of the TStyle setters or getters. Some functions have an extended description, in particular:

• TStyle::SetLabelFont

• TStyle::SetLineStyleString: set the format of dashed lines.

• TStyle::SetOptStat

• TStyle::SetPalette to change the colors palette

• TStyle::SetTitleOffset

• TStyle::SetOptDate(Int_t optdate) to support several date formats. If optdate is non-null, the current date/time will be printed in the canvas. The position of the date string can be controlled by: optdate = 10*format+mode

• mode = 1 the date is printed in the bottom/left corner

• mode = 2 date is printed in the bottom/right corner

• mode = 3 date is printed in the top/right corner

• format = 0 (default) date format is like: “Wed Sep 25 17:10:35 2002”

• format = 1 date format is: “2002-09-25”

• format = 2 date format is: “2002-09-25 17:10:35”

## 9.13 3D Viewers

ROOT provides several viewers capable of displaying 3D content:

• the Pad - simple line drawing using TPad and associated projection class TView;

• GL Viewer - high quality and performance viewer(See “The GL Viewer”);

• X3D viewer - simple legacy viewer (See “The X3D Viewer”);

• GL-in-pad - combination of basic GL viewer in TPad, with no hardware acceleration.

The X3D and GL viewers are created as external windows, associated with a pad, and displaying the same content as it. Only these external viewers are detailed here - for Pad (TPad, TView classes) you should refer to “Graphical Containers: Canvas and Pad” and the class definitions.

All viewers use a common architecture to publish 3D objects to the viewer - described in “Common 3D Viewer Architecture” below. In most cases, you will not need to use this, working instead with a package, such as the “The Geometry Package”, which provides comprehensive, high level functionality to create and place objects into complex 3D scenes, and uses the viewer architecture internally to show the result in your chosen viewer.

### 9.13.1 Invoking a 3D viewer

A 3D viewer can be created in a script by passing the appropriate option to Draw()when attaching the drawn object(s) to a pad. For a fuller explanation of pads, attaching objects with Draw() etc. refer to “Graphical Containers: Canvas and Pad”.

root[] myShapes->Draw("ogl");

Valid option strings are:

• ogl” : external GL viewer

• x3d”: external X3D viewer

• pad”: pad viewer

If no option is passed to Draw() then the “pad” is used by default. If you already have content in a pad, which you would like to display in one of the external viewers you can select from the canvas View menu / View With, and pick the viewer type.

Note: A current limitation means that when an external viewer is created the pad is no longer redrawn. When the external viewer is closed, clicking in the pad will refresh.

### 9.13.2 The GL Viewer

The GL Viewer uses <OpenGL®> (or compliant libraries such as ) to generate high quality, high-performance 3D renderings, with sophisticated lighting, materials and rendering styles for 3D scenes. Many users will be able to take advantage of hardware acceleration of the underlying OpenGL commands by their computer’s video card, resulting is considerable performance gains - up to interactive manipulation of 1000’s of complex shapes in real-time.

The GL Viewer is supported on all official ROOT platforms (assuming you have suitable <OpenGL®> libraries), and is the main 3D viewer, which development effort is concentrated upon. As OpenGL® is a trademark we refer to our viewer built on this technology as the ‘GL Viewer’. The code for it can be found under $ROOTSYS/gl. You can manipulate the viewer via the GUI or via the base TGLViewer object behind the interface. These are detailed below - see also $ROOTSYS/tutorials/gl/glViewerExercise.C.

#### 9.13.2.1 Projections Modes (Cameras)

The GL Viewer supports two basic types of camera, which affect how the 3D world is projected onto the 2D render area:

• Perspective: Objects are drawn with characteristic ‘foreshortening’ effect, where distant objects appear smaller than near ones. This is useful for obtaining a ‘real world’ views. The degree of foreshortening is affected by the current camera field of view (focal length of its ‘lens’) - see “Adjusting Cameras”.

• Orthographic: Distance from camera does not affect object size. These projections are useful for measurement or checking alignments, as the sizes and angles between objects are preserved.

You can select the active camera from the viewer’s Camera menu on the top menu bar. There are three perspective camera choices:

• Perspective (Floor XOZ) Default

• Perspective (Floor YOZ)

• Perspective (Floor XOY)

In each case the perspective camera is constrained to keep the chosen floor plane, defined by a pair of world axes, appearing level at all times - i.e. there is no banking of the ‘horizon’ that you experience when a plane rolls. There are also three orthographic camera choices:

• Orthographic (XOY)

• Orthographic (XOZ)

• Orthographic (ZOY)

Orthographic projections are generally constrained to look down one of the global axes of the world, with the other two axes lying horizontal/vertical on the viewer window. Therefore, XOY has the X-axis horizontal, the Y-axis vertical. You can always confirm the orientation and constraints of the camera in the world by enabling axis drawing in the “Guides” tab - see sections “Guides” and “Clipping” below. For orthographic camera a ruler-depicting current scene units is also available.

You can also pick the current camera by obtaining a handle to the GL Viewer object behind the interface:

TGLViewer * v = (TGLViewer *)gPad->GetViewer3D();

calling the method TGLViewer::SetCurrentCamera with one of the TGLViewer::ECameraType types:

v->SetCurrentCamera(TGLViewer::kCameraPerspXOZ);

See also ROOTSYS/tutorials/gl/glViewerExercise.C. #### 9.13.2.2 Adjusting Cameras The interactions with the camera are summarized above. In each case the interaction is listed, along with description and user actions required to achieve it. For all cameras you can reset the original default view, framing the entire scene, by double clicking any mouse button. For the Zoom interaction you can use the following modifiers combinations to adjust the sensitivity: • Shiftx 10 • Ctrlx 0.1 • Shift + Ctrlx 0.01 The modifiers must be applied after the zoom action has started (right mouse button is down). Note for orthographic cameras: • There is no field of view of view/focal length - dollying and zooming producing an identical scaling action. • There is a fixed eye direction - so the ‘Orbit’ action is disabled. Note for perspective cameras: • Dollying (moving the camera backwards/forwards) and zooming are often confused, and may appear very similar. • When you dolly the camera the lens focal length does not change, hence the distortions associated with the projections are unaffected. However the movement can result in objects coming ‘through the front’ of the camera and disappearing. • When you zoom, the camera does not move - hence clipping of near objects is unaffected. However with extremely small zooms (FOV large/focal length short) noticeable distortions, causing straight lines to become curved, can be seen with objects near the camera - the ‘fisheye’ lens effect. • Generally dollying is more ‘natural’, but you may need to use both to achieve the desired perspective and eye position - particularly when you are working inside or very close to 3D objects. Configure the camera by calling the methods SetPerspectiveCamera() or SetOrthographicCamera() of TGLViewer: TGLViewer * v = (TGLViewer *)gPad->GetViewer3D(); v->SetOrthoCamera(TGLViewer::kCameraOrthoXOY, left,right,top,bottom); ... v->SetPerspectiveCamera (camera,fov,dolly,center,hRotate,vRotate); Note - you can configure any of the six cameras in the viewer at any time, but you will not see the result until the camera is made current. #### 9.13.2.3 Draw Styles The GL Viewer supports three different rendering modes, which are applied to all the objects in your scene, but not Clip Shapes and Guides (See “Clipping” and “Manipulators”). These are shown below, along with the key used to activate the style. Filled Polygons Wireframe Outline Enable with ‘r’ key Enable with ‘w’ key Enable with ‘t’ key Solid polygons, with hidden surface Object edges in color, with Combination of Filled Polygons removal, color surface materials, no surface filling/hiding. and Outline styles. Solid opacity, specular reflection etc. shapes with edges. Black background. Black background. White background. Call method TGLViewer::SetStyle with one of TGLRnrCtx::EDrawStyleflags kFill, kOutline, kWireFrame: v->SetStyle(TGLRnrCtx::kFill); #### 9.13.2.4 Lighting / Style The GL viewer creates five diffuse lights (left, right, top, bottom, and front) arranged around the 3D scene. These lights are carried with the camera - that is they are always in same position relative to your eye - the left light always shines from the left. Light controls are located: Viewer Controls Pane ‘Style’. Each light has a checkbox to enable/disable it. Set lights on/off with TGLLightSet::SetLight e.g. v->GetLightSet()->SetLight(TGLLightSet::kLightBottom, kFALSE); #### 9.13.2.5 Clipping The GL viewer supports interactive clipping, enabling you to remove sections of your 3D scene and the shapes, revealing internal details. The controls for clipping can be found under: Viewer Controls Pane ‘Clipping’ tab. Two clipping ‘shapes’ are currently supported: • Single plane • Box Pick the type from the radio buttons - only one (or none) may be active at one time. The clip object can be adjusted by: • Adjusting the values in the properties panel GUI • Directly manipulating the clip object in the viewer To show and/or directly manipulate the object check the ‘Show / Edit in Viewer’ checkbox. The clip object is drawn in semi-transparent light brown. The current manipulator is attached to it, allowing you direct control over its position, scale and rotation. See “Manipulators” section below for details on using viewer manipulators. The clip plane is described by the standard plane equation: ax+by+cz+d=0, where the factors a, b, c, d are entered into the edit boxes, and applied using the ‘Apply’ button. The clip box is described by its center position, entered in the ‘Center X’, ‘Center Y’ and ‘Center Z’ edit boxes, and its lengths (extents) entered in the ‘Length X’, ‘Length Y’ and ‘Length Z’ edit boxes. This clipping is achieved using OpenGL clip plane support; as such, there are certain limitations: • Solid shapes are not capped - they appear hollow. • Only shapes, which can be described with combination of planes, can be rendered in this fashion - e.g. a clipping tube is not possible. • Each additional clipping plane requires an additional render pass - so the more active planes the more time the render will take. Set the current clip object with TGLClipSet::SetClipType v->GetClipSet()->SetClipType(TGLClipSet::kClipPlane); Configure the clip object with TGLClipSet::SetClipState Double_t planeEq[4] = {0.5,1.0,-1.0, 2.0}; v->GetClipSet()->SetClipState(TGLClipSet::kClipPlane, planeEq); As with cameras, any clip can be configured at any time, but you must set the clip current to see the effect. #### 9.13.2.6 Manipulators Manipulators are GUI ‘widgets’ or controls attached to a 3D object in the viewer, allowing a direct manipulation of the object’s geometry. There are three manipulators for the three basic geometries transformations. In each case, the manipulator consists of three components, one for each local axis of the object, shown in standard colors: red (X), green (Y) and blue (Z). Activate the manipulator by moving the mouse over one of these components (which turns yellow to indicate active state). Click with left mouse and drag this active component to perform the manipulation. Toggle between the manipulator types using the ‘x’, ‘c’, ‘v’ keys while the mouse cursor is above the manipulator. Note: Manipulators cannot be controlled via the API at present. #### 9.13.2.7 Guides Guides are visual aids drawn into the viewer world. Controls for these are under the “Guides” tab: Viewer Controls Pane Guides Tab Axes show the world (global) frame coordinatedirections: X (red), Y (green) and Z (blue). The negative portion of the axis line is shown in dark color, the positive in bright. The axis name and minimum / maximum values are labeled in the same color. There are three options for axes drawing - selected by radio buttons: • None - not drawn (default). • Edge - draw axes on the (minimum) edge of the scene extents box. • Origin - drawn axes through the origin. For edge axes, the zero value for each axis is marked on the axis line with a colored sphere. For origin axes, a single white sphere is shown at the origin. Edge axes are depth clipped - i.e. are obscured by 3D objects in front of them. Origin axes (which generally pass through the middle of the 3D scene) are not depth clipped - so always visible. A single orange sphere of fixed view port (window) size can be shown at any arbitrary position. Enable / disable the drawing with ‘Show’ checkbox. Enter X/Y/Z position in the edit boxes to set position. Initial position is at the center of the scene. Set the guides using TGLViewer::SetGuideState e.g. to enable edge axes, and enable a reference marker at world position 50, 60, 100: Double_t refPos[3] = {50.0,60.0,100.0}; v->SetGuideState(TGLUtil::kAxesEdge, kTRUE, refPos); #### 9.13.2.8 Selecting Scene Shapes You can select a single shape from your scene by pressing ‘Shift’ key, pointing and left clicking anywhere on the shape in the viewer. Selection is currently shown by drawing the shape-bounding box (not depth clipped) in white (polygon or wire frame render styles) or red (outline render style). Manipulators supported by the shape are drawn in red, green and blue while the non-supported ones are drawn in grey. To deselect a shape, either select another, or shift/click anywhere on the background (empty space) in the viewer. You cannot select Manipulators or Guides (Axes / Reference Marker). #### 9.13.2.9 Editing Shapes When a shape is selected, the viewer’s control pane shows the user interface that allows you to review and adjust the color and geometry properties of the shape. Note: At present modifications to the shapes are local to the viewer - they are not propagated back to external objects/client that published to the viewer. The changes are preserved only until the viewer is closed. In some cases, this will never be feasible as there is not a one-to-one correspondence between a shape in the viewer and a single external object in which the modification could be stored. #### 9.13.2.10 Colors / Style Viewer Controls Pane ‘Style’ tab. A full description of OpenGL materials, colors and lighting is beyond the scope of this document. You should refer to the OpenGL programming manual (Red Book) for a full discussion. In most cases adjustment of the Diffuse color material + Opacity/Shine properties is sufficient to achieve desired results. A shape has four-color materials (components): • Diffuse • Ambient • Specular • Emissive For each of these you can select the component via the radio buttons. Each component can have the red, green and blue values for the component adjusted via the sliders. You can apply this adjustment to the shape itself, or to all shapes sharing a common ‘family’. Shapes of the same family have external objects with the same TObject name string. You can also adjust the ‘Opacity’ and ‘Shine’ for the shapes materials via the sliders. #### 9.13.2.11 Geometry Viewer Controls Pane ‘Geometry’ tab. Review and modify the shapes X/Y/Z center and scaling factors via the edit boxes. Selection and editing of shapes is not available via the API at present. #### 9.13.2.12 Outputting Viewer Contents The current viewer rendering can be output to an external EPS or PDF, using the options under the ‘File’ menu on the top menu bar. The file is named ‘viewer.eps’ or ‘viewer.pdf’ and written to the current ROOT directory. ### 9.13.3 The X3D Viewer The X3D viewer is a fairly simple and limited viewer, capable of showing basic lines and polygons. It lacks the quality, performance and more advanced features of the GL Viewer, and additionally is not supported on Windows. It is not actively developed and you are encouraged to use the GL Viewer out of preference. The below table presents the main interactions - these are repeated in the Help dialog of the viewer. Action KeyActionKey Wireframe Mode wRotate about xx a Hidden Line Mode eRotate about yy b Hidden Surface Mode rRotate about zz c Move object down uAuto-rotate about x1 2 3 Move object up iAuto-rotate about y4 5 6 Move object left lAuto-rotate about z7 8 9 Move object right hToggle controls styleo Move object forward jToggle stereo displays Move object backward kToggle blue stereo viewd Adjust focus (stereo mode) [ ] { }Toggle double bufferf Rotate object Left mouse button down + move. ### 9.13.4 Common 3D Viewer Architecture The 3D Viewer Architecture provides a common mechanism for viewer clients to publish 3D objects to it. It enables: • Decoupling of producers (geometry packages etc) who model collection of 3D objects from consumers (viewers) which display them. • Producer code free of explicit drawing commands & viewer specific branching. • Support differing viewers and clients capabilities, e.g. • Mix of native (in viewer) shapes and generic client side tessellation. • Local/global frame object description • Bounding boxes • Placing copies sharing common geometry (logical/physical shapes). The architecture consists of: • TVirtualViewer3D interface: An abstract handle to the viewer, allowing client to add objects, test preferences etc. • TBuffer3D class hierarchy: Used to describe 3D objects (“shapes”) - filled /added by negotiation with viewer via TVirtualViewer3D. A typical interaction between viewer and client using these, taken from TGeoPainter is: TVirtualViewer3D * viewer = gPad->GetViewer3D(); // Does viewer prefer local frame positions? Bool_t localFrame = viewer->PreferLocalFrame(); // Perform first fetch of buffer from the shape and try adding it to the viewer const TBuffer3D &buffer = shape.GetBuffer3D(TBuffer3D::kCore | TBuffer3D::kBoundingBox | TBuffer3D::kShapeSpecific, localFrame); Int_t reqSections = viewer->AddObject(buffer, &addDaughters); // If the viewer requires additional sections fetch from the shape // (if possible) and add again if (reqSections != TBuffer3D::kNone) shape.GetBuffer3D(reqSections, localFrame); Together these allow clients to publish objects to any one of the 3D viewers free of viewer specific drawing code. They allow our simple x3d viewer, and considerably more sophisticated OpenGL one to both work with both geometry libraries (g3d and geom) efficiently. In addition to external viewers, created in separate windows, this architecture is also used by internal TPad drawing when it requires 3D projections. Publishing to a viewer consists of the following steps: 1- Create / obtain viewer handle. 2- Begin scene on viewer. 3- Fill mandatory parts of TBuffer3D describing object. 4- Add to viewer. 5- Fill optional parts of TBuffer3D as requested by viewer. [ …. repeat 3/4/5 as required for other/child objects] 6- End scene on viewer. You should attach the top-level node of your external geometry (or the manager) to a TPad object using TObject::Draw(), and perform the publishing to the viewer in your object’s TObject::Paint() overloaded method. See “Scene Rebuilds”, and example scripts, for more details. #### 9.13.4.1 Creating / Obtaining Viewer Handle External viewers are bound to a TPad object (this may be removed as a requirement in the future). You can create or obtain the current viewer handle via the method: TVirtualViewer3D * v = gPad->GetViewer3D("type"); Here the “type” string defines the viewer type - currently one of: • ogl” : External GL viewer • x3d”: External X3D viewer • pad”: Pad viewer If no type is passed (null string), and there is no current viewer, then the type is defaulted to “pad”. If no type is passed and there is a current viewer, then this is returned - hence once a viewer is created it can be obtained elsewhere by: TVirtualViewer3D * v = gPad->GetViewer3D(); #### 9.13.4.2 Opening / Closing Scenes Objects must be added to viewer between BeginScene() and EndScene() calls e.g. viewer->BeginScene(); // Add objects viewer ->EndScene(); These calls enable the viewer to suspend redraws, and perform internal caching/setup. If the object you attach to the pad derives from TAtt3D, then the pad will take responsibility for calling BeginScene() and EndScene() for you. You can always test if the scene is already open for object addition with: viewer->BuildingScene(); Note: the x3d viewer does not support rebuilding of scenes - objects added after the first Open/Close Scene pair will be ignored. #### 9.13.4.3 Describing Objects - Filling TBuffer3D The viewers behind the TVirtualViewer3D interface differ greatly in their capabilities e.g. • Some support native shape (e.g. spheres/tubes in OpenGL) and can draw these based on an abstract description. Others always require a tessellation description based on TBuffer3D’s kRaw / kRawSizes points/lines/segments sections. • Some need the 3D object positions in the master (world) frame, others can cope with local frames and a translation matrix to place the object. • Some require bounding boxes for objects - others do not. Similarly some viewer clients are only capable of providing positions in master frame, cannot provide bounding boxes etc. Additionally we do not want to incur the cost of expensive tessellation operations if the viewer does not require them. To cope with these variations the TBuffer3D objects are filled by negotiation with the viewer. TBuffer3D classes are conceptually divided into enumerated sections: kCore, kBoundingBox, kRaw - see the class diagram and the file TBuffer3D.h for more details. The TBuffer3D methods SectionsValid(), SetSectionsValid(), ClearSectionsValid() are used to test, set, clear these section validity flags e.g. buffer.SetSectionsValid(TBuffer3D::kShapeSpecific); ... if (buffer.SectionsValid(TBuffer3D:: kShapeSpecific)) { ... } The sections found in the base TBuffer3D (kCore/kBoundingBox/kRawSizes/kRaw) are sufficient to describe any tessellated shape in a generic fashion. An additional kShapeSpecific section is added in TBuffer3D derived classes, allowing a more abstract shape description (“a sphere of inner radius x, outer radius y”). This enables a viewer, which knows how to draw (tessellate) the shape itself to do so, while providing a generic fallback suitable for all viewers. The rules for client negotiation with the viewer are: • If suitable specialized TBuffer3D class exists, use it, otherwise use TBuffer3D. • Complete the mandatory kCore section. • Complete the kShapeSpecific section if applicable. • Complete the kBoundingBox if you can. • Pass this buffer to the viewer using one of the TBuffer3D::AddObject() methods. If the viewer requires more sections to be completed (kRaw/kRawSizes) TBuffer3D::AddObject() will return flags indicating which ones, otherwise it returns kNone. If requested, you must fill the buffer, mark these sections valid, and call TBuffer3D::AddObject again, to complete adding the object. For example, in out TGeo geometry package, in TGeoPainter::PaintShape, we perform the negotiation with viewer: TVirtualViewer3D * viewer = gPad->GetViewer3D(); if (shape.IsA() != TGeoCompositeShape::Class()) { // Does viewer prefer local frame positions? Bool_t localFrame = viewer->PreferLocalFrame(); // Perform first fetch of buffer from the shape and adding // it to the viewer const TBuffer3D &buffer = shape.GetBuffer3D(TBuffer3D::kCore | TBuffer3D::kBoundingBox | TBuffer3D::kShapeSpecific, localFrame); Int_t reqSections = viewer->AddObject(buffer, &addDaughters); // If the viewer requires additional sections fetch from the // shape (if possible) and add again if (reqSections != TBuffer3D::kNone) { shape.GetBuffer3D(reqSections, localFrame); viewer->AddObject(buffer, &addDaughters); } } The buffer is supplied/filled by the appropriate TShape::GetBuffer3D() and TShape::FillBuffer3D overloads e.g. for a sphere in TGeoSphere. const TBuffer3D &TGeoSphere::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const { // Fills a static 3D buffer and returns a reference. static TBuffer3DSphere buffer; // Filling of kBoundingBox is defered to TGeoBBox, and // kCore on up to TGeoShape TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame); // Complete kShapeSpecific section for sphere if (reqSections & TBuffer3D::kShapeSpecific) { buffer.fRadiusInner = fRmin; buffer.fRadiusOuter = fRmax; ... buffer.SetSectionsValid(TBuffer3D::kShapeSpecific); } // Complete kRawSizes section if (reqSections & TBuffer3D::kRawSizes) { ... buffer.SetSectionsValid(TBuffer3D::kRawSizes); } } // Complete kRaw tesselation section if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) { SetPoints(buffer.fPnts); // Transform points to master frame if viewer requires it // The fLocalFrame flag and translation matrix will have // already been set in TGeoShape::FillBuffer3D() as required if (!buffer.fLocalFrame) TransformPoints(buffer.fPnts, buffer.NbPnts()); SetSegsAndPols(buffer); buffer.SetSectionsValid(TBuffer3D::kRaw); } return buffer; } Note: • we use a static TBuffer3D derived object for efficiency - once the object is added the buffer can be reused. • kRawSize (the calculation of tessellation sizing required in buffer) and kRaw (the actual filling of tessellation) is split, as the X3D viewer requires two publication passes - one to establish the full tessellation capacity for all shapes, and another to actually add them. Splitting avoids having to do the expensive tessellation on the first pass. #### 9.13.4.4 Shape Specific TBuffer3D Derived Classes Currently we provide the following shape specific classes, which the GL Viewer can take advantage of (see TBuffer3D.h and TBuffer3DTypes.h) • TBuffer3DSphere - solid, hollow and cut spheres (GL Viewer only supports solid spheres at present - cut / hollow ones will be requested as tessellated objects by client.) • TBuffer3DTube - basic tube with inner/outer radius and length. • TBuffer3DTubeSeg - angle tube segment. • TBuffer3DCutTube - angle tube segment with plane cut ends. See the above example from TGeoSphere::GetBuffer3D and also equivalent functions in TGeoTube, TGeoTubeSeg and TGeoCtub. Anyone is free to add new TBuffer3D classes, but it should be clear that one or more viewers will require updating to be able to take advantage of them. Hence we only provide classes which existing viewers can benefit from. The number of native shapes in GL Viewer will be expanded in the future. #### 9.13.4.5 Master / Local Reference Frames The Core section of TBuffer3D contains two members relating to reference frames: • fLocalFrame: indicates if any positions in the buffer (bounding box and tessellation vertexes) are in local or master (world frame). • fLocalMaster: is a standard 4x4 translation matrix (OpenGL column major ordering) for placing the object into the 3D master frame. If fLocalFrame is false, fLocalMaster should contain an identity matrix. This is set by default, and can be reset using the TBuffer3D::SetLocalMasterIdentity() method. #### 9.13.4.6 Bounding Boxes You are not obliged to complete the kBoundingBox section, as any viewer requiring one internally (GL Viewer) will build it if you do not provide. However to do this the viewer will force you to provide the (expensive) raw tessellation, and the resulting box will be axis aligned with the overall scene, which is non-ideal for rotated shapes. As we need to support orientated (rotated) bounding boxes, TBuffer3D requires the 6 vertices of the box. We also provide a convenience function, TBuffer::SetAABoundingBox(), for simpler case of setting an axis aligned bounding box. The bounding box should be filled in same frame (local / master) as the rest of the TBuffer3D, and in accordance with fLocalFrame flag. A typical example from TGeoBBox::FillBuffer3D:  if (reqSections & TBuffer3D::kBoundingBox) { Double_t halfLengths[3] = { fDX, fDY, fDZ }; buffer.SetAABoundingBox(fOrigin, halfLengths); if (!buffer.fLocalFrame) { TransformPoints(buffer.fBBVertex[0], 8); } buffer.SetSectionsValid(TBuffer3D::kBoundingBox); } #### 9.13.4.7 Logical and Physical Objects Some viewers can support two types of object placement: • Add object as a single independent entity in the world reference frame - e.g. a sphere, radius r, at x, y, z. • Repeated placement (copying) in world frame of this locally unique piece of geometry (described in local reference frame) e.g. define a sphere S (radius r), place copy at x1, y1, z1, another copy at x2, y2, z2 etc. The second case is very typical in geometry packages, e.g. ROOT’s TGeo package, GEANT4 etc, where we have very large number repeated placements of relatively few unique “shapes”. Some viewers (GL Viewer only at present) are able to take advantage of this by identifying unique logical shapes from the fID logical ID member of TBuffer3D. If repeated addition of the same fID is found, the shape is cached already - and the costly tessellation does not need to be sent again. The viewer can also perform internal GL specific caching (display lists) with considerable performance gains in these cases. For this to work correctly the logical object in must be described in TBuffer3D in the local reference frame, complete with the local/master translation. In some cases you will not have a real object you can reasonably set TBuffer3D::fID to, or the object is recycled or temporary. To suppress internal caching in the GL Viewer in these cases, set TBuffer3D::fID to 0 (null). The viewer indicates it can support local frame objects through the TVirtualViewer3D interface method: PreferLocalFrame(). If this returns kTRUE you can make repeated calls to AddObject(), with TBuffer3D containing the same fID, and different fLocalMaster placements. For viewers supporting logical/physical objects, the TBuffer3D content refers to the properties of the logical object, with the exception of: • fLocalMaster transform • fColor • fTransparency attributes, which can be varied for each physical object. As a minimum requirement all clients must be capable of filling the raw tessellation of the object buffer, in the master reference frame. Conversely viewers must always be capable of displaying the object described by this buffer. If either does not meet this requirement the object may not be displayed. #### 9.13.4.8 Scene Rebuilds TBuffer3D::AddObject is not an explicit command to the viewer - it may for various reasons decide to ignore it: • It already has the object internally cached. • The object falls outside some ‘interest’ limits of the viewer camera. • The object is too small to be worth drawing. In all these cases TBuffer3D::AddObject() returns kNone, as it does for successful addition, indicating it does not require further information about this object. Hence you should not try to make any assumptions about what the viewer did with the object. The viewer may decide to force the client to rebuild (republish) the scene, obtaining a different collection of objects, if the internal viewer state changes .e.g. significant camera move. It does this presently by forcing a repaint on the attached TPad object - hence you should attach you master geometry object to the pad (via TObject::Draw()), and perform the publishing to the viewer in response to TObject::Paint(). #### 9.13.4.9 Physical IDs TVirtualViewer3D provides for two methods of object addition: virtual Int_t AddObject(const TBuffer3D &buffer, Bool_t * addChildren = 0) virtual Int_t AddObject(UInt_t physicalID, const TBuffer3D & buffer, Bool_t *addChildren = 0) If you use the first (simple) case a viewer using logical/physical pairs will generate sequential IDs for each physical object internally. Scene rebuilds will require destruction and recreation of all physical objects. For the second you can specify an identifier from the client side, which must be unique and stable - i.e. the IDs of a published object is consistent, regardless of changes in termination of contained child geometry branches. In this case the viewer can safely cache the physical objects across scene rebuilds, discarding those no longer of interest. #### 9.13.4.10 Child Objects In many geometries there is a rigid containment hierarchy, and so if the viewer is not interested in a certain object due to limits/size then it will also not be interest in any of the contained branch of siblings. Both TBuffer3D::AddObject() methods have an addChildren return parameter. The viewer will complete this (if passed) indicating if children of the object just sent are worth sending. #### 9.13.4.11 Recycling TBuffer3D Once add TBuffer3D::AddObject() has been called, the contents are copied to the viewer’s internal data structures. You are free to destroy this TBuffer3D, or recycle it for the next object if suitable. #### 9.13.4.12 Examples For an example of a simple geometry, working in master reference frame examine the code under ROOTSYS/g3d. For a more complex example, which works in both master and local frames, and uses logical/physical division of shape geometry and placement, examine the code under $ROOTSYS/geom - in particular TGeoShape hierarchy, and the painter object TGeoPainter (under geopainter) where the negotiation with the viewer is performed. # 10 Folders and Tasks ## 10.1 Folders A TFolder is a collection of objects visible and expandable in the ROOT object browser. Folders have a name and a title and are identified in the folder hierarchy by an “UNIX-like” naming convention. The base of all folders is //root. It is visible at the top of the left panel in the browser. The browser shows several folders under //root. New folders can be added and removed to/from a folder. ## 10.2 Why Use Folders? One reason to use folders is to reduce class dependencies and improve modularity. Each set of data has a producer class and one or many consumer classes. When using folders, the producer class places a pointer to the data into a folder, and the consumer class retrieves a reference to the folder. The consumer can access the objects in a folder by specifying the path name of the folder. Here is an example of a folder’s path name: //root/Event/Hits/TCP One does not have to specify the full path name. If the partial path name is unique, it will find it; otherwise it will return the first occurrence of the path. The first diagram shows a system without folders. The objects have pointers to each other to access each other’s data. Pointers are an efficient way to share data between classes. However, a direct pointer creates a direct coupling between classes. This design can become a very tangled web of dependencies in a system with a large number of classes. In the second diagram, a reference to the data is in the folder and the consumers refer to the folder rather than each other to access the data. The naming and search service provided by the ROOT folders hierarchy provides an alternative. It loosely couples the classes and greatly enhances I/O operations. In this way, folders separate the data from the algorithms and greatly improve the modularity of an application by minimizing the class dependencies. In addition, the folder hierarchy creates a picture of the data organization. This is useful when discussing data design issues or when learning the data organization. The example below illustrates this point. ## 10.3 How to Use Folders Using folders means to build a hierarchy of folders, posting the reference to the data in the folder by the producer, and creating a reference to the folder by the user. ### 10.3.1 Creating a Folder Hierarchy To create a folder hierarchy you add the top folder of your hierarchy to //root. Then you add a folder to an existing folder with the TFolder::AddFolder method. This method takes two parameters: the name and title of the folder to be added. It returns a pointer of the newly created folder. The code below creates the folder hierarchy shown in the browser. In this macro, the folder is also added to the list of browsable. This way, it is visible in the browser on the top level. { // Add the top folder of my hierary to //root TFolder *aliroot=gROOT->GetRootFolder()->AddFolder("aliroot", "aliroot top level folders"); // Add the hierarchy to the list of browsables gROOT->GetListOfBrowsables()->Add(aliroot,"aliroot"); // Create and add the constants folder TFolder *constants=aliroot->AddFolder("Constants", "Detector constants"); // Create and add the pdg folder to pdg TFolder *pdg = constants->AddFolder("DatabasePDG","PDG database"); // Create and add the run folder TFolder *run = aliroot->AddFolder("Run","Run dependent folders"); // Create and add the configuration folder to run TFolder *configuration = run->AddFolder("Configuration", "Run configuration"); // Create and add the run_mc folder TFolder *run_mc = aliroot->AddFolder("RunMC", "MonteCarlo run dependent folders"); // Create and add the configuration_mc folder to run_mc TFolder *configuration_mc = run_mc->AddFolder("Configuration", "MonteCarlo run configuration"); } ### 10.3.2 Posting Data to a Folder (Producer) A TFolder can contain other folders as shown above or any TObject descendents. In general, users will not post a single object to a folder; they will store a collection or multiple collections in a folder. For example, to add an array to a folder: TObjArray *array; run_mc->Add(array); ### 10.3.3 Reading Data from a Folder (Consumer) One can search for a folder or an object in a folder using the TROOT::FindObjectAny method. It analyzes the string passed as its argument and searches in the hierarchy until it finds an object or folder matching the name. With FindObjectAny, you can give the full path name, or the name of the folder. If only the name of the folder is given, it will return the first instance of that name. A string-based search is time consuming. If the retrieved object is used frequently or inside a loop, you should save a pointer to the object as a class data member. Use the naming service only in the initialization of the consumer class. When a folder is deleted, any reference to it in the parent or other folder is deleted also.  conf=(TFolder*)gROOT->FindObjectAny("/aliroot/Run/Configuration"); // or ... conf=(TFolder*)gROOT->FindObjectAny("Configuration"); By default, a folder does not own the object it contains. You can overwrite that with TFolder::SetOwner. Once the folder is the owner of its contents, the contents are deleted when the folder is deleted. Some ROOT objects are automatically added to the folder hierarchy. For example, the following folders exist on start up: //root/ROOT Files with the list of open Root files //root/Classes with the list of active classes //root/Geometries with active geometries //root/Canvases with the list of active canvases //root/Styles with the list of graphics styles //root/Colors with the list of active colors For example, if a file myFile.root is added to the list of files, one can retrieve a pointer to the corresponding TFile object with a statement like:  TFile *myFile = (TFile*)gROOT->FindObjectAny( "/ROOTFiles/myFile.root"); //or... TFile *myFile = (TFile*)gROOT->FindObjectAny("myFile.root"); ## 10.4 Tasks Tasks can be organized into a hierarchy and displayed in the browser. The TTask class is the base class from which the tasks are derived. To give task functionality, you need to subclass the TTask class and override the Exec method. An example of TTask subclassesis$ROOTSYS/tutorials/MyTasks.cxx. The script that creates a task hierarchy and adds it to the browser is $ROOTSYS/tutorials/tasks.C. Here is a part of MyTasks.cxx that shows how to subclass from TTask. // A set of classes deriving from TTask see macro tasks.C. The Exec // function of each class prints one line when it is called. #include "TTask.h" class MyRun : public TTask { public: MyRun() { ; } MyRun(const char *name,const char *title); virtual ~MyRun() { ; } void Exec(Option_t *option=""); ClassDef(MyRun,1) // Run Reconstruction task }; class MyEvent : public TTask { public: MyEvent() { ; } MyEvent(const char *name,const char *title); virtual ~MyEvent() { ; } void Exec(Option_t *option=""); ClassDef(MyEvent,1) // Event Reconstruction task }; Later in MyTasks.cxx, we can see examples of the constructor and overridden Exec() method: ClassImp(MyRun) MyRun::MyRun(const char *name,const char *title):TTask(name,title) { ... } void MyRun::Exec(Option_t *option) { printf("MyRun executingn"); } Each TTask derived class may contain other TTasks that can be executed recursively. In this way, a complex program can be dynamically built and executed by invoking the services of the top level task or one of its subtasks. The constructor of TTask has two arguments: the name and the title. This script creates the task defined above, and creates a hierarchy of tasks. // Show the tasks in a browser. To execute a Task, select // "ExecuteTask" in the context menu see also other functions in the // TTask context menu, such as: // -setting a breakpoint in one or more tasks // -enabling/disabling one task, etc void tasks() { gROOT->ProcessLine(".L MyTasks.cxx+"); TTask *run = new MyRun("run","Process one run"); TTask *event = new MyEvent("event","Process one event"); TTask *geomInit = new MyGeomInit("geomInit", "Geometry Initialisation"); TTask *matInit = new MyMaterialInit("matInit", "MaterialsInitialisation"); TTask *tracker = new MyTracker("tracker","Tracker manager"); TTask *tpc = new MyRecTPC("tpc","TPC Reconstruction"); TTask *its = new MyRecITS("its","ITS Reconstruction"); TTask *muon = new MyRecMUON("muon","MUON Reconstruction"); TTask *phos = new MyRecPHOS("phos","PHOS Reconstruction"); TTask *rich = new MyRecRICH("rich","RICH Reconstruction"); TTask *trd = new MyRecTRD("trd","TRD Reconstruction"); TTask *global = new MyRecGlobal("global","Global Reconstruction"); // Create a hierarchy by adding sub tasks run->Add(geomInit); run->Add(matInit); run->Add(event); event->Add(tracker); event->Add(global); tracker->Add(tpc); tracker->Add(its); tracker->Add(muon); tracker->Add(phos); tracker->Add(rich); tracker->Add(trd); // Add the top level task gROOT->GetListOfTasks()->Add(run); // Add the task to the browser gROOT->GetListOfBrowsables()->Add(run); new TBrowser; } Note that the first line loads the class definitions in MyTasks.cxx with ACLiC. ACLiC builds a shared library and adds the classes to the Cling dictionary. See “Adding a Class with ACLiC”. To execute a TTask, you call the ExecuteTask method. ExecuteTask will recursively call: • the TTask::Execmethod of the derived class; • the TTask::ExecuteTasks to execute for each task the list of its subtasks; If the top level task is added to the list of ROOT browsable objects, the tree of tasks can be seen in the ROOT browser. To add it to the browser, get the list of browsable objects first and add it to the collection.  gROOT->GetListOfBrowsables()->Add(run); The first parameter of the Add method is a pointer to a TTask, the second parameter is the string to show in the browser. If the string is left out, the name of the task is used. After executing, the script above the browser will look like in this figure. ## 10.5 Execute and Debug Tasks The browser can be used to start a task, set break points at the beginning of a task or when the task has completed. At a breakpoint, data structures generated by the execution up this point may be inspected asynchronously and then the execution can be resumed by selecting the “Continue” function of a task. A task may be active or inactive (controlled by TTask::SetActive). When a task is inactive, its sub tasks are not executed. A task tree may be made persistent, saving the status of all the tasks. # 11 Input/Output This chapter covers the saving and reading of objects to and from ROOT files. It begins with an explanation of the physical layout of a ROOT file. It includes a discussion on compression, and file recovery. Then we explain the logical file, the class TFile and its methods. We show how to navigate in a file, how to save objects and read them back. We also include a discussion on Streamers. Streamers are the methods responsible to capture an objects current state to save it to disk or send it over the network. At the end of the chapter is a discussion on the two specialized ROOT files: TNetFile and TWebFile. ## 11.1 The Physical Layout of ROOT Files A ROOT file is like a UNIX file directory. It can contain directories and objects organized in unlimited number of levels. It also is stored in machine independent format (ASCII, IEEE floating point, Big Endian byte ordering). To look at the physical layout of a ROOT file, we first create one. This example creates a ROOT file and 15 histograms, fills each histogram with 1000 entries from a Gaussian distribution, and writes them to the file. { char name[10], title[20]; TObjArray Hlist(0); // create an array of Histograms TH1F* h; // create a pointer to a histogram // make and fill 15 histograms and add them to the object array for (Int_t i = 0; i < 15; i++) { sprintf(name,"h%d",i); sprintf(title,"histo nr:%d",i); h = new TH1F(name,title,100,-4,4); Hlist.Add(h); h->FillRandom("gaus",1000); } // open a file and write the array to the file TFile f("demo.root","recreate"); Hlist.Write(); f.Close(); } The example begins with a call to the TFile constructor. This class is describing the ROOT file (that has the extension “.root”). In the next section, we will cover TFile in details. The last line of the example closes the file. To view its contents we need to open it again, and to create a TBrowser object by: root[] TFile f("demo.root") root[] TBrowser browser; You can check if the file is correctly opened by:  TFile f("demo.root"); if (f.IsZombie()) { cout << "Error opening file" << endl; exit(-1); } else { ... } Once we have the TFile object, we can call the TFile::Map() method to view the physical layout. The output prints the date/time, the start record address, the number of bytes in the record, the class name of the record and the compression factor. root[] f.Map() 20051208/124502 At:100 N=114 TFile 20051208/124502 At:214 N=413 TH1F CX = 2.35 20051208/124502 At:627 N=410 TH1F CX = 2.36 20051208/124502 At:1037 N=396 TH1F CX = 2.45 20051208/124502 At:1433 N=400 TH1F CX = 2.42 20051208/124502 At:1833 N=402 TH1F CX = 2.41 20051208/124502 At:2235 N=416 TH1F CX = 2.33 20051208/124502 At:2651 N=406 TH1F CX = 2.39 20051208/124502 At:3057 N=403 TH1F CX = 2.40 20051208/124502 At:3460 N=411 TH1F CX = 2.36 20051208/124502 At:3871 N=400 TH1F CX = 2.42 20051208/124502 At:4271 N=409 TH1F CX = 2.38 20051208/124502 At:4680 N=409 TH1F CX = 2.38 20051208/124502 At:5089 N=420 TH1F CX = 2.32 20051208/124502 At:5509 N=406 TH1F CX = 2.40 20051208/124502 At:5915 N=405 TH1F CX = 2.40 20051208/124503 At:6320 N=3052 StreamerInfo CX = 3.16 20051208/124503 At:9372 N=732 KeysList 20051208/124503 At:10104 N=53 FreeSegments 20051208/124503 At:10157 N=1 END Here we see the fifteen histograms (TH1F’s) with the first one starting at byte 148. We also see an entry TFile. You may notice that the first entry starts at byte 100. The first 100 bytes are taken by the file header. ### 11.1.1 The File Header This table shows the file header information. When fVersion is greater than 1000000, the file is a large file (> 2 GB) and the offsets will be 8 bytes long. The location in brackets are the location in the case of a large file.  Byte Value Name Description 1 -> 4 “root” Root file identifier 5 -> 8 fVersion File format version 9 -> 12 fBEGIN Pointer to first data record 13 -> 16 [13->20] fEND Pointer to first free word at the EOF 17 -> 20 [21->28] fSeekFree Pointer to FREE data record 21 -> 24 [29->32] fNbytesFree Number of bytes in FREE data record 25 -> 28 [33->36] nfree Number of free data records 29 -> 32 [37->40] fNbytesName Number of bytes in TNamed at creation time 33 -> 33 [41->41] fUnits Number of bytes for file pointers 34 -> 37 [42->45] fCompress Zip compression level 38 -> 41 [46->53] fSeekInfo Pointer to TStreamerInfo record 42 -> 45 [54->57] fNBytesInfo Number of bytes in TStreamerInfo record 46 -> 63 [58->75] fCompress Universal Unique ID The first four bytes of the file header contain the string “root” which identifies a file as a ROOT file. Because of this identifier, ROOT is not dependent on the “.root” extension. It is still a good idea to use the extension, just for us to recognize them easier. The nfree and value is the number of free records. This variable along with FNBytesFree keeps track of the free space in terms of records and bytes. This count also includes the deleted records, which are available again. ### 11.1.2 The Top Directory Description The 84 bytes after the file header contain the top directory description, including the name, the date and time it was created, and the date and time of the last modification. 20010404/092347 At:64 N=84 TFile ### 11.1.3 The Histogram Records What follows are the 15 histograms, in records of variable length. 20010404/092347 At:148 N=380 TH1F CX = 2.49 20010404/092347 At:528 N=377 TH1F CX = 2.51 The first 4 bytes of each record is an integer holding the number of bytes in this record. A negative number flags the record as deleted, and makes the space available for recycling in the next writing. The rest of bytes in the header contain all the information to identify uniquely a data block on the file. It is followed by the object data. The next table explains the values in each individual record. If the key is located past the 32 bit file limit (> 2 GB) then some fields will be 8 bytes instead of 4 bytes (values between the brackets):  Byte Value Name Description 1 -> 4 Nbytes Length of compressed object (in bytes) 5 -> 6 Version TKey version identifier 7 -> 10 ObjLen Length of uncompressed object 11 -> 14 Datime Date and time when object was written to file 15 -> 16 KeyLen Length of the key structure (in bytes) 17 -> 18 Cycle Cycle of key 19 -> 22 [19->26] SeekKey Pointer to record itself (consistency check) 23 -> 26 [27->34] SeekPdir Pointer to directory header 27 -> 27 [35->35] lname Number of bytes in the class name 28 -> … [36->.. .] | ClassName | Object Class Name … -> … | lname | Number of bytes in the object name … -> … | Name | lName bytes with the name of the object … -> … | lTitle | Number of bytes in the object title … -> … | Title | Title of the object … -> … | DATA | Data bytes associated to the object You see a reference to TKey. It is explained in detail in the next section. ### 11.1.4 The Class Description List (StreamerInfo List) The histogram records are followed by the StreamerInfo list of class descriptions. The list contains the description of each class that has been written to file. 20010404/092347 At:5854 N=2390 StreamerInfo CX = 3.41 The class description is recursive, because to fully describe a class, its ancestors and object data members have to be described also. In demo.root, the class description list contains the description for: • TH1F • all classes in the TH1F inheritance tree • all classes of the object data members • all classes in the object data members’ inheritance tree. This description is implemented by the TStreamerInfo class, and is often referred to as simply StreamerInfo. You can print a file’s StreamerInfolist with the TFile::ShowStreamerInfo method. Below is an example of the output. Only the first line of each class description is shown. The demo.root example contains only TH1F objects. Here we see the recursive nature of the class description; it contains the StreamerInfoof all the classes needed to describe TH1F. root[] f.ShowStreamerInfo() StreamerInfo for class: TH1F, version=1 BASE TH1 offset=0 type= 0 1-Dim histogram base class BASE TArrayF offset=0 type= 0 Array of floats StreamerInfo for class: TH1, version=3 BASE TNamed offset=0 type=67 The basis for named object(name,title) BASE TAttLine offset=0 type=0 Line attributes BASE TAttFill offset=0 type=0 Fill area attributes BASE TAttMarker offset=0 type=0 Marker attributes Int_t fNcells offset=0 type=3 number bins(1D),cells(2D)+U/Overflows TAxis fXaxis offset=0 type=61 X axis descriptor TAxis fYaxis offset=0 type=61 Y axis descriptor TAxis fZaxis offset=0 type=61 Z axis descriptor Short_t fBarOffset offset=0 type=2 (1000*offset) for barcharts or legos Short_t fBarWidth offset=0 type=2 (1000*width) for bar charts or legos Stat_t fEntries offset=0 type=8 Number of entries//continued... Stat_t fTsumw offset=0 type=8 Total Sum of weights Stat_t fTsumw2 offset=0 type=8 Total Sum of squares of weights Stat_t fTsumwx offset=0 type=8 Total Sum of weight*X Stat_t fTsumwx2 offset=0 type=8 Total Sum of weight*X*X Double_t fMaximum offset=0 type=8 Maximum value for plotting Double_t fMinimum offset=0 type=8 Minimum value for plotting Double_t fNormFactor offset=0 type=8 Normalization factor TArrayD fContour offset=0 type=62 Array to display contour levels TArrayD fSumw2 offset=0 type=62 Array of sum of squares of weights TString fOption offset=0 type=65 histogram options TList* fFunctions offset=0 type=63 ->Pointer to list of functions(fits,user) StreamerInfo for class: TNamed, version=1 ... StreamerInfo for class: TAttLine, version=1 ... StreamerInfo for class: TAttFill, version=1 ... StreamerInfo for class: TAttMarker, version=1 ... StreamerInfo for class: TArrayF, version=1 ... StreamerInfo for class: TArray, version=1 ... StreamerInfo for class: TAxis, version=6 ... StreamerInfo for class: TAttAxis, version=4 ... ROOT allows a class to have multiple versions, and each version has its own description in form of a StreamerInfo. Above you see the class name and version number. The StreamerInfolist has only one description for each class/version combination it encountered. The file can have multiple versions of the same class, for example objects of old and new versions of a class can be in the same file. The StreamerInfois described in detail in the section on Streamers. ### 11.1.5 The List of Keys and the List of Free Blocks The last three entries on the output of TFile::Map() are the list of keys, the list of free segments, and the address where the data ends.. When a file is closed, it writes a linked list of keys at the end of the file. This is what we see in the third to the last entry. In our example, the list of keys is stored in 732 bytes beginning at byte# 8244. 20010404/092347 At:8244 N=732 KeysList 20010404/092347 At:8976 N=53 FreeSegments 20010404/092347 At:9029 N=1 END The second to last entry is a list of free segments. In our case, this starts 8976 and is not very long, only 53 bytes, since we have not deleted any objects. The last entry is the address of the last byte in the file. ### 11.1.6 File Recovery A file may become corrupted or it may be impossible to write it to disk and close it properly. For example if the file is too large and exceeds the disk quota, or the job crashes or a batch job reaches its time limit before the file can be closed. In these cases, it is imperative to recover and retain as much information as possible. ROOT provides an intelligent and elegant file recovery mechanism using the redundant directory information in the record header. If a file that has been not properly closed is opened again, it is scanned and rebuilt according to the information in the record header. The recovery algorithm reads the file and creates the saved objects in memory according to the header information. It then rebuilds the directory and file structure. If the file is opened in write mode, the recovery makes the correction on disk when the file is closed; however if the file is opened in read mode, the correction can not be written to disk. You can also explicitly invoke the recovery procedure by calling the TFile::Recover() method. You can recover the directory structure, but you cannot save what you recovered to the file on disk. In the following example, we interrupted and aborted the previous ROOT session, causing the file not to be closed. When we start a new session and attempt to open the file, it gives us an explanation and status on the recovery attempt. root[] TFile f("demo.root") Warning in <TFile::TFile>: file demo.root probably not closed, trying to recover successfully recovered 15 keys ## 11.2 The Logical ROOT File: TFile and TKey We saw that the TFile::Map() method reads the file sequentially and prints information about each record while scanning the file. It is not feasible to support only sequential access and hence ROOT provides random or direct access, i.e. reading a specified object at a time. To do so, TFile keeps a list of TKeys, which is essentially an index to the objects in the file. The TKey class describes the record headers of objects in the file. For example, we can get the list of keys and print them. To find a specific object on the file we can use the TFile::Get() method. root[] TFile f("demo.root") root[] f.GetListOfKeys()->Print() TKey Name = h0, Title = histo nr:0, Cycle = 1 TKey Name = h1, Title = histo nr:1, Cycle = 1 TKey Name = h2, Title = histo nr:2, Cycle = 1 TKey Name = h3, Title = histo nr:3, Cycle = 1 TKey Name = h4, Title = histo nr:4, Cycle = 1 TKey Name = h5, Title = histo nr:5, Cycle = 1 TKey Name = h6, Title = histo nr:6, Cycle = 1 TKey Name = h7, Title = histo nr:7, Cycle = 1 TKey Name = h8, Title = histo nr:8, Cycle = 1 TKey Name = h9, Title = histo nr:9, Cycle = 1 TKey Name = h10, Title = histo nr:10, Cycle = 1 TKey Name = h11, Title = histo nr:11, Cycle = 1 TKey Name = h12, Title = histo nr:12, Cycle = 1 TKey Name = h13, Title = histo nr:13, Cycle = 1 TKey Name = h14, Title = histo nr:14, Cycle = 1 root[] TH1F *h9 = (TH1F*)f.Get("h9"); The TFile::Get() finds the TKey object with name “h9”. Using the TKey info it will import in memory the object in the file at the file address #3352 (see the output from the TFile::Map above). This is done by the Streamer method that is covered in detail in a later section. Since the keys are available in a TList of TKeys we can iterate over the list of keys: { TFile f("demo.root"); TIter next(f.GetListOfKeys()); TKey *key; while ((key=(TKey*)next())) { printf("key: %s points to an object of class: %s at %dn", key->GetName(), key->GetClassName(),key->GetSeekKey()); } } The output of this script is: root[] .x iterate.C key: h0 points to an object of class: TH1F at 150 key: h1 points to an object of class: TH1F at 503 key: h2 points to an object of class: TH1F at 854 key: h3 points to an object of class: TH1F at 1194 key: h4 points to an object of class: TH1F at 1539 key: h5 points to an object of class: TH1F at 1882 key: h6 points to an object of class: TH1F at 2240 key: h7 points to an object of class: TH1F at 2582 key: h8 points to an object of class: TH1F at 2937 key: h9 points to an object of class: TH1F at 3293 key: h10 points to an object of class: TH1F at 3639 key: h11 points to an object of class: TH1F at 3986 key: h12 points to an object of class: TH1F at 4339 key: h13 points to an object of class: TH1F at 4694 key: h14 points to an object of class: TH1F at 5038 In addition to the list of keys, TFile also keeps two other lists: TFile::fFree is a TList of free blocks used to recycle freed up space in the file. ROOT tries to find the best free block. If a free block matches the size of the new object to be stored, the object is written in the free block and this free block is deleted from the list. If not, the first free block bigger than the object is used. TFile::fListHead contains a sorted list (TSortedList) of objects in memory. The diagram below illustrates the logical view of the TFile and TKey. ### 11.2.1 Viewing the Logical File Contents TFile is a descendent of TDirectory, which means it behaves like a TDirectory. We can list the contents, print the name, and create subdirectories. In a ROOT session, you are always in a directory and the directory you are in is called the current directory and is stored in the global variable gDirectory. Let us look at a more detailed example of a ROOT file and its role as the current directory. First, we create a ROOT file by executing a sample script. root[] .x$ROOTSYS/tutorials/hsimple.C

Now you should have hsimple.root in your directory. The file was closed by the script so we have to open it again to work with it. We open the file with the intent to update it, and list its contents.

root[] TFile f ("hsimple.root","UPDATE")
root[] f.ls()
TFile** hsimple.root
TFile* hsimple.root
KEY: TH1F hpx;1 This is the px distribution
KEY: TH2F hpxpy;1 py vs px
KEY: TProfile hprof;1 Profile of pz versus px
KEY: TNtuple ntuple;1 Demo ntuple

It shows the two lines starting with TFile followed by four lines starting with the word “KEY”. The four keys tell us that there are four objects on disk in this file. The syntax of the listing is:

KEY: <class> <variable>;<cycle number> <title>

For example, the first line in the list means there is an object in the file on disk, called hpx. It is of the class TH1F (one-dimensional histogram of floating numbers). The object’s title is “This is the px distribution”. If the line starts with OBJ, the object is in memory. The <class> is the name of the ROOT class (T-something). The <variable> is the name of the object. The cycle number along with the variable name uniquely identifies the object. The <title> is the string given in the constructor of the object as title.

The figure shows a TFile with five objects in the top directory (kObjA;1, kObjA;2, kObjB;1, kObjC;1 and kObjD;1). ObjA is on file twice with two different cycle numbers. It also shows four objects in memory (mObjE, mObjeF, mObjM, mObjL). It also shows several subdirectories.

### 11.2.2 The Current Directory

When you create a TFile object, it becomes the current directory. Therefore, the last file to be opened is always the current directory. To check your current directory you can type:

root[] gDirectory->pwd()
Rint:/

This means that the current directory is the ROOT session (Rint). When you create a file, and repeat the command the file becomes the current directory.

root[] TFile f1("AFile1.root");
root[] gDirectory->pwd()
AFile1.root:/

If you create two files, the last becomes the current directory.

root[] TFile f2("AFile2.root");
root[] gDirectory->pwd()
AFile2.root:/

To switch back to the first file, or to switch to any file in general, you can use the TDirectory::cd method. The next command changes the current directory back to the first file.

root[] f1.cd();
root[] gDirectory->pwd()
AFile1.root:/

Note that even if you open the file in “READ” mode, it still becomes the current directory. Cling also offers a shortcut for gDirectory->pwd() and gDirectory->ls(), you can type:

root[] .pwd
AFile1.root:/
root[] .ls
TFile**        AFile1.root
TFile*         AFile1.root

root[] gROOT->cd()
(unsigned char)1
root[] gROOT->pwd()
Rint:/

### 11.2.3 Objects in Memory and Objects on Disk

The TFile::ls() method has an option to list the objects on disk (“-d”) or the objects in memory (“-m”). If no option is given it lists both, first the objects in memory, then the objects on disk. For example:

root[] TFile *f = new TFile("hsimple.root");
root[] gDirectory->ls("-m")
TFile**         hsimple.root
TFile*         hsimple.root

Remember that gDirectory is the current directory and at this time is equivalent to “f”. This correctly states that no objects are in memory.

The next command lists the objects on disk in the current directory.

root[] gDirectory->ls("-d")
TFile**         hsimple.root
TFile*         hsimple.root
KEY: TH1F     hpx;1    This is the px distribution
KEY: TH2F     hpxpy;1  py vs px
KEY: TProfile hprof;1  Profile of pz versus px
KEY: TNtuple  ntuple;1 Demo ntuple

To bring an object from disk into memory, we have to use it or “Get” it explicitly. When we use the object, ROOT gets it for us. Any reference to hprof will read it from the file. For example drawing hprof will read it from the file and create an object in memory. Here we draw the profile histogram, and then we list the contents.

root[] hprof->Draw()
<TCanvas::MakeDefCanvas>: created default TCanvas with name c1
root[] f->ls()
TFile** hsimple.root
TFile* hsimple.root
OBJ: TProfile hprof Profile of pz versus px : 0
KEY: TH1F hpx;1 This is the px distribution
KEY: TH2F hpxpy;1 py vs px
KEY: TProfile hprof;1 Profile of pz versus px
KEY: TNtuple ntuple;1 Demo ntuple

We now see a new line that starts with OBJ. This means that an object of class TProfile, called hprof has been added in memory to this directory. This new hprof in memory is independent from the hprof on disk. If we make changes to the hprof in memory, they are not propagated to the hprof on disk. A new version of hprof will be saved once we call Write.

You may wonder why hprof is added to the objects in the current directory. hprof is of the class TProfile that inherits from TH1D, which inherits from TH1. TH1 is the basic histogram. All histograms and trees are created in the current directory (also see “Histograms and the Current Directory”). The reference to “all histograms” includes objects of any class descending directly or indirectly from TH1. Hence, our TProfile hprof is created in the current directory f.There was another side effect when we called the TH1::Draw method. ROOT printed this statement:

<TCanvas::MakeDefCanvas>: created default TCanvas with name c1

It tells us that a TCanvas was created and it named it c1. This is where ROOT is being nice, and it creates a canvas for drawing the histogram if no canvas was named in the draw command, and if no active canvas exists. The newly created canvas, however, is NOT listed in the contents of the current directory. Why is that? The canvas is not added to the current directory, because by default ONLY histograms and trees are added to the object list of the current directory. Actually, TEventList objects are also added to the current directory, but at this time, we don’t have to worry about those. If the canvas is not in the current directory then where is it? Because it is a canvas, it was added to the list of canvases.

This list can be obtained by the command gROOT->GetListOfCanvases()->ls(). The ls() will print the contents of the list. In our list, we have one canvas called c1. It has a TFrame, a TProfile, and a TPaveStats.

root[] gROOT->GetListOfCanvases()->ls()
Canvas Name=c1 Title=c1
Option=TCanvas fXlowNDC=0 fYlowNDC=0 fWNDC=1 fHNDC=1
Name= c1 Title= c1
Option=TFrame  X1= -4.000000 Y1=0.000000 X2=4.000000 Y2=19.384882
OBJ: TProfile hprof   Profile of pz versus px : 0
TPaveText  X1=-4.900000 Y1=20.475282 X2=-0.950000 Y2=21.686837 title
TPaveStats X1=2.800000  Y1=17.446395 X2=4.800000  Y2=21.323371 stats

Lets proceed with our example and draw one more histogram, and we see one more OBJ entry.

root[] hpx->Draw()
root[] f->ls()
TFile**         hsimple.root
TFile*         hsimple.root
OBJ: TProfile hprof    Profile of pz versus px : 0
OBJ: TH1F     hpx      This is the px distribution : 0
KEY: TH1F     hpx;1    This is the px distribution
KEY: TH2F     hpxpy;1  py vs px
KEY: TProfile hprof;1  Profile of pz versus px
KEY: TNtuple  ntuple;1 Demo ntuple

TFile::ls() loops over the list of objects in memory and the list of objects on disk. In both cases, it calls the ls() method of each object. The implementation of the ls method is specific to the class of the object, all of these objects are descendants of TObject and inherit the TObject::ls() implementation. The histogram classes are descendants of TNamed that in turn is a descent of TObject. In this case, TNamed::ls() is executed, and it prints the name of the class, and the name and title of the object. Each directory keeps a list of its objects in the memory. You can get this list by TDirectory::GetList(). To see the lists in memory contents you can do:

root[]f->GetList()->ls()
OBJ: TProfile   hprof   Profile of pz versus px : 0
OBJ: TH1F       hpx     This is the px distribution : 0

Since the file f is the current directory (gDirectory), this will yield the same result:

root[] gDirectory->GetList()->ls()
OBJ: TProfile   hprof   Profile of pz versus px : 0
OBJ: TH1F       hpx     This is the px distribution : 0

### 11.2.4 Saving Histograms to Disk

At this time, the objects in memory (OBJ) are identical to the objects on disk (KEY). Let’s change that by adding a fill to the hpx we have in memory.

root[] hpx->Fill(0)

Now the hpx in memory is different from the histogram (hpx) on disk. Only one version of the object can be in memory, however, on disk we can store multiple versions of the object. The TFile::Write method will write the list of objects in the current directory to disk. It will add a new version of hpx and hprof.

root[] f->Write()
root[] f->ls()
TFile**         hsimple.root
TFile*         hsimple.root
OBJ: TProfile hprof  Profile of pz versus px : 0
OBJ: TH1F     hpx    This is the px distribution : 0
KEY: TH1F     hpx;2  This is the px distribution
KEY: TH1F     hpx;1  This is the px distribution
KEY: TH2F     hpxpy;1 py vs px
KEY: TProfile hprof;2 Profile of pz versus px
KEY: TProfile hprof;1 Profile of pz versus px
KEY: TNtuple  ntuple;1        Demo ntuple

The TFile::Write method wrote the entire list of objects in the current directory to the file. You see that it added two new keys: hpx;2 and hprof;2 to the file. Unlike memory, a file is capable of storing multiple objects with the same name. Their cycle number, the number after the semicolon, differentiates objects on disk with the same name. If you wanted to save only hpx to the file, but not the entire list of objects, you could use the TH1::Writemethod of hpx:

root[] hpx->Write()

A call to obj->Write without any parameters will call obj->GetName() to find the name of the object and use it to create a key with the same name. You can specify a new name by giving it as a parameter to the Write method.

root[] hpx->Write("newName")

If you want to re-write the same object, with the same key, use the overwrite option.

root[] hpx->Write("",TObject::kOverwrite)

If you give a new name and use the kOverwrite, the object on disk with the matching name is overwritten if such an object exists. If not, a new object with the new name will be created.

root[] hpx->Write("newName",TObject::kOverwrite)

The Write method did not affect the objects in memory at all. However, if the file is closed, the directory is emptied and the objects on the list are deleted.

root[] f->Close()
root[] f->ls()
TFile**     hsimple.root
TFile*      hsimple.root

In the code snipped above, you can see that the directory is now empty. If you followed along so far, you can see that c1 which was displaying hpx is now blank. Furthermore, hpx no longer exists.

root[] hpx->Draw()
Error: No symbol hpx in current scope

This is important to remember, do not close the file until you are done with the objects or any attempt to reference the objects will fail.

### 11.2.5 Histograms and the Current Directory

When a histogram is created, it is added by default to the list of objects in the current directory. You can get the list of histograms in a directory and retrieve a pointer to a specific histogram.

   TH1F *h = (TH1F*)gDirectory->Get("myHist"); // or
TH1F *h = (TH1F*)gDirectory->GetList()->FindObject("myHist");

The method TDirectory::GetList() returns a TList of objects in the directory. You can change the directory of a histogram with the SetDirectory method.

   h->SetDirectory(newDir);

If the parameter is 0, the histogram is no longer associated with a directory.

   h->SetDirectory(0);

Once a histogram is removed from the directory, it will no longer be deleted when the directory is closed. It is now your responsibility to delete this histogram object once you are finished with it. To change the default that automatically adds the histogram to the current directory, you can call the static function:

   TH1::AddDirectory(kFALSE);

In this case, you will need to do all the bookkeeping for all the created histograms.

### 11.2.6 Saving Objects to Disk

In addition to histograms and trees, you can save any object in a ROOT file. For example to save a canvas to the ROOT file you can use either TObject::Write() or TDirectory::WriteTObject(). The example:

root[] c1->Write()

This is equivalent to:

root[] f->WriteTObject(c1)

For objects that do not inherit from TObject use:

root[] f->WriteObject(ptr,"nameofobject")

Another example:

root[] TFile *f = new TFile("hsimple.root","UPDATE")
root[] hpx->Draw()
<TCanvas::MakeDefCanvas>: created default TCanvas with name c1
root[] c1->Write()
root[] f->ls()
TFile**        hsimple.root
TFile*         hsimple.root
OBJ: TH1F      hpx      This is the px distribution : 0
KEY: TH1F     hpx;2   This is the px distribution
KEY: TH1F     hpx;1   This is the px distribution
KEY: TH2F     hpxpy;1 py vs px
KEY: TProfile hprof;2 Profile of pz versus px
KEY: TProfile hprof;1 Profile of pz versus px
KEY: TNtuple  ntuple;1   Demo ntuple
KEY: TCanvas  c1;1    c1

### 11.2.7 Saving Collections to Disk

All collection classes inherit from TCollection and hence inherit the TCollection::Write() method. When you call TCollection::Write() each object in the container is written individually into its own key in the file. To write all objects into one key you can specify the name of the key and use the optionTObject::kSingleKey. For example:

root[] TList * list = new TList;
root[] TNamed * n1, * n2;
root[] n1 = new TNamed("name1","title1");
root[] n2 = new TNamed("name2","title2");
root[] gFile->WriteObject(list,"list",TObject::kSingleKey);

### 11.2.8 A TFile Object Going Out of Scope

There is another important point to remember about TFile::Close and TFile::Write. When a variable is declared on the stack in a function such as in the code below, it will be deleted when it goes out of scope.

void foo() {
TFile f("AFile.root","RECREATE");
}

As soon as the function foohas finished executing, the variable f is deleted. When a TFile object is deleted an implicit call to TFile::Close is made. This will save only the file descriptor to disk. It contains the file header, the StreamerInfolist, the key list, the free segment list, and the end address. See “The Physical Layout of ROOT Files”. The TFile::Close does not make a call to Write(), which means that the objects in memory will not be saved in the file. You need to explicitly call TFile::Write() to save the object in memory to file before the exit of the function.

void foo() {
TFile f("AFile.root","RECREATE");
... stuff ...
f.Write();
}

To prevent an object in a function from being deleted when it goes out of scope, you can create it on the heap instead of on the stack. This will create a TFile object f, that is available on a global scope, and it will still be available when exiting the function.

void foo() {
TFile *f = new TFile("AFile.root","RECREATE");
}

### 11.2.9 Retrieving Objects from Disk

If you have a ROOT session running, please quit and start fresh.

We saw that multiple versions of an object with the same name could be in a ROOT file. In our example, we saved a modified histogram hpx to the file, which resulted in two hpx's uniquely identified by the cycle number: hpx;1 and hpx;2. The question is how we can retrieve the right version of hpx. When opening the file and using hpx, Cling retrieves the one with the highest cycle number. To read the hpx;1 into memory, rather than the hpx:2 we would get by default, we have to explicitly get it and assign it to a variable.

root[] TFile *f1 = new TFile("hsimple.root")
root[] TH1F *hpx1; f1->GetObject("hpx;1",hpx)
root[] hpx1->Draw()

The TDirectory class lets you organize its contents into subdirectories, and TFile being a descendent of TDirectory inherits this ability. Here is an example of a ROOT file with multiple subdirectories as seen in the ROOT browser. To add a subdirectory to a file use TDirectory::mkdir. The example below opens the file for writing and creates a subdirectory called “Wed011003”. Listing the contents of the file shows the new directory in the file and the TDirectory object in memory.

root[] TFile *f = new TFile("AFile.root","RECREATE")
root[] f->mkdir("Wed011003")
(class TDirectory*)0x1072b5c8
root[] f->ls()
TFile**         AFile.root
TFile*          AFile.root
TDirectory*           Wed011003       Wed011003
KEY: TDirectory       Wed011003;1     Wed011003

We can change the current directory by navigating into the subdirectory, and after changing directory; we can see that gDirectory is now “Wed011003”.

root[] f->cd("Wed011003")
root[] gDirectory->pwd()
AFile.root:/Wed011003

In addition to gDirectory we have gFile, another global that points to the current file. In our example, gDirectory points to the subdirectory, and gFile points to the file (i.e. the files’ top directory).

root[] gFile->pwd()
AFile.root:/

Use cd() without any arguments to return to the file’s top directory.

root[] f->cd()
AFile.root:/

Change to the subdirectory again, and create a histogram. It is added to the current directory, which is the subdirectory “Wed011003”.

root[] f->cd("Wed011003")
root[] TH1F *histo = new TH1F("histo","histo",10,0,10)
root[] gDirectory->ls()
TDirectory* Wed011003   Wed011003
OBJ: TH1F      histo   histo : 0

If you are in a subdirectory and you want to have a pointer to the file containing the subdirectory, you can do:

root[] gDirectory->GetFile()

If you are in the top directory gDirectory is the same as gFile. We write the file to save the histogram on disk, to show you how to retrieve it later.

root[] f->Write()
root[] gDirectory->ls()
TDirectory*             Wed011003       Wed011003
OBJ: TH1F      histo   histo : 0
KEY: TH1F      histo;1 histo

When retrieving an object from a subdirectory, you can navigate to the subdirectory first or give it the path name relative to the file. The read object is created in memory in the current directory. In this first example, we get histo from the top directory and the object will be in the top directory.

root[] TH1 *h; f->GetObject("Wed011003/histo;1",h)

If file is written, a copy of histo will be in the top directory. This is an effective way to copy an object from one directory to another. In contrast, in the code box below, histo will be in memory in the subdirectory because we changed the current directory.

root[] f->cd("Wed011003")
root[] TH1 *h; gDirectory->GetObject("histo;1",h)

Note that there is no warning if the retrieving was not successful. You need to explicitly check the value of h, and if it is null, the object could not be found. For example, if you did not give the path name the histogram cannot be found and the pointer to h is null:

root[] TH1 *h; gDirectory->GetObject("Wed011003/histo;1",h)
root[] h
(class TH1*)0x10767de0
root[] TH1 *h; gDirectory->GetObject("histo;1",h)
root[] h
(class TH1*)0x0

To remove a subdirectory you need to use TDirectory::Delete. There is no TDirectory::rmdir. The Delete method takes a string containing the variable name and cycle number as a parameter.

void Delete(const char *namecycle)

The namecycle string has the format name;cycle. The next are some rules to remember:

• name = * means all, but don’t remove the subdirectories

• cycle =* means all cycles (memory and file)

• cycle ="" means apply to a memory object

• cycle = 9999 also means apply to a memory object

• namecycle = "" means the same as namecycle =“T*”

• namecycle = T* delete subdirectories

For example to delete a directory from a file, you must specify the directory cycle:

root[] f->Delete("Wed011003;1")

Some other examples of namecycle format are:

• foo:delete the object named foo from memory

• foo;1: delete the cycle 1 of the object named foo from the file

• foo;*: delete all cycles of foo from the file and also from memory

• *;2: delete all objects with cycle number 2 from the file

• *;*: delete all objects from memory and from the file

• T*;*: delete all objects from memory and from the file including all subdirectories

## 11.3 Streamers

To follow the discussion on Streamers, you need to know what a simple data type is. A variable is of a simple data type if it cannot be decomposed into other types. Examples of simple data types are longs, shorts, floats, and chars. In contrast, a variable is of a composite data type if it can be decomposed. For example, classes, structures, and arrays are composite types. Simple types are also called primitive types, basic types, and Cling sometimes calls them fundamental types.

When we say, “writing an object to a file”, we actually mean writing the current values of the data members. The most common way to do this is to decompose (also called the serialization of) the object into its data members and write them to disk. The decomposition is the job of the Streamer. Every class with ambitions to be stored in a file has a Streamerthat decomposes it and “streams” its members into a buffer.

The methods of the class are not written to the file, it contains only the persistent data members. To decompose the parent classes, the Streamercalls the Streamerof the parent classes. It moves up the inheritance tree until it reaches an ancestor without a parent. To serialize the object data members it calls their Streamer. They in turn move up their own inheritance tree and so forth. The simple data members are written to the buffer directly. Eventually the buffer contains all simple data members of all the classes that make up this particular object. Data members that are references (as MyClass &fObj;) are never saved, it is always the responsibility of the object’s constructor to set them properly.

### 11.3.1 Automatically Generated Streamers

A Streamerusually calls other Streamers: the Streamerof its parents and data members. This architecture depends on all classes having Streamers, because eventually they will be called. To ensure that a class has a Streamer, rootcling automatically creates one in the ClassDef macro that is defined in $ROOTSYS/include/Rtypes.h. ClassDef defines several methods for any class, and one of them is the Streamer. The automatically generated Streameris complete and can be used as long as no customization is needed. The Event class is defined in $ROOTSYS/test/Event.h. Looking at the class definition, we find that it inherits from TObject. It is a simple example of a class with diverse data members.

class Event : public TObject {
private:
TDirectory    *fTransient;            //! current directory
Float_t     fPt;                   //! transient value
char           fType[20];
Int_t          fNtrack;
Int_t          fNseg;
Int_t          fNvertex;
UInt_t         fFlag;
Float_t        fTemperature;
TClonesArray  *fTracks;           //->
TH1F          *fH;                //->
Int_t          fMeasures[10];
Float_t        fMatrix[4][4];
Float_t       *fClosestDistance;  //[fNvertex]
...

The Event class is added to the dictionary by the rootcling utility. This is the rootcling statement in the $ROOTSYS/test/Makefile: @rootcling -f EventDict.cxx -c Event.h EventLinkDef.h The EventDict.cxx file contains the automatically generated Streamerfor Event: void Event::Streamer(TBuffer &R__b){ // Stream an object of class Event. if (R__b.IsReading()) { Event::Class()->ReadBuffer(R__b, this); } else { Event::Class()->WriteBuffer(R__b, this); } } When writing an Event object, TClass::WriteBuffer is called. WriteBuffer writes the current version number of the Event class, and its contents into the buffer R__b. The Streamercalls TClass::ReadBuffer when reading an Event object. The ReadBuffer method reads the information from buffer R__b into the Event object. ### 11.3.2 Transient Data Members (//!) To prevent a data member from being written to the file, insert a “!” as the first character after the comment marks. It tells ROOT not to save that data member in a root file when saving the class. For example, in this version of Event, the fPt and fTransient data members are not persistent. class Event : public TObject { private: TDirectory *fTransient; //! current directory Float_t fPt; //! transient value ... ### 11.3.3 The Pointer to Objects (//->) The string “->” in the comment field of the members *fH and *fTracks instruct the automatic Streamer to assume these will point to valid objects and the Streamerof the objects can be called rather than the more expensive R__b << fH. It is important to note that no check is done on the validity of the pointer value. In particular if the pointer points, directly or indirectly, back to the current object, this will result in an infinite recursion and the abrupt end of the process. TClonesArray *fTracks; //-> TH1F *fH; //-> ### 11.3.4 Variable Length Array When the Streamercomes across a pointer to a simple type, it assumes it is an array. Somehow, it has to know how many elements are in the array to reserve enough space in the buffer and write out the appropriate number of elements. This is done in the class definition. For example: class Event : public TObject { private: char fType[20]; Int_t fNtrack; Int_t fNseg; Int_t fNvertex; ... Float_t *fClosestDistance; //[fNvertex] The array fClosestDistance is defined as a pointer of floating point numbers. A comment mark (//), and the number in square brackets tell the Streamerthe length of the array for this object. In general the syntax is: <simple type> *<name>//[<length>] The length cannot be an expression. If a variable is used, it needs to be an integer data member of the class. It must be defined ahead of its use, or in a base class. The same notation also applies to variable length array of object and variable length array of pointer to objects. MyObject *obj; //[fNojbs] MyObject **objs; //[fDatas] ### 11.3.5 Double32_t Math operations very often require double precision, but on saving single usually precision is sufficient. For this purpose we support the typedef Double32_t which is stored in memory as a double and on disk as a float or integer. The actual size of disk (before compression) is determined by the parameter next to the data member declaration. For example: Double32_t m_data; //[min,max<,nbits>] If the comment is absent or does not contain min, max, nbits, the member is saved as a float. If min and max are present, they are saved with 32 bits precision. min and max can be explicit values or expressions of values known to Cling (e.g. pi). If nbits is present, the member is saved as int with nbits bits precision. For more details see the io tutorials double32.C. ### 11.3.6 Prevent Splitting (//|| ) If you want to prevent a data member from being split when writing it to a tree, append the characters || right after the comment string. This only makes sense for object data members. For example: EventHeader fEvtHdr; //|| do not split the header ### 11.3.7 Streamers with Special Additions Most of the time you can let rootcling generate a Streamer for you. However if you want to write your own Streameryou can do so. For some classes, it may be necessary to execute some code before or after the read or write block in the automatic Streamer. For example after the execution of the read block, one can initialize some non persistent members. There are two reasons why you would need to write your own Streamer: 1) if you have a non-persistent data member that you want to initialize to a value depending on the read data members; 2) if you want or need to handle the schema evolution on your own. Note that an alternative for those cases is to consider write a schema evolution rule. First, you need to tell rootcling not to build a Streamerfor you. The input to the rootcling command (in the makefile) is a list of classes in a LinkDef.h file. For example, the list of classes for Event is listed in $ROOTSYS/test/EventLinkDef.h. The “-” at the end of the class name tells rootcling not to generate a Streamer. In the example, you can see the Event class is the only one for which rootcling is instructed not to generate a Streamer.

#ifdef __ROOTCLING__

#endif
#pragma link C++ class EventHeader+;

The “+” sign tells rootcling to use the new Streamersystem introduced in ROOT 3.0. The following is an example of a customized Streamerfor Event. The Streamer takes a TBuffer as a parameter, and first checks to see if this is a case of reading or writing the buffer.

void Event::Streamer(TBuffer &R__b) {
fTransient = gDirectory;       //save current directory
fPt= TMath::Sqrt(fPx*fPx + fPy*fPy + fPz*fPz);
} else {
Event::Class()->WriteBuffer(R__b, this);
}
}

### 11.3.8 Writing Objects

The Streamer decomposes the objects into data members and writes them to a buffer. It does not write the buffer to a file, it simply populates a buffer with bytes representing the object. This allows us to write the buffer to a file or do anything else we could do with the buffer. For example, we can write it to a socket to send it over the network. This is beyond the scope of this chapter, but it is worthwhile to emphasize the need and advantage of separating the creation of the buffer from its use. Let us look how a buffer is written to a file. The dictionary for a class needs to be loaded before any object of that type can be saved.

The TObject::Write method does the following:

• Creates a TKey object in the current directory

• Creates a TBuffer object which is part of the newly created TKey

• Fills the TBuffer with a call to the class::Streamer method

• Creates a second buffer for compression, if needed

• Reserves space by scanning the TFree list. At this point, the size of the buffer is known.

• Writes the buffer to the file

• Releases the TBuffer part of the key

In other words, the TObject::Write calls the Streamer method of the class to build the buffer. The buffer is in the key and the key is written to disk. Once written to disk the memory consumed by the buffer part is released. The key part of the TKey is kept.

The key consumes about 60 bytes, whereas the buffer, since it contains the object data, can be very large.

### 11.3.9 Ignore Object Streamers

Your class can ignore the TObject Streamerwith the MyClass->Class::IgnoreObjectStreamer() method. When the class kIgnoreTObjectStreamerbit is set (by calling the IgnoreTObjectStreamermethod), the automatically generated Streamerwill not call TObject::Streamer, and the TObject part of the class is not streamed to the file. This is useful in case you do not use the TObject fBits and fUniqueIDdata members. You gain space on the file, and you do not loose functionality if you do not use the fBits and fUniqueID.See “The Role of TObject” on the use of fBits and fUniqueID.

### 11.3.10 Streaming a TClonesArray

When writing a TClonesArray it bypasses by default the Streamerof the member class and uses a more efficient internal mechanism to write the members to the file. You can override the default and specify that the member class Streameris used by setting the TClonesArray::BypassStreamer bit to false:

   TClonesArray *fTracks;
fTracks->BypassStreamer(kFALSE);    // use the member Streamer

When the kBypassStreamer bit is set, the automatically generated Streamercan call directly the method TClass::WriteBuffer. Bypassing the Streamer improves the performance when writing/reading the objects in the TClonesArray. However, the drawback is when a TClonesArray is written with split=0 bypassing the Streamer, the StreamerInfoof the class in the array being optimized, one cannot later use the TClonesArray with split > 0. For example, there is a problem with the following scenario: a class Foo has a TClonesArray of Bar objects the Foo object is written with split=0 to Tree T1. In this case the StreamerInfo for the class Bar is created in optimized mode in such a way that data members of the same type are written as an array improving the I/O performance. In a new program, T1 is read and a new Tree T2 is created with the object Foo in split > 1.

When the T2branch is created, the StreamerInfo for the class Bar is created with no optimization (mandatory for the split mode). The optimized Bar StreamerInfo is going to be used to read the TClonesArray in T1. The result will be Bar objects with data member values not in the right sequence. The solution to this problem is to call BypassStreamer(kFALSE) for the TClonesArray. In this case, the normal Bar::Streamer function will be called. The Bar::Streamer function works OK independently if the Bar StreamerInfohad been generated in optimized mode or not.

## 11.4 Pointers and References in Persistency

An object pointer as a data member presents a challenge to the streaming software. If the object pointed to is saved every time, it could create circular dependencies and consume a large amount of disk space. The network of references must be preserved on disk and recreated upon reading the file.

If you use independent I/O operations for pointers and their referenced objects you can use the TRef class. Later in this section is an example that compares disk space, memory usage, and I/O times of C++ pointers and TRefs. In general, a TRef is faster than C++ but the advantage of a C++ pointer is that it is already C++.

### 11.4.1 Streaming C++ Pointers

When ROOT encounters a pointer data member it calls the Streamer of the object and labels it with a unique object identifier. The object identifier is unique for one I/O operation. If there is another pointer to the object in the same I/O operation, the first object is referenced i.e. it is not saved again. When reading the file, the object is rebuilt and the references recalculated.

In this way, the network of pointers and their objects is rebuilt and ready to use the same way it was used before it was persistent. If the pointer hold the address of an object which in embedded in another object (as opposed to being pointed to by a pointer), the object will be duplicate at read time. To avoid this, make the pointer a transient data member.

### 11.4.2 Motivation for the TRef Class

If the object is split into several files or into several branches of one or more TTrees, standard C++ pointers cannot be used because each I/O operation will write the referenced objects, and multiple copies will exist. In addition, if the pointer is read before the referenced object, it is null and may cause a run time system error. To address these limitations, ROOT offers the TRef class.

TRef allows referencing an object in a different branch and/or in a different file. TRef also supports the complex situation where a TFile is updated multiple times on the same machine or a different machine. When a TRef is read before its referenced object, it is null. As soon as the referenced object is read, the TRef points to it. In addition, one can specify an action to be taken by TRef in the case it is read before its reference object (see“Action on Demand” below).

### 11.4.3 Using TRef

A TRef is a lightweight object pointing to any TObject. This object can be used instead of normal C++ pointers in case:

• The referenced object R and the pointer P are not written to the same file

• P is read before R

• R and P are written to different Tree branches

Below is a line from the example in $ROOTSYS/test/Event.cxx.  TRef fLastTrack; //pointer to last track ... Track *track = (Track*)fTracks->ConstructedAt(fNtrack++); track->Set(random); // Save reference to last Track in the collection of Tracks fLastTrack = track; The track and its reference fLastTrack can be written with two separate I/O calls in the same or in different files, in the same or in different branches of a TTree. If the TRef is read and the referenced object has not yet been read, TRef will return a null pointer. As soon as the referenced object will be read, TRef will point to it. ### 11.4.4 How Does It Work? A TRef is itself a TObject with an additional transient pointer fPID. When a TRef is used to point to a TObject*R, for example in a class with  TRef P; one can do:  P = R; //to set the pointer When the statement P = Ris executed, the following happens: • The pointer fPID is set to the current TProcessID (see below). • The current ObjectNumber (see below) is incremented by one. • R.fUniqueID is set to ObjectNumber. • In the fPID object, the element fObjects[ObjectNumber] is set to R • P.fUniqueID is also set to ObjectNumber. After having set P, one can immediately return the value of R using P.GetObject(). This function returns the fObjects[fUniqueID] from the fPID object. When the TRef is written, the process id number pidf of fPID is written in addition to the TObject part of the TRef (fBits,fUniqueID). When the TRef is read, its pointer fPID is set to the value stored in the TObjArray of TFile::fProcessIDs(fProcessIDs[pidf]). When a referenced object is written, TObject::Streamer writes the pidf in addition to the standard fBits and fUniqueID. When TObject::Streamer reads a reference object, the pidf is read. At this point, the referenced object is entered into the table of objects of the TProcessID corresponding to pidf. WARNING: If MyClass is the class of the referenced object, The TObject part of MyClass must be streamed. One should not call MyClass::Class()->IgnoreTObjectStreamer(). #### 11.4.4.1 TProccessID and TUUID A TProcessID uniquely identifies a ROOT job. The TProcessID title consists of a TUUID object, which provides a globally unique identifier. The TUUID class implements the UUID (Universally Unique Identifier), also known as GUID (Globally Unique Identifier). A UUID is 128 bits long, and if generated according to this algorithm, is either guaranteed to be different from all other UUID generated until 3400 A.D. or extremely likely to be different. The TROOT constructor automatically creates a TProcessID. When a TFile contains referenced objects, the TProcessID object is written to the file. If a file has been written in multiple sessions (same machine or not), a TProcessID is written for each session. The TProcessID objects are used by TRef to uniquely identify the referenced TObject. When a referenced object is read from a file (its bit kIsReferenced is set), this object is entered into the objects table of the corresponding TProcessID. Each TFile has a list of TProcessIDs (see TFile::fProcessIDs) also accessible from TProcessID::fgPIDs (for all files). When this object is deleted, it is removed from the table via the cleanup mechanism invoked by the TObject destructor. Each TProcessID has a table (TObjArray *fObjects) that keeps track of all referenced objects. If a referenced object has a fUniqueID, a pointer to this unique object may be found using fObjects->At(fUniqueID). In the same way, when a TRef::GetObject is called, GetObject uses its own fUniqueID to find the pointer to the referenced object. See TProcessID::GetObjectWithID and PutObjectWithID. #### 11.4.4.2 Object Number When an object is referenced, a unique identifier is computed and stored in both the fUniqueID of the referenced and referencing object. This uniqueID is computed by incrementing by one the static global in TProcessID::fgNumber. The fUniqueID is the serial object number in the current session. One can retrieve the current fgNumber value by calling the static function TProcessID::GetObjectCount at any time or can set this number by TProcessID::SetObjectCount. To avoid a growing table of fObjects in TProcessID, in case, for example, one processes many events in a loop, it might be necessary to reset the object number at the end of processing of one event. See an example in $ROOTSYS/test/Event.cxx (look at function Build). The value of ObjectNumbermay be saved at the beginning of one event and reset to this original value at the end of the event. These actions may be nested.

   saveNumber = TProcessID::GetObjectCount();
...
TProcessID::SetObjectCount(savedNumber);

### 11.4.5 Action on Demand

The normal behavior of a TRef has been described above. In addition, TRef supports “Actions on Demand”. It may happen that the referenced object is not yet in the memory, on a separate file or not yet computed. In this case, TRef is able to execute automatically an action:

• Call to a compiled function (static function of member function)

• Call to an interpreted function

• Execution of a Cling script

#### 11.4.5.1 How to Select This Option?

In the definition of the TRef data member in the original class, do:

    TRef fRef;   //EXEC:execName points to something

When the special keyword "EXEC:" is found in the comment field of the member, the next string is assumed to be the name of a TExec object. When a file is connected, the dictionary of the classes on the file is read in memory (see TFile::ReadStreamerInfo). When the TStreamerElement object is read, a TExec object is automatically created with the name specified after the keyword "EXEC:" in case a TExec with a same name does not already exist.

The action to be executed via this TExec can be specified with:

• A call to the TExec constructor, if the constructor is called before

• Opening the file.

• A call to TExec::SetAction at any time.

One can compute a pointer to an existing TExec with a name with:

   TExec *myExec = gROOT->GetExec(execName);
myExec->SetAction(actionCommand);

The parameter actionCommand is a string containing a Cling instruction. Examples:

   myExec->SetAction("LoadHits()");
myExec->SetAction(".x script.C");

When a TRef is de-referenced via TRef::GetObject, its TExec** is automatically executed. The TExec function/script can do one or more of the following:**

• Load a file containing the referenced object. This function typically looks in the file catalog.

• Compute a pointer to the referenced object and communicate this pointer back to the calling function TRef::SetObject via:

   TRef::SetObject(object)

As soon as an object is returned to GetObject, the fUniqueID of the TRef is set to the fUniqueID of the referenced object. At the next call to GetObject, the pointer stored in fPid:fObjects[fUniqueID] will be returned directly. An example of action on demand is in $ROOTSYS/test/Event.h:  TRef fWebHistogram; //EXEC:GetWebHistogram When calling fWebHistogram.GetObject(), the function GetObject will automatically invoke the script GetWebHistogram.C via the interpreter. An example of a GetWebHistogram.C script is shown below: void GetWebHistogram() { TFile *f=TFile::Open("http://root.cern.ch/files/pippa.root"); f->cd("DM/CJ"); TH1 *h6 = (TH1*)gDirectory->Get("h6"); h6->SetDirectory(0); delete f; TRef::SetObject(h6); } In the above example, a call to fWebHistogram.GetObject() executes the script with the function GetWebHistogram. This script connects a file with histograms: pippa.root on the ROOT Web site and returns the object h6 to TRef::GetObject.  TRef fWebHistogram; //EXEC:GetWebHistogram() Note that if the definition of the TRef fWebHistogram had been changed the compiled or interpreted function GetWebHistogram() would have been called instead of the Cling script GetWebHistogram.C. ### 11.4.6 Array of TRef When storing multiple TRefs, it is more efficient to use a TRefArray. The efficiency is due to having a single pointer fPID for all TRefs in the array. It has a dynamic compact table of fUniqueIDs. We recommend that you use a TRefArray rather then a collection of TRefs. Example: • Suppose a TObjArray *mytracks containing a list of Track objects. • Suppose a TRefArray *pions containing pointers to the pion tracks in mytracks. This list is created with statements like: pions->Add(track); • Suppose a TRefArray *muons containing pointers to the muon tracks in mytracks. The 3 arrays mytracks,pions and muons may be written separately. ## 11.5 Schema Evolution Schema evolution is a problem faced by long-lived data. When a schema changes, existing persistent data can become inaccessible unless the system provides a mechanism to access data created with previous versions of the schema. In the lifetime of collaboration, the class definitions (i.e. the schema) are likely to change frequently. Not only can the class itself change, but any of its parent classes or data member classes can change also. This makes the support for schema evolution necessary. ROOT fully supports schema evolution. The next figure below illustrates some of the scenarios. The top half represents different versions of the shared library with the class definitions. These are the in-memory class versions. The bottom half represents data files that contain different versions of the classes. • An old version of a shared library and a file with new class definitions - this can be the case when someone has not updated the library and is reading a new file. • Reading a file with a shared library that is missing a class definition (i.e. missing class D). • Reading a file without any class definitions. This can be the case where the class definition is lost, or unavailable. • The current version of a shared library and an old file with old class versions (backward compatibility). This is often the case when reading old data. • Reading a file with a shared library built with MakeProject. This is the case when someone has already read the data without a shared library and has used ROOT MakeProject feature to reconstruct the class definitions and shared library (MakeProject is explained in detail later on). In case of a mismatch between the in-memory version and the persistent version of a class, ROOT maps the persistent one to the one in memory. This allows you to change the class definition at will, for example: • Change the order of data members in the class. • Add new data members. By default, the value of the missing member will be 0 or in case of an object it will be set to null. • Remove data members. • Move a data member to a base class or vice-versa. • Change the type of a member if it is a simple type or a pointer to a simple type. If a loss of precision occurs, a warning is given. • Add or remove a base class ROOT supports schema evolution by keeping a class description of each version of the class that was ever written to disk, with the class. When it writes an object to file, it also writes the description of the current class version along with it. This description is implemented in the StreamerInfoclass. ### 11.5.1 The TStreamerInfo Class Each class has a list of StreamerInfo objects, one for each version of the class if that version was written to disk at least once. When reading an object from a file, the system uses the StreamerInfo list to decode an object into the current version. The StreamerInfo is made up of TStreamerElements . Each describes one persistent data member of the class. By default, all data members of a class are persistent. To exclude a data member (i.e. make it not persistent), add a “!” after the comment marks. For example the pointer *fPainter of a TH1 is not persistent:  TVirtualHistPainter* fPainter //!pointer to histogram painter ### 11.5.2 The TStreamerElement Class A TStreamerElement describes a data member of a simple type, object, array, pointer, or container. The offset in the TStreamerElement is the starting address of the data for that data member. BASE TNamed offset= 0 type=67 The basis for a named object BASE TAttLine offset= 28 type= 0 Line attributes In this example, the TNamed data starts at byte 0, and TAttLine starts at byte 28. The offset is machine and compiler dependent and is computed when the StreamerInfo is analyzed. The types are defined in the file TStreamerInfo.h and listed here: enum EReadWrite { kBase=0, kChar=1,kShort=2,kInt=3,kLong=4, kFloat=5, kCounter=6,kCharStar=7, kDouble=8,kUChar=11, kUShort=12, kUInt=13,kULong=14,kBits=15,kOffsetL=20, kOffsetP=40, kObject=61,kAny=62,kObjectp=63,kObjectP=64, kTString=65, kTObject=66,kTNamed=67,kSkip=100,kSkipL=120, kSkipP=140, kConv=200, kConvL=220,kConvP=240,kStreamer=500, kStreamLoop=501, kMissing=99999 }; The method TClass::GetStreamerInfo analyzes the StreamerInfo the same way it would be analyzed by referring to the class. While analyzing the StreamerInfo, it computes the offsets. The type field is the type of the TStreamerElement. It is specific to the StreamerInfo definition. ### 11.5.3 Example: TH1 StreamerInfo In the StreamerInfo of the TH1 class we see the four base classes: TNamed, TAttLine, TAttFill, andTAttMarker. These are followed by a list of the data members. Each data member is implemented by a TStreamerElement object. root[] TH1::Class()->GetStreamerInfo()->ls() StreamerInfo for class: TH1, version=3 BASE TNamed offset= 0 type=67 The basis for a named object BASE TAttLine offset= 28 type= 0 Line attributes BASE TAttFill offset= 40 type= 0 Fill area attributes BASE TAttMarker offset= 48 type= 0 Marker attributes Int_t fNcells offset= 60 type= 3 number of bins(1D TAxis fXaxis offset= 64 type=61 X axis descriptor TAxis fYaxis offset=192 type=61 Y axis descriptor TAxis fZaxis offset=320 type=61 Z axis descriptor Short_t fBarOffset offset=448 type= 2(1000*offset)for bar charts or legos Short_t fBarWidth offset=450 type= 2 (1000*width)for bar charts or legos Stat_t fEntries offset=452 type= 8 Number of entries Stat_t fTsumw offset=460 type= 8 Total Sum of weights Stat_t fTsumw2 offset=468 type= 8 Total Sum of squares of weights Stat_t fTsumwx offset=476 type= 8 Total Sum of weight*X Stat_t fTsumwx2 offset=484 type= 8 Total Sum of weight*X*X Double_t fMaximum offset=492 type= 8 Maximum value for plotting Double_t fMinimum offset=500 type= 8 Minimum value for plotting Double_t fNormFactor offset=508 type= 8 Normalization factor TArrayD fContour offset=516 type=62 Array to display contour levels TArrayD fSumw2 offset=528 type=62 Array of sum of squares of weights TString fOption offset=540 type=65 histogram options TList* fFunctions offset=548 type=63 ->Pointer to list of functions i= 0, TNamed type= 67, offset= 0, len=1, method=0 i= 1, TAttLine type= 0, offset= 28, len=1, method=142484480 i= 2, TAttFill type= 0, offset= 40, len=1, method=142496992 i= 3, TAttMarker type= 0, offset= 48, len=1, method=142509704 i= 4, fNcells type= 3, offset= 60, len=1, method=0 i= 5, fXaxis type= 61, offset= 64, len=1, method=1081287424 i= 6, fYaxis type= 61, offset=192, len=1, method=1081287548 i= 7, fZaxis type= 61, offset=320, len=1, method=1081287676 i= 8, fBarOffset type= 22, offset=448, len=2, method=0 i= 9, fEntries type= 28, offset=452, len=8, method=0 i=10, fContour type= 62, offset=516, len=1, method=1081287804 i=11, fSumw2 type= 62, offset=528, len=1, method=1081287924 i=12, fOption type= 65, offset=540, len=1, method=1081288044 i=13, fFunctions type= 63, offset=548, len=1, method=1081288164 ### 11.5.4 Optimized StreamerInfo The entries starting with “i = 0” is the optimized format of the StreamerInfo. Consecutive data members of the same simple type and size are collapsed and read at once into an array for performance optimization. i= 0, TNamed type= 67, offset= 0, len=1, method=0 i= 1, TAttLine type= 0, offset= 28, len=1, method=142484480 i= 2, TAttFill type= 0, offset= 40, len=1, method=142496992 i= 3, TAttMarker type= 0, offset= 48, len=1, method=142509704 For example, the five data members beginning with fEntiesand the three data members beginning with fMaximum, are put into an array called fEntries (i = 9) with the length 8. i= 9, fEntries type= 28, offset=452, len=8, method=0 Only simple type data members are combined, object data members are not combined. For example the three axis data members remain separate. The “method” is a handle to the method that reads the object. ### 11.5.5 Automatic Schema Evolution When a class is defined in ROOT, it must include the ClassDef macro as the last line in the header file inside the class definition. The syntax is: ClassDef(<ClassName>,<VersionNumber>) The version number identifies this particular version of the class. When a class has version 0 it is not stored in a root file but its base class(es) is(are). The reason can be that this class has no data members worth saving or all real info is in the base classes. The version number is written to the file in the Streamer by the call TBuffer::WriteVersion. You, as the designer of the class, do not need to do any manual modification in the Streamer. ROOT schema evolution mechanism is automatic and handled by the StreamerInfo. ### 11.5.6 Manual Data Model Evolution Capabilities The automatic data model schema evolution implemented in ROOT makes it possible to read back the serialized data object in the situation when the definition of the classes those objects represent changed slightly (some of the data members were removed or some new ones added). It is also possible to manually specify the rules for more sophisticated data transformations done while reading to load the serialized objects into data structures that changed quite significantly. ROOT provides two interface enabling users to specify the conversion rules. The first way is to define a rule in the dictionary file and the second way is to insert it to the TClass object using the C++ API. There are two types of conversion rules. The first of them, the normal rules, are the ones that should be used in the most of the cases. They provide a buffered input data and an address of the in-memory target object and allow user to specify the conversion function mapping the data being read to the output format. The second type of the rules, the raw rules, also provide the pointer to the target object but the input is a raw TBuffer object containing the input data member declared as an input to the rule. This type of a rule is provided mainly to handle the file format changes that couldn’t have been handled otherwise and in general should not be used unless there is no other option. #### 11.5.6.1 The dictionaries The most convenient place to specify the conversion rules is a dictionary. One can do that either in a LinkDef file or in the selection xml file being fed to genreflex. The syntax of the rules is the following: • For dictionaries created from a LinkDef file: #pragma read \ sourceClass="ClassA" \ source="double m_a; double m_b; double m_c" \ version="[4-5,7,9,12-]" \ checksum="[12345,123456]" \ targetClass="ClassB" \ target="m_x" \ embed="true" \ include="iostream,cstdlib" \ code="{m_x = onfile.m_a * onfile.m_b * onfile.m_c; }" \ #pragma readraw \ sourceClass="TAxis" \ source="fXbins" \ targetClass="TAxis" \ target="fXbins" \ version="[-5]" \ include="TAxis.h" \ code="\ {\ Float_t * xbins=0; \ Int_t n = buffer.ReadArray( xbins ); \ fXbins.Set( xbins ); \ }" • For REFLEX dictionaries: <ioread sourceClass="ClassA" source="double m_a; double m_b; double m_c" version="[4-5,7,9,12-]" checksum="[12345,123456]" targetClass="ClassB" target="m_x" embed="true" include="iostream,cstdlib"> <![CDATA[ m_x = onfile.m_a * onfile.m_b * onfile.m_c; ]] > </ioread> <ioreadraw sourceClass="TAxis" source="fXbins" targetClass="TAxis" target="fXbins" version="[-5]" include="TAxis.h"> <![CDATA[ Float_t *xbins = 0; Int_t n = buffer.ReadArray( xbins ) ; fXbins.Set( xbins ); ]] > </ioreadraw> The variables in the rules have the following meaning: • sourceClass • The field defines the on-disk class that is the input for the rule. • source • A semicolon-separated list of values defining the source class data members that need to be cached and accessible via object proxy when the rule is executed. The values are either the names of the data members or the type-name pairs (separated by a space). If types are specified then the ondisk structure can be generated and used in the code snippet defined by the user. • version • A list of versions of the source class that can be an input for this rule. The list has to be enclosed in a square bracket and be a comma-separated list of versions or version ranges. The version is an integer number, whereas the version range is one of the following: • “a-b”: a and b are integers and the expression means all the numbers between and including a and b • “-a”: a is an integer and the expression means all the version numbers smaller than or equal to a • “a-”: a is an integer and the expression means all the version numbers greater than or equal to a • checksum • A list of checksums of the source class that can be an input for this rule. The list has to be enclosed in a square brackets and is a comma-separated list of integers. • targetClass • The field is obligatory and defines the name of the in-memory class that this rule can be applied to. • target • A comma-separated list of target class data member names that this rule is capable of calculating. • embed • This property tells the system if the rule should be written in the output file is some objects of this class are serialized. • include • A list of header files that should be included in order to provide the functionality used in the code snippet; the list is comma delimited. • code • An user specified code snippet The user can assume that in the provided code snippet the following variables will be defined: The user provided code snippets have to consist of valid C++ code. The system can do some preprocessing before wrapping the code into function calls and declare some variables to facilitate the rule definitions. The user can expect the following variables being predeclared: • newObj • variable representing the target in-memory object, its type is that of the target object • oldObj • in normal conversion rules, an object of TVirtualObject class representing the input data, guaranteed to hold the data members declared in the source property of the rule • buffer • in raw conversion rules, an object of TBuffer class holding the data member declared in source property of the rule • names of the data members of the target object declared in the target property of the rule declared to be the appropriate type • onfile.xxx • in normal conversion rules, names of the variables of basic types declared in the source property of the rule #### 11.5.6.2 The C++ API The schema evolution C++ API consists of two classes: ROOT::TSchemaRuleSet and ROOT::TSchemaRule. Objects of the TSchemaRule class represent the rules and their fields have exactly the same meaning as the ones of rules specified in the dictionaries. TSchemaRuleSet objects manage the sets of rules and ensure their consistency. There can be no conflicting rules in the rule sets. The rule sets are owned by the TClass objects corresponding to the target classes defined in the rules and can be accessed using TClass::{Get|Adopt}SchemaRules. ### 11.5.7 Manual Schema Evolution If you have written your own Streamer as described in the section “Streamers with Special Additions”, you will have to manually add code for each version and manage the evolution of your class. When you add or remove data members, you must modify the Streamer by hand. ROOT assumes that you have increased the class version number in the ClassDef statement and introduced the relevant test in the read part of the Streamer. For example, if a new version of the Event class above includes a new member: Int_t fNew the ClassDef statement should be changed to ClassDef(Event,2) and the following lines should be added to the read part of the Streamer:  if (R__v > 1) R__b >> fNew; else fNew = 0; // set to some default value If, in the same new version 2 you remove the member fH, you must add the following code to read the histogram object into some temporary object and delete it: if (R__v) < 2 { TH1F *dummy = 0; R__b >> dummy; delete dummy; } Our experience with manual schema evolution shows that it is easy to make and mismatches between Streamer writers and readers are frequent and increase as the number of classes increase. We recommend you use rootcling generated Streamers whenever you can, and profit from the automatic schema evolution. ### 11.5.8 Building Class Definitions with the StreamerInfo A ROOT file’s StreamerInfolist contains the description of all versions of all classes in the file. When a file is opened the StreamerInfois read into memory and it provides enough information to make the file browsable. The TStreamerInfoenables us to recreate a header file for the class in case the compiled class is not available. This is done with the TFile::MakeProject method. It creates a directory with the header files for the named classes and a makefile to compile a shared library with the class definitions. ### 11.5.9 Example: MakeProject To explain the details, we use the example of the ATLFast project that is a fast simulation for the ATLAS experiment. The complete source for ATLFast can be down loaded at ftp://root.cern.ch/root/atlfast.tar.gz. Once we compile and run ATLFast we get a ROOT file called atlfast.root, containing the ATLFast objects. When we open the file, we get a warning that the file contains classes that are not in the dictionary. This is correct since we did not load the class definitions. root[] TFile f("atlfast.root") Warning in <TClass::TClass>: no dictionary for class TMCParticle is available Warning in <TClass::TClass>: no dictionary for class ATLFMuon available We can see the StreamerInfofor the classes: root[] f.ShowStreamerInfo() ... StreamerInfo for class: ATLFMuon, version=1 BASE TObject offset= 0 type=66 Basic ROOT object BASE TAtt3D offset= 0 type= 0 3D attributes Int_t m_KFcode offset= 0 type= 3 Muon KF-code Int_t m_MCParticle offset= 0 type= 3 Muon position in MCParticles list Int_t m_KFmother offset= 0 type= 3 Muon mother KF-code Int_t m_UseFlag offset= 0 type= 3 Muon energy usage flag Int_t m_Isolated offset= 0 type= 3 Muon isolation (1 for isolated) Float_t m_Eta offset= 0 type= 5 Eta coordinate Float_t m_Phi offset= 0 type= 5 Phi coordinate Float_t m_PT offset= 0 type= 5 Transverse energy Int_t m_Trigger offset= 0 type= 3 Result of trigger... However, when we try to use a specific class we get a warning because the class is not in the dictionary. We can create a class using gROOT->GetClass() which makes a fake class from the StreamerInfo. // Build a 'fake' class root[] gROOT->GetClass("ATLFMuon") (const class TClass*)0x87e5c08 // The fake class has a StreamerInfo root[] gROOT->GetClass("ATLFMuon")->GetStreamerInfo()->ls() StreamerInfo for class: ATLFMuon, version=1 BASE TObject offset= 0 type=66 Basic ROOT object BASE TAtt3D offset= 0 type= 0 3D attributes Int_t m_KFcode offset= 16 type= 3 Muon KF-code Int_t m_MCParticle offset= 20 type= 3 Muon position in MCParticles list Int_t m_KFmother offset= 24 type= 3 Muon mother KF-code Int_t m_UseFlag offset= 28 type= 3 Muon energy usage flag Int_t m_Isolated offset= 32 type= 3 Muon isolation Float_t m_Eta offset= 36 type= 5 Eta coordinate Float_t m_Phi offset= 40 type= 5 Phi coordinate Float_t m_PT offset= 44 type= 5 Transverse energy Int_t m_Trigger offset= 48 type= 3 Result of trigger i= 0, TObject type= 66, offset= 0, len=1, method=0 i= 1, TAtt3D type= 0, offset= 0, len=1, method=142684688 i= 2, m_KFcode type= 23, offset= 16, len=5, method=0 i= 3, m_Eta type= 25, offset= 36, len=3, method=0 i= 4, m_Trigger type= 3, offset= 48, len=1, method=0 MakeProject has three parameters: MakeProject(const char *dirname,const char *classes,Option_t *option) The first is the directory name in which to place the generated header files. The second parameter is the name of the classes to include in the project. By default, all classes are included. It recognizes the wild card character *, for example, “ATLF*” includes all classes beginning with ATLF. The third parameter is an option with the following values: • new” If the directory does not exist, it is created. • recreate” If the directory does not exist, it is creates as in “new”, in addition if the directory does exist, all existing files are deleted before creating the new files. • update” The new classes are added to the existing directory and the existing classes are replaced with the new definition. If the directory does not exist, it creates it as in “new”. • “+”: This option can be used in combination with the other three. It will create the necessary files to easily build a shared library containing the class definitions.Specifically it will: • Generate a script called MAKE that builds the shared library containing the definition of all classes in the directory. • Generate a LinkDef.hfiles to use with rootcling in MAKE. • Run rootcling to generate a <dirname>ProjectDict.cxx file. • Compile the <dirname>ProjectDict.cxxwith the current options in compiledata.h. • Build a shared library<dirname>.so. • “++”:This option can be used instead of the single “+”. It does everything the single “+” does, and dynamically loads the shared library <dirname>.so. This example makes a directory called MyProject that will contain all class definitions from the atlfast.root file. The necessary makefile to build a shared library are also created, and since the ‘++’ is appended, the shared library is also loaded. root[] f.MakeProject("MyProject","*", "recreate++") MakeProject has generated 0 classes in MyProject MyProject/MAKE file has been generated Shared lib MyProject/MyProject.so has been generated Shared lib MyProject/MyProject.so has been dynamically linked The contents of MyProject: root[] .! ls MyProject ATLFCluster.h ATLFJet.h ATLFMiscMaker.h ATLFTrack.h TMCParticle.h ATLFClusterMaker.h ATLFJetMaker.h ATLFMuon.h ATLFElectron.h ATLFMCMaker.h ATLFMuonMaker.h ATLFElectronMaker.h ATLFMaker.h ATLFPhoton.h ATLFHistBrowser.h ATLFMisc.h ATLFPhotonMaker.h ATLFTrackMaker.h ATLFTrigger.h ATLFTriggerMaker.h LinkDef.h MAKE MyProject.so MyProjectProjectDict.h MyProjectProjectDict.cxx MyProjectProjectDict.o Now you can load the shared library in any consecutive root session to use the atlfast classes. root[]gSystem->Load("MyProject/MyProject") root[]ATLFMuon muon This is an example of a generated header file: ////////////////////////////////////////////////////////// // This class has been generated by TFile::MakeProject // (Thu Apr 5 10:18:37 2001 by ROOT version 3.00/06) // from the TStreamerInfo in file atlfast.root ////////////////////////////////////////////////////////// #ifndef ATLFMuon_h #define ATLFMuon_h #include "TObject.h" #include "TAtt3D.h" class ATLFMuon : public TObject , public TAtt3D { public: Int_t m_KFcode; //Muon KF-code Int_t m_MCParticle; //Muon position in MCParticles list Int_t m_KFmother; //Muon mother KF-code Int_t m_UseFlag; //Muon energy usage flag Int_t m_Isolated; //Muon isolation (1 for isolated) Float_t m_Eta; //Eta coordinate Float_t m_Phi; //Phi coordinate Float_t m_PT; //Transverse energy Int_t m_Trigger; //Result of trigger ATLFMuon() {;} virtual ~ATLFMuon() {;} ClassDef(ATLFMuon,1) // }; ClassImp(ATLFMuon) #endif ## 11.6 Compression and Performance ROOT uses a compression algorithm based on the well-known gzip algorithm. It supports nine levels of compression. The default for ROOT is one. The compression level can be set with the method TFile::SetCompressionLevel. The experience with this algorithm shows that a compression level of 1.3 for raw data files and around two on most DST files is the optimum. The choice of one for the default is a compromise between the time it takes to read and write the object vs. the disk space savings. To specify no compression, set the level to zero. We recommend using compression when the time spent in I/O is small compared to the total processing time. If the I/O operation is increased by a factor of 5 it is still a small percentage of the total time and it may compress the data by a factor of 10. On the other hand if the time spend on I/O is large, compression may have a large impact on the program’s performance. The compression factor, i.e. the savings of disk space, varies with the type of data. A buffer with a same value array is compressed so that the value is only written once. For example, a track has the mass of a pion that it is always the same, and the charge of the pion that is either positive or negative. For 1000 pions, the mass will be written only once, and the charge only twice (positive and negative). When the data is sparse, i.e. when there are many zeros, the compression factor is also high.  Compression level Bytes Write Time (sec) Read Time (sec.) 0 1,004,998 4.77 0.07 1 438,366 6.67 0.05 5 429,871 7.03 0.06 9 426,899 8.47 0.05 The time to uncompress an object is small compared to the compression time and is independent of the selected compression level. Note that the compression level may be changed at any time, but the new compression level will only apply to newly written objects. Consequently, a ROOT file may contain objects with different compression levels. This table shows four runs of the demo script that creates 15 histograms with different compression parameters. To make the numbers more significant, the macro was modified to create 1000 histograms. We have included two more examples to show the impact of compression on Trees in the next chapter. ### 11.6.1 Using the General Open Function of TFile To make life simple we provide a general function to open any type of file (except shared memory files of class TMapFile). This functionality is provided by the static TFile::Open() function: TFile *TFile::Open(const Text_t *name,Option_t *option="", const Text_t *title="",Int_t compress,Int_t netopt) Depending on the name argument, the function returns a TFile or one of its derivations, for example a TXNetFile or a TDavixFile object. In case a URL specifies a local file, a TFile object will be returned (and of course no login information is needed). The arguments of the Open() function are the same as the ones for the TFile constructor. Using ReOpen() method it is possible to reopen a file with a different access mode, like from READ to UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the mode argument can be either “READ” or “UPDATE”. The method returns: • 0 in case the mode was successfully modified; • 1 in case the mode did not change (it was already as requested or there were wrong input arguments); • -1 in case of failure. In the last case the file cannot be used anymore. ## 11.7 Remotely Access to ROOT Files ROOT files can be accessed remotely in many ways, on the base of the protocol URL. Among the most popular are XRootD (protocols ‘root://’ and ‘xrd://’) and a Web server (protocl ‘http://’ or ‘https://’). The rootd daemon is deprecated and has been removed in version 6.16/00. Please refer to the XRootD documentation for starting and ensuring that such a daemon is running. Reading and writing ROOT files over the net can be done by creating a TFile object using the static method TFile::Open() object. This will instantiate the appropriate derivation of TFile to handle the request. Inheriting from the TFile class, the returned instance will have exactly the same interface and behavior of TFile. The only difference is that it reads and writes from a remote service. In the example below the file is read via a web server through the TDavixFile plug-in. ### 11.7.1 A Simple Session root[] TFile *f1 = TFile::Open("local/file.root","update") root[] TFile *f2 = TFile::Open("root://my.server.org/data/file.root","new") root[] TFile *f3 = TFile::Open("http://root.cern.ch/files/hsimple.root") root[] f3.ls() TDavixFile** http://root.cern.ch/files/hsimple.root TDavixFile* http://root.cern.ch/files/hsimple.root KEY: TH1F hpx;1 This is the px distribution KEY: TH2F hpxpy;1 py vs px KEY: TProfile hprof;1 Profile of pz versus px KEY: TNtuple ntuple;1 Demo ntuple root[] hpx.Draw() ## 11.8 XML Interface A new module xml as implemented by Sergey Linev (GSI). It is an optional package that can be used to save a canvas into file.xml file format instead of file.root. XML files do not have any advantages compared to the normal ROOT files, except that the information in these files can be edited via a normal editor. The main motivation for this new format is to facilitate the communication with other non ROOT applications. Currently writing and reading XML files is limited to ROOT applications. It is our intention to develop a simple reader independent of the ROOT libraries that could be used as an example for real applications. The XML format should be used only for small data volumes, typically histogram files, pictures, geometries, calibrations. The XML file is built in memory before being dumped to disk. Like for normal ROOT files, XML files use the same I/O mechanism exploiting the ROOT/Cling dictionary. Any class having a dictionary can be saved in XML format. This first implementation does not support subdirectories or trees. The shared library libRXML.so may be loaded dynamically via gSystem->Load("libRXML"). This library is also automatically loaded by the plug-in manager as soon a XML file is created. To create an XTM file, simply specify a filename with an .xml extension when calling TFile::Open. TFile::Open will recognize that you are trying to open an XML file and return a TXMLFile object. When a XML file is open in write mode, one can use the normal TObject::Write to write an object in the file.  // example of a session saving a histogram to a XML file TFile *f = TFile::Open("Example.xml","recreate"); TH1F *h = new TH1F("h","test",1000,-2,2) h->FillRandom("gaus"); h->Write(); delete f; // example of a session saving a histogram to a XML file TFile *f = TFile::Open("Example.xml"); TH1F *h = (TH1F*)f->Get("h"); h->Draw(); The canvas can be saved as a XML file format via File menu / Save or Save As menu entries. One can do also:  canvas->Print("Example.xml"); # 12 Trees ## 12.1 Why Should You Use a Tree? In the “Input/Output” chapter, we saw how objects can be saved in ROOT files. In case you want to store large quantities of same-class objects, ROOT has designed the TTree and TNtuple classes specifically for that purpose. The TTree class is optimized to reduce disk space and enhance access speed. A TNtuple is a TTree that is limited to only hold floating-point numbers; a TTree on the other hand can hold all kind of data, such as objects or arrays in addition to all the simple types. When using a TTree, we fill its branch buffers with leaf data and the buffers are written to disk when it is full. Branches, buffers, and leafs, are explained a little later in this chapter, but for now, it is important to realize that each object is not written individually, but rather collected and written a bunch at a time. This is where the TTree takes advantage of compression and will produce a much smaller file than if the objects were written individually. Since the unit to be compressed is a buffer, and the TTree contains many same-class objects, the header of the objects can be compressed. The TTree reduces the header of each object, but it still contains the class name. Using compression, the class name of each same-class object has a good chance of being compressed, since the compression algorithm recognizes the bit pattern representing the class name. Using a TTree and compression the header is reduced to about 4 bytes compared to the original 60 bytes. However, if compression is turned off, you will not see these large savings. The TTree is also used to optimize the data access. A tree uses a hierarchy of branches, and each branch can be read independently from any other branch. Now, assume that Px and Py are data members of the event, and we would like to compute Px2 + Py2 for every event and histogram the result. If we had saved the million events without a TTree we would have to: • read each event in its entirety into memory • extract the Px and Py from the event • compute the sum of the squares • fill a histogram We would have to do that a million times! This is very time consuming, and we really do not need to read the entire event, every time. All we need are two little data members (Px and Py). On the other hand, if we use a tree with one branch containing Px and another branch containing Py, we can read all values of Px and Py by only reading the Px and Py branches. This makes the use of the TTree very attractive. ## 12.2 A Simple TTree This script builds a TTree from an ASCII file containing statistics about the staff at CERN. This script, cernbuild.C and its input file cernstaff.dat are in $ROOTSYS/tutorials/tree.

{
// Simplified version of cernbuild.C.
// This macro to read data from an ascii file and
// create a root file with a TTree

Int_t           Category;
UInt_t          Flag;
Int_t           Age;
Int_t           Service;
Int_t           Children;
Int_t           Step;
Int_t           Hrweek;
Int_t           Cost;
Char_t          Division[4];
Char_t          Nation[3];

FILE *fp = fopen("cernstaff.dat","r");

TFile *hfile = hfile = TFile::Open("cernstaff.root","RECREATE");

TTree *tree = new TTree("T","CERN 1988 staff data");
tree->Branch("Category",&Category,"Category/I");
tree->Branch("Flag",&Flag,"Flag/i");
tree->Branch("Age",&Age,"Age/I");
tree->Branch("Service",&Service,"Service/I");
tree->Branch("Children",&Children,"Children/I");
tree->Branch("Step",&Step,"Step/I");
tree->Branch("Hrweek",&Hrweek,"Hrweek/I");
tree->Branch("Cost",&Cost,"Cost/I");
tree->Branch("Division",Division,"Division/C");
tree->Branch("Nation",Nation,"Nation/C");
char line[80];
while (fgets(line,80,fp)) {
sscanf(&line[0],"%d %d %d %d %d %d %d  %d %d %s %s",
tree->Fill();
}
tree->Print();
tree->Write();

fclose(fp);
delete hfile;
}

The script opens the ASCII file, creates a ROOT file and a TTree. Then it creates branches with the TTree::Branch method. The first parameter of the Branch method is the branch name. The second parameter is the address from which the first leaf is to be read. Once the branches are defined, the script reads the data from the ASCII file into C variables and fills the tree. The ASCII file is closed, and the ROOT file is written to disk saving the tree. Remember, trees (and histograms) are created in the current directory, which is the file in our example. Hence a f->Write()saves the tree.

## 12.3 Show an Entry with TTree::Show

An easy way to access one entry of a tree is the use the TTree::Show method. For example to look at the 10th entry in the cernstaff.root tree:

root[] TFile f("cernstaff.root")
root[] T->Show(10)
======> EVENT:10
Category        = 361
Flag            = 15
Age             = 51
Service         = 29
Children        = 0
Step            = 13
Hrweek          = 40
Cost            = 7599
Division        = PS
Nation          = FR

A helpful command to see the tree structure meaning the number of entries, the branches and the leaves, is TTree::Print.

root[] T->Print()
**********************************************************************
*Tree    :T         : staff data from ascii file                     *
*Entries :3354      : Total = 245417 bytes  File  Size =        59945*
*                     Tree compression factor =   2.90               *
**********************************************************************
*         | Cost                                                     *
*Entries :3354 : Total Size  = 154237 bytes  File Size = 32316       *
*Baskets :   3 : Basket Size =  32000 bytes  Compression= 2.97       *

## 12.5 Scan a Variable the Tree with TTree::Scan

The TTree::Scan method shows all values of the list of leaves separated by a colon.

root[] T->Scan("Cost:Age:Children")
************************************************
*    Row   *      Cost *       Age *  Children *
************************************************
*        0 *     11975 *        58 *         0 *
*        1 *     10228 *        63 *         0 *
*        2 *     10730 *        56 *         2 *
*        3 *      9311 *        61 *         0 *
*        4 *      9966 *        52 *         2 *
*        5 *      7599 *        60 *         0 *
*        6 *      9868 *        53 *         1 *
*        7 *      8012 *        60 *         1 *
...

## 12.6 The Tree Viewer

The tree viewer is a quick and easy way to examine a tree. To start the tree viewer, open a file and object browser. Right click on a TTree and select StartViewer. You can also start the tree viewer from the command line. First load the viewer library.

root[] TFile f("cernstaff.root")
root[] T->StartViewer()

If you want to start a tree viewer without a tree, you need to load the tree player library first:

root[] gSystem->Load("libTreeViewer.so")
root[] new TTreeViewer()

The figure above shows how the tree viewer looks like for the example file cernstaff.root. The left panel contains the list of trees and their branches; in this case there is only one tree. You can add more trees with the File-Open command to open the file containing the new tree, then use the context menu on the right panel, select SetTreeName and enter the name of the tree to add. On the right are the leaves or variables in the tree. You can double click on any leaf to a histogram it.

The toolbar in the upper part can be used for user commands, changing the drawing option and the histogram name. The lower part contains three picture buttons that draw a histogram, stop the current command, and refresh the tree.

The three check buttons toggle the following:

Hist- the histogram drawing mode;

Scan- enables redirecting of TTree::Scancommand in an ASCII file;

Rec - enables recording of the last issued command.

• To draw more than one dimension you can drag and drop any leaf to the X,Y,Z boxes". Then push the Draw button, witch is marked with the purple icon on the bottom left.

• All commands can be interrupted at any time by pressing this button.

• The method TTree::Refresh is called by pressing the refresh button in TTreeViewer. It redraws the current exposed expression. Calling TTree::Refresh is useful when a tree is produced by a writer process and concurrently analyzed by one or more readers.

• To add a cut/weight to the histogram, enter an expression in the “cut box”. The cut box is the one with the scissor icon.

Below them there are two text widgets for specifying the input and output event lists. A Tree Viewer session is made by the list of user-defined expressions and cuts, applying to a specified tree. A session can be saved using File / SaveSource menu or the SaveSource method from the context menu of the right panel. This will create a macro having as default name treeviewer.C that can be ran at any time to reproduce the session.

Besides the list of user-defined expressions, a session may contain a list of RECORDS. A record can be produced in the following way: dragging leaves/expression on X/Y/Z; changing drawing options; clicking the RED button on the bottom when happy with the histogram

NOTE that just double clicking a leaf will not produce a record: the histogram must be produced when clicking the DRAW button on the bottom-left. The records will appear on the list of records in the bottom right of the tree viewer. Selecting a record will draw the corresponding histogram. Records can be played using the arrow buttons near to the record button. When saving the session, the list of records is being saved as well.

Records have a default name corresponding to the Z: Y: X selection, but this can be changed using SetRecordName() method from the right panel context menu. You can create a new expression by right clicking on any of theE() boxes. The expression can be dragged and dropped into any of the boxes (X, Y, Z, Cut, or Scan). To scan one or more variables, drop them into the Scan box, then double click on the box. You can also redirect the result of the scan to a file by checking the Scan box on top.

When the “Rec” box is checked, the Draw and Scan commands are recorded in the history file and echoed on the command line. The “Histogram” text box contains the name of the resulting histogram. By default it is htemp. You can type any name, if the histogram does not exist it will create one. The Option text box contains the list of Draw options. See “Draw Options”. You can select the options with the Options menu. The Command box lets you enter any command that you could also enter on the command line. The vertical slider on the far left side can be used to select the minimum and maximum of an event range. The actual start and end index are shown in on the bottom in the status window.

There is an extensive help utility accessible with the Help menu. The IList and OList are to specify an input list of entry indices and a name for the output list respectively. Both need to be of type TList and contain integers of entry indices. These lists are described below in the paragraph “Error! Reference source not found.”.

The first one is a plot of the age distribution, the second a scatter plot of the cost vs. age. The second one was generated by dragging the age leaf into the Y-box and the cost leaf into the X-box, and pressing the Draw button. By default, this will generate a scatter plot. Select a different option, for example "lego" to create a 2D histogram.

## 12.7 Creating and Saving Trees

This picture shows the TTree class:

To create a TTree we use its constructor. Then we design our data layout and add the branches. A tree can be created by giving a name and title:

   TTree t("MyTree","Example Tree");

### 12.7.1 Creating a Tree from a Folder Hierarchy

An alternative way to create a tree and organize it is to use folders (see “Folders and Tasks”). You can build a folder structure and create a tree with branches for each of the sub-folders:

   TTree folder_tree("MyFolderTree","/MyFolder");

The second argument "/MyFolder"is the top folder, and the “/” signals the TTree constructor that this is a folder not just the title. You fill the tree by placing the data into the folder structure and calling TTree::Fill.

### 12.7.2 Tree and TRef Objects

   MyTree->BranchRef();

This call requests the construction of an optional branch supporting table of references (TRefTable). This branch (TBranchRef) will keep all the information needed to find the branches containing referenced objects at each Tree::Fill, the branch numbers containing the referenced objects are saved in the table of references. When the Tree header is saved (via TTree::Write for example), the branch is saved, keeping the information with the pointers to the branches having referenced objects. Enabling this optional table, allow TTree::Draw to automatically load the branches needed to dereference a TRef (or TRefArray) object.

### 12.7.3 Autosave

Autosave gives the option to save all branch buffers every n byte. We recommend using Autosave for large acquisitions. If the acquisition fails to complete, you can recover the file and all the contents since the last Autosave. To set the number of bytes between Autosave you can use the TTree::SetAutosave() method. You can also call TTree::Autosave in the acquisition loop every nentry.

### 12.7.4 Trees with Circular Buffers

When a TTree is memory resident, you set it up so that it retains retain only the last few entries. For example, this can be very useful for monitoring purpose.

   void TTree::SetCircular(Long64_t maxEntries);

where maxEntries is the maximum number of entries to be kept in the buffers. When the number of entries exceeds this value, the first entries in the Tree are deleted and the buffers used again. An example of a script using a circular buffer is shown below:

void circular() {
gROOT->cd(); //make sure that the Tree is memory resident
TTree *T = new TTree("T","t`