• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

BCModel.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2010, Daniel Kollar and Kevin Kroeninger.
00003  * All rights reserved.
00004  *
00005  * For the licensing terms see doc/COPYING.
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    // loop over x and y bins
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    // define new graph
00278    int nx = fErrorBandXY->GetNbinsX();
00279 
00280    TGraph * graph = new TGraph(2 * nx);
00281    graph->SetFillStyle(1001);
00282    graph->SetFillColor(kYellow);
00283 
00284    // get error bands
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    // copy existing histogram
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    // loop over x bins
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    // define new graph
00340    int nx = fErrorBandXY->GetNbinsX();
00341    TGraph * graph = new TGraph(nx);
00342 
00343    // loop over x values
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    // define new graph
00362    TGraph * graph = new TGraph(n + 1);
00363 
00364    double dx = (xmax - xmin) / (double) n;
00365 
00366    // loop over x values
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    // create new data set consisting of a single data point
00403    BCDataSet * dataset = new BCDataSet();
00404 
00405    // add the data point
00406    dataset->AddDataPoint(datapoint);
00407 
00408    // set this new data set
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    // check if data set exists
00425    if (!fDataSet) {
00426       BCLog::OutError("BCModel::SetDataBoundaries : Need to define data set first.");
00427       return;
00428    }
00429 
00430    // check if index is within range
00431    if (index < 0 || index > fDataSet->GetDataPoint(0)->GetNValues()) {
00432       BCLog::OutError("BCModel::SetDataBoundaries : Index out of range.");
00433       return;
00434    }
00435 
00436    // check if boundary data points exist
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    // set boundaries
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    // clear x-values
00461    fErrorBandX.clear();
00462 
00463    // copy data x-values
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    // create new parameter
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    // check if parameter set exists
00485    if (!fParameterSet) {
00486       BCLog::OutError("BCModel::AddParameter : Parameter set does not exist");
00487       return ERROR_PARAMETERSETDOESNOTEXIST;
00488    }
00489 
00490    // check if parameter with same name exists
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    // define index of new parameter
00504    unsigned int index = fParameterSet->size();
00505    parameter->SetIndex(index);
00506 
00507    // add parameter to parameter container
00508    fParameterSet->push_back(parameter);
00509 
00510    // add empty object to prior container
00511    fPriorContainer.push_back(0); 
00512 
00513    // don't interpolate the prior histogram by default
00514    fPriorContainerInterpolate.push_back(false);
00515 
00516    // prior assumed to be non-constant in general case
00517    fPriorContainerConstant.push_back(false);
00518 
00519    // add parameters to integration methods
00520    SetParameters(fParameterSet);
00521 
00522    // reset results
00523    ResetResults();
00524 
00525    return 0;
00526 }
00527 
00528 // ---------------------------------------------------------
00529 double BCModel::LogProbabilityNN(std::vector<double> parameters)
00530 {
00531    // add log of conditional probability
00532    double logprob = LogLikelihood(parameters);
00533 
00534    // add log of prior probability
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    // check if normalized
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    // add log of conditional probabilities event-by-event
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    // get number of parameters
00575    int npar = GetNParameters();
00576 
00577    // loop over all 1-d priors
00578    for (int i = 0; i < npar; ++i) {
00579       if (fPriorContainer[i]) {
00580          // check what type of object is stored
00581          TF1 * f = dynamic_cast<TF1*>(fPriorContainer[i]);
00582          TH1 * h = dynamic_cast<TH1*>(fPriorContainer[i]);
00583 
00584          if (f) // TF1
00585             logprob += log(f->Eval(parameters[i]));
00586          else if (h) { // TH1
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())); // this should never happen
00597       }
00598       // use constant only if user has defined it
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    // add the contribution from constant priors in one step
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    // initialize BCIntegrate if not done already
00648    if (n == 0) {
00649       SetParameters(fParameterSet);
00650       n = GetNvar();
00651    }
00652 
00653    // integrate and get best fit parameters
00654    // maybe we have to remove the mode finding from here in the future
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    // check if vectors are of equal size
00666    if (!parameters.size() == fParameterSet->size())
00667       return ERROR_INVALIDNUMBEROFPARAMETERS;
00668 
00669    // check if parameters are within limits
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    // this implementation is CLEARLY not good we have to work on this.
00694 
00695    BCLog::OutSummary(Form("Model \'%s\': Finding mode using %s",GetName().data(), DumpOptimizationMethod().c_str()));
00696 
00697    // synchronize parameters in BCIntegrate
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    // synchronize parameters in BCIntegrate
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    // prepare function fitting
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    //   PrintResults(Form("%s.txt", GetName().data()));
00863 
00864    return 1;
00865 }
00866 
00867 // ---------------------------------------------------------
00868 BCH1D * BCModel::GetMarginalized(BCParameter * parameter)
00869 {
00870    if (!parameter) {
00871 // don't print any error message, should be done upstream
00872 //      BCLog::OutError("BCModel::GetMarginalized : Parameter does not exist.");
00873       return 0;
00874    }
00875 
00876    int index = parameter->GetIndex();
00877    if (fMCMCFlagsFillHistograms[index] == false) {
00878 // don't print any error message, should be done upstream
00879 //      BCLog::OutError(Form(
00880 //            "BCModel::GetMarginalized : Distribuion for '%s' not filled.",
00881 //            parameter->GetName().data()));
00882       return 0;
00883    }
00884 
00885    // get histogram
00886    TH1D * hist = MCMCGetH1Marginalized(index);
00887    if (!hist)
00888       return 0;
00889 
00890    // set axis labels
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    // set histogram
00897    BCH1D * hprob = new BCH1D();
00898    hprob->SetHistogram(hist);
00899 
00900    // set best fit parameter
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    // We reset the MCMCEngine here for the moment.
00924    // In the future maybe we only want to do this if the engine
00925    // wans't initialized at all or when there were some changes
00926    // in the model.
00927    // But maybe we want reset everything since we're overwriting
00928    // the marginalized distributions anyway.
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    // if there's only one parameter, we just want to call Print()
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; // default canvas width
01078    int c_height = 600; // default canvas height
01079 
01080    int type = 112; // landscape
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    // calculate number of plots
01105    int nplots2d = npar * (npar - 1) / 2;
01106    int nplots = npar + nplots2d;
01107 
01108    // give out warning if too many plots
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    // setup the canvas and postscript file
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    // draw all 1D distributions
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       // get corresponding parameter
01135       BCParameter * a = GetParameter(i);
01136 
01137       // check if histogram exists
01138       if (!GetMarginalized(a))
01139          continue;
01140 
01141       // check if histogram is filled
01142       if (GetMarginalized(a)->GetHistogram()->Integral() <= 0)
01143          continue;
01144 
01145       // if current page is full, switch to new page
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       // go to next pad
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       // draw all the 2D distributions
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          // get corresponding parameters
01184          BCParameter * a = GetParameter(i);
01185          BCParameter * b = GetParameter(j);
01186 
01187          // check if histogram exists
01188          if (!GetMarginalized(a, b))
01189             continue;
01190 
01191          // check if histogram is filled
01192          if (GetMarginalized(a, b)->GetHistogram()->Integral() <= 0)
01193             continue;
01194 
01195          // if current page is full, switch to new page
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          // go to next pad
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    // return total number of drawn histograms
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 // don't print any error message, should be done upstream
01246 //      BCLog::OutError(
01247 //            Form("BCModel::GetMarginalized : Distribuion for '%s' and/or '%s' not filled.",
01248 //                  par1->GetName().data(), par2->GetName().data()));
01249       return 0;
01250    }
01251 
01252    if (index1 == index2) {
01253 // don't print any error message, should be done upstream
01254 //      BCLog::OutError("BCModel::GetMarginalized : Provided parameters are identical. Distribution not available.");
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    // get histogram
01271    TH2D * hist = MCMCGetH2Marginalized(index1, index2);
01272 
01273    if (hist == 0)
01274       return 0;
01275 
01276    BCH2D * hprob = new BCH2D();
01277 
01278    // set axis labels
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    // set histogram
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    // look up corresponding p value
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    // number of observations
01332    int n = GetNDataPoints();
01333 
01334    if (nBins < 0)
01335       nBins = NumberBins();
01336 
01337    // fixed width quantiles, including final point!
01338    std::vector<double> a;
01339    for (int i = 0; i <= nBins; i++)
01340       a.push_back(i / double(nBins));
01341 
01342    // determine the bin counts and fill the histogram with data using the CDF
01343    TH1I * hist = new TH1I("h1", "h1 title", nBins, 0., 1.);
01344 
01345    // discrete case requires randomization to allocate counts of bins that cover more
01346    // than one quantile
01347    if (flag_discrete) {
01348       // loop over observations, each may have different likelihood and CDF
01349       for (int j = 0; j < n; j++) {
01350          // actual value
01351             double CDFval = CDF(par, j, false);
01352          // for the bin just before
01353          double CDFlower = CDF(par, j, true);
01354 
01355          // what quantiles q are covered, count from q_1 to q_{nBins}
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          // simplest case: observation bin entirely contained in one quantile
01372          if (qMin == qMax) {
01373             // watch out for overflow because CDF exactly 1
01374             if (CDFval < 1)
01375                hist->Fill(CDFval);
01376             else
01377                hist->AddBinContent(qMax);
01378 
01379             continue; // this observation finished
01380          }
01381 
01382          // if more than quantile is covered need more work:
01383          // determine probabilities of this observation to go for each quantile covered
01384          // as follows: If each quantile has size 0.25 and the CDF(integral of likelihood)
01385          // for current observation gives gives 0.27, but for observation-1 we would have
01386          // 0.20, then 5/7 of the 7% go for first quantile and 2/7 for the second.
01387          // This extend to bins covering more than two quantiles
01388          std::vector<double> prob;
01389          // normalization
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             // default case
01402             prob.push_back(norm * (a[i] - a[i - 1]));
01403          }
01404          // have distribution, use inverse-transform method
01405          double U = fRandom->Rndm();
01406          // build up the integral (CDF)
01407          for (uint i = 1; i < prob.size(); i++)
01408             prob[i] += prob[i - 1];
01409          // and search with linear comput. complexity
01410          for (uint i = 0; i < prob.size(); i++) {
01411             // we finally allocate the count, as center of quantile
01412             if (U <= prob[i]) {
01413                hist->Fill((a[qMin + i - 1] + a[qMin + i]) / 2.);
01414                break;
01415             }
01416          }
01417       }
01418    }
01419    else { //continuous case is simple
01420       for (int j = 0; j < n; j++)
01421             hist->Fill(CDF(par, j, false));
01422    }
01423 
01424    // calculate chi^2
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    // model parameters
01443    int nPar = (int)GetNParameters();
01444    std::vector<double> param(nPar);
01445 
01446    //parameters saved in branches should be the same
01447    int nParBranches = -1;
01448    tree->SetBranchAddress("fNParameters", &nParBranches);
01449 
01450    //assume all events have same number of parameters, so check only first
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    // buffer to construct correct branchnames for parameters, e.g. "fParameter3"
01461    char * branchName = new char[10 + nPar];
01462    // set up variables filled for each sample of parameters
01463    // assume same order as in model
01464    for (int i = 0; i < (int) nPar; i++) {
01465       +sprintf(branchName, "fParameter%d", i);
01466       tree->SetBranchAddress(branchName, &param[i]);
01467    }
01468 
01469    // get the p value from Johson's definition for each param from posterior
01470    long nEntries = tree->GetEntries();
01471 
01472    // RN ~ chi2 with K-1 DoF needed for comparison
01473    std::vector<double> randoms(nEntries);
01474    int K = NumberBins();
01475    BCMath::RandomChi2(randoms, K - 1);
01476 
01477    // number of Johnson chi2 values bigger than reference
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       // compare to set of chi2 variables
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    //calculate the ECDF from the 1D data
01521    std::vector<double> yData = fDataSet->GetDataComponents(index);
01522    TH1D * ECDF = BCMath::ECDF(yData);
01523 
01524    int N = GetNDataPoints();
01525 
01526    // calculated expected CDF for unique points only
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    // find maximum distance
01540    double distMax = 0.;
01541 
01542    // current distance
01543    double dist = 0.;
01544 
01545    std::set<double>::const_iterator iter = uniqueObservations.begin();
01546    for (int iBin = 0; iBin < nUnique; ++iBin) {
01547       // distance between current points
01548       dist = TMath::Abs(*iter - ECDF->GetBinContent(iBin + 1));
01549       // update maximum if necessary
01550       distMax = TMath::Max(dist, distMax);
01551 
01552 //      BCLog::OutDebug(Form("BCModel::GetPvalueFromKolmogorov : "
01553 //         "expected vs empirical (%f vs %f)", *iter, ECDF->GetBinContent(iBin
01554 //            + 1)));
01555 
01556       // advance to next entry in the set
01557       ++iter;
01558    }
01559 
01560    // correct for total #points, not unique #points.
01561    // would need sqrt(n1*n2/(n1+n2)) if we had two experimental datasets
01562    double z = distMax * sqrt(N);
01563 
01564    fPValue = TMath::KolmogorovProb(z);
01565 
01566 //   BCLog::OutDebug(Form("BCModel::GetPvalueFromKolmogorov : "
01567 //      "max distance vs corrected (%f vs %f)", distMax, z));
01568 
01569    // clean up
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    // print log
01581    BCLog::OutSummary("Do goodness-of-fit-test");
01582 
01583    // create model test
01584    BCGoFTest * goftest = new BCGoFTest("modeltest");
01585 
01586    // set this model as the model to be tested
01587    goftest->SetTestModel(this);
01588 
01589    // set the point in parameter space which is tested an initialize
01590    // the model testing
01591    if (!goftest->SetTestPoint(par))
01592       return 0;
01593 
01594    // disable the creation of histograms to save _a lot_ of memory
01595    // (histograms are not needed for p-value calculation)
01596    goftest->MCMCSetFlagFillHistograms(false);
01597 
01598    // set parameters of the MCMC for the GoFTest
01599    goftest->MCMCSetNChains(fGoFNChains);
01600    goftest->MCMCSetNIterationsMax(fGoFNIterationsMax);
01601    goftest->MCMCSetNIterationsRun(fGoFNIterationsRun);
01602 
01603    // get p-value
01604    fPValue = goftest->GetCalculatedPValue(flag_histogram);
01605 
01606    // get histogram
01607    if (flag_histogram) {
01608       hist = new BCH1D();
01609       hist->SetHistogram(goftest->GetHistogramLogProb());
01610    }
01611 
01612    // delete model test
01613    delete goftest;
01614 
01615    // return histogram
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    // check number of entries in vector
01629    if (point.size() != GetNParameters()) {
01630       BCLog::OutError("BCModel::HessianMatrixElement : Invalid number of entries in the vector.");
01631       return -1;
01632    }
01633 
01634    // define steps
01635    double nsteps = 1e5;
01636    double dx1 = par1->GetRangeWidth() / nsteps;
01637    double dx2 = par2->GetRangeWidth() / nsteps;
01638 
01639    // define points at which to evaluate
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    // calculate probability at these points
01661    double ppp = Likelihood(xpp);
01662    double ppm = Likelihood(xpm);
01663    double pmp = Likelihood(xmp);
01664    double pmm = Likelihood(xmm);
01665 
01666    // return derivative
01667    return (ppp + pmm - ppm - pmp) / (4. * dx1 * dx2);
01668 }
01669 
01670 // ---------------------------------------------------------
01671 void BCModel::FixDataAxis(unsigned int index, bool fixed)
01672 {
01673    // check if index is within range
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    // check if index is within range
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    // check index range
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    // copy function
01711    fPriorContainer[index] = new TF1(*f);
01712 
01713    fPriorContainerConstant[index] = false;
01714 
01715    RecalculatePriorConstant();
01716 
01717    // reset all results
01718    ResetResults();
01719 
01720    // no error 
01721    return 1; 
01722 }
01723 
01724 // ---------------------------------------------------------
01725 int BCModel::SetPrior(const char * name, TF1 * f)
01726 {
01727    // find index
01728    int index = -1;
01729    for (unsigned int i = 0; i < GetNParameters(); i++)
01730       if (name == GetParameter(i)->GetName())
01731         index = i;
01732 
01733    // set prior
01734    return SetPrior(index, f);
01735 }
01736 
01737 // ---------------------------------------------------------
01738 int BCModel::SetPriorGauss(int index, double mean, double sigma)
01739 {
01740    // check index range
01741    if (index < 0 || index >= int(GetNParameters())) {
01742       BCLog::OutError("BCModel::SetPriorGauss : Index out of range."); 
01743       return 0;
01744    }
01745 
01746    // create new function
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    // set prior
01755    return SetPrior(index, f); 
01756 }
01757 
01758 // ---------------------------------------------------------
01759 int BCModel::SetPriorGauss(const char* name, double mean, double sigma)
01760 {
01761    // find index
01762    int index = -1;
01763    for (unsigned int i = 0; i < GetNParameters(); i++)
01764       if (name == GetParameter(i)->GetName())
01765          index = i;
01766 
01767    // set prior
01768    return SetPriorGauss(index, mean, sigma); 
01769 }
01770 
01771 // ---------------------------------------------------------
01772 int BCModel::SetPriorGauss(int index, double mean, double sigmadown, double sigmaup)
01773 {
01774    // check index range
01775    if (index < 0 || index >= int(GetNParameters())) {
01776       BCLog::OutError("BCModel::SetPriorGauss : Index out of range."); 
01777       return 0;
01778    }
01779 
01780    // create new function
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    // set prior
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    // find index
01800    int index = -1;
01801    for (unsigned int i = 0; i < GetNParameters(); i++)
01802       if (name == GetParameter(i)->GetName())
01803         index = i;
01804 
01805    // set prior
01806    return SetPriorGauss(index, mean, sigmadown, sigmaup); 
01807 }
01808 
01809 // ---------------------------------------------------------
01810 int BCModel::SetPrior(int index, TH1 * h, bool interpolate)
01811 {
01812    // check index range
01813    if (index < 0 && index >= int(GetNParameters())) {
01814       BCLog::OutError("BCModel::SetPrior : Index out of range."); 
01815       return 0;
01816    }
01817 
01818    // if the histogram exists
01819    if(h) {
01820 
01821       // check if histogram is 1d
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       // normalize the histogram
01828       h->Scale(1./h->Integral("width"));
01829 
01830       if(fPriorContainer[index])
01831          delete fPriorContainer[index];
01832 
01833       // set function
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    // reset all results
01845    ResetResults();
01846 
01847    // no error 
01848    return 1; 
01849 }
01850 
01851 // ---------------------------------------------------------
01852 int BCModel::SetPrior(const char * name, TH1 * h, bool interpolate)
01853 {
01854    // find index
01855    int index = -1;
01856    for (unsigned int i = 0; i < GetNParameters(); i++)
01857       if (name == GetParameter(i)->GetName())
01858         index = i;
01859 
01860    // set prior
01861    return SetPrior(index, h, interpolate);
01862 }
01863 
01864 // ---------------------------------------------------------
01865 int BCModel::SetPriorConstant(int index)
01866 {
01867    // check index range
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    // set prior to a constant
01879    fPriorContainerConstant[index] = true;
01880 
01881    RecalculatePriorConstant();
01882 
01883    // reset all results
01884    ResetResults();
01885 
01886    // no error
01887    return 1;
01888 }
01889 
01890 // ---------------------------------------------------------
01891 int BCModel::SetPriorConstant(const char* name)
01892 {
01893    // find index
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    // get number of parameters
01915    int nPar = GetNParameters();
01916 
01917    if (nPar == 0)
01918       BCLog::OutWarning("BCModel::SetPriorConstantAll : No parameters defined.");
01919 
01920    // loop over all 1-d priors
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    // reset all results
01932    ResetResults();
01933 
01934    // no error
01935    return 1;
01936 }
01937 
01938 // ---------------------------------------------------------
01939 void BCModel::RecalculatePriorConstant()
01940 {
01941    fPriorConstantValue = 0.;
01942 
01943    // get number of parameters
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    // check index
01964    if (index < 0 || index >= int(GetNParameters())) {
01965       BCLog::OutError("BCModel::SetParameterRange : Index out of range.");
01966       return 0; 
01967    }
01968 
01969    // set parameter ranges in BAT 
01970    GetParameter(index)->SetLowerLimit(parmin); 
01971    GetParameter(index)->SetUpperLimit(parmax); 
01972    fMCMCBoundaryMin[index] = parmin; 
01973    fMCMCBoundaryMax[index] = parmax; 
01974 
01975    // reset results
01976    ResetResults();
01977 
01978    // no error 
01979    return 1; 
01980 }
01981 
01982 // ---------------------------------------------------------
01983 int BCModel::ResetResults()
01984 {
01985    BCIntegrate::IntegrateResetResults();
01986   
01987    BCEngineMCMC::MCMCResetResults();
01988 
01989    // no error
01990    return 1;
01991 }
01992 
01993 // ---------------------------------------------------------
01994 void BCModel::PrintSummary()
01995 {
01996    int nparameters = GetNParameters();
01997 
01998    // model summary
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    // parameter summary
02008    for (int i = 0; i < nparameters; i++)
02009       fParameterSet->at(i)->PrintSummary();
02010 
02011    // best fit parameters
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    // model testing
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    // normalization
02037    if (fNormalization > 0)
02038       std::cout << "     Normalization        : " << fNormalization << std::endl;
02039 }
02040 
02041 // ---------------------------------------------------------
02042 void BCModel::PrintResults(const char * file)
02043 {
02044    // print summary of Markov Chain Monte Carlo
02045 
02046    // open file
02047    ofstream ofi(file);
02048 
02049    // check if file is open
02050    if (!ofi.is_open()) {
02051       std::cerr << "Couldn't open file " << file << std::endl;
02052       return;
02053    }
02054 
02055    // number of parameters and chains
02056    int npar = MCMCGetNParameters();
02057    int nchains = MCMCGetNChains();
02058 
02059    // check convergence
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    // give warning if MCMC did not converge
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    // print results of marginalization (if MCMC was run)
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    // close file
02222    //   ofi.close;
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    // check number of entries in vector
02252    if (parameters.size() != GetNParameters()) {
02253       BCLog::OutError("BCModel::PrintHessianMatrix : Invalid number of entries in the vector");
02254       return;
02255    }
02256 
02257    // print to screen
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    // loop over all parameter pairs
02265    for (unsigned int i = 0; i < GetNParameters(); i++)
02266       for (unsigned int j = 0; j < i; j++) {
02267          // calculate Hessian matrix element
02268          double hessianmatrixelement = HessianMatrixElement(
02269                fParameterSet->at(i), fParameterSet->at(j), parameters);
02270 
02271          // print to screen
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 

Generated on Fri Nov 19 2010 17:02:53 for Bayesian Analysis Toolkit by  doxygen 1.7.1