115std::vector<std::string> valsToStringVec(
JSONNode const &node)
117 std::vector<std::string> out;
120 out.push_back(elem.val());
132bool isNumber(
const std::string &str)
137 std::istringstream stream(str);
139 return (stream >>
value) && stream.eof();
145 if (!
p.has_child(
"name")) {
148 if (
auto n =
p.find(
"value"))
149 v.setVal(
n->val_double());
151 if (
auto n =
p.find(
"nbins"))
152 v.setBins(
n->val_int());
153 if (
auto n =
p.find(
"relErr"))
154 v.setError(
v.getVal() *
n->val_double());
155 if (
auto n =
p.find(
"err"))
156 v.setError(
n->val_double());
157 if (
auto n =
p.find(
"const")) {
158 v.setConstant(
n->val_bool());
160 v.setConstant(
false);
166 auto paramPointsNode = rootNode.
find(
"parameter_points");
167 if (!paramPointsNode)
172 return &((*out)[
"parameters"]);
175std::string genPrefix(
const JSONNode &
p,
bool trailing_underscore)
180 if (
auto node =
p.find(
"namespaces")) {
181 for (
const auto &ns : node->
children()) {
187 if (trailing_underscore && !prefix.empty())
193void genIndicesHelper(std::vector<std::vector<int>> &combinations, std::vector<int> &curr_comb,
194 const std::vector<int> &vars_numbins,
size_t curridx)
196 if (curridx == vars_numbins.size()) {
198 combinations.emplace_back(curr_comb);
200 for (
int i = 0; i < vars_numbins[curridx]; ++i) {
201 curr_comb[curridx] = i;
202 ::genIndicesHelper(combinations, curr_comb, vars_numbins, curridx + 1);
210 if (
auto seq = node.
find(
"dict")) {
211 for (
const auto &
attr : seq->children()) {
215 if (
auto seq = node.
find(
"tags")) {
216 for (
const auto &
attr : seq->children()) {
225 out.
add(*args,
true);
229void collectParameterStepWidthCandidatesFromModelConfigs(
RooWorkspace const &workspace,
RooArgSet &candidates,
238 addIfPresent(candidates, mc->GetParametersOfInterest());
239 addIfPresent(candidates, mc->GetNuisanceParameters());
241 addIfPresent(excluded, mc->GetObservables());
242 addIfPresent(excluded, mc->GetGlobalObservables());
243 addIfPresent(excluded, mc->GetConditionalObservables());
247void collectParameterStepWidthCandidatesFromPdfs(std::vector<RooAbsPdf *>
const &pdfs,
248 std::vector<RooAbsData *>
const &
data,
RooArgSet &candidates,
254 std::unique_ptr<RooArgSet> pdfObs{pdf->
getObservables(*dataset->get())};
255 observables.
add(*pdfObs,
true);
258 if (observables.
empty()) {
264 candidates.
add(params,
true);
265 excluded.
add(observables,
true);
269void exportParameterStepWidths(
RooWorkspace const &workspace, std::vector<RooAbsPdf *>
const &pdfs,
270 std::vector<RooAbsData *>
const &
data,
JSONNode &rootnode)
275 collectParameterStepWidthCandidatesFromModelConfigs(workspace, candidates, excluded);
276 collectParameterStepWidthCandidatesFromPdfs(pdfs,
data, candidates, excluded);
280 JSONNode *parameterStepWidthsNode =
nullptr;
282 if (excluded.
find(*arg)) {
287 if (!var || !var->hasError()) {
291 if (!parameterStepWidthsNode) {
292 parameterStepWidthsNode = &rootnode[
"misc"][
"minimization"][
"parameter_stepwidths"].
set_seq();
296 stepWidthNode[
"step_width"] << var->getError();
302 auto const *parameterStepWidthsNode = rootnode.
find(
"misc",
"minimization",
"parameter_stepwidths");
303 if (!parameterStepWidthsNode) {
306 if (!parameterStepWidthsNode->is_seq()) {
311 for (
JSONNode const &stepWidthNode : parameterStepWidthsNode->children()) {
312 if (!stepWidthNode.is_map() || !stepWidthNode.has_child(
"name") || !stepWidthNode.has_child(
"step_width")) {
322 "RooFitHS3: skipping parameter_stepwidths entry for unknown or non-real variable '" +
name +
"'.");
326 var->setError(stepWidthNode.find(
"step_width")->val_double());
333 std::stringstream expression;
334 std::string classname(
ex.tclass->GetName());
335 size_t colon = classname.find_last_of(
':');
336 expression << (colon < classname.size() ? classname.substr(colon + 1) : classname);
339 for (
auto k :
ex.arguments) {
340 expression << (first ?
"::" +
name +
"(" :
",");
342 if (k ==
"true" || k ==
"false") {
343 expression << (k ==
"true" ?
"1" :
"0");
344 }
else if (!
p.has_child(k)) {
346 }
else if (
p[k].is_seq()) {
347 bool firstInner =
true;
350 expression << (firstInner ?
"" :
",") << arg->
GetName();
356 expression <<
p[k].val();
360 return expression.str();
364std::vector<std::vector<int>> generateBinIndices(
const RooArgSet &vars)
366 std::vector<std::vector<int>> combinations;
367 std::vector<int> vars_numbins;
368 vars_numbins.reserve(vars.
size());
369 for (
const auto *absv : static_range_cast<RooRealVar *>(vars)) {
370 vars_numbins.push_back(absv->getBins());
372 std::vector<int> curr_comb(vars.
size());
373 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
377template <
typename... Keys_t>
378JSONNode const *findRooFitInternal(
JSONNode const &node, Keys_t
const &...keys)
380 return node.
find(
"misc",
"ROOT_internal", keys...);
384bool isLiteralConstVar(
RooAbsArg const &arg)
386 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(&arg);
387 return isRooConstVar && isNumber(arg.
GetName());
394 if (isLiteralConstVar(*arg)) {
400 auto initializeNode = [&]() {
415 if (it.first ==
"factory_tag" || it.first ==
"PROD_TERM_TYPE")
418 (*node)[
"dict"].set_map()[it.first] << it.second;
424 if (
attr ==
"SnapShot_ExtRefClone" ||
attr ==
"RooRealConstant_Factory_Object")
427 (*node)[
"tags"].set_seq().append_child() <<
attr;
435 for (
const auto &
p : node[
"axes"].
children()) {
452 std::string
const &
type =
p[
"type"].val();
453 if (
type ==
"binned") {
456 }
else if (
type ==
"unbinned") {
459 getObservables(workspace,
p, varlist);
462 auto &coords =
p[
"entries"];
463 if (!coords.is_seq()) {
466 std::vector<double> weightVals;
467 if (
p.has_child(
"weights")) {
468 auto &weights =
p[
"weights"];
469 if (coords.num_children() != weights.num_children()) {
472 for (
auto const &weight : weights.children()) {
473 weightVals.push_back(weight.val_double());
477 for (
auto const &point : coords.children()) {
478 if (!point.is_seq()) {
481 if (point.num_children() != varlist.
size()) {
485 for (
auto const &pointj : point.children()) {
487 v->
setVal(pointj.val_double());
490 if (weightVals.size() > 0) {
491 data->add(vars, weightVals[i]);
506 const std::vector<std::unique_ptr<RooAbsData>> &datasets)
510 JSONNode const *mcAuxNode = findRooFitInternal(rootnode,
"ModelConfigs", analysisName);
512 JSONNode const *mcNameNode = mcAuxNode ? mcAuxNode->
find(
"mcName") :
nullptr;
513 std::string mcname = mcNameNode ? mcNameNode->
val() : analysisName;
514 if (workspace.
obj(mcname))
519 mc->
SetWS(workspace);
523 throw std::runtime_error(
"likelihood node not found!");
525 if (!nllNode->has_child(
"distributions")) {
526 throw std::runtime_error(
"likelihood node has no distributions attached!");
528 if (!nllNode->has_child(
"data")) {
529 throw std::runtime_error(
"likelihood node has no data attached!");
531 std::vector<std::string> nllDistNames = valsToStringVec((*nllNode)[
"distributions"]);
533 for (
auto &nameNode : (*nllNode)[
"aux_distributions"].children()) {
534 if (
RooAbsArg *extConstraint = workspace.
arg(nameNode.val())) {
535 extConstraints.
add(*extConstraint);
539 for (
auto &nameNode : (*nllNode)[
"data"].children()) {
541 for (
const auto &
d : datasets) {
542 if (
d->GetName() == nameNode.val()) {
544 observables.
add(*
d->get(),
true);
547 if (nameNode.val() !=
"0" && !found)
548 throw std::runtime_error(
"dataset '" + nameNode.val() +
"' cannot be found!");
551 JSONNode const *pdfNameNode = mcAuxNode ? mcAuxNode->
find(
"pdfName") :
nullptr;
552 std::string
const pdfName = pdfNameNode ? pdfNameNode->
val() :
"simPdf";
558 if (nllDistNames.size() == 1) {
560 pdf = workspace.
pdf(nllDistNames[0]);
563 std::string simPdfName = analysisName +
"_simPdf";
564 std::string indexCatName = analysisName +
"_categoryIndex";
565 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
566 std::map<std::string, RooAbsPdf *> pdfMap;
567 for (std::size_t i = 0; i < nllDistNames.size(); ++i) {
568 indexCat.defineType(nllDistNames[i], i);
569 pdfMap[nllDistNames[i]] = workspace.
pdf(nllDistNames[i]);
571 RooSimultaneous simPdf{simPdfName.c_str(), simPdfName.c_str(), pdfMap, indexCat};
573 pdf = workspace.
pdf(simPdfName);
579 if (!extConstraints.
empty())
580 mc->SetExternalConstraints(extConstraints);
582 auto readArgSet = [&](std::string
const &
name) {
590 mc->SetParametersOfInterest(readArgSet(
"parameters_of_interest"));
591 mc->SetObservables(observables);
602 for (
auto &domain : analysisNode[
"domains"].
children()) {
604 if (!thisDomain || !thisDomain->has_child(
"axes"))
606 for (
auto &var : (*thisDomain)[
"axes"].children()) {
609 domainPars.
add(*wsvar);
615 for (
const auto &
p : pars) {
616 if (mc->GetParametersOfInterest()->find(*
p))
618 if (
p->isConstant() && !mainPars.find(*
p) && domainPars.
find(*
p)) {
620 }
else if (domainPars.
find(*
p)) {
625 mc->SetGlobalObservables(globs);
626 mc->SetNuisanceParameters(nps);
629 if (
auto found = mcAuxNode->
find(
"combined_data_name")) {
634 if (analysisNode.
has_child(
"init") && workspace.
getSnapshot(analysisNode[
"init"].val().c_str())) {
635 mc->SetSnapshot(*workspace.
getSnapshot(analysisNode[
"init"].
val().c_str()));
641 auto *combinedPdfInfoNode = findRooFitInternal(rootnode,
"combined_distributions");
644 if (combinedPdfInfoNode ==
nullptr) {
648 for (
auto &info : combinedPdfInfoNode->children()) {
651 std::string combinedName = info.key();
652 std::string indexCatName = info[
"index_cat"].val();
653 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
654 std::vector<int> indices;
655 std::vector<std::string> pdfNames = valsToStringVec(info[
"distributions"]);
656 for (
auto &
n : info[
"indices"].children()) {
657 indices.push_back(
n.val_int());
660 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
661 std::map<std::string, RooAbsPdf *> pdfMap;
663 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
664 indexCat.defineType(labels[iChannel], indices[iChannel]);
665 pdfMap[labels[iChannel]] = ws.
pdf(pdfNames[iChannel]);
668 RooSimultaneous simPdf{combinedName.c_str(), combinedName.c_str(), pdfMap, indexCat};
673void combineDatasets(
const JSONNode &rootnode, std::vector<std::unique_ptr<RooAbsData>> &datasets)
675 auto *combinedDataInfoNode = findRooFitInternal(rootnode,
"combined_datasets");
678 if (combinedDataInfoNode ==
nullptr) {
682 for (
auto &info : combinedDataInfoNode->children()) {
685 std::string combinedName = info.key();
686 std::string indexCatName = info[
"index_cat"].val();
687 std::vector<std::string> labels = valsToStringVec(info[
"labels"]);
688 std::vector<int> indices;
689 for (
auto &
n : info[
"indices"].children()) {
690 indices.push_back(
n.val_int());
692 if (indices.size() != labels.size()) {
697 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
698 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
700 for (std::size_t iChannel = 0; iChannel < labels.size(); ++iChannel) {
701 auto componentName = combinedName +
"_" + labels[iChannel];
704 std::unique_ptr<RooAbsData> &component = *std::find_if(
705 datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
708 allVars.add(*component->get(),
true);
709 dsMap.insert({labels[iChannel], std::move(component)});
710 indexCat.defineType(labels[iChannel], indices[iChannel]);
713 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
715 datasets.emplace_back(std::move(combined));
720void sortByName(T &coll)
722 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
750 " has several category observables!");
772 if (isLiteralConstVar(*arg)) {
780 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
823 if (str.empty() || !(std::isalpha(str[0]) || str[0] ==
'_')) {
830 if (!(std::isalnum(
c) ||
c ==
'_')) {
842 std::stringstream ss;
843 ss <<
"RooJSONFactoryWSTool() name '" <<
name <<
"' is not valid!" << std::endl
844 <<
"Sanitize names by setting RooJSONFactoryWSTool::config().allowSanitizeNames = true." << std::endl;
862 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
866RooRealVar *RooJSONFactoryWSTool::requestImpl<RooRealVar>(
const std::string &objname)
871 if (
const auto &node = vars->find(objname)) {
881RooAbsPdf *RooJSONFactoryWSTool::requestImpl<RooAbsPdf>(
const std::string &objname)
895RooAbsReal *RooJSONFactoryWSTool::requestImpl<RooAbsReal>(
const std::string &objname)
899 if (isNumber(objname))
901 if (
RooAbsPdf *pdf = requestImpl<RooAbsPdf>(objname))
903 if (
RooRealVar *var = requestImpl<RooRealVar>(objname))
932 var[
"value"] << cv->getVal();
933 var[
"const"] <<
true;
935 var[
"value"] << rrv->getVal();
936 if (storeConstant && (rrv->isConstant() || rrv->getMin() >= rrv->getMax())) {
937 var[
"const"] <<
true;
938 }
else if (storeBins) {
939 var[
"min"] << rrv->getMin();
940 var[
"max"] << rrv->getMax();
942 if (rrv->getBins() != 0 && storeBins) {
943 var[
"nbins"] << rrv->getBins();
960 const std::string &formula)
962 std::string newname = std::string(original->
GetName()) + suffix;
964 trafo_node[
"type"] <<
"generic";
977 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
980 exportedObjectNames.insert(
name);
987 std::vector<std::string> channelNames;
988 for (
auto const &item : simPdf->indexCat()) {
989 channelNames.push_back(item.first);
993 auto &
child = infoNode[simPdf->GetName()].set_map();
994 child[
"index_cat"] << simPdf->indexCat().GetName();
996 child[
"distributions"].set_seq();
997 for (
auto const &item : simPdf->indexCat()) {
998 child[
"distributions"].append_child() << simPdf->getPdf(item.first.c_str())->GetName();
1010 auto &collectionNode = (*_rootnodeOutput)[
dynamic_cast<RooAbsPdf const *
>(&func) ?
"distributions" :
"functions"];
1019 auto it = exporters.find(cl);
1020 if (it != exporters.end()) {
1021 for (
auto &exp : it->second) {
1024 if (!exp->exportObject(
this, &func, elem)) {
1030 elem[
"name"] <<
name;
1034 if (exp->autoExportDependants()) {
1047 const auto &dict = exportKeys.find(cl);
1048 if (dict == exportKeys.end()) {
1049 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1050 <<
"there are several possible reasons for this:\n"
1051 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1053 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1054 <<
" 3. something is wrong with your setup, e.g. you might have called "
1055 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1056 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1057 <<
"either way, please make sure that:\n"
1058 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1059 "see what is available\n"
1060 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1061 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to "
1062 "see how to do this!\n";
1066 elem[
"type"] << dict->second.type;
1070 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();
1106 std::cerr <<
"unable to locate server of " << func.
GetName() << std::endl;
1146 std::string prefix = genPrefix(
p,
true);
1147 if (!prefix.empty())
1149 if (!
p.has_child(
"type")) {
1153 std::string functype(
p[
"type"].val());
1156 if (!importAllDependants) {
1161 auto it = importers.find(functype);
1163 if (it != importers.end()) {
1164 for (
auto &imp : it->second) {
1166 ok = imp->importArg(
this,
p);
1167 }
catch (
const std::exception &
e) {
1168 std::stringstream ss;
1169 const auto *ptr = imp.get();
1170 ss <<
"RooJSONFactoryWSTool() failed. The importer " <<
typeid(*ptr).name()
1171 <<
" emitted and error: " <<
e.what() << std::endl;
1179 auto expr = factoryExpressions.find(functype);
1180 if (expr != factoryExpressions.end()) {
1181 std::string expression = ::generate(expr->second,
p,
this);
1183 std::stringstream ss;
1184 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1185 <<
"', skipping. expression was\n"
1186 << expression << std::endl;
1190 std::stringstream ss;
1191 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1193 <<
"there are several possible reasons for this:\n"
1194 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1195 <<
" 2. " << functype
1196 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1197 <<
" 3. something is wrong with your setup, e.g. you might have called "
1198 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1199 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1200 <<
"either way, please make sure that:\n"
1201 <<
" 3: you are reading a file with factory expressions - call "
1202 "RooFit::JSONIO::printFactoryExpressions() "
1203 "to see what is available\n"
1204 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1205 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to see "
1230 this->
importFunction((JSONTree::create(jsonString))->rootnode(), importAllDependants);
1244 obsNode[
"name"] <<
name;
1263 auto &observablesNode = output[
"axes"].
set_seq();
1265 for (
auto *var : static_range_cast<RooRealVar *>(vars)) {
1266 exportAxis(observablesNode.append_child().set_map(), *var);
1286 for (std::size_t i = 0; i <
n; ++i) {
1287 double w = contents[i];
1301std::string makeValidNameOrError(std::string
const &in)
1303 if (!std::isalpha(in[0])) {
1308 oocoutW(
nullptr, IO) <<
"RooFitHS3: changed '" << in <<
"' to '" << out <<
"' to become a valid name";
1327 auto &labels = node[
"labels"].
set_seq();
1328 auto &indices = node[
"indices"].
set_seq();
1330 for (
auto const &item : cat) {
1331 labels.
append_child() << makeValidNameOrError(item.first);
1332 indices.append_child() << item.second;
1358 auto *combinedPdfInfoNode = findRooFitInternal(*
_rootnodeOutput,
"combined_distributions");
1359 if (combinedPdfInfoNode) {
1360 for (
auto &info : combinedPdfInfoNode->children()) {
1361 if (info[
"index_cat"].val() == cat->
GetName()) {
1371 std::vector<std::unique_ptr<RooAbsData>> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1373 for (std::unique_ptr<RooAbsData>
const &absData : dataList) {
1374 std::string catName(absData->GetName());
1375 std::string dataName = makeValidNameOrError(catName);
1376 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1377 datamap.
components[catName] = absData->GetName();
1400 if (
auto weightVar = variables.find(
"weightVar")) {
1401 variables.remove(*weightVar);
1406 output[
"type"] <<
"binned";
1407 for (
auto *var : static_range_cast<RooRealVar *>(variables)) {
1410 return exportHisto(variables, dh->numEntries(), dh->weightArray(), output);
1419 if (
data.isWeighted() && variables.size() == 1) {
1420 bool isBinnedData =
false;
1421 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1422 std::vector<double> contents;
1424 for (; i <
data.numEntries(); ++i) {
1426 if (
x.getBin() != i)
1428 contents.push_back(
data.weight());
1430 if (i ==
x.getBins())
1431 isBinnedData =
true;
1433 output[
"type"] <<
"binned";
1434 for (
auto *var : static_range_cast<RooRealVar *>(variables)) {
1437 return exportHisto(variables,
data.numEntries(), contents.data(), output);
1442 output[
"type"] <<
"unbinned";
1443 auto &observablesNode = output[
"axes"].
set_seq();
1444 for (
auto *var : static_range_cast<RooRealVar *>(variables)) {
1446 exportAxis(observablesNode.append_child().set_map(), *var);
1448 auto &coords = output[
"entries"].
set_seq();
1449 std::vector<double> weightVals;
1450 bool hasNonUnityWeights =
false;
1451 for (
int i = 0; i <
data.numEntries(); ++i) {
1453 coords.append_child().fill_seq(variables, [](
auto x) {
return static_cast<RooRealVar *
>(
x)->getVal(); });
1454 if (
data.isWeighted()) {
1455 weightVals.push_back(
data.weight());
1456 if (
data.weight() != 1.)
1457 hasNonUnityWeights =
true;
1460 if (
data.isWeighted() && hasNonUnityWeights) {
1461 output[
"weights"].
fill_seq(weightVals);
1479 if (node.has_child(
"edges")) {
1480 std::vector<double> edges;
1481 for (
auto const &bound : node[
"edges"].children()) {
1482 edges.push_back(bound.val_double());
1484 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(), edges[0],
1485 edges[edges.size() - 1]);
1486 RooBinning bins(obs->getMin(), obs->getMax());
1487 for (
auto b : edges) {
1490 obs->setBinning(bins);
1493 auto obs = std::make_unique<RooRealVar>(node[
"name"].val().c_str(), node[
"name"].val().c_str(),
1494 node[
"min"].val_double(), node[
"max"].val_double());
1495 obs->setBins(node[
"nbins"].val_int());
1514std::unique_ptr<RooDataHist>
1517 if (!
n.has_child(
"contents"))
1520 JSONNode const &contents =
n[
"contents"];
1526 if (
n.has_child(
"errors")) {
1527 errors = &
n[
"errors"];
1532 auto bins = generateBinIndices(vars);
1535 ", bins=" + std::to_string(bins.size()));
1537 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1538 std::vector<double> contentVals;
1540 for (
auto const &cont : contents.
children()) {
1541 contentVals.push_back(cont.val_double());
1543 std::vector<double> errorVals;
1546 for (
auto const &err : errors->
children()) {
1547 errorVals.push_back(err.val_double());
1550 for (
size_t ibin = 0; ibin < bins.size(); ++ibin) {
1551 const double err = errors ? errorVals[ibin] : -1;
1552 dh->set(ibin, contentVals[ibin], err);
1567 oocoutE(
nullptr, InputArguments) <<
"RooJSONFactoryWSTool() node '" <<
name <<
"' is not a map, skipping."
1571 if (
config().importNoDomainParametersAsRooConstVars && !
_domains->hasVariable(
name.c_str())) {
1572 if (!
p.has_child(
"value")) {
1575 wsEmplace<RooConstVar>(
name,
p[
"value"].val_double());
1578 configureVariable(*
_domains,
p, wsEmplace<RooRealVar>(
name, 1.));
1585 if (
JSONNode const *varsNode = getVariablesNode(
n)) {
1586 for (
const auto &
p : varsNode->children()) {
1590 if (
auto seq =
n.find(
"functions")) {
1591 for (
const auto &
p : seq->children()) {
1595 if (
auto seq =
n.find(
"distributions")) {
1596 for (
const auto &
p : seq->children()) {
1603 const std::vector<CombinedData> &combDataSets,
1604 const std::vector<RooAbsData *> &singleDataSets)
1609 for (std::size_t i = 0; i < std::max(combDataSets.size(), std::size_t(1)); ++i) {
1610 const bool hasdata = i < combDataSets.size();
1611 if (hasdata && !matches(combDataSets.at(i), simpdf))
1614 std::string analysisName(simpdf->GetName());
1616 analysisName +=
"_" + combDataSets[i].name;
1623 for (
auto *
data : singleDataSets) {
1625 std::map<std::string, std::string> mapping;
1626 mapping[pdf->GetName()] =
data->GetName();
1631 if (founddata == 0) {
1638 std::string
const &analysisName,
1639 std::map<std::string, std::string>
const *dataComponents)
1645 auto &domains = analysisNode[
"domains"].
set_seq();
1647 analysisNode[
"likelihood"] << analysisName;
1650 nllNode[
"distributions"].set_seq();
1651 nllNode[
"data"].set_seq();
1653 if (dataComponents) {
1656 for (
auto const &item : simPdf->indexCat()) {
1657 const auto &dataComp = dataComponents->find(item.first);
1658 nllNode[
"distributions"].append_child() << simPdf->getPdf(item.first)->GetName();
1659 nllNode[
"data"].append_child() << dataComp->second;
1662 for (
auto it : *dataComponents) {
1663 nllNode[
"distributions"].append_child() << it.first;
1664 nllNode[
"data"].append_child() << it.second;
1668 nllNode[
"distributions"].append_child() << pdf->GetName();
1669 nllNode[
"data"].append_child() << 0;
1673 auto &extConstrNode = nllNode[
"aux_distributions"];
1674 extConstrNode.set_seq();
1676 extConstrNode.append_child() << constr->GetName();
1680 auto writeList = [&](
const char *
name,
RooArgSet const *args) {
1681 if (!args || !args->size())
1684 std::vector<std::string> names;
1685 names.reserve(args->size());
1687 names.push_back(arg->GetName());
1688 std::sort(names.begin(), names.end());
1694 auto &domainsNode = rootnode[
"domains"];
1696 auto writeProductDomain = [&](
const char *suffix,
RooArgSet const *args) {
1697 if (!args || args->empty())
1699 const std::string domainName = analysisName + suffix;
1700 domains.append_child() << domainName;
1702 for (
auto *var : static_range_cast<const RooRealVar *>(*args)) {
1712 auto &modelConfigAux =
getRooFitInternal(rootnode,
"ModelConfigs", analysisName);
1713 modelConfigAux.set_map();
1714 modelConfigAux[
"pdfName"] << pdf->GetName();
1715 modelConfigAux[
"mcName"] << mc.
GetName();
1721 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1726 std::vector<RooAbsPdf *> allpdfs;
1729 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
1730 allpdfs.push_back(pdf);
1734 sortByName(allpdfs);
1735 std::set<std::string> exportedObjectNames;
1739 std::vector<RooAbsReal *> allfuncs;
1742 if (
auto *func =
dynamic_cast<RooAbsReal *
>(arg)) {
1743 allfuncs.push_back(func);
1747 sortByName(allfuncs);
1752 exportAttributes(arg,
n);
1756 std::vector<RooAbsData *> alldata;
1758 alldata.push_back(
d);
1760 sortByName(alldata);
1762 std::vector<RooAbsData *> singleData;
1763 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
1764 for (
auto &
d : alldata) {
1766 if (!
data.components.empty())
1767 combData.push_back(
data);
1769 singleData.push_back(
d);
1772 for (
auto &
d : alldata) {
1783 exportParameterStepWidths(
_workspace, allpdfs, alldata,
n);
1791 bool do_export =
false;
1792 for (
const auto &pdf : allpdfs) {
1793 if (pdf->dependsOn(*arg)) {
1799 snapshotSorted.
add(*arg);
1802 snapshotSorted.
sort();
1803 std::string
name(snsh->GetName());
1804 if (
name !=
"default_values") {
1823 std::stringstream ss(s);
1834 std::stringstream ss;
1846 std::unique_ptr<JSONTree> tree = JSONTree::create();
1849 auto &metadata =
n[
"metadata"].set_map();
1856 std::string versionName =
gROOT->GetVersion();
1859 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
1860 rootInfo[
"version"] << versionName;
1888 std::ofstream out(
filename.c_str());
1899 if (
auto seq = attrNode->find(
"tags")) {
1900 for (
auto &
a : seq->children()) {
1901 if (
a.val() == attrib)
1911 auto &tags = (*node)[
"tags"];
1921 if (
auto dict = attrNode->find(
"dict")) {
1922 if (
auto *
a = dict->find(attrib)) {
1930 const std::string &
value)
1933 auto &dict = (*node)[
"dict"];
1935 dict[attrib] <<
value;
1946 auto metadata =
n.find(
"metadata");
1947 if (!metadata || !metadata->find(
"hs3_version")) {
1948 std::stringstream ss;
1949 ss <<
"The HS3 version is missing in the JSON!\n"
1950 <<
"Please include the HS3 version in the metadata field, e.g.:\n"
1951 <<
" \"metadata\" :\n"
1962 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
1963 if (
auto domains =
n.find(
"domains")) {
1974 auto buildIndex = [&
n](
const char *key,
auto &
index) {
1976 auto seq =
n.find(key);
1977 if (!seq || !seq->is_seq())
1979 index.reserve(seq->num_children());
1980 for (
const auto &
p : seq->children()) {
1989 if (
auto paramPointsNode =
n.find(
"parameter_points")) {
1990 for (
const auto &snsh : paramPointsNode->children()) {
1995 for (
const auto &var : snsh[
"parameters"].children()) {
1997 configureVariable(*
_domains, var, *rrv);
2011 importAttributes(arg, elem);
2021 std::vector<std::unique_ptr<RooAbsData>> datasets;
2022 if (
auto dataNode =
n.find(
"data")) {
2023 for (
const auto &
p : dataNode->children()) {
2030 if (
auto analysesNode =
n.find(
"analyses")) {
2031 for (
JSONNode const &analysisNode : analysesNode->children()) {
2038 for (
auto const &
d : datasets) {
2041 for (
auto const &obs : *
d->get()) {
2042 if (
auto *rrv =
dynamic_cast<RooRealVar *
>(obs)) {
2043 _workspace.
var(rrv->GetName())->setBinning(rrv->getBinning());
2064 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2065 JSONNode const &rootnode = tree->rootnode();
2067 if (this->
workspace()->getSnapshot(
"default_values")) {
2070 importParameterStepWidths(*this->
workspace(), rootnode);
2083 std::ifstream infile(
filename.c_str());
2084 if (!infile.is_open())
2096 if (
n.find(
"poi")) {
2099 std::string poi =
n.find(
"poi")->val();
2100 std::string pdname =
n.find(
"pdfName")->val();
2102 modelConfig.SetPdf(pdname.c_str());
2111 bool isVariable =
true;
2112 bool isData =
false;
2114 if (
n.find(
"type")) {
2116 std::string elementType =
n.find(
"type")->val();
2117 if (elementType ==
"binned" || elementType ==
"unbinned") {
2125 }
else if (isData) {
2135 std::unique_ptr<RooFit::Detail::JSONTree> tree =
varJSONString(elementNode);
2137 _domains = std::make_unique<RooFit::JSONIO::Detail::Domains>();
2138 if (
auto domains =
n.find(
"domains"))
2144 JSONNode const *varsNode = getVariablesNode(
n);
2145 const auto &
p = varsNode->
child(0);
2148 auto paramPointsNode =
n.find(
"parameter_points");
2149 const auto &var = paramPointsNode->child(0)[
"parameters"].child(0);
2151 configureVariable(*
_domains, var, *rrv);
2158 importAttributes(arg, elem);
2187 throw std::runtime_error(s);
2200 for (
char c : str) {
2205 case '(':
result +=
'_';
break;
2210 case '.':
result +=
"_dot_";
break;
2211 case '@':
result +=
"at";
break;
2212 case '-':
result +=
"minus";
break;
2213 case '/':
result +=
"_div_";
break;
2228 if (onlyModelConfig) {
2237 for (
auto *pdf : ws.
allPdfs()) {
2238 if (isTopLevel(*pdf, ws)) {
2244 if (isTopLevel(*func, ws)) {
2263 auto *snshSet =
dynamic_cast<RooArgSet *
>(snsh);
2265 tmpWS.
saveSnapshot(snshSet->GetName(), *snshSet,
true);
2285 auto sanitizeIfNeeded = [](
auto const &list) {
2286 for (
auto *obj : list) {
2292 sanitizeIfNeeded(tmpWS.
allVars());
2294 sanitizeIfNeeded(tmpWS.
allPdfs());
2302 for (
auto *obj : *
data->get()) {
2309 for (
auto *obj : *
data->get()) {
2315 auto *snsh =
dynamic_cast<RooArgSet *
>(snshObj);
2317 std::cerr <<
"Warning: found snapshot that is not a RooArgSet, skipping\n";
2327 for (
auto *arg : *snsh) {
2337 if (
auto *named =
dynamic_cast<TNamed *
>(obj)) {
2338 named->SetName(
sanitizeName(named->GetName()).c_str());
2340 std::cerr <<
"Warning: object " << obj->GetName() <<
" is not TNamed, cannot rename.\n";
2351 for (
auto *obs : mc->GetObservables()->get()) {
2356 for (
auto *poi : mc->GetParametersOfInterest()->get()) {
2361 for (
auto *nuis : mc->GetNuisanceParameters()->get()) {
2366 for (
auto *glob : mc->GetGlobalObservables()->get()) {
2373 std::string wsName = std::string{ws.
GetName()} +
"_sanitized";
2375 newWS.
SetName(wsName.c_str());
std::unique_ptr< RooFit::Detail::JSONTree > varJSONString(const JSONNode &treeRoot)
void writeAxisBinning(JSONNode &node, const RooAbsBinning &binning)
double toDouble(const char *s)
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
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.
TClass * IsA() const override
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...
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
const std::set< std::string > & attributes() const
const RefCountList_t & servers() const
List of all servers of this object.
const std::map< std::string, std::string > & stringAttributes() const
Int_t numProxies() const
Return the number of registered proxies.
const RefCountList_t & clients() const
List of all clients of this object.
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.
bool equals(const RooAbsCollection &otherColl) const
Check if this and other collection have identically-named contents.
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.
void setName(const char *name)
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.
std::unique_ptr< RooArgSet > getAllConstraints(const RooArgSet &observables, RooArgSet &constrainedParams, bool stripDisconnected=true) 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.
bool containsInstance(const RooAbsArg &var) const override
Check if this exact instance is in this collection.
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
JSONNode const * find(std::string const &key) 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'.
const RooAbsBinning & getBinning(const char *name=nullptr, bool verbose=true, bool createOnTheFly=false, bool shared=true) const override
Return binning definition with name.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
const RooAbsCategoryLValue & indexCat() const
< A class that holds configuration information for a model using a workspace as a store
const RooArgSet * GetGlobalObservables() const
get RooArgSet for global observables (return nullptr if not existing)
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 * GetObservables() const
get RooArgSet for observables (return nullptr if not existing)
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)
const RooArgSet * getSnapshot(const char *name) const
Return the RooArgSet containing a snapshot of variables contained in the workspace.
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
RooArgSet allVars() const
Return set with all variable objects.
RooArgSet argSet(RooStringView nameList) const
Return set of RooAbsArgs matching to given list of names.
RooArgSet allResolutionModels() const
Return set with all resolution model objects.
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.
const RooArgSet & components() const
RooArgSet allFunctions() const
Return set with all function objects.
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.
std::list< RooAbsData * > allEmbeddedData() const
Return list of all dataset in the workspace.
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.
The TNamed class is the base class for all named ROOT classes.
const char * GetName() const override
Returns name of object.
virtual void SetName(const char *name)
Set the name of the TNamed.
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()