Example #1
0
void BackgroundPrediction(std::string pname,int rebin_factor,int model_number = 0,int imass=750, bool plotBands = false)
{
    rebin = rebin_factor;
    std::string fname = std::string("../fitFilesMETPT34/") + pname + std::string("/histos_bkg.root");
    
    stringstream iimass ;
    iimass << imass;
    std::string dirName = "info_"+iimass.str()+"_"+pname;
    
    
    gStyle->SetOptStat(000000000);
    gStyle->SetPadGridX(0);
    gStyle->SetPadGridY(0);
    
    setTDRStyle();
    gStyle->SetPadGridX(0);
    gStyle->SetPadGridY(0);
    gStyle->SetOptStat(0000);
    
    writeExtraText = true;       // if extra text
    extraText  = "Preliminary";  // default extra text is "Preliminary"
    lumi_13TeV  = "2.7 fb^{-1}"; // default is "19.7 fb^{-1}"
    lumi_7TeV  = "4.9 fb^{-1}";  // default is "5.1 fb^{-1}"
    
    
    double ratio_tau=-1;
    
    TFile *f=new TFile(fname.c_str());
    TH1F *h_mX_CR_tau=(TH1F*)f->Get("distribs_18_10_1")->Clone("CR_tau");
    TH1F *h_mX_SR=(TH1F*)f->Get("distribs_18_10_0")->Clone("The_SR");
    double maxdata = h_mX_SR->GetMaximum();
    double nEventsSR = h_mX_SR->Integral(600,4000);
    ratio_tau=(h_mX_SR->GetSumOfWeights()/(h_mX_CR_tau->GetSumOfWeights()));
    //double nEventsSR = h_mX_SR->Integral(600,4000);
    
    std::cout<<"ratio tau "<<ratio_tau<<std::endl;
    
    TH1F *h_SR_Prediction;
    TH1F *h_SR_Prediction2;
    
    if(blind) {
        h_SR_Prediction2 = (TH1F*)h_mX_CR_tau->Clone("h_SR_Prediction2");
        h_mX_CR_tau->Rebin(rebin);
        h_mX_CR_tau->SetLineColor(kBlack);
        h_SR_Prediction=(TH1F*)h_mX_CR_tau->Clone("h_SR_Prediction");
    } else {
        h_SR_Prediction2=(TH1F*)h_mX_SR->Clone("h_SR_Prediction2");
        h_mX_SR->Rebin(rebin);
        h_mX_SR->SetLineColor(kBlack);
        h_SR_Prediction=(TH1F*)h_mX_SR->Clone("h_SR_Prediction");
        
    }
    h_SR_Prediction->SetMarkerSize(0.7);
    h_SR_Prediction->GetYaxis()->SetTitleOffset(1.2);
    h_SR_Prediction->Sumw2();
    
    /*TFile *f_sig = new TFile((dirName+"/w_signal_"+iimass.str()+".root").c_str());
    RooWorkspace* xf_sig = (RooWorkspace*)f_sig->Get("Vg");
    RooAbsPdf *xf_sig_pdf = (RooAbsPdf *)xf_sig->pdf((std::string("signal_fixed_")+pname).c_str());
    
    RooWorkspace w_sig("w");
    w_sig.import(*xf_sig_pdf,RooFit::RenameVariable((std::string("signal_fixed_")+pname).c_str(),(std::string("signal_fixed_")+pname+std::string("low")).c_str()),RooFit::RenameAllVariablesExcept("low","x"));
    xf_sig_pdf = w_sig.pdf((std::string("signal_fixed_")+pname+std::string("low")).c_str());
   
    RooArgSet* biasVars = xf_sig_pdf->getVariables();
    TIterator *it = biasVars->createIterator();
    RooRealVar* var = (RooRealVar*)it->Next();
    while (var) {
        var->setConstant(kTRUE);
        var = (RooRealVar*)it->Next();
    }
    */
    RooRealVar x("x", "m_{X} (GeV)", SR_lo, SR_hi);
    
    RooRealVar nBackground((std::string("bg_")+pname+std::string("_norm")).c_str(),"nbkg",h_mX_SR->GetSumOfWeights());
    RooRealVar nBackground2((std::string("alt_bg_")+pname+std::string("_norm")).c_str(),"nbkg",h_mX_SR->GetSumOfWeights());
    std::string blah = pname;
    //pname=""; //Antibtag=tag to constrain b-tag to the anti-btag shape
    
    
    /* RooRealVar bg_p0((std::string("bg_p0_")+pname).c_str(), "bg_p0", 4.2, 0, 200.);
     RooRealVar bg_p1((std::string("bg_p1_")+pname).c_str(), "bg_p1", 4.5, 0, 300.);
     RooRealVar bg_p2((std::string("bg_p2_")+pname).c_str(), "bg_p2", 0.000047, 0, 10.1);
     RooGenericPdf bg_pure = RooGenericPdf((std::string("bg_pure_")+blah).c_str(),"(pow(1-@0/13000,@1)/pow(@0/13000,@2+@3*log(@0/13000)))",RooArgList(x,bg_p0,bg_p1,bg_p2));
   */
    RooRealVar bg_p0((std::string("bg_p0_")+pname).c_str(), "bg_p0", 0., -1000, 200.);
    RooRealVar bg_p1((std::string("bg_p1_")+pname).c_str(), "bg_p1", -13, -1000, 1000.);
    RooRealVar bg_p2((std::string("bg_p2_")+pname).c_str(), "bg_p2", -1.4, -1000, 1000.);
    bg_p0.setConstant(kTRUE);
    //RooGenericPdf bg_pure = RooGenericPdf((std::string("bg_pure_")+blah).c_str(),"(pow(@0/13000,@1+@2*log(@0/13000)))",RooArgList(x,bg_p1,bg_p2));
    RooGenericPdf bg = RooGenericPdf((std::string("bg_")+blah).c_str(),"(pow(@0/13000,@1+@2*log(@0/13000)))",RooArgList(x,bg_p1,bg_p2));
  

    /*TF1* biasFunc = new TF1("biasFunc","(0.63*x/1000-1.45)",1350,3600);
    TF1* biasFunc2 = new TF1("biasFunc2","TMath::Min(2.,2.3*x/1000-3.8)",1350,3600);
    double bias_term_s = 0;
    if ((imass > 2450 && blah == "antibtag") || (imass > 1640 && blah == "btag")) {
        if (blah == "antibtag") {
            bias_term_s = 2.7*biasFunc->Eval(imass);
        } else {
            bias_term_s = 2.7*biasFunc2->Eval(imass);
        }
       bias_term_s/=nEventsSR;
    }
    
    RooRealVar bias_term((std::string("bias_term_")+blah).c_str(), "bias_term", 0., -bias_term_s, bias_term_s);
    //bias_term.setConstant(kTRUE);
    RooAddPdf bg((std::string("bg_")+blah).c_str(), "bg_all", RooArgList(*xf_sig_pdf, bg_pure), bias_term);
    */
    string name_output = "CR_RooFit_Exp";
    
    std::cout<<"Nevents "<<nEventsSR<<std::endl;
    RooDataHist pred("pred", "Prediction from SB", RooArgList(x), h_SR_Prediction);
    RooFitResult *r_bg=bg.fitTo(pred, RooFit::Minimizer("Minuit2"), RooFit::Range(SR_lo, SR_hi), RooFit::SumW2Error(kTRUE), RooFit::Save());
    //RooFitResult *r_bg=bg.fitTo(pred, RooFit::Range(SR_lo, SR_hi), RooFit::Save());
    //RooFitResult *r_bg=bg.fitTo(pred, RooFit::Range(SR_lo, SR_hi), RooFit::Save(),RooFit::SumW2Error(kTRUE));
    std::cout<<" --------------------- Building Envelope --------------------- "<<std::endl;
    //std::cout<< "bg_p0_"<< pname << "   param   "<<bg_p0.getVal() <<  " "<<bg_p0.getError()<<std::endl;
    std::cout<< "bg_p1_"<< pname << "   param   "<<bg_p1.getVal() <<  " "<<100*bg_p1.getError()<<std::endl;
    std::cout<< "bg_p2_"<< pname << "   param   "<<bg_p2.getVal() <<  " "<<100*bg_p2.getError()<<std::endl;
    //std::cout<< "bias_term_"<< blah << "   param   0 "<<bias_term_s<<std::endl;
    
    RooPlot *aC_plot=x.frame();
    pred.plotOn(aC_plot, RooFit::MarkerColor(kPink+2));
    if (!plotBands) {
        bg.plotOn(aC_plot, RooFit::VisualizeError(*r_bg, 2), RooFit::FillColor(kYellow));
        bg.plotOn(aC_plot, RooFit::VisualizeError(*r_bg, 1), RooFit::FillColor(kGreen));
    }
    bg.plotOn(aC_plot, RooFit::LineColor(kBlue));
    //pred.plotOn(aC_plot, RooFit::LineColor(kBlack), RooFit::MarkerColor(kBlack));
    
    TGraph* error_curve[5]; //correct error bands
    TGraphAsymmErrors* dataGr = new TGraphAsymmErrors(h_SR_Prediction->GetNbinsX()); //data w/o 0 entries

    for (int i=2; i!=5; ++i) {
        error_curve[i] = new TGraph();
    }
    error_curve[2] = (TGraph*)aC_plot->getObject(1)->Clone("errs");
    int nPoints = error_curve[2]->GetN();
    
    error_curve[0] = new TGraph(2*nPoints);
    error_curve[1] = new TGraph(2*nPoints);
    
    error_curve[0]->SetFillStyle(1001);
    error_curve[1]->SetFillStyle(1001);
    
    error_curve[0]->SetFillColor(kGreen);
    error_curve[1]->SetFillColor(kYellow);
    
    error_curve[0]->SetLineColor(kGreen);
    error_curve[1]->SetLineColor(kYellow);
    
    if (plotBands) {
        RooDataHist pred2("pred2", "Prediction from SB", RooArgList(x), h_SR_Prediction2);

        error_curve[3]->SetFillStyle(1001);
        error_curve[4]->SetFillStyle(1001);
        
        error_curve[3]->SetFillColor(kGreen);
        error_curve[4]->SetFillColor(kYellow);
        
        error_curve[3]->SetLineColor(kGreen);
        error_curve[4]->SetLineColor(kYellow);
        
        error_curve[2]->SetLineColor(kBlue);
        error_curve[2]->SetLineWidth(3);
        
        double binSize = rebin;
        
        for (int i=0; i!=nPoints; ++i) {
            double x0,y0, x1,y1;
            error_curve[2]->GetPoint(i,x0,y0);
            
            RooAbsReal* nlim = new RooRealVar("nlim","y0",y0,-100000,100000);
            //double lowedge = x0 - (SR_hi - SR_lo)/double(2*nPoints);
            //double upedge = x0 + (SR_hi - SR_lo)/double(2*nPoints);
            
            double lowedge = x0 - binSize/2.;
            double upedge = x0 + binSize/2.;
            
            x.setRange("errRange",lowedge,upedge);
            
            RooExtendPdf* epdf = new RooExtendPdf("epdf","extpdf",bg, *nlim,"errRange");
            
            // Construct unbinned likelihood
            RooAbsReal* nll = epdf->createNLL(pred2,NumCPU(2));
            // Minimize likelihood w.r.t all parameters before making plots
            RooMinimizer* minim = new RooMinimizer(*nll);
            minim->setMinimizerType("Minuit2");
            minim->setStrategy(2);
            minim->setPrintLevel(-1);
            minim->migrad();
            
            minim->hesse();
            RooFitResult* result = minim->lastMinuitFit();
            double errm = nlim->getPropagatedError(*result);
            
            //std::cout<<x0<<" "<<lowedge<<" "<<upedge<<" "<<y0<<" "<<nlim->getVal()<<" "<<errm<<std::endl;
            
            error_curve[0]->SetPoint(i,x0,(y0-errm));
            error_curve[0]->SetPoint(2*nPoints-i-1,x0,y0+errm);
            
            error_curve[1]->SetPoint(i,x0,(y0-2*errm));
            error_curve[1]->SetPoint(2*nPoints-i-1,x0,(y0+2*errm));
            
            error_curve[3]->SetPoint(i,x0,-errm/sqrt(y0));
            error_curve[3]->SetPoint(2*nPoints-i-1,x0,errm/sqrt(y0));
            
            error_curve[4]->SetPoint(i,x0,-2*errm/sqrt(y0));
            error_curve[4]->SetPoint(2*nPoints-i-1,x0,2*errm/sqrt(y0));
            
        }
        
        int npois = 0;
        dataGr->SetMarkerSize(1.0);
        dataGr->SetMarkerStyle (20);
        
        const double alpha = 1 - 0.6827;
        
        for (int i=0; i!=h_SR_Prediction->GetNbinsX(); ++i){
            if (h_SR_Prediction->GetBinContent(i+1) > 0) {
                
                int N = h_SR_Prediction->GetBinContent(i+1);
                double L =  (N==0) ? 0  : (ROOT::Math::gamma_quantile(alpha/2,N,1.));
                double U =  ROOT::Math::gamma_quantile_c(alpha/2,N+1,1) ;
                
                dataGr->SetPoint(npois,h_SR_Prediction->GetBinCenter(i+1),h_SR_Prediction->GetBinContent(i+1));
                dataGr->SetPointEYlow(npois, N-L);
                dataGr->SetPointEYhigh(npois, U-N);
                npois++;
            }
        }
    }
    
    double xG[2] = {-10,4000};
    double yG[2] = {0.0,0.0};
    TGraph* unityG = new TGraph(2, xG, yG);
    unityG->SetLineColor(kBlue);
    unityG->SetLineWidth(1);

    double xPad = 0.3;
    TCanvas *c_rooFit=new TCanvas("c_rooFit", "c_rooFit", 800*(1.-xPad), 600);
    c_rooFit->SetFillStyle(4000);
    c_rooFit->SetFrameFillColor(0);
    
    TPad *p_1=new TPad("p_1", "p_1", 0, xPad, 1, 1);
    p_1->SetFillStyle(4000);
    p_1->SetFrameFillColor(0);
    p_1->SetBottomMargin(0.02);
    TPad* p_2 = new TPad("p_2", "p_2",0,0,1,xPad);
    p_2->SetBottomMargin((1.-xPad)/xPad*0.13);
    p_2->SetTopMargin(0.03);
    p_2->SetFillColor(0);
    p_2->SetBorderMode(0);
    p_2->SetBorderSize(2);
    p_2->SetFrameBorderMode(0);
    p_2->SetFrameBorderMode(0);
    
    p_1->Draw();
    p_2->Draw();
    p_1->cd();
    
    int nbins = (int) (SR_hi- SR_lo)/rebin;
    x.setBins(nbins);
    
    std::cout << "chi2(data) " <<  aC_plot->chiSquare()<<std::endl;
    
    //std::cout << "p-value: data     under hypothesis H0:  " << TMath::Prob(chi2_data->getVal(), nbins - 1) << std::endl;
    
    aC_plot->GetXaxis()->SetRangeUser(SR_lo, SR_hi);
    aC_plot->GetXaxis()->SetLabelOffset(0.02);
    aC_plot->GetYaxis()->SetRangeUser(0.1, 1000.);
    h_SR_Prediction->GetXaxis()->SetRangeUser(SR_lo, SR_hi);
    string rebin_ = itoa(rebin);
    
    aC_plot->GetXaxis()->SetTitle("M_{Z#gamma} [GeV] ");
    aC_plot->GetYaxis()->SetTitle(("Events / "+rebin_+" GeV ").c_str());
    aC_plot->SetMarkerSize(0.7);
    aC_plot->GetYaxis()->SetTitleOffset(1.2);
    aC_plot->Draw();
    
    if (plotBands) {
        error_curve[1]->Draw("Fsame");
        error_curve[0]->Draw("Fsame");
        error_curve[2]->Draw("Lsame");
        dataGr->Draw("p e1 same");
    }
    
    aC_plot->SetTitle("");
    TPaveText *pave = new TPaveText(0.85,0.4,0.67,0.5,"NDC");
    pave->SetBorderSize(0);
    pave->SetTextSize(0.05);
    pave->SetTextFont(42);
    pave->SetLineColor(1);
    pave->SetLineStyle(1);
    pave->SetLineWidth(2);
    pave->SetFillColor(0);
    pave->SetFillStyle(0);
    char name[1000];
    sprintf(name,"#chi^{2}/n = %.2f",aC_plot->chiSquare());
    pave->AddText(name);
    //pave->Draw();
    
    TLegend *leg = new TLegend(0.88,0.65,0.55,0.90,NULL,"brNDC");
    leg->SetBorderSize(0);
    leg->SetTextSize(0.05);
    leg->SetTextFont(42);
    leg->SetLineColor(1);
    leg->SetLineStyle(1);
    leg->SetLineWidth(2);
    leg->SetFillColor(0);
    leg->SetFillStyle(0);
    h_SR_Prediction->SetMarkerColor(kBlack);
    h_SR_Prediction->SetLineColor(kBlack);
    h_SR_Prediction->SetMarkerStyle(20);
    h_SR_Prediction->SetMarkerSize(1.0);
    //h_mMMMMa_3Tag_SR->GetXaxis()->SetTitleSize(0.09);
    if (blind)
        leg->AddEntry(h_SR_Prediction, "Data: sideband", "ep");
    else {
        if (blah == "antibtag" )
            leg->AddEntry(h_SR_Prediction, "Data: anti-b-tag SR", "ep");
        else
            leg->AddEntry(h_SR_Prediction, "Data: b-tag SR", "ep");
        
    }
    
    leg->AddEntry(error_curve[2], "Fit model", "l");
    leg->AddEntry(error_curve[0], "Fit #pm1#sigma", "f");
    leg->AddEntry(error_curve[1], "Fit #pm2#sigma", "f");
    leg->Draw();
    
    aC_plot->Draw("axis same");
    
    
    CMS_lumi( p_1, iPeriod, iPos );
    
    p_2->cd();
    RooHist* hpull;
    hpull = aC_plot->pullHist();
    RooPlot* frameP = x.frame() ;
    frameP->SetTitle("");
    frameP->GetXaxis()->SetRangeUser(SR_lo, SR_hi);
    
    frameP->addPlotable(hpull,"P");
    frameP->GetYaxis()->SetRangeUser(-7,7);
    frameP->GetYaxis()->SetNdivisions(505);
    frameP->GetYaxis()->SetTitle("#frac{(data-fit)}{#sigma_{stat}}");
    
    frameP->GetYaxis()->SetTitleSize((1.-xPad)/xPad*0.06);
    frameP->GetYaxis()->SetTitleOffset(1.0/((1.-xPad)/xPad));
    frameP->GetXaxis()->SetTitleSize((1.-xPad)/xPad*0.06);
    //frameP->GetXaxis()->SetTitleOffset(1.0);
    frameP->GetXaxis()->SetLabelSize((1.-xPad)/xPad*0.05);
    frameP->GetYaxis()->SetLabelSize((1.-xPad)/xPad*0.05);
    
    
    frameP->Draw();
    if (plotBands) {
        error_curve[4]->Draw("Fsame");
        error_curve[3]->Draw("Fsame");
        unityG->Draw("same");
        hpull->Draw("psame");
        
        frameP->Draw("axis same");
    }
    
    
    c_rooFit->SaveAs((dirName+"/"+name_output+".pdf").c_str());
    
    const int nModels = 9;
    TString models[nModels] = {
        "env_pdf_0_13TeV_dijet2", //0
        "env_pdf_0_13TeV_exp1", //1
        "env_pdf_0_13TeV_expow1", //2
        "env_pdf_0_13TeV_expow2", //3 => skip
        "env_pdf_0_13TeV_pow1", //4
        "env_pdf_0_13TeV_lau1", //5
        "env_pdf_0_13TeV_atlas1", //6
        "env_pdf_0_13TeV_atlas2", //7 => skip
        "env_pdf_0_13TeV_vvdijet1" //8
    };
    
    int nPars[nModels] = {
        2, 1, 2, 3, 1, 1, 2, 3, 2
    };
    
    TString parNames[nModels][3] = {
        "env_pdf_0_13TeV_dijet2_log1","env_pdf_0_13TeV_dijet2_log2","",
        "env_pdf_0_13TeV_exp1_p1","","",
        "env_pdf_0_13TeV_expow1_exp1","env_pdf_0_13TeV_expow1_pow1","",
        "env_pdf_0_13TeV_expow2_exp1","env_pdf_0_13TeV_expow2_pow1","env_pdf_0_13TeV_expow2_exp2",
        "env_pdf_0_13TeV_pow1_p1","","",
        "env_pdf_0_13TeV_lau1_l1","","",
        "env_pdf_0_13TeV_atlas1_coeff1","env_pdf_0_13TeV_atlas1_log1","",
        "env_pdf_0_13TeV_atlas2_coeff1","env_pdf_0_13TeV_atlas2_log1","env_pdf_0_13TeV_atlas2_log2",
        "env_pdf_0_13TeV_vvdijet1_coeff1","env_pdf_0_13TeV_vvdijet1_log1",""
    }
    
    if(bias){
        //alternative model
        gSystem->Load("libHiggsAnalysisCombinedLimit");
        gSystem->Load("libdiphotonsUtils");
        
        TFile *f = new TFile("antibtag_multipdf.root");
        RooWorkspace* xf = (RooWorkspace*)f->Get("wtemplates");
        RooWorkspace *w_alt=new RooWorkspace("Vg");
        for(int i=model_number; i<=model_number; i++){
            RooMultiPdf *alternative = (RooMultiPdf *)xf->pdf("model_bkg_AntiBtag");
            std::cout<<"Number of pdfs "<<alternative->getNumPdfs()<<std::endl;
            for (int j=0; j!=alternative->getNumPdfs(); ++j){
                std::cout<<alternative->getPdf(j)->GetName()<<std::endl;
            }
            RooAbsPdf *alt_bg = alternative->getPdf(alternative->getCurrentIndex()+i);//->clone();
            w_alt->import(*alt_bg, RooFit::RenameVariable(alt_bg->GetName(),("alt_bg_"+blah).c_str()));
            w_alt->Print("V");
            std::cerr<<w_alt->var("x")<<std::endl;
            RooRealVar * range_ = w_alt->var("x");
            range_->setRange(SR_lo,SR_hi);
            char* asd = ("alt_bg_"+blah).c_str()	;
            w_alt->import(nBackground2);
            std::cout<<alt_bg->getVal() <<std::endl;
            w_alt->pdf(asd)->fitTo(pred, RooFit::Minimizer("Minuit2"), RooFit::Range(SR_lo, SR_hi), RooFit::SumW2Error(kTRUE), RooFit::Save());

    	    RooArgSet* altVars = w_alt->pdf(asd)->getVariables();
            TIterator *it2 = altVars->createIterator();
            RooRealVar* varAlt = (RooRealVar*)it2->Next();
            while (varAlt) {
               varAlt->setConstant(kTRUE);
               varAlt = (RooRealVar*)it2->Next();
            }



            alt_bg->plotOn(aC_plot, RooFit::LineColor(i+1), RooFit::LineStyle(i+2));
            p_1->cd();
            aC_plot->GetYaxis()->SetRangeUser(0.01, maxdata*50.);
            aC_plot->Draw("same");
            TH1F *h=new TH1F();
            h->SetLineColor(1+i);
            h->SetLineStyle(i+2);
            leg->AddEntry(h, alt_bg->GetName(), "l");
            
            
            w_alt->SaveAs((dirName+"/w_background_alternative.root").c_str());
        }
        leg->Draw();
        p_1->SetLogy();
        c_rooFit->Update();
        c_rooFit->SaveAs((dirName+"/"+name_output+blah+"_multipdf.pdf").c_str());
        
        for (int i=0; i!=nPars[model_number]; ++i) {
            std::cout<<parNames[model_number][i]<<" param "<< w_alt->var(parNames[model_number][i])->getVal()<<"   "<<w_alt->var(parNames[model_number][i])->getError()<<std::endl;
        }
        
        
    } else {
        p_1->SetLogy();
        c_rooFit->Update();
        c_rooFit->SaveAs((dirName+"/"+name_output+"_log.pdf").c_str());
    }
    
    RooWorkspace *w=new RooWorkspace("Vg");
    w->import(bg);
    w->import(nBackground);
    w->SaveAs((dirName+"/w_background_GaussExp.root").c_str());
    
    TH1F *h_mX_SR_fakeData=(TH1F*)h_mX_SR->Clone("h_mX_SR_fakeData");
    h_mX_SR_fakeData->Scale(nEventsSR/h_mX_SR_fakeData->GetSumOfWeights());
    RooDataHist data_obs("data_obs", "Data", RooArgList(x), h_mX_SR_fakeData);
    std::cout<<" Background number of events = "<<nEventsSR<<std::endl;
    RooWorkspace *w_data=new RooWorkspace("Vg");
    w_data->import(data_obs);
    w_data->SaveAs((dirName+"/w_data.root").c_str());
    
}
Example #2
0
void buildModel(RooWorkspace& w,int chooseFitParams, int chooseSample,int whatBin, int signalModel, int bkgdModel, int doRap, int doPt,int doCent,int useRef,float muonPtMin, int fixFSR){
// C r e a t e   m o d e l  
  int nt=100000;
  // cout << "you're building a model for the quarkonium resonance of mass = "<< M1S <<" GeV/c^{2},"endl;
  RooRealVar *nsig1f   = new RooRealVar("N_{ #varUpsilon(1S)}","nsig1S",0,nt*10);
  RooRealVar* mass       = new RooRealVar("invariantMass","#mu#mu mass",mass_l,mass_h,"GeV/c^{2}");

  RooRealVar *nsig2f = NULL;
  RooRealVar *nsig3f = NULL;

 switch (chooseFitParams)
    {
    case 0://use the YIELDs of 2S and 3S as free parameters
      //minor modif here: 3S forced positive.
      nsig2f  = new RooRealVar("N_{ #varUpsilon(2S)}","nsig2S",   nt*0.25,-200,10*nt);
      nsig3f  = new RooRealVar("N_{ #varUpsilon(3S)}","nsig3S",   nt*0.25,-200,10*nt);
      cout << "you're fitting to extract yields, "<< endl;
      break;
    default:
      cout<<"Make a pick from chooseFitParams!!!"<<endl;
      break;
    }  

      RooRealVar  *mean = new RooRealVar("m_{ #varUpsilon(1S)}","#Upsilon mean",M1S,M1S-0.2,M1S+0.2);
      RooConstVar *rat2 = new RooConstVar("rat2", "rat2", M2S/M1S);
      RooConstVar *rat3 = new RooConstVar("rat3", "rat3", M3S/M1S);
      // scale mean and resolution by mass ratio
      RooFormulaVar *mean1S = new RooFormulaVar("mean1S","@0",RooArgList(*mean));
      RooFormulaVar *mean2S = new RooFormulaVar("mean2S","@0*@1", RooArgList(*mean,*rat2));
      RooFormulaVar *mean3S = new RooFormulaVar("mean3S","@0*@1", RooArgList(*mean,*rat3));

      // //detector resolution ?? where is this coming from?
      RooRealVar    *sigma1  = new RooRealVar("#sigma_{CB1}","#sigma_{CB1}",sigma_min[whatBin],sigma_max[whatBin]); // 
      RooFormulaVar *sigma1S = new RooFormulaVar("sigma1S","@0"   ,RooArgList(*sigma1));
      RooFormulaVar *sigma2S = new RooFormulaVar("sigma2S","@0*@1",RooArgList(*sigma1,*rat2));
      RooFormulaVar *sigma3S = new RooFormulaVar("sigma3S","@0*@1",RooArgList(*sigma1,*rat3));
      RooRealVar *alpha  = new RooRealVar("#alpha_{CB}","tail shift",alpha_min[whatBin],alpha_max[whatBin]);    // MC 5tev 1S pol2 
      RooRealVar *npow   = new RooRealVar("n_{CB}","power order",npow_min[whatBin],npow_max[whatBin]);    // MC 5tev 1S pol2 
      RooRealVar *sigmaFraction = new RooRealVar("sigmaFraction","Sigma Fraction",0.,1.);
      // scale the sigmaGaus with sigma1S*scale=sigmaGaus now.
      RooRealVar    *scaleWidth = new RooRealVar("#sigma_{CB2}/#sigma_{CB1}","scaleWidth",1.,2.5);
      RooFormulaVar *sigmaGaus = new RooFormulaVar("sigmaGaus","@0*@1", RooArgList(*sigma1,*scaleWidth));
      RooFormulaVar *sigmaGaus2 = new RooFormulaVar("sigmaGaus","@0*@1*@2", RooArgList(*sigma1,*scaleWidth,*rat2));
      RooFormulaVar *sigmaGaus3 = new RooFormulaVar("sigmaGaus","@0*@1*@2", RooArgList(*sigma1,*scaleWidth,*rat3));
      RooGaussian* gauss1 = new RooGaussian("gaus1s","gaus1s",
      					    *nsig1f,
      					    *mass,    //mean
      					    *sigmaGaus); //sigma
      // RooGaussian* gauss1b = new RooGaussian("gaus1sb","gaus1sb",
      // 					     *nsig1f,
      // 					     *m,    //mean
      // 					     *sigma1); //sigma
      switch(signalModel){    
      case 1: //crystal boule
	RooCBShape  *sig1S   = new RooCBShape ("cb1S_1", "FSR cb 1s",
					       *mass,*mean1S,*sigma1,*alpha,*npow);

	RooCBShape  *sig2S   = new RooCBShape ("cb2S_1", "FSR cb 1s",
					       *mass,*mean2S,*sigma2S,*alpha,*npow);
	RooCBShape  *sig3S   = new RooCBShape ("cb3S_1", "FSR cb 1s",
					       *mass,*mean3S,*sigma3S,*alpha,*npow);
	cout << "you're fitting each signal peak with a Crystal Ball function"<< endl;
	break;
      case 2: //Gaussein
	RooAbsPdf      *sig1S  = new RooGaussian ("g1", "gaus 1s",
						  *mass,*mean1S,*sigma1);
	cout << "you're fitting 1 signal peak with a Gaussian function"<< endl;
	break;
      case 3: //Gaussein + crystal boule
	RooCBShape  *cb1S_1    = new RooCBShape ("cb1S_1", "FSR cb 1s",
						 *mass,*mean1S,*sigma1,*alpha,*npow);
	RooAddPdf      *sig1S  = new RooAddPdf ("cbg", "cbgaus 1s",
						RooArgList(*gauss1,*cb1S_1),*sigmaFraction);
	cout << "you're fitting 1 signal peak with a sum of a Gaussian and a Crystal Ball function"<< endl;
	break;
      case 4: //crystal boules
	RooCBShape  *cb1S_1    = new RooCBShape ("cb1S_1", "FSR cb 1s",
						 *mass,*mean1S,*sigma1,*alpha,*npow);
       
	RooCBShape  *cb1S_2    = new RooCBShape ("cb1S_2", "FSR cb 1s",
						 *mass,*mean1S,*sigmaGaus,*alpha,*npow);
	RooAddPdf      *sig1S  = new RooAddPdf  ("cbcb","1S mass pdf",
						 RooArgList(*cb1S_1,*cb1S_2),*sigmaFraction);
	// /// Upsilon 2S
	RooCBShape  *cb2S_1    = new RooCBShape ("cb2S_1", "FSR cb 2s", 
						 *mass,*mean2S,*sigma2S,*alpha,*npow); 
	RooCBShape  *cb2S_2    = new RooCBShape ("cb2S_2", "FSR cb 2s", 
						 *mass,*mean2S,*sigmaGaus2,*alpha,*npow); 
	RooAddPdf      *sig2S  = new RooAddPdf  ("sig2S","2S mass pdf",
						 RooArgList(*cb2S_1,*cb2S_2),*sigmaFraction);
      
	// /// Upsilon 3S
	RooCBShape  *cb3S_1    = new RooCBShape ("cb3S_1", "FSR cb 3s", 
						 *mass,*mean3S,*sigma3S,*alpha,*npow); 
	RooCBShape  *cb3S_2    = new RooCBShape ("cb3S_2", "FSR cb 3s", 
						 *mass,*mean3S,*sigmaGaus3,*alpha,*npow); 
	RooAddPdf      *sig3S  = new RooAddPdf  ("sig3S","3S mass pdf",
						 RooArgList(*cb3S_1,*cb3S_2),*sigmaFraction); // = cb3S1*sigmaFrac + cb3S2*(1-sigmaFrac)
	cout << "you're fitting each signal peak with a Double Crystal Ball function"<< endl;
	break;
      
      case 5: //deux Gausseins
	RooAddPdf      *sig1S  = new RooAddPdf ("cb1S_1", "cbgaus 1s",
						RooArgList(*gauss1,*gauss1b),*sigmaFraction);
	cout << "you're fitting each signal peak with a Double Gaussian function"<< endl;
	break;
      }
      // bkg Chebychev
      RooRealVar *nbkgd   = new RooRealVar("n_{Bkgd}","nbkgd",0,nt);
      RooRealVar *bkg_a1  = new RooRealVar("a1_bkg", "bkg_{a1}", 0, -5, 5);
      RooRealVar *bkg_a2  = new RooRealVar("a2_Bkg", "bkg_{a2}", 0, -2, 2);
      RooRealVar *bkg_a3  = new RooRealVar("a3_Bkg", "bkg_{a3}", 0, -0.9, 2);

      //  likesign
      RooRealVar *nLikesignbkgd = new RooRealVar("NLikesignBkg","nlikesignbkgd",nt*0.75,0,10*nt);
      // *************************************************** bkgModel
      
      RooRealVar turnOn("turnOn","turnOn", turnOn_minCent[whatBin],turnOn_maxCent[whatBin]);
      RooRealVar width("width","width",width_minCent[whatBin],width_maxCent[whatBin]);// MB 2.63
      RooRealVar decay("decay","decay",decay_minCent[whatBin],decay_maxCent[whatBin]);// MB: 3.39
      if (doRap && !doPt)
	{
	  RooRealVar turnOn("turnOn","turnOn", turnOn_minRap[whatBin],turnOn_maxRap[whatBin]);
	  RooRealVar width("width","width",width_minRap[whatBin],width_maxRap[whatBin]);// MB 2.63
	  RooRealVar decay("decay","decay",decay_minRap[whatBin],decay_maxRap[whatBin]);// MB: 3.39
	}
      if (doPt && !doRap)
	{
	  RooRealVar turnOn("turnOn","turnOn", turnOn_minPt[whatBin],turnOn_maxPt[whatBin]);
	  RooRealVar width("width","width",width_minPt[whatBin],width_maxPt[whatBin]);// MB 2.63
	  RooRealVar decay("decay","decay",decay_minPt[whatBin],decay_maxPt[whatBin]);// MB: 3.39
	}
      
  
      width.setConstant(false);
      decay.setConstant(false);
      turnOn.setConstant(false);
 
  switch (useRef)// no reference
    {
    case 0: // forcing sigma and fsr to be left free.
      fixSigma1 = 0;
      fixFSR    = 0;
      break;
    case 1:
      //using data-driven estimates
      int dataRef=1;
      cout<<"You're using the debug mode based on data parameters. So you must not take this result as the central one."<<endl;
      break;
    case 2:
      
      cout << "doCent="<<doCent << endl;
      //using MC-driven estimates
      int dataRef=2;
      if(doCent)   //MB values, assumed to be the same with all centralities...
     	{
	  if(muonPtMin <4){
	    gROOT->LoadMacro("dataTable_loose.h");
	  }else if(muonPtMin > 3.5){
	    gROOT->LoadMacro("dataTable_tight.h");
	  }
	  npow->setVal(npow_rapBins[8]);
	  alpha->setVal(alpha_rapBins[8]);
	  sigma1->setVal(sigma1_rapBins[8]);
	  scaleWidth->setVal(scale_rapBins[8]);
	  sigmaFraction->setVal(pdFrac_rapBins[8]);
	  cout<< whatBin << endl;
	}
      if(doRap && !doPt)
	{
	  if(muonPtMin <4){
	    gROOT->LoadMacro("dataTable_loose.h");
	  }else if(muonPtMin > 3.5){
	    gROOT->LoadMacro("dataTable_tight.h");
	  }
	  npow->setVal(npow_rapBins[whatBin]);
	  alpha->setVal(alpha_rapBins[whatBin]);
	  sigma1->setVal(sigma1_rapBins[whatBin]);
	  scaleWidth->setVal(scale_rapBins[whatBin]);
	  sigmaFraction->setVal(pdFrac_rapBins[whatBin]);
	  cout<< whatBin << endl;
	}
      if(doPt && !doRap)
	{
	  // cout << "we're here" << endl;
	  if(muonPtMin <4){
	    gROOT->LoadMacro("dataTable_loose.h");
	  }else if(muonPtMin > 3.5){
	    gROOT->LoadMacro("dataTable_tight.h");
	  }
	  cout << " ok ... " <<endl;
	  npow->setVal(npow_ptBins[whatBin]);
	  alpha->setVal(alpha_ptBins[whatBin]);
	  sigma1->setVal(sigma1_ptBins[whatBin]);
	  scaleWidth->setVal(scale_ptBins[whatBin]);
	  sigmaFraction->setVal(pdFrac_ptBins[whatBin]);
	}
     
      cout<<"You're using MC parameters. So you may use this result as the central one, according to the LLR test outcome."<<endl;
      break;
    default: break;
    }

  //
  cout << "npow tried=" << npow->getVal(); 
  if(fixFSR==3 || fixFSR==1) cout << "   constant!" << endl;   else cout << "   floating!" << endl;
  cout << "alpha tried=" << alpha->getVal(); 
  if(fixFSR==2 || fixFSR==1) cout << "   constant!" << endl;   else cout << "   floating!" << endl;
  cout << "sigma1 tried=" << sigma1->getVal(); 
  if(fixFSR==4 || fixFSR==1) cout << "   constant!" << endl;   else cout << "   floating!" << endl;
  cout << "scale tried=" << scaleWidth->getVal(); 
  if(fixFSR==4 || fixFSR==1) cout << "   constant!" << endl;   else cout << "   floating!" << endl;
  cout << "normalisation tried=" << sigmaFraction->getVal();
  if(fixFSR==5 || fixFSR==1) cout << "   constant!" << endl;   else cout << "   floating!" << endl;
  
  switch (fixFSR) // 0: free;  1: both fixed 2: alpha fixed 3: npow fixed
    {      
    case 0:// all free
      alpha->setConstant(false);
      npow->setConstant(false);
      sigma1->setConstant(false);
      scaleWidth->setConstant(false);
      sigmaFraction->setConstant(false);
      break;
    case 1:// all fixed
      alpha->setConstant(true);
      npow ->setConstant(true);
      sigma1->setConstant(true);
      scaleWidth->setConstant(true);
      sigmaFraction->setConstant(true);
      break;
    case 2: // release alpha
      alpha->setConstant(false);
      npow ->setConstant(true);
      sigma1->setConstant(true);
      scaleWidth->setConstant(true);
      sigmaFraction->setConstant(true);
      break;
    case 3:// npow released
      alpha->setConstant(true);
      npow->setConstant(false);
      sigma1->setConstant(true);
      scaleWidth->setConstant(true);
      sigmaFraction->setConstant(true);
      break;
    case 4:// width+ sF +scale released
      alpha->setConstant(true);
      npow->setConstant(true);
      sigma1->setConstant(false);
      scaleWidth->setConstant(true);
      sigmaFraction->setConstant(true);
      break;
    case 5:// scale +sF
      alpha->setConstant(true);
      npow->setConstant(true);
      sigma1->setConstant(true);
      scaleWidth->setConstant(false);
      sigmaFraction->setConstant(true);
      break;
   case 6:// scale +sF
      alpha->setConstant(true);
      npow->setConstant(true);
      sigma1->setConstant(true);
      scaleWidth->setConstant(true);
      sigmaFraction->setConstant(false);
      break;
    default:
      cout<<"Donno this choice! Pick somehting for FSR parameters that I know"<<endl;
      break;
    }
   //thisPdf: form of the bkg pdf
  //pdf_combinedbkgd; // total bkg pdf. usually form*normalization  (so that you can do extended ML fits)
  switch (bkgdModel) 
    {
    case 1 :  //(erf*exp ) to fit the SS, then fix the shape and fit OS, in case of constrain option
      bkg_a3->setConstant(true);
      RooGenericPdf *ErrPdf = new  RooGenericPdf("ErrPdf","ErrPdf",
						 "exp(-@0/decay)*(TMath::Erf((@0-turnOn)/width)+1)",
					       RooArgList(*mass,turnOn,width,decay));
      RooFitResult* fit_1st  = ErrPdf->fitTo(*likesignData,Save(),NumCPU(4)) ; // likesign data
      if (doTrkRot) fit_1st  = thisPdf->fitTo(*TrkRotData,Save(),NumCPU(4)) ;
      
      if (doConstrainFit) 
	{ // allow parameters to vary within cenral value from above fit + their sigma
	  turnOn_constr = new RooGaussian("turnOn_constr","turnOn_constr",
					  turnOn,
					  RooConst(turnOn.getVal()),
					  RooConst(turnOn.getError()));
	  width_constr   = new RooGaussian("width_constr","width_constr",
					   width,					   RooConst(width.getVal()),
					   RooConst(width.getError()));
	  decay_constr    = new RooGaussian("decay_constr","decay_constr",
					    decay,
					    RooConst(decay.getVal()),
					    RooConst(decay.getError()));
	}
      else 
	{
	  turnOn.setConstant(kTRUE);
	  width.setConstant(kTRUE);
	  decay.setConstant(kTRUE);
	}
      RooRealVar *fLS =new RooRealVar("R_{SS/OS}","Empiric LS/SS ratio",0.,1.);
      RooAbsPdf  *ChebPdf  = new RooChebychev("ChebPdf","ChebPdf",
					      *mass, RooArgList(*bkg_a1,*bkg_a2));
      RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("bkgPdf","total combined background pdf",
						      RooArgList(*ErrPdf,*ChebPdf),
						      RooArgList(*fLS));
      
      break;
    case 2 : //us eRooKeysPdf to smooth the SS, then fit OS with pol+keys
      bkg_a3->setConstant(true);
      RooRealVar *fLS =new RooRealVar("R_{SS/OS}","Empiric LS/SS ratio",0.,1.);
      RooKeysPdf *KeysPdf        = new RooKeysPdf("KeysPdf","KeysPdf",*mass,*likesignData,
						  RooKeysPdf::MirrorBoth, 1.4);
      RooAbsPdf  *ChebPdf  = new RooChebychev("ChebPdf","ChebPdf",
					      *mass, RooArgList(*bkg_a1,*bkg_a2));
      if (doTrkRot) thisPdf     = new RooKeysPdf("thisPdf","thisPdf",*mass,*TrkRotData,
						 RooKeysPdf::MirrorBoth, 1.4);
      RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("bkgPdf","total combined background pdf",
						      RooArgList(*KeysPdf,*ChebPdf),
						      RooArgList(*fLS));
      break;
    case 3 : //use error function to fit the OS directly
      bkg_a3->setConstant(true);
      RooAbsPdf *pdf_combinedbkgd            = new  RooGenericPdf("bkgPdf","bkgPdf",
								  "exp(-@0/decay)*(TMath::Erf((@0-turnOn)/width)+1)",
								  RooArgList(*mass,turnOn,width,decay));
      break;
      
    case 4 : //use pol 2+ErfExp to fit the OS directly

      RooRealVar *fPol   = new RooRealVar("F_{pol}","fraction of polynomial distribution",0.0,1);
      RooAbsPdf  *ChebPdf  = new RooChebychev("ChebPdf","ChebPdf",
					      *mass, RooArgList(*bkg_a1,*bkg_a2));
      RooGenericPdf *ErrPdf     = new  RooGenericPdf("ErrPdf","ErrPdf",
						     "exp(-@0/decay)*(TMath::Erf((@0-turnOn)/width)+1)",
						     RooArgList(*mass,turnOn,width,decay));
      RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("bkgPdf","total combined background pdf",
						      RooArgList(*ChebPdf,*ErrPdf),
						      RooArgList(*fPol));

      break;
    case 5 : //use ( error function + polynomial 1) to fit the OS directly
      
      bkg_a3->setConstant(true);
      bkg_a2->setConstant(true);
      RooRealVar *fPol   = new RooRealVar("F_{pol}","fraction of polynomial distribution",0.0,1);
      RooAbsPdf  *ChebPdf  = new RooChebychev("ChebPdf","ChebPdf",
					      *mass, RooArgList(*bkg_a1,*bkg_a2,*bkg_a3));
      RooGenericPdf *ErrPdf     = new  RooGenericPdf("ErrPdf","ErrPdf",
						     "exp(-@0/decay)*(TMath::Erf((@0-turnOn)/width)+1)",
						   RooArgList(*mass,turnOn,width,decay));
      RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("bkgPdf","total combined background pdf",
						      RooArgList(*ChebPdf,*ErrPdf),
						      RooArgList(*fPol));
      break;
    case 6: // NOT WORKING
      RooRealVar *fPol   = new RooRealVar("F_{pol}","fraction of polynomial distribution",0.0,1);
      RooAbsPdf  *ChebPdf  = new RooChebychev("ChebPdf","ChebPdf",
					      *mass, RooArgList(*bkg_a1,*bkg_a2));
      RooGenericPdf *ExpPdf     = new  RooGenericPdf("ExpPdf","ExpPdf",
						     "exp(-@0/decay)",
						     RooArgList(*mass,decay));
      RooAbsPdf  *pdf_combinedbkgd  =  new RooAddPdf ("bkgPdf","total combined background pdf",
						      RooArgList(*ChebPdf,*ExpPdf),
						      RooArgList(*fPol));
      break;
    default :
      cout<<"Donno what you are talking about! Pick another fit option!"<<endl;
      break;
    }
  
  //###### the nominal fit with default pdf 
 
  // RooAbsPdf  *pdf; // nominal PDF
  if(chooseSample==8)
   {     
     // bkg_a1->setVal(0);// can be turned on at convenience
     // bkg_a1->setConstant();
     // bkg_a2->setVal(0);
     // bkg_a2->setConstant();
     // bkg_a3->setVal(0);
     // bkg_a3->setConstant();
     // RooAbsPdf  *pdf             = new RooAddPdf ("pdf","total p.d.f.",
     // 						  RooArgList(*sig1S,*pdf_combinedbkgd),
     // 						  RooArgList(*nsig1f,*nbkgd));
        RooAbsPdf  *pdf             = new RooAddPdf ("pdf","total p.d.f.",*sig1S,*nsig1f);
   } else if(chooseSample!=8)
    {
      // can remove the double crystal ball in pbpb: just commenting out and copying an appropriate version
      RooAbsPdf  *pdf             = new RooAddPdf ("pdf","total p.d.f.",
						   RooArgList(*sig1S,*sig2S,*sig3S,*pdf_combinedbkgd),
						   RooArgList(*nsig1f,*nsig2f,*nsig3f,*nbkgd));
      //  nsig3f->setVal(0); nsig3f->setConstant();
      
    }
  w.import(*pdf);
  w.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;
}
Example #4
0
	void fitpeaks(int bin){
		switch (bin)
		{
			case 0:
				cut_="abs(upsRapidity)<2.4";
				//cut_="( (muPlusPt>3.5 && abs(muPlusEta)<1.6) || (muPlusPt>2.5 && abs(muPlusEta)>=1.6 && abs(muPlusEta)<2.4) ) && ( (muMinusPt>3.5 && abs(muMinusEta)<1.6) || (muMinusPt>2.5 && abs(muMinusEta)>=1.6 && abs(muMinusEta)<2.4) ) && abs(upsRapidity)<2.0";   //pp acceptance for Upsilon 
				suffix_="";
				f2Svs1S_pp->setVal(0.5569);
				//f2Svs1S_pp->setVal(0);
				f3Svs1S_pp->setVal(0.4140);
				//f3Svs1S_pp->setVal(0);
				break;
			case 1:
				cut_="abs(upsRapidity)>=0.0 && abs(upsRapidity)<1.2";
				suffix_="_eta0-12"; binw_=0.14;
				break;
			case 2:
				cut_="abs(upsRapidity)>=1.2 && abs(upsRapidity)<2.4";
				suffix_="_eta12-24"; binw_=0.14;
				break;
			case 3:
				cut_="Centrality>=0 && Centrality<2";
				suffix_="_cntr0-5"; binw_=0.14;
				break;
			case 4:
				cut_="Centrality>=2 && Centrality<4";
				suffix_="_cntr5-10"; binw_=0.14;
				break;
			case 5:
				cut_="Centrality>=4 && Centrality<8";
				suffix_="_cntr10-20"; binw_=0.14;
				break;
			case 6:
				cut_="Centrality>=8 && Centrality<12";
				suffix_="_cntr20-30"; binw_=0.14;
				break;
			case 7:
				cut_="Centrality>=12 && Centrality<16";
				suffix_="_cntr30-40"; binw_=0.14;
				break;
			case 8:
				cut_="Centrality>=16 && Centrality<20";
				suffix_="_cntr40-50"; binw_=0.14;
				break;
			case 9:
				cut_="Centrality>=20 && Centrality<50";
				suffix_="_cntr50-100"; binw_=0.14;
				break;
			case 10:
				cut_="Centrality>=20 && Centrality<24";
				suffix_="_cntr50-60"; binw_=0.14;
				break;
			case 11:
				cut_="Centrality>=0 && Centrality<8";
				suffix_="_cntr0-20"; binw_=0.1;
				break;
			case 12:
				cut_="Centrality>=16 && Centrality<50";
				suffix_="_cntr40-100"; binw_=0.14;
				break;
			case 13:
				cut_="Centrality>=8 && Centrality<50";
				suffix_="_cntr20-100"; binw_=0.1;
				break;
			default:
				cout<<"error in binning"<<endl;
				break;
		}

		cout << "oniafitter processing"
			<< "\n\tInput:  \t" << finput
			<< "\n\tresults:\t" << figs_
			<< endl;
		ofstream outfile("fitresults.out", ios_base::app);
		outfile<<endl<<"**********"<<suffix_<<"**********"<<endl<<endl;

		//read the data
		TFile f(finput,"read");
		gDirectory->Cd(finput+":/"+dirname_);
		TTree* theTree     = (TTree*)gROOT->FindObject("UpsilonTree");
		TTree* allsignTree     = (TTree*)gROOT->FindObject("UpsilonTree_allsign");
		if (PR_plot) {TRKROT = 1; PbPb=1;}
		if (TRKROT) TTree* trkRotTree = (TTree*)gROOT->FindObject("UpsilonTree_trkRot");

		RooRealVar* mass  = new RooRealVar("invariantMass","#mu#mu mass",mmin_,mmax_,"GeV/c^{2}");
		RooRealVar* upsPt  = new RooRealVar("upsPt","p_{T}(#Upsilon)",0,60,"GeV");
		RooRealVar* upsEta = new RooRealVar("upsEta",  "upsEta"  ,-7,7);
		RooRealVar* upsRapidity = new RooRealVar("upsRapidity",  "upsRapidity"  ,-2.4,2.4);
		RooRealVar* vProb = new RooRealVar("vProb",  "vProb"  ,0.05,1.00);
		RooRealVar* QQsign = new RooRealVar("QQsign",  "QQsign"  ,-1,5);
		RooRealVar* weight = new RooRealVar("weight",  "weight"  ,-2,2);
		if (PbPb) RooRealVar* Centrality = new RooRealVar("Centrality",  "Centrality"  ,0,40);
		RooRealVar* muPlusPt = new RooRealVar("muPlusPt","muPlusPt",muonpTcut,50);
		RooRealVar* muPlusEta = new RooRealVar("muPlusEta","muPlusEta",-2.5,2.5);
		RooRealVar* muMinusPt = new RooRealVar("muMinusPt","muMinusPt",muonpTcut,50);
		RooRealVar* muMinusEta = new RooRealVar("muMinusEta","muMinusEta",-2.5,2.5);


		//import unlike-sign data set
		RooDataSet* data0, *data, *likesignData0, *likesignData, *TrkRotData0, *TrkRotData;
		if (PbPb) data0 = new RooDataSet("data","data",theTree,RooArgSet(*mass,*upsRapidity,*vProb,*upsPt,*Centrality,*muPlusPt,*muMinusPt));
		//data0 = new RooDataSet("data","data",theTree,RooArgSet(*mass,*upsRapidity,*upsPt,*muPlusPt,*muMinusPt,*QQsign,*weight));
		else data0 = new RooDataSet("data","data",theTree,RooArgSet(*mass,*upsRapidity,*vProb,*upsPt,*muPlusPt,*muMinusPt,*muPlusEta,*muMinusEta));
		data0->Print();
		data = ( RooDataSet*) data0->reduce(Cut(cut_));
		data->Print();

		//import like-sign data set
		if (PbPb) likesignData0 = new RooDataSet("likesignData","likesignData",allsignTree,RooArgSet(*mass,*upsRapidity,*vProb,*upsPt,*Centrality,*muPlusPt,*muMinusPt,*QQsign));
		else likesignData0 = new RooDataSet("likesignData","likesignData",allsignTree,RooArgSet(*mass,*upsRapidity,*vProb,*upsPt,*muPlusPt,*muMinusPt,*QQsign));
		likesignData0->Print();
		likesignData = ( RooDataSet*) likesignData0->reduce(Cut(cut_+" && QQsign != 0"));
		likesignData->Print();


		//import track-rotation data set
		if (TRKROT) {
			if (PbPb) TrkRotData0 = new RooDataSet("TrkRotData","TrkRotData",trkRotTree,RooArgSet(*mass,*upsRapidity,*vProb,*upsPt,*Centrality,*muPlusPt,*muMinusPt,*QQsign));
			else TrkRotData0 = new RooDataSet("TrkRotData","TrkRotData",trkRotTree,RooArgSet(*mass,*upsRapidity,*upsPt,*vProb,*muPlusPt,*muMinusPt,*QQsign));
			TrkRotData0->Print();
			if (PR_plot && RAA) TrkRotData = ( RooDataSet*) TrkRotData0->reduce(Cut(cut_+" && upsPt < 8.1"));
			else if (PR_plot && !RAA) TrkRotData = ( RooDataSet*) TrkRotData0->reduce(Cut(cut_+" && upsPt < 7.07"));
			else TrkRotData = ( RooDataSet*) TrkRotData0->reduce(Cut(cut_+" && QQsign != 0"));
			TrkRotData->Print();
		}

		mass->setRange("R1",7.0,10.2);
		mass->setRange("R2",7,14);
		mass->setRange("R3",10.8,14);
		const double M1S = 9.46;   //upsilon 1S pgd mass value
		const double M2S = 10.02;  //upsilon 2S pgd mass value
		const double M3S = 10.35;  //upsilon 3S pgd mass value

		RooRealVar *mean    = new RooRealVar("#mu_{#Upsilon(1S)}","#Upsilon mean",M1S,M1S-0.1,M1S+0.1);
		RooRealVar *shift21 = new RooRealVar("shift2","mass diff #Upsilon(1,2S)",M2S-M1S);
		RooRealVar *shift31 = new RooRealVar("shift3","mass diff #Upsilon(1,3S)",M3S-M1S);
		RooRealVar *mscale  = new RooRealVar("mscale","mass scale factor",1.,0.7,1.3);
		mscale->setConstant(kTRUE); /* the def. parameter value is fixed in the fit */
		RooFormulaVar *mean1S = new RooFormulaVar("mean1S","@0",
				RooArgList(*mean));
		RooFormulaVar *mean2S = new RooFormulaVar("mean2S","@0+@1*@2",
				RooArgList(*mean,*mscale,*shift21));
		RooFormulaVar *mean3S = new RooFormulaVar("mean3S","@0+@1*@2",
				RooArgList(*mean,*mscale,*shift31));

		RooRealVar *sigma1 = new RooRealVar("sigma","Sigma_1",0.10,0.01,0.30);    //detector resolution
		RooRealVar *sigma2 = new RooRealVar("#sigma_{#Upsilon(1S)}","Sigma_1S",0.08,0.01,0.30); //Y(1S) resolution
		RooFormulaVar *reso1S = new RooFormulaVar("reso1S","@0"             ,RooArgList(*sigma2));
		RooFormulaVar *reso2S = new RooFormulaVar("reso2S","@0*10.023/9.460",RooArgList(*sigma2));
		RooFormulaVar *reso3S = new RooFormulaVar("reso3S","@0*10.355/9.460",RooArgList(*sigma2));

		/// to describe final state radiation tail on the left of the peaks
		RooRealVar *alpha  = new RooRealVar("alpha","tail shift",0.982,0,2.4);   // minbias fit value
		//RooRealVar *alpha  = new RooRealVar("alpha","tail shift",1.6,0.2,4);   // MC value
		RooRealVar *npow   = new RooRealVar("npow","power order",2.3,1,3);       // MC value
		npow ->setConstant(kTRUE);
		if (!fitMB) alpha->setConstant(kTRUE);
		// relative fraction of the two peak components 
		RooRealVar *sigmaFraction = new RooRealVar("sigmaFraction","Sigma Fraction",0.3,0.,1.);
		sigmaFraction->setVal(0);
		sigmaFraction->setConstant(kTRUE);

		/// Upsilon 1S
		//RooCBShape  *gauss1S1 = new RooCBShape ("gauss1S1", "FSR cb 1s",
		//                  *mass,*mean1S,*sigma1,*alpha,*npow);
		RooCBShape  *gauss1S2 = new RooCBShape ("gauss1S2", "FSR cb 1s",
				*mass,*mean1S,*reso1S,*alpha,*npow);
		//RooAddPdf *sig1S      = new RooAddPdf  ("sig1S","1S mass pdf",
		//                  RooArgList(*gauss1S1,*gauss1S2),*sigmaFraction);

		//mean->setVal(9.46);
		//mean->setConstant(kTRUE);
		sigma1->setVal(0);
		sigma1->setConstant(kTRUE);
		if (!fitMB) {
			sigma2->setVal(width_);        //fix the resolution
			sigma2->setConstant(kTRUE);
		}
		/// Upsilon 2S
		RooCBShape  *gauss2S1 = new RooCBShape ("gauss2S1", "FSR cb 2s", 
				*mass,*mean2S,*sigma1,*alpha,*npow); 
		RooCBShape  *gauss2S2 = new RooCBShape ("gauss2S2", "FSR cb 2s", 
				*mass,*mean2S,*reso2S,*alpha,*npow); 
		RooAddPdf *sig2S      = new RooAddPdf  ("sig2S","2S mass pdf",
				RooArgList(*gauss2S1,*gauss2S2),*sigmaFraction);

		/// Upsilon 3S
		RooCBShape  *gauss3S1 = new RooCBShape ("gauss3S1", "FSR cb 3s", 
				*mass,*mean3S,*sigma1,*alpha,*npow); 
		RooCBShape  *gauss3S2 = new RooCBShape ("gauss3S2", "FSR cb 3s", 
				*mass,*mean3S,*reso3S,*alpha,*npow); 
		RooAddPdf *sig3S      = new RooAddPdf  ("sig3S","3S mass pdf",
				RooArgList(*gauss3S1,*gauss3S2),*sigmaFraction);

		/// Background
		RooRealVar *bkg_a1  = new RooRealVar("bkg_{a1}", "background a1", 0, -2, 2);
		RooRealVar *bkg_a2  = new RooRealVar("bkg_{a2}", "background a2", 0, -1, 1);
		//RooRealVar *bkg_a3  = new RooRealVar("bkg_{a3}", "background a3", 0, -1, 1);
		RooAbsPdf  *bkgPdf  = new RooChebychev("bkg","background",
				*mass, RooArgList(*bkg_a1,*bkg_a2));
		//bkg_a1->setVal(0);
		//bkg_a1->setConstant(kTRUE);
		//bkg_a2->setVal(0);
		//bkg_a2->setConstant(kTRUE); //set constant for liner background

		// only sideband region pdf, using RooPolynomial instead of RooChebychev for multiple ranges fit
		RooRealVar *SB_bkg_a1  = new RooRealVar("SB bkg_{a1}", "background a1", 0, -1, 1);
		RooRealVar *SB_bkg_a2  = new RooRealVar("SB bkg_{a2}", "background a2", 0, -1, 1);
		RooAbsPdf  *SB_bkgPdf  = new RooPolynomial("SB_bkg","side-band background",
				*mass, RooArgList(*SB_bkg_a1,*SB_bkg_a2));
		//SB_bkg_a1->setVal(0);
		//SB_bkg_a1->setConstant(kTRUE);
		//SB_bkg_a2->setVal(0);
		//SB_bkg_a2->setConstant(kTRUE);

		/// Combined pdf
		int nt = 100000;
		//bool fitfraction = true;
		RooRealVar *nbkgd = new RooRealVar("N_{bkg}","nbkgd",nt*0.75,0,10*nt);
		RooRealVar *SB_nbkgd = new RooRealVar("SB N_{bkg}","SB_nbkgd",nt*0.75,0,10*nt);
		RooRealVar *nsig1f  = new RooRealVar("N_{#Upsilon(1S)}","nsig1S",nt*0.25,0,10*nt);
		/*
		//use the YIELDs of 2S and 3S as free parameters
		RooRealVar *nsig2f  = new RooRealVar("N_{#Upsilon(2S)}","nsig2S",   nt*0.25,-1*nt,10*nt);
		RooRealVar *nsig3f  = new RooRealVar("N_{#Upsilon(3S)}","nsig3S",   nt*0.25,-1*nt,10*nt);
		 */
		//use the RATIOs of 2S and 3S as free parameters
		RooRealVar *f2Svs1S = new RooRealVar("N_{2S}/N_{1S}","f2Svs1S",0.21,-0.1,1);
		//RooRealVar *f3Svs1S = new RooRealVar("N_{3S}/N_{1S}","f3Svs1S",0.0,-0.1,0.5);
		RooRealVar *f23vs1S = new RooRealVar("N_{2S+3S}/N_{1S}","f23vs1S",0.45,-0.1,1);
		RooFormulaVar *nsig2f = new RooFormulaVar("nsig2S","@0*@1", RooArgList(*nsig1f,*f2Svs1S));
		//RooFormulaVar *nsig3f = new RooFormulaVar("nsig3S","@0*@1", RooArgList(*nsig1f,*f3Svs1S));
		RooFormulaVar *nsig3f = new RooFormulaVar("nsig3S","@0*@2-@0*@1", RooArgList(*nsig1f,*f2Svs1S,*f23vs1S));

		//f3Svs1S->setConstant(kTRUE);

		//force the ratio to the pp value
		f2Svs1S_pp->setConstant(kTRUE);
		f3Svs1S_pp->setConstant(kTRUE);
		RooFormulaVar *nsig2f_ = new RooFormulaVar("nsig2S_pp","@0*@1", RooArgList(*nsig1f,*f2Svs1S_pp)); 
		RooFormulaVar *nsig3f_ = new RooFormulaVar("nsig3S_pp","@0*@1", RooArgList(*nsig1f,*f3Svs1S_pp)); 

		//only sideband region pdf, using RooPolynomial instead of RooChebychev for multiple ranges fit
		RooAbsPdf  *SB_pdf = new RooAddPdf ("SB_pdf","sideband background pdf",
				RooArgList(*SB_bkgPdf),
				RooArgList(*SB_nbkgd));
		//only signal region pdf, using RooPolynomial instead of RooChebychev for multiple ranges fit
		RooAbsPdf  *S_pdf   = new RooAddPdf ("S_pdf","total signal+background pdf",
				RooArgList(*gauss1S2,*sig2S,*sig3S,*SB_bkgPdf),
				RooArgList(*nsig1f,*nsig2f,*nsig3f,*SB_nbkgd));

		//parameters for likesign
		RooRealVar m0shift("turnOn","turnOn",8.6,0,20.) ;
		RooRealVar width("width","width",2.36,0,20.) ;
		RooRealVar par3("decay","decay",6.8, 0, 20.) ;
		RooGaussian* m0shift_constr;
		RooGaussian* width_constr;
		RooGaussian* par3_constr;

		RooRealVar *nLikesignbkgd = new RooRealVar("NLikesign_{bkg}","nlikesignbkgd",nt*0.75,0,10*nt);
		if (TRKROT) {
			nLikesignbkgd->setVal(TrkRotData->sumEntries());
			nLikesignbkgd->setError(sqrt(TrkRotData->sumEntries()));
		}
		else {
			nLikesignbkgd->setVal(likesignData->sumEntries());
			nLikesignbkgd->setError(sqrt(likesignData->sumEntries()));
		}

		if (LS_constrain) {
			RooGaussian* nLikesignbkgd_constr = new RooGaussian("nLikesignbkgd_constr","nLikesignbkgd_constr",*nLikesignbkgd,RooConst(nLikesignbkgd->getVal()),RooConst(nLikesignbkgd->getError()));
		}
		else nLikesignbkgd->setConstant(kTRUE);

		RooFormulaVar *nResidualbkgd = new RooFormulaVar("NResidual_{bkg}","@0-@1",RooArgList(*nbkgd,*nLikesignbkgd));

		switch (bkgdModel) {
			case 1 :  //use error function to fit the like-sign, then fix the shape and normailization, 
				RooGenericPdf *LikeSignPdf = new  RooGenericPdf("Like-sign","likesign","exp(-@0/decay)*(TMath::Erf((@0-turnOn)/width)+1)",RooArgList(*mass,m0shift,width,par3));
				if (TRKROT) RooFitResult* fit_1st = LikeSignPdf->fitTo(*TrkRotData,Save()) ;
				else RooFitResult* fit_1st = LikeSignPdf->fitTo(*likesignData,Save()) ; // likesign data
				//LikeSignPdf.fitTo(*data) ;       // unlikesign data    
				//fit_1st->Print();
				if (LS_constrain) {
					m0shift_constr = new RooGaussian("m0shift_constr","m0shift_constr",m0shift,RooConst(m0shift.getVal()),RooConst(m0shift.getError()));
					width_constr = new RooGaussian("width_constr","width_constr",width,RooConst(width.getVal()),RooConst(width.getError()));
					par3_constr = new RooGaussian("par3_constr","par3_constr",par3,RooConst(par3.getVal()),RooConst(par3.getError()));
					//m0shift_constr = new RooGaussian("m0shift_constr","m0shift_constr",m0shift,RooConst(7.9),RooConst(0.34*2));
					//width_constr = new RooGaussian("width_constr","width_constr",width,RooConst(2.77),RooConst(0.38*2));
					//par3_constr = new RooGaussian("par3_constr","par3_constr",par3,RooConst(6.3),RooConst(1.0*2));
				}
				else {
					m0shift.setConstant(kTRUE);
					width.setConstant(kTRUE);
					par3.setConstant(kTRUE);
				}
				RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("pdf_combinedbkgd","total combined background pdf",
						RooArgList(*bkgPdf,*LikeSignPdf),
						RooArgList(*nResidualbkgd,*nLikesignbkgd));
				//RooArgList(*LikeSignPdf),
				//RooArgList(*nbkgd));
				break;

			case 2 : //use RooKeysPdf to smooth the like-sign, then fix the shape and normailization
				if (TRKROT) RooKeysPdf *LikeSignPdf = new RooKeysPdf("Like-sign","likesign",*mass,*TrkRotData,3,1.5);
				else RooKeysPdf *LikeSignPdf = new RooKeysPdf("Like-sign","likesign",*mass,*likesignData,3,1.7);
				RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("pdf_combinedbkgd","total combined background pdf",
						RooArgList(*bkgPdf,*LikeSignPdf),
						RooArgList(*nResidualbkgd,*nLikesignbkgd));
				break;

			case 3 : //use error function to fit the unlike-sign directly
				RooGenericPdf *LikeSignPdf = new  RooGenericPdf("Like-sign","likesign","exp(-@0/decay)*(TMath::Erf((@0-turnOn)/width)+1)",RooArgList(*mass,m0shift,width,par3));
				RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("pdf_combinedbkgd","total combined background pdf",
						RooArgList(*LikeSignPdf),
						RooArgList(*nbkgd));
				break;

			case 4 : //use polynomial to fit the unlike-sign directly
				RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("pdf_combinedbkgd","total combined background pdf",
						RooArgList(*bkgPdf),
						RooArgList(*nbkgd));
				break;


			case 5 : //use ( error function + polynomial ) to fit the unlike-sign directly
				RooGenericPdf *LikeSignPdf = new  RooGenericPdf("Like-sign","likesign","exp(-@0/decay)*(TMath::Erf((@0-turnOn)/width)+1)",RooArgList(*mass,m0shift,width,par3));
				RooAbsPdf  *pdf_combinedbkgd   = new RooAddPdf ("pdf_combinedbkgd","total combined background pdf",
						RooArgList(*bkgPdf,*LikeSignPdf),
						RooArgList(*nResidualbkgd,*nLikesignbkgd));
				break;

			default :
				break;
		}

		//pdf with fixed ratio of the pp ratio
		RooAbsPdf  *pdf_pp   = new RooAddPdf ("pdf_pp","total signal+background pdf",
				RooArgList(*gauss1S2,*sig2S,*sig3S,*pdf_combinedbkgd),
				RooArgList(*nsig1f,*nsig2f_,*nsig3f_,*nbkgd));

		//the nominal fit with default pdf 
		if (LS_constrain) {
			RooAbsPdf  *pdf_unconstr   = new RooAddPdf ("pdf_unconstr","total signal+background pdf",
					RooArgList(*gauss1S2,*sig2S,*sig3S,*pdf_combinedbkgd),
					RooArgList(*nsig1f,*nsig2f,*nsig3f,*nbkgd));
			RooProdPdf *pdf  = new RooProdPdf ("pdf","total constr pdf",
					RooArgSet(*pdf_unconstr,*m0shift_constr,*width_constr,*par3_constr,*nLikesignbkgd_constr));
			RooFitResult* fit_2nd = pdf->fitTo(*data,Constrained(),Save(kTRUE),Extended(kTRUE),Minos(doMinos));
		}
		else {
			RooAbsPdf  *pdf   = new RooAddPdf ("pdf","total signal+background pdf",
					RooArgList(*gauss1S2,*sig2S,*sig3S,*pdf_combinedbkgd),
					RooArgList(*nsig1f,*nsig2f,*nsig3f,*nbkgd));
			RooFitResult* fit_2nd = pdf->fitTo(*data,Save(kTRUE),Extended(kTRUE),Minos(doMinos));
		}


		//plot
		TCanvas c; c.cd();
		int nbins = ceil((mmax_-mmin_)/binw_); 
		RooPlot* frame = mass->frame(Bins(nbins),Range(mmin_,mmax_));
		data->plotOn(frame,Name("theData"),MarkerSize(0.8));
		pdf->plotOn(frame,Name("thePdf"));
		if (plotLikeSign) {
			if (TRKROT) TrkRotData->plotOn(frame,Name("theLikeSignData"),MarkerSize(0.8),MarkerColor(kMagenta),MarkerStyle(22));
			else likesignData->plotOn(frame,Name("theLikeSignData"),MarkerSize(0.8),MarkerColor(kRed),MarkerStyle(24));
			//LikeSignPdf->plotOn(frame,Name("theLikeSign"),VisualizeError(*fit_1st,1),FillColor(kOrange));
			//LikeSignPdf->plotOn(frame,Name("theLikeSign"),LineColor(kRed));
		}
		RooArgSet * pars = pdf->getParameters(data);
		//RooArgSet * pars = LikeSignPdf->getParameters(likesignData);

		//calculate chi2 in a mass range
		float bin_Min = (8.2-mmin_)/binw_;
		float bin_Max = (10.8-mmin_)/binw_;
		int binMin = ceil(bin_Min);
		int binMax = ceil(bin_Max);
		int nfloatpars = pars->selectByAttrib("Constant",kFALSE)->getSize();
		float myndof = ceil((10.8-8.2)/binw_) - nfloatpars;
		cout<<binMin<<" "<<binMax<<" "<<nfloatpars<<" "<<myndof<<endl;
		double mychsq = frame->mychiSquare("thePdf","theData",nfloatpars,true,binMin,binMax)*myndof;
		//double mychsq = frame->mychiSquare("theLikeSign","theLikeSignData",nfloatpars,true,binMin,binMax)*myndof;

		/*
		   int nfloatpars = pars->selectByAttrib("Constant",kFALSE)->getSize();
		   float myndof = frame->GetNbinsX() - nfloatpars;
		   double mychsq = frame->chiSquare("theLikeSign","theLikeSignData",nfloatpars)*myndof;
		 */
		//plot parameters
		if(plotpars) {
			paramOn_ = "_paramOn";
			pdf->paramOn(frame,Layout(0.15,0.6,0.4),Layout(0.5,0.935,0.97),Label(Form("#chi^{2}/ndf = %2.1f/%2.0f", mychsq,myndof)));
		}

		/*
		   mass->setRange("R1S",8.8,9.7);
		   mass->setRange("R2S",9.8,10.2);
		//pdf_combinedbkgd->fitTo(*data,Range("R1,R3"),Constrained(),Save(kTRUE),Extended(kTRUE),Minos(doMinos));
		RooAbsReal* integral_1S = pdf_combinedbkgd->createIntegral(*mass,NormSet(*mass),Range("R1S")) ;
		cout << "1S bkgd integral = " << integral_1S->getVal() * (nbkgd->getVal()) << endl ;
		RooAbsReal* integral_2S = pdf_combinedbkgd->createIntegral(*mass,NormSet(*mass),Range("R2S")) ;
		cout << "2S bkgd integral = " << integral_2S->getVal() * (nbkgd->getVal()) << endl ;
		cout << "1S range count: " << data->sumEntries("invariantMass","R1S") <<endl;
		cout << "2S range count: " << data->sumEntries("invariantMass","R2S") <<endl;
		cout << "1S signal yield: " << data->sumEntries("invariantMass","R1S") - integral_1S->getVal() * (nbkgd->getVal()) << endl;
		cout << "2S signal yield: " << data->sumEntries("invariantMass","R2S") - integral_2S->getVal() * (nbkgd->getVal()) << endl;
		 */
		outfile<<"Y(1S) yield  : = "<<nsig1f->getVal()<<" +/- "<<nsig1f->getError()<<endl<<endl;
		outfile<<"free parameter = "<< nfloatpars << ", mychi2 = " << mychsq << ", ndof = " << myndof  << endl << endl;

		//draw the fit lines and save plots
		data->plotOn(frame,Name("theData"),MarkerSize(0.8));
		pdf->plotOn(frame,Components("bkg"),Name("theBkg"),LineStyle(5),LineColor(kGreen));
		pdf->plotOn(frame,Components("pdf_combinedbkgd"),LineStyle(kDashed));
		if (plotLikeSign) {
			if (TRKROT) pdf->plotOn(frame,Components("Like-sign"),Name("theLikeSign"),LineStyle(9),LineColor(kMagenta));
			else  pdf->plotOn(frame,Components("Like-sign"),Name("theLikeSign"),LineStyle(9),LineColor(kRed));
		}
		pdf->plotOn(frame,Name("thePdf"));
		data->plotOn(frame,MarkerSize(0.8));
		if (plotLikeSign) {
			if (TRKROT) TrkRotData->plotOn(frame,Name("theTrkRotData"),MarkerSize(0.8),MarkerColor(kMagenta),MarkerStyle(22));
			else likesignData->plotOn(frame,Name("theLikeSignData"),MarkerSize(0.8),MarkerColor(kRed),MarkerStyle(24));
		}   


		frame->SetTitle( "" );
		frame->GetXaxis()->SetTitle("m_{#mu^{+}#mu^{-}} (GeV/c^{2})");
		frame->GetXaxis()->CenterTitle(kTRUE);
		frame->GetYaxis()->SetTitleOffset(1.3);
		if (PR_plot && RAA) frame->GetYaxis()->SetRangeUser(0,1200);
		//frame->GetYaxis()->SetLabelSize(0.05);
		frame->Draw();


		//plot parameters
		if(!plotpars) {
			paramOn_ = ""; 
			TLatex latex1;
			latex1.SetNDC();
			if (PbPb) {
				latex1.DrawLatex(0.46,1.-0.05*3,"CMS PbPb  #sqrt{s_{NN}} = 2.76 TeV");
				latex1.DrawLatex(0.5,1.-0.05*4.9,"L_{int} = 150 #mub^{-1}"); 
				switch (bin) {  
					case 0: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 0-100%, |y| < 2.4"); break;
					case 3: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 0-5%, |y| < 2.4"); break;
					case 4: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 5-10%, |y| < 2.4"); break;
					case 5: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 10-20%, |y| < 2.4"); break;
					case 6: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 20-30%, |y| < 2.4"); break;
					case 7: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 30-40%, |y| < 2.4"); break;
					case 8: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 40-50%, |y| < 2.4"); break;
					case 9: latex1.DrawLatex(0.5,1.-0.05*6.2,"Cent. 50-100%, |y| < 2.4"); break;
							default; break;
				}   
			}
			else {
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;
}