Logo ROOT  
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
22Class RooBinning is an implements RooAbsBinning in terms
23of an array of boundary values, posing no constraints on the choice
24of binning, thus allowing variable bin sizes. Various methods allow
25the user to add single bin boundaries, mirrored pairs, or sets of
26uniformly spaced boundaries.
27**/
28
29#include "Riostream.h"
30#include "RooBinning.h"
31#include "RooDouble.h"
32#include "RooAbsPdf.h"
33#include "RooRealVar.h"
34#include "RooNumber.h"
35#include "RooMsgService.h"
36#include "TBuffer.h"
37#include "TList.h"
38
39#include <algorithm>
40#include <cmath>
41
42using namespace std;
43
45;
46
47
48////////////////////////////////////////////////////////////////////////////////
49/// Constructor for an initially empty binning defining the range [xlo,xhi]
50
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
62RooBinning::RooBinning(Int_t nbins, Double_t xlo, Double_t xhi, const char* 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
76RooBinning::RooBinning(Int_t nbins, const Double_t* boundaries, const char* 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
90RooBinning::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);
123 return kTRUE;
124}
125
126////////////////////////////////////////////////////////////////////////////////
127/// Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary
128
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 }
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 if (binEdges(binNumber(x), xl, xh)) return 0;
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;
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
240 // Insert boundaries at range delimiter, if necessary
243 _xlo = xlo, _xhi = xhi;
244 // Count number of bins with new range
246}
247
248////////////////////////////////////////////////////////////////////////////////
249/// Update the internal bin counter
250
252{
253 if (_boundaries.size() <= 1) {
254 _nbins = -1;
255 return;
256 }
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
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 {
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 {
368 }
369}
#define coutE(a)
Definition: RooMsgService.h:33
short Version_t
Definition: RtypesCore.h:65
const Bool_t kFALSE
Definition: RtypesCore.h:101
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:375
char name[80]
Definition: TGX11.cxx:110
RooAbsBinning is the abstract base class for RooRealVar binning definitions.
Definition: RooAbsBinning.h:26
void Streamer(TBuffer &) override
Custom streamer implementing schema evolution between V1 and V2 persistent binnings.
Class RooBinning is an implements RooAbsBinning in terms of an array of boundary values,...
Definition: RooBinning.h:27
Bool_t hasBoundary(Double_t boundary)
Check if boundary exists at given value.
Definition: RooBinning.cxx:163
Int_t rawBinNumber(Double_t x) const override
Return sequential bin number that contains value x where bin zero is the first bin that is defined,...
Definition: RooBinning.cxx:194
void setRange(Double_t xlo, Double_t xhi) override
Change the defined range associated with this binning.
Definition: RooBinning.cxx:231
void updateBinCount()
Update the internal bin counter.
Definition: RooBinning.cxx:251
Double_t binHigh(Int_t bin) const override
Return the upper bound of the requested bin.
Definition: RooBinning.cxx:312
static TClass * Class()
Double_t binLow(Int_t bin) const override
Return the lower bound of the requested bin.
Definition: RooBinning.cxx:302
Double_t binWidth(Int_t bin) const override
Return the width of the requested bin.
Definition: RooBinning.cxx:292
TClass * IsA() const override
Definition: RooBinning.h:90
Double_t * _array
! Array of boundaries
Definition: RooBinning.h:87
Double_t _xlo
Lower bound.
Definition: RooBinning.h:80
Bool_t _ownBoundLo
Does the lower bound coincide with a bin boundary.
Definition: RooBinning.h:82
Int_t _blo
! bin number for _xlo
Definition: RooBinning.h:88
Bool_t _ownBoundHi
Does the upper bound coincide with a bin boundary.
Definition: RooBinning.h:83
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
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
Bool_t addBoundary(Double_t boundary)
Add bin boundary at given value.
Definition: RooBinning.cxx:109
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
Int_t numBoundaries() const override
Return the number boundaries.
Definition: RooBinning.h:38
Bool_t removeBoundary(Double_t boundary)
Remove boundary at given value.
Definition: RooBinning.cxx:138
~RooBinning() override
Destructor.
Definition: RooBinning.cxx:101
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 * array() const override
Return array of boundary values.
Definition: RooBinning.cxx:217
void Streamer(TBuffer &) override
Custom streamer that provides backward compatibility to read v1 data.
Definition: RooBinning.cxx:322
Int_t _nbins
Numer of bins.
Definition: RooBinning.h:84
virtual Double_t nearestBoundary(Double_t x) const
Return the value of the nearest boundary to x.
Definition: RooBinning.cxx:207
Double_t binCenter(Int_t bin) const override
Return the position of the center of bin 'bin'.
Definition: RooBinning.cxx:282
Int_t binNumber(Double_t x) const override
Return sequential bin number that contains value x where bin zero is the first bin with an upper boun...
Definition: RooBinning.cxx:184
Double_t _xhi
Upper bound.
Definition: RooBinning.h:81
std::vector< Double_t > _boundaries
Boundaries.
Definition: RooBinning.h:86
RooDouble is a minimal implementation of a TObject holding a Double_t value.
Definition: RooDouble.h:22
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
Bool_t IsReading() const
Definition: TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:184
Iterator abstract base class.
Definition: TIterator.h:30
virtual TObject * Next()=0
A doubly linked list.
Definition: TList.h:44
void Streamer(TBuffer &) override
Stream all objects in the collection to or from the I/O buffer.
Definition: TList.cxx:1191
TIterator * MakeIterator(Bool_t dir=kIterForward) const override
Return a list iterator.
Definition: TList.cxx:722
RVec< PromoteType< T > > abs(const RVec< T > &v)
Definition: RVec.hxx:1739
Double_t x[n]
Definition: legend1.C:17
@ InputArguments
Definition: RooGlobalFunc.h:64