Logo ROOT   6.14/05
Reference Guide
RooBinning.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 RooBinning.cxx
19 \class RooBinning
20 \ingroup Roofitcore
21 
22 Class RooBinning is an implements RooAbsBinning in terms
23 of an array of boundary values, posing no constraints on the choice
24 of binning, thus allowing variable bin sizes. Various methods allow
25 the user to add single bin boundaries, mirrored pairs, or sets of
26 uniformly spaced boundaries.
27 **/
28 
29 #include "RooFit.h"
30 
31 #include "Riostream.h"
32 #include "RooBinning.h"
33 #include "RooDouble.h"
34 #include "RooAbsPdf.h"
35 #include "RooRealVar.h"
36 #include "RooNumber.h"
37 #include "RooMsgService.h"
38 #include "TBuffer.h"
39 #include "TList.h"
40 
41 #include <algorithm>
42 #include <cmath>
43 
44 using namespace std;
45 
47 ;
48 
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// Constructor for an initially empty binning defining the range [xlo,xhi]
52 
53 RooBinning::RooBinning(Double_t xlo, Double_t xhi, const char* name) :
54  RooAbsBinning(name),
55  _xlo(0), _xhi(0), _ownBoundLo(kTRUE), _ownBoundHi(kTRUE),
56  _array(0), _blo(0)
57 {
58  setRange(xlo,xhi);
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Constructor for a uniform binning in 'nbins' bins in the range [xlo,xhi]
63 
64 RooBinning::RooBinning(Int_t nbins, Double_t xlo, Double_t xhi, const char* name) :
65  RooAbsBinning(name),
67  _array(0), _blo(0)
68 {
69  _boundaries.reserve(1 + nbins);
70  setRange(xlo, xhi);
71  addUniform(nbins, xlo, xhi);
72 }
73 
74 ////////////////////////////////////////////////////////////////////////////////
75 /// Constructor for a binning in the range[xlo,xhi] with 'nbins' bin boundaries listed
76 /// array 'boundaries'
77 
78 RooBinning::RooBinning(Int_t nbins, const Double_t* boundaries, const char* name) :
79  RooAbsBinning(name),
81  _array(0), _blo(0)
82 {
83  // Variable bin size constructor
84  _boundaries.reserve(1 + nbins);
85  setRange(boundaries[0], boundaries[nbins]);
86  while (nbins--) addBoundary(boundaries[nbins]);
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// Copy constructor
91 
92 RooBinning::RooBinning(const RooBinning& other, const char* name) :
93  RooAbsBinning(name), _xlo(other._xlo), _xhi(other._xhi),
95  _nbins(other._nbins), _boundaries(other._boundaries), _array(0),
96  _blo(other._blo)
97 {
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Destructor
102 
104 {
105  delete[] _array;
106 }
107 
108 ////////////////////////////////////////////////////////////////////////////////
109 /// Add bin boundary at given value
110 
112 {
113  std::vector<Double_t>::iterator it =
114  std::lower_bound(_boundaries.begin(), _boundaries.end(), boundary);
115  if (_boundaries.end() != it && *it == boundary) {
116  // If boundary previously existed as range delimiter,
117  // convert to regular boundary now
118  if (boundary == _xlo) _ownBoundLo = kFALSE;
119  if (boundary == _xhi) _ownBoundHi = kFALSE;
120  return kFALSE;
121  }
122  // Add a new boundary
123  _boundaries.insert(it, boundary);
124  updateBinCount();
125  return kTRUE;
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary
130 
131 void RooBinning::addBoundaryPair(Double_t boundary, Double_t mirrorPoint)
132 {
133  addBoundary(boundary);
134  addBoundary(2. * mirrorPoint - boundary);
135 }
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 /// Remove boundary at given value
139 
141 {
142  std::vector<Double_t>::iterator it = std::lower_bound(_boundaries.begin(),
143  _boundaries.end(), boundary);
144  if (_boundaries.end() != it && *it == boundary) {
145  _boundaries.erase(it);
146  // if some moron deletes the boundaries corresponding to the current
147  // range, we need to make sure that we do not get into an undefined state,
148  // so _xlo and _xhi need to be set to some valid values
149  if (_boundaries.empty()) {
150  _xlo = _xhi = 0.;
151  } else {
152  if (boundary == _xlo) _xlo = _boundaries.front();
153  if (boundary == _xhi) _xhi = _boundaries.back();
154  }
155  updateBinCount();
156  return kFALSE;
157  }
158  // Return error status - no boundary found
159  return kTRUE;
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Check if boundary exists at given value
164 
166 {
167  return std::binary_search(_boundaries.begin(), _boundaries.end(), boundary);
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Add array of nbins uniformly sized bins in range [xlo,xhi]
172 
174 {
175  _boundaries.reserve(_boundaries.size() + nbins + 1);
176  for (Int_t i = 0; i <= nbins; ++i)
177  addBoundary((double(nbins - i) / double(nbins)) * xlo +
178  (double(i) / double(nbins)) * xhi);
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Return sequential bin number that contains value x where bin
183 /// zero is the first bin with an upper boundary above the lower bound
184 /// of the range
185 
187 {
188  return std::max(0, std::min(_nbins, rawBinNumber(x) - _blo));
189 }
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 /// Return sequential bin number that contains value x where bin
193 /// zero is the first bin that is defined, regardless if that bin
194 /// is outside the current defined range
195 
197 {
198  std::vector<Double_t>::const_iterator it = std::lower_bound(
199  _boundaries.begin(), _boundaries.end(), x);
200  // always return valid bin number
201  while (_boundaries.begin() != it &&
202  (_boundaries.end() == it || _boundaries.end() == it + 1 || x < *it)) --it;
203  return it - _boundaries.begin();
204 }
205 
206 ////////////////////////////////////////////////////////////////////////////////
207 /// Return the value of the nearest boundary to x
208 
210 {
211  Double_t xl, xh;
212  binEdges(binNumber(x), xl, xh);
213  return (std::abs(xl - x) < std::abs(xh - x)) ? xl : xh;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Return array of boundary values
218 
220 {
221  delete[] _array;
222  _array = new Double_t[numBoundaries()];
223  std::copy(_boundaries.begin()+_blo, _boundaries.begin()+_blo+_nbins+1, _array);
224  return _array;
225 }
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Change the defined range associated with this binning.
229 /// Bins that lie outside the new range [xlo,xhi] will not be
230 /// removed, but will be 'inactive', i.e. the new 0 bin will
231 /// be the first bin with an upper boundarie > xlo
232 
234 {
235  if (xlo > xhi) {
236  coutE(InputArguments) << "RooBinning::setRange: ERROR low bound > high bound" << endl;
237  return;
238  }
239  // Remove previous boundaries
242  // Insert boundaries at range delimiter, if necessary
243  _ownBoundLo = addBoundary(xlo);
244  _ownBoundHi = addBoundary(xhi);
245  _xlo = xlo, _xhi = xhi;
246  // Count number of bins with new range
247  updateBinCount();
248 }
249 
250 ////////////////////////////////////////////////////////////////////////////////
251 /// Update the internal bin counter
252 
254 {
255  if (_boundaries.size() <= 1) {
256  _nbins = -1;
257  return;
258  }
260  std::vector<Double_t>::const_iterator it = std::lower_bound(
261  _boundaries.begin(), _boundaries.end(), _xhi);
262  if (_boundaries.begin() != it && (_boundaries.end() == it || _xhi < *it)) --it;
263  const Int_t bhi = it - _boundaries.begin();
264  _nbins = bhi - _blo;
265 }
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Return upper and lower bound of bin 'bin'. If the return value
269 /// is true an error occurred
270 
272 {
273  if (0 > bin || bin >= _nbins) {
274  coutE(InputArguments) << "RooBinning::binEdges ERROR: bin number must be in range (0," << _nbins << ")" << endl;
275  return kTRUE;
276  }
277  xlo = _boundaries[bin + _blo], xhi = _boundaries[bin + _blo + 1];
278  return kFALSE;
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Return the position of the center of bin 'bin'
283 
285 {
286  Double_t xlo, xhi;
287  if (binEdges(bin, xlo, xhi)) return 0;
288  return 0.5 * (xlo + xhi);
289 }
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 /// Return the width of the requested bin
293 
295 {
296  Double_t xlo, xhi;
297  if (binEdges(bin, xlo, xhi)) return 0;
298  return (xhi - xlo);
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// Return the lower bound of the requested bin
303 
305 {
306  Double_t xlo, xhi;
307  if (binEdges(bin, xlo, xhi)) return 0;
308  return xlo;
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Return the upper bound of the requested bin
313 
315 {
316  Double_t xlo, xhi;
317  if (binEdges(bin, xlo, xhi)) return 0;
318  return xhi;
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Custom streamer that provides backward compatibility to read v1 data
323 
324 void RooBinning::Streamer(TBuffer &R__b)
325 {
326  if (R__b.IsReading()) {
327 
328  UInt_t R__s, R__c;
329  Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
330  switch (R__v) {
331  case 3:
332  // current version - fallthrough intended
333  case 2:
334  // older version with std::set<Double_t> instead of
335  // std::vector<Double_t>, apparently ROOT is clever enough to not care
336  // about set vs vector
337  R__b.ReadClassBuffer(RooBinning::Class(), this, R__v, R__s, R__c);
338  break;
339  case 1:
340  {
341  RooAbsBinning::Streamer(R__b);
342  R__b >> _xlo;
343  R__b >> _xhi;
344  R__b >> _ownBoundLo;
345  R__b >> _ownBoundHi;
346  R__b >> _nbins;
347 
348  _boundaries.clear();
349  // Convert TList to std::vector<Double_t>
350  TList tmp;
351  tmp.Streamer(R__b);
352  _boundaries.reserve(tmp.GetSize());
353  TIterator* it = tmp.MakeIterator();
354  for (RooDouble* el = (RooDouble*) it->Next(); el;
355  el = (RooDouble*) it->Next()) _boundaries.push_back(*el);
356  delete it;
357  }
358  R__b.CheckByteCount(R__s, R__c, RooBinning::IsA());
359  break;
360  default:
361  throw std::string("Unknown class version!");
362  }
363  if (_boundaries.size() > 2) {
364  std::sort(_boundaries.begin(), _boundaries.end());
365  _boundaries.erase(std::unique(_boundaries.begin(), _boundaries.end()),
366  _boundaries.end());
367  }
368  } else {
369  R__b.WriteClassBuffer(RooBinning::Class(),this);
370  }
371 }
virtual void setRange(Double_t xlo, Double_t xhi)
Change the defined range associated with this binning.
Definition: RooBinning.cxx:233
Bool_t IsReading() const
Definition: TBuffer.h:83
#define coutE(a)
Definition: RooMsgService.h:34
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
virtual Double_t * array() const
Return array of boundary values.
Definition: RooBinning.cxx:219
short Version_t
Definition: RtypesCore.h:61
Int_t _blo
Array of boundaries.
Definition: RooBinning.h:88
RooBinning(Double_t xlo=-RooNumber::infinity(), Double_t xhi=RooNumber::infinity(), const char *name=0)
Constructor for an initially empty binning defining the range [xlo,xhi].
Definition: RooBinning.cxx:53
Double_t _xlo
Definition: RooBinning.h:80
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Double_t binHigh(Int_t bin) const
Return the upper bound of the requested bin.
Definition: RooBinning.cxx:314
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
void addUniform(Int_t nBins, Double_t xlo, Double_t xhi)
Add array of nbins uniformly sized bins in range [xlo,xhi].
Definition: RooBinning.cxx:173
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual Int_t rawBinNumber(Double_t x) const
Return sequential bin number that contains value x where bin zero is the first bin that is defined...
Definition: RooBinning.cxx:196
STL namespace.
RooDouble is a minimal implementation of a TObject holding a Double_t value.
Definition: RooDouble.h:22
Bool_t addBoundary(Double_t boundary)
Add bin boundary at given value.
Definition: RooBinning.cxx:111
Iterator abstract base class.
Definition: TIterator.h:30
Int_t _nbins
Definition: RooBinning.h:84
Double_t x[n]
Definition: legend1.C:17
virtual Int_t numBoundaries() const
Definition: RooBinning.h:39
void Class()
Definition: Class.C:29
Bool_t _ownBoundHi
Definition: RooBinning.h:83
virtual Double_t nearestBoundary(Double_t x) const
Return the value of the nearest boundary to x.
Definition: RooBinning.cxx:209
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.
Definition: RooBinning.h:29
virtual Double_t binWidth(Int_t bin) const
Return the width of the requested bin.
Definition: RooBinning.cxx:294
Bool_t binEdges(Int_t bin, Double_t &xlo, Double_t &xhi) const
Return upper and lower bound of bin &#39;bin&#39;.
Definition: RooBinning.cxx:271
~RooBinning()
Destructor.
Definition: RooBinning.cxx:103
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const
Return a list iterator.
Definition: TList.cxx:718
A doubly linked list.
Definition: TList.h:44
Double_t _xhi
Definition: RooBinning.h:81
Bool_t hasBoundary(Double_t boundary)
Check if boundary exists at given value.
Definition: RooBinning.cxx:165
void updateBinCount()
Update the internal bin counter.
Definition: RooBinning.cxx:253
unsigned int UInt_t
Definition: RtypesCore.h:42
Double_t * _array
Definition: RooBinning.h:87
std::vector< Double_t > _boundaries
Definition: RooBinning.h:86
virtual Int_t binNumber(Double_t x) const
Return sequential bin number that contains value x where bin zero is the first bin with an upper boun...
Definition: RooBinning.cxx:186
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
RooAbsBinning is the abstract base class for RooRealVar binning definitions This class defines the in...
Definition: RooAbsBinning.h:26
#define ClassImp(name)
Definition: Rtypes.h:359
double Double_t
Definition: RtypesCore.h:55
virtual Double_t binLow(Int_t bin) const
Return the lower bound of the requested bin.
Definition: RooBinning.cxx:304
Bool_t removeBoundary(Double_t boundary)
Remove boundary at given value.
Definition: RooBinning.cxx:140
virtual TObject * Next()=0
void addBoundaryPair(Double_t boundary, Double_t mirrorPoint=0)
Add pair of boundaries: one at &#39;boundary&#39; and one at 2*mirrorPoint-boundary.
Definition: RooBinning.cxx:131
Bool_t _ownBoundLo
Definition: RooBinning.h:82
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
const Bool_t kTRUE
Definition: RtypesCore.h:87
virtual Double_t binCenter(Int_t bin) const
Return the position of the center of bin &#39;bin&#39;.
Definition: RooBinning.cxx:284
char name[80]
Definition: TGX11.cxx:109
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0