Esempio n. 1
0
class EleTauProducer(Module):
    def __init__(self, name, dataType, **kwargs):

        year = kwargs.get('year', 2017)
        tes = kwargs.get('tes', 1.0)
        channel = 'eletau'

        self.name = name
        self.year = year
        self.tes = tes
        self.out = TreeProducerEleTau(name)
        self.isData = dataType == 'data'
        self.doZpt = 'DY' in self.name

        setYear(year)
        self.vlooseIso = getVLooseTauIso(year)
        if year == 2016:
            self.trigger = lambda e: e.HLT_Ele25_eta2p1_WPTight_Gsf or e.HLT_Ele45_WPLoose_Gsf_L1JetTauSeeded  #or e.HLT_Ele24_eta2p1_WPLoose_Gsf_LooseIsoPFTau20_SingleL1 or e.HLT_Ele24_eta2p1_WPLoose_Gsf_LooseIsoPFTau20 or e.HLT_Ele24_eta2p1_WPLoose_Gsf_LooseIsoPFTau30
            self.electronCutPt = 26
        else:
            # HLT_Ele32_WPTight_Gsf_L1DoubleEG
            # HLT_Ele32_WPTight_Gsf
            self.trigger = lambda e: e.HLT_Ele35_WPTight_Gsf or e.HLT_Ele32_WPTight_Gsf
            self.electronCutPt = 36
        self.tauCutPt = 20

        if not self.isData:
            self.eleSFs = ElectronSFs(year=year)
            self.puTool = PileupWeightTool(year=year)
            self.ltfSFs = LeptonTauFakeSFs('loose', 'tight', year=year)
            self.btagTool = BTagWeightTool('CSVv2',
                                           'medium',
                                           channel=channel,
                                           year=year)
            self.btagTool_deep = BTagWeightTool('DeepCSV',
                                                'medium',
                                                channel=channel,
                                                year=year)
            if self.doZpt:
                self.recoilTool = RecoilCorrectionTool(year=year)
        self.csvv2_wp = BTagWPs('CSVv2', year=year)
        self.deepcsv_wp = BTagWPs('DeepCSV', year=year)

        self.Nocut = 0
        self.Trigger = 1
        self.GoodElectrons = 2
        self.GoodTaus = 3
        self.GoodDiLepton = 4
        self.TotalWeighted = 15
        self.TotalWeighted_no0PU = 16

        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.Nocut, "no cut")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.Trigger, "trigger")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodElectrons,
                                                "electron object")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodTaus,
                                                "tau object")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodDiLepton,
                                                "eletau pair")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.TotalWeighted,
                                                "no cut, weighted")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.TotalWeighted_no0PU,
                                                "no cut, weighted, PU>0")
        self.out.cutflow.GetXaxis().SetLabelSize(0.041)

    def beginJob(self):
        pass

    def endJob(self):
        if not self.isData:
            self.btagTool.setDirectory(self.out.outputfile, 'btag')
            self.btagTool_deep.setDirectory(self.out.outputfile, 'btag')
        self.out.outputfile.Write()
        self.out.outputfile.Close()

    def beginFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        pass

    def endFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        pass

    def analyze(self, event):
        """process event, return True (go to next module) or False (fail, go to next event)"""

        #electrons = Collection(event, "Electron")

        #####################################
        self.out.cutflow.Fill(self.Nocut)
        if self.isData:
            self.out.cutflow.Fill(self.TotalWeighted, 1.)
            if event.PV_npvs > 0:
                self.out.cutflow.Fill(self.TotalWeighted_no0PU, 1.)
            else:
                return False
        else:
            self.out.cutflow.Fill(self.TotalWeighted, event.genWeight)
            if event.Pileup_nTrueInt > 0:
                self.out.cutflow.Fill(self.TotalWeighted_no0PU,
                                      event.genWeight)
            else:
                return False
        #####################################

        if not self.trigger(event):
            return False

        #####################################
        self.out.cutflow.Fill(self.Trigger)
        #####################################

        idx_goodelectrons = []
        for ielectron in range(event.nElectron):
            if event.Electron_pt[ielectron] < self.electronCutPt: continue
            if abs(event.Electron_eta[ielectron]) > 2.1: continue
            if abs(event.Electron_dz[ielectron]) > 0.2: continue
            if abs(event.Electron_dxy[ielectron]) > 0.045: continue
            if event.Electron_convVeto[ielectron] != 1: continue
            if ord(event.Electron_lostHits[ielectron]) > 1: continue
            if getvar(event, 'Electron_mvaFall17Iso_WP80')[ielectron] < 0.5:
                continue
            idx_goodelectrons.append(ielectron)

        if len(idx_goodelectrons) == 0:
            return False

        #####################################
        self.out.cutflow.Fill(self.GoodElectrons)
        #####################################

        idx_goodtaus = []
        for itau in range(event.nTau):
            if event.Tau_pt[itau] < self.tauCutPt: continue
            if abs(event.Tau_eta[itau]) > 2.3: continue
            if abs(event.Tau_dz[itau]) > 0.2: continue
            if event.Tau_decayMode[itau] not in [0, 1, 10]: continue
            if abs(event.Tau_charge[itau]) != 1: continue
            #if ord(event.Tau_idAntiEle[itau])<1: continue
            #if ord(event.Tau_idAntiMu[itau])<1: continue
            if not self.vlooseIso(event, itau): continue
            idx_goodtaus.append(itau)

        if len(idx_goodtaus) == 0:
            return False

        #####################################
        self.out.cutflow.Fill(self.GoodTaus)
        #####################################

        electrons = Collection(event, 'Electron')
        taus = Collection(event, 'Tau')
        ltaus = []
        for idx1 in idx_goodelectrons:
            for idx2 in idx_goodtaus:
                dR = taus[idx2].p4().DeltaR(electrons[idx1].p4())
                if dR < 0.5: continue
                ltau = LeptonTauPair(idx1, event.Electron_pt[idx1],
                                     event.Electron_pfRelIso03_all[idx1], idx2,
                                     event.Tau_pt[idx2],
                                     event.Tau_rawMVAoldDM2017v2[idx2])
                ltaus.append(ltau)

        if len(ltaus) == 0:
            return False

        ltau = bestDiLepton(ltaus)
        electron = electrons[ltau.id1].p4()
        tau = taus[ltau.id2].p4()
        #print 'chosen tau1 (idx, pt) = ', ltau.id1, ltau.tau1_pt, 'check', electron.p4().Pt()
        #print 'chosen tau2 (idx, pt) = ', ltau.id2, ltau.tau2_pt, 'check', tau.p4().Pt()

        #####################################
        self.out.cutflow.Fill(self.GoodDiLepton)
        #####################################

        jetIds = []
        bjetIds = []
        jets = Collection(event, 'Jet')
        nfjets = 0
        ncjets = 0
        nbtag = 0
        for ijet in range(event.nJet):
            if event.Jet_pt[ijet] < 30: continue
            if abs(event.Jet_eta[ijet]) > 4.7: continue
            if electron.DeltaR(jets[ijet].p4()) < 0.5: continue
            if tau.DeltaR(jets[ijet].p4()) < 0.5: continue
            jetIds.append(ijet)

            if abs(event.Jet_eta[ijet]) > 2.4:
                nfjets += 1
            else:
                ncjets += 1

            if event.Jet_btagDeepB[ijet] > self.deepcsv_wp.medium:
                nbtag += 1
                bjetIds.append(ijet)

        if not self.isData and self.vlooseIso(
                event,
                ltau.id2) and event.Electron_pfRelIso03_all[ltau.id1] < 0.50:
            self.btagTool.fillEfficiencies(event, jetIds)
            self.btagTool_deep.fillEfficiencies(event, jetIds)

        #eventSum = ROOT.TLorentzVector()
        #
        #for lep in electrons :
        #    eventSum += lep.p4()
        #for lep in electrons :
        #    eventSum += lep.p4()
        #for j in filter(self.jetSel,jets):
        #    eventSum += j.p4()

        # ELECTRON
        self.out.pt_1[0] = event.Electron_pt[ltau.id1]
        self.out.eta_1[0] = event.Electron_eta[ltau.id1]
        self.out.phi_1[0] = event.Electron_phi[ltau.id1]
        self.out.m_1[0] = event.Electron_mass[ltau.id1]
        self.out.dxy_1[0] = event.Electron_dxy[ltau.id1]
        self.out.dz_1[0] = event.Electron_dz[ltau.id1]
        self.out.q_1[0] = event.Electron_charge[ltau.id1]
        self.out.pfRelIso03_all_1[0] = event.Electron_pfRelIso03_all[ltau.id1]
        self.out.cutBased_1[0] = event.Electron_cutBased[ltau.id1]
        self.out.mvaFall17Iso_1[0] = getvar(event,
                                            'Electron_mvaFall17Iso')[ltau.id1]
        self.out.mvaFall17Iso_WP80_1[0] = getvar(
            event, 'Electron_mvaFall17Iso_WP80')[ltau.id1]
        self.out.mvaFall17Iso_WP90_1[0] = getvar(
            event, 'Electron_mvaFall17Iso_WP90')[ltau.id1]
        self.out.mvaFall17Iso_WPL_1[0] = getvar(
            event, 'Electron_mvaFall17Iso_WPL')[ltau.id1]

        # TAU
        self.out.pt_2[0] = event.Tau_pt[ltau.id2]
        self.out.eta_2[0] = event.Tau_eta[ltau.id2]
        self.out.phi_2[0] = event.Tau_phi[ltau.id2]
        self.out.m_2[0] = event.Tau_mass[ltau.id2]
        self.out.dxy_2[0] = event.Tau_dxy[ltau.id2]
        self.out.dz_2[0] = event.Tau_dz[ltau.id2]
        self.out.leadTkPtOverTauPt_2[0] = event.Tau_leadTkPtOverTauPt[ltau.id2]
        self.out.chargedIso_2[0] = event.Tau_chargedIso[ltau.id2]
        self.out.neutralIso_2[0] = event.Tau_neutralIso[ltau.id2]
        self.out.photonsOutsideSignalCone_2[
            0] = event.Tau_photonsOutsideSignalCone[ltau.id2]
        self.out.puCorr_2[0] = event.Tau_puCorr[ltau.id2]
        self.out.rawAntiEle_2[0] = event.Tau_rawAntiEle[ltau.id2]
        self.out.rawIso_2[0] = event.Tau_rawIso[ltau.id2]
        self.out.q_2[0] = event.Tau_charge[ltau.id2]
        self.out.decayMode_2[0] = event.Tau_decayMode[ltau.id2]
        ###self.out.rawAntiEleCat_2[0]            = event.Tau_rawAntiEleCat[ltau.id2]
        self.out.idAntiEle_2[0] = ord(event.Tau_idAntiEle[ltau.id2])
        self.out.idAntiMu_2[0] = ord(event.Tau_idAntiMu[ltau.id2])
        self.out.idDecayMode_2[0] = event.Tau_idDecayMode[ltau.id2]
        self.out.idDecayModeNewDMs_2[0] = event.Tau_idDecayModeNewDMs[ltau.id2]
        self.out.rawMVAoldDM_2[0] = event.Tau_rawMVAoldDM[ltau.id2]
        self.out.rawMVAnewDM2017v2_2[0] = event.Tau_rawMVAnewDM2017v2[ltau.id2]
        self.out.rawMVAoldDM2017v1_2[0] = event.Tau_rawMVAoldDM2017v1[ltau.id2]
        self.out.rawMVAoldDM2017v2_2[0] = event.Tau_rawMVAoldDM2017v2[ltau.id2]
        self.out.idMVAoldDM_2[0] = ord(event.Tau_idMVAoldDM[ltau.id2])
        self.out.idMVAoldDM2017v1_2[0] = ord(
            event.Tau_idMVAoldDM2017v1[ltau.id2])
        self.out.idMVAoldDM2017v2_2[0] = ord(
            event.Tau_idMVAoldDM2017v2[ltau.id2])
        self.out.idMVAnewDM2017v2_2[0] = ord(
            event.Tau_idMVAnewDM2017v2[ltau.id2])

        # GENERATOR
        #print type(event.Tau_genPartFlav[ltau.id2])
        if not self.isData:
            self.out.genPartFlav_1[0] = ord(
                event.Electron_genPartFlav[ltau.id1])
            self.out.genPartFlav_2[0] = ord(event.Tau_genPartFlav[ltau.id2])

            genvistau = Collection(event, 'GenVisTau')
            dRmax = 1000
            gendm = -1
            genpt = -1
            geneta = -1
            genphi = -1
            for igvt in range(event.nGenVisTau):
                dR = genvistau[igvt].p4().DeltaR(tau)
                if dR < 0.5 and dR < dRmax:
                    dRmax = dR
                    gendm = event.GenVisTau_status[igvt]
                    genpt = event.GenVisTau_pt[igvt]
                    geneta = event.GenVisTau_eta[igvt]
                    genphi = event.GenVisTau_phi[igvt]

            self.out.gendecayMode_2[0] = gendm
            self.out.genvistaupt_2[0] = genpt
            self.out.genvistaueta_2[0] = geneta
            self.out.genvistauphi_2[0] = genphi

        # EVENT
        self.out.isData[0] = self.isData
        self.out.run[0] = event.run
        self.out.luminosityBlock[0] = event.luminosityBlock
        self.out.event[0] = event.event & 0xffffffffffffffff
        self.out.met[0] = event.MET_pt
        self.out.metphi[0] = event.MET_phi
        ###self.out.puppimet[0]                  = event.PuppiMET_pt
        ###self.out.puppimetphi[0]               = event.PuppiMET_phi
        ###self.out.metsignificance[0]           = event.MET_significance
        ###self.out.metcovXX[0]                  = event.MET_covXX
        ###self.out.metcovXY[0]                  = event.MET_covXY
        ###self.out.metcovYY[0]                  = event.MET_covYY
        ###self.out.fixedGridRhoFastjetAll[0]    = event.fixedGridRhoFastjetAll
        self.out.npvs[0] = event.PV_npvs
        self.out.npvsGood[0] = event.PV_npvsGood

        if not self.isData:
            self.out.genmet[0] = event.GenMET_pt
            self.out.genmetphi[0] = event.GenMET_phi
            self.out.nPU[0] = event.Pileup_nPU
            self.out.nTrueInt[0] = event.Pileup_nTrueInt
            self.out.genWeight[0] = event.genWeight
            try:
                self.out.LHE_Njets[0] = event.LHE_Njets
            except RuntimeError:
                self.out.LHE_Njets[0] = -1

        # JETS
        self.out.njets[0] = len(jetIds)
        self.out.njets50[0] = len([j for j in jetIds if event.Jet_pt[j] > 50])
        self.out.nfjets[0] = nfjets
        self.out.ncjets[0] = ncjets
        self.out.nbtag[0] = nbtag

        if len(jetIds) > 0:
            self.out.jpt_1[0] = event.Jet_pt[jetIds[0]]
            self.out.jeta_1[0] = event.Jet_eta[jetIds[0]]
            self.out.jphi_1[0] = event.Jet_phi[jetIds[0]]
            self.out.jcsvv2_1[0] = event.Jet_btagCSVV2[jetIds[0]]
            self.out.jdeepb_1[0] = event.Jet_btagDeepB[jetIds[0]]
        else:
            self.out.jpt_1[0] = -9.
            self.out.jeta_1[0] = -9.
            self.out.jphi_1[0] = -9.
            self.out.jcsvv2_1[0] = -9.
            self.out.jdeepb_1[0] = -9.

        if len(jetIds) > 1:
            self.out.jpt_2[0] = event.Jet_pt[jetIds[1]]
            self.out.jeta_2[0] = event.Jet_eta[jetIds[1]]
            self.out.jphi_2[0] = event.Jet_phi[jetIds[1]]
            self.out.jcsvv2_2[0] = event.Jet_btagCSVV2[jetIds[1]]
            self.out.jdeepb_2[0] = event.Jet_btagDeepB[jetIds[1]]
        else:
            self.out.jpt_2[0] = -9.
            self.out.jeta_2[0] = -9.
            self.out.jphi_2[0] = -9.
            self.out.jcsvv2_2[0] = -9.
            self.out.jdeepb_2[0] = -9.

        if len(bjetIds) > 0:
            self.out.bpt_1[0] = event.Jet_pt[bjetIds[0]]
            self.out.beta_1[0] = event.Jet_eta[bjetIds[0]]
        else:
            self.out.bpt_1[0] = -9.
            self.out.beta_1[0] = -9.

        if len(bjetIds) > 1:
            self.out.bpt_2[0] = event.Jet_pt[bjetIds[1]]
            self.out.beta_2[0] = event.Jet_eta[bjetIds[1]]
        else:
            self.out.bpt_2[0] = -9.
            self.out.beta_2[0] = -9.

        self.out.pfmt_1[0] = math.sqrt(
            2 * self.out.pt_1[0] * self.out.met[0] *
            (1 - math.cos(deltaPhi(self.out.phi_1[0], self.out.metphi[0]))))
        self.out.pfmt_2[0] = math.sqrt(
            2 * self.out.pt_2[0] * self.out.met[0] *
            (1 - math.cos(deltaPhi(self.out.phi_2[0], self.out.metphi[0]))))

        self.out.m_vis[0] = (electron + tau).M()
        self.out.pt_ll[0] = (electron + tau).Pt()
        self.out.dR_ll[0] = electron.DeltaR(tau)
        self.out.dphi_ll[0] = deltaPhi(self.out.phi_1[0], self.out.phi_2[0])

        # PZETA
        leg1 = ROOT.TVector3(electron.Px(), electron.Py(), 0.)
        leg2 = ROOT.TVector3(tau.Px(), tau.Py(), 0.)
        met_tlv = ROOT.TLorentzVector()
        met_tlv = ROOT.TLorentzVector()
        met_tlv.SetPxPyPzE(self.out.met[0] * math.cos(self.out.metphi[0]),
                           self.out.met[0] * math.cos(self.out.metphi[0]), 0,
                           self.out.met[0])
        metleg = met_tlv.Vect()
        zetaAxis = ROOT.TVector3(leg1.Unit() + leg2.Unit()).Unit()
        pzetaVis = leg1 * zetaAxis + leg2 * zetaAxis
        pzetaMET = metleg * zetaAxis
        self.out.pzetamiss[0] = pzetaMET
        self.out.pzetavis[0] = pzetaVis
        self.out.dzeta[0] = pzetaMET - 0.85 * pzetaVis

        # VETOS
        self.out.extramuon_veto[0], self.out.extraelec_veto[
            0], self.out.dilepton_veto[0] = extraLeptonVetos(
                event, [-1], [ltau.id1], self.name)

        # WEIGHTS
        if not self.isData:
            if self.doZpt:
                zboson = getZPTMass(event)
                self.out.m_genboson[0] = zboson.M()
                self.out.pt_genboson[0] = zboson.Pt()
                self.out.zptweight[0] = self.recoilTool.getZptWeight(
                    zboson.Pt(), zboson.M())
            self.out.genweight[0] = event.genWeight
            self.out.puweight[0] = self.puTool.getWeight(event.Pileup_nTrueInt)
            self.out.trigweight[0] = self.eleSFs.getTriggerSF(
                self.out.pt_1[0], self.out.eta_1[0])
            self.out.idisoweight_1[0] = self.eleSFs.getIdIsoSF(
                self.out.pt_1[0], self.out.eta_1[0])
            self.out.idisoweight_2[0] = self.ltfSFs.getSF(
                self.out.genPartFlav_2[0], self.out.eta_2[0])
            self.out.btagweight[0] = self.btagTool.getWeight(event, jetIds)
            self.out.btagweight_deep[0] = self.btagTool_deep.getWeight(
                event, jetIds)
            self.out.weight[0] = self.out.genWeight[0] * self.out.puweight[
                0] * self.out.trigweight[0] * self.out.idisoweight_1[
                    0] * self.out.idisoweight_2[0]

        self.out.tree.Fill()
        return True
Esempio n. 2
0
class SameSign(Module):
    def __init__(self):
        self.writeHistFile = True

    def beginJob(self, histFile=None, histDirName=None):
        Module.beginJob(self, histFile, histDirName)
        self.event = 0
        self.hists = {}
        self.hists["Events"] = ROOT.TH1F("Events", "Events", 1, 0, 1)
#        self.addObject(self.h_events)
#        self.h_events.SetDirectory

    def endJob(self):
        Module.endJob(self)
        print "+ Module ended successfully,"  #, self.h_events.GetEntries(), "events analyzed"
        pass

    def beginFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        self.out = wrappedOutputTree
        self.out.branch("iSkim", "I")
        self.out.branch("isMC", "I")
        self.out.branch("isSingleMuIsoTrigger", "I")
        self.out.branch("isSingleMuTrigger", "I")
        self.out.branch("isDoubleMuonTrigger", "I")
        self.out.branch("isSingleEleIsoTrigger", "I")
        self.out.branch("isSingleEleTrigger", "I")
        self.out.branch("passedMETFilters", "I")
        self.out.branch("nCleanElectron", "I")
        self.out.branch("nCleanMuon", "I")
        self.out.branch("nCleanJet", "I")
        self.out.branch("Z_mass", "F")
        self.out.branch("Z_pt", "F")
        self.out.branch("W_mass", "F")
        self.out.branch("W_tmass", "F")
        self.out.branch("W_pt", "F")
        self.out.branch("ll_dEta", "F")
        self.out.branch("ll_dPhi", "F")
        self.out.branch("ll_dR", "F")
        self.out.branch("Wqq_mass", "F")
        self.out.branch("Tlvb1_mass", "F")
        self.out.branch("Tlvb2_mass", "F")
        self.out.branch("Tqqb1_mass", "F")
        self.out.branch("Tqqb2_mass", "F")
        self.out.branch("jj_mass", "F")
        self.out.branch("jj_pt", "F")
        self.out.branch("jj_dEta", "F")
        self.out.branch("jj_dPhi", "F")
        self.out.branch("jj_dR", "F")
        self.out.branch("nj_mass", "F")
        self.out.branch("vis_mass", "F")
        self.out.branch("lljj_mass", "F")
        self.out.branch("minMuonIso", "F")
        self.out.branch("maxMuonIso", "F")
        self.out.branch("minMuonMetDPhi", "F")
        self.out.branch("maxMuonMetDPhi", "F")
        self.out.branch("minMuonJetDR", "F")
        self.out.branch("HT30", "F")
        self.out.branch("nj20", "I")
        self.out.branch("nj30", "I")
        self.out.branch("nj40", "I")
        self.out.branch("nBJet", "I")
        self.out.branch("CSV1", "F")
        self.out.branch("CSV2", "F")
        self.out.branch("CSV3", "F")
        self.out.branch("CSV4", "F")
        self.out.branch("iCSV1", "I")
        self.out.branch("iCSV2", "I")
        self.out.branch("iCSV3", "I")
        self.out.branch("iCSV4", "I")
        self.out.branch("lumiWeight", "F")
        self.out.branch("lheWeight", "F")
        self.out.branch("stitchWeight", "F")
        self.out.branch("puWeight", "F")
        self.out.branch("topWeight", "F")
        self.out.branch("qcdnloWeight", "F")
        self.out.branch("qcdnnloWeight", "F")
        self.out.branch("ewknloWeight", "F")
        self.out.branch("triggerWeight", "F")
        self.out.branch("leptonWeight", "F")
        self.out.branch("eventWeightLumi", "F")

        self.fileName = inputFile.GetName()
        self.sampleName = getNameFromFile(self.fileName)

        self.isMC = not "Run201" in self.fileName

        print "+ Opening file", self.fileName

        # b-tagging working points for DeepCSV
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation2016Legacy
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation94X
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation102X
        if "Run2016" in self.fileName or "Summer16" in self.fileName:
            self.year = 2016
            self.lumi = 35920.
            self.btagLoose = 0.2217  #0.0614
            self.btagMedium = 0.6321  #0.3093
            self.btagTight = 0.8953  #0.7221
        elif "Run2017" in self.fileName or "Fall17" in self.fileName:
            self.year = 2017
            self.lumi = 41530.
            self.btagLoose = 0.1522  #0.0521
            self.btagMedium = 0.4941  #0.3033
            self.btagTight = 0.8001  #0.7489
        elif "Run2018" in self.fileName or "Autumn18" in self.fileName:
            self.year = 2018
            self.lumi = 59740.
            self.btagLoose = 0.1241  #0.0494
            self.btagMedium = 0.4184  #0.2770
            self.btagTight = 0.7527  #0.7264
        else:
            print "- Unknown year, aborting module"
            import sys
            sys.exit()

        self.xs = XS[self.sampleName] if self.sampleName in XS else 0.
        self.nevents = EV[self.sampleName] if self.sampleName in EV else 0.
        self.xsWeight = self.xs / self.nevents if self.nevents > 0 else 1.
        self.lumiWeight = self.xsWeight * self.lumi if self.isMC else 1.
        self.isLO = abs(
            self.nevents % 1
        ) < 1.e-6  # if True, the event count is integer, so the weight should be normalized (+1)

        print "+ Module parameters: isMC", self.isMC, ", year", self.year, ", lumi", self.lumi, "pb"
        print "+ Sample", self.sampleName, (
            "is LO" if self.isLO else
            "is not LO"), ", XS", self.xs, ", events", self.nevents
        print "+ Weight", self.lumiWeight
        if self.isMC and self.isLO:
            print "+ Sample is LO, gen weight will be set to 1"
        #        self.puTool = PileupWeightTool(year = year) if self.isMC else None

        self.SingleMuIsoTriggers = [
            "HLT_IsoMu24", "HLT_IsoTkMu24", "HLT_IsoMu27", "HLT_IsoTkMu27"
        ]
        self.SingleMuTriggers = [
            "HLT_Mu50", "HLT_TkMu50", "HLT_Mu100", "HLT_TkMu100"
        ]
        self.DoubleMuonTriggers = [
            "HLT_Mu17_Mu8", "HLT_Mu17_Mu8_DZ", "HLT_Mu17_TkMu8_DZ"
        ]
        self.SingleEleIsoTriggers = [
            "HLT_Ele27_WPTight_Gsf", "HLT_Ele27_WPLoose_Gsf",
            "HLT_Ele32_WPTight_Gsf", "HLT_Ele35_WPTight_Gsf"
        ]
        self.SingleEleTriggers = [
            "HLT_Ele105_CaloIdVT_GsfTrkIdT", "HLT_Ele115_CaloIdVT_GsfTrkIdT",
            "HLT_Photon175", "HLT_Photon200"
        ]

        if self.isMC:
            self.muSFs = MuonSFs(year=self.year)
            self.elSFs = ElectronSFs(year=self.year)
            self.puTool = PileupWeightTool(year=self.year)
            #            self.btagToolAK8 = BTagWeightTool('CSVv2','AK8','loose',sigma='central',channel='ll',year=year)
            #            self.btagToolAK4 = BTagWeightTool('CSVv2','AK4','loose',sigma='central',channel='ll',year=year)
            #            self.btagToolAK8_deep = BTagWeightTool('DeepCSV','AK8','loose',sigma='central',channel='ll',year=year)
            #            self.btagToolAK8_deep_up = BTagWeightTool('DeepCSV','AK8','loose',sigma='up',channel='ll',year=year)
            #            self.btagToolAK8_deep_down = BTagWeightTool('DeepCSV','AK8','loose',sigma='down',channel='ll',year=year)
            #            self.btagToolAK4_deep = BTagWeightTool('DeepCSV','AK4','loose',sigma='central',channel='ll',year=year)
            #            self.btagToolAK4_deep_up = BTagWeightTool('DeepCSV','AK4','loose',sigma='up',channel='ll',year=year)
            #            self.btagToolAK4_deep_down = BTagWeightTool('DeepCSV','AK4','loose',sigma='down',channel='ll',year=year)
            if 'DYJetsToLL_M-50' in self.fileName:
                self.VptCorr = DYCorrection('DYJetsToLL')
            elif 'ZJetsToNuNu' in self.fileName:
                self.VptCorr = DYCorrection('ZJetsToNuNu')
            elif 'WJetsToLNu' in self.fileName:
                self.VptCorr = DYCorrection('WJetsToLNu')
            else:
                self.VptCorr = None

    def endFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        outputFile.mkdir("Hists")
        outputFile.cd("Hists")
        for histname, hist in self.hists.iteritems():
            hist.Write()
        outputFile.cd("..")
        print "+ File closed successfully"
        pass

    def analyze(self, event):
        iSkim = 0
        eventWeightLumi, lheWeight, stitchWeight, puWeight, qcdnloWeight, qcdnnloWeight, ewknloWeight, topWeight = 1., 1., 1., 1., 1., 1., 1., 1.
        triggerWeight, leptonWeight = 1., 1.
        MinMuonIso, MaxMuonIso, MinMuonMetDPhi, MaxMuonMetDPhi, MinMuonJetDR = -1., -1., -1., -1., -1.
        mZ, mW, mT, ptZ, ptW = -1., -1., -1., -1., -1.
        dEtaLL, dPhiLL, dRLL = -1., -1., -1.
        mJJ, ptJJ, dEtaJJ, dPhiJJ, dRJJ = -1., -1., -1., -1., -1.
        mLLJJ, mNJ = -1., -1.
        mHadW, mLepTop1, mLepTop2, mHadTop1, mHadTop2 = -1., -1., -1., -1., -1.
        isSingleMuIsoTrigger, isSingleMuTrigger, isDoubleMuonTrigger, isSingleEleIsoTrigger, isSingleEleTrigger = False, False, False, False, False
        for t in self.SingleMuIsoTriggers:
            if hasattr(event, t) and getattr(event, t):
                isSingleMuIsoTrigger = True
        for t in self.SingleMuTriggers:
            if hasattr(event, t) and getattr(event, t):
                isSingleMuTrigger = True
        for t in self.DoubleMuonTriggers:
            if hasattr(event, t) and getattr(event, t):
                isDoubleMuonTrigger = True
        for t in self.SingleEleIsoTriggers:
            if hasattr(event, t) and getattr(event, t):
                isSingleEleIsoTrigger = True
        for t in self.SingleEleTriggers:
            if hasattr(event, t) and getattr(event, t):
                isSingleEleTrigger = True

        lheWeight = 1.

        if self.isMC:
            # Event weight
            if not self.isLO and hasattr(event, "LHEWeight_originalXWGTUP"):
                lheWeight = event.LHEWeight_originalXWGTUP

            GenVpt = self.VptCorr.getGenVpt(
                event) if not self.VptCorr is None else 0.

            # MC stitching weight

            # W+jets inclusive and exclusive
            if 'WJetsToLNu_TuneCUETP8M1_13TeV-amcatnloFXFX-pythia8' in self.fileName and 'Summer16' in self.fileName:
                if event.LHE_Vpt > 100.: stitchWeight = 0.

            # Z+jets and Z+gamma
            if self.fileName.startswith(
                    'ZGTo2LG_TuneCUETP8M1') or self.fileName.startswith(
                        'ZGToLLG_01J_5f_TuneCP5') or self.fileName.startswith(
                            'DYJetsToLL_M-50_Tune'):
                nGenPhotons = 0
                photonPtTh = 15. if self.fileName.startswith(
                    'ZGTo2LG_TuneCUETP8M1') or self.fileName.startswith(
                        'DYJetsToLL_M-50_TuneCUETP8M1') else 20.
                for i in range(event.nGenPart):
                    if GenPart_pdgId[i] == 22 and TMath.Odd(
                            GenPart_statusFlags[i]
                    ) and GenPart_pt > photonPtTh:
                        nGenPhotons += 1
                if self.fileName.startswith('ZG') and nGenPhotons <= 0:
                    stitchWeight = 0.
                if self.fileName.startswith(
                        'DYJetsToLL_M-50') and nGenPhotons >= 1:
                    stitchWeight = 0.

            # PU weight
            puWeight = self.puTool.getWeight(event.Pileup_nTrueInt)

            # Higher order correction weights
            if not self.VptCorr is None:
                if not 'amcatnlo' in self.fileName:
                    qcdnloWeight = self.VptCorr.getWeightQCDNLO(GenVpt)
                qcdnnloWeight = self.VptCorr.getWeightQCDNNLO(GenVpt)
                ewknloWeight = self.VptCorr.getWeightEWKNLO(GenVpt)

            if 'TTTo' in self.fileName:
                Top1_pt, Top2_pt = getTTPt(event)
                topWeight = getTTptWeight(Top1_pt, Top2_pt)

        self.hists["Events"].Fill(0, lheWeight)

        #        electrons = Collection(event, "Electron")
        #        muons = Collection(event, "Muon")
        #        jets = Collection(event, "Jet")
        #        eventSum = ROOT.TLorentzVector()

        #        #select events with at least 2 muons
        #        if len(muons) >=2 :
        #          for lep in muons :     #loop on muons
        #                  eventSum += lep.p4()
        #          for lep in electrons : #loop on electrons
        #            eventSum += lep.p4()
        #          for j in jets :       #loop on jets
        #            eventSum += j.p4()

        # Clean collections

        # Electrons
        cleanElectron = []
        for i in range(event.nElectron):
            if event.Electron_pt[i] > 10. and event.Electron_cutBased[i] >= 2:
                p4 = TLorentzVector()
                p4.SetPtEtaPhiM(event.Electron_pt[i], event.Electron_eta[i],
                                event.Electron_phi[i], event.Electron_mass[i])
                cleanElectron.append(p4)

        # Muons
        cleanMuon = []
        for i in range(event.nMuon):
            if event.Muon_pt[i] > 10. and event.Muon_mediumId[
                    i] and event.Muon_pfRelIso03_all[i] < 0.15:
                p4 = TLorentzVector()
                p4.SetPtEtaPhiM(event.Muon_pt[i], event.Muon_eta[i],
                                event.Muon_phi[i], event.Muon_mass[i])
                cleanMuon.append(p4)

        # Jets and Event variables
        cleanJet, cleanBJet, cleanNonBJet = [], [], []
        HT30, Nj20, Nj30, Nj40, nBJet = 0., 0, 0, 0, 0
        CSVs = []
        twoJets, allJets = TLorentzVector(), TLorentzVector()
        for i in range(event.nJet):
            if event.Jet_jetId[i] >= 6 and abs(event.Jet_eta[i]) < 2.5:
                p4 = TLorentzVector()
                p4.SetPtEtaPhiM(event.Jet_pt[i], event.Jet_eta[i],
                                event.Jet_phi[i], event.Jet_mass[i])
                # remove overlaps with electrons and muons
                cleanFromLeptons = True
                for e in range(len(cleanElectron)):
                    if cleanElectron[e].DeltaR(p4) < 0.4:
                        cleanFromLeptons = False
                for m in range(len(cleanMuon)):
                    if cleanMuon[m].DeltaR(p4) < 0.4: cleanFromLeptons = False
                # fill variables
                if cleanFromLeptons:
                    if event.Jet_pt[i] > 20.:
                        Nj20 += 1
                    if event.Jet_pt[i] > 30.:
                        HT30 += event.Jet_pt[i]
                        Nj30 += 1
                        cleanJet.append(p4)
                        if event.Jet_btagDeepB[i] >= self.btagMedium:
                            cleanBJet.append(p4)
                        else:
                            cleanNonBJet.append(p4)
                        CSVs.append([i, event.Jet_btagDeepB[i]])
                        if len(cleanJet) < 2: twoJets += p4
                        allJets += p4
                    if event.Jet_pt[i] > 40.:
                        Nj40 += 1

        # b-tag ranking
        nBJet = len(cleanBJet)
        CSV1, CSV2, CSV3, CSV4, iCSV1, iCSV2, iCSV3, iCSV4 = 0., 0., 0., 0., -1, -1, -1, -1

        CSVs.sort(key=lambda x: x[1], reverse=True)
        if len(CSVs) > 0: iCSV1, CSV1 = CSVs[0][0], CSVs[0][1]
        if len(CSVs) > 1: iCSV2, CSV2 = CSVs[1][0], CSVs[1][1]
        if len(CSVs) > 2: iCSV3, CSV3 = CSVs[2][0], CSVs[2][1]
        if len(CSVs) > 3: iCSV4, CSV4 = CSVs[3][0], CSVs[3][1]

        if len(cleanJet) >= 2:
            mJJ = (cleanJet[0] + cleanJet[1]).M()
            ptJJ = (cleanJet[0] + cleanJet[1]).Pt()
            dEtaJJ = abs(cleanJet[0].Eta() - cleanJet[1].Eta())
            dPhiJJ = abs(cleanJet[0].DeltaPhi(cleanJet[1]))
            dRJJ = cleanJet[0].DeltaR(cleanJet[1])
        mNJ = allJets.M()

        Lepton1, Lepton2, Lepton3, Neutrino, MET, LLJJ, Vis = TLorentzVector(
        ), TLorentzVector(), TLorentzVector(), TLorentzVector(
        ), TLorentzVector(), TLorentzVector(), TLorentzVector()
        MET.SetPtEtaPhiM(event.MET_pt, 0., event.MET_phi, 0.)

        # Categorization:
        # iSkim = 1: 2 muons (OS or SS)
        # iSkim = 2: 1 muon and 1 electron (no OS requirement)
        # iSkim = 3: 3 muons (assumed that they are not 3 same-sign)
        # iSkim = 4: 2 muons (OS) and 1 electron
        # iSkim = 5: 1 muons, 3 jets, >= 1 btag
        # iSkim = 6: 2 electrons

        # case 3a: 3 lepton CR (3mu)
        if iSkim == 0 and event.nMuon >= 3:
            if (isSingleMuIsoTrigger or isSingleMuTrigger) and event.Muon_pt[
                    0] > 27. and event.Muon_pt[1] > 15. and event.Muon_pt[
                        2] > 15. and event.Muon_mediumId[
                            0] and event.Muon_mediumId[
                                1] and event.Muon_mediumId[2]:
                Lepton1.SetPtEtaPhiM(event.Muon_pt[0], event.Muon_eta[0],
                                     event.Muon_phi[0], event.Muon_mass[0])
                Lepton2.SetPtEtaPhiM(event.Muon_pt[1], event.Muon_eta[1],
                                     event.Muon_phi[1], event.Muon_mass[1])
                Lepton3.SetPtEtaPhiM(event.Muon_pt[2], event.Muon_eta[2],
                                     event.Muon_phi[2], event.Muon_mass[2])
                if event.Muon_charge[0] * event.Muon_charge[1] < 0:
                    mll = (Lepton1 + Lepton2).M()
                    ptll = (Lepton1 + Lepton2).Pt()
                    detall = abs(Lepton1.Eta() - Lepton2.Eta())
                    dphill = abs(Lepton1.DeltaPhi(Lepton2))
                    drll = Lepton1.DeltaR(Lepton2)
                else:
                    mll = (Lepton1 + Lepton3).M()
                    ptll = (Lepton1 + Lepton3).Pt()
                    detall = abs(Lepton1.Eta() - Lepton3.Eta())
                    dphill = abs(Lepton1.DeltaPhi(Lepton3))
                    drll = Lepton1.DeltaR(Lepton3)
                if mll > 15.:
                    iSkim = 3
                    # Variables
                    mZ, ptZ = mll, ptll
                    dEtaLL, dPhiLL, dRLL = detall, dphill, drll
                    MinMuonIso = min(
                        min(event.Muon_pfRelIso03_all[0],
                            event.Muon_pfRelIso03_all[1]),
                        event.Muon_pfRelIso03_all[2])
                    MaxMuonIso = max(
                        max(event.Muon_pfRelIso03_all[0],
                            event.Muon_pfRelIso03_all[1]),
                        event.Muon_pfRelIso03_all[2])
                    MinMuonMetDPhi = min(
                        min(abs(Lepton1.DeltaPhi(MET)),
                            abs(Lepton2.DeltaPhi(MET))),
                        abs(Lepton3.DeltaPhi(MET)))
                    MaxMuonMetDPhi = max(
                        max(abs(Lepton1.DeltaPhi(MET)),
                            abs(Lepton2.DeltaPhi(MET))),
                        abs(Lepton3.DeltaPhi(MET)))
                    MinMuonJetDR = min(
                        min(getMinMuonJetDR(cleanJet, Lepton1),
                            getMinMuonJetDR(cleanJet, Lepton2)),
                        getMinMuonJetDR(cleanJet, Lepton3))
                    LLJJ = twoJets + Lepton1 + Lepton2
                    Vis = allJets + Lepton1 + Lepton2 + Lepton3
                    # Weights
                    if self.isMC:
                        triggerWeight = self.muSFs.getTriggerSF(
                            event.Muon_pt[0], event.Muon_eta[0])
                        IdSF1 = self.muSFs.getIdSF(event.Muon_pt[0],
                                                   event.Muon_eta[0], 2)
                        IsoSF1 = self.muSFs.getIsoSF(event.Muon_pt[0],
                                                     event.Muon_eta[0])
                        IdSF2 = self.muSFs.getIdSF(event.Muon_pt[1],
                                                   event.Muon_eta[1], 2)
                        IsoSF2 = self.muSFs.getIsoSF(event.Muon_pt[1],
                                                     event.Muon_eta[1])
                        IdSF3 = self.muSFs.getIdSF(event.Muon_pt[2],
                                                   event.Muon_eta[2], 2)
                        IsoSF3 = self.muSFs.getIsoSF(event.Muon_pt[2],
                                                     event.Muon_eta[2])
                        leptonWeight = IdSF1 * IsoSF1 * IdSF2 * IsoSF2 * IdSF3 * IsoSF3

        # case 3b: 3 lepton CR (2mu 1e)
        if iSkim == 0 and event.nMuon >= 2 and event.nElectron >= 1:
            if (isSingleMuIsoTrigger or isSingleMuTrigger) and event.Muon_pt[
                    0] > 27. and event.Muon_pt[1] > 15. and event.Electron_pt[
                        0] > 15. and event.Muon_mediumId[
                            0] and event.Muon_mediumId[
                                1] and event.Electron_cutBased[
                                    0] >= 2 and event.Muon_charge[
                                        0] * event.Muon_charge[1] < 0:
                Lepton1.SetPtEtaPhiM(event.Muon_pt[0], event.Muon_eta[0],
                                     event.Muon_phi[0], event.Muon_mass[0])
                Lepton2.SetPtEtaPhiM(event.Muon_pt[1], event.Muon_eta[1],
                                     event.Muon_phi[1], event.Muon_mass[1])
                Lepton3.SetPtEtaPhiM(event.Electron_pt[0],
                                     event.Electron_eta[0],
                                     event.Electron_phi[0],
                                     event.Electron_mass[0])
                mll = (Lepton1 + Lepton2).M()
                ptll = (Lepton1 + Lepton2).Pt()
                if mll > 15.:
                    iSkim = 4
                    # Variables
                    mZ, ptZ = mll, ptll
                    dEtaLL = abs(Lepton1.Eta() - Lepton2.Eta())
                    dPhiLL = abs(Lepton1.DeltaPhi(Lepton2))
                    dRLL = Lepton1.DeltaR(Lepton2)
                    MinMuonIso = min(event.Muon_pfRelIso03_all[0],
                                     event.Muon_pfRelIso03_all[1])
                    MaxMuonIso = max(event.Muon_pfRelIso03_all[0],
                                     event.Muon_pfRelIso03_all[1])
                    MinMuonMetDPhi = min(
                        min(abs(Lepton1.DeltaPhi(MET)),
                            abs(Lepton2.DeltaPhi(MET))),
                        abs(Lepton3.DeltaPhi(MET)))
                    MaxMuonMetDPhi = max(
                        max(abs(Lepton1.DeltaPhi(MET)),
                            abs(Lepton2.DeltaPhi(MET))),
                        abs(Lepton3.DeltaPhi(MET)))
                    MinMuonJetDR = min(getMinMuonJetDR(cleanJet, Lepton1),
                                       getMinMuonJetDR(cleanJet, Lepton2))
                    LLJJ = twoJets + Lepton1 + Lepton2
                    Vis = allJets + Lepton1 + Lepton2 + Lepton3
                    # Weights
                    if self.isMC:
                        triggerWeight = self.muSFs.getTriggerSF(
                            event.Muon_pt[0], event.Muon_eta[0])
                        IdSF1 = self.muSFs.getIdSF(event.Muon_pt[0],
                                                   event.Muon_eta[0], 2)
                        IsoSF1 = self.muSFs.getIsoSF(event.Muon_pt[0],
                                                     event.Muon_eta[0])
                        IdSF2 = self.muSFs.getIdSF(event.Muon_pt[1],
                                                   event.Muon_eta[1], 2)
                        IsoSF2 = self.muSFs.getIsoSF(event.Muon_pt[1],
                                                     event.Muon_eta[1])
                        IdIsoSF3 = self.elSFs.getIdIsoSF(
                            event.Electron_pt[0], event.Electron_eta[0])
                        leptonWeight = IdSF1 * IsoSF1 * IdSF2 * IsoSF2 * IdIsoSF3

        # case 1: Z->mumu CR (2 mu)
        if iSkim == 0 and event.nMuon >= 2:
            if (isSingleMuIsoTrigger or isSingleMuTrigger) and event.Muon_pt[
                    0] > 27. and event.Muon_pt[1] > 7. and event.Muon_mediumId[
                        0] and event.Muon_mediumId[1]:
                Lepton1.SetPtEtaPhiM(event.Muon_pt[0], event.Muon_eta[0],
                                     event.Muon_phi[0], event.Muon_mass[0])
                Lepton2.SetPtEtaPhiM(event.Muon_pt[1], event.Muon_eta[1],
                                     event.Muon_phi[1], event.Muon_mass[1])
                mll = (Lepton1 + Lepton2).M()
                ptll = (Lepton1 + Lepton2).Pt()
                if mll > 15.:
                    iSkim = 1
                    # Variables
                    mZ, ptZ = mll, ptll
                    dEtaLL = abs(Lepton1.Eta() - Lepton2.Eta())
                    dPhiLL = abs(Lepton1.DeltaPhi(Lepton2))
                    dRLL = Lepton1.DeltaR(Lepton2)
                    MinMuonIso = min(event.Muon_pfRelIso03_all[0],
                                     event.Muon_pfRelIso03_all[1])
                    MaxMuonIso = max(event.Muon_pfRelIso03_all[0],
                                     event.Muon_pfRelIso03_all[1])
                    MinMuonMetDPhi = min(abs(Lepton1.DeltaPhi(MET)),
                                         abs(Lepton2.DeltaPhi(MET)))
                    MaxMuonMetDPhi = max(abs(Lepton1.DeltaPhi(MET)),
                                         abs(Lepton2.DeltaPhi(MET)))
                    MinMuonJetDR = min(getMinMuonJetDR(cleanJet, Lepton1),
                                       getMinMuonJetDR(cleanJet, Lepton2))
                    LLJJ = twoJets + Lepton1 + Lepton2
                    Vis = allJets + Lepton1 + Lepton2
                    # Weights
                    if self.isMC:
                        triggerWeight = self.muSFs.getTriggerSF(
                            event.Muon_pt[0], event.Muon_eta[0])
                        IdSF1 = self.muSFs.getIdSF(event.Muon_pt[0],
                                                   event.Muon_eta[0], 2)
                        IdSF2 = self.muSFs.getIdSF(event.Muon_pt[1],
                                                   event.Muon_eta[1], 2)
                        IsoSF1 = self.muSFs.getIsoSF(event.Muon_pt[0],
                                                     event.Muon_eta[0])
                        IsoSF2 = self.muSFs.getIsoSF(event.Muon_pt[1],
                                                     event.Muon_eta[1])
                        leptonWeight = IdSF1 * IdSF2 * IsoSF1 * IsoSF2

        # case 4: Z->ee CR (2 electrons)
        if iSkim == 0 and event.nElectron >= 2:
            if isSingleEleIsoTrigger and event.Electron_pt[
                    0] > 35. and event.Electron_pt[
                        1] > 10. and event.Electron_cutBased[
                            0] > 0 and event.Electron_cutBased[1] > 0:
                Lepton1.SetPtEtaPhiM(event.Electron_pt[0],
                                     event.Electron_eta[0],
                                     event.Electron_phi[0],
                                     event.Electron_mass[0])
                Lepton2.SetPtEtaPhiM(event.Electron_pt[1],
                                     event.Electron_eta[1],
                                     event.Electron_phi[1],
                                     event.Electron_mass[1])
                mll = (Lepton1 + Lepton2).M()
                ptll = (Lepton1 + Lepton2).Pt()
                if mll > 15.:
                    iSkim = 6
                    # Variables
                    mZ, ptZ = mll, ptll
                    dEtaLL = abs(Lepton1.Eta() - Lepton2.Eta())
                    dPhiLL = abs(Lepton1.DeltaPhi(Lepton2))
                    dRLL = Lepton1.DeltaR(Lepton2)
                    MinMuonIso = event.Electron_pfRelIso03_all[0]
                    MaxMuonIso = event.Electron_pfRelIso03_all[0]
                    MinMuonMetDPhi = min(abs(Lepton1.DeltaPhi(MET)),
                                         abs(Lepton2.DeltaPhi(MET)))
                    MaxMuonMetDPhi = max(abs(Lepton1.DeltaPhi(MET)),
                                         abs(Lepton2.DeltaPhi(MET)))
                    MinMuonJetDR = min(getMinMuonJetDR(cleanJet, Lepton1),
                                       getMinMuonJetDR(cleanJet, Lepton2))
                    LLJJ = twoJets + Lepton1 + Lepton2
                    Vis = allJets + Lepton1 + Lepton2
                    # Weights
                    if self.isMC:
                        triggerWeight = self.elSFs.getTriggerSF(
                            event.Electron_pt[0], event.Electron_eta[0])
                        leptonWeight = self.elSFs.getIdIsoSF(
                            event.Electron_pt[0],
                            event.Electron_eta[0]) * self.elSFs.getIdIsoSF(
                                event.Electron_pt[1], event.Electron_eta[1])

        # case 2: ttbar and Z OF CR (1 muon and 1 electron)
        if iSkim == 0 and event.nMuon >= 1 and event.nElectron >= 1:
            if (isSingleMuIsoTrigger or isSingleMuTrigger
                ) and event.Muon_pt[0] > 27. and event.Electron_pt[
                    0] > 20. and event.Muon_mediumId[
                        0] and event.Electron_cutBased[0] >= 2:
                Lepton1.SetPtEtaPhiM(event.Muon_pt[0], event.Muon_eta[0],
                                     event.Muon_phi[0], event.Muon_mass[0])
                Lepton2.SetPtEtaPhiM(event.Electron_pt[0],
                                     event.Electron_eta[0],
                                     event.Electron_phi[0],
                                     event.Electron_mass[0])
                mll = (Lepton1 + Lepton2).M()
                ptll = (Lepton1 + Lepton2).Pt()
                if mll > 15.:
                    iSkim = 2
                    # Variables
                    mZ, ptZ = mll, ptll
                    dEtaLL = abs(Lepton1.Eta() - Lepton2.Eta())
                    dPhiLL = abs(Lepton1.DeltaPhi(Lepton2))
                    dRLL = Lepton1.DeltaR(Lepton2)
                    MinMuonIso = event.Muon_pfRelIso03_all[0]
                    MaxMuonIso = event.Muon_pfRelIso03_all[0]
                    MinMuonMetDPhi = abs(Lepton1.DeltaPhi(MET))
                    MaxMuonMetDPhi = abs(Lepton1.DeltaPhi(MET))
                    MinMuonJetDR = min(getMinMuonJetDR(cleanJet, Lepton1),
                                       getMinMuonJetDR(cleanJet, Lepton2))
                    LLJJ = twoJets + Lepton1 + Lepton2
                    Vis = allJets + Lepton1 + Lepton2
                    # Weights
                    if self.isMC:
                        triggerWeight = self.muSFs.getTriggerSF(
                            Lepton1.Pt(), Lepton1.Eta())
                        IdSF1 = self.muSFs.getIdSF(event.Muon_pt[0],
                                                   event.Muon_eta[0], 2)
                        IsoSF1 = self.muSFs.getIsoSF(event.Muon_pt[0],
                                                     event.Muon_eta[0])
                        IdIsoSF2 = self.elSFs.getIdIsoSF(
                            event.Electron_pt[0], event.Electron_eta[0])
                        leptonWeight = IdSF1 * IsoSF1 * IdIsoSF2

        # case 4: ttbar CR (1 muon and >= 3 jets)
        if iSkim == 0 and event.nMuon >= 1:
            if (isSingleMuIsoTrigger or isSingleMuTrigger
                ) and event.Muon_pt[0] > 27. and event.Muon_mediumId[
                    0] and event.Muon_pfRelIso03_all[0] < 0.15:
                Lepton1.SetPtEtaPhiM(event.Muon_pt[0], event.Muon_eta[0],
                                     event.Muon_phi[0], event.Muon_mass[0])
                pzN = recoverNeutrinoPz(Lepton1, MET)
                Neutrino.SetPxPyPzE(MET.Px(), MET.Py(), pzN, MET.Pt())
                mW = (Lepton1 + Neutrino).M()
                ptW = (Lepton1 + Neutrino).Pt()
                mT = math.sqrt(2. * Lepton1.Pt() * MET.Pt() *
                               (1. - math.cos(Lepton1.DeltaPhi(MET))))
                if Nj30 >= 3:  # and nBJet >= 1:
                    iSkim = 5
                    # Variables
                    MinMuonIso = event.Muon_pfRelIso03_all[0]
                    MaxMuonIso = event.Muon_pfRelIso03_all[0]
                    MinMuonMetDPhi = abs(Lepton1.DeltaPhi(MET))
                    MaxMuonMetDPhi = abs(Lepton1.DeltaPhi(MET))
                    MinMuonJetDR = getMinMuonJetDR(cleanJet, Lepton1)
                    LLJJ = twoJets + Lepton1
                    Vis = allJets + Lepton1
                    # W and Top reconstruction
                    if len(cleanBJet) >= 2:
                        mLepTop1 = (Lepton1 + Neutrino + cleanBJet[0]).M()
                        mLepTop2 = (Lepton1 + Neutrino + cleanBJet[1]).M()
                    elif len(cleanBJet) >= 1:
                        mLepTop1 = (Lepton1 + Neutrino + cleanBJet[0]).M()
                        mHadTop2 = mHadTop1
                    if len(cleanNonBJet) >= 2:
                        mHadW = (cleanNonBJet[0] + cleanNonBJet[1]).M()
                        if len(cleanBJet) >= 2:
                            mHadTop1 = (cleanNonBJet[0] + cleanNonBJet[1] +
                                        cleanBJet[0]).M()
                            mHadTop2 = (cleanNonBJet[0] + cleanNonBJet[1] +
                                        cleanBJet[1]).M()
                        elif len(cleanBJet) >= 1:
                            mHadTop1 = (cleanNonBJet[0] + cleanNonBJet[1] +
                                        cleanBJet[0]).M()
                            mHadTop2 = mHadTop1
                    # Weights
                    if self.isMC:
                        triggerWeight = self.muSFs.getTriggerSF(
                            Lepton1.Pt(), Lepton1.Eta())
                        IdSF1 = self.muSFs.getIdSF(event.Muon_pt[0],
                                                   event.Muon_eta[0], 2)
                        IsoSF1 = self.muSFs.getIsoSF(event.Muon_pt[0],
                                                     event.Muon_eta[0])
                        leptonWeight = IdSF1 * IsoSF1

        passedMETFilters = True
        filters = [
            "Flag_goodVertices", "Flag_globalSuperTightHalo2016Filter",
            "Flag_BadPFMuonFilter", "Flag_EcalDeadCellTriggerPrimitiveFilter",
            "Flag_HBHENoiseFilter", "Flag_HBHENoiseIsoFilter",
            "Flag_ecalBadCalibFilter", "Flag_ecalBadCalibFilterV2"
        ]
        if not self.isMC: filters += ["Flag_eeBadScFilter"]
        for f in filters:
            if hasattr(event, f) and getattr(event, f) == False:
                passedMETFilters = False
#        try:
##            if event.Flag_goodVertices: print "Flag_goodVertices"
##            if event.Flag_globalSuperTightHalo2016Filter: print "Flag_globalSuperTightHalo2016Filter"
##            if event.Flag_BadPFMuonFilter: print "Flag_BadPFMuonFilter"
##            if event.Flag_EcalDeadCellTriggerPrimitiveFilter: print "Flag_EcalDeadCellTriggerPrimitiveFilter"
##            if event.Flag_HBHENoiseFilter: print "Flag_HBHENoiseFilter"
##            if event.Flag_HBHENoiseIsoFilter: print "Flag_HBHENoiseIsoFilter"
###            if (self.isMC or event.Flag_eeBadScFilter): print "Flag_eeBadScFilter"
##            if event.Flag_ecalBadCalibFilter: print "Flag_ecalBadCalibFilterV2"
#            if event.Flag_goodVertices and event.Flag_globalSuperTightHalo2016Filter and event.Flag_BadPFMuonFilter and event.Flag_EcalDeadCellTriggerPrimitiveFilter and event.Flag_HBHENoiseFilter and event.Flag_HBHENoiseIsoFilter: # and event.Flag_ecalBadCalibFilter: #and (self.isMC or event.Flag_eeBadScFilter): FIXME
#                passedMETFilters = True
##            if not self.isMC:
##                if not event.Flag_eeBadScFilter:
##                    passedMETFilters = False
#        except:
#            passedMETFilters = False

        if iSkim == 0: return False

        if self.isMC:
            eventWeightLumi = self.lumiWeight * lheWeight * puWeight * topWeight * qcdnloWeight * qcdnnloWeight * ewknloWeight * triggerWeight * leptonWeight

        self.out.fillBranch("iSkim", iSkim)
        self.out.fillBranch("isMC", self.isMC)
        self.out.fillBranch("isSingleMuIsoTrigger", isSingleMuIsoTrigger)
        self.out.fillBranch("isSingleMuTrigger", isSingleMuTrigger)
        self.out.fillBranch("isDoubleMuonTrigger", isDoubleMuonTrigger)
        self.out.fillBranch("isSingleEleIsoTrigger", isSingleEleIsoTrigger)
        self.out.fillBranch("isSingleEleTrigger", isSingleEleTrigger)
        self.out.fillBranch("passedMETFilters", passedMETFilters)
        self.out.fillBranch("nCleanElectron", len(cleanElectron))
        self.out.fillBranch("nCleanMuon", len(cleanMuon))
        self.out.fillBranch("nCleanJet", len(cleanJet))
        self.out.fillBranch("Z_mass", mZ)
        self.out.fillBranch("Z_pt", ptZ)
        self.out.fillBranch("W_mass", mW)
        self.out.fillBranch("W_tmass", mT)
        self.out.fillBranch("W_pt", ptW)
        self.out.fillBranch("ll_dEta", dEtaLL)
        self.out.fillBranch("ll_dPhi", dPhiLL)
        self.out.fillBranch("ll_dR", dRLL)
        self.out.fillBranch("Wqq_mass", mHadW)
        self.out.fillBranch("Tlvb1_mass", mLepTop1)
        self.out.fillBranch("Tlvb2_mass", mLepTop2)
        self.out.fillBranch("Tqqb1_mass", mHadTop1)
        self.out.fillBranch("Tqqb2_mass", mHadTop2)
        self.out.fillBranch("jj_mass", mJJ)
        self.out.fillBranch("jj_pt", ptJJ)
        self.out.fillBranch("jj_dEta", dEtaJJ)
        self.out.fillBranch("jj_dPhi", dPhiJJ)
        self.out.fillBranch("jj_dR", dRJJ)
        self.out.fillBranch("nj_mass", mNJ)
        self.out.fillBranch("vis_mass", Vis.M())
        self.out.fillBranch("lljj_mass", LLJJ.M())
        self.out.fillBranch("minMuonIso", MinMuonIso)
        self.out.fillBranch("maxMuonIso", MaxMuonIso)
        self.out.fillBranch("minMuonMetDPhi", MinMuonMetDPhi)
        self.out.fillBranch("maxMuonMetDPhi", MaxMuonMetDPhi)
        self.out.fillBranch("minMuonJetDR", MinMuonJetDR)
        self.out.fillBranch("HT30", HT30)
        self.out.fillBranch("nj20", Nj20)
        self.out.fillBranch("nj30", Nj30)
        self.out.fillBranch("nj40", Nj40)
        self.out.fillBranch("nBJet", nBJet)
        self.out.fillBranch("CSV1", CSV1)
        self.out.fillBranch("CSV2", CSV2)
        self.out.fillBranch("CSV3", CSV3)
        self.out.fillBranch("CSV4", CSV4)
        self.out.fillBranch("iCSV1", iCSV1)
        self.out.fillBranch("iCSV2", iCSV2)
        self.out.fillBranch("iCSV3", iCSV3)
        self.out.fillBranch("iCSV4", iCSV4)
        self.out.fillBranch("lumiWeight", self.lumiWeight)
        self.out.fillBranch("lheWeight", lheWeight)
        self.out.fillBranch("stitchWeight", stitchWeight)
        self.out.fillBranch("puWeight", puWeight)
        self.out.fillBranch("topWeight", topWeight)
        self.out.fillBranch("qcdnloWeight", qcdnloWeight)
        self.out.fillBranch("qcdnnloWeight", qcdnnloWeight)
        self.out.fillBranch("ewknloWeight", ewknloWeight)
        self.out.fillBranch("triggerWeight", triggerWeight)
        self.out.fillBranch("leptonWeight", leptonWeight)
        self.out.fillBranch("eventWeightLumi", eventWeightLumi)

        return True
Esempio n. 3
0
class EleTauProducer(Module):
    def __init__(self, name, dataType, **kwargs):

        self.name = name
        self.out = TreeProducerEleTau(name)
        self.isData = dataType == 'data'
        self.year = kwargs.get('year', 2017)
        self.tes = kwargs.get('tes', 1.0)
        self.ltf = kwargs.get('ltf', 1.0)
        self.jtf = kwargs.get('jtf', 1.0)
        self.doZpt = kwargs.get('doZpt', 'DY' in name)
        self.doRecoil = kwargs.get(
            'doRecoil', ('DY' in name or re.search(r"W\d?Jets", name))
            and self.year > 2016)
        self.doTTpt = kwargs.get('doTTpt', 'TT' in name)
        self.doTight = kwargs.get('doTight', self.tes != 1 or self.ltf != 1)
        self.channel = 'eletau'
        year, channel = self.year, self.channel

        self.vlooseIso = getVLooseTauIso(year)
        if year == 2016:
            self.trigger = lambda e: e.HLT_Ele25_eta2p1_WPTight_Gsf or e.HLT_Ele27_WPTight_Gsf  #or e.HLT_Ele45_WPLoose_Gsf_L1JetTauSeeded #or e.HLT_Ele24_eta2p1_WPLoose_Gsf_LooseIsoPFTau20_SingleL1 or e.HLT_Ele24_eta2p1_WPLoose_Gsf_LooseIsoPFTau20 or e.HLT_Ele24_eta2p1_WPLoose_Gsf_LooseIsoPFTau30
            self.eleCutPt = 26
        elif year == 2017:
            self.trigger = lambda e: e.HLT_Ele35_WPTight_Gsf or e.HLT_Ele32_WPTight_Gsf_L1DoubleEG or e.HLT_Ele32_WPTight_Gsf
            self.eleCutPt = 36
        else:
            self.trigger = lambda e: e.HLT_Ele32_WPTight_Gsf or e.HLT_Ele35_WPTight_Gsf
            self.eleCutPt = 33
        self.tauCutPt = 20

        if not self.isData:
            self.eleSFs = ElectronSFs(year=year)
            self.puTool = PileupWeightTool(year=year)
            self.ltfSFs = LeptonTauFakeSFs('loose', 'tight', year=year)
            self.btagTool = BTagWeightTool('DeepCSV',
                                           'medium',
                                           channel='mutau',
                                           year=year)
            if self.doZpt:
                self.zptTool = ZptCorrectionTool(year=year)
            if self.doRecoil:
                self.recoilTool = RecoilCorrectionTool(year=year)
        self.deepcsv_wp = BTagWPs('DeepCSV', year=year)

        self.Nocut = 0
        self.Trigger = 1
        self.GoodElectrons = 2
        self.GoodTaus = 3
        self.GoodDiLepton = 4
        self.TotalWeighted = 15
        self.TotalWeighted_no0PU = 16

        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.Nocut, "no cut")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.Trigger, "trigger")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodElectrons,
                                                "electron object")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodTaus,
                                                "tau object")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodDiLepton,
                                                "eletau pair")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.TotalWeighted,
                                                "no cut, weighted")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.TotalWeighted_no0PU,
                                                "no cut, weighted, PU>0")
        self.out.cutflow.GetXaxis().SetLabelSize(0.041)

    def beginJob(self):
        pass

    def endJob(self):
        if not self.isData:
            self.btagTool.setDirectory(self.out.outputfile, 'btag')
        self.out.endJob()

    def beginFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        sys.stdout.flush()
        checkBranches(inputTree)

    def endFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        pass

    def analyze(self, event):
        """process event, return True (go to next module) or False (fail, go to next event)"""
        sys.stdout.flush()

        #####################################
        self.out.cutflow.Fill(self.Nocut)
        if self.isData:
            self.out.cutflow.Fill(self.TotalWeighted, 1.)
            if event.PV_npvs > 0:
                self.out.cutflow.Fill(self.TotalWeighted_no0PU, 1.)
            else:
                return False
        else:
            self.out.cutflow.Fill(self.TotalWeighted, event.genWeight)
            if event.Pileup_nTrueInt > 0:
                self.out.cutflow.Fill(self.TotalWeighted_no0PU,
                                      event.genWeight)
            else:
                return False
        #####################################

        if not self.trigger(event):
            return False

        #####################################
        self.out.cutflow.Fill(self.Trigger)
        #####################################

        idx_goodelectrons = []
        for ielectron in range(event.nElectron):
            if event.Electron_pt[ielectron] < self.eleCutPt: continue
            if abs(event.Electron_eta[ielectron]) > 2.1: continue
            if abs(event.Electron_dz[ielectron]) > 0.2: continue
            if abs(event.Electron_dxy[ielectron]) > 0.045: continue
            if event.Electron_convVeto[ielectron] != 1: continue
            if ord(event.Electron_lostHits[ielectron]) > 1: continue
            if event.Electron_mvaFall17V2Iso_WP80[ielectron] < 0.5: continue
            idx_goodelectrons.append(ielectron)

        if len(idx_goodelectrons) == 0:
            return False

        #####################################
        self.out.cutflow.Fill(self.GoodElectrons)
        #####################################

        Tau_genmatch = {}  # bug in Tau_genPartFlav
        idx_goodtaus = []
        for itau in range(event.nTau):
            if not self.vlooseIso(event, itau): continue
            if abs(event.Tau_eta[itau]) > 2.3: continue
            if abs(event.Tau_dz[itau]) > 0.2: continue
            if event.Tau_decayMode[itau] not in [0, 1, 10]: continue
            if abs(event.Tau_charge[itau]) != 1: continue
            if not self.isData:
                Tau_genmatch[itau] = genmatch(event, itau)
                #if self.tes!=1.0 and Tau_genmatch[itau]==5:
                #  event.Tau_pt[itau]   *= self.tes
                #  event.Tau_mass[itau] *= self.tes
                #elif self.ltf!=1.0 and 0<Tau_genmatch[itau]<5:
                #  event.Tau_pt[itau]   *= self.ltf
                #  event.Tau_mass[itau] *= self.ltf
                #elif self.jtf!=1.0 and Tau_genmatch[itau]==0:
                #  event.Tau_pt[itau]   *= self.jtf
                #  event.Tau_mass[itau] *= self.jtf
            if event.Tau_pt[itau] < self.tauCutPt: continue
            ###if ord(event.Tau_idAntiEle[itau])<1: continue
            ###if ord(event.Tau_idAntiMu[itau])<1: continue
            idx_goodtaus.append(itau)

        if len(idx_goodtaus) == 0:
            return False

        #####################################
        self.out.cutflow.Fill(self.GoodTaus)
        #####################################

        electrons = Collection(event, 'Electron')
        taus = Collection(event, 'Tau')
        ltaus = []
        for idx1 in idx_goodelectrons:
            for idx2 in idx_goodtaus:
                dR = taus[idx2].p4().DeltaR(electrons[idx1].p4())
                if dR < 0.5: continue
                ltau = LeptonTauPair(idx1, event.Electron_pt[idx1],
                                     event.Electron_pfRelIso03_all[idx1], idx2,
                                     event.Tau_pt[idx2],
                                     event.Tau_rawMVAoldDM2017v2[idx2])
                ltaus.append(ltau)

        if len(ltaus) == 0:
            return False

        ltau = bestDiLepton(ltaus)
        electron = electrons[ltau.id1].p4()
        tau = taus[ltau.id2].p4()
        #print 'chosen tau1 (idx, pt) = ', ltau.id1, ltau.tau1_pt, 'check', electron.p4().Pt()
        #print 'chosen tau2 (idx, pt) = ', ltau.id2, ltau.tau2_pt, 'check', tau.p4().Pt()

        #####################################
        self.out.cutflow.Fill(self.GoodDiLepton)
        #####################################

        # VETOS
        self.out.extramuon_veto[0], self.out.extraelec_veto[
            0], self.out.dilepton_veto[0] = extraLeptonVetos(
                event, [-1], [ltau.id1], self.channel)
        self.out.lepton_vetos[0] = self.out.extramuon_veto[
            0] or self.out.extraelec_veto[0] or self.out.dilepton_veto[0]
        ###if self.doTight and (self.out.lepton_vetos[0] or event.Electron_pfRelIso03_all[ltau.id1]>0.10 or\
        ###                     ord(event.Tau_idAntiMu[ltau.id2]<1 or ord(event.Tau_idAntiEle[ltau.id2]<8):
        ###  return False

        # JETS
        jetIds = []
        bjetIds = []
        jets = Collection(event, 'Jet')
        nfjets = 0
        ncjets = 0
        nbtag = 0
        for ijet in range(event.nJet):
            if event.Jet_pt[ijet] < 30: continue
            if abs(event.Jet_eta[ijet]) > 4.7: continue
            if electron.DeltaR(jets[ijet].p4()) < 0.5: continue
            if tau.DeltaR(jets[ijet].p4()) < 0.5: continue
            jetIds.append(ijet)

            if abs(event.Jet_eta[ijet]) > 2.4:
                nfjets += 1
            else:
                ncjets += 1

            if event.Jet_btagDeepB[ijet] > self.deepcsv_wp.medium:
                nbtag += 1
                bjetIds.append(ijet)

        if not self.isData and self.vlooseIso(
                event,
                ltau.id2) and event.Electron_pfRelIso03_all[ltau.id1] < 0.50:
            self.btagTool.fillEfficiencies(event, jetIds)

        # EVENT
        self.out.isData[0] = self.isData
        self.out.run[0] = event.run
        self.out.lumi[0] = event.luminosityBlock
        self.out.event[0] = event.event & 0xffffffffffffffff
        ###self.out.puppimet[0]                  = event.PuppiMET_pt
        ###self.out.puppimetphi[0]               = event.PuppiMET_phi
        ###self.out.metsignificance[0]           = event.MET_significance
        ###self.out.metcovXX[0]                  = event.MET_covXX
        ###self.out.metcovXY[0]                  = event.MET_covXY
        ###self.out.metcovYY[0]                  = event.MET_covYY
        self.out.npvs[0] = event.PV_npvs
        self.out.npvsGood[0] = event.PV_npvsGood

        if not self.isData:
            self.out.genmet[0] = event.GenMET_pt
            self.out.genmetphi[0] = event.GenMET_phi
            self.out.nPU[0] = event.Pileup_nPU
            self.out.nTrueInt[0] = event.Pileup_nTrueInt
            try:
                self.out.LHE_Njets[0] = event.LHE_Njets
            except RuntimeError:
                self.out.LHE_Njets[0] = -1

        # ELECTRON
        self.out.pt_1[0] = event.Electron_pt[ltau.id1]
        self.out.eta_1[0] = event.Electron_eta[ltau.id1]
        self.out.phi_1[0] = event.Electron_phi[ltau.id1]
        self.out.m_1[0] = event.Electron_mass[ltau.id1]
        self.out.dxy_1[0] = event.Electron_dxy[ltau.id1]
        self.out.dz_1[0] = event.Electron_dz[ltau.id1]
        self.out.q_1[0] = event.Electron_charge[ltau.id1]
        self.out.pfRelIso03_all_1[0] = event.Electron_pfRelIso03_all[ltau.id1]
        self.out.cutBased_1[0] = event.Electron_cutBased[ltau.id1]
        self.out.mvaFall17Iso_1[0] = event.Electron_mvaFall17V2Iso[ltau.id1]
        self.out.mvaFall17Iso_WPL_1[0] = event.Electron_mvaFall17V2Iso_WPL[
            ltau.id1]
        self.out.mvaFall17Iso_WP80_1[0] = event.Electron_mvaFall17V2Iso_WP80[
            ltau.id1]
        self.out.mvaFall17Iso_WP90_1[0] = event.Electron_mvaFall17V2Iso_WP90[
            ltau.id1]

        # TAU
        self.out.pt_2[0] = event.Tau_pt[ltau.id2]
        self.out.eta_2[0] = event.Tau_eta[ltau.id2]
        self.out.phi_2[0] = event.Tau_phi[ltau.id2]
        self.out.m_2[0] = event.Tau_mass[ltau.id2]
        self.out.dxy_2[0] = event.Tau_dxy[ltau.id2]
        self.out.dz_2[0] = event.Tau_dz[ltau.id2]
        self.out.leadTkPtOverTauPt_2[0] = event.Tau_leadTkPtOverTauPt[ltau.id2]
        self.out.chargedIso_2[0] = event.Tau_chargedIso[ltau.id2]
        self.out.neutralIso_2[0] = event.Tau_neutralIso[ltau.id2]
        self.out.photonsOutsideSignalCone_2[
            0] = event.Tau_photonsOutsideSignalCone[ltau.id2]
        self.out.puCorr_2[0] = event.Tau_puCorr[ltau.id2]
        self.out.rawAntiEle_2[0] = event.Tau_rawAntiEle[ltau.id2]
        self.out.rawIso_2[0] = event.Tau_rawIso[ltau.id2]
        self.out.q_2[0] = event.Tau_charge[ltau.id2]
        self.out.decayMode_2[0] = event.Tau_decayMode[ltau.id2]
        ###self.out.rawAntiEleCat_2[0]            = event.Tau_rawAntiEleCat[ltau.id2]
        self.out.idAntiEle_2[0] = ord(event.Tau_idAntiEle[ltau.id2])
        self.out.idAntiMu_2[0] = ord(event.Tau_idAntiMu[ltau.id2])
        self.out.idDecayMode_2[0] = event.Tau_idDecayMode[ltau.id2]
        self.out.idDecayModeNewDMs_2[0] = event.Tau_idDecayModeNewDMs[ltau.id2]
        self.out.rawMVAoldDM_2[0] = event.Tau_rawMVAoldDM[ltau.id2]
        self.out.rawMVAnewDM2017v2_2[0] = event.Tau_rawMVAnewDM2017v2[ltau.id2]
        self.out.rawMVAoldDM2017v1_2[0] = event.Tau_rawMVAoldDM2017v1[ltau.id2]
        self.out.rawMVAoldDM2017v2_2[0] = event.Tau_rawMVAoldDM2017v2[ltau.id2]
        self.out.idMVAoldDM_2[0] = ord(event.Tau_idMVAoldDM[ltau.id2])
        self.out.idMVAoldDM2017v1_2[0] = ord(
            event.Tau_idMVAoldDM2017v1[ltau.id2])
        self.out.idMVAoldDM2017v2_2[0] = ord(
            event.Tau_idMVAoldDM2017v2[ltau.id2])
        self.out.idMVAnewDM2017v2_2[0] = ord(
            event.Tau_idMVAnewDM2017v2[ltau.id2])

        # GENERATOR
        if not self.isData:
            self.out.genPartFlav_1[0] = ord(
                event.Electron_genPartFlav[ltau.id1])
            self.out.genPartFlav_2[0] = Tau_genmatch[
                ltau.id2]  # ord(event.Tau_genPartFlav[ltau.id2])

            genvistau = Collection(event, 'GenVisTau')
            dRmax = 1000
            gendm = -1
            genpt = -1
            geneta = -1
            genphi = -1
            for igvt in range(event.nGenVisTau):
                dR = genvistau[igvt].p4().DeltaR(tau)
                if dR < 0.5 and dR < dRmax:
                    dRmax = dR
                    gendm = event.GenVisTau_status[igvt]
                    genpt = event.GenVisTau_pt[igvt]
                    geneta = event.GenVisTau_eta[igvt]
                    genphi = event.GenVisTau_phi[igvt]

            self.out.gendecayMode_2[0] = gendm
            self.out.genvistaupt_2[0] = genpt
            self.out.genvistaueta_2[0] = geneta
            self.out.genvistauphi_2[0] = genphi

        # WEIGHTS
        met = TLorentzVector()
        met.SetPxPyPzE(event.MET_pt * cos(event.MET_phi),
                       event.MET_pt * sin(event.MET_phi), 0, event.MET_pt)
        if not self.isData:
            if self.doRecoil:
                boson, boson_vis = getBoson(event)
                self.recoilTool.CorrectPFMETByMeanResolution(
                    met, boson, boson_vis, len(jetIds))
                event.MET_pt = met.Pt()
                event.MET_phi = met.Phi()
                self.out.m_genboson[0] = boson.M()
                self.out.pt_genboson[0] = boson.Pt()
                if self.doZpt:
                    self.out.zptweight[0] = self.zptTool.getZptWeight(
                        boson.Pt(), boson.M())
            elif self.doZpt:
                zboson = getZBoson(event)
                self.out.m_genboson[0] = zboson.M()
                self.out.pt_genboson[0] = zboson.Pt()
                self.out.zptweight[0] = self.zptTool.getZptWeight(
                    zboson.Pt(), zboson.M())
            elif self.doTTpt:
                toppt1, toppt2 = getTTPt(event)
                self.out.ttptweight[0] = getTTptWeight(toppt1, toppt2)
            self.out.genweight[0] = event.genWeight
            self.out.puweight[0] = self.puTool.getWeight(event.Pileup_nTrueInt)
            self.out.trigweight[0] = self.eleSFs.getTriggerSF(
                self.out.pt_1[0], self.out.eta_1[0])
            self.out.idisoweight_1[0] = self.eleSFs.getIdIsoSF(
                self.out.pt_1[0], self.out.eta_1[0])
            self.out.idisoweight_2[0] = self.ltfSFs.getSF(
                self.out.genPartFlav_2[0], self.out.eta_2[0])
            self.out.btagweight[0] = self.btagTool.getWeight(event, jetIds)
            self.out.weight[0] = self.out.genweight[0] * self.out.puweight[
                0] * self.out.trigweight[0] * self.out.idisoweight_1[
                    0] * self.out.idisoweight_2[0]

        # JETS
        self.out.njets[0] = len(jetIds)
        self.out.njets50[0] = len([j for j in jetIds if event.Jet_pt[j] > 50])
        self.out.nfjets[0] = nfjets
        self.out.ncjets[0] = ncjets
        self.out.nbtag[0] = nbtag

        if len(jetIds) > 0:
            self.out.jpt_1[0] = event.Jet_pt[jetIds[0]]
            self.out.jeta_1[0] = event.Jet_eta[jetIds[0]]
            self.out.jphi_1[0] = event.Jet_phi[jetIds[0]]
            self.out.jdeepb_1[0] = event.Jet_btagDeepB[jetIds[0]]
        else:
            self.out.jpt_1[0] = -9.
            self.out.jeta_1[0] = -9.
            self.out.jphi_1[0] = -9.
            self.out.jdeepb_1[0] = -9.

        if len(jetIds) > 1:
            self.out.jpt_2[0] = event.Jet_pt[jetIds[1]]
            self.out.jeta_2[0] = event.Jet_eta[jetIds[1]]
            self.out.jphi_2[0] = event.Jet_phi[jetIds[1]]
            self.out.jdeepb_2[0] = event.Jet_btagDeepB[jetIds[1]]
        else:
            self.out.jpt_2[0] = -9.
            self.out.jeta_2[0] = -9.
            self.out.jphi_2[0] = -9.
            self.out.jdeepb_2[0] = -9.

        if len(bjetIds) > 0:
            self.out.bpt_1[0] = event.Jet_pt[bjetIds[0]]
            self.out.beta_1[0] = event.Jet_eta[bjetIds[0]]
        else:
            self.out.bpt_1[0] = -9.
            self.out.beta_1[0] = -9.

        if len(bjetIds) > 1:
            self.out.bpt_2[0] = event.Jet_pt[bjetIds[1]]
            self.out.beta_2[0] = event.Jet_eta[bjetIds[1]]
        else:
            self.out.bpt_2[0] = -9.
            self.out.beta_2[0] = -9.

        self.out.met[0] = event.MET_pt
        self.out.metphi[0] = event.MET_phi
        self.out.pfmt_1[0] = sqrt(
            2 * self.out.pt_1[0] * self.out.met[0] *
            (1 - cos(deltaPhi(self.out.phi_1[0], self.out.metphi[0]))))
        self.out.pfmt_2[0] = sqrt(
            2 * self.out.pt_2[0] * self.out.met[0] *
            (1 - cos(deltaPhi(self.out.phi_2[0], self.out.metphi[0]))))

        self.out.m_vis[0] = (electron + tau).M()
        self.out.pt_ll[0] = (electron + tau).Pt()
        self.out.dR_ll[0] = electron.DeltaR(tau)
        self.out.dphi_ll[0] = deltaPhi(self.out.phi_1[0], self.out.phi_2[0])
        self.out.deta_ll[0] = abs(self.out.eta_1[0] - self.out.eta_2[0])

        # PZETA
        leg1 = TVector3(electron.Px(), electron.Py(), 0.)
        leg2 = TVector3(tau.Px(), tau.Py(), 0.)
        zetaAxis = TVector3(leg1.Unit() + leg2.Unit()).Unit()
        pzeta_vis = leg1 * zetaAxis + leg2 * zetaAxis
        pzeta_miss = met.Vect() * zetaAxis
        self.out.pzetamiss[0] = pzeta_miss
        self.out.pzetavis[0] = pzeta_vis
        self.out.dzeta[0] = pzeta_miss - 0.85 * pzeta_vis

        self.out.tree.Fill()
        return True
Esempio n. 4
0
class EleMuProducer(Module):
    def __init__(self, name, dataType, **kwargs):

        self.name = name
        self.out = TreeProducerEleMu(name)
        self.isData = dataType == 'data'
        self.year = kwargs.get('year', 2017)
        self.tes = kwargs.get('tes', 1.0)
        self.ltf = kwargs.get('ltf', 1.0)
        self.doZpt = kwargs.get('doZpt', 'DY' in name)
        self.doRecoil = kwargs.get(
            'doRecoil', ('DY' in name or re.search(r"W\d?Jets", name))
            and self.year > 2016)
        self.doTTpt = kwargs.get('doTTpt', 'TT' in name)
        self.doTight = kwargs.get('doTight', self.tes != 1 or self.ltf != 1)
        self.channel = 'elemu'
        year, channel = self.year, self.channel

        if year == 2016:
            self.trigger = lambda e: e.HLT_IsoMu22 or e.HLT_IsoMu22_eta2p1 or e.HLT_IsoTkMu22 or e.HLT_IsoTkMu22_eta2p1  #or e.HLT_IsoMu19_eta2p1_LooseIsoPFTau20_SingleL1
            self.muonCutPt = lambda e: 23
        elif year == 2017:
            self.trigger = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27  #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
            self.muonCutPt = lambda e: 25 if e.HLT_IsoMu24 else 28
        else:
            self.trigger = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27  #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
            self.muonCutPt = lambda e: 25
        self.eleCutPt = 15

        if not self.isData:
            self.eleSFs = ElectronSFs(year=year)
            self.muonSFs = MuonSFs(year=year)
            self.puTool = PileupWeightTool(year=year)
            self.btagTool = BTagWeightTool('DeepCSV',
                                           'medium',
                                           channel='mutau',
                                           year=year)
            if self.doZpt:
                self.zptTool = ZptCorrectionTool(year=year)
            if self.doRecoil:
                self.recoilTool = RecoilCorrectionTool(year=year)
        self.deepcsv_wp = BTagWPs('DeepCSV', year=year)

        self.Nocut = 0
        self.Trigger = 1
        self.GoodMuons = 2
        self.GoodElectrons = 3
        self.GoodDiLepton = 4
        self.TotalWeighted = 15
        self.TotalWeighted_no0PU = 16

        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.Nocut, "no cut")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.Trigger, "trigger")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodMuons,
                                                "muon object")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodElectrons,
                                                "electron object")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.GoodDiLepton,
                                                "mumu pair")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.TotalWeighted,
                                                "no cut, weighted")
        self.out.cutflow.GetXaxis().SetBinLabel(1 + self.TotalWeighted_no0PU,
                                                "no cut, weighted, PU>0")
        self.out.cutflow.GetXaxis().SetLabelSize(0.041)

    def beginJob(self):
        pass

    def endJob(self):
        if not self.isData:
            self.btagTool.setDirectory(self.out.outputfile, 'btag')
        self.out.endJob()

    def beginFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        sys.stdout.flush()
        checkBranches(inputTree)

    def endFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        pass

    def analyze(self, event):
        """process event, return True (go to next module) or False (fail, go to next event)"""
        sys.stdout.flush()

        #####################################
        self.out.cutflow.Fill(self.Nocut)
        if self.isData:
            self.out.cutflow.Fill(self.TotalWeighted, 1.)
            if event.PV_npvs > 0:
                self.out.cutflow.Fill(self.TotalWeighted_no0PU, 1.)
            else:
                return False
        else:
            self.out.cutflow.Fill(self.TotalWeighted, event.genWeight)
            self.out.pileup.Fill(event.Pileup_nTrueInt)
            if event.Pileup_nTrueInt > 0:
                self.out.cutflow.Fill(self.TotalWeighted_no0PU,
                                      event.genWeight)
            else:
                return False
        #####################################

        if not self.trigger(event):
            return False

        #####################################
        self.out.cutflow.Fill(self.Trigger)
        #####################################

        idx_goodmuons = []
        for imuon in range(event.nMuon):
            if event.Muon_pt[imuon] < self.muonCutPt(event): continue
            if abs(event.Muon_eta[imuon]) > 2.4: continue
            if abs(event.Muon_dz[imuon]) > 0.2: continue
            if abs(event.Muon_dxy[imuon]) > 0.045: continue
            if not event.Muon_mediumId[imuon]: continue
            idx_goodmuons.append(imuon)

        if len(idx_goodmuons) == 0:
            return False

        #####################################
        self.out.cutflow.Fill(self.GoodMuons)
        #####################################

        idx_goodelectrons = []
        for ielectron in range(event.nElectron):
            if event.Electron_pt[ielectron] < self.eleCutPt: continue
            if abs(event.Electron_eta[ielectron]) > 2.1: continue
            if abs(event.Electron_dz[ielectron]) > 0.2: continue
            if abs(event.Electron_dxy[ielectron]) > 0.045: continue
            if event.Electron_convVeto[ielectron] != 1: continue
            if ord(event.Electron_lostHits[ielectron]) > 1: continue
            #if event.Electron_mvaFall17V2Iso_WP80[ielectron] < 0.5: continue
            idx_goodelectrons.append(ielectron)

        if len(idx_goodelectrons) == 0:
            return False

        #####################################
        self.out.cutflow.Fill(self.GoodElectrons)
        #####################################

        muons = Collection(event, 'Muon')
        electrons = Collection(event, 'Electron')
        dileptons = []
        for idx1 in idx_goodelectrons:
            for idx2 in idx_goodmuons:
                if electrons[idx1].p4().DeltaR(muons[idx2].p4()) < 0.5:
                    continue
                dilepton = DiLeptonBasicClass(
                    idx1, event.Electron_pt[idx1],
                    event.Electron_pfRelIso03_all[idx1], idx2,
                    event.Muon_pt[idx2], event.Muon_pfRelIso04_all[idx2])
                dileptons.append(dilepton)

        if len(dileptons) == 0:
            return False

        dilepton = bestDiLepton(dileptons)
        electron = electrons[dilepton.id1].p4()
        muon = muons[dilepton.id2].p4()

        #####################################
        self.out.cutflow.Fill(self.GoodDiLepton)
        #####################################

        # VETOS
        self.out.extramuon_veto[0], self.out.extraelec_veto[
            0], self.out.dilepton_veto[0] = extraLeptonVetos(
                event, [dilepton.id2], [dilepton.id1], self.channel)
        self.out.lepton_vetos[0] = self.out.extramuon_veto[
            0] or self.out.extraelec_veto[0] or self.out.dilepton_veto[0]
        ###if self.doTight and (self.out.lepton_vetos[0] or event.Electron_pfRelIso03_all[dilepton.id1]>0.10 or\
        ###                     ord(event.Tau_idAntiMu[dilepton.id2]<1 or ord(event.Tau_idAntiEle[dilepton.id2]<8):
        ###  return False

        # JETS
        jetIds = []
        bjetIds = []
        jets = Collection(event, 'Jet')
        nfjets = 0
        ncjets = 0
        nbtag = 0
        for ijet in range(event.nJet):
            if event.Jet_pt[ijet] < 20:
                continue  # 20 for tau -> j fake measurement
            if abs(event.Jet_eta[ijet]) > 4.7: continue
            if muon.DeltaR(jets[ijet].p4()) < 0.5: continue
            if electron.DeltaR(jets[ijet].p4()) < 0.5: continue
            jetIds.append(ijet)

            if abs(event.Jet_eta[ijet]) > 2.4:
                nfjets += 1
            else:
                ncjets += 1

            if event.Jet_btagDeepB[ijet] > self.deepcsv_wp.medium:
                nbtag += 1
                bjetIds.append(ijet)

        if not self.isData and event.Electron_pfRelIso03_all[
                dilepton.id1] < 0.50 and event.Muon_pfRelIso04_all[
                    dilepton.id2] < 0.50:
            self.btagTool.fillEfficiencies(event, jetIds)

        # EVENT
        self.out.isData[0] = self.isData
        self.out.run[0] = event.run
        self.out.lumi[0] = event.luminosityBlock
        self.out.event[0] = event.event & 0xffffffffffffffff
        ###self.out.puppimet[0]                  = event.PuppiMET_pt
        ###self.out.puppimetphi[0]               = event.PuppiMET_phi
        ###self.out.metsignificance[0]           = event.MET_significance
        ###self.out.metcovXX[0]                  = event.MET_covXX
        ###self.out.metcovXY[0]                  = event.MET_covXY
        ###self.out.metcovYY[0]                  = event.MET_covYY
        self.out.npvs[0] = event.PV_npvs
        self.out.npvsGood[0] = event.PV_npvsGood

        if not self.isData:
            self.out.genPartFlav_1[0] = ord(
                event.Electron_genPartFlav[dilepton.id1])
            self.out.genPartFlav_2[0] = ord(
                event.Muon_genPartFlav[dilepton.id2])
            self.out.genmet[0] = event.GenMET_pt
            self.out.genmetphi[0] = event.GenMET_phi
            self.out.nPU[0] = event.Pileup_nPU
            self.out.nTrueInt[0] = event.Pileup_nTrueInt
            try:
                self.out.LHE_Njets[0] = event.LHE_Njets
            except RuntimeError:
                self.out.LHE_Njets[0] = -1

        # ELECTRON
        self.out.pt_1[0] = event.Electron_pt[dilepton.id1]
        self.out.eta_1[0] = event.Electron_eta[dilepton.id1]
        self.out.phi_1[0] = event.Electron_phi[dilepton.id1]
        self.out.m_1[0] = event.Electron_mass[dilepton.id1]
        self.out.dxy_1[0] = event.Electron_dxy[dilepton.id1]
        self.out.dz_1[0] = event.Electron_dz[dilepton.id1]
        self.out.q_1[0] = event.Electron_charge[dilepton.id1]
        self.out.pfRelIso03_all_1[0] = event.Electron_pfRelIso03_all[
            dilepton.id1]
        self.out.cutBased_1[0] = event.Electron_cutBased[dilepton.id1]
        self.out.mvaFall17Iso_1[0] = event.Electron_mvaFall17V2Iso[
            dilepton.id1]
        self.out.mvaFall17Iso_WPL_1[0] = event.Electron_mvaFall17V2Iso_WPL[
            dilepton.id1]
        self.out.mvaFall17Iso_WP80_1[0] = event.Electron_mvaFall17V2Iso_WP80[
            dilepton.id1]
        self.out.mvaFall17Iso_WP90_1[0] = event.Electron_mvaFall17V2Iso_WP90[
            dilepton.id1]

        # MUON
        self.out.pt_2[0] = event.Muon_pt[dilepton.id2]
        self.out.eta_2[0] = event.Muon_eta[dilepton.id2]
        self.out.phi_2[0] = event.Muon_phi[dilepton.id2]
        self.out.m_2[0] = event.Muon_mass[dilepton.id2]
        self.out.dxy_2[0] = event.Muon_dxy[dilepton.id2]
        self.out.dz_2[0] = event.Muon_dz[dilepton.id2]
        self.out.q_2[0] = event.Muon_charge[dilepton.id2]
        self.out.pfRelIso04_all_2[0] = event.Muon_pfRelIso04_all[dilepton.id2]

        # TAU for jet -> tau fake control region
        maxId = -1
        maxPt = 20
        taus = Collection(event, 'Tau')
        for itau in range(event.nTau):
            if event.Tau_pt[itau] < maxPt: continue
            if electron.DeltaR(taus[itau].p4()) < 0.5: continue
            if muon.DeltaR(taus[itau].p4()) < 0.5: continue
            if abs(event.Tau_eta[itau]) > 2.3: continue
            if abs(event.Tau_dz[itau]) > 0.2: continue
            if event.Tau_decayMode[itau] not in [0, 1, 10, 11]: continue
            if abs(event.Tau_charge[itau]) != 1: continue
            if ord(event.Tau_idAntiEle[itau]) < 1: continue  # VLoose
            if ord(event.Tau_idAntiMu[itau]) < 1: continue  # Loose
            #if not self.vlooseIso(event,itau): continue
            maxId = itau
            maxPt = event.Tau_pt[itau]
        if maxId > -1:
            self.out.pt_3[0] = event.Tau_pt[maxId]
            self.out.eta_3[0] = event.Tau_eta[maxId]
            self.out.m_3[0] = event.Tau_mass[maxId]
            self.out.decayMode_3[0] = event.Tau_decayMode[maxId]
            self.out.idAntiEle_3[0] = ord(event.Tau_idAntiEle[maxId])
            self.out.idAntiMu_3[0] = ord(event.Tau_idAntiMu[maxId])
            self.out.idMVAoldDM_3[0] = ord(event.Tau_idMVAoldDM[maxId])
            self.out.idMVAoldDM2017v1_3[0] = ord(
                event.Tau_idMVAoldDM2017v1[maxId])
            self.out.idMVAoldDM2017v2_3[0] = ord(
                event.Tau_idMVAoldDM2017v2[maxId])
            self.out.idMVAnewDM2017v2_3[0] = ord(
                event.Tau_idMVAnewDM2017v2[maxId])
            self.out.idIso_3[0] = Tau_idIso(event, maxId)
            if not self.isData:
                self.out.genPartFlav_3[0] = ord(event.Tau_genPartFlav[maxId])
        else:
            self.out.pt_3[0] = -1
            self.out.eta_3[0] = -9
            self.out.m_3[0] = -1
            self.out.decayMode_3[0] = -1
            self.out.idAntiEle_3[0] = -1
            self.out.idAntiMu_3[0] = -1
            self.out.idMVAoldDM_3[0] = -1
            self.out.idMVAoldDM2017v1_3[0] = -1
            self.out.idMVAoldDM2017v2_3[0] = -1
            self.out.idMVAnewDM2017v2_3[0] = -1
            self.out.idIso_3[0] = -1
            self.out.genPartFlav_3[0] = -1

        # WEIGHTS
        met = TLorentzVector()
        met.SetPxPyPzE(event.MET_pt * cos(event.MET_phi),
                       event.MET_pt * sin(event.MET_phi), 0, event.MET_pt)
        if not self.isData:
            if self.doRecoil:
                boson, boson_vis = getBoson(event)
                self.recoilTool.CorrectPByMeanResolution(
                    met, boson, boson_vis, len(jetIds))
                event.MET_pt = met.Pt()
                event.MET_phi = met.Phi()
                self.out.m_genboson[0] = boson.M()
                self.out.pt_genboson[0] = boson.Pt()
                if self.doZpt:
                    self.out.zptweight[0] = self.zptTool.getZptWeight(
                        boson.Pt(), boson.M())
            elif self.doZpt:
                zboson = getZBoson(event)
                self.out.m_genboson[0] = zboson.M()
                self.out.pt_genboson[0] = zboson.Pt()
                self.out.zptweight[0] = self.zptTool.getZptWeight(
                    zboson.Pt(), zboson.M())
            elif self.doTTpt:
                toppt1, toppt2 = getTTPt(event)
                self.out.ttptweight[0] = getTTptWeight(toppt1, toppt2)
            self.out.genweight[0] = event.genWeight
            self.out.puweight[0] = self.puTool.getWeight(event.Pileup_nTrueInt)
            self.out.trigweight[0] = 1.
            self.out.idisoweight_1[0] = self.eleSFs.getIdIsoSF(
                self.out.pt_1[0], self.out.eta_1[0])
            self.out.idisoweight_2[0] = self.muonSFs.getIdIsoSF(
                self.out.pt_2[0], self.out.eta_2[0])
            self.out.btagweight[0] = self.btagTool.getWeight(event, jetIds)
            self.out.weight[0] = self.out.genweight[0] * self.out.puweight[
                0] * self.out.trigweight[0] * self.out.idisoweight_1[
                    0] * self.out.idisoweight_2[0]

        # JETS
        self.out.njets[0] = len(jetIds)
        self.out.njets50[0] = len([j for j in jetIds if event.Jet_pt[j] > 50])
        self.out.nfjets[0] = nfjets
        self.out.ncjets[0] = ncjets
        self.out.nbtag[0] = nbtag

        if len(jetIds) > 0:
            self.out.jpt_1[0] = event.Jet_pt[jetIds[0]]
            self.out.jeta_1[0] = event.Jet_eta[jetIds[0]]
            self.out.jphi_1[0] = event.Jet_phi[jetIds[0]]
            self.out.jdeepb_1[0] = event.Jet_btagDeepB[jetIds[0]]
        else:
            self.out.jpt_1[0] = -9.
            self.out.jeta_1[0] = -9.
            self.out.jphi_1[0] = -9.
            self.out.jdeepb_1[0] = -9.

        if len(jetIds) > 1:
            self.out.jpt_2[0] = event.Jet_pt[jetIds[1]]
            self.out.jeta_2[0] = event.Jet_eta[jetIds[1]]
            self.out.jphi_2[0] = event.Jet_phi[jetIds[1]]
            self.out.jdeepb_2[0] = event.Jet_btagDeepB[jetIds[1]]
        else:
            self.out.jpt_2[0] = -9.
            self.out.jeta_2[0] = -9.
            self.out.jphi_2[0] = -9.
            self.out.jdeepb_2[0] = -9.

        if len(bjetIds) > 0:
            self.out.bpt_1[0] = event.Jet_pt[bjetIds[0]]
            self.out.beta_1[0] = event.Jet_eta[bjetIds[0]]
        else:
            self.out.bpt_1[0] = -9.
            self.out.beta_1[0] = -9.

        if len(bjetIds) > 1:
            self.out.bpt_2[0] = event.Jet_pt[bjetIds[1]]
            self.out.beta_2[0] = event.Jet_eta[bjetIds[1]]
        else:
            self.out.bpt_2[0] = -9.
            self.out.beta_2[0] = -9.

        self.out.njets[0] = len(jetIds)
        self.out.nfjets[0] = nfjets
        self.out.ncjets[0] = ncjets
        self.out.nbtag[0] = nbtag

        self.out.met[0] = event.MET_pt
        self.out.metphi[0] = event.MET_phi
        self.out.pfmt_1[0] = sqrt(
            2 * self.out.pt_1[0] * self.out.met[0] *
            (1 - cos(deltaPhi(self.out.phi_1[0], self.out.metphi[0]))))
        self.out.pfmt_2[0] = sqrt(
            2 * self.out.pt_2[0] * self.out.met[0] *
            (1 - cos(deltaPhi(self.out.phi_2[0], self.out.metphi[0]))))

        self.out.m_vis[0] = (electron + muon).M()
        self.out.pt_ll[0] = (electron + muon).Pt()
        self.out.dR_ll[0] = electron.DeltaR(muon)
        self.out.dphi_ll[0] = deltaPhi(self.out.phi_1[0], self.out.phi_2[0])
        self.out.deta_ll[0] = abs(self.out.eta_1[0] - self.out.eta_2[0])

        # PZETA
        leg1 = TVector3(electron.Px(), electron.Py(), 0.)
        leg2 = TVector3(muon.Px(), muon.Py(), 0.)
        zetaAxis = TVector3(leg1.Unit() + leg2.Unit()).Unit()
        pzeta_vis = leg1 * zetaAxis + leg2 * zetaAxis
        pzeta_miss = met.Vect() * zetaAxis
        self.out.pzetamiss[0] = pzeta_miss
        self.out.pzetavis[0] = pzeta_vis
        self.out.dzeta[0] = pzeta_miss - 0.85 * pzeta_vis

        self.out.tree.Fill()
        return True