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