Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooCurve.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooCurve.cxx
19\class RooCurve
20\ingroup Roofitcore
21
22One-dimensional graphical representation of a real-valued function.
23A curve is approximated by straight line segments with end points chosen to give
24a "good" approximation to the true curve. The goodness of the approximation is
25controlled by a precision and a resolution parameter.
26
27A RooCurve derives from TGraph, so it can either be drawn as a line (default) or
28as points:
29```
30RooPlot *p = y.plotOn(x.frame());
31p->getAttMarker("curve_y")->SetMarkerStyle(20);
32p->setDrawOptions("curve_y","PL");
33p->Draw();
34```
35
36To retrieve a RooCurve from a RooPlot, use RooPlot::getCurve().
37**/
38
39#include "RooCurve.h"
40#include "RooHist.h"
41#include "RooAbsReal.h"
42#include "RooArgSet.h"
43#include "RooRealVar.h"
44#include "RooRealBinding.h"
45#include "RooMsgService.h"
46#include "RooProduct.h"
47#include "RooConstVar.h"
48
49#include "Riostream.h"
50#include "TMath.h"
51#include "TAxis.h"
52#include "TMatrixD.h"
53#include "TVectorD.h"
54#include "Math/Util.h"
55#include <iomanip>
56#include <deque>
57#include <algorithm>
58
59using std::deque, std::endl, std::ostream, std::list, std::vector, std::cout, std::setw, std::min;
60
62
63
64////////////////////////////////////////////////////////////////////////////////
65/// Default constructor.
66
68{
69 initialize();
70}
71
72
73////////////////////////////////////////////////////////////////////////////////
74/// Create a 1-dim curve of the value of the specified real-valued expression
75/// as a function of x. Use the optional precision parameter to control
76/// how precisely the smooth curve is rasterized. Use the optional argument set
77/// to specify how the expression should be normalized. Use the optional scale
78/// factor to rescale the expression after normalization.
79/// If shiftToZero is set, the entire curve is shifted down to make the lowest
80/// point of the curve go through zero.
81RooCurve::RooCurve(const RooAbsReal &f, RooAbsRealLValue &x, double xlo, double xhi, Int_t xbins, double scaleFactor,
82 const RooArgSet *normVars, double prec, double resolution, bool shiftToZero, WingMode wmode,
83 Int_t nEvalError, Int_t doEEVal, double eeVal, bool showProg)
84 : _showProgress(showProg)
85{
86 // grab the function's name and title
87 TString name(f.GetName());
88 SetName(name.Data());
89 TString title(f.GetTitle());
90 SetTitle(title.Data());
91 // append " ( [<funit> ][/ <xunit> ])" to our y-axis label if necessary
92 if(0 != strlen(f.getUnit()) || 0 != strlen(x.getUnit())) {
93 title.Append(" ( ");
94 if(0 != strlen(f.getUnit())) {
95 title.Append(f.getUnit());
96 title.Append(" ");
97 }
98 if(0 != strlen(x.getUnit())) {
99 title.Append("/ ");
100 title.Append(x.getUnit());
101 title.Append(" ");
102 }
103 title.Append(")");
104 }
105 setYAxisLabel(title.Data());
106
107 RooProduct scaledFunc{"scaled_func", "scaled_func", {f, RooFit::RooConst(scaleFactor)}};
108 std::unique_ptr<RooAbsFunc> funcPtr{scaledFunc.bindVars(x, normVars, true)};
109
110 // calculate the points to add to our curve
111 if(xbins > 0){
112 // regular mode - use the sampling hint to decide where to evaluate the pdf
113 std::unique_ptr<std::list<double>> hint{f.plotSamplingHint(x,xlo,xhi)};
114 addPoints(*funcPtr,xlo,xhi,xbins+1,prec,resolution,wmode,nEvalError,doEEVal,eeVal,hint.get());
115 if (_showProgress) {
116 ccoutP(Plotting) << endl ;
117 }
118 } else {
119 // if number of bins is set to <= 0, skip any interpolation and just evaluate the pdf at the bin centers
120 // this is useful when plotting a pdf like a histogram
121 int nBinsX = x.numBins();
122 for(int i=0; i<nBinsX; ++i){
123 double xval = x.getBinning().binCenter(i);
124 addPoint(xval,(*funcPtr)(&xval)) ;
125 }
126 }
127 initialize();
128
129 if (shiftToZero) shiftCurveToZero() ;
130
131 // Adjust limits
132 for (int i=0 ; i<GetN() ; i++) {
134 }
135 this->Sort();
136}
137
138
139
140////////////////////////////////////////////////////////////////////////////////
141/// Create a 1-dim curve of the value of the specified real-valued
142/// expression as a function of x. Use the optional precision
143/// parameter to control how precisely the smooth curve is
144/// rasterized. If shiftToZero is set, the entire curve is shifted
145/// down to make the lowest point in of the curve go through zero.
146
147RooCurve::RooCurve(const char *name, const char *title, const RooAbsFunc &func,
148 double xlo, double xhi, UInt_t minPoints, double prec, double resolution,
149 bool shiftToZero, WingMode wmode, Int_t nEvalError, Int_t doEEVal, double eeVal)
150{
151 SetName(name);
152 SetTitle(title);
153 addPoints(func,xlo,xhi,minPoints+1,prec,resolution,wmode,nEvalError,doEEVal,eeVal);
154 initialize();
155 if (shiftToZero) shiftCurveToZero() ;
156
157 // Adjust limits
158 for (int i=0 ; i<GetN() ; i++) {
160 }
161 this->Sort();
162}
163
164
165
166////////////////////////////////////////////////////////////////////////////////
167/// Constructor of a curve as sum of two other curves.
168/// \f[
169/// C_\mathrm{sum} = \mathrm{scale1}*c1 + \mathrm{scale2}*c2
170/// \f]
171///
172/// \param[in] name Name of the curve (to retrieve it from a plot)
173/// \param[in] title Title (for plotting).
174/// \param[in] c1 First curve.
175/// \param[in] c2 Second curve.
176/// \param[in] scale1 Scale y values for c1 by this factor.
177/// \param[in] scale2 Scale y values for c2 by this factor.
178
179RooCurve::RooCurve(const char* name, const char* title, const RooCurve& c1, const RooCurve& c2, double scale1, double scale2)
180{
181 initialize() ;
182 SetName(name) ;
183 SetTitle(title) ;
184
185 // Make deque of points in X
186 deque<double> pointList ;
187 double x;
188 double y;
189
190 // Add X points of C1
191 Int_t i1;
192 Int_t n1 = c1.GetN();
193 for (i1=0 ; i1<n1 ; i1++) {
194 c1.GetPoint(i1,x,y) ;
195 pointList.push_back(x) ;
196 }
197
198 // Add X points of C2
199 Int_t i2;
200 Int_t n2 = c2.GetN();
201 for (i2=0 ; i2<n2 ; i2++) {
202 c2.GetPoint(i2,x,y) ;
203 pointList.push_back(x) ;
204 }
205
206 // Sort X points
207 sort(pointList.begin(),pointList.end()) ;
208
209 // Loop over X points
210 double last(-RooNumber::infinity()) ;
211 for (auto point : pointList) {
212
213 if ((point-last)>1e-10) {
214 // Add OR of points to new curve, skipping duplicate points within tolerance
215 addPoint(point,scale1*c1.interpolate(point)+scale2*c2.interpolate(point)) ;
216 }
217 last = point ;
218 }
219
220 this->Sort();
221}
222
223
224RooCurve::~RooCurve() = default;
225
226
227////////////////////////////////////////////////////////////////////////////////
228/// Perform initialization that is common to all curves
229
231{
232 // set default line width in pixels
233 SetLineWidth(3);
234 // set default line color
236}
237
238
239
240////////////////////////////////////////////////////////////////////////////////
241/// Find lowest point in curve and move all points in curve so that
242/// lowest point will go exactly through zero
243
245{
246 double minVal = std::numeric_limits<double>::infinity();
247 double maxVal = -std::numeric_limits<double>::infinity();
248
249 // First iteration, find current lowest point
250 for (int i = 1; i < GetN() - 1; i++) {
251 double x;
252 double y;
253 GetPoint(i, x, y);
254 minVal = std::min(y, minVal);
255 maxVal = std::max(y, maxVal);
256 }
257
258 // Second iteration, lower all points by minVal
259 for (int i = 1; i < GetN() - 1; i++) {
260 double x;
261 double y;
262 GetPoint(i, x, y);
263 SetPoint(i, x, y - minVal);
264 }
265
266 setYAxisLimits(0, maxVal - minVal);
267}
268
269
270
271////////////////////////////////////////////////////////////////////////////////
272/// Add points calculated with the specified function, over the range (xlo,xhi).
273/// Add at least minPoints equally spaced points, and add sufficient points so that
274/// the maximum deviation from the final straight-line segments is prec*(ymax-ymin),
275/// down to a minimum horizontal spacing of resolution*(xhi-xlo).
276
277void RooCurve::addPoints(const RooAbsFunc &func, double xlo, double xhi,
278 Int_t minPoints, double prec, double resolution, WingMode wmode,
279 Int_t numee, bool doEEVal, double eeVal, list<double>* samplingHint)
280{
281 // check the inputs
282 if(!func.isValid()) {
283 coutE(InputArguments) << fName << "::addPoints: input function is not valid" << endl;
284 return;
285 }
286 if(minPoints <= 0 || xhi <= xlo) {
287 coutE(InputArguments) << fName << "::addPoints: bad input (nothing added)" << endl;
288 return;
289 }
290
291 // Perform a coarse scan of the function to estimate its y range.
292 // Save the results so we do not have to re-evaluate at the scan points.
293
294 // Adjust minimum number of points to external sampling hint if used
295 if (samplingHint) {
296 minPoints = samplingHint->size() ;
297 }
298
299 double dx= (xhi-xlo)/(minPoints-1.);
300 const double epsilon = (xhi - xlo) * relativeXEpsilon();;
301 std::vector<double> yval(minPoints);
302
303 // Get list of initial x values. If function provides sampling hint use that,
304 // otherwise use default binning of frame
305 std::vector<double> xval;
306 if (!samplingHint) {
307 for(int step= 0; step < minPoints; step++) {
308 xval.push_back(xlo + step*dx) ;
309 }
310 } else {
311 std::copy(samplingHint->begin(), samplingHint->end(), std::back_inserter(xval));
312 }
313
314 for (unsigned int step=0; step < xval.size(); ++step) {
315 double xx = xval[step];
316 if (step == static_cast<unsigned int>(minPoints-1))
317 xx -= 1e-9 * dx;
318
319 yval[step]= func(&xx);
320 if (_showProgress) {
321 ccoutP(Plotting) << "." ;
322 cout.flush() ;
323 }
324
326 if (numee>=0) {
327 coutW(Plotting) << "At observable [x]=" << xx << " " ;
328 RooAbsReal::printEvalErrors(ccoutW(Plotting),numee) ;
329 }
330 if (doEEVal) {
331 yval[step]=eeVal ;
332 }
333 }
335 }
336
337 const double ymax = *std::max_element(yval.begin(), yval.end());
338 const double ymin = *std::min_element(yval.begin(), yval.end());
339 double yrangeEst=(ymax-ymin) ;
340
341 // store points of the coarse scan and calculate any refinements necessary
342 double minDx= resolution*(xhi-xlo);
343 double x1;
344 double x2 = xlo;
345
346 if (wmode==Extended) {
347 // Add two points to make curve jump from 0 to yval at the left end of the plotting range.
348 // This ensures that filled polygons are drawn properly. The first point needs to be to the
349 // left of the second, so it's shifted by 1/1000 more than the second.
350 addPoint(xlo-dx*1.001, 0);
351 addPoint(xlo-dx,yval[0]) ;
352 } else if (wmode==Straight) {
353 addPoint(xlo-dx*0.001,0) ;
354 }
355
356 addPoint(xlo,yval[0]);
357
358 auto iter2 = xval.begin() ;
359 x1 = *iter2 ;
360 int step=1 ;
361 while(true) {
362 x1= x2;
363 ++iter2 ;
364 if (iter2==xval.end()) {
365 break ;
366 }
367 x2= *iter2 ;
368 if (prec<0) {
369 // If precision is <0, no attempt at recursive interpolation is made
370 addPoint(x2,yval[step]) ;
371 } else {
372 addRange(func,x1,x2,yval[step-1],yval[step],prec*yrangeEst,minDx,numee,doEEVal,eeVal,epsilon);
373 }
374 step++ ;
375 }
376 addPoint(xhi,yval[minPoints-1]) ;
377
378 if (wmode==Extended) {
379 // Add two points to close polygon. The order matters. Since they are sorted in x later, the second
380 // point is shifted by 1/1000 more than the second-to-last point.
381 addPoint(xhi+dx,yval[minPoints-1]) ;
382 addPoint(xhi+dx*1.001, 0);
383 } else if (wmode==Straight) {
384 addPoint(xhi+dx*0.001,0) ;
385 }
386}
387
388
389////////////////////////////////////////////////////////////////////////////////
390/// Fill the range (x1,x2) with points calculated using func(&x). No point will
391/// be added at x1, and a point will always be added at x2. The density of points
392/// will be calculated so that the maximum deviation from a straight line
393/// approximation is prec*(ymax-ymin) down to the specified minimum horizontal spacing.
394
395void RooCurve::addRange(const RooAbsFunc& func, double x1, double x2,
396 double y1, double y2, double minDy, double minDx,
397 int numee, bool doEEVal, double eeVal, double epsilon)
398{
399 // Explicitly skip empty ranges to eliminate point duplication
400 if (std::abs(x2-x1) <= epsilon) {
401 return ;
402 }
403
404 // calculate our value at the midpoint of this range
405 double xmid= 0.5*(x1+x2);
406 double ymid= func(&xmid);
407 if (_showProgress) {
408 ccoutP(Plotting) << "." ;
409 cout.flush() ;
410 }
411
413 if (numee>=0) {
414 coutW(Plotting) << "At observable [x]=" << xmid << " " ;
415 RooAbsReal::printEvalErrors(ccoutW(Plotting),numee) ;
416 }
417 if (doEEVal) {
418 ymid=eeVal ;
419 }
420 }
422
423 // test if the midpoint is sufficiently close to a straight line across this interval
424 double dy= ymid - 0.5*(y1+y2);
425 if((xmid - x1 >= minDx) && std::abs(dy)>0 && std::abs(dy) >= minDy) {
426 // fill in each subrange
427 addRange(func,x1,xmid,y1,ymid,minDy,minDx,numee,doEEVal,eeVal,epsilon);
428 addRange(func,xmid,x2,ymid,y2,minDy,minDx,numee,doEEVal,eeVal,epsilon);
429 }
430 else {
431 // add the endpoint
432 addPoint(x2,y2);
433 }
434}
435
436
437////////////////////////////////////////////////////////////////////////////////
438/// Add a point with the specified coordinates. Update our y-axis limits.
439
440void RooCurve::addPoint(double x, double y)
441{
442// cout << "RooCurve("<< GetName() << ") adding point at (" << x << "," << y << ")" << endl ;
443 Int_t next= GetN();
444 SetPoint(next, x, y);
446}
447
448
449////////////////////////////////////////////////////////////////////////////////
450/// Return the number of events associated with the plotable object,
451/// it is always 1 for curves
452
454 return 1;
455}
456
457
458////////////////////////////////////////////////////////////////////////////////
459/// Return the number of events associated with the plotable object,
460/// in the given range. It is always 1 for curves
461
462double RooCurve::getFitRangeNEvt(double, double) const
463{
464 return 1 ;
465}
466
467
468////////////////////////////////////////////////////////////////////////////////
469/// Get the bin width associated with this plotable object.
470/// It is alwats zero for curves
471
473 return 0 ;
474}
475
476
477
478////////////////////////////////////////////////////////////////////////////////
479
480void RooCurve::printName(ostream& os) const
481//
482{
483 // Print the name of this curve
484 os << GetName() ;
485}
486
487
488////////////////////////////////////////////////////////////////////////////////
489/// Print the title of this curve
490
491void RooCurve::printTitle(ostream& os) const
492{
493 os << GetTitle() ;
494}
495
496
497////////////////////////////////////////////////////////////////////////////////
498/// Print the class name of this curve
499
500void RooCurve::printClassName(ostream& os) const
501{
502 os << ClassName() ;
503}
504
505
506
507////////////////////////////////////////////////////////////////////////////////
508/// Print the details of this curve
509
510void RooCurve::printMultiline(ostream& os, Int_t /*contents*/, bool /*verbose*/, TString indent) const
511{
512 os << indent << "--- RooCurve ---" << endl ;
513 Int_t n= GetN();
514 os << indent << " Contains " << n << " points" << endl;
515 os << indent << " Graph points:" << endl;
516 for(Int_t i= 0; i < n; i++) {
517 os << indent << setw(3) << i << ") x = " << fX[i] << " , y = " << fY[i] << endl;
518 }
519}
520
521
522
523////////////////////////////////////////////////////////////////////////////////
524/// Calculate the chi^2/NDOF of this curve with respect to the histogram
525/// 'hist' accounting nFitParam floating parameters in case the curve
526/// was the result of a fit
527
528double RooCurve::chiSquare(const RooHist& hist, Int_t nFitParam) const
529{
530 Int_t i;
531 Int_t np = hist.GetN();
532 double x;
533 double y;
534 double eyl;
535 double eyh;
536 double exl;
537 double exh;
538
539 // Find starting and ending bin of histogram based on range of RooCurve
540 double xstart;
541 double xstop;
542
543 GetPoint(0,xstart,y) ;
544 GetPoint(GetN()-1,xstop,y) ;
545
546 Int_t nbin(0) ;
547
549 for (i=0 ; i<np ; i++) {
550
551 // Retrieve histogram contents
552 hist.GetPoint(i,x,y) ;
553
554 // Check if point is in range of curve
555 if (x<xstart || x>xstop) continue ;
556
557 eyl = hist.GetEYlow()[i] ;
558 eyh = hist.GetEYhigh()[i] ;
559 exl = hist.GetEXlow()[i] ;
560 exh = hist.GetEXhigh()[i] ;
561
562 // Integrate function over this bin
563 double avg = average(x-exl,x+exh) ;
564
565 // Add pull^2 to chisq
566 if (y!=0) {
567 double pull = (y>avg) ? ((y-avg)/eyl) : ((y-avg)/eyh) ;
568 chisq += pull*pull ;
569 nbin++ ;
570 }
571 }
572
573 // Return chisq/nDOF
574 return chisq.Sum() / (nbin-nFitParam) ;
575}
576
577
578
579////////////////////////////////////////////////////////////////////////////////
580/// Return average curve value in [xFirst,xLast] by integrating curve between points
581/// and dividing by xLast-xFirst
582
583double RooCurve::average(double xFirst, double xLast) const
584{
585 if (xFirst>=xLast) {
586 coutE(InputArguments) << "RooCurve::average(" << GetName()
587 << ") invalid range (" << xFirst << "," << xLast << ")" << endl ;
588 return 0 ;
589 }
590
591 // Find Y values and begin and end points
592 double yFirst = interpolate(xFirst,1e-10) ;
593 double yLast = interpolate(xLast,1e-10) ;
594
595 // Find first and last mid points
596 Int_t ifirst = findPoint(xFirst,1e10) ;
597 Int_t ilast = findPoint(xLast,1e10) ;
598 double xFirstPt;
599 double yFirstPt;
600 double xLastPt;
601 double yLastPt;
602 GetPoint(ifirst,xFirstPt,yFirstPt) ;
603 GetPoint(ilast,xLastPt,yLastPt) ;
604
605 double tolerance=1e-3*(xLast-xFirst) ;
606
607 // Handle trivial scenario -- no midway points, point only at or outside given range
608 if (ilast-ifirst==1 &&(xFirstPt-xFirst)<-1*tolerance && (xLastPt-xLast)>tolerance) {
609 return 0.5*(yFirst+yLast) ;
610 }
611
612 // If first point closest to xFirst is at xFirst or before xFirst take the next point
613 // as the first midway point
614 if ((xFirstPt-xFirst)<-1*tolerance) {
615 ifirst++ ;
616 const_cast<RooCurve&>(*this).GetPoint(ifirst,xFirstPt,yFirstPt) ;
617 }
618
619 // If last point closest to yLast is at yLast or beyond yLast the previous point
620 // as the last midway point
621 if ((xLastPt-xLast)>tolerance) {
622 ilast-- ;
623 const_cast<RooCurve&>(*this).GetPoint(ilast,xLastPt,yLastPt) ;
624 }
625
626 double sum(0);
627 double x1;
628 double y1;
629 double x2;
630 double y2;
631
632 // Trapezoid integration from lower edge to first midpoint
633 sum += (xFirstPt-xFirst)*(yFirst+yFirstPt)/2 ;
634
635 // Trapezoid integration between midpoints
636 Int_t i ;
637 for (i=ifirst ; i<ilast ; i++) {
638 const_cast<RooCurve&>(*this).GetPoint(i,x1,y1) ;
639 const_cast<RooCurve&>(*this).GetPoint(i+1,x2,y2) ;
640 sum += (x2-x1)*(y1+y2)/2 ;
641 }
642
643 // Trapezoid integration from last midpoint to upper edge
644 sum += (xLast-xLastPt)*(yLastPt+yLast)/2 ;
645 return sum/(xLast-xFirst) ;
646}
647
648
649
650////////////////////////////////////////////////////////////////////////////////
651/// Find the nearest point to xvalue. Return -1 if distance
652/// exceeds tolerance
653
654Int_t RooCurve::findPoint(double xvalue, double tolerance) const
655{
656 double delta(std::numeric_limits<double>::max());
657 double x;
658 double y;
659 Int_t i;
660 Int_t n = GetN();
661 Int_t ibest(-1) ;
662 for (i=0 ; i<n ; i++) {
663 GetPoint(i,x,y);
664 if (std::abs(xvalue-x)<delta) {
665 delta = std::abs(xvalue-x) ;
666 ibest = i ;
667 }
668 }
669
670 return (delta<tolerance)?ibest:-1 ;
671}
672
673
674////////////////////////////////////////////////////////////////////////////////
675/// Return linearly interpolated value of curve at xvalue. If distance
676/// to nearest point is less than tolerance, return nearest point value
677/// instead
678
679double RooCurve::interpolate(double xvalue, double tolerance) const
680{
681 // Find best point
682 int n = GetN() ;
683 int ibest = findPoint(xvalue,1e10) ;
684
685 // Get position of best point
686 double xbest;
687 double ybest;
688 const_cast<RooCurve*>(this)->GetPoint(ibest,xbest,ybest) ;
689
690 // Handle trivial case of being dead on
691 if (std::abs(xbest-xvalue)<tolerance) {
692 return ybest ;
693 }
694
695 // Get nearest point on other side w.r.t. xvalue
696 double xother;
697 double yother;
698 double retVal(0);
699 if (xbest<xvalue) {
700 if (ibest==n-1) {
701 // Value beyond end requested -- return value of last point
702 return ybest ;
703 }
704 const_cast<RooCurve*>(this)->GetPoint(ibest+1,xother,yother) ;
705 if (xother==xbest) return ybest ;
706 retVal = ybest + (yother-ybest)*(xvalue-xbest)/(xother-xbest) ;
707
708 } else {
709 if (ibest==0) {
710 // Value before 1st point requested -- return value of 1st point
711 return ybest ;
712 }
713 const_cast<RooCurve*>(this)->GetPoint(ibest-1,xother,yother) ;
714 if (xother==xbest) return ybest ;
715 retVal = yother + (ybest-yother)*(xvalue-xother)/(xbest-xother) ;
716 }
717
718 return retVal ;
719}
720
721
722
723
724////////////////////////////////////////////////////////////////////////////////
725/// Construct filled RooCurve represented error band that captures alpha% of the variations
726/// of the curves passed through argument variations, where the percentage alpha corresponds to
727/// the central interval fraction of a significance Z
728
729RooCurve* RooCurve::makeErrorBand(const vector<RooCurve*>& variations, double Z) const
730{
731 RooCurve* band = new RooCurve ;
732 band->SetName((std::string(GetName()) + "_errorband").c_str());
733 band->SetLineWidth(1) ;
734 band->SetFillColor(kCyan) ;
735 band->SetLineColor(kCyan) ;
736
737 vector<double> bandLo(GetN()) ;
738 vector<double> bandHi(GetN()) ;
739 for (int i=0 ; i<GetN() ; i++) {
740 calcBandInterval(variations,i,Z,bandLo[i],bandHi[i],false) ;
741 }
742
743 for (int i=0 ; i<GetN() ; i++) {
744 band->addPoint(GetX()[i],bandLo[i]) ;
745 }
746 for (int i=GetN()-1 ; i>=0 ; i--) {
747 band->addPoint(GetX()[i],bandHi[i]) ;
748 }
749 // if the axis of the old graph is alphanumeric, copy the labels to the new one as well
750 if(this->GetXaxis() && this->GetXaxis()->IsAlphanumeric()){
751 band->GetXaxis()->Set(this->GetXaxis()->GetNbins(),this->GetXaxis()->GetXmin(),this->GetXaxis()->GetXmax());
752 for(int i=0; i<this->GetXaxis()->GetNbins(); ++i){
753 band->GetXaxis()->SetBinLabel(i+1,this->GetXaxis()->GetBinLabel(i+1));
754 }
755 }
756
757 return band ;
758}
759
760
761
762
763////////////////////////////////////////////////////////////////////////////////
764/// Construct filled RooCurve represented error band represent the error added in quadrature defined by the curves arguments
765/// plusVar and minusVar corresponding to one-sigma variations of each parameter. The resulting error band, combined used the correlation matrix C
766/// is multiplied with the significance parameter Z to construct the equivalent of a Z sigma error band (in Gaussian approximation)
767
768RooCurve* RooCurve::makeErrorBand(const vector<RooCurve*>& plusVar, const vector<RooCurve*>& minusVar, const TMatrixD& C, double Z) const
769{
770
771 RooCurve* band = new RooCurve ;
772 band->SetName((std::string(GetName()) + "_errorband").c_str());
773 band->SetLineWidth(1) ;
774 band->SetFillColor(kCyan) ;
775 band->SetLineColor(kCyan) ;
776
777 vector<double> bandLo(GetN()) ;
778 vector<double> bandHi(GetN()) ;
779 for (int i=0 ; i<GetN() ; i++) {
780 calcBandInterval(plusVar,minusVar,i,C,Z,bandLo[i],bandHi[i]) ;
781 }
782
783 for (int i=0 ; i<GetN() ; i++) {
784 band->addPoint(GetX()[i],bandLo[i]) ;
785 }
786 for (int i=GetN()-1 ; i>=0 ; i--) {
787 band->addPoint(GetX()[i],bandHi[i]) ;
788 }
789
790 // if the axis of the old graph is alphanumeric, copy the labels to the new one as well
791 if(this->GetXaxis() && this->GetXaxis()->IsAlphanumeric()){
792 band->GetXaxis()->Set(this->GetXaxis()->GetNbins(),this->GetXaxis()->GetXmin(),this->GetXaxis()->GetXmax());
793 for(int i=0; i<this->GetXaxis()->GetNbins(); ++i){
794 band->GetXaxis()->SetBinLabel(i+1,this->GetXaxis()->GetBinLabel(i+1));
795 }
796 }
797
798 return band ;
799}
800
801
802
803
804
805////////////////////////////////////////////////////////////////////////////////
806/// Retrieve variation points from curves
807
808void RooCurve::calcBandInterval(const vector<RooCurve*>& plusVar, const vector<RooCurve*>& minusVar,Int_t i, const TMatrixD& C, double /*Z*/, double& lo, double& hi) const
809{
810 vector<double> y_plus(plusVar.size());
811 vector<double> y_minus(minusVar.size());
812 Int_t j(0) ;
813 for (vector<RooCurve*>::const_iterator iter=plusVar.begin() ; iter!=plusVar.end() ; ++iter) {
814 y_plus[j++] = (*iter)->interpolate(GetX()[i]) ;
815 }
816 j=0 ;
817 for (vector<RooCurve*>::const_iterator iter=minusVar.begin() ; iter!=minusVar.end() ; ++iter) {
818 y_minus[j++] = (*iter)->interpolate(GetX()[i]) ;
819 }
820 double y_cen = GetY()[i] ;
821 Int_t n = j ;
822
823 // Make vector of variations
824 TVectorD F(plusVar.size()) ;
825 for (j=0 ; j<n ; j++) {
826 F[j] = (y_plus[j]-y_minus[j])/2 ;
827 }
828
829 // Calculate error in linear approximation from variations and correlation coefficient
830 double sum = F*(C*F) ;
831
832 lo= y_cen + sqrt(sum) ;
833 hi= y_cen - sqrt(sum) ;
834}
835
836
837
838////////////////////////////////////////////////////////////////////////////////
839
840void RooCurve::calcBandInterval(const vector<RooCurve*>& variations,Int_t i,double Z, double& lo, double& hi, bool approxGauss) const
841{
842 vector<double> y(variations.size()) ;
843 Int_t j(0) ;
844 for (vector<RooCurve*>::const_iterator iter=variations.begin() ; iter!=variations.end() ; ++iter) {
845 y[j++] = (*iter)->interpolate(GetX()[i]) ;
846}
847
848 if (!approxGauss) {
849 // Construct central 68% interval from variations collected at each point
850 double pvalue = TMath::Erfc(Z/sqrt(2.)) ;
851 Int_t delta = Int_t( y.size()*(pvalue)/2 + 0.5) ;
852 sort(y.begin(),y.end()) ;
853 lo = y[delta] ;
854 hi = y[y.size()-delta] ;
855 } else {
856 // Estimate R.M.S of variations at each point and use that as Gaussian sigma
857 double sum_y(0);
858 double sum_ysq(0);
859 for (unsigned int k=0 ; k<y.size() ; k++) {
860 sum_y += y[k] ;
861 sum_ysq += y[k]*y[k] ;
862 }
863 sum_y /= y.size() ;
864 sum_ysq /= y.size() ;
865
866 double rms = sqrt(sum_ysq - (sum_y*sum_y)) ;
867 lo = GetY()[i] - Z*rms ;
868 hi = GetY()[i] + Z*rms ;
869 }
870}
871
872
873
874
875////////////////////////////////////////////////////////////////////////////////
876/// Return true if curve is identical to other curve allowing for given
877/// absolute tolerance on each point compared point.
878
879bool RooCurve::isIdentical(const RooCurve& other, double tol, bool verbose) const
880{
881 // Determine X range and Y range
882 Int_t n= min(GetN(),other.GetN());
883 double xmin(1e30);
884 double xmax(-1e30);
885 double ymin(1e30);
886 double ymax(-1e30);
887 for(Int_t i= 0; i < n; i++) {
888 if (fX[i]<xmin) xmin=fX[i] ;
889 if (fX[i]>xmax) xmax=fX[i] ;
890 if (fY[i]<ymin) ymin=fY[i] ;
891 if (fY[i]>ymax) ymax=fY[i] ;
892 }
893 const double Yrange=ymax-ymin ;
894
895 bool ret(true) ;
896 for(Int_t i= 2; i < n-2; i++) {
897 double yTest = interpolate(other.fX[i],1e-10) ;
898 double rdy = std::abs(yTest-other.fY[i])/Yrange ;
899 if (rdy>tol) {
900 ret = false;
901 if(!verbose) continue;
902 cout << "RooCurve::isIdentical[" << std::setw(3) << i << "] Y tolerance exceeded (" << std::setprecision(5) << std::setw(10) << rdy << ">" << tol << "),";
903 cout << " x,y=(" << std::right << std::setw(10) << fX[i] << "," << std::setw(10) << fY[i] << ")\tref: y="
904 << std::setw(10) << other.interpolate(fX[i], 1.E-15) << ". [Nearest point from ref: ";
905 auto j = other.findPoint(fX[i], 1.E10);
906 std::cout << "j=" << j << "\tx,y=(" << std::setw(10) << other.fX[j] << "," << std::setw(10) << other.fY[j] << ") ]" << "\trange=" << Yrange << std::endl;
907 }
908 }
909
910 return ret ;
911}
912
913
914
915////////////////////////////////////////////////////////////////////////////////
916/// Returns sampling hints for a histogram with given boundaries. This helper
917/// function is meant to be used by binned RooAbsReals to produce sampling
918/// hints that are working well with RooFits plotting.
919
920std::list<double> *
921RooCurve::plotSamplingHintForBinBoundaries(std::span<const double> boundaries, double xlo, double xhi)
922{
923 auto hint = new std::list<double>;
924
925 // Make sure the difference between two points around a bin boundary is
926 // larger than the relative epsilon for which the RooCurve considers two
927 // points as the same. Otherwise, the points right of the bin boundary would
928 // be skipped.
929 const double delta = (xhi - xlo) * RooCurve::relativeXEpsilon();
930
931 // Sample points right next to the plot limits
932 hint->push_back(xlo + delta);
933 hint->push_back(xhi - delta);
934
935 // Sample points very close to the left and right of the bin boundaries that
936 // are strictly in between the plot limits.
937 for (const double x : boundaries) {
938 if (x - xlo > delta && xhi - x > delta) {
939 hint->push_back(x - delta);
940 hint->push_back(x + delta);
941 }
942 }
943
944 hint->sort();
945
946 return hint;
947}
#define f(i)
Definition RSha256.hxx:104
#define e(i)
Definition RSha256.hxx:103
#define coutW(a)
#define ccoutP(a)
#define coutE(a)
#define ccoutW(a)
int Int_t
Definition RtypesCore.h:45
#define ClassImp(name)
Definition Rtypes.h:377
@ kCyan
Definition Rtypes.h:66
@ kBlue
Definition Rtypes.h:66
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t SetLineWidth
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 SetLineColor
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:110
float xmin
#define hi
float ymin
float xmax
float ymax
The Kahan summation is a compensated summation algorithm, which significantly reduces numerical error...
Definition Util.h:122
T Sum() const
Definition Util.h:240
Abstract interface for evaluating a real-valued function of one real variable and performing numerica...
Definition RooAbsFunc.h:27
bool isValid() const
Definition RooAbsFunc.h:37
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
RooFit::OwningPtr< RooAbsFunc > bindVars(const RooArgSet &vars, const RooArgSet *nset=nullptr, bool clipInvalid=false) const
Create an interface adaptor f(vars) that binds us to the specified variables (in arbitrary order).
static Int_t numEvalErrors()
Return the number of logged evaluation errors since the last clearing.
static void printEvalErrors(std::ostream &os=std::cout, Int_t maxPerNode=10000000)
Print all outstanding logged evaluation error on the given ostream.
static void clearEvalErrorLog()
Clear the stack of evaluation error messages.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
One-dimensional graphical representation of a real-valued function.
Definition RooCurve.h:36
void addPoints(const RooAbsFunc &func, double xlo, double xhi, Int_t minPoints, double prec, double resolution, WingMode wmode, Int_t numee=0, bool doEEVal=false, double eeVal=0.0, std::list< double > *samplingHint=nullptr)
Add points calculated with the specified function, over the range (xlo,xhi).
Definition RooCurve.cxx:277
void printTitle(std::ostream &os) const override
Print the title of this curve.
Definition RooCurve.cxx:491
void initialize()
Perform initialization that is common to all curves.
Definition RooCurve.cxx:230
~RooCurve() override
double getFitRangeBinW() const override
Get the bin width associated with this plotable object.
Definition RooCurve.cxx:472
static constexpr double relativeXEpsilon()
The distance between two points x1 and x2 relative to the full plot range below which two points are ...
Definition RooCurve.h:104
void addRange(const RooAbsFunc &func, double x1, double x2, double y1, double y2, double minDy, double minDx, int numee, bool doEEVal, double eeVal, double epsilon)
Fill the range (x1,x2) with points calculated using func(&x).
Definition RooCurve.cxx:395
void printName(std::ostream &os) const override
Print name of object.
Definition RooCurve.cxx:480
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Print the details of this curve.
Definition RooCurve.cxx:510
double interpolate(double x, double tolerance=1e-10) const
Return linearly interpolated value of curve at xvalue.
Definition RooCurve.cxx:679
static std::list< double > * plotSamplingHintForBinBoundaries(std::span< const double > boundaries, double xlo, double xhi)
Returns sampling hints for a histogram with given boundaries.
Definition RooCurve.cxx:921
void printClassName(std::ostream &os) const override
Print the class name of this curve.
Definition RooCurve.cxx:500
@ Extended
Definition RooCurve.h:39
@ Straight
Definition RooCurve.h:39
RooCurve()
Default constructor.
Definition RooCurve.cxx:67
bool _showProgress
! Show progress indication when adding points
Definition RooCurve.h:97
RooCurve * makeErrorBand(const std::vector< RooCurve * > &variations, double Z=1) const
Construct filled RooCurve represented error band that captures alpha% of the variations of the curves...
Definition RooCurve.cxx:729
double chiSquare(const RooHist &hist, int nFitParam) const
Calculate the chi^2/NDOF of this curve with respect to the histogram 'hist' accounting nFitParam floa...
Definition RooCurve.cxx:528
void calcBandInterval(const std::vector< RooCurve * > &variations, Int_t i, double Z, double &lo, double &hi, bool approxGauss) const
Definition RooCurve.cxx:840
double getFitRangeNEvt() const override
Return the number of events associated with the plotable object, it is always 1 for curves.
Definition RooCurve.cxx:453
void shiftCurveToZero()
Find lowest point in curve and move all points in curve so that lowest point will go exactly through ...
Definition RooCurve.cxx:244
void addPoint(double x, double y)
Add a point with the specified coordinates. Update our y-axis limits.
Definition RooCurve.cxx:440
bool isIdentical(const RooCurve &other, double tol=1e-6, bool verbose=true) const
Return true if curve is identical to other curve allowing for given absolute tolerance on each point ...
Definition RooCurve.cxx:879
Int_t findPoint(double value, double tolerance=1e-10) const
Find the nearest point to xvalue.
Definition RooCurve.cxx:654
double average(double lo, double hi) const
Return average curve value in [xFirst,xLast] by integrating curve between points and dividing by xLas...
Definition RooCurve.cxx:583
Graphical representation of binned data based on the TGraphAsymmErrors class.
Definition RooHist.h:29
static constexpr double infinity()
Return internal infinity representation.
Definition RooNumber.h:25
void updateYAxisLimits(double y)
Definition RooPlotable.h:30
void setYAxisLimits(double ymin, double ymax)
Definition RooPlotable.h:34
void setYAxisLabel(const char *label)
Definition RooPlotable.h:29
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition TAxis.cxx:886
Bool_t IsAlphanumeric() const
Definition TAxis.h:88
Double_t GetXmax() const
Definition TAxis.h:140
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:440
virtual void Set(Int_t nbins, Double_t xmin, Double_t xmax)
Initialize axis with fix bins.
Definition TAxis.cxx:794
Double_t GetXmin() const
Definition TAxis.h:139
Int_t GetNbins() const
Definition TAxis.h:125
Double_t * GetEXlow() const override
Double_t * GetEYhigh() const override
Double_t * GetEXhigh() const override
Double_t * GetEYlow() const override
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
Double_t * GetY() const
Definition TGraph.h:139
Int_t GetN() const
Definition TGraph.h:131
Double_t * fY
[fNpoints] array of Y points
Definition TGraph.h:48
virtual void Sort(Bool_t(*greater)(const TGraph *, Int_t, Int_t)=&TGraph::CompareX, Bool_t ascending=kTRUE, Int_t low=0, Int_t high=-1111)
Sorts the points of this TGraph using in-place quicksort (see e.g.
Definition TGraph.cxx:2463
Double_t * GetX() const
Definition TGraph.h:138
void SetName(const char *name="") override
Set graph name.
Definition TGraph.cxx:2358
TAxis * GetXaxis() const
Get x axis of the graph.
Definition TGraph.cxx:1544
Double_t * fX
[fNpoints] array of X points
Definition TGraph.h:47
void SetTitle(const char *title="") override
Change (i.e.
Definition TGraph.cxx:2374
virtual Int_t GetPoint(Int_t i, Double_t &x, Double_t &y) const
Get x and y values for point number i.
Definition TGraph.cxx:1511
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fName
Definition TNamed.h:32
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:376
TString & Append(const char *cs)
Definition TString.h:572
void addPoints()
Definition event_demo.C:69
RooConstVar & RooConst(double val)
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
return c2
Definition legend2.C:14
#define F(x, y, z)
Double_t Erfc(Double_t x)
Computes the complementary error function erfc(x).
Definition TMath.cxx:199
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345