00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #ifndef RooStats_LikelihoodInterval
00057 #include "RooStats/LikelihoodInterval.h"
00058 #endif
00059 #include "RooStats/RooStatsUtils.h"
00060
00061 #include "RooAbsReal.h"
00062 #include "RooMsgService.h"
00063
00064 #include "Math/WrappedFunction.h"
00065 #include "Math/Minimizer.h"
00066 #include "Math/Factory.h"
00067 #include "Math/MinimizerOptions.h"
00068 #include "RooFunctor.h"
00069 #include "RooProfileLL.h"
00070
00071 #include <string>
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 ClassImp(RooStats::LikelihoodInterval) ;
00082
00083 using namespace RooStats;
00084
00085
00086
00087 LikelihoodInterval::LikelihoodInterval(const char* name) :
00088 ConfInterval(name), fBestFitParams(0), fLikelihoodRatio(0), fConfidenceLevel(0.95)
00089 {
00090
00091 }
00092
00093
00094 LikelihoodInterval::LikelihoodInterval(const char* name, RooAbsReal* lr, const RooArgSet* params, RooArgSet * bestParams) :
00095 ConfInterval(name),
00096 fParameters(*params),
00097 fBestFitParams(bestParams),
00098 fLikelihoodRatio(lr),
00099 fConfidenceLevel(0.95)
00100 {
00101
00102
00103 }
00104
00105
00106
00107 LikelihoodInterval::~LikelihoodInterval()
00108 {
00109
00110 if (fBestFitParams) delete fBestFitParams;
00111 if (fLikelihoodRatio) delete fLikelihoodRatio;
00112 }
00113
00114
00115
00116 Bool_t LikelihoodInterval::IsInInterval(const RooArgSet ¶meterPoint) const
00117 {
00118
00119
00120
00121 RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
00122 RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
00123
00124 if( !this->CheckParameters(parameterPoint) ) {
00125 std::cout << "parameters don't match" << std::endl;
00126 RooMsgService::instance().setGlobalKillBelow(msglevel);
00127 return false;
00128 }
00129
00130
00131 if(!fLikelihoodRatio) {
00132 std::cout << "likelihood ratio not set" << std::endl;
00133 RooMsgService::instance().setGlobalKillBelow(msglevel);
00134 return false;
00135 }
00136
00137
00138
00139
00140 SetParameters(¶meterPoint, fLikelihoodRatio->getVariables() );
00141
00142
00143
00144 if (fLikelihoodRatio->getVal()<0){
00145 std::cout << "The likelihood ratio is < 0, indicates a bad minimum or numerical precision problems. Will return true" << std::endl;
00146 RooMsgService::instance().setGlobalKillBelow(msglevel);
00147 return true;
00148 }
00149
00150
00151
00152 if ( TMath::Prob( 2* fLikelihoodRatio->getVal(), parameterPoint.getSize()) < (1.-fConfidenceLevel) ){
00153 RooMsgService::instance().setGlobalKillBelow(msglevel);
00154 return false;
00155 }
00156
00157
00158 RooMsgService::instance().setGlobalKillBelow(msglevel);
00159
00160 return true;
00161
00162 }
00163
00164
00165 RooArgSet* LikelihoodInterval::GetParameters() const
00166 {
00167
00168 return new RooArgSet(fParameters);
00169 }
00170
00171
00172 Bool_t LikelihoodInterval::CheckParameters(const RooArgSet ¶meterPoint) const
00173 {
00174
00175
00176 if (parameterPoint.getSize() != fParameters.getSize() ) {
00177 std::cout << "size is wrong, parameters don't match" << std::endl;
00178 return false;
00179 }
00180 if ( ! parameterPoint.equals( fParameters ) ) {
00181 std::cout << "size is ok, but parameters don't match" << std::endl;
00182 return false;
00183 }
00184 return true;
00185 }
00186
00187
00188
00189
00190 Double_t LikelihoodInterval::LowerLimit(const RooRealVar& param, bool & status)
00191 {
00192
00193
00194
00195
00196
00197 double lower = 0;
00198 double upper = 0;
00199 status = FindLimits(param, lower, upper);
00200 return lower;
00201 }
00202
00203
00204 Double_t LikelihoodInterval::UpperLimit(const RooRealVar& param, bool & status)
00205 {
00206
00207
00208
00209
00210
00211 double lower = 0;
00212 double upper = 0;
00213 status = FindLimits(param, lower, upper);
00214 return upper;
00215 }
00216
00217
00218 void LikelihoodInterval::ResetLimits() {
00219
00220 fLowerLimits.clear();
00221 fUpperLimits.clear();
00222 }
00223
00224
00225 bool LikelihoodInterval::CreateMinimizer() {
00226
00227
00228
00229
00230 RooProfileLL * profilell = dynamic_cast<RooProfileLL*>(fLikelihoodRatio);
00231 if (!profilell) return false;
00232
00233 RooAbsReal & nll = profilell->nll();
00234
00235
00236
00237 RooArgSet * partmp = profilell->getVariables();
00238
00239 RemoveConstantParameters(partmp);
00240
00241 RooArgList params(*partmp);
00242 delete partmp;
00243
00244
00245 if (fBestFitParams) {
00246 for (int i = 0; i < params.getSize(); ++i) {
00247 RooRealVar & par = (RooRealVar &) params[i];
00248 RooRealVar * fitPar = (RooRealVar *) (fBestFitParams->find(par.GetName() ) );
00249 if (fitPar) {
00250 par.setVal( fitPar->getVal() );
00251 par.setError( fitPar->getError() );
00252 }
00253 }
00254 }
00255
00256
00257 fFunctor = std::auto_ptr<RooFunctor>(new RooFunctor(nll, RooArgSet(), params ));
00258
00259 std::string minimType = ROOT::Math::MinimizerOptions::DefaultMinimizerType();
00260
00261 if (minimType != "Minuit" && minimType != "Minuit2") {
00262 ccoutE(InputArguments) << minimType << "is wrong type of minimizer for getting interval limits or contours - must use Minuit or Minuit2" << std::endl;
00263 return false;
00264 }
00265
00266 fMinimizer = std::auto_ptr<ROOT::Math::Minimizer>(ROOT::Math::Factory::CreateMinimizer(minimType, "Migrad"));
00267
00268 if (!fMinimizer.get()) return false;
00269
00270 fMinFunc = std::auto_ptr<ROOT::Math::IMultiGenFunction>( new ROOT::Math::WrappedMultiFunction<RooFunctor &> (*fFunctor, fFunctor->nPar() ) );
00271 fMinimizer->SetFunction(*fMinFunc);
00272
00273
00274 assert( params.getSize() == int(fMinFunc->NDim()) );
00275
00276 for (unsigned int i = 0; i < fMinFunc->NDim(); ++i) {
00277 RooRealVar & v = (RooRealVar &) params[i];
00278 fMinimizer->SetLimitedVariable( i, v.GetName(), v.getVal(), v.getError(), v.getMin(), v.getMax() );
00279 }
00280
00281 bool iret = fMinimizer->Minimize();
00282 if (!iret || fMinimizer->X() == 0) {
00283 ccoutE(Minimization) << "Error: Minimization failed " << std::endl;
00284 return false;
00285 }
00286
00287
00288
00289
00290 return true;
00291 }
00292
00293 bool LikelihoodInterval::FindLimits(const RooRealVar & param, double &lower, double & upper)
00294 {
00295
00296
00297
00298
00299
00300
00301 std::map<std::string, double>::const_iterator itrl = fLowerLimits.find(param.GetName());
00302 std::map<std::string, double>::const_iterator itru = fUpperLimits.find(param.GetName());
00303 if ( itrl != fLowerLimits.end() && itru != fUpperLimits.end() ) {
00304 lower = itrl->second;
00305 upper = itru->second;
00306 return true;
00307 }
00308
00309
00310 RooArgSet * partmp = fLikelihoodRatio->getVariables();
00311 RemoveConstantParameters(partmp);
00312 RooArgList params(*partmp);
00313 delete partmp;
00314 int ix = params.index(¶m);
00315 if (ix < 0 ) {
00316 ccoutE(InputArguments) << "Error - invalid parameter " << param.GetName() << " specified for finding the interval limits " << std::endl;
00317 return false;
00318 }
00319
00320 bool ret = true;
00321 if (!fMinimizer.get()) ret = CreateMinimizer();
00322 if (!ret) {
00323 ccoutE(Eval) << "Error returned from minimization of likelihood function - cannot find interval limits " << std::endl;
00324 return false;
00325 }
00326
00327 assert(fMinimizer.get());
00328
00329
00330 double err_level = TMath::ChisquareQuantile(ConfidenceLevel(),1);
00331 err_level = err_level/2;
00332 fMinimizer->SetErrorDef(err_level);
00333
00334 unsigned int ivarX = ix;
00335
00336 double elow = 0;
00337 double eup = 0;
00338 ret = fMinimizer->GetMinosError(ivarX, elow, eup );
00339 if (!ret) {
00340 ccoutE(Minimization) << "Error running Minos for parameter " << param.GetName() << std::endl;
00341 return false;
00342 }
00343
00344
00345 if (elow == 0) {
00346 lower = param.getMin();
00347 ccoutW(Minimization) << "Warning: lower value for " << param.GetName() << " is at limit " << lower << std::endl;
00348 }
00349 else
00350 lower = fMinimizer->X()[ivarX] + elow;
00351
00352 if (eup == 0) {
00353 ccoutW(Minimization) << "Warning: upper value for " << param.GetName() << " is at limit " << upper << std::endl;
00354 upper = param.getMax();
00355 }
00356 else
00357 upper = fMinimizer->X()[ivarX] + eup;
00358
00359
00360
00361 fLowerLimits[param.GetName()] = lower;
00362 fUpperLimits[param.GetName()] = upper;
00363
00364 return true;
00365 }
00366
00367
00368 Int_t LikelihoodInterval::GetContourPoints(const RooRealVar & paramX, const RooRealVar & paramY, Double_t * x, Double_t *y, Int_t npoints ) {
00369
00370
00371
00372
00373
00374 RooArgSet * partmp = fLikelihoodRatio->getVariables();
00375 RemoveConstantParameters(partmp);
00376 RooArgList params(*partmp);
00377 delete partmp;
00378 int ix = params.index(¶mX);
00379 int iy = params.index(¶mY);
00380 if (ix < 0 || iy < 0) {
00381 ccoutE(InputArguments) << "Error - invalid parameters specified for finding the contours; parX = " << paramX.GetName()
00382 << " parY = " << paramY.GetName() << std::endl;
00383 return 0;
00384 }
00385
00386 bool ret = true;
00387 if (!fMinimizer.get()) ret = CreateMinimizer();
00388 if (!ret) {
00389 ccoutE(Eval) << "Error returned creating minimizer for likelihood function - cannot find contour points " << std::endl;
00390 return 0;
00391 }
00392
00393 assert(fMinimizer.get());
00394
00395
00396 double cont_level = TMath::ChisquareQuantile(ConfidenceLevel(),2);
00397 cont_level = cont_level/2;
00398 fMinimizer->SetErrorDef(cont_level);
00399
00400 unsigned int ncp = npoints;
00401 unsigned int ivarX = ix;
00402 unsigned int ivarY = iy;
00403 ret = fMinimizer->Contour(ivarX, ivarY, ncp, x, y );
00404 if (!ret) {
00405 ccoutE(Minimization) << "Error finding contour for parameters " << paramX.GetName() << " and " << paramY.GetName() << std::endl;
00406 return 0;
00407 }
00408 if (int(ncp) < npoints) {
00409 ccoutW(Minimization) << "Warning - Less points calculated in contours np = " << ncp << " / " << npoints << std::endl;
00410 }
00411
00412 return ncp;
00413 }