Fit drawing bug with Logx?

Hello Folks,

I fit a function to a TGraph, before I have a pad. Eventually, when I draw the graph, I set Logx on the pad.

If I do the obvious (at least to me, greatly simplified, see attachment for working example):

g->Fit(f1, "R"); // Make a canvas and draw new TCanvas(); gPad->SetLogx(); g->Draw("AP");
This produces the middle plot in the attached figure.
The axis range is incorrect (only three decades, not 6). (I need the “R” option because my function is ill-behaved at 0, so I’ve set the range appropriately.)

Thinking the fit is caching the underlying histogram, I tried:

g->Fit(f1, "R"); g->GetFunction(f1->GetName())->Update(); // Make a canvas and draw...
(Update() deletes the histogram.) I get the same (bad) behavior (right plot).

The only recipe I’ve come up with which produces the correct plot (on the left) is

g->Fit(f1, "RN"); // don't attach fit to graph g->GetListOfFunctions()->Add(f1); // add it by hand // Make a canvas and draw...

Is this a bug? Am I doing something outré?

Complete example macro, data file, and png of canvas are attached.

DrawFitBug.cpp (3.62 KB) (2.96 KB)

The way to bypass the problem is to set the log scale before doing the fit:

TGraphErrors *
DrawFitBug (const char * dataf = "")
  // Illustrate odd behavour of fits when drawing w/ or w/o Logx

  TCanvas *c1 = new TCanvas("DrawFitBug", "DrawFitBug", 1200, 400);

  TGraphErrors *g1 = ReadGraphData(dataf);

  // my eyes must be going bad

  // make sure we ask for fit statistics, to see that we can get them
  gStyle->SetOptFit(1);     // default: Chisquare/DoF, parameter names, values,>

  //  Create the graphs and fit them ___
  //  *before* we have a canvas/pad

  //  Correct plot:
  TF1 *f1 = NewFitFunction("Fit(\"RN\"), Add");   

  g1->Fit(f1, "R");       

  //  Obvious, but incorrect plot
  TF1 *f2 = NewFitFunction("Fit(\"R\")");   
  TGraphErrors *g2 = new TGraphErrors(*g1);
  g2->Fit(f2, "R");  // do the fit, attaching to graph   
  //  Should fix the error, but doesn't
  TF1 *f3 = NewFitFunction("Fit(\"R\"), Update()");   
  TGraphErrors *g3 = new TGraphErrors(*g1);   
  g3->Fit(f3, "R");  // do the fit, attaching to graph   

  // Now we make a pad and draw ________
  c1->cd(2);  gPad->SetLogx();  g2->Draw("AP");   
  c1->cd(3);  gPad->SetLogx();  g3->Draw("AP");   

  return g1;

I’ll try that out, but I think it will create other problems, in my case:
[ul][li] There may not be a canvas/pad yet. I thought gPad was null in this case?[/li]
[li] The current pad may not be mine. I can be called to do a fit in order to get the fit parameters after some one else has created a canvas and drawn. I don’t want to change the log setting on their pad, just to do my fit.[/li][/ul]

This is clearly a bug in the graph painting function and it will be fixed by Olivier. What happens is the following:
g2->Fit draws the graph in linear scale. The best scale computed for the graph is [0,1e6]. When setting the logx scale, the already existing histogram with x axis starting at 0 is used. The graph painting routine finds 0 for the minimum and resets it to xmax/1000. It should set it to the decade such that the first graph point is included

Thanks for the explanation. I look forward to the fix.


Yes that’s what Lorenzo and I found out. That needs do be fixed (carefully to avoid side effects). I gave the workaround just to help temporarelly but my intention was to fix it.

Now fixed in the SVN trunk.

Thanks for the update. I won’t get a chance to try it until tomorrow at the earliest. I do appreciate your effort to fix this promptly.


Boy, that was a long tomorrow…

Finally had a chance to build my code against root from svn. Your patch works for me.

Thanks for the fix.

Now, onto the next issue…(I’ll start a new thread)