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