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 <RooAddPdf.h>
16#include <RooBinSamplingPdf.h>
17#include <RooBinWidthFunction.h>
18#include <RooCategory.h>
19#include <RooDataHist.h>
20#include <RooExponential.h>
22#include <RooFitHS3/JSONIO.h>
23#include <RooFormulaVar.h>
24#include <RooGenericPdf.h>
25#include <RooHistFunc.h>
26#include <RooHistPdf.h>
27#include <RooLegacyExpPoly.h>
28#include <RooLognormal.h>
29#include <RooMultiVarGaussian.h>
30#include <RooPoisson.h>
31#include <RooPolynomial.h>
32#include <RooPolyVar.h>
33#include <RooRealSumFunc.h>
34#include <RooRealSumPdf.h>
35#include <RooRealVar.h>
36#include <RooTFnBinding.h>
37#include <RooWorkspace.h>
38#include <RooRealIntegral.h>
39
40#include <TF1.h>
41#include <TH1.h>
42
43#include "JSONIOUtils.h"
44
45#include "static_execute.h"
46
47#include <algorithm>
48#include <cctype>
49
51
52///////////////////////////////////////////////////////////////////////////////////////////////////////
53// individually implemented importers
54///////////////////////////////////////////////////////////////////////////////////////////////////////
55
56namespace {
57/**
58 * Extracts arguments from a mathematical expression.
59 *
60 * This function takes a string representing a mathematical
61 * expression and extracts the arguments from it. The arguments are
62 * defined as sequences of characters that do not contain digits,
63 * spaces, or parentheses, and that start with a letter. Function
64 * calls such as "exp( ... )", identified as being followed by an
65 * opening parenthesis, are not treated as arguments. The extracted
66 * arguments are returned as a vector of strings.
67 *
68 * @param expr A string representing a mathematical expression.
69 * @return A set of unique strings representing the extracted arguments.
70 */
71std::set<std::string> extractArguments(std::string expr)
72{
73 // Get rid of whitespaces
74 expr.erase(std::remove_if(expr.begin(), expr.end(), [](unsigned char c) { return std::isspace(c); }), expr.end());
75
76 std::set<std::string> arguments;
77 size_t startidx = expr.size();
78 for (size_t i = 0; i < expr.size(); ++i) {
79 if (startidx >= expr.size()) {
80 if (isalpha(expr[i])) {
81 startidx = i;
82 // check this character is not part of scientific notation, e.g. 2e-5
84 // if it is, we ignore this character
85 startidx = expr.size();
86 }
87 }
88 } else {
89 if (!isdigit(expr[i]) && !isalpha(expr[i]) && expr[i] != '_') {
90 if (expr[i] == '(') {
91 startidx = expr.size();
92 continue;
93 }
94 std::string arg(expr.substr(startidx, i - startidx));
95 startidx = expr.size();
96 arguments.insert(arg);
97 }
98 }
99 }
100 if (startidx < expr.size()) {
101 arguments.insert(expr.substr(startidx));
102 }
103 return arguments;
104}
105
106template <class RooArg_t>
107class RooFormulaArgFactory : public RooFit::JSONIO::Importer {
108public:
109 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
110 {
111 std::string name(RooJSONFactoryWSTool::name(p));
112 if (!p.has_child("expression")) {
113 RooJSONFactoryWSTool::error("no expression given for '" + name + "'");
114 }
115 TString formula(p["expression"].val());
116 RooArgList dependents;
117 for (const auto &d : extractArguments(formula.Data())) {
118 dependents.add(*tool->request<RooAbsReal>(d, name));
119 }
120 tool->wsImport(RooArg_t{name.c_str(), formula, dependents});
121 return true;
122 }
123};
124
125class RooAddPdfFactory : public RooFit::JSONIO::Importer {
126public:
127 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
128 {
129 std::string name(RooJSONFactoryWSTool::name(p));
130 tool->wsEmplace<RooAddPdf>(name, tool->requestArgList<RooAbsPdf>(p, "summands"),
131 tool->requestArgList<RooAbsReal>(p, "coefficients"));
132 return true;
133 }
134};
135
136class RooBinWidthFunctionFactory : public RooFit::JSONIO::Importer {
137public:
138 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
139 {
140 std::string name(RooJSONFactoryWSTool::name(p));
141 RooHistFunc *hf = static_cast<RooHistFunc *>(tool->request<RooAbsReal>(p["histogram"].val(), name));
142 tool->wsEmplace<RooBinWidthFunction>(name, *hf, p["divideByBinWidth"].val_bool());
143 return true;
144 }
145};
146
147class RooBinSamplingPdfFactory : public RooFit::JSONIO::Importer {
148public:
149 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
150 {
151 std::string name(RooJSONFactoryWSTool::name(p));
152
153 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
154 RooRealVar *obs = tool->requestArg<RooRealVar>(p, "observable");
155
156 if (!pdf->dependsOn(*obs)) {
157 RooJSONFactoryWSTool::error(std::string("pdf '") + pdf->GetName() + "' does not depend on observable '" +
158 obs->GetName() + "' as indicated by parent RooBinSamplingPdf '" + name +
159 "', please check!");
160 }
161
162 if (!p.has_child("epsilon")) {
163 RooJSONFactoryWSTool::error("no epsilon given in '" + name + "'");
164 }
165 double epsilon(p["epsilon"].val_double());
166
167 tool->wsEmplace<RooBinSamplingPdf>(name, *obs, *pdf, epsilon);
168
169 return true;
170 }
171};
172
173class RooRealSumPdfFactory : public RooFit::JSONIO::Importer {
174public:
175 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
176 {
177 std::string name(RooJSONFactoryWSTool::name(p));
178
179 bool extended = false;
180 if (p.has_child("extended") && p["extended"].val_bool()) {
181 extended = true;
182 }
183 tool->wsEmplace<RooRealSumPdf>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
184 tool->requestArgList<RooAbsReal>(p, "coefficients"), extended);
185 return true;
186 }
187};
188
189class RooRealSumFuncFactory : public RooFit::JSONIO::Importer {
190public:
191 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
192 {
193 std::string name(RooJSONFactoryWSTool::name(p));
194 tool->wsEmplace<RooRealSumFunc>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
195 tool->requestArgList<RooAbsReal>(p, "coefficients"));
196 return true;
197 }
198};
199template <class RooArg_t>
200class RooPolynomialFactory : public RooFit::JSONIO::Importer {
201public:
202 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
203 {
204 std::string name(RooJSONFactoryWSTool::name(p));
205 if (!p.has_child("coefficients")) {
206 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
207 }
208 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
209 RooArgList coefs;
210 int order = 0;
211 int lowestOrder = 0;
212 for (const auto &coef : p["coefficients"].children()) {
213 // As long as the coefficients match the default coefficients in
214 // RooFit, we don't have to instantiate RooFit objects but can
215 // increase the lowestOrder flag.
216 if (order == 0 && coef.val() == "1.0") {
217 ++lowestOrder;
218 } else if (coefs.empty() && coef.val() == "0.0") {
219 ++lowestOrder;
220 } else {
221 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
222 }
223 ++order;
224 }
225
226 tool->wsEmplace<RooArg_t>(name, *x, coefs, lowestOrder);
227 return true;
228 }
229};
230
231class RooPoissonFactory : public RooFit::JSONIO::Importer {
232public:
233 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
234 {
235 std::string name(RooJSONFactoryWSTool::name(p));
236 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
237 RooAbsReal *mean = tool->requestArg<RooAbsReal>(p, "mean");
238 tool->wsEmplace<RooPoisson>(name, *x, *mean, !p["integer"].val_bool());
239 return true;
240 }
241};
242
243class RooRealIntegralFactory : public RooFit::JSONIO::Importer {
244public:
245 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
246 {
247 std::string name(RooJSONFactoryWSTool::name(p));
248 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "integrand");
249 auto vars = tool->requestArgList<RooAbsReal>(p, "variables");
251 RooArgSet const *normSetPtr = nullptr;
252 if (p.has_child("normalization")) {
253 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
255 }
256 std::string domain;
257 bool hasDomain = p.has_child("domain");
258 if (hasDomain) {
259 domain = p["domain"].val();
260 }
261 // todo: at some point, take care of integrator configurations
262 tool->wsEmplace<RooRealIntegral>(name, *func, vars, normSetPtr, static_cast<RooNumIntConfig *>(nullptr),
263 hasDomain ? domain.c_str() : nullptr);
264 return true;
265 }
266};
267
268class RooLogNormalFactory : public RooFit::JSONIO::Importer {
269public:
270 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
271 {
272 std::string name(RooJSONFactoryWSTool::name(p));
273 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
274
275 // Same mechanism to undo the parameter transformation as in the
276 // RooExponentialFactory (see comments in that class for more info).
277 const std::string muName = p["mu"].val();
278 const std::string sigmaName = p["sigma"].val();
279 const bool isTransformed = endsWith(muName, "_lognormal_log");
280 const std::string suffixToRemove = isTransformed ? "_lognormal_log" : "";
283
284 tool->wsEmplace<RooLognormal>(name, *x, *mu, *sigma, !isTransformed);
285
286 return true;
287 }
288};
289
290class RooExponentialFactory : public RooFit::JSONIO::Importer {
291public:
292 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
293 {
294 std::string name(RooJSONFactoryWSTool::name(p));
295 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
296
297 // If the parameter name ends with the "_exponential_inverted" suffix,
298 // this means that it was exported from a RooFit object where the
299 // parameter first needed to be transformed on export to match the HS3
300 // specification. But when re-importing such a parameter, we can simply
301 // skip the transformation and use the original RooFit parameter without
302 // the suffix.
303 //
304 // A concrete example: take the following RooFit pdf in the factory language:
305 //
306 // "Exponential::exponential_1(x[0, 10], c[-0.1])"
307 //
308 // It defines en exponential exp(c * x). However, in HS3 the exponential
309 // is defined as exp(-c * x), to RooFit would export these dictionaries
310 // to the JSON:
311 //
312 // {
313 // "name": "exponential_1", // HS3 exponential_dist with transformed parameter
314 // "type": "exponential_dist",
315 // "x": "x",
316 // "c": "c_exponential_inverted"
317 // },
318 // {
319 // "name": "c_exponential_inverted", // transformation function created on-the-fly on export
320 // "type": "generic_function",
321 // "expression": "-c"
322 // }
323 //
324 // On import, we can directly take the non-transformed parameter, which is
325 // we check for the suffix and optionally remove it from the requested
326 // name next:
327
328 const std::string constParamName = p["c"].val();
329 const bool isInverted = endsWith(constParamName, "_exponential_inverted");
330 const std::string suffixToRemove = isInverted ? "_exponential_inverted" : "";
332
333 tool->wsEmplace<RooExponential>(name, *x, *c, !isInverted);
334
335 return true;
336 }
337};
338
339class RooLegacyExpPolyFactory : public RooFit::JSONIO::Importer {
340public:
341 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
342 {
343 std::string name(RooJSONFactoryWSTool::name(p));
344 if (!p.has_child("coefficients")) {
345 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
346 }
347 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
348 RooArgList coefs;
349 int order = 0;
350 int lowestOrder = 0;
351 for (const auto &coef : p["coefficients"].children()) {
352 // As long as the coefficients match the default coefficients in
353 // RooFit, we don't have to instantiate RooFit objects but can
354 // increase the lowestOrder flag.
355 if (order == 0 && coef.val() == "1.0") {
356 ++lowestOrder;
357 } else if (coefs.empty() && coef.val() == "0.0") {
358 ++lowestOrder;
359 } else {
360 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
361 }
362 ++order;
363 }
364
365 tool->wsEmplace<RooLegacyExpPoly>(name, *x, coefs, lowestOrder);
366 return true;
367 }
368};
369
370class RooMultiVarGaussianFactory : public RooFit::JSONIO::Importer {
371public:
372 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
373 {
374 std::string name(RooJSONFactoryWSTool::name(p));
375 bool has_cov = p.has_child("covariances");
376 bool has_corr = p.has_child("correlations") && p.has_child("standard_deviations");
377 if (!has_cov && !has_corr) {
378 RooJSONFactoryWSTool::error("no covariances or correlations+standard_deviations given in '" + name + "'");
379 }
380
382
383 if (has_cov) {
384 int n = p["covariances"].num_children();
385 int i = 0;
386 covmat.ResizeTo(n, n);
387 for (const auto &row : p["covariances"].children()) {
388 int j = 0;
389 for (const auto &val : row.children()) {
390 covmat(i, j) = val.val_double();
391 ++j;
392 }
393 ++i;
394 }
395 } else {
396 std::vector<double> variances;
397 for (const auto &v : p["standard_deviations"].children()) {
398 variances.push_back(v.val_double());
399 }
400 covmat.ResizeTo(variances.size(), variances.size());
401 int i = 0;
402 for (const auto &row : p["correlations"].children()) {
403 int j = 0;
404 for (const auto &val : row.children()) {
405 covmat(i, j) = val.val_double() * variances[i] * variances[j];
406 ++j;
407 }
408 ++i;
409 }
410 }
411 tool->wsEmplace<RooMultiVarGaussian>(name, tool->requestArgList<RooAbsReal>(p, "x"),
412 tool->requestArgList<RooAbsReal>(p, "mean"), covmat);
413 return true;
414 }
415};
416
417///////////////////////////////////////////////////////////////////////////////////////////////////////
418// specialized exporter implementations
419///////////////////////////////////////////////////////////////////////////////////////////////////////
420
421class RooAddPdfStreamer : public RooFit::JSONIO::Exporter {
422public:
423 std::string const &key() const override;
424 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
425 {
426 const RooAddPdf *pdf = static_cast<const RooAddPdf *>(func);
427 elem["type"] << key();
428 RooJSONFactoryWSTool::fillSeq(elem["summands"], pdf->pdfList());
429 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
430 elem["extended"] << (pdf->extendMode() != RooAbsPdf::CanNotBeExtended);
431 return true;
432 }
433};
434
435class RooRealSumPdfStreamer : public RooFit::JSONIO::Exporter {
436public:
437 std::string const &key() const override;
438 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
439 {
440 const RooRealSumPdf *pdf = static_cast<const RooRealSumPdf *>(func);
441 elem["type"] << key();
442 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
443 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
444 elem["extended"] << (pdf->extendMode() != RooAbsPdf::CanNotBeExtended);
445 return true;
446 }
447};
448
449class RooRealSumFuncStreamer : public RooFit::JSONIO::Exporter {
450public:
451 std::string const &key() const override;
452 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
453 {
454 const RooRealSumFunc *pdf = static_cast<const RooRealSumFunc *>(func);
455 elem["type"] << key();
456 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
457 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
458 return true;
459 }
460};
461
462class RooHistFuncStreamer : public RooFit::JSONIO::Exporter {
463public:
464 std::string const &key() const override;
465 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
466 {
467 const RooHistFunc *hf = static_cast<const RooHistFunc *>(func);
468 elem["type"] << key();
469 RooDataHist const &dh = hf->dataHist();
470 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
471 return true;
472 }
473};
474
475class RooHistFuncFactory : public RooFit::JSONIO::Importer {
476public:
477 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
478 {
479 std::string name(RooJSONFactoryWSTool::name(p));
480 if (!p.has_child("data")) {
481 RooJSONFactoryWSTool::error("function '" + name + "' is of histogram type, but does not define a 'data' key");
482 }
483 std::unique_ptr<RooDataHist> dataHist =
485 tool->wsEmplace<RooHistFunc>(name, *dataHist->get(), *dataHist);
486 return true;
487 }
488};
489
490class RooHistPdfStreamer : public RooFit::JSONIO::Exporter {
491public:
492 std::string const &key() const override;
493 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
494 {
495 const RooHistPdf *hf = static_cast<const RooHistPdf *>(func);
496 elem["type"] << key();
497 RooDataHist const &dh = hf->dataHist();
498 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
499 return true;
500 }
501};
502
503class RooHistPdfFactory : public RooFit::JSONIO::Importer {
504public:
505 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
506 {
507 std::string name(RooJSONFactoryWSTool::name(p));
508 if (!p.has_child("data")) {
509 RooJSONFactoryWSTool::error("function '" + name + "' is of histogram type, but does not define a 'data' key");
510 }
511 std::unique_ptr<RooDataHist> dataHist =
513 tool->wsEmplace<RooHistPdf>(name, *dataHist->get(), *dataHist);
514 return true;
515 }
516};
517
518class RooBinSamplingPdfStreamer : public RooFit::JSONIO::Exporter {
519public:
520 std::string const &key() const override;
521 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
522 {
523 const RooBinSamplingPdf *pdf = static_cast<const RooBinSamplingPdf *>(func);
524 elem["type"] << key();
525 elem["pdf"] << pdf->pdf().GetName();
526 elem["observable"] << pdf->observable().GetName();
527 elem["epsilon"] << pdf->epsilon();
528 return true;
529 }
530};
531
532class RooBinWidthFunctionStreamer : public RooFit::JSONIO::Exporter {
533public:
534 std::string const &key() const override;
535 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
536 {
537 const RooBinWidthFunction *pdf = static_cast<const RooBinWidthFunction *>(func);
538 elem["type"] << key();
539 elem["histogram"] << pdf->histFunc().GetName();
540 elem["divideByBinWidth"] << pdf->divideByBinWidth();
541 return true;
542 }
543};
544
545template <class RooArg_t>
546class RooFormulaArgStreamer : public RooFit::JSONIO::Exporter {
547public:
548 std::string const &key() const override;
549 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
550 {
551 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
552 elem["type"] << key();
553 TString expression(pdf->expression());
554 // If the tokens follow the "x[#]" convention, the square braces enclosing each number
555 // ensures that there is a unique mapping between the token and parameter name
556 // If the tokens follow the "@#" convention, the numbers are not enclosed by braces.
557 // So there may be tokens with numbers whose lower place value forms a subset string of ones with a higher place
558 // value, e.g. "@1" is a subset of "@10". So the names of these parameters must be applied descending from the
559 // highest place value in order to ensure each parameter name is uniquely applied to its token.
560 for (size_t idx = pdf->nParameters(); idx--;) {
561 const RooAbsArg *par = pdf->getParameter(idx);
562 expression.ReplaceAll(("x[" + std::to_string(idx) + "]").c_str(), par->GetName());
563 expression.ReplaceAll(("@" + std::to_string(idx)).c_str(), par->GetName());
564 }
565 elem["expression"] << expression.Data();
566 return true;
567 }
568};
569template <class RooArg_t>
570class RooPolynomialStreamer : public RooFit::JSONIO::Exporter {
571public:
572 std::string const &key() const override;
573 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
574 {
575 auto *pdf = static_cast<const RooArg_t *>(func);
576 elem["type"] << key();
577 elem["x"] << pdf->x().GetName();
578 auto &coefs = elem["coefficients"].set_seq();
579 // Write out the default coefficient that RooFit uses for the lower
580 // orders before the order of the first coefficient. Like this, the
581 // output is more self-documenting.
582 for (int i = 0; i < pdf->lowestOrder(); ++i) {
583 coefs.append_child() << (i == 0 ? "1.0" : "0.0");
584 }
585 for (const auto &coef : pdf->coefList()) {
586 coefs.append_child() << coef->GetName();
587 }
588 return true;
589 }
590};
591
592class RooLegacyExpPolyStreamer : public RooFit::JSONIO::Exporter {
593public:
594 std::string const &key() const override;
595 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
596 {
597 auto *pdf = static_cast<const RooLegacyExpPoly *>(func);
598 elem["type"] << key();
599 elem["x"] << pdf->x().GetName();
600 auto &coefs = elem["coefficients"].set_seq();
601 // Write out the default coefficient that RooFit uses for the lower
602 // orders before the order of the first coefficient. Like this, the
603 // output is more self-documenting.
604 for (int i = 0; i < pdf->lowestOrder(); ++i) {
605 coefs.append_child() << (i == 0 ? "1.0" : "0.0");
606 }
607 for (const auto &coef : pdf->coefList()) {
608 coefs.append_child() << coef->GetName();
609 }
610 return true;
611 }
612};
613
614class RooPoissonStreamer : public RooFit::JSONIO::Exporter {
615public:
616 std::string const &key() const override;
617 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
618 {
619 auto *pdf = static_cast<const RooPoisson *>(func);
620 elem["type"] << key();
621 elem["x"] << pdf->getX().GetName();
622 elem["mean"] << pdf->getMean().GetName();
623 elem["integer"] << !pdf->getNoRounding();
624 return true;
625 }
626};
627
628class RooLogNormalStreamer : public RooFit::JSONIO::Exporter {
629public:
630 std::string const &key() const override;
631 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
632 {
633 auto *pdf = static_cast<const RooLognormal *>(func);
634
635 elem["type"] << key();
636 elem["x"] << pdf->getX().GetName();
637
638 auto &m0 = pdf->getMedian();
639 auto &k = pdf->getShapeK();
640
641 if (pdf->useStandardParametrization()) {
642 elem["mu"] << m0.GetName();
643 elem["sigma"] << k.GetName();
644 } else {
645 elem["mu"] << tool->exportTransformed(&m0, "_lognormal_log", "log(%s)");
646 elem["sigma"] << tool->exportTransformed(&k, "_lognormal_log", "log(%s)");
647 }
648
649 return true;
650 }
651};
652
653class RooExponentialStreamer : public RooFit::JSONIO::Exporter {
654public:
655 std::string const &key() const override;
656 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
657 {
658 auto *pdf = static_cast<const RooExponential *>(func);
659 elem["type"] << key();
660 elem["x"] << pdf->variable().GetName();
661 auto &c = pdf->coefficient();
662 if (pdf->negateCoefficient()) {
663 elem["c"] << c.GetName();
664 } else {
665 elem["c"] << tool->exportTransformed(&c, "_exponential_inverted", "-%s");
666 }
667
668 return true;
669 }
670};
671
672class RooMultiVarGaussianStreamer : public RooFit::JSONIO::Exporter {
673public:
674 std::string const &key() const override;
675 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
676 {
677 auto *pdf = static_cast<const RooMultiVarGaussian *>(func);
678 elem["type"] << key();
679 RooJSONFactoryWSTool::fillSeq(elem["x"], pdf->xVec());
680 RooJSONFactoryWSTool::fillSeq(elem["mean"], pdf->muVec());
681 elem["covariances"].fill_mat(pdf->covarianceMatrix());
682 return true;
683 }
684};
685
686class RooTFnBindingStreamer : public RooFit::JSONIO::Exporter {
687public:
688 std::string const &key() const override;
689 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
690 {
691 auto *pdf = static_cast<const RooTFnBinding *>(func);
692 elem["type"] << key();
693
694 TString formula(pdf->function().GetExpFormula());
695 formula.ReplaceAll("x", pdf->observables()[0].GetName());
696 formula.ReplaceAll("y", pdf->observables()[1].GetName());
697 formula.ReplaceAll("z", pdf->observables()[2].GetName());
698 for (size_t i = 0; i < pdf->parameters().size(); ++i) {
699 TString pname(TString::Format("[%d]", (int)i));
700 formula.ReplaceAll(pname, pdf->parameters()[i].GetName());
701 }
702 elem["expression"] << formula.Data();
703 return true;
704 }
705};
706
707class RooRealIntegralStreamer : public RooFit::JSONIO::Exporter {
708public:
709 std::string const &key() const override;
710 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
711 {
712 auto *integral = static_cast<const RooRealIntegral *>(func);
713 std::string name = elem["name"].val();
714 for (char& c : name ) {
715 if (c == '[' || c == '|' || c==',') {
716 c = '_';
717 }
718 }
719 name.erase(std::remove(name.begin(), name.end(), ']'), name.end());
720 elem["name"] << name;
721 elem["type"] << key();
722 elem["integrand"] << integral->integrand().GetName();
723 if (integral->intRange()) {
724 elem["domain"] << integral->intRange();
725 }
726 RooJSONFactoryWSTool::fillSeq(elem["variables"], integral->intVars());
727 if (RooArgSet const *funcNormSet = integral->funcNormSet()) {
728 RooJSONFactoryWSTool::fillSeq(elem["normalization"], *funcNormSet);
729 }
730 return true;
731 }
732};
733
734#define DEFINE_EXPORTER_KEY(class_name, name) \
735 std::string const &class_name::key() const \
736 { \
737 const static std::string keystring = name; \
738 return keystring; \
739 }
740
741DEFINE_EXPORTER_KEY(RooAddPdfStreamer, "mixture_dist");
742DEFINE_EXPORTER_KEY(RooBinSamplingPdfStreamer, "binsampling");
743DEFINE_EXPORTER_KEY(RooBinWidthFunctionStreamer, "binwidth");
744DEFINE_EXPORTER_KEY(RooLegacyExpPolyStreamer, "legacy_exp_poly_dist");
745DEFINE_EXPORTER_KEY(RooExponentialStreamer, "exponential_dist");
746template <>
748template <>
750DEFINE_EXPORTER_KEY(RooHistFuncStreamer, "histogram");
751DEFINE_EXPORTER_KEY(RooHistPdfStreamer, "histogram_dist");
752DEFINE_EXPORTER_KEY(RooLogNormalStreamer, "lognormal_dist");
753DEFINE_EXPORTER_KEY(RooMultiVarGaussianStreamer, "multivariate_normal_dist");
754DEFINE_EXPORTER_KEY(RooPoissonStreamer, "poisson_dist");
755template <>
757template <>
759DEFINE_EXPORTER_KEY(RooRealSumFuncStreamer, "weighted_sum");
760DEFINE_EXPORTER_KEY(RooRealSumPdfStreamer, "weighted_sum_dist");
761DEFINE_EXPORTER_KEY(RooTFnBindingStreamer, "generic_function");
762DEFINE_EXPORTER_KEY(RooRealIntegralStreamer, "integral");
763
764///////////////////////////////////////////////////////////////////////////////////////////////////////
765// instantiate all importers and exporters
766///////////////////////////////////////////////////////////////////////////////////////////////////////
767
768STATIC_EXECUTE([]() {
769 using namespace RooFit::JSONIO;
770
771 registerImporter<RooAddPdfFactory>("mixture_dist", false);
772 registerImporter<RooBinSamplingPdfFactory>("binsampling_dist", false);
774 registerImporter<RooLegacyExpPolyFactory>("legacy_exp_poly_dist", false);
775 registerImporter<RooExponentialFactory>("exponential_dist", false);
778 registerImporter<RooHistFuncFactory>("histogram", false);
779 registerImporter<RooHistPdfFactory>("histogram_dist", false);
780 registerImporter<RooLogNormalFactory>("lognormal_dist", false);
781 registerImporter<RooMultiVarGaussianFactory>("multivariate_normal_dist", false);
782 registerImporter<RooPoissonFactory>("poisson_dist", false);
785 registerImporter<RooRealSumPdfFactory>("weighted_sum_dist", false);
786 registerImporter<RooRealSumFuncFactory>("weighted_sum", false);
788
807});
808
809} // 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 c(i)
Definition RSha256.hxx:101
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
char name[80]
Definition TGX11.cxx:110
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.
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
Efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:33
const RooArgList & coefList() const
Definition RooAddPdf.h:74
ExtendMode extendMode() const override
Returns ability of PDF to provide extended likelihood terms.
Definition RooAddPdf.h:60
static TClass * Class()
const RooArgList & pdfList() const
Definition RooAddPdf.h:70
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()
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
Exponential PDF.
static TClass * Class()
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 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 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()
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
Use TF1, TF2, TF3 functions as RooFit objects.
static TClass * Class()
static Bool_t IsScientificNotation(const TString &formula, int ipos)
Definition TFormula.cxx:329
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
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:2384
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)