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

BCIntegrate.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2012, Daniel Kollar and Kevin Kroeninger.
00003  * All rights reserved.
00004  *
00005  * For the licensing terms see doc/COPYING.
00006  */
00007 
00008 // ---------------------------------------------------------
00009 
00010 #include "config.h"
00011 
00012 #include "BCIntegrate.h"
00013 #include "BCLog.h"
00014 #include "BCMath.h"
00015 
00016 #include <TH1D.h>
00017 #include <TH2D.h>
00018 #include <TMinuit.h>
00019 #include <TRandom3.h>
00020 #include <TTree.h>
00021 
00022 #ifdef HAVE_CUBA_H
00023 #include "cuba.h"
00024 #endif
00025 
00026 // ---------------------------------------------------------
00027 
00028 class BCIntegrate * global_this;
00029 
00030 // ---------------------------------------------------------
00031 BCIntegrate::BCIntegrate()
00032    : BCEngineMCMC()
00033    , fNvar(0)
00034    , fNbins(100)
00035    , fNSamplesPer2DBin(100)
00036    , fMarkovChainStepSize(0.1)
00037    , fMarkovChainAutoN(true)
00038    , fDataPointLowerBoundaries(0)
00039    , fDataPointUpperBoundaries(0)
00040    , fFillErrorBand(false)
00041    , fFitFunctionIndexX(-1)
00042    , fFitFunctionIndexY(-1)
00043    , fErrorBandContinuous(true)
00044    , fErrorBandNbinsX(100)
00045    , fErrorBandNbinsY(500)
00046    , fMinuit(0)
00047    , fFlagIgnorePrevOptimization(false)
00048    , fFlagWriteMarkovChain(false)
00049    , fMarkovChainTree(0)
00050    , fSAT0(100)
00051    , fSATmin(0.1)
00052    , fTreeSA(0)
00053    , fFlagWriteSAToFile(false)
00054 
00055    , fNiterPerDimension(100)
00056 #ifdef HAVE_CUBA_H
00057    , fIntegrationMethod(BCIntegrate::kIntCuba)
00058 #else
00059    , fIntegrationMethod(BCIntegrate::kIntMonteCarlo)
00060 #endif
00061    , fMarginalizationMethod(BCIntegrate::kMargMetropolis)
00062    , fOptimizationMethod(BCIntegrate::kOptMinuit)
00063    , fOptimizationMethodMode(BCIntegrate::kOptMinuit)
00064    , fSASchedule(BCIntegrate::kSACauchy)
00065    , fNIterationsMax(1000000)
00066    , fNIterations(0)
00067    , fRelativePrecision(1e-3)
00068    , fAbsolutePrecision(1e-12)
00069    , fCubaIntegrationMethod(BCIntegrate::kCubaVegas)
00070    , fCubaMinEval(0)
00071    , fCubaMaxEval(2000000)
00072    , fCubaVerbosity(0)
00073    , fCubaVegasNStart(25000)
00074    , fCubaVegasNIncrease(25000)
00075    , fCubaSuaveNNew(10000)
00076    , fCubaSuaveFlatness(50)
00077    , fError(-999.)
00078 {
00079    fMinuitArglist[0] = 20000;
00080    fMinuitArglist[1] = 0.01;
00081 }
00082 
00083 // ---------------------------------------------------------
00084 BCIntegrate::BCIntegrate(BCParameterSet * par)
00085    : BCEngineMCMC()
00086    , fNvar(0)
00087    , fNbins(100)
00088    , fNSamplesPer2DBin(100)
00089    , fMarkovChainStepSize(0.1)
00090    , fMarkovChainAutoN(true)
00091    , fDataPointLowerBoundaries(0)
00092    , fDataPointUpperBoundaries(0)
00093    , fFillErrorBand(false)
00094    , fFitFunctionIndexX(-1)
00095    , fFitFunctionIndexY(-1)
00096    , fErrorBandContinuous(true)
00097    , fErrorBandNbinsX(100)
00098    , fErrorBandNbinsY(500)
00099    , fMinuit(0)
00100    , fFlagIgnorePrevOptimization(false)
00101    , fFlagWriteMarkovChain(false)
00102    , fMarkovChainTree(0)
00103    , fSAT0(100)
00104    , fSATmin(0.1)
00105    , fTreeSA(0)
00106    , fFlagWriteSAToFile(false)
00107 
00108    , fNiterPerDimension(100)
00109 #ifdef HAVE_CUBA_H
00110    , fIntegrationMethod(BCIntegrate::kIntCuba)
00111 #else
00112    , fIntegrationMethod(BCIntegrate::kIntMonteCarlo)
00113 #endif
00114    , fMarginalizationMethod(BCIntegrate::kMargMetropolis)
00115    , fOptimizationMethod(BCIntegrate::kOptMinuit)
00116    , fOptimizationMethodMode(BCIntegrate::kOptMinuit)
00117    , fSASchedule(BCIntegrate::kSACauchy)
00118    , fNIterationsMax(1000000)
00119    , fNIterations(0)
00120    , fRelativePrecision(1e-3)
00121    , fAbsolutePrecision(1e-12)
00122    , fCubaIntegrationMethod(BCIntegrate::kCubaVegas)
00123    , fCubaMinEval(0)
00124    , fCubaMaxEval(2000000)
00125    , fCubaVerbosity(0)
00126    , fCubaVegasNStart(25000)
00127    , fCubaVegasNIncrease(25000)
00128    , fCubaSuaveNNew(10000)
00129    , fCubaSuaveFlatness(50)
00130    , fError(-999.)
00131 {
00132    SetParameters(par);
00133 
00134    fMinuitArglist[0] = 20000;
00135    fMinuitArglist[1] = 0.01;
00136 }
00137 
00138 // ---------------------------------------------------------
00139 BCIntegrate::BCIntegrate(const BCIntegrate & bcintegrate) : BCEngineMCMC(bcintegrate)
00140  {
00141     fNvar                     = bcintegrate.fNvar;
00142     fNbins                    = bcintegrate.fNbins;
00143     fNSamplesPer2DBin         = bcintegrate.fNSamplesPer2DBin;
00144     fMarkovChainStepSize      = bcintegrate.fMarkovChainStepSize;
00145     fMarkovChainNIterations   = bcintegrate.fMarkovChainNIterations;
00146     fMarkovChainAutoN         = bcintegrate.fMarkovChainAutoN;
00147     if (bcintegrate.fDataPointLowerBoundaries)
00148        fDataPointLowerBoundaries = new BCDataPoint(*bcintegrate.fDataPointLowerBoundaries);
00149     else
00150        fDataPointLowerBoundaries = 0;
00151     if (bcintegrate.fDataPointUpperBoundaries)
00152        fDataPointUpperBoundaries = new BCDataPoint(*bcintegrate.fDataPointUpperBoundaries);
00153     else
00154        fDataPointUpperBoundaries = 0;
00155     fDataFixedValues          = bcintegrate.fDataFixedValues;
00156     fBestFitParameters        = bcintegrate.fBestFitParameters;
00157     fBestFitParameterErrors   = bcintegrate.fBestFitParameterErrors;
00158     fBestFitParametersMarginalized = bcintegrate.fBestFitParametersMarginalized;
00159     for (int i = 0; i < int(bcintegrate.fHProb1D.size()); ++i) {
00160        if (bcintegrate.fHProb1D.at(i))
00161           fHProb1D.push_back(new TH1D(*(bcintegrate.fHProb1D.at(i))));
00162        else
00163           fHProb1D.push_back(0);
00164     }
00165     for (int i = 0; i < int(bcintegrate.fHProb2D.size()); ++i) {
00166        if (bcintegrate.fHProb2D.at(i))
00167           fHProb2D.push_back(new TH2D(*(fHProb2D.at(i))));
00168        else
00169           fHProb2D.push_back(0);
00170     }
00171     fFillErrorBand            = bcintegrate.fFillErrorBand;
00172     fFitFunctionIndexX        = bcintegrate.fFitFunctionIndexX;
00173     fFitFunctionIndexY        = bcintegrate.fFitFunctionIndexY;
00174     fErrorBandX               = bcintegrate.fErrorBandX;
00175     if (bcintegrate.fErrorBandXY)
00176        fErrorBandXY = new TH2D(*(bcintegrate.fErrorBandXY));
00177     else
00178        fErrorBandXY = 0;
00179     fErrorBandNbinsX          = bcintegrate.fErrorBandNbinsX;
00180     fErrorBandNbinsY          = bcintegrate.fErrorBandNbinsY;
00181     fMinuit                   = new TMinuit();
00182     // debugKK
00183     //    *fMinuit = *(bcintegrate.fMinuit);
00184     fMinuitArglist[0]         = bcintegrate.fMinuitArglist[0];
00185     fMinuitArglist[1]         = bcintegrate.fMinuitArglist[1];
00186     fMinuitErrorFlag          = bcintegrate.fMinuitErrorFlag;
00187     fFlagIgnorePrevOptimization = bcintegrate.fFlagIgnorePrevOptimization;
00188     fFlagWriteMarkovChain     = bcintegrate.fFlagWriteMarkovChain;
00189     fMarkovChainTree          = bcintegrate.fMarkovChainTree;
00190     fMCMCIteration            = bcintegrate.fMCMCIteration;
00191     fSAT0                     = bcintegrate.fSAT0;
00192     fSATmin                   = bcintegrate.fSATmin;
00193     // debugKK
00194     fTreeSA = 0;
00195     fFlagWriteSAToFile        = bcintegrate.fFlagWriteSAToFile;
00196     fSANIterations            = bcintegrate.fSANIterations;
00197     fSATemperature            = bcintegrate.fSATemperature;
00198     fSALogProb                = bcintegrate.fSALogProb;
00199     fSAx                      = bcintegrate.fSAx;
00200     if (bcintegrate.fx)
00201        fx = new BCParameterSet(*(bcintegrate.fx));
00202     else
00203        fx = 0;
00204     fMin                      = new double[fNvar];
00205     fMax                      = new double[fNvar];
00206     fVarlist                  = new int[fNvar];
00207     fMin                      = bcintegrate.fMin;
00208     fMax                      = bcintegrate.fMax;
00209     fVarlist                  = bcintegrate.fVarlist;
00210     fNiterPerDimension        = bcintegrate.fNiterPerDimension;
00211     fIntegrationMethod        = bcintegrate.fIntegrationMethod;
00212     fMarginalizationMethod    = bcintegrate.fMarginalizationMethod;
00213     fOptimizationMethod       = bcintegrate.fOptimizationMethod;
00214     fOptimizationMethodMode   = bcintegrate.fOptimizationMethodMode;
00215     fSASchedule               = bcintegrate.fSASchedule;
00216     fNIterationsMax           = bcintegrate.fNIterationsMax;
00217     fNIterations              = bcintegrate.fNIterations;
00218     fRelativePrecision        = bcintegrate.fRelativePrecision;
00219     fAbsolutePrecision        = bcintegrate.fAbsolutePrecision;
00220     fCubaIntegrationMethod    = bcintegrate.fCubaIntegrationMethod;
00221     fCubaMinEval              = bcintegrate.fCubaMinEval;
00222     fCubaMaxEval              = bcintegrate.fCubaMaxEval;
00223     fCubaVerbosity            = bcintegrate.fCubaVerbosity;
00224     fCubaVegasNStart          = bcintegrate.fCubaVegasNStart;
00225     fCubaVegasNIncrease       = bcintegrate.fCubaVegasNIncrease;
00226     fCubaSuaveNNew            = bcintegrate.fCubaSuaveNNew;
00227     fCubaSuaveFlatness        = bcintegrate.fCubaSuaveFlatness;
00228     fError                    = bcintegrate.fError;
00229     fNmetro                   = bcintegrate.fNmetro;
00230     fNacceptedMCMC            = bcintegrate.fNacceptedMCMC;
00231     fXmetro0                  = bcintegrate.fXmetro0;
00232     fXmetro1                  = bcintegrate.fXmetro1;
00233     fMarkovChainValue         = bcintegrate.fMarkovChainValue;
00234 }
00235 
00236 // ---------------------------------------------------------
00237 BCIntegrate & BCIntegrate::operator = (const BCIntegrate & bcintegrate)
00238 {
00239     BCEngineMCMC::operator=(bcintegrate);
00240 
00241     fNvar                     = bcintegrate.fNvar;
00242     fNbins                    = bcintegrate.fNbins;
00243     fNSamplesPer2DBin         = bcintegrate.fNSamplesPer2DBin;
00244     fMarkovChainStepSize      = bcintegrate.fMarkovChainStepSize;
00245     fMarkovChainNIterations   = bcintegrate.fMarkovChainNIterations;
00246     fMarkovChainAutoN         = bcintegrate.fMarkovChainAutoN;
00247     if (bcintegrate.fDataPointLowerBoundaries)
00248        fDataPointLowerBoundaries = new BCDataPoint(*bcintegrate.fDataPointLowerBoundaries);
00249     else
00250        fDataPointLowerBoundaries = 0;
00251     if (bcintegrate.fDataPointUpperBoundaries)
00252        fDataPointUpperBoundaries = new BCDataPoint(*bcintegrate.fDataPointUpperBoundaries);
00253     else
00254        fDataPointUpperBoundaries = 0;
00255     fDataFixedValues          = bcintegrate.fDataFixedValues;
00256     fBestFitParameters        = bcintegrate.fBestFitParameters;
00257     fBestFitParameterErrors   = bcintegrate.fBestFitParameterErrors;
00258     fBestFitParametersMarginalized = bcintegrate.fBestFitParametersMarginalized;
00259     for (int i = 0; i < int(bcintegrate.fHProb1D.size()); ++i) {
00260        if (bcintegrate.fHProb1D.at(i))
00261           fHProb1D.push_back(new TH1D(*(bcintegrate.fHProb1D.at(i))));
00262        else
00263           fHProb1D.push_back(0);
00264     }
00265     for (int i = 0; i < int(bcintegrate.fHProb2D.size()); ++i) {
00266        if (bcintegrate.fHProb2D.at(i))
00267           fHProb2D.push_back(new TH2D(*(fHProb2D.at(i))));
00268        else
00269           fHProb2D.push_back(0);
00270     }
00271     fFillErrorBand            = bcintegrate.fFillErrorBand;
00272     fFitFunctionIndexX        = bcintegrate.fFitFunctionIndexX;
00273     fFitFunctionIndexY        = bcintegrate.fFitFunctionIndexY;
00274     fErrorBandX               = bcintegrate.fErrorBandX;
00275     if (bcintegrate.fErrorBandXY)
00276        fErrorBandXY = new TH2D(*(bcintegrate.fErrorBandXY));
00277     else
00278        fErrorBandXY = 0;
00279     fErrorBandNbinsX          = bcintegrate.fErrorBandNbinsX;
00280     fErrorBandNbinsY          = bcintegrate.fErrorBandNbinsY;
00281     fMinuit                   = new TMinuit();
00282     // debugKK
00283     //    *fMinuit = *(bcintegrate.fMinuit);
00284     fMinuitArglist[0]         = bcintegrate.fMinuitArglist[0];
00285     fMinuitArglist[1]         = bcintegrate.fMinuitArglist[1];
00286     fMinuitErrorFlag          = bcintegrate.fMinuitErrorFlag;
00287     fFlagIgnorePrevOptimization = bcintegrate.fFlagIgnorePrevOptimization;
00288     fFlagWriteMarkovChain     = bcintegrate.fFlagWriteMarkovChain;
00289     fMarkovChainTree          = bcintegrate.fMarkovChainTree;
00290     fMCMCIteration            = bcintegrate.fMCMCIteration;
00291     fSAT0                     = bcintegrate.fSAT0;
00292     fSATmin                   = bcintegrate.fSATmin;
00293     // debugKK
00294     fTreeSA = 0;
00295     fFlagWriteSAToFile        = bcintegrate.fFlagWriteSAToFile;
00296     fSANIterations            = bcintegrate.fSANIterations;
00297     fSATemperature            = bcintegrate.fSATemperature;
00298     fSALogProb                = bcintegrate.fSALogProb;
00299     fSAx                      = bcintegrate.fSAx;
00300     if (bcintegrate.fx)
00301        fx = new BCParameterSet(*(bcintegrate.fx));
00302     else
00303        fx = 0;
00304     fMin                      = new double[fNvar];
00305     fMax                      = new double[fNvar];
00306     fVarlist                  = new int[fNvar];
00307     fNiterPerDimension        = bcintegrate.fNiterPerDimension;
00308     fIntegrationMethod        = bcintegrate.fIntegrationMethod;
00309     fMarginalizationMethod    = bcintegrate.fMarginalizationMethod;
00310     fOptimizationMethod       = bcintegrate.fOptimizationMethod;
00311     fOptimizationMethodMode   = bcintegrate.fOptimizationMethodMode;
00312     fSASchedule               = bcintegrate.fSASchedule;
00313 
00314     fNIterationsMax           = bcintegrate.fNIterationsMax;
00315     fNIterations              = bcintegrate.fNIterations;
00316     fRelativePrecision        = bcintegrate.fRelativePrecision;
00317     fAbsolutePrecision        = bcintegrate.fAbsolutePrecision;
00318     fCubaIntegrationMethod    = bcintegrate.fCubaIntegrationMethod;
00319     fCubaMinEval              = bcintegrate.fCubaMinEval;
00320     fCubaMaxEval              = bcintegrate.fCubaMaxEval;
00321     fCubaVerbosity            = bcintegrate.fCubaVerbosity;
00322     fCubaVegasNStart          = bcintegrate.fCubaVegasNStart;
00323     fCubaVegasNIncrease       = bcintegrate.fCubaVegasNIncrease;
00324     fCubaSuaveNNew            = bcintegrate.fCubaSuaveNNew;
00325     fCubaSuaveFlatness        = bcintegrate.fCubaSuaveFlatness;
00326     fError                    = bcintegrate.fError;
00327     fNmetro                   = bcintegrate.fNmetro;
00328     fNacceptedMCMC            = bcintegrate.fNacceptedMCMC;
00329     fXmetro0                  = bcintegrate.fXmetro0;
00330     fXmetro1                  = bcintegrate.fXmetro1;
00331     fMarkovChainValue         = bcintegrate.fMarkovChainValue;
00332 
00333    // return this
00334    return *this;
00335 }
00336 
00337 // ---------------------------------------------------------
00338 BCIntegrate::~BCIntegrate()
00339 {
00340    DeleteVarList();
00341 
00342    fx=0;
00343 
00344    if (fMinuit)
00345       delete fMinuit;
00346 
00347    int n1 = fHProb1D.size();
00348    if(n1>0) {
00349       for (int i=0;i<n1;i++)
00350          delete fHProb1D.at(i);
00351    }
00352 
00353    int n2 = fHProb2D.size();
00354    if(n2>0) {
00355       for (int i=0;i<n2;i++)
00356          delete fHProb2D.at(i);
00357    }
00358 }
00359 
00360 // ---------------------------------------------------------
00361 void BCIntegrate::SetParameters(BCParameterSet * par)
00362 {
00363    DeleteVarList();
00364 
00365    fx = par;
00366    fNvar = fx->size();
00367    fMin = new double[fNvar];
00368    fMax = new double[fNvar];
00369    fVarlist = new int[fNvar];
00370 
00371    ResetVarlist(1);
00372 
00373    for(int i=0;i<fNvar;i++) {
00374       fMin[i]=(fx->at(i))->GetLowerLimit();
00375       fMax[i]=(fx->at(i))->GetUpperLimit();
00376    }
00377 
00378    fXmetro0.clear();
00379    for(int i=0;i<fNvar;i++)
00380       fXmetro0.push_back((fMin[i]+fMax[i])/2.0);
00381 
00382    fXmetro1.clear();
00383    fXmetro1.assign(fNvar,0.);
00384 
00385    fMCMCBoundaryMin.clear();
00386    fMCMCBoundaryMax.clear();
00387 
00388    for(int i=0;i<fNvar;i++) {
00389       fMCMCBoundaryMin.push_back(fMin[i]);
00390       fMCMCBoundaryMax.push_back(fMax[i]);
00391       fMCMCFlagsFillHistograms.push_back(true);
00392    }
00393 
00394    for (int i = int(fMCMCH1NBins.size()); i<fNvar; ++i)
00395       fMCMCH1NBins.push_back(100);
00396 
00397    fMCMCNParameters = fNvar;
00398 }
00399 
00400 // ---------------------------------------------------------
00401 void BCIntegrate::SetMarkovChainInitialPosition(std::vector<double> position)
00402 {
00403    int n = position.size();
00404 
00405    fXmetro0.clear();
00406 
00407    for (int i = 0; i < n; ++i)
00408       fXmetro0.push_back(position.at(i));
00409 }
00410 
00411 // ---------------------------------------------------------
00412 void BCIntegrate::DeleteVarList()
00413 {
00414    if(fNvar) {
00415       delete[] fVarlist;
00416       fVarlist=0;
00417 
00418       delete[] fMin;
00419       fMin=0;
00420 
00421       delete[] fMax;
00422       fMax=0;
00423 
00424       fx=0;
00425       fNvar=0;
00426    }
00427 }
00428 
00429 // ---------------------------------------------------------
00430 void BCIntegrate::SetNbins(int nbins, int index)
00431 {
00432    if (fNvar == 0)
00433       return;
00434 
00435    // check if index is in range
00436    if (index >= fNvar) {
00437       BCLog::OutWarning("BCIntegrate::SetNbins : Index out of range.");
00438       return;
00439    }
00440    // set for all parameters at once
00441    else if (index < 0) {
00442       for (int i = 0; i < fNvar; ++i)
00443          SetNbins(nbins, i);
00444       return;
00445    }
00446 
00447    // sanity check for nbins
00448    if (nbins <= 0)
00449       nbins = 10;
00450 
00451    fMCMCH1NBins[index] = nbins;
00452 
00453    return;
00454 
00455 //    if(n<2) {
00456 //       BCLog::OutWarning("BCIntegrate::SetNbins. Number of bins less than 2 makes no sense. Setting to 2.");
00457 //       n=2;
00458 //    }
00459 //    MCMCSetH1NBins(n, -1);
00460 
00461    //   fNbins=n;
00462 
00463    //   fMCMCH1NBins = n;
00464    //   fMCMCH2NBinsX = n;
00465    //   fMCMCH2NBinsY = n;
00466 }
00467 
00468 // ---------------------------------------------------------
00469 // void BCIntegrate::SetNbinsX(int n)
00470 // {
00471 //    if(n<2) {
00472 //       BCLog::OutWarning("BCIntegrate::SetNbins. Number of bins less than 2 makes no sense. Setting to 2.");
00473 //       n=2;
00474 //    }
00475 //    fMCMCH2NBinsX = n;
00476 // }
00477 
00478 // ---------------------------------------------------------
00479 // void BCIntegrate::SetNbinsY(int n)
00480 // {
00481 //    if(n<2) {
00482 //       BCLog::OutWarning("BCIntegrate::SetNbins. Number of bins less than 2 makes no sense. Setting to 2.");
00483 //       n=2;
00484 //    }
00485 //    fNbins=n;
00486 
00487 //    fMCMCH2NBinsY = n;
00488 // }
00489 
00490 // ---------------------------------------------------------
00491 void BCIntegrate::SetVarList(int * varlist)
00492 {
00493    for(int i=0;i<fNvar;i++)
00494       fVarlist[i]=varlist[i];
00495 }
00496 
00497 // ---------------------------------------------------------
00498 void BCIntegrate::ResetVarlist(int v)
00499 {
00500    for(int i=0;i<fNvar;i++)
00501       fVarlist[i]=v;
00502 }
00503 
00504 // ---------------------------------------------------------
00505 double BCIntegrate::Eval(const std::vector<double> & /*x*/)
00506 {
00507    BCLog::OutWarning( "BCIntegrate::Eval. No function. Function needs to be overloaded.");
00508    return 0;
00509 }
00510 
00511 // ---------------------------------------------------------
00512 double BCIntegrate::LogEval(const std::vector<double> &x)
00513 {
00514    // this method should better also be overloaded
00515    return log(Eval(x));
00516 }
00517 
00518 // ---------------------------------------------------------
00519 double BCIntegrate::EvalSampling(const std::vector<double> & /*x*/)
00520 {
00521    BCLog::OutWarning( "BCIntegrate::EvalSampling. No function. Function needs to be overloaded.");
00522    return 0;
00523 }
00524 
00525 // ---------------------------------------------------------
00526 double BCIntegrate::LogEvalSampling(const std::vector<double> &x)
00527 {
00528    return log(EvalSampling(x));
00529 }
00530 
00531 // ---------------------------------------------------------
00532 void BCIntegrate::SetIntegrationMethod(BCIntegrate::BCIntegrationMethod method)
00533 {
00534 #ifdef HAVE_CUBA_H
00535    fIntegrationMethod = method;
00536 #else
00537    BCLog::OutWarning("!!! This version of BAT is compiled without Cuba.");
00538    BCLog::OutWarning("    Monte Carlo Sampled Mean integration method will be used.");
00539    BCLog::OutWarning("    To be able to use Cuba integration, install Cuba and recompile BAT.");
00540 #endif
00541 }
00542 
00543 // ---------------------------------------------------------
00544 int BCIntegrate::IntegrateResetResults()
00545 {
00546    fBestFitParameters.clear();
00547    fBestFitParameterErrors.clear();
00548    fBestFitParametersMarginalized.clear();
00549 
00550    // no errors
00551    return 1;
00552 }
00553 
00554 // ---------------------------------------------------------
00555 double BCIntegrate::Integrate()
00556 {
00557    std::vector<double> parameter;
00558    parameter.assign(fNvar, 0.0);
00559 
00560    BCLog::OutSummary(
00561          Form("Running numerical integration using %s (%s)",
00562          DumpIntegrationMethod().c_str(),
00563          DumpCubaIntegrationMethod().c_str()));
00564 
00565    switch(fIntegrationMethod)
00566    {
00567       case BCIntegrate::kIntMonteCarlo:
00568          return IntegralMC(parameter);
00569 
00570       case BCIntegrate::kIntMetropolis:
00571          return IntegralMetro(parameter);
00572 
00573       case BCIntegrate::kIntImportance:
00574          return IntegralImportance(parameter);
00575 
00576       case BCIntegrate::kIntCuba:
00577 #ifdef HAVE_CUBA_H
00578          return CubaIntegrate();
00579 #else
00580          BCLog::OutError("!!! This version of BAT is compiled without Cuba.");
00581          BCLog::OutError("    Use other integration methods or install Cuba and recompile BAT.");
00582          break;
00583 #endif
00584       default:
00585          BCLog::OutError(
00586             Form("BCIntegrate::Integrate : Invalid integration method: %d", fIntegrationMethod));
00587          break;
00588    }
00589 
00590    return 0;
00591 }
00592 
00593 // ---------------------------------------------------------
00594 double BCIntegrate::IntegralMC(const std::vector<double> &x, int * varlist)
00595 {
00596    SetVarList(varlist);
00597    return IntegralMC(x);
00598 }
00599 
00600 // ---------------------------------------------------------
00601 double BCIntegrate::IntegralMC(const std::vector<double> &x)
00602 {
00603    // count the variables to integrate over
00604    // and calculate D (integrated volume)
00605    int NvarNow=0;
00606    double D=1.;
00607    for(int i = 0; i < fNvar; i++)
00608       if(fVarlist[i]) {
00609          NvarNow++;
00610          D *= fMax[i] - fMin[i];
00611       }
00612 
00613    // print to log
00614    BCLog::LogLevel level=BCLog::summary;
00615    if(fNvar!=NvarNow) {
00616       level=BCLog::detail;
00617       BCLog::OutDetail(Form("Running MC integation over %i dimensions out of %i.", NvarNow, fNvar));
00618       BCLog::OutDetail(" --> Fixed parameters:");
00619       for(int i = 0; i < fNvar; i++)
00620          if(!fVarlist[i])
00621             BCLog::OutDetail(Form("      %3i :  %g", i, x[i]));
00622    }
00623    else
00624       BCLog::OutSummary(Form("Running MC integation over %i dimensions.", NvarNow));
00625    BCLog::Out(level, Form(" --> Maximum number of iterations: %i", GetNIterationsMax()));
00626    BCLog::Out(level, Form(" --> Aimed relative precision:     %e", GetRelativePrecision()));
00627 
00628    // reset variables
00629    double pmax = 0.;
00630    double sumW  = 0.;
00631    double sumW2 = 0.;
00632    double integral = 0.;
00633    double variance = 0.;
00634    double relprecision = 1.;
00635 
00636    std::vector<double> randx;
00637    randx.assign(fNvar, 0.);
00638 
00639    // how often to print out the info line to screen
00640    int nwrite = fNIterationsMax/10;
00641    if(nwrite < 10000)
00642       nwrite=1000;
00643    else if(nwrite < 100000)
00644       nwrite=10000;
00645    else if(nwrite < 1000000)
00646       nwrite=100000;
00647    else
00648       nwrite=1000000;
00649 
00650    // reset number of iterations
00651    fNIterations = 0;
00652 
00653    // iterate while precision is not reached and the number of iterations is lower than maximum number of iterations
00654    while ((fRelativePrecision < relprecision && fNIterationsMax > fNIterations) || fNIterations < 10) {
00655       // increase number of iterations
00656       fNIterations++;
00657 
00658       // get random numbers
00659       GetRandomVector(randx);
00660 
00661       // scale random numbers
00662       for(int i = 0; i < fNvar; i++) {
00663          if(fVarlist[i])
00664             randx[i]=fMin[i]+randx[i]*(fMax[i]-fMin[i]);
00665          else
00666             randx[i]=x[i];
00667       }
00668 
00669       // evaluate function at sampled point
00670       double value = Eval(randx);
00671 
00672       // add value to sum and sum of squares
00673       sumW  += value;
00674       sumW2 += value * value;
00675 
00676       // search for maximum probability
00677       if (value > pmax) {
00678          // set new maximum value
00679          pmax = value;
00680 
00681          // delete old best fit parameter values
00682          fBestFitParameters.clear();
00683 
00684          // write best fit parameters
00685          for(int i = 0; i < fNvar; i++)
00686             fBestFitParameters.push_back(randx.at(i));
00687       }
00688 
00689       if (fNIterations%1000 == 0 || fNIterations%nwrite == 0) {
00690          // calculate integral and variance
00691          integral = D * sumW / fNIterations;
00692          variance = (1.0 / double(fNIterations)) * (D * D * sumW2 / double(fNIterations) - integral * integral);
00693          double error = sqrt(variance);
00694          relprecision = error / integral;
00695 
00696          if (fNIterations%nwrite == 0)
00697             BCLog::OutDetail(Form("BCIntegrate::IntegralMC. Iteration %i, integral: %e +- %e.", fNIterations, integral, error));
00698       }
00699    }
00700 
00701    integral = D * sumW / fNIterations;
00702    fError = variance / fNIterations;
00703 
00704    // print to log
00705    BCLog::OutSummary(Form(" --> Result of integration:        %e +- %e   in %i iterations.", integral, sqrt(variance), fNIterations));
00706    BCLog::OutSummary(Form(" --> Obtained relative precision:  %e. ", sqrt(variance) / integral));
00707 
00708    return integral;
00709 }
00710 
00711 
00712 // ---------------------------------------------------------
00713 double BCIntegrate::IntegralMetro(const std::vector<double> & /*x*/)
00714 {
00715    // print debug information
00716    BCLog::OutDebug(Form("BCIntegrate::IntegralMetro. Integate over %i dimensions.", fNvar));
00717 
00718    // get total number of iterations
00719    double Niter = pow(fNiterPerDimension, fNvar);
00720 
00721    // print if more than 100,000 iterations
00722    if(Niter>1e5)
00723       BCLog::OutDebug(Form(" --> Total number of iterations in Metropolis: %d.", (int)Niter));
00724 
00725    // reset sum
00726    double sumI = 0;
00727 
00728    // prepare Metropolis algorithm
00729    std::vector<double> randx;
00730    randx.assign(fNvar,0.);
00731    InitMetro();
00732 
00733    // prepare maximum value
00734    double pmax = 0.0;
00735 
00736    // loop over iterations
00737    for(int i = 0; i <= Niter; i++) {
00738       // get random point from sampling distribution
00739       GetRandomPointSamplingMetro(randx);
00740 
00741       // calculate probability at random point
00742       double val_f = Eval(randx);
00743 
00744       // calculate sampling distributions at that point
00745       double val_g = EvalSampling(randx);
00746 
00747       // add ratio to sum
00748       if (val_g > 0)
00749          sumI += val_f / val_g;
00750 
00751       // search for maximum probability
00752       if (val_f > pmax) {
00753          // set new maximum value
00754          pmax = val_f;
00755 
00756          // delete old best fit parameter values
00757          fBestFitParameters.clear();
00758 
00759          // write best fit parameters
00760          for(int i = 0; i < fNvar; i++)
00761             fBestFitParameters.push_back(randx.at(i));
00762       }
00763 
00764       // write intermediate results
00765       if((i+1)%100000 == 0)
00766          BCLog::OutDebug(Form("BCIntegrate::IntegralMetro. Iteration %d, integral: %g.", i+1, sumI/double(i+1)));
00767    }
00768 
00769    // calculate integral
00770    double result=sumI/Niter;
00771 
00772    // print debug information
00773    BCLog::OutDebug(Form(" --> Integral is %g in %g iterations.", result, Niter));
00774 
00775    return result;
00776 }
00777 
00778 // ---------------------------------------------------------
00779 double BCIntegrate::IntegralImportance(const std::vector<double> & /*x*/)
00780 {
00781    // print debug information
00782    BCLog::OutDebug(Form("BCIntegrate::IntegralImportance. Integate over %i dimensions.", fNvar));
00783 
00784    // get total number of iterations
00785    double Niter = pow(fNiterPerDimension, fNvar);
00786 
00787    // print if more than 100,000 iterations
00788    if(Niter>1e5)
00789       BCLog::OutDebug(Form("BCIntegrate::IntegralImportance. Total number of iterations: %d.", (int)Niter));
00790 
00791    // reset sum
00792    double sumI = 0;
00793 
00794    std::vector<double> randx;
00795    randx.assign(fNvar,0.);
00796 
00797    // prepare maximum value
00798    double pmax = 0.0;
00799 
00800    // loop over iterations
00801    for(int i = 0; i <= Niter; i++) {
00802       // get random point from sampling distribution
00803       GetRandomPointImportance(randx);
00804 
00805       // calculate probability at random point
00806       double val_f = Eval(randx);
00807 
00808       // calculate sampling distributions at that point
00809       double val_g = EvalSampling(randx);
00810 
00811       // add ratio to sum
00812       if (val_g > 0)
00813          sumI += val_f / val_g;
00814 
00815       // search for maximum probability
00816       if (val_f > pmax) {
00817          // set new maximum value
00818          pmax = val_f;
00819 
00820          // delete old best fit parameter values
00821          fBestFitParameters.clear();
00822 
00823          // write best fit parameters
00824          for(int i = 0; i < fNvar; i++)
00825             fBestFitParameters.push_back(randx.at(i));
00826       }
00827 
00828       // write intermediate results
00829       if((i+1)%100000 == 0)
00830          BCLog::OutDebug(Form("BCIntegrate::IntegralImportance : Iteration %d, integral: %g.", i+1, sumI/double(i+1)));
00831    }
00832 
00833    // calculate integral
00834    double result=sumI/Niter;
00835 
00836    // print debug information
00837    BCLog::OutDebug(Form("BCIntegrate::IntegralImportance : Integral %g in %i iterations.", result, (int)Niter));
00838 
00839    return result;
00840 }
00841 
00842 // ---------------------------------------------------------
00843 TH1D* BCIntegrate::Marginalize(BCParameter * parameter)
00844 {
00845    BCLog::OutDebug(Form(" --> Marginalizing model wrt. parameter %s using %s.", parameter->GetName().data(), DumpMarginalizationMethod().c_str()));
00846 
00847    switch(fMarginalizationMethod)
00848    {
00849       case BCIntegrate::kMargMonteCarlo:
00850          return MarginalizeByIntegrate(parameter);
00851 
00852       case BCIntegrate::kMargMetropolis:
00853          return MarginalizeByMetro(parameter);
00854 
00855       default:
00856          BCLog::OutError(
00857             Form("BCIntegrate::Marginalize. Invalid marginalization method: %d. Return 0.", fMarginalizationMethod));
00858          break;
00859 
00860    }
00861 
00862    return 0;
00863 }
00864 
00865 // ---------------------------------------------------------
00866 TH2D * BCIntegrate::Marginalize(BCParameter * parameter1, BCParameter * parameter2)
00867 {
00868    switch(fMarginalizationMethod)
00869    {
00870       case BCIntegrate::kMargMonteCarlo:
00871          return MarginalizeByIntegrate(parameter1,parameter2);
00872 
00873       case BCIntegrate::kMargMetropolis:
00874          return MarginalizeByMetro(parameter1,parameter2);
00875 
00876       default:
00877          BCLog::OutError(
00878             Form("BCIntegrate::Marginalize. Invalid marginalization method: %d. Return 0.", fMarginalizationMethod));
00879          break;
00880    }
00881 
00882    return 0;
00883 }
00884 
00885 // ---------------------------------------------------------
00886 TH1D* BCIntegrate::MarginalizeByIntegrate(BCParameter * parameter)
00887 {
00888    // set parameter to marginalize
00889    ResetVarlist(1);
00890    int index = parameter->GetIndex();
00891    UnsetVar(index);
00892 
00893    // define histogram
00894    double hmin = parameter->GetLowerLimit();
00895    double hmax = parameter->GetUpperLimit();
00896    double hdx  = (hmax - hmin) / double(fNbins);
00897    TH1D * hist = new TH1D("hist","", fNbins, hmin, hmax);
00898 
00899    // integrate
00900    std::vector<double> randx;
00901    randx.assign(fNvar, 0.);
00902 
00903    for(int i=0;i<=fNbins;i++) {
00904       randx[index] = hmin + (double)i * hdx;
00905 
00906       double val = IntegralMC(randx);
00907       hist->Fill(randx[index], val);
00908    }
00909 
00910    // normalize
00911    hist->Scale( 1./hist->Integral("width") );
00912 
00913    return hist;
00914 }
00915 
00916 // ---------------------------------------------------------
00917 TH2D * BCIntegrate::MarginalizeByIntegrate(BCParameter * parameter1, BCParameter * parameter2)
00918 {
00919    // set parameter to marginalize
00920    ResetVarlist(1);
00921    int index1 = parameter1->GetIndex();
00922    UnsetVar(index1);
00923    int index2 = parameter2->GetIndex();
00924    UnsetVar(index2);
00925 
00926    // define histogram
00927    double hmin1 = parameter1->GetLowerLimit();
00928    double hmax1 = parameter1->GetUpperLimit();
00929    double hdx1  = (hmax1 - hmin1) / double(fNbins);
00930 
00931    double hmin2 = parameter2->GetLowerLimit();
00932    double hmax2 = parameter2->GetUpperLimit();
00933    double hdx2  = (hmax2 - hmin2) / double(fNbins);
00934 
00935    TH2D * hist = new TH2D(Form("hist_%s_%s", parameter1->GetName().data(), parameter2->GetName().data()),"",
00936          fNbins, hmin1, hmax1,
00937          fNbins, hmin2, hmax2);
00938 
00939    // integrate
00940    std::vector<double> randx;
00941    randx.assign(fNvar, 0.0);
00942 
00943    for(int i=0;i<=fNbins;i++) {
00944       randx[index1] = hmin1 + (double)i * hdx1;
00945       for(int j=0;j<=fNbins;j++) {
00946          randx[index2] = hmin2 + (double)j * hdx2;
00947 
00948          double val = IntegralMC(randx);
00949          hist->Fill(randx[index1],randx[index2], val);
00950       }
00951    }
00952 
00953    // normalize
00954    hist->Scale(1.0/hist->Integral("width"));
00955 
00956    return hist;
00957 }
00958 
00959 // ---------------------------------------------------------
00960 TH1D * BCIntegrate::MarginalizeByMetro(BCParameter * parameter)
00961 {
00962    int niter = fMarkovChainNIterations;
00963 
00964    if (fMarkovChainAutoN == true)
00965       niter = fNbins*fNbins*fNSamplesPer2DBin*fNvar;
00966 
00967    BCLog::OutDetail(Form(" --> Number of samples in Metropolis marginalization: %d.", niter));
00968 
00969    // set parameter to marginalize
00970    int index = parameter->GetIndex();
00971 
00972    // define histogram
00973    double hmin = parameter->GetLowerLimit();
00974    double hmax = parameter->GetUpperLimit();
00975    TH1D * hist = new TH1D("hist","", fNbins, hmin, hmax);
00976 
00977    // prepare Metro
00978    std::vector<double> randx;
00979    randx.assign(fNvar, 0.0);
00980    InitMetro();
00981 
00982    for(int i=0;i<=niter;i++) {
00983       GetRandomPointMetro(randx);
00984       hist->Fill(randx[index]);
00985    }
00986 
00987    // normalize
00988    hist->Scale(1.0/hist->Integral("width"));
00989 
00990    return hist;
00991 }
00992 
00993 // ---------------------------------------------------------
00994 TH2D * BCIntegrate::MarginalizeByMetro(BCParameter * parameter1, BCParameter * parameter2)
00995 {
00996    int niter=fNbins*fNbins*fNSamplesPer2DBin*fNvar;
00997 
00998    // set parameter to marginalize
00999    int index1 = parameter1->GetIndex();
01000    int index2 = parameter2->GetIndex();
01001 
01002    // define histogram
01003    double hmin1 = parameter1->GetLowerLimit();
01004    double hmax1 = parameter1->GetUpperLimit();
01005 
01006    double hmin2 = parameter2->GetLowerLimit();
01007    double hmax2 = parameter2->GetUpperLimit();
01008 
01009    TH2D * hist = new TH2D(Form("hist_%s_%s", parameter1->GetName().data(), parameter2->GetName().data()),"",
01010          fNbins, hmin1, hmax1,
01011          fNbins, hmin2, hmax2);
01012 
01013    // prepare Metro
01014    std::vector<double> randx;
01015    randx.assign(fNvar, 0.0);
01016    InitMetro();
01017 
01018    for(int i=0;i<=niter;i++) {
01019       GetRandomPointMetro(randx);
01020       hist->Fill(randx[index1],randx[index2]);
01021    }
01022 
01023    // normalize
01024    hist->Scale(1.0/hist->Integral("width"));
01025 
01026    return hist;
01027 }
01028 
01029 // ---------------------------------------------------------
01030 int BCIntegrate::MarginalizeAllByMetro(const char * name="")
01031 {
01032    int niter=fNbins*fNbins*fNSamplesPer2DBin*fNvar;
01033 
01034    BCLog::OutDetail(Form(" --> Number of samples in Metropolis marginalization: %d.", niter));
01035 
01036    // define 1D histograms
01037    for(int i=0;i<fNvar;i++)
01038    {
01039       double hmin1 = fx->at(i)->GetLowerLimit();
01040       double hmax1 = fx->at(i)->GetUpperLimit();
01041 
01042       TH1D * h1 = new TH1D(
01043             TString::Format("h%s_%s", name, fx->at(i)->GetName().data()),"",
01044             fNbins, hmin1, hmax1);
01045 
01046       fHProb1D.push_back(h1);
01047    }
01048 
01049    // define 2D histograms
01050    for(int i=0;i<fNvar-1;i++)
01051       for(int j=i+1;j<fNvar;j++) {
01052          double hmin1 = fx->at(i)->GetLowerLimit();
01053          double hmax1 = fx->at(i)->GetUpperLimit();
01054 
01055          double hmin2 = fx->at(j)->GetLowerLimit();
01056          double hmax2 = fx->at(j)->GetUpperLimit();
01057 
01058          TH2D * h2 = new TH2D(
01059             TString::Format("h%s_%s_%s", name, fx->at(i)->GetName().data(), fx->at(j)->GetName().data()),"",
01060             fNbins, hmin1, hmax1,
01061             fNbins, hmin2, hmax2);
01062 
01063          fHProb2D.push_back(h2);
01064       }
01065 
01066    // get number of 2d distributions
01067    int nh2d = fHProb2D.size();
01068 
01069    BCLog::OutDetail(Form(" --> Marginalizing %d 1D distributions and %d 2D distributions.", fNvar, nh2d));
01070 
01071    // prepare function fitting
01072    double dx = 0.;
01073    double dy = 0.;
01074 
01075    if (fFitFunctionIndexX >= 0) {
01076       dx = (fDataPointUpperBoundaries->GetValue(fFitFunctionIndexX) -
01077             fDataPointLowerBoundaries->GetValue(fFitFunctionIndexX))
01078             / double(fErrorBandNbinsX);
01079 
01080       dx = (fDataPointUpperBoundaries->GetValue(fFitFunctionIndexY) -
01081             fDataPointLowerBoundaries->GetValue(fFitFunctionIndexY))
01082             / double(fErrorBandNbinsY);
01083 
01084       fErrorBandXY = new TH2D(
01085             TString::Format("errorbandxy_%d",BCLog::GetHIndex()), "",
01086             fErrorBandNbinsX,
01087             fDataPointLowerBoundaries->GetValue(fFitFunctionIndexX) - 0.5 * dx,
01088             fDataPointUpperBoundaries->GetValue(fFitFunctionIndexX) + 0.5 * dx,
01089             fErrorBandNbinsY,
01090             fDataPointLowerBoundaries->GetValue(fFitFunctionIndexY) - 0.5 * dy,
01091             fDataPointUpperBoundaries->GetValue(fFitFunctionIndexY) + 0.5 * dy);
01092       fErrorBandXY->SetStats(kFALSE);
01093 
01094       for (int ix = 1; ix <= fErrorBandNbinsX; ++ix)
01095          for (int iy = 1; iy <= fErrorBandNbinsX; ++iy)
01096             fErrorBandXY->SetBinContent(ix, iy, 0.0);
01097    }
01098 
01099    // prepare Metro
01100    std::vector<double> randx;
01101 
01102    randx.assign(fNvar, 0.0);
01103    InitMetro();
01104 
01105    // reset counter
01106    fNacceptedMCMC = 0;
01107 
01108    // run Metro and fill histograms
01109    for(int i=0;i<=niter;i++) {
01110       GetRandomPointMetro(randx);
01111 
01112       // save this point to the markov chain in the ROOT file
01113       if (fFlagWriteMarkovChain) {
01114          fMCMCIteration = i;
01115          fMarkovChainTree->Fill();
01116       }
01117 
01118       for(int j=0;j<fNvar;j++)
01119          fHProb1D[j]->Fill( randx[j] );
01120 
01121       int ih=0;
01122       for(int j=0;j<fNvar-1;j++)
01123          for(int k=j+1;k<fNvar;k++) {
01124             fHProb2D[ih]->Fill(randx[j],randx[k]);
01125             ih++;
01126          }
01127 
01128       if((i+1)%100000==0)
01129          BCLog::OutDebug(Form("BCIntegrate::MarginalizeAllByMetro. %d samples done.",i+1));
01130 
01131       // function fitting
01132 
01133       if (fFitFunctionIndexX >= 0) {
01134          // loop over all possible x values ...
01135          if (fErrorBandContinuous) {
01136             double x = 0;
01137 
01138             for (int ix = 0; ix < fErrorBandNbinsX; ix++) {
01139                // calculate x
01140                x = fErrorBandXY->GetXaxis()->GetBinCenter(ix + 1);
01141 
01142                // calculate y
01143                std::vector<double> xvec;
01144                xvec.push_back(x);
01145                double y = FitFunction(xvec, randx);
01146                xvec.clear();
01147 
01148                // fill histogram
01149                fErrorBandXY->Fill(x, y);
01150             }
01151          }
01152 
01153          // ... or evaluate at the data point x-values
01154          else {
01155             int ndatapoints = int(fErrorBandX.size());
01156             double x = 0;
01157 
01158             for (int ix = 0; ix < ndatapoints; ++ix) {
01159                // calculate x
01160                x = fErrorBandX.at(ix);
01161 
01162                // calculate y
01163                std::vector<double> xvec;
01164                xvec.push_back(x);
01165                double y = FitFunction(xvec, randx);
01166                xvec.clear();
01167 
01168                // fill histogram
01169                fErrorBandXY->Fill(x, y);
01170             }
01171          }
01172       }
01173    }
01174 
01175    // normalize histograms
01176    for(int i=0;i<fNvar;i++)
01177       fHProb1D[i]->Scale( 1./fHProb1D[i]->Integral("width") );
01178 
01179    for (int i=0;i<nh2d;i++)
01180       fHProb2D[i]->Scale( 1./fHProb2D[i]->Integral("width") );
01181 
01182    if (fFitFunctionIndexX >= 0)
01183       fErrorBandXY->Scale(1.0/fErrorBandXY->Integral() * fErrorBandXY->GetNbinsX());
01184 
01185    if (fFitFunctionIndexX >= 0) {
01186       for (int ix = 1; ix <= fErrorBandNbinsX; ix++) {
01187          double sum = 0;
01188 
01189          for (int iy = 1; iy <= fErrorBandNbinsY; iy++)
01190             sum += fErrorBandXY->GetBinContent(ix, iy);
01191 
01192          for (int iy = 1; iy <= fErrorBandNbinsY; iy++) {
01193             double newvalue = fErrorBandXY->GetBinContent(ix, iy) / sum;
01194             fErrorBandXY->SetBinContent(ix, iy, newvalue);
01195          }
01196       }
01197    }
01198 
01199    BCLog::OutDebug(Form("BCIntegrate::MarginalizeAllByMetro done with %i trials and %i accepted trials. Efficiency is %f",fNmetro, fNacceptedMCMC, double(fNacceptedMCMC)/double(fNmetro)));
01200 
01201    return fNvar+nh2d;
01202 }
01203 
01204 // ---------------------------------------------------------
01205 TH1D * BCIntegrate::GetH1D(int parIndex)
01206 {
01207    if(fHProb1D.size()==0) {
01208       BCLog::OutWarning("BCModel::GetH1D. MarginalizeAll() has to be run prior to this to fill the distributions.");
01209       return 0;
01210    }
01211 
01212    if(parIndex<0 || parIndex>fNvar) {
01213       BCLog::OutWarning(Form("BCIntegrate::GetH1D. Parameter index %d is invalid.",parIndex));
01214       return 0;
01215    }
01216 
01217    return fHProb1D[parIndex];
01218 }
01219 
01220 // ---------------------------------------------------------
01221 int BCIntegrate::GetH2DIndex(int parIndex1, int parIndex2)
01222 {
01223    if(parIndex1>fNvar-1 || parIndex1<0) {
01224       BCLog::OutWarning(Form("BCIntegrate::GetH2DIndex. Parameter index %d is invalid", parIndex1));
01225       return -1;
01226    }
01227 
01228    if(parIndex2>fNvar-1 || parIndex2<0) {
01229       BCLog::OutWarning(Form("BCIntegrate::GetH2DIndex. Parameter index %d is invalid", parIndex2));
01230       return -1;
01231    }
01232 
01233    if(parIndex1==parIndex2) {
01234       BCLog::OutWarning(Form("BCIntegrate::GetH2DIndex. Parameters have equal indeces: %d , %d", parIndex1, parIndex2));
01235       return -1;
01236    }
01237 
01238    if(parIndex1>parIndex2) {
01239       BCLog::OutWarning("BCIntegrate::GetH2DIndex. First parameters must be smaller than second (sorry).");
01240       return -1;
01241    }
01242 
01243    int index=0;
01244    for(int i=0;i<fNvar-1;i++)
01245       for(int j=i+1;j<fNvar;j++) {
01246          if(i==parIndex1 && j==parIndex2)
01247             return index;
01248          index++;
01249       }
01250 
01251    BCLog::OutWarning("BCIntegrate::GetH2DIndex. Invalid index combination.");
01252 
01253    return -1;
01254 }
01255 
01256 // ---------------------------------------------------------
01257 TH2D * BCIntegrate::GetH2D(int parIndex1, int parIndex2)
01258 {
01259    if(fHProb2D.size()==0) {
01260       BCLog::OutWarning("BCModel::GetH2D. MarginalizeAll() has to be run prior to this to fill the distributions.");
01261       return 0;
01262    }
01263 
01264    int hindex = GetH2DIndex(parIndex1, parIndex2);
01265    if(hindex==-1)
01266       return 0;
01267 
01268    if(hindex>(int)fHProb2D.size()-1) {
01269       BCLog::OutWarning("BCIntegrate::GetH2D. Got invalid index from GetH2DIndex(). Something went wrong.");
01270       return 0;
01271    }
01272 
01273    return fHProb2D[hindex];
01274 }
01275 
01276 // ---------------------------------------------------------
01277 double BCIntegrate::GetRandomPoint(std::vector<double> &x)
01278 {
01279    GetRandomVector(x);
01280 
01281    for(int i=0;i<fNvar;i++)
01282       x[i]=fMin[i]+x[i]*(fMax[i]-fMin[i]);
01283 
01284    return Eval(x);
01285 }
01286 
01287 // ---------------------------------------------------------
01288 double BCIntegrate::GetRandomPointImportance(std::vector<double> &x)
01289 {
01290    double p = 1.1;
01291    double g = 1.0;
01292 
01293    while (p>g) {
01294       GetRandomVector(x);
01295 
01296       for(int i=0;i<fNvar;i++)
01297          x[i] = fMin[i] + x[i] * (fMax[i]-fMin[i]);
01298 
01299       p = fRandom->Rndm();
01300 
01301       g = EvalSampling(x);
01302    }
01303 
01304    return Eval(x);
01305 }
01306 
01307 // ---------------------------------------------------------
01308 void BCIntegrate::InitMetro()
01309 {
01310    fNmetro=0;
01311 
01312    if (fXmetro0.size() <= 0) {
01313       // start in the center of the phase space
01314       for(int i=0;i<fNvar;i++)
01315          fXmetro0.push_back((fMin[i]+fMax[i])/2.0);
01316    }
01317 
01318    fMarkovChainValue =  LogEval(fXmetro0);
01319 
01320    // run metropolis for a few times and dump the result... (to forget the initial position)
01321    std::vector<double> x;
01322    x.assign(fNvar,0.);
01323 
01324    for(int i=0;i<1000;i++)
01325       GetRandomPointMetro(x);
01326 
01327    fNmetro = 0;
01328 }
01329 
01330 // ---------------------------------------------------------
01331 void BCIntegrate::GetRandomPointMetro(std::vector<double> &x)
01332 {
01333    // get new point
01334    GetRandomVectorMetro(fXmetro1);
01335 
01336    // scale the point to the allowed region and stepsize
01337    int in=1;
01338    for(int i=0;i<fNvar;i++) {
01339       fXmetro1[i] = fXmetro0[i] + fXmetro1[i] * (fMax[i]-fMin[i]);
01340 
01341       // check whether the generated point is inside the allowed region
01342       if( fXmetro1[i]<fMin[i] || fXmetro1[i]>fMax[i] )
01343          in=0;
01344    }
01345 
01346    // calculate the log probabilities and compare old and new point
01347 
01348    double p0 = fMarkovChainValue; // old point
01349    double p1 = 0; // new point
01350    int accept=0;
01351 
01352    if(in) {
01353       p1 = LogEval(fXmetro1);
01354 
01355       if(p1>=p0)
01356          accept=1;
01357       else {
01358          double r=log(fRandom->Rndm());
01359          if(r<p1-p0)
01360             accept=1;
01361       }
01362    }
01363 
01364    // fill the return point after the decision
01365    if(accept) {
01366       // increase counter
01367       fNacceptedMCMC++;
01368 
01369       for(int i=0;i<fNvar;i++) {
01370          fXmetro0[i]=fXmetro1[i];
01371          x[i]=fXmetro1[i];
01372          fMarkovChainValue = p1;
01373       }
01374    }
01375    else
01376       for(int i=0;i<fNvar;i++) {
01377          x[i]=fXmetro0[i];
01378          fXmetro1[i] = x[i];
01379          fMarkovChainValue = p0;
01380       }
01381 
01382    fNmetro++;
01383 }
01384 
01385 // ---------------------------------------------------------
01386 void BCIntegrate::GetRandomPointSamplingMetro(std::vector<double> &x)
01387 {
01388    // get new point
01389    GetRandomVectorMetro(fXmetro1);
01390 
01391    // scale the point to the allowed region and stepsize
01392    int in=1;
01393    for(int i=0;i<fNvar;i++) {
01394       fXmetro1[i] = fXmetro0[i] + fXmetro1[i] * (fMax[i]-fMin[i]);
01395 
01396       // check whether the generated point is inside the allowed region
01397       if( fXmetro1[i]<fMin[i] || fXmetro1[i]>fMax[i] )
01398          in=0;
01399    }
01400 
01401    // calculate the log probabilities and compare old and new point
01402    double p0 = LogEvalSampling(fXmetro0); // old point
01403    double p1=0; // new point
01404    if(in)
01405       p1= LogEvalSampling(fXmetro1);
01406 
01407    // compare log probabilities
01408    int accept=0;
01409    if(in) {
01410       if(p1>=p0)
01411          accept=1;
01412       else {
01413          double r=log(fRandom->Rndm());
01414          if(r<p1-p0)
01415             accept=1;
01416       }
01417    }
01418 
01419    // fill the return point after the decision
01420    if(accept)
01421       for(int i=0;i<fNvar;i++) {
01422          fXmetro0[i]=fXmetro1[i];
01423          x[i]=fXmetro1[i];
01424       }
01425    else
01426       for(int i=0;i<fNvar;i++)
01427          x[i]=fXmetro0[i];
01428 
01429    fNmetro++;
01430 }
01431 
01432 // ---------------------------------------------------------
01433 void BCIntegrate::GetRandomVector(std::vector<double> &x)
01434 {
01435    double * randx = new double[fNvar];
01436 
01437    fRandom->RndmArray(fNvar, randx);
01438 
01439    for(int i=0;i<fNvar;i++)
01440       x[i] = randx[i];
01441 
01442    delete[] randx;
01443    randx = 0;
01444 }
01445 
01446 // ---------------------------------------------------------
01447 void BCIntegrate::GetRandomVectorMetro(std::vector<double> &x)
01448 {
01449    double * randx = new double[fNvar];
01450 
01451    fRandom->RndmArray(fNvar, randx);
01452 
01453    for(int i=0;i<fNvar;i++)
01454       x[i] = 2.0 * (randx[i] - 0.5) * fMarkovChainStepSize;
01455 
01456    delete[] randx;
01457    randx = 0;
01458 }
01459 
01460 // ---------------------------------------------------------
01461 TMinuit * BCIntegrate::GetMinuit()
01462 {
01463    if (!fMinuit)
01464       fMinuit = new TMinuit();
01465 
01466    return fMinuit;
01467 }
01468 
01469 // ---------------------------------------------------------
01470 
01471 void BCIntegrate::FindModeMinuit(std::vector<double> start, int printlevel)
01472 {
01473    bool have_start = true;
01474 
01475    // check start values
01476    if (int(start.size()) != fNvar)
01477       have_start = false;
01478 
01479    // set global this
01480    global_this = this;
01481 
01482    // define minuit
01483    if (fMinuit)
01484       delete fMinuit;
01485    fMinuit = new TMinuit(fNvar);
01486 
01487    // set print level
01488    fMinuit->SetPrintLevel(printlevel);
01489 
01490    // set function
01491    fMinuit->SetFCN(&BCIntegrate::FCNLikelihood);
01492 
01493    // set UP for likelihood
01494    fMinuit->SetErrorDef(0.5);
01495 
01496    // set parameters
01497    int flag;
01498    for (int i = 0; i < fNvar; i++) {
01499       double starting_point = (fMin[i]+fMax[i])/2.;
01500       if(have_start)
01501          starting_point = start[i];
01502          fMinuit->mnparm(i,
01503                          fx->at(i)->GetName().data(),
01504                          starting_point,
01505                          (fMax[i]-fMin[i])/100.,
01506                          fMin[i],
01507                          fMax[i],
01508                          flag);
01509    }
01510 
01511    // do mcmc minimization
01512    //   fMinuit->mnseek();
01513 
01514    // do minimization
01515    fMinuit->mnexcm("MIGRAD", fMinuitArglist, 2, flag);
01516 
01517    // improve search for local minimum
01518    //   fMinuit->mnimpr();
01519 
01520    // copy flag
01521    fMinuitErrorFlag = flag;
01522 
01523    // check if mode found by minuit is better than previous estimation
01524    double probmax = 0;
01525    bool valid = false;
01526 
01527    if ( int(fBestFitParameters.size()) == fNvar) {
01528       valid = true;
01529       for (int i = 0; i < fNvar; ++i)
01530          if (fBestFitParameters.at(i) < fMin[i] || fBestFitParameters.at(i) > fMax[i])
01531             valid= false;
01532 
01533       if (valid)
01534          probmax = Eval( fBestFitParameters );
01535    }
01536 
01537    std::vector<double> tempvec;
01538    for (int i = 0; i < fNvar; i++) {
01539       double par;
01540       double parerr;
01541       fMinuit->GetParameter(i, par, parerr);
01542       tempvec.push_back(par);
01543    }
01544    double probmaxminuit = Eval( tempvec );
01545 
01546    // set best fit parameters
01547    if ( (probmaxminuit > probmax && !fFlagIgnorePrevOptimization) || !valid || fFlagIgnorePrevOptimization) {
01548       fBestFitParameters.clear();
01549       fBestFitParameterErrors.clear();
01550 
01551       for (int i = 0; i < fNvar; i++) {
01552          double par;
01553          double parerr;
01554          fMinuit->GetParameter(i, par, parerr);
01555          fBestFitParameters.push_back(par);
01556          fBestFitParameterErrors.push_back(parerr);
01557       }
01558 
01559       // set optimization method used to find the mode
01560       fOptimizationMethodMode = BCIntegrate::kOptMinuit;
01561    }
01562 
01563    // delete minuit
01564    fMinuit = 0;
01565 
01566    return;
01567 }
01568 
01569 // ---------------------------------------------------------
01570 void BCIntegrate::InitializeSATree()
01571 {
01572   if (fTreeSA)
01573     delete fTreeSA;
01574   fTreeSA = new TTree("SATree", "SATree");
01575 
01576    fTreeSA->Branch("Iteration",      &fSANIterations,   "iteration/I");
01577    fTreeSA->Branch("NParameters",    &fNvar,            "parameters/I");
01578    fTreeSA->Branch("Temperature",    &fSATemperature,   "temperature/D");
01579    fTreeSA->Branch("LogProbability", &fSALogProb,       "log(probability)/D");
01580 
01581    for (int i = 0; i < fNvar; ++i)
01582       fTreeSA->Branch(TString::Format("Parameter%i", i), &fSAx[i], TString::Format("parameter %i/D", i));
01583 }
01584 
01585 // ---------------------------------------------------------
01586 void BCIntegrate::FindModeSA(std::vector<double> start)
01587 {
01588    // note: if f(x) is the function to be minimized, then
01589    // f(x) := - LogEval(parameters)
01590 
01591    bool have_start = true;
01592    std::vector<double> x, y, best_fit; // vectors for current state, new proposed state and best fit up to now
01593    double fval_x, fval_y, fval_best_fit; // function values at points x, y and best_fit (we save them rather than to re-calculate them every time)
01594    int t = 1; // time iterator
01595 
01596    // check start values
01597    if (int(start.size()) != fNvar)
01598       have_start = false;
01599 
01600    // if no starting point is given, set to center of parameter space
01601    if ( !have_start ) {
01602       start.clear();
01603       for (int i = 0; i < fNvar; i++)
01604          start.push_back((fMin[i]+fMax[i])/2.);
01605    }
01606 
01607    // set current state and best fit to starting point
01608    x.clear();
01609    best_fit.clear();
01610    for (int i = 0; i < fNvar; i++) {
01611       x.push_back(start[i]);
01612       best_fit.push_back(start[i]);
01613    }
01614    // calculate function value at starting point
01615    fval_x = fval_best_fit = LogEval(x);
01616 
01617    // run while still "hot enough"
01618    while ( SATemperature(t) > fSATmin ) {
01619       // generate new state
01620       y = GetProposalPointSA(x, t);
01621 
01622       // check if the proposed point is inside the phase space
01623       // if not, reject it
01624       bool is_in_ranges = true;
01625 
01626       for (int i = 0; i < fNvar; i++)
01627          if (y[i] > fMax[i] || y[i] < fMin[i])
01628             is_in_ranges = false;
01629 
01630       if ( !is_in_ranges )
01631          ; // do nothing...
01632       else {
01633          // calculate function value at new point
01634          fval_y = LogEval(y);
01635 
01636          // is it better than the last one?
01637          // if so, update state and chef if it is the new best fit...
01638          if (fval_y >= fval_x) {
01639             x.clear();
01640             for (int i = 0; i < fNvar; i++)
01641                x.push_back(y[i]);
01642 
01643             fval_x = fval_y;
01644 
01645             if (fval_y > fval_best_fit) {
01646                best_fit.clear();
01647                for (int i = 0; i < fNvar; i++)
01648                   best_fit.push_back(y[i]);
01649 
01650                fval_best_fit = fval_y;
01651             }
01652          }
01653          // ...else, only accept new state w/ certain probability
01654          else {
01655             if (fRandom->Rndm() <= exp( (fval_y - fval_x) / SATemperature(t) )) {
01656                x.clear();
01657                for (int i = 0; i < fNvar; i++)
01658                   x.push_back(y[i]);
01659 
01660                fval_x = fval_y;
01661             }
01662          }
01663       }
01664 
01665       // update tree variables
01666       fSANIterations = t;
01667       fSATemperature = SATemperature(t);
01668       fSALogProb = fval_x;
01669       fSAx.clear();
01670       for (int i = 0; i < fNvar; ++i)
01671          fSAx.push_back(x[i]);
01672 
01673       // fill tree
01674       if (fFlagWriteSAToFile)
01675          fTreeSA->Fill();
01676 
01677       // increate t
01678       t++;
01679    }
01680 
01681    // check if mode found by minuit is better than previous estimation
01682    double probmax = 0;
01683    bool valid = false;
01684 
01685    if ( int(fBestFitParameters.size()) == fNvar) {
01686       valid = true;
01687       for (int i = 0; i < fNvar; ++i)
01688          if (fBestFitParameters.at(i) < fMin[i] || fBestFitParameters.at(i) > fMax[i])
01689             valid= false;
01690 
01691       if (valid)
01692          probmax = Eval( fBestFitParameters );
01693    }
01694 
01695    double probmaxsa = Eval( best_fit);
01696 
01697    if ( (probmaxsa > probmax  && !fFlagIgnorePrevOptimization) || !valid || fFlagIgnorePrevOptimization) {
01698       // set best fit parameters
01699       fBestFitParameters.clear();
01700       fBestFitParameterErrors.clear();
01701 
01702       for (int i = 0; i < fNvar; i++) {
01703          fBestFitParameters.push_back(best_fit[i]);
01704          fBestFitParameterErrors.push_back(-1.); // error undefined
01705       }
01706 
01707       // set optimization moethod used to find the mode
01708       fOptimizationMethodMode = BCIntegrate::kOptSA;
01709    }
01710 
01711    return;
01712 }
01713 
01714 // ---------------------------------------------------------
01715 double BCIntegrate::SATemperature(double t)
01716 {
01717    // do we have Cauchy (default), Boltzmann or custom annealing schedule?
01718    if (fSASchedule == BCIntegrate::kSABoltzmann)
01719       return SATemperatureBoltzmann(t);
01720    else if (fSASchedule == BCIntegrate::kSACauchy)
01721       return SATemperatureCauchy(t);
01722    else
01723       return SATemperatureCustom(t);
01724 }
01725 
01726 // ---------------------------------------------------------
01727 double BCIntegrate::SATemperatureBoltzmann(double t)
01728 {
01729    return fSAT0 / log((double)(t + 1));
01730 }
01731 
01732 // ---------------------------------------------------------
01733 double BCIntegrate::SATemperatureCauchy(double t)
01734 {
01735    return fSAT0 / (double)t;
01736 }
01737 
01738 // ---------------------------------------------------------
01739 double BCIntegrate::SATemperatureCustom(double /*t*/)
01740 {
01741    BCLog::OutError("BCIntegrate::SATemperatureCustom : No custom temperature schedule defined");
01742    return 0.;
01743 }
01744 
01745 // ---------------------------------------------------------
01746 std::vector<double> BCIntegrate::GetProposalPointSA(const std::vector<double> &x, int t)
01747 {
01748    // do we have Cauchy (default), Boltzmann or custom annealing schedule?
01749    if (fSASchedule == BCIntegrate::kSABoltzmann)
01750       return GetProposalPointSABoltzmann(x, t);
01751    else if (fSASchedule == BCIntegrate::kSACauchy)
01752       return GetProposalPointSACauchy(x, t);
01753    else
01754       return GetProposalPointSACustom(x, t);
01755 }
01756 
01757 // ---------------------------------------------------------
01758 std::vector<double> BCIntegrate::GetProposalPointSABoltzmann(const std::vector<double> &x, int t)
01759 {
01760    std::vector<double> y;
01761    y.clear();
01762    double new_val, norm;
01763 
01764    for (int i = 0; i < fNvar; i++) {
01765       norm = (fMax[i] - fMin[i]) * SATemperature(t) / 2.;
01766       new_val = x[i] + norm * fRandom->Gaus();
01767       y.push_back(new_val);
01768    }
01769 
01770    return y;
01771 }
01772 
01773 // ---------------------------------------------------------
01774 std::vector<double> BCIntegrate::GetProposalPointSACauchy(const std::vector<double> &x, int t)
01775 {
01776    std::vector<double> y;
01777    y.clear();
01778 
01779    if (fNvar == 1) {
01780       double cauchy, new_val, norm;
01781 
01782       norm = (fMax[0] - fMin[0]) * SATemperature(t) / 2.;
01783       cauchy = tan(3.14159 * (fRandom->Rndm() - 0.5));
01784       new_val = x[0] + norm * cauchy;
01785       y.push_back(new_val);
01786    }
01787    else {
01788       // use sampling to get radial n-dim Cauchy distribution
01789 
01790       // first generate a random point uniformly distributed on a
01791       // fNvar-dimensional hypersphere
01792       y = SAHelperGetRandomPointOnHypersphere();
01793 
01794       // scale the vector by a random factor determined by the radial
01795       // part of the fNvar-dimensional Cauchy distribution
01796       double radial = SATemperature(t) * SAHelperGetRadialCauchy();
01797 
01798       // scale y by radial part and the size of dimension i in phase space
01799       // afterwards, move by x
01800       for (int i = 0; i < fNvar; i++)
01801          y[i] = (fMax[i] - fMin[i]) * y[i] * radial / 2. + x[i];
01802    }
01803 
01804    return y;
01805 }
01806 
01807 // ---------------------------------------------------------
01808 std::vector<double> BCIntegrate::GetProposalPointSACustom(const std::vector<double> & /*x*/, int /*t*/)
01809 {
01810    BCLog::OutError("BCIntegrate::GetProposalPointSACustom : No custom proposal function defined");
01811    return std::vector<double>(fNvar);
01812 }
01813 
01814 // ---------------------------------------------------------
01815 std::vector<double> BCIntegrate::SAHelperGetRandomPointOnHypersphere()
01816 {
01817    std::vector<double> rand_point(fNvar);
01818 
01819    // This method can only be called with fNvar >= 2 since the 1-dim case
01820    // is already hard wired into the Cauchy annealing proposal function.
01821    // To speed things up, hard-code fast method for 2 and dimensions.
01822    // The algorithm for 2D can be found at
01823    // http://mathworld.wolfram.com/CirclePointPicking.html
01824    // For 3D just using ROOT's algorithm.
01825    if (fNvar == 2) {
01826       double x1, x2, s;
01827       do {
01828          x1 = fRandom->Rndm() * 2. - 1.;
01829          x2 = fRandom->Rndm() * 2. - 1.;
01830          s = x1*x1 + x2*x2;
01831       }
01832       while (s >= 1);
01833 
01834       rand_point[0] = (x1*x1 - x2*x2) / s;
01835       rand_point[1] = (2.*x1*x2) / s;
01836    }
01837    else if (fNvar == 3) {
01838       fRandom->Sphere(rand_point[0], rand_point[1], rand_point[2], 1.0);
01839    }
01840    else {
01841       double s = 0.,
01842          gauss_num;
01843 
01844       for (int i = 0; i < fNvar; i++) {
01845          gauss_num = fRandom->Gaus();
01846          rand_point[i] = gauss_num;
01847          s += gauss_num * gauss_num;
01848       }
01849       s = sqrt(s);
01850 
01851       for (int i = 0; i < fNvar; i++)
01852          rand_point[i] = rand_point[i] / s;
01853    }
01854 
01855    return rand_point;
01856 }
01857 
01858 // ---------------------------------------------------------
01859 double BCIntegrate::SAHelperGetRadialCauchy()
01860 {
01861    // theta is sampled from a rather complicated distribution,
01862    // so first we create a lookup table with 10000 random numbers
01863    // once and then, each time we need a new random number,
01864    // we just look it up in the table.
01865    double theta;
01866 
01867    // static vectors for theta-sampling-map
01868    static double map_u[10001];
01869    static double map_theta[10001];
01870    static bool initialized = false;
01871    static int map_dimension = 0;
01872 
01873    // is the lookup-table already initialized? if not, do it!
01874    if (!initialized || map_dimension != fNvar) {
01875       double init_theta;
01876       double beta = SAHelperSinusToNIntegral(fNvar - 1, 1.57079632679);
01877 
01878       for (int i = 0; i <= 10000; i++) {
01879          init_theta = 3.14159265 * (double)i / 5000.;
01880          map_theta[i] = init_theta;
01881 
01882          map_u[i] = SAHelperSinusToNIntegral(fNvar - 1, init_theta) / beta;
01883       }
01884 
01885       map_dimension = fNvar;
01886       initialized = true;
01887    } // initializing is done.
01888 
01889    // generate uniform random number for sampling
01890    double u = fRandom->Rndm();
01891 
01892    // Find the two elements just greater than and less than u
01893    // using a binary search (O(log(N))).
01894    int lo = 0;
01895    int up = 10000;
01896    int mid;
01897 
01898    while (up != lo) {
01899       mid = ((up - lo + 1) / 2) + lo;
01900 
01901       if (u >= map_u[mid])
01902          lo = mid;
01903       else
01904          up = mid - 1;
01905    }
01906    up++;
01907 
01908    // perform linear interpolation:
01909    theta = map_theta[lo] + (u - map_u[lo]) / (map_u[up] - map_u[lo]) * (map_theta[up] - map_theta[lo]);
01910 
01911    return tan(theta);
01912 }
01913 
01914 // ---------------------------------------------------------
01915 double BCIntegrate::SAHelperSinusToNIntegral(int dim, double theta)
01916 {
01917    if (dim < 1)
01918       return theta;
01919    else if (dim == 1)
01920       return (1. - cos(theta));
01921    else if (dim == 2)
01922       return 0.5 * (theta - sin(theta) * cos(theta));
01923    else if (dim == 3)
01924       return (2. - sin(theta) * sin(theta) * cos(theta) - 2. * cos(theta)) / 3.;
01925    else
01926       return - pow(sin(theta), (double)(dim - 1)) * cos(theta) / (double)dim
01927          + (double)(dim - 1) / (double)dim
01928          * SAHelperSinusToNIntegral(dim - 2, theta);
01929 }
01930 
01931 // ---------------------------------------------------------
01932 
01933 void BCIntegrate::SetMode(std::vector<double> mode)
01934 {
01935    if((int)mode.size() == fNvar) {
01936       fBestFitParameters.clear();
01937       for (int i = 0; i < fNvar; i++)
01938          fBestFitParameters.push_back(mode[i]);
01939    }
01940 }
01941 
01942 // ---------------------------------------------------------
01943 
01944 void BCIntegrate::FCNLikelihood(int & /*npar*/, double * /*grad*/, double &fval, double * par, int /*flag*/)
01945 {
01946    // copy parameters
01947    std::vector<double> parameters;
01948 
01949    int n = global_this->GetNvar();
01950 
01951    for (int i = 0; i < n; i++)
01952       parameters.push_back(par[i]);
01953 
01954    fval = - global_this->LogEval(parameters);
01955 
01956    // delete parameters
01957    parameters.clear();
01958 }
01959 
01960 // ---------------------------------------------------------
01961 
01962 //void BCIntegrate::FindModeMCMC(int flag_run)
01963 void BCIntegrate::FindModeMCMC()
01964 {
01965    // call PreRun
01966 //   if (flag_run == 0)
01967    if (!fMCMCFlagPreRun)
01968       MCMCMetropolisPreRun();
01969 
01970    // find global maximum
01971    //   double probmax = (MCMCGetMaximumLogProb()).at(0);
01972 
01973    double probmax = 0;
01974 
01975    if ( int(fBestFitParameters.size()) == fNvar) {
01976       probmax = Eval( fBestFitParameters );
01977 //      fBestFitParameters = MCMCGetMaximumPoint(0);
01978    }
01979 
01980    // loop over all chains and find the maximum point
01981    for (int i = 0; i < fMCMCNChains; ++i) {
01982       double prob = exp( (MCMCGetMaximumLogProb()).at(i));
01983 
01984       // copy the point into the vector
01985       if ( (prob >= probmax && !fFlagIgnorePrevOptimization) || fFlagIgnorePrevOptimization) {
01986          probmax = prob;
01987 
01988          fBestFitParameters.clear();
01989          fBestFitParameterErrors.clear();
01990          fBestFitParameters = MCMCGetMaximumPoint(i);
01991 
01992          for (int j = 0; j < fNvar; ++j)
01993             fBestFitParameterErrors.push_back(-1.); // error undefined
01994 
01995          fOptimizationMethodMode = BCIntegrate::kOptMetropolis;
01996       }
01997    }
01998 }
01999 
02000 // ---------------------------------------------------------
02001 void BCIntegrate::SetCubaIntegrationMethod(BCIntegrate::BCCubaMethod type)
02002 {
02003 #ifdef HAVE_CUBA_H
02004    switch(type) {
02005       case BCIntegrate::kCubaVegas:
02006       case BCIntegrate::kCubaSuave:
02007          fCubaIntegrationMethod = type;
02008          return;
02009       case BCIntegrate::kCubaDivonne:
02010       case BCIntegrate::kCubaCuhre:
02011          BCLog::OutError(TString::Format(
02012             "BAT does not yet support global setting of Cuba integration method to %s. "
02013             "To use this method use explicit call to CubaIntegrate() with arguments.",
02014             DumpCubaIntegrationMethod(type).c_str()));
02015          return;
02016       default:
02017          BCLog::OutError(TString::Format("Integration method of type %d is not defined for Cuba",type));
02018          return;
02019    }
02020 #else
02021    BCLog::OutWarning("!!! This version of BAT is compiled without Cuba.");
02022    BCLog::OutWarning("    Setting Cuba integration method will have no effect.");
02023 #endif
02024 }
02025 
02026 // ---------------------------------------------------------
02027 int BCIntegrate::CubaIntegrand(const int *ndim, const double xx[],
02028                                               const int * /*ncomp*/, double ff[], void * /*userdata*/)
02029 {
02030 #ifdef HAVE_CUBA_H
02031    // scale variables
02032    double jacobian = 1.0;
02033 
02034    std::vector<double> scaled_parameters;
02035 
02036    for (int i = 0; i < *ndim; i++) {
02037       double range = global_this->fx->at(i)->GetUpperLimit() - global_this->fx->at(i)->GetLowerLimit();
02038 
02039       // multiply range to jacobian
02040       jacobian *= range;
02041 
02042       // get the scaled parameter value
02043       scaled_parameters.push_back(global_this->fx->at(i)->GetLowerLimit() + xx[i] * range);
02044    }
02045 
02046    // call function to integrate
02047    ff[0] = global_this->Eval(scaled_parameters);
02048 
02049    // multiply jacobian
02050    ff[0] *= jacobian;
02051 
02052    // multiply fudge factor
02053    ff[0] *= 1e99;
02054 
02055    // remove parameter vector
02056    scaled_parameters.clear();
02057 #else
02058    BCLog::OutError("!!! This version of BAT is compiled without Cuba.");
02059    BCLog::OutError("    Use other integration methods or install Cuba and recompile BAT.");
02060 
02061    return 1;
02062 #endif
02063 
02064    return 0;
02065 }
02066 
02067 // ---------------------------------------------------------
02068 double BCIntegrate::CubaIntegrate()
02069 {
02070 #ifdef HAVE_CUBA_H
02071    std::vector<double> parameters_double;
02072    std::vector<double>    parameters_int;
02073 
02074    parameters_double.push_back(fRelativePrecision);
02075    parameters_double.push_back(fAbsolutePrecision);
02076 
02077    parameters_int.push_back(fCubaVerbosity);
02078    parameters_int.push_back(fCubaMinEval);
02079    parameters_int.push_back(fCubaMaxEval);
02080 
02081    switch (fCubaIntegrationMethod) {
02082       case BCIntegrate::kCubaSuave:
02083          parameters_int.push_back(fCubaSuaveNNew);
02084          parameters_double.push_back(fCubaSuaveFlatness);
02085          break;
02086       case BCIntegrate::kCubaDivonne:
02087          break;
02088       case BCIntegrate::kCubaCuhre:
02089          break;
02090       default: // if unknown method run Vegas. Shouldn't ever happen anyway
02091       case BCIntegrate::kCubaVegas:
02092          parameters_int.push_back(fCubaVegasNStart);
02093          parameters_int.push_back(fCubaVegasNIncrease);
02094    }
02095 
02096    // print to log
02097    BCLog::OutDebug( Form(" --> Running Cuba/%s integation over %i dimensions.", DumpCubaIntegrationMethod().c_str(), fNvar));
02098    BCLog::OutDebug( Form(" --> Maximum number of iterations: %i", fCubaMaxEval));
02099    BCLog::OutDebug( Form(" --> Aimed relative precision:     %e", fRelativePrecision));
02100 
02101    return CubaIntegrate(fCubaIntegrationMethod, parameters_double, parameters_int);
02102 #else
02103    BCLog::OutError("!!! This version of BAT is compiled without Cuba.");
02104    BCLog::OutError("    Use other integration methods or install Cuba and recompile BAT.");
02105    return 0.;
02106 #endif
02107 }
02108 
02109 // ---------------------------------------------------------
02110 double BCIntegrate::CubaIntegrate(BCIntegrate::BCCubaMethod method, std::vector<double> parameters_double, std::vector<double> parameters_int)
02111 {
02112 #ifdef HAVE_CUBA_H
02113    const int NDIM      = int(fx ->size());
02114    const int NCOMP     = 1;
02115    const int USERDATA  = 0;
02116    const int SEED      = 0;
02117    const int NBATCH    = 1000;
02118    const int GRIDNO    = -1;
02119    const char*STATEFILE = "";
02120 
02121    const double EPSREL = parameters_double[0];
02122    const double EPSABS = parameters_double[1];
02123    const int VERBOSE   = int(parameters_int[0]);
02124    const int MINEVAL   = int(parameters_int[1]);
02125    const int MAXEVAL   = int(parameters_int[2]);
02126 
02127    int neval;
02128    int fail;
02129    int nregions;
02130    double integral[NCOMP];
02131    double error[NCOMP];
02132    double prob[NCOMP];
02133 
02134    global_this = this;
02135 
02136    integrand_t an_integrand = &BCIntegrate::CubaIntegrand;
02137 
02138    if (method == 0) {
02139       // set VEGAS specific parameters
02140       const int NSTART    = int(parameters_int[3]);
02141       const int NINCREASE = int(parameters_int[4]);
02142 
02143       // call VEGAS integration method
02144       Vegas(NDIM, NCOMP, an_integrand, USERDATA,
02145             EPSREL, EPSABS, VERBOSE, SEED,
02146             MINEVAL, MAXEVAL, NSTART, NINCREASE, NBATCH,
02147             GRIDNO, STATEFILE,
02148             &neval, &fail, integral, error, prob);
02149 
02150       // interface for Cuba version 1.5
02151       /*
02152       Vegas(NDIM, NCOMP, an_integrand,
02153             EPSREL, EPSABS, VERBOSE, MINEVAL, MAXEVAL,
02154             NSTART, NINCREASE,
02155             &neval, &fail, integral, error, prob);
02156       */
02157    }
02158    else if (method == 1) {
02159       // set SUAVE specific parameters
02160        //      const int LAST     = int(parameters_int[3]);
02161       const int NNEW        = int(parameters_int[3]);
02162       const double FLATNESS = parameters_double[2];
02163 
02164       // call SUAVE integration method
02165       Suave(NDIM, NCOMP, an_integrand,
02166             USERDATA, EPSREL, EPSABS, VERBOSE, SEED,
02167             MINEVAL, MAXEVAL,
02168             NNEW, FLATNESS,
02169             &nregions, &neval, &fail, integral, error, prob);
02170 
02171       // interface for Cuba version 1.5
02172       /*
02173       Suave(NDIM, NCOMP, an_integrand,
02174             EPSREL, EPSABS, VERBOSE | LAST, MINEVAL, MAXEVAL,
02175             NNEW, FLATNESS,
02176             &nregions, &neval, &fail, integral, error, prob);
02177       */
02178    }
02179    else if (method == 2) {
02180       // set DIVONNE specific parameters
02181       const int KEY1         = int(parameters_int[3]);
02182       const int KEY2         = int(parameters_int[4]);
02183       const int KEY3         = int(parameters_int[5]);
02184       const int MAXPASS      = int(parameters_int[6]);
02185       const int BORDER       = int(parameters_int[7]);
02186       const int MAXCHISQ     = int(parameters_int[8]);
02187       const int MINDEVIATION = int(parameters_int[9]);
02188       const int NGIVEN       = int(parameters_int[10]);
02189       const int LDXGIVEN     = int(parameters_int[11]);
02190       const int NEXTRA       = int(parameters_int[12]);
02191       const int FLAGS    = 0;
02192 
02193       // call DIVONNE integration method
02194       Divonne(NDIM, NCOMP, an_integrand, USERDATA,
02195               EPSREL, EPSABS, FLAGS, SEED, MINEVAL, MAXEVAL,
02196               KEY1, KEY2, KEY3, MAXPASS, BORDER, MAXCHISQ, MINDEVIATION,
02197               NGIVEN, LDXGIVEN, NULL, NEXTRA, NULL,
02198               &nregions, &neval, &fail, integral, error, prob);
02199 
02200 
02201       // interface for Cuba version 1.5
02202       /*
02203       Divonne(NDIM, NCOMP, an_integrand,
02204               EPSREL, EPSABS, VERBOSE, MINEVAL, MAXEVAL,
02205               KEY1, KEY2, KEY3, MAXPASS, BORDER, MAXCHISQ, MINDEVIATION,
02206               NGIVEN, LDXGIVEN, NULL, NEXTRA, NULL,
02207               &nregions, &neval, &fail, integral, error, prob);
02208       */
02209    }
02210    else if (method == 3) {
02211       // set CUHRE specific parameters
02212       //const int LAST = int(parameters_int[3]);
02213       const int KEY  = int(parameters_int[4]);
02214       const int FLAGS    = 0;
02215 
02216       // call CUHRE integration method
02217       Cuhre(NDIM, NCOMP, an_integrand, USERDATA,
02218             EPSREL, EPSABS, FLAGS, MINEVAL, MAXEVAL, KEY,
02219             &nregions, &neval, &fail, integral, error, prob);
02220 
02221       // interface for Cuba version 1.5
02222       /*
02223       Cuhre(NDIM, NCOMP, an_integrand,
02224             EPSREL, EPSABS, VERBOSE | LAST, MINEVAL, MAXEVAL, KEY,
02225             &nregions, &neval, &fail, integral, error, prob);
02226       */
02227    }
02228    else {
02229       std::cout << " Integration method not available. " << std::endl;
02230       integral[0] = -1e99;
02231    }
02232 
02233    if (fail != 0) {
02234       std::cout << " Warning, integral did not converge with the given set of parameters. "<< std::endl;
02235       std::cout << " neval    = " << neval       << std::endl;
02236       std::cout << " fail     = " << fail        << std::endl;
02237       std::cout << " integral = " << integral[0] << std::endl;
02238       std::cout << " error    = " << error[0]    << std::endl;
02239       std::cout << " prob     = " << prob[0]     << std::endl;
02240    }
02241 
02242    return integral[0] / 1e99;
02243 #else
02244    BCLog::OutError("!!! This version of BAT is compiled without Cuba.");
02245    BCLog::OutError("    Use other integration methods or install Cuba and recompile BAT.");
02246    return 0.;
02247 #endif
02248 }
02249 
02250 // ---------------------------------------------------------
02251 void BCIntegrate::MCMCIterationInterface()
02252 {
02253    // what's within this method will be executed
02254    // for every iteration of the MCMC
02255 
02256    // fill error band
02257    MCMCFillErrorBand();
02258 
02259    // do user defined stuff
02260    MCMCUserIterationInterface();
02261 }
02262 
02263 // ---------------------------------------------------------
02264 void BCIntegrate::MCMCFillErrorBand()
02265 {
02266    if (!fFillErrorBand)
02267       return;
02268 
02269    // function fitting
02270    if (fFitFunctionIndexX < 0)
02271       return;
02272 
02273    // loop over all possible x values ...
02274    if (fErrorBandContinuous) {
02275       double x = 0;
02276       for (int ix = 0; ix < fErrorBandNbinsX; ix++) {
02277          // calculate x
02278          x = fErrorBandXY->GetXaxis()->GetBinCenter(ix + 1);
02279 
02280          // calculate y
02281          std::vector<double> xvec;
02282          xvec.push_back(x);
02283 
02284          // loop over all chains
02285          for (int ichain = 0; ichain < MCMCGetNChains(); ++ichain) {
02286             // calculate y
02287             double y = FitFunction(xvec, MCMCGetx(ichain));
02288 
02289             // fill histogram
02290             fErrorBandXY->Fill(x, y);
02291          }
02292 
02293          xvec.clear();
02294       }
02295    }
02296    // ... or evaluate at the data point x-values
02297    else {
02298       int ndatapoints = int(fErrorBandX.size());
02299       double x = 0;
02300 
02301       for (int ix = 0; ix < ndatapoints; ++ix) {
02302          // calculate x
02303          x = fErrorBandX.at(ix);
02304 
02305          // calculate y
02306          std::vector<double> xvec;
02307          xvec.push_back(x);
02308 
02309          // loop over all chains
02310          for (int ichain = 0; ichain < MCMCGetNChains(); ++ichain) {
02311             // calculate y
02312             double y = FitFunction(xvec, MCMCGetx(ichain));
02313 
02314             // fill histogram
02315             fErrorBandXY->Fill(x, y);
02316          }
02317 
02318          xvec.clear();
02319       }
02320    }
02321 }
02322 
02323 // ---------------------------------------------------------
02324 void BCIntegrate::SAInitialize()
02325 {
02326    fSAx.clear();
02327    fSAx.assign(fNvar, 0.0);
02328 }
02329 
02330 // ---------------------------------------------------------
02331 std::string BCIntegrate::DumpIntegrationMethod(BCIntegrate::BCIntegrationMethod type)
02332 {
02333    switch(type) {
02334       case BCIntegrate::kIntMonteCarlo:
02335          return "Sampled Mean Monte Carlo";
02336       case BCIntegrate::kIntImportance:
02337          return "Importance Sampling";
02338       case BCIntegrate::kIntMetropolis:
02339          return "Metropolis";
02340       case BCIntegrate::kIntCuba:
02341          return "Cuba";
02342       default:
02343          return "Undefined";
02344    }
02345 }
02346 
02347 // ---------------------------------------------------------
02348 std::string BCIntegrate::DumpMarginalizationMethod(BCIntegrate::BCMarginalizationMethod type)
02349 {
02350    switch(type) {
02351       case BCIntegrate::kMargMonteCarlo:
02352          return "Monte Carlo Integration";
02353       case BCIntegrate::kMargMetropolis:
02354          return "Metropolis MCMC";
02355       default:
02356          return "Undefined";
02357    }
02358 }
02359 
02360 // ---------------------------------------------------------
02361 std::string BCIntegrate::DumpOptimizationMethod(BCIntegrate::BCOptimizationMethod type)
02362 {
02363    switch(type) {
02364       case BCIntegrate::kOptSA:
02365          return "Simulated Annealing";
02366       case BCIntegrate::kOptMetropolis:
02367          return "Metropolis MCMC";
02368       case BCIntegrate::kOptMinuit:
02369          return "Minuit";
02370       default:
02371          return "Undefined";
02372    }
02373 }
02374 
02375 // ---------------------------------------------------------
02376 std::string BCIntegrate::DumpCubaIntegrationMethod(BCIntegrate::BCCubaMethod type)
02377 {
02378    switch(type) {
02379       case BCIntegrate::kCubaVegas:
02380          return "Vegas";
02381       case BCIntegrate::kCubaSuave:
02382          return "Suave";
02383       case BCIntegrate::kCubaDivonne:
02384          return "Divonne";
02385       case BCIntegrate::kCubaCuhre:
02386          return "Cuhre";
02387       default:
02388          return "Undefined";
02389    }
02390 }
02391 
02392 // ---------------------------------------------------------
02393 

Generated by  doxygen 1.7.1