Home | News | Documentation | Download

ROOT Fit function initially set to zero


ROOT Version: 6.18 for centos7
Platform: Not Provided
Compiler: g++


Hi there, ROOT community.
I have tried to do some training with ROOT fit functionality, described in chapter 5 of Users Guide https://root.cern.ch/root/htmldoc/guides/users-guide/ROOTUsersGuide.html#example-of-fit-combining-functions . And I got stuck on 5.4 example.
I have written all stuff in .cpp file, it compiled fine, and produced output Canvas with points scattered and with fitting function == 0.

My code is as follows:

Blockquote
#include<TF1.h>
#include<TCanvas.h>
#include<TMath.h>
#include<TH1D.h>

Double_t Background(Double_t* x, Double_t* par){ //fit requires x to be pointer for some reason
return par[0]+par[1]*(x)+par[2](x)(*x);
}

Double_t LorentzianPeak(Double_t* x, Double_t* par){
return ((par[0]par[1])/(2TMath::Pi()))/((par[3]-(x))(par[3]-(*x))+ par[1]*par[1]/4.0);
}

Double_t FittingCurve(Double_t* x, Double_t* par){
return Background(x,par)+LorentzianPeak(x,par+3);
}

int main(){
TCanvas* C = new TCanvas(“Canvas”, “Canvas”,1);
//our task - Fit the LorentzianPeak ~1/(x^2+a^2) with quadratic background a+bx+cx^2 - six parameters altogether
/auto Background = [](Double_t x, Double_t* par){return par[0]+par[1]x[0]+par[2]x[0]x[0];};//background fitting curve
auto LorentzianPeak = [](Double_t
x, Double_t
par){
return ((par[0]par[1])/(2TMath::Pi()))/((par[3]-x[0])
(par[3]-x[0])+ par[1]par[1]/4.0);//Lorentzian Peak’s one
};
auto FittingCurve = [&Background, &LorentzianPeak](Double_t
x, Double_t* par){
return Background(x, par) + LorentzianPeak(x,par+3); //first three parameters refers to Background, three others refers to LoretzianPeak, pointer algebra helps to workaround it
};/
//Let’s make this tash with use of histogram. Firstly, let’s fill this with some data, which correspond to such peak
const Int_t Nbins = 60;
Double_t data[Nbins] =
{6, 1,10,12, 6,13,23,22,15,21,
23,26,36,25,27,35,40,44,66,81,
75,57,48,45,46,41,35,36,53,32,
40,37,38,31,36,44,42,37,32,32,
43,44,35,33,33,39,29,41,32,44,
26,39,29,35,32,21,21,15,25,15};
TH1D
hist = new TH1D(“hist”,“Lorentzian Peak Fit on quadratic background”,60,0,3);//range [0,3]
for(Int_t i=0;i<Nbins; ++i){
hist->SetBinContent(i+1,data[i]);
hist->SetBinError(i+1,TMath::Sqrt(data[i]));
}//Fills histogram with points
TF1* FittingCurve_tf = new TF1(“fit”,FittingCurve,0,3,6); //6 denotes number of parametets
//FittingCurve_tf->SetParameters(1,1,-1,20,1,1);
hist->Fit(“fit”);
C->SaveAs(“temp.pdf”);
delete C, hist, FittingCurve_tf;
}

Blockquote

You may compare it to those one suggested in the user guide. And here is the result:

  1. Even if I change initial parameters set, they seemingly do not change under Fit function. Why is that?
  2. I firstly tried to make all stuff using lambdas, bud did not succeeded (got many non-easy errors). Maybe there is working example you could provide?

I would be very grateful for any suggests.

I guess @moneta can help you.

Should I ask him personally or he will be informed?

The fact I mentioned him in my previous post. informs him automatically.

UPD: I digged further and 1st question vanished partially : parameters changes actually, and they do in seemingly reasonable way (but read further). It is mentioned in the user guide that parameters initially set to 1 though in my case they are set to 0 (maybe it is my version’s feature?). So I decided to set them to 1 manually - it did not help much - my Lorentzian Peak is still as bad as possible.


So the 1st question become this : Is the solution to example 5.4 described properly? Or it’s my version feature and the example actually works on another one?

Thanks

Hi,
I am not sure exactly which code you are using for this example. You can find however a running version of this example in the tutorial tutorials/fit/FittingDemo.C, that is also available here:
https://root.cern.ch/doc/master/FittingDemo_8C.html

As shown in the example, you need to set good initial parameter value for the functions. Values of 1’s are not good for the Peak function and you need better values (e.g. 0.2 for the width and 1 for the peak position)

Lorenzo

Dear Lorenzo,
Thank you for clarification. The link you attached helped me to understand that everything works as I would expect, but the code for this example presented in the user guide confused me a bit with commentaries provided there.


It is mentioned in the 5.4 example commentaries that all parameters for fit function is 1 by default. But as far as I can see, they are 0 by default?

So I got fit function equal to zero and interpreted it like an error, since I expected nonzero one.

If I got it right, I suggest a correction.

Anyway, your answer is very helpful, thank you!

And, returning to my 2nd question, could you please provide fit example with use of lambdas? I tried seemingly in the same way as with normal functions but I’ve got tonn of errors which I do not understand.

Hi,

You are right! This is wrong what is written in the Users Guide, maybe working for very old versions of ROOT. The Users guide refers anyway to old ROOT version, 5.34 , and we are phasing it out. Reference online guide, complemented with tutorials should instead serve as documentation.

For using lambda, here is an example code:

auto histo = new TH1D("h1","h1",100,-5,5);
histo->FillRandom("gaus"); 
auto myfunc = [](double *x, double *p){ return p[0]*ROOT::Math::normal_pdf(x[0], p[2],p[1]); }
auto f1 = new TF1("f1",myfunc, -5, 5,3); 
// we need to set initial parameter values
f1->SetParameters(1,0,1);
histo->Fit(f1); 

Note that lambda can also capture objects and be available inside the lambda function. In that case you should make sure that when the lambda is used those objects are alive.
If you are having still issues creating a fitting function with the lambda, please let me know

Best regards

Lorenzo

1 Like