45 if (
name ==
nullptr || strlen(
name) == 0) {
58 fPars->addClone(*std::unique_ptr<RooAbsCollection>(
result->GetParameters()));
60 for (
auto p : *
fPars) {
64 spaceSize *= (
v->getMax() -
v->getMin());
66 for (
int i = 0; i <
result->ArraySize(); i++) {
68 double xVal =
result->GetXValue(i);
69 double ssize = spaceSize;
70 for (
auto p : *
fPars) {
74 ssize /= (
v->getMax() -
v->getMin());
75 double remain = std::fmod(xVal, ssize);
76 v->setVal((xVal - remain) / ssize);
82 for (
auto &p : *
this) {
83 for (
auto a : *p.coords) {
84 if (!
fPars->find(
a->GetName()))
101 std::shared_ptr<xRooNode> out =
nullptr;
103 for (
auto &[_range, _pdf] :
fPdfs) {
106 bool collision =
true;
107 for (
auto &_lhs : *_range) {
108 auto _rhs = rhs.
find(*_lhs);
113 if (!(
v->getMin() <=
v2->getMax() &&
v2->getMin() <=
v->getMax())) {
118 if (!(
v->getMin() <=
c2->getVal() &&
c2->getVal() <=
v->getMax())) {
125 if (!(
c->getVal() <=
v2->getMax() &&
v2->getMin() <=
c->getVal())) {
130 if (!(
c->getVal() ==
c2->getVal())) {
139 throw std::runtime_error(
"Multiple pdf possibilities");
157 auto _idx = s.
Index(
'=');
166 _idx = _val.
Index(
',');
185 throw std::runtime_error(
"Unknown parameter");
186 _par->setAttribute(
"axis");
188 if (low < _par->getMin()) {
189 Warning(
"AddPoints",
"low edge of hypoSpace %g below lower bound of parameter: %g. Changing to lower bound", low,
191 low = _par->getMin();
193 if (high > _par->getMax()) {
194 Warning(
"AddPoints",
"high edge of hypoSpace %g above upper bound of parameter: %g. Changing to upper bound",
195 high, _par->getMax());
196 high = _par->getMax();
200 _par->setVal((high + low) * 0.5);
205 double step = (high - low) / (nPoints - 1);
207 throw std::runtime_error(
"Invalid steps");
209 for (
size_t i = 0; i < nPoints; i++) {
210 _par->setVal((i == nPoints - 1) ? high : (low + step * i));
218 if (
axes().empty()) {
221 throw std::runtime_error(
"No POI to scan");
223 poi().first()->setAttribute(
"axis");
229 poi().setAttribAll(
"poi",
false);
230 axes().setAttribAll(
"poi");
237 const std::vector<double> &nSigmas,
double relUncert)
245 throw std::runtime_error(
"scan type must be equal to one of: plr, cls, ts, pnull");
249 if (
axes().empty()) {
252 throw std::runtime_error(
"No POI to scan");
254 poi().first()->setAttribute(
"axis");
259 poi().setAttribAll(
"poi",
false);
260 axes().setAttribAll(
"poi");
268 if (empty() && relUncert == std::numeric_limits<double>::infinity()) {
270 ::Info(
"xRooHypoSpace::scan",
"Using default precision of 10%% for auto-scan");
273 for (
auto a :
axes()) {
274 if (!
a->hasRange(
"physical")) {
275 ::Info(
"xRooHypoSpace::scan",
"No physical range set for %s, setting to [0,inf]", p->GetName());
276 dynamic_cast<RooRealVar *
>(
a)->setRange(
"physical", 0, std::numeric_limits<double>::infinity());
278 if (!
a->getStringAttribute(
"altVal") || !strlen(p->getStringAttribute(
"altVal"))) {
279 ::Info(
"xRooHypoSpace::scan",
"No altVal set for %s, setting to 0",
a->GetName());
280 a->setStringAttribute(
"altVal",
"0");
283 double altVal =
TString(
a->getStringAttribute(
"altVal")).
Atof();
285 if (
v->getMin() >= altVal) {
286 ::Info(
"xRooHypoSpace::scan",
"range of POI does not straddle alt value, adjusting minimum to %g",
288 v->setMin(altVal - 1
e-5);
290 if (
v->getMax() <= altVal) {
291 ::Info(
"xRooHypoSpace::scan",
"range of POI does not straddle alt value, adjusting maximum to %g",
293 v->setMax(altVal + 1
e-5);
296 if (
auto _v =
dynamic_cast<RooRealVar *
>(nll->pars()->find(*
a))) {
297 _v->setRange(
v->getMin(),
v->getMax());
311 if (!
a->getStringAttribute(
"altVal") || !strlen(p->getStringAttribute(
"altVal"))) {
312 ::Info(
"xRooHypoSpace::scan",
"No altVal set for %s, setting to 1",
a->GetName());
313 a->setStringAttribute(
"altVal",
"1");
318 if ( (high == low && nPoints != 1)) {
320 low = p->getMin(
"scan");
321 high = p->getMax(
"scan");
323 if (!std::isnan(low) && !std::isnan(high) && !(std::isinf(low) && std::isinf(high))) {
324 p->setRange(
"scan", std::min(low, high), std::max(low, high));
326 if (p->hasRange(
"scan")) {
327 ::Info(
"xRooHypoSpace::scan",
"Using %s scan range: %g - %g", p->GetName(), p->getMin(
"scan"), p->getMax(
"scan"));
331 for (
auto nSigma : nSigmas) {
332 if (std::isnan(nSigma)) {
341 relUncert = std::numeric_limits<double>::infinity();
350#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 26, 00)
370 if (
auto myDb =
dynamic_cast<TMemFile *
>(fFitDb.get())) {
372 myDb->SetWritable(
true);
388 fFitDb = std::shared_ptr<TDirectory>(
389 new TMemFile(
TString::Format(
"fitDatabase_%s", TUUID().AsString()),
"RECREATE"), [](TDirectory *) {});
401 sType +=
" visualize";
406 for (
double nSigma : nSigmas) {
408 if (std::isnan(nSigma)) {
414 findlimit(
TString::Format(
"%s exp%s%d", sType.
Data(), nSigma > 0 ?
"+" :
"",
int(nSigma)), relUncert);
416 if (std::isnan(res.first) || std::isnan(res.second)) {
418 }
else if (std::isinf(res.second)) {
425 AddPoint(
TString::Format(
"%s=%g", poi().first()->GetName(), poi().getRealValue(poi().first()->GetName())));
427 if (back().status() != 0) {
431 low = std::max(low, back().mu_hat().getVal()-back().mu_hat().getError()*3);
432 high = std::min(high, back().mu_hat().getVal()+back().mu_hat().getError()*3);
434 double step = (high - low) / (nPoints - 1);
435 for (
size_t i = 0; i < nPoints; i++) {
436 AddPoint(
TString::Format(
"%s=%g", poi().first()->GetName(), low + step * i));
438 if (back().status() != 0)
444 throw std::runtime_error(
TString::Format(
"Automatic scanning not yet supported for %s",
type));
449 AddPoint(
TString::Format(
"%s=%g", poi().first()->GetName(), (high + low) / 2.));
451 if (back().status() != 0)
454 double step = (high - low) / (nPoints - 1);
455 for (
size_t i = 0; i < nPoints; i++) {
456 AddPoint(
TString::Format(
"%s=%g", poi().first()->GetName(), low + step * i));
458 if (back().status() != 0)
467 if (
auto myDb =
dynamic_cast<TMemFile *
>(fFitDb.get())) {
469 myDb->SetWritable(
false);
474std::map<std::string, xRooNLLVar::xValueWithError>
481 relUncert = std::numeric_limits<double>::infinity();
484 scan(opt, nSigmas, relUncert);
486 std::map<std::string, xRooNLLVar::xValueWithError> out;
487 for (
auto nSigma : nSigmas) {
488 auto lim =
limit(opt, nSigma);
490 lim.second = -lim.second;
508 auto _idx = s.
Index(
'=');
519 _v->setVal(_val.
Atof());
526 throw std::runtime_error(
"no model at coordinates");
534 fNlls[_pdf] = std::make_shared<xRooNLLVar>(_pdf->nll(
"" , {}));
554 ->
remove(*std::unique_ptr<RooAbsCollection>(out.
coords->selectByAttrib(
"Constant",
false)),
true,
true);
557 double alt_value = out.
fAltVal();
562 if (std::isnan(alt_value)) {
564 }
else if (value >= alt_value) {
574 for (
auto &p : *
this) {
575 if (p.nllVar != out.
nllVar)
577 if (p.fData != out.
fData)
579 if (!p.alt_poi().equals(out.
alt_poi()))
582 for (
auto c : p.alt_poi()) {
596 if (!p.coords->equals(*out.
coords))
598 for (
auto c : *p.coords) {
599 if (
c->getAttribute(
"poi")) {
603 v && std::abs(
v->getVal() - out.
coords->getRealValue(
v->GetName())) > 1
e-12) {
617 if (
auto cfit = p.cfit_alt(
true)) {
620 if (p.asimov(
true) && p.asimov(
true)->fData.first && (!out.
asimov(
true) || !out.
asimov(
true)->fData.first)) {
621 out.
asimov()->fData = p.asimov(
true)->fData;
623 if (!p.poi().equals(out.
poi()))
625 for (
auto c : p.poi()) {
638 std::string coordString;
639 for (
auto a :
axes()) {
643 coordString.erase(coordString.end() - 1);
645 ::Info(
"xRooHypoSpace::AddPoint",
"Added new point @ %s", coordString.c_str());
646 return emplace_back(out);
653 throw std::runtime_error(
"Not a pdf");
659 auto vpars =
toArgs(validity);
661 vpars.remove(
pars,
true,
true);
664 if (
auto existing =
pdf(
pars)) {
665 throw std::runtime_error(std::string(
"Clashing model: ") + existing->GetName());
668 auto myPars = std::shared_ptr<RooArgList>(
dynamic_cast<RooArgList *
>(
pars.snapshot()));
675 fPdfs.insert(std::make_pair(myPars, std::make_shared<xRooNode>(_pdf)));
686 out.
add(*std::unique_ptr<RooAbsCollection>(
687 fPars->selectByAttrib(
"axis",
true)));
693 std::set<std::vector<double>> coords;
694 for (
auto &p : *
this) {
695 std::vector<double> p_coords;
697 auto _v =
dynamic_cast<RooRealVar *
>(p.coords->find(o->GetName()));
699 (_v && _v->isConstant())
701 : std::numeric_limits<double>::infinity());
704 if (coords.find(p_coords) != coords.end()) {
708 coords.insert(p_coords);
713 std::map<std::string, std::unordered_set<double>> values;
714 for (
auto &par : *
pars()) {
717 for (
auto p : *
this) {
718 auto _v =
dynamic_cast<RooRealVar *
>(p.coords->find(par->GetName()));
719 values[par->GetName()].insert(
720 (_v && _v->isConstant())
722 : std::numeric_limits<double>::infinity());
731 for (
auto &[k,
v] : values) {
732 if (
v.size() > maxDiff || (
v.size() == maxDiff && !isPOI &&
pars()->find(k.c_str())->getAttribute(
"poi"))) {
734 isPOI =
pars()->find(k.c_str())->getAttribute(
"poi");
735 maxDiff = std::max(maxDiff,
v.size());
738 if (bestVar.empty()) {
742 out.
add(*
pars()->find(bestVar.c_str()));
758 out.
add(*std::unique_ptr<RooAbsCollection>(
pars()->selectByAttrib(
"poi",
true)));
769 for (
size_t i = 0; i <
size(); i++) {
770 std::cout << i <<
") ";
771 for (
auto a : _axes) {
772 if (
a != _axes.first())
774 std::cout <<
a->GetName() <<
"="
775 << at(i).coords->getRealValue(
a->GetName(), std::numeric_limits<double>::quiet_NaN());
777 std::cout <<
" status=[ufit:";
782 std::cout << ufit->status();
785 std::cout <<
",cfit_null:";
786 auto cfit =
const_cast<xRooHypoPoint &
>(at(i)).cfit_null(
true);
790 std::cout << cfit->status();
793 std::cout <<
",cfit_alt:";
794 auto afit =
const_cast<xRooHypoPoint &
>(at(i)).cfit_alt(
true);
798 std::cout << afit->status();
801 if (
auto asiPoint =
const_cast<xRooHypoPoint &
>(at(i)).asimov(
true)) {
802 std::cout <<
",asimov.ufit:";
803 auto asi_ufit = asiPoint->ufit(
true);
807 std::cout << asi_ufit->status();
810 std::cout <<
",asimov.cfit_null:";
811 auto asi_cfit = asiPoint->cfit_null(
true);
815 std::cout << asi_cfit->status();
818 auto cfit_lbound =
const_cast<xRooHypoPoint &
>(at(i)).cfit_lbound(
true);
821 std::cout <<
",cfit_lbound:" << cfit_lbound->status();
826 auto sigma_mu =
const_cast<xRooHypoPoint &
>(at(i)).sigma_mu(
true);
827 if (!std::isnan(sigma_mu.first)) {
828 std::cout <<
" sigma_mu=" << sigma_mu.first;
830 std::cout <<
" +/- " << sigma_mu.second;
832 std::cout << std::endl;
834 std::cout <<
"--------------------------" << std::endl;
835 std::cout <<
"Number of bad fits: " << badFits << std::endl;
839 const char *opt )
const
846 bool readOnly = sOpt.
Contains(
"readonly");
847 bool visualize = sOpt.
Contains(
"visualize") && !readOnly;
854 : std::numeric_limits<double>::quiet_NaN();
856 !std::isnan(nSigma) && nSigma && !(sOpt(sOpt.
Index(
"exp") + 3) ==
'+' || sOpt(sOpt.
Index(
"exp") + 3) ==
'-');
859 if (_axes.size() != 1)
862 auto out = std::make_shared<TGraphErrors>();
864 out->SetEditable(
false);
865 const char *sCL = (doCLs) ?
"CLs" :
"null";
871 : (!nSigma ?
"Expected"
873 expBand || !nSigma ?
"" : ((nSigma < 0) ?
"-" :
"+"),
int(nSigma))
875 _axes.at(0)->GetTitle(), sCL);
877 if (std::isnan(nSigma)) {
879 out->SetMarkerStyle(20);
880 out->SetMarkerSize(0.5);
882 out->SetNameTitle(
"obs_ts",
TString::Format(
"Observed;%s;%s", _axes.at(0)->GetTitle(),
883 (empty() ?
"" : front().tsTitle(
true).Data())));
886 out->SetNameTitle(
TString::Format(
"exp%d_p%s",
int(nSigma), sCL), title);
887 out->SetMarkerStyle(0);
888 out->SetMarkerSize(0);
889 out->SetLineStyle(2 +
int(nSigma));
890 if (expBand && nSigma) {
893 out->SetLineStyle(0);
894 out->SetLineWidth(0);
895 auto x = out->Clone(
"up");
899 out->GetListOfFunctions()->Add(
x,
"F");
900 x = out->Clone(
"down");
904 out->GetListOfFunctions()->Add(
x,
"F");
908 TString::Format(
"Expected;%s;%s", _axes.at(0)->GetTitle(), front().tsTitle(
true).Data()));
912 auto badPoints = [&]() {
913 auto badPoints2 =
dynamic_cast<TGraph *
>(out->GetListOfFunctions()->
FindObject(
"badPoints"));
917 badPoints2->SetName(
"badPoints");
918 badPoints2->SetMarkerStyle(5);
919 badPoints2->SetMarkerColor(std::isnan(nSigma) ?
kRed :
kBlue);
920 badPoints2->SetMarkerSize(1);
921 out->GetListOfFunctions()->Add(badPoints2,
"P");
930 for (
auto &p : *
this) {
934 auto gra =
graph(sOpt +
" readOnly");
935 if (gra && gra->GetN()) {
937 gROOT->GetSelectedPad()->cd();
940 gra->DrawClone(expBand ?
"AF" :
"ALP")->SetBit(
kCanDelete);
941#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 00)
942 if (
auto pad =
gROOT->GetSelectedPad()) {
943 pad->GetCanvas()->ResetUpdated();
949 ::Info(
"xRooHypoSpace::graph",
"Completed %d/%d points for %s",
int(nDone),
int(
size()), sOpt.
Data());
955 double _x = p.coords->getRealValue(_axes.at(0)->GetName(), std::numeric_limits<double>::quiet_NaN());
957 auto idx = out->GetN() - nPointsDown;
959 if (std::isnan(pval.first)) {
960 if (p.status() != 0) {
961 badPoints()->SetPoint(badPoints()->GetN(), _x, 0);
964 out->InsertPointBefore(idx, _x, pval.first);
965 out->SetPointError(idx, 0, pval.second);
968 if (expBand && nSigma) {
972 if (std::isnan(pval.first)) {
973 if (p.status() != 0) {
974 badPoints()->SetPoint(badPoints()->GetN(), _x, 0);
977 out->InsertPointBefore(idx + 1, _x, pval.first);
978 out->SetPointError(idx + 1, 0, pval.second);
980 if (out->GetPointY(idx) < pval.first)
987 if (out->GetN() == 0)
992 if (out->GetListOfFunctions()->FindObject(
"badPoints")) {
994 for (
int i = 0; i < badPoints()->GetN(); i++) {
995 badPoints()->SetPointY(i, out->Eval(badPoints()->GetPointX(i)));
1000 out->Sort(&
TGraph::CompareX,
false, out->GetN() - nPointsDown, out->GetN() - 1);
1003 auto up =
dynamic_cast<TGraph *
>(out->GetListOfFunctions()->
FindObject(
"up"));
1004 auto down =
dynamic_cast<TGraph *
>(out->GetListOfFunctions()->
FindObject(
"down"));
1006 for (
int i = 0; i < out->GetN(); i++) {
1007 if (i < out->GetN() - nPointsDown) {
1008 up->SetPoint(up->GetN(), out->GetPointX(i), out->GetPointY(i) + out->GetErrorY(i) * (above ? 1. : -1.));
1009 down->SetPoint(down->GetN(), out->GetPointX(i), out->GetPointY(i) - out->GetErrorY(i) * (above ? 1. : -1.));
1011 up->SetPoint(up->GetN(), out->GetPointX(i), out->GetPointY(i) - out->GetErrorY(i) * (above ? 1. : -1.));
1012 down->SetPoint(down->GetN(), out->GetPointX(i), out->GetPointY(i) + out->GetErrorY(i) * (above ? 1. : -1.));
1020 gROOT->GetSelectedPad()->cd();
1023 out->DrawClone(expBand ?
"AF" :
"ALP")->SetBit(
kCanDelete);
1024#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 00)
1025 if (
auto pad =
gROOT->GetSelectedPad()) {
1026 pad->GetCanvas()->ResetUpdated();
1039 std::shared_ptr<TMultiGraph> out;
1042 bool visualize = sOpt.
Contains(
"visualize");
1045 auto exp2 =
graph(sOpt +
" exp2");
1046 auto exp1 =
graph(sOpt +
" exp1");
1047 auto exp =
graph(sOpt +
" exp");
1050 auto obs = (doObs) ?
graph(sOpt) :
nullptr;
1053 if (exp2 && exp2->GetN() > 1)
1054 out->Add(
static_cast<TGraph *
>(exp2->Clone()),
"FP");
1055 if (exp1 && exp1->GetN() > 1)
1056 out->Add(
static_cast<TGraph *
>(exp1->Clone()),
"FP");
1057 if (exp && exp->GetN() > 1)
1058 out->Add(
static_cast<TGraph *
>(exp->Clone()),
"LP");
1059 if (obs && obs->GetN() > 1)
1060 out->Add(
static_cast<TGraph *
>(obs->Clone()),
"LP");
1062 if (!out->GetListOfGraphs()) {
1066 TGraph *testedPoints =
nullptr;
1069 line->SetName(
"alpha");
1070 line->SetLineStyle(2);
1071 line->SetEditable(
false);
1072 line->SetPoint(
line->GetN(), out->GetHistogram()->GetXaxis()->GetXmin() - 10, 0.05);
1073 testedPoints =
new TGraph;
1074 testedPoints->
SetName(
"hypoPoints");
1079 for (
int i = 0; i < exp->GetN(); i++) {
1080 testedPoints->
SetPoint(testedPoints->
GetN(), exp->GetPointX(i), 0.05);
1083 line->SetPoint(
line->GetN(), out->GetHistogram()->GetXaxis()->GetXmax() + 10, 0.05);
1085 out->GetListOfFunctions()->Add(
line,
"L");
1088 out->GetHistogram()->GetXaxis()->SetTitle(exp->GetHistogram()->GetXaxis()->GetTitle());
1089 out->GetHistogram()->GetYaxis()->SetTitle(exp->GetHistogram()->GetYaxis()->GetTitle());
1092 if (out->GetListOfGraphs()->GetEntries() > 1) {
1094 1. -
gStyle->GetPadRightMargin() - 0.05, 1. -
gStyle->GetPadTopMargin() - 0.05);
1095 leg->SetName(
"legend");
1098 out->GetListOfFunctions()->Add(
leg);
1101 for (
auto g : *out->GetListOfGraphs()) {
1102 if (
auto o =
dynamic_cast<TGraph *
>(
g)->GetListOfFunctions()->
FindObject(
"down")) {
1103 leg->AddEntry(o,
"",
"F");
1105 leg->AddEntry(
g,
"",
"LPE");
1110 auto addToLegend = [](
TLegend *
l,
const char *label,
const std::pair<double, double> val) {
1113 TString::Format(
"%s%s: %g #pm %g%s", std::isfinite(val.second) ?
"" :
"#color[2]{", label,
1114 val.first, val.second, std::isfinite(val.second) ?
"" :
"}"),
1121 if (exp2 && exp2->GetN() > 1) {
1123 addToLegend(
leg,
"-2#sigma",
l);
1125 if (exp1 && exp1->GetN() > 1) {
1127 addToLegend(
leg,
"-1#sigma",
l);
1129 if (exp && exp->GetN() > 1) {
1131 addToLegend(
leg,
"0#sigma",
l);
1133 if (exp1 && exp1->GetN() > 1) {
1135 addToLegend(
leg,
"+1#sigma",
l);
1137 if (exp2 && exp2->GetN() > 1) {
1139 addToLegend(
leg,
"+2#sigma",
l);
1141 if (obs && obs->GetN() > 1) {
1143 addToLegend(
leg,
"Observed",
l);
1147 out->Add(testedPoints,
"P");
1151 gROOT->GetSelectedPad()->cd();
1154 auto gra2 =
static_cast<TMultiGraph *
>(out->DrawClone(
"A"));
1157 gra2->GetHistogram()->SetMinimum(1
e-6);
1161 gPad->GetCanvas()->Paint();
1162 gPad->GetCanvas()->Update();
1163#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 00)
1164 gPad->GetCanvas()->ResetUpdated();
1177 if (std::isnan(target)) {
1178 target = 1. -
gEnv->GetValue(
"xRooHypoSpace.CL", 95.) / 100.;
1181 auto gr = std::make_shared<TGraph>(pValues);
1184 std::set<double> existingX;
1185 while (i < gr->GetN()) {
1186 if (std::isnan(
gr->GetPointY(i))) {
1188 }
else if (existingX.find(
gr->GetPointX(i)) != existingX.end()) {
1191 existingX.insert(
gr->GetPointX(i));
1193 gr->SetPointY(i, log(std::max(
gr->GetPointY(i), 1
e-10)));
1201 if (
gr->GetN() < 2) {
1202 return std::pair<double, double>(std::numeric_limits<double>::quiet_NaN(), 0);
1205 double alpha = log(target);
1207 bool above =
gr->GetPointY(0) > alpha;
1208 for (
int ii = 1; ii <
gr->GetN(); ii++) {
1209 if ((above && (
gr->GetPointY(ii) <= alpha)) || (!above && (
gr->GetPointY(ii) >= alpha))) {
1211 double lim =
gr->GetPointX(ii - 1) + (
gr->GetPointX(ii) -
gr->GetPointX(ii - 1)) *
1212 (alpha -
gr->GetPointY(ii - 1)) /
1213 (
gr->GetPointY(ii) -
gr->GetPointY(ii - 1));
1215 double err = std::max(lim -
gr->GetPointX(ii - 1),
gr->GetPointX(ii) - lim);
1217 if ((lim -
gr->GetPointX(ii - 1)) > (
gr->GetPointX(ii) - lim))
1219 return std::pair(lim,
err);
1223 if ((above &&
gr->GetPointY(
gr->GetN() - 1) <=
gr->GetPointY(0)) ||
1224 (!above &&
gr->GetPointY(
gr->GetN() - 1) >=
gr->GetPointY(0))) {
1228 while (offset < gr->GetN() &&
gr->GetPointY(
gr->GetN() - offset) == 0)
1230 double x1 =
gr->GetPointX(
gr->GetN() - offset);
1231 double y1 =
gr->GetPointY(
gr->GetN() - offset);
1232 double m = (
gr->GetPointY(
gr->GetN() - 1) - y1) / (
gr->GetPointX(
gr->GetN() - 1) - x1);
1234 return std::pair(std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity());
1235 return std::pair((alpha - y1) /
m + x1, std::numeric_limits<double>::infinity());
1238 double x1 =
gr->GetPointX(0);
1239 double y1 =
gr->GetPointY(0);
1240 double m = (
gr->GetPointY(1) - y1) / (
gr->GetPointX(1) - x1);
1242 return std::pair(-std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity());
1243 return std::pair((alpha - y1) /
m + x1, -std::numeric_limits<double>::infinity());
1250 if (std::isnan(nSigma)) {
1253 sOpt +=
TString::Format(
"exp%s%d", nSigma > 0 ?
"+" :
"",
int(nSigma));
1262 bool visualize = sOpt.
Contains(
"visualize");
1264 std::shared_ptr<TGraphErrors>
gr =
graph(sOpt +
" readonly");
1266 auto gra =
graphs(sOpt.
Contains(
"toys") ?
"pcls readonly toys" :
"pcls readonly");
1273 gra->GetHistogram()->SetMinimum(1
e-9);
1274 gra->GetHistogram()->GetYaxis()->SetRangeUser(1
e-9, 1);
1276#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 00)
1277 gPad->GetCanvas()->ResetUpdated();
1284 for (
auto p :
axes()) {
1286 if (
auto _v =
dynamic_cast<RooRealVar *
>(nll->pars()->find(*p))) {
1287 dynamic_cast<RooRealVar *
>(p)->setRange(_v->getMin(), _v->getMax());
1292 if (!
gr ||
gr->GetN() < 2) {
1295 return std::pair(std::numeric_limits<double>::quiet_NaN(), 0.);
1296 double muMax = std::min(std::min(
v->getMax(
"physical"),
v->getMax()),
v->getMax(
"scan"));
1297 double muMin = std::max(std::max(
v->getMin(
"physical"),
v->getMin()),
v->getMin(
"scan"));
1298 if (!
gr ||
gr->GetN() < 1) {
1301 ::Error(
"findlimit",
"Problem evaluating %s @ %s=%g", sOpt.
Data(),
v->GetName(), muMin);
1302 return std::pair(std::numeric_limits<double>::quiet_NaN(), 0.);
1305 return findlimit(opt, relUncert, maxTries - 1);
1312 double nextPoint = muMin + (muMax - muMin) / 50;
1318 auto expLim =
findlimit(sOpt2, std::numeric_limits<double>::infinity(), 0);
1319 if (!std::isnan(expLim.first) && expLim.first < nextPoint)
1320 nextPoint = expLim.first;
1324 (sOpt.
Contains(
"exp")) ? back().asimov() : std::shared_ptr<xRooHypoPoint>(&back(), [](
xRooHypoPoint *) {});
1327 double rough_sigma_mu =
point->mu_hat().getError();
1330 nextPoint = another_estimate;
1331 ::Info(
"xRooHypoSpace::findlimit",
"Guessing %g based on rough sigma_mu = %g", nextPoint, rough_sigma_mu);
1337 ::Error(
"xRooHypoSpace::findlimit",
"Problem evaluating %s @ %s=%g", sOpt.
Data(),
v->GetName(), nextPoint);
1338 return std::pair(std::numeric_limits<double>::quiet_NaN(), 0.);
1341 return findlimit(opt, relUncert, maxTries - 1);
1346 if (std::isnan(lim.first)) {
1351 double maxMu = std::min(std::min(
v->getMax(
"physical"),
v->getMax()),
v->getMax(
"scan"));
1352 double minMu = std::max(std::max(
v->getMin(
"physical"),
v->getMin()),
v->getMin(
"scan"));
1355 if (lim.first > -std::numeric_limits<double>::infinity() && lim.first < std::numeric_limits<double>::infinity() &&
1356 (std::abs(lim.second) <= relUncert * std::abs(lim.first) ))
1361 if (lim.second == std::numeric_limits<double>::infinity()) {
1363 nextPoint = lim.first;
1364 if (nextPoint == std::numeric_limits<double>::infinity() || nextPoint > maxMu) {
1365 nextPoint =
gr->GetPointX(
gr->GetN() - 1) + (maxMu - minMu) / 50;
1371 (sOpt.
Contains(
"exp")) ? back().asimov() : std::shared_ptr<xRooHypoPoint>(&back(), [](
xRooHypoPoint *) {});
1374 double rough_sigma_mu =
point->mu_hat().getError();
1377 nextPoint = std::max(nextPoint, another_estimate);
1378 ::Info(
"xRooHypoSpace::findlimit",
"Guessing %g based on rough sigma_mu = %g", nextPoint, rough_sigma_mu);
1381 nextPoint = std::min(nextPoint + nextPoint * relUncert * 0.99, maxMu);
1383 if (nextPoint > maxMu)
1385 }
else if (lim.second == -std::numeric_limits<double>::infinity()) {
1387 nextPoint = lim.first;
1388 if (nextPoint < minMu)
1389 nextPoint =
gr->GetPointX(0) - (maxMu - minMu) / 50;
1390 if (nextPoint < minMu)
1393 nextPoint = lim.first + lim.second * relUncert * 0.99;
1399 ::Info(
"xRooHypoSpace::findlimit",
"%s -- Testing new point @ %s=%g (delta=%g)", sOpt.
Data(),
v->GetName(),
1400 nextPoint, lim.second);
1402 if (maxTries == 0) {
1403 ::Warning(
"xRooHypoSpace::findlimit",
"Reached max number of point evaluations");
1405 ::Error(
"xRooHypoSpace::findlimit",
"Problem evaluating %s @ %s=%g", sOpt.
Data(),
v->GetName(), nextPoint);
1410 return findlimit(opt, relUncert, maxTries - 1);
1419 if ((sOpt ==
"" || sOpt ==
"same") && !empty()) {
1422 for (
auto &hp : *
this) {
1423 if (!hp.nullToys.empty() || !hp.altToys.empty()) {
1434 auto _axes =
axes();
1438 if (sOpt ==
"status") {
1440 if (_axes.size() <= 2) {
1455 badPoints->
SetName(
"bad_ufit");
1461 badPoints2->
SetName(
"bad_cfit_null");
1468 (_axes.size() == 1) ?
"" : _axes.at(1)->GetTitle()));
1469 for (
auto &p : *
this) {
1470 bool _readOnly = p.nllVar ? p.nllVar->get()->getAttribute(
"readOnly") :
false;
1472 p.nllVar->get()->setAttribute(
"readOnly",
true);
1473 double x = p.coords->getRealValue(_axes.at(0)->GetName());
1474 double y = _axes.size() == 1 ? p.ts_asymp().first : p.coords->getRealValue(_axes.at(1)->GetName());
1476 if (!std::isnan(p.ts_asymp().first)) {
1477 if (_axes.size() == 1)
1480 }
else if (p.fUfit && (std::isnan(p.fUfit->minNll()) ||
1484 }
else if (p.fNull_cfit && (std::isnan(p.fNull_cfit->minNll()) ||
1489 if (!std::isnan(p.ts_asymp(0).first)) {
1491 }
else if (p.asimov() && p.asimov()->fUfit &&
1492 (std::isnan(p.asimov()->fUfit->minNll()) ||
1496 }
else if (p.asimov() && p.asimov()->fNull_cfit &&
1497 (std::isnan(p.asimov()->fNull_cfit->minNll()) ||
1502 p.nllVar->get()->setAttribute(
"readOnly", _readOnly);
1505 if (_axes.size() == 1) {
1507 for (
int i = 0; i < out->
GetN(); i++) {
1511 auto fixPoints = [&](
TGraph *
g) {
1512 for (
int i = 0; i <
g->GetN(); i++) {
1513 if (std::isnan(
g->GetPointY(i)))
1514 g->SetPointY(i, std::isnan(tmp.
Eval(
g->GetPointX(i))) ? 0. : tmp.
Eval(
g->GetPointX(i)));
1519 fixPoints(expAvail);
1520 fixPoints(badPoints);
1521 fixPoints(badPoints2);
1526 auto leg =
new TLegend(1. -
gPad->GetRightMargin() - 0.3, 1. -
gPad->GetTopMargin() - 0.35,
1527 1. -
gPad->GetRightMargin() - 0.05, 1. -
gPad->GetTopMargin() - 0.05);
1528 leg->SetName(
"legend");
1529 leg->AddEntry(out,
"Uncomputed",
"P");
1531 if (tsAvail->
GetN()) {
1533 leg->AddEntry(tsAvail,
"Computed",
"P");
1537 if (expAvail->
GetN()) {
1539 leg->AddEntry(expAvail,
"Expected computed",
"P");
1543 if (badPoints->
GetN()) {
1545 leg->AddEntry(badPoints,
"Bad ufit",
"P");
1549 if (badPoints2->
GetN()) {
1551 leg->AddEntry(badPoints2,
"Bad null cfit",
"P");
1558 gPad->SetGrid(
true, _axes.size() > 1);
1559 if (_axes.size() == 1)
1560 gPad->SetLogy(
false);
1569 auto gra =
graphs(sOpt +
" readonly");
1571 gROOT->GetSelectedPad()->cd();
1581 gra2->GetHistogram()->SetMinimum(1
e-6);
1585 gPad->GetCanvas()->Paint();
1586 gPad->GetCanvas()->Update();
1587#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 00)
1588 gPad->GetCanvas()->ResetUpdated();
1614 if (!empty() &&
axes().
size() == 1) {
1615 for (
auto &p : *
this) {
1617 pllType = p.fPllType;
1621 title += front().tsTitle(
true);
1625 *
dynamic_cast<TAttFill *
>(out) = *
this;
1626 *
dynamic_cast<TAttLine *
>(out) = *
this;
1636 bool doFits =
false;
1642 auto mainPad =
gPad;
1649 gPad->SetBottomMargin(
gPad->GetBottomMargin() * 2.);
1653 mainPad = basePad->
GetPad(1);
1659 std::pair<double, double> minMax(std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity());
1660 for (
auto &p : *
this) {
1661 if (p.fPllType != pllType)
1663 auto val = p.pll(
true).first;
1664 if (std::isnan(val))
1666 minMax.first = std::min(minMax.first, val);
1667 minMax.second = std::max(minMax.second, val);
1669 if (minMax.first < std::numeric_limits<double>::infinity())
1671 if (minMax.second > -std::numeric_limits<double>::infinity())
1674 TGraph *badPoints =
nullptr;
1678 std::shared_ptr<const RooFitResult> ufr;
1679 for (
auto &p : *
this) {
1680 if (p.fPllType != pllType)
1682 auto val = p.pll().first;
1685 if (out->
GetN() == 0 && ufr && ufr->status() == 0) {
1687 ufr->floatParsFinal().getRealValue(
axes().first()->
GetName(),
1688 ufr->constPars().getRealValue(
axes().first()->
GetName())),
1692 if (
auto fr = p.fNull_cfit;
1698 pad->SetNumber(out->
GetN() + 1);
1705 if (std::isnan(val) && p.status() != 0) {
1709 badPoints->
SetName(
"badPoints");
1715 badPoints->
SetPoint(badPoints->
GetN(), p.fNullVal(), out->
Eval(p.fNullVal()));
1716 mainPad->Modified();
1717 }
else if (!std::isnan(val)) {
1724 for (
int i = 0; i < badPoints->
GetN(); i++)
1728 mainPad->Modified();
1741#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 00)
1747 if (ufr && doFits) {
1749 auto pad =
new TPad(ufr->GetName(),
"unconditional fit", 0, 0, 1., 1.);
1757 pad =
new TPad(
"selected",
"selected", 0, 0, 1, 1);
1772 gPad->GetCanvas()->Connect(
"Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
"xRooNode::InteractiveObject",
1784 auto _axes =
axes();
1791 for (
auto &p : *
this) {
1792 double _x = p.coords->getRealValue(_axes.at(0)->GetName(), std::numeric_limits<double>::quiet_NaN());
1793 out->
Add(_x, p.result());
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
const char Option_t
Option string (const char).
Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.", GetName(), objname)
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
static std::pair< double, double > matchPrecision(const std::pair< double, double > &in)
static std::set< int > allowedStatusCodes
std::shared_ptr< xRooHypoPoint > asimov(bool readOnly=false)
std::pair< std::shared_ptr< RooAbsData >, std::shared_ptr< const RooAbsCollection > > fData
std::shared_ptr< const RooAbsCollection > coords
std::shared_ptr< xRooNLLVar > nllVar
xRooFit::Asymptotics::PLLType fPllType
RooArgList alt_poi() const
std::shared_ptr< const RooFitResult > fAlt_cfit
bool AddModel(const xRooNode &pdf, const char *validity="")
std::shared_ptr< TGraphErrors > graph(const char *opt) const
std::shared_ptr< RooArgSet > pars() const
xRooFit::Asymptotics::PLLType fTestStatType
void Draw(Option_t *opt="") override
Default Draw method for all objects.
xRooHypoPoint & point(size_t i)
std::map< std::string, xValueWithError > limits(const char *opt="cls", const std::vector< double > &nSigmas={0, 1, 2, -1, -2, std::numeric_limits< double >::quiet_NaN()}, double relUncert=std::numeric_limits< double >::infinity())
std::map< std::shared_ptr< xRooNode >, std::shared_ptr< xRooNLLVar > > fNlls
static RooArgList toArgs(const char *str)
xRooHypoSpace(const char *name="", const char *title="")
xRooHypoPoint & AddPoint(double value)
int AddPoints(const char *parName, size_t nPoints, double low, double high)
std::shared_ptr< TMultiGraph > graphs(const char *opt)
RooStats::HypoTestInverterResult * result()
std::shared_ptr< RooArgSet > fPars
std::shared_ptr< xRooNode > pdf(const RooAbsCollection &parValues) const
xValueWithError limit(const char *type="cls", double nSigma=std::numeric_limits< double >::quiet_NaN()) const
int scan(const char *type, size_t nPoints, double low=std::numeric_limits< double >::quiet_NaN(), double high=std::numeric_limits< double >::quiet_NaN(), const std::vector< double > &nSigmas={0, 1, 2, -1, -2, std::numeric_limits< double >::quiet_NaN()}, double relUncert=0.1)
xValueWithError findlimit(const char *opt, double relUncert=std::numeric_limits< double >::infinity(), unsigned int maxTries=20)
void Print(Option_t *opt="") const override
Print TNamed name and title.
static xValueWithError GetLimit(const TGraph &pValues, double target=std::numeric_limits< double >::quiet_NaN())
std::set< std::pair< std::shared_ptr< RooArgList >, std::shared_ptr< xRooNode > > > fPdfs
std::shared_ptr< RooArgSet > pars(bool stripGlobalObs=true) const
std::shared_ptr< RooAbsPdf > pdf() const
The xRooNode class is designed to wrap over a TObject and provide functionality to aid with interacti...
void Draw(Option_t *opt="") override
Default Draw method for all objects.
RooArgList argList() const
static InteractiveObject * gIntObj
xRooNode pars() const
List of parameters (non-observables) of this node.
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
A space to attach TBranches.
virtual value_type getCurrentIndex() const
Return index number of current state.
Abstract container object that can hold multiple RooAbsArg objects.
RooAbsCollection * selectByAttrib(const char *name, bool value) const
Create a subset of the current collection, consisting only of those elements with the specified attri...
double getRealValue(const char *name, double defVal=0.0, bool verbose=false) const
Get value of a RooAbsReal stored in set with given name.
Int_t getCatIndex(const char *name, Int_t defVal=0, bool verbose=false) const
Get index value of a RooAbsCategory stored in set with given name.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
void setAttribAll(const Text_t *name, bool value=true)
Set given attribute in each element of the collection by calling each elements setAttribute() functio...
virtual RooAbsArg * addClone(const RooAbsArg &var, bool silent=false)
Add a clone of the specified argument to list.
void sort(bool reverse=false)
Sort collection using std::sort and name comparison.
void useHashMapForFind(bool flag) const
void setName(const char *name)
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract interface for all probability density functions.
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
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.
Represents a constant real-valued object.
Container class to hold unbinned data.
RooRealVar * weightVar() const
Returns a pointer to the weight variable (if set).
Variable that can be changed from the outside.
HypoTestInverterResult class holds the array of hypothesis test results and compute a confidence inte...
bool Add(const HypoTestInverterResult &otherResult)
merge with the content of another HypoTestInverterResult object
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
virtual Size_t GetMarkerSize() const
Return the marker size.
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
static TCanvas * MakeDefCanvas()
Static function to build a default canvas.
void Paint(Option_t *option="") override
Paint canvas.
void Update() override
Update canvas pad buffers.
virtual Bool_t cd()
Change current directory to "this" directory.
virtual void SetPointError(Double_t ex, Double_t ey)
static Bool_t CompareX(const TGraph *gr, Int_t left, Int_t right)
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
virtual void SetEditable(Bool_t editable=kTRUE)
virtual Double_t Eval(Double_t x, TSpline *spline=nullptr, Option_t *option="") const
virtual TH1F * GetHistogram() const
TList * GetListOfFunctions() const
virtual void SetPointY(Int_t i, Double_t y)
void SetName(const char *name="") override
Set the name of the TNamed.
void Draw(Option_t *chopt="") override
Default Draw method for all objects.
virtual Double_t GetPointY(Int_t i) const
void SetTitle(const char *title="") override
Set the title of the TNamed.
virtual Double_t GetPointX(Int_t i) const
virtual void Sort(Bool_t(*greater)(const TGraph *, Int_t, Int_t)=&TGraph::CompareX, Bool_t ascending=kTRUE, Int_t low=0, Int_t high=-1111)
virtual void SetMaximum(Double_t maximum=-1111)
virtual void SetMinimum(Double_t minimum=-1111)
void Add(TObject *obj) override
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
const char * GetName() const override
Returns name of object.
const char * GetTitle() const override
Returns title of object.
virtual void SetName(const char *name)
Set the name of the TNamed.
virtual void SetNameTitle(const char *name, const char *title)
Set all the TNamed parameters (name and title).
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
TObject()
TObject constructor.
@ kCanDelete
if object in a list can be deleted
The most important graphics class in the ROOT system.
Double_t RealTime()
Stop the stopwatch (if it is running) and return the realtime (in seconds) passed between the start a...
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
void Continue()
Resume a stopped stopwatch.
Provides iteration through tokens of a given string.
Bool_t NextToken()
Get the next token, it is stored in this TString.
void ToLower()
Change string to lower-case.
Double_t Atof() const
Return floating-point value contained in string.
Bool_t IsFloat() const
Returns kTRUE if string contains a floating point or integer number.
const char * Data() const
TString & ReplaceAll(const TString &s1, const TString &s2)
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
TVirtualPad is an abstract base class for the Pad and Canvas classes.
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual TVirtualPad * GetPad(Int_t subpadnumber) const =0
virtual TCanvas * GetCanvas() const =0
void Clear(Option_t *option="") override=0
double gaussian_quantile(double z, double sigma)
Inverse ( ) of the cumulative distribution function of the lower tail of the normal (Gaussian) distri...
#define BEGIN_XROOFIT_NAMESPACE
#define END_XROOFIT_NAMESPACE