Trouble with fit function

Hello,

I am new to coding and root. I am learning how to use root for a summer program and I have ran into a problem I do not understand. Below I have copied my code. (when I tried uploading a message told me new users cannot post links)

My goal: I want to make a program that will go through ever fit option root offers and find the fit option that has the lowest chi2 value. Then, I want to graph the option with the best fit.

My problem: I am not sure how to graph with the best fit, unless the best fit is the last option. For some reason, if I remove the gaus option from the array of const char*, no graph is created. Also, the position of where the gaus option is in that array changes the resulting graph.

My thoughts: I believe this has something to do with the hist->Fit(bestfit); part of my code, as I am not sure I fully grasp what this is doing yet. Any comments would be awesome!

Cheers

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// chi2 analysis for many fits
void analysis1()
{

TH1F *hist = new TH1F("hist", "histogram", 100, 0, 10);

TRandom *rand = new TRandom2(50);

fstream file;
file.open("data.txt", ios::out);

for (int i = 0; i < 1e4; i++)
{
	double r = rand->Gaus(5,1);
	//cout << r << endl;
	file << r << endl;;
}

file.close();

file.open("data.txt", ios::in);

double value;

while(1)
{
	file >> value;
	hist->Fill(value);
	if(file.eof()) break;
}

file.close();

hist->GetXaxis()->SetTitle("Distrobution");
hist->GetYaxis()->SetTitle("Entries");

const char* fit_arr[23] = { "expo", "pol0", "pol1", "pol2", "pol3", "pol4", "pol5", "pol6", "pol7", "pol8", "pol9", "cheb0", "cheb1", "cheb2", "cheb3", "cheb4", "cheb5", "cheb6", "cheb7", "cheb8", "cheb9" ,"gausn" ,"gaus" };

TF1 *fit[23];
double min = 1e100;
const char* bestfit = "No fit";
int improvements = 0;

for (int j = 0; j < 23; j++) 
{
    	fit[j] = new TF1(fit_arr[j], fit_arr[j], 0, 10);
    	hist->Fit(fit_arr[j]);
    	double chi2 = fit[j]->GetChisquare();
    	if(min > chi2) 
    	{
    		min = chi2;
    		bestfit = fit_arr[j];
    		improvements++;
    		cout << "\n" <<

β€œ\033[1;31m&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\033[0m\n” << β€œ\033[1;31m&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\033[0m\n” << β€œ\033[1;31m&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&\033[0m\n” <<
β€œ\033[1;31m&&&&&&&&&&&&&&&&&&&&& chi2 was improved! &&&&&&&&&&&&&&&&&&&&&\033[0m\n” << β€œ\033[1;31m&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&\033[0m\n” <<
β€œ\033[1;31m&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\033[0m\n” <<
β€œ\033[1;31m&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\033[0m\n” << endl;
}
}
//TF1 *fit = new TF1(β€œpol5”, β€œpol5”, 0, 10);

//hist->Fit("pol5");

//double chi2 = fit->GetChisquare();
//cout << chi2 << endl;

cout << 
"\n" << 
"\033[1;31mmin_chi2: \033[0m"<< min << "\n" <<
"\033[1;31mbestfit: \033[0m" << bestfit << "\n" << 
"\033[1;31mimprovements: \033[0m" << improvements << "\n" 
<< "\n" << endl;

hist->Fit(bestfit);
TCanvas *c1 = new TCanvas();
hist->Draw();

}

Welcome to the ROOT forum.

You can try to add the option "0"

hist->Fit(fit_arr[j],"0"); 

to fit without drawing. Here there is the documentation for the fit option.

Then in your last part of your code try to change the order like this.

TCanvas *c1 = new TCanvas();
hist->Draw();
hist->Fit(bestfit);

Regarding the position of the gaussian affecting the fit:
since your functions have the same name of the default ROOT fit functions this could maybe create some conflicts and affects the default starting parameters for the fit. But let’s wait someone who is more expert than me.

PS
In general looking at the chi2 while increasing the order of the polynomial could not be the best idea if you do not have a stopping criteria. Since the larger is the number of free parameters the better is the fit

PPS
Using Chebyshev polynomials or standard polynomials should not affect the resulting function or chi2.

1 Like

Hi,

I am not sure of the utility of the approach you are using, since trying to fit an histogram with just some pre-defined functions is quite arbitrary. You can also combined those functions to have an infinity variety of functions to fit.
It makes more sense to fit different polynomial degrees, or a single gaussian vs the sum of 2 or more gaussians, etc…

This is however not your problem. If you are fitting multiple functions to an histogram and you want to display all of them you should use the fit option +, for example by doing:

h->Fit("gaus","+");
h->Fit("expo","+");

you will have a plot with both the Gaussian and the exponential fitted function.
Otherwise if you want a plot with just the best fit, you can do as you are doing in the code, or fit with option β€œ0”, save the function pointer when you find the best function and drawing it again afterwards or just add yourself in the histogram function list by calling
hist->GetListOfFunctions()->Add(best fit_function_ptr)

Cheers

Lorenzo

1 Like