Graph: non correct display of error bars when exceeding y-range
Check duplicate issues.
- [ ] Checked for duplicates
Description
Dear ROOT developpers,
I would like to report some bugs that I observed when displaying some TGraph errors (please find the reproducers code provided below). Here I used TGraphAsymmErrors.
-
The first issue
testErrorGraph_v1is I am creating a frame to display a graph with error but controling the y-range for the display (see screen shot below).-
The points have increasing errors bars and some should go beyond that y-range (starting from
x=4) however the end of error bars are displayed on the x-bottom and top axis. So it looks like it is the total error bar while it is indeed not. It would be nice to not have those vertical lines if the error bars exceed the y-range used for the plot. -
For the rightest most point (
x=9) I have put the data point on purpose to be below the ymin value and you can see the weird display too.
-
-
The second issue
testErrorGraph_v2is related to a very weird interplay betweenTPad::SetBottomMargin()function and usingTPad::SetLogy()function- If one sets the bottom margin to be
0withpad.SetBottomMargin(0)here is the plot- Again the error bars starting from
x>=3should go beyondymin=0.1. - The last point which I set to be negative is displayed on the x-axis while it should indeed not be displayed since
ymin= 0.1.
- Again the error bars starting from
- If one sets the bottom margin of the pad to be different from
0with e.g.pad.SetBottomMargin(0.1), notice the last point atx=9disappear with a white space. If I increase the marker size you can see that this white space increases as shown in the two screen shots below
- If one sets the bottom margin to be
--> I believe the best would be to not have that point or white space displayed in any case
Many thanks in advance for the fix that would be super helpful, In the meantime I have found some very hacky workaround (not very useful here I just played with several ways of displaying the information to arrive to what I want), Best, Romain
Reproducer
Below are the two codes that allow reprocuding the errors
testErrorGraph_v1
import ROOT
from array import array
ROOT.gROOT.SetBatch(True)
ROOT.gStyle.SetEndErrorSize(10)
nPoints = 10
# Set ymin and ymax on purpose so that some error bars should be go beyon this range
ymax = 4
ymin = 0
# Data x, y
data_x = array('d', list(range(nPoints)))
data_y = array('d', [2.]*nPoints)
# x and y up/down errors
# Increasing y-error for each points
unc_y_lo = array('d', [0.5*(i+1) for i in range(nPoints)])
unc_y_hi = array('d', [0.5*(i+1) for i in range(nPoints)])
unc_x_lo = array('d', [0]*nPoints)
unc_x_hi = array('d', [0]*nPoints)
# Make last point be out of range w.r.t to the zoom
data_y[-1] = ymin-1
canv = ROOT.TCanvas("c","c")
canv.cd()
pad = ROOT.TPad("pad", "pad", 0.1, 0.1, 0.9, 0.9)
pad.Draw()
pad.cd()
xminFrame = min(data_x) - 0.5
xmaxFrame = max(data_x) + 0.5
yminFrame = ymin
ymaxFrame = ymax
drawframe = pad.DrawFrame(xminFrame, yminFrame, xmaxFrame, ymaxFrame)
gr = ROOT.TGraphAsymmErrors(nPoints, data_x, data_y, unc_x_lo, unc_x_hi, unc_y_lo, unc_y_hi)
gr.SetMarkerColor(2)
gr.SetLineColor(ROOT.kRed)
gr.SetMarkerStyle(20)
gr.SetMarkerColor(ROOT.kBlue)
gr.SetMarkerSize(1.5)
gr.SetLineWidth(3)
gr.Draw("same PE0")
canv.Print("testErrorGraph_v1.pdf")
testErrorGraph_v2
import ROOT
from array import array
ROOT.gROOT.SetBatch(True)
ROOT.gStyle.SetEndErrorSize(10)
nPoints = 10
# Set ymin and ymax on purpose so that some error bars should be go beyon this range
ymax = 4
# Set ymin > 0 since here we use log scale
ymin = 0.1
# Data x, y
data_x = array('d', list(range(nPoints)))
data_y = array('d', [2.]*nPoints)
# x and y up/down errors
# Increasing y-error for each points
unc_y_lo = array('d', [0.5*(i+1) for i in range(nPoints)])
unc_y_hi = array('d', [0.5*(i+1) for i in range(nPoints)])
unc_x_lo = array('d', [0]*nPoints)
unc_x_hi = array('d', [0]*nPoints)
# Make last point negative
data_y[-1] = -1
canv = ROOT.TCanvas("c","c")
canv.cd()
pad = ROOT.TPad("pad", "pad", 0.1, 0.1, 0.9, 0.9)
pad.Draw()
pad.cd()
# Make the plot with bottom margin = 0 and something different than 0
# observe the difference for the last point
pad.SetBottomMargin(0.)
#pad.SetBottomMargin(0.1)
pad.SetLogy()
xminFrame = min(data_x) - 0.5
xmaxFrame = max(data_x) + 0.5
yminFrame = ymin
ymaxFrame = ymax
drawframe = pad.DrawFrame(xminFrame, yminFrame, xmaxFrame, ymaxFrame)
gr = ROOT.TGraphAsymmErrors(nPoints, data_x, data_y, unc_x_lo, unc_x_hi, unc_y_lo, unc_y_hi)
gr.SetMarkerColor(2)
gr.SetLineColor(ROOT.kRed)
gr.SetMarkerStyle(20)
gr.SetMarkerColor(ROOT.kBlue)
gr.SetMarkerSize(3)
gr.SetLineWidth(3)
gr.Draw("same PE0")
canv.Print("testErrorGraph_v2.pdf")
ROOT version
I think all versions are affected but I tested it with ROOT 6.30/02 and 6.30/00
Installation method
Build from source
Operating system
Linux, MacOs
Additional context
No response
Thanks for your report. I will check. (note: the option "same" does not exist fro graph drawing)
I have the fix for the 1st issue. It is not only in TGRaphAssymErrors but also in TGraphErrors and TGraphBentErrors and also for the drawing options > |> || []
The 2nd one seems more tricky as your y scale has negative values which is always tricky with log scale. I will first make a PR for the first one and once merged I will tackle the 2nd issue.
This PR fixes the 1st issue: https://github.com/root-project/root/pull/16093
To make it easier to debug interactively I made this C version of the 2nd issue:
void testErrorGraph_v2() {
gStyle->SetEndErrorSize(10);
auto c = new TCanvas();
c->Divide(3,1);
c->SetGridx();
c->SetGridy();
const int n = 10;
Double_t x[n] = {0,1,2,3,4,5,6,7,8,9};
Double_t y[n] = {2,2,2,2,2,2,2,2,2,-4};
Double_t exl[n] = {0,0,0,0,0,0,0,0,0,0};
Double_t eyl[n] = {1,2,3,4,5,6,7,8,9,10};
Double_t exh[n] = {0,0,0,0,0,0,0,0,0,0};
Double_t eyh[n] = {1,2,3,4,5,6,7,8,9,10};
auto gr = new TGraphAsymmErrors(n,x,y,exl,exh,eyl,eyh);
gr->SetLineColor(kRed);
gr->SetMarkerStyle(20);
gr->SetMarkerColor(kBlue);
gr->SetMarkerSize(1.5);
gr->SetLineWidth(3);
c->cd(1);
gPad->DrawFrame(-1,0.1,10,4);
gr->Draw("E0P");
c->cd(2)->SetLogy();
gPad->DrawFrame(-1,0.1,10,4);
gr->Draw("E0P");
c->cd(3)->SetLogy();
c->cd(4)->SetBottomMargin(0.);
gPad->DrawFrame(-1,0.1,10,4);
gr->Draw("E0P");
}
Many thanks @couet for the fix of the first issue!
I took another look at the second "issue." In this case, the plot in Y-log scale is invalid because some points are negative along the Y-axis. The graph rendering does "its best," but handling y=-1 will always be approximate. There is no obvious clean fix without compromising the entire code and generating potential bad side effects. In a way, this spurious plot indicates that something is wrong with that data point, and in reality, something is indeed wrong as the Y value is negative.
Just in case - canvas displayed correctly in web mode:
Hi @couet, @linev,
It appears this issue is closed, but wasn't yet added to a project. Please add upcoming versions that will include the fix, or 'not applicable' otherwise.
Sincerely, :robot: