// @(#)root/roostats:$Id$ // Author: Kyle Cranmer 28/07/2008 /************************************************************************* * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ //___________________________________________________ /* BEGIN_HTML

A factory for building PDFs and data for a number counting combination. The factory produces a PDF for N channels with uncorrelated background uncertainty. Correlations can be added by extending this PDF with additional terms. The factory relates the signal in each channel to a master signal strength times the expected signal in each channel. Thus, the final test is performed on the master signal strength. This yields a more powerful test than letting signal in each channel be independent.

The problem has been studied in these references:

One can incorporate uncertainty on the expected signal by adding additional terms. For the future, perhaps this factory should be extended to include the efficiency terms automatically.

END_HTML */ #ifndef RooStats_NumberCountingPdfFactory #include "RooStats/NumberCountingPdfFactory.h" #endif #ifndef RooStats_RooStatsUtils #include "RooStats/RooStatsUtils.h" #endif #include "RooRealVar.h" #include "RooAddition.h" #include "RooProduct.h" #include "RooDataSet.h" #include "RooProdPdf.h" #include "RooFitResult.h" #include "RooPoisson.h" #include "RooGlobalFunc.h" #include "RooCmdArg.h" #include "RooWorkspace.h" #include "RooMsgService.h" #include "TTree.h" #include ClassImp(RooStats::NumberCountingPdfFactory) ; using namespace RooStats; using namespace RooFit; using namespace std; //_______________________________________________________ NumberCountingPdfFactory::NumberCountingPdfFactory() { // constructor } //_______________________________________________________ NumberCountingPdfFactory::~NumberCountingPdfFactory(){ // destructor } //_______________________________________________________ void NumberCountingPdfFactory::AddModel(Double_t* sig, Int_t nbins, RooWorkspace* ws, const char* pdfName, const char* muName) { // This method produces a PDF for N channels with uncorrelated background // uncertainty. It relates the signal in each channel to a master signal strength times the // expected signal in each channel. // // For the future, perhaps this method should be extended to include the efficiency terms automatically. using namespace RooFit; using std::vector; TList likelihoodFactors; // Double_t MaxSigma = 8; // Needed to set ranges for varaibles. RooRealVar* masterSignal = new RooRealVar(muName,"masterSignal",1., 0., 3.); // loop over individual channels for(Int_t i=0; isetConstant(kTRUE); RooProduct* s = new RooProduct(("s"+str.str()).c_str(),("s"+str.str()).c_str(), RooArgSet(*masterSignal, *expectedSignal)); RooRealVar* b = new RooRealVar(("b"+str.str()).c_str(),("b"+str.str()).c_str(), .5, 0.,1.); RooRealVar* tau = new RooRealVar(("tau"+str.str()).c_str(),("tau"+str.str()).c_str(), .5, 0., 1.); tau->setConstant(kTRUE); RooAddition* splusb = new RooAddition(("splusb"+str.str()).c_str(),("s"+str.str()+"+"+"b"+str.str()).c_str(), RooArgSet(*s,*b)); RooProduct* bTau = new RooProduct(("bTau"+str.str()).c_str(),("b*tau"+str.str()).c_str(), RooArgSet(*b, *tau)); RooRealVar* x = new RooRealVar(("x"+str.str()).c_str(),("x"+str.str()).c_str(), 0.5 , 0., 1.); RooRealVar* y = new RooRealVar(("y"+str.str()).c_str(),("y"+str.str()).c_str(), 0.5, 0., 1.); RooPoisson* sigRegion = new RooPoisson(("sigRegion"+str.str()).c_str(),("sigRegion"+str.str()).c_str(), *x,*splusb); //LM: need to set noRounding since y can take non integer values RooPoisson* sideband = new RooPoisson(("sideband"+str.str()).c_str(),("sideband"+str.str()).c_str(), *y,*bTau,true); likelihoodFactors.Add(sigRegion); likelihoodFactors.Add(sideband); } RooArgSet likelihoodFactorSet(likelihoodFactors); RooProdPdf joint(pdfName,"joint", likelihoodFactorSet ); // joint.printCompactTree(); // add this PDF to workspace. // Need to do import into workspace now to get all the structure imported as well. // Just returning the WS will loose the rest of the structure b/c it will go out of scope RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ; ws->import(joint); RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ; } //_______________________________________________________ void NumberCountingPdfFactory::AddExpData(Double_t* sig, Double_t* back, Double_t* back_syst, Int_t nbins, RooWorkspace* ws, const char* dsName) { // Arguements are an array of expected signal, expected background, and relative // background uncertainty (eg. 0.1 for 10% uncertainty), and the number of channels. std::vector mainMeas(nbins); // loop over channels for(Int_t i=0; i mainMeas(nbins); std::vector sideband(nbins); for(Int_t i=0; ivar( varName ); if( !x ) x = new RooRealVar(varName, varName, value, 0, maximum ); if( x->getMax() < value ) x->setMax( max(x->getMax(), 10*value ) ); x->setVal( value ); return x; } //_______________________________________________________ void NumberCountingPdfFactory::AddData(Double_t* mainMeas, Double_t* back, Double_t* back_syst, Int_t nbins, RooWorkspace* ws, const char* dsName) { // Arguments are an array of results from a main measurement, a measured background, // and relative background uncertainty (eg. 0.1 for 10% uncertainty), and the number of channels. using namespace RooFit; using std::vector; Double_t MaxSigma = 8; // Needed to set ranges for varaibles. TList observablesCollection; TTree* tree = new TTree(); std::vector xForTree(nbins); std::vector yForTree(nbins); // loop over channels for(Int_t i=0; iGetName() << " to " << tau->getVal() << " to be consistent with background and its uncertainty. " << " Also stored these values of tau into workspace with name . " << (string(tau->GetName())+string(dsName)).c_str() << " if you test with a different dataset, you should adjust tau appropriately.\n"<< endl; RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ; ws->import(*((RooRealVar*) tau->clone( (string(tau->GetName())+string(dsName)).c_str() ) ) ); RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ; // need to be careful RooRealVar* x = SafeObservableCreation(ws, ("x"+str.str()).c_str(), mainMeas[i]); // need to be careful RooRealVar* y = SafeObservableCreation(ws, ("y"+str.str()).c_str(), back[i]*_tau ); observablesCollection.Add(x); observablesCollection.Add(y); xForTree[i] = mainMeas[i]; yForTree[i] = back[i]*_tau; tree->Branch(("x"+str.str()).c_str(), &xForTree[i] ,("x"+str.str()+"/D").c_str()); tree->Branch(("y"+str.str()).c_str(), &yForTree[i] ,("y"+str.str()+"/D").c_str()); ws->var(("b"+str.str()).c_str())->setMax( 1.2*back[i]+MaxSigma*(sqrt(back[i])+back[i]*back_syst[i]) ); ws->var(("b"+str.str()).c_str())->setVal( back[i] ); } tree->Fill(); // tree->Print(); // tree->Scan(); RooArgList* observableList = new RooArgList(observablesCollection); // observableSet->Print(); // observableList->Print(); RooDataSet* data = new RooDataSet(dsName,"Number Counting Data", tree, *observableList); // one experiment // data->Scan(); // import hypothetical data RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL) ; ws->import(*data); RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ; } //_______________________________________________________ void NumberCountingPdfFactory::AddDataWithSideband(Double_t* mainMeas, Double_t* sideband, Double_t* tauForTree, Int_t nbins, RooWorkspace* ws, const char* dsName) { // Arguements are an array of expected signal, expected background, and relative // background uncertainty (eg. 0.1 for 10% uncertainty), and the number of channels. using namespace RooFit; using std::vector; Double_t MaxSigma = 8; // Needed to set ranges for varaibles. TList observablesCollection; TTree* tree = new TTree(); std::vector xForTree(nbins); std::vector yForTree(nbins); // loop over channels for(Int_t i=0; iGetName() << " to " << tau->getVal() << " to be consistent with background and its uncertainty. " << " Also stored these values of tau into workspace with name . " << (string(tau->GetName())+string(dsName)).c_str() << " if you test with a different dataset, you should adjust tau appropriately.\n"<< endl; RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ; ws->import(*((RooRealVar*) tau->clone( (string(tau->GetName())+string(dsName)).c_str() ) ) ); RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ; // need to be careful RooRealVar* x = SafeObservableCreation(ws, ("x"+str.str()).c_str(), mainMeas[i]); // need to be careful RooRealVar* y = SafeObservableCreation(ws, ("y"+str.str()).c_str(), sideband[i] ); observablesCollection.Add(x); observablesCollection.Add(y); xForTree[i] = mainMeas[i]; yForTree[i] = sideband[i]; tree->Branch(("x"+str.str()).c_str(), &xForTree[i] ,("x"+str.str()+"/D").c_str()); tree->Branch(("y"+str.str()).c_str(), &yForTree[i] ,("y"+str.str()+"/D").c_str()); ws->var(("b"+str.str()).c_str())->setMax( 1.2*back+MaxSigma*(sqrt(back)+back*back_syst) ); ws->var(("b"+str.str()).c_str())->setVal( back ); } tree->Fill(); // tree->Print(); // tree->Scan(); RooArgList* observableList = new RooArgList(observablesCollection); // observableSet->Print(); // observableList->Print(); RooDataSet* data = new RooDataSet(dsName,"Number Counting Data", tree, *observableList); // one experiment // data->Scan(); // import hypothetical data RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL) ; ws->import(*data); RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ; }