Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
51RooBinning::RooBinning(double xlo, double xhi, const char* name) :
53 _xlo(0), _xhi(0), _ownBoundLo(true), _ownBoundHi(true),
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 xlo, double xhi, const char* name) :
64 _xlo(0), _xhi(0), _ownBoundLo(true), _ownBoundHi(true),
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* boundaries, const char* name) :
78 _xlo(0), _xhi(0), _ownBoundLo(true), _ownBoundHi(true),
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
109bool RooBinning::addBoundary(double boundary)
110{
111 std::vector<double>::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 = false;
117 if (boundary == _xhi) _ownBoundHi = false;
118 return false;
119 }
120 // Add a new boundary
121 _boundaries.insert(it, boundary);
123 return true;
124}
125
126////////////////////////////////////////////////////////////////////////////////
127/// Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary
128
129void RooBinning::addBoundaryPair(double boundary, double mirrorPoint)
130{
131 addBoundary(boundary);
132 addBoundary(2. * mirrorPoint - boundary);
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Remove boundary at given value
137
138bool RooBinning::removeBoundary(double boundary)
139{
140 std::vector<double>::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 false;
155 }
156 // Return error status - no boundary found
157 return true;
158}
159
160////////////////////////////////////////////////////////////////////////////////
161/// Add array of nbins uniformly sized bins in range [xlo,xhi]
162
163void RooBinning::addUniform(Int_t nbins, double xlo, double xhi)
164{
165 _boundaries.reserve(_boundaries.size() + nbins + 1);
166 for (Int_t i = 0; i <= nbins; ++i)
167 addBoundary((double(nbins - i) / double(nbins)) * xlo +
168 (double(i) / double(nbins)) * xhi);
169}
170
171namespace {
172
173inline int rawBinNumberImpl(double x, std::vector<double> const& boundaries) {
174 auto it = std::lower_bound(boundaries.begin(), boundaries.end(), x);
175 // always return valid bin number
176 while (boundaries.begin() != it &&
177 (boundaries.end() == it || boundaries.end() == it + 1 || x < *it)) --it;
178 return it - boundaries.begin();
179}
180
181}
182
183////////////////////////////////////////////////////////////////////////////////
184/// Return sequential bin number that contains value x where bin
185/// zero is the first bin with an upper boundary above the lower bound
186/// of the range
187
188void RooBinning::binNumbers(double const * x, int * bins, std::size_t n, int coef) const
189{
190 for(std::size_t i = 0; i < n; ++i) {
191 bins[i] += coef * (std::max(0, std::min(_nbins, rawBinNumberImpl(x[i], _boundaries) - _blo)));
192 }
193}
194
195////////////////////////////////////////////////////////////////////////////////
196/// Return sequential bin number that contains value x where bin
197/// zero is the first bin that is defined, regardless if that bin
198/// is outside the current defined range
199
201{
202 return rawBinNumberImpl(x, _boundaries);
203}
204
205
206////////////////////////////////////////////////////////////////////////////////
207/// Return the value of the nearest boundary to x
208
209double RooBinning::nearestBoundary(double x) const
210{
211 double xl, xh;
212 if (binEdges(binNumber(x), xl, xh)) return 0;
213 return (std::abs(xl - x) < std::abs(xh - x)) ? xl : xh;
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Return array of boundary values
218
219double* RooBinning::array() const
220{
221 delete[] _array;
222 _array = new double[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
233void RooBinning::setRange(double xlo, double xhi)
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
245 _xlo = xlo, _xhi = xhi;
246 // Count number of bins with new range
248}
249
250////////////////////////////////////////////////////////////////////////////////
251/// Update the internal bin counter
252
254{
255 if (_boundaries.size() <= 1) {
256 _nbins = -1;
257 return;
258 }
259 _blo = rawBinNumberImpl(_xlo, _boundaries);
260 std::vector<double>::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
271bool RooBinning::binEdges(Int_t bin, double& xlo, double& xhi) const
272{
273 if (0 > bin || bin >= _nbins) {
274 coutE(InputArguments) << "RooBinning::binEdges ERROR: bin number must be in range (0," << _nbins << ")" << endl;
275 return true;
276 }
277 xlo = _boundaries[bin + _blo], xhi = _boundaries[bin + _blo + 1];
278 return false;
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// Return the position of the center of bin 'bin'
283
285{
286 double 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 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
304double RooBinning::binLow(Int_t bin) const
305{
306 double 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
314double RooBinning::binHigh(Int_t bin) const
315{
316 double 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
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> instead of
335 // std::vector<double>, 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 {
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>
350 TList tmp;
351 tmp.Streamer(R__b);
352 _boundaries.reserve(tmp.GetSize());
353 for(auto * el : static_range_cast<RooDouble*>(tmp)) {
354 _boundaries.push_back(*el);
355 }
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 {
369 }
370}
#define coutE(a)
short Version_t
Definition RtypesCore.h:65
#define ClassImp(name)
Definition Rtypes.h:377
char name[80]
Definition TGX11.cxx:110
RooAbsBinning is the abstract base class for RooRealVar binning definitions.
int binNumber(double x) const
Returns the bin number corresponding to the value x.
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
double binLow(Int_t bin) const override
Return the lower bound of the requested bin.
double * array() const override
Return array of boundary values.
Int_t rawBinNumber(double x) const
Return sequential bin number that contains value x where bin zero is the first bin that is defined,...
void updateBinCount()
Update the internal bin counter.
static TClass * Class()
TClass * IsA() const override
Definition RooBinning.h:88
double _xhi
Upper bound.
Definition RooBinning.h:79
Int_t _blo
! bin number for _xlo
Definition RooBinning.h:86
std::vector< double > _boundaries
Boundaries.
Definition RooBinning.h:84
Int_t numBoundaries() const override
Return the number boundaries.
Definition RooBinning.h:38
~RooBinning() override
Destructor.
bool addBoundary(double boundary)
Add bin boundary at given value.
void binNumbers(double const *x, int *bins, std::size_t n, int coef) const override
Return sequential bin number that contains value x where bin zero is the first bin with an upper boun...
RooBinning(double xlo=-RooNumber::infinity(), double xhi=RooNumber::infinity(), const char *name=nullptr)
Constructor for an initially empty binning defining the range [xlo,xhi].
void addUniform(Int_t nBins, double xlo, double xhi)
Add array of nbins uniformly sized bins in range [xlo,xhi].
double binCenter(Int_t bin) const override
Return the position of the center of bin 'bin'.
double binHigh(Int_t bin) const override
Return the upper bound of the requested bin.
void Streamer(TBuffer &) override
Custom streamer that provides backward compatibility to read v1 data.
bool _ownBoundHi
Does the upper bound coincide with a bin boundary.
Definition RooBinning.h:81
double * _array
! Array of boundaries
Definition RooBinning.h:85
double binWidth(Int_t bin) const override
Return the width of the requested bin.
Int_t _nbins
Numer of bins.
Definition RooBinning.h:82
void addBoundaryPair(double boundary, double mirrorPoint=0)
Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary.
bool _ownBoundLo
Does the lower bound coincide with a bin boundary.
Definition RooBinning.h:80
double _xlo
Lower bound.
Definition RooBinning.h:78
bool removeBoundary(double boundary)
Remove boundary at given value.
virtual double nearestBoundary(double x) const
Return the value of the nearest boundary to x.
bool binEdges(Int_t bin, double &xlo, double &xhi) const
Return upper and lower bound of bin 'bin'.
void setRange(double xlo, double xhi) override
Change the defined range associated with this binning.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=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.
A doubly linked list.
Definition TList.h:38
void Streamer(TBuffer &) override
Stream all objects in the collection to or from the I/O buffer.
Definition TList.cxx:1191
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16