//Constants and global options
//David Gerick
//Renata Kopecna
//All the libraries are included here, I am way to lazy to clean up, so here we are

#ifndef GLOBALFUNCTIONS
#define GLOBALFUNCTIONS

#include <cmath>
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <map>
#include <unistd.h>
#include <sys/stat.h>

    //ROOT Libraries
#include <TChain.h>
#include <TTree.h>
#include <TH1D.h>
#include <TH2D.h>
#include <TF1.h>
#include <TFile.h>
#include <TCanvas.h>
#include <TGaxis.h>
#include <TGraphErrors.h>
#include <TLorentzVector.h>
#include <TROOT.h>
#include <TStyle.h>
#include <TFitResult.h>
#include <TLatex.h>
#include <TLegend.h>
#include <TLine.h>
#include <TMarker.h>
#include <TNtuple.h>
#include <TPaveText.h>
#include "TRandom3.h"
#include "TMath.h"
#include "TString.h"
#include "TSystem.h"
#include "TStopwatch.h"
#include <THStack.h>
#include "TGaxis.h"
#include <TMultiGraph.h>
#include "TApplication.h"


    //RooFit Libraries
#include <RooDataSet.h>
#include <RooMCStudy.h>
#include "RooGaussModel.h"
#include "RooExponential.h"
#include "RooGenericPdf.h"
#include "RooChebychev.h"
#include "RooFitResult.h"
#include "RooAddModel.h"
#include "RooPolynomial.h"
#include "RooTruthModel.h"
#include "RooDecay.h"
#include "RooPlot.h"
#include "RooGaussian.h"
#include "RooDstD0BG.h"
#include "RooAddPdf.h"
#include "RooExtendPdf.h"
#include "RooDataHist.h"
#include "RooCBShape.h"
#include "RooCategory.h"
#include "RooFormulaVar.h"
#include "RooSimultaneous.h"
#include "RooHist.h"
#include "RooStats/SPlot.h"
#include "RooTreeDataStore.h"
#include "RooBifurGauss.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooConstVar.h"
#include "RooProdPdf.h"
#include "RooNDKeysPdf.h"
#include "RooKeysPdf.h"
#include "RooGlobalFunc.h"
#include "RooRealIntegral.h"
#include "RooAbsReal.h"
#include "RooMsgService.h"

//Custom RooFit libraries
#include "RooFit/RooExpAndGauss/RooExpAndGauss.hpp"
#include "RooFit/RooDoubleCB/RooDoubleCB.h"

#include "LHCbStyle.h"
//indexed auto looping over vectors
#define for_indexed(...) for_indexed_v(i, __VA_ARGS__)
#define for_indexed_v(v, ...) for(bool _i_ = true, _break_ = false; _i_;) for(size_t v = 0; _i_; _i_ = false) for(__VA_ARGS__) if(_break_) break; else for(bool _j_ = true; _j_;) for(_break_ = true; _j_; _j_ = false) for(bool _k_ = true; _k_; v++, _k_ = false, _break_ = false)

////////////////////////////////////
/////
/////         DECAY options
/////
////////////////////////////////////

bool GetKSfromExePath(){

  char cwd[256];
  if (getcwd(cwd, sizeof(cwd)) != NULL) {
    //printf("Current working dir: %s\n", cwd);
    char * KS = NULL;
    KS = strstr(cwd, "dgerick");
    if(KS){
      std::cout << "Hello David! Now running KS0 pi+ mode!" << std::endl;
      return true;
    }
  }
  std::cout << "Hello Renata! Now running K+ pi0 mode!" << std::endl;

  return false;
}

const bool KshortChannel = GetKSfromExePath(); // false := pi0 channel
const bool SplitDDandLL = KshortChannel ? true : false; //for pi0 SplitDDandLL is always false!

std::string TheDecay = (KshortChannel ? "KshortPiplus" : "KplusPi0Resolved");
const bool Kst2Kpluspi0Resolved = !KshortChannel; //keep the old variables, but set global!
const bool Kst2Kpluspi0Merged = false;
const bool Kst2Kspiplus = KshortChannel;

////////////////////////////////////
///
///         Basic options
///
////////////////////////////////////

    //use only small sample of data for testing purposes
const bool smallSample = false;

    //folder with stored data
const std::string path_to_data = "/auto/data/dgerick/B2Kstmumu";
const std::string path_to_output_KshortPiplus = "/auto/data/dgerick/B2Kstmumu";
const std::string path_to_output_KplusPizero = "/home/lhcb/kopecna/B2KstarMuMu_clean/Data";
const std::string thePath = Kst2Kspiplus ? path_to_output_KshortPiplus : path_to_output_KplusPizero;

    // Use DTF varialbes
const bool UseDTF = KshortChannel ? true : true; //use mass and momenta of particles obtained by DTF?

// Use PDG mass for LorentzVectors or PE from branch
const bool UsePDGmIn4Dvectors = KshortChannel ? false : true;

// Reweight MC to the ratio of sWeighted Jpsi Data to Jpsi MonteCarlo (both reference channel)
const bool ReweightByRefChannel = KshortChannel ? true : true;
// Always reweight MC to pure jpsi data? (also for years without jpsi MC)
const bool AlwaysUseRefChannelData = KshortChannel ? true : true;

// Include 2017 and 2018?
const bool Use2017 = KshortChannel ? true : true;
const bool Use2018 = KshortChannel ? true : true;

    // Use PIDgen for MC tuples
const bool UsePIDgen = KshortChannel ? true : false;


////////////////////////////////////
///
///         Weighting options
///
////////////////////////////////////
///
const std::string firstMCweight = (KshortChannel ? "nLongTracks" : "nLongTracks");
const std::string seconMCweight = KshortChannel ? (UseDTF ? "B_plus_PT_DTF" : "B_plus_PT") : (UseDTF ? "B_plus_PT_DTF" : "B_plus_PT");

const UInt_t firstnBins = 75;
const UInt_t secondnBins = 50;
const double firstMCrange[2] = {-0.5, 149.5};
const double seconMCrange[2] = {TMath::Log(1500.), TMath::Log(50000.)};
const std::string firstMClatex = KshortChannel ? "N^{Long}_{Tracks}" : "N^{Long}_{Tracks}";
const std::string seconMClatex = KshortChannel ? "p_{T}(B^{+}) ( MeV/c )" : "p_{T}(B^{+}) ( MeV/c )";

////////////////////////////////////
///
///           TM options
///
////////////////////////////////////

// TruthMatch MC only according to the BKGCAT
const bool UseBKGCAT = KshortChannel ? true : false;

//Truthmatching: set an option to TM particles
const bool pi0TM = true;
const std::string TMtag = UseBKGCAT ? "" : "_TM" + std::string(pi0TM ? "" : "_noPi0TM");
const std::string TMbranch = "TMed" + std::string(UseBKGCAT ? "BKGCAT" : "") + std::string(pi0TM ? "" : "_noPi0");
const std::string gammaTMbranch = "TM_gammas" + std::string(pi0TM ? "" : "_noPi0");

//Function
bool isTM(std::string customTMbranch, bool TM, bool gammaTM, int gTM){
    if(customTMbranch.find("BKGCAT") != std::string::npos){
        return TM;
    }
    else{
        if(gammaTM) return (TM && (gTM <4));
        else return (TM && (gTM <6));
    }
}

const bool gammaTMdefault = false;

////////////////////////////////////
///
///         Cuts
///
////////////////////////////////////

//DTF convergence cuts
const double cut_DTF_status = 0.5;
const double cut_DTF_chi2   = 200.0;

//Mass cuts
const double K_star_plus_mass_difference = 100.0; //MeV  //difference between K* mass and PDG K* mass

const double cut_B_plus_M_low_basic = 4900.;  //MeV, to account for cut on non-DTF mass in stripping
const double cut_B_plus_M_low =  KshortChannel ? 5150. : 5150.;  //MeV
const double cut_B_plus_M_high = KshortChannel ? 6000. : 5800.;  //MeV
const double B_plus_M_signal_window = KshortChannel ? 50. : 100; 	//MeV -- as PDGmass +/- the window

//kinematic cut <=> pseudorapidity (for each particle, except for gammas)
const double cut_kin_Theta_low = 0.0;
const double cut_kin_Theta_up = 0.4;

//Kinematic cuts
const double cut_K_star_plus_pT = 1350.0; //MeV
const double cut_B_plus_pT = 2000.0; //MeV
const double cut_pi_zero_PT = 800.0; //MeV
const double cut_B_plus_DIRA = 0.99996;
const double cut_muon_angle = 0.001;

const double cut_B_plus_FDCHI2 = 121.0;
const double cut_K_star_plus_FDCHI2 = 9.0;

const double cut_B_plus_ConePTasym = -0.5;

const double cut_DiMuon_M = 7100.0;

//Primary vertex cuts
const double cut_muon_IPCHI2_OWNPV_low  = 9.0;
const double cut_IPCHI2_OWNPV_low  = 0.0;
const double cut_IPCHI2_OWNPV_high = 12.0;

//PID cuts
const double cut_muon_ProbNNmu = 0.25;
const double cut_K_plus_ProbNNk = 0.25;
const double cut_gamma_CL = 0.15;


const bool SplitInQ2 = KshortChannel ? false : false;


//std::vector<double> q2BinsUp  = {0.98, 2.5, 4.0, 6.0, 8.0, 12.5, 17.0, 19.0};
//std::vector<double> q2BinsLow = {0.1,  1.1, 2.5, 4.0, 6.0, 11.0, 15.0, 17.0};
//std::vector<double> diMuonMassBinsUp  = {};  ///TODO
//std::vector<double> diMuonMassBinsLow = {}; //TODO
//const int nq2Bins = q2BinsUp.size();

////////////////////////////////////
///
///         Constants
///
////////////////////////////////////

//TMVA meethod
TString TMVAmethod =  KshortChannel ? "BDTG" : "MLP"; //used TMVA method

//define PDG masses:
    struct PDGMASS{
            Double_t B_PLUS = 5279.29;
            const Double_t B_ZERO = 5279.61;
            const Double_t J_PSI = 3096.90;
            const Double_t PSI_2S = 3686.10;
            const Double_t K_STAR_PLUS = 891.66;
            const Double_t K_ONE_PLUS = 1272.0;
            const Double_t K_PLUS = 493.68;
            const Double_t K_SHORT = 497.61;
            const Double_t PI_PLUS = 139.57;
            const Double_t PI_ZERO = 134.98;
            const Double_t MU = 105.66;
            const Double_t GAMMA = 0;
    } PDGMASS;

//define the TRUEIDs:
    struct TRUEIDS{
            const Int_t B_PLUS = 521;
            const Int_t B_ZERO = 511;
            const Int_t K_STAR_PLUS = 323;
            const Int_t K_STAR_ZERO = 313;
            const Int_t K_ONE_PLUS = 10323; // K1(1270)+
            const Int_t K_ONE_PLUS_1400 = 20323; // K1(1400)+
            const Int_t K_ONE_PLUS_1410 = 100323; // K1(1410)+
            const Int_t K_ONE_ZERO = 10313; // K0(1270)+
            const Int_t K_PLUS = 321;
            const Int_t K_SHORT = 310;
            const Int_t PI_PLUS = 211;
            const Int_t PI_ZERO = 111;
            const Int_t RHO_ZERO = 113;
            const Int_t MU_MINUS = 13;
            const Int_t GAMMA = 22;
            const Int_t J_PSI = 443;
            const Int_t ELECTRON = 11;
    } TRUEID;

//branching ratios
    //const double BR_sig = 9.6e-7;               //PDG value for B+ -> K*+ mu mu
    //const double BR_sig = 6.09576e-7;           //BR for B+ -> K*+ mu mu without resonances from LHCb-PAPER-2014-006
    const double BR_sig = 8.668e-7;             //BR for B+ -> K*+ mu mu without resonances from flavio (09-05-19)
    const double BR_ref = 1.43e-3 * 5.961e-2;   //PDG value for B+ -> J/psi K*+ times J/psi -> mu mu
    const double BR_ref2 = 6.7e-4 * 8.0e-3;   //PDG value for B+ -> psi(2s) K*+ times psi(2s) -> mu mu

    const float SignalRegionNsigma = 2.; //How many sigmas around the signal peak comprises the signal region

    double getTMVAcut(int Run){
       if (Run == 1) return 0.9985;
       else if (Run == 2) return 0.996;
       else return 1;
    }

#ifndef SIGNALPARAMETERS
#define SIGNALPARAMETERS
struct SignalFitParameters{ //TODO: possibly add the K1 to ParamValues at some point

    //signal fractions
    Double_t SigmaEff = 15.;

    //background parameter
    Double_t bkg_mean_K1 = 5158.6;
    Double_t bkg_sigma_K1 = 50.;

    //background fraction
    Double_t f_BplusBckGndK1 = 0.5;
} SignalFitParameter;
#endif //signalfitParams

#ifndef SIGNALPARAMETERSFIXED
#define SIGNALPARAMETERSFIXED
struct FixedParameters{//TODO: possibly add the K1 to ParamValues at some point
    //background parameter
    bool bkg_mean_K1  = KshortChannel ? false : true;
    bool bkg_sigma_K1 = KshortChannel ? false : false;
} FixParameter;
#endif //sigparams

////////////////////////////////////
///
///         Check if file exists
///
////////////////////////////////////


inline bool exists_test (const std::string& name) {
  struct stat buffer;
  return (stat (name.c_str(), &buffer) == 0);
}


////////////////////////////////////
///
///         SetOutputLevel
///
////////////////////////////////////

int verboseLevel = 2;
  //verboseLevel 0: cout Tests, Debugs, Infos, Warnings and Errors
  //verboseLevel 1: cout Debugs, Infos, Warnings and Errors
  //verboseLevel 2: cout Infos, Warnings and Errors
  //verboseLevel 3: cout Warnings and Errors
  //verboseLevel 4: cout Errors (always cout errors)
void setVerboseLevel(int level){
    verboseLevel  = level;
}

bool set_gErrorIgnoreLevel(){
    gStyle -> SetOptStat(0);
    LHCbStyle();
    gROOT->SetBatch(kTRUE);

    if (verboseLevel == 3 || verboseLevel == 2) gErrorIgnoreLevel = kWarning;
    if (verboseLevel == 4) gErrorIgnoreLevel = kError;
    return true;
}

bool get_gErrorIgnoreLevel = set_gErrorIgnoreLevel();

////////////////////////////////////
///
///         Colors
///
////////////////////////////////////

#define cBOLDWHITE   "\033[1m\033[37m"   /* Bold White   */
#define cBOLDRED     "\033[1m\033[31m"   /* Bold Red     */
#define cBOLDGREEN   "\033[1m\033[32m"   /* Bold Green   */
#define cGREEN       "\033[32m"          /* Green        */
#define cBOLDCYAN    "\033[1m\033[36m"   /* Bold Cyan    */
#define cCYAN        "\033[36m"          /* Cyan         */
#define cRED         "\033[31m"          /* Red          */
#define cBOLDRED     "\033[1m\033[31m"   /* Bold red     */
#define cYELLOW      "\033[33m"          /* Yellow       */
#define cBOLDYELLOW  "\033[1m\033[33m"   /* Bold Yellow  */

#define cRESET       "\033[0m"


////////////////////////////////////
///
///         Fancy couts
///
////////////////////////////////////

void coutTest(string message){
    if (verboseLevel==0) cout << "[TEST]\t\t" << message << endl;
}
void coutDebug(string message){
    if (verboseLevel<2) cout << "[DEBUG]\t\t" << message << endl;
}
void coutInfo(string message){
    if (verboseLevel<3) cout << "[INFO]\t\t" << message << endl;
}
void coutWarning(string message){
    if (verboseLevel<4)  cout << cBOLDYELLOW << "[WARN]\t\t" << cYELLOW << message << cRESET << endl;
}
void coutERROR(string message){
    cout << cBOLDRED << "[ERROR]\t\t" << cRED << message << cRESET <<  endl;
}

////////////////////////////////////
///
///         FUNCTIONS
///
/// bool IsDST(year,MC,ReferenceChannel,PHSP)
///     checks whether the input file is MDST or DST
///     Important for branch names in BDTSelection.cpp
///
/// void addLHCbTag(x,y,suffix, color, Scaling)
///     Draws TLatex "LHCb + suffix" with the size of 0.07*scaling
///
/// string Float2Comma(f,d)
///     Returns a comma-separated string of the input float up to the given precision.
///     NO ROUNDING!
///
/// bool replace(str,from,to)
///     replaces string 'from' by 'to'
///     replaces all occurences of 'from'
///
/// void printVector(vector)
///     couts members of a vector
///
////////////////////////////////////

double get_cut_B_plus_M_low(int Run = 2){ //setting lower B mass cut for different run/years
    if (KshortChannel) return cut_B_plus_M_low;
    else{
        if (Run==1) return 5150.0;
        else if (Run==2) return cut_B_plus_M_low;
        else{
            std:: cout << "[WARN] Wrong year input! Choose either 1 or 2. Lower cut set to " << cut_B_plus_M_low << "MeV" << std::endl;
            return cut_B_plus_M_low;


        }
    }

}

double get_cut_B_plus_M_low( std::string year = "2015"){
    if (KshortChannel) return cut_B_plus_M_low;
    else{
        if (year == "2011" || year == "2012") return 5150.0;
        else if (year == "2015" || year == "2016" || year == "2017" || year =="2018" ) return cut_B_plus_M_low;        
        else{
            std:: cout << "[WARN] Wrong year input! Choose a year from 2011, 2012, 2015, 2016, 2017 or 2018. Lower cut set to " << cut_B_plus_M_low << "MeV" << std::endl;
            return cut_B_plus_M_low;

        }
    }
}

bool IsDST(std::string year, bool MC, bool ReferenceChannel, bool PHSP){
    if (MC && (year == "2011" || year == "2012")) return true;
    if (MC && (year == "2018" && KshortChannel) && !PHSP) return true;
    if (MC && ReferenceChannel && (year == "2015" || year == "2016") && !KshortChannel) return true;
    return false;
}

void addLHCbtag(Float_t x = 0.6, Float_t y = 0.85, std::string suffix = "", Int_t color = 1, Float_t Scaling = 1.0){
    TLatex* lhcbtext = new TLatex();
    lhcbtext->SetTextFont(132);
    lhcbtext->SetTextColor(color);
    lhcbtext->SetTextSize(0.07*Scaling);
    lhcbtext->SetTextAlign(13);
    lhcbtext->SetNDC(1);
    lhcbtext->DrawLatex(x,y,("LHCb "+suffix).c_str());
}

std::string Float2Comma(Float_t f, Int_t d){

	if(d > 5){
        std::cout << "[WARNING]\tPrecision larger '5' is not given by this function! Limit to 5." << std::endl;
		d = 5;
	}

    std::string out = Form("%i", static_cast<Int_t>(f + 1e-6));
    /* just curious, why don't we use something like
     * tmp = f //just to be sure nothing happens to f itself
     * stringstream ss;
     * ss << fixed << setprecision(d) << tmp;
     * string out = ss.str()
     * out.replace(out.find("."),out.find(".")+1,",")
     * return out;
     * Seems a bit easier to me, or?
     * */

	if(d <= 0)return out;

	Int_t N[d];
        out.append(",");	

	for(Int_t n = 0; n <= d; n++){
		N[n] = static_cast<Int_t>((f + 1e-6) * TMath::Power(10., n));
        //std::cout << "Iteration " << n << " : " << (f + 1e-6) * TMath::Power(10., n) << " and as INT: " << N[n] << std::endl;
		for(Int_t m = 0; m < n; m++)N[n] -= N[m] * TMath::Power(10., n - m);
		if(n != 0)out.append(Form("%i", N[n]));
	}

	return out;

}

bool replace(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = str.find(from);
    if(start_pos == std::string::npos) return false;
    while ( (start_pos = str.find(from,start_pos)) != std::string::npos){
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
    }
    return true;
}

void printVector (std::vector<int> vector){
    for (auto e: vector) cout << e << " ";
}
void printVector (std::vector<double> vector){
    for (auto e: vector) cout << e << " ";
}/*
void printVector (std::vector<float> vector){
    for (float e: vector) cout << e << " ";
}*/
void printVector (std::vector<string> vector){
    for (auto e: vector) cout << e << " ";
}

std::vector<string> yearsMC (bool Reference = false, bool PHSP = false, int Run = 1){
     std::vector<string> yearsTmp;
     if(Run != 1 && Run != 2 && Run !=12 ){         
         coutERROR("Invalid Run number given: " + to_string(Run) + ". Exit program!");
         return yearsTmp;
     }
     if(Run == 1|| Run == 12) {
         yearsTmp.push_back("2011");
         yearsTmp.push_back("2012");
     }
     if(Run == 2|| Run == 12){
         if (Kst2Kpluspi0Resolved){
             if (Reference || PHSP) yearsTmp.push_back("2015"); //Buggy 2015 MC
             yearsTmp.push_back("2016");
             if (!Reference){ //No reference channel for 2017 and 2018
                 if(Use2017) yearsTmp.push_back("2017");
                 if(Use2018) yearsTmp.push_back("2018");
             }
         }
         else if (Kst2Kspiplus){
             if (!Reference){ //no reference channel for Run II
                 yearsTmp.push_back("2015");
                 yearsTmp.push_back("2016");
                 if(Use2017) yearsTmp.push_back("2017");
                 if(Use2018) yearsTmp.push_back("2018");
             }
             if (Reference){ //@David TODO
                 yearsTmp.push_back("2016");
             }
         }
     }
     return yearsTmp;
 }
std::vector<string> yearsData (int Run = 1){
     std::vector<string> yearsTmp;
     if(Run != 1 && Run != 2 && Run !=12 ){
         std::cout << "[ERROR]\t\tInvalid Run number given: " << Run  << ". Exit program!" << std::endl;
         return yearsTmp;
     }
     if(Run == 1|| Run == 12) {
         yearsTmp.push_back("2011");
         yearsTmp.push_back("2012");
     }
     if(Run == 2|| Run == 12){
         yearsTmp.push_back("2015");
         yearsTmp.push_back("2016");
         yearsTmp.push_back("2017");
         yearsTmp.push_back("2018");
     }
     return yearsTmp;
 }
std::vector<string> yearsVector (bool MC = false, bool Reference = false, bool PHSP = false, int Run = 1){
     if (MC) return yearsMC(Reference,PHSP, Run);
     else return yearsData(Run);
 }

std::vector<int> yearsVectorInt(bool MC = false, bool Reference = false, bool PHSP = false, int Run = 1){

     std::vector<Int_t> yearsTmp;

     for (auto yr: yearsVector(MC,Reference,PHSP,Run))
         yearsTmp.push_back(stoi(yr));
     return yearsTmp;
 }

std::vector<string> yearsInc(int Run){
    std::vector<string> yearsTmp;
    if(Run != 1 && Run != 2 && Run !=12 ){
        std::cout << "[ERROR]\t\tInvalid Run number given: " << Run  << ". Exit program!" << std::endl;
        return yearsTmp;
    }
    if(Run == 1|| Run == 12) {
        yearsTmp.push_back("2011");
        yearsTmp.push_back("2012");
    }
    if(Run == 2|| Run == 12){
        yearsTmp.push_back("2016");
    }
    return yearsTmp;
}

std::vector<string> yearsBkgMC(bool Reference, bool B0, bool K1, bool Inc, int Run){
     std::vector<string> yearsTmp;
     if (B0){
         if(Run == 1|| Run == 12) {
             yearsTmp.push_back("2011");
             yearsTmp.push_back("2012");
         }
         if(Run == 2|| Run == 12){
             if (Kst2Kpluspi0Resolved){
                 yearsTmp.push_back("2015");
                 yearsTmp.push_back("2016");
             }
         }
     }
     else if (K1){
         if(Run == 1|| Run == 12) {
             if (!Reference) yearsTmp.push_back("2011");
             yearsTmp.push_back("2012");
         }
         if(Run == 2){
             coutWarning("No Run II BtoK1Jpsi no BtoK1MuMu sample!");
             coutERROR("Returning an empty vector.");
         }
     }
     else if (Inc){
         if (!Reference){
             coutWarning("No Run inclusive BtoXMuMu sample!");
             coutERROR("Returning an empty vector.");
         }
         if(Run == 1|| Run == 12) {
             yearsTmp.push_back("2011");
             yearsTmp.push_back("2012");
         }
         if(Run == 2|| Run == 12){
             if (Kst2Kpluspi0Resolved){
                 yearsTmp.push_back("2016");
             }
         }
     }
     else{
         coutERROR("No background sample selected! Choose between B0, K1 and inclusive samples!.");
         coutERROR("Returning an empty vector.");
     }
     return yearsTmp;
 }

int getRunID(string year){
    int RunID = -1;
    if (year == "2011" || year == "2012") RunID = 1;
    else  if (year == "2015" || year == "2016"|| year == "2017"|| year == "2018") RunID = 2;
    else coutERROR("Wrong year input!");
    return RunID;
}



#endif //GlobalFunctions
