ROOT Version 5.08/00 Release Notes
ROOT version 5.08/00 has been released December 15, 2005.
Binaries for all supported platforms are available at:
http://root.cern.ch/root/Version508.html
Versions for AFS have also been updated. See the list of supported platforms:
http://root.cern.ch/root/AFS.html
For more information, see:
http://root.cern.ch
The following people have contributed to this new version:
Ilka Antcheva,
Maarten Ballintijn,
Bertrand Bellenot,
Zev Benjamin,
Marek Biskup,
Walter Brown,
Rene Brun,
Philippe Canal,
Jan Conrad,
Olivier Couet,
Christophe Delaere,
Denis Favre-Miville,
Valeri Fine,
Mark Fishler,
Markus Frank,
John Frankland,
Gerri Ganis,
Andrei Gheata,
Mihaela Gheata,
Masaharu Goto,
Andy Hanushevsky,
Christian Holm Christensen,
Anna Kreshuk,
Wim Lavrijsen,
Sergei Linev,
Jose Lo,
John Marraffino,
Pere Mato,
Richard Maunder,
Lorenzo Moneta,
Axel Naumann,
Paul Nilsson,
Eddy Offermann,
Valeriy Onuchin,
Andreas Peters,
Muriel Pivk,
Timur Pocheptsov,
Fons Rademakers,
Stefan Roiser,
Paul Russo,
Andras Zsenei
Base
License Change
With this release we've moved to the LGPL license. The LGPL is very liberal
Open Source license with should not impede much our many long time commercial
users, while at the same time put ROOT solidly in the Open Source domain.
New Class TMacro
This class allow for storing a C++ macro in a ROOT file.
In addition to being stored in a ROOT file a TMacro can be executed,
edited, etc.
A macro can be built line by line by calling the AddLine() function,
or it can be created directly from a file via a special constructor.
A macro can be executed via the Exec() function. Arguments can be
specified when calling Exec().
A macro can be drawn in a pad. When the pad is updated, the macro is
automatically executed.
The code in the macro can be saved via the SaveSource() function.
If the macro is in the list of primitives of a pad/canvas, the macro
will be saved in the script generated by TCanvas::SaveSource().
A macro can be written to a ROOT file via TObject::Write().
Examples:
TMacro m("Peaks.C"); //macro m with name "Peaks" is created
//from file Peaks.C
m.Exec(); //macro executed with default arguments
m.Exec("4"); //macro executed with argument
m.SaveSource("newPeaks.C");
TFile f("mymacros.root","recreate");
m.Write(); //macro saved to file with name "Peaks"
Multi-level TAB Completion
Support for multi-level TAB completion in the ROOT shell, like:
obj->GetVariable1ptr()->GetVar2Ptr()->[tab]
Previously only the first level after obj-> could be expanded.
New Class TFileMerger
This new class allows for easy copying of two or more files using the
many TFile plugins (i.e. it can copy from Castor to dCache, or from
xrootd to Chirp, etc.). Its file merge functionality is taken from hadd.
To use it do, e.g.:
TFileMerger m
m->Cp("srcUrl", "destUrl")
or
m->AddFile("url1")
m->AddFile("url2")
m->Merge()
The AddFile() and Merge() use the Cp() to copy the file locally before
making the merge, and if the output file is remote the merged file
will be copied back to the remote destination.
New TFile Feature
Support for opening files in raw mode when the file url contains the
option string "filetype=raw", like "anyfile.tgz?filetype=raw".
This allows TFile and its many remote access plugins to be used to open
and read any file. This is used by the TFileMerger::Cp() method to copy
any file from and to Grid storage elements (e.g. from Castor to dCache,
from xrootd to a local file, and all possible permutations).
New TUrl Feature
Added support for file namespaces, like: /alien/user/rdm/bla.root, which
will be split in protocol=alien, file=/user/rdm/bla.root. Special
namespaces like /alien/ are added via [system].rootrc. This also allows us to
directly support filenames like /castor/cern.ch/... instead of
castor:/castor/cern.ch/...
New Class TPRegexp and PCRE Interface
The new TPRegexp class provides an interface to the PCRE (Perl Compatible
Regular Expression) library. The TPRegexp class has also been interfaced
with the TString class for easy string regexp operations.
A new tutorial regexp.C shows the power of this regexp class.
New TGFALFile and TGFALSystem Classes
A TGFALFile is like a normal TFile except that it reads and writes
its data via the underlaying Grid access mechanism.
TGFALFile file names are either a logical file name, a guid, an
SURL or a TURL, like:
gfal:/lfn/user/r/ram/galice.root
Grid storage interactions today require using several existing
software components:
- The replica catalog services to locate valid replicas of
files.
- The SRM software to ensure:
- files exist on disk (they are recalled from mass
storage if necessary) or
- space is allocated on disk for new files (they are possibly
migrated to mass storage later)
- A file access mechanism to access files from the storage
system on the worker node.
The GFAL library hides these interactions and presents a Posix
interface for the I/O operations. The currently supported protocols
are: file for local access, dcap, gsidcap and kdcap (dCache access
protocol) and rfio (CASTOR access protocol).
File naming convention:
A file name can be a Logical File Name (LFN), a Grid Unique
IDentifier (GUID), a file replica (SURL) or a Transport file
name (TURL):
- an LFN starts with lfn, for example:
lfn:baud/testgfal15
- a GUID starts with guid, for example:
guid:2cd59291-7ae7-4778-af6d-b1f423719441
- an SURL starts with srm://, for example:
srm://wacdr002d.cern.ch:8443/castor/cern.ch/user/b/baud/testgfal15
- a TURL starts with a protocol name, for example:
rfio:////castor/cern.ch/user/b/baud/testgfal15
Note that for the TGFALFile plugin to work, all these pathnames
should be prepended by gfal:.
The code is provided by the libGFAL plugin.
New MonaLisa Monitoring Pluging
New class TMonaLisa
The new class TMonaLisa defines an interface to the MonaLisa Monitoring
Services in ROOT.
The TMonaLisa object is used to send monitoring information to a
MonaLisa server using the MonaLisa ApMon package (libapmoncpp.so/UDP
packets). The MonaLisa ApMon library for C++ can be downloaded at
http://monalisa.cacr.caltech.edu/monalisa__Download__ApMon.html,
with the current version being:
http://monalisa.cacr.caltech.edu/download/apmon/ApMon_cpp-2.0.6.tar.gz
The ROOT implementation is primary optimized for process/job
monitoring, although all other generic MonaLisa ApMon functionality
can be exploited through the ApMon class directly via gMonaLisa->GetApMon().
Improvements in the Build System on Windows
Several optimizations in the build system fix the problem where
all plugins had to be relinked if either libCore or libCint was changed.
Now this does not happen anymore, bringing the build efficiency to the
level of the one on Unix/Linux.
Added Support for VC++2005
Made several modifications to support the new Microsoft VC++ 2005 compiler.
New TString Methods
New methods:
- Atoi()
- Atof()
- IsDigit()
- IsWhitespace()
These methods allow typical string based representations of floating point
and integer numbers to be converted to floats and ints, like:
"1 3030 440.0" or "123 456"
Miscellaneous
New option --config to root-config which returns the full string used
to configure this specific version of ROOT.
XML DOM Parser
The DOM (Document Object Model) is a
platform and language-neutral interface that will allow programs and
scripts to dynamically access and update the content, structure and
style of documents. The DOM parser, as the previously introduced SAX
parser, are internally using libxml2.
The DOM parser comes with two new tutorials: DOMParsePerson.C
and DOMRecursive.C.
Castor 2 Support in TCastorFile
Castor v2 is now supported by the TCastorFile class. Both
protocols, Castor v1 and v2 ar supported. The plugin needs to be
linked with the new castor-2.0.0 library.
New TBits feature
We added support for the operators:
|,&,^,<<.>>,|=,&=,^=,>>=,<<= and []
and for printing a TBits object via an ostream.
New Ports
Finalized the port to MacOS X Tiger (10.4).
On Tiger the default Fortran compiler is gfortran. Usage of the optional
g95 is possible by setting g95 in ROOTBUILD, e.g.:
export ROOTBUILD="debug g95"
New port to AIX5 with gcc and at the same time improved the port to xlC.
Support for FreeBSD6 (autodetected by ./configure).
Thread Safety
Work has been done to make more classes thread safe, like when accessing
global TROOT containers and classes like TDatime, TTimestamp, etc.
CINT
Developments in Trees
-
Fast Merging: We added new option, "fast", to CloneTree and Merge.
When using the "fast" option, TTree::CloneTree does not unzip nor unstream
the content of the TTrees but copies directly the raw bytes of the baskets
from one file to another. This will result in a much higher performance in
reading and writing the file. The "fast" option is currently only
available if the complete content of TTree is being copied.
The option "SortBasketsByBranch" also allows for a reordering of the baskets
on the output file: all the baskets of a given branch of a given tree will be
stored contiguously.
-
Extended the support for variable size C style array inside a split collection
to Long64 and Bool_t.
-
The name of the new tree created in TChain::Merge is now set to the name of the
chain __without__ the potential directory name.
-
TChain::FindBranch and TChain::FindLeaf now properly call their counterpart in
the interlying TTree object (fTree) instead of the inherited version.
This results in TTree::Draw properly looking at the friend of both the
underlying TTree object and the TChain object (instead of just the TChain
object).
We improved the performance of TBranchElement::SetAddress by increasing the
caching of TClass pointers and offsets. Also leverage the use of TClassRef
to reduce the number of calls to gROOT->GetClass. Optimize a couple of
additional functions. The improvement is dramatic for the 2nd call to
SetAddress on the same branch object (90%)! In addition we solved several
issue involving complex class structures and collections (see cvs logs for
details)
We fixed a problem in the writing of fBits when it was writing in its own
branch and the object were referenced. We improved on the support of nested
TTree Friend (use multiple locks instead of only one). We enabled the
browsing/Drawing of emulated std::map
Meta
Significantly improved the IsA lookup for foreign classes
(i.e the lookup by typeid). It is inspired from the implementation
used by POOL/Reflex. It uses a new abstract interface TVirtualIsAProxy.
We Improved performance of TClassRef.
Nested namespace are now allowed in a rootmap file.
Input/Output
We introduced a new feature allowing the customization of
the constructor used by the I/O.
The constructor actually called by the ROOT I/O can be customized by
using the rootcint pragma:
#pragma link C++ ioctortype UserClass;
For example, with this pragma and a class named MyClass,
this method will called the first of the following 3
constructors which exists and is public:
MyClass(UserClass*);
MyClass(TRootIOCtor*);
MyClass(); // Or a constructor with all its arguments defaulted.
When more than one pragma ioctortype is used, the first seen as priority
For example with:
#pragma link C++ ioctortype UserClass1;
#pragma link C++ ioctortype UserClass2;
We look for the first existing public constructor in the following order:
MyClass(UserClass1*);
MyClass(UserClass2*);
MyClass(TRootIoCtor*);
MyClass(); // Or a constructor with all its arguments defaulted.
We extended the support for pointers to varying length arrays of objects to
include the cases:
-
Foreign Objects: objects whose classes do not have a
ClassDef macro, but do have dictionaries loaded (no default Streamer, but we do
have TStreamerInfo).
-
Objects of classes with custom Streamer functions.
-
Reading an object from a file when we do not have the dictionary loaded for the
object's class, and then writing that object out to a file again (emulated
objects). This allows us to copy trees without have to have the class
dictionaries loaded.
-
Note that we still do not support the case of STL objects.
New utility classs TDirectory::TContext to keep track and
restore the current directory. With this construct C++
exceptions will be guaranteed to properly restore the
current directory pointer.
We added a new member function, TDirectory::GetDirectory, which factors out
the code of TDirectory::cd and its static counterpart TDirectory::Cd.
TDirectory::GetDirectory can be used to quietly find out if a directory
exist:
TDirectory *mydir = myfile->GetDirectory(somepath);
if (mydir==0) mydir->mkdir(somepath);
myfile->cd(somepath);
We improved performance of reading of legacy ROOT 3 files.
Improved streaming speed for std::string.
Improve performance of STL container streaming.
TDirectory::Get and TDirectory::GetObject now rely on recursivity
rather than changing the current directory to handle pathname. This
solves a problem appearing when the object looked-for has the same name as one.
TFormula
New implementation of the executor part of TFormula which minimizes
the size of the existing switch statement by combining some operation
and/or replacing some operations by a single indirect function call.
This result in a significant speed-up of the execution.
The change is fully backward compatible since the new optimized
operation are stored in an additional set of transient data members.
(fExprOptimized and fOperOptimized).
Function with default paramater can not yet be properly handled
via the faster function primitive mechanism.
We extended the syntax to allow to calls function whose names start
(but are different from) gaus, landau, rndm or expo.
Insured that the paramaters of the Formula are properly restored
by TFormula::Streamer even if the formula contains calls to
external C++ function (like TMath::Abs).
Added support for the creation of TF1, TF2 and TF3 object from function with
the signature
double (*)(const double*,const double*);
from compiled code. So far only double (*)(double*,double*)
was supported
We fixed a problem in arithmetic operation when signed char array (whichcan also
be used as a string) is on the right hand.
We fixed a couple of issue regarding how saved TFormulas were restored by
TFormula::Streame when they contain calls to external C++ function
like TMath::Abs).
TTreeFormula
Add a new member function TTreeFormula::ResetLoading. This can
be used instead of calling TTreeFormula::EvalInstance(0) to insure
the proper loading of the branches. In particular this solves issues
when the formula is invalid (invalid indices for example) for the first
instance.
New class TFileSQL
Introduce a "transparent" access to SQL data base via standard TFile interface.
The main approach that each class (but not each object) has one or two tables
with names like $(CLASSNAME)_ver$(VERSION) and $(CLASSNAME)_streamer_ver$(VERSION)
For example: TAxis_ver8 or TList_streamer_ver5
Second kind of tables appears, when some of class members can not be converted to
normalized form or when class has custom streamer.
For instance, for TH1 class two tables are required: TH1_ver4 and TH1_streamer_ver4
Most of memebers are stored in TH1_ver4 table columnwise, and only memeber:
Double_t* fBuffer; //[fBufferSize]
can not be represented as column while size of array is not known apriory.
Therefore, fBuffer will be written as list of values in TH1_streamer_ver4 table.
All objects, stored in the DB, will be registered in table "ObjectsTable".
In this there are following columns:
- "key:id" - key identifier to which belong object
- "obj:id" - object identifier
- "Class" - object class name
- "Version" - object class version
Data in each "ObjectsTable" row uniqly identify, in which table
and which column object is stored.
In normal situation all class data should be sorted columnwise.
Up to now following member are supported:
- Basic data types.
Here is everything clear. Column SQL type will be as much as possible
close to the original type of value.
- Fixed array of basic data types
In this case n columns like fArr[0], fArr[1] and so on will be created.
If there is multidimensional array, names will be fArr2[1][2][1] and so on
- Parent class.
In this case version of parent class is stored and
data of parent class will be stored with the same obj:id in corrspondent table.
There is a special case, when parent store nothing (this is for instance TQObject).
In that case just -1 is written to avoid any extra checks if table exist or not.
- Object as data member.
In that case object is saved in normal way to data base and column
will contain id of this object.
- Pointer on object.
Same as before. In case if object was already stored, just its id
will be placed in the column. For NULL pointer 0 is used.
- TString.
Now column with limited width like VARCAHR(255) in MySQL is used.
Later this will be improved to support maximum possible strings
- Anything else.
Data will be converted to raw format and saved in _streamer_ table.
Each row supplied with obj:id and row:id, where row:id indicates
data, corresponding to this particular data member, and column
will contain this raw:id
See the TSQLFile documentation for more details.
example of a session saving data to a SQL data base
=====================================================
const char* dbname = "mysql://host.domain:3306/dbname";
const char* username = "username";
const char* userpass = "userpass";
// Clean data base and create primary tables
TSQLFile* f = new TSQLFile(dbname, "recreate", username, userpass);
// Write with standard I/O functions
arr->Write("arr",TObject::kSingleKey);
h1->Write("histo");
// Close connection to DB
delete f;
example of a session read data from SQL data base
=====================================================
// Open database again in read-only mode
TSQLFile* f = new TSQLFile(dbname, "open", username, userpass);
// Show list of keys
f->ls();
// Read stored object, again standard ROOT I/O
TH1* h1 = (TH1*) f->Get("histo");
if (h1!=0) { h1->SetDirectory(0); h1->Draw(); }
TObject* obj = f->Get("arr");
if (obj!=0) obj->Print("*");
// close connection to DB
delete f;
Known problems and open questions.
- TTree is not supported by TSQLFile. There is independent development
of TTreeSQL, which allows to store trees directly in SQL database
- TDirectory cannot work. Hopefully, will (changes in ROOT basic I/O is required)
New class TTreeSQL
We introduced the first version of TTreeSQL facility. This
new facility allows the storing and restoring of TTree to and from
an SQL database:
TSQLServer *dbserver =
TSQLServer::Connect("mysql://localhost:3306/rootDev","rootdevel",
"r00tg6ys");
dbserver->Query("drop table ntuple;");
ntuple = new TTreeSQL(dbserver, "rootDev", "ntuple");
If the database contain a table named ntuple, this will connect to it and
let
you use any of TTree functionality on (Scan, Draw, etc.)
If the database does not contain a table named ntuple, it will created once
you called the first Fill on the TTree. This version supports the leaflist
type of branches.
PROOF
Many new features have been
introduced in
the PROOF system. A new communication layer based on the top component
of XROOTD has been implemented. The new layer allows, in
particular, to connect to the same PROOF sessions from different client
terminals, to disconnect from a running session and to reconnect to a
later time. The XROOTD server running XrdProofdProtocol, shortly XPD,
acts as a coordinator or manager of PROOF sessions. To map on the
client side the manager functionality brought by XPD, a new class has
been introduced, TVirtualProofMgr.
TVirtualProof has also been extended
to
accommodate the possibility of multiple sessions, to support
asynchronous running mode and to handle the results of processed
queries.
Finally a completely new GUI has been designed to handle all the new
functionality in a more user-friendly way.
The
libXrdProofd.so plugin
This library contains the code to run the protocol XrdProofdProtocol in
a XROOTD application. A new application, xproofd, running by default
the new protocol is available in $ROOTSYS/bin . To start the new daemon
just make sure that $ROOTSYS and the execution and library paths are
correctly set and execute
~>
xproofd -p 1093
This will start a daemon with default settings, listening on port 1093
(for the time being the rootd default 1094 is hard-coded in XRD; it
will be made configurable for future releases). The relevant
directives applying to xrootd can be given via configuration file (the
port can be specified there):
~>
xproofd -c xpd.cf
See $ROOTSYS/etc/xpd.cf for an example activating authentication via
the usual $HOME/.rootdpass file .
Examples of startup scripts can also be found in $ROOTSYS/etc
(see startXRD.sh, for a generic standalone script starting xrootd or
xproofd in the background, and 'xproofd' for a init.d-like script).
TVirtualProofMgr:
Proof Session manager
This class implements manager
functionality for sessions. A manager instance is initialized using the
static method TVirtualProofMgr::Create by passing the URL of the
master, e.g.
root[0]
TVirtualProofMgr
*mgr = TVirtualProofMgr::Create("pcepsft43.cern.ch:5252")
There is one instance per unique master URL. The list of instantiated
managers in available via gROOT->GetListOfProofs(). The list of
sessions known the manager is available via
TVirtualProofMgr::QuerySessions():
root [1] TList
*sessions = mgr->QuerySessions()
// # 1
// alias:
pcepsft43.cern.ch, url: "proof://pcepsft43.cern.ch:5252/"
// tag:
0-pcepsft43-1134569200-31505
// status: idle,
attached: NO (remote ID: 0)
(class
TList*)0x93e5518
To be able to use the session one
needs to attach to it with
TVirtualProofMgr::AttachSession(Int_t locid):
root [2] TProof *p =
mgr->AttachSession(1)
Starting master:
opening connection ...
Starting master: OK
PROOF set to
parallel mode (2 workers)
(class
TVirtualProof*)0x91d59a0
Argument to AttachSession is the local ID of the session as shown by
QuerySessions. The attach operation is fast since there is no
need to start any new process, but just to restore the connection.
A new session can be created using
TVirtualProofMgr::CreateSession(const char *conf_file, ...):
root [3] TProof *p2
= mgr->CreateSession("proof.test.conf")
Starting master:
opening connection ...
Starting master: OK
Opening connections
to workers: OK (2 workers)
Setting up worker
servers: OK (2 workers)
PROOF set to
parallel mode (2 workers)
(class
TVirtualProof*)0x9441070
the main argument being here the name of the configuration file to be
used.
The additional functionality provided by the manager relates to
disconnection; DetachSession(Int_t locid) justs
disconnect
from the session, while ShutdownSession(Int_t locid) terminates the
session. The same actions are available from TProof using the
new
methods Detach() and Detach("S"), respectively; e.g., in the above
example, p2->Detach("S") would terminate the second session.
The full manager functionality requires the new XProofd communication
layer. The class works with reduced functionality also with the
standard communication layer: CreateSession and AttachSession both
create a new session (AttachSession using the default configuration
file; and so are DetachSession and ShutdownSession, both
terminating the session.
Sessions can still be started via TROOT::Proof(...): the relevant
manager is started or attached to internally and the first active
session is attached to; if none is available, a new one is created.
TROOT::Proof returns now a pointer to the started session, to
keep
track of the sessions. For example, equivalent to the above is the
following:
root[0] TProof *p = gROOT->Proof("pcepsft43.cern.ch:5252")
It
is also possible to force the creation of a new session :
root[0] TProof *p2 =
gROOT->Proof("pcepsft43.cern.ch:5252/?N")
The syntax is very convenient to exploit the disconnect/reconnect
functionality when working with only one session.
The manager is able to detect automatically the kind of remote server
(i.e. xprood of prood); this information is avaibale via
TVirtualProofMgr::IsProofd().
Multi
sessions
As mentioned above, the limit to only
one PROOF session per ROOT client session
has been removed. Sessions are started via the manager or
TROOT::Proof(...) as shown above. The global gProof
refers
now to the last open
session or to the session selected via TProof::cd().
The list of active PROOF sessions per manager is available via
TVirtualProofMgr::QuerySessions; the started managers via the global
list gROOT->GetListOfProofs().
Each session has:
- a GUI progress
dialog, which is started when the first processing action is started;
- a list of results (
TQueryResult
objects, see below) which can accessed
via
TProof::GetQueryResults();
- a
unique identifier or session tag, a
string generated by the
master and which can be accessed via
TProof::GetSessionTag();
the session tag contains the master host name, the time at which the
PROOF session has started and the process ID of the top master server.
A Powerful New PROOF Session Management GUI
A new GUI which allows easy access to the many new PROOF features
described above. The GUI is especially important now that we can have
many active PROOF sessions each running mulitple queries. To start the
new PROOF GUI do:
gROOT->Proof()
Other improvements
- GUI progress dialog. The progress
dialog is now started whenever a processing is started, i.e. also for Draw
actions. There is now one dialog box per session (and not per query).
Information about the query processing performance is kept in TQueryResult and can be displayed using
option "F" to TProof::ShowQueries(). The dialog box now also gives the
possibility to display the log messages per query or the whole set. A coherency problem for enabling/disabling
of Stop/Cancel buttons has been
fixed.
- TProof::UploadPackage. Package
uploading to master or to slaves is now done via the already open
connection, i.e. there is no need to start a rootd on each node of the cluster
to receive the packages.
- Progressive packetizer (TPacketizerProgressive). This class implements a new packetizer, a generator of packets to be processed on PROOF slave servers. A packet is an event range (begin entry and number of entries) or object range (first object and number of objects) in a TTree (entries) or a directory (objects) in a file. Packets are generated taking into account the performance of the remote machine, the time it took to process a previous packet on the remote machine, the locality of the database files, etc. This packetizer does not pre-open the files to calculate the total number of events, it just walks sequentially through the list of files.
- Optimization of sequential slave
startup. The two main steps of slave startup have been
de-synchronized allowing to introduce some sort of parallelism without the
use of threads. This allows to significantly improve
the startup time for clusters of relatively slow machines.
- Support for Friend Trees. Friends can be added to a TDSet using
TDSet::AddFriend(). Also TChain::MakeTDSet() creates a TDSet from a
TChain and adds all chain's friends to it.
- Support for Indexes. Indexes can be used with PROOF to connect events
from different trees. There are two ways of using them. The first one
is if the friend has the same number of files. In this case the files
will be matched in the same way as without indexes (i.a. first file
from the main chain with the first file of the friend chain, second
file with the second, etc.) but events inside files are matched
according to values of the index. The second case is if there is only
one file in the friend chain.
Geometry package enhancements
Assemblies of volumes
New classes created to describe volume assemblies:
TGeoVolumeAssembly : public TGeoVolume
TGeoShapeAssembly : public TGeoBBox
An assembly represents a union of more than 2 volumes positioned with
respect to
the local assembly reference frame. Assemblies behave like normal
volumes, but
their shape is defined as the union of the shapes of the volumes
positioned
inside. This shape is represented by the class TGeoShapeAssembly, which
is
automatically created and updated whenever a new node is added to the
assembly
content. This makes the assembly a self-contained volume in the sense
that any
point inside it is automatically inside one of the components. For this
reason
an assembly volume does not need a medium/material nor a shape to be
defined.
Creating an assembly can be done in a very similar way as creating a
volume:
TGeoVolumeAssembly *assembly = new TGeoVolumeAssembly("STRUCT"); // assembly volume
assembly->AddNode(pVol1, id1, pMatrix1); // components of the assembly
assembly->AddNode(pVol2, id2, pMatrix2);
...
The components have to obey the same rule of thumb as any positioned
volume:
they should not overlap each other. On the other hand they formally
cannot
extrude the assembly container since the later is defined by them.
Assemblies can be positioned as nodes in any other volume and support
nesting
and replication. A detailed example of their usage can be found in the
new tutorial assembly.C.
There are several advantages in using assemblies instead of normal
volumes
whenever the definition of a replicated complex structure is needed. In
such
cases generally it is difficult to define a container that perfectly
fits to the
structure, therefore one usualy defines a larger one with a simple
shape. The
problem may appear when positioning this container because it may
overlap with
other volumes (not allowed). To avoid this, people split the structure
in many
components and place them individually without defining a container,
resulting
in flat structures which are hard to optimize at certain geometry
levels. All
these can be avoided by using assemblies. The automatically-generated
TGeoShapeAssembly uses the same optimization mechanisms for navigation
as
volumes.
Assemblies can be browsed as nodes in the geometry tree and generate
an
additional geometry level, but they are invisible during navigation.
Any
navigation query performed in a geometry having assemblies will end-up
in
non-assembly leafs. Tests demonstated that grouping the existing nodes
of a
volume with many components via assemblies improve navigation
performance.
Therefore there is no penalty in performance observed due to usage of
assemblies.
Additions related to navigation
New combined querry:
TGeoNode* TGeoManager::FindNextBoundaryAndStep(Double_t propStep=TGeoShape::Big(), Bool_t compSafe=kFALSE)
The method was optimized to performs several navigation tasks in one
go. Prior
to its usage one have to initialize the current global point/direction
and to
locate the state:
TGeoManager::InitTrack(Double_t *point, Double_t *dir); // or a combination
// performing FindNode() task
After the initialization is completed, one can use the new method to
propagate
the current track to the next boundary. The input propStep is the
maximum step
allowed by the user for locating next boundary. If the boundary is
found further
away, the current point is propagated with propStep and the current
node is
returnes as final location. In case the user requires also computation
of the
safe distance, it has to provide compSafe
= true.
If a boundary is found closer than the proposed step, the modeller
will
propagate the current state with the found distance and the state
(TGeoNode)
after crossing the boundary is returned. The propagation distance to
the
boundary can be retreived via:
Double_t TGeoManager::GetStep()
To test if the boundary crossing really occured, one can use:
Bool_t TGeoManager::IsOnBoundary()
If this is the case, the normal vector to the crossed surface can be
computed
via the "fast" approach:
Double_t *TGeoManager::FindNormalFast()
One can use the new query method to propagate a ray from boundary to
boundary
until getting outside of the geometry. If this is the case, the
computation of
the safe distance make sense only for the first query (for subsequent
ones it
will be 0). To retreive the safe distance one should call:
Double_t TGeoManager::GetSafeDistance()
Capacity of shapes and weight of volumes
Analytical computation of shapes
capacity implemented for most of the shapes:
Double_t TGeoShape::Capacity() const;
The capacity cannot be computed for Boolean shapes in the general
case, so the implementation for TGeoCompositeShape class is providing
an estimate with 1% error (by sampling). Capacity is computed in [length3] where [length] is the used unit in
defining the shape parameters.
The volume weight can be computed for a volume in a recursive way
based on the shape capacity. This represents the sum of the weights of
all daughter volumes plus the weigth of the unoccupied region of the
volume itself.
Double_t TGeoVolume::Weight(Double_t precision=0.01, Option_t *option="va");
In the method above, precision
is meaningful only if the option
does not contain "a" (analytical). In this case the weigth is estimated
by sampling points in the volume bounding box. The letter "v" in option
turns on verbosity.
Note:
For weight computation, the length unit is assumed to be centimeter.
Gases with density less than 0.01 are ignored.
Alignment of physical nodes
Physical nodes represent a unique object in the geometry,
represented by a path like:
/TOP_1/A_1/B_5/C_3
Each element in this path represent a logical node identifier
(volume positioned with respect to its mother volume frame) and
provides a relative transformation matrix with respect to the frame
defined by the upper level. The product of all transformations in the
branch define the unique position of the object in the master frame.
This transformation can be computed only after the geometry has been
closed and represent the original (ideal) position of the object. The
class TGeoPhysicalNode
provides the tools to unalign the object C_3 with another relative
matrix (w.r.t. volume B) after the geometry was closed.
TGeoPhysicalNode::TGeoPhysicalNode(const char *path);
In order to unalign a physical node, one can either modify the
existing matrix of C_3 by casting it to the proper type, or just
provide a new matrix :
TGeoTranslation *tr = (TGeoTranslation*)physNode->GetNode()->GetMatrix();
tr->SetTranslation(new_x, new_y, new_z);
physNode->Align(tr);
If a new matrix was provided, its ownership will pass to TGeoManager
class. Note that one can also change the shape of the aligned node:
void TGeoPhysicalNode::Align(TGeoMatrix *newmat=0, TGeoShape *newshape=0, Bool_t check=kFALSE);
The original global matrix of the physical node before
mis-alignment caAn optional check can be performed to see if the align
operation produces an illegal overlap.n be accessed at any time:
TGeoHMatrix * TGeoPhysicalNode::GetOriginalMatrix() const
The manager class TGeoManager owns the list of all defined physical
nodes:
TObjArray *TGeoManager::GetListOfPhysicalNodes();
Notes:
- Due to possible replication of volumes in the geometry, the
alignment operation needs to duplicate (clone) some volumes and nodes
and to conect them in the geometry tree instead of the existing ones.
For this reason the operation might be expensive in terms of memory
usage and time in case of extensive usage.
- The mother volume of the aligned node need to rebuild its
navigation optimisation structure (voxels) before using the new
geometry for navigation. This operation is postponed for performance
reasons until the first navigation query that involves the changed
structures. Due to this, one might notice a small delay after the first
post-alignment navigation requests.
- Nodes that are the result of a volume division operation cannot
be (mis)aligned. If such an operation is needed, onee needs to change
their definition by simple positioning.
An example of applying mis-alignment to an ideal geometry can be
found at:
$ROOTSYS/tutorials/geodemo.C
http://root.cern.ch/root/html/examples/geodemo.C.html
Miscellaneous
Several improvements or fixes related to: navigation consistency near
boundaries, graphics (mesh poligonal representation), matrix package,
caching.
Major developments related to OGL 3D viewer.
Reflex
Reflex is a new package in the ROOT environment since the 5.x release series.
It provides reflection capabilities for C++. Reflection being the ability to
introspect and interact with C++ "constructs" (e.g. types, scopes,
members, etc.) at runtime in a generic way. With the use of dictionary libraries,
which contain the meta information about C++ definitions, Reflex allows generic
interaction withoug prior knowlegdge about original definitions.
For the time being Reflex is an optional package in ROOT. If the build of
the Reflex library is wanted it has to be triggered with "--enable-reflex" at
the configuration step of the ROOT build procedure. In a mini-workshop in May
2005 at CERN it was decided that Reflex will closely cooperate with CINT. Below
you may find a brief overview of the features, way of interaction and main
user types of the package. For any more details on the functionality of the
package, the current status and future developments concerning this cooperation
with CINT please check out the ROOT
workshop presentation about Reflex.
The main features of Reflex are:
- close to ISO/IEC standard for C++
- light and standalone system without external
dependencies
- automatic and non-intrusive generation of reflection information
- dictionaries
can be produced for every gcc compatible source code
- written for multi platform/compiler
- optimized on (dictionary) library size
and memory consumption
The usual way of generating dictionary information for and interacting with
Reflex is as follows:
- The C++ files containing the definition of the types the dictionary information
is wanted for are parsed and dictionary source code (in C++) is produced.
There are two ways how this source code can be generated.
- CINT can parse the C++ definitions and a front-end (similar
to rootcint/makecint) will generate C++ dictionary source code
- an extension of the gcc compiler called gccxml parses
the definition files and generates XML output. This XML information is
further processed by a Python script which generates C++ dictionary source
code from it (not committed to the Root cvs repository yet)
- The so generated C++ files are compiled into a library
- Through a Builder API the dictionary library will be loaded
into the Reflex system
- The Reflex user API provides the reflection information about the original
C++ definitions.
The main user types of the Reflex API are:
- Type is an abstraction of a C++ type. Types are pointers, pointers
to member, typedefs, arrays, functions, fundamentals, unions, enums and classes.
- Scope is an abstraction of a C++ scope which are classes, namespaces,
enums and unions.
- Member is the abstraction of either a data- or a function member.
- Object is the abstraction of a C++ object. An object is of
a given type and allocates an amount of memory.
- PropertyLists can be attached to Types,
Scopes and Members and are containers of key value pairs. The
key being a string and the value an object of arbitrary type.
- Base is the abstraction of a C++ base class. It contains information
such as the type of inheritance and the base class offset.
- TypeTemplate the abstraction of a templated type.
- MemberTemplate the abstraction of a templated member.
- Added scripts for reflex code generation. These will be
installed automatically. In order to use them ROOT has to be
configured with the option --with-gccxml=/dir where the argument is
the path to the gccxml executable. The two scripts installed are:
- genreflex which is the native dictionary generation
script. Type genreflex --help for more details
- genreflex-rootcint takes the same options as rootcint but
will generate reflex dictioanary source code via gccxml
genreflex and genreflex-rootcint also pass in a macro __REFLEX__
which can be used similar to __CINT__ to prevent certain information
to appear in the dictionaries. The python scripts will be installed
in $ROOTSYS/lib/python/genreflex. The invocation can be done through
shell scripts from $ROOTSYS/bin
- Added test suite to reflex. In order to run ROOT has to be
configured with the option --with-cppunit=/dir where the argument
is the root directory of a CppUnit installation. The target for
running the test suite is check-reflex
- Added autobuild files. In order to use, you may run
build/autogen in the reflex directory. Then the usual ./configure;
make; make install
- ChangeLogs from the SEAL repository can be found in doc/
Code changes since the import from the SEAL repository:
- In respect to the code in the SEAL repository the API has
changed - details can be found in doc/ChangeLog.reflex
- Extended number of possible function parameters for dictionary
generation to 32
- Extra stub functions are generated for new/delete of arrays of
types
- Added stl like iterators for all containers in the API to
e.g. loop over all data members of a scope
- Added support for lookup of overloaded member functions
Cintex
Cintex is a new package in the ROOT environment since the 5.x release series.
It provides a (uni-directonal) gateway from Reflex dictionary information to
CINT dictionary information.
This gateway allows CINT users to interact seemlessly with Reflex dictionary
information. As Reflex dictionary information is very small both in library
size and memory allocation the additional overhead using this gateway is also
small.
Enabling the Cintex gateway is done through the static function "Cintex::Enable()".
Once this function has been called all Reflex dictionaries currently in memory
or dictionaries loaded in the future will be propagated to CINT's internal
memory structures.
For the time being Cintex is an optional package in ROOT. If the build of
the Cintex library is wanted it has to be triggered with "--enable-cintex"
at the configuration step of the ROOT build procedure. Cintex is an internal
package to the ROOT framework and should not be visible for the "general" ROOT
user.
Cintex and Reflex Integration
As a non-production, developer testing feature, rootcint can generate
dictionaries which use the Reflex API.
There are two options to generate such a dictionary: using cint's C++ parser, and using gccxml.
The latter allows to validate and study the gccxml generated dictionaries.
None of them is meant to be a replacement for Cint's dictionaries yet;
functionality is limited, even when using Cintex.
You can generate reflex dictionaries for ROOT itself, loading the dictionaries
into Cint using Cintex.
You can not, however, generate non-cint dictionaries for any classes in Core,
Hist, Graf, Graf3d, Gpad, Tree, and Matrix, due to dictionary initialization
problems.
In a future release, Cint's dictionaries will be replaced by Reflex
dictionaries.
ROOT will support both generator options, rootcint and gccxml;
there will be no need for Cintex, as Cint will use the Reflex API directly.
Reflex dictionary with rootcint
To generate a reflex dictionary with the Cint code parser, add -reflex
as the first parameter to rootcint.
Alternatively, if the environment variable ROOTDICTTYPE=reflex
is set, rootcint generates reflex dictionaries.
The latter option allows an easy, temporary switch for your code where your Makefile invokes rootcint.
Reflex dictionary with GCCXML
To generate a Reflex dictionary with the GCCXML code parser, add
-gccxml as the first argument to rootcint, or set the environment
variable ROOTDICTTYPE=gccxml.
Rootcint will invoke a python script that generates the dictionaries
using gccxml.
It is known not to work on ROOT's build for Windows.
If you want to use these dictionaries with Cintex (i.e. insert them into Cint),
you have to call Cintex::Enable() before loading your library.
PyROOT
There are several improvements to the pythonization of ROOT classes, the
interaction with the interpreter environment, and the treatment of
(low-level) C++ features.
Python/C++ language features
Support is added for inner classes, templated classes (in particular: STL),
pre-processor macro's of builtin types, ptr-to-ptr and ref-ptr argument types,
object return-by-value, object argument-by-value, double/long argument-by-ref,
range-checking of unsigned integer types, array assignment, and the supported
array/buffer types have been completed for all C++ builtins.
The memory policy has been extended to use either heuristics (default) or to
be strict, the ownership of individual objects can be set by hand, addresses
of objects can be taken, all C++ typedefs now map onto the same python type,
and typed null pointers (for use as value holders through pass-by-ref) can be
created. A generic __setitem__ handler has been added that will allow
assignment if a C++ class offers return by reference for operator[](int).
Interpreter environment
The python help() system is now supported: it will e.g. show the C++
signatures of functions. CINT errors/warnings are treated as python
exceptions/warnings and error reporting has been improved, e.g. overloaded
functions that fail show a message for each individual overload.
The .L CINT command is supported, objects from TFile's can now be used
directly, cf. RINT, and the initial startup environment is more closely
mimicking RINT. Tab-completion is added for file names in the local directory
structure. Wrapper object prints show the C++ object address. Further
workarounds for IPython are provided.
During startup, no GUI thread will be started in batch mode, and the creation
of a TApplication object can be pre-empted. The shutdown sequence of the ROOT
module has been made explicit, and, in interactive mode, C++ signals such as
segmentation violations are turned (after a printing stack trace) into python
exceptions. C++ globals now act just like python globals do.
Pythonization
TMinuit::SetFCN now accepts python functions, as do TF2/3 (modeled after the
support for TF1). Use of TClonesArray is now safe. TTree, TBranch, and TFile
member templates are available: the appropriate casting is done internally,
based on the available run-time type information.
TTree direct data access has been improved in speed and functionality.
STL vector and string can be used with python-style iteration.
Linear Algebra package: IMPORTANT WARNINGS
The next version (in 2006) of the TMatrix and TVector classes will be using templates.
As a result, the classes currently named TMatrixD, TMatrixF, TVectorD, TVectorF
will become typedefs to TMatrix, TMatrix, TVector, TVector.
The new package itself is totally back compatible.
However you will not be able anymore to use forward declarations of the type
class TMatrixD;
class TVectorF;
These declarations will have to be replaced respectively by:
#include "TMatrixDfwh.h"
#include "TVectorFfwd.h"
We STRONGLY recommend to already use these includes with this release 5.08.
The includes Txxxfwd.h are simple forward declarations. In the next release, these include
will contain the correct declaration of TMatrixD, TVectorF using the corresponding typedefs.
TF1, TF2, TF3
Functions GetMinimumXY() and GetMinimumXYZ() were implemented in classes TF2 and TF3.
These new functions allow to find the x and y (x, y and z) values, corresponding to
the minimum of the function on its range. Method: first, a grid search is performed
to find the initial estimate of the minimum location. Then, this initial estimate is
used as the starting parameter of Minuit minimization.
Function TF1::GradientPar(), used by the TVirtualFitter::GetConfidenceIntervals() functions of the fitter
classes, was added to TF1. It computes the gradient of the function wrt parameters
at the selected point.
Improvement of min/max finding routines. Now first a grid search is
performed to bracket the extremum and then Brent's method is used for
minimization. Brent's method is a combination of golden section search
and parabolic interpolation.
Minimization and fitting
TVirtualFitter
A new function GetConfidenceIntervals() was added to the TVirtualFitter, TFitter
and TLinearFitter classes. It computes confidence intervals on the fitted function.
Two interfaces are provided, one to simply compute the intervals at the selected
points, the other to facilitate drawing of computed intervals along with the fitted
function and histogram/graph.
Robust fitting - Least Trimmed Squares regression (LTS)
A new method for robust fitting was added to the TLinearFitter class, to
be used for fitting linear functions in presense of outliers in the data.
Even a single gross outlier can greatly influence the results of least-
squares fitting procedure, and in this case use of robust(resistant)
methods is recommended.
The method implemented here is based on the article and algorithm:
Computing LTS Regression for Large Data Sets by P.J.Rousseeuw and
Katrien Van Driessen.
The idea of the method is to find the fitting coefficients for a subset
of h observations (out of n) with the smallest sum of squared residuals.
The size of the subset h should lie between (npoints + nparameters +1)/2
and n, and represents the minimal number of good points in the dataset.
The default value is set to (npoints + nparameters +1)/2, but if you are
sure that the data contains less outliers it's better to change h
according to your data.
To perform a robust fit one can
Note, that standard errors on parameters are not computed!
TMath
New function Quantiles(), that computes sample quantiles. All 9 commonly used
definitions of sample quantiles are provided, with default being the same as in
the R-package.
New MathCore Package
This is a new package introduced in ROOT version 5. It provides
a collection of functions and C++ classes for HEP numerical computing.
This library provides the basic and most used mathematical
functionality, while MathMore provides more advanced functionality.
MathCore contains up to now:
See here for more information on the GenVector package and for the API documentation. The test program stressVector.cxx in the ROOT test directory show the capabilities of the GenVector classes comparing the performances with the ROOT Physics classes. The new tutorial mathcoreVectorIO.C show how to write and read in a Tree the new mathcore LorentzVector classes and the tutorial mathcoreVectorCollection.C how to store a collection of LorentzVector's in a std::vector container and to archive them in ROOT Treee. The tutorial mathcoreGenVector.C test the package and provide as well examples on how to use the GenVector classes.
MathCore can be built as an independent package from a tar file or directly from CVS. The library built in ROOT contains in addition the CINT dictionary for all mathcore classes and a big fraction of all the templated functions.
All the classes and functions of MathCore are in the namespace ROOT::Math and the header files are installed under $ROOTSYS/include/Math.
More detailed description of the current released MathCore, including the reference documentation and the link to download, can be found at this location.
New MathMore Package
It is a new package introduced in the present version of ROOT. It
incorporates mathematical functionality which might be needed for an
advanced user (as opposed to MathCore which addresses the primary needs
of users). The need of separating the mathematical functionality is
twofold. In order to keep the size of the core of ROOT reasonable only
the most used mathematical functionality should be included in it.
Secondly, there are licensing issues concerning some of the more
advanced functionality which uses GSL. One of the design goals is to
hide the implementation, i.e. presently for most of the mathematical
functionality GSL is used underneath. However, it would be very easy to
shift to another package, like CEPHES, or any other package appearing
in the future, it would be completely transparent to the user and
straightforward for the developer. As of now, MathMore is composed of
the following major parts:
- Special Functions: bessel
functions with fractional order, elliptic integrals, Laguerre and
Legendre polynomials, hypergeometric functions.
- Cumulative Distribution
Functions and their inverses: cumulative distribution functions
of chi-squared, gamma, f and t-distributions and their inverses. There
are also the inverses of the CDFs of the Breit-Wigner, exponential,
Gaussian, lognormal and uniform distributions.
- Function Infrastructure:
definition of function classes that the user can inherit from combined
with some implementations (for example ParamFunction for parametric
functions). Also provides wrappers to encapsulate global C functions
and use them in the mathematical operations.
- Derivation: classes for
computing numerical derivatives of a function.
- Integration: classes for
performing numerical integration of a function in one dimension.
Various types of adaptive and non-adaptive integration are supported.
These include integration over infinite and semi-infinite ranges and
singular integrals.
- Interpolation: classes
for performing function interpolation of points using linear,
polynomial, Akima and Akima periodic algorithms.
- Root Finding: classes
which find the root of one dimensional functions. The possible types of
root-finding algorithms are:
- Root Bracketing Algorithms which they do not require function
derivatives
- Bisection
- False position
- Brent-Dekker
- Root Finding Algorithms using Derivatives
- Chebyshev Polynomials:
Class describing a Chebyshev series which can be used to approximate a
function
in a defined range.
Obviously, as user needs might evolve, we intend to add new
functionality. More detailed description can be found at
the MathMore reference documentation.
Disclaimer: as it is a new
package, some user needs might have been ignored. As we will
continually try to improve ROOT there might be a slight evolution in the
user interface in the initial stage if strong user needs arise to do so.
New Package SMatrix
Add new package for linear algebra matrices and vectors, optimized for small dimension sizes. The matrix and vector classes are templated on the scalar type and on the matrix and vector dimensions. Therefore, they can be used ONLY when the dimensions are known at compile time. The package uses expression templates to achieve an high level optimization by minimizing the creation of temporary objects when performing matrix operations. The package has been developed initially by T. Glebe as part of the HeraB analysis software (see here) and a subset of the original package has been now ported to ROOT and adapted to meet the ROOT coding conventions and to satisfy the requirements of the LHC experiments. In particular the following modifications or improvements have been applied:
- optimized Cramer inversion for matrices up to size 6x6
- methods to invert a matrix and to calculate the determinant which are const (i.e they do not change the original content of the matrix)
- possibility to return, as a copy, a sub vector or a sub matrix
- support for STL like iterators
The test program in smatrix/test directory, testOperation.cxx and testKalman.cxx show how the SMatrix and SVector classes can be used and measure the CPU performances in matrix and vector operations comparing with the TMatrixD and TVectorD classes from the ROOT Matrix library.
More information on the new SMatrix package can be found at this location.
New Package Minuit2
This package contains the new object oriented re-implementation of MINUIT in C++, developed by M. Winkler and F. James in the context of the SEAL project. These new version contains basically all the functionality present in the old Fortran and TMinuit version. Furthermore, it provides the FUMILI algorithm, for least square and log likelihood minimizations. More information on the new C++ can be found on the MINUIT Web Site.
Minuit2 contains the C++ MINUIT package imported in ROOT from the SEAL project. The API has been changed to follow the ROOT coding convention (function names starting with capital letters) and the classes have been moved inside the namespace ROOT::Minuit2. In addition, the ROOT distribution contains classes needed to integrate Minuit2 in the ROOT framework. Two implementation of the TVirtualFitter interface exist: TFitterMinuit and TFitterFumili, which define two different fitter plug-in's: Minuit2 and Fumili2. Some helper classes are present for implementing the objective function interface (FCNBase) required by MINUIT minimization.
Minuit2 can be used through the TVirtualFitter interface or directly using the C++ interface of the ROOT::Minuit2 classes.
For example for fitting an histogram via the TVirtualFitter, one needs to select first the Minuit2 fitter plugin by:
TVirtualFitter::SetDefaultFitter("Minuit2"); // or Fumili2 for the FUMILI algorithm
h1->Fit()
or for minimization problem, passing the FCN function to minimize, one can do:
TVirtualFitter::SetDefaultFitter(fitter);
TVirtualFitter * minuit2 = TVirtualFitter::Fitter(0,2);
and then set the parameters, the FCN and minimize using the TVirtualFitter methods: SetParameter, SetFCN and ExecuteCommand like in the old minuit example tutorial. Examples on how to use the Minuit2 and Fumili2 plug-in's are provided in the tutorials minuit2FitBench.C, minuit2FitBench2D.C and minuit2GausFit.C .
Examples on how to use directly Minuit2, without the ROOT interface are provided in the tests present in the directories minuit2/tests/MnSim and minuit2/test/MnTutorial. More information on the C++ interface can be also found on the new MINUIT user guide or looking at the reference documentation.
Minuit2, without the ROOT TVirtualFitter interface classes, can be built and used as an independent package. See the file minuit2/build/INSTALL.
New class TSPlot
A
common method used in High Energy Physics to perform measurements is
the maximum Likelihood method, exploiting discriminating variables to
disentangle signal from background. The crucial point for such an
analysis to be reliable is to use an exhaustive list of sources of
events combined with an accurate description of all the Probability
Density Functions (PDF).
To assess the validity of the fit, a
convincing quality check is to explore further the data sample by
examining the distributions of control variables. A control variable
can be obtained for instance by removing one of the discriminating
variables before performing again the maximum Likelihood fit: this
removed variable is a control variable. The expected distribution of
this control variable, for signal, is to be compared to the one
extracted, for signal, from the data sample. In order to be able to do
so, one must be able to unfold from the distribution of the whole data
sample.
The TSPlot method allows to reconstruct the
distributions for the control variable, independently for each of the
various sources of events, without making use of any a priori knowledge
on this variable. The aim is thus to use the knowledge available for
the discriminating variables to infer the behavior of the individual
sources of events with respect to the control variable.
TSPlot is optimal if the control variable is uncorrelated with the discriminating variables.
A
detail description of the formalism itself, called sPlot is given in M.
Pivk and F.R. Le Diberder, Nucl.Inst.Meth.A(in press), physics/0402083
More information about the method and some examples of usage can be found in the TSPlot class description and tutorials.
New class TGraphQQ
This new class allows to draw quantile-quantile plots.
Quantile-quantile plots are used to determine if 2 datasets come from the
same distribution, or if 1 dataset comes from specified theoretical distribution,
such as normal.
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. More information and some examples
can be found in the class description
GUI
New features in TRootBrowser
- browsing files in the different image formats:
xpm, gif, jpeg, png, tiff, tga, ppm, pnm, bmp, xbm, xcf, cur, ico.
- browsing PS, EPS, PDF files (gs, aka GhostScript program must be installed).
- dynamic generation of icons. If some macro after execution creates a new canvas
a small image with canvas content becomes a new icon for this macro.
- If file is a text file its content will be displayed in the right pane
of the browser. If it's a C++ macro after execution
it can be editted in the browser and re-executed.
- new toolbar buttons added which allow:
- forward, backward "history navigation"
- refresh browser content
- invoke "find dialog"
- execute editted macro
- interrupt editted macro execution
- save editted macro
- Implemented a new check box feature to TGListTree widget. This option
allows checkboxes on the tree nodes to turn on/off pieces of the tree
hierarchy. Used in the ROOT browser to toggle visibility of geometries.
The different checkbox states are as follows:
- Checked: the list tree item and all its children are checked;
- Unchecked: the list tree item and all its children are unchecked;
- Checked and greyed: the list tree item is checked, but at least one
of its children is not;
- Unchecked and greyed: the list tree item is unchecked, but at least
one of its children is checked
This new feature can be used as shown below:
TGListTree *fLt;
fLt = new TGListTree(fTreeView, kHorizontalFrame, fgWhitePixel);
...
// Add an item with a checkbox to the list tree.
TGListTreeItem *item = fLt->AddItem(0, name, obj, 0, 0, kTRUE);
// Check or uncheck this item setting the second parameter to kTRUE or kFALSE.
fLt->CheckItem(item, (Bool_t)check);
Usage of this feature with the TBrowser:
void AnyClass::Browse(TBrowser b) {
// Add the class 'AnyClass' to the browser.
b->Add(this);
// Add a checkbox to the list tree item. The parameter 'ischecked' is Bool_t variable.
b->AddCheckBox(this, ischecked);
// Connect the Checked() signal to a slot method of AnyClass.
Connect("TRootBrowser", "Checked(TObject*,Bool_t)", "AnyClass", this, "SetChecked(TObject*,Bool_t)");
}
The new methods added to TGListTree class are:
- CheckItem(TGListTreeItem *item, Bool_t check = kTRUE);
- SetCheckBox(TGListTreeItem *item, Bool_t on = kTRUE);
- ToggleItem(TGListTreeItem *item);
- Checked(TObject *obj, Bool_t check); //*SIGNAL*
- and the checkbox option in: AddItem(..., Bool_t checkbox);
In addition, the new icons for list tree item check boxes were created in
relation to the existing TGeo shapes. Added mime types linking new icons
to the object types.
Added a new member / option in TGListTree allowing to disable item opening on doubleclick.
- TCanvas objects (for example stored in a ROOT file) can be embedded
dynamically into a TRootEmbeddedCanvas following way:
TCanvas* oldCanvas = fEmbeddedCanvas->GetCanvas();
if (oldCanvas) {
delete oldCanvas;
}
// Get a canvas from the file.
fCurrentCanvas = (TCanvas *)file->Get(CanvasName);
if (fCurrentCanvas == 0)
return;
fEmbeddedCanvas->AdoptCanvas(fCurrentCanvas);
fCurrentCanvas->Draw();
fCurrentCanvas->Modified();
fCurrentCanvas->Update();
- Improvements in the popup menus and cascaded menus behavior. Users are allowed
to change the title of the context menu by:
TObject* anyObj;
anyObj->IsA()->SetContextMenuTitle("myTitle");
- Added two new methods to the TGView class that help to show the top or
the bottom of the text viewer page.
- TGListView - support listbox entries with icons in addition to the text.
Style Manager
- This new Graphical User Interface is created to manage the styles in
a ROOT session. It allows users to edit styles, to import, export them
using macros, to apply a currently selected style on the selected object
or on all canvases, to change the gStyle.
The Style Manager interface is composed of two parts:
- the top level interface that manages a list of styles;
- the style editor, which deals with the current style settings.
- The top level interface contains:
- The combo box 'Available Styles'
that shows the list of all available styles in the current ROOT session.
The field on the right shows the setting of the gStyle. You can set the
global variable gStyle to the selected style by clicking on the button
in the middle.
- The group frame 'Apply on' displays information for the currently
selected canvas and object in the ROOT session. This selection might
be changed by clicking on another object with the middle mouse button
You have a choice to apply a style on the selected object or
on all available canvases.
WARNING: You cannot undo the changes after applying the style! If
you are not sure of that action, it may be better to see a preview
of what you are going to apply.
If the check button 'Preview' is selected, a preview of the selected
canvas according to the selected style will be shown. The selection
of the next check button 'Run Time Preview' will apply updates of
the preview any time a value of the selected style is changed. For
drawings that take a time it is better to disable this option.
- Create a new style:
A new style can be created via the Style menu/New... or the toolbar.
A clone of the selected style will be used as a base of the new
style. All its values can be modified via the style editor later.
The dialog that appears will ask for the name and description of the
new style.
- Import a style (from a macro):
A style macro can be imported at any time. The new imported style in
the ROOT session will become the selected one.
- Import a style (from a canvas):
You can do that selecting the Style menu/Import from.../Canvas or
the corresponding Tool bar button. A new style will be created in the
ROOT session and will become the selected one. This style is a clone
of the gStyle with modified values as they are set in the currently
selected canvas. You can import a style from any canvas and apply it
later on some objects.
- Export a style (in a C++ macro file):
To store a style longer than for the current ROOT session you can
save it in a C++ macro file. This can be done via the menu or the
tool bar button. There is a naming convention for the style macros:
the name must be 'Style_*.C', where * can be replaced by anything
you want.
- Delete a style:
The selected style can be deleted from the list when you use the
Style menu/Delete or the corresponding tool bar button. The selected
style is removed from the list of all available styles for the
current ROOT session. WARRNING: it will be lost if you didn't saved
it in a C++ macro file before its deletion. Also, you cannot delete
the selected style if it is set to gStyle. A message 'Can not delete
gStyle' will be displayed on the CINT prompt.
- The style editor interface:
- Open / close the style editor:
The button 'Edit >>' opens the style editor and its label changes to
'Close <<'. For all details of what can be changed and how please see
the provided Help.
- Reset a style (to a previously saved state):
When the editor is opened, the 'Reset' button allows you to reset
the values of the selected style for editing. Doing that you cancel
all changes made since the last time you saved that style in a macro.
If the selected style is one of the five ROOT styles (Plain, Bold,
Video, Pub or Default), it will be recreated.
- Update the preview:
The button 'Update Preview' is available when a preview is shown and
the run time option is not selected. This button allows you to
refresh the preview any time you want to see how the style you edit
looks like.
- Help button:
Provides a help of the currently selected tab.
Object Editors Improvements
- Marker Editor - the marker pop up window shows 18 predefined marker types for user choice;
3 of them (type 1, 6, 7) have fixed size. The marker size combo box is
replaced by a number entry for faster size setting.
- Histogram Editors - improved performance of both TH1/2Editor .
The interface of TH1Editor works for histograms drawn with option 'same';
Qt Interface
OpenGL developments:
Features and Interaction
-
New code to draw shapes outline style - enable with
't' key. This provide s a 'line-drawing' style, with filled polygons outlined
in black - rendering take approx twice as long. Draw styles now:

- Interactive clipping
- Enable under Scene/Clipping in the side GUI panel
- Two types - plane and box
-
- Adjust via direct entry in properties of GUI boxes, or interactively.
Check 'Show/Edit' checkbox - clip object is shown in light brown in
viewer. Current manipulator is attached to it allowing in place editing
(see below for use)
-
Manipulators - widget attached to selected object (limited
to clip object s only at present). Allows manipulation along/around local
axis (red/X, green/Y, blue/Z). In some cases a manipulation is not permitted
(e.g clip plane cannot be scaled) in which case manipu lator component
is greyed and inactive. Three types:
-
Translation - Translation along local axis (v key)
-
Scaling - Scale along local axis (x key)
-
Rotatation - Rotate local axis (c key)

- Extended camera interactions
- Rotate (Orbit) : LMB + Drag
- Truck (Pan) : MMB + Drag, or arrow keys.
- Dolly (interactive move in/out) : RMB + Drag
- Zoom (field of view) : Mouse Wheel, or 'j' / 'k' keys.
- Modifiers applied to above adjust sensitivity
- Shift: x 10
- Ctrl: x 0.1
- Shift+Ctrl: x 0.01
- Double click any button to reset the camera.
- Moved selected object interaction to:
- Select : Shift + LMB
- Move Selected Object : MMB + Shift
- Context Menu Selected Object: RMB + Shift
- New options for axes (draw at scene edge or through origin) and simple
reference position marker - moved to 'Guide' tab under 'Scene' is GUI.
- Transparent objects:
- Picking - now pick closest opaque objects first, and if none closest
transparent one.
- Ensure transparent selected object is only drawn once.
- Allocate pro-rata time for transparent drawing - previous assumption
that number transparent << number opaque was invalid in some
cases.
- Improvement to perspective cameras - level floor formed from 2 of the 3
world axes - avoids tipping of horizon. Added missing two combinations
under renamed 'Camera' menu:
- Perspective (Floor XOZ) - default.
- Perspective (Floor YOZ)
- Perspective (Floor XOY)
- Two interaction modes for rotation manipulator
- Normal - when ring is at reasonable angle - follow ellipse round
as previously (with line to dragged point on ring)
- Shallow - when ring plane is at shaloow angle to eye (very tight
ellipse) - use pixel delta (drag) on viewport along ring plane (with
movement arrows)
- Improvements to orthographic cameras - Larger range/sensitivities, better
auto-framing, lighting.
Performance / Quality
Major internal re-structuring of GL viewer to support:
- Repeated addition of duplicate placed shapes - added new
classes TGLLogicalShape (a unique local frame 'shape') and TGLPhysicalShape
(a placement of TGLLogicalShape), held in stl::maps in new TGLScene. Previous
shape hierarchy TGLScene object moved to local reference frame, and derives
from TGLLogicalShape. TGLPhysical shape holds translation matrix,
and color/transparency attributes, loads these before asking the referenced
TGLLogicalShape to draw.
- Dynamic scene builds: Only accept objects of interest into viewer - fall
within expanded camera limits, and above certain size c.f. whole scene. Viewer
can prompt external client (pad) to republish objects to it, when camera
limits have changed significantly. Logical shapes always retained, physicals
ones destroyed and cretaed as camera moves through scene. Enables viewer
to connect to very large geometries without being overloaded, pulling
required parts on demand. Extended TGLCamera class with OfInterest() +
other internals to test.
- Level of detail (LOD) scheme: Calculate a hint for quality of tessellation
(by projecting shape bounding box onto screen). Shape's Draw() passed this,
based on projected screen size - enable sensible tessellation (TGLSphere
only using at present).
- Common display list cache: TGLLogicalShape and TGLPhysicalShape derive
from common TGLDrawable, and can enable capture to common TGLDisplayListCache,
including LOD hints (caches each Draw of certain quality). TGLDrawable can
disable caching of general or LOD basis. (TGLSphere only using at present).
- Multi-pass rendering:
- Interactive (speed). Reduce all shapes LOD hint (tessellation cost),
draw sorted from large -> small objects, terminate after 150msec,
discard very low (small) LODs.
- Final(quality) - full LOD quality, unlimited time, no dropping.
Misc Internals
- TGLPerspectiveCamera/TGLOrthoCamera: Improve near/far clip plane calculations
- set using current projected scene limits. Reduces depth buffer precision
problems - seen particularly on MESA software GL.
- Added new TGLBoundingBox, supports both axis aligned and orientated BB,
with various overlap/projection testing in conjunction with TGL Camera classes.
- Tuning based on VTune examination
- Cache axes in TGLBoundingBox, reduce creation/destruction of excessive
temp objects.
- Add a cheap sphere/sphere test first in TGLBoundingBox::Overlap
- Only do scene rebuilds after a final quality draw has completed.
Added several debugging aids:
- Viewer debug mode - enable with 'd' key. Viewer stops automatic scene rebuilds
- these can be force explicitly using space key. Also draws out:
- Scene bounding box + center sphere (Green)
- Origin (0,0,0) as white sphere
- Camera interest frustum basis (Red)
- Camera interest frustum basis as box (Orange)
- Current interest box (Blue)
- Previous interest box (Grey)
- Active light positions (yellow spheres)
- Tracing of viewer scene contents, draw loads, timing etc - variable level
of detail from gDebug=3 to gDebug=6
GL-in-TPad
- Reorganize internals of GL viewer to allow it to be embedded
directly into TP ad object.
- Removed all GUI components from core TGLViewer,
created new TGLSAViewer (SA = Standalone), derives from TGLViewer and
contains the TGLSAFrame GUI.
- Created new TGLManager (replacement for TGLKernel/TVirtualGL)
a base abstract class, responsible for window creation, gl-context/glpixmap
and context creation, manipulation with gl-context and gl-pixmap.
TGWin32GLManager - concrete implementation for Win32
TGX11GLManager - concrete implementation for X11.
- GL-in-TPad enabled with: gStyle->SetCanvasPreferGL(kTRUE) to
turn on GL support.
- Legos and Surfaces can be displayed with GL directly in a TPad. Almost
all the standard option are available (SURF, SURF1, LEGO, LEGO1 etc .. )
- File output can be done in gif, jpeg, pgn etc .. formats.
- Development still in progress - notable limitations:
- Can be used with g3d
and geom now (not with hists, polylines or polymarkers, composite shapes
do not work).
- In case of complex geometry the selection is very slow now.
- It is not yet possible to do the output in a PostScript file.
3D Viewer Infrastructure Overview
The 3D Viewer infrastructure has had a re-design to better support more advanced
viewers. It consists of:
- TVirtualViewer3D interface: An abstract handle to the viewer, allowing
client to test preferences, add objects, control the viewer via scripting
(to be added) etc.
- TBuffer3D class hierarchy: Used to describe 3D objects
("shapes")
- filled /added by negotiation with viewer via TVirtualViewer3D.
Together these allow clients to publish objects to any one of the 3D viewers
(currently OpenGL/x3d,TPad), 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.
Publishing to a viewer consists of the following steps:
- Create / obtain viewer handle
- Begin scene on viewer
- Fill mandatory parts of TBuffer3D describing object
- Add to viewer
- Fill optional parts of TBuffer3D if requested by viewer, and add again
... repeat 3/4/5
as required
- End scene on viewer
Creating / Obtaining Viewer
Create/obtain the viewer handle via local/global pad - the viewer is always
bound to a TPad object at present [This may be removed as a restriction in
the future] . You should perform the publishing to the viewer described below
in the Paint() method of the object you attach to the pad (via Draw())
TVirtualViewer3D * v = gPad->GetViewer3D("xxxx");
" xxxx" is viewer type: OpenGL "ogl", X3D "x3d" or
Pad "pad" (default). The viewer is created via the plugin manager,
attached to pad, and the interface returned.
Begin / End Scene
Objects must be added to viewer between BeginScene/EndScene calls e.g.
v->BeginScene();
.....
v->AddObject(....);
v->AddObject(....);
.....
v->EndScene();
The BeginScene call will cause the viewer to suspend redraws etc, and after
the EndScene the viewer will reset the camera to frame the new scene and redraw.
[x3d viewer does not support changing of scenes - objects added after the
first Open/CloseScene pair will be ignored.]
Filling TBuffer3D and Adding to Viewer
The viewers behind the TVirtualViewer3D interface differ greatly in their
capabilities e.g.
- Some know how to draw certain shapes natively (e.g. spheres/tubes in
OpenGL) - others always require a raw tessellation description of points/lines/segments.
- Some
need the 3D object positions in the global frame, others can cope with
local frames + a translation matrix - which can give considerable performance
benefits.
To cope with these situations the object buffer is filled out in negotiation
with the viewer. TBuffer3D classes are conceptually divided into enumerated
sections Core, BoundingBox, Raw etc (see TBuffer3D.h for more details).
The SectionsValid() / SetSectionsValid / ClearSectionsValid() methods of TBuffer3D
are used to test/set/clear these section valid flags.
The sections found in TBuffer3D (Core/BoundingBox/Raw Sizes/Raw)
are sufficient to describe any tessellated shape in a generic fashion. An additional ShapeSpecific section
in derived shape specific classes allows 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, which can bring
considerable performance and quality benefits, 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 Core section.
- Complete the ShapeSpecific section
if applicable.
- Complete the BoundingBox if you can.
- Pass this buffer to the viewer using
one of the AddObject() methods - see below.
If the viewer requires more sections to be completed (Raw/RawSizes) AddObject()
will return flags indicating which ones, otherwise it returns kNone. You must
fill the buffer and mark these sections valid, and pass the buffer again. A
typical code snippet would be:
TBuffer3DSphere sphereBuffer;
// Fill out kCore...
// Fill out kBoundingBox...
// Fill out kShapeSpecific for TBuffer3DSphere
// Try first add to viewer
Int_t reqSections = viewer->AddObject(buffer);
if (reqSections != TBuffer3D::kNone) {
if (reqSections & TBuffer3D::kRawSizes) {
// Fill out kRawSizes...
}
if (reqSections & TBuffer3D::kRaw) {
// Fill out kRaw...
}
// Add second time to viewer - ignore return cannot do more
viewer->AddObject(buffer);
}
}
ShapeSpecific: If the viewer can directly display the buffer without
filling of the kRaw/kRawSizes section it will not need to request client side
tessellation.
Currently we provide the following various shape specific classes, which the
OpenGL viewer can take advantage of (see TBuffer3D.h and TBuffer3DTypes.h)
- TBuffer3DSphere - solid, hollow and cut spheres*
- TBuffer3DTubeSeg - angle tube segment
- TBuffer3DCutTube - angle tube segment with plane cut ends.
*OpenGL only supports solid spheres at present - cut/hollow ones will be
requested tessellated.
Anyone is free to add new TBuffer3D classes, but it should be clear that the
viewers require updating to be able to take advantage of them. The number of
native shapes in OpenGL will be expanded over time.
BoundingBox: You are not obliged to complete this, as any viewer
requiring one internally (OpenGL) will build one for you if you do not provide.
However
to do this the viewer will force you to provide the 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, SetAABoundingBox(),
for simpler case of setting an axis aligned bounding box.
Master/Local Reference Frames
The Core section of TBuffer3D contains two members relating to reference
frames:
fLocalFrame & fLocalMaster. 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
colum major ordering) for placing the object into the 3D master frame.
If fLocalFrame is kFALSE, fLocalMaster should contain an
identity matrix. This is set by default, and can be reset using SetLocalMasterIdentity() function.
Logical & Physical Objects
There are two cases of object addition:
- Add this object as a single independent entity in the world reference
frame.
- Add
a physical placement (copy) of this logical object (described in local
reference frame).
The second case is very typical in geometry packages, GEANT4, where we have
very large number repeated placements of relatively few logical (unique) shapes.
Some viewers (OpenGL 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 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. The
viewer indicates this through the 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 logical object, with the fLocalMaster transform and the
fColor and 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.
Scene Rebuilds
It should be understood that 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 AddObject() returns kNone, as it does for successful addition,
simply indicating it does not require you to provide further information about
this object. You should
not try to make any assumptions about what the viewer did with it.
This enables the viewer to be connected to a client which sends potentially
millions of objects, and only accept those that are of interest at a certain
time, caching the relatively small number of CPU/memory costly logical shapes,
and retaining/discarding the physical placements as required. The viewer may
decide to force the client to rebuild (republish) the scene (via
a TPad repaint at present), and thus collect these objects if the
internal viewer state changes. It does this presently by forcing a repaint
on the attached TPad object - hence the reason for putting all publishing to
the viewer in the attached pad objects Paint() method. We will likely remove
this requirement in the future, indicating the rebuild request via a normal
ROOT signal, which the client can detect.
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 IDs for each physical object internally. In the second you
can specify
a unique identifier from the client, which allows the viewer to be more
efficient. It can now cache both logical and physical objects, and only discard
physical objects no longer of interest as part of scene rebuilds.
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 descendents. Both AddObject()
methods have an addChildren parameter. The viewer will complete this (if passed)
indicating if children (contained within the one just sent) are worth adding.
Recyling TBuffer3D
Once add AddObject() has been called, the contents are copied to the viewer
internally. You are free to destroy this object, or recycle it for the next
object if suitable.
New printing facilities in batch via TASImage
TASImage is an
interface to image processing library using libAfterImage.
It allows reading and writing of images in different
formats, several image manipulations (scaling, tiling, merging,
etc.) and displaying in pads.
The size of the image on the screen does not depend on the original
size of the image but on the size of the pad. Therefore it is very
easy to resize the image on the screen by resizing the pad.
Besides reading an image from a file an image can be defined by a
two dimensional array of values. A palette defines the color of
each value.
The image can be zoomed by defining a rectangle with the mouse.
The color palette can be modified with a GUI, just select
StartPaletteEditor() from the context menu.
The new class TImageDump using TASImage and derived from TVirtualPS
allows to save canvas in GIF, JPEG etc, image formats in batch mode.
Before this clas was intriduced it was not possible to generate bitmap files
(in particular GIFfiles) in batch, such files were generated from a TCanvas.
Now the method TPad::Print or TPad::SavesAs can be used
in macro running in batch (root -b) to generated bitmap files
(gif, jpeg, png, xpm, tiff). Example:
$ root -b
root [0] .x hsimple.C
root [1] c1->Print("c1.gif");
The full description of TPad::Print options is now:
TPad::Print(const char *filename, Option_t *option)
filename extension (or option) can be:
"ps" - Postscript file is produced (see special cases below)
"eps" - an Encapsulated Postscript file is produced
"pdf" - a PDF file is produced
"svg" - a SVG file is produced
"gif" - a GIF file is produced
"xpm" - a XPM file is produced
"png" - a PNG file is produced
"jpg" - a JPEG file is produced
"tiff" - a TIFF file is produced
"cxx" - a C++ macro file is produced
"xml" - a XML file
"root" - a ROOT binary file
Some extras options:
"Portrait" - Postscript file is produced (Portrait)
"Landscape" - Postscript file is produced (Landscape)
"Preview" - an Encapsulated Postscript file with preview is produced.
All these option (except "Preview") are availabe from the File menu in TCanvas.
TImageDump
TImageDump save canvas as an image (GIF, JPEG, PNG, XPM, TIFF etc.)
It can be used in any mode (batch, interactive) as follows:
TCanvas *c1;
TImageDump *imgdump = new TImageDump("test.png");
c1->Paint();
imgdump->Close();
Other new features in the graphics area
TStyle
- New data member and corresponding Getter/Setter
Width_t fLegendBorderSize; //TLegend box border size
Width_t GetLegendBorderSize() const {return fLegendBorderSize;}
void SetLegendBorderSize(Width_t size=4)
The "Plain" style initializes the legend border size to 1.
All other styles to 4.
In TLegend constructor, the legend border size is set by default to
the current value in gStyle.
- The line styles defined via TStyle::SetLineStyleString() are now
available for all graphical interfaces: SVG, PostScript, PDF, X11, and
Win32GDK. Previously they were visible only in PostScript files. They
are still missing for Qt driver.
- Line styles 5 to 10 are predefined.
- TGedAttLineEditor shows the new line styles.
- New method SetHatchesLineWidth to set the hatches line width for
hatch styles > 3100
TPaveStats
- Skewness and kurtosis can now be displayed in TPaveStats (1D and 2D
histos).
- Skewness and kurtosis are available in the TPaveStats editor
- Errors can be displayed for 2D histograms statistics.
TPad
New method BuildLegend to automatically add a TLegend in a Pad.
TGraph2D
- New option "Line" to paint TGraph2D. TGraph2D are connected with
with a 3D polyline.
- New method SetHistogram. It allows to define the histogram to be
filled. This is useful to set the range of the X and Y axis.
Example:
void graph2dhist()
{
TCanvas *c = new TCanvas("c","Graph2D example",0,0,700,600);
Double_t x, y, z, P = 6.;
Int_t np = 300; // generate this many nodes
TGraph2D *dt = new TGraph2D();
TH2D* h2 = new TH2D("h2","h2",40,-6,6,40,-10,10);
dt->SetHistogram(h2);
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(1);
dt->Draw("TRI1 p0");
}
TASImage
- New method GetImageBuffer is introduced. It returns in-memory buffer
compressed according to the image type.
Buffer must be deallocated after usage.
This method can be used for sending images over the network.
- New method SetImageBuffer introduced. It creates image from compressed
buffer. Supported formats:
PNG - by default
XPM - two options exist:
1. xpm as a single string (raw buffer). Such a string
is returned by GetImageBuffer method.
For example:
char *buf;
int sz;
im1->GetImageBuffer(&buf, &int, TImage::kXpm); /*raw buffer*/
TImage *im2 = TImage::Create();
im2->SetImageBuffer(&buf, TImage::kXpm);
2. xpm as an array of strigs (preparsed)
For example:
char *xpm[] = {
"64 28 58 1",
" c #0A030C",
". c #1C171B"
...
TImage *im = TImage::Create();
im->SetImageBuffer(xpm, TImage::kXpm);
- Custom Streamer was implemented. That allows to save images in ROOT files.
Image's thumbnail is also saved into a file.
- galaxy_image.C tutorial is modified according to new saving schema.
- New demo file gallery.root added to tutorials. It contains thumbnailed
and browsable pictures produced by some ROOT tutorials.
- Fix bug im TASImage::DrawRectangle methods. Thanks to Thomas Bretz
for reporting it.
- TKey class.
Possibility to save thumbnail/icon as XPM string along with object added.
Currently such mechanism is used for saving thumbnailed images.
- TGPicture. Platform-dependent code was removed. Now TGPictures
are created by TImage objects.
- TRootBrowser classes. Possibility to show objects with dynamically created
icons added.
- New function void SetImage(ASImage * aimag)
PostScript / PDF
- Structuting directive %%Orientation added in PS files.
This allows the PostScript viewers
(like gv) to display automatically the PS files with the correct
orientation.
- The marker size is now the same as the one on screen.
- Patterns number 1 to 25 are now available in PDF
- PostScript and PDF files can now use the CMYK color model. A new TStyle method
(SetColorModelPS) allows to choose the color model (RGB or CMYK).
TStyle::SetColorModelPS(Int_t c)
Defines the color model use by TPostScript and TPDF (RGB or 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. PostScript and PDF support the CMYK model.
c = 0 means TPostScript and TPDF will use RGB color model (default)
c = 1 means TPostScript and TPDF will use CMYK color model
TArrow
It is now possible to draw "begin" and "end" bars on arrows.
TArrow, TCurlyArc,TCurlyLine
Implement default attributes values and the corresponding getters
and setters
TArrow
static Float_t fgDefaultAngle; //default Arrow opening angle (degrees)
static Float_t fgDefaultArrowSize; //default Arrow Size
static TString fgDefaultOption; //default Arrow shapes
TCurlyArc
static Double_t fgDefaultWaveLength; //default wavelength
static Double_t fgDefaultAmplitude; //default amplitude
static Bool_t fgDefaultIsCurly; //default curly type
TCurlyLine
static Double_t fgDefaultWaveLength; //default wavelength
static Double_t fgDefaultAmplitude; //default amplitude
static Bool_t fgDefaultIsCurly; //default curly type
These default value are used at creation time for these primitives.
Bug fixes ad Improvments in Graphics area
TMultiGraph
Add a new function
Option_t *TMultiGraph::GetGraphDrawOption(const TGraph *gr) const
Which returns the draw option for the TGraph gr in this TMultiGraph.
The return option is the one specified when calling TMultiGraph::Add(gr,option).
TStyle
In SetPalette: The DeepSea palette is defined only if needed. Without
this protection the following macro went slower and slower.
{
for (int i=0; i<10; i++) {
TStopwatch clock;
clock.Start();
gStyle->SetPalette(51, NULL);
clock.Print();
}
}
TCreatePrimitives
Some log scales support was missing
TGraphDelaunay (TGraph2D drawing)
Postpone the creation of the triangles data structure and the hull
finding. They are now done only when really needed. This increases the
performances in cases where triangles and hull are not useful, for
instance when a TGraph2D is drawn with option "P" only.
TH1
TH1::TH1() now uses UseCurrentStyle() to initialize the default
histogram "style parameters". In particular it initializes properly the
Histogram Fill Color to 0 which prevent the following three lines to
generate a "X11 Fatal Error".
TH1D h
h.SetBins(5000000,0,1)
h.Draw()
TArrow
Complete rewrite of TArrow::PaintArrow. The previous version used the
pixel coordinates. This method generated many rounding errors. The
visible effects on arrows were:
- distorted arrows' heads
- misplaced arrow compared to a Tline at the same coordinates.
The new TArrow::PaintArrow version fixes these two problems. Instead of
using pixel coordinates it uses "true NDC" coordinates. The "ROOT NDC
coordinates" are not appropriate in this case because X an Y axis are not normalized
the same way, therefore angles are not kept during a rotation.
THStack
- The maximum number of histograms in a THStack plotted as lego plot was
18. Now there is no limit anymore.
- THStack colors are now stored in a dynamic arrays. Previously they were
stored in a fixed length arrays of 10 entries.
2D polygons clipping
Clip polygons using the Sutherland-Hodgman algorithm. The previous
algorithm used (Cohen-Sutherland) is a line clipping algorithm which
produces wrong results on polygons. This new algorithm is implemented in
the function TPad::ClipPolygon used in the PaintFillArea method in its
Double_t version ONLY. The Float_t version of PaintFillArea prints a
warning.
Sutherland and Hodgman's polygon-clipping algorithm uses a divide-and-conquer
strategy: It solves a series of simple and identical problems that, when
combined, solve the overall problem. The simple problem is to clip a polygon
against a single infinite clip edge. Four clip edges, each defining one boundary
of the clip rectangle, successively clip a polygon against a clip rectangle.
Steps of Sutherland-Hodgman's polygon-clipping algorithm:
- Polygons can be clipped against each edge of the window one at a time.
Windows/edge intersections, if any, are easy to find since the X or Y coordinates
are already known.
- Vertices which are kept after clipping against one window edge are saved for
clipping against the remaining edges.
- Note that the number of vertices usually changes and will often increases.
The clip boundary determines a visible and invisible region. The edges from
vertex i to vertex i+1 can be one of four types:
- Case 1 : Wholly inside visible region - save endpoint
- Case 2 : Exit visible region - save the intersection
- Case 3 : Wholly outside visible region - save nothing
- Case 4 : Enter visible region - save intersection and endpoint
PostScript
- Protection added to TVirtualPS::PrinStr and TVirtualPS::PrintFast
to take into account the terminating null character.
- Some modifications for the CUPS printing system.
- Remove the %%BeginSetup/%%EndSetup section as it was empty since the last
CUPS modification. With that empty section tools like "psresize"
didn't work
anymore on PS files generated by ROOT.
SVG
Bitmap output
Bitmap files like gif, jpg, png etc ... are now created without highlight
color around the current TPad.
THistPainter::PaintErrors
The polygon drawn in case of option E3 (and E4) was
wrongly clipped when a Y value was greater than the Y axis maximum.
TCanvas
- The TCanvas size in interactive mode and batch mode were different (4
pixels horizontally and 28 vertically). Most of the time this was not a
real problem. But in some cases the same macro produced a different
result executed interactively or in batch. For instance the following
macro executed in batch did not show the histogram title in the
PostScript output. This patch make sure that batch interactive canvas
sizes are the same.
{
TCanvas *c2 = new TCanvas("c2","",0,0,600,900);
c2->Divide(3,3);
TH1F *h = new TH1F("h","This is a really long title for test purposes only hopefully long enough hehehe",100,0,100);
c2->cd(1);
h->Draw();
c2->Print("test.ps");
}
TLegend
In case the user doesn't supply a label for the legend entry (or NULL pointer)
the label for the entry is set to the title of the TObject referenced in the
first argument.
TTF
Font wingding.ttf (number 14) was not working. Nothing was displayed.
Axis drawing
- Always paint the axis title before painting the tick marks.
This fixes a problem when setting the number of divisions to 0.
In this case the axis title was not drawn.
- Label size was wrong when the text precision was equal to 3.
- In case of log scale on a vertical axis, the x-position of the extra labels
(when SetMoreLogLabels is true) was not computed the same way as the
x-position of the decades labels. Therefore they where not aligned.
TGraphErrors
- The fill style for boxes (option 3) was ignored.
- If a point is outside the pad limits it is set
to the limit it exceed. Previously it was not initialized. This produced
random drawing with the following macro:
{
const int n=200;
double x[n],y[n],e[n];
TCanvas *c1 = new TCanvas("c1", "Test",800,600);
for (int i=0;i<n;i++) {
x[i]=i;
y[i]=sqrt(i);
e[i]=y[i]/(i+1);
}
TH1D *Fond = new TH1D("Fond","",2,0,n);
Fond->SetMinimum(0);
Fond->SetMaximum(10);
Fond->Draw();
TGraphErrors *gr = new TGraphErrors(n,x,y,0,e);
gr->SetFillColor(17);
gr->Draw(" E3");
}
TGraph
- A better version of the TGraph constructor creating a TGraph from an input ascii file.
- The following example produced a wrong output:
{
hpx1 = new TH1F("hpx1","hpx1",100,-4,4);
hpx2 = new TH1F("hpx2","hpx2",100,-4,4);
Float_t px, py;
for (Int_t i = 0; i < 25000; i++) {
gRandom->Rannor(px,py);
hpx1->Fill(px);
hpx2->Fill(px);
hpx2->Fill(py);
}
hpx1->SetFillColor(2);
hpx1->SetFillStyle(3004);
hpx1->Draw("LF2");
hpx2->SetFillColor(1);
hpx2->SetFillStyle(3005);
hpx2->Draw("LF2 same");
}
The black histogram was not completly hatched.
GL/gl2ps
- New version of gl2ps
- New options to improve outline drawing in GL/PS files.
THistPainter
- Problems in CONT4 contour option fixed:
- Tick marks were on the wrong axis' side.
- It was not possible to draw axis's grid.
- SetTickx() and SetTicky() had no effect.
The axis for CONT4 are now drawn with THistPainter::PaintAxis(), not
anymore using TPainter3dAlgorithms.
- The angular variables in POL, SPH, CYL and PSR representations are now mapped correctly.
- Protect THistPainter::PaintBoxes against a division by 0
in case of code like
hh = new TH2F("hh","hh",100,0,1,100,0,1);
hh->Fill(200,200); // out of range value, so that
GetSumOfWeights()==0
hh->Draw("box");
- PaintErrors: In case of log scale on a Y axis with a positive maximum value and a minimum
value less or equal to 0, a new minimum is computed as a percentage of the
maximum. This rule is fine but may brings back visible some bins which are
out of range in linear mode. A new test has been added to prevent that. This
problem is visible since revision 1.197. Previously the test modified in that
revision was able to filter such wrong cases.
- In case of 1D histograms plotted as a LEGO or a SURFACE, one had to change
the option LogZ to set the logarithmic scale on the Y axis. Setting the
option LogY produced an error. This is now fixed.
New tutorials
- double32.C
- loopdir.C
- treefriend.C
- fitLinearRobust.C
- importCode.C
- readCode.C
- RoofitDemo.C
- assembly.C
- mathcoreVectorIO.C
- mathcoreVectorCollection.C
- mathcoreStatFunc.C
- mathcoreSpecFunc.C
- mathcoreGenVector.C
- mathcoreCDF.C
- minuit2FitBench.C
- minuit2FitBench2D.C
- minuit2GausFit.C
- glsurfaces.C
- psview.C
- copyFiles.C
- ConfidenceIntervals.C
- sqlcanvas.C
- sqltables.C
- thumbnail.C
- glViewerExercise.C
- TestSPlot.C
- regexp.C
ROOT page - Class index - Top of the page