#include <TH1.h>
#include <TF1.h>
#include <TMath.h>
#include <TGraph.h>
#include <TStyle.h>
#include <TLatex.h>
struct Reference
{
static Double_t function(Double_t* x, Double_t* par)
{
const Double_t invSq2Pi = 1. / TMath::Sqrt(TMath::TwoPi());
const Double_t mpShift = -0.22278298;
const Int_t np = 100;
const Double_t sc = 5;
Double_t sum = 0;
Double_t x0 = x[0];
Double_t xi = par[0];
Double_t mpc = par[1] - mpShift * xi;
Double_t area = par[2];
Double_t sigma = par[3];
Double_t xLow = x0 - sc * sigma;
Double_t xUpp = x0 + sc * sigma;
Double_t step = (xUpp - xLow) / np;
for (Int_t i = 1; i <= np/2; i++) {
Double_t x1 = xLow + (i - .5) * step;
Double_t x2 = xUpp - (i - .5) * step;
sum += TMath::Landau(x1, mpc, xi, true) * TMath::Gaus(x0,x1,sigma);
sum += TMath::Landau(x2, mpc, xi, true) * TMath::Gaus(x0,x2,sigma);
}
return area * step * sum * invSq2Pi / sigma;
}
static TF1* fit(TH1* hist,
Double_t* range,
Double_t* guess,
Double_t* lowLimits,
Double_t* uppLimits,
Double_t* params,
Double_t* errors,
Double_t& chi2,
Int_t& ndf)
{
TF1* func = new TF1(Form("func%s", hist->GetName()), &function,
range[0], range[1], 4);
func->SetParameters(guess);
func->SetParNames("#xi", "#Delta_{p}", "C", "#sigma");
for (Int_t i = 0; i < 4; i++)
func->SetParLimits(i, lowLimits[i], uppLimits[i]);
hist->Fit(func, "RB0");
for (Int_t i = 0; i < 4; i++) {
params[i] = func->GetParameter(i);
errors[i] = func->GetParError(i);
}
chi2 = func->GetChisquare();
ndf = func->GetNDF();
return func;
}
static Bool_t search(TF1* f, Double_t start, Double_t step,
Bool_t peak, Double_t& res)
{
const Int_t maxCalls = 10000;
Double_t lOld = -2;
Double_t l = peak ? -1 : -1e300;
Int_t i = 0;
Double_t x = 0;
Double_t cur = start;
while ((i < maxCalls) &&
TMath::Abs(l - lOld) > 1e-6 &&
TMath::Abs(step) > 1e-8) {
i++;
lOld = l;
x = cur + step;
l = f->Eval(x);
if (!peak) l = TMath::Abs(l-res);
// Printf("mode=%d x=%g step=%g l=%g lOld=%g", mode, x, step, l, lOld);
if ((peak && l < lOld) || (!peak && l > lOld))
step = -step/10; // Go the other way in smaller steps
cur += step;
}
if (i >= maxCalls) return false;
res = x;
return true;
}
static Int_t find(TF1* f, Int_t iXi, Int_t iMpc,
Double_t& maxX, Double_t& fwhm)
{
Double_t xi = f->GetParameter(iXi); // params[0];
Double_t mpc = f->GetParameter(iMpc); // params[1];
if (!search(f, mpc-0.1*xi, 0.05 * xi, true, maxX)) return false;
Double_t left = f->Eval(maxX) / 2;
Double_t right = left;
if (!search(f, maxX-.5*xi, xi, false, left)) return false;
if (!search(f, maxX+xi, -xi, false, right)) return false;
fwhm = right - left;
return true;
}
static TH1* histo()
{
Int_t data[100] = {0, 0, 0, 0, 0, 0, 2, 6, 11, 18,
18, 55, 90,141,255,323,454,563,681,737,
821,796,832,720,637,558,519,460,357,291,
279,241,212,153,164,139,106, 95, 91, 76,
80, 80, 59, 58, 51, 30, 49, 23, 35, 28,
23, 22, 27, 27, 24, 20, 16, 17, 14, 20,
12, 12, 13, 10, 17, 7, 6, 12, 6, 12,
4, 9, 9, 10, 3, 4, 5, 2, 4, 1,
5, 5, 1, 7, 1, 6, 3, 3, 3, 4,
5, 4, 4, 2, 2, 7, 2, 4};
TH1D *ret = new TH1D("snr","Signal-to-noise",100,0,100);
for (Int_t i = 0; i < 100; i++) ret->Fill(i, data[i]);
ret->SetFillColor(kRed+1);
ret->SetFillStyle(3001);
ret->SetXTitle("#Delta");
ret->SetDirectory(0);
return ret;
}
static void maxFwhm(TF1* f, Int_t iXi, Int_t iMpc)
{
printf("Find max and FWHM ...");
Double_t maxX = 0;
Double_t fwhm = 0;
if (!find(f, iXi, iMpc, maxX, fwhm))
Printf(" failed");
else {
Printf(" Max: %f FWHM: %f", maxX, fwhm);
Double_t y = f->Eval(maxX);
TGraph* maxG = new TGraph(1);
maxG->SetPoint(0, maxX, y);
maxG->SetMarkerStyle(20);
maxG->SetMarkerColor(kBlue+2);
maxG->Draw("p");
TLatex* maxT = new TLatex(1.2*maxX, y, Form("Max: %f", maxX));
maxT->SetTextAlign(11);
maxT->Draw();
TGraph* fwhmG = new TGraph(2);
fwhmG->SetPoint(0, maxX-fwhm/2, y/2);
fwhmG->SetPoint(1, maxX+fwhm/2, y/2);
fwhmG->SetMarkerStyle(21);
fwhmG->SetMarkerColor(kMagenta+2);
fwhmG->Draw("pl");
TLatex* fwhmT = new TLatex(1.2*(maxX+fwhm/2), y/2,
Form("FWHM: %f", fwhm));
fwhmT->SetTextAlign(11);
fwhmT->Draw();
}
}
static void test()
{
TH1* hist = histo();
Double_t range[] = { .3 * hist->GetMean(), 3 * hist->GetMean() };
Double_t guess[] = { 1.8, 20., 5e4, 3.0 };
Double_t low[] = { 0.5, 5., 1., 0.4 };
Double_t upp[] = { 5.0, 50., 1e6, 5.0 };
Double_t chi2 = 0;
Int_t ndf = 0;
Double_t params[4];
Double_t errors[4];
printf("Fitting ...");
TF1* f = fit(hist, range, guess, low, upp, params, errors, chi2, ndf);
Printf(" done");
f->Print();
printf("Drawing ...");
gStyle->SetOptStat(1111);
gStyle->SetOptFit(111);
hist->Draw();
f->Draw("same");
Printf(" done");
maxFwhm(f, 0, 1);
}
};