# 2D Graphs

Under specific circumstances, it might be useful to plot some quantities versus two variables, therefore creating a bi-dimensional graph. Of course ROOT can help you in this task, with the `TGraph2DErrors` class. The following macro produces a bi-dimensional graph representing a hypothetical measurement, fits a bi-dimensional function to it and draws it together with its x and y projections. Some points of the code will be explained in detail. This time, the graph is populated with data points using random numbers, introducing a new and very important ingredient, the ROOT `TRandom3` random number generator using the Mersenne Twister algorithm[1]

```// Create, Draw and fit a TGraph2DErrors
void macro4(){
gStyle->SetPalette(kBird);
const double e = 0.3;
const int nd = 500;

TRandom3 my_random_generator;
TF2 f2("f2",
"1000*(([0]*sin(x)/x)*([1]*sin(y)/y))+200",
-6,6,-6,6);
f2.SetParameters(1,1);
TGraph2DErrors dte(nd);
// Fill the 2D graph
double rnd, x, y, z, ex, ey, ez;
for (Int_t i=0; i<nd; i++) {
f2.GetRandom2(x,y);
// A random number in [-e,e]
rnd = my_random_generator.Uniform(-e,e);
z = f2.Eval(x,y)*(1+rnd);
dte.SetPoint(i,x,y,z);
ex = 0.05*my_random_generator.Uniform();
ey = 0.05*my_random_generator.Uniform();
ez = fabs(z*rnd);
dte.SetPointError(i,ex,ey,ez);
}
// Fit function to generated data
f2.SetParameters(0.7,1.5);  // set initial values for fit
f2.SetTitle("Fitted 2D function");
dte.Fit(&f2);
// Plot the result
auto c1 = new TCanvas();
f2.SetLineWidth(1);
f2.SetLineColor(kBlue-5);
TF2   *f2c = (TF2*)f2.DrawClone("Surf1");
TAxis *Xaxis = f2c->GetXaxis();
TAxis *Yaxis = f2c->GetYaxis();
TAxis *Zaxis = f2c->GetZaxis();
Xaxis->SetTitle("X Title"); Xaxis->SetTitleOffset(1.5);
Yaxis->SetTitle("Y Title"); Yaxis->SetTitleOffset(1.5);
Zaxis->SetTitle("Z Title"); Zaxis->SetTitleOffset(1.5);
dte.DrawClone("P0 Same");
// Make the x and y projections
auto c_p= new TCanvas("ProjCan",
"The Projections",1000,400);
c_p->Divide(2,1);
c_p->cd(1);
dte.Project("x")->Draw();
c_p->cd(2);
dte.Project("y")->Draw();
}
```

Let's go through the code, step by step to understand what is going on:

• Line 3: This sets the palette colour code to a much nicer one than the default. Comment this line to give it a try. This article gives more details about colour map choice.
• Line 7: The instance of the random generator. You can then draw out of this instance random numbers distributed according to different probability density functions, like the Uniform one at lines 27-29. See the on-line documentation to appreciate the full power of this ROOT feature.
• Line 8: You are already familiar with the `TF1` class. This is its two-dimensional version. At line 16 two random numbers distributed according to the `TF2` formula are drawn with the method `TF2::GetRandom2(double& a, double&b)`.
• Line 27-29: Fitting a 2-dimensional function just works like in the one-dimensional case, i.e. initialisation of parameters and calling of the `Fit()` method.
• Line 34: The Surf1 option draws the `TF2` objects (but also bi-dimensional histograms) as coloured surfaces with a wire-frame on three-dimensional canvases. See Figure 4.3.
• Line 35-40: Retrieve the axis pointer and define the axis titles.
• Line 41: Draw the cloud of points on top of the coloured surface.
• Line 43-49: Here you learn how to create a canvas, partition it in two sub-pads and access them. It is very handy to show multiple plots in the same window or image.

A dataset fitted with a bidimensional function visualised as a colored surface.