|
1 | 1 | #ifndef CombineMathFuncs_h
|
2 | 2 | #define CombineMathFuncs_h
|
3 | 3 |
|
| 4 | +#include <RooAbsReal.h> |
| 5 | +#include <RooArgList.h> |
| 6 | +#include <RooArgSet.h> |
| 7 | +#include <RooConstVar.h> |
| 8 | + |
4 | 9 | #include <cmath>
|
5 | 10 |
|
6 | 11 | namespace RooFit {
|
@@ -145,6 +150,162 @@ inline double processNormalization(double nominalValue, std::size_t nThetas, std
|
145 | 150 | return norm;
|
146 | 151 | }
|
147 | 152 |
|
| 153 | +// Interpolation (from VerticalInterpPdf) |
| 154 | +inline Double_t interpolate(Double_t const coeff, Double_t const central, Double_t const fUp, |
| 155 | + Double_t const fDn, Double_t const quadraticRegion, Int_t const quadraticAlgo) |
| 156 | +{ |
| 157 | + if (quadraticAlgo == -1) { |
| 158 | + Double_t kappa = (coeff > 0 ? fUp/central : central/fDn); |
| 159 | + return pow(kappa, sqrt(pow(coeff, 2))); |
| 160 | + } |
| 161 | + |
| 162 | + if (fabs(coeff) >= quadraticRegion) { |
| 163 | + return coeff * (coeff > 0 ? fUp - central : central - fDn); |
| 164 | + } else { |
| 165 | + // quadratic interpolation coefficients between the three |
| 166 | + if (quadraticAlgo == 0) { |
| 167 | + // quadratic interpolation null at zero and continuous at boundaries, but not differentiable at boundaries |
| 168 | + // conditions: |
| 169 | + // c_up (+quadraticRegion) = +quadraticRegion |
| 170 | + // c_cen(+quadraticRegion) = -quadraticRegion |
| 171 | + // c_dn (+quadraticRegion) = 0 |
| 172 | + // c_up (-quadraticRegion) = 0 |
| 173 | + // c_cen(-quadraticRegion) = -quadraticRegion |
| 174 | + // c_dn (-quadraticRegion) = +quadraticRegion |
| 175 | + // c_up(0) = c_dn(0) = c_cen(0) = 0 |
| 176 | + Double_t c_up = + coeff * (quadraticRegion + coeff) / (2 * quadraticRegion); |
| 177 | + Double_t c_dn = - coeff * (quadraticRegion - coeff) / (2 * quadraticRegion); |
| 178 | + Double_t c_cen = - coeff * coeff / quadraticRegion; |
| 179 | + return c_up * fUp + c_dn * fDn + c_cen * central; |
| 180 | + } else if (quadraticAlgo == 1) { |
| 181 | + // quadratic interpolation that is everywhere differentiable, but it's not null at zero |
| 182 | + // conditions on the function |
| 183 | + // c_up (+quadraticRegion) = +quadraticRegion |
| 184 | + // c_cen(+quadraticRegion) = -quadraticRegion |
| 185 | + // c_dn (+quadraticRegion) = 0 |
| 186 | + // c_up (-quadraticRegion) = 0 |
| 187 | + // c_cen(-quadraticRegion) = -quadraticRegion |
| 188 | + // c_dn (-quadraticRegion) = +quadraticRegion |
| 189 | + // conditions on the derivatives |
| 190 | + // c_up '(+quadraticRegion) = +1 |
| 191 | + // c_cen'(+quadraticRegion) = -1 |
| 192 | + // c_dn '(+quadraticRegion) = 0 |
| 193 | + // c_up '(-quadraticRegion) = 0 |
| 194 | + // c_cen'(-quadraticRegion) = +1 |
| 195 | + // c_dn '(-quadraticRegion) = -1 |
| 196 | + Double_t c_up = (quadraticRegion + coeff) * (quadraticRegion + coeff) / (4 * quadraticRegion); |
| 197 | + Double_t c_dn = (quadraticRegion - coeff) * (quadraticRegion - coeff) / (4 * quadraticRegion); |
| 198 | + Double_t c_cen = - c_up - c_dn; |
| 199 | + return c_up * fUp + c_dn * fDn + c_cen * central; |
| 200 | + } else/* if (quadraticAlgo == 1)*/ { |
| 201 | + // P(6) interpolation that is everywhere differentiable and null at zero |
| 202 | + /* === how the algorithm works, in theory === |
| 203 | + * let dhi = h_hi - h_nominal |
| 204 | + * dlo = h_lo - h_nominal |
| 205 | + * and x be the morphing parameter |
| 206 | + * we define alpha = x * 0.5 * ((dhi-dlo) + (dhi+dlo)*smoothStepFunc(x)); |
| 207 | + * which satisfies: |
| 208 | + * alpha(0) = 0 |
| 209 | + * alpha(+1) = dhi |
| 210 | + * alpha(-1) = dlo |
| 211 | + * alpha(x >= +1) = |x|*dhi |
| 212 | + * alpha(x <= -1) = |x|*dlo |
| 213 | + * alpha is continuous and has continuous first and second derivative, as smoothStepFunc has them |
| 214 | + * === and in practice === |
| 215 | + * we already have computed the histogram for diff=(dhi-dlo) and sum=(dhi+dlo) |
| 216 | + * so we just do template += (0.5 * x) * (diff + smoothStepFunc(x) * sum) |
| 217 | + * ========================================== */ |
| 218 | + Double_t cnorm = coeff/quadraticRegion; |
| 219 | + Double_t cnorm2 = pow(cnorm, 2); |
| 220 | + Double_t hi = fUp - central; |
| 221 | + Double_t lo = fDn - central; |
| 222 | + Double_t sum = hi+lo; |
| 223 | + Double_t diff = hi-lo; |
| 224 | + Double_t a = coeff/2.; // cnorm*quadraticRegion |
| 225 | + Double_t b = 0.125 * cnorm * (cnorm2 * (3.*cnorm2 - 10.) + 15.); |
| 226 | + Double_t result = a*(diff + b*sum); |
| 227 | + return result; |
| 228 | + } |
| 229 | + } |
| 230 | +} |
| 231 | + |
| 232 | +template <typename Operation> |
| 233 | +inline Double_t opInterpolate(RooArgList const& coefList, RooArgList const& funcList, Double_t const pdfFloorVal, |
| 234 | + Double_t const quadraticRegion, Int_t const quadraticAlgo, const RooArgSet* normSet2=nullptr) |
| 235 | +{ |
| 236 | + // Do running sum of coef/func pairs, calculate lastCoef. |
| 237 | + RooAbsReal* func = &(RooAbsReal&)funcList[0]; |
| 238 | + Double_t central = func->getVal(); |
| 239 | + Double_t value = central; |
| 240 | + |
| 241 | + Operation op; |
| 242 | + |
| 243 | + for (int iCoef = 0; iCoef < coefList.getSize(); ++iCoef) { |
| 244 | + Double_t coefVal = static_cast<RooAbsReal&>(coefList[iCoef]).getVal(normSet2) ; |
| 245 | + RooAbsReal* funcUp = &(RooAbsReal&)funcList[2 * iCoef + 1]; |
| 246 | + RooAbsReal* funcDn = &(RooAbsReal&)funcList[2 * iCoef + 2]; |
| 247 | + value = op(value, interpolate(coefVal, central, funcUp->getVal(), funcDn->getVal(), quadraticRegion, quadraticAlgo)); |
| 248 | + } |
| 249 | + return ( value > 0. ? value : pdfFloorVal); |
| 250 | +} |
| 251 | + |
| 252 | +inline Double_t additiveInterpolate(double const* coefList, std::size_t nCoeffs, double const* funcList, std::size_t nFuncs, |
| 253 | + Double_t const pdfFloorVal, Double_t const quadraticRegion, Int_t const quadraticAlgo) |
| 254 | +{ |
| 255 | + // Do running sum of coef/func pairs, calculate lastCoef. |
| 256 | + Double_t central = funcList[0]; |
| 257 | + Double_t value = central; |
| 258 | + |
| 259 | + for (std::size_t iCoef = 0; iCoef < nCoeffs; ++iCoef) { |
| 260 | + double coefVal = coefList[iCoef]; |
| 261 | + double funcUp = funcList[2 * iCoef + 1]; |
| 262 | + double funcDn = funcList[2 * iCoef + 2]; |
| 263 | + value += interpolate(coefVal, central, funcUp, funcDn, quadraticRegion, quadraticAlgo); |
| 264 | + } |
| 265 | + return ( value > 0. ? value : pdfFloorVal); |
| 266 | +} |
| 267 | + |
| 268 | +inline Double_t multiplicativeInterpolate(double const* coefList, std::size_t nCoeffs, double const* funcList, std::size_t nFuncs, |
| 269 | + Double_t const pdfFloorVal, Double_t const quadraticRegion, Int_t const quadraticAlgo) |
| 270 | +{ |
| 271 | + // Do running sum of coef/func pairs, calculate lastCoef. |
| 272 | + Double_t central = funcList[0]; |
| 273 | + Double_t value = central; |
| 274 | + |
| 275 | + for (std::size_t iCoef = 0; iCoef < nCoeffs; ++iCoef) { |
| 276 | + double coefVal = coefList[iCoef]; |
| 277 | + double funcUp = funcList[2 * iCoef + 1]; |
| 278 | + double funcDn = funcList[2 * iCoef + 2]; |
| 279 | + value *= interpolate(coefVal, central, funcUp, funcDn, quadraticRegion, quadraticAlgo); |
| 280 | + } |
| 281 | + return ( value > 0. ? value : pdfFloorVal); |
| 282 | +} |
| 283 | + |
| 284 | +inline Double_t verticalInterpolate(double const* coefList, std::size_t nCoeffs, double const* funcList, std::size_t nFuncs, |
| 285 | + double const pdfFloorVal, double const quadraticRegion, Int_t const quadraticAlgo) |
| 286 | +{ |
| 287 | + // Do running sum of coef/func pairs, calculate lastCoef. |
| 288 | + Double_t value = pdfFloorVal; |
| 289 | + if (quadraticAlgo >= 0) { |
| 290 | + value = RooFit::Detail::MathFuncs::additiveInterpolate(coefList, nCoeffs, funcList, nFuncs, pdfFloorVal, quadraticRegion, quadraticAlgo); |
| 291 | + } else { |
| 292 | + value = RooFit::Detail::MathFuncs::multiplicativeInterpolate(coefList, nCoeffs, funcList, nFuncs, pdfFloorVal, quadraticRegion, quadraticAlgo); |
| 293 | + } |
| 294 | + return value; |
| 295 | +} |
| 296 | + |
| 297 | +inline Double_t verticalInterpPdfIntegral(double const* coefList, std::size_t nCoeffs, double const* funcIntList, std::size_t nFuncs, |
| 298 | + double const pdfFloorVal, double const integralFloorVal, |
| 299 | + double const quadraticRegion, Int_t const quadraticAlgo) |
| 300 | +{ |
| 301 | + double value = RooFit::Detail::MathFuncs::additiveInterpolate(coefList, nCoeffs, funcIntList, nFuncs, |
| 302 | + pdfFloorVal, quadraticRegion, quadraticAlgo); |
| 303 | + double normVal(1); |
| 304 | + double result = 0; |
| 305 | + if(normVal>0.) result = value / normVal; |
| 306 | + return result > 0. ? result : integralFloorVal; |
| 307 | +} |
| 308 | + |
148 | 309 | } // namespace MathFuncs
|
149 | 310 | } // namespace Detail
|
150 | 311 | } // namespace RooFit
|
|
0 commit comments