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