00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <TGraphErrors.h>
00011 #include <TF1.h>
00012 #include <TString.h>
00013 #include <TPad.h>
00014 #include <TLegend.h>
00015 #include <Math/ProbFuncMathCore.h>
00016
00017 #include "../../BAT/BCLog.h"
00018 #include "../../BAT/BCDataSet.h"
00019 #include "../../BAT/BCDataPoint.h"
00020 #include "../../BAT/BCMath.h"
00021
00022 #include "BCGraphFitter.h"
00023
00024
00025
00026 BCGraphFitter::BCGraphFitter()
00027 : BCModel()
00028 , fGraph(0)
00029 , fFitFunction(0)
00030 , fErrorBand(0)
00031 , fGraphFitFunction(0)
00032 {
00033 MCMCSetNIterationsRun(2000);
00034
00035 SetFillErrorBand();
00036 }
00037
00038
00039
00040 BCGraphFitter::BCGraphFitter(const char * name)
00041 : BCModel(name)
00042 , fGraph(0)
00043 , fFitFunction(0)
00044 , fErrorBand(0)
00045 , fGraphFitFunction(0)
00046 {
00047 MCMCSetNIterationsRun(2000);
00048
00049 SetFillErrorBand();
00050 }
00051
00052
00053
00054 BCGraphFitter::BCGraphFitter(TGraphErrors * graph, TF1 * func)
00055 : BCModel()
00056 , fGraph(0)
00057 , fFitFunction(0)
00058 , fErrorBand(0)
00059 , fGraphFitFunction(0)
00060 {
00061 MCMCSetNIterationsRun(2000);
00062
00063 SetGraph(graph);
00064 SetFitFunction(func);
00065
00066 SetFillErrorBand();
00067 }
00068
00069
00070
00071 BCGraphFitter::BCGraphFitter(const char * name, TGraphErrors * graph, TF1 * func)
00072 : BCModel(name)
00073 , fGraph(0)
00074 , fFitFunction(0)
00075 , fErrorBand(0)
00076 , fGraphFitFunction(0)
00077 {
00078 MCMCSetNIterationsRun(2000);
00079
00080 SetGraph(graph);
00081 SetFitFunction(func);
00082
00083 SetFillErrorBand();
00084 }
00085
00086
00087
00088 int BCGraphFitter::SetGraph(TGraphErrors * graph)
00089 {
00090 if(!graph) {
00091 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors not created.");
00092 return 0;
00093 }
00094
00095 int npoints = graph->GetN();
00096 if(!npoints)
00097 {
00098 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors is empty.");
00099 return 0;
00100 }
00101 else if(npoints==1)
00102 {
00103 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors has only one point. Not able to fit.");
00104 return 0;
00105 }
00106
00107 fGraph = graph;
00108
00109 double * x = fGraph->GetX();
00110 double * y = fGraph->GetY();
00111 double * ex = fGraph->GetEX();
00112 double * ey = fGraph->GetEY();
00113
00114 if(!ey)
00115 {
00116 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors has NO errors set on Y. Not able to fit.");
00117 return 0;
00118 }
00119
00120 BCDataSet * ds = new BCDataSet();
00121
00122
00123
00124 double xmin=x[0];
00125 double xmax=x[0];
00126 double ymin=y[0];
00127 double ymax=y[0];
00128 for (int i = 0; i < npoints; ++i)
00129 {
00130
00131 double errx = ex ? ex[i] : 0.;
00132
00133
00134 BCDataPoint * dp = new BCDataPoint(4);
00135 dp->SetValue(0, x[i]);
00136 dp->SetValue(1, y[i]);
00137 dp->SetValue(2, errx);
00138 dp->SetValue(3, ey[i]);
00139 ds->AddDataPoint(dp);
00140
00141 if(x[i]-errx < xmin)
00142 xmin = x[i]-errx;
00143 else if(x[i]+errx > xmax)
00144 xmax = x[i]+errx;
00145
00146 if(y[i] - 5.*ey[i] < ymin)
00147 ymin = y[i] - 5.*ey[i];
00148 else if(y[i] + 5.*ey[i] > ymax)
00149 ymax = y[i] + 5.*ey[i];
00150 }
00151
00152 SetDataSet(ds);
00153
00154
00155 SetDataBoundaries(0, xmin, xmax);
00156 SetDataBoundaries(1, ymin, ymax);
00157
00158 SetFitFunctionIndices(0, 1);
00159
00160 return GetNDataPoints();
00161 }
00162
00163
00164
00165 int BCGraphFitter::SetFitFunction(TF1 * func)
00166 {
00167 if(!func)
00168 {
00169 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetFitFunction() : TF1 not created.");
00170 return 0;
00171 }
00172
00173
00174 int npar = func->GetNpar();
00175 if(!npar)
00176 {
00177 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetFitFunction() : TF1 has zero parameters. Not able to fit.");
00178 return 0;
00179 }
00180
00181
00182 fFitFunction = func;
00183
00184
00185 if(fName=="model")
00186 SetName(TString::Format("GraphFitter with %s",fFitFunction->GetName()));
00187
00188
00189 fParameterSet->clear();
00190
00191
00192 for (int i = 0; i < npar; ++i)
00193 {
00194 double xmin;
00195 double xmax;
00196 fFitFunction->GetParLimits(i, xmin, xmax);
00197
00198 AddParameter(fFitFunction->GetParName(i), xmin, xmax);
00199 }
00200
00201
00202 SetPriorConstantAll();
00203
00204 return GetNParameters();
00205 }
00206
00207
00208
00209 BCGraphFitter::~BCGraphFitter()
00210 {}
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 double BCGraphFitter::LogLikelihood(const std::vector<double> & params)
00229 {
00230
00231 double logl = 0.;
00232
00233
00234
00235
00236
00237
00238
00239 fFitFunction->SetParameters(¶ms[0]);
00240
00241
00242 for (int i = 0; i < GetNDataPoints(); i++)
00243 {
00244 std::vector<double> x = GetDataPoint(i)->GetValues();
00245
00246
00247
00248 double y = x[1];
00249 double yerr = x[3];
00250 double yexp = fFitFunction->Eval(x[0]);
00251
00252
00253
00254 logl += BCMath::LogGaus(y, yexp, yerr, true);
00255 }
00256
00257 return logl;
00258 }
00259
00260
00261
00262 double BCGraphFitter::FitFunction(const std::vector<double> & x, const std::vector<double> & params)
00263 {
00264
00265
00266
00267
00268
00269
00270 fFitFunction->SetParameters(¶ms[0]);
00271
00272 return fFitFunction->Eval(x[0]);
00273 }
00274
00275
00276
00277 int BCGraphFitter::Fit(TGraphErrors * graph, TF1 * func)
00278 {
00279
00280 if (!SetGraph(graph)) {
00281 BCLog::OutError("BCEfficiencyFitter::Fit : Graph not defined.");
00282 return 0;
00283 }
00284
00285
00286 if (!SetFitFunction(func)) {
00287 return 0;
00288 BCLog::OutError("BCEfficiencyFitter::Fit : Fit function not defined.");
00289 }
00290
00291 return Fit();
00292 }
00293
00294
00295
00296 int BCGraphFitter::Fit()
00297 {
00298
00299 if (!fGraph) {
00300 BCLog::OutError("BCEfficiencyFitter::Fit : Graph not defined.");
00301 return 0;
00302 }
00303
00304
00305 if (!fFitFunction) {
00306 BCLog::OutError("BCEfficiencyFitter::Fit : Fit function not defined.");
00307 return 0;
00308 }
00309
00310
00311 BCLog::Out(BCLog::detail,BCLog::detail,
00312 Form("Fitting %d data points with function of %d parameters",GetNDataPoints(),GetNParameters()));
00313 if(GetNDataPoints() <= (int)GetNParameters())
00314 {
00315 BCLog::Out(BCLog::warning,BCLog::warning,
00316 Form("Number of parameters (%d) lower than or equal to number of points (%d)."
00317 , GetNParameters(), GetNDataPoints()));
00318 BCLog::Out(BCLog::warning,BCLog::warning,"Fit doesn't have much meaning.");
00319 }
00320
00321
00322 MarginalizeAll();
00323
00324
00325
00326 FindModeMinuit( GetBestFitParameters(), -1);
00327
00328
00329
00330
00331 GetPvalueFromChi2(GetBestFitParameters(), 3);
00332 GetPvalueFromChi2NDoF(GetBestFitParameters(), 3);
00333
00334
00335 PrintShortFitSummary(1);
00336
00337 return 1;
00338 }
00339
00340
00341
00342 void BCGraphFitter::DrawFit(const char * options, bool flaglegend)
00343 {
00344 if (!fGraph)
00345 {
00346 BCLog::Out(BCLog::error, BCLog::error,"BCGraphFitter::DrawFit() : TGraphErrors not defined.");
00347 return;
00348 }
00349
00350 if (!fFitFunction)
00351 {
00352 BCLog::Out(BCLog::error, BCLog::error,"BCGraphFitter::DrawFit() : Fit function not defined.");
00353 return;
00354 }
00355
00356
00357 TString opt = options;
00358 opt.ToLower();
00359
00360
00361 if(!opt.Contains("same"))
00362 fGraph->Draw("ap");
00363
00364
00365 fErrorBand = GetErrorBandGraph(0.16, 0.84);
00366 fErrorBand->Draw("f same");
00367
00368
00369 fGraphFitFunction = GetFitFunctionGraph( GetBestFitParameters() );
00370 fGraphFitFunction->SetLineColor(kRed);
00371 fGraphFitFunction->SetLineWidth(2);
00372 fGraphFitFunction->Draw("l same");
00373
00374
00375
00376 fGraph->Draw("p same");
00377
00378
00379 if (flaglegend)
00380 {
00381 TLegend * legend = new TLegend(0.25, 0.75, 0.55, 0.95);
00382 legend->SetBorderSize(0);
00383 legend->SetFillColor(kWhite);
00384 legend->AddEntry(fGraph, "Data", "P");
00385 legend->AddEntry(fGraphFitFunction, "Best fit", "L");
00386 legend->AddEntry(fErrorBand, "Error band", "F");
00387 legend->Draw();
00388 }
00389
00390 gPad->RedrawAxis();
00391 }
00392
00393
00394
00395 double BCGraphFitter::CDF(const std::vector<double> & parameters, int index, bool ) {
00396
00397
00398 std::vector<double> values = fDataSet->GetDataPoint(index)->GetValues();
00399
00400 if (values.at(2))
00401 BCLog::OutWarning("BCGraphFitter::CDF: Non-zero errors in x-direction are ignored!");
00402
00403
00404 double yObs = values.at(1);
00405
00406
00407 double yExp = FitFunction(values, parameters);
00408
00409 return ROOT::Math::normal_cdf(yObs, values.at(3), yExp);
00410 }
00411
00412