// @(#)root/roostats:$Id$
// Authors: Kevin Belasco        17/06/2009
// Authors: Kyle Cranmer         17/06/2009
/*************************************************************************
 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef RooStats_MCMCInterval
#define RooStats_MCMCInterval

#ifndef ROOT_Rtypes
#include "Rtypes.h"
#endif

#ifndef ROOSTATS_ConfInterval
#include "RooStats/ConfInterval.h"
#endif
#ifndef ROO_ARG_SET
#include "RooArgSet.h"
#endif
#ifndef ROO_ARG_LIST
#include "RooArgList.h"
#endif
#ifndef ROOSTATS_MarkovChain
#include "RooStats/MarkovChain.h"
#endif

class RooNDKeysPdf;
class RooProduct;


namespace RooStats {

   class Heaviside;


   class MCMCInterval : public ConfInterval {


   public:

      // default constructor
      explicit MCMCInterval(const char* name = 0);

      // constructor from parameter of interest and Markov chain object
      MCMCInterval(const char* name, const RooArgSet& parameters,
                   MarkovChain& chain);

      enum {DEFAULT_NUM_BINS = 50};
      enum IntervalType {kShortest, kTailFraction};

      virtual ~MCMCInterval();
        
      // determine whether this point is in the confidence interval
      virtual Bool_t IsInInterval(const RooArgSet& point) const;

      // set the desired confidence level (see GetActualConfidenceLevel())
      // Note: calling this function triggers the algorithm that determines
      // the interval, so call this after initializing all other aspects
      // of this IntervalCalculator
      // Also, calling this function again with a different confidence level
      // retriggers the calculation of the interval
      virtual void SetConfidenceLevel(Double_t cl);

      // get the desired confidence level (see GetActualConfidenceLevel())
      virtual Double_t ConfidenceLevel() const {return fConfidenceLevel;}
 
      // return a set containing the parameters of this interval
      // the caller owns the returned RooArgSet*
      virtual RooArgSet* GetParameters() const;

      // get the cutoff bin height for being considered in the
      // confidence interval
      virtual Double_t GetHistCutoff();

      // get the cutoff RooNDKeysPdf value for being considered in the
      // confidence interval
      virtual Double_t GetKeysPdfCutoff();
      //virtual Double_t GetKeysPdfCutoff() { return fKeysCutoff; }

      // get the actual value of the confidence level for this interval.
      virtual Double_t GetActualConfidenceLevel();

      // whether the specified confidence level is a floor for the actual
      // confidence level (strict), or a ceiling (not strict)
      virtual void SetHistStrict(Bool_t isHistStrict)
      { fIsHistStrict = isHistStrict; }

      // check if parameters are correct. (dummy implementation to start)
      Bool_t CheckParameters(const RooArgSet& point) const;

      // Set the parameters of interest for this interval
      // and change other internal data members accordingly
      virtual void SetParameters(const RooArgSet& parameters);

      // Set the MarkovChain that this interval is based on
      virtual void SetChain(MarkovChain& chain) { fChain = &chain; }

      // Set which parameters go on which axis.  The first list element
      // goes on the x axis, second (if it exists) on y, third (if it
      // exists) on z, etc
      virtual void SetAxes(RooArgList& axes);

      // return a list of RooRealVars representing the axes
      // you own the returned RooArgList
      virtual RooArgList* GetAxes()
      {
         RooArgList* axes = new RooArgList();
         for (Int_t i = 0; i < fDimension; i++)
            axes->addClone(*fAxes[i]);
         return axes;
      }

      // get the lowest value of param that is within the confidence interval
      virtual Double_t LowerLimit(RooRealVar& param);

      // determine lower limit of the lower confidence interval
      virtual Double_t LowerLimitTailFraction(RooRealVar& param);

      // get the lower limit of param in the shortest confidence interval
      // Note that this works better for some distributions (ones with exactly
      // one maximum) than others, and sometimes has little value.
      virtual Double_t LowerLimitShortest(RooRealVar& param);

      // determine lower limit in the shortest interval by using keys pdf
      virtual Double_t LowerLimitByKeys(RooRealVar& param);

      // determine lower limit using histogram
      virtual Double_t LowerLimitByHist(RooRealVar& param);

      // determine lower limit using histogram
      virtual Double_t LowerLimitBySparseHist(RooRealVar& param);

      // determine lower limit using histogram
      virtual Double_t LowerLimitByDataHist(RooRealVar& param);

      // get the highest value of param that is within the confidence interval
      virtual Double_t UpperLimit(RooRealVar& param);

      // determine upper limit of the lower confidence interval
      virtual Double_t UpperLimitTailFraction(RooRealVar& param);

      // get the upper limit of param in the confidence interval
      // Note that this works better for some distributions (ones with exactly
      // one maximum) than others, and sometimes has little value.
      virtual Double_t UpperLimitShortest(RooRealVar& param);

      // determine upper limit in the shortest interval by using keys pdf
      virtual Double_t UpperLimitByKeys(RooRealVar& param);

      // determine upper limit using histogram
      virtual Double_t UpperLimitByHist(RooRealVar& param);

      // determine upper limit using histogram
      virtual Double_t UpperLimitBySparseHist(RooRealVar& param);

      // determine upper limit using histogram
      virtual Double_t UpperLimitByDataHist(RooRealVar& param);

      // Determine the approximate maximum value of the Keys PDF
      Double_t GetKeysMax();

      // set the number of steps in the chain to discard as burn-in,
      // starting from the first
      virtual void SetNumBurnInSteps(Int_t numBurnInSteps)
      { fNumBurnInSteps = numBurnInSteps; }

      // set whether to use kernel estimation to determine the interval
      virtual void SetUseKeys(Bool_t useKeys) { fUseKeys = useKeys; }

      // set whether to use a sparse histogram.  you MUST also call
      // SetUseKeys(kFALSE) to use a histogram.
      virtual void SetUseSparseHist(Bool_t useSparseHist)
      { fUseSparseHist = useSparseHist; }

      // get whether we used kernel estimation to determine the interval
      virtual Bool_t GetUseKeys() { return fUseKeys; }

      // get the number of steps in the chain to disard as burn-in,

      // get the number of steps in the chain to disard as burn-in,
      // starting from the first
      virtual Int_t GetNumBurnInSteps() { return fNumBurnInSteps; }

      // set the number of bins to use (same for all axes, for now)
      //virtual void SetNumBins(Int_t numBins);

      // Get a clone of the histogram of the posterior
      virtual TH1* GetPosteriorHist();

      // Get a clone of the keys pdf of the posterior
      virtual RooNDKeysPdf* GetPosteriorKeysPdf();

      // Get a clone of the (keyspdf * heaviside) product of the posterior
      virtual RooProduct* GetPosteriorKeysProduct();

      // Get the number of parameters of interest in this interval
      virtual Int_t GetDimension() const { return fDimension; }

      // Get the markov chain on which this interval is based
      // You do not own the returned MarkovChain*
      virtual const MarkovChain* GetChain() { return fChain; }

      // Get a clone of the markov chain on which this interval is based
      // as a RooDataSet.  You own the returned RooDataSet*
      virtual RooDataSet* GetChainAsDataSet(RooArgSet* whichVars = NULL)
      { return fChain->GetAsDataSet(whichVars); }

      // Get the markov chain on which this interval is based
      // as a RooDataSet.  You do not own the returned RooDataSet*
      virtual const RooDataSet* GetChainAsConstDataSet()
      { return fChain->GetAsConstDataSet(); }

      // Get a clone of the markov chain on which this interval is based
      // as a RooDataHist.  You own the returned RooDataHist*
      virtual RooDataHist* GetChainAsDataHist(RooArgSet* whichVars = NULL)
      { return fChain->GetAsDataHist(whichVars); }

      // Get a clone of the markov chain on which this interval is based
      // as a THnSparse.  You own the returned THnSparse*
      virtual THnSparse* GetChainAsSparseHist(RooArgSet* whichVars = NULL)
      { return fChain->GetAsSparseHist(whichVars); }

      // Get a clone of the NLL variable from the markov chain
      virtual RooRealVar* GetNLLVar() const
      { return fChain->GetNLLVar(); }

      // Get a clone of the weight variable from the markov chain
      virtual RooRealVar* GetWeightVar() const
      { return fChain->GetWeightVar(); }

      // set the acceptable level or error for Keys interval determination
      virtual void SetEpsilon(Double_t epsilon)
      {
         if (epsilon < 0)
            coutE(InputArguments) << "MCMCInterval::SetEpsilon will not allow "
                                  << "negative epsilon value" << std::endl;
         else
            fEpsilon = epsilon;
      }

      // Set the type of interval to find.  This will only have an effect for
      // 1-D intervals.  If is more than 1 parameter of interest, then a
      // "shortest" interval will always be used, since it generalizes directly
      // to N dimensions
      virtual void SetIntervalType(enum IntervalType intervalType)
      { fIntervalType = intervalType; }

      // Return the type of this interval
      virtual enum IntervalType GetIntervalType() { return fIntervalType; }

      // set the left-side tail fraction for a tail-fraction interval
      virtual void SetLeftSideTailFraction(Double_t a) { fLeftSideTF = a; }

      // kbelasco: The inner-workings of the class really should not be exposed
      // like this in a comment, but it seems to be the only way to give
      // the user any control over this process, if they desire it
      //
      // Set the fraction delta such that
      // topCutoff (a) is considered == bottomCutoff (b) iff
      // (TMath::Abs(a - b) < TMath::Abs(fDelta * (a + b)/2))
      // when determining the confidence interval by Keys
      virtual void SetDelta(Double_t delta)
      {
         if (delta < 0.)
            coutE(InputArguments) << "MCMCInterval::SetDelta will not allow "
                                  << "negative delta value" << std::endl;
         else
            fDelta = delta;
      }

   private:
      inline Bool_t AcceptableConfLevel(Double_t confLevel);
      inline Bool_t WithinDeltaFraction(Double_t a, Double_t b);

   protected:
      // data members
      RooArgSet  fParameters; // parameters of interest for this interval
      MarkovChain* fChain; // the markov chain
      Double_t fConfidenceLevel; // Requested confidence level (eg. 0.95 for 95% CL)

      RooDataHist* fDataHist; // the binned Markov Chain data
      THnSparse* fSparseHist; // the binned Markov Chain data
      Double_t fHistConfLevel; // the actual conf level determined by hist
      Double_t fHistCutoff; // cutoff bin size to be in interval

      RooNDKeysPdf* fKeysPdf; // the kernel estimation pdf
      RooProduct* fProduct; // the (keysPdf * heaviside) product
      Heaviside* fHeaviside; // the Heaviside function
      RooDataHist* fKeysDataHist; // data hist representing product
      RooRealVar* fCutoffVar; // cutoff variable to use for integrating keys pdf
      Double_t fKeysConfLevel; // the actual conf level determined by keys
      Double_t fKeysCutoff; // cutoff keys pdf value to be in interval
      Double_t fFull; // Value of intergral of fProduct

      Double_t fLeftSideTF; // left side tail-fraction for interval
      Double_t fTFConfLevel; // the actual conf level of tail-fraction interval
      std::vector<Int_t> fVector; // vector containing the Markov chain data
      Double_t fVecWeight; // sum of weights of all entries in fVector
      Double_t fTFLower;   // lower limit of the tail-fraction interval
      Double_t fTFUpper;   // upper limit of the tail-fraction interval

      TH1* fHist; // the binned Markov Chain data

      Bool_t fUseKeys; // whether to use kernel estimation
      Bool_t fUseSparseHist; // whether to use sparse hist (vs. RooDataHist)
      Bool_t fIsHistStrict; // whether the specified confidence level is a
                            // floor for the actual confidence level (strict),
                            // or a ceiling (not strict) for determination by
                            // histogram
      Int_t fDimension; // number of variables
      Int_t fNumBurnInSteps; // number of steps to discard as burn in, starting
                             // from the first
      // LM (not used) Double_t fIntervalSum; // sum of heights of bins in the interval
      RooRealVar** fAxes; // array of pointers to RooRealVars representing
                          // the axes of the histogram
                          // fAxes[0] represents x-axis, [1] y, [2] z, etc

      Double_t fEpsilon; // acceptable error for Keys interval determination

      Double_t fDelta; // topCutoff (a) considered == bottomCutoff (b) iff
                       // (TMath::Abs(a - b) < TMath::Abs(fDelta * (a + b)/2));
                       // Theoretically, the Abs is not needed here, but
                       // floating-point arithmetic does not always work
                       // perfectly, and the Abs doesn't hurt
      enum IntervalType fIntervalType;


      // functions
      virtual void DetermineInterval();
      virtual void DetermineShortestInterval();
      virtual void DetermineTailFractionInterval();
      virtual void DetermineByHist();
      virtual void DetermineBySparseHist();
      virtual void DetermineByDataHist();
      virtual void DetermineByKeys();
      virtual void CreateHist();
      virtual void CreateSparseHist();
      virtual void CreateDataHist();
      virtual void CreateKeysPdf();
      virtual void CreateKeysDataHist();
      virtual void CreateVector(RooRealVar* param);
      inline virtual Double_t CalcConfLevel(Double_t cutoff, Double_t full);

      ClassDef(MCMCInterval,1)  // Concrete implementation of a ConfInterval based on MCMC calculation
      
   };
}

#endif
 MCMCInterval.h:1
 MCMCInterval.h:2
 MCMCInterval.h:3
 MCMCInterval.h:4
 MCMCInterval.h:5
 MCMCInterval.h:6
 MCMCInterval.h:7
 MCMCInterval.h:8
 MCMCInterval.h:9
 MCMCInterval.h:10
 MCMCInterval.h:11
 MCMCInterval.h:12
 MCMCInterval.h:13
 MCMCInterval.h:14
 MCMCInterval.h:15
 MCMCInterval.h:16
 MCMCInterval.h:17
 MCMCInterval.h:18
 MCMCInterval.h:19
 MCMCInterval.h:20
 MCMCInterval.h:21
 MCMCInterval.h:22
 MCMCInterval.h:23
 MCMCInterval.h:24
 MCMCInterval.h:25
 MCMCInterval.h:26
 MCMCInterval.h:27
 MCMCInterval.h:28
 MCMCInterval.h:29
 MCMCInterval.h:30
 MCMCInterval.h:31
 MCMCInterval.h:32
 MCMCInterval.h:33
 MCMCInterval.h:34
 MCMCInterval.h:35
 MCMCInterval.h:36
 MCMCInterval.h:37
 MCMCInterval.h:38
 MCMCInterval.h:39
 MCMCInterval.h:40
 MCMCInterval.h:41
 MCMCInterval.h:42
 MCMCInterval.h:43
 MCMCInterval.h:44
 MCMCInterval.h:45
 MCMCInterval.h:46
 MCMCInterval.h:47
 MCMCInterval.h:48
 MCMCInterval.h:49
 MCMCInterval.h:50
 MCMCInterval.h:51
 MCMCInterval.h:52
 MCMCInterval.h:53
 MCMCInterval.h:54
 MCMCInterval.h:55
 MCMCInterval.h:56
 MCMCInterval.h:57
 MCMCInterval.h:58
 MCMCInterval.h:59
 MCMCInterval.h:60
 MCMCInterval.h:61
 MCMCInterval.h:62
 MCMCInterval.h:63
 MCMCInterval.h:64
 MCMCInterval.h:65
 MCMCInterval.h:66
 MCMCInterval.h:67
 MCMCInterval.h:68
 MCMCInterval.h:69
 MCMCInterval.h:70
 MCMCInterval.h:71
 MCMCInterval.h:72
 MCMCInterval.h:73
 MCMCInterval.h:74
 MCMCInterval.h:75
 MCMCInterval.h:76
 MCMCInterval.h:77
 MCMCInterval.h:78
 MCMCInterval.h:79
 MCMCInterval.h:80
 MCMCInterval.h:81
 MCMCInterval.h:82
 MCMCInterval.h:83
 MCMCInterval.h:84
 MCMCInterval.h:85
 MCMCInterval.h:86
 MCMCInterval.h:87
 MCMCInterval.h:88
 MCMCInterval.h:89
 MCMCInterval.h:90
 MCMCInterval.h:91
 MCMCInterval.h:92
 MCMCInterval.h:93
 MCMCInterval.h:94
 MCMCInterval.h:95
 MCMCInterval.h:96
 MCMCInterval.h:97
 MCMCInterval.h:98
 MCMCInterval.h:99
 MCMCInterval.h:100
 MCMCInterval.h:101
 MCMCInterval.h:102
 MCMCInterval.h:103
 MCMCInterval.h:104
 MCMCInterval.h:105
 MCMCInterval.h:106
 MCMCInterval.h:107
 MCMCInterval.h:108
 MCMCInterval.h:109
 MCMCInterval.h:110
 MCMCInterval.h:111
 MCMCInterval.h:112
 MCMCInterval.h:113
 MCMCInterval.h:114
 MCMCInterval.h:115
 MCMCInterval.h:116
 MCMCInterval.h:117
 MCMCInterval.h:118
 MCMCInterval.h:119
 MCMCInterval.h:120
 MCMCInterval.h:121
 MCMCInterval.h:122
 MCMCInterval.h:123
 MCMCInterval.h:124
 MCMCInterval.h:125
 MCMCInterval.h:126
 MCMCInterval.h:127
 MCMCInterval.h:128
 MCMCInterval.h:129
 MCMCInterval.h:130
 MCMCInterval.h:131
 MCMCInterval.h:132
 MCMCInterval.h:133
 MCMCInterval.h:134
 MCMCInterval.h:135
 MCMCInterval.h:136
 MCMCInterval.h:137
 MCMCInterval.h:138
 MCMCInterval.h:139
 MCMCInterval.h:140
 MCMCInterval.h:141
 MCMCInterval.h:142
 MCMCInterval.h:143
 MCMCInterval.h:144
 MCMCInterval.h:145
 MCMCInterval.h:146
 MCMCInterval.h:147
 MCMCInterval.h:148
 MCMCInterval.h:149
 MCMCInterval.h:150
 MCMCInterval.h:151
 MCMCInterval.h:152
 MCMCInterval.h:153
 MCMCInterval.h:154
 MCMCInterval.h:155
 MCMCInterval.h:156
 MCMCInterval.h:157
 MCMCInterval.h:158
 MCMCInterval.h:159
 MCMCInterval.h:160
 MCMCInterval.h:161
 MCMCInterval.h:162
 MCMCInterval.h:163
 MCMCInterval.h:164
 MCMCInterval.h:165
 MCMCInterval.h:166
 MCMCInterval.h:167
 MCMCInterval.h:168
 MCMCInterval.h:169
 MCMCInterval.h:170
 MCMCInterval.h:171
 MCMCInterval.h:172
 MCMCInterval.h:173
 MCMCInterval.h:174
 MCMCInterval.h:175
 MCMCInterval.h:176
 MCMCInterval.h:177
 MCMCInterval.h:178
 MCMCInterval.h:179
 MCMCInterval.h:180
 MCMCInterval.h:181
 MCMCInterval.h:182
 MCMCInterval.h:183
 MCMCInterval.h:184
 MCMCInterval.h:185
 MCMCInterval.h:186
 MCMCInterval.h:187
 MCMCInterval.h:188
 MCMCInterval.h:189
 MCMCInterval.h:190
 MCMCInterval.h:191
 MCMCInterval.h:192
 MCMCInterval.h:193
 MCMCInterval.h:194
 MCMCInterval.h:195
 MCMCInterval.h:196
 MCMCInterval.h:197
 MCMCInterval.h:198
 MCMCInterval.h:199
 MCMCInterval.h:200
 MCMCInterval.h:201
 MCMCInterval.h:202
 MCMCInterval.h:203
 MCMCInterval.h:204
 MCMCInterval.h:205
 MCMCInterval.h:206
 MCMCInterval.h:207
 MCMCInterval.h:208
 MCMCInterval.h:209
 MCMCInterval.h:210
 MCMCInterval.h:211
 MCMCInterval.h:212
 MCMCInterval.h:213
 MCMCInterval.h:214
 MCMCInterval.h:215
 MCMCInterval.h:216
 MCMCInterval.h:217
 MCMCInterval.h:218
 MCMCInterval.h:219
 MCMCInterval.h:220
 MCMCInterval.h:221
 MCMCInterval.h:222
 MCMCInterval.h:223
 MCMCInterval.h:224
 MCMCInterval.h:225
 MCMCInterval.h:226
 MCMCInterval.h:227
 MCMCInterval.h:228
 MCMCInterval.h:229
 MCMCInterval.h:230
 MCMCInterval.h:231
 MCMCInterval.h:232
 MCMCInterval.h:233
 MCMCInterval.h:234
 MCMCInterval.h:235
 MCMCInterval.h:236
 MCMCInterval.h:237
 MCMCInterval.h:238
 MCMCInterval.h:239
 MCMCInterval.h:240
 MCMCInterval.h:241
 MCMCInterval.h:242
 MCMCInterval.h:243
 MCMCInterval.h:244
 MCMCInterval.h:245
 MCMCInterval.h:246
 MCMCInterval.h:247
 MCMCInterval.h:248
 MCMCInterval.h:249
 MCMCInterval.h:250
 MCMCInterval.h:251
 MCMCInterval.h:252
 MCMCInterval.h:253
 MCMCInterval.h:254
 MCMCInterval.h:255
 MCMCInterval.h:256
 MCMCInterval.h:257
 MCMCInterval.h:258
 MCMCInterval.h:259
 MCMCInterval.h:260
 MCMCInterval.h:261
 MCMCInterval.h:262
 MCMCInterval.h:263
 MCMCInterval.h:264
 MCMCInterval.h:265
 MCMCInterval.h:266
 MCMCInterval.h:267
 MCMCInterval.h:268
 MCMCInterval.h:269
 MCMCInterval.h:270
 MCMCInterval.h:271
 MCMCInterval.h:272
 MCMCInterval.h:273
 MCMCInterval.h:274
 MCMCInterval.h:275
 MCMCInterval.h:276
 MCMCInterval.h:277
 MCMCInterval.h:278
 MCMCInterval.h:279
 MCMCInterval.h:280
 MCMCInterval.h:281
 MCMCInterval.h:282
 MCMCInterval.h:283
 MCMCInterval.h:284
 MCMCInterval.h:285
 MCMCInterval.h:286
 MCMCInterval.h:287
 MCMCInterval.h:288
 MCMCInterval.h:289
 MCMCInterval.h:290
 MCMCInterval.h:291
 MCMCInterval.h:292
 MCMCInterval.h:293
 MCMCInterval.h:294
 MCMCInterval.h:295
 MCMCInterval.h:296
 MCMCInterval.h:297
 MCMCInterval.h:298
 MCMCInterval.h:299
 MCMCInterval.h:300
 MCMCInterval.h:301
 MCMCInterval.h:302
 MCMCInterval.h:303
 MCMCInterval.h:304
 MCMCInterval.h:305
 MCMCInterval.h:306
 MCMCInterval.h:307
 MCMCInterval.h:308
 MCMCInterval.h:309
 MCMCInterval.h:310
 MCMCInterval.h:311
 MCMCInterval.h:312
 MCMCInterval.h:313
 MCMCInterval.h:314
 MCMCInterval.h:315
 MCMCInterval.h:316
 MCMCInterval.h:317
 MCMCInterval.h:318
 MCMCInterval.h:319
 MCMCInterval.h:320
 MCMCInterval.h:321
 MCMCInterval.h:322
 MCMCInterval.h:323
 MCMCInterval.h:324
 MCMCInterval.h:325
 MCMCInterval.h:326
 MCMCInterval.h:327
 MCMCInterval.h:328
 MCMCInterval.h:329
 MCMCInterval.h:330
 MCMCInterval.h:331
 MCMCInterval.h:332
 MCMCInterval.h:333
 MCMCInterval.h:334
 MCMCInterval.h:335
 MCMCInterval.h:336
 MCMCInterval.h:337
 MCMCInterval.h:338
 MCMCInterval.h:339
 MCMCInterval.h:340
 MCMCInterval.h:341
 MCMCInterval.h:342
 MCMCInterval.h:343
 MCMCInterval.h:344
 MCMCInterval.h:345
 MCMCInterval.h:346
 MCMCInterval.h:347
 MCMCInterval.h:348
 MCMCInterval.h:349
 MCMCInterval.h:350
 MCMCInterval.h:351
 MCMCInterval.h:352
 MCMCInterval.h:353
 MCMCInterval.h:354