Note5 :数据拟合
今天还是关于TH1和TF1的内容,使用Fit方法,使用不同的函数对数据进行拟合。下面以问题的形式做个小的总结记录。
Section 1
目标: Read histogram “\h1” from file “\hists.root” that I give you. And Draw it.
- 读取一个.root文件:
基于TFile类,有这样几种方法:
TFile f("file.root");
TFile* f = new TFile("file.root");
TFile* f = TFile::Open("file.root");
- 将文件中的直方图取出来
TFile::Get()方法可以提取文件中的项目,前面括号的内容可以规定格式,还可以完成允许的格式转换。
- 画图(简单拟合)
就用Fit方法就可以,很简单。有一些常用的格式可以直接用,比如:
h->Fit("gaus");
h->Fit("expo");
整个过程如下:
TFile * file = TFile::Open("hists.root"); // Load file given
TH1D * h1 = (TH1D*)file->Get("h1");
TF1 * f1 = new TF1("f1","gaus",0,100); // Use TF1 to fit
h1->Fit(f1);
TCanvas * c1 = new TCanvas();
h1->Draw();
c1->Draw();
会有这样的拟合结果出来,有
和
的值、误差、一阶导数等信息。
FCN=75.7525 FROM MIGRAD STATUS=CONVERGED 67 CALLS 68 TOTAL
EDM=4.32103e-09 STRATEGY= 1 ERROR MATRIX ACCURATE
EXT PARAMETER STEP FIRST
NO. NAME VALUE ERROR SIZE DERIVATIVE
1 Constant 3.98366e+01 1.69178e+00 5.60562e-03 3.37524e-05
2 Mean 4.94769e+01 3.13950e-01 1.32816e-03 -2.62125e-04
3 Sigma 9.29006e+00 2.57773e-01 2.91662e-05 2.17782e-03
Section 2
目标: Same to Exercise 1, but read histogram “\h2” from file ”\hists.root“, and fit it with an exponential function.
这次使用了带参数的TF1作拟合,与section1中的稍有不同,但没有本质差别。
TH1D * h2 = (TH1D*)file->Get("h2");
TF1 * f2 = new TF1("f2","[0]*exp([1]+[2]*x)",0,100);
h2->Fit(f2); // 拟合结束之后,会直接将图象记录在直方图中
TCanvas * c2 = new TCanvas();
h2->Draw();
c2->Draw();
FCN=57.8513 FROM HESSE STATUS=NOT POSDEF 16 CALLS 219 TOTAL
EDM=1.59512e-07 STRATEGY= 1 ERR MATRIX NOT POS-DEF
EXT PARAMETER APPROXIMATE STEP FIRST
NO. NAME VALUE ERROR SIZE DERIVATIVE
1 p0 7.63153e+00 3.40960e+00 1.86116e-04 -1.24184e-03
2 p1 2.18370e+00 4.46787e-01 2.43901e-05 -9.47712e-03
3 p2 -7.13006e-02 2.68137e-03 1.34260e-06 4.84167e-02
Section 3
目标:
- Same to Exercise 1, but read histogram “\h3” from file “\hists.root"
- Make a composed function of the two function you draw in Exercise 1 and 2, and fit it to the histogram “\h3".
- From the fit, you should be able to measure the mean (µ) and the width (σ) of the signal peak. And print out the results.
实验上的数据,往往是由本底和信号两部分组成的。这两者的概率分布情况总是不同。因此,就需要用复合的函数进行拟合。
实际上变化也不大:要么直接定义这样的一个复合函数,要么先定义两个函数,再将他们整和到一个TF1中。
值得注意的是: 在拟合之前,函数参数的初始化是必要的,而且初始化的值、以及是否设置约束,对拟合的结果都有不小的影响。因此,拟合是个有些玄学的事,观察数据,给定一组合适的初始值以及约束,才能顺利的拟合出来。有的时候,数据量的缺少也会让拟合结果十分离谱。
添加约束使用SetParLimits()方法,第一个参数是参数的序号,后面是上下限。这个也不是很难
TH1D * h3 = (TH1D*)file->Get("h3");
TF1 * f3 = new TF1("f3","[0]*exp([1]+[2]*x)+[3]*TMath::Gaus(x,[4],[5])",90,150);
f3->SetParameters(100,1,-0.1,100,125,5,6); //100,1,-0.1,,125
f3->SetParLimits(4,50,130);
f3->SetParLimits(5,1,10);
h3->Fit(f3);
TCanvas * c3 = new TCanvas();
h3->Draw();
c3->Draw();
FCN=36.5204 FROM HESSE STATUS=NOT POSDEF 40 CALLS 1112 TOTAL
EDM=7.05757e-07 STRATEGY= 1 ERR MATRIX NOT POS-DEF
EXT PARAMETER APPROXIMATE STEP FIRST
NO. NAME VALUE ERROR SIZE DERIVATIVE
1 p0 1.69717e+01 1.59509e+00 7.34583e-05 9.23455e-03
2 p1 5.87786e+00 9.39849e-02 4.32764e-06 1.56726e-01
3 p2 -2.51793e-02 4.03518e-04 3.80634e-08 1.78659e+01
4 p3 2.00010e+02 1.80736e+01 9.07347e-03 4.20113e-06
5 p4 1.25056e+02 1.02996e-01 3.19930e-06 3.84786e-02
6 p5 1.02594e+00 8.81243e-02 9.26399e-05 2.29845e-03
看起来很正常的一幅图,其实调参调了一段时间。