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) {
522 for (
const auto &
comp :
p[
"samples"].children()) {
531 if (constraints.
empty()) {
546 std::string
const &key()
const override
548 static const std::string
keystring =
"interpolation0d";
554 elem[
"type"] << key();
555 elem[
"interpolationCodes"].fill_seq(
fip->interpolationCodes());
558 elem[
"high"].fill_seq(
fip->high(),
fip->variables().size());
559 elem[
"low"].fill_seq(
fip->low(),
fip->variables().size());
566 std::string
const &key()
const override
568 static const std::string
keystring =
"interpolation";
574 elem[
"type"] << key();
575 elem[
"interpolationCodes"].fill_seq(
pip->interpolationCodes());
576 elem[
"positiveDefinite"] <<
pip->positiveDefinite();
578 elem[
"nom"] <<
pip->nominalHist()->GetName();
597 pip.setPositiveDefinite(
p[
"positiveDefinite"].val_bool());
599 if (
p.has_child(
"interpolationCodes")) {
601 for (
auto const &node :
p[
"interpolationCodes"].children()) {
602 pip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int(),
true);
616 if (!
p.has_child(
"high")) {
619 if (!
p.has_child(
"low")) {
622 if (!
p.has_child(
"nom")) {
626 double nom(
p[
"nom"].val_double());
630 std::vector<double> high;
633 std::vector<double> low;
636 if (vars.size() != low.size() || vars.size() != high.size()) {
638 "' has non-matching lengths of 'vars', 'high' and 'low'!");
643 if (
p.has_child(
"interpolationCodes")) {
645 for (
auto const &node :
p[
"interpolationCodes"].children()) {
646 fip.setInterpCode(*
static_cast<RooAbsReal *
>(vars.at(i)), node.val_int());
667 std::string
name =
"";
671 int interpolationCode = 4;
676 :
name(
n), param(
p), low(
l), high(
h), interpolationCode(i), constraint(
c), constraintType(
c->
IsA())
684 std::vector<double> low;
685 std::vector<double> high;
689 :
name(
n), param(
p), constraint(
c), constraintType(
c->
IsA())
691 low.assign(
l->dataHist().weightArray(),
l->dataHist().weightArray() +
l->dataHist().numEntries());
692 high.assign(
h->dataHist().weightArray(),
h->dataHist().weightArray() +
h->dataHist().numEntries());
697 std::vector<double> constraints;
698 std::vector<RooAbsReal *> parameters;
704struct GenericElement {
713 size_t end = s.size();
715 while (start < end && s[start] ==
'(' && s[end - 1] ==
')') {
718 for (
size_t i = start; i < end - 1; ++i) {
721 else if (s[i] ==
')')
723 if (
depth == 0 && i < end - 1) {
735 return s.substr(start, end - start);
740 std::vector<std::string>
parts;
745 for (
size_t i = 0; i <
expr.size(); ++i) {
749 }
else if (
c ==
')') {
751 }
else if (
c ==
'*' &&
depth == 0) {
753 std::string sub =
expr.substr(start, i - start);
763 std::string sub =
expr.substr(start);
776 static const std::regex pattern(
777 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*$)");
783 if (std::regex_match(s, match, pattern)) {
784 if (match[1].str() ==
"-") {
788 std::string
token2 = match[2].str();
789 std::string
token3 = match[4].str();
800 sys.name =
p2->GetName();
805 sys.name =
p3->GetName();
810 sys.name =
v2->GetName();
812 sys.high =
sign *
p3->getVal();
813 sys.low = -
sign *
p3->getVal();
815 sys.name =
v3->GetName();
817 sys.high =
sign *
p2->getVal();
818 sys.low = -
sign *
p2->getVal();
822 sys.interpolationCode = 1;
831 if (
auto prod =
dynamic_cast<RooProduct *
>(arg)) {
832 for (
const auto &
e : prod->components()) {
842 for (
auto *var : list) {
852 std::vector<double> hist;
853 std::vector<double> histError;
854 std::vector<NormFactor> normfactors;
855 std::vector<NormSys> normsys;
856 std::vector<HistoSys> histosys;
857 std::vector<ShapeSys> shapesys;
858 std::vector<GenericElement> tmpElements;
859 std::vector<GenericElement> otherElements;
860 bool useBarlowBeestonLight =
false;
861 std::vector<RooAbsReal *> staterrorParameters;
870 for (
RooAbsArg const *pdf : ws->allPdfs()) {
871 if (
auto gauss =
dynamic_cast<RooGaussian const *
>(pdf)) {
872 if (
parname == gauss->getX().GetName()) {
873 sample.normfactors.emplace_back(*par, gauss);
879 sample.normfactors.emplace_back(*par);
890 std::vector<Sample> samples;
891 std::map<int, double> tot_yield;
892 std::map<int, double> tot_yield2;
893 std::map<int, double> rel_errors;
895 long unsigned int nBins = 0;
910 std::vector<ParamHistFunc *>
phfs;
920 if (channel.varSet ==
nullptr) {
921 channel.varSet = dataHist.get();
922 channel.nBins = dataHist.numEntries();
924 if (
sample.hist.empty()) {
925 auto *
w = dataHist.weightArray();
926 sample.hist.assign(
w,
w + dataHist.numEntries());
943 }
else if (
auto par =
dynamic_cast<RooRealVar *
>(
e)) {
952 for (
size_t i = 0; i <
fip->variables().size(); ++i) {
961 fip->interpolationCodes()[i], constraint);
972 expression.ReplaceAll((
"x[" + std::to_string(i) +
"]").c_str(),
p->GetName());
973 expression.ReplaceAll((
"@" + std::to_string(i)).c_str(),
p->GetName());
976 if (components.size() == 0) {
978 sample.otherElements.push_back(formula);
981 std::vector<RooAbsArg *> realComponents;
983 for (
auto &
comp : components) {
987 realComponents.push_back(
part);
993 sample.normsys.emplace_back(std::move(normsys));
998 std::string
name = std::string(formula->
GetName()) +
"_part" + std::to_string(idx);
1001 sample.tmpElements.push_back({var});
1029 for (
size_t i = 0; i <
pip->paramList().
size(); ++i) {
1033 if (
auto lo =
dynamic_cast<RooHistFunc *
>(
pip->lowList().at(i))) {
1050 for (
const auto &
g :
phf->paramList()) {
1054 if (channel.tot_yield.find(idx) == channel.tot_yield.end()) {
1055 channel.tot_yield[idx] = 0;
1056 channel.tot_yield2[idx] = 0;
1058 channel.tot_yield[idx] +=
sample.hist[idx - 1];
1059 channel.tot_yield2[idx] += (
sample.hist[idx - 1] *
sample.hist[idx - 1]);
1061 sample.barlowBeestonLightConstraintType = constraint->
IsA();
1064 channel.rel_errors[idx] =
erel;
1067 channel.rel_errors[idx] =
erel;
1070 "currently, only RooPoisson and RooGaussian are supported as constraint types");
1074 sample.useBarlowBeestonLight =
true;
1081 for (
const auto &
g :
phf->paramList()) {
1082 sys.parameters.push_back(
static_cast<RooRealVar *
>(
g));
1088 if (!constraint && !
g->isConstant()) {
1095 sys.constraints.push_back(0.0);
1097 sys.constraints.push_back(1. / std::sqrt(
constraint_p->getX().getVal()));
1098 if (!sys.constraint) {
1103 if (!sys.constraint) {
1108 sample.shapesys.emplace_back(std::move(sys));
1114 channel.samples.emplace_back(std::move(
sample));
1123 for (
auto &
sample : channel.samples) {
1124 if (
sample.useBarlowBeestonLight) {
1126 for (
auto bin : channel.rel_errors) {
1129 const int i = bin.first;
1131 const double count =
sample.hist[i - 1];
1134 sample.histError[i - 1] =
1146 if (sys.constraint) {
1147 mod[
"constraint_name"] << sys.constraint->GetName();
1148 }
else if (sys.constraintType) {
1149 mod[
"constraint_type"] <<
toString(sys.constraintType);
1154 for (
const auto &
sample : channel.samples) {
1156 elem[
"type"] <<
"histfactory_dist";
1163 for (
const auto &
nf :
sample.normfactors) {
1166 mod[
"name"] <<
nf.name;
1167 mod[
"parameter"] <<
nf.param->GetName();
1168 mod[
"type"] <<
"normfactor";
1169 if (
nf.constraint) {
1170 mod[
"constraint_name"] <<
nf.constraint->GetName();
1171 tool->queueExport(*
nf.constraint);
1175 for (
const auto &sys :
sample.normsys) {
1178 mod[
"name"] << sys.name;
1179 mod[
"type"] <<
"normsys";
1180 mod[
"parameter"] << sys.param->GetName();
1181 if (sys.interpolationCode != 4) {
1182 mod[
"interpolation"] << sys.interpolationCode;
1185 auto &
data =
mod[
"data"].set_map();
1186 data[
"lo"] << sys.low;
1187 data[
"hi"] << sys.high;
1190 for (
const auto &sys :
sample.histosys) {
1193 mod[
"name"] << sys.name;
1194 mod[
"type"] <<
"histosys";
1195 mod[
"parameter"] << sys.param->GetName();
1197 auto &
data =
mod[
"data"].set_map();
1198 if (channel.nBins != sys.low.size() || channel.nBins != sys.high.size()) {
1199 std::stringstream
ss;
1200 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " << sys.low.size() <<
"/"
1201 << sys.high.size() <<
" found in nominal histogram errors!";
1208 for (
const auto &sys :
sample.shapesys) {
1211 mod[
"name"] << sys.name;
1212 mod[
"type"] <<
"shapesys";
1215 auto &vals =
mod[
"data"].set_map()[
"vals"];
1216 if (sys.constraint || sys.constraintType) {
1217 vals.fill_seq(sys.constraints);
1219 vals.fill_seq(std::vector<double>(sys.parameters.size(), 0.0));
1227 mod[
"type"] <<
"custom";
1233 mod[
"type"] <<
"custom";
1236 if (
sample.useBarlowBeestonLight) {
1239 mod[
"name"] << ::Literals::staterror;
1240 mod[
"type"] << ::Literals::staterror;
1248 auto &out =
output.append_child().set_map();
1251 out[
"name"] <<
name;
1256 auto &
dataNode = s[
"data"].set_map();
1257 if (channel.nBins !=
sample.hist.size()) {
1258 std::stringstream
ss;
1259 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.hist.size()
1260 <<
" found in nominal histogram!";
1264 if (!
sample.histError.empty()) {
1265 if (channel.nBins !=
sample.histError.size()) {
1266 std::stringstream
ss;
1267 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.histError.size()
1268 <<
" found in nominal histogram errors!";
1281 std::set<const RooAbsReal *> vars;
1282 for (
const auto &
sample : channel.samples) {
1283 for (
const auto &
nf :
sample.normfactors) {
1284 vars.insert(
nf.param);
1286 for (
const auto &sys :
sample.normsys) {
1287 vars.insert(sys.param);
1290 for (
const auto &sys :
sample.histosys) {
1291 vars.insert(sys.param);
1293 for (
const auto &sys :
sample.shapesys) {
1294 for (
const auto &par : sys.parameters) {
1298 if (
sample.useBarlowBeestonLight) {
1299 for (
const auto &par :
sample.staterrorParameters) {
1307 for (
auto *pdf : constraints) {
1309 for (
const auto *var : vars) {
1310 if (pdf->dependsOn(*var)) {
1328 std::cout <<
pdfname <<
" is not a sumpdf" << std::endl;
1336 std::cout <<
"sample " <<
sample->GetName() <<
" is no RooProduct or RooRealSumPdf in " <<
pdfname
1345 if (channel.samples.size() == 0)
1347 for (
auto &
sample : channel.samples) {
1348 if (
sample.hist.empty()) {
1360 "losing constraint term '" + std::string(constraint->
GetName()) +
1361 "', implicit constraints are not supported by HS3 yet! The term will appear in the HS3 file, but will not be "
1362 "picked up when creating a likelihood from it! You will have to add it manually as an external constraint.");
1363 tool->queueExport(*constraint);
1367 for (
const auto &
sample : channel.samples) {
1386 for (
const auto &
sample : channel.samples) {
1397 sumpdf->getParameters(channel.varSet, parameters);
1401 tool->queueExport(*param);
1410 bool autoExportDependants()
const override {
return false; }
1413 std::vector<RooAbsPdf *> constraints;
1424 constraints.push_back(pdf);
1433 std::string
const &key()
const override
1435 static const std::string
keystring =
"histfactory_dist";
1446 bool autoExportDependants()
const override {
return false; }
1449 std::vector<RooAbsPdf *> constraints;
1452 std::string
const &key()
const override
1454 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)