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,
201 size_t n = std::max(vals.size(),
parnames.size());
203 for (std::size_t i = 0; i <
n; ++i) {
214 if (vals.size() > 0) {
215 if (constraintType !=
"Const") {
224 gamma->setConstant(
true);
234 if (!
comp.has_child(
"modifiers"))
236 for (
const auto &
mod :
comp[
"modifiers"].children()) {
237 if (
mod[
"type"].val() == ::Literals::staterror)
245 if (
comp.has_child(
"modifiers")) {
246 for (
const auto &
mod :
comp[
"modifiers"].children()) {
247 if (
mod[
"type"].val() == ::Literals::staterror)
252 ::Literals::staterror +
" modifier!");
269 param.
setError(gauss->getSigma().getVal());
280 *
tool.workspace()->var(std::string(
"nom_") + param.
GetName()), 1.);
299 if (!
p.has_child(
"data")) {
315 if (
p.has_child(
"modifiers")) {
326 for (
const auto &
mod :
p[
"modifiers"].children()) {
327 std::string
const &
modtype =
mod[
"type"].val();
329 mod.has_child(
"name")
331 : (
mod.has_child(
"parameter") ?
mod[
"parameter"].val() :
"syst_" + std::to_string(idx));
335 }
else if (
modtype ==
"normfactor") {
338 if (
mod.has_child(
"constraint_name") ||
mod.has_child(
"constraint_type")) {
342 }
else if (
modtype ==
"normsys") {
350 if (
mod.has_child(
"interpolation")) {
353 double low =
data[
"lo"].val_double();
354 double high =
data[
"hi"].val_double();
360 if (
interp == 4 && low <= 0)
361 low = std::numeric_limits<double>::epsilon();
362 if (
interp == 4 && high <= 0)
363 high = std::numeric_limits<double>::epsilon();
370 }
else if (
modtype ==
"histosys") {
387 std::vector<double> vals;
388 if (
mod[
"data"].has_child(
"vals")) {
389 for (
const auto &
v :
mod[
"data"][
"vals"].children()) {
390 vals.push_back(
v.val_double());
394 for (
const auto &
v :
mod[
"parameters"].children()) {
397 if (vals.empty() &&
parnames.empty()) {
399 "' with neither values nor parameters!");
401 std::string constraint(
mod.has_child(
"constraint_type") ?
mod[
"constraint_type"].val()
402 :
mod.has_child(
"constraint") ?
mod[
"constraint"].val()
406 }
else if (
modtype ==
"custom") {
430 v.setAllInterpCodes(4);
452 if (!
p.has_child(
"samples")) {
457 if (
p.has_child(::Literals::staterror)) {
458 auto &
staterr =
p[::Literals::staterror];
459 if (
staterr.has_child(
"relThreshold"))
461 if (
staterr.has_child(
"constraint_type"))
464 std::vector<double>
sumW;
465 std::vector<double>
sumW2;
471 std::vector<std::unique_ptr<RooDataHist>>
data;
472 for (
const auto &
comp :
p[
"samples"].children()) {
475 size_t nbins =
dh->numEntries();
482 for (
size_t i = 0; i < nbins; ++i) {
484 sumW2[i] +=
dh->weightSquared(i);
494 data.emplace_back(std::move(
dh));
503 std::vector<double>
errs(
sumW.size());
504 for (
size_t i = 0; i <
sumW.size(); ++i) {
518 for (
const auto &
comp :
p[
"samples"].children()) {
527 if (constraints.
empty()) {
542 std::string
const &key()
const override
544 static const std::string
keystring =
"interpolation0d";
550 elem[
"type"] << key();
551 elem[
"interpolationCodes"].fill_seq(
fip->interpolationCodes());
554 elem[
"high"].fill_seq(
fip->high(),
fip->variables().size());
555 elem[
"low"].fill_seq(
fip->low(),
fip->variables().size());
562 std::string
const &key()
const override
564 static const std::string
keystring =
"interpolation";
570 elem[
"type"] << key();
571 elem[
"interpolationCodes"].fill_seq(
pip->interpolationCodes());
572 elem[
"positiveDefinite"] <<
pip->positiveDefinite();
574 elem[
"nom"] <<
pip->nominalHist()->GetName();
593 pip.setPositiveDefinite(
p[
"positiveDefinite"].val_bool());
595 if (
p.has_child(
"interpolationCodes")) {
597 for (
auto const &node :
p[
"interpolationCodes"].children()) {
598 pip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int(),
true);
612 if (!
p.has_child(
"high")) {
615 if (!
p.has_child(
"low")) {
618 if (!
p.has_child(
"nom")) {
622 double nom(
p[
"nom"].val_double());
626 std::vector<double> high;
629 std::vector<double> low;
632 if (vars.size() != low.size() || vars.size() != high.size()) {
634 "' has non-matching lengths of 'vars', 'high' and 'low'!");
639 if (
p.has_child(
"interpolationCodes")) {
641 for (
auto const &node :
p[
"interpolationCodes"].children()) {
642 fip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int());
663 std::string
name =
"";
667 int interpolationCode = 4;
672 :
name(
n), param(
p), low(
l), high(
h), interpolationCode(i), constraint(
c), constraintType(
c->
IsA())
680 std::vector<double> low;
681 std::vector<double> high;
685 :
name(
n), param(
p), constraint(
c), constraintType(
c->
IsA())
687 low.assign(
l->dataHist().weightArray(),
l->dataHist().weightArray() +
l->dataHist().numEntries());
688 high.assign(
h->dataHist().weightArray(),
h->dataHist().weightArray() +
h->dataHist().numEntries());
693 std::vector<double> constraints;
694 std::vector<RooAbsReal *> parameters;
700struct GenericElement {
709 size_t end = s.size();
711 while (start < end && s[start] ==
'(' && s[end - 1] ==
')') {
714 for (
size_t i = start; i < end - 1; ++i) {
717 else if (s[i] ==
')')
719 if (
depth == 0 && i < end - 1) {
731 return s.substr(start, end - start);
736 std::vector<std::string>
parts;
741 for (
size_t i = 0; i <
expr.size(); ++i) {
745 }
else if (
c ==
')') {
747 }
else if (
c ==
'*' &&
depth == 0) {
749 std::string sub =
expr.substr(start, i - start);
759 std::string sub =
expr.substr(start);
772 static const std::regex pattern(
773 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*$)");
779 if (std::regex_match(s, match, pattern)) {
780 if (match[1].str() ==
"-") {
784 std::string
token2 = match[2].str();
785 std::string
token3 = match[4].str();
796 sys.name =
p2->GetName();
801 sys.name =
p3->GetName();
806 sys.name =
v2->GetName();
808 sys.high =
sign *
p3->getVal();
809 sys.low = -
sign *
p3->getVal();
811 sys.name =
v3->GetName();
813 sys.high =
sign *
p2->getVal();
814 sys.low = -
sign *
p2->getVal();
818 sys.interpolationCode = 1;
827 if (
auto prod =
dynamic_cast<RooProduct *
>(arg)) {
828 for (
const auto &
e : prod->components()) {
838 for (
auto *var : list) {
848 std::vector<double> hist;
849 std::vector<double> histError;
850 std::vector<NormFactor> normfactors;
851 std::vector<NormSys> normsys;
852 std::vector<HistoSys> histosys;
853 std::vector<ShapeSys> shapesys;
854 std::vector<GenericElement> tmpElements;
855 std::vector<GenericElement> otherElements;
856 bool useBarlowBeestonLight =
false;
857 std::vector<RooAbsReal *> staterrorParameters;
866 for (
RooAbsArg const *pdf : ws->allPdfs()) {
867 if (
auto gauss =
dynamic_cast<RooGaussian const *
>(pdf)) {
868 if (
parname == gauss->getX().GetName()) {
869 sample.normfactors.emplace_back(*par, gauss);
875 sample.normfactors.emplace_back(*par);
886 std::vector<Sample> samples;
887 std::map<int, double> tot_yield;
888 std::map<int, double> tot_yield2;
889 std::map<int, double> rel_errors;
891 long unsigned int nBins = 0;
906 std::vector<ParamHistFunc *>
phfs;
916 if (channel.varSet ==
nullptr) {
917 channel.varSet = dataHist.get();
918 channel.nBins = dataHist.numEntries();
920 if (
sample.hist.empty()) {
921 auto *
w = dataHist.weightArray();
922 sample.hist.assign(
w,
w + dataHist.numEntries());
939 }
else if (
auto par =
dynamic_cast<RooRealVar *
>(
e)) {
948 for (
size_t i = 0; i <
fip->variables().size(); ++i) {
957 fip->interpolationCodes()[i], constraint);
968 expression.ReplaceAll((
"x[" + std::to_string(i) +
"]").c_str(),
p->GetName());
969 expression.ReplaceAll((
"@" + std::to_string(i)).c_str(),
p->GetName());
972 if (components.size() == 0) {
974 sample.otherElements.push_back(formula);
977 std::vector<RooAbsArg *> realComponents;
979 for (
auto &
comp : components) {
983 realComponents.push_back(
part);
989 sample.normsys.emplace_back(std::move(normsys));
994 std::string
name = std::string(formula->
GetName()) +
"_part" + std::to_string(idx);
997 sample.tmpElements.push_back({var});
1025 for (
size_t i = 0; i <
pip->paramList().
size(); ++i) {
1029 if (
auto lo =
dynamic_cast<RooHistFunc *
>(
pip->lowList().at(i))) {
1046 for (
const auto &
g :
phf->paramList()) {
1050 if (channel.tot_yield.find(idx) == channel.tot_yield.end()) {
1051 channel.tot_yield[idx] = 0;
1052 channel.tot_yield2[idx] = 0;
1054 channel.tot_yield[idx] +=
sample.hist[idx - 1];
1055 channel.tot_yield2[idx] += (
sample.hist[idx - 1] *
sample.hist[idx - 1]);
1057 sample.barlowBeestonLightConstraintType = constraint->
IsA();
1060 channel.rel_errors[idx] =
erel;
1063 channel.rel_errors[idx] =
erel;
1066 "currently, only RooPoisson and RooGaussian are supported as constraint types");
1070 sample.useBarlowBeestonLight =
true;
1077 for (
const auto &
g :
phf->paramList()) {
1078 sys.parameters.push_back(
static_cast<RooRealVar *
>(
g));
1084 if (!constraint && !
g->isConstant()) {
1091 sys.constraints.push_back(0.0);
1093 sys.constraints.push_back(1. / std::sqrt(
constraint_p->getX().getVal()));
1094 if (!sys.constraint) {
1099 if (!sys.constraint) {
1104 sample.shapesys.emplace_back(std::move(sys));
1110 channel.samples.emplace_back(std::move(
sample));
1119 for (
auto &
sample : channel.samples) {
1120 if (
sample.useBarlowBeestonLight) {
1122 for (
auto bin : channel.rel_errors) {
1125 const int i =
bin.first;
1127 const double count =
sample.hist[i - 1];
1130 sample.histError[i - 1] =
1140 for (
const auto &
sample : channel.samples) {
1142 elem[
"type"] <<
"histfactory_dist";
1149 for (
const auto &
nf :
sample.normfactors) {
1152 mod[
"name"] <<
nf.name;
1153 mod[
"parameter"] <<
nf.param->GetName();
1154 mod[
"type"] <<
"normfactor";
1155 if (
nf.constraint) {
1156 mod[
"constraint_name"] <<
nf.constraint->GetName();
1157 tool->queueExport(*
nf.constraint);
1161 for (
const auto &sys :
sample.normsys) {
1164 mod[
"name"] << sys.name;
1165 mod[
"type"] <<
"normsys";
1166 mod[
"parameter"] << sys.param->GetName();
1167 if (sys.interpolationCode != 4) {
1168 mod[
"interpolation"] << sys.interpolationCode;
1170 if (sys.constraint) {
1171 mod[
"constraint_name"] << sys.constraint->GetName();
1172 }
else if (sys.constraintType) {
1173 mod[
"constraint_type"] <<
toString(sys.constraintType);
1175 auto &
data =
mod[
"data"].set_map();
1176 data[
"lo"] << sys.low;
1177 data[
"hi"] << sys.high;
1180 for (
const auto &sys :
sample.histosys) {
1183 mod[
"name"] << sys.name;
1184 mod[
"type"] <<
"histosys";
1185 mod[
"parameter"] << sys.param->GetName();
1186 if (sys.constraint) {
1187 mod[
"constraint_name"] << sys.constraint->GetName();
1188 }
else if (sys.constraintType) {
1189 mod[
"constraint_type"] <<
toString(sys.constraintType);
1191 auto &
data =
mod[
"data"].set_map();
1192 if (channel.nBins != sys.low.size() || channel.nBins != sys.high.size()) {
1193 std::stringstream
ss;
1194 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " << sys.low.size() <<
"/"
1195 << sys.high.size() <<
" found in nominal histogram errors!";
1202 for (
const auto &sys :
sample.shapesys) {
1205 mod[
"name"] << sys.name;
1206 mod[
"type"] <<
"shapesys";
1208 if (sys.constraint) {
1209 mod[
"constraint_name"] << sys.constraint->GetName();
1210 }
else if (sys.constraintType) {
1211 mod[
"constraint_type"] <<
toString(sys.constraintType);
1213 if (sys.constraint || sys.constraintType) {
1214 auto &vals =
mod[
"data"].set_map()[
"vals"];
1215 vals.fill_seq(sys.constraints);
1217 auto &vals =
mod[
"data"].set_map()[
"vals"];
1219 for (std::size_t i = 0; i < sys.parameters.size(); ++i) {
1220 vals.append_child() << 0;
1229 mod[
"type"] <<
"custom";
1235 mod[
"type"] <<
"custom";
1238 if (
sample.useBarlowBeestonLight) {
1241 mod[
"name"] << ::Literals::staterror;
1242 mod[
"type"] << ::Literals::staterror;
1248 auto &output =
elem[
"axes"].set_seq();
1250 auto &out = output.append_child().set_map();
1253 out[
"name"] <<
name;
1258 auto &
dataNode = s[
"data"].set_map();
1259 if (channel.nBins !=
sample.hist.size()) {
1260 std::stringstream
ss;
1261 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.hist.size()
1262 <<
" found in nominal histogram!";
1266 if (!
sample.histError.empty()) {
1267 if (channel.nBins !=
sample.histError.size()) {
1268 std::stringstream
ss;
1269 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.histError.size()
1270 <<
" found in nominal histogram errors!";
1283 std::set<const RooAbsReal *> vars;
1284 for (
const auto &
sample : channel.samples) {
1285 for (
const auto &
nf :
sample.normfactors) {
1286 vars.insert(
nf.param);
1288 for (
const auto &sys :
sample.normsys) {
1289 vars.insert(sys.param);
1292 for (
const auto &sys :
sample.histosys) {
1293 vars.insert(sys.param);
1295 for (
const auto &sys :
sample.shapesys) {
1296 for (
const auto &par : sys.parameters) {
1300 if (
sample.useBarlowBeestonLight) {
1301 for (
const auto &par :
sample.staterrorParameters) {
1309 for (
auto *pdf : constraints) {
1311 for (
const auto *var : vars) {
1312 if (pdf->dependsOn(*var)) {
1330 std::cout <<
pdfname <<
" is not a sumpdf" << std::endl;
1338 std::cout <<
"sample " <<
sample->GetName() <<
" is no RooProduct or RooRealSumPdf in " <<
pdfname
1347 if (channel.samples.size() == 0)
1349 for (
auto &
sample : channel.samples) {
1350 if (
sample.hist.empty()) {
1362 "losing constraint term '" + std::string(constraint->
GetName()) +
1363 "', implicit constraints are not supported by HS3 yet! The term will appear in the HS3 file, but will not be "
1364 "picked up when creating a likelihood from it! You will have to add it manually as an external constraint.");
1365 tool->queueExport(*constraint);
1369 for (
const auto &
sample : channel.samples) {
1388 for (
const auto &
sample : channel.samples) {
1399 sumpdf->getParameters(channel.varSet, parameters);
1403 tool->queueExport(*param);
1412 bool autoExportDependants()
const override {
return false; }
1415 std::vector<RooAbsPdf *> constraints;
1426 constraints.push_back(pdf);
1435 std::string
const &key()
const override
1437 static const std::string
keystring =
"histfactory_dist";
1448 bool autoExportDependants()
const override {
return false; }
1451 std::vector<RooAbsPdf *> constraints;
1454 std::string
const &key()
const override
1456 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, bool shared=true) 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.
TObject * obj(RooStringView name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name)
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)