00001
00002
00003
00004 #include "../interface/Combine.h"
00005 #include <cstring>
00006 #include <cerrno>
00007 #include <iostream>
00008 #include <cstdlib>
00009 #include <cmath>
00010 #include <vector>
00011 #include <string>
00012 #include <stdexcept>
00013 #include <algorithm>
00014 #include <unistd.h>
00015 #include <errno.h>
00016
00017 #include <TCanvas.h>
00018 #include <TFile.h>
00019 #include <TGraphErrors.h>
00020 #include <TIterator.h>
00021 #include <TLine.h>
00022 #include <TMath.h>
00023 #include <TString.h>
00024 #include <TSystem.h>
00025 #include <TStopwatch.h>
00026 #include <TTree.h>
00027
00028 #include <RooAbsData.h>
00029 #include <RooAbsPdf.h>
00030 #include <RooArgSet.h>
00031 #include <RooCustomizer.h>
00032 #include <RooDataHist.h>
00033 #include <RooDataSet.h>
00034 #include <RooFitResult.h>
00035 #include <RooMsgService.h>
00036 #include <RooPlot.h>
00037 #include <RooRandom.h>
00038 #include <RooRealVar.h>
00039 #include <RooUniform.h>
00040 #include <RooWorkspace.h>
00041
00042 #include <RooStats/HLFactory.h>
00043 #include <RooStats/RooStatsUtils.h>
00044 #include <RooStats/ModelConfig.h>
00045
00046 #include <boost/filesystem.hpp>
00047 #include <boost/program_options.hpp>
00048
00049
00050 #include "../interface/LimitAlgo.h"
00051 #include "../interface/utils.h"
00052 #include "../interface/CloseCoutSentry.h"
00053 #include "../interface/RooSimultaneousOpt.h"
00054 #include "../interface/ToyMCSamplerOpt.h"
00055 #include "../interface/AsimovUtils.h"
00056
00057 using namespace RooStats;
00058 using namespace RooFit;
00059
00060 LimitAlgo * algo, * hintAlgo;
00061
00062 Float_t t_cpu_, t_real_;
00063 Float_t g_quantileExpected_ = -1.0;
00064 TDirectory *outputFile = 0;
00065 TDirectory *writeToysHere = 0;
00066 TDirectory *readToysFromHere = 0;
00067 int verbose = 1;
00068 bool withSystematics = 1;
00069 bool doSignificance_ = 0;
00070 bool lowerLimit_ = 0;
00071 float cl = 0.95;
00072 TTree *Combine::tree_ = 0;
00073
00074
00075 Combine::Combine() :
00076 statOptions_("Common statistics options"),
00077 ioOptions_("Common input-output options"),
00078 miscOptions_("Common miscellaneous options"),
00079 rMin_(std::numeric_limits<float>::quiet_NaN()),
00080 rMax_(std::numeric_limits<float>::quiet_NaN()) {
00081 namespace po = boost::program_options;
00082 statOptions_.add_options()
00083 ("systematics,S", po::value<bool>(&withSystematics)->default_value(true), "Add systematic uncertainties")
00084 ("cl,C", po::value<float>(&cl)->default_value(0.95), "Confidence Level")
00085 ("rMin", po::value<float>(&rMin_), "Override minimum value for signal strength")
00086 ("rMax", po::value<float>(&rMax_), "Override maximum value for signal strength")
00087 ("prior", po::value<std::string>(&prior_)->default_value("flat"), "Prior to use, for methods that require it and if it's not already in the input file: 'flat' (default), '1/sqrt(r)'")
00088 ("significance", "Compute significance instead of upper limit (works only for some methods)")
00089 ("lowerLimit", "Compute the lower limit instead of the upper limit (works only for some methods)")
00090 ("hintStatOnly", "Ignore systematics when computing the hint")
00091 ("toysNoSystematics", "Generate all toys with the central value of the nuisance parameters, without fluctuating them")
00092 ("toysFrequentist", "Generate all toys in the frequentist way. Note that this affects the toys generated by option '-t' that happen in the main loop, not the ones within the Hybrid(New) algorithm.")
00093 ("expectSignal", po::value<float>(&expectSignal_)->default_value(0.), "If set to non-zero, generate *signal* toys instead of background ones, with the specified signal strength.")
00094 ("unbinned,U", "Generate unbinned datasets instead of binned ones (works only for extended pdfs)")
00095 ("generateBinnedWorkaround", "Make binned datasets generating unbinned ones and then binnning them. Workaround for a bug in RooFit.")
00096 ;
00097 ioOptions_.add_options()
00098 ("saveWorkspace", "Save workspace to output root file")
00099 ("workspaceName,w", po::value<std::string>(&workspaceName_)->default_value("w"), "Workspace name, when reading it from or writing it to a rootfile.")
00100 ("modelConfigName", po::value<std::string>(&modelConfigName_)->default_value("ModelConfig"), "ModelConfig name, when reading it from or writing it to a rootfile.")
00101 ("modelConfigNameB", po::value<std::string>(&modelConfigNameB_)->default_value("%s_bonly"), "Name of the ModelConfig for b-only hypothesis.\n"
00102 "If not present, it will be made from the singal model taking zero signal strength.\n"
00103 "A '%s' in the name will be replaced with the modelConfigName.")
00104 ("validateModel,V", "Perform some sanity checks on the model and abort if they fail.")
00105 ("saveToys", "Save results of toy MC in output file")
00106 ;
00107 miscOptions_.add_options()
00108 ("newGenerator", po::value<bool>(&newGen_)->default_value(true), "Use new generator code for toys, fixes all issues with binned and mixed generation (equivalent of --newToyMC but affects the top-level toys from option '-t' instead of the ones within the HybridNew)")
00109 ("optimizeSimPdf", po::value<bool>(&optSimPdf_)->default_value(true), "Turn on special optimizations of RooSimultaneous. On by default, you can turn it off if it doesn't work for your workspace.")
00110 ("rebuildSimPdf", po::value<bool>(&rebuildSimPdf_)->default_value(false), "Rebuild simultaneous pdf from scratch to make sure constraints are correct (not needed in CMS workspaces)")
00111 ("compile", "Compile expressions instead of interpreting them")
00112 ("tempDir", po::value<bool>(&makeTempDir_)->default_value(false), "Run the program from a temporary directory (automatically on for text datacards or if 'compile' is activated)")
00113 ("guessGenMode", "Guess if to generate binned or unbinned based on dataset");
00114 ;
00115 }
00116
00117 void Combine::applyOptions(const boost::program_options::variables_map &vm) {
00118 if(withSystematics) {
00119 std::cout << ">>> including systematics" << std::endl;
00120 } else {
00121 std::cout << ">>> no systematics included" << std::endl;
00122 }
00123 unbinned_ = vm.count("unbinned");
00124 generateBinnedWorkaround_ = vm.count("generateBinnedWorkaround");
00125 if (unbinned_ && generateBinnedWorkaround_) throw std::logic_error("You can't set generateBinnedWorkaround and unbinned options at the same time");
00126 guessGenMode_ = vm.count("guessGenMode");
00127 compiledExpr_ = vm.count("compile"); if (compiledExpr_) makeTempDir_ = true;
00128 doSignificance_ = vm.count("significance");
00129 lowerLimit_ = vm.count("lowerLimit");
00130 hintUsesStatOnly_ = vm.count("hintStatOnly");
00131 saveWorkspace_ = vm.count("saveWorkspace");
00132 toysNoSystematics_ = vm.count("toysNoSystematics");
00133 toysFrequentist_ = vm.count("toysFrequentist");
00134 if (toysNoSystematics_ && toysFrequentist_) throw std::logic_error("You can't set toysNoSystematics and toysFrequentist options at the same time");
00135 if (modelConfigNameB_.find("%s") != std::string::npos) {
00136 char modelBName[1024];
00137 sprintf(modelBName, modelConfigNameB_.c_str(), modelConfigName_.c_str());
00138 modelConfigNameB_ = modelBName;
00139 }
00140 mass_ = vm["mass"].as<float>();
00141 saveToys_ = vm.count("saveToys");
00142 validateModel_ = vm.count("validateModel");
00143 }
00144
00145 bool Combine::mklimit(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr) {
00146 TStopwatch timer;
00147 bool ret = false;
00148 try {
00149 double hint = 0, hintErr = 0; bool hashint = false;
00150 if (hintAlgo) {
00151 if (hintUsesStatOnly_ && withSystematics) {
00152 withSystematics = false;
00153 hashint = hintAlgo->run(w, mc_s, mc_b, data, hint, hintErr, 0);
00154 withSystematics = true;
00155 } else {
00156 hashint = hintAlgo->run(w, mc_s, mc_b, data, hint, hintErr, 0);
00157 }
00158 }
00159 limitErr = 0;
00160 ret = algo->run(w, mc_s, mc_b, data, limit, limitErr, (hashint ? &hint : 0));
00161 } catch (std::exception &ex) {
00162 std::cerr << "Caught exception " << ex.what() << std::endl;
00163 return false;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172 timer.Stop(); t_cpu_ = timer.CpuTime()/60.; t_real_ = timer.RealTime()/60.;
00173 printf("Done in %.2f min (cpu), %.2f min (real)\n", t_cpu_, t_real_);
00174 return ret;
00175 }
00176
00177 namespace {
00178 struct ToCleanUp {
00179 TFile *tfile; std::string file, path;
00180 ToCleanUp() : tfile(0), file(""), path("") {}
00181 ~ToCleanUp() {
00182 if (tfile) { tfile->Close(); delete tfile; }
00183 if (!file.empty()) {
00184 if (unlink(file.c_str()) == -1) std::cerr << "Failed to delete temporary file " << file << ": " << strerror(errno) << std::endl;
00185 }
00186 if (!path.empty()) { boost::filesystem::remove_all(path); }
00187 }
00188 };
00189 }
00190 void Combine::run(TString hlfFile, const std::string &dataset, double &limit, double &limitErr, int &iToy, TTree *tree, int nToys) {
00191 ToCleanUp garbageCollect;
00192
00193 TString tmpDir = "", tmpFile = "", pwd(gSystem->pwd());
00194 if (makeTempDir_) {
00195 tmpDir = "roostats-XXXXXX"; tmpFile = "model";
00196 mkdtemp(const_cast<char *>(tmpDir.Data()));
00197 gSystem->cd(tmpDir.Data());
00198 garbageCollect.path = tmpDir.Data();
00199 } else if (!hlfFile.EndsWith(".hlf") && !hlfFile.EndsWith(".root")) {
00200 tmpFile = "roostats-XXXXXX";
00201 mktemp(const_cast<char *>(tmpFile.Data()));
00202 }
00203
00204 bool isTextDatacard = false, isBinary = false;
00205 TString fileToLoad = (hlfFile[0] == '/' ? hlfFile : pwd+"/"+hlfFile);
00206 if (!boost::filesystem::exists(fileToLoad.Data())) throw std::invalid_argument(("File "+fileToLoad+" does not exist").Data());
00207 if (hlfFile.EndsWith(".hlf") ) {
00208
00209 } else if (hlfFile.EndsWith(".root")) {
00210 isBinary = true;
00211 } else {
00212 TString txtFile = fileToLoad.Data();
00213 TString options = TString::Format(" -m %f -D %s", mass_, dataset.c_str());
00214 if (!withSystematics) options += " --stat ";
00215 if (compiledExpr_) options += " --compiled ";
00216 if (verbose > 1) options += TString::Format(" --verbose %d", verbose-1);
00217
00218
00219
00220
00221 int status = gSystem->Exec("text2workspace.py "+options+" '"+txtFile+"' -b -o "+tmpFile+".root");
00222 isBinary = true; fileToLoad = tmpFile+".root";
00223 if (status != 0 || !boost::filesystem::exists(fileToLoad.Data())) {
00224 throw std::invalid_argument("Failed to convert the input datacard from LandS to RooStats format. The lines above probably contain more information about the error.");
00225 }
00226 garbageCollect.file = fileToLoad;
00227 }
00228
00229 if (getenv("CMSSW_BASE")) {
00230 gSystem->AddIncludePath(TString::Format(" -I%s/src ", getenv("CMSSW_BASE")));
00231 if (verbose > 3) std::cout << "Adding " << getenv("CMSSW_BASE") << "/src to include path" << std::endl;
00232 }
00233 if (getenv("ROOFITSYS")) {
00234 gSystem->AddIncludePath(TString::Format(" -I%s/include ", getenv("ROOFITSYS")));
00235 if (verbose > 3) std::cout << "Adding " << getenv("ROOFITSYS") << "/include to include path" << std::endl;
00236 }
00237
00238 if (verbose <= 2) RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
00239
00240 RooWorkspace *w = 0; RooStats::ModelConfig *mc = 0, *mc_bonly = 0;
00241 std::auto_ptr<RooStats::HLFactory> hlf(0);
00242 if (isBinary) {
00243 TFile *fIn = TFile::Open(fileToLoad);
00244 garbageCollect.tfile = fIn;
00245
00246 w = dynamic_cast<RooWorkspace *>(fIn->Get(workspaceName_.c_str()));
00247 if (w == 0) {
00248 std::cerr << "Could not find workspace '" << workspaceName_ << "' in file " << fileToLoad << std::endl; fIn->ls();
00249 throw std::invalid_argument("Missing Workspace");
00250 }
00251 if (verbose > 3) { std::cout << "Input workspace '" << workspaceName_ << "': \n"; w->Print("V"); }
00252 RooRealVar *MH = w->var("MH");
00253 if (MH!=0) {
00254 if (verbose > 2) std::cerr << "Setting variable 'MH' in workspace to the higgs mass " << mass_ << std::endl;
00255 MH->setVal(mass_);
00256 }
00257 mc = dynamic_cast<RooStats::ModelConfig *>(w->genobj(modelConfigName_.c_str()));
00258 mc_bonly = dynamic_cast<RooStats::ModelConfig *>(w->genobj(modelConfigNameB_.c_str()));
00259 if (mc == 0) {
00260 std::cerr << "Could not find ModelConfig '" << modelConfigName_ << "' in workspace '" << workspaceName_ << "' in file " << fileToLoad << std::endl;
00261 throw std::invalid_argument("Missing ModelConfig");
00262 } else if (verbose > 3) { std::cout << "Workspace has a ModelConfig for signal called '" << modelConfigName_ << "', with contents:\n"; mc->Print("V"); }
00263 if (verbose > 3) { std::cout << "Input ModelConfig '" << modelConfigName_ << "': \n"; mc->Print("V"); }
00264 const RooArgSet *POI = mc->GetParametersOfInterest();
00265 if (POI == 0 || POI->getSize() == 0) throw std::invalid_argument("ModelConfig '"+modelConfigName_+"' does not define parameters of interest.");
00266 if (POI->getSize() > 1) std::cerr << "ModelConfig '" << modelConfigName_ << "' defines more than one parameter of interest. This is not supported in some statistical methods." << std::endl;
00267 if (mc->GetObservables() == 0) throw std::invalid_argument("ModelConfig '"+modelConfigName_+"' does not define observables.");
00268 if (mc->GetPdf() == 0) throw std::invalid_argument("ModelConfig '"+modelConfigName_+"' does not define a pdf.");
00269 if (rebuildSimPdf_ && typeid(*mc->GetPdf()) == typeid(RooSimultaneous)) {
00270 RooSimultaneous *newpdf = utils::rebuildSimPdf(*mc->GetObservables(), dynamic_cast<RooSimultaneous*>(mc->GetPdf()));
00271 w->import(*newpdf);
00272 mc->SetPdf(*newpdf);
00273 }
00274 if (optSimPdf_ && typeid(*mc->GetPdf()) == typeid(RooSimultaneous)) {
00275 RooSimultaneousOpt *optpdf = new RooSimultaneousOpt(static_cast<RooSimultaneous&>(*mc->GetPdf()), TString(mc->GetPdf()->GetName())+"_opt");
00276 w->import(*optpdf);
00277 mc->SetPdf(*optpdf);
00278 }
00279 if (mc_bonly == 0) {
00280 std::cerr << "Missing background ModelConfig '" << modelConfigNameB_ << "' in workspace '" << workspaceName_ << "' in file " << fileToLoad << std::endl;
00281 std::cerr << "Will make one from the signal ModelConfig '" << modelConfigName_ << "' setting signal strenth '" << POI->first()->GetName() << "' to zero" << std::endl;
00282 w->factory("_zero_[0]");
00283 RooCustomizer make_model_s(*mc->GetPdf(),"_model_bonly_");
00284 make_model_s.replaceArg(*POI->first(), *w->var("_zero_"));
00285 RooAbsPdf *model_b = dynamic_cast<RooAbsPdf *>(make_model_s.build());
00286 model_b->SetName("_model_bonly_");
00287 w->import(*model_b);
00288 mc_bonly = new RooStats::ModelConfig(*mc);
00289 mc_bonly->SetPdf(*model_b);
00290 }
00291 } else {
00292 hlf.reset(new RooStats::HLFactory("factory", fileToLoad));
00293 w = hlf->GetWs();
00294 if (w == 0) {
00295 std::cerr << "Could not read HLF from file " << (hlfFile[0] == '/' ? hlfFile : pwd+"/"+hlfFile) << std::endl;
00296 return;
00297 }
00298 RooRealVar *MH = w->var("MH");
00299 if (MH==0) {
00300 std::cerr << "Could not find MH var in workspace '" << workspaceName_ << "' in file " << fileToLoad << std::endl;
00301 throw std::invalid_argument("Missing MH");
00302 }
00303 MH->setVal(mass_);
00304 if (w->set("observables") == 0) throw std::invalid_argument("The model must define a RooArgSet 'observables'");
00305 if (w->set("POI") == 0) throw std::invalid_argument("The model must define a RooArgSet 'POI' for the parameters of interest");
00306 if (w->pdf("model_b") == 0) throw std::invalid_argument("The model must define a RooAbsPdf 'model_b'");
00307 if (w->pdf("model_s") == 0) throw std::invalid_argument("The model must define a RooAbsPdf 'model_s'");
00308
00309
00310 mc = new RooStats::ModelConfig(modelConfigName_.c_str(),"signal",w);
00311 mc->SetPdf(*w->pdf("model_s"));
00312 mc->SetObservables(*w->set("observables"));
00313 mc->SetParametersOfInterest(*w->set("POI"));
00314 if (w->set("nuisances")) mc->SetNuisanceParameters(*w->set("nuisances"));
00315 if (w->set("globalObservables")) mc->SetGlobalObservables(*w->set("globalObservables"));
00316 if (w->pdf("prior")) mc->SetNuisanceParameters(*w->pdf("prior"));
00317 w->import(*mc, modelConfigName_.c_str());
00318
00319 mc_bonly = new RooStats::ModelConfig(modelConfigNameB_.c_str(),"background",w);
00320 mc_bonly->SetPdf(*w->pdf("model_b"));
00321 mc_bonly->SetObservables(*w->set("observables"));
00322 mc_bonly->SetParametersOfInterest(*w->set("POI"));
00323 if (w->set("nuisances")) mc_bonly->SetNuisanceParameters(*w->set("nuisances"));
00324 if (w->set("globalObservables")) mc_bonly->SetGlobalObservables(*w->set("globalObservables"));
00325 if (w->pdf("prior")) mc_bonly->SetNuisanceParameters(*w->pdf("prior"));
00326 w->import(*mc_bonly, modelConfigNameB_.c_str());
00327 }
00328 gSystem->cd(pwd);
00329
00330 if (verbose <= 2) RooMsgService::instance().setGlobalKillBelow(RooFit::WARNING);
00331
00332 const RooArgSet * observables = mc->GetObservables();
00333 const RooArgSet * POI = mc->GetParametersOfInterest();
00334 const RooArgSet * nuisances = mc->GetNuisanceParameters();
00335 if (dynamic_cast<RooRealVar*>(POI->first()) == 0) throw std::invalid_argument("First parameter of interest is not a RooRealVar");
00336
00337 if (w->data(dataset.c_str()) == 0) {
00338 if (isTextDatacard) {
00339 RooDataSet *data_obs = new RooDataSet(dataset.c_str(), dataset.c_str(), *observables);
00340 data_obs->add(*observables);
00341 w->import(*data_obs);
00342 } else {
00343 std::cout << "Dataset " << dataset.c_str() << " not found." << std::endl;
00344 }
00345 }
00346
00347 if (verbose < -1) {
00348 RooMsgService::instance().setStreamStatus(0,kFALSE);
00349 RooMsgService::instance().setStreamStatus(1,kFALSE);
00350 RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
00351 }
00352
00353
00354 if (!isnan(rMin_)) ((RooRealVar*)POI->first())->setMin(rMin_);
00355 if (!isnan(rMax_)) ((RooRealVar*)POI->first())->setMax(rMax_);
00356
00357 if (mc->GetPriorPdf() == 0) {
00358 if (prior_ == "flat") {
00359 RooAbsPdf *prior = new RooUniform("prior","prior",*POI);
00360 w->import(*prior);
00361 mc->SetPriorPdf(*prior);
00362 } else if (prior_ == "1/sqrt(r)") {
00363 w->factory(TString::Format("EXPR::prior(\\\"1/sqrt(@0)\\\",%s)", POI->first()->GetName()));
00364 mc->SetPriorPdf(*w->pdf("prior"));
00365 } else if (!prior_.empty() && w->pdf(prior_.c_str()) != 0) {
00366 std::cout << "Will use prior '" << prior_ << "' in from the input workspace" << std::endl;
00367 mc->SetPriorPdf(*w->pdf(prior_.c_str()));
00368 } else {
00369 std::cerr << "Unknown prior '" << prior_ << "'. It's not 'flat' '1/sqrt(r)' or the name of a pdf in the model.\n" << std::endl;
00370 throw std::invalid_argument("Bad prior");
00371 }
00372 }
00373
00374 if (withSystematics && nuisances == 0) {
00375 std::cout << "The signal model has no nuisance parameters. Please run the limit tool with no systematics (option -S 0)." << std::endl;
00376 std::cout << "To make things easier, I will assume you have done it." << std::endl;
00377 withSystematics = false;
00378 } else if (!withSystematics && nuisances != 0) {
00379 std::cout << "Will set nuisance parameters to constants: " ;
00380 utils::setAllConstant(*nuisances, true);
00381 }
00382
00383 bool validModel = validateModel_ ? utils::checkModel(*mc, false) : true;
00384 if (validateModel_ && verbose) std::cout << "Sanity checks on the model: " << (validModel ? "OK" : "FAIL") << std::endl;
00385
00386
00387 if (mc->GetNuisanceParameters() && withSystematics) utils::setAllConstant(*mc->GetNuisanceParameters(), false);
00388 if (mc->GetGlobalObservables()) utils::setAllConstant(*mc->GetGlobalObservables(), true);
00389 if (mc_bonly->GetNuisanceParameters() && withSystematics) utils::setAllConstant(*mc_bonly->GetNuisanceParameters(), false);
00390 if (mc_bonly->GetGlobalObservables()) utils::setAllConstant(*mc_bonly->GetGlobalObservables(), true);
00391
00392
00393 w->saveSnapshot("clean", w->allVars());
00394
00395 if (saveWorkspace_) {
00396 w->SetName(workspaceName_.c_str());
00397 outputFile->WriteTObject(w,workspaceName_.c_str());
00398 }
00399
00400 tree_ = tree;
00401
00402 bool isExtended = mc_bonly->GetPdf()->canBeExtended();
00403 RooAbsData *dobs = w->data(dataset.c_str());
00404 RooAbsPdf *genPdf = expectSignal_ > 0 ? mc->GetPdf() : mc_bonly->GetPdf();
00405 toymcoptutils::SimPdfGenInfo newToyMC(*genPdf, *observables, !unbinned_); RooRealVar *weightVar_ = 0;
00406
00407 if (guessGenMode_ && genPdf->InheritsFrom("RooSimultaneous") && (dobs != 0)) {
00408 utils::guessChannelMode(dynamic_cast<RooSimultaneous&>(*mc->GetPdf()), *dobs, verbose);
00409 utils::guessChannelMode(dynamic_cast<RooSimultaneous&>(*mc_bonly->GetPdf()), *dobs, 0);
00410 }
00411 if (expectSignal_ > 0) {
00412 ((RooRealVar*)POI->first())->setVal(expectSignal_);
00413 }
00414 if (nToys <= 0) {
00415 iToy = nToys;
00416 if (iToy == -1) {
00417 if (newGen_) {
00418 if (toysFrequentist_) {
00419 w->saveSnapshot("reallyClean", w->allVars());
00420 if (dobs == 0) throw std::invalid_argument("Frequentist Asimov datasets can't be generated without a real dataset to fit");
00421 RooArgSet gobsAsimov;
00422 dobs = asimovutils::asimovDatasetWithFit(mc, *dobs, gobsAsimov, expectSignal_, verbose);
00423 if (mc->GetGlobalObservables()) {
00424 RooArgSet gobs(*mc->GetGlobalObservables());
00425 gobs = gobsAsimov;
00426 utils::setAllConstant(*mc->GetParametersOfInterest(), false);
00427 w->saveSnapshot("clean", w->allVars());
00428 }
00429 } else {
00430 dobs = newToyMC.generateAsimov(weightVar_);
00431 }
00432 } else if (isExtended) {
00433 if (unbinned_) {
00434 throw std::invalid_argument("Asimov datasets can only be generated binned");
00435 } else {
00436 dobs = genPdf->generateBinned(*observables,RooFit::Extended(),RooFit::Asimov());
00437 }
00438 } else {
00439 dobs = genPdf->generate(*observables,1,RooFit::Asimov());
00440 }
00441 } else if (dobs == 0) {
00442 std::cerr << "No observed data '" << dataset << "' in the workspace. Cannot compute limit.\n" << std::endl;
00443 return;
00444 }
00445 if (saveToys_) {
00446 writeToysHere->WriteTObject(dobs, TString::Format("toy_asimov%g", expectSignal_));
00447 }
00448 std::cout << "Computing limit starting from " << (iToy == 0 ? "observation" : "expected outcome") << std::endl;
00449 if (verbose > (isExtended ? 3 : 2)) utils::printRAD(dobs);
00450 if (mklimit(w,mc,mc_bonly,*dobs,limit,limitErr)) tree->Fill();
00451 }
00452
00453
00454 std::vector<double> limitHistory;
00455 std::auto_ptr<RooAbsPdf> nuisancePdf;
00456 if (nToys > 0) {
00457 double expLimit = 0;
00458 unsigned int nLimits = 0;
00459 w->loadSnapshot("clean");
00460 RooDataSet *systDs = 0;
00461 if (withSystematics && !toysNoSystematics_ && (readToysFromHere == 0)) {
00462 if (nuisances == 0) throw std::logic_error("Running with systematics enabled, but nuisances not defined.");
00463 nuisancePdf.reset(utils::makeNuisancePdf(expectSignal_ ? *mc : *mc_bonly));
00464 if (toysFrequentist_) {
00465 if (mc->GetGlobalObservables() == 0) throw std::logic_error("Cannot use toysFrequentist with no global observables");
00466 w->saveSnapshot("reallyClean", w->allVars());
00467 {
00468 if (dobs == 0) throw std::logic_error("Cannot use toysFrequentist with no input dataset");
00469 CloseCoutSentry sentry(verbose < 3);
00470 genPdf->fitTo(*dobs, RooFit::Save(1), RooFit::Minimizer("Minuit2","minimize"), RooFit::Strategy(0), RooFit::Hesse(0), RooFit::Constrain(*(expectSignal_ ?mc:mc_bonly)->GetNuisanceParameters()));
00471 }
00472 w->saveSnapshot("clean", w->allVars());
00473 systDs = nuisancePdf->generate(*mc->GetGlobalObservables(), nToys);
00474 } else {
00475 systDs = nuisancePdf->generate(*nuisances, nToys);
00476 }
00477 }
00478 std::auto_ptr<RooArgSet> vars(genPdf->getVariables());
00479 algo->setNToys(nToys);
00480 for (iToy = 1; iToy <= nToys; ++iToy) {
00481 algo->setToyNumber(iToy-1);
00482 RooAbsData *absdata_toy = 0;
00483 if (readToysFromHere == 0) {
00484 w->loadSnapshot("clean");
00485 if (verbose > 3) utils::printPdf(*mc_bonly);
00486 if (withSystematics && !toysNoSystematics_) {
00487 *vars = *systDs->get(iToy-1);
00488 if (toysFrequentist_) w->saveSnapshot("clean", w->allVars());
00489 if (verbose > 3) utils::printPdf(*mc_bonly);
00490 }
00491 if (expectSignal_) ((RooRealVar*)POI->first())->setVal(expectSignal_);
00492 std::cout << "Generate toy " << iToy << "/" << nToys << std::endl;
00493 if (isExtended) {
00494 if (newGen_) {
00495 absdata_toy = newToyMC.generate(weightVar_);
00496 } else if (unbinned_) {
00497 absdata_toy = genPdf->generate(*observables,RooFit::Extended());
00498 } else if (generateBinnedWorkaround_) {
00499 std::auto_ptr<RooDataSet> unbinn(genPdf->generate(*observables,RooFit::Extended()));
00500 absdata_toy = new RooDataHist("toy","binned toy", *observables, *unbinn);
00501 } else {
00502 absdata_toy = genPdf->generateBinned(*observables,RooFit::Extended());
00503 }
00504 } else {
00505 RooDataSet *data_toy = genPdf->generate(*observables,1);
00506 absdata_toy = data_toy;
00507 }
00508 } else {
00509 absdata_toy = dynamic_cast<RooAbsData *>(readToysFromHere->Get(TString::Format("toys/toy_%d",iToy)));
00510 if (absdata_toy == 0) {
00511 std::cerr << "Toy toy_"<<iToy<<" not found in " << readToysFromHere->GetName() << ". List follows:\n";
00512 readToysFromHere->ls();
00513 return;
00514 }
00515 }
00516 if (verbose > (isExtended ? 3 : 2)) utils::printRAD(absdata_toy);
00517 w->loadSnapshot("clean");
00518
00519 if (mklimit(w,mc,mc_bonly,*absdata_toy,limit,limitErr)) {
00520 tree->Fill();
00521 ++nLimits;
00522 expLimit += limit;
00523 limitHistory.push_back(limit);
00524 }
00525 if (saveToys_) {
00526 writeToysHere->WriteTObject(absdata_toy, TString::Format("toy_%d", iToy));
00527 }
00528 delete absdata_toy;
00529 }
00530 if (weightVar_) delete weightVar_;
00531 expLimit /= nLimits;
00532 double rms = 0;
00533 for (std::vector<double>::const_iterator itl = limitHistory.begin(); itl != limitHistory.end(); ++itl) {
00534 rms += pow(*itl-expLimit, 2);
00535 }
00536 if (nLimits > 1) {
00537 rms = sqrt(rms/(nLimits-1)/nLimits);
00538 cout << "mean expected limit: r < " << expLimit << " +/- " << rms << " @ " << cl*100 << "%CL (" <<nLimits << " toyMC)" << endl;
00539 } else {
00540 cout << "mean expected limit: r < " << expLimit << " @ " << cl*100 << "%CL (" <<nLimits << " toyMC)" << endl;
00541 }
00542 sort(limitHistory.begin(), limitHistory.end());
00543 if (nLimits > 0) {
00544 double medianLimit = (nLimits % 2 == 0 ? 0.5*(limitHistory[nLimits/2-1]+limitHistory[nLimits/2]) : limitHistory[nLimits/2]);
00545 cout << "median expected limit: r < " << medianLimit << " @ " << cl*100 << "%CL (" <<nLimits << " toyMC)" << endl;
00546 double hi68 = limitHistory[min<int>(nLimits-1, ceil(0.84 * nLimits))];
00547 double lo68 = limitHistory[min<int>(nLimits-1, floor(0.16 * nLimits))];
00548 double hi95 = limitHistory[min<int>(nLimits-1, ceil(0.975 * nLimits))];
00549 double lo95 = limitHistory[min<int>(nLimits-1, floor(0.025 * nLimits))];
00550 cout << " 68% expected band : " << lo68 << " < r < " << hi68 << endl;
00551 cout << " 95% expected band : " << lo95 << " < r < " << hi95 << endl;
00552 }
00553 }
00554
00555 }
00556
00557 void Combine::commitPoint(bool expected, float quantile) {
00558 Float_t saveQuantile = g_quantileExpected_;
00559 g_quantileExpected_ = quantile;
00560 tree_->Fill();
00561 g_quantileExpected_ = saveQuantile;
00562 }
00563
00564 void Combine::addBranch(const char *name, void *address, const char *leaflist) {
00565 tree_->Branch(name,address,leaflist);
00566 }