Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
CodegenImpl.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Garima Singh, CERN 2023
5 * Jonas Rembser, CERN 2024
6 *
7 * Copyright (c) 2024, 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#include <RooFit/CodegenImpl.h>
15
17
18#include <RooAddPdf.h>
19#include <RooAddition.h>
20#include <RooBernstein.h>
21#include <RooBifurGauss.h>
22#include <RooCBShape.h>
23#include <RooCategory.h>
24#include <RooChebychev.h>
25#include <RooConstVar.h>
26#include <RooConstraintSum.h>
27#include <RooEffProd.h>
28#include <RooEfficiency.h>
29#include <RooExponential.h>
30#include <RooExtendPdf.h>
33#include <RooFormulaVar.h>
34#include <RooFunctor1DBinding.h>
35#include <RooFunctorBinding.h>
36#include <RooGamma.h>
37#include <RooGaussian.h>
38#include <RooGenericPdf.h>
39#include <RooHistFunc.h>
40#include <RooHistPdf.h>
41#include <RooLandau.h>
42#include <RooLognormal.h>
43#include <RooMultiPdf.h>
44#include <RooMultiVarGaussian.h>
45#include <RooONNXFunc.h>
46#include <RooParamHistFunc.h>
47#include <RooPoisson.h>
48#include <RooPolyVar.h>
49#include <RooPolynomial.h>
50#include <RooProdPdf.h>
51#include <RooProduct.h>
52#include <RooRatio.h>
53#include <RooRealIntegral.h>
54#include <RooRealSumFunc.h>
55#include <RooRealSumPdf.h>
56#include <RooRealVar.h>
58#include <RooSimultaneous.h>
62#include <RooUniform.h>
63#include <RooWrapperPdf.h>
64
65#include "RooFitImplHelpers.h"
66
67#include <TInterpreter.h>
68
69#include <locale>
70#include <unordered_set>
71
72namespace RooFit::Experimental {
73
74namespace {
75
76// Return a stringy-field version of the value, formatted to maximum precision.
77std::string doubleToString(double val)
78{
79 std::stringstream ss;
80 // The formatting must not depend on the global locale: a comma decimal
81 // separator (e.g. from a German locale) would corrupt the generated C++.
82 ss.imbue(std::locale::classic());
83 ss << std::setprecision(std::numeric_limits<double>::max_digits10) << val;
84 return ss.str();
85}
86
87std::string mathFunc(std::string const &name)
88{
89 return "RooFit::Detail::MathFuncs::" + name;
90}
91
92void rooHistTranslateImpl(RooAbsArg const &arg, CodegenContext &ctx, int intOrder, RooDataHist const &dataHist,
93 const RooArgSet &obs, bool correctForBinSize, bool cdfBoundaries)
94{
95 if (intOrder != 0 && !(!cdfBoundaries && !correctForBinSize && intOrder == 1 && obs.size() == 1)) {
96 ooccoutE(&arg, InputArguments) << "RooHistPdf::weight(" << arg.GetName()
97 << ") ERROR: codegen currently only supports non-interpolation cases."
98 << std::endl;
99 return;
100 }
101
102 if (intOrder == 1) {
103 RooAbsBinning const &binning = *dataHist.getBinnings()[0];
104 std::string weightArr = dataHist.declWeightArrayForCodeSquash(ctx, correctForBinSize);
105 ctx.addResult(&arg, ctx.buildCall(mathFunc("interpolate1d"), binning.lowBound(), binning.highBound(), *obs[0],
106 binning.numBins(), weightArr));
107 return;
108 }
109 std::string const &offset = dataHist.calculateTreeIndexForCodeSquash(ctx, obs);
110 std::string weightArr = dataHist.declWeightArrayForCodeSquash(ctx, correctForBinSize);
111 ctx.addResult(&arg, "(" + weightArr + ")[" + offset + "]");
112}
113
114std::string
115realSumPdfTranslateImpl(CodegenContext &ctx, RooArgList const &funcList, RooArgList const &coefList, bool normalize)
116{
117 bool noLastCoeff = funcList.size() != coefList.size();
118
119 // Decide the scope from the inputs rather than from the RooRealSumPdf
120 // itself: this function is also used for the integral of the sum, whose
121 // inputs are the integrals of the components. Those usually don't depend
122 // on the data even though the sum does, and then the code must not end up
123 // inside the event loop, because the integral is also the expected number
124 // of events that the extended likelihood uses after the loop.
125 bool scopeIndependent = true;
126 for (RooAbsArg const *func : funcList) {
127 scopeIndependent = scopeIndependent && ctx.isScopeIndependent(func);
128 }
129 for (RooAbsArg const *coef : coefList) {
130 scopeIndependent = scopeIndependent && ctx.isScopeIndependent(coef);
131 }
132 auto addCode = [&](std::string const &code) { ctx.addToCodeBody(code, scopeIndependent); };
133
134 std::string const &funcName = ctx.buildArg(funcList);
135 std::string const &coeffName = ctx.buildArg(coefList);
136 std::string const &coeffSize = std::to_string(coefList.size());
137
138 std::string sum = ctx.getTmpVarName();
139 std::string coeffSum = ctx.getTmpVarName();
140 addCode("double " + sum + " = 0;\ndouble " + coeffSum + "= 0;\n");
141
142 std::string iterator = "i_" + ctx.getTmpVarName();
143 std::string subscriptExpr = "[" + iterator + "]";
144
145 std::string code = "for(int " + iterator + " = 0; " + iterator + " < " + coeffSize + "; " + iterator + "++) {\n" +
146 sum + " += " + funcName + subscriptExpr + " * " + coeffName + subscriptExpr + ";\n";
147 code += coeffSum + " += " + coeffName + subscriptExpr + ";\n";
148 code += "}\n";
149
150 if (noLastCoeff) {
151 code += sum + " += " + funcName + "[" + coeffSize + "]" + " * (1 - " + coeffSum + ");\n";
152 } else if (normalize) {
153 code += sum + " /= " + coeffSum + ";\n";
154 }
155 addCode(code);
156
157 return sum;
158}
159
160} // namespace
161
163{
164 if (arg.isRearranged()) {
165 ctx.addResult(&arg, ctx.buildCall(mathFunc("ratio"), *arg.rearrangedNum(), *arg.rearrangedDen()));
166 } else {
167 ctx.addResult(&arg, ctx.buildCall(mathFunc("product"), *arg.partList(), arg.partList()->size()));
168 }
169}
170
172{
173 std::string const &idx = arg.dataHist().calculateTreeIndexForCodeSquash(ctx, arg.dataVars(), true);
174 std::string const &paramNames = ctx.buildArg(arg.paramList());
175
176 ctx.addResult(&arg, paramNames + "[" + idx + "]");
177}
178
180{
181 auto const &interpCodes = arg.interpolationCodes();
182
183 std::size_t n = interpCodes.size();
184
185 std::string resName = "total_" + ctx.getTmpVarName();
186 for (std::size_t i = 0; i < n; ++i) {
187 if (interpCodes[i] != interpCodes[0]) {
189 << "FlexibleInterpVar::evaluate ERROR: Code Squashing AD does not yet support having "
190 "different interpolation codes for the same class object "
191 << std::endl;
192 }
193 }
194
195 // The PiecewiseInterpolation class is used in the context of HistFactory
196 // models, where is is always used the same way: all RooAbsReals in _lowSet,
197 // _histSet, and also nominal are 1D RooHistFuncs with with same structure.
198 //
199 // Therefore, we can make a big optimization: we get the bin index only once
200 // here in the generated code for PiecewiseInterpolation. Then, we also
201 // rearrange the histogram data in such a way that we can always pass the
202 // same arrays to the free function that implements the interpolation, just
203 // with a dynamic offset calculated from the bin index.
204 RooDataHist const &nomHist = dynamic_cast<RooHistFunc const &>(*arg.nominalHist()).dataHist();
205 int nBins = nomHist.numEntries();
206 std::vector<double> valsNominal;
207 std::vector<double> valsLow;
208 std::vector<double> valsHigh;
209 for (int i = 0; i < nBins; ++i) {
210 valsNominal.push_back(nomHist.weight(i));
211 }
212 for (int i = 0; i < nBins; ++i) {
213 for (std::size_t iParam = 0; iParam < n; ++iParam) {
214 valsLow.push_back(dynamic_cast<RooHistFunc const &>(arg.lowList()[iParam]).dataHist().weight(i));
215 valsHigh.push_back(dynamic_cast<RooHistFunc const &>(arg.highList()[iParam]).dataHist().weight(i));
216 }
217 }
218 std::string idxName = ctx.getTmpVarName();
219 std::string valsNominalStr = ctx.buildArg(valsNominal);
220 std::string valsLowStr = ctx.buildArg(valsLow);
221 std::string valsHighStr = ctx.buildArg(valsHigh);
222 std::string nStr = std::to_string(n);
223 std::string code;
224
225 std::string lowName = ctx.getTmpVarName();
226 std::string highName = ctx.getTmpVarName();
227 std::string nominalName = ctx.getTmpVarName();
228 code +=
229 "unsigned int " + idxName + " = " +
230 nomHist.calculateTreeIndexForCodeSquash(ctx, dynamic_cast<RooHistFunc const &>(*arg.nominalHist()).variables()) +
231 ";\n";
232 code += "double const* " + lowName + " = " + valsLowStr + " + " + nStr + " * " + idxName + ";\n";
233 code += "double const* " + highName + " = " + valsHighStr + " + " + nStr + " * " + idxName + ";\n";
234 code += "double " + nominalName + " = *(" + valsNominalStr + " + " + idxName + ");\n";
235
236 std::string funcCall = ctx.buildCall(mathFunc("flexibleInterp"), interpCodes[0], arg.paramList(), n, lowName,
237 highName, 1.0, nominalName, 0.0);
238 code += "double " + resName + " = " + funcCall + ";\n";
239
240 if (arg.positiveDefinite()) {
241 code += resName + " = " + resName + " < 0 ? 0 : " + resName + ";\n";
242 }
243
244 ctx.addToCodeBody(&arg, code);
245 ctx.addResult(&arg, resName);
246}
247
248////////////////////////////////////////////////////////////////////////////////
249/// This function defines a translation for each RooAbsReal based object that can be used
250/// to express the class as simple C++ code. The function adds the code represented by
251/// each class as an std::string (that is later concatenated with code strings from translate calls)
252/// to form the C++ code that AD tools can understand. Any class that wants to support AD, has to
253/// implement this function.
254///
255/// \param[in] ctx An object to manage auxiliary information for code-squashing. Also takes the
256/// code string that this class outputs into the squashed code through the 'addToCodeBody' function.
258{
259 std::stringstream errorMsg;
260 errorMsg << "Translate function for class \"" << arg.ClassName() << "\" has not yet been implemented.";
261 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
262 return ctx.addResult(&arg, "1.0");
263}
264
266{
267 ctx.addResult(&arg, realSumPdfTranslateImpl(ctx, arg.pdfList(), arg.coefList(), true));
268}
269
271{
272 auto const &covI = arg.covarianceMatrixInverse();
273 std::span<const double> covISpan{covI.GetMatrixArray(), static_cast<size_t>(covI.GetNoElements())};
274 ctx.addResult(&arg,
275 ctx.buildCall(mathFunc("multiVarGaussian"), arg.xVec().size(), arg.xVec(), arg.muVec(), covISpan));
276}
277
279{
280 int numPdfs = arg.getNumPdfs();
281
282 // MathFunc call
283
284 // The value of this number should be discussed. Beyound a certain number of
285 // indices MathFunc call becomes more efficient.
286 if (numPdfs > 2) {
287 ctx.addResult(&arg, ctx.buildCall(mathFunc("multipdf"), arg.indexCategory(), arg.getPdfList()));
288
289 std::cout << "MathFunc call used\n";
290
291 } else {
292
293 // Ternary nested expression
294 std::string indexExpr = ctx.getResult(arg.indexCategory());
295
296 // int numPdfs = arg.getNumPdfs();
297 std::string expr;
298
299 for (int i = 0; i < numPdfs; ++i) {
300 RooAbsPdf *pdf = arg.getPdf(i);
301 std::string pdfExpr = ctx.getResult(*pdf);
302
303 expr += "(" + indexExpr + " == " + std::to_string(i) + " ? (" + pdfExpr + ") : ";
304 }
305
306 expr += "0.0";
307 expr += std::string(numPdfs, ')'); // Close all ternary operators
308
309 ctx.addResult(&arg, expr);
310 std::cout << "Ternary expression call used \n";
311 }
312}
313
315{
316 // A RooSimultaneous appears as a node in the compute graph only when its
317 // index category is not an observable (see the "switch mode" in
318 // RooSimultaneous::compileForNormSet()): its value is then the one of the
319 // component selected by the current category state, like for RooMultiPdf.
320 // With an observable index category, the likelihood is decomposed into
321 // per-channel terms and the RooSimultaneous itself is never translated.
322 if (!arg.indexCat().isFundamental()) {
323 std::stringstream errorMsg;
324 errorMsg << "RooSimultaneous \"" << arg.GetName()
325 << "\" with a derived, non-observable index category can't be translated.";
326 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
327 throw std::runtime_error(errorMsg.str());
328 }
329
330 std::string const &indexExpr = ctx.getResult(arg.indexCat());
331
332 // Nested ternary expression that selects the pdf matching the category
333 // state, keyed on the state index numbers.
334 std::string expr;
335 std::size_t numStates = 0;
336 for (auto const &nameIdx : arg.indexCat()) {
337 RooAbsPdf *pdf = arg.getPdf(nameIdx.first.c_str());
338 if (!pdf) {
339 continue;
340 }
341 expr += "(" + indexExpr + " == " + std::to_string(nameIdx.second) + " ? (" + ctx.getResult(*pdf) + ") : ";
342 ++numStates;
343 }
344 expr += "0.0" + std::string(numStates, ')');
345
346 ctx.addResult(&arg, expr);
347}
348
349// RooCategory index added.
351{
352 int idx = ctx.observableIndexOf(arg);
353 if (idx < 0) {
354
355 idx = 1;
356 ctx.addVecObs(arg.GetName(), idx);
357 }
358
359 std::string result = std::to_string(arg.getCurrentIndex());
360 ctx.addResult(&arg, result);
361}
362
364{
365 if (arg.list().empty()) {
366 ctx.addResult(&arg, "0.0");
367 }
368 std::string result;
369 if (arg.list().size() > 1)
370 result += "(";
371
372 std::size_t i = 0;
373 for (auto *component : static_range_cast<RooAbsReal *>(arg.list())) {
374
375 if (!dynamic_cast<RooFit::Detail::RooNLLVarNew *>(component) || arg.list().size() == 1) {
376 result += ctx.getResult(*component);
377 ++i;
378 if (i < arg.list().size())
379 result += '+';
380 continue;
381 }
382 result += ctx.buildFunction(*component, ctx.dependsOnData()) + "(params, obs, xlArr)";
383 ++i;
384 if (i < arg.list().size())
385 result += '+';
386 }
387 if (arg.list().size() > 1)
388 result += ')';
389 ctx.addResult(&arg, result);
390}
391
393{
394 arg.fillBuffer();
395 ctx.addResult(&arg, ctx.buildCall(mathFunc("bernstein"), arg.x(), arg.xmin(), arg.xmax(), arg.coefList(),
396 arg.coefList().size()));
397}
398
400{
401 ctx.addResult(&arg,
402 ctx.buildCall(mathFunc("bifurGauss"), arg.getX(), arg.getMean(), arg.getSigmaL(), arg.getSigmaR()));
403}
404
406{
407 ctx.addResult(
408 &arg, ctx.buildCall(mathFunc("cbShape"), arg.getM(), arg.getM0(), arg.getSigma(), arg.getAlpha(), arg.getN()));
409}
410
412{
413 // first bring the range of the variable _x to the normalised range [-1, 1]
414 // calculate sum_k c_k T_k(x) where x is given in the normalised range,
415 // c_0 = 1, and the higher coefficients are given in _coefList
416 double xmax = static_cast<RooAbsRealLValue const &>(arg.x()).getMax(arg.refRangeName());
417 double xmin = static_cast<RooAbsRealLValue const &>(arg.x()).getMin(arg.refRangeName());
418
419 ctx.addResult(&arg,
420 ctx.buildCall(mathFunc("chebychev"), arg.coefList(), arg.coefList().size(), arg.x(), xmin, xmax));
421}
422
424{
425 ctx.addResult(&arg, doubleToString(arg.getVal()));
426}
427
429{
430 ctx.addResult(&arg, ctx.buildCall(mathFunc("constraintSum"), arg.list(), arg.list().size()));
431}
432
433// Generate RooFit codegen wrappers for RooFunctorBinding and similar objects,
434// emitting both the primal function call and its gradient pullback for
435// Clad-based AD.
436template <class RooArg_t>
437void functorCodegenImpl(RooArg_t &arg, RooArgList const &variables, CodegenContext &ctx)
438{
439 if (!arg.function()->HasGradient()) {
440 std::stringstream errorMsg;
441 errorMsg << "Functor wrapped by \"" << arg.GetName() << "\" doesn't provide a gradient function."
442 << " RooFit codegen is therefore not supported.";
443 oocoutE(&arg, InputArguments) << errorMsg.str() << std::endl;
444 throw std::runtime_error(errorMsg.str());
445 }
446
447 std::string funcAddrStr = TString::Format("0x%zx", reinterpret_cast<std::size_t>(arg.function())).Data();
448 std::string wrapperName = "roo_functor_" + funcAddrStr;
449
450 static std::unordered_set<std::string> wrapperNames;
451
452 if (wrapperNames.find(wrapperName) == wrapperNames.end()) {
453
454 wrapperNames.insert(wrapperName);
455
456 std::string pullbackName = wrapperName + "_pullback";
457 std::string nStr = std::to_string(std::size(variables));
458
459 std::string type;
460 if constexpr (std::is_same_v<RooArg_t, RooFunctor1DBinding> || std::is_same_v<RooArg_t, RooFunctor1DPdfBinding>)
461 type = "::ROOT::Math::IGradientFunctionOneDim";
462 else
463 type = "::ROOT::Math::IGradientFunctionMultiDim";
464
465 std::string funcAddrCasted = "reinterpret_cast<" + type + " const *>(" + funcAddrStr + ")";
466
467 std::string code;
468
469 code += "double " + wrapperName +
470 "(double const *x) {\n"
471 " return " +
472 funcAddrCasted +
473 "->operator()(x);\n"
474 "}\n\n"
475 "namespace clad::custom_derivatives {\n\n"
476 "void " +
477 pullbackName +
478 "(double const* x, double d_y, double *d_x) {\n"
479 " double output[" +
480 nStr +
481 "]{};\n"
482 " " +
483 funcAddrCasted +
484 "->Gradient(x, output);\n"
485 " for (int i = 0; i < " +
486 nStr +
487 "; ++i) {\n"
488 " d_x[i] += output[i] * d_y;\n"
489 " }\n"
490 "}\n"
491 "} // namespace clad::custom_derivatives\n";
492
493 gInterpreter->Declare(code.c_str());
494 }
495
496 ctx.addResult(&arg, ctx.buildCall(wrapperName, variables));
497}
498
500{
501 functorCodegenImpl(arg, arg.variable(), ctx);
502}
503
505{
506 functorCodegenImpl(arg, arg.variable(), ctx);
507}
508
510{
511 functorCodegenImpl(arg, arg.variables(), ctx);
512}
513
515{
516 functorCodegenImpl(arg, arg.variables(), ctx);
517}
518
520{
521 ctx.addResult(&arg, ctx.buildCall("TMath::GammaDist", arg.getX(), arg.getGamma(), arg.getMu(), arg.getBeta()));
522}
523
525{
526 arg.getVal(); // to trigger the creation of the TFormula
527 std::string funcName = arg.getUniqueFuncName();
528 ctx.collectFunction(funcName);
529 // We have to force the array type to be "double" because that's what the
530 // declared function wrapped by the TFormula expects.
531 auto inputVar = ctx.buildArg(arg.dependents(), /*arrayType=*/"double");
532 ctx.addResult(&arg, funcName + "(" + inputVar + ")");
533}
534
536{
537 ctx.addResult(&arg, ctx.buildCall(mathFunc("effProd"), arg.eff(), arg.pdf()));
538}
539
541{
542 RooAbsCategory const &cat = arg.cat();
543 int sigCatIndex = cat.lookupIndex(arg.sigCatName());
544 ctx.addResult(&arg, ctx.buildCall(mathFunc("efficiency"), arg.effFunc(), cat, sigCatIndex));
545}
546
548{
549 // Build a call to the stateless exponential defined later.
550 std::string coef;
551 if (arg.negateCoefficient()) {
552 coef += "-";
553 }
554 coef += ctx.getResult(arg.coefficient());
555 ctx.addResult(&arg, "std::exp(" + coef + " * " + ctx.getResult(arg.variable()) + ")");
556}
557
559{
560 // Use the result of the underlying pdf.
561 ctx.addResult(&arg, ctx.getResult(arg.pdf()));
562}
563
565{
566 // Build a call to the stateless gaussian defined later.
567 ctx.addResult(&arg, ctx.buildCall(mathFunc("gaussian"), arg.getX(), arg.getMean(), arg.getSigma()));
568}
569
571{
572 arg.getVal(); // to trigger the creation of the TFormula
573 std::string funcName = arg.getUniqueFuncName();
574 ctx.collectFunction(funcName);
575 // We have to force the array type to be "double" because that's what the
576 // declared function wrapped by the TFormula expects.
577 auto inputVar = ctx.buildArg(arg.dependents(), /*arrayType=*/"double");
578 ctx.addResult(&arg, funcName + "(" + inputVar + ")");
579}
580
582{
583 rooHistTranslateImpl(arg, ctx, arg.getInterpolationOrder(), arg.dataHist(), arg.variables(), false,
584 arg.getCdfBoundaries());
585}
586
588{
589 rooHistTranslateImpl(arg, ctx, arg.getInterpolationOrder(), arg.dataHist(), arg.variables(), !arg.haveUnitNorm(),
590 arg.getCdfBoundaries());
591}
592
594{
595 ctx.addResult(&arg, ctx.buildCall(mathFunc("landau"), arg.getX(), arg.getMean(), arg.getSigma()));
596}
597
599{
600 std::string funcName = arg.useStandardParametrization() ? "logNormalStandard" : "logNormal";
601 ctx.addResult(&arg, ctx.buildCall(mathFunc(funcName), arg.getX(), arg.getShapeK(), arg.getMedian()));
602}
603
604namespace {
605
606void codegenChi2(RooFit::Detail::RooNLLVarNew &arg, CodegenContext &ctx)
607{
608 using FuncMode = RooFit::Detail::RooNLLVarNew::FuncMode;
609
610 std::string resName = RooFit::Detail::makeValidVarName(arg.GetName()) + "Result";
611 ctx.addResult(&arg, resName);
612 ctx.addToGlobalScope("double " + resName + " = 0.0;\n");
613
614 // DataError::None means "no errors": every bin contributes zero.
615 if (arg.chi2ErrorType() == RooDataHist::None) {
616 return;
617 }
618
619 // Compute the per-bin normalization factor (constant with respect to the
620 // loop).
621 std::string normFactor;
622 if (arg.funcMode() == FuncMode::Function) {
623 normFactor = "1.0";
624 } else if (arg.funcMode() == FuncMode::ExtendedPdf) {
625 normFactor = ctx.getResult(*arg.expectedEvents());
626 } else { // Pdf
627 std::string weightSumName = RooFit::Detail::makeValidVarName(arg.GetName()) + "WeightSum";
628 ctx.addToGlobalScope("double " + weightSumName + " = 0.0;\n");
629 {
630 auto scope = ctx.beginLoop(&arg);
631 ctx.addToCodeBody(weightSumName + " += " + ctx.getResult(arg.weightVar()) + ";\n");
632 }
633 normFactor = weightSumName;
634 }
635
636 auto scope = ctx.beginLoop(&arg);
637 const std::string mu =
638 "(" + ctx.getResult(arg.func()) + " * " + ctx.getResult(*arg.binVolumes()) + " * " + normFactor + ")";
639
640 std::string term;
641 switch (arg.chi2ErrorType()) {
642 case RooDataHist::Expected: term = ctx.buildCall(mathFunc("chi2Expected"), mu, arg.weightVar()); break;
644 term = ctx.buildCall(mathFunc("chi2Symmetric"), mu, arg.weightVar(), arg.weightSquaredVar());
645 break;
647 term = ctx.buildCall(mathFunc("chi2Asymmetric"), mu, arg.weightVar(), *arg.weightErrLo(), *arg.weightErrHi());
648 break;
649 default: break;
650 }
651 ctx.addToCodeBody(&arg, resName + " += " + term + ";");
652}
653
654} // namespace
655
656void codegenImpl(RooFit::Detail::RooNLLVarNew &arg, CodegenContext &ctx)
657{
658 if (arg.statistic() == RooFit::Detail::RooNLLVarNew::Statistic::Chi2) {
659 return codegenChi2(arg, ctx);
660 }
661
662 if (arg.binnedL() && !arg.func().getAttribute("BinnedLikelihoodActiveYields")) {
663 std::stringstream errorMsg;
664 errorMsg << "codegen: binned likelihood optimization is only supported when raw pdf "
665 "values can be interpreted as yields."
666 << " This is not the case for HistFactory models written with ROOT versions before 6.26.00";
667 oocoutE(&arg, InputArguments) << errorMsg.str() << std::endl;
668 throw std::runtime_error(errorMsg.str());
669 }
670
671 std::string weightSumName = RooFit::Detail::makeValidVarName(arg.GetName()) + "WeightSum";
672 std::string resName = RooFit::Detail::makeValidVarName(arg.GetName()) + "Result";
673 ctx.addResult(&arg, resName);
674 ctx.addToGlobalScope("double " + weightSumName + " = 0.0;\n");
675 ctx.addToGlobalScope("double " + resName + " = 0.0;\n");
676
677 const bool needWeightSum = arg.expectedEvents() || arg.simCount() > 1;
678
679 if (needWeightSum) {
680 auto scope = ctx.beginLoop(&arg);
681 ctx.addToCodeBody(weightSumName + " += " + ctx.getResult(arg.weightVar()) + ";\n");
682 }
683 if (arg.simCount() > 1) {
684 std::string simCountStr = std::to_string(static_cast<double>(arg.simCount()));
685 ctx.addToCodeBody(resName + " += " + weightSumName + " * std::log(" + simCountStr + ");\n");
686 }
687
688 // Begin loop scope for the observables and weight variable. If the weight
689 // is a scalar, the context will ignore it for the loop scope. The closing
690 // brackets of the loop is written at the end of the scopes lifetime.
691 {
692 auto scope = ctx.beginLoop(&arg);
693 std::string term = ctx.buildCall(mathFunc("nll"), arg.func(), arg.weightVar(), arg.binnedL(), 0);
694 ctx.addToCodeBody(&arg, resName + " += " + term + ";");
695 }
696 if (arg.expectedEvents()) {
697 std::string expected = ctx.getResult(*arg.expectedEvents());
698 ctx.addToCodeBody(resName + " += " + expected + " - " + weightSumName + " * std::log(" + expected + ");\n");
699 }
700}
701
703{
704 // For now just return function/normalization integral.
705 ctx.addResult(&arg, ctx.getResult(arg.pdf()) + "/" + ctx.getResult(arg.normIntegral()));
706}
707
709{
710 std::string const &idx = arg.dataHist().calculateTreeIndexForCodeSquash(ctx, arg.xList());
711 std::string arrName = ctx.buildArg(arg.paramList());
712 std::stringstream result;
713 result << arrName << "[" << idx << "]";
714 if (arg.relParam()) {
715 // get weight[idx] * binv[idx]. Here we get the bin volume for the first element as we assume the distribution to
716 // be binned uniformly.
717 double binV = arg.dataHist().binVolume(0);
718 std::string weightArr = arg.dataHist().declWeightArrayForCodeSquash(ctx, false);
719 result << " * *(" << weightArr << " + " << idx + ") * " << doubleToString(binV);
720 }
721 ctx.addResult(&arg, result.str());
722}
723
725{
726 std::string xName = ctx.getResult(arg.getX());
727 if (!arg.getNoRounding())
728 xName = "std::floor(" + xName + ")";
729
730 ctx.addResult(&arg, ctx.buildCall(mathFunc("poisson"), xName, arg.getMean()));
731}
732
734{
735 const unsigned sz = arg.coefList().size();
736 if (!sz) {
737 ctx.addResult(&arg, std::to_string(arg.lowestOrder() ? 1. : 0.));
738 return;
739 }
740
741 ctx.addResult(&arg, ctx.buildCall(mathFunc("polynomial"), arg.coefList(), sz, arg.lowestOrder(), arg.x()));
742}
743
745{
746 const unsigned sz = arg.coefList().size();
747 if (!sz) {
748 ctx.addResult(&arg, std::to_string(arg.lowestOrder() ? 1. : 0.));
749 return;
750 }
751
752 ctx.addResult(&arg, ctx.buildCall(mathFunc("polynomial<true>"), arg.coefList(), sz, arg.lowestOrder(), arg.x()));
753}
754
756{
757 ctx.addResult(&arg, ctx.buildCall(mathFunc("product"), arg.realComponents(), arg.realComponents().size()));
758}
759
761{
762 ctx.addResult(&arg, ctx.buildCall(mathFunc("ratio"), arg.numerator(), arg.denominator()));
763}
764
765namespace {
766
767std::string codegenIntegral(RooAbsReal &arg, int code, const char *rangeName, CodegenContext &ctx)
768{
769 using Func = std::string (*)(RooAbsReal &, int, const char *, CodegenContext &);
770
771 Func func;
772
773 TClass *tclass = arg.IsA();
774
775 // Cache the overload resolutions
776 static std::unordered_map<TClass *, Func> dispatchMap;
777
778 auto found = dispatchMap.find(tclass);
779
780 if (found != dispatchMap.end()) {
781 func = found->second;
782 } else {
783 // Can probably done with CppInterop in the future to avoid string manipulation.
784 std::stringstream cmd;
785 cmd << "&RooFit::Experimental::CodegenIntegralImplCaller<" << tclass->GetName() << ">::call;";
786 func = reinterpret_cast<Func>(gInterpreter->ProcessLine(cmd.str().c_str()));
787 dispatchMap[tclass] = func;
788 }
789
790 return func(arg, code, rangeName, ctx);
791}
792
793} // namespace
794
796{
797 if (arg.numIntCatVars().empty() && arg.numIntRealVars().empty()) {
798 ctx.addResult(&arg, codegenIntegral(const_cast<RooAbsReal &>(arg.integrand()), arg.mode(), arg.intRange(), ctx));
799 return;
800 }
801
802 if (arg.intVars().size() != 1 || arg.numIntRealVars().size() != 1) {
803 std::stringstream errorMsg;
804 errorMsg << "Only analytical integrals and 1D numeric integrals are supported for AD for class"
805 << arg.integrand().GetName();
806 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
807 throw std::runtime_error(errorMsg.str().c_str());
808 }
809
810 auto &intVar = static_cast<RooAbsRealLValue &>(*arg.numIntRealVars()[0]);
811
812 std::string obsName = ctx.getTmpVarName();
813 std::string oldIntVarResult = ctx.getResult(intVar);
814 ctx.addResult(&intVar, "obs[0]");
815
816 std::string funcName = ctx.buildFunction(arg.integrand(), {});
817
818 std::stringstream ss;
819
820 ss << "double " << obsName << "[1];\n";
821
822 std::string resName = RooFit::Detail::makeValidVarName(arg.GetName()) + "Result";
823 ctx.addResult(&arg, resName);
824 ctx.addToGlobalScope("double " + resName + " = 0.0;\n");
825
826 // TODO: once Clad has support for higher-order functions (follow also the
827 // Clad issue #637), we could refactor this code into an actual function
828 // instead of hardcoding it here as a string.
829 ss << "{\n"
830 << " const int n = 1000; // number of sampling points\n"
831 << " double d = " << intVar.getMax(arg.intRange()) << " - " << intVar.getMin(arg.intRange()) << ";\n"
832 << " double eps = d / n;\n"
833 << " #pragma clad checkpoint loop\n"
834 << " for (int i = 0; i < n; ++i) {\n"
835 << " " << obsName << "[0] = " << intVar.getMin(arg.intRange()) << " + eps * i;\n"
836 << " double tmpA = " << funcName << "(params, " << obsName << ", xlArr);\n"
837 << " " << obsName << "[0] = " << intVar.getMin(arg.intRange()) << " + eps * (i + 1);\n"
838 << " double tmpB = " << funcName << "(params, " << obsName << ", xlArr);\n"
839 << " " << resName << " += (tmpA + tmpB) * 0.5 * eps;\n"
840 << " }\n"
841 << "}\n";
842
843 ctx.addToGlobalScope(ss.str());
844
845 ctx.addResult(&intVar, oldIntVarResult);
846}
847
849{
850 ctx.addResult(&arg, realSumPdfTranslateImpl(ctx, arg.funcList(), arg.coefList(), false));
851}
852
854{
855 ctx.addResult(&arg, realSumPdfTranslateImpl(ctx, arg.funcList(), arg.coefList(), false));
856}
857
859{
860 if (!arg.isConstant()) {
861 ctx.addResult(&arg, arg.GetName());
862 }
863 ctx.addResult(&arg, doubleToString(arg.getVal()));
864}
865
867{
868 ctx.addResult(&arg, ctx.buildCall(mathFunc("recursiveFraction"), arg.variables(), arg.variables().size()));
869}
870
872{
873 auto const &interpCodes = arg.interpolationCodes();
874
875 unsigned int n = interpCodes.size();
876
877 int interpCode = interpCodes[0];
878 // To get consistent codes with the PiecewiseInterpolation
879 if (interpCode == 4) {
880 interpCode = 5;
881 }
882
883 for (unsigned int i = 1; i < n; i++) {
884 if (interpCodes[i] != interpCodes[0]) {
886 << "FlexibleInterpVar::evaluate ERROR: Code Squashing AD does not yet support having "
887 "different interpolation codes for the same class object "
888 << std::endl;
889 }
890 }
891
892 std::string const &resName = ctx.buildCall(mathFunc("flexibleInterp"), interpCode, arg.variables(), n, arg.low(),
893 arg.high(), arg.globalBoundary(), arg.nominal(), 1.0);
894 ctx.addResult(&arg, resName);
895}
896
898{
899 ctx.addResult(&arg, "1.0");
900}
901
903{
904 ctx.addResult(&arg, ctx.getResult(arg.function()));
905}
906
907////////////////////////////////////////////////////////////////////////////////
908/// This function defines the analytical integral translation for the class.
909///
910/// \param[in] code The code that decides the integrands.
911/// \param[in] rangeName Name of the normalization range.
912/// \param[in] ctx An object to manage auxiliary information for code-squashing.
913///
914/// \returns The representative code string of the integral for the given object.
915std::string codegenIntegralImpl(RooAbsReal &arg, int, const char *, CodegenContext &)
916{
917 std::stringstream errorMsg;
918 errorMsg << "An analytical integral function for class \"" << arg.ClassName() << "\" has not yet been implemented.";
919 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
920 throw std::runtime_error(errorMsg.str().c_str());
921}
922
923std::string codegenIntegralImpl(RooBernstein &arg, int, const char *rangeName, CodegenContext &ctx)
924{
925 arg.fillBuffer(); // to get the right xmin() and xmax()
926 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
927 return ctx.buildCall(mathFunc("bernsteinIntegral"), x.getMin(rangeName), x.getMax(rangeName), arg.xmin(), arg.xmax(),
928 arg.coefList(), arg.coefList().size());
929}
930
931std::string codegenIntegralImpl(RooBifurGauss &arg, int code, const char *rangeName, CodegenContext &ctx)
932{
933 auto &constant = code == 1 ? arg.getMean() : arg.getX();
934 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(code == 1 ? arg.getX() : arg.getMean());
935
936 return ctx.buildCall(mathFunc("bifurGaussIntegral"), integrand.getMin(rangeName), integrand.getMax(rangeName),
937 constant, arg.getSigmaL(), arg.getSigmaR());
938}
939
940std::string codegenIntegralImpl(RooCBShape &arg, int /*code*/, const char *rangeName, CodegenContext &ctx)
941{
942 auto &m = dynamic_cast<RooAbsRealLValue const &>(arg.getM());
943 return ctx.buildCall(mathFunc("cbShapeIntegral"), m.getMin(rangeName), m.getMax(rangeName), arg.getM0(),
944 arg.getSigma(), arg.getAlpha(), arg.getN());
945}
946
947std::string codegenIntegralImpl(RooChebychev &arg, int, const char *rangeName, CodegenContext &ctx)
948{
949 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
950 double xmax = x.getMax(arg.refRangeName());
951 double xmin = x.getMin(arg.refRangeName());
952 unsigned int sz = arg.coefList().size();
953
954 return ctx.buildCall(mathFunc("chebychevIntegral"), arg.coefList(), sz, xmin, xmax, x.getMin(rangeName),
955 x.getMax(rangeName));
956}
957
958std::string codegenIntegralImpl(RooEfficiency &, int, const char *, CodegenContext &)
959{
960 return "1.0";
961}
962
963std::string codegenIntegralImpl(RooExponential &arg, int code, const char *rangeName, CodegenContext &ctx)
964{
965 bool isOverX = code == 1;
966
967 std::string constant;
968 if (arg.negateCoefficient() && isOverX) {
969 constant += "-";
970 }
971 constant += ctx.getResult(isOverX ? arg.coefficient() : arg.variable());
972
973 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(isOverX ? arg.variable() : arg.coefficient());
974
975 double min = integrand.getMin(rangeName);
976 double max = integrand.getMax(rangeName);
977
978 if (!isOverX && arg.negateCoefficient()) {
979 std::swap(min, max);
980 min = -min;
981 max = -max;
982 }
983
984 return ctx.buildCall(mathFunc("exponentialIntegral"), min, max, constant);
985}
986
987std::string codegenIntegralImpl(RooGamma &arg, int, const char *rangeName, CodegenContext &ctx)
988{
989 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.getX());
990 const std::string a =
991 ctx.buildCall("ROOT::Math::gamma_cdf", x.getMax(rangeName), arg.getGamma(), arg.getBeta(), arg.getMu());
992 const std::string b =
993 ctx.buildCall("ROOT::Math::gamma_cdf", x.getMin(rangeName), arg.getGamma(), arg.getBeta(), arg.getMu());
994 return a + " - " + b;
995}
996
997std::string codegenIntegralImpl(RooGaussian &arg, int code, const char *rangeName, CodegenContext &ctx)
998{
999 auto &constant = code == 1 ? arg.getMean() : arg.getX();
1000 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(code == 1 ? arg.getX() : arg.getMean());
1001
1002 return ctx.buildCall(mathFunc("gaussianIntegral"), integrand.getMin(rangeName), integrand.getMax(rangeName),
1003 constant, arg.getSigma());
1004}
1005
1006namespace {
1007
1008std::string rooHistIntegralTranslateImpl(int code, RooAbsArg const &arg, RooDataHist const &dataHist,
1009 const RooArgSet &obs, bool histFuncMode)
1010{
1011 if (((2 << obs.size()) - 1) != code) {
1012 oocoutE(&arg, InputArguments) << "RooHistPdf::integral(" << arg.GetName()
1013 << ") ERROR: AD currently only supports integrating over all histogram observables."
1014 << std::endl;
1015 return "";
1016 }
1017 return doubleToString(dataHist.sum(histFuncMode));
1018}
1019
1020} // namespace
1021
1022std::string codegenIntegralImpl(RooHistFunc &arg, int code, const char *, CodegenContext &)
1023{
1024 return rooHistIntegralTranslateImpl(code, arg, arg.dataHist(), arg.variables(), true);
1025}
1026
1027std::string codegenIntegralImpl(RooHistPdf &arg, int code, const char *, CodegenContext &)
1028{
1029 return rooHistIntegralTranslateImpl(code, arg, arg.dataHist(), arg.variables(), false);
1030}
1031
1032std::string codegenIntegralImpl(RooLandau &arg, int, const char *rangeName, CodegenContext &ctx)
1033{
1034 // Don't do anything with "code". It can only be "1" anyway (see
1035 // implementation of getAnalyticalIntegral).
1036 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.getX());
1037 const std::string a = ctx.buildCall("ROOT::Math::landau_cdf", x.getMax(rangeName), arg.getSigma(), arg.getMean());
1038 const std::string b = ctx.buildCall("ROOT::Math::landau_cdf", x.getMin(rangeName), arg.getSigma(), arg.getMean());
1039 return ctx.getResult(arg.getSigma()) + " * " + "(" + a + " - " + b + ")";
1040}
1041
1042std::string codegenIntegralImpl(RooLognormal &arg, int, const char *rangeName, CodegenContext &ctx)
1043{
1044 std::string funcName = arg.useStandardParametrization() ? "logNormalIntegralStandard" : "logNormalIntegral";
1045 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.getX());
1046 return ctx.buildCall(mathFunc(funcName), x.getMin(rangeName), x.getMax(rangeName), arg.getMedian(), arg.getShapeK());
1047}
1048
1049std::string codegenIntegralImpl(RooMultiVarGaussian &arg, int code, const char *rangeName, CodegenContext &)
1050{
1051 if (code != -1) {
1052 std::stringstream errorMsg;
1053 errorMsg << "Partial integrals over RooMultiVarGaussian are not supported.";
1054 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
1055 throw std::runtime_error(errorMsg.str().c_str());
1056 }
1057
1058 return doubleToString(arg.analyticalIntegral(code, rangeName));
1059}
1060
1062{
1063 std::stringstream ss;
1064 ss << arg.outerWrapperName() << "(";
1065 for (std::size_t i = 0; i < arg.nInputTensors(); ++i) {
1066 ss << ctx.buildArg(arg.inputTensorList(i)) << std::endl;
1067 if (i != arg.nInputTensors() - 1) {
1068 ss << ", ";
1069 }
1070 }
1071 ss << ")";
1072
1073 ctx.addResult(&arg, ss.str());
1074}
1075
1076std::string codegenIntegralImpl(RooPoisson &arg, int code, const char *rangeName, CodegenContext &ctx)
1077{
1078 assert(code == 1 || code == 2);
1079 std::string xName = ctx.getResult(arg.getX());
1080 if (!arg.getNoRounding())
1081 xName = "std::floor(" + xName + ")";
1082
1083 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(code == 1 ? arg.getX() : arg.getMean());
1084 // Since the integral function is the same for both codes, we need to make sure the indexed observables do not appear
1085 // in the function if they are not required.
1086 xName = code == 1 ? "0" : xName;
1087 return ctx.buildCall(mathFunc("poissonIntegral"), code, arg.getMean(), xName, integrand.getMin(rangeName),
1088 integrand.getMax(rangeName), arg.getProtectNegativeMean());
1089}
1090
1091std::string codegenIntegralImpl(RooPolyVar &arg, int, const char *rangeName, CodegenContext &ctx)
1092{
1093 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
1094 const double xmin = x.getMin(rangeName);
1095 const double xmax = x.getMax(rangeName);
1096 const unsigned sz = arg.coefList().size();
1097 if (!sz)
1098 return std::to_string(arg.lowestOrder() ? xmax - xmin : 0.0);
1099
1100 return ctx.buildCall(mathFunc("polynomialIntegral"), arg.coefList(), sz, arg.lowestOrder(), xmin, xmax);
1101}
1102
1103std::string codegenIntegralImpl(RooPolynomial &arg, int, const char *rangeName, CodegenContext &ctx)
1104{
1105 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
1106 const double xmin = x.getMin(rangeName);
1107 const double xmax = x.getMax(rangeName);
1108 const unsigned sz = arg.coefList().size();
1109 if (!sz)
1110 return std::to_string(arg.lowestOrder() ? xmax - xmin : 0.0);
1111
1112 return ctx.buildCall(mathFunc("polynomialIntegral<true>"), arg.coefList(), sz, arg.lowestOrder(), xmin, xmax);
1113}
1114
1115std::string codegenIntegralImpl(RooRealSumPdf &arg, int code, const char *rangeName, CodegenContext &ctx)
1116{
1117 // Re-use translate, since integration is linear.
1118 return realSumPdfTranslateImpl(ctx, arg.funcIntListFromCache(code, rangeName), arg.coefList(), false);
1119}
1120
1121std::string codegenIntegralImpl(RooUniform &arg, int code, const char *rangeName, CodegenContext &)
1122{
1123 // The integral of a uniform distribution is static, so we can just hardcode
1124 // the result in a string.
1125 return doubleToString(arg.analyticalIntegral(code, rangeName));
1126}
1127
1128} // namespace RooFit::Experimental
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
#define oocoutE(o, a)
#define ooccoutE(o, a)
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
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
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:142
float xmin
float xmax
#define gInterpreter
A class which maps the current values of a RooRealVar (or a set of RooRealVars) to one of a number of...
const RooArgList & paramList() const
const RooArgList & dataVars() const
RooDataHist const & dataHist() const
The PiecewiseInterpolation is a class that can morph distributions into each other,...
const RooArgList & highList() const
const RooAbsReal * nominalHist() const
Return pointer to the nominal hist function.
const RooArgList & lowList() const
const RooArgList & paramList() const
const std::vector< int > & interpolationCodes() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
bool isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:283
virtual bool isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition RooAbsArg.h:175
Abstract base class for RooRealVar binning definitions.
Int_t numBins() const
Return number of bins.
virtual double highBound() const =0
virtual double lowBound() const =0
A space to attach TBranches.
value_type lookupIndex(const std::string &stateName) const
Find the index number corresponding to the state name.
Storage_t::size_type size() const
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:107
TClass * IsA() const override
Definition RooAbsReal.h:553
Efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:32
const RooArgList & coefList() const
Definition RooAddPdf.h:73
const RooArgList & pdfList() const
Definition RooAddPdf.h:69
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition RooAddition.h:27
const RooArgList & list() const
Definition RooAddition.h:42
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Bernstein basis polynomials are positive-definite in the range [0,1].
void fillBuffer() const
RooAbsRealLValue const & x() const
RooArgList const & coefList() const
double xmax() const
double xmin() const
Bifurcated Gaussian p.d.f with different widths on left and right side of maximum value.
RooAbsReal const & getSigmaL() const
Get the left sigma parameter.
RooAbsReal const & getSigmaR() const
Get the right sigma parameter.
RooAbsReal const & getX() const
Get the x variable.
RooAbsReal const & getMean() const
Get the mean parameter.
PDF implementing the Crystal Ball line shape.
Definition RooCBShape.h:24
RooAbsReal const & getSigma() const
Definition RooCBShape.h:43
RooAbsReal const & getM() const
Definition RooCBShape.h:41
RooAbsReal const & getN() const
Definition RooCBShape.h:45
RooAbsReal const & getM0() const
Definition RooCBShape.h:42
RooAbsReal const & getAlpha() const
Definition RooCBShape.h:44
Object to represent discrete states.
Definition RooCategory.h:28
value_type getCurrentIndex() const final
Return current index.
Definition RooCategory.h:40
Chebychev polynomial p.d.f.
RooAbsReal const & x() const
RooArgList const & coefList() const
const char * refRangeName() const
Represents a constant real-valued object.
Definition RooConstVar.h:23
Calculates the sum of the -(log) likelihoods of a set of RooAbsPfs that represent constraint function...
const RooArgList & list() const
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
double sum(bool correctForBinSize, bool inverseCorr=false) const
Return the sum of the weights of all bins in the histogram.
std::vector< std::unique_ptr< const RooAbsBinning > > const & getBinnings() const
std::string declWeightArrayForCodeSquash(RooFit::Experimental::CodegenContext &ctx, bool correctForBinSize) const
double weight(std::size_t i) const
Return weight of i-th bin.
std::string calculateTreeIndexForCodeSquash(RooFit::Experimental::CodegenContext &ctx, const RooAbsCollection &coords, bool reverse=false) const
double binVolume(std::size_t i) const
Return bin volume of i-th bin.
The class RooEffProd implements the product of a PDF with an efficiency function.
Definition RooEffProd.h:19
RooAbsReal const & pdf() const
Definition RooEffProd.h:31
RooAbsReal const & eff() const
Definition RooEffProd.h:32
A PDF helper class to fit efficiencies parameterized by a supplied function F.
RooAbsCategory const & cat() const
RooAbsReal const & effFunc() const
std::string sigCatName() const
Exponential PDF.
bool negateCoefficient() const
RooAbsReal const & coefficient() const
Get the coefficient "c".
RooAbsReal const & variable() const
Get the x variable.
RooExtendPdf is a wrapper around an existing PDF that adds a parameteric extended likelihood term to ...
RooAbsPdf const & pdf() const
A RooProdPdf with a fixed normalization set can be replaced by this class.
Definition RooProdPdf.h:209
RooArgSet const * partList() const
Definition RooProdPdf.h:264
RooAbsReal const * rearrangedDen() const
Definition RooProdPdf.h:259
RooAbsReal const * rearrangedNum() const
Definition RooProdPdf.h:255
RooAbsReal const & normIntegral() const
RooAbsPdf const & pdf() const
A class to maintain the context for squashing of RooFit models into code.
void addToGlobalScope(std::string const &str)
Adds the given string to the string block that will be emitted at the top of the squashed function.
std::string const & getResult(RooAbsArg const &arg)
Gets the result for the given node using the node name.
std::string getTmpVarName() const
Get a unique variable name to be used in the generated code.
void addResult(RooAbsArg const *key, std::string const &value)
A function to save an expression that includes/depends on the result of the input node.
void addToCodeBody(RooAbsArg const *klass, std::string const &in)
Adds the input string to the squashed code body.
std::unique_ptr< LoopScope > beginLoop(RooAbsArg const *in)
Create a RAII scope for iterating over vector observables.
void collectFunction(std::string const &name)
Register a function that is only know to the interpreter to the context.
void addVecObs(const char *key, int idx)
Since the squashed code represents all observables as a single flattened array, it is important to ke...
int observableIndexOf(const RooAbsArg &arg) const
std::string buildArg(RooAbsCollection const &x, std::string const &arrayType="double")
Function to save a RooListProxy as an array in the squashed code.
std::string buildFunction(RooAbsArg const &arg, std::unordered_set< RooFit::Detail::DataKey > const &dependsOnData={})
Assemble and return the final code with the return expression and global statements.
std::string buildCall(std::string const &funcname, Args_t const &...args)
Build the code to call the function with name funcname, passing some arguments.
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
const RooArgList & dependents() const
std::string getUniqueFuncName() const
RooCFunction1Binding is a templated implementation of class RooAbsReal that binds generic C(++) funct...
RooAbsReal const & variable() const
RooAbsReal const & variable() const
RooFunctorBinding makes math functions from ROOT usable in RooFit.
RooArgList const & variables() const
RooFunctorPdfBinding makes math functions from ROOT usable as PDFs in RooFit.
RooArgList const & variables() const
Implementation of the Gamma PDF for RooFit/RooStats.
Definition RooGamma.h:20
RooAbsReal const & getX() const
Definition RooGamma.h:34
RooAbsReal const & getGamma() const
Definition RooGamma.h:35
RooAbsReal const & getBeta() const
Definition RooGamma.h:36
RooAbsReal const & getMu() const
Definition RooGamma.h:37
Plain Gaussian p.d.f.
Definition RooGaussian.h:24
RooAbsReal const & getX() const
Get the x variable.
Definition RooGaussian.h:45
RooAbsReal const & getMean() const
Get the mean parameter.
Definition RooGaussian.h:48
RooAbsReal const & getSigma() const
Get the sigma parameter.
Definition RooGaussian.h:51
Implementation of a probability density function that takes a RooArgList of servers and a C++ express...
const RooArgList & dependents() const
std::string getUniqueFuncName() const
A real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:29
Int_t getInterpolationOrder() const
Return histogram interpolation order.
Definition RooHistFunc.h:67
bool getCdfBoundaries() const
If true, special boundary conditions for c.d.f.s are used.
Definition RooHistFunc.h:83
RooDataHist & dataHist()
Return RooDataHist that is represented.
Definition RooHistFunc.h:43
RooArgSet const & variables() const
A probability density function sampled from a multidimensional histogram.
Definition RooHistPdf.h:29
Int_t getInterpolationOrder() const
Definition RooHistPdf.h:58
RooDataHist & dataHist()
Definition RooHistPdf.h:41
bool haveUnitNorm() const
Definition RooHistPdf.h:81
bool getCdfBoundaries() const
Definition RooHistPdf.h:72
RooArgSet const & variables() const
Definition RooHistPdf.h:97
Landau distribution p.d.f.
Definition RooLandau.h:24
RooAbsReal const & getSigma() const
Definition RooLandau.h:42
RooAbsReal const & getMean() const
Definition RooLandau.h:41
RooAbsReal const & getX() const
Definition RooLandau.h:40
RooFit Lognormal PDF.
bool useStandardParametrization() const
RooAbsReal const & getMedian() const
Get the median parameter.
RooAbsReal const & getShapeK() const
Get the shape parameter.
RooAbsReal const & getX() const
Get the x variable.
The class RooMultiPdf allows for the creation of a RooMultiPdf object, which can switch between previ...
Definition RooMultiPdf.h:9
const RooCategoryProxy & indexCategory() const
Definition RooMultiPdf.h:25
RooAbsPdf * getPdf(int index) const
Definition RooMultiPdf.h:31
int getNumPdfs() const
Definition RooMultiPdf.h:23
const RooListProxy & getPdfList() const
Definition RooMultiPdf.h:26
Multivariate Gaussian p.d.f.
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Handle full integral here.
const RooArgList & xVec() const
const TMatrixDSym & covarianceMatrixInverse() const
const RooArgList & muVec() const
RooONNXFunc wraps an ONNX model as a RooAbsReal, allowing it to be used as a building block in likeli...
Definition RooONNXFunc.h:21
std::string outerWrapperName() const
Definition RooONNXFunc.h:37
std::size_t nInputTensors() const
Definition RooONNXFunc.h:33
RooArgList const & inputTensorList(int iTensor) const
Definition RooONNXFunc.h:34
A histogram function that assigns scale parameters to every bin.
const RooArgList & paramList() const
const RooArgList & xList() const
const RooDataHist & dataHist() const
bool relParam() const
Poisson pdf.
Definition RooPoisson.h:18
RooAbsReal const & getX() const
Get the x variable.
Definition RooPoisson.h:44
bool getProtectNegativeMean() const
Definition RooPoisson.h:41
bool getNoRounding() const
Definition RooPoisson.h:36
RooAbsReal const & getMean() const
Get the mean parameter.
Definition RooPoisson.h:47
A RooAbsReal implementing a polynomial in terms of a list of RooAbsReal coefficients.
Definition RooPolyVar.h:25
RooArgList const & coefList() const
Definition RooPolyVar.h:38
int lowestOrder() const
Definition RooPolyVar.h:39
RooAbsReal const & x() const
Definition RooPolyVar.h:37
RooPolynomial implements a polynomial p.d.f of the form.
RooAbsReal const & x() const
Get the x variable.
int lowestOrder() const
Return the order for the first coefficient in the list.
RooArgList const & coefList() const
Get the coefficient list.
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
const RooArgList & realComponents() const
Definition RooProduct.h:50
Represents the ratio of two RooAbsReal objects.
Definition RooRatio.h:21
RooAbsReal const & numerator() const
Definition RooRatio.h:34
RooAbsReal const & denominator() const
Definition RooRatio.h:35
Performs hybrid numerical/analytical integrals of RooAbsReal objects.
const RooArgSet & numIntRealVars() const
RooArgSet intVars() const
const RooAbsReal & integrand() const
const RooArgSet & numIntCatVars() const
const char * intRange() const
const RooArgList & coefList() const
const RooArgList & funcList() const
Implements a PDF constructed from a sum of functions:
const RooArgList & funcList() const
const RooArgList & funcIntListFromCache(Int_t code, const char *rangeName=nullptr) const
Collect the list of functions to be integrated from the cache.
const RooArgList & coefList() const
Variable that can be changed from the outside.
Definition RooRealVar.h:37
A RooAbsReal implementation that calculates the plain fraction of sum of RooAddPdf components from a ...
RooArgList const & variables() const
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
RooAbsPdf * getPdf(RooStringView catName) const
Return the p.d.f associated with the given index category name.
const RooAbsCategoryLValue & indexCat() const
const std::vector< int > & interpolationCodes() const
const RooListProxy & variables() const
const std::vector< double > & high() const
const std::vector< double > & low() const
Flat p.d.f.
Definition RooUniform.h:24
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Implement analytical integral.
The RooWrapperPdf is a class that can be used to convert a function into a PDF.
RooAbsReal const & function() const
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
const Element * GetMatrixArray() const override
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
const char * Data() const
Definition TString.h:385
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
std::string makeValidVarName(std::string const &in)
void codegenImpl(RooFit::Detail::RooFixedProdPdf &arg, CodegenContext &ctx)
void functorCodegenImpl(RooArg_t &arg, RooArgList const &variables, CodegenContext &ctx)
std::string codegenIntegralImpl(RooAbsReal &arg, int code, const char *rangeName, CodegenContext &ctx)
This function defines the analytical integral translation for the class.
@ InputArguments
TMarker m
Definition textangle.C:8
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2335