void upper_limit_Bayesian_MCMC(Model* model,double confidence,int Niters){
  cout<<"///////////////////////////////////////////////////////////////////////////////////////////"<<endl;
  cout<<"Calculating upper limit with the MCMC method"<<endl;
  cout<<"///////////////////////////////////////////////////////////////////////////////////////////"<<endl;
  
  RooWorkspace* wspace = new RooWorkspace("wspace");
  ModelConfig* modelConfig = new ModelConfig("bayes");
  modelConfig->SetWorkspace(*wspace);
  modelConfig->SetPdf(*model->get_complete_likelihood());
  modelConfig->SetPriorPdf(*model->get_POI_prior());
  modelConfig->SetParametersOfInterest(*model->get_POI_set());
  //  modelConfig->SetNuisanceParameters();
  modelConfig->SetNuisanceParameters(*model->get_nuisance_set());


  //configure the calculator
  //model->Print();

  cout<<" POI size "<<model->get_POI_set()->getSize()<<endl; 
  RooRealVar* firstPOI = (RooRealVar*) modelConfig->GetParametersOfInterest()->first();


  MCMCCalculator mcmccalc(*model->get_data(), *modelConfig );
  mcmccalc.SetTestSize(1-confidence);
  mcmccalc.SetLeftSideTailFraction(0);
  mcmccalc.SetNumIters(Niters);
  MCMCInterval* interval = mcmccalc.GetInterval();
  double ul = interval->UpperLimit(*firstPOI);
  cout<<"UpperLimit: "<<ul<<endl;

}
double upper_limit_FC(Model* model,double confidence){
  cout<<"///////////////////////////////////////////////////////////////////////////////////////////"<<endl;
  cout<<"Calculating upper limit with the FC method"<<endl;
  cout<<"///////////////////////////////////////////////////////////////////////////////////////////"<<endl;
  
  RooWorkspace* wspace = new RooWorkspace("wspace");

  ModelConfig* modelConfig = new ModelConfig("FC");
  modelConfig->SetWorkspace(*wspace);
  modelConfig->SetPdf(*model->get_complete_likelihood());
  modelConfig->SetPriorPdf(*model->get_POI_prior());
  modelConfig->SetParametersOfInterest(*model->get_POI_set());
  //modelConfig->SetParametersOfInterest(*wspace->set("poi"));
  //modelConfig->SetNuisanceParameters(*wspace->set("nuis"));
  // modelConfig->SetNuisanceParameters();
  modelConfig->SetNuisanceParameters(*model->get_nuisance_set());

  RooDataSet* data = model->get_data();
  RooArgSet* poi= model->get_POI_set();
  //configure the calculator
  //model->Print();



  cout<<" POI size "<<model->get_POI_set()->getSize()<<endl; 

  // use FeldmaCousins (takes ~20 min)  
  FeldmanCousins fc(*data, *modelConfig);
  fc.SetConfidenceLevel(0.95); //0.9 central limit=0.95 upper limit
  //fc.SetTestSize(.1); // set size of test
  //number counting: dataset always has 1 entry with N events observed
  fc.FluctuateNumDataEntries(false); 
  fc.UseAdaptiveSampling(true);

  fc.SetNBins(200);
  PointSetInterval* fcInt = NULL;
  //ConfInterval* interval = 0;


  RooRealVar* firstPOI = (RooRealVar*) modelConfig->GetParametersOfInterest()->first();

  //  if(doFeldmanCousins){ // takes 7 minutes
  fcInt = (PointSetInterval*) fc.GetInterval(); // fix cast
  //xs}
  //interval = (PointSetInterval*) fc.GetInterval();

  cout<<" ["<<fcInt->LowerLimit( *firstPOI ) << ", " <<
  fcInt->UpperLimit( *firstPOI ) << "]" << endl;
  cout<<" ["<<fcInt->LowerLimit( *firstPOI ) << ", " <<
  fcInt->UpperLimit( *firstPOI ) << "]" << endl;
    
  double ul=fcInt->UpperLimit( *firstPOI );
  //double ul=interval->UpperLimit( *firstPOI );
  return ul;
}
Exemple #3
0
double TwoBody::printMcmcUpperLimit( double peak, ModelConfig &_mc, std::string filename ){
  //
  // print out the upper limit on the first Parameter of Interest
  //

  std::string _legend = "[TwoBody::printMcmcUpperLimit]: ";

  char buf[1024];

  double _limit = numeric_limits<double>::max();

  if (mcInt){
    //mc.SetWorkspace(*ws);
    RooRealVar * firstPOI = (RooRealVar*) _mc.GetParametersOfInterest()->first();
    _limit = mcInt->UpperLimit(*firstPOI);
    std::cout << "\n95% upper limit on " << firstPOI->GetName() << " is : " <<
      _limit << endl;
    
    if (bMcmcConverged){
      sprintf(buf, "%7.1f   %7.6f", peak, _limit);
    }
    else{
      sprintf(buf, "# %7.1f   %7.6f  # MCMC did not converge", peak, _limit);
    }

  }
  else{
    sprintf(buf, "# MCMC did not converge");
  }

  if (filename.size()!=0){
    
    std::ofstream aFile;
    
    // append to file if exists
    aFile.open(filename.c_str(), std::ios_base::app);
    
    aFile << buf << std::endl;
    
    // close outfile here so it is safe even if subsequent iterations crash
    aFile.close();
    
  }
    
  return _limit;
}
Exemple #4
0
Double_t TwoBody::GetPoiUpper(std::string channel, Double_t peak, ModelConfig &_mc){
  //
  // Estimate a good value for the upper boundary of the range of POI
  //

  std::string legend = "[TwoBody::GetPoiUpper]: ";

  double _range = -1.0;

  std::cout << legend << "doing a rough estimate of the POI range" << std::endl;
  // adding auto-channel option (multi) while
  // preserving backwards compatibility
  // if single channel
  _range = GetPoiUpperSimple(channel, peak);
  
  std::cout << legend << "crude estimate for poi range (x3): "
	    << 3.0*_range << std::endl;
  std::cout << legend 
	    << "this will be used if the profile likelihood ratio estimate fails"
	    << std::endl;
  std::cout << legend 
	    << "will try to estimate POI range better with profile likelihood ratio limit now"
	    << std::endl;

  Double_t result = 0.1;

  // estimate limit with profile likelihood ratio and
  // set the range to 3 times the limit
  
  // query intervals
  RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
  RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
  RooRealVar * _poi = (RooRealVar *)_mc.GetParametersOfInterest()->first();
  double upper_limit = GetPlrInterval(0.95, _mc)->UpperLimit( *_poi );
  RooMsgService::instance().setGlobalKillBelow(msglevel);
  
  // safety in case upper limit == 0
  if (upper_limit<std::numeric_limits<double>::min()){
    upper_limit = _range;
  }

  result = 3.0*upper_limit;

  return result;
}
void StandardTestStatDistributionDemo(const char* infile = "",
                                      const char* workspaceName = "combined",
                                      const char* modelConfigName = "ModelConfig",
                                      const char* dataName = "obsData"){


  // the number of toy MC used to generate the distribution
  int nToyMC = 1000;
  // The parameter below is needed for asymptotic distribution to be chi-square,
  // but set to false if your model is not numerically stable if mu<0
  bool allowNegativeMu=true;


  /////////////////////////////////////////////////////////////
  // 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";
      bool fileExist = !gSystem->AccessPathName(filename); // note opposite return code
      // if file does not exists generate with histfactory
      if (!fileExist) {
#ifdef _WIN32
         cout << "HistFactory file cannot be generated on Windows - exit" << endl;
         return;
#endif
         // 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;
      }

   }
   else
      filename = infile;

   // Try to open the file
   TFile *file = TFile::Open(filename);

   // if input file was specified byt not found, quit
   if(!file ){
      cout <<"StandardRooStatsDemoMacro: Input file " << filename << " is not found" << endl;
      return;
   }


  /////////////////////////////////////////////////////////////
  // Now get the data and workspace
  ////////////////////////////////////////////////////////////

  // get the workspace out of the file
  RooWorkspace* w = (RooWorkspace*) file->Get(workspaceName);
  if(!w){
    cout <<"workspace not found" << endl;
    return;
  }

  // get the modelConfig out of the file
  ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

  // get the modelConfig out of the file
  RooAbsData* data = w->data(dataName);

  // make sure ingredients are found
  if(!data || !mc){
    w->Print();
    cout << "data or ModelConfig was not found" <<endl;
    return;
  }

  mc->Print();
  /////////////////////////////////////////////////////////////
  // Now find the upper limit based on the asymptotic results
  ////////////////////////////////////////////////////////////
  RooRealVar* firstPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
  ProfileLikelihoodCalculator plc(*data,*mc);
  LikelihoodInterval* interval = plc.GetInterval();
  double plcUpperLimit = interval->UpperLimit(*firstPOI);
  delete interval;
  cout << "\n\n--------------------------------------"<<endl;
  cout <<"Will generate sampling distribution at " << firstPOI->GetName() << " = " << plcUpperLimit <<endl;
  int nPOI = mc->GetParametersOfInterest()->getSize();
  if(nPOI>1){
    cout <<"not sure what to do with other parameters of interest, but here are their values"<<endl;
    mc->GetParametersOfInterest()->Print("v");
  }

  /////////////////////////////////////////////
  // create thte test stat sampler
  ProfileLikelihoodTestStat ts(*mc->GetPdf());

  // to avoid effects from boundary and simplify asymptotic comparison, set min=-max
  if(allowNegativeMu)
    firstPOI->setMin(-1*firstPOI->getMax());

  // temporary RooArgSet
  RooArgSet poi;
  poi.add(*mc->GetParametersOfInterest());

  // create and configure the ToyMCSampler
  ToyMCSampler sampler(ts,nToyMC);
  sampler.SetPdf(*mc->GetPdf());
  sampler.SetObservables(*mc->GetObservables());
  sampler.SetGlobalObservables(*mc->GetGlobalObservables());
  if(!mc->GetPdf()->canBeExtended() && (data->numEntries()==1)){
    cout << "tell it to use 1 event"<<endl;
    sampler.SetNEventsPerToy(1);
  }
  firstPOI->setVal(plcUpperLimit); // set POI value for generation
  sampler.SetParametersForTestStat(*mc->GetParametersOfInterest()); // set POI value for evaluation

  if (useProof) {
     ProofConfig pc(*w, nworkers, "",false);
     sampler.SetProofConfig(&pc); // enable proof
  }

  firstPOI->setVal(plcUpperLimit);
  RooArgSet allParameters;
  allParameters.add(*mc->GetParametersOfInterest());
  allParameters.add(*mc->GetNuisanceParameters());
  allParameters.Print("v");

  SamplingDistribution* sampDist = sampler.GetSamplingDistribution(allParameters);
  SamplingDistPlot plot;
  plot.AddSamplingDistribution(sampDist);
  plot.GetTH1F(sampDist)->GetYaxis()->SetTitle(Form("f(-log #lambda(#mu=%.2f) | #mu=%.2f)",plcUpperLimit,plcUpperLimit));
  plot.SetAxisTitle(Form("-log #lambda(#mu=%.2f)",plcUpperLimit));

  TCanvas* c1 = new TCanvas("c1");
  c1->SetLogy();
  plot.Draw();
  double min = plot.GetTH1F(sampDist)->GetXaxis()->GetXmin();
  double max = plot.GetTH1F(sampDist)->GetXaxis()->GetXmax();

  TF1* f = new TF1("f",Form("2*ROOT::Math::chisquared_pdf(2*x,%d,0)",nPOI),min,max);
  f->Draw("same");
  c1->SaveAs("standard_test_stat_distribution.pdf");

}
Exemple #6
0
void splitws(string inFolderName, double mass, string channel) {
  cout << "Splitting workspace in " << channel << endl;

  int flatInterpCode = 4;
  int shapeInterpCode = 4;

  bool do2011 = 0;

  if (inFolderName.find("2011") != string::npos) do2011 = 1;

  bool conditionalAsimov = 0;
  bool doData = 1;
  //if (inFolderName.find("_blind_") != string::npos) {
    //conditionalAsimov = 0;
  //}
  //else {
    //conditionalAsimov = 1;
  //}

  set<string> channelNames;

  if (channel == "01j") {
    channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));

    channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));
  }
  else if (channel == "0j") {
    channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));
  }
  else if (channel == "1j") {
    channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));
  }
  else if (channel == "OF01j") {
    channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_sscr_0j"+string(!do2011?"_2012":""));

    channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_sscr_1j"+string(!do2011?"_2012":""));
  }
  else if (channel == "OF0j") {
    channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_sscr_0j"+string(!do2011?"_2012":""));
  }
  else if (channel == "OF1j") {
    channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_sscr_1j"+string(!do2011?"_2012":""));
  }
  else if (channel == "SF01j") {
    channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));

    channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));
  }
  else if (channel == "SF0j") {
    channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));
  }
  else if (channel == "SF1j") {
    channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));
  }
  else if (channel == "2j") {
    channelNames.insert("em_signalLike1_2j"+string(!do2011?"_2012":""));
    channelNames.insert("ee_signalLike1_2j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":""));
  }
  else if (channel == "OF2j") {
    channelNames.insert("em_signalLike1_2j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":""));
  }
  else if (channel == "SF2j") {
    channelNames.insert("ee_signalLike1_2j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":""));
  }
  else if (channel == "OF") {
    channelNames.insert("em_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_0j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));

    channelNames.insert("em_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("em_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike1_1j"+string(!do2011?"_2012":""));
    channelNames.insert("me_signalLike2_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));

    channelNames.insert("em_signalLike1_2j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":""));
  }
  else if (channel == "SF") {
    channelNames.insert("SF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_0j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_0j"+string(!do2011?"_2012":""));

    channelNames.insert("SF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_AfrecSR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_ASR_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CfrecZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_CZpeak_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_mainControl_1j"+string(!do2011?"_2012":""));
    channelNames.insert("OF_topbox_1j"+string(!do2011?"_2012":""));

    channelNames.insert("ee_signalLike1_2j"+string(!do2011?"_2012":""));
    channelNames.insert("SF_topbox_2j"+string(!do2011?"_2012":""));
  }
  else {
    cout << "Channel " << channel << " not defined. Please check!" << endl;
    exit(1);
  }

  // bool fix = 1;
  stringstream inFileName;

  inFileName << "workspaces/" << inFolderName << "/" << mass << ".root";
  TFile f(inFileName.str().c_str());
  
  RooWorkspace* w = (RooWorkspace*)f.Get("combWS");
  if (!w) w = (RooWorkspace*)f.Get("combined");
  
  RooDataSet* data = (RooDataSet*)w->data("combData");
  if (!data) data = (RooDataSet*)w->data("obsData");
  
  ModelConfig* mc = (ModelConfig*)w->obj("ModelConfig");
  
  RooRealVar* weightVar = w->var("weightVar");
  
  RooRealVar* mu = (RooRealVar*)mc->GetParametersOfInterest()->first();
  if (!mu) mu = w->var("SigXsecOverSM");

  const RooArgSet* mc_obs = mc->GetObservables();
  const RooArgSet* mc_nuis = mc->GetNuisanceParameters();
  const RooArgSet* mc_globs = mc->GetGlobalObservables();
  const RooArgSet* mc_poi = mc->GetParametersOfInterest();

  RooArgSet nuis = *mc_nuis;
  RooArgSet antiNuis = *mc_nuis;

  RooArgSet globs = *mc_globs;
  RooArgSet antiGlobs = *mc_globs;

  RooArgSet allParams;

  RooSimultaneous* simPdf = (RooSimultaneous*)mc->GetPdf();
  RooCategory* cat = (RooCategory*)&simPdf->indexCat();

  RooArgSet nuis_tmp = nuis;
  RooArgSet fullConstraints = *simPdf->getAllConstraints(*mc_obs,nuis_tmp,false);

  vector<string> foundChannels;
  vector<string> skippedChannels;  

  cout << "Getting constraints" << endl;
  map<string, RooDataSet*> data_map;
  map<string, RooAbsPdf*> pdf_map;
  RooCategory* decCat = new RooCategory("dec_channel","dec_channel");
  // int i = 0;
  TIterator* catItr = cat->typeIterator();
  RooCatType* type;
  RooArgSet allConstraints;
  while ((type = (RooCatType*)catItr->Next())) {
    RooAbsPdf* pdf =  simPdf->getPdf(type->GetName());

    string typeName(type->GetName());
    if (channelNames.size() && channelNames.find(typeName) == channelNames.end())  {
      skippedChannels.push_back(typeName);
      continue;
    }
    cout << "On channel " << type->GetName() << endl;
    foundChannels.push_back(typeName);

    decCat->defineType(type->GetName());
    // pdf->getParameters(*data)->Print("v");

    RooArgSet nuis_tmp1 = nuis;
    RooArgSet nuis_tmp2 = nuis;
    RooArgSet* constraints = pdf->getAllConstraints(*mc_obs, nuis_tmp1, true);
    constraints->Print();
    allConstraints.add(*constraints);
  }

  catItr->Reset();

  while ((type = (RooCatType*)catItr->Next())) {
    RooAbsPdf* pdf =  simPdf->getPdf(type->GetName());

    string typeName(type->GetName());
    cout << "Considering type " << typeName << endl;
    if (channelNames.size() && channelNames.find(typeName) == channelNames.end()) continue;
    cout << "On channel " << type->GetName() << endl;

    RooArgSet nuis_tmp1 = nuis;
    RooArgSet nuis_tmp2 = nuis;
    RooArgSet* constraints = pdf->getAllConstraints(*mc_obs, nuis_tmp1, true);

    cout << "Adding pdf to map: " << typeName << " = " << pdf->GetName() << endl;
    pdf_map[typeName] = pdf;

    RooProdPdf prod("prod","prod",*constraints);

    RooArgSet* params = pdf->getParameters(*data);
    antiNuis.remove(*params);
    antiGlobs.remove(*params);

    allParams.add(*params);
    // cout << type->GetName() << endl;
  }
  // return;

  RooArgSet decNuis;
  TIterator* nuiItr = mc_nuis->createIterator();
  TIterator* parItr = allParams.createIterator();
  RooAbsArg* nui, *par;
  while ((par = (RooAbsArg*)parItr->Next())) {
    nuiItr->Reset();
    while ((nui = (RooAbsArg*)nuiItr->Next())) {
      if (par == nui) decNuis.add(*nui);
    }
  }

  RooArgSet decGlobs;
  TIterator* globItr = mc_globs->createIterator();
  parItr->Reset();
  RooAbsArg* glob;
  while ((par = (RooAbsArg*)parItr->Next())) {
    globItr->Reset();
    while ((glob = (RooAbsArg*)globItr->Next())) {
      if (par == glob) decGlobs.add(*glob);
    }
  }

  // antiNuis.Print();

  // nuis.Print();
  // globs.Print();

  // i = 0;
  TList* datalist = data->split(*cat, true);
  TIterator* dataItr = datalist->MakeIterator();
  RooAbsData* ds;
  while ((ds = (RooAbsData*)dataItr->Next())) {
    string typeName(ds->GetName());
    if (channelNames.size() && channelNames.find(typeName) == channelNames.end()) continue;

    cout << "Adding dataset to map: " << ds->GetName() << endl;
    data_map[string(ds->GetName())] = (RooDataSet*)ds;

    cout << ds->GetName() << endl;
  }

  RooSimultaneous* decPdf = new RooSimultaneous("decPdf","decPdf",pdf_map,*decCat); 
  RooArgSet decObs = *decPdf->getObservables(data);
  // decObs.add(*(RooAbsArg*)weightVar);
  decObs.add(*(RooAbsArg*)decCat);
  decObs.Print();

  nuis.remove(antiNuis);
  globs.remove(antiGlobs);
  // nuis.Print("v");

  RooDataSet* decData = new RooDataSet("obsData","obsData",RooArgSet(decObs,*(RooAbsArg*)weightVar),Index(*decCat),Import(data_map),WeightVar(*weightVar));

  decData->Print();

  RooArgSet poi(*(RooAbsArg*)mu);
  RooWorkspace decWS("combined");
  ModelConfig decMC("ModelConfig",&decWS);
  decMC.SetPdf(*decPdf);
  decMC.SetObservables(decObs);
  decMC.SetNuisanceParameters(decNuis);
  decMC.SetGlobalObservables(decGlobs);
  decMC.SetParametersOfInterest(poi);

  decMC.Print();
  decWS.import(*decPdf);
  decWS.import(decMC);
  decWS.import(*decData);
  // decWS.Print();

  ModelConfig* mcInWs = (ModelConfig*)decWS.obj("ModelConfig");
  decPdf = (RooSimultaneous*)mcInWs->GetPdf();

  // setup(mcInWs);
  // return;

  mcInWs->GetNuisanceParameters()->Print("v");
  mcInWs->GetGlobalObservables()->Print("v");
  // decData->tree()->Scan("*");

  // Make asimov data
  RooArgSet funcs = decWS.allFunctions();
  TIterator* it = funcs.createIterator();
  TObject* tempObj = 0;
  while((tempObj=it->Next()))
  {
    FlexibleInterpVar* flex = dynamic_cast<FlexibleInterpVar*>(tempObj);
    if(flex) {
      flex->setAllInterpCodes(flatInterpCode);
    }
    PiecewiseInterpolation* piece = dynamic_cast<PiecewiseInterpolation*>(tempObj);
    if(piece) {
      piece->setAllInterpCodes(shapeInterpCode);
    }
  }

  RooDataSet* dataInWs = (RooDataSet*)decWS.data("obsData");
  makeAsimovData(mcInWs, conditionalAsimov && doData, &decWS, mcInWs->GetPdf(), dataInWs, 0);
  makeAsimovData(mcInWs, conditionalAsimov && doData, &decWS, mcInWs->GetPdf(), dataInWs, 1);
  makeAsimovData(mcInWs, conditionalAsimov && doData, &decWS, mcInWs->GetPdf(), dataInWs, 2);

  system(("mkdir -vp workspaces/"+inFolderName+"_"+channel).c_str());
  stringstream outFileName;
  outFileName << "workspaces/" << inFolderName << "_" << channel << "/" << mass << ".root";
  cout << "Exporting" << endl;

  decWS.writeToFile(outFileName.str().c_str());

  cout << "\nIncluded the following channels: " << endl;
  for (int i=0;i<(int)foundChannels.size();i++) {
    cout << "-> " << foundChannels[i] << endl;
  }

  cout << "\nSkipping the following channels: " << endl;
  
  for (int i=0;i<(int)skippedChannels.size();i++) {
    cout << "-> " << skippedChannels[i] << endl;
  }

  cout << "Done" << endl;

  // decPdf->fitTo(*decData, Hesse(0), Minos(0), PrintLevel(0));
}
// internal routine to run the inverter
HypoTestInverterResult *
RooStats::HypoTestInvTool::RunInverter(RooWorkspace * w,
                                       const char * modelSBName, const char * modelBName, 
                                       const char * dataName, int type,  int testStatType, 
                                       bool useCLs, int npoints, double poimin, double poimax, 
                                       int ntoys,
                                       bool useNumberCounting,
                                       const char * nuisPriorName ){

   std::cout << "Running HypoTestInverter on the workspace " << w->GetName() << std::endl;
  
   w->Print();
  
  
   RooAbsData * data = w->data(dataName); 
   if (!data) { 
      Error("StandardHypoTestDemo","Not existing data %s",dataName);
      return 0;
   }
   else 
      std::cout << "Using data set " << dataName << std::endl;
  
   if (mUseVectorStore) { 
      RooAbsData::setDefaultStorageType(RooAbsData::Vector);
      data->convertToVectorStore() ;
   }
  
  
   // get models from WS
   // get the modelConfig out of the file
   ModelConfig* bModel = (ModelConfig*) w->obj(modelBName);
   ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName);
  
   if (!sbModel) {
      Error("StandardHypoTestDemo","Not existing ModelConfig %s",modelSBName);
      return 0;
   }
   // check the model 
   if (!sbModel->GetPdf()) { 
      Error("StandardHypoTestDemo","Model %s has no pdf ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetObservables()) {
      Error("StandardHypoTestInvDemo","Model %s has no observables ",modelSBName);
      return 0;
   }
   if (!sbModel->GetSnapshot() ) { 
      Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi",modelSBName);
      sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() );
   }
  
   // case of no systematics
   // remove nuisance parameters from model
   if (noSystematics) { 
      const RooArgSet * nuisPar = sbModel->GetNuisanceParameters();
      if (nuisPar && nuisPar->getSize() > 0) { 
         std::cout << "StandardHypoTestInvDemo" << "  -  Switch off all systematics by setting them constant to their initial values" << std::endl;
         RooStats::SetAllConstant(*nuisPar);
      }
      if (bModel) { 
         const RooArgSet * bnuisPar = bModel->GetNuisanceParameters();
         if (bnuisPar) 
            RooStats::SetAllConstant(*bnuisPar);
      }
   }
  
   if (!bModel || bModel == sbModel) {
      Info("StandardHypoTestInvDemo","The background model %s does not exist",modelBName);
      Info("StandardHypoTestInvDemo","Copy it from ModelConfig %s and set POI to zero",modelSBName);
      bModel = (ModelConfig*) sbModel->Clone();
      bModel->SetName(TString(modelSBName)+TString("_with_poi_0"));      
      RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
      if (!var) return 0;
      double oldval = var->getVal();
      var->setVal(0);
      bModel->SetSnapshot( RooArgSet(*var)  );
      var->setVal(oldval);
   }
   else { 
      if (!bModel->GetSnapshot() ) { 
         Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi and 0 values ",modelBName);
         RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
         if (var) { 
            double oldval = var->getVal();
            var->setVal(0);
            bModel->SetSnapshot( RooArgSet(*var)  );
            var->setVal(oldval);
         }
         else { 
            Error("StandardHypoTestInvDemo","Model %s has no valid poi",modelBName);
            return 0;
         }         
      }
   }

   // check model  has global observables when there are nuisance pdf
   // for the hybrid case the globobs are not needed
   if (type != 1 ) { 
      bool hasNuisParam = (sbModel->GetNuisanceParameters() && sbModel->GetNuisanceParameters()->getSize() > 0);
      bool hasGlobalObs = (sbModel->GetGlobalObservables() && sbModel->GetGlobalObservables()->getSize() > 0);
      if (hasNuisParam && !hasGlobalObs ) {  
         // try to see if model has nuisance parameters first 
         RooAbsPdf * constrPdf = RooStats::MakeNuisancePdf(*sbModel,"nuisanceConstraintPdf_sbmodel");
         if (constrPdf) { 
            Warning("StandardHypoTestInvDemo","Model %s has nuisance parameters but no global observables associated",sbModel->GetName());
            Warning("StandardHypoTestInvDemo","\tThe effect of the nuisance parameters will not be treated correctly ");
         }
      }
   }


  
   // run first a data fit 
  
   const RooArgSet * poiSet = sbModel->GetParametersOfInterest();
   RooRealVar *poi = (RooRealVar*)poiSet->first();
  
   std::cout << "StandardHypoTestInvDemo : POI initial value:   " << poi->GetName() << " = " << poi->getVal()   << std::endl;  
  
   // fit the data first (need to use constraint )
   TStopwatch tw; 

   bool doFit = initialFit;
   if (testStatType == 0 && initialFit == -1) doFit = false;  // case of LEP test statistic
   if (type == 3  && initialFit == -1) doFit = false;         // case of Asymptoticcalculator with nominal Asimov
   double poihat = 0;

   if (minimizerType.size()==0) minimizerType = ROOT::Math::MinimizerOptions::DefaultMinimizerType();
   else 
      ROOT::Math::MinimizerOptions::SetDefaultMinimizer(minimizerType.c_str());
    
   Info("StandardHypoTestInvDemo","Using %s as minimizer for computing the test statistic",
        ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str() );
   
   if (doFit)  { 

      // do the fit : By doing a fit the POI snapshot (for S+B)  is set to the fit value
      // and the nuisance parameters nominal values will be set to the fit value. 
      // This is relevant when using LEP test statistics

      Info( "StandardHypoTestInvDemo"," Doing a first fit to the observed data ");
      RooArgSet constrainParams;
      if (sbModel->GetNuisanceParameters() ) constrainParams.add(*sbModel->GetNuisanceParameters());
      RooStats::RemoveConstantParameters(&constrainParams);
      tw.Start(); 
      RooFitResult * fitres = sbModel->GetPdf()->fitTo(*data,InitialHesse(false), Hesse(false),
                                                       Minimizer(minimizerType.c_str(),"Migrad"), Strategy(0), PrintLevel(mPrintLevel), Constrain(constrainParams), Save(true) );
      if (fitres->status() != 0) { 
         Warning("StandardHypoTestInvDemo","Fit to the model failed - try with strategy 1 and perform first an Hesse computation");
         fitres = sbModel->GetPdf()->fitTo(*data,InitialHesse(true), Hesse(false),Minimizer(minimizerType.c_str(),"Migrad"), Strategy(1), PrintLevel(mPrintLevel+1), Constrain(constrainParams), Save(true) );
      }
      if (fitres->status() != 0) 
         Warning("StandardHypoTestInvDemo"," Fit still failed - continue anyway.....");
  
  
      poihat  = poi->getVal();
      std::cout << "StandardHypoTestInvDemo - Best Fit value : " << poi->GetName() << " = "  
                << poihat << " +/- " << poi->getError() << std::endl;
      std::cout << "Time for fitting : "; tw.Print(); 
  
      //save best fit value in the poi snapshot 
      sbModel->SetSnapshot(*sbModel->GetParametersOfInterest());
      std::cout << "StandardHypoTestInvo: snapshot of S+B Model " << sbModel->GetName() 
                << " is set to the best fit value" << std::endl;
  
   }

   // print a message in case of LEP test statistics because it affects result by doing or not doing a fit 
   if (testStatType == 0) {
      if (!doFit) 
         Info("StandardHypoTestInvDemo","Using LEP test statistic - an initial fit is not done and the TS will use the nuisances at the model value");
      else 
         Info("StandardHypoTestInvDemo","Using LEP test statistic - an initial fit has been done and the TS will use the nuisances at the best fit value");
   }


   // build test statistics and hypotest calculators for running the inverter 
  
   SimpleLikelihoodRatioTestStat slrts(*sbModel->GetPdf(),*bModel->GetPdf());

   // null parameters must includes snapshot of poi plus the nuisance values 
   RooArgSet nullParams(*sbModel->GetSnapshot());
   if (sbModel->GetNuisanceParameters()) nullParams.add(*sbModel->GetNuisanceParameters());
   if (sbModel->GetSnapshot()) slrts.SetNullParameters(nullParams);
   RooArgSet altParams(*bModel->GetSnapshot());
   if (bModel->GetNuisanceParameters()) altParams.add(*bModel->GetNuisanceParameters());
   if (bModel->GetSnapshot()) slrts.SetAltParameters(altParams);
  
   // ratio of profile likelihood - need to pass snapshot for the alt
   RatioOfProfiledLikelihoodsTestStat 
      ropl(*sbModel->GetPdf(), *bModel->GetPdf(), bModel->GetSnapshot());
   ropl.SetSubtractMLE(false);
   if (testStatType == 11) ropl.SetSubtractMLE(true);
   ropl.SetPrintLevel(mPrintLevel);
   ropl.SetMinimizer(minimizerType.c_str());
  
   ProfileLikelihoodTestStat profll(*sbModel->GetPdf());
   if (testStatType == 3) profll.SetOneSided(true);
   if (testStatType == 4) profll.SetSigned(true);
   profll.SetMinimizer(minimizerType.c_str());
   profll.SetPrintLevel(mPrintLevel);

   profll.SetReuseNLL(mOptimize);
   slrts.SetReuseNLL(mOptimize);
   ropl.SetReuseNLL(mOptimize);

   if (mOptimize) { 
      profll.SetStrategy(0);
      ropl.SetStrategy(0);
      ROOT::Math::MinimizerOptions::SetDefaultStrategy(0);
   }
  
   if (mMaxPoi > 0) poi->setMax(mMaxPoi);  // increase limit
  
   MaxLikelihoodEstimateTestStat maxll(*sbModel->GetPdf(),*poi); 
   NumEventsTestStat nevtts;

   AsymptoticCalculator::SetPrintLevel(mPrintLevel);
  
   // create the HypoTest calculator class 
   HypoTestCalculatorGeneric *  hc = 0;
   if (type == 0) hc = new FrequentistCalculator(*data, *bModel, *sbModel);
   else if (type == 1) hc = new HybridCalculator(*data, *bModel, *sbModel);
   // else if (type == 2 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, false, mAsimovBins);
   // else if (type == 3 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, true, mAsimovBins);  // for using Asimov data generated with nominal values 
   else if (type == 2 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, false );
   else if (type == 3 ) hc = new AsymptoticCalculator(*data, *bModel, *sbModel, true );  // for using Asimov data generated with nominal values 
   else {
      Error("StandardHypoTestInvDemo","Invalid - calculator type = %d supported values are only :\n\t\t\t 0 (Frequentist) , 1 (Hybrid) , 2 (Asymptotic) ",type);
      return 0;
   }
  
   // set the test statistic 
   TestStatistic * testStat = 0;
   if (testStatType == 0) testStat = &slrts;
   if (testStatType == 1 || testStatType == 11) testStat = &ropl;
   if (testStatType == 2 || testStatType == 3 || testStatType == 4) testStat = &profll;
   if (testStatType == 5) testStat = &maxll;
   if (testStatType == 6) testStat = &nevtts;

   if (testStat == 0) { 
      Error("StandardHypoTestInvDemo","Invalid - test statistic type = %d supported values are only :\n\t\t\t 0 (SLR) , 1 (Tevatron) , 2 (PLR), 3 (PLR1), 4(MLE)",testStatType);
      return 0;
   }
  
  
   ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler();
   if (toymcs && (type == 0 || type == 1) ) { 
      // look if pdf is number counting or extended
      if (sbModel->GetPdf()->canBeExtended() ) { 
         if (useNumberCounting)   Warning("StandardHypoTestInvDemo","Pdf is extended: but number counting flag is set: ignore it ");
      }
      else { 
         // for not extended pdf
         if (!useNumberCounting  )  { 
            int nEvents = data->numEntries();
            Info("StandardHypoTestInvDemo","Pdf is not extended: number of events to generate taken  from observed data set is %d",nEvents);
            toymcs->SetNEventsPerToy(nEvents);
         }
         else {
            Info("StandardHypoTestInvDemo","using a number counting pdf");
            toymcs->SetNEventsPerToy(1);
         }
      }

      toymcs->SetTestStatistic(testStat);
    
      if (data->isWeighted() && !mGenerateBinned) { 
         Info("StandardHypoTestInvDemo","Data set is weighted, nentries = %d and sum of weights = %8.1f but toy generation is unbinned - it would be faster to set mGenerateBinned to true\n",data->numEntries(), data->sumEntries());
      }
      toymcs->SetGenerateBinned(mGenerateBinned);
  
      toymcs->SetUseMultiGen(mOptimize);
    
      if (mGenerateBinned &&  sbModel->GetObservables()->getSize() > 2) { 
         Warning("StandardHypoTestInvDemo","generate binned is activated but the number of ovservable is %d. Too much memory could be needed for allocating all the bins",sbModel->GetObservables()->getSize() );
      }

      // set the random seed if needed
      if (mRandomSeed >= 0) RooRandom::randomGenerator()->SetSeed(mRandomSeed); 
    
   }
  
   // specify if need to re-use same toys
   if (reuseAltToys) {
      hc->UseSameAltToys();
   }
  
   if (type == 1) { 
      HybridCalculator *hhc = dynamic_cast<HybridCalculator*> (hc);
      assert(hhc);
    
      hhc->SetToys(ntoys,ntoys/mNToysRatio); // can use less ntoys for b hypothesis 
    
      // remove global observables from ModelConfig (this is probably not needed anymore in 5.32)
      bModel->SetGlobalObservables(RooArgSet() );
      sbModel->SetGlobalObservables(RooArgSet() );
    
    
      // check for nuisance prior pdf in case of nuisance parameters 
      if (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() ) {

         // fix for using multigen (does not work in this case)
         toymcs->SetUseMultiGen(false);
         ToyMCSampler::SetAlwaysUseMultiGen(false);

         RooAbsPdf * nuisPdf = 0; 
         if (nuisPriorName) nuisPdf = w->pdf(nuisPriorName);
         // use prior defined first in bModel (then in SbModel)
         if (!nuisPdf)  { 
            Info("StandardHypoTestInvDemo","No nuisance pdf given for the HybridCalculator - try to deduce  pdf from the model");
            if (bModel->GetPdf() && bModel->GetObservables() ) 
               nuisPdf = RooStats::MakeNuisancePdf(*bModel,"nuisancePdf_bmodel");
            else 
               nuisPdf = RooStats::MakeNuisancePdf(*sbModel,"nuisancePdf_sbmodel");
         }   
         if (!nuisPdf ) {
            if (bModel->GetPriorPdf())  { 
               nuisPdf = bModel->GetPriorPdf();
               Info("StandardHypoTestInvDemo","No nuisance pdf given - try to use %s that is defined as a prior pdf in the B model",nuisPdf->GetName());            
            }
            else { 
               Error("StandardHypoTestInvDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified or can be derived");
               return 0;
            }
         }
         assert(nuisPdf);
         Info("StandardHypoTestInvDemo","Using as nuisance Pdf ... " );
         nuisPdf->Print();
      
         const RooArgSet * nuisParams = (bModel->GetNuisanceParameters() ) ? bModel->GetNuisanceParameters() : sbModel->GetNuisanceParameters();
         RooArgSet * np = nuisPdf->getObservables(*nuisParams);
         if (np->getSize() == 0) { 
            Warning("StandardHypoTestInvDemo","Prior nuisance does not depend on nuisance parameters. They will be smeared in their full range");
         }
         delete np;
      
         hhc->ForcePriorNuisanceAlt(*nuisPdf);
         hhc->ForcePriorNuisanceNull(*nuisPdf);
      
      
      }
   } 
   else if (type == 2 || type == 3) { 
      if (testStatType == 3) ((AsymptoticCalculator*) hc)->SetOneSided(true);  
      if (testStatType != 2 && testStatType != 3)  
         Warning("StandardHypoTestInvDemo","Only the PL test statistic can be used with AsymptoticCalculator - use by default a two-sided PL");
   }
   else if (type == 0 || type == 1) 
      ((FrequentistCalculator*) hc)->SetToys(ntoys,ntoys/mNToysRatio); 

  
   // Get the result
   RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration);
  
  
  
   HypoTestInverter calc(*hc);
   calc.SetConfidenceLevel(0.95);
  
  
   calc.UseCLs(useCLs);
   calc.SetVerbose(true);
  
   // can speed up using proof-lite
   if (mUseProof && mNWorkers > 1) { 
      ProofConfig pc(*w, mNWorkers, "", kFALSE);
      toymcs->SetProofConfig(&pc);    // enable proof
   }
  
  
   if (npoints > 0) {
      if (poimin > poimax) { 
         // if no min/max given scan between MLE and +4 sigma 
         poimin = int(poihat);
         poimax = int(poihat +  4 * poi->getError());
      }
      std::cout << "Doing a fixed scan  in interval : " << poimin << " , " << poimax << std::endl;
      calc.SetFixedScan(npoints,poimin,poimax);
   }
   else { 
      //poi->setMax(10*int( (poihat+ 10 *poi->getError() )/10 ) );
      std::cout << "Doing an  automatic scan  in interval : " << poi->getMin() << " , " << poi->getMax() << std::endl;
   }
  
   tw.Start();
   HypoTestInverterResult * r = calc.GetInterval();
   std::cout << "Time to perform limit scan \n";
   tw.Print();
  
   if (mRebuild) {
      calc.SetCloseProof(1);
      tw.Start();
      SamplingDistribution * limDist = calc.GetUpperLimitDistribution(true,mNToyToRebuild);
      std::cout << "Time to rebuild distributions " << std::endl;
      tw.Print();
    
      if (limDist) { 
         std::cout << "expected up limit " << limDist->InverseCDF(0.5) << " +/- " 
                   << limDist->InverseCDF(0.16) << "  " 
                   << limDist->InverseCDF(0.84) << "\n"; 
      
         //update r to a new updated result object containing the rebuilt expected p-values distributions
         // (it will not recompute the expected limit)
         if (r) delete r;  // need to delete previous object since GetInterval will return a cloned copy
         r = calc.GetInterval();
      
      }
      else 
         std::cout << "ERROR : failed to re-build distributions " << std::endl; 
   }
  
   return r;
}
Exemple #8
0
//void RunToyScan5(TString fileName, double startVal, double stopVal, TString outFile) {
void frequentist(TString fileName) {
  cout << "Starting frequentist " << time(NULL) << endl;
  double startVal = 0;
  double stopVal = 200;
  TString outFile = "";

  int nToys = 1 ;
  int nscanpoints = 2 ;

  /*
  gROOT->LoadMacro("RooBetaPdf.cxx+") ;
  gROOT->LoadMacro("RooRatio.cxx+") ;
  gROOT->LoadMacro("RooPosDefCorrGauss.cxx+") ;
  */

  // get relevant objects out of the "ws" file

  TFile *file = TFile::Open(fileName);
  if(!file){
    cout <<"file not found" << endl;
    return;
  } 

  RooWorkspace* w = (RooWorkspace*) file->Get("workspace");
  if(!w){
    cout <<"workspace not found" << endl;
    return;
  }

  ModelConfig* mc = (ModelConfig*) w->obj("S+B_model");
  RooAbsData* data = w->data("data");

  if( !data || !mc ){
    w->Print();
    cout << "data or ModelConfig was not found" <<endl;
    return;
  }

  RooRealVar* myPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
  myPOI->setRange(0, 1000.);

  ModelConfig* bModel = (ModelConfig*) w->obj("B_model");
  ModelConfig* sbModel = (ModelConfig*) w->obj("S+B_model");

  ProfileLikelihoodTestStat profll(*sbModel->GetPdf());
  profll.SetPrintLevel(2);
  profll.SetOneSided(1);
  TestStatistic * testStat = &profll;

  HypoTestCalculatorGeneric *  hc = 0;
  hc = new FrequentistCalculator(*data, *bModel, *sbModel);
  
  ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler();
  toymcs->SetMaxToys(10000);
  toymcs->SetNEventsPerToy(1);
  toymcs->SetTestStatistic(testStat);


  ((FrequentistCalculator *)hc)->SetToys(nToys,nToys);
  
  HypoTestInverter calc(*hc);
  calc.SetConfidenceLevel(0.95);
  calc.UseCLs(true);
  //calc.SetVerbose(true);
  calc.SetVerbose(2);

  cout << "About to set fixed scan " << time(NULL) << endl;
  calc.SetFixedScan(nscanpoints,startVal,stopVal);
  cout << "About to do inverter " << time(NULL) << endl;
  HypoTestInverterResult * res_toysCLs_calculator = calc.GetInterval();

  cout << "CLs = " << res_toysCLs_calculator->UpperLimit() 
	    << "   CLs_exp = " << res_toysCLs_calculator->GetExpectedUpperLimit(0) 
	    << "   CLs_exp(-1s) = " << res_toysCLs_calculator->GetExpectedUpperLimit(-1) 
	    << "   CLs_exp(+1s) = " << res_toysCLs_calculator->GetExpectedUpperLimit(1) << endl ;

  /*
  // dump results string to output file
  ofstream outStream ;
  outStream.open(outFile,ios::app) ;
  
  outStream << "CLs = " << res_toysCLs_calculator->UpperLimit() 
	    << "   CLs_exp = " << res_toysCLs_calculator->GetExpectedUpperLimit(0) 
	    << "   CLs_exp(-1s) = " << res_toysCLs_calculator->GetExpectedUpperLimit(-1) 
	    << "   CLs_exp(+1s) = " << res_toysCLs_calculator->GetExpectedUpperLimit(1) << endl ;
  
  outStream.close() ;
  */


  cout << "End of frequentist " << time(NULL) << endl;
  return ;

}
// 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 OneSidedFrequentistUpperLimitWithBands(const char* infile = "",
                                            const char* workspaceName = "combined",
                                            const char* modelConfigName = "ModelConfig",
                                            const char* dataName = "obsData") {



   double confidenceLevel=0.95;
   int nPointsToScan = 20;
   int nToyMC = 200;

   // -------------------------------------------------------
   // 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";
      bool fileExist = !gSystem->AccessPathName(filename); // note opposite return code
      // if file does not exists generate with histfactory
      if (!fileExist) {
#ifdef _WIN32
         cout << "HistFactory file cannot be generated on Windows - exit" << endl;
         return;
#endif
         // 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;
      }

   }
   else
      filename = infile;

   // Try to open the file
   TFile *file = TFile::Open(filename);

   // if input file was specified byt not found, quit
   if(!file ){
      cout <<"StandardRooStatsDemoMacro: Input file " << filename << " is not found" << endl;
      return;
   }


   // -------------------------------------------------------
   // Now get the data and workspace

   // get the workspace out of the file
   RooWorkspace* w = (RooWorkspace*) file->Get(workspaceName);
   if(!w){
      cout <<"workspace not found" << endl;
      return;
   }

   // get the modelConfig out of the file
   ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

   // get the modelConfig out of the file
   RooAbsData* data = w->data(dataName);

   // make sure ingredients are found
   if(!data || !mc){
      w->Print();
      cout << "data or ModelConfig was not found" <<endl;
      return;
   }

   // -------------------------------------------------------
   // Now get the POI for convenience
   // you may want to adjust the range of your POI

   RooRealVar* firstPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
   /*  firstPOI->setMin(0);*/
   /*  firstPOI->setMax(10);*/

   // --------------------------------------------
   // Create and use the FeldmanCousins tool
   // to find and plot the 95% confidence interval
   // on the parameter of interest as specified
   // in the model config
   // REMEMBER, we will change the test statistic
   // so this is NOT a Feldman-Cousins interval
   FeldmanCousins fc(*data,*mc);
   fc.SetConfidenceLevel(confidenceLevel);
   /*  fc.AdditionalNToysFactor(0.25); // degrade/improve sampling that defines confidence belt*/
   /*  fc.UseAdaptiveSampling(true); // speed it up a bit, don't use for expected limits*/
   fc.SetNBins(nPointsToScan); // set how many points per parameter of interest to scan
   fc.CreateConfBelt(true); // save the information in the belt for plotting

   // -------------------------------------------------------
   // Feldman-Cousins is a unified limit by definition
   // but the tool takes care of a few things for us like which values
   // of the nuisance parameters should be used to generate toys.
   // so let's just change the test statistic and realize this is
   // no longer "Feldman-Cousins" but is a fully frequentist Neyman-Construction.
   /*  ProfileLikelihoodTestStatModified onesided(*mc->GetPdf());*/
   /*  fc.GetTestStatSampler()->SetTestStatistic(&onesided);*/
   /* ((ToyMCSampler*) fc.GetTestStatSampler())->SetGenerateBinned(true); */
   ToyMCSampler*  toymcsampler = (ToyMCSampler*) fc.GetTestStatSampler();
   ProfileLikelihoodTestStat* testStat = dynamic_cast<ProfileLikelihoodTestStat*>(toymcsampler->GetTestStatistic());
   testStat->SetOneSided(true);

   // Since this tool needs to throw toy MC the PDF needs to be
   // extended or the tool needs to know how many entries in a dataset
   // per pseudo experiment.
   // In the 'number counting form' where the entries in the dataset
   // are counts, and not values of discriminating variables, the
   // datasets typically only have one entry and the PDF is not
   // extended.
   if(!mc->GetPdf()->canBeExtended()){
      if(data->numEntries()==1)
         fc.FluctuateNumDataEntries(false);
      else
         cout <<"Not sure what to do about this model" <<endl;
   }

   // We can use PROOF to speed things along in parallel
   // However, the test statistic has to be installed on the workers
   // so either turn off PROOF or include the modified test statistic
   // in your `$ROOTSYS/roofit/roostats/inc` directory,
   // add the additional line to the LinkDef.h file,
   // and recompile root.
   if (useProof) {
      ProofConfig pc(*w, nworkers, "", false);
      toymcsampler->SetProofConfig(&pc); // enable proof
   }

   if(mc->GetGlobalObservables()){
      cout << "will use global observables for unconditional ensemble"<<endl;
      mc->GetGlobalObservables()->Print();
      toymcsampler->SetGlobalObservables(*mc->GetGlobalObservables());
   }


   // Now get the interval
   PointSetInterval* interval = fc.GetInterval();
   ConfidenceBelt* belt = fc.GetConfidenceBelt();

   // print out the interval on the first Parameter of Interest
   cout << "\n95% interval on " <<firstPOI->GetName()<<" is : ["<<
      interval->LowerLimit(*firstPOI) << ", "<<
      interval->UpperLimit(*firstPOI) <<"] "<<endl;

   // get observed UL and value of test statistic evaluated there
   RooArgSet tmpPOI(*firstPOI);
   double observedUL = interval->UpperLimit(*firstPOI);
   firstPOI->setVal(observedUL);
   double obsTSatObsUL = fc.GetTestStatSampler()->EvaluateTestStatistic(*data,tmpPOI);


   // Ask the calculator which points were scanned
   RooDataSet* parameterScan = (RooDataSet*) fc.GetPointsToScan();
   RooArgSet* tmpPoint;

   // make a histogram of parameter vs. threshold
   TH1F* histOfThresholds = new TH1F("histOfThresholds","",
                                       parameterScan->numEntries(),
                                       firstPOI->getMin(),
                                       firstPOI->getMax());
   histOfThresholds->GetXaxis()->SetTitle(firstPOI->GetName());
   histOfThresholds->GetYaxis()->SetTitle("Threshold");

   // loop through the points that were tested and ask confidence belt
   // what the upper/lower thresholds were.
   // For FeldmanCousins, the lower cut off is always 0
   for(Int_t i=0; i<parameterScan->numEntries(); ++i){
      tmpPoint = (RooArgSet*) parameterScan->get(i)->clone("temp");
      //cout <<"get threshold"<<endl;
      double arMax = belt->GetAcceptanceRegionMax(*tmpPoint);
      double poiVal = tmpPoint->getRealValue(firstPOI->GetName()) ;
      histOfThresholds->Fill(poiVal,arMax);
   }
   TCanvas* c1 = new TCanvas();
   c1->Divide(2);
   c1->cd(1);
   histOfThresholds->SetMinimum(0);
   histOfThresholds->Draw();
   c1->cd(2);

   // -------------------------------------------------------
   // Now we generate the expected bands and power-constraint

   // First: find parameter point for mu=0, with conditional MLEs for nuisance parameters
   RooAbsReal* nll = mc->GetPdf()->createNLL(*data);
   RooAbsReal* profile = nll->createProfile(*mc->GetParametersOfInterest());
   firstPOI->setVal(0.);
   profile->getVal(); // this will do fit and set nuisance parameters to profiled values
   RooArgSet* poiAndNuisance = new RooArgSet();
   if(mc->GetNuisanceParameters())
      poiAndNuisance->add(*mc->GetNuisanceParameters());
   poiAndNuisance->add(*mc->GetParametersOfInterest());
   w->saveSnapshot("paramsToGenerateData",*poiAndNuisance);
   RooArgSet* paramsToGenerateData = (RooArgSet*) poiAndNuisance->snapshot();
   cout << "\nWill use these parameter points to generate pseudo data for bkg only" << endl;
   paramsToGenerateData->Print("v");


   RooArgSet unconditionalObs;
   unconditionalObs.add(*mc->GetObservables());
   unconditionalObs.add(*mc->GetGlobalObservables()); // comment this out for the original conditional ensemble

   double CLb=0;
   double CLbinclusive=0;

   // Now we generate background only and find distribution of upper limits
   TH1F* histOfUL = new TH1F("histOfUL","",100,0,firstPOI->getMax());
   histOfUL->GetXaxis()->SetTitle("Upper Limit (background only)");
   histOfUL->GetYaxis()->SetTitle("Entries");
   for(int imc=0; imc<nToyMC; ++imc){

      // set parameters back to values for generating pseudo data
      //    cout << "\n get current nuis, set vals, print again" << endl;
      w->loadSnapshot("paramsToGenerateData");
      //    poiAndNuisance->Print("v");

      RooDataSet* toyData = 0;
      // now generate a toy dataset
      if(!mc->GetPdf()->canBeExtended()){
         if(data->numEntries()==1)
            toyData = mc->GetPdf()->generate(*mc->GetObservables(),1);
         else
            cout <<"Not sure what to do about this model" <<endl;
      } else{
         //      cout << "generating extended dataset"<<endl;
         toyData = mc->GetPdf()->generate(*mc->GetObservables(),Extended());
      }

      // generate global observables
      // need to be careful for simpdf
      //    RooDataSet* globalData = mc->GetPdf()->generate(*mc->GetGlobalObservables(),1);

      RooSimultaneous* simPdf = dynamic_cast<RooSimultaneous*>(mc->GetPdf());
      if(!simPdf){
         RooDataSet *one = mc->GetPdf()->generate(*mc->GetGlobalObservables(), 1);
         const RooArgSet *values = one->get();
         RooArgSet *allVars = mc->GetPdf()->getVariables();
         *allVars = *values;
         delete allVars;
         delete values;
         delete one;
      } else {

         //try fix for sim pdf
         TIterator* iter = simPdf->indexCat().typeIterator() ;
         RooCatType* tt = NULL;
         while((tt=(RooCatType*) iter->Next())) {

            // Get pdf associated with state from simpdf
            RooAbsPdf* pdftmp = simPdf->getPdf(tt->GetName()) ;

            // Generate only global variables defined by the pdf associated with this state
            RooArgSet* globtmp = pdftmp->getObservables(*mc->GetGlobalObservables()) ;
            RooDataSet* tmp = pdftmp->generate(*globtmp,1) ;

            // Transfer values to output placeholder
            *globtmp = *tmp->get(0) ;

            // Cleanup
            delete globtmp ;
            delete tmp ;
         }
      }

      //    globalData->Print("v");
      //    unconditionalObs = *globalData->get();
      //    mc->GetGlobalObservables()->Print("v");
      //    delete globalData;
      //    cout << "toy data = " << endl;
      //    toyData->get()->Print("v");

      // get test stat at observed UL in observed data
      firstPOI->setVal(observedUL);
      double toyTSatObsUL = fc.GetTestStatSampler()->EvaluateTestStatistic(*toyData,tmpPOI);
      //    toyData->get()->Print("v");
      //    cout <<"obsTSatObsUL " <<obsTSatObsUL << "toyTS " << toyTSatObsUL << endl;
      if(obsTSatObsUL < toyTSatObsUL) // not sure about <= part yet
         CLb+= (1.)/nToyMC;
      if(obsTSatObsUL <= toyTSatObsUL) // not sure about <= part yet
         CLbinclusive+= (1.)/nToyMC;


      // loop over points in belt to find upper limit for this toy data
      double thisUL = 0;
      for(Int_t i=0; i<parameterScan->numEntries(); ++i){
         tmpPoint = (RooArgSet*) parameterScan->get(i)->clone("temp");
         double arMax = belt->GetAcceptanceRegionMax(*tmpPoint);
         firstPOI->setVal( tmpPoint->getRealValue(firstPOI->GetName()) );
         //   double thisTS = profile->getVal();
         double thisTS = fc.GetTestStatSampler()->EvaluateTestStatistic(*toyData,tmpPOI);

         //   cout << "poi = " << firstPOI->getVal()
         // << " max is " << arMax << " this profile = " << thisTS << endl;
         //      cout << "thisTS = " << thisTS<<endl;
         if(thisTS<=arMax){
            thisUL = firstPOI->getVal();
         } else{
            break;
         }
      }



      /*
      // loop over points in belt to find upper limit for this toy data
      double thisUL = 0;
      for(Int_t i=0; i<histOfThresholds->GetNbinsX(); ++i){
         tmpPoint = (RooArgSet*) parameterScan->get(i)->clone("temp");
         cout <<"----------------  "<<i<<endl;
         tmpPoint->Print("v");
         cout << "from hist " << histOfThresholds->GetBinCenter(i+1) <<endl;
         double arMax = histOfThresholds->GetBinContent(i+1);
         // cout << " threhold from Hist = aMax " << arMax<<endl;
         // double arMax2 = belt->GetAcceptanceRegionMax(*tmpPoint);
         // cout << "from scan arMax2 = "<< arMax2 << endl; // not the same due to TH1F not TH1D
         // cout << "scan - hist" << arMax2-arMax << endl;
         firstPOI->setVal( histOfThresholds->GetBinCenter(i+1));
         //   double thisTS = profile->getVal();
         double thisTS = fc.GetTestStatSampler()->EvaluateTestStatistic(*toyData,tmpPOI);

         //   cout << "poi = " << firstPOI->getVal()
         // << " max is " << arMax << " this profile = " << thisTS << endl;
         //      cout << "thisTS = " << thisTS<<endl;

         // NOTE: need to add a small epsilon term for single precision vs. double precision
         if(thisTS<=arMax + 1e-7){
            thisUL = firstPOI->getVal();
         } else{
            break;
         }
      }
      */

      histOfUL->Fill(thisUL);

      // for few events, data is often the same, and UL is often the same
      //    cout << "thisUL = " << thisUL<<endl;

      delete toyData;
   }
   histOfUL->Draw();
   c1->SaveAs("one-sided_upper_limit_output.pdf");

   // if you want to see a plot of the sampling distribution for a particular scan point:
   /*
   SamplingDistPlot sampPlot;
   int indexInScan = 0;
   tmpPoint = (RooArgSet*) parameterScan->get(indexInScan)->clone("temp");
   firstPOI->setVal( tmpPoint->getRealValue(firstPOI->GetName()) );
   toymcsampler->SetParametersForTestStat(tmpPOI);
   SamplingDistribution* samp = toymcsampler->GetSamplingDistribution(*tmpPoint);
   sampPlot.AddSamplingDistribution(samp);
   sampPlot.Draw();
      */

   // Now find bands and power constraint
   Double_t* bins = histOfUL->GetIntegral();
   TH1F* cumulative = (TH1F*) histOfUL->Clone("cumulative");
   cumulative->SetContent(bins);
   double band2sigDown, band1sigDown, bandMedian, band1sigUp,band2sigUp;
   for(int i=1; i<=cumulative->GetNbinsX(); ++i){
      if(bins[i]<RooStats::SignificanceToPValue(2))
         band2sigDown=cumulative->GetBinCenter(i);
      if(bins[i]<RooStats::SignificanceToPValue(1))
         band1sigDown=cumulative->GetBinCenter(i);
      if(bins[i]<0.5)
         bandMedian=cumulative->GetBinCenter(i);
      if(bins[i]<RooStats::SignificanceToPValue(-1))
         band1sigUp=cumulative->GetBinCenter(i);
      if(bins[i]<RooStats::SignificanceToPValue(-2))
         band2sigUp=cumulative->GetBinCenter(i);
   }
   cout << "-2 sigma  band " << band2sigDown << endl;
   cout << "-1 sigma  band " << band1sigDown << " [Power Constraint)]" << endl;
   cout << "median of band " << bandMedian << endl;
   cout << "+1 sigma  band " << band1sigUp << endl;
   cout << "+2 sigma  band " << band2sigUp << endl;

   // print out the interval on the first Parameter of Interest
   cout << "\nobserved 95% upper-limit "<< interval->UpperLimit(*firstPOI) <<endl;
   cout << "CLb strict [P(toy>obs|0)] for observed 95% upper-limit "<< CLb <<endl;
   cout << "CLb inclusive [P(toy>=obs|0)] for observed 95% upper-limit "<< CLbinclusive <<endl;

   delete profile;
   delete nll;

}
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();
     }
  }
*/




}
Exemple #12
0
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");
}
void StandardHistFactoryPlotsWithCategories(const char* infile = "",
                                            const char* workspaceName = "combined",
                                            const char* modelConfigName = "ModelConfig",
                                            const char* dataName = "obsData"){


   double nSigmaToVary=5.;
   double muVal=0;
   bool doFit=false;

   // -------------------------------------------------------
   // 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";
      bool fileExist = !gSystem->AccessPathName(filename); // note opposite return code
                                                           // if file does not exists generate with histfactory
      if (!fileExist) {
#ifdef _WIN32
         cout << "HistFactory file cannot be generated on Windows - exit" << endl;
         return;
#endif
         // 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;
      }

   }
   else
      filename = infile;

   // Try to open the file
   TFile *file = TFile::Open(filename);

   // if input file was specified byt not found, quit
   if(!file ){
      cout <<"StandardRooStatsDemoMacro: Input file " << filename << " is not found" << 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;
   }

   // get the modelConfig out of the file
   ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

   // get the modelConfig out of the file
   RooAbsData* data = w->data(dataName);

   // make sure ingredients are found
   if(!data || !mc){
      w->Print();
      cout << "data or ModelConfig was not found" <<endl;
      return;
   }

   // -------------------------------------------------------
   // now use the profile inspector

   RooRealVar* obs = (RooRealVar*)mc->GetObservables()->first();
   TList* list = new TList();


   RooRealVar * firstPOI = dynamic_cast<RooRealVar*>(mc->GetParametersOfInterest()->first());

   firstPOI->setVal(muVal);
   //  firstPOI->setConstant();
   if(doFit){
      mc->GetPdf()->fitTo(*data);
   }

   // -------------------------------------------------------


   mc->GetNuisanceParameters()->Print("v");
   int  nPlotsMax = 1000;
   cout <<" check expectedData by category"<<endl;
   RooDataSet* simData=NULL;
   RooSimultaneous* simPdf = NULL;
   if(strcmp(mc->GetPdf()->ClassName(),"RooSimultaneous")==0){
      cout <<"Is a simultaneous PDF"<<endl;
      simPdf = (RooSimultaneous *)(mc->GetPdf());
   } else {
      cout <<"Is not a simultaneous PDF"<<endl;
   }



   if(doFit) {
      RooCategory* channelCat = (RooCategory*) (&simPdf->indexCat());
      TIterator* iter = channelCat->typeIterator() ;
      RooCatType* tt = NULL;
      tt=(RooCatType*) iter->Next();
      RooAbsPdf* pdftmp = ((RooSimultaneous*)mc->GetPdf())->getPdf(tt->GetName()) ;
      RooArgSet* obstmp = pdftmp->getObservables(*mc->GetObservables()) ;
      obs = ((RooRealVar*)obstmp->first());
      RooPlot* frame = obs->frame();
      cout <<Form("%s==%s::%s",channelCat->GetName(),channelCat->GetName(),tt->GetName())<<endl;
      cout << tt->GetName() << " " << channelCat->getLabel() <<endl;
      data->plotOn(frame,MarkerSize(1),Cut(Form("%s==%s::%s",channelCat->GetName(),channelCat->GetName(),tt->GetName())),DataError(RooAbsData::None));

      Double_t normCount = data->sumEntries(Form("%s==%s::%s",channelCat->GetName(),channelCat->GetName(),tt->GetName())) ;

      pdftmp->plotOn(frame,LineWidth(2.),Normalization(normCount,RooAbsReal::NumEvent)) ;
      frame->Draw();
      cout <<"expected events = " << mc->GetPdf()->expectedEvents(*data->get()) <<endl;
      return;
   }



   int nPlots=0;
   if(!simPdf){

      TIterator* it = mc->GetNuisanceParameters()->createIterator();
      RooRealVar* var = NULL;
      while( (var = (RooRealVar*) it->Next()) != NULL){
         RooPlot* frame = obs->frame();
         frame->SetYTitle(var->GetName());
         data->plotOn(frame,MarkerSize(1));
         var->setVal(0);
         mc->GetPdf()->plotOn(frame,LineWidth(1.));
         var->setVal(1);
         mc->GetPdf()->plotOn(frame,LineColor(kRed),LineStyle(kDashed),LineWidth(1));
         var->setVal(-1);
         mc->GetPdf()->plotOn(frame,LineColor(kGreen),LineStyle(kDashed),LineWidth(1));
         list->Add(frame);
         var->setVal(0);
      }


   } else {
      RooCategory* channelCat = (RooCategory*) (&simPdf->indexCat());
      //    TIterator* iter = simPdf->indexCat().typeIterator() ;
      TIterator* iter = channelCat->typeIterator() ;
      RooCatType* tt = NULL;
      while(nPlots<nPlotsMax && (tt=(RooCatType*) iter->Next())) {

         cout << "on type " << tt->GetName() << " " << endl;
         // Get pdf associated with state from simpdf
         RooAbsPdf* pdftmp = simPdf->getPdf(tt->GetName()) ;

         // Generate observables defined by the pdf associated with this state
         RooArgSet* obstmp = pdftmp->getObservables(*mc->GetObservables()) ;
         //      obstmp->Print();


         obs = ((RooRealVar*)obstmp->first());

         TIterator* it = mc->GetNuisanceParameters()->createIterator();
         RooRealVar* var = NULL;
         while(nPlots<nPlotsMax && (var = (RooRealVar*) it->Next())){
            TCanvas* c2 = new TCanvas("c2");
            RooPlot* frame = obs->frame();
            frame->SetName(Form("frame%d",nPlots));
            frame->SetYTitle(var->GetName());

            cout <<Form("%s==%s::%s",channelCat->GetName(),channelCat->GetName(),tt->GetName())<<endl;
            cout << tt->GetName() << " " << channelCat->getLabel() <<endl;
            data->plotOn(frame,MarkerSize(1),Cut(Form("%s==%s::%s",channelCat->GetName(),channelCat->GetName(),tt->GetName())),DataError(RooAbsData::None));

            Double_t normCount = data->sumEntries(Form("%s==%s::%s",channelCat->GetName(),channelCat->GetName(),tt->GetName())) ;

            if(strcmp(var->GetName(),"Lumi")==0){
               cout <<"working on lumi"<<endl;
               var->setVal(w->var("nominalLumi")->getVal());
               var->Print();
            } else{
               var->setVal(0);
            }
            // w->allVars().Print("v");
            // mc->GetNuisanceParameters()->Print("v");
            // pdftmp->plotOn(frame,LineWidth(2.));
            // mc->GetPdf()->plotOn(frame,LineWidth(2.),Slice(*channelCat,tt->GetName()),ProjWData(*data));
            //pdftmp->plotOn(frame,LineWidth(2.),Slice(*channelCat,tt->GetName()),ProjWData(*data));
            normCount = pdftmp->expectedEvents(*obs);
            pdftmp->plotOn(frame,LineWidth(2.),Normalization(normCount,RooAbsReal::NumEvent)) ;

            if(strcmp(var->GetName(),"Lumi")==0){
               cout <<"working on lumi"<<endl;
               var->setVal(w->var("nominalLumi")->getVal()+0.05);
               var->Print();
            } else{
               var->setVal(nSigmaToVary);
            }
            // pdftmp->plotOn(frame,LineColor(kRed),LineStyle(kDashed),LineWidth(2));
            // mc->GetPdf()->plotOn(frame,LineColor(kRed),LineStyle(kDashed),LineWidth(2.),Slice(*channelCat,tt->GetName()),ProjWData(*data));
            //pdftmp->plotOn(frame,LineColor(kRed),LineStyle(kDashed),LineWidth(2.),Slice(*channelCat,tt->GetName()),ProjWData(*data));
            normCount = pdftmp->expectedEvents(*obs);
            pdftmp->plotOn(frame,LineWidth(2.),LineColor(kRed),LineStyle(kDashed),Normalization(normCount,RooAbsReal::NumEvent)) ;

            if(strcmp(var->GetName(),"Lumi")==0){
               cout <<"working on lumi"<<endl;
               var->setVal(w->var("nominalLumi")->getVal()-0.05);
               var->Print();
            } else{
               var->setVal(-nSigmaToVary);
            }
            // pdftmp->plotOn(frame,LineColor(kGreen),LineStyle(kDashed),LineWidth(2));
            // mc->GetPdf()->plotOn(frame,LineColor(kGreen),LineStyle(kDashed),LineWidth(2),Slice(*channelCat,tt->GetName()),ProjWData(*data));
            //pdftmp->plotOn(frame,LineColor(kGreen),LineStyle(kDashed),LineWidth(2),Slice(*channelCat,tt->GetName()),ProjWData(*data));
            normCount = pdftmp->expectedEvents(*obs);
            pdftmp->plotOn(frame,LineWidth(2.),LineColor(kGreen),LineStyle(kDashed),Normalization(normCount,RooAbsReal::NumEvent)) ;



            // set them back to normal
            if(strcmp(var->GetName(),"Lumi")==0){
               cout <<"working on lumi"<<endl;
               var->setVal(w->var("nominalLumi")->getVal());
               var->Print();
            } else{
               var->setVal(0);
            }

            list->Add(frame);

            // quit making plots
            ++nPlots;

            frame->Draw();
            c2->SaveAs(Form("%s_%s_%s.pdf",tt->GetName(),obs->GetName(),var->GetName()));
            delete c2;
         }
      }
   }



   // -------------------------------------------------------


   // 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();
   }





}
void HypoTestInvDemo(const char * fileName ="GausModel_b.root",
                     const char * wsName = "w",
                     const char * modelSBName = "model_sb",
                     const char * modelBName = "model_b",
                     const char * dataName = "data_obs",                  
                     int type = 0,  // calculator type 
                     int testStatType = 0, // test stat type
                     int npoints = 10,   
                     int ntoys=1000,
                     bool useCls = true )
{ 
   /*
    type = 0 Freq calculator 
    type = 1 Hybrid 

    testStatType = 0 LEP
                 = 1 Tevatron 
                 = 2 PL


   */

   if (fileName==0) { 
      std::cout << "give input filename " << std::endl;
      return; 
   }
   TFile * file = new TFile(fileName); 

   RooWorkspace * w = dynamic_cast<RooWorkspace*>( file->Get(wsName) );
   if (!w) {      
      return; 
   }
   w->Print();


   RooAbsData * data = w->data(dataName); 
   if (!data) { 
      Error("HypoTestDemo","Not existing data %s",dataName);
   }

   
   // get models from WS
  // get the modelConfig out of the file
  ModelConfig* bModel = (ModelConfig*) w->obj(modelBName);
  ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName);


   SimpleLikelihoodRatioTestStat slrts(*bModel->GetPdf(),*sbModel->GetPdf());
   slrts.SetNullParameters(*bModel->GetSnapshot());
   slrts.SetAltParameters(*sbModel->GetSnapshot());

   RatioOfProfiledLikelihoodsTestStat 
   ropl(*bModel->GetPdf(), *sbModel->GetPdf(), sbModel->GetSnapshot());
   ropl.SetSubtractMLE(false);
   
   ProfileLikelihoodTestStat profll(*sbModel->GetPdf());
   profll.SetOneSided(0);

   TestStatistic * testStat = &slrts;
   if (testStatType == 1) testStat = &ropl;
   if (testStatType == 2) testStat = &profll;
  
   
   HypoTestCalculatorGeneric *  hc = 0;
   if (type == 0) hc = new FrequentistCalculator(*data, *sbModel, *bModel);
   else new HybridCalculator(*data, *sbModel, *bModel);

   ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler();
   //toymcs->SetNEventsPerToy(1);
   toymcs->SetTestStatistic(testStat);


    if (type == 1) { 
      HybridCalculator *hhc = (HybridCalculator*) hc;
      hhc->SetToys(ntoys,ntoys); 
      // hhc->ForcePriorNuisanceAlt(*pdfNuis);
      // hhc->ForcePriorNuisanceNull(*pdfNuis);
   } 
   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();
   //poi->setVal(30);
   //poi->setError(10);


   HypoTestInverter calc(*hc);
   // GENA: for two-sided interval
   //calc.SetConfidenceLevel(0.95);
   // GENA: for 95% upper limit
   calc.SetConfidenceLevel(0.90);

   calc.UseCLs(useCls);
   calc.SetVerbose(true);

   // can spped up using proof
   ProofConfig pc(*w, 2, "workers=2", kFALSE);
   //ProofConfig pc(*w, 30, "localhost", kFALSE);
   //ToyMCSampler * toymcs = dynamic_cast<ToyMCSampler *> (calc.GetHypoTestCalculator()->GetTestStatSampler() );
   // GENA: disable proof for now
   //toymcs->SetProofConfig(&pc);    // enable proof

   
   if (npoints > 0) {
     // GENA
     double poimin = TMath::Max(poihat -   4 * poi->getError(), 0.0);
     //poimin = poihat;
     double poimax = poihat +  4 * poi->getError();
     poimin = 0; 
     poimax = 20;
     //double poimin = poi->getMin();
     //double poimax = poi->getMax();
     std::cout << "Doing a fixed scan  in interval : " << poimin << " , " << poimax << std::endl;
     calc.SetFixedScan(npoints,poimin,poimax);
   }

   HypoTestInverterResult * r = calc.GetInterval();

   // write to a file the results
   TString resultFileName = (useCls) ? "CLs_" : "Cls+b_";
   resultFileName += fileName;

   // GENA
   //TFile * file = new TFile(resultFileName,"RECREATE");
   file = new TFile(resultFileName,"RECREATE");
   r->Write();
   file->Close();                                                                     

  double ulError = r->UpperLimitEstimatedError();
  double upperLimit = r->UpperLimit();
  std::cout << "The computed upper limit is: " << upperLimit << std::endl;
  std::cout << "an estimated error on this upper limit is: " << ulError << std::endl;

  // check using interpolation
  // double interpLimit = r->FindInterpolatedLimit(1.-r->ConfidenceLevel() );
  // cout << "The computer interpolated limits is " << interpLimit << endl;

  const int nEntries = r->ArraySize();

  std::vector<Double_t> xArray(nEntries);
  std::vector<Double_t> yArray(nEntries);
  std::vector<Double_t> yErrArray(nEntries);
  for (int i=0; i<nEntries; i++) {
    xArray[i] = r->GetXValue(i);
    yArray[i] = r->GetYValue(i);
    yErrArray[i] = r->GetYError(i);
    std::cout << xArray[i] << " , " << yArray[i] << " err = " << yErrArray[i] << std::endl;
  }
 

   // see expected result (bands)
   TGraph * g0 = new TGraph(nEntries);
   TGraphAsymmErrors * g1 = new TGraphAsymmErrors(nEntries);
   TGraphAsymmErrors * g2l = new TGraphAsymmErrors(nEntries);
   TGraphAsymmErrors * g2u = new TGraphAsymmErrors(nEntries);
   double p[7]; 
   double q[7];
   p[0] = ROOT::Math::normal_cdf(-2);
   p[1] = ROOT::Math::normal_cdf(-1.5);
   p[2] = ROOT::Math::normal_cdf(-1);
   p[3] = 0.5;
   p[4] = ROOT::Math::normal_cdf(1);
   p[5] = ROOT::Math::normal_cdf(1.5);
   p[6] = ROOT::Math::normal_cdf(2);
   for (int i=0; i<nEntries; i++) {
      SamplingDistribution * s = r->GetExpectedDistribution(i);
      // GENA
      //const std::vector<double> & values = s->GetSamplingDistribution();
      const std::vector<Double_t> & cValues = s->GetSamplingDistribution();
      std::vector<Double_t> values;
      for (std::vector<Double_t>::const_iterator val = cValues.begin();
	   val != cValues.end();
	   ++val) values.push_back(*val);
      TMath::Quantiles(values.size(), 7, &values[0],q,p,false);
      double p0 = q[3];
      double p2l =  q[1];
      double p2u =  q[5];
      g0->SetPoint(i, r->GetXValue(i), p0 ) ;
      g1->SetPoint(i, r->GetXValue(i),  p0);
      g2l->SetPoint(i, r->GetXValue(i), p2l);
      g2u->SetPoint(i, r->GetXValue(i), p2u);
      //g2->SetPoint(i, r->GetXValue(i), s->InverseCDF(0.50));
      g1->SetPointEYlow(i, q[3] - q[2]); // -1 sigma errorr   
      g1->SetPointEYhigh(i, q[4] - q[3]);//+1 sigma error

      g2l->SetPointEYlow(i, q[1]-q[0]);   // -2 -- -1 sigma error
      g2l->SetPointEYhigh(i, q[2]-q[1]);

      g2u->SetPointEYlow(i, q[5]-q[4]);
      g2u->SetPointEYhigh(i, q[6]-q[5]);


      if (plotHypoTestResult) { 
         HypoTestResult * hr = new HypoTestResult();
         hr->SetNullDistribution( r->GetBackgroundDistribution() );
         hr->SetAltDistribution( r->GetSignalAndBackgroundDistribution(i) );
         new TCanvas();
         HypoTestPlot * pl = new HypoTestPlot(*hr);
         pl->Draw();
      }
  }

   HypoTestInverterPlot *plot = new HypoTestInverterPlot("result","",r);
   TGraphErrors * g = plot->MakePlot();

   g->Draw("APL");   
   g2l->SetFillColor(kYellow);
   g2l->Draw("3");
   g2u->SetFillColor(kYellow);
   g2u->Draw("3");
   g1->SetFillColor(kGreen);
   g1->Draw("3");
   g0->SetLineColor(kBlue);
   g0->SetLineStyle(2);
   g0->SetLineWidth(2);
   g0->Draw("L");

   //g1->Draw("P");
   //g2->Draw("P");
   g->SetLineWidth(2);
   g->Draw("PL");   

   // GENA: two-sided interval
   //double alpha = 1.-r->ConfidenceLevel();
   // GENA: upper limit
   double alpha = (1.-r->ConfidenceLevel())/2.0;
   double x1 = g->GetXaxis()->GetXmin();
   double x2 = g->GetXaxis()->GetXmax();
   TLine * line = new TLine(x1, alpha, x2,alpha);
   line->SetLineColor(kRed);
   line->Draw();

   // see the expected limit and -1 +1 sigma bands
   // SamplingDistribution * limits = r->GetUpperLimitDistribution();

   // std::cout << " expected limit (median) " << limits->InverseCDF(0.50) << std::endl;
   // std::cout << " expected limit (-1 sig) " << limits->InverseCDF((ROOT::Math::normal_cdf(-1))) << std::endl;
   // std::cout << " expected limit (+1 sig) " << limits->InverseCDF((ROOT::Math::normal_cdf(+1))) << std::endl;
   
   tw.Print();

}
void StandardBayesianNumericalDemo(const char* infile = "",
		      const char* workspaceName = "combined",
		      const char* modelConfigName = "ModelConfig",
		      const char* dataName = "obsData"){

  /////////////////////////////////////////////////////////////
  // First part is just to access a user-defined file 
  // or create the standard example file if it doesn't exist
  ////////////////////////////////////////////////////////////
  TString filename = infile;
  if (filename.IsNull()) { 
    filename = "results/example_combined_GaussExample_model.root";
    std::cout << "Use standard file generated with HistFactory : " << filename << std::endl;
  }

  // Check if example input file exists
  TFile *file = TFile::Open(filename);

  // if input file was specified but not found, quit
  if(!file && !TString(infile).IsNull()){
     cout <<"file " << filename << " 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;
  }

  // get the modelConfig out of the file
  ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

  // get the modelConfig out of the file
  RooAbsData* data = w->data(dataName);

  // make sure ingredients are found
  if(!data || !mc){
    w->Print();
    cout << "data or ModelConfig was not found" <<endl;
    return;
  }

  /////////////////////////////////////////////
  // create and use the BayesianCalculator
  // to find and plot the 95% credible interval
  // on the parameter of interest as specified
  // in the model config
  
  // before we do that, we must specify our prior
  // it belongs in the model config, but it may not have
  // been specified
  RooUniform prior("prior","",*mc->GetParametersOfInterest());
  w->import(prior);
  mc->SetPriorPdf(*w->pdf("prior"));

  // do without systematics
  //mc->SetNuisanceParameters(RooArgSet() );

  
  BayesianCalculator bayesianCalc(*data,*mc);
  bayesianCalc.SetConfidenceLevel(0.95); // 95% interval

  // default of the calculator is central interval.  here use shortest , central or upper limit depending on input
  // doing a shortest interval might require a longer time since it requires a scan of the posterior function
  if (intervalType == 0)  bayesianCalc.SetShortestInterval(); // for shortest interval
  if (intervalType == 1)  bayesianCalc.SetLeftSideTailFraction(0.5); // for central interval
  if (intervalType == 2)  bayesianCalc.SetLeftSideTailFraction(0.); // for upper limit

  if (!integrationType.IsNull() ) { 
     bayesianCalc.SetIntegrationType(integrationType); // set integrationType
     bayesianCalc.SetNumIters(nToys); // set number of ietrations (i.e. number of toys for MC integrations)
  }

  // compute interval by scanning the posterior function
  if (scanPosterior)   
     bayesianCalc.SetScanOfPosterior(nScanPoints);


  SimpleInterval* interval = bayesianCalc.GetInterval();

  // print out the iterval on the first Parameter of Interest
  RooRealVar* firstPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
  cout << "\n95% interval on " <<firstPOI->GetName()<<" is : ["<<
    interval->LowerLimit() << ", "<<
    interval->UpperLimit() <<"] "<<endl;


  // make a plot 
  // since plotting may take a long time (it requires evaluating 
  // the posterior in many points) this command will speed up 
  // by reducing the number of points to plot - do 50

  cout << "\nDrawing plot of posterior function....." << endl;

  bayesianCalc.SetScanOfPosterior(nScanPoints);

  RooPlot * plot = bayesianCalc.GetPosteriorPlot();
  plot->Draw();  

}
// 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; 
}
Exemple #17
0
result fit_toy(RooWorkspace* wspace, int n, const RooArgSet* globals) {
    RooRandom::randomGenerator()->SetSeed(0);
    // TFile f(filename);
    // RooWorkspace *wspace = (RooWorkspace*)f.Get("combined");
    ModelConfig* model = (ModelConfig*)wspace->obj("ModelConfig");

    RooAbsPdf* pdf;
    pdf = model->GetPdf();

    RooAbsPdf* top_constraint = (RooAbsPdf*)wspace->obj("top_ratio_constraint");
    RooAbsPdf* vv_constraint = (RooAbsPdf*)wspace->obj("vv_ratio_constraint");
    RooAbsPdf* top_vv_constraint_sf = (RooAbsPdf*)wspace->obj("top_vv_ratio_sf_constraint");
    RooAbsPdf* top_vv_constraint_of = (RooAbsPdf*)wspace->obj("top_vv_ratio_of_constraint");


    // generate constraint global observables
    RooRealVar *nom_top_ratio = (RooRealVar*)wspace->obj("nom_top_ratio");
    nom_top_ratio->setRange(0, 100);
    RooRealVar *nom_vv_ratio = (RooRealVar*)wspace->obj("nom_vv_ratio");
    nom_vv_ratio->setRange(0,100);
    RooRealVar *nom_top_vv_ratio_sf = (RooRealVar*)wspace->obj("nom_top_vv_ratio_sf");
    nom_top_vv_ratio_sf->setRange(0,100);
    RooRealVar *nom_top_vv_ratio_of = (RooRealVar*)wspace->obj("nom_top_vv_ratio_of");
    nom_top_vv_ratio_of->setRange(0,100);

    RooDataSet *nom_top_generated = top_constraint->generateSimGlobal(RooArgSet(*nom_top_ratio), 1);
    nom_top_ratio->setVal(((RooRealVar*)nom_top_generated->get(0)->find("nom_top_ratio"))->getVal());

    RooDataSet *nom_vv_generated = vv_constraint->generateSimGlobal(RooArgSet(*nom_vv_ratio), 1);
    nom_vv_ratio->setVal(((RooRealVar*)nom_vv_generated->get(0)->find("nom_vv_ratio"))->getVal());

    RooDataSet *nom_top_vv_sf_generated = top_vv_constraint_sf->generateSimGlobal(RooArgSet(*nom_top_vv_ratio_sf), 1);
    nom_top_vv_ratio_sf->setVal(((RooRealVar*)nom_top_vv_sf_generated->get(0)->find("nom_top_vv_ratio_sf"))->getVal());

    RooDataSet *nom_top_vv_of_generated = top_vv_constraint_of->generateSimGlobal(RooArgSet(*nom_top_vv_ratio_of), 1);
    nom_top_vv_ratio_of->setVal(((RooRealVar*)nom_top_vv_of_generated->get(0)->find("nom_top_vv_ratio_of"))->getVal());

    NumEventsTestStat* dummy = new NumEventsTestStat(*pdf);

    ToyMCSampler* mc = new ToyMCSampler(*dummy, 1);
    mc->SetPdf(*pdf);
    mc->SetObservables(*model->GetObservables());
    mc->SetGlobalObservables(*globals);
    mc->SetNuisanceParameters(*model->GetNuisanceParameters());
    mc->SetParametersForTestStat(*model->GetParametersOfInterest());
    mc->SetNEventsPerToy(n);

    RooArgSet constr;
    constr.add(*(model->GetNuisanceParameters()));
    RemoveConstantParameters(&constr);

    RooDataSet* toy_data = (RooDataSet*)mc->GenerateToyData(*const_cast<RooArgSet*>(model->GetSnapshot()));

    RooFitResult *res = pdf->fitTo(*toy_data, Constrain(constr), PrintLevel(0), Save(),
                                               Range("fitRange"), InitialHesse(),
                                               ExternalConstraints(RooArgSet(*top_constraint, *vv_constraint, *top_vv_constraint_sf, *top_vv_constraint_of)));
    result yield = get_results(wspace, res);
    yield.of.generated_sum.val = toy_data->sumEntries("(channelCat==channelCat::of) & (obs_x_of>120)");
    yield.sf.generated_sum.val = toy_data->sumEntries("(channelCat==channelCat::sf) & (obs_x_sf>120)");

    delete mc;
    delete dummy;
    // f.Close();

    return yield;
}
void StandardFeldmanCousinsDemo(const char* infile = "",
                                const char* workspaceName = "combined",
                                const char* modelConfigName = "ModelConfig",
                                const char* dataName = "obsData"){

   // -------------------------------------------------------
   // 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";
      bool fileExist = !gSystem->AccessPathName(filename); // note opposite return code
      // if file does not exists generate with histfactory
      if (!fileExist) {
#ifdef _WIN32
         cout << "HistFactory file cannot be generated on Windows - exit" << endl;
         return;
#endif
         // 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;
      }

   }
   else
      filename = infile;

   // Try to open the file
   TFile *file = TFile::Open(filename);

   // if input file was specified byt not found, quit
   if(!file ){
      cout <<"StandardRooStatsDemoMacro: Input file " << filename << " is not found" << 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;
   }

   // get the modelConfig out of the file
   ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

   // get the modelConfig out of the file
   RooAbsData* data = w->data(dataName);

   // make sure ingredients are found
   if(!data || !mc){
      w->Print();
      cout << "data or ModelConfig was not found" <<endl;
      return;
   }

   // -------------------------------------------------------
   // create and use the FeldmanCousins tool
   // to find and plot the 95% confidence interval
   // on the parameter of interest as specified
   // in the model config
   FeldmanCousins fc(*data,*mc);
   fc.SetConfidenceLevel(0.95); // 95% interval
   //fc.AdditionalNToysFactor(0.1); // to speed up the result
   fc.UseAdaptiveSampling(true); // speed it up a bit
   fc.SetNBins(10); // set how many points per parameter of interest to scan
   fc.CreateConfBelt(true); // save the information in the belt for plotting

   // Since this tool needs to throw toy MC the PDF needs to be
   // extended or the tool needs to know how many entries in a dataset
   // per pseudo experiment.
   // In the 'number counting form' where the entries in the dataset
   // are counts, and not values of discriminating variables, the
   // datasets typically only have one entry and the PDF is not
   // extended.
   if(!mc->GetPdf()->canBeExtended()){
      if(data->numEntries()==1)
         fc.FluctuateNumDataEntries(false);
      else
         cout <<"Not sure what to do about this model" <<endl;
   }

   // We can use PROOF to speed things along in parallel
   //  ProofConfig pc(*w, 1, "workers=4", kFALSE);
   //  ToyMCSampler*  toymcsampler = (ToyMCSampler*) fc.GetTestStatSampler();
   //  toymcsampler->SetProofConfig(&pc); // enable proof


   // Now get the interval
   PointSetInterval* interval = fc.GetInterval();
   ConfidenceBelt* belt = fc.GetConfidenceBelt();

   // print out the iterval on the first Parameter of Interest
   RooRealVar* firstPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
   cout << "\n95% interval on " <<firstPOI->GetName()<<" is : ["<<
      interval->LowerLimit(*firstPOI) << ", "<<
      interval->UpperLimit(*firstPOI) <<"] "<<endl;

   // ---------------------------------------------
   // No nice plots yet, so plot the belt by hand

   // Ask the calculator which points were scanned
   RooDataSet* parameterScan = (RooDataSet*) fc.GetPointsToScan();
   RooArgSet* tmpPoint;

   // make a histogram of parameter vs. threshold
   TH1F* histOfThresholds = new TH1F("histOfThresholds","",
                                       parameterScan->numEntries(),
                                       firstPOI->getMin(),
                                       firstPOI->getMax());

   // loop through the points that were tested and ask confidence belt
   // what the upper/lower thresholds were.
   // For FeldmanCousins, the lower cut off is always 0
   for(Int_t i=0; i<parameterScan->numEntries(); ++i){
      tmpPoint = (RooArgSet*) parameterScan->get(i)->clone("temp");
      double arMax = belt->GetAcceptanceRegionMax(*tmpPoint);
      double arMin = belt->GetAcceptanceRegionMax(*tmpPoint);
      double poiVal = tmpPoint->getRealValue(firstPOI->GetName()) ;
      histOfThresholds->Fill(poiVal,arMax);
   }
   histOfThresholds->SetMinimum(0);
   histOfThresholds->Draw();

}
   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 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; 
         
      }
   }

}
Exemple #21
0
void runQ(const char* inFileName,
	    const char* wsName = "combined",
	    const char* modelConfigName = "ModelConfig",
	    const char* dataName = "obsData",
	    const char* asimov0DataName = "asimovData_0",
	    const char* conditional0Snapshot = "conditionalGlobs_0",
	    const char* asimov1DataName = "asimovData_1",
	    const char* conditional1Snapshot = "conditionalGlobs_1",
	    const char* nominalSnapshot = "nominalGlobs",
	    string smass = "130",
	    string folder = "test")
{
  double mass;
  stringstream massStr;
  massStr << smass;
  massStr >> mass;

  bool errFast = 0;
  bool goFast = 1;
  bool remakeData = 1;
  bool doRightSided = 1;
  bool doInj = 0;
  bool doObs = 1;
  bool doMedian = 1;

  TStopwatch timer;
  timer.Start();

  TFile f(inFileName);
  RooWorkspace* ws = (RooWorkspace*)f.Get(wsName);
  if (!ws)
  {
    cout << "ERROR::Workspace: " << wsName << " doesn't exist!" << endl;
    return;
  }
  ModelConfig* mc = (ModelConfig*)ws->obj(modelConfigName);
  if (!mc)
  {
    cout << "ERROR::ModelConfig: " << modelConfigName << " doesn't exist!" << endl;
    return;
  }
  RooDataSet* data = (RooDataSet*)ws->data(dataName);
  if (!data)
  {
    cout << "ERROR::Dataset: " << dataName << " doesn't exist!" << endl;
    return;
  }





  mc->GetNuisanceParameters()->Print("v");

  RooNLLVar::SetIgnoreZeroEntries(1);
  ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2");
  ROOT::Math::MinimizerOptions::SetDefaultStrategy(0);
  ROOT::Math::MinimizerOptions::SetDefaultPrintLevel(1);
  cout << "Setting max function calls" << endl;
  //ROOT::Math::MinimizerOptions::SetDefaultMaxFunctionCalls(20000);
  RooMinimizer::SetMaxFunctionCalls(10000);

  ws->loadSnapshot("conditionalNuis_0");
  RooArgSet nuis(*mc->GetNuisanceParameters());

  RooRealVar* mu = (RooRealVar*)mc->GetParametersOfInterest()->first();



  if (string(mc->GetPdf()->ClassName()) == "RooSimultaneous" && remakeData)
  {
    RooSimultaneous* simPdf = (RooSimultaneous*)mc->GetPdf();
    double min_mu;
    data = makeData(data, simPdf, mc->GetObservables(), mu, mass, min_mu);
  }







  RooDataSet* asimovData0 = (RooDataSet*)ws->data(asimov0DataName);
  if (!asimovData0)
  {
    cout << "Asimov data doesn't exist! Please, allow me to build one for you..." << endl;
    makeAsimovData(mc, true, ws, mc->GetPdf(), data, 1);
    ws->Print();
    asimovData0 = (RooDataSet*)ws->data("asimovData_0");
  }

  RooDataSet* asimovData1 = (RooDataSet*)ws->data(asimov1DataName);
  if (!asimovData1)
  {
    cout << "Asimov data doesn't exist! Please, allow me to build one for you..." << endl;
    makeAsimovData(mc, true, ws, mc->GetPdf(), data, 0);
    ws->Print();
    asimovData1 = (RooDataSet*)ws->data("asimovData_1");
  }
  
  if (!doRightSided) mu->setRange(0, 40);
  else mu->setRange(-40, 40);






  bool old = false;
  if (old)
  {

    mu->setVal(0);
    RooArgSet poi(*mu);
    ProfileLikelihoodTestStat_modified asimov_testStat_sig(*mc->GetPdf());
    asimov_testStat_sig.SetRightSided(doRightSided);
    asimov_testStat_sig.SetNuis(&nuis);
    if (!doInj) asimov_testStat_sig.SetDoAsimov(true, 1);
    asimov_testStat_sig.SetWorkspace(ws);

    ProfileLikelihoodTestStat_modified testStat(*mc->GetPdf());
    testStat.SetRightSided(doRightSided);
    testStat.SetNuis(&nuis);
    testStat.SetWorkspace(ws);





    //RooMinimizerFcn::SetOverrideEverything(true);
    double med_sig = 0;
    double med_testStat_val = 0;

    //gRandom->SetSeed(1);
    //RooRandom::randomGenerator()->SetSeed(1);


    RooNLLVar::SetIgnoreZeroEntries(1);
    if (asimov1DataName != "" && doMedian)
    {
      mu->setVal(0);
      if (!doInj) mu->setRange(0, 2);
      ws->loadSnapshot("conditionalNuis_0");
      asimov_testStat_sig.SetLoadUncondSnapshot("conditionalNuis_1");
      if (string(conditional1Snapshot) != "") ws->loadSnapshot(conditional1Snapshot);
      med_testStat_val = 2*asimov_testStat_sig.Evaluate(*asimovData1, poi);
      if (med_testStat_val < 0 && !doInj) 
      {
	mu->setVal(0);
	med_testStat_val = 2*asimov_testStat_sig.Evaluate(*asimovData1, poi); // just try again
      }
      int sign = med_testStat_val != 0 ? med_testStat_val/fabs(med_testStat_val) : 0;
      med_sig = sign*sqrt(fabs(med_testStat_val));
      if (string(nominalSnapshot) != "") ws->loadSnapshot(nominalSnapshot);

      if (!doRightSided) mu->setRange(0, 40);
      else mu->setRange(-40, 40);
    }
    RooNLLVar::SetIgnoreZeroEntries(0);


    //gRandom->SetSeed(1);
    //RooRandom::randomGenerator()->SetSeed(1);

    //RooMinimizerFcn::SetOverrideEverything(false);

    cout << "med test stat: " << med_testStat_val << endl;
    ws->loadSnapshot("nominalGlobs");

    ws->loadSnapshot("conditionalNuis_0");
    mu->setVal(0);


    testStat.SetWorkspace(ws);
    testStat.SetLoadUncondSnapshot("ucmles");
    double obsTestStat_val = doObs ? 2*testStat.Evaluate(*data, poi) : 0;
    cout << "obs test stat: " << obsTestStat_val << endl;
//   obsTestStat_val = 2*testStat.Evaluate(*data, poi);
//   cout << "obs test stat: " << obsTestStat_val << endl;
//   obsTestStat_val = 2*testStat.Evaluate(*data, poi);
//   cout << "obs test stat: " << obsTestStat_val << endl;

    double obs_sig;
    int sign = obsTestStat_val == 0 ? 0 : obsTestStat_val / fabs(obsTestStat_val);
    if (!doRightSided && (obsTestStat_val < 0 && obsTestStat_val > -0.1 || mu->getVal() < 0.001)) obs_sig = 0; 
    else obs_sig = sign*sqrt(fabs(obsTestStat_val));
    if (obs_sig != obs_sig) //nan, do by hand
    {
      cout << "Obs test stat gave nan: try by hand" << endl;

      mu->setVal(0);
      mu->setConstant(1);
      mc->GetPdf()->fitTo(*data, Hesse(0), Minos(0), PrintLevel(-1), Constrain(*mc->GetNuisanceParameters()));
      mu->setConstant(0);

      double L_0 = mc->GetPdf()->getVal();

      //mu->setVal(0);
      //mu->setConstant(1);
      mc->GetPdf()->fitTo(*data, Hesse(0), Minos(0), PrintLevel(-1), Constrain(*mc->GetNuisanceParameters()));
      //mu->setConstant(0);
      double L_muhat = mc->GetPdf()->getVal();

      cout << "L_0: " << L_0 << ", L_muhat: " << L_muhat << endl;
      obs_sig = sqrt(-2*TMath::Log(L_0/L_muhat));

//still nan
      if (obs_sig != obs_sig && fabs(L_0 - L_muhat) < 0.000001) obs_sig = 0;
    }
    cout << "obs: " << obs_sig << endl;

    cout << "Observed significance: " << obs_sig << endl;
    if (med_sig)
    {
      cout << "Median test stat val: " << med_testStat_val << endl;
      cout << "Median significance:   " << med_sig << endl;
    }


    f.Close();

    stringstream fileName;
    fileName << "root_files/" << folder << "/" << mass << ".root";
    system(("mkdir -vp root_files/" + folder).c_str());
    TFile f2(fileName.str().c_str(),"recreate");

//   stringstream fileName;
//   fileName << "results_sig/" << mass << ".root";
//   system("mkdir results_sig");
//   TFile f(fileName.str().c_str(),"recreate");

    TH1D* h_hypo = new TH1D("hypo","hypo",2,0,2);
    h_hypo->SetBinContent(1, obs_sig);
    h_hypo->SetBinContent(2, med_sig);


    f2.Write();
    f2.Close();
    //mc->GetPdf()->fitTo(*data, PrintLevel(0));

    timer.Stop();
    timer.Print();
  }
  else
  {

    RooAbsPdf* pdf = mc->GetPdf();



    RooArgSet nuis_tmp1 = *mc->GetNuisanceParameters();
    RooNLLVar* asimov_nll0 = (RooNLLVar*)pdf->createNLL(*asimovData0, Constrain(nuis_tmp1));

    RooArgSet nuis_tmp2 = *mc->GetNuisanceParameters();
    RooNLLVar* asimov_nll1 = (RooNLLVar*)pdf->createNLL(*asimovData1, Constrain(nuis_tmp2));

    RooArgSet nuis_tmp3 = *mc->GetNuisanceParameters();
    RooNLLVar* obs_nll = (RooNLLVar*)pdf->createNLL(*data, Constrain(nuis_tmp3));

    
//do asimov

    int status;




//get sigma_b

    ws->loadSnapshot(conditional0Snapshot);
    status = ws->loadSnapshot("conditionalNuis_0");
    if (status != 0 && goFast) errFast = 1;

    mu->setVal(0);
    mu->setConstant(1);
    status = goFast ? 0 : minimize(asimov_nll0, ws);
    if (status < 0) 
    {
      cout << "Retrying" << endl;
      //ws->loadSnapshot("conditionalNuis_0");
      status = minimize(asimov_nll0, ws);
      if (status >= 0) cout << "Success!" << endl;
    }
    double asimov0_nll0 = asimov_nll0->getVal();

    mu->setVal(1);
    ws->loadSnapshot("conditionalNuis_1");
    status = minimize(asimov_nll0, ws);
    if (status < 0) 
    {
      cout << "Retrying" << endl;
      //ws->loadSnapshot("conditionalNuis_0");
      status = minimize(asimov_nll0, ws);
      if (status >= 0) cout << "Success!" << endl;
    }

    double asimov0_nll1 = asimov_nll0->getVal();
    double asimov0_q = 2*(asimov0_nll1 - asimov0_nll0);
    double sigma_b = sqrt(1./asimov0_q);

    ws->loadSnapshot(nominalSnapshot);





//get sigma_sb

    ws->loadSnapshot(conditional1Snapshot);
    ws->loadSnapshot("conditionalNuis_0");

    mu->setVal(0);
    mu->setConstant(1);
    status = minimize(asimov_nll1, ws);
    if (status < 0) 
    {
      cout << "Retrying" << endl;
      //ws->loadSnapshot("conditionalNuis_0");
      status = minimize(asimov_nll1, ws);
      if (status >= 0) cout << "Success!" << endl;
    }
    double asimov1_nll0 = asimov_nll1->getVal();

    mu->setVal(1);
    status = ws->loadSnapshot("conditionalNuis_1");
    if (status != 0 && goFast) errFast = 1;
    status = goFast ? 0 : minimize(asimov_nll1, ws);
    if (status < 0) 
    {
      cout << "Retrying" << endl;
      //ws->loadSnapshot("conditionalNuis_0");
      status = minimize(asimov_nll1, ws);
      if (status >= 0) cout << "Success!" << endl;
    }

    double asimov1_nll1 = asimov_nll1->getVal();
    double asimov1_q = 2*(asimov1_nll1 - asimov1_nll0);
    double sigma_sb = sqrt(-1./asimov1_q);

    ws->loadSnapshot(nominalSnapshot);



//do obs

    mu->setVal(0);
    status = ws->loadSnapshot("conditionalNuis_0");
    if (status != 0 && goFast) errFast = 1;
    mu->setConstant(1);
    status = goFast ? 0 : minimize(obs_nll, ws);
    if (status < 0) 
    {
      cout << "Retrying with conditional snapshot at mu=1" << endl;
      ws->loadSnapshot("conditionalNuis_0");
      status = minimize(obs_nll, ws);
      if (status >= 0) cout << "Success!" << endl;
    }
    double obs_nll0 = obs_nll->getVal();



    status = ws->loadSnapshot("conditionalNuis_1");
    if (status != 0 && goFast) errFast = 1;
    mu->setVal(1);
    status = goFast ? 0 : minimize(obs_nll, ws);
    if (status < 0) 
    {
      cout << "Retrying with conditional snapshot at mu=1" << endl;
      ws->loadSnapshot("conditionalNuis_0");
      status = minimize(obs_nll, ws);
      if (status >= 0) cout << "Success!" << endl;
    }

    double obs_nll1 = obs_nll->getVal();
    double obs_q = 2*(obs_nll1 - obs_nll0);



    double Zobs = (1./sigma_b/sigma_b - obs_q) / (2./sigma_b);
    double Zexp = (1./sigma_b/sigma_b - asimov1_q) / (2./sigma_b);

    double pb_obs = 1-ROOT::Math::gaussian_cdf(Zobs);
    double pb_exp = 1-ROOT::Math::gaussian_cdf(Zexp);


    cout << "asimov0_q = " << asimov0_q << endl;
    cout << "asimov1_q = " << asimov1_q << endl;
    cout << "obs_q     = " << obs_q << endl;
    cout << "sigma_b   = " << sigma_b << endl;
    cout << "sigma_sb  = " << sigma_sb << endl;
    cout << "Z obs     = " << Zobs << endl;
    cout << "Z exp     = " << Zexp << endl;



    f.Close();

    stringstream fileName;
    fileName << "root_files/" << folder << "/" << mass << ".root";
    system(("mkdir -vp root_files/" + folder).c_str());
    TFile f2(fileName.str().c_str(),"recreate");

    TH1D* h_hypo = new TH1D("hypo_tev","hypo_tev",2,0,2);
    h_hypo->SetBinContent(1, pb_obs);
    h_hypo->SetBinContent(2, pb_exp);


    f2.Write();
    f2.Close();

    stringstream fileName3;
    fileName3 << "root_files/" << folder << "_llr/" << mass << ".root";
    system(("mkdir -vp root_files/" + folder + "_llr").c_str());
    TFile f3(fileName3.str().c_str(),"recreate");

    TH1D* h_hypo3 = new TH1D("hypo_llr","hypo_llr",7,0,7);
    h_hypo3->SetBinContent(1, -obs_q);
    h_hypo3->SetBinContent(2, -asimov1_q);
    h_hypo3->SetBinContent(3, -asimov0_q);
    h_hypo3->SetBinContent(4, -asimov0_q-2*2/sigma_b);
    h_hypo3->SetBinContent(5, -asimov0_q-1*2/sigma_b);
    h_hypo3->SetBinContent(6, -asimov0_q+1*2/sigma_b);
    h_hypo3->SetBinContent(7, -asimov0_q+2*2/sigma_b);


    f3.Write();
    f3.Close();

    timer.Stop();
    timer.Print();




  }
}
Exemple #22
0
void compute_p0(const char* inFileName,
	    const char* wsName = "combined",
	    const char* modelConfigName = "ModelConfig",
	    const char* dataName = "obsData",
	    const char* asimov1DataName = "asimovData_1",
	    const char* conditional1Snapshot = "conditionalGlobs_1",
	    const char* nominalSnapshot = "nominalGlobs",
	    string smass = "130",
	    string folder = "test")
{
  double mass;
  stringstream massStr;
  massStr << smass;
  massStr >> mass;

  double mu_profile_value = 1; // mu value to profile the obs data at wbefore generating the expected
  bool doConditional      = 1; // do conditional expected data
  bool remakeData         = 0; // handle unphysical pdf cases in H->ZZ->4l
  bool doUncap            = 1; // uncap p0
  bool doInj              = 0; // setup the poi for injection study (zero is faster if you're not)
  bool doObs              = 1; // compute median significance
  bool doMedian           = 1; // compute observed significance

  TStopwatch timer;
  timer.Start();

  TFile f(inFileName);
  RooWorkspace* ws = (RooWorkspace*)f.Get(wsName);
  if (!ws)
  {
    cout << "ERROR::Workspace: " << wsName << " doesn't exist!" << endl;
    return;
  }
  ModelConfig* mc = (ModelConfig*)ws->obj(modelConfigName);
  if (!mc)
  {
    cout << "ERROR::ModelConfig: " << modelConfigName << " doesn't exist!" << endl;
    return;
  }
  RooDataSet* data = (RooDataSet*)ws->data(dataName);
  if (!data)
  {
    cout << "ERROR::Dataset: " << dataName << " doesn't exist!" << endl;
    return;
  }

  mc->GetNuisanceParameters()->Print("v");

  ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2");
  ROOT::Math::MinimizerOptions::SetDefaultStrategy(0);
  ROOT::Math::MinimizerOptions::SetDefaultPrintLevel(1);
  cout << "Setting max function calls" << endl;

  ws->loadSnapshot("conditionalNuis_0");
  RooArgSet nuis(*mc->GetNuisanceParameters());

  RooRealVar* mu = (RooRealVar*)mc->GetParametersOfInterest()->first();

  RooAbsPdf* pdf = mc->GetPdf();

  string condSnapshot(conditional1Snapshot);
  RooArgSet nuis_tmp2 = *mc->GetNuisanceParameters();
  RooNLLVar* obs_nll = doObs ? (RooNLLVar*)pdf->createNLL(*data, Constrain(nuis_tmp2)) : NULL;

  RooDataSet* asimovData1 = (RooDataSet*)ws->data(asimov1DataName);
  RooRealVar* emb = (RooRealVar*)mc->GetNuisanceParameters()->find("ATLAS_EMB");
  if (!asimovData1 || (string(inFileName).find("ic10") != string::npos && emb))
  {
    if (emb) emb->setVal(0.7);
    cout << "Asimov data doesn't exist! Please, allow me to build one for you..." << endl;
    string mu_str, mu_prof_str;
    asimovData1 = makeAsimovData(mc, doConditional, ws, obs_nll, 1, &mu_str, &mu_prof_str, mu_profile_value, true);
    condSnapshot="conditionalGlobs"+mu_prof_str;
  }
  
  if (!doUncap) mu->setRange(0, 40);
  else mu->setRange(-40, 40);

  RooAbsPdf* pdf = mc->GetPdf();

  RooArgSet nuis_tmp1 = *mc->GetNuisanceParameters();
  RooNLLVar* asimov_nll = (RooNLLVar*)pdf->createNLL(*asimovData1, Constrain(nuis_tmp1));

  //do asimov
  mu->setVal(1);
  mu->setConstant(0);
  if (!doInj) mu->setConstant(1);

  int status,sign;
  double med_sig=0,obs_sig=0,asimov_q0=0,obs_q0=0;

  if (doMedian)
  {
    ws->loadSnapshot(condSnapshot.c_str());
    if (doInj) ws->loadSnapshot("conditionalNuis_inj");
    else ws->loadSnapshot("conditionalNuis_1");
    mc->GetGlobalObservables()->Print("v");
    mu->setVal(0);
    mu->setConstant(1);
    status = minimize(asimov_nll, ws);
    if (status < 0) 
    {
      cout << "Retrying with conditional snapshot at mu=1" << endl;
      ws->loadSnapshot("conditionalNuis_0");
      status = minimize(asimov_nll, ws);
      if (status >= 0) cout << "Success!" << endl;
    }
    double asimov_nll_cond = asimov_nll->getVal();

    mu->setVal(1);
    if (doInj) ws->loadSnapshot("conditionalNuis_inj");
    else ws->loadSnapshot("conditionalNuis_1");
    if (doInj) mu->setConstant(0);
    status = minimize(asimov_nll, ws);
    if (status < 0) 
    {
      cout << "Retrying with conditional snapshot at mu=1" << endl;
      ws->loadSnapshot("conditionalNuis_0");
      status = minimize(asimov_nll, ws);
      if (status >= 0) cout << "Success!" << endl;
    }

    double asimov_nll_min = asimov_nll->getVal();
    asimov_q0 = 2*(asimov_nll_cond - asimov_nll_min);
    if (doUncap && mu->getVal() < 0) asimov_q0 = -asimov_q0;

    sign = int(asimov_q0 != 0 ? asimov_q0/fabs(asimov_q0) : 0);
    med_sig = sign*sqrt(fabs(asimov_q0));

    ws->loadSnapshot(nominalSnapshot);
  }

  if (doObs)
  {

    ws->loadSnapshot("conditionalNuis_0");
    mu->setVal(0);
    mu->setConstant(1);
    status = minimize(obs_nll, ws);
    if (status < 0) 
    {
      cout << "Retrying with conditional snapshot at mu=1" << endl;
      ws->loadSnapshot("conditionalNuis_0");
      status = minimize(obs_nll, ws);
      if (status >= 0) cout << "Success!" << endl;
    }
    double obs_nll_cond = obs_nll->getVal();

    mu->setConstant(0);
    status = minimize(obs_nll, ws);
    if (status < 0) 
    {
      cout << "Retrying with conditional snapshot at mu=1" << endl;
      ws->loadSnapshot("conditionalNuis_0");
      status = minimize(obs_nll, ws);
      if (status >= 0) cout << "Success!" << endl;
    }

    double obs_nll_min = obs_nll->getVal();



    obs_q0 = 2*(obs_nll_cond - obs_nll_min);
    if (doUncap && mu->getVal() < 0) obs_q0 = -obs_q0;

    sign = int(obs_q0 == 0 ? 0 : obs_q0 / fabs(obs_q0));
    if (!doUncap && (obs_q0 < 0 && obs_q0 > -0.1 || mu->getVal() < 0.001)) obs_sig = 0; 
    else obs_sig = sign*sqrt(fabs(obs_q0));
  }

  // Report results
  cout << "obs: " << obs_sig << endl;

  cout << "Observed significance: " << obs_sig << endl;
  cout << "Corresponding to a p-value of " << (1-ROOT::Math::gaussian_cdf( obs_sig )) << endl;
  if (med_sig)
  {
    cout << "Median test stat val: " << asimov_q0 << endl;
    cout << "Median significance:   " << med_sig << endl;
  }


  f.Close();

  stringstream fileName;
  fileName << "root-files/" << folder << "/" << mass << ".root";
  system(("mkdir -vp root-files/" + folder).c_str());
  TFile f2(fileName.str().c_str(),"recreate");

  TH1D* h_hypo = new TH1D("hypo","hypo",2,0,2);
  h_hypo->SetBinContent(1, obs_sig);
  h_hypo->SetBinContent(2, med_sig);

  f2.Write();
  f2.Close();

  timer.Stop();
  timer.Print();
  
}
void OneSidedFrequentistUpperLimitWithBands_intermediate(const char* infile = "",
					    const char* workspaceName = "combined",
					    const char* modelConfigName = "ModelConfig",
					    const char* dataName = "obsData"){


  double confidenceLevel=0.95;
  // degrade/improve number of pseudo-experiments used to define the confidence belt.  
  // value of 1 corresponds to default number of toys in the tail, which is 50/(1-confidenceLevel)
  double additionalToysFac = 1.;  
  int nPointsToScan = 30; // number of steps in the parameter of interest 
  int nToyMC = 100; // number of toys used to define the expected limit and band

  TStopwatch t;
  t.Start();
  /////////////////////////////////////////////////////////////
  // 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;
  }

  
  /////////////////////////////////////////////////////////////
  // Now get the data and workspace
  ////////////////////////////////////////////////////////////

  // get the workspace out of the file
  RooWorkspace* w = (RooWorkspace*) file->Get(workspaceName);
  if(!w){
    cout <<"workspace not found" << endl;
    return;
  }

  // get the modelConfig out of the file
  ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

  // get the modelConfig out of the file
  RooAbsData* data = w->data(dataName);

  // make sure ingredients are found
  if(!data || !mc){
    w->Print();
    cout << "data or ModelConfig was not found" <<endl;
    return;
  }

  cout << "Found data and ModelConfig:" <<endl;
  mc->Print();

  /////////////////////////////////////////////////////////////
  // Now get the POI for convenience
  // you may want to adjust the range of your POI
  ////////////////////////////////////////////////////////////
  RooRealVar* firstPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
  //  firstPOI->setMin(0);
  //  firstPOI->setMax(10);

  /////////////////////////////////////////////
  // create and use the FeldmanCousins tool
  // to find and plot the 95% confidence interval
  // on the parameter of interest as specified
  // in the model config
  // REMEMBER, we will change the test statistic
  // so this is NOT a Feldman-Cousins interval
  FeldmanCousins fc(*data,*mc);
  fc.SetConfidenceLevel(confidenceLevel); 
  fc.AdditionalNToysFactor(additionalToysFac); // improve sampling that defines confidence belt
  //  fc.UseAdaptiveSampling(true); // speed it up a bit, but don't use for expectd limits
  fc.SetNBins(nPointsToScan); // set how many points per parameter of interest to scan
  fc.CreateConfBelt(true); // save the information in the belt for plotting

  /////////////////////////////////////////////
  // Feldman-Cousins is a unified limit by definition
  // but the tool takes care of a few things for us like which values
  // of the nuisance parameters should be used to generate toys.
  // so let's just change the test statistic and realize this is 
  // no longer "Feldman-Cousins" but is a fully frequentist Neyman-Construction.
  //  ProfileLikelihoodTestStatModified onesided(*mc->GetPdf());
  //  fc.GetTestStatSampler()->SetTestStatistic(&onesided);
  // ((ToyMCSampler*) fc.GetTestStatSampler())->SetGenerateBinned(true);
  ToyMCSampler*  toymcsampler = (ToyMCSampler*) fc.GetTestStatSampler(); 
  ProfileLikelihoodTestStat* testStat = dynamic_cast<ProfileLikelihoodTestStat*>(toymcsampler->GetTestStatistic());
  testStat->SetOneSided(true);


  // test speedups:
  testStat->SetReuseNLL(true);
  //  toymcsampler->setUseMultiGen(true); // not fully validated

  // Since this tool needs to throw toy MC the PDF needs to be
  // extended or the tool needs to know how many entries in a dataset
  // per pseudo experiment.  
  // In the 'number counting form' where the entries in the dataset
  // are counts, and not values of discriminating variables, the
  // datasets typically only have one entry and the PDF is not
  // extended.  
  if(!mc->GetPdf()->canBeExtended()){
    if(data->numEntries()==1)     
      fc.FluctuateNumDataEntries(false);
    else
      cout <<"Not sure what to do about this model" <<endl;
  }

  // We can use PROOF to speed things along in parallel
  ProofConfig pc(*w, 4, "",false); 
  if(mc->GetGlobalObservables()){
    cout << "will use global observables for unconditional ensemble"<<endl;
    mc->GetGlobalObservables()->Print();
    toymcsampler->SetGlobalObservables(*mc->GetGlobalObservables());
  }
  toymcsampler->SetProofConfig(&pc);	// enable proof


  // Now get the interval
  PointSetInterval* interval = fc.GetInterval();
  ConfidenceBelt* belt = fc.GetConfidenceBelt();
 
  // print out the iterval on the first Parameter of Interest
  cout << "\n95% interval on " <<firstPOI->GetName()<<" is : ["<<
    interval->LowerLimit(*firstPOI) << ", "<<
    interval->UpperLimit(*firstPOI) <<"] "<<endl;

  // get observed UL and value of test statistic evaluated there
  RooArgSet tmpPOI(*firstPOI);
  double observedUL = interval->UpperLimit(*firstPOI);
  firstPOI->setVal(observedUL);
  double obsTSatObsUL = fc.GetTestStatSampler()->EvaluateTestStatistic(*data,tmpPOI);


  // Ask the calculator which points were scanned
  RooDataSet* parameterScan = (RooDataSet*) fc.GetPointsToScan();
  RooArgSet* tmpPoint;

  // make a histogram of parameter vs. threshold
  TH1F* histOfThresholds = new TH1F("histOfThresholds","",
				    parameterScan->numEntries(),
				    firstPOI->getMin(),
				    firstPOI->getMax());
  histOfThresholds->GetXaxis()->SetTitle(firstPOI->GetName());
  histOfThresholds->GetYaxis()->SetTitle("Threshold");

  // loop through the points that were tested and ask confidence belt
  // what the upper/lower thresholds were.
  // For FeldmanCousins, the lower cut off is always 0
  for(Int_t i=0; i<parameterScan->numEntries(); ++i){
    tmpPoint = (RooArgSet*) parameterScan->get(i)->clone("temp");
    double arMax = belt->GetAcceptanceRegionMax(*tmpPoint);
    double poiVal = tmpPoint->getRealValue(firstPOI->GetName()) ;
    histOfThresholds->Fill(poiVal,arMax);
  }
  TCanvas* c1 = new TCanvas();
  c1->Divide(2);
  c1->cd(1);
  histOfThresholds->SetMinimum(0);
  histOfThresholds->Draw();
  c1->cd(2);

  /////////////////////////////////////////////////////////////
  // Now we generate the expected bands and power-constriant
  ////////////////////////////////////////////////////////////

  // First: find parameter point for mu=0, with conditional MLEs for nuisance parameters
  RooAbsReal* nll = mc->GetPdf()->createNLL(*data);
  RooAbsReal* profile = nll->createProfile(*mc->GetParametersOfInterest());
  firstPOI->setVal(0.);
  profile->getVal(); // this will do fit and set nuisance parameters to profiled values
  RooArgSet* poiAndNuisance = new RooArgSet();
  if(mc->GetNuisanceParameters())
    poiAndNuisance->add(*mc->GetNuisanceParameters());
  poiAndNuisance->add(*mc->GetParametersOfInterest());
  w->saveSnapshot("paramsToGenerateData",*poiAndNuisance);
  RooArgSet* paramsToGenerateData = (RooArgSet*) poiAndNuisance->snapshot();
  cout << "\nWill use these parameter points to generate pseudo data for bkg only" << endl;
  paramsToGenerateData->Print("v");


  double CLb=0;
  double CLbinclusive=0;

  // Now we generate background only and find distribution of upper limits
  TH1F* histOfUL = new TH1F("histOfUL","",100,0,firstPOI->getMax());
  histOfUL->GetXaxis()->SetTitle("Upper Limit (background only)");
  histOfUL->GetYaxis()->SetTitle("Entries");
  for(int imc=0; imc<nToyMC; ++imc){

    // set parameters back to values for generating pseudo data
    w->loadSnapshot("paramsToGenerateData");

    // in 5.30 there is a nicer way to generate toy data  & randomize global obs
    RooAbsData* toyData = toymcsampler->GenerateToyData(*paramsToGenerateData);

    // get test stat at observed UL in observed data
    firstPOI->setVal(observedUL);
    double toyTSatObsUL = fc.GetTestStatSampler()->EvaluateTestStatistic(*toyData,tmpPOI);
    //    toyData->get()->Print("v");
    //    cout <<"obsTSatObsUL " <<obsTSatObsUL << "toyTS " << toyTSatObsUL << endl;
    if(obsTSatObsUL < toyTSatObsUL) // (should be checked)
      CLb+= (1.)/nToyMC;
    if(obsTSatObsUL <= toyTSatObsUL) // (should be checked)
      CLbinclusive+= (1.)/nToyMC;


    // loop over points in belt to find upper limit for this toy data
    double thisUL = 0;
    for(Int_t i=0; i<parameterScan->numEntries(); ++i){
      tmpPoint = (RooArgSet*) parameterScan->get(i)->clone("temp");
      double arMax = belt->GetAcceptanceRegionMax(*tmpPoint);
      firstPOI->setVal( tmpPoint->getRealValue(firstPOI->GetName()) );
      double thisTS = fc.GetTestStatSampler()->EvaluateTestStatistic(*toyData,tmpPOI);

      if(thisTS<=arMax){
	thisUL = firstPOI->getVal();
      } else{
	break;
      }
    }
    

    histOfUL->Fill(thisUL);

    
    delete toyData;
  }
  histOfUL->Draw();
  c1->SaveAs("one-sided_upper_limit_output.pdf");

  // if you want to see a plot of the sampling distribution for a particular scan point:

  // Now find bands and power constraint
  Double_t* bins = histOfUL->GetIntegral();
  TH1F* cumulative = (TH1F*) histOfUL->Clone("cumulative");
  cumulative->SetContent(bins);
  double band2sigDown=0, band1sigDown=0, bandMedian=0, band1sigUp=0,band2sigUp=0;
  for(int i=1; i<=cumulative->GetNbinsX(); ++i){
    if(bins[i]<RooStats::SignificanceToPValue(2))
      band2sigDown=cumulative->GetBinCenter(i);
    if(bins[i]<RooStats::SignificanceToPValue(1))
      band1sigDown=cumulative->GetBinCenter(i);
    if(bins[i]<0.5)
      bandMedian=cumulative->GetBinCenter(i);
    if(bins[i]<RooStats::SignificanceToPValue(-1))
      band1sigUp=cumulative->GetBinCenter(i);
    if(bins[i]<RooStats::SignificanceToPValue(-2))
      band2sigUp=cumulative->GetBinCenter(i);
  }

  t.Stop();
  t.Print();

  cout << "-2 sigma  band " << band2sigDown << endl;
  cout << "-1 sigma  band " << band1sigDown  << endl;
  cout << "median of band " << bandMedian << " [Power Constriant)]" << endl;
  cout << "+1 sigma  band " << band1sigUp << endl;
  cout << "+2 sigma  band " << band2sigUp << endl;

  // print out the iterval on the first Parameter of Interest
  cout << "\nobserved 95% upper-limit "<< interval->UpperLimit(*firstPOI) <<endl;
  cout << "CLb strict [P(toy>obs|0)] for observed 95% upper-limit "<< CLb <<endl;
  cout << "CLb inclusive [P(toy>=obs|0)] for observed 95% upper-limit "<< CLbinclusive <<endl;

  delete profile;
  delete nll;

}
void StandardProfileLikelihoodDemo(const char* infile = "",
                                   const char* workspaceName = "combined",
                                   const char* modelConfigName = "ModelConfig",
                                   const char* dataName = "obsData"){

      double confLevel = optPL.confLevel;
      double nScanPoints = optPL.nScanPoints;
      bool plotAsTF1 = optPL.plotAsTF1;
      double poiXMin = optPL.poiMinPlot;
      double poiXMax = optPL.poiMaxPlot;
      bool doHypoTest = optPL.doHypoTest;
      double nullParamValue = optPL.nullValue;

   // -------------------------------------------------------
   // 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";
         bool fileExist = !gSystem->AccessPathName(filename); // note opposite return code
         // if file does not exists generate with histfactory
         if (!fileExist) {
#ifdef _WIN32
            cout << "HistFactory file cannot be generated on Windows - exit" << endl;
            return;
#endif
            // 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;
         }

      }
      else
         filename = infile;

      // Try to open the file
      TFile *file = TFile::Open(filename);

      // if input file was specified byt not found, quit
      if(!file ){
         cout <<"StandardRooStatsDemoMacro: Input file " << filename << " is not found" << 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;
   }

   // get the modelConfig out of the file
   ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

   // get the modelConfig out of the file
   RooAbsData* data = w->data(dataName);

   // make sure ingredients are found
   if(!data || !mc){
      w->Print();
      cout << "data or ModelConfig was not found" <<endl;
      return;
   }

   // ---------------------------------------------
   // create and use the ProfileLikelihoodCalculator
   // to find and plot the 95% confidence interval
   // on the parameter of interest as specified
   // in the model config
   ProfileLikelihoodCalculator pl(*data,*mc);
   pl.SetConfidenceLevel(confLevel); // 95% interval
   LikelihoodInterval* interval = pl.GetInterval();

   // print out the interval on the first Parameter of Interest
   RooRealVar* firstPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
   cout << "\n>>>> RESULT : " << confLevel*100 << "% interval on " <<firstPOI->GetName()<<" is : ["<<
      interval->LowerLimit(*firstPOI) << ", "<<
      interval->UpperLimit(*firstPOI) <<"]\n "<<endl;

   // make a plot

   cout << "making a plot of the profile likelihood function ....(if it is taking a lot of time use less points or the TF1 drawing option)\n";
   LikelihoodIntervalPlot plot(interval);
   plot.SetNPoints(nScanPoints);  // do not use too many points, it could become very slow for some models
   if (poiXMin < poiXMax) plot.SetRange(poiXMin, poiXMax);
   TString opt;
   if (plotAsTF1) opt += TString("tf1");
   plot.Draw(opt);  // use option TF1 if too slow (plot.Draw("tf1")


   // if requested perform also an hypothesis test for the significance
   if (doHypoTest) {
      RooArgSet nullparams("nullparams");
      nullparams.addClone(*firstPOI);
      nullparams.setRealValue(firstPOI->GetName(), nullParamValue);
      pl.SetNullParameters(nullparams);
      std::cout << "Perform Test of Hypothesis : null Hypothesis is " << firstPOI->GetName() << nullParamValue << std::endl;
      auto result = pl.GetHypoTest();
      std::cout << "\n>>>> Hypotheis Test Result \n";
      result->Print();
   }


}
Exemple #25
0
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;

}
/*
 * 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 ----------------------------------------
double StandardFrequentistDiscovery(
   const char* infile = "",
   const char* workspaceName = "channel1",
   const char* modelConfigNameSB = "ModelConfig",
   const char* dataName = "obsData",
   int toys = 1000,
   double poiValueForBackground = 0.0,
   double poiValueForSignal = 1.0
) {

   // The workspace contains the model for s+b. The b model is "autogenerated"
   // by copying s+b and setting the one parameter of interest to zero.
   // To keep the script simple, multiple parameters of interest or different
   // functional forms of the b model are not supported.

   // for now, assume there is only one parameter of interest, and these are
   // its values:

   /////////////////////////////////////////////////////////////
   // 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_channel1_GammaExample_model.root";
      bool fileExist = !gSystem->AccessPathName(filename); // note opposite return code
      // if file does not exists generate with histfactory
      if (!fileExist) {
#ifdef _WIN32
         cout << "HistFactory file cannot be generated on Windows - exit" << endl;
         return -1;
#endif
         // 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;
      }
      
   }
   else
      filename = infile;
   
   // Try to open the file
   TFile *file = TFile::Open(filename);
   
   // if input file was specified byt not found, quit
   if(!file ){
      cout <<"StandardRooStatsDemoMacro: Input file " << filename << " is not found" << endl;
      return -1;
   } 


   /////////////////////////////////////////////////////////////
   // Tutorial starts here
   ////////////////////////////////////////////////////////////

   TStopwatch *mn_t = new TStopwatch;
   mn_t->Start();

   // get the workspace out of the file
   RooWorkspace* w = (RooWorkspace*) file->Get(workspaceName);
   if (!w) {
      cout << "workspace not found" << endl;
      return -1.0;
   }

   // get the modelConfig out of the file
   ModelConfig* mc = (ModelConfig*) w->obj(modelConfigNameSB);

   // get the data out of the file
   RooAbsData* data = w->data(dataName);

   // make sure ingredients are found
   if (!data || !mc) {
      w->Print();
      cout << "data or ModelConfig was not found" << endl;
      return -1.0;
   }


   RooRealVar* firstPOI = (RooRealVar*) mc->GetParametersOfInterest()->first();
   firstPOI->setVal(poiValueForSignal);
   mc->SetSnapshot(*mc->GetParametersOfInterest());
   // create null model
   ModelConfig *mcNull = mc->Clone("ModelConfigNull");
   firstPOI->setVal(poiValueForBackground);
   mcNull->SetSnapshot(*(RooArgSet*)mcNull->GetParametersOfInterest()->snapshot());



   // ----------------------------------------------------
   // Configure a ProfileLikelihoodTestStat and a SimpleLikelihoodRatioTestStat
   // to use simultaneously with ToyMCSampler
   ProfileLikelihoodTestStat* plts =  new ProfileLikelihoodTestStat(*mc->GetPdf());
   plts->SetOneSidedDiscovery(true);
   plts->SetVarName( "q_{0}/2" );
   
   // ----------------------------------------------------
   // configure the ToyMCImportanceSampler with two test statistics
   ToyMCSampler toymcs(*plts, 50);



   // Since this tool needs to throw toy MC the PDF needs to be
   // extended or the tool needs to know how many entries in a dataset
   // per pseudo experiment.
   // In the 'number counting form' where the entries in the dataset
   // are counts, and not values of discriminating variables, the
   // datasets typically only have one entry and the PDF is not
   // extended.
   if (!mc->GetPdf()->canBeExtended()) {
      if (data->numEntries() == 1) {
         toymcs.SetNEventsPerToy(1);
      } else cout << "Not sure what to do about this model" << endl;
   }

   // We can use PROOF to speed things along in parallel
   // ProofConfig pc(*w, 2, "user@yourfavoriteproofcluster", false);
   ProofConfig pc(*w, 2, "", false);
   //toymcs.SetProofConfig(&pc);    // enable proof


   // instantiate the calculator
   FrequentistCalculator freqCalc(*data, *mc, *mcNull, &toymcs);
   freqCalc.SetToys( toys,toys ); // null toys, alt toys

   // Run the calculator and print result
   HypoTestResult* freqCalcResult = freqCalc.GetHypoTest();
   freqCalcResult->GetNullDistribution()->SetTitle( "b only" );
   freqCalcResult->GetAltDistribution()->SetTitle( "s+b" );
   freqCalcResult->Print();
   double pvalue = freqCalcResult->NullPValue();

   // stop timing
   mn_t->Stop();
   cout << "total CPU time: " << mn_t->CpuTime() << endl;
   cout << "total real time: " << mn_t->RealTime() << endl;

   // plot
   TCanvas* c1 = new TCanvas();
   HypoTestPlot *plot = new HypoTestPlot(*freqCalcResult, 100, -0.49, 9.51 );
   plot->SetLogYaxis(true);
   
   // add chi2 to plot
   int nPOI = 1;
   TF1* f = new TF1("f", TString::Format("1*ROOT::Math::chisquared_pdf(2*x,%d,0)",nPOI), 0,20);
   f->SetLineColor( kBlack );
   f->SetLineStyle( 7 );
   plot->AddTF1( f, TString::Format("#chi^{2}(2x,%d)",nPOI) );
   
   plot->Draw();
   c1->SaveAs("standard_discovery_output.pdf");
   

   return pvalue;
}
void StandardBayesianNumericalDemo(const char* infile = "",
                                   const char* workspaceName = "combined",
                                   const char* modelConfigName = "ModelConfig",
                                   const char* dataName = "obsData") {

   // option definitions 
   double confLevel = optBayes.confLevel; 
   TString integrationType = optBayes.integrationType;
   int nToys = optBayes.nToys; 
   bool scanPosterior = optBayes.scanPosterior; 
   int nScanPoints = optBayes.nScanPoints; 
   int intervalType = optBayes.intervalType;
   int  maxPOI =  optBayes.maxPOI;
   double  nSigmaNuisance = optBayes.nSigmaNuisance;
   


  /////////////////////////////////////////////////////////////
  // 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";
      bool fileExist = !gSystem->AccessPathName(filename); // note opposite return code
      // if file does not exists generate with histfactory
      if (!fileExist) {
#ifdef _WIN32
         cout << "HistFactory file cannot be generated on Windows - exit" << endl;
         return;
#endif
         // 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;
      }

   }
   else
      filename = infile;

   // Try to open the file
   TFile *file = TFile::Open(filename);

   // if input file was specified byt not found, quit
   if(!file ){
      cout <<"StandardRooStatsDemoMacro: Input file " << filename << " is not found" << 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;
  }

  // get the modelConfig out of the file
  ModelConfig* mc = (ModelConfig*) w->obj(modelConfigName);

  // get the modelConfig out of the file
  RooAbsData* data = w->data(dataName);

  // make sure ingredients are found
  if(!data || !mc){
    w->Print();
    cout << "data or ModelConfig was not found" <<endl;
    return;
  }

  /////////////////////////////////////////////
  // create and use the BayesianCalculator
  // to find and plot the 95% credible interval
  // on the parameter of interest as specified
  // in the model config

  // before we do that, we must specify our prior
  // it belongs in the model config, but it may not have
  // been specified
  RooUniform prior("prior","",*mc->GetParametersOfInterest());
  w->import(prior);
  mc->SetPriorPdf(*w->pdf("prior"));

  // do without systematics
  //mc->SetNuisanceParameters(RooArgSet() );
  if (nSigmaNuisance > 0) {
     RooAbsPdf * pdf = mc->GetPdf();
     assert(pdf);
     RooFitResult * res = pdf->fitTo(*data, Save(true), Minimizer(ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str()), Hesse(true),
                                     PrintLevel(ROOT::Math::MinimizerOptions::DefaultPrintLevel()-1) );

     res->Print();
     RooArgList nuisPar(*mc->GetNuisanceParameters());
     for (int i = 0; i < nuisPar.getSize(); ++i) {
        RooRealVar * v = dynamic_cast<RooRealVar*> (&nuisPar[i] );
        assert( v);
        v->setMin( TMath::Max( v->getMin(), v->getVal() - nSigmaNuisance * v->getError() ) );
        v->setMax( TMath::Min( v->getMax(), v->getVal() + nSigmaNuisance * v->getError() ) );
        std::cout << "setting interval for nuisance  " << v->GetName() << " : [ " << v->getMin() << " , " << v->getMax() << " ]" << std::endl;
     }
  }


  BayesianCalculator bayesianCalc(*data,*mc);
  bayesianCalc.SetConfidenceLevel(confLevel); // 95% interval

  // default of the calculator is central interval.  here use shortest , central or upper limit depending on input
  // doing a shortest interval might require a longer time since it requires a scan of the posterior function
  if (intervalType == 0)  bayesianCalc.SetShortestInterval(); // for shortest interval
  if (intervalType == 1)  bayesianCalc.SetLeftSideTailFraction(0.5); // for central interval
  if (intervalType == 2)  bayesianCalc.SetLeftSideTailFraction(0.); // for upper limit

  if (!integrationType.IsNull() ) {
     bayesianCalc.SetIntegrationType(integrationType); // set integrationType
     bayesianCalc.SetNumIters(nToys); // set number of ietrations (i.e. number of toys for MC integrations)
  }

  // in case of toyMC make a nnuisance pdf
  if (integrationType.Contains("TOYMC") ) {
    RooAbsPdf * nuisPdf = RooStats::MakeNuisancePdf(*mc, "nuisance_pdf");
    cout << "using TOYMC integration: make nuisance pdf from the model " << std::endl;
    nuisPdf->Print();
    bayesianCalc.ForceNuisancePdf(*nuisPdf);
    scanPosterior = true; // for ToyMC the posterior is scanned anyway so used given points
  }

  // compute interval by scanning the posterior function
  if (scanPosterior)
     bayesianCalc.SetScanOfPosterior(nScanPoints);

  RooRealVar* poi = (RooRealVar*) mc->GetParametersOfInterest()->first();
  if (maxPOI != -999 &&  maxPOI > poi->getMin())
    poi->setMax(maxPOI);


  SimpleInterval* interval = bayesianCalc.GetInterval();

  // print out the iterval on the first Parameter of Interest
  cout << "\n>>>> RESULT : " << confLevel*100 << "% interval on " << poi->GetName()<<" is : ["<<
    interval->LowerLimit() << ", "<<
    interval->UpperLimit() <<"] "<<endl;


  // make a plot
  // since plotting may take a long time (it requires evaluating
  // the posterior in many points) this command will speed up
  // by reducing the number of points to plot - do 50

  // ignore errors of PDF if is zero
  RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::Ignore) ;

  
  cout << "\nDrawing plot of posterior function....." << endl;

  // always plot using numer of scan points
  bayesianCalc.SetScanOfPosterior(nScanPoints);

  RooPlot * plot = bayesianCalc.GetPosteriorPlot();
  plot->Draw();

}
Exemple #29
0
TH1D* runSig(RooWorkspace* ws,
             const char* modelConfigName = "ModelConfig",
             const char* dataName = "obsData",
             const char* asimov1DataName = "asimovData_1",
             const char* conditional1Snapshot = "conditionalGlobs_1",
             const char* nominalSnapshot = "nominalGlobs")
{
    string defaultMinimizer    = "Minuit";     // or "Minuit"
    int defaultStrategy        = 2;             // Minimization strategy. 0-2. 0 = fastest, least robust. 2 = slowest, most robust

    double mu_profile_value = 1; // mu value to profile the obs data at wbefore generating the expected
    bool doUncap            = 1; // uncap p0
    bool doInj              = 0; // setup the poi for injection study (zero is faster if you're not)
    bool doMedian           = 1; // compute median significance
    bool isBlind            = 0; // Dont look at observed data
    bool doConditional      = !isBlind; // do conditional expected data
    bool doObs              = !isBlind; // compute observed significance

    TStopwatch timer;
    timer.Start();

    if (!ws)
    {
        cout << "ERROR::Workspace is NULL!" << endl;
        return NULL;
    }
    ModelConfig* mc = (ModelConfig*)ws->obj(modelConfigName);
    if (!mc)
    {
        cout << "ERROR::ModelConfig: " << modelConfigName << " doesn't exist!" << endl;
        return NULL;
    }
    RooDataSet* data = (RooDataSet*)ws->data(dataName);
    if (!data)
    {
        cout << "ERROR::Dataset: " << dataName << " doesn't exist!" << endl;
        return NULL;
    }

    mc->GetNuisanceParameters()->Print("v");

    //RooNLLVar::SetIgnoreZeroEntries(1);
    ROOT::Math::MinimizerOptions::SetDefaultMinimizer(defaultMinimizer.c_str());
    ROOT::Math::MinimizerOptions::SetDefaultStrategy(defaultStrategy);
    ROOT::Math::MinimizerOptions::SetDefaultPrintLevel(-1);
    //  cout << "Setting max function calls" << endl;
    //ROOT::Math::MinimizerOptions::SetDefaultMaxFunctionCalls(20000);
    //RooMinimizer::SetMaxFunctionCalls(10000);

    ws->loadSnapshot("conditionalNuis_0");
    RooArgSet nuis(*mc->GetNuisanceParameters());

    RooRealVar* mu = (RooRealVar*)mc->GetParametersOfInterest()->first();

    RooAbsPdf* pdf_temp = mc->GetPdf();

    string condSnapshot(conditional1Snapshot);
    RooArgSet nuis_tmp2 = *mc->GetNuisanceParameters();
    RooNLLVar* obs_nll = doObs ? (RooNLLVar*)pdf_temp->createNLL(*data, Constrain(nuis_tmp2)) : NULL;

    RooDataSet* asimovData1 = (RooDataSet*)ws->data(asimov1DataName);
    if (!asimovData1)
    {
        cout << "Asimov data doesn't exist! Please, allow me to build one for you..." << endl;
        string mu_str, mu_prof_str;

        asimovData1 = makeAsimovData(mc, doConditional, ws, obs_nll, 1, &mu_str, &mu_prof_str, mu_profile_value, true);
        condSnapshot="conditionalGlobs"+mu_prof_str;

        //makeAsimovData(mc, true, ws, mc->GetPdf(), data, 0);
        //ws->Print();
        //asimovData1 = (RooDataSet*)ws->data("asimovData_1");
    }

    if (!doUncap) mu->setRange(0, 40);
    else mu->setRange(-40, 40);

    RooAbsPdf* pdf = mc->GetPdf();
    RooArgSet nuis_tmp1 = *mc->GetNuisanceParameters();
    RooNLLVar* asimov_nll = (RooNLLVar*)pdf->createNLL(*asimovData1, Constrain(nuis_tmp1));

    //do asimov
    mu->setVal(1);
    mu->setConstant(0);
    if (!doInj) mu->setConstant(1);

    int status,sign;
    double med_sig=0,obs_sig=0,asimov_q0=0,obs_q0=0;

    if (doMedian)
    {
        ws->loadSnapshot(condSnapshot.c_str());
        if (doInj) ws->loadSnapshot("conditionalNuis_inj");
        else ws->loadSnapshot("conditionalNuis_1");
        mc->GetGlobalObservables()->Print("v");
        mu->setVal(0);
        mu->setConstant(1);
        status = minimize(asimov_nll, ws);
        if (status >= 0) cout << "Success!" << endl;

        if (status < 0) 
        {
            cout << "Retrying with conditional snapshot at mu=1" << endl;
            ws->loadSnapshot("conditionalNuis_0");
            status = minimize(asimov_nll, ws);
            if (status >= 0) cout << "Success!" << endl;
        }
        double asimov_nll_cond = asimov_nll->getVal();

        mu->setVal(1);
        if (doInj) ws->loadSnapshot("conditionalNuis_inj");
        else ws->loadSnapshot("conditionalNuis_1");
        if (doInj) mu->setConstant(0);
        status = minimize(asimov_nll, ws);
        if (status >= 0) cout << "Success!" << endl;

        if (status < 0) 
        {
            cout << "Retrying with conditional snapshot at mu=1" << endl;
            ws->loadSnapshot("conditionalNuis_0");
            status = minimize(asimov_nll, ws);
            if (status >= 0) cout << "Success!" << endl;
        }

        double asimov_nll_min = asimov_nll->getVal();
        asimov_q0 = 2*(asimov_nll_cond - asimov_nll_min);
        if (doUncap && mu->getVal() < 0) asimov_q0 = -asimov_q0;

        sign = int(asimov_q0 != 0 ? asimov_q0/fabs(asimov_q0) : 0);
        med_sig = sign*sqrt(fabs(asimov_q0));

        ws->loadSnapshot(nominalSnapshot);
    }

    if (doObs)
    {
        ws->loadSnapshot("conditionalNuis_0");
        mu->setVal(0);
        mu->setConstant(1);
        status = minimize(obs_nll, ws);
        if (status < 0) 
        {
            cout << "Retrying with conditional snapshot at mu=1" << endl;
            ws->loadSnapshot("conditionalNuis_0");
            status = minimize(obs_nll, ws);
            if (status >= 0) cout << "Success!" << endl;
        }
        double obs_nll_cond = obs_nll->getVal();

        //ws->loadSnapshot("ucmles");
        mu->setConstant(0);
        status = minimize(obs_nll, ws);
        if (status < 0) 
        {
            cout << "Retrying with conditional snapshot at mu=1" << endl;
            ws->loadSnapshot("conditionalNuis_0");
            status = minimize(obs_nll, ws);
            if (status >= 0) cout << "Success!" << endl;
        }

        double obs_nll_min = obs_nll->getVal();

        obs_q0 = 2*(obs_nll_cond - obs_nll_min);
        if (doUncap && mu->getVal() < 0) obs_q0 = -obs_q0;

        sign = int(obs_q0 == 0 ? 0 : obs_q0 / fabs(obs_q0));
        if (!doUncap && ((obs_q0 < 0 && obs_q0 > -0.1) || mu->getVal() < 0.001)) obs_sig = 0; 
        else obs_sig = sign*sqrt(fabs(obs_q0));
    }

    cout << "obs: " << obs_sig << endl;
    cout << "Observed significance: " << obs_sig << endl;

    if (med_sig)
    {
        cout << "Median test stat val: " << asimov_q0 << endl;
        cout << "Median significance:   " << med_sig << endl;
    }

    TH1D* h_hypo = new TH1D("hypo","hypo",2,0,2);
    h_hypo->SetBinContent(1, obs_sig);
    h_hypo->SetBinContent(2, med_sig);

    timer.Stop();
    timer.Print();
    return h_hypo;
}