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