52 if (binning.isUniform()) {
54 axis[
"min"] << obs.
getMin();
55 axis[
"max"] << obs.
getMax();
57 auto &edges = axis[
"edges"];
59 double val = binning.binLow(0);
60 edges.append_child() << val;
61 for (
int i = 0; i < binning.numBins(); ++i) {
62 val = binning.binHigh(i);
63 edges.append_child() << val;
72 int ndigits = std::floor(std::log10(std::abs(
d))) + 1 -
nSig;
74 if (std::abs(
d /
sf) < 2)
76 return sf * std::round(
d /
sf);
85void erasePrefix(std::string &str, std::string_view prefix)
88 str.erase(0, prefix.size());
95 str.erase(str.size() -
suffix.size());
105 std::sort(
coll.
begin(),
coll.
end(), [](
auto &
l,
auto &
r) { return l.name < r.name; });
111 for (
const auto &client :
gamma->clients()) {
112 if (
auto casted =
dynamic_cast<T *
>(client)) {
158 return "gamma_" +
sysname +
"_bin_" + std::to_string(i);
168 for (std::size_t i = 0; i < params.size(); ++i) {
169 std::string
name(params[i]->GetName());
183 nom.setConstant(
true);
195 const std::vector<std::string> &
parnames,
const std::vector<double> &vals,
202 for (std::size_t i = 0; i < vals.size(); ++i) {
209 if (constraintType !=
"Const") {
218 gamma->setConstant(
true);
227 if (!
comp.has_child(
"modifiers"))
229 for (
const auto &
mod :
comp[
"modifiers"].children()) {
230 if (
mod[
"type"].val() == ::Literals::staterror)
238 if (
comp.has_child(
"modifiers")) {
239 for (
const auto &
mod :
comp[
"modifiers"].children()) {
240 if (
mod[
"type"].val() == ::Literals::staterror)
245 ::Literals::staterror +
" modifier!");
262 param.
setError(gauss->getSigma().getVal());
266 std::cout <<
"creating new constraint for " << param << std::endl;
274 *
tool.workspace()->var(std::string(
"nom_") + param.
GetName()), 1.);
293 if (!
p.has_child(
"data")) {
309 if (
p.has_child(
"modifiers")) {
320 for (
const auto &
mod :
p[
"modifiers"].children()) {
321 std::string
const &
modtype =
mod[
"type"].val();
323 mod.has_child(
"name")
325 : (
mod.has_child(
"parameter") ?
mod[
"parameter"].val() :
"syst_" + std::to_string(idx));
329 }
else if (
modtype ==
"normfactor") {
332 if (
mod.has_child(
"constraint_name") ||
mod.has_child(
"constraint_type")) {
336 }
else if (
modtype ==
"normsys") {
344 if (
mod.has_child(
"interpolation")) {
347 double low =
data[
"lo"].val_double();
348 double high =
data[
"hi"].val_double();
354 if (
interp == 4 && low <= 0)
355 low = std::numeric_limits<double>::epsilon();
356 if (
interp == 4 && high <= 0)
357 high = std::numeric_limits<double>::epsilon();
364 }
else if (
modtype ==
"histosys") {
378 }
else if (
modtype ==
"shapesys") {
381 std::vector<double> vals;
382 for (
const auto &
v :
mod[
"data"][
"vals"].children()) {
383 vals.push_back(
v.val_double());
386 for (
const auto &
v :
mod[
"parameters"].children()) {
392 std::string constraint(
mod.has_child(
"constraint_type") ?
mod[
"constraint_type"].val()
393 :
mod.has_child(
"constraint") ?
mod[
"constraint"].val()
397 }
else if (
modtype ==
"custom") {
421 v.setAllInterpCodes(4);
443 if (!
p.has_child(
"samples")) {
448 if (
p.has_child(::Literals::staterror)) {
449 auto &
staterr =
p[::Literals::staterror];
450 if (
staterr.has_child(
"relThreshold"))
452 if (
staterr.has_child(
"constraint_type"))
455 std::vector<double>
sumW;
456 std::vector<double>
sumW2;
462 std::vector<std::unique_ptr<RooDataHist>>
data;
463 for (
const auto &
comp :
p[
"samples"].children()) {
466 size_t nbins =
dh->numEntries();
473 for (
size_t i = 0; i < nbins; ++i) {
475 sumW2[i] +=
dh->weightSquared(i);
485 data.emplace_back(std::move(
dh));
494 std::vector<double>
errs(
sumW.size());
495 for (
size_t i = 0; i <
sumW.size(); ++i) {
509 for (
const auto &
comp :
p[
"samples"].children()) {
518 if (constraints.
empty()) {
533 std::string
const &key()
const override
535 static const std::string
keystring =
"interpolation0d";
541 elem[
"type"] << key();
542 elem[
"interpolationCodes"].fill_seq(
fip->interpolationCodes());
545 elem[
"high"].fill_seq(
fip->high(),
fip->variables().size());
546 elem[
"low"].fill_seq(
fip->low(),
fip->variables().size());
553 std::string
const &key()
const override
555 static const std::string
keystring =
"interpolation";
561 elem[
"type"] << key();
562 elem[
"interpolationCodes"].fill_seq(
pip->interpolationCodes());
563 elem[
"positiveDefinite"] <<
pip->positiveDefinite();
565 elem[
"nom"] <<
pip->nominalHist()->GetName();
584 pip.setPositiveDefinite(
p[
"positiveDefinite"].val_bool());
586 if (
p.has_child(
"interpolationCodes")) {
588 for (
auto const &node :
p[
"interpolationCodes"].children()) {
589 pip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int(),
true);
603 if (!
p.has_child(
"high")) {
606 if (!
p.has_child(
"low")) {
609 if (!
p.has_child(
"nom")) {
613 double nom(
p[
"nom"].val_double());
617 std::vector<double> high;
620 std::vector<double> low;
623 if (vars.size() != low.size() || vars.size() != high.size()) {
625 "' has non-matching lengths of 'vars', 'high' and 'low'!");
630 if (
p.has_child(
"interpolationCodes")) {
632 for (
auto const &node :
p[
"interpolationCodes"].children()) {
633 fip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int());
654 std::string
name =
"";
658 int interpolationCode = 4;
663 :
name(
n), param(
p), low(
l), high(
h), interpolationCode(i), constraint(
c), constraintType(
c->
IsA())
671 std::vector<double> low;
672 std::vector<double> high;
676 :
name(
n), param(
p), constraint(
c), constraintType(
c->
IsA())
678 low.assign(
l->dataHist().weightArray(),
l->dataHist().weightArray() +
l->dataHist().numEntries());
679 high.assign(
h->dataHist().weightArray(),
h->dataHist().weightArray() +
h->dataHist().numEntries());
684 std::vector<double> constraints;
685 std::vector<RooAbsReal *> parameters;
691struct GenericElement {
700 size_t end = s.size();
702 while (start < end && s[start] ==
'(' && s[end - 1] ==
')') {
705 for (
size_t i = start; i < end - 1; ++i) {
708 else if (s[i] ==
')')
710 if (
depth == 0 && i < end - 1) {
722 return s.substr(start, end - start);
727 std::vector<std::string>
parts;
732 for (
size_t i = 0; i <
expr.size(); ++i) {
736 }
else if (
c ==
')') {
738 }
else if (
c ==
'*' &&
depth == 0) {
740 std::string sub =
expr.substr(start, i - start);
750 std::string sub =
expr.substr(start);
763 static const std::regex pattern(
764 R
"(^\s*1(?:\.0)?\s*([\+\-])\s*([a-zA-Z_][a-zA-Z0-9_]*|[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*\*\s*([a-zA-Z_][a-zA-Z0-9_]*|[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*$)");
770 if (std::regex_match(s, match, pattern)) {
771 if (match[1].str() ==
"-") {
775 std::string
token2 = match[2].str();
776 std::string
token3 = match[4].str();
787 sys.name =
p2->GetName();
792 sys.name =
p3->GetName();
797 sys.name =
v2->GetName();
799 sys.high =
sign *
p3->getVal();
800 sys.low = -
sign *
p3->getVal();
802 sys.name =
v3->GetName();
804 sys.high =
sign *
p2->getVal();
805 sys.low = -
sign *
p2->getVal();
809 sys.interpolationCode = 1;
818 if (
auto prod =
dynamic_cast<RooProduct *
>(arg)) {
819 for (
const auto &
e : prod->components()) {
829 std::vector<double> hist;
830 std::vector<double> histError;
831 std::vector<NormFactor> normfactors;
832 std::vector<NormSys> normsys;
833 std::vector<HistoSys> histosys;
834 std::vector<ShapeSys> shapesys;
835 std::vector<GenericElement> tmpElements;
836 std::vector<GenericElement> otherElements;
837 bool useBarlowBeestonLight =
false;
838 std::vector<RooAbsReal *> staterrorParameters;
847 for (
RooAbsArg const *pdf : ws->allPdfs()) {
848 if (
auto gauss =
dynamic_cast<RooGaussian const *
>(pdf)) {
849 if (
parname == gauss->getX().GetName()) {
850 sample.normfactors.emplace_back(*par, gauss);
856 sample.normfactors.emplace_back(*par);
867 std::vector<Sample> samples;
868 std::map<int, double> tot_yield;
869 std::map<int, double> tot_yield2;
870 std::map<int, double> rel_errors;
872 long unsigned int nBins = 0;
887 std::vector<ParamHistFunc *>
phfs;
897 if (channel.varSet ==
nullptr) {
898 channel.varSet = dataHist.get();
899 channel.nBins = dataHist.numEntries();
901 if (
sample.hist.empty()) {
902 auto *
w = dataHist.weightArray();
903 sample.hist.assign(
w,
w + dataHist.numEntries());
920 }
else if (
auto par =
dynamic_cast<RooRealVar *
>(
e)) {
929 for (
size_t i = 0; i <
fip->variables().
size(); ++i) {
938 fip->interpolationCodes()[i], constraint);
949 expression.ReplaceAll((
"x[" + std::to_string(i) +
"]").c_str(),
p->GetName());
950 expression.ReplaceAll((
"@" + std::to_string(i)).c_str(),
p->GetName());
953 if (components.size() == 0) {
955 sample.otherElements.push_back(formula);
958 std::vector<RooAbsArg *> realComponents;
960 for (
auto &
comp : components) {
964 realComponents.push_back(
part);
970 sample.normsys.emplace_back(std::move(normsys));
975 std::string
name = std::string(formula->
GetName()) +
"_part" + std::to_string(idx);
978 sample.tmpElements.push_back({var});
1006 for (
size_t i = 0; i <
pip->paramList().
size(); ++i) {
1010 if (
auto lo =
dynamic_cast<RooHistFunc *
>(
pip->lowList().at(i))) {
1027 for (
const auto &
g :
phf->paramList()) {
1031 if (channel.tot_yield.find(idx) == channel.tot_yield.end()) {
1032 channel.tot_yield[idx] = 0;
1033 channel.tot_yield2[idx] = 0;
1035 channel.tot_yield[idx] +=
sample.hist[idx - 1];
1036 channel.tot_yield2[idx] += (
sample.hist[idx - 1] *
sample.hist[idx - 1]);
1038 sample.barlowBeestonLightConstraintType = constraint->
IsA();
1041 channel.rel_errors[idx] =
erel;
1044 channel.rel_errors[idx] =
erel;
1047 "currently, only RooPoisson and RooGaussian are supported as constraint types");
1051 sample.useBarlowBeestonLight =
true;
1058 for (
const auto &
g :
phf->paramList()) {
1059 sys.parameters.push_back(
static_cast<RooRealVar *
>(
g));
1065 if (!constraint && !
g->isConstant()) {
1072 sys.constraints.push_back(0.0);
1074 sys.constraints.push_back(1. / std::sqrt(
constraint_p->getX().getVal()));
1075 if (!sys.constraint) {
1080 if (!sys.constraint) {
1085 sample.shapesys.emplace_back(std::move(sys));
1091 channel.samples.emplace_back(std::move(
sample));
1100 for (
auto &
sample : channel.samples) {
1101 if (
sample.useBarlowBeestonLight) {
1103 for (
auto bin : channel.rel_errors) {
1106 const int i = bin.first;
1108 const double count =
sample.hist[i - 1];
1111 sample.histError[i - 1] =
1121 for (
const auto &
sample : channel.samples) {
1123 elem[
"type"] <<
"histfactory_dist";
1130 for (
const auto &
nf :
sample.normfactors) {
1133 mod[
"name"] <<
nf.name;
1134 mod[
"parameter"] <<
nf.param->GetName();
1135 mod[
"type"] <<
"normfactor";
1136 if (
nf.constraint) {
1137 mod[
"constraint_name"] <<
nf.constraint->GetName();
1138 tool->queueExport(*
nf.constraint);
1142 for (
const auto &sys :
sample.normsys) {
1145 mod[
"name"] << sys.name;
1146 mod[
"type"] <<
"normsys";
1147 mod[
"parameter"] << sys.param->GetName();
1148 if (sys.interpolationCode != 4) {
1149 mod[
"interpolation"] << sys.interpolationCode;
1151 if (sys.constraint) {
1152 mod[
"constraint_name"] << sys.constraint->GetName();
1153 }
else if (sys.constraintType) {
1154 mod[
"constraint_type"] <<
toString(sys.constraintType);
1156 auto &
data =
mod[
"data"].set_map();
1157 data[
"lo"] << sys.low;
1158 data[
"hi"] << sys.high;
1161 for (
const auto &sys :
sample.histosys) {
1164 mod[
"name"] << sys.name;
1165 mod[
"type"] <<
"histosys";
1166 mod[
"parameter"] << sys.param->GetName();
1167 if (sys.constraint) {
1168 mod[
"constraint_name"] << sys.constraint->GetName();
1169 }
else if (sys.constraintType) {
1170 mod[
"constraint_type"] <<
toString(sys.constraintType);
1172 auto &
data =
mod[
"data"].set_map();
1173 if (channel.nBins != sys.low.size() || channel.nBins != sys.high.size()) {
1174 std::stringstream
ss;
1175 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " << sys.low.size() <<
"/"
1176 << sys.high.size() <<
" found in nominal histogram errors!";
1183 for (
const auto &sys :
sample.shapesys) {
1186 mod[
"name"] << sys.name;
1187 mod[
"type"] <<
"shapesys";
1189 if (sys.constraint) {
1190 mod[
"constraint_name"] << sys.constraint->GetName();
1191 }
else if (sys.constraintType) {
1192 mod[
"constraint_type"] <<
toString(sys.constraintType);
1194 if (sys.constraint || sys.constraintType) {
1195 auto &vals =
mod[
"data"].set_map()[
"vals"];
1196 vals.fill_seq(sys.constraints);
1198 auto &vals =
mod[
"data"].set_map()[
"vals"];
1200 for (std::size_t i = 0; i < sys.parameters.size(); ++i) {
1201 vals.append_child() << 0;
1210 mod[
"type"] <<
"custom";
1216 mod[
"type"] <<
"custom";
1219 if (
sample.useBarlowBeestonLight) {
1222 mod[
"name"] << ::Literals::staterror;
1223 mod[
"type"] << ::Literals::staterror;
1234 out[
"name"] <<
name;
1239 auto &
dataNode = s[
"data"].set_map();
1240 if (channel.nBins !=
sample.hist.size()) {
1241 std::stringstream
ss;
1242 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.hist.size()
1243 <<
" found in nominal histogram!";
1247 if (!
sample.histError.empty()) {
1248 if (channel.nBins !=
sample.histError.size()) {
1249 std::stringstream
ss;
1250 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.histError.size()
1251 <<
" found in nominal histogram errors!";
1264 std::set<const RooAbsReal *> vars;
1265 for (
const auto &
sample : channel.samples) {
1266 for (
const auto &
nf :
sample.normfactors) {
1267 vars.insert(
nf.param);
1269 for (
const auto &sys :
sample.normsys) {
1270 vars.insert(sys.param);
1273 for (
const auto &sys :
sample.histosys) {
1274 vars.insert(sys.param);
1276 for (
const auto &sys :
sample.shapesys) {
1277 for (
const auto &par : sys.parameters) {
1281 if (
sample.useBarlowBeestonLight) {
1282 for (
const auto &par :
sample.staterrorParameters) {
1290 for (
auto *pdf : constraints) {
1292 for (
const auto *var : vars) {
1293 if (pdf->dependsOn(*var)) {
1311 std::cout <<
pdfname <<
" is not a sumpdf" << std::endl;
1319 std::cout <<
"sample " <<
sample->GetName() <<
" is no RooProduct or RooRealSumPdf in " <<
pdfname
1328 if (channel.samples.size() == 0)
1330 for (
auto &
sample : channel.samples) {
1331 if (
sample.hist.empty()) {
1343 "losing constraint term '" + std::string(constraint->
GetName()) +
1344 "', implicit constraints are not supported by HS3 yet! The term will appear in the HS3 file, but will not be "
1345 "picked up when creating a likelihood from it! You will have to add it manually as an external constraint.");
1346 tool->queueExport(*constraint);
1350 for (
const auto &
sample : channel.samples) {
1369 for (
const auto &
sample : channel.samples) {
1380 sumpdf->getParameters(channel.varSet, parameters);
1384 tool->queueExport(*param);
1393 bool autoExportDependants()
const override {
return false; }
1396 std::vector<RooAbsPdf *> constraints;
1407 constraints.push_back(pdf);
1416 std::string
const &key()
const override
1418 static const std::string
keystring =
"histfactory_dist";
1429 bool autoExportDependants()
const override {
return false; }
1432 std::vector<RooAbsPdf *> constraints;
1435 std::string
const &key()
const override
1437 static const std::string
keystring =
"histfactory_dist";
bool startsWith(std::string_view str, std::string_view prefix)
bool endsWith(std::string_view str, std::string_view suffix)
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
double toDouble(const char *s)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
TClass * IsA() const override
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,...
void setPositiveDefinite(bool flag=true)
const_iterator begin() const
const_iterator end() const
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.
bool isConstant() const
Check if the "Constant" attribute is set.
Abstract container object that can hold multiple RooAbsArg objects.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Abstract interface for all probability density functions.
TClass * IsA() const override
Int_t numBins(const char *rangeName=nullptr) const override
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...
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Returns the bin width (or volume) given a RooHistFunc.
Represents a constant real-valued object.
Container class to hold N-dimensional binned data.
virtual JSONNode & set_seq()=0
A real-valued function sampled from a multidimensional histogram.
Efficient implementation of a product of PDFs of the form.
Represents the product of a given set of RooAbsReal objects.
Implements a PDF constructed from a sum of functions:
Variable that can be changed from the outside.
void setError(double value)
const RooAbsBinning & getBinning(const char *name=nullptr, bool verbose=true, bool createOnTheFly=false) const override
Return binning definition with name.
This class encapsulates all information for the statistical interpretation of one experiment.
Configuration for a constrained, coherent shape variation of affected samples.
Configuration for an un- constrained overall systematic to scale sample normalisations.
std::string GetName() const
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.
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.
const char * GetName() const override
Returns name of object.
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
RooCmdArg RecycleConflictNodes(bool flag=true)
RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, bool depsAreCond=false)
void function(const Char_t *name_, T fun, const Char_t *docstring=0)
constexpr double defaultShapeSysGammaMax
constexpr double minShapeUncertainty
constexpr double defaultStatErrorGammaMax
constexpr double defaultGammaMin
CreateGammaConstraintsOutput createGammaConstraints(RooArgList const ¶mList, std::span< const double > relSigmas, double minSigma, Constraint::Type type)
#define STATIC_EXECUTE(MY_FUNC)
static uint64_t sum(uint64_t i)