// @(#)root/roostats:$Id$
// Author: Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke
/*************************************************************************
 * 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_LikelihoodInterval
#define RooStats_LikelihoodInterval

#ifndef RooStats_ConfInterval
#include "RooStats/ConfInterval.h"
#endif

#ifndef ROO_ARG_SET
#include "RooArgSet.h"
#endif

#ifndef ROO_ABS_REAL
#include "RooAbsReal.h"
#endif

#ifndef ROOT_Math_IFunctionfwd
#include "Math/IFunctionfwd.h"
#endif

#include <map>
#include <memory>

namespace ROOT { 
   namespace Math { 
      class Minimizer; 
   }
}

namespace RooStats {


/**

   \ingroup Roostats

   LikelihoodInterval is a concrete implementation of the RooStats::ConfInterval interface.  
   It implements a connected N-dimensional intervals based on the contour of a likelihood ratio.
   The boundary of the inteval is equivalent to a MINUIT/MINOS contour about the maximum likelihood estimator

   The interval does not need to be an ellipse (eg. it is not the HESSE error matrix).
   The level used to make the contour is the same as that used in MINOS, eg. it uses Wilks' theorem, 
   which states that under certain regularity conditions the function -2* log (profile likelihood ratio) is asymptotically distributed as a chi^2 with N-dof, where 
   N is the number of parameters of interest.  

   
   Note, a boundary on the parameter space (eg. s>= 0) or a degeneracy (eg. mass of signal if Nsig = 0) can lead to violations of the conditions necessary for Wilks'
   theorem to be true.

   Also note, one can use any RooAbsReal as the function that will be used in the contour; however, the level of the contour
   is based on Wilks' theorem as stated above.


#### References 

*  1. F. James., Minuit.Long writeup D506, CERN, 1998.

  
*/


   class LikelihoodInterval : public ConfInterval {

   public:

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

      //// construct the interval from a Profile Likelihood object, parameter of interest and optionally a snapshot of 
      //// POI with their best fit values 
      LikelihoodInterval(const char* name, RooAbsReal*, const RooArgSet*,  RooArgSet * = 0);

      /// destructor
      virtual ~LikelihoodInterval();
      
      /// check if given point is in the interval
      virtual Bool_t IsInInterval(const RooArgSet&) const;

      /// set the confidence level for the interval (e.g 0.682 for a 1-sigma interval) 
      virtual void SetConfidenceLevel(Double_t cl) {fConfidenceLevel = cl; ResetLimits(); }

      /// return confidence level
      virtual Double_t ConfidenceLevel() const {return fConfidenceLevel;}
 
      /// return a cloned list of parameters of interest.  User manages the return object
      virtual  RooArgSet* GetParameters() const;

      /// check if parameters are correct (i.e. they are the POI of this interval) 
      Bool_t CheckParameters(const RooArgSet&) const ;


      /// return the lower bound of the interval on a given parameter 
      Double_t LowerLimit(const RooRealVar& param) { bool ok; return LowerLimit(param,ok); }
      Double_t LowerLimit(const RooRealVar& param, bool & status) ;

      /// return the upper bound of the interval on a given parameter 
      Double_t UpperLimit(const RooRealVar& param) { bool ok; return UpperLimit(param,ok); }
      Double_t UpperLimit(const RooRealVar& param, bool & status) ;

      /// find both lower and upper interval boundaries for a given parameter
      /// retun false if the bounds have not been found
      Bool_t FindLimits(const RooRealVar & param, double & lower, double &upper);

      /**
         return the 2D-contour points for the given subset of parameters
         by default make the contour using 30 points. The User has to preallocate the x and y array which will return 
         the set of x and y points defining the contour. 
         The return value of the funciton specify the number of contour point found.
         In case of error a zero is returned
      */
      Int_t GetContourPoints(const RooRealVar & paramX, const RooRealVar & paramY, Double_t * x, Double_t *y, Int_t npoints = 30);

      /// return the profile log-likelihood ratio function
      RooAbsReal* GetLikelihoodRatio() {return fLikelihoodRatio;}

      /// return a pointer to a snapshot with best fit parameter of interest
      const RooArgSet * GetBestFitParameters() const { return fBestFitParams; }

   protected: 

      /// reset the cached limit values
      void ResetLimits(); 

      /// internal function to create the minimizer for finding the contours
      bool CreateMinimizer();

   private:

      RooArgSet   fParameters; /// parameters of interest for this interval
      RooArgSet * fBestFitParams; /// snapshot of the model parameters with best fit value (managed internally)
      RooAbsReal* fLikelihoodRatio; /// likelihood ratio function used to make contours (managed internally)
      Double_t fConfidenceLevel; /// Requested confidence level (eg. 0.95 for 95% CL)
      std::map<std::string, double> fLowerLimits; /// map with cached lower bound values
      std::map<std::string, double> fUpperLimits; /// map with cached upper bound values
      std::shared_ptr<ROOT::Math::Minimizer > fMinimizer; //! transient pointer to minimizer class used to find limits and contour
      std::shared_ptr<RooFunctor>           fFunctor;   //! transient pointer to functor class used by the minimizer
      std::shared_ptr<ROOT::Math::IMultiGenFunction> fMinFunc; //! transient pointer to the minimization function 

      ClassDef(LikelihoodInterval,1)  /// Concrete implementation of a ConfInterval based on a likelihood ratio
      
   };
}

#endif
 LikelihoodInterval.h:1
 LikelihoodInterval.h:2
 LikelihoodInterval.h:3
 LikelihoodInterval.h:4
 LikelihoodInterval.h:5
 LikelihoodInterval.h:6
 LikelihoodInterval.h:7
 LikelihoodInterval.h:8
 LikelihoodInterval.h:9
 LikelihoodInterval.h:10
 LikelihoodInterval.h:11
 LikelihoodInterval.h:12
 LikelihoodInterval.h:13
 LikelihoodInterval.h:14
 LikelihoodInterval.h:15
 LikelihoodInterval.h:16
 LikelihoodInterval.h:17
 LikelihoodInterval.h:18
 LikelihoodInterval.h:19
 LikelihoodInterval.h:20
 LikelihoodInterval.h:21
 LikelihoodInterval.h:22
 LikelihoodInterval.h:23
 LikelihoodInterval.h:24
 LikelihoodInterval.h:25
 LikelihoodInterval.h:26
 LikelihoodInterval.h:27
 LikelihoodInterval.h:28
 LikelihoodInterval.h:29
 LikelihoodInterval.h:30
 LikelihoodInterval.h:31
 LikelihoodInterval.h:32
 LikelihoodInterval.h:33
 LikelihoodInterval.h:34
 LikelihoodInterval.h:35
 LikelihoodInterval.h:36
 LikelihoodInterval.h:37
 LikelihoodInterval.h:38
 LikelihoodInterval.h:39
 LikelihoodInterval.h:40
 LikelihoodInterval.h:41
 LikelihoodInterval.h:42
 LikelihoodInterval.h:43
 LikelihoodInterval.h:44
 LikelihoodInterval.h:45
 LikelihoodInterval.h:46
 LikelihoodInterval.h:47
 LikelihoodInterval.h:48
 LikelihoodInterval.h:49
 LikelihoodInterval.h:50
 LikelihoodInterval.h:51
 LikelihoodInterval.h:52
 LikelihoodInterval.h:53
 LikelihoodInterval.h:54
 LikelihoodInterval.h:55
 LikelihoodInterval.h:56
 LikelihoodInterval.h:57
 LikelihoodInterval.h:58
 LikelihoodInterval.h:59
 LikelihoodInterval.h:60
 LikelihoodInterval.h:61
 LikelihoodInterval.h:62
 LikelihoodInterval.h:63
 LikelihoodInterval.h:64
 LikelihoodInterval.h:65
 LikelihoodInterval.h:66
 LikelihoodInterval.h:67
 LikelihoodInterval.h:68
 LikelihoodInterval.h:69
 LikelihoodInterval.h:70
 LikelihoodInterval.h:71
 LikelihoodInterval.h:72
 LikelihoodInterval.h:73
 LikelihoodInterval.h:74
 LikelihoodInterval.h:75
 LikelihoodInterval.h:76
 LikelihoodInterval.h:77
 LikelihoodInterval.h:78
 LikelihoodInterval.h:79
 LikelihoodInterval.h:80
 LikelihoodInterval.h:81
 LikelihoodInterval.h:82
 LikelihoodInterval.h:83
 LikelihoodInterval.h:84
 LikelihoodInterval.h:85
 LikelihoodInterval.h:86
 LikelihoodInterval.h:87
 LikelihoodInterval.h:88
 LikelihoodInterval.h:89
 LikelihoodInterval.h:90
 LikelihoodInterval.h:91
 LikelihoodInterval.h:92
 LikelihoodInterval.h:93
 LikelihoodInterval.h:94
 LikelihoodInterval.h:95
 LikelihoodInterval.h:96
 LikelihoodInterval.h:97
 LikelihoodInterval.h:98
 LikelihoodInterval.h:99
 LikelihoodInterval.h:100
 LikelihoodInterval.h:101
 LikelihoodInterval.h:102
 LikelihoodInterval.h:103
 LikelihoodInterval.h:104
 LikelihoodInterval.h:105
 LikelihoodInterval.h:106
 LikelihoodInterval.h:107
 LikelihoodInterval.h:108
 LikelihoodInterval.h:109
 LikelihoodInterval.h:110
 LikelihoodInterval.h:111
 LikelihoodInterval.h:112
 LikelihoodInterval.h:113
 LikelihoodInterval.h:114
 LikelihoodInterval.h:115
 LikelihoodInterval.h:116
 LikelihoodInterval.h:117
 LikelihoodInterval.h:118
 LikelihoodInterval.h:119
 LikelihoodInterval.h:120
 LikelihoodInterval.h:121
 LikelihoodInterval.h:122
 LikelihoodInterval.h:123
 LikelihoodInterval.h:124
 LikelihoodInterval.h:125
 LikelihoodInterval.h:126
 LikelihoodInterval.h:127
 LikelihoodInterval.h:128
 LikelihoodInterval.h:129
 LikelihoodInterval.h:130
 LikelihoodInterval.h:131
 LikelihoodInterval.h:132
 LikelihoodInterval.h:133
 LikelihoodInterval.h:134
 LikelihoodInterval.h:135
 LikelihoodInterval.h:136
 LikelihoodInterval.h:137
 LikelihoodInterval.h:138
 LikelihoodInterval.h:139
 LikelihoodInterval.h:140
 LikelihoodInterval.h:141
 LikelihoodInterval.h:142
 LikelihoodInterval.h:143
 LikelihoodInterval.h:144
 LikelihoodInterval.h:145
 LikelihoodInterval.h:146
 LikelihoodInterval.h:147
 LikelihoodInterval.h:148
 LikelihoodInterval.h:149
 LikelihoodInterval.h:150
 LikelihoodInterval.h:151
 LikelihoodInterval.h:152
 LikelihoodInterval.h:153