double getChisq(RooAbsData &dat, RooAbsPdf &pdf, RooRealVar &var, bool prt=false) { // Find total number of events double nEvt; double nTot=0.0; for(int j=0; j<dat.numEntries(); j++) { dat.get(j); nEvt=dat.weight(); nTot+=nEvt; } // Find chi-squared equivalent 2NLL //RooRealVar *var=(RooRealVar*)(pdf.getParameters(*dat)->find("CMS_hgg_mass")); double totNLL=0.0; double prbSum=0.0; for(int j=0; j<dat.numEntries(); j++) { double m=dat.get(j)->getRealValue(var.GetName()); if ( m < var.getMin() || m > var.getMax()) continue; // Find probability density and hence probability var.setVal(m); double prb = var.getBinWidth(0)*pdf.getVal(var); prbSum+=prb; dat.get(j); nEvt=dat.weight(); double mubin=nTot*prb; double contrib(0.); if (nEvt < 1) contrib = mubin; else contrib=mubin-nEvt+nEvt*log(nEvt/mubin); totNLL+=contrib; if(prt) cout << "Bin " << j << " prob = " << prb << " nEvt = " << nEvt << ", mu = " << mubin << " contribution " << contrib << endl; } totNLL*=2.0; if(prt) cout << pdf.GetName() << " nTot = " << nTot << " 2NLL constant = " << totNLL << endl; return totNLL; }
void setup(ModelConfig* mcInWs) { RooAbsPdf* combPdf = mcInWs->GetPdf(); RooArgSet mc_obs = *mcInWs->GetObservables(); RooArgSet mc_globs = *mcInWs->GetGlobalObservables(); RooArgSet mc_nuis = *mcInWs->GetNuisanceParameters(); // pair the nuisance parameter to the global observable RooArgSet mc_nuis_tmp = mc_nuis; RooArgList nui_list; RooArgList glob_list; RooArgSet constraint_set_tmp(*combPdf->getAllConstraints(mc_obs, mc_nuis_tmp, false)); RooArgSet constraint_set; int counter_tmp = 0; unfoldConstraints(constraint_set_tmp, constraint_set, mc_obs, mc_nuis_tmp, counter_tmp); TIterator* cIter = constraint_set.createIterator(); RooAbsArg* arg; while ((arg = (RooAbsArg*)cIter->Next())) { RooAbsPdf* pdf = (RooAbsPdf*)arg; if (!pdf) continue; // pdf->Print(); TIterator* nIter = mc_nuis.createIterator(); RooRealVar* thisNui = NULL; RooAbsArg* nui_arg; while ((nui_arg = (RooAbsArg*)nIter->Next())) { if (pdf->dependsOn(*nui_arg)) { thisNui = (RooRealVar*)nui_arg; break; } } delete nIter; // need this incase the observable isn't fundamental. // in this case, see which variable is dependent on the nuisance parameter and use that. RooArgSet* components = pdf->getComponents(); // components->Print(); components->remove(*pdf); if (components->getSize()) { TIterator* itr1 = components->createIterator(); RooAbsArg* arg1; while ((arg1 = (RooAbsArg*)itr1->Next())) { TIterator* itr2 = components->createIterator(); RooAbsArg* arg2; while ((arg2 = (RooAbsArg*)itr2->Next())) { if (arg1 == arg2) continue; if (arg2->dependsOn(*arg1)) { components->remove(*arg1); } } delete itr2; } delete itr1; } if (components->getSize() > 1) { cout << "ERROR::Couldn't isolate proper nuisance parameter" << endl; return; } else if (components->getSize() == 1) { thisNui = (RooRealVar*)components->first(); } TIterator* gIter = mc_globs.createIterator(); RooRealVar* thisGlob = NULL; RooAbsArg* glob_arg; while ((glob_arg = (RooAbsArg*)gIter->Next())) { if (pdf->dependsOn(*glob_arg)) { thisGlob = (RooRealVar*)glob_arg; break; } } delete gIter; if (!thisNui || !thisGlob) { cout << "WARNING::Couldn't find nui or glob for constraint: " << pdf->GetName() << endl; //return; continue; } // cout << "Pairing nui: " << thisNui->GetName() << ", with glob: " << thisGlob->GetName() << ", from constraint: " << pdf->GetName() << endl; nui_list.add(*thisNui); glob_list.add(*thisGlob); if (string(pdf->ClassName()) == "RooPoisson") { double minVal = max(0.0, thisGlob->getVal() - 8*sqrt(thisGlob->getVal())); double maxVal = max(10.0, thisGlob->getVal() + 8*sqrt(thisGlob->getVal())); thisNui->setRange(minVal, maxVal); thisGlob->setRange(minVal, maxVal); } else if (string(pdf->ClassName()) == "RooGaussian") { thisNui->setRange(-7, 7); thisGlob->setRange(-10, 10); } // thisNui->Print(); // thisGlob->Print(); } delete cIter; }
void splitws(string inFolderName, double mass, string channel) { cout << "Splitting workspace in " << channel << endl; int flatInterpCode = 4; int shapeInterpCode = 4; bool do2011 = 0; if (inFolderName.find("2011") != string::npos) do2011 = 1; bool conditionalAsimov = 0; bool doData = 1; //if (inFolderName.find("_blind_") != string::npos) { //conditionalAsimov = 0; //} //else { //conditionalAsimov = 1; //} set<string> channelNames; if (channel == "01j") { channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); } else if (channel == "0j") { channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); } else if (channel == "1j") { channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); } else if (channel == "OF01j") { channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_sscr_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_sscr_1j"+string(!do2011?"_2012":"")); } else if (channel == "OF0j") { channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_sscr_0j"+string(!do2011?"_2012":"")); } else if (channel == "OF1j") { channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_sscr_1j"+string(!do2011?"_2012":"")); } else if (channel == "SF01j") { channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); } else if (channel == "SF0j") { channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); } else if (channel == "SF1j") { channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); } else if (channel == "2j") { channelNames.insert("em_signalLike1_2j"+string(!do2011?"_2012":"")); channelNames.insert("ee_signalLike1_2j"+string(!do2011?"_2012":"")); channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":"")); } else if (channel == "OF2j") { channelNames.insert("em_signalLike1_2j"+string(!do2011?"_2012":"")); channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":"")); } else if (channel == "SF2j") { channelNames.insert("ee_signalLike1_2j"+string(!do2011?"_2012":"")); channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":"")); } else if (channel == "OF") { channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":"")); channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); channelNames.insert("em_signalLike1_2j"+string(!do2011?"_2012":"")); channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":"")); } else if (channel == "SF") { channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":"")); channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":"")); channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":"")); channelNames.insert("ee_signalLike1_2j"+string(!do2011?"_2012":"")); channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":"")); } else { cout << "Channel " << channel << " not defined. Please check!" << endl; exit(1); } // bool fix = 1; stringstream inFileName; inFileName << "workspaces/" << inFolderName << "/" << mass << ".root"; TFile f(inFileName.str().c_str()); RooWorkspace* w = (RooWorkspace*)f.Get("combWS"); if (!w) w = (RooWorkspace*)f.Get("combined"); RooDataSet* data = (RooDataSet*)w->data("combData"); if (!data) data = (RooDataSet*)w->data("obsData"); ModelConfig* mc = (ModelConfig*)w->obj("ModelConfig"); RooRealVar* weightVar = w->var("weightVar"); RooRealVar* mu = (RooRealVar*)mc->GetParametersOfInterest()->first(); if (!mu) mu = w->var("SigXsecOverSM"); const RooArgSet* mc_obs = mc->GetObservables(); const RooArgSet* mc_nuis = mc->GetNuisanceParameters(); const RooArgSet* mc_globs = mc->GetGlobalObservables(); const RooArgSet* mc_poi = mc->GetParametersOfInterest(); RooArgSet nuis = *mc_nuis; RooArgSet antiNuis = *mc_nuis; RooArgSet globs = *mc_globs; RooArgSet antiGlobs = *mc_globs; RooArgSet allParams; RooSimultaneous* simPdf = (RooSimultaneous*)mc->GetPdf(); RooCategory* cat = (RooCategory*)&simPdf->indexCat(); RooArgSet nuis_tmp = nuis; RooArgSet fullConstraints = *simPdf->getAllConstraints(*mc_obs,nuis_tmp,false); vector<string> foundChannels; vector<string> skippedChannels; cout << "Getting constraints" << endl; map<string, RooDataSet*> data_map; map<string, RooAbsPdf*> pdf_map; RooCategory* decCat = new RooCategory("dec_channel","dec_channel"); // int i = 0; TIterator* catItr = cat->typeIterator(); RooCatType* type; RooArgSet allConstraints; while ((type = (RooCatType*)catItr->Next())) { RooAbsPdf* pdf = simPdf->getPdf(type->GetName()); string typeName(type->GetName()); if (channelNames.size() && channelNames.find(typeName) == channelNames.end()) { skippedChannels.push_back(typeName); continue; } cout << "On channel " << type->GetName() << endl; foundChannels.push_back(typeName); decCat->defineType(type->GetName()); // pdf->getParameters(*data)->Print("v"); RooArgSet nuis_tmp1 = nuis; RooArgSet nuis_tmp2 = nuis; RooArgSet* constraints = pdf->getAllConstraints(*mc_obs, nuis_tmp1, true); constraints->Print(); allConstraints.add(*constraints); } catItr->Reset(); while ((type = (RooCatType*)catItr->Next())) { RooAbsPdf* pdf = simPdf->getPdf(type->GetName()); string typeName(type->GetName()); cout << "Considering type " << typeName << endl; if (channelNames.size() && channelNames.find(typeName) == channelNames.end()) continue; cout << "On channel " << type->GetName() << endl; RooArgSet nuis_tmp1 = nuis; RooArgSet nuis_tmp2 = nuis; RooArgSet* constraints = pdf->getAllConstraints(*mc_obs, nuis_tmp1, true); cout << "Adding pdf to map: " << typeName << " = " << pdf->GetName() << endl; pdf_map[typeName] = pdf; RooProdPdf prod("prod","prod",*constraints); RooArgSet* params = pdf->getParameters(*data); antiNuis.remove(*params); antiGlobs.remove(*params); allParams.add(*params); // cout << type->GetName() << endl; } // return; RooArgSet decNuis; TIterator* nuiItr = mc_nuis->createIterator(); TIterator* parItr = allParams.createIterator(); RooAbsArg* nui, *par; while ((par = (RooAbsArg*)parItr->Next())) { nuiItr->Reset(); while ((nui = (RooAbsArg*)nuiItr->Next())) { if (par == nui) decNuis.add(*nui); } } RooArgSet decGlobs; TIterator* globItr = mc_globs->createIterator(); parItr->Reset(); RooAbsArg* glob; while ((par = (RooAbsArg*)parItr->Next())) { globItr->Reset(); while ((glob = (RooAbsArg*)globItr->Next())) { if (par == glob) decGlobs.add(*glob); } } // antiNuis.Print(); // nuis.Print(); // globs.Print(); // i = 0; TList* datalist = data->split(*cat, true); TIterator* dataItr = datalist->MakeIterator(); RooAbsData* ds; while ((ds = (RooAbsData*)dataItr->Next())) { string typeName(ds->GetName()); if (channelNames.size() && channelNames.find(typeName) == channelNames.end()) continue; cout << "Adding dataset to map: " << ds->GetName() << endl; data_map[string(ds->GetName())] = (RooDataSet*)ds; cout << ds->GetName() << endl; } RooSimultaneous* decPdf = new RooSimultaneous("decPdf","decPdf",pdf_map,*decCat); RooArgSet decObs = *decPdf->getObservables(data); // decObs.add(*(RooAbsArg*)weightVar); decObs.add(*(RooAbsArg*)decCat); decObs.Print(); nuis.remove(antiNuis); globs.remove(antiGlobs); // nuis.Print("v"); RooDataSet* decData = new RooDataSet("obsData","obsData",RooArgSet(decObs,*(RooAbsArg*)weightVar),Index(*decCat),Import(data_map),WeightVar(*weightVar)); decData->Print(); RooArgSet poi(*(RooAbsArg*)mu); RooWorkspace decWS("combined"); ModelConfig decMC("ModelConfig",&decWS); decMC.SetPdf(*decPdf); decMC.SetObservables(decObs); decMC.SetNuisanceParameters(decNuis); decMC.SetGlobalObservables(decGlobs); decMC.SetParametersOfInterest(poi); decMC.Print(); decWS.import(*decPdf); decWS.import(decMC); decWS.import(*decData); // decWS.Print(); ModelConfig* mcInWs = (ModelConfig*)decWS.obj("ModelConfig"); decPdf = (RooSimultaneous*)mcInWs->GetPdf(); // setup(mcInWs); // return; mcInWs->GetNuisanceParameters()->Print("v"); mcInWs->GetGlobalObservables()->Print("v"); // decData->tree()->Scan("*"); // Make asimov data RooArgSet funcs = decWS.allFunctions(); TIterator* it = funcs.createIterator(); TObject* tempObj = 0; while((tempObj=it->Next())) { FlexibleInterpVar* flex = dynamic_cast<FlexibleInterpVar*>(tempObj); if(flex) { flex->setAllInterpCodes(flatInterpCode); } PiecewiseInterpolation* piece = dynamic_cast<PiecewiseInterpolation*>(tempObj); if(piece) { piece->setAllInterpCodes(shapeInterpCode); } } RooDataSet* dataInWs = (RooDataSet*)decWS.data("obsData"); makeAsimovData(mcInWs, conditionalAsimov && doData, &decWS, mcInWs->GetPdf(), dataInWs, 0); makeAsimovData(mcInWs, conditionalAsimov && doData, &decWS, mcInWs->GetPdf(), dataInWs, 1); makeAsimovData(mcInWs, conditionalAsimov && doData, &decWS, mcInWs->GetPdf(), dataInWs, 2); system(("mkdir -vp workspaces/"+inFolderName+"_"+channel).c_str()); stringstream outFileName; outFileName << "workspaces/" << inFolderName << "_" << channel << "/" << mass << ".root"; cout << "Exporting" << endl; decWS.writeToFile(outFileName.str().c_str()); cout << "\nIncluded the following channels: " << endl; for (int i=0;i<(int)foundChannels.size();i++) { cout << "-> " << foundChannels[i] << endl; } cout << "\nSkipping the following channels: " << endl; for (int i=0;i<(int)skippedChannels.size();i++) { cout << "-> " << skippedChannels[i] << endl; } cout << "Done" << endl; // decPdf->fitTo(*decData, Hesse(0), Minos(0), PrintLevel(0)); }
// internal routine to run the inverter HypoTestInverterResult * RooStats::HypoTestInvTool::RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName, const char * dataName, int type, int testStatType, bool useCLs, int npoints, double poimin, double poimax, int ntoys, bool useNumberCounting, const char * nuisPriorName ){ std::cout << "Running HypoTestInverter on the workspace " << w->GetName() << std::endl; w->Print(); RooAbsData * data = w->data(dataName); if (!data) { Error("StandardHypoTestDemo","Not existing data %s",dataName); return 0; } else std::cout << "Using data set " << dataName << std::endl; if (mUseVectorStore) { RooAbsData::setDefaultStorageType(RooAbsData::Vector); data->convertToVectorStore() ; } // get models from WS // get the modelConfig out of the file ModelConfig* bModel = (ModelConfig*) w->obj(modelBName); ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName); if (!sbModel) { Error("StandardHypoTestDemo","Not existing ModelConfig %s",modelSBName); return 0; } // check the model if (!sbModel->GetPdf()) { Error("StandardHypoTestDemo","Model %s has no pdf ",modelSBName); return 0; } if (!sbModel->GetParametersOfInterest()) { Error("StandardHypoTestDemo","Model %s has no poi ",modelSBName); return 0; } if (!sbModel->GetObservables()) { Error("StandardHypoTestInvDemo","Model %s has no observables ",modelSBName); return 0; } if (!sbModel->GetSnapshot() ) { Info("StandardHypoTestInvDemo","Model %s has no snapshot - make one using model poi",modelSBName); sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() ); } // case of no systematics // remove nuisance parameters from model if (noSystematics) { const RooArgSet * nuisPar = sbModel->GetNuisanceParameters(); if (nuisPar && nuisPar->getSize() > 0) { std::cout << "StandardHypoTestInvDemo" << " - Switch off all systematics by setting them constant to their initial values" << std::endl; RooStats::SetAllConstant(*nuisPar); } if (bModel) { const RooArgSet * bnuisPar = bModel->GetNuisanceParameters(); if (bnuisPar) RooStats::SetAllConstant(*bnuisPar); } } if (!bModel || bModel == sbModel) { Info("StandardHypoTestInvDemo","The background model %s does not exist",modelBName); Info("StandardHypoTestInvDemo","Copy it from ModelConfig %s and set POI to zero",modelSBName); bModel = (ModelConfig*) sbModel->Clone(); bModel->SetName(TString(modelSBName)+TString("_with_poi_0")); RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first()); if (!var) return 0; double oldval = var->getVal(); var->setVal(0); bModel->SetSnapshot( RooArgSet(*var) ); var->setVal(oldval); } else { if (!bModel->GetSnapshot() ) { Info("StandardHypoTestInvDemo","Model %s has no snapshot - make one using model poi and 0 values ",modelBName); RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first()); if (var) { double oldval = var->getVal(); var->setVal(0); bModel->SetSnapshot( RooArgSet(*var) ); var->setVal(oldval); } else { Error("StandardHypoTestInvDemo","Model %s has no valid poi",modelBName); return 0; } } } // check model has global observables when there are nuisance pdf // for the hybrid case the globobs are not needed if (type != 1 ) { bool hasNuisParam = (sbModel->GetNuisanceParameters() && sbModel->GetNuisanceParameters()->getSize() > 0); bool hasGlobalObs = (sbModel->GetGlobalObservables() && sbModel->GetGlobalObservables()->getSize() > 0); if (hasNuisParam && !hasGlobalObs ) { // try to see if model has nuisance parameters first RooAbsPdf * constrPdf = RooStats::MakeNuisancePdf(*sbModel,"nuisanceConstraintPdf_sbmodel"); if (constrPdf) { Warning("StandardHypoTestInvDemo","Model %s has nuisance parameters but no global observables associated",sbModel->GetName()); Warning("StandardHypoTestInvDemo","\tThe effect of the nuisance parameters will not be treated correctly "); } } } // run first a data fit const RooArgSet * poiSet = sbModel->GetParametersOfInterest(); RooRealVar *poi = (RooRealVar*)poiSet->first(); std::cout << "StandardHypoTestInvDemo : POI initial value: " << poi->GetName() << " = " << poi->getVal() << std::endl; // fit the data first (need to use constraint ) TStopwatch tw; bool doFit = initialFit; if (testStatType == 0 && initialFit == -1) doFit = false; // case of LEP test statistic if (type == 3 && initialFit == -1) doFit = false; // case of Asymptoticcalculator with nominal Asimov double poihat = 0; if (minimizerType.size()==0) minimizerType = ROOT::Math::MinimizerOptions::DefaultMinimizerType(); else ROOT::Math::MinimizerOptions::SetDefaultMinimizer(minimizerType.c_str()); Info("StandardHypoTestInvDemo","Using %s as minimizer for computing the test statistic", ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str() ); if (doFit) { // do the fit : By doing a fit the POI snapshot (for S+B) is set to the fit value // and the nuisance parameters nominal values will be set to the fit value. // This is relevant when using LEP test statistics Info( "StandardHypoTestInvDemo"," Doing a first fit to the observed data "); RooArgSet constrainParams; if (sbModel->GetNuisanceParameters() ) constrainParams.add(*sbModel->GetNuisanceParameters()); RooStats::RemoveConstantParameters(&constrainParams); tw.Start(); RooFitResult * fitres = sbModel->GetPdf()->fitTo(*data,InitialHesse(false), Hesse(false), Minimizer(minimizerType.c_str(),"Migrad"), Strategy(0), PrintLevel(mPrintLevel), Constrain(constrainParams), Save(true) ); if (fitres->status() != 0) { Warning("StandardHypoTestInvDemo","Fit to the model failed - try with strategy 1 and perform first an Hesse computation"); fitres = sbModel->GetPdf()->fitTo(*data,InitialHesse(true), Hesse(false),Minimizer(minimizerType.c_str(),"Migrad"), Strategy(1), PrintLevel(mPrintLevel+1), Constrain(constrainParams), Save(true) ); } if (fitres->status() != 0) Warning("StandardHypoTestInvDemo"," Fit still failed - continue anyway....."); poihat = poi->getVal(); std::cout << "StandardHypoTestInvDemo - Best Fit value : " << poi->GetName() << " = " << poihat << " +/- " << poi->getError() << std::endl; std::cout << "Time for fitting : "; tw.Print(); //save best fit value in the poi snapshot sbModel->SetSnapshot(*sbModel->GetParametersOfInterest()); std::cout << "StandardHypoTestInvo: snapshot of S+B Model " << sbModel->GetName() << " is set to the best fit value" << std::endl; } // print a message in case of LEP test statistics because it affects result by doing or not doing a fit if (testStatType == 0) { if (!doFit) Info("StandardHypoTestInvDemo","Using LEP test statistic - an initial fit is not done and the TS will use the nuisances at the model value"); else Info("StandardHypoTestInvDemo","Using LEP test statistic - an initial fit has been done and the TS will use the nuisances at the best fit value"); } // build test statistics and hypotest calculators for running the inverter SimpleLikelihoodRatioTestStat slrts(*sbModel->GetPdf(),*bModel->GetPdf()); // null parameters must includes snapshot of poi plus the nuisance values RooArgSet nullParams(*sbModel->GetSnapshot()); if (sbModel->GetNuisanceParameters()) nullParams.add(*sbModel->GetNuisanceParameters()); if (sbModel->GetSnapshot()) slrts.SetNullParameters(nullParams); RooArgSet altParams(*bModel->GetSnapshot()); if (bModel->GetNuisanceParameters()) altParams.add(*bModel->GetNuisanceParameters()); if (bModel->GetSnapshot()) slrts.SetAltParameters(altParams); // ratio of profile likelihood - need to pass snapshot for the alt RatioOfProfiledLikelihoodsTestStat ropl(*sbModel->GetPdf(), *bModel->GetPdf(), bModel->GetSnapshot()); ropl.SetSubtractMLE(false); if (testStatType == 11) ropl.SetSubtractMLE(true); ropl.SetPrintLevel(mPrintLevel); ropl.SetMinimizer(minimizerType.c_str()); ProfileLikelihoodTestStat profll(*sbModel->GetPdf()); if (testStatType == 3) profll.SetOneSided(true); if (testStatType == 4) profll.SetSigned(true); profll.SetMinimizer(minimizerType.c_str()); profll.SetPrintLevel(mPrintLevel); profll.SetReuseNLL(mOptimize); slrts.SetReuseNLL(mOptimize); ropl.SetReuseNLL(mOptimize); if (mOptimize) { profll.SetStrategy(0); ropl.SetStrategy(0); ROOT::Math::MinimizerOptions::SetDefaultStrategy(0); } if (mMaxPoi > 0) poi->setMax(mMaxPoi); // increase limit MaxLikelihoodEstimateTestStat maxll(*sbModel->GetPdf(),*poi); NumEventsTestStat nevtts; AsymptoticCalculator::SetPrintLevel(mPrintLevel); // create the HypoTest calculator class HypoTestCalculatorGeneric * hc = 0; if (type == 0) hc = new FrequentistCalculator(*data, *bModel, *sbModel); else if (type == 1) hc = new HybridCalculator(*data, *bModel, *sbModel); // else if (type == 2 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, false, mAsimovBins); // else if (type == 3 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, true, mAsimovBins); // for using Asimov data generated with nominal values else if (type == 2 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, false ); else if (type == 3 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, true ); // for using Asimov data generated with nominal values else { Error("StandardHypoTestInvDemo","Invalid - calculator type = %d supported values are only :\n\t\t\t 0 (Frequentist) , 1 (Hybrid) , 2 (Asymptotic) ",type); return 0; } // set the test statistic TestStatistic * testStat = 0; if (testStatType == 0) testStat = &slrts; if (testStatType == 1 || testStatType == 11) testStat = &ropl; if (testStatType == 2 || testStatType == 3 || testStatType == 4) testStat = &profll; if (testStatType == 5) testStat = &maxll; if (testStatType == 6) testStat = &nevtts; if (testStat == 0) { Error("StandardHypoTestInvDemo","Invalid - test statistic type = %d supported values are only :\n\t\t\t 0 (SLR) , 1 (Tevatron) , 2 (PLR), 3 (PLR1), 4(MLE)",testStatType); return 0; } ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler(); if (toymcs && (type == 0 || type == 1) ) { // look if pdf is number counting or extended if (sbModel->GetPdf()->canBeExtended() ) { if (useNumberCounting) Warning("StandardHypoTestInvDemo","Pdf is extended: but number counting flag is set: ignore it "); } else { // for not extended pdf if (!useNumberCounting ) { int nEvents = data->numEntries(); Info("StandardHypoTestInvDemo","Pdf is not extended: number of events to generate taken from observed data set is %d",nEvents); toymcs->SetNEventsPerToy(nEvents); } else { Info("StandardHypoTestInvDemo","using a number counting pdf"); toymcs->SetNEventsPerToy(1); } } toymcs->SetTestStatistic(testStat); if (data->isWeighted() && !mGenerateBinned) { Info("StandardHypoTestInvDemo","Data set is weighted, nentries = %d and sum of weights = %8.1f but toy generation is unbinned - it would be faster to set mGenerateBinned to true\n",data->numEntries(), data->sumEntries()); } toymcs->SetGenerateBinned(mGenerateBinned); toymcs->SetUseMultiGen(mOptimize); if (mGenerateBinned && sbModel->GetObservables()->getSize() > 2) { Warning("StandardHypoTestInvDemo","generate binned is activated but the number of ovservable is %d. Too much memory could be needed for allocating all the bins",sbModel->GetObservables()->getSize() ); } // set the random seed if needed if (mRandomSeed >= 0) RooRandom::randomGenerator()->SetSeed(mRandomSeed); } // specify if need to re-use same toys if (reuseAltToys) { hc->UseSameAltToys(); } if (type == 1) { HybridCalculator *hhc = dynamic_cast<HybridCalculator*> (hc); assert(hhc); hhc->SetToys(ntoys,ntoys/mNToysRatio); // can use less ntoys for b hypothesis // remove global observables from ModelConfig (this is probably not needed anymore in 5.32) bModel->SetGlobalObservables(RooArgSet() ); sbModel->SetGlobalObservables(RooArgSet() ); // check for nuisance prior pdf in case of nuisance parameters if (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() ) { // fix for using multigen (does not work in this case) toymcs->SetUseMultiGen(false); ToyMCSampler::SetAlwaysUseMultiGen(false); RooAbsPdf * nuisPdf = 0; if (nuisPriorName) nuisPdf = w->pdf(nuisPriorName); // use prior defined first in bModel (then in SbModel) if (!nuisPdf) { Info("StandardHypoTestInvDemo","No nuisance pdf given for the HybridCalculator - try to deduce pdf from the model"); if (bModel->GetPdf() && bModel->GetObservables() ) nuisPdf = RooStats::MakeNuisancePdf(*bModel,"nuisancePdf_bmodel"); else nuisPdf = RooStats::MakeNuisancePdf(*sbModel,"nuisancePdf_sbmodel"); } if (!nuisPdf ) { if (bModel->GetPriorPdf()) { nuisPdf = bModel->GetPriorPdf(); Info("StandardHypoTestInvDemo","No nuisance pdf given - try to use %s that is defined as a prior pdf in the B model",nuisPdf->GetName()); } else { Error("StandardHypoTestInvDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified or can be derived"); return 0; } } assert(nuisPdf); Info("StandardHypoTestInvDemo","Using as nuisance Pdf ... " ); nuisPdf->Print(); const RooArgSet * nuisParams = (bModel->GetNuisanceParameters() ) ? bModel->GetNuisanceParameters() : sbModel->GetNuisanceParameters(); RooArgSet * np = nuisPdf->getObservables(*nuisParams); if (np->getSize() == 0) { Warning("StandardHypoTestInvDemo","Prior nuisance does not depend on nuisance parameters. They will be smeared in their full range"); } delete np; hhc->ForcePriorNuisanceAlt(*nuisPdf); hhc->ForcePriorNuisanceNull(*nuisPdf); } } else if (type == 2 || type == 3) { if (testStatType == 3) ((AsymptoticCalculator*) hc)->SetOneSided(true); if (testStatType != 2 && testStatType != 3) Warning("StandardHypoTestInvDemo","Only the PL test statistic can be used with AsymptoticCalculator - use by default a two-sided PL"); } else if (type == 0 || type == 1) ((FrequentistCalculator*) hc)->SetToys(ntoys,ntoys/mNToysRatio); // Get the result RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration); HypoTestInverter calc(*hc); calc.SetConfidenceLevel(0.95); calc.UseCLs(useCLs); calc.SetVerbose(true); // can speed up using proof-lite if (mUseProof && mNWorkers > 1) { ProofConfig pc(*w, mNWorkers, "", kFALSE); toymcs->SetProofConfig(&pc); // enable proof } if (npoints > 0) { if (poimin > poimax) { // if no min/max given scan between MLE and +4 sigma poimin = int(poihat); poimax = int(poihat + 4 * poi->getError()); } std::cout << "Doing a fixed scan in interval : " << poimin << " , " << poimax << std::endl; calc.SetFixedScan(npoints,poimin,poimax); } else { //poi->setMax(10*int( (poihat+ 10 *poi->getError() )/10 ) ); std::cout << "Doing an automatic scan in interval : " << poi->getMin() << " , " << poi->getMax() << std::endl; } tw.Start(); HypoTestInverterResult * r = calc.GetInterval(); std::cout << "Time to perform limit scan \n"; tw.Print(); if (mRebuild) { calc.SetCloseProof(1); tw.Start(); SamplingDistribution * limDist = calc.GetUpperLimitDistribution(true,mNToyToRebuild); std::cout << "Time to rebuild distributions " << std::endl; tw.Print(); if (limDist) { std::cout << "expected up limit " << limDist->InverseCDF(0.5) << " +/- " << limDist->InverseCDF(0.16) << " " << limDist->InverseCDF(0.84) << "\n"; //update r to a new updated result object containing the rebuilt expected p-values distributions // (it will not recompute the expected limit) if (r) delete r; // need to delete previous object since GetInterval will return a cloned copy r = calc.GetInterval(); } else std::cout << "ERROR : failed to re-build distributions " << std::endl; } return r; }
//put very small data entries in a binned dataset to avoid unphysical pdfs, specifically for H->ZZ->4l RooDataSet* makeData(RooDataSet* orig, RooSimultaneous* simPdf, const RooArgSet* observables, RooRealVar* firstPOI, double mass, double& mu_min) { double max_soverb = 0; mu_min = -10e9; map<string, RooDataSet*> data_map; firstPOI->setVal(0); RooCategory* cat = (RooCategory*)&simPdf->indexCat(); TList* datalist = orig->split(*(RooAbsCategory*)cat, true); TIterator* dataItr = datalist->MakeIterator(); RooAbsData* ds; RooRealVar* weightVar = new RooRealVar("weightVar","weightVar",1); while ((ds = (RooAbsData*)dataItr->Next())) { string typeName(ds->GetName()); cat->setLabel(typeName.c_str()); RooAbsPdf* pdf = simPdf->getPdf(typeName.c_str()); cout << "pdf: " << pdf << endl; RooArgSet* obs = pdf->getObservables(observables); cout << "obs: " << obs << endl; RooArgSet obsAndWeight(*obs, *weightVar); obsAndWeight.add(*cat); stringstream datasetName; datasetName << "newData_" << typeName; RooDataSet* thisData = new RooDataSet(datasetName.str().c_str(),datasetName.str().c_str(), obsAndWeight, WeightVar(*weightVar)); RooRealVar* firstObs = (RooRealVar*)obs->first(); //int ibin = 0; int nrEntries = ds->numEntries(); for (int ib=0;ib<nrEntries;ib++) { const RooArgSet* event = ds->get(ib); const RooRealVar* thisObs = (RooRealVar*)event->find(firstObs->GetName()); firstObs->setVal(thisObs->getVal()); firstPOI->setVal(0); double b = pdf->expectedEvents(*firstObs)*pdf->getVal(obs); firstPOI->setVal(1); double s = pdf->expectedEvents(*firstObs)*pdf->getVal(obs) - b; if (s > 0) { mu_min = max(mu_min, -b/s); double soverb = s/b; if (soverb > max_soverb) { max_soverb = soverb; cout << "Found new max s/b: " << soverb << " in pdf " << pdf->GetName() << " at m = " << thisObs->getVal() << endl; } } if (b == 0 && s != 0) { cout << "Expecting non-zero signal and zero bg at m=" << firstObs->getVal() << " in pdf " << pdf->GetName() << endl; } if (s+b <= 0) { cout << "expecting zero" << endl; continue; } double weight = ds->weight(); if ((typeName.find("ATLAS_H_4mu") != string::npos || typeName.find("ATLAS_H_4e") != string::npos || typeName.find("ATLAS_H_2mu2e") != string::npos || typeName.find("ATLAS_H_2e2mu") != string::npos) && fabs(firstObs->getVal() - mass) < 10 && weight == 0) { cout << "adding event: " << firstObs->getVal() << endl; thisData->add(*event, pow(10., -9.)); } else { //weight = max(pow(10.0, -9), weight); thisData->add(*event, weight); } } data_map[string(ds->GetName())] = (RooDataSet*)thisData; } RooDataSet* newData = new RooDataSet("newData","newData",RooArgSet(*observables, *weightVar), Index(*cat), Import(data_map), WeightVar(*weightVar)); orig->Print(); newData->Print(); //newData->tree()->Scan("*"); return newData; }
/// /// Fit to the minimum using an improve method. /// The idea is to kill known minima. For this, we add a multivariate /// Gaussian to the chi2 at the position of the minimum. Ideally it should /// be a parabola shaped function, but the Gaussian is readily available. /// A true parabola like in the original IMPROVE algorithm doesn't work /// because apparently it affects the other regions of /// the chi2 too much. There are two parameters to tune: the width of the /// Gaussian, which is controlled by the error definition of the first fit, /// and the height of the Gaussian, which is set to 16 (=4 sigma). /// Three fits are performed: 1) initial fit, 2) fit with improved FCN, /// 3) fit of the non-improved FCN using the result from step 2 as the start /// parameters. /// So far it is only available for the Prob method, via the probimprove /// command line flag. /// RooFitResult* Utils::fitToMinImprove(RooWorkspace *w, TString name) { TString parsName = "par_"+name; TString obsName = "obs_"+name; TString pdfName = "pdf_"+name; int printlevel = -1; RooMsgService::instance().setGlobalKillBelow(ERROR); // step 1: find a minimum to start with RooFitResult *r1 = 0; { RooFormulaVar ll("ll", "ll", "-2*log(@0)", RooArgSet(*w->pdf(pdfName))); // RooFitResult* r1 = fitToMin(&ll, printlevel); RooMinuit m(ll); m.setPrintLevel(-2); m.setNoWarn(); m.setErrorLevel(4.0); ///< define 2 sigma errors. This will make the hesse PDF 2 sigma wide! int status = m.migrad(); r1 = m.save(); // if ( 102<RadToDeg(w->var("g")->getVal())&&RadToDeg(w->var("g")->getVal())<103 ) // { // cout << "step 1" << endl; // r1->Print("v"); // gStyle->SetPalette(1); // float xmin = 0.; // float xmax = 3.14; // float ymin = 0.; // float ymax = 0.2; // TH2F* histo = new TH2F("histo", "histo", 100, xmin, xmax, 100, ymin, ymax); // for ( int ix=0; ix<100; ix++ ) // for ( int iy=0; iy<100; iy++ ) // { // float x = xmin + (xmax-xmin)*(double)ix/(double)100; // float y = ymin + (ymax-ymin)*(double)iy/(double)100; // w->var("d_dk")->setVal(x); // w->var("r_dk")->setVal(y); // histo->SetBinContent(ix+1,iy+1,ll.getVal()); // } // newNoWarnTCanvas("c2"); // histo->GetZaxis()->SetRangeUser(0,20); // histo->Draw("colz"); // setParameters(w, parsName, r1); // } } // step 2: build and fit the improved fcn RooFitResult *r2 = 0; { // create a Hesse PDF, import both PDFs into a new workspace, // so that their parameters are linked RooAbsPdf* hessePdf = r1->createHessePdf(*w->set(parsName)); if ( !hessePdf ) return r1; // RooWorkspace* wImprove = (RooWorkspace*)w->Clone(); RooWorkspace* wImprove = new RooWorkspace(); wImprove->import(*w->pdf(pdfName)); wImprove->import(*hessePdf); hessePdf = wImprove->pdf(hessePdf->GetName()); RooAbsPdf* fullPdf = wImprove->pdf(pdfName); RooFormulaVar ll("ll", "ll", "-2*log(@0) +16*@1", RooArgSet(*fullPdf, *hessePdf)); // RooFitResult *r2 = fitToMin(&ll, printlevel); RooMinuit m(ll); m.setPrintLevel(-2); m.setNoWarn(); m.setErrorLevel(1.0); int status = m.migrad(); r2 = m.save(); // if ( 102<RadToDeg(w->var("g")->getVal())&&RadToDeg(w->var("g")->getVal())<103 ) // { // cout << "step 3" << endl; // r2->Print("v"); // // gStyle->SetPalette(1); // float xmin = 0.; // float xmax = 3.14; // float ymin = 0.; // float ymax = 0.2; // TH2F* histo = new TH2F("histo", "histo", 100, xmin, xmax, 100, ymin, ymax); // for ( int ix=0; ix<100; ix++ ) // for ( int iy=0; iy<100; iy++ ) // { // float x = xmin + (xmax-xmin)*(double)ix/(double)100; // float y = ymin + (ymax-ymin)*(double)iy/(double)100; // wImprove->var("d_dk")->setVal(x); // wImprove->var("r_dk")->setVal(y); // histo->SetBinContent(ix+1,iy+1,ll.getVal()); // } // newNoWarnTCanvas("c7"); // histo->GetZaxis()->SetRangeUser(0,20); // histo->Draw("colz"); // // setParameters(wImprove, parsName, r1); // } delete wImprove; } // step 3: use the fit result of the improved fit as // start parameters for the nominal fcn RooFitResult* r3; { setParameters(w, parsName, r2); RooFormulaVar ll("ll", "ll", "-2*log(@0)", RooArgSet(*w->pdf(pdfName))); RooMinuit m(ll); m.setPrintLevel(-2); m.setNoWarn(); m.setErrorLevel(1.0); int status = m.migrad(); r3 = m.save(); // if ( 102<RadToDeg(w->var("g")->getVal())&&RadToDeg(w->var("g")->getVal())<103 ) // { // cout << "step 3" << endl; // r3->Print("v"); // } } // step 5: chose better minimum // cout << r1->minNll() << " " << r3->minNll() << endl; RooFitResult* r = 0; if ( r1->minNll()<r3->minNll() ) { delete r3; r = r1; } else { delete r1; r = r3; // cout << "Utils::fitToMinImprove() : improved fit is better!" << endl; } RooMsgService::instance().setGlobalKillBelow(INFO); // set to best parameters setParameters(w, parsName, r); return r; }
void StandardHypoTestDemo(const char* infile = "", const char* workspaceName = "combined", const char* modelSBName = "ModelConfig", const char* modelBName = "", const char* dataName = "obsData", int calcType = 0, // 0 freq 1 hybrid, 2 asymptotic int testStatType = 3, // 0 LEP, 1 TeV, 2 LHC, 3 LHC - one sided int ntoys = 5000, bool useNC = false, const char * nuisPriorName = 0) { /* Other Parameter to pass in tutorial apart from standard for filename, ws, modelconfig and data type = 0 Freq calculator type = 1 Hybrid calculator type = 2 Asymptotic calculator testStatType = 0 LEP = 1 Tevatron = 2 Profile Likelihood = 3 Profile Likelihood one sided (i.e. = 0 if mu < mu_hat) ntoys: number of toys to use useNumberCounting: set to true when using number counting events nuisPriorName: name of prior for the nnuisance. This is often expressed as constraint term in the global model It is needed only when using the HybridCalculator (type=1) If not given by default the prior pdf from ModelConfig is used. extra options are available as global paramwters of the macro. They major ones are: generateBinned generate binned data sets for toys (default is false) - be careful not to activate with a too large (>=3) number of observables nToyRatio ratio of S+B/B toys (default is 2) printLevel */ // disable - can cause some problems //ToyMCSampler::SetAlwaysUseMultiGen(true); SimpleLikelihoodRatioTestStat::SetAlwaysReuseNLL(true); ProfileLikelihoodTestStat::SetAlwaysReuseNLL(true); RatioOfProfiledLikelihoodsTestStat::SetAlwaysReuseNLL(true); //RooRandom::randomGenerator()->SetSeed(0); // to change minimizers // ROOT::Math::MinimizerOptions::SetDefaultStrategy(0); // ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2"); // ROOT::Math::MinimizerOptions::SetDefaultTolerance(1); ///////////////////////////////////////////////////////////// // First part is just to access a user-defined file // or create the standard example file if it doesn't exist //////////////////////////////////////////////////////////// const char* filename = ""; if (!strcmp(infile,"")) filename = "results/example_combined_GaussExample_model.root"; else filename = infile; // Check if example input file exists TFile *file = TFile::Open(filename); // if input file was specified byt not found, quit if(!file && strcmp(infile,"")){ cout <<"file not found" << endl; return; } // if default file not found, try to create it if(!file ){ // Normally this would be run on the command line cout <<"will run standard hist2workspace example"<<endl; gROOT->ProcessLine(".! prepareHistFactory ."); gROOT->ProcessLine(".! hist2workspace config/example.xml"); cout <<"\n\n---------------------"<<endl; cout <<"Done creating example input"<<endl; cout <<"---------------------\n\n"<<endl; } // now try to access the file again file = TFile::Open(filename); if(!file){ // if it is still not there, then we can't continue cout << "Not able to run hist2workspace to create example input" <<endl; return; } ///////////////////////////////////////////////////////////// // Tutorial starts here //////////////////////////////////////////////////////////// // get the workspace out of the file RooWorkspace* w = (RooWorkspace*) file->Get(workspaceName); if(!w){ cout <<"workspace not found" << endl; return; } w->Print(); // get the modelConfig out of the file ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName); // get the modelConfig out of the file RooAbsData* data = w->data(dataName); // make sure ingredients are found if(!data || !sbModel){ w->Print(); cout << "data or ModelConfig was not found" <<endl; return; } // make b model ModelConfig* bModel = (ModelConfig*) w->obj(modelBName); // case of no systematics // remove nuisance parameters from model if (noSystematics) { const RooArgSet * nuisPar = sbModel->GetNuisanceParameters(); if (nuisPar && nuisPar->getSize() > 0) { std::cout << "StandardHypoTestInvDemo" << " - Switch off all systematics by setting them constant to their initial values" << std::endl; RooStats::SetAllConstant(*nuisPar); } if (bModel) { const RooArgSet * bnuisPar = bModel->GetNuisanceParameters(); if (bnuisPar) RooStats::SetAllConstant(*bnuisPar); } } if (!bModel ) { Info("StandardHypoTestInvDemo","The background model %s does not exist",modelBName); Info("StandardHypoTestInvDemo","Copy it from ModelConfig %s and set POI to zero",modelSBName); bModel = (ModelConfig*) sbModel->Clone(); bModel->SetName(TString(modelSBName)+TString("B_only")); RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first()); if (!var) return; double oldval = var->getVal(); var->setVal(0); //bModel->SetSnapshot( RooArgSet(*var, *w->var("lumi")) ); bModel->SetSnapshot( RooArgSet(*var) ); var->setVal(oldval); } if (!sbModel->GetSnapshot() || poiValue > 0) { Info("StandardHypoTestDemo","Model %s has no snapshot - make one using model poi",modelSBName); RooRealVar * var = dynamic_cast<RooRealVar*>(sbModel->GetParametersOfInterest()->first()); if (!var) return; double oldval = var->getVal(); if (poiValue > 0) var->setVal(poiValue); //sbModel->SetSnapshot( RooArgSet(*var, *w->var("lumi") ) ); sbModel->SetSnapshot( RooArgSet(*var) ); if (poiValue > 0) var->setVal(oldval); //sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() ); } // part 1, hypothesis testing SimpleLikelihoodRatioTestStat * slrts = new SimpleLikelihoodRatioTestStat(*bModel->GetPdf(), *sbModel->GetPdf()); // null parameters must includes snapshot of poi plus the nuisance values RooArgSet nullParams(*bModel->GetSnapshot()); if (bModel->GetNuisanceParameters()) nullParams.add(*bModel->GetNuisanceParameters()); slrts->SetNullParameters(nullParams); RooArgSet altParams(*sbModel->GetSnapshot()); if (sbModel->GetNuisanceParameters()) altParams.add(*sbModel->GetNuisanceParameters()); slrts->SetAltParameters(altParams); ProfileLikelihoodTestStat * profll = new ProfileLikelihoodTestStat(*bModel->GetPdf()); RatioOfProfiledLikelihoodsTestStat * ropl = new RatioOfProfiledLikelihoodsTestStat(*bModel->GetPdf(), *sbModel->GetPdf(), sbModel->GetSnapshot()); ropl->SetSubtractMLE(false); if (testStatType == 3) profll->SetOneSidedDiscovery(1); profll->SetPrintLevel(printLevel); // profll.SetReuseNLL(mOptimize); // slrts.SetReuseNLL(mOptimize); // ropl.SetReuseNLL(mOptimize); AsymptoticCalculator::SetPrintLevel(printLevel); HypoTestCalculatorGeneric * hypoCalc = 0; // note here Null is B and Alt is S+B if (calcType == 0) hypoCalc = new FrequentistCalculator(*data, *sbModel, *bModel); else if (calcType == 1) hypoCalc= new HybridCalculator(*data, *sbModel, *bModel); else if (calcType == 2) hypoCalc= new AsymptoticCalculator(*data, *sbModel, *bModel); if (calcType == 0) ((FrequentistCalculator*)hypoCalc)->SetToys(ntoys, ntoys/nToysRatio); if (calcType == 1) ((HybridCalculator*)hypoCalc)->SetToys(ntoys, ntoys/nToysRatio); if (calcType == 2 ) { if (testStatType == 3) ((AsymptoticCalculator*) hypoCalc)->SetOneSidedDiscovery(true); if (testStatType != 2 && testStatType != 3) Warning("StandardHypoTestDemo","Only the PL test statistic can be used with AsymptoticCalculator - use by default a two-sided PL"); } // check for nuisance prior pdf in case of nuisance parameters if (calcType == 1 && (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() )) { RooAbsPdf * nuisPdf = 0; if (nuisPriorName) nuisPdf = w->pdf(nuisPriorName); // use prior defined first in bModel (then in SbModel) if (!nuisPdf) { Info("StandardHypoTestDemo","No nuisance pdf given for the HybridCalculator - try to deduce pdf from the model"); if (bModel->GetPdf() && bModel->GetObservables() ) nuisPdf = RooStats::MakeNuisancePdf(*bModel,"nuisancePdf_bmodel"); else nuisPdf = RooStats::MakeNuisancePdf(*sbModel,"nuisancePdf_sbmodel"); } if (!nuisPdf ) { if (bModel->GetPriorPdf()) { nuisPdf = bModel->GetPriorPdf(); Info("StandardHypoTestDemo","No nuisance pdf given - try to use %s that is defined as a prior pdf in the B model",nuisPdf->GetName()); } else { Error("StandardHypoTestDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified or can be derived"); return; } } assert(nuisPdf); Info("StandardHypoTestDemo","Using as nuisance Pdf ... " ); nuisPdf->Print(); const RooArgSet * nuisParams = (bModel->GetNuisanceParameters() ) ? bModel->GetNuisanceParameters() : sbModel->GetNuisanceParameters(); RooArgSet * np = nuisPdf->getObservables(*nuisParams); if (np->getSize() == 0) { Warning("StandardHypoTestDemo","Prior nuisance does not depend on nuisance parameters. They will be smeared in their full range"); } delete np; ((HybridCalculator*)hypoCalc)->ForcePriorNuisanceAlt(*nuisPdf); ((HybridCalculator*)hypoCalc)->ForcePriorNuisanceNull(*nuisPdf); } // hypoCalc->ForcePriorNuisanceAlt(*sbModel->GetPriorPdf()); // hypoCalc->ForcePriorNuisanceNull(*bModel->GetPriorPdf()); ToyMCSampler * sampler = (ToyMCSampler *)hypoCalc->GetTestStatSampler(); if (sampler && (calcType == 0 || calcType == 1) ) { // look if pdf is number counting or extended if (sbModel->GetPdf()->canBeExtended() ) { if (useNC) Warning("StandardHypoTestDemo","Pdf is extended: but number counting flag is set: ignore it "); } else { // for not extended pdf if (!useNC) { int nEvents = data->numEntries(); Info("StandardHypoTestDemo","Pdf is not extended: number of events to generate taken from observed data set is %d",nEvents); sampler->SetNEventsPerToy(nEvents); } else { Info("StandardHypoTestDemo","using a number counting pdf"); sampler->SetNEventsPerToy(1); } } if (data->isWeighted() && !generateBinned) { Info("StandardHypoTestDemo","Data set is weighted, nentries = %d and sum of weights = %8.1f but toy generation is unbinned - it would be faster to set generateBinned to true\n",data->numEntries(), data->sumEntries()); } if (generateBinned) sampler->SetGenerateBinned(generateBinned); // set the test statistic if (testStatType == 0) sampler->SetTestStatistic(slrts); if (testStatType == 1) sampler->SetTestStatistic(ropl); if (testStatType == 2 || testStatType == 3) sampler->SetTestStatistic(profll); } HypoTestResult * htr = hypoCalc->GetHypoTest(); htr->SetPValueIsRightTail(true); htr->SetBackgroundAsAlt(false); htr->Print(); // how to get meaningfull CLs at this point? delete sampler; delete slrts; delete ropl; delete profll; if (calcType != 2) { HypoTestPlot * plot = new HypoTestPlot(*htr,100); plot->SetLogYaxis(true); plot->Draw(); } else { std::cout << "Asymptotic results " << std::endl; } // look at expected significances // found median of S+B distribution if (calcType != 2) { SamplingDistribution * altDist = htr->GetAltDistribution(); HypoTestResult htExp("Expected Result"); htExp.Append(htr); // find quantiles in alt (S+B) distribution double p[5]; double q[5]; for (int i = 0; i < 5; ++i) { double sig = -2 + i; p[i] = ROOT::Math::normal_cdf(sig,1); } std::vector<double> values = altDist->GetSamplingDistribution(); TMath::Quantiles( values.size(), 5, &values[0], q, p, false); for (int i = 0; i < 5; ++i) { htExp.SetTestStatisticData( q[i] ); double sig = -2 + i; std::cout << " Expected p -value and significance at " << sig << " sigma = " << htExp.NullPValue() << " significance " << htExp.Significance() << " sigma " << std::endl; } } else { // case of asymptotic calculator for (int i = 0; i < 5; ++i) { double sig = -2 + i; // sigma is inverted here double pval = AsymptoticCalculator::GetExpectedPValues( htr->NullPValue(), htr->AlternatePValue(), -sig, false); std::cout << " Expected p -value and significance at " << sig << " sigma = " << pval << " significance " << ROOT::Math::normal_quantile_c(pval,1) << " sigma " << std::endl; } } }