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



#ifndef ROOSTATS_SimpleInterval
#include "RooStats/SimpleInterval.h"
#endif

#include "RooStats/HypoTestResult.h"

class RooRealVar;

namespace RooStats {

class SamplingDistribution;

class HypoTestInverterResult : public SimpleInterval {

public:

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

   // constructor
   HypoTestInverterResult( const char* name, 
                           const RooRealVar& scannedVariable,
                           double cl ) ;

   HypoTestInverterResult( const HypoTestInverterResult& other, const char* name );

   // destructor
   virtual ~HypoTestInverterResult();

   // operator =
   HypoTestInverterResult& operator = (const HypoTestInverterResult& other);

   // remove points that appear to have failed.
   int ExclusionCleanup();

   // merge with the content of another HypoTestInverterResult object
   bool Add( const HypoTestInverterResult& otherResult );

   //add the result of a single point (an HypoTestRsult) 
   bool Add( Double_t x, const HypoTestResult & result ); 

   // function to return the value of the parameter of interest for the i^th entry in the results
   double GetXValue( int index ) const ;

   // function to return the value of the confidence level for the i^th entry in the results
   double GetYValue( int index ) const ;

   // function to return the estimated error on the value of the confidence level for the i^th entry in the results
   double GetYError( int index ) const ;

   // return the observed CLsplusb value  for the i-th entry
   double CLsplusb( int index) const; 
 
   // return the observed CLb value  for the i-th entry
   double CLb( int index) const; 

   // return the observed CLb value  for the i-th entry
   double CLs( int index) const; 

   // return the observed CLsplusb value  for the i-th entry
   double CLsplusbError( int index) const; 
 
   // return the observed CLb value  for the i-th entry
   double CLbError( int index) const; 

   // return the observed CLb value  for the i-th entry
   double CLsError( int index) const; 
   
   // return a pointer to the i^th result object
   HypoTestResult* GetResult( int index ) const ;   

   double GetLastYValue( ) const  { return GetYValue(  fXValues.size()-1); }

   double GetLastXValue( ) const  { return GetXValue(  fXValues.size()-1); }

   double GetLastYError( ) const  { return GetYError(  fXValues.size()-1); }

   HypoTestResult * GetLastResult( ) const  { return GetResult(  fXValues.size()-1); }

   // number of entries in the results array
   int ArraySize() const { return fXValues.size(); };

   int FindIndex(double xvalue) const;

   // set the size of the test (rate of Type I error) (eg. 0.05 for a 95% Confidence Interval)
   virtual void SetTestSize( Double_t size ) { fConfidenceLevel = 1.-size; }

   // set the confidence level for the interval (eg. 0.95 for a 95% Confidence Interval)
   virtual void SetConfidenceLevel( Double_t cl ) { fConfidenceLevel = cl; }

   // set CLs threshold for exclusion cleanup function 
   inline void SetCLsCleanupThreshold( Double_t th ) { fCLsCleanupThreshold = th; }

   // flag to switch between using CLsb (default) or CLs as confidence level
   void UseCLs( bool on = true ) { fUseCLs = on; }  

   // query if one sided result
   bool IsOneSided() const { return !fIsTwoSided; }
   // query if two sided result
   bool IsTwoSided() const { return fIsTwoSided; }

   // lower and upper bound of the confidence interval (to get upper/lower limits, multiply the size( = 1-confidence level ) by 2
   Double_t LowerLimit();
   Double_t UpperLimit();

   // rough estimation of the error on the computed bound of the confidence interval 
   // Estimate of lower limit error
   //function evaluates only a rought error on the lower limit. Be careful when using this estimation
   Double_t LowerLimitEstimatedError();

   // Estimate of lower limit error
   //function evaluates only a rought error on the lower limit. Be careful when using this estimation
   Double_t UpperLimitEstimatedError();

   // return expected distribution of p-values (Cls or Clsplusb)
   
   SamplingDistribution * GetExpectedPValueDist(int index) const; 

   SamplingDistribution * GetBackgroundTestStatDist(int index ) const; 

   SamplingDistribution * GetSignalAndBackgroundTestStatDist(int index) const; 

   // same in terms of alt and null
   SamplingDistribution * GetNullTestStatDist(int index) const { 
      return  GetSignalAndBackgroundTestStatDist(index);
   }
   SamplingDistribution * GetAltTestStatDist(int index) const { 
      return  GetBackgroundTestStatDist(index);
   }

   // get expected lower limit distributions
   // implemented using interpolation 
   //  The size for the sampling distribution is given (by default is given by the average number of toy/point)
   SamplingDistribution* GetLowerLimitDistribution() const { return GetLimitDistribution(true); }

   // get expected upper limit distributions
   // implemented using interpolation
   SamplingDistribution* GetUpperLimitDistribution() const { return GetLimitDistribution(false); }

   // get Limit value correspnding at the desired nsigma level (0) is median -1 sigma is 1 sigma
   double GetExpectedLowerLimit(double nsig = 0, const char * opt = "" ) const ; 

   // get Limit value correspnding at the desired nsigma level (0) is median -1 sigma is 1 sigma
   double GetExpectedUpperLimit(double nsig = 0, const char * opt = "") const ; 


   double FindInterpolatedLimit(double target, bool lowSearch = false, double xmin=1, double xmax=0);

   enum InterpolOption_t { kLinear, kSpline };

   // set the interpolation option, linear (kLinear ) or spline  (kSpline)
   void SetInterpolationOption( InterpolOption_t opt) { fInterpolOption = opt; }
   
   InterpolOption_t GetInterpolationOption() const { return fInterpolOption; }

private:


   double CalculateEstimatedError(double target, bool lower = true, double xmin = 1, double xmax = 0);

   int FindClosestPointIndex(double target, int mode = 0, double xtarget = 0);

   SamplingDistribution* GetLimitDistribution(bool lower ) const;

   double GetExpectedLimit(double nsig, bool lower, const char * opt = "" ) const ; 

   double GetGraphX(const TGraph & g, double y0, bool lowSearch, double &xmin, double &xmax) const;
   double GetGraphX(const TGraph & g, double y0, bool lowSearch = true) const { 
      double xmin=1; double xmax = 0;
      return GetGraphX(g,y0,lowSearch,xmin,xmax);
   }

 
protected:

   bool fUseCLs; 
   bool fIsTwoSided;                  // two sided scan (look for lower/upper limit) 
   bool fInterpolateLowerLimit;
   bool fInterpolateUpperLimit;
   bool fFittedLowerLimit;
   bool fFittedUpperLimit;
   InterpolOption_t fInterpolOption;  // interpolatation option (linear or spline)

   double fLowerLimitError;
   double fUpperLimitError;

   double fCLsCleanupThreshold;

   static double fgAsymptoticMaxSigma;  // max sigma value used to scan asymptotic expected p values 

   std::vector<double> fXValues;

   TList fYObjects;       // list of HypoTestResult for each point
   TList fExpPValues;     // list of expected sampling distribution for each point

   friend class HypoTestInverter;
   friend class HypoTestInverterPlot;
   friend class HypoTestInverterOriginal;

   ClassDef(HypoTestInverterResult,5)  // HypoTestInverterResult class      
};
}

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