103std::vector<std::string> valsToStringVec(
JSONNode const &node)
105 std::vector<std::string> out;
108 out.push_back(elem.val());
140 std::vector<double> edges;
146 Var(
int n) : nbins(
n), min(0), max(
n) {}
165bool isNumber(
const std::string &str)
168 for (
char const &
c : str) {
169 if (std::isdigit(
c) == 0 &&
c !=
'.' && !(first && (
c ==
'-' ||
c ==
'+')))
185bool isValidName(
const std::string &str)
188 if (str.empty() || !(std::isalpha(str[0]) || str[0] ==
'_')) {
195 if (!(std::isalnum(
c) ||
c ==
'_')) {
220 if (!
p.has_child(
"name")) {
223 if (
auto n =
p.find(
"value"))
224 v.setVal(
n->val_double());
226 if (
auto n =
p.find(
"nbins"))
227 v.setBins(
n->val_int());
228 if (
auto n =
p.find(
"relErr"))
229 v.setError(
v.getVal() *
n->val_double());
230 if (
auto n =
p.find(
"err"))
231 v.setError(
n->val_double());
232 if (
auto n =
p.find(
"const")) {
233 v.setConstant(
n->val_bool());
235 v.setConstant(
false);
241 auto paramPointsNode = rootNode.
find(
"parameter_points");
242 if (!paramPointsNode)
247 return &((*out)[
"parameters"]);
252 if (val.
find(
"edges")) {
254 this->edges.push_back(
child.val_double());
256 this->nbins = this->edges.size();
257 this->min = this->edges[0];
258 this->max = this->edges[this->nbins - 1];
260 if (!val.
find(
"nbins")) {
263 this->nbins = val[
"nbins"].
val_int();
265 if (!val.
find(
"min")) {
270 if (!val.
find(
"max")) {
278std::string genPrefix(
const JSONNode &
p,
bool trailing_underscore)
283 if (
auto node =
p.find(
"namespaces")) {
284 for (
const auto &ns : node->
children()) {
290 if (trailing_underscore && !prefix.empty())
296void genIndicesHelper(std::vector<std::vector<int>> &combinations, std::vector<int> &curr_comb,
297 const std::vector<int> &vars_numbins,
size_t curridx)
299 if (curridx == vars_numbins.size()) {
301 combinations.emplace_back(curr_comb);
303 for (
int i = 0; i < vars_numbins[curridx]; ++i) {
304 curr_comb[curridx] = i;
305 ::genIndicesHelper(combinations, curr_comb, vars_numbins, curridx + 1);
322 if (
auto seq = node.
find(
"dict")) {
323 for (
const auto &
attr : seq->children()) {
327 if (
auto seq = node.
find(
"tags")) {
328 for (
const auto &
attr : seq->children()) {
337 std::stringstream expression;
338 std::string classname(
ex.tclass->GetName());
339 size_t colon = classname.find_last_of(
':');
340 expression << (colon < classname.size() ? classname.substr(colon + 1) : classname);
343 for (
auto k :
ex.arguments) {
344 expression << (first ?
"::" +
name +
"(" :
",");
346 if (k ==
"true" || k ==
"false") {
347 expression << (k ==
"true" ?
"1" :
"0");
348 }
else if (!
p.has_child(k)) {
349 std::stringstream errMsg;
350 errMsg <<
"node '" <<
name <<
"' is missing key '" << k <<
"'";
352 }
else if (
p[k].is_seq()) {
353 bool firstInner =
true;
355 expression << (firstInner ?
"{" :
",") << arg->
GetName();
361 expression <<
p[k].val();
365 return expression.str();
378std::vector<std::vector<int>> generateBinIndices(
const RooArgSet &vars)
380 std::vector<std::vector<int>> combinations;
381 std::vector<int> vars_numbins;
382 vars_numbins.reserve(vars.
size());
383 for (
const auto *absv : static_range_cast<RooRealVar *>(vars)) {
384 vars_numbins.push_back(absv->getBins());
386 std::vector<int> curr_comb(vars.
size());
387 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
391template <
typename... Keys_t>
392JSONNode const *findRooFitInternal(
JSONNode const &node, Keys_t
const &...keys)
394 return node.
find(
"misc",
"ROOT_internal", keys...);
406bool isLiteralConstVar(
RooAbsArg const &arg)
408 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(&arg);
409 return isRooConstVar && isNumber(arg.
GetName());
424 if (isLiteralConstVar(*arg)) {
430 auto initializeNode = [&]() {
440 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(arg);
443 (*node)[
"is_const_var"] << 1;
450 if (it.first ==
"factory_tag" || it.first ==
"PROD_TERM_TYPE")
453 (*node)[
"dict"].set_map()[it.first] << it.second;
459 if (
attr ==
"SnapShot_ExtRefClone" ||
attr ==
"RooRealConstant_Factory_Object")
462 (*node)[
"tags"].set_seq().append_child() <<
attr;
482 std::map<std::string, Var> vars;
483 for (
const auto &
p : node[
"axes"].
children()) {
487 for (
auto v : vars) {
488 std::string
name(
v.first);
492 std::stringstream errMsg;
493 errMsg <<
"The observable \"" <<
name <<
"\" could not be found in the workspace!";
514 if (!::isValidName(
name)) {
515 std::stringstream ss;
516 ss <<
"RooJSONFactoryWSTool() data name '" <<
name <<
"' is not valid!" << std::endl;
520 std::string
const &
type =
p[
"type"].val();
521 if (
type ==
"binned") {
524 }
else if (
type ==
"unbinned") {
527 getObservables(workspace,
p, vars);
530 auto &coords =
p[
"entries"];
531 auto &weights =
p[
"weights"];
532 if (coords.num_children() != weights.num_children()) {
535 if (!coords.is_seq()) {
538 std::vector<double> weightVals;
539 for (
auto const &weight : weights.children()) {
540 weightVals.push_back(weight.val_double());
543 for (
auto const &point : coords.children()) {
544 if (!point.is_seq()) {
545 std::stringstream errMsg;
546 errMsg <<
"coordinate point '" << i <<
"' is not a list!";
549 if (point.num_children() != varlist.
size()) {
553 for (
auto const &pointj : point.children()) {
555 v->
setVal(pointj.val_double());
558 data->add(vars, weightVals[i]);
564 std::stringstream ss;
565 ss <<
"RooJSONFactoryWSTool() failed to create dataset " <<
name << std::endl;
585 RooWorkspace &workspace,
const std::vector<std::unique_ptr<RooAbsData>> &datasets)
589 JSONNode const *mcAuxNode = findRooFitInternal(rootnode,
"ModelConfigs", analysisName);
591 JSONNode const *mcNameNode = mcAuxNode ? mcAuxNode->
find(
"mcName") :
nullptr;
592 std::string mcname = mcNameNode ? mcNameNode->
val() : analysisName;
593 if (workspace.
obj(mcname))
598 mc->
SetWS(workspace);
600 std::vector<std::string> nllDataNames;
604 throw std::runtime_error(
"likelihood node not found!");
606 std::vector<std::string> nllDistNames = valsToStringVec((*nllNode)[
"distributions"]);
608 for (
auto &nameNode : (*nllNode)[
"aux_distributions"].children()) {
609 if (
RooAbsArg *extConstraint = workspace.
arg(nameNode.val())) {
610 extConstraints.
add(*extConstraint);
614 for (
auto &nameNode : (*nllNode)[
"data"].children()) {
615 nllDataNames.push_back(nameNode.val());
616 for (
const auto &
d : datasets) {
617 if (
d->GetName() == nameNode.val()) {
618 observables.
add(*
d->get());
623 JSONNode const *pdfNameNode = mcAuxNode ? mcAuxNode->
find(
"pdfName") :
nullptr;
624 std::string
const pdfName = pdfNameNode ? pdfNameNode->
val() :
"simPdf";
630 if (nllDistNames.size() == 1) {
632 pdf = workspace.
pdf(nllDistNames[0]);
635 std::string simPdfName = analysisName +
"_simPdf";
636 std::string indexCatName = analysisName +
"_categoryIndex";
637 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
638 std::map<std::string, RooAbsPdf *> pdfMap;
639 for (std::size_t i = 0; i < nllDistNames.size(); ++i) {
641 pdfMap[nllDistNames[i]] = workspace.
pdf(nllDistNames[i]);
643 RooSimultaneous simPdf{simPdfName.c_str(), simPdfName.c_str(), pdfMap, indexCat};
651 if (!extConstraints.
empty())
652 mc->SetExternalConstraints(extConstraints);
654 auto readArgSet = [&](std::string
const &
name) {
657 out.add(*workspace.
arg(
child.val()));
662 mc->SetParametersOfInterest(readArgSet(
"parameters_of_interest"));
663 mc->SetObservables(observables);
675 for (
const auto &
p : pars) {
676 if (mc->GetParametersOfInterest()->find(*
p))
678 if (
p->isConstant() && !mainPars.find(*
p)) {
684 mc->SetGlobalObservables(globs);
685 mc->SetNuisanceParameters(nps);
688 if (
auto found = mcAuxNode->
find(
"combined_data_name")) {
696 auto *combinedPdfInfoNode = findRooFitInternal(rootnode,
"combined_distributions");
699 if (combinedPdfInfoNode ==
nullptr) {
703 for (
auto &info : combinedPdfInfoNode->children()) {
706 std::string combinedName = info.key();
707 std::string indexCatName = info[
"index_cat"].val();
708 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
709 std::vector<int> indices;
710 std::vector<std::string> pdfNames = valsToStringVec(info[
"distributions"]);
711 for (
auto &
n : info[
"indices"].children()) {
712 indices.push_back(
n.val_int());
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 = valsToStringVec(info[
"labels"]);
743 std::vector<int> indices;
744 for (
auto &
n : info[
"indices"].children()) {
745 indices.push_back(
n.val_int());
747 if (indices.size() != labels.size()) {
752 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
753 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
755 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
756 auto componentName = combinedName +
"_" + labels[iChannel];
759 std::unique_ptr<RooAbsData> &component = *std::find_if(
760 datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
763 allVars.add(*component->get());
764 dsMap.insert({labels[iChannel], std::move(component)});
765 indexCat.defineType(labels[iChannel], indices[iChannel]);
768 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
770 datasets.emplace_back(std::move(combined));
775void sortByName(T &coll)
777 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
794 if (isLiteralConstVar(*arg)) {
802 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
840 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
844RooRealVar *RooJSONFactoryWSTool::requestImpl<RooRealVar>(
const std::string &objname)
849 if (
auto node = vars->find(objname)) {
859RooAbsPdf *RooJSONFactoryWSTool::requestImpl<RooAbsPdf>(
const std::string &objname)
874RooAbsReal *RooJSONFactoryWSTool::requestImpl<RooAbsReal>(
const std::string &objname)
878 if (isNumber(objname))
880 if (
RooAbsPdf *pdf = requestImpl<RooAbsPdf>(objname))
882 if (
RooRealVar *var = requestImpl<RooRealVar>(objname))
924 var[
"value"] << cv->getVal();
925 var[
"const"] <<
true;
927 var[
"value"] << rrv->getVal();
928 if (rrv->isConstant()) {
929 var[
"const"] << rrv->isConstant();
931 if (rrv->getBins() != 100) {
932 var[
"nbins"] << rrv->getBins();
957 const std::string &formula)
959 std::string newname = std::string(original->
GetName()) + suffix;
961 trafo_node[
"type"] <<
"generic_function";
983 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
986 exportedObjectNames.insert(
name);
993 std::vector<std::string> channelNames;
994 for (
auto const &item : simPdf->indexCat()) {
995 channelNames.push_back(item.first);
999 auto &
child = infoNode[simPdf->GetName()].set_map();
1000 child[
"index_cat"] << simPdf->indexCat().GetName();
1002 child[
"distributions"].set_seq();
1003 for (
auto const &item : simPdf->indexCat()) {
1004 child[
"distributions"].append_child() << simPdf->getPdf(item.first.c_str())->GetName();
1016 auto &collectionNode = (*_rootnodeOutput)[
dynamic_cast<RooAbsPdf const *
>(&func) ?
"distributions" :
"functions"];
1025 auto it = exporters.find(cl);
1026 if (it != exporters.end()) {
1027 for (
auto &exp : it->second) {
1029 if (!exp->exportObject(
this, &func, elem)) {
1035 elem[
"name"] <<
name;
1039 if (exp->autoExportDependants()) {
1049 const auto &dict = exportKeys.find(cl);
1050 if (dict == exportKeys.end()) {
1051 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1052 <<
"there are several possible reasons for this:\n"
1053 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1055 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1056 <<
" 3. something is wrong with your setup, e.g. you might have called "
1057 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1058 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1059 <<
"either way, please make sure that:\n"
1060 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1061 "see what is available\n"
1062 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1063 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to "
1064 "see how to do this!\n";
1068 elem[
"type"] << dict->second.type;
1072 for (
size_t i = 0; i < nprox; ++i) {
1076 std::string pname(
p->name());
1077 if (pname[0] ==
'!')
1080 auto k = dict->second.proxies.find(pname);
1081 if (k == dict->second.proxies.end()) {
1082 std::cerr <<
"failed to find key matching proxy '" << pname <<
"' for type '" << dict->second.type
1083 <<
"', encountered in '" << func.
GetName() <<
"', skipping" << std::endl;
1088 if (k->second.empty())
1095 if (isLiteralConstVar(*
r->absArg())) {
1096 elem[k->second] <<
static_cast<RooConstVar *
>(
r->absArg())->getVal();
1098 elem[k->second] <<
r->absArg()->GetName();
1132 if (!::isValidName(
name)) {
1133 std::stringstream ss;
1134 ss <<
"RooJSONFactoryWSTool() function name '" <<
name <<
"' is not valid!" << std::endl;
1144 std::stringstream ss;
1145 ss <<
"RooJSONFactoryWSTool() function node " +
name +
" is not a map!";
1149 std::string prefix = genPrefix(
p,
true);
1150 if (!prefix.empty())
1152 if (!
p.has_child(
"type")) {
1153 std::stringstream ss;
1154 ss <<
"RooJSONFactoryWSTool() no type given for function '" <<
name <<
"', skipping." << std::endl;
1159 std::string functype(
p[
"type"].val());
1162 if (!importAllDependants) {
1167 auto it = importers.find(functype);
1169 if (it != importers.end()) {
1170 for (
auto &imp : it->second) {
1171 ok = imp->importArg(
this,
p);
1177 auto expr = factoryExpressions.find(functype);
1178 if (expr != factoryExpressions.end()) {
1179 std::string expression = ::generate(expr->second,
p,
this);
1181 std::stringstream ss;
1182 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1183 <<
"', skipping. expression was\n"
1184 << expression << std::endl;
1188 std::stringstream ss;
1189 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1191 <<
"there are several possible reasons for this:\n"
1192 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1193 <<
" 2. " << functype
1194 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1195 <<
" 3. something is wrong with your setup, e.g. you might have called "
1196 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1197 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1198 <<
"either way, please make sure that:\n"
1199 <<
" 3: you are reading a file with factory expressions - call "
1200 "RooFit::JSONIO::printFactoryExpressions() "
1201 "to see what is available\n"
1202 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1203 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to see "
1212 std::stringstream err;
1213 err <<
"something went wrong importing function '" <<
name <<
"'.";
1230 this->
importFunction((JSONTree::create(jsonString))->rootnode(), importAllDependants);
1247 auto &observablesNode =
output[
"axes"].set_seq();
1249 for (
auto *var : static_range_cast<RooRealVar *>(vars)) {
1251 obsNode[
"name"] << var->GetName();
1252 if (var->getBinning().isUniform()) {
1253 obsNode[
"min"] << var->getMin();
1254 obsNode[
"max"] << var->getMax();
1255 obsNode[
"nbins"] << var->getBins();
1257 auto &edges = obsNode[
"edges"];
1259 double val = var->getBinning().binLow(0);
1261 for (
int i = 0; i < var->getBinning().numBins(); ++i) {
1262 val = var->getBinning().binHigh(i);
1263 edges.append_child() << val;
1285 for (std::size_t i = 0; i <
n; ++i) {
1286 double w = contents[i];
1308 auto &labels = node[
"labels"].
set_seq();
1309 auto &indices = node[
"indices"].
set_seq();
1311 for (
auto const &item : cat) {
1313 if (std::isalpha(item.first[0])) {
1315 if (label != item.first) {
1316 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << item.first <<
"' to '" << label
1317 <<
"' to become a valid name";
1321 "' to make a valid name!");
1324 labels.append_child() << label;
1325 indices.append_child() << item.second;
1347 " has several category observables!");
1369 auto *combinedPdfInfoNode = findRooFitInternal(*
_rootnodeOutput,
"combined_distributions");
1370 if (combinedPdfInfoNode) {
1371 for (
auto &info : combinedPdfInfoNode->children()) {
1372 if (info[
"index_cat"].val() == cat->
GetName()) {
1382 std::unique_ptr<TList> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1384 for (
RooAbsData *absData : static_range_cast<RooAbsData *>(*dataList)) {
1385 std::string catName(absData->GetName());
1386 std::string dataName;
1387 if (std::isalpha(catName[0])) {
1389 if (dataName != catName) {
1390 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << catName <<
"' to '" << dataName
1391 <<
"' to become a valid name";
1395 "' to make a valid name!");
1398 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1399 datamap.
components[catName] = absData->GetName();
1422 " has several category observables!");
1435 output[
"type"] <<
"binned";
1448 if (
auto weightVar = variables.find(
"weightVar")) {
1449 variables.remove(*weightVar);
1458 if (
data.isWeighted() && variables.size() == 1) {
1459 bool isBinnedData =
false;
1460 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1461 std::vector<double> contents;
1463 for (; i <
data.numEntries(); ++i) {
1465 if (
x.getBin() != i)
1467 contents.push_back(
data.weight());
1469 if (i ==
x.getBins())
1470 isBinnedData =
true;
1472 output[
"type"] <<
"binned";
1477 output[
"type"] <<
"unbinned";
1482 auto &coords =
output[
"entries"].set_seq();
1483 auto *weights =
data.isWeighted() ? &
output[
"weights"].set_seq() :
nullptr;
1484 for (
int i = 0; i <
data.numEntries(); ++i) {
1486 coords.append_child().fill_seq(variables, [](
auto x) {
return static_cast<RooRealVar *
>(
x)->getVal(); });
1488 weights->append_child() <<
data.weight();
1506 if (node.has_child(
"edges")) {
1507 std::vector<double> edges;
1508 for (
auto const &bound : node[
"edges"].children()) {
1509 edges.push_back(bound.val_double());
1511 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(), edges[0],
1512 edges[edges.size() - 1]);
1513 RooBinning bins(obs->getMin(), obs->getMax());
1514 for (
auto b : edges) {
1517 obs->setBinning(bins);
1520 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(),
1521 node[
"min"].val_double(), node[
"max"].val_double());
1522 obs->setBins(node[
"nbins"].val_int());
1541std::unique_ptr<RooDataHist>
1544 if (!
n.has_child(
"contents"))
1547 JSONNode const &contents =
n[
"contents"];
1553 if (
n.has_child(
"errors")) {
1554 errors = &
n[
"errors"];
1559 auto bins = generateBinIndices(vars);
1561 std::stringstream errMsg;
1562 errMsg <<
"inconsistent bin numbers: contents=" << contents.
num_children() <<
", bins=" << bins.size();
1565 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1566 std::vector<double> contentVals;
1568 for (
auto const &cont : contents.
children()) {
1569 contentVals.push_back(cont.val_double());
1571 std::vector<double> errorVals;
1574 for (
auto const &err : errors->
children()) {
1575 errorVals.push_back(err.val_double());
1578 for (
size_t ibin = 0; ibin < bins.size(); ++ibin) {
1579 const double err = errors ? errorVals[ibin] : -1;
1580 dh->set(ibin, contentVals[ibin], err);
1599 if (!::isValidName(
name)) {
1600 std::stringstream ss;
1601 ss <<
"RooJSONFactoryWSTool() variable name '" <<
name <<
"' is not valid!" << std::endl;
1608 std::stringstream ss;
1609 ss <<
"RooJSONFactoryWSTool() node '" <<
name <<
"' is not a map, skipping.";
1610 oocoutE(
nullptr, InputArguments) << ss.str() << std::endl;
1616 if (attrNode->has_child(
"is_const_var") && (*attrNode)[
"is_const_var"].val_int() == 1) {
1617 wsEmplace<RooConstVar>(
name,
p[
"value"].val_double());
1622 configureVariable(*
_domains,
p, wsEmplace<RooRealVar>(
name, 1.));
1637 if (
JSONNode const *varsNode = getVariablesNode(
n)) {
1638 for (
const auto &
p : varsNode->children()) {
1642 if (
auto seq =
n.find(
"functions")) {
1643 for (
const auto &
p : seq->children()) {
1647 if (
auto seq =
n.find(
"distributions")) {
1648 for (
const auto &
p : seq->children()) {
1655 const std::vector<CombinedData> &combDataSets)
1658 if (pdf ==
nullptr) {
1659 warning(
"RooFitHS3 only supports ModelConfigs with RooSimultaneous! Skipping ModelConfig.");
1663 for (std::size_t i = 0; i < std::max(combDataSets.size(), std::size_t(1)); ++i) {
1664 const bool hasdata = i < combDataSets.size();
1665 if (hasdata && !matches(combDataSets.at(i), pdf))
1668 std::string analysisName(pdf->GetName());
1670 analysisName +=
"_" + combDataSets[i].name;
1677 std::string
const &analysisName,
1678 std::map<std::string, std::string>
const *dataComponents)
1686 analysisNode[
"likelihood"] << analysisName;
1689 nllNode[
"distributions"].set_seq();
1690 nllNode[
"data"].set_seq();
1692 if (dataComponents) {
1693 for (
auto const &item : pdf->indexCat()) {
1694 const auto &dataComp = dataComponents->find(item.first);
1695 nllNode[
"distributions"].append_child() << pdf->getPdf(item.first)->GetName();
1696 nllNode[
"data"].append_child() << dataComp->second;
1701 auto &extConstrNode = nllNode[
"aux_distributions"];
1702 extConstrNode.set_seq();
1704 extConstrNode.append_child() << constr->GetName();
1708 auto writeList = [&](
const char *
name,
RooArgSet const *args) {
1712 std::vector<std::string> names;
1713 names.reserve(args->size());
1715 names.push_back(arg->GetName());
1716 std::sort(names.begin(), names.end());
1722 auto &modelConfigAux =
getRooFitInternal(rootnode,
"ModelConfigs", analysisName);
1723 modelConfigAux.set_map();
1724 modelConfigAux[
"pdfName"] << pdf->GetName();
1725 modelConfigAux[
"mcName"] << mc.
GetName();
1739 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1744 std::vector<RooAbsPdf *> allpdfs;
1746 if (!arg->hasClients()) {
1747 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
1748 allpdfs.push_back(pdf);
1752 sortByName(allpdfs);
1753 std::set<std::string> exportedObjectNames;
1758 exportAttributes(arg,
n);
1762 std::vector<RooAbsData *> alldata;
1764 alldata.push_back(
d);
1766 sortByName(alldata);
1768 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
1769 for (
auto &
d : alldata) {
1771 if (!
data.components.empty())
1772 combData.push_back(
data);
1775 for (
auto &
d : alldata) {
1792 if (exportedObjectNames.find(arg->GetName()) != exportedObjectNames.end()) {
1793 bool do_export =
false;
1794 for (
const auto &pdf : allpdfs) {
1795 if (pdf->dependsOn(*arg)) {
1799 if (do_export && !::isValidName(arg->GetName())) {
1800 std::stringstream ss;
1801 ss <<
"RooJSONFactoryWSTool() variable '" << arg->GetName() <<
"' has an invalid name!" << std::endl;
1805 snapshotSorted.
add(*arg);
1808 snapshotSorted.
sort();
1809 std::string
name(snsh->GetName());
1810 if (
name !=
"default_values") {
1828 std::stringstream ss(s);
1840 std::stringstream ss(s);
1851 std::stringstream ss;
1863 std::stringstream ss;
1875 std::unique_ptr<JSONTree> tree = JSONTree::create();
1878 auto &metadata =
n[
"metadata"].set_map();
1885 std::string versionName =
gROOT->GetVersion();
1888 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
1889 rootInfo[
"version"] << versionName;
1917 std::ofstream out(
filename.c_str());
1918 if (!out.is_open()) {
1919 std::stringstream ss;
1920 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
1950 std::ofstream out(
filename.c_str());
1951 if (!out.is_open()) {
1952 std::stringstream ss;
1953 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
1965 if (
auto seq = attrNode->find(
"tags")) {
1966 for (
auto &
a : seq->children()) {
1967 if (
a.val() == attrib)
1977 auto &tags = (*node)[
"tags"];
1987 if (
auto dict = attrNode->find(
"dict")) {
1988 if (
auto *
a = dict->find(attrib)) {
1996 const std::string &
value)
1999 auto &dict = (*node)[
"dict"];
2001 dict[attrib] <<
value;
2017 auto metadata =
n.find(
"metadata");
2018 if (!metadata || !metadata->find(
"hs3_version")) {
2019 std::stringstream ss;
2020 ss <<
"The HS3 version is missing in the JSON!\n"
2021 <<
"Please include the HS3 version in the metadata field, e.g.:\n"
2022 <<
" \"metadata\" :\n"
2029 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2030 if (
auto domains =
n.find(
"domains")) {
2041 if (
auto paramPointsNode =
n.find(
"parameter_points")) {
2042 for (
const auto &snsh : paramPointsNode->children()) {
2045 if (!::isValidName(
name)) {
2046 std::stringstream ss;
2047 ss <<
"RooJSONFactoryWSTool() node name '" <<
name <<
"' is not valid!" << std::endl;
2052 for (
const auto &var : snsh[
"parameters"].children()) {
2054 configureVariable(*
_domains, var, *rrv);
2068 importAttributes(arg, elem);
2078 std::vector<std::unique_ptr<RooAbsData>> datasets;
2079 if (
auto dataNode =
n.find(
"data")) {
2080 for (
const auto &
p : dataNode->children()) {
2087 if (
auto analysesNode =
n.find(
"analyses")) {
2088 for (
JSONNode const &analysisNode : analysesNode->children()) {
2095 for (
auto const &
d : datasets) {
2113 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2127 std::ifstream infile(
filename.c_str());
2128 if (!infile.is_open()) {
2129 std::stringstream ss;
2130 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2146 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2160 std::ifstream infile(
filename.c_str());
2161 if (!infile.is_open()) {
2162 std::stringstream ss;
2163 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2176 bool isVariable =
true;
2177 if (
n.find(
"type")) {
2190 std::unique_ptr<RooFit::Detail::JSONTree> tree =
varJSONString(elementNode);
2192 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2193 if (
auto domains =
n.find(
"domains"))
2199 JSONNode const *varsNode = getVariablesNode(
n);
2200 const auto &
p = varsNode->
child(0);
2203 auto paramPointsNode =
n.find(
"parameter_points");
2204 const auto &snsh = paramPointsNode->child(0);
2207 const auto &var = snsh[
"parameters"].child(0);
2209 configureVariable(*
_domains, var, *rrv);
2217 importAttributes(arg, elem);
2246 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
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()