00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "BAT/BCModel.h"
00011
00012 #include "BAT/BCDataPoint.h"
00013 #include "BAT/BCDataSet.h"
00014 #include "BAT/BCParameter.h"
00015 #include "BAT/BCH1D.h"
00016 #include "BAT/BCH2D.h"
00017 #include "BAT/BCGoFTest.h"
00018 #include "BAT/BCLog.h"
00019 #include "BAT/BCErrorCodes.h"
00020 #include "BAT/BCMath.h"
00021 #include "BAT/BCModelOutput.h"
00022
00023 #include <TROOT.h>
00024 #include <TNamed.h>
00025 #include <TCanvas.h>
00026 #include <TPostScript.h>
00027 #include <TDirectory.h>
00028 #include <TFile.h>
00029 #include <TKey.h>
00030 #include <TTree.h>
00031 #include <TMath.h>
00032 #include <TGraph.h>
00033 #include <TH1.h>
00034 #include <TH2D.h>
00035 #include <TH1I.h>
00036 #include <TRandom3.h>
00037 #include <TF1.h>
00038 #include <Math/QuantFuncMathCore.h>
00039
00040 #include <algorithm>
00041 #include <set>
00042
00043 #include <fstream>
00044 #include <iomanip>
00045
00046
00047 BCModel::BCModel(const char * name)
00048 : BCIntegrate()
00049 {
00050 fNormalization = -1.;
00051 fDataSet = 0;
00052 fParameterSet = new BCParameterSet;
00053
00054 fIndex = -1;
00055 fPValue = -1;
00056 fPValueNDoF = -1;
00057 fChi2NDoF = -1;
00058
00059 fName = (char *) name;
00060 flag_ConditionalProbabilityEntry = true;
00061
00062 fDataPointUpperBoundaries = 0;
00063 fDataPointLowerBoundaries = 0;
00064
00065 fErrorBandXY = 0;
00066
00067 fGoFNChains = 5;
00068 fGoFNIterationsMax = 100000;
00069 fGoFNIterationsRun = 2000;
00070
00071 flag_discrete = false;
00072
00073 fPriorConstantAll = false;
00074 fPriorConstantValue = 0;
00075 }
00076
00077
00078 BCModel::BCModel()
00079 : BCIntegrate()
00080 {
00081 fNormalization = -1.;
00082 fDataSet = 0;
00083 fParameterSet = new BCParameterSet();
00084
00085 fIndex = -1;
00086 fPValue = -1;
00087 fPValueNDoF = -1;
00088 fChi2NDoF = -1;
00089
00090 fName = "model";
00091 fDataPointUpperBoundaries = 0;
00092 fDataPointLowerBoundaries = 0;
00093
00094 flag_ConditionalProbabilityEntry = true;
00095
00096 fGoFNChains = 5;
00097 fGoFNIterationsMax = 100000;
00098 fGoFNIterationsRun = 2000;
00099
00100 flag_discrete = false;
00101
00102 fPriorConstantAll = false;
00103 fPriorConstantValue = 0;
00104 }
00105
00106
00107 BCModel::~BCModel()
00108 {
00109 for (unsigned int i = 0; i < GetNParameters(); ++i)
00110 delete fPriorContainer[i];
00111 fPriorContainer.clear();
00112
00113 delete fParameterSet;
00114
00115 delete fDataPointLowerBoundaries;
00116 delete fDataPointUpperBoundaries;
00117 }
00118
00119
00120 int BCModel::GetNDataPoints()
00121 {
00122 int npoints = 0;
00123 if (fDataSet)
00124 npoints = fDataSet->GetNDataPoints();
00125 else {
00126 BCLog::OutWarning("BCModel::GetNDataPoints() : No data set defined.");
00127 return ERROR_NOEVENTS;
00128 }
00129
00130 return npoints;
00131 }
00132
00133
00134 BCDataPoint * BCModel::GetDataPoint(unsigned int index)
00135 {
00136 if (fDataSet)
00137 return fDataSet->GetDataPoint(index);
00138
00139 BCLog::OutWarning("BCModel::GetDataPoint : No data set defined.");
00140 return 0;
00141 }
00142
00143
00144 BCParameter * BCModel::GetParameter(int index)
00145 {
00146 if (!fParameterSet)
00147 return 0;
00148
00149 if (index < 0 || index >= (int)GetNParameters()) {
00150 BCLog::OutWarning(
00151 Form("BCModel::GetParameter : Parameter index %d not within range.",index));
00152 return 0;
00153 }
00154
00155 return fParameterSet->at(index);
00156 }
00157
00158
00159 BCParameter * BCModel::GetParameter(const char * name)
00160 {
00161 if (!fParameterSet)
00162 return 0;
00163
00164 int index = -1;
00165 for (unsigned int i = 0; i < GetNParameters(); i++)
00166 if (name == GetParameter(i)->GetName())
00167 index = i;
00168
00169 if (index < 0) {
00170 BCLog::OutWarning(
00171 Form("BCModel::GetParameter : Model %s has no parameter named '%s'",
00172 GetName().data(), name));
00173 return 0;
00174 }
00175
00176 return GetParameter(index);
00177 }
00178
00179
00180 double BCModel::GetBestFitParameter(unsigned int index)
00181 {
00182 if(index >= GetNParameters()) {
00183 BCLog::OutError("BCModel::GetBestFitParameter : Parameter index out of range, returning -1e+111.");
00184 return -1e+111;
00185 }
00186
00187 if(fBestFitParameters.size()==0) {
00188 BCLog::OutError("BCModel::GetBestFitParameter : Mode finding not yet run, returning center of the range.");
00189 return (GetParameter(index)->GetUpperLimit() + GetParameter(index)->GetLowerLimit() ) / 2.;
00190 }
00191
00192 return fBestFitParameters[index];
00193 }
00194
00195
00196 double BCModel::GetBestFitParameterError(unsigned int index)
00197 {
00198 if(index >= GetNParameters()) {
00199 BCLog::OutError("BCModel::GetBestFitParameterError : Parameter index out of range, returning -1.");
00200 return -1;
00201 }
00202
00203 if(fBestFitParameterErrors.size()==0) {
00204 BCLog::OutError("BCModel::GetBestFitParameterError : Mode finding not yet run, returning -1.");
00205 return -1.;
00206 }
00207
00208 if(fBestFitParameterErrors[index]<0.)
00209 BCLog::OutWarning("BCModel::GetBestFitParameterError : Parameter error not available, returning -1.");
00210
00211 return fBestFitParameterErrors[index];
00212 }
00213
00214
00215 double BCModel::GetBestFitParameterMarginalized(unsigned int index)
00216 {
00217 if(index >= GetNParameters()) {
00218 BCLog::OutError("BCModel::GetBestFitParameterMarginalized : Parameter index out of range, returning -1e+111.");
00219 return -1e+111;
00220 }
00221
00222 if(fBestFitParametersMarginalized.size()==0) {
00223 BCLog::OutError("BCModel::GetBestFitParameterMarginalized : MCMC not yet run, returning center of the range.");
00224 return (GetParameter(index)->GetUpperLimit() + GetParameter(index)->GetLowerLimit() ) / 2.;
00225 }
00226
00227 return fBestFitParametersMarginalized[index];
00228 }
00229
00230
00231 void BCModel::SetNbins(const char * parname, int nbins)
00232 {
00233 BCParameter * p = GetParameter(parname);
00234 if (!p) {
00235 BCLog::OutWarning(
00236 Form("BCModel::SetNbins : Parameter '%s' not found so Nbins not set",parname));
00237 return;
00238 }
00239
00240 BCIntegrate::SetNbins(nbins, p->GetIndex());
00241 }
00242
00243
00244 std::vector<double> BCModel::GetErrorBand(double level)
00245 {
00246 std::vector<double> errorband;
00247
00248 if (!fErrorBandXY)
00249 return errorband;
00250
00251 int nx = fErrorBandXY->GetNbinsX();
00252 errorband.assign(nx, 0.);
00253
00254
00255 for (int ix = 1; ix <= nx; ix++) {
00256 TH1D * temphist = fErrorBandXY->ProjectionY("temphist", ix, ix);
00257
00258 int nprobSum = 1;
00259 double q[1];
00260 double probSum[1];
00261 probSum[0] = level;
00262
00263 temphist->GetQuantiles(nprobSum, q, probSum);
00264
00265 errorband[ix - 1] = q[0];
00266 }
00267
00268 return errorband;
00269 }
00270
00271
00272 TGraph * BCModel::GetErrorBandGraph(double level1, double level2)
00273 {
00274 if (!fErrorBandXY)
00275 return 0;
00276
00277
00278 int nx = fErrorBandXY->GetNbinsX();
00279
00280 TGraph * graph = new TGraph(2 * nx);
00281 graph->SetFillStyle(1001);
00282 graph->SetFillColor(kYellow);
00283
00284
00285 std::vector<double> ymin = GetErrorBand(level1);
00286 std::vector<double> ymax = GetErrorBand(level2);
00287
00288 for (int i = 0; i < nx; i++) {
00289 graph->SetPoint(i, fErrorBandXY->GetXaxis()->GetBinCenter(i + 1), ymin[i]);
00290 graph->SetPoint(nx + i, fErrorBandXY->GetXaxis()->GetBinCenter(nx - i), ymax[nx - i - 1]);
00291 }
00292
00293 return graph;
00294 }
00295
00296
00297 TH2D * BCModel::GetErrorBandXY_yellow(double level, int nsmooth)
00298 {
00299 if (!fErrorBandXY)
00300 return 0;
00301
00302 int nx = fErrorBandXY->GetNbinsX();
00303 int ny = fErrorBandXY->GetNbinsY();
00304
00305
00306 TH2D * hist_tempxy = (TH2D*) fErrorBandXY->Clone(
00307 TString::Format("%s_sub_%f.2", fErrorBandXY->GetName(), level));
00308 hist_tempxy->Reset();
00309 hist_tempxy->SetFillColor(kYellow);
00310
00311
00312 for (int ix = 1; ix < nx; ix++) {
00313 BCH1D * hist_temp = new BCH1D();
00314
00315 TH1D * hproj = fErrorBandXY->ProjectionY("temphist", ix, ix);
00316 if (nsmooth > 0)
00317 hproj->Smooth(nsmooth);
00318
00319 hist_temp->SetHistogram(hproj);
00320
00321 TH1D * hist_temp_yellow = hist_temp->GetSmallestIntervalHistogram(level);
00322
00323 for (int iy = 1; iy <= ny; ++iy)
00324 hist_tempxy->SetBinContent(ix, iy, hist_temp_yellow->GetBinContent(iy));
00325
00326 delete hist_temp_yellow;
00327 delete hist_temp;
00328 }
00329
00330 return hist_tempxy;
00331 }
00332
00333
00334 TGraph * BCModel::GetFitFunctionGraph(std::vector<double> parameters)
00335 {
00336 if (!fErrorBandXY)
00337 return 0;
00338
00339
00340 int nx = fErrorBandXY->GetNbinsX();
00341 TGraph * graph = new TGraph(nx);
00342
00343
00344 for (int i = 0; i < nx; i++) {
00345 double x = fErrorBandXY->GetXaxis()->GetBinCenter(i + 1);
00346
00347 std::vector<double> xvec;
00348 xvec.push_back(x);
00349 double y = FitFunction(xvec, parameters);
00350 xvec.clear();
00351
00352 graph->SetPoint(i, x, y);
00353 }
00354
00355 return graph;
00356 }
00357
00358
00359 TGraph * BCModel::GetFitFunctionGraph(std::vector<double> parameters, double xmin, double xmax, int n)
00360 {
00361
00362 TGraph * graph = new TGraph(n + 1);
00363
00364 double dx = (xmax - xmin) / (double) n;
00365
00366
00367 for (int i = 0; i <= n; i++) {
00368 double x = (double) i * dx + xmin;
00369 std::vector<double> xvec;
00370 xvec.push_back(x);
00371 double y = FitFunction(xvec, parameters);
00372
00373 xvec.clear();
00374
00375 graph->SetPoint(i, x, y);
00376 }
00377
00378 return graph;
00379 }
00380
00381
00382 bool BCModel::GetFlagBoundaries()
00383 {
00384 if (!fDataPointLowerBoundaries)
00385 return false;
00386
00387 if (!fDataPointUpperBoundaries)
00388 return false;
00389
00390 if (fDataPointLowerBoundaries->GetNValues() != fDataSet->GetDataPoint(0)->GetNValues())
00391 return false;
00392
00393 if (fDataPointUpperBoundaries->GetNValues() != fDataSet->GetDataPoint(0)->GetNValues())
00394 return false;
00395
00396 return true;
00397 }
00398
00399
00400 void BCModel::SetSingleDataPoint(BCDataPoint * datapoint)
00401 {
00402
00403 BCDataSet * dataset = new BCDataSet();
00404
00405
00406 dataset->AddDataPoint(datapoint);
00407
00408
00409 SetDataSet(dataset);
00410 }
00411
00412
00413 void BCModel::SetSingleDataPoint(BCDataSet * dataset, unsigned int index)
00414 {
00415 if (index < 0 || index > dataset->GetNDataPoints())
00416 return;
00417
00418 SetSingleDataPoint(dataset->GetDataPoint(index));
00419 }
00420
00421
00422 void BCModel::SetDataBoundaries(unsigned int index, double lowerboundary, double upperboundary, bool fixed)
00423 {
00424
00425 if (!fDataSet) {
00426 BCLog::OutError("BCModel::SetDataBoundaries : Need to define data set first.");
00427 return;
00428 }
00429
00430
00431 if (index < 0 || index > fDataSet->GetDataPoint(0)->GetNValues()) {
00432 BCLog::OutError("BCModel::SetDataBoundaries : Index out of range.");
00433 return;
00434 }
00435
00436
00437 if (!fDataPointLowerBoundaries)
00438 fDataPointLowerBoundaries = new BCDataPoint(fDataSet->GetDataPoint(0)->GetNValues());
00439
00440 if (!fDataPointUpperBoundaries)
00441 fDataPointUpperBoundaries = new BCDataPoint(fDataSet->GetDataPoint(0)->GetNValues());
00442
00443 if (fDataFixedValues.size() == 0)
00444 fDataFixedValues.assign(fDataSet->GetDataPoint(0)->GetNValues(), false);
00445
00446
00447 fDataPointLowerBoundaries->SetValue(index, lowerboundary);
00448 fDataPointUpperBoundaries->SetValue(index, upperboundary);
00449 fDataFixedValues[index] = fixed;
00450 }
00451
00452
00453 void BCModel::SetErrorBandContinuous(bool flag)
00454 {
00455 fErrorBandContinuous = flag;
00456
00457 if (flag)
00458 return;
00459
00460
00461 fErrorBandX.clear();
00462
00463
00464 for (unsigned int i = 0; i < fDataSet->GetNDataPoints(); ++i)
00465 fErrorBandX.push_back(fDataSet->GetDataPoint(i)->GetValue(fFitFunctionIndexX));
00466 }
00467
00468
00469 int BCModel::AddParameter(const char * name, double lowerlimit, double upperlimit)
00470 {
00471
00472 BCParameter * parameter = new BCParameter(name, lowerlimit, upperlimit);
00473
00474 int flag_ok = AddParameter(parameter);
00475 if (flag_ok)
00476 delete parameter;
00477
00478 return flag_ok;
00479 }
00480
00481
00482 int BCModel::AddParameter(BCParameter * parameter)
00483 {
00484
00485 if (!fParameterSet) {
00486 BCLog::OutError("BCModel::AddParameter : Parameter set does not exist");
00487 return ERROR_PARAMETERSETDOESNOTEXIST;
00488 }
00489
00490
00491 int flag_exists = 0;
00492 for (unsigned int i = 0; i < GetNParameters(); i++)
00493 if (CompareStrings(parameter->GetName().data(), GetParameter(i)->GetName().data()) == 0)
00494 flag_exists = -1;
00495
00496 if (flag_exists < 0) {
00497 BCLog::OutError(Form(
00498 "BCModel::AddParameter : Parameter with name %s exists already. ",
00499 parameter->GetName().data()));
00500 return ERROR_PARAMETEREXISTSALREADY;
00501 }
00502
00503
00504 unsigned int index = fParameterSet->size();
00505 parameter->SetIndex(index);
00506
00507
00508 fParameterSet->push_back(parameter);
00509
00510
00511 fPriorContainer.push_back(0);
00512
00513
00514 fPriorContainerInterpolate.push_back(false);
00515
00516
00517 fPriorContainerConstant.push_back(false);
00518
00519
00520 SetParameters(fParameterSet);
00521
00522
00523 ResetResults();
00524
00525 return 0;
00526 }
00527
00528
00529 double BCModel::LogProbabilityNN(std::vector<double> parameters)
00530 {
00531
00532 double logprob = LogLikelihood(parameters);
00533
00534
00535 if(fPriorConstantAll)
00536 logprob += fPriorConstantValue;
00537 else
00538 logprob += LogAPrioriProbability(parameters);
00539
00540 return logprob;
00541 }
00542
00543
00544 double BCModel::LogProbability(std::vector<double> parameters)
00545 {
00546
00547 if (fNormalization < 0. || fNormalization == 0.) {
00548 BCLog::OutError("BCModel::LogProbability. Normalization not available or zero.");
00549 return 0.;
00550 }
00551
00552 return LogProbabilityNN(parameters) - log(fNormalization);
00553 }
00554
00555
00556 double BCModel::LogLikelihood(std::vector<double> parameters)
00557 {
00558 double logprob = 0.;
00559
00560
00561 for (unsigned int i = 0; i < fDataSet->GetNDataPoints(); i++) {
00562 BCDataPoint * datapoint = GetDataPoint(i);
00563 logprob += LogConditionalProbabilityEntry(datapoint, parameters);
00564 }
00565
00566 return logprob;
00567 }
00568
00569
00570 double BCModel::LogAPrioriProbability(std::vector<double> parameters)
00571 {
00572 double logprob = 0;
00573
00574
00575 int npar = GetNParameters();
00576
00577
00578 for (int i = 0; i < npar; ++i) {
00579 if (fPriorContainer[i]) {
00580
00581 TF1 * f = dynamic_cast<TF1*>(fPriorContainer[i]);
00582 TH1 * h = dynamic_cast<TH1*>(fPriorContainer[i]);
00583
00584 if (f)
00585 logprob += log(f->Eval(parameters[i]));
00586 else if (h) {
00587 if(fPriorContainerInterpolate[i])
00588 logprob += log(h->Interpolate(parameters[i]));
00589 else
00590 logprob += log(h->GetBinContent(h->FindBin(parameters[i])));
00591 }
00592 else
00593 BCLog::OutError(Form(
00594 "BCModel::LogAPrioriProbability : Prior for parameter %s "
00595 "is defined but not recodnized.",
00596 GetParameter(i)->GetName().c_str()));
00597 }
00598
00599 else if (!fPriorContainerConstant[i]) {
00600 BCLog::OutWarning(Form(
00601 "BCModel::LogAPrioriProbability: Prior for parameter %s "
00602 "is undefined. Using constant prior to proceed.",
00603 GetParameter(i)->GetName().c_str()));
00604 logprob -= log(GetParameter(i)->GetRangeWidth());
00605 }
00606 }
00607
00608
00609 logprob += fPriorConstantValue;
00610
00611 return logprob;
00612 }
00613
00614
00615 double BCModel::LogEval(std::vector<double> parameters)
00616 {
00617 return LogProbabilityNN(parameters);
00618 }
00619
00620
00621 double BCModel::EvalSampling(std::vector<double> parameters)
00622 {
00623 return SamplingFunction(parameters);
00624 }
00625
00626
00627 double BCModel::SamplingFunction(std::vector<double> parameters)
00628 {
00629 double probability = 1.;
00630 for (std::vector<BCParameter *>::const_iterator it = fParameterSet->begin(); it != fParameterSet->end(); ++it)
00631 probability *= 1. / ((*it)->GetUpperLimit() - (*it)->GetLowerLimit());
00632 return probability;
00633 }
00634
00635
00636 double BCModel::Normalize()
00637 {
00638 if(fParameterSet->size()<1) {
00639 BCLog::OutError(Form("Normalize : No parameters defined in model \'%s\'. Aborting.",GetName().data()));
00640 return -1.;
00641 }
00642
00643 BCLog::OutSummary(Form("Model \'%s\': Normalizing probability",GetName().data()));
00644
00645 unsigned int n = GetNvar();
00646
00647
00648 if (n == 0) {
00649 SetParameters(fParameterSet);
00650 n = GetNvar();
00651 }
00652
00653
00654
00655 fNormalization = Integrate();
00656
00657 BCLog::OutDetail(Form(" --> Normalization factor : %.6g", fNormalization));
00658
00659 return fNormalization;
00660 }
00661
00662
00663 int BCModel::CheckParameters(std::vector<double> parameters)
00664 {
00665
00666 if (!parameters.size() == fParameterSet->size())
00667 return ERROR_INVALIDNUMBEROFPARAMETERS;
00668
00669
00670 for (unsigned int i = 0; i < fParameterSet->size(); i++) {
00671 BCParameter * modelparameter = fParameterSet->at(i);
00672
00673 if (modelparameter->GetLowerLimit() > parameters.at(i)
00674 || modelparameter->GetUpperLimit() < parameters.at(i)) {
00675 BCLog::OutError(Form(
00676 "BCModel::CheckParameters : Parameter %s not within limits.",
00677 fParameterSet-> at(i)-> GetName().data()));
00678 return ERROR_PARAMETERNOTWITHINRANGE;
00679 }
00680 }
00681
00682 return 0;
00683 }
00684
00685
00686 void BCModel::FindMode(std::vector<double> start)
00687 {
00688 if(fParameterSet->size()<1) {
00689 BCLog::OutError(Form("FindMode : No parameters defined in model \'%s\'. Aborting.",GetName().data()));
00690 return;
00691 }
00692
00693
00694
00695 BCLog::OutSummary(Form("Model \'%s\': Finding mode using %s",GetName().data(), DumpOptimizationMethod().c_str()));
00696
00697
00698 SetParameters(fParameterSet);
00699
00700 switch (GetOptimizationMethod()) {
00701 case BCIntegrate::kOptSA:
00702 FindModeSA(start);
00703 return;
00704
00705 case BCIntegrate::kOptMinuit: {
00706 int printlevel = -1;
00707 if (BCLog::GetLogLevelScreen() <= BCLog::detail)
00708 printlevel = 0;
00709 if (BCLog::GetLogLevelScreen() <= BCLog::debug)
00710 printlevel = 1;
00711 BCIntegrate::FindModeMinuit(start, printlevel);
00712 return;
00713 }
00714
00715 case BCIntegrate::kOptMetropolis:
00716 MarginalizeAll();
00717 return;
00718
00719 default:
00720 BCLog::OutError(Form("BCModel::FindMode : Invalid mode finding method: %d",GetOptimizationMethod()));
00721 }
00722
00723
00724 return;
00725 }
00726
00727
00728 void BCModel::FindModeMinuit(std::vector<double> start, int printlevel)
00729 {
00730 if(fParameterSet->size()<1) {
00731 BCLog::OutError(Form("FindModeMinuit : No parameters defined in model \'%s\'. Aborting.",GetName().data()));
00732 return;
00733 }
00734
00735
00736 SetParameters(fParameterSet);
00737 BCIntegrate::FindModeMinuit(start, printlevel);
00738 }
00739
00740
00741 void BCModel::WriteMode(const char * file)
00742 {
00743 ofstream ofi(file);
00744 if (!ofi.is_open()) {
00745 std::cerr << "Couldn't open file " << file << std::endl;
00746 return;
00747 }
00748
00749 int npar = fParameterSet->size();
00750 for (int i = 0; i < npar; i++)
00751 ofi << fBestFitParameters.at(i) << std::endl;
00752
00753 ofi << std::endl;
00754 ofi << "#######################################################################"
00755 << std::endl;
00756 ofi << "#" << std::endl;
00757 ofi << "# This file was created automatically by BCModel::WriteMode() call."
00758 << std::endl;
00759 ofi << "# It can be read in by call to BCModel::ReadMode()." << std::endl;
00760 ofi << "# Do not modify it unless you know what you're doing." << std::endl;
00761 ofi << "#" << std::endl;
00762 ofi << "#######################################################################"
00763 << std::endl;
00764 ofi << "#" << std::endl;
00765 ofi << "# Best fit parameters (mode) for model:" << std::endl;
00766 ofi << "# \'" << fName.data() << "\'" << std::endl;
00767 ofi << "#" << std::endl;
00768 ofi << "# Number of parameters: " << npar << std::endl;
00769 ofi << "# Parameters ordered as above:" << std::endl;
00770
00771 for (int i = 0; i < npar; i++) {
00772 ofi << "# " << i << ": ";
00773 ofi << fParameterSet->at(i)->GetName().data() << " = ";
00774 ofi << fBestFitParameters.at(i) << std::endl;
00775 }
00776
00777 ofi << "#" << std::endl;
00778 ofi << "########################################################################"
00779 << std::endl;
00780 }
00781
00782
00783 int BCModel::ReadMode(const char * file)
00784 {
00785 ifstream ifi(file);
00786 if (!ifi.is_open()) {
00787 BCLog::OutError(Form("BCModel::ReadMode : Couldn't open file %s.", file));
00788 return 0;
00789 }
00790
00791 int npar = fParameterSet->size();
00792 std::vector<double> mode;
00793
00794 int i = 0;
00795 while (i < npar && !ifi.eof()) {
00796 double a;
00797 ifi >> a;
00798 mode.push_back(a);
00799 i++;
00800 }
00801
00802 if (i < npar) {
00803 BCLog::OutError(Form("BCModel::ReadMode : Couldn't read mode from file %s.", file));
00804 BCLog::OutError(Form("BCModel::ReadMode : Expected %d parameters, found %d.", npar, i));
00805 return 0;
00806 }
00807
00808 BCLog::OutSummary(
00809 Form("# Read in best fit parameters (mode) for model \'%s\' from file %s:",
00810 fName.data(), file));
00811 SetMode(mode);
00812 for (int j = 0; j < npar; j++)
00813 BCLog::OutSummary(Form("# ->Parameter %d : %s = %e", j,
00814 fParameterSet->at(j)->GetName().data(), fBestFitParameters[j]));
00815
00816 BCLog::OutWarning("# ! Best fit values obtained before this call will be overwritten !");
00817
00818 return npar;
00819 }
00820
00821
00822 int BCModel::MarginalizeAll()
00823 {
00824 if(fParameterSet->size()<1) {
00825 BCLog::OutError(Form("MarginalizeAll : No parameters defined in model \'%s\'. Aborting.",GetName().data()));
00826 return 0;
00827 }
00828
00829 BCLog::OutSummary(Form("Running MCMC for model \'%s\'",GetName().data()));
00830
00831
00832 double dx = 0.;
00833 double dy = 0.;
00834
00835 if (fFitFunctionIndexX >= 0) {
00836 dx = (fDataPointUpperBoundaries->GetValue(fFitFunctionIndexX)
00837 - fDataPointLowerBoundaries->GetValue(fFitFunctionIndexX))
00838 / (double) fErrorBandNbinsX;
00839
00840 dy = (fDataPointUpperBoundaries->GetValue(fFitFunctionIndexY)
00841 - fDataPointLowerBoundaries->GetValue(fFitFunctionIndexY))
00842 / (double) fErrorBandNbinsY;
00843
00844 fErrorBandXY
00845 = new TH2D(TString::Format("errorbandxy_%d", BCLog::GetHIndex()), "",
00846 fErrorBandNbinsX,
00847 fDataPointLowerBoundaries->GetValue(fFitFunctionIndexX) - .5 * dx,
00848 fDataPointUpperBoundaries->GetValue(fFitFunctionIndexX) + .5 * dx,
00849 fErrorBandNbinsY,
00850 fDataPointLowerBoundaries->GetValue(fFitFunctionIndexY) - .5 * dy,
00851 fDataPointUpperBoundaries->GetValue(fFitFunctionIndexY) + .5 * dy);
00852 fErrorBandXY->SetStats(kFALSE);
00853
00854 for (int ix = 1; ix <= fErrorBandNbinsX; ++ix)
00855 for (int iy = 1; iy <= fErrorBandNbinsX; ++iy)
00856 fErrorBandXY->SetBinContent(ix, iy, 0.);
00857 }
00858
00859 MCMCMetropolis();
00860 FindModeMCMC();
00861
00862
00863
00864 return 1;
00865 }
00866
00867
00868 BCH1D * BCModel::GetMarginalized(BCParameter * parameter)
00869 {
00870 if (!parameter) {
00871
00872
00873 return 0;
00874 }
00875
00876 int index = parameter->GetIndex();
00877 if (fMCMCFlagsFillHistograms[index] == false) {
00878
00879
00880
00881
00882 return 0;
00883 }
00884
00885
00886 TH1D * hist = MCMCGetH1Marginalized(index);
00887 if (!hist)
00888 return 0;
00889
00890
00891 hist->SetName(Form("hist_%s_%s", GetName().data(), parameter->GetName().data()));
00892 hist->SetXTitle(parameter->GetName().data());
00893 hist->SetYTitle(Form("p(%s|data)", parameter->GetName().data()));
00894 hist->SetStats(kFALSE);
00895
00896
00897 BCH1D * hprob = new BCH1D();
00898 hprob->SetHistogram(hist);
00899
00900
00901 double bestfit = hprob->GetMode();
00902
00903 if (fBestFitParametersMarginalized.size() == 0)
00904 for (unsigned int i = 0; i < GetNParameters(); i++)
00905 fBestFitParametersMarginalized.push_back(0.);
00906
00907 fBestFitParametersMarginalized[index] = bestfit;
00908
00909 hprob->SetGlobalMode(fBestFitParameters.at(index));
00910
00911 return hprob;
00912 }
00913
00914
00915 int BCModel::ReadMarginalizedFromFile(const char * file)
00916 {
00917 TFile * froot = new TFile(file);
00918 if (!froot->IsOpen()) {
00919 BCLog::OutError(Form("BCModel::ReadMarginalizedFromFile : Couldn't open file %s.", file));
00920 return 0;
00921 }
00922
00923
00924
00925
00926
00927
00928
00929 MCMCInitialize();
00930
00931 int k = 0;
00932 int n = GetNParameters();
00933 for (int i = 0; i < n; i++) {
00934 BCParameter * a = GetParameter(i);
00935 TKey * key = froot->GetKey(TString::Format("hist_%s_%s",GetName().data(), a->GetName().data()));
00936 if (key) {
00937 TH1D * h1 = (TH1D*) key->ReadObjectAny(TH1D::Class());
00938 h1->SetDirectory(0);
00939 if (SetMarginalized(i, h1))
00940 k++;
00941 }
00942 else
00943 BCLog::OutWarning(
00944 Form("BCModel::ReadMarginalizedFromFile : Couldn't read histogram \"hist_%s_%s\" from file %s.",
00945 GetName().data(), a->GetName().data(), file));
00946 }
00947
00948 for (int i = 0; i < n - 1; i++) {
00949 for (int j = i + 1; j < n; j++) {
00950 BCParameter * a = GetParameter(i);
00951 BCParameter * b = GetParameter(j);
00952 TKey * key = froot->GetKey(
00953 TString::Format("hist_%s_%s_%s",GetName().data(), a->GetName().data(),b->GetName().data()));
00954 if (key) {
00955 TH2D * h2 = (TH2D*) key->ReadObjectAny(TH2D::Class());
00956 h2->SetDirectory(0);
00957 if (SetMarginalized(i, j, h2))
00958 k++;
00959 }
00960 else
00961 BCLog::OutWarning(
00962 Form("BCModel::ReadMarginalizedFromFile : Couldn't read histogram \"hist_%s_%s_%s\" from file %s.",
00963 GetName().data(), a->GetName().data(), b->GetName().data(), file));
00964 }
00965 }
00966
00967 froot->Close();
00968
00969 return k;
00970 }
00971
00972
00973 int BCModel::ReadErrorBandFromFile(const char * file)
00974 {
00975 TFile * froot = new TFile(file);
00976 if (!froot->IsOpen()) {
00977 BCLog::OutError(Form("BCModel::ReadErrorBandFromFile. Couldn't open file %s.", file));
00978 return 0;
00979 }
00980
00981 int r = 0;
00982
00983 TH2D * h2 = (TH2D*) froot->Get("errorbandxy");
00984 if (h2) {
00985 h2->SetDirectory(0);
00986 h2->SetName(TString::Format("errorbandxy_%d", BCLog::GetHIndex()));
00987 SetErrorBandHisto(h2);
00988 r = 1;
00989 }
00990 else
00991 BCLog::OutWarning(
00992 Form("BCModel::ReadErrorBandFromFile : Couldn't read histogram \"errorbandxy\" from file %s.",file));
00993
00994 froot->Close();
00995
00996 return r;
00997 }
00998
00999
01000 int BCModel::PrintAllMarginalized1D(const char * filebase)
01001 {
01002 if (fMCMCH1Marginalized.size() == 0) {
01003 BCLog::OutError("BCModel::PrintAllMarginalized : Marginalized distributions not available.");
01004 return 0;
01005 }
01006
01007 int n = GetNParameters();
01008 for (int i = 0; i < n; i++) {
01009 BCParameter * a = GetParameter(i);
01010 if (GetMarginalized(a))
01011 GetMarginalized(a)->Print(Form("%s_1D_%s.ps", filebase, a->GetName().data()));
01012 }
01013
01014 return n;
01015 }
01016
01017
01018 int BCModel::PrintAllMarginalized2D(const char * filebase)
01019 {
01020 if (fMCMCH2Marginalized.size() == 0) {
01021 BCLog::OutError("BCModel::PrintAllMarginalized : Marginalized distributions not available.");
01022 return 0;
01023 }
01024
01025 int k = 0;
01026 int n = GetNParameters();
01027 for (int i = 0; i < n - 1; i++) {
01028 for (int j = i + 1; j < n; j++) {
01029 BCParameter * a = GetParameter(i);
01030 BCParameter * b = GetParameter(j);
01031
01032 double meana = (a->GetLowerLimit() + a->GetUpperLimit()) / 2.;
01033 double deltaa = (a->GetUpperLimit() - a->GetLowerLimit());
01034 if (deltaa <= 1e-7 * meana)
01035 continue;
01036
01037 double meanb = (b->GetLowerLimit() + b->GetUpperLimit()) / 2.;
01038 double deltab = (b->GetUpperLimit() - b->GetLowerLimit());
01039 if (deltab <= 1e-7 * meanb)
01040 continue;
01041
01042 if (GetMarginalized(a, b))
01043 GetMarginalized(a, b)->Print(
01044 Form("%s_2D_%s_%s.ps",filebase, a->GetName().data(), b->GetName().data()));
01045 k++;
01046 }
01047 }
01048
01049 return k;
01050 }
01051
01052
01053 int BCModel::PrintAllMarginalized(const char * file, unsigned int hdiv, unsigned int vdiv)
01054 {
01055 if (!fMCMCFlagFillHistograms) {
01056 BCLog::OutError("BCModel::PrintAllMarginalized : Marginalized distributions not filled.");
01057 return 0;
01058 }
01059
01060 int npar = GetNParameters();
01061
01062 if (fMCMCH1Marginalized.size() == 0 || (fMCMCH2Marginalized.size() == 0
01063 && npar > 1)) {
01064 BCLog::OutError(
01065 "BCModel::PrintAllMarginalized : Marginalized distributions not available.");
01066 return 0;
01067 }
01068
01069
01070 if (fMCMCH1Marginalized.size() == 1 && fMCMCH2Marginalized.size() == 0) {
01071 BCParameter * a = GetParameter(0);
01072 if (GetMarginalized(a))
01073 GetMarginalized(a)->Print(file);
01074 return 1;
01075 }
01076
01077 int c_width = 600;
01078 int c_height = 600;
01079
01080 int type = 112;
01081
01082 if (hdiv > vdiv) {
01083 if (hdiv > 3) {
01084 c_width = 1000;
01085 c_height = 700;
01086 }
01087 else {
01088 c_width = 800;
01089 c_height = 600;
01090 }
01091 }
01092 else if (hdiv < vdiv) {
01093 if (hdiv > 3) {
01094 c_height = 1000;
01095 c_width = 700;
01096 }
01097 else {
01098 c_height = 800;
01099 c_width = 600;
01100 }
01101 type = 111;
01102 }
01103
01104
01105 int nplots2d = npar * (npar - 1) / 2;
01106 int nplots = npar + nplots2d;
01107
01108
01109 BCLog::OutSummary(
01110 Form(
01111 "Printing all marginalized distributions (%d x 1D + %d x 2D = %d) into file %s",
01112 npar, nplots2d, nplots, file));
01113 if (nplots > 100)
01114 BCLog::OutDetail("This can take a while...");
01115
01116
01117 TCanvas * c = new TCanvas("c", "canvas", c_width, c_height);
01118
01119 TPostScript * ps = new TPostScript(file, type);
01120
01121 if (type == 112)
01122 ps->Range(24, 16);
01123 else
01124 ps->Range(16, 24);
01125
01126
01127 ps->NewPage();
01128 c->cd();
01129 c->Clear();
01130 c->Divide(hdiv, vdiv);
01131
01132 int n = 0;
01133 for (int i = 0; i < npar; i++) {
01134
01135 BCParameter * a = GetParameter(i);
01136
01137
01138 if (!GetMarginalized(a))
01139 continue;
01140
01141
01142 if (GetMarginalized(a)->GetHistogram()->Integral() <= 0)
01143 continue;
01144
01145
01146 if (i != 0 && i % (hdiv * vdiv) == 0) {
01147 c->Update();
01148 ps->NewPage();
01149 c->cd();
01150 c->Clear();
01151 c->Divide(hdiv, vdiv);
01152 }
01153
01154
01155 c->cd(i % (hdiv * vdiv) + 1);
01156
01157 GetMarginalized(a)->Draw();
01158 n++;
01159
01160 if (n % 100 == 0)
01161 BCLog::OutDetail(Form(" --> %d plots done", n));
01162 }
01163
01164 if (n > 0) {
01165 c->Update();
01166
01167
01168 ps->NewPage();
01169 c->cd();
01170 c->Clear();
01171 }
01172
01173 c->Divide(hdiv, vdiv);
01174
01175 int k = 0;
01176 for (int i = 0; i < npar - 1; i++) {
01177 if (!fMCMCFlagsFillHistograms[i])
01178 continue;
01179 for (int j = i + 1; j < npar; j++) {
01180 if (!fMCMCFlagsFillHistograms[j])
01181 continue;
01182
01183
01184 BCParameter * a = GetParameter(i);
01185 BCParameter * b = GetParameter(j);
01186
01187
01188 if (!GetMarginalized(a, b))
01189 continue;
01190
01191
01192 if (GetMarginalized(a, b)->GetHistogram()->Integral() <= 0)
01193 continue;
01194
01195
01196 if (k != 0 && k % (hdiv * vdiv) == 0) {
01197 c->Update();
01198 ps->NewPage();
01199 c->cd();
01200 c->Clear();
01201 c->Divide(hdiv, vdiv);
01202 }
01203
01204
01205 c->cd(k % (hdiv * vdiv) + 1);
01206
01207 double meana = (a->GetLowerLimit() + a->GetUpperLimit()) / 2.;
01208 double deltaa = (a->GetUpperLimit() - a->GetLowerLimit());
01209 if (deltaa <= 1e-7 * meana)
01210 continue;
01211
01212 double meanb = (b->GetLowerLimit() + b->GetUpperLimit()) / 2.;
01213 double deltab = (b->GetUpperLimit() - b->GetLowerLimit());
01214 if (deltab <= 1e-7 * meanb)
01215 continue;
01216
01217 GetMarginalized(a, b)->Draw(52);
01218 k++;
01219
01220 if ((n + k) % 100 == 0)
01221 BCLog::OutDetail(Form(" --> %d plots done", n + k));
01222 }
01223 }
01224
01225 if ((n + k) > 100 && (n + k) % 100 != 0)
01226 BCLog::OutDetail(Form(" --> %d plots done", n + k));
01227
01228 c->Update();
01229 ps->Close();
01230
01231 delete c;
01232 delete ps;
01233
01234
01235 return n + k;
01236 }
01237
01238
01239 BCH2D * BCModel::GetMarginalized(BCParameter * par1, BCParameter * par2)
01240 {
01241 int index1 = par1->GetIndex();
01242 int index2 = par2->GetIndex();
01243
01244 if (fMCMCFlagsFillHistograms[index1] == false || fMCMCFlagsFillHistograms[index2] == false) {
01245
01246
01247
01248
01249 return 0;
01250 }
01251
01252 if (index1 == index2) {
01253
01254
01255 return 0;
01256 }
01257
01258 BCParameter * npar1 = par1;
01259 BCParameter * npar2 = par2;
01260
01261 if (index1 > index2) {
01262 npar1 = par2;
01263 npar2 = par1;
01264
01265 int itmp = index1;
01266 index1 = index2;
01267 index2 = itmp;
01268 }
01269
01270
01271 TH2D * hist = MCMCGetH2Marginalized(index1, index2);
01272
01273 if (hist == 0)
01274 return 0;
01275
01276 BCH2D * hprob = new BCH2D();
01277
01278
01279 hist->SetName(Form("hist_%s_%s_%s", GetName().data(), npar1->GetName().data(), npar2->GetName().data()));
01280 hist->SetXTitle(Form("%s", npar1->GetName().data()));
01281 hist->SetYTitle(Form("%s", npar2->GetName().data()));
01282 hist->SetStats(kFALSE);
01283
01284 double gmode[] = { fBestFitParameters.at(index1), fBestFitParameters.at(index2) };
01285 hprob->SetGlobalMode(gmode);
01286
01287
01288 hprob->SetHistogram(hist);
01289
01290 return hprob;
01291 }
01292
01293
01294 double BCModel::GetPvalueFromChi2(std::vector<double> par, int sigma_index)
01295 {
01296 double ll = LogLikelihood(par);
01297 int n = GetNDataPoints();
01298
01299 double sum_sigma = 0;
01300 for (int i = 0; i < n; i++)
01301 sum_sigma += log(GetDataPoint(i)->GetValue(sigma_index));
01302
01303 double chi2 = -2. * (ll + (double) n / 2. * log(2. * M_PI) + sum_sigma);
01304
01305 fPValue = TMath::Prob(chi2, n);
01306
01307 return fPValue;
01308 }
01309
01310
01311 std::vector<double> BCModel::GetChi2Runs(int dataIndex, int sigmaIndex)
01312 {
01313 std::vector<double> x;
01314 return x;
01315 }
01316
01317
01318 double BCModel::GetPvalueFromChi2Johnson(std::vector<double> par)
01319 {
01320 double chi2 = GetChi2Johnson(par);
01321
01322 fPValue = TMath::Prob(chi2, NumberBins() - 1);
01323 return fPValue;
01324 }
01325
01326
01327 double BCModel::GetChi2Johnson(std::vector<double> par, int nBins)
01328 {
01329 typedef unsigned int uint;
01330
01331
01332 int n = GetNDataPoints();
01333
01334 if (nBins < 0)
01335 nBins = NumberBins();
01336
01337
01338 std::vector<double> a;
01339 for (int i = 0; i <= nBins; i++)
01340 a.push_back(i / double(nBins));
01341
01342
01343 TH1I * hist = new TH1I("h1", "h1 title", nBins, 0., 1.);
01344
01345
01346
01347 if (flag_discrete) {
01348
01349 for (int j = 0; j < n; j++) {
01350
01351 double CDFval = CDF(par, j, false);
01352
01353 double CDFlower = CDF(par, j, true);
01354
01355
01356 int qMax = 1;
01357 for (int i = 0; i < nBins; i++) {
01358 if (CDFval > a[i])
01359 qMax = i + 1;
01360 else
01361 break;
01362 }
01363 int qMin = 1;
01364 for (int i = 0; i < nBins; i++) {
01365 if (CDFlower > a[i])
01366 qMin = i + 1;
01367 else
01368 break;
01369 }
01370
01371
01372 if (qMin == qMax) {
01373
01374 if (CDFval < 1)
01375 hist->Fill(CDFval);
01376 else
01377 hist->AddBinContent(qMax);
01378
01379 continue;
01380 }
01381
01382
01383
01384
01385
01386
01387
01388 std::vector<double> prob;
01389
01390 double norm = 1 / double(CDFval - CDFlower);
01391
01392 for (int i = 0; i < (qMax - qMin + 1); i++) {
01393 if (i == 0) {
01394 prob.push_back(norm * (a[qMin] - CDFlower));
01395 continue;
01396 }
01397 if (i == (qMax - qMin)) {
01398 prob.push_back(norm * (CDFval - a[qMax - 1]));
01399 continue;
01400 }
01401
01402 prob.push_back(norm * (a[i] - a[i - 1]));
01403 }
01404
01405 double U = fRandom->Rndm();
01406
01407 for (uint i = 1; i < prob.size(); i++)
01408 prob[i] += prob[i - 1];
01409
01410 for (uint i = 0; i < prob.size(); i++) {
01411
01412 if (U <= prob[i]) {
01413 hist->Fill((a[qMin + i - 1] + a[qMin + i]) / 2.);
01414 break;
01415 }
01416 }
01417 }
01418 }
01419 else {
01420 for (int j = 0; j < n; j++)
01421 hist->Fill(CDF(par, j, false));
01422 }
01423
01424
01425 double chi2 = 0.;
01426 double mk, pk;
01427 double N = double(n);
01428 for (int i = 1; i <= nBins; i++) {
01429 mk = hist->GetBinContent(i);
01430 pk = a[i] - a[i - 1];
01431 chi2 += (mk - N * pk) * (mk - N * pk) / (N * pk);
01432 }
01433
01434 delete hist;
01435
01436 return chi2;
01437 }
01438
01439
01440 double BCModel::GetAvalueFromChi2Johnson(TTree * tree, TH1D * distribution)
01441 {
01442
01443 int nPar = (int)GetNParameters();
01444 std::vector<double> param(nPar);
01445
01446
01447 int nParBranches = -1;
01448 tree->SetBranchAddress("fNParameters", &nParBranches);
01449
01450
01451 tree->GetEntry(0);
01452 if (nParBranches != nPar) {
01453 BCLog::OutError(Form(
01454 "Cannot compute A value: number of parameters in tree (%d)"
01455 "doesn't match number of parameters in model (%d)",
01456 nParBranches, nPar));
01457 return -1.;
01458 }
01459
01460
01461 char * branchName = new char[10 + nPar];
01462
01463
01464 for (int i = 0; i < (int) nPar; i++) {
01465 +sprintf(branchName, "fParameter%d", i);
01466 tree->SetBranchAddress(branchName, ¶m[i]);
01467 }
01468
01469
01470 long nEntries = tree->GetEntries();
01471
01472
01473 std::vector<double> randoms(nEntries);
01474 int K = NumberBins();
01475 BCMath::RandomChi2(randoms, K - 1);
01476
01477
01478 int nBigger = 0;
01479 for (int i = 0; i < nEntries; i++) {
01480 tree->GetEntry(i);
01481 double chi2 = GetChi2Johnson(param);
01482 if (distribution != 0)
01483 distribution->Fill(chi2);
01484
01485 if (chi2 > randoms[i])
01486 nBigger++;
01487 }
01488
01489 return nBigger / double(nEntries);
01490 }
01491
01492
01493 double BCModel::GetPvalueFromChi2NDoF(std::vector<double> par, int sigma_index)
01494 {
01495 double ll = LogLikelihood(par);
01496 int n = GetNDataPoints();
01497 int npar = GetNParameters();
01498
01499 double sum_sigma = 0;
01500 for (int i = 0; i < n; i++)
01501 sum_sigma += log(GetDataPoint(i)->GetValue(sigma_index));
01502
01503 double chi2 = -2. * (ll + (double) n / 2. * log(2. * M_PI) + sum_sigma);
01504
01505 fChi2NDoF = chi2 / double(n - npar);
01506 fPValueNDoF = TMath::Prob(chi2, n - npar);
01507
01508 return fPValueNDoF;
01509 }
01510
01511
01512 double BCModel::GetPvalueFromKolmogorov(const std::vector<double>& par,int index)
01513 {
01514 if (flag_discrete) {
01515 BCLog::OutError(Form("BCModel::GetPvalueFromKolmogorov : "
01516 "test defined only for continuous distributions."));
01517 return -1.;
01518 }
01519
01520
01521 std::vector<double> yData = fDataSet->GetDataComponents(index);
01522 TH1D * ECDF = BCMath::ECDF(yData);
01523
01524 int N = GetNDataPoints();
01525
01526
01527 std::set<double> uniqueObservations;
01528 for (int i = 0; i < N; i++)
01529 uniqueObservations.insert(CDF(par, i, false));
01530
01531 int nUnique = uniqueObservations.size();
01532 if (nUnique != ECDF->GetNbinsX() + 1) {
01533 BCLog::OutError(Form("BCModel::GetPvalueFromKolmogorov : "
01534 "Number of unique data points doesn't match (%d vs %d)", nUnique,
01535 ECDF->GetNbinsX() + 1));
01536 return -1.;
01537 }
01538
01539
01540 double distMax = 0.;
01541
01542
01543 double dist = 0.;
01544
01545 std::set<double>::const_iterator iter = uniqueObservations.begin();
01546 for (int iBin = 0; iBin < nUnique; ++iBin) {
01547
01548 dist = TMath::Abs(*iter - ECDF->GetBinContent(iBin + 1));
01549
01550 distMax = TMath::Max(dist, distMax);
01551
01552
01553
01554
01555
01556
01557 ++iter;
01558 }
01559
01560
01561
01562 double z = distMax * sqrt(N);
01563
01564 fPValue = TMath::KolmogorovProb(z);
01565
01566
01567
01568
01569
01570 delete ECDF;
01571
01572 return fPValue;
01573 }
01574
01575
01576 BCH1D * BCModel::CalculatePValue(std::vector<double> par, bool flag_histogram)
01577 {
01578 BCH1D * hist = 0;
01579
01580
01581 BCLog::OutSummary("Do goodness-of-fit-test");
01582
01583
01584 BCGoFTest * goftest = new BCGoFTest("modeltest");
01585
01586
01587 goftest->SetTestModel(this);
01588
01589
01590
01591 if (!goftest->SetTestPoint(par))
01592 return 0;
01593
01594
01595
01596 goftest->MCMCSetFlagFillHistograms(false);
01597
01598
01599 goftest->MCMCSetNChains(fGoFNChains);
01600 goftest->MCMCSetNIterationsMax(fGoFNIterationsMax);
01601 goftest->MCMCSetNIterationsRun(fGoFNIterationsRun);
01602
01603
01604 fPValue = goftest->GetCalculatedPValue(flag_histogram);
01605
01606
01607 if (flag_histogram) {
01608 hist = new BCH1D();
01609 hist->SetHistogram(goftest->GetHistogramLogProb());
01610 }
01611
01612
01613 delete goftest;
01614
01615
01616 return hist;
01617 }
01618
01619
01620 void BCModel::CorrelateDataPointValues(std::vector<double> &x)
01621 {
01622
01623 }
01624
01625
01626 double BCModel::HessianMatrixElement(BCParameter * par1, BCParameter * par2, std::vector<double> point)
01627 {
01628
01629 if (point.size() != GetNParameters()) {
01630 BCLog::OutError("BCModel::HessianMatrixElement : Invalid number of entries in the vector.");
01631 return -1;
01632 }
01633
01634
01635 double nsteps = 1e5;
01636 double dx1 = par1->GetRangeWidth() / nsteps;
01637 double dx2 = par2->GetRangeWidth() / nsteps;
01638
01639
01640 std::vector<double> xpp = point;
01641 std::vector<double> xpm = point;
01642 std::vector<double> xmp = point;
01643 std::vector<double> xmm = point;
01644
01645 int idx1 = par1->GetIndex();
01646 int idx2 = par2->GetIndex();
01647
01648 xpp[idx1] += dx1;
01649 xpp[idx2] += dx2;
01650
01651 xpm[idx1] += dx1;
01652 xpm[idx2] -= dx2;
01653
01654 xmp[idx1] -= dx1;
01655 xmp[idx2] += dx2;
01656
01657 xmm[idx1] -= dx1;
01658 xmm[idx2] -= dx2;
01659
01660
01661 double ppp = Likelihood(xpp);
01662 double ppm = Likelihood(xpm);
01663 double pmp = Likelihood(xmp);
01664 double pmm = Likelihood(xmm);
01665
01666
01667 return (ppp + pmm - ppm - pmp) / (4. * dx1 * dx2);
01668 }
01669
01670
01671 void BCModel::FixDataAxis(unsigned int index, bool fixed)
01672 {
01673
01674 if (index < 0 || index > fDataSet->GetDataPoint(0)->GetNValues()) {
01675 BCLog::OutError("BCModel::FixDataAxis : Index out of range.");
01676 return;
01677 }
01678
01679 if (fDataFixedValues.size() == 0)
01680 fDataFixedValues.assign(fDataSet->GetDataPoint(0)->GetNValues(),
01681 false);
01682
01683 fDataFixedValues[index] = fixed;
01684 }
01685
01686
01687 bool BCModel::GetFixedDataAxis(unsigned int index)
01688 {
01689
01690 if (index < 0 || index > fDataSet->GetDataPoint(0)->GetNValues()) {
01691 BCLog::OutError("BCModel::GetFixedDataAxis : Index out of range.");
01692 return false;
01693 }
01694
01695 return fDataFixedValues[index];
01696 }
01697
01698
01699 int BCModel::SetPrior(int index, TF1 * f)
01700 {
01701
01702 if (index < 0 && index >= int(GetNParameters())) {
01703 BCLog::OutError("BCModel::SetPrior : Index out of range.");
01704 return 0;
01705 }
01706
01707 if (fPriorContainer[index])
01708 delete fPriorContainer[index];
01709
01710
01711 fPriorContainer[index] = new TF1(*f);
01712
01713 fPriorContainerConstant[index] = false;
01714
01715 RecalculatePriorConstant();
01716
01717
01718 ResetResults();
01719
01720
01721 return 1;
01722 }
01723
01724
01725 int BCModel::SetPrior(const char * name, TF1 * f)
01726 {
01727
01728 int index = -1;
01729 for (unsigned int i = 0; i < GetNParameters(); i++)
01730 if (name == GetParameter(i)->GetName())
01731 index = i;
01732
01733
01734 return SetPrior(index, f);
01735 }
01736
01737
01738 int BCModel::SetPriorGauss(int index, double mean, double sigma)
01739 {
01740
01741 if (index < 0 || index >= int(GetNParameters())) {
01742 BCLog::OutError("BCModel::SetPriorGauss : Index out of range.");
01743 return 0;
01744 }
01745
01746
01747 TF1 * f = new TF1(Form("prior_%s", GetParameter(index)->GetName().c_str()),
01748 "1./sqrt(2.*TMath::Pi())/[1] * exp(- (x-[0])*(x-[0])/2./[1]/[1])",
01749 GetParameter(index)->GetLowerLimit(),
01750 GetParameter(index)->GetUpperLimit());
01751 f->SetParameter(0, mean);
01752 f->SetParameter(1, sigma);
01753
01754
01755 return SetPrior(index, f);
01756 }
01757
01758
01759 int BCModel::SetPriorGauss(const char* name, double mean, double sigma)
01760 {
01761
01762 int index = -1;
01763 for (unsigned int i = 0; i < GetNParameters(); i++)
01764 if (name == GetParameter(i)->GetName())
01765 index = i;
01766
01767
01768 return SetPriorGauss(index, mean, sigma);
01769 }
01770
01771
01772 int BCModel::SetPriorGauss(int index, double mean, double sigmadown, double sigmaup)
01773 {
01774
01775 if (index < 0 || index >= int(GetNParameters())) {
01776 BCLog::OutError("BCModel::SetPriorGauss : Index out of range.");
01777 return 0;
01778 }
01779
01780
01781 TF1 * f = new TF1(Form("prior_%s", GetParameter(index)->GetName().c_str()),
01782 BCMath::SplitGaussian,
01783 GetParameter(index)->GetLowerLimit(),
01784 GetParameter(index)->GetUpperLimit(),
01785 3);
01786 f->SetParameter(0, mean);
01787 f->SetParameter(1, sigmadown);
01788 f->SetParameter(2, sigmaup);
01789
01790
01791 return SetPrior(index, f);
01792
01793 return 0;
01794 }
01795
01796
01797 int BCModel::SetPriorGauss(const char * name, double mean, double sigmadown, double sigmaup)
01798 {
01799
01800 int index = -1;
01801 for (unsigned int i = 0; i < GetNParameters(); i++)
01802 if (name == GetParameter(i)->GetName())
01803 index = i;
01804
01805
01806 return SetPriorGauss(index, mean, sigmadown, sigmaup);
01807 }
01808
01809
01810 int BCModel::SetPrior(int index, TH1 * h, bool interpolate)
01811 {
01812
01813 if (index < 0 && index >= int(GetNParameters())) {
01814 BCLog::OutError("BCModel::SetPrior : Index out of range.");
01815 return 0;
01816 }
01817
01818
01819 if(h) {
01820
01821
01822 if (h->GetDimension() != 1) {
01823 BCLog::OutError(Form("BCModel::SetPrior : Histogram given for parameter %d is not 1D.",index));
01824 return 0;
01825 }
01826
01827
01828 h->Scale(1./h->Integral("width"));
01829
01830 if(fPriorContainer[index])
01831 delete fPriorContainer[index];
01832
01833
01834 fPriorContainer[index] = new TH1(*h);
01835
01836 if (interpolate)
01837 fPriorContainerInterpolate[index] = true;
01838
01839 fPriorContainerConstant[index] = false;
01840 }
01841
01842 RecalculatePriorConstant();
01843
01844
01845 ResetResults();
01846
01847
01848 return 1;
01849 }
01850
01851
01852 int BCModel::SetPrior(const char * name, TH1 * h, bool interpolate)
01853 {
01854
01855 int index = -1;
01856 for (unsigned int i = 0; i < GetNParameters(); i++)
01857 if (name == GetParameter(i)->GetName())
01858 index = i;
01859
01860
01861 return SetPrior(index, h, interpolate);
01862 }
01863
01864
01865 int BCModel::SetPriorConstant(int index)
01866 {
01867
01868 if (index < 0 && index >= int(GetNParameters())) {
01869 BCLog::OutError("BCModel::SetPriorConstant : Index out of range.");
01870 return 0;
01871 }
01872
01873 if(fPriorContainer[index]) {
01874 delete fPriorContainer[index];
01875 fPriorContainer[index] = 0;
01876 }
01877
01878
01879 fPriorContainerConstant[index] = true;
01880
01881 RecalculatePriorConstant();
01882
01883
01884 ResetResults();
01885
01886
01887 return 1;
01888 }
01889
01890
01891 int BCModel::SetPriorConstant(const char* name)
01892 {
01893
01894 int index = -1;
01895 for (unsigned int i = 0; i < GetNParameters(); i++) {
01896 if (name == GetParameter(i)->GetName()) {
01897 index = i;
01898 break;
01899 }
01900 }
01901
01902 if (index == -1) {
01903 BCLog::OutError(Form(
01904 "BCModel::SetPriorConstant : parameter '%s' doesn't exist.", name));
01905 return 0;
01906 }
01907
01908 return SetPriorConstant(index);
01909 }
01910
01911
01912 int BCModel::SetPriorConstantAll()
01913 {
01914
01915 int nPar = GetNParameters();
01916
01917 if (nPar == 0)
01918 BCLog::OutWarning("BCModel::SetPriorConstantAll : No parameters defined.");
01919
01920
01921 for (int i = 0; i < nPar; ++i) {
01922 if (fPriorContainer[i]) {
01923 delete fPriorContainer[i];
01924 fPriorContainer[i]=0;
01925 }
01926 fPriorContainerConstant[i] = true;
01927 }
01928
01929 RecalculatePriorConstant();
01930
01931
01932 ResetResults();
01933
01934
01935 return 1;
01936 }
01937
01938
01939 void BCModel::RecalculatePriorConstant()
01940 {
01941 fPriorConstantValue = 0.;
01942
01943
01944 int npar = GetNParameters();
01945
01946 int nconstant = 0;
01947
01948 for (int i=0; i<npar; ++i)
01949 if (fPriorContainerConstant[i]) {
01950 fPriorConstantValue -= log(GetParameter(i)->GetRangeWidth());
01951 ++nconstant;
01952 }
01953
01954 if (nconstant == npar)
01955 fPriorConstantAll = true;
01956 else
01957 fPriorConstantAll = false;
01958 }
01959
01960
01961 int BCModel::SetParameterRange(int index, double parmin, double parmax)
01962 {
01963
01964 if (index < 0 || index >= int(GetNParameters())) {
01965 BCLog::OutError("BCModel::SetParameterRange : Index out of range.");
01966 return 0;
01967 }
01968
01969
01970 GetParameter(index)->SetLowerLimit(parmin);
01971 GetParameter(index)->SetUpperLimit(parmax);
01972 fMCMCBoundaryMin[index] = parmin;
01973 fMCMCBoundaryMax[index] = parmax;
01974
01975
01976 ResetResults();
01977
01978
01979 return 1;
01980 }
01981
01982
01983 int BCModel::ResetResults()
01984 {
01985 BCIntegrate::IntegrateResetResults();
01986
01987 BCEngineMCMC::MCMCResetResults();
01988
01989
01990 return 1;
01991 }
01992
01993
01994 void BCModel::PrintSummary()
01995 {
01996 int nparameters = GetNParameters();
01997
01998
01999 std::cout << std::endl
02000 << " ---------------------------------" << std::endl
02001 << " Model : " << fName.data() << std::endl
02002 << " ---------------------------------" << std::endl
02003 << " Index : " << fIndex << std::endl
02004 << " Number of parameters : " << nparameters << std::endl << std::endl
02005 << " - Parameters : " << std::endl << std::endl;
02006
02007
02008 for (int i = 0; i < nparameters; i++)
02009 fParameterSet->at(i)->PrintSummary();
02010
02011
02012 if (GetBestFitParameters().size() > 0) {
02013 std::cout << std::endl << " - Best fit parameters :" << std::endl << std::endl;
02014
02015 for (int i = 0; i < nparameters; i++) {
02016 std::cout << " " << fParameterSet->at(i)->GetName().data()
02017 << " = " << GetBestFitParameter(i) << " (overall)" << std::endl;
02018 if ((int) fBestFitParametersMarginalized.size() == nparameters)
02019 std::cout << " "
02020 << fParameterSet->at(i)->GetName().data() << " = "
02021 << GetBestFitParameterMarginalized(i)
02022 << " (marginalized)" << std::endl;
02023 }
02024 }
02025
02026 std::cout << std::endl;
02027
02028
02029 if (fPValue >= 0) {
02030 double likelihood = Likelihood(GetBestFitParameters());
02031 std::cout << " - Model testing:" << std::endl << std::endl
02032 << " p(data|lambda*) = " << likelihood << std::endl
02033 << " p-value = " << fPValue << std::endl << std::endl;
02034 }
02035
02036
02037 if (fNormalization > 0)
02038 std::cout << " Normalization : " << fNormalization << std::endl;
02039 }
02040
02041
02042 void BCModel::PrintResults(const char * file)
02043 {
02044
02045
02046
02047 ofstream ofi(file);
02048
02049
02050 if (!ofi.is_open()) {
02051 std::cerr << "Couldn't open file " << file << std::endl;
02052 return;
02053 }
02054
02055
02056 int npar = MCMCGetNParameters();
02057 int nchains = MCMCGetNChains();
02058
02059
02060 bool flag_conv = MCMCGetNIterationsConvergenceGlobal() > 0;
02061
02062 ofi << std::endl
02063 << " -----------------------------------------------------" << std::endl
02064 << " Summary" << std::endl
02065 << " -----------------------------------------------------" << std::endl
02066 << std::endl;
02067
02068 ofi << " Model summary" << std::endl << " =============" << std::endl
02069 << " Model: " << fName.data() << std::endl
02070 << " Number of parameters: " << npar << std::endl
02071 << " List of Parameters and ranges:" << std::endl;
02072 for (int i = 0; i < npar; ++i)
02073 ofi << " (" << i << ") Parameter \""
02074 << fParameterSet->at(i)->GetName().data() << "\"" << ": "
02075 << "(" << fParameterSet->at(i)->GetLowerLimit() << ", "
02076 << fParameterSet->at(i)->GetUpperLimit() << ")" << std::endl;
02077 ofi << std::endl;
02078
02079
02080 if (!flag_conv && fMCMCFlagRun)
02081 ofi << " WARNING: the Markov Chain did not converge!" << std::endl
02082 << " Be cautious using the following results!" << std::endl
02083 << std::endl;
02084
02085
02086 if (fMCMCFlagRun && fMCMCFlagFillHistograms) {
02087 ofi << " Results of the marginalization" << std::endl
02088 << " ==============================" << std::endl
02089 << " List of parameters and properties of the marginalized"
02090 << std::endl << " distributions:" << std::endl;
02091 for (int i = 0; i < npar; ++i) {
02092 if (!fMCMCFlagsFillHistograms[i])
02093 continue;
02094
02095 BCH1D * bch1d = GetMarginalized(fParameterSet->at(i));
02096
02097 ofi << " (" << i << ") Parameter \""
02098 << fParameterSet->at(i)->GetName().data() << "\":" << std::endl
02099
02100 << " Mean +- sqrt(V): " << std::setprecision(4)
02101 << bch1d->GetMean() << " +- " << std::setprecision(4)
02102 << bch1d->GetRMS() << std::endl
02103
02104 << " Median +- central 68% interval: "
02105 << std::setprecision(4) << bch1d->GetMedian() << " + "
02106 << std::setprecision(4) << bch1d->GetQuantile(0.84) - bch1d->GetMedian()
02107 << " - " << std::setprecision(4)
02108 << bch1d->GetMedian() - bch1d->GetQuantile(0.16) << std::endl
02109
02110 << " (Marginalized) mode: " << bch1d->GetMode() << std::endl;
02111
02112 ofi << " 5% quantile: " << std::setprecision(4)
02113 << bch1d->GetQuantile(0.05) << std::endl
02114 << " 10% quantile: " << std::setprecision(4)
02115 << bch1d->GetQuantile(0.10) << std::endl
02116 << " 16% quantile: " << std::setprecision(4)
02117 << bch1d->GetQuantile(0.16) << std::endl
02118 << " 84% quantile: " << std::setprecision(4)
02119 << bch1d->GetQuantile(0.85) << std::endl
02120 << " 90% quantile: " << std::setprecision(4)
02121 << bch1d->GetQuantile(0.90) << std::endl
02122 << " 95% quantile: " << std::setprecision(4)
02123 << bch1d->GetQuantile(0.95) << std::endl;
02124
02125 std::vector<double> v;
02126 v = bch1d->GetSmallestIntervals(0.68);
02127 int ninter = int(v.size());
02128
02129 ofi << " Smallest interval(s) containing 68% and local modes:"
02130 << std::endl;
02131 for (int j = 0; j < ninter; j += 5)
02132 ofi << " (" << v[j] << ", " << v[j + 1]
02133 << ") (local mode at " << v[j + 3] << " with rel. height "
02134 << v[j + 2] << "; rel. area " << v[j + 4] << ")"
02135 << std::endl;
02136 ofi << std::endl;
02137 }
02138 }
02139
02140 ofi << " Results of the optimization" << std::endl
02141 << " ===========================" << std::endl
02142 << " Optimization algorithm used:"
02143 << DumpOptimizationMethod() << std::endl;
02144
02145 if (int(fBestFitParameters.size()) > 0) {
02146 ofi << " List of parameters and global mode:" << std::endl;
02147 for (int i = 0; i < npar; ++i) {
02148 ofi << " (" << i << ") Parameter \""
02149 << fParameterSet->at(i)->GetName().data() << "\": "
02150 << fBestFitParameters[i];
02151 if (int(fBestFitParameterErrors.size()) == npar)
02152 if(fBestFitParameterErrors[i]>=0.)
02153 ofi << " +- " << fBestFitParameterErrors[i];
02154 ofi << std::endl;
02155 }
02156 ofi << std::endl;
02157 }
02158 else {
02159 ofi << " No best fit information available." << std::endl;
02160 ofi << std::endl;
02161 }
02162
02163 if (fPValue >= 0.) {
02164 ofi << " Results of the model test" << std::endl
02165 << " =========================" << std::endl
02166 << " p-value at global mode: " << fPValue << std::endl << std::endl;
02167 }
02168
02169 if (fNormalization >= 0.) {
02170 ofi << " Results of the normalization" << std::endl
02171 << " ============================" << std::endl
02172 << " Integration method used:"
02173 << DumpIntegrationMethod() << std::endl;
02174 ofi << " Normalization factor: " << fNormalization << std::endl << std::endl;
02175 }
02176
02177 if (fMCMCFlagRun) {
02178 ofi << " Status of the MCMC" << std::endl << " ==================" << std::endl
02179 << " Convergence reached: " << (flag_conv ? "yes" : "no")
02180 << std::endl;
02181
02182 if (flag_conv)
02183 ofi << " Number of iterations until convergence: "
02184 << MCMCGetNIterationsConvergenceGlobal() << std::endl;
02185 else
02186 ofi << " WARNING: the Markov Chain did not converge! Be\n"
02187 << " cautious using the following results!" << std::endl
02188 << std::endl;
02189 ofi << " Number of chains: " << MCMCGetNChains() << std::endl
02190 << " Number of iterations per chain: " << MCMCGetNIterationsRun() << std::endl
02191 << " Average efficiencies:" << std::endl;
02192
02193 std::vector<double> efficiencies;
02194 efficiencies.assign(npar, 0.);
02195
02196 for (int ipar = 0; ipar < npar; ++ipar)
02197 for (int ichain = 0; ichain < nchains; ++ichain) {
02198 int index = ichain * npar + ipar;
02199 efficiencies[ipar] +=
02200 double(MCMCGetNTrialsTrue().at(index)) / double(MCMCGetNTrialsTrue().at(index)
02201 + MCMCGetNTrialsFalse().at(index)) / double(nchains) * 100.;
02202 }
02203
02204 for (int ipar = 0; ipar < npar; ++ipar)
02205 ofi << " (" << ipar << ") Parameter \""
02206 << fParameterSet->at(ipar)->GetName().data() << "\": "
02207 << efficiencies.at(ipar) << "%" << std::endl;
02208 ofi << std::endl;
02209 }
02210
02211 ofi << " -----------------------------------------------------" << std::endl
02212 << " Notation: " << std::endl
02213 << " Mean : mean value of the marg. pdf" << std::endl
02214 << " Median : maximum of the marg. pdf" << std::endl
02215 << " Marg. mode : most probable value of the marg. pdf" << std::endl
02216 << " V : Variance of the marg. pdf" << std::endl
02217 << " Quantiles : most commonly used quantiles" <<std::endl
02218 << " -----------------------------------------------------" << std::endl
02219 << std::endl;
02220
02221
02222
02223 }
02224
02225
02226 void BCModel::PrintShortFitSummary(int chi2flag)
02227 {
02228 BCLog::OutSummary("---------------------------------------------------");
02229 BCLog::OutSummary(Form("Fit summary for model \'%s\':", GetName().data()));
02230 BCLog::OutSummary(Form(" Number of parameters: Npar = %i", GetNParameters()));
02231 BCLog::OutSummary(Form(" Number of data points: Ndata = %i", GetNDataPoints()));
02232 BCLog::OutSummary(" Number of degrees of freedom:");
02233 BCLog::OutSummary(Form(" NDoF = Ndata - Npar = %i", GetNDataPoints() - GetNParameters()));
02234
02235 BCLog::OutSummary(" Best fit parameters (global):");
02236 for (unsigned int i = 0; i < GetNParameters(); ++i)
02237 BCLog::OutSummary(Form(" %s = %.3g", GetParameter(i)->GetName().data(), GetBestFitParameter(i)));
02238
02239 BCLog::OutSummary(" Goodness-of-fit test:");
02240 BCLog::OutSummary(Form(" p-value = %.3g", GetPValue()));
02241 if (chi2flag) {
02242 BCLog::OutSummary(Form(" p-value corrected for NDoF = %.3g", GetPValueNDoF()));
02243 BCLog::OutSummary(Form(" chi2 / NDoF = %.3g", GetChi2NDoF()));
02244 }
02245 BCLog::OutSummary("---------------------------------------------------");
02246 }
02247
02248
02249 void BCModel::PrintHessianMatrix(std::vector<double> parameters)
02250 {
02251
02252 if (parameters.size() != GetNParameters()) {
02253 BCLog::OutError("BCModel::PrintHessianMatrix : Invalid number of entries in the vector");
02254 return;
02255 }
02256
02257
02258 std::cout << std::endl << " Hessian matrix elements: " << std::endl << " Point: ";
02259
02260 for (int i = 0; i < int(parameters.size()); i++)
02261 std::cout << parameters.at(i) << " ";
02262 std::cout << std::endl;
02263
02264
02265 for (unsigned int i = 0; i < GetNParameters(); i++)
02266 for (unsigned int j = 0; j < i; j++) {
02267
02268 double hessianmatrixelement = HessianMatrixElement(
02269 fParameterSet->at(i), fParameterSet->at(j), parameters);
02270
02271
02272 std::cout << " " << i << " " << j << " : " << hessianmatrixelement << std::endl;
02273 }
02274 }
02275
02276
02277 BCDataPoint * BCModel::VectorToDataPoint(std::vector<double> data)
02278 {
02279 int sizeofvector = int(data.size());
02280 BCDataPoint * datapoint = new BCDataPoint(sizeofvector);
02281 datapoint->SetValues(data);
02282 return datapoint;
02283 }
02284
02285
02286 int BCModel::CompareStrings(const char * string1, const char * string2)
02287 {
02288 int flag_same = 0;
02289
02290 if (strlen(string1) != strlen(string2))
02291 return -1;
02292
02293 for (int i = 0; i < int(strlen(string1)); i++)
02294 if (string1[i] != string2[i])
02295 flag_same = -1;
02296
02297 return flag_same;
02298 }
02299
02300
02301