Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
HypoTestInverterResult.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/** \class RooStats::HypoTestInverterResult
13 \ingroup Roostats
14
15HypoTestInverterResult class holds the array of hypothesis test results and compute a confidence interval.
16Based on the RatioFinder code available in the RooStatsCms package developed by Gregory Schott and Danilo Piparo
17Ported and adapted to RooStats by Gregory Schott
18Some contributions to this class have been written by Matthias Wolf (error estimation)
19
20*/
21
22// include header file of this class
24
28#include "RooMsgService.h"
29#include "RooGlobalFunc.h"
30
31#include "TF1.h"
32#include "TGraphErrors.h"
33#include <cmath>
36#include "Math/Functor.h"
37
38#include "TCanvas.h"
39#include "TFile.h"
41
42#include <algorithm>
43
44
45using namespace RooStats;
46using namespace RooFit;
47
48// initialize static value
51
52////////////////////////////////////////////////////////////////////////////////
53/// default constructor
54
57 fUseCLs(false),
58 fIsTwoSided(false),
59 fInterpolateLowerLimit(true),
60 fInterpolateUpperLimit(true),
61 fFittedLowerLimit(false),
62 fFittedUpperLimit(false),
63 fInterpolOption(kLinear),
64 fLowerLimitError(-1),
65 fUpperLimitError(-1),
66 fCLsCleanupThreshold(0.005)
67{
70
73}
74
75////////////////////////////////////////////////////////////////////////////////
76/// copy constructor
77
80 fUseCLs(other.fUseCLs),
81 fIsTwoSided(other.fIsTwoSided),
82 fInterpolateLowerLimit(other.fInterpolateLowerLimit),
83 fInterpolateUpperLimit(other.fInterpolateUpperLimit),
84 fFittedLowerLimit(other.fFittedLowerLimit),
85 fFittedUpperLimit(other.fFittedUpperLimit),
86 fInterpolOption(other.fInterpolOption),
87 fLowerLimitError(other.fLowerLimitError),
88 fUpperLimitError(other.fUpperLimitError),
89 fCLsCleanupThreshold(other.fCLsCleanupThreshold),
90 fXValues(other.fXValues)
91{
94 int nOther = other.ArraySize();
95
96 for (int i = 0; i < nOther; ++i)
97 fYObjects.Add( other.fYObjects.At(i)->Clone() );
98 for (int i = 0; i < fExpPValues.GetSize() ; ++i)
99 fExpPValues.Add( other.fExpPValues.At(i)->Clone() );
100
103}
104
105////////////////////////////////////////////////////////////////////////////////
106
109{
110 if (&other==this) {
111 return *this ;
112 }
113
115 fLowerLimit = other.fLowerLimit;
116 fUpperLimit = other.fUpperLimit;
117 fUseCLs = other.fUseCLs;
118 fIsTwoSided = other.fIsTwoSided;
119 fInterpolateLowerLimit = other.fInterpolateLowerLimit;
120 fInterpolateUpperLimit = other.fInterpolateUpperLimit;
121 fFittedLowerLimit = other.fFittedLowerLimit;
122 fFittedUpperLimit = other.fFittedUpperLimit;
123 fInterpolOption = other.fInterpolOption;
124 fLowerLimitError = other.fLowerLimitError;
125 fUpperLimitError = other.fUpperLimitError;
126 fCLsCleanupThreshold = other.fCLsCleanupThreshold;
127
128 int nOther = other.ArraySize();
129 fXValues = other.fXValues;
130
132 for (int i=0; i < nOther; ++i) {
133 fYObjects.Add( other.fYObjects.At(i)->Clone() );
134 }
136 for (int i=0; i < fExpPValues.GetSize() ; ++i) {
137 fExpPValues.Add( other.fExpPValues.At(i)->Clone() );
138 }
139
142
143 return *this;
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// constructor
148
151 double cl ) :
152 SimpleInterval(name,scannedVariable,TMath::QuietNaN(),TMath::QuietNaN(),cl),
153 fUseCLs(false),
154 fIsTwoSided(false),
155 fInterpolateLowerLimit(true),
156 fInterpolateUpperLimit(true),
157 fFittedLowerLimit(false),
158 fFittedUpperLimit(false),
159 fInterpolOption(kLinear),
160 fLowerLimitError(-1),
161 fUpperLimitError(-1),
162 fCLsCleanupThreshold(0.005)
163{
166
167 // put a cloned copy of scanned variable to set in the interval
168 // to avoid I/O problem of the Result class -
169 // make the set owning the cloned copy (use clone instead of Clone to not copying all links)
171 fParameters.addOwned(std::unique_ptr<RooRealVar>{static_cast<RooRealVar *>(scannedVariable.clone(scannedVariable.GetName()))});
172}
173
174////////////////////////////////////////////////////////////////////////////////
175/// destructor
176
178{
179 // explicitly empty the TLists - these contain pointers, not objects
182
185}
186
187////////////////////////////////////////////////////////////////////////////////
188/// Remove problematic points from this result.
189///
190/// This function can be used to clean up a result that has failed fits, spiking CLs
191/// or similar problems. It removes
192/// - Points where CLs is not falling monotonously. These may result from a lack of numerical precision.
193/// - Points where CLs spikes to more than 0.999.
194/// - Points with very low CLs. These are not needed to run the inverter, which speeds up the process.
195/// - Points where CLs < 0. These occur when fits fail.
197{
198 const int nEntries = ArraySize();
199
200 // initialization
201 double nsig1(1.0);
202 double nsig2(2.0);
203 double p[5];
204 double q[5];
205
208 p[2] = 0.5;
211
212 bool resultIsAsymptotic(false);
213 if (nEntries>=1) {
214 HypoTestResult* r = dynamic_cast<HypoTestResult *> ( GetResult(0) );
215 assert(r!=nullptr);
216 if ( !r->GetNullDistribution() && !r->GetAltDistribution() ) {
217 resultIsAsymptotic = true;
218 }
219 }
220
221 int nPointsRemoved(0);
222
223 double CLsobsprev(1.0);
224
225 for (auto itr = fXValues.begin(); itr != fXValues.end(); ++itr) {
226 const double x = *itr;
227 const int i = FindIndex(x);
228
230 if (!s) break;
231
232 /////////////////////////////////////////////////////////////////////////////////////////
233
234 const std::vector<double> & values = s->GetSamplingDistribution();
235 if ((int) values.size() != fgAsymptoticNumPoints) {
236 coutE(Eval) << "HypoTestInverterResult::ExclusionCleanup - invalid size of sampling distribution" << std::endl;
237 delete s;
238 break;
239 }
240
241 /// expected p-values
242 // special case for asymptotic results (cannot use TMath::quantile in that case)
243 if (resultIsAsymptotic) {
245 double dsig = 2.*maxSigma / (values.size() -1) ;
246 int i0 = (int) TMath::Floor ( ( -nsig2 + maxSigma )/dsig + 0.5 );
247 int i1 = (int) TMath::Floor ( ( -nsig1 + maxSigma )/dsig + 0.5 );
248 int i2 = (int) TMath::Floor ( ( maxSigma )/dsig + 0.5 );
249 int i3 = (int) TMath::Floor ( ( nsig1 + maxSigma )/dsig + 0.5 );
250 int i4 = (int) TMath::Floor ( ( nsig2 + maxSigma )/dsig + 0.5 );
251 //
252 q[0] = values[i0];
253 q[1] = values[i1];
254 q[2] = values[i2];
255 q[3] = values[i3];
256 q[4] = values[i4];
257 } else {
258 double * z = const_cast<double *>(&values[0] ); // need to change TMath::Quantiles
259 TMath::Quantiles(values.size(), 5, z, q, p, false);
260 }
261
262 delete s;
263
264 const double CLsobs = CLs(i);
265
266 /////////////////////////////////////////////////////////////////////////////////////////
267
268 bool removeThisPoint(false);
269
270 // 1. CLs should drop, else skip this point
271 if (resultIsAsymptotic && i>=1 && CLsobs>CLsobsprev) {
272 removeThisPoint = true;
273 } else if (CLsobs >= 0.) {
275 }
276
277 // 2. CLs should not spike, else skip this point
278 removeThisPoint |= i>=1 && CLsobs >= 0.9999;
279
280 // 3. Not interested in CLs values that become too low.
281 removeThisPoint |= i>=1 && q[4] < fCLsCleanupThreshold;
282
283 // 4. Negative CLs indicate failed fits
284 removeThisPoint |= CLsobs < 0.;
285
286 // to remove or not to remove
287 if (removeThisPoint) {
288 itr = fXValues.erase(itr)--;
292 continue;
293 } else { // keep
295 }
296 }
297
298 // after cleanup, reset existing limits
299 fFittedUpperLimit = false;
300 fFittedLowerLimit = false;
302
303 return nPointsRemoved;
304}
305
306////////////////////////////////////////////////////////////////////////////////
307/// Merge this HypoTestInverterResult with another
308/// HypoTestInverterResult passed as argument
309/// The merge is done by combining the HypoTestResult when the same point value exist in both results.
310/// If results exist at different points these are added in the new result
311/// NOTE: Merging of the expected p-values obtained with pseudo-data.
312/// When expected p-values exist in the result (i.e. when rebuild option is used when getting the expected
313/// limit distribution in the HYpoTestInverter) then the expected p-values are also merged. This is equivalent
314/// at merging the pseudo-data. However there can be an inconsistency if the expected p-values have been
315/// obtained with different toys. In this case the merge is done but a warning message is printed.
316
318{
319 int nThis = ArraySize();
320 int nOther = otherResult.ArraySize();
321 if (nOther == 0) return true;
322 if (nOther != otherResult.fYObjects.GetSize() ) return false;
323 if (nThis != fYObjects.GetSize() ) return false;
324
325 // cannot merge in case of inconsistent members
326 if (fExpPValues.GetSize() > 0 && fExpPValues.GetSize() != nThis ) return false;
327 if (otherResult.fExpPValues.GetSize() > 0 && otherResult.fExpPValues.GetSize() != nOther ) return false;
328
329 coutI(Eval) << "HypoTestInverterResult::Add - merging result from " << otherResult.GetName()
330 << " in " << GetName() << std::endl;
331
332 bool addExpPValues = (fExpPValues.GetSize() == 0 && otherResult.fExpPValues.GetSize() > 0);
333 bool mergeExpPValues = (fExpPValues.GetSize() > 0 && otherResult.fExpPValues.GetSize() > 0);
334
336 coutI(Eval) << "HypoTestInverterResult::Add - merging also the expected p-values from pseudo-data" << std::endl;
337
338
339 // case current result is empty
340 // just make a simple copy of the other result
341 if (nThis == 0) {
342 fXValues = otherResult.fXValues;
343 for (int i = 0; i < nOther; ++i)
344 fYObjects.Add( otherResult.fYObjects.At(i)->Clone() );
345 for (int i = 0; i < fExpPValues.GetSize() ; ++i)
346 fExpPValues.Add( otherResult.fExpPValues.At(i)->Clone() );
347 }
348 // now do the real merge combining point with same value or adding extra ones
349 else {
350 for (int i = 0; i < nOther; ++i) {
351 double otherVal = otherResult.fXValues[i];
352 HypoTestResult * otherHTR = static_cast<HypoTestResult*>(otherResult.fYObjects.At(i));
353 if (otherHTR == nullptr) continue;
354 bool sameXFound = false;
355 for (int j = 0; j < nThis; ++j) {
356 double thisVal = fXValues[j];
357
358 // if same value merge the result
359 if ( (std::abs(otherVal) < 1 && TMath::AreEqualAbs(otherVal, thisVal,1.E-12) ) ||
360 (std::abs(otherVal) >= 1 && TMath::AreEqualRel(otherVal, thisVal,1.E-12) ) ) {
362 thisHTR->Append(otherHTR);
363 sameXFound = true;
364 if (mergeExpPValues) {
365 (static_cast<SamplingDistribution*>(fExpPValues.At(j)))->Add( static_cast<SamplingDistribution*>(otherResult.fExpPValues.At(i)) );
366 // check if same toys have been used for the test statistic distribution
367 int thisNToys = (thisHTR->GetNullDistribution() ) ? thisHTR->GetNullDistribution()->GetSize() : 0;
368 int otherNToys = (otherHTR->GetNullDistribution() ) ? otherHTR->GetNullDistribution()->GetSize() : 0;
369 if (thisNToys != otherNToys )
370 coutW(Eval) << "HypoTestInverterResult::Add expected p values have been generated with different toys " << thisNToys << " , " << otherNToys << std::endl;
371 }
372 break;
373 }
374 }
375 if (!sameXFound) {
376 // add the new result
377 fYObjects.Add(otherHTR->Clone() );
378 fXValues.push_back( otherVal);
379 }
380 // add in any case also when same x found
381 if (addExpPValues)
382 fExpPValues.Add( otherResult.fExpPValues.At(i)->Clone() );
383
384
385 }
386 }
387
388 if (ArraySize() > nThis) {
389 coutI(Eval) << "HypoTestInverterResult::Add - new number of points is " << fXValues.size()
390 << std::endl;
391 } else {
392 coutI(Eval) << "HypoTestInverterResult::Add - new toys/point is "
393 << (static_cast<HypoTestResult *>(fYObjects.At(0)))->GetNullDistribution()->GetSize() << std::endl;
394 }
395
396 // reset cached limit values
399
400 return true;
401}
402
403////////////////////////////////////////////////////////////////////////////////
404/// Add a single point result (an HypoTestResult)
405
407{
408 int i= FindIndex(x);
409 if (i<0) {
410 fXValues.push_back(x);
411 fYObjects.Add(res.Clone());
412 } else {
414 if (!r) return false;
415 r->Append(&res);
416 }
417
418 // reset cached limit values
421
422 return true;
423}
424
425////////////////////////////////////////////////////////////////////////////////
426/// function to return the value of the parameter of interest for the i^th entry in the results
427
429{
430 if ( index >= ArraySize() || index<0 ) {
431 coutE(InputArguments) << "Problem: You are asking for an impossible array index value\n";
432 return -999;
433 }
434
435 return fXValues[index];
436}
437
438////////////////////////////////////////////////////////////////////////////////
439/// function to return the value of the confidence level for the i^th entry in the results
440
442{
443 auto result = GetResult(index);
444 if ( !result ) {
445 return -999;
446 }
447
448 if (fUseCLs) {
449 return result->CLs();
450 } else {
451 return result->CLsplusb(); // CLs+b
452 }
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// function to return the estimated error on the value of the confidence level for the i^th entry in the results
457
459{
460 auto result = GetResult(index);
461 if ( !result ) {
462 return -999;
463 }
464
465 if (fUseCLs) {
466 return result->CLsError();
467 } else {
468 return result->CLsplusbError();
469 }
470}
471
472////////////////////////////////////////////////////////////////////////////////
473/// function to return the observed CLb value for the i-th entry
474
476{
477 auto result = GetResult(index);
478 if ( !result ) {
479 return -999;
480 }
481 return result->CLb();
482}
483
484////////////////////////////////////////////////////////////////////////////////
485/// function to return the observed CLs+b value for the i-th entry
486
488{
489 auto result = GetResult(index);
490 if ( !result) {
491 return -999;
492 }
493 return result->CLsplusb();
494}
495
496////////////////////////////////////////////////////////////////////////////////
497/// function to return the observed CLs value for the i-th entry
498
500{
501 auto result = GetResult(index);
502 if ( !result ) {
503 return -999;
504 }
505 return result->CLs();
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// function to return the error on the observed CLb value for the i-th entry
510
512{
513 auto result = GetResult(index);
514 if ( !result ) {
515 return -999;
516 }
517 return result->CLbError();
518}
519
520////////////////////////////////////////////////////////////////////////////////
521/// function to return the error on the observed CLs+b value for the i-th entry
522
524{
525 auto result = GetResult(index);
526 if ( ! result ) {
527 return -999;
528 }
529 return result->CLsplusbError();
530}
531
532////////////////////////////////////////////////////////////////////////////////
533/// function to return the error on the observed CLs value for the i-th entry
534
536{
537 auto result = GetResult(index);
538 if ( ! result ){
539 return -999;
540 }
541 return result->CLsError();
542}
543
544////////////////////////////////////////////////////////////////////////////////
545/// get the HypoTestResult object at the given index point
546
548{
549 if ( index >= ArraySize() || index<0 ) {
550 coutE(InputArguments) << "Problem: You are asking for an impossible array index value\n";
551 return nullptr;
552 }
553
554 return (static_cast<HypoTestResult*>(fYObjects.At(index)));
555}
556
557////////////////////////////////////////////////////////////////////////////////
558/// find the index corresponding at the poi value xvalue
559/// If no points is found return -1
560/// Note that a tolerance is used of 10^-12 to find the closest point
561
563{
564 const double tol = 1.E-12;
565 for (int i=0; i<ArraySize(); i++) {
566 double xpoint = fXValues[i];
567 if ( (std::abs(xvalue) > 1 && TMath::AreEqualRel( xvalue, xpoint, tol) ) ||
568 (std::abs(xvalue) <= 1 && TMath::AreEqualAbs( xvalue, xpoint, tol) ) )
569 return i;
570 }
571 return -1;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// return the X value of the given graph for the target value y0
576/// the graph is evaluated using linear interpolation by default.
577/// if option = "S" a TSpline3 is used
578
579double HypoTestInverterResult::GetGraphX(const TGraph & graph, double y0, bool lowSearch, double &axmin, double &axmax) const {
580
581//#define DO_DEBUG
582#ifdef DO_DEBUG
583 std::cout << "using graph for search " << lowSearch << " min " << axmin << " max " << axmax << std::endl;
584#endif
585
586
587 // find reasonable xmin and xmax if not given
588 const double * y = graph.GetY();
589 int n = graph.GetN();
590 if (n < 2) {
591 ooccoutE(this,Eval) << "HypoTestInverterResult::GetGraphX - need at least 2 points for interpolation (n=" << n << ")\n";
592 return (n>0) ? y[0] : 0;
593 }
594
595 double varmin = - TMath::Infinity();
596 double varmax = TMath::Infinity();
597 const RooRealVar* var = dynamic_cast<RooRealVar*>(fParameters.first() );
598 if (var) {
599 varmin = var->getMin();
600 varmax = var->getMax();
601 }
602
603
604 // find ymin and ymax and corresponding values
605 double ymin = TMath::MinElement(n,y);
606 double ymax = TMath::MaxElement(n,y);
607 // cannot find intercept in the full range - return min or max valie
608 if (ymax < y0) {
609 return (lowSearch) ? varmax : varmin;
610 }
611 if (ymin > y0) {
612 return (lowSearch) ? varmin : varmax;
613 }
614
615 double xmin = axmin;
616 double xmax = axmax;
617
618 // case no range is given check if need to extrapolate to lower/upper values
619 if (axmin >= axmax ) {
620
621#ifdef DO_DEBUG
622 std::cout << "No range given - check if extrapolation is needed " << std::endl;
623#endif
624
625 xmin = graph.GetX()[0];
626 xmax = graph.GetX()[n-1];
627
628 double yfirst = graph.GetY()[0];
629 double ylast = graph.GetY()[n-1];
630
631 // distinguish the case we have lower /upper limits
632 // check if a possible crossing exists otherwise return variable min/max
633
634 // do lower extrapolation
635 if ( (ymax < y0 && !lowSearch) || ( yfirst > y0 && lowSearch) ) {
636 xmin = varmin;
637 }
638 // do upper extrapolation
639 if ( (ymax < y0 && lowSearch) || ( ylast > y0 && !lowSearch) ) {
640 xmax = varmax;
641 }
642 }
643
644 auto func = [&](double x) {
645 return (fInterpolOption == kSpline) ? graph.Eval(x, nullptr, "S") - y0 : graph.Eval(x) - y0;
646 };
648
650 brf.SetFunction(f1d,xmin,xmax);
651 brf.SetNpx(std::max(graph.GetN()*2,100) );
652#ifdef DO_DEBUG
653 std::cout << "findind root for " << xmin << " , "<< xmax << "f(x) : " << graph.Eval(xmin) << " , " << graph.Eval(0.5*(xmax+xmin))
654 << " , " << graph.Eval(xmax) << " target " << y0 << std::endl;
655#endif
656
657 bool ret = brf.Solve(100, 1.E-16, 1.E-6);
658 if (!ret) {
659 ooccoutE(this,Eval) << "HypoTestInverterResult - interpolation failed for interval [" << xmin << "," << xmax
660 << " ] g(xmin,xmax) =" << graph.Eval(xmin) << "," << graph.Eval(xmax)
661 << " target=" << y0 << " return inf" << std::endl
662 << "One may try to clean up invalid points using HypoTestInverterResult::ExclusionCleanup()." << std::endl;
663 return TMath::Infinity();
664 }
665 double limit = brf.Root();
666
667#ifdef DO_DEBUG
668 if (lowSearch) std::cout << "lower limit search : ";
669 else std::cout << "Upper limit search : ";
670 std::cout << "interpolation done between " << xmin << " and " << xmax
671 << "\n Found limit using RootFinder is " << limit << std::endl;
672
673 TString fname = "graph_upper.root";
674 if (lowSearch) fname = "graph_lower.root";
675 {
676 std::unique_ptr<TFile> file{TFile::Open(fname,"RECREATE")};
677 graph.Write("graph");
678 }
679#endif
680
681 // look in case if a new intersection exists
682 // only when boundaries are not given
683 if (axmin >= axmax) {
684 int index = TMath::BinarySearch(n, graph.GetX(), limit);
685#ifdef DO_DEBUG
686 std::cout << "do new interpolation dividing from " << index << " and " << y[index] << std::endl;
687#endif
688
689 if (lowSearch && index >= 1 && (y[0] - y0) * ( y[index]- y0) < 0) {
690 //search if another intersection exists at a lower value
691 limit = GetGraphX(graph, y0, lowSearch, graph.GetX()[0], graph.GetX()[index] );
692 }
693 else if (!lowSearch && index < n-2 && (y[n-1] - y0) * ( y[index+1]- y0) < 0) {
694 // another intersection exists at an higher value
695 limit = GetGraphX(graph, y0, lowSearch, graph.GetX()[index+1], graph.GetX()[n-1] );
696 }
697 }
698 // return also xmin, xmax values
699 axmin = xmin;
700 axmax = xmax;
701
702 return limit;
703}
704
705////////////////////////////////////////////////////////////////////////////////
706/// interpolate to find a limit value
707/// Use a linear or a spline interpolation depending on the interpolation option
708
710{
711
712 // variable minimum and maximum
713 double varmin = - TMath::Infinity();
714 double varmax = TMath::Infinity();
715 const RooRealVar* var = dynamic_cast<RooRealVar*>(fParameters.first() );
716 if (var) {
717 varmin = var->getMin();
718 varmax = var->getMax();
719 }
720
721 if (ArraySize()<2) {
722 double val = (lowSearch) ? xmin : xmax;
723 coutW(Eval) << "HypoTestInverterResult::FindInterpolatedLimit"
724 << " - not enough points to get the inverted interval - return "
725 << val << std::endl;
728 return (lowSearch) ? fLowerLimit : fUpperLimit;
729 }
730
731 // sort the values in x
732 int n = ArraySize();
733 std::vector<unsigned int> index(n );
734 TMath::SortItr(fXValues.begin(), fXValues.end(), index.begin(), false);
735 // make a graph with the sorted point
736 TGraph graph(n);
737 for (int i = 0; i < n; ++i)
738 graph.SetPoint(i, GetXValue(index[i]), GetYValue(index[i] ) );
739
740
741 //std::cout << " search for " << lowSearch << " xmin = " << xmin << " xmax " << xmax << std::endl;
742
743
744 // search first for min/max in the given range
745 if (xmin >= xmax) {
746
747
748 // search for maximum between the point
749 double * itrmax = std::max_element(graph.GetY() , graph.GetY() +n);
750 double ymax = *itrmax;
751 int iymax = itrmax - graph.GetY();
752 double xwithymax = graph.GetX()[iymax];
753
754#ifdef DO_DEBUG
755 std::cout << " max of y " << iymax << " " << xwithymax << " " << ymax << " target is " << target << std::endl;
756#endif
757 // look if maximum is above/below target
758 if (ymax > target) {
759 if (lowSearch) {
760 if ( iymax > 0) {
761 // low search (minimum is first point or minimum range)
762 xmin = ( graph.GetY()[0] <= target ) ? graph.GetX()[0] : varmin;
763 xmax = xwithymax;
764 }
765 else {
766 // no room for lower limit
768 return fLowerLimit;
769 }
770 }
771 if (!lowSearch ) {
772 // up search
773 if ( iymax < n-1 ) {
774 xmin = xwithymax;
775 xmax = ( graph.GetY()[n-1] <= target ) ? graph.GetX()[n-1] : varmax;
776 }
777 else {
778 // no room for upper limit
780 return fUpperLimit;
781 }
782 }
783 }
784 else {
785 // in case is below the target
786 // find out if is a lower or upper search
787 if (iymax <= (n-1)/2 ) {
788 lowSearch = false;
790 }
791 else {
792 lowSearch = true;
794 }
795 }
796
797#ifdef DO_DEBUG
798 std::cout << " found xmin, xmax = " << xmin << " " << xmax << " for search " << lowSearch << std::endl;
799#endif
800
801 // now come here if I have already found a lower/upper limit
802 // i.e. I am calling routine for the second time
803#ifdef ISNEEDED
804 // should not really come here
805 if (lowSearch && fUpperLimit < varmax) {
806 xmin = fXValues[ index.front() ];
807 // find xmax (is first point before upper limit)
809 if (upI < 1) return xmin;
810 xmax = GetXValue(upI);
811 }
812 else if (!lowSearch && fLowerLimit > varmin ) {
813 // find xmin (is first point after lower limit)
815 if (lowI >= n-1) return xmax;
817 xmax = fXValues[ index.back() ];
818 }
819#endif
820 }
821
822#ifdef DO_DEBUG
823 std::cout << "finding " << lowSearch << " limit between " << xmin << " " << xmax << std::endl;
824#endif
825
826 // compute now the limit using the TGraph interpolations routine
827 double limit = GetGraphX(graph, target, lowSearch, xmin, xmax);
828 if (lowSearch) fLowerLimit = limit;
829 else fUpperLimit = limit;
830 // estimate the error
832
833 TString limitType = (lowSearch) ? "lower" : "upper";
834 ooccoutD(this,Eval) << "HypoTestInverterResult::FindInterpolateLimit "
835 << "the computed " << limitType << " limit is " << limit << " +/- " << error << std::endl;
836
837#ifdef DO_DEBUG
838 std::cout << "Found limit is " << limit << " +/- " << error << std::endl;
839#endif
840
841
842 if (lowSearch) return fLowerLimit;
843 return fUpperLimit;
844
845
846// if (lowSearch && !TMath::IsNaN(fUpperLimit)) return fLowerLimit;
847// if (!lowSearch && !TMath::IsNaN(fLowerLimit)) return fUpperLimit;
848// // is this needed ?
849// // we call again the function for the upper limits
850
851// // now perform the opposite search on the complement interval
852// if (lowSearch) {
853// xmin = xmax;
854// xmax = varmax;
855// } else {
856// xmax = xmin;
857// xmin = varmin;
858// }
859// double limit2 = GetGraphX(graph, target, !lowSearch, xmin, xmax);
860// if (!lowSearch) fLowerLimit = limit2;
861// else fUpperLimit = limit2;
862
863// CalculateEstimatedError( target, !lowSearch, xmin, xmax);
864
865// #ifdef DO_DEBUG
866// std::cout << "other limit is " << limit2 << std::endl;
867// #endif
868
869// return (lowSearch) ? fLowerLimit : fUpperLimit;
870
871}
872
873////////////////////////////////////////////////////////////////////////////////
874/// - if mode = 0
875/// find closest point to target in Y, the object closest to the target which is 3 sigma from the target
876/// and has smaller error
877/// - if mode = 1
878/// find 2 closest point to target in X and between these two take the one closer to the target
879/// - if mode = 2 as in mode = 1 but return the lower point not the closest one
880/// - if mode = 3 as in mode = 1 but return the upper point not the closest one
881
883{
884
885 int bestIndex = -1;
886 int closestIndex = -1;
887 if (mode == 0) {
888 double smallestError = 2; // error must be < 1
889 double bestValue = 2;
890 for (int i=0; i<ArraySize(); i++) {
891 double dist = std::abs(GetYValue(i)-target);
892 if ( dist <3 *GetYError(i) ) { // less than 1 sigma from target CL
893 if (GetYError(i) < smallestError ) {
895 bestIndex = i;
896 }
897 }
898 if ( dist < bestValue) {
899 bestValue = dist;
900 closestIndex = i;
901 }
902 }
903 if (bestIndex >=0) return bestIndex;
904 // if no points found just return the closest one to the target
905 return closestIndex;
906 }
907 // else mode = 1,2,3
908 // find the two closest points to limit value
909 // sort the array first
910 int n = fXValues.size();
911 std::vector<unsigned int> indx(n);
912 TMath::SortItr(fXValues.begin(), fXValues.end(), indx.begin(), false);
913 std::vector<double> xsorted( n);
914 for (int i = 0; i < n; ++i) xsorted[i] = fXValues[indx[i] ];
916
917#ifdef DO_DEBUG
918 std::cout << "finding closest point to " << xtarget << " is " << index1 << " " << indx[index1] << std::endl;
919#endif
920
921 // case xtarget is outside the range (before or afterwards)
922 if (index1 < 0) return indx[0];
923 if (index1 >= n-1) return indx[n-1];
924 int index2 = index1 +1;
925
926 if (mode == 2) return (GetXValue(indx[index1]) < GetXValue(indx[index2])) ? indx[index1] : indx[index2];
927 if (mode == 3) return (GetXValue(indx[index1]) > GetXValue(indx[index2])) ? indx[index1] : indx[index2];
928 // get smaller point of the two (mode == 1)
929 if (std::abs(GetYValue(indx[index1])-target) <= std::abs(GetYValue(indx[index2])-target) )
930 return indx[index1];
931 return indx[index2];
932
933}
934
935////////////////////////////////////////////////////////////////////////////////
936
938{
939 if (fFittedLowerLimit) return fLowerLimit;
940 //std::cout << "finding point with cl = " << 1-(1-ConfidenceLevel())/2 << std::endl;
942 // find both lower/upper limit
944 } else {
945 //LM: I think this is never called
947 }
948 return fLowerLimit;
949}
950
951////////////////////////////////////////////////////////////////////////////////
952
954{
955 //std::cout << "finding point with cl = " << (1-ConfidenceLevel())/2 << std::endl;
956 if (fFittedUpperLimit) return fUpperLimit;
959 } else {
960 //LM: I think this is never called
962 }
963 return fUpperLimit;
964}
965
966////////////////////////////////////////////////////////////////////////////////
967/// Return an error estimate on the upper(lower) limit. This is the error on
968/// either CLs or CLsplusb divided by an estimate of the slope at this
969/// point.
970
972{
973
974 if (ArraySize()==0) {
975 coutW(Eval) << "HypoTestInverterResult::CalculateEstimateError"
976 << "Empty result \n";
977 return 0;
978 }
979
980 if (ArraySize()<2) {
981 coutW(Eval) << "HypoTestInverterResult::CalculateEstimateError"
982 << " only points - return its error\n";
983 return GetYError(0);
984 }
985
986 // it does not make sense in case of asymptotic which do not have point errors
987 if (!GetNullTestStatDist(0) ) return 0;
988
989 TString type = (!lower) ? "upper" : "lower";
990
991#ifdef DO_DEBUG
992 std::cout << "calculate estimate error " << type << " between " << xmin << " and " << xmax << std::endl;
993 std::cout << "computed limit is " << ( (lower) ? fLowerLimit : fUpperLimit ) << std::endl;
994#endif
995
996 // make a TGraph Errors with the sorted points
997 std::vector<unsigned int> indx(fXValues.size());
998 TMath::SortItr(fXValues.begin(), fXValues.end(), indx.begin(), false);
999 // make a graph with the sorted point
1000 TGraphErrors graph;
1001 int ip = 0;
1002 int np = 0;
1003 for (int i = 0; i < ArraySize(); ++i) {
1004 if ( (xmin < xmax) && ( GetXValue(indx[i]) >= xmin && GetXValue(indx[i]) <= xmax) ) {
1005 np++;
1006 // exclude points with zero or very small errors
1007 if (GetYError(indx[i] ) > 1.E-6) {
1008 graph.SetPoint(ip, GetXValue(indx[i]), GetYValue(indx[i] ) );
1009 graph.SetPointError(ip, 0., GetYError(indx[i]) );
1010 ip++;
1011 }
1012 }
1013 }
1014 if (graph.GetN() < 2) {
1015 if (np >= 2) coutW(Eval) << "HypoTestInverterResult::CalculateEstimatedError - no valid points - cannot estimate the " << type << " limit error " << std::endl;
1016 return 0;
1017 }
1018
1019 double minX = xmin;
1020 double maxX = xmax;
1021 if (xmin >= xmax) {
1022 minX = fXValues[ indx.front() ];
1023 maxX = fXValues[ indx.back() ];
1024 }
1025
1026 TF1 fct("fct", "exp([0] * (x - [2] ) + [1] * (x-[2])**2)", minX, maxX);
1027 double scale = maxX-minX;
1028 if (lower) {
1029 fct.SetParameters( 2./scale, 0.1/scale, graph.GetX()[0] );
1030 fct.SetParLimits(0,0,100./scale);
1031 fct.SetParLimits(1,0, 10./scale); }
1032 else {
1033 fct.SetParameters( -2./scale, -0.1/scale );
1034 fct.SetParLimits(0,-100./scale, 0);
1035 fct.SetParLimits(1,-100./scale, 0); }
1036
1037 if (graph.GetN() < 3) fct.FixParameter(1,0.);
1038
1039 // find the point closest to the limit
1040 double limit = (!lower) ? fUpperLimit : fLowerLimit;
1041 if (TMath::IsNaN(limit)) return 0; // cannot do if limit not computed
1042
1043
1044#ifdef DO_DEBUG
1045 TCanvas * c1 = new TCanvas();
1046 std::cout << "fitting for limit " << type << "between " << minX << " , " << maxX << " points considered " << graph.GetN() << std::endl;
1047 int fitstat = graph.Fit(&fct," EX0");
1048 graph.SetMarkerStyle(20);
1049 graph.Draw("AP");
1050 graph.Print();
1051 c1->SaveAs(TString::Format("graphFit_%s.pdf",type.Data()) );
1052 delete c1;
1053#else
1054 int fitstat = graph.Fit(&fct,"Q EX0");
1055#endif
1056
1057 int index = FindClosestPointIndex(target, 1, limit);
1058 double theError = 0;
1059 if (fitstat == 0) {
1060 double errY = GetYError(index);
1061 if (errY > 0) {
1062 double m = fct.Derivative( GetXValue(index) );
1063 theError = std::min(std::abs( GetYError(index) / m), maxX-minX);
1064 }
1065 }
1066 else {
1067 coutW(Eval) << "HypoTestInverterResult::CalculateEstimatedError - cannot estimate the " << type << " limit error " << std::endl;
1068 theError = 0;
1069 }
1070 if (lower) {
1072 } else {
1074 }
1075
1076#ifdef DO_DEBUG
1077 std::cout << "closes point to the limit is " << index << " " << GetXValue(index) << " and has error " << GetYError(index) << std::endl;
1078#endif
1079
1080 return theError;
1081}
1082
1083////////////////////////////////////////////////////////////////////////////////
1084/// need to have compute first lower limit
1085
1087{
1089 if (fLowerLimitError >= 0) return fLowerLimitError;
1090 // try to recompute the error
1091 return CalculateEstimatedError(1-ConfidenceLevel(), true);
1092}
1093
1094////////////////////////////////////////////////////////////////////////////////
1095
1097{
1099 if (fUpperLimitError >= 0) return fUpperLimitError;
1100 // try to recompute the error
1101 return CalculateEstimatedError(1-ConfidenceLevel(), false);
1102}
1103
1104////////////////////////////////////////////////////////////////////////////////
1105/// get the background test statistic distribution
1106
1108
1110 if (!firstResult) return nullptr;
1111 return firstResult->GetBackGroundIsAlt() ? firstResult->GetAltDistribution() : firstResult->GetNullDistribution();
1112}
1113
1114////////////////////////////////////////////////////////////////////////////////
1115/// get the signal and background test statistic distribution
1116
1119 if (!result) return nullptr;
1120 return !result->GetBackGroundIsAlt() ? result->GetAltDistribution() : result->GetNullDistribution();
1121}
1122
1123////////////////////////////////////////////////////////////////////////////////
1124/// get the expected p-value distribution at the scanned point index
1125
1127
1128 if (index < 0 || index >= ArraySize() ) return nullptr;
1129
1130 if (fExpPValues.GetSize() == ArraySize() ) {
1131 return static_cast<SamplingDistribution*>( fExpPValues.At(index)->Clone());
1132 }
1133
1134 static bool useFirstB = false;
1135 // get the S+B distribution
1136 int bIndex = (useFirstB) ? 0 : index;
1137
1140
1142
1144
1145 // create a new HypoTestResult
1147 tempResult.SetPValueIsRightTail( result->GetPValueIsRightTail() );
1148 tempResult.SetBackgroundAsAlt( true);
1149 // ownership of SamplingDistribution is in HypoTestResult class now
1150 tempResult.SetNullDistribution( new SamplingDistribution(*sbDistribution) );
1151 tempResult.SetAltDistribution( new SamplingDistribution(*bDistribution ) );
1152
1153 std::vector<double> values(bDistribution->GetSize());
1154 for (int i = 0; i < bDistribution->GetSize(); ++i) {
1155 tempResult.SetTestStatisticData( bDistribution->GetSamplingDistribution()[i] );
1156 values[i] = (fUseCLs) ? tempResult.CLs() : tempResult.CLsplusb();
1157 }
1158 return new SamplingDistribution("expected values","expected values",values);
1159 }
1160 // in case b abs sbDistribution are null assume is coming from the asymptotic calculator
1161 // hard -coded this value (no really needed to be used by user)
1164 const double smax = fgAsymptoticMaxSigma;
1165 const int npoints = fgAsymptoticNumPoints;
1166 const double dsig = 2* smax/ (npoints-1) ;
1167 std::vector<double> values(npoints);
1168 for (int i = 0; i < npoints; ++i) {
1169 double nsig = -smax + dsig*i;
1170 double pval = AsymptoticCalculator::GetExpectedPValues( result->NullPValue(), result->AlternatePValue(), nsig, fUseCLs, !fIsTwoSided);
1171 if (pval < 0) { return nullptr;}
1172 values[i] = pval;
1173 }
1174 return new SamplingDistribution("Asymptotic expected values","Asymptotic expected values",values);
1175
1176}
1177
1178////////////////////////////////////////////////////////////////////////////////
1179/// get the limit distribution (lower/upper depending on the flag)
1180/// by interpolating the expected p values for each point
1181
1183 if (ArraySize()<2) {
1184 coutE(Eval) << "HypoTestInverterResult::GetLimitDistribution"
1185 << " not enough points - return 0 " << std::endl;
1186 return nullptr;
1187 }
1188
1189 ooccoutD(this,Eval) << "HypoTestInverterResult - computing limit distribution...." << std::endl;
1190
1191
1192 // find optimal size by looking at the PValue distribution obtained
1193 int npoints = ArraySize();
1194 std::vector<SamplingDistribution*> distVec( npoints );
1195 double sum = 0;
1196 for (unsigned int i = 0; i < distVec.size(); ++i) {
1198 // sort the distributions
1199 // hack (by calling InverseCDF(0) will sort the sampling distribution
1200 if (distVec[i] ) {
1201 distVec[i]->InverseCDF(0);
1202 sum += distVec[i]->GetSize();
1203 }
1204 }
1205 int size = int( sum/ npoints);
1206
1207 if (size < 10) {
1208 ooccoutW(this,InputArguments) << "HypoTestInverterResult - set a minimum size of 10 for limit distribution" << std::endl;
1209 size = 10;
1210 }
1211
1212
1213 double target = 1-fConfidenceLevel;
1214
1215 // vector with the quantiles of the p-values for each scanned poi point
1216 std::vector< std::vector<double> > quantVec(npoints );
1217 for (int i = 0; i < npoints; ++i) {
1218
1219 if (!distVec[i]) continue;
1220
1221 // make quantiles from the sampling distributions of the expected p values
1222 std::vector<double> pvalues = distVec[i]->GetSamplingDistribution();
1223 delete distVec[i]; distVec[i] = nullptr;
1224 std::sort(pvalues.begin(), pvalues.end());
1225 // find the quantiles of the distribution
1226 double p[1] = {0};
1227 double q[1] = {0};
1228
1229 quantVec[i] = std::vector<double>(size);
1230 for (int ibin = 0; ibin < size; ++ibin) {
1231 // exclude for a bug in TMath::Quantiles last item
1232 p[0] = std::min( (ibin+1) * 1./double(size), 1.0);
1233 // use the type 1 which give the point value
1234 TMath::Quantiles(pvalues.size(), 1, &pvalues[0], q, p, true, nullptr, 1 );
1235 (quantVec[i])[ibin] = q[0];
1236 }
1237
1238 }
1239
1240 // sort the values in x
1241 std::vector<unsigned int> index( npoints );
1242 TMath::SortItr(fXValues.begin(), fXValues.end(), index.begin(), false);
1243
1244 // SamplingDistribution * dist0 = distVec[index[0]];
1245 // SamplingDistribution * dist1 = distVec[index[1]];
1246
1247
1248 std::vector<double> limits(size);
1249 // loop on the p values and find the limit for each expected point in the quantiles vector
1250 for (int j = 0; j < size; ++j ) {
1251
1252 TGraph g;
1253 for (int k = 0; k < npoints ; ++k) {
1254 if (!quantVec[index[k]].empty() )
1255 g.SetPoint(g.GetN(), GetXValue(index[k]), (quantVec[index[k]])[j] );
1256 }
1257
1258 limits[j] = GetGraphX(g, target, lower);
1259
1260 }
1261
1262 if (lower) {
1263 return new SamplingDistribution("Expected lower Limit","Expected lower limits",limits);
1264 } else {
1265 return new SamplingDistribution("Expected upper Limit", "Expected upper limits", limits);
1266 }
1267}
1268
1269////////////////////////////////////////////////////////////////////////////////
1270/// Get the expected lower limit
1271/// nsig is used to specify which expected value of the UpperLimitDistribution
1272/// For example
1273/// - nsig = 0 (default value) returns the expected value
1274/// - nsig = -1 returns the lower band value at -1 sigma
1275/// - nsig + 1 return the upper value
1276/// - opt = "" (default) : compute limit by interpolating all the p values, find the corresponding limit distribution
1277/// and then find the quantiles in the limit distribution
1278/// ioption = "P" is the method used for plotting. One Finds the corresponding nsig quantile in the p values and then
1279/// interpolates them
1280
1281double HypoTestInverterResult::GetExpectedLowerLimit(double nsig, const char * opt ) const {
1282
1283 return GetExpectedLimit(nsig, true, opt);
1284}
1285
1286////////////////////////////////////////////////////////////////////////////////
1287/// Get the expected upper limit
1288/// nsig is used to specify which expected value of the UpperLimitDistribution
1289/// For example
1290/// - nsig = 0 (default value) returns the expected value
1291/// - nsig = -1 returns the lower band value at -1 sigma
1292/// - nsig + 1 return the upper value
1293/// - opt is an option specifying the type of method used for computing the upper limit
1294/// - opt = "" (default) : compute limit by interpolating all the p values, find the corresponding limit distribution
1295/// and then find the quantiles in the limit distribution
1296/// ioption = "P" is the method used for plotting. One Finds the corresponding nsig quantile in the p values and then
1297/// interpolates them
1298
1299double HypoTestInverterResult::GetExpectedUpperLimit(double nsig, const char * opt ) const {
1300
1301 return GetExpectedLimit(nsig, false, opt);
1302}
1303
1304////////////////////////////////////////////////////////////////////////////////
1305/// get expected limit (lower/upper) depending on the flag
1306/// for asymptotic is a special case (the distribution is generated an step in sigma values)
1307/// distinguish asymptotic looking at the hypotest results
1308/// if option = "P" get expected limit using directly quantiles of p value distribution
1309/// else (default) find expected limit by obtaining first a full limit distributions
1310/// The last one is in general more correct
1311
1312double HypoTestInverterResult::GetExpectedLimit(double nsig, bool lower, const char * opt ) const {
1313
1314 const int nEntries = ArraySize();
1315 if (nEntries <= 0) return (lower) ? 1 : 0; // return 1 for lower, 0 for upper
1316
1317 HypoTestResult * r = dynamic_cast<HypoTestResult *> (fYObjects.First() );
1318 assert(r != nullptr);
1319 if (!r->GetNullDistribution() && !r->GetAltDistribution() ) {
1320 // we are in the asymptotic case
1321 // get the limits obtained at the different sigma values
1323 if (!limitDist) return 0;
1324 const std::vector<double> & values = limitDist->GetSamplingDistribution();
1325 if (values.size() <= 1) return 0;
1326 double dsig = 2* fgAsymptoticMaxSigma/ (values.size() -1) ;
1327 int i = (int) TMath::Floor ( (nsig + fgAsymptoticMaxSigma)/dsig + 0.5);
1328 return values[i];
1329 }
1330
1331 double p[1] = {0};
1332 double q[1] = {0};
1334
1335 // for CLs+b can get the quantiles of p-value distribution and
1336 // interpolate them
1337 // In the case of CLs (since it is not a real p-value anymore but a ratio)
1338 // then it is needed to get first all limit distribution values and then the quantiles
1339
1340 TString option(opt);
1341 option.ToUpper();
1342 if (option.Contains("P")) {
1343
1344 TGraph g;
1345
1346 // sort the arrays based on the x values
1347 std::vector<unsigned int> index(nEntries);
1348 TMath::SortItr(fXValues.begin(), fXValues.end(), index.begin(), false);
1349
1350 for (int j=0; j<nEntries; ++j) {
1351 int i = index[j]; // i is the order index
1353 if (!s) {
1354 ooccoutI(this,Eval) << "HypoTestInverterResult - cannot compute expected p value distribution for point, x = "
1355 << GetXValue(i) << " skip it " << std::endl;
1356 continue;
1357 }
1358 const std::vector<double> & values = s->GetSamplingDistribution();
1359 double * x = const_cast<double *>(&values[0]); // need to change TMath::Quantiles
1360 TMath::Quantiles(values.size(), 1, x,q,p,false);
1361 g.SetPoint(g.GetN(), fXValues[i], q[0] );
1362 delete s;
1363 }
1364 if (g.GetN() < 2) {
1365 ooccoutE(this,Eval) << "HypoTestInverterResult - cannot compute limits , not enough points, n = " << g.GetN() << std::endl;
1366 return 0;
1367 }
1368
1369 // interpolate the graph to obtain the limit
1370 double target = 1-fConfidenceLevel;
1371 return GetGraphX(g, target, lower);
1372
1373 }
1374 // here need to use the limit distribution
1376 if (!limitDist) return 0;
1377 const std::vector<double> & values = limitDist->GetSamplingDistribution();
1378 double * x = const_cast<double *>(&values[0]); // need to change TMath::Quantiles
1379 TMath::Quantiles(values.size(), 1, x,q,p,false);
1380 return q[0];
1381
1382}
#define g(i)
Definition RSha256.hxx:105
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define coutI(a)
#define coutW(a)
#define coutE(a)
#define ooccoutW(o, a)
#define ooccoutI(o, a)
#define ooccoutD(o, a)
#define ooccoutE(o, a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
float xmin
float * q
float ymin
float xmax
float ymax
Class for finding the root of a one dimensional function using the Brent algorithm.
Functor1D class for one-dimensional functions.
Definition Functor.h:95
const_iterator begin() const
const_iterator end() const
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
RooAbsArg * first() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
virtual double getMax(const char *name=nullptr) const
Get maximum of currently defined range.
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
Variable that can be changed from the outside.
Definition RooRealVar.h:37
static double GetExpectedPValues(double pnull, double palt, double nsigma, bool usecls, bool oneSided=true)
function given the null and the alt p value - return the expected one given the N - sigma value
HypoTestInverterResult class holds the array of hypothesis test results and compute a confidence inte...
double GetYValue(int index) const
function to return the value of the confidence level for the i^th entry in the results
double LowerLimitEstimatedError()
rough estimation of the error on the computed bound of the confidence interval Estimate of lower limi...
double FindInterpolatedLimit(double target, bool lowSearch=false, double xmin=1, double xmax=0.0)
interpolate to find a limit value Use a linear or a spline interpolation depending on the interpolati...
double UpperLimitEstimatedError()
Estimate of lower limit error function evaluates only a rough error on the lower limit.
SamplingDistribution * GetSignalAndBackgroundTestStatDist(int index) const
get the signal and background test statistic distribution
HypoTestResult * GetResult(int index) const
return a pointer to the i^th result object
HypoTestInverterResult & operator=(const HypoTestInverterResult &other)
operator =
InterpolOption_t fInterpolOption
interpolation option (linear or spline)
int ArraySize() const
number of entries in the results array
double CLsplusbError(int index) const
return the observed CLsplusb value for the i-th entry
double CLsError(int index) const
return the observed CLb value for the i-th entry
double GetGraphX(const TGraph &g, double y0, bool lowSearch, double &xmin, double &xmax) const
return the X value of the given graph for the target value y0 the graph is evaluated using linear int...
double CLbError(int index) const
return the observed CLb value for the i-th entry
double GetExpectedUpperLimit(double nsig=0, const char *opt="") const
get Limit value corresponding at the desired nsigma level (0) is median -1 sigma is 1 sigma
HypoTestInverterResult(const char *name=nullptr)
default constructor
double GetXValue(int index) const
function to return the value of the parameter of interest for the i^th entry in the results
double UpperLimit() override
return the interval upper limit
bool Add(const HypoTestInverterResult &otherResult)
merge with the content of another HypoTestInverterResult object
int FindClosestPointIndex(double target, int mode=0, double xtarget=0)
TList fExpPValues
list of expected sampling distribution for each point
double GetExpectedLowerLimit(double nsig=0, const char *opt="") const
get Limit value corresponding at the desired nsigma level (0) is median -1 sigma is 1 sigma
bool fIsTwoSided
two sided scan (look for lower/upper limit)
double CalculateEstimatedError(double target, bool lower=true, double xmin=1, double xmax=0.0)
Return an error estimate on the upper(lower) limit.
static int fgAsymptoticNumPoints
number of points used to build expected p-values
static double fgAsymptoticMaxSigma
max sigma value used to scan asymptotic expected p values
int ExclusionCleanup()
remove points that appear to have failed.
double LowerLimit() override
lower and upper bound of the confidence interval (to get upper/lower limits, multiply the size( = 1-c...
double CLs(int index) const
return the observed CLb value for the i-th entry
int FindIndex(double xvalue) const
find the index corresponding at the poi value xvalue If no points is found return -1 Note that a tole...
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...
double CLb(int index) const
return the observed CLb value for the i-th entry
TList fYObjects
list of HypoTestResult for each point
double GetExpectedLimit(double nsig, bool lower, const char *opt="") const
get expected limit (lower/upper) depending on the flag for asymptotic is a special case (the distribu...
SamplingDistribution * GetExpectedPValueDist(int index) const
return expected distribution of p-values (Cls or Clsplusb)
double CLsplusb(int index) const
return the observed CLsplusb value for the i-th entry
SamplingDistribution * GetLimitDistribution(bool lower) const
get the limit distribution (lower/upper depending on the flag) by interpolating the expected p values...
SamplingDistribution * GetNullTestStatDist(int index) const
same in terms of alt and null
SamplingDistribution * GetBackgroundTestStatDist(int index) const
get the background test statistic distribution
HypoTestResult is a base class for results from hypothesis tests.
TObject * Clone(const char *newname=nullptr) const override
clone method, required since some data members cannot rely on the streamers to copy them
This class simply holds a sampling distribution of some test statistic.
const std::vector< double > & GetSamplingDistribution() const
Get test statistics values.
SimpleInterval is a concrete implementation of the ConfInterval interface.
double fUpperLimit
upper interval limit
RooArgSet fParameters
set containing the parameter of interest
double ConfidenceLevel() const override
return the confidence interval
double fLowerLimit
lower interval limit
double fConfidenceLevel
confidence level
SimpleInterval & operator=(const SimpleInterval &other)
default constructor
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:41
The Canvas class.
Definition TCanvas.h:23
virtual void RemoveAll(TCollection *col)
Remove all objects in collection col from this collection.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
1-Dim function class
Definition TF1.h:234
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4130
A TGraphErrors is a TGraph with error bars.
void Print(Option_t *chopt="") const override
Print graph and errors values.
virtual void SetPointError(Double_t ex, Double_t ey)
Set ex and ey values for point pointed by the mouse.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Set x and y values for point number i.
Definition TGraph.cxx:2291
Double_t * GetY() const
Definition TGraph.h:139
Int_t GetN() const
Definition TGraph.h:131
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Axis_t xmin=0, Axis_t xmax=0)
Fit this graph with function with name fname.
Definition TGraph.cxx:1256
Double_t * GetX() const
Definition TGraph.h:138
virtual Double_t Eval(Double_t x, TSpline *spline=nullptr, Option_t *option="") const
Interpolate points in this graph at x using a TSpline.
Definition TGraph.cxx:955
void Draw(Option_t *chopt="") override
Draw this graph with its current attributes.
Definition TGraph.cxx:833
void Add(TObject *obj) override
Definition TList.h:81
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:657
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition TObject.cxx:242
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:947
virtual TObject * RemoveAt(Int_t idx)
Basic string class.
Definition TString.h:139
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
double normal_cdf(double x, double sigma=1, double x0=0)
Cumulative distribution function of the normal (Gaussian) distribution (lower tail).
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:64
@ InputArguments
Namespace for the RooStats classes.
Definition CodegenImpl.h:58
TMath.
Definition TMathBase.h:35
Bool_t IsNaN(Double_t x)
Definition TMath.h:896
void SortItr(Iterator first, Iterator last, IndexIterator index, Bool_t down=kTRUE)
Sort the n1 elements of the Short_t array defined by its iterators.
Definition TMathBase.h:406
Double_t QuietNaN()
Returns a quiet NaN as defined by IEEE 754.
Definition TMath.h:906
Double_t Floor(Double_t x)
Rounds x downward, returning the largest integral value that is not greater than x.
Definition TMath.h:684
T MinElement(Long64_t n, const T *a)
Returns minimum of array a of length n.
Definition TMath.h:964
void Quantiles(Int_t n, Int_t nprob, Double_t *x, Double_t *quantiles, Double_t *prob, Bool_t isSorted=kTRUE, Int_t *index=nullptr, Int_t type=7)
Computes sample quantiles, corresponding to the given probabilities.
Definition TMath.cxx:1207
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:426
Bool_t AreEqualAbs(Double_t af, Double_t bf, Double_t epsilon)
Comparing floating points.
Definition TMath.h:418
T MaxElement(Long64_t n, const T *a)
Returns maximum of array a of length n.
Definition TMath.h:972
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:347
Double_t Infinity()
Returns an infinity as defined by the IEEE standard.
Definition TMath.h:921
TMarker m
Definition textangle.C:8
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345