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);
770 static const std::regex pattern(
771 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*$)");
777 if (std::regex_match(s, match, pattern)) {
778 if (match[1].str() ==
"-") {
782 std::string
token2 = match[2].str();
783 std::string
token3 = match[4].str();
794 sys.name =
p2->GetName();
799 sys.name =
p3->GetName();
804 sys.name =
v2->GetName();
806 sys.high =
sign *
p3->getVal();
807 sys.low = -
sign *
p3->getVal();
809 sys.name =
v3->GetName();
811 sys.high =
sign *
p2->getVal();
812 sys.low = -
sign *
p2->getVal();
816 sys.interpolationCode = 1;
825 if (
auto prod =
dynamic_cast<RooProduct *
>(arg)) {
826 for (
const auto &
e : prod->components()) {
836 for (
auto *var : list) {
846 std::vector<double> hist;
847 std::vector<double> histError;
848 std::vector<NormFactor> normfactors;
849 std::vector<NormSys> normsys;
850 std::vector<HistoSys> histosys;
851 std::vector<ShapeSys> shapesys;
852 std::vector<GenericElement> tmpElements;
853 std::vector<GenericElement> otherElements;
854 bool useBarlowBeestonLight =
false;
855 std::vector<RooAbsReal *> staterrorParameters;
864 for (
RooAbsArg const *pdf : ws->allPdfs()) {
865 if (
auto gauss =
dynamic_cast<RooGaussian const *
>(pdf)) {
866 if (
parname == gauss->getX().GetName()) {
867 sample.normfactors.emplace_back(*par, gauss);
873 sample.normfactors.emplace_back(*par);
884 std::vector<Sample> samples;
885 std::map<int, double> tot_yield;
886 std::map<int, double> tot_yield2;
887 std::map<int, double> rel_errors;
889 long unsigned int nBins = 0;
904 std::vector<ParamHistFunc *>
phfs;
914 if (channel.varSet ==
nullptr) {
915 channel.varSet = dataHist.get();
916 channel.nBins = dataHist.numEntries();
918 if (
sample.hist.empty()) {
919 auto *
w = dataHist.weightArray();
920 sample.hist.assign(
w,
w + dataHist.numEntries());
937 }
else if (
auto par =
dynamic_cast<RooRealVar *
>(
e)) {
946 for (
size_t i = 0; i <
fip->variables().size(); ++i) {
955 fip->interpolationCodes()[i], constraint);
966 expression.ReplaceAll((
"x[" + std::to_string(i) +
"]").c_str(),
p->GetName());
967 expression.ReplaceAll((
"@" + std::to_string(i)).c_str(),
p->GetName());
970 if (components.size() == 0) {
972 sample.otherElements.push_back(formula);
975 std::vector<RooAbsArg *> realComponents;
977 for (
auto &
comp : components) {
981 realComponents.push_back(
part);
987 sample.normsys.emplace_back(std::move(normsys));
992 std::string
name = std::string(formula->
GetName()) +
"_part" + std::to_string(idx);
995 sample.tmpElements.push_back({var});
1023 for (
size_t i = 0; i <
pip->paramList().
size(); ++i) {
1027 if (
auto lo =
dynamic_cast<RooHistFunc *
>(
pip->lowList().at(i))) {
1044 for (
const auto &
g :
phf->paramList()) {
1048 if (channel.tot_yield.find(idx) == channel.tot_yield.end()) {
1049 channel.tot_yield[idx] = 0;
1050 channel.tot_yield2[idx] = 0;
1052 channel.tot_yield[idx] +=
sample.hist[idx - 1];
1053 channel.tot_yield2[idx] += (
sample.hist[idx - 1] *
sample.hist[idx - 1]);
1055 sample.barlowBeestonLightConstraintType = constraint->
IsA();
1058 channel.rel_errors[idx] =
erel;
1061 channel.rel_errors[idx] =
erel;
1064 "currently, only RooPoisson and RooGaussian are supported as constraint types");
1068 sample.useBarlowBeestonLight =
true;
1075 for (
const auto &
g :
phf->paramList()) {
1076 sys.parameters.push_back(
static_cast<RooRealVar *
>(
g));
1082 if (!constraint && !
g->isConstant()) {
1089 sys.constraints.push_back(0.0);
1091 sys.constraints.push_back(1. / std::sqrt(
constraint_p->getX().getVal()));
1092 if (!sys.constraint) {
1097 if (!sys.constraint) {
1102 sample.shapesys.emplace_back(std::move(sys));
1108 channel.samples.emplace_back(std::move(
sample));
1117 for (
auto &
sample : channel.samples) {
1118 if (
sample.useBarlowBeestonLight) {
1120 for (
auto bin : channel.rel_errors) {
1123 const int i = bin.first;
1125 const double count =
sample.hist[i - 1];
1128 sample.histError[i - 1] =
1140 if (sys.constraint) {
1141 mod[
"constraint_name"] << sys.constraint->GetName();
1142 }
else if (sys.constraintType) {
1143 mod[
"constraint_type"] <<
toString(sys.constraintType);
1148 for (
const auto &
sample : channel.samples) {
1150 elem[
"type"] <<
"histfactory_dist";
1157 for (
const auto &
nf :
sample.normfactors) {
1160 mod[
"name"] <<
nf.name;
1161 mod[
"parameter"] <<
nf.param->GetName();
1162 mod[
"type"] <<
"normfactor";
1163 if (
nf.constraint) {
1164 mod[
"constraint_name"] <<
nf.constraint->GetName();
1165 tool->queueExport(*
nf.constraint);
1169 for (
const auto &sys :
sample.normsys) {
1172 mod[
"name"] << sys.name;
1173 mod[
"type"] <<
"normsys";
1174 mod[
"parameter"] << sys.param->GetName();
1175 if (sys.interpolationCode != 4) {
1176 mod[
"interpolation"] << sys.interpolationCode;
1179 auto &
data =
mod[
"data"].set_map();
1180 data[
"lo"] << sys.low;
1181 data[
"hi"] << sys.high;
1184 for (
const auto &sys :
sample.histosys) {
1187 mod[
"name"] << sys.name;
1188 mod[
"type"] <<
"histosys";
1189 mod[
"parameter"] << sys.param->GetName();
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";
1209 auto &vals =
mod[
"data"].set_map()[
"vals"];
1210 if (sys.constraint || sys.constraintType) {
1211 vals.fill_seq(sys.constraints);
1213 vals.fill_seq(std::vector<double>(sys.parameters.size(), 0.0));
1221 mod[
"type"] <<
"custom";
1227 mod[
"type"] <<
"custom";
1230 if (
sample.useBarlowBeestonLight) {
1233 mod[
"name"] << ::Literals::staterror;
1234 mod[
"type"] << ::Literals::staterror;
1242 auto &out =
output.append_child().set_map();
1245 out[
"name"] <<
name;
1250 auto &
dataNode = s[
"data"].set_map();
1251 if (channel.nBins !=
sample.hist.size()) {
1252 std::stringstream
ss;
1253 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.hist.size()
1254 <<
" found in nominal histogram!";
1258 if (!
sample.histError.empty()) {
1259 if (channel.nBins !=
sample.histError.size()) {
1260 std::stringstream
ss;
1261 ss <<
"inconsistent binning: " << channel.nBins <<
" bins expected, but " <<
sample.histError.size()
1262 <<
" found in nominal histogram errors!";
1275 std::set<const RooAbsReal *> vars;
1276 for (
const auto &
sample : channel.samples) {
1277 for (
const auto &
nf :
sample.normfactors) {
1278 vars.insert(
nf.param);
1280 for (
const auto &sys :
sample.normsys) {
1281 vars.insert(sys.param);
1284 for (
const auto &sys :
sample.histosys) {
1285 vars.insert(sys.param);
1287 for (
const auto &sys :
sample.shapesys) {
1288 for (
const auto &par : sys.parameters) {
1292 if (
sample.useBarlowBeestonLight) {
1293 for (
const auto &par :
sample.staterrorParameters) {
1301 for (
auto *pdf : constraints) {
1303 for (
const auto *var : vars) {
1304 if (pdf->dependsOn(*var)) {
1322 std::cout <<
pdfname <<
" is not a sumpdf" << std::endl;
1330 std::cout <<
"sample " <<
sample->GetName() <<
" is no RooProduct or RooRealSumPdf in " <<
pdfname
1339 if (channel.samples.size() == 0)
1341 for (
auto &
sample : channel.samples) {
1342 if (
sample.hist.empty()) {
1354 "losing constraint term '" + std::string(constraint->
GetName()) +
1355 "', implicit constraints are not supported by HS3 yet! The term will appear in the HS3 file, but will not be "
1356 "picked up when creating a likelihood from it! You will have to add it manually as an external constraint.");
1357 tool->queueExport(*constraint);
1361 for (
const auto &
sample : channel.samples) {
1380 for (
const auto &
sample : channel.samples) {
1391 sumpdf->getParameters(channel.varSet, parameters);
1395 tool->queueExport(*param);
1404 bool autoExportDependants()
const override {
return false; }
1407 std::vector<RooAbsPdf *> constraints;
1417 constraints.push_back(pdf);
1426 std::string
const &key()
const override
1428 static const std::string
keystring =
"histfactory_dist";
1439 bool autoExportDependants()
const override {
return false; }
1442 std::vector<RooAbsPdf *> constraints;
1445 std::string
const &key()
const override
1447 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)