Skip to content

Commit abc5385

Browse files
committed
[RF][HS3] Sort variables exported by RooGenericPdf and FooFormulaVar
This makes the generated JSON more reproducible.
1 parent 1681382 commit abc5385

File tree

3 files changed

+28
-30
lines changed

3 files changed

+28
-30
lines changed

roofit/hs3/src/JSONFactories_RooFitCore.cxx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
#include <RooBinWidthFunction.h>
1818
#include <RooCategory.h>
1919
#include <RooDataHist.h>
20-
#include <RooLegacyExpPoly.h>
2120
#include <RooExponential.h>
2221
#include <RooFit/Detail/JSONInterface.h>
2322
#include <RooFitHS3/JSONIO.h>
2423
#include <RooFormulaVar.h>
2524
#include <RooGenericPdf.h>
2625
#include <RooHistFunc.h>
2726
#include <RooHistPdf.h>
27+
#include <RooLegacyExpPoly.h>
2828
#include <RooLognormal.h>
2929
#include <RooMultiVarGaussian.h>
3030
#include <RooPoisson.h>
@@ -35,11 +35,11 @@
3535
#include <RooTFnBinding.h>
3636
#include <RooWorkspace.h>
3737

38-
#include "JSONIOUtils.h"
39-
4038
#include <TF1.h>
4139
#include <TH1.h>
4240

41+
#include "JSONIOUtils.h"
42+
4343
#include "static_execute.h"
4444

4545
#include <algorithm>
@@ -519,14 +519,15 @@ class RooFormulaArgStreamer : public RooFit::JSONIO::Exporter {
519519
const RooArg_t *pdf = static_cast<const RooArg_t *>(func);
520520
elem["type"] << key();
521521
TString expression(pdf->expression());
522+
std::vector<std::pair<RooAbsArg *, std::size_t>> paramsWithIndex;
523+
paramsWithIndex.reserve(pdf->nParameters());
522524
for (size_t i = 0; i < pdf->nParameters(); ++i) {
523-
RooAbsArg *par = pdf->getParameter(i);
524-
std::stringstream ss_1;
525-
ss_1 << "x[" << i << "]";
526-
std::stringstream ss_2;
527-
ss_2 << "@" << i << "";
528-
expression.ReplaceAll(ss_1.str().c_str(), par->GetName());
529-
expression.ReplaceAll(ss_2.str().c_str(), par->GetName());
525+
paramsWithIndex.emplace_back(pdf->getParameter(i), i);
526+
}
527+
std::sort(paramsWithIndex.begin(), paramsWithIndex.end());
528+
for (auto [par, idx] : paramsWithIndex) {
529+
expression.ReplaceAll(("x[" + std::to_string(idx) + "]").c_str(), par->GetName());
530+
expression.ReplaceAll(("@" + std::to_string(idx)).c_str(), par->GetName());
530531
}
531532
elem["expression"] << expression.Data();
532533
return true;

roofit/hs3/src/RooJSONFactoryWSTool.cxx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ using RooFit::Detail::JSONTree;
100100

101101
namespace {
102102

103+
std::vector<std::string> valsToStringVec(JSONNode const &node)
104+
{
105+
std::vector<std::string> out;
106+
out.reserve(node.num_children());
107+
for (JSONNode const &elem : node.children()) {
108+
out.push_back(elem.val());
109+
}
110+
return out;
111+
}
112+
103113
/**
104114
* @brief Check if the number of components in CombinedData matches the number of categories in the RooSimultaneous PDF.
105115
*
@@ -587,16 +597,13 @@ void importAnalysis(const JSONNode &rootnode, const JSONNode &analysisNode, cons
587597
auto *mc = static_cast<RooStats::ModelConfig *>(workspace.obj(mcname));
588598
mc->SetWS(workspace);
589599

590-
std::vector<std::string> nllDistNames;
591600
std::vector<std::string> nllDataNames;
592601

593602
auto *nllNode = RooJSONFactoryWSTool::findNamedChild(likelihoodsNode, analysisNode["likelihood"].val());
594603
if (!nllNode) {
595604
throw std::runtime_error("likelihood node not found!");
596605
}
597-
for (auto &nameNode : (*nllNode)["distributions"].children()) {
598-
nllDistNames.push_back(nameNode.val());
599-
}
606+
std::vector<std::string> nllDistNames = valsToStringVec((*nllNode)["distributions"]);
600607
RooArgSet extConstraints;
601608
for (auto &nameNode : (*nllNode)["aux_distributions"].children()) {
602609
RooAbsArg *extConstraint = workspace.arg(nameNode.val());
@@ -699,18 +706,12 @@ void combinePdfs(const JSONNode &rootnode, RooWorkspace &ws)
699706
// parse the information
700707
std::string combinedName = info.key();
701708
std::string indexCatName = info["index_cat"].val();
702-
std::vector<std::string> labels;
709+
std::vector<std::string> labels = valsToStringVec(info["labels"]);
703710
std::vector<int> indices;
704-
std::vector<std::string> pdfNames;
711+
std::vector<std::string> pdfNames = valsToStringVec(info["distributions"]);
705712
for (auto &n : info["indices"].children()) {
706713
indices.push_back(n.val_int());
707714
}
708-
for (auto &n : info["labels"].children()) {
709-
labels.push_back(n.val());
710-
}
711-
for (auto &n : info["distributions"].children()) {
712-
pdfNames.push_back(n.val());
713-
}
714715

715716
RooCategory indexCat{indexCatName.c_str(), indexCatName.c_str()};
716717
std::map<std::string, RooAbsPdf *> pdfMap;
@@ -739,14 +740,11 @@ void combineDatasets(const JSONNode &rootnode, std::vector<std::unique_ptr<RooAb
739740
// parse the information
740741
std::string combinedName = info.key();
741742
std::string indexCatName = info["index_cat"].val();
742-
std::vector<std::string> labels;
743+
std::vector<std::string> labels = valsToStringVec(info["labels"]);
743744
std::vector<int> indices;
744745
for (auto &n : info["indices"].children()) {
745746
indices.push_back(n.val_int());
746747
}
747-
for (auto &n : info["labels"].children()) {
748-
labels.push_back(n.val());
749-
}
750748
if (indices.size() != labels.size()) {
751749
RooJSONFactoryWSTool::error("mismatch in number of indices and labels!");
752750
}

roofit/jsoninterface/inc/RooFit/Detail/JSONInterface.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ class JSONNode {
3737
virtual bool equal(const Impl &other) const = 0;
3838
};
3939

40-
private:
41-
std::unique_ptr<Impl> it;
42-
43-
public:
4440
child_iterator_t(std::unique_ptr<Impl> impl) : it(std::move(impl)) {}
4541
child_iterator_t(const child_iterator_t &other) : it(std::move(other.it->clone())) {}
4642

@@ -65,6 +61,9 @@ class JSONNode {
6561
{
6662
return lhs.it->equal(*rhs.it);
6763
}
64+
65+
private:
66+
std::unique_ptr<Impl> it;
6867
};
6968

7069
using child_iterator = child_iterator_t<JSONNode>;

0 commit comments

Comments
 (0)