00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "RooFit.h"
00028
00029 #include "RooHist.h"
00030 #include "RooHist.h"
00031 #include "RooHistError.h"
00032 #include "RooCurve.h"
00033 #include "RooMsgService.h"
00034
00035 #include "TH1.h"
00036 #include "TClass.h"
00037 #include "Riostream.h"
00038 #include <iomanip>
00039 #include <math.h>
00040
00041 ClassImp(RooHist)
00042 ;
00043
00044
00045
00046 RooHist::RooHist() :
00047 _nominalBinWidth(1),
00048 _nSigma(1),
00049 _entries(0),
00050 _rawEntries(0)
00051 {
00052
00053 }
00054
00055
00056
00057
00058 RooHist::RooHist(Double_t nominalBinWidth, Double_t nSigma, Double_t , Double_t ) :
00059 TGraphAsymmErrors(), _nominalBinWidth(nominalBinWidth), _nSigma(nSigma), _rawEntries(-1)
00060 {
00061
00062
00063
00064
00065
00066
00067
00068 initialize();
00069 }
00070
00071
00072
00073 RooHist::RooHist(const TH1 &data, Double_t nominalBinWidth, Double_t nSigma, RooAbsData::ErrorType etype, Double_t xErrorFrac,
00074 Bool_t correctForBinWidth, Double_t scaleFactor) :
00075 TGraphAsymmErrors(), _nominalBinWidth(nominalBinWidth), _nSigma(nSigma), _rawEntries(-1)
00076 {
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 initialize();
00088
00089 SetName(data.GetName());
00090 SetTitle(data.GetTitle());
00091
00092 if(_nominalBinWidth == 0) {
00093 const TAxis *axis= ((TH1&)data).GetXaxis();
00094 if(axis->GetNbins() > 0) _nominalBinWidth= (axis->GetXmax() - axis->GetXmin())/axis->GetNbins();
00095 }
00096
00097 setYAxisLabel(const_cast<TH1&>(data).GetYaxis()->GetTitle());
00098
00099
00100 Int_t nbin= data.GetNbinsX();
00101 for(Int_t bin= 1; bin <= nbin; bin++) {
00102 Axis_t x= data.GetBinCenter(bin);
00103 Stat_t y= data.GetBinContent(bin);
00104 Stat_t dy = data.GetBinError(bin) ;
00105 if (etype==RooAbsData::Poisson) {
00106 addBin(x,y,data.GetBinWidth(bin),xErrorFrac,scaleFactor);
00107 } else if (etype==RooAbsData::SumW2) {
00108 addBinWithError(x,y,dy,dy,data.GetBinWidth(bin),xErrorFrac,correctForBinWidth,scaleFactor);
00109 } else {
00110 addBinWithError(x,y,0,0,data.GetBinWidth(bin),xErrorFrac,correctForBinWidth,scaleFactor);
00111 }
00112 }
00113
00114 _entries+= data.GetBinContent(0) + data.GetBinContent(nbin+1);
00115 }
00116
00117
00118
00119
00120 RooHist::RooHist(const TH1 &data1, const TH1 &data2, Double_t nominalBinWidth, Double_t nSigma,
00121 RooAbsData::ErrorType etype, Double_t xErrorFrac, Bool_t efficiency, Double_t scaleFactor) :
00122 TGraphAsymmErrors(), _nominalBinWidth(nominalBinWidth), _nSigma(nSigma), _rawEntries(-1)
00123 {
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 initialize();
00136
00137 SetName(data1.GetName());
00138 SetTitle(data1.GetTitle());
00139
00140 if(_nominalBinWidth == 0) {
00141 const TAxis *axis= ((TH1&)data1).GetXaxis();
00142 if(axis->GetNbins() > 0) _nominalBinWidth= (axis->GetXmax() - axis->GetXmin())/axis->GetNbins();
00143 }
00144
00145 if (!efficiency) {
00146 setYAxisLabel(Form("Asymmetry (%s - %s)/(%s + %s)",
00147 data1.GetName(),data2.GetName(),data1.GetName(),data2.GetName()));
00148 } else {
00149 setYAxisLabel(Form("Efficiency (%s)/(%s + %s)",
00150 data1.GetName(),data1.GetName(),data2.GetName()));
00151 }
00152
00153 Int_t nbin= data1.GetNbinsX();
00154 if(data2.GetNbinsX() != nbin) {
00155 coutE(InputArguments) << "RooHist::RooHist: histograms have different number of bins" << endl;
00156 return;
00157 }
00158 for(Int_t bin= 1; bin <= nbin; bin++) {
00159 Axis_t x= data1.GetBinCenter(bin);
00160 if(fabs(data2.GetBinCenter(bin)-x)>1e-10) {
00161 coutW(InputArguments) << "RooHist::RooHist: histograms have different centers for bin " << bin << endl;
00162 }
00163 Stat_t y1= data1.GetBinContent(bin);
00164 Stat_t y2= data2.GetBinContent(bin);
00165 if (!efficiency) {
00166
00167 if (etype==RooAbsData::Poisson) {
00168 addAsymmetryBin(x,roundBin(y1),roundBin(y2),data1.GetBinWidth(bin),xErrorFrac,scaleFactor);
00169 } else if (etype==RooAbsData::SumW2) {
00170 Stat_t dy1= data1.GetBinError(bin);
00171 Stat_t dy2= data2.GetBinError(bin);
00172 addAsymmetryBinWithError(x,y1,y2,dy1,dy2,data1.GetBinWidth(bin),xErrorFrac,scaleFactor);
00173 } else {
00174 addAsymmetryBinWithError(x,y1,y2,0,0,data1.GetBinWidth(bin),xErrorFrac,scaleFactor);
00175 }
00176
00177 } else {
00178
00179 if (etype==RooAbsData::Poisson) {
00180 addEfficiencyBin(x,roundBin(y1),roundBin(y2),data1.GetBinWidth(bin),xErrorFrac,scaleFactor);
00181 } else if (etype==RooAbsData::SumW2) {
00182 Stat_t dy1= data1.GetBinError(bin);
00183 Stat_t dy2= data2.GetBinError(bin);
00184 addEfficiencyBinWithError(x,y1,y2,dy1,dy2,data1.GetBinWidth(bin),xErrorFrac,scaleFactor);
00185 } else {
00186 addEfficiencyBinWithError(x,y1,y2,0,0,data1.GetBinWidth(bin),xErrorFrac,scaleFactor);
00187 }
00188
00189 }
00190
00191 }
00192
00193 _entries= -1;
00194 }
00195
00196
00197
00198
00199 RooHist::RooHist(const RooHist& hist1, const RooHist& hist2, Double_t wgt1, Double_t wgt2,
00200 RooAbsData::ErrorType etype, Double_t xErrorFrac) : _rawEntries(-1)
00201 {
00202
00203
00204
00205
00206
00207
00208 initialize() ;
00209
00210
00211 SetName(hist1.GetName()) ;
00212 SetTitle(hist1.GetTitle()) ;
00213 _nominalBinWidth=hist1._nominalBinWidth ;
00214 _nSigma=hist1._nSigma ;
00215 setYAxisLabel(hist1.getYAxisLabel()) ;
00216
00217 if (!hist1.hasIdenticalBinning(hist2)) {
00218 coutE(InputArguments) << "RooHist::RooHist input histograms have incompatible binning, combined histogram will remain empty" << endl ;
00219 return ;
00220 }
00221
00222 if (etype==RooAbsData::Poisson) {
00223
00224
00225
00226 if (wgt1!=1.0 || wgt2 != 1.0) {
00227 coutW(InputArguments) << "RooHist::RooHist: WARNING: Poisson errors of weighted sum of two histograms is not well defined! " << endl
00228 << " Summed histogram bins will rounded to nearest integer for Poisson confidence interval calculation" << endl ;
00229 }
00230
00231
00232 Int_t i,n=hist1.GetN() ;
00233 for(i=0 ; i<n ; i++) {
00234 Double_t x1,y1,x2,y2,dx1 ;
00235 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00236 hist1.GetPoint(i,x1,y1) ;
00237 #else
00238 const_cast<RooHist&>(hist1).GetPoint(i,x1,y1) ;
00239 #endif
00240 dx1 = hist1.GetErrorX(i) ;
00241 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00242 hist2.GetPoint(i,x2,y2) ;
00243 #else
00244 const_cast<RooHist&>(hist2).GetPoint(i,x2,y2) ;
00245 #endif
00246 addBin(x1,roundBin(wgt1*y1+wgt2*y2),2*dx1/xErrorFrac,xErrorFrac) ;
00247 }
00248
00249 } else {
00250
00251
00252
00253 Int_t i,n=hist1.GetN() ;
00254 for(i=0 ; i<n ; i++) {
00255 Double_t x1,y1,x2,y2,dx1,dy1,dy2 ;
00256 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00257 hist1.GetPoint(i,x1,y1) ;
00258 #else
00259 const_cast<RooHist&>(hist1).GetPoint(i,x1,y1) ;
00260 #endif
00261 dx1 = hist1.GetErrorX(i) ;
00262 dy1 = hist1.GetErrorY(i) ;
00263 dy2 = hist2.GetErrorY(i) ;
00264 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00265 hist2.GetPoint(i,x2,y2) ;
00266 #else
00267 const_cast<RooHist&>(hist2).GetPoint(i,x2,y2) ;
00268 #endif
00269 Double_t dy = sqrt(wgt1*wgt1*dy1*dy1+wgt2*wgt2*dy2*dy2) ;
00270 addBinWithError(x1,wgt1*y1+wgt2*y2,dy,dy,2*dx1/xErrorFrac,xErrorFrac) ;
00271 }
00272 }
00273
00274 }
00275
00276
00277
00278 void RooHist::initialize()
00279 {
00280
00281
00282 SetMarkerStyle(8);
00283 _entries= 0;
00284 }
00285
00286
00287
00288 Double_t RooHist::getFitRangeNEvt() const
00289 {
00290
00291
00292
00293
00294 return (_rawEntries==-1 ? _entries : _rawEntries) ;
00295 }
00296
00297
00298
00299 Double_t RooHist::getFitRangeNEvt(Double_t xlo, Double_t xhi) const
00300 {
00301
00302
00303 Double_t sum(0) ;
00304 for (int i=0 ; i<GetN() ; i++) {
00305 Double_t x,y ;
00306
00307 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00308 GetPoint(i,x,y) ;
00309 #else
00310 const_cast<RooHist*>(this)->GetPoint(i,x,y) ;
00311 #endif
00312
00313 if (x>=xlo && x<=xhi) {
00314 sum += y ;
00315 }
00316 }
00317
00318 if (_rawEntries!=-1) {
00319 coutW(Plotting) << "RooHist::getFitRangeNEvt() WARNING: Number of normalization events associated to histogram is not equal to number of events in histogram" << endl
00320 << " due cut made in RooAbsData::plotOn() call. Automatic normalization over sub-range of plot variable assumes" << endl
00321 << " that the effect of that cut is uniform across the plot, which may be an incorrect assumption. To be sure of" << endl
00322 << " correct normalization explicit pass normalization information to RooAbsPdf::plotOn() call using Normalization()" << endl ;
00323 sum *= _rawEntries / _entries ;
00324 }
00325
00326 return sum ;
00327 }
00328
00329
00330
00331
00332 Double_t RooHist::getFitRangeBinW() const
00333 {
00334
00335 return _nominalBinWidth ;
00336 }
00337
00338
00339
00340
00341 Int_t RooHist::roundBin(Double_t y)
00342 {
00343
00344
00345
00346 if(y < 0) {
00347 coutW(Plotting) << fName << "::roundBin: rounding negative bin contents to zero: " << y << endl;
00348 return 0;
00349 }
00350 Int_t n= (Int_t)(y+0.5);
00351 if(fabs(y-n)>1e-6) {
00352 coutW(Plotting) << fName << "::roundBin: rounding non-integer bin contents: " << y << endl;
00353 }
00354 return n;
00355 }
00356
00357
00358
00359
00360 void RooHist::addBin(Axis_t binCenter, Double_t n, Double_t binWidth, Double_t xErrorFrac, Double_t scaleFactor)
00361 {
00362
00363
00364
00365
00366 if (n<0) {
00367 coutW(Plotting) << "RooHist::addBin(" << GetName() << ") WARNING: negative entry set to zero when Poisson error bars are requested" << endl ;
00368 }
00369
00370 Double_t scale= 1;
00371 if(binWidth > 0) {
00372 scale= _nominalBinWidth/binWidth;
00373 }
00374 _entries+= n;
00375 Int_t index= GetN();
00376
00377
00378 Double_t ym,yp,dx(0.5*binWidth);
00379
00380 if (fabs((double)((n-Int_t(n))>1e-5))) {
00381
00382 Double_t ym1(0),yp1(0),ym2(0),yp2(0) ;
00383 Int_t n1 = Int_t(n) ;
00384 Int_t n2 = n1+1 ;
00385 if(!RooHistError::instance().getPoissonInterval(n1,ym1,yp1,_nSigma) ||
00386 !RooHistError::instance().getPoissonInterval(n2,ym2,yp2,_nSigma)) {
00387 coutE(Plotting) << "RooHist::addBin: unable to add bin with " << n << " events" << endl;
00388 }
00389 ym = ym1 + (n-n1)*(ym2-ym1) ;
00390 yp = yp1 + (n-n1)*(yp2-yp1) ;
00391 coutW(Plotting) << "RooHist::addBin(" << GetName()
00392 << ") WARNING: non-integer bin entry " << n << " with Poisson errors, interpolating between Poisson errors of adjacent integer" << endl ;
00393 } else {
00394
00395 if(!RooHistError::instance().getPoissonInterval(Int_t(n),ym,yp,_nSigma)) {
00396 coutE(Plotting) << "RooHist::addBin: unable to add bin with " << n << " events" << endl;
00397 return;
00398 }
00399 }
00400
00401 SetPoint(index,binCenter,n*scale*scaleFactor);
00402 SetPointError(index,dx*xErrorFrac,dx*xErrorFrac,scale*(n-ym)*scaleFactor,scale*(yp-n)*scaleFactor);
00403 updateYAxisLimits(scale*yp);
00404 updateYAxisLimits(scale*ym);
00405 }
00406
00407
00408
00409
00410 void RooHist::addBinWithError(Axis_t binCenter, Double_t n, Double_t elow, Double_t ehigh, Double_t binWidth,
00411 Double_t xErrorFrac, Bool_t correctForBinWidth, Double_t scaleFactor)
00412 {
00413
00414
00415
00416
00417 Double_t scale= 1;
00418 if(binWidth > 0 && correctForBinWidth) {
00419 scale= _nominalBinWidth/binWidth;
00420 }
00421 _entries+= n;
00422 Int_t index= GetN();
00423
00424 Double_t dx(0.5*binWidth) ;
00425 SetPoint(index,binCenter,n*scale*scaleFactor);
00426 SetPointError(index,dx*xErrorFrac,dx*xErrorFrac,elow*scale*scaleFactor,ehigh*scale*scaleFactor);
00427 updateYAxisLimits(scale*(n-elow));
00428 updateYAxisLimits(scale*(n+ehigh));
00429 }
00430
00431
00432
00433
00434
00435 void RooHist::addBinWithXYError(Axis_t binCenter, Double_t n, Double_t exlow, Double_t exhigh, Double_t eylow, Double_t eyhigh,
00436 Double_t scaleFactor)
00437 {
00438
00439
00440
00441
00442 _entries+= n;
00443 Int_t index= GetN();
00444
00445 SetPoint(index,binCenter,n*scaleFactor);
00446 SetPointError(index,exlow,exhigh,eylow*scaleFactor,eyhigh*scaleFactor);
00447 updateYAxisLimits(scaleFactor*(n-eylow));
00448 updateYAxisLimits(scaleFactor*(n+eyhigh));
00449 }
00450
00451
00452
00453
00454
00455
00456 void RooHist::addAsymmetryBin(Axis_t binCenter, Int_t n1, Int_t n2, Double_t binWidth, Double_t xErrorFrac, Double_t scaleFactor)
00457 {
00458
00459
00460
00461 Double_t scale= 1;
00462 if(binWidth > 0) scale= _nominalBinWidth/binWidth;
00463 Int_t index= GetN();
00464
00465
00466 Double_t ym,yp,dx(0.5*binWidth);
00467 if(!RooHistError::instance().getBinomialIntervalAsym(n1,n2,ym,yp,_nSigma)) {
00468 coutE(Plotting) << "RooHist::addAsymmetryBin: unable to calculate binomial error for bin with " << n1 << "," << n2 << " events" << endl;
00469 return;
00470 }
00471
00472 Double_t a= (Double_t)(n1-n2)/(n1+n2);
00473 SetPoint(index,binCenter,a*scaleFactor);
00474 SetPointError(index,dx*xErrorFrac,dx*xErrorFrac,(a-ym)*scaleFactor,(yp-a)*scaleFactor);
00475 updateYAxisLimits(scale*yp);
00476 updateYAxisLimits(scale*ym);
00477 }
00478
00479
00480
00481
00482 void RooHist::addAsymmetryBinWithError(Axis_t binCenter, Double_t n1, Double_t n2, Double_t en1, Double_t en2, Double_t binWidth, Double_t xErrorFrac, Double_t scaleFactor)
00483 {
00484
00485
00486
00487 Double_t scale= 1;
00488 if(binWidth > 0) scale= _nominalBinWidth/binWidth;
00489 Int_t index= GetN();
00490
00491
00492 Double_t ym,yp,dx(0.5*binWidth);
00493 Double_t a= (Double_t)(n1-n2)/(n1+n2);
00494
00495 Double_t error = 2*sqrt( pow(en1,2)*pow(n2,2) + pow(en2,2)*pow(n1,2) ) / pow(n1+n2,2) ;
00496 ym=a-error ;
00497 yp=a+error ;
00498
00499 SetPoint(index,binCenter,a*scaleFactor);
00500 SetPointError(index,dx*xErrorFrac,dx*xErrorFrac,(a-ym)*scaleFactor,(yp-a)*scaleFactor);
00501 updateYAxisLimits(scale*yp);
00502 updateYAxisLimits(scale*ym);
00503 }
00504
00505
00506
00507
00508 void RooHist::addEfficiencyBin(Axis_t binCenter, Int_t n1, Int_t n2, Double_t binWidth, Double_t xErrorFrac, Double_t scaleFactor)
00509 {
00510
00511
00512
00513 Double_t scale= 1;
00514 if(binWidth > 0) scale= _nominalBinWidth/binWidth;
00515 Int_t index= GetN();
00516
00517 Double_t a= (Double_t)(n1)/(n1+n2);
00518
00519
00520 Double_t ym,yp,dx(0.5*binWidth);
00521 if(!RooHistError::instance().getBinomialIntervalEff(n1,n2,ym,yp,_nSigma)) {
00522 coutE(Plotting) << "RooHist::addEfficiencyBin: unable to calculate binomial error for bin with " << n1 << "," << n2 << " events" << endl;
00523 return;
00524 }
00525
00526 SetPoint(index,binCenter,a*scaleFactor);
00527 SetPointError(index,dx*xErrorFrac,dx*xErrorFrac,(a-ym)*scaleFactor,(yp-a)*scaleFactor);
00528 updateYAxisLimits(scale*yp);
00529 updateYAxisLimits(scale*ym);
00530 }
00531
00532
00533
00534
00535 void RooHist::addEfficiencyBinWithError(Axis_t binCenter, Double_t n1, Double_t n2, Double_t en1, Double_t en2, Double_t binWidth, Double_t xErrorFrac, Double_t scaleFactor)
00536 {
00537
00538
00539
00540 Double_t scale= 1;
00541 if(binWidth > 0) scale= _nominalBinWidth/binWidth;
00542 Int_t index= GetN();
00543
00544 Double_t a= (Double_t)(n1)/(n1+n2);
00545
00546 Double_t error = sqrt( pow(en1,2)*pow(n2,2) + pow(en2,2)*pow(n1,2) ) / pow(n1+n2,2) ;
00547
00548
00549 Double_t ym,yp,dx(0.5*binWidth);
00550 ym=a-error ;
00551 yp=a+error ;
00552
00553
00554 SetPoint(index,binCenter,a*scaleFactor);
00555 SetPointError(index,dx*xErrorFrac,dx*xErrorFrac,(a-ym)*scaleFactor,(yp-a)*scaleFactor);
00556 updateYAxisLimits(scale*yp);
00557 updateYAxisLimits(scale*ym);
00558 }
00559
00560
00561
00562
00563 RooHist::~RooHist()
00564 {
00565
00566 }
00567
00568
00569
00570
00571 Bool_t RooHist::hasIdenticalBinning(const RooHist& other) const
00572 {
00573
00574
00575
00576 if (GetN() != other.GetN()) {
00577 return kFALSE ;
00578 }
00579
00580
00581 Int_t i ;
00582 for (i=0 ; i<GetN() ; i++) {
00583 Double_t x1,x2,y1,y2 ;
00584
00585 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00586 GetPoint(i,x1,y1) ;
00587 other.GetPoint(i,x2,y2) ;
00588 #else
00589 const_cast<RooHist&>(*this).GetPoint(i,x1,y1) ;
00590 const_cast<RooHist&>(other).GetPoint(i,x2,y2) ;
00591 #endif
00592
00593 if (fabs(x1-x2)>1e-10) {
00594 return kFALSE ;
00595 }
00596
00597 }
00598
00599 return kTRUE ;
00600 }
00601
00602
00603
00604
00605 Bool_t RooHist::isIdentical(const RooHist& other, Double_t tol) const
00606 {
00607
00608
00609
00610
00611 TH1::AddDirectory(kFALSE) ;
00612 TH1F h_self("h_self","h_self",GetN(),0,1) ;
00613 TH1F h_other("h_other","h_other",GetN(),0,1) ;
00614 TH1::AddDirectory(kTRUE) ;
00615
00616 for (Int_t i=0 ; i<GetN() ; i++) {
00617 h_self.SetBinContent(i+1,GetY()[i]) ;
00618 h_other.SetBinContent(i+1,other.GetY()[i]) ;
00619 }
00620
00621 Double_t M = h_self.KolmogorovTest(&h_other,"M") ;
00622 if (M>tol) {
00623 Double_t kprob = h_self.KolmogorovTest(&h_other) ;
00624 cout << "RooHist::isIdentical() tolerance exceeded M=" << M << " (tol=" << tol << "), corresponding prob = " << kprob << endl ;
00625 return kFALSE ;
00626 }
00627
00628 return kTRUE ;
00629 }
00630
00631
00632
00633
00634 void RooHist::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent) const
00635 {
00636
00637
00638
00639
00640
00641
00642 RooPlotable::printMultiline(os,contents,verbose,indent);
00643 os << indent << "--- RooHist ---" << endl;
00644 Int_t n= GetN();
00645 os << indent << " Contains " << n << " bins" << endl;
00646 if(verbose) {
00647 os << indent << " Errors calculated at" << _nSigma << "-sigma CL" << endl;
00648 os << indent << " Bin Contents:" << endl;
00649 for(Int_t i= 0; i < n; i++) {
00650 os << indent << setw(3) << i << ") x= " << fX[i];
00651 if(fEXhigh[i] > 0 || fEXlow[i] > 0) {
00652 os << " +" << fEXhigh[i] << " -" << fEXlow[i];
00653 }
00654 os << " , y = " << fY[i] << " +" << fEYhigh[i] << " -" << fEYlow[i] << endl;
00655 }
00656 }
00657 }
00658
00659
00660
00661
00662 void RooHist::printName(ostream& os) const
00663 {
00664
00665
00666 os << GetName() ;
00667 }
00668
00669
00670
00671
00672 void RooHist::printTitle(ostream& os) const
00673 {
00674
00675
00676 os << GetTitle() ;
00677 }
00678
00679
00680
00681
00682 void RooHist::printClassName(ostream& os) const
00683 {
00684
00685
00686 os << IsA()->GetName() ;
00687 }
00688
00689
00690
00691
00692 RooHist* RooHist::makeResidHist(const RooCurve& curve,bool normalize) const
00693 {
00694
00695
00696
00697
00698
00699
00700 RooHist* hist = new RooHist(_nominalBinWidth) ;
00701 if (normalize) {
00702 hist->SetName(Form("pull_%s_%s",GetName(),curve.GetName())) ;
00703 hist->SetTitle(Form("Pull of %s and %s",GetTitle(),curve.GetTitle())) ;
00704 } else {
00705 hist->SetName(Form("resid_%s_%s",GetName(),curve.GetName())) ;
00706 hist->SetTitle(Form("Residual of %s and %s",GetTitle(),curve.GetTitle())) ;
00707 }
00708
00709
00710 Double_t xstart,xstop,y ;
00711 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00712 curve.GetPoint(0,xstart,y) ;
00713 curve.GetPoint(curve.GetN()-1,xstop,y) ;
00714 #else
00715 const_cast<RooCurve&>(curve).GetPoint(0,xstart,y) ;
00716 const_cast<RooCurve&>(curve).GetPoint(curve.GetN()-1,xstop,y) ;
00717 #endif
00718
00719
00720 for(Int_t i=0 ; i<GetN() ; i++) {
00721 Double_t x,point;
00722 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00723 GetPoint(i,x,point) ;
00724 #else
00725 const_cast<RooHist&>(*this).GetPoint(i,x,point) ;
00726 #endif
00727
00728
00729 if (x<xstart || x>xstop) continue ;
00730
00731 Double_t yy = point - curve.interpolate(x) ;
00732 Double_t dyl = GetErrorYlow(i) ;
00733 Double_t dyh = GetErrorYhigh(i) ;
00734 if (normalize) {
00735 Double_t norm = (yy>0?dyl:dyh);
00736 if (norm==0.) {
00737 coutW(Plotting) << "RooHist::makeResisHist(" << GetName() << ") WARNING: point " << i << " has zero error, setting residual to zero" << endl ;
00738 yy=0 ;
00739 dyh=0 ;
00740 dyl=0 ;
00741 } else {
00742 yy /= norm;
00743 dyh /= norm;
00744 dyl /= norm;
00745 }
00746 }
00747 hist->addBinWithError(x,yy,dyl,dyh);
00748 }
00749 return hist ;
00750 }