Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
RooCrystalBall.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Authors: *
4 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
5 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
6 * *
7 * Copyright (c) 2000-2019, Regents of the University of California *
8 * and Stanford University. All rights reserved. *
9 * *
10 * Redistribution and use in source and binary forms, *
11 * with or without modification, are permitted according to the terms *
12 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
13 *****************************************************************************/
14
15// Authors of this class:
16// T. Skwarnicki:
17// - modify RooCBShape to Asymmetrical Double-Sided CB
18// Michael Wilkinson
19// - add to RooFit source
20// Jonas Rembser, CERN 02/2021:
21// - merging RooDSCBShape with RooSDSCBShape to RooCrystalBall
22// - implement possibility to have asymmetrical Gaussian core
23// - complete rewrite of evaluation and integral code to reduce code
24// duplication
25
26/** \class RooCrystalBall
27 \ingroup Roofit
28
29PDF implementing the generalized Asymmetrical Double-Sided Crystall Ball line shape.
30\f[
31 f(m;m_0,\sigma,\alpha_L,n_L,\alpha_R,n_R) =
32 \begin{cases}
33 A_L \cdot (B_L - \frac{m - m_0}{\sigma_L})^{-n_L}, & \mbox{for }\frac{m - m_0}{\sigma_L} < -\alpha_L \
34 \exp \left( - \frac{1}{2} \cdot \left[ \frac{m - m_0}{\sigma_L} \right]^2 \right), & \mbox{for }\frac{m - m_0}{\sigma_L} \leq 0 \
35 \exp \left( - \frac{1}{2} \cdot \left[ \frac{m - m_0}{\sigma_R} \right]^2 \right), & \mbox{for }\frac{m - m_0}{\sigma_R} \leq \alpha_R \
36 A_R \cdot (B_R + \frac{m - m_0}{\sigma_R})^{-n_R}, & \mbox{otherwise}, \
37 \end{cases}
38\f]
39times some normalization factor,
40where
41\f[
42 \begin{align}
43 A_i &= \left(\frac{n_i}{\left| \alpha_i \right|}\right)^{n_i} \cdot \exp\left(- \frac {\left| \alpha_i \right|^2}{2}\right) \
44 B_i &= \frac{n_i}{\left| \alpha_i \right|} - \left| \alpha_i \right| \
45 \end{align}
46\f]
47**/
48
49#include "RooCrystalBall.h"
50#include "RooHelpers.h"
51#include "TError.h"
52
53#include <cmath>
54#include <limits>
55#include <memory>
56#include <utility>
57
58
59////////////////////////////////////////////////////////////////////////////////
60/// Creates the fully parametrized crystal ball shape with asymmetric Gaussian core and asymmetric tails.
61///
62/// \param name Name that identifies the PDF in computations.
63/// \param title Title for plotting.
64/// \param x The variable of the PDF.
65/// \param x0 Location parameter of the Gaussian component.
66/// \param sigmaL Width parameter of the left side of the Gaussian component.
67/// \param sigmaR Width parameter of the right side of the Gaussian component.
68/// \param alphaL Location of transition to a power law on the left, in standard deviations away from the mean.
69/// \param nL Exponent of power-law tail on the left.
70/// \param alphaR Location of transition to a power law on the right, in standard deviations away from the mean.
71/// \param nR Exponent of power-law tail on the right.
72RooCrystalBall::RooCrystalBall(const char *name, const char *title, RooAbsReal &x, RooAbsReal &x0, RooAbsReal &sigmaL,
73 RooAbsReal &sigmaR, RooAbsReal &alphaL, RooAbsReal &nL, RooAbsReal &alphaR,
74 RooAbsReal &nR)
75 : RooAbsPdf(name, title), x_("x", "Dependent", this, x), x0_("x0", "X0", this, x0),
76 sigmaL_("sigmaL", "Left Sigma", this, sigmaL), sigmaR_("sigmaR", "Right Sigma", this, sigmaR),
77 alphaL_{"alphaL", "Left Alpha", this, alphaL}, nL_{"nL", "Left Order", this, nL},
78 alphaR_{std::make_unique<RooRealProxy>("alphaR", "Right Alpha", this, alphaR)},
79 nR_{std::make_unique<RooRealProxy>("nR", "Right Order", this, nR)}
80{
87}
88
89////////////////////////////////////////////////////////////////////////////////
90/// Create a crystal ball shape with symmetric Gaussian core and asymmetric tails (just like `RooDSCBShape`).
91///
92/// \param name Name that identifies the PDF in computations.
93/// \param title Title for plotting.
94/// \param x The variable of the PDF.
95/// \param x0 Location parameter of the Gaussian component.
96/// \param sigmaLR Width parameter of the Gaussian component.
97/// \param alphaL Location of transition to a power law on the left, in standard deviations away from the mean.
98/// \param nL Exponent of power-law tail on the left.
99/// \param alphaR Location of transition to a power law on the right, in standard deviations away from the mean.
100/// \param nR Exponent of power-law tail on the right.
102 RooAbsReal &alphaL, RooAbsReal &nL, RooAbsReal &alphaR, RooAbsReal &nR)
103 : RooAbsPdf(name, title), x_("x", "Dependent", this, x), x0_("x0", "X0", this, x0),
104 sigmaL_("sigmaL", "Left Sigma", this, sigmaLR), sigmaR_("sigmaR", "Right Sigma", this, sigmaLR),
105 alphaL_{"alphaL", "Left Alpha", this, alphaL}, nL_{"nL", "Left Order", this, nL},
106 alphaR_{std::make_unique<RooRealProxy>("alphaR", "Right Alpha", this, alphaR)},
107 nR_{std::make_unique<RooRealProxy>("nR", "Right Order", this, nR)}
108{
114}
115
116////////////////////////////////////////////////////////////////////////////////
117/// Create a crystal ball shape with symmetric Gaussian core and only a tail on
118/// one side (just like `RooCBShape`) or two symmetric tails (like `RooSDSCBShape`).
119///
120/// \param name Name that identifies the PDF in computations.
121/// \param title Title for plotting.
122/// \param x The variable of the PDF.
123/// \param x0 Location parameter of the Gaussian component.
124/// \param sigmaLR Width parameter of the Gaussian component.
125/// \param alpha Location of transition to a power law, in standard deviations away from the mean.
126/// \param n Exponent of power-law tail.
127/// \param doubleSided Whether the tail is only on one side or on both sides
129 RooAbsReal &alpha, RooAbsReal &n, bool doubleSided)
130 : RooAbsPdf(name, title), x_("x", "Dependent", this, x), x0_("x0", "X0", this, x0),
131 sigmaL_{"sigmaL", "Left Sigma", this, sigmaLR}, sigmaR_{"sigmaR", "Right Sigma", this, sigmaLR},
132 alphaL_{"alphaL", "Left Alpha", this, alpha},
133 nL_{"nL", "Left Order", this, n}
134{
135 if (doubleSided) {
136 alphaR_ = std::make_unique<RooRealProxy>("alphaR", "Right Alpha", this, alpha);
137 nR_ = std::make_unique<RooRealProxy>("nR", "Right Order", this, n);
138 }
139
142 if (doubleSided) {
143 RooHelpers::checkRangeOfParameters(this, {&alpha}, 0.0);
144 }
145}
146
147////////////////////////////////////////////////////////////////////////////////
148/// Copy a RooCrystalBall.
150 : RooAbsPdf(other, name), x_("x", this, other.x_), x0_("x0", this, other.x0_),
151 sigmaL_("sigmaL", this, other.sigmaL_),
152 sigmaR_("sigmaR", this, other.sigmaR_), alphaL_{"alphaL", this, other.alphaL_},
153 nL_{"nL", this, other.nL_},
154 alphaR_{other.alphaR_ ? std::make_unique<RooRealProxy>("alphaR", this, *other.alphaR_) : nullptr},
155 nR_{other.nR_ ? std::make_unique<RooRealProxy>("nR", this, *other.nR_) : nullptr}
156{
157}
158
159////////////////////////////////////////////////////////////////////////////////
160
161namespace {
162
163inline double evaluateCrystalBallTail(double t, double alpha, double n)
164{
165 double a = std::pow(n / alpha, n) * std::exp(-0.5 * alpha * alpha);
166 double b = n / alpha - alpha;
167
168 return a / std::pow(b - t, n);
169}
170
171inline double integrateGaussian(double sigmaL, double sigmaR, double tmin, double tmax)
172{
173 constexpr double sqrtPiOver2 = 1.2533141373;
174 constexpr double sqrt2 = 1.4142135624;
175
176 const double sigmaMin = tmin < 0 ? sigmaL : sigmaR;
177 const double sigmaMax = tmax < 0 ? sigmaL : sigmaR;
178
179 return sqrtPiOver2 * (sigmaMax * std::erf(tmax / sqrt2) - sigmaMin * std::erf(tmin / sqrt2));
180}
181
182inline double integrateTailLogVersion(double sigma, double alpha, double n, double tmin, double tmax)
183{
184 double a = std::pow(n / alpha, n) * exp(-0.5 * alpha * alpha);
185 double b = n / alpha - alpha;
186
187 return a * sigma * (log(b - tmin) - log(b - tmax));
188}
189
190inline double integrateTailRegular(double sigma, double alpha, double n, double tmin, double tmax)
191{
192 double a = std::pow(n / alpha, n) * exp(-0.5 * alpha * alpha);
193 double b = n / alpha - alpha;
194
195 return a * sigma / (1.0 - n) * (1.0 / (std::pow(b - tmin, n - 1.0)) - 1.0 / (std::pow(b - tmax, n - 1.0)));
196}
197
198} // namespace
199
200////////////////////////////////////////////////////////////////////////////////
201
203{
204 const double x = x_;
205 const double x0 = x0_;
206 const double sigmaL = std::abs(sigmaL_);
207 const double sigmaR = std::abs(sigmaR_);
208 double alphaL = std::abs(alphaL_);
209 double nL = nL_;
210 double alphaR = alphaR_ ? std::abs(*alphaR_) : std::numeric_limits<double>::infinity();
211 double nR = nR_ ? *nR_ : 0.0;
212
213 // If alphaL is negative, then the tail will be on the right side.
214 // Like this, we follow the convention established by RooCBShape.
215 if(!alphaR_ && alphaL_ < 0.0) {
216 std::swap(alphaL, alphaR);
217 std::swap(nL, nR);
218 }
219
220 const double t = (x - x0) / (x < x0 ? sigmaL : sigmaR);
221
222 if (t < -alphaL) {
224 } else if (t <= alphaR) {
225 return std::exp(-0.5 * t * t);
226 } else {
227 return evaluateCrystalBallTail(-t, alphaR, nR);
228 }
229}
230
231////////////////////////////////////////////////////////////////////////////////
232
233Int_t RooCrystalBall::getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char * /*rangeName*/) const
234{
235 return matchArgs(allVars, analVars, x_) ? 1 : 0;
236}
237
238////////////////////////////////////////////////////////////////////////////////
239
240double RooCrystalBall::analyticalIntegral(Int_t code, const char *rangeName) const
241{
242 R__ASSERT(code == 1);
243
244 const double x0 = x0_;
245 const double sigmaL = std::abs(sigmaL_);
246 const double sigmaR = std::abs(sigmaR_);
247 double alphaL = std::abs(alphaL_);
248 double nL = nL_;
249 double alphaR = alphaR_ ? std::abs(*alphaR_) : std::numeric_limits<double>::infinity();
250 double nR = nR_ ? *nR_ : 0.0;
251
252 // If alphaL is negative, then the tail will be on the right side.
253 // Like this, we follow the convention established by RooCBShape.
254 if(!alphaR_ && alphaL_ < 0.0) {
255 std::swap(alphaL, alphaR);
256 std::swap(nL, nR);
257 }
258
259 constexpr double switchToLogThreshold = 1.0e-05;
260
261 const double xmin = x_.min(rangeName);
262 const double xmax = x_.max(rangeName);
263 const double tmin = (xmin - x0) / (xmin < x0 ? sigmaL : sigmaR);
264 const double tmax = (xmax - x0) / (xmax < x0 ? sigmaL : sigmaR);
265
266 double result = 0.0;
267
268 if (tmin < -alphaL) {
270 result += integrateTailL(sigmaL, alphaL, nL, tmin, std::min(tmax, -alphaL));
271 }
272 if (tmax > alphaR) {
274 result += integrateTailR(sigmaR, alphaR, nR, -tmax, std::min(-tmin, -alphaR));
275 }
277 result += integrateGaussian(sigmaL, sigmaR, std::max(tmin, -alphaL), std::min(tmax, alphaR));
278 }
279
280 return result;
281}
282
283////////////////////////////////////////////////////////////////////////////////
284/// Advertise that we know the maximum of self for given (m0,alpha,n,sigma).
285
287{
288 RooArgSet dummy;
289 return matchArgs(vars, dummy, x_) ? 1 : 0;
290}
291
292////////////////////////////////////////////////////////////////////////////////
293
295{
296 R__ASSERT(code == 1);
297
298 // The maximum value for given (m0,alpha,n,sigma) is 1./ Integral in the variable range
299 // For the crystal ball, the maximum is 1.0 in the current implementation,
300 // but it's maybe better to keep this general in case the implementation changes.
301 return 1.0 / analyticalIntegral(code);
302}
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
char name[80]
Definition TGX11.cxx:110
float xmin
float xmax
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
bool matchArgs(const RooArgSet &allDeps, RooArgSet &numDeps, const RooArgProxy &a) const
Utility function for use in getAnalyticalIntegral().
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
PDF implementing the generalized Asymmetrical Double-Sided Crystall Ball line shape.
std::unique_ptr< RooRealProxy > nR_
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=nullptr) const override
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
RooAbsReal const * nR() const
RooAbsReal const * alphaR() const
RooRealProxy sigmaR_
RooRealProxy nL_
RooAbsReal const & sigmaR() const
RooRealProxy x_
std::unique_ptr< RooRealProxy > alphaR_
RooAbsReal const & nL() const
RooRealProxy x0_
RooAbsReal const & x0() const
RooAbsReal const & x() const
RooRealProxy alphaL_
double maxVal(Int_t code) const override
Return maximum value for set of observables identified by code assigned in getMaxVal.
double evaluate() const override
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
RooAbsReal const & sigmaL() const
RooRealProxy sigmaL_
Int_t getMaxVal(const RooArgSet &vars) const override
Advertise that we know the maximum of self for given (m0,alpha,n,sigma).
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
RooAbsReal const & alphaL() const
double max(const char *rname=nullptr) const
Query upper limit of range. This requires the payload to be RooAbsRealLValue or derived.
double min(const char *rname=nullptr) const
Query lower limit of range. This requires the payload to be RooAbsRealLValue or derived.
const Double_t sigma
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
void checkRangeOfParameters(const RooAbsReal *callingClass, std::initializer_list< const RooAbsReal * > pars, double min=-std::numeric_limits< double >::max(), double max=std::numeric_limits< double >::max(), bool limitsInAllowedRange=false, std::string const &extraMessage="")
Check if the parameters have a range, and warn if the range extends below / above the set limits.