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