15 #include <TGraphAsymmErrors.h>
22 #include "BAT/BCLog.h"
23 #include "BAT/BCDataSet.h"
24 #include "BAT/BCDataPoint.h"
25 #include "BAT/BCMath.h"
26 #include "BAT/BCH1D.h"
28 #include "BCEfficiencyFitter.h"
37 , fHistogramBinomial(0)
41 fFlagIntegration =
false;
44 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
54 , fHistogramBinomial(0)
58 fFlagIntegration =
false;
61 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
71 , fHistogramBinomial(0)
77 fFlagIntegration =
false;
80 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
90 , fHistogramBinomial(0)
96 MCMCSetRValueCriterion(0.01);
97 fFlagIntegration =
false;
100 SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
108 if (!hist1 || !hist2) {
109 BCLog::OutError(
"BCEfficiencyFitter::SetHistograms : TH1D not created.");
114 if (hist1->GetNbinsX() != hist2->GetNbinsX()) {
115 BCLog::OutError(
"BCEfficiencyFitter::SetHistograms : Histograms do not have the same number of bins.");
120 for (
int i = 1; i <= hist1->GetNbinsX(); ++i)
121 if (hist1->GetBinContent(i) < hist2->GetBinContent(i)) {
122 BCLog::OutError(
"BCEfficiencyFitter::SetHistograms : Histogram 1 has fewer entries than histogram 2.");
136 int nbins = fHistogram1->GetNbinsX();
137 for (
int i = 0; i < nbins; ++i) {
146 double xmin = hist1->GetBinLowEdge(1);
147 double xmax = hist1->GetBinLowEdge(nbins+1);
159 SetDataBoundaries(0, xmin, xmax);
160 SetDataBoundaries(1, 0.0, 1.0);
175 BCLog::OutError(
"BCEfficiencyFitter::SetFitFunction : TF1 not created.");
184 SetName(TString::Format(
"BCEfficiencyFitter with %s",fFitFunction->GetName()));
187 ClearParameters(
true);
190 int n = func->GetNpar();
193 for (
int i = 0; i < n; ++i)
198 func->GetParLimits(i, xmin, xmax);
206 return GetNParameters();
215 delete fHistogramBinomial;
222 if(type < 0 || type > 2)
223 BCLog::OutError(Form(
"BCEfficiencyFitter::SetDataPointType : Unknown data point type %d (should be between 0 and 2).",type));
225 fDataPointType = type;
234 double loglikelihood = 0;
237 fFitFunction->SetParameters(¶ms[0]);
240 int nbins = fHistogram1->GetNbinsX();
243 double dx = fHistogram1->GetXaxis()->GetBinWidth(0);
246 for (
int ibin = 1; ibin <= nbins; ++ibin)
249 int n = int(fHistogram1->GetBinContent(ibin));
252 int k = int(fHistogram2->GetBinContent(ibin));
255 double x = fHistogram1->GetBinCenter(ibin);
260 if (fFlagIntegration)
261 eff = fFitFunction->Integral(x - dx/2., x + dx/2.) / dx;
265 eff = (fFitFunction->Eval(x + dx/2.) + fFitFunction->Eval(x - dx/2.)) / 2.;
271 return loglikelihood;
279 fFitFunction->SetParameters(¶ms[0]);
281 return fFitFunction->Eval(x[0]);
292 BCLog::OutError(
"BCEfficiencyFitter::Fit : Histogram(s) not defined.");
300 BCLog::OutError(
"BCEfficiencyFitter::Fit : Fit function not defined.");
312 if (!fHistogram1 || !fHistogram2) {
313 BCLog::OutError(
"BCEfficiencyFitter::Fit : Histogram(s) not defined.");
319 BCLog::OutError(
"BCEfficiencyFitter::Fit : Fit function not defined.");
328 BCIntegrate::BCOptimizationMethod method_temp = GetOptimizationMethod();
329 SetOptimizationMethod(BCIntegrate::kOptMinuit);
330 FindMode( GetBestFitParameters());
331 SetOptimizationMethod(method_temp);
334 double pvalue, pvalueCorrected;
338 BCLog::OutError(
"BCEfficiencyFitter::Fit : Could not use the fast p-value evaluation.");
351 if (!fHistogram1 || !fHistogram2) {
352 BCLog::OutError(
"BCEfficiencyFitter::DrawFit : Histogram(s) not defined.");
357 BCLog::OutError(
"BCEfficiencyFitter::DrawFit : Fit function not defined.");
362 TGraphAsymmErrors * histRatio =
new TGraphAsymmErrors();
363 histRatio->SetMarkerStyle(20);
364 histRatio->SetMarkerSize(1.5);
369 for (
int i = 1; i <= fHistogram1->GetNbinsX(); ++i)
371 if(
int(fHistogram1->GetBinContent(i)) == 0) {
377 double xexp, xmin, xmax;
378 GetUncertainties(
int(fHistogram1->GetBinContent(i)),
int(fHistogram2->GetBinContent(i)), 0.68, xexp, xmin, xmax);
380 histRatio->SetPoint( npoints, fHistogram1->GetBinCenter(i), xexp);
383 histRatio->SetPointEXhigh(npoints, 0.);
384 histRatio->SetPointEXlow(npoints, 0.);
387 histRatio->SetPointEYhigh(npoints, xmax - xexp);
388 histRatio->SetPointEYlow(npoints, xexp - xmin);
395 TString opt = options;
399 if(!opt.Contains(
"same"))
402 TH2D * hist_axes =
new TH2D(
"hist_axes",
403 Form(
";%s;ratio", fHistogram1->GetXaxis()->GetTitle()),
404 fHistogram1->GetNbinsX(),
405 fHistogram1->GetXaxis()->GetBinLowEdge(1),
406 fHistogram1->GetXaxis()->GetBinLowEdge(fHistogram1->GetNbinsX()+1),
408 hist_axes->SetStats(kFALSE);
411 histRatio->Draw(TString::Format(
"%sp",opt.Data()));
415 fErrorBand = GetErrorBandGraph(0.16, 0.84);
416 fErrorBand->Draw(
"f same");
419 histRatio->SetMarkerSize(.7);
420 histRatio->Draw(TString::Format(
"%ssamep",opt.Data()));
423 fGraphFitFunction = GetFitFunctionGraph( GetBestFitParameters() );
424 fGraphFitFunction->SetLineColor(kRed);
425 fGraphFitFunction->SetLineWidth(2);
426 fGraphFitFunction->Draw(
"l same");
431 TLegend * legend =
new TLegend(0.25, 0.75, 0.55, 0.95);
432 legend->SetBorderSize(0);
433 legend->SetFillColor(kWhite);
434 legend->AddEntry(histRatio,
"Data",
"L");
435 legend->AddEntry(fGraphFitFunction,
"Best fit",
"L");
436 legend->AddEntry(fErrorBand,
"Error band",
"F");
444 double & pvalueCorrected,
unsigned nIterations)
453 double & pvalueCorrected,
unsigned nIterations)
456 if (par.size() != GetNParameters()) {
457 BCLog::OutError(
"BCEfficiencyFitter::CalculatePValueFast : Number of parameters is inconsistent.");
462 if (!fHistogram1 || !fHistogram2) {
463 BCLog::OutError(
"BCEfficiencyFitter::CalculatePValueFast : Histogram not defined.");
468 int nbins = fHistogram1->GetNbinsX();
470 std::vector<unsigned> histogram(nbins, 0);
471 std::vector<double> expectation(nbins, 0);
474 double logp_start = 0;
475 int counter_pvalue = 0;
478 for (
int ibin = 0; ibin < nbins; ++ibin) {
480 double xmin = fHistogram1->GetBinLowEdge(ibin+1);
481 double xmax = fHistogram1->GetBinLowEdge(ibin+2);
484 double yexp = fFitFunction->Integral(xmin, xmax);
487 int n = int(fHistogram1->GetBinContent(ibin));
490 int k = int(fHistogram2->GetBinContent(ibin));
493 expectation[ibin] = n * yexp;
501 for (
unsigned iiter = 0; iiter < nIterations; ++iiter)
504 for (
int ibin = 0; ibin < nbins; ++ibin)
507 int n = int(fHistogram1->GetBinContent(ibin));
510 int k = histogram.at(ibin);
515 yexp = expectation.at(ibin)/n;
518 double ptest = fRandom->Rndm() - 0.5;
521 if (!(yexp > 0. || yexp < 1.0))
525 if (ptest > 0 && (k < n))
528 double r = (double(n)-double(k))/(
double(k)+1.) * yexp / (1. - yexp);
531 if (fRandom->Rndm() < r)
533 histogram[ibin] = k + 1;
539 else if (ptest <= 0 && (k > 0))
542 double r = double(k) / (double(n)-(double(k)-1)) * (1-yexp)/yexp;
545 if (fRandom->Rndm() < r)
547 histogram[ibin] = k - 1;
557 (*callback)(expectation, histogram);
560 if (logp < logp_start)
566 pvalue = double(counter_pvalue) / double(nIterations);
586 BCLog::OutDebug(Form(
"Calculating efficiency data-point of type %d for (n,k) = (%d,%d)",fDataPointType,n,k));
589 if (fHistogramBinomial)
590 fHistogramBinomial->Reset();
592 fHistogramBinomial =
new TH1D(
"hist_binomial",
"", 1000, 0., 1.);
595 for (
int i = 1; i <= 1000; ++i) {
596 double x = fHistogramBinomial->GetBinCenter(i);
598 fHistogramBinomial->SetBinContent(i, val);
602 fHistogramBinomial->Scale(1. / fHistogramBinomial->Integral());
605 if (fDataPointType == 0) {
606 xexp = fHistogramBinomial->GetMean();
607 double rms = fHistogramBinomial->GetRMS();
610 BCLog::OutDebug(Form(
" - mean = %f , rms = %f)",xexp,rms));
612 else if (fDataPointType == 1) {
613 xexp = (double)k/(
double)n;
614 BCH1D * fbh =
new BCH1D((TH1D*)fHistogramBinomial->Clone(
"hcp"));
616 int ninter = intervals.size();
618 xmin = xmax = xexp = 0.;
631 probSum[0] = (1.-p)/2.;
632 probSum[1] = 1.-(1.-p)/2.;
635 fHistogramBinomial->GetQuantiles(nprobSum, q, probSum);
643 BCLog::OutDebug(Form(
" - efficiency = %f , range (%f - %f)",xexp,xmin,xmax));
void PrintShortFitSummary(int chi2flag=0)
A class representing a data point.
double FitFunction(const std::vector< double > &x, const std::vector< double > ¶meters)
void SetName(const char *name)
void SetDataSet(BCDataSet *dataset)
int SetPriorConstantAll()
int GetUncertainties(int n, int k, double p, double &xexp, double &xmin, double &xmax)
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)
void DrawFit(const char *options="", bool flaglegend=false)
A class for handling 1D distributions.
std::vector< double > GetSmallestIntervals(double content=0.68)
int CalculatePValueFast(const std::vector< double > &par, BCEfficiencyFitter::ToyDataInterface *callback, double &pvalue, double &pvalueCorrected, unsigned nIterations=100000)
double ApproxBinomial(int n, int k, double p)
int SetFitFunction(TF1 *func)
double LogApproxBinomial(int n, int k, double p)
void SetDataPointType(int type)
void AddDataPoint(BCDataPoint *datapoint)
int SetHistograms(TH1D *hist1, TH1D *hist2)
A base class for all fitting classes.
virtual double LogLikelihood(const std::vector< double > ¶meters)