Exemplo n.º 1
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// DY
//
// channel = SF, MuMu, EE
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void DY(Double_t &yield,
        Double_t &statError,
        Double_t &systError,
        Double_t &scaleFactor,
        Int_t     njet,
        TString   channel,
        TString   directory,
        Bool_t    useDataDriven,
        Int_t     printLevel,
        Bool_t    drawR = false)
{
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // Input files
    //
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    TString path = Form("%s/%djet/%s/", directory.Data(), njet, channel.Data());

    TFile* inputDYSF   = new TFile(path + "DY.root");
    TFile* inputZZSF   = new TFile(path + "ZZ.root");
    TFile* inputWZSF   = new TFile(path + "WZ.root");
    TFile* inputDataSF = new TFile(path + "DataRun2012_Total.root");
    TFile* inputDataOF = new TFile(Form("%s/%djet/OF/DataRun2012_Total.root", directory.Data(), njet));


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // Input histograms
    //
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    TH1F* hNinDYSF  [numberMetCuts];
    TH1F* hNinWZSF  [numberMetCuts];
    TH1F* hNinZZSF  [numberMetCuts];
    TH1F* hNinDataSF[numberMetCuts];
    TH1F* hNinDataOF[numberMetCuts];

    TH1F* hNoutDYSF  [numberMetCuts];
    TH1F* hNoutWZSF  [numberMetCuts];
    TH1F* hNoutZZSF  [numberMetCuts];
    TH1F* hNoutDataSF[numberMetCuts];
    TH1F* hNoutDataOF[numberMetCuts];

    for (UInt_t nC=0; nC<numberMetCuts; nC++) {
        hNinDYSF  [nC] = (TH1F*)inputDYSF  ->Get(Form("hNinZevents%.2f", MetCuts[nC]));
        hNinWZSF  [nC] = (TH1F*)inputWZSF  ->Get(Form("hNinZevents%.2f", MetCuts[nC]));
        hNinZZSF  [nC] = (TH1F*)inputZZSF  ->Get(Form("hNinZevents%.2f", MetCuts[nC]));
        hNinDataSF[nC] = (TH1F*)inputDataSF->Get(Form("hNinZevents%.2f", MetCuts[nC]));
        hNinDataOF[nC] = (TH1F*)inputDataOF->Get(Form("hNinZevents%.2f", MetCuts[nC]));

        hNoutDYSF  [nC] = (TH1F*)inputDYSF  ->Get(Form("hNoutZevents%.2f", MetCuts[nC]));
        hNoutWZSF  [nC] = (TH1F*)inputWZSF  ->Get(Form("hNoutZevents%.2f", MetCuts[nC]));
        hNoutZZSF  [nC] = (TH1F*)inputZZSF  ->Get(Form("hNoutZevents%.2f", MetCuts[nC]));
        hNoutDataSF[nC] = (TH1F*)inputDataSF->Get(Form("hNoutZevents%.2f", MetCuts[nC]));
        hNoutDataOF[nC] = (TH1F*)inputDataOF->Get(Form("hNoutZevents%.2f", MetCuts[nC]));
    }


    // Histogram at analysis level
    //----------------------------------------------------------------------------
    TH1F* hExpectedDYSF = (TH1F*)inputDYSF->Get("hWTopTagging");


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // k estimation
    //
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    TFile* inputDYmumu = new TFile(Form("%s/%djet/MuMu/DY.root", directory.Data(), njet));
    TFile* inputDYee   = new TFile(Form("%s/%djet/EE/DY.root",   directory.Data(), njet));

    TH1F* hNinDYmumu = (TH1F*)inputDYmumu->Get("hNinLooseZevents20.00");
    TH1F* hNinDYee   = (TH1F*)inputDYee  ->Get("hNinLooseZevents20.00");

    Double_t NinDYmumu = hNinDYmumu->GetBinContent(2);
    Double_t NinDYee   = hNinDYee  ->GetBinContent(2);

    Double_t k    = 0.5 * (sqrt(NinDYmumu / NinDYee) + sqrt(NinDYee / NinDYmumu));
    Double_t errk = errkSF(NinDYmumu, NinDYee);

    if (channel == "MuMu") {
        k    = 0.5 * sqrt(NinDYmumu / NinDYee);
        errk = errkFunction(NinDYmumu, NinDYee);
    }
    else if (channel == "EE") {
        k    = 0.5 * sqrt(NinDYee / NinDYmumu);
        errk = errkFunction(NinDYee, NinDYmumu);
    }


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // Counters
    //
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Double_t NinDYSF  [numberMetCuts];
    Double_t NinWZSF  [numberMetCuts];
    Double_t NinZZSF  [numberMetCuts];
    Double_t NinDataSF[numberMetCuts];
    Double_t NinDataOF[numberMetCuts];

    Double_t NoutDYSF  [numberMetCuts];
    Double_t NoutWZSF  [numberMetCuts];  // Not used for now
    Double_t NoutZZSF  [numberMetCuts];  // Not used for now
    Double_t NoutDataSF[numberMetCuts];
    Double_t NoutDataOF[numberMetCuts];

    for (UInt_t nC=0; nC<numberMetCuts-1; nC++) {
        NinDYSF   [nC] = hNinDYSF   [nC]->GetBinContent(2);
        NinWZSF   [nC] = hNinWZSF   [nC]->GetBinContent(2);
        NinZZSF   [nC] = hNinZZSF   [nC]->GetBinContent(2);
        NinDataSF [nC] = hNinDataSF [nC]->GetBinContent(2);
        NinDataOF [nC] = hNinDataOF [nC]->GetBinContent(2);

        NoutDYSF  [nC] = hNoutDYSF  [nC]->GetBinContent(2);
        NoutWZSF  [nC] = hNoutWZSF  [nC]->GetBinContent(2);
        NoutZZSF  [nC] = hNoutZZSF  [nC]->GetBinContent(2);
        NoutDataSF[nC] = hNoutDataSF[nC]->GetBinContent(2);
        NoutDataOF[nC] = hNoutDataOF[nC]->GetBinContent(2);
    }


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // R estimation
    //
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Double_t R       [numberMetCuts];
    Double_t RData   [numberMetCuts];
    Double_t errR    [numberMetCuts];
    Double_t errRData[numberMetCuts];


    // Loop over the met cuts
    //----------------------------------------------------------------------------
    for (UInt_t nC=0; nC<numberMetCuts-1; nC++) {

        R   [nC] = NoutDYSF[nC] / NinDYSF[nC];
        errR[nC] = errRFunction(NoutDYSF[nC], NinDYSF[nC]);

        RData   [nC] = RDataFunction   (NoutDataSF[nC], NoutDataOF[nC], NinDataSF[nC], NinDataOF[nC], k);
        errRData[nC] = errRDataFunction(NoutDataSF[nC], NoutDataOF[nC], NinDataSF[nC], NinDataOF[nC], k, errk);


        if (printLevel > 2) {
            printf("\n %.0f < mpmet < %.0f GeV\n", MetCuts[nC], MetCuts[nC+1]);
            printf(" -------------------------------------------------\n");
            printf("         N^{MC}_{out,SF}   = %6.1f\n", NoutDYSF[nC]);
            printf("         N^{MC}_{in, SF}   = %6.1f\n", NinDYSF[nC]);
            printf("         N^{data}_{out,SF} = %4.0f\n", NoutDataSF[nC]);
            printf("         N^{data}_{out,OF} = %4.0f\n", NoutDataOF[nC]);
            printf("         N^{data}_{in, SF} = %4.0f\n", NinDataSF[nC]);
            printf("         N^{data}_{in, OF} = %4.0f\n", NinDataOF[nC]);
            printf("         k                 = % 5.3f +- %5.3f\n", k,         errk);
            printf("         R^{MC}            = % 5.3f +- %5.3f\n", R[nC],     errR[nC]);
            printf("         R^{data}          = % 5.3f +- %5.3f\n", RData[nC], errRData[nC]);
        }
    }


    // Estimate the R systematic as the difference between R[2] and R[3]
    //----------------------------------------------------------------------------
    Int_t iMaxR = 0;
    Int_t iMinR = 0;

    for (UInt_t nC=0; nC<numberMetCuts-1; nC++) {

        if (R[nC] > 0 && R[nC] > R[iMaxR]) iMaxR = nC;
        if (R[nC] > 0 && R[nC] < R[iMinR]) iMinR = nC;
    }

    Int_t theR = 2;
    Int_t sysR = 3;

    Double_t RelDiffR = (R[theR] > 0) ? fabs(R[theR] - R[sysR]) / R[theR] : -999;


    if (printLevel > 0) {
        printf("\n [%s] R systematic uncertainty\n", channel.Data());
        printf(" -------------------------------------------------\n");
        printf("         min R              = %5.3f\n",     R[iMinR]);
        printf("         max R              = %5.3f\n",     R[iMaxR]);
        printf("         R[%d]               = %5.3f\n",    theR, R[theR]);
        printf("         R[%d]               = %5.3f\n",    sysR, R[sysR]);
        printf("         |R[%d]-R[%d]| / R[%d] = %.1f%s\n", theR, sysR, theR, 1e2*RelDiffR, "%");
        printf("\n");
    }


    // Estimate Nout
    //----------------------------------------------------------------------------
    Double_t NinCountedSFWZ   = NinWZSF  [sysR];
    Double_t NinCountedSFZZ   = NinZZSF  [sysR];
    Double_t NinCountedSFData = NinDataSF[sysR];
    Double_t NinCountedOFData = NinDataOF[sysR];

    Double_t NinEstSFFinal    = NinCountedSFData - k*NinCountedOFData;
    Double_t errNinEstSFFinal = errNinEstFunction(NinCountedSFData, NinCountedOFData, k, errk);

    Double_t NestSFFinal    = R[theR] * NinEstSFFinal;
    Double_t errNestSFFinal = errNestFunction(NestSFFinal, R[theR], errR[theR], NinEstSFFinal, errNinEstSFFinal);

    Double_t NinEstSFNoDibosonFinal    = NinEstSFFinal - NinCountedSFWZ - NinCountedSFZZ;
    Double_t errNinEstSFNoDibosonFinal = errNinEstNoDibosonFunction(NinCountedSFData, k, errk, NinCountedOFData, NinCountedSFWZ, NinCountedSFZZ);

    Double_t NestSFNoDibosonFinal    = R[theR] * NinEstSFNoDibosonFinal;
    Double_t errNestSFNoDibosonFinal = errNestFunction(NestSFNoDibosonFinal, R[theR], errR[theR], NinEstSFNoDibosonFinal, errNinEstSFNoDibosonFinal);
    Double_t totalError              = sqrt(errNestSFNoDibosonFinal*errNestSFNoDibosonFinal + (RelDiffR*NestSFNoDibosonFinal)*(RelDiffR*NestSFNoDibosonFinal));


    Double_t SFsf = NestSFNoDibosonFinal / hExpectedDYSF->GetBinContent(2);


    if (printLevel > 1) {
        printf("\n Analysis results\n");
        printf(" -------------------------------------------------\n");
        printf("         N^{data}_{in,SF} = %4.0f\n", NinCountedSFData);
        printf("         N^{data}_{in,OF} = %4.0f\n", NinCountedOFData);
        printf("         k                = %5.3f +- %5.3f\n", k, errk);
        printf("         R[%d]             = %5.3f +- %5.3f\n", theR, R[theR], errR[theR]);
        printf("         N^{WZ}_{in,SF}   = %7.2f +- %6.2f (stat.) +- %6.2f (syst.)\n",
               NinCountedSFWZ, sqrt(NinCountedSFWZ), 0.1*NinCountedSFWZ);
        printf("         N^{ZZ}_{in,SF}   = %7.2f +- %6.2f (stat.) +- %6.2f (syst.)\n",
               NinCountedSFZZ, sqrt(NinCountedSFZZ), 0.1*NinCountedSFZZ);
        printf("         N^{est}_{in, SF} = %7.2f +- %6.2f\n", NinEstSFFinal, errNinEstSFFinal);
        printf("         N^{est}_{out,SF} = %7.2f +- %6.2f (stat.) +- %6.2f (syst.)\n",
               NestSFFinal, errNestSFFinal, RelDiffR*NestSFFinal);
        printf(" -------------------------------------------------\n");
        printf(" [no VZ] N^{est}_{out,SF} = %7.2f +- %6.2f (stat.) +- %6.2f (syst.) = %7.2f +- %6.2f (stat. + syst.)\n",
               NestSFNoDibosonFinal, errNestSFNoDibosonFinal, RelDiffR*NestSFNoDibosonFinal,
               NestSFNoDibosonFinal, totalError);
        printf("         N^{MC}_{out,SF}  = %7.2f +- %6.2f\n",
               hExpectedDYSF->GetBinContent(2), hExpectedDYSF->GetBinError(2));
        printf("     *** scale factor     = %.3f\n\n", SFsf);
    }


    // Save the result
    //----------------------------------------------------------------------------
    yield       = (useDataDriven) ? NestSFNoDibosonFinal : hExpectedDYSF->GetBinContent(2);
    statError   = errNestSFNoDibosonFinal;
    systError   = RelDiffR*NestSFNoDibosonFinal;
    scaleFactor = yield / hExpectedDYSF->GetBinContent(2);


    // For the note
    //----------------------------------------------------------------------------
    if (printLevel > 0) {
        printf("\n [%s] DY values for the note\n", channel.Data());
        printf(" -------------------------------------------------\n");
        printf(" final state   &             R_{MC}  &  N^{control,data}  &     N_{DY}^{data}  &       N_{DY}^{MC}  &  data/MC\n");
        printf(" same flavour  &  %5.3f $\\pm$ %5.3f  &              %4.0f  &  %5.1f $\\pm$ %4.1f  &  %5.1f $\\pm$ %4.1f  &     %4.1f\n\n",
               R[theR],
               errR[theR],
               NinCountedSFData,
               yield,
               statError,
               hExpectedDYSF->GetBinContent(2),
               hExpectedDYSF->GetBinError(2),
               scaleFactor);
        printf("\n [%s] DY relative systematic uncertainties\n", channel.Data());
        printf(" -------------------------------------------------\n");
        printf(" DY normalisation = %.0f (stat.) $\\bigoplus$ %.0f (syst.)\n\n",
               1e2*statError/yield, 1e2*systError/yield);
    }


    // Check
    //----------------------------------------------------------------------------
    Double_t check = hExpectedDYSF->GetBinContent(2) - NoutDYSF[sysR];
    if (check != 0) printf(" WARNING: DY yields do not much by %f\n\n", check);


    // Draw histograms
    //----------------------------------------------------------------------------
    if (drawR) {

        Double_t absoluteMin = 999;

        TGraphErrors* gR     = new TGraphErrors(numberMetCuts-1);
        TGraphErrors* gRdata = new TGraphErrors(numberMetCuts-1);

        for (UInt_t i=0; i<numberMetCuts-1; i++) {

            gR->SetPoint     (i, 0.5 * (MetDraw[i+1] + MetDraw[i]),    R[i]);
            gR->SetPointError(i, 0.5 * (MetDraw[i+1] - MetDraw[i]), errR[i]);

            gRdata->SetPoint     (i, 0.5 * (MetDraw[i+1] + MetDraw[i]),    RData[i]);
            gRdata->SetPointError(i, 0.5 * (MetDraw[i+1] - MetDraw[i]), errRData[i]);

            if (absoluteMin > (R[i]     - errR[i]))     absoluteMin = R[i]     - errR[i];
            if (absoluteMin > (RData[i] - errRData[i])) absoluteMin = RData[i] - errRData[i];
        }

        if (absoluteMin > 0) absoluteMin = 0;


        // Cosmetics
        //--------------------------------------------------------------------------
        gR->SetMarkerSize (0.9);
        gR->SetMarkerStyle(kFullCircle);

        gRdata->SetLineColor  (kRed+1);
        gRdata->SetMarkerColor(kRed+1);
        gRdata->SetMarkerSize (0.9);
        gRdata->SetMarkerStyle(kFullCircle);


        // Draw
        //--------------------------------------------------------------------------
        canvas = new TCanvas();

        TMultiGraph *mgR = new TMultiGraph();
        mgR->Add(gRdata);
        mgR->Add(gR);

        mgR->Draw("ap");

        mgR->GetYaxis()->SetTitle("R^{out/in}");
        mgR->GetXaxis()->SetTitle("mpmet (GeV)");

        mgR->SetMinimum(absoluteMin - 0.1);
        mgR->SetMaximum(1.0);


        // Legend
        //--------------------------------------------------------------------------
        TLegend* lmgR = new TLegend(0.72, 0.68, 0.92, 0.88);

        lmgR->AddEntry(gR,    " DY MC", "lp");
        lmgR->AddEntry(gRdata," data",  "lp");

        lmgR->SetFillColor(0);
        lmgR->SetTextAlign(12);
        lmgR->SetTextFont (42);
        lmgR->SetTextSize (0.04);

        if      (channel == "SF")   lmgR->SetHeader("ee + #mu#mu");
        else if (channel == "EE")   lmgR->SetHeader("ee");
        else if (channel == "MuMu") lmgR->SetHeader("#mu#mu");

        lmgR->Draw("same");


        // Line at zero
        //--------------------------------------------------------------------------
        TLine* zeroLine = new TLine(canvas->GetUxmin(), 0.0, canvas->GetUxmax(), 0.0);
        zeroLine->SetLineStyle(3);
        zeroLine->SetLineWidth(2);
        zeroLine->Draw("same");
        mgR->Draw("p,same");


        // Save
        //--------------------------------------------------------------------------
        canvas->SaveAs("R_" + channel + ".png");
    }
}
Exemplo n.º 2
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// DY
//
// channel = SF, MuMu, EE
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void doDY(char jetbin,
	  TString channel,
	  TString ID = "MediumIDTighterIP",
	  TString bunch = "50ns",
	  Bool_t  useDataDriven = true,
	  Int_t   printLevel = 100,
	  Bool_t  drawR = true)
{
  cout<<"nJet = "<<jetbin<<endl;
  cout<<"Channel = "<<channel<<endl;

  Double_t yield;                                                                                                                      
  Double_t statError;
  Double_t systError;                                                                                                                    
  Double_t scaleFactor;
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //
  // Input files
  //
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  TString path   = "../rootFiles/" + channel + "/" + ID + "/" + bunch + "/"; 
  TString pathOF = "../rootFiles/OF/" + ID + "/" + bunch + "/"; 

  TFile* inputDYSF   = new TFile(path + "DY.root");
  TFile* inputVVSF   = new TFile(path + "VV.root");
  TFile* inputDataSF = new TFile(path + "Data2015.root");
  TFile* inputDataOF = new TFile(pathOF + "Data2015.root");

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //
  // Input histograms
  //
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  TH1F* hNinDYSF  [numberMetCuts];
  TH1F* hNinVVSF  [numberMetCuts];
  TH1F* hNinDataSF[numberMetCuts];
  TH1F* hNinDataOF[numberMetCuts];

  TH1F* hNoutDYSF  [numberMetCuts];
  TH1F* hNoutVVSF  [numberMetCuts];
  TH1F* hNoutDataSF[numberMetCuts];
  TH1F* hNoutDataOF[numberMetCuts];

  for (UInt_t nC=0; nC<numberMetCuts; nC++) {
    hNinDYSF  [nC] = (TH1F*)inputDYSF  ->Get(Form("hNinZevents%.i%.c", MetCuts[nC],jetbin));
    cout<<Form("hNinZevents%.i%.c", MetCuts[nC],jetbin)<<endl;
    hNinVVSF  [nC] = (TH1F*)inputVVSF  ->Get(Form("hNinZevents%.i%.c", MetCuts[nC],jetbin));
    hNinDataSF[nC] = (TH1F*)inputDataSF->Get(Form("hNinZevents%.i%.c", MetCuts[nC],jetbin));
    hNinDataOF[nC] = (TH1F*)inputDataOF->Get(Form("hNinZevents%.i%.c", MetCuts[nC],jetbin));

    hNoutDYSF  [nC] = (TH1F*)inputDYSF  ->Get(Form("hNoutZevents%.i%.c", MetCuts[nC],jetbin));     
    hNoutVVSF  [nC] = (TH1F*)inputVVSF  ->Get(Form("hNoutZevents%.i%.c", MetCuts[nC],jetbin));     
    hNoutDataSF[nC] = (TH1F*)inputDataSF->Get(Form("hNoutZevents%.i%.c", MetCuts[nC],jetbin));
    hNoutDataOF[nC] = (TH1F*)inputDataOF->Get(Form("hNoutZevents%.i%.c", MetCuts[nC],jetbin));
  }


  // Histogram at analysis level
  //----------------------------------------
  TH1F* hExpectedDYSF = (TH1F*)inputDYSF->Get(Form("hPtLepton1WWLevel%.c", jetbin));//("hWTopTagging");

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //
  // k estimation
  //
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  TFile* inputDYmumu = new TFile("../rootFiles/MuMu/" + ID + "/" + bunch + "/DY.root");
  TFile* inputDYee   = new TFile("../rootFiles/EE/"   + ID + "/" + bunch + "/DY.root");

  TH1F* hNinDYmumu = (TH1F*)inputDYmumu->Get(Form("hNinLooseZevents20%.c", jetbin));
  TH1F* hNinDYee   = (TH1F*)inputDYee  ->Get(Form("hNinLooseZevents20%.c", jetbin));

  Double_t NinDYmumu = hNinDYmumu -> GetBinContent(2);
  Double_t NinDYee   = hNinDYee   -> GetBinContent(2);

  Double_t k    = 0.5 * (sqrt(NinDYmumu / NinDYee) + sqrt(NinDYee / NinDYmumu));
  Double_t errk = errkSF(NinDYmumu, NinDYee);

  if (channel == "MuMu") {
    k    = 0.5 * sqrt(NinDYmumu / NinDYee);
    errk = errkFunction(NinDYmumu, NinDYee);
  }
  else if (channel == "EE") {
    k    = 0.5 * sqrt(NinDYee / NinDYmumu);
    errk = errkFunction(NinDYee, NinDYmumu);
  }


  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //
  // Counters
  //
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Double_t NinDYSF  [numberMetCuts];
  Double_t NinVVSF  [numberMetCuts];
  Double_t NinDataSF[numberMetCuts];
  Double_t NinDataOF[numberMetCuts];

  Double_t NoutDYSF  [numberMetCuts];
  Double_t NoutVVSF  [numberMetCuts];  // Not used for now
  Double_t NoutDataSF[numberMetCuts];
  Double_t NoutDataOF[numberMetCuts];

  for (UInt_t nC=0; nC<numberMetCuts-1; nC++) {
    NinDYSF   [nC] = hNinDYSF   [nC]->GetBinContent(2);
    NinVVSF   [nC] = hNinVVSF   [nC]->GetBinContent(2);
    NinDataSF [nC] = hNinDataSF [nC]->GetBinContent(2);    
    NinDataOF [nC] = hNinDataOF [nC]->GetBinContent(2);

    NoutDYSF  [nC] = hNoutDYSF  [nC]->GetBinContent(2);
    NoutVVSF  [nC] = hNoutVVSF  [nC]->GetBinContent(2);
    NoutDataSF[nC] = hNoutDataSF[nC]->GetBinContent(2);    
    NoutDataOF[nC] = hNoutDataOF[nC]->GetBinContent(2);
  }

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //
  // R estimation
  //
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Double_t R       [numberMetCuts];
  Double_t RData   [numberMetCuts];
  Double_t errR    [numberMetCuts];
  Double_t errRData[numberMetCuts];


  // Loop over the met cuts
  //----------------------------------------------------------------------------
  for (UInt_t nC=0; nC<numberMetCuts-1; nC++) {

    R   [nC] = NoutDYSF[nC] / NinDYSF[nC]; 
    errR[nC] = errRFunction(NoutDYSF[nC], NinDYSF[nC]);

    RData   [nC] = RDataFunction   (NoutDataSF[nC], NoutDataOF[nC], NinDataSF[nC], NinDataOF[nC], k);
    errRData[nC] = errRDataFunction(NoutDataSF[nC], NoutDataOF[nC], NinDataSF[nC], NinDataOF[nC], k, errk);

    if (printLevel > 2) {
      printf("\n %.0f < mpmet < %.0f GeV\n", MetCuts[nC], MetCuts[nC+1]);
      printf(" -------------------------------------------------\n");
      printf("         N^{MC}_{out,SF}   = %6.1f\n", NoutDYSF[nC]);
      printf("         N^{MC}_{in, SF}   = %6.1f\n", NinDYSF[nC]);
      printf("         N^{data}_{out,SF} = %4.0f\n", NoutDataSF[nC]);
      printf("         N^{data}_{out,OF} = %4.0f\n", NoutDataOF[nC]);
      printf("         N^{data}_{in, SF} = %4.0f\n", NinDataSF[nC]);
      printf("         N^{data}_{in, OF} = %4.0f\n", NinDataOF[nC]);
      printf("         k                 = % 5.3f +- %5.3f\n", k,         errk);
      printf("         R^{MC}            = % 5.3f +- %5.3f\n", R[nC],     errR[nC]);
      printf("         R^{data}          = % 5.3f +- %5.3f\n", RData[nC], errRData[nC]);
    }
  }

  // Estimate the R systematic as the difference between R[2] and R[3]
  //----------------------------------------------------------------------------
  Int_t iMaxR = 0; 
  Int_t iMinR = 0; 

  for (UInt_t nC=0; nC<numberMetCuts-1; nC++) {

    if (R[nC] > 0 && R[nC] > R[iMaxR]) iMaxR = nC;
    if (R[nC] > 0 && R[nC] < R[iMinR]) iMinR = nC;
  }

  Int_t theR = 2;
  Int_t sysR = 3;

  Double_t RelDiffR = (R[theR] > 0) ? fabs(R[theR] - R[sysR]) / R[theR] : -999;


  if (printLevel > 0) {
    printf("\n [%s] R systematic uncertainty\n", channel.Data());
    printf(" -------------------------------------------------\n");
    printf("         min R               = %5.3f\n",     R[iMinR]);
    printf("         max R               = %5.3f\n",     R[iMaxR]);
    printf("         R[%d]               = %5.3f\n",    theR, R[theR]);
    printf("         R[%d]               = %5.3f\n",    sysR, R[sysR]);
    printf("         |R[%d]-R[%d]| / R[%d] = %.1f%s\n", theR, sysR, theR, 1e2*RelDiffR, "%");
    printf("\n");
  }


  // Estimate Nout
  //----------------------------------------------------------------------------
  Double_t NinCountedSFVV   = NinVVSF  [sysR];
  Double_t NinCountedSFData = NinDataSF[sysR];
  Double_t NinCountedOFData = NinDataOF[sysR];

  Double_t NinEstSFFinal    = NinCountedSFData - k*NinCountedOFData;
  Double_t errNinEstSFFinal = errNinEstFunction(NinCountedSFData, NinCountedOFData, k, errk);

  Double_t NestSFFinal    = R[theR] * NinEstSFFinal;
  Double_t errNestSFFinal = errNestFunction(NestSFFinal, R[theR], errR[theR], NinEstSFFinal, errNinEstSFFinal);

  Double_t NinEstSFNoDibosonFinal    = NinEstSFFinal - NinCountedSFVV;
  Double_t errNinEstSFNoDibosonFinal = errNinEstNoDibosonFunction(NinCountedSFData, k, errk, NinCountedOFData, NinCountedSFVV);

  Double_t NestSFNoDibosonFinal    = R[theR] * NinEstSFNoDibosonFinal;
  Double_t errNestSFNoDibosonFinal = errNestFunction(NestSFNoDibosonFinal, R[theR], errR[theR], NinEstSFNoDibosonFinal, errNinEstSFNoDibosonFinal);
  Double_t totalError              = sqrt(errNestSFNoDibosonFinal*errNestSFNoDibosonFinal + (RelDiffR*NestSFNoDibosonFinal)*(RelDiffR*NestSFNoDibosonFinal));


  Double_t SFsf = NestSFNoDibosonFinal / hExpectedDYSF->Integral();


  if (printLevel > 1) {
    printf("\n Analysis results\n");
    printf(" -------------------------------------------------\n");
    printf("         N^{data}_{in,SF} = %4.0f\n", NinCountedSFData);
    printf("         N^{data}_{in,OF} = %4.0f\n", NinCountedOFData);
    printf("         k                = %5.3f +- %5.3f\n", k, errk);
    printf("         R[%d]             = %5.3f +- %5.3f\n", theR, R[theR], errR[theR]);
    printf("         N^{VV}_{in,SF}   = %7.2f +- %6.2f (stat.) +- %6.2f (syst.)\n",
	   NinCountedSFVV, sqrt(NinCountedSFVV), 0.1*NinCountedSFVV);
    printf("         N^{est}_{in, SF} = %7.2f +- %6.2f\n", NinEstSFFinal, errNinEstSFFinal);
    printf("         N^{est}_{out,SF} = %7.2f +- %6.2f (stat.) +- %6.2f (syst.)\n",
	   NestSFFinal, errNestSFFinal, RelDiffR*NestSFFinal);
    printf(" -------------------------------------------------\n");
    printf(" [no VZ] N^{est}_{out,SF} = %7.2f +- %6.2f (stat.) +- %6.2f (syst.) = %7.2f +- %6.2f (stat. + syst.)\n",
	   NestSFNoDibosonFinal, errNestSFNoDibosonFinal, RelDiffR*NestSFNoDibosonFinal,
	   NestSFNoDibosonFinal, totalError);
    printf("         N^{MC}_{out,SF}  = %7.2f +- %6.2f\n",
	   hExpectedDYSF->Integral(), sqrt(hExpectedDYSF->Integral()));
    printf("     *** scale factor     = %.3f\n\n", SFsf);
  }


  // Save the result
  //----------------------------------------------------------------------------
  yield       = (useDataDriven) ? NestSFNoDibosonFinal : hExpectedDYSF->Integral();
  statError   = errNestSFNoDibosonFinal;
  systError   = RelDiffR*NestSFNoDibosonFinal;
  scaleFactor = yield / hExpectedDYSF->Integral();


  // For the note
  //----------------------------------------------------------------------------
  if (printLevel > 0) {
    printf("\n [%s] DY values for the note\n", channel.Data());
    printf(" -------------------------------------------------\n");
    printf(" final state   &             R_{MC}  &  N^{control,data}  &     N_{DY}^{data}  &       N_{DY}^{MC}  &  data/MC\n");
    printf(" same flavour  &  %5.3f $\\pm$ %5.3f  &              %4.0f  &  %5.1f $\\pm$ %4.1f  &  %5.1f $\\pm$ %4.1f  &     %4.1f\n\n",
	   R[theR],
	   errR[theR],
	   NinCountedSFData,
	   yield,
	   statError,
	   hExpectedDYSF->Integral(),
	   sqrt(hExpectedDYSF->Integral()),
	   scaleFactor);
    printf("\n [%s] DY relative systematic uncertainties\n", channel.Data());
    printf(" -------------------------------------------------\n");
    printf(" DY normalisation = %.0f (stat.) $\\bigoplus$ %.0f (syst.)\n\n",
	   1e2*statError/yield, 1e2*systError/yield);
  }


  // Check
  //----------------------------------------------------------------------------
  Double_t check = hExpectedDYSF->Integral() - NoutDYSF[sysR];
  if (check != 0) printf(" WARNING: DY yields do not much by %f\n\n", check);


  // Draw histograms
  //----------------------------------------------------------------------------
  if (drawR) {

    Double_t absoluteMin = 999;

    TGraphErrors* gR     = new TGraphErrors(numberMetCuts-1);
    TGraphErrors* gRdata = new TGraphErrors(numberMetCuts-1);

    for (UInt_t i=0; i<numberMetCuts-1; i++) {

      gR->SetPoint     (i, 0.5 * (MetDraw[i+1] + MetDraw[i]),    R[i]);
      gR->SetPointError(i, 0.5 * (MetDraw[i+1] - MetDraw[i]), errR[i]);

      gRdata->SetPoint     (i, 0.5 * (MetDraw[i+1] + MetDraw[i]),    RData[i]);
      gRdata->SetPointError(i, 0.5 * (MetDraw[i+1] - MetDraw[i]), errRData[i]);

      if (absoluteMin > (R[i]     - errR[i]))     absoluteMin = R[i]     - errR[i];
      if (absoluteMin > (RData[i] - errRData[i])) absoluteMin = RData[i] - errRData[i];
    }
    
    if (absoluteMin > 0) absoluteMin = 0;

    // Cosmetics
    //--------------------------------------------------------------------------
    gR->SetMarkerSize (0.9);
    gR->SetMarkerStyle(kFullCircle);

    gRdata->SetLineColor  (kRed+1);
    gRdata->SetMarkerColor(kRed+1);
    gRdata->SetMarkerSize (0.9);
    gRdata->SetMarkerStyle(kFullCircle);


    // Draw
    //--------------------------------------------------------------------------
    canvas = new TCanvas();

    TMultiGraph *mgR = new TMultiGraph();
    mgR->Add(gRdata);
    mgR->Add(gR);

    mgR->Draw("ap");

    mgR->GetYaxis()->SetTitle("R^{out/in}");
    mgR->GetXaxis()->SetTitle("mpmet (GeV)");

    mgR->SetMinimum(absoluteMin - 0.1);
    mgR->SetMaximum(1.0);


    // Legend
    //--------------------------------------------------------------------------
    TLegend* lmgR = new TLegend(0.62, 0.68, 0.86, 0.88);

    lmgR->AddEntry(gR,    " DY MC", "lp");
    lmgR->AddEntry(gRdata," data",  "lp");

    lmgR->SetFillColor(0);
    lmgR->SetLineColor(kWhite);
    lmgR->SetTextAlign(12);
    lmgR->SetTextFont (42);
    lmgR->SetTextSize (0.04);

    if      (channel == "SF")   lmgR->SetHeader("ee + #mu#mu");
    else if (channel == "EE")   lmgR->SetHeader("ee");
    else if (channel == "MuMu") lmgR->SetHeader("#mu#mu");

    lmgR->Draw();

    // Line at zero
    //--------------------------------------------------------------------------
    TLine* zeroLine = new TLine(canvas->GetUxmin(), 0.0, canvas->GetUxmax(), 0.0);
    zeroLine->SetLineStyle(3);
    zeroLine->SetLineWidth(2);
    zeroLine->Draw("same");
    mgR->Draw("p,same");
  

    // Save
    //--------------------------------------------------------------------------
    lmgR->Draw("same");

    if (jetbin == '3'){
      DrawTLatex(0.725, 0.65, 0.04,  "Inclusive");
      canvas->SaveAs("R_" + channel + "_Inclusive.png");
      canvas->SaveAs("R_" + channel + "_Inclusive.pdf");
    }
    else{                                                   //Inclusive 
      if      (jetbin == '0') DrawTLatex(0.725, 0.65, 0.04,  "0 Jet    ");
      else if (jetbin == '1') DrawTLatex(0.725, 0.65, 0.04,  "1 Jet    ");
      else if (jetbin == '2') DrawTLatex(0.725, 0.65, 0.04,  "2+ Jets  ");
      canvas->SaveAs("R_" + channel + "_" + jetbin + "jet.png");
      canvas->SaveAs("R_" + channel + "_" + jetbin + "jet.pdf");
    }
  }
}