43 ClassImp(RooStats::HypoTestInverterOriginal);
45 using namespace RooStats;
50 HypoTestInverterOriginal::HypoTestInverterOriginal( ) :
62 HypoTestInverterOriginal::HypoTestInverterOriginal( HypoTestCalculator& myhc0,
63 RooRealVar& scannedVariable,
double size ) :
66 fScannedVariable(&scannedVariable),
73 SetName(
"HypoTestInverterOriginal");
76 HybridCalculatorOriginal * hc =
dynamic_cast<HybridCalculatorOriginal *
> (fCalculator0);
78 Fatal(
"HypoTestInverterOriginal",
"Using non HybridCalculatorOriginal class IS NOT SUPPORTED");
85 HypoTestInverterOriginal::~HypoTestInverterOriginal()
90 if (fResults)
delete fResults;
95 void HypoTestInverterOriginal::CreateResults() {
98 TString results_name = this->GetName();
99 results_name +=
"_results";
100 fResults =
new HypoTestInverterResult(results_name,*fScannedVariable,ConfidenceLevel());
101 fResults->SetTitle(
"HypoTestInverterOriginal Result");
103 fResults->UseCLs(fUseCLs);
108 bool HypoTestInverterOriginal::RunAutoScan(
double xMin,
double xMax,
double target,
double epsilon,
unsigned int numAlgorithm )
117 if ( xMin>=xMax || xMin< fScannedVariable->getMin() || xMax>fScannedVariable->getMax() ) {
118 std::cout <<
"Error: problem with the specified range\n";
121 if ( target<=0 || target>=1 ) {
122 std::cout <<
"Error: problem with target value\n";
125 if ( epsilon>0.5-fabs(0.5-target) ) {
126 std::cout <<
"Error: problem with error value\n";
129 if ( numAlgorithm!=0 && numAlgorithm!=1 ) {
130 std::cout <<
"Error: invalid interpolation algorithm\n";
137 if ( fabs(1-target/(1-Size()/2))<DBL_EPSILON ) {
138 fResults->fInterpolateLowerLimit =
false;
139 std::cout <<
"Target matches lower limit: de-activate interpolation in HypoTestInverterResult\n";
142 if ( fabs(1-target/((Size()/2)))<DBL_EPSILON ) {
143 fResults->fInterpolateUpperLimit =
false;
144 std::cout <<
"Target matches upper limit: de-activate interpolation in HypoTestInverterResult\n";
148 const double nSigma = 1;
151 const unsigned int nToys_backup = ((HybridCalculatorOriginal*)fCalculator0)->GetNumberOfToys();
155 if (!RunOnePoint(leftX))
return false;
156 double leftCL = fResults->GetYValue(fResults->ArraySize()-1);
157 double leftCLError = fResults->GetYError(fResults->ArraySize()-1);
159 double rightX = xMax;
160 if (!RunOnePoint(rightX))
return false;
161 double rightCL = fResults->GetYValue(fResults->ArraySize()-1);
162 double rightCLError = fResults->GetYError(fResults->ArraySize()-1);
164 if ( rightCL>target && leftCL>target ) {
165 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";
168 if ( rightCL<target && leftCL<target ) {
169 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";
173 unsigned int nIteration = 2;
174 bool quitThisLoop =
false;
177 double centerCLError = 0;
186 if (leftCL==rightCL) {
187 std::cout <<
"This cannot (and should not) happen... quit\n";
189 }
else if (leftX==rightX) {
190 std::cout <<
"This cannot (and should not) happen... quit\n";
195 if (numAlgorithm==0) {
199 if (!leftCL) leftCL = DBL_EPSILON;
200 if (!rightCL) rightCL = DBL_EPSILON;
202 double a = (log(leftCL) - log(rightCL)) / (leftX - rightX);
203 double b = leftCL / exp(a * leftX);
204 x = (log(target) - log(b)) / a;
207 if (x<xMin || x>xMax || TMath::IsNaN(x)) {
208 std::cout <<
"Extrapolated value out of range or nan: exits\n";
211 }
else if (numAlgorithm==1) {
214 double a = (leftCL-rightCL)/(leftX-rightX);
215 double b = leftCL-a*leftX;
218 if (x<xMin || x>xMax || TMath::IsNaN(x)) {
219 std::cout <<
"Extrapolated value out of range or nan: exits\n";
225 if ( x==leftX || x==rightX ) {
226 std::cout <<
"Error: exit because interpolated value equals to a previous iteration\n";
231 bool success =
false;
232 if (!quitThisLoop) success = RunOnePoint(x);
237 centerCL = fResults->GetYValue(fResults->ArraySize()-1);
238 centerCLError = fResults->GetYError(fResults->ArraySize()-1);
244 if ( (leftCL > target) == (rightCL < target) ) {
245 if ( (centerCL > target) == (leftCL > target) ) {
248 leftCLError = centerCLError;
252 rightCLError = centerCLError;
256 }
else if ( (fabs(leftCL - target) / leftCLError) >
257 (fabs(rightCL - target) / rightCLError) ) {
260 leftCLError = centerCLError;
264 rightCLError = centerCLError;
269 if ( fabs(centerCL-target) < nSigma*centerCLError && centerCLError > epsilon ) {
272 int nToys = ((HybridCalculatorOriginal*)fCalculator0)->GetNumberOfToys();
273 int nToysTarget = (int) TMath::Max(nToys*1.5, 1.2*nToys*pow(centerCLError/epsilon,2));
275 std::cout <<
"Increasing the number of toys to: " << nToysTarget << std::endl;
278 ((HybridCalculatorOriginal*)fCalculator0)->SetNumberOfToys(nToysTarget-nToys);
280 if (!RunOnePoint(x)) quitThisLoop=
true;
282 centerCL = fResults->GetYValue(fResults->ArraySize()-1);
283 centerCLError = fResults->GetYError(fResults->ArraySize()-1);
286 ((HybridCalculatorOriginal*)fCalculator0)->SetNumberOfToys(nToysTarget);
287 }
while ( fabs(centerCL-target) < nSigma*centerCLError && centerCLError > epsilon && quitThisLoop==
false );
290 if (leftCL==rightCL) {
291 std::cout <<
"Algorithm failed: left and right CL are equal (no interpolation possible or more toy-MC statistics needed)\n";
296 }
while ( ( fabs(centerCL-target) > nSigma*centerCLError || centerCLError > epsilon ) && quitThisLoop==
false );
299 ((HybridCalculatorOriginal*)fCalculator0)->SetNumberOfToys(nToys_backup);
301 if ( quitThisLoop==
true ) {
303 std::cout <<
"Aborted the search because something happened\n";
307 std::cout <<
"Converged in " << fResults->ArraySize() <<
" iterations\n";
315 bool HypoTestInverterOriginal::RunFixedScan(
int nBins,
double xMin,
double xMax )
322 std::cout <<
"Please provide nBins>0\n";
325 if ( nBins==1 && xMin!=xMax ) {
326 std::cout <<
"nBins==1 -> I will run for xMin (" << xMin <<
")\n";
328 if ( xMin==xMax && nBins>1 ) {
329 std::cout <<
"xMin==xMax -> I will enforce nBins==1\n";
333 std::cout <<
"Please provide xMin (" << xMin <<
") smaller that xMax (" << xMax <<
")\n";
337 for (
int i=0; i<nBins; i++) {
338 double thisX = xMin+i*(xMax-xMin)/(nBins-1);
339 bool status = RunOnePoint(thisX);
342 if ( status==
false ) {
343 std::cout <<
"Loop interrupted because of failed status\n";
354 bool HypoTestInverterOriginal::RunOnePoint(
double thisX )
360 if ( thisX<fScannedVariable->getMin() ) {
361 std::cout <<
"Out of range: using the lower bound on the scanned variable rather than " << thisX<<
"\n";
362 thisX = fScannedVariable->getMin();
364 if ( thisX>fScannedVariable->getMax() ) {
365 std::cout <<
"Out of range: using the upper bound on the scanned variable rather than " << thisX<<
"\n";
366 thisX = fScannedVariable->getMax();
369 double oldValue = fScannedVariable->getVal();
371 fScannedVariable->setVal(thisX);
372 std::cout <<
"Running for " << fScannedVariable->GetName() <<
" = " << thisX << endl;
375 HypoTestResult* myHybridResult = fCalculator0->GetHypoTest();
378 if ( fResults->ArraySize()!=0 ) lastXtested = fResults->GetXValue(fResults->ArraySize()-1);
379 else lastXtested = -999;
381 if ( lastXtested==thisX ) {
383 std::cout <<
"Merge with previous result\n";
384 HybridResult* latestResult = (HybridResult*) fResults->GetResult(fResults->ArraySize()-1);
385 latestResult->Add((HybridResult*)myHybridResult);
386 delete myHybridResult;
391 fResults->fXValues.push_back(thisX);
392 fResults->fYObjects.Add(myHybridResult);
396 std::cout <<
"computed: " << fResults->GetYValue(fResults->ArraySize()-1) << endl;
398 fScannedVariable->setVal(oldValue);