Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
JSONFactories_RooFitCore.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Carsten D. Burgard, DESY/ATLAS, Dec 2021
5 *
6 * Copyright (c) 2022, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
14
15#include <RooAbsCachedPdf.h>
16#include <RooAddPdf.h>
17#include <RooAddModel.h>
18#include <RooBinSamplingPdf.h>
19#include <RooBinWidthFunction.h>
20#include <RooCategory.h>
21#include <RooDataHist.h>
22#include <RooDecay.h>
23#include <RooDerivative.h>
24#include <RooExponential.h>
25#include <RooExtendPdf.h>
26#include <RooFFTConvPdf.h>
28#include <RooFitHS3/JSONIO.h>
29#include <RooFormulaVar.h>
30#include <RooGenericPdf.h>
31#include <RooHistFunc.h>
32#include <RooHistPdf.h>
33#include <RooLegacyExpPoly.h>
34#include <RooLognormal.h>
35#include <RooMultiVarGaussian.h>
36#include <RooPoisson.h>
37#include <RooPolynomial.h>
38#include <RooPolyVar.h>
39#include <RooRealSumFunc.h>
40#include <RooRealSumPdf.h>
41#include <RooRealVar.h>
42#include <RooResolutionModel.h>
43#include <RooTFnBinding.h>
44#include <RooTruthModel.h>
45#include <RooGaussModel.h>
46#include <RooWorkspace.h>
47#include <RooRealIntegral.h>
48
49#include <TF1.h>
50#include <TH1.h>
51
52#include "JSONIOUtils.h"
53
54#include "static_execute.h"
55
56#include <algorithm>
57#include <cctype>
58
60
61///////////////////////////////////////////////////////////////////////////////////////////////////////
62// individually implemented importers
63///////////////////////////////////////////////////////////////////////////////////////////////////////
64
65namespace {
66/**
67 * Extracts arguments from a mathematical expression.
68 *
69 * This function takes a string representing a mathematical
70 * expression and extracts the arguments from it. The arguments are
71 * defined as sequences of characters that do not contain digits,
72 * spaces, or parentheses, and that start with a letter. Function
73 * calls such as "exp( ... )", identified as being followed by an
74 * opening parenthesis, are not treated as arguments. The extracted
75 * arguments are returned as a vector of strings.
76 *
77 * @param expr A string representing a mathematical expression.
78 * @return A set of unique strings representing the extracted arguments.
79 */
80std::set<std::string> extractArguments(std::string expr)
81{
82 // Get rid of whitespaces
83 expr.erase(std::remove_if(expr.begin(), expr.end(), [](unsigned char c) { return std::isspace(c); }), expr.end());
84
85 std::set<std::string> arguments;
86 size_t startidx = expr.size();
87 for (size_t i = 0; i < expr.size(); ++i) {
88 if (startidx >= expr.size()) {
89 if (isalpha(expr[i])) {
90 startidx = i;
91 // check this character is not part of scientific notation, e.g. 2e-5
93 // if it is, we ignore this character
94 startidx = expr.size();
95 }
96 }
97 } else {
98 if (!isdigit(expr[i]) && !isalpha(expr[i]) && expr[i] != '_') {
99 if (expr[i] == '(') {
100 startidx = expr.size();
101 continue;
102 }
103 std::string arg(expr.substr(startidx, i - startidx));
104 startidx = expr.size();
105 arguments.insert(arg);
106 }
107 }
108 }
109 if (startidx < expr.size()) {
110 arguments.insert(expr.substr(startidx));
111 }
112 return arguments;
113}
114
115template <class RooArg_t>
116class RooFormulaArgFactory : public RooFit::JSONIO::Importer {
117public:
118 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
119 {
120 std::string name(RooJSONFactoryWSTool::name(p));
121 if (!p.has_child("expression")) {
122 RooJSONFactoryWSTool::error("no expression given for '" + name + "'");
123 }
124 TString formula(p["expression"].val());
125 RooArgList dependents;
126 for (const auto &d : extractArguments(formula.Data())) {
127 dependents.add(*tool->request<RooAbsReal>(d, name));
128 }
129 tool->wsImport(RooArg_t{name.c_str(), formula, dependents});
130 return true;
131 }
132};
133
134class RooAddPdfFactory : public RooFit::JSONIO::Importer {
135public:
136 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
137 {
138 std::string name(RooJSONFactoryWSTool::name(p));
139 if (!tool->requestArgList<RooAbsReal>(p, "coefficients").empty()) {
140 tool->wsEmplace<RooAddPdf>(name, tool->requestArgList<RooAbsPdf>(p, "summands"),
141 tool->requestArgList<RooAbsReal>(p, "coefficients"));
142 return true;
143 }
144 tool->wsEmplace<RooAddPdf>(name, tool->requestArgList<RooAbsPdf>(p, "summands"));
145 return true;
146 }
147};
148
149class RooAddModelFactory : public RooFit::JSONIO::Importer {
150public:
151 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
152 {
153 std::string name(RooJSONFactoryWSTool::name(p));
154 tool->wsEmplace<RooAddModel>(name, tool->requestArgList<RooAbsPdf>(p, "summands"),
155 tool->requestArgList<RooAbsReal>(p, "coefficients"));
156 return true;
157 }
158};
159
160class RooBinWidthFunctionFactory : public RooFit::JSONIO::Importer {
161public:
162 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
163 {
164 std::string name(RooJSONFactoryWSTool::name(p));
165 RooHistFunc *hf = static_cast<RooHistFunc *>(tool->request<RooAbsReal>(p["histogram"].val(), name));
166 tool->wsEmplace<RooBinWidthFunction>(name, *hf, p["divideByBinWidth"].val_bool());
167 return true;
168 }
169};
170
171class RooBinSamplingPdfFactory : public RooFit::JSONIO::Importer {
172public:
173 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
174 {
175 std::string name(RooJSONFactoryWSTool::name(p));
176
177 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
178 RooRealVar *obs = tool->requestArg<RooRealVar>(p, "observable");
179
180 if (!pdf->dependsOn(*obs)) {
181 RooJSONFactoryWSTool::error(std::string("pdf '") + pdf->GetName() + "' does not depend on observable '" +
182 obs->GetName() + "' as indicated by parent RooBinSamplingPdf '" + name +
183 "', please check!");
184 }
185
186 if (!p.has_child("epsilon")) {
187 RooJSONFactoryWSTool::error("no epsilon given in '" + name + "'");
188 }
189 double epsilon(p["epsilon"].val_double());
190
191 tool->wsEmplace<RooBinSamplingPdf>(name, *obs, *pdf, epsilon);
192
193 return true;
194 }
195};
196
197class RooRealSumPdfFactory : public RooFit::JSONIO::Importer {
198public:
199 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
200 {
201 std::string name(RooJSONFactoryWSTool::name(p));
202
203 bool extended = false;
204 if (p.has_child("extended") && p["extended"].val_bool()) {
205 extended = true;
206 }
207 tool->wsEmplace<RooRealSumPdf>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
208 tool->requestArgList<RooAbsReal>(p, "coefficients"), extended);
209 return true;
210 }
211};
212
213class RooRealSumFuncFactory : public RooFit::JSONIO::Importer {
214public:
215 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
216 {
217 std::string name(RooJSONFactoryWSTool::name(p));
218 tool->wsEmplace<RooRealSumFunc>(name, tool->requestArgList<RooAbsReal>(p, "samples"),
219 tool->requestArgList<RooAbsReal>(p, "coefficients"));
220 return true;
221 }
222};
223template <class RooArg_t>
224class RooPolynomialFactory : public RooFit::JSONIO::Importer {
225public:
226 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
227 {
228 std::string name(RooJSONFactoryWSTool::name(p));
229 if (!p.has_child("coefficients")) {
230 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
231 }
232 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
233 RooArgList coefs;
234 int order = 0;
235 int lowestOrder = 0;
236 for (const auto &coef : p["coefficients"].children()) {
237 // As long as the coefficients match the default coefficients in
238 // RooFit, we don't have to instantiate RooFit objects but can
239 // increase the lowestOrder flag.
240 if (order == 0 && coef.val() == "1.0") {
241 ++lowestOrder;
242 } else if (coefs.empty() && coef.val() == "0.0") {
243 ++lowestOrder;
244 } else {
245 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
246 }
247 ++order;
248 }
249
250 tool->wsEmplace<RooArg_t>(name, *x, coefs, lowestOrder);
251 return true;
252 }
253};
254
255class RooPoissonFactory : public RooFit::JSONIO::Importer {
256public:
257 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
258 {
259 std::string name(RooJSONFactoryWSTool::name(p));
260 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
261 RooAbsReal *mean = tool->requestArg<RooAbsReal>(p, "mean");
262 tool->wsEmplace<RooPoisson>(name, *x, *mean, !p["integer"].val_bool());
263 return true;
264 }
265};
266
267class RooDecayFactory : public RooFit::JSONIO::Importer {
268public:
269 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
270 {
271 std::string name(RooJSONFactoryWSTool::name(p));
272 RooRealVar *t = tool->requestArg<RooRealVar>(p, "t");
273 RooAbsReal *tau = tool->requestArg<RooAbsReal>(p, "tau");
274 RooResolutionModel *model = dynamic_cast<RooResolutionModel *>(tool->requestArg<RooAbsPdf>(p, "resolutionModel"));
275 RooDecay::DecayType decayType = static_cast<RooDecay::DecayType>(p["decayType"].val_int());
276 tool->wsEmplace<RooDecay>(name, *t, *tau, *model, decayType);
277 return true;
278 }
279};
280
281class RooTruthModelFactory : public RooFit::JSONIO::Importer {
282public:
283 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
284 {
285 std::string name(RooJSONFactoryWSTool::name(p));
286 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
287 tool->wsEmplace<RooTruthModel>(name, *x);
288 return true;
289 }
290};
291
292class RooGaussModelFactory : public RooFit::JSONIO::Importer {
293public:
294 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
295 {
296 std::string name(RooJSONFactoryWSTool::name(p));
297 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
298 RooRealVar *mean = tool->requestArg<RooRealVar>(p, "mean");
299 RooRealVar *sigma = tool->requestArg<RooRealVar>(p, "sigma");
300 tool->wsEmplace<RooGaussModel>(name, *x, *mean, *sigma);
301 return true;
302 }
303};
304
305class RooRealIntegralFactory : public RooFit::JSONIO::Importer {
306public:
307 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
308 {
309 std::string name(RooJSONFactoryWSTool::name(p));
310 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "integrand");
311 auto vars = tool->requestArgList<RooAbsReal>(p, "variables");
313 RooArgSet const *normSetPtr = nullptr;
314 if (p.has_child("normalization")) {
315 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
317 }
318 std::string domain;
319 bool hasDomain = p.has_child("domain");
320 if (hasDomain) {
321 domain = p["domain"].val();
322 }
323 // todo: at some point, take care of integrator configurations
324 tool->wsEmplace<RooRealIntegral>(name, *func, vars, normSetPtr, static_cast<RooNumIntConfig *>(nullptr),
325 hasDomain ? domain.c_str() : nullptr);
326 return true;
327 }
328};
329
330class RooDerivativeFactory : public RooFit::JSONIO::Importer {
331public:
332 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
333 {
334 std::string name(RooJSONFactoryWSTool::name(p));
335 RooAbsReal *func = tool->requestArg<RooAbsReal>(p, "function");
336 RooRealVar *x = tool->requestArg<RooRealVar>(p, "x");
337 Int_t order = p["order"].val_int();
338 double eps = p["eps"].val_double();
339 if (p.has_child("normalization")) {
341 normSet.add(tool->requestArgSet<RooAbsReal>(p, "normalization"));
342 tool->wsEmplace<RooDerivative>(name, *func, *x, normSet, order, eps);
343 return true;
344 }
345 tool->wsEmplace<RooDerivative>(name, *func, *x, order, eps);
346 return true;
347 }
348};
349
350class RooFFTConvPdfFactory : public RooFit::JSONIO::Importer {
351public:
352 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
353 {
354 std::string name(RooJSONFactoryWSTool::name(p));
355 RooRealVar *convVar = tool->requestArg<RooRealVar>(p, "conv_var");
356 Int_t order = p["ipOrder"].val_int();
357 RooAbsPdf *pdf1 = tool->requestArg<RooAbsPdf>(p, "pdf1");
358 RooAbsPdf *pdf2 = tool->requestArg<RooAbsPdf>(p, "pdf2");
359 if (p.has_child("conv_func")) {
360 RooAbsReal *convFunc = tool->requestArg<RooAbsReal>(p, "conv_func");
361 tool->wsEmplace<RooFFTConvPdf>(name, *convFunc, *convVar, *pdf1, *pdf2, order);
362 return true;
363 }
364 tool->wsEmplace<RooFFTConvPdf>(name, *convVar, *pdf1, *pdf2, order);
365 return true;
366 }
367};
368
369class RooExtendPdfFactory : public RooFit::JSONIO::Importer {
370public:
371 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
372 {
373 std::string name(RooJSONFactoryWSTool::name(p));
374 RooAbsPdf *pdf = tool->requestArg<RooAbsPdf>(p, "pdf");
375 RooAbsReal *norm = tool->requestArg<RooAbsReal>(p, "norm");
376 if (p.has_child("range")) {
377 std::string rangeName = p["range"].val();
378 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm, rangeName.c_str());
379 return true;
380 }
381 tool->wsEmplace<RooExtendPdf>(name, *pdf, *norm);
382 return true;
383 }
384};
385
386class RooLogNormalFactory : public RooFit::JSONIO::Importer {
387public:
388 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
389 {
390 std::string name(RooJSONFactoryWSTool::name(p));
391 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
392
393 // Same mechanism to undo the parameter transformation as in the
394 // RooExponentialFactory (see comments in that class for more info).
395 const std::string muName = p["mu"].val();
396 const std::string sigmaName = p["sigma"].val();
397 const bool isTransformed = endsWith(muName, "_lognormal_log");
398 const std::string suffixToRemove = isTransformed ? "_lognormal_log" : "";
401
402 tool->wsEmplace<RooLognormal>(name, *x, *mu, *sigma, !isTransformed);
403
404 return true;
405 }
406};
407
408class RooExponentialFactory : public RooFit::JSONIO::Importer {
409public:
410 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
411 {
412 std::string name(RooJSONFactoryWSTool::name(p));
413 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
414
415 // If the parameter name ends with the "_exponential_inverted" suffix,
416 // this means that it was exported from a RooFit object where the
417 // parameter first needed to be transformed on export to match the HS3
418 // specification. But when re-importing such a parameter, we can simply
419 // skip the transformation and use the original RooFit parameter without
420 // the suffix.
421 //
422 // A concrete example: take the following RooFit pdf in the factory language:
423 //
424 // "Exponential::exponential_1(x[0, 10], c[-0.1])"
425 //
426 // It defines en exponential exp(c * x). However, in HS3 the exponential
427 // is defined as exp(-c * x), to RooFit would export these dictionaries
428 // to the JSON:
429 //
430 // {
431 // "name": "exponential_1", // HS3 exponential_dist with transformed parameter
432 // "type": "exponential_dist",
433 // "x": "x",
434 // "c": "c_exponential_inverted"
435 // },
436 // {
437 // "name": "c_exponential_inverted", // transformation function created on-the-fly on export
438 // "type": "generic_function",
439 // "expression": "-c"
440 // }
441 //
442 // On import, we can directly take the non-transformed parameter, which is
443 // we check for the suffix and optionally remove it from the requested
444 // name next:
445
446 const std::string constParamName = p["c"].val();
447 const bool isInverted = endsWith(constParamName, "_exponential_inverted");
448 const std::string suffixToRemove = isInverted ? "_exponential_inverted" : "";
450
451 tool->wsEmplace<RooExponential>(name, *x, *c, !isInverted);
452
453 return true;
454 }
455};
456
457class RooLegacyExpPolyFactory : public RooFit::JSONIO::Importer {
458public:
459 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
460 {
461 std::string name(RooJSONFactoryWSTool::name(p));
462 if (!p.has_child("coefficients")) {
463 RooJSONFactoryWSTool::error("no coefficients given in '" + name + "'");
464 }
465 RooAbsReal *x = tool->requestArg<RooAbsReal>(p, "x");
466 RooArgList coefs;
467 int order = 0;
468 int lowestOrder = 0;
469 for (const auto &coef : p["coefficients"].children()) {
470 // As long as the coefficients match the default coefficients in
471 // RooFit, we don't have to instantiate RooFit objects but can
472 // increase the lowestOrder flag.
473 if (order == 0 && coef.val() == "1.0") {
474 ++lowestOrder;
475 } else if (coefs.empty() && coef.val() == "0.0") {
476 ++lowestOrder;
477 } else {
478 coefs.add(*tool->request<RooAbsReal>(coef.val(), name));
479 }
480 ++order;
481 }
482
483 tool->wsEmplace<RooLegacyExpPoly>(name, *x, coefs, lowestOrder);
484 return true;
485 }
486};
487
488class RooMultiVarGaussianFactory : public RooFit::JSONIO::Importer {
489public:
490 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
491 {
492 std::string name(RooJSONFactoryWSTool::name(p));
493 bool has_cov = p.has_child("covariances");
494 bool has_corr = p.has_child("correlations") && p.has_child("standard_deviations");
495 if (!has_cov && !has_corr) {
496 RooJSONFactoryWSTool::error("no covariances or correlations+standard_deviations given in '" + name + "'");
497 }
498
500
501 if (has_cov) {
502 int n = p["covariances"].num_children();
503 int i = 0;
504 covmat.ResizeTo(n, n);
505 for (const auto &row : p["covariances"].children()) {
506 int j = 0;
507 for (const auto &val : row.children()) {
508 covmat(i, j) = val.val_double();
509 ++j;
510 }
511 ++i;
512 }
513 } else {
514 std::vector<double> variances;
515 for (const auto &v : p["standard_deviations"].children()) {
516 variances.push_back(v.val_double());
517 }
518 covmat.ResizeTo(variances.size(), variances.size());
519 int i = 0;
520 for (const auto &row : p["correlations"].children()) {
521 int j = 0;
522 for (const auto &val : row.children()) {
523 covmat(i, j) = val.val_double() * variances[i] * variances[j];
524 ++j;
525 }
526 ++i;
527 }
528 }
529 tool->wsEmplace<RooMultiVarGaussian>(name, tool->requestArgList<RooAbsReal>(p, "x"),
530 tool->requestArgList<RooAbsReal>(p, "mean"), covmat);
531 return true;
532 }
533};
534
535///////////////////////////////////////////////////////////////////////////////////////////////////////
536// specialized exporter implementations
537///////////////////////////////////////////////////////////////////////////////////////////////////////
538template <class RooArg_t>
539class RooAddPdfStreamer : public RooFit::JSONIO::Exporter {
540public:
541 std::string const &key() const override;
542 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
543 {
544 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
545 elem["type"] << key();
546 std::string name = elem["name"].val();
547 /*elem["name"] << RooJSONFactoryWSTool::sanitizeName(name);
548 RooJSONFactoryWSTool::fillSeqSanitizedName(elem["summands"], pdf->pdfList());
549 RooJSONFactoryWSTool::fillSeqSanitizedName(elem["coefficients"], pdf->coefList());
550 */
551 elem["name"] << name;
552 RooJSONFactoryWSTool::fillSeq(elem["summands"], pdf->pdfList());
553 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
554 elem["extended"] << (pdf->extendMode() != RooArg_t::CanNotBeExtended);
555 return true;
556 }
557};
558
559class RooRealSumPdfStreamer : public RooFit::JSONIO::Exporter {
560public:
561 std::string const &key() const override;
562 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
563 {
564 const RooRealSumPdf *pdf = static_cast<const RooRealSumPdf *>(func);
565 elem["type"] << key();
566 std::string name = elem["name"].val();
567 /*elem["name"] << RooJSONFactoryWSTool::sanitizeName(name);
568 RooJSONFactoryWSTool::fillSeqSanitizedName(elem["samples"], pdf->funcList());
569 RooJSONFactoryWSTool::fillSeqSanitizedName(elem["coefficients"], pdf->coefList());
570 */
571 elem["name"] << name;
572 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
573 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
574 elem["extended"] << (pdf->extendMode() != RooAbsPdf::CanNotBeExtended);
575 return true;
576 }
577};
578
579class RooRealSumFuncStreamer : public RooFit::JSONIO::Exporter {
580public:
581 std::string const &key() const override;
582 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
583 {
584 const RooRealSumFunc *pdf = static_cast<const RooRealSumFunc *>(func);
585 elem["type"] << key();
586 std::string name = elem["name"].val();
587 /*elem["name"] << RooJSONFactoryWSTool::sanitizeName(name);
588 RooJSONFactoryWSTool::fillSeqSanitizedName(elem["samples"], pdf->funcList());
589 RooJSONFactoryWSTool::fillSeqSanitizedName(elem["coefficients"], pdf->coefList());
590 */
591 elem["name"] << name;
592 RooJSONFactoryWSTool::fillSeq(elem["samples"], pdf->funcList());
593 RooJSONFactoryWSTool::fillSeq(elem["coefficients"], pdf->coefList());
594 return true;
595 }
596};
597
598class RooHistFuncStreamer : public RooFit::JSONIO::Exporter {
599public:
600 std::string const &key() const override;
601 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
602 {
603 const RooHistFunc *hf = static_cast<const RooHistFunc *>(func);
604 elem["type"] << key();
605 RooDataHist const &dh = hf->dataHist();
606 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
607 return true;
608 }
609};
610
611class RooHistFuncFactory : public RooFit::JSONIO::Importer {
612public:
613 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
614 {
615 std::string name(RooJSONFactoryWSTool::name(p));
616 if (!p.has_child("data")) {
617 RooJSONFactoryWSTool::error("function '" + name + "' is of histogram type, but does not define a 'data' key");
618 }
619 std::unique_ptr<RooDataHist> dataHist =
621 tool->wsEmplace<RooHistFunc>(name, *dataHist->get(), *dataHist);
622 return true;
623 }
624};
625
626class RooHistPdfStreamer : public RooFit::JSONIO::Exporter {
627public:
628 std::string const &key() const override;
629 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
630 {
631 const RooHistPdf *hf = static_cast<const RooHistPdf *>(func);
632 elem["type"] << key();
633 RooDataHist const &dh = hf->dataHist();
634 tool->exportHisto(*dh.get(), dh.numEntries(), dh.weightArray(), elem["data"].set_map());
635 return true;
636 }
637};
638
639class RooHistPdfFactory : public RooFit::JSONIO::Importer {
640public:
641 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
642 {
643 std::string name(RooJSONFactoryWSTool::name(p));
644 if (!p.has_child("data")) {
645 RooJSONFactoryWSTool::error("function '" + name + "' is of histogram type, but does not define a 'data' key");
646 }
647 std::unique_ptr<RooDataHist> dataHist =
649 tool->wsEmplace<RooHistPdf>(name, *dataHist->get(), *dataHist);
650 return true;
651 }
652};
653
654class RooBinSamplingPdfStreamer : public RooFit::JSONIO::Exporter {
655public:
656 std::string const &key() const override;
657 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
658 {
659 const RooBinSamplingPdf *pdf = static_cast<const RooBinSamplingPdf *>(func);
660 elem["type"] << key();
661 elem["pdf"] << pdf->pdf().GetName();
662 elem["observable"] << pdf->observable().GetName();
663 elem["epsilon"] << pdf->epsilon();
664 return true;
665 }
666};
667
668class RooBinWidthFunctionStreamer : public RooFit::JSONIO::Exporter {
669public:
670 std::string const &key() const override;
671 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
672 {
673 const RooBinWidthFunction *pdf = static_cast<const RooBinWidthFunction *>(func);
674 elem["type"] << key();
675 elem["histogram"] << pdf->histFunc().GetName();
676 elem["divideByBinWidth"] << pdf->divideByBinWidth();
677 return true;
678 }
679};
680
681template <class RooArg_t>
682class RooFormulaArgStreamer : public RooFit::JSONIO::Exporter {
683public:
684 std::string const &key() const override;
685 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
686 {
687 const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
688 elem["type"] << key();
689 TString expression(pdf->expression());
690 // If the tokens follow the "x[#]" convention, the square braces enclosing each number
691 // ensures that there is a unique mapping between the token and parameter name
692 // If the tokens follow the "@#" convention, the numbers are not enclosed by braces.
693 // So there may be tokens with numbers whose lower place value forms a subset string of ones with a higher place
694 // value, e.g. "@1" is a subset of "@10". So the names of these parameters must be applied descending from the
695 // highest place value in order to ensure each parameter name is uniquely applied to its token.
696 for (size_t idx = pdf->nParameters(); idx--;) {
697 const RooAbsArg *par = pdf->getParameter(idx);
698 expression.ReplaceAll(("x[" + std::to_string(idx) + "]").c_str(), par->GetName());
699 expression.ReplaceAll(("@" + std::to_string(idx)).c_str(), par->GetName());
700 }
701 elem["expression"] << expression.Data();
702 return true;
703 }
704};
705template <class RooArg_t>
706class RooPolynomialStreamer : 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 *pdf = static_cast<const RooArg_t *>(func);
712 elem["type"] << key();
713 elem["x"] << pdf->x().GetName();
714 auto &coefs = elem["coefficients"].set_seq();
715 // Write out the default coefficient that RooFit uses for the lower
716 // orders before the order of the first coefficient. Like this, the
717 // output is more self-documenting.
718 for (int i = 0; i < pdf->lowestOrder(); ++i) {
719 coefs.append_child() << (i == 0 ? "1.0" : "0.0");
720 }
721 for (const auto &coef : pdf->coefList()) {
722 coefs.append_child() << coef->GetName();
723 }
724 return true;
725 }
726};
727
728class RooLegacyExpPolyStreamer : public RooFit::JSONIO::Exporter {
729public:
730 std::string const &key() const override;
731 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
732 {
733 auto *pdf = static_cast<const RooLegacyExpPoly *>(func);
734 elem["type"] << key();
735 elem["x"] << pdf->x().GetName();
736 auto &coefs = elem["coefficients"].set_seq();
737 // Write out the default coefficient that RooFit uses for the lower
738 // orders before the order of the first coefficient. Like this, the
739 // output is more self-documenting.
740 for (int i = 0; i < pdf->lowestOrder(); ++i) {
741 coefs.append_child() << (i == 0 ? "1.0" : "0.0");
742 }
743 for (const auto &coef : pdf->coefList()) {
744 coefs.append_child() << coef->GetName();
745 }
746 return true;
747 }
748};
749
750class RooPoissonStreamer : public RooFit::JSONIO::Exporter {
751public:
752 std::string const &key() const override;
753 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
754 {
755 auto *pdf = static_cast<const RooPoisson *>(func);
756 elem["type"] << key();
757 elem["x"] << pdf->getX().GetName();
758 elem["mean"] << pdf->getMean().GetName();
759 elem["integer"] << !pdf->getNoRounding();
760 return true;
761 }
762};
763
764class RooDecayStreamer : public RooFit::JSONIO::Exporter {
765public:
766 std::string const &key() const override;
767 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
768 {
769 auto *pdf = static_cast<const RooDecay *>(func);
770 elem["type"] << key();
771 elem["t"] << pdf->getT().GetName();
772 elem["tau"] << pdf->getTau().GetName();
773 elem["resolutionModel"] << pdf->getModel().GetName();
774 elem["decayType"] << pdf->getDecayType();
775
776 return true;
777 }
778};
779
780class RooTruthModelStreamer : public RooFit::JSONIO::Exporter {
781public:
782 std::string const &key() const override;
783 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
784 {
785 auto *pdf = static_cast<const RooTruthModel *>(func);
786 elem["type"] << key();
787 std::string name = elem["name"].val();
788 // elem["name"] << RooJSONFactoryWSTool::sanitizeName(name);
789 elem["name"] << name;
790 elem["x"] << pdf->convVar().GetName();
791
792 return true;
793 }
794};
795
796class RooGaussModelStreamer : public RooFit::JSONIO::Exporter {
797public:
798 std::string const &key() const override;
799 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
800 {
801 auto *pdf = static_cast<const RooGaussModel *>(func);
802 elem["type"] << key();
803 std::string name = elem["name"].val();
804 // elem["name"] << RooJSONFactoryWSTool::sanitizeName(name);
805 elem["name"] << name;
806 elem["x"] << pdf->convVar().GetName();
807 elem["mean"] << pdf->getMean().GetName();
808 elem["sigma"] << pdf->getSigma().GetName();
809 return true;
810 }
811};
812
813class RooLogNormalStreamer : public RooFit::JSONIO::Exporter {
814public:
815 std::string const &key() const override;
816 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
817 {
818 auto *pdf = static_cast<const RooLognormal *>(func);
819
820 elem["type"] << key();
821 elem["x"] << pdf->getX().GetName();
822
823 auto &m0 = pdf->getMedian();
824 auto &k = pdf->getShapeK();
825
826 if (pdf->useStandardParametrization()) {
827 elem["mu"] << m0.GetName();
828 elem["sigma"] << k.GetName();
829 } else {
830 elem["mu"] << tool->exportTransformed(&m0, "_lognormal_log", "log(%s)");
831 elem["sigma"] << tool->exportTransformed(&k, "_lognormal_log", "log(%s)");
832 }
833
834 return true;
835 }
836};
837
838class RooExponentialStreamer : public RooFit::JSONIO::Exporter {
839public:
840 std::string const &key() const override;
841 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
842 {
843 auto *pdf = static_cast<const RooExponential *>(func);
844 elem["type"] << key();
845 elem["x"] << pdf->variable().GetName();
846 auto &c = pdf->coefficient();
847 if (pdf->negateCoefficient()) {
848 elem["c"] << c.GetName();
849 } else {
850 elem["c"] << tool->exportTransformed(&c, "_exponential_inverted", "-%s");
851 }
852
853 return true;
854 }
855};
856
857class RooMultiVarGaussianStreamer : public RooFit::JSONIO::Exporter {
858public:
859 std::string const &key() const override;
860 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
861 {
862 auto *pdf = static_cast<const RooMultiVarGaussian *>(func);
863 elem["type"] << key();
864 RooJSONFactoryWSTool::fillSeq(elem["x"], pdf->xVec());
865 RooJSONFactoryWSTool::fillSeq(elem["mean"], pdf->muVec());
866 elem["covariances"].fill_mat(pdf->covarianceMatrix());
867 return true;
868 }
869};
870
871class RooTFnBindingStreamer : public RooFit::JSONIO::Exporter {
872public:
873 std::string const &key() const override;
874 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
875 {
876 auto *pdf = static_cast<const RooTFnBinding *>(func);
877 elem["type"] << key();
878
879 TString formula(pdf->function().GetExpFormula());
880 formula.ReplaceAll("x", pdf->observables()[0].GetName());
881 formula.ReplaceAll("y", pdf->observables()[1].GetName());
882 formula.ReplaceAll("z", pdf->observables()[2].GetName());
883 for (size_t i = 0; i < pdf->parameters().size(); ++i) {
884 TString pname(TString::Format("[%d]", (int)i));
885 formula.ReplaceAll(pname, pdf->parameters()[i].GetName());
886 }
887 elem["expression"] << formula.Data();
888 return true;
889 }
890};
891
892class RooDerivativeStreamer : public RooFit::JSONIO::Exporter {
893public:
894 std::string const &key() const override;
895 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
896 {
897 auto *pdf = static_cast<const RooDerivative *>(func);
898 elem["type"] << key();
899 elem["x"] << pdf->getX().GetName();
900 elem["function"] << pdf->getFunc().GetName();
901 if (!pdf->getNset().empty()) {
902 RooJSONFactoryWSTool::fillSeq(elem["normalization"], pdf->getNset());
903 }
904 elem["order"] << pdf->order();
905 elem["eps"] << pdf->eps();
906 return true;
907 }
908};
909
910class RooRealIntegralStreamer : public RooFit::JSONIO::Exporter {
911public:
912 std::string const &key() const override;
913 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
914 {
915 auto *integral = static_cast<const RooRealIntegral *>(func);
916 std::string name = elem["name"].val();
917 // elem["name"] << RooJSONFactoryWSTool::sanitizeName(name);
918 elem["name"] << name;
919
920 elem["type"] << key();
921 std::string integrand = integral->integrand().GetName();
922 // elem["integrand"] << RooJSONFactoryWSTool::sanitizeName(integrand);
923 elem["integrand"] << integrand;
924 if (integral->intRange()) {
925 elem["domain"] << integral->intRange();
926 }
927 RooJSONFactoryWSTool::fillSeq(elem["variables"], integral->intVars());
928 if (RooArgSet const *funcNormSet = integral->funcNormSet()) {
929 RooJSONFactoryWSTool::fillSeq(elem["normalization"], *funcNormSet);
930 }
931 return true;
932 }
933};
934
935class RooFFTConvPdfStreamer : public RooFit::JSONIO::Exporter {
936public:
937 std::string const &key() const override;
938 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
939 {
940 auto *pdf = static_cast<const RooFFTConvPdf *>(func);
941 elem["type"] << key();
942 if (auto convFunc = pdf->getPdfConvVar()) {
943 elem["conv_func"] << convFunc->GetName();
944 }
945 elem["conv_var"] << pdf->getConvVar().GetName();
946 elem["pdf1"] << pdf->getPdf1().GetName();
947 elem["pdf2"] << pdf->getPdf2().GetName();
948 elem["ipOrder"] << pdf->getInterpolationOrder();
949 return true;
950 }
951};
952
953class RooExtendPdfStreamer : public RooFit::JSONIO::Exporter {
954public:
955 std::string const &key() const override;
956 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
957 {
958 auto *pdf = static_cast<const RooExtendPdf *>(func);
959 elem["type"] << key();
960 if (auto rangeName = pdf->getRangeName()) {
961 elem["range"] << rangeName->GetName();
962 }
963 elem["pdf"] << pdf->pdf().GetName();
964 elem["norm"] << pdf->getN().GetName();
965 return true;
966 }
967};
968
969#define DEFINE_EXPORTER_KEY(class_name, name) \
970 std::string const &class_name::key() const \
971 { \
972 const static std::string keystring = name; \
973 return keystring; \
974 }
975template <>
977template <>
979DEFINE_EXPORTER_KEY(RooBinSamplingPdfStreamer, "binsampling");
980DEFINE_EXPORTER_KEY(RooBinWidthFunctionStreamer, "binwidth");
981DEFINE_EXPORTER_KEY(RooLegacyExpPolyStreamer, "legacy_exp_poly_dist");
982DEFINE_EXPORTER_KEY(RooExponentialStreamer, "exponential_dist");
983template <>
985template <>
987DEFINE_EXPORTER_KEY(RooHistFuncStreamer, "histogram");
988DEFINE_EXPORTER_KEY(RooHistPdfStreamer, "histogram_dist");
989DEFINE_EXPORTER_KEY(RooLogNormalStreamer, "lognormal_dist");
990DEFINE_EXPORTER_KEY(RooMultiVarGaussianStreamer, "multivariate_normal_dist");
991DEFINE_EXPORTER_KEY(RooPoissonStreamer, "poisson_dist");
992DEFINE_EXPORTER_KEY(RooDecayStreamer, "decay_dist");
993DEFINE_EXPORTER_KEY(RooTruthModelStreamer, "truth_model_function");
994DEFINE_EXPORTER_KEY(RooGaussModelStreamer, "gauss_model_function");
995template <>
997template <>
999DEFINE_EXPORTER_KEY(RooRealSumFuncStreamer, "weighted_sum");
1000DEFINE_EXPORTER_KEY(RooRealSumPdfStreamer, "weighted_sum_dist");
1001DEFINE_EXPORTER_KEY(RooTFnBindingStreamer, "generic_function");
1002DEFINE_EXPORTER_KEY(RooRealIntegralStreamer, "integral");
1003DEFINE_EXPORTER_KEY(RooDerivativeStreamer, "derivative");
1004DEFINE_EXPORTER_KEY(RooFFTConvPdfStreamer, "fft_conv_pdf");
1005DEFINE_EXPORTER_KEY(RooExtendPdfStreamer, "extend_pdf");
1006
1007///////////////////////////////////////////////////////////////////////////////////////////////////////
1008// instantiate all importers and exporters
1009///////////////////////////////////////////////////////////////////////////////////////////////////////
1010
1011STATIC_EXECUTE([]() {
1012 using namespace RooFit::JSONIO;
1013
1014 registerImporter<RooAddPdfFactory>("mixture_dist", false);
1015 registerImporter<RooAddModelFactory>("mixture_model", false);
1016 registerImporter<RooBinSamplingPdfFactory>("binsampling_dist", false);
1018 registerImporter<RooLegacyExpPolyFactory>("legacy_exp_poly_dist", false);
1019 registerImporter<RooExponentialFactory>("exponential_dist", false);
1020 registerImporter<RooFormulaArgFactory<RooFormulaVar>>("generic_function", false);
1022 registerImporter<RooHistFuncFactory>("histogram", false);
1023 registerImporter<RooHistPdfFactory>("histogram_dist", false);
1024 registerImporter<RooLogNormalFactory>("lognormal_dist", false);
1025 registerImporter<RooMultiVarGaussianFactory>("multivariate_normal_dist", false);
1026 registerImporter<RooPoissonFactory>("poisson_dist", false);
1027 registerImporter<RooDecayFactory>("decay_dist", false);
1028 registerImporter<RooTruthModelFactory>("truth_model_function", false);
1029 registerImporter<RooGaussModelFactory>("gauss_model_function", false);
1032 registerImporter<RooRealSumPdfFactory>("weighted_sum_dist", false);
1033 registerImporter<RooRealSumFuncFactory>("weighted_sum", false);
1035 registerImporter<RooDerivativeFactory>("derivative", false);
1036 registerImporter<RooFFTConvPdfFactory>("fft_conv_pdf", false);
1037 registerImporter<RooExtendPdfFactory>("extend_pdf", false);
1038
1064});
1065
1066} // 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
RooAddModel is an efficient implementation of a sum of PDFs of the form.
Definition RooAddModel.h:27
static TClass * Class()
Efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:33
static TClass * Class()
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
Single or double sided decay function that can be analytically convolved with any RooResolutionModel ...
Definition RooDecay.h:22
static TClass * Class()
Represents the first, second, or third order derivative of any RooAbsReal as calculated (numerically)...
static TClass * Class()
Exponential PDF.
static TClass * Class()
RooExtendPdf is a wrapper around an existing PDF that adds a parameteric extended likelihood term to ...
static TClass * Class()
PDF for the numerical (FFT) convolution of two PDFs.
static TClass * Class()
static TClass * Class()
Class RooGaussModel implements a RooResolutionModel that models a Gaussian distribution.
static TClass * Class()
static TClass * Class()
A real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:31
static TClass * Class()
A probability density function sampled from a multidimensional histogram.
Definition RooHistPdf.h:30
static TClass * Class()
When using RooFit, statistical models can be conveniently handled and stored as a RooWorkspace.
static void fillSeq(RooFit::Detail::JSONNode &node, RooAbsCollection const &coll, size_t nMax=-1)
static std::unique_ptr< RooDataHist > readBinnedData(const RooFit::Detail::JSONNode &n, const std::string &namecomp, RooArgSet const &vars)
Read binned data from the JSONNode and create a RooDataHist object.
static 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
RooResolutionModel is the base class for PDFs that represent a resolution model that can be convolute...
Use TF1, TF2, TF3 functions as RooFit objects.
static TClass * Class()
Implements a RooResolution model that corresponds to a delta function.
static TClass * Class()
static Bool_t IsScientificNotation(const TString &formula, int ipos)
Definition TFormula.cxx: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)