130 std::vector<double> edges;
136 Var(
int n) : nbins(
n), min(0), max(
n) {}
155bool isNumber(
const std::string &str)
158 for (
char const &
c : str) {
159 if (std::isdigit(
c) == 0 &&
c !=
'.' && !(first && (
c ==
'-' ||
c ==
'+')))
175bool isValidName(
const std::string &str)
178 if (str.empty() || !(std::isalpha(str[0]) || str[0] ==
'_')) {
185 if (!(std::isalnum(
c) ||
c ==
'_')) {
210 if (!
p.has_child(
"name")) {
213 if (
auto n =
p.find(
"value"))
214 v.setVal(
n->val_double());
216 if (
auto n =
p.find(
"nbins"))
217 v.setBins(
n->val_int());
218 if (
auto n =
p.find(
"relErr"))
219 v.setError(
v.getVal() *
n->val_double());
220 if (
auto n =
p.find(
"err"))
221 v.setError(
n->val_double());
222 if (
auto n =
p.find(
"const")) {
223 v.setConstant(
n->val_bool());
225 v.setConstant(
false);
231 auto paramPointsNode = rootNode.
find(
"parameter_points");
232 if (!paramPointsNode)
237 return &((*out)[
"parameters"]);
242 if (val.
find(
"edges")) {
244 this->edges.push_back(
child.val_double());
246 this->nbins = this->edges.size();
247 this->min = this->edges[0];
248 this->max = this->edges[this->nbins - 1];
250 if (!val.
find(
"nbins")) {
253 this->nbins = val[
"nbins"].
val_int();
255 if (!val.
find(
"min")) {
260 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)) {
678 mc->SetGlobalObservables(globs);
679 mc->SetNuisanceParameters(nps);
682 if (
auto found = mcAuxNode->
find(
"combined_data_name")) {
690 auto *combinedPdfInfoNode = findRooFitInternal(rootnode,
"combined_distributions");
693 if (combinedPdfInfoNode ==
nullptr) {
697 for (
auto &info : combinedPdfInfoNode->children()) {
700 std::string combinedName = info.key();
701 std::string indexCatName = info[
"index_cat"].val();
702 std::vector<std::string> labels;
703 std::vector<int> indices;
704 std::vector<std::string> pdfNames;
705 for (
auto &
n : info[
"indices"].children()) {
706 indices.push_back(
n.val_int());
708 for (
auto &
n : info[
"labels"].children()) {
709 labels.push_back(
n.val());
711 for (
auto &
n : info[
"distributions"].children()) {
712 pdfNames.push_back(
n.val());
715 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
716 std::map<std::string, RooAbsPdf *> pdfMap;
718 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
719 indexCat.
defineType(labels[iChannel], indices[iChannel]);
720 pdfMap[labels[iChannel]] = ws.
pdf(pdfNames[iChannel]);
723 RooSimultaneous simPdf{combinedName.c_str(), combinedName.c_str(), pdfMap, indexCat};
728void combineDatasets(
const JSONNode &rootnode, std::vector<std::unique_ptr<RooAbsData>> &datasets)
730 auto *combinedDataInfoNode = findRooFitInternal(rootnode,
"combined_datasets");
733 if (combinedDataInfoNode ==
nullptr) {
737 for (
auto &info : combinedDataInfoNode->children()) {
740 std::string combinedName = info.key();
741 std::string indexCatName = info[
"index_cat"].val();
742 std::vector<std::string> labels;
743 std::vector<int> indices;
744 for (
auto &
n : info[
"indices"].children()) {
745 indices.push_back(
n.val_int());
747 for (
auto &
n : info[
"labels"].children()) {
748 labels.push_back(
n.val());
750 if (indices.size() != labels.size()) {
755 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
756 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
758 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
759 auto componentName = combinedName +
"_" + labels[iChannel];
762 std::unique_ptr<RooAbsData> &component = *std::find_if(
763 datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
766 allVars.add(*component->get());
767 dsMap.insert({labels[iChannel], std::move(component)});
768 indexCat.defineType(labels[iChannel], indices[iChannel]);
771 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
773 datasets.emplace_back(std::move(combined));
778void sortByName(T &coll)
780 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
797 if (isLiteralConstVar(*arg)) {
805 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
843 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
847RooRealVar *RooJSONFactoryWSTool::requestImpl<RooRealVar>(
const std::string &objname)
852 if (
auto node = vars->find(objname)) {
862RooAbsPdf *RooJSONFactoryWSTool::requestImpl<RooAbsPdf>(
const std::string &objname)
877RooAbsReal *RooJSONFactoryWSTool::requestImpl<RooAbsReal>(
const std::string &objname)
881 if (isNumber(objname))
883 if (
RooAbsPdf *pdf = requestImpl<RooAbsPdf>(objname))
885 if (
RooRealVar *var = requestImpl<RooRealVar>(objname))
927 var[
"value"] << cv->getVal();
928 var[
"const"] <<
true;
930 var[
"value"] << rrv->getVal();
931 if (rrv->isConstant()) {
932 var[
"const"] << rrv->isConstant();
934 if (rrv->getBins() != 100) {
935 var[
"nbins"] << rrv->getBins();
960 const std::string &operation_name,
const std::string &formula)
963 const std::string tagname =
"autogen_transform_" + tag;
970 const std::string newname =
name +
"_" + tag +
"_" + operation_name;
975 error(
"unable to import transformed of '" +
name +
"', original not present.");
979 transformed = &wsEmplace<RooFormulaVar>(newname, expression.c_str(), components);
986 const std::string &operation_name,
const std::string &formula)
988 const std::string tagname =
"autogen_transform_" + tag;
991 return trafo->dependents().first()->
GetName();
995 std::string newname = std::string(original->
GetName()) +
"_" + tag +
"_" + operation_name;
996 auto &trafo_node = this->
createAdHoc(
"functions", newname);
997 trafo_node[
"type"] <<
"generic_function";
1006 auto &collectionNode = (*_rootnodeOutput)[toplevel];
1026 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
1029 exportedObjectNames.insert(
name);
1038 std::vector<std::string> channelNames;
1039 for (
auto const &item : simPdf->indexCat()) {
1040 channelNames.push_back(item.first);
1044 auto &
child = infoNode[simPdf->GetName()].set_map();
1045 child[
"index_cat"] << simPdf->indexCat().GetName();
1047 child[
"distributions"].set_seq();
1048 for (
auto const &item : simPdf->indexCat()) {
1049 child[
"distributions"].append_child() << simPdf->getPdf(item.first.c_str())->GetName();
1061 auto &collectionNode = (*_rootnodeOutput)[
dynamic_cast<RooAbsPdf const *
>(&func) ?
"distributions" :
"functions"];
1070 auto it = exporters.find(cl);
1071 if (it != exporters.end()) {
1072 for (
auto &exp : it->second) {
1074 if (!exp->exportObject(
this, &func, elem)) {
1080 elem[
"name"] <<
name;
1084 if (exp->autoExportDependants()) {
1098 const auto &dict = exportKeys.find(cl);
1099 if (dict == exportKeys.end()) {
1100 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1101 <<
"there are several possible reasons for this:\n"
1102 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1104 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1105 <<
" 3. something is wrong with your setup, e.g. you might have called "
1106 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1107 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1108 <<
"either way, please make sure that:\n"
1109 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1110 "see what is available\n"
1111 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1112 "https://github.com/root-project/root/blob/master/roofit/hs3/README.md to "
1113 "see how to do this!\n";
1117 elem[
"type"] << dict->second.type;
1121 for (
size_t i = 0; i < nprox; ++i) {
1125 std::string pname(
p->name());
1126 if (pname[0] ==
'!')
1129 auto k = dict->second.proxies.find(pname);
1130 if (k == dict->second.proxies.end()) {
1131 std::cerr <<
"failed to find key matching proxy '" << pname <<
"' for type '" << dict->second.type
1132 <<
"', encountered in '" << func.
GetName() <<
"', skipping" << std::endl;
1137 if (k->second.empty())
1144 if (isLiteralConstVar(*
r->absArg())) {
1145 elem[k->second] <<
static_cast<RooConstVar *
>(
r->absArg())->getVal();
1147 elem[k->second] <<
r->absArg()->GetName();
1175 if (!::isValidName(
name)) {
1176 std::stringstream ss;
1177 ss <<
"RooJSONFactoryWSTool() function name '" <<
name <<
"' is not valid!" << std::endl;
1187 std::stringstream ss;
1188 ss <<
"RooJSONFactoryWSTool() function node " +
name +
" is not a map!";
1192 std::string prefix = genPrefix(
p,
true);
1193 if (!prefix.empty())
1195 if (!
p.has_child(
"type")) {
1196 std::stringstream ss;
1197 ss <<
"RooJSONFactoryWSTool() no type given for function '" <<
name <<
"', skipping." << std::endl;
1202 std::string functype(
p[
"type"].val());
1205 if (!importAllDependants) {
1210 auto it = importers.find(functype);
1212 if (it != importers.end()) {
1213 for (
auto &imp : it->second) {
1214 ok = imp->importArg(
this,
p);
1220 auto expr = factoryExpressions.find(functype);
1221 if (expr != factoryExpressions.end()) {
1222 std::string expression = ::generate(expr->second,
p,
this);
1224 std::stringstream ss;
1225 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1226 <<
"', skipping. expression was\n"
1227 << expression << std::endl;
1231 std::stringstream ss;
1232 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1234 <<
"there are several possible reasons for this:\n"
1235 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1236 <<
" 2. " << functype
1237 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1238 <<
" 3. something is wrong with your setup, e.g. you might have called "
1239 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1240 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1241 <<
"either way, please make sure that:\n"
1242 <<
" 3: you are reading a file with factory expressions - call "
1243 "RooFit::JSONIO::printFactoryExpressions() "
1244 "to see what is available\n"
1245 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1246 "https://github.com/root-project/root/blob/master/roofit/hs3/README.md to see "
1255 std::stringstream err;
1256 err <<
"something went wrong importing function '" <<
name <<
"'.";
1273 this->
importFunction((JSONTree::create(jsonString))->rootnode(), importAllDependants);
1290 auto &observablesNode =
output[
"axes"].set_seq();
1292 for (
auto *var : static_range_cast<RooRealVar *>(vars)) {
1294 obsNode[
"name"] << var->GetName();
1295 if (var->getBinning().isUniform()) {
1296 obsNode[
"min"] << var->getMin();
1297 obsNode[
"max"] << var->getMax();
1298 obsNode[
"nbins"] << var->getBins();
1300 auto &edges = obsNode[
"edges"];
1302 double val = var->getBinning().binLow(0);
1304 for (
int i = 0; i < var->getBinning().numBins(); ++i) {
1305 val = var->getBinning().binHigh(i);
1306 edges.append_child() << val;
1328 for (std::size_t i = 0; i <
n; ++i) {
1329 double w = contents[i];
1351 auto &labels = node[
"labels"].
set_seq();
1352 auto &indices = node[
"indices"].
set_seq();
1354 for (
auto const &item : cat) {
1356 if (std::isalpha(item.first[0])) {
1358 if (label != item.first) {
1359 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << item.first <<
"' to '" << label
1360 <<
"' to become a valid name";
1364 "' to make a valid name!");
1367 labels.append_child() << label;
1368 indices.append_child() << item.second;
1390 " has several category observables!");
1412 auto *combinedPdfInfoNode = findRooFitInternal(*
_rootnodeOutput,
"combined_distributions");
1413 if (combinedPdfInfoNode) {
1414 for (
auto &info : combinedPdfInfoNode->children()) {
1415 if (info[
"index_cat"].val() == cat->
GetName()) {
1425 std::unique_ptr<TList> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1427 for (
RooAbsData *absData : static_range_cast<RooAbsData *>(*dataList)) {
1428 std::string catName(absData->GetName());
1429 std::string dataName;
1430 if (std::isalpha(catName[0])) {
1432 if (dataName != catName) {
1433 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << catName <<
"' to '" << dataName
1434 <<
"' to become a valid name";
1438 "' to make a valid name!");
1441 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1442 datamap.
components[catName] = absData->GetName();
1465 " has several category observables!");
1478 output[
"type"] <<
"binned";
1491 if (
auto weightVar = variables.find(
"weightVar")) {
1492 variables.remove(*weightVar);
1501 if (
data.isWeighted() && variables.size() == 1) {
1502 bool isBinnedData =
false;
1503 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1504 std::vector<double> contents;
1506 for (; i <
data.numEntries(); ++i) {
1508 if (
x.getBin() != i)
1510 contents.push_back(
data.weight());
1512 if (i ==
x.getBins())
1513 isBinnedData =
true;
1515 output[
"type"] <<
"binned";
1520 output[
"type"] <<
"unbinned";
1525 auto &coords =
output[
"entries"].set_seq();
1526 auto *weights =
data.isWeighted() ? &
output[
"weights"].set_seq() :
nullptr;
1527 for (
int i = 0; i <
data.numEntries(); ++i) {
1529 coords.append_child().fill_seq(variables, [](
auto x) {
return static_cast<RooRealVar *
>(
x)->getVal(); });
1531 weights->append_child() <<
data.weight();
1549 if (node.has_child(
"edges")) {
1550 std::vector<double> edges;
1551 for (
auto const &bound : node[
"edges"].children()) {
1552 edges.push_back(bound.val_double());
1554 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(), edges[0],
1555 edges[edges.size() - 1]);
1556 RooBinning bins(obs->getMin(), obs->getMax());
1557 for (
auto b : edges) {
1560 obs->setBinning(bins);
1563 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(),
1564 node[
"min"].val_double(), node[
"max"].val_double());
1565 obs->setBins(node[
"nbins"].val_int());
1584std::unique_ptr<RooDataHist>
1587 if (!
n.has_child(
"contents"))
1590 JSONNode const &contents =
n[
"contents"];
1596 if (
n.has_child(
"errors")) {
1597 errors = &
n[
"errors"];
1602 auto bins = generateBinIndices(vars);
1604 std::stringstream errMsg;
1605 errMsg <<
"inconsistent bin numbers: contents=" << contents.
num_children() <<
", bins=" << bins.size();
1608 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1609 std::vector<double> contentVals;
1611 for (
auto const &cont : contents.
children()) {
1612 contentVals.push_back(cont.val_double());
1614 std::vector<double> errorVals;
1617 for (
auto const &err : errors->
children()) {
1618 errorVals.push_back(err.val_double());
1621 for (
size_t ibin = 0; ibin < bins.size(); ++ibin) {
1622 const double err = errors ? errorVals[ibin] : -1;
1623 dh->set(ibin, contentVals[ibin], err);
1642 if (!::isValidName(
name)) {
1643 std::stringstream ss;
1644 ss <<
"RooJSONFactoryWSTool() variable name '" <<
name <<
"' is not valid!" << std::endl;
1651 std::stringstream ss;
1652 ss <<
"RooJSONFactoryWSTool() node '" <<
name <<
"' is not a map, skipping.";
1653 oocoutE(
nullptr, InputArguments) << ss.str() << std::endl;
1659 if (attrNode->has_child(
"is_const_var") && (*attrNode)[
"is_const_var"].val_int() == 1) {
1660 wsEmplace<RooConstVar>(
name,
p[
"value"].val_double());
1665 configureVariable(*
_domains,
p, wsEmplace<RooRealVar>(
name, 1.));
1680 if (
JSONNode const *varsNode = getVariablesNode(
n)) {
1681 for (
const auto &
p : varsNode->children()) {
1685 if (
auto seq =
n.find(
"functions")) {
1686 for (
const auto &
p : seq->children()) {
1690 if (
auto seq =
n.find(
"distributions")) {
1691 for (
const auto &
p : seq->children()) {
1698 const std::vector<CombinedData> &combDataSets)
1701 if (pdf ==
nullptr) {
1702 warning(
"RooFitHS3 only supports ModelConfigs with RooSimultaneous! Skipping ModelConfig.");
1706 for (std::size_t i = 0; i < std::max(combDataSets.size(), std::size_t(1)); ++i) {
1707 const bool hasdata = i < combDataSets.size();
1708 if (hasdata && !matches(combDataSets.at(i), pdf))
1711 std::string analysisName(pdf->GetName());
1713 analysisName +=
"_" + combDataSets[i].name;
1720 std::string
const &analysisName,
1721 std::map<std::string, std::string>
const *dataComponents)
1729 analysisNode[
"likelihood"] << analysisName;
1732 nllNode[
"distributions"].set_seq();
1733 nllNode[
"data"].set_seq();
1735 if (dataComponents) {
1736 for (
auto const &item : pdf->indexCat()) {
1737 const auto &dataComp = dataComponents->find(item.first);
1738 nllNode[
"distributions"].append_child() << pdf->getPdf(item.first)->GetName();
1739 nllNode[
"data"].append_child() << dataComp->second;
1744 auto &extConstrNode = nllNode[
"aux_distributions"];
1745 extConstrNode.set_seq();
1747 extConstrNode.append_child() << constr->GetName();
1751 auto writeList = [&](
const char *
name,
RooArgSet const *args) {
1755 std::vector<std::string> names;
1756 names.reserve(args->size());
1758 names.push_back(arg->GetName());
1759 std::sort(names.begin(), names.end());
1765 auto &modelConfigAux =
getRooFitInternal(rootnode,
"ModelConfigs", analysisName);
1766 modelConfigAux.set_map();
1767 modelConfigAux[
"pdfName"] << pdf->GetName();
1768 modelConfigAux[
"mcName"] << mc.
GetName();
1782 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1787 std::vector<RooAbsPdf *> allpdfs;
1789 if (!arg->hasClients()) {
1790 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
1791 allpdfs.push_back(pdf);
1795 sortByName(allpdfs);
1796 std::set<std::string> exportedObjectNames;
1803 exportAttributes(arg,
n);
1807 std::vector<RooAbsData *> alldata;
1809 alldata.push_back(
d);
1811 sortByName(alldata);
1813 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
1814 for (
auto &
d : alldata) {
1816 if (!
data.components.empty())
1817 combData.push_back(
data);
1820 for (
auto &
d : alldata) {
1837 if (exportedObjectNames.find(arg->GetName()) != exportedObjectNames.end()) {
1838 bool do_export =
false;
1839 for (
const auto &pdf : allpdfs) {
1840 if (pdf->dependsOn(*arg)) {
1844 if (do_export && !::isValidName(arg->GetName())) {
1845 std::stringstream ss;
1846 ss <<
"RooJSONFactoryWSTool() variable '" << arg->GetName() <<
"' has an invalid name!" << std::endl;
1850 snapshotSorted.
add(*arg);
1853 snapshotSorted.
sort();
1854 std::string
name(snsh->GetName());
1855 if (
name !=
"default_values") {
1873 std::stringstream ss(s);
1885 std::stringstream ss(s);
1896 std::stringstream ss;
1908 std::stringstream ss;
1920 std::unique_ptr<JSONTree> tree = JSONTree::create();
1923 auto &metadata =
n[
"metadata"].set_map();
1930 std::string versionName =
gROOT->GetVersion();
1933 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
1934 rootInfo[
"version"] << versionName;
1962 std::ofstream out(
filename.c_str());
1963 if (!out.is_open()) {
1964 std::stringstream ss;
1965 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
1995 std::ofstream out(
filename.c_str());
1996 if (!out.is_open()) {
1997 std::stringstream ss;
1998 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
2010 if (
auto seq = attrNode->find(
"tags")) {
2011 for (
auto &
a : seq->children()) {
2012 if (
a.val() == attrib)
2022 auto &tags = (*node)[
"tags"];
2032 if (
auto dict = attrNode->find(
"dict")) {
2033 if (
auto *
a = dict->find(attrib)) {
2041 const std::string &
value)
2044 auto &dict = (*node)[
"dict"];
2046 dict[attrib] <<
value;
2062 auto metadata =
n.find(
"metadata");
2063 if (!metadata || !metadata->find(
"hs3_version")) {
2064 std::stringstream ss;
2065 ss <<
"The HS3 version is missing in the JSON!\n"
2066 <<
"Please include the HS3 version in the metadata field, e.g.:\n"
2067 <<
" \"metadata\" :\n"
2074 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2075 if (
auto domains =
n.find(
"domains")) {
2086 if (
auto paramPointsNode =
n.find(
"parameter_points")) {
2087 for (
const auto &snsh : paramPointsNode->children()) {
2090 if (!::isValidName(
name)) {
2091 std::stringstream ss;
2092 ss <<
"RooJSONFactoryWSTool() node name '" <<
name <<
"' is not valid!" << std::endl;
2097 for (
const auto &var : snsh[
"parameters"].children()) {
2099 configureVariable(*
_domains, var, *rrv);
2113 importAttributes(arg, elem);
2123 std::vector<std::unique_ptr<RooAbsData>> datasets;
2124 if (
auto dataNode =
n.find(
"data")) {
2125 for (
const auto &
p : dataNode->children()) {
2132 if (
auto analysesNode =
n.find(
"analyses")) {
2133 for (
JSONNode const &analysisNode : analysesNode->children()) {
2140 for (
auto const &
d : datasets) {
2158 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2172 std::ifstream infile(
filename.c_str());
2173 if (!infile.is_open()) {
2174 std::stringstream ss;
2175 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2191 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2205 std::ifstream infile(
filename.c_str());
2206 if (!infile.is_open()) {
2207 std::stringstream ss;
2208 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2221 bool isVariable =
true;
2222 if (
n.find(
"type")) {
2235 std::unique_ptr<RooFit::Detail::JSONTree> tree =
varJSONString(elementNode);
2237 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2238 if (
auto domains =
n.find(
"domains"))
2244 JSONNode const *varsNode = getVariablesNode(
n);
2245 const auto &
p = varsNode->
child(0);
2248 auto paramPointsNode =
n.find(
"parameter_points");
2249 const auto &snsh = paramPointsNode->child(0);
2252 const auto &var = snsh[
"parameters"].child(0);
2254 configureVariable(*
_domains, var, *rrv);
2262 importAttributes(arg, elem);
2291 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 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 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 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.
TIterator Use servers() and begin()
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
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....
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.
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.
bool defineType(const std::string &label)
Define a state with given name.
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 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.
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()