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 <RooWorkspace.h>
52#include <RooRealIntegral.h>
53#include <RooSpline.h>
54#include <TSpline.h>
55
56#include <TF1.h>
57#include <TH1.h>
58
59#include "JSONIOUtils.h"
60
61#include "static_execute.h"
62
63#include <algorithm>
64#include <cctype>
65
67
68///////////////////////////////////////////////////////////////////////////////////////////////////////
69// individually implemented importers
70///////////////////////////////////////////////////////////////////////////////////////////////////////
71
72namespace {
73/**
74 * Extracts arguments from a mathematical expression.
75 *
76 * This function takes a string representing a mathematical
77 * expression and extracts the arguments from it. The arguments are
78 * defined as sequences of characters that do not contain digits,
79 * spaces, or parentheses, and that start with a letter. Function
80 * calls such as "exp( ... )", identified as being followed by an
81 * opening parenthesis, are not treated as arguments. The extracted
82 * arguments are returned as a vector of strings.
83 *
84 * @param expr A string representing a mathematical expression.
85 * @return A set of unique strings representing the extracted arguments.
86 */
87std::set<std::string> extractArguments(std::string expr)
88{
89 // Get rid of whitespaces
90 expr.erase(std::remove_if(expr.begin(), expr.end(), [](unsigned char c) { return std::isspace(c); }), expr.end());
91
92 std::set<std::string> arguments;
93 size_t startidx = expr.size();
94 for (size_t i = 0; i < expr.size(); ++i) {
95 if (startidx >= expr.size()) {
96 if (isalpha(expr[i])) {
97 startidx = i;
98 // check this character is not part of scientific notation, e.g. 2e-5
100 // if it is, we ignore this character
101 startidx = expr.size();
102 }
103 }
104 } else {
105 if (!isdigit(expr[i]) && !isalpha(expr[i]) && expr[i] != '_') {
106 if (expr[i] == '(') {
107 startidx = expr.size();
108 continue;
109 }
110 std::string arg(expr.substr(startidx, i - startidx));
111 startidx = expr.size();
112 arguments.insert(arg);
113 }
114 }
115 }
116 if (startidx < expr.size()) {
117 arguments.insert(expr.substr(startidx));
118 }
119 return arguments;
120}
121
122template <class RooArg_t>
123class RooFormulaArgFactory : public RooFit::JSONIO::Importer {
124public:
125 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
126 {
127 std::string name(RooJSONFactoryWSTool::name(p));
128 if (!p.has_child("expression")) {
129 RooJSONFactoryWSTool::error("no expression given for '" + name + "'");
130 }
131 TString formula(p["expression"].val());
132 RooArgList dependents;
133 for (const auto &d : extractArguments(formula.Data())) {
134 dependents.add(*tool->request<RooAbsReal>(d, name));
135 }
136 tool->wsImport(RooArg_t{name.c_str(), formula, dependents});
137 return true;
138 }
139};
140
141// Fast-path importers for RooProduct, RooAddition, and RooProdPdf that
142// bypass the generic factory-expression mechanism. The default path
143// generates a string expression and passes it to gROOT->ProcessLineFast(),
144// which invokes the Cling JIT for every single call. For workspaces with
145// thousands of product/sum nodes (a common shape for HistFactory models)
146// that JIT cost dominates JSON import time. Constructing the RooFit object
147// directly here keeps the work O(N) of cheap C++ calls.
148class RooProductFactory : public RooFit::JSONIO::Importer {
149public:
150 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
151 {
152 std::string name(RooJSONFactoryWSTool::name(p));
153 tool->wsEmplace<RooProduct>(name, tool->requestArgList<RooAbsReal>(p, "factors"));
154 return true;
155 }
156};
157
158class RooProdPdfFactory : public RooFit::JSONIO::Importer {
159public:
160 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
161 {
162 std::string name(RooJSONFactoryWSTool::name(p));
163 tool->wsEmplace<RooProdPdf>(name, tool->requestArgList<RooAbsPdf>(p, "factors"));
164 return true;
165 }
166};
167
168class RooAdditionFactory : public RooFit::JSONIO::Importer {
169public:
170 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
171 {
172 std::string name(RooJSONFactoryWSTool::name(p));
173 tool->wsEmplace<RooAddition>(name, tool->requestArgList<RooAbsReal>(p, "summands"));
174 return true;
175 }
176};
177
178class RooAddPdfFactory : public RooFit::JSONIO::Importer {
179public:
180 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
181 {
182 std::string name(RooJSONFactoryWSTool::name(p));
183 if (!tool->requestArgList<RooAbsReal>(p, "coefficients").empty()) {
184 tool->wsEmplace<RooAddPdf>(name, tool->requestArgList<RooAbsPdf>(p, "summands"),
185 tool->requestArgList<RooAbsReal>(p, "coefficients"));
186 return true;
187 }
188 tool->wsEmplace<RooAddPdf>(name, tool->requestArgList<RooAbsPdf>(p, "summands"));
189 return true;
190 }
191};
192
193class RooAddModelFactory : public RooFit::JSONIO::Importer {
194public:
195 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
196 {
197 std::string name(RooJSONFactoryWSTool::name(p));
198 tool->wsEmplace<RooAddModel>(name, tool->requestArgList<RooAbsPdf>(p, "summands"),
199 tool->requestArgList<RooAbsReal>(p, "coefficients"));
200 return true;
201 }
202};
203
204class RooBinWidthFunctionFactory : public RooFit::JSONIO::Importer {
205public:
206 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
207 {
208 std::string name(RooJSONFactoryWSTool::name(p));
209 RooHistFunc *hf = static_cast<RooHistFunc *>(tool->request<RooAbsReal>(p["histogram"].val(), name));
210 tool->wsEmplace<RooBinWidthFunction>(name, *hf, p["divideByBinWidth"].val_bool());
211 return true;
212 }
213};
214
215class RooBinSamplingPdfFactory : public RooFit::JSONIO::Importer {
216public:
217 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
218 {
219 std::string name(RooJSONFactoryWSTool::name(p));
220
221 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
222 RooRealVar *obs = tool->requestArg<RooRealVar>(p, "observable");
223
224 if (!pdf->dependsOn(*obs)) {
225 RooJSONFactoryWSTool::error(std::string("pdf '") + pdf->GetName() + "' does not depend on observable '" +
226 obs->GetName() + "' as indicated by parent RooBinSamplingPdf '" + name +
227 "', please check!");
228 }
229
230 if (!p.has_child("epsilon")) {
231 RooJSONFactoryWSTool::error("no epsilon given in '" + name + "'");
232 }
233 double epsilon(p["epsilon"].val_double());
234
235 tool->wsEmplace<RooBinSamplingPdf>(name, *obs, *pdf, epsilon);
236
237 return true;
238 }
239};
240
241class RooRealSumPdfFactory : public RooFit::JSONIO::Importer {
242public:
243 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
244 {
245 std::string name(RooJSONFactoryWSTool::name(p));
246
247 bool extended = false;
248 if (p.has_child("extended") && p["extended"].val_bool()) {
249 extended = true;
250 }
251 tool->wsEmplace<RooRealSumPdf>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
252 tool->requestArgList<RooAbsReal>(p, "coefficients"), extended);
253 return true;
254 }
255};
256
257class RooRealSumFuncFactory : public RooFit::JSONIO::Importer {
258public:
259 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
260 {
261 std::string name(RooJSONFactoryWSTool::name(p));
262 tool->wsEmplace<RooRealSumFunc>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
263 tool->requestArgList<RooAbsReal>(p, "coefficients"));
264 return true;
265 }
266};
267template <class RooArg_t>
268class RooPolynomialFactory : public RooFit::JSONIO::Importer {
269public:
270 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
271 {
272 std::string name(RooJSONFactoryWSTool::name(p));
273 if (!p.has_child("coefficients")) {
274 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
275 }
276 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
277 RooArgList coefs;
278 int order = 0;
279 int lowestOrder = 0;
280 for (const auto &coef : p["coefficients"].children()) {
281 // As long as the coefficients match the default coefficients in
282 // RooFit, we don't have to instantiate RooFit objects but can
283 // increase the lowestOrder flag.
284 if (order == 0 && coef.val() == "1.0") {
285 ++lowestOrder;
286 } else if (coefs.empty() && coef.val() == "0.0") {
287 ++lowestOrder;
288 } else {
289 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
290 }
291 ++order;
292 }
293
294 tool->wsEmplace<RooArg_t>(name, *x, coefs, lowestOrder);
295 return true;
296 }
297};
298
299class RooPoissonFactory : public RooFit::JSONIO::Importer {
300public:
301 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
302 {
303 std::string name(RooJSONFactoryWSTool::name(p));
304 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
305 RooAbsReal *mean = tool->requestArg<RooAbsReal>(p, "mean");
306 tool->wsEmplace<RooPoisson>(name, *x, *mean, !p["integer"].val_bool());
307 return true;
308 }
309};
310
311class RooDecayFactory : public RooFit::JSONIO::Importer {
312public:
313 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
314 {
315 std::string name(RooJSONFactoryWSTool::name(p));
316 RooRealVar *t = tool->requestArg<RooRealVar>(p, "t");
317 RooAbsReal *tau = tool->requestArg<RooAbsReal>(p, "tau");
318 RooResolutionModel *model = dynamic_cast<RooResolutionModel *>(tool->requestArg<RooAbsPdf>(p, "resolutionModel"));
319 RooDecay::DecayType decayType = static_cast<RooDecay::DecayType>(p["decayType"].val_int());
320 tool->wsEmplace<RooDecay>(name, *t, *tau, *model, decayType);
321 return true;
322 }
323};
324
325class RooTruthModelFactory : public RooFit::JSONIO::Importer {
326public:
327 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
328 {
329 std::string name(RooJSONFactoryWSTool::name(p));
330 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
331 tool->wsEmplace<RooTruthModel>(name, *x);
332 return true;
333 }
334};
335
336class RooGaussModelFactory : public RooFit::JSONIO::Importer {
337public:
338 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
339 {
340 std::string name(RooJSONFactoryWSTool::name(p));
341 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
342 RooRealVar *mean = tool->requestArg<RooRealVar>(p, "mean");
343 RooRealVar *sigma = tool->requestArg<RooRealVar>(p, "sigma");
344 tool->wsEmplace<RooGaussModel>(name, *x, *mean, *sigma);
345 return true;
346 }
347};
348
349class RooRealIntegralFactory : public RooFit::JSONIO::Importer {
350public:
351 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
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};
373
374class RooDerivativeFactory : public RooFit::JSONIO::Importer {
375public:
376 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
377 {
378 std::string name(RooJSONFactoryWSTool::name(p));
379 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "function");
380 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
381 Int_t order = p["order"].val_int();
382 double eps = p["eps"].val_double();
383 if (p.has_child("normalization")) {
385 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
386 tool->wsEmplace<RooDerivative>(name, *func, *x, normSet, order, eps);
387 return true;
388 }
389 tool->wsEmplace<RooDerivative>(name, *func, *x, order, eps);
390 return true;
391 }
392};
393
394class RooFFTConvPdfFactory : public RooFit::JSONIO::Importer {
395public:
396 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
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};
412
413class RooExtendPdfFactory : public RooFit::JSONIO::Importer {
414public:
415 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
416 {
417 std::string name(RooJSONFactoryWSTool::name(p));
418 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
419 RooAbsReal *norm = tool->requestArg<RooAbsReal>(p, "norm");
420 if (p.has_child("range")) {
421 std::string rangeName = p["range"].val();
422 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm, rangeName.c_str());
423 return true;
424 }
425 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm);
426 return true;
427 }
428};
429
430class RooLogNormalFactory : public RooFit::JSONIO::Importer {
431public:
432 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
433 {
434 std::string name(RooJSONFactoryWSTool::name(p));
435 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
436
437 // Same mechanism to undo the parameter transformation as in the
438 // RooExponentialFactory (see comments in that class for more info).
439 const std::string muName = p["mu"].val();
440 const std::string sigmaName = p["sigma"].val();
441 const bool isTransformed = endsWith(muName, "_lognormal_log");
442 const std::string suffixToRemove = isTransformed ? "_lognormal_log" : "";
445
446 tool->wsEmplace<RooLognormal>(name, *x, *mu, *sigma, !isTransformed);
447
448 return true;
449 }
450};
451
452class RooExponentialFactory : public RooFit::JSONIO::Importer {
453public:
454 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
455 {
456 std::string name(RooJSONFactoryWSTool::name(p));
457 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
458
459 // If the parameter name ends with the "_exponential_inverted" suffix,
460 // this means that it was exported from a RooFit object where the
461 // parameter first needed to be transformed on export to match the HS3
462 // specification. But when re-importing such a parameter, we can simply
463 // skip the transformation and use the original RooFit parameter without
464 // the suffix.
465 //
466 // A concrete example: take the following RooFit pdf in the factory language:
467 //
468 // "Exponential::exponential_1(x[0, 10], c[-0.1])"
469 //
470 // It defines en exponential exp(c * x). However, in HS3 the exponential
471 // is defined as exp(-c * x), to RooFit would export these dictionaries
472 // to the JSON:
473 //
474 // {
475 // "name": "exponential_1", // HS3 exponential_dist with transformed parameter
476 // "type": "exponential_dist",
477 // "x": "x",
478 // "c": "c_exponential_inverted"
479 // },
480 // {
481 // "name": "c_exponential_inverted", // transformation function created on-the-fly on export
482 // "type": "generic_function",
483 // "expression": "-c"
484 // }
485 //
486 // On import, we can directly take the non-transformed parameter, which is
487 // we check for the suffix and optionally remove it from the requested
488 // name next:
489
490 const std::string constParamName = p["c"].val();
491 const bool isInverted = endsWith(constParamName, "_exponential_inverted");
492 const std::string suffixToRemove = isInverted ? "_exponential_inverted" : "";
494
495 tool->wsEmplace<RooExponential>(name, *x, *c, !isInverted);
496
497 return true;
498 }
499};
500
501class RooLegacyExpPolyFactory : public RooFit::JSONIO::Importer {
502public:
503 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
504 {
505 std::string name(RooJSONFactoryWSTool::name(p));
506 if (!p.has_child("coefficients")) {
507 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
508 }
509 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
510 RooArgList coefs;
511 int order = 0;
512 int lowestOrder = 0;
513 for (const auto &coef : p["coefficients"].children()) {
514 // As long as the coefficients match the default coefficients in
515 // RooFit, we don't have to instantiate RooFit objects but can
516 // increase the lowestOrder flag.
517 if (order == 0 && coef.val() == "1.0") {
518 ++lowestOrder;
519 } else if (coefs.empty() && coef.val() == "0.0") {
520 ++lowestOrder;
521 } else {
522 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
523 }
524 ++order;
525 }
526
527 tool->wsEmplace<RooLegacyExpPoly>(name, *x, coefs, lowestOrder);
528 return true;
529 }
530};
531
532class RooMultiVarGaussianFactory : public RooFit::JSONIO::Importer {
533public:
534 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
535 {
536 std::string name(RooJSONFactoryWSTool::name(p));
537 bool has_cov = p.has_child("covariances");
538 bool has_corr = p.has_child("correlations") && p.has_child("standard_deviations");
539 if (!has_cov && !has_corr) {
540 RooJSONFactoryWSTool::error("no covariances or correlations+standard_deviations given in '" + name + "'");
541 }
542
544
545 if (has_cov) {
546 int n = p["covariances"].num_children();
547 int i = 0;
548 covmat.ResizeTo(n, n);
549 for (const auto &row : p["covariances"].children()) {
550 int j = 0;
551 for (const auto &val : row.children()) {
552 covmat(i, j) = val.val_double();
553 ++j;
554 }
555 ++i;
556 }
557 } else {
558 std::vector<double> variances;
559 for (const auto &v : p["standard_deviations"].children()) {
560 variances.push_back(v.val_double());
561 }
562 covmat.ResizeTo(variances.size(), variances.size());
563 int i = 0;
564 for (const auto &row : p["correlations"].children()) {
565 int j = 0;
566 for (const auto &val : row.children()) {
567 covmat(i, j) = val.val_double() * variances[i] * variances[j];
568 ++j;
569 }
570 ++i;
571 }
572 }
573 tool->wsEmplace<RooMultiVarGaussian>(name, tool->requestArgList<RooAbsReal>(p, "x"),
574 tool->requestArgList<RooAbsReal>(p, "mean"), covmat);
575 return true;
576 }
577};
578
579class ParamHistFuncFactory : public RooFit::JSONIO::Importer {
580public:
581 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
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
598private:
600 {
601 // Temporary map from variable name → RooRealVar
602 std::map<std::string, std::unique_ptr<RooRealVar>> varMap;
603
604 // Build variables from JSON
605 for (const JSONNode &node : topNode["axes"].children()) {
606 const std::string name = node["name"].val();
607 std::unique_ptr<RooRealVar> obs;
608
609 if (node.has_child("edges")) {
610 std::vector<double> edges;
611 for (const auto &bound : node["edges"].children()) {
612 edges.push_back(bound.val_double());
613 }
614 obs = std::make_unique<RooRealVar>(name.c_str(), name.c_str(), edges.front(), edges.back());
615 RooBinning bins(obs->getMin(), obs->getMax());
616 for (auto b : edges)
617 bins.addBoundary(b);
618 obs->setBinning(bins);
619 } else {
620 obs = std::make_unique<RooRealVar>(name.c_str(), name.c_str(), node["min"].val_double(),
621 node["max"].val_double());
622 obs->setBins(node["nbins"].val_int());
623 }
624
625 varMap[name] = std::move(obs);
626 }
627
628 // Now build the final list following the order in varList
629 RooArgList vars;
630 for (int i = 0; i < varList.getSize(); ++i) {
631 const auto *refVar = dynamic_cast<RooRealVar *>(varList.at(i));
632 if (!refVar)
633 continue;
634
635 auto it = varMap.find(refVar->GetName());
636 if (it != varMap.end()) {
637 vars.addOwned(std::move(it->second)); // preserve ownership
638 }
639 }
640 return vars;
641 }
642};
643
644class RooSplineFactory : public RooFit::JSONIO::Importer {
645public:
646 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
647 {
648 const std::string name(RooJSONFactoryWSTool::name(p));
649
650 // Mandatory fields
651 if (!p.has_child("x")) {
652 RooJSONFactoryWSTool::error("no x given in '" + name + "'");
653 }
654 if (!p.has_child("x0") || !p.has_child("y0")) {
655 RooJSONFactoryWSTool::error("no x0/y0 given in '" + name + "'");
656 }
657
658 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
659
660 // Optional fields (defaults follow RooSpline ctor defaults)
661 std::string algo = p.has_child("interpolation") ? p["interpolation"].val() : "poly3";
662 int order = 0;
663 if (algo == "poly3")
664 order = 3;
665 else if (algo == "poly5")
666 order = 5;
667 else {
668 RooJSONFactoryWSTool::error("unsupported algo '" + algo + "' for RooSpline in '" + name +
669 "': allowed are 'poly3' and 'poly5'");
670 }
671 const bool logx = p.has_child("logx") ? p["logx"].val_bool() : false;
672 const bool logy = p.has_child("logy") ? p["logy"].val_bool() : false;
673
674 // Read knots
675 std::vector<double> x0;
676 std::vector<double> y0;
677 x0.reserve(p["x0"].num_children());
678 y0.reserve(p["y0"].num_children());
679
680 for (const auto &v : p["x0"].children())
681 x0.push_back(v.val_double());
682 for (const auto &v : p["y0"].children())
683 y0.push_back(v.val_double());
684
685 if (x0.size() != y0.size()) {
686 RooJSONFactoryWSTool::error("x0/y0 size mismatch in '" + name + "': x0 has " + std::to_string(x0.size()) +
687 ", y0 has " + std::to_string(y0.size()));
688 }
689 if (x0.size() < 2) {
690 RooJSONFactoryWSTool::error("need at least 2 knots in '" + name + "'");
691 }
692
693 // Construct RooSpline(name,title, x, x0, y0, order, logx, logy)
694 tool->wsEmplace<::RooSpline>(name.c_str(), *x, std::span<const double>(x0.data(), x0.size()),
695 std::span<const double>(y0.data(), y0.size()), order, logx, logy);
696
697 return true;
698 }
699};
700
701///////////////////////////////////////////////////////////////////////////////////////////////////////
702// specialized exporter implementations
703///////////////////////////////////////////////////////////////////////////////////////////////////////
704template <class RooArg_t>
705class RooAddPdfStreamer : public RooFit::JSONIO::Exporter {
706public:
707 std::string const &key() const override;
708 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
709 {
710 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
711 elem["type"] << key();
712 RooJSONFactoryWSTool::fillSeq(elem["summands"], pdf->pdfList());
713 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
714 elem["extended"] << (pdf->extendMode() != RooArg_t::CanNotBeExtended);
715 return true;
716 }
717};
718
719class RooRealSumPdfStreamer : public RooFit::JSONIO::Exporter {
720public:
721 std::string const &key() const override;
722 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
723 {
724 const RooRealSumPdf *pdf = static_cast<const RooRealSumPdf *>(func);
725 elem["type"] << key();
726 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
727 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
728 elem["extended"] << (pdf->extendMode() != RooAbsPdf::CanNotBeExtended);
729 return true;
730 }
731};
732
733class RooRealSumFuncStreamer : public RooFit::JSONIO::Exporter {
734public:
735 std::string const &key() const override;
736 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
737 {
738 const RooRealSumFunc *pdf = static_cast<const RooRealSumFunc *>(func);
739 elem["type"] << key();
740 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
741 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
742 return true;
743 }
744};
745
746class RooHistFuncStreamer : public RooFit::JSONIO::Exporter {
747public:
748 std::string const &key() const override;
749 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
750 {
751 const RooHistFunc *hf = static_cast<const RooHistFunc *>(func);
752 elem["type"] << key();
753 RooDataHist const &dh = hf->dataHist();
754 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
755 return true;
756 }
757};
758
759class RooHistFuncFactory : public RooFit::JSONIO::Importer {
760public:
761 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
762 {
763 std::string name(RooJSONFactoryWSTool::name(p));
764 if (!p.has_child("data")) {
765 RooJSONFactoryWSTool::error("function '" + name + "' is of histogram type, but does not define a 'data' key");
766 }
767 std::unique_ptr<RooDataHist> dataHist =
769 tool->wsEmplace<RooHistFunc>(name, *dataHist->get(), *dataHist);
770 return true;
771 }
772};
773
774class RooHistPdfStreamer : public RooFit::JSONIO::Exporter {
775public:
776 std::string const &key() const override;
777 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
778 {
779 const RooHistPdf *hf = static_cast<const RooHistPdf *>(func);
780 elem["type"] << key();
781 RooDataHist const &dh = hf->dataHist();
782 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
783 return true;
784 }
785};
786
787class RooHistPdfFactory : public RooFit::JSONIO::Importer {
788public:
789 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
790 {
791 std::string name(RooJSONFactoryWSTool::name(p));
792 if (!p.has_child("data")) {
793 RooJSONFactoryWSTool::error("function '" + name + "' is of histogram type, but does not define a 'data' key");
794 }
795 std::unique_ptr<RooDataHist> dataHist =
797 tool->wsEmplace<RooHistPdf>(name, *dataHist->get(), *dataHist);
798 return true;
799 }
800};
801
802class RooBinSamplingPdfStreamer : public RooFit::JSONIO::Exporter {
803public:
804 std::string const &key() const override;
805 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
806 {
807 const RooBinSamplingPdf *pdf = static_cast<const RooBinSamplingPdf *>(func);
808 elem["type"] << key();
809 elem["pdf"] << pdf->pdf().GetName();
810 elem["observable"] << pdf->observable().GetName();
811 elem["epsilon"] << pdf->epsilon();
812 return true;
813 }
814};
815
816class RooBinWidthFunctionStreamer : public RooFit::JSONIO::Exporter {
817public:
818 std::string const &key() const override;
819 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
820 {
821 const RooBinWidthFunction *pdf = static_cast<const RooBinWidthFunction *>(func);
822 elem["type"] << key();
823 elem["histogram"] << pdf->histFunc().GetName();
824 elem["divideByBinWidth"] << pdf->divideByBinWidth();
825 return true;
826 }
827};
828
829template <class RooArg_t>
830class RooFormulaArgStreamer : public RooFit::JSONIO::Exporter {
831public:
832 std::string const &key() const override;
833 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
834 {
835 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
836 elem["type"] << key();
837 TString expression(pdf->expression());
838 cleanExpression(expression);
839 // If the tokens follow the "x[#]" convention, the square braces enclosing each number
840 // ensures that there is a unique mapping between the token and parameter name
841 // If the tokens follow the "@#" convention, the numbers are not enclosed by braces.
842 // So there may be tokens with numbers whose lower place value forms a subset string of ones with a higher place
843 // value, e.g. "@1" is a subset of "@10". So the names of these parameters must be applied descending from the
844 // highest place value in order to ensure each parameter name is uniquely applied to its token.
845 for (size_t idx = pdf->nParameters(); idx--;) {
846 const RooAbsArg *par = pdf->getParameter(idx);
847 expression.ReplaceAll(("x[" + std::to_string(idx) + "]").c_str(), par->GetName());
848 expression.ReplaceAll(("@" + std::to_string(idx)).c_str(), par->GetName());
849 }
850 elem["expression"] << expression.Data();
851 return true;
852 }
853
854private:
855 void cleanExpression(TString &expr) const
856 {
857 expr.ReplaceAll("TMath::Exp", "exp");
858 expr.ReplaceAll("TMath::Min", "min");
859 expr.ReplaceAll("TMath::Max", "max");
860 expr.ReplaceAll("TMath::Log", "log");
861 expr.ReplaceAll("TMath::Cos", "cos");
862 expr.ReplaceAll("TMath::Sin", "sin");
863 expr.ReplaceAll("TMath::Sqrt", "sqrt");
864 expr.ReplaceAll("TMath::Power", "pow");
865 expr.ReplaceAll("TMath::Erf", "erf");
866 }
867};
868// Write the "x" reference and the coefficient list for polynomial-like
869// pdfs/funcs, including the implicit defaults below "lowestOrder" so that the
870// output is self-documenting.
871template <class Pdf>
872void writePolynomialBody(const Pdf *pdf, JSONNode &elem)
873{
874 elem["x"] << pdf->x().GetName();
875 auto &coefs = elem["coefficients"].set_seq();
876 for (int i = 0; i < pdf->lowestOrder(); ++i) {
877 coefs.append_child() << (i == 0 ? "1.0" : "0.0");
878 }
879 for (const auto &coef : pdf->coefList()) {
880 coefs.append_child() << coef->GetName();
881 }
882}
883
884template <class RooArg_t>
885class RooPolynomialStreamer : public RooFit::JSONIO::Exporter {
886public:
887 std::string const &key() const override;
888 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
889 {
890 elem["type"] << key();
891 writePolynomialBody(static_cast<const RooArg_t *>(func), elem);
892 return true;
893 }
894};
895
896class RooLegacyExpPolyStreamer : public RooFit::JSONIO::Exporter {
897public:
898 std::string const &key() const override;
899 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
900 {
901 elem["type"] << key();
902 writePolynomialBody(static_cast<const RooLegacyExpPoly *>(func), elem);
903 return true;
904 }
905};
906
907class RooPoissonStreamer : public RooFit::JSONIO::Exporter {
908public:
909 std::string const &key() const override;
910 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
911 {
912 auto *pdf = static_cast<const RooPoisson *>(func);
913 elem["type"] << key();
914 elem["x"] << pdf->getX().GetName();
915 elem["mean"] << pdf->getMean().GetName();
916 elem["integer"] << !pdf->getNoRounding();
917 return true;
918 }
919};
920
921class RooDecayStreamer : public RooFit::JSONIO::Exporter {
922public:
923 std::string const &key() const override;
924 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
925 {
926 auto *pdf = static_cast<const RooDecay *>(func);
927 elem["type"] << key();
928 elem["t"] << pdf->getT().GetName();
929 elem["tau"] << pdf->getTau().GetName();
930 elem["resolutionModel"] << pdf->getModel().GetName();
931 elem["decayType"] << pdf->getDecayType();
932
933 return true;
934 }
935};
936
937class RooTruthModelStreamer : public RooFit::JSONIO::Exporter {
938public:
939 std::string const &key() const override;
940 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
941 {
942 auto *pdf = static_cast<const RooTruthModel *>(func);
943 elem["type"] << key();
944 elem["x"] << pdf->convVar().GetName();
945
946 return true;
947 }
948};
949
950class RooGaussModelStreamer : public RooFit::JSONIO::Exporter {
951public:
952 std::string const &key() const override;
953 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
954 {
955 auto *pdf = static_cast<const RooGaussModel *>(func);
956 elem["type"] << key();
957 elem["x"] << pdf->convVar().GetName();
958 elem["mean"] << pdf->getMean().GetName();
959 elem["sigma"] << pdf->getSigma().GetName();
960 return true;
961 }
962};
963
964class RooLogNormalStreamer : public RooFit::JSONIO::Exporter {
965public:
966 std::string const &key() const override;
967 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
968 {
969 auto *pdf = static_cast<const RooLognormal *>(func);
970
971 elem["type"] << key();
972 elem["x"] << pdf->getX().GetName();
973
974 auto &m0 = pdf->getMedian();
975 auto &k = pdf->getShapeK();
976
977 if (pdf->useStandardParametrization()) {
978 elem["mu"] << m0.GetName();
979 elem["sigma"] << k.GetName();
980 } else {
981 elem["mu"] << tool->exportTransformed(&m0, "_lognormal_log", "log(%s)");
982 elem["sigma"] << tool->exportTransformed(&k, "_lognormal_log", "log(%s)");
983 }
984
985 return true;
986 }
987};
988
989class RooExponentialStreamer : public RooFit::JSONIO::Exporter {
990public:
991 std::string const &key() const override;
992 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
993 {
994 auto *pdf = static_cast<const RooExponential *>(func);
995 elem["type"] << key();
996 elem["x"] << pdf->variable().GetName();
997 auto &c = pdf->coefficient();
998 if (pdf->negateCoefficient()) {
999 elem["c"] << c.GetName();
1000 } else {
1001 elem["c"] << tool->exportTransformed(&c, "_exponential_inverted", "-%s");
1002 }
1003
1004 return true;
1005 }
1006};
1007
1008class RooMultiVarGaussianStreamer : public RooFit::JSONIO::Exporter {
1009public:
1010 std::string const &key() const override;
1011 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
1012 {
1013 auto *pdf = static_cast<const RooMultiVarGaussian *>(func);
1014 elem["type"] << key();
1015 RooJSONFactoryWSTool::fillSeq(elem["x"], pdf->xVec());
1016 RooJSONFactoryWSTool::fillSeq(elem["mean"], pdf->muVec());
1017 elem["covariances"].fill_mat(pdf->covarianceMatrix());
1018 return true;
1019 }
1020};
1021
1022class RooTFnBindingStreamer : public RooFit::JSONIO::Exporter {
1023public:
1024 std::string const &key() const override;
1025 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
1026 {
1027 auto *pdf = static_cast<const RooTFnBinding *>(func);
1028 elem["type"] << key();
1029
1030 TString formula(pdf->function().GetExpFormula());
1031 formula.ReplaceAll("x", pdf->observables()[0].GetName());
1032 formula.ReplaceAll("y", pdf->observables()[1].GetName());
1033 formula.ReplaceAll("z", pdf->observables()[2].GetName());
1034 for (size_t i = 0; i < pdf->parameters().size(); ++i) {
1035 TString pname(TString::Format("[%d]", (int)i));
1036 formula.ReplaceAll(pname, pdf->parameters()[i].GetName());
1037 }
1038 elem["expression"] << formula.Data();
1039 return true;
1040 }
1041};
1042
1043class RooDerivativeStreamer : public RooFit::JSONIO::Exporter {
1044public:
1045 std::string const &key() const override;
1046 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
1047 {
1048 auto *pdf = static_cast<const RooDerivative *>(func);
1049 elem["type"] << key();
1050 elem["x"] << pdf->getX().GetName();
1051 elem["function"] << pdf->getFunc().GetName();
1052 if (!pdf->getNset().empty()) {
1053 RooJSONFactoryWSTool::fillSeq(elem["normalization"], pdf->getNset());
1054 }
1055 elem["order"] << pdf->order();
1056 elem["eps"] << pdf->eps();
1057 return true;
1058 }
1059};
1060
1061class RooRealIntegralStreamer : public RooFit::JSONIO::Exporter {
1062public:
1063 std::string const &key() const override;
1064 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
1065 {
1066 auto *integral = static_cast<const RooRealIntegral *>(func);
1067 elem["type"] << key();
1068 std::string integrand = integral->integrand().GetName();
1069 // elem["integrand"] << RooJSONFactoryWSTool::sanitizeName(integrand);
1070 elem["integrand"] << integrand;
1071 if (integral->intRange()) {
1072 elem["domain"] << integral->intRange();
1073 }
1074 RooJSONFactoryWSTool::fillSeq(elem["variables"], integral->intVars());
1075 if (RooArgSet const *funcNormSet = integral->funcNormSet()) {
1076 RooJSONFactoryWSTool::fillSeq(elem["normalization"], *funcNormSet);
1077 }
1078 return true;
1079 }
1080};
1081
1082class RooFFTConvPdfStreamer : public RooFit::JSONIO::Exporter {
1083public:
1084 std::string const &key() const override;
1085 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
1086 {
1087 auto *pdf = static_cast<const RooFFTConvPdf *>(func);
1088 elem["type"] << key();
1089 if (auto convFunc = pdf->getPdfConvVar()) {
1090 elem["conv_func"] << convFunc->GetName();
1091 }
1092 elem["conv_var"] << pdf->getConvVar().GetName();
1093 elem["pdf1"] << pdf->getPdf1().GetName();
1094 elem["pdf2"] << pdf->getPdf2().GetName();
1095 elem["ipOrder"] << pdf->getInterpolationOrder();
1096 return true;
1097 }
1098};
1099
1100class RooExtendPdfStreamer : public RooFit::JSONIO::Exporter {
1101public:
1102 std::string const &key() const override;
1103 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
1104 {
1105 auto *pdf = static_cast<const RooExtendPdf *>(func);
1106 elem["type"] << key();
1107 if (auto rangeName = pdf->getRangeName()) {
1108 elem["range"] << rangeName->GetName();
1109 }
1110 elem["pdf"] << pdf->pdf().GetName();
1111 elem["norm"] << pdf->getN().GetName();
1112 return true;
1113 }
1114};
1115
1116class ParamHistFuncStreamer : public RooFit::JSONIO::Exporter {
1117public:
1118 std::string const &key() const override;
1119 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
1120 {
1121 auto *pdf = static_cast<const ParamHistFunc *>(func);
1122 elem["type"] << key();
1123 RooJSONFactoryWSTool::fillSeq(elem["variables"], pdf->dataVars());
1124 RooJSONFactoryWSTool::fillSeq(elem["parameters"], pdf->paramList());
1125 writeBinningInfo(pdf, elem);
1126 return true;
1127 }
1128
1129private:
1130 void writeBinningInfo(const ParamHistFunc *pdf, JSONNode &elem) const
1131 {
1132 auto &observablesNode = elem["axes"].set_seq();
1133 // axes have to be ordered to get consistent bin indices
1134 for (auto *var : static_range_cast<RooRealVar *>(pdf->dataVars())) {
1135 std::string name = var->GetName();
1137 JSONNode &obsNode = observablesNode.append_child().set_map();
1138 obsNode["name"] << name;
1139 auto const &binning = var->getBinning();
1140 if (binning.isUniform()) {
1141 obsNode["min"] << var->getMin();
1142 obsNode["max"] << var->getMax();
1143 obsNode["nbins"] << var->getBins();
1144 } else {
1145 auto &edges = obsNode["edges"].set_seq();
1146 edges.append_child() << binning.binLow(0);
1147 for (int i = 0; i < binning.numBins(); ++i) {
1148 edges.append_child() << binning.binHigh(i);
1149 }
1150 }
1151 }
1152 }
1153};
1154
1155class RooSplineStreamer : public RooFit::JSONIO::Exporter {
1156public:
1157 std::string const &key() const override;
1158
1159 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, RooFit::Detail::JSONNode &elem) const override
1160 {
1161 auto const *rs = static_cast<RooSpline const *>(func);
1162
1163 elem["type"] << key();
1164
1165 // Independent variable
1166 elem["x"] << rs->x().GetName();
1167
1168 // Spline configuration
1169 // Canonical algo for RooSpline
1170 elem["interpolation"] << (rs->order() == 5 ? "poly5" : "poly3");
1171 elem["logx"] << rs->logx();
1172 elem["logy"] << rs->logy();
1173
1174 // Serialize knots as primitive arrays
1175 TSpline const &sp = rs->spline();
1176 auto &x0 = elem["x0"].set_seq();
1177 auto &y0 = elem["y0"].set_seq();
1178
1179 const int np = sp.GetNp();
1180 for (int i = 0; i < np; ++i) {
1181 double xk = 0.0, yk = 0.0;
1182 sp.GetKnot(i, xk, yk);
1183 x0.append_child() << xk;
1184 y0.append_child() << yk;
1185 }
1186
1187 return true;
1188 }
1189};
1190
1191#define DEFINE_EXPORTER_KEY(class_name, name) \
1192 std::string const &class_name::key() const \
1193 { \
1194 const static std::string keystring = name; \
1195 return keystring; \
1196 }
1197template <>
1199template <>
1201DEFINE_EXPORTER_KEY(RooBinSamplingPdfStreamer, "binsampling");
1202DEFINE_EXPORTER_KEY(RooBinWidthFunctionStreamer, "binwidth");
1203DEFINE_EXPORTER_KEY(RooLegacyExpPolyStreamer, "legacy_exp_poly_dist");
1204DEFINE_EXPORTER_KEY(RooExponentialStreamer, "exponential_dist");
1205template <>
1207template <>
1209DEFINE_EXPORTER_KEY(RooHistFuncStreamer, "histogram");
1210DEFINE_EXPORTER_KEY(RooHistPdfStreamer, "histogram_dist");
1211DEFINE_EXPORTER_KEY(RooLogNormalStreamer, "lognormal_dist");
1212DEFINE_EXPORTER_KEY(RooMultiVarGaussianStreamer, "multivariate_normal_dist");
1213DEFINE_EXPORTER_KEY(RooPoissonStreamer, "poisson_dist");
1214DEFINE_EXPORTER_KEY(RooDecayStreamer, "decay_dist");
1215DEFINE_EXPORTER_KEY(RooTruthModelStreamer, "truth_model_function");
1216DEFINE_EXPORTER_KEY(RooGaussModelStreamer, "gauss_model_function");
1217template <>
1219template <>
1221DEFINE_EXPORTER_KEY(RooRealSumFuncStreamer, "weighted_sum");
1222DEFINE_EXPORTER_KEY(RooRealSumPdfStreamer, "weighted_sum_dist");
1223DEFINE_EXPORTER_KEY(RooTFnBindingStreamer, "generic_function");
1224DEFINE_EXPORTER_KEY(RooRealIntegralStreamer, "integral");
1225DEFINE_EXPORTER_KEY(RooDerivativeStreamer, "derivative");
1226DEFINE_EXPORTER_KEY(RooFFTConvPdfStreamer, "fft_conv_pdf");
1227DEFINE_EXPORTER_KEY(RooExtendPdfStreamer, "extend_pdf");
1228DEFINE_EXPORTER_KEY(ParamHistFuncStreamer, "step");
1229DEFINE_EXPORTER_KEY(RooSplineStreamer, "spline");
1230
1231///////////////////////////////////////////////////////////////////////////////////////////////////////
1232// instantiate all importers and exporters
1233///////////////////////////////////////////////////////////////////////////////////////////////////////
1234
1235STATIC_EXECUTE([]() {
1236 using namespace RooFit::JSONIO;
1237
1238 registerImporter<RooProductFactory>("product", false);
1239 registerImporter<RooProdPdfFactory>("product_dist", false);
1241 registerImporter<RooAddPdfFactory>("mixture_dist", false);
1242 registerImporter<RooAddModelFactory>("mixture_model", false);
1243 registerImporter<RooBinSamplingPdfFactory>("binsampling_dist", false);
1245 registerImporter<RooLegacyExpPolyFactory>("legacy_exp_poly_dist", false);
1246 registerImporter<RooExponentialFactory>("exponential_dist", false);
1247 registerImporter<RooFormulaArgFactory<RooFormulaVar>>("generic_function", false);
1249 registerImporter<RooHistFuncFactory>("histogram", false);
1250 registerImporter<RooHistPdfFactory>("histogram_dist", false);
1251 registerImporter<RooLogNormalFactory>("lognormal_dist", false);
1252 registerImporter<RooMultiVarGaussianFactory>("multivariate_normal_dist", false);
1253 registerImporter<RooPoissonFactory>("poisson_dist", false);
1254 registerImporter<RooDecayFactory>("decay_dist", false);
1255 registerImporter<RooTruthModelFactory>("truth_model_function", false);
1256 registerImporter<RooGaussModelFactory>("gauss_model_function", false);
1259 registerImporter<RooRealSumPdfFactory>("weighted_sum_dist", false);
1260 registerImporter<RooRealSumFuncFactory>("weighted_sum", false);
1262 registerImporter<RooDerivativeFactory>("derivative", false);
1263 registerImporter<RooFFTConvPdfFactory>("fft_conv_pdf", false);
1264 registerImporter<RooExtendPdfFactory>("extend_pdf", false);
1266 registerImporter<RooSplineFactory>("spline", false);
1267
1295});
1296
1297} // namespace
#define DEFINE_EXPORTER_KEY(class_name, name)
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, 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()
A probability density function sampled from a multidimensional histogram.
Definition RooHistPdf.h:30
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 bool testValidName(const std::string &str, bool forcError)
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.
RooLegacyExpPoly implements a polynomial PDF of the form.
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()
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
#define STATIC_EXECUTE(MY_FUNC)