Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
JSONFactories_RooFitCore.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Carsten D. Burgard, DESY/ATLAS, Dec 2021
5 *
6 * Copyright (c) 2022, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
14
15#include <RooAbsCachedPdf.h>
16#include <RooAddPdf.h>
17#include <RooAddModel.h>
18#include <RooBinning.h>
19#include <RooBinSamplingPdf.h>
20#include <RooBinWidthFunction.h>
21#include <RooCategory.h>
22#include <RooDataHist.h>
23#include <RooDecay.h>
24#include <RooDerivative.h>
25#include <RooExponential.h>
26#include <RooExtendPdf.h>
27#include <RooFFTConvPdf.h>
29#include <RooFitHS3/JSONIO.h>
30#include <RooFormulaVar.h>
31#include <RooGenericPdf.h>
32#include <RooHistFunc.h>
33#include <RooHistPdf.h>
34#include <RooLegacyExpPoly.h>
35#include <RooLognormal.h>
36#include <RooMultiVarGaussian.h>
38#include <RooAddition.h>
39#include <RooProduct.h>
40#include <RooProdPdf.h>
41#include <RooPoisson.h>
42#include <RooPolynomial.h>
43#include <RooPolyVar.h>
44#include <RooRealSumFunc.h>
45#include <RooRealSumPdf.h>
46#include <RooRealVar.h>
47#include <RooResolutionModel.h>
48#include <RooTFnBinding.h>
49#include <RooTruthModel.h>
50#include <RooGaussModel.h>
51#include <RooWrapperPdf.h>
52#include <RooWorkspace.h>
53#include <RooRealIntegral.h>
54#include <RooSpline.h>
55#include <TSpline.h>
56
57#include <TF1.h>
58#include <TH1.h>
59
60#include "JSONIOUtils.h"
61
62#include "static_execute.h"
63
64#include <algorithm>
65#include <cctype>
66#include <set>
67#include <string_view>
68
70
71///////////////////////////////////////////////////////////////////////////////////////////////////////
72// individually implemented importers
73///////////////////////////////////////////////////////////////////////////////////////////////////////
74
75namespace {
76bool isReservedExpressionIdentifier(const std::string &arg)
77{
78 return arg == "PI" || arg == "EULER" || arg == "TMath";
79}
80
81/**
82 * Extracts arguments from a mathematical expression.
83 *
84 * This function takes a string representing a mathematical
85 * expression and extracts the arguments from it. The arguments are
86 * defined as sequences of characters that do not contain digits,
87 * spaces, or parentheses, and that start with a letter. Function
88 * calls such as "exp( ... )", identified as being followed by an
89 * opening parenthesis, are not treated as arguments. The extracted
90 * arguments are returned as a vector of strings.
91 *
92 * @param expr A string representing a mathematical expression.
93 * @return A set of unique strings representing the extracted arguments.
94 */
95std::set<std::string> extractArguments(std::string expr)
96{
97 // Get rid of whitespaces
98 expr.erase(std::remove_if(expr.begin(), expr.end(), [](unsigned char c) { return std::isspace(c); }), expr.end());
99
100 std::set<std::string> arguments;
101 size_t startidx = expr.size();
102 for (size_t i = 0; i < expr.size(); ++i) {
103 if (startidx >= expr.size()) {
104 if (isalpha(expr[i])) {
105 startidx = i;
106 // check this character is not part of scientific notation, e.g. 2e-5
108 // if it is, we ignore this character
109 startidx = expr.size();
110 }
111 }
112 } else {
113 if (!isdigit(expr[i]) && !isalpha(expr[i]) && expr[i] != '_') {
114 if (expr[i] == '(') {
115 startidx = expr.size();
116 continue;
117 }
118 std::string arg(expr.substr(startidx, i - startidx));
119 startidx = expr.size();
121 arguments.insert(arg);
122 }
123 }
124 }
125 }
126 if (startidx < expr.size()) {
127 std::string arg(expr.substr(startidx));
129 arguments.insert(arg);
130 }
131 }
132 return arguments;
133}
134
135void replaceIdentifier(TString &expr, std::string_view identifier, std::string_view replacement)
136{
137 std::string in(expr.Data());
138 std::string out;
139 out.reserve(in.size());
140
141 for (std::size_t pos = 0; pos < in.size();) {
142 const bool matches = in.compare(pos, identifier.size(), identifier) == 0;
143 const bool beforeIdentifier =
144 pos > 0 && (std::isalnum(static_cast<unsigned char>(in[pos - 1])) || in[pos - 1] == '_');
145 const std::size_t end = pos + identifier.size();
146 const bool afterIdentifier =
147 end < in.size() && (std::isalnum(static_cast<unsigned char>(in[end])) || in[end] == '_');
148 if (matches && !beforeIdentifier && !afterIdentifier) {
149 out.append(replacement);
150 pos = end;
151 } else {
152 out.push_back(in[pos]);
153 ++pos;
154 }
155 }
156
157 expr = out.c_str();
158}
159
161{
162 replaceIdentifier(expr, "PI", "TMath::Pi()");
163 replaceIdentifier(expr, "EULER", "TMath::E()");
164}
165
166template <class RooArg_t>
168{
169 std::string name(RooJSONFactoryWSTool::name(p));
170 if (!p.has_child("expression")) {
171 RooJSONFactoryWSTool::error("no expression given for '" + name + "'");
172 }
173 TString formula(p["expression"].val());
175 RooArgList dependents;
176 for (const auto &d : extractArguments(formula.Data())) {
177 dependents.add(*tool->request<RooAbsReal>(d, name));
178 }
179 tool->wsImport(RooArg_t{name.c_str(), formula, dependents});
180 return true;
181}
182
183// Fast-path importers for RooProduct, RooAddition, and RooProdPdf that
184// bypass the generic factory-expression mechanism. The default path
185// generates a string expression and passes it to gROOT->ProcessLineFast(),
186// which invokes the Cling JIT for every single call. For workspaces with
187// thousands of product/sum nodes (a common shape for HistFactory models)
188// that JIT cost dominates JSON import time. Constructing the RooFit object
189// directly here keeps the work O(N) of cheap C++ calls.
191{
192 std::string name(RooJSONFactoryWSTool::name(p));
193 tool->wsEmplace<RooProduct>(name, tool->requestArgList<RooAbsReal>(p, "factors"));
194 return true;
195}
196
198{
199 std::string name(RooJSONFactoryWSTool::name(p));
200 tool->wsEmplace<RooProdPdf>(name, tool->requestArgList<RooAbsPdf>(p, "factors"));
201 return true;
202}
203
205{
206 std::string name(RooJSONFactoryWSTool::name(p));
207 tool->wsEmplace<RooAddition>(name, tool->requestArgList<RooAbsReal>(p, "summands"));
208 return true;
209}
210
212{
213 std::string name(RooJSONFactoryWSTool::name(p));
214 if (!tool->requestArgList<RooAbsReal>(p, "coefficients").empty()) {
215 tool->wsEmplace<RooAddPdf>(name, tool->requestArgList<RooAbsPdf>(p, "summands"),
216 tool->requestArgList<RooAbsReal>(p, "coefficients"));
217 return true;
218 }
219 tool->wsEmplace<RooAddPdf>(name, tool->requestArgList<RooAbsPdf>(p, "summands"));
220 return true;
221}
222
224{
225 std::string name(RooJSONFactoryWSTool::name(p));
226 tool->wsEmplace<RooAddModel>(name, tool->requestArgList<RooAbsPdf>(p, "summands"),
227 tool->requestArgList<RooAbsReal>(p, "coefficients"));
228 return true;
229}
230
231template <bool DivideByBinWidth>
233{
234 std::string name(RooJSONFactoryWSTool::name(p));
235 RooHistFunc *hf = static_cast<RooHistFunc *>(tool->request<RooAbsReal>(p["histogram"].val(), name));
237 return true;
238}
239
241{
242 std::string name(RooJSONFactoryWSTool::name(p));
243
244 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
245 RooRealVar *obs = tool->requestArg<RooRealVar>(p, "observable");
246
247 if (!pdf->dependsOn(*obs)) {
248 RooJSONFactoryWSTool::error(std::string("pdf '") + pdf->GetName() + "' does not depend on observable '" +
249 obs->GetName() + "' as indicated by parent RooBinSamplingPdf '" + name +
250 "', please check!");
251 }
252
253 if (!p.has_child("epsilon")) {
254 RooJSONFactoryWSTool::error("no epsilon given in '" + name + "'");
255 }
256 double epsilon(p["epsilon"].val_double());
257
258 tool->wsEmplace<RooBinSamplingPdf>(name, *obs, *pdf, epsilon);
259
260 return true;
261}
262
264{
265 std::string name(RooJSONFactoryWSTool::name(p));
266
267 bool extended = false;
268 if (p.has_child("extended") && p["extended"].val_bool()) {
269 extended = true;
270 }
271 tool->wsEmplace<RooRealSumPdf>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
272 tool->requestArgList<RooAbsReal>(p, "coefficients"), extended);
273 return true;
274}
275
277{
278 std::string name(RooJSONFactoryWSTool::name(p));
279 tool->wsEmplace<RooRealSumFunc>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
280 tool->requestArgList<RooAbsReal>(p, "coefficients"));
281 return true;
282}
283
284template <class RooArg_t>
286{
287 std::string name(RooJSONFactoryWSTool::name(p));
288 if (!p.has_child("coefficients")) {
289 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
290 }
291 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
292 RooArgList coefs;
293 int order = 0;
294 int lowestOrder = 0;
295 for (const auto &coef : p["coefficients"].children()) {
296 // As long as the coefficients match the default coefficients in
297 // RooFit, we don't have to instantiate RooFit objects but can
298 // increase the lowestOrder flag.
299 if (order == 0 && (coef.val() == "1.0" || coef.val() == "1")) {
300 ++lowestOrder;
301 } else if (coefs.empty() && (coef.val() == "0.0" || coef.val() == "0")) {
302 ++lowestOrder;
303 } else {
304 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
305 }
306 ++order;
307 }
308
309 tool->wsEmplace<RooArg_t>(name, *x, coefs, lowestOrder);
310 return true;
311}
312
314{
315 std::string name(RooJSONFactoryWSTool::name(p));
316 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
317 RooAbsReal *mean = tool->requestArg<RooAbsReal>(p, "mean");
318 tool->wsEmplace<RooPoisson>(name, *x, *mean, !p["integer"].val_bool());
319 return true;
320}
321
323{
324 std::string name(RooJSONFactoryWSTool::name(p));
325 RooRealVar *t = tool->requestArg<RooRealVar>(p, "t");
326 RooAbsReal *tau = tool->requestArg<RooAbsReal>(p, "tau");
327 RooResolutionModel *model = dynamic_cast<RooResolutionModel *>(tool->requestArg<RooAbsPdf>(p, "resolutionModel"));
328 RooDecay::DecayType decayType = static_cast<RooDecay::DecayType>(p["decayType"].val_int());
329 tool->wsEmplace<RooDecay>(name, *t, *tau, *model, decayType);
330 return true;
331}
332
334{
335 std::string name(RooJSONFactoryWSTool::name(p));
336 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
337 tool->wsEmplace<RooTruthModel>(name, *x);
338 return true;
339}
340
342{
343 std::string name(RooJSONFactoryWSTool::name(p));
344 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
345 RooRealVar *mean = tool->requestArg<RooRealVar>(p, "mean");
346 RooRealVar *sigma = tool->requestArg<RooRealVar>(p, "sigma");
347 tool->wsEmplace<RooGaussModel>(name, *x, *mean, *sigma);
348 return true;
349}
350
352{
353 std::string name(RooJSONFactoryWSTool::name(p));
354 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "integrand");
355 auto vars = tool->requestArgList<RooAbsReal>(p, "variables");
357 RooArgSet const *normSetPtr = nullptr;
358 if (p.has_child("normalization")) {
359 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
361 }
362 std::string domain;
363 bool hasDomain = p.has_child("domain");
364 if (hasDomain) {
365 domain = p["domain"].val();
366 }
367 // todo: at some point, take care of integrator configurations
368 tool->wsEmplace<RooRealIntegral>(name, *func, vars, normSetPtr, static_cast<RooNumIntConfig *>(nullptr),
369 hasDomain ? domain.c_str() : nullptr);
370 return true;
371}
372
374{
375 std::string name(RooJSONFactoryWSTool::name(p));
376 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "function");
377 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
378 Int_t order = p["order"].val_int();
379 double eps = p["eps"].val_double();
380 if (p.has_child("normalization")) {
382 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
383 tool->wsEmplace<RooDerivative>(name, *func, *x, normSet, order, eps);
384 return true;
385 }
386 tool->wsEmplace<RooDerivative>(name, *func, *x, order, eps);
387 return true;
388}
389
391{
392 std::string name(RooJSONFactoryWSTool::name(p));
393 RooRealVar *convVar = tool->requestArg<RooRealVar>(p, "conv_var");
394 Int_t order = p["ipOrder"].val_int();
395 RooAbsPdf *pdf1 = tool->requestArg<RooAbsPdf>(p, "pdf1");
396 RooAbsPdf *pdf2 = tool->requestArg<RooAbsPdf>(p, "pdf2");
397 if (p.has_child("conv_func")) {
398 RooAbsReal *convFunc = tool->requestArg<RooAbsReal>(p, "conv_func");
399 tool->wsEmplace<RooFFTConvPdf>(name, *convFunc, *convVar, *pdf1, *pdf2, order);
400 return true;
401 }
402 tool->wsEmplace<RooFFTConvPdf>(name, *convVar, *pdf1, *pdf2, order);
403 return true;
404}
405
407{
408 std::string name(RooJSONFactoryWSTool::name(p));
409 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
410 RooAbsReal *norm = tool->requestArg<RooAbsReal>(p, "norm");
411 if (p.has_child("range")) {
412 std::string rangeName = p["range"].val();
413 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm, rangeName.c_str());
414 return true;
415 }
416 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm);
417 return true;
418}
419
421{
422 std::string name(RooJSONFactoryWSTool::name(p));
423 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
424
425 // Same mechanism to undo the parameter transformation as in the
426 // importExponential() function (see comments in that function for more info).
427 const std::string muName = p["mu"].val();
428 const std::string sigmaName = p["sigma"].val();
429 const bool isTransformed = endsWith(muName, "_lognormal_log");
430 const std::string suffixToRemove = isTransformed ? "_lognormal_log" : "";
433
434 tool->wsEmplace<RooLognormal>(name, *x, *mu, *sigma, !isTransformed);
435
436 return true;
437}
438
440{
441 std::string name(RooJSONFactoryWSTool::name(p));
442 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
443
444 // If the parameter name ends with the "_exponential_inverted" suffix,
445 // this means that it was exported from a RooFit object where the
446 // parameter first needed to be transformed on export to match the HS3
447 // specification. But when re-importing such a parameter, we can simply
448 // skip the transformation and use the original RooFit parameter without
449 // the suffix.
450 //
451 // A concrete example: take the following RooFit pdf in the factory language:
452 //
453 // "Exponential::exponential_1(x[0, 10], c[-0.1])"
454 //
455 // It defines en exponential exp(c * x). However, in HS3 the exponential
456 // is defined as exp(-c * x), to RooFit would export these dictionaries
457 // to the JSON:
458 //
459 // {
460 // "name": "exponential_1", // HS3 exponential_dist with transformed parameter
461 // "type": "exponential_dist",
462 // "x": "x",
463 // "c": "c_exponential_inverted"
464 // },
465 // {
466 // "name": "c_exponential_inverted", // transformation function created on-the-fly on export
467 // "type": "generic_function",
468 // "expression": "-c"
469 // }
470 //
471 // On import, we can directly take the non-transformed parameter, which is
472 // we check for the suffix and optionally remove it from the requested
473 // name next:
474
475 const std::string constParamName = p["c"].val();
476 const bool isInverted = endsWith(constParamName, "_exponential_inverted");
477 const std::string suffixToRemove = isInverted ? "_exponential_inverted" : "";
479
480 tool->wsEmplace<RooExponential>(name, *x, *c, !isInverted);
481
482 return true;
483}
484
486{
487 std::string name(RooJSONFactoryWSTool::name(p));
488 bool has_cov = p.has_child("covariances");
489 bool has_corr = p.has_child("correlations") && p.has_child("standard_deviations");
490 if (!has_cov && !has_corr) {
491 RooJSONFactoryWSTool::error("no covariances or correlations+standard_deviations given in '" + name + "'");
492 }
493
495
496 if (has_cov) {
497 int n = p["covariances"].num_children();
498 int i = 0;
499 covmat.ResizeTo(n, n);
500 for (const auto &row : p["covariances"].children()) {
501 int j = 0;
502 for (const auto &val : row.children()) {
503 covmat(i, j) = val.val_double();
504 ++j;
505 }
506 ++i;
507 }
508 } else {
509 std::vector<double> variances;
510 for (const auto &v : p["standard_deviations"].children()) {
511 variances.push_back(v.val_double());
512 }
513 covmat.ResizeTo(variances.size(), variances.size());
514 int i = 0;
515 for (const auto &row : p["correlations"].children()) {
516 int j = 0;
517 for (const auto &val : row.children()) {
518 covmat(i, j) = val.val_double() * variances[i] * variances[j];
519 ++j;
520 }
521 ++i;
522 }
523 }
524 tool->wsEmplace<RooMultiVarGaussian>(name, tool->requestArgList<RooAbsReal>(p, "x"),
525 tool->requestArgList<RooAbsReal>(p, "mean"), covmat);
526 return true;
527}
528
529RooArgList readBinning(const JSONNode &topNode, const RooArgList &varList)
530{
531 // Temporary map from variable name → RooRealVar
532 std::map<std::string, std::unique_ptr<RooRealVar>> varMap;
533
534 // Build variables from JSON
535 for (const JSONNode &node : topNode["axes"].children()) {
536 const std::string name = node["name"].val();
537 std::unique_ptr<RooRealVar> obs;
538
539 if (node.has_child("edges")) {
540 std::vector<double> edges;
541 for (const auto &bound : node["edges"].children()) {
542 edges.push_back(bound.val_double());
543 }
544 obs = std::make_unique<RooRealVar>(name.c_str(), name.c_str(), edges.front(), edges.back());
545 RooBinning bins(obs->getMin(), obs->getMax());
546 for (auto b : edges)
547 bins.addBoundary(b);
548 obs->setBinning(bins);
549 } else {
550 obs = std::make_unique<RooRealVar>(name.c_str(), name.c_str(), node["min"].val_double(),
551 node["max"].val_double());
552 obs->setBins(node["nbins"].val_int());
553 }
554
555 varMap[name] = std::move(obs);
556 }
557
558 // Now build the final list following the order in varList
559 RooArgList vars;
560 for (auto *refVar : dynamic_range_cast<RooRealVar *>(varList)) {
561 if (!refVar)
562 continue;
563
564 auto it = varMap.find(refVar->GetName());
565 if (it != varMap.end()) {
566 vars.addOwned(std::move(it->second)); // preserve ownership
567 }
568 }
569 return vars;
570}
571
573{
574 if (!p.has_child("parameters")) {
575 return false;
576 }
577 std::string name(RooJSONFactoryWSTool::name(p));
578 RooArgList varList = tool->requestArgList<RooRealVar>(p, "variables");
579 if (!p.has_child("axes")) {
580 std::stringstream ss;
581 ss << "No axes given in '" << name << "'"
582 << ". Using default binning (uniform; nbins=100). If needed, export the Workspace to JSON with a newer "
583 << "Root version that supports custom ParamHistFunc binnings(>=6.38.00)." << std::endl;
585 tool->wsEmplace<ParamHistFunc>(name, varList, tool->requestArgList<RooAbsReal>(p, "parameters"));
586 return true;
587 }
588 tool->wsEmplace<ParamHistFunc>(name, readBinning(p, varList), tool->requestArgList<RooAbsReal>(p, "parameters"));
589 return true;
590}
591
593{
594 const std::string name(RooJSONFactoryWSTool::name(p));
595
596 // Mandatory fields
597 if (!p.has_child("x")) {
598 RooJSONFactoryWSTool::error("no x given in '" + name + "'");
599 }
600 if (!p.has_child("x0") || !p.has_child("y0")) {
601 RooJSONFactoryWSTool::error("no x0/y0 given in '" + name + "'");
602 }
603
604 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
605
606 // Optional fields (defaults follow RooSpline ctor defaults)
607 std::string algo = p.has_child("interpolation") ? p["interpolation"].val() : "poly3";
608 int order = 0;
609 if (algo == "poly3")
610 order = 3;
611 else if (algo == "poly5")
612 order = 5;
613 else {
614 RooJSONFactoryWSTool::error("unsupported algo '" + algo + "' for RooSpline in '" + name +
615 "': allowed are 'poly3' and 'poly5'");
616 }
617 const bool logx = p.has_child("logx") ? p["logx"].val_bool() : false;
618 const bool logy = p.has_child("logy") ? p["logy"].val_bool() : false;
619
620 // Read knots
621 std::vector<double> x0;
622 std::vector<double> y0;
623 x0.reserve(p["x0"].num_children());
624 y0.reserve(p["y0"].num_children());
625
626 for (const auto &v : p["x0"].children())
627 x0.push_back(v.val_double());
628 for (const auto &v : p["y0"].children())
629 y0.push_back(v.val_double());
630
631 if (x0.size() != y0.size()) {
632 RooJSONFactoryWSTool::error("x0/y0 size mismatch in '" + name + "': x0 has " + std::to_string(x0.size()) +
633 ", y0 has " + std::to_string(y0.size()));
634 }
635 if (x0.size() < 2) {
636 RooJSONFactoryWSTool::error("need at least 2 knots in '" + name + "'");
637 }
638
639 // Construct RooSpline(name,title, x, x0, y0, order, logx, logy)
640 tool->wsEmplace<::RooSpline>(name.c_str(), *x, std::span<const double>(x0.data(), x0.size()),
641 std::span<const double>(y0.data(), y0.size()), order, logx, logy);
642
643 return true;
644}
645
646///////////////////////////////////////////////////////////////////////////////////////////////////////
647// specialized exporter implementations
648///////////////////////////////////////////////////////////////////////////////////////////////////////
649template <class RooArg_t>
650bool exportAddPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
651{
652 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
653 elem["type"] << key;
654 RooJSONFactoryWSTool::fillSeq(elem["summands"], pdf->pdfList());
655 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
656 elem["extended"] << (pdf->extendMode() != RooArg_t::CanNotBeExtended);
657 return true;
658}
659
660bool exportRealSumPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
661{
662 const RooRealSumPdf *pdf = static_cast<const RooRealSumPdf *>(func);
663 elem["type"] << key;
664 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
665 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
666 elem["extended"] << (pdf->extendMode() != RooAbsPdf::CanNotBeExtended);
667 return true;
668}
669
670bool exportRealSumFunc(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
671{
672 const RooRealSumFunc *pdf = static_cast<const RooRealSumFunc *>(func);
673 elem["type"] << key;
674 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
675 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
676 return true;
677}
678
679template <class RooArg_t>
680bool exportHist(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem, std::string const &key)
681{
682 const RooArg_t *hf = static_cast<const RooArg_t *>(func);
683 elem["type"] << key;
684 RooDataHist const &dh = hf->dataHist();
685 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
686 return true;
687}
688
689template <class RooArg_t>
691{
692 std::string name(RooJSONFactoryWSTool::name(p));
693 if (!p.has_child("data")) {
694 return false;
695 }
696 std::unique_ptr<RooDataHist> dataHist =
698 tool->wsEmplace<RooArg_t>(name, *dataHist->get(), *dataHist);
699 return true;
700}
701
702bool exportBinSamplingPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
703{
704 const RooBinSamplingPdf *pdf = static_cast<const RooBinSamplingPdf *>(func);
705 elem["type"] << key;
706 elem["pdf"] << pdf->pdf().GetName();
707 elem["observable"] << pdf->observable().GetName();
708 elem["epsilon"] << pdf->epsilon();
709 return true;
710}
711
712bool exportBinWidthFunction(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &)
713{
714 const RooBinWidthFunction *pdf = static_cast<const RooBinWidthFunction *>(func);
715 elem["type"] << (pdf->divideByBinWidth() ? "inverse_binvolume" : "binvolume");
716 elem["histogram"] << pdf->histFunc().GetName();
717 return true;
718}
719
721{
722 // Plain substring replacement would also hit longer identifiers that
723 // share a prefix (e.g. "TMath::Tan" in "TMath::TanH", or "TMath::Pi" in
724 // "TMath::PiOver2"), corrupting the exported expression. Identifiers
725 // without a replacement are kept as-is.
726 replaceIdentifier(expr, "TMath::Exp", "exp");
727 replaceIdentifier(expr, "TMath::Min", "min");
728 replaceIdentifier(expr, "TMath::Max", "max");
729 replaceIdentifier(expr, "TMath::Log", "log");
730 replaceIdentifier(expr, "TMath::Log10", "log10");
731 replaceIdentifier(expr, "TMath::Cos", "cos");
732 replaceIdentifier(expr, "TMath::CosH", "cosh");
733 replaceIdentifier(expr, "TMath::Sin", "sin");
734 replaceIdentifier(expr, "TMath::SinH", "sinh");
735 replaceIdentifier(expr, "TMath::Sqrt", "sqrt");
736 replaceIdentifier(expr, "TMath::Power", "pow");
737 replaceIdentifier(expr, "TMath::Erf", "erf");
738 replaceIdentifier(expr, "TMath::Erfc", "erfc");
739 replaceIdentifier(expr, "TMath::Floor", "floor");
740 replaceIdentifier(expr, "TMath::Ceil", "ceil");
741 replaceIdentifier(expr, "TMath::Abs", "abs");
742 replaceIdentifier(expr, "TMath::Tan", "tan");
743 replaceIdentifier(expr, "TMath::TanH", "tanh");
744 replaceIdentifier(expr, "TMath::ASin", "asin");
745 replaceIdentifier(expr, "TMath::ACos", "acos");
746 replaceIdentifier(expr, "TMath::ATan", "atan");
747 replaceIdentifier(expr, "TMath::ATan2", "atan2");
748 replaceIdentifier(expr, "TMath::Pi()", "PI");
749 replaceIdentifier(expr, "TMath::E()", "EULER");
750}
751
752template <class RooArg_t>
753bool exportFormulaArg(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
754{
755 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
756 elem["type"] << key;
757 TString expression(pdf->expression());
758 cleanExpression(expression);
759 // If the tokens follow the "x[#]" convention, the square braces enclosing each number
760 // ensures that there is a unique mapping between the token and parameter name
761 // If the tokens follow the "@#" convention, the numbers are not enclosed by braces.
762 // So there may be tokens with numbers whose lower place value forms a subset string of ones with a higher place
763 // value, e.g. "@1" is a subset of "@10". So the names of these parameters must be applied descending from the
764 // highest place value in order to ensure each parameter name is uniquely applied to its token.
765 for (size_t idx = pdf->nParameters(); idx--;) {
766 const RooAbsArg *par = pdf->getParameter(idx);
767 expression.ReplaceAll(("x[" + std::to_string(idx) + "]").c_str(), par->GetName());
768 expression.ReplaceAll(("@" + std::to_string(idx)).c_str(), par->GetName());
769 }
770 elem["expression"] << expression.Data();
771 return true;
772}
773
774// Write the "x" reference and the coefficient list for polynomial-like
775// pdfs/funcs, including the implicit defaults below "lowestOrder" so that the
776// output is self-documenting.
777template <class Pdf>
778void writePolynomialBody(const Pdf *pdf, JSONNode &elem)
779{
780 elem["x"] << pdf->x().GetName();
781 auto &coefs = elem["coefficients"].set_seq();
782 for (int i = 0; i < pdf->lowestOrder(); ++i) {
783 coefs.append_child() << (i == 0 ? 1.0 : 0.0);
784 }
785 for (const auto &coef : pdf->coefList()) {
786 coefs.append_child() << coef->GetName();
787 }
788}
789
790template <class RooArg_t>
791bool exportPolynomial(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
792{
793 elem["type"] << key;
794 writePolynomialBody(static_cast<const RooArg_t *>(func), elem);
795 return true;
796}
797
798bool exportPoisson(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
799{
800 auto *pdf = static_cast<const RooPoisson *>(func);
801 elem["type"] << key;
802 elem["x"] << pdf->getX().GetName();
803 elem["mean"] << pdf->getMean().GetName();
804 elem["integer"] << !pdf->getNoRounding();
805 return true;
806}
807
808bool exportDecay(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
809{
810 auto *pdf = static_cast<const RooDecay *>(func);
811 elem["type"] << key;
812 elem["t"] << pdf->getT().GetName();
813 elem["tau"] << pdf->getTau().GetName();
814 elem["resolutionModel"] << pdf->getModel().GetName();
815 elem["decayType"] << pdf->getDecayType();
816
817 return true;
818}
819
820bool exportTruthModel(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
821{
822 auto *pdf = static_cast<const RooTruthModel *>(func);
823 elem["type"] << key;
824 elem["x"] << pdf->convVar().GetName();
825
826 return true;
827}
828
829bool exportGaussModel(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
830{
831 auto *pdf = static_cast<const RooGaussModel *>(func);
832 elem["type"] << key;
833 elem["x"] << pdf->convVar().GetName();
834 elem["mean"] << pdf->getMean().GetName();
835 elem["sigma"] << pdf->getSigma().GetName();
836 return true;
837}
838
839bool exportLogNormal(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem, std::string const &key)
840{
841 auto *pdf = static_cast<const RooLognormal *>(func);
842
843 elem["type"] << key;
844 elem["x"] << pdf->getX().GetName();
845
846 auto &m0 = pdf->getMedian();
847 auto &k = pdf->getShapeK();
848
849 if (pdf->useStandardParametrization()) {
850 elem["mu"] << m0.GetName();
851 elem["sigma"] << k.GetName();
852 } else {
853 elem["mu"] << tool->exportTransformed(&m0, "_lognormal_log", "log(%s)");
854 elem["sigma"] << tool->exportTransformed(&k, "_lognormal_log", "log(%s)");
855 }
856
857 return true;
858}
859
860bool exportExponential(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem, std::string const &key)
861{
862 auto *pdf = static_cast<const RooExponential *>(func);
863 elem["type"] << key;
864 elem["x"] << pdf->variable().GetName();
865 auto &c = pdf->coefficient();
866 if (pdf->negateCoefficient()) {
867 elem["c"] << c.GetName();
868 } else {
869 elem["c"] << tool->exportTransformed(&c, "_exponential_inverted", "-%s");
870 }
871
872 return true;
873}
874
875bool exportMultiVarGaussian(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
876{
877 auto *pdf = static_cast<const RooMultiVarGaussian *>(func);
878 elem["type"] << key;
879 RooJSONFactoryWSTool::fillSeq(elem["x"], pdf->xVec());
880 RooJSONFactoryWSTool::fillSeq(elem["mean"], pdf->muVec());
881 elem["covariances"].fill_mat(pdf->covarianceMatrix());
882 return true;
883}
884
885bool exportTFnBinding(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
886{
887 auto *pdf = static_cast<const RooTFnBinding *>(func);
888 elem["type"] << key;
889
890 TString formula(pdf->function().GetExpFormula());
891 formula.ReplaceAll("x", pdf->observables()[0].GetName());
892 formula.ReplaceAll("y", pdf->observables()[1].GetName());
893 formula.ReplaceAll("z", pdf->observables()[2].GetName());
894 for (size_t i = 0; i < pdf->parameters().size(); ++i) {
895 TString pname(TString::Format("[%d]", (int)i));
896 formula.ReplaceAll(pname, pdf->parameters()[i].GetName());
897 }
898 elem["expression"] << formula.Data();
899 return true;
900}
901
902bool exportDerivative(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
903{
904 auto *pdf = static_cast<const RooDerivative *>(func);
905 elem["type"] << key;
906 elem["x"] << pdf->getX().GetName();
907 elem["function"] << pdf->getFunc().GetName();
908 if (!pdf->getNset().empty()) {
909 RooJSONFactoryWSTool::fillSeq(elem["normalization"], pdf->getNset());
910 }
911 elem["order"] << pdf->order();
912 elem["eps"] << pdf->eps();
913 return true;
914}
915
916bool exportRealIntegral(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
917{
918 auto *integral = static_cast<const RooRealIntegral *>(func);
919 elem["type"] << key;
920 std::string integrand = integral->integrand().GetName();
921 // elem["integrand"] << RooJSONFactoryWSTool::sanitizeName(integrand);
922 elem["integrand"] << integrand;
923 if (integral->intRange()) {
924 elem["domain"] << integral->intRange();
925 }
926 RooJSONFactoryWSTool::fillSeq(elem["variables"], integral->intVars());
927 if (RooArgSet const *funcNormSet = integral->funcNormSet()) {
928 RooJSONFactoryWSTool::fillSeq(elem["normalization"], *funcNormSet);
929 }
930 return true;
931}
932
933bool exportFFTConvPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
934{
935 auto *pdf = static_cast<const RooFFTConvPdf *>(func);
936 elem["type"] << key;
937 if (auto convFunc = pdf->getPdfConvVar()) {
938 elem["conv_func"] << convFunc->GetName();
939 }
940 elem["conv_var"] << pdf->getConvVar().GetName();
941 elem["pdf1"] << pdf->getPdf1().GetName();
942 elem["pdf2"] << pdf->getPdf2().GetName();
943 elem["ipOrder"] << pdf->getInterpolationOrder();
944 return true;
945}
946
947bool exportExtendPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
948{
949 auto *pdf = static_cast<const RooExtendPdf *>(func);
950 elem["type"] << key;
951 if (auto rangeName = pdf->getRangeName()) {
952 elem["range"] << rangeName->GetName();
953 }
954 elem["pdf"] << pdf->pdf().GetName();
955 elem["norm"] << pdf->getN().GetName();
956 return true;
957}
958
959bool exportParamHistFunc(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
960{
961 auto *pdf = static_cast<const ParamHistFunc *>(func);
962 elem["type"] << key;
963 RooJSONFactoryWSTool::fillSeq(elem["variables"], pdf->dataVars());
964 RooJSONFactoryWSTool::fillSeq(elem["parameters"], pdf->paramList());
965 auto &observablesNode = elem["axes"].set_seq();
966 // axes have to be ordered to get consistent bin indices
967 for (auto *var : static_range_cast<RooRealVar *>(pdf->dataVars())) {
968 RooJSONFactoryWSTool::exportAxis(observablesNode.append_child().set_map(), *var);
969 }
970 return true;
971}
972
973bool exportSpline(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
974{
975 auto const *rs = static_cast<RooSpline const *>(func);
976
977 elem["type"] << key;
978
979 // Independent variable
980 elem["x"] << rs->x().GetName();
981
982 // Spline configuration
983 // Canonical algo for RooSpline
984 elem["interpolation"] << (rs->order() == 5 ? "poly5" : "poly3");
985 elem["logx"] << rs->logx();
986 elem["logy"] << rs->logy();
987
988 // Serialize knots as primitive arrays
989 TSpline const &sp = rs->spline();
990 auto &x0 = elem["x0"].set_seq();
991 auto &y0 = elem["y0"].set_seq();
992
993 const int np = sp.GetNp();
994 for (int i = 0; i < np; ++i) {
995 double xk = 0.0, yk = 0.0;
996 sp.GetKnot(i, xk, yk);
997 x0.append_child() << xk;
998 y0.append_child() << yk;
999 }
1000
1001 return true;
1002}
1003
1005{
1006 if (node["type"].val() != "density_function_dist")
1007 return false;
1008
1009 auto name = RooJSONFactoryWSTool::name(node);
1010 auto *func = tool->requestArg<RooAbsReal>(node, "function");
1011
1012 bool selfNormalized = false;
1013
1014 if (auto sn = node.find("selfNormalized"))
1015 selfNormalized = sn->val_bool();
1016
1017 tool->wsEmplace<RooWrapperPdf>(name, *func, selfNormalized);
1018 return true;
1019}
1020
1021bool exportWrapperPdf(RooJSONFactoryWSTool *, const RooAbsArg *arg, JSONNode &node, std::string const &key)
1022{
1023 auto const *pdf = dynamic_cast<RooWrapperPdf const *>(arg);
1024 if (!pdf)
1025 return false;
1026
1027 node["type"] << key;
1028
1029 // Proxy name in RooWrapperPdf is "_func" / "func" depending on accessor/proxy export.
1030 // Prefer a public accessor if one exists; otherwise inspect proxies as below.
1031 auto const *funcProxy = dynamic_cast<RooRealProxy const *>(pdf->getProxy(0));
1032 if (!funcProxy || !funcProxy->absArg())
1033 return false;
1034
1035 node["function"] << funcProxy->absArg()->GetName();
1036 if (pdf->selfNormalized())
1037 node["selfnormalized"] << true;
1038
1039 return true;
1040}
1041
1042///////////////////////////////////////////////////////////////////////////////////////////////////////
1043// instantiate all importers and exporters
1044///////////////////////////////////////////////////////////////////////////////////////////////////////
1045
1046// Adapters that wrap the plain import/export functions above into the
1047// RooFit::JSONIO::Importer/Exporter interface. The exporter also owns the HS3
1048// type key, which is passed at registration time.
1049template <auto Func>
1050class FuncImporter : public RooFit::JSONIO::Importer {
1051public:
1052 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override { return Func(tool, p); }
1053};
1054
1055template <auto Func>
1056class FuncExporter : public RooFit::JSONIO::Exporter {
1057public:
1058 FuncExporter(std::string key) : _key{std::move(key)} {}
1059 std::string const &key() const override { return _key; }
1060 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
1061 {
1062 return Func(tool, func, elem, _key);
1063 }
1064
1065private:
1066 const std::string _key;
1067};
1068
1069template <auto Func>
1070void registerImporter(const std::string &key, bool topPriority = true)
1071{
1073}
1074
1075template <auto Func>
1076void registerExporter(TClass const *cl, std::string key, bool topPriority = true)
1077{
1078 RooFit::JSONIO::registerExporter(cl, std::make_unique<FuncExporter<Func>>(std::move(key)), topPriority);
1079}
1080
1081STATIC_EXECUTE([]() {
1082 registerImporter<importWrapperPdf>("density_function_dist");
1083 registerImporter<importExtendPdf>("rate_extended_dist");
1084 registerImporter<importProduct>("product", false);
1085 registerImporter<importProdPdf>("product_dist", false);
1087 registerImporter<importAddPdf>("mixture_dist", false);
1088 registerImporter<importAddModel>("mixture_resolution_model", false);
1089 registerImporter<importBinSamplingPdf>("binsampling_dist", false);
1091 registerImporter<importBinWidthFunction<true>>("inverse_binvolume", false);
1092 registerImporter<importPolynomial<RooLegacyExpPoly>>("legacy_exp_poly_dist", false);
1093 registerImporter<importExponential>("exponential_dist", false);
1095 registerImporter<importFormulaArg<RooFormulaVar>>("generic_function", false);
1097 registerImporter<importHist<RooHistFunc>>("histogram", false);
1099 registerImporter<importHist<RooHistPdf>>("histogram_dist", false);
1100 registerImporter<importLogNormal>("lognormal_dist", false);
1101 registerImporter<importMultiVarGaussian>("multivariate_normal_dist", false);
1102 registerImporter<importPoisson>("poisson_dist", false);
1103 registerImporter<importDecay>("decay_dist", false);
1104 registerImporter<importTruthModel>("delta_resolution_model", false);
1105 registerImporter<importGaussModel>("gauss_resolution_model", false);
1106 registerImporter<importPolynomial<RooPolynomial>>("polynomial_dist", false);
1108 registerImporter<importRealSumPdf>("weighted_sum_dist", false);
1109 registerImporter<importRealSumFunc>("weighted_sum", false);
1110 registerImporter<importRealIntegral>("integral", false);
1111 registerImporter<importDerivative>("derivative", false);
1112 registerImporter<importFFTConvPdf>("fft_convolution_dist", false);
1113 registerImporter<importExtendPdf>("extend_pdf", false);
1115 registerImporter<importSpline>("spline", false);
1116
1117 registerExporter<exportWrapperPdf>(RooWrapperPdf::Class(), "density_function_dist");
1119 registerExporter<exportAddPdf<RooAddModel>>(RooAddModel::Class(), "mixture_resolution_model", false);
1123 registerExporter<exportExponential>(RooExponential::Class(), "exponential_dist", false);
1128 registerExporter<exportLogNormal>(RooLognormal::Class(), "lognormal_dist", false);
1129 registerExporter<exportMultiVarGaussian>(RooMultiVarGaussian::Class(), "multivariate_normal_dist", false);
1130 registerExporter<exportPoisson>(RooPoisson::Class(), "poisson_dist", false);
1131 registerExporter<exportDecay>(RooDecay::Class(), "decay_dist", false);
1132 registerExporter<exportTruthModel>(RooTruthModel::Class(), "delta_resolution_model", false);
1133 registerExporter<exportGaussModel>(RooGaussModel::Class(), "gauss_resolution_model", false);
1137 registerExporter<exportRealSumPdf>(RooRealSumPdf::Class(), "weighted_sum_dist", false);
1138 registerExporter<exportTFnBinding>(RooTFnBinding::Class(), "generic_function", false);
1141 registerExporter<exportFFTConvPdf>(RooFFTConvPdf::Class(), "fft_convolution_dist", false);
1142 registerExporter<exportExtendPdf>(RooExtendPdf::Class(), "rate_extended_dist", false);
1145});
1146
1147} // namespace
bool endsWith(std::string_view str, std::string_view suffix)
std::string removeSuffix(std::string_view str, std::string_view suffix)
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
ROOT::RRangeCast< T, true, Range_t > dynamic_range_cast(Range_t &&coll)
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
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 np
char name[80]
Definition TGX11.cxx:148
A class which maps the current values of a RooRealVar (or a set of RooRealVars) to one of a number of...
static TClass * Class()
const_iterator begin() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
bool dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr, bool valueOnly=false) const
Test whether we depend on (ie, are served by) any object in the specified collection.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
@ CanNotBeExtended
Definition RooAbsPdf.h:208
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
RooAddModel is an efficient implementation of a sum of PDFs of the form.
Definition RooAddModel.h:27
static TClass * Class()
Efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:33
static TClass * Class()
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition RooAddition.h:27
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
The RooBinSamplingPdf is supposed to be used as an adapter between a continuous PDF and a binned dist...
static TClass * Class()
double epsilon() const
const RooAbsPdf & pdf() const
const RooAbsReal & observable() const
Returns the bin width (or volume) given a RooHistFunc.
const RooHistFunc & histFunc() const
static TClass * Class()
Implements a RooAbsBinning in terms of an array of boundary values, posing no constraints on the choi...
Definition RooBinning.h:27
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
Single or double sided decay function that can be analytically convolved with any RooResolutionModel ...
Definition RooDecay.h:22
static TClass * Class()
Represents the first, second, or third order derivative of any RooAbsReal as calculated (numerically)...
static TClass * Class()
Exponential PDF.
static TClass * Class()
RooExtendPdf is a wrapper around an existing PDF that adds a parameteric extended likelihood term to ...
static TClass * Class()
PDF for the numerical (FFT) convolution of two PDFs.
static TClass * Class()
static TClass * Class()
Class RooGaussModel implements a RooResolutionModel that models a Gaussian distribution.
static TClass * Class()
static TClass * Class()
A real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:31
static TClass * Class()
static TClass * Class()
When using RooFit, statistical models can be conveniently handled and stored as a RooWorkspace.
static void fillSeq(RooFit::Detail::JSONNode &node, RooAbsCollection const &coll, size_t nMax=-1)
static std::unique_ptr< RooDataHist > readBinnedData(const RooFit::Detail::JSONNode &n, const std::string &namecomp, RooArgSet const &vars)
Read binned data from the JSONNode and create a RooDataHist object.
static void exportAxis(RooFit::Detail::JSONNode &obsNode, RooRealVar const &var)
Export the name and binning of a RooRealVar to a JSONNode.
static void error(const char *s)
Writes an error message to the RooFit message service and throws a runtime_error.
static std::string name(const RooFit::Detail::JSONNode &n)
static std::ostream & warning(const std::string &s)
Writes a warning message to the RooFit message service.
static RooArgSet readAxes(const RooFit::Detail::JSONNode &node)
Read axes from the JSONNode and create a RooArgSet representing them.
static TClass * Class()
RooFit Lognormal PDF.
static TClass * Class()
Multivariate Gaussian p.d.f.
static TClass * Class()
Holds the configuration parameters of the various numeric integrators used by RooRealIntegral.
Poisson pdf.
Definition RooPoisson.h:19
static TClass * Class()
static TClass * Class()
static TClass * Class()
Efficient implementation of a product of PDFs of the form.
Definition RooProdPdf.h:36
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
Performs hybrid numerical/analytical integrals of RooAbsReal objects.
static TClass * Class()
const RooArgList & coefList() const
const RooArgList & funcList() const
static TClass * Class()
Implements a PDF constructed from a sum of functions:
const RooArgList & funcList() const
static TClass * Class()
ExtendMode extendMode() const override
Returns ability of PDF to provide extended likelihood terms.
const RooArgList & coefList() const
Variable that can be changed from the outside.
Definition RooRealVar.h:37
RooResolutionModel is the base class for PDFs that represent a resolution model that can be convolute...
A RooFit class for creating spline functions.
Definition RooSpline.h:27
static TClass * Class()
Use TF1, TF2, TF3 functions as RooFit objects.
static TClass * Class()
Implements a RooResolution model that corresponds to a delta function.
static TClass * Class()
The RooWrapperPdf is a class that can be used to convert a function into a PDF.
static TClass * Class()
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
static Bool_t IsScientificNotation(const TString &formula, int ipos)
Definition TFormula.cxx:383
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Base class for spline implementation containing the Draw/Paint methods.
Definition TSpline.h:31
Basic string class.
Definition TString.h:138
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:2459
const Double_t sigma
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
static bool registerImporter(const std::string &key, bool topPriority=true)
Definition JSONIO.h:85
bool registerImporter(const std::string &key, std::unique_ptr< const Importer > f, bool topPriority=true)
Definition JSONIO.cxx:123
static bool registerExporter(const TClass *key, bool topPriority=true)
Definition JSONIO.h:90
bool registerExporter(const TClass *key, std::unique_ptr< const Exporter > f, bool topPriority=true)
Definition JSONIO.cxx:130
#define STATIC_EXECUTE(MY_FUNC)