root icon indicating copy to clipboard operation
root copied to clipboard

[ROOT-10952] Vertical grid lines in ratioplot4.C not at specified positions

Open vepadulano opened this issue 1 year ago • 4 comments

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

vepadulano avatar Feb 04 '24 17:02 vepadulano

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: Screenshot 2024-02-13 at 13 21 33 It is a precision issue. It might be that on an other machine it will not give the same result.

couet avatar Feb 13 '24 12:02 couet

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.

couet avatar Feb 14 '24 11:02 couet

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.);
}

couet avatar Feb 14 '24 14:02 couet

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

linev avatar Feb 14 '24 15:02 linev

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

linev avatar Feb 27 '24 13:02 linev