53 int ndigits = std::floor(std::log10(std::abs(
d))) + 1 -
nSig;
55 if (std::abs(
d /
sf) < 2)
57 return sf * std::round(
d /
sf);
66void erasePrefix(std::string &str, std::string_view prefix)
69 str.erase(0, prefix.size());
76 str.erase(str.size() -
suffix.size());
92 for (
const auto &client :
gamma->clients()) {
93 if (
auto casted =
dynamic_cast<T *
>(client)) {
139 return "gamma_" +
sysname +
"_bin_" + std::to_string(i);
149 for (std::size_t i = 0; i < params.size(); ++i) {
150 std::string
name(params[i]->GetName());
164 nom.setConstant(
true);
176 const std::vector<std::string> &
parnames,
const std::vector<double> &vals,
182 size_t n = std::max(vals.size(),
parnames.size());
184 for (std::size_t i = 0; i <
n; ++i) {
195 if (vals.size() > 0) {
196 if (constraintType !=
"Const") {
205 gamma->setConstant(
true);
215 if (!
comp.has_child(
"modifiers"))
217 for (
const auto &
mod :
comp[
"modifiers"].children()) {
218 if (
mod[
"type"].val() == ::Literals::staterror)
226 if (
comp.has_child(
"modifiers")) {
227 for (
const auto &
mod :
comp[
"modifiers"].children()) {
228 if (
mod[
"type"].val() == ::Literals::staterror)
233 ::Literals::staterror +
" modifier!");
250 param.
setError(gauss->getSigma().getVal());
261 *
tool.workspace()->var(std::string(
"nom_") + param.
GetName()), 1.);
272 std::string(constraint.
GetName()));
280 if (
auto const *tau =
dynamic_cast<RooConstVar const *
>(arg)) {
281 return tau->getVal();
288 return real->getVal();
294 std::string(constraint.
GetName()));
295 return std::numeric_limits<double>::quiet_NaN();
310 if (!
p.has_child(
"data")) {
326 if (
p.has_child(
"modifiers")) {
337 for (
const auto &
mod :
p[
"modifiers"].children()) {
338 std::string
const &
modtype =
mod[
"type"].val();
340 mod.has_child(
"name")
342 : (
mod.has_child(
"parameter") ?
mod[
"parameter"].val() :
"syst_" + std::to_string(idx));
346 }
else if (
modtype ==
"normfactor") {
350 if (
mod.has_child(
"constraint_name") ||
mod.has_child(
"constraint_type")) {
354 }
else if (
modtype ==
"normsys") {
362 if (
mod.has_child(
"interpolation")) {
365 double low =
data[
"lo"].val_double();
366 double high =
data[
"hi"].val_double();
372 if (
interp == 4 && low <= 0)
373 low = std::numeric_limits<double>::epsilon();
374 if (
interp == 4 && high <= 0)
375 high = std::numeric_limits<double>::epsilon();
382 }
else if (
modtype ==
"histosys") {
399 std::vector<double> vals;
400 if (
mod[
"data"].has_child(
"vals")) {
401 for (
const auto &
v :
mod[
"data"][
"vals"].children()) {
402 vals.push_back(
v.val_double());
406 for (
const auto &
v :
mod[
"parameters"].children()) {
409 if (vals.empty() &&
parnames.empty()) {
411 "' with neither values nor parameters!");
413 std::string constraint(
mod.has_child(
"constraint_type") ?
mod[
"constraint_type"].val()
414 :
mod.has_child(
"constraint") ?
mod[
"constraint"].val()
418 }
else if (
modtype ==
"custom") {
442 v.setAllInterpCodes(4);
464 if (!
p.has_child(
"samples")) {
469 if (
p.has_child(::Literals::staterror)) {
470 auto &
staterr =
p[::Literals::staterror];
471 if (
staterr.has_child(
"relThreshold"))
473 if (
staterr.has_child(
"constraint_type"))
476 std::vector<double>
sumW;
477 std::vector<double>
sumW2;
483 std::vector<std::unique_ptr<RooDataHist>>
data;
484 for (
const auto &
comp :
p[
"samples"].children()) {
487 size_t nbins =
dh->numEntries();
494 for (
size_t i = 0; i <
nbins; ++i) {
496 sumW2[i] +=
dh->weightSquared(i);
506 data.emplace_back(std::move(
dh));
515 std::vector<double>
errs(
sumW.size());
516 for (
size_t i = 0; i <
sumW.size(); ++i) {
534 for (
const auto &
comp :
p[
"samples"].children()) {
543 if (constraints.
empty()) {
558 std::string
const &key()
const override
560 static const std::string
keystring =
"interpolation0d";
566 elem[
"type"] << key();
567 elem[
"interpolationCodes"].fill_seq(
fip->interpolationCodes());
570 elem[
"high"].fill_seq(
fip->high(),
fip->variables().size());
571 elem[
"low"].fill_seq(
fip->low(),
fip->variables().size());
578 std::string
const &key()
const override
580 static const std::string
keystring =
"interpolation";
586 elem[
"type"] << key();
587 elem[
"interpolationCodes"].fill_seq(
pip->interpolationCodes());
588 elem[
"positiveDefinite"] <<
pip->positiveDefinite();
590 elem[
"nom"] <<
pip->nominalHist()->GetName();
609 pip.setPositiveDefinite(
p[
"positiveDefinite"].val_bool());
611 if (
p.has_child(
"interpolationCodes")) {
613 for (
auto const &node :
p[
"interpolationCodes"].children()) {
614 pip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int(),
true);
628 if (!
p.has_child(
"high")) {
631 if (!
p.has_child(
"low")) {
634 if (!
p.has_child(
"nom")) {
638 double nom(
p[
"nom"].val_double());
642 std::vector<double> high;
645 std::vector<double> low;
648 if (vars.size() != low.size() || vars.size() != high.size()) {
650 "' has non-matching lengths of 'vars', 'high' and 'low'!");
655 if (
p.has_child(
"interpolationCodes")) {
657 for (
auto const &node :
p[
"interpolationCodes"].children()) {
658 fip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int());
679 std::string
name =
"";
683 int interpolationCode = 4;
688 :
name(
n), param(
p), low(
l), high(
h), interpolationCode(i), constraint(
c), constraintType(
c->
IsA())
696 std::vector<double> low;
697 std::vector<double> high;
701 :
name(
n), param(
p), constraint(
c), constraintType(
c->
IsA())
703 low.assign(
l->dataHist().weightArray(),
l->dataHist().weightArray() +
l->dataHist().numEntries());
704 high.assign(
h->dataHist().weightArray(),
h->dataHist().weightArray() +
h->dataHist().numEntries());
709 std::vector<double> constraints;
710 std::vector<RooAbsReal *> parameters;
716struct GenericElement {
725 size_t end = s.size();
727 while (start < end && s[start] ==
'(' && s[end - 1] ==
')') {
730 for (
size_t i = start; i < end - 1; ++i) {
733 else if (s[i] ==
')')
735 if (
depth == 0 && i < end - 1) {
747 return s.substr(start, end - start);
752 std::vector<std::string>
parts;
757 for (
size_t i = 0; i <
expr.size(); ++i) {
761 }
else if (
c ==
')') {
763 }
else if (
c ==
'*' &&
depth == 0) {
765 std::string sub =
expr.substr(start, i - start);
775 std::string sub =
expr.substr(start);
782 static const std::regex pattern(
783 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*$)");
789 if (std::regex_match(s, match, pattern)) {
790 if (match[1].str() ==
"-") {
794 std::string
token2 = match[2].str();
795 std::string
token3 = match[4].str();
806 sys.name =
p2->GetName();
811 sys.name =
p3->GetName();
816 sys.name =
v2->GetName();
818 sys.high =
sign *
p3->getVal();
819 sys.low = -
sign *
p3->getVal();
821 sys.name =
v3->GetName();
823 sys.high =
sign *
p2->getVal();
824 sys.low = -
sign *
p2->getVal();
828 sys.interpolationCode = 1;
837 if (
auto prod =
dynamic_cast<RooProduct *
>(arg)) {
838 for (
const auto &
e : prod->components()) {
848 for (
auto *var : list) {
858 std::vector<double> hist;
859 std::vector<double> histError;
860 std::vector<NormFactor> normfactors;
861 std::vector<NormSys> normsys;
862 std::vector<HistoSys> histosys;
863 std::vector<ShapeSys> shapesys;
864 std::vector<GenericElement> tmpElements;
865 std::vector<GenericElement> otherElements;
866 bool useBarlowBeestonLight =
false;
867 std::vector<RooAbsReal *> staterrorParameters;
876 for (
RooAbsArg const *pdf : ws->allPdfs()) {
877 if (
auto gauss =
dynamic_cast<RooGaussian const *
>(pdf)) {
878 if (
parname == gauss->getX().GetName()) {
879 sample.normfactors.emplace_back(*par, gauss);
885 sample.normfactors.emplace_back(*par);
896 std::vector<Sample> samples;
897 std::map<int, double> tot_yield;
898 std::map<int, double> tot_yield2;
899 std::map<int, double> rel_errors;
901 long unsigned int nBins = 0;
916 std::vector<ParamHistFunc *>
phfs;
926 if (channel.varSet ==
nullptr) {
927 channel.varSet = dataHist.get();
928 channel.nBins = dataHist.numEntries();
930 if (
sample.hist.empty()) {
931 auto *
w = dataHist.weightArray();
932 sample.hist.assign(
w,
w + dataHist.numEntries());
949 }
else if (
auto par =
dynamic_cast<RooRealVar *
>(
e)) {
958 for (
size_t i = 0; i <
fip->variables().size(); ++i) {
967 fip->interpolationCodes()[i], constraint);
978 expression.ReplaceAll((
"x[" + std::to_string(i) +
"]").c_str(),
p->GetName());
979 expression.ReplaceAll((
"@" + std::to_string(i)).c_str(),
p->GetName());
982 if (components.size() == 0) {
984 sample.otherElements.push_back(formula);
987 std::vector<RooAbsArg *> realComponents;
989 for (
auto &
comp : components) {
993 realComponents.push_back(
part);
999 sample.normsys.emplace_back(std::move(normsys));
1004 std::string
name = std::string(formula->
GetName()) +
"_part" + std::to_string(idx);
1007 sample.tmpElements.push_back({var});
1035 for (
size_t i = 0; i <
pip->paramList().
size(); ++i) {
1039 if (
auto lo =
dynamic_cast<RooHistFunc *
>(
pip->lowList().at(i))) {
1056 for (
const auto &
g :
phf->paramList()) {
1060 if (channel.tot_yield.find(idx) == channel.tot_yield.end()) {
1061 channel.tot_yield[idx] = 0;
1062 channel.tot_yield2[idx] = 0;
1064 channel.tot_yield[idx] +=
sample.hist[idx - 1];
1065 channel.tot_yield2[idx] += (
sample.hist[idx - 1] *
sample.hist[idx - 1]);
1067 sample.barlowBeestonLightConstraintType = constraint->
IsA();
1070 channel.rel_errors[idx] =
erel;
1073 channel.rel_errors[idx] =
erel;
1076 "currently, only RooPoisson and RooGaussian are supported as constraint types");
1080 sample.useBarlowBeestonLight =
true;
1087 for (
const auto &
g :
phf->paramList()) {
1088 sys.parameters.push_back(
static_cast<RooRealVar *
>(
g));
1094 if (!constraint && !
g->isConstant()) {
1101 sys.constraints.push_back(0.0);
1104 if (!sys.constraint) {
1109 if (!sys.constraint) {
1114 sample.shapesys.emplace_back(std::move(sys));
1120 channel.samples.emplace_back(std::move(
sample));
1129 for (
auto &
sample : channel.samples) {
1130 if (
sample.useBarlowBeestonLight) {
1132 for (
auto bin : channel.rel_errors) {
1135 const int i = bin.first;
1137 const double count =
sample.hist[i - 1];
1140 sample.histError[i - 1] =
1152 if (sys.constraint) {
1153 mod[
"constraint_name"] << sys.constraint->GetName();
1154 }
else if (sys.constraintType) {
1155 mod[
"constraint_type"] <<
toString(sys.constraintType);
1160 for (
const auto &
sample : channel.samples) {
1162 elem[
"type"] <<
"histfactory_dist";
1169 for (
const auto &
nf :
sample.normfactors) {
1172 mod[
"name"] <<
nf.name;
1173 mod[
"parameter"] <<
nf.param->GetName();
1174 mod[
"type"] <<
"normfactor";
1175 if (
nf.constraint) {
1176 mod[
"constraint_name"] <<
nf.constraint->GetName();
1177 tool->queueExport(*
nf.constraint);
1181 for (
const auto &sys :
sample.normsys) {
1184 mod[
"name"] << sys.name;
1185 mod[
"type"] <<
"normsys";
1186 mod[
"parameter"] << sys.param->GetName();
1187 if (sys.interpolationCode != 4) {
1188 mod[
"interpolation"] << sys.interpolationCode;
1191 auto &
data =
mod[
"data"].set_map();
1192 data[
"lo"] << sys.low;
1193 data[
"hi"] << sys.high;
1196 for (
const auto &sys :
sample.histosys) {
1199 mod[
"name"] << sys.name;
1200 mod[
"type"] <<
"histosys";
1201 mod[
"parameter"] << sys.param->GetName();
1203 auto &
data =
mod[
"data"].set_map();
1204 if (channel.nBins != sys.low.size() || channel.nBins != sys.high.size()) {
1205 std::stringstream
ss;
1206 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " << sys.low.size() <<
"/"
1207 << sys.high.size() <<
" found in nominal histogram errors!";
1214 for (
const auto &sys :
sample.shapesys) {
1217 mod[
"name"] << sys.name;
1218 mod[
"type"] <<
"shapesys";
1221 auto &vals =
mod[
"data"].set_map()[
"vals"];
1222 if (sys.constraint || sys.constraintType) {
1223 vals.fill_seq(sys.constraints);
1225 vals.fill_seq(std::vector<double>(sys.parameters.size(), 0.0));
1233 mod[
"type"] <<
"custom";
1239 mod[
"type"] <<
"custom";
1242 if (
sample.useBarlowBeestonLight) {
1245 mod[
"name"] << ::Literals::staterror;
1246 mod[
"type"] << ::Literals::staterror;
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;
1425 constraints.push_back(pdf);
1434 std::string
const &key()
const override
1436 static const std::string
keystring =
"histfactory_dist";
1447 bool autoExportDependants()
const override {
return false; }
1450 std::vector<RooAbsPdf *> constraints;
1453 std::string
const &key()
const override
1455 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
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.
A real-valued function sampled from a multidimensional histogram.
RooAbsReal const & getMean() const
Get the mean parameter.
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)
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)