Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
JSONFactories_HistFactory.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Carsten D. Burgard, DESY/ATLAS, Dec 2021
5 *
6 * Copyright (c) 2022, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
14#include <RooFitHS3/JSONIO.h>
16
21#include <RooConstVar.h>
22#include <RooRealVar.h>
23#include <RooDataHist.h>
24#include <RooHistFunc.h>
25#include <RooRealSumPdf.h>
26#include <RooBinWidthFunction.h>
27#include <RooProdPdf.h>
28#include <RooPoisson.h>
29#include <RooLognormal.h>
30#include <RooGaussian.h>
31#include <RooProduct.h>
32#include <RooWorkspace.h>
33
34#include "static_execute.h"
35#include "JSONIOUtils.h"
36
38
39using namespace RooStats::HistFactory;
40using namespace RooStats::HistFactory::Detail;
42
43namespace {
44
45inline void writeAxis(JSONNode &axis, RooRealVar const &obs)
46{
47 auto &binning = obs.getBinning();
48 if (binning.isUniform()) {
49 axis["nbins"] << obs.numBins();
50 axis["min"] << obs.getMin();
51 axis["max"] << obs.getMax();
52 } else {
53 auto &edges = axis["edges"];
54 edges.set_seq();
55 double val = binning.binLow(0);
56 edges.append_child() << val;
57 for (int i = 0; i < binning.numBins(); ++i) {
58 val = binning.binHigh(i);
59 edges.append_child() << val;
60 }
61 }
62}
63
64double round_prec(double d, int nSig)
65{
66 if (d == 0.0)
67 return 0.0;
68 int ndigits = std::floor(std::log10(std::abs(d))) + 1 - nSig;
69 double sf = std::pow(10, ndigits);
70 if (std::abs(d / sf) < 2)
71 ndigits--;
72 return sf * std::round(d / sf);
73}
74
75// To avoid repeating the same string literals that can potentially get out of
76// sync.
77namespace Literals {
78constexpr auto staterror = "staterror";
79}
80
81void erasePrefix(std::string &str, std::string_view prefix)
82{
83 if (startsWith(str, prefix)) {
84 str.erase(0, prefix.size());
85 }
86}
87
88void eraseSuffix(std::string &str, std::string_view suffix)
89{
90 if (endsWith(str, suffix)) {
91 str.erase(str.size() - suffix.size());
92 }
93}
94
95template <class Coll>
96void sortByName(Coll &coll)
97{
98 std::sort(coll.begin(), coll.end(), [](auto &l, auto &r) { return l.name < r.name; });
99}
100
101template <class T>
102T *findClient(RooAbsArg *gamma)
103{
104 for (const auto &client : gamma->clients()) {
105 if (auto casted = dynamic_cast<T *>(client)) {
106 return casted;
107 } else {
108 T *c = findClient<T>(client);
109 if (c)
110 return c;
111 }
112 }
113 return nullptr;
114}
115
116RooAbsPdf *findConstraint(RooAbsArg *g)
117{
118 RooPoisson *constraint_p = findClient<RooPoisson>(g);
119 if (constraint_p)
120 return constraint_p;
121 RooGaussian *constraint_g = findClient<RooGaussian>(g);
122 if (constraint_g)
123 return constraint_g;
124 RooLognormal *constraint_l = findClient<RooLognormal>(g);
125 if (constraint_l)
126 return constraint_l;
127 return nullptr;
128}
129
130std::string toString(TClass *c)
131{
132 if (!c) {
133 return "Const";
134 }
135 if (c == RooPoisson::Class()) {
136 return "Poisson";
137 }
138 if (c == RooGaussian::Class()) {
139 return "Gauss";
140 }
141 if (c == RooLognormal::Class()) {
142 return "Lognormal";
143 }
144 return "unknown";
145}
146
147inline std::string defaultGammaName(std::string const &sysname, std::size_t i)
148{
149 return "gamma_" + sysname + "_bin_" + std::to_string(i);
150}
151
152/// Export the names of the gamma parameters to the modifier struct if the
153/// names don't match the default gamma parameter names, which is gamma_<sysname>_bin_<i>
154void optionallyExportGammaParameters(JSONNode &mod, std::string const &sysname,
155 std::vector<std::string> const &paramNames)
156{
157 for (std::size_t i = 0; i < paramNames.size(); ++i) {
158 if (paramNames[i] != defaultGammaName(sysname, i)) {
159 mod["parameters"].fill_seq(paramNames);
160 return;
161 }
162 }
163}
164
165RooRealVar &createNominal(RooWorkspace &ws, std::string const &parname, double val, double min, double max)
166{
167 RooRealVar &nom = getOrCreate<RooRealVar>(ws, "nom_" + parname, val, min, max);
168 nom.setConstant(true);
169 return nom;
170}
171
172/// Get the conventional name of the constraint pdf for a constrained
173/// parameter.
174std::string constraintName(std::string const &paramName)
175{
176 return paramName + "Constraint";
177}
178
179RooAbsPdf &getConstraint(RooWorkspace &ws, const std::string &pname)
180{
181 RooRealVar *constrParam = ws.var(pname);
182 constrParam->setError(1.0);
183 return getOrCreate<RooGaussian>(ws, constraintName(pname), *constrParam, *ws.var("nom_" + pname), 1.);
184}
185
186ParamHistFunc &createPHF(const std::string &phfname, std::string const &sysname,
187 const std::vector<std::string> &parnames, const std::vector<double> &vals,
188 RooJSONFactoryWSTool &tool, RooArgList &constraints, const RooArgSet &observables,
189 const std::string &constraintType, double gammaMin, double gammaMax, double minSigma)
190{
191 RooWorkspace &ws = *tool.workspace();
192
193 RooArgList gammas;
194 for (std::size_t i = 0; i < vals.size(); ++i) {
195 const std::string name = parnames.empty() ? defaultGammaName(sysname, i) : parnames[i];
196 gammas.add(getOrCreate<RooRealVar>(ws, name, 1., gammaMin, gammaMax));
197 }
198
199 auto &phf = tool.wsEmplace<ParamHistFunc>(phfname, observables, gammas);
200
201 if (constraintType != "Const") {
202 auto constraintsInfo = createGammaConstraints(
203 gammas, vals, minSigma, constraintType == "Poisson" ? Constraint::Poisson : Constraint::Gaussian);
204 for (auto const &term : constraintsInfo.constraints) {
206 constraints.add(*ws.pdf(term->GetName()));
207 }
208 } else {
209 for (auto *gamma : static_range_cast<RooRealVar *>(gammas)) {
210 gamma->setConstant(true);
211 }
212 }
213
214 return phf;
215}
216
217bool hasStaterror(const JSONNode &comp)
218{
219 if (!comp.has_child("modifiers"))
220 return false;
221 for (const auto &mod : comp["modifiers"].children()) {
222 if (mod["type"].val() == ::Literals::staterror)
223 return true;
224 }
225 return false;
226}
227
228const JSONNode &findStaterror(const JSONNode &comp)
229{
230 if (comp.has_child("modifiers")) {
231 for (const auto &mod : comp["modifiers"].children()) {
232 if (mod["type"].val() == ::Literals::staterror)
233 return mod;
234 }
235 }
236 RooJSONFactoryWSTool::error("sample '" + RooJSONFactoryWSTool::name(comp) + "' does not have a " +
237 ::Literals::staterror + " modifier!");
238}
239
240bool importHistSample(RooJSONFactoryWSTool &tool, RooDataHist &dh, RooArgSet const &varlist,
241 RooAbsArg const *mcStatObject, const std::string &fprefix, const JSONNode &p,
242 RooArgList &constraints)
243{
244 RooWorkspace &ws = *tool.workspace();
245
246 std::string sampleName = RooJSONFactoryWSTool::name(p);
247 std::string prefixedName = fprefix + "_" + sampleName;
248
249 std::string channelName = fprefix;
250 erasePrefix(channelName, "model_");
251
252 if (!p.has_child("data")) {
253 RooJSONFactoryWSTool::error("sample '" + sampleName + "' does not define a 'data' key");
254 }
255
256 auto &hf = tool.wsEmplace<RooHistFunc>("hist_" + prefixedName, varlist, dh);
258
259 RooArgList shapeElems;
260 RooArgList normElems;
261
262 shapeElems.add(tool.wsEmplace<RooBinWidthFunction>(prefixedName + "_binWidth", hf, true));
263
264 if (hasStaterror(p)) {
265 shapeElems.add(*mcStatObject);
266 }
267
268 if (p.has_child("modifiers")) {
269 RooArgList overall_nps;
270 std::vector<double> overall_low;
271 std::vector<double> overall_high;
272
273 RooArgList histNps;
274 RooArgList histoLo;
275 RooArgList histoHi;
276
277 int idx = 0;
278 for (const auto &mod : p["modifiers"].children()) {
279 std::string const &modtype = mod["type"].val();
280 std::string const &sysname =
281 mod.has_child("name")
282 ? mod["name"].val()
283 : (mod.has_child("parameter") ? mod["parameter"].val() : "syst_" + std::to_string(idx));
284 ++idx;
285 if (modtype == "staterror") {
286 // this is dealt with at a different place, ignore it for now
287 } else if (modtype == "normfactor") {
288 RooRealVar &constrParam = getOrCreate<RooRealVar>(ws, sysname, 1., -3, 5);
289 normElems.add(constrParam);
290 if (auto constrInfo = mod.find("constraint_name")) {
291 auto constraint = tool.request<RooAbsReal>(constrInfo->val(), sampleName);
292 if (auto gauss = dynamic_cast<RooGaussian const *>(constraint)) {
293 constrParam.setError(gauss->getSigma().getVal());
294 }
295 constraints.add(*constraint);
296 }
297 } else if (modtype == "normsys") {
298 auto *parameter = mod.find("parameter");
299 std::string parname(parameter ? parameter->val() : "alpha_" + sysname);
300 createNominal(ws, parname, 0.0, -10, 10);
301 overall_nps.add(getOrCreate<RooRealVar>(ws, parname, 0., -5, 5));
302 auto &data = mod["data"];
303 // the below contains a a hack to cut off variations that go below 0
304 // this is needed because with interpolation code 4, which is the default, interpolation is done in
305 // log-space. hence, values <= 0 result in NaN which propagate throughout the model and cause evaluations to
306 // fail if you know a nicer way to solve this, please go ahead and fix the lines below
307 overall_low.push_back(data["lo"].val_double() > 0 ? data["lo"].val_double()
308 : std::numeric_limits<double>::epsilon());
309 overall_high.push_back(data["hi"].val_double() > 0 ? data["hi"].val_double()
310 : std::numeric_limits<double>::epsilon());
311 constraints.add(getConstraint(ws, parname));
312 } else if (modtype == "histosys") {
313 auto *parameter = mod.find("parameter");
314 std::string parname(parameter ? parameter->val() : "alpha_" + sysname);
315 createNominal(ws, parname, 0.0, -10, 10);
316 histNps.add(getOrCreate<RooRealVar>(ws, parname, 0., -5, 5));
317 auto &data = mod["data"];
318 histoLo.add(tool.wsEmplace<RooHistFunc>(
319 sysname + "Low_" + prefixedName, varlist,
320 RooJSONFactoryWSTool::readBinnedData(data["lo"], sysname + "Low_" + prefixedName, varlist)));
321 histoHi.add(tool.wsEmplace<RooHistFunc>(
322 sysname + "High_" + prefixedName, varlist,
323 RooJSONFactoryWSTool::readBinnedData(data["hi"], sysname + "High_" + prefixedName, varlist)));
324 constraints.add(getConstraint(ws, parname));
325 } else if (modtype == "shapesys") {
326 std::string funcName = channelName + "_" + sysname + "_ShapeSys";
327 // funcName should be "<channel_name>_<sysname>_ShapeSys"
328 std::vector<double> vals;
329 for (const auto &v : mod["data"]["vals"].children()) {
330 vals.push_back(v.val_double());
331 }
332 std::vector<std::string> parnames;
333 for (const auto &v : mod["parameters"].children()) {
334 parnames.push_back(v.val());
335 }
336 if (vals.empty()) {
337 RooJSONFactoryWSTool::error("unable to instantiate shapesys '" + sysname + "' with 0 values!");
338 }
339 std::string constraint(mod["constraint"].val());
340 shapeElems.add(createPHF(funcName, sysname, parnames, vals, tool, constraints, varlist, constraint,
342 } else if (modtype == "custom") {
343 RooAbsReal *obj = ws.function(sysname);
344 if (!obj) {
345 RooJSONFactoryWSTool::error("unable to find custom modifier '" + sysname + "'");
346 }
347 if (obj->dependsOn(varlist)) {
348 shapeElems.add(*obj);
349 } else {
350 normElems.add(*obj);
351 }
352 } else {
353 RooJSONFactoryWSTool::error("modifier '" + sysname + "' of unknown type '" + modtype + "'");
354 }
355 }
356
357 std::string interpName = sampleName + "_" + channelName + "_epsilon";
358 if (!overall_nps.empty()) {
359 auto &v = tool.wsEmplace<RooStats::HistFactory::FlexibleInterpVar>(interpName, overall_nps, 1., overall_low,
360 overall_high);
361 v.setAllInterpCodes(4); // default HistFactory interpCode
362 normElems.add(v);
363 }
364 if (!histNps.empty()) {
365 auto &v = tool.wsEmplace<PiecewiseInterpolation>("histoSys_" + prefixedName, hf, histoLo, histoHi, histNps);
367 v.setAllInterpCodes(4); // default interpCode for HistFactory
368 shapeElems.add(v);
369 } else {
370 shapeElems.add(hf);
371 }
372 }
373
374 tool.wsEmplace<RooProduct>(prefixedName + "_shapes", shapeElems);
375 if (!normElems.empty()) {
376 tool.wsEmplace<RooProduct>(prefixedName + "_scaleFactors", normElems);
377 } else {
378 ws.factory("RooConstVar::" + prefixedName + "_scaleFactors(1.)");
379 }
380
381 return true;
382}
383
384class HistFactoryImporter : public RooFit::JSONIO::Importer {
385public:
386 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
387 {
388 std::string name = RooJSONFactoryWSTool::name(p);
389 if (!p.has_child("samples")) {
390 RooJSONFactoryWSTool::error("no samples in '" + name + "', skipping.");
391 }
392 double statErrThresh = 0;
393 std::string statErrType = "Poisson";
394 if (p.has_child(::Literals::staterror)) {
395 auto &staterr = p[::Literals::staterror];
396 if (staterr.has_child("relThreshold"))
397 statErrThresh = staterr["relThreshold"].val_double();
398 if (staterr.has_child("constraint"))
399 statErrType = staterr["constraint"].val();
400 }
401 std::vector<double> sumW;
402 std::vector<double> sumW2;
403 std::vector<std::string> gammaParnames;
405
406 std::string fprefix = name;
407
408 std::vector<std::unique_ptr<RooDataHist>> data;
409 for (const auto &comp : p["samples"].children()) {
410 std::unique_ptr<RooDataHist> dh = RooJSONFactoryWSTool::readBinnedData(
411 comp["data"], fprefix + "_" + RooJSONFactoryWSTool::name(comp) + "_dataHist", observables);
412 size_t nbins = dh->numEntries();
413
414 if (hasStaterror(comp)) {
415 if (sumW.empty()) {
416 sumW.resize(nbins);
417 sumW2.resize(nbins);
418 }
419 for (size_t i = 0; i < nbins; ++i) {
420 sumW[i] += dh->weight(i);
421 sumW2[i] += dh->weightSquared(i);
422 }
423 if (gammaParnames.empty()) {
424 if (auto staterrorParams = findStaterror(comp).find("parameters")) {
425 for (const auto &v : staterrorParams->children()) {
426 gammaParnames.push_back(v.val());
427 }
428 }
429 }
430 }
431 data.emplace_back(std::move(dh));
432 }
433
434 RooAbsArg *mcStatObject = nullptr;
435 RooArgList constraints;
436 if (!sumW.empty()) {
437 std::string channelName = name;
438 erasePrefix(channelName, "model_");
439
440 std::vector<double> errs(sumW.size());
441 for (size_t i = 0; i < sumW.size(); ++i) {
442 errs[i] = std::sqrt(sumW2[i]) / sumW[i];
443 // avoid negative sigma. This NP will be set constant anyway later
444 errs[i] = std::max(errs[i], 0.);
445 }
446
447 mcStatObject =
448 &createPHF("mc_stat_" + channelName, "stat_" + channelName, gammaParnames, errs, *tool, constraints,
449 observables, statErrType, defaultGammaMin, defaultStatErrorGammaMax, statErrThresh);
450 }
451
452 int idx = 0;
454 RooArgList coefs;
455 for (const auto &comp : p["samples"].children()) {
456 importHistSample(*tool, *data[idx], observables, mcStatObject, fprefix, comp, constraints);
457 ++idx;
458
459 std::string const &compName = RooJSONFactoryWSTool::name(comp);
460 funcs.add(*tool->request<RooAbsReal>(fprefix + "_" + compName + "_shapes", name));
461 coefs.add(*tool->request<RooAbsReal>(fprefix + "_" + compName + "_scaleFactors", name));
462 }
463
464 if (constraints.empty()) {
465 tool->wsEmplace<RooRealSumPdf>(name, funcs, coefs, true);
466 } else {
467 std::string sumName = name + "_model";
468 erasePrefix(sumName, "model_");
469 auto &sum = tool->wsEmplace<RooRealSumPdf>(sumName, funcs, coefs, true);
470 sum.SetTitle(name.c_str());
471 tool->wsEmplace<RooProdPdf>(name, constraints, RooFit::Conditional(sum, observables));
472 }
473 return true;
474 }
475};
476
477class FlexibleInterpVarStreamer : public RooFit::JSONIO::Exporter {
478public:
479 std::string const &key() const override
480 {
481 static const std::string keystring = "interpolation0d";
482 return keystring;
483 }
484 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
485 {
486 auto fip = static_cast<const RooStats::HistFactory::FlexibleInterpVar *>(func);
487 elem["type"] << key();
488 elem["interpolationCodes"].fill_seq(fip->interpolationCodes());
489 RooJSONFactoryWSTool::fillSeq(elem["vars"], fip->variables());
490 elem["nom"] << fip->nominal();
491 elem["high"].fill_seq(fip->high(), fip->variables().size());
492 elem["low"].fill_seq(fip->low(), fip->variables().size());
493 return true;
494 }
495};
496
497class PiecewiseInterpolationStreamer : public RooFit::JSONIO::Exporter {
498public:
499 std::string const &key() const override
500 {
501 static const std::string keystring = "interpolation";
502 return keystring;
503 }
504 bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *func, JSONNode &elem) const override
505 {
506 const PiecewiseInterpolation *pip = static_cast<const PiecewiseInterpolation *>(func);
507 elem["type"] << key();
508 elem["interpolationCodes"].fill_seq(pip->interpolationCodes());
509 elem["positiveDefinite"] << pip->positiveDefinite();
510 RooJSONFactoryWSTool::fillSeq(elem["vars"], pip->paramList());
511 elem["nom"] << pip->nominalHist()->GetName();
512 RooJSONFactoryWSTool::fillSeq(elem["high"], pip->highList(), pip->paramList().size());
513 RooJSONFactoryWSTool::fillSeq(elem["low"], pip->lowList(), pip->paramList().size());
514 return true;
515 }
516};
517
518class PiecewiseInterpolationFactory : public RooFit::JSONIO::Importer {
519public:
520 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
521 {
522 std::string name(RooJSONFactoryWSTool::name(p));
523
524 RooArgList vars{tool->requestArgList<RooRealVar>(p, "vars")};
525
526 auto &pip = tool->wsEmplace<PiecewiseInterpolation>(name, *tool->requestArg<RooAbsReal>(p, "nom"),
527 tool->requestArgList<RooAbsReal>(p, "low"),
528 tool->requestArgList<RooAbsReal>(p, "high"), vars);
529
530 pip.setPositiveDefinite(p["positiveDefinite"].val_bool());
531
532 if (p.has_child("interpolationCodes")) {
533 std::size_t i = 0;
534 for (auto const &node : p["interpolationCodes"].children()) {
535 pip.setInterpCode(*static_cast<RooAbsReal *>(vars.at(i)), node.val_int(), true);
536 ++i;
537 }
538 }
539
540 return true;
541 }
542};
543
544class FlexibleInterpVarFactory : public RooFit::JSONIO::Importer {
545public:
546 bool importArg(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
547 {
548 std::string name(RooJSONFactoryWSTool::name(p));
549 if (!p.has_child("high")) {
550 RooJSONFactoryWSTool::error("no high variations of '" + name + "'");
551 }
552 if (!p.has_child("low")) {
553 RooJSONFactoryWSTool::error("no low variations of '" + name + "'");
554 }
555 if (!p.has_child("nom")) {
556 RooJSONFactoryWSTool::error("no nominal variation of '" + name + "'");
557 }
558
559 double nom(p["nom"].val_double());
560
561 RooArgList vars{tool->requestArgList<RooRealVar>(p, "vars")};
562
563 std::vector<double> high;
564 high << p["high"];
565
566 std::vector<double> low;
567 low << p["low"];
568
569 if (vars.size() != low.size() || vars.size() != high.size()) {
570 RooJSONFactoryWSTool::error("FlexibleInterpVar '" + name +
571 "' has non-matching lengths of 'vars', 'high' and 'low'!");
572 }
573
574 auto &fip = tool->wsEmplace<RooStats::HistFactory::FlexibleInterpVar>(name, vars, nom, low, high);
575
576 if (p.has_child("interpolationCodes")) {
577 size_t i = 0;
578 for (auto const &node : p["interpolationCodes"].children()) {
579 fip.setInterpCode(*static_cast<RooAbsReal *>(vars.at(i)), node.val_int());
580 ++i;
581 }
582 }
583
584 return true;
585 }
586};
587
588void collectElements(RooArgSet &elems, RooAbsArg *arg)
589{
590 if (auto prod = dynamic_cast<RooProduct *>(arg)) {
591 for (const auto &e : prod->components()) {
592 collectElements(elems, e);
593 }
594 } else {
595 elems.add(*arg);
596 }
597}
598
599struct NormFactor {
600 std::string name;
601 RooAbsArg const *param = nullptr;
602 RooAbsPdf const *constraint = nullptr;
603 NormFactor(RooAbsArg const &par, RooAbsPdf const *constr = nullptr)
604 : name{par.GetName()}, param{&par}, constraint{constr}
605 {
606 }
607};
608
609struct NormSys {
610 std::string name;
611 RooAbsArg const *param = nullptr;
612 double low;
613 double high;
614 TClass *constraint = RooGaussian::Class();
615 NormSys(const std::string &n, RooAbsArg *const p, double h, double l, TClass *c)
616 : name(n), param(p), low(l), high(h), constraint(c)
617 {
618 }
619};
620struct HistoSys {
621 std::string name;
622 RooAbsArg const *param = nullptr;
623 std::vector<double> low;
624 std::vector<double> high;
625 TClass *constraint = RooGaussian::Class();
626 HistoSys(const std::string &n, RooAbsArg *const p, RooHistFunc *l, RooHistFunc *h, TClass *c)
627 : name(n), param(p), constraint(c)
628 {
629 low.assign(l->dataHist().weightArray(), l->dataHist().weightArray() + l->dataHist().numEntries());
630 high.assign(h->dataHist().weightArray(), h->dataHist().weightArray() + h->dataHist().numEntries());
631 }
632};
633struct ShapeSys {
634 std::string name;
635 std::vector<double> constraints;
636 std::vector<std::string> parameters;
637 TClass *constraint = nullptr;
638 ShapeSys(const std::string &n) : name{n} {}
639};
640struct Sample {
641 std::string name;
642 std::vector<double> hist;
643 std::vector<double> histError;
644 std::vector<NormFactor> normfactors;
645 std::vector<NormSys> normsys;
646 std::vector<HistoSys> histosys;
647 std::vector<ShapeSys> shapesys;
648 std::vector<RooAbsReal *> otherElements;
649 bool useBarlowBeestonLight = false;
650 std::vector<std::string> staterrorParameters;
651 TClass *barlowBeestonLightConstraint = RooPoisson::Class();
652 Sample(const std::string &n) : name{n} {}
653};
654
655void addNormFactor(RooRealVar const *par, Sample &sample, RooWorkspace *ws)
656{
657 std::string parname = par->GetName();
658 bool isConstrained = false;
659 for (RooAbsArg const *pdf : ws->allPdfs()) {
660 if (auto gauss = dynamic_cast<RooGaussian const *>(pdf)) {
661 if (parname == gauss->getX().GetName()) {
662 sample.normfactors.emplace_back(*par, gauss);
663 isConstrained = true;
664 }
665 }
666 }
667 if (!isConstrained)
668 sample.normfactors.emplace_back(*par);
669}
670
671namespace {
672
673bool verbose = false;
674
675}
676
677bool tryExportHistFactory(RooJSONFactoryWSTool *tool, const std::string &pdfname, const RooRealSumPdf *sumpdf,
678 JSONNode &elem)
679{
680 RooWorkspace *ws = tool->workspace();
681 RooArgSet customModifiers;
682
683 if (!sumpdf) {
684 if (verbose) {
685 std::cout << pdfname << " is not a sumpdf" << std::endl;
686 }
687 return false;
688 }
689
690 std::string channelName = pdfname;
691 erasePrefix(channelName, "model_");
692 eraseSuffix(channelName, "_model");
693
694 for (RooAbsArg *sample : sumpdf->funcList()) {
695 if (!dynamic_cast<RooProduct *>(sample) && !dynamic_cast<RooRealSumPdf *>(sample)) {
696 if (verbose)
697 std::cout << "sample " << sample->GetName() << " is no RooProduct or RooRealSumPdf in " << pdfname
698 << std::endl;
699 return false;
700 }
701 }
702
703 std::map<int, double> tot_yield;
704 std::map<int, double> tot_yield2;
705 std::map<int, double> rel_errors;
706 RooArgSet const *varSet = nullptr;
707 long unsigned int nBins = 0;
708
709 std::vector<Sample> samples;
710
711 for (size_t sampleidx = 0; sampleidx < sumpdf->funcList().size(); ++sampleidx) {
712 PiecewiseInterpolation *pip = nullptr;
713 std::vector<RooStats::HistFactory::FlexibleInterpVar *> fips;
714 std::vector<ParamHistFunc *> phfs;
715
716 const auto func = sumpdf->funcList().at(sampleidx);
717 Sample sample(func->GetName());
718 erasePrefix(sample.name, "L_x_");
719 eraseSuffix(sample.name, "_shapes");
720 eraseSuffix(sample.name, "_" + channelName);
721 erasePrefix(sample.name, pdfname + "_");
722 RooArgSet elems;
723 collectElements(elems, func);
724 collectElements(elems, sumpdf->coefList().at(sampleidx));
725
726 auto updateObservables = [&](RooDataHist const &dataHist) {
727 if (varSet == nullptr) {
728 varSet = dataHist.get();
729 nBins = dataHist.numEntries();
730 }
731 if (sample.hist.empty()) {
732 auto *w = dataHist.weightArray();
733 sample.hist.assign(w, w + dataHist.numEntries());
734 }
735 };
736
737 for (RooAbsArg *e : elems) {
738 if (TString(e->GetName()).Contains("binWidth")) {
739 // The bin width modifiers are handled separately. We can't just
740 // check for the RooBinWidthFunction type here, because prior to
741 // ROOT 6.26, the multiplication with the inverse bin width was
742 // done in a different way (like a normfactor with a RooRealVar,
743 // but it was stored in the dataset).
744 // Fortunately, the name was similar, so we can match the modifier
745 // name.
746 } else if (auto constVar = dynamic_cast<RooConstVar *>(e)) {
747 if (constVar->getVal() != 1.) {
748 sample.normfactors.emplace_back(*e);
749 }
750 } else if (auto par = dynamic_cast<RooRealVar *>(e)) {
751 addNormFactor(par, sample, ws);
752 } else if (auto hf = dynamic_cast<const RooHistFunc *>(e)) {
753 updateObservables(hf->dataHist());
754 } else if (auto phf = dynamic_cast<ParamHistFunc *>(e)) {
755 phfs.push_back(phf);
756 } else if (auto fip = dynamic_cast<RooStats::HistFactory::FlexibleInterpVar *>(e)) {
757 // some (modified) histfactory models have several instances of FlexibleInterpVar
758 // we collect and merge them here
759 fips.push_back(fip);
760 } else if (!pip && (pip = dynamic_cast<PiecewiseInterpolation *>(e))) {
761 } else if (auto real = dynamic_cast<RooAbsReal *>(e)) {
762 sample.otherElements.push_back(real);
763 }
764 }
765
766 // see if we can get the observables
767 if (pip) {
768 if (auto nh = dynamic_cast<RooHistFunc const *>(pip->nominalHist())) {
769 updateObservables(nh->dataHist());
770 }
771 }
772
773 // sort and configure norms
774 sortByName(sample.normfactors);
775
776 // sort and configure the normsys
777 for (auto *fip : fips) {
778 for (size_t i = 0; i < fip->variables().size(); ++i) {
779 RooAbsArg *var = fip->variables().at(i);
780 std::string sysname(var->GetName());
781 erasePrefix(sysname, "alpha_");
782 const auto *constraint = findConstraint(var);
783 if (!constraint)
784 RooJSONFactoryWSTool::error("cannot find constraint for " + std::string(var->GetName()));
785 sample.normsys.emplace_back(sysname, var, fip->high()[i], fip->low()[i],
786 constraint ? constraint->IsA() : nullptr);
787 }
788 }
789 sortByName(sample.normsys);
790
791 // sort and configure the histosys
792 if (pip) {
793 for (size_t i = 0; i < pip->paramList().size(); ++i) {
794 RooAbsArg *var = pip->paramList().at(i);
795 std::string sysname(var->GetName());
796 erasePrefix(sysname, "alpha_");
797 if (auto lo = dynamic_cast<RooHistFunc *>(pip->lowList().at(i))) {
798 if (auto hi = dynamic_cast<RooHistFunc *>(pip->highList().at(i))) {
799 const auto *constraint = findConstraint(var);
800 if (!constraint)
801 RooJSONFactoryWSTool::error("cannot find constraint for " + std::string(var->GetName()));
802 sample.histosys.emplace_back(sysname, var, lo, hi, constraint ? constraint->IsA() : nullptr);
803 }
804 }
805 }
806 sortByName(sample.histosys);
807 }
808
809 for (ParamHistFunc *phf : phfs) {
810 if (startsWith(std::string(phf->GetName()), "mc_stat_")) { // MC stat uncertainty
811 int idx = 0;
812 for (const auto &g : phf->paramList()) {
813 sample.staterrorParameters.push_back(g->GetName());
814 ++idx;
815 RooAbsPdf *constraint = findConstraint(g);
816 if (tot_yield.find(idx) == tot_yield.end()) {
817 tot_yield[idx] = 0;
818 tot_yield2[idx] = 0;
819 }
820 tot_yield[idx] += sample.hist[idx - 1];
821 tot_yield2[idx] += (sample.hist[idx - 1] * sample.hist[idx - 1]);
822 if (constraint) {
823 sample.barlowBeestonLightConstraint = constraint->IsA();
824 if (RooPoisson *constraint_p = dynamic_cast<RooPoisson *>(constraint)) {
825 double erel = 1. / std::sqrt(constraint_p->getX().getVal());
826 rel_errors[idx] = erel;
827 } else if (RooGaussian *constraint_g = dynamic_cast<RooGaussian *>(constraint)) {
828 double erel = constraint_g->getSigma().getVal() / constraint_g->getMean().getVal();
829 rel_errors[idx] = erel;
830 } else {
832 "currently, only RooPoisson and RooGaussian are supported as constraint types");
833 }
834 }
835 }
836 sample.useBarlowBeestonLight = true;
837 } else { // other ShapeSys
838 ShapeSys sys(phf->GetName());
839 erasePrefix(sys.name, channelName + "_");
840 eraseSuffix(sys.name, "_ShapeSys");
841
842 for (const auto &g : phf->paramList()) {
843 sys.parameters.push_back(g->GetName());
844 RooAbsPdf *constraint = findConstraint(g);
845 if (!constraint)
846 constraint = ws->pdf(constraintName(g->GetName()));
847 if (!constraint && !g->isConstant()) {
848 RooJSONFactoryWSTool::error("cannot find constraint for " + std::string(g->GetName()));
849 } else if (!constraint) {
850 sys.constraints.push_back(0.0);
851 } else if (auto constraint_p = dynamic_cast<RooPoisson *>(constraint)) {
852 sys.constraints.push_back(1. / std::sqrt(constraint_p->getX().getVal()));
853 if (!sys.constraint) {
854 sys.constraint = RooPoisson::Class();
855 }
856 } else if (auto constraint_g = dynamic_cast<RooGaussian *>(constraint)) {
857 sys.constraints.push_back(constraint_g->getSigma().getVal() / constraint_g->getMean().getVal());
858 if (!sys.constraint) {
859 sys.constraint = RooGaussian::Class();
860 }
861 }
862 }
863 sample.shapesys.emplace_back(std::move(sys));
864 }
865 }
866 sortByName(sample.shapesys);
867
868 // add the sample
869 samples.emplace_back(std::move(sample));
870 }
871
872 sortByName(samples);
873
874 for (auto &sample : samples) {
875 if (sample.hist.empty()) {
876 return false;
877 }
878 if (sample.useBarlowBeestonLight) {
879 sample.histError.resize(sample.hist.size());
880 for (auto bin : rel_errors) {
881 // reverse engineering the correct partial error
882 // the (arbitrary) convention used here is that all samples should have the same relative error
883 const int i = bin.first;
884 const double relerr_tot = bin.second;
885 const double count = sample.hist[i - 1];
886 // this reconstruction is inherently imprecise, so we truncate it at some decimal places to make sure that
887 // we don't carry around too many useless digits
888 sample.histError[i - 1] = round_prec(relerr_tot * tot_yield[i] / std::sqrt(tot_yield2[i]) * count, 7);
889 }
890 }
891 }
892
893 bool observablesWritten = false;
894 for (const auto &sample : samples) {
895
896 elem["type"] << "histfactory_dist";
897
898 auto &s = RooJSONFactoryWSTool::appendNamedChild(elem["samples"], sample.name);
899
900 auto &modifiers = s["modifiers"];
901 modifiers.set_seq();
902
903 for (const auto &nf : sample.normfactors) {
904 auto &mod = modifiers.append_child();
905 mod.set_map();
906 mod["name"] << nf.name;
907 mod["parameter"] << nf.param->GetName();
908 mod["type"] << "normfactor";
909 if (nf.constraint) {
910 mod["constraint_name"] << nf.constraint->GetName();
911 tool->queueExport(*nf.constraint);
912 }
913 }
914
915 for (const auto &sys : sample.normsys) {
916 auto &mod = modifiers.append_child();
917 mod.set_map();
918 mod["name"] << sys.name;
919 mod["type"] << "normsys";
920 mod["parameter"] << sys.param->GetName();
921 mod["constraint"] << toString(sys.constraint);
922 auto &data = mod["data"].set_map();
923 data["lo"] << sys.low;
924 data["hi"] << sys.high;
925 }
926
927 for (const auto &sys : sample.histosys) {
928 auto &mod = modifiers.append_child();
929 mod.set_map();
930 mod["name"] << sys.name;
931 mod["type"] << "histosys";
932 mod["parameter"] << sys.param->GetName();
933 mod["constraint"] << toString(sys.constraint);
934 auto &data = mod["data"].set_map();
935 if (nBins != sys.low.size() || nBins != sys.high.size()) {
936 std::stringstream ss;
937 ss << "inconsistent binning: " << nBins << " bins expected, but " << sys.low.size() << "/"
938 << sys.high.size() << " found in nominal histogram errors!";
939 RooJSONFactoryWSTool::error(ss.str().c_str());
940 }
941 RooJSONFactoryWSTool::exportArray(nBins, sys.low.data(), data["lo"].set_map()["contents"]);
942 RooJSONFactoryWSTool::exportArray(nBins, sys.high.data(), data["hi"].set_map()["contents"]);
943 }
944
945 for (const auto &sys : sample.shapesys) {
946 auto &mod = modifiers.append_child();
947 mod.set_map();
948 mod["name"] << sys.name;
949 mod["type"] << "shapesys";
950 optionallyExportGammaParameters(mod, sys.name, sys.parameters);
951 mod["constraint"] << toString(sys.constraint);
952 if (sys.constraint) {
953 auto &vals = mod["data"].set_map()["vals"];
954 vals.fill_seq(sys.constraints);
955 } else {
956 auto &vals = mod["data"].set_map()["vals"];
957 vals.set_seq();
958 for (std::size_t i = 0; i < sys.parameters.size(); ++i) {
959 vals.append_child() << 0;
960 }
961 }
962 }
963
964 for (const auto &other : sample.otherElements) {
965 auto &mod = modifiers.append_child();
966 mod.set_map();
967 mod["name"] << other->GetName();
968 customModifiers.add(*other);
969 mod["type"] << "custom";
970 }
971
972 if (sample.useBarlowBeestonLight) {
973 auto &mod = modifiers.append_child();
974 mod.set_map();
975 mod["name"] << ::Literals::staterror;
976 mod["type"] << ::Literals::staterror;
977 optionallyExportGammaParameters(mod, "stat_" + channelName, sample.staterrorParameters);
978 mod["constraint"] << toString(sample.barlowBeestonLightConstraint);
979 }
980
981 if (!observablesWritten) {
982 auto &output = elem["axes"].set_seq();
983 for (auto *obs : static_range_cast<RooRealVar *>(*varSet)) {
984 auto &out = output.append_child().set_map();
985 out["name"] << obs->GetName();
986 writeAxis(out, *obs);
987 }
988 observablesWritten = true;
989 }
990 auto &dataNode = s["data"].set_map();
991 if (nBins != sample.hist.size()) {
992 std::stringstream ss;
993 ss << "inconsistent binning: " << nBins << " bins expected, but " << sample.hist.size()
994 << " found in nominal histogram!";
995 RooJSONFactoryWSTool::error(ss.str().c_str());
996 }
997 RooJSONFactoryWSTool::exportArray(nBins, sample.hist.data(), dataNode["contents"]);
998 if (!sample.histError.empty()) {
999 if (nBins != sample.histError.size()) {
1000 std::stringstream ss;
1001 ss << "inconsistent binning: " << nBins << " bins expected, but " << sample.histError.size()
1002 << " found in nominal histogram errors!";
1003 RooJSONFactoryWSTool::error(ss.str().c_str());
1004 }
1005 RooJSONFactoryWSTool::exportArray(nBins, sample.histError.data(), dataNode["errors"]);
1006 }
1007 }
1008
1009 // Export all the custom modifiers
1010 for (RooAbsArg *modifier : customModifiers) {
1011 tool->queueExport(*modifier);
1012 }
1013
1014 // Export all model parameters
1015 RooArgSet parameters;
1016 sumpdf->getParameters(varSet, parameters);
1017 for (RooAbsArg *param : parameters) {
1018 // This should exclude the global observables
1019 if (!startsWith(std::string{param->GetName()}, "nom_")) {
1020 tool->queueExport(*param);
1021 }
1022 }
1023
1024 return true;
1025}
1026
1027class HistFactoryStreamer_ProdPdf : public RooFit::JSONIO::Exporter {
1028public:
1029 bool autoExportDependants() const override { return false; }
1030 bool tryExport(RooJSONFactoryWSTool *tool, const RooProdPdf *prodpdf, JSONNode &elem) const
1031 {
1032 RooRealSumPdf *sumpdf = nullptr;
1033 for (RooAbsArg *v : prodpdf->pdfList()) {
1034 auto thispdf = dynamic_cast<RooRealSumPdf *>(v);
1035 if (thispdf) {
1036 if (!sumpdf)
1037 sumpdf = thispdf;
1038 else
1039 return false;
1040 }
1041 }
1042 if (!sumpdf)
1043 return false;
1044
1045 return tryExportHistFactory(tool, prodpdf->GetName(), sumpdf, elem);
1046 }
1047 std::string const &key() const override
1048 {
1049 static const std::string keystring = "histfactory_dist";
1050 return keystring;
1051 }
1052 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *p, JSONNode &elem) const override
1053 {
1054 return tryExport(tool, static_cast<const RooProdPdf *>(p), elem);
1055 }
1056};
1057
1058class HistFactoryStreamer_SumPdf : public RooFit::JSONIO::Exporter {
1059public:
1060 bool autoExportDependants() const override { return false; }
1061 bool tryExport(RooJSONFactoryWSTool *tool, const RooRealSumPdf *sumpdf, JSONNode &elem) const
1062 {
1063 return tryExportHistFactory(tool, sumpdf->GetName(), sumpdf, elem);
1064 }
1065 std::string const &key() const override
1066 {
1067 static const std::string keystring = "histfactory_dist";
1068 return keystring;
1069 }
1070 bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *p, JSONNode &elem) const override
1071 {
1072 return tryExport(tool, static_cast<const RooRealSumPdf *>(p), elem);
1073 }
1074};
1075
1076STATIC_EXECUTE([]() {
1077 using namespace RooFit::JSONIO;
1078
1079 registerImporter<HistFactoryImporter>("histfactory_dist", true);
1080 registerImporter<PiecewiseInterpolationFactory>("interpolation", true);
1081 registerImporter<FlexibleInterpVarFactory>("interpolation0d", true);
1082 registerExporter<FlexibleInterpVarStreamer>(RooStats::HistFactory::FlexibleInterpVar::Class(), true);
1083 registerExporter<PiecewiseInterpolationStreamer>(PiecewiseInterpolation::Class(), true);
1084 registerExporter<HistFactoryStreamer_ProdPdf>(RooProdPdf::Class(), true);
1085 registerExporter<HistFactoryStreamer_SumPdf>(RooRealSumPdf::Class(), true);
1086});
1087
1088} // namespace
bool startsWith(std::string_view str, std::string_view prefix)
bool endsWith(std::string_view str, std::string_view suffix)
#define d(i)
Definition RSha256.hxx:102
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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 r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void funcs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t modifier
char name[80]
Definition TGX11.cxx:110
#define hi
A class which maps the current values of a RooRealVar (or a set of RooRealVars) to one of a number of...
The PiecewiseInterpolation is a class that can morph distributions into each other,...
const RooArgList & highList() const
const RooAbsReal * nominalHist() const
Return pointer to the nominal hist function.
static TClass * Class()
const RooArgList & lowList() const
void setInterpCode(RooAbsReal &param, int code, bool silent=true)
void setPositiveDefinite(bool flag=true)
const RooArgList & paramList() const
const std::vector< int > & interpolationCodes() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
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.
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...
Storage_t const & get() const
Const access to the underlying stl container.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
TClass * IsA() const override
Definition RooAbsPdf.h:351
Int_t numBins(const char *rangeName=nullptr) const override
void setConstant(bool value=true)
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...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Returns the bin width (or volume) given a RooHistFunc.
Represents a constant real-valued object.
Definition RooConstVar.h:23
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
virtual std::string val() const =0
void fill_seq(Collection const &coll)
virtual JSONNode & set_map()=0
virtual JSONNode & append_child()=0
virtual JSONNode & set_seq()=0
virtual bool has_child(std::string const &) const =0
JSONNode const * find(std::string const &key) const
virtual bool autoExportDependants() const
Definition JSONIO.h:58
virtual std::string const & key() const =0
virtual bool exportObject(RooJSONFactoryWSTool *, const RooAbsArg *, RooFit::Detail::JSONNode &) const
Definition JSONIO.h:59
virtual bool importArg(RooJSONFactoryWSTool *tool, const RooFit::Detail::JSONNode &node) const
Definition JSONIO.h:37
Plain Gaussian p.d.f.
Definition RooGaussian.h:24
static TClass * Class()
RooAbsReal const & getMean() const
Get the mean parameter.
Definition RooGaussian.h:48
RooAbsReal const & getSigma() const
Get the sigma parameter.
Definition RooGaussian.h:51
A real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:31
When using RooFit, statistical models can be conveniently handled and stored as a RooWorkspace.
static void fillSeq(RooFit::Detail::JSONNode &node, RooAbsCollection const &coll, size_t nMax=-1)
T * requestArg(const RooFit::Detail::JSONNode &node, const std::string &key)
T * request(const std::string &objname, const std::string &requestAuthor)
static std::unique_ptr< RooDataHist > readBinnedData(const RooFit::Detail::JSONNode &n, const std::string &namecomp, RooArgSet const &vars)
Read binned data from the JSONNode and create a RooDataHist object.
static RooFit::Detail::JSONNode & appendNamedChild(RooFit::Detail::JSONNode &node, std::string const &name)
static void exportArray(std::size_t n, double const *contents, RooFit::Detail::JSONNode &output)
Export an array of doubles to a JSONNode.
void queueExport(RooAbsArg const &arg)
RooArgList requestArgList(const RooFit::Detail::JSONNode &node, const std::string &seqName)
static void error(const char *s)
Writes an error message to the RooFit message service and throws a runtime_error.
Obj_t & wsEmplace(RooStringView name, Args_t &&...args)
static std::string name(const RooFit::Detail::JSONNode &n)
static RooArgSet readAxes(const RooFit::Detail::JSONNode &node)
Read axes from the JSONNode and create a RooArgSet representing them.
RooFit Lognormal PDF.
static TClass * Class()
Poisson pdf.
Definition RooPoisson.h:19
RooAbsReal const & getX() const
Get the x variable.
Definition RooPoisson.h:45
static TClass * Class()
Efficient implementation of a product of PDFs of the form.
Definition RooProdPdf.h:39
static TClass * Class()
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
Implements a PDF constructed from a sum of functions:
const RooArgList & funcList() const
static TClass * Class()
const RooArgList & coefList() const
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setError(double value)
Definition RooRealVar.h:60
const RooAbsBinning & getBinning(const char *name=nullptr, bool verbose=true, bool createOnTheFly=false) const override
Return binning definition with name.
void setInterpCode(RooAbsReal &param, int code)
Configuration for a constrained, coherent shape variation of affected samples.
Configuration for an un- constrained overall systematic to scale sample normalisations.
Definition Systematics.h:62
std::string GetName() const
get name of sample
Definition Sample.h:82
Constrained bin-by-bin variation of affected histogram.
Persistable container for RooFit projects.
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
RooAbsReal * function(RooStringView name) const
Retrieve function (RooAbsReal) with given name. Note that all RooAbsPdfs are also RooAbsReals....
RooFactoryWSTool & factory()
Return instance to factory tool.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
bool 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.
Definition TClass.h:81
TClass * IsA() const override
Definition TClass.h:618
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Basic string class.
Definition TString.h:139
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
RooCmdArg RecycleConflictNodes(bool flag=true)
RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, bool depsAreCond=false)
const Int_t n
Definition legend1.C:16
double gamma(double x)
double T(double x)
CreateGammaConstraintsOutput createGammaConstraints(RooArgList const &paramList, std::span< const double > relSigmas, double minSigma, Constraint::Type type)
#define STATIC_EXECUTE(MY_FUNC)
TLine l
Definition textangle.C:4
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345
static void output()