Int_t RooHistN::roundBin(Double_t y) { // Return the nearest positive integer to the input value // and print a warning if an adjustment is required. if(y < 0) { coutW(Plotting) << fName << "::roundBin: rounding negative bin contents to zero: " << y << endl; return 0; } Int_t n= (Int_t)(y+0.5); if(fabs(y-n)>1e-6) { coutW(Plotting) << fName << "::roundBin: rounding non-integer bin contents: " << y << endl; } return n; }
Double_t RooHistN::getFitRangeNEvt(Double_t xlo, Double_t xhi) const { // Calculate integral of histogram in given range Double_t sum(0) ; for (int i=0 ; i<GetN() ; i++) { Double_t x,y ; #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1) GetPoint(i,x,y) ; #else const_cast<RooHistN*>(this)->GetPoint(i,x,y) ; #endif if (x>=xlo && x<=xhi) { sum += y ; } } if (_rawEntries!=-1) { coutW(Plotting) << "RooHistN::getFitRangeNEvt() WARNING: Number of normalization events associated to histogram is not equal to number of events in histogram" << endl << " due cut made in RooAbsData::plotOn() call. Automatic normalization over sub-range of plot variable assumes" << endl << " that the effect of that cut is uniform across the plot, which may be an incorrect assumption. To be sure of" << endl << " correct normalization explicit pass normalization information to RooAbsPdf::plotOn() call using Normalization()" << endl ; sum *= _rawEntries / _entries ; } return sum ; }
RooHistN* RooHistN::makeResidHist(const RooCurve& curve,bool normalize) const { // Make histogram of (normalized) residuals w.r.t to given curve // Copy all non-content properties from hist1 RooHistN* hist = new RooHistN(_nominalBinWidth) ; hist->SetName(Form(normalize?"pull_%s_s":"resid_%s_s",GetName(),curve.GetName())) ; hist->SetTitle(Form(normalize?"Pull of %s and %s":"Residual of %s and %s",GetTitle(),curve.GetTitle())) ; // Determine range of curve Double_t xstart,xstop,y ; #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1) curve.GetPoint(0,xstart,y) ; curve.GetPoint(curve.GetN()-1,xstop,y) ; #else const_cast<RooCurve&>(curve).GetPoint(0,xstart,y) ; const_cast<RooCurve&>(curve).GetPoint(curve.GetN()-1,xstop,y) ; #endif // Add histograms, calculate Poisson confidence interval on sum value for(Int_t i=0 ; i<GetN() ; i++) { Double_t x,point; #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1) GetPoint(i,x,point) ; #else const_cast<RooHistN&>(*this).GetPoint(i,x,point) ; #endif // Only calculate pull for bins inside curve range if (x<xstart || x>xstop) continue ; Double_t y = point - curve.interpolate(x) ; Double_t dyl = GetErrorYlow(i) ; Double_t dyh = GetErrorYhigh(i) ; if (normalize) { Double_t norm = (y>0?dyh:dyl); if (norm==0.) { coutW(Plotting) << "RooHistN::makeResisHist(" << GetName() << ") WARNING: point " << i << " has zero error, setting residual to zero" << endl ; y=0 ; dyh=0 ; dyl=0 ; } else { y /= norm; dyh /= norm; dyl /= norm; } } hist->addBinWithError(x,y,dyl,dyh); } return hist ; }
RooHistN::RooHistN(const TH1 &data1, const TH1 &data2, Double_t nominalBinWidth, Double_t nSigma, Double_t xErrorFrac) : TGraphAsymmErrors(), _nominalBinWidth(nominalBinWidth), _nSigma(nSigma), _rawEntries(-1) { // Create a histogram from the asymmetry between the specified TH1 objects // which may have fixed or variable bin widths, but which must both have // the same binning. The asymmetry is calculated as (1-2)/(1+2). Error bars are // calculated using Binomial statistics. Prints a warning and rounds // any bins with non-integer contents. Use the optional parameter to // specify the confidence level in units of sigma to use for // calculating error bars. The nominal bin width specifies the // default used by addAsymmetryBin(), and is used to set the relative // normalization of bins with different widths. If not set, the // nominal bin width is calculated as range/nbins. initialize(); // copy the first input histogram's name and title SetName(data1.GetName()); SetTitle(data1.GetTitle()); // calculate our nominal bin width if necessary if(_nominalBinWidth == 0) { const TAxis *axis= ((TH1&)data1).GetXaxis(); if(axis->GetNbins() > 0) _nominalBinWidth= (axis->GetXmax() - axis->GetXmin())/axis->GetNbins(); } setYAxisLabel(Form("Asymmetry (%s - %s)/(%s + %s)", data1.GetName(),data2.GetName(),data1.GetName(),data2.GetName())); // initialize our contents from the input histogram contents Int_t nbin= data1.GetNbinsX(); if(data2.GetNbinsX() != nbin) { coutE(InputArguments) << "RooHistN::RooHistN: histograms have different number of bins" << endl; return; } for(Int_t bin= 1; bin <= nbin; bin++) { Axis_t x= data1.GetBinCenter(bin); if(fabs(data2.GetBinCenter(bin)-x)>1e-10) { coutW(InputArguments) << "RooHistN::RooHistN: histograms have different centers for bin " << bin << endl; } Stat_t y1= data1.GetBinContent(bin); Stat_t y2= data2.GetBinContent(bin); addAsymmetryBin(x,roundBin(y1),roundBin(y2),data1.GetBinWidth(bin),xErrorFrac); } // we do not have a meaningful number of entries _entries= -1; }
void coutW(const std::wstring &str) { coutW((const wchar_t *)str.c_str(), (int)str.size()); }
RooHistN::RooHistN(const RooHistN& hist1, const RooHistN& hist2, Double_t wgt1, Double_t wgt2, RooAbsData::ErrorType etype, Double_t xErrorFrac) : _rawEntries(-1){ // Create histogram as sum of two existing histograms. If Poisson errors are selected the histograms are // added and Poisson confidence intervals are calculated for the summed content. If wgt1 and wgt2 are not // 1 in this mode, a warning message is printed. If SumW2 errors are selectd the histograms are added // and the histograms errors are added in quadrature, taking the weights into account. // Initialize the histogram initialize() ; // Copy all non-content properties from hist1 SetName(hist1.GetName()) ; SetTitle(hist1.GetTitle()) ; _nominalBinWidth=hist1._nominalBinWidth ; _nSigma=hist1._nSigma ; setYAxisLabel(hist1.getYAxisLabel()) ; if (!hist1.hasIdenticalBinning(hist2)) { coutE(InputArguments) << "RooHistN::RooHistN input histograms have incompatible binning, combined histogram will remain empty" << endl ; return ; } if (etype==RooAbsData::Poisson) { // Add histograms with Poisson errors // Issue warning if weights are not 1 if (wgt1!=1.0 || wgt2 != 1.0) { coutW(InputArguments) << "RooHistN::RooHistN: WARNING: Poisson errors of weighted sum of two histograms is not well defined! " << endl << " Summed histogram bins will rounded to nearest integer for Poisson confidence interval calculation" << endl ; } // Add histograms, calculate Poisson confidence interval on sum value Int_t i,n=hist1.GetN() ; for(i=0 ; i<n ; i++) { Double_t x1,y1,x2,y2,dx1 ; #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1) hist1.GetPoint(i,x1,y1) ; #else const_cast<RooHistN&>(hist1).GetPoint(i,x1,y1) ; #endif dx1 = hist1.GetErrorX(i) ; #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1) hist2.GetPoint(i,x2,y2) ; #else const_cast<RooHistN&>(hist2).GetPoint(i,x2,y2) ; #endif addBin(x1,roundBin(wgt1*y1+wgt2*y2),2*dx1/xErrorFrac,xErrorFrac) ; } } else { // Add histograms with SumW2 errors // Add histograms, calculate combined sum-of-weights error Int_t i,n=hist1.GetN() ; for(i=0 ; i<n ; i++) { Double_t x1,y1,x2,y2,dx1,dy1,dy2 ; #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1) hist1.GetPoint(i,x1,y1) ; #else const_cast<RooHistN&>(hist1).GetPoint(i,x1,y1) ; #endif dx1 = hist1.GetErrorX(i) ; dy1 = hist1.GetErrorY(i) ; dy2 = hist2.GetErrorY(i) ; #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1) hist2.GetPoint(i,x2,y2) ; #else const_cast<RooHistN&>(hist2).GetPoint(i,x2,y2) ; #endif Double_t dy = sqrt(wgt1*wgt1*dy1*dy1+wgt2*wgt2*dy2*dy2) ; addBinWithError(x1,wgt1*y1+wgt2*y2,dy,dy,2*dx1/xErrorFrac,xErrorFrac) ; } } }