Error bars inside markers with draw("same")

Hi,

I discovered that when plotting a TGraphErrors with error bars smaller than the markers, the bars are now displayed over the marker, pointing inward. I assume it’s a new feature dating back from release 6.26, given what I could guess from the release notes. That’s a very nice one, by the way.
However I noticed that these bars do not appear if a second graph is drawn. If the error bars are increase by hand so that they become larger than the markers, then they appear on both graphs.
Here is a minimal working environment to confirm this:

#include "TGraphErrors.h"
#include "TCanvas.h"

int main() {

    const int nPoints = 10;
    double x[nPoints] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    double y2[nPoints] = {1.5, 2.5, 2, 3.5, 3, 4, 4.5, 5.5, 5, 5.5};
    double y1[nPoints] = {1, 2, 1.5, 3, 2.5, 3.5, 4, 5, 4.5, 6};
    double ex[nPoints] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    double eyy = 0.02;
    double ey[nPoints] = {eyy, eyy, eyy, eyy, eyy, eyy, eyy, eyy, eyy};

    TGraphErrors *graph1 = new TGraphErrors(nPoints, x, y1, ex, ey);
    TGraphErrors *graph2 = new TGraphErrors(nPoints, x, y2, ex, ey);

    TCanvas *canvas = new TCanvas("canvas", "TGraphErrors Example", 1600, 1200);

    graph1->SetMarkerStyle(20);
    graph1->SetMarkerColor(kRed);
    graph1->SetMarkerSize(5);
    graph1->SetLineWidth(3);
    graph1->SetTitle(Form("TGraphErrors with errors bars of %.2f", eyy));

    graph2->SetMarkerStyle(20);
    graph2->SetMarkerColor(kBlue);
    graph2->SetMarkerSize(5);
    graph2->SetLineWidth(3);

    graph1->Draw("AP"); 
    graph2->Draw("P SAME");

    canvas->SaveAs(Form("MWE_error_bars_%.2f.png", eyy));
}

and here are 2 versions of the output plot obtained for vertical error bars of 0.02 and 0.2:


Could this be a bug? Maybe the new feature has not been implemented “recursively” so that it can work nicely with the “same” option for draw().

Cheers,
Tristan


ROOT Version: 6.32.02


Hello @Tristan,
thank you for reporting this, I add in the loop our graphics expert @couet!
Cheers,
Monica

I get the same result. I will check

Ok, understood. I tried this:

{
    const int nPoints = 10;
    double x[nPoints] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    double y1[nPoints] = {1, 2, 1.5, 3, 2.5, 3.5, 4, 5, 4.5, 6};
    double ex[nPoints] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    double eyy = 0.02;
    double ey[nPoints] = {eyy, eyy, eyy, eyy, eyy, eyy, eyy, eyy, eyy};
    auto graph1 = new TGraphErrors(nPoints, x, y1, ex, ey);
    graph1->Draw("AP");
}

whixh draws your graph wihout any marker. I get this:


The errors bars are so small that any marker excpt a simple dot will fit in it.

Hello Couet and thank you for your answer. However I don’t get your point, I’m sorry. I know the errors are smaller than the marker and this is what I pointed out. The thing is that the first TGraphErrors draws the errors within the marker, on top of it, while the second, drawn with the “same option”, doesn’t even though it’s a circle marker as well.

Cheers,
Tristan

Yes, you are correct. When graph1 is drawn with the option "AP", it should not display the error bars. It works correctly when the option "A" is not included. I will debug. The minimal reproducer is:

{
   const int n  = 2;
   double x[n]  = {1, 10};
   double y[n]  = {1.0,  3.0};
   double ex[n] = {0, 0};
   double ey[n] = {0.02, 0.02};
   
   auto g = new TGraphErrors(n, x, y, ex, ey);
   
   g->SetMarkerStyle(20);
   g->SetMarkerColor(kRed);
   g->SetMarkerSize(5);
   g->SetLineWidth(3);
   
   g->Draw("AP");
}

Indeed the real minimal reproducer is:

{
   auto C = new TCanvas();
   C->DrawFrame(0., 0., 10, 10);

   auto g1 = new TGraphErrors();
   g1->AddPointError(5,5,0,0.02);
   g1->SetMarkerStyle(24);
   g1->SetMarkerSize(9);
   g1->Draw("P");
}

The complete test should be done with:

{
   auto C = new TCanvas();
   C->DrawFrame(0., 0., 10, 10);

   auto g1a = new TGraphErrors();
   g1a->AddPointError(2,7,0.3,0.3);
   g1a->SetMarkerStyle(24);
   g1a->SetMarkerSize(9);
   g1a->Draw("P");

   auto g1b = new TGraphErrors();
   g1b->AddPointError(2,3,0.3,0.3);
   g1b->SetMarkerStyle(24);
   g1b->SetMarkerSize(9);
   g1b->Draw(">P");

   auto g2a = new TGraphAsymmErrors();
   g2a->AddPointError(5,7,0.2,0.3,0.2,0.3);
   g2a->SetMarkerStyle(24);
   g2a->SetMarkerSize(9);
   g2a->Draw("P");

   auto g2b = new TGraphAsymmErrors();
   g2b->AddPointError(5,3,0.2,0.3,0.2,0.3);
   g2b->SetMarkerStyle(24);
   g2b->SetMarkerSize(9);
   g2b->Draw(">P");

   auto g3a = new TGraphBentErrors();
   g3a->AddPointError(8,7,0.2,0.3,0.2,0.3);
   g3a->SetMarkerStyle(24);
   g3a->SetMarkerSize(9);
   g3a->Draw("P");

   auto g3b = new TGraphBentErrors();
   g3b->AddPointError(8,3,0.2,0.3,0.2,0.3);
   g3b->SetMarkerStyle(24);
   g3b->SetMarkerSize(9);
   g3b->Draw(">P");
}

This PR (under construction) fixes the problem: Do not draw error bars when they are smaller than the marker. by couet · Pull Request #16372 · root-project/root · GitHub

Hi,

In my opinion, the behaviour observed for the first TGraphErrors, with the error bars drawn inwards, is a very good and convenient feature, whether it was added on purpose or not. Maybe it would be best to propagate this behaviour to all TGraphErrors drawn after the first one instead of suppressing it?

Cheers,
Tristan

It seems to me that error bars being drawn inwards is not a desired feature. The scenario where the marker is larger than the error bars wasn’t considered in the TGraphPainter code. The meaning of such “inward error bars” is confusing. In your example, you used solid markers, and depending on whether the axes are present, the markers are drawn either before or after the error bars. That’s why, in your first plot, the error bars aren’t visible on the blue marker. In my additional examples, I used hollow markers, and we can clearly see that, in case of markers larger than the errors, the error bars are drawn inwards in all cases (with or without predefined axes).

Drawing the error bars inward inside the marker, makes the plot confusing, as error bars are typically meant to represent uncertainty or variation, and drawing them inward could distort this interpretation.

The PR is merged. Do not draw error bars when they are smaller than the marker. by couet · Pull Request #16372 · root-project/root · GitHub