11 #include "BCHistogramFitter.h"
12 #include "BAT/BCLog.h"
13 #include "BAT/BCDataSet.h"
14 #include "BAT/BCDataPoint.h"
15 #include "BAT/BCMath.h"
25 #include <Math/ProbFuncMathCore.h>
34 , fHistogramExpected(0)
37 MCMCSetNIterationsRun(2000);
39 fFlagIntegration =
true;
43 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
52 , fHistogramExpected(0)
55 MCMCSetNIterationsRun(2000);
57 fFlagIntegration =
true;
61 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
70 , fHistogramExpected(0)
75 MCMCSetNIterationsRun(2000);
77 fFlagIntegration =
true;
81 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
90 , fHistogramExpected(0)
95 MCMCSetNIterationsRun(2000);
97 fFlagIntegration =
true;
101 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
110 BCLog::OutError(
"BCHistogramFitter::SetHistogram : TH1D not created.");
125 int nbins = fHistogram->GetNbinsX();
126 for (
int i = 0; i < nbins; ++i) {
128 dp ->
SetValue(0, fHistogram->GetBinLowEdge(i + 1));
129 dp ->
SetValue(1, fHistogram->GetBinContent(i + 1));
137 double xmin = hist->GetBinLowEdge(1);
138 double xmax = hist->GetBinLowEdge(nbins + 1);
141 double histymin = hist->GetMinimum();
142 double histymax = hist->GetMaximum();
146 double ymin = TMath::Max(0., histymin - 5. * sqrt(histymin));
147 double ymax = histymax + 5. * sqrt(histymax);
150 SetDataBoundaries(0, xmin, xmax);
151 SetDataBoundaries(1, ymin, ymax);
165 if (fHistogramExpected) {
166 delete fHistogramExpected;
169 fHistogramExpected =
new TH1D(*fHistogram);
172 int nBins = fHistogramExpected->GetNbinsX();
175 double dx = fHistogramExpected->GetBinWidth(1);
178 fFitFunction->SetParameters(¶meters[0]);
181 double fedgelow = fFitFunction->Eval(fHistogramExpected->GetBinLowEdge(1));
184 for (
int ibin = 1; ibin <= nBins; ++ibin) {
186 double xedgehi = fHistogramExpected->GetBinLowEdge(ibin) + dx;
192 if (fFlagIntegration)
193 yexp = fFitFunction->Integral(xedgehi - dx, xedgehi);
198 double fedgehi = fFitFunction->Eval(xedgehi);
199 yexp = fedgelow * dx + (fedgehi - fedgelow) * dx / 2.;
206 fHistogramExpected->SetBinContent(ibin, yexp);
209 fHistogramExpected->SetBinError(ibin, 0.0);
212 fHistogram->SetBinError(ibin, sqrt(yexp));
224 BCLog::OutError(
"BCHistogramFitter::SetFitFunction : TF1 not created.");
233 SetName(TString::Format(
"HistogramFitter with %s", fFitFunction->GetName()));
236 ClearParameters(
true);
239 int n = func->GetNpar();
242 for (
int i = 0; i < n; ++i) {
246 func->GetParLimits(i, xmin, xmax);
254 return GetNParameters();
262 delete fHistogramExpected;
270 double loglikelihood = 0;
273 fFitFunction->SetParameters(¶ms[0]);
276 int nbins = fHistogram->GetNbinsX();
279 double dx = fHistogram->GetBinWidth(1);
282 double fedgelow = fFitFunction->Eval(fHistogram->GetBinLowEdge(1));
285 for (
int ibin = 1; ibin <= nbins; ++ibin) {
287 double xedgehi = fHistogram->GetBinLowEdge(ibin) + dx;
290 double fedgehi = fFitFunction->Eval(xedgehi);
293 double y = fHistogram->GetBinContent(ibin);
298 if (fFlagIntegration)
299 yexp = fFitFunction->Integral(xedgehi - dx, xedgehi);
303 yexp = fedgelow * dx + (fedgehi - fedgelow) * dx / 2.;
313 return loglikelihood;
321 fFitFunction->SetParameters(¶ms[0]);
323 return fFitFunction->Eval(x[0]) * fHistogram->GetBinWidth(fHistogram->FindBin(x[0]));
334 BCLog::OutError(
"BCHistogramFitter::Fit : Histogram not defined.");
342 BCLog::OutError(
"BCHistogramFitter::Fit : Fit function not defined.");
355 BCLog::OutError(
"BCHistogramFitter::Fit : Histogram not defined.");
361 BCLog::OutError(
"BCHistogramFitter::Fit : Fit function not defined.");
370 BCIntegrate::BCOptimizationMethod method_temp = GetOptimizationMethod();
371 SetOptimizationMethod(BCIntegrate::kOptMinuit);
372 FindMode( GetBestFitParameters());
373 SetOptimizationMethod(method_temp);
378 "BCHistogramFitter::Fit : Could not use the fast p-value evaluation.");
392 BCLog::OutError(
"BCHistogramFitter::DrawFit : Histogram not defined.");
397 BCLog::OutError(
"BCHistogramFitter::DrawFit : Fit function not defined.");
402 BCLog::OutError(
"BCHistogramFitter::DrawFit : Fit not performed yet.");
407 TString opt = options;
411 if (!opt.Contains(
"same"))
412 fHistogram->Draw(opt.Data());
415 fErrorBand = GetErrorBandGraph(0.16, 0.84);
416 fErrorBand->Draw(
"f same");
419 fHistogram->Draw(TString::Format(
"%ssame", opt.Data()));
422 fGraphFitFunction = GetFitFunctionGraph(GetBestFitParameters());
423 fGraphFitFunction->SetLineColor(kRed);
424 fGraphFitFunction->SetLineWidth(2);
425 fGraphFitFunction->Draw(
"l same");
429 TLegend * legend =
new TLegend(0.25, 0.75, 0.55, 0.95);
430 legend->SetBorderSize(0);
431 legend->SetFillColor(kWhite);
432 legend->AddEntry(fHistogram,
"Data",
"L");
433 legend->AddEntry(fGraphFitFunction,
"Best fit",
"L");
434 legend->AddEntry(fErrorBand,
"Error band",
"F");
445 if (par.size() != GetNParameters()) {
447 "BCHistogramFitter::CalculatePValueFast : Number of parameters is inconsistent.");
454 "BCHistogramFitter::CalculatePValueFast : Histogram not defined.");
462 std::vector<unsigned> observed(fHistogram->GetNbinsX());
463 std::vector<double> expected(fHistogramExpected->GetNbinsX());
465 for (
int ibin = 0 ; ibin < fHistogram->GetNbinsX(); ++ibin){
466 observed[ibin] = (
unsigned int) fHistogram->GetBinContent(ibin + 1);
467 expected[ibin] = fHistogramExpected->GetBinContent(ibin + 1);
484 double logLambda = 0.0;
489 for (
int ibin = 1; ibin <= fHistogram->GetNbinsX(); ++ibin) {
492 double y = fHistogram->GetBinContent(ibin);
495 double yexp = fHistogramExpected->GetBinContent(ibin);
501 logLambda += yexp - y + y * log(y / yexp);
509 fPValueNDoF = TMath::Prob(logLambda,
GetNDataPoints() - GetNParameters());
525 for (
int ibin = 1; ibin <= fHistogram->GetNbinsX(); ++ibin) {
528 double y = fHistogram->GetBinContent(ibin);
531 double yexp = fHistogramExpected->GetBinContent(ibin);
536 weight = (yexp > 0) ? yexp : 1.0;
538 weight = (y > 0) ? y : 1.0;
541 chi2 += (y - yexp) * (y - yexp) / weight;
546 fPValueNDoF = TMath::Prob(chi2,
GetNDataPoints() - GetNParameters());
556 if (!fHistogramExpected || !fHistogram) {
557 BCLog::OutError(
"BCHistogramFitter::CalculatePValueKolmogorov: "
558 "Please define the reference distribution by calling \n"
559 "BCHistogramFitter::SetHistogramExpected() first!");
567 fPValue = fHistogramExpected->KolmogorovTest(fHistogram);
579 if (parameters.empty())
580 BCLog::OutWarning(
"BCHistogramFitter::CDF: parameter vector empty!");
585 double yObs = fHistogram->GetBinContent(index);
588 double edgeLow = fHistogram->GetBinLowEdge(index);
589 double edgeHigh = edgeLow + fHistogram->GetBinWidth(index);
595 if (fFlagIntegration) {
596 TF1 tmpF(*fFitFunction);
597 tmpF.SetParameters(¶meters[0]);
598 yExp = tmpF.Integral(edgeLow, edgeHigh);
602 double dx = fHistogram->GetBinWidth(index);
603 double fEdgeLow = fFitFunction->Eval(edgeLow);
604 double fEdgeHigh = fFitFunction->Eval(edgeHigh);
605 yExp = fEdgeLow * dx + (fEdgeHigh - fEdgeLow) * dx / 2.;
613 return ROOT::Math::poisson_cdf((
unsigned int) (yObs - 1), yExp);
618 if ((
double) (
unsigned int) yObs != yObs) {
619 BCLog::OutWarning(Form(
620 "BCHistogramFitter::CDF: Histogram values should be integer!\n"
621 " Bin %d = %f", index, yObs));
627 double U = fRandom->Rndm();
628 double yObsLower = (
unsigned int) yObs;
629 if (U > (yObs - yObsLower))
632 yObs = yObsLower + 1;
635 return ROOT::Math::poisson_cdf((
unsigned int) yObs, yExp);
void PrintShortFitSummary(int chi2flag=0)
virtual double LogLikelihood(const std::vector< double > ¶meters)
int SetFitFunction(TF1 *func)
int CalculatePValueLeastSquares(const std::vector< double > &par, bool weightExpect=true)
A class representing a data point.
int SetHistogramExpected(const std::vector< double > ¶meters)
double FastPValue(const std::vector< unsigned > &observed, const std::vector< double > &expected, unsigned nIterations, unsigned seed)
void SetName(const char *name)
void SetDataSet(BCDataSet *dataset)
int SetPriorConstantAll()
A class representing a set of data points.
void SetFitFunctionIndices(int indexx, int indexy)
double CorrectPValue(const double &pvalue, const unsigned &npar, const unsigned &nobservations)
virtual int AddParameter(BCParameter *parameter)
unsigned GetNDataPoints() const
double FitFunction(const std::vector< double > &x, const std::vector< double > ¶meters)
int CalculatePValueKolmogorov(const std::vector< double > &par)
int SetHistogram(TH1D *hist)
void SetFillErrorBand(bool flag=true)
double LogPoisson(double x, double par)
double CDF(const std::vector< double > ¶meters, int index, bool lower=false)
void DrawFit(const char *options="HIST", bool flaglegend=false)
int CalculatePValueFast(const std::vector< double > &par, unsigned nIterations=100000)
void AddDataPoint(BCDataPoint *datapoint)
A base class for all fitting classes.
void SetValue(unsigned index, double value)
int CalculatePValueLikelihood(const std::vector< double > &par)