ROOT logo
// @(#)root/roostats:$Id: HypoTestInverter.cxx 31876 2009-12-14 11:11:27Z brun $
// 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.             *
 *************************************************************************/

//_________________________________________________________________
/**
   HypoTestInverter class for performing an hypothesis test inversion by scanning the hypothesis test results of the 
  HybridCalculator  for various values of the parameter of interest. By looking at the confidence level curve of 
 the result  an upper limit, where it intersects the desired confidence level, can be derived.
 The class implements the RooStats::IntervalCalculator interface and returns an  RooStats::HypoTestInverterResult class.
 The result is a SimpleInterval, which via the method UpperLimit returns to the user the upper limit value.

The  HypoTestInverter implements various option for performing the scan. HypoTestInverter::RunFixedScan will scan using a fixed grid the parameter of interest. HypoTestInverter::RunAutoScan will perform an automatic scan to find optimally the curve and it will stop until the desired precision is obtained.
The confidence level value at a given point can be done via  HypoTestInverter::RunOnePoint.
The class can scan the CLs+b values or alternativly CLs (if the method HypoTestInverter::UseCLs has been called).


   New contributions to this class have been written by Matthias Wolf (advanced AutoRun algorithm)
**/

// include other header files

#include "RooAbsPdf.h"
#include "RooAbsData.h"
#include "RooRealVar.h"
#include "TMath.h"

#include "RooStats/HybridCalculator.h"
#include "RooStats/HybridResult.h"

// include header file of this class 
#include "RooStats/HypoTestInverter.h"


ClassImp(RooStats::HypoTestInverter)

using namespace RooStats;


HypoTestInverter::HypoTestInverter( ) :
   fCalculator0(0),
   fScannedVariable(0),
   fResults(0),
   fUseCLs(false),
   fSize(0)
{
  // default constructor (doesn't do anything) 
}


HypoTestInverter::HypoTestInverter( HypoTestCalculator& myhc0,
				    RooRealVar& scannedVariable, double size ) :
   TNamed( ),
   fCalculator0(&myhc0),
   fScannedVariable(&scannedVariable), 
   fResults(0),
   fUseCLs(false),
   fSize(size)
{
   // constructor from a reference to an HypoTestCalculator 
   // (it must be an HybridCalculator type) and a RooRealVar for the variable
   SetName("HypoTestInverter");


   HybridCalculator * hc = dynamic_cast<HybridCalculator *> (fCalculator0);
   if (hc == 0) { 
      Fatal("HypoTestInverter","Using non HybridCalculator class IS NOT SUPPORTED");
   }

}


HypoTestInverter::~HypoTestInverter()
{
  // destructor
  
  // delete the HypoTestInverterResult
  if (fResults) delete fResults;
}

void  HypoTestInverter::CreateResults() { 
  // create a new HypoTestInverterResult to hold all computed results
   if (fResults == 0) {
      TString results_name = this->GetName();
      results_name += "_results";
      fResults = new HypoTestInverterResult(results_name,*fScannedVariable,ConfidenceLevel());
      fResults->SetTitle("HypoTestInverter Result");
   }
   fResults->UseCLs(fUseCLs);
}


bool HypoTestInverter::RunAutoScan( double xMin, double xMax, double target, double epsilon, unsigned int numAlgorithm  )
{
  /// Search for the value of the parameter of interest (vary the
  /// hypothesis being tested) in the specified range [xMin,xMax]
  /// until the confidence level is compatible with the target value
  /// within one time the estimated error (and the estimated error
  /// should also become smaller than the specified parameter epsilon)

  // various sanity checks on the input parameters
  if ( xMin>=xMax || xMin< fScannedVariable->getMin() || xMax>fScannedVariable->getMax() ) {
    std::cout << "Error: problem with the specified range\n";
    return false;
  }
  if ( target<=0 || target>=1 ) {
    std::cout << "Error: problem with target value\n";
    return false;
  }
  if ( epsilon>0.5-fabs(0.5-target) ) {
    std::cout << "Error: problem with error value\n";
    return false;
  }
  if ( numAlgorithm!=0 && numAlgorithm!=1 ) {
    std::cout << "Error: invalid interpolation algorithm\n";
    return false;
  }

  CreateResults();

  // if ( TMath::AreEqualRel(target,1-Size()/2,DBL_EPSILON) ) {  // to uncomment for ROOT 5.26
  if ( fabs(1-target/(1-Size()/2))<DBL_EPSILON ) {
    fResults->fInterpolateLowerLimit = false;
    std::cout << "Target matches lower limit: de-activate interpolation in HypoTestInverterResult\n";
  }
  // if ( TMath::AreEqualRel(target,Size()/2,DBL_EPSILON) ) {  // to uncomment for ROOT 5.26
  if ( fabs(1-target/((Size()/2)))<DBL_EPSILON ) {
    fResults->fInterpolateUpperLimit = false;
    std::cout << "Target matches upper limit: de-activate interpolation in HypoTestInverterResult\n";
  }

  // parameters of the algorithm that are hard-coded
  const double nSigma = 1; // number of times the estimated error the final p-value should be from the target

  // backup some values to be restored at the end 
  const unsigned int nToys_backup = ((HybridCalculator*)fCalculator0)->GetNumberOfToys();

  // check the 2 hypothesis tests specified as extrema in the constructor
  double leftX = xMin;
  if (!RunOnePoint(leftX)) return false;
  double leftCL = fResults->GetYValue(fResults->ArraySize()-1);
  double leftCLError = fResults->GetYError(fResults->ArraySize()-1);
 
  double rightX = xMax;
  if (!RunOnePoint(rightX)) return false;
  double rightCL = fResults->GetYValue(fResults->ArraySize()-1);
  double rightCLError = fResults->GetYError(fResults->ArraySize()-1);
  
  if ( rightCL>target && leftCL>target ) {
    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";
    return false;
  }
  if ( rightCL<target && leftCL<target ) {
    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";
    return false;
  }

  unsigned int nIteration = 2;  // number of iteration performed by the algorithm
  bool quitThisLoop = false;  // flag to interrupt the search and quit cleanly

  double centerCL = 0;
  double centerCLError = 0;

  // search for the value of the searched variable where the CL is
  // within 1 sigma of the desired level and sigma smaller than
  // epsilon.
  do {
    double x = 0;

    // safety checks
    if (leftCL==rightCL) {
      std::cout << "This cannot (and should not) happen... quit\n";
      quitThisLoop = true;
    } else if (leftX==rightX) {
      std::cout << "This cannot (and should not) happen... quit\n";
      quitThisLoop = true;
    } else {

      // apply chosen type of interpolation algorithm
      if (numAlgorithm==0) {
	// exponential interpolation

	// add safety checks
	if (!leftCL) leftCL = DBL_EPSILON;
	if (!rightCL) rightCL = DBL_EPSILON;

	double a = (log(leftCL) - log(rightCL)) / (leftX - rightX);
	double b = leftCL / exp(a * leftX);
	x = (log(target) - log(b)) / a;

	// to do: do not allow next iteration outside the xMin,xMax interval
	if (x<xMin || x>xMax || isnan(x)) {
	  std::cout << "Extrapolated value out of range or nan: exits\n";
	  quitThisLoop = true;
	}
      } else if (numAlgorithm==1) {
	// linear interpolation
	
	double a = (leftCL-rightCL)/(leftX-rightX);
	double b = leftCL-a*leftX;
	x = (target-b)/a;

	if (x<xMin || x>xMax || isnan(x)) {
	  std::cout << "Extrapolated value out of range or nan: exits\n";
	  quitThisLoop = true;
	}
      }  // end of interpolation algorithms
    }

    if ( x==leftX || x==rightX ) {
      std::cout << "Error: exit because interpolated value equals to a previous iteration\n";
      quitThisLoop = true;
    }

    // perform another hypothesis-test for value x
    bool success = false;
    if (!quitThisLoop) success = RunOnePoint(x);

    if (success) {

      nIteration++;  // succeeded, increase the iteration counter
      centerCL = fResults->GetYValue(fResults->ArraySize()-1);
      centerCLError = fResults->GetYError(fResults->ArraySize()-1);

      // replace either the left or right point by this new point
    
      // test if the interval points are on different sides, then
      // replace the one on the correct side with the center
      if ( (leftCL > target) == (rightCL < target) ) {
	if ( (centerCL > target) == (leftCL > target) ) {
	  leftX = x;
	  leftCL = centerCL;
	  leftCLError = centerCLError;
	} else {
	  rightX = x;
	  rightCL = centerCL;
	  rightCLError = centerCLError;
	}
	// Otherwise replace the point farest away from target (measured in
	// sigmas)
      } else if ( (fabs(leftCL - target) / leftCLError) >
		  (fabs(rightCL - target) / rightCLError) ) {
	leftX = x;
	leftCL = centerCL;
	leftCLError = centerCLError;
      } else {
	rightX = x;
	rightCL = centerCL;
	rightCLError = centerCLError;
      }

      // if a point is found compatible with the target CL but with too
      // large error, increase the number of toyMC
      if ( fabs(centerCL-target) < nSigma*centerCLError && centerCLError > epsilon  ) {
	do {

	  int nToys = ((HybridCalculator*)fCalculator0)->GetNumberOfToys();  // current number of toys
	  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
	  
	  std::cout << "Increasing the number of toys to: " << nToysTarget << std::endl;
	  
	  // run again the same point with more toyMC (run the complement number of toys)
	  ((HybridCalculator*)fCalculator0)->SetNumberOfToys(nToysTarget-nToys);
	  
	  if (!RunOnePoint(x)) quitThisLoop=true;
	  nIteration++;  // succeeded, increase the iteration counter
	  centerCL = fResults->GetYValue(fResults->ArraySize()-1);
	  centerCLError = fResults->GetYError(fResults->ArraySize()-1);
	  
	  // set the number of toys to reach the target 
	  ((HybridCalculator*)fCalculator0)->SetNumberOfToys(nToysTarget);
	} 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
      }
      
      if (leftCL==rightCL) {
	std::cout << "Algorithm failed: left and right CL are equal (no intrapolation possible or more toy-MC statistics needed)\n";
	  quitThisLoop = true;
      }
    } // end running one more iteration

  } while ( ( fabs(centerCL-target) > nSigma*centerCLError || centerCLError > epsilon ) && quitThisLoop==false );  // end of the main 'do' loop 

  // restore some parameters that might have been changed by the algorithm
  ((HybridCalculator*)fCalculator0)->SetNumberOfToys(nToys_backup);
  
  if ( quitThisLoop==true ) {
    // abort and return 'false' to indicate fail status
    std::cout << "Aborted the search because something happened\n";
    return false;
  }

  std::cout << "Converged in " << fResults->ArraySize() << " iterations\n";

  // finished: return 'true' for success status
  return true;
}


bool HypoTestInverter::RunFixedScan( int nBins, double xMin, double xMax )
{
   // Run a Fixed scan in npoints between min and max

   CreateResults();
  // safety checks
  if ( nBins<=0 ) {
    std::cout << "Please provide nBins>0\n";
    return false;
  }
  if ( nBins==1 && xMin!=xMax ) {
    std::cout << "nBins==1 -> I will run for xMin (" << xMin << ")\n";
  }
  if ( xMin==xMax && nBins>1 ) { 
    std::cout << "xMin==xMax -> I will enforce nBins==1\n";
    nBins = 1;
  }
  if ( xMin>xMax ) {
    std::cout << "Please provide xMin (" << xMin << ") smaller that xMax (" << xMax << ")\n";
    return false;
  } 
  
  for (int i=0; i<nBins; i++) {
    double thisX = xMin+i*(xMax-xMin)/(nBins-1);
    bool status = RunOnePoint(thisX);
    
    // check if failed status
    if ( status==false ) {
      std::cout << "Loop interupted because of failed status\n";
      return false;
    }
  }

  return true;
}


bool HypoTestInverter::RunOnePoint( double thisX )
{
   // run only one point 

   CreateResults();

   // check if thisX is in the range specified for fScannedVariable
   if ( thisX<fScannedVariable->getMin() ) {
     std::cout << "Out of range: using the lower bound on the scanned variable rather than " << thisX<< "\n";
     thisX = fScannedVariable->getMin();
   }
   if ( thisX>fScannedVariable->getMax() ) {
     std::cout << "Out of range: using the upper bound on the scanned variable rather than " << thisX<< "\n";
     thisX = fScannedVariable->getMax();
   }

   double oldValue = fScannedVariable->getVal();

   fScannedVariable->setVal(thisX);
   std::cout << "Running for " << fScannedVariable->GetName() << " = " << thisX << endl;
   
   // compute the results
   HypoTestResult* myHybridResult = fCalculator0->GetHypoTest(); 
   
   double lastXtested;
   if ( fResults->ArraySize()!=0 ) lastXtested = fResults->GetXValue(fResults->ArraySize()-1);
   else lastXtested = -999;

   if ( lastXtested==thisX ) {
     
     std::cout << "Merge with previous result\n";
     HybridResult* latestResult = (HybridResult*) fResults->GetResult(fResults->ArraySize()-1);
     latestResult->Add((HybridResult*)myHybridResult);
     delete myHybridResult;

   } else {
     
     // fill the results in the HypoTestInverterResult array
     fResults->fXValues.push_back(thisX);
     fResults->fYObjects.Add(myHybridResult);
   }
   
   fScannedVariable->setVal(oldValue);
   
   return true;
}
 HypoTestInverter.cxx:1
 HypoTestInverter.cxx:2
 HypoTestInverter.cxx:3
 HypoTestInverter.cxx:4
 HypoTestInverter.cxx:5
 HypoTestInverter.cxx:6
 HypoTestInverter.cxx:7
 HypoTestInverter.cxx:8
 HypoTestInverter.cxx:9
 HypoTestInverter.cxx:10
 HypoTestInverter.cxx:11
 HypoTestInverter.cxx:12
 HypoTestInverter.cxx:13
 HypoTestInverter.cxx:14
 HypoTestInverter.cxx:15
 HypoTestInverter.cxx:16
 HypoTestInverter.cxx:17
 HypoTestInverter.cxx:18
 HypoTestInverter.cxx:19
 HypoTestInverter.cxx:20
 HypoTestInverter.cxx:21
 HypoTestInverter.cxx:22
 HypoTestInverter.cxx:23
 HypoTestInverter.cxx:24
 HypoTestInverter.cxx:25
 HypoTestInverter.cxx:26
 HypoTestInverter.cxx:27
 HypoTestInverter.cxx:28
 HypoTestInverter.cxx:29
 HypoTestInverter.cxx:30
 HypoTestInverter.cxx:31
 HypoTestInverter.cxx:32
 HypoTestInverter.cxx:33
 HypoTestInverter.cxx:34
 HypoTestInverter.cxx:35
 HypoTestInverter.cxx:36
 HypoTestInverter.cxx:37
 HypoTestInverter.cxx:38
 HypoTestInverter.cxx:39
 HypoTestInverter.cxx:40
 HypoTestInverter.cxx:41
 HypoTestInverter.cxx:42
 HypoTestInverter.cxx:43
 HypoTestInverter.cxx:44
 HypoTestInverter.cxx:45
 HypoTestInverter.cxx:46
 HypoTestInverter.cxx:47
 HypoTestInverter.cxx:48
 HypoTestInverter.cxx:49
 HypoTestInverter.cxx:50
 HypoTestInverter.cxx:51
 HypoTestInverter.cxx:52
 HypoTestInverter.cxx:53
 HypoTestInverter.cxx:54
 HypoTestInverter.cxx:55
 HypoTestInverter.cxx:56
 HypoTestInverter.cxx:57
 HypoTestInverter.cxx:58
 HypoTestInverter.cxx:59
 HypoTestInverter.cxx:60
 HypoTestInverter.cxx:61
 HypoTestInverter.cxx:62
 HypoTestInverter.cxx:63
 HypoTestInverter.cxx:64
 HypoTestInverter.cxx:65
 HypoTestInverter.cxx:66
 HypoTestInverter.cxx:67
 HypoTestInverter.cxx:68
 HypoTestInverter.cxx:69
 HypoTestInverter.cxx:70
 HypoTestInverter.cxx:71
 HypoTestInverter.cxx:72
 HypoTestInverter.cxx:73
 HypoTestInverter.cxx:74
 HypoTestInverter.cxx:75
 HypoTestInverter.cxx:76
 HypoTestInverter.cxx:77
 HypoTestInverter.cxx:78
 HypoTestInverter.cxx:79
 HypoTestInverter.cxx:80
 HypoTestInverter.cxx:81
 HypoTestInverter.cxx:82
 HypoTestInverter.cxx:83
 HypoTestInverter.cxx:84
 HypoTestInverter.cxx:85
 HypoTestInverter.cxx:86
 HypoTestInverter.cxx:87
 HypoTestInverter.cxx:88
 HypoTestInverter.cxx:89
 HypoTestInverter.cxx:90
 HypoTestInverter.cxx:91
 HypoTestInverter.cxx:92
 HypoTestInverter.cxx:93
 HypoTestInverter.cxx:94
 HypoTestInverter.cxx:95
 HypoTestInverter.cxx:96
 HypoTestInverter.cxx:97
 HypoTestInverter.cxx:98
 HypoTestInverter.cxx:99
 HypoTestInverter.cxx:100
 HypoTestInverter.cxx:101
 HypoTestInverter.cxx:102
 HypoTestInverter.cxx:103
 HypoTestInverter.cxx:104
 HypoTestInverter.cxx:105
 HypoTestInverter.cxx:106
 HypoTestInverter.cxx:107
 HypoTestInverter.cxx:108
 HypoTestInverter.cxx:109
 HypoTestInverter.cxx:110
 HypoTestInverter.cxx:111
 HypoTestInverter.cxx:112
 HypoTestInverter.cxx:113
 HypoTestInverter.cxx:114
 HypoTestInverter.cxx:115
 HypoTestInverter.cxx:116
 HypoTestInverter.cxx:117
 HypoTestInverter.cxx:118
 HypoTestInverter.cxx:119
 HypoTestInverter.cxx:120
 HypoTestInverter.cxx:121
 HypoTestInverter.cxx:122
 HypoTestInverter.cxx:123
 HypoTestInverter.cxx:124
 HypoTestInverter.cxx:125
 HypoTestInverter.cxx:126
 HypoTestInverter.cxx:127
 HypoTestInverter.cxx:128
 HypoTestInverter.cxx:129
 HypoTestInverter.cxx:130
 HypoTestInverter.cxx:131
 HypoTestInverter.cxx:132
 HypoTestInverter.cxx:133
 HypoTestInverter.cxx:134
 HypoTestInverter.cxx:135
 HypoTestInverter.cxx:136
 HypoTestInverter.cxx:137
 HypoTestInverter.cxx:138
 HypoTestInverter.cxx:139
 HypoTestInverter.cxx:140
 HypoTestInverter.cxx:141
 HypoTestInverter.cxx:142
 HypoTestInverter.cxx:143
 HypoTestInverter.cxx:144
 HypoTestInverter.cxx:145
 HypoTestInverter.cxx:146
 HypoTestInverter.cxx:147
 HypoTestInverter.cxx:148
 HypoTestInverter.cxx:149
 HypoTestInverter.cxx:150
 HypoTestInverter.cxx:151
 HypoTestInverter.cxx:152
 HypoTestInverter.cxx:153
 HypoTestInverter.cxx:154
 HypoTestInverter.cxx:155
 HypoTestInverter.cxx:156
 HypoTestInverter.cxx:157
 HypoTestInverter.cxx:158
 HypoTestInverter.cxx:159
 HypoTestInverter.cxx:160
 HypoTestInverter.cxx:161
 HypoTestInverter.cxx:162
 HypoTestInverter.cxx:163
 HypoTestInverter.cxx:164
 HypoTestInverter.cxx:165
 HypoTestInverter.cxx:166
 HypoTestInverter.cxx:167
 HypoTestInverter.cxx:168
 HypoTestInverter.cxx:169
 HypoTestInverter.cxx:170
 HypoTestInverter.cxx:171
 HypoTestInverter.cxx:172
 HypoTestInverter.cxx:173
 HypoTestInverter.cxx:174
 HypoTestInverter.cxx:175
 HypoTestInverter.cxx:176
 HypoTestInverter.cxx:177
 HypoTestInverter.cxx:178
 HypoTestInverter.cxx:179
 HypoTestInverter.cxx:180
 HypoTestInverter.cxx:181
 HypoTestInverter.cxx:182
 HypoTestInverter.cxx:183
 HypoTestInverter.cxx:184
 HypoTestInverter.cxx:185
 HypoTestInverter.cxx:186
 HypoTestInverter.cxx:187
 HypoTestInverter.cxx:188
 HypoTestInverter.cxx:189
 HypoTestInverter.cxx:190
 HypoTestInverter.cxx:191
 HypoTestInverter.cxx:192
 HypoTestInverter.cxx:193
 HypoTestInverter.cxx:194
 HypoTestInverter.cxx:195
 HypoTestInverter.cxx:196
 HypoTestInverter.cxx:197
 HypoTestInverter.cxx:198
 HypoTestInverter.cxx:199
 HypoTestInverter.cxx:200
 HypoTestInverter.cxx:201
 HypoTestInverter.cxx:202
 HypoTestInverter.cxx:203
 HypoTestInverter.cxx:204
 HypoTestInverter.cxx:205
 HypoTestInverter.cxx:206
 HypoTestInverter.cxx:207
 HypoTestInverter.cxx:208
 HypoTestInverter.cxx:209
 HypoTestInverter.cxx:210
 HypoTestInverter.cxx:211
 HypoTestInverter.cxx:212
 HypoTestInverter.cxx:213
 HypoTestInverter.cxx:214
 HypoTestInverter.cxx:215
 HypoTestInverter.cxx:216
 HypoTestInverter.cxx:217
 HypoTestInverter.cxx:218
 HypoTestInverter.cxx:219
 HypoTestInverter.cxx:220
 HypoTestInverter.cxx:221
 HypoTestInverter.cxx:222
 HypoTestInverter.cxx:223
 HypoTestInverter.cxx:224
 HypoTestInverter.cxx:225
 HypoTestInverter.cxx:226
 HypoTestInverter.cxx:227
 HypoTestInverter.cxx:228
 HypoTestInverter.cxx:229
 HypoTestInverter.cxx:230
 HypoTestInverter.cxx:231
 HypoTestInverter.cxx:232
 HypoTestInverter.cxx:233
 HypoTestInverter.cxx:234
 HypoTestInverter.cxx:235
 HypoTestInverter.cxx:236
 HypoTestInverter.cxx:237
 HypoTestInverter.cxx:238
 HypoTestInverter.cxx:239
 HypoTestInverter.cxx:240
 HypoTestInverter.cxx:241
 HypoTestInverter.cxx:242
 HypoTestInverter.cxx:243
 HypoTestInverter.cxx:244
 HypoTestInverter.cxx:245
 HypoTestInverter.cxx:246
 HypoTestInverter.cxx:247
 HypoTestInverter.cxx:248
 HypoTestInverter.cxx:249
 HypoTestInverter.cxx:250
 HypoTestInverter.cxx:251
 HypoTestInverter.cxx:252
 HypoTestInverter.cxx:253
 HypoTestInverter.cxx:254
 HypoTestInverter.cxx:255
 HypoTestInverter.cxx:256
 HypoTestInverter.cxx:257
 HypoTestInverter.cxx:258
 HypoTestInverter.cxx:259
 HypoTestInverter.cxx:260
 HypoTestInverter.cxx:261
 HypoTestInverter.cxx:262
 HypoTestInverter.cxx:263
 HypoTestInverter.cxx:264
 HypoTestInverter.cxx:265
 HypoTestInverter.cxx:266
 HypoTestInverter.cxx:267
 HypoTestInverter.cxx:268
 HypoTestInverter.cxx:269
 HypoTestInverter.cxx:270
 HypoTestInverter.cxx:271
 HypoTestInverter.cxx:272
 HypoTestInverter.cxx:273
 HypoTestInverter.cxx:274
 HypoTestInverter.cxx:275
 HypoTestInverter.cxx:276
 HypoTestInverter.cxx:277
 HypoTestInverter.cxx:278
 HypoTestInverter.cxx:279
 HypoTestInverter.cxx:280
 HypoTestInverter.cxx:281
 HypoTestInverter.cxx:282
 HypoTestInverter.cxx:283
 HypoTestInverter.cxx:284
 HypoTestInverter.cxx:285
 HypoTestInverter.cxx:286
 HypoTestInverter.cxx:287
 HypoTestInverter.cxx:288
 HypoTestInverter.cxx:289
 HypoTestInverter.cxx:290
 HypoTestInverter.cxx:291
 HypoTestInverter.cxx:292
 HypoTestInverter.cxx:293
 HypoTestInverter.cxx:294
 HypoTestInverter.cxx:295
 HypoTestInverter.cxx:296
 HypoTestInverter.cxx:297
 HypoTestInverter.cxx:298
 HypoTestInverter.cxx:299
 HypoTestInverter.cxx:300
 HypoTestInverter.cxx:301
 HypoTestInverter.cxx:302
 HypoTestInverter.cxx:303
 HypoTestInverter.cxx:304
 HypoTestInverter.cxx:305
 HypoTestInverter.cxx:306
 HypoTestInverter.cxx:307
 HypoTestInverter.cxx:308
 HypoTestInverter.cxx:309
 HypoTestInverter.cxx:310
 HypoTestInverter.cxx:311
 HypoTestInverter.cxx:312
 HypoTestInverter.cxx:313
 HypoTestInverter.cxx:314
 HypoTestInverter.cxx:315
 HypoTestInverter.cxx:316
 HypoTestInverter.cxx:317
 HypoTestInverter.cxx:318
 HypoTestInverter.cxx:319
 HypoTestInverter.cxx:320
 HypoTestInverter.cxx:321
 HypoTestInverter.cxx:322
 HypoTestInverter.cxx:323
 HypoTestInverter.cxx:324
 HypoTestInverter.cxx:325
 HypoTestInverter.cxx:326
 HypoTestInverter.cxx:327
 HypoTestInverter.cxx:328
 HypoTestInverter.cxx:329
 HypoTestInverter.cxx:330
 HypoTestInverter.cxx:331
 HypoTestInverter.cxx:332
 HypoTestInverter.cxx:333
 HypoTestInverter.cxx:334
 HypoTestInverter.cxx:335
 HypoTestInverter.cxx:336
 HypoTestInverter.cxx:337
 HypoTestInverter.cxx:338
 HypoTestInverter.cxx:339
 HypoTestInverter.cxx:340
 HypoTestInverter.cxx:341
 HypoTestInverter.cxx:342
 HypoTestInverter.cxx:343
 HypoTestInverter.cxx:344
 HypoTestInverter.cxx:345
 HypoTestInverter.cxx:346
 HypoTestInverter.cxx:347
 HypoTestInverter.cxx:348
 HypoTestInverter.cxx:349
 HypoTestInverter.cxx:350
 HypoTestInverter.cxx:351
 HypoTestInverter.cxx:352
 HypoTestInverter.cxx:353
 HypoTestInverter.cxx:354
 HypoTestInverter.cxx:355
 HypoTestInverter.cxx:356
 HypoTestInverter.cxx:357
 HypoTestInverter.cxx:358
 HypoTestInverter.cxx:359
 HypoTestInverter.cxx:360
 HypoTestInverter.cxx:361
 HypoTestInverter.cxx:362
 HypoTestInverter.cxx:363
 HypoTestInverter.cxx:364
 HypoTestInverter.cxx:365
 HypoTestInverter.cxx:366
 HypoTestInverter.cxx:367
 HypoTestInverter.cxx:368
 HypoTestInverter.cxx:369
 HypoTestInverter.cxx:370
 HypoTestInverter.cxx:371
 HypoTestInverter.cxx:372
 HypoTestInverter.cxx:373
 HypoTestInverter.cxx:374
 HypoTestInverter.cxx:375
 HypoTestInverter.cxx:376
 HypoTestInverter.cxx:377
 HypoTestInverter.cxx:378
 HypoTestInverter.cxx:379
 HypoTestInverter.cxx:380
 HypoTestInverter.cxx:381
 HypoTestInverter.cxx:382
 HypoTestInverter.cxx:383
 HypoTestInverter.cxx:384
 HypoTestInverter.cxx:385
 HypoTestInverter.cxx:386
 HypoTestInverter.cxx:387