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
22A RooCurve is a one-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 "RooRealIntegral.h"
45#include "RooRealBinding.h"
46#include "RooScaledFunc.h"
47#include "RooMsgService.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 namespace std ;
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,
82 double scaleFactor, const RooArgSet *normVars, double prec, double resolution,
83 bool shiftToZero, WingMode wmode, Int_t nEvalError, Int_t doEEVal, double eeVal,
84 bool showProg) :
85 TGraph(),
87 _showProgress(showProg)
88{
89
90 // grab the function's name and title
91 TString name(f.GetName());
92 SetName(name.Data());
93 TString title(f.GetTitle());
94 SetTitle(title.Data());
95 // append " ( [<funit> ][/ <xunit> ])" to our y-axis label if necessary
96 if(0 != strlen(f.getUnit()) || 0 != strlen(x.getUnit())) {
97 title.Append(" ( ");
98 if(0 != strlen(f.getUnit())) {
99 title.Append(f.getUnit());
100 title.Append(" ");
101 }
102 if(0 != strlen(x.getUnit())) {
103 title.Append("/ ");
104 title.Append(x.getUnit());
105 title.Append(" ");
106 }
107 title.Append(")");
108 }
109 setYAxisLabel(title.Data());
110
111 RooAbsFunc *funcPtr = 0;
112 RooAbsFunc *rawPtr = 0;
113 funcPtr= f.bindVars(x,normVars,true);
114
115 // apply a scale factor if necessary
116 if(scaleFactor != 1) {
117 rawPtr= funcPtr;
118 funcPtr= new RooScaledFunc(*rawPtr,scaleFactor);
119 }
120 assert(0 != funcPtr);
121
122 // calculate the points to add to our curve
123 double prevYMax = getYAxisMax() ;
124 if(xbins > 0){
125 // regular mode - use the sampling hint to decide where to evaluate the pdf
126 std::unique_ptr<std::list<double>> hint{f.plotSamplingHint(x,xlo,xhi)};
127 addPoints(*funcPtr,xlo,xhi,xbins+1,prec,resolution,wmode,nEvalError,doEEVal,eeVal,hint.get());
128 if (_showProgress) {
129 ccoutP(Plotting) << endl ;
130 }
131 } else {
132 // if number of bins is set to <= 0, skip any interpolation and just evaluate the pdf at the bin centers
133 // this is useful when plotting a pdf like a histogram
134 int nBinsX = x.numBins();
135 for(int i=0; i<nBinsX; ++i){
136 double xval = x.getBinning().binCenter(i);
137 addPoint(xval,(*funcPtr)(&xval)) ;
138 }
139 }
140 initialize();
141
142 // cleanup
143 delete funcPtr;
144 if(rawPtr) delete rawPtr;
145 if (shiftToZero) shiftCurveToZero(prevYMax) ;
146
147 // Adjust limits
148 for (int i=0 ; i<GetN() ; i++) {
150 }
151 this->Sort();
152}
153
154
155
156////////////////////////////////////////////////////////////////////////////////
157/// Create a 1-dim curve of the value of the specified real-valued
158/// expression as a function of x. Use the optional precision
159/// parameter to control how precisely the smooth curve is
160/// rasterized. If shiftToZero is set, the entire curve is shifted
161/// down to make the lowest point in of the curve go through zero.
162
163RooCurve::RooCurve(const char *name, const char *title, const RooAbsFunc &func,
164 double xlo, double xhi, UInt_t minPoints, double prec, double resolution,
165 bool shiftToZero, WingMode wmode, Int_t nEvalError, Int_t doEEVal, double eeVal)
166{
167 SetName(name);
168 SetTitle(title);
169 double prevYMax = getYAxisMax() ;
170 addPoints(func,xlo,xhi,minPoints+1,prec,resolution,wmode,nEvalError,doEEVal,eeVal);
171 initialize();
172 if (shiftToZero) shiftCurveToZero(prevYMax) ;
173
174 // Adjust limits
175 for (int i=0 ; i<GetN() ; i++) {
177 }
178 this->Sort();
179}
180
181
182
183////////////////////////////////////////////////////////////////////////////////
184/// Constructor of a curve as sum of two other curves.
185/// \f[
186/// C_\mathrm{sum} = \mathrm{scale1}*c1 + \mathrm{scale2}*c2
187/// \f]
188///
189/// \param[in] name Name of the curve (to retrieve it from a plot)
190/// \param[in] title Title (for plotting).
191/// \param[in] c1 First curve.
192/// \param[in] c2 Second curve.
193/// \param[in] scale1 Scale y values for c1 by this factor.
194/// \param[in] scale2 Scale y values for c2 by this factor.
195
196RooCurve::RooCurve(const char* name, const char* title, const RooCurve& c1, const RooCurve& c2, double scale1, double scale2)
197{
198 initialize() ;
199 SetName(name) ;
200 SetTitle(title) ;
201
202 // Make deque of points in X
203 deque<double> pointList ;
204 double x,y ;
205
206 // Add X points of C1
207 Int_t i1,n1 = c1.GetN() ;
208 for (i1=0 ; i1<n1 ; i1++) {
209 c1.GetPoint(i1,x,y) ;
210 pointList.push_back(x) ;
211 }
212
213 // Add X points of C2
214 Int_t i2,n2 = c2.GetN() ;
215 for (i2=0 ; i2<n2 ; i2++) {
216 c2.GetPoint(i2,x,y) ;
217 pointList.push_back(x) ;
218 }
219
220 // Sort X points
221 sort(pointList.begin(),pointList.end()) ;
222
223 // Loop over X points
224 double last(-RooNumber::infinity()) ;
225 for (auto point : pointList) {
226
227 if ((point-last)>1e-10) {
228 // Add OR of points to new curve, skipping duplicate points within tolerance
229 addPoint(point,scale1*c1.interpolate(point)+scale2*c2.interpolate(point)) ;
230 }
231 last = point ;
232 }
233
234 this->Sort();
235}
236
237
238
239////////////////////////////////////////////////////////////////////////////////
240/// Destructor
241
243{
244}
245
246
247
248////////////////////////////////////////////////////////////////////////////////
249/// Perform initialization that is common to all curves
250
252{
253 // set default line width in pixels
254 SetLineWidth(3);
255 // set default line color
257}
258
259
260
261////////////////////////////////////////////////////////////////////////////////
262/// Find lowest point in curve and move all points in curve so that
263/// lowest point will go exactly through zero
264
265void RooCurve::shiftCurveToZero(double prevYMax)
266{
267 Int_t i ;
268 double minVal(1e30) ;
269 double maxVal(-1e30) ;
270
271 // First iteration, find current lowest point
272 for (i=1 ; i<GetN()-1 ; i++) {
273 double x,y ;
274 GetPoint(i,x,y) ;
275 if (y<minVal) minVal=y ;
276 if (y>maxVal) maxVal=y ;
277 }
278
279 // Second iteration, lower all points by minVal
280 for (i=1 ; i<GetN()-1 ; i++) {
281 double x,y ;
282 GetPoint(i,x,y) ;
283 SetPoint(i,x,y-minVal) ;
284 }
285
286 // Check if y-axis range needs readjustment
287 if (getYAxisMax()>prevYMax) {
288 double newMax = maxVal - minVal ;
289 setYAxisLimits(getYAxisMin(), newMax<prevYMax ? prevYMax : newMax) ;
290 }
291}
292
293
294
295////////////////////////////////////////////////////////////////////////////////
296/// Add points calculated with the specified function, over the range (xlo,xhi).
297/// Add at least minPoints equally spaced points, and add sufficient points so that
298/// the maximum deviation from the final straight-line segments is prec*(ymax-ymin),
299/// down to a minimum horizontal spacing of resolution*(xhi-xlo).
300
301void RooCurve::addPoints(const RooAbsFunc &func, double xlo, double xhi,
302 Int_t minPoints, double prec, double resolution, WingMode wmode,
303 Int_t numee, bool doEEVal, double eeVal, list<double>* samplingHint)
304{
305 // check the inputs
306 if(!func.isValid()) {
307 coutE(InputArguments) << fName << "::addPoints: input function is not valid" << endl;
308 return;
309 }
310 if(minPoints <= 0 || xhi <= xlo) {
311 coutE(InputArguments) << fName << "::addPoints: bad input (nothing added)" << endl;
312 return;
313 }
314
315 // Perform a coarse scan of the function to estimate its y range.
316 // Save the results so we do not have to re-evaluate at the scan points.
317
318 // Adjust minimum number of points to external sampling hint if used
319 if (samplingHint) {
320 minPoints = samplingHint->size() ;
321 }
322
323 double dx= (xhi-xlo)/(minPoints-1.);
324 std::vector<double> yval(minPoints);
325
326 // Get list of initial x values. If function provides sampling hint use that,
327 // otherwise use default binning of frame
328 std::vector<double> xval;
329 if (!samplingHint) {
330 for(int step= 0; step < minPoints; step++) {
331 xval.push_back(xlo + step*dx) ;
332 }
333 } else {
334 std::copy(samplingHint->begin(), samplingHint->end(), std::back_inserter(xval));
335 }
336
337 for (unsigned int step=0; step < xval.size(); ++step) {
338 double xx = xval[step];
339 if (step == static_cast<unsigned int>(minPoints-1))
340 xx -= 1e-9 * dx;
341
342 yval[step]= func(&xx);
343 if (_showProgress) {
344 ccoutP(Plotting) << "." ;
345 cout.flush() ;
346 }
347
349 if (numee>=0) {
350 coutW(Plotting) << "At observable [x]=" << xx << " " ;
351 RooAbsReal::printEvalErrors(ccoutW(Plotting),numee) ;
352 }
353 if (doEEVal) {
354 yval[step]=eeVal ;
355 }
356 }
358 }
359
360 const double ymax = *std::max_element(yval.begin(), yval.end());
361 const double ymin = *std::min_element(yval.begin(), yval.end());
362 double yrangeEst=(ymax-ymin) ;
363
364 // store points of the coarse scan and calculate any refinements necessary
365 double minDx= resolution*(xhi-xlo);
366 double x1,x2= xlo;
367
368 if (wmode==Extended) {
369 // Add two points to make curve jump from 0 to yval at the left end of the plotting range.
370 // This ensures that filled polygons are drawn properly. The first point needs to be to the
371 // left of the second, so it's shifted by 1/1000 more than the second.
372 addPoint(xlo-dx*1.001, 0);
373 addPoint(xlo-dx,yval[0]) ;
374 } else if (wmode==Straight) {
375 addPoint(xlo-dx*0.001,0) ;
376 }
377
378 addPoint(xlo,yval[0]);
379
380 auto iter2 = xval.begin() ;
381 x1 = *iter2 ;
382 int step=1 ;
383 while(true) {
384 x1= x2;
385 ++iter2 ;
386 if (iter2==xval.end()) {
387 break ;
388 }
389 x2= *iter2 ;
390 if (prec<0) {
391 // If precision is <0, no attempt at recursive interpolation is made
392 addPoint(x2,yval[step]) ;
393 } else {
394 addRange(func,x1,x2,yval[step-1],yval[step],prec*yrangeEst,minDx,numee,doEEVal,eeVal);
395 }
396 step++ ;
397 }
398 addPoint(xhi,yval[minPoints-1]) ;
399
400 if (wmode==Extended) {
401 // Add two points to close polygon. The order matters. Since they are sorted in x later, the second
402 // point is shifted by 1/1000 more than the second-to-last point.
403 addPoint(xhi+dx,yval[minPoints-1]) ;
404 addPoint(xhi+dx*1.001, 0);
405 } else if (wmode==Straight) {
406 addPoint(xhi+dx*0.001,0) ;
407 }
408}
409
410
411////////////////////////////////////////////////////////////////////////////////
412/// Fill the range (x1,x2) with points calculated using func(&x). No point will
413/// be added at x1, and a point will always be added at x2. The density of points
414/// will be calculated so that the maximum deviation from a straight line
415/// approximation is prec*(ymax-ymin) down to the specified minimum horizontal spacing.
416
417void RooCurve::addRange(const RooAbsFunc& func, double x1, double x2,
418 double y1, double y2, double minDy, double minDx,
419 Int_t numee, bool doEEVal, double eeVal)
420{
421 // Explicitly skip empty ranges to eliminate point duplication
422 if (std::abs(x2-x1)<1e-20) {
423 return ;
424 }
425
426 // calculate our value at the midpoint of this range
427 double xmid= 0.5*(x1+x2);
428 double ymid= func(&xmid);
429 if (_showProgress) {
430 ccoutP(Plotting) << "." ;
431 cout.flush() ;
432 }
433
435 if (numee>=0) {
436 coutW(Plotting) << "At observable [x]=" << xmid << " " ;
437 RooAbsReal::printEvalErrors(ccoutW(Plotting),numee) ;
438 }
439 if (doEEVal) {
440 ymid=eeVal ;
441 }
442 }
444
445 // test if the midpoint is sufficiently close to a straight line across this interval
446 double dy= ymid - 0.5*(y1+y2);
447 if((xmid - x1 >= minDx) && std::abs(dy)>0 && std::abs(dy) >= minDy) {
448 // fill in each subrange
449 addRange(func,x1,xmid,y1,ymid,minDy,minDx,numee,doEEVal,eeVal);
450 addRange(func,xmid,x2,ymid,y2,minDy,minDx,numee,doEEVal,eeVal);
451 }
452 else {
453 // add the endpoint
454 addPoint(x2,y2);
455 }
456}
457
458
459////////////////////////////////////////////////////////////////////////////////
460/// Add a point with the specified coordinates. Update our y-axis limits.
461
462void RooCurve::addPoint(double x, double y)
463{
464// cout << "RooCurve("<< GetName() << ") adding point at (" << x << "," << y << ")" << endl ;
465 Int_t next= GetN();
466 SetPoint(next, x, y);
468}
469
470
471////////////////////////////////////////////////////////////////////////////////
472/// Return the number of events associated with the plotable object,
473/// it is always 1 for curves
474
476 return 1;
477}
478
479
480////////////////////////////////////////////////////////////////////////////////
481/// Return the number of events associated with the plotable object,
482/// in the given range. It is always 1 for curves
483
484double RooCurve::getFitRangeNEvt(double, double) const
485{
486 return 1 ;
487}
488
489
490////////////////////////////////////////////////////////////////////////////////
491/// Get the bin width associated with this plotable object.
492/// It is alwats zero for curves
493
495 return 0 ;
496}
497
498
499
500////////////////////////////////////////////////////////////////////////////////
501
502void RooCurve::printName(ostream& os) const
503//
504{
505 // Print the name of this curve
506 os << GetName() ;
507}
508
509
510////////////////////////////////////////////////////////////////////////////////
511/// Print the title of this curve
512
513void RooCurve::printTitle(ostream& os) const
514{
515 os << GetTitle() ;
516}
517
518
519////////////////////////////////////////////////////////////////////////////////
520/// Print the class name of this curve
521
522void RooCurve::printClassName(ostream& os) const
523{
524 os << ClassName() ;
525}
526
527
528
529////////////////////////////////////////////////////////////////////////////////
530/// Print the details of this curve
531
532void RooCurve::printMultiline(ostream& os, Int_t /*contents*/, bool /*verbose*/, TString indent) const
533{
534 os << indent << "--- RooCurve ---" << endl ;
535 Int_t n= GetN();
536 os << indent << " Contains " << n << " points" << endl;
537 os << indent << " Graph points:" << endl;
538 for(Int_t i= 0; i < n; i++) {
539 os << indent << setw(3) << i << ") x = " << fX[i] << " , y = " << fY[i] << endl;
540 }
541}
542
543
544
545////////////////////////////////////////////////////////////////////////////////
546/// Calculate the chi^2/NDOF of this curve with respect to the histogram
547/// 'hist' accounting nFitParam floating parameters in case the curve
548/// was the result of a fit
549
550double RooCurve::chiSquare(const RooHist& hist, Int_t nFitParam) const
551{
552 Int_t i,np = hist.GetN() ;
553 double x,y,eyl,eyh,exl,exh ;
554
555 // Find starting and ending bin of histogram based on range of RooCurve
556 double xstart,xstop ;
557
558 GetPoint(0,xstart,y) ;
559 GetPoint(GetN()-1,xstop,y) ;
560
561 Int_t nbin(0) ;
562
564 for (i=0 ; i<np ; i++) {
565
566 // Retrieve histogram contents
567 hist.GetPoint(i,x,y) ;
568
569 // Check if point is in range of curve
570 if (x<xstart || x>xstop) continue ;
571
572 eyl = hist.GetEYlow()[i] ;
573 eyh = hist.GetEYhigh()[i] ;
574 exl = hist.GetEXlow()[i] ;
575 exh = hist.GetEXhigh()[i] ;
576
577 // Integrate function over this bin
578 double avg = average(x-exl,x+exh) ;
579
580 // Add pull^2 to chisq
581 if (y!=0) {
582 double pull = (y>avg) ? ((y-avg)/eyl) : ((y-avg)/eyh) ;
583 chisq += pull*pull ;
584 nbin++ ;
585 }
586 }
587
588 // Return chisq/nDOF
589 return chisq.Sum() / (nbin-nFitParam) ;
590}
591
592
593
594////////////////////////////////////////////////////////////////////////////////
595/// Return average curve value in [xFirst,xLast] by integrating curve between points
596/// and dividing by xLast-xFirst
597
598double RooCurve::average(double xFirst, double xLast) const
599{
600 if (xFirst>=xLast) {
601 coutE(InputArguments) << "RooCurve::average(" << GetName()
602 << ") invalid range (" << xFirst << "," << xLast << ")" << endl ;
603 return 0 ;
604 }
605
606 // Find Y values and begin and end points
607 double yFirst = interpolate(xFirst,1e-10) ;
608 double yLast = interpolate(xLast,1e-10) ;
609
610 // Find first and last mid points
611 Int_t ifirst = findPoint(xFirst,1e10) ;
612 Int_t ilast = findPoint(xLast,1e10) ;
613 double xFirstPt,yFirstPt,xLastPt,yLastPt ;
614 GetPoint(ifirst,xFirstPt,yFirstPt) ;
615 GetPoint(ilast,xLastPt,yLastPt) ;
616
617 double tolerance=1e-3*(xLast-xFirst) ;
618
619 // Handle trivial scenario -- no midway points, point only at or outside given range
620 if (ilast-ifirst==1 &&(xFirstPt-xFirst)<-1*tolerance && (xLastPt-xLast)>tolerance) {
621 return 0.5*(yFirst+yLast) ;
622 }
623
624 // If first point closest to xFirst is at xFirst or before xFirst take the next point
625 // as the first midway point
626 if ((xFirstPt-xFirst)<-1*tolerance) {
627 ifirst++ ;
628 const_cast<RooCurve&>(*this).GetPoint(ifirst,xFirstPt,yFirstPt) ;
629 }
630
631 // If last point closest to yLast is at yLast or beyond yLast the previous point
632 // as the last midway point
633 if ((xLastPt-xLast)>tolerance) {
634 ilast-- ;
635 const_cast<RooCurve&>(*this).GetPoint(ilast,xLastPt,yLastPt) ;
636 }
637
638 double sum(0),x1,y1,x2,y2 ;
639
640 // Trapezoid integration from lower edge to first midpoint
641 sum += (xFirstPt-xFirst)*(yFirst+yFirstPt)/2 ;
642
643 // Trapezoid integration between midpoints
644 Int_t i ;
645 for (i=ifirst ; i<ilast ; i++) {
646 const_cast<RooCurve&>(*this).GetPoint(i,x1,y1) ;
647 const_cast<RooCurve&>(*this).GetPoint(i+1,x2,y2) ;
648 sum += (x2-x1)*(y1+y2)/2 ;
649 }
650
651 // Trapezoid integration from last midpoint to upper edge
652 sum += (xLast-xLastPt)*(yLastPt+yLast)/2 ;
653 return sum/(xLast-xFirst) ;
654}
655
656
657
658////////////////////////////////////////////////////////////////////////////////
659/// Find the nearest point to xvalue. Return -1 if distance
660/// exceeds tolerance
661
662Int_t RooCurve::findPoint(double xvalue, double tolerance) const
663{
664 double delta(std::numeric_limits<double>::max()),x,y ;
665 Int_t i,n = GetN() ;
666 Int_t ibest(-1) ;
667 for (i=0 ; i<n ; i++) {
668 GetPoint(i,x,y);
669 if (std::abs(xvalue-x)<delta) {
670 delta = std::abs(xvalue-x) ;
671 ibest = i ;
672 }
673 }
674
675 return (delta<tolerance)?ibest:-1 ;
676}
677
678
679////////////////////////////////////////////////////////////////////////////////
680/// Return linearly interpolated value of curve at xvalue. If distance
681/// to nearest point is less than tolerance, return nearest point value
682/// instead
683
684double RooCurve::interpolate(double xvalue, double tolerance) const
685{
686 // Find best point
687 int n = GetN() ;
688 int ibest = findPoint(xvalue,1e10) ;
689
690 // Get position of best point
691 double xbest, ybest ;
692 const_cast<RooCurve*>(this)->GetPoint(ibest,xbest,ybest) ;
693
694 // Handle trivial case of being dead on
695 if (std::abs(xbest-xvalue)<tolerance) {
696 return ybest ;
697 }
698
699 // Get nearest point on other side w.r.t. xvalue
700 double xother,yother, retVal(0) ;
701 if (xbest<xvalue) {
702 if (ibest==n-1) {
703 // Value beyond end requested -- return value of last point
704 return ybest ;
705 }
706 const_cast<RooCurve*>(this)->GetPoint(ibest+1,xother,yother) ;
707 if (xother==xbest) return ybest ;
708 retVal = ybest + (yother-ybest)*(xvalue-xbest)/(xother-xbest) ;
709
710 } else {
711 if (ibest==0) {
712 // Value before 1st point requested -- return value of 1st point
713 return ybest ;
714 }
715 const_cast<RooCurve*>(this)->GetPoint(ibest-1,xother,yother) ;
716 if (xother==xbest) return ybest ;
717 retVal = yother + (ybest-yother)*(xvalue-xother)/(xbest-xother) ;
718 }
719
720 return retVal ;
721}
722
723
724
725
726////////////////////////////////////////////////////////////////////////////////
727/// Construct filled RooCurve represented error band that captures alpha% of the variations
728/// of the curves passed through argument variations, where the percentage alpha corresponds to
729/// the central interval fraction of a significance Z
730
731RooCurve* RooCurve::makeErrorBand(const vector<RooCurve*>& variations, double Z) const
732{
733 RooCurve* band = new RooCurve ;
734 band->SetName(Form("%s_errorband",GetName())) ;
735 band->SetLineWidth(1) ;
736 band->SetFillColor(kCyan) ;
737 band->SetLineColor(kCyan) ;
738
739 vector<double> bandLo(GetN()) ;
740 vector<double> bandHi(GetN()) ;
741 for (int i=0 ; i<GetN() ; i++) {
742 calcBandInterval(variations,i,Z,bandLo[i],bandHi[i],false) ;
743 }
744
745 for (int i=0 ; i<GetN() ; i++) {
746 band->addPoint(GetX()[i],bandLo[i]) ;
747 }
748 for (int i=GetN()-1 ; i>=0 ; i--) {
749 band->addPoint(GetX()[i],bandHi[i]) ;
750 }
751 // if the axis of the old graph is alphanumeric, copy the labels to the new one as well
752 if(this->GetXaxis() && this->GetXaxis()->IsAlphanumeric()){
753 band->GetXaxis()->Set(this->GetXaxis()->GetNbins(),this->GetXaxis()->GetXmin(),this->GetXaxis()->GetXmax());
754 for(int i=0; i<this->GetXaxis()->GetNbins(); ++i){
755 band->GetXaxis()->SetBinLabel(i+1,this->GetXaxis()->GetBinLabel(i+1));
756 }
757 }
758
759 return band ;
760}
761
762
763
764
765////////////////////////////////////////////////////////////////////////////////
766/// Construct filled RooCurve represented error band represent the error added in quadrature defined by the curves arguments
767/// plusVar and minusVar corresponding to one-sigma variations of each parameter. The resulting error band, combined used the correlation matrix C
768/// is multiplied with the significance parameter Z to construct the equivalent of a Z sigma error band (in Gaussian approximation)
769
770RooCurve* RooCurve::makeErrorBand(const vector<RooCurve*>& plusVar, const vector<RooCurve*>& minusVar, const TMatrixD& C, double Z) const
771{
772
773 RooCurve* band = new RooCurve ;
774 band->SetName(Form("%s_errorband",GetName())) ;
775 band->SetLineWidth(1) ;
776 band->SetFillColor(kCyan) ;
777 band->SetLineColor(kCyan) ;
778
779 vector<double> bandLo(GetN()) ;
780 vector<double> bandHi(GetN()) ;
781 for (int i=0 ; i<GetN() ; i++) {
782 calcBandInterval(plusVar,minusVar,i,C,Z,bandLo[i],bandHi[i]) ;
783 }
784
785 for (int i=0 ; i<GetN() ; i++) {
786 band->addPoint(GetX()[i],bandLo[i]) ;
787 }
788 for (int i=GetN()-1 ; i>=0 ; i--) {
789 band->addPoint(GetX()[i],bandHi[i]) ;
790 }
791
792 // if the axis of the old graph is alphanumeric, copy the labels to the new one as well
793 if(this->GetXaxis() && this->GetXaxis()->IsAlphanumeric()){
794 band->GetXaxis()->Set(this->GetXaxis()->GetNbins(),this->GetXaxis()->GetXmin(),this->GetXaxis()->GetXmax());
795 for(int i=0; i<this->GetXaxis()->GetNbins(); ++i){
796 band->GetXaxis()->SetBinLabel(i+1,this->GetXaxis()->GetBinLabel(i+1));
797 }
798 }
799
800 return band ;
801}
802
803
804
805
806
807////////////////////////////////////////////////////////////////////////////////
808/// Retrieve variation points from curves
809
810void RooCurve::calcBandInterval(const vector<RooCurve*>& plusVar, const vector<RooCurve*>& minusVar,Int_t i, const TMatrixD& C, double /*Z*/, double& lo, double& hi) const
811{
812 vector<double> y_plus(plusVar.size()), y_minus(minusVar.size()) ;
813 Int_t j(0) ;
814 for (vector<RooCurve*>::const_iterator iter=plusVar.begin() ; iter!=plusVar.end() ; ++iter) {
815 y_plus[j++] = (*iter)->interpolate(GetX()[i]) ;
816 }
817 j=0 ;
818 for (vector<RooCurve*>::const_iterator iter=minusVar.begin() ; iter!=minusVar.end() ; ++iter) {
819 y_minus[j++] = (*iter)->interpolate(GetX()[i]) ;
820 }
821 double y_cen = GetY()[i] ;
822 Int_t n = j ;
823
824 // Make vector of variations
825 TVectorD F(plusVar.size()) ;
826 for (j=0 ; j<n ; j++) {
827 F[j] = (y_plus[j]-y_minus[j])/2 ;
828 }
829
830 // Calculate error in linear approximation from variations and correlation coefficient
831 double sum = F*(C*F) ;
832
833 lo= y_cen + sqrt(sum) ;
834 hi= y_cen - sqrt(sum) ;
835}
836
837
838
839////////////////////////////////////////////////////////////////////////////////
840
841void RooCurve::calcBandInterval(const vector<RooCurve*>& variations,Int_t i,double Z, double& lo, double& hi, bool approxGauss) const
842{
843 vector<double> y(variations.size()) ;
844 Int_t j(0) ;
845 for (vector<RooCurve*>::const_iterator iter=variations.begin() ; iter!=variations.end() ; ++iter) {
846 y[j++] = (*iter)->interpolate(GetX()[i]) ;
847}
848
849 if (!approxGauss) {
850 // Construct central 68% interval from variations collected at each point
851 double pvalue = TMath::Erfc(Z/sqrt(2.)) ;
852 Int_t delta = Int_t( y.size()*(pvalue)/2 + 0.5) ;
853 sort(y.begin(),y.end()) ;
854 lo = y[delta] ;
855 hi = y[y.size()-delta] ;
856 } else {
857 // Estimate R.M.S of variations at each point and use that as Gaussian sigma
858 double sum_y(0), 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), xmax(-1e30), ymin(1e30), ymax(-1e30) ;
884 for(Int_t i= 0; i < n; i++) {
885 if (fX[i]<xmin) xmin=fX[i] ;
886 if (fX[i]>xmax) xmax=fX[i] ;
887 if (fY[i]<ymin) ymin=fY[i] ;
888 if (fY[i]>ymax) ymax=fY[i] ;
889 }
890 const double Yrange=ymax-ymin ;
891
892 bool ret(true) ;
893 for(Int_t i= 2; i < n-2; i++) {
894 double yTest = interpolate(other.fX[i],1e-10) ;
895 double rdy = std::abs(yTest-other.fY[i])/Yrange ;
896 if (rdy>tol) {
897 ret = false;
898 if(!verbose) continue;
899 cout << "RooCurve::isIdentical[" << std::setw(3) << i << "] Y tolerance exceeded (" << std::setprecision(5) << std::setw(10) << rdy << ">" << tol << "),";
900 cout << " x,y=(" << std::right << std::setw(10) << fX[i] << "," << std::setw(10) << fY[i] << ")\tref: y="
901 << std::setw(10) << other.interpolate(fX[i], 1.E-15) << ". [Nearest point from ref: ";
902 auto j = other.findPoint(fX[i], 1.E10);
903 std::cout << "j=" << j << "\tx,y=(" << std::setw(10) << other.fX[j] << "," << std::setw(10) << other.fY[j] << ") ]" << "\trange=" << Yrange << std::endl;
904 }
905 }
906
907 return ret ;
908}
909
910
#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
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2467
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
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:62
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
A RooCurve is a one-dimensional graphical representation of a real-valued function.
Definition RooCurve.h:32
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:301
void printTitle(std::ostream &os) const override
Print the title of this curve.
Definition RooCurve.cxx:513
void initialize()
Perform initialization that is common to all curves.
Definition RooCurve.cxx:251
~RooCurve() override
Destructor.
Definition RooCurve.cxx:242
double getFitRangeBinW() const override
Get the bin width associated with this plotable object.
Definition RooCurve.cxx:494
void shiftCurveToZero(double prevYMax)
Find lowest point in curve and move all points in curve so that lowest point will go exactly through ...
Definition RooCurve.cxx:265
void printName(std::ostream &os) const override
Print name of object.
Definition RooCurve.cxx:502
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Print the details of this curve.
Definition RooCurve.cxx:532
double interpolate(double x, double tolerance=1e-10) const
Return linearly interpolated value of curve at xvalue.
Definition RooCurve.cxx:684
void printClassName(std::ostream &os) const override
Print the class name of this curve.
Definition RooCurve.cxx:522
@ Extended
Definition RooCurve.h:35
@ Straight
Definition RooCurve.h:35
void addRange(const RooAbsFunc &func, double x1, double x2, double y1, double y2, double minDy, double minDx, Int_t numee=0, bool doEEVal=false, double eeVal=0.0)
Fill the range (x1,x2) with points calculated using func(&x).
Definition RooCurve.cxx:417
RooCurve()
Default constructor.
Definition RooCurve.cxx:67
bool _showProgress
! Show progress indication when adding points
Definition RooCurve.h:91
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:731
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:550
void calcBandInterval(const std::vector< RooCurve * > &variations, Int_t i, double Z, double &lo, double &hi, bool approxGauss) const
Definition RooCurve.cxx:841
double getFitRangeNEvt() const override
Return the number of events associated with the plotable object, it is always 1 for curves.
Definition RooCurve.cxx:475
void addPoint(double x, double y)
Add a point with the specified coordinates. Update our y-axis limits.
Definition RooCurve.cxx:462
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:662
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:598
A RooHist is a 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:24
Class RooPotable is a base class for objects that can be inserted into RooPlots and take advantage of...
Definition RooPlotable.h:26
void updateYAxisLimits(double y)
Definition RooPlotable.h:33
double getYAxisMin() const
Definition RooPlotable.h:41
void setYAxisLimits(double ymin, double ymax)
Definition RooPlotable.h:37
double getYAxisMax() const
Definition RooPlotable.h:42
void setYAxisLabel(const char *label)
Definition RooPlotable.h:32
Lightweight RooAbsFunction implementation that applies a constant scale factor to another RooAbsFunc.
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:851
Bool_t IsAlphanumeric() const
Definition TAxis.h:84
Double_t GetXmax() const
Definition TAxis.h:135
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:759
Double_t GetXmin() const
Definition TAxis.h:134
Int_t GetNbins() const
Definition TAxis.h:121
Double_t * GetEXlow() const override
Double_t * GetEYhigh() const override
Double_t * GetEXhigh() const override
Double_t * GetEYlow() const override
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:2325
Double_t * GetY() const
Definition TGraph.h:137
Int_t GetN() const
Definition TGraph.h:129
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:2469
Double_t * GetX() const
Definition TGraph.h:136
void SetName(const char *name="") override
Set graph name.
Definition TGraph.cxx:2364
TAxis * GetXaxis() const
Get x axis of the graph.
Definition TGraph.cxx:1550
Double_t * fX
[fNpoints] array of X points
Definition TGraph.h:47
void SetTitle(const char *title="") override
Change (i.e.
Definition TGraph.cxx:2380
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:1517
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:380
TString & Append(const char *cs)
Definition TString.h:576
void addPoints()
Definition event_demo.C:69
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