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 = dynamic_cast<RooHistFunc *>(tool->request<RooAbsReal>(p["histogram"].val(), name));
236 if (!hf) {
237 RooJSONFactoryWSTool::error("histogram '" + p["histogram"].val() + "' of '" + name + "' is not a RooHistFunc");
238 }
240 return true;
241}
242
244{
245 std::string name(RooJSONFactoryWSTool::name(p));
246
247 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
248 RooRealVar *obs = tool->requestArg<RooRealVar>(p, "observable");
249
250 if (!pdf->dependsOn(*obs)) {
251 RooJSONFactoryWSTool::error(std::string("pdf '") + pdf->GetName() + "' does not depend on observable '" +
252 obs->GetName() + "' as indicated by parent RooBinSamplingPdf '" + name +
253 "', please check!");
254 }
255
256 if (!p.has_child("epsilon")) {
257 RooJSONFactoryWSTool::error("no epsilon given in '" + name + "'");
258 }
259 double epsilon(p["epsilon"].val_double());
260
261 tool->wsEmplace<RooBinSamplingPdf>(name, *obs, *pdf, epsilon);
262
263 return true;
264}
265
267{
268 std::string name(RooJSONFactoryWSTool::name(p));
269
270 bool extended = false;
271 if (p.has_child("extended") && p["extended"].val_bool()) {
272 extended = true;
273 }
274 tool->wsEmplace<RooRealSumPdf>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
275 tool->requestArgList<RooAbsReal>(p, "coefficients"), extended);
276 return true;
277}
278
280{
281 std::string name(RooJSONFactoryWSTool::name(p));
282 tool->wsEmplace<RooRealSumFunc>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
283 tool->requestArgList<RooAbsReal>(p, "coefficients"));
284 return true;
285}
286
287template <class RooArg_t>
289{
290 std::string name(RooJSONFactoryWSTool::name(p));
291 if (!p.has_child("coefficients")) {
292 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
293 }
294 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
295 RooArgList coefs;
296 int order = 0;
297 int lowestOrder = 0;
298 for (const auto &coef : p["coefficients"].children()) {
299 // As long as the coefficients match the default coefficients in
300 // RooFit, we don't have to instantiate RooFit objects but can
301 // increase the lowestOrder flag.
302 if (order == 0 && (coef.val() == "1.0" || coef.val() == "1")) {
303 ++lowestOrder;
304 } else if (coefs.empty() && (coef.val() == "0.0" || coef.val() == "0")) {
305 ++lowestOrder;
306 } else {
307 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
308 }
309 ++order;
310 }
311
312 tool->wsEmplace<RooArg_t>(name, *x, coefs, lowestOrder);
313 return true;
314}
315
317{
318 std::string name(RooJSONFactoryWSTool::name(p));
319 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
320 RooAbsReal *mean = tool->requestArg<RooAbsReal>(p, "mean");
321 tool->wsEmplace<RooPoisson>(name, *x, *mean, !p["integer"].val_bool());
322 return true;
323}
324
326{
327 std::string name(RooJSONFactoryWSTool::name(p));
328 RooRealVar *t = tool->requestArg<RooRealVar>(p, "t");
329 RooAbsReal *tau = tool->requestArg<RooAbsReal>(p, "tau");
330 RooResolutionModel *model = dynamic_cast<RooResolutionModel *>(tool->requestArg<RooAbsPdf>(p, "resolutionModel"));
331 if (!model) {
332 RooJSONFactoryWSTool::error("resolutionModel of '" + name + "' is not a RooResolutionModel");
333 }
334 RooDecay::DecayType decayType = static_cast<RooDecay::DecayType>(p["decayType"].val_int());
335 tool->wsEmplace<RooDecay>(name, *t, *tau, *model, decayType);
336 return true;
337}
338
340{
341 std::string name(RooJSONFactoryWSTool::name(p));
342 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
343 tool->wsEmplace<RooTruthModel>(name, *x);
344 return true;
345}
346
348{
349 std::string name(RooJSONFactoryWSTool::name(p));
350 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
351 RooRealVar *mean = tool->requestArg<RooRealVar>(p, "mean");
352 RooRealVar *sigma = tool->requestArg<RooRealVar>(p, "sigma");
353 tool->wsEmplace<RooGaussModel>(name, *x, *mean, *sigma);
354 return true;
355}
356
358{
359 std::string name(RooJSONFactoryWSTool::name(p));
360 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "integrand");
361 auto vars = tool->requestArgList<RooAbsReal>(p, "variables");
363 RooArgSet const *normSetPtr = nullptr;
364 if (p.has_child("normalization")) {
365 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
367 }
368 std::string domain;
369 bool hasDomain = p.has_child("domain");
370 if (hasDomain) {
371 domain = p["domain"].val();
372 }
373 // todo: at some point, take care of integrator configurations
374 tool->wsEmplace<RooRealIntegral>(name, *func, vars, normSetPtr, static_cast<RooNumIntConfig *>(nullptr),
375 hasDomain ? domain.c_str() : nullptr);
376 return true;
377}
378
380{
381 std::string name(RooJSONFactoryWSTool::name(p));
382 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "function");
383 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
384 Int_t order = p["order"].val_int();
385 double eps = p["eps"].val_double();
386 if (p.has_child("normalization")) {
388 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
389 tool->wsEmplace<RooDerivative>(name, *func, *x, normSet, order, eps);
390 return true;
391 }
392 tool->wsEmplace<RooDerivative>(name, *func, *x, order, eps);
393 return true;
394}
395
397{
398 std::string name(RooJSONFactoryWSTool::name(p));
399 RooRealVar *convVar = tool->requestArg<RooRealVar>(p, "conv_var");
400 Int_t order = p["ipOrder"].val_int();
401 RooAbsPdf *pdf1 = tool->requestArg<RooAbsPdf>(p, "pdf1");
402 RooAbsPdf *pdf2 = tool->requestArg<RooAbsPdf>(p, "pdf2");
403 if (p.has_child("conv_func")) {
404 RooAbsReal *convFunc = tool->requestArg<RooAbsReal>(p, "conv_func");
405 tool->wsEmplace<RooFFTConvPdf>(name, *convFunc, *convVar, *pdf1, *pdf2, order);
406 return true;
407 }
408 tool->wsEmplace<RooFFTConvPdf>(name, *convVar, *pdf1, *pdf2, order);
409 return true;
410}
411
413{
414 std::string name(RooJSONFactoryWSTool::name(p));
415 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
416 RooAbsReal *norm = tool->requestArg<RooAbsReal>(p, "norm");
417 if (p.has_child("range")) {
418 std::string rangeName = p["range"].val();
419 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm, rangeName.c_str());
420 return true;
421 }
422 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm);
423 return true;
424}
425
427{
428 std::string name(RooJSONFactoryWSTool::name(p));
429 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
430
431 // Same mechanism to undo the parameter transformation as in the
432 // importExponential() function (see comments in that function for more info).
433 const std::string muName = p["mu"].val();
434 const std::string sigmaName = p["sigma"].val();
435 const bool isTransformed = endsWith(muName, "_lognormal_log");
436 const std::string suffixToRemove = isTransformed ? "_lognormal_log" : "";
439
440 tool->wsEmplace<RooLognormal>(name, *x, *mu, *sigma, !isTransformed);
441
442 return true;
443}
444
446{
447 std::string name(RooJSONFactoryWSTool::name(p));
448 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
449
450 // If the parameter name ends with the "_exponential_inverted" suffix,
451 // this means that it was exported from a RooFit object where the
452 // parameter first needed to be transformed on export to match the HS3
453 // specification. But when re-importing such a parameter, we can simply
454 // skip the transformation and use the original RooFit parameter without
455 // the suffix.
456 //
457 // A concrete example: take the following RooFit pdf in the factory language:
458 //
459 // "Exponential::exponential_1(x[0, 10], c[-0.1])"
460 //
461 // It defines en exponential exp(c * x). However, in HS3 the exponential
462 // is defined as exp(-c * x), to RooFit would export these dictionaries
463 // to the JSON:
464 //
465 // {
466 // "name": "exponential_1", // HS3 exponential_dist with transformed parameter
467 // "type": "exponential_dist",
468 // "x": "x",
469 // "c": "c_exponential_inverted"
470 // },
471 // {
472 // "name": "c_exponential_inverted", // transformation function created on-the-fly on export
473 // "type": "generic_function",
474 // "expression": "-c"
475 // }
476 //
477 // On import, we can directly take the non-transformed parameter, which is
478 // we check for the suffix and optionally remove it from the requested
479 // name next:
480
481 const std::string constParamName = p["c"].val();
482 const bool isInverted = endsWith(constParamName, "_exponential_inverted");
483 const std::string suffixToRemove = isInverted ? "_exponential_inverted" : "";
485
486 tool->wsEmplace<RooExponential>(name, *x, *c, !isInverted);
487
488 return true;
489}
490
492{
493 std::string name(RooJSONFactoryWSTool::name(p));
494 bool has_cov = p.has_child("covariances");
495 bool has_corr = p.has_child("correlations") && p.has_child("standard_deviations");
496 if (!has_cov && !has_corr) {
497 RooJSONFactoryWSTool::error("no covariances or correlations+standard_deviations given in '" + name + "'");
498 }
499
501
502 if (has_cov) {
503 int n = p["covariances"].num_children();
504 int i = 0;
505 covmat.ResizeTo(n, n);
506 for (const auto &row : p["covariances"].children()) {
507 int j = 0;
508 for (const auto &val : row.children()) {
509 covmat(i, j) = val.val_double();
510 ++j;
511 }
512 ++i;
513 }
514 } else {
515 std::vector<double> variances;
516 for (const auto &v : p["standard_deviations"].children()) {
517 variances.push_back(v.val_double());
518 }
519 covmat.ResizeTo(variances.size(), variances.size());
520 int i = 0;
521 for (const auto &row : p["correlations"].children()) {
522 int j = 0;
523 for (const auto &val : row.children()) {
524 covmat(i, j) = val.val_double() * variances[i] * variances[j];
525 ++j;
526 }
527 ++i;
528 }
529 }
530 tool->wsEmplace<RooMultiVarGaussian>(name, tool->requestArgList<RooAbsReal>(p, "x"),
531 tool->requestArgList<RooAbsReal>(p, "mean"), covmat);
532 return true;
533}
534
535RooArgList readBinning(const JSONNode &topNode, const RooArgList &varList)
536{
537 // Temporary map from variable name → RooRealVar
538 std::map<std::string, std::unique_ptr<RooRealVar>> varMap;
539
540 // Build variables from JSON
541 for (const JSONNode &node : topNode["axes"].children()) {
542 const std::string name = node["name"].val();
543 std::unique_ptr<RooRealVar> obs;
544
545 if (node.has_child("edges")) {
546 std::vector<double> edges;
547 for (const auto &bound : node["edges"].children()) {
548 edges.push_back(bound.val_double());
549 }
550 obs = std::make_unique<RooRealVar>(name.c_str(), name.c_str(), edges.front(), edges.back());
551 RooBinning bins(obs->getMin(), obs->getMax());
552 for (auto b : edges)
553 bins.addBoundary(b);
554 obs->setBinning(bins);
555 } else {
556 obs = std::make_unique<RooRealVar>(name.c_str(), name.c_str(), node["min"].val_double(),
557 node["max"].val_double());
558 obs->setBins(node["nbins"].val_int());
559 }
560
561 varMap[name] = std::move(obs);
562 }
563
564 // Now build the final list following the order in varList
565 RooArgList vars;
566 for (auto *refVar : dynamic_range_cast<RooRealVar *>(varList)) {
567 if (!refVar)
568 continue;
569
570 auto it = varMap.find(refVar->GetName());
571 if (it != varMap.end()) {
572 vars.addOwned(std::move(it->second)); // preserve ownership
573 }
574 }
575 return vars;
576}
577
579{
580 if (!p.has_child("parameters")) {
581 return false;
582 }
583 std::string name(RooJSONFactoryWSTool::name(p));
584 RooArgList varList = tool->requestArgList<RooRealVar>(p, "variables");
585 if (!p.has_child("axes")) {
586 std::stringstream ss;
587 ss << "No axes given in '" << name << "'"
588 << ". Using default binning (uniform; nbins=100). If needed, export the Workspace to JSON with a newer "
589 << "Root version that supports custom ParamHistFunc binnings(>=6.38.00)." << std::endl;
591 tool->wsEmplace<ParamHistFunc>(name, varList, tool->requestArgList<RooAbsReal>(p, "parameters"));
592 return true;
593 }
594 tool->wsEmplace<ParamHistFunc>(name, readBinning(p, varList), tool->requestArgList<RooAbsReal>(p, "parameters"));
595 return true;
596}
597
599{
600 const std::string name(RooJSONFactoryWSTool::name(p));
601
602 // Mandatory fields
603 if (!p.has_child("x")) {
604 RooJSONFactoryWSTool::error("no x given in '" + name + "'");
605 }
606 if (!p.has_child("x0") || !p.has_child("y0")) {
607 RooJSONFactoryWSTool::error("no x0/y0 given in '" + name + "'");
608 }
609
610 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
611
612 // Optional fields (defaults follow RooSpline ctor defaults)
613 std::string algo = p.has_child("interpolation") ? p["interpolation"].val() : "poly3";
614 int order = 0;
615 if (algo == "poly3")
616 order = 3;
617 else if (algo == "poly5")
618 order = 5;
619 else {
620 RooJSONFactoryWSTool::error("unsupported algo '" + algo + "' for RooSpline in '" + name +
621 "': allowed are 'poly3' and 'poly5'");
622 }
623 const bool logx = p.has_child("logx") ? p["logx"].val_bool() : false;
624 const bool logy = p.has_child("logy") ? p["logy"].val_bool() : false;
625
626 // Read knots
627 std::vector<double> x0;
628 std::vector<double> y0;
629 x0.reserve(p["x0"].num_children());
630 y0.reserve(p["y0"].num_children());
631
632 for (const auto &v : p["x0"].children())
633 x0.push_back(v.val_double());
634 for (const auto &v : p["y0"].children())
635 y0.push_back(v.val_double());
636
637 if (x0.size() != y0.size()) {
638 RooJSONFactoryWSTool::error("x0/y0 size mismatch in '" + name + "': x0 has " + std::to_string(x0.size()) +
639 ", y0 has " + std::to_string(y0.size()));
640 }
641 if (x0.size() < 2) {
642 RooJSONFactoryWSTool::error("need at least 2 knots in '" + name + "'");
643 }
644
645 // Construct RooSpline(name,title, x, x0, y0, order, logx, logy)
646 tool->wsEmplace<::RooSpline>(name.c_str(), *x, std::span<const double>(x0.data(), x0.size()),
647 std::span<const double>(y0.data(), y0.size()), order, logx, logy);
648
649 return true;
650}
651
652///////////////////////////////////////////////////////////////////////////////////////////////////////
653// specialized exporter implementations
654///////////////////////////////////////////////////////////////////////////////////////////////////////
655template <class RooArg_t>
656bool exportAddPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
657{
658 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
659 elem["type"] << key;
660 RooJSONFactoryWSTool::fillSeq(elem["summands"], pdf->pdfList());
661 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
662 elem["extended"] << (pdf->extendMode() != RooArg_t::CanNotBeExtended);
663 return true;
664}
665
666bool exportRealSumPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
667{
668 const RooRealSumPdf *pdf = static_cast<const RooRealSumPdf *>(func);
669 elem["type"] << key;
670 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
671 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
672 elem["extended"] << (pdf->extendMode() != RooAbsPdf::CanNotBeExtended);
673 return true;
674}
675
676bool exportRealSumFunc(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
677{
678 const RooRealSumFunc *pdf = static_cast<const RooRealSumFunc *>(func);
679 elem["type"] << key;
680 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
681 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
682 return true;
683}
684
685template <class RooArg_t>
686bool exportHist(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem, std::string const &key)
687{
688 const RooArg_t *hf = static_cast<const RooArg_t *>(func);
689 elem["type"] << key;
690 RooDataHist const &dh = hf->dataHist();
691 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
692 return true;
693}
694
695template <class RooArg_t>
697{
698 std::string name(RooJSONFactoryWSTool::name(p));
699 if (!p.has_child("data")) {
700 return false;
701 }
702 std::unique_ptr<RooDataHist> dataHist =
704 tool->wsEmplace<RooArg_t>(name, *dataHist->get(), *dataHist);
705 return true;
706}
707
708bool exportBinSamplingPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
709{
710 const RooBinSamplingPdf *pdf = static_cast<const RooBinSamplingPdf *>(func);
711 elem["type"] << key;
712 elem["pdf"] << pdf->pdf().GetName();
713 elem["observable"] << pdf->observable().GetName();
714 elem["epsilon"] << pdf->epsilon();
715 return true;
716}
717
718bool exportBinWidthFunction(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &)
719{
720 const RooBinWidthFunction *pdf = static_cast<const RooBinWidthFunction *>(func);
721 elem["type"] << (pdf->divideByBinWidth() ? "inverse_binvolume" : "binvolume");
722 elem["histogram"] << pdf->histFunc().GetName();
723 return true;
724}
725
727{
728 // Plain substring replacement would also hit longer identifiers that
729 // share a prefix (e.g. "TMath::Tan" in "TMath::TanH", or "TMath::Pi" in
730 // "TMath::PiOver2"), corrupting the exported expression. Identifiers
731 // without a replacement are kept as-is.
732 replaceIdentifier(expr, "TMath::Exp", "exp");
733 replaceIdentifier(expr, "TMath::Min", "min");
734 replaceIdentifier(expr, "TMath::Max", "max");
735 replaceIdentifier(expr, "TMath::Log", "log");
736 replaceIdentifier(expr, "TMath::Log10", "log10");
737 replaceIdentifier(expr, "TMath::Cos", "cos");
738 replaceIdentifier(expr, "TMath::CosH", "cosh");
739 replaceIdentifier(expr, "TMath::Sin", "sin");
740 replaceIdentifier(expr, "TMath::SinH", "sinh");
741 replaceIdentifier(expr, "TMath::Sqrt", "sqrt");
742 replaceIdentifier(expr, "TMath::Power", "pow");
743 replaceIdentifier(expr, "TMath::Erf", "erf");
744 replaceIdentifier(expr, "TMath::Erfc", "erfc");
745 replaceIdentifier(expr, "TMath::Floor", "floor");
746 replaceIdentifier(expr, "TMath::Ceil", "ceil");
747 replaceIdentifier(expr, "TMath::Abs", "abs");
748 replaceIdentifier(expr, "TMath::Tan", "tan");
749 replaceIdentifier(expr, "TMath::TanH", "tanh");
750 replaceIdentifier(expr, "TMath::ASin", "asin");
751 replaceIdentifier(expr, "TMath::ACos", "acos");
752 replaceIdentifier(expr, "TMath::ATan", "atan");
753 replaceIdentifier(expr, "TMath::ATan2", "atan2");
754 replaceIdentifier(expr, "TMath::Pi()", "PI");
755 replaceIdentifier(expr, "TMath::E()", "EULER");
756}
757
758template <class RooArg_t>
759bool exportFormulaArg(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
760{
761 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
762 elem["type"] << key;
763 TString expression(pdf->expression());
764 cleanExpression(expression);
765 // If the tokens follow the "x[#]" convention, the square braces enclosing each number
766 // ensures that there is a unique mapping between the token and parameter name
767 // If the tokens follow the "@#" convention, the numbers are not enclosed by braces.
768 // So there may be tokens with numbers whose lower place value forms a subset string of ones with a higher place
769 // value, e.g. "@1" is a subset of "@10". So the names of these parameters must be applied descending from the
770 // highest place value in order to ensure each parameter name is uniquely applied to its token.
771 for (size_t idx = pdf->nParameters(); idx--;) {
772 const RooAbsArg *par = pdf->getParameter(idx);
773 expression.ReplaceAll(("x[" + std::to_string(idx) + "]").c_str(), par->GetName());
774 expression.ReplaceAll(("@" + std::to_string(idx)).c_str(), par->GetName());
775 }
776 elem["expression"] << expression.Data();
777 return true;
778}
779
780// Write the "x" reference and the coefficient list for polynomial-like
781// pdfs/funcs, including the implicit defaults below "lowestOrder" so that the
782// output is self-documenting.
783template <class Pdf>
784void writePolynomialBody(const Pdf *pdf, JSONNode &elem)
785{
786 elem["x"] << pdf->x().GetName();
787 auto &coefs = elem["coefficients"].set_seq();
788 for (int i = 0; i < pdf->lowestOrder(); ++i) {
789 coefs.append_child() << (i == 0 ? 1.0 : 0.0);
790 }
791 for (const auto &coef : pdf->coefList()) {
792 coefs.append_child() << coef->GetName();
793 }
794}
795
796template <class RooArg_t>
797bool exportPolynomial(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
798{
799 elem["type"] << key;
800 writePolynomialBody(static_cast<const RooArg_t *>(func), elem);
801 return true;
802}
803
804bool exportPoisson(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
805{
806 auto *pdf = static_cast<const RooPoisson *>(func);
807 elem["type"] << key;
808 elem["x"] << pdf->getX().GetName();
809 elem["mean"] << pdf->getMean().GetName();
810 elem["integer"] << !pdf->getNoRounding();
811 return true;
812}
813
814bool exportDecay(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
815{
816 auto *pdf = static_cast<const RooDecay *>(func);
817 elem["type"] << key;
818 elem["t"] << pdf->getT().GetName();
819 elem["tau"] << pdf->getTau().GetName();
820 elem["resolutionModel"] << pdf->getModel().GetName();
821 elem["decayType"] << pdf->getDecayType();
822
823 return true;
824}
825
826bool exportTruthModel(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
827{
828 auto *pdf = static_cast<const RooTruthModel *>(func);
829 elem["type"] << key;
830 elem["x"] << pdf->convVar().GetName();
831
832 return true;
833}
834
835bool exportGaussModel(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
836{
837 auto *pdf = static_cast<const RooGaussModel *>(func);
838 elem["type"] << key;
839 elem["x"] << pdf->convVar().GetName();
840 elem["mean"] << pdf->getMean().GetName();
841 elem["sigma"] << pdf->getSigma().GetName();
842 return true;
843}
844
845bool exportLogNormal(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem, std::string const &key)
846{
847 auto *pdf = static_cast<const RooLognormal *>(func);
848
849 elem["type"] << key;
850 elem["x"] << pdf->getX().GetName();
851
852 auto &m0 = pdf->getMedian();
853 auto &k = pdf->getShapeK();
854
855 if (pdf->useStandardParametrization()) {
856 elem["mu"] << m0.GetName();
857 elem["sigma"] << k.GetName();
858 } else {
859 elem["mu"] << tool->exportTransformed(&m0, "_lognormal_log", "log(%s)");
860 elem["sigma"] << tool->exportTransformed(&k, "_lognormal_log", "log(%s)");
861 }
862
863 return true;
864}
865
866bool exportExponential(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem, std::string const &key)
867{
868 auto *pdf = static_cast<const RooExponential *>(func);
869 elem["type"] << key;
870 elem["x"] << pdf->variable().GetName();
871 auto &c = pdf->coefficient();
872 if (pdf->negateCoefficient()) {
873 elem["c"] << c.GetName();
874 } else {
875 elem["c"] << tool->exportTransformed(&c, "_exponential_inverted", "-%s");
876 }
877
878 return true;
879}
880
881bool exportMultiVarGaussian(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
882{
883 auto *pdf = static_cast<const RooMultiVarGaussian *>(func);
884 elem["type"] << key;
885 RooJSONFactoryWSTool::fillSeq(elem["x"], pdf->xVec());
886 RooJSONFactoryWSTool::fillSeq(elem["mean"], pdf->muVec());
887 elem["covariances"].fill_mat(pdf->covarianceMatrix());
888 return true;
889}
890
891bool exportTFnBinding(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
892{
893 auto *pdf = static_cast<const RooTFnBinding *>(func);
894 elem["type"] << key;
895
896 TString formula(pdf->function().GetExpFormula());
897 formula.ReplaceAll("x", pdf->observables()[0].GetName());
898 formula.ReplaceAll("y", pdf->observables()[1].GetName());
899 formula.ReplaceAll("z", pdf->observables()[2].GetName());
900 for (size_t i = 0; i < pdf->parameters().size(); ++i) {
901 TString pname(TString::Format("[%d]", (int)i));
902 formula.ReplaceAll(pname, pdf->parameters()[i].GetName());
903 }
904 elem["expression"] << formula.Data();
905 return true;
906}
907
908bool exportDerivative(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
909{
910 auto *pdf = static_cast<const RooDerivative *>(func);
911 elem["type"] << key;
912 elem["x"] << pdf->getX().GetName();
913 elem["function"] << pdf->getFunc().GetName();
914 if (!pdf->getNset().empty()) {
915 RooJSONFactoryWSTool::fillSeq(elem["normalization"], pdf->getNset());
916 }
917 elem["order"] << pdf->order();
918 elem["eps"] << pdf->eps();
919 return true;
920}
921
922bool exportRealIntegral(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
923{
924 auto *integral = static_cast<const RooRealIntegral *>(func);
925 elem["type"] << key;
926 std::string integrand = integral->integrand().GetName();
927 elem["integrand"] << integrand;
928 if (integral->intRange()) {
929 elem["domain"] << integral->intRange();
930 }
931 RooJSONFactoryWSTool::fillSeq(elem["variables"], integral->intVars());
932 if (RooArgSet const *funcNormSet = integral->funcNormSet()) {
933 RooJSONFactoryWSTool::fillSeq(elem["normalization"], *funcNormSet);
934 }
935 return true;
936}
937
938bool exportFFTConvPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
939{
940 auto *pdf = static_cast<const RooFFTConvPdf *>(func);
941 elem["type"] << key;
942 if (auto convFunc = pdf->getPdfConvVar()) {
943 elem["conv_func"] << convFunc->GetName();
944 }
945 elem["conv_var"] << pdf->getConvVar().GetName();
946 elem["pdf1"] << pdf->getPdf1().GetName();
947 elem["pdf2"] << pdf->getPdf2().GetName();
948 elem["ipOrder"] << pdf->getInterpolationOrder();
949 return true;
950}
951
952bool exportExtendPdf(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
953{
954 auto *pdf = static_cast<const RooExtendPdf *>(func);
955 elem["type"] << key;
956 if (auto rangeName = pdf->getRangeName()) {
957 elem["range"] << rangeName->GetName();
958 }
959 elem["pdf"] << pdf->pdf().GetName();
960 elem["norm"] << pdf->getN().GetName();
961 return true;
962}
963
964bool exportParamHistFunc(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
965{
966 auto *pdf = static_cast<const ParamHistFunc *>(func);
967 elem["type"] << key;
968 RooJSONFactoryWSTool::fillSeq(elem["variables"], pdf->dataVars());
969 RooJSONFactoryWSTool::fillSeq(elem["parameters"], pdf->paramList());
970 auto &observablesNode = elem["axes"].set_seq();
971 // axes have to be ordered to get consistent bin indices
972 for (auto *var : static_range_cast<RooRealVar *>(pdf->dataVars())) {
973 RooJSONFactoryWSTool::exportAxis(observablesNode.append_child().set_map(), *var);
974 }
975 return true;
976}
977
978bool exportSpline(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem, std::string const &key)
979{
980 auto const *rs = static_cast<RooSpline const *>(func);
981
982 elem["type"] << key;
983
984 // Independent variable
985 elem["x"] << rs->x().GetName();
986
987 // Spline configuration
988 // Canonical algo for RooSpline
989 elem["interpolation"] << (rs->order() == 5 ? "poly5" : "poly3");
990 elem["logx"] << rs->logx();
991 elem["logy"] << rs->logy();
992
993 // Serialize knots as primitive arrays
994 TSpline const &sp = rs->spline();
995 auto &x0 = elem["x0"].set_seq();
996 auto &y0 = elem["y0"].set_seq();
997
998 const int np = sp.GetNp();
999 for (int i = 0; i < np; ++i) {
1000 double xk = 0.0, yk = 0.0;
1001 sp.GetKnot(i, xk, yk);
1002 x0.append_child() << xk;
1003 y0.append_child() << yk;
1004 }
1005
1006 return true;
1007}
1008
1010{
1011 if (node["type"].val() != "density_function_dist")
1012 return false;
1013
1014 auto name = RooJSONFactoryWSTool::name(node);
1015 auto *func = tool->requestArg<RooAbsReal>(node, "function");
1016
1017 bool selfNormalized = false;
1018
1019 if (auto sn = node.find("selfNormalized"))
1020 selfNormalized = sn->val_bool();
1021
1022 tool->wsEmplace<RooWrapperPdf>(name, *func, selfNormalized);
1023 return true;
1024}
1025
1026bool exportWrapperPdf(RooJSONFactoryWSTool *, const RooAbsArg *arg, JSONNode &node, std::string const &key)
1027{
1028 auto const *pdf = dynamic_cast<RooWrapperPdf const *>(arg);
1029 if (!pdf)
1030 return false;
1031
1032 node["type"] << key;
1033
1034 // Proxy name in RooWrapperPdf is "_func" / "func" depending on accessor/proxy export.
1035 // Prefer a public accessor if one exists; otherwise inspect proxies as below.
1036 auto const *funcProxy = dynamic_cast<RooRealProxy const *>(pdf->getProxy(0));
1037 if (!funcProxy || !funcProxy->absArg())
1038 return false;
1039
1040 node["function"] << funcProxy->absArg()->GetName();
1041 if (pdf->selfNormalized())
1042 node["selfnormalized"] << true;
1043
1044 return true;
1045}
1046
1047///////////////////////////////////////////////////////////////////////////////////////////////////////
1048// instantiate all importers and exporters
1049///////////////////////////////////////////////////////////////////////////////////////////////////////
1050
1051// Adapters that wrap the plain import/export functions above into the
1052// RooFit::JSONIO::Importer/Exporter interface. The exporter also owns the HS3
1053// type key, which is passed at registration time.
1054template <auto Func>
1055class FuncImporter : public RooFit::JSONIO::Importer {
1056public:
1057 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override { return Func(tool, p); }
1058};
1059
1060template <auto Func>
1061class FuncExporter : public RooFit::JSONIO::Exporter {
1062public:
1063 FuncExporter(std::string key) : _key{std::move(key)} {}
1064 std::string const &key() const override { return _key; }
1065 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
1066 {
1067 return Func(tool, func, elem, _key);
1068 }
1069
1070private:
1071 const std::string _key;
1072};
1073
1074template <auto Func>
1075void registerImporter(const std::string &key, bool topPriority = true)
1076{
1078}
1079
1080template <auto Func>
1081void registerExporter(TClass const *cl, std::string key, bool topPriority = true)
1082{
1083 RooFit::JSONIO::registerExporter(cl, std::make_unique<FuncExporter<Func>>(std::move(key)), topPriority);
1084}
1085
1086STATIC_EXECUTE([]() {
1087 registerImporter<importWrapperPdf>("density_function_dist");
1088 registerImporter<importExtendPdf>("rate_extended_dist");
1089 registerImporter<importProduct>("product", false);
1090 registerImporter<importProdPdf>("product_dist", false);
1092 registerImporter<importAddPdf>("mixture_dist", false);
1093 registerImporter<importAddModel>("mixture_resolution_model", false);
1094 registerImporter<importBinSamplingPdf>("binsampling_dist", false);
1096 registerImporter<importBinWidthFunction<true>>("inverse_binvolume", false);
1097 registerImporter<importPolynomial<RooLegacyExpPoly>>("legacy_exp_poly_dist", false);
1098 registerImporter<importExponential>("exponential_dist", false);
1100 registerImporter<importFormulaArg<RooFormulaVar>>("generic_function", false);
1102 registerImporter<importHist<RooHistFunc>>("histogram", false);
1104 registerImporter<importHist<RooHistPdf>>("histogram_dist", false);
1105 registerImporter<importLogNormal>("lognormal_dist", false);
1106 registerImporter<importMultiVarGaussian>("multivariate_normal_dist", false);
1107 registerImporter<importPoisson>("poisson_dist", false);
1108 registerImporter<importDecay>("decay_dist", false);
1109 registerImporter<importTruthModel>("delta_resolution_model", false);
1110 registerImporter<importGaussModel>("gauss_resolution_model", false);
1111 registerImporter<importPolynomial<RooPolynomial>>("polynomial_dist", false);
1113 registerImporter<importRealSumPdf>("weighted_sum_dist", false);
1114 registerImporter<importRealSumFunc>("weighted_sum", false);
1115 registerImporter<importRealIntegral>("integral", false);
1116 registerImporter<importDerivative>("derivative", false);
1117 registerImporter<importFFTConvPdf>("fft_convolution_dist", false);
1118 registerImporter<importExtendPdf>("extend_pdf", false);
1120 registerImporter<importSpline>("spline", false);
1121
1122 registerExporter<exportWrapperPdf>(RooWrapperPdf::Class(), "density_function_dist");
1124 registerExporter<exportAddPdf<RooAddModel>>(RooAddModel::Class(), "mixture_resolution_model", false);
1128 registerExporter<exportExponential>(RooExponential::Class(), "exponential_dist", false);
1133 registerExporter<exportLogNormal>(RooLognormal::Class(), "lognormal_dist", false);
1134 registerExporter<exportMultiVarGaussian>(RooMultiVarGaussian::Class(), "multivariate_normal_dist", false);
1135 registerExporter<exportPoisson>(RooPoisson::Class(), "poisson_dist", false);
1136 registerExporter<exportDecay>(RooDecay::Class(), "decay_dist", false);
1137 registerExporter<exportTruthModel>(RooTruthModel::Class(), "delta_resolution_model", false);
1138 registerExporter<exportGaussModel>(RooGaussModel::Class(), "gauss_resolution_model", false);
1142 registerExporter<exportRealSumPdf>(RooRealSumPdf::Class(), "weighted_sum_dist", false);
1143 registerExporter<exportTFnBinding>(RooTFnBinding::Class(), "generic_function", false);
1146 registerExporter<exportFFTConvPdf>(RooFFTConvPdf::Class(), "fft_convolution_dist", false);
1147 registerExporter<exportExtendPdf>(RooExtendPdf::Class(), "rate_extended_dist", false);
1150});
1151
1152} // 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:145
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:2385
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:122
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:129
#define STATIC_EXECUTE(MY_FUNC)