134 std::vector<double> edges;
140 Var(
int n) : nbins(
n), min(0), max(
n) {}
159bool isNumber(
const std::string &str)
162 for (
char const &
c : str) {
163 if (std::isdigit(
c) == 0 &&
c !=
'.' && !(
first && (
c ==
'-' ||
c ==
'+')))
179bool isValidName(
const std::string &str)
182 if (str.empty() || !(std::isalpha(str[0]) || str[0] ==
'_')) {
189 if (!(std::isalnum(
c) ||
c ==
'_')) {
214 if (!
p.has_child(
"name")) {
217 if (
auto n =
p.find(
"value"))
218 v.setVal(
n->val_double());
220 if (
auto n =
p.find(
"nbins"))
221 v.setBins(
n->val_int());
222 if (
auto n =
p.find(
"relErr"))
223 v.setError(
v.getVal() *
n->val_double());
224 if (
auto n =
p.find(
"err"))
225 v.setError(
n->val_double());
226 if (
auto n =
p.find(
"const"))
227 v.setConstant(
n->val_bool());
229 v.setConstant(
false);
234 auto paramPointsNode = rootNode.
find(
"parameter_points");
235 if (!paramPointsNode)
240 return &((*out)[
"parameters"]);
245 if (val.
find(
"edges")) {
247 this->edges.push_back(
child.val_double());
249 this->nbins = this->edges.size();
250 this->min = this->edges[0];
251 this->max = this->edges[this->nbins - 1];
253 if (!val.
find(
"nbins"))
256 this->nbins = val[
"nbins"].
val_int();
257 if (!val.
find(
"min"))
261 if (!val.
find(
"max"))
268std::string genPrefix(
const JSONNode &
p,
bool trailing_underscore)
273 if (
auto node =
p.find(
"namespaces")) {
274 for (
const auto &ns : node->children()) {
280 if (trailing_underscore && !prefix.empty())
286void genIndicesHelper(std::vector<std::vector<int>> &combinations, std::vector<int> &curr_comb,
287 const std::vector<int> &vars_numbins,
size_t curridx)
289 if (curridx == vars_numbins.size()) {
291 combinations.emplace_back(curr_comb);
293 for (
int i = 0; i < vars_numbins[curridx]; ++i) {
294 curr_comb[curridx] = i;
295 ::genIndicesHelper(combinations, curr_comb, vars_numbins, curridx + 1);
312 if (
auto seq = node.
find(
"dict")) {
313 for (
const auto &
attr : seq->children()) {
317 if (
auto seq = node.
find(
"tags")) {
318 for (
const auto &
attr : seq->children()) {
327 std::stringstream expression;
328 std::string classname(
ex.tclass->GetName());
329 size_t colon = classname.find_last_of(
':');
330 expression << (colon < classname.size() ? classname.substr(colon + 1) : classname);
333 for (
auto k :
ex.arguments) {
334 expression << (
first ?
"::" +
name +
"(" :
",");
336 if (k ==
"true" || k ==
"false") {
337 expression << (k ==
"true" ?
"1" :
"0");
338 }
else if (!
p.has_child(k)) {
339 std::stringstream errMsg;
340 errMsg <<
"node '" <<
name <<
"' is missing key '" << k <<
"'";
342 }
else if (
p[k].is_seq()) {
343 bool firstInner =
true;
345 expression << (firstInner ?
"{" :
",") << arg->
GetName();
351 expression <<
p[k].val();
355 return expression.str();
368std::vector<std::vector<int>> generateBinIndices(
const RooArgSet &vars)
370 std::vector<std::vector<int>> combinations;
371 std::vector<int> vars_numbins;
372 vars_numbins.reserve(vars.
size());
373 for (
const auto *absv : static_range_cast<RooRealVar *>(vars)) {
374 vars_numbins.push_back(absv->getBins());
376 std::vector<int> curr_comb(vars.
size());
377 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
381template <
typename... Keys_t>
382JSONNode const *findRooFitInternal(
JSONNode const &node, Keys_t
const &...keys)
384 return node.
find(
"misc",
"ROOT_internal", keys...);
396bool isLiteralConstVar(
RooAbsArg const &arg)
398 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(&arg);
399 return isRooConstVar && isNumber(arg.
GetName());
414 if (isLiteralConstVar(*arg)) {
420 auto initializeNode = [&]() {
430 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(arg);
433 (*node)[
"is_const_var"] << 1;
440 if (it.first ==
"factory_tag" || it.first ==
"PROD_TERM_TYPE")
443 (*node)[
"dict"].set_map()[it.first] << it.second;
449 if (
attr ==
"SnapShot_ExtRefClone" ||
attr ==
"RooRealConstant_Factory_Object")
452 (*node)[
"tags"].set_seq().append_child() <<
attr;
472 std::map<std::string, Var> vars;
473 for (
const auto &
p : node[
"axes"].
children()) {
477 for (
auto v : vars) {
478 std::string
name(
v.first);
482 std::stringstream errMsg;
483 errMsg <<
"The observable \"" <<
name <<
"\" could not be found in the workspace!";
504 if (!::isValidName(
name)) {
505 std::stringstream ss;
506 ss <<
"RooJSONFactoryWSTool() data name '" <<
name <<
"' is not valid!" << std::endl;
510 std::string
const &
type =
p[
"type"].val();
511 if (
type ==
"binned") {
514 }
else if (
type ==
"unbinned") {
517 getObservables(workspace,
p, vars);
520 auto &coords =
p[
"entries"];
521 auto &weights =
p[
"weights"];
522 if (coords.num_children() != weights.num_children()) {
525 if (!coords.is_seq()) {
528 std::vector<double> weightVals;
529 for (
auto const &weight : weights.children()) {
530 weightVals.push_back(weight.val_double());
533 for (
auto const &point : coords.children()) {
534 if (!point.is_seq()) {
535 std::stringstream errMsg;
536 errMsg <<
"coordinate point '" << i <<
"' is not a list!";
539 if (point.num_children() != varlist.
size()) {
543 for (
auto const &pointj : point.children()) {
545 v->
setVal(pointj.val_double());
548 data->add(vars, weightVals[i]);
554 std::stringstream ss;
555 ss <<
"RooJSONFactoryWSTool() failed to create dataset " <<
name << std::endl;
575 RooWorkspace &workspace,
const std::vector<std::unique_ptr<RooAbsData>> &datasets)
579 JSONNode const *mcAuxNode = findRooFitInternal(rootnode,
"ModelConfigs", analysisName);
581 JSONNode const *mcNameNode = mcAuxNode ? mcAuxNode->
find(
"mcName") :
nullptr;
582 std::string mcname = mcNameNode ? mcNameNode->
val() : analysisName;
583 if (workspace.
obj(mcname))
588 mc->
SetWS(workspace);
590 std::vector<std::string> nllDistNames;
591 std::vector<std::string> nllDataNames;
595 throw std::runtime_error(
"likelihood node not found!");
597 for (
auto &nameNode : (*nllNode)[
"distributions"].children()) {
598 nllDistNames.push_back(nameNode.val());
601 for (
auto &nameNode : (*nllNode)[
"aux_distributions"].children()) {
602 RooAbsArg *extConstraint = workspace.
arg(nameNode.val());
604 extConstraints.
add(*extConstraint);
608 for (
auto &nameNode : (*nllNode)[
"data"].children()) {
609 nllDataNames.push_back(nameNode.val());
610 for (
const auto &
d : datasets) {
611 if (
d->GetName() == nameNode.val()) {
612 observables.
add(*
d->get());
617 JSONNode const *pdfNameNode = mcAuxNode ? mcAuxNode->
find(
"pdfName") :
nullptr;
618 std::string
const pdfName = pdfNameNode ? pdfNameNode->
val() :
"simPdf";
624 if (nllDistNames.size() == 1) {
626 pdf = workspace.
pdf(nllDistNames[0]);
629 std::string simPdfName = analysisName +
"_simPdf";
630 std::string indexCatName = analysisName +
"_categoryIndex";
631 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
632 std::map<std::string, RooAbsPdf *> pdfMap;
633 for (std::size_t i = 0; i < nllDistNames.size(); ++i) {
635 pdfMap[nllDistNames[i]] = workspace.
pdf(nllDistNames[i]);
637 RooSimultaneous simPdf{simPdfName.c_str(), simPdfName.c_str(), pdfMap, indexCat};
645 if (!extConstraints.
empty())
646 mc->SetExternalConstraints(extConstraints);
648 auto readArgSet = [&](std::string
const &
name) {
651 out.add(*workspace.
arg(
child.val()));
656 mc->SetParametersOfInterest(readArgSet(
"parameters_of_interest"));
657 mc->SetObservables(observables);
669 for (
const auto &
p : pars) {
670 if (mc->GetParametersOfInterest()->find(*
p))
672 if (
p->isConstant() && !mainPars.find(*
p))
677 mc->SetGlobalObservables(globs);
678 mc->SetNuisanceParameters(nps);
681 if (
auto found = mcAuxNode->
find(
"combined_data_name")) {
689 auto *combinedPdfInfoNode = findRooFitInternal(rootnode,
"combined_distributions");
692 if (combinedPdfInfoNode ==
nullptr) {
696 for (
auto &info : combinedPdfInfoNode->children()) {
699 std::string combinedName = info.key();
700 std::string indexCatName = info[
"index_cat"].val();
701 std::vector<std::string> labels;
702 std::vector<int> indices;
703 std::vector<std::string> pdfNames;
704 for (
auto &
n : info[
"indices"].children()) {
705 indices.push_back(
n.val_int());
707 for (
auto &
n : info[
"labels"].children()) {
708 labels.push_back(
n.val());
710 for (
auto &
n : info[
"distributions"].children()) {
711 pdfNames.push_back(
n.val());
714 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
715 std::map<std::string, RooAbsPdf *> pdfMap;
717 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
718 indexCat.
defineType(labels[iChannel], indices[iChannel]);
719 pdfMap[labels[iChannel]] = ws.
pdf(pdfNames[iChannel]);
722 RooSimultaneous simPdf{combinedName.c_str(), combinedName.c_str(), pdfMap, indexCat};
727void combineDatasets(
const JSONNode &rootnode, std::vector<std::unique_ptr<RooAbsData>> &datasets)
729 auto *combinedDataInfoNode = findRooFitInternal(rootnode,
"combined_datasets");
732 if (combinedDataInfoNode ==
nullptr) {
736 for (
auto &info : combinedDataInfoNode->children()) {
739 std::string combinedName = info.key();
740 std::string indexCatName = info[
"index_cat"].val();
741 std::vector<std::string> labels;
742 std::vector<int> indices;
743 for (
auto &
n : info[
"indices"].children()) {
744 indices.push_back(
n.val_int());
746 for (
auto &
n : info[
"labels"].children()) {
747 labels.push_back(
n.val());
749 if (indices.size() != labels.size()) {
754 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
755 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
757 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
758 auto componentName = combinedName +
"_" + labels[iChannel];
761 std::unique_ptr<RooAbsData> &component = *std::find_if(
762 datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
765 allVars.add(*component->get());
766 dsMap.insert({labels[iChannel], std::move(component)});
767 indexCat.defineType(labels[iChannel], indices[iChannel]);
770 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
772 datasets.emplace_back(std::move(combined));
777void sortByName(T &coll)
779 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
796 if (isLiteralConstVar(*arg))
803 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
841 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
845RooRealVar *RooJSONFactoryWSTool::requestImpl<RooRealVar>(
const std::string &objname)
850 if (
auto node = vars->find(objname)) {
860RooAbsPdf *RooJSONFactoryWSTool::requestImpl<RooAbsPdf>(
const std::string &objname)
875RooAbsReal *RooJSONFactoryWSTool::requestImpl<RooAbsReal>(
const std::string &objname)
879 if (isNumber(objname))
881 if (
RooAbsPdf *pdf = requestImpl<RooAbsPdf>(objname))
883 if (
RooRealVar *var = requestImpl<RooRealVar>(objname))
925 var[
"value"] << cv->getVal();
926 var[
"const"] <<
true;
928 var[
"value"] << rrv->getVal();
929 if (rrv->isConstant()) {
930 var[
"const"] << rrv->isConstant();
932 if (rrv->getBins() != 100) {
933 var[
"nbins"] << rrv->getBins();
958 const std::string &operation_name,
const std::string &formula)
961 const std::string tagname =
"autogen_transform_" + tag;
968 const std::string newname =
name +
"_" + tag +
"_" + operation_name;
973 error(
"unable to import transformed of '" +
name +
"', original not present.");
977 transformed = &wsEmplace<RooFormulaVar>(newname, expression.c_str(), components);
984 const std::string &operation_name,
const std::string &formula)
986 const std::string tagname =
"autogen_transform_" + tag;
989 return trafo->dependents().first()->
GetName();
993 std::string newname = std::string(original->
GetName()) +
"_" + tag +
"_" + operation_name;
994 auto &trafo_node = this->
createAdHoc(
"functions", newname);
995 trafo_node[
"type"] <<
"generic_function";
1004 auto &collectionNode = (*_rootnodeOutput)[toplevel];
1024 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
1027 exportedObjectNames.insert(
name);
1036 std::vector<std::string> channelNames;
1037 for (
auto const &item : simPdf->indexCat()) {
1038 channelNames.push_back(item.first);
1042 auto &
child = infoNode[simPdf->GetName()].set_map();
1043 child[
"index_cat"] << simPdf->indexCat().GetName();
1045 child[
"distributions"].set_seq();
1046 for (
auto const &item : simPdf->indexCat()) {
1047 child[
"distributions"].append_child() << simPdf->getPdf(item.first.c_str())->GetName();
1059 auto &collectionNode = (*_rootnodeOutput)[
dynamic_cast<RooAbsPdf const *
>(&func) ?
"distributions" :
"functions"];
1068 auto it = exporters.find(cl);
1069 if (it != exporters.end()) {
1070 for (
auto &exp : it->second) {
1072 if (!exp->exportObject(
this, &func, elem)) {
1078 elem[
"name"] <<
name;
1082 if (exp->autoExportDependants()) {
1096 const auto &dict = exportKeys.find(cl);
1097 if (dict == exportKeys.end()) {
1098 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1099 <<
"there are several possible reasons for this:\n"
1100 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1102 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1103 <<
" 3. something is wrong with your setup, e.g. you might have called "
1104 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1105 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1106 <<
"either way, please make sure that:\n"
1107 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1108 "see what is available\n"
1109 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1110 "https://github.com/root-project/root/blob/master/roofit/hs3/README.md to "
1111 "see how to do this!\n";
1115 elem[
"type"] << dict->second.type;
1119 for (
size_t i = 0; i < nprox; ++i) {
1123 std::string pname(
p->name());
1124 if (pname[0] ==
'!')
1127 auto k = dict->second.proxies.find(pname);
1128 if (k == dict->second.proxies.end()) {
1129 std::cerr <<
"failed to find key matching proxy '" << pname <<
"' for type '" << dict->second.type
1130 <<
"', encountered in '" << func.
GetName() <<
"', skipping" << std::endl;
1135 if (k->second.empty())
1142 if (isLiteralConstVar(*
r->absArg()))
1143 elem[k->second] <<
static_cast<RooConstVar *
>(
r->absArg())->getVal();
1145 elem[k->second] <<
r->absArg()->GetName();
1172 if (!::isValidName(
name)) {
1173 std::stringstream ss;
1174 ss <<
"RooJSONFactoryWSTool() function name '" <<
name <<
"' is not valid!" << std::endl;
1184 std::stringstream ss;
1185 ss <<
"RooJSONFactoryWSTool() function node " +
name +
" is not a map!";
1189 std::string prefix = genPrefix(
p,
true);
1190 if (!prefix.empty())
1192 if (!
p.has_child(
"type")) {
1193 std::stringstream ss;
1194 ss <<
"RooJSONFactoryWSTool() no type given for function '" <<
name <<
"', skipping." << std::endl;
1199 std::string functype(
p[
"type"].val());
1202 if (!importAllDependants) {
1207 auto it = importers.find(functype);
1209 if (it != importers.end()) {
1210 for (
auto &imp : it->second) {
1211 ok = imp->importArg(
this,
p);
1217 auto expr = factoryExpressions.find(functype);
1218 if (expr != factoryExpressions.end()) {
1219 std::string expression = ::generate(expr->second,
p,
this);
1221 std::stringstream ss;
1222 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1223 <<
"', skipping. expression was\n"
1224 << expression << std::endl;
1228 std::stringstream ss;
1229 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1231 <<
"there are several possible reasons for this:\n"
1232 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1233 <<
" 2. " << functype
1234 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1235 <<
" 3. something is wrong with your setup, e.g. you might have called "
1236 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1237 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1238 <<
"either way, please make sure that:\n"
1239 <<
" 3: you are reading a file with factory expressions - call "
1240 "RooFit::JSONIO::printFactoryExpressions() "
1241 "to see what is available\n"
1242 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1243 "https://github.com/root-project/root/blob/master/roofit/hs3/README.md to see "
1252 std::stringstream err;
1253 err <<
"something went wrong importing function '" <<
name <<
"'.";
1270 this->
importFunction((JSONTree::create(jsonString))->rootnode(), importAllDependants);
1287 auto &observablesNode =
output[
"axes"].set_seq();
1289 for (
auto *var : static_range_cast<RooRealVar *>(vars)) {
1291 obsNode[
"name"] << var->GetName();
1292 if (var->getBinning().isUniform()) {
1293 obsNode[
"min"] << var->getMin();
1294 obsNode[
"max"] << var->getMax();
1295 obsNode[
"nbins"] << var->getBins();
1297 auto &edges = obsNode[
"edges"];
1299 double val = var->getBinning().binLow(0);
1301 for (
int i = 0; i < var->getBinning().numBins(); ++i) {
1302 val = var->getBinning().binHigh(i);
1303 edges.append_child() << val;
1325 for (std::size_t i = 0; i <
n; ++i) {
1326 double w = contents[i];
1348 auto &labels = node[
"labels"].
set_seq();
1349 auto &indices = node[
"indices"].
set_seq();
1351 for (
auto const &item : cat) {
1353 if (std::isalpha(item.first[0])) {
1355 if (label != item.first) {
1356 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << item.first <<
"' to '" << label
1357 <<
"' to become a valid name";
1361 "' to make a valid name!");
1364 labels.append_child() << label;
1365 indices.append_child() << item.second;
1387 " has several category observables!");
1409 auto *combinedPdfInfoNode = findRooFitInternal(*
_rootnodeOutput,
"combined_distributions");
1410 if (combinedPdfInfoNode) {
1411 for (
auto &info : combinedPdfInfoNode->children()) {
1412 if (info[
"index_cat"].val() == cat->
GetName()) {
1422 std::unique_ptr<TList> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1424 for (
RooAbsData *absData : static_range_cast<RooAbsData *>(*dataList)) {
1425 std::string catName(absData->GetName());
1426 std::string dataName;
1427 if (std::isalpha(catName[0])) {
1429 if (dataName != catName) {
1430 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << catName <<
"' to '" << dataName
1431 <<
"' to become a valid name";
1435 "' to make a valid name!");
1438 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1439 datamap.
components[catName] = absData->GetName();
1462 " has several category observables!");
1475 output[
"type"] <<
"binned";
1488 if (
auto weightVar = variables.find(
"weightVar")) {
1489 variables.remove(*weightVar);
1498 if (
data.isWeighted() && variables.size() == 1) {
1499 bool isBinnedData =
false;
1500 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1501 std::vector<double> contents;
1503 for (; i <
data.numEntries(); ++i) {
1505 if (
x.getBin() != i)
1507 contents.push_back(
data.weight());
1509 if (i ==
x.getBins())
1510 isBinnedData =
true;
1512 output[
"type"] <<
"binned";
1517 output[
"type"] <<
"unbinned";
1522 auto &coords =
output[
"entries"].set_seq();
1523 auto *weights =
data.isWeighted() ? &
output[
"weights"].set_seq() :
nullptr;
1524 for (
int i = 0; i <
data.numEntries(); ++i) {
1526 coords.append_child().fill_seq(variables, [](
auto x) {
return static_cast<RooRealVar *
>(
x)->getVal(); });
1528 weights->append_child() <<
data.weight();
1546 if (node.has_child(
"edges")) {
1547 std::vector<double> edges;
1548 for (
auto const &bound : node[
"edges"].children()) {
1549 edges.push_back(bound.val_double());
1551 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(), edges[0],
1552 edges[edges.size() - 1]);
1553 RooBinning bins(obs->getMin(), obs->getMax());
1554 for (
auto b : edges) {
1557 obs->setBinning(bins);
1560 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(),
1561 node[
"min"].val_double(), node[
"max"].val_double());
1562 obs->setBins(node[
"nbins"].val_int());
1581std::unique_ptr<RooDataHist>
1584 if (!
n.has_child(
"contents"))
1587 JSONNode const &contents =
n[
"contents"];
1593 if (
n.has_child(
"errors")) {
1594 errors = &
n[
"errors"];
1599 auto bins = generateBinIndices(vars);
1601 std::stringstream errMsg;
1602 errMsg <<
"inconsistent bin numbers: contents=" << contents.
num_children() <<
", bins=" << bins.size();
1605 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1606 std::vector<double> contentVals;
1608 for (
auto const &cont : contents.
children()) {
1609 contentVals.push_back(cont.val_double());
1611 std::vector<double> errorVals;
1614 for (
auto const &err : errors->
children()) {
1615 errorVals.push_back(err.val_double());
1618 for (
size_t ibin = 0; ibin < bins.size(); ++ibin) {
1619 const double err = errors ? errorVals[ibin] : -1;
1620 dh->set(ibin, contentVals[ibin], err);
1639 if (!::isValidName(
name)) {
1640 std::stringstream ss;
1641 ss <<
"RooJSONFactoryWSTool() variable name '" <<
name <<
"' is not valid!" << std::endl;
1648 std::stringstream ss;
1649 ss <<
"RooJSONFactoryWSTool() node '" <<
name <<
"' is not a map, skipping.";
1650 oocoutE(
nullptr, InputArguments) << ss.str() << std::endl;
1656 if (attrNode->has_child(
"is_const_var") && (*attrNode)[
"is_const_var"].val_int() == 1) {
1657 wsEmplace<RooConstVar>(
name,
p[
"value"].val_double());
1662 configureVariable(*
_domains,
p, wsEmplace<RooRealVar>(
name, 1.));
1677 if (
JSONNode const *varsNode = getVariablesNode(
n)) {
1678 for (
const auto &
p : varsNode->children()) {
1682 if (
auto seq =
n.find(
"functions")) {
1683 for (
const auto &
p : seq->children()) {
1687 if (
auto seq =
n.find(
"distributions")) {
1688 for (
const auto &
p : seq->children()) {
1695 const std::vector<CombinedData> &combDataSets)
1698 if (pdf ==
nullptr) {
1699 warning(
"RooFitHS3 only supports ModelConfigs with RooSimultaneous! Skipping ModelConfig.");
1703 for (std::size_t i = 0; i < std::max(combDataSets.size(), std::size_t(1)); ++i) {
1704 const bool hasdata = i < combDataSets.size();
1705 if (hasdata && !matches(combDataSets.at(i), pdf))
1708 std::string analysisName(pdf->GetName());
1710 analysisName +=
"_" + combDataSets[i].name;
1717 std::string
const &analysisName,
1718 std::map<std::string, std::string>
const *dataComponents)
1726 analysisNode[
"likelihood"] << analysisName;
1729 nllNode[
"distributions"].set_seq();
1730 nllNode[
"data"].set_seq();
1732 if (dataComponents) {
1733 for (
auto const &item : pdf->indexCat()) {
1734 const auto &dataComp = dataComponents->find(item.first);
1735 nllNode[
"distributions"].append_child() << pdf->getPdf(item.first)->GetName();
1736 nllNode[
"data"].append_child() << dataComp->second;
1741 auto &extConstrNode = nllNode[
"aux_distributions"];
1742 extConstrNode.set_seq();
1744 extConstrNode.append_child() << constr->GetName();
1748 auto writeList = [&](
const char *
name,
RooArgSet const *args) {
1752 std::vector<std::string> names;
1753 names.reserve(args->size());
1755 names.push_back(arg->GetName());
1756 std::sort(names.begin(), names.end());
1762 auto &modelConfigAux =
getRooFitInternal(rootnode,
"ModelConfigs", analysisName);
1763 modelConfigAux.set_map();
1764 modelConfigAux[
"pdfName"] << pdf->GetName();
1765 modelConfigAux[
"mcName"] << mc.
GetName();
1779 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1784 std::vector<RooAbsPdf *> allpdfs;
1786 if (!arg->hasClients()) {
1787 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
1788 allpdfs.push_back(pdf);
1792 sortByName(allpdfs);
1793 std::set<std::string> exportedObjectNames;
1800 exportAttributes(arg,
n);
1804 std::vector<RooAbsData *> alldata;
1806 alldata.push_back(
d);
1808 sortByName(alldata);
1810 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
1811 for (
auto &
d : alldata) {
1813 if (!
data.components.empty())
1814 combData.push_back(
data);
1817 for (
auto &
d : alldata) {
1834 if (exportedObjectNames.find(arg->GetName()) != exportedObjectNames.end()) {
1835 bool do_export =
false;
1836 for (
const auto &pdf : allpdfs) {
1837 if (pdf->dependsOn(*arg)) {
1841 if (do_export && !::isValidName(arg->GetName())) {
1842 std::stringstream ss;
1843 ss <<
"RooJSONFactoryWSTool() variable '" << arg->GetName() <<
"' has an invalid name!" << std::endl;
1847 snapshotSorted.
add(*arg);
1850 snapshotSorted.
sort();
1851 std::string
name(snsh->GetName());
1852 if (
name !=
"default_values") {
1870 std::stringstream ss(s);
1882 std::stringstream ss(s);
1893 std::stringstream ss;
1905 std::stringstream ss;
1917 std::unique_ptr<JSONTree>
tree = JSONTree::create();
1920 auto &metadata =
n[
"metadata"].set_map();
1927 std::string versionName =
gROOT->GetVersion();
1930 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
1931 rootInfo[
"version"] << versionName;
1959 std::ofstream out(
filename.c_str());
1960 if (!out.is_open()) {
1961 std::stringstream ss;
1962 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
1992 std::ofstream out(
filename.c_str());
1993 if (!out.is_open()) {
1994 std::stringstream ss;
1995 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
2007 if (
auto seq = attrNode->find(
"tags")) {
2008 for (
auto &
a : seq->children()) {
2009 if (
a.val() == attrib)
2019 auto &tags = (*node)[
"tags"];
2029 if (
auto dict = attrNode->find(
"dict")) {
2030 if (
auto *
a = dict->find(attrib)) {
2038 const std::string &
value)
2041 auto &dict = (*node)[
"dict"];
2043 dict[attrib] <<
value;
2059 auto metadata =
n.find(
"metadata");
2060 if (!metadata || !metadata->find(
"hs3_version")) {
2061 std::stringstream ss;
2062 ss <<
"The HS3 version is missing in the JSON!\n"
2063 <<
"Please include the HS3 version in the metadata field, e.g.:\n"
2064 <<
" \"metadata\" :\n"
2071 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2072 if (
auto domains =
n.find(
"domains")) {
2083 if (
auto paramPointsNode =
n.find(
"parameter_points")) {
2084 for (
const auto &snsh : paramPointsNode->children()) {
2087 if (!::isValidName(
name)) {
2088 std::stringstream ss;
2089 ss <<
"RooJSONFactoryWSTool() node name '" <<
name <<
"' is not valid!" << std::endl;
2094 for (
const auto &var : snsh[
"parameters"].children()) {
2096 configureVariable(*
_domains, var, *rrv);
2110 importAttributes(arg, elem);
2120 std::vector<std::unique_ptr<RooAbsData>> datasets;
2121 if (
auto dataNode =
n.find(
"data")) {
2122 for (
const auto &
p : dataNode->children()) {
2129 if (
auto analysesNode =
n.find(
"analyses")) {
2130 for (
JSONNode const &analysisNode : analysesNode->children()) {
2137 for (
auto const &
d : datasets) {
2155 std::unique_ptr<JSONTree>
tree = JSONTree::create(is);
2169 std::ifstream infile(
filename.c_str());
2170 if (!infile.is_open()) {
2171 std::stringstream ss;
2172 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2188 std::unique_ptr<JSONTree>
tree = JSONTree::create(is);
2202 std::ifstream infile(
filename.c_str());
2203 if (!infile.is_open()) {
2204 std::stringstream ss;
2205 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2218 bool isVariable =
true;
2219 if (
n.find(
"type")) {
2234 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2235 if (
auto domains =
n.find(
"domains"))
2241 JSONNode const *varsNode = getVariablesNode(
n);
2242 const auto &
p = varsNode->
child(0);
2245 auto paramPointsNode =
n.find(
"parameter_points");
2246 const auto &snsh = paramPointsNode->child(0);
2249 const auto &var = snsh[
"parameters"].child(0);
2251 configureVariable(*
_domains, var, *rrv);
2259 importAttributes(arg, elem);
2288 throw std::runtime_error(s);
std::unique_ptr< RooFit::Detail::JSONTree > varJSONString(const JSONNode &treeRoot)
winID h TVirtualViewer3D TVirtualGLPainter p
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 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 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
Common abstract base class for objects that represent a value and a "shape" in RooFit.
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.
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
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.
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.
Abstract base class for binned and unbinned datasets.
Abstract interface for all probability density functions.
RooArgSet * getAllConstraints(const RooArgSet &observables, RooArgSet &constrainedParams, bool stripDisconnected=true, bool removeConstraintsFromPdf=false) const
This helper function finds and collects all constraints terms of all component p.d....
RooAbsProxy is the abstract interface for proxy classes.
Abstract base class for objects that represent a real value and implements functionality common to al...
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.
Class RooBinning is an implements RooAbsBinning in terms of an array of boundary values,...
bool addBoundary(double boundary)
Add bin boundary at given value.
Object to represent discrete states.
bool defineType(const std::string &label)
Define a state with given name.
RooConstVar represent a constant real-valued object.
The RooDataHist is a 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 void writeJSON(std::ostream &os) const =0
virtual bool is_seq() const =0
virtual bool is_map() const =0
virtual std::string key() const =0
virtual double val_double() const
JSONNode const * find(std::string const &key) const
virtual int val_int() const
static std::unique_ptr< JSONTree > create()
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.
RooRealVar represents a variable that can be changed from the outside.
void setVal(double value) override
Set value of variable to 'value'.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
const RooAbsCategoryLValue & indexCat() const
ModelConfig is a simple class that holds configuration information specifying how a model should be u...
const RooArgSet * GetParametersOfInterest() const
get RooArgSet containing the parameter of interest (return nullptr if not existing)
void SetWS(RooWorkspace &ws) override
Set a workspace that owns all the necessary components for the analysis.
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)
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
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.
RooAbsReal * function(RooStringView name) const
Retrieve function (RooAbsReal) with given name. Note that all RooAbsPdfs are also RooAbsReals....
RooAbsArg * arg(RooStringView name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
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.
const RooArgSet & components() const
RooFactoryWSTool & factory()
Return instance to factory tool.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
TClass instances represent classes, structs and namespaces in the ROOT type system.
const char * GetName() const override
Returns name of object.
TClass * IsA() const override
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()