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