63 using namespace RooFit;
64 using namespace RooStats;
66 struct HypoTestOptions {
68 bool noSystematics =
false;
69 double nToysRatio = 4;
72 bool generateBinned =
false;
73 bool useProof =
false;
74 bool enableDetailedOutput =
false;
77 HypoTestOptions optHT;
79 void StandardHypoTestDemo(
const char *infile =
"",
const char *workspaceName =
"combined",
80 const char *modelSBName =
"ModelConfig",
const char *modelBName =
"",
81 const char *dataName =
"obsData",
int calcType = 0,
83 int ntoys = 5000,
bool useNC =
false,
const char *nuisPriorName = 0)
86 bool noSystematics = optHT.noSystematics;
87 double nToysRatio = optHT.nToysRatio;
88 double poiValue = optHT.poiValue;
89 int printLevel = optHT.printLevel;
90 bool generateBinned = optHT.generateBinned;
91 bool useProof = optHT.useProof;
92 bool enableDetOutput = optHT.enableDetailedOutput;
124 SimpleLikelihoodRatioTestStat::SetAlwaysReuseNLL(
true);
125 ProfileLikelihoodTestStat::SetAlwaysReuseNLL(
true);
126 RatioOfProfiledLikelihoodsTestStat::SetAlwaysReuseNLL(
true);
140 const char *filename =
"";
141 if (!strcmp(infile,
"")) {
142 filename =
"results/example_combined_GaussExample_model.root";
143 bool fileExist = !gSystem->AccessPathName(filename);
147 cout <<
"HistFactory file cannot be generated on Windows - exit" << endl;
151 cout <<
"will run standard hist2workspace example" << endl;
152 gROOT->ProcessLine(
".! prepareHistFactory .");
153 gROOT->ProcessLine(
".! hist2workspace config/example.xml");
154 cout <<
"\n\n---------------------" << endl;
155 cout <<
"Done creating example input" << endl;
156 cout <<
"---------------------\n\n" << endl;
163 TFile *file = TFile::Open(filename);
167 cout <<
"StandardRooStatsDemoMacro: Input file " << filename <<
" is not found" << endl;
176 RooWorkspace *w = (RooWorkspace *)file->Get(workspaceName);
178 cout <<
"workspace not found" << endl;
184 ModelConfig *sbModel = (ModelConfig *)w->obj(modelSBName);
187 RooAbsData *data = w->data(dataName);
190 if (!data || !sbModel) {
192 cout <<
"data or ModelConfig was not found" << endl;
196 ModelConfig *bModel = (ModelConfig *)w->obj(modelBName);
201 const RooArgSet *nuisPar = sbModel->GetNuisanceParameters();
202 if (nuisPar && nuisPar->getSize() > 0) {
203 std::cout <<
"StandardHypoTestInvDemo"
204 <<
" - Switch off all systematics by setting them constant to their initial values" << std::endl;
205 RooStats::SetAllConstant(*nuisPar);
208 const RooArgSet *bnuisPar = bModel->GetNuisanceParameters();
210 RooStats::SetAllConstant(*bnuisPar);
215 Info(
"StandardHypoTestInvDemo",
"The background model %s does not exist", modelBName);
216 Info(
"StandardHypoTestInvDemo",
"Copy it from ModelConfig %s and set POI to zero", modelSBName);
217 bModel = (ModelConfig *)sbModel->Clone();
218 bModel->SetName(TString(modelSBName) + TString(
"B_only"));
219 RooRealVar *var =
dynamic_cast<RooRealVar *
>(bModel->GetParametersOfInterest()->first());
222 double oldval = var->getVal();
225 bModel->SetSnapshot(RooArgSet(*var));
229 if (!sbModel->GetSnapshot() || poiValue > 0) {
230 Info(
"StandardHypoTestDemo",
"Model %s has no snapshot - make one using model poi", modelSBName);
231 RooRealVar *var =
dynamic_cast<RooRealVar *
>(sbModel->GetParametersOfInterest()->first());
234 double oldval = var->getVal();
236 var->setVal(poiValue);
238 sbModel->SetSnapshot(RooArgSet(*var));
245 SimpleLikelihoodRatioTestStat *slrts =
new SimpleLikelihoodRatioTestStat(*bModel->GetPdf(), *sbModel->GetPdf());
247 RooArgSet nullParams(*bModel->GetSnapshot());
248 if (bModel->GetNuisanceParameters())
249 nullParams.add(*bModel->GetNuisanceParameters());
251 slrts->SetNullParameters(nullParams);
252 RooArgSet altParams(*sbModel->GetSnapshot());
253 if (sbModel->GetNuisanceParameters())
254 altParams.add(*sbModel->GetNuisanceParameters());
255 slrts->SetAltParameters(altParams);
257 ProfileLikelihoodTestStat *profll =
new ProfileLikelihoodTestStat(*bModel->GetPdf());
259 RatioOfProfiledLikelihoodsTestStat *ropl =
260 new RatioOfProfiledLikelihoodsTestStat(*bModel->GetPdf(), *sbModel->GetPdf(), sbModel->GetSnapshot());
261 ropl->SetSubtractMLE(
false);
263 if (testStatType == 3)
264 profll->SetOneSidedDiscovery(1);
265 profll->SetPrintLevel(printLevel);
267 if (enableDetOutput) {
268 slrts->EnableDetailedOutput();
269 profll->EnableDetailedOutput();
270 ropl->EnableDetailedOutput();
277 AsymptoticCalculator::SetPrintLevel(printLevel);
279 HypoTestCalculatorGeneric *hypoCalc = 0;
282 hypoCalc =
new FrequentistCalculator(*data, *sbModel, *bModel);
283 else if (calcType == 1)
284 hypoCalc =
new HybridCalculator(*data, *sbModel, *bModel);
285 else if (calcType == 2)
286 hypoCalc =
new AsymptoticCalculator(*data, *sbModel, *bModel);
289 ((FrequentistCalculator *)hypoCalc)->SetToys(ntoys, ntoys / nToysRatio);
291 ((FrequentistCalculator *)hypoCalc)->StoreFitInfo(
true);
294 ((HybridCalculator *)hypoCalc)->SetToys(ntoys, ntoys / nToysRatio);
298 if (testStatType == 3)
299 ((AsymptoticCalculator *)hypoCalc)->SetOneSidedDiscovery(
true);
300 if (testStatType != 2 && testStatType != 3)
301 Warning(
"StandardHypoTestDemo",
302 "Only the PL test statistic can be used with AsymptoticCalculator - use by default a two-sided PL");
306 if (calcType == 1 && (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters())) {
307 RooAbsPdf *nuisPdf = 0;
309 nuisPdf = w->pdf(nuisPriorName);
312 Info(
"StandardHypoTestDemo",
313 "No nuisance pdf given for the HybridCalculator - try to deduce pdf from the model");
314 if (bModel->GetPdf() && bModel->GetObservables())
315 nuisPdf = RooStats::MakeNuisancePdf(*bModel,
"nuisancePdf_bmodel");
317 nuisPdf = RooStats::MakeNuisancePdf(*sbModel,
"nuisancePdf_sbmodel");
320 if (bModel->GetPriorPdf()) {
321 nuisPdf = bModel->GetPriorPdf();
322 Info(
"StandardHypoTestDemo",
323 "No nuisance pdf given - try to use %s that is defined as a prior pdf in the B model",
326 Error(
"StandardHypoTestDemo",
"Cannot run Hybrid calculator because no prior on the nuisance parameter is "
327 "specified or can be derived");
332 Info(
"StandardHypoTestDemo",
"Using as nuisance Pdf ... ");
335 const RooArgSet *nuisParams =
336 (bModel->GetNuisanceParameters()) ? bModel->GetNuisanceParameters() : sbModel->GetNuisanceParameters();
337 RooArgSet *np = nuisPdf->getObservables(*nuisParams);
338 if (np->getSize() == 0) {
339 Warning(
"StandardHypoTestDemo",
340 "Prior nuisance does not depend on nuisance parameters. They will be smeared in their full range");
344 ((HybridCalculator *)hypoCalc)->ForcePriorNuisanceAlt(*nuisPdf);
345 ((HybridCalculator *)hypoCalc)->ForcePriorNuisanceNull(*nuisPdf);
351 ToyMCSampler *sampler = (ToyMCSampler *)hypoCalc->GetTestStatSampler();
353 if (sampler && (calcType == 0 || calcType == 1)) {
356 if (sbModel->GetPdf()->canBeExtended()) {
358 Warning(
"StandardHypoTestDemo",
"Pdf is extended: but number counting flag is set: ignore it ");
362 int nEvents = data->numEntries();
363 Info(
"StandardHypoTestDemo",
364 "Pdf is not extended: number of events to generate taken from observed data set is %d", nEvents);
365 sampler->SetNEventsPerToy(nEvents);
367 Info(
"StandardHypoTestDemo",
"using a number counting pdf");
368 sampler->SetNEventsPerToy(1);
372 if (data->isWeighted() && !generateBinned) {
373 Info(
"StandardHypoTestDemo",
"Data set is weighted, nentries = %d and sum of weights = %8.1f but toy "
374 "generation is unbinned - it would be faster to set generateBinned to true\n",
375 data->numEntries(), data->sumEntries());
378 sampler->SetGenerateBinned(generateBinned);
382 ProofConfig pc(*w, 0,
"", kFALSE);
383 sampler->SetProofConfig(&pc);
387 if (testStatType == 0)
388 sampler->SetTestStatistic(slrts);
389 if (testStatType == 1)
390 sampler->SetTestStatistic(ropl);
391 if (testStatType == 2 || testStatType == 3)
392 sampler->SetTestStatistic(profll);
395 HypoTestResult *htr = hypoCalc->GetHypoTest();
396 htr->SetPValueIsRightTail(
true);
397 htr->SetBackgroundAsAlt(
false);
406 HypoTestPlot *plot =
new HypoTestPlot(*htr, 100);
407 plot->SetLogYaxis(
true);
410 std::cout <<
"Asymptotic results " << std::endl;
417 SamplingDistribution *altDist = htr->GetAltDistribution();
418 HypoTestResult htExp(
"Expected Result");
423 for (
int i = 0; i < 5; ++i) {
425 p[i] = ROOT::Math::normal_cdf(sig, 1);
427 std::vector<double> values = altDist->GetSamplingDistribution();
428 TMath::Quantiles(values.size(), 5, &values[0], q, p,
false);
430 for (
int i = 0; i < 5; ++i) {
431 htExp.SetTestStatisticData(q[i]);
433 std::cout <<
" Expected p -value and significance at " << sig <<
" sigma = " << htExp.NullPValue()
434 <<
" significance " << htExp.Significance() <<
" sigma " << std::endl;
438 for (
int i = 0; i < 5; ++i) {
441 double pval = AsymptoticCalculator::GetExpectedPValues(htr->NullPValue(), htr->AlternatePValue(), -sig,
false);
442 std::cout <<
" Expected p -value and significance at " << sig <<
" sigma = " << pval <<
" significance "
443 << ROOT::Math::normal_quantile_c(pval, 1) <<
" sigma " << std::endl;
448 bool writeResult = (calcType != 2);
450 if (enableDetOutput) {
452 Info(
"StandardHypoTestDemo",
"Detailed output will be written in output result file");
455 if (htr != NULL && writeResult) {
458 const char *calcTypeName = (calcType == 0) ?
"Freq" : (calcType == 1) ?
"Hybr" :
"Asym";
459 TString resultFileName = TString::Format(
"%s_HypoTest_ts%d_", calcTypeName, testStatType);
462 TString name = infile;
463 name.Replace(0, name.Last(
'/') + 1,
"");
464 resultFileName += name;
466 TFile *fileOut =
new TFile(resultFileName,
"RECREATE");
468 Info(
"StandardHypoTestDemo",
"HypoTestResult has been written in the file %s", resultFileName.Data());