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