76 ClassImp(RooStats::LikelihoodInterval); ;
78 using namespace RooStats;
85 LikelihoodInterval::LikelihoodInterval(
const char* name) :
86 ConfInterval(name), fBestFitParams(0), fLikelihoodRatio(0), fConfidenceLevel(0.95)
94 LikelihoodInterval::LikelihoodInterval(
const char* name, RooAbsReal* lr,
const RooArgSet* params, RooArgSet * bestParams) :
97 fBestFitParams(bestParams),
99 fConfidenceLevel(0.95)
107 LikelihoodInterval::~LikelihoodInterval()
109 if (fBestFitParams)
delete fBestFitParams;
110 if (fLikelihoodRatio)
delete fLikelihoodRatio;
118 Bool_t LikelihoodInterval::IsInInterval(
const RooArgSet ¶meterPoint)
const
120 RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
121 RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
123 if( !this->CheckParameters(parameterPoint) ) {
124 std::cout <<
"parameters don't match" << std::endl;
125 RooMsgService::instance().setGlobalKillBelow(msglevel);
130 if(!fLikelihoodRatio) {
131 std::cout <<
"likelihood ratio not set" << std::endl;
132 RooMsgService::instance().setGlobalKillBelow(msglevel);
139 SetParameters(¶meterPoint, fLikelihoodRatio->getVariables() );
143 if (fLikelihoodRatio->getVal()<0){
144 std::cout <<
"The likelihood ratio is < 0, indicates a bad minimum or numerical precision problems. Will return true" << std::endl;
145 RooMsgService::instance().setGlobalKillBelow(msglevel);
151 if ( TMath::Prob( 2* fLikelihoodRatio->getVal(), parameterPoint.getSize()) < (1.-fConfidenceLevel) ){
152 RooMsgService::instance().setGlobalKillBelow(msglevel);
157 RooMsgService::instance().setGlobalKillBelow(msglevel);
166 RooArgSet* LikelihoodInterval::GetParameters()
const
168 return new RooArgSet(fParameters);
174 Bool_t LikelihoodInterval::CheckParameters(
const RooArgSet ¶meterPoint)
const
176 if (parameterPoint.getSize() != fParameters.getSize() ) {
177 std::cout <<
"size is wrong, parameters don't match" << std::endl;
180 if ( ! parameterPoint.equals( fParameters ) ) {
181 std::cout <<
"size is ok, but parameters don't match" << std::endl;
195 Double_t LikelihoodInterval::LowerLimit(
const RooRealVar& param,
bool & status)
199 status = FindLimits(param, lower, upper);
209 Double_t LikelihoodInterval::UpperLimit(
const RooRealVar& param,
bool & status)
213 status = FindLimits(param, lower, upper);
218 void LikelihoodInterval::ResetLimits() {
220 fLowerLimits.clear();
221 fUpperLimits.clear();
225 bool LikelihoodInterval::CreateMinimizer() {
230 RooProfileLL * profilell =
dynamic_cast<RooProfileLL*
>(fLikelihoodRatio);
231 if (!profilell)
return false;
233 RooAbsReal & nll = profilell->nll();
237 RooArgSet * partmp = profilell->getVariables();
239 RemoveConstantParameters(partmp);
241 RooArgList params(*partmp);
245 if (fBestFitParams) {
246 for (
int i = 0; i < params.getSize(); ++i) {
247 RooRealVar & par = (RooRealVar &) params[i];
248 RooRealVar * fitPar = (RooRealVar *) (fBestFitParams->find(par.GetName() ) );
250 par.setVal( fitPar->getVal() );
251 par.setError( fitPar->getError() );
256 const auto& config = GetGlobalRooStatsConfig();
259 if (config.useLikelihoodOffset) {
260 ccoutI(InputArguments) <<
"LikelihoodInterval: using nll offset - set all RooAbsReal to hide the offset " << std::endl;
261 RooAbsReal::setHideOffset(kFALSE);
263 fFunctor = std::make_shared<RooFunctor>(nll, RooArgSet(), params);
265 std::string minimType = ROOT::Math::MinimizerOptions::DefaultMinimizerType();
266 std::transform(minimType.begin(), minimType.end(), minimType.begin(), (int(*)(int)) tolower );
267 *minimType.begin() = toupper( *minimType.begin());
269 if (minimType !=
"Minuit" && minimType !=
"Minuit2") {
270 ccoutE(InputArguments) << minimType <<
" is wrong type of minimizer for getting interval limits or contours - must use Minuit or Minuit2" << std::endl;
274 if (minimType ==
"Minuit") TMinuitMinimizer::UseStaticMinuit(
false);
276 fMinimizer = std::shared_ptr<ROOT::Math::Minimizer>(ROOT::Math::Factory::CreateMinimizer(minimType,
"Migrad"));
278 if (!fMinimizer.get())
return false;
280 fMinFunc = std::static_pointer_cast<ROOT::Math::IMultiGenFunction>(
281 std::make_shared<ROOT::Math::WrappedMultiFunction<RooFunctor &>>(*fFunctor, fFunctor->nPar()) );
282 fMinimizer->SetFunction(*fMinFunc);
285 assert( params.getSize() == int(fMinFunc->NDim()) );
287 for (
unsigned int i = 0; i < fMinFunc->NDim(); ++i) {
288 RooRealVar & v = (RooRealVar &) params[i];
289 fMinimizer->SetLimitedVariable( i, v.GetName(), v.getVal(), v.getError(), v.getMin(), v.getMax() );
292 bool iret = fMinimizer->Minimize();
293 if (!iret || fMinimizer->X() == 0) {
294 ccoutE(Minimization) <<
"Error: Minimization failed " << std::endl;
304 bool LikelihoodInterval::FindLimits(
const RooRealVar & param,
double &lower,
double & upper)
312 std::map<std::string, double>::const_iterator itrl = fLowerLimits.find(param.GetName());
313 std::map<std::string, double>::const_iterator itru = fUpperLimits.find(param.GetName());
314 if ( itrl != fLowerLimits.end() && itru != fUpperLimits.end() ) {
315 lower = itrl->second;
316 upper = itru->second;
321 RooArgSet * partmp = fLikelihoodRatio->getVariables();
322 RemoveConstantParameters(partmp);
323 RooArgList params(*partmp);
325 int ix = params.index(¶m);
327 ccoutE(InputArguments) <<
"Error - invalid parameter " << param.GetName() <<
" specified for finding the interval limits " << std::endl;
332 if (!fMinimizer.get()) ret = CreateMinimizer();
334 ccoutE(Eval) <<
"Error returned from minimization of likelihood function - cannot find interval limits " << std::endl;
338 assert(fMinimizer.get());
341 double err_level = TMath::ChisquareQuantile(ConfidenceLevel(),1);
342 err_level = err_level/2;
343 fMinimizer->SetErrorDef(err_level);
345 unsigned int ivarX = ix;
349 ret = fMinimizer->GetMinosError(ivarX, elow, eup );
351 ccoutE(Minimization) <<
"Error running Minos for parameter " << param.GetName() << std::endl;
357 lower = param.getMin();
358 ccoutW(Minimization) <<
"Warning: lower value for " << param.GetName() <<
" is at limit " << lower << std::endl;
361 lower = fMinimizer->X()[ivarX] + elow;
364 ccoutW(Minimization) <<
"Warning: upper value for " << param.GetName() <<
" is at limit " << upper << std::endl;
365 upper = param.getMax();
368 upper = fMinimizer->X()[ivarX] + eup;
372 fLowerLimits[param.GetName()] = lower;
373 fUpperLimits[param.GetName()] = upper;
379 Int_t LikelihoodInterval::GetContourPoints(
const RooRealVar & paramX,
const RooRealVar & paramY, Double_t * x, Double_t *y, Int_t npoints ) {
385 RooArgSet * partmp = fLikelihoodRatio->getVariables();
386 RemoveConstantParameters(partmp);
387 RooArgList params(*partmp);
389 int ix = params.index(¶mX);
390 int iy = params.index(¶mY);
391 if (ix < 0 || iy < 0) {
392 coutE(InputArguments) <<
"LikelihoodInterval - Error - invalid parameters specified for finding the contours; parX = " << paramX.GetName()
393 <<
" parY = " << paramY.GetName() << std::endl;
398 if (!fMinimizer.get()) ret = CreateMinimizer();
400 coutE(Eval) <<
"LikelihoodInterval - Error returned creating minimizer for likelihood function - cannot find contour points " << std::endl;
404 assert(fMinimizer.get());
407 double cont_level = TMath::ChisquareQuantile(ConfidenceLevel(),2);
408 cont_level = cont_level/2;
409 fMinimizer->SetErrorDef(cont_level);
411 unsigned int ncp = npoints;
412 unsigned int ivarX = ix;
413 unsigned int ivarY = iy;
414 coutI(Minimization) <<
"LikelihoodInterval - Finding the contour of " << paramX.GetName() <<
" ( " << ivarX <<
" ) and " << paramY.GetName() <<
" ( " << ivarY <<
" ) " << std::endl;
415 ret = fMinimizer->Contour(ivarX, ivarY, ncp, x, y );
417 coutE(Minimization) <<
"LikelihoodInterval - Error finding contour for parameters " << paramX.GetName() <<
" and " << paramY.GetName() << std::endl;
420 if (
int(ncp) < npoints) {
421 coutW(Minimization) <<
"LikelihoodInterval -Warning - Less points calculated in contours np = " << ncp <<
" / " << npoints << std::endl;