119std::vector<std::string> valsToStringVec(
JSONNode const &node)
121 std::vector<std::string> out;
124 out.push_back(elem.val());
156 std::vector<double> edges;
162 Var(
int n) : nbins(
n), min(0), max(
n) {}
175bool isNumber(
const std::string &str)
177 bool seen_digit =
false;
178 bool seen_dot =
false;
180 bool after_e =
false;
181 bool sign_allowed =
true;
183 for (
size_t i = 0; i < str.size(); ++i) {
186 if (std::isdigit(
c)) {
188 sign_allowed =
false;
189 }
else if ((
c ==
'+' ||
c ==
'-') && sign_allowed) {
191 sign_allowed =
false;
192 }
else if (
c ==
'.' && !seen_dot && !after_e) {
194 sign_allowed =
false;
195 }
else if ((
c ==
'e' ||
c ==
'E') && seen_digit && !seen_e) {
227 if (
auto n = p.
find(
"value"))
228 v.setVal(
n->val_double());
230 if (
auto n = p.
find(
"nbins"))
231 v.setBins(
n->val_int());
232 if (
auto n = p.
find(
"relErr"))
233 v.setError(
v.getVal() *
n->val_double());
234 if (
auto n = p.
find(
"err"))
235 v.setError(
n->val_double());
236 if (
auto n = p.
find(
"const")) {
237 v.setConstant(
n->val_bool());
239 v.setConstant(
false);
245 auto paramPointsNode = rootNode.
find(
"parameter_points");
246 if (!paramPointsNode)
251 return &((*out)[
"parameters"]);
254std::string genPrefix(
const JSONNode &p,
bool trailing_underscore)
259 if (
auto node = p.
find(
"namespaces")) {
260 for (
const auto &ns : node->
children()) {
266 if (trailing_underscore && !prefix.empty())
272void genIndicesHelper(std::vector<std::vector<int>> &combinations, std::vector<int> &curr_comb,
273 const std::vector<int> &vars_numbins,
size_t curridx)
275 if (curridx == vars_numbins.size()) {
277 combinations.emplace_back(curr_comb);
279 for (
int i = 0; i < vars_numbins[curridx]; ++i) {
280 curr_comb[curridx] = i;
281 ::genIndicesHelper(combinations, curr_comb, vars_numbins, curridx + 1);
298 if (
auto seq = node.
find(
"dict")) {
299 for (
const auto &
attr : seq->children()) {
303 if (
auto seq = node.
find(
"tags")) {
304 for (
const auto &
attr : seq->children()) {
313 std::stringstream expression;
314 std::string classname(
ex.tclass->GetName());
315 size_t colon = classname.find_last_of(
':');
316 expression << (colon < classname.size() ? classname.substr(colon + 1) : classname);
319 for (
auto k :
ex.arguments) {
320 expression << (first ?
"::" +
name +
"(" :
",");
322 if (k ==
"true" || k ==
"false") {
323 expression << (k ==
"true" ?
"1" :
"0");
325 std::stringstream errMsg;
326 errMsg <<
"node '" <<
name <<
"' is missing key '" << k <<
"'";
328 }
else if (p[k].is_seq()) {
329 bool firstInner =
true;
332 expression << (firstInner ?
"" :
",") << arg->
GetName();
338 expression << p[k].val();
342 return expression.str();
355std::vector<std::vector<int>> generateBinIndices(
const RooArgSet &vars)
357 std::vector<std::vector<int>> combinations;
358 std::vector<int> vars_numbins;
359 vars_numbins.reserve(vars.
size());
361 vars_numbins.push_back(absv->getBins());
363 std::vector<int> curr_comb(vars.
size());
364 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
368template <
typename... Keys_t>
369JSONNode const *findRooFitInternal(
JSONNode const &node, Keys_t
const &...keys)
371 return node.
find(
"misc",
"ROOT_internal", keys...);
383bool isLiteralConstVar(
RooAbsArg const &arg)
385 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(&arg);
386 return isRooConstVar && isNumber(arg.
GetName());
401 if (isLiteralConstVar(*arg)) {
407 auto initializeNode = [&]() {
425 if (it.first ==
"factory_tag" || it.first ==
"PROD_TERM_TYPE")
428 (*node)[
"dict"].set_map()[it.first] << it.second;
434 if (
attr ==
"SnapShot_ExtRefClone" ||
attr ==
"RooRealConstant_Factory_Object")
437 (*node)[
"tags"].set_seq().append_child() <<
attr;
457 for (
const auto &p : node[
"axes"].children()) {
462 std::stringstream errMsg;
463 errMsg <<
"The observable \"" <<
name <<
"\" could not be found in the workspace!";
486 std::string
const &
type = p[
"type"].
val();
487 if (
type ==
"binned") {
490 }
else if (
type ==
"unbinned") {
493 getObservables(workspace, p, varlist);
496 auto &coords = p[
"entries"];
497 if (!coords.is_seq()) {
500 std::vector<double> weightVals;
502 auto &weights = p[
"weights"];
503 if (coords.num_children() != weights.num_children()) {
506 for (
auto const &weight : weights.children()) {
507 weightVals.push_back(weight.val_double());
511 for (
auto const &point : coords.children()) {
512 if (!point.is_seq()) {
513 std::stringstream errMsg;
514 errMsg <<
"coordinate point '" << i <<
"' is not a list!";
517 if (point.num_children() != varlist.
size()) {
521 for (
auto const &pointj : point.children()) {
523 v->setVal(pointj.val_double());
526 if (weightVals.size() > 0) {
527 data->add(vars, weightVals[i]);
536 std::stringstream ss;
537 ss <<
"RooJSONFactoryWSTool() failed to create dataset " <<
name << std::endl;
559 const std::vector<std::unique_ptr<RooAbsData>> &datasets)
563 JSONNode const *mcAuxNode = findRooFitInternal(rootnode,
"ModelConfigs", analysisName);
565 JSONNode const *mcNameNode = mcAuxNode ? mcAuxNode->
find(
"mcName") :
nullptr;
566 std::string mcname = mcNameNode ? mcNameNode->
val() : analysisName;
567 if (workspace.
obj(mcname))
572 mc->SetWS(workspace);
576 throw std::runtime_error(
"likelihood node not found!");
578 if (!nllNode->has_child(
"distributions")) {
579 throw std::runtime_error(
"likelihood node has no distributions attached!");
581 if (!nllNode->has_child(
"data")) {
582 throw std::runtime_error(
"likelihood node has no data attached!");
584 std::vector<std::string> nllDistNames = valsToStringVec((*nllNode)[
"distributions"]);
586 for (
auto &nameNode : (*nllNode)[
"aux_distributions"].children()) {
587 if (
RooAbsArg *extConstraint = workspace.
arg(nameNode.val())) {
588 extConstraints.
add(*extConstraint);
592 for (
auto &nameNode : (*nllNode)[
"data"].children()) {
594 for (
const auto &
d : datasets) {
595 if (
d->GetName() == nameNode.val()) {
597 observables.
add(*
d->get());
600 if (nameNode.val() !=
"0" && !found)
601 throw std::runtime_error(
"dataset '" + nameNode.val() +
"' cannot be found!");
604 JSONNode const *pdfNameNode = mcAuxNode ? mcAuxNode->
find(
"pdfName") :
nullptr;
605 std::string
const pdfName = pdfNameNode ? pdfNameNode->
val() :
"simPdf";
611 if (nllDistNames.size() == 1) {
613 pdf = workspace.
pdf(nllDistNames[0]);
616 std::string simPdfName = analysisName +
"_simPdf";
617 std::string indexCatName = analysisName +
"_categoryIndex";
618 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
619 std::map<std::string, RooAbsPdf *> pdfMap;
620 for (std::size_t i = 0; i < nllDistNames.size(); ++i) {
621 indexCat.defineType(nllDistNames[i], i);
622 pdfMap[nllDistNames[i]] = workspace.
pdf(nllDistNames[i]);
624 RooSimultaneous simPdf{simPdfName.c_str(), simPdfName.c_str(), pdfMap, indexCat};
632 if (!extConstraints.
empty())
633 mc->SetExternalConstraints(extConstraints);
635 auto readArgSet = [&](std::string
const &
name) {
637 for (
auto const &
child : analysisNode[
name].children()) {
643 mc->SetParametersOfInterest(readArgSet(
"parameters_of_interest"));
644 mc->SetObservables(observables);
655 for (
auto &domain : analysisNode[
"domains"].children()) {
657 if (!thisDomain || !thisDomain->has_child(
"axes"))
659 for (
auto &var : (*thisDomain)[
"axes"].children()) {
662 domainPars.
add(*wsvar);
668 for (
const auto &p : pars) {
669 if (mc->GetParametersOfInterest()->find(*p))
671 if (p->isConstant() && !mainPars.
find(*p) && domainPars.
find(*p)) {
673 }
else if (domainPars.
find(*p)) {
678 mc->SetGlobalObservables(globs);
679 mc->SetNuisanceParameters(nps);
682 if (
auto found = mcAuxNode->
find(
"combined_data_name")) {
688 mc->SetSnapshot(*workspace.
getSnapshot(analysisNode[
"init"].
val().c_str()));
694 auto *combinedPdfInfoNode = findRooFitInternal(rootnode,
"combined_distributions");
697 if (combinedPdfInfoNode ==
nullptr) {
701 for (
auto &info : combinedPdfInfoNode->children()) {
704 std::string combinedName = info.key();
705 std::string indexCatName = info[
"index_cat"].val();
706 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
707 std::vector<int> indices;
708 std::vector<std::string> pdfNames = valsToStringVec(info[
"distributions"]);
709 for (
auto &
n : info[
"indices"].children()) {
710 indices.push_back(
n.val_int());
713 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
714 std::map<std::string, RooAbsPdf *> pdfMap;
716 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
717 indexCat.defineType(labels[iChannel], indices[iChannel]);
718 pdfMap[labels[iChannel]] = ws.
pdf(pdfNames[iChannel]);
721 RooSimultaneous simPdf{combinedName.c_str(), combinedName.c_str(), pdfMap, indexCat};
726void combineDatasets(
const JSONNode &rootnode, std::vector<std::unique_ptr<RooAbsData>> &datasets)
728 auto *combinedDataInfoNode = findRooFitInternal(rootnode,
"combined_datasets");
731 if (combinedDataInfoNode ==
nullptr) {
735 for (
auto &info : combinedDataInfoNode->children()) {
738 std::string combinedName = info.key();
739 std::string indexCatName = info[
"index_cat"].val();
740 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
741 std::vector<int> indices;
742 for (
auto &
n : info[
"indices"].children()) {
743 indices.push_back(
n.val_int());
745 if (indices.size() != labels.size()) {
750 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
751 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
753 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
754 auto componentName = combinedName +
"_" + labels[iChannel];
757 std::unique_ptr<RooAbsData> &component = *std::find_if(
758 datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
761 allVars.add(*component->get());
762 dsMap.insert({labels[iChannel], std::move(component)});
763 indexCat.defineType(labels[iChannel], indices[iChannel]);
766 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
768 datasets.emplace_back(std::move(combined));
773void sortByName(T &coll)
775 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
792 if (isLiteralConstVar(*arg)) {
800 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
812 if (isLiteralConstVar(*arg)) {
820 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
863 if (str.empty() || !(std::isalpha(str[0]) || str[0] ==
'_')) {
870 if (!(std::isalnum(
c) ||
c ==
'_')) {
884 std::stringstream ss;
885 ss <<
"RooJSONFactoryWSTool() name '" <<
name <<
"' is not valid!" << std::endl
886 <<
"Sanitize names by setting RooJSONFactoryWSTool::allowSanitizeNames = True." << std::endl;
904 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
913 if (
const auto &node = vars->find(objname)) {
927 if (
const auto &distributionsNode =
_rootnodeInput->find(
"distributions")) {
942 if (isNumber(objname))
948 if (
const auto &functionNode =
_rootnodeInput->find(
"functions")) {
976 if (cv && strcmp(cv->GetName(),
TString::Format(
"%g", cv->getVal()).Data()) == 0) {
983 var[
"value"] << cv->getVal();
984 var[
"const"] <<
true;
986 var[
"value"] << rrv->getVal();
987 if (rrv->isConstant() && storeConstant) {
988 var[
"const"] << rrv->isConstant();
990 var[
"min"] << rrv->getMin();
991 var[
"max"] << rrv->getMax();
993 if (rrv->getBins() != 100 && storeBins) {
994 var[
"nbins"] << rrv->getBins();
1020 const std::string &formula)
1022 std::string newname = std::string(original->
GetName()) + suffix;
1024 trafo_node[
"type"] <<
"generic_function";
1047 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
1050 exportedObjectNames.insert(
name);
1057 std::vector<std::string> channelNames;
1058 for (
auto const &item : simPdf->indexCat()) {
1059 channelNames.push_back(item.first);
1063 auto &
child = infoNode[simPdf->GetName()].set_map();
1064 child[
"index_cat"] << simPdf->indexCat().GetName();
1066 child[
"distributions"].set_seq();
1067 for (
auto const &item : simPdf->indexCat()) {
1068 child[
"distributions"].append_child() << simPdf->getPdf(item.first.c_str())->GetName();
1080 auto &collectionNode = (*_rootnodeOutput)[
dynamic_cast<RooAbsPdf const *
>(&func) ?
"distributions" :
"functions"];
1089 auto it = exporters.find(cl);
1090 if (it != exporters.end()) {
1091 for (
auto &exp : it->second) {
1094 if (!exp->exportObject(
this, &func, elem)) {
1100 elem[
"name"] <<
name;
1104 if (exp->autoExportDependants()) {
1117 const auto &dict = exportKeys.find(cl);
1118 if (dict == exportKeys.end()) {
1119 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1120 <<
"there are several possible reasons for this:\n"
1121 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1123 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1124 <<
" 3. something is wrong with your setup, e.g. you might have called "
1125 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1126 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1127 <<
"either way, please make sure that:\n"
1128 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1129 "see what is available\n"
1130 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1131 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to "
1132 "see how to do this!\n";
1136 elem[
"type"] << dict->second.type;
1140 for (
size_t i = 0; i < nprox; ++i) {
1146 std::string pname(p->
name());
1147 if (pname[0] ==
'!')
1150 auto k = dict->second.proxies.find(pname);
1151 if (k == dict->second.proxies.end()) {
1152 std::cerr <<
"failed to find key matching proxy '" << pname <<
"' for type '" << dict->second.type
1153 <<
"', encountered in '" << func.
GetName() <<
"', skipping" << std::endl;
1158 if (k->second.empty())
1165 if (isLiteralConstVar(*
r->absArg())) {
1168 elem[k->second] <<
r->absArg()->GetName();
1176 std::cerr <<
"unable to locate server of " << func.
GetName() << std::endl;
1214 std::stringstream ss;
1215 ss <<
"RooJSONFactoryWSTool() function node " +
name +
" is not a map!";
1219 std::string prefix = genPrefix(p,
true);
1220 if (!prefix.empty())
1223 std::stringstream ss;
1224 ss <<
"RooJSONFactoryWSTool() no type given for function '" <<
name <<
"', skipping." << std::endl;
1229 std::string functype(p[
"type"].val());
1232 if (!importAllDependants) {
1237 auto it = importers.find(functype);
1239 if (it != importers.end()) {
1240 for (
auto &imp : it->second) {
1242 ok = imp->importArg(
this, p);
1243 }
catch (
const std::exception &
e) {
1244 std::stringstream ss;
1245 const auto *ptr = imp.get();
1246 ss <<
"RooJSONFactoryWSTool() failed. The importer " <<
typeid(*ptr).name()
1247 <<
" emitted and error: " <<
e.what() << std::endl;
1255 auto expr = factoryExpressions.find(functype);
1256 if (expr != factoryExpressions.end()) {
1257 std::string expression = ::generate(expr->second, p,
this);
1259 std::stringstream ss;
1260 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1261 <<
"', skipping. expression was\n"
1262 << expression << std::endl;
1266 std::stringstream ss;
1267 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1269 <<
"there are several possible reasons for this:\n"
1270 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1271 <<
" 2. " << functype
1272 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1273 <<
" 3. something is wrong with your setup, e.g. you might have called "
1274 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1275 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1276 <<
"either way, please make sure that:\n"
1277 <<
" 3: you are reading a file with factory expressions - call "
1278 "RooFit::JSONIO::printFactoryExpressions() "
1279 "to see what is available\n"
1280 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1281 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to see "
1290 std::stringstream err;
1291 err <<
"something went wrong importing function '" <<
name <<
"'.";
1325 auto &observablesNode = output[
"axes"].
set_seq();
1328 std::string
name = var->GetName();
1331 obsNode[
"name"] <<
name;
1332 if (var->getBinning().isUniform()) {
1333 obsNode[
"min"] << var->getMin();
1334 obsNode[
"max"] << var->getMax();
1335 obsNode[
"nbins"] << var->getBins();
1337 auto &edges = obsNode[
"edges"];
1339 double val = var->getBinning().binLow(0);
1341 for (
int i = 0; i < var->getBinning().numBins(); ++i) {
1342 val = var->getBinning().binHigh(i);
1343 edges.append_child() << val;
1365 for (std::size_t i = 0; i <
n; ++i) {
1366 double w = contents[i];
1388 auto &labels = node[
"labels"].
set_seq();
1389 auto &indices = node[
"indices"].
set_seq();
1391 for (
auto const &item : cat) {
1393 if (std::isalpha(item.first[0])) {
1395 if (label != item.first) {
1396 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << item.first <<
"' to '" << label
1397 <<
"' to become a valid name";
1401 "' to make a valid name!");
1404 labels.append_child() << label;
1405 indices.append_child() << item.second;
1427 " has several category observables!");
1449 auto *combinedPdfInfoNode = findRooFitInternal(*
_rootnodeOutput,
"combined_distributions");
1450 if (combinedPdfInfoNode) {
1451 for (
auto &info : combinedPdfInfoNode->children()) {
1452 if (info[
"index_cat"].val() == cat->
GetName()) {
1462 std::vector<std::unique_ptr<RooAbsData>> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1464 for (std::unique_ptr<RooAbsData>
const &absData : dataList) {
1465 std::string catName(absData->GetName());
1466 std::string dataName;
1467 if (std::isalpha(catName[0])) {
1469 if (dataName != catName) {
1470 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << catName <<
"' to '" << dataName
1471 <<
"' to become a valid name";
1475 "' to make a valid name!");
1478 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1479 datamap.
components[catName] = absData->GetName();
1503 " has several category observables!");
1521 if (
auto weightVar = variables.find(
"weightVar")) {
1522 variables.remove(*weightVar);
1527 output[
"type"] <<
"binned";
1531 return exportHisto(variables, dh->numEntries(), dh->weightArray(), output);
1540 if (
data.isWeighted() && variables.size() == 1) {
1541 bool isBinnedData =
false;
1542 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1543 std::vector<double> contents;
1545 for (; i <
data.numEntries(); ++i) {
1547 if (
x.getBin() != i)
1549 contents.push_back(
data.weight());
1551 if (i ==
x.getBins())
1552 isBinnedData =
true;
1554 output[
"type"] <<
"binned";
1558 return exportHisto(variables,
data.numEntries(), contents.data(), output);
1563 output[
"type"] <<
"unbinned";
1565 auto &coords = output[
"entries"].
set_seq();
1566 std::vector<double> weightVals;
1567 bool hasNonUnityWeights =
false;
1568 for (
int i = 0; i <
data.numEntries(); ++i) {
1570 coords.append_child().fill_seq(variables, [](
auto x) {
return static_cast<RooRealVar *
>(
x)->getVal(); });
1571 std::string datasetName =
data.GetName();
1572 if (
data.isWeighted()) {
1573 weightVals.push_back(
data.weight());
1574 if (
data.weight() != 1.)
1575 hasNonUnityWeights =
true;
1578 if (
data.isWeighted() && hasNonUnityWeights) {
1579 output[
"weights"].
fill_seq(weightVals);
1596 for (
JSONNode const &node : topNode[
"axes"].children()) {
1597 if (node.has_child(
"edges")) {
1598 std::vector<double> edges;
1599 for (
auto const &bound : node[
"edges"].children()) {
1600 edges.push_back(bound.val_double());
1602 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(), edges[0],
1603 edges[edges.size() - 1]);
1604 RooBinning bins(obs->getMin(), obs->getMax());
1605 for (
auto b : edges) {
1608 obs->setBinning(bins);
1611 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(),
1612 node[
"min"].val_double(), node[
"max"].val_double());
1613 obs->setBins(node[
"nbins"].val_int());
1632std::unique_ptr<RooDataHist>
1635 if (!
n.has_child(
"contents"))
1638 JSONNode const &contents =
n[
"contents"];
1644 if (
n.has_child(
"errors")) {
1645 errors = &
n[
"errors"];
1650 auto bins = generateBinIndices(vars);
1652 std::stringstream errMsg;
1653 errMsg <<
"inconsistent bin numbers: contents=" << contents.
num_children() <<
", bins=" << bins.size();
1656 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1657 std::vector<double> contentVals;
1659 for (
auto const &cont : contents.
children()) {
1660 contentVals.push_back(cont.val_double());
1662 std::vector<double> errorVals;
1665 for (
auto const &err : errors->
children()) {
1666 errorVals.push_back(err.val_double());
1669 for (
size_t ibin = 0; ibin < bins.size(); ++ibin) {
1670 const double err = errors ? errorVals[ibin] : -1;
1671 dh->set(ibin, contentVals[ibin], err);
1694 std::stringstream ss;
1695 ss <<
"RooJSONFactoryWSTool() node '" <<
name <<
"' is not a map, skipping.";
1696 oocoutE(
nullptr, InputArguments) << ss.str() << std::endl;
1702 if (attrNode->has_child(
"is_const_var") && (*attrNode)[
"is_const_var"].val_int() == 1) {
1723 if (
JSONNode const *varsNode = getVariablesNode(
n)) {
1724 for (
const auto &p : varsNode->children()) {
1728 if (
auto seq =
n.find(
"functions")) {
1729 for (
const auto &p : seq->children()) {
1733 if (
auto seq =
n.find(
"distributions")) {
1734 for (
const auto &p : seq->children()) {
1741 const std::vector<CombinedData> &combDataSets,
1742 const std::vector<RooAbsData *> &singleDataSets)
1747 for (std::size_t i = 0; i < std::max(combDataSets.size(), std::size_t(1)); ++i) {
1748 const bool hasdata = i < combDataSets.size();
1749 if (hasdata && !matches(combDataSets.at(i), simpdf))
1752 std::string analysisName(simpdf->GetName());
1754 analysisName +=
"_" + combDataSets[i].name;
1761 for (
auto *
data : singleDataSets) {
1763 std::map<std::string, std::string> mapping;
1764 mapping[pdf->GetName()] =
data->GetName();
1769 if (founddata == 0) {
1776 std::string
const &analysisName,
1777 std::map<std::string, std::string>
const *dataComponents)
1783 auto &domains = analysisNode[
"domains"].
set_seq();
1785 analysisNode[
"likelihood"] << analysisName;
1788 nllNode[
"distributions"].set_seq();
1789 nllNode[
"data"].set_seq();
1791 if (dataComponents) {
1794 for (
auto const &item : simPdf->indexCat()) {
1795 const auto &dataComp = dataComponents->find(item.first);
1796 nllNode[
"distributions"].append_child() << simPdf->getPdf(item.first)->GetName();
1797 nllNode[
"data"].append_child() << dataComp->second;
1800 for (
auto it : *dataComponents) {
1801 nllNode[
"distributions"].append_child() << it.first;
1802 nllNode[
"data"].append_child() << it.second;
1806 nllNode[
"distributions"].append_child() << pdf->GetName();
1807 nllNode[
"data"].append_child() << 0;
1811 auto &extConstrNode = nllNode[
"aux_distributions"];
1812 extConstrNode.set_seq();
1814 extConstrNode.append_child() << constr->GetName();
1818 auto writeList = [&](
const char *
name,
RooArgSet const *args) {
1819 if (!args || !args->size())
1822 std::vector<std::string> names;
1823 names.reserve(args->size());
1825 names.push_back(arg->GetName());
1826 std::sort(names.begin(), names.end());
1832 auto &domainsNode = rootnode[
"domains"];
1834 auto writeProductDomain = [&](
const char *suffix,
RooArgSet const *args) {
1835 if (!args || args->empty())
1837 const std::string domainName = analysisName + suffix;
1838 domains.append_child() << domainName;
1850 auto &modelConfigAux =
getRooFitInternal(rootnode,
"ModelConfigs", analysisName);
1851 modelConfigAux.set_map();
1852 modelConfigAux[
"pdfName"] << pdf->GetName();
1853 modelConfigAux[
"mcName"] << mc.
GetName();
1867 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1872 std::vector<RooAbsPdf *> allpdfs;
1874 if (!arg->hasClients()) {
1875 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
1876 allpdfs.push_back(pdf);
1880 sortByName(allpdfs);
1881 std::set<std::string> exportedObjectNames;
1885 std::vector<RooAbsReal *> allfuncs;
1886 for (
auto &arg :
_workspace.allFunctions()) {
1887 if (!arg->hasClients()) {
1888 if (
auto *func =
dynamic_cast<RooAbsReal *
>(arg)) {
1889 allfuncs.push_back(func);
1893 sortByName(allfuncs);
1898 exportAttributes(arg,
n);
1902 std::vector<RooAbsData *> alldata;
1904 alldata.push_back(
d);
1906 sortByName(alldata);
1908 std::vector<RooAbsData *> singleData;
1909 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
1910 for (
auto &
d : alldata) {
1912 if (!
data.components.empty())
1913 combData.push_back(
data);
1915 singleData.push_back(
d);
1918 for (
auto &
d : alldata) {
1935 bool do_export =
false;
1936 for (
const auto &pdf : allpdfs) {
1937 if (pdf->dependsOn(*arg)) {
1943 snapshotSorted.
add(*arg);
1946 snapshotSorted.
sort();
1947 std::string
name(snsh->GetName());
1948 if (
name !=
"default_values") {
1967 std::stringstream ss(s);
1979 std::stringstream ss(s);
1990 std::stringstream ss;
2002 std::stringstream ss;
2017 auto &metadata =
n[
"metadata"].set_map();
2024 std::string versionName =
gROOT->GetVersion();
2027 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
2028 rootInfo[
"version"] << versionName;
2056 std::ofstream out(
filename.c_str());
2057 if (!out.is_open()) {
2058 std::stringstream ss;
2059 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
2089 std::ofstream out(
filename.c_str());
2090 if (!out.is_open()) {
2091 std::stringstream ss;
2092 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
2104 if (
auto seq = attrNode->find(
"tags")) {
2105 for (
auto &
a : seq->children()) {
2106 if (
a.val() == attrib)
2116 auto &tags = (*node)[
"tags"];
2126 if (
auto dict = attrNode->find(
"dict")) {
2127 if (
auto *
a = dict->find(attrib)) {
2135 const std::string &
value)
2138 auto &dict = (*node)[
"dict"];
2140 dict[attrib] <<
value;
2156 auto metadata =
n.find(
"metadata");
2157 if (!metadata || !metadata->find(
"hs3_version")) {
2158 std::stringstream ss;
2159 ss <<
"The HS3 version is missing in the JSON!\n"
2160 <<
"Please include the HS3 version in the metadata field, e.g.:\n"
2161 <<
" \"metadata\" :\n"
2168 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2169 if (
auto domains =
n.find(
"domains")) {
2180 if (
auto paramPointsNode =
n.find(
"parameter_points")) {
2181 for (
const auto &snsh : paramPointsNode->children()) {
2186 for (
const auto &var : snsh[
"parameters"].children()) {
2188 configureVariable(*
_domains, var, *rrv);
2202 importAttributes(arg, elem);
2212 std::vector<std::unique_ptr<RooAbsData>> datasets;
2213 if (
auto dataNode =
n.find(
"data")) {
2214 for (
const auto &p : dataNode->children()) {
2221 if (
auto analysesNode =
n.find(
"analyses")) {
2229 for (
auto const &
d : datasets) {
2232 for (
auto const &obs : *
d->get()) {
2233 if (
auto *rrv =
dynamic_cast<RooRealVar *
>(obs)) {
2234 _workspace.var(rrv->GetName())->setBinning(rrv->getBinning());
2255 if (this->
workspace()->getSnapshot(
"default_values")) {
2270 std::ifstream infile(
filename.c_str());
2271 if (!infile.is_open()) {
2272 std::stringstream ss;
2273 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2303 std::ifstream infile(
filename.c_str());
2304 if (!infile.is_open()) {
2305 std::stringstream ss;
2306 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2319 bool isVariable =
true;
2320 if (
n.find(
"type")) {
2333 std::unique_ptr<RooFit::Detail::JSONTree> tree =
varJSONString(elementNode);
2335 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2336 if (
auto domains =
n.find(
"domains"))
2342 JSONNode const *varsNode = getVariablesNode(
n);
2343 const auto &p = varsNode->
child(0);
2346 auto paramPointsNode =
n.find(
"parameter_points");
2347 const auto &snsh = paramPointsNode->child(0);
2350 const auto &var = snsh[
"parameters"].child(0);
2352 configureVariable(*
_domains, var, *rrv);
2360 importAttributes(arg, elem);
2389 throw std::runtime_error(s);
2402 for (
char c : str) {
2407 case '(':
result +=
'_';
break;
2412 case '.':
result +=
"_dot_";
break;
2413 case '@':
result +=
"at";
break;
2414 case '-':
result +=
"minus";
break;
2415 case '/':
result +=
"_div_";
break;
2430 if (onlyModelConfig) {
2439 for (
auto *pdf : ws.
allPdfs()) {
2440 if (!pdf->hasClients()) {
2446 if (!func->hasClients()) {
2465 auto *snshSet =
dynamic_cast<RooArgSet *
>(snsh);
2467 tmpWS.
saveSnapshot(snshSet->GetName(), *snshSet,
true);
2481 auto sanitizeIfNeeded = [](
auto const &list) {
2482 for (
auto *obj : list) {
2488 sanitizeIfNeeded(tmpWS.
allVars());
2490 sanitizeIfNeeded(tmpWS.
allPdfs());
2498 for (
auto *obj : *
data->get()) {
2505 for (
auto *obj : *
data->get()) {
2511 auto *snsh =
dynamic_cast<RooArgSet *
>(snshObj);
2513 std::cerr <<
"Warning: found snapshot that is not a RooArgSet, skipping\n";
2523 for (
auto *arg : *snsh) {
2533 if (
auto *named =
dynamic_cast<TNamed *
>(obj)) {
2534 named->SetName(
sanitizeName(named->GetName()).c_str());
2536 std::cerr <<
"Warning: object " << obj->GetName() <<
" is not TNamed, cannot rename.\n";
2547 for (
auto *obs : mc->GetObservables()->get()) {
2552 for (
auto *poi : mc->GetParametersOfInterest()->get()) {
2557 for (
auto *nuis : mc->GetNuisanceParameters()->get()) {
2562 for (
auto *glob : mc->GetGlobalObservables()->get()) {
2569 std::string wsName = std::string{ws.
GetName()} +
"_sanitized";
2571 newWS.
SetName(wsName.c_str());
std::unique_ptr< RooFit::Detail::JSONTree > varJSONString(const JSONNode &treeRoot)
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
double toDouble(const char *s)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void w
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
static std::unique_ptr< JSONTree > create()
Common abstract base class for objects that represent a value and a "shape" in RooFit.
TClass * IsA() const override
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
const std::set< std::string > & attributes() const
const RefCountList_t & servers() const
List of all servers of this object.
const std::map< std::string, std::string > & stringAttributes() const
Int_t numProxies() const
Return the number of registered proxies.
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
RooAbsProxy * getProxy(Int_t index) const
Return the nth proxy from the proxy list.
A space to attach TBranches.
std::size_t size() const
Number of states defined.
Abstract container object that can hold multiple RooAbsArg objects.
bool equals(const RooAbsCollection &otherColl) const
Check if this and other collection have identically-named contents.
const char * GetName() const override
Returns name of object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
void sort(bool reverse=false)
Sort collection using std::sort and name comparison.
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for binned and unbinned datasets.
Abstract interface for all probability density functions.
std::unique_ptr< RooArgSet > getAllConstraints(const RooArgSet &observables, RooArgSet &constrainedParams, bool stripDisconnected=true) const
This helper function finds and collects all constraints terms of all component p.d....
Abstract interface for proxy classes.
virtual const char * name() const
Abstract base class for objects that represent a real value and implements functionality common to al...
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Abstract interface for RooAbsArg proxy classes.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Implements a RooAbsBinning in terms of an array of boundary values, posing no constraints on the choi...
bool addBoundary(double boundary)
Add bin boundary at given value.
Object to represent discrete states.
Represents a constant real-valued object.
Container class to hold N-dimensional binned data.
virtual std::string val() const =0
void fill_seq(Collection const &coll)
virtual JSONNode & set_map()=0
virtual JSONNode & append_child()=0
virtual children_view children()
virtual size_t num_children() const =0
virtual JSONNode & child(size_t pos)=0
virtual JSONNode & set_seq()=0
virtual bool is_seq() const =0
virtual bool is_map() const =0
virtual bool has_child(std::string const &) const =0
virtual std::string key() const =0
JSONNode const * find(std::string const &key) const
static std::unique_ptr< JSONTree > create()
void readVariable(const RooRealVar &)
void writeJSON(RooFit::Detail::JSONNode &) const
void writeVariable(RooRealVar &) const
std::ostream & log(const RooAbsArg *self, RooFit::MsgLevel level, RooFit::MsgTopic facility, bool forceSkipPrefix=false)
Log error message associated with RooAbsArg object self at given level and topic.
static RooMsgService & instance()
Return reference to singleton instance.
Variable that can be changed from the outside.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
const RooAbsCategoryLValue & indexCat() const
const RooArgSet * GetGlobalObservables() const
get RooArgSet for global observables (return nullptr if not existing)
const RooArgSet * GetParametersOfInterest() const
get RooArgSet containing the parameter of interest (return nullptr if not existing)
const RooArgSet * GetNuisanceParameters() const
get RooArgSet containing the nuisance parameters (return nullptr if not existing)
const RooArgSet * GetObservables() const
get RooArgSet for observables (return nullptr if not existing)
const RooArgSet * GetExternalConstraints() const
get RooArgSet for global observables (return nullptr if not existing)
RooAbsPdf * GetPdf() const
get model PDF (return nullptr if pdf has not been specified or does not exist)
Persistable container for RooFit projects.
TObject * obj(RooStringView name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name)
const RooArgSet * getSnapshot(const char *name) const
Return the RooArgSet containing a snapshot of variables contained in the workspace.
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
RooArgSet allVars() const
Return set with all variable objects.
RooArgSet allResolutionModels() const
Return set with all resolution model objects.
bool saveSnapshot(RooStringView, const char *paramNames)
Save snapshot of values and attributes (including "Constant") of given parameters.
RooArgSet allPdfs() const
Return set with all probability density function objects.
std::list< RooAbsData * > allData() const
Return list of all dataset in the workspace.
RooLinkedList const & getSnapshots() const
std::list< TObject * > allGenericObjects() const
Return list of all generic objects in the workspace.
RooAbsArg * arg(RooStringView name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
RooArgSet allFunctions() const
Return set with all function objects.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
std::list< RooAbsData * > allEmbeddedData() const
Return list of all dataset in the workspace.
bool loadSnapshot(const char *name)
Load the values and attributes of the parameters in the snapshot saved with the given name.
bool import(const RooAbsArg &arg, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={})
Import a RooAbsArg object, e.g.
TClass instances represent classes, structs and namespaces in the ROOT type system.
The TNamed class is the base class for all named ROOT classes.
const char * GetName() const override
Returns name of object.
virtual void SetName(const char *name)
Set the name of the TNamed.
Mother of all ROOT objects.
const char * Data() const
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
RooCmdArg RecycleConflictNodes(bool flag=true)
RooConstVar & RooConst(double val)
RooCmdArg Silence(bool flag=true)
RooCmdArg Index(RooCategory &icat)
RooCmdArg WeightVar(const char *name="weight", bool reinterpretAsWeight=false)
RooCmdArg Import(const char *state, TH1 &histo)
std::string makeValidVarName(std::string const &in)
ImportExpressionMap & importExpressions()
ExportKeysMap & exportKeys()
RooStats::ModelConfig ModelConfig