float getDLL(RooWorkspace* w, TString tag) {
  //RooFitResult::sexp_b_fitres

  RooFitResult *b = (RooFitResult*)w->obj(tag+"_b_fitres");
  RooFitResult *sb = (RooFitResult*)w->obj(tag+"_sb_fitres");

  return -2*(sb->minNll()-b->minNll());
}
Beispiel #2
0
Datei: fit.C Projekt: dcraik/lhcb
void fit(Int_t i, Double_t va=-0.43, Double_t vb=0.){
    sprintf(namestr,"%d_%.2f_%.2f",i,va,vb);

    Double_t g1, g2;
    g1 = 0.1*r.Rndm() - 0.05;
    g2 =     r.Rndm() - 0.5;

    //a->setVal(va);
    //b->setVal(vb);

    //G001->setVal(g1);
    //G002->setVal(g2);

    //RooRealVar * G000 = new RooRealVar("G000", "G000",  0.5);
    //RooRealVar * G001 = new RooRealVar("G001", "G001",  g1, -5., 5.);
    //RooRealVar * G002 = new RooRealVar("G002", "G002",  g2, -5., 5.);
    //RooRealVar * G003 = new RooRealVar("G003", "G003", 0.0);//, -1., 1.);
    //RooRealVar * G004 = new RooRealVar("G004", "G004", 0.0);//, -1., 1.);
    //RooRealVar * a    = new RooRealVar("a",    "a",    va);
    //RooRealVar * b    = new RooRealVar("b",    "b",    vb);
    //RooRealVar * n    = new RooRealVar("n",    "n",    1000., -100., 5000.);
    RooRealVar G000("G000", "G000",  0.5);
    RooRealVar G001("G001", "G001",  g1, -5., 5.);
    RooRealVar G002("G002", "G002",  g2, -5., 5.);
    RooRealVar G003("G003", "G003", 0.0);//, -1., 1.);
    RooRealVar G004("G004", "G004", 0.0);//, -1., 1.);
    RooRealVar    a("a",    "a",    va);
    RooRealVar    b("b",    "b",    vb);
    RooRealVar    n("n",    "n",    1000., -100., 5000.);

    RooB2Kll pdf("pdf", "pdf", *cosTheta, G000, G001, G002, G003, G004, a, b, n);

    RooFitResult * fitresult = pdf.fitTo(*data,Save(kTRUE), Minos(kFALSE), NumCPU(4), SumW2Error(kTRUE));
    
    RooPlot * frame = cosTheta->frame();
    data->plotOn(frame);
    pdf.plotOn(frame);

    if(fitresult->minNll() == fitresult->minNll() && fitresult->minNll()>0 ) {
    fout << i << "\t" << a.getVal() << "\t" << b.getVal() << "\t" << fitresult->minNll() << "\t" << fitresult->status() << "\t" 
         << G000.getVal() << "\t" << G001.getVal() << "\t" << G002.getVal() << "\t" << G003.getVal() << "\t" << G004.getVal() << endl;
    }

    gROOT->ProcessLine(".x ~/lhcb/lhcbStyle.C");
    TCanvas c("fit","fit", 800, 800);
    frame->Draw();
    c.SaveAs("fits/fit"+TString(namestr)+".png");
    c.SaveAs("fits/fit"+TString(namestr)+".pdf");
}
void runFit(RooAbsPdf *pdf, RooDataSet *data, double *NLL, int *stat_t, int MaxTries, int mhLow, int mhHigh){

	int ntries=0;
	int stat=1;
	double minnll=10e8;
	while (stat!=0){
	  if (ntries>=MaxTries) break;
	  RooFitResult *fitTest = pdf->fitTo(*data,RooFit::Save(1),Range(mhLow,mhHigh));
	  //RooFitResult *fitTest = pdf->fitTo(*data,RooFit::Save(1),Range(85,110));
	  //RooFitResult *fitTest = pdf->fitTo(*data,RooFit::Save(1),SumW2Error(kTRUE)
          stat = fitTest->status();
	  minnll = fitTest->minNll();
	  ntries++; 
	}
	*stat_t = stat;
	*NLL = minnll;
}
Beispiel #4
0
void FitBias(TString CAT,TString CUT,float SIG,float BKG,int NTOYS)
{
  gROOT->ForceStyle();
  
  RooMsgService::instance().setSilentMode(kTRUE);
  RooMsgService::instance().setStreamStatus(0,kFALSE);
  RooMsgService::instance().setStreamStatus(1,kFALSE);
  
  // -----------------------------------------
  TFile *fTemplates = TFile::Open("templates_"+CUT+"_"+CAT+"_workspace.root");
  RooWorkspace *wTemplates = (RooWorkspace*)fTemplates->Get("w");
  RooRealVar *x            = (RooRealVar*)wTemplates->var("mTop");
  RooAbsPdf *pdf_signal    = (RooAbsPdf*)wTemplates->pdf("ttbar_pdf_Nominal");
  RooAbsPdf *pdf_bkg       = (RooAbsPdf*)wTemplates->pdf("qcdCor_pdf"); 
  TRandom *rnd = new TRandom();
  rnd->SetSeed(0);
  x->setBins(250);   
  RooPlot *frame;

  TFile *outf;

  if (NTOYS > 1) { 
    outf = TFile::Open("FitBiasToys_"+CUT+"_"+CAT+".root","RECREATE");
  }

  float nSigInj,nBkgInj,nSigFit,nBkgFit,eSigFit,eBkgFit,nll;

  TTree *tr = new TTree("toys","toys");
  
  tr->Branch("nSigInj",&nSigInj,"nSigInj/F");
  tr->Branch("nSigFit",&nSigFit,"nSigFit/F");
  tr->Branch("nBkgInj",&nBkgInj,"nBkgInj/F");
  tr->Branch("nBkgFit",&nBkgFit,"nBkgFit/F");
  tr->Branch("eSigFit",&eSigFit,"eSigFit/F");
  tr->Branch("eBkgFit",&eBkgFit,"eBkgFit/F");
  tr->Branch("nll"    ,&nll    ,"nll/F");

  for(int itoy=0;itoy<NTOYS;itoy++) {
    // generate pseudodataset
    nSigInj = rnd->Poisson(SIG);
    nBkgInj = rnd->Poisson(BKG);
    RooRealVar *nSig = new RooRealVar("nSig","nSig",nSigInj);
    RooRealVar *nBkg = new RooRealVar("nBkg","nBkg",nBkgInj);
    RooAddPdf *model = new RooAddPdf("model","model",RooArgList(*pdf_signal,*pdf_bkg),RooArgList(*nSig,*nBkg)); 
    RooDataSet *data = model->generate(*x,nSigInj+nBkgInj);
    
    RooDataHist *roohist = new RooDataHist("roohist","roohist",RooArgList(*x),*data);
    // build fit model
    RooRealVar *nFitSig = new RooRealVar("nFitSig","nFitSig",SIG,0,10*SIG);
    RooRealVar *nFitBkg = new RooRealVar("nFitBkg","nFitBkg",BKG,0,10*BKG);
    RooAddPdf *modelFit = new RooAddPdf("modelFit","modelFit",RooArgList(*pdf_signal,*pdf_bkg),RooArgList(*nFitSig,*nFitBkg)); 
    // fit the pseudo dataset
    RooFitResult *res = modelFit->fitTo(*roohist,RooFit::Save(),RooFit::Extended(kTRUE));
    //res->Print();
    nSigFit = nFitSig->getVal();
    nBkgFit = nFitBkg->getVal();
    eSigFit = nFitSig->getError();
    eBkgFit = nFitBkg->getError();
    nll     = res->minNll();
    tr->Fill();
    if (itoy % 100 == 0) {
      cout<<"Toy #"<<itoy<<": injected = "<<nSigInj<<", fitted = "<<nSigFit<<", error = "<<eSigFit<<endl;
    }
    if (NTOYS == 1) {
      frame = x->frame();
      roohist->plotOn(frame); 
      model->plotOn(frame);
    }
  }
  if (NTOYS == 1) {
    TCanvas *can = new TCanvas("Toy","Toy",900,600);
    frame->Draw();
  }  
  else {
    outf->cd();
    tr->Write();
    outf->Close();
    fTemplates->Close();
  }  
}
RooWorkspace* makeInvertedANFit(TTree* tree, float forceSigma=-1, bool constrainMu=false, float forceMu=-1) {
  RooWorkspace *ws = new RooWorkspace("ws","");

  std::vector< TString (*)(TString, RooRealVar&, RooWorkspace&) > bkgPdfList;
  bkgPdfList.push_back(makeSingleExp);
  bkgPdfList.push_back(makeDoubleExp);
#if DEBUG==0
  //bkgPdfList.push_back(makeTripleExp);
  bkgPdfList.push_back(makeModExp);
  bkgPdfList.push_back(makeSinglePow);
  bkgPdfList.push_back(makeDoublePow);
  bkgPdfList.push_back(makePoly2);
  bkgPdfList.push_back(makePoly3);
#endif



  RooRealVar mgg("mgg","m_{#gamma#gamma}",103,160,"GeV");
  mgg.setBins(38);

  mgg.setRange("sideband_low", 103,120);
  mgg.setRange("sideband_high",131,160);
  mgg.setRange("signal",120,131);

  RooRealVar MR("MR","",0,3000,"GeV");
  MR.setBins(60);
  
  RooRealVar Rsq("t1Rsq","",0,1,"GeV");
  Rsq.setBins(20);

  RooRealVar hem1_M("hem1_M","",-1,2000,"GeV");
  hem1_M.setBins(40);

  RooRealVar hem2_M("hem2_M","",-1,2000,"GeV");
  hem2_M.setBins(40);

  RooRealVar ptgg("ptgg","p_{T}^{#gamma#gamma}",0,500,"GeV");
  ptgg.setBins(50);

  RooDataSet data("data","",tree,RooArgSet(mgg,MR,Rsq,hem1_M,hem2_M,ptgg));

  RooDataSet* blind_data = (RooDataSet*)data.reduce("mgg<121 || mgg>130");

  std::vector<TString> tags;
  //fit many different background models
  for(auto func = bkgPdfList.begin(); func != bkgPdfList.end(); func++) {
    TString tag = (*func)("bonly",mgg,*ws);
    tags.push_back(tag);
    ws->pdf("bonly_"+tag+"_ext")->fitTo(data,RooFit::Strategy(0),RooFit::Extended(kTRUE),RooFit::Range("sideband_low,sideband_high"));
    RooFitResult* bres = ws->pdf("bonly_"+tag+"_ext")->fitTo(data,RooFit::Strategy(2),RooFit::Save(kTRUE),RooFit::Extended(kTRUE),RooFit::Range("sideband_low,sideband_high"));
    bres->SetName(tag+"_bonly_fitres");
    ws->import(*bres);

    //make blinded fit
    RooPlot *fmgg_b = mgg.frame();
    blind_data->plotOn(fmgg_b,RooFit::Range("sideband_low,sideband_high"));
    TBox blindBox(121,fmgg_b->GetMinimum()-(fmgg_b->GetMaximum()-fmgg_b->GetMinimum())*0.015,130,fmgg_b->GetMaximum());
    blindBox.SetFillColor(kGray);
    fmgg_b->addObject(&blindBox);
    ws->pdf("bonly_"+tag+"_ext")->plotOn(fmgg_b,RooFit::LineColor(kRed),RooFit::Range("Full"),RooFit::NormRange("sideband_low,sideband_high"));
    fmgg_b->SetName(tag+"_blinded_frame");
    ws->import(*fmgg_b);
    delete fmgg_b;
    

    //set all the parameters constant
    RooArgSet* vars = ws->pdf("bonly_"+tag)->getVariables();
    RooFIter iter = vars->fwdIterator();
    RooAbsArg* a;
    while( (a = iter.next()) ){
      if(string(a->GetName()).compare("mgg")==0) continue;
      static_cast<RooRealVar*>(a)->setConstant(kTRUE);
    }

    //make the background portion of the s+b fit
    (*func)("b",mgg,*ws);

    RooRealVar sigma(tag+"_s_sigma","",5,0,100);
    if(forceSigma!=-1) {
      sigma.setVal(forceSigma);
      sigma.setConstant(true);
    }
    RooRealVar mu(tag+"_s_mu","",126,120,132);
    if(forceMu!=-1) {
      mu.setVal(forceMu);
      mu.setConstant(true);
    }
    RooGaussian sig(tag+"_sig_model","",mgg,mu,sigma);
    RooRealVar Nsig(tag+"_sb_Ns","",5,0,100);
    RooRealVar Nbkg(tag+"_sb_Nb","",100,0,100000);
    

    RooRealVar HiggsMass("HiggsMass","",125.1);
    RooRealVar HiggsMassError("HiggsMassError","",0.24);
    RooGaussian HiggsMassConstraint("HiggsMassConstraint","",mu,HiggsMass,HiggsMassError);


    RooAddPdf fitModel(tag+"_sb_model","",RooArgList( *ws->pdf("b_"+tag), sig ),RooArgList(Nbkg,Nsig));

    RooFitResult* sbres;
    RooAbsReal* nll;
    if(constrainMu) {
      fitModel.fitTo(data,RooFit::Strategy(0),RooFit::Extended(kTRUE),RooFit::ExternalConstraints(RooArgSet(HiggsMassConstraint)));
      sbres = fitModel.fitTo(data,RooFit::Strategy(2),RooFit::Save(kTRUE),RooFit::Extended(kTRUE),RooFit::ExternalConstraints(RooArgSet(HiggsMassConstraint)));
      nll = fitModel.createNLL(data,RooFit::NumCPU(4),RooFit::Extended(kTRUE),RooFit::ExternalConstraints(RooArgSet(HiggsMassConstraint)));
    } else {
      fitModel.fitTo(data,RooFit::Strategy(0),RooFit::Extended(kTRUE));
      sbres = fitModel.fitTo(data,RooFit::Strategy(2),RooFit::Save(kTRUE),RooFit::Extended(kTRUE));
      nll = fitModel.createNLL(data,RooFit::NumCPU(4),RooFit::Extended(kTRUE));
    }
    sbres->SetName(tag+"_sb_fitres");
    ws->import(*sbres);
    ws->import(fitModel);

    RooPlot *fmgg = mgg.frame();
    data.plotOn(fmgg);
    fitModel.plotOn(fmgg);
    ws->pdf("b_"+tag+"_ext")->plotOn(fmgg,RooFit::LineColor(kRed),RooFit::Range("Full"),RooFit::NormRange("Full"));
    fmgg->SetName(tag+"_frame");
    ws->import(*fmgg);
    delete fmgg;


    RooMinuit(*nll).migrad();

    RooPlot *fNs = Nsig.frame(0,25);
    fNs->SetName(tag+"_Nsig_pll");
    RooAbsReal *pll = nll->createProfile(Nsig);
    //nll->plotOn(fNs,RooFit::ShiftToZero(),RooFit::LineColor(kRed));
    pll->plotOn(fNs);
    ws->import(*fNs);

    delete fNs;

    RooPlot *fmu = mu.frame(125,132);
    fmu->SetName(tag+"_mu_pll");
    RooAbsReal *pll_mu = nll->createProfile(mu);
    pll_mu->plotOn(fmu);
    ws->import(*fmu);

    delete fmu;

  }

  RooArgSet weights("weights");
  RooArgSet pdfs_bonly("pdfs_bonly");
  RooArgSet pdfs_b("pdfs_b");

  RooRealVar minAIC("minAIC","",1E10);
  //compute AIC stuff
  for(auto t = tags.begin(); t!=tags.end(); t++) {
    RooAbsPdf *p_bonly = ws->pdf("bonly_"+*t);
    RooAbsPdf *p_b = ws->pdf("b_"+*t);
    RooFitResult *sb = (RooFitResult*)ws->obj(*t+"_bonly_fitres");
    RooRealVar k(*t+"_b_k","",p_bonly->getParameters(RooArgSet(mgg))->getSize());
    RooRealVar nll(*t+"_b_minNll","",sb->minNll());
    RooRealVar Npts(*t+"_b_N","",blind_data->sumEntries());
    RooFormulaVar AIC(*t+"_b_AIC","2*@0+2*@1+2*@1*(@1+1)/(@2-@1-1)",RooArgSet(nll,k,Npts));
    ws->import(AIC);
    if(AIC.getVal() < minAIC.getVal()) {
      minAIC.setVal(AIC.getVal());
    }
    //aicExpSum+=TMath::Exp(-0.5*AIC.getVal()); //we will need this precomputed  for the next step
    pdfs_bonly.add(*p_bonly);
    pdfs_b.add(*p_b);
  }
  ws->import(minAIC);
  //compute the AIC weight
  float aicExpSum=0;
  for(auto t = tags.begin(); t!=tags.end(); t++) {
    RooFormulaVar *AIC = (RooFormulaVar*)ws->obj(*t+"_b_AIC");
    aicExpSum+=TMath::Exp(-0.5*(AIC->getVal()-minAIC.getVal())); //we will need this precomputed  for the next step    
  }
  std::cout << "aicExpSum: " << aicExpSum << std::endl;

  for(auto t = tags.begin(); t!=tags.end(); t++) {
    RooFormulaVar *AIC = (RooFormulaVar*)ws->obj(*t+"_b_AIC");
    RooRealVar *AICw = new RooRealVar(*t+"_b_AICWeight","",TMath::Exp(-0.5*(AIC->getVal()-minAIC.getVal()))/aicExpSum);
    if( TMath::IsNaN(AICw->getVal()) ) {AICw->setVal(0);}
    ws->import(*AICw);
    std::cout << *t << ":  " << AIC->getVal()-minAIC.getVal() << "    " << AICw->getVal() << std::endl;
    weights.add(*AICw);
  }
  RooAddPdf bonly_AIC("bonly_AIC","",pdfs_bonly,weights);
  RooAddPdf b_AIC("b_AIC","",pdfs_b,weights);

  //b_AIC.fitTo(data,RooFit::Strategy(0),RooFit::Extended(kTRUE),RooFit::Range("sideband_low,sideband_high"));
  //RooFitResult* bres = b_AIC.fitTo(data,RooFit::Strategy(2),RooFit::Save(kTRUE),RooFit::Extended(kTRUE),RooFit::Range("sideband_low,sideband_high"));
  //bres->SetName("AIC_b_fitres");
  //ws->import(*bres);

  //make blinded fit
  RooPlot *fmgg_b = mgg.frame(RooFit::Range("sideband_low,sideband_high"));
  blind_data->plotOn(fmgg_b,RooFit::Range("sideband_low,sideband_high"));
  TBox blindBox(121,fmgg_b->GetMinimum()-(fmgg_b->GetMaximum()-fmgg_b->GetMinimum())*0.015,130,fmgg_b->GetMaximum());
  blindBox.SetFillColor(kGray);
  fmgg_b->addObject(&blindBox);
  bonly_AIC.plotOn(fmgg_b,RooFit::LineColor(kRed),RooFit::Range("Full"),RooFit::NormRange("sideband_low,sideband_high"));
  fmgg_b->SetName("AIC_blinded_frame");
  ws->import(*fmgg_b);
  delete fmgg_b;
    
#if 1

  RooRealVar sigma("AIC_s_sigma","",5,0,100);
  if(forceSigma!=-1) {
    sigma.setVal(forceSigma);
    sigma.setConstant(true);
  }
  RooRealVar mu("AIC_s_mu","",126,120,132);
  if(forceMu!=-1) {
    mu.setVal(forceMu);
    mu.setConstant(true);
  }
  RooGaussian sig("AIC_sig_model","",mgg,mu,sigma);
  RooRealVar Nsig("AIC_sb_Ns","",5,0,100);
  RooRealVar Nbkg("AIC_sb_Nb","",100,0,100000);
  
  
  RooRealVar HiggsMass("HiggsMass","",125.1);
  RooRealVar HiggsMassError("HiggsMassError","",0.24);
  RooGaussian HiggsMassConstraint("HiggsMassConstraint","",mu,HiggsMass,HiggsMassError);
  
  
  RooAddPdf fitModel("AIC_sb_model","",RooArgList( b_AIC, sig ),RooArgList(Nbkg,Nsig));

  RooFitResult* sbres;
  RooAbsReal *nll;

  if(constrainMu) {
    fitModel.fitTo(data,RooFit::Strategy(0),RooFit::Extended(kTRUE),RooFit::ExternalConstraints(RooArgSet(HiggsMassConstraint)));
    sbres = fitModel.fitTo(data,RooFit::Strategy(2),RooFit::Save(kTRUE),RooFit::Extended(kTRUE),RooFit::ExternalConstraints(RooArgSet(HiggsMassConstraint)));
    nll = fitModel.createNLL(data,RooFit::NumCPU(4),RooFit::Extended(kTRUE),RooFit::ExternalConstraints(RooArgSet(HiggsMassConstraint)));
  } else {
    fitModel.fitTo(data,RooFit::Strategy(0),RooFit::Extended(kTRUE));
    sbres = fitModel.fitTo(data,RooFit::Strategy(2),RooFit::Save(kTRUE),RooFit::Extended(kTRUE));
    nll = fitModel.createNLL(data,RooFit::NumCPU(4),RooFit::Extended(kTRUE));
  }

  assert(nll!=0);
  
  sbres->SetName("AIC_sb_fitres");
  ws->import(*sbres);
  ws->import(fitModel);
  
  RooPlot *fmgg = mgg.frame();
  data.plotOn(fmgg);
  fitModel.plotOn(fmgg);
  ws->pdf("b_AIC")->plotOn(fmgg,RooFit::LineColor(kRed),RooFit::Range("Full"),RooFit::NormRange("Full"));
  fmgg->SetName("AIC_frame");
  ws->import(*fmgg);
  delete fmgg;

  RooMinuit(*nll).migrad();
  
  RooPlot *fNs = Nsig.frame(0,25);
  fNs->SetName("AIC_Nsig_pll");
  RooAbsReal *pll = nll->createProfile(Nsig);
  //nll->plotOn(fNs,RooFit::ShiftToZero(),RooFit::LineColor(kRed));
  pll->plotOn(fNs);
  ws->import(*fNs);
  delete fNs;


  RooPlot *fmu = mu.frame(125,132);
  fmu->SetName("AIC_mu_pll");
  RooAbsReal *pll_mu = nll->createProfile(mu);
  pll_mu->plotOn(fmu);
  ws->import(*fmu);

  delete fmu;

  std::cout << "min AIC: " << minAIC.getVal() << std::endl;
  for(auto t = tags.begin(); t!=tags.end(); t++) {
    RooFormulaVar *AIC = (RooFormulaVar*)ws->obj(*t+"_b_AIC");
    RooRealVar *AICw = ws->var(*t+"_b_AICWeight");
    RooRealVar* k = ws->var(*t+"_b_k");
    printf("%s & %0.0f & %0.2f & %0.2f \\\\\n",t->Data(),k->getVal(),AIC->getVal()-minAIC.getVal(),AICw->getVal());
    //std::cout << k->getVal() << " " << AIC->getVal()-minAIC.getVal() << " " << AICw->getVal() << std::endl;
  }
#endif
  return ws;
}
///
/// Find the global minimum in a more thorough way.
/// First fit with external start parameters, then
/// for each parameter that starts with "d" or "r" (typically angles and ratios):
///   - at upper scan range, rest at start parameters
///   - at lower scan range, rest at start parameters
/// This amounts to a maximum of 1+2^n fits, where n is the number
/// of parameters to be varied.
///
/// \param w Workspace holding the pdf.
/// \param name Name of the pdf without leading "pdf_".
/// \param forceVariables Apply the force method for these variables only. Format
/// "var1,var2,var3," (list must end with comma). Default is to apply for all angles,
/// all ratios except rD_k3pi and rD_kpi, and the k3pi coherence factor.
///
RooFitResult* Utils::fitToMinForce(RooWorkspace *w, TString name, TString forceVariables)
{
	bool debug = true;

	TString parsName = "par_"+name;
	TString obsName  = "obs_"+name;
	TString pdfName  = "pdf_"+name;
	RooFitResult *r = 0;
	int printlevel = -1;
	RooMsgService::instance().setGlobalKillBelow(ERROR);

	// save start parameters
	if ( !w->set(parsName) ){
		cout << "MethodProbScan::scan2d() : ERROR : parsName not found: " << parsName << endl;
		exit(1);
	}
	RooDataSet *startPars = new RooDataSet("startParsForce", "startParsForce", *w->set(parsName));
	startPars->add(*w->set(parsName));

	// set up parameters and ranges
	RooArgList *varyPars = new RooArgList();
	TIterator* it = w->set(parsName)->createIterator();
	while ( RooRealVar* p = (RooRealVar*)it->Next() )
	{
		if ( p->isConstant() ) continue;
		if ( forceVariables=="" && ( false
					|| TString(p->GetName()).BeginsWith("d") ///< use these variables
					// || TString(p->GetName()).BeginsWith("r")
					|| TString(p->GetName()).BeginsWith("k")
					|| TString(p->GetName()) == "g"
					) && ! (
						TString(p->GetName()) == "rD_k3pi"  ///< don't use these
						|| TString(p->GetName()) == "rD_kpi"
						// || TString(p->GetName()) == "dD_kpi"
						|| TString(p->GetName()) == "d_dk"
						|| TString(p->GetName()) == "d_dsk"
						))
		{
			varyPars->add(*p);
		}
		else if ( forceVariables.Contains(TString(p->GetName())+",") )
		{
			varyPars->add(*p);
		}
	}
	delete it;
	int nPars = varyPars->getSize();
	if ( debug ) cout << "Utils::fitToMinForce() : nPars = " << nPars << " => " << pow(2.,nPars) << " fits" << endl;
	if ( debug ) cout << "Utils::fitToMinForce() : varying ";
	if ( debug ) varyPars->Print();

	//////////

	r = fitToMinBringBackAngles(w->pdf(pdfName), false, printlevel);

	//////////

	int nErrors = 0;

	// We define a binary mask where each bit corresponds
	// to parameter at max or at min.
	for ( int i=0; i<pow(2.,nPars); i++ )
	{
		if ( debug ) cout << "Utils::fitToMinForce() : fit " << i << "        \r" << flush;
		setParameters(w, parsName, startPars->get(0));

		for ( int ip=0; ip<nPars; ip++ )
		{
			RooRealVar *p = (RooRealVar*)varyPars->at(ip);
			float oldMin = p->getMin();
			float oldMax = p->getMax();
			setLimit(w, p->GetName(), "force");
			if ( i/(int)pow(2.,ip) % 2==0 ) { p->setVal(p->getMin()); }
			if ( i/(int)pow(2.,ip) % 2==1 ) { p->setVal(p->getMax()); }
			p->setRange(oldMin, oldMax);
		}

		// check if start parameters are sensible, skip if they're not
		double startParChi2 = getChi2(w->pdf(pdfName));
		if ( startParChi2>2000 ){
			nErrors += 1;
			continue;
		}

		// refit
		RooFitResult *r2 = fitToMinBringBackAngles(w->pdf(pdfName), false, printlevel);

		// In case the initial fit failed, accept the second one.
		// If both failed, still select the second one and hope the
		// next fit succeeds.
		if ( !(r->edm()<1 && r->covQual()==3) ){
			delete r;
			r = r2;
		}
		else if ( r2->edm()<1 && r2->covQual()==3 && r2->minNll()<r->minNll() ){
			// better minimum found!
			delete r;
			r = r2;
		}
		else{
			delete r2;
		}
	}

	if ( debug ) cout << endl;
	if ( debug ) cout << "Utils::fitToMinForce() : nErrors = " << nErrors << endl;

	RooMsgService::instance().setGlobalKillBelow(INFO);

	// (re)set to best parameters
	setParameters(w, parsName, r);

	delete startPars;
	return r;
}
Beispiel #7
0
int main(int argc, char *argv[]){
 
  OptionParser(argc,argv);

  TStopwatch sw;
  sw.Start();

  RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
  RooMsgService::instance().setSilentMode(true);

  system("mkdir -p plots/fTest");

  vector<string> procs;
  split(procs,procString_,boost::is_any_of(","));
  
  TFile *inFile = TFile::Open(filename_.c_str());
  RooWorkspace *inWS = (RooWorkspace*)inFile->Get("cms_hgg_workspace");
  
  RooRealVar *mass = (RooRealVar*)inWS->var("CMS_hgg_mass");
  //mass->setBins(320);
  //mass->setRange(mass_-10,mass_+10);
  //mass->setBins(20);
  RooRealVar *MH = new RooRealVar("MH","MH",mass_);
  MH->setVal(mass_);
  MH->setConstant(true);

  map<string,pair<int,int> > choices;
  map<string,vector<RooPlot*> > plotsRV;
  map<string,vector<RooPlot*> > plotsWV;

  for (unsigned int p=0; p<procs.size(); p++){
    vector<RooPlot*> tempRV;
    vector<RooPlot*> tempWV;
    for (int cat=0; cat<ncats_; cat++){
      RooPlot *plotRV = mass->frame(Range(mass_-10,mass_+10));
      plotRV->SetTitle(Form("%s_cat%d_RV",procs[p].c_str(),cat));
      tempRV.push_back(plotRV);
      RooPlot *plotWV = mass->frame(Range(mass_-10,mass_+10));
      plotWV->SetTitle(Form("%s_cat%d_WV",procs[p].c_str(),cat));
      tempWV.push_back(plotWV);
    }
    plotsRV.insert(pair<string,vector<RooPlot*> >(procs[p],tempRV));
    plotsWV.insert(pair<string,vector<RooPlot*> >(procs[p],tempWV));
  }

  vector<int> colors;
  colors.push_back(kBlue);
  colors.push_back(kRed);
  colors.push_back(kGreen+2);
  colors.push_back(kMagenta+1);
  
  for (int cat=0; cat<ncats_; cat++){
    for (unsigned int p=0; p<procs.size(); p++){
      string proc = procs[p];
      RooDataSet *dataRV = (RooDataSet*)inWS->data(Form("sig_%s_mass_m%d_rv_cat%d",proc.c_str(),mass_,cat));
      RooDataSet *dataWV = (RooDataSet*)inWS->data(Form("sig_%s_mass_m%d_wv_cat%d",proc.c_str(),mass_,cat));
      //mass->setBins(160);
      //RooDataHist *dataRV = dataRVtemp->binnedClone();
      //RooDataHist *dataWV = dataWVtemp->binnedClone();
      //RooDataSet *dataRVw = (RooDataSet*)dataRVtemp->reduce(Form("CMS_hgg_mass>=%3d && CMS_hgg_mass<=%3d",mass_-10,mass_+10)); 
      //RooDataSet *dataWVw = (RooDataSet*)dataWVtemp->reduce(Form("CMS_hgg_mass>=%3d && CMS_hgg_mass<=%3d",mass_-10,mass_+10));
      //RooDataHist *dataRV = new RooDataHist(Form("roohist_%s",dataRVtemp->GetName()),Form("roohist_%s",dataRVtemp->GetName()),RooArgSet(*mass),*dataRVtemp);
      //RooDataHist *dataWV = new RooDataHist(Form("roohist_%s",dataWVtemp->GetName()),Form("roohist_%s",dataWVtemp->GetName()),RooArgSet(*mass),*dataWVtemp);
      //RooDataSet *dataRV = stripWeights(dataRVweight,mass);
      //RooDataSet *dataWV = stripWeights(dataWVweight,mass);
      //RooDataSet *data = (RooDataSet*)inWS->data(Form("sig_%s_mass_m%d_cat%d",proc.c_str(),mass_,cat));
     
      int rvChoice=0;
      int wvChoice=0;
      
      // right vertex
      int order=1;
      int prev_order=0;
      int cache_order=0;
      double thisNll=0.;
      double prevNll=1.e6;
      double chi2=0.;
      double prob=0.;

      dataRV->plotOn(plotsRV[proc][cat]);
      //while (prob<0.8) {
      while (order<5) {
        RooAddPdf *pdf = buildSumOfGaussians(Form("cat%d_g%d",cat,order),mass,MH,order);
        RooFitResult *fitRes = pdf->fitTo(*dataRV,Save(true),SumW2Error(true));//,Range(mass_-10,mass_+10));
        double myNll=0.;
        thisNll = fitRes->minNll();
        //double myNll = getMyNLL(mass,pdf,dataRV);
        //thisNll = getMyNLL(mass,pdf,dataRV);
        //RooAbsReal *nll = pdf->createNLL(*dataRV);
        //RooMinuit m(*nll);
        //m.migrad();
        //thisNll = nll->getVal();
        //plot(Form("plots/fTest/%s_cat%d_g%d_rv",proc.c_str(),cat,order),mass_,mass,dataRV,pdf);
        pdf->plotOn(plotsRV[proc][cat],LineColor(colors[order-1]));
        chi2 = 2.*(prevNll-thisNll);
        //if (chi2<0. && order>1) chi2=0.;
        int diffInDof = (2*order+(order-1))-(2*prev_order+(prev_order-1));
        prob = TMath::Prob(chi2,diffInDof);
        cout << "\t RV: " << cat << " " << order << " " << diffInDof << " " << prevNll << " " << thisNll << " " << myNll << " " << chi2 << " " << prob << endl;
        prevNll=thisNll;
        cache_order=prev_order;
        prev_order=order;
        order++;
      }
      rvChoice=cache_order;
      
      // wrong vertex
      order=1;
      prev_order=0;
      cache_order=0;
      thisNll=0.;
      prevNll=1.e6;
      chi2=0.;
      prob=0.;

      dataWV->plotOn(plotsWV[proc][cat]);
      while (order<4) {
      //while (prob<0.8) {
        RooAddPdf *pdf = buildSumOfGaussians(Form("cat%d_g%d",cat,order),mass,MH,order);
        RooFitResult *fitRes = pdf->fitTo(*dataWV,Save(true),SumW2Error(true));//,Range(mass_-10,mass_+10));
        double myNll=0.;
        thisNll = fitRes->minNll();
        //double myNll = getMyNLL(mass,pdf,dataRV);
        //thisNll = getMyNLL(mass,pdf,dataRV);
        //RooAbsReal *nll = pdf->createNLL(*dataWV);
        //RooMinuit m(*nll);
        //m.migrad();
        //thisNll = nll->getVal();
        //plot(Form("plots/fTest/%s_cat%d_g%d_wv",proc.c_str(),cat,order),mass_,mass,dataWV,pdf);
        pdf->plotOn(plotsWV[proc][cat],LineColor(colors[order-1]));
        chi2 = 2.*(prevNll-thisNll);
        //if (chi2<0. && order>1) chi2=0.;
        int diffInDof = (2*order+(order-1))-(2*prev_order+(prev_order-1));
        prob = TMath::Prob(chi2,diffInDof);
        cout << "\t WV: " << cat << " " << order << " " << diffInDof << " " << prevNll << " " << thisNll << " " << myNll << " " << chi2 << " " << prob << endl;
        prevNll=thisNll;
        cache_order=prev_order;
        prev_order=order;
        order++;
      }
      wvChoice=cache_order;

      choices.insert(pair<string,pair<int,int> >(Form("%s_cat%d",proc.c_str(),cat),make_pair(rvChoice,wvChoice)));
    } 
  }

  TLegend *leg = new TLegend(0.6,0.6,0.89,0.89);
  leg->SetFillColor(0);
  leg->SetLineColor(0);
  TH1F *h1 = new TH1F("h1","",1,0,1);
  h1->SetLineColor(colors[0]);
  leg->AddEntry(h1,"1st order","L");
  TH1F *h2 = new TH1F("h2","",1,0,1);
  h2->SetLineColor(colors[1]);
  leg->AddEntry(h2,"2nd order","L");
  TH1F *h3 = new TH1F("h3","",1,0,1);
  h3->SetLineColor(colors[2]);
  leg->AddEntry(h3,"3rd order","L");
  TH1F *h4 = new TH1F("h4","",1,0,1);
  h4->SetLineColor(colors[3]);
  leg->AddEntry(h4,"4th order","L");

  TCanvas *canv = new TCanvas();
  for (map<string,vector<RooPlot*> >::iterator plotIt=plotsRV.begin(); plotIt!=plotsRV.end(); plotIt++){
    string proc = plotIt->first;
    for (int cat=0; cat<ncats_; cat++){
      RooPlot *plot = plotIt->second.at(cat);
      plot->Draw();
      leg->Draw();
      canv->Print(Form("plots/fTest/rv_%s_cat%d.pdf",proc.c_str(),cat));
    }
  }
  for (map<string,vector<RooPlot*> >::iterator plotIt=plotsWV.begin(); plotIt!=plotsWV.end(); plotIt++){
    string proc = plotIt->first;
    for (int cat=0; cat<ncats_; cat++){
      RooPlot *plot = plotIt->second.at(cat);
      plot->Draw();
      leg->Draw();
      canv->Print(Form("plots/fTest/wv_%s_cat%d.pdf",proc.c_str(),cat));
    }
  }
  delete canv;

  cout << "Recommended options" << endl;
  for (map<string,pair<int,int> >::iterator it=choices.begin(); it!=choices.end(); it++){
    cout << "\t " << it->first << " - " << it->second.first << " " << it->second.second << endl; 
  }

  inFile->Close();
  return 0;
}
Beispiel #8
0
   void constrained_scan( const char* wsfile = "outputfiles/ws.root",
                          const char* new_poi_name="mu_bg_4b_msig_met1",
                          double constraintWidth=1.5,
                          int npoiPoints = 20,
                          double poiMinVal = 0.,
                          double poiMaxVal = 10.0,
                          double ymax = 9.,
                          int verbLevel=1  ) {

      TString outputdir("outputfiles") ;

      gStyle->SetOptStat(0) ;

      TFile* wstf = new TFile( wsfile ) ;
      RooWorkspace* ws = dynamic_cast<RooWorkspace*>( wstf->Get("ws") );
      ws->Print() ;

      RooDataSet* rds = (RooDataSet*) ws->obj( "hbb_observed_rds" ) ;
      cout << "\n\n\n  ===== RooDataSet ====================\n\n" << endl ;
      rds->Print() ;
      rds->printMultiline(cout, 1, kTRUE, "") ;

      RooRealVar* rv_sig_strength = ws->var("sig_strength") ;
      if ( rv_sig_strength == 0x0 ) { printf("\n\n *** can't find sig_strength in workspace.\n\n" ) ; return ; }

      RooAbsPdf* likelihood = ws->pdf("likelihood") ;
      if ( likelihood == 0x0 ) { printf("\n\n *** can't find likelihood in workspace.\n\n" ) ; return ; }
      printf("\n\n Likelihood:\n") ;
      likelihood -> Print() ;



      /////rv_sig_strength -> setConstant( kFALSE ) ;
      rv_sig_strength -> setVal(0.) ;
      rv_sig_strength -> setConstant( kTRUE ) ;

      likelihood->fitTo( *rds, Save(false), PrintLevel(0), Hesse(true), Strategy(1) ) ;
      //RooFitResult* fitResult = likelihood->fitTo( *rds, Save(true), PrintLevel(0), Hesse(true), Strategy(1) ) ;
      //double minNllSusyFloat = fitResult->minNll() ;
      //double susy_ss_atMinNll = rv_sig_strength -> getVal() ;

      RooMsgService::instance().getStream(1).removeTopic(Minimization) ;
      RooMsgService::instance().getStream(1).removeTopic(Fitting) ;



     //-- Construct the new POI parameter.
      RooAbsReal* new_poi_rar(0x0) ;

      new_poi_rar = ws->var( new_poi_name ) ;
      if ( new_poi_rar == 0x0 ) {
         printf("\n\n New POI %s is not a variable.  Trying function.\n\n", new_poi_name ) ;
         new_poi_rar = ws->function( new_poi_name ) ;
         if ( new_poi_rar == 0x0 ) {
            printf("\n\n New POI %s is not a function.  I quit.\n\n", new_poi_name ) ;
            return ;
         } else {
            printf("\n Found it.\n\n") ;
         }
      } else {
         printf("\n\n     New POI %s is a variable with current value %.1f.\n\n", new_poi_name, new_poi_rar->getVal() ) ;
      }

       double startPoiVal = new_poi_rar->getVal() ;


       RooAbsReal* nll = likelihood -> createNLL( *rds, Verbose(true) ) ;

       RooRealVar* rrv_poiValue = new RooRealVar( "poiValue", "poiValue", 0., -10000., 10000. ) ;

       RooRealVar* rrv_constraintWidth = new RooRealVar("constraintWidth","constraintWidth", 0.1, 0.1, 1000. ) ;
       rrv_constraintWidth -> setVal( constraintWidth ) ;
       rrv_constraintWidth -> setConstant(kTRUE) ;


       RooMinuit* rminuit( 0x0 ) ;


       RooMinuit* rminuit_uc = new RooMinuit( *nll  ) ;

       rminuit_uc->setPrintLevel(verbLevel-1) ;
       rminuit_uc->setNoWarn() ;

       rminuit_uc->migrad() ;
       rminuit_uc->hesse() ;

       RooFitResult* rfr_uc = rminuit_uc->fit("mr") ;

       double floatParInitVal[10000] ;
       char   floatParName[10000][100] ;
       int nFloatParInitVal(0) ;
       RooArgList ral_floats = rfr_uc->floatParsFinal() ;
       TIterator* floatParIter = ral_floats.createIterator() ;
       {
          RooRealVar* par ;
          while ( (par = (RooRealVar*) floatParIter->Next()) ) {
             sprintf( floatParName[nFloatParInitVal], "%s", par->GetName() ) ;
             floatParInitVal[nFloatParInitVal] = par->getVal() ;
             nFloatParInitVal++ ;
          }
       }


       printf("\n\n Unbiased best value for new POI %s is : %7.1f\n\n", new_poi_rar->GetName(), new_poi_rar->getVal() ) ;
       double best_poi_val = new_poi_rar->getVal() ;

       char minuit_formula[10000] ;
       sprintf( minuit_formula, "%s+%s*(%s-%s)*(%s-%s)",
         nll->GetName(),
         rrv_constraintWidth->GetName(),
         new_poi_rar->GetName(), rrv_poiValue->GetName(),
         new_poi_rar->GetName(), rrv_poiValue->GetName()
          ) ;

       printf("\n\n Creating new minuit variable with formula: %s\n\n", minuit_formula ) ;
       RooFormulaVar* new_minuit_var = new RooFormulaVar("new_minuit_var", minuit_formula,
           RooArgList( *nll,
                       *rrv_constraintWidth,
                       *new_poi_rar, *rrv_poiValue,
                       *new_poi_rar, *rrv_poiValue
                       ) ) ;

       printf("\n\n Current value is %.2f\n\n",
            new_minuit_var->getVal() ) ;

       rminuit = new RooMinuit( *new_minuit_var ) ;


       RooAbsReal* plot_var = nll ;

       printf("\n\n Current value is %.2f\n\n",
            plot_var->getVal() ) ;


       rminuit->setPrintLevel(verbLevel-1) ;
       if ( verbLevel <=0 ) { rminuit->setNoWarn() ; }


       if ( poiMinVal < 0. && poiMaxVal < 0. ) {

          printf("\n\n Automatic determination of scan range.\n\n") ;

          if ( startPoiVal <= 0. ) {
             printf("\n\n *** POI starting value zero or negative %g.  Quit.\n\n\n", startPoiVal ) ;
             return ;
          }

          poiMinVal = startPoiVal - 3.5 * sqrt(startPoiVal) ;
          poiMaxVal = startPoiVal + 6.0 * sqrt(startPoiVal) ;

          if ( poiMinVal < 0. ) { poiMinVal = 0. ; }

          printf("    Start val = %g.   Scan range:   %g  to  %g\n\n", startPoiVal, poiMinVal, poiMaxVal ) ;


       }



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


       double poiVals_scanDown[1000] ;
       double nllVals_scanDown[1000] ;

       //-- Do scan down from best value.

       printf("\n\n +++++ Starting scan down from best value.\n\n") ;

       double minNllVal(1.e9) ;

       for ( int poivi=0; poivi < npoiPoints/2 ; poivi++ ) {

          ////double poiValue = poiMinVal + poivi*(poiMaxVal-poiMinVal)/(1.*(npoiPoints-1)) ;
          double poiValue = best_poi_val - poivi*(best_poi_val-poiMinVal)/(1.*(npoiPoints/2-1)) ;

          rrv_poiValue -> setVal( poiValue ) ;
          rrv_poiValue -> setConstant( kTRUE ) ;


       //+++++++++++++++++++++++++++++++++++

          rminuit->migrad() ;
          rminuit->hesse() ;
          RooFitResult* rfr = rminuit->save() ;

       //+++++++++++++++++++++++++++++++++++


          if ( verbLevel > 0 ) { rfr->Print("v") ; }


          float fit_minuit_var_val = rfr->minNll() ;

          printf(" %02d : poi constraint = %.2f : allvars : MinuitVar, createNLL, PV, POI :    %.5f   %.5f   %.5f   %.5f\n",
                poivi, rrv_poiValue->getVal(), fit_minuit_var_val, nll->getVal(), plot_var->getVal(), new_poi_rar->getVal() ) ;
          cout << flush ;



          poiVals_scanDown[poivi] = new_poi_rar->getVal() ;
          nllVals_scanDown[poivi] = plot_var->getVal() ;

          if ( nllVals_scanDown[poivi] < minNllVal ) { minNllVal = nllVals_scanDown[poivi] ; }

          delete rfr ;


       } // poivi


       printf("\n\n +++++ Resetting floats to best fit values.\n\n") ;

       for ( int pi=0; pi<nFloatParInitVal; pi++ ) {
          RooRealVar* par = ws->var( floatParName[pi] ) ;
          par->setVal( floatParInitVal[pi] ) ;
       } // pi.

       printf("\n\n +++++ Starting scan up from best value.\n\n") ;

      //-- Now do scan up.

       double poiVals_scanUp[1000] ;
       double nllVals_scanUp[1000] ;

       for ( int poivi=0; poivi < npoiPoints/2 ; poivi++ ) {

          double poiValue = best_poi_val + poivi*(poiMaxVal-best_poi_val)/(1.*(npoiPoints/2-1)) ;

          rrv_poiValue -> setVal( poiValue ) ;
          rrv_poiValue -> setConstant( kTRUE ) ;


       //+++++++++++++++++++++++++++++++++++

          rminuit->migrad() ;
          rminuit->hesse() ;
          RooFitResult* rfr = rminuit->save() ;

       //+++++++++++++++++++++++++++++++++++


          if ( verbLevel > 0 ) { rfr->Print("v") ; }


          float fit_minuit_var_val = rfr->minNll() ;

          printf(" %02d : poi constraint = %.2f : allvars : MinuitVar, createNLL, PV, POI :    %.5f   %.5f   %.5f   %.5f\n",
                poivi, rrv_poiValue->getVal(), fit_minuit_var_val, nll->getVal(), plot_var->getVal(), new_poi_rar->getVal() ) ;
          cout << flush ;

          poiVals_scanUp[poivi] = new_poi_rar->getVal() ;
          nllVals_scanUp[poivi] = plot_var->getVal() ;

          if ( nllVals_scanUp[poivi] < minNllVal ) { minNllVal = nllVals_scanUp[poivi] ; }

          delete rfr ;


       } // poivi





       double poiVals[1000] ;
       double nllVals[1000] ;

       int pointCount(0) ;
       for ( int pi=0; pi<npoiPoints/2; pi++ ) {
          poiVals[pi] = poiVals_scanDown[(npoiPoints/2-1)-pi] ;
          nllVals[pi] = nllVals_scanDown[(npoiPoints/2-1)-pi] ;
          pointCount++ ;
       }
       for ( int pi=1; pi<npoiPoints/2; pi++ ) {
          poiVals[pointCount] = poiVals_scanUp[pi] ;
          nllVals[pointCount] = nllVals_scanUp[pi] ;
          pointCount++ ;
       }
       npoiPoints = pointCount ;

       printf("\n\n --- TGraph arrays:\n") ;
       for ( int i=0; i<npoiPoints; i++ ) {
          printf("  %2d : poi = %6.1f, nll = %g\n", i, poiVals[i], nllVals[i] ) ;
       }
       printf("\n\n") ;

       double nllDiffVals[1000] ;

       double poiAtMinlnL(-1.) ;
       double poiAtMinusDelta2(-1.) ;
       double poiAtPlusDelta2(-1.) ;
       for ( int poivi=0; poivi < npoiPoints ; poivi++ ) {
          nllDiffVals[poivi] = 2.*(nllVals[poivi] - minNllVal) ;
          double poiValue = poiMinVal + poivi*(poiMaxVal-poiMinVal)/(1.*npoiPoints) ;
          if ( nllDiffVals[poivi] < 0.01 ) { poiAtMinlnL = poiValue ; }
          if ( poiAtMinusDelta2 < 0. && nllDiffVals[poivi] < 2.5 ) { poiAtMinusDelta2 = poiValue ; }
          if ( poiAtMinlnL > 0. && poiAtPlusDelta2 < 0. && nllDiffVals[poivi] > 2.0 ) { poiAtPlusDelta2 = poiValue ; }
       } // poivi

       printf("\n\n Estimates for poi at delta ln L = -2, 0, +2:  %g ,   %g ,   %g\n\n", poiAtMinusDelta2, poiAtMinlnL, poiAtPlusDelta2 ) ;




      //--- Main canvas

       TCanvas* cscan = (TCanvas*) gDirectory->FindObject("cscan") ;
       if ( cscan == 0x0 ) {
          printf("\n Creating canvas.\n\n") ;
          cscan = new TCanvas("cscan","Delta nll") ;
       }


       char gname[1000] ;

       TGraph* graph = new TGraph( npoiPoints, poiVals, nllDiffVals ) ;
       sprintf( gname, "scan_%s", new_poi_name ) ;
       graph->SetName( gname ) ;

       double poiBest(-1.) ;
       double poiMinus1stdv(-1.) ;
       double poiPlus1stdv(-1.) ;
       double poiMinus2stdv(-1.) ;
       double poiPlus2stdv(-1.) ;
       double twoDeltalnLMin(1e9) ;

       int nscan(1000) ;
       for ( int xi=0; xi<nscan; xi++ ) {

          double x = poiVals[0] + xi*(poiVals[npoiPoints-1]-poiVals[0])/(nscan-1) ;

          double twoDeltalnL = graph -> Eval( x, 0, "S" ) ;

          if ( poiMinus1stdv < 0. && twoDeltalnL < 1.0 ) { poiMinus1stdv = x ; printf(" set m1 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}
          if ( poiMinus2stdv < 0. && twoDeltalnL < 4.0 ) { poiMinus2stdv = x ; printf(" set m2 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}
          if ( twoDeltalnL < twoDeltalnLMin ) { poiBest = x ; twoDeltalnLMin = twoDeltalnL ; }
          if ( twoDeltalnLMin < 0.3 && poiPlus1stdv < 0. && twoDeltalnL > 1.0 ) { poiPlus1stdv = x ; printf(" set p1 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}
          if ( twoDeltalnLMin < 0.3 && poiPlus2stdv < 0. && twoDeltalnL > 4.0 ) { poiPlus2stdv = x ; printf(" set p2 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}

          if ( xi%100 == 0 ) { printf( " %4d : poi=%6.2f,  2DeltalnL = %6.2f\n", xi, x, twoDeltalnL ) ; }

       }
       printf("\n\n POI estimate :  %g  +%g  -%g    [%g,%g],   two sigma errors: +%g  -%g   [%g,%g]\n\n",
               poiBest,
               (poiPlus1stdv-poiBest), (poiBest-poiMinus1stdv), poiMinus1stdv, poiPlus1stdv,
               (poiPlus2stdv-poiBest), (poiBest-poiMinus2stdv), poiMinus2stdv, poiPlus2stdv
               ) ;

       printf(" %s val,pm1sig,pm2sig: %7.2f  %7.2f  %7.2f  %7.2f  %7.2f\n",
          new_poi_name, poiBest, (poiPlus1stdv-poiBest), (poiBest-poiMinus1stdv), (poiPlus2stdv-poiBest), (poiBest-poiMinus2stdv) ) ;

       char htitle[1000] ;
       sprintf(htitle, "%s profile likelihood scan: -2ln(L/Lm)", new_poi_name ) ;
       TH1F* hscan = new TH1F("hscan", htitle, 10, poiMinVal, poiMaxVal ) ;
       hscan->SetMinimum(0.) ;
       hscan->SetMaximum(ymax) ;


       hscan->DrawCopy() ;
       graph->SetLineColor(4) ;
       graph->SetLineWidth(3) ;
       graph->Draw("CP") ;
       gPad->SetGridx(1) ;
       gPad->SetGridy(1) ;
       cscan->Update() ;

       TLine* line = new TLine() ;
       line->SetLineColor(2) ;
       line->DrawLine(poiMinVal, 1., poiPlus1stdv, 1.) ;
       line->DrawLine(poiMinus1stdv,0., poiMinus1stdv, 1.) ;
       line->DrawLine(poiPlus1stdv ,0., poiPlus1stdv , 1.) ;

       TText* text = new TText() ;
       text->SetTextSize(0.04) ;
       char tstring[1000] ;

       sprintf( tstring, "%s = %.1f +%.1f -%.1f", new_poi_name, poiBest, (poiPlus1stdv-poiBest), (poiBest-poiMinus1stdv) ) ;
       text -> DrawTextNDC( 0.15, 0.85, tstring ) ;

       sprintf( tstring, "68%% interval [%.1f,  %.1f]", poiMinus1stdv, poiPlus1stdv ) ;
       text -> DrawTextNDC( 0.15, 0.78, tstring ) ;


       char hname[1000] ;
       sprintf( hname, "hscanout_%s", new_poi_name ) ;
       TH1F* hsout = new TH1F( hname,"scan results",4,0.,4.) ;
       double obsVal(-1.) ;
       hsout->SetBinContent(1, obsVal ) ;
       hsout->SetBinContent(2, poiPlus1stdv ) ;
       hsout->SetBinContent(3, poiBest ) ;
       hsout->SetBinContent(4, poiMinus1stdv ) ;
       TAxis* xaxis = hsout->GetXaxis() ;
       xaxis->SetBinLabel(1,"Observed val.") ;
       xaxis->SetBinLabel(2,"Model+1sd") ;
       xaxis->SetBinLabel(3,"Model") ;
       xaxis->SetBinLabel(4,"Model-1sd") ;

       char outrootfile[10000] ;
       sprintf( outrootfile, "%s/scan-ff-%s.root", outputdir.Data(), new_poi_name ) ;

       char outpdffile[10000] ;
       sprintf( outpdffile, "%s/scan-ff-%s.pdf", outputdir.Data(), new_poi_name ) ;

       cscan->Update() ; cscan->Draw() ;

       printf("\n Saving %s\n", outpdffile ) ;
       cscan->SaveAs( outpdffile ) ;



     //--- save in root file

       printf("\n Saving %s\n", outrootfile ) ;
       TFile fout(outrootfile,"recreate") ;
       graph->Write() ;
       hsout->Write() ;
       fout.Close() ;

       delete ws ;
       wstf->Close() ;




   } // constrained_scan.
///
/// Perform the 1d Prob scan.
/// Saves chi2 values and the prob-Scan p-values in a root tree
/// For the datasets stuff, we do not yet have a MethodDatasetsProbScan class, so we do it all in
/// MethodDatasetsProbScan
/// \param nRun Part of the root tree file name to facilitate parallel production.
///
int MethodDatasetsProbScan::scan1d(bool fast, bool reverse)
{
	if (fast) return 0; // tmp

	if ( arg->debug ) cout << "MethodDatasetsProbScan::scan1d() : starting ... " << endl;

    // Set limit to all parameters.
    this->loadParameterLimits(); /// Default is "free", if not changed by cmd-line parameter


    // Define scan parameter and scan range.
    RooRealVar *parameterToScan = w->var(scanVar1);
    float parameterToScan_min = hCL->GetXaxis()->GetXmin();
    float parameterToScan_max = hCL->GetXaxis()->GetXmax();

		// do a free fit
		RooFitResult *result = this->loadAndFit(this->pdf); // fit on data
		assert(result);
    RooSlimFitResult *slimresult = new RooSlimFitResult(result,true);
		slimresult->setConfirmed(true);
		solutions.push_back(slimresult);
		double freeDataFitValue = w->var(scanVar1)->getVal();

    // Define outputfile
    system("mkdir -p root");
    TString probResName = Form("root/scan1dDatasetsProb_" + this->pdf->getName() + "_%ip" + "_" + scanVar1 + ".root", arg->npoints1d);
    TFile* outputFile = new TFile(probResName, "RECREATE");

    // Set up toy root tree
    this->probScanTree = new ToyTree(this->pdf, arg);
    this->probScanTree->init();
    this->probScanTree->nrun = -999; //\todo: why does this branch even exist in the output tree of the prob scan?

    // Save parameter values that were active at function
    // call. We'll reset them at the end to be transparent
    // to the outside.
    RooDataSet* parsFunctionCall = new RooDataSet("parsFunctionCall", "parsFunctionCall", *w->set(pdf->getParName()));
    parsFunctionCall->add(*w->set(pdf->getParName()));

    // start scan
    cout << "MethodDatasetsProbScan::scan1d_prob() : starting ... with " << nPoints1d << " scanpoints..." << endl;
    ProgressBar progressBar(arg, nPoints1d);
    for ( int i = 0; i < nPoints1d; i++ )
    {
        progressBar.progress();
        // scanpoint is calculated using min, max, which are the hCL x-Axis limits set in this->initScan()
        // this uses the "scan" range, as expected
        // don't add half the bin size. try to solve this within plotting method

        float scanpoint = parameterToScan_min + (parameterToScan_max - parameterToScan_min) * (double)i / ((double)nPoints1d - 1);
				if (arg->debug) cout << "DEBUG in MethodDatasetsProbScan::scan1d_prob() " << scanpoint << " " << parameterToScan_min << " " << parameterToScan_max << endl;

        this->probScanTree->scanpoint = scanpoint;

        if (arg->debug) cout << "DEBUG in MethodDatasetsProbScan::scan1d_prob() - scanpoint in step " << i << " : " << scanpoint << endl;

        // don't scan in unphysical region
        // by default this means checking against "free" range
        if ( scanpoint < parameterToScan->getMin() || scanpoint > parameterToScan->getMax() + 2e-13 ) {
            cout << "it seems we are scanning in an unphysical region: " << scanpoint << " < " << parameterToScan->getMin() << " or " << scanpoint << " > " << parameterToScan->getMax() + 2e-13 << endl;
            exit(EXIT_FAILURE);
        }

        // FIT TO REAL DATA WITH FIXED HYPOTHESIS(=SCANPOINT).
        // THIS GIVES THE NUMERATOR FOR THE PROFILE LIKELIHOOD AT THE GIVEN HYPOTHESIS
        // THE RESULTING NUISANCE PARAMETERS TOGETHER WITH THE GIVEN HYPOTHESIS ARE ALSO
        // USED WHEN SIMULATING THE TOY DATA FOR THE FELDMAN-COUSINS METHOD FOR THIS HYPOTHESIS(=SCANPOINT)
        // Here the scanvar has to be fixed -> this is done once per scanpoint
        // and provides the scanner with the DeltaChi2 for the data as reference
        // additionally the nuisances are set to the resulting fit values

        parameterToScan->setVal(scanpoint);
        parameterToScan->setConstant(true);

        RooFitResult *result = this->loadAndFit(this->pdf); // fit on data
        assert(result);

        if (arg->debug) {
            cout << "DEBUG in MethodDatasetsProbScan::scan1d_prob() - minNll data scan at scan point " << scanpoint << " : " << 2 * result->minNll() << ": "<< 2 * pdf->getMinNll() << endl;
        }
        this->probScanTree->statusScanData = result->status();

        // set chi2 of fixed fit: scan fit on data
        // CAVEAT: chi2min from fitresult gives incompatible results to chi2min from pdf
        // this->probScanTree->chi2min           = 2 * result->minNll();
        this->probScanTree->chi2min           = 2 * pdf->getMinNll();
        this->probScanTree->covQualScanData   = result->covQual();
        this->probScanTree->scanbest  = freeDataFitValue;

        // After doing the fit with the parameter of interest constrained to the scanpoint,
        // we are now saving the fit values of the nuisance parameters. These values will be
        // used to generate toys according to the PLUGIN method.
        this->probScanTree->storeParsScan(); // \todo : figure out which one of these is semantically the right one

        this->pdf->deleteNLL();

        // also save the chi2 of the free data fit to the tree:
        this->probScanTree->chi2minGlobal = this->getChi2minGlobal();
        this->probScanTree->chi2minBkg = this->getChi2minBkg();

        this->probScanTree->genericProbPValue = this->getPValueTTestStatistic(this->probScanTree->chi2min - this->probScanTree->chi2minGlobal);
        this->probScanTree->fill();

        if(arg->debug && pdf->getBkgPdf())
        {
            float pval_cls = this->getPValueTTestStatistic(this->probScanTree->chi2min - this->probScanTree->chi2minBkg, true);
            cout << "DEBUG in MethodDatasetsProbScan::scan1d() - p value CLs: " << pval_cls << endl;
        }


        // reset
        setParameters(w, pdf->getParName(), parsFunctionCall->get(0));
        //setParameters(w, pdf->getObsName(), obsDataset->get(0));
    } // End of npoints loop
    probScanTree->writeToFile();
    if (bkgOnlyFitResult) bkgOnlyFitResult->Write();
    if (dataFreeFitResult) dataFreeFitResult->Write();
    outputFile->Close();
    std::cout << "Wrote ToyTree to file" << std::endl;
    delete parsFunctionCall;

    // This is kind of a hack. The effect is supposed to be the same as callincg
    // this->sethCLFromProbScanTree(); here, but the latter gives a segfault somehow....
    // \todo: use this->sethCLFromProbScanTree() directly after figuring out the cause of the segfault.
    this->loadScanFromFile();

    return 0;
}
   void ws_constrained_profile3D( const char* wsfile = "rootfiles/ws-data-unblind.root",
                                   const char* new_poi_name = "n_M234_H4_3b",
                                   int npoiPoints = 20,
                                   double poiMinVal = 0.,
                                   double poiMaxVal = 20.,
                                   double constraintWidth = 1.5,
                                   double ymax = 10.,
                                   int verbLevel=0 ) {


     gStyle->SetOptStat(0) ;

     //--- make output directory.

     char command[10000] ;
     sprintf( command, "basename %s", wsfile ) ;
     TString wsfilenopath = gSystem->GetFromPipe( command ) ;
     wsfilenopath.ReplaceAll(".root","") ;
     char outputdirstr[1000] ;
     sprintf( outputdirstr, "outputfiles/scans-%s", wsfilenopath.Data() ) ;
     TString outputdir( outputdirstr ) ;


     printf("\n\n Creating output directory: %s\n\n", outputdir.Data() ) ;
     sprintf(command, "mkdir -p %s", outputdir.Data() ) ;
     gSystem->Exec( command ) ;


     //--- Tell RooFit to shut up about anything less important than an ERROR.
      RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;



       if ( verbLevel > 0 ) { printf("\n\n Verbose level : %d\n\n", verbLevel) ; }


       TFile* wstf = new TFile( wsfile ) ;

       RooWorkspace* ws = dynamic_cast<RooWorkspace*>( wstf->Get("ws") );

       if ( verbLevel > 0 ) { ws->Print() ; }






       RooDataSet* rds = (RooDataSet*) ws->obj( "ra2b_observed_rds" ) ;

       if ( verbLevel > 0 ) {
          printf("\n\n\n  ===== RooDataSet ====================\n\n") ;
          rds->Print() ;
          rds->printMultiline(cout, 1, kTRUE, "") ;
       }





       ModelConfig* modelConfig = (ModelConfig*) ws->obj( "SbModel" ) ;
       RooAbsPdf* likelihood = modelConfig->GetPdf() ;

       RooRealVar* rrv_mu_susy_all0lep = ws->var("mu_susy_all0lep") ;
       if ( rrv_mu_susy_all0lep == 0x0 ) {
          printf("\n\n\n *** can't find mu_susy_all0lep in workspace.  Quitting.\n\n\n") ;
          return ;
       }





       //-- do BG only.
       rrv_mu_susy_all0lep->setVal(0.) ;
       rrv_mu_susy_all0lep->setConstant( kTRUE ) ;










       //-- do a prefit.

       printf("\n\n\n ====== Pre fit with unmodified nll var.\n\n") ;

       RooFitResult* dataFitResultSusyFixed = likelihood->fitTo(*rds, Save(true),Hesse(false),Minos(false),Strategy(1),PrintLevel(verbLevel));
       int dataSusyFixedFitCovQual = dataFitResultSusyFixed->covQual() ;
       if ( dataSusyFixedFitCovQual < 2 ) { printf("\n\n\n *** Failed fit!  Cov qual %d.  Quitting.\n\n", dataSusyFixedFitCovQual ) ; return ; }
       double dataFitSusyFixedNll = dataFitResultSusyFixed->minNll() ;

       if ( verbLevel > 0 ) {
          dataFitResultSusyFixed->Print("v") ;
       }

       printf("\n\n Nll value, from fit result : %.3f\n\n", dataFitSusyFixedNll ) ;

       delete dataFitResultSusyFixed ;






       //-- Construct the new POI parameter.
       RooAbsReal* new_poi_rar(0x0) ;

       new_poi_rar = ws->var( new_poi_name ) ;
       if ( new_poi_rar == 0x0 ) {
          printf("\n\n New POI %s is not a variable.  Trying function.\n\n", new_poi_name ) ;
          new_poi_rar = ws->function( new_poi_name ) ;
          if ( new_poi_rar == 0x0 ) {
             printf("\n\n New POI %s is not a function.  I quit.\n\n", new_poi_name ) ;
             return ;
          }
       } else {
          printf("\n\n     New POI %s is a variable with current value %.1f.\n\n", new_poi_name, new_poi_rar->getVal() ) ;
       }








       if ( npoiPoints <=0 ) {
          printf("\n\n Quitting now.\n\n" ) ;
          return ;
       }


       double startPoiVal = new_poi_rar->getVal() ;



      //--- The RooNLLVar is NOT equivalent to what minuit uses.
  //   RooNLLVar* nll = new RooNLLVar("nll","nll", *likelihood, *rds ) ;
  //   printf("\n\n Nll value, from construction : %.3f\n\n", nll->getVal() ) ;

      //--- output of createNLL IS what minuit uses, so use that.
       RooAbsReal* nll = likelihood -> createNLL( *rds, Verbose(true) ) ;

       RooRealVar* rrv_poiValue = new RooRealVar( "poiValue", "poiValue", 0., -10000., 10000. ) ;
   /// rrv_poiValue->setVal( poiMinVal ) ;
   /// rrv_poiValue->setConstant(kTRUE) ;

       RooRealVar* rrv_constraintWidth = new RooRealVar("constraintWidth","constraintWidth", 0.1, 0.1, 1000. ) ;
       rrv_constraintWidth -> setVal( constraintWidth ) ;
       rrv_constraintWidth -> setConstant(kTRUE) ;




       if ( verbLevel > 0 ) {
          printf("\n\n ======= debug likelihood print\n\n") ;
          likelihood->Print("v") ;
          printf("\n\n ======= debug nll print\n\n") ;
          nll->Print("v") ;
       }






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

       RooMinuit* rminuit( 0x0 ) ;


       RooMinuit* rminuit_uc = new RooMinuit( *nll  ) ;

       rminuit_uc->setPrintLevel(verbLevel-1) ;
       rminuit_uc->setNoWarn() ;

       rminuit_uc->migrad() ;
       rminuit_uc->hesse() ;

       RooFitResult* rfr_uc = rminuit_uc->fit("mr") ;

       double floatParInitVal[10000] ;
       char   floatParName[10000][100] ;
       int nFloatParInitVal(0) ;
       RooArgList ral_floats = rfr_uc->floatParsFinal() ;
       TIterator* floatParIter = ral_floats.createIterator() ;
       {
          RooRealVar* par ;
          while ( (par = (RooRealVar*) floatParIter->Next()) ) {
             sprintf( floatParName[nFloatParInitVal], "%s", par->GetName() ) ;
             floatParInitVal[nFloatParInitVal] = par->getVal() ;
             nFloatParInitVal++ ;
          }
       }



     //-------

       printf("\n\n Unbiased best value for new POI %s is : %7.1f\n\n", new_poi_rar->GetName(), new_poi_rar->getVal() ) ;
       double best_poi_val = new_poi_rar->getVal() ;

       char minuit_formula[10000] ;
       sprintf( minuit_formula, "%s+%s*(%s-%s)*(%s-%s)",
         nll->GetName(),
         rrv_constraintWidth->GetName(),
         new_poi_rar->GetName(), rrv_poiValue->GetName(),
         new_poi_rar->GetName(), rrv_poiValue->GetName()
          ) ;

       printf("\n\n Creating new minuit variable with formula: %s\n\n", minuit_formula ) ;
       RooFormulaVar* new_minuit_var = new RooFormulaVar("new_minuit_var", minuit_formula,
           RooArgList( *nll,
                       *rrv_constraintWidth,
                       *new_poi_rar, *rrv_poiValue,
                       *new_poi_rar, *rrv_poiValue
                       ) ) ;

       printf("\n\n Current value is %.2f\n\n",
            new_minuit_var->getVal() ) ;

       rminuit = new RooMinuit( *new_minuit_var ) ;


       RooAbsReal* plot_var = nll ;

       printf("\n\n Current value is %.2f\n\n",
            plot_var->getVal() ) ;




       rminuit->setPrintLevel(verbLevel-1) ;
       if ( verbLevel <=0 ) { rminuit->setNoWarn() ; }

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

       //-- If POI range is -1 to -1, automatically determine the range using the set value.

       if ( poiMinVal < 0. && poiMaxVal < 0. ) {

          printf("\n\n Automatic determination of scan range.\n\n") ;

          if ( startPoiVal <= 0. ) {
             printf("\n\n *** POI starting value zero or negative %g.  Quit.\n\n\n", startPoiVal ) ;
             return ;
          }

          poiMinVal = startPoiVal - 3.5 * sqrt(startPoiVal) ;
          poiMaxVal = startPoiVal + 6.0 * sqrt(startPoiVal) ;

          if ( poiMinVal < 0. ) { poiMinVal = 0. ; }

          printf("    Start val = %g.   Scan range:   %g  to  %g\n\n", startPoiVal, poiMinVal, poiMaxVal ) ;


       }



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


       double poiVals_scanDown[1000] ;
       double nllVals_scanDown[1000] ;

       //-- Do scan down from best value.

       printf("\n\n +++++ Starting scan down from best value.\n\n") ;

       double minNllVal(1.e9) ;

       for ( int poivi=0; poivi < npoiPoints/2 ; poivi++ ) {

          ////double poiValue = poiMinVal + poivi*(poiMaxVal-poiMinVal)/(1.*(npoiPoints-1)) ;
          double poiValue = best_poi_val - poivi*(best_poi_val-poiMinVal)/(1.*(npoiPoints/2-1)) ;

          rrv_poiValue -> setVal( poiValue ) ;
          rrv_poiValue -> setConstant( kTRUE ) ;


       //+++++++++++++++++++++++++++++++++++

          rminuit->migrad() ;
          rminuit->hesse() ;
          RooFitResult* rfr = rminuit->save() ;

       //+++++++++++++++++++++++++++++++++++


          if ( verbLevel > 0 ) { rfr->Print("v") ; }


          float fit_minuit_var_val = rfr->minNll() ;

          printf(" %02d : poi constraint = %.2f : allvars : MinuitVar, createNLL, PV, POI :    %.5f   %.5f   %.5f   %.5f\n",
                poivi, rrv_poiValue->getVal(), fit_minuit_var_val, nll->getVal(), plot_var->getVal(), new_poi_rar->getVal() ) ;
          cout << flush ;



          poiVals_scanDown[poivi] = new_poi_rar->getVal() ;
          nllVals_scanDown[poivi] = plot_var->getVal() ;

          if ( nllVals_scanDown[poivi] < minNllVal ) { minNllVal = nllVals_scanDown[poivi] ; }

          delete rfr ;


       } // poivi


       printf("\n\n +++++ Resetting floats to best fit values.\n\n") ;

       for ( int pi=0; pi<nFloatParInitVal; pi++ ) {
          RooRealVar* par = ws->var( floatParName[pi] ) ;
          par->setVal( floatParInitVal[pi] ) ;
       } // pi.

       printf("\n\n +++++ Starting scan up from best value.\n\n") ;

      //-- Now do scan up.

       double poiVals_scanUp[1000] ;
       double nllVals_scanUp[1000] ;

       for ( int poivi=0; poivi < npoiPoints/2 ; poivi++ ) {

          double poiValue = best_poi_val + poivi*(poiMaxVal-best_poi_val)/(1.*(npoiPoints/2-1)) ;

          rrv_poiValue -> setVal( poiValue ) ;
          rrv_poiValue -> setConstant( kTRUE ) ;


       //+++++++++++++++++++++++++++++++++++

          rminuit->migrad() ;
          rminuit->hesse() ;
          RooFitResult* rfr = rminuit->save() ;

       //+++++++++++++++++++++++++++++++++++


          if ( verbLevel > 0 ) { rfr->Print("v") ; }


          float fit_minuit_var_val = rfr->minNll() ;

          printf(" %02d : poi constraint = %.2f : allvars : MinuitVar, createNLL, PV, POI :    %.5f   %.5f   %.5f   %.5f\n",
                poivi, rrv_poiValue->getVal(), fit_minuit_var_val, nll->getVal(), plot_var->getVal(), new_poi_rar->getVal() ) ;
          cout << flush ;

          poiVals_scanUp[poivi] = new_poi_rar->getVal() ;
          nllVals_scanUp[poivi] = plot_var->getVal() ;

          if ( nllVals_scanUp[poivi] < minNllVal ) { minNllVal = nllVals_scanUp[poivi] ; }

          delete rfr ;


       } // poivi





       double poiVals[1000] ;
       double nllVals[1000] ;

       int pointCount(0) ;
       for ( int pi=0; pi<npoiPoints/2; pi++ ) {
          poiVals[pi] = poiVals_scanDown[(npoiPoints/2-1)-pi] ;
          nllVals[pi] = nllVals_scanDown[(npoiPoints/2-1)-pi] ;
          pointCount++ ;
       }
       for ( int pi=1; pi<npoiPoints/2; pi++ ) {
          poiVals[pointCount] = poiVals_scanUp[pi] ;
          nllVals[pointCount] = nllVals_scanUp[pi] ;
          pointCount++ ;
       }
       npoiPoints = pointCount ;

       printf("\n\n --- TGraph arrays:\n") ;
       for ( int i=0; i<npoiPoints; i++ ) {
          printf("  %2d : poi = %6.1f, nll = %g\n", i, poiVals[i], nllVals[i] ) ;
       }
       printf("\n\n") ;

       double nllDiffVals[1000] ;

       double poiAtMinlnL(-1.) ;
       double poiAtMinusDelta2(-1.) ;
       double poiAtPlusDelta2(-1.) ;
       for ( int poivi=0; poivi < npoiPoints ; poivi++ ) {
          nllDiffVals[poivi] = 2.*(nllVals[poivi] - minNllVal) ;
          double poiValue = poiMinVal + poivi*(poiMaxVal-poiMinVal)/(1.*npoiPoints) ;
          if ( nllDiffVals[poivi] < 0.01 ) { poiAtMinlnL = poiValue ; }
          if ( poiAtMinusDelta2 < 0. && nllDiffVals[poivi] < 2.5 ) { poiAtMinusDelta2 = poiValue ; }
          if ( poiAtMinlnL > 0. && poiAtPlusDelta2 < 0. && nllDiffVals[poivi] > 2.0 ) { poiAtPlusDelta2 = poiValue ; }
       } // poivi

       printf("\n\n Estimates for poi at delta ln L = -2, 0, +2:  %g ,   %g ,   %g\n\n", poiAtMinusDelta2, poiAtMinlnL, poiAtPlusDelta2 ) ;




      //--- Main canvas

       TCanvas* cscan = (TCanvas*) gDirectory->FindObject("cscan") ;
       if ( cscan == 0x0 ) {
          printf("\n Creating canvas.\n\n") ;
          cscan = new TCanvas("cscan","Delta nll") ;
       }


       char gname[1000] ;

       TGraph* graph = new TGraph( npoiPoints, poiVals, nllDiffVals ) ;
       sprintf( gname, "scan_%s", new_poi_name ) ;
       graph->SetName( gname ) ;

       double poiBest(-1.) ;
       double poiMinus1stdv(-1.) ;
       double poiPlus1stdv(-1.) ;
       double poiMinus2stdv(-1.) ;
       double poiPlus2stdv(-1.) ;
       double twoDeltalnLMin(1e9) ;

       int nscan(1000) ;
       for ( int xi=0; xi<nscan; xi++ ) {

          double x = poiVals[0] + xi*(poiVals[npoiPoints-1]-poiVals[0])/(nscan-1) ;

          double twoDeltalnL = graph -> Eval( x, 0, "S" ) ;

          if ( poiMinus1stdv < 0. && twoDeltalnL < 1.0 ) { poiMinus1stdv = x ; printf(" set m1 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}
          if ( poiMinus2stdv < 0. && twoDeltalnL < 4.0 ) { poiMinus2stdv = x ; printf(" set m2 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}
          if ( twoDeltalnL < twoDeltalnLMin ) { poiBest = x ; twoDeltalnLMin = twoDeltalnL ; }
          if ( twoDeltalnLMin < 0.3 && poiPlus1stdv < 0. && twoDeltalnL > 1.0 ) { poiPlus1stdv = x ; printf(" set p1 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}
          if ( twoDeltalnLMin < 0.3 && poiPlus2stdv < 0. && twoDeltalnL > 4.0 ) { poiPlus2stdv = x ; printf(" set p2 : %d, x=%g, 2dnll=%g\n", xi, x, twoDeltalnL) ;}

          if ( xi%100 == 0 ) { printf( " %4d : poi=%6.2f,  2DeltalnL = %6.2f\n", xi, x, twoDeltalnL ) ; }

       }
       printf("\n\n POI estimate :  %g  +%g  -%g    [%g,%g],   two sigma errors: +%g  -%g   [%g,%g]\n\n",
               poiBest,
               (poiPlus1stdv-poiBest), (poiBest-poiMinus1stdv), poiMinus1stdv, poiPlus1stdv,
               (poiPlus2stdv-poiBest), (poiBest-poiMinus2stdv), poiMinus2stdv, poiPlus2stdv
               ) ;

       printf(" %s val,pm1sig,pm2sig: %7.2f  %7.2f  %7.2f  %7.2f  %7.2f\n",
          new_poi_name, poiBest, (poiPlus1stdv-poiBest), (poiBest-poiMinus1stdv), (poiPlus2stdv-poiBest), (poiBest-poiMinus2stdv) ) ;

       char htitle[1000] ;
       sprintf(htitle, "%s profile likelihood scan: -2ln(L/Lm)", new_poi_name ) ;
       TH1F* hscan = new TH1F("hscan", htitle, 10, poiMinVal, poiMaxVal ) ;
       hscan->SetMinimum(0.) ;
       hscan->SetMaximum(ymax) ;


       hscan->DrawCopy() ;
       graph->SetLineColor(4) ;
       graph->SetLineWidth(3) ;
       graph->Draw("CP") ;
       gPad->SetGridx(1) ;
       gPad->SetGridy(1) ;
       cscan->Update() ;

       TLine* line = new TLine() ;
       line->SetLineColor(2) ;
       line->DrawLine(poiMinVal, 1., poiPlus1stdv, 1.) ;
       line->DrawLine(poiMinus1stdv,0., poiMinus1stdv, 1.) ;
       line->DrawLine(poiPlus1stdv ,0., poiPlus1stdv , 1.) ;

       TText* text = new TText() ;
       text->SetTextSize(0.04) ;
       char tstring[1000] ;

       sprintf( tstring, "%s = %.1f +%.1f -%.1f", new_poi_name, poiBest, (poiPlus1stdv-poiBest), (poiBest-poiMinus1stdv) ) ;
       text -> DrawTextNDC( 0.15, 0.85, tstring ) ;

       sprintf( tstring, "68%% interval [%.1f,  %.1f]", poiMinus1stdv, poiPlus1stdv ) ;
       text -> DrawTextNDC( 0.15, 0.78, tstring ) ;


       char hname[1000] ;
       sprintf( hname, "hscanout_%s", new_poi_name ) ;
       TH1F* hsout = new TH1F( hname,"scan results",4,0.,4.) ;
       double obsVal(-1.) ;
       hsout->SetBinContent(1, obsVal ) ;
       hsout->SetBinContent(2, poiPlus1stdv ) ;
       hsout->SetBinContent(3, poiBest ) ;
       hsout->SetBinContent(4, poiMinus1stdv ) ;
       TAxis* xaxis = hsout->GetXaxis() ;
       xaxis->SetBinLabel(1,"Observed val.") ;
       xaxis->SetBinLabel(2,"Model+1sd") ;
       xaxis->SetBinLabel(3,"Model") ;
       xaxis->SetBinLabel(4,"Model-1sd") ;

       char outrootfile[10000] ;
       sprintf( outrootfile, "%s/scan-ff-%s.root", outputdir.Data(), new_poi_name ) ;

       char outpdffile[10000] ;
       sprintf( outpdffile, "%s/scan-ff-%s.pdf", outputdir.Data(), new_poi_name ) ;

       cscan->Update() ; cscan->Draw() ;

       printf("\n Saving %s\n", outpdffile ) ;
       cscan->SaveAs( outpdffile ) ;



     //--- save in root file

       printf("\n Saving %s\n", outrootfile ) ;
       TFile fout(outrootfile,"recreate") ;
       graph->Write() ;
       hsout->Write() ;
       fout.Close() ;

       delete ws ;
       wstf->Close() ;

   }
///
/// Perform 1d Prob scan.
///
/// - Scan range defined through limit "scan".
/// - Will fill the hCL histogram with the 1-CL curve.
/// - Start at a scan value that is in the middle of the allowed
///   range, preferably a solution, and scan up and down from there.
/// - use the "probforce" command line flag to enable force minimum finding
///
/// \param fast This will scan each scanpoint only once.
/// \param reverse This will scan in reverse direction.
///   When using the drag mode, this can sometimes make a difference.
/// \return status: 2 = new global minimum found, 1 = error
///
int MethodProbScan::scan1d(bool fast, bool reverse)
{
	if ( arg->debug ) cout << "MethodProbScan::scan1d() : starting ... " << endl;
	nScansDone++;

	// The "improve" method doesn't need multiple scans.
	if ( arg->probforce || arg->probimprove ) fast = true;
	if ( arg->probforce ) scanDisableDragMode = true;

	// Save parameter values that were active at function call.
	if ( startPars ) delete startPars;
	startPars = new RooDataSet("startPars", "startPars", *w->set(parsName));
	startPars->add(*w->set(parsName));

	// // start scan from global minimum (not always a good idea as we need to set from other places as well)
	// setParameters(w, parsName, globalMin);

	// load scan parameter and scan range
	setLimit(w, scanVar1, "scan");
	RooRealVar *par = w->var(scanVar1);
	assert(par);
	float min = hCL->GetXaxis()->GetXmin();
	float max = hCL->GetXaxis()->GetXmax();
	if ( fabs(par->getMin()-min)>1e-6 || fabs(par->getMax()-max)>1e-6 ){
		cout << "MethodProbScan::scan1d() : WARNING : Scan range was changed after initScan()" << endl;
		cout << "                           was called so the old range will be used." << endl;
	}
	if ( arg->verbose ){
		cout << "\nProb configuration:" << endl;
		cout << "  combination : " << title << endl;
		cout << "  scan variable : " << scanVar1 << endl;
		cout << "  scan range : " << min << " ... " << max << endl;
		cout << "  scan steps : " << nPoints1d << endl;
		cout << "  fast mode : " << fast << endl;
		cout << endl;
	}

	// Set limit to all parameters.
	combiner->loadParameterLimits();

	// fix scan parameter
	par->setConstant(true);

	// j =
	// 0 : start value -> upper limit
	// 1 : upper limit -> start value
	// 2 : start value -> lower limit
	// 3 : lower limit -> start value
	float startValue = par->getVal();
	bool scanUp;

	// for the status bar
	float nTotalSteps = nPoints1d;
	nTotalSteps *= fast ? 1 : 2;
	float nStep = 0;
	float printFreq = nTotalSteps>15 ? 10 : nTotalSteps;

	// Report on the smallest new minimum we come across while scanning.
	// Sometimes the scan doesn't find the minimum
	// that was found before. Warn if this happens.
	double bestMinOld = chi2minGlobal;
	double bestMinFoundInScan = 100.;

	for ( int jj=0; jj<4; jj++ )
	{
		int j = jj;
		if ( reverse ) switch(jj)
		{
			case 0: j = 2; break;
			case 1: j = 3; break;
			case 2: j = 0; break;
			case 3: j = 1; break;
		}

		float scanStart, scanStop;
		switch(j)
		{
			case 0:
				// UP
				setParameters(w, parsName, startPars->get(0));
				scanStart = startValue;
				scanStop  = par->getMax();
				scanUp = true;
				break;
			case 1:
				// DOWN
				scanStart = par->getMax();
				scanStop  = startValue;
				scanUp = false;
				break;
			case 2:
				// DOWN
				setParameters(w, parsName, startPars->get(0));
				scanStart = startValue;
				scanStop  = par->getMin();
				scanUp = false;
				break;
			case 3:
				// UP
				scanStart = par->getMin();
				scanStop  = startValue;
				scanUp = true;
				break;
		}

		if ( fast && ( j==1 || j==3 ) ) continue;

		for ( int i=0; i<nPoints1d; i++ )
		{
			float scanvalue;
			if ( scanUp )
			{
				scanvalue = min + (max-min)*(double)i/(double)nPoints1d + hCL->GetBinWidth(1)/2.;
				if ( scanvalue < scanStart ) continue;
				if ( scanvalue > scanStop ) break;
			}
			else
			{
				scanvalue = max - (max-min)*(double)(i+1)/(double)nPoints1d + hCL->GetBinWidth(1)/2.;
				if ( scanvalue > scanStart ) continue;
				if ( scanvalue < scanStop ) break;
			}

			// disable drag mode
			// (the improve method doesn't work with drag mode as parameter run
			// at their limits)
			if ( scanDisableDragMode ) setParameters(w, parsName, startPars->get(0));

			// set the parameter of interest to the scan point
			par->setVal(scanvalue);

			// don't scan in unphysical region
			if ( scanvalue < par->getMin() || scanvalue > par->getMax() ) continue;

			// status bar
			if ( (((int)nStep % (int)(nTotalSteps/printFreq)) == 0))
				cout << "MethodProbScan::scan1d() : scanning " << (float)nStep/(float)nTotalSteps*100. << "%   \r" << flush;

			// fit!
			RooFitResult *fr = 0;
			if ( arg->probforce )         fr = fitToMinForce(w, combiner->getPdfName());
			else if ( arg->probimprove )  fr = fitToMinImprove(w, combiner->getPdfName());
			else                          fr = fitToMinBringBackAngles(w->pdf(pdfName), false, -1);
			double chi2minScan = fr->minNll();
			if ( std::isinf(chi2minScan) ) chi2minScan=1e4; // else the toys in PDF_testConstraint don't work
			RooSlimFitResult *r = new RooSlimFitResult(fr); // try to save memory by using the slim fit result
			delete fr;
			allResults.push_back(r);
			bestMinFoundInScan = TMath::Min((double)chi2minScan, (double)bestMinFoundInScan);

			TString warningChi2Neg;
			if ( chi2minScan < 0 ){
				float newChi2minScan = chi2minGlobal + 25.; // 5sigma more than best point
				warningChi2Neg = "MethodProbScan::scan1d() : WARNING : " + title;
				warningChi2Neg += TString(Form(" chi2 negative for scan point %i: %f",i,chi2minScan));
				warningChi2Neg += " setting to: " + TString(Form("%f",newChi2minScan));
				//cout << warningChi2Neg << "\r" << flush;
				cout << warningChi2Neg << endl;
				chi2minScan = newChi2minScan;
			}

			// If we find a minimum smaller than the old "global" minimum, this means that all
			// previous 1-CL values are too high.
			if ( chi2minScan<chi2minGlobal ){
				if ( arg->verbose ) cout << "MethodProbScan::scan1d() : WARNING : '" << title << "' new global minimum found! "
																		<< " chi2minScan=" << chi2minScan << endl;
				chi2minGlobal = chi2minScan;
				// recompute previous 1-CL values
				for ( int k=1; k<=hCL->GetNbinsX(); k++ ){
					hCL->SetBinContent(k, TMath::Prob(hChi2min->GetBinContent(k)-chi2minGlobal, 1));
				}
			}

			double deltaChi2 = chi2minScan - chi2minGlobal;
			double oneMinusCL = TMath::Prob(deltaChi2, 1);

			// Save the 1-CL value and the corresponding fit result.
			// But only if better than before!
			if ( hCL->GetBinContent(hCL->FindBin(scanvalue)) <= oneMinusCL ){
				hCL->SetBinContent(hCL->FindBin(scanvalue), oneMinusCL);
				hChi2min->SetBinContent(hCL->FindBin(scanvalue), chi2minScan);
				int iRes = hCL->FindBin(scanvalue)-1;
				curveResults[iRes] = r;
			}

			nStep++;
		}
	}
	cout << "MethodProbScan::scan1d() : scan done.           " << endl;

	if ( bestMinFoundInScan-bestMinOld > 0.01 ){
		cout << "MethodProbScan::scan1d() : WARNING: Scan didn't find similar minimum to what was found before!" << endl;
		cout << "MethodProbScan::scan1d() :          Too strict parameter limits? Too coarse scan steps? Didn't load global minimum?" << endl;
		cout << "MethodProbScan::scan1d() :          chi2 bestMinFoundInScan=" << bestMinFoundInScan << ", bestMinOld=" << bestMinOld << endl;
	}

	// attempt to correct for undercoverage
	if (pvalueCorrectorSet) {
		for ( int k=1; k<=hCL->GetNbinsX(); k++ ){
			double pvalueProb = hCL->GetBinContent(k);
			pvalueProb = pvalueCorrector->transform(pvalueProb);
			hCL->SetBinContent(k, pvalueProb);
		}
	}

	setParameters(w, parsName, startPars->get(0));
	saveSolutions();
	if (arg->confirmsols) confirmSolutions();

	if ( (bestMinFoundInScan-bestMinOld)/bestMinOld > 0.01 ) return 1;
	return 0;
}
///
/// Perform a 2d Prob scan.
/// Scan range defined through limit "scan".
/// Fills the hCL2d histogram with the 1-CL curve.
/// Saves all encountered fit results to allResults.
/// Saves the fit results that make it into the 1-CL curve into curveResults2d.
/// Scan strategy: Spiral out!
///
int MethodProbScan::scan2d()
{
	if ( arg->debug ) cout << "MethodProbScan::scan2d() : starting ..." << endl;
	nScansDone++;
	sanityChecks();
	if ( startPars ) delete startPars;

	// Define whether the 2d contours in hCL are "1D sigma" (ndof=1) or "2D sigma" (ndof=2).
	// Leave this at 1 for now, as the "2D sigma" contours are computed from hChi2min2d, not hCL.
	int ndof = 1;

	// Set up storage for fit results of this particular
	// scan. This is used for the drag start parameters.
	// We cannot use the curveResults2d member because that
	// only holds better results.
	vector<vector<RooSlimFitResult*> > mycurveResults2d;
	for ( int i=0; i<nPoints2dx; i++ ){
		vector<RooSlimFitResult*> tmp;
		for ( int j=0; j<nPoints2dy; j++ ) tmp.push_back(0);
		mycurveResults2d.push_back(tmp);
	}

	// store start parameters so we can reset them later
	startPars = new RooDataSet("startPars", "startPars", *w->set(parsName));
	startPars->add(*w->set(parsName));

	// // start scan from global minimum (not always a good idea as we need to set from other places as well)
	// setParameters(w, parsName, globalMin);

	// Define scan parameters and scan range:
	RooRealVar *par1 = w->var(scanVar1);
	RooRealVar *par2 = w->var(scanVar2);

	// Set limit to all parameters.
	combiner->loadParameterLimits();

	// fix scan parameters
	par1->setConstant(true);
	par2->setConstant(true);

	// Report on the smallest new minimum we come across while scanning.
	// Sometimes the scan doesn't find the minimum
	// that was found before. Warn if this happens.
	double bestMinOld = chi2minGlobal;
	double bestMinFoundInScan = 100.;

	// for the status bar
	int nSteps = 0;
	float nTotalSteps = nPoints2dx*nPoints2dy;
	float printFreq = nTotalSteps>100 && !arg->probforce ? 100 : nTotalSteps; ///< number of messages

	// initialize some control plots
	gStyle->SetOptTitle(1);
	TCanvas *cDbg = newNoWarnTCanvas(getUniqueRootName(), Form("DeltaChi2 for 2D scan %i",nScansDone));
	cDbg->SetMargin(0.1,0.15,0.1,0.1);
	float hChi2min2dMin = hChi2min2d->GetMinimum();
	bool firstScanDone = hChi2min2dMin<1e5;
	TH2F *hDbgChi2min2d = histHardCopy(hChi2min2d, firstScanDone);
	hDbgChi2min2d->SetTitle(Form("#Delta#chi^{2} for scan %i, %s",nScansDone,title.Data()));
	if ( firstScanDone ) hDbgChi2min2d->GetZaxis()->SetRangeUser(hChi2min2dMin,hChi2min2dMin+25);
	hDbgChi2min2d->GetXaxis()->SetTitle(par1->GetTitle());
	hDbgChi2min2d->GetYaxis()->SetTitle(par2->GetTitle());
	hDbgChi2min2d->GetZaxis()->SetTitle("#Delta#chi^{2}");
	TH2F *hDbgStart = histHardCopy(hChi2min2d, false);

	// start coordinates
	// don't allow the under/overflow bins
	int iStart = min(hCL2d->GetXaxis()->FindBin(par1->getVal()), hCL2d->GetNbinsX());
	int jStart = min(hCL2d->GetYaxis()->FindBin(par2->getVal()), hCL2d->GetNbinsY());
	iStart = max(iStart, 1);
	jStart = max(jStart, 1);
	hDbgStart->SetBinContent(iStart, jStart, 500.);
	TMarker *startpointmark = new TMarker(par1->getVal(),par2->getVal(),3);

	// timer
	TStopwatch tFit;
	TStopwatch tSlimResult;
	TStopwatch tScan;
	TStopwatch tMemory;

	// set up the scan spiral
	int X = 2*nPoints2dx;
	int Y = 2*nPoints2dy;
	int x,y,dx,dy;
	x = y = dx = 0;
	dy = -1;
	int t = std::max(X,Y);
	int maxI = t*t;
	for ( int spiralstep=0; spiralstep<maxI; spiralstep++ )
	{
		if ((-X/2 <= x) && (x <= X/2) && (-Y/2 <= y) && (y <= Y/2))
		{
			int i = x+iStart;
			int j = y+jStart;
			if ( i>0 && i<=nPoints2dx && j>0 && j<=nPoints2dy )
			{
				tScan.Start(false);

				// status bar
				if (((int)nSteps % (int)(nTotalSteps/printFreq)) == 0){
					cout << Form("MethodProbScan::scan2d() : scanning %3.0f%%", (float)nSteps/(float)nTotalSteps*100.)
															 << "       \r" << flush;
				}
				nSteps++;

				// status histogram
				if ( spiralstep>0 ) hDbgStart->SetBinContent(i, j, 500./*firstScan ? 1. : hChi2min2dMin+36*/);

				// set start parameters from inner turn of the spiral
				int xStartPars, yStartPars;
				computeInnerTurnCoords(iStart, jStart, i, j, xStartPars, yStartPars, 1);
				RooSlimFitResult *rStartPars = mycurveResults2d[xStartPars-1][yStartPars-1];
				if ( rStartPars ) setParameters(w, parsName, rStartPars);

				// memory management:
				tMemory.Start(false);
				// delete old, inner fit results, that we don't need for start parameters anymore
				// for this we take the second-inner-most turn.
				int iOld, jOld;
				bool innerTurnExists = computeInnerTurnCoords(iStart, jStart, i, j, iOld, jOld, 2);
				if ( innerTurnExists ){
					deleteIfNotInCurveResults2d(mycurveResults2d[iOld-1][jOld-1]);
					mycurveResults2d[iOld-1][jOld-1] = 0;
				}
				tMemory.Stop();

				// alternative choice for start parameters: always from what we found at function call
				// setParameters(w, parsName, startPars->get(0));

				// set scan point
				float scanvalue1 = hCL2d->GetXaxis()->GetBinCenter(i);
				float scanvalue2 = hCL2d->GetYaxis()->GetBinCenter(j);
				par1->setVal(scanvalue1);
				par2->setVal(scanvalue2);

				// fit!
				tFit.Start(false);
				RooFitResult *fr;
				if ( !arg->probforce ) fr = fitToMinBringBackAngles(w->pdf(pdfName), false, -1);
				else                   fr = fitToMinForce(w, combiner->getPdfName());
				double chi2minScan = fr->minNll();
				tFit.Stop();
				tSlimResult.Start(false);
				RooSlimFitResult *r = new RooSlimFitResult(fr); // try to save memory by using the slim fit result
				tSlimResult.Stop();
				delete fr;
				allResults.push_back(r);
				bestMinFoundInScan = TMath::Min((double)chi2minScan, (double)bestMinFoundInScan);
				mycurveResults2d[i-1][j-1] = r;

				// If we find a new global minumum, this means that all
				// previous 1-CL values are too high. We'll save the new possible solution, adjust the global
				// minimum, return a status code, and stop.
				if ( chi2minScan > -500 && chi2minScan<chi2minGlobal ){
					// warn only if there was a significant improvement
					if ( arg->debug || chi2minScan<chi2minGlobal-1e-2 ){
						if ( arg->verbose ) cout << "MethodProbScan::scan2d() : WARNING : '" << title << "' new global minimum found! chi2minGlobal="
															<< chi2minGlobal << " chi2minScan=" << chi2minScan << endl;
					}
					chi2minGlobal = chi2minScan;
					// recompute previous 1-CL values
					for ( int k=1; k<=hCL2d->GetNbinsX(); k++ )
						for ( int l=1; l<=hCL2d->GetNbinsY(); l++ ){
							hCL2d->SetBinContent(k, l, TMath::Prob(hChi2min2d->GetBinContent(k,l)-chi2minGlobal, ndof));
						}
				}

				double deltaChi2 = chi2minScan - chi2minGlobal;
				double oneMinusCL = TMath::Prob(deltaChi2, ndof);

				// Save the 1-CL value. But only if better than before!
				if ( hCL2d->GetBinContent(i, j) < oneMinusCL ){
					hCL2d->SetBinContent(i, j, oneMinusCL);
					hChi2min2d->SetBinContent(i, j, chi2minScan);
					hDbgChi2min2d->SetBinContent(i, j, chi2minScan);
					curveResults2d[i-1][j-1] = r;
				}

				// draw/update histograms - doing only every 10th update saves
				// a lot of time for small combinations
				if ( ( arg->interactive && ((int)nSteps % 10 == 0) ) || nSteps==nTotalSteps ){
					hDbgChi2min2d->Draw("colz");
					hDbgStart->Draw("boxsame");
					startpointmark->Draw();
					cDbg->Update();
          cDbg->Modified();
				}
				tScan.Stop();
			}
		}
		// spiral stuff:
		if( (x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1-y)))
		{
			t = dx;
			dx = -dy;
			dy = t;
		}
		x += dx;
		y += dy;
	}
	cout << "MethodProbScan::scan2d() : scan done.            " << endl;
	if ( arg->debug ){
		cout << "MethodProbScan::scan2d() : full scan time:             "; tScan.Print();
		cout << "MethodProbScan::scan2d() : - fitting:                  "; tFit.Print();
		cout << "MethodProbScan::scan2d() : - create RooSlimFitResults: "; tSlimResult.Print();
		cout << "MethodProbScan::scan2d() : - memory management:        "; tMemory.Print();
	}
	setParameters(w, parsName, startPars->get(0));
	saveSolutions2d();
	if ( arg->debug ) printLocalMinima();
	if ( arg->confirmsols ) confirmSolutions();

	// clean all fit results that didn't make it into the final result
	for ( int i=0; i<allResults.size(); i++ ){
		deleteIfNotInCurveResults2d(allResults[i]);
	}

	if ( bestMinFoundInScan-bestMinOld > 0.1 )
	{
		cout << "MethodProbScan::scan2d() : WARNING: Scan didn't find minimum that was found before!" << endl;
		cout << "MethodProbScan::scan2d() :          Are you using too strict parameter limits?" << endl;
		cout << "MethodProbScan::scan2d() :          min chi2 found in scan: " << bestMinFoundInScan << ", old min chi2: " << bestMinOld << endl;
		return 1;
	}
	return 0;
}
Beispiel #13
0
int fitHisto(int siteNum,string dataVer)
{

//===>initialize variable
	bool anaLiHe=true;//He8/Li9 bg
    int ADNumOfSite[3]={0};
    int daqHistNum=5;
    if( dataVer.find("13")!=-1 || dataVer.find("14")!=-1 || dataVer.find("15")!=-1 || dataVer.find("16")!=-1)
    {
        ADNumOfSite[0]=2;
        ADNumOfSite[1]=2;
        ADNumOfSite[2]=4;
        daqHistNum=5;
    } else
    {
        if( dataVer.find("11")!=-1 || dataVer.find("12")!=-1 )
        {
            ADNumOfSite[0]=2;
            ADNumOfSite[1]=1;
            ADNumOfSite[2]=3;
            daqHistNum=4;
        }
    }
	string site;
	if( siteNum==1 )
	{
		site="EH1";
	} else if(siteNum==2)
	{
		site="EH2";
	}else if (siteNum==3)
	{
		site="EH3";
	}else
	{
		site="EH1";
	}

//===>initialize histograms
	//livetime
	string runnum;
	TH1F* h[daqHistNum];//the fifth is for daqtime
	Double_t totalTime[5]={0.};

	//Li9 He8
	double n98total=0.;
	//double in98total=0.;
    double ifitn98total=0.;
    double n98Rate=0.;
    double in98Rate=0.;
    double tlivetime=0.;
	TH1F* showermuonNum[6]; 
	TH1F* time2lastshowermuon[6];
	TH1F* hh[6];

//===>get histograms from .root file for analyse
	string filename;
    filename=site;
    filename+="mergedHist_";
    filename+=dataVer;
    filename+=".root";
    TFile* f=new TFile(filename.c_str());

		//livetime
		for( int i=0 ; i<daqHistNum ; i++ )
		{

			stringstream hname;
			if( i==daqHistNum-1 )
			{
				hname<<"LiveTime/DaqTime";
			} else
			{
				hname<<"LiveTime/AD";
				hname<<i+1;
				hname<<"LiveTime";	
			}
			h[i] = (TH1F*)f->Get(hname.str().c_str());
			if( !(h[i]) )
			{
				cout<<"Can not get Hist : "<<hname.str()<<" from "<<site<<"/"<<runnum<<" ."<<endl;
				//return true;
                continue;
			}
		}

		//Li9 He8
        if(anaLiHe)
		{
            for( int i=0 ; i<6 ; i++ )
            {
                TString hnameLi;
                hnameLi="lidj/showermuonNum";
                hnameLi+=i+1;
                showermuonNum[i]=(TH1F*)f->Get(hnameLi);
                hnameLi="lidj/time2lastshowermuon";
                hnameLi+=i+1;
                hnameLi+="4Li";
                time2lastshowermuon[i]=(TH1F*)f->Get(hnameLi);
            }
		}
	
//===>analyse 
	TAxis *xaxis = h[0]->GetXaxis();
	int binNum = xaxis->GetNbins();
    int BinBound=h[0]->FindBin(1346428800);//2012.9.1 0:0:0
	//livetime
    if( BinBound!=0 )
    {
        if( site=="EH2" )
        {
            for(int j=1  ; j<=BinBound ; j++ )
            {
                h[1]->SetBinContent(j,0);
            }
        }
        if( site=="EH3" )
        {
            for(int j=1  ; j<=BinBound ; j++ )
            {
                h[3]->SetBinContent(j,0);
            }
        }
    }
    double totalTimeSpecical=0.;
    for( int j=BinBound ; j<=binNum ; j++ )
    {
        totalTimeSpecical+=h[4]->GetBinContent(j);
    }

    for( int i=0 ; i<5 ; i++ )
    {
        totalTime[i]=0.;
        for( int j=1 ; j<=binNum ; j++ )
        {
            totalTime[i]+=h[i]->GetBinContent(j);
        }

    }
    double totalDaqtime=0.;
    if( site=="EH2" )
    {
        totalDaqtime=totalTime[4]+totalTimeSpecical;
    }else if( site=="EH3" )
    {
        totalDaqtime=totalTime[4]*3+totalTimeSpecical;
    } else
    {
        totalDaqtime=totalTime[4]*2;
    }

	//Li He
    std::cout<<"begin to analyse Li "<<endl;
	if(anaLiHe)
	{
        int hnum=time2lastshowermuon[0]->FindBin(100);
        //std::cout<<"0.001  : "<<time2lastshowermuon[0]->FindBin(0.001)<<endl;
        //std::cout<<"100  : "<<time2lastshowermuon[0]->FindBin(100)<<endl;
        //std::cout<<"hnum  : "<<hnum<<endl;
        for( int k=0 ; k<6 ; k++ )
        {
            TString hhname="slice";
            hhname+=k+1;
            hh[k]=new TH1F(hhname,"hh",hnum-2,0.001,100);
                for( int i=1 ; i<hnum-2 ; i++ )
                {
                    hh[k]->SetBinContent(i,time2lastshowermuon[k]->GetBinContent(i+1));
                }
                hh[k]->SetOption("E1");
        }
        double showerTh[7] = {0.02, 0.5, 1.5, 2.5, 3.5, 4.5, 5.0};
        TH1F* LiResult[5];
        LiResult[0]= new TH1F("LiResult", "All", 6, showerTh);
        LiResult[1]= new TH1F("LiResult", "AD1", 6, showerTh);
        LiResult[2]= new TH1F("LiResult", "AD2", 6, showerTh);
        LiResult[3]= new TH1F("LiResult", "AD3", 6, showerTh);
        LiResult[4]= new TH1F("LiResult", "AD4", 6, showerTh);
		double NumMuon[6]={0.};
		double RateMuon[6]={0.};
		double NumIbd[6]={0.};
        
		RooRealVar x("x","x",0.001,40., "s");
		RooRealVar tauLi9("tauLi9", "tauLi9", -0.257, "s");
		RooRealVar tauHe8("tauHe8", "tauHe8", -0.172, "s");
		RooRealVar rateMu("rateMu","rate of showermuon",-0.1,-10., 0.,"Hz");
		RooRealVar Li9Frac("Li9Frac","Li9's Frac", 0.0);//R
		RooRealVar N98("N98","total number of Li9 and He8",500.,0.,1.e5);
		//RooRealVar N98("N98","total number of Li9 and He8",3e2, 1e1, 2.e5);
		RooFormulaVar lambdaLi9("lambdaLi9","lambdaLi9","1/@0 + @1",RooArgList(tauLi9, rateMu));
		RooFormulaVar lambdaHe8("lambdaHe8","lambdaHe8","1/@0 + @1",RooArgList(tauHe8, rateMu));
		RooFormulaVar coeLi9("coeLi9","coeLi9","@0 * @1 ",RooArgList(N98,Li9Frac));
		RooFormulaVar coeHe8("coeHe8","coeHe8","@0 * ( 1 - @1 )",RooArgList(N98,Li9Frac));
		RooRealVar NIbd("NIbd","number of background",3e2, 1e1, 2.e6);
		RooExponential expLi9("expLi9", "Li9 distribution", x, lambdaLi9);
		RooExponential expHe8("expHe8", "He8 distribution", x, lambdaHe8);
        double Ibdrate[3]={0.0076,0.0067,0.00082};
        RooRealVar rateIbd("rateIbd","rateIbd",-Ibdrate[siteNum-1],-10,0.,"Hz");
        RooFormulaVar lambdaIbd("lambdaIbd","lambdaIbd","@0 + @1",RooArgList(rateIbd, rateMu));
		RooExponential expIbd("expIbd","Ibd distribution",x,rateMu);
		//RooExponential expIbd("expIbd","Ibd distribution",x,lambdaIbd);
		
		RooFitResult* fitres;
		RooAddPdf* sum;
		RooDataHist* data;
        RooPlot* mesframe[6];
		double n98[41]={0.};
		double in98[41]={0.};
		double nIbd[41]={0.};
		double inIbd[41]={0.};
		double minNLL[41]={0.};
        double rateMuValue[41]={0.};
        double rateMuErr[41]={0.};
		//double minNl[6]={0.};
		int minindex[6]={0};
		double n98fit[6]={0.};
		double in98fit[6]={0.};
        double rateMufit[6]={0.};
		double binwidth=0.;
        TH1F* lh[5][6];
        TString lname[5]={"","AD1","AD2","AD3","AD4"};
        int lcolor[5]={4,3,2,6,5};
        bool draw6slice=false;
        TCanvas* c;
        TString xTitle[6]={"slice 1 : 0.02~0.5GeV","slice 2 : 0.5~1.5GeV","slice 3 : 1.5~2.5GeV","slice 4 : 2.5~3.5GeV","slice 5 : 3.5~4.5GeV","slice 6 : >4.5GeV"};
        if( draw6slice )
        {
	        c = new TCanvas("c","c",2000,800) ; 
	        c->Divide(3,2);
	        gStyle->SetEndErrorSize(5.0);
	        gStyle->SetMarkerSize(0.1);
	        //gStyle->SetHistLineWidth(1);
	        if( 0 )
	        {
	            // it's strange ,if you can't draw following six figs in the big 3*2 pad,you can fist use these code,run once,don't exit the ROOT,then you can draw six figs!!!
			    data = new RooDataHist("data", "data", x, time2lastshowermuon[0]);
				sum  = new RooAddPdf("sum","sum",RooArgList(expLi9, expHe8, expIbd),RooArgList(coeLi9, coeHe8, NIbd));
		        RooPlot* mesframe = x.frame() ;
		        data->plotOn(mesframe) ;
		        c->cd(1);
		        mesframe->Draw();
	            return true;
	        }
        }
        for( int ihist=0 ; ihist<1 ; ihist++ )
        {
			double minNl[6]={0.};
			for( int j=0 ; j<6 ; j++ )
			{
	            std::cout<<"now is  "<< j+1<<endl;
	            NumIbd[j]=hh[j]->Integral(1,hh[j]->FindBin(40));
	            hh[j]->Rebin(100);
				data = new RooDataHist("data", "data", x, hh[j]);
				sum  = new RooAddPdf("sum","sum",RooArgList(expLi9, expHe8, expIbd),RooArgList(coeLi9, coeHe8, NIbd));
				for( int i=0 ; i<41 ; i++ )
				{
					Li9Frac.setVal(i*0.025);
					fitres = sum->fitTo((*data),Save(),PrintLevel(-1),Extended(kTRUE));
	                //fitres->Print();
					n98[i]=N98.getVal(0);
					in98[i]=N98.getError();
	                nIbd[i]=NIbd.getVal(0);
	                inIbd[i]=NIbd.getError();
	                rateMuValue[i]=rateMu.getVal(0);
	                rateMuErr[i]=rateMu.getError();
					minNLL[i] = fitres->minNll();
					if( minNLL[i]<minNl[j] )
					{
						minNl[j]=minNLL[i];
						minindex[j]=i;
					}
				}
				n98fit[j]=n98[minindex[j]];
				in98fit[j]=in98[minindex[j]];
	            rateMufit[j]=rateMuValue[minindex[j]];
	            if( draw6slice )
	            {
		            //for drawing fit figure
					Li9Frac.setVal(minindex[j]*0.025);
					fitres = sum->fitTo((*data),Save(),PrintLevel(-1),Extended(kTRUE));
		            //fitres->Print();
		            mesframe[j] = x.frame() ;
		            data->plotOn(mesframe[j]) ;
		            sum->plotOn(mesframe[j]);
		            sum->plotOn(mesframe[j],Components(expIbd),LineStyle(kDashed),LineColor(kGreen)) ;
		            sum->plotOn(mesframe[j],Components(RooArgSet(expLi9,expHe8)),LineStyle(kDashed),LineColor(kRed)) ;
		            xTitle[j]+="        time since last muon (s)";
		            mesframe[j]->GetXaxis()->SetTitle(xTitle[j]);
		            mesframe[j]->GetYaxis()->SetTitle("Entries");
		            c->cd(j+1);
		            mesframe[j]->Draw();
		            //gPad->SetLogy();
	            }
			}
	        
			n98total=(n98fit[0]+n98fit[1]+n98fit[2]+(n98fit[3]+n98fit[4]+n98fit[5])*exp(-1/0.257))/0.678;
			ifitn98total=sqrt(in98fit[0]*in98fit[0]+in98fit[1]*in98fit[1]+in98fit[2]*in98fit[2]+((in98fit[3]+in98fit[4]+in98fit[5])*exp(-1/0.257)*(in98fit[3]+in98fit[4]+in98fit[5])*exp(-1/0.257)))/0.678;
	        if( ihist==0 )
	        {
	            for( int i=0 ; i<ADNumOfSite[siteNum-1] ; i++ )
	            {
	                tlivetime+=totalTime[i];
	            }
	        }else
	        {
	            tlivetime=totalTime[ihist-1];
	        }
	        n98Rate=n98total/(tlivetime/(24*3600));
	        in98Rate=sqrt((ifitn98total/(tlivetime/(24*3600)))*(ifitn98total/(tlivetime/(24*3600)))+(n98total/(tlivetime/(24*3600))/2)*(n98total/(tlivetime/(24*3600))/2));
	        for( int j=0 ; j<6 ; j++ )
	        {
	            LiResult[ihist]->SetBinContent(j+1,n98fit[j]);
	            LiResult[ihist]->SetBinError(j+1,in98fit[j]);
			    for( int jbin=0 ; jbin<binNum ; jbin++ )
	            {
	                NumMuon[j]+=showermuonNum[j]->GetBinContent(jbin);
	            }
				RateMuon[j]=NumMuon[j]/totalDaqtime;
	            //std::cout<<"RateMuon[j]  : "<<RateMuon[j]<<endl;
	            //std::cout<<"RateMuon0[j]  : "<<RateMuon0[j]<<endl;
	            std::cout<<"  R "<<minindex[j]*0.025<<"   n98["<<minindex[j]<<"] "<<n98fit[j]<<"   in98["<<minindex[j]<<"] "<< in98fit[j]<<"   fitRateMu["<<minindex[j]<<"] "<<rateMufit[j]<<"  realRateMu "<<RateMuon[j]<<"   NumTol "<<NumIbd[j]<<endl;
	        }
	        std::cout<<"n98Num   : "<<n98total<<" +- "<<ifitn98total<<" Rate  : "<<n98Rate<<" +- "<< in98Rate<<endl;
        }
        
            /*
        //TCanvas* c4 = new TCanvas("c4", "c4", 600, 400);
        //gStyle->SetEndErrorSize(0.0);
        LiResult[0]->SetMarkerStyle(20);
		LiResult[0]->SetMarkerColor(lcolor[0]);
		LiResult[0]->SetLineColor(lcolor[0]);
		LiResult[0]->SetMarkerSize(1.0);
		LiResult[0]->SetMinimum(0);
		LiResult[0]->SetMaximum(LiResult[0]->GetMaximum()*1.5);
		LiResult[0]->GetXaxis()->SetTitle("Muon visible energy (GeV)");
		LiResult[0]->GetYaxis()->SetTitle("Fitted ^{9}Li events");
		LiResult[0]->SetTitle("");
        LiResult[0]->SetStats(kFALSE);
		LiResult[0]->Draw("EP");
        TLegend *legend=new TLegend(.6,.65,.79,.89);
        TString legendLabel=dataVer+" "+site+" "+"All";
        legend->AddEntry(LiResult[0],legendLabel,"lp");

        for( int ihist=1 ; ihist<ADNumOfSite[siteNum-1]+1; ihist++ )
        {
            LiResult[ihist]->SetMarkerStyle(20);
		    LiResult[ihist]->SetMarkerColor(lcolor[ihist]);
		    LiResult[ihist]->SetLineColor(lcolor[ihist]);
		    LiResult[ihist]->SetMarkerSize(1.0);
            LiResult[ihist]->SetStats(kFALSE);
		    LiResult[ihist]->Draw("EPsame");
            legend->AddEntry(LiResult[ihist],lname[ihist],"lp");
        }
        legend->SetFillColor(0);
        legend->Draw();
        */
	}	
	
    //f->Close();
//===>print result
	std::cout<<""<<endl;
	std::cout<<site <<"'s infomation : "<<endl;
	std::cout<<""<<endl;
	for( int i=0 ; i<ADNumOfSite[siteNum-1] ; i++ )
	{
		std::cout<<"Total AD"<<i+1<<"LiveTime                         : "<<totalTime[i]/(24*3600)<<endl;
	}
	std::cout<<"Total DaqTime : "<<totalTime[daqHistNum-1]/(24*3600)<<" day" <<endl;
	std::cout<<""<<endl;

	if(anaLiHe)
	{
	    std::cout<<" "<<endl;
        /*
	    std::cout<<"Li9/He8 "<<endl;
	    std::cout<<"n98total  : "<<n98total <<" +- "<<in98total <<" Rate:"<<n98total/totalTime[0]*24*3600 <<" +- "<<in98total/totalTime[0]*24*3600 <<endl;
	    std::cout<<"n98total0(without rpc)  : "<<n98total0 <<" +- "<<in98total0 <<" Rate:"<<n98total0/totalTime0[0]*24*3600 <<" +- "<<in98total0/totalTime0[0]*24*3600 <<endl;
        */
	}

//===>write into .root file
	string rootname=site;
	rootname+="FitResult_"+dataVer+".root";
	TFile* file = new TFile(rootname.c_str(),"RECREATE");
    file->cd();
    for( int i=0 ; i<daqHistNum ; i++ )
    {
        h[i]->Write();
    }
    
    if( anaLiHe )
    {
		//for( int i=0 ; i<ADNumOfSite[siteNum-1] ; i++ )
		for( int i=0 ; i<6 ; i++ )
		{
			hh[i]->Write();
		}
    }
	file->Close();
	f->Close();
	return 0;
}
Beispiel #14
0
float ComputeTestStat(TString wsfile, double mu_susy_sig_val) {

  gROOT->Reset();

  TFile* wstf = new TFile( wsfile ) ;

  RooWorkspace* ws = dynamic_cast<RooWorkspace*>( wstf->Get("ws") );
  ws->Print() ;
  
  ModelConfig* modelConfig = (ModelConfig*) ws->obj( "SbModel" ) ;
  
  modelConfig->Print() ;

  RooDataSet* rds = (RooDataSet*) ws->obj( "ra2b_observed_rds" ) ;
  
  rds->Print() ;
  rds->printMultiline(cout, 1, kTRUE, "") ;
  
  RooAbsPdf* likelihood = modelConfig->GetPdf() ;
  
  RooRealVar* rrv_mu_susy_sig = ws->var("mu_susy_all0lep") ;
  if ( rrv_mu_susy_sig == 0x0 ) {
    printf("\n\n\n *** can't find mu_susy_all0lep in workspace.  Quitting.\n\n\n") ;
    return ;
  } else {
    printf(" current value is : %8.3f\n", rrv_mu_susy_sig->getVal() ) ; cout << flush ;
    rrv_mu_susy_sig->setConstant(kFALSE) ;
  }

  /*
  // check the impact of varying the qcd normalization:

  RooRealVar *rrv_qcd_0lepLDP_ratioH1 = ws->var("qcd_0lepLDP_ratio_H1");
  RooRealVar *rrv_qcd_0lepLDP_ratioH2 = ws->var("qcd_0lepLDP_ratio_H2");
  RooRealVar *rrv_qcd_0lepLDP_ratioH3 = ws->var("qcd_0lepLDP_ratio_H3");
  
  rrv_qcd_0lepLDP_ratioH1->setVal(0.3);
  rrv_qcd_0lepLDP_ratioH2->setVal(0.3);
  rrv_qcd_0lepLDP_ratioH3->setVal(0.3);
  
  rrv_qcd_0lepLDP_ratioH1->setConstant(kTRUE);
  rrv_qcd_0lepLDP_ratioH2->setConstant(kTRUE);
  rrv_qcd_0lepLDP_ratioH3->setConstant(kTRUE);
  */
  
  printf("\n\n\n  ===== Doing a fit with SUSY component floating ====================\n\n") ;

  RooFitResult* fitResult = likelihood->fitTo( *rds, Save(true), PrintLevel(0) ) ;
  double logLikelihoodSusyFloat = fitResult->minNll() ;
  
  double logLikelihoodSusyFixed(0.) ;
  double testStatVal(-1.) ;
  if ( mu_susy_sig_val >= 0. ) {
    printf("\n\n\n  ===== Doing a fit with SUSY fixed ====================\n\n") ;
    printf(" fixing mu_susy_sig to %8.2f.\n", mu_susy_sig_val ) ;
    rrv_mu_susy_sig->setVal( mu_susy_sig_val ) ;
    rrv_mu_susy_sig->setConstant(kTRUE) ;
    
    fitResult = likelihood->fitTo( *rds, Save(true), PrintLevel(0) ) ;
    logLikelihoodSusyFixed = fitResult->minNll() ;
    testStatVal = 2.*(logLikelihoodSusyFixed - logLikelihoodSusyFloat) ;
    printf("\n\n\n ======= test statistic : -2 * ln (L_fixed / ln L_max) = %8.3f\n\n\n", testStatVal ) ;
  }


  return testStatVal ;

}
Beispiel #15
0
   void ws_cls_hybrid1_ag( const char* wsfile = "output-files/expected-ws-lm9-2BL.root", bool isBgonlyStudy=false, double poiVal = 150.0, int nToys=100, bool makeTtree=true, int verbLevel=0 ) {



       TTree* toytt(0x0) ;
       TFile* ttfile(0x0) ;

       int    tt_gen_Nsig ;
       int    tt_gen_Nsb ;
       int    tt_gen_Nsig_sl ;
       int    tt_gen_Nsb_sl ;
       int    tt_gen_Nsig_ldp ;
       int    tt_gen_Nsb_ldp ;
       int    tt_gen_Nsig_ee ;
       int    tt_gen_Nsb_ee ;
       int    tt_gen_Nsig_mm ;
       int    tt_gen_Nsb_mm ;

       double tt_testStat ;
       double tt_dataTestStat ;
       double tt_hypo_mu_susy_sig ;
       char ttname[1000] ;
       char tttitle[1000] ;

       if ( makeTtree ) {

          ttfile = gDirectory->GetFile() ;
          if ( ttfile == 0x0 ) { printf("\n\n\n *** asked for a ttree but no open file???\n\n") ; return ; }


          if ( isBgonlyStudy ) {
             sprintf( ttname, "toytt_%.0f_bgo", poiVal ) ;
             sprintf( tttitle, "Toy study for background only, mu_susy_sig = %.0f", poiVal ) ;
          } else {
             sprintf( ttname, "toytt_%.0f_spb", poiVal ) ;
             sprintf( tttitle, "Toy study for signal+background, mu_susy_sig = %.0f", poiVal ) ;
          }

          printf("\n\n Creating TTree : %s : %s\n\n", ttname, tttitle ) ;

          gDirectory->pwd() ;
          gDirectory->ls() ;

          toytt = new TTree( ttname, tttitle ) ;

          gDirectory->ls() ;

          toytt -> Branch(  "gen_Nsig"         ,       &tt_gen_Nsig         ,      "gen_Nsig/I"         ) ;
          toytt -> Branch(  "gen_Nsb"          ,       &tt_gen_Nsb          ,      "gen_Nsb/I"          ) ;
          toytt -> Branch(  "gen_Nsig_sl"      ,       &tt_gen_Nsig_sl      ,      "gen_Nsig_sl/I"      ) ;
          toytt -> Branch(  "gen_Nsb_sl"       ,       &tt_gen_Nsb_sl       ,      "gen_Nsb_sl/I"       ) ;
          toytt -> Branch(  "gen_Nsig_ldp"     ,       &tt_gen_Nsig_ldp     ,      "gen_Nsig_ldp/I"     ) ;
          toytt -> Branch(  "gen_Nsb_ldp"      ,       &tt_gen_Nsb_ldp      ,      "gen_Nsb_ldp/I"      ) ;
          toytt -> Branch(  "gen_Nsig_ee"      ,       &tt_gen_Nsig_ee      ,      "gen_Nsig_ee/I"      ) ;
          toytt -> Branch(  "gen_Nsb_ee"       ,       &tt_gen_Nsb_ee       ,      "gen_Nsb_ee/I"       ) ;
          toytt -> Branch(  "gen_Nsig_mm"      ,       &tt_gen_Nsig_mm      ,      "gen_Nsig_mm/I"      ) ;
          toytt -> Branch(  "gen_Nsb_mm"       ,       &tt_gen_Nsb_mm       ,      "gen_Nsb_mm/I"       ) ;

          toytt -> Branch(  "testStat"         ,       &tt_testStat         ,      "testStat/D"         ) ;
          toytt -> Branch(  "dataTestStat"     ,       &tt_dataTestStat     ,      "dataTestStat/D"     ) ;
          toytt -> Branch(  "hypo_mu_susy_sig" ,       &tt_hypo_mu_susy_sig ,      "hypo_mu_susy_sig/D" ) ;

       }


     //--- Tell RooFit to shut up about anything less important than an ERROR.
      RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;


       random_ng = new TRandom2(12345) ;

   /// char sel[100] ;
   /// if ( strstr( wsfile, "1BL" ) != 0 ) {
   ///    sprintf( sel, "1BL" ) ;
   /// } else if ( strstr( wsfile, "2BL" ) != 0 ) {
   ///    sprintf( sel, "2BL" ) ;
   /// } else if ( strstr( wsfile, "3B" ) != 0 ) {
   ///    sprintf( sel, "3B" ) ;
   /// } else if ( strstr( wsfile, "1BT" ) != 0 ) {
   ///    sprintf( sel, "1BT" ) ;
   /// } else if ( strstr( wsfile, "2BT" ) != 0 ) {
   ///    sprintf( sel, "2BT" ) ;
   /// } else {
   ///    printf("\n\n\n *** can't figure out which selection this is.  I quit.\n\n" ) ;
   ///    return ;
   /// }
   /// printf("\n\n selection is %s\n\n", sel ) ;




       TFile* wstf = new TFile( wsfile ) ;

       RooWorkspace* ws = dynamic_cast<RooWorkspace*>( wstf->Get("ws") );

       ws->Print() ;






       RooDataSet* rds = (RooDataSet*) ws->obj( "ra2b_observed_rds" ) ;
       printf("\n\n\n  ===== RooDataSet ====================\n\n") ;

       rds->Print() ;
       rds->printMultiline(cout, 1, kTRUE, "") ;





       ModelConfig* modelConfig = (ModelConfig*) ws->obj( "SbModel" ) ;
       RooAbsPdf* likelihood = modelConfig->GetPdf() ;

       const RooArgSet* nuisanceParameters = modelConfig->GetNuisanceParameters() ;

       RooRealVar* rrv_mu_susy_sig = ws->var("mu_susy_sig") ;
       if ( rrv_mu_susy_sig == 0x0 ) {
          printf("\n\n\n *** can't find mu_susy_sig in workspace.  Quitting.\n\n\n") ;
          return ;
       }






 ////  printf("\n\n\n  ===== Doing a fit ====================\n\n") ;

 ////  RooFitResult* preFitResult = likelihood->fitTo( *rds, Save(true) ) ;
 ////  const RooArgList preFitFloatVals = preFitResult->floatParsFinal() ;
 ////  {
 ////    TIterator* parIter = preFitFloatVals.createIterator() ;
 ////    while ( RooRealVar* par = (RooRealVar*) parIter->Next() ) {
 ////       printf(" %20s : %8.2f\n", par->GetName(), par->getVal() ) ;
 ////    }
 ////  }







       //--- Get pointers to the model predictions of the observables.

       rfv_n_sig       = ws->function("n_sig") ;
       rfv_n_sb        = ws->function("n_sb") ;
       rfv_n_sig_sl    = ws->function("n_sig_sl") ;
       rfv_n_sb_sl     = ws->function("n_sb_sl") ;
       rfv_n_sig_ldp   = ws->function("n_sig_ldp") ;
       rfv_n_sb_ldp    = ws->function("n_sb_ldp") ;
       rfv_n_sig_ee    = ws->function("n_sig_ee") ;
       rfv_n_sb_ee     = ws->function("n_sb_ee") ;
       rfv_n_sig_mm    = ws->function("n_sig_mm") ;
       rfv_n_sb_mm     = ws->function("n_sb_mm") ;

       if ( rfv_n_sig         == 0x0 ) { printf("\n\n\n *** can't find n_sig       in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sb          == 0x0 ) { printf("\n\n\n *** can't find n_sb        in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sig_sl      == 0x0 ) { printf("\n\n\n *** can't find n_sig_sl    in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sb_sl       == 0x0 ) { printf("\n\n\n *** can't find n_sb_sl     in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sig_ldp     == 0x0 ) { printf("\n\n\n *** can't find n_sig_ldp   in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sb_ldp      == 0x0 ) { printf("\n\n\n *** can't find n_sb_ldp    in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sig_ee      == 0x0 ) { printf("\n\n\n *** can't find n_sig_ee    in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sb_ee       == 0x0 ) { printf("\n\n\n *** can't find n_sb_ee     in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sig_mm      == 0x0 ) { printf("\n\n\n *** can't find n_sig_mm    in workspace.  Quitting.\n\n\n") ; return ; }
       if ( rfv_n_sb_mm       == 0x0 ) { printf("\n\n\n *** can't find n_sb_mm     in workspace.  Quitting.\n\n\n") ; return ; }







       //--- Get pointers to the observables.

       const RooArgSet* dsras = rds->get() ;
       TIterator* obsIter = dsras->createIterator() ;
       while ( RooRealVar* obs = (RooRealVar*) obsIter->Next() ) {
          if ( strcmp( obs->GetName(), "Nsig"     ) == 0 ) { rrv_Nsig      = obs ; }
          if ( strcmp( obs->GetName(), "Nsb"      ) == 0 ) { rrv_Nsb       = obs ; }
          if ( strcmp( obs->GetName(), "Nsig_sl"  ) == 0 ) { rrv_Nsig_sl   = obs ; }
          if ( strcmp( obs->GetName(), "Nsb_sl"   ) == 0 ) { rrv_Nsb_sl    = obs ; }
          if ( strcmp( obs->GetName(), "Nsig_ldp" ) == 0 ) { rrv_Nsig_ldp  = obs ; }
          if ( strcmp( obs->GetName(), "Nsb_ldp"  ) == 0 ) { rrv_Nsb_ldp   = obs ; }
          if ( strcmp( obs->GetName(), "Nsig_ee"  ) == 0 ) { rrv_Nsig_ee   = obs ; }
          if ( strcmp( obs->GetName(), "Nsb_ee"   ) == 0 ) { rrv_Nsb_ee    = obs ; }
          if ( strcmp( obs->GetName(), "Nsig_mm"  ) == 0 ) { rrv_Nsig_mm   = obs ; }
          if ( strcmp( obs->GetName(), "Nsb_mm"   ) == 0 ) { rrv_Nsb_mm    = obs ; }
       }

       if ( rrv_Nsig       == 0x0 ) { printf("\n\n\n *** can't find Nsig       in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsb        == 0x0 ) { printf("\n\n\n *** can't find Nsb        in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsig_sl    == 0x0 ) { printf("\n\n\n *** can't find Nsig_sl    in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsb_sl     == 0x0 ) { printf("\n\n\n *** can't find Nsb_sl     in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsig_ldp   == 0x0 ) { printf("\n\n\n *** can't find Nsig_ldp   in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsb_ldp    == 0x0 ) { printf("\n\n\n *** can't find Nsb_ldp    in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsig_ee    == 0x0 ) { printf("\n\n\n *** can't find Nsig_ee    in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsb_ee     == 0x0 ) { printf("\n\n\n *** can't find Nsb_ee     in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsig_mm    == 0x0 ) { printf("\n\n\n *** can't find Nsig_mm    in dataset.  Quitting.\n\n\n") ; return ; }
       if ( rrv_Nsb_mm     == 0x0 ) { printf("\n\n\n *** can't find Nsb_mm     in dataset.  Quitting.\n\n\n") ; return ; }






       printf("\n\n\n === Model values for observables\n\n") ;

       printObservables() ;



      //--- save the actual values of the observables.

       saveObservables() ;











       //--- evaluate the test stat on the data: fit with susy floating.

       rrv_mu_susy_sig->setVal( poiVal ) ;
       rrv_mu_susy_sig->setConstant( kTRUE ) ;

       printf("\n\n\n ====== Fitting the data with susy fixed.\n\n") ;

       RooFitResult* dataFitResultSusyFixed = likelihood->fitTo(*rds, Save(true));
       int dataSusyFixedFitCovQual = dataFitResultSusyFixed->covQual() ;
       if ( dataSusyFixedFitCovQual != 3 ) { printf("\n\n\n *** Failed fit!  Cov qual %d.  Quitting.\n\n", dataSusyFixedFitCovQual ) ; return ; }
       double dataFitSusyFixedNll = dataFitResultSusyFixed->minNll() ;


       rrv_mu_susy_sig->setVal( 0.0 ) ;
       rrv_mu_susy_sig->setConstant( kFALSE ) ;

       printf("\n\n\n ====== Fitting the data with susy floating.\n\n") ;

       RooFitResult* dataFitResultSusyFloat = likelihood->fitTo(*rds, Save(true));
       int dataSusyFloatFitCovQual = dataFitResultSusyFloat->covQual() ;
       if ( dataSusyFloatFitCovQual != 3 ) { printf("\n\n\n *** Failed fit!  Cov qual %d.  Quitting.\n\n", dataSusyFloatFitCovQual ) ; return ; }
       double dataFitSusyFloatNll = dataFitResultSusyFloat->minNll() ;

       double dataTestStat = 2.*( dataFitSusyFixedNll - dataFitSusyFloatNll) ;

       printf("\n\n\n Data value of test stat : %8.2f\n", dataTestStat ) ;












       printf("\n\n\n === Nuisance parameters\n\n") ;

       {
          int npi(0) ;
          TIterator* npIter = nuisanceParameters->createIterator() ;
          while ( RooRealVar* np_rrv = (RooRealVar*) npIter->Next() ) {

             np_initial_val[npi] = np_rrv->getVal() ; //--- I am assuming that the order of the NPs in the iterator does not change.

             TString npname( np_rrv->GetName() ) ;
             npname.ReplaceAll("_prim","") ;
             RooAbsReal* np_rfv = ws->function( npname ) ;

             TString pdfname( np_rrv->GetName() ) ;
             pdfname.ReplaceAll("_prim","") ;
             pdfname.Prepend("pdf_") ;
             RooAbsPdf* np_pdf = ws->pdf( pdfname ) ;
             if ( np_pdf == 0x0 ) { printf("\n\n *** Can't find nuisance parameter pdf with name %s.\n\n", pdfname.Data() ) ; }

             if ( np_rfv != 0x0 ) {
                printf(" %20s : %8.2f , %20s, %8.2f\n", np_rrv->GetName(), np_rrv->getVal(), np_rfv->GetName(), np_rfv->getVal() ) ;
             } else {
                printf(" %20s : %8.2f\n", np_rrv->GetName(), np_rrv->getVal() ) ;
             }

             npi++ ;
          } // np_rrv iterator.

          np_count = npi ;

       }







       tt_dataTestStat = dataTestStat ;
       tt_hypo_mu_susy_sig = poiVal ;














       printf("\n\n\n === Doing the toys\n\n") ;

       int nToyOK(0) ;
       int nToyWorseThanData(0) ;

       for ( int ti=0; ti<nToys; ti++ ) {

          printf("\n\n\n ======= Toy %4d\n\n\n", ti ) ;





          //--- 1) pick values for the nuisance parameters from the PDFs and fix them.

          {
             TIterator* npIter = nuisanceParameters->createIterator() ;
             while ( RooRealVar* np_rrv = (RooRealVar*) npIter->Next() ) {

                TString pdfname( np_rrv->GetName() ) ;
                pdfname.ReplaceAll("_prim","") ;
                pdfname.Prepend("pdf_") ;
                RooAbsPdf* np_pdf = ws->pdf( pdfname ) ;
                if ( np_pdf == 0x0 ) { printf("\n\n *** Can't find nuisance parameter pdf with name %s.\n\n", pdfname.Data() ) ; return ; }

                RooDataSet* nprds = np_pdf->generate( RooArgSet(*np_rrv) ,1) ;
                const RooArgSet* npdsras = nprds->get() ;
                TIterator* valIter = npdsras->createIterator() ;
                RooRealVar* val = (RooRealVar*) valIter->Next() ;

                //--- reset the value of the nuisance parameter and fix it for the toy model definition fit.
                np_rrv->setVal( val->getVal() ) ;
                np_rrv->setConstant( kTRUE ) ;


                TString npname( np_rrv->GetName() ) ;
                npname.ReplaceAll("_prim","") ;
                RooAbsReal* np_rfv = ws->function( npname ) ;

                if ( verbLevel > 0 ) {
                   if ( np_rfv != 0x0 ) {
                      printf(" %20s : %8.2f , %15s, %8.3f\n", val->GetName(), val->getVal(), np_rfv->GetName(), np_rfv->getVal() ) ;
                   } else if ( strstr( npname.Data(), "eff_sf" ) != 0 ) {
                      np_rfv = ws->function( "eff_sf_sig" ) ;
                      RooAbsReal* np_rfv2 = ws->function( "eff_sf_sb" ) ;
                      printf(" %20s : %8.2f , %15s, %8.3f , %15s, %8.3f\n", val->GetName(), val->getVal(), np_rfv->GetName(), np_rfv->getVal(), np_rfv2->GetName(), np_rfv2->getVal() ) ;
                   } else if ( strstr( npname.Data(), "sf_ll" ) != 0 ) {
                      np_rfv = ws->function( "sf_ee" ) ;
                      RooAbsReal* np_rfv2 = ws->function( "sf_mm" ) ;
                      printf(" %20s : %8.2f , %15s, %8.3f , %15s, %8.3f\n", val->GetName(), val->getVal(), np_rfv->GetName(), np_rfv->getVal(), np_rfv2->GetName(), np_rfv2->getVal() ) ;
                   } else {
                      printf(" %20s : %8.2f\n", val->GetName(), val->getVal() ) ;
                   }
                }

                delete nprds ;

             } // np_rrv iterator
          }






          //--- 2) Fit the dataset with these values for the nuisance parameters.

          if ( isBgonlyStudy ) {
            //-- fit with susy yield fixed to zero.
             rrv_mu_susy_sig -> setVal( 0. ) ;
             if ( verbLevel > 0 ) { printf("\n Setting mu_susy_sig to zero.\n\n") ; }
          } else {
            //-- fit with susy yield fixed to predicted value.
             rrv_mu_susy_sig -> setVal( poiVal ) ;
             if ( verbLevel > 0 ) { printf("\n Setting mu_susy_sig to %8.1f.\n\n", poiVal) ; }
          }
          rrv_mu_susy_sig->setConstant( kTRUE ) ;

          if ( verbLevel > 0 ) {
             printf("\n\n") ;
             printf("  Fitting with these values for the observables to define the model for toy generation.\n") ;
             rds->printMultiline(cout, 1, kTRUE, "") ;
             printf("\n\n") ;
          }

          RooFitResult* toyModelDefinitionFitResult(0x0) ;
          if ( verbLevel < 2 ) {
             toyModelDefinitionFitResult = likelihood->fitTo(*rds, Save(true), PrintLevel(-1));
          } else {
             toyModelDefinitionFitResult = likelihood->fitTo(*rds, Save(true));
          }

          int toyModelDefFitCovQual = toyModelDefinitionFitResult->covQual() ;
          if ( verbLevel > 0 ) { printf("\n fit covariance matrix quality: %d\n\n", toyModelDefFitCovQual ) ; }
          if ( toyModelDefFitCovQual != 3 ) {
             printf("\n\n\n *** Bad toy model definition fit.  Cov qual %d.  Aborting this toy.\n\n\n", toyModelDefFitCovQual ) ;
             continue ;
          }

          delete toyModelDefinitionFitResult ;

          if ( verbLevel > 0 ) {
             printf("\n\n\n === Model values for observables.  These will be used to generate the toy dataset.\n\n") ;
             printObservables() ;
          }









          //--- 3) Generate a new set of observables based on this model.

          generateObservables() ;

          printf("\n\n\n   Generated dataset\n") ;
          rds->Print() ;
          rds->printMultiline(cout, 1, kTRUE, "") ;

          //--- Apparently, I need to make a new RooDataSet...  Resetting the
          //    values in the old one doesn't stick.  If you do likelihood->fitTo(*rds), it
          //    uses the original values, not the reset ones, in the fit.

          RooArgSet toyFitobservedParametersList ;
          toyFitobservedParametersList.add( *rrv_Nsig        ) ;
          toyFitobservedParametersList.add( *rrv_Nsb         ) ;
          toyFitobservedParametersList.add( *rrv_Nsig_sl     ) ;
          toyFitobservedParametersList.add( *rrv_Nsb_sl      ) ;
          toyFitobservedParametersList.add( *rrv_Nsig_ldp    ) ;
          toyFitobservedParametersList.add( *rrv_Nsb_ldp     ) ;
          toyFitobservedParametersList.add( *rrv_Nsig_ee     ) ;
          toyFitobservedParametersList.add( *rrv_Nsb_ee      ) ;
          toyFitobservedParametersList.add( *rrv_Nsig_mm     ) ;
          toyFitobservedParametersList.add( *rrv_Nsb_mm      ) ;


          RooDataSet* toyFitdsObserved = new RooDataSet("toyfit_ra2b_observed_rds", "RA2b toy observed data values",
                                         toyFitobservedParametersList ) ;
          toyFitdsObserved->add( toyFitobservedParametersList ) ;





          //--- 4) Reset and free the nuisance parameters.

          {
             if ( verbLevel > 0 ) { printf("\n\n") ; }
             int npi(0) ;
             TIterator* npIter = nuisanceParameters->createIterator() ;
             while ( RooRealVar* np_rrv = (RooRealVar*) npIter->Next() ) {
                np_rrv -> setVal( np_initial_val[npi] ) ; // assuming that the order in the iterator does not change.
                np_rrv -> setConstant( kFALSE ) ;
                npi++ ;
                if ( verbLevel > 0 ) { printf("    reset %20s to %8.2f and freed it.\n", np_rrv->GetName() , np_rrv->getVal() ) ; }
             } // np_rrv iterator.
             if ( verbLevel > 0 ) { printf("\n\n") ; }
          }





          //--- 5a) Evaluate the test statistic: Fit with susy yield floating to get the absolute maximum log likelihood.

          if ( verbLevel > 0 ) { printf("\n\n  Evaluating the test statistic for this toy.  Fitting with susy floating.\n\n") ; }

          rrv_mu_susy_sig->setVal( 0.0 ) ;
          rrv_mu_susy_sig->setConstant( kFALSE ) ;

          if ( verbLevel > 0 ) {
             printf("\n toy dataset\n\n") ;
             toyFitdsObserved->printMultiline(cout, 1, kTRUE, "") ;
          }

     /////---- nfg.  Need to create a new dataset  ----------
     /////RooFitResult* maxLikelihoodFitResult = likelihood->fitTo(*rds, Save(true), PrintLevel(-1));
     /////RooFitResult* maxLikelihoodFitResult = likelihood->fitTo(*rds, Save(true));
     /////--------------

          RooFitResult* maxLikelihoodFitResult(0x0) ;
          if ( verbLevel < 2 ) {
             maxLikelihoodFitResult = likelihood->fitTo(*toyFitdsObserved, Save(true), PrintLevel(-1));
          } else {
             maxLikelihoodFitResult = likelihood->fitTo(*toyFitdsObserved, Save(true));
          }

          if ( verbLevel > 0 ) { printObservables() ; }

          int mlFitCovQual = maxLikelihoodFitResult->covQual() ;
          if ( verbLevel > 0 ) { printf("\n fit covariance matrix quality: %d , -log likelihood %f\n\n", mlFitCovQual, maxLikelihoodFitResult->minNll() ) ; }
          if ( mlFitCovQual != 3 ) {
             printf("\n\n\n *** Bad maximum likelihood fit (susy floating).  Cov qual %d.  Aborting this toy.\n\n\n", mlFitCovQual ) ;
             continue ;
          }
          double maxL_susyFloat = maxLikelihoodFitResult->minNll() ;
          double maxL_mu_susy_sig = rrv_mu_susy_sig->getVal() ;

          delete maxLikelihoodFitResult ;






          //--- 5b) Evaluate the test statistic: Fit with susy yield fixed to hypothesis value.
          //        This is only necessary if the maximum likelihood fit value of the susy yield
          //        is less than the hypothesis value (to get a one-sided limit).


          double testStat(0.0) ;
          double maxL_susyFixed(0.0) ;

          if ( maxL_mu_susy_sig < poiVal ) {

             if ( verbLevel > 0 ) { printf("\n\n  Evaluating the test statistic for this toy.  Fitting with susy fixed to %8.2f.\n\n", poiVal ) ; }

             rrv_mu_susy_sig->setVal( poiVal ) ;
             rrv_mu_susy_sig->setConstant( kTRUE ) ;

             if ( verbLevel > 0 ) {
                printf("\n toy dataset\n\n") ;
                rds->printMultiline(cout, 1, kTRUE, "") ;
             }

         ////--------- nfg.  need to make a new dataset  ---------------
         ////RooFitResult* susyFixedFitResult = likelihood->fitTo(*rds, Save(true), PrintLevel(-1));
         ////RooFitResult* susyFixedFitResult = likelihood->fitTo(*rds, Save(true));
         ////-----------------------------

             RooFitResult* susyFixedFitResult(0x0) ;
             if ( verbLevel < 2 ) {
                susyFixedFitResult = likelihood->fitTo(*toyFitdsObserved, Save(true), PrintLevel(-1));
             } else {
                susyFixedFitResult = likelihood->fitTo(*toyFitdsObserved, Save(true));
             }

             if ( verbLevel > 0 ) { printObservables() ; }

             int susyFixedFitCovQual = susyFixedFitResult->covQual() ;
             if ( verbLevel > 0 ) { printf("\n fit covariance matrix quality: %d , -log likelihood %f\n\n", susyFixedFitCovQual, susyFixedFitResult->minNll()  ) ; }
             if ( susyFixedFitCovQual != 3 ) {
                printf("\n\n\n *** Bad maximum likelihood fit (susy fixed).  Cov qual %d.  Aborting this toy.\n\n\n", susyFixedFitCovQual ) ;
                continue ;
             }
             maxL_susyFixed = susyFixedFitResult->minNll() ;
             testStat = 2. * (maxL_susyFixed - maxL_susyFloat) ;


             delete susyFixedFitResult ;


          } else {

             if ( verbLevel > 0 ) { printf("\n\n  Floating value of susy yield greater than hypo value (%8.2f > %8.2f).  Setting test stat to zero.\n\n", maxL_mu_susy_sig, poiVal ) ; }

             testStat = 0.0 ;

          }

          printf("   --- test stat for toy %4d : %8.2f\n", ti, testStat ) ;





          nToyOK++ ;

          if ( testStat > dataTestStat ) { nToyWorseThanData++ ; }


          if ( makeTtree ) {

             tt_testStat = testStat ;

             tt_gen_Nsig     = rrv_Nsig->getVal() ;
             tt_gen_Nsb      = rrv_Nsb->getVal() ;
             tt_gen_Nsig_sl  = rrv_Nsig_sl->getVal() ;
             tt_gen_Nsb_sl   = rrv_Nsb_sl->getVal() ;
             tt_gen_Nsig_ldp = rrv_Nsig_ldp->getVal() ;
             tt_gen_Nsb_ldp  = rrv_Nsb_ldp->getVal() ;
             tt_gen_Nsig_ee  = rrv_Nsig_ee->getVal() ;
             tt_gen_Nsb_ee   = rrv_Nsb_ee->getVal() ;
             tt_gen_Nsig_mm  = rrv_Nsig_mm->getVal() ;
             tt_gen_Nsb_mm   = rrv_Nsb_mm->getVal() ;

             toytt->Fill() ;

          }





          //--- *) reset things for the next toy.

          resetObservables() ;

          delete toyFitdsObserved ;




       } // ti.

       wstf->Close() ;

       printf("\n\n\n") ;

       if ( nToyOK == 0 ) { printf("\n\n\n *** All toys bad !?!?!\n\n\n") ; return ; }

       double pValue = (1.0*nToyWorseThanData) / (1.0*nToyOK) ;

       if ( isBgonlyStudy ) {
          printf("\n\n\n p-value result, BG-only , poi=%3.0f : %4d / %4d = %6.3f\n\n\n\n", poiVal, nToyWorseThanData, nToyOK, pValue ) ;
       } else {
          printf("\n\n\n p-value result, S-plus-B, poi=%3.0f : %4d / %4d = %6.3f\n\n\n\n", poiVal, nToyWorseThanData, nToyOK, pValue ) ;
       }


       if ( makeTtree ) {
          printf("\n\n Writing TTree : %s : %s\n\n", ttname, tttitle ) ;
          ttfile->cd() ;
          toytt->Write() ;
       }


   } // ws_cls_hybrid1