//************************************************
// Author: Federica Lionetto
// Created on: 06/27/2014
//************************************************

/*
   List of useful functions.
   */

// Header guard.
#ifndef __STYLE_C_INCLUDED__
#define __STYLE_C_INCLUDED__

#include "Lib.C"
#include "lhcbStyle.C"

//************************************************
//
// Declarations.
//

void dca();

void PersonalStyle();

void InitHist(TH1 *hist, TString title = "", TString x = "", TString y = "");

void InitHist2(TH2 *hist, TString title = "", TString x = "", TString y = "", TString z = "");

void DrawHist(TCanvas *canvas, TH1 *hist, TString option = "", TString folder = "");

void DrawHistCompare(TCanvas *canvas, TH1 *hist1, TString option1, TH1 *hist2, TString option2, TLegend *leg, TString folder = "");

void DrawHistCompare3(TCanvas *canvas, TH1 *hist1, TString option1, TH1 *hist2, TString option2, TH1 *hist3, TString option3, TLegend *leg, TString folder = "");

void DrawHistFunc(TCanvas *canvas, TH1 *hist, TF1 *func, TString folder = "");

void DrawHist2(TCanvas *canvas, TH2 *hist, TString option = "", TString folder = "");

void DrawHistStats(TCanvas *canvas, TH1 *hist, TPaveStats *stats, TString option = "", TString folder = "");

void DrawHistStats2(TCanvas *canvas, TH2 *hist, TPaveStats *stats, TString option = "", TString folder = "");

void InitGraph(TGraph *graph, TString title = "", TString x = "", TString y = "");

void InitGraphErrors(TGraphErrors *graph, TString title = "", TString x = "", TString y = "");

void DrawGraph(TCanvas *canvas, TGraph *graph, TString option = "APC", TString folder = "");

void DrawGraphErrors(TCanvas *canvas, TGraphErrors *graph, TString option = "APC", TString folder = "");

void DrawGraphFunc(TCanvas *canvas, TGraph *graph, TF1 *func, TString option = "APC", TString folder = "");

void DrawGraphFunc2(TCanvas *canvas, TGraph *graph, TF1 *func1, TF1 *func2, TString option = "APC", TString folder = "");

void DrawGraphErrorsFunc(TCanvas *canvas, TGraphErrors *graph, TF1 *func, TString option = "APC", TString folder = "");

void DrawGraphErrorsFunc2(TCanvas *canvas, TGraphErrors *graph, TF1 *func1, TF1 *func2, TString option = "APC", TString folder = "");

void DrawGraphCompare(TCanvas *canvas, TMultiGraph *graph, TLegend *leg, TString title = "", TString x = "", TString y = "", TString option = "APE", TString folder = "");

void DrawFrame(TCanvas *canvas, RooPlot *frame, TLegend *leg, bool logy = false, bool res = false, TString folder = "");

TLegend *CreateLegend2(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TString option = "w", Double_t x1 = 0.64, Double_t y1 = 0.59, Double_t x2 = 0.94, Double_t y2 = 0.89);

TLegend *CreateLegend3(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TObject *obj3, TString lab3, TString option3, TString option = "w", Double_t x1 = 0.64, Double_t y1 = 0.59, Double_t x2 = 0.94, Double_t y2 = 0.89);

TLegend *CreateLegend4(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TObject *obj3, TString lab3, TString option3, TObject *obj4, TString lab4, TString option4, TString option = "w", Double_t x1 = 0.64, Double_t y1 = 0.59, Double_t x2 = 0.94, Double_t y2 = 0.89);

TLegend *CreateLegend5(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TObject *obj3, TString lab3, TString option3, TObject *obj4, TString lab4, TString option4, TObject *obj5, TString lab5, TString option5, TString option = "w", Double_t x1 = 0.64, Double_t y1 = 0.59, Double_t x2 = 0.94, Double_t y2 = 0.89);

TPaveStats *CreateStats(TH1 *hist, TString option = "");

double Residual(Double_t datum, Double_t pdf);

void AddLinesToResidualHist(const TH1F *hist);

TH1F *CreateResidualHist(const RooHist *rhist, const RooCurve *curve);

//************************************************
//
// Definitions.
//

// Thanks to Angelo Di Canto.
void dca()
{
    TStyle *dcastyle = new TStyle("dcastyle","The real perfect style");

    // canvas
    dcastyle->SetCanvasColor(0);
    dcastyle->SetCanvasBorderSize(10);
    dcastyle->SetCanvasBorderMode(0);
    dcastyle->SetCanvasDefW(600);
    dcastyle->SetCanvasDefH(600);

    // pads
    dcastyle->SetPadColor(0);
    dcastyle->SetPadBorderSize(10);
    dcastyle->SetPadBorderMode(0);
    dcastyle->SetPadLeftMargin(.18);
    dcastyle->SetPadRightMargin(.05);
    dcastyle->SetPadBottomMargin(.12);
    dcastyle->SetPadTopMargin(.1);
    //dcastyle->SetPadGridX(1);
    //dcastyle->SetPadGridY(1);
    dcastyle->SetPadTickX(0);
    dcastyle->SetPadTickY(0);

    // frame
    dcastyle->SetFrameBorderMode(0);
    dcastyle->SetFrameBorderSize(10);
    dcastyle->SetFrameFillStyle(0);
    dcastyle->SetFrameFillColor(0);
    dcastyle->SetFrameLineColor(1);
    dcastyle->SetFrameLineStyle(0);
    dcastyle->SetFrameLineWidth(1);

    // histogram
    dcastyle->SetHistFillColor(0);
    dcastyle->SetHistFillStyle(1001);// solid
    dcastyle->SetHistLineColor(1);
    dcastyle->SetHistLineStyle(0);
    dcastyle->SetHistLineWidth(1.5);
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,16,0)
    dcastyle->SetHistMinimumZero();
#endif
    dcastyle->SetOptStat(0);
    dcastyle->SetOptFit(0);
    dcastyle->SetStatColor(0);
    dcastyle->SetStatBorderSize(1);
    dcastyle->SetStatFontSize(.05);

    // graph
    dcastyle->SetEndErrorSize(0);
    dcastyle->SetErrorX(0.5);

    // marker
    dcastyle->SetMarkerStyle(20);
    dcastyle->SetMarkerColor(kBlack);
    dcastyle->SetMarkerSize(0.6);

    // title 
    dcastyle->SetOptTitle(1);
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,16,0)
    dcastyle->SetTitleAlign(33);
    dcastyle->SetTitleX(.95);
#else
    dcastyle->SetTitleX(.15);
#endif
    dcastyle->SetTitleFillColor(0);
    dcastyle->SetTitleBorderSize(0);
    dcastyle->SetTitleStyle(0);

    // axes
    dcastyle->SetNdivisions(505,"X");
    dcastyle->SetNdivisions(505,"Y");

    dcastyle->SetTitleSize(.05,"X");//.055
    dcastyle->SetTitleOffset(1.,"X");//1.2,0.9
    dcastyle->SetLabelOffset(0.003,"X");
    dcastyle->SetLabelSize(.05,"X");
    dcastyle->SetLabelFont(42,"X");

    dcastyle->SetTitleSize(.05,"Y");//.055
    dcastyle->SetTitleOffset(1.8,"Y");
    dcastyle->SetLabelOffset(0.008,"Y");
    dcastyle->SetLabelSize(.05,"Y");
    dcastyle->SetLabelFont(42,"Y");

    dcastyle->SetStripDecimals(kFALSE);

    dcastyle->SetTitleSize(0.05,"Z");
    dcastyle->SetTitleOffset(1.800,"Z");
    dcastyle->SetLabelOffset(0.008,"Z");
    dcastyle->SetLabelSize(0.05,"Z");
    dcastyle->SetLabelFont(42,"Z");

    // fonts
    dcastyle->SetTextSize(.05);//.055
    dcastyle->SetTextFont(42);
    dcastyle->SetStatFont(42);
    dcastyle->SetTitleFont(42,"");
    dcastyle->SetTitleFont(42,"Z");
    dcastyle->SetTitleFont(42,"X");
    dcastyle->SetTitleFont(42,"Y");

    // function
    dcastyle->SetFuncColor(kBlue);
    dcastyle->SetFuncStyle(0);
    dcastyle->SetFuncWidth(1);

    // legend
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,16,0)
    dcastyle->SetLegendBorderSize(1);
#endif

    // palette
    dcastyle->SetPalette(1);
    dcastyle->SetNumberContours(20);

    // set dcastyle as current style
    gROOT->SetStyle("dcastyle");

    gSystem->ProcessEvents();
}

// PersonalStyle modifies the official LHCb style.
void PersonalStyle() {
    TStyle *style = getLHCbStyle();
    // style->SetOptStat("emruo");
    style->SetTitleOffset(1.47,"Y");
    style->SetStatY(0.88);
    // TGaxis::SetMaxDigits(3);
    style->SetPadTopMargin(0.0735);
    style->SetPadLeftMargin(0.2);
    style->SetPadRightMargin(0.1);

    // Set the line style
    style->SetLineStyleString(kDashed, "40 40");
    style->SetLineStyleString(kDotted, "4 12");
    style->SetLineStyleString(kDashDotted, "20 20 4 20");

    return;
}

// InitHist defines some attributes of the "hist" histogram: the title "title" and the x-axis and y-axis labels "x" and "y".
void InitHist(TH1 *hist, TString title, TString x, TString y) {
    hist->SetTitle(title);
    hist->GetXaxis()->SetTitle(x);
    if (y == "")
        hist->GetYaxis()->SetTitle(Form("Entries / %g",hist->GetBinWidth(1)));
    else
        hist->GetYaxis()->SetTitle(y);

    return;
}

// InitHist2 defines some attributes of the "hist" histogram: the title "title" and the x-axis, y-axis, and z-axis labels "x", "y", and "z".
void InitHist2(TH2 *hist, TString title, TString x, TString y, TString z) {
    hist->SetTitle(title);
    hist->GetXaxis()->SetTitle(x);
    hist->GetYaxis()->SetTitle(y);
    if (z == "")
        hist->GetZaxis()->SetTitle(Form("Entries / (%g*%g)",hist->GetXaxis()->GetBinWidth(1),hist->GetYaxis()->GetBinWidth(1)));
    else
        hist->GetZaxis()->SetTitle(z);
    hist->SetLabelOffset(0.005,"Z");
    hist->SetTitleOffset(0.65,"Z");

    return;
}

// DrawHist draws the "hist" histogram in the "canvas" canvas, by default with the "" option, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawHist(TCanvas *canvas, TH1 *hist, TString option, TString folder) {
    TString path;
    /*
       if (folder == "")
       path = "Figures/";
       else
       path = folder + "/" + "Figures/";
       */
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    hist->Draw(option);
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawHistCompare draws the "hist1" and "hist2" histograms in the "canvas" canvas, by default with the "" option, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawHistCompare(TCanvas *canvas, TH1 *hist1, TString option1, TH1 *hist2, TString option2, TLegend *leg, TString folder) {
    TString path;
    /*
       if (folder == "")
       path = "Figures/";
       else
       path = folder + "/" + "Figures/";
       */
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    hist1->SetMarkerColor(kViolet);
    hist2->SetMarkerColor(kTeal-5);
    hist1->SetLineColor(kViolet);
    hist2->SetLineColor(kTeal-5);
    hist1->SetMarkerStyle(20);
    hist2->SetMarkerStyle(21);
    if (hist1->GetMaximum() > hist2->GetMaximum()) {
        hist1->Draw(option1);
        hist2->Draw(option2+"SAME");
    }
    else {
        hist2->Draw(option2);
        hist1->Draw(option1+"SAME");
    }
    leg->Draw();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawHistCompare3 draws the "hist1", "hist2", and "hist3" histograms in the "canvas" canvas, by default with the "" option, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawHistCompare3(TCanvas *canvas, TH1 *hist1, TString option1, TH1 *hist2, TString option2, TH1 *hist3, TString option3, TLegend *leg, TString folder) {
    TString path;
    /*
       if (folder == "")
       path = "Figures/";
       else
       path = folder + "/" + "Figures/";
       */
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    hist1->SetMarkerColor(kViolet);
    hist2->SetMarkerColor(kTeal-5);
    hist3->SetMarkerColor(kBlue);
    hist1->SetLineColor(kViolet);
    hist2->SetLineColor(kTeal-5);
    hist3->SetLineColor(kBlue);
    hist1->SetMarkerStyle(20);
    hist2->SetMarkerStyle(21);
    hist3->SetMarkerStyle(22);
    if (hist1->GetMaximum() > hist2->GetMaximum()) {
        if (hist1->GetMaximum() > hist3->GetMaximum())
        {
            hist1->Draw(option1);
            hist2->Draw(option2+"SAME");
            hist3->Draw(option3+"SAME");
        }
        else
        {
            hist3->Draw(option3);
            hist1->Draw(option1+"SAME");
            hist2->Draw(option2+"SAME");
        }
    }
    else
    {
        if (hist2->GetMaximum() > hist3->GetMaximum())
        {
            hist2->Draw(option2);
            hist1->Draw(option1+"SAME");
            hist3->Draw(option3+"SAME");
        }
        else
        {
            hist3->Draw(option3);
            hist1->Draw(option1+"SAME");
            hist2->Draw(option2+"SAME");
        }
    }
    leg->Draw();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawHistFunc draws the "hist" histogram and the "func" function in the "canvas" canvas and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawHistFunc(TCanvas *canvas, TH1 *hist, TF1 *func, TString folder){
    TString path;
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    hist->Draw("E");
    func->Draw("SAME");
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawHist2 draws the "hist" histogram in the "canvas" canvas, by default with the "" option, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawHist2(TCanvas *canvas, TH2 *hist, TString option, TString folder) {
    TString path;
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    hist->Draw(option);
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawHistStats draws the "hist" histogram and the "stats" stats in the "canvas" canvas, by default with the "" option, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawHistStats(TCanvas *canvas, TH1 *hist, TPaveStats *stats, TString option, TString folder) {
    TString path;
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    hist->Draw(option);
    stats->Draw("SAME");
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawHistStats2 draws the "hist" histogram and the "stats" stats in the "canvas" canvas, by default with the "" option, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawHistStats2(TCanvas *canvas, TH2 *hist, TPaveStats *stats, TString option, TString folder) {
    TString path;
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    hist->Draw(option);
    stats->Draw("SAME");
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// InitGraph defines some attributes of the "graph" graph: the title "title" and the x-axis and y-axis labels "x" and "y".
void InitGraph(TGraph *graph, TString title, TString x, TString y) {
    graph->SetTitle(title);
    graph->GetXaxis()->SetTitle(x);
    graph->GetYaxis()->SetTitle(y);
    graph->SetFillColor(kWhite);

    return;
}

// InitGraphErrors defines some attributes of the "graph" graph: the title "title" and the x-axis and y-axis labels "x" and "y".
void InitGraphErrors(TGraphErrors *graph, TString title, TString x, TString y) {
    graph->SetTitle(title);
    graph->GetXaxis()->SetTitle(x);
    graph->GetYaxis()->SetTitle(y);
    graph->SetFillColor(kWhite);

    return;
}

// DrawGraph draws the "graph" graph in the "canvas" canvas, by default with the "APC" option, adds the "leg" legend, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
// "A" = with axes
// "P" = with points
// "C" = with smooth curves
void DrawGraph(TCanvas *canvas, TGraph *graph, TString option, TString folder) {
    TString path;
    path = folder; 
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);
    graph->Draw(option);
    graph->SetFillColor(38);
    graph->SetMarkerSize(1);
    graph->SetMarkerStyle(20);
    graph->SetMarkerColor(1);
    graph->SetLineWidth(2);
    graph->SetLineStyle(1);
    graph->SetLineColor(2);
    gPad->Modified();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawGraph draws the "graph" graph in the "canvas" canvas, by default with the "APC" option, adds the "leg" legend, and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
// "A" = with axes
// "P" = with points
// "C" = with smooth curves
void DrawGraphErrors(TCanvas *canvas, TGraphErrors *graph, TString option, TString folder) {
    TString path;
    path = folder; 
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);
    graph->Draw(option);
    graph->SetFillColor(38);
    graph->SetMarkerSize(1);
    graph->SetMarkerStyle(20);
    graph->SetMarkerColor(1);
    graph->SetLineWidth(2);
    graph->SetLineStyle(1);
    graph->SetLineColor(2);
    gPad->Modified();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawGraphFunc draws the "graph" graph and the "func" function in the "canvas" canvas and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawGraphFunc(TCanvas *canvas, TGraph *graph, TF1 *func, TString option, TString folder) {
    TString path;
    path = folder; 
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);
    graph->Draw(option);
    graph->SetFillColor(38);
    graph->SetMarkerSize(1);
    graph->SetMarkerStyle(20);
    graph->SetMarkerColor(1);
    graph->SetLineWidth(2);
    graph->SetLineStyle(1);
    graph->SetLineColor(2);
    func->Draw("SAME");
    func->SetLineWidth(2);
    func->SetLineStyle(1);
    func->SetLineColor(kMagenta);
    gPad->Modified();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawGraphFunc2 draws the "graph" graph and the "func1" and "func2" functions in the "canvas" canvas and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawGraphFunc2(TCanvas *canvas, TGraph *graph, TF1 *func1, TF1 *func2, TString option, TString folder) {
    TString path;
    path = folder; 
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);
    graph->Draw(option);
    graph->SetFillColor(38);
    graph->SetMarkerSize(1);
    graph->SetMarkerStyle(20);
    graph->SetMarkerColor(1);
    graph->SetLineWidth(2);
    graph->SetLineStyle(1);
    graph->SetLineColor(2);
    func1->Draw("SAME");
    func1->SetLineWidth(2);
    func1->SetLineStyle(1);
    func1->SetLineColor(kOrange);
    func2->Draw("SAME");
    func2->SetLineWidth(2);
    func2->SetLineStyle(1);
    func2->SetLineColor(kMagenta);
    gPad->Modified();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawGraphErrorsFunc draws the "graph" graph and the "func" function in the "canvas" canvas and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawGraphErrorsFunc(TCanvas *canvas, TGraphErrors *graph, TF1 *func, TString option, TString folder) {
    TString path;
    path = folder; 
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);
    graph->Draw(option);
    graph->SetFillColor(38);
    graph->SetMarkerSize(1);
    graph->SetMarkerStyle(20);
    graph->SetMarkerColor(1);
    graph->SetLineWidth(2);
    graph->SetLineStyle(1);
    graph->SetLineColor(2);
    func->Draw("SAME");
    func->SetLineWidth(2);
    func->SetLineStyle(1);
    func->SetLineColor(kMagenta);
    gPad->Modified();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawGraphErrorsFunc2 draws the "graph" graph and the "func1" and "func2" functions in the "canvas" canvas and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawGraphErrorsFunc2(TCanvas *canvas, TGraphErrors *graph, TF1 *func1, TF1 *func2, TString option, TString folder) {
    TString path;
    path = folder; 
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);
    graph->Draw(option);
    graph->SetFillColor(38);
    graph->SetMarkerSize(1);
    graph->SetMarkerStyle(20);
    graph->SetMarkerColor(1);
    graph->SetLineWidth(2);
    graph->SetLineStyle(1);
    graph->SetLineColor(2);
    func1->Draw("SAME");
    func1->SetLineWidth(2);
    func1->SetLineStyle(1);
    func1->SetLineColor(kOrange);
    func2->Draw("SAME");
    func2->SetLineWidth(2);
    func2->SetLineStyle(1);
    func2->SetLineColor(kMagenta);
    gPad->Modified();
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawGraphCompare draws the "graph" graph in the "canvas" canvas and saves the result in the "folder" folder, in a pdf file named "canvas.pdf".
void DrawGraphCompare(TCanvas *canvas, TMultiGraph *graph, TLegend *leg, TString title, TString x, TString y, TString option, TString folder) {
    TString path;
    path = folder; 
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);
    graph->Draw(option.Data());
    leg->Draw();
    // graph->SetFillColor(38);
    // graph->SetMarkerSize(1);
    // graph->SetMarkerStyle(20);
    // graph->SetMarkerColor(1);
    // graph->SetLineWidth(2);
    // graph->SetLineStyle(1);
    // graph->SetLineColor(2);
    graph->GetYaxis()->SetTitleOffset(0.8);
    gPad->Modified();
    graph->SetTitle(title);
    graph->GetXaxis()->SetTitle(x);
    graph->GetYaxis()->SetTitle(y);
    canvas->Update();
    canvas->Write();
    name = path + "/" + name + ".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// DrawFrame draws the "frame" frame in the "canvas" canvas and saves the result in the "folder" folder, in a pdf file names "canvas.pdf".
void DrawFrame(TCanvas *canvas, RooPlot *frame, TLegend *leg, bool logy, bool res, TString folder) {
    TString path;
    path = folder;
    TString name = canvas->GetName();
    canvas->cd();
    canvas->SetTickx(1);
    canvas->SetTicky(1);

    if (res == false) {
        if (logy == true)
            canvas->SetLogy();
        frame->Draw();
        leg->Draw();
    }

    else if (res == true) {
        RooHist *histogram = frame->getHist("histogram");
        RooCurve *curve = frame->getCurve("curve");
        TH1F *hRes = CreateResidualHist(histogram,curve);
        hRes->GetXaxis()->SetLabelSize((1./(1.+ .35)) * hRes->GetXaxis()->GetLabelSize());
        hRes->GetYaxis()->SetLabelSize((1./(1.+ .35)) * hRes->GetYaxis()->GetLabelSize());

        canvas->Divide(1,2,.1,.1);
        TPad *pHist = (TPad *)canvas->cd(1);
        TPad *pRes = (TPad *)canvas->cd(2);

        pHist->SetPad(0.,0.25,1.,1.);
        if (logy == true)
            pHist->SetLogy();

        pRes->SetPad(0.,0.,1.,0.25);
        pRes->SetBottomMargin(0.3);
        pRes->SetTopMargin(0.1);

        pHist->cd();
        frame->Draw();
        leg->Draw();
        pRes->cd();
        hRes->Draw();
        AddLinesToResidualHist(hRes);
        hRes->Draw("SAME");
    }

    canvas->Update();
    canvas->Write();
    name = path+"/"+name+".pdf";
    canvas->SaveAs(name);
    canvas->Close();

    return;
}

// CreateLegend2 creates and returns the legend for "obj1" (with "lab1" label and "option1" option) and "obj2" (with "lab2" label and "option2" option) objects. It allows to specify the drawing options ("lpfw" by default) and the posizion and size inside the canvas.
// l = lines
// p = points
// f = filled
// w = white
TLegend *CreateLegend2(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TString option, Double_t x1, Double_t y1, Double_t x2, Double_t y2) {
    TLegend *leg = new TLegend(x1,y1,x2,y2);
    leg->AddEntry(obj1,lab1,option1.Data());
    leg->AddEntry(obj2,lab2,option2.Data());
    leg->SetTextSize(0.05);
    if(option.Contains("w"))
        leg->SetFillColor(kWhite);

    return leg;
}

// CreateLegend3 creates and returns the legend for 3 objects.
// l = lines
// p = points
// f = filled
// w = white
TLegend *CreateLegend3(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TObject *obj3, TString lab3, TString option3, TString option, Double_t x1, Double_t y1, Double_t x2, Double_t y2) {
    TLegend *leg = new TLegend(x1,y1,x2,y2);
    leg->AddEntry(obj1,lab1,option1.Data());
    leg->AddEntry(obj2,lab2,option2.Data());
    leg->AddEntry(obj3,lab3,option3.Data());
    leg->SetTextSize(0.05);
    if(option.Contains("w"))
        leg->SetFillColor(kWhite);

    return leg;
}

// CreateLegend4 creates and returns the legend for 4 objects.
// l = lines
// p = points
// f = filled
// w = white
TLegend *CreateLegend4(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TObject *obj3, TString lab3, TString option3, TObject *obj4, TString lab4, TString option4, TString option, Double_t x1, Double_t y1, Double_t x2, Double_t y2) {
    TLegend *leg = new TLegend(x1,y1,x2,y2);
    leg->AddEntry(obj1,lab1,option1.Data());
    leg->AddEntry(obj2,lab2,option2.Data());
    leg->AddEntry(obj3,lab3,option3.Data());
    leg->AddEntry(obj4,lab4,option4.Data());
    leg->SetTextSize(0.05);
    if(option.Contains("w"))
        leg->SetFillColor(kWhite);

    return leg;
}

// CreateLegend5 creates and returns the legend for 5 objects.
// l = lines
// p = points
// f = filled
// w = white
TLegend *CreateLegend5(TObject *obj1, TString lab1, TString option1, TObject *obj2, TString lab2, TString option2, TObject *obj3, TString lab3, TString option3, TObject *obj4, TString lab4, TString option4, TObject *obj5, TString lab5, TString option5, TString option, Double_t x1, Double_t y1, Double_t x2, Double_t y2) {
    TLegend *leg = new TLegend(x1,y1,x2,y2);
    leg->AddEntry(obj1,lab1,option1.Data());
    leg->AddEntry(obj2,lab2,option2.Data());
    leg->AddEntry(obj3,lab3,option3.Data());
    leg->AddEntry(obj4,lab4,option4.Data());
    leg->AddEntry(obj5,lab5,option5.Data());
    leg->SetTextSize(0.05);
    if(option.Contains("w"))
        leg->SetFillColor(kWhite);

    return leg;
}  

// CreateStats creates and returns the stats for "hist" histogram. It allows to specify the drawing options ("" by default).
// I = integral
// S = skewness
// K = kurtosis
// U = underflow
// O = overflow
TPaveStats *CreateStats(TH1 *hist, TString option) {
    TPaveStats *stats = new TPaveStats(0.629396,0.657343,0.932953,0.879860,"brNDC");
    stats->SetName("stats");
    stats->SetBorderSize(1);
    stats->SetFillColor(0);
    stats->SetTextAlign(12);
    TText *text = stats->AddText(Form("Entries = %g",hist->GetEntries()));
    if(option.Contains("I"))
        text = stats->AddText(Form("Integral = %g",hist->Integral()));	
    Int_t N = hist->GetDimension();	
    if (N==1) {
        text = stats->AddText(Form("Mean  = %g",hist->GetMean()));
        text = stats->AddText(Form("RMS   = %g",hist->GetRMS()));
        if(option.Contains("S"))
            text = stats->AddText(Form("Skewness = %g",hist->GetSkewness()));
        if(option.Contains("K"))
            text = stats->AddText(Form("Kurtosis = %g",hist->GetKurtosis()));
        if(option.Contains("U"))
            text = stats->AddText(Form("Underflow = %f",hist->GetBinContent(0)));
        if(option.Contains("O")) {
            Int_t over = hist->GetNbinsX()+1;
            text = stats->AddText(Form("Overflow  = %f",hist->GetBinContent(over)));
        }
    } else {
        text = stats->AddText(Form("Mean x = %g",hist->GetMean(1)));
        text = stats->AddText(Form("Mean y = %g",hist->GetMean(2)));
        text = stats->AddText(Form("RMS x  = %g",hist->GetRMS(1)));
        text = stats->AddText(Form("RMS y = %g",hist->GetRMS(2)));
        if(option.Contains("S")) {
            text = stats->AddText(Form("Skewness x = %g",hist->GetSkewness(1)));
            text = stats->AddText(Form("Skewness y = %g",hist->GetSkewness(2)));
        }
        if(option.Contains("K")) {
            text = stats->AddText(Form("Kurtosis x = %g",hist->GetKurtosis(1)));
            text = stats->AddText(Form("Kurtosis y = %g",hist->GetKurtosis(2)));
        }
        if(option.Contains("U") || option.Contains("O")) {
            Int_t nbinsX = hist->GetNbinsX();
            Int_t nbinsY = hist->GetNbinsY();
            Double_t bl = hist->GetBinContent(0,0);
            Double_t bc = 0; for(int i=1; i<=nbinsX; i++) bc += hist->GetBinContent(i,0);
            Double_t br = hist->GetBinContent(nbinsX+1,0);
            Double_t cl = 0; for(int i=1; i<=nbinsY; i++) cl += hist->GetBinContent(0,i);
            Double_t cc = hist->GetEffectiveEntries();
            Double_t cr = 0; for(int i=1; i<=nbinsX; i++) cr += hist->GetBinContent(nbinsX+1,i);
            Double_t tl = hist->GetBinContent(0,nbinsY+1);
            Double_t tc = 0; for(int i=1; i<=nbinsX; i++) tc += hist->GetBinContent(i,nbinsY+1);
            Double_t tr = hist->GetBinContent(nbinsX+1,nbinsY+1);
            text = stats->AddText(Form("%g| %g| %g",tl,tc,tr));
            text = stats->AddText(Form("%g| %g| %g",cl,cc,cr));
            text = stats->AddText(Form("%g| %g| %g",bl,bc,br));
        }
    }

    return stats;
}

// Residual evaluates the residual.
double Residual(Double_t datum, Double_t pdf)
{
    double chi2 = 0.;

    if ( pdf > 0 )
        chi2 += 2. * ( pdf - datum );

    if ( datum > 0 && pdf > 0 )
        chi2 += 2. * datum * log( datum / pdf );

    return ( ( datum >= pdf ) ? sqrt( chi2 ) : -sqrt( chi2 ) );
}

// AddLinesToResidualHist adds the lines to the histogram of the residuals.
void AddLinesToResidualHist(const TH1F *hist)
{
    double xMin = hist->GetXaxis()->GetXmin();
    double xMax = hist->GetXaxis()->GetXmax();

    TLine *midLine = new TLine( xMin,  0., xMax,  0. );
    TLine *uppLine = new TLine( xMin,  3., xMax,  3. );
    TLine *lowLine = new TLine( xMin, -3., xMax, -3. );

    uppLine->SetLineColor( kGray );
    lowLine->SetLineColor( kGray );

    uppLine->SetLineStyle(7);
    lowLine->SetLineStyle(7);

    midLine->Draw( "same" );
    uppLine->Draw( "same" );
    lowLine->Draw( "same" );

    return;
}

// CreateResidualHist returns the histogram of the residuals.
TH1F *CreateResidualHist(const RooHist *rhist, const RooCurve *curve)
{
    double r = 0.2;
    double sr = 1. / r;

    // Grab info from the histogram.
    int     n = rhist->GetN();
    double* x = rhist->GetX();
    double* y = rhist->GetY();

    // Create residual histogram.
    double xMin = x[ 0     ];
    double xMax = x[ n - 1 ];
    TH1F* residuals_temp = new TH1F( "r", "", n, xMin, xMax );

    double datum = 0.;
    double pdf   = 0.;

    // Fill the histogram.
    if ( curve )
        for ( int bin = 0; bin < n; bin++ )
        {
            datum = y[ bin ];
            pdf   = curve->Eval( x[ bin ] );
            residuals_temp->SetBinContent( bin + 1, Residual( datum, pdf ) );
            residuals_temp->SetBinError  ( bin + 1, 1. );
        }

    residuals_temp->SetMinimum    ( -5.   );
    residuals_temp->SetMaximum    (  5.   );
    residuals_temp->SetStats      ( false );
    residuals_temp->SetMarkerStyle( 8     );
    residuals_temp->SetMarkerSize ( .8    );

    TAxis* xAxis = residuals_temp->GetXaxis();
    xAxis->SetTickLength ( sr * xAxis->GetTickLength()  );
    xAxis->SetLabelSize  ( sr * xAxis->GetLabelSize()   );
    xAxis->SetTitleSize  ( sr * xAxis->GetTitleSize()   );
    xAxis->SetLabelOffset( sr * xAxis->GetLabelOffset() );

    TAxis* yAxis = residuals_temp->GetYaxis();
    yAxis->SetNdivisions ( 504                          );
    yAxis->SetLabelSize  ( sr * yAxis->GetLabelSize()   );

    return residuals_temp;
}

#endif
