40JSONNode &appendNamedChild(JSONNode &node, std::string
const &
name)
42 static constexpr bool useListsInsteadOfDicts =
true;
44 if (!useListsInsteadOfDicts) {
47 JSONNode &
child = node.set_seq().append_child().set_map();
54 void readVariable(
const char *
name,
double min,
double max);
61 void readVariable(
const char *
name,
double min,
double max);
66 struct ProductDomainElement {
71 std::map<std::string, ProductDomainElement> _map;
74 std::map<std::string, ProductDomain> _map;
77void Domains::readVariable(
const char *
name,
double min,
double max)
79 _map[
"default_domain"].readVariable(
name, min, max);
84 for (
auto const &domain : _map) {
85 domain.second.writeJSON(appendNamedChild(node, domain.first));
88void Domains::ProductDomain::readVariable(
const char *
name,
double min,
double max)
90 auto &elem = _map[
name];
98 node[
"type"] <<
"product_domain";
100 auto &variablesNode = node[
"axes"];
102 for (
auto const &item : _map) {
103 auto const &elem = item.second;
105 varnode[
"min"] << elem.min;
106 varnode[
"max"] << elem.max;
110bool checkRegularBins(
const TAxis &ax)
114 for (
int i = 0; i <= ax.
GetNbins(); ++i) {
121inline void writeAxis(JSONNode &axis,
const TAxis &ax)
130 auto &edges = axis[
"edges"];
132 for (
int i = 0; i <= ax.
GetNbins(); ++i) {
140 std::vector<std::string> obsnames{
"obs_x_" +
c.GetName(),
"obs_y_" +
c.GetName(),
"obs_z_" +
c.GetName()};
141 obsnames.resize(
c.GetData().GetHisto()->GetDimension());
145void writeObservables(
const TH1 &
h, JSONNode &node,
const std::vector<std::string> &varnames)
148 auto &observables = node[
"axes"].set_seq();
149 auto &
x = observables.append_child().set_map();
150 x[
"name"] << varnames[0];
151 writeAxis(
x, *
h.GetXaxis());
152 if (
h.GetDimension() > 1) {
153 auto &
y = observables.append_child().set_map();
154 y[
"name"] << varnames[1];
155 writeAxis(
y, *(
h.GetYaxis()));
156 if (
h.GetDimension() > 2) {
157 auto &z = observables.append_child().set_map();
158 z[
"name"] << varnames[2];
159 writeAxis(z, *(
h.GetZaxis()));
164void exportSimpleHistogram(
const TH1 &histo, JSONNode &node)
168 for (
int i = 1; i <= nBins; ++i) {
170 node.append_child() << val;
174void exportHistogram(
const TH1 &histo, JSONNode &node,
const std::vector<std::string> &varnames,
175 const TH1 *errH =
nullptr,
bool doWriteObservables =
true,
bool writeErrors =
true)
178 auto &weights = node[
"contents"].set_seq();
179 JSONNode *errors =
nullptr;
181 errors = &node[
"errors"].set_seq();
183 if (doWriteObservables) {
184 writeObservables(histo, node, varnames);
187 for (
int i = 1; i <= nBins; ++i) {
189 weights.append_child() << val;
191 const double err = errH ? val * errH->GetBinContent(i) : histo.
GetBinError(i);
192 errors->append_child() << err;
198 std::vector<std::string>
const &obsnames)
200 auto &s = appendNamedChild(channelNode[
"samples"], sample.
GetName());
203 auto &modifiers = s[
"modifiers"].set_seq();
204 for (
const auto &sys : sample.GetOverallSysList()) {
205 auto &node = modifiers.append_child().set_map();
206 node[
"name"] << sys.GetName();
207 node[
"type"] <<
"normsys";
208 auto &
data = node[
"data"];
210 data[
"lo"] << sys.GetLow();
211 data[
"hi"] << sys.GetHigh();
216 auto &modifiers = s[
"modifiers"].set_seq();
217 for (
const auto &nf : sample.GetNormFactorList()) {
218 auto &mod = modifiers.append_child().set_map();
219 mod[
"name"] << nf.GetName();
220 mod[
"type"] <<
"normfactor";
222 auto &mod = modifiers.append_child().set_map();
223 mod[
"name"] <<
"Lumi";
224 mod[
"type"] <<
"normfactor";
225 mod[
"constraint_name"] <<
"lumiConstraint";
229 auto &modifiers = s[
"modifiers"].set_seq();
232 auto &node = modifiers.append_child().set_map();
233 node[
"name"] << sys.GetName();
234 node[
"type"] <<
"histosys";
235 auto &
data = node[
"data"].set_map();
236 exportSimpleHistogram(*sys.GetHistoLow(),
data[
"lo"].set_map()[
"contents"]);
237 exportSimpleHistogram(*sys.GetHistoHigh(),
data[
"hi"].set_map()[
"contents"]);
242 auto &modifiers = s[
"modifiers"].set_seq();
245 auto &node = modifiers.append_child().set_map();
246 node[
"name"] << sys.GetName();
247 node[
"type"] <<
"shapesys";
249 node[
"constraint"] <<
"Gauss";
251 node[
"constraint"] <<
"Poisson";
252 auto &
data = node[
"data"].set_map();
253 exportSimpleHistogram(*sys.GetErrorHist(),
data[
"vals"]);
257 auto &tags = s[
"dict"].set_map();
261 RooStats::HistFactory::JSONTool::activateStatError(s);
264 auto &
data = s[
"data"];
268 if (!channelNode.has_child(
"axes")) {
269 writeObservables(*sample.
GetHisto(), channelNode, obsnames);
271 exportHistogram(*sample.
GetHisto(),
data, obsnames, errH,
false);
276 ch[
"type"] <<
"histfactory_dist";
278 auto &staterr = ch[
"statError"].set_map();
279 staterr[
"relThreshold"] <<
c.GetStatErrorConfig().GetRelErrorThreshold();
282 const std::vector<std::string> obsnames = getObsnames(
c);
284 for (
const auto &s :
c.GetSamples()) {
285 exportSample(s, ch, obsnames);
289void setAttribute(JSONNode &rootnode,
const std::string &obj,
const std::string &attrib)
291 auto node = &rootnode.get(
"misc",
"ROOT_internal",
"attributes").set_map()[obj].set_map();
292 auto &tags = (*node)[
"tags"];
294 tags.append_child() << attrib;
301 for (
const auto &ch : measurement.GetChannels()) {
302 if (!ch.CheckHistograms())
303 throw std::runtime_error(
"unable to export histograms, please call CollectHistograms first");
308 auto &funclist = rootnode[
"functions"];
309 for (
const auto &func : measurement.GetFunctionObjects()) {
310 auto &
f = appendNamedChild(funclist, func.GetName());
311 f[
"name"] << func.GetName();
312 f[
"expression"] << func.GetExpression();
313 f[
"dependents"] << func.GetDependents();
314 f[
"command"] << func.GetCommand();
318 auto &pdflist = rootnode[
"distributions"];
320 auto &analysisNode = appendNamedChild(rootnode[
"analyses"],
"simPdf");
321 analysisNode[
"domains"].set_seq().append_child() <<
"default_domain";
323 auto &analysisPois = analysisNode[
"parameters_of_interest"].set_seq();
325 for (
const auto &poi : measurement.GetPOIList()) {
326 analysisPois.append_child() << poi;
329 analysisNode[
"likelihood"] << measurement.
GetName();
331 auto &likelihoodNode = appendNamedChild(rootnode[
"likelihoods"], measurement.
GetName());
332 likelihoodNode[
"distributions"].set_seq();
333 likelihoodNode[
"data"].set_seq();
336 for (
const auto &
c : measurement.GetChannels()) {
338 auto pdfName = std::string(
"model_") +
c.GetName();
339 auto realSumPdfName =
c.GetName() + std::string(
"_model");
341 likelihoodNode[
"distributions"].append_child() << pdfName;
342 likelihoodNode[
"data"].append_child() << std::string(
"obsData_") +
c.GetName();
343 exportChannel(
c, appendNamedChild(pdflist, pdfName));
344 setAttribute(rootnode, realSumPdfName,
"BinnedLikelihood");
347 struct VariableInfo {
349 double minVal = -5.0;
351 bool isConstant =
false;
352 bool writeDomain =
true;
354 std::unordered_map<std::string, VariableInfo>
variables;
356 for (
const auto &channel : measurement.GetChannels()) {
357 for (
const auto &sample : channel.GetSamples()) {
358 for (
const auto &norm : sample.GetNormFactorList()) {
360 info.val = norm.GetVal();
361 info.minVal = norm.GetLow();
362 info.maxVal = norm.GetHigh();
364 for (
const auto &sys : sample.GetOverallSysList()) {
365 variables[std::string(
"alpha_") + sys.GetName()] = VariableInfo{};
369 for (
const auto &sys : measurement.GetConstantParams()) {
371 info.isConstant =
true;
372 bool isGamma = sys.find(
"gamma_") != std::string::npos;
374 info.val = isGamma ? 1.0 : 0.0;
377 info.writeDomain = !isGamma;
382 double nominal = measurement.
GetLumi();
388 info1.maxVal = 10 * nominal;
389 info1.isConstant =
true;
394 info2.maxVal = nominal + 10 * error;
395 info2.isConstant =
true;
398 JSONNode &varlist = appendNamedChild(rootnode[
"parameter_points"],
"default_values")[
"parameters"];
400 std::string
const &parname = item.first;
401 VariableInfo
const &info = item.second;
403 auto &
v = appendNamedChild(varlist, parname);
404 v[
"value"] << info.val;
407 if (info.writeDomain) {
408 domains.readVariable(parname.c_str(), info.minVal, info.maxVal);
413 auto &child1 = rootnode.get(
"misc",
"ROOT_internal",
"combined_datasets").set_map()[
"obsData"].set_map();
414 auto &child2 = rootnode.get(
"misc",
"ROOT_internal",
"combined_distributions").set_map()[
"simPdf"].set_map();
416 child1[
"index_cat"] <<
"channelCat";
417 auto &labels1 = child1[
"labels"].set_seq();
418 auto &indices1 = child1[
"indices"].set_seq();
420 child2[
"index_cat"] <<
"channelCat";
421 auto &labels2 = child2[
"labels"].set_seq();
422 auto &indices2 = child2[
"indices"].set_seq();
423 auto &pdfs2 = child2[
"distributions"].set_seq();
425 std::vector<std::string> channelNames;
426 for (
const auto &
c : measurement.GetChannels()) {
427 labels1.append_child() <<
c.GetName();
428 indices1.append_child() <<
int(channelNames.size());
429 labels2.append_child() <<
c.GetName();
430 indices2.append_child() <<
int(channelNames.size());
431 pdfs2.append_child() << (std::string(
"model_") +
c.GetName());
433 JSONNode &dataOutput = appendNamedChild(rootnode[
"data"], std::string(
"obsData_") +
c.GetName());
434 dataOutput[
"type"] <<
"binned";
436 exportHistogram(*
c.GetData().GetHisto(), dataOutput, getObsnames(
c));
437 channelNames.push_back(
c.GetName());
440 auto &modelConfigAux = rootnode.get(
"misc",
"ROOT_internal",
"ModelConfigs",
"simPdf").set_map();
441 modelConfigAux[
"combined_data_name"] <<
"obsData";
442 modelConfigAux[
"pdfName"] <<
"simPdf";
443 modelConfigAux[
"mcName"] <<
"ModelConfig";
446 auto &lumiConstraint = appendNamedChild(pdflist,
"lumiConstraint");
447 lumiConstraint[
"mean"] <<
"nominalLumi";
449 lumiConstraint[
"type"] <<
"gaussian_dist";
450 lumiConstraint[
"x"] <<
"Lumi";
453std::unique_ptr<RooFit::Detail::JSONTree> createNewJSONTree()
456 JSONNode &
n =
tree->rootnode();
458 auto &metadata =
n[
"metadata"].set_map();
461 metadata[
"hs3_version"] <<
"0.1.90";
464 auto &rootInfo = appendNamedChild(metadata[
"packages"],
"ROOT");
465 std::string versionName =
gROOT->GetVersion();
468 std::replace(versionName.begin(), versionName.end(),
'/',
'.');
469 rootInfo[
"version"] << versionName;
476void RooStats::HistFactory::JSONTool::PrintJSON(std::ostream &os)
478 std::unique_ptr<RooFit::Detail::JSONTree>
tree = createNewJSONTree();
479 auto &rootnode =
tree->rootnode();
481 exportMeasurement(_measurement, rootnode, domains);
482 domains.writeJSON(rootnode[
"domains"]);
483 rootnode.writeJSON(os);
485void RooStats::HistFactory::JSONTool::PrintJSON(std::string
const &
filename)
488 this->PrintJSON(out);
491void RooStats::HistFactory::JSONTool::PrintYAML(std::ostream &os)
493 std::unique_ptr<RooFit::Detail::JSONTree>
tree = createNewJSONTree();
494 auto &rootnode =
tree->rootnode().set_map();
496 exportMeasurement(_measurement, rootnode, domains);
497 domains.writeJSON(rootnode[
"domains"]);
498 rootnode.writeYML(os);
501void RooStats::HistFactory::JSONTool::PrintYAML(std::string
const &
filename)
504 this->PrintYAML(out);
507void RooStats::HistFactory::JSONTool::activateStatError(JSONNode &sampleNode)
509 auto &node = sampleNode[
"modifiers"].set_seq().append_child().set_map();
510 node[
"name"] <<
"mcstat";
511 node[
"type"] <<
"staterror";
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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 Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
virtual JSONNode & set_map()=0
static std::unique_ptr< JSONTree > create()
This class encapsulates all information for the statistical interpretation of one experiment.
The RooStats::HistFactory::Measurement class can be used to construct a model by combining multiple R...
double GetLumiRelErr()
retrieve relative uncertainty on luminosity
std::vector< RooStats::HistFactory::PreprocessFunction > & GetFunctionObjects()
get vector of defined function objects
double GetLumi()
retrieve integrated luminosity
std::vector< RooStats::HistFactory::OverallSys > & GetOverallSysList()
std::string GetName() const
get name of sample
const TH1 * GetHisto() const
RooStats::HistFactory::StatError & GetStatError()
std::vector< RooStats::HistFactory::NormFactor > & GetNormFactorList()
std::vector< RooStats::HistFactory::HistoSys > & GetHistoSysList()
bool GetNormalizeByTheory() const
does the normalization scale with luminosity
std::vector< RooStats::HistFactory::ShapeSys > & GetShapeSysList()
const TH1 * GetErrorHist() const
Class to manage histogram axis.
Bool_t IsVariableBinSize() const
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
TH1 is the base class of all histogram classes in ROOT.
virtual Int_t GetNbinsY() const
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
virtual Int_t GetNbinsZ() const
virtual Int_t GetNbinsX() const
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
const char * GetName() const override
Returns name of object.
double min(double x, double y)
std::string Name(Type type)
__device__ AFloat max(AFloat x, AFloat y)
void variables(TString dataset, TString fin="TMVA.root", TString dirName="InputVariables_Id", TString title="TMVA Input Variables", Bool_t isRegression=kFALSE, Bool_t useTMVAStyle=kTRUE)