# Zooming a canvas with TH2

Hello,

this is an old issue which I noticed already in my early ROOT times. I heavily use the possibility to zoom a canvas by drawing a TH2 first (as suggested in ROOT manual). This works perfectly. But then, when I try to zoom the canvas again by mouse in the GUI, the problems starts. Either it doesn’t do anything or the zoomed region is different from that one selected by mouse. A subsequent attempt for zooming again fails in most cases… Can this be solved?

When zooming by mouse fails, I try to use TAxis::SetRangeUser method. And again I’m not successful very often…

I’m using the trick with TH2 mainly because I need to superimpose several graphs with different value ranges. Suppose one has two graphs, one with values in (0, 1) and the second with values in (-1, 0). If one plots the first one, the scale of canvas is set to (0, 1) and when the second graph is plotted it cannot be seen. Is there a way to use kind of “dynamic scale adjustment”?

BTW. I’m using ROOT 5.15 on SL4. If you cannot reproduce my problems I can supply examples.

Thank you very much for any hints,
Kaspi.

I cannot reproduce your problem. I have tried to simulate what you described with the following example:

``````{
c1 = new TCanvas("c1","2 Graphs",200,10,700,500);
TH2D *f  = new TH2D("f","f",10,0,7,10,1,12);
f->Draw();
const Int_t n = 20;
Double_t x[n], y[n], x1[n], y1[n];
for (Int_t i=0;i<n;i++) {
x[i] = i*0.15;
y[i] = 10*sin(x[i]+0.2);
y1[i] = y[i]+1;
x1[i] = x[i]+3;
}
gr0 = new TGraph(n,x,y);
gr1 = new TGraph(n,x1,y1);
gr0->SetMarkerStyle(3);
gr1->SetMarkerStyle(3);
gr1->Draw("CP");
gr0->Draw("CP");
}``````

With this example I can zoom both the X and Y axis using the mouse and it works fine.

Hi,

thanks for reply and for the example. Now I can describe the problem really precisely.

When I run the example I get x range 0 to 7 and y range 1 to 12. This is OK. Then I tried to zoom x region 3 to 4 by mouse. I got region 2.8 to 4.2. Strange, because I really did my best to select precisely region 3 to 4. But OK. Then I tried to zoom again, this time region 3.4 to 3.7 and nothing happened.

Then I tried the SetRangeUser method, particularly I added the following line to your code

```f->GetYaxis()->SetRangeUser(..., ...); ```
and instead of range 8 to 12 I got 7.5 to 12, instead of 4 to 6 I got 3.2 to 6.5 and instead of -20 to +20 I got 1 to 12 (i.e. the method did nothing).

Kašpi.

That’s normal. The zooming is based on the TH2F bins. In the example I sent you I put only 10 bins on each axis. So the precision is not very good. Increase the number of bins (100 for instance) and you will get a better precision in pointing.

OK, now I understand. But this feature makes (in my opinion) the zooming even more awkward. Isn’t there an easy method to set scales for a TPad? I tried methods TPad::Range and RangeAxis, but they just emits a signal and nothing happens. Or one can use TAxis::SetRangeUser, but it is not clear which axes one should use if there are several objects drawn in the pad. All these solutions look too complicated for me. Is there a way to do it easily? Many thanks,

Kašpi.

``````{
c1 = new TCanvas("c1","2 Graphs",200,10,700,500);
const Int_t n = 20;
Double_t x[n], y[n], x1[n], y1[n];
for (Int_t i=0;i<n;i++) {
x[i] = i*0.15;
y[i] = 10*sin(x[i]+0.2);
y1[i] = y[i]+1;
x1[i] = x[i]+3;
}
gr0 = new TGraph(n,x,y);
gr1 = new TGraph(n,x1,y1);
gr0->SetMarkerStyle(3);
gr1->SetMarkerStyle(3);
gr1->Draw("ACP");
gr0->Draw("CP");
gr1->GetXaxis()->SetLimits(-1.1,6.2);
}``````

Thanks, but I asked for something slightly else. Supposed you have a pad with several objects drawn. You’re given pointer to the pad and your task is to set the ranges. Is there an easy and straightforward way? Thanks again,

Kašpi.

Can you sen a small example illustrating what you are talking about ?

[code]{
/// create canvas and draw something
new TCanvas();
double X1[3] = {0., 1., 2.};
double X2[3] = {0., -1., -2.};
double Y1[3] = {0., 1., 4.};
double Y2[3] = {-1., -2., -5.};

``````TGraph *g1 = new TGraph(3, X1, Y1);
TGraph *g2 = new TGraph(3, X1, Y2);
TGraph *g3 = new TGraph(3, X2, Y1);
g1->Draw("AL");
g2->Draw("L");
g3->Draw("L");

/// Now I'd like to change axis ranges to show all the graphs
/// something like gPad->SetRanges(-2., 2, -5, 5);
``````

}
[/code]

I’m looking for something independent on what was drawn in the canvas. Sure, one can use g1->GetXaxis->SetLimits() here. But only because you know that g1 was drawn with “A” option. What shall I do if I have only gPad pointer to the current canvas, I do not know what is drawn there and I want to set x range -2 to 2 and y range -5 to 5?

And secondly, what can I do in the GUI to show the 3rd graph? In the popup menu I can only pick the TAxis::SetRangeUser which fails if I enter range -2 to 2.

Thanks, Kaspi.

You should use TMultiGraph.

OK, and what shall I do if there are not only TGraph objects drawn. If there are also TH1 objects or TLine objects… ? Like in the following code:

[code]{
/// create canvas and draw something
new TCanvas();
myGraph->Draw(“AP”);
myHistogram->Draw(“same”);
myEllipse->Draw(“same”);

/// Now I’d like to change axis ranges to show all the elements of various kind
/// something like gPad->SetRanges(-2., 2, -5, 5);
} [/code]

You take the axis of the first element and you change the limits with SetLimits.
I am not sure we undertand each other …

If we take again the first example I sent you. You have a frame “f” well defined so you know it is this guy which define the scale then you can change that scale as you wish:

``````{
c1 = new TCanvas("c1","2 Graphs",200,10,700,500);
TH2D *f  = new TH2D("f","f",500,0,7,500,1,12);
f->Draw();
const Int_t n = 20;
Double_t x[n], y[n], x1[n], y1[n];
for (Int_t i=0;i<n;i++) {
x[i] = i*0.15;
y[i] = 10*sin(x[i]+0.2);
y1[i] = y[i]+1;
x1[i] = x[i]+3;
}
gr0 = new TGraph(n,x,y);
gr1 = new TGraph(n,x1,y1);
gr0->SetMarkerStyle(3);
gr1->SetMarkerStyle(3);
gr1->Draw("CP");
gr0->Draw("CP");
f->GetXaxis()->SetLimits(-10.,10);
}``````

You can also use DrawFrame from TPad. But that very similar to the previous macro.