191 ToCleanUp garbageCollect;
193 TString tmpDir =
"", tmpFile =
"",
pwd(gSystem->pwd());
195 tmpDir =
"roostats-XXXXXX"; tmpFile =
"model";
196 mkdtemp(const_cast<char *>(tmpDir.Data()));
197 gSystem->cd(tmpDir.Data());
198 garbageCollect.path = tmpDir.Data();
199 }
else if (!hlfFile.EndsWith(
".hlf") && !hlfFile.EndsWith(
".root")) {
200 tmpFile =
"roostats-XXXXXX";
201 mktemp(const_cast<char *>(tmpFile.Data()));
204 bool isTextDatacard =
false,
isBinary =
false;
205 TString fileToLoad = (hlfFile[0] ==
'/' ? hlfFile :
pwd+
"/"+hlfFile);
206 if (!boost::filesystem::exists(fileToLoad.Data()))
throw std::invalid_argument((
"File "+fileToLoad+
" does not exist").
Data());
207 if (hlfFile.EndsWith(
".hlf") ) {
209 }
else if (hlfFile.EndsWith(
".root")) {
212 TString txtFile = fileToLoad.Data();
216 if (
verbose > 1) options += TString::Format(
" --verbose %d",
verbose-1);
221 int status = gSystem->Exec(
"text2workspace.py "+options+
" '"+txtFile+
"' -b -o "+tmpFile+
".root");
222 isBinary =
true; fileToLoad = tmpFile+
".root";
223 if (status != 0 || !boost::filesystem::exists(fileToLoad.Data())) {
224 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.");
226 garbageCollect.file = fileToLoad;
229 if (getenv(
"CMSSW_BASE")) {
230 gSystem->AddIncludePath(TString::Format(
" -I%s/src ", getenv(
"CMSSW_BASE")));
231 if (
verbose > 3)
std::cout <<
"Adding " << getenv(
"CMSSW_BASE") <<
"/src to include path" << std::endl;
233 if (getenv(
"ROOFITSYS")) {
234 gSystem->AddIncludePath(TString::Format(
" -I%s/include ", getenv(
"ROOFITSYS")));
235 if (
verbose > 3)
std::cout <<
"Adding " << getenv(
"ROOFITSYS") <<
"/include to include path" << std::endl;
240 RooWorkspace *
w = 0; RooStats::ModelConfig *mc = 0, *mc_bonly = 0;
241 std::auto_ptr<RooStats::HLFactory> hlf(0);
243 TFile *fIn = TFile::Open(fileToLoad);
244 garbageCollect.tfile = fIn;
246 w =
dynamic_cast<RooWorkspace *
>(fIn->Get(
workspaceName_.c_str()));
248 std::cerr <<
"Could not find workspace '" <<
workspaceName_ <<
"' in file " << fileToLoad << std::endl; fIn->ls();
249 throw std::invalid_argument(
"Missing Workspace");
252 RooRealVar *MH = w->var(
"MH");
254 if (
verbose > 2)
std::cerr <<
"Setting variable 'MH' in workspace to the higgs mass " <<
mass_ << std::endl;
257 mc =
dynamic_cast<RooStats::ModelConfig *
>(w->genobj(
modelConfigName_.c_str()));
258 mc_bonly =
dynamic_cast<RooStats::ModelConfig *
>(w->genobj(
modelConfigNameB_.c_str()));
260 std::cerr <<
"Could not find ModelConfig '" <<
modelConfigName_ <<
"' in workspace '" << workspaceName_ <<
"' in file " << fileToLoad << std::endl;
261 throw std::invalid_argument(
"Missing ModelConfig");
263 if (
verbose > 3) {
std::cout <<
"Input ModelConfig '" << modelConfigName_ <<
"': \n"; mc->Print(
"V"); }
264 const RooArgSet *POI = mc->GetParametersOfInterest();
265 if (POI == 0 || POI->getSize() == 0)
throw std::invalid_argument(
"ModelConfig '"+modelConfigName_+
"' does not define parameters of interest.");
266 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;
267 if (mc->GetObservables() == 0)
throw std::invalid_argument(
"ModelConfig '"+modelConfigName_+
"' does not define observables.");
268 if (mc->GetPdf() == 0)
throw std::invalid_argument(
"ModelConfig '"+modelConfigName_+
"' does not define a pdf.");
269 if (
rebuildSimPdf_ &&
typeid(*mc->GetPdf()) ==
typeid(RooSimultaneous)) {
270 RooSimultaneous *newpdf =
utils::rebuildSimPdf(*mc->GetObservables(),
dynamic_cast<RooSimultaneous*
>(mc->GetPdf()));
274 if (
optSimPdf_ &&
typeid(*mc->GetPdf()) ==
typeid(RooSimultaneous)) {
280 std::cerr <<
"Missing background ModelConfig '" <<
modelConfigNameB_ <<
"' in workspace '" << workspaceName_ <<
"' in file " << fileToLoad << std::endl;
281 std::cerr <<
"Will make one from the signal ModelConfig '" << modelConfigName_ <<
"' setting signal strenth '" << POI->first()->GetName() <<
"' to zero" << std::endl;
282 w->factory(
"_zero_[0]");
283 RooCustomizer make_model_s(*mc->GetPdf(),
"_model_bonly_");
284 make_model_s.replaceArg(*POI->first(), *w->var(
"_zero_"));
285 RooAbsPdf *model_b =
dynamic_cast<RooAbsPdf *
>(make_model_s.build());
286 model_b->SetName(
"_model_bonly_");
288 mc_bonly =
new RooStats::ModelConfig(*mc);
289 mc_bonly->SetPdf(*model_b);
292 hlf.reset(
new RooStats::HLFactory(
"factory", fileToLoad));
295 std::cerr <<
"Could not read HLF from file " << (hlfFile[0] ==
'/' ? hlfFile :
pwd+
"/"+hlfFile) << std::endl;
298 RooRealVar *MH = w->var(
"MH");
300 std::cerr <<
"Could not find MH var in workspace '" << workspaceName_ <<
"' in file " << fileToLoad << std::endl;
301 throw std::invalid_argument(
"Missing MH");
304 if (w->set(
"observables") == 0)
throw std::invalid_argument(
"The model must define a RooArgSet 'observables'");
305 if (w->set(
"POI") == 0)
throw std::invalid_argument(
"The model must define a RooArgSet 'POI' for the parameters of interest");
306 if (w->pdf(
"model_b") == 0)
throw std::invalid_argument(
"The model must define a RooAbsPdf 'model_b'");
307 if (w->pdf(
"model_s") == 0)
throw std::invalid_argument(
"The model must define a RooAbsPdf 'model_s'");
310 mc =
new RooStats::ModelConfig(modelConfigName_.c_str(),
"signal",
w);
311 mc->SetPdf(*w->pdf(
"model_s"));
312 mc->SetObservables(*w->set(
"observables"));
313 mc->SetParametersOfInterest(*w->set(
"POI"));
314 if (w->set(
"nuisances")) mc->SetNuisanceParameters(*w->set(
"nuisances"));
315 if (w->set(
"globalObservables")) mc->SetGlobalObservables(*w->set(
"globalObservables"));
316 if (w->pdf(
"prior")) mc->SetNuisanceParameters(*w->pdf(
"prior"));
317 w->import(*mc, modelConfigName_.c_str());
320 mc_bonly->SetPdf(*w->pdf(
"model_b"));
321 mc_bonly->SetObservables(*w->set(
"observables"));
322 mc_bonly->SetParametersOfInterest(*w->set(
"POI"));
323 if (w->set(
"nuisances")) mc_bonly->SetNuisanceParameters(*w->set(
"nuisances"));
324 if (w->set(
"globalObservables")) mc_bonly->SetGlobalObservables(*w->set(
"globalObservables"));
325 if (w->pdf(
"prior")) mc_bonly->SetNuisanceParameters(*w->pdf(
"prior"));
332 const RooArgSet * observables = mc->GetObservables();
333 const RooArgSet * POI = mc->GetParametersOfInterest();
334 const RooArgSet * nuisances = mc->GetNuisanceParameters();
335 if (dynamic_cast<RooRealVar*>(POI->first()) == 0)
throw std::invalid_argument(
"First parameter of interest is not a RooRealVar");
337 if (w->data(
dataset.c_str()) == 0) {
338 if (isTextDatacard) {
339 RooDataSet *data_obs =
new RooDataSet(
dataset.c_str(),
dataset.c_str(), *observables);
340 data_obs->add(*observables);
341 w->import(*data_obs);
357 if (mc->GetPriorPdf() == 0) {
359 RooAbsPdf *
prior =
new RooUniform(
"prior",
"prior",*POI);
361 mc->SetPriorPdf(*prior);
362 }
else if (
prior_ ==
"1/sqrt(r)") {
363 w->factory(TString::Format(
"EXPR::prior(\\\"1/sqrt(@0)\\\",%s)", POI->first()->GetName()));
364 mc->SetPriorPdf(*w->pdf(
"prior"));
365 }
else if (!
prior_.empty() && w->pdf(
prior_.c_str()) != 0) {
366 std::cout <<
"Will use prior '" <<
prior_ <<
"' in from the input workspace" << std::endl;
367 mc->SetPriorPdf(*w->pdf(
prior_.c_str()));
369 std::cerr <<
"Unknown prior '" <<
prior_ <<
"'. It's not 'flat' '1/sqrt(r)' or the name of a pdf in the model.\n" << std::endl;
370 throw std::invalid_argument(
"Bad prior");
375 std::cout <<
"The signal model has no nuisance parameters. Please run the limit tool with no systematics (option -S 0)." << std::endl;
376 std::cout <<
"To make things easier, I will assume you have done it." << std::endl;
379 std::cout <<
"Will set nuisance parameters to constants: " ;
390 if (mc_bonly->GetGlobalObservables())
utils::setAllConstant(*mc_bonly->GetGlobalObservables(),
true);
393 w->saveSnapshot(
"clean", w->allVars());
396 w->SetName(workspaceName_.c_str());
397 outputFile->WriteTObject(w,workspaceName_.c_str());
402 bool isExtended = mc_bonly->GetPdf()->canBeExtended();
403 RooAbsData *dobs = w->data(
dataset.c_str());
404 RooAbsPdf *genPdf =
expectSignal_ > 0 ? mc->GetPdf() : mc_bonly->GetPdf();
407 if (
guessGenMode_ && genPdf->InheritsFrom(
"RooSimultaneous") && (dobs != 0)) {
419 w->saveSnapshot(
"reallyClean", w->allVars());
420 if (dobs == 0)
throw std::invalid_argument(
"Frequentist Asimov datasets can't be generated without a real dataset to fit");
421 RooArgSet gobsAsimov;
423 if (mc->GetGlobalObservables()) {
424 RooArgSet gobs(*mc->GetGlobalObservables());
427 w->saveSnapshot(
"clean", w->allVars());
430 dobs = newToyMC.generateAsimov(weightVar_);
432 }
else if (isExtended) {
434 throw std::invalid_argument(
"Asimov datasets can only be generated binned");
436 dobs = genPdf->generateBinned(*observables,RooFit::Extended(),RooFit::Asimov());
439 dobs = genPdf->generate(*observables,1,RooFit::Asimov());
441 }
else if (dobs == 0) {
442 std::cerr <<
"No observed data '" <<
dataset <<
"' in the workspace. Cannot compute limit.\n" << std::endl;
448 std::cout <<
"Computing limit starting from " << (iToy == 0 ?
"observation" :
"expected outcome") << std::endl;
454 std::vector<double> limitHistory;
455 std::auto_ptr<RooAbsPdf> nuisancePdf;
458 unsigned int nLimits = 0;
459 w->loadSnapshot(
"clean");
460 RooDataSet *systDs = 0;
462 if (nuisances == 0)
throw std::logic_error(
"Running with systematics enabled, but nuisances not defined.");
465 if (mc->GetGlobalObservables() == 0)
throw std::logic_error(
"Cannot use toysFrequentist with no global observables");
466 w->saveSnapshot(
"reallyClean", w->allVars());
468 if (dobs == 0)
throw std::logic_error(
"Cannot use toysFrequentist with no input dataset");
470 genPdf->fitTo(*dobs, RooFit::Save(1), RooFit::Minimizer(
"Minuit2",
"minimize"), RooFit::Strategy(0), RooFit::Hesse(0), RooFit::Constrain(*(
expectSignal_ ?mc:mc_bonly)->GetNuisanceParameters()));
472 w->saveSnapshot(
"clean", w->allVars());
473 systDs = nuisancePdf->generate(*mc->GetGlobalObservables(), nToys);
475 systDs = nuisancePdf->generate(*nuisances, nToys);
478 std::auto_ptr<RooArgSet> vars(genPdf->getVariables());
480 for (iToy = 1; iToy <= nToys; ++iToy) {
482 RooAbsData *absdata_toy = 0;
484 w->loadSnapshot(
"clean");
487 *vars = *systDs->get(iToy-1);
492 std::cout <<
"Generate toy " << iToy <<
"/" << nToys << std::endl;
495 absdata_toy = newToyMC.generate(weightVar_);
497 absdata_toy = genPdf->generate(*observables,RooFit::Extended());
499 std::auto_ptr<RooDataSet> unbinn(genPdf->generate(*observables,RooFit::Extended()));
500 absdata_toy =
new RooDataHist(
"toy",
"binned toy", *observables, *unbinn);
502 absdata_toy = genPdf->generateBinned(*observables,RooFit::Extended());
505 RooDataSet *data_toy = genPdf->generate(*observables,1);
506 absdata_toy = data_toy;
509 absdata_toy =
dynamic_cast<RooAbsData *
>(
readToysFromHere->Get(TString::Format(
"toys/toy_%d",iToy)));
510 if (absdata_toy == 0) {
517 w->loadSnapshot(
"clean");
519 if (
mklimit(w,mc,mc_bonly,*absdata_toy,
limit,limitErr)) {
523 limitHistory.push_back(
limit);
526 writeToysHere->WriteTObject(absdata_toy, TString::Format(
"toy_%d", iToy));
530 if (weightVar_)
delete weightVar_;
533 for (std::vector<double>::const_iterator itl = limitHistory.begin(); itl != limitHistory.end(); ++itl) {
534 rms +=
pow(*itl-expLimit, 2);
537 rms =
sqrt(rms/(nLimits-1)/nLimits);
538 cout <<
"mean expected limit: r < " << expLimit <<
" +/- " << rms <<
" @ " <<
cl*100 <<
"%CL (" <<nLimits <<
" toyMC)" << endl;
540 cout <<
"mean expected limit: r < " << expLimit <<
" @ " <<
cl*100 <<
"%CL (" <<nLimits <<
" toyMC)" << endl;
542 sort(limitHistory.begin(), limitHistory.end());
544 double medianLimit = (nLimits % 2 == 0 ? 0.5*(limitHistory[nLimits/2-1]+limitHistory[nLimits/2]) : limitHistory[nLimits/2]);
545 cout <<
"median expected limit: r < " << medianLimit <<
" @ " <<
cl*100 <<
"%CL (" <<nLimits <<
" toyMC)" << endl;
546 double hi68 = limitHistory[min<int>(nLimits-1, ceil(0.84 * nLimits))];
547 double lo68 = limitHistory[min<int>(nLimits-1, floor(0.16 * nLimits))];
548 double hi95 = limitHistory[min<int>(nLimits-1, ceil(0.975 * nLimits))];
549 double lo95 = limitHistory[min<int>(nLimits-1, floor(0.025 * nLimits))];
550 cout <<
" 68% expected band : " << lo68 <<
" < r < " << hi68 << endl;
551 cout <<
" 95% expected band : " << lo95 <<
" < r < " << hi95 << endl;
TDirectory * readToysFromHere
bool setAllConstant(const RooAbsCollection &coll, bool constant=true)
set all RooRealVars to constants. return true if at least one changed status
static PFTauRenderPlugin instance
void guessChannelMode(RooSimultaneous &simPdf, RooAbsData &simData, bool verbose=false)
virtual void setNToys(const int)
RooAbsPdf * makeNuisancePdf(RooStats::ModelConfig &model, const char *name="nuisancePdf")
RooAbsData * asimovDatasetWithFit(RooStats::ModelConfig *mc, RooAbsData &realdata, RooAbsCollection &snapshot, double poiValue=0.0, int verbose=0)
Generate asimov dataset from best fit value of nuisance parameters, and fill in snapshot of correspon...
TDirectory * writeToysHere
RooSimultaneous * rebuildSimPdf(const RooArgSet &observables, RooSimultaneous *pdf)
void printPdf(RooAbsPdf *pdf)
bool generateBinnedWorkaround_
std::string workspaceName_
bool checkModel(const RooStats::ModelConfig &model, bool throwOnFail=false)
std::string modelConfigNameB_
bool mklimit(RooWorkspace *w, RooStats::ModelConfig *mc_s, RooStats::ModelConfig *mc_b, RooAbsData &data, double &limit, double &limitErr)
std::string modelConfigName_
void printRAD(const RooAbsData *d)
virtual void setToyNumber(const int)
Power< A, B >::type pow(const A &a, const B &b)