root
root copied to clipboard
[ROOT-10952] Vertical grid lines in ratioplot4.C not at specified positions
Check duplicate issues.
- [ ] Checked for duplicates
Description
From https://its.cern.ch/jira/browse/ROOT-10952
In the bottom panel as created by the ratio plot tutorial tutorials/hist/ratioplot4.C
vertical grid lines are set by
auto rp1 = new TRatioPlot(h1);
std::vector<double> lines = {-3, -2, -1, 0, 1, 2, 3};
rp1->SetGridlines(lines);
The lines at -3, -2, -1, 1 and three are displayed correctly but the lines at 0 and 2 (and the border line at 4) are slightly offset to lower values in the reference plot at [https://root.cern/doc/master/pict1_ratioplot4.C.png] If running the macro and by hand and resizing the lower panel in the interactive display, some of the vertical grid lines are also displayed at wrong (i.e. lower value) positions, although it are not necessarily the same ones as in the reference rendering in the documentation.
Reproducer
As per description
ROOT version
Any
Installation method
Any
Operating system
Any
Additional context
No response
Indeed this has nothing to do with TRatioplot. It can be reproduced with the simple following macro:
void lineonaxis(){
auto c1 = new TCanvas("c1", "c1",10,53,700,525);
gPad->DrawFrame(-5,-1.25,5,1.25);
TLine *line = new TLine(-5,-0.5,5,-0.5);
line->SetLineStyle(2);
line->Draw();
}
Which, on my Mac, gives:
It is a precision issue. It might be that on an other machine it will not give the same result.
The problem has been simplified to:
{
double x = 6.25;
double y = 1.5625000232831;
double y1 = -y;
double y2 = y;
double yv = -0.5;
auto c1 = new TCanvas("c1", "c1", 0, 0, 700, 525);
c1->Range(-x, y1, x, y2);
TLine *line = new TLine();
line->DrawLine(-x, yv, x, yv) ->SetLineColor(kRed);
double r = 1./(y2-y1);
line->DrawLineNDC(0., r*(yv-y1),
1., r*(yv-y1))->SetLineColor(kBlue);
}
DrawlLine paint a red horizontal line at yv = 0.5
. DrawLineNDC does the same in NDC coordinates. The 2 lines should overlap but they don't (by 1 pixel). Note that the values defined at the beginning of the macro are those that make the problem. As soon as you change, for instance, y
the lines will overlap. Same if you change interactively the canvas size.
The same problem shows with web canvas (@linev ?) for instance with this simple macro:
void lineonaxis(){
auto c1 = new TCanvas("c1", "c1", 0, 0, 700, 525);
c1->SetGridy();
TH1F *f = gPad->DrawFrame(-5, -1.25, 5, 1.25);
f->GetYaxis()->SetNdivisions(10);
f->GetXaxis()->SetNdivisions(0);
auto line = new TLine();
line->SetLineColor(kRed);
line->DrawLine(-5, -1., 5 , -1.);
line->DrawLine(-5, -0.5, 5 , -0.5);
line->DrawLine(-5, 0., 5 , 0.);
line->DrawLine(-5, 0.5, 5 , 0.5);
line->DrawLine(-5, 1., 5 , 1.);
}
Yes, I see same problem in JSROOT.
It is because we are using different coordinates inside frame for axes/grids/histogram drawings and for TLine
which is drawn in the pad coordinates.
Main problem here that left/top coordinates of the frame are rounded integer values.
And then axis position calculated relative to this rounded values.
In this example vertical coordinate of the frame should be 52.5
, but rounded to 52
or 53
.
Drawing will be perfect when canvas vertical size is 500.
I see no simple solution here. To fix problem we have to change fX1, fY1, fX2, fY2 members of the TPad every time canvas width or height is changing.
More easy solution is to provide extra draw option for TLine
(and similar classes) where coordinates calculated using frame functions. Then it automatically will be adjusted to the rounded position of the frame
In the ROOT it is pure rounding problem which will be fixed by #14837
In JSROOT it is SVG frame layer with integer coordinates and therefore rounding works differently. Solved for this particular case of TLine by comit: https://github.com/root-project/jsroot/commit/4abf28c32f184b166a43b0943f587a7068804749