// 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; }
/* * Prepares the workspace to be used by the hypothesis test calculator */ void workspace_preparer(char *signal_file_name, char *signal_hist_name_in_file, char *background_file_name, char *background_hist_name_in_file, char *data_file_name, char *data_hist_name_in_file, char *config_file) { // Include the config_reader class. TString path = gSystem->GetIncludePath(); path.Append(" -I/home/max/cern/cls/mario"); gSystem->SetIncludePath(path); gROOT->LoadMacro("config_reader.cxx"); // RooWorkspace used to store values. RooWorkspace * pWs = new RooWorkspace("ws"); // Create a config_reader (see source for details) to read the config // file. config_reader reader(config_file, pWs); // Read MR and RR bounds from the config file. double MR_lower = reader.find_double("MR_lower"); double MR_upper = reader.find_double("MR_upper"); double RR_lower = reader.find_double("RR_lower"); double RR_upper = reader.find_double("RR_upper"); double MR_initial = (MR_lower + MR_upper)/2; double RR_initial = (RR_lower + RR_upper)/2; // Define the Razor Variables RooRealVar MR = RooRealVar("MR", "MR", MR_initial, MR_lower, MR_upper); RooRealVar RR = RooRealVar("RSQ", "RSQ", RR_initial, RR_lower, RR_upper); // Argument lists RooArgList pdf_arg_list(MR, RR, "input_args_list"); RooArgSet pdf_arg_set(MR, RR, "input_pdf_args_set"); /***********************************************************************/ /* PART 1: IMPORTING SIGNAL AND BACKGROUND HISTOGRAMS */ /***********************************************************************/ /* * Get the signal's unextended pdf by converting the TH2D in the file * into a RooHistPdf */ TFile *signal_file = new TFile(signal_file_name); TH2D *signal_hist = (TH2D *)signal_file->Get(signal_hist_name_in_file); RooDataHist *signal_RooDataHist = new RooDataHist("signal_roodatahist", "signal_roodatahist", pdf_arg_list, signal_hist); RooHistPdf *unextended_sig_pdf = new RooHistPdf("unextended_sig_pdf", "unextended_sig_pdf", pdf_arg_set, *signal_RooDataHist); /* * Repeat this process for the background. */ TFile *background_file = new TFile(background_file_name); TH2D *background_hist = (TH2D *)background_file->Get(background_hist_name_in_file); RooDataHist *background_RooDataHist = new RooDataHist("background_roodatahist", "background_roodatahist", pdf_arg_list, background_hist); RooHistPdf *unextended_bkg_pdf = new RooHistPdf("unextended_bkg_pdf", "unextended_bkg_pdf", pdf_arg_set, *background_RooDataHist); /* * Now, we want to create the bprime variable, which represents the * integral over the background-only sample. We will perform the * integral automatically (that's why this is the only nuisance * parameter declared in this file - its value can be determined from * the input histograms). */ ostringstream bprime_string; ostringstream bprime_pdf_string; bprime_string << "bprime[" << background_hist->Integral() << ", 0, 999999999]"; bprime_pdf_string << "Poisson::bprime_pdf(bprime, " << background_hist->Integral() << ")"; pWs->factory(bprime_string.str().c_str()); pWs->factory(bprime_pdf_string.str().c_str()); /* * This simple command will create all values from the config file * with 'make:' at the beginning and a delimiter at the end (see config * _reader if you don't know what a delimiter is). In other * words, the luminosity, efficiency, transfer factors, and their pdfs * are created from this command. The declarations are contained in the * config file to be changed easily without having to modify this code. */ reader.factory_all(); /* * Now, we want to create the extended pdfs from the unextended pdfs, as * well as from the S and B values we manufactured in the config file. * S and B are the values by which the signal and background pdfs, * respectively, are extended. Recall that they were put in the * workspace in the reader.facotry_all() command. */ RooAbsReal *S = pWs->function("S"); RooAbsReal *B = pWs->function("B"); RooExtendPdf *signalpart = new RooExtendPdf("signalpart", "signalpart", *unextended_sig_pdf, *S); RooExtendPdf *backgroundpart = new RooExtendPdf("backgroundpart", "backgroundpart", *unextended_bkg_pdf, *B); RooArgList *pdf_list = new RooArgList(*signalpart, *backgroundpart, "list"); // Add the signal and background pdfs to make a TotalPdf RooAddPdf *TotalPdf = new RooAddPdf("TotalPdf", "TotalPdf", *pdf_list); RooArgList *pdf_prod_list = new RooArgList(*TotalPdf, *pWs->pdf("lumi_pdf"), *pWs->pdf("eff_pdf"), *pWs->pdf("rho_pdf"), *pWs->pdf("bprime_pdf")); // This creates the final model pdf. RooProdPdf *model = new RooProdPdf("model", "model", *pdf_prod_list); /* * Up until now, we have been using the workspace pWs to contain all of * our values. Now, all of our values that we require are in use in the * RooProdPdf called "model". So, we need to import "model" into a * RooWorkspace. To avoid recopying values into the rooworkspace, when * the values may already be present (which can cause problems), we will * simply create a new RooWorkspace to avoid confusion and problems. The * new RooWorkspace is created here. */ RooWorkspace *newworkspace = new RooWorkspace("newws"); newworkspace->import(*model); // Immediately delete pWs, so we don't accidentally use it again. delete pWs; // Show off the newworkspace newworkspace->Print(); // observables RooArgSet obs(*newworkspace->var("MR"), *newworkspace->var("RSQ"), "obs"); // global observables RooArgSet globalObs(*newworkspace->var("nom_lumi"), *newworkspace->var("nom_eff"), *newworkspace->var("nom_rho")); //fix global observables to their nominal values newworkspace->var("nom_lumi")->setConstant(); newworkspace->var("nom_eff")->setConstant(); newworkspace->var("nom_rho")->setConstant(); //Set Parameters of interest RooArgSet poi(*newworkspace->var("sigma"), "poi"); //Set Nuisnaces RooArgSet nuis(*newworkspace->var("prime_lumi"), *newworkspace->var("prime_eff"), *newworkspace->var("prime_rho"), *newworkspace->var("bprime")); // priors (for Bayesian calculation) newworkspace->factory("Uniform::prior_signal(sigma)"); // for parameter of interest newworkspace->factory("Uniform::prior_bg_b(bprime)"); // for data driven nuisance parameter newworkspace->factory("PROD::prior(prior_signal,prior_bg_b)"); // total prior //Observed data is pulled from histogram. //TFile *data_file = new TFile(data_file_name); TFile *data_file = new TFile(data_file_name); TH2D *data_hist = (TH2D *)data_file->Get(data_hist_name_in_file); RooDataHist *pData = new RooDataHist("data", "data", obs, data_hist); newworkspace->import(*pData); // Now, we will draw our data from a RooDataHist. /*TFile *data_file = new TFile(data_file_name); TTree *data_tree = (TTree *) data_file->Get(data_hist_name_in_file); RooDataSet *pData = new RooDataSet("data", "data", data_tree, obs); newworkspace->import(*pData);*/ // Craft the signal+background model ModelConfig * pSbModel = new ModelConfig("SbModel"); pSbModel->SetWorkspace(*newworkspace); pSbModel->SetPdf(*newworkspace->pdf("model")); pSbModel->SetPriorPdf(*newworkspace->pdf("prior")); pSbModel->SetParametersOfInterest(poi); pSbModel->SetNuisanceParameters(nuis); pSbModel->SetObservables(obs); pSbModel->SetGlobalObservables(globalObs); // set all but obs, poi and nuisance to const SetConstants(newworkspace, pSbModel); newworkspace->import(*pSbModel); // background-only model // use the same PDF as s+b, with sig=0 // POI value under the background hypothesis // (We will set the value to 0 later) Double_t poiValueForBModel = 0.0; ModelConfig* pBModel = new ModelConfig(*(RooStats::ModelConfig *)newworkspace->obj("SbModel")); pBModel->SetName("BModel"); pBModel->SetWorkspace(*newworkspace); newworkspace->import(*pBModel); // find global maximum with the signal+background model // with conditional MLEs for nuisance parameters // and save the parameter point snapshot in the Workspace // - safer to keep a default name because some RooStats calculators // will anticipate it RooAbsReal * pNll = pSbModel->GetPdf()->createNLL(*pData); RooAbsReal * pProfile = pNll->createProfile(RooArgSet()); pProfile->getVal(); // this will do fit and set POI and nuisance parameters to fitted values RooArgSet * pPoiAndNuisance = new RooArgSet(); if(pSbModel->GetNuisanceParameters()) pPoiAndNuisance->add(*pSbModel->GetNuisanceParameters()); pPoiAndNuisance->add(*pSbModel->GetParametersOfInterest()); cout << "\nWill save these parameter points that correspond to the fit to data" << endl; pPoiAndNuisance->Print("v"); pSbModel->SetSnapshot(*pPoiAndNuisance); delete pProfile; delete pNll; delete pPoiAndNuisance; // Find a parameter point for generating pseudo-data // with the background-only data. // Save the parameter point snapshot in the Workspace pNll = pBModel->GetPdf()->createNLL(*pData); pProfile = pNll->createProfile(poi); ((RooRealVar *)poi.first())->setVal(poiValueForBModel); pProfile->getVal(); // this will do fit and set nuisance parameters to profiled values pPoiAndNuisance = new RooArgSet(); if(pBModel->GetNuisanceParameters()) pPoiAndNuisance->add(*pBModel->GetNuisanceParameters()); pPoiAndNuisance->add(*pBModel->GetParametersOfInterest()); cout << "\nShould use these parameter points to generate pseudo data for bkg only" << endl; pPoiAndNuisance->Print("v"); pBModel->SetSnapshot(*pPoiAndNuisance); delete pProfile; delete pNll; delete pPoiAndNuisance; // save workspace to file newworkspace->writeToFile("ws_twobin.root"); // clean up delete newworkspace; delete pData; delete pSbModel; delete pBModel; } // ----- end of tutorial ----------------------------------------
// internal routine to run the inverter HypoTestInverterResult * RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName, const char * dataName, int type, int testStatType, int npoints, double poimin, double poimax, int ntoys, bool useCls ) { std::cout << "Running HypoTestInverter on the workspace " << w->GetName() << std::endl; w->Print(); RooAbsData * data = w->data(dataName); if (!data) { Error("RA2bHypoTestDemo","Not existing data %s",dataName); return 0; } else std::cout << "Using data set " << dataName << std::endl; // 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("RA2bHypoTestDemo","Not existing ModelConfig %s",modelSBName); return 0; } // check the model if (!sbModel->GetPdf()) { Error("RA2bHypoTestDemo","Model %s has no pdf ",modelSBName); return 0; } if (!sbModel->GetParametersOfInterest()) { Error("RA2bHypoTestDemo","Model %s has no poi ",modelSBName); return 0; } if (!sbModel->GetParametersOfInterest()) { Error("RA2bHypoTestInvDemo","Model %s has no poi ",modelSBName); return 0; } if (!sbModel->GetSnapshot() ) { Info("RA2bHypoTestInvDemo","Model %s has no snapshot - make one using model poi",modelSBName); sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() ); } if (!bModel || bModel == sbModel) { Info("RA2bHypoTestInvDemo","The background model %s does not exist",modelBName); Info("RA2bHypoTestInvDemo","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("RA2bHypoTestInvDemo","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("RA2bHypoTestInvDemo","Model %s has no valid poi",modelBName); return 0; } } } SimpleLikelihoodRatioTestStat slrts(*sbModel->GetPdf(),*bModel->GetPdf()); if (sbModel->GetSnapshot()) slrts.SetNullParameters(*sbModel->GetSnapshot()); if (bModel->GetSnapshot()) slrts.SetAltParameters(*bModel->GetSnapshot()); // ratio of profile likelihood - need to pass snapshot for the alt RatioOfProfiledLikelihoodsTestStat ropl(*sbModel->GetPdf(), *bModel->GetPdf(), bModel->GetSnapshot()); ropl.SetSubtractMLE(false); //MyProfileLikelihoodTestStat profll(*sbModel->GetPdf()); ProfileLikelihoodTestStat profll(*sbModel->GetPdf()); if (testStatType == 3) profll.SetOneSided(1); if (optimize) profll.SetReuseNLL(true); TestStatistic * testStat = &slrts; if (testStatType == 1) testStat = &ropl; if (testStatType == 2 || testStatType == 3) testStat = &profll; HypoTestCalculatorGeneric * hc = 0; if (type == 0) hc = new FrequentistCalculator(*data, *bModel, *sbModel); else hc = new HybridCalculator(*data, *bModel, *sbModel); ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler(); //=== DEBUG ///// toymcs->SetWS( w ) ; //=== DEBUG toymcs->SetNEventsPerToy(1); toymcs->SetTestStatistic(testStat); if (optimize) toymcs->SetUseMultiGen(true); if (type == 1) { HybridCalculator *hhc = (HybridCalculator*) hc; hhc->SetToys(ntoys,ntoys); // check for nuisance prior pdf if (bModel->GetPriorPdf() && sbModel->GetPriorPdf() ) { hhc->ForcePriorNuisanceAlt(*bModel->GetPriorPdf()); hhc->ForcePriorNuisanceNull(*sbModel->GetPriorPdf()); } else { if (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() ) { Error("RA2bHypoTestInvDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified"); return 0; } } } else ((FrequentistCalculator*) hc)->SetToys(ntoys,ntoys); // Get the result RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration); TStopwatch tw; tw.Start(); const RooArgSet * poiSet = sbModel->GetParametersOfInterest(); RooRealVar *poi = (RooRealVar*)poiSet->first(); // fit the data first sbModel->GetPdf()->fitTo(*data); double poihat = poi->getVal(); HypoTestInverter calc(*hc); calc.SetConfidenceLevel(0.95); calc.UseCLs(useCls); calc.SetVerbose(true); // can speed up using proof-lite if (useProof && nworkers > 1) { ProofConfig pc(*w, nworkers, "", kFALSE); toymcs->SetProofConfig(&pc); // enable proof } printf(" npoints = %d, poimin = %7.2f, poimax = %7.2f\n\n", npoints, poimin, poimax ) ; cout << flush ; if ( npoints==1 ) { std::cout << "Evaluating one point : " << poimax << std::endl; calc.RunOnePoint(poimax); } else 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; } cout << "\n\n right before calc.GetInterval(), ntoys = " << ntoys << " \n\n" << flush ; HypoTestInverterResult * r = calc.GetInterval(); return r; }
// implementation void TwoBinInstructional( void ){ // let's time this example TStopwatch t; t.Start(); // set RooFit random seed for reproducible results RooRandom::randomGenerator()->SetSeed(4357); // make model RooWorkspace * pWs = new RooWorkspace("ws"); // derived from data pWs->factory("xsec[0.2,0,2]"); // POI pWs->factory("bg_b[10,0,50]"); // data driven nuisance // predefined nuisances pWs->factory("lumi[100,0,1000]"); pWs->factory("eff_a[0.2,0,1]"); pWs->factory("eff_b[0.05,0,1]"); pWs->factory("tau[0,1]"); pWs->factory("xsec_bg_a[0.05]"); // constant pWs->var("xsec_bg_a")->setConstant(1); // channel a (signal): lumi*xsec*eff_a + lumi*bg_a + tau*bg_b pWs->factory("prod::sig_a(lumi,xsec,eff_a)"); pWs->factory("prod::bg_a(lumi,xsec_bg_a)"); pWs->factory("prod::tau_bg_b(tau, bg_b)"); pWs->factory("Poisson::pdf_a(na[14,0,100],sum::mu_a(sig_a,bg_a,tau_bg_b))"); // channel b (control): lumi*xsec*eff_b + bg_b pWs->factory("prod::sig_b(lumi,xsec,eff_b)"); pWs->factory("Poisson::pdf_b(nb[11,0,100],sum::mu_b(sig_b,bg_b))"); // nuisance constraint terms (systematics) pWs->factory("Lognormal::l_lumi(lumi,nom_lumi[100,0,1000],sum::kappa_lumi(1,d_lumi[0.1]))"); pWs->factory("Lognormal::l_eff_a(eff_a,nom_eff_a[0.20,0,1],sum::kappa_eff_a(1,d_eff_a[0.05]))"); pWs->factory("Lognormal::l_eff_b(eff_b,nom_eff_b[0.05,0,1],sum::kappa_eff_b(1,d_eff_b[0.05]))"); pWs->factory("Lognormal::l_tau(tau,nom_tau[0.50,0,1],sum::kappa_tau(1,d_tau[0.05]))"); //pWs->factory("Lognormal::l_bg_a(bg_a,nom_bg_a[0.05,0,1],sum::kappa_bg_a(1,d_bg_a[0.10]))"); // complete model PDF pWs->factory("PROD::model(pdf_a,pdf_b,l_lumi,l_eff_a,l_eff_b,l_tau)"); // Now create sets of variables. Note that we could use the factory to // create sets but in that case many of the sets would be duplicated // when the ModelConfig objects are imported into the workspace. So, // we create the sets outside the workspace, and only the needed ones // will be automatically imported by ModelConfigs // observables RooArgSet obs(*pWs->var("na"), *pWs->var("nb"), "obs"); // global observables RooArgSet globalObs(*pWs->var("nom_lumi"), *pWs->var("nom_eff_a"), *pWs->var("nom_eff_b"), *pWs->var("nom_tau"), "global_obs"); // parameters of interest RooArgSet poi(*pWs->var("xsec"), "poi"); // nuisance parameters RooArgSet nuis(*pWs->var("lumi"), *pWs->var("eff_a"), *pWs->var("eff_b"), *pWs->var("tau"), "nuis"); // priors (for Bayesian calculation) pWs->factory("Uniform::prior_xsec(xsec)"); // for parameter of interest pWs->factory("Uniform::prior_bg_b(bg_b)"); // for data driven nuisance parameter pWs->factory("PROD::prior(prior_xsec,prior_bg_b)"); // total prior // create data pWs->var("na")->setVal(14); pWs->var("nb")->setVal(11); RooDataSet * pData = new RooDataSet("data","",obs); pData->add(obs); pWs->import(*pData); //pData->Print(); // signal+background model ModelConfig * pSbModel = new ModelConfig("SbModel"); pSbModel->SetWorkspace(*pWs); pSbModel->SetPdf(*pWs->pdf("model")); pSbModel->SetPriorPdf(*pWs->pdf("prior")); pSbModel->SetParametersOfInterest(poi); pSbModel->SetNuisanceParameters(nuis); pSbModel->SetObservables(obs); pSbModel->SetGlobalObservables(globalObs); // set all but obs, poi and nuisance to const SetConstants(pWs, pSbModel); pWs->import(*pSbModel); // background-only model // use the same PDF as s+b, with xsec=0 // POI value under the background hypothesis Double_t poiValueForBModel = 0.0; ModelConfig* pBModel = new ModelConfig(*(RooStats::ModelConfig *)pWs->obj("SbModel")); pBModel->SetName("BModel"); pBModel->SetWorkspace(*pWs); pWs->import(*pBModel); // find global maximum with the signal+background model // with conditional MLEs for nuisance parameters // and save the parameter point snapshot in the Workspace // - safer to keep a default name because some RooStats calculators // will anticipate it RooAbsReal * pNll = pSbModel->GetPdf()->createNLL(*pData); RooAbsReal * pProfile = pNll->createProfile(RooArgSet()); pProfile->getVal(); // this will do fit and set POI and nuisance parameters to fitted values RooArgSet * pPoiAndNuisance = new RooArgSet(); if(pSbModel->GetNuisanceParameters()) pPoiAndNuisance->add(*pSbModel->GetNuisanceParameters()); pPoiAndNuisance->add(*pSbModel->GetParametersOfInterest()); cout << "\nWill save these parameter points that correspond to the fit to data" << endl; pPoiAndNuisance->Print("v"); pSbModel->SetSnapshot(*pPoiAndNuisance); delete pProfile; delete pNll; delete pPoiAndNuisance; // Find a parameter point for generating pseudo-data // with the background-only data. // Save the parameter point snapshot in the Workspace pNll = pBModel->GetPdf()->createNLL(*pData); pProfile = pNll->createProfile(poi); ((RooRealVar *)poi.first())->setVal(poiValueForBModel); pProfile->getVal(); // this will do fit and set nuisance parameters to profiled values pPoiAndNuisance = new RooArgSet(); if(pBModel->GetNuisanceParameters()) pPoiAndNuisance->add(*pBModel->GetNuisanceParameters()); pPoiAndNuisance->add(*pBModel->GetParametersOfInterest()); cout << "\nShould use these parameter points to generate pseudo data for bkg only" << endl; pPoiAndNuisance->Print("v"); pBModel->SetSnapshot(*pPoiAndNuisance); delete pProfile; delete pNll; delete pPoiAndNuisance; // inspect workspace pWs->Print(); // save workspace to file pWs->writeToFile("ws_twobin.root"); // clean up delete pWs; delete pData; delete pSbModel; delete pBModel; } // ----- end of tutorial ----------------------------------------
void new_RA4(){ // let's time this challenging example TStopwatch t; t.Start(); // set RooFit random seed for reproducible results RooRandom::randomGenerator()->SetSeed(4357); // make model RooWorkspace* wspace = new RooWorkspace("wspace"); wspace->factory("Gaussian::sigCons(prime_SigEff[0,-5,5], nom_SigEff[0,-5,5], 1)"); wspace->factory("expr::SigEff('1.0*pow(1.20,@0)',prime_SigEff)"); // // 1+-20%, 1.20=exp(20%) wspace->factory("Poisson::on(non[0,50], sum::splusb(prod::SigUnc(s[0,0,50],SigEff),mainb[8.8,0,50],dilep[0.9,0,20],tau[2.3,0,20],QCD[0.,0,10],MC[0.1,0,4]))"); wspace->factory("Gaussian::mcCons(prime_rho[0,-5,5], nom_rho[0,-5,5], 1)"); wspace->factory("expr::rho('1.0*pow(1.39,@0)',prime_rho)"); // // 1+-39% wspace->factory("Poisson::off(noff[0,200], prod::rhob(mainb,rho,mu_plus_e[0.74,0.01,10],1.08))"); wspace->factory("Gaussian::mcCons2(mu_plus_enom[0.74,0.01,4], mu_plus_e, sigmatwo[.05])"); wspace->factory("Gaussian::dilep_pred(dilep_nom[0.9,0,20], dilep, sigma3[2.2])"); wspace->factory("Gaussian::tau_pred(tau_nom[2.3,0,20], tau, sigma4[0.5])"); wspace->factory("Gaussian::QCD_pred(QCD_nom[0.0,0,10], QCD, sigma5[1.0])"); wspace->factory("Gaussian::MC_pred(MC_nom[0.1,0.01,4], MC, sigma7[0.14])"); wspace->factory("PROD::model(on,off,mcCons,mcCons2,sigCons,dilep_pred,tau_pred,QCD_pred,MC_pred)"); RooArgSet obs(*wspace->var("non"), *wspace->var("noff"), *wspace->var("mu_plus_enom"), *wspace->var("dilep_nom"), *wspace->var("tau_nom"), "obs"); obs.add(*wspace->var("QCD_nom")); obs.add(*wspace->var("MC_nom")); RooArgSet globalObs(*wspace->var("nom_SigEff"), *wspace->var("nom_rho"), "global_obs"); // fix global observables to their nominal values wspace->var("nom_SigEff")->setConstant(); wspace->var("nom_rho")->setConstant(); RooArgSet poi(*wspace->var("s"), "poi"); RooArgSet nuis(*wspace->var("mainb"), *wspace->var("prime_rho"), *wspace->var("prime_SigEff"), *wspace->var("mu_plus_e"), *wspace->var("dilep"), *wspace->var("tau"), "nuis"); nuis.add(*wspace->var("QCD")); nuis.add(*wspace->var("MC")); wspace->factory("Uniform::prior_poi({s})"); wspace->factory("Uniform::prior_nuis({mainb,mu_plus_e,dilep,tau,QCD,MC})"); wspace->factory("PROD::prior(prior_poi,prior_nuis)"); wspace->var("non")->setVal(8); //observed //wspace->var("non")->setVal(12); //expected observation wspace->var("noff")->setVal(7); //observed events in control region wspace->var("mu_plus_enom")->setVal(0.74); wspace->var("dilep_nom")->setVal(0.9); wspace->var("tau_nom")->setVal(2.3); wspace->var("QCD")->setVal(0.0); wspace->var("MC")->setVal(0.1); RooDataSet * data = new RooDataSet("data","",obs); data->add(obs); wspace->import(*data); ///////////////////////////////////////////////////// // Now the statistical tests // model config ModelConfig* pSbModel = new ModelConfig("SbModel"); pSbModel->SetWorkspace(*wspace); pSbModel->SetPdf(*wspace->pdf("model")); pSbModel->SetPriorPdf(*wspace->pdf("prior")); pSbModel->SetParametersOfInterest(poi); pSbModel->SetNuisanceParameters(nuis); pSbModel->SetObservables(obs); pSbModel->SetGlobalObservables(globalObs); wspace->import(*pSbModel); // set all but obs, poi and nuisance to const SetConstants(wspace, pSbModel); wspace->import(*pSbModel); Double_t poiValueForBModel = 0.0; ModelConfig* pBModel = new ModelConfig(*(RooStats::ModelConfig *)wspace->obj("SbModel")); pBModel->SetName("BModel"); pBModel->SetWorkspace(*wspace); wspace->import(*pBModel); RooAbsReal * pNll = pSbModel->GetPdf()->createNLL(*data); RooAbsReal * pProfile = pNll->createProfile(RooArgSet()); pProfile->getVal(); // this will do fit and set POI and nuisance parameters to fitted values RooArgSet * pPoiAndNuisance = new RooArgSet(); //if(pSbModel->GetNuisanceParameters()) // pPoiAndNuisance->add(*pSbModel->GetNuisanceParameters()); pPoiAndNuisance->add(*pSbModel->GetParametersOfInterest()); cout << "\nWill save these parameter points that correspond to the fit to data" << endl; pPoiAndNuisance->Print("v"); pSbModel->SetSnapshot(*pPoiAndNuisance); delete pProfile; delete pNll; delete pPoiAndNuisance; pNll = pBModel->GetPdf()->createNLL(*data); pProfile = pNll->createProfile(poi); ((RooRealVar *)poi.first())->setVal(poiValueForBModel); pProfile->getVal(); // this will do fit and set nuisance parameters to profiled values pPoiAndNuisance = new RooArgSet(); //if(pBModel->GetNuisanceParameters()) // pPoiAndNuisance->add(*pBModel->GetNuisanceParameters()); pPoiAndNuisance->add(*pBModel->GetParametersOfInterest()); cout << "\nShould use these parameter points to generate pseudo data for bkg only" << endl; pPoiAndNuisance->Print("v"); pBModel->SetSnapshot(*pPoiAndNuisance); delete pProfile; delete pNll; delete pPoiAndNuisance; // inspect workspace wspace->Print(); // save workspace to file wspace->writeToFile("tight.root"); //wspace->writeToFile("tight_median.root"); // clean up delete wspace; delete data; delete pSbModel; delete pBModel; }
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; } } }
void build_hbb_workspace1( const char* infile = "outputfiles/input-file.txt", const char* outfile = "outputfiles/ws.root" ) { //------------------------------------------------------------------------- //-- Create workspace and other RooStats things. printf("\n\n Creating workspace.\n\n") ; RooWorkspace workspace("ws") ; workspace.autoImportClassCode(true) ; globalObservables = new RooArgSet("globalObservables"); allNuisances = new RooArgSet("allNuisances"); allNuisancePdfs = new RooArgSet("allNuisancePdfs"); RooArgSet* observedParametersList = new RooArgSet("observables") ; //------------------------------------------------------------------------- printf("\n\n Reading input file: %s\n\n", infile ) ; float fileVal ; char pname[1000] ; char formula[1000] ; sprintf( pname, "bins_of_met" ) ; if ( !getFileValue( infile, pname, fileVal ) ) { printf("\n\n *** Error. Can't find %s\n\n", pname ) ; return ; } int bins_of_met = TMath::Nint( fileVal ) ; //-- save bins_of_met in the workspace for convenience. RooRealVar bom( "bins_of_met", "bins_of_met", bins_of_met, 0., 1000. ) ; bom.setConstant(kTRUE) ; workspace.import(bom) ; //-- save bins_of_nb in the workspace for convenience. RooRealVar bonb( "bins_of_nb", "bins_of_nb", bins_of_nb, 0., 1000. ) ; bonb.setConstant(kTRUE) ; workspace.import(bonb) ; RooRealVar* rv_N_msig[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooRealVar* rv_N_msb[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooRealVar* rv_smc_msig[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooRealVar* rv_smc_msb[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooAbsReal* rv_Rsigsb_corr[bins_of_nb][max_bins_of_met] ; for ( int nbi=0; nbi<bins_of_nb; nbi++ ) { for ( int mbi=0; mbi<bins_of_met; mbi++ ) { sprintf( pname, "N_%db_msig_met%d", nbi+2, mbi+1 ) ; if ( !getFileValue( infile, pname, fileVal ) ) { printf("\n\n *** Error. Can't find %s\n\n", pname ) ; return ; } rv_N_msig[nbi][mbi] = new RooRealVar( pname, pname, 0., 1.e6 ) ; rv_N_msig[nbi][mbi] -> setVal( TMath::Nint(fileVal) ) ; rv_N_msig[nbi][mbi] -> setConstant( kTRUE ) ; observedParametersList -> add( *rv_N_msig[nbi][mbi] ) ; sprintf( pname, "N_%db_msb_met%d", nbi+2, mbi+1 ) ; if ( !getFileValue( infile, pname, fileVal ) ) { printf("\n\n *** Error. Can't find %s\n\n", pname ) ; return ; } rv_N_msb[nbi][mbi] = new RooRealVar( pname, pname, 0., 1.e6 ) ; rv_N_msb[nbi][mbi] -> setVal( TMath::Nint(fileVal) ) ; rv_N_msb[nbi][mbi] -> setConstant( kTRUE ) ; observedParametersList -> add( *rv_N_msb[nbi][mbi] ) ; sprintf( pname, "smc_%db_msig_met%d", nbi+2, mbi+1 ) ; if ( !getFileValue( infile, pname, fileVal ) ) { printf("\n\n *** Error. Can't find %s\n\n", pname ) ; return ; } rv_smc_msig[nbi][mbi] = new RooRealVar( pname, pname, 0., 1.e6 ) ; rv_smc_msig[nbi][mbi] -> setVal( TMath::Nint(fileVal) ) ; rv_smc_msig[nbi][mbi] -> setConstant( kTRUE ) ; sprintf( pname, "smc_%db_msb_met%d", nbi+2, mbi+1 ) ; if ( !getFileValue( infile, pname, fileVal ) ) { printf("\n\n *** Error. Can't find %s\n\n", pname ) ; return ; } rv_smc_msb[nbi][mbi] = new RooRealVar( pname, pname, 0., 1.e6 ) ; rv_smc_msb[nbi][mbi] -> setVal( TMath::Nint(fileVal) ) ; rv_smc_msb[nbi][mbi] -> setConstant( kTRUE ) ; float corrVal, corrSyst ; sprintf( pname, "Rsigsb_syst_%db_met%d", nbi+2, mbi+1 ) ; if ( !getFileValue( infile, pname, corrSyst ) ) { printf("\n\n *** Error. Can't find %s\n\n", pname ) ; return ; } sprintf( pname, "Rsigsb_corr_%db_met%d", nbi+2, mbi+1 ) ; if ( !getFileValue( infile, pname, corrVal ) ) { printf("\n\n *** Error. Can't find %s\n\n", pname ) ; return ; } rv_Rsigsb_corr[nbi][mbi] = makeLognormalConstraint( pname, corrVal, corrSyst ) ; } // mbi. } // nbi. //-- Finished reading input from file. //------------------------------------------------------------------------- printf("\n\n Creating and importing dataset into workspace.\n\n") ; RooDataSet* dsObserved = new RooDataSet("hbb_observed_rds", "hbb observed data values", *observedParametersList ) ; dsObserved -> add( *observedParametersList ) ; workspace.import( *dsObserved ) ; //------------------------------------------------------------------------- //-- Define all floats. printf("\n\n Defining all unconstrained floats (Ratios, signal strength).\n\n") ; double R_msigmsb_initialval(0.15) ; RooRealVar* rv_R_msigmsb[50] ; for ( int mbi=0; mbi<bins_of_met; mbi++ ) { sprintf( pname, "R_msigmsb_met%d", mbi+1 ) ; printf( " %s\n", pname ) ; rv_R_msigmsb[mbi] = new RooRealVar( pname, pname, R_msigmsb_initialval, 0., 3. ) ; rv_R_msigmsb[mbi] -> setConstant( kFALSE ) ; rv_R_msigmsb[mbi] -> Print() ; } // mbi. printf("\n") ; sprintf( pname, "sig_strength" ) ; RooRealVar* rv_sig_strength = new RooRealVar( pname, pname, 1.0, 0., 10. ) ; rv_sig_strength -> setConstant(kFALSE) ; rv_sig_strength -> Print() ; printf(" %s\n\n", pname ) ; //------------------------------------------------------------------------- //-- Define all mu parameters. printf("\n\n Defining mu parameters.\n\n") ; RooAbsReal* rv_mu_bg_msig[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooAbsReal* rv_mu_bg_msb[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooAbsReal* rv_mu_sig_msig[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooAbsReal* rv_mu_sig_msb[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. for ( int nbi=0; nbi<bins_of_nb; nbi++ ) { for ( int mbi=0; mbi<bins_of_met; mbi++ ) { sprintf( pname, "mu_bg_%db_msb_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_mu_bg_msb[nbi][mbi] = new RooRealVar( pname, pname, rv_N_msb[nbi][mbi] -> getVal(), 0., 1.e6 ) ; rv_mu_bg_msb[nbi][mbi] -> Print() ; sprintf( formula, "@0 * @1 * @2" ) ; sprintf( pname, "mu_bg_%db_msig_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_mu_bg_msig[nbi][mbi] = new RooFormulaVar( pname, formula, RooArgSet( *rv_Rsigsb_corr[nbi][mbi], *rv_R_msigmsb[mbi], *rv_mu_bg_msb[nbi][mbi] ) ) ; rv_mu_bg_msig[nbi][mbi] -> Print() ; sprintf( formula, "@0 * @1" ) ; sprintf( pname, "mu_sig_%db_msig_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_mu_sig_msig[nbi][mbi] = new RooFormulaVar( pname, formula, RooArgSet( *rv_sig_strength, *rv_smc_msig[nbi][mbi] ) ) ; rv_mu_sig_msig[nbi][mbi] -> Print() ; sprintf( formula, "@0 * @1" ) ; sprintf( pname, "mu_sig_%db_msb_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_mu_sig_msb[nbi][mbi] = new RooFormulaVar( pname, formula, RooArgSet( *rv_sig_strength, *rv_smc_msb[nbi][mbi] ) ) ; rv_mu_sig_msb[nbi][mbi] -> Print() ; } // mbi. } // nbi. //-- Finished defining mu parameters. //------------------------------------------------------------------------- //-- Defining small n's printf("\n\n Defining small n's.\n\n") ; RooAbsReal* rv_n_msig[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooAbsReal* rv_n_msb[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. for ( int nbi=0; nbi<bins_of_nb; nbi++ ) { for ( int mbi=0; mbi<bins_of_met; mbi++ ) { sprintf( formula, "@0 + @1" ) ; sprintf( pname, "n_%db_msig_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_n_msig[nbi][mbi] = new RooFormulaVar( pname, formula, RooArgSet( *rv_mu_sig_msig[nbi][mbi], *rv_mu_bg_msig[nbi][mbi] ) ) ; rv_n_msig[nbi][mbi] -> Print() ; workspace.import( *rv_n_msig[nbi][mbi] ) ; sprintf( pname, "n_%db_msb_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_n_msb[nbi][mbi] = new RooFormulaVar( pname, formula, RooArgSet( *rv_mu_sig_msb[nbi][mbi], *rv_mu_bg_msb[nbi][mbi] ) ) ; rv_n_msb[nbi][mbi] -> Print() ; workspace.import( *rv_n_msb[nbi][mbi] ) ; } // mbi. } // nbi. //------------------------------------------------------------------------- //-- Define the Poisson pdfs for the observables. printf("\n\n Defining Poisson pdfs for the observables.\n\n") ; RooAbsReal* rv_pdf_msig[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooAbsReal* rv_pdf_msb[bins_of_nb][max_bins_of_met] ; // first index is number of btags, second is met bin. RooArgSet pdflist ; for ( int nbi=0; nbi<bins_of_nb; nbi++ ) { for ( int mbi=0; mbi<bins_of_met; mbi++ ) { sprintf( pname, "pdf_%db_msig_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_pdf_msig[nbi][mbi] = new RooPoisson( pname, pname, *rv_N_msig[nbi][mbi], *rv_n_msig[nbi][mbi] ) ; rv_pdf_msig[nbi][mbi] -> Print() ; pdflist.add( *rv_pdf_msig[nbi][mbi] ) ; sprintf( pname, "pdf_%db_msb_met%d", nbi+2, mbi+1 ) ; printf( " %s\n", pname ) ; rv_pdf_msb[nbi][mbi] = new RooPoisson( pname, pname, *rv_N_msb[nbi][mbi], *rv_n_msb[nbi][mbi] ) ; rv_pdf_msb[nbi][mbi] -> Print() ; pdflist.add( *rv_pdf_msb[nbi][mbi] ) ; } // mbi. } // nbi. //------------------------------------------------------------------------- //-- Build the likelihood. printf("\n\n Building the likelihood.\n\n") ; pdflist.add( *allNuisancePdfs ) ; pdflist.Print() ; printf("\n") ; RooProdPdf* likelihood = new RooProdPdf( "likelihood", "hbb likelihood", pdflist ) ; likelihood->Print() ; //------------------------------------------------------------------------- // printf("\n\n Running a test fit.\n\n") ; // dsObserved -> Print() ; // dsObserved -> printMultiline(cout, 1, kTRUE, "") ; // printf("\n\n =============================================\n\n") ; // likelihood -> fitTo( *dsObserved, PrintLevel(3), Hesse(0), Minos(0) ) ; // printf("\n\n =============================================\n\n") ; //-- Set up RooStats models. printf("\n\n Setting up S+B model.\n\n") ; RooArgSet poi( *rv_sig_strength, "poi" ) ; RooUniform signal_prior( "signal_prior", "signal_prior", *rv_sig_strength ) ; ModelConfig sbModel ("SbModel"); sbModel.SetWorkspace( workspace ) ; sbModel.SetPdf( *likelihood ) ; sbModel.SetParametersOfInterest( poi ); sbModel.SetPriorPdf(signal_prior); sbModel.SetObservables( *observedParametersList ); sbModel.SetNuisanceParameters( *allNuisances ); sbModel.SetGlobalObservables( *globalObservables ); workspace.Print() ; printf("\n\n Doing fit for S+B model.\n" ) ; fflush(stdout) ; RooAbsReal* pNll = sbModel.GetPdf()->createNLL(*dsObserved); RooAbsReal* pProfile = pNll->createProfile(RooArgSet()); pProfile->getVal(); RooArgSet* pPoiAndNuisance = new RooArgSet(); pPoiAndNuisance->add(*sbModel.GetParametersOfInterest()); if(sbModel.GetNuisanceParameters()) pPoiAndNuisance->add(*sbModel.GetNuisanceParameters()); printf("\n\n Will save these parameter points that correspond to the fit to data.\n\n") ; fflush(stdout) ; pPoiAndNuisance->Print("v"); sbModel.SetSnapshot(*pPoiAndNuisance); workspace.import (sbModel); delete pProfile ; delete pNll ; delete pPoiAndNuisance ; printf("\n\n Setting up BG-only model.\n\n") ; ModelConfig bModel (*(RooStats::ModelConfig *)workspace.obj("SbModel")); bModel.SetName("BModel"); bModel.SetWorkspace(workspace); printf("\n\n Doing fit for BG-only model.\n" ) ; fflush(stdout) ; pNll = bModel.GetPdf()->createNLL(*dsObserved); pProfile = pNll->createProfile(*bModel.GetParametersOfInterest()); ((RooRealVar *)(bModel.GetParametersOfInterest()->first()))->setVal(0.); pProfile->getVal(); pPoiAndNuisance = new RooArgSet(); pPoiAndNuisance->add(*bModel.GetParametersOfInterest()); if(bModel.GetNuisanceParameters()) pPoiAndNuisance->add(*bModel.GetNuisanceParameters()); printf("\n\n Should use these parameter points to generate pseudo data for bkg only.\n\n") ; fflush(stdout) ; pPoiAndNuisance->Print("v"); bModel.SetSnapshot(*pPoiAndNuisance); workspace.import (bModel); delete pProfile ; delete pNll ; delete pPoiAndNuisance ; workspace.Print() ; printf("\n\n Saving workspace in : %s\n\n", outfile ) ; gSystem->Exec(" mkdir -p outputfiles " ) ; workspace.writeToFile( outfile ) ; } // build_hbb_workspace1.
void test_counting_experiment() { ////////////////////// MODEL BUILDING ///////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* N_s = N_tot_theory(Mass,Xsec) * Acceptance_SR * Eff_AmBe_bin_i * mu N_b = N_Co_SR_bin_i * Norm_factor Xesec: considered 10^-40 cm^2 Norm_factor = N_Data_CR / N_Co_CR --> assuming no difference between Co and Data in CR and SR. N_tot_theory(Mass,Xsec): for 225 livedays, 45kg and considering Xsec. It is a constant, no uncertainty at the moment. ---Costraint Signal nuissance parameter = Acceptance_SR, Eff_AmBe_bin_i Gauss(Acceptance_SR_obs | Acceptance_SR, err.) Poisson(S0_i | S_tot_SR * Eff_AmBe_bin_i) ---Costraint Bkg nuissance parameter = N_Co_SR_bin_i, Norm_factor Gauss(Norm_factor_obs | Norm_factor, err) Poisson(B0_i | N_Co_SR_bin_i) ---- WARNING:: convergence problems: mu_hat should always be >> 1, too small values have problem in finding minimum because mu is set >0. ---> Try to fix Xsec in order to have mu_hat ~ 10 */ RooWorkspace w("w"); //gROOT->ProcessLine(".L retrieve_input_from_histo_NoSys.C+"); gROOT->ProcessLine(".L retrieve_input_from_histo.C+"); retrieve_input_from_histo(w); // Building the model ModelConfig mc("ModelConfig",&w); mc.SetPdf(*w.pdf("model")); mc.SetParametersOfInterest(*w.var("mu")); // Setting nuissance parameter mc.SetNuisanceParameters(*w.set("nuissance_parameter")); // need now to set the global observable mc.SetGlobalObservables(*w.set("g_observables")); mc.SetObservables(*w.set("observables")); // this is needed for the hypothesis tests mc.SetSnapshot(*w.var("mu")); // make data set with the number of observed events RooDataSet data("data","", *w.set("observables")); data.add(*w.set("observables")); // import data set in workspace and save it in a file w.import(data); // import model in the workspace w.import(mc); w.writeToFile("CountingModel.root", true); w.Print(); data.Print(); /* cout << w.var("S_i")->getValV() << endl;//<< " " << w.var("S_i_exp")->getValV() << endl; /////////////////////////////////////////////////////////////////////// ProfileLikelihoodCalculator pl(data,mc); pl.SetConfidenceLevel(0.95); LikelihoodInterval* interval = pl.GetInterval(); // find the iterval on the first Parameter of Interest RooRealVar* firstPOI = (RooRealVar*) mc.GetParametersOfInterest()->first(); double lowerLimit = interval->LowerLimit(*firstPOI); double upperLimit = interval->UpperLimit(*firstPOI); cout << "\n95% interval on " <<firstPOI->GetName()<<" is : ["<< lowerLimit << ", "<< upperLimit <<"] "<<endl; LikelihoodIntervalPlot * plot = new LikelihoodIntervalPlot(interval); // plot->SetRange(0,50); // possible eventually to change ranges //plot->SetNPoints(50); // do not use too many points, it could become very slow for some models plot->Draw(""); // use option TF1 if too slow (plot.Draw("tf1") */ ////////////////////////// hypo test // get the modelConfig (S+B) out of the file // and create the B model from the S+B model ModelConfig * sbModel = (ModelConfig*) mc.Clone(); sbModel->SetName("S+B Model"); RooRealVar* poi = (RooRealVar*) sbModel->GetParametersOfInterest()->first(); poi->setVal(1); // set POI snapshot in S+B model for expected significance sbModel->SetSnapshot(*poi); ModelConfig * bModel = (ModelConfig*) mc.Clone(); bModel->SetName("B Model"); RooRealVar* poi2 = (RooRealVar*) bModel->GetParametersOfInterest()->first(); poi2->setVal(0); bModel->SetSnapshot( *poi2 ); //------------------Limit calculation for N_th event expected = 10 AsymptoticCalculator ac(data, *bModel, *sbModel); //ac.SetOneSidedDiscovery(true); // for one-side discovery test // ac.SetOneSided(true); // for one-side tests (limits) ac.SetQTilde(true); ac.SetPrintLevel(2); // to suppress print level // create hypotest inverter // passing the desired calculator HypoTestInverter *calc = new HypoTestInverter(ac); // for asymptotic //HypoTestInverter calc(fc); // for frequentist calc->SetConfidenceLevel(0.90); //calc->UseCLs(false); calc->UseCLs(true); int npoints = 500; // number of points to scan //int npoints = 1000; // number of points to scan default 1000 // min and max (better to choose smaller intervals) double poimin = poi->getMin(); double poimax = poi->getMax(); //poimin = 0; poimax=10; std::cout << "Doing a fixed scan in interval : " << poimin << " , " << poimax << std::endl; calc->SetFixedScan(npoints,poimin,poimax); calc->SetVerbose(2); HypoTestInverterResult * r = calc->GetInterval(); double upperLimit = r->UpperLimit(); std::cout << "The computed Expected upper limit is: " << r->GetExpectedUpperLimit(0) << std::endl; //------------ Getting the interval as function of m --------------// /* ifstream in; in.open("integral_mass.dat"); vector <double> masses_v; vector <double> observed_v; vector <double> expected_v; vector <double> expected_gaud_v; vector <double> expected_S1_up_v; vector <double> expected_S1_dw_v; vector <double> expected_S2_up_v; vector <double> expected_S2_dw_v; double mass_itr =0.; double Nev_exp_th_itr =0.; double xsec_modifier = 10.; double N_tot_theory = w.var("N_tot_theory")->getValV(); while(mass_itr <1000.){ in >> mass_itr; in >> Nev_exp_th_itr; xsec_modifier = Nev_exp_th_itr * 225.009 * 34.; //225.009 livedays and 34 kg and 10^-40 cm2 Xsec. masses_v.push_back(mass_itr); observed_v.push_back( 1.e-40 * N_tot_theory / xsec_modifier * upperLimit ); expected_v.push_back( 1.e-40 * N_tot_theory / xsec_modifier * r->GetExpectedUpperLimit(0) ); expected_gaud_v.push_back(7e-38 * 1.37590955945e-05 / Nev_exp_th_itr ); expected_S1_up_v.push_back(1.e-40 * N_tot_theory / xsec_modifier * r->GetExpectedUpperLimit(1)); expected_S2_up_v.push_back(1.e-40 * N_tot_theory / xsec_modifier * r->GetExpectedUpperLimit(2)); expected_S2_dw_v.push_back(1.e-40 * N_tot_theory / xsec_modifier * r->GetExpectedUpperLimit(-2)); expected_S1_dw_v.push_back(1.e-40 * N_tot_theory / xsec_modifier * r->GetExpectedUpperLimit(-1)); cout << "Expected median limit for mass " << mass_itr << " GeV = " << 1.e-40 * N_tot_theory / xsec_modifier * r->GetExpectedUpperLimit(0) << " cm^2 " << endl; // observed_v.push_back( w.var("Xsec")->getValV() * w.var("K_m")->getValV()* upperLimit ); // expected_v.push_back( w.var("Xsec")->getValV() * w.var("K_m")->getValV()* r->GetExpectedUpperLimit(0) ); // expected_S1_up_v.push_back(w.var("Xsec")->getValV() * w.var("K_m")->getValV()* r->GetExpectedUpperLimit(1)); // expected_S2_up_v.push_back(w.var("Xsec")->getValV() * w.var("K_m")->getValV()* r->GetExpectedUpperLimit(2)); // expected_S2_dw_v.push_back(w.var("Xsec")->getValV() * w.var("K_m")->getValV()* r->GetExpectedUpperLimit(-2)); // expected_S1_dw_v.push_back(w.var("Xsec")->getValV() * w.var("K_m")->getValV()* r->GetExpectedUpperLimit(-1)); } in.close(); const int n = masses_v.size(); double xe[n]; double mA[n]; double observed[n]; double expected[n]; double expected_gaudenz[n]; double exSigma1_l[n]; double exSigma1_u[n]; double exSigma2_l[n]; double exSigma2_u[n]; for(int k=0; k< n; k++){ mA[k] = masses_v[k]; observed[k] = observed_v[k]; expected[k] = expected_v[k]; expected_gaudenz[k] = expected_gaud_v[k]; exSigma1_l[k] =expected_v[k] - expected_S1_dw_v[k] ; exSigma1_u[k] = expected_S1_up_v[k] - expected_v[k]; exSigma2_l[k] = expected_v[k] - expected_S2_dw_v[k]; exSigma2_u[k] = expected_S2_up_v[k] - expected_v[k] ; } TGraphErrors *obs_limits = new TGraphErrors(n, mA, observed); TGraphErrors *Exp_limits = new TGraphErrors(n, mA, expected ); TGraphAsymmErrors *Exp_limitsS1 = new TGraphAsymmErrors(n, mA, expected ,xe, xe, exSigma1_l, exSigma1_u ); TGraphAsymmErrors *Exp_limitsS2 = new TGraphAsymmErrors(n, mA, expected ,xe, xe, exSigma2_l, exSigma2_u); TGraphErrors *Exp_limits_gaudenz = new TGraphErrors( n, mA, expected_gaudenz); //double expected_xmass[15] = {8e-36,7e-37, 2e-37, 1e-37, 8e-38, 6e-38, 5.5e-38, 5e-38, 4.3e-38, 5e-38, 6e-38, 7e-38, 9e-38, 1.2e-37, 1.5e-37}; //double m_xmass[15] = { 20, 30., 40., 50., 60., 70., 80., 90., 100., 200., 300., 400, 500.,700., 1000.}; TGraphErrors *Exp_limits_xmass = new TGraphErrors(16); Exp_limits_xmass->SetPoint(0,20,8e-36); Exp_limits_xmass->SetPointError(0,0,0); Exp_limits_xmass->SetPoint(1,29.8071,7.162923e-37); Exp_limits_xmass->SetPointError(1,0,0); Exp_limits_xmass->SetPoint(2,39.90202,2.027528e-37); Exp_limits_xmass->SetPointError(2,0,0); Exp_limits_xmass->SetPoint(3,53.41583,9.91722e-38); Exp_limits_xmass->SetPointError(3,0,0); Exp_limits_xmass->SetPoint(4,62.16429,7.461589e-38); Exp_limits_xmass->SetPointError(4,0,0); Exp_limits_xmass->SetPoint(5,69.85718,6.3506e-38); Exp_limits_xmass->SetPointError(5,0,0); Exp_limits_xmass->SetPoint(6,83.21777,5.354015e-38); Exp_limits_xmass->SetPointError(6,0,0); Exp_limits_xmass->SetPoint(7,90,5e-38); Exp_limits_xmass->SetPointError(7,0,0); Exp_limits_xmass->SetPoint(8,105.0887,4.600252e-38); Exp_limits_xmass->SetPointError(8,0,0); Exp_limits_xmass->SetPoint(9,200,5e-38); Exp_limits_xmass->SetPointError(9,0,0); Exp_limits_xmass->SetPoint(10,300,6e-38); Exp_limits_xmass->SetPointError(10,0,0); Exp_limits_xmass->SetPoint(11,388.2045,7.252295e-38); Exp_limits_xmass->SetPointError(11,0,0); Exp_limits_xmass->SetPoint(12,590.8438,9.823615e-38); Exp_limits_xmass->SetPointError(12,0,0); Exp_limits_xmass->SetPoint(13,746.1269,1.210266e-37); Exp_limits_xmass->SetPointError(13,0,0); Exp_limits_xmass->SetPoint(14,1000,1.5e-37); Exp_limits_xmass->SetPointError(14,0,0); Exp_limits_xmass->SetPoint(15,4244.204,4.354065e-37); Exp_limits_xmass->SetPointError(15,0,0); TCanvas *c1 = new TCanvas("limits", "limit", 600, 600); Exp_limitsS1->SetFillColor(3); Exp_limitsS1->SetLineColor(3); Exp_limitsS1->SetMarkerColor(3); Exp_limitsS1->SetMarkerSize(0); Exp_limitsS2->SetFillColor(5); Exp_limitsS2->SetLineColor(5); Exp_limitsS2->SetMarkerColor(5); Exp_limitsS2->SetMarkerSize(0); obs_limits->SetFillColor(0); obs_limits->SetLineWidth(3); obs_limits->SetMarkerSize(0); Exp_limits->SetFillColor(0); Exp_limits->SetMarkerSize(0); Exp_limits->SetLineStyle(7); Exp_limits->SetLineWidth(3); Exp_limits_gaudenz->SetFillColor(0); Exp_limits_gaudenz->SetMarkerSize(0); Exp_limits_gaudenz->SetLineWidth(3); Exp_limits_gaudenz->SetLineColor(4); Exp_limits_xmass->SetFillColor(0); Exp_limits_xmass->SetMarkerSize(0); Exp_limits_xmass->SetLineWidth(3); Exp_limits_xmass->SetLineColor(2); //Exp_limitsS2->GetYaxis()->SetTitle("#sigma#timesBR( #phi #rightarrow #tau#tau ) [pb]"); Exp_limitsS2->GetYaxis()->SetTitle("#sigma"); Exp_limitsS2->GetXaxis()->SetTitle("M [GeV]"); Exp_limitsS2->GetXaxis()->SetLimits(9.,1000.); Exp_limitsS2->GetYaxis()->SetRangeUser(1E-38,1E-30); Exp_limits->GetXaxis()->SetLimits(9.,1000.); Exp_limits->GetYaxis()->SetRangeUser(1E-38,1E-30); Exp_limitsS2->Draw("Al3"); Exp_limitsS1->Draw("sameL3"); Exp_limits->Draw("PL"); Exp_limits_gaudenz->Draw("PC"); Exp_limits_xmass->Draw("PC"); //obs_limits->Draw("PL"); TLegend* lego = new TLegend(0.2,0.9,0.5,0.7); lego->SetTextSize(0.033); lego->SetFillColor(0); lego->SetBorderSize(0); lego->AddEntry(obs_limits,"Observed 90\% CLs limit"); lego->AddEntry(Exp_limits_gaudenz, "Expected 90\% Gaudenz"); lego->AddEntry(Exp_limits_xmass, "Expected 90\% XMASS"); lego->AddEntry(Exp_limits, "Expected 90\% CLs limit"); lego->AddEntry(Exp_limitsS1,"1 #sigma","f"); lego->AddEntry(Exp_limitsS2,"2 #sigma","f"); lego->Draw(); gPad->SetLogy(); gPad->SetLogx(); gPad->RedrawAxis("g"); myText(0.4,0.86,2,"Test"); */ // now use the profile inspector ProfileInspector p; TList* list = p.GetListOfProfilePlots(data,&mc); // now make plots TCanvas* c1 = new TCanvas("c1","ProfileInspectorDemo",800,200); if(list->GetSize()>4){ double n = list->GetSize(); int nx = (int)sqrt(n) ; int ny = TMath::CeilNint(n/nx); nx = TMath::CeilNint( sqrt(n) ); c1->Divide(ny,nx); } else c1->Divide(list->GetSize()); for(int i=0; i<list->GetSize(); ++i){ c1->cd(i+1); list->At(i)->Draw("al"); } cout << endl; /* // plot now the result of the scan HypoTestInverterPlot *plot = new HypoTestInverterPlot("HTI_Result_Plot","HypoTest Scan Result",r); // plot in a new canvas with style TCanvas * c1 = new TCanvas("HypoTestInverter Scan"); c1->SetLogy(false); plot->Draw("2CL"); // plot also CLb and CLs+b //plot->Draw("OBS"); // plot only observed p-value */ // plot also in a new canvas the test statistics distributions // plot test statistics distributions for the two hypothesis /* // when distribution is generated (case of FrequentistCalculators) const int n = r->ArraySize(); if (n> 0 && r->GetResult(0)->GetNullDistribution() ) { TCanvas * c2 = new TCanvas("Test Statistic Distributions","",2); if (n > 1) { int ny = TMath::CeilNint( sqrt(n) ); int nx = TMath::CeilNint(double(n)/ny); c2->Divide( nx,ny); } for (int i=0; i<n; i++) { if (n > 1) c2->cd(i+1); SamplingDistPlot * pl = plot->MakeTestStatPlot(i); pl->SetLogYaxis(true); pl->Draw(); } } */ }
void significance(RooWorkspace& w ) { ModelConfig* mc = (ModelConfig*)w.obj("mc"); RooDataSet* data = (RooDataSet*)w.data("data"); //data->Print(); // define the S+B snapshot (this is used for computing the expected significance) ModelConfig* sbModel = mc->Clone(); sbModel->SetName("S+B Model"); RooRealVar* poi = (RooRealVar*) sbModel->GetParametersOfInterest()->first(); poi->setVal(50); sbModel->SetSnapshot(*poi); ModelConfig * bModel = (ModelConfig*) sbModel->Clone(); bModel->SetName("B model"); poi->setVal(0); bModel->SetSnapshot(*poi); vector<double> masses; vector<double> p0values; vector<double> p0valuesExpected; vector<double> sigvalues; double massMin = 200; double massMax = 2500; int nbins = 100; // loop on the mass values for ( double mass=massMin; mass<=massMax; mass += (massMax-massMin)/nbins ) { w.var("mass")->setVal( mass ); // create the AsymptoticCalculator from data,alt model, null model AsymptoticCalculator * ac = new AsymptoticCalculator(*data, *sbModel, *bModel); ac->SetOneSidedDiscovery(true); // for one-side discovery test AsymptoticCalculator::SetPrintLevel(-1); // run the calculator HypoTestResult* asymCalcResult = ac->GetHypoTest(); asymCalcResult->Print(); double pvalue = asymCalcResult->NullPValue(); double sigvalue = asymCalcResult->Significance(); double expectedP0 = AsymptoticCalculator::GetExpectedPValues(asymCalcResult->NullPValue(),asymCalcResult->AlternatePValue(), 0, false); masses.push_back(mass); p0values.push_back(pvalue); p0valuesExpected.push_back(expectedP0); sigvalues.push_back(sigvalue); std::cout << "** Mass = " << mass << " p0-value = " << expectedP0 << " p-value = " << pvalue << " significance = " << sigvalue << std::endl; } TGraph* graph1 = new TGraph(masses.size(),&masses[0],&p0values[0]); TGraph* graph2 = new TGraph(masses.size(),&masses[0],&p0valuesExpected[0]); TGraph* graph3 = new TGraph(masses.size(),&masses[0],&sigvalues[0]); TCanvas* c2 = new TCanvas("c2","Significance", 900, 700); c2->Divide(1,2); c2->cd(1); graph1->SetMarkerStyle(10); //graph1->Draw("APC"); graph1->Draw("AC"); graph2->SetLineStyle(2); graph2->Draw("C"); graph1->GetXaxis()->SetTitle("Mass [GeV]"); graph1->GetYaxis()->SetTitle("p0 value"); graph1->SetTitle("P-value vs Mass"); graph1->SetMinimum(graph2->GetMinimum()); graph1->SetLineColor(kBlue); graph2->SetLineColor(kRed); gPad->SetLogy(true); c2->cd(2); graph3->SetMarkerStyle(10); graph3->Draw("AC"); graph3->SetLineStyle(1); graph3->SetLineColor(kRed); graph3->GetXaxis()->SetTitle("Mass [GeV]"); graph3->GetYaxis()->SetTitle("Significance"); graph3->SetTitle("Significance vs Mass"); gPad->SetLogy(false); c2->SaveAs("significance.pdf"); c2->SaveAs("significance.png"); }