Architectural Overview

The backbone of the ROOT architecture is a layered class hierarchy with, currently, around 310 classes grouped in about 24 frameworks divided in 14 categories. This hierarchy is organized in a mostly single-rooted class library, that is, most of the classes inherit from a common base class TObject. While this organization is not very popular in C++, it has proven to be well suited for our needs (and indeed for almost all successful class libraries: Java, Smalltalk, MFC, etc.). It enabled the implementation of some essential infrastructure inherited by all descendants of TObject. However, we also can have classes not inheriting from TObject when appropriate (e.g., classes that are used as built-in types, like TString).

The Class Categories

The basic ROOT classes contain the most low-level building blocks of ROOT. For example, the TObject class, which implements common behaviour for all ROOT classes. The class TClass and its helper classes that provide support for extended runtime type information. The storage manager TStorage which handles all memory allocation and de-allocation operations and performs basic error checking (memory overwrites, etc.). The class TFile which provides a hierachical sequential and direct access persistant object store. The operating system abstraction layer TSystem and the concrete OS interfaces TUnixSystem, TWinNTSystem, TMacSystem and TVmsSystem concentrate all OS dependent behaviour, like file system access, dynamic loading and IPC for the three main platforms supported by ROOT.

The container classes general purpose data structure classes like, arrays, lists, sets, B-trees, maps, etc., which are heavily used in the implementation of ROOT itself.

The Physics classes, Feldman Cousins algorithm, N-body phase space generator, Lorentz rotation, Lorentz vector, 2-D vectors, 3-D vectors, etc.

The Matrix and Vector classes, lazy matrices, general matrices, vectors.

The histogram and minimization classes offer advanced statistical data analysis features, like 1D, 2D and 3D histograming of short, long, float or double values, with fixed or variable bin sizes, profile histograms, data fitting, formula evaluation and minimization.

The Interface to the minimizers: , Minuit, Fumili

The Linear Quadratic Programming classes

The tree and ntuple classes contain the tree system. The row-wise and column-wise ntuples have been one of the major strengths of the PAW system. Trees extend the concept of ntuples to all complex objects and data structures found on raw data tapes and DSTs. The idea is that the same data model, same language, same style of queries can be used on all data sets in an experiment. Trees are designed to support not only complex objects, but also a very large number of them in a large number of files. Ntuples are simple trees with one branch only.

The 2D graphics classes contain the low-level graphics primitives, like lines, arrows, rectangles, ellipses, text, legends, annotations, text with Latex notation, splines, etc., but also the higher level constructs like pads and canvases. They also handle basic style and attribute management.

The 3D graphics and detector geometry classes provide basic 3D graphics primitives, like 3D polylines and 3D polymarkers as well as higher level geometrical shapes (boxes, cones, polygons, tubes, etc.) which can be efficiently assembled into very complex detector geometries.

The Image processing classes such as TASImage.

The Detector Geometry classes The geometry package is a tool designed for building, browsing, tracking and visualizing a detector geometry. The code is independent from other external MC for simulation, therefore it does not contain any constraints related to physics. However, the package defines a number of hooks for tracking, such as materials, magnetic field or track state flags, in order to allow interfacing to tracking MC's. The final goal is to be able to use the same geometry for several purposes, such as tracking, reconstruction or visualization, taking advantage of the ROOT features related to bookkeeping, I/O, histograming, browsing and GUI's. The geometrical modeler is the most important component of the package and it provides answers to the basic questions like "Where am I ?" or "How far from the next boundary ?", but also to more complex ones like "How far from the closest surface ?" or "Which is the next crossing along a helix ?".

The Neural Network classes.

The Graphical User Interface classes contain all the graphical and interactive components found in almost every user interface toolkit, such as buttons, windows, dialogs and menus. Similar classes have also been developed for Windows.

The Graphics editor classes.

The interactive interface classes and C++ interpreter allow the construction of interactive applications in which the user has to learn only one language, C++, to communicate with the program. The command language, macro language and programming language are all one and the same.

The operating system interface is the sole interface to the operating system. All OS services are handled via the TSystem (TUnixSystem, TWinNTSystem, TMacSystem) and TVmsSystem class.

The networking classes provide a simple, but powerful way to construct client/server application. All low level IPC services are provided via the TSystem class.

The SQL interface classes provide a simple, but powerful abstract interface to different SQL database servers (MySQL, SAPDB, PostgreSQL, Oracle). See classes TSQLServer, TSQLResult and TSQLRow.

The documentation classes allow the creation of hyperized (in HTML format) C++ header and source files, inheritance trees, class indices, macro's and session transcripts. Thanks to this facility almost everything in the ROOT system can be automatically documented and cross-referenced.

The TObject Class

Most ROOT classes are derived from TObject. TObject defines protocols (abstract methods) for comparing objects, for object I/O, for graphics hit detection and for notification between objects, to name the most important ones.

The ROOT object I/O facility supports the transfer of arbitrarily complex polymorphic data structures from memory to a ROOT binary machine-independent file and vice versa or to XMLfiles. This functionality is based on the abstract method Streamer, which is overridden in subclasses to stream an object's instance variables. Circular structures are linearized, and multiple references to the same object are restored properly. Storing pointers is implemented by an object table, which assigns a unique identifier to each transmitted object. This identifier can be transferred to other address spaces or to permanent storage.

Object I/O needs some information about the type of an object at runtime, because not only the state of an object but also its corresponding class type has to be transmitted. ROOT runtime support could provide enough information about an object's instance variables to implement the Streamer method generically in class TObject. However, we preferred the approach of a programmer selectively deciding which data members should be written to disk. Data members caching some state of an object that can easily be reconstructed in the Streamer method do not have to be transferred to disk. Another example is when variables can be compacted into short words or even single bits (booleans). To aid the programmer we provide a tool to generate automatically a default Streamer method.

The case of encountering an unknown class while reading back an object structure leads to the discussion of dynamic loading and linking. To handle this case gracefully, ROOT includes a mechanism to load a new class and link it to a running application. This dynamic linking support can be further used to extend a running system. In the case of the NA49 data analysis the library with the experiment specific classes is dynamically linked to the running interactive ROOT program.

The object I/O facility is also used as the standard format for transferring arbitrary data structures to other ROOT based applications running in other address spaces or on other machines. The transparent integration of dynamic linking into the object I/O mechanism allows the copying of instances of classes that are not known in the running application. This feature allows us to develop fairly easily advanced, web like, browsers that could operate on imported ROOT objects (for example, we could refit imported histograms without having to leave the browser).

The Class Dictionary and Object Runtime Support

Even with the upcoming runtime type identification (RTTI) extension for C++, the runtime system does not provide any information about the class structure, the instance variables or the member functions of an object. Consequently, an additional mechanism had to be introduced to gather this information, in order to support InheritsFrom, Inspect and Dump methods, the object I/O facility and the automatic documentation system. ROOT uses the approach of associating with each class (via a static pointer) a special object describing its structure. These descriptors are instances of the class TClass which is itself a subclass of TObject. TClass objects store the following information about a class: Because the C++ runtime system gives no access to type and structure information, the ROOT system uses a dictionary generator called CINT. CINT parses the class header files and generates a dictionary (in the form of a C++ function). To link the CINT generated dictionary function to a class the programmer only has to add two preprocessor macros to his code. One macro, ClassDef, must be placed in the class definition file and the other macro, ClassImp, in the implementation file.

Besides as a dictionary generator, CINT is being used in the ROOT system as a command line interpreter and macro processor. Thanks to CINT the ROOT system can offer the user a single language (C++) interface.

Rene Brun, Fons Rademakers
Last update 30/5/96 by FR