Root Notes

For good/high resolution png plots, MAKE SURE CANVAS HAS ENOUGH PIXELS !!!!!!
ie: TCanvas *c1 = new TCanvas("c1", "SIC data", 800, 600);

RootTalk DavecRoofit

ROOT users guide Root homepage ROOT primer FAQs
ROOT Class Index Histograms, TH1, TH2D methods etc TF1 methods Fit with TF1 etc
Useful ROOT tips !!! Multi histos - looping/filling Tulika - ROOT tutorial Luca Perrozzi - ROOT tutorial

fnal root tips Pad tricks for axes


Command line options

These are some command line options you can use when starting ROOT:
-b: ROOT session runs in batch mode, without graphics display. This mode is useful in case you do not want to set the DISPLAY.
-n: Does not execute the logon script and logoff script as specified in .rootrc.
-q: Exits after processing the command line macro files.
-l: Does not show the ROOT banner.
-a: Displays the ROOT splash screen.
-x: Exits on exception.
dir: If dir is a valid directory, change to it (cd) before executing ROOT.
-?, -h, --help: Prints usage.


~/<1>src/Reco/RecoAnalyzer $ echo $ROOTSYS

echo $PATH

ROOTSYS and PATH on my MAC, 30 MARCH 2021

HEPMBP069:~ david$ echo $ROOTSYS

HEPMBP069:~ david$ echo $PATH

On Ubuntu, 30 March 2021

you don’t have to compile ROOT from source on Ubuntu.

You can download pre-compiled binaries (
that you just need to uncompress, 

and a source /path/to/ROOT/bin/ gives you a working ROOT.

Batch mode
Back to Grapnics mode:

Turn off stats

TLegend(Double_t x1,Double_t y1,Double_t x2,Double_t y2,const char *header, Option_t *option)
The legend is defined with default coordinates, border size and option. The legend coordinates (NDC) in the current pad are x1, y1, x2, y2. The default text attributes for the legend are:

  • Alignment = 12 left adjusted and vertically centered
  • Angle = 0 (degrees)
  • Color = 1 (black)
  • Size = calculate when number of entries is known
  • Font = helvetica-medium-r-normal scalable font = 42, and bold = 62 for title
gStyle->SetLegendBorderSize(0); for no bounding box
  • Dont use mumbers > 1.0. This only works if the font is a pixel-based one; else try 0.03 or similar values.

AddEntry(TObject *obj, const char *label,Option_t *option)
The parameters are:
  • obj is a pointer to an object having marker, line, or fill attributes (a histogram, or a graph)
  • label is the label to be associated to the object
  • option:
  • ”L” draw line associated with line attributes of obj, if obj inherits from TAttLine.
  • ”P” draw poly-marker associated with marker attributes of obj, if obj inherits TAttMarker.
  • ”F” draw a box with fill associated with fill attributes of obj, if obj inherits TAttFill

Plot single point

TMarker m(.5,.5,22);  // x,y, marker type !!!!!!!!

TMarker tt; 

or, for a point in a 3D plot:
  TGraph2D* t = new TGraph2D(1);
  t->SetPoint(0, 1. , 2. , 3.);
  t->GetXaxis()->SetLimits(0, 2);
  t->GetYaxis()->SetLimits(1, 3);
  t->GetZaxis()->SetLimits(2, 4);
  //  t->GetXaxis()->SetRangeUser(0, 2);
  //  t->GetYaxis()->SetRangeUser(1, 3);
  t->GetZaxis()->SetRangeUser(2, 4);

Change title

TPaveLabel *title = new TPaveLabel(.11,.95,.35,.99,"my new title","brndc"); 

Canvases and pads

TLatex in NDC coordinates
NDC coordinates: canvas or pad ranges from 0 to 1, in both x and y.

TLatex tt; 

Convert string to const char * for TFile name

std::string str;
const char * c = str.c_str();

  //std::string str;
  const char * c = s.c_str();
  //s = "Run-" + s + ".root";
  TFile f(c, "RECREATE");

Put run number into histo title

  string s, s1, s2;
  TString tsrun;

  s1 = to_string(328337);
  s2 = to_string(328338);

  s = "Runs " + s1 + " and " +s2;

  cout<< "\n\nString is " << s <<endl;
  tsrun = s;
  cout << tsrun << endl;

TH2D *EEPlaser1pnratio = new TH2D("EEPlaser1pnratio", tsrun + ", EEP, pn ratio, pn g=16/pn g=1, laser power = 1", 100, 0, 100, 100, 0, 100);

TGraph constructors - only these are valid !!!

    TGraph (Int_t n, const Int_t *x, const Int_t *y)
    Graph normal constructor with ints. More...
    TGraph (Int_t n, const Float_t *x, const Float_t *y)
    Graph normal constructor with floats. More...
    TGraph (Int_t n, const Double_t *x, const Double_t *y)
    Graph normal constructor with doubles. More...

TGraph options
Painter options
Graphs' plotting options

Graphs can be drawn with the following options:
Option    Description
"A"    Axis are drawn around the graph
"I"    Combine with option 'A' it draws invisible axis
"L"    A simple polyline is drawn
"F"    A fill area is drawn ('CF' draw a smoothed fill area)
"C"    A smooth Curve is drawn
"*"    A Star is plotted at each point
"P"    The current marker is plotted at each point
"B"    A Bar chart is drawn
"1"    When a graph is drawn as a bar chart, this option makes the bars start from the bottom of the pad. By default they start at 0.
"X+"    The X-axis is drawn on the top side of the plot.
"Y+"    The Y-axis is drawn on the right side of the plot.
"PFC"    Palette Fill Color: graph's fill color is taken in the current palette.
"PLC"    Palette Line Color: graph's line color is taken in the current palette.
"PMC"    Palette Marker Color: graph's marker color is taken in the current palette.
"RX"    Reverse the X axis.
"RY"    Reverse the Y axis. 

histos from a directory

Get data from a Canvas saved as a root file
From a canvas or a pad

TFile miofile(“test.root”);
TCanvas can = (TCanvas)miofile.Get(“c1”);
TH1D his = ((TH1D)(can->FindObject(“MCA”)));
Double_t xmin = his->GetBinCenter(1);
Double_t xmax = his->GetBinCenter(his->GetNbinsX());
his->Fit(“gaus”, “”, “”, xmin, xmax);

TFile miofile(“test.root”);
TCanvas can = (TCanvas)miofile.Get(“c1”);
((TPad *)can->FindObject(“pad1”))->GetListOfPrimitives()->ls();
((TPad *)can->FindObject(“pad1”))->GetListOfPrimitives()->Print();
TH1D his = ((TH1D)(((TPad *)can->FindObject(“pad1”))->GetPrimitive(“MCA”)));
Double_t xmin = his->GetBinCenter(1);
Double_t xmax = his->GetBinCenter(his->GetNbinsX());
his->Fit(“gaus”, “”, “”, xmin, xmax);
Oct '12

Thank you very very much!
can->FindObject(“MCA”) was the trick. :smiley:

Rene answer

I wrote a canvas in a file and now I'd like to
get back the histogram from the 
canvas and do some stuff...
This is the 1st script:

   TFile miofile("Hfra40.root","read");
   TCanvas *c1 = (TCanvas*)miofile.Get("c1");

the c1 canvas is drawn and this is the output:
TFile**         Hfra40.root
 TFile*         Hfra40.root
  KEY: TCanvas  c1;1    c1

   In your 2nd script, do;
   TFile miofile("Hfra40.root","read");
   TH1F *hFra40;
   TCanvas *c1 = (TCanvas*)miofile.Get("c1");
   hFra40 = (TH1F*)c1->GetPrimitive("hFracEtcorr2Part");
   TFile miofile("Hfra40.root","read");
   TH1F *hFra40;
   TCanvas *c1 = (TCanvas*)miofile.Get("c1");
   hFra40 = (TH1F*)c1->GetPrimitive("hFracEtcorr2Part");
   TCanvas c2;
In your original script, the current pad/canvas is c1.
So you draw the histogram in this canvas.
   Rene Brun  

TDatime Info

TDatime t;

Plot single point
TMarker m(.5,.5,22);

TFiles - directories and input/output
Chap 11: Input/Output

How to show pdf, ps, eps in canvas

Greek symbols
#eta etc

Getting info from TGraphs
Manipulations !!!

//search points (may be more than 1)
Int_t j = 0;
for (j=0;j<n;j++) {
if (TMath::AreEqualRel(0.5,gr->GetX()[j],1e-6)) {
printf(“found point %d with x=%g, y=%g\n”,j,gr->GetX()[j],gr->GetY()[j]);

Writing/reading TGraphs
Only histograms and trees are written when calling TFile::Write(). All other objects like TGraphs have to be each written out explicitly. Rene Brun answer

Float_t x[5] = {1, 2, 3, 4, 5};
Float_t y[5] = {3, 3, 3, 3 ,3};
Float_t ex[5] = {1, 1, 1, 1, 1};
Float_t ey[5] = {1, 1, 1, 1 ,1};
TFile f("test.root",  "RECREATE");
TGraph *g = new TGraphErrors(5, x, y, ex, ey);
delete f;

As suggested above, you can write your graphs one by one to the file
or alternatively add the graphs to the list of objects associated
to the file with
f->GetList()->Add(gr2); //etc
f->Write(); //will write all the objects in the list
In this case, you better give a name to your graphs

When you want to draw the graph in a file
-via TBrowser, double click on the graph. If you use a version >= 4.02
the graph will be drawn by default with option “alp”.
you can change this default option by setting
TGraph::BrowseOption: alp
in the file .rootrc or $ROOTSYS/etc/system.rootrc

-via the command
TGraph gr1 = (TGraph)f->Get(“name of gr1”);
gr1->Draw(“alp”); //or any other option

Only TH1 and TTree objects are automatically registered to
gDirectory->GetList(). TGraphs are not.

You can register any TObject derived object (eg TGraph) to this list with a
statement like
where TGraph *mygraph is an already existing TGraph.

You can replace your saveAll function with
This statement will write all objects registered in the directory.

To see the list of objects in a directory, do
  dir->ls(), eg gDirectory->ls();

Rene Brun

Getting global variables from another file
Just list all the variables in the other file, no {} needed at start/end of file, and do:

#include "sic-btcp-lcf-info.C"
void Drawlcps() {
...........can now use the variables listed in sic-btcp-lcf-info.C, they are now global variables

and in root:
> .L corr-fac-vs-int-lumi-300-with-extraps.C   // the file which has the function:  void Drawlcps() {...}
> Drawlcps()

Colour, Markers and styles
Colour wheel at link
Text colour map at link
Marker styles at link
Fill styles at link and link2

Text discussion atlas logon


gROOT->ProcessLine(".! echo $ROOTSYS"); ProcessLine to execute other code from within one program
gROOT->Reset() When running an un-named script over again, and this is frequently the case
since un-named scripts are used to prototype, one should reset
the global environment to clear the variables with gROOT->Reset()

TString Examples, use of the TString class
TGraph TGraph methods

Fast tip:
2D plot, with Browser editor, click inside the plot and in editor check boxes "col" and "palette" to see the z-value palette bar on the RHS.
Also h2->Draw("zcol");

Canvas/Histo setups
SetTitle question
Please read the documentation of TStyle::SetTitleFont

> =====
> void SetTitleFont(Style_t font, Option_t *axis)
> if axis =="x" set the X axis title font
> if axis =="y" set the Y axis title font
> if axis =="z" set the Z axis title font
> any other value of axis will set the pad title font
> if axis="xyz" set all 3 axes
> ====
> gStyle->SetTitleFont(62);
> gStyle->SetTitleFontSize(0.09);
Also note that if you select a font style in pixels (63), ie: gStyle->SetTitleFont(63,"");
you should specify a number of pixels for the font size. See class description at TAttText.

Text Font and Precision
The text font code is combination of the font number and the precision.
Text font code = 10*fontnumber + precision
Font numbers must be between 1 and 14.
The precision can be:

precision = 0 fast hardware fonts (steps in the size)
precision = 1 scalable and rotatable hardware fonts (see below)
precision = 2 scalable and rotatable hardware fonts
precision = 3 scalable and rotatable hardware fonts. Text size is given in pixels.

List of the currently supported fonts:
Font number         X11 Names             Win32/TTF Names
    1 :       times-medium-i-normal      "Times New Roman"
    2 :       times-bold-r-normal        "Times New Roman"
    3 :       times-bold-i-normal        "Times New Roman"
    4 :       helvetica-medium-r-normal  "Arial"
    5 :       helvetica-medium-o-normal  "Arial"
    6 :       helvetica-bold-r-normal    "Arial"
    7 :       helvetica-bold-o-normal    "Arial"
    8 :       courier-medium-r-normal    "Courier New"
    9 :       courier-medium-o-normal    "Courier New"
   10 :       courier-bold-r-normal      "Courier New"
   11 :       courier-bold-o-normal      "Courier New"
   12 :       symbol-medium-r-normal     "Symbol"
   13 :       times-medium-r-normal      "Times New Roman"
   14 :                                  "Wingdings"
   15 :       Symbol italic (derived from Symbol)
Font images.

Font quality and speed
When precision 0 is used, only the original non-scaled system fonts are used.
The fonts have a minimum (4) and maximum (37) size in pixels.
These fonts are fast and are of good quality. Their size varies with large steps and they cannot be rotated.

Precision 1 and 2 fonts have a different behaviour depending if the True Type Fonts (TTF) are used or not.
If TTF are used, you always get very good quality scalable and rotatable fonts. However TTF are slow.

How to use True Type Fonts
One can activate the TTF by adding (or activating) the following line in the .rootrc file:

Unix.*.Root.UseTTFonts:     true
It is possible to check the TTF are in use in a Root session with the command:

If the TTF are in use, the following line will appear at the beginning of the printout given by this command:
Unix.*.Root.UseTTFonts:   true                           [Global]

TStyle Class Reference link
TStyle default settings at link
This class includes functions to set some of the following object attributes:

Histogram axis
Fill areas
Histogram Statistics and Titles
Set font number for axis labels. SetLabelFont(): void TStyle::SetLabelFont ( Style_t font = 62, Option_t * axis = "X" )
Set size of axis labels. SetLabelSize(): void TStyle::SetLabelSize ( Float_t size = 0.04, Option_t * axis = "X" )
The size is expressed as a percent of the pad height, unless precision = 3. axis specifies which axis ("x","y","z"), default = "x" if axis="xyz" set all 3 axes
Definition at line 1072 of file TStyle.cxx.

Text Size
If the text precision (see next paragraph) is smaller than 3, the text size (textsize) is a fraction of the current pad size. Therefore the same textsize value can generate text outputs with different absolute sizes in two different pads. The text size in pixels (charheight) is computed the following way:

pad_width  = gPad->XtoPixel(gPad->GetX2());
pad_height = gPad->YtoPixel(gPad->GetY1());
if (pad_width < pad_height)  charheight = textsize*pad_width;
else                         charheight = textsize*pad_height;
If the text precision is equal to 3, the text size doesn't depend on the pad's dimensions. A given textsize value always generates the same absolute size. The text size (charheight) is given in pixels: charheight = textsize;
Note that to scale fonts to the same size as the old True Type package a scale factor of 0.93376068 is apply to the text size before drawing.

The text size of any class inheriting from TAttText can be changed using the method SetTextSize and retrieved using the method GetTextSize.

Histogramme draw options
Residuals below a histogram

Draw histogram without the vertical lines for the first and the last bin
Use “][”

Good resolution pngs for ppt
Expand canvas to as large a size as possible before saving as png

Quick histo reminder

#include <TH2.h>

TH1F *iprod1 = new TH1F("iprod1","iprod distn",12,-2,10);
TH2D *iprod2 = new TH2D("iprod2","EE- types",100,0,100,100,0,100);
TH2D *iprod3 = new TH2D("iprod3","EE+ types",100,0,100,100,0,100);

Getting the bin content at x,y:

hEE->GetBinContent(  hEE->FindBin(x,y)  )

Get the bin centers for a point (x,y):

x_=h2D->GetXaxis()->GetBinCenter( h2D->GetXaxis()->FindBin(x) );
y_=h2D->GetYaxis()->GetBinCenter( h2D->GetYaxis()->FindBin(y) );

Using more than one TFile:

cout << "Histos available on disk, before TFiles: " << endl;
   cout << "Histos available in memory, before TFiles: " << endl;
  cout << "\n\n" << endl;  

  TFile f ("histo-reco.root");

 cout << "Histos available on disk, after TFile f (histo-reco.root) : " << endl;
   cout << "Histos available in memory, after TFile f (histo-reco.root) : " << endl;
  cout << "\n\n" << endl;  

  TFile ff ("result-of-adding.root");

  TFile fff ("EBdata.root");

TH1 *EEMcs2 = (TH1*)EEMcs->Clone("EEMcs2"); // EE- status
  TH1 *iprod22 = (TH1*)iprod2->Clone("iprod22");"");
 TH1 *EBiprod2 = (TH1*)EBiprod->Clone("EBiprod2"); // btcp = 1, SIC = 2, preprod = 3
 TH1 *EBiproddist2 = (TH1*)EBiproddist->Clone("EBiproddist2"); // btcp = 1, SIC = 2, preprod = 3

Plotting multiple graphs

   TGraph *g[10];
   Double_t x[10] = {0,1,2,3,4,5,6,7,8,9};
   Double_t y[10] = {1,2,3,4,5,6,4,3,2,1};
   TMultiGraph *mg = new TMultiGraph();
   for (int i=0; i<10; i++) {
      g[i] = new TGraph(10, x, y);
      y[i] = y[i]+1;

// will auto draw x-y ranges to fit all graphs

// changing mg ranges
// need GetXaxis for x-axis range <-- with decimal not integer numbers !!!!!!!
// need SetMinimum and SetMaximum for y-axis range <-- with decimal not integer numbers !!!!!!!
mg3040->GetXaxis()->SetLimits(690., 720.)
root [4] mg3040->SetMinimum(-1.5)
root [5] mg3040->SetMaximum(1.1)

Saving histos to a file:

save the histograms to a file
root[14] TFile* file = new TFile("exercise0.root","RECREATE")
and now we can write the histograms and close the file
root[15] myhisto.Write()
root[16] histo->Write()
root[17] file->Close()
root[18] delete file
Now try to read the histograms back in:
root[19] TFile* fileagain = new TFile("exercise0.root","READ")
root[20] TH1F * histoagain = (TH1F*)fileagain->Get("histo");

Histo methods
link :
Clone a histogramme from another, ie h from h1:

TH1F *h = (TH1F*)h1->Clone("h");

virtual Bool_t    Add (const TH1 *h1, Double_t c1=1)
 Performs the operation: this = this + c1*h1 If errors are defined (see TH1::Sumw2), errors are also recalculated. More...

virtual Bool_t    Add (const TH1 *h, const TH1 *h2, Double_t c1=1, Double_t c2=1)
Replace contents of this histogram by the addition of h1 and h2. More...

Bool_t TH1::Divide   (   TF1 *    f1, Double_t    c1 = 1 )
Performs the operation: this = this/(c1*f1) if errors are defined (see TH1::Sumw2), errors are also recalculated.

Bool_t TH1::Divide   (   const TH1 *    h1   )   
Divide this histogram by h1.
this = this/h1 if errors are defined (see TH1::Sumw2), errors are also recalculated.

Bool_t TH1::Divide   (   const TH1 *    h1, const TH1 *    h2, Double_t    c1 = 1, Double_t    c2 = 1, Option_t *    option = "" )      
Replace contents of this histogram by the division of h1 by h2.
this = c1*h1/(c2*h2)
If errors are defined (see TH1::Sumw2), errors are also recalculated

Note: //(*EETPmean)=(*EETPrad)/(*EETPradhits); // operations can be done with histogram pointers
led to problems to do EETPmean->Write();
Got a 2nd version of EETPrad, EETPrad;1 and also EETPrad;2 in place of EETPmean.
Instead do:

TH1F *EETPmean = new TH1F("EETPmean","EE testpulse mean vs radius, sqrt(ix**2 + iy**2); Radius,  sqrt(x*x + y*y)", 60, 0., 60.);
     EETPmean->SetTitle("EE testpulse mean vs radius, sqrt(ix**2 + iy**2) " )  ;
     EETPmean->SetXTitle("Radius, sqrt(x*x + y*y)" );

Int_t TH1::FindBin ( Double_t x, Double_t y = 0, Double_t z = 0 )
Return Global bin number corresponding to x,y,z.

Bool_t TH1::Multiply ( TF1 * f1, Double_t c1 = 1 )
Performs the operation: this = this*c1*f1 if errors are defined (see TH1::Sumw2), errors are also recalculated.

Bool_t TH1::Multiply ( const TH1 * h1, const TH1 * h2, Double_t c1 = 1, Double_t c2 = 1, Option_t * option = "" )

Replace contents of this histogram by multiplication of h1 by h2.
this = (c1*h1)*(c2*h2)
If errors of this are available (TH1::Sumw2), errors are recalculated

Setting the bin content:

virtual void    SetBinContent (Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin 

gROOT->ls() ; // to get to objects in memory !!!!!!!!!!!

TLIne t
NOTE, assigning TLIne t(2,3,4,5); then t.SetLineColor(2) may not work !!!!

Better to do just TLIne t. and then use t.DrawLine itself. )
t.DrawLine(2,3,4,5) // using DrawLine to do repeat dwgs with same object, t
TLatex tx;
tx.DrawLatex(6.0,7.5," some text") // using DrawLatex to do repeat dwgs with different text with same object, tx

Changing frame normalisation:
TLatex latex

Conventions and Types

Coding Conventions
From the first days of ROOT development, it was decided to use a set of coding conventions. This allows a consistency throughout the source code. Learning these will help you identify what type of information you are dealing with and enable you to understand the code better and quicker. Of course, you can use whatever convention you want but if you are going to submit some code for inclusion into the ROOT sources, you will need to use these.
These are the coding conventions:
• Classes begin with T: TLine, TTree
• Non-class types end with _t: Int_t
• Data members begin with f: fTree
• Member functions begin with a capital: Loop()
• Constants begin with k: kInitialSize, kRed
• Global variables begin with g: gEnv
• Static data members begin with fg: fgTokenClient
• Enumeration types begin with E: EColorLevel
• Locals and parameters begin with a lower case: nbytes
• Getters and setters begin with Get and Set: SetLast(), GetFirst()

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

• Char_t Signed Character 1 byte
• UChar_t Unsigned Character 1 byte
• Short_t Signed Short integer 2 bytes
• UShort_t Unsigned Short integer 2 bytes
• Int_t Signed integer 4 bytes
• UInt_t Unsigned integer 4 bytes
• Long64_t Portable signed long integer 8 bytes
• ULong64_t Portable unsigned long integer 8 bytes
• Float_t Float 4 bytes
• Double_t Float 8 bytes
• Double32_t Double 8 bytes in memory, written as a Float 4 bytes
• Bool_t Boolean (0=false, 1=true)

Root trees/ntuples, read in ascii file

Read in 2 ascii data files. Types defined in .dat files.
Each variable loaded from its corresponding branch object.

Extra .dat file: basic-vpts-john-wood-linux-data.dat

Read in an ascii file with floats, integers and character strings. Types defined in .dat file.
Each variable loaded from its corresponding branch object.

Tree-vpts-types-in-dat-file.c basic-vpts-with-types.dat

Read in an ascii file with floats, integers and character strings. Types defined in .C file.
Each variable loaded from its corresponding branch object.

Tree-test.C basic.dat

Tree branch:

tree->Branch("Ev_Branch",&event,"temp/F:ntrack/I:nseg:nvtex:flag/i ");
The first parameter is the branch name.

The second parameter is the address from which the first variable is to be read. In the code
above, “event” is a structure with one float and three integers and one unsigned integer. 

You should not assume that the compiler aligns the elements of a structure without gaps. To avoid
alignment problems, you need to use structures with same length members. If your structure does not qualify,
you need to create one branch for each element of the structure.

The leaf name is NOT used to pick the variable out of the structure, but is only used as the name for the leaf.
This means that the list of variables needs to be in a structure in the order described in the third parameter.

The third parameter is a string describing the leaf list. Each leaf has a name and a type separated by a "/". 
It is separated from the next leaf by a ":".

Two leafs: a floating-point number called temp and an integer named ntrack. "temp/F:ntrack/I:"

The type can be omitted and if no type is given, the same type as the previous variable is assumed.
The leaf list below has three integers called ntrack, nseg, and nvtex.

*When no type is given for the very first leaf, it becomes a float (F).*
The leaf list below has three floats called temp, mass, and px.

Can add a leaf that holds an entire array of variables. To add an array of floats use the f[n] notation when describing the leaf.
Float_t f[10];

You can also add an array of variable length:

TFile *f = new TFile("peter.root","recreate");
Int_t nPhot;
Float_t E[500];
TTree* nEmcPhotons = new TTree("nEmcPhotons","EMC Photons");

List of tree variable types:

The symbols used for the type are:
• C: a character string terminated by the 0 character
• B: an 8 bit signed integer
• b: an 8 bit unsigned integer
• S: a 16 bit signed integer
• s: a 16 bit unsigned integer
• I: a 32 bit signed integer
• i: a 32 bit unsigned integer
• L: a 64 bit signed integer
• l: a 64 bit unsigned integer
• F: a 32 bit floating point
• D: a 64 bit floating point

Root hints

Book multiple histogrammes

Create a dynamic array of pointers
TH1F** h = new TH1F*[m];
for (int i=0;i<m;i++) {
h[i] = new TH1F(name,title... 

Rene Brun
see root faq

Copy a histogramme from one file to another from the command line
rootcp xtal-types.root:iprod2 result-of-adding.root

Histogram bins etc
TH1 methods

bin = 0; underflow bin
bin = 1; first bin with low-edge xlow INCLUDED
bin = nbins; last bin with upper-edge xup EXCLUDED
bin = nbins+1; overflow bin

virtual Double_t GetBinContent (Int_t bin) const
virtual Double_t GetBinContent (Int_t bin, Int_t) const
virtual Double_t GetBinContent (Int_t bin, Int_t, Int_t) const

Int_t TH1::FindBin ( Double_t x, Double_t y = 0, Double_t z = 0)
virtual Int_t FindBin(Double_t x); // Find bin number corresponding to abscissa x.

gDirectory and subdirectories
You can change the directory of a histogram with the SetDirectory method.
If the parameter is 0, the histogram is no longer associated with a directory!!!

In a ROOT session, you are always in a directory. The directory
you are in is called the current directory and is stored in the global variable gDirectory.

Make a pointer to a specific histogramme with gDirectory:

TH1F *h = (TH1F*)gDirectory->GetList()->FindObject("myHist");

gDirectory->pwd() gDirectory points to the subdirectory. It prints the current directory location with pwd
gFile->pwd() gFile points to the file's top directory, and prints the directory location with pwd; changes the current directory back to f1
.pwd CINT shortcut for gDirectory->pwd()
.ls CINT shortcut for gDirectory->ls()
gROOT->cd() Back to Rint:/, the topmost directory, and prints "(unsigned char)1" or "true"
  then gROOT->pwd() gives Rint:/
gDirectory->ls("-d") lists the objects on disk in the current directory
gDirectory->ls("-m") list objects in memory
gDirectory->ls("-d") list objects on disk
gDirectory->ls() list objects in memory and then objects on disk
f->cd("Wed011003") Change to subdirectory Wed011003
gDirectory->GetFile() From a subdirectory, get a pointer to the file containing the subdirectory
TH1 *h; f->GetObject("Wed011003/histo;1",h) | histo from the top directory and the object will be in the top directory???? |

Create a sub-directory and return a pointer to the created directory.
Create first a/b/c and then a/b/d

TFile * file = new TFile("afile","RECREATE");

Clone histogrammes
Make a complete copy of the underlying object. See TH1, line 2544

TObject* TH1::Clone(const char* newname) const
    TH1* obj = (TH1*)IsA()->GetNew()(0);
    Copy(*obj); ..................

TH1F *h = (TH1F*)h1->Clone("h"); 
TH1F *hnew = (TH1F*)h->Clone("hnew") 
If 'newname' is set, the copy's name will be set to that name.

Fits to data, with error bars

i.e. a function defined in f1, a TF1 histogramme:
TF1 *f1 = new TF1("f1","[0]+[1]*x+[2]*x*x",90.,210.);

Some data, gr
gr = new TGraphErrors(np,volts,data,ex,ey);

Fit the data in gr, to the function in f1

Place the data points

Overlay a canvas on top of an existing PDF (pre-made plot)
Rene's solution, and $ROOTSYS/tutorials/image/img2pad.C

void canvasimage() {
   //create a canvas with a picture (.png,.jpg,.gif, etc) in the background
   TImage *img = TImage::Open("rose512.jpg");  //put your own picture here
   TCanvas *c1 = new TCanvas("c1");
   //Create a transparent pad filling the full canvas
   TPad *p = new TPad("p","p",0,0,1,1);

Make Class

root[] TFile f ("staff.root")

TFile** staff.root
TFile* staff.root
KEY: TTree T;1 staff data from ascii file

Look at T, and make appropriate class
TTree *MyTree = T
Files: MyClass.h and MyClass.C generated from Tree: T

root[] MyTree->Scan();
will print the first 8 variables of the tree.
root[] MyTree->Scan("*");
will print all the variable of the tree.
Specific variables of the tree can be explicit selected by list them in column separated list:
root[] MyTree->Scan("var1:var2:var3");
will print the values of var1, var2 and var3. A selection can be applied in the second argument:
root[] MyTree->Scan("var1:var2:var3","var1==0");
will print the values of var1, var2 and var3 for the entries where var1 is exactly 0.

root -b run in batch mode without graphics display
root -l do not show the startup panel
gROOT->Reset() Add at start of un-named scripts. Clears the variables, clears the global scope to the state
gROOT::GetListOf"TAB" For other gROOT actions
TFile f("staff.root"); read in file staff.root
  TFile *_file0 = TFile::Open("root://castorcms//castor/")
  Note the new formalism from Feb 2014, for castorcms
f->ls() or list file contents, write out list of trees
T->Show(10); show values of variables, 10th entry
T->Print() Print list of variables/structure for tree T
T->Scan("Cost:Age:Children") values for a list of leaves
T->StartViewer() Get a viewer to look at the tree
T->Draw("Cost:Age") plot cost versus age
TDatime t(unixTime_); Convert unix time to ordinary time
t.Print(); Print the time
UnZoom rh click on axis concerned, in drop down menu, click on UnZoom
ZoomOut rh click on axis concerned, in drop down menu, click on ZoomOut
The TPad::SetTicks() method specifies the type of tick marks on the axis. Let tx=gPad->GetTickx() and ty=gPad->GetTicky().
Axes TGaxis to draw more axes
Axes Paint axis with chopt comments
tx = 1; tick marks on top side are drawn (inside)
tx = 2; tick marks and labels on top side are drawn
ty = 1; tick marks on right side are drawn (inside)
ty = 2; tick marks and labels on right side are drawn
tx=ty=0 by default only the left Y axis and X bottom axis are drawn
Use TPad::SetTicks(tx,ty) to set these options. See also the methods of TAxis that set specific axis attributes.
  If multiple color-filled histograms are drawn on the same pad, the fill area may hide the axis tick marks.
  One can force the axis redrawing over all the histograms by calling: gPad->RedrawAxis()
TFile *f800 = new TFile("histo-run152847.root"); read in root file
f800->ls(); list contents of f800
hadd hadd newfile.root file_0.root file-1.root file-2.root file_3.root to add histos to a file
ifstream inFile ("cms_ecal_dcs_07_ECAL_HVM_0.csv"); read in csv file
f800->cd("demo"); go to histogram directory
gDirectory->ls("-d"); list the objects in the directory
h006->Draw(); draw one of the histos
h167 = new TH2D ("h167"," ", 102, 0.,102., 102, 0.,102.); new 2D histo
h65 = new TH1F ("h65"," ",100,0.,2.); new 1D histo
h65->SetTitle(" EE+, Ratios for Va750/Va800, B=0T, 31Jan2011"); Set title
hpx->GetXaxis()->SetTitle("Anode volts (Dynode = +600V) "); set x-axis title
h167->Fill(i+1,j+1,1.0); Fill histo
gPad->SetLogx(1) Set log scale, x-axis
gPad->SetLogy(1) Set log scale, y-axis
hpx->SetMaximum(5.); set Max Y axis
hpx->Draw(); Draw histo
hpx->Fit("gaus"); FIT FIT, contents of hpx with a gaussian
hpx->Fit("pol5"); FIT FIT, contents of hpx with a polynomial to power 5 (x**5)
hpx->Fit("expo"); FIT FIT, contents of hpx with an exponential
hpx->Fit("landau"); FIT FIT, contents of hpx to a landau
gr3->Fit("expo"); Fit an exponential to set of points gr3, where gr3 is a TGraph or TGraphErrors gr3(n,x,y,ex,ey);
gr3->Fit("pol0"); etc
gStyle->SetOptStat(0); no stats box
gStyle->SetOptStat(1); to print fit values in the plot stats box
gStyle->SetOptFit(1011); what fit values to print out
  mode = pcev (default = 0111)
  p = 1 print probability
  c = 1 print Chi-square/number of degrees of freedom
  e = 1 print errors (if e=1, v must be 1)
  v = 1 print name/values of parameters
ph700[i][j] = h006->GetBinContent(i+1,j+1); get bin content
hsimple.C generates hpx and hpxpy histos and writes them to hsimple.root
  from C: root tutorials

Unix commands from root

  • to stream root output to a file use the > key as usual:
  • .x protfit.c > fit-out.txt

  • start with .! before a unix command, ie
  • .! ls

Bin content

  • ix = icentre = histo->Xaxis->GetBinCenter(bin id along x)
  • then getBinContent

To link and use other files do

  • .L fn.C where fn.C does not have outside brackets
  • ie File print1.h:
// File print1.h:

int iy; // this will be a GLOBAL variable, accessible by other files !!!

void print1(int i, double ran1, int ib, double ran2, double probib, int icountib) {
  cout << " i= " << i << ", ran1 = " << ran1 << ", ib = " << ib << " ran2 = " 
  << ran2 << ", prob[ib] = " << probib << " icount[ib] = " << icountib << endl;  }

void prtchisq(double data[],int icount[],int bincount[],double chisqj, int bintot, int nevents, int ictot) {  cout << endl;
for(int i=0; i<5; i++) {
double chisqbin = ( (data[i]-double(icount[i]))**2) / icount[i] ;
cout << "i = " << i << ", bincount = " << bincount[i] << " data = " << data[i] << ", icount = " 
     << icount[i] << ", chisqbin = " << chisqbin << endl; }
cout << "bintot = " << bintot << ", nevents = " << nevents << ", ictot = " 
     << ictot << ", chisq = " << chisqj << "\n\n " << endl;}

Don't include type defs in function call !!!!!!

From  file: res-500-2p2.C

// if eta, lumiref,, lumi set for type in rescalc then DON'T do it here if have done .L rescalc.C before .x res-500-2p2.C!!!!!!!!!!!!!
//double eta = 2.2;
//double lumiref = 500.;
//double lumi = 3000.;
//double lumi = 500.;
eta=2.2; lumiref=500.; lumi=500;

rescalc(eta, lumiref, lumi);
// NOT NOT rescalc(double eta, double lumiref, double lumi); !!!!!!!!!!!!

  • TABs: typing f1->TAB will list all possible methods to do with f1, ie f1->Integral, -> Derivative, -> GetMaximum etc
  • In .tcshrc file put: alias root "root -l" to avoid startup panel
  • root[] TLine l
  • root[] l.Print()
  • root[] l.Print(); > test.log, Unix like I/O redirection (; is required before >)
  • root[] l.Dump(); >> test.log, Unix like I/O redirection to append onto existing file (; is required before >>)
  • root[] .class TLine, Use .class as quick help and reference

How to change text attributes

How do I obtain a list of Branch or Leaf names?

  • myTree->GetListOfBranches()->Print();
  • myTree->GetListOfLeaves()->Print(); > leaf-list.txt

How do I get the Tree setup from a root file generated by someone else?

  • Use MakeClass which will create the appropriate header file and class objects

How do I locate and fill the correct 1D or 2D bin, ie for EE ix, iy plots?

  • Use Int_t FindBin(Double_t x, Double_t y = 0, Double_t z = 0), eg:
Double_t ph = 45.63;
Int_t ix=36; 
Int_t iy=45;
Int_t nb = hxy->FindBin(Double_t(ix), Double_t(iy), 0); // returns a GLOBAL bin number
//SetBinContent(Int_t bin, Double_t content)
hxy->SetBinContent(nb, ph);

How to print a number and/or a string of text on the plot:

Double_t dg = 0.;
dg=100*(fit[1]+2*fit[2]*v )/(fit[0]+fit[1]*v+fit[2]*v*v);
char textToPlot[80];
sprintf(textToPlot,"%5.3f%%",dg);   // %% prints the % sign
cout << textToPlot  << endl;
TLatex t;
   t.DrawLatex(800,0.105,"per volt");

How to get run number etc into the histogramme title:

  string run;
  string side;
  string volts;
  run = iConfig.getUntrackedParameter<string>("runnum");
  side = iConfig.getUntrackedParameter<string>("EEside");
  volts = iConfig.getUntrackedParameter<string>("volts");
  TString tsrun, tsside, tsvolts, tsinfo;
   tsside = side;
   tsvolts = volts;
   tsrun = run;
   tsinfo = "Run " + run + ", " + side + ", " + volts;
h901 = fs->make<TH2D>("h901", tsinfo + ", digiph (ADC counts) versus rechit ph (ADC counts)",
100,-0.5,1000., 100,-0.5, 1000. );

******** and in config file:
run = ['158931','EE+','400/200']
process.demo = cms.EDAnalyzer('HVAnalyzer',
                runnum = cms.untracked.string(run[0]),
                EEside = cms.untracked.string(run[1]),
                volts = cms.untracked.string(run[2])

FAQ sites and How to's

Stanford skpark MINOS-viren

From Jpark - Tutorial Day 2 To find all methods associated with a class, command line completion with TAB.

  • Most methods which change an object begin "Set…"
  • Most methods which give information about an object begin "Get…"
  • TAB use, typing f1->TAB will list all possible methods to do with f1, ie f1->Integral, -> Derivative, -> GetMaximum etc
  • go to ROOT reference guide - > list of classes and key word search
  • cannot access object directly, use: delete toto; where toto is a pointer to the object
  • Looking for a method, ie Divide -> could be a parent method, ie in the public TPad area, a parent of TCanvas -> since TCanvas does not have a Divide method, the one in TPad is used
Finding 'lost' objects !
  • ROOT keeps lists of objects allowing them to be found easily
  • Go to ROOT Object Browser -> Click on 'root', click on Canvases, get window list
  • Each object has a unique name
Use a pointer found with gROOT or - if you know the address of the object, you could use a pointer, ie:
  • gROOT->GetListOfCanvases()->FindObject("c1");
  • gROOT is a GLOBAL pointer, with the address of the root folder of the folder tree.
  • gROOT points to an object of the class TROOT.
If you aren't sure which folder to look in, you can recursively search through all the folders:
  • Instead of gROOT->GetListOfCanvases()->FindObject("c1");
  • Do gROOT->FindObject("name");
This is the MAGIC FORMULA which allows to find (nearly) any object anywhere anytime. You'll use it all the time!! All you have to do now is put the address in the appropriate pointer and use it:
  • ClassName* toto = (ClassName*) gROOT->FindObject("nom"); (Have to respecify the class of the object we hope to find here)
  • Example: we look for canvas "c1" and wipe it clean:
  • TCanvas* c1_ptr = (TCanvas*) gROOT->FindObject("c1");
  • c1_ptr->Clear();
Testing if an object exists: gROOT-> FindObject("h1")
  • If it exists, get ie, (const TObject*)0xaffa198
  • If not, (const TObject*)0x0 function returns an address equal to zero
To be rigorous, you should always test the value of a pointer before trying to use it, ie
  • TH1F* p=(TH1F*)gROOT->FindObject("hh")
  • p->Draw()


ROOT tutorials
Histo tutorials
Canvas setup instructions with picture


Class index

TPad Click on Tpad in middle of screen to link to the Tpad class
TFile Open a root file
It is recommended to specify fname1 as ".root". The suffix ".root"
classTFile.html NEW or CREATE: Create a new file and open it for writing
if the file already exists the file is not opened.
  RECREATE: Create a new file, if the file already exists it will be overwritten.
| | Syntax: TFile * file = new TFile("afile","RECREATE");
  UPDATE: Open an existing file for writing. If no file exists, it is created.
  READ: Open an existing file for reading (default).
  If option = "" (default), READ is assumed. The file can be specified as a URL of the form:
file:///user/rdm/bla.root or file:/user/rdm/bla.root
file->Write(); Save all histograms in memory to file
  The file can also be a member of an archive, in which case it is specified as: or
which will open file.root which is a member of the file archive or member
from the archive. See TArchiveFile class
  TFile and its remote access plugins can also be used to open any file, i.e. also non ROOT files, using: file.tar?filetype=raw
TStyle This class lists the functions to set the following object attributes:
Canvas - Pad - Histogram axis - Lines - Fill areas - Text - Markers - Functions - Histogram Statistics and Titles,
SetLabelOffset(Float_t offset=0.005, Option_t *axis="X");
SetTitleFont(Style_t font=62, Option_t *axis="X");
SetTitleX(Float_t x=0); void SetTitleY(Float_t y=0.985)
TCanvas TCanvas construct and destruct syntax
TCanvas source code,
TPad* The TPad class is the most important graphics class in the ROOT system.
TPad source code ,
ie TPad::TPad(const char *name, const char *title, Double_t xlow, Double_t ylow, Double_t xup, Double_t yup, Color_t color, Short_t bordersize, Short_t bordermode)
TAttPad Manage TPad attributes, referenced by TStyle, ie SetMargin(Float_t left, Float_t right, Float_t bottom, Float_t top) etc


Example of the SetTitleOffset member
void SetTitleOffset (Float_t offset = 1, Option_t* axis = "X")
Specify a parameter offset to control the distance between the axis and the axis title.
offset = 1 means : use the default distance
offset = 1.2 means: the distance will be 1.2*(default distance)
offset = 0.8 means: the distance will be 0.8*(default distance)
axis specifies which axis ("x","y","z"), default = "x"
if axis="xyz", set all 3 axes

Example of the SetTitleSize member

void SetTitleSize (Float_t size = 0.02, Option_t* axis = "X")
 if axis =="x"  set the X axis title size
 if axis =="y"  set the Y axis title size
 if axis =="z"  set the Z axis title size
 *Any other value of axis will set the PAD title size!!!*
if axis="xyz" set all 3 axes


Comment ROOT
Most common error, no ";" at end of line This MAY NOT cause a compiler error and so is most frustrating!
Canvases A canvas has a default pad which has the name of the canvas itself
TCanvas(const char* name, const char* title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh) Set pos'n on screen and size
TCanvas(const char *name, const char *title, Int_t ww, Int_t wh) Set size, random position on screen
TCanvas(const char* name, const char* title = "", Int_t form = 1) Sets up a canvas, of size/pos for 5 forms, 1-5
TCanvas(const char *name, Int_t ww, Int_t wh, Int_t winid) Create an embedded canvas
TLine * l; define a pointer to a line object, called l
l = new TLine(x1,y1,x2,y2); l->SetLineStyle(2); l->Draw(); l is new so stays on heap??, line style 'dash'
TArrow * ar; define a pointer to an arrow object, called ar
ar = new TArrow(200, 0.08, 200, 0.03, 0.01, ">"); ar->Draw(); x1, y1, x2, y2, size, "arrow head", also "<", "|>", "<|", "<>", "<|>"
char textToPlot[80]; dg = 0.0148; printing text and values of variables to the canvas using latex
sprintf(textToPlot,"%5.4f%%",dg); cout << textToPlot << endl; using sprintf to combine text and variable, note the format spec %5.4f and the percentage sign enterred with %%
TLatex t; t.SetTextAlign(22); t.SetTextSize(0.05);
t.SetTextAlign(Align); horiz 1=left, 2=centre, 3=rt, vert 1=bott, 2=centre, 3=top, ie Align=23
t.DrawLatex(195,0.105,textToPlot); t.DrawLatex(195,0.09,"per volt");
Histo titles etc f1->SetTitle("Dynode scan, anode 800V, 3.8T");
f1->GetXaxis()->SetTitle("Anode-Dynode voltage (V)"); x-axis title
f1->GetXaxis()->CenterTitle(); places x-axis title at centre across plot
f1->GetYaxis()->SetTitle("VPT response (arb. units)"); y-axis title
f1->GetYaxis()->CenterTitle(); places y-axis title at centre along y
f1->GetYaxis()->SetRangeUser(0.894,1.01); set user range for the Y axis
f1->GetXaxis()->SetRangeUser(90.,210.); set user range for the X axis
gStyle->SetTitleOffset(1.1,"y"); y-axis title, distance from y axis
gStyle->SetTitleOffset(1.,"x"); x-axis title, distance from x axis
gStyle->SetTitleAlign(13); histo title position along x, global set for all histos following
gStyle->SetPadBottomMargin(0.15); Set distance from histo x-axis to bottom of pad
gROOT->ProcesssLine(".x myprog.C"); 
to execute a script inside another script
max 20 value, Set max value on Y axis for 1D hist #20 h20->SetMaximum(value);
min 20 value, Set min value on Y axis for 1D hist #20 h20->SetMinimum(value);
Get max entries from histo h1 h1->GetMaximum();
Get min entries from histo h1 h1->GetMinimum();
histo/del 10 h10->Delete();
Increase # of points plotted along a fn, f1 (default is 100 only) f1.SetNpx(200);
h/fill, h1->Fill(x); (note the capital F!)
Set y-axis range on a 2D function plot f1->GetYaxis()->SetRangeUser(min, max);
Data from fits func->GetParameter(0);
Data from fits func->GetParameter(1);
Data from fits func->GetParameter(2); etc
Error on data from fits func->GetParameterError(0); etc
Set up a function, transfer the coefficients, draw TF1 *f1 = new TF1("f1","[0]+[1]*x+[2]*x*x",360.,860.); x from 360 to 860
f1->SetParameters(fit[0],fit[1],fit[2]); f1->Draw();
Line characteristics f1->SetLineColor(2); 1=blk 2=red 3=bright grn 4=bright blue 5=yell 6=pink 7=aqua 8=grn 9=blue
f1->SetLineWidth(2); // range from 1-15
f1->SetTitle("Anode scan, anode-dynode 200V, 0T");
int_t lwid = 0; lwid = f1->GetLineWidth();
int_t lcol = 0; lcol = f1->GetLineColor();
Un-named scripts must start and end with {....}
  with #include statements inside the {
  All statements executed in the interpreters global scope
  Variables are in the global scope and are available on the cmd line, even after script has done executing
gROOT->Reset() place at top of un-named script, to reset global environment/clear the variables
  calls destructor of objects, if object created on stack
  If object was created on the heap, with 'new', it is not deleted
  Must call the destructor explicitly (or get Memory leak warnings)
Named scripts #include statements, then function statements, no {....} from start to end
  Objects are created on the stack, and are deleted upon exit, including histos
  To avoid histo dissappearing, create it on the heap using 'new'
  Histos and trees auto deleted when the current directory is closed
ie file script.C:  
#include <iostream.h>  
int run()  
{cout << " Hello" << endl; return 0; }  
root[0] .L script.C  
root[1] run ()  

Setting up Root, 23.9.09

Success incorporating ROOTSYS into PATH in tcsh shell.
  • setenv ROOTSYS /afs/
  • setenv PATH $PATH":$ROOTSYS" appends the ROOTSYS string, with a colon, to the rest of the PATH string set.

Trip ups and Warnings

28 Jul 2014 Problems, in HXX work, with statement
Need to separate out with Double_t myintegral = 0.; myintegral = hMZ1_3->Integral(); hMZ1_3->Scale(1./myintegral);

Memory leakage warnings from ROOT - happens if creating same histo again, ie running .C file again. Pointers to original histos are lost -> old histos in inaccessible memory space. Change directory to zero. Changes ownership of histos from ROOT to me. Can then delete histos. However ROOT manages all these memory leaks so not an issue.

Paw to Root


-- DavidCockerill - 05-Nov-2009

  • pict1_TColor_002.png:
Topic attachments
I Attachment History Action Size Date Who Comment
C source code filec Tree-test.C r1 manage 3.0 K 2015-06-02 - 13:34 DavidCockerill  
C source code filec Tree-vpts-types-in-dat-file.c r1 manage 3.7 K 2015-06-04 - 11:15 DavidCockerill  
Unknown file formatdat basic-vpts-john-wood-linux-data.dat r1 manage 2.4 K 2015-06-04 - 11:15 DavidCockerill  
Unknown file formatdat basic-vpts-with-types.dat r1 manage 3.1 K 2015-06-04 - 11:15 DavidCockerill  
Unknown file formatdat basic.dat r1 manage 0.1 K 2015-06-02 - 13:34 DavidCockerill  
C source code filec dynode-scan-fit.C r1 manage 4.0 K 2013-12-02 - 10:38 DavidCockerill  
C source code filec fit-protons-with-eta.C r1 manage 2.8 K 2015-06-17 - 13:54 DavidCockerill  
PNGpng pict1_TColor_002.png r1 manage 55.0 K 2019-09-26 - 10:49 DavidCockerill  
Edit | Attach | Watch | Print version | History: r121 < r120 < r119 < r118 < r117 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r121 - 2021-10-17 - DavidCockerill
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright &© 2008-2023 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback