ROOT CSC11-Handout PDF
ROOT CSC11-Handout PDF
CSC11 • ROOT 2
What's ROOT?
CSC11 • ROOT 3
ROOT: An Open Source Project
• Started in 1995
• 7 full time developers at CERN, plus Fermilab
• Large number of part-time developers: let users
participate
• Available (incl. source) under GNU LGPL
CSC11 • ROOT 4
ROOT in a Nutshell
Framework for large scale data handling
Provides, among others,
– an efficient data storage, access and query system
(PetaBytes)
– advanced statistical analysis algorithms (multi dimensional
histogramming, fitting, minimization and cluster finding)
– scientific visualization: 2D and 3D graphics, Postscript, PDF,
LateX
– geometrical modeller
– PROOF parallel query engine
CSC11 • ROOT 5
Graphics
CSC11 • ROOT 6
Histogramming
• Histogram is just occurrence counting, i.e. how often
they appear
• Example: {1,3,2,6,2,3,4,3,4,3,5}
CSC11 • ROOT 7
Histogramming
• How is a Real Histogram Made?
Lets consider the age distribution of the CSC
participants in 2008:
Binning:
Grouping ages of
participants in several
categories (bins)
CSC11 • ROOT 8
Histogramming
Table of Ages
(binned)
CSC11 • ROOT 9
Histograms
Analysis result: often a histogram
Menu:
View / Editor
CSC11 • ROOT 10
Fitting
Analysis result: often a fit of a histogram
CSC11 • ROOT 11
Fit Panel
To fit a histogram:
right click histogram,
"Fit Panel"
Straightforward interface
for fitting!
CSC11 • ROOT 12
2D/3D
We have seen 1D histograms, but there are
also histograms in more dimensions.
2D Histogram 3D Histogram
CSC11 • ROOT 13
OpenGL
OpenGL can be used to render 2D & 3D histograms,
functions, parametric equations, and to visualize 3D
objects (geometry)
CSC11 • ROOT 14
Geometry
• Describes complex detector geometries
• Allows visualization of these detector geometries with
e.g. OpenGL
• Optimized particle transport in complex geometries
• Working in correlation with simulation packages such
as GEANT3, GEANT4 and FLUKA
CSC11 • ROOT 15
Geometry
CSC11 • ROOT 16
EVE (Event Visualization Environment)
• Event: Collection of data from a detector
(hits, tracks, …)
Use EVE to:
• Visualize these physics objects together with detector
geometry (OpenGL)
• Visually interact with the data, e.g. select a particular
track and retrieve its physical properties
CSC11 • ROOT 17
EVE
CSC11 • ROOT 18
Math
CSC11 • ROOT 19
Math Example:
RANDOM NUMBERS
CSC11 • ROOT 20
Quasi-Random Numbers
• Needed e.g. to simulate nature: will particle interact?
• Trivial example for random number generator function:
last digit of n = n + 7,
say start with 0:
0, 7, 4, 1, 8, 5, 2, 9, 6, 3, 0, 7, 4, 1, 8, 5, 2, 9, 6, 3, 0, 7, 4, 1, 8,
• Properties:
– identical frequency of all numbers 0..9
– “looks” random, but short period:
0, 7, 4, 1, 8, 5, 2, 9, 6, 3, 0, 7, 4, 1, 8, 5, 2, 9, 6, 3, 0, 7, 4, 1,
– numbers not independent!
CSC11 • ROOT 21
Random Number Generator
• Solution: more complex function
– Mersenne Twister (TRandom3) is recommended
TRandom3 myRnd; myRnd.Uniform();
generates random number between >0 and <= 1
– period 106000, fast!
• Flat probability distribution function good for dice,
usually not for physics:
– measurement uncertainty: gaussian
– particle lifetime: N(t) = N0 exp(-t/τ) i.e. exponential
– energy loss of particles in matter: landau
CSC11 • ROOT 22
Naïve Random Distribution
• Want to “sample” distribution
y = 2x for 0 < x < 1
• Acceptance-rejection method
• Generate random x* and y* point:
if y* <= 1 – x2, return as random
number, else generate new x*, y*.
CSC11 • ROOT 23
Random Distribution From Inverse
• Integral g(x) of distribution f(x) (probability density
function “PDF”):
f(x) g(x)
CSC11 • ROOT 25
Interlude: HELP!
ROOT is a framework – only as good as its
documentation.
http://root.cern.ch
• User's Guide (it has your answers!)
• Reference Guide
What is TRandom?
What functions does it have?
CSC11 • ROOT 26
LET'S FIRE UP ROOT!
CSC11 • ROOT 27
Setting Up ROOT
Before starting ROOT:
setup environment variables $PATH,
$LD_LIBRARY_PATH
(ba)sh:
$ source /PathToRoot/bin/thisroot.sh
(t)csh:
$ source /PathToRoot/bin/thisroot.csh
CSC11 • ROOT 28
Starting Up ROOT
ROOT is prompt-based
$ root
root [0] _
CSC11 • ROOT 29
ROOT As Pocket Calculator
Calculations:
root [0] sqrt(42)
(const double)6.48074069840786038e+00
root [1] double val = 0.17;
root [2] sin(val)
(const double)1.69182349066996029e-01
CSC11 • ROOT 30
Running Code
To run function mycode() in file mycode.C:
root [0] .x mycode.C
Quit:
root [0] .q
All of CINT's commands (help):
root [0] .h
CSC11 • ROOT 31
ROOT Prompt
Why C++ and not a scripting language?!
You'll write your code in C++, too. Support for python,
ruby,… exists.
CSC11 • ROOT 32
Running Code
Macro: file that is interpreted by CINT (.x)
CSC11 • ROOT 33
Compiling Code: ACLiC
Load code as shared lib, much faster:
.x mymacro.C+(42)
CSC11 • ROOT 34
Compiled versus Interpreted
Why compile?
Faster execution, CINT has limitations, validate code.
Why interpret?
Faster Edit → Run → Check result → Edit cycles
("rapid prototyping").
Scripting is sometimes just easier.
CSC11 • ROOT 35
A LITTLE C++
CSC11 • ROOT 36
A Little C++
Hopefully many of you know – but some don't.
• Object, constructor, assignment
• Pointers
• Scope, destructor
• Stack vs. heap
• Inheritance, virtual functions
CSC11 • ROOT 37
Objects, Constructors, =
Look at this code:
TNamed myObject("name", "title");
TNamed mySecond;
mySecond = myObject;
cout << mySecond.GetName() << endl;
CSC11 • ROOT 38
Objects, Constructors, =
Look at this code:
TNamed myObject("name", "title");
TNamed mySecond;
mySecond = myObject;
cout << mySecond.GetName() << endl;
Creating objects:
1. Constructor TNamed::TNamed(const char*,
const char*)
2. Default constructor TNamed::TNamed()
CSC11 • ROOT 39
Objects, Constructors, =
Look at this code:
TNamed myObject("name", "title");
TNamed mySecond;
mySecond = myObject;
cout << mySecond.GetName() << endl;
3. Assignment:
mySecond myObject
TNamed: TNamed:
fName "" fName "name"
fTitle "" fTitle "title"
CSC11 • ROOT 40
Objects, Constructors, =
Look at this code:
TNamed myObject("name", "title");
TNamed mySecond;
mySecond = myObject;
cout << mySecond.GetName() << endl;
4. New content
mySecond
TNamed: output: "name"
fName "name"
fTitle "title"
CSC11 • ROOT 42
Pointers
Modified code:
TNamed myObject("name", "title");
TNamed* pMySecond = 0;
pMySecond = &myObject;
cout << pMySecond->GetName() << endl;
CSC11 • ROOT 43
Pointers
Modified code:
TNamed myObject("name", "title");
TNamed* pMySecond = 0;
pMySecond = &myObject;
cout << pMySecond->GetName() << endl;
[address] myObject
pMySecond TNamed:
fName "name"
fTitle "title"
CSC11 • ROOT 44
Pointers
Modified code:
TNamed myObject("name", "title");
TNamed* pMySecond = 0;
pMySecond = &myObject;
cout << pMySecond->GetName() << endl;
myObject
pMySecond
[address] = & TNamed:
fName "name"
fTitle "title"
CSC11 • ROOT 45
Pointers
Modified code:
TNamed myObject("name", "title");
TNamed* pMySecond = 0;
pMySecond = &myObject;
cout << pMySecond->GetName() << endl;
CSC11 • ROOT 46
Pointers
Changes propagated:
TNamed myObject("name", "title");
TNamed* pMySecond = 0;
pMySecond = &myObject;
pMySecond->SetName("newname");
cout << myObject.GetName() << endl;
CSC11 • ROOT 47
Object vs. Pointer
Compare object:
TNamed myObject("name", "title");
TNamed mySecond = myObject;
cout << mySecond.GetName() << endl;
to pointer:
TNamed myObject("name", "title");
TNamed* pMySecond = &myObject;
cout << pMySecond->GetName() << endl;
CSC11 • ROOT 48
Object vs. Pointer: Parameters
Calling functions: object parameter obj gets copied
for function void funcO(TNamed obj);
call!
TNamed myObject;
funcO(myObject);
CSC11 • ROOT 49
Object vs. Pointer: Parameters
Functions changing parameter: funcO can only access
copy! void funcO(TNamed obj){
caller not obj.SetName("nope");
changed! }
funcO(caller);
int a = 42;
{ int a = 0; }
cout << a << endl;
CSC11 • ROOT 51
Scope
Functions are scopes:
void func(){ TNamed obj; }
func();
cout << obj << end; // obj UNKNOWN!
CSC11 • ROOT 52
Stack vs. Heap
So far only stack:
TNamed myObj("n","t");
CSC11 • ROOT 53
Stack vs. Heap: Functions
Can return heap objects without copying:
TNamed* CreateNamed(){
// user must delete returned obj!
TNamed* ptr = new TNamed("n","t");
return ptr; }
CSC11 • ROOT 54
Inheritance
Classes "of same kind" can re-use functionality
E.g. plate and bowl are both dishes:
class TPlate: public TDish {...};
class TBowl: public TDish {...};
CSC11 • ROOT 55
Inheritance: The Base
Use TPlate, TBowl as dishes:
assign pointer of derived to pointer of base "every
plate is a dish"
TDish *a = new TPlate();
TDish *b = new TBowl();
But not every dish is a plate, i.e. the inverse doesn't work.
And a bowl is totally not a plate!
CSC11 • ROOT 56
Virtual Functions
Often derived classes behave differently:
class TDish { ...
virtual bool ForSoup() const;
};
class TPlate: public TDish { ...
bool ForSoup() const { return false; }
};
class TBowl: public TDish { ...
bool ForSoup() const { return true; }
};
CSC11 • ROOT 57
Pure Virtual Functions
But TDish cannot know! Mark as "not implemented"
class TDish { ...
virtual bool ForSoup() const = 0;
};
CSC11 • ROOT 58
Calling Virtual Functions
Call to virtual functions evaluated at runtime:
void FillWithSoup(TDish* dish) {
if (dish->ForSoup())
dish->SetFull();
}
CSC11 • ROOT 59
Virtual vs. Non-Virtual
So what happens if non-virtual?
class TDish { ...
bool ForSoup() const {return false;}
};
CSC11 • ROOT 60
Congrats!
CSC11 • ROOT 61
Summary
We know:
• why and how to start ROOT
• C++ basics
• that you run your code with ".x"
• can call functions in libraries
• can (mis-) use ROOT as a pocket calculator!
CSC11 • ROOT 62
Streaming, Reflection, TFile,
Schema Evolution
SAVING DATA
CSC11 • ROOT 63
Saving Objects
Cannot do in C++:
TNamed* o = new TNamed("name","title");
std::write("file.bin", "obj1", o);
TNamed* p =
std::read("file.bin", "obj1");
p->GetName();
CSC11 • ROOT 64
Saving Objects – Saving Types
What's needed?
TNamed* o = new TNamed("name", "title");
std::write("file.bin", "obj1", o);
CSC11 • ROOT 65
Serialization
Store data members of TNamed: serialization
1) type of object: runtime-type-information RTTI
2) data members for the type: reflection
3) where data members are in memory: introspection
4) read their values from memory, write to disk: raw I/O
CSC11 • ROOT 66
Reflection
Need type description (aka reflection)
1. types, sizes, members
class TMyClass {
float fFloat;
TMyClass is a class.
Long64_t fLong;
};
Members:
– "fFloat", type float, size 4 bytes
– "fLong", type Long64_t, size 8 bytes
CSC11 • ROOT 67
Platform Data Types
Fundamental data types (int, long,…):
size is platform dependent
CSC11 • ROOT 68
ROOT Basic Data Types
Solution: ROOT typedefs
CSC11 • ROOT 69
Reflection
Need type description (platform dependent)
1. types, sizes, members
2. offsets in memory class TMyClass {
float fFloat;
– 16 Long64_t fLong;
Memory Address
– 14 };
– 12 fLong
TMyClass
– 10
– 8
– 6 PADDING "fFloat" is at offset 0
– 4
– 2 fFloat "fLong" is at offset 8
CSC11 • ROOT
– 0 70
I/O Using Reflection
members memory disk
– 16
Memory Address
– 14
– 12 fLong
TMyClass
– 10
– 8
– 6 PADDING
– 4
– 2 fFloat
– 0
CSC11 • ROOT 71
C++ Is Not Java
Lesson: need reflection!
Where from?
Class.forName("MyClass").getFields()
CSC11 • ROOT 72
ROOT And Reflection
Simply use ACLiC:
.L MyCode.cxx+
CSC11 • ROOT 73
Back To Saving Objects
Given a TFile:
TFile* f = TFile::Open("file.root","RECREATE");
CSC11 • ROOT 74
TFile
ROOT stores objects in TFiles:
TFile* f = TFile::Open("file.root", "NEW");
TFile behaves like file system:
f->mkdir("dir");
TFile has a current directory:
f->cd("dir");
TFile compresses data ("zip"):
f->GetCompressionFactor()
2.6
CSC11 • ROOT 75
"Where Is My Histogram?"
TFile owns histograms, graphs, trees
(due to historical reasons):
TFile* f = TFile::Open("myfile.root");
TH1F* h = new TH1F("h","h",10,0.,1.);
TNamed* o = new TNamed("name", "title");
o->Write();
delete f;
h automatically deleted: owned by file.
o still there
unique names!
even if saving o to file!
TFile acts like a scope for hists, graphs, trees!
CSC11 • ROOT 76
Risks With I/O
Physicists can loop a lot:
For each particle collision
For each particle created
For each detector module
Do something.
Physicists can loose a lot:
Run for hours…
Crash.
Everything lost.
CSC11 • ROOT 77
Name Cycles
Create snapshots regularly:
MyObject;1
MyObject;2
…
MyObject;5427
MyObject
CSC11 • ROOT 78
The "I" Of I/O
Reading is simple:
TFile* f = TFile::Open("myfile.root");
TH1F* h = 0;
f->GetObject("h", h);
h->Draw();
delete f;
Remember:
TFile owns histograms!
file gone, histogram gone!
CSC11 • ROOT 79
Ownership And TFiles
Separate TFile and histograms:
TFile* f = TFile::Open("myfile.root");
TH1F* h = 0;
TH1::AddDirectory(kFALSE);
f->GetObject("h", h);
h->Draw();
delete f;
CSC11 • ROOT 80
Changing Class – The Problem
Things change:
class TMyClass {
float fFloat;
Long64_t fLong;
};
CSC11 • ROOT 81
Changing Class – The Problem
Things change:
class TMyClass {
double fFloat;
Long64_t fLong;
};
CSC11 • ROOT 82
Schema Evolution
Simple rules to convert disk to memory layout
1. skip removed members
file.root RAM
Long64_t fLong; ignore
float fFloat; float fFloat;
CSC11 • ROOT 84
Reading Files
Files store reflection and data: need no library!
function
call
CSC11 • ROOT 85
ROOT I/O Candy
• Nice viewer for TFile: new TBrowser
• Can even open
TFile::Open("http://cern.ch/file.root") including
read-what-you-need!
• Combine contents of TFiles with $ROOTSYS/bin/hadd
CSC11 • ROOT 86
Summary
Big picture:
• you know ROOT files – for petabytes of data
• you learned that reflection is key for I/O
• you learned what schema evolution is
Small picture:
• you can write your own data to files
• you can read it back
• you can change the definition of your classes
CSC11 • ROOT 87
ROOT COLLECTION CLASSES
Collection Classes
ROOT collections polymorphic containers: hold pointers
to TObject, so:
• Can only hold objects that inherit from TObject
• Return pointers to TObject, that have to be cast back
to the correct subclass
CSC11 • ROOT 89
TClonesArray
Array of objects of the same class ("clones")
Designed for repetitive data analysis tasks:
same type of objects
created and deleted
many times.
No comparable class in STL!
TClonesArray:
while (next_event()) {
for (int i=0;i<N;++i) TTrack
TTrack
new(a[i]) TTrack(x,y,z); TTrack
TTrack
TTrack
TTrack
do_something(a); TTrack
TTrack
TTrack
TTrack
a.Delete();
};
CSC11 • ROOT 91
Traditional Arrays
Very large number of new and delete calls in large loops
like this (Nevents x Ntracks times new/delete):
Nevents
= 100000
TObjArray a(10000);
while (TEvent *ev = (TEvent *)next()) {
for (int i = 0; i < ev->Ntracks; ++i) {
a[i] = new TTrack(x,y,z,...);
...
Ntracks
} = 10000
a.Delete();
}
CSC11 • ROOT 92
Use of TClonesArray
You better use a TClonesArray which reduces the
number of new/delete calls to only Ntracks: Nevents
= 100000
TClonesArray a("TTrack", 10000);
while (TEvent *ev = (TEvent *)next()) {
for (int i = 0; i < ev->Ntracks; ++i) {
new(a[i]) TTrack(x,y,z,...);
...
} Ntracks
a.Delete(); = 10000
}
• Pair of new / delete calls cost about 4 μs
• Allocating / freeing memory Nevents*Ntracks = 109 times
costs about 1 hour!
CSC11 • ROOT 93
ROOT TREES
Trees
From: To:
Simple data types Complex data types
(e.g. Excel tables) (e.g. Database tables)
Event
Header Type
Particles
Pt Charge
Energy Track
Vertex
Position
CSC11 • ROOT … 95
Why Trees ?
• Extremely efficient write once, read many ("WORM")
• Designed to store >109 (HEP events) with same data
structure
• Trees allow fast direct and random access to any entry
(sequential access is the best)
• Optimized for network access (read-ahead)
CSC11 • ROOT 96
Why Trees ?
object.Write() convenient for simple objects like
histograms, inappropriate for saving collections of
events containing complex objects
• Reading a collection: read all elements (all events)
• With trees: only one element in memory, or even only
a part of it (less I/O)
• Trees buffered to disk (TFile); I/O is integral part of
TTree concept
CSC11 • ROOT 97
Tree Access
• Databases have row wise access
– Can only access the full object (e.g. full event)
• ROOT trees have column wise access
– Direct access to any event, any branch or any leaf even in the
case of variable length structures
– Designed to access only a subset of the object attributes
(e.g. only particles’ energy)
– Makes same members consecutive, e.g. for object with
position in X, Y, Z, and energy E, all X are consecutive, then
come Y, then Z, then E. A lot higher zip efficiency!
CSC11 • ROOT 98
Branch Creation from Class
a Branches
b
float a; c
int b; N
double c[5];
int N; xxxxxx Class1::a
float* x; //[N] yyyyyy Class1::b
float* y; //[N]
c1 T::a
Class1 c1;
Class2 c2; //! c3 T::b
T::c
Class3 *c3;
std::vector<T> v1; v1 S::a
S::b
std::vector<S*> v2; v2
TClonesArray *tc; X::a
tc X::b
X::c
X::d
CSC11 • ROOT 99
ObjectWise/MemberWise Streaming
member-wise
streaming of
3 modes to stream
collections default
an object
since 5.27
a1b1c1d1a2b2c2d2…anbncndn
a
b
c a1a2..anb1b2..bnc1c2..cnd1d2..dn
d
a1a2…an
member-
b1b2…bn
wise gives
better
c1c2…cn
compression
d1d2…dn
CSC11 • ROOT 100
Building ROOT Trees
Overview of
– Trees
– Branches
5 steps to build a TTree
T.Fill()
T
CSC11 • ROOT 104
Memory ↔ Tree
• Each Node is a branch in the Tree Memory
0
1
2
3
4
5
6
T.GetEntry(6)
T
CSC11 • ROOT 105
Five Steps to Build a Tree
Steps:
1. Create a TFile
2. Create a TTree
3. Add TBranch to the TTree
4. Fill the tree
5. Write the file
myTree->Write();
root [] myTree->Scan("fEvtHdr.fDate:fNtrack:fPx:fPy","",
"colsize=13 precision=3 col=13:7::15.10");
******************************************************************************
* Row * Instance * fEvtHdr.fDate * fNtrack * fPx * fPy *
******************************************************************************
* 0 * 0 * 960312 * 594 * 2.07 * 1.459911346 *
* 0 * 1 * 960312 * 594 * 0.903 * -0.4093382061 *
* 0 * 2 * 960312 * 594 * 0.696 * 0.3913401663 *
* 0 * 3 * 960312 * 594 * -0.638 * 1.244356871 *
* 0 * 4 * 960312 * 594 * -0.556 * -0.7361358404 *
* 0 * 5 * 960312 * 594 * -1.57 * -0.3049036264 *
* 0 * 6 * 960312 * 594 * 0.0425 * -1.006743073 *
* 0 * 7 * 960312 * 594 * -0.6 * -1.895804524 *
Prints the values of var1, var2 and var3 for the entries
where var1 is greater than 0
Use the same syntax for TTree::Draw()
CSC11 • ROOT 120
Looking at the Tree
TTree::Show(entry_number) shows values for one entry
root [] myTree->Show(0);
======> EVENT:0
eBranch = NULL
fUniqueID = 0
fBits = 50331648
[...]
fNtrack = 594
fNseg = 5964
[...]
fEvtHdr.fRun = 200
[...]
fTracks.fPx = 2.066806, 0.903484, 0.695610,-0.637773,…
fTracks.fPy = 1.459911, -0.409338, 0.391340, 1.244357,…
T(2)
file2.root
T(1)
file1.root
TTree TChain
n x
a b c i j
o p
k l x
q r
TFile f1("tree.root");
tree.AddFriend("tree_1", "tree1.root")
tree.AddFriend("tree_2", "tree2.root");
tree.Draw("x:a", "k<c");
tree.Draw("x:tree_2.x");
CSC11 • ROOT 126
Splitting
ANALYZING TREES
Init(tree)
SlaveBegin()
Process(i)
yes
next entry?
no
Terminate()
CSC11 • ROOT 135
TSelector
Steps of ROOT using a TSelector:
1. setup TMySelector::Init(TTree *tree)
fChain = tree; fChain->SetBranchAddress()
2. start TMySelector::SlaveBegin()
create histograms
3. run TMySelector::Process(Long64_t)
fChain->GetTree()->GetEntry(entry);
analyze data, fill histograms,…
4. end TMySelector::Terminate()
fit histograms, write them to files,…
FITTING
Not monotonic!
1. Find appropriate
function with
parameters
1. Fit function to
distribution
[0]
[1]
f->SetParameter(0, 35.);
Sensible values:
f->SetParameter(1, 10.);
f->SetParameter(2, 1.);
CSC11 • ROOT 144
Fitting Result
Result of hist->Fit(f); is printed, or use
f->GetParameter(0)
[0]: 34.9
[1]: 12.1
[2]: 0.98
which means:
(TMath::Erf((x-34.9)/12.1)/2.+0.5)*0.98
list of output
objects MASTER
(histograms, …)
Workers
CSC11 • ROOT 152
Scheduling
• Decides where to run which (part of) the jobs
• E.g. simple batch system
• Can autonomously split jobs into parts (“packets”)
• Involves
– resource management (CPU, I/O, memory)
– data locality
– priorities (jobs / users)
– and whatever other criteria are deemed relevant
• Often optimizing jobs’ distribution towards overall
goal: maximum CPU utilization (Grid), minimum time
to result (PROOF)
CSC11 • ROOT 153
Packetizer Role and Goals
• Distributes units of work (“packets”) to workers
• Grid’s packet: >=1 file
• Result arrives when last resource has processed last
file:
t = tinit + maxjobs(Ri . Nifiles) + tfinal
tinit, tfinal: time to initialize / finalize the jobs
Ri: processing rate of job i
Nifiles: number of files for job i
• Result:
– slowest job defines running time
– large tail in CPU utilization versus time
CSC11 • ROOT 154
Static…
• Example: 24 files on 4 worker nodes, one under-
performing
TProof::Open("master")
Client commands,
scripts
list of output
objects
(histograms, …)
Multi-core Desktop/Laptop
TProof::Open("")
// MySelector is a TSelector
root[3] c->Process("MySelector.C+");
Begin() Terminate()
leaf leaf branch branch •Final analysis
(fitting, saving …)
branch leaf leaf leaf
leaf leaf
Chain 1 2 n last
void MySelector::Terminate() {
fHist->Draw(); // display histogram
}
TProof::Open()
Opens GUI: