// @(#)root/roostats:$Id$
// Author: Sven Kreiss, Kyle Cranmer   Nov 2010
/*************************************************************************
 * 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_AsymptoticCalculator
#define ROOSTATS_AsymptoticCalculator



#ifndef ROOSTATS_HypoTestCalculatorGeneric
#include "RooStats/HypoTestCalculatorGeneric.h"
#endif

class RooArgSet;
class RooPoisson;
class RooProdPdf;


namespace RooStats {

/**

  Hypothesis Test Calculator based on the asymptotic formulae for the profile likelihood ratio.
 
  See G. Cowan, K. Cranmer, E. Gross and O. Vitells: Asymptotic formulae for likelihood- based tests of new physics. Eur. Phys. J., C71:1–19, 2011.
  It provides method to perform an hypothesis tests using the likelihood function 
  and computes the p values for the null and the alternate using the asymptotic
  formulae for the profile likelihood ratio described in the given paper. 

  The calculator provides methods to produce the Asimov dataset, i.e a dataset generated where the observade values are equal to the expected ones. 
  The Asimov data set is then used to compute the observed asymptotic p-value for the alternate hypothesis and the asympotic expected p-values.

  The asymptotic formulae are valid only for one POI (parameter of interest). So the calculator works only for one-dimesional (one POI) model. 
   If more than one POI exists consider as POI only the first one is used.                                                                                       

   \ingroup Roostats
*/


   class AsymptoticCalculator : public HypoTestCalculatorGeneric {

   public:
      AsymptoticCalculator(
         RooAbsData &data,  // need to pass non-const since RooAbsPdf::fitTo takes a non-const data set 
         const ModelConfig &altModel,
         const ModelConfig &nullModel,  
         bool nominalAsimov = false 
         );
      //    HypoTestCalculatorGeneric(data, altModel, nullModel, 0)
      // {
      // }

      ~AsymptoticCalculator() {
      }

      /// initialize the calculator by performin g a global fit and make the Asimov data set
      bool Initialize() const; 

      /// re-implement HypoTest computation using the asymptotic 
      virtual HypoTestResult *GetHypoTest() const; 

      /// make the asimov data from the ModelConfig and list of poi - return data set annd snapshoot of global obs 
      /// poiValues is the snapshot of POI used for finding the best buisance parameter values (conditioned at these values)
      /// genPoiValues is optionally a different set of POI values used for generating. By default the same POI are used for generating and for finding the nuisance parameters
      static RooAbsData * MakeAsimovData( RooAbsData & data, const ModelConfig & model,  const RooArgSet & poiValues, RooArgSet & globObs, const RooArgSet * genPoiValues = 0); 


      /// make a nominal asimov data from the ModelConfig and parameter values
      /// The parameter values (including the nunisance) could be given from a fit to data or be at the nominal values
      static RooAbsData * MakeAsimovData( const ModelConfig & model,  const RooArgSet & allParamValues, RooArgSet & globObs);



      static RooAbsData * GenerateAsimovData(const RooAbsPdf & pdf, const RooArgSet & observables ); 

      /// function given the null and the alt p value - return the expected one given the N - sigma value
      static double GetExpectedPValues(double pnull, double palt, double nsigma, bool usecls, bool oneSided = true ); 

      /// set test statistic for one sided (upper limits)
      void SetOneSided(bool on) { fOneSided = on; }

      /// set the test statistics for two sided (in case of upper limits
      /// for discovery does not make really sense)
      void SetTwoSided() { fOneSided = false; fOneSidedDiscovery = false;}

      /// set the test statistics for one-sided discovery
      void SetOneSidedDiscovery(bool on) { fOneSidedDiscovery = on; }

      /// re-implementation of  setters since they are needed to re-initialize the calculator
      virtual void SetNullModel(const ModelConfig &nullModel) {
         HypoTestCalculatorGeneric::SetNullModel(nullModel);
         fIsInitialized = false; 
      }
      virtual void SetAlternateModel(const ModelConfig &altModel) {
         HypoTestCalculatorGeneric::SetAlternateModel(altModel);
         fIsInitialized = false; 
      }
      virtual void SetData(RooAbsData &data) { 
         HypoTestCalculatorGeneric::SetData(data);
         fIsInitialized = false; 
      }


      bool IsTwoSided() const { return (!fOneSided && !fOneSidedDiscovery); }
      bool IsOneSidedDiscovery() const { return fOneSidedDiscovery; }


      /// set using of qtilde, by default is controlled if RoORealVar is limited or not 
      void SetQTilde(bool on) { fUseQTilde = on; }

      /// return snapshot of the best fit parameter 
      const RooArgSet & GetBestFitPoi() const { return fBestFitPoi; }
      /// return best fit parameter (firs of poi)
      const RooRealVar * GetMuHat() const { return dynamic_cast<RooRealVar*>(fBestFitPoi.first()); }
      /// return best fit value for all parameters
      const RooArgSet & GetBestFitParams() const { return fBestFitPoi; }

      static void SetPrintLevel(int level);

   protected:
      // // configure TestStatSampler for the Null run
      // int PreNullHook(RooArgSet *parameterPoint, double obsTestStat) const;

      // // configure TestStatSampler for the Alt run
      // int PreAltHook(RooArgSet *parameterPoint, double obsTestStat) const;

      
      static RooAbsData * GenerateAsimovDataSinglePdf(const RooAbsPdf & pdf, const RooArgSet & obs,  const RooRealVar & weightVar,
                                                      RooCategory * channelCat = 0);

      static RooAbsData * GenerateCountingAsimovData(RooAbsPdf & pdf, const RooArgSet & obs,  const RooRealVar & weightVar,
                                                      RooCategory * channelCat = 0);


      static void FillBins(const RooAbsPdf & pdf, const RooArgList &obs, RooAbsData & data, int &index,  double
                           &binVolume, int &ibin); 

      static double EvaluateNLL(RooAbsPdf & pdf, RooAbsData& data, const RooArgSet * condObs, const RooArgSet *poiSet = 0 ); 

      static bool SetObsToExpected(RooAbsPdf &pdf, const RooArgSet &obs);
      static bool SetObsToExpected(RooProdPdf &prod, const RooArgSet &obs); 

   protected:
      ClassDef(AsymptoticCalculator,2)

   private: 

      bool fOneSided;                // for one sided PL test statistic (upper limits)
      mutable bool fOneSidedDiscovery;                // for one sided PL test statistic (for discovery)
      bool fNominalAsimov;                   // make Asimov at nominal parameter values
      mutable bool fIsInitialized;                  //! flag to check if calculator is initialized
      mutable int fUseQTilde;              // flag to indicate if using qtilde or not (-1 (default based on RooRealVar)), 0 false, 1 (true)
      static int fgPrintLevel;     // control print level  (0 minimal, 1 normal, 2 debug)
      mutable double fNLLObs; 
      mutable double fNLLAsimov; 

      mutable RooAbsData * fAsimovData;   // asimov data set 
      mutable RooArgSet  fAsimovGlobObs;  // snapshot of Asimov global observables 
      mutable RooArgSet  fBestFitPoi;       // snapshot of best fitted POI values
      mutable RooArgSet  fBestFitParams;       // snapshot of all best fitted Parameter values
      
      
   };
}

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