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());
273 *
tool.workspace()->var(std::string(
"nom_") + param.
GetName()), 1.);
292 if (!
p.has_child(
"data")) {
308 if (
p.has_child(
"modifiers")) {
319 for (
const auto &
mod :
p[
"modifiers"].children()) {
320 std::string
const &
modtype =
mod[
"type"].val();
322 mod.has_child(
"name")
324 : (
mod.has_child(
"parameter") ?
mod[
"parameter"].val() :
"syst_" + std::to_string(idx));
328 }
else if (
modtype ==
"normfactor") {
331 if (
mod.has_child(
"constraint_name") ||
mod.has_child(
"constraint_type")) {
335 }
else if (
modtype ==
"normsys") {
343 if (
mod.has_child(
"interpolation")) {
346 double low =
data[
"lo"].val_double();
347 double high =
data[
"hi"].val_double();
353 if (
interp == 4 && low <= 0)
354 low = std::numeric_limits<double>::epsilon();
355 if (
interp == 4 && high <= 0)
356 high = std::numeric_limits<double>::epsilon();
363 }
else if (
modtype ==
"histosys") {
377 }
else if (
modtype ==
"shapesys") {
380 std::vector<double> vals;
381 for (
const auto &
v :
mod[
"data"][
"vals"].children()) {
382 vals.push_back(
v.val_double());
385 for (
const auto &
v :
mod[
"parameters"].children()) {
391 std::string constraint(
mod.has_child(
"constraint_type") ?
mod[
"constraint_type"].val()
392 :
mod.has_child(
"constraint") ?
mod[
"constraint"].val()
396 }
else if (
modtype ==
"custom") {
420 v.setAllInterpCodes(4);
442 if (!
p.has_child(
"samples")) {
447 if (
p.has_child(::Literals::staterror)) {
448 auto &
staterr =
p[::Literals::staterror];
449 if (
staterr.has_child(
"relThreshold"))
451 if (
staterr.has_child(
"constraint_type"))
454 std::vector<double>
sumW;
455 std::vector<double>
sumW2;
461 std::vector<std::unique_ptr<RooDataHist>>
data;
462 for (
const auto &
comp :
p[
"samples"].children()) {
465 size_t nbins =
dh->numEntries();
472 for (
size_t i = 0; i < nbins; ++i) {
474 sumW2[i] +=
dh->weightSquared(i);
484 data.emplace_back(std::move(
dh));
493 std::vector<double>
errs(
sumW.size());
494 for (
size_t i = 0; i <
sumW.size(); ++i) {
508 for (
const auto &
comp :
p[
"samples"].children()) {
517 if (constraints.
empty()) {
532 std::string
const &key()
const override
534 static const std::string
keystring =
"interpolation0d";
540 elem[
"type"] << key();
541 elem[
"interpolationCodes"].fill_seq(
fip->interpolationCodes());
544 elem[
"high"].fill_seq(
fip->high(),
fip->variables().size());
545 elem[
"low"].fill_seq(
fip->low(),
fip->variables().size());
552 std::string
const &key()
const override
554 static const std::string
keystring =
"interpolation";
560 elem[
"type"] << key();
561 elem[
"interpolationCodes"].fill_seq(
pip->interpolationCodes());
562 elem[
"positiveDefinite"] <<
pip->positiveDefinite();
564 elem[
"nom"] <<
pip->nominalHist()->GetName();
583 pip.setPositiveDefinite(
p[
"positiveDefinite"].val_bool());
585 if (
p.has_child(
"interpolationCodes")) {
587 for (
auto const &node :
p[
"interpolationCodes"].children()) {
588 pip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int(),
true);
602 if (!
p.has_child(
"high")) {
605 if (!
p.has_child(
"low")) {
608 if (!
p.has_child(
"nom")) {
612 double nom(
p[
"nom"].val_double());
616 std::vector<double> high;
619 std::vector<double> low;
622 if (vars.size() != low.size() || vars.size() != high.size()) {
624 "' has non-matching lengths of 'vars', 'high' and 'low'!");
629 if (
p.has_child(
"interpolationCodes")) {
631 for (
auto const &node :
p[
"interpolationCodes"].children()) {
632 fip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int());
653 std::string
name =
"";
657 int interpolationCode = 4;
662 :
name(
n), param(
p), low(
l), high(
h), interpolationCode(i), constraint(
c), constraintType(
c->
IsA())
670 std::vector<double> low;
671 std::vector<double> high;
675 :
name(
n), param(
p), constraint(
c), constraintType(
c->
IsA())
677 low.assign(
l->dataHist().weightArray(),
l->dataHist().weightArray() +
l->dataHist().numEntries());
678 high.assign(
h->dataHist().weightArray(),
h->dataHist().weightArray() +
h->dataHist().numEntries());
683 std::vector<double> constraints;
684 std::vector<RooAbsReal *> parameters;
690struct GenericElement {
699 size_t end = s.size();
701 while (start < end && s[start] ==
'(' && s[end - 1] ==
')') {
704 for (
size_t i = start; i < end - 1; ++i) {
707 else if (s[i] ==
')')
709 if (
depth == 0 && i < end - 1) {
721 return s.substr(start, end - start);
726 std::vector<std::string>
parts;
731 for (
size_t i = 0; i <
expr.size(); ++i) {
735 }
else if (
c ==
')') {
737 }
else if (
c ==
'*' &&
depth == 0) {
739 std::string sub =
expr.substr(start, i - start);
749 std::string sub =
expr.substr(start);
762 static const std::regex pattern(
763 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*$)");
769 if (std::regex_match(s, match, pattern)) {
770 if (match[1].str() ==
"-") {
774 std::string
token2 = match[2].str();
775 std::string
token3 = match[4].str();
786 sys.name =
p2->GetName();
791 sys.name =
p3->GetName();
796 sys.name =
v2->GetName();
798 sys.high =
sign *
p3->getVal();
799 sys.low = -
sign *
p3->getVal();
801 sys.name =
v3->GetName();
803 sys.high =
sign *
p2->getVal();
804 sys.low = -
sign *
p2->getVal();
808 sys.interpolationCode = 1;
817 if (
auto prod =
dynamic_cast<RooProduct *
>(arg)) {
818 for (
const auto &
e : prod->components()) {
828 for (
auto *var : list) {
838 std::vector<double> hist;
839 std::vector<double> histError;
840 std::vector<NormFactor> normfactors;
841 std::vector<NormSys> normsys;
842 std::vector<HistoSys> histosys;
843 std::vector<ShapeSys> shapesys;
844 std::vector<GenericElement> tmpElements;
845 std::vector<GenericElement> otherElements;
846 bool useBarlowBeestonLight =
false;
847 std::vector<RooAbsReal *> staterrorParameters;
856 for (
RooAbsArg const *pdf : ws->allPdfs()) {
857 if (
auto gauss =
dynamic_cast<RooGaussian const *
>(pdf)) {
858 if (
parname == gauss->getX().GetName()) {
859 sample.normfactors.emplace_back(*par, gauss);
865 sample.normfactors.emplace_back(*par);
876 std::vector<Sample> samples;
877 std::map<int, double> tot_yield;
878 std::map<int, double> tot_yield2;
879 std::map<int, double> rel_errors;
881 long unsigned int nBins = 0;
896 std::vector<ParamHistFunc *>
phfs;
906 if (channel.varSet ==
nullptr) {
907 channel.varSet = dataHist.get();
908 channel.nBins = dataHist.numEntries();
910 if (
sample.hist.empty()) {
911 auto *
w = dataHist.weightArray();
912 sample.hist.assign(
w,
w + dataHist.numEntries());
929 }
else if (
auto par =
dynamic_cast<RooRealVar *
>(
e)) {
938 for (
size_t i = 0; i <
fip->variables().size(); ++i) {
947 fip->interpolationCodes()[i], constraint);
958 expression.ReplaceAll((
"x[" + std::to_string(i) +
"]").c_str(),
p->GetName());
959 expression.ReplaceAll((
"@" + std::to_string(i)).c_str(),
p->GetName());
962 if (components.size() == 0) {
964 sample.otherElements.push_back(formula);
967 std::vector<RooAbsArg *> realComponents;
969 for (
auto &
comp : components) {
973 realComponents.push_back(
part);
979 sample.normsys.emplace_back(std::move(normsys));
984 std::string
name = std::string(formula->
GetName()) +
"_part" + std::to_string(idx);
987 sample.tmpElements.push_back({var});
1015 for (
size_t i = 0; i <
pip->paramList().
size(); ++i) {
1019 if (
auto lo =
dynamic_cast<RooHistFunc *
>(
pip->lowList().at(i))) {
1036 for (
const auto &
g :
phf->paramList()) {
1040 if (channel.tot_yield.find(idx) == channel.tot_yield.end()) {
1041 channel.tot_yield[idx] = 0;
1042 channel.tot_yield2[idx] = 0;
1044 channel.tot_yield[idx] +=
sample.hist[idx - 1];
1045 channel.tot_yield2[idx] += (
sample.hist[idx - 1] *
sample.hist[idx - 1]);
1047 sample.barlowBeestonLightConstraintType = constraint->
IsA();
1050 channel.rel_errors[idx] =
erel;
1053 channel.rel_errors[idx] =
erel;
1056 "currently, only RooPoisson and RooGaussian are supported as constraint types");
1060 sample.useBarlowBeestonLight =
true;
1067 for (
const auto &
g :
phf->paramList()) {
1068 sys.parameters.push_back(
static_cast<RooRealVar *
>(
g));
1074 if (!constraint && !
g->isConstant()) {
1081 sys.constraints.push_back(0.0);
1083 sys.constraints.push_back(1. / std::sqrt(
constraint_p->getX().getVal()));
1084 if (!sys.constraint) {
1089 if (!sys.constraint) {
1094 sample.shapesys.emplace_back(std::move(sys));
1100 channel.samples.emplace_back(std::move(
sample));
1109 for (
auto &
sample : channel.samples) {
1110 if (
sample.useBarlowBeestonLight) {
1112 for (
auto bin : channel.rel_errors) {
1115 const int i = bin.first;
1117 const double count =
sample.hist[i - 1];
1120 sample.histError[i - 1] =
1130 for (
const auto &
sample : channel.samples) {
1132 elem[
"type"] <<
"histfactory_dist";
1139 for (
const auto &
nf :
sample.normfactors) {
1142 mod[
"name"] <<
nf.name;
1143 mod[
"parameter"] <<
nf.param->GetName();
1144 mod[
"type"] <<
"normfactor";
1145 if (
nf.constraint) {
1146 mod[
"constraint_name"] <<
nf.constraint->GetName();
1147 tool->queueExport(*
nf.constraint);
1151 for (
const auto &sys :
sample.normsys) {
1154 mod[
"name"] << sys.name;
1155 mod[
"type"] <<
"normsys";
1156 mod[
"parameter"] << sys.param->GetName();
1157 if (sys.interpolationCode != 4) {
1158 mod[
"interpolation"] << sys.interpolationCode;
1160 if (sys.constraint) {
1161 mod[
"constraint_name"] << sys.constraint->GetName();
1162 }
else if (sys.constraintType) {
1163 mod[
"constraint_type"] <<
toString(sys.constraintType);
1165 auto &
data =
mod[
"data"].set_map();
1166 data[
"lo"] << sys.low;
1167 data[
"hi"] << sys.high;
1170 for (
const auto &sys :
sample.histosys) {
1173 mod[
"name"] << sys.name;
1174 mod[
"type"] <<
"histosys";
1175 mod[
"parameter"] << sys.param->GetName();
1176 if (sys.constraint) {
1177 mod[
"constraint_name"] << sys.constraint->GetName();
1178 }
else if (sys.constraintType) {
1179 mod[
"constraint_type"] <<
toString(sys.constraintType);
1181 auto &
data =
mod[
"data"].set_map();
1182 if (channel.nBins != sys.low.size() || channel.nBins != sys.high.size()) {
1183 std::stringstream
ss;
1184 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " << sys.low.size() <<
"/"
1185 << sys.high.size() <<
" found in nominal histogram errors!";
1192 for (
const auto &sys :
sample.shapesys) {
1195 mod[
"name"] << sys.name;
1196 mod[
"type"] <<
"shapesys";
1198 if (sys.constraint) {
1199 mod[
"constraint_name"] << sys.constraint->GetName();
1200 }
else if (sys.constraintType) {
1201 mod[
"constraint_type"] <<
toString(sys.constraintType);
1203 if (sys.constraint || sys.constraintType) {
1204 auto &vals =
mod[
"data"].set_map()[
"vals"];
1205 vals.fill_seq(sys.constraints);
1207 auto &vals =
mod[
"data"].set_map()[
"vals"];
1209 for (std::size_t i = 0; i < sys.parameters.size(); ++i) {
1210 vals.append_child() << 0;
1219 mod[
"type"] <<
"custom";
1225 mod[
"type"] <<
"custom";
1228 if (
sample.useBarlowBeestonLight) {
1231 mod[
"name"] << ::Literals::staterror;
1232 mod[
"type"] << ::Literals::staterror;
1243 out[
"name"] <<
name;
1248 auto &
dataNode = s[
"data"].set_map();
1249 if (channel.nBins !=
sample.hist.size()) {
1250 std::stringstream
ss;
1251 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.hist.size()
1252 <<
" found in nominal histogram!";
1256 if (!
sample.histError.empty()) {
1257 if (channel.nBins !=
sample.histError.size()) {
1258 std::stringstream
ss;
1259 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.histError.size()
1260 <<
" found in nominal histogram errors!";
1273 std::set<const RooAbsReal *> vars;
1274 for (
const auto &
sample : channel.samples) {
1275 for (
const auto &
nf :
sample.normfactors) {
1276 vars.insert(
nf.param);
1278 for (
const auto &sys :
sample.normsys) {
1279 vars.insert(sys.param);
1282 for (
const auto &sys :
sample.histosys) {
1283 vars.insert(sys.param);
1285 for (
const auto &sys :
sample.shapesys) {
1286 for (
const auto &par : sys.parameters) {
1290 if (
sample.useBarlowBeestonLight) {
1291 for (
const auto &par :
sample.staterrorParameters) {
1299 for (
auto *pdf : constraints) {
1301 for (
const auto *var : vars) {
1302 if (pdf->dependsOn(*var)) {
1320 std::cout <<
pdfname <<
" is not a sumpdf" << std::endl;
1328 std::cout <<
"sample " <<
sample->GetName() <<
" is no RooProduct or RooRealSumPdf in " <<
pdfname
1337 if (channel.samples.size() == 0)
1339 for (
auto &
sample : channel.samples) {
1340 if (
sample.hist.empty()) {
1352 "losing constraint term '" + std::string(constraint->
GetName()) +
1353 "', implicit constraints are not supported by HS3 yet! The term will appear in the HS3 file, but will not be "
1354 "picked up when creating a likelihood from it! You will have to add it manually as an external constraint.");
1355 tool->queueExport(*constraint);
1359 for (
const auto &
sample : channel.samples) {
1378 for (
const auto &
sample : channel.samples) {
1389 sumpdf->getParameters(channel.varSet, parameters);
1393 tool->queueExport(*param);
1402 bool autoExportDependants()
const override {
return false; }
1405 std::vector<RooAbsPdf *> constraints;
1416 constraints.push_back(pdf);
1425 std::string
const &key()
const override
1427 static const std::string
keystring =
"histfactory_dist";
1438 bool autoExportDependants()
const override {
return false; }
1441 std::vector<RooAbsPdf *> constraints;
1444 std::string
const &key()
const override
1446 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)