// Class RooBinning is an implements RooAbsBinning in terms
// of an array of boundary values, posing no constraints on the choice
// of binning, thus allowing variable bin sizes. Various methods allow
// the user to add single bin boundaries, mirrored pairs, or sets of
// uniformly spaced boundaries.
// END_HTML
#include "RooFit.h"
#include "Riostream.h"
#include "Riostream.h"
#include "RooBinning.h"
#include "RooDouble.h"
#include "RooAbsPdf.h"
#include "RooRealVar.h"
#include "RooNumber.h"
#include "RooMsgService.h"
ClassImp(RooBinning)
;
RooBinning::RooBinning(Double_t xlo, Double_t xhi, const char* name) :
RooAbsBinning(name),
_xlo(0),
_xhi(0),
_ownBoundLo(kTRUE),
_ownBoundHi(kTRUE),
_array(0)
{
_bIter = binIterator() ;
setRange(xlo,xhi) ;
}
RooBinning::RooBinning(Int_t nbins, Double_t xlo, Double_t xhi, const char* name) :
RooAbsBinning(name),
_xlo(0),
_xhi(0),
_ownBoundLo(kTRUE),
_ownBoundHi(kTRUE),
_array(0)
{
_bIter = binIterator() ;
setRange(xlo,xhi) ;
addUniform(nbins,xlo,xhi) ;
}
RooBinning::RooBinning(Int_t nbins, const Double_t* boundaries, const char* name) :
RooAbsBinning(name),
_xlo(0),
_xhi(0),
_ownBoundLo(kTRUE),
_ownBoundHi(kTRUE),
_array(0)
{
_bIter = binIterator() ;
setRange(boundaries[0],boundaries[nbins]) ;
while(nbins--) addBoundary(boundaries[nbins]) ;
}
RooBinning::RooBinning(const RooBinning& other, const char* name) :
RooAbsBinning(name),
_array(0)
{
_boundaries.Delete() ;
_bIter = binIterator();
other._bIter->Reset() ;
RooDouble* boundary ;
while ((boundary=(RooDouble*)other._bIter->Next())) {
addBoundary((Double_t)*boundary) ;
}
_xlo = other._xlo ;
_xhi = other._xhi ;
_ownBoundLo = other._ownBoundLo ;
_ownBoundHi = other._ownBoundHi ;
_nbins = other._nbins ;
}
RooBinning::~RooBinning()
{
delete _bIter ;
if (_array) delete[] _array ;
_boundaries.Delete() ;
}
Bool_t RooBinning::addBoundary(Double_t boundary)
{
if (hasBoundary(boundary)) {
if (boundary==_xlo) _ownBoundLo = kFALSE ;
if (boundary==_xhi) _ownBoundHi = kFALSE ;
return kFALSE ;
}
_boundaries.Add(new RooDouble(boundary)) ;
_boundaries.Sort() ;
updateBinCount() ;
return kTRUE ;
}
void RooBinning::addBoundaryPair(Double_t boundary, Double_t mirrorPoint)
{
addBoundary(boundary) ;
addBoundary(2*mirrorPoint-boundary) ;
}
Bool_t RooBinning::removeBoundary(Double_t boundary)
{
_bIter->Reset() ;
RooDouble* b ;
while((b=(RooDouble*)_bIter->Next())) {
if (((Double_t)(*b))==boundary) {
if (boundary!= _xlo && boundary != _xhi) {
_boundaries.Remove(b) ;
delete b ;
}
return kFALSE ;
}
}
return kTRUE ;
}
Bool_t RooBinning::hasBoundary(Double_t boundary)
{
_bIter->Reset() ;
RooDouble* b ;
while((b=(RooDouble*)_bIter->Next())) {
if (((Double_t)(*b))==boundary) {
return kTRUE ;
}
}
return kFALSE ;
}
void RooBinning::addUniform(Int_t nbins, Double_t xlo, Double_t xhi)
{
Int_t i ;
Double_t binw = (xhi-xlo)/nbins ;
for (i=0 ; i<=nbins ; i++)
addBoundary(xlo+i*binw) ;
}
Int_t RooBinning::binNumber(Double_t x) const
{
Int_t n(0) ;
_bIter->Reset() ;
RooDouble* b ;
while((b=(RooDouble*)_bIter->Next())) {
Double_t val = (Double_t)*b ;
if (x<val) {
return n ;
}
if (val> _xlo && n<_nbins-1) n++ ;
}
return n;
}
Int_t RooBinning::rawBinNumber(Double_t x) const
{
Int_t n(0) ;
_bIter->Reset() ;
RooDouble* b ;
while((b=(RooDouble*)_bIter->Next())) {
Double_t val = (Double_t)*b ;
if (x<val) return n>0?n-1:0 ;
n++ ;
}
return n-1;
}
Double_t RooBinning::nearestBoundary(Double_t x) const
{
Int_t bn = binNumber(x) ;
if (fabs(binLow(bn)-x)<fabs(binHigh(bn)-x)) {
return binLow(bn) ;
} else {
return binHigh(bn) ;
}
}
TIterator* RooBinning::binIterator() const
{
return _boundaries.MakeIterator() ;
}
Double_t* RooBinning::array() const
{
if (_array) delete[] _array ;
_array = new Double_t[numBoundaries()] ;
_bIter->Reset() ;
RooDouble* boundary ;
Int_t i(0) ;
while((boundary=(RooDouble*)_bIter->Next())) {
Double_t bval = (Double_t)*boundary ;
if (bval>=_xlo && bval <=_xhi) {
_array[i++] = bval ;
}
}
return _array ;
}
void RooBinning::setRange(Double_t xlo, Double_t xhi)
{
if (xlo>xhi) {
coutE(InputArguments) << "RooUniformBinning::setRange: ERROR low bound > high bound" << endl ;
return ;
}
_bIter->Reset() ;
RooDouble* b ;
while((b=(RooDouble*)_bIter->Next())) {
if (((Double_t)*b == _xlo && _ownBoundLo) ||
((Double_t)*b == _xhi && _ownBoundHi)) {
_boundaries.Remove(b) ;
delete b ;
}
}
_ownBoundLo = kFALSE ;
_ownBoundHi = kFALSE ;
if (!hasBoundary(xlo)) {
addBoundary(xlo) ;
_ownBoundLo = kTRUE ;
}
if (!hasBoundary(xhi)) {
addBoundary(xhi) ;
_ownBoundHi = kTRUE ;
}
_xlo = xlo ;
_xhi = xhi ;
updateBinCount() ;
}
void RooBinning::updateBinCount()
{
_bIter->Reset() ;
RooDouble* boundary=0 ;
Int_t i(-1) ;
while((boundary=(RooDouble*)_bIter->Next())) {
Double_t bval = (Double_t)*boundary ;
if (bval>=_xlo && bval <=_xhi) {
i++ ;
}
}
_nbins = i ;
}
Bool_t RooBinning::binEdges(Int_t bin, Double_t& xlo, Double_t& xhi) const
{
if (bin<0 || bin>= _nbins) {
coutE(InputArguments) << "RooBinning::binEdges ERROR: bin number must be in range (0," << _nbins << ")" << endl ;
return kTRUE ;
}
Int_t n(0) ;
_bIter->Reset() ;
RooDouble* b ;
while((b=(RooDouble*)_bIter->Next())) {
Double_t val = (Double_t)*b ;
if (n==bin && val>=_xlo) {
xlo = val ;
b = (RooDouble*)_bIter->Next() ;
xhi = *b ;
return kFALSE ;
}
if (val>= _xlo && n<_nbins-1) n++ ;
}
return kTRUE ;
}
Double_t RooBinning::binCenter(Int_t bin) const
{
Double_t xlo,xhi ;
if (binEdges(bin,xlo,xhi)) return 0 ;
return (xlo+xhi)/2 ;
}
Double_t RooBinning::binWidth(Int_t bin) const
{
Double_t xlo,xhi ;
if (binEdges(bin,xlo,xhi)) return 0 ;
return (xhi-xlo);
}
Double_t RooBinning::binLow(Int_t bin) const
{
Double_t xlo,xhi ;
if (binEdges(bin,xlo,xhi)) return 0 ;
return xlo ;
}
Double_t RooBinning::binHigh(Int_t bin) const
{
Double_t xlo,xhi ;
if (binEdges(bin,xlo,xhi)) return 0 ;
return xhi ;
}
Last change: Wed Jun 25 08:32:05 2008
Last generated: 2008-06-25 08:32
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.