NumberCountingPdfFactory.cxx

Go to the documentation of this file.
00001 // @(#)root/roostats:$Id: NumberCountingPdfFactory.cxx 29179 2009-06-23 18:39:27Z brun $
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 A factory for building PDFs and data for a number counting combination.  
00017 The factory produces a PDF for N channels with uncorrelated background 
00018 uncertainty.  Correlations can be added by extending this PDF with additional terms.
00019 The factory relates the signal in each channel to a master signal strength times the 
00020 expected signal in each channel.  Thus, the final test is performed on the master signal strength.
00021 This yields a more powerful test than letting signal in each channel be independent.
00022 </p>
00023 <p>
00024 The problem has been studied in these references:
00025 <ul>
00026  <li>   http://arxiv.org/abs/physics/0511028</li>
00027  <li>   http://arxiv.org/abs/physics/0702156</li>
00028  <li>   http://cdsweb.cern.ch/record/1099969?ln=en</li>
00029 </ul>
00030 </p>
00031 
00032 <p>
00033 One can incorporate uncertainty on the expected signal by adding additional terms.
00034 For the future, perhaps this factory should be extended to include the efficiency terms automatically.
00035 </p>
00036 END_HTML
00037 */
00038 
00039 #ifndef RooStats_NumberCountingPdfFactory
00040 #include "RooStats/NumberCountingPdfFactory.h"
00041 #endif
00042 
00043 #ifndef RooStats_RooStatsUtils
00044 #include "RooStats/RooStatsUtils.h"
00045 #endif
00046 
00047 #include "RooRealVar.h"
00048 #include "RooAddition.h"
00049 #include "RooProduct.h"
00050 #include "RooDataSet.h"
00051 #include "RooProdPdf.h"
00052 #include "RooFitResult.h"
00053 #include "RooPoisson.h"
00054 #include "RooGlobalFunc.h"
00055 #include "RooCmdArg.h"
00056 #include "RooWorkspace.h"
00057 #include "RooMsgService.h"
00058 #include "TTree.h"
00059 #include <sstream>
00060 
00061 
00062 
00063 ClassImp(RooStats::NumberCountingPdfFactory) ;
00064 
00065 
00066 using namespace RooStats;
00067 using namespace RooFit;
00068 
00069 
00070 //_______________________________________________________
00071 NumberCountingPdfFactory::NumberCountingPdfFactory() {
00072    // constructor
00073 
00074 }
00075 
00076 //_______________________________________________________
00077 NumberCountingPdfFactory::~NumberCountingPdfFactory(){
00078    // destructor
00079 }
00080 
00081 //_______________________________________________________
00082 void NumberCountingPdfFactory::AddModel(Double_t* sig, 
00083                                         Int_t nbins, 
00084                                         RooWorkspace* ws, 
00085                                         const char* pdfName, const char* muName) {
00086   
00087 
00088 // This method produces a PDF for N channels with uncorrelated background 
00089 // uncertainty. It relates the signal in each channel to a master signal strength times the 
00090 // expected signal in each channel.
00091 //
00092 // For the future, perhaps this method should be extended to include the efficiency terms automatically.
00093 
00094    using namespace RooFit;
00095    using std::vector;
00096 
00097    TList likelihoodFactors;
00098 
00099    //  Double_t MaxSigma = 8; // Needed to set ranges for varaibles.
00100 
00101    RooRealVar*   masterSignal = 
00102       new RooRealVar(muName,"masterSignal",1., 0., 3.);
00103 
00104 
00105    // loop over individual channels
00106    for(Int_t i=0; i<nbins; ++i){
00107       // need to name the variables dynamically, so please forgive the string manipulation and focus on values & ranges.
00108       std::stringstream str;
00109       str<<"_"<<i;
00110       RooRealVar*   expectedSignal = 
00111          new RooRealVar(("expected_s"+str.str()).c_str(),("expected_s"+str.str()).c_str(),sig[i], 0., 2*sig[i]);
00112       expectedSignal->setConstant(kTRUE);
00113 
00114       RooProduct*   s = 
00115          new RooProduct(("s"+str.str()).c_str(),("s"+str.str()).c_str(), RooArgSet(*masterSignal, *expectedSignal)); 
00116 
00117       RooRealVar*   b = 
00118          new RooRealVar(("b"+str.str()).c_str(),("b"+str.str()).c_str(), .5,  0.,1.);
00119       RooRealVar*  tau = 
00120          new RooRealVar(("tau"+str.str()).c_str(),("tau"+str.str()).c_str(), .5, 0., 1.); 
00121       tau->setConstant(kTRUE);
00122 
00123       RooAddition*  splusb = 
00124          new RooAddition(("splusb"+str.str()).c_str(),("s"+str.str()+"+"+"b"+str.str()).c_str(),   
00125                          RooArgSet(*s,*b)); 
00126       RooProduct*   bTau = 
00127          new RooProduct(("bTau"+str.str()).c_str(),("b*tau"+str.str()).c_str(),   RooArgSet(*b, *tau)); 
00128       RooRealVar*   x = 
00129          new RooRealVar(("x"+str.str()).c_str(),("x"+str.str()).c_str(),  0.5 , 0., 1.);
00130       RooRealVar*   y = 
00131          new RooRealVar(("y"+str.str()).c_str(),("y"+str.str()).c_str(),  0.5,  0., 1.);
00132 
00133 
00134       RooPoisson* sigRegion = 
00135          new RooPoisson(("sigRegion"+str.str()).c_str(),("sigRegion"+str.str()).c_str(), *x,*splusb);
00136       RooPoisson* sideband = 
00137          new RooPoisson(("sideband"+str.str()).c_str(),("sideband"+str.str()).c_str(), *y,*bTau);
00138 
00139       likelihoodFactors.Add(sigRegion);
00140       likelihoodFactors.Add(sideband);
00141     
00142    }
00143 
00144    RooArgSet likelihoodFactorSet(likelihoodFactors);
00145    RooProdPdf joint(pdfName,"joint", likelihoodFactorSet );
00146    //  joint.printCompactTree();
00147 
00148    // add this PDF to workspace.  
00149    // Need to do import into workspace now to get all the structure imported as well.
00150    // Just returning the WS will loose the rest of the structure b/c it will go out of scope
00151    RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;
00152    ws->import(joint);
00153    RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ;
00154 }
00155 
00156 //_______________________________________________________
00157 void NumberCountingPdfFactory::AddExpData(Double_t* sig, 
00158                                           Double_t* back, 
00159                                           Double_t* back_syst, 
00160                                           Int_t nbins, 
00161                                           RooWorkspace* ws, const char* dsName) {
00162 
00163    // Arguements are an array of expected signal, expected background, and relative 
00164    // background uncertainty (eg. 0.1 for 10% uncertainty), and the number of channels.
00165 
00166    using std::vector;
00167    Double_t* mainMeas = new Double_t[nbins];
00168 
00169    // loop over channels
00170    for(Int_t i=0; i<nbins; ++i){
00171       mainMeas[i] = sig[i] + back[i];
00172    }
00173    return AddData(mainMeas, back, back_syst, nbins, ws, dsName);
00174 }
00175 
00176 //_______________________________________________________
00177 void NumberCountingPdfFactory::AddExpDataWithSideband(Double_t* sigExp, 
00178                                                       Double_t* backExp, 
00179                                                       Double_t* tau, 
00180                                                       Int_t nbins, 
00181                                                       RooWorkspace* ws, const char* dsName) {
00182 
00183    // Arguements are an array of expected signal, expected background, and relative 
00184    // ratio of background expected in the sideband to that expected in signal region, and the number of channels.
00185 
00186    Double_t* mainMeas = new Double_t[nbins];
00187    Double_t* sideband = new Double_t[nbins];
00188    for(Int_t i=0; i<nbins; ++i){
00189       mainMeas[i] = sigExp[i] + backExp[i];
00190       sideband[i] = backExp[i]*tau[i];
00191    }
00192    return AddDataWithSideband(mainMeas, sideband, tau, nbins, ws, dsName);
00193 
00194 }
00195 
00196 //_______________________________________________________
00197 RooRealVar* NumberCountingPdfFactory::SafeObservableCreation(RooWorkspace* ws, const char* varName, Double_t value) {
00198    // need to be careful here that the range of observable in the dataset is consistent with the one in the workspace
00199    // don't rescale unless necessary.  If it is necessary, then rescale by x10 or a defined maximum.
00200 
00201    return SafeObservableCreation(ws, varName, value, 10.*value);
00202 
00203 }
00204 
00205 //_______________________________________________________
00206 RooRealVar* NumberCountingPdfFactory::SafeObservableCreation(RooWorkspace* ws, const char* varName, 
00207                                                              Double_t value, Double_t maximum) {
00208    // need to be careful here that the range of observable in the dataset is consistent with the one in the workspace
00209    // don't rescale unless necessary.  If it is necessary, then rescale by x10 or a defined maximum.
00210 
00211    RooRealVar*   x = ws->var( varName );
00212    if( !x )
00213       x = new RooRealVar(varName, varName, value, 0, maximum );
00214    if( x->getMax() < value )
00215       x->setMax( max(x->getMax(), 10*value ) );
00216    x->setVal( value );
00217 
00218    return x;
00219 }
00220 
00221 
00222 //_______________________________________________________
00223 void NumberCountingPdfFactory::AddData(Double_t* mainMeas, 
00224                                        Double_t* back, 
00225                                        Double_t* back_syst, 
00226                                        Int_t nbins, 
00227                                        RooWorkspace* ws, const char* dsName) {
00228 
00229    // Arguments are an array of results from a main measurement, a measured background,
00230    //  and relative background uncertainty (eg. 0.1 for 10% uncertainty), and the number of channels.
00231 
00232    using namespace RooFit;
00233    using std::vector;
00234 
00235    Double_t MaxSigma = 8; // Needed to set ranges for varaibles.
00236 
00237    TList observablesCollection;
00238 
00239    TTree* tree = new TTree();
00240    Double_t* xForTree = new Double_t[nbins];
00241    Double_t* yForTree = new Double_t[nbins];
00242 
00243    // loop over channels
00244    for(Int_t i=0; i<nbins; ++i){
00245       std::stringstream str;
00246       str<<"_"<<i;
00247 
00248       Double_t _tau = 1./back[i]/back_syst[i]/back_syst[i];
00249       RooRealVar*  tau = SafeObservableCreation(ws,  ("tau"+str.str()).c_str(), _tau );
00250 
00251       oocoutW(ws,ObjectHandling) << "NumberCountingPdfFactory: changed value of " << tau->GetName() << " to " << tau->getVal() << 
00252          " to be consistent with background and its uncertainty. " <<
00253          " Also stored these values of tau into workspace with name . " << (string(tau->GetName())+string(dsName)).c_str() <<
00254          " if you test with a different dataset, you should adjust tau appropriately.\n"<< endl;
00255       RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;
00256       ws->import(*((RooRealVar*) tau->clone( (string(tau->GetName())+string(dsName)).c_str() ) ) );
00257       RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ;
00258 
00259       // need to be careful
00260       RooRealVar* x = SafeObservableCreation(ws, ("x"+str.str()).c_str(), mainMeas[i]);
00261     
00262       // need to be careful
00263       RooRealVar*   y = SafeObservableCreation(ws, ("y"+str.str()).c_str(), back[i]*_tau );
00264 
00265       observablesCollection.Add(x);
00266       observablesCollection.Add(y);
00267     
00268       xForTree[i] = mainMeas[i];
00269       yForTree[i] = back[i]*_tau;
00270 
00271       tree->Branch(("x"+str.str()).c_str(), xForTree+i ,("x"+str.str()+"/D").c_str());
00272       tree->Branch(("y"+str.str()).c_str(), yForTree+i ,("y"+str.str()+"/D").c_str());
00273 
00274       ws->var(("b"+str.str()).c_str())->setMax( 1.2*back[i]+MaxSigma*(sqrt(back[i])+back[i]*back_syst[i]) );
00275       ws->var(("b"+str.str()).c_str())->setVal( back[i] );
00276 
00277    }
00278    tree->Fill();
00279    //  tree->Print();
00280    //  tree->Scan();
00281 
00282    RooArgList* observableList = new RooArgList(observablesCollection);
00283 
00284    //  observableSet->Print();
00285    //  observableList->Print();
00286 
00287    RooDataSet* data = new RooDataSet(dsName,"Number Counting Data", tree, *observableList); // one experiment
00288    //  data->Scan();
00289 
00290 
00291    // import hypothetical data
00292    RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL) ;
00293    ws->import(*data);
00294    RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ;
00295 
00296 }
00297 
00298 //_______________________________________________________
00299 void NumberCountingPdfFactory::AddDataWithSideband(Double_t* mainMeas, 
00300                                                    Double_t* sideband, 
00301                                                    Double_t* tauForTree, 
00302                                                    Int_t nbins, 
00303                                                    RooWorkspace* ws, const char* dsName) {
00304 
00305    // Arguements are an array of expected signal, expected background, and relative 
00306    // background uncertainty (eg. 0.1 for 10% uncertainty), and the number of channels.
00307 
00308    using namespace RooFit;
00309    using std::vector;
00310 
00311    Double_t MaxSigma = 8; // Needed to set ranges for varaibles.
00312 
00313    TList observablesCollection;
00314 
00315    TTree* tree = new TTree();
00316    Double_t* xForTree = new Double_t[nbins];
00317    Double_t* yForTree = new Double_t[nbins];
00318 
00319    // loop over channels
00320    for(Int_t i=0; i<nbins; ++i){
00321       std::stringstream str;
00322       str<<"_"<<i;
00323 
00324       Double_t _tau = tauForTree[i];
00325       Double_t back_syst = 1./sqrt(sideband[i]);
00326       Double_t back = (sideband[i]/_tau);
00327 
00328 
00329       RooRealVar*  tau = SafeObservableCreation(ws,  ("tau"+str.str()).c_str(), _tau );
00330 
00331       oocoutW(ws,ObjectHandling) << "NumberCountingPdfFactory: changed value of " << tau->GetName() << " to " << tau->getVal() << 
00332          " to be consistent with background and its uncertainty. " <<
00333          " Also stored these values of tau into workspace with name . " << (string(tau->GetName())+string(dsName)).c_str() <<
00334          " if you test with a different dataset, you should adjust tau appropriately.\n"<< endl;
00335       RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;
00336       ws->import(*((RooRealVar*) tau->clone( (string(tau->GetName())+string(dsName)).c_str() ) ) );
00337       RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ;
00338 
00339       // need to be careful
00340       RooRealVar* x = SafeObservableCreation(ws, ("x"+str.str()).c_str(), mainMeas[i]);
00341     
00342       // need to be careful
00343       RooRealVar*   y = SafeObservableCreation(ws, ("y"+str.str()).c_str(), sideband[i] );
00344 
00345 
00346       observablesCollection.Add(x);
00347       observablesCollection.Add(y);
00348     
00349       xForTree[i] = mainMeas[i];
00350       yForTree[i] = sideband[i];
00351 
00352       tree->Branch(("x"+str.str()).c_str(), xForTree+i ,("x"+str.str()+"/D").c_str());
00353       tree->Branch(("y"+str.str()).c_str(), yForTree+i ,("y"+str.str()+"/D").c_str());
00354 
00355       ws->var(("b"+str.str()).c_str())->setMax(  1.2*back+MaxSigma*(sqrt(back)+back*back_syst) );
00356       ws->var(("b"+str.str()).c_str())->setVal( back );
00357 
00358    }
00359    tree->Fill();
00360    //  tree->Print();
00361    //  tree->Scan();
00362 
00363    RooArgList* observableList = new RooArgList(observablesCollection);
00364 
00365    //  observableSet->Print();
00366    //  observableList->Print();
00367 
00368    RooDataSet* data = new RooDataSet(dsName,"Number Counting Data", tree, *observableList); // one experiment
00369    //  data->Scan();
00370 
00371 
00372    // import hypothetical data
00373    RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL) ;
00374    ws->import(*data);
00375    RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ;
00376 
00377 }
00378 
00379 
00380 

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