CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/HiggsAnalysis/CombinedLimit/src/SimplerLikelihoodRatioTestStatExt.cc

Go to the documentation of this file.
00001 #include "../interface/SimplerLikelihoodRatioTestStatExt.h"
00002 #include "../interface/utils.h"
00003 
00004 SimplerLikelihoodRatioTestStatOpt::SimplerLikelihoodRatioTestStatOpt(
00005         const RooArgSet &obs, 
00006         RooAbsPdf &pdfNull, RooAbsPdf &pdfAlt, 
00007         const RooArgSet & paramsNull, const RooArgSet & paramsAlt, 
00008         bool factorize) :
00009     obs_(&obs)
00010 {
00011     // take a snapshot of the pdf so we can modify it at will
00012     RooAbsPdf *cloneNull = utils::fullClonePdf(&pdfNull, pdfCompNull_);
00013     RooAbsPdf *cloneAlt  = utils::fullClonePdf(&pdfAlt, pdfCompAlt_);
00014 
00015     // factorize away constraints
00016     RooArgList constraints;
00017     pdfNull_ = factorize ? utils::factorizePdf(obs, *cloneNull, constraints) : cloneNull;
00018     if (pdfNull_ == 0) throw std::invalid_argument("SimplerLikelihoodRatioTestStatOpt:: pdf does not depend on observables");
00019     if (pdfNull_ != cloneNull) pdfNullOwned_.reset(pdfNull_); // if new, then take ownership of it
00020     if (cloneNull == cloneAlt) {
00021         pdfAlt_ = pdfNull_;
00022     } else {
00023         pdfAlt_  = factorize ? utils::factorizePdf(obs, *cloneAlt,  constraints) : cloneAlt;
00024         if (pdfAlt_ == 0) throw std::invalid_argument("SimplerLikelihoodRatioTestStatOpt:: pdf does not depend on observables");
00025         if (pdfAlt_ != cloneAlt)  pdfAltOwned_.reset(pdfAlt_); // if new, then take ownership of it
00026     }
00027 
00028     // take snapshot of parameters
00029     snapNull_.addClone(paramsNull);
00030     snapAlt_.addClone(paramsAlt);
00031 
00032     // if the pdf is a RooSimultaneous, unroll it
00033     simPdfNull_ =  dynamic_cast<RooSimultaneous *>(pdfNull_);
00034     simPdfAlt_ =  dynamic_cast<RooSimultaneous *>(pdfAlt_);
00035     if (simPdfNull_) unrollSimPdf(simPdfNull_, simPdfComponentsNull_);
00036     if (simPdfAlt_) unrollSimPdf(simPdfAlt_, simPdfComponentsAlt_);
00037 
00038     // optimize caching
00039     pdfNull_->optimizeCacheMode(*obs_);
00040     pdfAlt_->optimizeCacheMode(*obs_);
00041 
00042     // find nodes that directly depend on observables
00043     utils::getClients(*obs_, pdfCompNull_, pdfDepObs_);
00044     utils::getClients(*obs_, pdfCompAlt_,  pdfDepObs_);
00045 }
00046 
00047 SimplerLikelihoodRatioTestStatOpt::~SimplerLikelihoodRatioTestStatOpt() 
00048 {
00049 }
00050 
00051 Double_t
00052 SimplerLikelihoodRatioTestStatOpt::Evaluate(RooAbsData& data, RooArgSet& nullPOI) 
00053 {
00054     // get parameters, if not there already
00055     if (paramsNull_.get() == 0) paramsNull_.reset(pdfNull_->getParameters(data));
00056     if (paramsAlt_.get() == 0)  paramsAlt_.reset(pdfAlt_->getParameters(data));
00057 
00058     // if the dataset is not empty, redirect pdf nodes to the dataset
00059     std::auto_ptr<TIterator> iterDepObs(pdfDepObs_.createIterator());
00060     bool nonEmpty = data.numEntries() > 0;
00061     if (nonEmpty) {
00062         const RooArgSet *entry = data.get(0);
00063         for (RooAbsArg *a = (RooAbsArg *) iterDepObs->Next(); a != 0; a = (RooAbsArg *) iterDepObs->Next()) {
00064             a->redirectServers(*entry);    
00065         }
00066     }
00067 
00068     // evaluate null pdf
00069     *paramsNull_ = snapNull_;
00070     *paramsNull_ = nullPOI;
00071     double nullNLL = simPdfNull_ ? evalSimNLL(data, simPdfNull_, simPdfComponentsNull_) : evalSimpleNLL(data, pdfNull_);
00072 
00073     // evaluate alt pdf
00074     *paramsAlt_ = snapAlt_;
00075     double altNLL = simPdfAlt_ ? evalSimNLL(data, simPdfAlt_, simPdfComponentsAlt_) : evalSimpleNLL(data, pdfAlt_);
00076 
00077     // put back links in pdf nodes, otherwise if the dataset goes out of scope they have dangling pointers
00078     if (nonEmpty) {
00079         iterDepObs->Reset();
00080         for (RooAbsArg *a = (RooAbsArg *) iterDepObs->Next(); a != 0; a = (RooAbsArg *) iterDepObs->Next()) {
00081             a->redirectServers(*obs_);    
00082         }
00083     }
00084 
00085     return nullNLL-altNLL;
00086 }
00087 
00088 void SimplerLikelihoodRatioTestStatOpt::unrollSimPdf(RooSimultaneous *simpdf, std::vector<RooAbsPdf *> &out) {
00089     // get a clone of the pdf category, so that I can use it to enumerate the pdf states
00090     std::auto_ptr<RooAbsCategoryLValue> catClone((RooAbsCategoryLValue*) simpdf->indexCat().Clone());
00091     out.resize(catClone->numBins(NULL), 0);
00092     //std::cout << "Pdf " << pdf->GetName() <<" is a SimPdf over category " << catClone->GetName() << ", with " << out.size() << " bins" << std::endl;
00093 
00094     // loop on the category state and fetch the pdfs
00095     for (int ib = 0, nb = out.size(); ib < nb; ++ib) {
00096         catClone->setBin(ib);
00097         RooAbsPdf *pdfi = simpdf->getPdf(catClone->getLabel());
00098         pdfi->optimizeCacheMode(*obs_);
00099         if (pdfi != 0) {
00100             //std::cout << "   bin " << ib << " (label " << catClone->getLabel() << ") has pdf " << pdfi->GetName() << " of type " << pdfi->ClassName() << std::endl;
00101             out[ib] = pdfi;
00102         }
00103     }
00104 }
00105 
00106 double SimplerLikelihoodRatioTestStatOpt::evalSimNLL(RooAbsData &data,  RooSimultaneous *pdf, std::vector<RooAbsPdf *> &components) {
00107     data.setDirtyProp(false);
00108 
00109     double sum = 0.0;
00110     int i, n = data.numEntries(); 
00111 
00112     // must fetch the category, from the dataset first, if it's not empty
00113     RooAbsCategoryLValue *cat = 0;
00114     if (n) {
00115         const RooArgSet *entry = data.get(0);
00116         cat = dynamic_cast<RooAbsCategoryLValue *>(entry->find(pdf->indexCat().GetName()));
00117         assert(cat != 0 && "Didn't find category in dataset");
00118     }
00119 
00120     // now loop on the dataset, and dispatch the request to the appropriate pdf
00121     std::vector<double> sumw(components.size(), 0);
00122     for (i = 0; i < n; ++i) {
00123         data.get(i); 
00124         double w = data.weight(); if (w == 0) continue;
00125         int bin = cat->getBin();
00126         assert(bin < int(components.size()) && "Bin outside range");
00127         if (components[bin] == 0) continue;
00128         sum  += -w*components[bin]->getLogVal(obs_);
00129         sumw[bin] +=  w;
00130     }
00131 
00132     // then compute extended term
00133     for (i = 0, n = components.size(); i < n; ++i) {
00134         if (components[i]) sum += components[i]->extendedTerm(UInt_t(sumw[i]), obs_);
00135     }
00136     return sum;
00137 }
00138 
00139 double SimplerLikelihoodRatioTestStatOpt::evalSimpleNLL(RooAbsData &data,  RooAbsPdf *pdf) {
00140     data.setDirtyProp(false);
00141     double sum = 0.0, sumw = 0.0;
00142     int i, n = data.numEntries(); 
00143     for (i = 0; i < n; ++i) {
00144         data.get(i); 
00145         double w = data.weight(); if (w == 0) continue;
00146         sum  += -w*pdf->getLogVal(obs_);
00147         sumw +=  w;
00148     }
00149     sum += pdf->extendedTerm(UInt_t(sumw), obs_);
00150     return sum;
00151 }
00152 
00153 // ===== This below is identical to the RooStats::SimpleLikelihoodRatioTestStat also in implementation
00154 //       I've made a copy here just to be able to put some debug hooks inside.
00155 #if 0
00156 
00157 SimplerLikelihoodRatioTestStatExt::SimplerLikelihoodRatioTestStatExt(
00158         const RooArgSet &obs, 
00159         RooAbsPdf &pdfNull, RooAbsPdf &pdfAlt, 
00160         const RooArgSet & paramsNull, const RooArgSet & paramsAlt)
00161 {
00162     RooArgList constraints;
00163     pdfNull_ = &pdfNull;
00164     pdfAlt_  = &pdfAlt;
00165     paramsNull_.reset(pdfNull_->getVariables());
00166     paramsAlt_.reset(pdfAlt_->getVariables());
00167     snapNull_.addClone(paramsNull);
00168     snapAlt_.addClone(paramsAlt);
00169 }
00170 
00171 SimplerLikelihoodRatioTestStatExt::~SimplerLikelihoodRatioTestStatExt() 
00172 {
00173 }
00174 
00175 Double_t
00176 SimplerLikelihoodRatioTestStatExt::Evaluate(RooAbsData& data, RooArgSet& nullPOI) 
00177 {
00178     std::auto_ptr<RooAbsReal> nllNull_(pdfNull_->createNLL(data));
00179     std::auto_ptr<RooAbsReal> nllAlt_(pdfAlt_->createNLL(data));
00180 
00181     *paramsNull_ = snapNull_;
00182     *paramsNull_ = nullPOI;
00183     double nullNLL = nllNull_->getVal();
00184 
00185     *paramsAlt_ = snapAlt_;
00186     double altNLL = nllAlt_->getVal();
00187     return nullNLL-altNLL;
00188 }
00189 
00190 #endif