// @(#)root/roostats:$Id$
// Author: Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke
// Additional Contributions: Giovanni Petrucciani 
/*************************************************************************
 * 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_ProfileLikelihoodTestStat
#define ROOSTATS_ProfileLikelihoodTestStat

//_________________________________________________
/*
BEGIN_HTML
<p>
ProfileLikelihoodTestStat is an implementation of the TestStatistic interface that calculates the profile
likelihood ratio at a particular parameter point given a dataset.  It does not constitute a statistical test, for that one may either use:
<ul>
 <li> the ProfileLikelihoodCalculator that relies on asymptotic properties of the Profile Likelihood Ratio</li>
 <li> the Neyman Construction classes with this class as a test statistic</li>
 <li> the Hybrid Calculator class with this class as a test statistic</li>
</ul>

</p>
END_HTML
*/
//

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

#ifndef ROOSTATS_TestStatistic
#include "RooStats/TestStatistic.h"
#endif


#ifndef ROO_REAL_VAR
#include "RooRealVar.h"
#endif

#ifndef ROO_NLL_VAR
#include "RooNLLVar.h"
#endif

#ifndef ROOTT_Math_MinimizerOptions
#include "Math/MinimizerOptions.h"
#endif

#ifndef ROOSTATS_RooStatsUtils
#include "RooStats/RooStatsUtils.h"
#endif


namespace RooStats {

  class ProfileLikelihoodTestStat : public TestStatistic{

     enum LimitType {twoSided, oneSided, oneSidedDiscovery};

   public:
     ProfileLikelihoodTestStat() {
        // Proof constructor. Do not use.
        fPdf = 0;
        fNll = 0;
        fCachedBestFitParams = 0;
        fLastData = 0;
	fLimitType = twoSided;
	fSigned = false;
        fDetailedOutputWithErrorsAndPulls = false;
        fDetailedOutputEnabled = false;
        fDetailedOutput = NULL;
	fLOffset = RooStats::IsNLLOffset() ;
      
        fVarName = "Profile Likelihood Ratio";
        fReuseNll = false;
	fMinimizer=::ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str();
	fStrategy=::ROOT::Math::MinimizerOptions::DefaultStrategy();
        fTolerance=TMath::Max(1.,::ROOT::Math::MinimizerOptions::DefaultTolerance());
	fPrintLevel=::ROOT::Math::MinimizerOptions::DefaultPrintLevel();

     }
     ProfileLikelihoodTestStat(RooAbsPdf& pdf) {
       fPdf = &pdf;
       fNll = 0;
       fCachedBestFitParams = 0;
       fLastData = 0;
       fLimitType = twoSided;
       fSigned = false;
       fDetailedOutputWithErrorsAndPulls = false;
       fDetailedOutputEnabled = false;
       fDetailedOutput = NULL;
       fLOffset = RooStats::IsNLLOffset() ;
      
       fVarName = "Profile Likelihood Ratio";
       fReuseNll = false;
       fMinimizer=::ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str();
       fStrategy=::ROOT::Math::MinimizerOptions::DefaultStrategy();
       // avoid default tolerance to be too small (1. is default in RooMinimizer)
       fTolerance=TMath::Max(1.,::ROOT::Math::MinimizerOptions::DefaultTolerance());
       fPrintLevel=::ROOT::Math::MinimizerOptions::DefaultPrintLevel();
     }
     
     virtual ~ProfileLikelihoodTestStat() {
       if(fNll) delete fNll;
       if(fCachedBestFitParams) delete fCachedBestFitParams;
       if(fDetailedOutput) delete fDetailedOutput;
     }

     //LM use default copy constructor and assignment copying the pointers. Is this what we want ?

     void SetOneSided(Bool_t flag=true) {fLimitType = (flag ? oneSided : twoSided);}
     void SetOneSidedDiscovery(Bool_t flag=true) {fLimitType = (flag ? oneSidedDiscovery : twoSided);}
     void SetSigned(Bool_t flag=true) {fSigned = flag;}  // +/- t_mu instead of t_mu>0 with one-sided settings
     //void SetOneSidedDiscovery(Bool_t flag=true) {fOneSidedDiscovery = flag;}

     bool IsTwoSided() const { return fLimitType == twoSided; }
     bool IsOneSidedDiscovery() const { return fLimitType == oneSidedDiscovery; }

     static void SetAlwaysReuseNLL(Bool_t flag);

     void SetReuseNLL(Bool_t flag) { fReuseNll = flag ; }
     void SetLOffset(Bool_t flag=kTRUE) { fLOffset = flag ; }

     void SetMinimizer(const char* minimizer){ fMinimizer=minimizer;}
     void SetStrategy(Int_t strategy){fStrategy=strategy;}
     void SetTolerance(double tol){fTolerance=tol;}
     void SetPrintLevel(Int_t printlevel){fPrintLevel=printlevel;}
    
     // Main interface to evaluate the test statistic on a dataset
     virtual Double_t Evaluate(RooAbsData& data, RooArgSet& paramsOfInterest) {
        return EvaluateProfileLikelihood(0, data, paramsOfInterest);
     }

     // evaluate  the profile likelihood ratio (type = 0) or the minimum of likelihood (type=1) or the conditional LL (type = 2) 
     virtual Double_t EvaluateProfileLikelihood(int type, RooAbsData &data, RooArgSet & paramsOfInterest);
     
     virtual void EnableDetailedOutput( bool e=true, bool withErrorsAndPulls=false ) {
        fDetailedOutputEnabled = e;
        fDetailedOutputWithErrorsAndPulls = withErrorsAndPulls;
        delete fDetailedOutput;
        fDetailedOutput = NULL;
     }
     virtual const RooArgSet* GetDetailedOutput(void) const {
	     // Returns detailed output. The value returned by this function is updated after each call to Evaluate().
	     // The returned RooArgSet contains the following:
	     // <ul>
	     // <li> the minimum nll, fitstatus and convergence quality for each fit </li> 
	     // <li> for each fit and for each non-constant parameter, the value, error and pull of the parameter are stored </li>
	     // </ul>
	     return fDetailedOutput;
     }
         
     // set the conditional observables which will be used when creating the NLL
     // so the pdf's will not be normalized on the conditional observables when computing the NLL 
     virtual void SetConditionalObservables(const RooArgSet& set) {fConditionalObs.removeAll(); fConditionalObs.add(set);}

     virtual void SetVarName(const char* name) { fVarName = name; }
     virtual const TString GetVarName() const {return fVarName;}

     virtual RooAbsPdf * GetPdf() const { return fPdf; }

      
      //      const bool PValueIsRightTail(void) { return false; } // overwrites default

  private:

     RooFitResult* GetMinNLL();

   private:

      RooAbsPdf* fPdf;
      RooAbsReal* fNll; //!
      const RooArgSet* fCachedBestFitParams;
      RooAbsData* fLastData;
      //      Double_t fLastMLE;
      LimitType fLimitType;
      Bool_t fSigned;
      
      // this will store a snapshot of the unconditional nuisance
      // parameter fit.
      bool fDetailedOutputEnabled;
      bool fDetailedOutputWithErrorsAndPulls;
      RooArgSet* fDetailedOutput; //!
      RooArgSet fConditionalObs;    // conditional observables 
      
      TString fVarName;

      static Bool_t fgAlwaysReuseNll ;
      Bool_t fReuseNll ;
      TString fMinimizer;
      Int_t fStrategy;
      Double_t fTolerance; 
      Int_t fPrintLevel;
      Bool_t fLOffset ;

   protected:

      ClassDef(ProfileLikelihoodTestStat,9)   // implements the profile likelihood ratio as a test statistic to be used with several tools
   };
}


#endif
 ProfileLikelihoodTestStat.h:1
 ProfileLikelihoodTestStat.h:2
 ProfileLikelihoodTestStat.h:3
 ProfileLikelihoodTestStat.h:4
 ProfileLikelihoodTestStat.h:5
 ProfileLikelihoodTestStat.h:6
 ProfileLikelihoodTestStat.h:7
 ProfileLikelihoodTestStat.h:8
 ProfileLikelihoodTestStat.h:9
 ProfileLikelihoodTestStat.h:10
 ProfileLikelihoodTestStat.h:11
 ProfileLikelihoodTestStat.h:12
 ProfileLikelihoodTestStat.h:13
 ProfileLikelihoodTestStat.h:14
 ProfileLikelihoodTestStat.h:15
 ProfileLikelihoodTestStat.h:16
 ProfileLikelihoodTestStat.h:17
 ProfileLikelihoodTestStat.h:18
 ProfileLikelihoodTestStat.h:19
 ProfileLikelihoodTestStat.h:20
 ProfileLikelihoodTestStat.h:21
 ProfileLikelihoodTestStat.h:22
 ProfileLikelihoodTestStat.h:23
 ProfileLikelihoodTestStat.h:24
 ProfileLikelihoodTestStat.h:25
 ProfileLikelihoodTestStat.h:26
 ProfileLikelihoodTestStat.h:27
 ProfileLikelihoodTestStat.h:28
 ProfileLikelihoodTestStat.h:29
 ProfileLikelihoodTestStat.h:30
 ProfileLikelihoodTestStat.h:31
 ProfileLikelihoodTestStat.h:32
 ProfileLikelihoodTestStat.h:33
 ProfileLikelihoodTestStat.h:34
 ProfileLikelihoodTestStat.h:35
 ProfileLikelihoodTestStat.h:36
 ProfileLikelihoodTestStat.h:37
 ProfileLikelihoodTestStat.h:38
 ProfileLikelihoodTestStat.h:39
 ProfileLikelihoodTestStat.h:40
 ProfileLikelihoodTestStat.h:41
 ProfileLikelihoodTestStat.h:42
 ProfileLikelihoodTestStat.h:43
 ProfileLikelihoodTestStat.h:44
 ProfileLikelihoodTestStat.h:45
 ProfileLikelihoodTestStat.h:46
 ProfileLikelihoodTestStat.h:47
 ProfileLikelihoodTestStat.h:48
 ProfileLikelihoodTestStat.h:49
 ProfileLikelihoodTestStat.h:50
 ProfileLikelihoodTestStat.h:51
 ProfileLikelihoodTestStat.h:52
 ProfileLikelihoodTestStat.h:53
 ProfileLikelihoodTestStat.h:54
 ProfileLikelihoodTestStat.h:55
 ProfileLikelihoodTestStat.h:56
 ProfileLikelihoodTestStat.h:57
 ProfileLikelihoodTestStat.h:58
 ProfileLikelihoodTestStat.h:59
 ProfileLikelihoodTestStat.h:60
 ProfileLikelihoodTestStat.h:61
 ProfileLikelihoodTestStat.h:62
 ProfileLikelihoodTestStat.h:63
 ProfileLikelihoodTestStat.h:64
 ProfileLikelihoodTestStat.h:65
 ProfileLikelihoodTestStat.h:66
 ProfileLikelihoodTestStat.h:67
 ProfileLikelihoodTestStat.h:68
 ProfileLikelihoodTestStat.h:69
 ProfileLikelihoodTestStat.h:70
 ProfileLikelihoodTestStat.h:71
 ProfileLikelihoodTestStat.h:72
 ProfileLikelihoodTestStat.h:73
 ProfileLikelihoodTestStat.h:74
 ProfileLikelihoodTestStat.h:75
 ProfileLikelihoodTestStat.h:76
 ProfileLikelihoodTestStat.h:77
 ProfileLikelihoodTestStat.h:78
 ProfileLikelihoodTestStat.h:79
 ProfileLikelihoodTestStat.h:80
 ProfileLikelihoodTestStat.h:81
 ProfileLikelihoodTestStat.h:82
 ProfileLikelihoodTestStat.h:83
 ProfileLikelihoodTestStat.h:84
 ProfileLikelihoodTestStat.h:85
 ProfileLikelihoodTestStat.h:86
 ProfileLikelihoodTestStat.h:87
 ProfileLikelihoodTestStat.h:88
 ProfileLikelihoodTestStat.h:89
 ProfileLikelihoodTestStat.h:90
 ProfileLikelihoodTestStat.h:91
 ProfileLikelihoodTestStat.h:92
 ProfileLikelihoodTestStat.h:93
 ProfileLikelihoodTestStat.h:94
 ProfileLikelihoodTestStat.h:95
 ProfileLikelihoodTestStat.h:96
 ProfileLikelihoodTestStat.h:97
 ProfileLikelihoodTestStat.h:98
 ProfileLikelihoodTestStat.h:99
 ProfileLikelihoodTestStat.h:100
 ProfileLikelihoodTestStat.h:101
 ProfileLikelihoodTestStat.h:102
 ProfileLikelihoodTestStat.h:103
 ProfileLikelihoodTestStat.h:104
 ProfileLikelihoodTestStat.h:105
 ProfileLikelihoodTestStat.h:106
 ProfileLikelihoodTestStat.h:107
 ProfileLikelihoodTestStat.h:108
 ProfileLikelihoodTestStat.h:109
 ProfileLikelihoodTestStat.h:110
 ProfileLikelihoodTestStat.h:111
 ProfileLikelihoodTestStat.h:112
 ProfileLikelihoodTestStat.h:113
 ProfileLikelihoodTestStat.h:114
 ProfileLikelihoodTestStat.h:115
 ProfileLikelihoodTestStat.h:116
 ProfileLikelihoodTestStat.h:117
 ProfileLikelihoodTestStat.h:118
 ProfileLikelihoodTestStat.h:119
 ProfileLikelihoodTestStat.h:120
 ProfileLikelihoodTestStat.h:121
 ProfileLikelihoodTestStat.h:122
 ProfileLikelihoodTestStat.h:123
 ProfileLikelihoodTestStat.h:124
 ProfileLikelihoodTestStat.h:125
 ProfileLikelihoodTestStat.h:126
 ProfileLikelihoodTestStat.h:127
 ProfileLikelihoodTestStat.h:128
 ProfileLikelihoodTestStat.h:129
 ProfileLikelihoodTestStat.h:130
 ProfileLikelihoodTestStat.h:131
 ProfileLikelihoodTestStat.h:132
 ProfileLikelihoodTestStat.h:133
 ProfileLikelihoodTestStat.h:134
 ProfileLikelihoodTestStat.h:135
 ProfileLikelihoodTestStat.h:136
 ProfileLikelihoodTestStat.h:137
 ProfileLikelihoodTestStat.h:138
 ProfileLikelihoodTestStat.h:139
 ProfileLikelihoodTestStat.h:140
 ProfileLikelihoodTestStat.h:141
 ProfileLikelihoodTestStat.h:142
 ProfileLikelihoodTestStat.h:143
 ProfileLikelihoodTestStat.h:144
 ProfileLikelihoodTestStat.h:145
 ProfileLikelihoodTestStat.h:146
 ProfileLikelihoodTestStat.h:147
 ProfileLikelihoodTestStat.h:148
 ProfileLikelihoodTestStat.h:149
 ProfileLikelihoodTestStat.h:150
 ProfileLikelihoodTestStat.h:151
 ProfileLikelihoodTestStat.h:152
 ProfileLikelihoodTestStat.h:153
 ProfileLikelihoodTestStat.h:154
 ProfileLikelihoodTestStat.h:155
 ProfileLikelihoodTestStat.h:156
 ProfileLikelihoodTestStat.h:157
 ProfileLikelihoodTestStat.h:158
 ProfileLikelihoodTestStat.h:159
 ProfileLikelihoodTestStat.h:160
 ProfileLikelihoodTestStat.h:161
 ProfileLikelihoodTestStat.h:162
 ProfileLikelihoodTestStat.h:163
 ProfileLikelihoodTestStat.h:164
 ProfileLikelihoodTestStat.h:165
 ProfileLikelihoodTestStat.h:166
 ProfileLikelihoodTestStat.h:167
 ProfileLikelihoodTestStat.h:168
 ProfileLikelihoodTestStat.h:169
 ProfileLikelihoodTestStat.h:170
 ProfileLikelihoodTestStat.h:171
 ProfileLikelihoodTestStat.h:172
 ProfileLikelihoodTestStat.h:173
 ProfileLikelihoodTestStat.h:174
 ProfileLikelihoodTestStat.h:175
 ProfileLikelihoodTestStat.h:176
 ProfileLikelihoodTestStat.h:177
 ProfileLikelihoodTestStat.h:178
 ProfileLikelihoodTestStat.h:179
 ProfileLikelihoodTestStat.h:180
 ProfileLikelihoodTestStat.h:181
 ProfileLikelihoodTestStat.h:182
 ProfileLikelihoodTestStat.h:183
 ProfileLikelihoodTestStat.h:184
 ProfileLikelihoodTestStat.h:185
 ProfileLikelihoodTestStat.h:186
 ProfileLikelihoodTestStat.h:187
 ProfileLikelihoodTestStat.h:188
 ProfileLikelihoodTestStat.h:189
 ProfileLikelihoodTestStat.h:190
 ProfileLikelihoodTestStat.h:191
 ProfileLikelihoodTestStat.h:192
 ProfileLikelihoodTestStat.h:193
 ProfileLikelihoodTestStat.h:194
 ProfileLikelihoodTestStat.h:195
 ProfileLikelihoodTestStat.h:196
 ProfileLikelihoodTestStat.h:197
 ProfileLikelihoodTestStat.h:198
 ProfileLikelihoodTestStat.h:199
 ProfileLikelihoodTestStat.h:200
 ProfileLikelihoodTestStat.h:201
 ProfileLikelihoodTestStat.h:202
 ProfileLikelihoodTestStat.h:203
 ProfileLikelihoodTestStat.h:204
 ProfileLikelihoodTestStat.h:205
 ProfileLikelihoodTestStat.h:206
 ProfileLikelihoodTestStat.h:207