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 ==
'_')) {
239 if (!
p.has_child(
"name")) {
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");
367 }
else if (!
p.has_child(k)) {
368 std::stringstream errMsg;
369 errMsg <<
"node '" <<
name <<
"' is missing key '" << k <<
"'";
371 }
else if (
p[k].is_seq()) {
372 bool firstInner =
true;
374 expression << (firstInner ?
"{" :
",") << arg->
GetName();
380 expression <<
p[k].val();
384 return expression.str();
397std::vector<std::vector<int>> generateBinIndices(
const RooArgSet &vars)
399 std::vector<std::vector<int>> combinations;
400 std::vector<int> vars_numbins;
401 vars_numbins.reserve(vars.
size());
402 for (
const auto *absv : static_range_cast<RooRealVar *>(vars)) {
403 vars_numbins.push_back(absv->getBins());
405 std::vector<int> curr_comb(vars.
size());
406 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
410template <
typename... Keys_t>
411JSONNode const *findRooFitInternal(
JSONNode const &node, Keys_t
const &...keys)
413 return node.
find(
"misc",
"ROOT_internal", keys...);
425bool isLiteralConstVar(
RooAbsArg const &arg)
427 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(&arg);
428 return isRooConstVar && isNumber(arg.
GetName());
443 if (isLiteralConstVar(*arg)) {
449 auto initializeNode = [&]() {
467 if (it.first ==
"factory_tag" || it.first ==
"PROD_TERM_TYPE")
470 (*node)[
"dict"].set_map()[it.first] << it.second;
476 if (
attr ==
"SnapShot_ExtRefClone" ||
attr ==
"RooRealConstant_Factory_Object")
479 (*node)[
"tags"].set_seq().append_child() <<
attr;
499 std::map<std::string, Var> vars;
500 for (
const auto &
p : node[
"axes"].
children()) {
504 for (
auto v : vars) {
505 std::string
name(
v.first);
509 std::stringstream errMsg;
510 errMsg <<
"The observable \"" <<
name <<
"\" could not be found in the workspace!";
531 if (!::isValidName(
name)) {
532 std::stringstream ss;
533 ss <<
"RooJSONFactoryWSTool() data name '" <<
name <<
"' is not valid!" << std::endl;
537 std::string
const &
type =
p[
"type"].val();
538 if (
type ==
"binned") {
541 }
else if (
type ==
"unbinned") {
544 getObservables(workspace,
p, vars);
547 auto &coords =
p[
"entries"];
548 if (!coords.is_seq()) {
551 std::vector<double> weightVals;
552 if (
p.has_child(
"weights")) {
553 auto &weights =
p[
"weights"];
554 if (coords.num_children() != weights.num_children()) {
557 for (
auto const &weight : weights.children()) {
558 weightVals.push_back(weight.val_double());
562 for (
auto const &point : coords.children()) {
563 if (!point.is_seq()) {
564 std::stringstream errMsg;
565 errMsg <<
"coordinate point '" << i <<
"' is not a list!";
568 if (point.num_children() != varlist.
size()) {
572 for (
auto const &pointj : point.children()) {
574 v->
setVal(pointj.val_double());
577 if (weightVals.size() > 0) {
578 data->add(vars, weightVals[i]);
587 std::stringstream ss;
588 ss <<
"RooJSONFactoryWSTool() failed to create dataset " <<
name << std::endl;
610 const std::vector<std::unique_ptr<RooAbsData>> &datasets)
614 JSONNode const *mcAuxNode = findRooFitInternal(rootnode,
"ModelConfigs", analysisName);
616 JSONNode const *mcNameNode = mcAuxNode ? mcAuxNode->
find(
"mcName") :
nullptr;
617 std::string mcname = mcNameNode ? mcNameNode->
val() : analysisName;
618 if (workspace.
obj(mcname))
623 mc->
SetWS(workspace);
625 std::vector<std::string> nllDataNames;
629 throw std::runtime_error(
"likelihood node not found!");
631 if (!nllNode->has_child(
"distributions")) {
632 throw std::runtime_error(
"likelihood node has no distributions attached!");
634 if (!nllNode->has_child(
"data")) {
635 throw std::runtime_error(
"likelihood node has no data attached!");
637 std::vector<std::string> nllDistNames = valsToStringVec((*nllNode)[
"distributions"]);
639 for (
auto &nameNode : (*nllNode)[
"aux_distributions"].children()) {
640 if (
RooAbsArg *extConstraint = workspace.
arg(nameNode.val())) {
641 extConstraints.
add(*extConstraint);
645 for (
auto &nameNode : (*nllNode)[
"data"].children()) {
646 nllDataNames.push_back(nameNode.val());
647 for (
const auto &
d : datasets) {
648 if (
d->GetName() == nameNode.val()) {
649 observables.
add(*
d->get());
654 JSONNode const *pdfNameNode = mcAuxNode ? mcAuxNode->
find(
"pdfName") :
nullptr;
655 std::string
const pdfName = pdfNameNode ? pdfNameNode->
val() :
"simPdf";
661 if (nllDistNames.size() == 1) {
663 pdf = workspace.
pdf(nllDistNames[0]);
666 std::string simPdfName = analysisName +
"_simPdf";
667 std::string indexCatName = analysisName +
"_categoryIndex";
668 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
669 std::map<std::string, RooAbsPdf *> pdfMap;
670 for (std::size_t i = 0; i < nllDistNames.size(); ++i) {
672 pdfMap[nllDistNames[i]] = workspace.
pdf(nllDistNames[i]);
674 RooSimultaneous simPdf{simPdfName.c_str(), simPdfName.c_str(), pdfMap, indexCat};
682 if (!extConstraints.
empty())
683 mc->SetExternalConstraints(extConstraints);
685 auto readArgSet = [&](std::string
const &
name) {
688 out.add(*workspace.
arg(
child.val()));
693 mc->SetParametersOfInterest(readArgSet(
"parameters_of_interest"));
694 mc->SetObservables(observables);
705 for (
auto &domain : analysisNode[
"domains"].
children()) {
707 if (!thisDomain || !thisDomain->has_child(
"axes"))
709 for (
auto &var : (*thisDomain)[
"axes"].children()) {
712 domainPars.
add(*wsvar);
718 for (
const auto &
p : pars) {
719 if (mc->GetParametersOfInterest()->find(*
p))
721 if (
p->isConstant() && !mainPars.find(*
p)) {
723 }
else if (domainPars.
find(*
p)) {
727 mc->SetGlobalObservables(globs);
728 mc->SetNuisanceParameters(nps);
731 if (
auto found = mcAuxNode->
find(
"combined_data_name")) {
739 auto *combinedPdfInfoNode = findRooFitInternal(rootnode,
"combined_distributions");
742 if (combinedPdfInfoNode ==
nullptr) {
746 for (
auto &info : combinedPdfInfoNode->children()) {
749 std::string combinedName = info.key();
750 std::string indexCatName = info[
"index_cat"].val();
751 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
752 std::vector<int> indices;
753 std::vector<std::string> pdfNames = valsToStringVec(info[
"distributions"]);
754 for (
auto &
n : info[
"indices"].children()) {
755 indices.push_back(
n.val_int());
758 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
759 std::map<std::string, RooAbsPdf *> pdfMap;
761 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
762 indexCat.
defineType(labels[iChannel], indices[iChannel]);
763 pdfMap[labels[iChannel]] = ws.
pdf(pdfNames[iChannel]);
766 RooSimultaneous simPdf{combinedName.c_str(), combinedName.c_str(), pdfMap, indexCat};
771void combineDatasets(
const JSONNode &rootnode, std::vector<std::unique_ptr<RooAbsData>> &datasets)
773 auto *combinedDataInfoNode = findRooFitInternal(rootnode,
"combined_datasets");
776 if (combinedDataInfoNode ==
nullptr) {
780 for (
auto &info : combinedDataInfoNode->children()) {
783 std::string combinedName = info.key();
784 std::string indexCatName = info[
"index_cat"].val();
785 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
786 std::vector<int> indices;
787 for (
auto &
n : info[
"indices"].children()) {
788 indices.push_back(
n.val_int());
790 if (indices.size() != labels.size()) {
795 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
796 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
798 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
799 auto componentName = combinedName +
"_" + labels[iChannel];
802 std::unique_ptr<RooAbsData> &component = *std::find_if(
803 datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
806 allVars.add(*component->get());
807 dsMap.insert({labels[iChannel], std::move(component)});
808 indexCat.defineType(labels[iChannel], indices[iChannel]);
811 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
813 datasets.emplace_back(std::move(combined));
818void sortByName(T &coll)
820 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
837 if (isLiteralConstVar(*arg)) {
845 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
883 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
887RooRealVar *RooJSONFactoryWSTool::requestImpl<RooRealVar>(
const std::string &objname)
892 if (
auto node = vars->find(objname)) {
902RooAbsPdf *RooJSONFactoryWSTool::requestImpl<RooAbsPdf>(
const std::string &objname)
917RooAbsReal *RooJSONFactoryWSTool::requestImpl<RooAbsReal>(
const std::string &objname)
921 if (isNumber(objname))
923 if (
RooAbsPdf *pdf = requestImpl<RooAbsPdf>(objname))
925 if (
RooRealVar *var = requestImpl<RooRealVar>(objname))
967 var[
"value"] << cv->getVal();
968 var[
"const"] <<
true;
970 var[
"value"] << rrv->getVal();
971 if (rrv->isConstant()) {
972 var[
"const"] << rrv->isConstant();
974 if (rrv->getBins() != 100) {
975 var[
"nbins"] << rrv->getBins();
1000 const std::string &formula)
1002 std::string newname = std::string(original->
GetName()) + suffix;
1004 trafo_node[
"type"] <<
"generic_function";
1026 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
1029 exportedObjectNames.insert(
name);
1036 std::vector<std::string> channelNames;
1037 for (
auto const &item : simPdf->indexCat()) {
1038 channelNames.push_back(item.first);
1042 auto &
child = infoNode[simPdf->GetName()].set_map();
1043 child[
"index_cat"] << simPdf->indexCat().GetName();
1045 child[
"distributions"].set_seq();
1046 for (
auto const &item : simPdf->indexCat()) {
1047 child[
"distributions"].append_child() << simPdf->getPdf(item.first.c_str())->GetName();
1059 auto &collectionNode = (*_rootnodeOutput)[
dynamic_cast<RooAbsPdf const *
>(&func) ?
"distributions" :
"functions"];
1068 auto it = exporters.find(cl);
1069 if (it != exporters.end()) {
1070 for (
auto &exp : it->second) {
1072 if (!exp->exportObject(
this, &func, elem)) {
1078 elem[
"name"] <<
name;
1082 if (exp->autoExportDependants()) {
1092 const auto &dict = exportKeys.find(cl);
1093 if (dict == exportKeys.end()) {
1094 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1095 <<
"there are several possible reasons for this:\n"
1096 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1098 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1099 <<
" 3. something is wrong with your setup, e.g. you might have called "
1100 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1101 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1102 <<
"either way, please make sure that:\n"
1103 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1104 "see what is available\n"
1105 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1106 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to "
1107 "see how to do this!\n";
1111 elem[
"type"] << dict->second.type;
1115 for (
size_t i = 0; i < nprox; ++i) {
1121 std::string pname(
p->name());
1122 if (pname[0] ==
'!')
1125 auto k = dict->second.proxies.find(pname);
1126 if (k == dict->second.proxies.end()) {
1127 std::cerr <<
"failed to find key matching proxy '" << pname <<
"' for type '" << dict->second.type
1128 <<
"', encountered in '" << func.
GetName() <<
"', skipping" << std::endl;
1133 if (k->second.empty())
1140 if (isLiteralConstVar(*
r->absArg())) {
1141 elem[k->second] <<
static_cast<RooConstVar *
>(
r->absArg())->getVal();
1143 elem[k->second] <<
r->absArg()->GetName();
1151 std::cerr <<
"unable to locate server of " << func.
GetName() << std::endl;
1181 if (!::isValidName(
name)) {
1182 std::stringstream ss;
1183 ss <<
"RooJSONFactoryWSTool() function name '" <<
name <<
"' is not valid!" << std::endl;
1193 std::stringstream ss;
1194 ss <<
"RooJSONFactoryWSTool() function node " +
name +
" is not a map!";
1198 std::string prefix = genPrefix(
p,
true);
1199 if (!prefix.empty())
1201 if (!
p.has_child(
"type")) {
1202 std::stringstream ss;
1203 ss <<
"RooJSONFactoryWSTool() no type given for function '" <<
name <<
"', skipping." << std::endl;
1208 std::string functype(
p[
"type"].val());
1211 if (!importAllDependants) {
1216 auto it = importers.find(functype);
1218 if (it != importers.end()) {
1219 for (
auto &imp : it->second) {
1220 ok = imp->importArg(
this,
p);
1226 auto expr = factoryExpressions.find(functype);
1227 if (expr != factoryExpressions.end()) {
1228 std::string expression = ::generate(expr->second,
p,
this);
1230 std::stringstream ss;
1231 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1232 <<
"', skipping. expression was\n"
1233 << expression << std::endl;
1237 std::stringstream ss;
1238 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1240 <<
"there are several possible reasons for this:\n"
1241 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1242 <<
" 2. " << functype
1243 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1244 <<
" 3. something is wrong with your setup, e.g. you might have called "
1245 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1246 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1247 <<
"either way, please make sure that:\n"
1248 <<
" 3: you are reading a file with factory expressions - call "
1249 "RooFit::JSONIO::printFactoryExpressions() "
1250 "to see what is available\n"
1251 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1252 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to see "
1261 std::stringstream err;
1262 err <<
"something went wrong importing function '" <<
name <<
"'.";
1279 this->
importFunction((JSONTree::create(jsonString))->rootnode(), importAllDependants);
1296 auto &observablesNode =
output[
"axes"].set_seq();
1298 for (
auto *var : static_range_cast<RooRealVar *>(vars)) {
1300 obsNode[
"name"] << var->GetName();
1301 if (var->getBinning().isUniform()) {
1302 obsNode[
"min"] << var->getMin();
1303 obsNode[
"max"] << var->getMax();
1304 obsNode[
"nbins"] << var->getBins();
1306 auto &edges = obsNode[
"edges"];
1308 double val = var->getBinning().binLow(0);
1310 for (
int i = 0; i < var->getBinning().numBins(); ++i) {
1311 val = var->getBinning().binHigh(i);
1312 edges.append_child() << val;
1334 for (std::size_t i = 0; i <
n; ++i) {
1335 double w = contents[i];
1357 auto &labels = node[
"labels"].
set_seq();
1358 auto &indices = node[
"indices"].
set_seq();
1360 for (
auto const &item : cat) {
1362 if (std::isalpha(item.first[0])) {
1364 if (label != item.first) {
1365 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << item.first <<
"' to '" << label
1366 <<
"' to become a valid name";
1370 "' to make a valid name!");
1373 labels.append_child() << label;
1374 indices.append_child() << item.second;
1396 " has several category observables!");
1418 auto *combinedPdfInfoNode = findRooFitInternal(*
_rootnodeOutput,
"combined_distributions");
1419 if (combinedPdfInfoNode) {
1420 for (
auto &info : combinedPdfInfoNode->children()) {
1421 if (info[
"index_cat"].val() == cat->
GetName()) {
1431 std::unique_ptr<TList> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1433 for (
RooAbsData *absData : static_range_cast<RooAbsData *>(*dataList)) {
1434 std::string catName(absData->GetName());
1435 std::string dataName;
1436 if (std::isalpha(catName[0])) {
1438 if (dataName != catName) {
1439 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << catName <<
"' to '" << dataName
1440 <<
"' to become a valid name";
1444 "' to make a valid name!");
1447 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1448 datamap.
components[catName] = absData->GetName();
1471 " has several category observables!");
1484 output[
"type"] <<
"binned";
1497 if (
auto weightVar = variables.find(
"weightVar")) {
1498 variables.remove(*weightVar);
1507 if (
data.isWeighted() && variables.size() == 1) {
1508 bool isBinnedData =
false;
1509 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1510 std::vector<double> contents;
1512 for (; i <
data.numEntries(); ++i) {
1514 if (
x.getBin() != i)
1516 contents.push_back(
data.weight());
1518 if (i ==
x.getBins())
1519 isBinnedData =
true;
1521 output[
"type"] <<
"binned";
1526 output[
"type"] <<
"unbinned";
1531 auto &coords =
output[
"entries"].set_seq();
1532 std::vector<double> weightVals;
1533 bool hasNonUnityWeights =
false;
1534 for (
int i = 0; i <
data.numEntries(); ++i) {
1536 coords.append_child().fill_seq(variables, [](
auto x) {
return static_cast<RooRealVar *
>(
x)->getVal(); });
1537 if (
data.isWeighted()) {
1538 weightVals.push_back(
data.weight());
1539 if (
data.weight() != 1.)
1540 hasNonUnityWeights =
true;
1543 if (
data.isWeighted() && hasNonUnityWeights) {
1544 output[
"weights"].fill_seq(weightVals);
1562 if (node.has_child(
"edges")) {
1563 std::vector<double> edges;
1564 for (
auto const &bound : node[
"edges"].children()) {
1565 edges.push_back(bound.val_double());
1567 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(), edges[0],
1568 edges[edges.size() - 1]);
1569 RooBinning bins(obs->getMin(), obs->getMax());
1570 for (
auto b : edges) {
1573 obs->setBinning(bins);
1576 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(),
1577 node[
"min"].val_double(), node[
"max"].val_double());
1578 obs->setBins(node[
"nbins"].val_int());
1597std::unique_ptr<RooDataHist>
1600 if (!
n.has_child(
"contents"))
1603 JSONNode const &contents =
n[
"contents"];
1609 if (
n.has_child(
"errors")) {
1610 errors = &
n[
"errors"];
1615 auto bins = generateBinIndices(vars);
1617 std::stringstream errMsg;
1618 errMsg <<
"inconsistent bin numbers: contents=" << contents.
num_children() <<
", bins=" << bins.size();
1621 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1622 std::vector<double> contentVals;
1624 for (
auto const &cont : contents.
children()) {
1625 contentVals.push_back(cont.val_double());
1627 std::vector<double> errorVals;
1630 for (
auto const &err : errors->
children()) {
1631 errorVals.push_back(err.val_double());
1634 for (
size_t ibin = 0; ibin < bins.size(); ++ibin) {
1635 const double err = errors ? errorVals[ibin] : -1;
1636 dh->set(ibin, contentVals[ibin], err);
1655 if (!::isValidName(
name)) {
1656 std::stringstream ss;
1657 ss <<
"RooJSONFactoryWSTool() variable name '" <<
name <<
"' is not valid!" << std::endl;
1664 std::stringstream ss;
1665 ss <<
"RooJSONFactoryWSTool() node '" <<
name <<
"' is not a map, skipping.";
1666 oocoutE(
nullptr, InputArguments) << ss.str() << std::endl;
1672 if (attrNode->has_child(
"is_const_var") && (*attrNode)[
"is_const_var"].val_int() == 1) {
1673 wsEmplace<RooConstVar>(
name,
p[
"value"].val_double());
1678 configureVariable(*
_domains,
p, wsEmplace<RooRealVar>(
name, 1.));
1693 if (
JSONNode const *varsNode = getVariablesNode(
n)) {
1694 for (
const auto &
p : varsNode->children()) {
1698 if (
auto seq =
n.find(
"functions")) {
1699 for (
const auto &
p : seq->children()) {
1703 if (
auto seq =
n.find(
"distributions")) {
1704 for (
const auto &
p : seq->children()) {
1711 const std::vector<CombinedData> &combDataSets)
1714 if (pdf ==
nullptr) {
1715 warning(
"RooFitHS3 only supports ModelConfigs with RooSimultaneous! Skipping ModelConfig.");
1719 for (std::size_t i = 0; i < std::max(combDataSets.size(), std::size_t(1)); ++i) {
1720 const bool hasdata = i < combDataSets.size();
1721 if (hasdata && !matches(combDataSets.at(i), pdf))
1724 std::string analysisName(pdf->GetName());
1726 analysisName +=
"_" + combDataSets[i].name;
1733 std::string
const &analysisName,
1734 std::map<std::string, std::string>
const *dataComponents)
1740 auto &domains = analysisNode[
"domains"].
set_seq();
1742 analysisNode[
"likelihood"] << analysisName;
1745 nllNode[
"distributions"].set_seq();
1746 nllNode[
"data"].set_seq();
1748 if (dataComponents) {
1749 for (
auto const &item : pdf->indexCat()) {
1750 const auto &dataComp = dataComponents->find(item.first);
1751 nllNode[
"distributions"].append_child() << pdf->getPdf(item.first)->GetName();
1752 nllNode[
"data"].append_child() << dataComp->second;
1757 auto &extConstrNode = nllNode[
"aux_distributions"];
1758 extConstrNode.set_seq();
1760 extConstrNode.append_child() << constr->GetName();
1764 auto writeList = [&](
const char *
name,
RooArgSet const *args) {
1768 std::vector<std::string> names;
1769 names.reserve(args->size());
1771 names.push_back(arg->GetName());
1772 std::sort(names.begin(), names.end());
1778 auto &domainsNode = rootnode[
"domains"];
1781 std::string npDomainName = analysisName +
"_nuisance_parameters";
1791 std::string poiDomainName = analysisName +
"_parameters_of_interest";
1792 domains.append_child() << poiDomainName;
1800 auto &modelConfigAux =
getRooFitInternal(rootnode,
"ModelConfigs", analysisName);
1801 modelConfigAux.set_map();
1802 modelConfigAux[
"pdfName"] << pdf->GetName();
1803 modelConfigAux[
"mcName"] << mc.
GetName();
1817 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1822 std::vector<RooAbsPdf *> allpdfs;
1824 if (!arg->hasClients()) {
1825 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
1826 allpdfs.push_back(pdf);
1830 sortByName(allpdfs);
1831 std::set<std::string> exportedObjectNames;
1836 exportAttributes(arg,
n);
1840 std::vector<RooAbsData *> alldata;
1842 alldata.push_back(
d);
1844 sortByName(alldata);
1846 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
1847 for (
auto &
d : alldata) {
1849 if (!
data.components.empty())
1850 combData.push_back(
data);
1853 for (
auto &
d : alldata) {
1870 if (exportedObjectNames.find(arg->GetName()) != exportedObjectNames.end()) {
1871 bool do_export =
false;
1872 for (
const auto &pdf : allpdfs) {
1873 if (pdf->dependsOn(*arg)) {
1877 if (do_export && !::isValidName(arg->GetName())) {
1878 std::stringstream ss;
1879 ss <<
"RooJSONFactoryWSTool() variable '" << arg->GetName() <<
"' has an invalid name!" << std::endl;
1883 snapshotSorted.
add(*arg);
1886 snapshotSorted.
sort();
1887 std::string
name(snsh->GetName());
1888 if (
name !=
"default_values") {
1906 std::stringstream ss(s);
1918 std::stringstream ss(s);
1929 std::stringstream ss;
1941 std::stringstream ss;
1953 std::unique_ptr<JSONTree> tree = JSONTree::create();
1956 auto &metadata =
n[
"metadata"].set_map();
1963 std::string versionName =
gROOT->GetVersion();
1966 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
1967 rootInfo[
"version"] << versionName;
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;
2028 std::ofstream out(
filename.c_str());
2029 if (!out.is_open()) {
2030 std::stringstream ss;
2031 ss <<
"RooJSONFactoryWSTool() invalid output file '" <<
filename <<
"'." << std::endl;
2043 if (
auto seq = attrNode->find(
"tags")) {
2044 for (
auto &
a : seq->children()) {
2045 if (
a.val() == attrib)
2055 auto &tags = (*node)[
"tags"];
2065 if (
auto dict = attrNode->find(
"dict")) {
2066 if (
auto *
a = dict->find(attrib)) {
2074 const std::string &
value)
2077 auto &dict = (*node)[
"dict"];
2079 dict[attrib] <<
value;
2095 auto metadata =
n.find(
"metadata");
2096 if (!metadata || !metadata->find(
"hs3_version")) {
2097 std::stringstream ss;
2098 ss <<
"The HS3 version is missing in the JSON!\n"
2099 <<
"Please include the HS3 version in the metadata field, e.g.:\n"
2100 <<
" \"metadata\" :\n"
2107 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2108 if (
auto domains =
n.find(
"domains")) {
2119 if (
auto paramPointsNode =
n.find(
"parameter_points")) {
2120 for (
const auto &snsh : paramPointsNode->children()) {
2122 if (!::isValidName(
name)) {
2123 std::stringstream ss;
2124 ss <<
"RooJSONFactoryWSTool() node name '" <<
name <<
"' is not valid!" << std::endl;
2129 for (
const auto &var : snsh[
"parameters"].children()) {
2131 configureVariable(*
_domains, var, *rrv);
2145 importAttributes(arg, elem);
2155 std::vector<std::unique_ptr<RooAbsData>> datasets;
2156 if (
auto dataNode =
n.find(
"data")) {
2157 for (
const auto &
p : dataNode->children()) {
2164 if (
auto analysesNode =
n.find(
"analyses")) {
2165 for (
JSONNode const &analysisNode : analysesNode->children()) {
2172 for (
auto const &
d : datasets) {
2190 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2192 if (this->
workspace()->getSnapshot(
"default_values")) {
2207 std::ifstream infile(
filename.c_str());
2208 if (!infile.is_open()) {
2209 std::stringstream ss;
2210 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2226 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2240 std::ifstream infile(
filename.c_str());
2241 if (!infile.is_open()) {
2242 std::stringstream ss;
2243 ss <<
"RooJSONFactoryWSTool() invalid input file '" <<
filename <<
"'." << std::endl;
2256 bool isVariable =
true;
2257 if (
n.find(
"type")) {
2270 std::unique_ptr<RooFit::Detail::JSONTree> tree =
varJSONString(elementNode);
2272 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2273 if (
auto domains =
n.find(
"domains"))
2279 JSONNode const *varsNode = getVariablesNode(
n);
2280 const auto &
p = varsNode->
child(0);
2283 auto paramPointsNode =
n.find(
"parameter_points");
2284 const auto &snsh = paramPointsNode->child(0);
2287 const auto &var = snsh[
"parameters"].child(0);
2289 configureVariable(*
_domains, var, *rrv);
2297 importAttributes(arg, elem);
2326 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 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
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.
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 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.
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)
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.
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.
bool loadSnapshot(const char *name)
Load the values and attributes of the parameters in the snapshot saved with the given name.
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()