ProfileLikelihoodCalculator.cxx

Go to the documentation of this file.
00001 // @(#)root/roostats:$Id: ProfileLikelihoodCalculator.cxx 36586 2010-11-10 15:09:58Z moneta $
00002 // Author: Kyle Cranmer   28/07/2008
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //_________________________________________________
00013 /*
00014 BEGIN_HTML
00015 <p>
00016 ProfileLikelihoodCalculator is a concrete implementation of CombinedCalculator 
00017 (the interface class for a tools which can produce both RooStats HypoTestResults and ConfIntervals).  
00018 The tool uses the profile likelihood ratio as a test statistic, and assumes that Wilks' theorem is valid.  
00019 Wilks' theorem states that -2* log (profile likelihood ratio) is asymptotically distributed as a chi^2 distribution 
00020 with N-dof, where N is the number of degrees of freedom.  Thus, p-values can be constructed and the profile likelihood ratio
00021 can be used to construct a LikelihoodInterval.
00022 (In the future, this class could be extended to use toy Monte Carlo to calibrate the distribution of the test statistic).
00023 </p>
00024 <p> Usage: It uses the interface of the CombinedCalculator, so that it can be configured by specifying:
00025 <ul>
00026  <li>a model common model (eg. a family of specific models which includes both the null and alternate),</li>
00027  <li>a data set, </li>
00028  <li>a set of parameters of interest. The nuisance parameters will be all other parameters of the model </li>
00029  <li>a set of parameters of which specify the null hypothesis (including values and const/non-const status)  </li>
00030 </ul>
00031 The interface allows one to pass the model, data, and parameters either directly or via a ModelConfig class.
00032 The alternate hypothesis leaves the parameter free to take any value other than those specified by the null hypotesis. There is therefore no need to 
00033 specify the alternate parameters. 
00034 </p>
00035 <p>
00036 After configuring the calculator, one only needs to ask GetHypoTest() (which will return a HypoTestResult pointer) or GetInterval() (which will return an ConfInterval pointer).
00037 </p>
00038 <p>
00039 The concrete implementations of this interface should deal with the details of how the nuisance parameters are
00040 dealt with (eg. integration vs. profiling) and which test-statistic is used (perhaps this should be added to the interface).
00041 </p>
00042 <p>
00043 The motivation for this interface is that we hope to be able to specify the problem in a common way for several concrete calculators.
00044 </p>
00045 END_HTML
00046 */
00047 //
00048 
00049 #ifndef RooStats_ProfileLikelihoodCalculator
00050 #include "RooStats/ProfileLikelihoodCalculator.h"
00051 #endif
00052 
00053 #ifndef RooStats_RooStatsUtils
00054 #include "RooStats/RooStatsUtils.h"
00055 #endif
00056 
00057 #include "RooStats/LikelihoodInterval.h"
00058 #include "RooStats/HypoTestResult.h"
00059 
00060 #include "RooFitResult.h"
00061 #include "RooRealVar.h"
00062 #include "RooProfileLL.h"
00063 #include "RooNLLVar.h"
00064 #include "RooGlobalFunc.h"
00065 //#include "RooProdPdf.h"
00066 
00067 ClassImp(RooStats::ProfileLikelihoodCalculator) ;
00068 
00069 using namespace RooFit;
00070 using namespace RooStats;
00071 
00072 
00073 //_______________________________________________________
00074 ProfileLikelihoodCalculator::ProfileLikelihoodCalculator() : 
00075    CombinedCalculator(), fFitResult(0)
00076 {
00077    // default constructor
00078 }
00079 
00080 ProfileLikelihoodCalculator::ProfileLikelihoodCalculator(RooAbsData& data, RooAbsPdf& pdf, const RooArgSet& paramsOfInterest, 
00081                                                          Double_t size, const RooArgSet* nullParams ) :
00082    CombinedCalculator(data,pdf, paramsOfInterest, size, nullParams ), 
00083    fFitResult(0)
00084 {
00085    // constructor from pdf and parameters
00086    // the pdf must contain eventually the nuisance parameters
00087 }
00088 
00089 ProfileLikelihoodCalculator::ProfileLikelihoodCalculator(RooAbsData& data,  ModelConfig& model, Double_t size) :
00090    CombinedCalculator(data, model, size), 
00091    fFitResult(0)
00092 {
00093    // construct from a ModelConfig. Assume data model.GetPdf() will provide full description of model including 
00094    // constraint term on the nuisances parameters
00095    assert(model.GetPdf() );
00096 }
00097 
00098 
00099 //_______________________________________________________
00100 ProfileLikelihoodCalculator::~ProfileLikelihoodCalculator(){
00101    // destructor
00102    // cannot delete prod pdf because it will delete all the composing pdf's
00103 //    if (fOwnPdf) delete fPdf; 
00104 //    fPdf = 0; 
00105    if (fFitResult) delete fFitResult; 
00106 }
00107 
00108 void ProfileLikelihoodCalculator::DoReset() const { 
00109    // reset and clear fit result 
00110    // to be called when a new model or data are set in the calculator 
00111    if (fFitResult) delete fFitResult; 
00112    fFitResult = 0; 
00113 }
00114 
00115 void  ProfileLikelihoodCalculator::DoGlobalFit() const { 
00116    // perform a global fit of the likelihood letting with all parameter of interest and 
00117    // nuisance parameters 
00118    // keep the list of fitted parameters 
00119 
00120    DoReset(); 
00121    RooAbsPdf * pdf = GetPdf();
00122    RooAbsData* data = GetData(); 
00123    if (!data || !pdf ) return;
00124 
00125    // get all non-const parameters
00126    RooArgSet* constrainedParams = pdf->getParameters(*data);
00127    if (!constrainedParams) return ; 
00128    RemoveConstantParameters(constrainedParams);
00129 
00130    // calculate MLE 
00131    RooFitResult* fit = pdf->fitTo(*data, Constrain(*constrainedParams),Strategy(1),Hesse(kTRUE),Save(kTRUE),PrintLevel(-1));
00132   
00133    // for debug 
00134    fit->Print();
00135 
00136    delete constrainedParams; 
00137    // store fit result for further use 
00138    fFitResult =  fit; 
00139    if (fFitResult == 0) 
00140       oocoutI((TObject*)0,Minimization) << "ProfileLikelihoodCalcultor::DoGlobalFit -  Global fit failed " << std::endl;      
00141 
00142 }
00143 
00144 //_______________________________________________________
00145 LikelihoodInterval* ProfileLikelihoodCalculator::GetInterval() const {
00146    // Main interface to get a RooStats::ConfInterval.  
00147    // It constructs a profile likelihood ratio and uses that to construct a RooStats::LikelihoodInterval.
00148 
00149 //    RooAbsPdf* pdf   = fWS->pdf(fPdfName);
00150 //    RooAbsData* data = fWS->data(fDataName);
00151    RooAbsPdf * pdf = GetPdf();
00152    RooAbsData* data = GetData(); 
00153    if (!data || !pdf || fPOI.getSize() == 0) return 0;
00154 
00155    RooArgSet* constrainedParams = pdf->getParameters(*data);
00156    RemoveConstantParameters(constrainedParams);
00157 
00158 
00159    /*
00160    RooNLLVar* nll = new RooNLLVar("nll","",*pdf,*data, Extended(),Constrain(*constrainedParams));
00161    RooProfileLL* profile = new RooProfileLL("pll","",*nll, *fPOI);
00162    profile->addOwnedComponents(*nll) ;  // to avoid memory leak
00163    */
00164 
00165    RooAbsReal* nll = pdf->createNLL(*data, CloneData(kTRUE), Constrain(*constrainedParams));
00166    RooAbsReal* profile = nll->createProfile(fPOI);
00167    profile->addOwnedComponents(*nll) ;  // to avoid memory leak
00168 
00169 
00170    //RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL) ;
00171    // perform a Best Fit 
00172    if (!fFitResult) DoGlobalFit();
00173    // if fit fails return
00174    if (!fFitResult)   return 0;
00175 
00176    // t.b.f. " RooProfileLL should keep and provide possibility to query on global minimum
00177    // set POI to fit value (this will speed up profileLL calculation of global minimum)
00178    const RooArgList & fitParams = fFitResult->floatParsFinal(); 
00179    for (int i = 0; i < fitParams.getSize(); ++i) {
00180       RooRealVar & fitPar =  (RooRealVar &) fitParams[i];
00181       RooRealVar * par = (RooRealVar*) fPOI.find( fitPar.GetName() );      
00182       if (par) { 
00183          par->setVal( fitPar.getVal() );
00184          par->setError( fitPar.getError() );
00185       }
00186    }
00187   
00188    // do this so profile will cache inside the absolute minimum and 
00189    // minimum values of nuisance parameters
00190    profile->getVal(); 
00191    //RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ;
00192    //  profile->Print();
00193 
00194    TString name = TString("LikelihoodInterval_");// + TString(GetName() ); 
00195 
00196    // make a list of fPOI with fit result values and pass to LikelihoodInterval class
00197    // bestPOI is a cloned list of POI only with their best fit values 
00198    TIter iter = fPOI.createIterator(); 
00199    RooArgSet fitParSet(fitParams); 
00200    RooArgSet * bestPOI = new RooArgSet();  
00201    while (RooAbsArg * arg =  (RooAbsArg*) iter.Next() ) { 
00202       RooAbsArg * p  =  fitParSet.find( arg->GetName() );
00203       if (p) bestPOI->addClone(*p);
00204       else bestPOI->addClone(*arg);
00205    }
00206    // fPOI contains the paramter of interest of the PL object 
00207    // and bestPOI contains a snapshot with the best fit values 
00208    LikelihoodInterval* interval = new LikelihoodInterval(name, profile, &fPOI, bestPOI);
00209    interval->SetConfidenceLevel(1.-fSize);
00210    delete constrainedParams;
00211    return interval;
00212 }
00213 
00214 //_______________________________________________________
00215 HypoTestResult* ProfileLikelihoodCalculator::GetHypoTest() const {
00216    // Main interface to get a HypoTestResult.
00217    // It does two fits:
00218    // the first lets the null parameters float, so it's a maximum likelihood estimate
00219    // the second is to the null (fixing null parameters to their specified values): eg. a conditional maximum likelihood
00220    // the ratio of the likelihood at the conditional MLE to the MLE is the profile likelihood ratio.
00221    // Wilks' theorem is used to get p-values 
00222 
00223 //    RooAbsPdf* pdf   = fWS->pdf(fPdfName);
00224 //    RooAbsData* data = fWS->data(fDataName);
00225    RooAbsPdf * pdf = GetPdf();
00226    RooAbsData* data = GetData(); 
00227 
00228 
00229    if (!data || !pdf) return 0;
00230 
00231    if (fNullParams.getSize() == 0) return 0; 
00232 
00233    // make a clone and ordered list since a vector will be associated to keep parameter values
00234    // clone the list since first fit will changes the fNullParams values
00235    RooArgList poiList; 
00236    poiList.addClone(fNullParams); // make a clone list 
00237 
00238 
00239    // do a global fit 
00240    if (!fFitResult) DoGlobalFit(); 
00241    if (!fFitResult) return 0; 
00242 
00243    RooArgSet* constrainedParams = pdf->getParameters(*data);
00244    RemoveConstantParameters(constrainedParams);
00245 
00246    // perform a global fit if it is not done before
00247    if (!fFitResult) DoGlobalFit(); 
00248    Double_t NLLatMLE= fFitResult->minNll();
00249 
00250    // set POI to given values, set constant, calculate conditional MLE
00251    std::vector<double> oldValues(poiList.getSize() ); 
00252    for (unsigned int i = 0; i < oldValues.size(); ++i) { 
00253       RooRealVar * mytarget = (RooRealVar*) constrainedParams->find(poiList[i].GetName());
00254       if (mytarget) { 
00255          oldValues[i] = mytarget->getVal(); 
00256          mytarget->setVal( ( (RooRealVar&) poiList[i] ).getVal() );
00257          mytarget->setConstant(kTRUE);
00258       }
00259    }
00260 
00261    
00262 
00263    // perform the fit only if nuisance parameters are available
00264    // get nuisance parameters
00265    // nuisance parameters are the non const parameters from the likelihood parameters
00266    RooArgSet nuisParams(*constrainedParams);
00267 
00268    // need to remove the parameter of interest
00269    RemoveConstantParameters(&nuisParams);
00270 
00271    // check there are variable parameter in order to do a fit 
00272    bool existVarParams = false; 
00273    TIter it = nuisParams.createIterator();
00274    RooRealVar * myarg = 0; 
00275    while ((myarg = (RooRealVar *)it.Next())) { 
00276       if ( !myarg->isConstant() ) {
00277          existVarParams = true; 
00278          break;
00279       }
00280    }
00281 
00282    Double_t NLLatCondMLE = NLLatMLE; 
00283    if (existVarParams) {
00284 
00285       RooFitResult* fit2 = pdf->fitTo(*data,Constrain(*constrainedParams),Hesse(kFALSE),Strategy(0), Minos(kFALSE), Save(kTRUE),PrintLevel(-1));
00286      
00287       NLLatCondMLE = fit2->minNll();
00288       fit2->Print();
00289    }
00290    else { 
00291       // get just the likelihood value (no need to do a fit since the likelihood is a constant function)
00292       RooAbsReal* nll = pdf->createNLL(*data, CloneData(kTRUE), Constrain(*constrainedParams));
00293       NLLatCondMLE = nll->getVal();
00294       delete nll;
00295    }
00296 
00297    // Use Wilks' theorem to translate -2 log lambda into a signifcance/p-value
00298    Double_t deltaNLL = std::max( NLLatCondMLE-NLLatMLE, 0.);
00299 
00300    TString name = TString("ProfileLRHypoTestResult_");// + TString(GetName() ); 
00301    HypoTestResult* htr = 
00302       new HypoTestResult(name, SignificanceToPValue(sqrt( 2*deltaNLL)), 0 );
00303 
00304 
00305    // restore previous value of poi
00306    for (unsigned int i = 0; i < oldValues.size(); ++i) { 
00307       RooRealVar * mytarget = (RooRealVar*) constrainedParams->find(poiList[i].GetName());
00308       if (mytarget) { 
00309          mytarget->setVal(oldValues[i] ); 
00310          mytarget->setConstant(false); 
00311       }
00312    }
00313 
00314    delete constrainedParams;
00315    return htr;
00316 
00317 }
00318 

Generated on Tue Jul 5 15:14:36 2011 for ROOT_528-00b_version by  doxygen 1.5.1