13 #include <TFitResult.h>
17 static const float feps = numeric_limits<float>::epsilon();
18 static const double deps = numeric_limits<double>::epsilon();
19 static const double dmax = numeric_limits<double>::max();
23 inline double identity (
double x) {
return x; };
31 template<const
size_t n>
struct Term {
32 static double Eval (
const double x)
34 const size_t m = n-1, k = n-2;
38 template<>
struct Term<1> {
39 static double Eval (
double x) {
return x; }
41 template<>
struct Term<0> {
42 static double Eval (
double x) {
return 1.; }
48 static double Eval (
double x,
const double p[])
55 static double Eval (
double x,
const double p[]) {
return p[0]; }
60 template<const
size_t maxnPt, const
size_t nPt, const
size_t nY>
struct Polynom2D {
61 static double Eval (
double xPt,
double xY,
const double p[])
63 const size_t kY = nY-1;
64 const double * pPt =
p + nY * maxnPt *
sizeof(double);
70 template<const
size_t maxnPt, const
size_t nPt>
struct Polynom2D<maxnPt,nPt,0> {
71 static double Eval (
double xPt,
double xY,
const double p[])
84 template<const
size_t d,
double (*Log)(
double) = log,
double (*Exp)(
double) = exp>
91 maxdegree(d), npars(d+1), m(Log(mi)), M(Log(Ma))
93 static_assert(d > 1,
"degree must be greater than 1");
96 double operator() (
const double * x,
const double *
p)
98 double nx = -1 + 2* (Log(x[0]) - m) / (M - m);
100 double result = Exp(chebyshev);
110 template<
double (*Log)(
double) = log,
double (*Exp)(
double) = exp>
121 Greta (
int d,
double mi,
double Ma) :
122 degree(d), npars(d+1), m(mi), M(Ma)
127 static double T (
double x,
int i)
129 if (i == 0)
return 1.;
130 if (i == 1)
return x;
131 return 2*x*T(x, i-1)-T(x, i-2);
134 static const char *
T (
const char * x,
int i)
136 if (i == 0)
return Form(
"1.");
137 if (i == 1)
return x;
138 const char * t1 = T(x, i-1), * t2 = T(x, i-2);
139 return Form(
"2*%s*%s-%s", x, t1, t2);
144 return -1 + 2* (Log(*x) - Log(m)) / (Log(M) - Log(m));
147 double operator() (
const double *x,
const double *
p)
const
149 double nx = normalise(x);
151 for (
int i = 0; i <= degree; ++i)
152 result +=
p[i]*T(nx,i);
157 static const char *
formula (
double mi,
double Ma,
int deg)
159 TString result =
"[2]";
160 TString nx =
"(-1+2*(log(x)-log([0]))/(log([1])-log([0])))";
161 for (
int i = 1; i <= deg; ++i)
162 result += Form(
"+[%d]*%s", i+2, T(nx, i));
163 result =
"exp(" + result +
")";
164 return result.Data();
169 return formula(m, M, degree);
176 template<
double (*Log)(
double) = log,
double (*Exp)(
double) = exp>
182 p(pars), g(Npars-1, m, M) { }
183 double operator() (
double x)
const {
198 template<
double (*Log)(
double) = log,
double (*Exp)(
double) = exp>
202 vector<GretaPolynomial<Log,Exp>>
pols;
207 cout <<
"Reading " <<
fname << endl;
213 cerr <<
"Failure at opening the file " <<
fname <<
'\n';
223 double * pars =
new double[Npars];
224 for (
int i = 0; i < Npars; ++i) infile >> pars[i];
229 if (ymins.size() == 0) { assert(abs(ymin) < deps); }
230 else { assert(ymin > ymins.back()); }
231 ymins.push_back(
ymin);
237 cout << std::setw(3) <<
ymin
238 << std::setw(8) << (int)
ptmin
239 << std::setw(8) << (int)
ptmax
240 << std::setw(3) << Npars;
241 for (
int j = 0; j < Npars; ++j) std::cout << std::setw(15) << pars[j];
246 assert(ymins.size() > 0);
247 assert(ymins.size() == pols.size());
252 double operator() (
double pt,
double y)
255 size_t iy = ymins.size();
257 while (ymins.at(iy) > y);
258 auto& g = pols.at(iy);
265 template<const
size_t d>
271 const char *
options =
"Q0SNRE",
272 bool autoStop =
false)
275 assert(ifM <= h->GetNbinsX());
276 assert(h->GetDimension() == 1);
278 double contentfm = h->GetBinContent(ifm),
279 contentfM = h->GetBinContent(ifM);
281 double m = h->GetBinLowEdge(ifm), M = h->GetBinLowEdge(ifM+1);
283 cout <<
"From bin " << ifm <<
" (m = " << m <<
", content = " << contentfm <<
")"
284 <<
" to bin " << ifM <<
" (M = " << M <<
", content = " << contentfM <<
")" << endl;
286 if (abs(contentfm) <=
deps || abs(contentfM) <=
deps) {
287 cerr <<
"Fit cannot start with empty bins\n";
292 double errorfm = h->GetBinError(ifm),
293 errorfM = h->GetBinError(ifM);
295 if (abs(errorfm) <=
deps || abs(errorfM) <=
deps) {
296 cerr <<
"There must be uncertainties for the fit\n";
301 double fm = log(contentfm),
306 static int iname = 0; ++iname;
309 const size_t maxdegree = greta.
maxdegree;
310 TF1 *
f =
new TF1(Form(
"greta%d", iname), greta, m, M, greta.
npars);
313 f->SetParameter(0,(fM+fm)/2);
314 f->SetParameter(1,(fM-fm)/2);
315 for (
size_t degree = 2; degree <= maxdegree; ++degree)
316 f->FixParameter(degree,0);
318 auto dump = [
f](
int degree) {
319 cout <<
"parameters:\t";
320 for (
int i = 0; i <= degree; ++i) cout <<
f->GetParameter(i) <<
' ';
325 for (
size_t degree = 2; degree <= maxdegree; ++degree) {
328 f->ReleaseParameter(degree);
330 TFitResultPtr r = h->Fit(
f,
options);
332 double chi2 = r->Chi2();
333 if (!isnormal(chi2)) {
335 cerr <<
"Fit aborted (chi2 = " << chi2 <<
")\n";
338 double ndf = r->Ndf();
340 int status = r->Status();
343 cerr <<
"Fit aborted (status = " << status <<
")\n";
349 error = sqrt(2./ndf);
350 cout <<
"\e[1m" << degree <<
' ' << status <<
'\t' << chi2 <<
' ' << ndf <<
'\t' << x2n <<
"\u00B1" << error <<
"\e[0m" << endl;
353 if (autoStop && x2n > lastx2n) {
354 cerr <<
"Chi2/ndf has increased -- stepping back and stopping!\n";
355 f->FixParameter(degree,0);
360 if (abs(x2n-1) <= nSigmaStop*error)
break;
367 template<const
size_t d>
373 const char *
options =
"Q0SNRE",
374 bool autoStop =
false)
378 int ifm = h->FindBin(m+
feps),
379 ifM = h->FindBin(M-
feps);
380 cout <<
"Axis interval (" << m <<
',' << M <<
") to bin interval (" << ifm <<
',' << ifM <<
')' << endl;
384 return GetSmoothFit<d>(h, ifm, ifM, nSigmaStop,
options, autoStop);