Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooJSONFactoryWSTool.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 <RooGlobalFunc.h>
16#include <RooConstVar.h>
17#include <RooRealVar.h>
18#include <RooAbsCategory.h>
19#include <RooRealProxy.h>
20#include <RooListProxy.h>
21#include <RooAbsProxy.h>
22#include <RooCategory.h>
23#include <RooDataSet.h>
24#include <RooDataHist.h>
26
27#include "TROOT.h"
28#include "TH1.h"
29
30#include "RConfigure.h"
31
32#ifdef ROOFIT_HS3_WITH_RYML
33#include "RYMLParser.h"
34typedef TRYMLTree tree_t;
35#else
36#include "JSONParser.h"
38#endif
39
40#include <algorithm>
41#include <fstream>
42#include <iostream>
43#include <stack>
44#include <stdexcept>
45
46/** \class RooJSONFactoryWSTool
47\ingroup roofit
48
49When using `RooFit`, statistical models can be conveniently handled and
50stored as a `RooWorkspace`. However, for the sake of interoperability
51with other statistical frameworks, and also ease of manipulation, it
52may be useful to store statistical models in text form.
53
54The RooJSONFactoryWSTool is a helper class to achieve exactly this,
55exporting to and importing from JSON and YML.
56
57In order to import a workspace from a JSON file, you can do
58
59~~~ {.py}
60ws = ROOT.RooWorkspace("ws")
61tool = ROOT.RooJSONFactoryWSTool(ws)
62tool.importJSON("myjson.json")
63~~~
64
65Similarly, in order to export a workspace to a JSON file, you can do
66
67~~~ {.py}
68tool = ROOT.RooJSONFactoryWSTool(ws)
69tool.exportJSON("myjson.json")
70~~~
71
72For more details, consult the tutorial <a
73href="https://root.cern/doc/v626/rf515__hfJSON_8py.html">rf515_hfJSON</a>.
74
75In order to import and export YML files, `ROOT` needs to be compiled
76with the external dependency <a
77href="https://github.com/biojppm/rapidyaml">RapidYAML</a>, which needs
78to be installed on your system and enabled via the CMake option
79`roofit_hs3_ryml`.
80
81The RooJSONFactoryWSTool only knows about a limited set of classes for
82import and export. If import or export of a class you're interested in
83fails, you might need to add your own importer or exporter. Please
84consult the <a
85href="https://github.com/root-project/root/blob/master/roofit/hs3/README.md">README</a>
86to learn how to do that.
87
88You can always get a list of all the avialable importers and exporters by calling the following functions:
89~~~ {.py}
90tool = ROOT.RooJSONFactoryWSTool(ws)
91tool.printImporters()
92tool.printExporters()
93tool.printFactoryExpressions()
94tool.printExportKeys()
95~~~
96
97Alternatively, you can generate a LaTeX version of the available importers and exporters by calling
98~~~ {.py}
99tool = ROOT.RooJSONFactoryWSTool(ws)
100tool.writedoc("hs3.tex")
101~~~
102
103*/
104
106
107namespace {
108bool isNumber(const std::string &str)
109{
110 bool first = true;
111 for (char const &c : str) {
112 if (std::isdigit(c) == 0 && c != '.' && !(first && (c == '-' || c == '+')))
113 return false;
114 first = false;
115 }
116 return true;
117}
118} // namespace
119
121{
123 return *_rootnode_output;
124 throw MissingRootnodeError();
125}
127{
128 if (_rootnode_input)
129 return *_rootnode_input;
130 throw MissingRootnodeError();
131}
132
133template <>
134RooRealVar *RooJSONFactoryWSTool::request<RooRealVar>(const std::string &objname, const std::string &requestAuthor)
135{
136 RooRealVar *retval = this->workspace()->var(objname.c_str());
137 if (retval)
138 return retval;
139 if (irootnode().has_child("variables")) {
140 const JSONNode &vars = irootnode()["variables"];
141 if (vars.has_child(objname)) {
142 this->importVariable(vars[objname]);
143 retval = this->workspace()->var(objname.c_str());
144 if (retval)
145 return retval;
146 }
147 }
148 throw DependencyMissingError(requestAuthor, objname, "RooRealVar");
149}
150
151template <>
152RooAbsPdf *RooJSONFactoryWSTool::request<RooAbsPdf>(const std::string &objname, const std::string &requestAuthor)
153{
154 RooAbsPdf *retval = this->workspace()->pdf(objname.c_str());
155 if (retval)
156 return retval;
157 if (irootnode().has_child("pdfs")) {
158 const JSONNode &pdfs = irootnode()["pdfs"];
159 if (pdfs.has_child(objname)) {
160 this->importFunction(pdfs[objname], true);
161 retval = this->workspace()->pdf(objname.c_str());
162 if (retval)
163 return retval;
164 }
165 }
166 throw DependencyMissingError(requestAuthor, objname, "RooAbsPdf");
167}
168
169template <>
170RooAbsReal *RooJSONFactoryWSTool::request<RooAbsReal>(const std::string &objname, const std::string &requestAuthor)
171{
172 RooAbsReal *retval = nullptr;
173 retval = this->workspace()->pdf(objname.c_str());
174 if (retval)
175 return retval;
176 retval = this->workspace()->function(objname.c_str());
177 if (retval)
178 return retval;
179 retval = this->workspace()->var(objname.c_str());
180 if (retval)
181 return retval;
182 if (isNumber(objname))
183 return dynamic_cast<RooAbsReal *>(this->workspace()->factory(objname.c_str()));
184 if (irootnode().has_child("pdfs")) {
185 const JSONNode &pdfs = irootnode()["pdfs"];
186 if (pdfs.has_child(objname)) {
187 this->importFunction(pdfs[objname], true);
188 retval = this->workspace()->pdf(objname.c_str());
189 if (retval)
190 return retval;
191 }
192 }
193 if (irootnode().has_child("variables")) {
194 const JSONNode &vars = irootnode()["variables"];
195 if (vars.has_child(objname)) {
196 this->importVariable(vars[objname]);
197 retval = this->workspace()->var(objname.c_str());
198 if (retval)
199 return retval;
200 }
201 }
202 if (irootnode().has_child("functions")) {
203 const JSONNode &funcs = irootnode()["functions"];
204 if (funcs.has_child(objname)) {
205 this->importFunction(funcs[objname], false);
206 retval = this->workspace()->function(objname.c_str());
207 if (retval)
208 return retval;
209 }
210 }
211 throw DependencyMissingError(requestAuthor, objname, "RooAbsReal");
212}
213
214namespace {
215
216void logInputArgumentsError(std::stringstream &&ss)
217{
218 oocoutE(static_cast<RooAbsArg *>(nullptr), InputArguments) << ss.str();
219}
220
221} // namespace
222
224{
225 if (val.is_map()) {
226 if (!val.has_child("nbins"))
227 this->nbins = 1;
228 else
229 this->nbins = val["nbins"].val_int();
230 if (!val.has_child("min"))
231 this->min = 0;
232 else
233 this->min = val["min"].val_float();
234 if (!val.has_child("max"))
235 this->max = 1;
236 else
237 this->max = val["max"].val_float();
238 } else if (val.is_seq()) {
239 for (size_t i = 0; i < val.num_children(); ++i) {
240 this->bounds.push_back(val[i].val_float());
241 }
242 this->nbins = this->bounds.size();
243 this->min = this->bounds[0];
244 this->max = this->bounds[this->nbins - 1];
245 }
246}
247
248std::string RooJSONFactoryWSTool::genPrefix(const JSONNode &p, bool trailing_underscore)
249{
250 std::string prefix;
251 if (!p.is_map())
252 return prefix;
253 if (p.has_child("namespaces")) {
254 for (const auto &ns : p["namespaces"].children()) {
255 if (prefix.size() > 0)
256 prefix += "_";
257 prefix += ns.val();
258 }
259 }
260 if (trailing_underscore && prefix.size() > 0)
261 prefix += "_";
262 return prefix;
263}
264
265namespace {
266// helpers for serializing / deserializing binned datasets
267inline void genIndicesHelper(std::vector<std::vector<int>> &combinations, std::vector<int> &curr_comb,
268 const std::vector<int> &vars_numbins, size_t curridx)
269{
270 if (curridx == vars_numbins.size()) {
271 // we have filled a combination. Copy it.
272 combinations.push_back(std::vector<int>(curr_comb));
273 } else {
274 for (int i = 0; i < vars_numbins[curridx]; ++i) {
275 curr_comb[curridx] = i;
276 ::genIndicesHelper(combinations, curr_comb, vars_numbins, curridx + 1);
277 }
278 }
279}
280
281std::string containerName(RooAbsArg *elem)
282{
283 std::string contname = "functions";
284 if (elem->InheritsFrom(RooAbsPdf::Class()))
285 contname = "pdfs";
286 if (elem->InheritsFrom(RooRealVar::Class()) || elem->InheritsFrom(RooConstVar::Class()))
287 contname = "variables";
288 return contname;
289}
290} // namespace
291
293
294bool RooJSONFactoryWSTool::registerImporter(const std::string &key,
295 std::unique_ptr<const RooJSONFactoryWSTool::Importer> f, bool topPriority)
296{
297 auto &vec = staticImporters()[key];
298 vec.insert(topPriority ? vec.begin() : vec.end(), std::move(f));
299 return true;
300}
301
302bool RooJSONFactoryWSTool::registerExporter(const TClass *key, std::unique_ptr<const RooJSONFactoryWSTool::Exporter> f,
303 bool topPriority)
304{
305 auto &vec = staticExporters()[key];
306 vec.insert(topPriority ? vec.begin() : vec.end(), std::move(f));
307 return true;
308}
309
310int RooJSONFactoryWSTool::removeImporters(const std::string &needle)
311{
312 int n = 0;
313 for (auto &element : staticImporters()) {
314 for (size_t i = element.second.size(); i > 0; --i) {
315 auto *imp = element.second[i - 1].get();
316 std::string name(typeid(*imp).name());
317 if (name.find(needle) != std::string::npos) {
318 element.second.erase(element.second.begin() + i - 1);
319 ++n;
320 }
321 }
322 }
323 return n;
324}
325
326int RooJSONFactoryWSTool::removeExporters(const std::string &needle)
327{
328 int n = 0;
329 for (auto &element : staticExporters()) {
330 for (size_t i = element.second.size(); i > 0; --i) {
331 auto *imp = element.second[i - 1].get();
332 std::string name(typeid(*imp).name());
333 if (name.find(needle) != std::string::npos) {
334 element.second.erase(element.second.begin() + i - 1);
335 ++n;
336 }
337 }
338 }
339 return n;
340}
341
343{
344 for (const auto &x : staticImporters()) {
345 for (const auto &ePtr : x.second) {
346 // Passing *e directory to typeid results in clang warnings.
347 auto const &e = *ePtr;
348 std::cout << x.first << "\t" << typeid(e).name() << std::endl;
349 }
350 }
351}
353{
354 for (const auto &x : staticExporters()) {
355 for (const auto &ePtr : x.second) {
356 // Passing *e directory to typeid results in clang warnings.
357 auto const &e = *ePtr;
358 std::cout << x.first->GetName() << "\t" << typeid(e).name() << std::endl;
359 }
360 }
361}
362
363///////////////////////////////////////////////////////////////////////////////////////////////////////
364// helper functions specific to JSON
365///////////////////////////////////////////////////////////////////////////////////////////////////////
366
367namespace {
368
369inline void importAttributes(RooAbsArg *arg, const JSONNode &n)
370{
371 if (!n.is_map())
372 return;
373 if (n.has_child("dict") && n["dict"].is_map()) {
374 for (const auto &attr : n["dict"].children()) {
375 arg->setStringAttribute(RooJSONFactoryWSTool::name(attr).c_str(), attr.val().c_str());
376 }
377 }
378 if (n.has_child("tags") && n["tags"].is_seq()) {
379 for (const auto &attr : n["tags"].children()) {
380 arg->setAttribute(attr.val().c_str());
381 }
382 }
383}
384inline bool checkRegularBins(const TAxis &ax)
385{
386 double w = ax.GetXmax() - ax.GetXmin();
387 double bw = w / ax.GetNbins();
388 for (int i = 0; i <= ax.GetNbins(); ++i) {
389 if (fabs(ax.GetBinUpEdge(i) - (ax.GetXmin() + (bw * i))) > w * 1e-6)
390 return false;
391 }
392 return true;
393}
394inline void writeAxis(JSONNode &bounds, const TAxis &ax)
395{
396 bool regular = (!ax.IsVariableBinSize()) || checkRegularBins(ax);
397 if (regular) {
398 bounds.set_map();
399 bounds["nbins"] << ax.GetNbins();
400 bounds["min"] << ax.GetXmin();
401 bounds["max"] << ax.GetXmax();
402 } else {
403 bounds.set_seq();
404 for (int i = 0; i <= ax.GetNbins(); ++i) {
405 bounds.append_child() << ax.GetBinUpEdge(i);
406 }
407 }
408}
409} // namespace
410
411///////////////////////////////////////////////////////////////////////////////////////////////////////
412// RooWSFactoryTool expression handling
413///////////////////////////////////////////////////////////////////////////////////////////////////////
414
415namespace {
416std::string generate(const RooJSONFactoryWSTool::ImportExpression &ex, const JSONNode &p, RooJSONFactoryWSTool *tool)
417{
418 std::string name(RooJSONFactoryWSTool::name(p));
419 std::stringstream expression;
420 std::string classname(ex.tclass->GetName());
421 size_t colon = classname.find_last_of(":");
422 if (colon < classname.size()) {
423 expression << classname.substr(colon + 1);
424 } else {
425 expression << classname;
426 }
427 expression << "::" << name << "(";
428 bool first = true;
429 for (auto k : ex.arguments) {
430 if (!first)
431 expression << ",";
432 first = false;
433 if (k == "true") {
434 expression << "1";
435 continue;
436 } else if (k == "false") {
437 expression << "0";
438 continue;
439 } else if (!p.has_child(k)) {
440 std::stringstream err;
441 err << "factory expression for class '" << ex.tclass->GetName() << "', which expects key '" << k
442 << "' missing from input for object '" << name << "', skipping.";
443 RooJSONFactoryWSTool::error(err.str().c_str());
444 }
445 if (p[k].is_seq()) {
446 expression << "{";
447 bool f = true;
448 for (const auto &x : p[k].children()) {
449 if (!f)
450 expression << ",";
451 f = false;
452 std::string obj(x.val());
453 tool->request<RooAbsReal>(obj, name);
454 expression << obj;
455 }
456 expression << "}";
457 } else {
458 std::string obj(p[k].val());
459 tool->request<RooAbsReal>(obj, name);
460 expression << obj;
461 }
462 }
463 expression << ")";
464 return expression.str();
465}
466}; // namespace
467
469{
470 auto &pdfFactoryExpressions = staticPdfImportExpressions();
471 auto &funcFactoryExpressions = staticFunctionImportExpressions();
472
473 // load a yml file defining the factory expressions
474 std::ifstream infile(fname);
475 if (!infile.is_open()) {
476 std::cerr << "unable to read file '" << fname << "'" << std::endl;
477 return;
478 }
479 try {
480 tree_t p(infile);
481 const JSONNode &n = p.rootnode();
482 for (const auto &cl : n.children()) {
483 std::string key(RooJSONFactoryWSTool::name(cl));
484 if (!cl.has_child("class")) {
485 std::cerr << "error in file '" << fname << "' for entry '" << key << "': 'class' key is required!"
486 << std::endl;
487 continue;
488 }
489 std::string classname(cl["class"].val());
490 TClass *c = TClass::GetClass(classname.c_str());
491 if (!c) {
492 std::cerr << "unable to find class " << classname << ", skipping." << std::endl;
493 } else {
495 ex.tclass = c;
496 if (!cl.has_child("arguments")) {
497 std::cerr << "class " << classname << " seems to have no arguments attached, skipping" << std::endl;
498 continue;
499 }
500 for (const auto &arg : cl["arguments"].children()) {
501 ex.arguments.push_back(arg.val());
502 }
503 if (c->InheritsFrom(RooAbsPdf::Class())) {
504 pdfFactoryExpressions[key] = ex;
505 } else if (c->InheritsFrom(RooAbsReal::Class())) {
506 funcFactoryExpressions[key] = ex;
507 } else {
508 std::cerr << "class " << classname << " seems to not inherit from any suitable class, skipping"
509 << std::endl;
510 }
511 }
512 }
513 } catch (const std::exception &ex) {
514 std::cout << "caught" << std::endl;
515 std::cerr << "unable to load factory expressions: " << ex.what() << std::endl;
516 }
517}
519{
520 // clear all factory expressions
523}
525{
526 // print all factory expressions
527 for (auto it : staticPdfImportExpressions()) {
528 std::cout << it.first;
529 std::cout << " " << it.second.tclass->GetName();
530 for (auto v : it.second.arguments) {
531 std::cout << " " << v;
532 }
533 std::cout << std::endl;
534 }
535 for (auto it : staticFunctionImportExpressions()) {
536 std::cout << it.first;
537 std::cout << " " << it.second.tclass->GetName();
538 for (auto v : it.second.arguments) {
539 std::cout << " " << v;
540 }
541 std::cout << std::endl;
542 }
543}
544
545std::vector<std::vector<int>> RooJSONFactoryWSTool::generateBinIndices(const RooArgList &vars)
546{
547 std::vector<std::vector<int>> combinations;
548 std::vector<int> vars_numbins;
549 vars_numbins.reserve(vars.size());
550 for (const auto *absv : static_range_cast<RooRealVar *>(vars)) {
551 vars_numbins.push_back(absv->numBins());
552 }
553 std::vector<int> curr_comb(vars.size());
554 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
555 return combinations;
556}
557
558void RooJSONFactoryWSTool::writeObservables(const TH1 &h, JSONNode &n, const std::vector<std::string> &varnames)
559{
560 auto &observables = n["observables"];
561 observables.set_map();
562 auto &x = observables[varnames[0]];
563 writeAxis(x, *(h.GetXaxis()));
564 if (h.GetDimension() > 1) {
565 auto &y = observables[varnames[1]];
566 writeAxis(y, *(h.GetYaxis()));
567 if (h.GetDimension() > 2) {
568 auto &z = observables[varnames[2]];
569 writeAxis(z, *(h.GetZaxis()));
570 }
571 }
572}
573
574void RooJSONFactoryWSTool::exportHistogram(const TH1 &h, JSONNode &n, const std::vector<std::string> &varnames,
575 const TH1 *errH, bool writeObservables, bool writeErrors)
576{
577 n.set_map();
578 auto &weights = n["counts"];
579 weights.set_seq();
580 if (writeErrors) {
581 n["errors"].set_seq();
582 }
583 if (writeObservables) {
585 }
586 for (int i = 1; i <= h.GetNbinsX(); ++i) {
587 if (h.GetDimension() == 1) {
588 weights.append_child() << h.GetBinContent(i);
589 if (writeErrors) {
590 n["errors"].append_child() << (errH ? h.GetBinContent(i) * errH->GetBinContent(i) : h.GetBinError(i));
591 }
592 } else {
593 for (int j = 1; j <= h.GetNbinsY(); ++j) {
594 if (h.GetDimension() == 2) {
595 weights.append_child() << h.GetBinContent(i, j);
596 if (writeErrors) {
597 n["errors"].append_child()
598 << (errH ? h.GetBinContent(i, j) * errH->GetBinContent(i, j) : h.GetBinError(i, j));
599 }
600 } else {
601 for (int k = 1; k <= h.GetNbinsZ(); ++k) {
602 weights.append_child() << h.GetBinContent(i, j, k);
603 if (writeErrors) {
604 n["errors"].append_child()
605 << (errH ? h.GetBinContent(i, j, k) * errH->GetBinContent(i, j, k) : h.GetBinError(i, j, k));
606 }
607 }
608 }
609 }
610 }
611 }
612}
613
614///////////////////////////////////////////////////////////////////////////////////////////////////////
615// RooProxy-based export handling
616///////////////////////////////////////////////////////////////////////////////////////////////////////
617
618void RooJSONFactoryWSTool::loadExportKeys(const std::string &fname)
619{
621
622 // load a yml file defining the export keys
623 std::ifstream infile(fname);
624 if (!infile.is_open()) {
625 std::cerr << "unable to read file '" << fname << "'" << std::endl;
626 return;
627 }
628 try {
629 tree_t p(infile);
630 const JSONNode &n = p.rootnode();
631 for (const auto &cl : n.children()) {
632 std::string classname(RooJSONFactoryWSTool::name(cl));
633 TClass *c = TClass::GetClass(classname.c_str());
634 if (!c) {
635 std::cerr << "unable to find class " << classname << ", skipping." << std::endl;
636 } else {
638 if (!cl.has_child("type")) {
639 std::cerr << "class " << classname << "has not type key set, skipping" << std::endl;
640 continue;
641 }
642 if (!cl.has_child("proxies")) {
643 std::cerr << "class " << classname << "has no proxies identified, skipping" << std::endl;
644 continue;
645 }
646 ex.type = cl["type"].val();
647 for (const auto &k : cl["proxies"].children()) {
648 std::string key(RooJSONFactoryWSTool::name(k));
649 std::string val(k.val());
650 ex.proxies[key] = val;
651 }
652 exportKeys[c] = ex;
653 }
654 }
655 } catch (const std::exception &ex) {
656 std::cerr << "unable to load export keys: " << ex.what() << std::endl;
657 }
658}
659
661{
662 // clear all export keys
663 staticExportKeys().clear();
664}
665
667{
668 // print all export keys
669 for (const auto &it : staticExportKeys()) {
670 std::cout << it.first->GetName() << ": " << it.second.type;
671 for (const auto &kv : it.second.proxies) {
672 std::cout << " " << kv.first << "=" << kv.second;
673 }
674 std::cout << std::endl;
675 }
676}
677
678///////////////////////////////////////////////////////////////////////////////////////////////////////
679// helper namespace
680///////////////////////////////////////////////////////////////////////////////////////////////////////
681
682bool RooJSONFactoryWSTool::find(const JSONNode &n, const std::string &elem)
683{
684 // find an attribute
685 if (n.is_seq()) {
686 for (const auto &t : n.children()) {
687 if (t.val() == elem)
688 return true;
689 }
690 return false;
691 } else if (n.is_map()) {
692 return n.has_child(elem.c_str());
693 }
694 return false;
695}
696
697void RooJSONFactoryWSTool::append(JSONNode &n, const std::string &elem)
698{
699 // append an attribute
700 n.set_seq();
701 if (!find(n, elem)) {
702 n.append_child() << elem;
703 }
704}
705
707{
708 // export all string attributes of an object
709 if (arg->stringAttributes().size() > 0) {
710 auto &dict = n["dict"];
711 dict.set_map();
712 for (const auto &it : arg->stringAttributes()) {
713 dict[it.first] << it.second;
714 }
715 }
716 if (arg->attributes().size() > 0) {
717 auto &tags = n["tags"];
718 tags.set_seq();
719 for (const auto &it : arg->attributes()) {
721 }
722 }
723}
724
726{
727 auto &var = n[v->GetName()];
728 const RooConstVar *cv = dynamic_cast<const RooConstVar *>(v);
729 const RooRealVar *rrv = dynamic_cast<const RooRealVar *>(v);
730 var.set_map();
731 if (cv) {
732 var["value"] << cv->getVal();
733 var["const"] << true;
734 } else if (rrv) {
735 var["value"] << rrv->getVal();
736 if (rrv->getMin() > -1e30) {
737 var["min"] << rrv->getMin();
738 }
739 if (rrv->getMax() < 1e30) {
740 var["max"] << rrv->getMax();
741 }
742 if (rrv->isConstant()) {
743 var["const"] << rrv->isConstant();
744 }
745 if (rrv->numBins() != 100) {
746 var["nbins"] << rrv->numBins();
747 }
748 }
750}
751
753{
754 // export a list of RooRealVar objects
755 for (auto *arg : allElems) {
756 RooAbsReal *v = dynamic_cast<RooAbsReal *>(arg);
757 if (!v)
758 continue;
759 if (v->InheritsFrom(RooRealVar::Class()) || v->InheritsFrom(RooConstVar::Class())) {
761 }
762 }
763}
764
766{
767 auto const &exporters = staticExporters();
768 auto const &exportKeys = staticExportKeys();
769
770 // if this element already exists, skip
771 if (n.has_child(func->GetName()))
772 return;
773
774 if (func->InheritsFrom(RooConstVar::Class()) &&
775 strcmp(func->GetName(), TString::Format("%g", ((RooConstVar *)func)->getVal()).Data()) == 0) {
776 // for RooConstVar, if name and value are the same, we don't need to do anything
777 return;
778 } else if (func->InheritsFrom(RooAbsCategory::Class())) {
779 // categories are created by the respective RooSimultaneous, so we're skipping the export here
780 return;
781 } else if (func->InheritsFrom(RooRealVar::Class()) || func->InheritsFrom(RooConstVar::Class())) {
782 // for variables, call the variable exporter
783 exportVariable(static_cast<const RooAbsReal *>(func), n);
784 return;
785 }
786
787 TClass *cl = TClass::GetClass(func->ClassName());
788
789 auto it = exporters.find(cl);
790 bool ok = false;
791 if (it != exporters.end()) { // check if we have a specific exporter available
792 for (auto &exp : it->second) {
793 try {
794 auto &elem = n[func->GetName()];
795 elem.set_map();
796 if (!exp->exportObject(this, func, elem)) {
797 continue;
798 }
799 if (exp->autoExportDependants()) {
801 }
803 ok = true;
804 } catch (const std::exception &ex) {
805 std::cerr << "error exporting " << func->Class()->GetName() << " " << func->GetName() << ": " << ex.what()
806 << ". skipping." << std::endl;
807 return;
808 }
809 if (ok)
810 break;
811 }
812 }
813 if (!ok) { // generic export using the factory expressions
814 const auto &dict = exportKeys.find(cl);
815 if (dict == exportKeys.end()) {
816 std::cerr << "unable to export class '" << cl->GetName() << "' - no export keys available!" << std::endl;
817 std::cerr << "there are several possible reasons for this:" << std::endl;
818 std::cerr << " 1. " << cl->GetName() << " is a custom class that you or some package you are using added."
819 << std::endl;
820 std::cerr << " 2. " << cl->GetName()
821 << " is a ROOT class that nobody ever bothered to write a serialization definition for."
822 << std::endl;
823 std::cerr << " 3. something is wrong with your setup, e.g. you might have called "
824 "RooJSONFactoryWSTool::clearExportKeys() and/or never successfully read a file defining these "
825 "keys with RooJSONFactoryWSTool::loadExportKeys(filename)"
826 << std::endl;
827 std::cerr << "either way, please make sure that:" << std::endl;
828 std::cerr << " 3: you are reading a file with export keys - call RooJSONFactoryWSTool::printExportKeys() to "
829 "see what is available"
830 << std::endl;
831 std::cerr << " 2 & 1: you might need to write a serialization definition yourself. check "
832 "https://github.com/root-project/root/blob/master/roofit/hs3/README.md to "
833 "see how to do this!"
834 << std::endl;
835 return;
836 }
837
839
840 auto &elem = n[func->GetName()];
841 elem.set_map();
842 elem["type"] << dict->second.type;
843
844 size_t nprox = func->numProxies();
845 for (size_t i = 0; i < nprox; ++i) {
846 RooAbsProxy *p = func->getProxy(i);
847
848 std::string pname(p->name());
849 if (pname[0] == '!')
850 pname.erase(0, 1);
851
852 auto k = dict->second.proxies.find(pname);
853 if (k == dict->second.proxies.end()) {
854 std::cerr << "failed to find key matching proxy '" << pname << "' for type '" << dict->second.type
855 << "', skipping" << std::endl;
856 return;
857 }
858
859 RooListProxy *l = dynamic_cast<RooListProxy *>(p);
860 if (l) {
861 auto &items = elem[k->second];
862 items.set_seq();
863 for (auto e : *l) {
864 items.append_child() << e->GetName();
865 }
866 }
867 RooRealProxy *r = dynamic_cast<RooRealProxy *>(p);
868 if (r) {
869 elem[k->second] << r->arg().GetName();
870 }
871 }
873 }
874}
875
877{
878 // export a list of functions
879 // note: this function assumes that all the dependants of these objects have already been exported
880 for (auto *arg : allElems) {
881 RooAbsReal *func = dynamic_cast<RooAbsReal *>(arg);
882 if (!func)
883 continue;
885 }
886}
887
888///////////////////////////////////////////////////////////////////////////////////////////////////////
889// importing functions
891{
892 // import a list of RooAbsReal objects
893 if (!n.is_map())
894 return;
895 for (const auto &p : n.children()) {
896 importFunction(p, false);
897 }
898}
899
900///////////////////////////////////////////////////////////////////////////////////////////////////////
901// importing functions
903{
904 auto const &importers = staticImporters();
905 auto const &pdfFactoryExpressions = staticPdfImportExpressions();
906 auto const &funcFactoryExpressions = staticFunctionImportExpressions();
907
908 // some preparations: what type of function are we dealing with here?
909 std::string name(RooJSONFactoryWSTool::name(p));
910 // if it's an empty name, it's a lost cause, let's just skip it
911 if (name.empty())
912 return;
913 // if the function already exists, we don't need to do anything
914 if (isPdf) {
915 if (this->_workspace->pdf(name.c_str()))
916 return;
917 } else {
918 if (this->_workspace->function(name.c_str()))
919 return;
920 }
921 // if the key we found is not a map, it's an error
922 if (!p.is_map()) {
923 std::stringstream ss;
924 ss << "RooJSONFactoryWSTool() function node " + name + " is not a map!";
925 logInputArgumentsError(std::move(ss));
926 return;
927 }
928 std::string prefix = RooJSONFactoryWSTool::genPrefix(p, true);
929 if (prefix.size() > 0)
930 name = prefix + name;
931 if (!p.has_child("type")) {
932 std::stringstream ss;
933 ss << "RooJSONFactoryWSTool() no type given for function '" << name << "', skipping." << std::endl;
934 logInputArgumentsError(std::move(ss));
935 return;
936 }
937
938 bool toplevel = false;
939 if (isPdf && p.has_child("tags")) {
940 toplevel = RooJSONFactoryWSTool::find(p["tags"], "toplevel");
941 }
942
943 std::string functype(p["type"].val());
944 this->importDependants(p);
945
946 try {
947 // check for specific implementations
948 auto it = importers.find(functype);
949 bool ok = false;
950 if (it != importers.end()) {
951 for (auto &imp : it->second) {
952 ok = isPdf ? imp->importPdf(this, p) : imp->importFunction(this, p);
953 if (ok)
954 break;
955 }
956 }
957 if (!ok) { // generic import using the factory expressions
958 auto expr = isPdf ? pdfFactoryExpressions.find(functype) : funcFactoryExpressions.find(functype);
959 if (expr != (isPdf ? pdfFactoryExpressions.end() : funcFactoryExpressions.end())) {
960 std::string expression = ::generate(expr->second, p, this);
961 if (!this->_workspace->factory(expression.c_str())) {
962 std::stringstream ss;
963 ss << "RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() << " '" << name
964 << "', skipping. expression was\n"
965 << expression << std::endl;
966 logInputArgumentsError(std::move(ss));
967 }
968 } else {
969 std::stringstream ss;
970 ss << "RooJSONFactoryWSTool() no handling for type '" << functype << "' implemented, skipping."
971 << "\n"
972 << "there are several possible reasons for this:\n"
973 << " 1. " << functype << " is a custom type that is not available in RooFit.\n"
974 << " 2. " << functype
975 << " is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
976 << " 3. something is wrong with your setup, e.g. you might have called "
977 "RooJSONFactoryWSTool::clearFactoryExpressions() and/or never successfully read a file defining "
978 "these expressions with RooJSONFactoryWSTool::loadFactoryExpressions(filename)\n"
979 << "either way, please make sure that:\n"
980 << " 3: you are reading a file with factory expressions - call "
981 "RooJSONFactoryWSTool::printFactoryExpressions() "
982 "to see what is available\n"
983 << " 2 & 1: you might need to write a deserialization definition yourself. check "
984 "https://github.com/root-project/root/blob/master/roofit/hs3/README.md to see "
985 "how to do this!"
986 << std::endl;
987 logInputArgumentsError(std::move(ss));
988 return;
989 }
990 }
991 RooAbsReal *func = this->_workspace->function(name.c_str());
992 if (!func) {
993 std::stringstream err;
994 err << "something went wrong importing function '" << name << "'.";
995 RooJSONFactoryWSTool::error(err.str().c_str());
996 } else {
997 ::importAttributes(func, p);
998
999 if (isPdf && toplevel) {
1000 configureToplevelPdf(p, *static_cast<RooAbsPdf *>(func));
1001 }
1002 }
1004 throw;
1006 throw;
1007 } catch (const std::exception &ex) {
1008 std::stringstream ss;
1009 ss << "RooJSONFactoryWSTool(): error importing " << name << ": " << ex.what() << ". skipping." << std::endl;
1010 logInputArgumentsError(std::move(ss));
1011 }
1012}
1013
1014///////////////////////////////////////////////////////////////////////////////////////////////////////
1015// generating an unbinned dataset from a binned one
1016
1017std::unique_ptr<RooDataSet> RooJSONFactoryWSTool::unbinned(RooDataHist const &hist)
1018{
1019 RooArgSet obs(*hist.get());
1020 RooRealVar *weight = this->getWeightVar("weight");
1021 obs.add(*weight, true);
1022 auto data = std::make_unique<RooDataSet>(hist.GetName(), hist.GetTitle(), obs, RooFit::WeightVar(*weight));
1023 for (int i = 0; i < hist.numEntries(); ++i) {
1024 data->add(*hist.get(i), hist.weight(i));
1025 }
1026 return data;
1027}
1028
1029///////////////////////////////////////////////////////////////////////////////////////////////////////
1030// generating a weight variable
1031
1033{
1034 RooRealVar *weightVar = _workspace->var(weightName);
1035 if (!weightVar) {
1036 _workspace->factory(TString::Format("%s[0.,0.,10000000]", weightName).Data());
1037 }
1038 weightVar = _workspace->var(weightName);
1039 return weightVar;
1040}
1041
1042///////////////////////////////////////////////////////////////////////////////////////////////////////
1043// importing data
1044std::map<std::string, std::unique_ptr<RooAbsData>> RooJSONFactoryWSTool::loadData(const JSONNode &n)
1045{
1046 std::map<std::string, std::unique_ptr<RooAbsData>> dataMap;
1047 if (!n.is_map()) {
1048 return dataMap;
1049 }
1050 for (const auto &p : n.children()) {
1051 std::string name(RooJSONFactoryWSTool::name(p));
1052 if (name.empty())
1053 continue;
1054 if (this->_workspace->data(name.c_str()))
1055 continue;
1056 if (!p.is_map())
1057 continue;
1058 if (p.has_child("counts")) {
1059 // binned
1060 RooArgSet vars;
1061 this->getObservables(p, name, vars);
1062 dataMap[name] = this->readBinnedData(p, name, vars);
1063 } else if (p.has_child("coordinates")) {
1064 // unbinned
1065 RooArgSet vars;
1066 this->getObservables(p, name, vars);
1067 RooArgList varlist(vars);
1068 RooRealVar *weightVar = this->getWeightVar("weight");
1069 vars.add(*weightVar, true);
1070 auto data = std::make_unique<RooDataSet>(name, name, vars, RooFit::WeightVar(*weightVar));
1071 auto &coords = p["coordinates"];
1072 auto &weights = p["weights"];
1073 if (coords.num_children() != weights.num_children()) {
1074 RooJSONFactoryWSTool::error("inconsistent number of coordinates and weights!");
1075 }
1076 if (!coords.is_seq()) {
1077 RooJSONFactoryWSTool::error("key 'coordinates' is not a list!");
1078 }
1079 for (size_t i = 0; i < coords.num_children(); ++i) {
1080 auto &point = coords[i];
1081 if (!point.is_seq()) {
1082 RooJSONFactoryWSTool::error(TString::Format("coordinate point '%d' is not a list!", (int)i).Data());
1083 }
1084 if (point.num_children() != varlist.size()) {
1085 RooJSONFactoryWSTool::error("inconsistent number of coordinates and observables!");
1086 }
1087 for (size_t j = 0; j < point.num_children(); ++j) {
1088 auto *v = static_cast<RooRealVar *>(varlist.at(j));
1089 v->setVal(point[j].val_float());
1090 }
1091 data->add(vars, weights[i].val_float());
1092 }
1093 dataMap[name] = std::move(data);
1094 } else if (p.has_child("index")) {
1095 // combined measurement
1096 auto subMap = loadData(p);
1097 auto catname = p["index"].val();
1098 RooCategory *channelCat = _workspace->cat(catname.c_str());
1099 if (!channelCat) {
1100 std::stringstream ss;
1101 ss << "RooJSONFactoryWSTool() failed to retrieve channel category " << catname << std::endl;
1102 logInputArgumentsError(std::move(ss));
1103 } else {
1104 RooArgSet allVars;
1105 allVars.add(*channelCat, true);
1106 std::stack<std::unique_ptr<RooDataSet>> ownedDataSets;
1107 std::map<std::string, RooDataSet *> datasets;
1108 for (const auto &subd : subMap) {
1109 allVars.add(*subd.second->get(), true);
1110 if (subd.second->InheritsFrom(RooDataHist::Class())) {
1111 ownedDataSets.push(unbinned(static_cast<RooDataHist const &>(*subd.second)));
1112 datasets[subd.first] = ownedDataSets.top().get();
1113 } else {
1114 datasets[subd.first] = static_cast<RooDataSet *>(subd.second.get());
1115 }
1116 }
1117 RooRealVar *weightVar = this->getWeightVar("weight");
1118 allVars.add(*weightVar, true);
1119 dataMap[name] =
1120 std::make_unique<RooDataSet>(name.c_str(), name.c_str(), allVars, RooFit::Index(*channelCat),
1121 RooFit::Import(datasets), RooFit::WeightVar(*weightVar));
1122 }
1123 } else {
1124 std::stringstream ss;
1125 ss << "RooJSONFactoryWSTool() failed to create dataset " << name << std::endl;
1126 logInputArgumentsError(std::move(ss));
1127 }
1128 }
1129 return dataMap;
1130}
1131
1132///////////////////////////////////////////////////////////////////////////////////////////////////////
1133// exporting data
1135{
1136 RooArgSet observables(*data->get());
1137 auto &output = n[data->GetName()];
1138 output.set_map();
1139
1140 // find category observables
1141 RooAbsCategory *cat = nullptr;
1142 for (const auto &obs : observables) {
1143 if (obs->InheritsFrom(RooAbsCategory::Class())) {
1144 if (cat) {
1145 RooJSONFactoryWSTool::error("dataset '" + std::string(data->GetName()) +
1146 " has several category observables!");
1147 } else {
1148 cat = (RooAbsCategory *)(obs);
1149 }
1150 }
1151 }
1152
1153 if (cat) {
1154 // this is a composite dataset
1155 RooDataSet *ds = (RooDataSet *)(data);
1156 output["index"] << cat->GetName();
1157 std::unique_ptr<TList> dataList{ds->split(*(cat), true)};
1158 if (!dataList) {
1159 RooJSONFactoryWSTool::error("unable to split dataset '" + std::string(ds->GetName()) + "' at '" +
1160 std::string(cat->GetName()) + "'");
1161 }
1162 for (RooAbsData *absData : static_range_cast<RooAbsData *>(*dataList)) {
1163 this->exportData(absData, output);
1164 }
1165 } else if (data->InheritsFrom(RooDataHist::Class())) {
1166 // this is a binned dataset
1167 RooDataHist *dh = (RooDataHist *)(data);
1168 auto &obs = output["observables"];
1169 obs.set_map();
1170 exportVariables(observables, obs);
1171 auto &weights = output["counts"];
1172 weights.set_seq();
1173 for (int i = 0; i < dh->numEntries(); ++i) {
1174 dh->get(i);
1175 weights.append_child() << dh->weight();
1176 }
1177 } else {
1178 // this is a regular unbinned dataset
1179 RooDataSet *ds = (RooDataSet *)(data);
1180
1181 bool singlePoint = (ds->numEntries() <= 1);
1182 RooArgSet reduced_obs;
1184 if (!singlePoint) {
1185 std::map<RooRealVar *, std::vector<double>> obs_values;
1186 for (int i = 0; i < ds->numEntries(); ++i) {
1187 ds->get(i);
1188 for (const auto &obs : observables) {
1189 RooRealVar *rv = (RooRealVar *)(obs);
1190 obs_values[rv].push_back(rv->getVal());
1191 }
1192 }
1193 for (auto &obs_it : obs_values) {
1194 auto &vals = obs_it.second;
1195 double v0 = vals[0];
1196 bool is_const_val = std::all_of(vals.begin(), vals.end(), [v0](double v) { return v == v0; });
1197 if (!is_const_val)
1198 reduced_obs.add(*(obs_it.first), true);
1199 }
1200 }
1201 } else {
1202 reduced_obs.add(observables);
1203 }
1204 if (reduced_obs.size() > 0) {
1205 auto &obsset = output["observables"];
1206 obsset.set_map();
1207 exportVariables(reduced_obs, obsset);
1208 }
1209 auto &weights = singlePoint && Config::stripObservables ? output["counts"] : output["weights"];
1210 weights.set_seq();
1211 for (int i = 0; i < ds->numEntries(); ++i) {
1212 ds->get(i);
1213 if (!(Config::stripObservables && singlePoint)) {
1214 auto &coordinates = output["coordinates"];
1215 coordinates.set_seq();
1216 auto &point = coordinates.append_child();
1217 point.set_seq();
1218 for (const auto &obs : reduced_obs) {
1219 RooRealVar *rv = (RooRealVar *)(obs);
1220 point.append_child() << rv->getVal();
1221 }
1222 }
1223 weights.append_child() << ds->weight();
1224 }
1225 }
1226}
1227
1228///////////////////////////////////////////////////////////////////////////////////////////////////////
1229// create several observables
1230void RooJSONFactoryWSTool::getObservables(const JSONNode &n, const std::string &obsnamecomp, RooArgSet &out)
1231{
1232 if (!_scope.observables.empty()) {
1233 out.add(_scope.observables.begin(), _scope.observables.end());
1234 return;
1235 }
1236 auto vars = readObservables(n, obsnamecomp);
1237 for (auto v : vars) {
1238 std::string name(v.first);
1239 if (_workspace->var(name.c_str())) {
1240 out.add(*(_workspace->var(name.c_str())));
1241 } else {
1243 }
1244 }
1245}
1246
1248{
1249 for (auto *arg : args) {
1250 _scope.observables.push_back(arg);
1251 }
1252}
1254{
1255 this->_scope.objects[name] = obj;
1256}
1258{
1259 return this->_scope.objects[name];
1260}
1262{
1263 this->_scope.objects.clear();
1264 this->_scope.observables.clear();
1265}
1266
1267///////////////////////////////////////////////////////////////////////////////////////////////////////
1268// create an observable
1270{
1271 this->_workspace->factory(TString::Format("%s[%f]", name.c_str(), var.min));
1272 RooRealVar *rrv = this->_workspace->var(name.c_str());
1273 rrv->setMin(var.min);
1274 rrv->setMax(var.max);
1275 rrv->setConstant(true);
1276 rrv->setBins(var.nbins);
1277 rrv->setAttribute("observable");
1278 return rrv;
1279}
1280
1281///////////////////////////////////////////////////////////////////////////////////////////////////////
1282// reading binned data
1283std::unique_ptr<RooDataHist>
1284RooJSONFactoryWSTool::readBinnedData(const JSONNode &n, const std::string &namecomp, RooArgList varlist)
1285{
1286 if (!n.is_map())
1287 RooJSONFactoryWSTool::error("data is not a map");
1288 if (varlist.size() == 0) {
1289 std::string obsname = "obs_x_" + namecomp;
1290 varlist.add(*(this->_workspace->factory((obsname + "[0.]").c_str())));
1291 }
1292 auto bins = RooJSONFactoryWSTool::generateBinIndices(varlist);
1293 if (!n.has_child("counts"))
1294 RooJSONFactoryWSTool::error("no counts given");
1295 if (!n["counts"].is_seq())
1296 RooJSONFactoryWSTool::error("counts are not in list form");
1297 auto &counts = n["counts"];
1298 if (counts.num_children() != bins.size())
1299 RooJSONFactoryWSTool::error(TString::Format("inconsistent bin numbers: counts=%d, bins=%d",
1300 (int)counts.num_children(), (int)(bins.size())));
1301 auto dh = std::make_unique<RooDataHist>(("dataHist_" + namecomp).c_str(), namecomp.c_str(), varlist);
1302 // temporarily disable dirty flag propagation when filling the RDH
1303 std::vector<double> initVals;
1304 for (auto &v : varlist) {
1305 v->setDirtyInhibit(true);
1306 initVals.push_back(((RooRealVar *)v)->getVal());
1307 }
1308 for (size_t ibin = 0; ibin < bins.size(); ++ibin) {
1309 for (size_t i = 0; i < bins[ibin].size(); ++i) {
1310 RooRealVar *v = (RooRealVar *)(varlist.at(i));
1311 v->setBin(bins[ibin][i]);
1312 }
1313 dh->add(varlist, counts[ibin].val_float());
1314 }
1315 // re-enable dirty flag propagation
1316 for (size_t i = 0; i < varlist.size(); ++i) {
1317 RooRealVar *v = (RooRealVar *)(varlist.at(i));
1318 v->setVal(initVals[i]);
1319 v->setDirtyInhibit(false);
1320 }
1321 return dh;
1322}
1323
1324///////////////////////////////////////////////////////////////////////////////////////////////////////
1325// read observables
1326std::map<std::string, RooJSONFactoryWSTool::Var>
1327RooJSONFactoryWSTool::readObservables(const JSONNode &n, const std::string &obsnamecomp)
1328{
1329 std::map<std::string, RooJSONFactoryWSTool::Var> vars;
1330 if (!n.is_map())
1331 return vars;
1332 if (n.has_child("observables")) {
1333 auto &observables = n["observables"];
1334 if (!observables.is_map())
1335 return vars;
1336 if (observables.has_child("nbins")) {
1337 vars.emplace(std::make_pair("obs_x_" + obsnamecomp, RooJSONFactoryWSTool::Var(observables)));
1338 } else {
1339 for (const auto &p : observables.children()) {
1340 vars.emplace(std::make_pair(RooJSONFactoryWSTool::name(p), RooJSONFactoryWSTool::Var(p)));
1341 }
1342 }
1343 } else {
1344 vars.emplace(std::make_pair("obs_x_" + obsnamecomp, RooJSONFactoryWSTool::Var(n["counts"].num_children())));
1345 }
1346 return vars;
1347}
1348
1349///////////////////////////////////////////////////////////////////////////////////////////////////////
1350// importing pdfs
1352{
1353 // import a list of RooAbsPdf objects
1354 if (!n.is_map())
1355 return;
1356 for (const auto &p : n.children()) {
1357 this->importFunction(p, true);
1358 }
1359}
1360
1361///////////////////////////////////////////////////////////////////////////////////////////////////////
1362// configure a pdf as "toplevel" by creating a modelconfig for it
1364{
1365 // if this is a toplevel pdf, also create a modelConfig for it
1366 std::string mcname = "ModelConfig";
1367 if (p.has_child("dict")) {
1368 if (p["dict"].has_child("ModelConfig")) {
1369 mcname = p["dict"]["ModelConfig"].val();
1370 }
1371 }
1372 {
1373 RooStats::ModelConfig mc{mcname.c_str(), pdf.GetName()};
1374 this->_workspace->import(mc);
1375 }
1376 RooStats::ModelConfig *inwsmc = dynamic_cast<RooStats::ModelConfig *>(this->_workspace->obj(mcname.c_str()));
1377 if (inwsmc) {
1378 inwsmc->SetWS(*(this->_workspace));
1379 inwsmc->SetPdf(pdf);
1380 RooArgSet observables;
1381 RooArgSet nps;
1382 RooArgSet pois;
1383 RooArgSet globs;
1384 std::unique_ptr<RooArgSet> pdfVars{pdf.getVariables()};
1385 for (auto &var : this->_workspace->allVars()) {
1386 if (!pdfVars->find(*var))
1387 continue;
1388 if (var->getAttribute("observable")) {
1389 observables.add(*var, true);
1390 }
1391 if (var->getAttribute("np")) {
1392 nps.add(*var, true);
1393 }
1394 if (var->getAttribute("poi")) {
1395 pois.add(*var, true);
1396 }
1397 if (var->getAttribute("glob")) {
1398 globs.add(*var, true);
1399 }
1400 }
1401 inwsmc->SetObservables(observables);
1402 inwsmc->SetParametersOfInterest(pois);
1403 inwsmc->SetNuisanceParameters(nps);
1404 inwsmc->SetGlobalObservables(globs);
1405 } else {
1406 std::stringstream ss;
1407 ss << "RooJSONFactoryWSTool() object '" << mcname << "' in workspace is not of type RooStats::ModelConfig!"
1408 << std::endl;
1409 logInputArgumentsError(std::move(ss));
1410 }
1411}
1412
1413///////////////////////////////////////////////////////////////////////////////////////////////////////
1414// importing variables
1416{
1417 // import a list of RooRealVar objects
1418 if (!n.is_map())
1419 return;
1420 for (const auto &p : n.children()) {
1421 importVariable(p);
1422 }
1423}
1424
1425///////////////////////////////////////////////////////////////////////////////////////////////////////
1426// importing variable
1428{
1429 // import a RooRealVar object
1430 std::string name(RooJSONFactoryWSTool::name(p));
1431 if (this->_workspace->var(name.c_str()))
1432 return;
1433 if (!p.is_map()) {
1434 std::stringstream ss;
1435 ss << "RooJSONFactoryWSTool() node '" << name << "' is not a map, skipping." << std::endl;
1436 logInputArgumentsError(std::move(ss));
1437 return;
1438 }
1439 RooRealVar v(name.c_str(), name.c_str(), 1.);
1440 configureVariable(p, v);
1441 ::importAttributes(&v, p);
1443}
1444
1445///////////////////////////////////////////////////////////////////////////////////////////////////////
1446// configuring variable
1448{
1449 if (p.has_child("value"))
1450 v.setVal(p["value"].val_float());
1451 if (p.has_child("min"))
1452 v.setMin(p["min"].val_float());
1453 if (p.has_child("max"))
1454 v.setMax(p["max"].val_float());
1455 if (p.has_child("nbins"))
1456 v.setBins(p["nbins"].val_int());
1457 if (p.has_child("relErr"))
1458 v.setError(v.getVal() * p["relErr"].val_float());
1459 if (p.has_child("err"))
1460 v.setError(p["err"].val_float());
1461 if (p.has_child("const"))
1462 v.setConstant(p["const"].val_bool());
1463 else
1464 v.setConstant(false);
1465}
1466
1467///////////////////////////////////////////////////////////////////////////////////////////////////////
1468// export all dependants (servers) of a RooAbsArg
1470{
1471 if (n) {
1472 this->exportDependants(source, *n);
1473 } else {
1475 "cannot export dependents without a valid root node, only call within the context of 'exportAllObjects'");
1476 }
1477}
1478
1480{
1481 // export all the servers of a given RooAbsArg
1482 auto servers(source->servers());
1483 for (auto s : servers) {
1484 auto &container = n[containerName(s)];
1485 container.set_map();
1486 this->exportObject(s, container);
1487 }
1488}
1489
1490///////////////////////////////////////////////////////////////////////////////////////////////////////
1491// import all dependants (servers) of a node
1493{
1494 // import all the dependants of an object
1495 if (n.has_child("variables")) {
1496 this->importVariables(n["variables"]);
1497 }
1498 if (n.has_child("functions")) {
1499 this->importFunctions(n["functions"]);
1500 }
1501 if (n.has_child("pdfs")) {
1502 this->importPdfs(n["pdfs"]);
1503 }
1504}
1505
1507{
1508 std::stringstream ss;
1509 if (n.is_container() && n.has_child("name")) {
1510 ss << n["name"].val();
1511 } else if (n.has_key()) {
1512 ss << n.key();
1513 } else {
1514 ss << n.val();
1515 }
1516 return ss.str();
1517}
1518
1520{
1521 // export all ModelConfig objects and attached Pdfs
1522 std::vector<RooStats::ModelConfig *> mcs;
1523 std::vector<RooAbsPdf *> toplevel;
1524 this->_rootnode_output = &n;
1525 for (auto obj : this->_workspace->allGenericObjects()) {
1526 if (obj->InheritsFrom(RooStats::ModelConfig::Class())) {
1527 RooStats::ModelConfig *mc = static_cast<RooStats::ModelConfig *>(obj);
1528 auto &vars = n["variables"];
1529 vars.set_map();
1530 if (mc->GetObservables()) {
1531 for (auto obs : *(mc->GetObservables())) {
1532 RooRealVar *v = dynamic_cast<RooRealVar *>(obs);
1533 if (v) {
1534 exportVariable(v, vars);
1535 auto &tags = vars[v->GetName()]["tags"];
1536 tags.set_seq();
1537 RooJSONFactoryWSTool::append(tags, "observable");
1538 }
1539 }
1540 }
1541 if (mc->GetParametersOfInterest()) {
1542 for (auto poi : *(mc->GetParametersOfInterest())) {
1543 RooRealVar *v = dynamic_cast<RooRealVar *>(poi);
1544 if (v) {
1545 exportVariable(v, vars);
1546 auto &tags = vars[v->GetName()]["tags"];
1547 tags.set_seq();
1548 RooJSONFactoryWSTool::append(tags, "poi");
1549 }
1550 }
1551 }
1552 if (mc->GetNuisanceParameters()) {
1553 for (auto np : *(mc->GetNuisanceParameters())) {
1554 RooRealVar *v = dynamic_cast<RooRealVar *>(np);
1555 if (v) {
1556 exportVariable(v, vars);
1557 auto &tags = vars[v->GetName()]["tags"];
1558 tags.set_seq();
1559 RooJSONFactoryWSTool::append(tags, "np");
1560 }
1561 }
1562 }
1563 if (mc->GetGlobalObservables()) {
1564 for (auto *np : *mc->GetGlobalObservables()) {
1565 if (auto *v = dynamic_cast<RooRealVar *>(np)) {
1566 exportVariable(v, vars);
1567 auto &tags = vars[v->GetName()]["tags"];
1568 tags.set_seq();
1569 RooJSONFactoryWSTool::append(tags, "glob");
1570 }
1571 }
1572 }
1573 mcs.push_back(mc);
1574 }
1575 }
1576 for (auto pdf : this->_workspace->allPdfs()) {
1577 if (!pdf->hasClients() || pdf->getAttribute("toplevel")) {
1578 bool hasMC = false;
1579 for (const auto &mc : mcs) {
1580 if (mc->GetPdf() == pdf)
1581 hasMC = true;
1582 }
1583 if (!hasMC)
1584 toplevel.push_back(static_cast<RooAbsPdf *>(pdf));
1585 }
1586 }
1587 for (auto d : this->_workspace->allData()) {
1588 auto &data = n["data"];
1589 data.set_map();
1590 this->exportData(d, data);
1591 }
1592 for (const auto *snsh_obj : this->_workspace->getSnapshots()) {
1593 const RooArgSet *snsh = static_cast<const RooArgSet *>(snsh_obj);
1594 auto &snapshots = n["snapshots"];
1595 snapshots.set_map();
1596 auto &coll = snapshots[snsh->GetName()];
1597 coll.set_map();
1598 this->exportVariables(*snsh, coll);
1599 }
1600 for (const auto &mc : mcs) {
1601 auto &pdfs = n["pdfs"];
1602 pdfs.set_map();
1603 RooAbsPdf *pdf = mc->GetPdf();
1605 auto &node = pdfs[pdf->GetName()];
1606 node.set_map();
1607 auto &tags = node["tags"];
1608 tags.set_seq();
1609 if (!pdf->getAttribute("toplevel"))
1610 RooJSONFactoryWSTool::append(tags, "toplevel");
1611 auto &dict = node["dict"];
1612 dict.set_map();
1613 dict["ModelConfig"] << mc->GetName();
1614 }
1615 for (const auto &pdf : toplevel) {
1616 auto &pdfs = n["pdfs"];
1617 pdfs.set_map();
1619 auto &node = pdfs[pdf->GetName()];
1620 node.set_map();
1621 auto &tags = node["tags"];
1622 tags.set_seq();
1623 if (!pdf->getAttribute("toplevel"))
1624 RooJSONFactoryWSTool::append(tags, "toplevel");
1625 auto &dict = node["dict"];
1626 dict.set_map();
1627 if (toplevel.size() + mcs.size() == 1) {
1628 dict["ModelConfig"] << "ModelConfig";
1629 } else {
1630 dict["ModelConfig"] << std::string(pdf->GetName()) + "_modelConfig";
1631 }
1632 }
1633 this->_rootnode_output = nullptr;
1634}
1635
1637{
1638 // import the workspace from JSON
1639 std::stringstream ss(s);
1640 return importJSON(ss);
1641}
1642
1644{
1645 // import the workspace from YML
1646 std::stringstream ss(s);
1647 return importYML(ss);
1648}
1649
1651{
1652 // export the workspace to JSON
1653 std::stringstream ss;
1654 exportJSON(ss);
1655 return ss.str();
1656}
1657
1659{
1660 // export the workspace to YML
1661 std::stringstream ss;
1662 exportYML(ss);
1663 return ss.str();
1664}
1665
1667{
1668 // export the workspace in JSON
1669 tree_t p;
1670 JSONNode &n = p.rootnode();
1671 n.set_map();
1672 this->exportAllObjects(n);
1673 n.writeJSON(os);
1674 return true;
1675}
1676bool RooJSONFactoryWSTool::exportJSON(std::string const &filename)
1677{
1678 // export the workspace in JSON
1679 std::ofstream out(filename.c_str());
1680 if (!out.is_open()) {
1681 std::stringstream ss;
1682 ss << "RooJSONFactoryWSTool() invalid output file '" << filename << "'." << std::endl;
1683 logInputArgumentsError(std::move(ss));
1684 return false;
1685 }
1686 return this->exportJSON(out);
1687}
1688
1690{
1691 // export the workspace in YML
1692 tree_t p;
1693 JSONNode &n = p.rootnode();
1694 n.set_map();
1695 this->exportAllObjects(n);
1696 n.writeYML(os);
1697 return true;
1698}
1699bool RooJSONFactoryWSTool::exportYML(std::string const &filename)
1700{
1701 // export the workspace in YML
1702 std::ofstream out(filename.c_str());
1703 if (!out.is_open()) {
1704 std::stringstream ss;
1705 ss << "RooJSONFactoryWSTool() invalid output file '" << filename << "'." << std::endl;
1706 logInputArgumentsError(std::move(ss));
1707 return false;
1708 }
1709 return this->exportYML(out);
1710}
1711
1713{
1714 this->_rootnode_input = &n;
1715 gROOT->ProcessLine("using namespace RooStats::HistFactory;");
1716 this->importDependants(n);
1717
1718 if (n.has_child("data")) {
1719 auto data = this->loadData(n["data"]);
1720 for (const auto &d : data) {
1721 this->_workspace->import(*d.second);
1722 }
1723 }
1724
1725 this->_workspace->saveSnapshot("fromJSON", this->_workspace->allVars());
1726 if (n.has_child("snapshots")) {
1727 for (const auto &snsh : n["snapshots"].children()) {
1728 std::string name = RooJSONFactoryWSTool::name(snsh);
1729 if (name == "fromJSON")
1730 continue;
1731 RooArgSet vars;
1732 for (const auto &var : snsh.children()) {
1733 std::string vname = RooJSONFactoryWSTool::name(var);
1734 RooRealVar *rrv = this->_workspace->var(vname.c_str());
1735 if (!rrv)
1736 continue;
1737 this->configureVariable(var, *rrv);
1738 vars.add(*rrv);
1739 }
1740 this->_workspace->saveSnapshot(name.c_str(), vars);
1741 }
1742 }
1743 this->_workspace->loadSnapshot("fromJSON");
1744
1745 this->_rootnode_input = nullptr;
1746}
1747
1749{
1750 // import a JSON file to the workspace
1751 try {
1752 tree_t p(is);
1753 this->importAllNodes(p.rootnode());
1754 } catch (const std::exception &ex) {
1755 std::cerr << "unable to import JSON: " << ex.what() << std::endl;
1756 return false;
1757 }
1758 return true;
1759}
1760
1761bool RooJSONFactoryWSTool::importJSON(std::string const &filename)
1762{
1763 // import a JSON file to the workspace
1764 std::ifstream infile(filename.c_str());
1765 if (!infile.is_open()) {
1766 std::stringstream ss;
1767 ss << "RooJSONFactoryWSTool() invalid input file '" << filename << "'." << std::endl;
1768 logInputArgumentsError(std::move(ss));
1769 return false;
1770 }
1771 return this->importJSON(infile);
1772}
1773
1775{
1776 // import a YML file to the workspace
1777 try {
1778 tree_t p(is);
1779 this->importAllNodes(p.rootnode());
1780 } catch (const std::exception &ex) {
1781 std::cerr << "unable to import JSON: " << ex.what() << std::endl;
1782 return false;
1783 }
1784 return true;
1785}
1786bool RooJSONFactoryWSTool::importYML(std::string const &filename)
1787{
1788 // import a YML file to the workspace
1789 std::ifstream infile(filename.c_str());
1790 if (!infile.is_open()) {
1791 std::stringstream ss;
1792 ss << "RooJSONFactoryWSTool() invalid input file '" << filename << "'." << std::endl;
1793 logInputArgumentsError(std::move(ss));
1794 return false;
1795 }
1796 return this->importYML(infile);
1797}
1798
1799std::ostream &RooJSONFactoryWSTool::log(int level) const
1800{
1801 return RooMsgService::instance().log(static_cast<TObject *>(nullptr), static_cast<RooFit::MsgLevel>(level),
1802 RooFit::IO);
1803}
1804
1806{
1807 static ImportMap _importers;
1808 return _importers;
1809}
1810
1812{
1813 static ExportMap _exporters;
1814 return _exporters;
1815}
1816
1818{
1819 static ImportExpressionMap _pdfFactoryExpressions;
1820 return _pdfFactoryExpressions;
1821}
1822
1824{
1825 static ImportExpressionMap _funcFactoryExpressions;
1826 return _funcFactoryExpressions;
1827}
1828
1830{
1831 static ExportKeysMap _exportKeys;
1832 return _exportKeys;
1833}
ROOT::R::TRInterface & r
Definition Object.C:4
#define d(i)
Definition RSha256.hxx:102
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
TJSONTree tree_t
#define oocoutE(o, a)
char name[80]
Definition TGX11.cxx:110
#define gROOT
Definition TROOT.h:404
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:69
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
void setAttribute(const Text_t *name, Bool_t value=kTRUE)
Set (default) or clear a named boolean attribute of this object.
const std::set< std::string > & attributes() const
Definition RooAbsArg.h:356
RooArgSet * getVariables(Bool_t stripDisconnected=kTRUE) const
Return RooArgSet with all variables (tree leaf nodes of expresssion tree)
const RefCountList_t & servers() const
List of all servers of this object.
Definition RooAbsArg.h:196
const std::map< std::string, std::string > & stringAttributes() const
Definition RooAbsArg.h:363
Int_t numProxies() const
Return the number of registered proxies.
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
RooAbsProxy * getProxy(Int_t index) const
Return the nth proxy from the proxy list.
Bool_t isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:377
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Storage_t::size_type size() const
const char * GetName() const
Returns name of object.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:82
virtual const RooArgSet * get() const
Definition RooAbsData.h:128
virtual TList * split(const RooAbsCategory &splitCat, Bool_t createEmptyDataSets=kFALSE) const
Split dataset into subsets based on states of given splitCat in this dataset.
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
RooAbsProxy is the abstact interface for proxy classes.
Definition RooAbsProxy.h:30
virtual const char * name() const
Definition RooAbsProxy.h:40
virtual Double_t getMax(const char *name=0) const
Get maximum of currently defined range.
virtual void setBin(Int_t ibin, const char *rangeName=0)
Set value to center of bin 'ibin' of binning 'rangeName' (or of default binning if no range is specif...
virtual Int_t numBins(const char *rangeName=0) const
void setConstant(Bool_t value=kTRUE)
virtual Double_t getMin(const char *name=0) const
Get miniminum of currently defined range.
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:64
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:94
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:35
RooCategory is an object to represent discrete states.
Definition RooCategory.h:27
RooConstVar represent a constant real-valued object.
Definition RooConstVar.h:26
The RooDataHist is a container class to hold N-dimensional binned data.
Definition RooDataHist.h:45
double weight(std::size_t i) const
Return weight of i-th bin.
Int_t numEntries() const override
Return the number of bins.
const RooArgSet * get() const override
Get bin centre of current bin.
Definition RooDataHist.h:84
RooDataSet is a container class to hold unbinned data.
Definition RooDataSet.h:36
virtual const RooArgSet * get(Int_t index) const override
Return RooArgSet with coordinates of event 'index'.
virtual Double_t weight() const override
Return event weight of current event.
virtual std::string val() const =0
virtual bool has_child(std::string const &) const =0
virtual size_t num_children() const =0
virtual bool is_seq() const =0
virtual float val_float() const
virtual JSONNode & append_child()=0
virtual children_view children()
virtual bool is_map() const =0
When using RooFit, statistical models can be conveniently handled and stored as a RooWorkspace.
void exportAttributes(const RooAbsArg *arg, RooFit::Experimental::JSONNode &n)
void exportData(RooAbsData *data, RooFit::Experimental::JSONNode &n)
void append(RooFit::Experimental::JSONNode &n, const std::string &elem)
void importVariables(const RooFit::Experimental::JSONNode &n)
std::map< TClass const *, std::vector< std::unique_ptr< const Exporter > > > ExportMap
bool importYML(std::string const &filename)
static void exportHistogram(const TH1 &h, RooFit::Experimental::JSONNode &n, const std::vector< std::string > &obsnames, const TH1 *errH=0, bool writeObservables=true, bool writeErrors=true)
std::map< TClass const *, ExportKeys > ExportKeysMap
T * request(const std::string &objname, const std::string &requestAuthor)
std::ostream & log(int level) const
static void loadExportKeys(const std::string &fname)
void importAllNodes(const RooFit::Experimental::JSONNode &n)
void configureVariable(const RooFit::Experimental::JSONNode &p, RooRealVar &v)
bool importJSON(std::string const &filename)
void configureToplevelPdf(const RooFit::Experimental::JSONNode &n, RooAbsPdf &pdf)
void exportVariable(const RooAbsReal *v, RooFit::Experimental::JSONNode &n)
std::map< const std::string, ImportExpression > ImportExpressionMap
static void loadFactoryExpressions(const std::string &fname)
void importVariable(const RooFit::Experimental::JSONNode &n)
RooAbsArg * getScopeObject(const std::string &name)
static ImportMap const & importers()
static int removeExporters(const std::string &needle)
void setScopeObject(const std::string &key, RooAbsArg *obj)
bool find(const RooFit::Experimental::JSONNode &n, const std::string &elem)
bool importYMLfromString(const std::string &s)
const RooFit::Experimental::JSONNode * _rootnode_input
void importPdfs(const RooFit::Experimental::JSONNode &n)
const RooFit::Experimental::JSONNode & irootnode() const
static bool registerExporter(const TClass *key, bool topPriority=true)
static std::string genPrefix(const RooFit::Experimental::JSONNode &p, bool trailing_underscore)
RooRealVar * getWeightVar(const char *name)
static int removeImporters(const std::string &needle)
void exportObject(const RooAbsArg *func, RooFit::Experimental::JSONNode &n)
static ExportMap const & exporters()
static std::string name(const RooFit::Experimental::JSONNode &n)
void exportFunctions(const RooArgSet &allElems, RooFit::Experimental::JSONNode &n)
std::unique_ptr< RooDataSet > unbinned(RooDataHist const &hist)
std::map< std::string, std::unique_ptr< RooAbsData > > loadData(const RooFit::Experimental::JSONNode &n)
void exportAllObjects(RooFit::Experimental::JSONNode &n)
std::map< const std::string, std::vector< std::unique_ptr< const Importer > > > ImportMap
static ImportMap & staticImporters()
void exportVariables(const RooArgSet &allElems, RooFit::Experimental::JSONNode &n)
RooFit::Experimental::JSONNode * _rootnode_output
void exportDependants(const RooAbsArg *source, RooFit::Experimental::JSONNode &n)
static std::vector< std::vector< int > > generateBinIndices(const RooArgList &vars)
RooRealVar * createObservable(const std::string &name, const RooJSONFactoryWSTool::Var &var)
static std::map< std::string, RooJSONFactoryWSTool::Var > readObservables(const RooFit::Experimental::JSONNode &n, const std::string &obsnamecomp)
static ExportKeysMap const & exportKeys()
bool exportYML(std::string const &fileName)
static ImportExpressionMap & staticFunctionImportExpressions()
RooFit::Experimental::JSONNode & orootnode()
void importFunctions(const RooFit::Experimental::JSONNode &n)
std::unique_ptr< RooDataHist > readBinnedData(const RooFit::Experimental::JSONNode &n, const std::string &namecomp, RooArgList observables)
static void writeObservables(const TH1 &h, RooFit::Experimental::JSONNode &n, const std::vector< std::string > &varnames)
bool importJSONfromString(const std::string &s)
static ExportKeysMap & staticExportKeys()
void importDependants(const RooFit::Experimental::JSONNode &n)
static ImportExpressionMap & staticPdfImportExpressions()
static ExportMap & staticExporters()
void getObservables(const RooFit::Experimental::JSONNode &n, const std::string &obsnamecomp, RooArgSet &out)
bool exportJSON(std::string const &fileName)
static bool registerImporter(const std::string &key, bool topPriority=true)
void setScopeObservables(const RooArgList &args)
static void error(const char *s)
void importFunction(const RooFit::Experimental::JSONNode &n, bool isPdf)
RooListProxy is the concrete proxy for RooArgList objects.
static RooMsgService & instance()
Return reference to singleton instance.
std::ostream & log(const RooAbsArg *self, RooFit::MsgLevel level, RooFit::MsgTopic facility, Bool_t forceSkipPrefix=kFALSE)
Log error message associated with RooAbsArg object self at given level and topic.
RooRealVar represents a variable that can be changed from the outside.
Definition RooRealVar.h:39
void setMin(const char *name, Double_t value)
Set minimum of name range to given value.
void setBins(Int_t nBins, const char *name=0)
Create a uniform binning under name 'name' for this variable.
void setMax(const char *name, Double_t value)
Set maximum of name range to given value.
virtual void setVal(Double_t value)
Set value of variable to 'value'.
ModelConfig is a simple class that holds configuration information specifying how a model should be u...
Definition ModelConfig.h:30
virtual void SetObservables(const RooArgSet &set)
Specify the observables.
const RooArgSet * GetGlobalObservables() const
get RooArgSet for global observables (return NULL if not existing)
virtual void SetParametersOfInterest(const RooArgSet &set)
Specify parameters of interest.
const RooArgSet * GetParametersOfInterest() const
get RooArgSet containing the parameter of interest (return NULL if not existing)
const RooArgSet * GetNuisanceParameters() const
get RooArgSet containing the nuisance parameters (return NULL if not existing)
virtual void SetGlobalObservables(const RooArgSet &set)
Specify the global observables.
virtual void SetWS(RooWorkspace &ws) override
Set a workspace that owns all the necessary components for the analysis.
const RooArgSet * GetObservables() const
get RooArgSet for observables (return NULL if not existing)
virtual void SetNuisanceParameters(const RooArgSet &set)
Specify the nuisance parameters (parameters that are not POI).
virtual void SetPdf(const RooAbsPdf &pdf)
Set the Pdf, add to the the workspace if not already there.
Definition ModelConfig.h:81
RooAbsData * data(const char *name) const
Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found.
std::list< RooAbsData * > allData() const
Return list of all dataset in the workspace.
RooArgSet allVars() const
Return set with all variable objects.
Bool_t import(const RooAbsArg &arg, const RooCmdArg &arg1=RooCmdArg(), const RooCmdArg &arg2=RooCmdArg(), const RooCmdArg &arg3=RooCmdArg(), const RooCmdArg &arg4=RooCmdArg(), const RooCmdArg &arg5=RooCmdArg(), const RooCmdArg &arg6=RooCmdArg(), const RooCmdArg &arg7=RooCmdArg(), const RooCmdArg &arg8=RooCmdArg(), const RooCmdArg &arg9=RooCmdArg())
Import a RooAbsArg object, e.g.
RooAbsReal * function(const char *name) const
Retrieve function (RooAbsReal) with given name. Note that all RooAbsPdfs are also RooAbsReals....
RooCategory * cat(const char *name) const
Retrieve discrete variable (RooCategory) with given name. A null pointer is returned if not found.
RooArgSet allPdfs() const
Return set with all probability density function objects.
std::list< TObject * > allGenericObjects() const
Return list of all generic objects in the workspace.
RooLinkedList const & getSnapshots() const
Bool_t saveSnapshot(const char *name, const char *paramNames)
Save snapshot of values and attributes (including "Constant") of given parameters.
Bool_t loadSnapshot(const char *name)
Load the values and attributes of the parameters in the snapshot saved with the given name.
RooRealVar * var(const char *name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
RooFactoryWSTool & factory()
Return instance to factory tool.
TObject * obj(const char *name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name)
RooAbsPdf * pdf(const char *name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
Class to manage histogram axis.
Definition TAxis.h:30
Bool_t IsVariableBinSize() const
Definition TAxis.h:136
Double_t GetXmax() const
Definition TAxis.h:134
Double_t GetXmin() const
Definition TAxis.h:133
Int_t GetNbins() const
Definition TAxis.h:121
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:528
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:80
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2966
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:4994
virtual Node & rootnode() override
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:429
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:200
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:515
const char * Data() const
Definition TString.h:369
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:2336
RooCmdArg RecycleConflictNodes(Bool_t flag=kTRUE)
RooCmdArg Silence(Bool_t flag=kTRUE)
RooCmdArg WeightVar(const char *name, Bool_t reinterpretAsWeight=kFALSE)
RooCmdArg Index(RooCategory &icat)
RooCmdArg Import(const char *state, TH1 &histo)
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
Definition first.py:1
std::map< std::string, RooAbsArg * > objects
std::vector< RooAbsArg * > observables
std::vector< double > bounds
auto * l
Definition textangle.C:4
static void output(int code)
Definition gifencode.c:226