// @(#)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

//_________________________________________________
/*
BEGIN_HTML
<p>
Calculator based on Asymptotic formula, 
 on the ProfileLikelihood and the Asimov data set
</p>
END_HTML
*/
//



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

class RooArgSet;
class RooPoisson;
class RooProdPdf;


namespace 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-implement setters since they needs 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