Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
EvaluateFuncs.h
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Jonas Rembser, CERN 2023
5 * Garima Singh, CERN 2023
6 *
7 * Copyright (c) 2023, CERN
8 *
9 * Redistribution and use in source and binary forms,
10 * with or without modification, are permitted according to the terms
11 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
12 */
13
14#ifndef RooFit_Detail_EvaluateFuncs_h
15#define RooFit_Detail_EvaluateFuncs_h
16
17#include <TMath.h>
19
20#include <cmath>
21
22namespace RooFit {
23
24namespace Detail {
25
26namespace EvaluateFuncs {
27
28/// @brief Function to evaluate an un-normalized RooGaussian.
29inline double gaussianEvaluate(double x, double mean, double sigma)
30{
31 const double arg = x - mean;
32 const double sig = sigma;
33 return std::exp(-0.5 * arg * arg / (sig * sig));
34}
35
36// RooRatio evaluate function.
37inline double ratioEvaluate(double numerator, double denominator) {
38 return numerator / denominator;
39}
40
41inline double bifurGaussEvaluate(double x, double mean, double sigmaL, double sigmaR)
42{
43 // Note: this simplification does not work with Clad as of v1.1!
44 // return gaussianEvaluate(x, mean, x < mean ? sigmaL : sigmaR);
45 if(x < mean) return gaussianEvaluate(x, mean, sigmaL);
46 return gaussianEvaluate(x, mean, sigmaR);
47}
48
49inline double efficiencyEvaluate(double effFuncVal, int catIndex, int sigCatIndex)
50{
51 // Truncate efficiency function in range 0.0-1.0
52 effFuncVal = std::clamp(effFuncVal, 0.0, 1.0);
53
54 if (catIndex == sigCatIndex)
55 return effFuncVal; // Accept case
56 else
57 return 1 - effFuncVal; // Reject case
58}
59
60/// In pdfMode, a coefficient for the constant term of 1.0 is implied if lowestOrder > 0.
61template <bool pdfMode = false>
62inline double polynomialEvaluate(double const *coeffs, int nCoeffs, int lowestOrder, double x)
63{
64 double retVal = coeffs[nCoeffs - 1];
65 for (int i = nCoeffs - 2; i >= 0; i--)
66 retVal = coeffs[i] + x * retVal;
67 retVal = retVal * std::pow(x, lowestOrder);
68 return retVal + (pdfMode && lowestOrder > 0 ? 1.0 : 0.0);
69}
70
71inline double chebychevEvaluate(double *coeffs, unsigned int nCoeffs, double x_in, double xMin, double xMax)
72{
73 // transform to range [-1, +1]
74 const double xPrime = (x_in - 0.5 * (xMax + xMin)) / (0.5 * (xMax - xMin));
75
76 // extract current values of coefficients
77 double sum = 1.;
78 if (nCoeffs > 0) {
79 double curr = xPrime;
80 double twox = 2 * xPrime;
81 double last = 1;
82 double newval = twox * curr - last;
83 last = curr;
84 curr = newval;
85 for (unsigned int i = 0; nCoeffs != i; ++i) {
86 sum += last * coeffs[i];
87 newval = twox * curr - last;
88 last = curr;
89 curr = newval;
90 }
91 }
92 return sum;
93}
94
95inline double constraintSumEvaluate(double const *comp, unsigned int compSize)
96{
97 double sum = 0;
98 for (unsigned int i = 0; i < compSize; i++) {
99 sum -= std::log(comp[i]);
100 }
101 return sum;
102}
103
104inline unsigned int getUniformBinning(double low, double high, double val, unsigned int numBins)
105{
106 double binWidth = (high - low) / numBins;
107 return val >= high ? numBins - 1 : std::abs((val - low) / binWidth);
108}
109
110inline double poissonEvaluate(double x, double par)
111{
112 if (par < 0)
113 return TMath::QuietNaN();
114
115 if (x < 0) {
116 return 0;
117 } else if (x == 0.0) {
118 return std::exp(-par);
119 } else {
120 double out = x * std::log(par) - TMath::LnGamma(x + 1.) - par;
121 return std::exp(out);
122 }
123}
124
125inline double interpolate6thDegree(double x, double low, double high, double nominal, double boundary)
126{
127 double t = x / boundary;
128 double eps_plus = high - nominal;
129 double eps_minus = nominal - low;
130 double S = 0.5 * (eps_plus + eps_minus);
131 double A = 0.0625 * (eps_plus - eps_minus);
132
133 return x * (S + t * A * (15 + t * t * (-10 + t * t * 3)));
134}
135
136inline double interpolate6thDegreeExp(double x, double low, double high, double nominal, double boundary)
137{
138 double x0 = boundary;
139
140 // GHL: Swagato's suggestions
141 double powUp = std::pow(high / nominal, x0);
142 double powDown = std::pow(low / nominal, x0);
143 double logHi = std::log(high);
144 double logLo = std::log(low);
145 double powUpLog = high <= 0.0 ? 0.0 : powUp * logHi;
146 double powDownLog = low <= 0.0 ? 0.0 : -powDown * logLo;
147 double powUpLog2 = high <= 0.0 ? 0.0 : powUpLog * logHi;
148 double powDownLog2 = low <= 0.0 ? 0.0 : -powDownLog * logLo;
149
150 double S0 = 0.5 * (powUp + powDown);
151 double A0 = 0.5 * (powUp - powDown);
152 double S1 = 0.5 * (powUpLog + powDownLog);
153 double A1 = 0.5 * (powUpLog - powDownLog);
154 double S2 = 0.5 * (powUpLog2 + powDownLog2);
155 double A2 = 0.5 * (powUpLog2 - powDownLog2);
156
157 // fcns+der+2nd_der are eq at bd
158
159 double a = 1. / (8 * x0) * (15 * A0 - 7 * x0 * S1 + x0 * x0 * A2);
160 double b = 1. / (8 * x0 * x0) * (-24 + 24 * S0 - 9 * x0 * A1 + x0 * x0 * S2);
161 double c = 1. / (4 * std::pow(x0, 3)) * (-5 * A0 + 5 * x0 * S1 - x0 * x0 * A2);
162 double d = 1. / (4 * std::pow(x0, 4)) * (12 - 12 * S0 + 7 * x0 * A1 - x0 * x0 * S2);
163 double e = 1. / (8 * std::pow(x0, 5)) * (+3 * A0 - 3 * x0 * S1 + x0 * x0 * A2);
164 double f = 1. / (8 * std::pow(x0, 6)) * (-8 + 8 * S0 - 5 * x0 * A1 + x0 * x0 * S2);
165
166 // evaluate the 6-th degree polynomial using Horner's method
167 double value = 1. + x * (a + x * (b + x * (c + x * (d + x * (e + x * f)))));
168 return value;
169}
170
171inline double
172flexibleInterp(unsigned int code, double low, double high, double boundary, double nominal, double paramVal, double res)
173{
174 if (code == 0) {
175 // piece-wise linear
176 if (paramVal > 0) {
177 return paramVal * (high - nominal);
178 } else {
179 return paramVal * (nominal - low);
180 }
181 } else if (code == 1) {
182 // piece-wise log
183 if (paramVal >= 0) {
184 return res * (std::pow(high / nominal, +paramVal) - 1);
185 } else {
186 return res * (std::pow(low / nominal, -paramVal) - 1);
187 }
188 } else if (code == 2) {
189 // parabolic with linear
190 double a = 0.5 * (high + low) - nominal;
191 double b = 0.5 * (high - low);
192 double c = 0;
193 if (paramVal > 1) {
194 return (2 * a + b) * (paramVal - 1) + high - nominal;
195 } else if (paramVal < -1) {
196 return -1 * (2 * a - b) * (paramVal + 1) + low - nominal;
197 } else {
198 return a * std::pow(paramVal, 2) + b * paramVal + c;
199 }
200 } else if (code == 3) {
201 // parabolic version of log-normal
202 double a = 0.5 * (high + low) - nominal;
203 double b = 0.5 * (high - low);
204 double c = 0;
205 if (paramVal > 1) {
206 return (2 * a + b) * (paramVal - 1) + high - nominal;
207 } else if (paramVal < -1) {
208 return -1 * (2 * a - b) * (paramVal + 1) + low - nominal;
209 } else {
210 return a * std::pow(paramVal, 2) + b * paramVal + c;
211 }
212 } else if (code == 4) {
213 double x = paramVal;
214 if (x >= boundary) {
215 return x * (high - nominal);
216 } else if (x <= -boundary) {
217 return x * (nominal - low);
218 }
219
220 return interpolate6thDegree(x, low, high, nominal, boundary);
221 } else if (code == 5) {
222 double x = paramVal;
223 double mod = 1.0;
224 if (x >= boundary) {
225 mod = std::pow(high / nominal, +paramVal);
226 } else if (x <= -boundary) {
227 mod = std::pow(low / nominal, -paramVal);
228 } else {
229 mod = interpolate6thDegreeExp(x, low, high, nominal, boundary);
230 }
231 return res * (mod - 1.0);
232 }
233
234 return 0.0;
235}
236
237inline double flexibleInterpEvaluate(unsigned int code, double *params, unsigned int n, double *low, double *high,
238 double boundary, double nominal)
239{
240 double total = nominal;
241 for (std::size_t i = 0; i < n; ++i) {
242 total += flexibleInterp(code, low[i], high[i], boundary, nominal, params[i], total);
243 }
244
245 return total <= 0 ? TMath::Limits<double>::Min() : total;
246}
247
248inline double piecewiseInterpolationEvaluate(unsigned int code, double *low, double *high, double nominal,
249 double *params, unsigned int n)
250{
251 double total = nominal;
252 for (std::size_t i = 0; i < n; ++i) {
253 total += flexibleInterp(code, low[i], high[i], 1.0, nominal, params[i], total);
254 }
255
256 return total;
257}
258
259inline double logNormalEvaluate(double x, double k, double m0)
260{
261 return ROOT::Math::lognormal_pdf(x, std::log(m0), std::abs(std::log(k)));
262}
263
264inline double logNormalEvaluateStandard(double x, double sigma, double mu)
265{
266 return ROOT::Math::lognormal_pdf(x, mu, std::abs(sigma));
267}
268
269inline double effProdEvaluate(double eff, double pdf) {
270 return eff * pdf;
271}
272
273inline double nllEvaluate(double pdf, double weight, int binnedL, int doBinOffset)
274{
275 if (binnedL) {
276 // Special handling of this case since log(Poisson(0,0)=0 but can't be
277 // calculated with usual log-formula since log(mu)=0. No update of result
278 // is required since term=0.
279 if (std::abs(pdf) < 1e-10 && std::abs(weight) < 1e-10) {
280 return 0.0;
281 }
282 if (doBinOffset) {
283 return pdf - weight - weight * (std::log(pdf) - std::log(weight));
284 }
285 return pdf - weight * std::log(pdf) + TMath::LnGamma(weight + 1);
286 } else {
287 return -weight * std::log(pdf);
288 }
289}
290
291} // namespace EvaluateFuncs
292
293} // namespace Detail
294
295} // namespace RooFit
296
297#endif
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define S0(x)
Definition RSha256.hxx:88
#define S1(x)
Definition RSha256.hxx:89
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
static unsigned int total
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
double lognormal_pdf(double x, double m, double s, double x0=0)
Probability density function of the lognormal distribution.
const Double_t sigma
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
double poissonEvaluate(double x, double par)
double bifurGaussEvaluate(double x, double mean, double sigmaL, double sigmaR)
double constraintSumEvaluate(double const *comp, unsigned int compSize)
double gaussianEvaluate(double x, double mean, double sigma)
Function to evaluate an un-normalized RooGaussian.
double piecewiseInterpolationEvaluate(unsigned int code, double *low, double *high, double nominal, double *params, unsigned int n)
double flexibleInterp(unsigned int code, double low, double high, double boundary, double nominal, double paramVal, double res)
double effProdEvaluate(double eff, double pdf)
double polynomialEvaluate(double const *coeffs, int nCoeffs, int lowestOrder, double x)
In pdfMode, a coefficient for the constant term of 1.0 is implied if lowestOrder > 0.
double flexibleInterpEvaluate(unsigned int code, double *params, unsigned int n, double *low, double *high, double boundary, double nominal)
double logNormalEvaluate(double x, double k, double m0)
double logNormalEvaluateStandard(double x, double sigma, double mu)
double efficiencyEvaluate(double effFuncVal, int catIndex, int sigCatIndex)
double interpolate6thDegreeExp(double x, double low, double high, double nominal, double boundary)
unsigned int getUniformBinning(double low, double high, double val, unsigned int numBins)
double ratioEvaluate(double numerator, double denominator)
double interpolate6thDegree(double x, double low, double high, double nominal, double boundary)
double nllEvaluate(double pdf, double weight, int binnedL, int doBinOffset)
double chebychevEvaluate(double *coeffs, unsigned int nCoeffs, double x_in, double xMin, double xMax)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition JSONIO.h:26
Double_t QuietNaN()
Returns a quiet NaN as defined by IEEE 754.
Definition TMath.h:902
Double_t LnGamma(Double_t z)
Computation of ln[gamma(z)] for all z.
Definition TMath.cxx:509
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345