68 RooCurve::RooCurve() : _showProgress(kFALSE)
82 RooCurve::RooCurve(
const RooAbsReal &f, RooAbsRealLValue &x, Double_t xlo, Double_t xhi, Int_t xbins,
83 Double_t scaleFactor,
const RooArgSet *normVars, Double_t prec, Double_t resolution,
84 Bool_t shiftToZero, WingMode wmode, Int_t nEvalError, Int_t doEEVal, Double_t eeVal,
88 _showProgress(showProg)
92 TString name(f.GetName());
94 TString title(f.GetTitle());
95 SetTitle(title.Data());
97 if(0 != strlen(f.getUnit()) || 0 != strlen(x.getUnit())) {
99 if(0 != strlen(f.getUnit())) {
100 title.Append(f.getUnit());
103 if(0 != strlen(x.getUnit())) {
105 title.Append(x.getUnit());
110 setYAxisLabel(title.Data());
112 RooAbsFunc *funcPtr = 0;
113 RooAbsFunc *rawPtr = 0;
114 funcPtr= f.bindVars(x,normVars,kTRUE);
117 if(scaleFactor != 1) {
119 funcPtr=
new RooScaledFunc(*rawPtr,scaleFactor);
121 assert(0 != funcPtr);
124 Double_t prevYMax = getYAxisMax() ;
127 list<Double_t>* hint = f.plotSamplingHint(x,xlo,xhi) ;
128 addPoints(*funcPtr,xlo,xhi,xbins+1,prec,resolution,wmode,nEvalError,doEEVal,eeVal,hint);
130 ccoutP(Plotting) << endl ;
138 int nBinsX = x.numBins();
139 for(
int i=0; i<nBinsX; ++i){
140 double xval = x.getBinning().binCenter(i);
141 addPoint(xval,(*funcPtr)(&xval)) ;
148 if(rawPtr)
delete rawPtr;
149 if (shiftToZero) shiftCurveToZero(prevYMax) ;
152 for (
int i=0 ; i<GetN() ; i++) {
153 updateYAxisLimits(fY[i]);
167 RooCurve::RooCurve(
const char *name,
const char *title,
const RooAbsFunc &func,
168 Double_t xlo, Double_t xhi, UInt_t minPoints, Double_t prec, Double_t resolution,
169 Bool_t shiftToZero, WingMode wmode, Int_t nEvalError, Int_t doEEVal, Double_t eeVal) :
170 _showProgress(kFALSE)
174 Double_t prevYMax = getYAxisMax() ;
175 addPoints(func,xlo,xhi,minPoints+1,prec,resolution,wmode,nEvalError,doEEVal,eeVal);
177 if (shiftToZero) shiftCurveToZero(prevYMax) ;
180 for (
int i=0 ; i<GetN() ; i++) {
181 updateYAxisLimits(fY[i]);
201 RooCurve::RooCurve(
const char* name,
const char* title,
const RooCurve& c1,
const RooCurve& c2, Double_t scale1, Double_t scale2) :
202 _showProgress(kFALSE)
209 deque<Double_t> pointList ;
213 Int_t i1,n1 = c1.GetN() ;
214 for (i1=0 ; i1<n1 ; i1++) {
215 c1.GetPoint(i1,x,y) ;
216 pointList.push_back(x) ;
220 Int_t i2,n2 = c2.GetN() ;
221 for (i2=0 ; i2<n2 ; i2++) {
222 c2.GetPoint(i2,x,y) ;
223 pointList.push_back(x) ;
227 sort(pointList.begin(),pointList.end()) ;
230 Double_t last(-RooNumber::infinity()) ;
231 for (
auto point : pointList) {
233 if ((point-last)>1e-10) {
235 addPoint(point,scale1*c1.interpolate(point)+scale2*c2.interpolate(point)) ;
248 RooCurve::~RooCurve()
257 void RooCurve::initialize()
271 void RooCurve::shiftCurveToZero(Double_t prevYMax)
274 Double_t minVal(1e30) ;
275 Double_t maxVal(-1e30) ;
278 for (i=1 ; i<GetN()-1 ; i++) {
281 if (y<minVal) minVal=y ;
282 if (y>maxVal) maxVal=y ;
286 for (i=1 ; i<GetN()-1 ; i++) {
289 SetPoint(i,x,y-minVal) ;
293 if (getYAxisMax()>prevYMax) {
294 Double_t newMax = maxVal - minVal ;
295 setYAxisLimits(getYAxisMin(), newMax<prevYMax ? prevYMax : newMax) ;
307 void RooCurve::addPoints(
const RooAbsFunc &func, Double_t xlo, Double_t xhi,
308 Int_t minPoints, Double_t prec, Double_t resolution, WingMode wmode,
309 Int_t numee, Bool_t doEEVal, Double_t eeVal, list<Double_t>* samplingHint)
312 if(!func.isValid()) {
313 coutE(InputArguments) << fName <<
"::addPoints: input function is not valid" << endl;
316 if(minPoints <= 0 || xhi <= xlo) {
317 coutE(InputArguments) << fName <<
"::addPoints: bad input (nothing added)" << endl;
326 minPoints = samplingHint->size() ;
330 Double_t dx= (xhi-xlo)/(minPoints-1.);
331 Double_t *yval=
new Double_t[minPoints];
335 list<Double_t>* xval = samplingHint ;
337 xval =
new list<Double_t> ;
338 for(step= 0; step < minPoints; step++) {
339 xval->push_back(xlo + step*dx) ;
344 Double_t ymax(-1e30), ymin(1e30) ;
347 for(list<Double_t>::iterator iter = xval->begin() ; iter!=xval->end() ; ++iter,++step) {
348 Double_t xx = *iter ;
349 if (step==minPoints-1) xx-=1e-15 ;
351 yval[step]= func(&xx);
353 ccoutP(Plotting) <<
"." ;
357 if (RooAbsReal::numEvalErrors()>0) {
359 coutW(Plotting) <<
"At observable [x]=" << xx <<
" " ;
360 RooAbsReal::printEvalErrors(ccoutW(Plotting),numee) ;
366 RooAbsReal::clearEvalErrorLog() ;
369 if (yval[step]>ymax) ymax=yval[step] ;
370 if (yval[step]<ymin) ymin=yval[step] ;
372 Double_t yrangeEst=(ymax-ymin) ;
375 Double_t minDx= resolution*(xhi-xlo);
378 if (wmode==Extended) {
381 addPoint(xlo-dx*1.00000001,0) ;
382 addPoint(xlo-dx,yval[0]) ;
383 }
else if (wmode==Straight) {
387 addPoint(xlo,yval[0]);
389 list<Double_t>::iterator iter2 = xval->begin() ;
395 if (iter2==xval->end()) {
401 addPoint(x2,yval[step]) ;
403 addRange(func,x1,x2,yval[step-1],yval[step],prec*yrangeEst,minDx,numee,doEEVal,eeVal);
407 addPoint(xhi,yval[minPoints-1]) ;
409 if (wmode==Extended) {
410 addPoint(xhi+dx,yval[minPoints-1]) ;
412 }
else if (wmode==Straight) {
418 if (xval != samplingHint) {
431 void RooCurve::addRange(
const RooAbsFunc& func, Double_t x1, Double_t x2,
432 Double_t y1, Double_t y2, Double_t minDy, Double_t minDx,
433 Int_t numee, Bool_t doEEVal, Double_t eeVal)
436 if (fabs(x2-x1)<1e-20) {
441 Double_t xmid= 0.5*(x1+x2);
442 Double_t ymid= func(&xmid);
444 ccoutP(Plotting) <<
"." ;
448 if (RooAbsReal::numEvalErrors()>0) {
450 coutW(Plotting) <<
"At observable [x]=" << xmid <<
" " ;
451 RooAbsReal::printEvalErrors(ccoutW(Plotting),numee) ;
457 RooAbsReal::clearEvalErrorLog() ;
460 Double_t dy= ymid - 0.5*(y1+y2);
461 if((xmid - x1 >= minDx) && fabs(dy)>0 && fabs(dy) >= minDy) {
463 addRange(func,x1,xmid,y1,ymid,minDy,minDx,numee,doEEVal,eeVal);
464 addRange(func,xmid,x2,ymid,y2,minDy,minDx,numee,doEEVal,eeVal);
476 void RooCurve::addPoint(Double_t x, Double_t y)
480 SetPoint(next, x, y);
481 updateYAxisLimits(y) ;
489 Double_t RooCurve::getFitRangeNEvt()
const {
498 Double_t RooCurve::getFitRangeNEvt(Double_t, Double_t)
const
508 Double_t RooCurve::getFitRangeBinW()
const {
516 void RooCurve::printName(ostream& os)
const
527 void RooCurve::printTitle(ostream& os)
const
536 void RooCurve::printClassName(ostream& os)
const
538 os << IsA()->GetName() ;
546 void RooCurve::printMultiline(ostream& os, Int_t , Bool_t , TString indent)
const
548 os << indent <<
"--- RooCurve ---" << endl ;
550 os << indent <<
" Contains " << n <<
" points" << endl;
551 os << indent <<
" Graph points:" << endl;
552 for(Int_t i= 0; i < n; i++) {
553 os << indent << setw(3) << i <<
") x = " << fX[i] <<
" , y = " << fY[i] << endl;
564 Double_t RooCurve::chiSquare(
const RooHist& hist, Int_t nFitParam)
const
566 Int_t i,np = hist.GetN() ;
567 Double_t x,y,eyl,eyh,exl,exh ;
570 Double_t xstart,xstop ;
572 GetPoint(0,xstart,y) ;
573 GetPoint(GetN()-1,xstop,y) ;
578 for (i=0 ; i<np ; i++) {
581 ((RooHist&)hist).GetPoint(i,x,y) ;
584 if (x<xstart || x>xstop) continue ;
586 eyl = hist.GetEYlow()[i] ;
587 eyh = hist.GetEYhigh()[i] ;
588 exl = hist.GetEXlow()[i] ;
589 exh = hist.GetEXhigh()[i] ;
592 Double_t avg = average(x-exl,x+exh) ;
596 Double_t pull = (y>avg) ? ((y-avg)/eyl) : ((y-avg)/eyh) ;
603 return chisq / (nbin-nFitParam) ;
612 Double_t RooCurve::average(Double_t xFirst, Double_t xLast)
const
615 coutE(InputArguments) <<
"RooCurve::average(" << GetName()
616 <<
") invalid range (" << xFirst <<
"," << xLast <<
")" << endl ;
621 Double_t yFirst = interpolate(xFirst,1e-10) ;
622 Double_t yLast = interpolate(xLast,1e-10) ;
625 Int_t ifirst = findPoint(xFirst,1e10) ;
626 Int_t ilast = findPoint(xLast,1e10) ;
627 Double_t xFirstPt,yFirstPt,xLastPt,yLastPt ;
628 const_cast<RooCurve&
>(*this).GetPoint(ifirst,xFirstPt,yFirstPt) ;
629 const_cast<RooCurve&
>(*this).GetPoint(ilast,xLastPt,yLastPt) ;
631 Double_t tolerance=1e-3*(xLast-xFirst) ;
634 if (ilast-ifirst==1 &&(xFirstPt-xFirst)<-1*tolerance && (xLastPt-xLast)>tolerance) {
635 return 0.5*(yFirst+yLast) ;
640 if ((xFirstPt-xFirst)<-1*tolerance) {
642 const_cast<RooCurve&
>(*this).GetPoint(ifirst,xFirstPt,yFirstPt) ;
647 if ((xLastPt-xLast)>tolerance) {
649 const_cast<RooCurve&
>(*this).GetPoint(ilast,xLastPt,yLastPt) ;
652 Double_t sum(0),x1,y1,x2,y2 ;
655 sum += (xFirstPt-xFirst)*(yFirst+yFirstPt)/2 ;
659 for (i=ifirst ; i<ilast ; i++) {
660 const_cast<RooCurve&
>(*this).GetPoint(i,x1,y1) ;
661 const_cast<RooCurve&
>(*this).GetPoint(i+1,x2,y2) ;
662 sum += (x2-x1)*(y1+y2)/2 ;
666 sum += (xLast-xLastPt)*(yLastPt+yLast)/2 ;
667 return sum/(xLast-xFirst) ;
676 Int_t RooCurve::findPoint(Double_t xvalue, Double_t tolerance)
const
678 Double_t delta(std::numeric_limits<double>::max()),x,y ;
681 for (i=0 ; i<n ; i++) {
682 ((RooCurve&)*
this).GetPoint(i,x,y) ;
683 if (fabs(xvalue-x)<delta) {
684 delta = fabs(xvalue-x) ;
689 return (delta<tolerance)?ibest:-1 ;
698 Double_t RooCurve::interpolate(Double_t xvalue, Double_t tolerance)
const
702 int ibest = findPoint(xvalue,1e10) ;
705 Double_t xbest, ybest ;
706 const_cast<RooCurve*
>(
this)->GetPoint(ibest,xbest,ybest) ;
709 if (fabs(xbest-xvalue)<tolerance) {
714 Double_t xother,yother, retVal(0) ;
720 const_cast<RooCurve*
>(
this)->GetPoint(ibest+1,xother,yother) ;
721 if (xother==xbest)
return ybest ;
722 retVal = ybest + (yother-ybest)*(xvalue-xbest)/(xother-xbest) ;
729 const_cast<RooCurve*
>(
this)->GetPoint(ibest-1,xother,yother) ;
730 if (xother==xbest)
return ybest ;
731 retVal = yother + (ybest-yother)*(xvalue-xother)/(xbest-xother) ;
745 RooCurve* RooCurve::makeErrorBand(
const vector<RooCurve*>& variations, Double_t Z)
const
747 RooCurve* band =
new RooCurve ;
748 band->SetName(Form(
"%s_errorband",GetName())) ;
749 band->SetLineWidth(1) ;
750 band->SetFillColor(kCyan) ;
751 band->SetLineColor(kCyan) ;
753 vector<double> bandLo(GetN()) ;
754 vector<double> bandHi(GetN()) ;
755 for (
int i=0 ; i<GetN() ; i++) {
756 calcBandInterval(variations,i,Z,bandLo[i],bandHi[i],kFALSE) ;
759 for (
int i=0 ; i<GetN() ; i++) {
760 band->addPoint(GetX()[i],bandLo[i]) ;
762 for (
int i=GetN()-1 ; i>=0 ; i--) {
763 band->addPoint(GetX()[i],bandHi[i]) ;
766 if(this->GetXaxis() && this->GetXaxis()->IsAlphanumeric()){
767 band->GetXaxis()->Set(this->GetXaxis()->GetNbins(),this->GetXaxis()->GetXmin(),this->GetXaxis()->GetXmax());
768 for(
int i=0; i<this->GetXaxis()->GetNbins(); ++i){
769 band->GetXaxis()->SetBinLabel(i+1,this->GetXaxis()->GetBinLabel(i+1));
784 RooCurve* RooCurve::makeErrorBand(
const vector<RooCurve*>& plusVar,
const vector<RooCurve*>& minusVar,
const TMatrixD& C, Double_t Z)
const
787 RooCurve* band =
new RooCurve ;
788 band->SetName(Form(
"%s_errorband",GetName())) ;
789 band->SetLineWidth(1) ;
790 band->SetFillColor(kCyan) ;
791 band->SetLineColor(kCyan) ;
793 vector<double> bandLo(GetN()) ;
794 vector<double> bandHi(GetN()) ;
795 for (
int i=0 ; i<GetN() ; i++) {
796 calcBandInterval(plusVar,minusVar,i,C,Z,bandLo[i],bandHi[i]) ;
799 for (
int i=0 ; i<GetN() ; i++) {
800 band->addPoint(GetX()[i],bandLo[i]) ;
802 for (
int i=GetN()-1 ; i>=0 ; i--) {
803 band->addPoint(GetX()[i],bandHi[i]) ;
807 if(this->GetXaxis() && this->GetXaxis()->IsAlphanumeric()){
808 band->GetXaxis()->Set(this->GetXaxis()->GetNbins(),this->GetXaxis()->GetXmin(),this->GetXaxis()->GetXmax());
809 for(
int i=0; i<this->GetXaxis()->GetNbins(); ++i){
810 band->GetXaxis()->SetBinLabel(i+1,this->GetXaxis()->GetBinLabel(i+1));
824 void RooCurve::calcBandInterval(
const vector<RooCurve*>& plusVar,
const vector<RooCurve*>& minusVar,Int_t i,
const TMatrixD& C, Double_t , Double_t& lo, Double_t& hi)
const
826 vector<double> y_plus(plusVar.size()), y_minus(minusVar.size()) ;
828 for (vector<RooCurve*>::const_iterator iter=plusVar.begin() ; iter!=plusVar.end() ; ++iter) {
829 y_plus[j++] = (*iter)->interpolate(GetX()[i]) ;
832 for (vector<RooCurve*>::const_iterator iter=minusVar.begin() ; iter!=minusVar.end() ; ++iter) {
833 y_minus[j++] = (*iter)->interpolate(GetX()[i]) ;
835 Double_t y_cen = GetY()[i] ;
839 TVectorD F(plusVar.size()) ;
840 for (j=0 ; j<n ; j++) {
841 F[j] = (y_plus[j]-y_minus[j])/2 ;
845 Double_t sum = F*(C*F) ;
847 lo= y_cen + sqrt(sum) ;
848 hi= y_cen - sqrt(sum) ;
855 void RooCurve::calcBandInterval(
const vector<RooCurve*>& variations,Int_t i,Double_t Z, Double_t& lo, Double_t& hi, Bool_t approxGauss)
const
857 vector<double> y(variations.size()) ;
859 for (vector<RooCurve*>::const_iterator iter=variations.begin() ; iter!=variations.end() ; ++iter) {
860 y[j++] = (*iter)->interpolate(GetX()[i]) ;
865 Double_t pvalue = TMath::Erfc(Z/sqrt(2.)) ;
866 Int_t delta = Int_t( y.size()*(pvalue)/2 + 0.5) ;
867 sort(y.begin(),y.end()) ;
869 hi = y[y.size()-delta] ;
872 Double_t sum_y(0), sum_ysq(0) ;
873 for (
unsigned int k=0 ; k<y.size() ; k++) {
875 sum_ysq += y[k]*y[k] ;
878 sum_ysq /= y.size() ;
880 Double_t rms = sqrt(sum_ysq - (sum_y*sum_y)) ;
881 lo = GetY()[i] - Z*rms ;
882 hi = GetY()[i] + Z*rms ;
893 Bool_t RooCurve::isIdentical(
const RooCurve& other, Double_t tol)
const
896 Int_t n= min(GetN(),other.GetN());
897 Double_t xmin(1e30), xmax(-1e30), ymin(1e30), ymax(-1e30) ;
898 for(Int_t i= 0; i < n; i++) {
899 if (fX[i]<xmin) xmin=fX[i] ;
900 if (fX[i]>xmax) xmax=fX[i] ;
901 if (fY[i]<ymin) ymin=fY[i] ;
902 if (fY[i]>ymax) ymax=fY[i] ;
904 Double_t Yrange=ymax-ymin ;
907 for(Int_t i= 2; i < n-2; i++) {
908 Double_t yTest = interpolate(other.fX[i],1e-10) ;
909 Double_t rdy = fabs(yTest-other.fY[i])/Yrange ;
915 cout <<
"RooCurve::isIdentical[" << i <<
"] Y tolerance exceeded (" << rdy <<
">" << tol
916 <<
"), X=" << other.fX[i] <<
"(" << fX[i] <<
")" <<
" Ytest=" << yTest <<
" Yref=" << other.fY[i] <<
" range = " << Yrange << endl ;