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
22Implements a 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/// Constructor for an initially empty binning defining the range [xlo,xhi]
49
50RooBinning::RooBinning(double xlo, double xhi, const char* name) :
52{
53 setRange(xlo,xhi);
54}
55
56////////////////////////////////////////////////////////////////////////////////
57/// Constructor for a uniform binning in 'nbins' bins in the range [xlo,xhi]
58
59RooBinning::RooBinning(Int_t nbins, double xlo, double xhi, const char* name) :
61{
62 _boundaries.reserve(1 + nbins);
63 setRange(xlo, xhi);
64 addUniform(nbins, xlo, xhi);
65}
66
67////////////////////////////////////////////////////////////////////////////////
68/// Constructor for a binning in the range[xlo,xhi] with 'nbins' bin boundaries listed
69/// array 'boundaries'
70
71RooBinning::RooBinning(Int_t nbins, const double* boundaries, const char* name) :
73{
74 // Variable bin size constructor
75 _boundaries.reserve(1 + nbins);
76 setRange(boundaries[0], boundaries[nbins]);
77 while (nbins--) addBoundary(boundaries[nbins]);
78}
79
80////////////////////////////////////////////////////////////////////////////////
81/// Copy constructor
82
83RooBinning::RooBinning(const RooBinning& other, const char* name) :
84 RooAbsBinning(name), _xlo(other._xlo), _xhi(other._xhi),
85 _ownBoundLo(other._ownBoundLo), _ownBoundHi(other._ownBoundHi),
86 _nbins(other._nbins), _boundaries(other._boundaries),
87 _blo(other._blo)
88{
89}
90
91////////////////////////////////////////////////////////////////////////////////
92/// Destructor
93
95{
96 delete[] _array;
97}
98
99////////////////////////////////////////////////////////////////////////////////
100/// Add bin boundary at given value
101
102bool RooBinning::addBoundary(double boundary)
103{
104 std::vector<double>::iterator it =
105 std::lower_bound(_boundaries.begin(), _boundaries.end(), boundary);
106 if (_boundaries.end() != it && *it == boundary) {
107 // If boundary previously existed as range delimiter,
108 // convert to regular boundary now
109 if (boundary == _xlo) _ownBoundLo = false;
110 if (boundary == _xhi) _ownBoundHi = false;
111 return false;
112 }
113 // Add a new boundary
114 _boundaries.insert(it, boundary);
116 return true;
117}
118
119////////////////////////////////////////////////////////////////////////////////
120/// Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary
121
122void RooBinning::addBoundaryPair(double boundary, double mirrorPoint)
123{
124 addBoundary(boundary);
125 addBoundary(2. * mirrorPoint - boundary);
126}
127
128////////////////////////////////////////////////////////////////////////////////
129/// Remove boundary at given value
130
131bool RooBinning::removeBoundary(double boundary)
132{
133 std::vector<double>::iterator it = std::lower_bound(_boundaries.begin(),
134 _boundaries.end(), boundary);
135 if (_boundaries.end() != it && *it == boundary) {
136 _boundaries.erase(it);
137 // if some moron deletes the boundaries corresponding to the current
138 // range, we need to make sure that we do not get into an undefined state,
139 // so _xlo and _xhi need to be set to some valid values
140 if (_boundaries.empty()) {
141 _xlo = _xhi = 0.;
142 } else {
143 if (boundary == _xlo) _xlo = _boundaries.front();
144 if (boundary == _xhi) _xhi = _boundaries.back();
145 }
147 return false;
148 }
149 // Return error status - no boundary found
150 return true;
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Add array of nbins uniformly sized bins in range [xlo,xhi]
155
156void RooBinning::addUniform(Int_t nbins, double xlo, double xhi)
157{
158 _boundaries.reserve(_boundaries.size() + nbins + 1);
159 for (Int_t i = 0; i <= nbins; ++i) {
160 addBoundary((double(nbins - i) / double(nbins)) * xlo + (double(i) / double(nbins)) * xhi);
161 }
162}
163
164namespace {
165
166inline int rawBinNumberImpl(double x, std::vector<double> const& boundaries) {
167 auto it = std::lower_bound(boundaries.begin(), boundaries.end(), x);
168 // always return valid bin number
169 while (boundaries.begin() != it &&
170 (boundaries.end() == it || boundaries.end() == it + 1 || x < *it)) --it;
171 return it - boundaries.begin();
172}
173
174}
175
176////////////////////////////////////////////////////////////////////////////////
177/// Return sequential bin number that contains value x where bin
178/// zero is the first bin with an upper boundary above the lower bound
179/// of the range
180
181void RooBinning::binNumbers(double const * x, int * bins, std::size_t n, int coef) const
182{
183 for(std::size_t i = 0; i < n; ++i) {
184 bins[i] += coef * (std::max(0, std::min(_nbins, rawBinNumberImpl(x[i], _boundaries) - _blo)));
185 }
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Return the value of the nearest boundary to x
190
191double RooBinning::nearestBoundary(double x) const
192{
193 double xl;
194 double 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;
270 double xhi;
271 if (binEdges(bin, xlo, xhi)) return 0;
272 return 0.5 * (xlo + xhi);
273}
274
275////////////////////////////////////////////////////////////////////////////////
276/// Return the width of the requested bin
277
279{
280 double xlo;
281 double xhi;
282 if (binEdges(bin, xlo, xhi)) return 0;
283 return (xhi - xlo);
284}
285
286////////////////////////////////////////////////////////////////////////////////
287/// Return the lower bound of the requested bin
288
289double RooBinning::binLow(Int_t bin) const
290{
291 double xlo;
292 double xhi;
293 if (binEdges(bin, xlo, xhi)) return 0;
294 return xlo;
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// Return the upper bound of the requested bin
299
300double RooBinning::binHigh(Int_t bin) const
301{
302 double xlo;
303 double xhi;
304 if (binEdges(bin, xlo, xhi)) return 0;
305 return xhi;
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// Custom streamer that provides backward compatibility to read v1 data
310
312{
313 if (R__b.IsReading()) {
314
315 UInt_t R__s;
316 UInt_t R__c;
317 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
318 if (R__v) { }
319 switch (R__v) {
320 case 3:
321 // current version - fallthrough intended
322 case 2:
323 // older version with std::set<double> instead of
324 // std::vector<double>, apparently ROOT is clever enough to not care
325 // about set vs vector
326 R__b.ReadClassBuffer(RooBinning::Class(), this, R__v, R__s, R__c);
327 break;
328 case 1:
329 {
331 R__b >> _xlo;
332 R__b >> _xhi;
333 R__b >> _ownBoundLo;
334 R__b >> _ownBoundHi;
335 R__b >> _nbins;
336
337 _boundaries.clear();
338 // Convert TList to std::vector<double>
339 TList tmp;
340 tmp.Streamer(R__b);
341 _boundaries.reserve(tmp.GetSize());
342 for(auto * el : static_range_cast<RooDouble*>(tmp)) {
343 _boundaries.push_back(*el);
344 }
345 }
346 R__b.CheckByteCount(R__s, R__c, RooBinning::IsA());
347 break;
348 default:
349 throw std::string("Unknown class version!");
350 }
351 if (_boundaries.size() > 2) {
352 std::sort(_boundaries.begin(), _boundaries.end());
353 _boundaries.erase(std::unique(_boundaries.begin(), _boundaries.end()),
354 _boundaries.end());
355 }
356 } else {
358 }
359}
#define coutE(a)
short Version_t
Definition RtypesCore.h:65
#define ClassImp(name)
Definition Rtypes.h:377
char name[80]
Definition TGX11.cxx:110
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.
Implements a RooAbsBinning in terms of an array of boundary values, posing no constraints on the choi...
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
A doubly linked list.
Definition TList.h:38
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16