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  }