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
00016 #include "BAT/BCLog.h"
00017 #include "BAT/BCDataSet.h"
00018 #include "BAT/BCDataPoint.h"
00019 #include "BAT/BCMath.h"
00020
00021 #include "BAT/BCGraphFitter.h"
00022
00023
00024
00025 BCGraphFitter::BCGraphFitter() : BCModel("GraphFitter")
00026 {
00027 fGraph = 0;
00028 fFitFunction = 0;
00029 fErrorBand = 0;
00030 fGraphFitFunction = 0;
00031
00032 this -> MCMCSetNIterationsRun(2000);
00033
00034 this -> SetFillErrorBand();
00035 }
00036
00037
00038
00039 BCGraphFitter::BCGraphFitter(TGraphErrors * graph, TF1 * func) : BCModel("GraphFitter")
00040 {
00041 fGraph = 0;
00042 fFitFunction = 0;
00043 fErrorBand = 0;
00044 fGraphFitFunction = 0;
00045
00046 this -> MCMCSetNIterationsRun(2000);
00047
00048 this -> SetGraph(graph);
00049 this -> SetFitFunction(func);
00050
00051 this -> SetFillErrorBand();
00052 }
00053
00054
00055
00056 int BCGraphFitter::SetGraph(TGraphErrors * graph)
00057 {
00058 if(!graph)
00059 {
00060 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors not created.");
00061 return 0;
00062 }
00063
00064 int npoints = graph -> GetN();
00065 if(!npoints)
00066 {
00067 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors is empty.");
00068 return 0;
00069 }
00070 else if(npoints==1)
00071 {
00072 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors has only one point. Not able to fit.");
00073 return 0;
00074 }
00075 else if(npoints==2)
00076 {
00077 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors has only two points. Fit has no meaning.");
00078 return 0;
00079 }
00080
00081 fGraph = graph;
00082
00083 double * x = fGraph -> GetX();
00084 double * y = fGraph -> GetY();
00085 double * ex = fGraph -> GetEX();
00086 double * ey = fGraph -> GetEY();
00087
00088 if(!ey)
00089 {
00090 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetGraph() : TGraphErrors has no errors set on Y. Not able to fit.");
00091 return 0;
00092 }
00093
00094 BCDataSet * ds = new BCDataSet();
00095
00096
00097
00098 double xmin=x[0];
00099 double xmax=x[0];
00100 double ymin=y[0];
00101 double ymax=y[0];
00102 for (int i = 0; i < npoints; ++i)
00103 {
00104
00105 double errx = ex ? ex[i] : 0.;
00106
00107
00108 BCDataPoint * dp = new BCDataPoint(4);
00109 dp -> SetValue(0, x[i]);
00110 dp -> SetValue(1, y[i]);
00111 dp -> SetValue(2, errx);
00112 dp -> SetValue(3, ey[i]);
00113 ds -> AddDataPoint(dp);
00114
00115 if(x[i]-errx < xmin)
00116 xmin = x[i]-errx;
00117 else if(x[i]+errx > xmax)
00118 xmax = x[i]+errx;
00119
00120 if(y[i] - 5.*ey[i] < ymin)
00121 ymin = y[i] - 5.*ey[i];
00122 else if(y[i] + 5.*ey[i] > ymax)
00123 ymax = y[i] + 5.*ey[i];
00124 }
00125
00126 this -> SetDataSet(ds);
00127
00128
00129 this -> SetDataBoundaries(0, xmin, xmax);
00130 this -> SetDataBoundaries(1, ymin, ymax);
00131
00132 this -> SetFitFunctionIndices(0, 1);
00133
00134 return this -> GetNDataPoints();
00135 }
00136
00137
00138
00139 int BCGraphFitter::SetFitFunction(TF1 * func)
00140 {
00141 if(!func)
00142 {
00143 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetFitFunction() : TF1 not created.");
00144 return 0;
00145 }
00146
00147
00148 int npar = func -> GetNpar();
00149 if(!npar)
00150 {
00151 BCLog::Out(BCLog::error,BCLog::error,"BCGraphFitter::SetFitFunction() : TF1 has zero parameters. Not able to fit.");
00152 return 0;
00153 }
00154
00155
00156 fFitFunction = func;
00157
00158
00159 this -> SetName(TString::Format("GraphFitter with %s",fFitFunction->GetName()));
00160
00161
00162 fParameterSet -> clear();
00163
00164
00165 for (int i = 0; i < npar; ++i)
00166 {
00167 double xmin;
00168 double xmax;
00169 fFitFunction -> GetParLimits(i, xmin, xmax);
00170
00171 this -> AddParameter(fFitFunction->GetParName(i), xmin, xmax);
00172 }
00173
00174 return this -> GetNParameters();
00175 }
00176
00177
00178
00179 BCGraphFitter::~BCGraphFitter()
00180 {}
00181
00182
00183
00184 double BCGraphFitter::LogAPrioriProbability(std::vector <double> parameters)
00185 {
00186
00187 double logprob = 0.;
00188 for(unsigned int i=0; i < this -> GetNParameters(); i++)
00189 logprob -= log(this -> GetParameter(i) -> GetRangeWidth());
00190
00191 return logprob;
00192 }
00193
00194
00195
00196 double BCGraphFitter::LogLikelihood(std::vector <double> params)
00197 {
00198
00199 double logl = 0.;
00200
00201
00202
00203
00204
00205
00206
00207 fFitFunction -> SetParameters(¶ms[0]);
00208
00209
00210 for (int i = 0; i < this -> GetNDataPoints(); i++)
00211 {
00212 std::vector <double> x = GetDataPoint(i) -> GetValues();
00213
00214
00215
00216 double y = x[1];
00217 double yerr = x[3];
00218 double yexp = this -> FitFunction(x,params);
00219
00220
00221
00222 logl += BCMath::LogGaus(y, yexp, yerr, true);
00223 }
00224
00225 return logl;
00226 }
00227
00228
00229
00230 double BCGraphFitter::FitFunction(std::vector <double> x, std::vector <double> params)
00231 {
00232
00233 fFitFunction -> SetParameters(¶ms[0]);
00234
00235 return fFitFunction -> Eval(x[0]);
00236 }
00237
00238
00239
00240 int BCGraphFitter::Fit(TGraphErrors * graph, TF1 * func)
00241 {
00242
00243 if (!this -> SetGraph(graph))
00244 return 0;
00245
00246
00247 if (!this -> SetFitFunction(func))
00248 return 0;
00249
00250
00251 this -> MarginalizeAll();
00252
00253
00254
00255 this -> FindModeMinuit( this -> GetBestFitParameters(), -1);
00256
00257
00258
00259
00260 this -> GetPvalueFromChi2(this -> GetBestFitParameters(), 3);
00261
00262
00263 this -> PrintShortFitSummary();
00264
00265 return 1;
00266 }
00267
00268
00269
00270 void BCGraphFitter::DrawFit(const char * options, bool flaglegend)
00271 {
00272 if (!fGraph)
00273 {
00274 BCLog::Out(BCLog::error, BCLog::error,"BCGraphFitter::DrawFit() : TGraphErrors not defined.");
00275 return;
00276 }
00277
00278 if (!fFitFunction)
00279 {
00280 BCLog::Out(BCLog::error, BCLog::error,"BCGraphFitter::DrawFit() : Fit function not defined.");
00281 return;
00282 }
00283
00284
00285 TString opt = options;
00286 opt.ToLower();
00287
00288
00289 if(!opt.Contains("same"))
00290 fGraph -> Draw("ap");
00291
00292
00293 fErrorBand = this -> GetErrorBandGraph(0.16, 0.84);
00294 fErrorBand -> Draw("f same");
00295
00296
00297 fGraphFitFunction = this -> GetFitFunctionGraph( this->GetBestFitParameters() );
00298 fGraphFitFunction -> SetLineColor(kRed);
00299 fGraphFitFunction -> SetLineWidth(2);
00300 fGraphFitFunction -> Draw("l same");
00301
00302
00303
00304 fGraph -> Draw("p same");
00305
00306
00307 if (flaglegend)
00308 {
00309 TLegend * legend = new TLegend(0.25, 0.75, 0.55, 0.95);
00310 legend -> SetBorderSize(0);
00311 legend -> SetFillColor(kWhite);
00312 legend -> AddEntry(fGraph, "Data", "P");
00313 legend -> AddEntry(fGraphFitFunction, "Best fit", "L");
00314 legend -> AddEntry(fErrorBand, "Error band", "F");
00315 legend -> Draw();
00316 }
00317
00318 gPad -> RedrawAxis();
00319 }
00320
00321