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 <RooAbsPdf.h>
31#include <RooBinning.h>
32#include <RooDouble.h>
35#include <RooMsgService.h>
36#include <RooNumber.h>
37#include <RooRealVar.h>
38
39#include <TBuffer.h>
40#include <TList.h>
41
42#include <algorithm>
43#include <cmath>
44
45using std::endl;
46
48
49
50////////////////////////////////////////////////////////////////////////////////
51/// Constructor for an initially empty binning defining the range [xlo,xhi]
52
53RooBinning::RooBinning(double xlo, double xhi, const char* name) :
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{
65 _boundaries.reserve(1 + nbins);
66 setRange(xlo, xhi);
67 addUniform(nbins, xlo, xhi);
68}
69
70////////////////////////////////////////////////////////////////////////////////
71/// Constructor for a binning in the range[xlo,xhi] with 'nbins' bin boundaries listed
72/// array 'boundaries'
73
74RooBinning::RooBinning(Int_t nbins, const double* boundaries, const char* name) :
76{
77 // Variable bin size constructor
78 _boundaries.reserve(1 + nbins);
79 setRange(boundaries[0], boundaries[nbins]);
80 while (nbins--) addBoundary(boundaries[nbins]);
81}
82
83////////////////////////////////////////////////////////////////////////////////
84/// Copy constructor
85
87 RooAbsBinning(name), _xlo(other._xlo), _xhi(other._xhi),
88 _ownBoundLo(other._ownBoundLo), _ownBoundHi(other._ownBoundHi),
89 _nbins(other._nbins), _boundaries(other._boundaries),
90 _blo(other._blo)
91{
92}
93
94////////////////////////////////////////////////////////////////////////////////
95/// Destructor
96
98{
99 delete[] _array;
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Add bin boundary at given value
104
106{
107 auto it = std::lower_bound(_boundaries.begin(), _boundaries.end(), boundary);
108 if (_boundaries.end() != it && *it == boundary) {
109 // If boundary previously existed as range delimiter,
110 // convert to regular boundary now
111 if (boundary == _xlo) _ownBoundLo = false;
112 if (boundary == _xhi) _ownBoundHi = false;
113 return false;
114 }
115 // Add a new boundary
116 _boundaries.insert(it, boundary);
118 return true;
119}
120
121////////////////////////////////////////////////////////////////////////////////
122/// Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary
123
129
130////////////////////////////////////////////////////////////////////////////////
131/// Remove boundary at given value
132
134{
135 auto it = std::lower_bound(_boundaries.begin(), _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 + (double(i) / double(nbins)) * xhi);
162 }
163}
164
165////////////////////////////////////////////////////////////////////////////////
166/// Return sequential bin number that contains value x where bin
167/// zero is the first bin with an upper boundary above the lower bound
168/// of the range
169
170void RooBinning::binNumbers(double const *x, int *bins, std::size_t n, int coef) const
171{
172 for (std::size_t i = 0; i < n; ++i) {
173 bins[i] += RooFit::Detail::MathFuncs::binNumber(x[i], coef, _boundaries.data(), _boundaries.size(), _nbins, _blo);
174 }
175}
176
177////////////////////////////////////////////////////////////////////////////////
178/// Return the value of the nearest boundary to x
179
180double RooBinning::nearestBoundary(double x) const
181{
182 double xl;
183 double xh;
184 if (binEdges(binNumber(x), xl, xh)) return 0;
185 return (std::abs(xl - x) < std::abs(xh - x)) ? xl : xh;
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Return array of boundary values
190
191double* RooBinning::array() const
192{
193 delete[] _array;
194 _array = new double[numBoundaries()];
195 std::copy(_boundaries.begin()+_blo, _boundaries.begin()+_blo+_nbins+1, _array);
196 return _array;
197}
198
199////////////////////////////////////////////////////////////////////////////////
200/// Change the defined range associated with this binning.
201/// Bins that lie outside the new range [xlo,xhi] will not be
202/// removed, but will be 'inactive', i.e. the new 0 bin will
203/// be the first bin with an upper boundarie > xlo
204
205void RooBinning::setRange(double xlo, double xhi)
206{
207 if (xlo > xhi) {
208 coutE(InputArguments) << "RooBinning::setRange: ERROR low bound > high bound" << std::endl;
209 return;
210 }
211 // Remove previous boundaries
214 // Insert boundaries at range delimiter, if necessary
217 _xlo = xlo, _xhi = xhi;
218 // Count number of bins with new range
220}
221
222////////////////////////////////////////////////////////////////////////////////
223/// Update the internal bin counter
224
226{
227 if (_boundaries.size() <= 1) {
228 _nbins = -1;
229 return;
230 }
232 auto it = std::lower_bound(_boundaries.begin(), _boundaries.end(), _xhi);
233 if (_boundaries.begin() != it && (_boundaries.end() == it || _xhi < *it)) --it;
234 const Int_t bhi = it - _boundaries.begin();
235 _nbins = bhi - _blo;
236}
237
238////////////////////////////////////////////////////////////////////////////////
239/// Return upper and lower bound of bin 'bin'. If the return value
240/// is true an error occurred
241
242bool RooBinning::binEdges(Int_t bin, double& xlo, double& xhi) const
243{
244 if (0 > bin || bin >= _nbins) {
245 coutE(InputArguments) << "RooBinning::binEdges ERROR: bin number must be in range (0," << _nbins << ")" << std::endl;
246 return true;
247 }
248 xlo = _boundaries[bin + _blo], xhi = _boundaries[bin + _blo + 1];
249 return false;
250}
251
252////////////////////////////////////////////////////////////////////////////////
253/// Return the position of the center of bin 'bin'
254
256{
257 double xlo;
258 double xhi;
259 if (binEdges(bin, xlo, xhi)) return 0;
260 return 0.5 * (xlo + xhi);
261}
262
263////////////////////////////////////////////////////////////////////////////////
264/// Return the width of the requested bin
265
267{
268 double xlo;
269 double xhi;
270 if (binEdges(bin, xlo, xhi)) return 0;
271 return (xhi - xlo);
272}
273
274////////////////////////////////////////////////////////////////////////////////
275/// Return the lower bound of the requested bin
276
277double RooBinning::binLow(Int_t bin) const
278{
279 double xlo;
280 double xhi;
281 if (binEdges(bin, xlo, xhi)) return 0;
282 return xlo;
283}
284
285////////////////////////////////////////////////////////////////////////////////
286/// Return the upper bound of the requested bin
287
288double RooBinning::binHigh(Int_t bin) const
289{
290 double xlo;
291 double xhi;
292 if (binEdges(bin, xlo, xhi)) return 0;
293 return xhi;
294}
295
296////////////////////////////////////////////////////////////////////////////////
297/// Custom streamer that provides backward compatibility to read v1 data
298
300{
301 if (R__b.IsReading()) {
302
303 UInt_t R__s;
304 UInt_t R__c;
305 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
306 if (R__v) { }
307 switch (R__v) {
308 case 3:
309 // current version - fallthrough intended
310 case 2:
311 // older version with std::set<double> instead of
312 // std::vector<double>, apparently ROOT is clever enough to not care
313 // about set vs vector
314 R__b.ReadClassBuffer(RooBinning::Class(), this, R__v, R__s, R__c);
315 break;
316 case 1:
317 {
319 R__b >> _xlo;
320 R__b >> _xhi;
321 R__b >> _ownBoundLo;
322 R__b >> _ownBoundHi;
323 R__b >> _nbins;
324
325 _boundaries.clear();
326 // Convert TList to std::vector<double>
327 TList tmp;
328 tmp.Streamer(R__b);
329 _boundaries.reserve(tmp.GetSize());
330 for(auto * el : static_range_cast<RooDouble*>(tmp)) {
331 _boundaries.push_back(*el);
332 }
333 }
334 R__b.CheckByteCount(R__s, R__c, RooBinning::IsA());
335 break;
336 default:
337 throw std::string("Unknown class version!");
338 }
339 if (_boundaries.size() > 2) {
340 std::sort(_boundaries.begin(), _boundaries.end());
341 _boundaries.erase(std::unique(_boundaries.begin(), _boundaries.end()),
342 _boundaries.end());
343 }
344 } else {
345 R__b.WriteClassBuffer(RooBinning::Class(),this);
346 }
347}
348
350{
351 return ctx.buildCall("RooFit::Detail::MathFuncs::binNumber", var, coef, _boundaries, _boundaries.size(), _nbins, _blo);
352}
#define coutE(a)
short Version_t
Definition RtypesCore.h:65
#define ClassImp(name)
Definition Rtypes.h:374
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:110
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
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:89
double _xhi
Upper bound.
Definition RooBinning.h:80
Int_t _blo
! bin number for _xlo
Definition RooBinning.h:87
std::vector< double > _boundaries
Boundaries.
Definition RooBinning.h:85
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'.
std::string translateBinNumber(RooFit::Experimental::CodegenContext &ctx, RooAbsArg const &var, int coef) const override
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:82
double * _array
! Array of boundaries
Definition RooBinning.h:86
double binWidth(Int_t bin) const override
Return the width of the requested bin.
Int_t _nbins
Number of bins.
Definition RooBinning.h:83
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:81
double _xlo
Lower bound.
Definition RooBinning.h:79
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.
A class to maintain the context for squashing of RooFit models into code.
std::string buildCall(std::string const &funcname, Args_t const &...args)
Build the code to call the function with name funcname, passing some arguments.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
A doubly linked list.
Definition TList.h:38
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
unsigned int binNumber(double x, double coef, double const *boundaries, unsigned int nBoundaries, int nbins, int blo)
Definition MathFuncs.h:190
unsigned int rawBinNumber(double x, double const *boundaries, std::size_t nBoundaries)
Definition MathFuncs.h:178