Automatic histogram bins and fit

Dear Rooters,

Fitting some functions to histograms I come across some strange behaviour, when the binning of the histogram is automatically set by root. Here a small example reproducing the problem:

from ROOT import TCanvas,TH1D,TRandom2
h1 = TH1D('h1','',4,0,0)
#h1 = TH1D('h1','',4,-2,2) #use this instead to make it work
#just something to put into the histogram:
rg = TRandom2()
for i in range(100):
  h1.Fill(rg.Gaus(0,1))
c1 = TCanvas('c1','',600,600)
h1.Draw()

h1.Fit('gaus')
f = h1.FindObject('gaus')
#printing the reference:
for i in range (10):
  print f
  1. The fit is not drawn
  2. The TF1 Object from h1.FindObject(…) seems to be lost during the running program. Printing the reference sometimes results in ‘none’. (Perhaps the script has to be rerun a few times, to reproduce this)

Regards,

Stefan

Stefan,

not during the running program, but during the line update which updates the canvases, and the deletion comes from the C++ side (to verify, simply call c1.Update() and see that that is what makes f disappear).

Seems to me that the failure of the fit (look at the first derivative of Sigma) is the cause for the C++ side to not draw and subsequently delete the fit function. Make the histo symmetric, or add some more entries so that the fit succeeds, and f will remain even after a canvas update.

Cheers,
Wim

Dear Wim,

I am not sure that this has to do with the outcome of the fit. I have tried to modify the script to point the problem

from ROOT import TCanvas,TH1D,TRandom2
h1 = TH1D('h1','',10,0,0)
rg = TRandom2()
for i in range(1000):
  h1.Fill(rg.Uniform(0,1))
h1.Draw() #comment out to not loose the fit
h1.Fit('pol0','0')
f = h1.FindObject('pol0')
for i in range (100):
    print 'What is f? :',f

In this case always the automatic binning is used. When the Histogram in not drawn, the fit function can be accessed and the fit runs stable. However, if the script is like above, once in a while the object f is lost during the further processing of the script. Then the outcome looks like:

Minimizer is Linear
Chi2 = 5.87539
NDf = 9
p0 = 99.4125 +/- 3.15297
What is f? : <ROOT.TF1 object (“pol0”) at 0x9708530>
What is f? : <ROOT.TF1 object (“pol0”) at 0x9708530>
What is f? : None
What is f? : None
What is f? : None

Here the TF1 object was there in the beginning of the loop but then it was lost…

Stefan,

yes, and it is still exactly as I described above: the function gets deleted (in case of fit failure) on TCanvas::Update().

If you don’t draw the histogram, there is no canvas, hence no canvas update => fit function stays alive.

If you do draw the histogram, there is a canvas, hence a canvas update => fit function gets deleted.

The deletion can happen in the middle of a loop if the loop is long enough (see for what long is sys.getcheckinterval()), as there is a separate thread running to update graphics objects. If the loop is long enough for a thread switch in between, the canvas gets updated somewhere in the loop.

Either which way, it is still the C++ side where the fit function is being lost, not the python side or due to python ref counting (in that case, f would be gone rather than being reset to PyROOT_NoneType). There’s an option to fit “+” that is supposed to keep the fit function alive, but that does not appear to help here, which again leads me to conclude that the cause is fit failure.

Cheers,
Wim

Dear Wim,

ok, I see that the fit might get lost. However,

is strange because in both cases - with and without the automatic binning - the fit seems to work even giving the same result.

So using:

h1 = TH1D('h1','',10,0,1)

in the beginning instead leads to:

Minimizer is Linear
Chi2 = 5.87539
NDf = 9
p0 = 99.4125 +/- 3.15297
What is f? : <ROOT.TF1 object (“pol0”) at 0xac65398>

So I have checked that the problem also occurs on the c++ side:

{
  TH1D* h1 = new TH1D("h1","",10,0,0);
  //TH1D* h1 = new TH1D("h1","",10,0,1); //same fit result, different behaviour in drawing
  TRandom2* rg = new TRandom2();
  for (int i=0;i<1000;i++){
    h1->Fill(rg->Uniform(0,1));
  }
  h1->Draw();
  h1->Fit("pol0","0+");
  TF1* f = (TF1*)h1->FindObject("pol0");
  for (int i=0;i<100;i++){
      cout<<"What is f? :"<<f->GetParameter(0)<<endl;
  }
  f->Draw("same");
}

So here as well the automatic binning results in different behaviour of how the things are drawn. So perhaps the whole discussion should go over to the c++ side. Or is this an intended behaviour?

Regards,

Stefan

Hi,

Indeed this is a problem. Can you please submit this as a bug report on savannah?

Thanks,
Philippe.

Stefan,

yes, maybe better to open a topic on ROOT Support … this is beyond my knowledge.

Cheers,
Wim

I have forwarded the discussion to the ROOT support section:
[url]Automatic histogram bins and fit

Stefan