TH1::Fit draw mutliple fits on the same canvas and get the parameters


Running on lxplus7


Dear co-rooters,

I am trying to perform multiple fits on a histogram, in different ranges using the same fitting function.
I would like to store the parameters in each fit as well as to draw the functions.

My code to do the above is below

#include "TCanvas.h"
#include "TStyle.h"
#include "TFile.h"
#include "TH1.h"

void fit(){

// (1) Store the movie in arrays

        // The file can be found in https://cernbox.cern.ch/index.php/s/3XnsnbWYg2obDtD
	TFile *fin = new TFile("fit.root", "OPEN");
	TH1D *h = (TH1D*) fin->Get("histo_movie");								

	gStyle->SetOptStat(0);
	TCanvas *canvas = new TCanvas("canvas", "HPGe", 500, 500);
	canvas->Divide(1, 2);	
	
	// Pad 1
	canvas->cd(1);	
	h->Draw("histo ][");	
	
	h->Fit("pol1", "WCFQ", "HIST ][ SAME", 5.6005e6, 5.6021e6);
	h->GetFunction("pol1")->Draw("SAME");	
	cout << "The [0] parameter is : " << h->GetFunction("pol1")->GetParameter(0) << endl;
	
	h->Fit("pol1", "WCFQ", "HIST ][ SAME", 5.60235e6, 5.60393e6);
	h->GetFunction("pol1")->Draw("SAME");	
	cout << "The [0] parameter is : " << h->GetFunction("pol1")->GetParameter(0) << endl;
	
	//Pad 2
	canvas->cd(2);
	h->Draw("histo ][");

}

With this code I can get the parameters, however only the second function is drawn.

I tried to use the + option but then only the first function is drawn and only the parameters of the first fit are kept.

One idea could be to clone the histogram and do the fit on the cloned, but this procedure eventually will involve hundreds of fits on big histograms, so I don’t think that this is an option.

Any idea on how to do it?

Thanks in advance!

h->GetListOfFunctions()->ls();
h->GetListOfFunctions()->Print();

Thanks for your reply!

I still don’t know how to plot the functions and get their parameters.

What I get is the following

OBJ: TList	TList	Doubly linked list : 0
 OBJ: TF1	pol1	pol1 : 0 at: 0x1f34cf0
Collection name='TList', class='TList', size=1
 Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 301 
 Formula expression: 
	([p0]+[p1]*x)

I modified the code as follows

// Pad 1
canvas->cd(1);	
h->Draw("histo ][");	
//h->TH1::Fit("pol1", "WCQF", "C SAME", 5.6005e6, 5.6021e6);
	
h->Fit("pol1", "WCFQ", "HIST ][ SAME", 5.6005e6, 5.6021e6);
h->GetFunction("pol1")->Draw("SAME");	
cout << "The [0] parameter is : " << h->GetFunction("pol1")->GetParameter(0) << endl;

h->Fit("pol1", "WCFQ", "HIST ][ SAME", 5.60235e6, 5.60393e6);
h->GetFunction("pol1")->Draw("SAME");	
cout << "The [0] parameter is : " << h->GetFunction("pol1")->GetParameter(0) << endl;

h->GetListOfFunctions()->ls();
h->GetListOfFunctions()->Print();

And this only prints the last function which is the one that is draw. If I add the + option to the fits

h->Fit("pol1", "WCFQ+", "HIST ][ SAME", 5.6005e6, 5.6021e6);
h->Fit("pol1", "WCFQ+", "HIST ][ SAME", 5.60235e6, 5.60393e6);

then only the first function is drawn and the printed output is the following

The [0] parameter is : -449770
The [0] parameter is : -449770
OBJ: TList	TList	Doubly linked list : 0
 OBJ: TF1	pol1	pol1 : 0 at: 0x2e859e0
 OBJ: TF1	pol1	pol1 : 0 at: 0x2c54590
 OBJ: TF1	pol1	pol1 : 0 at: 0x32af610
Collection name='TList', class='TList', size=3
 Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 0 
 Formula expression: 
	([p0]+[p1]*x) 
 Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 301 
 Formula expression: 
	([p0]+[p1]*x) 
 Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 301 
 Formula expression: 
	([p0]+[p1]*x)

so only parameters associated with the first fit are kept.

Any idea on what am I doing wrong?

h->GetListOfFunctions()->At(0)->Print();
h->GetListOfFunctions()->At(1)->Print();
h->GetListOfFunctions()->At(2)->Print();

I am sorry for my ignorance, but I still don’t understand how to use that. I modified the code as shown

	h->Fit("pol1", "WCFQ+", "HIST ][ SAME", 5.6005e6, 5.6021e6);
	h->GetFunction("pol1")->Draw("SAME");	
	cout << "The [0] parameter is : " << h->GetFunction("pol1")->GetParameter(0) << endl;
	
	h->Fit("pol1", "WCFQ+", "HIST ][ SAME", 5.60235e6, 5.60393e6);
	h->GetFunction("pol1")->Draw("SAME");	
	cout << "The [0] parameter is : " << h->GetFunction("pol1")->GetParameter(0) << endl;
	
	h->GetListOfFunctions()->At(0)->Print();
	h->GetListOfFunctions()->At(1)->Print();
	h->GetListOfFunctions()->At(2)->Print();

and the output is practically the same

The [0] parameter is : -449770
The [0] parameter is : -449770
Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 0 
 Formula expression: 
	([p0]+[p1]*x) 
Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 301 
 Formula expression: 
	([p0]+[p1]*x) 
Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 301 
 Formula expression: 
	([p0]+[p1]*x)

What am I missing?

Try:

((TF1*)(h->GetListOfFunctions()->At(0)))->Print("V");

Thank you very much once again.
I still don’t see how can I draw the functions with that.

The output is

root [0] 
Processing fit.C...
The [0] parameter is : -449770
Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 301 
 Formula expression: 
	([p0]+[p1]*x) 
List of  Variables: 
Var   0                    x =    0.000000 
List of  Parameters: 
Par   0                   p0 =  -449770.399256 
Par   1                   p1 =    0.023981 
Expression passed to Cling:
	#pragma cling optimize(2)
Double_t TFormula____id11347957373624834409(Double_t *x,Double_t *p){ return (p[0]+p[1]*x[0]) ; }
The [0] parameter is : -449770
Formula based function:     pol1 
                 pol1 : pol1 Ndim= 1, Npar= 2, Number= 301 
 Formula expression: 
	([p0]+[p1]*x) 
List of  Variables: 
Var   0                    x =    0.000000 
List of  Parameters: 
Par   0                   p0 =  -449770.399256 
Par   1                   p1 =    0.023981 
Expression passed to Cling:
	#pragma cling optimize(2)
Double_t TFormula____id11347957373624834409(Double_t *x,Double_t *p){ return (p[0]+p[1]*x[0]) ; }

but still the fitting functions are not drawn.

Can you post your root file so we can run your macro ?

Thank you very much for your reply!

The file can be found here
https://cernbox.cern.ch/index.php/s/3XnsnbWYg2obDtD

If I do this:

void fit(){
   TFile *fin = new TFile("fit.root", "OPEN");
   TH1D *h = (TH1D*) fin->Get("histo_movie");
   gStyle->SetOptStat(0);
   TCanvas *canvas = new TCanvas("canvas", "HPGe", 850, 500);
   h->GetXaxis()->SetRange(559605,561085);
   h->Sumw2(kFALSE);
   h->Draw(" ][");
   h->Fit("pol1", "WCFQ+", "same", 5.6005e6, 5.6021e6);
   h->Fit("pol1", "WCFQ+", "same", 5.60235e6, 5.60393e6);
   h->GetListOfFunctions()->ls();
}

I get this plot:

Note that your histogram stored in the root file already contains a pol1 function.

This is strange, because when I do the fits, nothing is plotted.
The only way I managed to do it, it to get the parameters of the poly1 fitting functions and create a new function.

Do you get the same result as me when you run the macro I posted ?

If I execute your macro I get the functions properly plotted!

But what was wrong in my code?

The only difference I see is these two following lines

h->GetXaxis()->SetRange(559605,561085);
h->Sumw2(kFALSE);

but can they cause the fitting functions not to be plotted?

yes I added them on purpose

I guess so!
But I don’t get it!
The magic one is h->Sumw2(kFALSE); ?

It tells the histogram to not store the errors and therefore the histogram is not drawn with errors bars.

Thank you very much for your help!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.