129 for (
auto const &function : doc.
functions) {
130 functions.emplace(function.name, &function);
136 if (point.name ==
"default_values") {
138 for (
auto const &
p : point.parameters) {
147 std::unordered_map<std::string, HS3::Function const *>
functions;
159 std::map<std::string, std::map<std::string, HS3::DomainAxis>>
domains;
166 std::vector<DistributionRef> channelConstraints)
168 tool.
_export->typedObject = std::move(dist);
169 tool.
_export->channelConstraints = std::move(channelConstraints);
181 for (
int i = 0; i < binning.
numBins(); ++i) {
199 axis.
binning = toBinning(binning);
206void recordDomains(std::map<std::string, std::map<std::string, HS3::DomainAxis>> &domains,
RooRealVar const &var)
209 for (
auto const &
name : var.getBinningNames()) {
216void appendDomain(std::vector<HS3::Domain> &domains, std::string
const &
name,
217 std::map<std::string, HS3::DomainAxis> axes)
221 for (
auto &item : axes) {
222 domain.
axes.emplace_back(std::move(item.second));
229 if (
auto const *edges = std::get_if<HS3::EdgesBinning>(&binning)) {
230 if (edges->
edges.empty()) {
234 for (
double edge : edges->edges) {
235 bins.addBoundary(edge);
238 }
else if (
int nbins = std::get<HS3::RegularBinning>(binning).nbins) {
260 applyBinning(var, *axis.
binning);
268 auto forEachAxis = [&](
auto &&fn) {
270 for (
auto const &axis : domain.axes) {
271 if (
auto const *continuous = std::get_if<HS3::DomainAxis>(&axis)) {
272 fn(domain.
name, *continuous);
281 ws.import(RooConstVar{axis.name.c_str(), axis.name.c_str(), *axis.fixedValue},
RooFit::Silence());
286 RooRealVar var{axis.name.c_str(), axis.name.c_str(), axis.min.value_or(-inf), axis.max.value_or(inf)};
288 applyBinning(var, *axis.
binning);
297 for (
auto const &axisVariant : domain.axes) {
298 auto const *axis = std::get_if<HS3::CategoricalAxis>(&axisVariant);
306 "' already exists and is not a category");
308 std::set<std::string> existingLabels;
309 for (
auto const &state : *cat) {
310 existingLabels.insert(state.first);
312 if (existingLabels != std::set<std::string>(axis->categories.begin(), axis->categories.end())) {
314 "' differ from the states of the existing category '" + axis->
name +
"'");
319 for (std::size_t i = 0; i < axis->categories.size(); ++i) {
320 cat.defineType(axis->categories[i],
static_cast<int>(i));
325 forEachAxis([&](std::string
const &domain,
HS3::DomainAxis const &axis) {
328 var->
setRange(domain.c_str(), axis.
min.value_or(-inf), axis.
max.value_or(inf));
330 applyBinning(*var, *axis.
binning, domain.c_str());
344 ImportGuard(std::vector<std::string> &stack, std::string
const &
name) : _stack{stack}
346 if (std::find(_stack.begin(), _stack.end(),
name) != _stack.end()) {
348 for (std::string
const &ancestor : _stack) {
349 chain += ancestor +
" -> ";
353 _stack.push_back(
name);
355 ~ImportGuard() { _stack.pop_back(); }
358 std::vector<std::string> &_stack;
366 for (
Diagnostic const &diagnostic : diagnostics) {
367 const std::string
text =
368 diagnostic.path.empty() ? diagnostic.message : diagnostic.path +
": " + diagnostic.message;
369 if (diagnostic.severity == Diagnostic::Severity::Error) {
370 errors += (errors.empty() ?
"" :
"\n") +
text;
375 if (!errors.empty()) {
389bool isNumber(
const std::string &str)
394 std::istringstream stream(str);
396 return (stream >>
value) && stream.eof();
403 if (
auto const *
value = std::get_if<double>(&*
p.value)) {
408 applyRange(
v, *range);
413 v.setError(
v.getVal() * *
p.relError);
415 v.setError(*
p.error);
416 v.setConstant(
p.isConst);
419std::string genPrefix(
const JSONNode &
p,
bool trailing_underscore)
424 if (
auto node =
p.find(
"namespaces")) {
425 for (
const auto &ns : node->children()) {
431 if (trailing_underscore && !prefix.empty())
437void genIndicesHelper(std::vector<std::vector<int>> &combinations, std::vector<int> &curr_comb,
438 const std::vector<int> &vars_numbins,
size_t curridx)
440 if (curridx == vars_numbins.size()) {
442 combinations.emplace_back(curr_comb);
444 for (
int i = 0; i < vars_numbins[curridx]; ++i) {
445 curr_comb[curridx] = i;
446 ::genIndicesHelper(combinations, curr_comb, vars_numbins, curridx + 1);
454 for (
auto const &
attr : attributes.dict) {
457 for (
auto const &tag : attributes.tags) {
465 out.
add(*args,
true);
469void collectParameterStepWidthCandidatesFromModelConfigs(
RooWorkspace const &workspace,
RooArgSet &candidates,
472 for (
TObject *obj : workspace.allGenericObjects()) {
478 addIfPresent(candidates, mc->GetParametersOfInterest());
479 addIfPresent(candidates, mc->GetNuisanceParameters());
481 addIfPresent(excluded, mc->GetObservables());
482 addIfPresent(excluded, mc->GetGlobalObservables());
483 addIfPresent(excluded, mc->GetConditionalObservables());
487void collectParameterStepWidthCandidatesFromPdfs(std::vector<RooAbsPdf *>
const &pdfs,
488 std::vector<RooAbsData *>
const &
data,
RooArgSet &candidates,
494 std::unique_ptr<RooArgSet> pdfObs{pdf->
getObservables(*dataset->get())};
495 observables.
add(*pdfObs,
true);
498 if (observables.
empty()) {
504 candidates.
add(params,
true);
505 excluded.
add(observables,
true);
509void exportParameterStepWidths(
RooWorkspace const &workspace, std::vector<RooAbsPdf *>
const &pdfs,
510 std::vector<RooAbsData *>
const &
data, std::vector<HS3::StepWidth> &out)
515 collectParameterStepWidthCandidatesFromModelConfigs(workspace, candidates, excluded);
516 collectParameterStepWidthCandidatesFromPdfs(pdfs,
data, candidates, excluded);
521 if (excluded.
find(*arg)) {
537 auto *var =
dynamic_cast<RooRealVar *
>(workspace.
arg(stepWidth.name));
541 stepWidth.name +
"'.");
551 std::stringstream expression;
552 std::string classname(
ex.tclass->GetName());
553 size_t colon = classname.find_last_of(
':');
554 expression << (colon < classname.size() ? classname.substr(colon + 1) : classname);
557 for (
auto k :
ex.arguments) {
558 expression << (first ?
"::" +
name +
"(" :
",");
560 if (k ==
"true" || k ==
"false") {
561 expression << (k ==
"true" ?
"1" :
"0");
562 }
else if (!
p.has_child(k)) {
564 }
else if (
p[k].is_seq()) {
565 bool firstInner =
true;
568 expression << (firstInner ?
"" :
",") << arg->
GetName();
574 expression <<
p[k].val();
578 return expression.str();
582std::vector<std::vector<int>> generateBinIndices(
const RooArgSet &vars)
584 std::vector<std::vector<int>> combinations;
585 std::vector<int> vars_numbins;
586 vars_numbins.reserve(vars.
size());
591 std::vector<int> curr_comb(vars.
size());
592 ::genIndicesHelper(combinations, curr_comb, vars_numbins, 0);
596template <
typename... Keys_t>
597JSONNode const *findRooFitInternal(
JSONNode const &node, Keys_t
const &...keys)
599 return node.
find(
"misc",
"ROOT_internal", keys...);
603bool isLiteralConstVar(
RooAbsArg const &arg)
605 bool isRooConstVar =
dynamic_cast<RooConstVar const *
>(&arg);
606 return isRooConstVar && isNumber(arg.
GetName());
610void exportAttributes(
const RooAbsArg *arg, std::map<std::string, HS3::Attributes> &attributes)
613 if (isLiteralConstVar(*arg) ||
dynamic_cast<RooConstVar const *
>(arg)) {
620 out = &attributes[arg->
GetName()];
625 for (
const auto &it : arg->stringAttributes()) {
627 if (it.first ==
"factory_tag" || it.first ==
"PROD_TERM_TYPE")
630 out->
dict[it.first] = it.second;
632 for (
auto const &
attr : arg->attributes()) {
634 if (
attr ==
"SnapShot_ExtRefClone" ||
attr ==
"RooRealConstant_Factory_Object")
651 axis.
binning = toBinning(binning);
657 if (isLiteralConstVar(arg)) {
658 return static_cast<RooConstVar const &
>(arg).getVal();
660 return std::string{arg.
GetName()};
665std::unique_ptr<RooRealVar> createObservable(
HS3::BinnedAxis const &axis)
667 auto obs = std::make_unique<RooRealVar>(axis.
name.c_str(), axis.
name.c_str(), axis.
min, axis.
max);
668 applyBinning(*obs, axis.
binning);
673std::set<std::string> labelsOf(
RooCategory const &cat)
675 std::set<std::string> labels;
676 for (
auto const &state : cat) {
677 labels.insert(state.first);
687RooArgSet createBinnedObservables(std::vector<std::variant<HS3::BinnedAxis, HS3::CategoricalAxis>>
const &axes,
688 RooWorkspace const &workspace, std::string
const &dataName,
689 std::vector<std::size_t> &binOrder)
692 std::vector<std::vector<std::size_t>> axisPositions;
693 bool reordered =
false;
694 for (
auto const &axisVariant : axes) {
695 if (
auto const *axis = std::get_if<HS3::BinnedAxis>(&axisVariant)) {
696 auto obs = createObservable(*axis);
697 std::vector<std::size_t> positions(obs->numBins());
698 std::iota(positions.begin(), positions.end(), 0);
699 axisPositions.push_back(std::move(positions));
703 auto const &axis = std::get<HS3::CategoricalAxis>(axisVariant);
704 auto cat = std::make_unique<RooCategory>(axis.
name.c_str(), axis.
name.c_str());
706 if (labelsOf(*wsCat) != std::set<std::string>(axis.categories.begin(), axis.categories.end())) {
708 "' differ from those of the category '" + axis.
name +
"'");
710 for (
unsigned int i = 0; i < wsCat->size(); ++i) {
711 auto const &state = wsCat->getOrdinal(i);
715 for (std::size_t i = 0; i < axis.categories.size(); ++i) {
716 cat->
defineType(axis.categories[i],
static_cast<int>(i));
719 std::vector<std::size_t> positions(axis.categories.size());
720 for (std::size_t i = 0; i < positions.size(); ++i) {
721 auto found = std::find(axis.categories.begin(), axis.categories.end(), cat->
getOrdinal(i).first);
722 positions[i] = std::distance(axis.categories.begin(), found);
723 reordered |= positions[i] != i;
725 axisPositions.push_back(std::move(positions));
732 std::size_t
total = 1;
733 for (
auto const &positions : axisPositions) {
734 total *= positions.size();
736 binOrder.resize(
total);
737 for (std::size_t k = 0; k <
total; ++k) {
739 std::size_t rest = k;
740 std::size_t docIndex = 0;
741 std::size_t stride = 1;
742 for (std::size_t j = axisPositions.size(); j-- > 0;) {
743 const std::size_t nBins = axisPositions[j].size();
744 docIndex += axisPositions[j][rest % nBins] * stride;
748 binOrder[k] = docIndex;
754std::vector<double> permute(std::vector<double>
const &values, std::vector<std::size_t>
const &order)
756 if (order.empty() || values.size() != order.size()) {
759 std::vector<double> out(values.size());
760 for (std::size_t k = 0; k < order.size(); ++k) {
761 out[k] = values[order[k]];
771 if (!axis.
min || !axis.
max) {
777 std::stringstream ss;
778 ss <<
"RooFitHS3: the range [" << *axis.
min <<
", " << *axis.
max <<
"] of the axis '" << axis.
name
779 <<
"' of the dataset '" << dataName <<
"' differs from the range [" << var.
getMin() <<
", " << var.
getMax()
780 <<
"] of the variable.";
789 for (
auto const &axisVariant :
input.axes) {
790 auto const *axis = std::get_if<HS3::ContinuousAxis>(&axisVariant);
793 auto const &catAxis = std::get<HS3::CategoricalAxis>(axisVariant);
797 "\" could not be found in the workspace! Categorical observables are "
798 "declared by a categorical axis in a domain.");
800 if (labelsOf(*cat) != std::set<std::string>(catAxis.categories.begin(), catAxis.categories.end())) {
802 "\" differ from the states of the category \"" + catAxis.name +
"\"");
812 applyUnbinnedAxisRange(*axis,
name, *var, ranges);
816 const std::size_t nAxes =
input.axes.size();
817 for (std::size_t i = 0; i <
input.numEntries(); ++i) {
818 for (std::size_t j = 0; j < nAxes; ++j) {
819 const double value =
input.entries[i * nAxes + j];
820 if (
auto const *catAxis = std::get_if<HS3::CategoricalAxis>(&
input.axes[j])) {
822 static_cast<RooCategory *
>(varlist.
at(j))->setLabel(catAxis->categories[
static_cast<std::size_t
>(
value)]);
833std::unique_ptr<RooAbsData>
839 if (
auto const *binned = std::get_if<HS3::BinnedData>(&
input.body)) {
840 if (
binned->uncertainty && !
binned->uncertainty->correlation.empty()) {
842 input.name +
"' are ignored, because RooDataHist can't store them.");
844 std::vector<std::size_t> binOrder;
846 std::vector<double>
sigma;
847 if (
binned->uncertainty) {
848 sigma = permute(
binned->uncertainty->sigma, binOrder);
853 if (
auto const *unbinned = std::get_if<HS3::UnbinnedData>(&
input.body)) {
854 if (
unbinned->hasEntriesUncertainties) {
856 "' are ignored, because RooDataSet can't store them.");
858 return createUnbinnedData(
input.name, *unbinned, workspace, ranges);
864std::string rootVersion()
866 std::string versionName =
gROOT->GetVersion();
867 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
872void requirePdf(
RooAbsArg const *arg, std::string
const &
what)
874 if (!
dynamic_cast<RooAbsPdf const *
>(arg)) {
876 (arg ? std::string(
"a ") + arg->
ClassName() +
", not a pdf" :
"not imported"));
882 const std::vector<std::unique_ptr<RooAbsData>> &datasets)
885 std::string
const &analysisName = analysis.
name;
889 std::string mcname = mcInfo && mcInfo->
mcName ? *mcInfo->
mcName : analysisName;
890 if (workspace.
obj(mcname))
895 mc->
SetWS(workspace);
898 [&](
HS3::Likelihood const &
l) { return l.name == analysis.likelihood.name; });
900 throw std::runtime_error(
"likelihood node not found!");
904 auto checkPdf = [&](
RooAbsArg const *arg, std::string
const &
name, std::string
const &
what) {
905 requirePdf(arg,
"the " +
what +
" '" +
name +
"' of analysis '" + analysisName +
"'");
908 std::vector<std::string> nllDistNames;
909 nllDistNames.reserve(likelihood.
terms.size());
910 for (
auto const &term : likelihood.terms) {
911 checkPdf(workspace.
arg(term.distribution.name), term.distribution.name,
"distribution");
912 nllDistNames.push_back(term.distribution.name);
916 std::set<std::string> channelConstraints;
917 for (
auto const &item : doc.rooFit.channelConstraints) {
918 for (
auto const &ref : item.second) {
919 channelConstraints.insert(ref.name);
923 for (
auto const &aux : likelihood.auxDistributions) {
925 if (!extConstraint) {
928 checkPdf(extConstraint, aux.name,
"auxiliary distribution");
930 if (channelConstraints.count(aux.name) &&
931 std::any_of(nllDistNames.begin(), nllDistNames.end(), [&](std::string
const &distName) {
932 RooAbsArg const *dist = workspace.arg(distName);
933 return dist && dist->dependsOn(*extConstraint);
937 extConstraints.
add(*extConstraint);
940 for (
auto const &term : likelihood.terms) {
941 auto const *dataRef = std::get_if<HS3::DataRef>(&term.data);
946 for (
const auto &
d : datasets) {
947 if (
d->GetName() == dataRef->name) {
949 observables.
add(*
d->get(),
true);
953 throw std::runtime_error(
"dataset '" + dataRef->name +
"' cannot be found!");
956 std::string
const pdfName = mcInfo && mcInfo->
pdfName ? *mcInfo->
pdfName :
"simPdf";
962 if (nllDistNames.size() == 1) {
964 pdf = workspace.
pdf(nllDistNames[0]);
967 std::string simPdfName = analysisName +
"_simPdf";
968 std::string indexCatName = analysisName +
"_categoryIndex";
969 RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
970 std::map<std::string, RooAbsPdf *> pdfMap;
971 for (std::size_t i = 0; i < nllDistNames.size(); ++i) {
972 indexCat.defineType(nllDistNames[i], i);
973 pdfMap[nllDistNames[i]] = workspace.
pdf(nllDistNames[i]);
975 RooSimultaneous simPdf{simPdfName.c_str(), simPdfName.c_str(), pdfMap, indexCat};
977 pdf = workspace.
pdf(simPdfName);
983 if (!extConstraints.
empty())
984 mc->SetExternalConstraints(extConstraints);
986 if (analysis.
prior) {
988 checkPdf(prior, analysis.
prior->name,
"prior");
989 mc->SetPriorPdf(
static_cast<RooAbsPdf &
>(*prior));
994 for (
auto const &poi : analysis.parametersOfInterest) {
998 analysisName +
"' does not exist");
1002 "' is a " + arg->
ClassName() +
", not a variable" +
1003 (
dynamic_cast<RooConstVar *
>(arg) ?
", because no domain lists it" :
""));
1005 parametersOfInterest.
add(*arg);
1008 mc->SetParametersOfInterest(parametersOfInterest);
1009 mc->SetObservables(observables);
1020 for (
auto const &domainRef : analysis.domains) {
1021 auto thisDomain = std::find_if(doc.
domains.begin(), doc.
domains.end(),
1022 [&](
HS3::Domain const &
d) { return d.name == domainRef.name; });
1023 if (thisDomain == doc.
domains.end())
1025 for (
auto const &axis : thisDomain->axes) {
1026 auto *wsvar = workspace.
var(std::visit([](
auto const &
a) -> std::string
const & {
return a.name; }, axis));
1028 domainPars.
add(*wsvar);
1034 for (
const auto &
p : pars) {
1035 if (mc->GetParametersOfInterest()->find(*
p))
1037 if (
p->isConstant() && !mainPars.find(*
p) && domainPars.
find(*
p)) {
1039 }
else if (domainPars.
find(*
p)) {
1044 mc->SetGlobalObservables(globs);
1045 mc->SetNuisanceParameters(nps);
1054 const std::string &initName = analysis.
init->name;
1057 std::string setName = initName;
1058 const std::string prefix = mcname +
"_";
1059 const std::string suffix =
"_snapshot";
1060 if (initName.size() >= prefix.size() + suffix.size() &&
startsWith(initName, prefix) &&
1062 setName = initName.substr(prefix.size(), initName.size() - prefix.size() - suffix.size());
1067 initSet.
setName(setName.c_str());
1068 mc->SetSnapshot(initSet);
1074 for (
auto const &item : doc.rooFit.combinedDistributions) {
1075 std::string
const &combinedName = item.first;
1079 std::map<std::string, RooAbsPdf *> pdfMap;
1081 for (std::size_t iChannel = 0; iChannel < info.
labels.size(); ++iChannel) {
1082 indexCat.defineType(info.
labels[iChannel], info.
indices[iChannel]);
1085 "the distribution '" +
name +
"' of the combined distribution '" + combinedName +
"'");
1089 RooSimultaneous simPdf{combinedName.c_str(), combinedName.c_str(), pdfMap, indexCat};
1094void combineDatasets(
HS3Document const &doc, std::vector<std::unique_ptr<RooAbsData>> &datasets)
1096 for (
auto const &item : doc.rooFit.combinedDatasets) {
1097 std::string
const &combinedName = item.first;
1101 std::map<std::string, std::unique_ptr<RooAbsData>> dsMap;
1104 for (std::size_t iChannel = 0; iChannel < info.
labels.size(); ++iChannel) {
1105 auto componentName = combinedName +
"_" + info.
labels[iChannel];
1109 std::find_if(datasets.begin(), datasets.end(), [&](
auto &
d) { return d && d->GetName() == componentName; });
1110 if (found == datasets.end()) {
1113 allVars.add(*(*found)->get(),
true);
1114 dsMap.insert({info.
labels[iChannel], std::move(*found)});
1115 indexCat.defineType(info.
labels[iChannel], info.
indices[iChannel]);
1118 auto combined = std::make_unique<RooDataSet>(combinedName, combinedName, allVars,
RooFit::Import(dsMap),
1120 datasets.emplace_back(std::move(combined));
1125void sortByName(T &coll)
1127 std::sort(coll.begin(), coll.end(), [](
auto &
l,
auto &
r) { return strcmp(l->GetName(), r->GetName()) < 0; });
1139 for (
RooAbsArg const *client : arg.clients()) {
1155 " has several category observables!");
1169 vars.
addOwned(createObservable(axis));
1175 std::vector<double>
const &contents,
1176 std::vector<double>
const *errors)
1178 if (errors && errors->size() != contents.size()) {
1180 std::to_string(errors->size()) +
", contents=" + std::to_string(contents.size()));
1182 auto bins = generateBinIndices(vars);
1183 if (contents.size() != bins.size()) {
1185 ", bins=" + std::to_string(bins.size()));
1187 auto dh = std::make_unique<RooDataHist>(
name,
name, vars);
1190 if (errors && !errors->empty()) {
1193 for (std::size_t ibin = 0; ibin < bins.size(); ++ibin) {
1194 dh->set(ibin, contents[ibin], errors ? (*errors)[ibin] : -1);
1211 if (isLiteralConstVar(*arg)) {
1219 error(
"unable to stream collection " + std::string(coll.
GetName()) +
" to " + node.
key());
1254 if (str.empty() || !(std::isalpha(str[0]) || str[0] ==
'_')) {
1259 for (
char c : str) {
1261 if (!(std::isalnum(
c) ||
c ==
'_')) {
1273 std::stringstream ss;
1274 ss <<
"RooJSONFactoryWSTool() name '" <<
name <<
"' is not valid!" << std::endl
1275 <<
"Sanitize names by setting RooJSONFactoryWSTool::config().allowSanitizeNames = true." << std::endl;
1288 return n[
"name"].val();
1293 return appendNamedChild(rootNode[
"parameter_points"],
"default_values")[
"parameters"];
1297RooRealVar *RooJSONFactoryWSTool::requestImpl<RooRealVar>(
const std::string &objname)
1302 auto it =
_import->defaultValuesByName.find(objname);
1303 if (it !=
_import->defaultValuesByName.end()) {
1313RooAbsPdf *RooJSONFactoryWSTool::requestImpl<RooAbsPdf>(
const std::string &objname)
1318 auto it =
_import->distributions.find(objname);
1319 if (it !=
_import->distributions.end()) {
1325 auto function =
_import->functions.find(objname);
1326 if (function !=
_import->functions.end()) {
1336RooAbsReal *RooJSONFactoryWSTool::requestImpl<RooAbsReal>(
const std::string &objname)
1340 if (isNumber(objname))
1342 if (
RooAbsPdf *pdf = requestImpl<RooAbsPdf>(objname))
1344 if (
RooRealVar *var = requestImpl<RooRealVar>(objname))
1349 auto it =
_import->functions.find(objname);
1350 if (it !=
_import->functions.end()) {
1376 axis.
name = cv->GetName();
1383 var.
name =
v->GetName();
1384 var.
value = rrv->getVal();
1385 var.
isConst = storeConstant && (rrv->isConstant() || rrv->getMin() >= rrv->getMax());
1386 recordDomains(
_export->domains, *rrv);
1399 const std::string &formula)
1401 std::string newname = std::string(original->
GetName()) + suffix;
1403 auto &functions =
_export->doc.functions;
1404 if (std::find_if(functions.begin(), functions.end(), [&](
auto const &
f) { return f.name == newname; }) !=
1409 trafo_node[
"type"] <<
"generic";
1411 functions.push_back({newname, {
"generic",
nullptr}});
1420std::string makeValidNameOrError(std::string
const &in)
1422 if (!std::isalpha(in[0])) {
1427 oocoutW(
nullptr, ObjectHandling) <<
"RooFitHS3: changed '" << in <<
"' to '" << out <<
"' to become a valid name";
1456 if (exportedObjectNames.find(
name) != exportedObjectNames.end())
1459 exportedObjectNames.insert(
name);
1467 info.
indexCat = simPdf->indexCat().GetName();
1468 for (
auto const &item : simPdf->indexCat()) {
1469 info.
labels.push_back(makeValidNameOrError(item.first));
1470 info.
indices.push_back(item.second);
1471 info.
distributions.push_back({simPdf->getPdf(item.first.c_str())->GetName()});
1486 auto &collectionNode = (*
_export->root)[isPdf ?
"distributions" :
"functions"];
1495 auto it = exporters.find(cl);
1496 if (it != exporters.end()) {
1497 for (
auto &exp : it->second) {
1500 if (!exp->exportObject(
this, &func, elem)) {
1505 elem[
"name"] <<
name;
1511 elem[
"name"] <<
name;
1514 if (!
_export->channelConstraints.empty()) {
1515 _export->doc.rooFit.channelConstraints[
name] = std::move(
_export->channelConstraints);
1517 _export->channelConstraints.clear();
1519 recordGenericObject(
_export->doc, isPdf,
name, elem);
1521 if (exp->autoExportDependants()) {
1534 const auto &dict = exportKeys.find(cl);
1535 if (dict == exportKeys.end()) {
1536 std::cerr <<
"unable to export class '" << cl->
GetName() <<
"' - no export keys available!\n"
1537 <<
"there are several possible reasons for this:\n"
1538 <<
" 1. " << cl->
GetName() <<
" is a custom class that you or some package you are using added.\n"
1540 <<
" is a ROOT class that nobody ever bothered to write a serialization definition for.\n"
1541 <<
" 3. something is wrong with your setup, e.g. you might have called "
1542 "RooFit::JSONIO::clearExportKeys() and/or never successfully read a file defining these "
1543 "keys with RooFit::JSONIO::loadExportKeys(filename)\n"
1544 <<
"either way, please make sure that:\n"
1545 <<
" 3: you are reading a file with export keys - call RooFit::JSONIO::printExportKeys() to "
1546 "see what is available\n"
1547 <<
" 2 & 1: you might need to write a serialization definition yourself. check "
1548 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to "
1549 "see how to do this!\n";
1553 elem[
"type"] << dict->second.type;
1554 recordGenericObject(
_export->doc, isPdf,
name, elem);
1558 for (
size_t i = 0; i < nprox; ++i) {
1564 std::string pname(
p->name());
1565 if (pname[0] ==
'!')
1568 auto k = dict->second.proxies.find(pname);
1569 if (k == dict->second.proxies.end()) {
1570 std::cerr <<
"failed to find key matching proxy '" << pname <<
"' for type '" << dict->second.type
1571 <<
"', encountered in '" << func.
GetName() <<
"', skipping" << std::endl;
1576 if (k->second.empty())
1583 if (isLiteralConstVar(*
r->absArg())) {
1584 elem[k->second] <<
static_cast<RooConstVar *
>(
r->absArg())->getVal();
1586 elem[k->second] <<
r->absArg()->GetName();
1594 std::cerr <<
"unable to locate server of " << func.
GetName() << std::endl;
1637 std::string prefix = genPrefix(
p,
true);
1638 if (!prefix.empty())
1640 if (!
p.has_child(
"type")) {
1644 std::string functype(
p[
"type"].val());
1647 if (!importAllDependants) {
1652 auto it = importers.find(functype);
1654 if (it != importers.end()) {
1655 for (
auto &imp : it->second) {
1659 auto const &channelConstraints =
_import->document.rooFit.channelConstraints;
1660 auto found = channelConstraints.find(
name);
1664 ok = imp->importArg(
this,
p);
1666 }
catch (
const std::exception &
e) {
1667 std::stringstream ss;
1668 const auto *ptr = imp.get();
1669 ss <<
"RooJSONFactoryWSTool() failed. The importer " <<
typeid(*ptr).name()
1670 <<
" emitted and error: " <<
e.what() << std::endl;
1678 auto expr = factoryExpressions.find(functype);
1679 if (expr != factoryExpressions.end()) {
1680 std::string expression = ::generate(expr->second,
p,
this);
1682 std::stringstream ss;
1683 ss <<
"RooJSONFactoryWSTool() failed to create " << expr->second.tclass->GetName() <<
" '" <<
name
1684 <<
"', skipping. expression was\n"
1685 << expression << std::endl;
1689 std::stringstream ss;
1690 ss <<
"RooJSONFactoryWSTool() no handling for type '" << functype <<
"' implemented, skipping."
1692 <<
"there are several possible reasons for this:\n"
1693 <<
" 1. " << functype <<
" is a custom type that is not available in RooFit.\n"
1694 <<
" 2. " << functype
1695 <<
" is a ROOT class that nobody ever bothered to write a deserialization definition for.\n"
1696 <<
" 3. something is wrong with your setup, e.g. you might have called "
1697 "RooFit::JSONIO::clearFactoryExpressions() and/or never successfully read a file defining "
1698 "these expressions with RooFit::JSONIO::loadFactoryExpressions(filename)\n"
1699 <<
"either way, please make sure that:\n"
1700 <<
" 3: you are reading a file with factory expressions - call "
1701 "RooFit::JSONIO::printFactoryExpressions() "
1702 "to see what is available\n"
1703 <<
" 2 & 1: you might need to write a deserialization definition yourself. check "
1704 "https://root.cern/doc/master/group__roofit__dev__docs__hs3.html to see "
1715 for (std::string
const &component : recorder.unreadComponents()) {
1716 warning(
"RooFitHS3: " +
name +
": unknown component \"" + component +
"\" is ignored");
1723 if (
auto const *generic = std::get_if<HS3::GenericObject>(&distribution.
body)) {
1727 std::string
const &
name = distribution.
name;
1736 auto const &channelConstraints =
_import->document.rooFit.channelConstraints;
1737 auto found = channelConstraints.find(
name);
1739 found != channelConstraints.end() ? &found->second :
nullptr);
1754 this->
importFunction((JSONTree::create(jsonString))->rootnode(), importAllDependants);
1768 obsNode[
"name"] <<
name;
1787 auto &observablesNode = output[
"axes"].
set_seq();
1789 for (
auto *var : static_range_cast<RooRealVar *>(vars)) {
1790 exportAxis(observablesNode.append_child().set_map(), *var);
1810 for (std::size_t i = 0; i <
n; ++i) {
1811 double w = contents[i];
1833 auto &labels = node[
"labels"].
set_seq();
1834 auto &indices = node[
"indices"].
set_seq();
1836 for (
auto const &item : cat) {
1837 labels.append_child() << makeValidNameOrError(item.first);
1838 indices.append_child() << item.second;
1860 for (
auto const &item : *cat) {
1861 info.
labels.push_back(makeValidNameOrError(item.first));
1862 info.
indices.push_back(item.second);
1867 for (
auto const &item :
_export->doc.rooFit.combinedDistributions) {
1868 if (item.second.indexCat == cat->
GetName()) {
1877 std::vector<std::unique_ptr<RooAbsData>> dataList{simPdf ?
data.split(*simPdf,
true) :
data.split(*cat,
true)};
1879 for (std::unique_ptr<RooAbsData>
const &absData : dataList) {
1880 std::string catName(absData->GetName());
1881 std::string dataName = makeValidNameOrError(catName);
1882 absData->SetName((std::string(
data.GetName()) +
"_" + dataName).c_str());
1883 datamap.
components[catName] = absData->GetName();
1907 if (
auto weightVar = variables.find(
"weightVar")) {
1908 variables.remove(*weightVar);
1911 auto exportBinned = [&](std::size_t
n,
double const *contents) {
1913 for (
auto *var : static_range_cast<RooRealVar *>(variables)) {
1914 recordDomains(
_export->domains, *var);
1917 binned.contents.assign(contents, contents +
n);
1918 output.
body = std::move(binned);
1919 _export->doc.data.push_back(std::move(output));
1924 return exportBinned(dh->numEntries(), dh->weightArray());
1933 if (
data.isWeighted() && variables.size() == 1) {
1934 bool isBinnedData =
false;
1935 auto &
x =
static_cast<RooRealVar const &
>(*variables[0]);
1936 std::vector<double> contents;
1938 for (; i <
data.numEntries(); ++i) {
1940 if (
x.getBin() != i)
1942 contents.push_back(
data.weight());
1944 if (i ==
x.getBins())
1945 isBinnedData =
true;
1947 return exportBinned(
data.numEntries(), contents.data());
1953 for (
auto *var : static_range_cast<RooRealVar *>(variables)) {
1954 recordDomains(
_export->domains, *var);
1959 std::vector<double> weightVals;
1960 bool hasNonUnityWeights =
false;
1961 for (
int i = 0; i <
data.numEntries(); ++i) {
1963 for (
auto *var : static_range_cast<RooRealVar *>(variables)) {
1964 unbinned.entries.push_back(var->
getVal());
1966 if (
data.isWeighted()) {
1967 weightVals.push_back(
data.weight());
1968 if (
data.weight() != 1.)
1969 hasNonUnityWeights =
true;
1972 if (
data.isWeighted() && hasNonUnityWeights) {
1973 unbinned.weights = std::move(weightVals);
1975 output.
body = std::move(unbinned);
1976 _export->doc.data.push_back(std::move(output));
2007std::unique_ptr<RooDataHist>
2010 if (!
n.has_child(
"contents"))
2013 JSONNode const &contents =
n[
"contents"];
2018 std::vector<double> contentVals;
2019 contentVals << contents;
2021 if (!
n.has_child(
"errors")) {
2024 if (!
n[
"errors"].is_seq())
2026 std::vector<double> errorVals;
2027 errorVals <<
n[
"errors"];
2040 if (
p.value && std::holds_alternative<std::string>(*
p.value))
2042 if (!
_import->ranges.contains(
p.name)) {
2044 auto const &attributes =
_import->document.rooFit.attributes;
2045 auto found = attributes.find(
p.name);
2046 if (found != attributes.end() && found->second.isConstVar) {
2050 wsEmplace<RooConstVar>(
p.name, std::get<double>(*
p.value));
2054 RooRealVar &var = wsEmplace<RooRealVar>(
p.name, 1.);
2055 configureVariable(
_import->ranges,
p, var);
2063 warning(std::string(
"RooFitHS3: the parameter '") + var.
GetName() +
2064 "' is not listed in any domain and is not constant: HS3 requires a domain, or \"const\": true. It "
2065 "is read as a free parameter without range.");
2072 for (
const char *section : {
"functions",
"distributions"}) {
2073 if (
auto seq =
n.find(section)) {
2074 for (
const auto &
p : seq->children()) {
2082 const std::vector<CombinedData> &combDataSets,
2083 const std::vector<RooAbsData *> &singleDataSets)
2088 for (std::size_t i = 0; i < std::max(combDataSets.size(), std::size_t(1)); ++i) {
2089 const bool hasdata = i < combDataSets.size();
2090 if (hasdata && !matches(combDataSets.at(i), simpdf))
2093 std::string analysisName(mc.
GetName());
2095 analysisName +=
"_" + combDataSets[i].name;
2102 for (
auto *
data : singleDataSets) {
2104 std::map<std::string, std::string> mapping;
2110 if (founddata == 0) {
2117 std::map<std::string, std::string>
const *dataComponents)
2123 analysis.
name = analysisName;
2127 likelihood.
name = analysisName +
"_likelihood";
2130 if (dataComponents) {
2133 for (
auto const &item : simPdf->indexCat()) {
2134 const auto &dataComp = dataComponents->find(item.first);
2135 likelihood.
terms.push_back({{simPdf->getPdf(item.first)->GetName()},
HS3::DataRef{dataComp->second}});
2138 for (
auto it : *dataComponents) {
2146 auto addAux = [&](std::string
const &
name) {
2148 if (std::find_if(aux.begin(), aux.end(), [&](
auto const &ref) {
return ref.name ==
name; }) == aux.end()) {
2149 aux.push_back({
name});
2153 for (
auto const &term : likelihood.
terms) {
2156 for (
auto const &ref : found->second) {
2163 addAux(constr->GetName());
2169 std::vector<std::string> names;
2170 names.reserve(pois->size());
2172 names.push_back(arg->
GetName());
2173 std::sort(names.begin(), names.end());
2174 for (
auto const &
name : names) {
2179 auto writeProductDomain = [&](
const char *suffix,
RooArgSet const *args) {
2180 if (!args || args->
empty())
2182 const std::string domainName = analysisName + suffix;
2183 analysis.
domains.push_back({domainName});
2184 std::map<std::string, HS3::DomainAxis> axes;
2185 for (
auto *var : static_range_cast<const RooRealVar *>(*args)) {
2188 appendDomain(doc.
domains, domainName, std::move(axes));
2203 doc.
analyses.push_back(std::move(analysis));
2213 _export = std::make_unique<HS3::ToolExportState>();
2216 struct ExportScope {
2218 ~ExportScope() { tool.
_export.reset(); }
2219 } exportScope{*
this};
2227 std::vector<RooAbsPdf *> allpdfs;
2230 if (
auto *pdf =
dynamic_cast<RooAbsPdf *
>(arg)) {
2231 allpdfs.push_back(pdf);
2235 sortByName(allpdfs);
2236 std::set<std::string> exportedObjectNames;
2240 std::vector<RooAbsReal *> allfuncs;
2243 if (
auto *func =
dynamic_cast<RooAbsReal *
>(arg)) {
2244 allfuncs.push_back(func);
2248 sortByName(allfuncs);
2257 std::vector<RooAbsData *> alldata;
2259 alldata.push_back(
d);
2261 sortByName(alldata);
2263 std::vector<RooAbsData *> singleData;
2264 std::vector<RooJSONFactoryWSTool::CombinedData> combData;
2265 for (
auto &
d : alldata) {
2267 if (!data.components.empty()) {
2268 combData.push_back(
data);
2270 singleData.push_back(
d);
2274 for (
auto &
d : alldata) {
2293 bool do_export =
false;
2294 for (
const auto &pdf : allpdfs) {
2301 snapshotSorted.
add(*arg);
2304 snapshotSorted.
sort();
2305 std::string
name(snsh->GetName());
2306 if (
name !=
"default_values") {
2312 for (
auto &item :
_export->domains) {
2314 [&](
HS3::Domain const &domain) { return domain.name == item.first; })) {
2315 appendDomain(doc.
domains, item.first, std::move(item.second));
2323 validateOptions.
isExternal = [](std::string
const &) {
return false; };
2326 for (
auto &diagnostic : diagnostics) {
2327 diagnostic.severity = HS3::Diagnostic::Severity::Warning;
2328 diagnostic.message =
"the exported document is not valid: " + diagnostic.message;
2342 std::stringstream ss(s);
2353 std::stringstream ss;
2365 std::unique_ptr<JSONTree> tree = JSONTree::create();
2368 auto &metadata =
n[
"metadata"].set_map();
2373 appendNamedChild(metadata[
"packages"],
"ROOT")[
"version"] << rootVersion();
2386 std::unique_ptr<JSONTree> tree = JSONTree::create();
2387 JSONNode &
n = tree->rootnode().set_map();
2401 std::ofstream out(
filename.c_str());
2411 auto const &attributes =
_import->document.rooFit.attributes;
2412 auto found = attributes.find(obj);
2413 if (found == attributes.end())
2415 auto const &tags = found->second.tags;
2416 return std::find(tags.begin(), tags.end(), attrib) != tags.end();
2420 _export->doc.rooFit.attributes[obj].tags.push_back(attrib);
2427 auto const &attributes =
_import->document.rooFit.attributes;
2428 auto found = attributes.find(obj);
2429 if (found == attributes.end())
2431 auto value = found->second.dict.find(attrib);
2432 return value != found->second.dict.end() ?
value->second :
"";
2435 const std::string &
value)
2437 _export->doc.rooFit.attributes[obj].dict[attrib] =
value;
2446 auto histFactoryImporters = importers.find(
"histfactory_dist");
2447 options.
typedHistFactory = histFactoryImporters != importers.end() && !histFactoryImporters->second.empty() &&
2453 std::optional<RooFit::ValidatedHS3Document> validated;
2458 validated =
HS3::validate(std::move(parsed), diagnostics, validateOptions);
2464 struct ImportScope {
2471 } importScope{*
this};
2475 _import = std::make_unique<HS3::ToolImportState>(doc);
2480 for (
auto const &
p :
_import->defaultValues->parameters) {
2484 for (
auto const &function : doc.
functions) {
2498 for (
auto const &var : point.parameters) {
2499 std::string
const *label = var.value ? std::get_if<std::string>(&*var.value) :
nullptr;
2502 cat->setLabel(label->c_str());
2503 }
else if (var.value) {
2504 cat->setIndex(
static_cast<int>(std::get<double>(*var.value)));
2510 warning(
"RooFitHS3: ignoring the string value of parameter '" + var.name +
"' in parameter point '" +
2511 point.name +
"', because there is no category with that name.");
2519 rrv = &wsEmplace<RooRealVar>(var.name, 1.);
2520 configureVariable(
_import->ranges, var, *rrv);
2523 configureVariable(
_import->ranges, var, *rrv);
2535 importAttributes(arg, item.second);
2542 std::vector<std::unique_ptr<RooAbsData>> datasets;
2543 datasets.reserve(doc.
data.size());
2544 for (
auto const &
data : doc.
data) {
2550 for (
auto const &analysis : doc.
analyses) {
2551 importAnalysis(doc, analysis,
_workspace, datasets);
2554 combineDatasets(doc, datasets);
2556 for (
auto const &
d : datasets) {
2559 for (
auto const &obs : *
d->get()) {
2560 if (
auto *rrv =
dynamic_cast<RooRealVar *
>(obs)) {
2561 _workspace.
var(rrv->GetName())->setBinning(rrv->getBinning());
2582 std::unique_ptr<JSONTree> tree = JSONTree::create(is);
2596 std::ifstream infile(
filename.c_str());
2597 if (!infile.is_open())
2609 if (
n.find(
"poi")) {
2612 std::string poi =
n.find(
"poi")->val();
2613 std::string pdname =
n.find(
"pdfName")->val();
2615 modelConfig.SetPdf(pdname.c_str());
2624 bool isVariable =
true;
2625 bool isData =
false;
2627 if (
n.find(
"type")) {
2629 std::string elementType =
n.find(
"type")->val();
2630 if (elementType ==
"binned" || elementType ==
"unbinned") {
2638 }
else if (isData) {
2655 if (!
value && !(min && max)) {
2656 throw std::invalid_argument(
"Invalid Syntax: Please provide either 'value' or 'min' and 'max' or both");
2659 axis.
name = elementNode[
"name"].
val();
2663 axis.
min = min->val_double();
2664 axis.
max = max->val_double();
2672 _import = std::make_unique<HS3::ToolImportState>(doc);
2673 struct ImportScope {
2675 ~ImportScope() { tool.
_import.reset(); }
2676 } importScope{*
this};
2680 configureVariable(
_import->ranges, parameter, *rrv);
2704 throw std::runtime_error(s);
2717 for (
char c : str) {
2722 case '(':
result +=
'_';
break;
2727 case '.':
result +=
"_dot_";
break;
2728 case '@':
result +=
"at";
break;
2729 case '-':
result +=
"minus";
break;
2730 case '/':
result +=
"_div_";
break;
2745 if (onlyModelConfig) {
2754 for (
auto *pdf : ws.
allPdfs()) {
2755 if (isTopLevel(*pdf, ws)) {
2761 if (isTopLevel(*func, ws)) {
2780 auto *snshSet =
dynamic_cast<RooArgSet *
>(snsh);
2782 tmpWS.
saveSnapshot(snshSet->GetName(), *snshSet,
true);
2802 auto sanitizeIfNeeded = [](
auto const &list) {
2803 for (
auto *obj : list) {
2809 sanitizeIfNeeded(tmpWS.
allVars());
2811 sanitizeIfNeeded(tmpWS.
allPdfs());
2819 for (
auto *obj : *
data->get()) {
2826 for (
auto *obj : *
data->get()) {
2832 auto *snsh =
dynamic_cast<RooArgSet *
>(snshObj);
2834 std::cerr <<
"Warning: found snapshot that is not a RooArgSet, skipping\n";
2844 for (
auto *arg : *snsh) {
2854 if (
auto *named =
dynamic_cast<TNamed *
>(obj)) {
2855 named->SetName(
sanitizeName(named->GetName()).c_str());
2857 std::cerr <<
"Warning: object " << obj->GetName() <<
" is not TNamed, cannot rename.\n";
2868 for (
auto *obs : mc->GetObservables()->get()) {
2873 for (
auto *poi : mc->GetParametersOfInterest()->get()) {
2878 for (
auto *nuis : mc->GetNuisanceParameters()->get()) {
2883 for (
auto *glob : mc->GetGlobalObservables()->get()) {
2890 std::string wsName = std::string{ws.
GetName()} +
"_sanitized";
2892 newWS.
SetName(wsName.c_str());
bool isHS3VersionBefore(std::string const &version, int major, int minor)
bool startsWith(std::string_view str, std::string_view prefix)
bool endsWith(std::string_view str, std::string_view suffix)
void writeAxisBinning(JSONNode &node, const RooAbsBinning &binning)
double toDouble(const char *s)
static unsigned int total
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 input
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 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
Option_t Option_t TPoint TPoint const char text
Common abstract base class for objects that represent a value and a "shape" in RooFit.
bool dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr, bool valueOnly=false) const
Test whether we depend on (ie, are served by) any object in the specified collection.
TClass * IsA() const override
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
bool isConstant() const
Check if the "Constant" attribute is set.
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.
void SetName(const char *name) override
Set the name of the TNamed.
const RefCountList_t & servers() const
List of all servers of this object.
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.
Abstract base class for RooRealVar binning definitions.
Int_t numBins() const
Return number of bins.
virtual double binLow(Int_t bin) const =0
virtual bool isUniform() const
virtual double highBound() const =0
virtual double lowBound() const =0
virtual double binHigh(Int_t bin) const =0
A space to attach TBranches.
const std::map< std::string, value_type >::value_type & getOrdinal(unsigned int n) const
Return name and index of the nth defined state.
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 base class for objects that are lvalues, i.e.
virtual Int_t numBins(const char *rangeName=nullptr) const =0
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.
virtual double getMax(const char *name=nullptr) const
Get maximum of currently defined range.
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
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.
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
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...
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.
JSONNode & append_child()
size_t num_children() const
JSONNode const * find(std::string const &key) const
bool has_child(std::string const &) const
Records which components of a JSON map are read while it is alive, through any node of the tree.
static std::unique_ptr< JSONTree > create()
An HS3 document. It is move-only, because generic objects refer to the JSON tree that the document wa...
std::vector< HS3::Analysis > analyses
std::vector< HS3::Data > data
std::vector< HS3::Likelihood > likelihoods
std::vector< HS3::Function > functions
std::vector< HS3::ParameterPoint > parameterPoints
HS3::RooFitInternal rooFit
std::vector< HS3::Domain > domains
std::vector< HS3::Distribution > distributions
A position in the JSON tree.
Where RooFit takes the ranges of variables from: the "default_domain" if there is one,...
DomainAxis const * find(std::string const &name) const
The axis that defines the range of a variable, or null.
bool contains(std::string const &name) const
Whether any domain has the variable.
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.
static constexpr double infinity()
Return internal infinity representation.
static constexpr int isInfinite(double x)
Return true if x is infinite by RooNumber internal specification.
Variable that can be changed from the outside.
void removeMin(const char *name=nullptr)
Remove lower range limit for binning with given name. Empty name means default range.
void setError(double value)
void setMin(const char *name, double value, bool shared=true)
Set minimum of name range to given value.
void setRange(const char *name, double min, double max, bool shared=true)
Set a fit or plotting range.
void setBins(Int_t nBins, const char *name=nullptr, bool shared=true)
Create a uniform binning under name 'name' for this variable.
bool hasError(bool allowZero=true) const
void setBinning(const RooAbsBinning &binning, const char *name=nullptr, bool shared=true)
Add given binning under name 'name' with this variable.
void setMax(const char *name, double value, bool shared=true)
Set maximum of name range to given value.
void removeMax(const char *name=nullptr)
Remove upper range limit for binning with given name. Empty name means default range.
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 std::string & GetSnapshotName() const
get the name of the workspace snapshot saved by SetSnapshot() (empty if there is none)
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)
RooAbsPdf * GetPriorPdf() const
get parameters prior pdf (return nullptr if not existing)
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.
RooCategory * cat(RooStringView name) const
Retrieve discrete variable (RooCategory) 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.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
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)
CoordSystem::Scalar get(DisplacementVector2D< CoordSystem, Tag > const &p)
std::string makeValidVarName(std::string const &in)
Types that represent an HS3 document.
std::variant< std::string, double > NameOrNumber
A name, or a number for a constant.
void buildHistFactoryDist(RooJSONFactoryWSTool &tool, std::string const &name, HistFactoryDist const &dist, std::vector< DistributionRef > const *channelConstraints=nullptr)
Create the RooFit objects of a HistFactory distribution in the workspace of the tool.
void checkDocument(HS3Document const &doc, Diagnostics &diagnostics, ValidateOptions const &options={})
The checks of validate(), for a document that is still needed if it doesn't pass them.
std::variant< RegularBinning, EdgesBinning > Binning
constexpr char const * defaultDomainName
The domain in which RooFit writes the ranges of all variables. It is a convention of RooFit,...
std::optional< ValidatedHS3Document > validate(HS3Document doc, Diagnostics &diagnostics, ValidateOptions const &options)
Checks what can be checked without knowing how the objects are built: unique names,...
void setExportedObject(RooJSONFactoryWSTool &tool, HistFactoryDist dist, std::vector< DistributionRef > channelConstraints)
Called by the exporter of a HistFactory distribution, which is then written by the tool.
void writeDocument(Detail::JSONNode &root, HS3Document const &doc)
Writes everything but the distributions and functions, which are written one by one while they are ex...
RooArgSet createObservables(std::vector< BinnedAxis > const &axes)
Create the variables for the axes of binned data.
void importHistFactoryNode(RooJSONFactoryWSTool &tool, Detail::JSONNode const &node, std::vector< DistributionRef > const *channelConstraints)
What the built-in importer does with a HistFactory distribution, plus the constraint terms of the cha...
bool hasErrors(Diagnostics const &diagnostics)
Whether there is a diagnostic with error severity.
void writeHistFactoryDist(Detail::JSONNode &node, HistFactoryDist const &dist)
Writes a HistFactory distribution, without its name.
std::vector< Diagnostic > Diagnostics
void report(Diagnostics const &diagnostics)
Forward the warnings to the message service, and throw if there are errors.
NameOrNumber toNameOrNumber(RooAbsArg const &arg)
The name of an object, or the value of a literal constant.
void upgradeDocument(Detail::JSONNode &root, Diagnostics &diagnostics, ParseOptions const &options={})
Rewrites everything that older versions of RooFit wrote in a way that is not part of the standard int...
BinnedAxis toBinnedAxis(RooRealVar const &var)
The axis of binned data for a variable.
std::unique_ptr< RooDataHist > createDataHist(std::string const &name, RooArgSet const &vars, std::vector< double > const &contents, std::vector< double > const *errors)
Create a RooDataHist with the contents and errors. If there are no errors, it doesn't store squared w...
bool isBuiltinHistFactoryImporter(JSONIO::Importer const &importer)
Whether this is the importer that RooFit registers for HistFactory distributions, as opposed to the o...
std::vector< BinnedAxis > parseBinnedAxes(Detail::JSONNode const &axes, Diagnostics &diagnostics)
Reads the axes of binned data that doesn't come with a document.
HS3Document parseDocument(Detail::JSONNode const &root, Diagnostics &diagnostics, ParseOptions const &options={})
Reads a document.
ImportExpressionMap & importExpressions()
ExportKeysMap & exportKeys()
void initialize(typename Architecture_t::Matrix_t &A, EInitialization m)
std::optional< DistributionRef > prior
std::optional< ParameterPointRef > init
std::vector< DomainRef > domains
std::vector< ParameterRef > parametersOfInterest
std::vector< std::string > tags
std::map< std::string, std::string > dict
std::vector< int > indices
std::vector< std::string > labels
std::vector< std::string > labels
std::vector< DistributionRef > distributions
std::vector< int > indices
The axis of point data or unbinned data, which can't have a binning.
std::optional< double > max
std::optional< double > min
std::variant< PointData, UnbinnedData, BinnedData > body
std::variant< GenericObject, HistFactoryDist > body
std::optional< double > min
std::optional< double > max
std::optional< Binning > binning
std::optional< double > fixedValue
std::vector< std::variant< DomainAxis, CategoricalAxis > > axes
std::vector< double > edges
A distribution or function that is not interpreted by the document, but by the importers that are reg...
std::vector< DistributionRef > auxDistributions
std::vector< LikelihoodTerm > terms
std::optional< std::string > pdfName
std::optional< std::string > mcName
std::optional< std::string > combinedDataName
std::vector< ParameterValue > parameters
std::optional< std::variant< double, std::string > > value
A string selects the state of a category.
Options for upgradeDocument() and parseDocument().
bool typedHistFactory
If false, HistFactory distributions stay generic objects, because a user registered their own importe...
A name that says what it refers to, so that for example a DataRef can't be used as a DomainRef.
std::map< std::string, Attributes > attributes
std::map< std::string, std::vector< DistributionRef > > channelConstraints
The constraint terms of HistFactory distributions that no modifier names, by distribution.
std::vector< StepWidth > stepWidths
std::map< std::string, ModelConfigInfo > modelConfigs
bool strict
Whether the document has to follow the current standard, or if older conventions of RooFit are tolera...
std::function< bool(std::string const &) isExternal)
Whether a name that is not defined in the document is known in some other way, e.g....