1 #include "../interface/GoodnessOfFit.h"
2 #include <RooRealVar.h>
5 #include <RooDataSet.h>
6 #include <RooFitResult.h>
8 #include <RooProdPdf.h>
9 #include <RooSimultaneous.h>
10 #include <RooAddPdf.h>
11 #include <RooConstVar.h>
12 #include <RooDataSet.h>
13 #include <RooDataHist.h>
14 #include <RooHistPdf.h>
19 #include <RooStats/ModelConfig.h>
20 #include "../interface/Combine.h"
21 #include "../interface/ProfileLikelihood.h"
22 #include "../interface/CloseCoutSentry.h"
23 #include "../interface/RooSimultaneousOpt.h"
24 #include "../interface/utils.h"
27 #include <Math/MinimizerOptions.h>
29 using namespace RooStats;
39 LimitAlgo(
"GoodnessOfFit specific options")
42 (
"algorithm", boost::program_options::value<std::string>(&
algo_),
"Goodness of fit algorithm. Currently, the only option is 'saturated' (which works for binned models only)")
43 (
"minimizerAlgo", boost::program_options::value<std::string>(&
minimizerAlgo_)->default_value(
minimizerAlgo_),
"Choice of minimizer (Minuit vs Minuit2)")
46 (
"fixedSignalStrength", boost::program_options::value<float>(&
mu_)->default_value(
mu_),
"Compute the goodness of fit for a fixed signal strength. If not specified, it's left floating")
52 fixedMu_ = !vm[
"fixedSignalStrength"].defaulted();
53 if (
algo_ ==
"saturated")
std::cout <<
"Will use saturated models to compute goodness of fit for a binned likelihood" << std::endl;
54 else throw std::invalid_argument(
"GoodnessOfFit: algorithm "+
algo_+
" not supported");
57 bool GoodnessOfFit::run(RooWorkspace *
w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &
data,
double &
limit,
double &limitErr,
const double *hint) {
60 RooRealVar *
r =
dynamic_cast<RooRealVar *
>(mc_s->GetParametersOfInterest()->first());
61 if (
fixedMu_) { r->setVal(
mu_); r->setConstant(
true); }
67 RooAbsPdf *pdf_nominal = mc_s->GetPdf();
69 std::auto_ptr<RooAbsPdf> saturated;
74 RooSimultaneous *
sim =
dynamic_cast<RooSimultaneous *
>(obsOnlyPdf);
76 RooAbsCategoryLValue *cat = (RooAbsCategoryLValue *) sim->indexCat().Clone();
77 std::auto_ptr<TList>
datasets(data.split(*cat,
true));
78 int nbins = cat->numBins((
const char *)0);
80 TString satname = TString::Format(
"%s_saturated", sim->GetName());
82 for (
int ic = 0, nc = nbins; ic < nc; ++ic) {
84 RooAbsPdf *pdfi = sim->getPdf(cat->getLabel());
85 if (pdfi == 0)
continue;
86 RooAbsData *datai = (RooAbsData *)
datasets->FindObject(cat->getLabel());
87 if (datai == 0)
throw std::runtime_error(std::string(
"Error: missing dataset for category label ")+cat->getLabel());
90 if (constraints.getSize() > 0) {
91 RooArgList terms(constraints); terms.add(*saturatedPdfi);
92 RooProdPdf *prodpdf =
new RooProdPdf(TString::Format(
"%s_constr", saturatedPdfi->GetName()),
"", terms);
93 prodpdf->addOwnedComponents(RooArgSet(*saturatedPdfi));
94 saturatedPdfi = prodpdf;
96 satsim->addPdf(*saturatedPdfi, cat->getLabel());
97 satsim->addOwnedComponents(RooArgSet(*saturatedPdfi));
99 saturated.reset(satsim);
102 if (constraints.getSize() > 0) {
103 RooArgList terms(constraints); terms.add(*saturatedPdfi);
104 RooProdPdf *prodpdf =
new RooProdPdf(TString::Format(
"%s_constr", saturatedPdfi->GetName()),
"", terms);
105 prodpdf->addOwnedComponents(RooArgSet(*saturatedPdfi));
106 saturatedPdfi = prodpdf;
108 saturated.reset(saturatedPdfi);
113 const RooCmdArg &minim = RooFit::Minimizer(ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str(),
114 ROOT::Math::MinimizerOptions::DefaultMinimizerAlgo().c_str());
115 std::auto_ptr<RooFitResult> result_nominal(pdf_nominal->fitTo(data, RooFit::Save(1), minim, RooFit::Strategy(
minimizerStrategy_), RooFit::Hesse(0), RooFit::Constrain(*mc_s->GetNuisanceParameters())));
116 std::auto_ptr<RooFitResult> result_saturated(saturated->fitTo(data, RooFit::Save(1), minim, RooFit::Strategy(
minimizerStrategy_), RooFit::Hesse(0), RooFit::Constrain(*mc_s->GetNuisanceParameters())));
123 if (result_nominal.get() == 0)
return false;
124 if (result_saturated.get() == 0)
return false;
126 double nll_nominal = result_nominal->minNll();
127 double nll_saturated = result_saturated->minNll();
128 if (fabs(nll_nominal) > 1e10 || fabs(nll_saturated) > 1e10)
return false;
129 limit = 2*(nll_nominal-nll_saturated);
131 std::cout <<
"\n --- GoodnessOfFit --- " << std::endl;
132 std::cout <<
"Best fit test statistic: " << limit << std::endl;
137 if (
verbose > 1)
std::cout <<
"Generating saturated model for " << data.GetName() << std::endl;
138 RooDataHist *rdh =
new RooDataHist(TString::Format(
"%s_binned", data.GetName()),
"", *data.get(),
data);
tempData_.push_back(rdh);
140 RooHistPdf *hpdf =
new RooHistPdf(TString::Format(
"%s_shape", data.GetName()),
"", *rdh->get(), *rdh);
141 RooConstVar *norm =
new RooConstVar(TString::Format(
"%s_norm", data.GetName()),
"", data.sumEntries());
143 RooAddPdf *
ret =
new RooAddPdf(TString::Format(
"%s_saturated", data.GetName()),
"", RooArgList(*hpdf), RooArgList(*norm));
144 ret->addOwnedComponents(RooArgSet(*norm));
145 ret->addOwnedComponents(RooArgSet(*hpdf));
RooAbsPdf * makeSaturatedPdf(RooAbsData &data)
virtual void applyOptions(const boost::program_options::variables_map &vm)
static float minimizerTolerance_
virtual bool runSaturatedModel(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint)
RooAbsPdf * factorizePdf(const RooArgSet &observables, RooAbsPdf &pdf, RooArgList &constraints)
void printRDH(RooAbsData *data)
static std::string minimizerAlgo_
static int minimizerStrategy_
Setup Minimizer configuration on creation, reset the previous one on destruction. ...
char data[epos_bytes_allocation]
std::vector< RooAbsData * > tempData_
virtual bool run(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr, const double *hint)
boost::program_options::options_description options_