int gammaJetHistogram(const TString configFile, const TString inputFile, const TString outputFile, const int nJobs, const int jobNum) {
    TH1::SetDefaultSumw2();

    std::cout << "running gammaJetHistogram()" << std::endl;
    std::cout << "configFile  = " << configFile.Data() << std::endl;
    std::cout << "inputFile   = " << inputFile.Data() << std::endl;
    std::cout << "outputFile  = " << outputFile.Data() << std::endl;

    InputConfiguration configInput = InputConfigurationParser::Parse(configFile.Data());
    CutConfiguration configCuts = CutConfigurationParser::Parse(configFile.Data());

    // input configuration
    if (!configInput.isValid) {
        std::cout << "Invalid input configuration" << std::endl;
        return 1;
    } else if (!configCuts.isValid) {
        std::cout << "Invalid cut configuration" << std::endl;
        return 1;
    }

    // input configuration
    // verbose about input configuration
    std::cout << "Input Configuration :" << std::endl;

    const int collision = configInput.proc[INPUT::kHISTOGRAM].i[INPUT::k_collisionType];
    const char* collisionName = getCollisionTypeName((COLL::TYPE)collision).c_str();
    std::cout << "collision = " << collisionName << std::endl;

    const bool isMC = collisionIsMC((COLL::TYPE)collision);
    const bool isHI = collisionIsHI((COLL::TYPE)collision);

    // observable bins
    std::vector<float> bins_pt[2];          // array of vectors for eta bins, each array element is a vector.
    std::vector<int>   bins_hiBin[2];       // array of vectors for hiBin bins, each array element is a vector.

    bins_pt[0] = ConfigurationParser::ParseListFloat(configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].s[CUTS::PHO::k_bins_pt_gt]);
    bins_pt[1] = ConfigurationParser::ParseListFloat(configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].s[CUTS::PHO::k_bins_pt_lt]);
    bins_hiBin[0] = ConfigurationParser::ParseListInteger(configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kEVENT].s[CUTS::EVT::k_bins_hiBin_gt]);
    bins_hiBin[1] = ConfigurationParser::ParseListInteger(configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kEVENT].s[CUTS::EVT::k_bins_hiBin_lt]);

    const int nSmearBins = configCuts.proc[CUTS::kSKIM].obj[CUTS::kJET].i[CUTS::JET::k_nSmearBins];

    // event cuts/weights
    // photon cuts
    const std::string trigger = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].s[CUTS::PHO::k_trigger_gammaJet].c_str();
    const float cut_phoHoverE = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].f[CUTS::PHO::k_phoHoverE];
    const float cut_phoSigmaIEtaIEta = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].f[CUTS::PHO::k_phoSigmaIEtaIEta];
    const float cut_sumIso = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].f[CUTS::PHO::k_sumIso];

    // jet cuts
    const std::string jetCollection = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kJET].s[CUTS::JET::k_jetCollection];
    const float cut_jetpt = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kJET].f[CUTS::JET::k_pt];
    const float cut_jeteta = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kJET].f[CUTS::JET::k_eta];
    const int   cut_jetID = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kJET].i[CUTS::JET::k_jetID];

    // gammaJet cuts
    const float cut_awayRange = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kGAMMAJET].f[CUTS::GJT::k_awayRange] * TMath::Pi();
    const float cut_dR = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kGAMMAJET].f[CUTS::GJT::k_dR];

    // process cuts
    const bool doPhotonEnergyScaleSystematics = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].i[CUTS::PHO::k_doPhotonEnergyScaleSystematics];
    const bool doElectronRejection = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].i[CUTS::PHO::k_doElectronRejection];
    const bool doPhotonIsolationSys = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].i[CUTS::PHO::k_doPhotonIsolationSys];
    const bool useCorrectedSumIso = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kPHOTON].i[CUTS::PHO::k_useCorrectedSumIso];

    const float smearingResJet = configCuts.proc[CUTS::kSKIM].obj[CUTS::kJET].f[CUTS::JET::k_smearingRes];
    const bool doSmearingRes = (smearingResJet > 0);
    const int sysUncFactor = 100;
    TRandom3 rand(12345);
    
    const int dphi_check = configCuts.proc[CUTS::kHISTOGRAM].obj[CUTS::kEVENT].i[CUTS::EVT::k_dphi_check];

    const int nBins_pt = bins_pt[0].size();         // assume <myvector>[0] and <myvector>[1] have the same size.
    const int nBins_hiBin = bins_hiBin[0].size();     // assume <myvector>[0] and <myvector>[1] have the same size.
    // verbose about cut configuration
    std::cout << "Cut Configuration :" << std::endl;
    std::cout << "nBins_pt = " << nBins_pt << std::endl;
    for (int i=0; i<nBins_pt; ++i)
        std::cout << Form("bins_pt[%d] = [%.1f, %.1f)", i, bins_pt[0][i], bins_pt[1][i]) << std::endl;
    std::cout << "nBins_hiBin = " << nBins_hiBin << std::endl;
    for (int i=0; i<nBins_hiBin; ++i)
        std::cout << Form("bins_hiBin[%d] = [%d, %d)", i, bins_hiBin[0][i], bins_hiBin[1][i]) << std::endl;

    std::cout << "trigger    = " << trigger.c_str() << std::endl;

    std::cout << "cut_phoHoverE             = " << cut_phoHoverE << std::endl;
    std::cout << "cut_phoSigmaIEtaIEta      = " << cut_phoSigmaIEtaIEta << std::endl;
    std::cout << "cut_sumIso                = " << cut_sumIso << std::endl;
    std::cout << "useCorrectedSumIso        = " << useCorrectedSumIso << std::endl;

    std::cout << "jetCollection             = " << jetCollection.c_str() << std::endl;
    std::cout << "cut_jetpt                 = " << cut_jetpt << std::endl;
    std::cout << "cut_jeteta                = " << cut_jeteta << std::endl;
    std::cout << "cut_jetID                 = " << cut_jetID << std::endl;

    std::cout << "cut_awayRange             = " << cut_awayRange << std::endl;
    std::cout << "cut_dR                    = " << cut_dR << std::endl;

    std::cout << "doPhotonEnergyScaleSystematics = " << doPhotonEnergyScaleSystematics << std::endl;
    std::cout << "doSmearingRes = " << doSmearingRes << std::endl;
    std::cout << "smearingResJet = " << smearingResJet << std::endl;

    /// Input Bookkeeping block ///
    TFile* input = TFile::Open(inputFile);

    TTree* tHlt = (TTree*)input->Get("hltTree");
    tHlt->SetBranchStatus("*", 0);
    tHlt->SetBranchStatus("HLT_HISinglePhoton40_Eta1p5_v1", 1);
    tHlt->SetBranchStatus("HLT_HISinglePhoton40_Eta1p5_v2", 1);
    tHlt->SetBranchStatus("HLT_HISinglePhoton50_Eta3p1_v1", 1);
    tHlt->SetBranchStatus("HLT_HISinglePhoton50_Eta3p1_v2", 1);
    tHlt->SetBranchStatus("HLT_HISinglePhoton40_Eta1p5ForPPRef_v1", 1);

    TTree* tPho = (TTree*)input->Get("EventTree");    // photons
    tPho->SetBranchStatus("*", 0);
    tPho->SetBranchStatus("phoEt", 1);
    tPho->SetBranchStatus("phoEtCorrected", 1);
    tPho->SetBranchStatus("phoEtCorrected_sys", 1);
    tPho->SetBranchStatus("phoEta", 1);
    tPho->SetBranchStatus("phoPhi", 1);
    tPho->SetBranchStatus("phoSigmaIEtaIEta_2012", 1);
    tPho->SetBranchStatus("pho_ecalClusterIsoR4", 1);
    tPho->SetBranchStatus("pho_hcalRechitIsoR4", 1);
    tPho->SetBranchStatus("pho_trackIsoR4PtCut20", 1);
    tPho->SetBranchStatus("pho_sumIsoCorrected", 1);
    tPho->SetBranchStatus("phoHoverE", 1);
    tPho->SetBranchStatus("phoE3x3", 1);
    tPho->SetBranchStatus("phoE5x5", 1);
    tPho->SetBranchStatus("phoE1x5", 1);
    tPho->SetBranchStatus("phoE2x5", 1);
    if (doElectronRejection) {
        tPho->SetBranchStatus("nEle", 1);
        tPho->SetBranchStatus("elePt", 1);
        tPho->SetBranchStatus("eleEta", 1);
        tPho->SetBranchStatus("elePhi", 1);
        tPho->SetBranchStatus("eleEoverP", 1);
    }
    if (isMC && doPhotonIsolationSys) {
        tPho->SetBranchStatus("nMC", 1);
        tPho->SetBranchStatus("mcPID", 1);
        tPho->SetBranchStatus("mcEta", 1);
        tPho->SetBranchStatus("mcPhi", 1);
        tPho->SetBranchStatus("mcCalIsoDR03", 1);
        tPho->SetBranchStatus("mcCalIsoDR04", 1);
        tPho->SetBranchStatus("pho_genMatchedIndex", 1);
    }

    TTree* tJet = (TTree*)input->Get(jetCollection.c_str());
    if (!tJet) {
        std::cout << "following jet collection is not found in the input file : " << jetCollection.c_str() << std::endl;
        std::cout << "exiting" << std::endl;
        return 1;
    }

    tJet->SetBranchStatus("*", 0);
    tJet->SetBranchStatus("nref", 1);
    tJet->SetBranchStatus("jtpt", 1);
    tJet->SetBranchStatus("jtpt_smeared", 1);
    // tJet->SetBranchStatus("jteta", 1);

    TTree* tHiEvt = (TTree*)input->Get("HiEvt");       // HiEvt tree will be placed in PP forest as well.

    ggHiNtuplizer pho;
    pho.setupTreeForReading(tPho);

    Jets jet;
    jet.setupTreeForReading(tJet);

    hiEvt evt;
    evt.setupTreeForReading(tHiEvt);

    Int_t HLT_HISinglePhoton40_Eta1p5_v1, HLT_HISinglePhoton40_Eta1p5_v2;
    Int_t HLT_HISinglePhoton50_Eta3p1_v1, HLT_HISinglePhoton50_Eta3p1_v2;
    Int_t HLT_HISinglePhoton40_Eta1p5ForPPRef_v1;
    tHlt->SetBranchAddress("HLT_HISinglePhoton40_Eta1p5_v1", &HLT_HISinglePhoton40_Eta1p5_v1);
    tHlt->SetBranchAddress("HLT_HISinglePhoton40_Eta1p5_v2", &HLT_HISinglePhoton40_Eta1p5_v2);
    tHlt->SetBranchAddress("HLT_HISinglePhoton50_Eta3p1_v1", &HLT_HISinglePhoton50_Eta3p1_v1);
    tHlt->SetBranchAddress("HLT_HISinglePhoton50_Eta3p1_v2", &HLT_HISinglePhoton50_Eta3p1_v2);
    tHlt->SetBranchAddress("HLT_HISinglePhoton40_Eta1p5ForPPRef_v1", &HLT_HISinglePhoton40_Eta1p5ForPPRef_v1);

    TTree* gammaJetTree[nSmearBins+1];
    gammaJetTree[0] = (TTree*)input->Get(Form("gamma_%s", jetCollection.c_str()));
    for (int i=0; i<nSmearBins; i++)
        gammaJetTree[i+1] = (TTree*)input->Get(Form("gamma_%s_smearBin%i", jetCollection.c_str(), i));

    GammaJet gammaJet[nSmearBins+1];
    for (int i=0; i<nSmearBins+1; i++)
        gammaJet[i].setupGammaJetTree(gammaJetTree[i]);

    TTree* jetTreeMB = 0;
    TTree* gammaJetTreeMB = 0;
    // check the existence of HI specific trees in "gammaJetSkim.root" file
    bool hasJetsMB = false;
    bool hasGammaJetMB = false;
    if (isHI) {
        input->GetObject(Form("%sMB", jetCollection.c_str()), jetTreeMB);
        input->GetObject(Form("gamma_%sMB", jetCollection.c_str()), gammaJetTreeMB);

        if (jetTreeMB)
            hasJetsMB = true;
        if (gammaJetTreeMB)
            hasGammaJetMB = true;
    }

    Jets jetMB;
    GammaJet gammaJetMB;
    if (hasJetsMB && hasGammaJetMB) {
        jetTreeMB->SetBranchStatus("*", 0);
        jetTreeMB->SetBranchStatus("jtpt", 1);
        jetTreeMB->SetBranchStatus("nref", 1);
        // jetTreeMB->SetBranchStatus("jteta", 1);

        jetMB.setupTreeForReading(jetTreeMB);
        gammaJetMB.setupGammaJetTree(gammaJetTreeMB);
    }

    // smearing set up block
    // ONLY used for JER systematic
    // WARNING make super sure this matches the values in gammaJetSkim.C !!
    // otherwise JER systematic will be off
    jetCorrector resolutionJetSmear[6];

    // smear 0-10 %
    std::vector<double> CSN_HI_cent0010 = {0.06, 1.23, 8.38};
    std::vector<double> CSN_phi_HI_cent0010 = {-3.18781/10000000, 0.125911, 2.23898};
    // smear 10-30 %
    std::vector<double> CSN_HI_cent1030 = {0.06, 1.23, 5.88};
    std::vector<double> CSN_phi_HI_cent1030 = {1.14344/100000, 0.179847, 1.56128};
    // smear 30-50 %
    std::vector<double> CSN_HI_cent3050 = {0.06, 1.23, 3.24};
    std::vector<double> CSN_phi_HI_cent3050 = {0.0145775, 0.1222, 1.21751};
    // smear 50-100 %
    std::vector<double> CSN_HI_cent50100 = {0.06, 1.23, 0};
    std::vector<double> CSN_phi_HI_cent50100 = {-0.0073078, 0.168879, 0.798885};

    // 0-30 and 30-100 are necessary only for smeared pp JER computation
    // smear 0-30 %
    std::vector<double> CSN_HI_cent0030 = {0.06, 1.23, 7.38};
    std::vector<double> CSN_phi_HI_cent0030 = {-1.303/1000000, 0.1651, 1.864};
    // smear 30-100 %
    std::vector<double> CSN_HI_cent30100 = {0.06, 1.23, 2.1};
    std::vector<double> CSN_phi_HI_cent30100 = {-2.013/100000000, 0.1646, 1.04};


    for (int i=0; i<6; ++i) {
        resolutionJetSmear[i].rand = rand;

        switch (i) {
        case 0: //0-10
            resolutionJetSmear[i].CSN_HI = CSN_HI_cent0010;
            resolutionJetSmear[i].CSN_phi_HI = CSN_phi_HI_cent0010;
            break;
        case 1: //10-30
            resolutionJetSmear[i].CSN_HI = CSN_HI_cent1030;
            resolutionJetSmear[i].CSN_phi_HI = CSN_phi_HI_cent1030;
            break;
        case 2: //30-50
            resolutionJetSmear[i].CSN_HI = CSN_HI_cent3050;
            resolutionJetSmear[i].CSN_phi_HI = CSN_phi_HI_cent3050;
            break;
        case 3: //50-100
            resolutionJetSmear[i].CSN_HI = CSN_HI_cent50100;
            resolutionJetSmear[i].CSN_phi_HI = CSN_phi_HI_cent50100;
            break;
        case 4: // 0-30, for smeared pp only
            resolutionJetSmear[i].CSN_HI = CSN_HI_cent0030;
            resolutionJetSmear[i].CSN_phi_HI = CSN_phi_HI_cent0030;
            break;
        case 5: // 30-100, for smeared pp only
            resolutionJetSmear[i].CSN_HI = CSN_HI_cent30100;
            resolutionJetSmear[i].CSN_phi_HI = CSN_phi_HI_cent30100;
            break;
        }
    }

    /// End Input Bookkeeping block //

    TFile* output = TFile::Open(outputFile, "RECREATE");
    // histograms will be put under a directory whose name is the type of the collision
    if (!output->GetKey(collisionName))
        output->mkdir(collisionName, Form("input file is %s", inputFile.Data()));
    output->cd(collisionName);
    std::cout << "histograms will be put under directory : " << collisionName << std::endl;

    TTree *configTree = setupConfigurationTreeForWriting(configCuts);

    int nCorrHist = correlationHistNames.size();
    correlationHist corrHists[nCorrHist][nBins_pt][nBins_hiBin];

    // prepare histogram names for xjg, abs(dphi) and jet pt
    for (int iHist=0; iHist<nCorrHist; ++iHist) {
        for (int i=0; i<nBins_pt; ++i) {
            for (int j=0; j<nBins_hiBin; ++j) {
                corrHists[iHist][i][j].name = Form("%s_ptBin%d_hiBin%d", correlationHistNames[iHist].c_str(), i, j);

                for (int iCorr = 0; iCorr < CORR::kN_CORRFNC; ++iCorr) {
                    for (int jCorr = 0; jCorr < CORR::kN_CORRFNC; ++jCorr) {
                        std::string subHistName = Form("%s_ptBin%d_hiBin%d_%s_%s", correlationHistNames[iHist].c_str(), i, j,
                                                       CORR::CORR_PHO_LABELS[iCorr].c_str(), CORR::CORR_JET_LABELS[jCorr].c_str());
                        corrHists[iHist][i][j].h1D_name[iCorr][jCorr] = subHistName.c_str();
                        corrHists[iHist][i][j].h1D[iCorr][jCorr] = new TH1D(Form("h1D_%s", subHistName.c_str()), "",
                                nBinsx[iHist], xlow[iHist], xup[iHist]);

                        corrHists[iHist][i][j].h1D_titleX[iCorr][jCorr] = correlationHistTitleX[iHist].c_str();
                        corrHists[iHist][i][j].h1D_titleY_final_norm[iCorr][jCorr] = correlationHistTitleY_final_normalized[iHist].c_str();
                    }
                }
            }
        }
    }

    // histograms to store the number of photon events, not photon-Jet event
    // those histograms have a single bin whose content is the number of photon events
    // they are just a tool to store number.
    TH1D* h_nPho[nBins_pt][nBins_hiBin][2];
    for (int i=0; i<nBins_pt; ++i) {
        for (int j=0; j<nBins_hiBin; ++j) {
            std::string histNamePhoRAW = Form("h_nPho_ptBin%d_hiBin%d_%s", i, j, CORR::CORR_PHO_LABELS[CORR::kRAW].c_str());
            h_nPho[i][j][CORR::kRAW] = new TH1D(histNamePhoRAW.c_str(), "", 1, 0, 1);

            std::string histNamePhoBKG = Form("h_nPho_ptBin%d_hiBin%d_%s", i, j, CORR::CORR_PHO_LABELS[CORR::kBKG].c_str());
            h_nPho[i][j][CORR::kBKG] = new TH1D(histNamePhoBKG.c_str(), "", 1, 0, 1);
        }
    }

    // selection for jet regions
    // jet from bkg region are already separated from raw region.
    // no additional selection for jets. just use different trees.
    std::cout << "####################" << std::endl;
    std::cout << "gammaJetTree->GetEntries() = " << gammaJetTree[0]->GetEntries() << std::endl;
    if (trigger.compare("") != 0 && !isMC)
        std::cout << "gammaJetTree->GetEntries(trigger==1) = " << tHlt->GetEntries(Form("%s == 1", trigger.c_str())) << std::endl;
    else
        std::cout << "gammaJetTree->GetEntries(trigger==1) is skipped because either no trigger is specified or the data is coming from MC." << std::endl;
    std::cout << "####################" << std::endl;

    long long nentries = gammaJetTree[0]->GetEntries();
    long long firstEntry = 0;
    long long lastEntry = nentries;
    std::cout << "Total Entries: " << nentries << std::endl;

    if (nJobs != -1) {
        if (jobNum >= nJobs) {
            std::cout << "jobNum > nJobs, invalid configuration, aborting" << std::endl;
            return 1;
        }

        firstEntry = floor(nentries/nJobs)*jobNum;
        lastEntry = floor(nentries/nJobs)*(jobNum+1);
        if (jobNum == nJobs-1)
            lastEntry = nentries;

        std::cout << "For this job " << jobNum << std::endl;
        std::cout << "First Entry: " << firstEntry << std::endl;
        std::cout << "Final Entry: " << lastEntry << std::endl;
    }

    for (long long jentry = firstEntry; jentry < lastEntry; jentry++) {
        if (jentry % 2000 == 0 && nJobs == -1)
            printf("current entry = %lli out of %lli : %3f%%\n", jentry, nentries, (double)jentry/nentries*100);

        tHlt->GetEntry(jentry);
        // event selection
        if (!isMC && !HLT_HISinglePhoton40_Eta1p5_v1)
            continue;
        if (isHI && isMC && !HLT_HISinglePhoton40_Eta1p5_v2)
            continue;
        if (!isHI && isMC && !HLT_HISinglePhoton40_Eta1p5ForPPRef_v1)
            continue;

        tPho->GetEntry(jentry);
        gammaJetTree[0]->GetEntry(jentry);

        // eta cut moved to skim step
        // if (TMath::Abs((*pho.phoEta)[gammaJet[0].phoIdx]) > 1.44) continue;

        // noise cut
        if (((*pho.phoE3x3)[gammaJet[0].phoIdx]/(*pho.phoE5x5)[gammaJet[0].phoIdx] > 2./3.-0.03 &&
             (*pho.phoE3x3)[gammaJet[0].phoIdx]/(*pho.phoE5x5)[gammaJet[0].phoIdx] < 2./3.+0.03) &&
            ((*pho.phoE1x5)[gammaJet[0].phoIdx]/(*pho.phoE5x5)[gammaJet[0].phoIdx] > 1./3.-0.03 &&
             (*pho.phoE1x5)[gammaJet[0].phoIdx]/(*pho.phoE5x5)[gammaJet[0].phoIdx] < 1./3.+0.03) &&
            ((*pho.phoE2x5)[gammaJet[0].phoIdx]/(*pho.phoE5x5)[gammaJet[0].phoIdx] > 2./3.-0.03 &&
             (*pho.phoE2x5)[gammaJet[0].phoIdx]/(*pho.phoE5x5)[gammaJet[0].phoIdx] < 2./3.+0.03)) continue;

        // isolation cut
        if (useCorrectedSumIso) {
            if ((*pho.pho_sumIsoCorrected)[gammaJet[0].phoIdx] > cut_sumIso) {
                continue;
            }
        } else if (((*pho.pho_ecalClusterIsoR4)[gammaJet[0].phoIdx] +
                    (*pho.pho_hcalRechitIsoR4)[gammaJet[0].phoIdx] +
                    (*pho.pho_trackIsoR4PtCut20)[gammaJet[0].phoIdx]) > cut_sumIso) {
            continue;
        }

        if ((*pho.phoHoverE)[gammaJet[0].phoIdx] > 0.1)
            continue;

        bool isSignalPho = ((*pho.phoSigmaIEtaIEta_2012)[gammaJet[0].phoIdx] < cut_phoSigmaIEtaIEta);
        bool isBkgPho = ((*pho.phoSigmaIEtaIEta_2012)[gammaJet[0].phoIdx] > 0.011 &&
                         (*pho.phoSigmaIEtaIEta_2012)[gammaJet[0].phoIdx] < 0.017);

        if (!(isSignalPho || isBkgPho))
            continue;

        int phoType = isSignalPho ? CORR::kRAW : CORR::kBKG;

        // reco electron rejection part
        bool isEle = false;
        if (doElectronRejection) {
            float eleEpTemp = 100.0;
            for (int ie=0; ie<pho.nEle; ++ie) {
                if ((*pho.elePt)[ie] < 10)
                    continue;
                if (abs((*pho.eleEta)[ie] - (*pho.phoEta)[gammaJet[0].phoIdx]) > 0.03) // deta
                    continue;
                if (abs(getDPHI((*pho.elePhi)[ie], (*pho.phoPhi)[gammaJet[0].phoIdx])) > 0.03) // dphi
                    continue;
                if (eleEpTemp < pho.eleEoverP->at(ie))
                    continue;

                isEle = true;
                break;
            }
        }
        if (isEle)
            continue;

        // photon isolation systematic part (gen matching & genIso condition)
        if (isMC && doPhotonIsolationSys) {
            if (!(((*pho.pho_genMatchedIndex)[gammaJet[0].phoIdx]!=-1) && (pho.mcCalIsoDR04->at((*pho.pho_genMatchedIndex)[gammaJet[0].phoIdx])<5.0))) {
                // std::cout << "failedGenIso : mcCalIso = " << (pho.mcCalIsoDR04->at((*pho.pho_genMatchedIndex)[gammaJet[0].phoIdx]))<< std::endl;
                continue;
            }
        }

        tJet->GetEntry(jentry);
        tHiEvt->GetEntry(jentry);

        float weight = isMC ? evt.weight : 1;
        float phoEt = doPhotonEnergyScaleSystematics ? (*pho.phoEtCorrected_sys)[gammaJet[0].phoIdx] : (*pho.phoEtCorrected)[gammaJet[0].phoIdx];

        // handle nEntriesPho separate from jet loop
        for (int i=0; i<nBins_pt; ++i) {
            if (phoEt <  bins_pt[0][i] || phoEt >= bins_pt[1][i])
                continue;
            for (int j=0; j<nBins_hiBin; ++j) {
                if (isHI && (evt.hiBin <  bins_hiBin[0][j] || evt.hiBin >= bins_hiBin[1][j]))
                    continue;
                for (int iHist = 0; iHist < nCorrHist; iHist++)
                    corrHists[iHist][i][j].nEntriesPho[phoType][CORR::kRAW] += weight;
            }
        }

        if(doSmearingRes)
            weight /= sysUncFactor;

        for (int j=0; j<nBins_hiBin; ++j) {
            int smearBin = 0;
            if (isHI) {
                if (evt.hiBin <  bins_hiBin[0][j] || evt.hiBin >= bins_hiBin[1][j])
                    continue;
            } else {
                if (j) {
                    // change smearBin to select the smeared jtpt and jtphi corresponding to the centrality bin
                    // 0 is unsmeared jtpt
                    smearBin = j;
                }

                if (smearBin)
                    gammaJetTree[smearBin]->GetEntry(jentry);
            }

            for (int ijet = 0; ijet < jet.nref; ijet++) {
                int multiplyJets = 1;
                if(doSmearingRes)
                    multiplyJets = sysUncFactor;
                for(int iResSmear = 0; iResSmear < multiplyJets; iResSmear++){
                    float jetpt = (*jet.jtpt_smeared)[smearBin][ijet];
                    float smearFactor = 1;
                    if(doSmearingRes) {
                        //smearFactor = rand.Gaus(1,smearingResJet);
                        float SF = 1 + smearingResJet;
                        int resolutionBin = 0;
                        if(isHI) {
                            resolutionBin = getResolutionBin(evt.hiBin);
                        } else {
                            resolutionBin = getResolutionBinPP(smearBin);
                        }
                        float initialResolution = resolutionJetSmear[resolutionBin].getResolutionHI(jetpt);
                        smearFactor = rand.Gaus(1, SF * initialResolution * sqrt(SF*SF - 1));
                        jetpt *= smearFactor;
                    }
                    // jet cuts
                    // jteta cut moved to skim
                    // if (TMath::Abs(jet.jteta[ijet]) > cut_jeteta) continue;
                    if ((*gammaJet[0].jetID)[ijet] < cut_jetID)
                        continue;
                    if (jetpt < cut_jetpt)
                        continue;
                    if ((*gammaJet[smearBin].dR)[ijet] < cut_dR)
                        continue;

                    for (int i=0; i<nBins_pt; ++i) {
                        if (phoEt <  bins_pt[0][i] || phoEt >= bins_pt[1][i])
                            continue;

                        // fill histograms
                        // dphi = 1
                        corrHists[1][i][j].h1D[phoType][CORR::kRAW]->Fill(TMath::Abs((*gammaJet[smearBin].dphi)[ijet]), weight);
                        corrHists[1][i][j].nEntries[phoType][CORR::kRAW] += weight;
                        
                        //apply dphi cuts now
                        if (TMath::Abs((*gammaJet[smearBin].dphi)[ijet]) <= cut_awayRange)
                            continue;
                        // xjg = 0
                        // jtpt = 2
                        float xjg = doPhotonEnergyScaleSystematics ? (*gammaJet[smearBin].xjgCorrected_sys)[ijet] : (*gammaJet[smearBin].xjgCorrected)[ijet];
                        if(doSmearingRes){
                            xjg *= smearFactor;
                        }
                        corrHists[0][i][j].h1D[phoType][CORR::kRAW]->Fill(xjg, weight);
                        corrHists[0][i][j].nEntries[phoType][CORR::kRAW] += weight;
                        corrHists[2][i][j].h1D[phoType][CORR::kRAW]->Fill(jetpt, weight);
                        corrHists[2][i][j].nEntries[phoType][CORR::kRAW] += weight;
                    }
                }
            }
        }

        if (dphi_check && isHI) {
            for (int ijet = 0; ijet < jet.nref; ijet++) {
                for (int j=0; j<nBins_hiBin; ++j) {
                    if (evt.hiBin <  bins_hiBin[0][j] || evt.hiBin >= bins_hiBin[1][j])
                        continue;
                    if (jet.jtpt[ijet] < cut_jetpt)
                        continue;
                    if ((*gammaJet[0].dR)[ijet] < cut_dR)
                        continue;

                    for (int i=0; i<nBins_pt; ++i) {
                        if ((*pho.phoEtCorrected)[gammaJet[0].phoIdx] <  bins_pt[0][i] ||
                            (*pho.phoEtCorrected)[gammaJet[0].phoIdx] >= bins_pt[1][i]) continue;

                        float lower_sideband = 1;
                        float upper_sideband = TMath::Pi()/2;
                        float sideband_width = upper_sideband - lower_sideband;

                        // select dphi sideband region
                        if (TMath::Abs((*gammaJet[0].dphi)[ijet]) > upper_sideband || TMath::Abs((*gammaJet[0].dphi)[ijet]) < lower_sideband)
                            continue;

                        corrHists[1][i][j].h1D[phoType][CORR::kBKG]->Fill((TMath::Abs((*gammaJet[0].dphi)[ijet])-lower_sideband)*(TMath::Pi()/sideband_width), weight*40*(TMath::Pi()/sideband_width));
                        corrHists[1][i][j].nEntries[phoType][CORR::kBKG] += weight*40*(TMath::Pi()/sideband_width);

                        corrHists[0][i][j].h1D[phoType][CORR::kBKG]->Fill((*gammaJet[0].xjgCorrected)[ijet], weight*40*(TMath::Pi()/8/sideband_width));
                        corrHists[0][i][j].nEntries[phoType][CORR::kBKG] += weight*40*(TMath::Pi()/8/sideband_width);
                        corrHists[2][i][j].h1D[phoType][CORR::kBKG]->Fill(jet.jtpt[ijet], weight*40*(TMath::Pi()/8/sideband_width));
                        corrHists[2][i][j].nEntries[phoType][CORR::kBKG] += weight*40*(TMath::Pi()/8/sideband_width);
                    }
                }
            }
        } else {
            if (hasJetsMB && hasGammaJetMB) {
                jetTreeMB->GetEntry(jentry);
                gammaJetTreeMB->GetEntry(jentry);

                for (int ijet = 0; ijet < jetMB.nref; ijet++) {
                    int multiplyJets = 1;
                    if(doSmearingRes)
                        multiplyJets = sysUncFactor;
                    for(int iResSmear = 0; iResSmear < multiplyJets; iResSmear++){
                        float jetpt = jetMB.jtpt[ijet];
                        float smearFactor = 1;
                        if(doSmearingRes) {
                            //smearFactor = rand.Gaus(1,smearingResJet);
                            float SF = 1 + smearingResJet;
                            int resolutionBin = 0;
                            resolutionBin = getResolutionBin(evt.hiBin);
                            float initialResolution = resolutionJetSmear[resolutionBin].getResolutionHI(jetpt);
                            smearFactor = rand.Gaus(1, SF * initialResolution * sqrt(SF*SF - 1));
                            jetpt *= smearFactor;
                        }

                        // jet cuts
                        if ((*gammaJetMB.dR)[ijet] < cut_dR)
                            continue;
                        // jteta cut moved to skim
                        // if (TMath::Abs(jetMB.jteta[ijet]) > cut_jeteta) continue;
                        if (jetpt < cut_jetpt)
                            continue;
                        if ((*gammaJetMB.jetID)[ijet] < cut_jetID)
                            continue;

                        for (int i=0; i<nBins_pt; ++i) {
                            if ((*pho.phoEtCorrected)[gammaJetMB.phoIdx] <  bins_pt[0][i] ||
                                (*pho.phoEtCorrected)[gammaJetMB.phoIdx] >= bins_pt[1][i]) continue;
                            for (int j=0; j<nBins_hiBin; ++j) {
                                if (evt.hiBin <  bins_hiBin[0][j] || evt.hiBin >= bins_hiBin[1][j])
                                    continue;

                                // fill histograms
                                // dphi = 1
                                corrHists[1][i][j].h1D[phoType][CORR::kBKG]->Fill(TMath::Abs((*gammaJetMB.dphi)[ijet]), weight);
                                corrHists[1][i][j].nEntries[phoType][CORR::kBKG] += weight;
                                // apply dphi cuts now
                                if (TMath::Abs((*gammaJetMB.dphi)[ijet]) <= cut_awayRange)
                                    continue;
                                // xjg = 0
                                // jtpt = 2
                                float xjg = doPhotonEnergyScaleSystematics ? (*gammaJetMB.xjgCorrected_sys)[ijet] : (*gammaJetMB.xjgCorrected)[ijet];
                                if(doSmearingRes){
                                    xjg *= smearFactor;
                                }
                                corrHists[0][i][j].h1D[phoType][CORR::kBKG]->Fill(xjg, weight);
                                corrHists[0][i][j].nEntries[phoType][CORR::kBKG] += weight;
                                corrHists[2][i][j].h1D[phoType][CORR::kBKG]->Fill(jetpt, weight);
                                corrHists[2][i][j].nEntries[phoType][CORR::kBKG] += weight;
                            }
                        }
                    }
                }
            }
        }
    }

    /// Histogram arithmetic (no reading I/O)
    for (int iHist = 0; iHist < nCorrHist; iHist++) {
        for (int i=0; i<nBins_pt; ++i) {
            for (int j=0; j<nBins_hiBin; ++j) {
                corrHists[iHist][i][j].nEntriesPho[CORR::kRAW][CORR::kBKG] = corrHists[iHist][i][j].nEntriesPho[CORR::kRAW][CORR::kRAW];
                corrHists[iHist][i][j].nEntriesPho[CORR::kBKG][CORR::kBKG] = corrHists[iHist][i][j].nEntriesPho[CORR::kBKG][CORR::kRAW];

                if (h_nPho[i][j][CORR::kRAW]->GetBinContent(1) == 0) {
                    h_nPho[i][j][CORR::kRAW]->SetBinContent(1, corrHists[iHist][i][j].nEntriesPho[CORR::kRAW][CORR::kRAW]);
                    h_nPho[i][j][CORR::kRAW]->Write("", TObject::kOverwrite);
                }

                if (h_nPho[i][j][CORR::kBKG]->GetBinContent(1) == 0) {
                    h_nPho[i][j][CORR::kBKG]->SetBinContent(1, corrHists[iHist][i][j].nEntriesPho[CORR::kBKG][CORR::kRAW]);
                    h_nPho[i][j][CORR::kBKG]->Write("", TObject::kOverwrite);
                }

                std::cout << "nEntries[CORR::kRAW][CORR::kRAW] = " << corrHists[iHist][i][j].nEntries[CORR::kRAW][CORR::kRAW] << std::endl;
                std::cout << "nEntries[CORR::kBKG][CORR::kRAW] = " << corrHists[iHist][i][j].nEntries[CORR::kBKG][CORR::kRAW] << std::endl;
                std::cout << "nEntriesPho[CORR::kRAW][CORR::kRAW] = " << corrHists[iHist][i][j].nEntriesPho[CORR::kRAW][CORR::kRAW] << std::endl;
                std::cout << "nEntriesPho[CORR::kBKG][CORR::kRAW] = " << corrHists[iHist][i][j].nEntriesPho[CORR::kBKG][CORR::kRAW] << std::endl;

                std::string histoTitle;
                if (bins_pt[1][i] == 9999 && bins_hiBin[0][j] <= 0 && bins_hiBin[1][j] >= 200)
                    histoTitle = Form("%s , p^{#gamma}_{T} > %.0f GeV/c", collisionName , bins_pt[0][i]);
                else if (bins_hiBin[0][j] <= 0 && bins_hiBin[1][j] >= 200)
                    histoTitle = Form("%s , %.0f < p^{#gamma}_{T} < %.0f GeV/c", collisionName , bins_pt[0][i], bins_pt[1][i]);
                else if (bins_pt[1][i] == 9999)
                    histoTitle = Form("%s , p^{#gamma}_{T} > %.0f GeV/c, %d-%d %% ", collisionName , bins_pt[0][i], bins_hiBin[0][j]/2, bins_hiBin[1][j]/2);
                else
                    histoTitle = Form("%s , %.0f < p^{#gamma}_{T} < %.0f GeV/c, %d-%d %% ", collisionName , bins_pt[0][i], bins_pt[1][i], bins_hiBin[0][j]/2, bins_hiBin[1][j]/2);

                // histograms for RAW and BKG regions
                for (int iCorr = 0; iCorr < CORR::kN_CORRFNC-1; ++iCorr) {
                    for (int jCorr = 0; jCorr < CORR::kN_CORRFNC-1; ++jCorr) {
                        if (jCorr == CORR::kBKG && !isHI) continue;      // no jet background for non-HI

                        std::string titleX = corrHists[iHist][i][j].h1D_titleX[iCorr][jCorr].c_str();
                        corrHists[iHist][i][j].h1D[iCorr][jCorr]->SetTitle(Form("%s;%s;%s", histoTitle.c_str(), titleX.c_str(), "Entries"));
                        corrHists[iHist][i][j].h1D[iCorr][jCorr]->SetMarkerStyle(kFullCircle);
                        corrHists[iHist][i][j].h1D[iCorr][jCorr]->SetMarkerColor(kBlack);

                        // histogram name excluding the "h1D" prefix
                        std::string tmpH1D_name = corrHists[iHist][i][j].h1D_name[iCorr][jCorr].c_str();
                        std::string tmpHistName = corrHists[iHist][i][j].h1D[iCorr][jCorr]->GetName();

                        corrHists[iHist][i][j].h1D[iCorr][jCorr]->Write("", TObject::kOverwrite);
                    }
                }
            }
        }
    }

    configTree->Write("", TObject::kOverwrite);

    output->Write("", TObject::kOverwrite);
    input->Close();
    output->Close();

    return 0;
}
Ejemplo n.º 2
0
int makeWJetAnaSkim(std::string fList = "", sampleType sType = kHIDATA, Int_t num = 0)
{
  //Define MC or Data
  Bool_t montecarlo = isMonteCarlo(sType);
  Bool_t hi = isHI(sType);

  std::cout << sType << std::endl;
  std::cout << montecarlo << std::endl;

  std::string buffer;
  std::vector<std::string> listOfFiles;
  int nLines = 0;
  ifstream inFile(fList.data());

  std::cout << fList << std::endl;
  std::cout << inFile.is_open() << std::endl;

  if(!inFile.is_open()){
    std::cout << "Error opening file. Exiting." <<std::endl;
    return 1;
  }
  else{
    while(true){
      inFile >> buffer;
      if(inFile.eof()) break;
      listOfFiles.push_back(buffer);
      nLines++;
    }
  }

  std::cout << "FileList Loaded" << std::endl;

  std::cout << "FileJob: " << listOfFiles[num] << std::endl;

  TFile* iniSkim_p = new TFile(listOfFiles[num].data(), "READ");

  GetWJetIniSkim(iniSkim_p, sType);

  std::cout << "IniSkim Loaded" << std::endl;
  
  std::string outName = listOfFiles[num];
  const std::string cutString = "/";
  const std::string iniString = "Ini";
  std::size_t strIndex = 0;

  std::cout << "Cull string" << std::endl;

  while(true){
    strIndex = outName.find(cutString);

    if(strIndex == std::string::npos) break;

    outName.replace(0, strIndex + 1, "");
  }

  std::cout << "Replace string" << std::endl;

  strIndex = outName.find(iniString);
  if(!(strIndex == std::string::npos)){
    outName.replace(strIndex, iniString.length(), "Ana"); 
  }

  std::cout << "Output name: " << outName.c_str() << std::endl;
  TFile *outFile = new TFile(outName.c_str(), "RECREATE");
  InitWJetAnaSkim(sType);

  Long64_t nentries = jetTreeIni_p->GetEntries();

  std::cout << nentries << std::endl;

  Float_t prevLeptPt = 0;
  Float_t prevLeptVsPt = 0;
  Float_t prevLeptPhi = 0;
  Float_t prevLeptEta = 0;

  for(Long64_t jentry = 0; jentry < nentries; jentry++){
    trackTreeIni_p->GetEntry(jentry);
    pfCandTreeIni_p->GetEntry(jentry);
    jetTreeIni_p->GetEntry(jentry);
    if(montecarlo) genTreeIni_p->GetEntry(jentry);

    if(jentry%1000 == 0) std::cout << jentry << std::endl;

    InitAnaVar();

    run_ = runIni_;
    evt_ = evtIni_;
    lumi_ = lumiIni_;

    if(montecarlo) pthat_ = pthatIni_;
    
    if(hi){
      hiBin_ = hiBinIni_;
      hiEvtPlane_ = hiEvtPlaneIni_;
      psin_ = psinIni_;
    }


    for(Int_t iter = 0; iter < nPF_; iter++){
      pfEvtPtSum_[0] += pfPt_[iter]*TMath::Cos(pfPhi_[iter]);
      pfEvtPtSum_[1] += pfPt_[iter]*TMath::Sin(pfPhi_[iter]);

      if(hi){
	pfEvtVsPtSum_[0] += pfVsPt_[iter]*TMath::Cos(pfPhi_[iter]);
	pfEvtVsPtSum_[1] += pfVsPt_[iter]*TMath::Sin(pfPhi_[iter]);
      }

      if(pfPt_[iter] > leptPtCut && TMath::Abs(pfEta_[iter]) < leptEtaCut){
	if(TMath::Abs(pfId_[iter]) == 3 && pfPt_[iter] > muonPt_){
	  muonPt_ = pfPt_[iter];
	  if(hi) muonVsPt_ = pfVsPt_[iter];
	  muonPhi_ = pfPhi_[iter];
	  muonEta_ = pfEta_[iter];
	}

	if(TMath::Abs(pfId_[iter]) == 2 && pfPt_[iter] > electronPt_ && (TMath::Abs(pfEta_[iter]) < 0.80 || TMath::Abs(pfEta_[iter]) > 1.4)){
	  electronPt_ = pfPt_[iter];
	  if(hi) electronVsPt_ = pfVsPt_[iter];
	  electronPhi_ = pfPhi_[iter];
	  electronEta_ = pfEta_[iter];
	}
      }
    }

    if(electronPt_ > muonPt_){
      leptPt_ = electronPt_;
      if(hi) leptVsPt_ = electronVsPt_;
      leptPhi_ = electronPhi_;
      leptEta_ = electronEta_;
    }
    else if(muonPt_ > electronPt_){
      leptPt_ = muonPt_;
      if(hi) leptVsPt_ = muonVsPt_;
      leptPhi_ = muonPhi_;
      leptEta_ = muonEta_;
    }

    for(Int_t iter = 0; iter < nPF_; iter++){
      if(TMath::Abs(pfId_[iter]) != 2 && TMath::Abs(pfId_[iter]) != 3 && pfPt_[iter] > check1Pt_){
	if(getDR(leptEta_, leptPhi_, pfEta_[iter], pfPhi_[iter]) > 0.5){
	  check1Pt_ = pfPt_[iter];
	  if(hi) check1VsPt_ = pfVsPt_[iter];
	  check1Phi_ = pfPhi_[iter];
	  check1Eta_ = pfEta_[iter];
	}
      }
    }

    check2Pt_ = prevLeptPt;
    if(hi) check2VsPt_ = prevLeptVsPt;
    check2Phi_ = prevLeptPhi;
    check2Eta_ = prevLeptEta;

    prevLeptPt = leptPt_;
    if(hi) prevLeptVsPt = leptVsPt_;
    prevLeptPhi = leptPhi_;
    prevLeptEta = leptEta_;

    for(Int_t iter = 0; iter < nTrk_; iter++){
      trkEvtPtSum_[0] += trkPt_[iter]*TMath::Cos(trkPhi_[iter]);
      trkEvtPtSum_[1] += trkPt_[iter]*TMath::Sin(trkPhi_[iter]);

      if(trkPt_[iter] > trkPtCut){
	trkCutEvtPtSum_[0] += trkPt_[iter]*TMath::Cos(trkPhi_[iter]);
	trkCutEvtPtSum_[1] += trkPt_[iter]*TMath::Sin(trkPhi_[iter]);
      }
    }

    if(leptPt_ > 0){    
      pfEvtPtMag_ = TMath::Sqrt(pfEvtPtSum_[0]*pfEvtPtSum_[0] + pfEvtPtSum_[1]*pfEvtPtSum_[1]);
      pfEvtPhi_ = TMath::ATan2(pfEvtPtSum_[1], pfEvtPtSum_[0]);
      pfNeuPhi_ = TMath::ATan2(-pfEvtPtSum_[1], -pfEvtPtSum_[0]);
      pfMt_ = TMath::Sqrt(2*leptPt_*pfEvtPtMag_*(1 - TMath::Cos(getDPHI(leptPhi_, pfNeuPhi_))));
      pfWPtSum_[0] = leptPt_*TMath::Cos(leptPhi_) - pfEvtPtSum_[0];
      pfWPtSum_[1] = leptPt_*TMath::Sin(leptPhi_) - pfEvtPtSum_[1];
      pfWPtMag_ = TMath::Sqrt(pfWPtSum_[0]*pfWPtSum_[0] + pfWPtSum_[1]*pfWPtSum_[1]);
      pfWPhi_ = TMath::ATan2(pfWPtSum_[1], pfWPtSum_[0]);

      if(hi){
	pfEvtVsPtMag_ = TMath::Sqrt(pfEvtVsPtSum_[0]*pfEvtVsPtSum_[0] + pfEvtVsPtSum_[1]*pfEvtVsPtSum_[1]);
	pfEvtVsPhi_ = TMath::ATan2(pfEvtVsPtSum_[1], pfEvtVsPtSum_[0]);
	pfVsNeuPhi_ = TMath::ATan2(-pfEvtVsPtSum_[1], -pfEvtVsPtSum_[0]);
	pfVsMt_ = TMath::Sqrt(2*leptPt_*pfEvtVsPtMag_*(1 - TMath::Cos(getDPHI(leptPhi_, pfVsNeuPhi_))));
	pfVsWPtSum_[0] = leptPt_*TMath::Cos(leptPhi_) - pfEvtVsPtSum_[0];
	pfVsWPtSum_[1] = leptPt_*TMath::Sin(leptPhi_) - pfEvtVsPtSum_[1];
	pfVsWPtMag_ = TMath::Sqrt(pfVsWPtSum_[0]*pfVsWPtSum_[0] + pfVsWPtSum_[1]*pfVsWPtSum_[1]);
	pfVsWPhi_ = TMath::ATan2(pfVsWPtSum_[1], pfVsWPtSum_[0]);
      }

      trkEvtPtMag_ = TMath::Sqrt(trkEvtPtSum_[0]*trkEvtPtSum_[0] + trkEvtPtSum_[1]*trkEvtPtSum_[1]);
      trkEvtPhi_ = TMath::ATan2(trkEvtPtSum_[1], trkEvtPtSum_[0]);
      trkNeuPhi_ = TMath::ATan2(-trkEvtPtSum_[1], -trkEvtPtSum_[0]);
      trkMt_ = TMath::Sqrt(2*leptPt_*trkEvtPtMag_*(1 - TMath::Cos(getDPHI(leptPhi_, trkNeuPhi_))));
      trkWPtSum_[0] = leptPt_*TMath::Cos(leptPhi_) - trkEvtPtSum_[0];
      trkWPtSum_[1] = leptPt_*TMath::Sin(leptPhi_) - trkEvtPtSum_[1];
      trkWPtMag_ = TMath::Sqrt(trkWPtSum_[0]*trkWPtSum_[0] + trkWPtSum_[1]*trkWPtSum_[1]);
      trkWPhi_ = TMath::ATan2(trkWPtSum_[1], trkWPtSum_[0]);

      trkCutEvtPtMag_ = TMath::Sqrt(trkCutEvtPtSum_[0]*trkCutEvtPtSum_[0] + trkCutEvtPtSum_[1]*trkCutEvtPtSum_[1]);
      trkCutEvtPhi_ = TMath::ATan2(trkCutEvtPtSum_[1], trkCutEvtPtSum_[0]);
      trkCutNeuPhi_ = TMath::ATan2(-trkCutEvtPtSum_[1], -trkCutEvtPtSum_[0]);
      trkCutMt_ = TMath::Sqrt(2*leptPt_*trkCutEvtPtMag_*(1 - TMath::Cos(getDPHI(leptPhi_, trkCutNeuPhi_))));
      trkCutWPtSum_[0] = leptPt_*TMath::Cos(leptPhi_) - trkCutEvtPtSum_[0];
      trkCutWPtSum_[1] = leptPt_*TMath::Sin(leptPhi_) - trkCutEvtPtSum_[1];
      trkCutWPtMag_ = TMath::Sqrt(trkCutWPtSum_[0]*trkCutWPtSum_[0] + trkCutWPtSum_[1]*trkCutWPtSum_[1]);
      trkCutWPhi_ = TMath::ATan2(trkCutWPtSum_[1], trkCutWPtSum_[0]);
    }
    if(check1Pt_ > 0){
      pfCheck1Mt_ = TMath::Sqrt(2*check1Pt_*pfEvtPtMag_*(1 - TMath::Cos(getDPHI(check1Phi_, pfNeuPhi_))));
      if(hi) pfVsCheck1Mt_ = TMath::Sqrt(2*check1Pt_*pfEvtVsPtMag_*(1 - TMath::Cos(getDPHI(check1Phi_, pfVsNeuPhi_))));
      trkCheck1Mt_ = TMath::Sqrt(2*check1Pt_*trkEvtPtMag_*(1 - TMath::Cos(getDPHI(check1Phi_, trkNeuPhi_))));
      trkCutCheck1Mt_ = TMath::Sqrt(2*check1Pt_*trkCutEvtPtMag_*(1 - TMath::Cos(getDPHI(check1Phi_, trkCutNeuPhi_))));
    }
    if(check2Pt_ > 0){
      pfCheck2Mt_ = TMath::Sqrt(2*check2Pt_*pfEvtPtMag_*(1 - TMath::Cos(getDPHI(check2Phi_, pfNeuPhi_))));
      if(hi) pfVsCheck2Mt_ = TMath::Sqrt(2*check2Pt_*pfEvtVsPtMag_*(1 - TMath::Cos(getDPHI(check2Phi_, pfVsNeuPhi_))));
      trkCheck2Mt_ = TMath::Sqrt(2*check2Pt_*trkEvtPtMag_*(1 - TMath::Cos(getDPHI(check2Phi_, trkNeuPhi_))));
      trkCutCheck2Mt_ = TMath::Sqrt(2*check2Pt_*trkCutEvtPtMag_*(1 - TMath::Cos(getDPHI(check2Phi_, trkCutNeuPhi_))));
    }

    Float_t dummyArr[2];

    getJtVar(nVs3Calo_, Vs3CaloPt_, Vs3CaloPhi_, Vs3CaloEta_, Vs3CaloRefPt_, Vs3CaloRefPhi_, Vs3CaloRefEta_, 0, montecarlo, false);
    getJtVar(nVs4Calo_, Vs4CaloPt_, Vs4CaloPhi_, Vs4CaloEta_, Vs4CaloRefPt_, Vs4CaloRefPhi_, Vs4CaloRefEta_, 1, montecarlo, false);
    getJtVar(nVs5Calo_, Vs5CaloPt_, Vs5CaloPhi_, Vs5CaloEta_, Vs5CaloRefPt_, Vs5CaloRefPhi_, Vs5CaloRefEta_, 2, montecarlo, false);
    getJtVar(nT3_, T3Pt_, T3Phi_, T3Eta_, dummyArr, dummyArr, dummyArr, 3, montecarlo, true);
    getJtVar(nT4_, T4Pt_, T4Phi_, T4Eta_, dummyArr, dummyArr, dummyArr, 4, montecarlo, true);
    getJtVar(nT5_, T5Pt_, T5Phi_, T5Eta_, dummyArr, dummyArr, dummyArr, 5, montecarlo, true);

    trackTreeAna_p->Fill();
    pfCandTreeAna_p->Fill();
    jetTreeAna_p->Fill();
    if(montecarlo) genTreeAna_p->Fill();
  }
  
  outFile->cd(); 
  trackTreeAna_p->Write("", TObject::kOverwrite);
  pfCandTreeAna_p->Write("", TObject::kOverwrite);
  jetTreeAna_p->Write("", TObject::kOverwrite);
  if(montecarlo) genTreeAna_p->Write("", TObject::kOverwrite);

  CleanupWJetAnaSkim();
  outFile->Close();
  delete outFile;

  iniSkim_p->Close();
  delete iniSkim_p;

  printf("Done.\n");
  return(0);
}