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