122std::vector<std::string> valsToStringVec(
JSONNode const &node)
124 std::vector<std::string> out;
127 out.push_back(elem.val());
159 std::vector<double> edges;
165 Var(
int n) : nbins(
n), min(0), max(
n) {}
184bool isNumber(
const std::string &str)
187 for (
char const &
c : str) {
188 if (std::isdigit(
c) == 0 &&
c !=
'.' && !(first && (
c ==
'-' ||
c ==
'+')))
204bool isValidName(
const std::string &str)
207 if (str.empty() || !(std::isalpha(str[0]) || str[0] ==
'_')) {
214 if (!(std::isalnum(
c) ||
c ==
'_')) {
242 if (
auto n = p.
find(
"value"))
243 v.setVal(
n->val_double());
245 if (
auto n = p.
find(
"nbins"))
246 v.setBins(
n->val_int());
247 if (
auto n = p.
find(
"relErr"))
248 v.setError(
v.getVal() *
n->val_double());
249 if (
auto n = p.
find(
"err"))
250 v.setError(
n->val_double());
251 if (
auto n = p.
find(
"const")) {
252 v.setConstant(
n->val_bool());
254 v.setConstant(
false);
260 auto paramPointsNode = rootNode.
find(
"parameter_points");
261 if (!paramPointsNode)
266 return &((*out)[
"parameters"]);
271 if (val.
find(
"edges")) {
273 this->edges.push_back(
child.val_double());
275 this->nbins = this->edges.size();
276 this->min = this->edges[0];
277 this->max = this->edges[this->nbins - 1];
279 if (!val.
find(
"nbins")) {
282 this->nbins = val[
"nbins"].
val_int();
284 if (!val.
find(
"min")) {
289 if (!val.
find(
"max")) {
297std::string genPrefix(
const JSONNode &p,
bool trailing_underscore)
302 if (
auto node = p.
find(
"namespaces")) {
303 for (
const auto &ns : node->
children()) {
309 if (trailing_underscore && !prefix.empty())
315void genIndicesHelper(std::vector<std::vector<int>> &combinations, std::vector<int> &curr_comb,
316 const std::vector<int> &vars_numbins,
size_t curridx)
318 if (curridx == vars_numbins.size()) {
320 combinations.emplace_back(curr_comb);
322 for (
int i = 0;
i < vars_numbins[curridx]; ++
i) {
323 curr_comb[curridx] =
i;
324 ::genIndicesHelper(combinations, curr_comb, vars_numbins, curridx + 1);
341 if (
auto seq = node.
find(
"dict")) {
342 for (
const auto &
attr : seq->children()) {
346 if (
auto seq = node.
find(
"tags")) {
347 for (
const auto &
attr : seq->children()) {
356 std::stringstream expression;
357 std::string classname(
ex.tclass->GetName());
358 size_t colon = classname.find_last_of(
':');
359 expression << (colon < classname.size() ? classname.substr(colon + 1) : classname);
362 for (
auto k :
ex.arguments) {
363 expression << (first ?
"::" +
name +
"(" :
",");
365 if (k ==
"true" || k ==
"false") {
366 expression << (k ==
"true" ?
"1" :
"0");
368 std::stringstream errMsg;
369 errMsg <<
"node '" <<
name <<
"' is missing key '" << k <<
"'";
371 }
else if (p[k].is_seq()) {
372 bool firstInner =
true;
375 expression << (firstInner ?
"" :
",") << arg->
GetName();
381 expression << p[k].val();
385 return expression.str();
398std::vector<std::vector<int>> generateBinIndices(
const RooArgSet &vars)
400 std::vector<std::vector<int>> combinations;
401 std::vector<int> vars_numbins;
402 vars_numbins.reserve(vars.
size());
404 vars_numbins.push_back(absv->getBins());
406 std::vector<int> curr_comb(vars.
size());
407 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
411template <
typename... Keys_t>
412JSONNode const *findRooFitInternal(
JSONNode const &node, Keys_t
const &...keys)
414 return node.
find(
"misc",
"ROOT_internal", keys...);
426bool isLiteralConstVar(
RooAbsArg const &arg)
428 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(&arg);
429 return isRooConstVar && isNumber(arg.
GetName());
444 if (isLiteralConstVar(*arg)) {
450 auto initializeNode = [&]() {
468 if (it.first ==
"factory_tag" || it.first ==
"PROD_TERM_TYPE")
471 (*node)[
"dict"].set_map()[it.first] << it.second;
477 if (
attr ==
"SnapShot_ExtRefClone" ||
attr ==
"RooRealConstant_Factory_Object")
480 (*node)[
"tags"].set_seq().append_child() <<
attr;
500 std::map<std::string, Var> vars;
501 for (
const auto &p : node[
"axes"].children()) {
505 for (
auto v : vars) {
506 std::string
name(
v.first);
510 std::stringstream errMsg;
511 errMsg <<
"The observable \"" <<
name <<
"\" could not be found in the workspace!";
532 if (!::isValidName(
name)) {
533 std::stringstream ss;
534 ss <<
"RooJSONFactoryWSTool() data name '" <<
name <<
"' is not valid!" << std::endl;
538 std::string
const &
type = p[
"type"].
val();
539 if (
type ==
"binned") {
542 }
else if (
type ==
"unbinned") {
545 getObservables(workspace, p, vars);
548 auto &coords = p[
"entries"];
549 if (!coords.is_seq()) {
552 std::vector<double> weightVals;
554 auto &weights = p[
"weights"];
555 if (coords.num_children() != weights.num_children()) {
558 for (
auto const &weight : weights.children()) {
559 weightVals.push_back(weight.val_double());
563 for (
auto const &point : coords.children()) {
564 if (!point.is_seq()) {
565 std::stringstream errMsg;
566 errMsg <<
"coordinate point '" <<
i <<
"' is not a list!";
569 if (point.num_children() != varlist.
size()) {
573 for (
auto const &pointj : point.children()) {
575 v->setVal(pointj.val_double());
578 if (weightVals.size() > 0) {
579 data->add(vars, weightVals[
i]);
588 std::stringstream ss;
589 ss <<
"RooJSONFactoryWSTool() failed to create dataset " <<
name << std::endl;
611 const std::vector<std::unique_ptr<RooAbsData>> &datasets)
615 JSONNode const *mcAuxNode = findRooFitInternal(rootnode,
"ModelConfigs", analysisName);
617 JSONNode const *mcNameNode = mcAuxNode ? mcAuxNode->
find(
"mcName") :
nullptr;
618 std::string mcname = mcNameNode ? mcNameNode->
val() : analysisName;
619 if (workspace.
obj(mcname))
624 mc->
SetWS(workspace);
626 std::vector<std::string> nllDataNames;
630 throw std::runtime_error(
"likelihood node not found!");
632 if (!nllNode->has_child(
"distributions")) {
633 throw std::runtime_error(
"likelihood node has no distributions attached!");
635 if (!nllNode->has_child(
"data")) {
636 throw std::runtime_error(
"likelihood node has no data attached!");
638 std::vector<std::string> nllDistNames = valsToStringVec((*nllNode)[
"distributions"]);
640 for (
auto &nameNode : (*nllNode)[
"aux_distributions"].children()) {
641 if (
RooAbsArg *extConstraint = workspace.
arg(nameNode.val())) {
642 extConstraints.
add(*extConstraint);
646 for (
auto &nameNode : (*nllNode)[
"data"].children()) {
647 nllDataNames.push_back(nameNode.val());
648 for (
const auto &
d : datasets) {
649 if (
d->GetName() == nameNode.val()) {
650 observables.
add(*
d->get());
655 JSONNode const *pdfNameNode = mcAuxNode ? mcAuxNode->
find(
"pdfName") :
nullptr;
656 std::string
const pdfName = pdfNameNode ? pdfNameNode->
val() :
"simPdf";
662 if (nllDistNames.size() == 1) {
664 pdf = workspace.
pdf(nllDistNames[0]);
667 std::string simPdfName = analysisName +
"_simPdf";
668 std::string indexCatName = analysisName +
"_categoryIndex";
669 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
670 std::map<std::string, RooAbsPdf *> pdfMap;
671 for (std::size_t
i = 0;
i < nllDistNames.size(); ++
i) {
672 indexCat.defineType(nllDistNames[
i],
i);
673 pdfMap[nllDistNames[
i]] = workspace.
pdf(nllDistNames[
i]);
675 RooSimultaneous simPdf{simPdfName.c_str(), simPdfName.c_str(), pdfMap, indexCat};
683 if (!extConstraints.
empty())
684 mc->SetExternalConstraints(extConstraints);
686 auto readArgSet = [&](std::string
const &
name) {
688 for (
auto const &
child : analysisNode[
name].children()) {
689 out.add(*workspace.
arg(
child.val()));
694 mc->SetParametersOfInterest(readArgSet(
"parameters_of_interest"));
695 mc->SetObservables(observables);
706 for (
auto &domain : analysisNode[
"domains"].children()) {
708 if (!thisDomain || !thisDomain->has_child(
"axes"))
710 for (
auto &var : (*thisDomain)[
"axes"].children()) {
713 domainPars.
add(*wsvar);
719 for (
const auto &p : pars) {
720 if (mc->GetParametersOfInterest()->find(*p))
722 if (p->isConstant() && !mainPars.
find(*p)) {
724 }
else if (domainPars.
find(*p)) {
728 mc->SetGlobalObservables(globs);
729 mc->SetNuisanceParameters(nps);
732 if (
auto found = mcAuxNode->
find(
"combined_data_name")) {
740 auto *combinedPdfInfoNode = findRooFitInternal(rootnode,
"combined_distributions");
743 if (combinedPdfInfoNode ==
nullptr) {
747 for (
auto &info : combinedPdfInfoNode->children()) {
750 std::string combinedName = info.key();
751 std::string indexCatName = info[
"index_cat"].val();
752 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
753 std::vector<int> indices;
754 std::vector<std::string> pdfNames = valsToStringVec(info[
"distributions"]);
755 for (
auto &
n : info[
"indices"].children()) {
756 indices.push_back(
n.val_int());
759 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
760 std::map<std::string, RooAbsPdf *> pdfMap;
762 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
763 indexCat.defineType(labels[iChannel], indices[iChannel]);
764 pdfMap[labels[iChannel]] = ws.
pdf(pdfNames[iChannel]);
767 RooSimultaneous simPdf{combinedName.c_str(), combinedName.c_str(), pdfMap, indexCat};
772void combineDatasets(
const JSONNode &rootnode, std::vector<std::unique_ptr<RooAbsData>> &datasets)
774 auto *combinedDataInfoNode = findRooFitInternal(rootnode,
"combined_datasets");
777 if (combinedDataInfoNode ==
nullptr) {
781 for (
auto &info : combinedDataInfoNode->children()) {
784 std::string combinedName = info.key();
785 std::string indexCatName = info[
"index_cat"].val();
786 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
787 std::vector<int> indices;
788 for (
auto &
n : info[
"indices"].children()) {
789 indices.push_back(
n.val_int());
791 if (indices.size() != labels.size()) {
796 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
797 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
799 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
800 auto componentName = combinedName +
"_" + labels[iChannel];
803 std::unique_ptr<RooAbsData> &component = *std::find_if(
804 datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
807 allVars.add(*component->get());
808 dsMap.insert({labels[iChannel], std::move(component)});
809 indexCat.defineType(labels[iChannel], indices[iChannel]);
812 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
814 datasets.emplace_back(std::move(combined));
819void sortByName(T &coll)
821 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
838 if (isLiteralConstVar(*arg)) {
846 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
884 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
893 if (
auto node = vars->find(objname)) {
907 if (
auto distributionsNode =
_rootnodeInput->find(
"distributions")) {
922 if (isNumber(objname))
956 if (cv && strcmp(cv->GetName(),
TString::Format(
"%g", cv->getVal()).Data()) == 0) {
968 var[
"value"] << cv->getVal();
969 var[
"const"] <<
true;
971 var[
"value"] << rrv->getVal();
972 if (rrv->isConstant()) {
973 var[
"const"] << rrv->isConstant();
975 if (rrv->getBins() != 100) {
976 var[
"nbins"] << rrv->getBins();
1001 const std::string &formula)
1003 std::string newname = std::string(original->
GetName()) + suffix;
1005 trafo_node[
"type"] <<
"generic_function";
1027 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
1030 exportedObjectNames.insert(
name);
1037 std::vector<std::string> channelNames;
1038 for (
auto const &item : simPdf->indexCat()) {
1039 channelNames.push_back(item.first);
1043 auto &
child = infoNode[simPdf->GetName()].set_map();
1044 child[
"index_cat"] << simPdf->indexCat().GetName();
1046 child[
"distributions"].set_seq();
1047 for (
auto const &item : simPdf->indexCat()) {
1048 child[
"distributions"].append_child() << simPdf->getPdf(item.first.c_str())->GetName();
1060 auto &collectionNode = (*_rootnodeOutput)[
dynamic_cast<RooAbsPdf const *
>(&func) ?
"distributions" :
"functions"];
1069 auto it = exporters.find(cl);
1070 if (it != exporters.end()) {
1071 for (
auto &exp : it->second) {
1073 if (!exp->exportObject(
this, &func, elem)) {
1079 elem[
"name"] <<
name;
1083 if (exp->autoExportDependants()) {
1093 const auto &dict = exportKeys.find(cl);
1094 if (dict == exportKeys.end()) {
1095 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1096 <<
"there are several possible reasons for this:\n"
1097 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1099 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1100 <<
" 3. something is wrong with your setup, e.g. you might have called "
1101 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1102 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1103 <<
"either way, please make sure that:\n"
1104 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1105 "see what is available\n"
1106 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1107 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to "
1108 "see how to do this!\n";
1112 elem[
"type"] << dict->second.type;
1116 for (
size_t i = 0;
i < nprox; ++
i) {
1122 std::string pname(p->
name());
1123 if (pname[0] ==
'!')
1126 auto k = dict->second.proxies.find(pname);
1127 if (k == dict->second.proxies.end()) {
1128 std::cerr <<
"failed to find key matching proxy '" << pname <<
"' for type '" << dict->second.type
1129 <<
"', encountered in '" << func.
GetName() <<
"', skipping" << std::endl;
1134 if (k->second.empty())
1141 if (isLiteralConstVar(*
r->absArg())) {
1144 elem[k->second] <<
r->absArg()->GetName();
1152 std::cerr <<
"unable to locate server of " << func.
GetName() << std::endl;
1182 if (!::isValidName(
name)) {
1183 std::stringstream ss;
1184 ss <<
"RooJSONFactoryWSTool() function name '" <<
name <<
"' is not valid!" << std::endl;
1194 std::stringstream ss;
1195 ss <<
"RooJSONFactoryWSTool() function node " +
name +
" is not a map!";
1199 std::string prefix = genPrefix(p,
true);
1200 if (!prefix.empty())
1203 std::stringstream ss;
1204 ss <<
"RooJSONFactoryWSTool() no type given for function '" <<
name <<
"', skipping." << std::endl;
1209 std::string functype(p[
"type"].val());
1212 if (!importAllDependants) {
1217 auto it = importers.find(functype);
1219 if (it != importers.end()) {
1220 for (
auto &imp : it->second) {
1221 ok = imp->importArg(
this, p);
1227 auto expr = factoryExpressions.find(functype);
1228 if (expr != factoryExpressions.end()) {
1229 std::string expression = ::generate(expr->second, p,
this);
1231 std::stringstream ss;
1232 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1233 <<
"', skipping. expression was\n"
1234 << expression << std::endl;
1238 std::stringstream ss;
1239 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1241 <<
"there are several possible reasons for this:\n"
1242 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1243 <<
" 2. " << functype
1244 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1245 <<
" 3. something is wrong with your setup, e.g. you might have called "
1246 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1247 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1248 <<
"either way, please make sure that:\n"
1249 <<
" 3: you are reading a file with factory expressions - call "
1250 "RooFit::JSONIO::printFactoryExpressions() "
1251 "to see what is available\n"
1252 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1253 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to see "
1262 std::stringstream err;
1263 err <<
"something went wrong importing function '" <<
name <<
"'.";
1297 auto &observablesNode =
output[
"axes"].set_seq();
1301 obsNode[
"name"] << var->GetName();
1302 if (var->getBinning().isUniform()) {
1303 obsNode[
"min"] << var->getMin();
1304 obsNode[
"max"] << var->getMax();
1305 obsNode[
"nbins"] << var->getBins();
1307 auto &edges = obsNode[
"edges"];
1309 double val = var->getBinning().binLow(0);
1311 for (
int i = 0;
i < var->getBinning().numBins(); ++
i) {
1312 val = var->getBinning().binHigh(
i);
1313 edges.append_child() << val;
1335 for (std::size_t
i = 0;
i <
n; ++
i) {
1336 double w = contents[
i];
1358 auto &labels = node[
"labels"].
set_seq();
1359 auto &indices = node[
"indices"].
set_seq();
1361 for (
auto const &item : cat) {
1363 if (std::isalpha(item.first[0])) {
1365 if (label != item.first) {
1366 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << item.first <<
"' to '" << label
1367 <<
"' to become a valid name";
1371 "' to make a valid name!");
1374 labels.append_child() << label;
1375 indices.append_child() << item.second;
1397 " has several category observables!");
1419 auto *combinedPdfInfoNode = findRooFitInternal(*
_rootnodeOutput,
"combined_distributions");
1420 if (combinedPdfInfoNode) {
1421 for (
auto &info : combinedPdfInfoNode->children()) {
1422 if (info[
"index_cat"].val() == cat->
GetName()) {
1432 std::unique_ptr<TList> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1435 std::string catName(absData->GetName());
1436 std::string dataName;
1437 if (std::isalpha(catName[0])) {
1439 if (dataName != catName) {
1440 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << catName <<
"' to '" << dataName
1441 <<
"' to become a valid name";
1445 "' to make a valid name!");
1448 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1449 datamap.
components[catName] = absData->GetName();
1472 " has several category observables!");
1485 output[
"type"] <<
"binned";
1498 if (
auto weightVar = variables.find(
"weightVar")) {
1499 variables.remove(*weightVar);
1508 if (
data.isWeighted() && variables.size() == 1) {
1509 bool isBinnedData =
false;
1510 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1511 std::vector<double> contents;
1513 for (;
i <
data.numEntries(); ++
i) {
1515 if (
x.getBin() !=
i)
1517 contents.push_back(
data.weight());
1519 if (
i ==
x.getBins())
1520 isBinnedData =
true;
1522 output[
"type"] <<
"binned";
1527 output[
"type"] <<
"unbinned";
1532 auto &coords =
output[
"entries"].set_seq();
1533 std::vector<double> weightVals;
1534 bool hasNonUnityWeights =
false;
1535 for (
int i = 0;
i <
data.numEntries(); ++
i) {
1537 coords.append_child().fill_seq(variables, [](
auto x) {
return static_cast<RooRealVar *
>(
x)->getVal(); });
1538 if (
data.isWeighted()) {
1539 weightVals.push_back(
data.weight());
1540 if (
data.weight() != 1.)
1541 hasNonUnityWeights =
true;
1544 if (
data.isWeighted() && hasNonUnityWeights) {
1545 output[
"weights"].fill_seq(weightVals);
1562 for (
JSONNode const &node : topNode[
"axes"].children()) {
1563 if (node.has_child(
"edges")) {
1564 std::vector<double> edges;
1565 for (
auto const &bound : node[
"edges"].children()) {
1566 edges.push_back(bound.val_double());
1568 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(), edges[0],
1569 edges[edges.size() - 1]);
1570 RooBinning bins(obs->getMin(), obs->getMax());
1571 for (
auto b : edges) {
1574 obs->setBinning(bins);
1577 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(),
1578 node[
"min"].val_double(), node[
"max"].val_double());
1579 obs->setBins(node[
"nbins"].val_int());
1598std::unique_ptr<RooDataHist>
1601 if (!
n.has_child(
"contents"))
1604 JSONNode const &contents =
n[
"contents"];
1610 if (
n.has_child(
"errors")) {
1611 errors = &
n[
"errors"];
1616 auto bins = generateBinIndices(vars);
1618 std::stringstream errMsg;
1619 errMsg <<
"inconsistent bin numbers: contents=" << contents.
num_children() <<
", bins=" << bins.size();
1622 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1623 std::vector<double> contentVals;
1625 for (
auto const &cont : contents.
children()) {
1626 contentVals.push_back(cont.val_double());
1628 std::vector<double> errorVals;
1631 for (
auto const &err : errors->
children()) {
1632 errorVals.push_back(err.val_double());
1635 for (
size_t ibin = 0; ibin < bins.size(); ++ibin) {
1636 const double err = errors ? errorVals[ibin] : -1;
1637 dh->set(ibin, contentVals[ibin], err);
1656 if (!::isValidName(
name)) {
1657 std::stringstream ss;
1658 ss <<
"RooJSONFactoryWSTool() variable name '" <<
name <<
"' is not valid!" << std::endl;
1665 std::stringstream ss;
1666 ss <<
"RooJSONFactoryWSTool() node '" <<
name <<
"' is not a map, skipping.";
1667 oocoutE(
nullptr, InputArguments) << ss.str() << std::endl;
1673 if (attrNode->has_child(
"is_const_var") && (*attrNode)[
"is_const_var"].val_int() == 1) {
1694 if (
JSONNode const *varsNode = getVariablesNode(
n)) {
1695 for (
const auto &p : varsNode->children()) {
1699 if (
auto seq =
n.find(
"functions")) {
1700 for (
const auto &p : seq->children()) {
1704 if (
auto seq =
n.find(
"distributions")) {
1705 for (
const auto &p : seq->children()) {
1712 const std::vector<CombinedData> &combDataSets)
1715 if (pdf ==
nullptr) {
1716 warning(
"RooFitHS3 only supports ModelConfigs with RooSimultaneous! Skipping ModelConfig.");
1720 for (std::size_t
i = 0;
i < std::max(combDataSets.size(), std::size_t(1)); ++
i) {
1721 const bool hasdata =
i < combDataSets.size();
1722 if (hasdata && !matches(combDataSets.at(
i), pdf))
1725 std::string analysisName(pdf->GetName());
1727 analysisName +=
"_" + combDataSets[
i].name;
1734 std::string
const &analysisName,
1735 std::map<std::string, std::string>
const *dataComponents)
1741 auto &domains = analysisNode[
"domains"].
set_seq();
1743 analysisNode[
"likelihood"] << analysisName;
1746 nllNode[
"distributions"].set_seq();
1747 nllNode[
"data"].set_seq();
1749 if (dataComponents) {
1750 for (
auto const &item : pdf->indexCat()) {
1751 const auto &dataComp = dataComponents->find(item.first);
1752 nllNode[
"distributions"].append_child() << pdf->getPdf(item.first)->GetName();
1753 nllNode[
"data"].append_child() << dataComp->second;
1758 auto &extConstrNode = nllNode[
"aux_distributions"];
1759 extConstrNode.set_seq();
1761 extConstrNode.append_child() << constr->GetName();
1765 auto writeList = [&](
const char *
name,
RooArgSet const *args) {
1769 std::vector<std::string> names;
1770 names.reserve(args->size());
1772 names.push_back(arg->GetName());
1773 std::sort(names.begin(), names.end());
1779 auto &domainsNode = rootnode[
"domains"];
1782 std::string npDomainName = analysisName +
"_nuisance_parameters";
1783 domains.append_child() << npDomainName;
1792 std::string poiDomainName = analysisName +
"_parameters_of_interest";
1793 domains.append_child() << poiDomainName;
1801 auto &modelConfigAux =
getRooFitInternal(rootnode,
"ModelConfigs", analysisName);
1802 modelConfigAux.set_map();
1803 modelConfigAux[
"pdfName"] << pdf->GetName();
1804 modelConfigAux[
"mcName"] << mc.
GetName();
1818 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1823 std::vector<RooAbsPdf *> allpdfs;
1825 if (!arg->hasClients()) {
1826 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
1827 allpdfs.push_back(pdf);
1831 sortByName(allpdfs);
1832 std::set<std::string> exportedObjectNames;
1837 exportAttributes(arg,
n);
1841 std::vector<RooAbsData *> alldata;
1843 alldata.push_back(
d);
1845 sortByName(alldata);
1847 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
1848 for (
auto &
d : alldata) {
1850 if (!
data.components.empty())
1851 combData.push_back(
data);
1854 for (
auto &
d : alldata) {
1871 if (exportedObjectNames.find(arg->GetName()) != exportedObjectNames.end()) {
1872 bool do_export =
false;
1873 for (
const auto &pdf : allpdfs) {
1874 if (pdf->dependsOn(*arg)) {
1878 if (do_export && !::isValidName(arg->GetName())) {
1879 std::stringstream ss;
1880 ss <<
"RooJSONFactoryWSTool() variable '" << arg->GetName() <<
"' has an invalid name!" << std::endl;
1884 snapshotSorted.
add(*arg);
1887 snapshotSorted.
sort();
1888 std::string
name(snsh->GetName());
1889 if (
name !=
"default_values") {
1907 std::stringstream ss(s);
1919 std::stringstream ss(s);
1930 std::stringstream ss;
1942 std::stringstream ss;
1957 auto &metadata =
n[
"metadata"].set_map();
1964 std::string versionName =
gROOT->GetVersion();
1967 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
1968 rootInfo[
"version"] << versionName;
1996 std::ofstream out(
filename.c_str());
1997 if (!out.is_open()) {
1998 std::stringstream ss;
1999 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
2029 std::ofstream out(
filename.c_str());
2030 if (!out.is_open()) {
2031 std::stringstream ss;
2032 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
2044 if (
auto seq = attrNode->find(
"tags")) {
2045 for (
auto &
a : seq->children()) {
2046 if (
a.val() == attrib)
2056 auto &tags = (*node)[
"tags"];
2066 if (
auto dict = attrNode->find(
"dict")) {
2067 if (
auto *
a = dict->find(attrib)) {
2075 const std::string &
value)
2078 auto &dict = (*node)[
"dict"];
2080 dict[attrib] <<
value;
2096 auto metadata =
n.find(
"metadata");
2097 if (!metadata || !metadata->find(
"hs3_version")) {
2098 std::stringstream ss;
2099 ss <<
"The HS3 version is missing in the JSON!\n"
2100 <<
"Please include the HS3 version in the metadata field, e.g.:\n"
2101 <<
" \"metadata\" :\n"
2108 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2109 if (
auto domains =
n.find(
"domains")) {
2120 if (
auto paramPointsNode =
n.find(
"parameter_points")) {
2121 for (
const auto &snsh : paramPointsNode->children()) {
2123 if (!::isValidName(
name)) {
2124 std::stringstream ss;
2125 ss <<
"RooJSONFactoryWSTool() node name '" <<
name <<
"' is not valid!" << std::endl;
2130 for (
const auto &var : snsh[
"parameters"].children()) {
2132 configureVariable(*
_domains, var, *rrv);
2146 importAttributes(arg, elem);
2156 std::vector<std::unique_ptr<RooAbsData>> datasets;
2157 if (
auto dataNode =
n.find(
"data")) {
2158 for (
const auto &p : dataNode->children()) {
2165 if (
auto analysesNode =
n.find(
"analyses")) {
2173 for (
auto const &
d : datasets) {
2193 if (this->
workspace()->getSnapshot(
"default_values")) {
2208 std::ifstream infile(
filename.c_str());
2209 if (!infile.is_open()) {
2210 std::stringstream ss;
2211 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2241 std::ifstream infile(
filename.c_str());
2242 if (!infile.is_open()) {
2243 std::stringstream ss;
2244 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2257 bool isVariable =
true;
2258 if (
n.find(
"type")) {
2271 std::unique_ptr<RooFit::Detail::JSONTree> tree =
varJSONString(elementNode);
2273 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2274 if (
auto domains =
n.find(
"domains"))
2280 JSONNode const *varsNode = getVariablesNode(
n);
2281 const auto &p = varsNode->
child(0);
2284 auto paramPointsNode =
n.find(
"parameter_points");
2285 const auto &snsh = paramPointsNode->child(0);
2288 const auto &var = snsh[
"parameters"].child(0);
2290 configureVariable(*
_domains, var, *rrv);
2298 importAttributes(arg, elem);
2327 throw std::runtime_error(s);
std::unique_ptr< RooFit::Detail::JSONTree > varJSONString(const JSONNode &treeRoot)
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void w
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t 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 np
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
static std::unique_ptr< JSONTree > create()
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.
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for binned and unbinned datasets.
Abstract interface for all probability density functions.
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.
virtual const char * name() const
Abstract base class for objects that represent a real value and implements functionality common to al...
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Abstract interface for RooAbsArg proxy classes.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Implements a RooAbsBinning in terms of an array of boundary values, posing no constraints on the choi...
bool addBoundary(double boundary)
Add bin boundary at given value.
Object to represent discrete states.
Represents a constant real-valued object.
Container class to hold N-dimensional binned data.
virtual std::string val() const =0
void fill_seq(Collection const &coll)
virtual JSONNode & set_map()=0
virtual JSONNode & append_child()=0
virtual children_view children()
virtual size_t num_children() const =0
virtual JSONNode & child(size_t pos)=0
virtual JSONNode & set_seq()=0
virtual bool is_seq() const =0
virtual bool is_map() const =0
virtual bool has_child(std::string const &) const =0
virtual std::string key() const =0
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 readVariable(const RooRealVar &)
void writeJSON(RooFit::Detail::JSONNode &) const
void writeVariable(RooRealVar &) const
std::ostream & log(const RooAbsArg *self, RooFit::MsgLevel level, RooFit::MsgTopic facility, bool forceSkipPrefix=false)
Log error message associated with RooAbsArg object self at given level and topic.
static RooMsgService & instance()
Return reference to singleton instance.
Variable that can be changed from the outside.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
const RooAbsCategoryLValue & indexCat() const
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)
const RooArgSet * GetNuisanceParameters() const
get RooArgSet containing the nuisance parameters (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.
RooAbsArg * arg(RooStringView name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
bool loadSnapshot(const char *name)
Load the values and attributes of the parameters in the snapshot saved with the given name.
bool import(const RooAbsArg &arg, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={})
Import a RooAbsArg object, e.g.
TClass instances represent classes, structs and namespaces in the ROOT type system.
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()