Example #1
0
MCMCInterval * Tprime::GetMcmcInterval(ModelConfig mc,
                                       double conf_level,
                                       int n_iter,
                                       int n_burn,
                                       double left_side_tail_fraction,
                                       int n_bins) {
    //
    // Bayesian MCMC calculation using arbitrary ModelConfig
    // Want an efficient proposal function, so derive it from covariance
    // matrix of fit
    //

    RooAbsData * _data = data;
    //RooAbsData * _data = pWs->data("obsData");
    //RooStats::ModelConfig * _mc = (RooStats::ModelConfig *)pWs->genobj("ModelConfig");
    RooStats::ModelConfig * _mc = GetModelConfig();
    _mc->Print();

    //RooFitResult * fit = pWs->pdf("model_tprime")->fitTo(*_data,Save());
    RooFitResult * fit = _mc->GetPdf()->fitTo(*_data,Save());
    ProposalHelper ph;
    ph.SetVariables((RooArgSet&)fit->floatParsFinal());
    ph.SetCovMatrix(fit->covarianceMatrix());
    ph.SetUpdateProposalParameters(kTRUE); // auto-create mean vars and add mappings
    ph.SetCacheSize(100);
    ProposalFunction * pf = ph.GetProposalFunction();

    //delete pf;
    //pf = new SequentialProposal();

    MCMCCalculator mcmc( *_data, mc );
    mcmc.SetConfidenceLevel(conf_level);
    mcmc.SetNumIters(n_iter);          // Metropolis-Hastings algorithm iterations
    mcmc.SetProposalFunction(*pf);
    mcmc.SetNumBurnInSteps(n_burn); // first N steps to be ignored as burn-in
    mcmc.SetLeftSideTailFraction(left_side_tail_fraction);
    mcmc.SetNumBins(n_bins);

    //mcInt = mcmc.GetInterval();
    try {
        mcInt = mcmc.GetInterval();
    } catch ( std::length_error &ex) {
        mcInt = 0;
    }

    //std::cout << "!!!!!!!!!!!!!! interval" << std::endl;
    if (mcInt == 0) std::cout << "No interval found!" << std::endl;

    delete fit;
    delete pf;

    return mcInt;
}
Example #2
0
//_________________________________________________
void TestJeffreysGaussSigma(){
  // this one is VERY sensitive
  // if the Gaussian is narrow ~ range(x)/nbins(x) then the peak isn't resolved
  //   and you get really bizzare shapes
  // if the Gaussian is too wide range(x) ~ sigma then PDF gets renormalized
  //   and the PDF falls off too fast at high sigma
  RooWorkspace w("w");
  w.factory("Gaussian::g(x[0,-20,20],mu[0,-5,5],sigma[1,1,5])");
  w.factory("n[100,.1,2000]");
  w.factory("ExtendPdf::p(g,n)");
  //  w.var("sigma")->setConstant();
  w.var("mu")->setConstant();
  w.var("n")->setConstant();
  w.var("x")->setBins(301);

  RooDataHist* asimov = w.pdf("p")->generateBinned(*w.var("x"),ExpectedData());

  RooFitResult* res = w.pdf("p")->fitTo(*asimov,Save(),SumW2Error(kTRUE));

  asimov->Print();
  res->Print();
  TMatrixDSym cov = res->covarianceMatrix();
  cout << "variance = " << (cov.Determinant()) << endl;
  cout << "stdev = " << sqrt(cov.Determinant()) << endl;
  cov.Invert();
  cout << "jeffreys = " << sqrt(cov.Determinant()) << endl;


  //  w.defineSet("poi","mu,sigma");
  //w.defineSet("poi","mu,sigma,n");
  w.defineSet("poi","sigma");
  w.defineSet("obs","x");

  RooJeffreysPrior pi("jeffreys","jeffreys",*w.pdf("p"),*w.set("poi"),*w.set("obs"));
  //  pi.specialIntegratorConfig(kTRUE)->method1D().setLabel("RooAdaptiveGaussKronrodIntegrator1D")  ;
  pi.specialIntegratorConfig(kTRUE)->getConfigSection("RooIntegrator1D").setRealValue("maxSteps",3);

  const RooArgSet* temp = w.set("poi");
  pi.getParameters(*temp)->Print();
  //  return;

  //  return;
  RooGenericPdf* test = new RooGenericPdf("test","test","sqrt(2.)/sigma",*w.set("poi"));

  TCanvas* c1 = new TCanvas;
  RooPlot* plot = w.var("sigma")->frame();
  pi.plotOn(plot);
  test->plotOn(plot,LineColor(kRed),LineStyle(kDotted));
  plot->Draw();


}
Example #3
0
void JeffreysPriorDemo(){
  RooWorkspace w("w");
  w.factory("Uniform::u(x[0,1])");
  w.factory("mu[100,1,200]");
  w.factory("ExtendPdf::p(u,mu)");

  //  w.factory("Poisson::pois(n[0,inf],mu)");

  RooDataHist* asimov = w.pdf("p")->generateBinned(*w.var("x"),ExpectedData());
  //  RooDataHist* asimov2 = w.pdf("pois")->generateBinned(*w.var("n"),ExpectedData());

  RooFitResult* res = w.pdf("p")->fitTo(*asimov,Save(),SumW2Error(kTRUE));

  asimov->Print();
  res->Print();
  TMatrixDSym cov = res->covarianceMatrix();
  cout << "variance = " << (cov.Determinant()) << endl;
  cout << "stdev = " << sqrt(cov.Determinant()) << endl;
  cov.Invert();
  cout << "jeffreys = " << sqrt(cov.Determinant()) << endl;

  w.defineSet("poi","mu");
  w.defineSet("obs","x");
  //  w.defineSet("obs2","n");

  RooJeffreysPrior pi("jeffreys","jeffreys",*w.pdf("p"),*w.set("poi"),*w.set("obs"));
  //  pi.specialIntegratorConfig(kTRUE)->method1D().setLabel("RooAdaptiveGaussKronrodIntegrator1D")  ;
  //  pi.specialIntegratorConfig(kTRUE)->getConfigSection("RooIntegrator1D").setRealValue("maxSteps",10);

  //  JeffreysPrior pi2("jeffreys2","jeffreys",*w.pdf("pois"),*w.set("poi"),*w.set("obs2"));

  //  return;
  RooGenericPdf* test = new RooGenericPdf("test","test","1./sqrt(mu)",*w.set("poi"));

  TCanvas* c1 = new TCanvas;
  RooPlot* plot = w.var("mu")->frame();
  //  pi.plotOn(plot, Normalization(1,RooAbsReal::Raw),Precision(.1));
  pi.plotOn(plot);
  //  pi2.plotOn(plot,LineColor(kGreen),LineStyle(kDotted));
  test->plotOn(plot,LineColor(kRed));
  plot->Draw();

}
Example #4
0
//_________________________________________________
void TestJeffreysGaussMean(){
  RooWorkspace w("w");
  w.factory("Gaussian::g(x[0,-20,20],mu[0,-5,5],sigma[1,0,10])");
  w.factory("n[10,.1,200]");
  w.factory("ExtendPdf::p(g,n)");
  w.var("sigma")->setConstant();
  w.var("n")->setConstant();

  RooDataHist* asimov = w.pdf("p")->generateBinned(*w.var("x"),ExpectedData());

  RooFitResult* res = w.pdf("p")->fitTo(*asimov,Save(),SumW2Error(kTRUE));

  asimov->Print();
  res->Print();
  TMatrixDSym cov = res->covarianceMatrix();
  cout << "variance = " << (cov.Determinant()) << endl;
  cout << "stdev = " << sqrt(cov.Determinant()) << endl;
  cov.Invert();
  cout << "jeffreys = " << sqrt(cov.Determinant()) << endl;

  //  w.defineSet("poi","mu,sigma");
  w.defineSet("poi","mu");
  w.defineSet("obs","x");

  RooJeffreysPrior pi("jeffreys","jeffreys",*w.pdf("p"),*w.set("poi"),*w.set("obs"));
  //  pi.specialIntegratorConfig(kTRUE)->method1D().setLabel("RooAdaptiveGaussKronrodIntegrator1D")  ;
  //  pi.specialIntegratorConfig(kTRUE)->getConfigSection("RooIntegrator1D").setRealValue("maxSteps",3);

  const RooArgSet* temp = w.set("poi");
  pi.getParameters(*temp)->Print();

  //  return;
  RooGenericPdf* test = new RooGenericPdf("test","test","1",*w.set("poi"));

  TCanvas* c1 = new TCanvas;
  RooPlot* plot = w.var("mu")->frame();
  pi.plotOn(plot);
  test->plotOn(plot,LineColor(kRed),LineStyle(kDotted));
  plot->Draw();


}
Example #5
0
MCMCInterval * TwoBody::GetMcmcInterval_OldWay(ModelConfig mc,
					double conf_level,
					int n_iter,
					int n_burn,
					double left_side_tail_fraction,
					int n_bins){
  // use MCMCCalculator  (takes about 1 min)
  // Want an efficient proposal function, so derive it from covariance
  // matrix of fit
  
  RooFitResult* fit = ws->pdf("model")->fitTo(*data,Save());
  ProposalHelper ph;
  ph.SetVariables((RooArgSet&)fit->floatParsFinal());
  ph.SetCovMatrix(fit->covarianceMatrix());
  ph.SetUpdateProposalParameters(kTRUE); // auto-create mean vars and add mappings
  ph.SetCacheSize(100);
  ProposalFunction* pf = ph.GetProposalFunction();
  
  MCMCCalculator mcmc( *data, mc );
  mcmc.SetConfidenceLevel(conf_level);
  mcmc.SetNumIters(n_iter);          // Metropolis-Hastings algorithm iterations
  mcmc.SetProposalFunction(*pf);
  mcmc.SetNumBurnInSteps(n_burn); // first N steps to be ignored as burn-in
  mcmc.SetLeftSideTailFraction(left_side_tail_fraction);
  mcmc.SetNumBins(n_bins);
  
//mcInt = mcmc.GetInterval();
  try {
    mcInt = mcmc.GetInterval();
  } catch ( std::length_error &ex) {
    mcInt = 0;
  }

  //std::cout << "!!!!!!!!!!!!!! interval" << std::endl;
  if (mcInt == 0) std::cout << "No interval found!" << std::endl;
  
  return mcInt;
}
Example #6
0
int KinZfitter::PerZ1Likelihood(double & l1, double & l2, double & lph1, double & lph2)
{

    l1= 1.0; l2 = 1.0;
    lph1 = 1.0; lph2 = 1.0;

    if(debug_) cout<<"start Z1 refit"<<endl;

    TLorentzVector Z1_1 = p4sZ1_[0]; TLorentzVector Z1_2 = p4sZ1_[1];

    double RECOpT1 = Z1_1.Pt(); double RECOpT2 = Z1_2.Pt();
    double pTerrZ1_1 = pTerrsZ1_[0]; double pTerrZ1_2 = pTerrsZ1_[1];

    if(debug_)cout<<"pT1 "<<RECOpT1<<" pTerrZ1_1 "<<pTerrZ1_1<<endl;
    if(debug_)cout<<"pT2 "<<RECOpT2<<" pTerrZ1_2 "<<pTerrZ1_2<<endl;

    //////////////

    TLorentzVector Z1_ph1, Z1_ph2;
    double pTerrZ1_ph1, pTerrZ1_ph2;
    double RECOpTph1, RECOpTph2;

    TLorentzVector nullFourVector(0, 0, 0, 0);
    Z1_ph1=nullFourVector; Z1_ph2=nullFourVector;
    RECOpTph1 = 0; RECOpTph2 = 0;
    pTerrZ1_ph1 = 0; pTerrZ1_ph2 = 0;

    if(p4sZ1ph_.size()>=1){

      Z1_ph1 = p4sZ1ph_[0]; pTerrZ1_ph1 = pTerrsZ1ph_[0];
      RECOpTph1 = Z1_ph1.Pt();
      if(debug_) cout<<"put in Z1 fsr photon 1 pT "<<RECOpTph1<<" pT err "<<pTerrZ1_ph1<<endl; 
    }
    if(p4sZ1ph_.size()==2){
      //if(debug_) cout<<"put in Z1 fsr photon 2"<<endl;
      Z1_ph2 = p4sZ1ph_[1]; pTerrZ1_ph2 = pTerrsZ1ph_[1];
      RECOpTph2 = Z1_ph2.Pt();     
    }

    RooRealVar* pT1RECO = new RooRealVar("pT1RECO","pT1RECO", RECOpT1, 5, 500);
    RooRealVar* pT2RECO = new RooRealVar("pT2RECO","pT2RECO", RECOpT2, 5, 500);
   
    double RECOpT1min = max(5.0, RECOpT1-2*pTerrZ1_1);
    double RECOpT2min = max(5.0, RECOpT2-2*pTerrZ1_2);

    RooRealVar* pTph1RECO = new RooRealVar("pTph1RECO","pTph1RECO", RECOpTph1, 5, 500);
    RooRealVar* pTph2RECO = new RooRealVar("pTph2RECO","pTph2RECO", RECOpTph2, 5, 500);

    double RECOpTph1min = max(0.5, RECOpTph1-2*pTerrZ1_ph1);
    double RECOpTph2min = max(0.5, RECOpTph2-2*pTerrZ1_ph2);

    // observables pT1,2,ph1,ph2
    RooRealVar* pT1 = new RooRealVar("pT1", "pT1FIT", RECOpT1, RECOpT1min, RECOpT1+2*pTerrZ1_1 );
    RooRealVar* pT2 = new RooRealVar("pT2", "pT2FIT", RECOpT2, RECOpT2min, RECOpT2+2*pTerrZ1_2 );

    RooRealVar* m1 = new RooRealVar("m1","m1", Z1_1.M());
    RooRealVar* m2 = new RooRealVar("m2","m2", Z1_2.M());

    if(debug_) cout<<"m1 "<<m1->getVal()<<" m2 "<<m2->getVal()<<endl;

    double Vtheta1, Vphi1, Vtheta2, Vphi2;
    Vtheta1 = (Z1_1).Theta(); Vtheta2 = (Z1_2).Theta();
    Vphi1 = (Z1_1).Phi(); Vphi2 = (Z1_2).Phi();

    RooRealVar* theta1 = new RooRealVar("theta1","theta1",Vtheta1);
    RooRealVar* phi1   = new RooRealVar("phi1","phi1",Vphi1);
    RooRealVar* theta2 = new RooRealVar("theta2","theta2",Vtheta2);
    RooRealVar* phi2   = new RooRealVar("phi2","phi2",Vphi2);

    // dot product to calculate (p1+p2+ph1+ph2).M()
    RooFormulaVar E1("E1","TMath::Sqrt((@0*@0)/((TMath::Sin(@1))*(TMath::Sin(@1)))+@2*@2)",
                          RooArgList(*pT1,*theta1,*m1));
    RooFormulaVar E2("E2","TMath::Sqrt((@0*@0)/((TMath::Sin(@1))*(TMath::Sin(@1)))+@2*@2)",
                          RooArgList(*pT2,*theta2,*m2));
    if(debug_) cout<<"E1 "<<E1.getVal()<<"; E2 "<<E2.getVal()<<endl;

    /////

    RooRealVar* pTph1 = new RooRealVar("pTph1", "pTph1FIT", RECOpTph1, RECOpTph1min, RECOpTph1+2*pTerrZ1_ph1 );
    RooRealVar* pTph2 = new RooRealVar("pTph2", "pTph2FIT", RECOpTph2, RECOpTph2min, RECOpTph2+2*pTerrZ1_ph2 );

    double Vthetaph1, Vphiph1, Vthetaph2, Vphiph2;
    Vthetaph1 = (Z1_ph1).Theta(); Vthetaph2 = (Z1_ph2).Theta();
    Vphiph1 = (Z1_ph1).Phi(); Vphiph2 = (Z1_ph2).Phi();

    RooRealVar* thetaph1 = new RooRealVar("thetaph1","thetaph1",Vthetaph1);
    RooRealVar* phiph1   = new RooRealVar("phiph1","phiph1",Vphiph1);
    RooRealVar* thetaph2 = new RooRealVar("thetaph2","thetaph2",Vthetaph2);
    RooRealVar* phiph2   = new RooRealVar("phiph2","phi2",Vphiph2);

    RooFormulaVar Eph1("Eph1","TMath::Sqrt((@0*@0)/((TMath::Sin(@1))*(TMath::Sin(@1))))", 
                              RooArgList(*pTph1,*thetaph1));
    RooFormulaVar Eph2("Eph2","TMath::Sqrt((@0*@0)/((TMath::Sin(@1))*(TMath::Sin(@1))))", 
                              RooArgList(*pTph2,*thetaph2));

    //// dot products of 4-vectors

    // 3-vector DOT
    RooFormulaVar* p1v3D2 = new RooFormulaVar("p1v3D2",
         "@0*@1*( ((TMath::Cos(@2))*(TMath::Cos(@3)))/((TMath::Sin(@2))*(TMath::Sin(@3)))+(TMath::Cos(@4-@5)))",
         RooArgList(*pT1,*pT2,*theta1,*theta2,*phi1,*phi2));    
    if(debug_) cout<<"p1 DOT p2 is "<<p1v3D2->getVal()<<endl;
    // 4-vector DOT metric 1 -1 -1 -1
    RooFormulaVar p1D2("p1D2","@0*@1-@2",RooArgList(E1,E2,*p1v3D2));

    //lep DOT fsrPhoton1

    // 3-vector DOT
    RooFormulaVar* p1v3Dph1 = new RooFormulaVar("p1v3Dph1",
         "@0*@1*( (TMath::Cos(@2)*TMath::Cos(@3))/(TMath::Sin(@2)*TMath::Sin(@3))+TMath::Cos(@4-@5))",
         RooArgList(*pT1,*pTph1,*theta1,*thetaph1,*phi1,*phiph1));

    // 4-vector DOT metric 1 -1 -1 -1
    RooFormulaVar p1Dph1("p1Dph1","@0*@1-@2",RooArgList(E1,Eph1,*p1v3Dph1));

    // 3-vector DOT
    RooFormulaVar* p2v3Dph1 = new RooFormulaVar("p2v3Dph1",
         "@0*@1*( (TMath::Cos(@2)*TMath::Cos(@3))/(TMath::Sin(@2)*TMath::Sin(@3))+TMath::Cos(@4-@5))",
         RooArgList(*pT2,*pTph1,*theta2,*thetaph1,*phi2,*phiph1));
    // 4-vector DOT metric 1 -1 -1 -1
    RooFormulaVar p2Dph1("p2Dph1","@0*@1-@2",RooArgList(E2,Eph1,*p2v3Dph1));

    // lep DOT fsrPhoton2 

    // 3-vector DOT
    RooFormulaVar* p1v3Dph2 = new RooFormulaVar("p1v3Dph2",
         "@0*@1*( (TMath::Cos(@2)*TMath::Cos(@3))/(TMath::Sin(@2)*TMath::Sin(@3))+TMath::Cos(@4-@5))",
         RooArgList(*pT1,*pTph2,*theta1,*thetaph2,*phi1,*phiph2));

    // 4-vector DOT metric 1 -1 -1 -1
    RooFormulaVar p1Dph2("p1Dph2","@0*@1-@2",RooArgList(E1,Eph2,*p1v3Dph2));

    // 3-vector DOT
    RooFormulaVar* p2v3Dph2 = new RooFormulaVar("p2v3Dph2",
         "@0*@1*( (TMath::Cos(@2)*TMath::Cos(@3))/(TMath::Sin(@2)*TMath::Sin(@3))+TMath::Cos(@4-@5))",
         RooArgList(*pT2,*pTph2,*theta2,*thetaph2,*phi2,*phiph2));
    // 4-vector DOT metric 1 -1 -1 -1
    RooFormulaVar p2Dph2("p2Dph2","@0*@1-@2",RooArgList(E2,Eph2,*p2v3Dph2));

    // fsrPhoton1 DOT fsrPhoton2

    // 3-vector DOT
    RooFormulaVar* ph1v3Dph2 = new RooFormulaVar("ph1v3Dph2",
         "@0*@1*( (TMath::Cos(@2)*TMath::Cos(@3))/(TMath::Sin(@2)*TMath::Sin(@3))+TMath::Cos(@4-@5))",
         RooArgList(*pTph1,*pTph2,*thetaph1,*thetaph2,*phiph1,*phiph2));    
    // 4-vector DOT metric 1 -1 -1 -1
    RooFormulaVar ph1Dph2("ph1Dph2","@0*@1-@2",RooArgList(Eph1,Eph2,*ph1v3Dph2));

    // mZ1

    RooFormulaVar* mZ1;
    mZ1 = new RooFormulaVar("mZ1","TMath::Sqrt(2*@0+@1*@1+@2*@2)",RooArgList(p1D2,*m1,*m2));
    if(p4sZ1ph_.size()==1)
      mZ1 = new RooFormulaVar("mZ1","TMath::Sqrt(2*@0+2*@1+2*@2+@3*@3+@4*@4)",
                                    RooArgList(p1D2, p1Dph1, p2Dph1, *m1,*m2));
    if(p4sZ1ph_.size()==2)
      mZ1 = new RooFormulaVar("mZ1","TMath::Sqrt(2*@0+2*@1+2*@2+2*@3+2*@4+2*@5+@6*@6+@7*@7)",
                              RooArgList(p1D2,p1Dph1,p2Dph1,p1Dph2,p2Dph2,ph1Dph2, *m1,*m2));

    if(debug_) cout<<"mZ1 is "<<mZ1->getVal()<<endl;

    // pTerrs, 1,2,ph1,ph2
    RooRealVar sigmaZ1_1("sigmaZ1_1", "sigmaZ1_1", pTerrZ1_1);
    RooRealVar sigmaZ1_2("sigmaZ1_2", "sigmaZ1_2", pTerrZ1_2);

    RooRealVar sigmaZ1_ph1("sigmaZ1_ph1", "sigmaZ1_ph1", pTerrZ1_ph1);
    RooRealVar sigmaZ1_ph2("sigmaZ1_ph2", "sigmaZ1_ph2", pTerrZ1_ph2);

    // resolution for decay products
    RooGaussian gauss1("gauss1","gaussian PDF", *pT1RECO, *pT1, sigmaZ1_1);
    RooGaussian gauss2("gauss2","gaussian PDF", *pT2RECO, *pT2, sigmaZ1_2);

    RooGaussian gaussph1("gaussph1","gaussian PDF", *pTph1RECO, *pTph1, sigmaZ1_ph1);
    RooGaussian gaussph2("gaussph2","gaussian PDF", *pTph2RECO, *pTph2, sigmaZ1_ph2);

    RooRealVar bwMean("bwMean", "m_{Z^{0}}", 91.187);
    RooRealVar bwGamma("bwGamma", "#Gamma", 2.5);

    RooRealVar sg("sg", "sg", sgVal_);
    RooRealVar a("a", "a", aVal_);
    RooRealVar n("n", "n", nVal_);

    RooCBShape CB("CB","CB",*mZ1,bwMean,sg,a,n);
    RooRealVar f("f","f", fVal_);

    RooRealVar mean("mean","mean",meanVal_);
    RooRealVar sigma("sigma","sigma",sigmaVal_);
    RooRealVar f1("f1","f1",f1Val_);

    RooGenericPdf RelBW("RelBW","1/( pow(mZ1*mZ1-bwMean*bwMean,2)+pow(mZ1,4)*pow(bwGamma/bwMean,2) )", RooArgSet(*mZ1,bwMean,bwGamma) );

    RooAddPdf RelBWxCB("RelBWxCB","RelBWxCB", RelBW, CB, f);
    RooGaussian gauss("gauss","gauss",*mZ1,mean,sigma);
    RooAddPdf RelBWxCBxgauss("RelBWxCBxgauss","RelBWxCBxgauss", RelBWxCB, gauss, f1);

    RooProdPdf *PDFRelBWxCBxgauss;
    PDFRelBWxCBxgauss = new RooProdPdf("PDFRelBWxCBxgauss","PDFRelBWxCBxgauss", 
                                     RooArgList(gauss1, gauss2, RelBWxCBxgauss) );
    if(p4sZ1ph_.size()==1)    
      PDFRelBWxCBxgauss = new RooProdPdf("PDFRelBWxCBxgauss","PDFRelBWxCBxgauss", 
                                     RooArgList(gauss1, gauss2, gaussph1, RelBWxCBxgauss) );
    if(p4sZ1ph_.size()==2)
      PDFRelBWxCBxgauss = new RooProdPdf("PDFRelBWxCBxgauss","PDFRelBWxCBxgauss", 
                                     RooArgList(gauss1, gauss2, gaussph1, gaussph2, RelBWxCBxgauss) );

    // observable set
    RooArgSet *rastmp;
      rastmp = new RooArgSet(*pT1RECO,*pT2RECO);
    if(p4sZ1ph_.size()==1)
      rastmp = new RooArgSet(*pT1RECO,*pT2RECO,*pTph1RECO);
    if(p4sZ1ph_.size()>=2)
      rastmp = new RooArgSet(*pT1RECO,*pT2RECO,*pTph1RECO,*pTph2RECO);

    RooDataSet* pTs = new RooDataSet("pTs","pTs", *rastmp);
    pTs->add(*rastmp); 

    //RooAbsReal* nll;
    //nll = PDFRelBWxCBxgauss->createNLL(*pTs);
    //RooMinuit(*nll).migrad();

    RooFitResult* r = PDFRelBWxCBxgauss->fitTo(*pTs,RooFit::Save(),RooFit::PrintLevel(-1));
    const TMatrixDSym& covMatrix = r->covarianceMatrix();
   
    const RooArgList& finalPars = r->floatParsFinal();
    for (int i=0 ; i<finalPars.getSize(); i++){
        TString name = TString(((RooRealVar*)finalPars.at(i))->GetName());

        if(debug_) cout<<"name list of RooRealVar for covariance matrix "<<name<<endl;

    }

    int size = covMatrix.GetNcols();
    //TMatrixDSym covMatrixTest_(size);
    covMatrixZ1_.ResizeTo(size,size);
    covMatrixZ1_ = covMatrix;   

    if(debug_) cout<<"save the covariance matrix"<<endl;
    
    l1 = pT1->getVal()/RECOpT1; l2 = pT2->getVal()/RECOpT2;
    double pTerrZ1REFIT1 = pT1->getError(); double pTerrZ1REFIT2 = pT2->getError();

    pTerrsZ1REFIT_.push_back(pTerrZ1REFIT1);
    pTerrsZ1REFIT_.push_back(pTerrZ1REFIT2);

    if(p4sZ1ph_.size()>=1){

      if(debug_) cout<<"set refit result for Z1 fsr photon 1"<<endl;

      lph1 = pTph1->getVal()/RECOpTph1;
      double pTerrZ1phREFIT1 = pTph1->getError();
      if(debug_) cout<<"scale "<<lph1<<" pterr "<<pTerrZ1phREFIT1<<endl;  
   
      pTerrsZ1phREFIT_.push_back(pTerrZ1phREFIT1);

    } 
    if(p4sZ1ph_.size()==2){

      lph2 = pTph2->getVal()/RECOpTph2;
      double pTerrZ1phREFIT2 = pTph2->getError();
      pTerrsZ1phREFIT_.push_back(pTerrZ1phREFIT2);

    }

    //delete nll;
    delete r;
    delete mZ1;
    delete pT1; delete pT2; delete pTph1; delete pTph2;
    delete pT1RECO; delete pT2RECO; delete pTph1RECO; delete pTph2RECO;
    delete ph1v3Dph2; delete p1v3Dph1; delete p2v3Dph1; delete p1v3Dph2; delete p2v3Dph2;
    delete PDFRelBWxCBxgauss;
    delete pTs;
    delete rastmp;

    if(debug_) cout<<"end Z1 refit"<<endl;

    return 0;

}
Example #7
0
//
// calculation of the limit: assumes that wspace is set up and observations
//   contained in data
//
MyLimit computeLimit (RooWorkspace* wspace, RooDataSet* data, StatMethod method, bool draw) {

  // let's time this challenging example
  TStopwatch t;

  //
  // get nominal signal
  //
  RooRealVar exp_sig(*wspace->var("s"));
  double exp_sig_val = exp_sig.getVal();
  std::cout << "exp_sig = " << exp_sig_val << std::endl;
  
  /////////////////////////////////////////////////////
  // Now the statistical tests
  // model config
  std::cout << wspace->pdf("model") << " "
	    << wspace->pdf("prior") << " "
	    << wspace->set("poi") << " "
	    << wspace->set("nuis") << std::endl;
  ModelConfig modelConfig("RA4abcd");
  modelConfig.SetWorkspace(*wspace);
  modelConfig.SetPdf(*wspace->pdf("model"));
  modelConfig.SetPriorPdf(*wspace->pdf("prior"));
  modelConfig.SetParametersOfInterest(*wspace->set("poi"));
  modelConfig.SetNuisanceParameters(*wspace->set("nuis"));


  //////////////////////////////////////////////////
  // If you want to see the covariance matrix uncomment
  // wspace->pdf("model")->fitTo(*data);

  // use ProfileLikelihood
  if ( method == ProfileLikelihoodMethod ) {
    ProfileLikelihoodCalculator plc(*data, modelConfig);
    plc.SetConfidenceLevel(0.95);
    RooFit::MsgLevel msglevel = RooMsgService::instance().globalKillBelow();
    RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
    LikelihoodInterval* plInt = plc.GetInterval();
    RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
    plInt->LowerLimit( *wspace->var("s") ); // get ugly print out of the way. Fix.
    // RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG);
    if ( draw ) {
      TCanvas* c = new TCanvas("ProfileLikelihood");
      LikelihoodIntervalPlot* lrplot = new LikelihoodIntervalPlot(plInt);
      lrplot->Draw();
    }
//     RooMsgService::instance().setGlobalKillBelow(msglevel);
    double lowLim = plInt->LowerLimit(*wspace->var("s"));
    double uppLim = plInt->UpperLimit(*wspace->var("s"));
//     double exp_sig_val = wspace->var("s")->getVal();
//     double exp_sig_val = exp_sig.getVal();
    cout << "Profile Likelihood interval on s = [" << 
      lowLim << ", " <<
      uppLim << "]" << " " << exp_sig_val << endl; 
//     MyLimit result(plInt->IsInInterval(exp_sig),
    MyLimit result(exp_sig_val>lowLim&&exp_sig_val<uppLim,lowLim,uppLim);
    // std::cout << "isIn " << result << std::endl;
    delete plInt;
//     delete modelConfig;
    return result;
  }

  // use FeldmaCousins (takes ~20 min)  
  if ( method == FeldmanCousinsMethod ) {
    FeldmanCousins fc(*data, modelConfig);
    fc.SetConfidenceLevel(0.95);
    //number counting: dataset always has 1 entry with N events observed
    fc.FluctuateNumDataEntries(false); 
    fc.UseAdaptiveSampling(true);
    fc.SetNBins(100);
    PointSetInterval* fcInt = NULL;
    fcInt = (PointSetInterval*) fc.GetInterval(); // fix cast
    double lowLim = fcInt->LowerLimit(*wspace->var("s"));
    double uppLim = fcInt->UpperLimit(*wspace->var("s"));
//     double exp_sig_val = wspace->var("s")->getVal();
    cout << "Feldman Cousins interval on s = [" << lowLim << " " << uppLim << endl;
    // std::cout << "isIn " << result << std::endl;
    MyLimit result(exp_sig_val>lowLim&&exp_sig_val<uppLim,
		   fcInt->LowerLimit(*wspace->var("s")),fcInt->UpperLimit(*wspace->var("s")));
    delete fcInt;
    return result;
  }


  // use BayesianCalculator (only 1-d parameter of interest, slow for this problem)  
  if ( method == BayesianMethod ) {
    BayesianCalculator bc(*data, modelConfig);
    bc.SetConfidenceLevel(0.95);
    bc.SetLeftSideTailFraction(0.5);
    SimpleInterval* bInt = NULL;
    if( wspace->set("poi")->getSize() == 1)   {
      bInt = bc.GetInterval();
      if ( draw ) {
	TCanvas* c = new TCanvas("Bayesian");
	// the plot takes a long time and print lots of error
	// using a scan it is better
	bc.SetScanOfPosterior(50);
	RooPlot* bplot = bc.GetPosteriorPlot();
	bplot->Draw();
      }
      cout << "Bayesian interval on s = [" << 
	bInt->LowerLimit( ) << ", " <<
	bInt->UpperLimit( ) << "]" << endl;
      // std::cout << "isIn " << result << std::endl;
      MyLimit result(bInt->IsInInterval(exp_sig),
		     bInt->LowerLimit(),bInt->UpperLimit());
      delete bInt;
      return result;
    } else {
    cout << "Bayesian Calc. only supports on parameter of interest" << endl;
    return MyLimit();
    }
  }


  // use MCMCCalculator  (takes about 1 min)
  // Want an efficient proposal function, so derive it from covariance
  // matrix of fit
  if ( method == MCMCMethod ) {
    RooFitResult* fit = wspace->pdf("model")->fitTo(*data,Save());
    ProposalHelper ph;
    ph.SetVariables((RooArgSet&)fit->floatParsFinal());
    ph.SetCovMatrix(fit->covarianceMatrix());
    ph.SetUpdateProposalParameters(kTRUE); // auto-create mean vars and add mappings
    ph.SetCacheSize(100);
    ProposalFunction* pf = ph.GetProposalFunction();
    
    MCMCCalculator mc(*data, modelConfig);
    mc.SetConfidenceLevel(0.95);
    mc.SetProposalFunction(*pf);
    mc.SetNumBurnInSteps(100); // first N steps to be ignored as burn-in
    mc.SetNumIters(100000);
    mc.SetLeftSideTailFraction(0.5); // make a central interval
    MCMCInterval* mcInt = NULL;
    mcInt = mc.GetInterval();
    MCMCIntervalPlot mcPlot(*mcInt); 
    mcPlot.Draw();
    cout << "MCMC interval on s = [" << 
      mcInt->LowerLimit(*wspace->var("s") ) << ", " <<
      mcInt->UpperLimit(*wspace->var("s") ) << "]" << endl;
    // std::cout << "isIn " << result << std::endl;
    MyLimit result(mcInt->IsInInterval(exp_sig),
		   mcInt->LowerLimit(*wspace->var("s")),mcInt->UpperLimit(*wspace->var("s")));
    delete mcInt;
    return result;
  }
  

  t.Print();

//   delete modelConfig;
  return MyLimit();

}
Example #8
0
void KinZfitter::MakeModel(/*RooWorkspace &w,*/ KinZfitter::FitInput &input, KinZfitter::FitOutput &output) {

     //lep
     RooRealVar pTRECO1_lep("pTRECO1_lep", "pTRECO1_lep", input.pTRECO1_lep, 5, 500);
     RooRealVar pTRECO2_lep("pTRECO2_lep", "pTRECO2_lep", input.pTRECO2_lep, 5, 500);
     RooRealVar pTMean1_lep("pTMean1_lep", "pTMean1_lep", 
                            input.pTRECO1_lep, max(5.0, input.pTRECO1_lep-2*input.pTErr1_lep), input.pTRECO1_lep+2*input.pTErr1_lep);
     RooRealVar pTMean2_lep("pTMean2_lep", "pTMean2_lep", 
                            input.pTRECO2_lep, max(5.0, input.pTRECO2_lep-2*input.pTErr2_lep), input.pTRECO2_lep+2*input.pTErr2_lep);
     RooRealVar pTSigma1_lep("pTSigma1_lep", "pTSigma1_lep", input.pTErr1_lep);
     RooRealVar pTSigma2_lep("pTSigma2_lep", "pTSigma2_lep", input.pTErr2_lep);
     RooRealVar theta1_lep("theta1_lep", "theta1_lep", input.theta1_lep);
     RooRealVar theta2_lep("theta2_lep", "theta2_lep", input.theta2_lep);
     RooRealVar phi1_lep("phi1_lep", "phi1_lep", input.phi1_lep);
     RooRealVar phi2_lep("phi2_lep", "phi2_lep", input.phi2_lep);
     RooRealVar m1("m1", "m1", input.m1);
     RooRealVar m2("m2", "m2", input.m2);

     //gamma
     RooRealVar pTRECO1_gamma("pTRECO1_gamma", "pTRECO1_gamma", input.pTRECO1_gamma, 5, 500);
     RooRealVar pTRECO2_gamma("pTRECO2_gamma", "pTRECO2_gamma", input.pTRECO2_gamma, 5, 500);
     RooRealVar pTMean1_gamma("pTMean1_gamma", "pTMean1_gamma", 
                              input.pTRECO1_gamma, max(0.5, input.pTRECO1_gamma-2*input.pTErr1_gamma), input.pTRECO1_gamma+2*input.pTErr1_gamma);
     RooRealVar pTMean2_gamma("pTMean2_gamma", "pTMean2_gamma", 
                              input.pTRECO2_gamma, max(0.5, input.pTRECO2_gamma-2*input.pTErr2_gamma), input.pTRECO2_gamma+2*input.pTErr2_gamma);
     RooRealVar pTSigma1_gamma("pTSigma1_gamma", "pTSigma1_gamma", input.pTErr1_gamma);
     RooRealVar pTSigma2_gamma("pTSigma2_gamma", "pTSigma2_gamma", input.pTErr2_gamma);
     RooRealVar theta1_gamma("theta1_gamma", "theta1_gamma", input.theta1_gamma);
     RooRealVar theta2_gamma("theta2_gamma", "theta2_gamma", input.theta2_gamma);
     RooRealVar phi1_gamma("phi1_gamma", "phi1_gamma", input.phi1_gamma);
     RooRealVar phi2_gamma("phi2_gamma", "phi2_gamma", input.phi2_gamma);

     //gauss
     RooGaussian gauss1_lep("gauss1_lep", "gauss1_lep", pTRECO1_lep, pTMean1_lep, pTSigma1_lep);
     RooGaussian gauss2_lep("gauss2_lep", "gauss2_lep", pTRECO2_lep, pTMean2_lep, pTSigma2_lep);
     RooGaussian gauss1_gamma("gauss1_gamma", "gauss1_gamma", pTRECO1_gamma, pTMean1_gamma, pTSigma1_gamma);
     RooGaussian gauss2_gamma("gauss2_gamma", "gauss2_gamma", pTRECO2_gamma, pTMean2_gamma, pTSigma2_gamma);


     TString makeE_lep = "TMath::Sqrt((@0*@0)/((TMath::Sin(@1))*(TMath::Sin(@1)))+@2*@2)";
     RooFormulaVar E1_lep("E1_lep", makeE_lep, RooArgList(pTMean1_lep, theta1_lep, m1));  //w.import(E1_lep);
     RooFormulaVar E2_lep("E2_lep", makeE_lep, RooArgList(pTMean2_lep, theta2_lep, m2));  //w.import(E2_lep);

     TString makeE_gamma = "TMath::Sqrt((@0*@0)/((TMath::Sin(@1))*(TMath::Sin(@1))))";
     RooFormulaVar E1_gamma("E1_gamma", makeE_gamma, RooArgList(pTMean1_gamma, theta1_gamma));  //w.import(E1_gamma);
     RooFormulaVar E2_gamma("E2_gamma", makeE_gamma, RooArgList(pTMean2_gamma, theta2_gamma));  //w.import(E2_gamma);

     //dotProduct 3d
     TString dotProduct_3d = "@0*@1*( ((TMath::Cos(@2))*(TMath::Cos(@3)))/((TMath::Sin(@2))*(TMath::Sin(@3)))+(TMath::Cos(@4-@5)))";
     RooFormulaVar p1v3D2("p1v3D2", dotProduct_3d, RooArgList(pTMean1_lep, pTMean2_lep, theta1_lep, theta2_lep, phi1_lep, phi2_lep));
     RooFormulaVar p1v3Dph1("p1v3Dph1", dotProduct_3d, RooArgList(pTMean1_lep, pTMean1_gamma, theta1_lep, theta1_gamma, phi1_lep, phi1_gamma));
     RooFormulaVar p2v3Dph1("p2v3Dph1", dotProduct_3d, RooArgList(pTMean2_lep, pTMean1_gamma, theta2_lep, theta1_gamma, phi2_lep, phi1_gamma));
     RooFormulaVar p1v3Dph2("p1v3Dph2", dotProduct_3d, RooArgList(pTMean1_lep, pTMean2_gamma, theta1_lep, theta2_gamma, phi1_lep, phi2_gamma));
     RooFormulaVar p2v3Dph2("p2v3Dph2", dotProduct_3d, RooArgList(pTMean2_lep, pTMean2_gamma, theta2_lep, theta2_gamma, phi2_lep, phi2_gamma));
     RooFormulaVar ph1v3Dph2("ph1v3Dph2", dotProduct_3d, RooArgList(pTMean1_gamma, pTMean2_gamma, theta1_gamma, theta2_gamma, phi1_gamma, phi2_gamma));

     TString dotProduct_4d = "@0*@1-@2";
     RooFormulaVar p1D2("p1D2", dotProduct_4d, RooArgList(E1_lep, E2_lep, p1v3D2));  //w.import(p1D2);
     RooFormulaVar p1Dph1("p1Dph1", dotProduct_4d, RooArgList(E1_lep, E1_gamma, p1v3Dph1));//  w.import(p1Dph1);
     RooFormulaVar p2Dph1("p2Dph1", dotProduct_4d, RooArgList(E2_lep, E1_gamma, p2v3Dph1)); // w.import(p2Dph1);
     RooFormulaVar p1Dph2("p1Dph2", dotProduct_4d, RooArgList(E1_lep, E2_gamma, p1v3Dph2));  //w.import(p1Dph2);
     RooFormulaVar p2Dph2("p2Dph2", dotProduct_4d, RooArgList(E2_lep, E2_gamma, p2v3Dph2));  //w.import(p2Dph2);
     RooFormulaVar ph1Dph2("ph1Dph2", dotProduct_4d, RooArgList(E1_gamma, E2_gamma, ph1v3Dph2)); // w.import(ph1Dph2);

     RooRealVar bwMean("bwMean", "m_{Z^{0}}", 91.187); //w.import(bwMean);
     RooRealVar bwGamma("bwGamma", "#Gamma", 2.5); 


     RooProdPdf* PDFRelBW;  
     RooFormulaVar* mZ;
     RooGenericPdf* RelBW;

     //mZ
     mZ = new RooFormulaVar("mZ", "TMath::Sqrt(2*@0+@1*@1+@2*@2)", RooArgList(p1D2, m1, m2));
     RelBW = new RooGenericPdf("RelBW","1/( pow(mZ*mZ-bwMean*bwMean,2)+pow(mZ,4)*pow(bwGamma/bwMean,2) )", RooArgSet(*mZ,bwMean,bwGamma) );
     PDFRelBW = new RooProdPdf("PDFRelBW", "PDFRelBW", RooArgList(gauss1_lep, gauss2_lep, *RelBW));     

     if (input.nFsr == 1) {

        mZ = new RooFormulaVar("mZ", "TMath::Sqrt(2*@0+2*@1+2*@2+@3*@3+@4*@4)", RooArgList(p1D2, p1Dph1, p2Dph1, m1, m2));
        RelBW = new RooGenericPdf("RelBW","1/( pow(mZ*mZ-bwMean*bwMean,2)+pow(mZ,4)*pow(bwGamma/bwMean,2) )", RooArgSet(*mZ,bwMean,bwGamma) );
//        PDFRelBW = new RooProdPdf("PDFRelBW", "PDFRelBW", RooArgList(gauss1_lep, gauss2_lep, gauss1_gamma, *RelBW));

        } 

     if (input.nFsr == 2) {

        mZ = new RooFormulaVar("mZ", "TMath::Sqrt(2*@0+2*@1+2*@2+2*@3+2*@4+2*@5+@6*@6+@7*@7)", RooArgList(p1D2,p1Dph1,p2Dph1,p1Dph2,p2Dph2,ph1Dph2, m1, m2));
        RelBW = new RooGenericPdf("RelBW","1/( pow(mZ*mZ-bwMean*bwMean,2)+pow(mZ,4)*pow(bwGamma/bwMean,2) )", RooArgSet(*mZ,bwMean,bwGamma) );
//        PDFRelBW = new RooProdPdf("PDFRelBW", "PDFRelBW", RooArgList(gauss1_lep, gauss2_lep, gauss1_gamma, gauss2_gamma, *RelBW));

        }

     //true shape
     RooRealVar sg("sg", "sg", sgVal_);
     RooRealVar a("a", "a", aVal_);
     RooRealVar n("n", "n", nVal_);

     RooCBShape CB("CB","CB",*mZ,bwMean,sg,a,n);
     RooRealVar f("f","f", fVal_);

     RooRealVar mean("mean","mean",meanVal_);
     RooRealVar sigma("sigma","sigma",sigmaVal_);
     RooRealVar f1("f1","f1",f1Val_);

     RooAddPdf *RelBWxCB;
     RelBWxCB = new RooAddPdf("RelBWxCB","RelBWxCB", *RelBW, CB, f);
     RooGaussian *gauss;
     gauss = new RooGaussian("gauss","gauss",*mZ,mean,sigma);
     RooAddPdf *RelBWxCBxgauss;
     RelBWxCBxgauss = new RooAddPdf("RelBWxCBxgauss","RelBWxCBxgauss", *RelBWxCB, *gauss, f1);

     RooProdPdf *PDFRelBWxCBxgauss;
     PDFRelBWxCBxgauss = new RooProdPdf("PDFRelBWxCBxgauss","PDFRelBWxCBxgauss", 
                                     RooArgList(gauss1_lep, gauss2_lep, *RelBWxCBxgauss) );


    //make fit
    RooArgSet *rastmp;
    rastmp = new RooArgSet(pTRECO1_lep, pTRECO2_lep);
/*
    if(input.nFsr == 1) {
      rastmp = new RooArgSet(pTRECO1_lep, pTRECO2_lep, pTRECO1_gamma);
      }

    if(input.nFsr == 2) {
      rastmp = new RooArgSet(pTRECO1_lep, pTRECO2_lep, pTRECO1_gamma, pTRECO2_gamma);
      }
*/
    RooDataSet* pTs = new RooDataSet("pTs","pTs", *rastmp);
    pTs->add(*rastmp);

    RooFitResult* r;
    if (mass4lRECO_ > 140) {

       r = PDFRelBW->fitTo(*pTs,RooFit::Save(),RooFit::PrintLevel(-1));

       } else {

              r = PDFRelBWxCBxgauss->fitTo(*pTs,RooFit::Save(),RooFit::PrintLevel(-1));

              }
    //save fit result
    const TMatrixDSym& covMatrix = r->covarianceMatrix();
    const RooArgList& finalPars = r->floatParsFinal();

    for (int i=0 ; i<finalPars.getSize(); i++){
 
        TString name = TString(((RooRealVar*)finalPars.at(i))->GetName());
        if(debug_) cout<<"name list of RooRealVar for covariance matrix "<<name<<endl;

    }

    int size = covMatrix.GetNcols();
    output.covMatrixZ.ResizeTo(size,size);
    output.covMatrixZ = covMatrix;
    
    output.pT1_lep = pTMean1_lep.getVal();
    output.pT2_lep = pTMean2_lep.getVal();
    output.pTErr1_lep = pTMean1_lep.getError();
    output.pTErr2_lep = pTMean2_lep.getError();
/*
    if (input.nFsr >= 1) {

       output.pT1_gamma = pTMean1_gamma.getVal();
       output.pTErr1_gamma = pTMean1_gamma.getError();
    
       }

    if (input.nFsr == 2) {

       output.pT2_gamma = pTMean2_gamma.getVal();
       output.pTErr2_gamma = pTMean2_gamma.getError();

       }
*/
    delete rastmp;
    delete pTs;
    delete PDFRelBW;
    delete mZ;
    delete RelBW;
    delete RelBWxCB;
    delete gauss;
    delete RelBWxCBxgauss;
    delete PDFRelBWxCBxgauss;
}
Example #9
0
void rs101_limitexample()
{
    // --------------------------------------
    // An example of setting a limit in a number counting experiment with uncertainty on background and signal

    // to time the macro
    TStopwatch t;
    t.Start();

    // --------------------------------------
    // The Model building stage
    // --------------------------------------
    RooWorkspace* wspace = new RooWorkspace();
    wspace->factory("Poisson::countingModel(obs[150,0,300], sum(s[50,0,120]*ratioSigEff[1.,0,3.],b[100]*ratioBkgEff[1.,0.,3.]))"); // counting model
    //  wspace->factory("Gaussian::sigConstraint(ratioSigEff,1,0.05)"); // 5% signal efficiency uncertainty
    //  wspace->factory("Gaussian::bkgConstraint(ratioBkgEff,1,0.1)"); // 10% background efficiency uncertainty
    wspace->factory("Gaussian::sigConstraint(gSigEff[1,0,3],ratioSigEff,0.05)"); // 5% signal efficiency uncertainty
    wspace->factory("Gaussian::bkgConstraint(gSigBkg[1,0,3],ratioBkgEff,0.2)"); // 10% background efficiency uncertainty
    wspace->factory("PROD::modelWithConstraints(countingModel,sigConstraint,bkgConstraint)"); // product of terms
    wspace->Print();

    RooAbsPdf* modelWithConstraints = wspace->pdf("modelWithConstraints"); // get the model
    RooRealVar* obs = wspace->var("obs"); // get the observable
    RooRealVar* s = wspace->var("s"); // get the signal we care about
    RooRealVar* b = wspace->var("b"); // get the background and set it to a constant.  Uncertainty included in ratioBkgEff
    b->setConstant();

    RooRealVar* ratioSigEff = wspace->var("ratioSigEff"); // get uncertain parameter to constrain
    RooRealVar* ratioBkgEff = wspace->var("ratioBkgEff"); // get uncertain parameter to constrain
    RooArgSet constrainedParams(*ratioSigEff, *ratioBkgEff); // need to constrain these in the fit (should change default behavior)

    RooRealVar * gSigEff = wspace->var("gSigEff");     // global observables for signal efficiency
    RooRealVar * gSigBkg = wspace->var("gSigBkg");  // global obs for background efficiency
    gSigEff->setConstant();
    gSigBkg->setConstant();

    // Create an example dataset with 160 observed events
    obs->setVal(160.);
    RooDataSet* data = new RooDataSet("exampleData", "exampleData", RooArgSet(*obs));
    data->add(*obs);

    RooArgSet all(*s, *ratioBkgEff, *ratioSigEff);

    // not necessary
    modelWithConstraints->fitTo(*data, RooFit::Constrain(RooArgSet(*ratioSigEff, *ratioBkgEff)));

    // Now let's make some confidence intervals for s, our parameter of interest
    RooArgSet paramOfInterest(*s);

    ModelConfig modelConfig(wspace);
    modelConfig.SetPdf(*modelWithConstraints);
    modelConfig.SetParametersOfInterest(paramOfInterest);
    modelConfig.SetNuisanceParameters(constrainedParams);
    modelConfig.SetObservables(*obs);
    modelConfig.SetGlobalObservables( RooArgSet(*gSigEff,*gSigBkg));
    modelConfig.SetName("ModelConfig");
    wspace->import(modelConfig);
    wspace->import(*data);
    wspace->SetName("w");
    wspace->writeToFile("rs101_ws.root");



    // First, let's use a Calculator based on the Profile Likelihood Ratio
    //ProfileLikelihoodCalculator plc(*data, *modelWithConstraints, paramOfInterest);
    ProfileLikelihoodCalculator plc(*data, modelConfig);
    plc.SetTestSize(.05);
    ConfInterval* lrinterval = plc.GetInterval();  // that was easy.

    // Let's make a plot
    TCanvas* dataCanvas = new TCanvas("dataCanvas");
    dataCanvas->Divide(2,1);

    dataCanvas->cd(1);
    LikelihoodIntervalPlot plotInt((LikelihoodInterval*)lrinterval);
    plotInt.SetTitle("Profile Likelihood Ratio and Posterior for S");
    plotInt.Draw();

    // Second, use a Calculator based on the Feldman Cousins technique
    FeldmanCousins fc(*data, modelConfig);
    fc.UseAdaptiveSampling(true);
    fc.FluctuateNumDataEntries(false); // number counting analysis: dataset always has 1 entry with N events observed
    fc.SetNBins(100); // number of points to test per parameter
    fc.SetTestSize(.05);
    //  fc.SaveBeltToFile(true); // optional
    ConfInterval* fcint = NULL;
    fcint = fc.GetInterval();  // that was easy.

    RooFitResult* fit = modelWithConstraints->fitTo(*data, Save(true));

    // Third, use a Calculator based on Markov Chain monte carlo
    // Before configuring the calculator, let's make a ProposalFunction
    // that will achieve a high acceptance rate
    ProposalHelper ph;
    ph.SetVariables((RooArgSet&)fit->floatParsFinal());
    ph.SetCovMatrix(fit->covarianceMatrix());
    ph.SetUpdateProposalParameters(true);
    ph.SetCacheSize(100);
    ProposalFunction* pdfProp = ph.GetProposalFunction();  // that was easy

    MCMCCalculator mc(*data, modelConfig);
    mc.SetNumIters(20000); // steps to propose in the chain
    mc.SetTestSize(.05); // 95% CL
    mc.SetNumBurnInSteps(40); // ignore first N steps in chain as "burn in"
    mc.SetProposalFunction(*pdfProp);
    mc.SetLeftSideTailFraction(0.5);  // find a "central" interval
    MCMCInterval* mcInt = (MCMCInterval*)mc.GetInterval();  // that was easy


    // Get Lower and Upper limits from Profile Calculator
    cout << "Profile lower limit on s = " << ((LikelihoodInterval*) lrinterval)->LowerLimit(*s) << endl;
    cout << "Profile upper limit on s = " << ((LikelihoodInterval*) lrinterval)->UpperLimit(*s) << endl;

    // Get Lower and Upper limits from FeldmanCousins with profile construction
    if (fcint != NULL) {
        double fcul = ((PointSetInterval*) fcint)->UpperLimit(*s);
        double fcll = ((PointSetInterval*) fcint)->LowerLimit(*s);
        cout << "FC lower limit on s = " << fcll << endl;
        cout << "FC upper limit on s = " << fcul << endl;
        TLine* fcllLine = new TLine(fcll, 0, fcll, 1);
        TLine* fculLine = new TLine(fcul, 0, fcul, 1);
        fcllLine->SetLineColor(kRed);
        fculLine->SetLineColor(kRed);
        fcllLine->Draw("same");
        fculLine->Draw("same");
        dataCanvas->Update();
    }

    // Plot MCMC interval and print some statistics
    MCMCIntervalPlot mcPlot(*mcInt);
    mcPlot.SetLineColor(kMagenta);
    mcPlot.SetLineWidth(2);
    mcPlot.Draw("same");

    double mcul = mcInt->UpperLimit(*s);
    double mcll = mcInt->LowerLimit(*s);
    cout << "MCMC lower limit on s = " << mcll << endl;
    cout << "MCMC upper limit on s = " << mcul << endl;
    cout << "MCMC Actual confidence level: "
         << mcInt->GetActualConfidenceLevel() << endl;

    // 3-d plot of the parameter points
    dataCanvas->cd(2);
    // also plot the points in the markov chain
    RooDataSet * chainData = mcInt->GetChainAsDataSet();

    assert(chainData);
    std::cout << "plotting the chain data - nentries = " << chainData->numEntries() << std::endl;
    TTree* chain =  RooStats::GetAsTTree("chainTreeData","chainTreeData",*chainData);
    assert(chain);
    chain->SetMarkerStyle(6);
    chain->SetMarkerColor(kRed);

    chain->Draw("s:ratioSigEff:ratioBkgEff","nll_MarkovChain_local_","box"); // 3-d box proportional to posterior

    // the points used in the profile construction
    RooDataSet * parScanData = (RooDataSet*) fc.GetPointsToScan();
    assert(parScanData);
    std::cout << "plotting the scanned points used in the frequentist construction - npoints = " << parScanData->numEntries() << std::endl;
    // getting the tree and drawing it -crashes (very strange....);
    // TTree* parameterScan =  RooStats::GetAsTTree("parScanTreeData","parScanTreeData",*parScanData);
    // assert(parameterScan);
    // parameterScan->Draw("s:ratioSigEff:ratioBkgEff","","goff");
    TGraph2D *gr = new TGraph2D(parScanData->numEntries());
    for (int ievt = 0; ievt < parScanData->numEntries(); ++ievt) {
        const RooArgSet * evt = parScanData->get(ievt);
        double x = evt->getRealValue("ratioBkgEff");
        double y = evt->getRealValue("ratioSigEff");
        double z = evt->getRealValue("s");
        gr->SetPoint(ievt, x,y,z);
        // std::cout << ievt << "  " << x << "  " << y << "  " << z << std::endl;
    }
    gr->SetMarkerStyle(24);
    gr->Draw("P SAME");


    delete wspace;
    delete lrinterval;
    delete mcInt;
    delete fcint;
    delete data;

    // print timing info
    t.Stop();
    t.Print();
}
void addNuisanceWithToys(std::string iFileName,std::string iChannel,std::string iBkg,std::string iEnergy,std::string iName,std::string iDir,bool iRebin=true,bool iVarBin=false,int iFitModel=1,int iFitModel1=1,double iFirst=150,double iLast=1500,std::string iSigMass="800",double iSigScale=0.1,int iNToys=1000) { 
  std::cout << "======> " << iDir << "/" << iBkg << " -- " << iFileName << std::endl;  
  if(iVarBin) std::cout << "option not implemented yet!";
  if(iVarBin) return;
  //double lFirst = 200;
  //double lLast  = 1500;
  double lFirst = iFirst;
  double lLast  = iLast;

  std::cout << "===================================================================================================================================================" <<std::endl;
  std::cout << "Using Initial fit model: " << iFitModel << ", fitting range: " << iFirst << "-" << iLast << " , using alternative fit model: " << iFitModel1 << std::endl; 
  std::cout << "===================================================================================================================================================" <<std::endl;

  TFile *lFile = new TFile(iFileName.c_str());
  TH1F  *lH0   = (TH1F*) lFile->Get((iDir+"/"+iBkg).c_str());
  TH1F  *lData = (TH1F*) lFile->Get((iDir+"/data_obs").c_str());
  TH1F  *lSig = 0;

  // for now, use bbH signal for testing in b-tag and ggH in no-btag
  if(iDir.find("_btag") != std::string::npos) lSig = (TH1F*)lFile->Get((iDir+"/bbH"+iSigMass+"_fine_binning").c_str());
  else lSig = (TH1F*)lFile->Get((iDir+"/ggH"+iSigMass+"_fine_binning").c_str());

  TH1F *lH0Clone = (TH1F*)lH0->Clone("lH0Clone");     // binning too fine as of now? start by rebinning
  TH1F *lDataClone = (TH1F*)lData->Clone("lDataClone");   
  TH1F *lSigClone = (TH1F*)lSig->Clone("lSigClone");  
 // lH0Clone->Rebin(2);
 // lDataClone->Rebin(2);
 // lSigClone->Rebin(2);

  lSig->Rebin(10);  

  //Define the fit function
  RooRealVar lM("m","m" ,0,5000);
  lM.setRange(lFirst,lLast);
  RooRealVar lA("a","a" ,50,  0.1,200);
  RooRealVar lB("b","b" ,0.0 , -10.5,10.5);
  RooRealVar lA1("a1","a1" ,50,  0.1,1000);
  RooRealVar lB1("b1","b1" ,0.0 , -10.5,10.5);

  RooDataHist *pH0  =  new RooDataHist("Data","Data" ,RooArgList(lM),lH0);
  double lNB0 = lH0->Integral(lH0->FindBin(lFirst),lH0->FindBin(lLast));
  double lNSig0 = lSig->Integral(lSig->FindBin(lFirst),lSig->FindBin(lLast));
 //lNB0=500;
// lNSig0=500;
 lSig->Scale(iSigScale*lNB0/lNSig0);                                         // scale signal to iSigScale*(Background yield), could try other options
 lNSig0 = lSig->Integral(lSig->FindBin(lFirst),lSig->FindBin(lLast));        // readjust norm of signal hist   
  
  //Generate the "default" fit model 

  RooGenericPdf *lFit  = 0; lFit = new RooGenericPdf("genPdf","exp(-m/(a+b*m))",RooArgList(lM,lA,lB));
  if(iFitModel == 1) lFit = new RooGenericPdf("genPdf","exp(-a*pow(m,b))",RooArgList(lM,lA,lB));
  if(iFitModel == 1) {lA.setVal(0.3); lB.setVal(0.5);}
  if(iFitModel == 2) lFit = new RooGenericPdf("genPdf","a*exp(b*m)",RooArgList(lM,lA,lB));
  if(iFitModel == 2) {lA.setVal(0.01); lA.setRange(0,10); }
  if(iFitModel == 3) lFit = new RooGenericPdf("genPdf","a/pow(m,b)",RooArgList(lM,lA,lB));
 
  // Generate the alternative model
  
  RooGenericPdf *lFit1  = 0; lFit1 = new RooGenericPdf("genPdf","exp(-m/(a1+b1*m))",RooArgList(lM,lA1,lB1));
  if(iFitModel1 == 1) lFit1 = new RooGenericPdf("genPdf","exp(-a1*pow(m,b1))",RooArgList(lM,lA1,lB1));
  if(iFitModel1 == 1) {lA1.setVal(0.3); lB1.setVal(0.5);}
  if(iFitModel1 == 2) lFit1 = new RooGenericPdf("genPdf","a1*exp(b1*m)",RooArgList(lM,lA1,lB1));
  if(iFitModel1 == 2) {lA1.setVal(0.01); lA1.setRange(0,10); }
  if(iFitModel1 == 3) lFit1 = new RooGenericPdf("genPdf","a1/pow(m,b1)",RooArgList(lM,lA1,lB1));
  
  //=============================================================================================================================================
  //Perform the tail fit and generate the shift up and down histograms
  //=============================================================================================================================================

  RooFitResult  *lRFit = 0;
  lRFit = lFit->fitTo(*pH0,RooFit::Save(kTRUE),RooFit::Range(lFirst,lLast),RooFit::Strategy(0)); 
  TMatrixDSym lCovMatrix   = lRFit->covarianceMatrix(); 
  TMatrixD  lEigVecs(2,2);    lEigVecs = TMatrixDSymEigen(lCovMatrix).GetEigenVectors();
  TVectorD  lEigVals(2);      lEigVals = TMatrixDSymEigen(lCovMatrix).GetEigenValues();
  cout << " Ve---> " << lEigVecs(0,0) << " -- " << lEigVecs(1,0) << " -- " << lEigVecs(0,1) << " -- " << lEigVecs(1,1) << endl;
  cout << " Co---> " << lCovMatrix(0,0) << " -- " << lCovMatrix(1,0) << " -- " << lCovMatrix(0,1) << " -- " << lCovMatrix(1,1) << endl;
  double lACentral = lA.getVal();
  double lBCentral = lB.getVal();
  lEigVals(0) = sqrt(lEigVals(0));
  lEigVals(1) = sqrt(lEigVals(1));
  cout << "===> " << lEigVals(0) << " -- " << lEigVals(1) << endl;
  
  TH1F* lH     = (TH1F*) lFit->createHistogram("fit" ,lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));

  lA.setVal(lACentral + lEigVals(0)*lEigVecs(0,0));
  lB.setVal(lBCentral + lEigVals(0)*lEigVecs(1,0));
  TH1F* lHUp   = (TH1F*) lFit->createHistogram("Up"  ,lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));

  lA.setVal(lACentral - lEigVals(0)*lEigVecs(0,0));
  lB.setVal(lBCentral - lEigVals(0)*lEigVecs(1,0));
  TH1F* lHDown = (TH1F*) lFit->createHistogram("Down",lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));

  lA.setVal(lACentral + lEigVals(1)*lEigVecs(0,1));
  lB.setVal(lBCentral + lEigVals(1)*lEigVecs(1,1));
  TH1F* lHUp1   = (TH1F*) lFit->createHistogram("Up1",lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));

  lA.setVal(lACentral - lEigVals(1)*lEigVecs(0,1));
  lB.setVal(lBCentral - lEigVals(1)*lEigVecs(1,1));
  TH1F* lHDown1 = (TH1F*) lFit->createHistogram("Down1",lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));

  std::string lNuisance1 =  iBkg+"_"+"CMS_"+iName+"1_" + iChannel + "_" + iEnergy;
  std::string lNuisance2 =  iBkg+"_"+"CMS_"+iName+"2_" + iChannel + "_" + iEnergy;
  lHUp    = merge(lNuisance1 + "Up"   ,lFirst,lH0,lHUp);
  lHDown  = merge(lNuisance1 + "Down" ,lFirst,lH0,lHDown);
  lHUp1   = merge(lNuisance2 + "Up"   ,lFirst,lH0,lHUp1);
  lHDown1 = merge(lNuisance2 + "Down" ,lFirst,lH0,lHDown1);
  lH      = merge(lH0->GetName()      ,lFirst,lH0,lH);

  //=============================================================================================================================================
  //=============================================================================================================================================
  
  //Set the variables A and B to the final central values from the tail fit

  lA.setVal(lACentral);
  lB.setVal(lBCentral);
 // lA.removeRange();
 // lB.removeRange();
 
  //Generate the background pdf corresponding to the final result of the tail fit
 
 RooGenericPdf *lFitFinal  = 0; lFitFinal = new RooGenericPdf("genPdf","exp(-m/(a+b*m))",RooArgList(lM,lA,lB));
  if(iFitModel == 1) lFitFinal = new RooGenericPdf("genPdf","exp(-a*pow(m,b))",RooArgList(lM,lA,lB));
  if(iFitModel == 2) lFitFinal = new RooGenericPdf("genPdf","a*exp(b*m)",RooArgList(lM,lA,lB));
  if(iFitModel == 3) lFitFinal = new RooGenericPdf("genPdf","a/pow(m,b)",RooArgList(lM,lA,lB));



  //=============================================================================================================================================
  //Perform the tail fit with the alternative fit function (once initially, before allowing tail fit to float in toy fit).
  //=============================================================================================================================================

  RooFitResult  *lRFit1 = 0;
 //lRFit1=lFit1->fitTo(*pH0,RooFit::Save(kTRUE),RooFit::Range(iFirst,iLast),RooFit::Strategy(0));  
 lRFit1=lFit1->fitTo(*pH0,RooFit::Save(kTRUE),RooFit::Range(200,1500),RooFit::Strategy(0));  
  
  //Generate the background pdf corresponding to the result of the alternative tail fit

  RooGenericPdf *lFit1Final  = 0; lFit1Final = new RooGenericPdf("genPdf","exp(-m/(a1+b1*m))",RooArgList(lM,lA1,lB1));
  if(iFitModel1 == 1) lFit1Final = new RooGenericPdf("genPdf","exp(-a1*pow(m,b1))",RooArgList(lM,lA1,lB1));
  if(iFitModel1 == 2) lFit1Final = new RooGenericPdf("genPdf","a1*exp(b1*m)",RooArgList(lM,lA1,lB1));
  if(iFitModel1 == 3) lFit1Final = new RooGenericPdf("genPdf","a1/pow(m,b1)",RooArgList(lM,lA1,lB1));

 // lA1.removeRange();
 // lB1.removeRange();
  
  //=============================================================================================================================================

  //Define RooRealVar for the normalization of the signal and background, starting from the initial integral of the input histograms

  lM.setRange(300,1500);  

  RooRealVar lNB("nb","nb",lNB0,0,10000);
  RooRealVar lNSig("nsig","nsig",lNSig0,-1000,1000);

  //Define a PDF for the signal histogram lSig
  
  RooDataHist  *pS      = new RooDataHist("sigH","sigH",RooArgList(lM),lSig);
  RooHistPdf   *lSPdf   = new RooHistPdf ("sigPdf","sigPdf",lM,*pS);
 
  //Define generator and fit functions for the RooMCStudy

  RooAddPdf    *lGenMod = new RooAddPdf  ("genmod","genmod",RooArgList(*lFitFinal ,*lSPdf),RooArgList(lNB,lNSig));
  RooAddPdf    *lFitMod = new RooAddPdf  ("fitmod","fitmod",RooArgList(*lFit1Final,*lSPdf),RooArgList(lNB,lNSig));

  //Generate plot of the signal and background models going into the toy generation   

  RooPlot* plot=lM.frame();
  lGenMod->plotOn(plot);
  lGenMod->plotOn(plot,RooFit::Components(*lSPdf),RooFit::LineColor(2));
  TCanvas* lC11 = new TCanvas("pdf","pdf",600,600) ;
  lC11->cd();
  plot->Draw();
  lC11->SaveAs(("SBModel_"+iBkg+"_" + iDir + "_" + iEnergy+".pdf").c_str());

  std::cout << "===================================================================================================================================================" <<std::endl;
  std::cout << "FIT PARAMETERS BEFORE ROOMCSTUDY: lA: " << lA.getVal() << " lB: " << lB.getVal() << " lA1: " << lA1.getVal() << " lB1: " << lB1.getVal() << std::endl;  
  std::cout << "===================================================================================================================================================" <<std::endl;


  RooMCStudy   *lToy    = new RooMCStudy(*lGenMod,lM,RooFit::FitModel(*lFitMod),RooFit::Binned(kTRUE),RooFit::Silence(),RooFit::Extended(kTRUE),RooFit::Verbose(kTRUE),RooFit::FitOptions(RooFit::Save(kTRUE),RooFit::Strategy(0)));

  // Generate and fit iNToys toy samples
  
  std::cout << "Number of background events: " << lNB0 << " Number of signal events: " << lNSig0 << " Sum: " << lNB0+lNSig0 << std::endl;
  
  //=============================================================================================================================================
  // Generate and fit toys
  //============================================================================================================================================= 
    
  lToy->generateAndFit(iNToys,lNB0+lNSig0,kTRUE);
 
  std::cout << "===================================================================================================================================================" <<std::endl;
  std::cout << "FIT PARAMETERS AFTER ROOMCSTUDY: lA: " << lA.getVal() << " lB: " << lB.getVal() << " lA1: " << lA1.getVal() << " lB1: " << lB1.getVal() << std::endl;  
  std::cout << "===================================================================================================================================================" <<std::endl;
  

  //=============================================================================================================================================
  // Generate plots relevant to the toy fit
  //=============================================================================================================================================

  RooPlot* lFrame1 = lToy->plotPull(lNSig,-5,5,100,kTRUE);
  lFrame1->SetTitle("distribution of pulls on signal yield from toys");
  lFrame1->SetXTitle("N_{sig} pull");
  
  TCanvas* lC00 = new TCanvas("pulls","pulls",600,600) ;
  lC00->cd();
  lFrame1->GetYaxis()->SetTitleOffset(1.2); 
  lFrame1->GetXaxis()->SetTitleOffset(1.0); 
  lFrame1->Draw() ;
  lC00->SaveAs(("sig_pulls_toyfits_"+iBkg+"_" + iDir + "_" + iEnergy+".png").c_str());

  RooPlot* lFrame2 = lToy->plotParam(lA1);
  lFrame2->SetTitle("distribution of values of parameter 1 (a) after toy fit");
  lFrame2->SetXTitle("Parameter 1 (a)");
  TCanvas* lC01 = new TCanvas("valA","valA",600,600) ;
  lFrame2->Draw() ;
  lC01->SaveAs(("valA_toyfits_"+iBkg+"_" + iDir + "_" + iEnergy+".png").c_str());

  RooPlot* lFrame3 = lToy->plotParam(lB1);
  lFrame3->SetTitle("distribution of values of parameter 2 (b) after toy fit");
  lFrame3->SetXTitle("Parameter 2 (b)");
  TCanvas* lC02 = new TCanvas("valB","valB",600,600) ;
  lFrame3->Draw() ;
  lC02->SaveAs(("valB_toyfits_"+iBkg+"_" + iDir + "_" + iEnergy+".png").c_str());
  
  RooPlot* lFrame6 = lToy->plotNLL(0,1000,100);
  lFrame6->SetTitle("-log(L)");
  lFrame6->SetXTitle("-log(L)");
  TCanvas* lC05 = new TCanvas("logl","logl",600,600) ;
  lFrame6->Draw() ;
  lC05->SaveAs(("logL_toyfits_"+iBkg+"_" + iDir + "_" + iEnergy+".png").c_str());

  RooPlot* lFrame7 = lToy->plotParam(lNSig);
  lFrame7->SetTitle("distribution of values of N_{sig} after toy fit");
  lFrame7->SetXTitle("N_{sig}");
  TCanvas* lC06 = new TCanvas("Nsig","Nsig",600,600) ;
  lFrame7->Draw() ;
  lC06->SaveAs(("NSig_toyfits_"+iBkg+"_" + iDir + "_" + iEnergy+".png").c_str());
  
  RooPlot* lFrame8 = lToy->plotParam(lNB);
  lFrame8->SetTitle("distribution of values of N_{bkg} after toy fit");
  lFrame8->SetXTitle("N_{bkg}");
  TCanvas* lC07 = new TCanvas("Nbkg","Nbkg",600,600) ;
  lFrame8->Draw() ;
  lC07->SaveAs(("Nbkg_toyfits_"+iBkg+"_" + iDir + "_" + iEnergy+".png").c_str());
 

  if(iRebin) { 
    const int lNBins = lData->GetNbinsX();
    double *lAxis    = getAxis(lData);
    lH0     = rebin(lH0    ,lNBins,lAxis);
    lH      = rebin(lH     ,lNBins,lAxis);
    lHUp    = rebin(lHUp   ,lNBins,lAxis);
    lHDown  = rebin(lHDown ,lNBins,lAxis);
    lHUp1   = rebin(lHUp1  ,lNBins,lAxis);
    lHDown1 = rebin(lHDown1,lNBins,lAxis);
  }

  // we dont need this bin errors since we do not use them (fit tails replaces bin-by-bin error!), therefore i set all errors to 0, this also saves us from modifying the add_bbb_error.py script in which I otherwise would have to include a option for adding bbb only in specific ranges
  int lMergeBin = lH->GetXaxis()->FindBin(iFirst);
  for(int i0 = lMergeBin; i0 < lH->GetNbinsX()+1; i0++){
    lH->SetBinError  (i0,0);
    lHUp->SetBinError  (i0,0);
    lHDown->SetBinError  (i0,0);
    lHUp1->SetBinError  (i0,0);
    lHDown1->SetBinError  (i0,0);
  }


  TFile *lOutFile =new TFile("Output.root","RECREATE");
  cloneFile(lOutFile,lFile,iDir+"/"+iBkg);
  lOutFile->cd(iDir.c_str());
  lH     ->Write();
  lHUp   ->Write(); 
  lHDown ->Write(); 
  lHUp1  ->Write(); 
  lHDown1->Write(); 

  // Debug Plots
  lH0->SetStats(0);
  lH->SetStats(0);
  lHUp->SetStats(0);
  lHDown->SetStats(0);
  lHUp1->SetStats(0);
  lHDown1->SetStats(0);
  lH0    ->SetLineWidth(1); lH0->SetMarkerStyle(kFullCircle);
  lH     ->SetLineColor(kGreen);
  lHUp   ->SetLineColor(kRed);
  lHDown ->SetLineColor(kRed);
  lHUp1  ->SetLineColor(kBlue);
  lHDown1->SetLineColor(kBlue);
  TCanvas *lC0 = new TCanvas("Can","Can",800,600);
  lC0->Divide(1,2); lC0->cd();  lC0->cd(1)->SetPad(0,0.2,1.0,1.0); gPad->SetLeftMargin(0.2) ; 
  lH0->Draw();
  lH     ->Draw("hist sames");
  lHUp   ->Draw("hist sames");
  lHDown ->Draw("hist sames");
  lHUp1  ->Draw("hist sames");
  lHDown1->Draw("hist sames");
  gPad->SetLogy();
  
  TLegend* leg1;
  /// setup the CMS Preliminary
  leg1 = new TLegend(0.7, 0.80, 1, 1); 
  leg1->SetBorderSize( 0 );
  leg1->SetFillStyle ( 1001 );
  leg1->SetFillColor (kWhite);
  leg1->AddEntry( lH0 , "orignal",  "PL" );
  leg1->AddEntry( lH , "cental fit",  "L" );
  leg1->AddEntry( lHUp , "shift1 up",  "L" );
  leg1->AddEntry( lHDown , "shift1 down",  "L" );
  leg1->AddEntry( lHUp1 , "shift2 up",  "L" );
  leg1->AddEntry( lHDown1 , "shift2 down",  "L" );
  leg1->Draw("same");


  lC0->cd(2)->SetPad(0,0,1.0,0.2); gPad->SetLeftMargin(0.2) ;
  drawDifference(lH0,lH,lHUp,lHDown,lHUp1,lHDown1);
  lH0->SetStats(0);
  lC0->Update();
  lC0->SaveAs((iBkg+"_"+"CMS_"+iName+"1_" + iDir + "_" + iEnergy+".png").c_str());
  //lFile->Close();
  return;
}
void addNuisance(std::string iFileName,std::string iChannel,std::string iBkg,std::string iEnergy,std::string iName,std::string iDir,bool iRebin=true,bool iVarBin=false,int iFitModel=1,double iFirst=150,double iLast=1500) { 
  std::cout << "======> " << iDir << "/" << iBkg << " -- " << iFileName << std::endl;  
  if(iVarBin) addVarBinNuisance(iFileName,iChannel,iBkg,iEnergy,iName,iDir,iRebin,iFitModel,iFirst,iLast);
  if(iVarBin) return;

  TFile *lFile = new TFile(iFileName.c_str());
  TH1F  *lH0   = (TH1F*) lFile->Get((iDir+"/"+iBkg).c_str());
  TH1F  *lData = (TH1F*) lFile->Get((iDir+"/data_obs").c_str());

  //Define the fit function
  RooRealVar lM("m","m" ,0,5000);   //lM.setBinning(lBinning);
  RooRealVar lA("a","a" ,50,  0.1,100);
  RooRealVar lB("b","b" ,0.0 , -10.5,10.5); //lB.setConstant(kTRUE);
  RooDataHist *pH0  =  new RooDataHist("Data","Data" ,RooArgList(lM),lH0);
  RooGenericPdf *lFit  = 0; lFit = new RooGenericPdf("genPdf","exp(-m/(a+b*m))",RooArgList(lM,lA,lB));
  if(iFitModel == 1) lFit = new RooGenericPdf("genPdf","exp(-a*pow(m,b))",RooArgList(lM,lA,lB));
  if(iFitModel == 1) {lA.setVal(0.3); lB.setVal(0.5);}
  if(iFitModel == 2) lFit = new RooGenericPdf("genPdf","a*exp(b*m)",RooArgList(lM,lA,lB));
  if(iFitModel == 3) lFit = new RooGenericPdf("genPdf","a/pow(m,b)",RooArgList(lM,lA,lB));
  RooFitResult  *lRFit = 0;
  double lFirst = iFirst;
  double lLast  = iLast;
  //lRFit = lFit->chi2FitTo(*pH0,RooFit::Save(kTRUE),RooFit::Range(lFirst,lLast));
  lRFit = lFit->fitTo(*pH0,RooFit::Save(kTRUE),RooFit::Range(lFirst,lLast),RooFit::Strategy(0)); 
  TMatrixDSym lCovMatrix   = lRFit->covarianceMatrix(); 
  TMatrixD  lEigVecs(2,2);    lEigVecs = TMatrixDSymEigen(lCovMatrix).GetEigenVectors();
  TVectorD  lEigVals(2);      lEigVals = TMatrixDSymEigen(lCovMatrix).GetEigenValues();
  cout << " Ve---> " << lEigVecs(0,0) << " -- " << lEigVecs(1,0) << " -- " << lEigVecs(0,1) << " -- " << lEigVecs(1,1) << endl;
  cout << " Co---> " << lCovMatrix(0,0) << " -- " << lCovMatrix(1,0) << " -- " << lCovMatrix(0,1) << " -- " << lCovMatrix(1,1) << endl;
  double lACentral = lA.getVal();
  double lBCentral = lB.getVal();
  lEigVals(0) = sqrt(lEigVals(0));
  lEigVals(1) = sqrt(lEigVals(1));
  cout << "===> " << lEigVals(0) << " -- " << lEigVals(1) << endl;
  
  TH1F* lH     = (TH1F*) lFit->createHistogram("fit" ,lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));
  lA.setVal(lACentral + lEigVals(0)*lEigVecs(0,0));
  lB.setVal(lBCentral + lEigVals(0)*lEigVecs(1,0));
  TH1F* lHUp   = (TH1F*) lFit->createHistogram("Up"  ,lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));
  lA.setVal(lACentral - lEigVals(0)*lEigVecs(0,0));
  lB.setVal(lBCentral - lEigVals(0)*lEigVecs(1,0));
  TH1F* lHDown = (TH1F*) lFit->createHistogram("Down",lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));

  lA.setVal(lACentral + lEigVals(1)*lEigVecs(0,1));
  lB.setVal(lBCentral + lEigVals(1)*lEigVecs(1,1));
  TH1F* lHUp1   = (TH1F*) lFit->createHistogram("Up1",lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));
  lA.setVal(lACentral - lEigVals(1)*lEigVecs(0,1));
  lB.setVal(lBCentral - lEigVals(1)*lEigVecs(1,1));
  TH1F* lHDown1 = (TH1F*) lFit->createHistogram("Down1",lM,RooFit::Binning(lH0->GetNbinsX(),lH0->GetXaxis()->GetXmin(),lH0->GetXaxis()->GetXmax()));

  std::string lNuisance1 =  iBkg+"_"+"CMS_"+iName+"1_" + iChannel + "_" + iEnergy;
  std::string lNuisance2 =  iBkg+"_"+"CMS_"+iName+"2_" + iChannel + "_" + iEnergy;
  lHUp    = merge(lNuisance1 + "Up"   ,lFirst,lH0,lHUp);
  lHDown  = merge(lNuisance1 + "Down" ,lFirst,lH0,lHDown);
  lHUp1   = merge(lNuisance2 + "Up"   ,lFirst,lH0,lHUp1);
  lHDown1 = merge(lNuisance2 + "Down" ,lFirst,lH0,lHDown1);
  lH      = merge(lH0->GetName()      ,lFirst,lH0,lH);

  if(iRebin) { 
    const int lNBins = lData->GetNbinsX();
    double *lAxis    = getAxis(lData);
    lH0     = rebin(lH0    ,lNBins,lAxis);
    lH      = rebin(lH     ,lNBins,lAxis);
    lHUp    = rebin(lHUp   ,lNBins,lAxis);
    lHDown  = rebin(lHDown ,lNBins,lAxis);
    lHUp1   = rebin(lHUp1  ,lNBins,lAxis);
    lHDown1 = rebin(lHDown1,lNBins,lAxis);
  }

  // we dont need this bin errors since we do not use them (fit tails replaces bin-by-bin error!), therefore i set all errors to 0, this also saves us from modifying the add_bbb_error.py script in which I otherwise would have to include a option for adding bbb only in specific ranges
  int lMergeBin = lH->GetXaxis()->FindBin(iFirst);
  for(int i0 = lMergeBin; i0 < lH->GetNbinsX()+1; i0++){
    lH->SetBinError  (i0,0);
    lHUp->SetBinError  (i0,0);
    lHDown->SetBinError  (i0,0);
    lHUp1->SetBinError  (i0,0);
    lHDown1->SetBinError  (i0,0);
  }


  TFile *lOutFile =new TFile("Output.root","RECREATE");
  cloneFile(lOutFile,lFile,iDir+"/"+iBkg);
  lOutFile->cd(iDir.c_str());
  lH     ->Write();
  lHUp   ->Write(); 
  lHDown ->Write(); 
  lHUp1  ->Write(); 
  lHDown1->Write(); 

  // Debug Plots
  lH0->SetStats(0);
  lH->SetStats(0);
  lHUp->SetStats(0);
  lHDown->SetStats(0);
  lHUp1->SetStats(0);
  lHDown1->SetStats(0);
  lH0    ->SetLineWidth(1); lH0->SetMarkerStyle(kFullCircle);
  lH     ->SetLineColor(kGreen);
  lHUp   ->SetLineColor(kRed);
  lHDown ->SetLineColor(kRed);
  lHUp1  ->SetLineColor(kBlue);
  lHDown1->SetLineColor(kBlue);
  TCanvas *lC0 = new TCanvas("Can","Can",800,600);
  lC0->Divide(1,2); lC0->cd();  lC0->cd(1)->SetPad(0,0.2,1.0,1.0); gPad->SetLeftMargin(0.2) ; 
  lH0->Draw();
  lH     ->Draw("hist sames");
  lHUp   ->Draw("hist sames");
  lHDown ->Draw("hist sames");
  lHUp1  ->Draw("hist sames");
  lHDown1->Draw("hist sames");
  gPad->SetLogy();
  
  TLegend* leg1;
  /// setup the CMS Preliminary
  leg1 = new TLegend(0.7, 0.80, 1, 1); 
  leg1->SetBorderSize( 0 );
  leg1->SetFillStyle ( 1001 );
  leg1->SetFillColor (kWhite);
  leg1->AddEntry( lH0 , "orignal",  "PL" );
  leg1->AddEntry( lH , "cental fit",  "L" );
  leg1->AddEntry( lHUp , "shift1 up",  "L" );
  leg1->AddEntry( lHDown , "shift1 down",  "L" );
  leg1->AddEntry( lHUp1 , "shift2 up",  "L" );
  leg1->AddEntry( lHDown1 , "shift2 down",  "L" );
  leg1->Draw("same");


  lC0->cd(2)->SetPad(0,0,1.0,0.2); gPad->SetLeftMargin(0.2) ;
  drawDifference(lH0,lH,lHUp,lHDown,lHUp1,lHDown1);
  lH0->SetStats(0);
  lC0->Update();
  lC0->SaveAs((iBkg+"_"+"CMS_"+iName+"1_" + iDir + "_" + iEnergy+".png").c_str());
  //lFile->Close();
  return;
}