|
12 | 12 |
|
13 | 13 | #include <RooAbsPdf.h> |
14 | 14 | #include <RooArgSet.h> |
| 15 | +#include <RooNaNPacker.h> |
15 | 16 | #include <RooRealConstant.h> |
16 | 17 | #include <RooRealIntegral.h> |
17 | 18 | #include <RooRealVar.h> |
@@ -239,3 +240,127 @@ RooArgList AddCacheElem::containedArgs(Action) |
239 | 240 |
|
240 | 241 | return allNodes; |
241 | 242 | } |
| 243 | + |
| 244 | +void RooAddHelpers::updateCoefficients(RooAbsPdf const &addPdf, RooArgList const &pdfList, RooArgList const &coefList, |
| 245 | + AddCacheElem &cache, const RooArgSet *nset, bool projectCoefs, |
| 246 | + RooArgSet const &refCoefNorm, bool allExtendable, std::vector<double> &coefCache, |
| 247 | + int &coefErrCount) |
| 248 | +{ |
| 249 | + bool haveLastCoef = pdfList.size() == coefList.size(); |
| 250 | + |
| 251 | + coefCache.resize(haveLastCoef ? coefList.size() : pdfList.size(), 0.); |
| 252 | + |
| 253 | + // Straight coefficients |
| 254 | + if (allExtendable) { |
| 255 | + |
| 256 | + // coef[i] = expectedEvents[i] / SUM(expectedEvents) |
| 257 | + double coefSum(0); |
| 258 | + std::size_t i = 0; |
| 259 | + for (auto arg : pdfList) { |
| 260 | + auto pdf = static_cast<RooAbsPdf *>(arg); |
| 261 | + coefCache[i] = pdf->expectedEvents(!refCoefNorm.empty() ? &refCoefNorm : nset); |
| 262 | + coefSum += coefCache[i]; |
| 263 | + i++; |
| 264 | + } |
| 265 | + |
| 266 | + if (coefSum == 0.) { |
| 267 | + oocoutW(&addPdf, Eval) << addPdf.ClassName() << "::updateCoefCache(" << addPdf.GetName() |
| 268 | + << ") WARNING: total number of expected events is 0" << std::endl; |
| 269 | + } else { |
| 270 | + for (std::size_t j = 0; j < pdfList.size(); j++) { |
| 271 | + coefCache[j] /= coefSum; |
| 272 | + } |
| 273 | + } |
| 274 | + |
| 275 | + } else { |
| 276 | + if (haveLastCoef) { |
| 277 | + |
| 278 | + // coef[i] = coef[i] / SUM(coef) |
| 279 | + double coefSum(0); |
| 280 | + std::size_t i = 0; |
| 281 | + for (auto coefArg : coefList) { |
| 282 | + auto coef = static_cast<RooAbsReal *>(coefArg); |
| 283 | + coefCache[i] = coef->getVal(nset); |
| 284 | + coefSum += coefCache[i++]; |
| 285 | + } |
| 286 | + if (coefSum == 0.) { |
| 287 | + oocoutW(&addPdf, Eval) << addPdf.ClassName() << "::updateCoefCache(" << addPdf.GetName() |
| 288 | + << ") WARNING: sum of coefficients is zero 0" << std::endl; |
| 289 | + } else { |
| 290 | + const double invCoefSum = 1. / coefSum; |
| 291 | + for (std::size_t j = 0; j < coefList.size(); j++) { |
| 292 | + coefCache[j] *= invCoefSum; |
| 293 | + } |
| 294 | + } |
| 295 | + } else { |
| 296 | + |
| 297 | + // coef[i] = coef[i] ; coef[n] = 1-SUM(coef[0...n-1]) |
| 298 | + double lastCoef(1); |
| 299 | + std::size_t i = 0; |
| 300 | + for (auto coefArg : coefList) { |
| 301 | + auto coef = static_cast<RooAbsReal *>(coefArg); |
| 302 | + coefCache[i] = coef->getVal(nset); |
| 303 | + lastCoef -= coefCache[i++]; |
| 304 | + } |
| 305 | + coefCache[coefList.size()] = lastCoef; |
| 306 | + |
| 307 | + // Treat coefficient degeneration |
| 308 | + const float coefDegen = lastCoef < 0. ? -lastCoef : (lastCoef > 1. ? lastCoef - 1. : 0.); |
| 309 | + if (coefDegen > 1.E-5) { |
| 310 | + coefCache[coefList.size()] = RooNaNPacker::packFloatIntoNaN(100.f * coefDegen); |
| 311 | + |
| 312 | + std::stringstream msg; |
| 313 | + if (coefErrCount-- > 0) { |
| 314 | + msg << "RooAddPdf::updateCoefCache(" << addPdf.GetName() |
| 315 | + << " WARNING: sum of PDF coefficients not in range [0-1], value=" << 1 - lastCoef; |
| 316 | + if (coefErrCount == 0) { |
| 317 | + msg << " (no more will be printed)"; |
| 318 | + } |
| 319 | + oocoutW(&addPdf, Eval) << msg.str() << std::endl; |
| 320 | + } |
| 321 | + } |
| 322 | + } |
| 323 | + } |
| 324 | + |
| 325 | + // Stop here if not projection is required or needed |
| 326 | + if ((!projectCoefs && !addPdf.normRange()) || cache._projList.empty()) { |
| 327 | + return; |
| 328 | + } |
| 329 | + |
| 330 | + // Adjust coefficients for given projection |
| 331 | + double coefSum(0); |
| 332 | + { |
| 333 | + RooAbsReal::GlobalSelectComponentRAII compRAII(true); |
| 334 | + |
| 335 | + for (std::size_t i = 0; i < pdfList.size(); i++) { |
| 336 | + |
| 337 | + RooAbsReal *pp = ((RooAbsReal *)cache._projList.at(i)); |
| 338 | + RooAbsReal *sn = ((RooAbsReal *)cache._suppProjList.at(i)); |
| 339 | + RooAbsReal *r1 = ((RooAbsReal *)cache._refRangeProjList.at(i)); |
| 340 | + RooAbsReal *r2 = ((RooAbsReal *)cache._rangeProjList.at(i)); |
| 341 | + |
| 342 | + double proj = pp->getVal() / sn->getVal() * (r2->getVal() / r1->getVal()); |
| 343 | + |
| 344 | + coefCache[i] *= proj; |
| 345 | + coefSum += coefCache[i]; |
| 346 | + } |
| 347 | + } |
| 348 | + |
| 349 | + if ((RooMsgService::_debugCount > 0) && |
| 350 | + RooMsgService::instance().isActive(&addPdf, RooFit::Caching, RooFit::DEBUG)) { |
| 351 | + for (std::size_t i = 0; i < pdfList.size(); ++i) { |
| 352 | + ooccoutD(&addPdf, Caching) << " ALEX: POST-SYNC coef[" << i << "] = " << coefCache[i] |
| 353 | + << " ( _coefCache[i]/coefSum = " << coefCache[i] * coefSum << "/" << coefSum |
| 354 | + << " ) " << std::endl; |
| 355 | + } |
| 356 | + } |
| 357 | + |
| 358 | + if (coefSum == 0.) { |
| 359 | + oocoutE(&addPdf, Eval) << addPdf.ClassName() << "::updateCoefCache(" << addPdf.GetName() |
| 360 | + << ") sum of coefficients is zero." << std::endl; |
| 361 | + } |
| 362 | + |
| 363 | + for (std::size_t i = 0; i < pdfList.size(); i++) { |
| 364 | + coefCache[i] /= coefSum; |
| 365 | + } |
| 366 | +} |
0 commit comments