Logo ROOT   6.08/07
Reference Guide
HypoTestInverterOriginal.cxx
Go to the documentation of this file.
1 // @(#)root/roostats:$Id$
2 // Author: Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke
3 /*************************************************************************
4  * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 ////////////////////////////////////////////////////////////////////////////////
12 
13 
14 // include header file of this class
16 
18 #include "RooStats/HybridResult.h"
21 
22 // include other header files
23 #include "RooAbsPdf.h"
24 #include "RooAbsData.h"
25 #include "RooRealVar.h"
26 #include "TMath.h"
27 
29 
30 using namespace RooStats;
31 using namespace std;
32 
33 
35  fCalculator0(0),
36  fScannedVariable(0),
37  fResults(0),
38  fUseCLs(false),
39  fSize(0)
40 {
41  // default constructor (doesn't do anything)
42 }
43 
44 
46  RooRealVar& scannedVariable, double size ) :
47  TNamed( ),
48  fCalculator0(&myhc0),
49  fScannedVariable(&scannedVariable),
50  fResults(0),
51  fUseCLs(false),
52  fSize(size)
53 {
54  // constructor from a reference to an HypoTestCalculator
55  // (it must be an HybridCalculator type) and a RooRealVar for the variable
56  SetName("HypoTestInverterOriginal");
57 
58 
60  if (hc == 0) {
61  Fatal("HypoTestInverterOriginal","Using non HybridCalculatorOriginal class IS NOT SUPPORTED");
62  }
63 
64 }
65 
66 
68 {
69  // destructor
70 
71  // delete the HypoTestInverterResult
72  if (fResults) delete fResults;
73 }
74 
76  // create a new HypoTestInverterResult to hold all computed results
77  if (fResults == 0) {
78  TString results_name = this->GetName();
79  results_name += "_results";
81  fResults->SetTitle("HypoTestInverterOriginal Result");
82  }
84 }
85 
86 
87 bool HypoTestInverterOriginal::RunAutoScan( double xMin, double xMax, double target, double epsilon, unsigned int numAlgorithm )
88 {
89  /// Search for the value of the parameter of interest (vary the
90  /// hypothesis being tested) in the specified range [xMin,xMax]
91  /// until the confidence level is compatible with the target value
92  /// within one time the estimated error (and the estimated error
93  /// should also become smaller than the specified parameter epsilon)
94 
95  // various sanity checks on the input parameters
96  if ( xMin>=xMax || xMin< fScannedVariable->getMin() || xMax>fScannedVariable->getMax() ) {
97  std::cout << "Error: problem with the specified range\n";
98  return false;
99  }
100  if ( target<=0 || target>=1 ) {
101  std::cout << "Error: problem with target value\n";
102  return false;
103  }
104  if ( epsilon>0.5-fabs(0.5-target) ) {
105  std::cout << "Error: problem with error value\n";
106  return false;
107  }
108  if ( numAlgorithm!=0 && numAlgorithm!=1 ) {
109  std::cout << "Error: invalid interpolation algorithm\n";
110  return false;
111  }
112 
113  CreateResults();
114 
115  // if ( TMath::AreEqualRel(target,1-Size()/2,DBL_EPSILON) ) { // to uncomment for ROOT 5.26
116  if ( fabs(1-target/(1-Size()/2))<DBL_EPSILON ) {
118  std::cout << "Target matches lower limit: de-activate interpolation in HypoTestInverterResult\n";
119  }
120  // if ( TMath::AreEqualRel(target,Size()/2,DBL_EPSILON) ) { // to uncomment for ROOT 5.26
121  if ( fabs(1-target/((Size()/2)))<DBL_EPSILON ) {
123  std::cout << "Target matches upper limit: de-activate interpolation in HypoTestInverterResult\n";
124  }
125 
126  // parameters of the algorithm that are hard-coded
127  const double nSigma = 1; // number of times the estimated error the final p-value should be from the target
128 
129  // backup some values to be restored at the end
130  const unsigned int nToys_backup = ((HybridCalculatorOriginal*)fCalculator0)->GetNumberOfToys();
131 
132  // check the 2 hypothesis tests specified as extrema in the constructor
133  double leftX = xMin;
134  if (!RunOnePoint(leftX)) return false;
135  double leftCL = fResults->GetYValue(fResults->ArraySize()-1);
136  double leftCLError = fResults->GetYError(fResults->ArraySize()-1);
137 
138  double rightX = xMax;
139  if (!RunOnePoint(rightX)) return false;
140  double rightCL = fResults->GetYValue(fResults->ArraySize()-1);
141  double rightCLError = fResults->GetYError(fResults->ArraySize()-1);
142 
143  if ( rightCL>target && leftCL>target ) {
144  std::cout << "The confidence level at both boundaries are both too large ( " << leftCL << " and " << rightCL << std::endl << "Run again with other boundaries or larger toy-MC statistics\n";
145  return false;
146  }
147  if ( rightCL<target && leftCL<target ) {
148  std::cout << "The confidence level at both boundaries are both too small ( " << leftCL << " and " << rightCL << std::endl << "Run again with other boundaries or larger toy-MC statistics\n";
149  return false;
150  }
151 
152  unsigned int nIteration = 2; // number of iteration performed by the algorithm
153  bool quitThisLoop = false; // flag to interrupt the search and quit cleanly
154 
155  double centerCL = 0;
156  double centerCLError = 0;
157 
158  // search for the value of the searched variable where the CL is
159  // within 1 sigma of the desired level and sigma smaller than
160  // epsilon.
161  do {
162  double x = 0;
163 
164  // safety checks
165  if (leftCL==rightCL) {
166  std::cout << "This cannot (and should not) happen... quit\n";
167  quitThisLoop = true;
168  } else if (leftX==rightX) {
169  std::cout << "This cannot (and should not) happen... quit\n";
170  quitThisLoop = true;
171  } else {
172 
173  // apply chosen type of interpolation algorithm
174  if (numAlgorithm==0) {
175  // exponential interpolation
176 
177  // add safety checks
178  if (!leftCL) leftCL = DBL_EPSILON;
179  if (!rightCL) rightCL = DBL_EPSILON;
180 
181  double a = (log(leftCL) - log(rightCL)) / (leftX - rightX);
182  double b = leftCL / exp(a * leftX);
183  x = (log(target) - log(b)) / a;
184 
185  // to do: do not allow next iteration outside the xMin,xMax interval
186  if (x<xMin || x>xMax || TMath::IsNaN(x)) {
187  std::cout << "Extrapolated value out of range or nan: exits\n";
188  quitThisLoop = true;
189  }
190  } else if (numAlgorithm==1) {
191  // linear interpolation
192 
193  double a = (leftCL-rightCL)/(leftX-rightX);
194  double b = leftCL-a*leftX;
195  x = (target-b)/a;
196 
197  if (x<xMin || x>xMax || TMath::IsNaN(x)) {
198  std::cout << "Extrapolated value out of range or nan: exits\n";
199  quitThisLoop = true;
200  }
201  } // end of interpolation algorithms
202  }
203 
204  if ( x==leftX || x==rightX ) {
205  std::cout << "Error: exit because interpolated value equals to a previous iteration\n";
206  quitThisLoop = true;
207  }
208 
209  // perform another hypothesis-test for value x
210  bool success = false;
211  if (!quitThisLoop) success = RunOnePoint(x);
212 
213  if (success) {
214 
215  nIteration++; // succeeded, increase the iteration counter
216  centerCL = fResults->GetYValue(fResults->ArraySize()-1);
217  centerCLError = fResults->GetYError(fResults->ArraySize()-1);
218 
219  // replace either the left or right point by this new point
220 
221  // test if the interval points are on different sides, then
222  // replace the one on the correct side with the center
223  if ( (leftCL > target) == (rightCL < target) ) {
224  if ( (centerCL > target) == (leftCL > target) ) {
225  leftX = x;
226  leftCL = centerCL;
227  leftCLError = centerCLError;
228  } else {
229  rightX = x;
230  rightCL = centerCL;
231  rightCLError = centerCLError;
232  }
233  // Otherwise replace the point farest away from target (measured in
234  // sigmas)
235  } else if ( (fabs(leftCL - target) / leftCLError) >
236  (fabs(rightCL - target) / rightCLError) ) {
237  leftX = x;
238  leftCL = centerCL;
239  leftCLError = centerCLError;
240  } else {
241  rightX = x;
242  rightCL = centerCL;
243  rightCLError = centerCLError;
244  }
245 
246  // if a point is found compatible with the target CL but with too
247  // large error, increase the number of toyMC
248  if ( fabs(centerCL-target) < nSigma*centerCLError && centerCLError > epsilon ) {
249  do {
250 
251  int nToys = ((HybridCalculatorOriginal*)fCalculator0)->GetNumberOfToys(); // current number of toys
252  int nToysTarget = (int) TMath::Max(nToys*1.5, 1.2*nToys*pow(centerCLError/epsilon,2)); // estimated number of toys until the target precision is reached
253 
254  std::cout << "Increasing the number of toys to: " << nToysTarget << std::endl;
255 
256  // run again the same point with more toyMC (run the complement number of toys)
257  ((HybridCalculatorOriginal*)fCalculator0)->SetNumberOfToys(nToysTarget-nToys);
258 
259  if (!RunOnePoint(x)) quitThisLoop=true;
260  nIteration++; // succeeded, increase the iteration counter
261  centerCL = fResults->GetYValue(fResults->ArraySize()-1);
262  centerCLError = fResults->GetYError(fResults->ArraySize()-1);
263 
264  // set the number of toys to reach the target
265  ((HybridCalculatorOriginal*)fCalculator0)->SetNumberOfToys(nToysTarget);
266  } while ( fabs(centerCL-target) < nSigma*centerCLError && centerCLError > epsilon && quitThisLoop==false ); // run this block again if it's still compatible with the target and the error still too large
267  }
268 
269  if (leftCL==rightCL) {
270  std::cout << "Algorithm failed: left and right CL are equal (no intrapolation possible or more toy-MC statistics needed)\n";
271  quitThisLoop = true;
272  }
273  } // end running one more iteration
274 
275  } while ( ( fabs(centerCL-target) > nSigma*centerCLError || centerCLError > epsilon ) && quitThisLoop==false ); // end of the main 'do' loop
276 
277  // restore some parameters that might have been changed by the algorithm
278  ((HybridCalculatorOriginal*)fCalculator0)->SetNumberOfToys(nToys_backup);
279 
280  if ( quitThisLoop==true ) {
281  // abort and return 'false' to indicate fail status
282  std::cout << "Aborted the search because something happened\n";
283  return false;
284  }
285 
286  std::cout << "Converged in " << fResults->ArraySize() << " iterations\n";
287 
288  // finished: return 'true' for success status
289  return true;
290 }
291 
292 
293 bool HypoTestInverterOriginal::RunFixedScan( int nBins, double xMin, double xMax )
294 {
295  // Run a Fixed scan in npoints between min and max
296 
297  CreateResults();
298  // safety checks
299  if ( nBins<=0 ) {
300  std::cout << "Please provide nBins>0\n";
301  return false;
302  }
303  if ( nBins==1 && xMin!=xMax ) {
304  std::cout << "nBins==1 -> I will run for xMin (" << xMin << ")\n";
305  }
306  if ( xMin==xMax && nBins>1 ) {
307  std::cout << "xMin==xMax -> I will enforce nBins==1\n";
308  nBins = 1;
309  }
310  if ( xMin>xMax ) {
311  std::cout << "Please provide xMin (" << xMin << ") smaller that xMax (" << xMax << ")\n";
312  return false;
313  }
314 
315  for (int i=0; i<nBins; i++) {
316  double thisX = xMin+i*(xMax-xMin)/(nBins-1);
317  bool status = RunOnePoint(thisX);
318 
319  // check if failed status
320  if ( status==false ) {
321  std::cout << "Loop interrupted because of failed status\n";
322  return false;
323  }
324  }
325 
326  return true;
327 }
328 
329 
331 {
332  // run only one point
333 
334  CreateResults();
335 
336  // check if thisX is in the range specified for fScannedVariable
337  if ( thisX<fScannedVariable->getMin() ) {
338  std::cout << "Out of range: using the lower bound on the scanned variable rather than " << thisX<< "\n";
339  thisX = fScannedVariable->getMin();
340  }
341  if ( thisX>fScannedVariable->getMax() ) {
342  std::cout << "Out of range: using the upper bound on the scanned variable rather than " << thisX<< "\n";
343  thisX = fScannedVariable->getMax();
344  }
345 
346  double oldValue = fScannedVariable->getVal();
347 
348  fScannedVariable->setVal(thisX);
349  std::cout << "Running for " << fScannedVariable->GetName() << " = " << thisX << endl;
350 
351  // compute the results
352  HypoTestResult* myHybridResult = fCalculator0->GetHypoTest();
353 
354  double lastXtested;
355  if ( fResults->ArraySize()!=0 ) lastXtested = fResults->GetXValue(fResults->ArraySize()-1);
356  else lastXtested = -999;
357 
358  if ( lastXtested==thisX ) {
359 
360  std::cout << "Merge with previous result\n";
361  HybridResult* latestResult = (HybridResult*) fResults->GetResult(fResults->ArraySize()-1);
362  latestResult->Add((HybridResult*)myHybridResult);
363  delete myHybridResult;
364 
365  } else {
366 
367  // fill the results in the HypoTestInverterResult array
368  fResults->fXValues.push_back(thisX);
369  fResults->fYObjects.Add(myHybridResult);
370  }
371 
372 
373  std::cout << "computed: " << fResults->GetYValue(fResults->ArraySize()-1) << endl;
374 
375  fScannedVariable->setVal(oldValue);
376 
377  return true;
378 }
virtual Double_t getMin(const char *name=0) const
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual Double_t getMax(const char *name=0) const
bool RunAutoScan(double xMin, double xMax, double target, double epsilon=0.005, unsigned int numAlgorithm=0)
void Add(HybridResult *other)
add additional toy-MC experiments to the current results use the data test statistics of the added ob...
Double_t getVal(const RooArgSet *set=0) const
Definition: RooAbsReal.h:64
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
double GetXValue(int index) const
function to return the value of the parameter of interest for the i^th entry in the results ...
HypoTestResult is a base class for results from hypothesis tests.
HypoTestResult * GetResult(int index) const
return a pointer to the i^th result object
HybridCalculatorOriginal class.
TArc * a
Definition: textangle.C:12
virtual Double_t ConfidenceLevel() const
Get the Confidence level for the test.
double GetYError(int index) const
function to return the estimated error on the value of the confidence level for the i^th entry in the...
STL namespace.
Double_t x[n]
Definition: legend1.C:17
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
double pow(double, double)
void UseCLs(bool on=true)
flag to switch between using CLsb (default) or CLs as confidence level
bool fInterpolateLowerLimit
two sided scan (look for lower/upper limit)
HypoTestCalculator is an interface class for a tools which produce RooStats HypoTestResults.
RooRealVar represents a fundamental (non-derived) real valued object.
Definition: RooRealVar.h:37
virtual void setVal(Double_t value)
Set value of variable to &#39;value&#39;.
Definition: RooRealVar.cxx:205
virtual Double_t Size() const
Get the size of the test (eg. rate of Type I error)
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
REAL epsilon
Definition: triangle.c:617
virtual HypoTestResult * GetHypoTest() const =0
Namespace for the RooStats classes.
Definition: Asimov.h:20
This class is now depratcated and to be replaced by the HypoTestInverter.
#define ClassImp(name)
Definition: Rtypes.h:279
HypoTestInverterResult class: holds the array of hypothesis test results and compute a confidence int...
double GetYValue(int index) const
function to return the value of the confidence level for the i^th entry in the results ...
virtual void Add(TObject *obj)
Definition: TList.h:81
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Int_t IsNaN(Double_t x)
Definition: TMath.h:613
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
bool RunFixedScan(int nBins, double xMin, double xMax)
double exp(double)
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
int ArraySize() const
number of entries in the results array
double log(double)
std::vector< double > fXValues
number of points used to build expected p-values