class ttHLepStudyTreeProducer( ttHLepTreeProducerNew ):
    def __init__(self, cfg_ana, cfg_comp, looperName ):
        super(ttHLepStudyTreeProducer,self).__init__(cfg_ana,cfg_comp,looperName) 

        self.leptonMVA = LeptonMVA("%s/src/CMGTools/TTHAnalysis/data/leptonMVA/%%s_BDTG.weights.xml" % os.environ['CMSSW_BASE'], self.cfg_comp.isMC)

        self.globalVariables = [ 
            NTupleVariable("nVert",  lambda ev: len(ev.goodVertices), int, help="Number of good vertices"),
        ]
        self.globalObjects = {
            "lep"  : NTupleObject("Lep",   leptonTypeFull, help="Probe lepton"),
        }
        self.collections = {}

        ## Now book the variables
        self.initDone = True
        self.declareVariables()

    def declareHandles(self):
        super(ttHLepStudyTreeProducer, self).declareHandles()

    def beginLoop(self):
        super(ttHLepStudyTreeProducer,self).beginLoop()
        self.counters.addCounter('leptons')
        count = self.counters.counter('leptons')
        count.register('electron')
        count.register('prompt electron')
        count.register('non-prompt electron')
        count.register('unmatched electron')
        count.register('muon')
        count.register('prompt muon')
        count.register('non-prompt muon')
        count.register('unmatched muon')

    def process(self, iEvent, event):
        self.readCollections( iEvent )
        for lep in event.inclusiveLeptons:
            ## compute lepton MVA
            self.leptonMVA.addMVA(lep)
            ## increment counters
            name = "muon" if abs(lep.pdgId()) == 13 else "electron"
            self.counters.counter('leptons').inc(name)
            if lep.mcMatchId > 0:     self.counters.counter('leptons').inc('prompt '+name)
            elif lep.mcMatchAny != 0: self.counters.counter('leptons').inc('non-prompt '+name)
            else:                     self.counters.counter('leptons').inc('unmatched '+name)
            event.lep = lep
            self.fillTree(iEvent, event)
         
        return True
Exemple #2
0
class ttHLepEventAnalyzer(Analyzer):
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(ttHLepEventAnalyzer, self).__init__(cfg_ana, cfg_comp,
                                                  looperName)
        self.maxLeps = cfg_ana.maxLeps

        self.leptonMVA = LeptonMVA(
            "%s/src/CMGTools/TTHAnalysis/data/leptonMVA/%%s_BDTG.weights.xml" %
            os.environ['CMSSW_BASE'], self.cfg_comp.isMC)

    def declareHandles(self):
        super(ttHLepEventAnalyzer, self).declareHandles()
        self.handles['met'] = AutoHandle('cmgPFMET',
                                         'std::vector<cmg::BaseMET>')
        self.handles['nopumet'] = AutoHandle('nopuMet',
                                             'std::vector<reco::PFMET>')
        self.handles['metSignificance'] = AutoHandle('pfMetSignificance',
                                                     'cmg::METSignificance')

    def beginLoop(self):
        super(ttHLepEventAnalyzer, self).beginLoop()

    def makeZs(self, event, maxLeps):
        event.bestZ1 = [0., -1, -1]
        event.bestZ1sfss = [0., -1, -1]
        event.bestZ2 = [0., -1, -1, 0.]
        nlep = len(event.selectedLeptons)
        for i, l1 in enumerate(event.selectedLeptons):
            for j in range(i + 1, nlep):
                if j >= maxLeps: break
                l2 = event.selectedLeptons[j]
                if l1.pdgId() == -l2.pdgId():
                    zmass = (l1.p4() + l2.p4()).M()
                    if event.bestZ1[0] == 0 or abs(zmass - 91.188) < abs(
                            event.bestZ1[0] - 91.188):
                        event.bestZ1 = [zmass, i, j]
                if l1.pdgId() == l2.pdgId():
                    zmass = (l1.p4() + l2.p4()).M()
                    if event.bestZ1sfss[0] == 0 or abs(zmass - 91.188) < abs(
                            event.bestZ1sfss[0] - 91.188):
                        event.bestZ1sfss = [zmass, i, j]
        if event.bestZ1[0] != 0 and nlep > 3:
            for i, l1 in enumerate(event.selectedLeptons):
                if i == event.bestZ1[1]: continue
                for j in range(i + 1, nlep):
                    if j >= maxLeps: break
                    if j == event.bestZ1[2]: continue
                    l2 = event.selectedLeptons[j]
                    if l1.pdgId() == -l2.pdgId():
                        if l1.pt() + l2.pt() > event.bestZ2[0]:
                            event.bestZ2 = [
                                l1.pt() + l2.pt(), i, j,
                                (l1.p4() + l2.p4()).M()
                            ]

    def makeMlls(self, event, maxLeps):
        mllsfos = self.mllValues(event,
                                 lambda l1, l2: l1.pdgId() == -l2.pdgId(),
                                 maxLeps)
        mllafos = self.mllValues(event,
                                 lambda l1, l2: l1.charge() == -l2.charge(),
                                 maxLeps)
        mllafss = self.mllValues(event,
                                 lambda l1, l2: l1.charge() == l2.charge(),
                                 maxLeps)
        mllafas = self.mllValues(event, lambda l1, l2: True, maxLeps)
        event.minMllSFOS = min(mllsfos)
        event.minMllAFOS = min(mllafos)
        event.minMllAFSS = min(mllafss)
        event.minMllAFAS = min(mllafas)
        event.maxMllAFOS = max(mllafos)
        event.maxMllAFSS = max(mllafss)
        drllafos = self.drllValues(event,
                                   lambda l1, l2: l1.charge() == -l2.charge(),
                                   maxLeps)
        drllafss = self.drllValues(event,
                                   lambda l1, l2: l1.charge() == l2.charge(),
                                   maxLeps)
        event.minDrllAFSS = min(drllafss)
        event.minDrllAFOS = min(drllafos)
        event.maxDrllAFOS = max(drllafos)
        event.maxDrllAFSS = max(drllafss)
        ptllafos = self.ptllValues(event,
                                   lambda l1, l2: l1.charge() == -l2.charge(),
                                   maxLeps)
        ptllafss = self.ptllValues(event,
                                   lambda l1, l2: l1.charge() == l2.charge(),
                                   maxLeps)
        event.minPtllAFSS = min(ptllafss)
        event.minPtllAFOS = min(ptllafos)
        event.maxPtllAFOS = max(ptllafos)
        event.maxPtllAFSS = max(ptllafss)
        leps = event.selectedLeptons
        nlep = len(leps)
        event.m2l = (leps[0].p4() + leps[1].p4()).M() if nlep >= 2 else 0
        event.pt2l = (leps[0].p4() + leps[1].p4()).Pt() if nlep >= 2 else 0
        event.q3l = sum([l.charge() for l in leps[:2]]) if nlep >= 3 else 0
        event.ht3l = sum([l.pt() for l in leps[:2]]) if nlep >= 3 else 0
        event.pt3l = (leps[0].p4() + leps[1].p4() +
                      leps[2].p4()).Pt() if nlep >= 3 else 0
        event.m3l = (leps[0].p4() + leps[1].p4() +
                     leps[2].p4()).M() if nlep >= 3 else 0
        event.q4l = sum([l.charge() for l in leps[:3]]) if nlep >= 4 else 0
        event.ht4l = sum([l.pt() for l in leps[:3]]) if nlep >= 4 else 0
        event.pt4l = (leps[0].p4() + leps[1].p4() + leps[2].p4() +
                      leps[3].p4()).Pt() if nlep >= 4 else 0
        event.m4l = (leps[0].p4() + leps[1].p4() + leps[2].p4() +
                     leps[3].p4()).M() if nlep >= 4 else 0

    def mllValues(self, event, pairSelection, maxLeps):
        return self.llValues(event, lambda l1, l2: (l1.p4() + l2.p4()).M(),
                             pairSelection, maxLeps)

    def drllValues(self, event, pairSelection, maxLeps):
        return self.llValues(
            event,
            lambda l1, l2: deltaR(l1.eta(), l1.phi(), l2.eta(), l2.phi()),
            pairSelection, maxLeps)

    def ptllValues(self, event, pairSelection, maxLeps):
        return self.llValues(event, lambda l1, l2: (l1.p4() + l2.p4()).Pt(),
                             pairSelection, maxLeps)

    def llValues(self, event, function, pairSelection, maxLeps):
        pairs = []
        nlep = len(event.selectedLeptons)
        for i, l1 in enumerate(event.selectedLeptons):
            for j in range(i + 1, nlep):
                if j >= maxLeps: break
                l2 = event.selectedLeptons[j]
                if pairSelection(l1, l2):
                    pairs.append(function(l1, l2))
        if pairs == []: pairs.append(-1)
        return pairs

    def makeLepBJetDeltaR(self, event):
        for l in event.selectedLeptons + event.looseLeptons:
            match, dr = bestMatch(l, event.bjetsLoose)
            l.drBJet = dr

        for l in event.selectedLeptons:
            (px, py, pz) = (l.px(), l.py(), l.pz())
            (jx, jy, jz) = (l.jet.px(), l.jet.py(), l.jet.pz())
            cross = (px * jy - py * jx, py * jz - pz * jy, pz * jx - px * jz)
            l.ptRelJet = sqrt(sum([v * v for v in cross])) / l.jet.p()

    def jetProjectedMET(self, met, jets, oneSided=True):
        import math
        projfactor = 1.0
        for j in jets:
            dphi = abs(deltaPhi(j.phi(), met.phi()))
            proj = sin(dphi)
            if oneSided and dphi > 0.5 * math.pi:
                continue
            if projfactor > proj: projfactor = proj
        return met.pt() * projfactor

    def makeMETs(self, event):
        event.met = self.handles['met'].product()[0]
        event.metNoPU = self.handles['nopumet'].product()[0]
        if hasattr(event, 'deltaMetFromJetSmearing'):
            import ROOT
            px, py = event.met.px() + event.deltaMetFromJetSmearing[
                0], event.met.py() + event.deltaMetFromJetSmearing[1]
            event.met.setP4(
                ROOT.reco.Particle.LorentzVector(px, py, 0, hypot(px, py)))
            px, py = event.metNoPU.px() + event.deltaMetFromJetSmearing[
                0], event.metNoPU.py() + event.deltaMetFromJetSmearing[1]
            event.metNoPU.setP4(
                ROOT.reco.Particle.LorentzVector(px, py, 0, hypot(px, py)))
        metMatrix = self.handles['metSignificance'].product().significance()
        metMatrix.Invert()
        import array
        metVector = TVectorD(
            2, array.array('d',
                           [event.met.px(), event.met.py()]))
        event.metSignificance = metMatrix.Similarity(metVector)
        event.projMetAll1S = self.jetProjectedMET(event.met, event.jets, True)
        event.projMetAll2S = self.jetProjectedMET(event.met, event.jets, False)
        event.projMetJets1S = self.jetProjectedMET(event.met, event.cleanJets,
                                                   True)
        event.projMetJets2S = self.jetProjectedMET(event.met, event.cleanJets,
                                                   False)
        #print "MET value:  ", event.met.pt()
        #print "MET sumET:  ", event.met.sumEt()
        #print "MET signif: ", event.metSignificance
        #print "PrMETAll 1S:", event.projMetAll1S
        #print "PrMETAll 2S:", event.projMetAll2S
        #print "PrMETJet 1S:", event.projMetJets1S
        #print "PrMETJet 2S:", event.projMetJets2S

    def makeHadTopDecays(self, event):
        event.lightJets = [
            j for j in event.cleanJets if not j.getSelection("cuts_csv_medium")
        ]
        event.minMWjj = 999
        event.minMWjjPt = 0
        event.bestMWjj = 0
        event.bestMWjjPt = 0
        event.bestMTopHad = 0
        event.bestMTopHadPt = 0
        for i1, j1 in enumerate(event.lightJets):
            for i2 in xrange(i1 + 1, len(event.lightJets)):
                j2 = event.lightJets[i2]
                jjp4 = j1.p4() + j2.p4()
                mjj = jjp4.M()
                if mjj > 30 and mjj < event.minMWjj:
                    event.minMWjj = mjj
                    event.minMWjjPt = jjp4.Pt()
                if abs(mjj - 80.4) < abs(event.bestMWjj - 80.4):
                    event.bestMWjj = mjj
                    event.bestMWjjPt = jjp4.Pt()
                    for bj in event.bjetsLoose:
                        if deltaR(bj.eta(), bj.phi(), j1.eta(),
                                  j1.phi()) < 0.1 or deltaR(
                                      bj.eta(), bj.phi(), j2.eta(),
                                      j2.phi()) < 0.1:
                            continue
                        tp4 = jjp4 + bj.p4()
                        mtop = tp4.M()
                        if abs(mtop - 172) < abs(event.bestMTopHad - 172):
                            event.bestMTopHad = mtop
                            event.bestMTopHadPt = tp4.Pt()

    def process(self, iEvent, event):
        self.readCollections(iEvent)

        if hasattr(self.cfg_ana, 'minJets25'):
            n25 = len([j for j in event.cleanJets if j.pt() > 25])
            if n25 < self.cfg_ana.minJets25:
                return False

        eventNumber = iEvent.eventAuxiliary().id().event()

        event.bjetsLoose = [
            j for j in event.cleanJets if j.getSelection("cuts_csv_loose")
        ]
        event.bjetsMedium = [
            j for j in event.cleanJets if j.getSelection("cuts_csv_medium")
        ]

        objects25 = [j for j in event.cleanJets if j.pt() > 25
                     ] + event.selectedLeptons
        objects30 = [j for j in event.cleanJets if j.pt() > 30
                     ] + event.selectedLeptons
        event.htJet25 = sum([x.pt() for x in objects25])
        event.mhtJet25 = hypot(sum([x.px() for x in objects25]),
                               sum([x.py() for x in objects25]))
        event.htJet30 = sum([x.pt() for x in objects30])
        event.mhtJet30 = hypot(sum([x.px() for x in objects30]),
                               sum([x.py() for x in objects30]))
        ## same but with all eta range
        objects25a = [j for j in event.cleanJetsAll if j.pt() > 25
                      ] + event.selectedLeptons
        objects30a = [j for j in event.cleanJetsAll if j.pt() > 30
                      ] + event.selectedLeptons
        event.htJet25a = sum([x.pt() for x in objects25a])
        event.mhtJet25a = hypot(sum([x.px() for x in objects25a]),
                                sum([x.py() for x in objects25a]))
        event.htJet30a = sum([x.pt() for x in objects30a])
        event.mhtJet30a = hypot(sum([x.px() for x in objects30a]),
                                sum([x.py() for x in objects30a]))

        self.makeMETs(event)
        self.makeZs(event, self.maxLeps)
        self.makeMlls(event, self.maxLeps)

        self.makeHadTopDecays(event)
        for lep in event.selectedLeptons:
            self.leptonMVA.addMVA(lep)

        if self.cfg_ana.verbose:
            print 'Event ', eventNumber
            print 'Selected leptons: ', len(event.selectedLeptons)
            print "\n".join(["\t%s" % p for p in event.selectedLeptons])
            print 'Selected clean jets   : ', len(event.cleanJets)
            print "\n".join(["\t%s" % p for p in event.cleanJets])
            print 'Selected loose  b-jets: ', len(event.bjetsLoose)
            print 'Selected medium b-jets: ', len(event.bjetsMedium)
            print 'Best Z1, if any: mass = %6.1f ' % event.bestZ1[0]
            print 'Best Z2, if any: mass = %6.1f ' % event.bestZ2[3]
            print 'Min m(ll) values: SF/OS = %5.1f, AF/OS = %5.1f, AF/AS = %5.1f' % (
                event.minMllSFOS, event.minMllAFOS, event.minMllAFAS)

        return True
Exemple #3
0
class ttHLepFRAnalyzer(TreeAnalyzerNumpy):
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(ttHLepFRAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        self.leptonMVA = LeptonMVA(
            "%s/src/CMGTools/TTHAnalysis/data/leptonMVA/%%s_BDTG.weights.xml" %
            os.environ['CMSSW_BASE'], self.cfg_comp.isMC)

    def declareHandles(self):
        super(ttHLepFRAnalyzer, self).declareHandles()
        self.handles['met'] = AutoHandle('cmgPFMET',
                                         'std::vector<cmg::BaseMET>')
        self.handles['nopumet'] = AutoHandle('nopuMet',
                                             'std::vector<reco::PFMET>')

    def declareVariables(self):
        tr = self.tree

        isMC = self.cfg_comp.isMC

        tr = self.tree
        var(tr, 'run', int)
        var(tr, 'lumi', int)
        var(tr, 'evt', int)
        var(tr, 'nVert', int)

        bookLepton(tr, "Probe", isMC)

        var(tr, 'tagType', int)

        bookLepton(tr, "TagLepton", isMC)
        bookJet(tr, "TagJet", isMC)
        #bookParticle(tr,"TagPhoton", isMC)

        for I in (5, 8, 12, 17, 24, 40):
            var(tr, "Trig_Probe_Mu%d" % I, int)
            var(tr, "Trig_Tag_Mu%d" % I, int)
        var(tr, "Trig_Probe_RelIso1p0Mu5", int)
        var(tr, "Trig_Tag_RelIso1p0Mu5", int)
        var(tr, "Trig_Probe_1ElT", int)
        var(tr, "Trig_Probe_1ElL", int)
        var(tr, "Trig_Pair_2Mu", int)
        var(tr, "Trig_Pair_MuEG", int)

        var(tr, 'dphi_tp')
        var(tr, 'dr_tp')
        var(tr, 'mll')
        var(tr, 'mtw_probe')
        var(tr, 'mtw_tag')
        var(tr, 'mtwNoPU_probe')
        var(tr, 'mtwNoPU_tag')
        var(tr, 'met')
        var(tr, 'metPhi')
        var(tr, 'metNoPU')
        var(tr, 'metPhiNoPU')

    def beginLoop(self):
        super(ttHLepFRAnalyzer, self).beginLoop()
        self.counters.addCounter('pairs')
        count = self.counters.counter('pairs')
        count.register('all events')
        count.register('one lepton')
        count.register('loose jet')
        count.register('high pt jet')
        count.register('bjet tag')
        count.register('mu tag')

    def process(self, iEvent, event):
        self.readCollections(iEvent)
        event.met = self.handles['met'].product()[0]
        event.metNoPU = self.handles['nopumet'].product()[0]

        tr = self.tree
        fill(tr, 'run', event.run)
        fill(tr, 'lumi', event.lumi)
        fill(tr, 'evt', event.eventId)
        fill(tr, 'nVert', len(event.goodVertices))

        fill(tr, 'met', event.met.pt())
        fill(tr, 'metPhi', event.met.phi())
        fill(tr, 'metNoPU', event.metNoPU.pt())
        fill(tr, 'metPhiNoPU', event.metNoPU.phi())

        self.counters.counter('pairs').inc('all events')

        # di-lepton veto: simple, for now
        if len(event.selectedLeptons) > 1:
            return False
        self.counters.counter('pairs').inc('one lepton')

        def mtw(x1, x2):
            return sqrt(2 * x1.pt() * x2.pt() * (1 - cos(x1.phi() - x2.phi())))

        def passTrigg(lep, triggers):
            for t in triggers:
                if lep.sourcePtr().triggerObjectMatchesByPath(
                        'HLT_%s_v*' % t, 1, 0).size() > 0:
                    return True
            return False

        def passFilter(lep, filters):
            for t in filters:
                if lep.sourcePtr().triggerObjectMatchesByFilter(t).size() > 0:
                    return True
            return False

        def passSingleMu(lep):
            return passTrigg(
                lep,
                "Mu12 Mu24_eta2p1 Mu30_eta2p1 Mu40 Mu40_eta2p1 Mu17 Mu8".split(
                ))

        def passSingleIsoMu(lep):
            return passTrigg(lep, "IsoMu24 IsoMu24_eta2p1".split())

        def passSingleElL(lep):
            return passTrigg(
                lep, "Ele17_CaloIdL_CaloIsoVL Ele8_CaloIdL_CaloIsoVL".split())

        def passSingleElT(lep):
            return passTrigg(
                lep,
                "Ele17_CaloIdT_CaloIsoVL_TrkIdVL_TrkIsoVL Ele8_CaloIdT_CaloIsoVL_TrkIdVL_TrkIsoVL"
                .split())

        def passDoubleMu(lep1, lep2):
            mu17_1 = passFilter(
                lep1,
                'hltL3fL1DoubleMu10MuOpenL1f0L2f10L3Filtered17 hltL3fL1DoubleMu10MuOpenOR3p5L1f0L2f10L3Filtered17'
                .split())
            mu17_2 = passFilter(
                lep2,
                'hltL3fL1DoubleMu10MuOpenL1f0L2f10L3Filtered17 hltL3fL1DoubleMu10MuOpenOR3p5L1f0L2f10L3Filtered17'
                .split())
            mu8_1 = passFilter(
                lep1,
                'hltL3pfL1DoubleMu10MuOpenL1f0L2pf0L3PreFiltered8 hltL3pfL1DoubleMu10MuOpenOR3p5L1f0L2pf0L3PreFiltered8'
                .split())
            mu8_2 = passFilter(
                lep2,
                'hltL3pfL1DoubleMu10MuOpenL1f0L2pf0L3PreFiltered8 hltL3pfL1DoubleMu10MuOpenOR3p5L1f0L2pf0L3PreFiltered8'
                .split())
            mu8tk_1 = passFilter(lep1, ['hltDiMuonGlbFiltered17TrkFiltered8'])
            mu8tk_2 = passFilter(lep2, ['hltDiMuonGlbFiltered17TrkFiltered8'])
            if lep1.sourcePtr().triggerObjectMatchesByPath(
                    'HLT_Mu17_Mu8_v*', 1, 0).size() and (
                        mu17_1 + mu17_2 >= 1) and (mu8_1 + mu8_2 >= 2):
                return True
            if lep2.sourcePtr().triggerObjectMatchesByPath(
                    'HLT_Mu17_Mu8_v*', 1, 0).size() and (
                        mu17_1 + mu17_2 >= 1) and (mu8_1 + mu8_2 >= 2):
                return True
            if lep1.sourcePtr().triggerObjectMatchesByPath(
                    'HLT_Mu17_TkMu8_v*', 1, 0).size() and (
                        (mu17_1 and mu8tk_2) or (mu17_2 and mu8tk_1)):
                return True
            if lep2.sourcePtr().triggerObjectMatchesByPath(
                    'HLT_Mu17_TkMu8_v*', 1, 0).size() and (
                        (mu17_1 and mu8tk_2) or (mu17_2 and mu8tk_1)):
                return True
            return False

        def passMuEG(mu, el):
            if (mu.sourcePtr().triggerObjectMatchesByFilter(
                    "hltL1Mu12EG7L3MuFiltered17"
            ).size() > 0 and el.sourcePtr().triggerObjectMatchesByFilter(
                    "hltMu17Ele8CaloIdTCaloIsoVLTrkIdVLTrkIsoVLTrackIsoFilter"
            ).size()):
                return True
            if (mu.sourcePtr().triggerObjectMatchesByFilter(
                    "hltL1sL1Mu3p5EG12ORL1MuOpenEG12L3Filtered8"
            ).size() > 0 and el.sourcePtr().triggerObjectMatchesByFilter(
                    "hltMu8Ele17CaloIdTCaloIsoVLTrkIdVLTrkIsoVLTrackIsoFilter"
            ).size()):
                return True
            return False

        for lep in event.selectedLeptons:
            self.leptonMVA.addMVA(lep)

        # now fill probes
        for lep in event.selectedLeptons:
            fillLepton(tr, "Probe", lep)
            fill(tr, 'mtw_probe', mtw(lep, event.met))
            fill(tr, 'mtwNoPU_probe', mtw(lep, event.metNoPU))
            fill(tr, 'Trig_Probe_Mu5', passTrigg(lep, ['Mu5']))
            fill(tr, 'Trig_Probe_Mu8', passTrigg(lep, ['Mu8']))
            fill(tr, 'Trig_Probe_Mu12', passTrigg(lep, ['Mu12']))
            fill(tr, 'Trig_Probe_Mu17', passTrigg(lep, ['Mu17']))
            fill(tr, 'Trig_Probe_Mu24', passTrigg(lep, ['Mu24_eta2p1']))
            fill(tr, 'Trig_Probe_Mu40', passTrigg(lep, ['Mu40_eta2p1']))
            fill(tr, 'Trig_Probe_RelIso1p0Mu5',
                 passTrigg(lep, ['RelIso1p0Mu5']))
            fill(tr, 'Trig_Probe_1ElL', passSingleElL(lep))
            fill(tr, 'Trig_Probe_1ElT', passSingleElT(lep))
            # first search for a jet tag
            fill(tr, 'tagType', 1)  # jet
            for jet in event.cleanJets:
                dr = deltaR(jet.eta(), jet.phi(), lep.eta(), lep.phi())
                dphi = deltaPhi(jet.phi(), lep.phi())
                if (dr < 0.8): continue
                self.counters.counter('pairs').inc('loose jet')
                if jet.pt() < self.cfg_ana.tagJetSel['minPt']: continue
                self.counters.counter('pairs').inc('high pt jet')
                if jet.btag('combinedSecondaryVertexBJetTags'
                            ) < self.cfg_ana.tagJetSel['minBTag']:
                    continue
                self.counters.counter('pairs').inc('bjet tag')
                fillJet(tr, "TagJet", jet)
                fill(tr, 'dr_tp', dr)
                fill(tr, 'dphi_tp', dphi)
                tr.tree.Fill()
                break
            # then search for a lepton tag
            fill(tr, 'tagType', 13)  # muon
            for tag in event.looseLeptons:
                if abs(tag.pdgId()) != 13: continue
                if tag.pt() < 10: continue
                if tag.sourcePtr().userFloat("isPFMuon") < 0.5: continue
                if tag.sip3D() < self.cfg_ana.tagLeptonSel['minSip3D']:
                    continue
                if tag.relIso() < self.cfg_ana.tagLeptonSel['minRelIso']:
                    continue
                dr = deltaR(tag.eta(), tag.phi(), lep.eta(), lep.phi())
                dphi = deltaPhi(tag.phi(), lep.phi())
                if (dr < 0.8): continue
                fillLepton(tr, "TagLepton", tag)
                fill(tr, 'mtw_tag', mtw(tag, event.met))
                fill(tr, 'mtwNoPU_tag', mtw(tag, event.metNoPU))
                fill(tr, 'dr_tp', dr)
                fill(tr, 'dphi_tp', dphi)
                fill(tr, 'mll', (tag.p4() + lep.p4()).M())
                fill(tr, 'Trig_Tag_RelIso1p0Mu5',
                     passTrigg(tag, ['RelIso1p0Mu5']))
                fill(tr, 'Trig_Tag_Mu5', passTrigg(tag, ['Mu5']))
                fill(tr, 'Trig_Tag_Mu8', passTrigg(tag, ['Mu8']))
                fill(tr, 'Trig_Tag_Mu12', passTrigg(tag, ['Mu12']))
                fill(tr, 'Trig_Tag_Mu17', passTrigg(tag, ['Mu17']))
                fill(tr, 'Trig_Tag_Mu24', passTrigg(tag, ['Mu24_eta2p1']))
                fill(tr, 'Trig_Tag_Mu40', passTrigg(tag, ['Mu40_eta2p1']))
                fill(tr, 'Trig_Pair_2Mu',
                     abs(lep.pdgId()) == 13 and passDoubleMu(tag, lep))
                fill(tr, 'Trig_Pair_MuEG',
                     abs(lep.pdgId()) == 11 and passMuEG(tag, lep))
                self.counters.counter('pairs').inc('mu tag')
                tr.tree.Fill()
                break

        return True
Exemple #4
0
class ttHLepEventAnalyzer( Analyzer ):
    def __init__(self, cfg_ana, cfg_comp, looperName ):
        super(ttHLepEventAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName)
        self.maxLeps = cfg_ana.maxLeps

        self.leptonMVA = LeptonMVA("%s/src/CMGTools/TTHAnalysis/data/leptonMVA/%%s_BDTG.weights.xml" % os.environ['CMSSW_BASE'], self.cfg_comp.isMC)
    def declareHandles(self):
        super(ttHLepEventAnalyzer, self).declareHandles()
        self.handles['met'] = AutoHandle( 'cmgPFMET', 'std::vector<cmg::BaseMET>' )
        self.handles['nopumet'] = AutoHandle( 'nopuMet', 'std::vector<reco::PFMET>' )
        self.handles['metSignificance'] = AutoHandle( 'pfMetSignificance', 'cmg::METSignificance' )

    def beginLoop(self):
        super(ttHLepEventAnalyzer,self).beginLoop()
        self.counters.addCounter('events')
        count = self.counters.counter('events')
        count.register('all events')
        count.register('accepted events')

    def makeZs(self, event, maxLeps):
        event.bestZ1 = [ 0., -1,-1 ]
        event.bestZ1sfss = [ 0., -1,-1 ]
        event.bestZ2 = [ 0., -1,-1, 0. ]
        nlep = len(event.selectedLeptons)
        for i,l1 in enumerate(event.selectedLeptons):
            for j in range(i+1,nlep):
                if j >= maxLeps: break
                l2 = event.selectedLeptons[j]    
                if l1.pdgId() == -l2.pdgId():
                    zmass = (l1.p4() + l2.p4()).M()
                    if event.bestZ1[0] == 0 or abs(zmass - 91.188) < abs(event.bestZ1[0] - 91.188):
                        event.bestZ1 = [ zmass, i, j ]
                if l1.pdgId() == l2.pdgId():
                    zmass = (l1.p4() + l2.p4()).M()
                    if event.bestZ1sfss[0] == 0 or abs(zmass - 91.188) < abs(event.bestZ1sfss[0] - 91.188):
                        event.bestZ1sfss = [ zmass, i, j ]
        if event.bestZ1[0] != 0 and nlep > 3:
            for i,l1 in enumerate(event.selectedLeptons):
                if i == event.bestZ1[1]: continue
                for j in range(i+1,nlep):
                    if j >= maxLeps: break
                    if j == event.bestZ1[2]: continue
                    l2 = event.selectedLeptons[j]    
                    if l1.pdgId() == -l2.pdgId():
                        if l1.pt() + l2.pt() > event.bestZ2[0]:
                            event.bestZ2 = [ l1.pt() + l2.pt(), i, j, (l1.p4() + l2.p4()).M() ]

    def makeMlls(self, event, maxLeps):
        mllsfos = self.mllValues(event,  lambda l1,l2 : l1.pdgId()  == -l2.pdgId(),  maxLeps)
        mllafos = self.mllValues(event,  lambda l1,l2 : l1.charge() == -l2.charge(),  maxLeps)
        mllafss = self.mllValues(event,  lambda l1,l2 : l1.charge() ==  l2.charge(),  maxLeps)
        mllafas = self.mllValues(event,  lambda l1,l2 : True, maxLeps)
        event.minMllSFOS = min(mllsfos)
        event.minMllAFOS = min(mllafos)
        event.minMllAFSS = min(mllafss)
        event.minMllAFAS = min(mllafas)
        event.maxMllSFOS = max(mllsfos)
        event.maxMllAFAS = max(mllafas)
        event.maxMllAFOS = max(mllafos)
        event.maxMllAFSS = max(mllafss)
        drllafos = self.drllValues(event,  lambda l1,l2 : l1.charge() == -l2.charge(),  maxLeps)
        drllafss = self.drllValues(event,  lambda l1,l2 : l1.charge() ==  l2.charge(),  maxLeps)
        event.minDrllAFSS = min(drllafss)
        event.minDrllAFOS = min(drllafos)
        event.maxDrllAFOS = max(drllafos)
        event.maxDrllAFSS = max(drllafss)
        ptllafos = self.ptllValues(event,  lambda l1,l2 : l1.charge() == -l2.charge(),  maxLeps)
        ptllafss = self.ptllValues(event,  lambda l1,l2 : l1.charge() ==  l2.charge(),  maxLeps)
        event.minPtllAFSS = min(ptllafss)
        event.minPtllAFOS = min(ptllafos)
        event.maxPtllAFOS = max(ptllafos)
        event.maxPtllAFSS = max(ptllafss)
        leps = event.selectedLeptons; nlep = len(leps)
        event.m2l = (leps[0].p4() + leps[1].p4()).M() if nlep >= 2 else 0
        event.pt2l = (leps[0].p4() + leps[1].p4()).Pt() if nlep >= 2 else 0
        event.q3l = sum([l.charge() for l in leps[:2]]) if nlep >= 3 else 0
        event.ht3l = sum([l.pt() for l in leps[:2]]) if nlep >= 3 else 0
        event.pt3l = (leps[0].p4() + leps[1].p4() + leps[2].p4()).Pt() if nlep >= 3 else 0
        event.m3l = (leps[0].p4() + leps[1].p4() + leps[2].p4()).M() if nlep >= 3 else 0
        event.q4l = sum([l.charge() for l in leps[:3]])  if nlep >= 4 else 0
        event.ht4l = sum([l.pt() for l in leps[:3]]) if nlep >= 4 else 0
        event.pt4l = (leps[0].p4() + leps[1].p4() + leps[2].p4() + leps[3].p4()).Pt() if nlep >= 4 else 0
        event.m4l = (leps[0].p4() + leps[1].p4() + leps[2].p4() + leps[3].p4()).M() if nlep >= 4 else 0
        event.vtx2l = twoTrackChi2(leps[0],leps[1]) if nlep >= 2 else (-1,-1)

    def mllValues(self, event, pairSelection, maxLeps):
        return self.llValues(event, lambda l1,l2: (l1.p4() + l2.p4()).M(), pairSelection, maxLeps)

    def drllValues(self, event, pairSelection, maxLeps):
        return self.llValues(event, lambda l1,l2: deltaR(l1.eta(), l1.phi(), l2.eta(), l2.phi()), pairSelection, maxLeps)

    def ptllValues(self, event, pairSelection, maxLeps):
        return self.llValues(event, lambda l1,l2: (l1.p4() + l2.p4()).Pt(), pairSelection, maxLeps)

    def llValues(self, event, function, pairSelection, maxLeps):
        pairs = []
        nlep = len(event.selectedLeptons)
        for i,l1 in enumerate(event.selectedLeptons):
            for j in range(i+1,nlep):
                if j >= maxLeps: break
                l2 = event.selectedLeptons[j]    
                if pairSelection(l1,l2):
                    pairs.append( function(l1, l2) )
        if pairs == []: pairs.append(-1)
        return pairs
    
    def makeLepBJetDeltaR(self, event):
        for l in event.selectedLeptons + event.looseLeptons:
            match, dr = bestMatch(l, event.bjetsLoose)
            l.drBJet = dr

        for l in event.selectedLeptons:
            (px,py,pz) = (l.px(),l.py(),l.pz())
            (jx,jy,jz) = (l.jet.px(),l.jet.py(),l.jet.pz())
            cross = (px*jy-py*jx, py*jz-pz*jy, pz*jx-px*jz)
            l.ptRelJet = sqrt(sum([v*v for v in cross]))/l.jet.p()

    def jetProjectedMET(self, met, jets, oneSided=True):
        import math
        projfactor = 1.0
        for j in jets:
            dphi = abs(deltaPhi(j.phi(), met.phi()))
            proj = sin(dphi)
            if oneSided and dphi > 0.5*math.pi:
                continue
            if projfactor > proj: projfactor = proj
        return met.pt()*projfactor

    def makeMETs(self, event):
        event.met = self.handles['met'].product()[0]
        event.metNoPU = self.handles['nopumet'].product()[0]
        if hasattr(event, 'deltaMetFromJetSmearing'):
            import ROOT
            px,py = event.met.px()+event.deltaMetFromJetSmearing[0], event.met.py()+event.deltaMetFromJetSmearing[1]
            event.met.setP4(ROOT.reco.Particle.LorentzVector(px,py, 0, hypot(px,py)))
            px,py = event.metNoPU.px()+event.deltaMetFromJetSmearing[0], event.metNoPU.py()+event.deltaMetFromJetSmearing[1]
            event.metNoPU.setP4(ROOT.reco.Particle.LorentzVector(px,py, 0, hypot(px,py)))
        if hasattr(event, 'deltaMetFromJEC') and event.deltaMetFromJEC[0] != 0 and event.deltaMetFromJEC[1] != 0:
            import ROOT
            px,py = event.met.px()+event.deltaMetFromJEC[0], event.met.py()+event.deltaMetFromJEC[1]
            event.met.setP4(ROOT.reco.Particle.LorentzVector(px,py, 0, hypot(px,py)))
            px,py = event.metNoPU.px()+event.deltaMetFromJEC[0], event.metNoPU.py()+event.deltaMetFromJEC[1]
            event.metNoPU.setP4(ROOT.reco.Particle.LorentzVector(px,py, 0, hypot(px,py)))

        metMatrix = self.handles['metSignificance'].product().significance()
        metMatrix.Invert();
        import array
        metVector = TVectorD(2,array.array('d',[event.met.px(), event.met.py()]))
        event.metSignificance = metMatrix.Similarity(metVector) 
        event.projMetAll1S  = self.jetProjectedMET(event.met, event.jets,True)
        event.projMetAll2S  = self.jetProjectedMET(event.met, event.jets,False)
        event.projMetJets1S = self.jetProjectedMET(event.met, event.cleanJets,True)
        event.projMetJets2S = self.jetProjectedMET(event.met, event.cleanJets,False)
        #print "MET value:  ", event.met.pt()
        #print "MET sumET:  ", event.met.sumEt()
        #print "MET signif: ", event.metSignificance
        #print "PrMETAll 1S:", event.projMetAll1S 
        #print "PrMETAll 2S:", event.projMetAll2S 
        #print "PrMETJet 1S:", event.projMetJets1S 
        #print "PrMETJet 2S:", event.projMetJets2S

    def makeHadTopDecays(self, event):
        event.lightJets = [ j for j in event.cleanJets if not j.btagWP("CSVM") ]
        event.minMWjj   = 999
        event.minMWjjPt = 0
        event.bestMWjj   = 0
        event.bestMWjjPt = 0
        event.bestMTopHad   = 0
        event.bestMTopHadPt = 0
        for i1,j1 in enumerate(event.lightJets):
            for i2 in xrange(i1+1,len(event.lightJets)):
                j2 = event.lightJets[i2]
                jjp4 = j1.p4() + j2.p4()
                mjj  = jjp4.M()
                if mjj > 30 and mjj < event.minMWjj:
                    event.minMWjj = mjj
                    event.minMWjjPt = jjp4.Pt()
                if abs(mjj-80.4) < abs(event.bestMWjj-80.4):
                    event.bestMWjj = mjj
                    event.bestMWjjPt = jjp4.Pt()
                    for bj in event.bjetsLoose:
                        if deltaR(bj.eta(),bj.phi(),j1.eta(),j1.phi()) < 0.1 or deltaR(bj.eta(),bj.phi(),j2.eta(),j2.phi()) < 0.1: continue
                        tp4 = jjp4 + bj.p4()
                        mtop = tp4.M()
                        if abs(mtop-172) < abs(event.bestMTopHad - 172):
                            event.bestMTopHad = mtop
                            event.bestMTopHadPt = tp4.Pt()

    def process(self, iEvent, event):
        self.readCollections( iEvent )
        self.counters.counter('events').inc('all events')

        if hasattr(self.cfg_ana, 'minJets25'):
            n25 = len([ j for j in event.cleanJets if j.pt() > 25 ])
            if n25 < self.cfg_ana.minJets25: 
                return False

        eventNumber = iEvent.eventAuxiliary().id().event()

        event.bjetsLoose  = [ j for j in event.cleanJets if j.btagWP("CSVL") ]
        event.bjetsMedium = [ j for j in event.cleanJets if j.btagWP("CSVM") ]

        objects25 = [ j for j in event.cleanJets if j.pt() > 25 ] + event.selectedLeptons
        objects30 = [ j for j in event.cleanJets if j.pt() > 30 ] + event.selectedLeptons
        objects40j = [ j for j in event.cleanJets if j.pt() > 40 ] 
        objects40  = [ j for j in event.cleanJets if j.pt() > 40 ] + event.selectedLeptons
        event.htJet25 = sum([x.pt() for x in objects25])
        event.mhtJet25 = hypot(sum([x.px() for x in objects25]), sum([x.py() for x in objects25]))
        event.htJet30 = sum([x.pt() for x in objects30])
        event.mhtJet30 = hypot(sum([x.px() for x in objects30]), sum([x.py() for x in objects30]))
        event.htJet40 = sum([x.pt() for x in objects40])
        event.htJet40j = sum([x.pt() for x in objects40j])
        event.mhtJet40 = hypot(sum([x.px() for x in objects40]), sum([x.py() for x in objects40]))
        ## same but with all eta range
        objects25a = [ j for j in event.cleanJetsAll if j.pt() > 25 ] + event.selectedLeptons
        objects30a = [ j for j in event.cleanJetsAll if j.pt() > 30 ] + event.selectedLeptons
        event.htJet25a = sum([x.pt() for x in objects25a])
        event.mhtJet25a = hypot(sum([x.px() for x in objects25a]), sum([x.py() for x in objects25a]))
        event.htJet30a = sum([x.pt() for x in objects30a])
        event.mhtJet30a = hypot(sum([x.px() for x in objects30a]), sum([x.py() for x in objects30a]))

        self.makeMETs(event);
        self.makeZs(event, self.maxLeps)
        self.makeMlls(event, self.maxLeps)

        self.makeHadTopDecays(event)
        for lep in event.selectedLeptons:
            self.leptonMVA.addMVA(lep)
        for lep in event.inclusiveLeptons:
            if lep not in event.selectedLeptons:
                self.leptonMVA.addMVA(lep)

        if self.cfg_ana.verbose:
            print 'Event ',eventNumber
            print 'Selected leptons: ',len(event.selectedLeptons)
            print "\n".join(["\t%s" % p for p in event.selectedLeptons])
            print 'Selected clean jets   : ',len(event.cleanJets)
            print "\n".join(["\t%s" % p for p in event.cleanJets])
            print 'Selected loose  b-jets: ',len(event.bjetsLoose)
            print 'Selected medium b-jets: ',len(event.bjetsMedium)
            print 'Best Z1, if any: mass = %6.1f ' % event.bestZ1[0]
            print 'Best Z2, if any: mass = %6.1f ' % event.bestZ2[3]
            print 'Min m(ll) values: SF/OS = %5.1f, AF/OS = %5.1f, AF/AS = %5.1f' % (event.minMllSFOS, event.minMllAFOS, event.minMllAFAS)

        self.counters.counter('events').inc('accepted events')
        return True
class ttHCoreEventAnalyzer(Analyzer):
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(ttHCoreEventAnalyzer, self).__init__(cfg_ana, cfg_comp,
                                                   looperName)
        self.maxLeps = cfg_ana.maxLeps
        self.leptonMVA = LeptonMVA(
            "%s/src/CMGTools/TTHAnalysis/data/leptonMVA/%%s_BDTG.weights.xml" %
            os.environ['CMSSW_BASE'], self.cfg_comp.isMC)

    def declareHandles(self):
        super(ttHCoreEventAnalyzer, self).declareHandles()
        self.handles['met'] = AutoHandle('cmgPFMET',
                                         'std::vector<cmg::BaseMET>')
        self.handles['nopumet'] = AutoHandle('nopuMet',
                                             'std::vector<reco::PFMET>')
        self.handles['metSignificance'] = AutoHandle('pfMetSignificance',
                                                     'cmg::METSignificance')
        self.handles['rho'] = AutoHandle(('kt6PFJets', 'rho', ''), 'double')

    def beginLoop(self):
        super(ttHCoreEventAnalyzer, self).beginLoop()
        self.counters.addCounter('events')
        count = self.counters.counter('events')
        count.register('all events')

    def makeZs(self, event, maxLeps):
        event.bestZ1 = [0., -1, -1]
        event.bestZ1sfss = [0., -1, -1]
        event.bestZ2 = [0., -1, -1, 0.]
        nlep = len(event.selectedLeptons)
        for i, l1 in enumerate(event.selectedLeptons):
            for j in range(i + 1, nlep):
                if j >= maxLeps: break
                l2 = event.selectedLeptons[j]
                if l1.pdgId() == -l2.pdgId():
                    zmass = (l1.p4() + l2.p4()).M()
                    if event.bestZ1[0] == 0 or abs(zmass - 91.188) < abs(
                            event.bestZ1[0] - 91.188):
                        event.bestZ1 = [zmass, i, j]
                if l1.pdgId() == l2.pdgId():
                    zmass = (l1.p4() + l2.p4()).M()
                    if event.bestZ1sfss[0] == 0 or abs(zmass - 91.188) < abs(
                            event.bestZ1sfss[0] - 91.188):
                        event.bestZ1sfss = [zmass, i, j]
        if event.bestZ1[0] != 0 and nlep > 3:
            for i, l1 in enumerate(event.selectedLeptons):
                if i == event.bestZ1[1]: continue
                for j in range(i + 1, nlep):
                    if j >= maxLeps: break
                    if j == event.bestZ1[2]: continue
                    l2 = event.selectedLeptons[j]
                    if l1.pdgId() == -l2.pdgId():
                        if l1.pt() + l2.pt() > event.bestZ2[0]:
                            event.bestZ2 = [
                                l1.pt() + l2.pt(), i, j,
                                (l1.p4() + l2.p4()).M()
                            ]

    def makeMlls(self, event, maxLeps):
        mllsfos = self.mllValues(event,
                                 lambda l1, l2: l1.pdgId() == -l2.pdgId(),
                                 maxLeps)
        mllafos = self.mllValues(event,
                                 lambda l1, l2: l1.charge() == -l2.charge(),
                                 maxLeps)
        mllafss = self.mllValues(event,
                                 lambda l1, l2: l1.charge() == l2.charge(),
                                 maxLeps)
        mllafas = self.mllValues(event, lambda l1, l2: True, maxLeps)
        event.minMllSFOS = min(mllsfos)
        event.minMllAFOS = min(mllafos)
        event.minMllAFSS = min(mllafss)
        event.minMllAFAS = min(mllafas)
        event.maxMllSFOS = max(mllsfos)
        event.maxMllAFAS = max(mllafas)
        event.maxMllAFOS = max(mllafos)
        event.maxMllAFSS = max(mllafss)
        drllafos = self.drllValues(event,
                                   lambda l1, l2: l1.charge() == -l2.charge(),
                                   maxLeps)
        drllafss = self.drllValues(event,
                                   lambda l1, l2: l1.charge() == l2.charge(),
                                   maxLeps)
        event.minDrllAFSS = min(drllafss)
        event.minDrllAFOS = min(drllafos)
        event.maxDrllAFOS = max(drllafos)
        event.maxDrllAFSS = max(drllafss)
        ptllafos = self.ptllValues(event,
                                   lambda l1, l2: l1.charge() == -l2.charge(),
                                   maxLeps)
        ptllafss = self.ptllValues(event,
                                   lambda l1, l2: l1.charge() == l2.charge(),
                                   maxLeps)
        event.minPtllAFSS = min(ptllafss)
        event.minPtllAFOS = min(ptllafos)
        event.maxPtllAFOS = max(ptllafos)
        event.maxPtllAFSS = max(ptllafss)
        leps = event.selectedLeptons
        nlep = len(leps)
        event.m2l = (leps[0].p4() + leps[1].p4()).M() if nlep >= 2 else 0
        event.pt2l = (leps[0].p4() + leps[1].p4()).Pt() if nlep >= 2 else 0
        event.q3l = sum([l.charge() for l in leps[:2]]) if nlep >= 3 else 0
        event.ht3l = sum([l.pt() for l in leps[:2]]) if nlep >= 3 else 0
        event.pt3l = (leps[0].p4() + leps[1].p4() +
                      leps[2].p4()).Pt() if nlep >= 3 else 0
        event.m3l = (leps[0].p4() + leps[1].p4() +
                     leps[2].p4()).M() if nlep >= 3 else 0
        event.q4l = sum([l.charge() for l in leps[:3]]) if nlep >= 4 else 0
        event.ht4l = sum([l.pt() for l in leps[:3]]) if nlep >= 4 else 0
        event.pt4l = (leps[0].p4() + leps[1].p4() + leps[2].p4() +
                      leps[3].p4()).Pt() if nlep >= 4 else 0
        event.m4l = (leps[0].p4() + leps[1].p4() + leps[2].p4() +
                     leps[3].p4()).M() if nlep >= 4 else 0
        event.vtx2l = twoTrackChi2(leps[0], leps[1]) if nlep >= 2 else (-1, -1)

    def mllValues(self, event, pairSelection, maxLeps):
        return self.llValues(event, lambda l1, l2: (l1.p4() + l2.p4()).M(),
                             pairSelection, maxLeps)

    def drllValues(self, event, pairSelection, maxLeps):
        return self.llValues(
            event,
            lambda l1, l2: deltaR(l1.eta(), l1.phi(), l2.eta(), l2.phi()),
            pairSelection, maxLeps)

    def ptllValues(self, event, pairSelection, maxLeps):
        return self.llValues(event, lambda l1, l2: (l1.p4() + l2.p4()).Pt(),
                             pairSelection, maxLeps)

    def llValues(self, event, function, pairSelection, maxLeps):
        pairs = []
        nlep = len(event.selectedLeptons)
        for i, l1 in enumerate(event.selectedLeptons):
            for j in range(i + 1, nlep):
                if j >= maxLeps: break
                l2 = event.selectedLeptons[j]
                if pairSelection(l1, l2):
                    pairs.append(function(l1, l2))
        if pairs == []: pairs.append(-1)
        return pairs

    def makeLepPtRel(self, event):
        for l in event.selectedLeptons:
            (px, py, pz) = (l.px(), l.py(), l.pz())
            (jx, jy, jz) = (l.jet.px(), l.jet.py(), l.jet.pz())
            cross = (px * jy - py * jx, py * jz - pz * jy, pz * jx - px * jz)
            l.ptRelJet = sqrt(sum([v * v for v in cross])) / l.jet.p()

    def makeMETs(self, event):
        event.met = self.handles['met'].product()[0]
        event.metNoPU = self.handles['nopumet'].product()[0]
        if hasattr(event, 'deltaMetFromJetSmearing'):
            import ROOT
            px, py = event.met.px() + event.deltaMetFromJetSmearing[
                0], event.met.py() + event.deltaMetFromJetSmearing[1]
            event.met.setP4(
                ROOT.reco.Particle.LorentzVector(px, py, 0, hypot(px, py)))
            px, py = event.metNoPU.px() + event.deltaMetFromJetSmearing[
                0], event.metNoPU.py() + event.deltaMetFromJetSmearing[1]
            event.metNoPU.setP4(
                ROOT.reco.Particle.LorentzVector(px, py, 0, hypot(px, py)))
        if hasattr(
                event, 'deltaMetFromJEC'
        ) and event.deltaMetFromJEC[0] != 0 and event.deltaMetFromJEC[1] != 0:
            import ROOT
            px, py = event.met.px() + event.deltaMetFromJEC[0], event.met.py(
            ) + event.deltaMetFromJEC[1]
            event.met.setP4(
                ROOT.reco.Particle.LorentzVector(px, py, 0, hypot(px, py)))
            px, py = event.metNoPU.px() + event.deltaMetFromJEC[
                0], event.metNoPU.py() + event.deltaMetFromJEC[1]
            event.metNoPU.setP4(
                ROOT.reco.Particle.LorentzVector(px, py, 0, hypot(px, py)))

        metMatrix = self.handles['metSignificance'].product().significance()
        metMatrix.Invert()
        import array
        metVector = TVectorD(
            2, array.array('d',
                           [event.met.px(), event.met.py()]))
        event.metSignificance = metMatrix.Similarity(metVector)

    def process(self, iEvent, event):
        self.readCollections(iEvent)
        self.counters.counter('events').inc('all events')

        event.rho = self.handles['rho'].product()[0]
        event.bjetsLoose = [j for j in event.cleanJets if j.btagWP("CSVL")]
        event.bjetsMedium = [j for j in event.cleanJets if j.btagWP("CSVM")]

        import ROOT

        objects25 = [j for j in event.cleanJets if j.pt() > 25
                     ] + event.selectedLeptons
        objects30 = [j for j in event.cleanJets if j.pt() > 30
                     ] + event.selectedLeptons
        objects40 = [j for j in event.cleanJets if j.pt() > 40
                     ] + event.selectedLeptons
        objects40j = [j for j in event.cleanJets if j.pt() > 40]
        objects40jc = [
            j for j in event.cleanJets if j.pt() > 40 and abs(j.eta()) < 2.5
        ]

        event.htJet25 = sum([x.pt() for x in objects25])
        event.mhtJet25vec = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects25])),
            -1. * (sum([x.py() for x in objects25])), 0, 0)
        event.mhtPhiJet25 = event.mhtJet25vec.phi()
        event.mhtJet25 = event.mhtJet25vec.pt()

        event.htJet30 = sum([x.pt() for x in objects30])
        event.mhtJet30vec = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects30])),
            -1. * (sum([x.py() for x in objects30])), 0, 0)
        event.mhtJet30 = event.mhtJet30vec.pt()
        event.mhtPhiJet30 = event.mhtJet30vec.phi()

        event.htJet40 = sum([x.pt() for x in objects40])
        event.mhtJet40vec = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects40])),
            -1. * (sum([x.py() for x in objects40])), 0, 0)
        event.mhtJet40 = event.mhtJet40vec.pt()
        event.mhtPhiJet40 = event.mhtJet40vec.phi()

        event.htJet40j = sum([x.pt() for x in objects40j])
        event.mhtJet40jvec = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects40j])),
            -1. * (sum([x.py() for x in objects40j])), 0, 0)
        event.mhtJet40j = event.mhtJet40jvec.pt()
        event.mhtPhiJet40j = event.mhtJet40jvec.phi()

        event.htJet40jc = sum([x.pt() for x in objects40jc])
        event.mhtJet40jcvec = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects40jc])),
            -1. * (sum([x.py() for x in objects40jc])), 0, 0)
        event.mhtJet40jc = event.mhtJet40jcvec.pt()
        event.mhtPhiJet40jc = event.mhtJet40jcvec.phi()

        ## same but with all eta range
        objects25a = [j for j in event.cleanJetsAll if j.pt() > 25
                      ] + event.selectedLeptons
        objects30a = [j for j in event.cleanJetsAll if j.pt() > 30
                      ] + event.selectedLeptons
        objects40a = [j for j in event.cleanJetsAll if j.pt() > 40
                      ] + event.selectedLeptons
        objects40ja = [j for j in event.cleanJetsAll if j.pt() > 40]

        event.htJet25a = sum([x.pt() for x in objects25a])
        event.mhtJet25veca = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects25a])),
            -1. * (sum([x.py() for x in objects25a])), 0, 0)
        event.mhtPhiJet25a = event.mhtJet25veca.phi()
        event.mhtJet25a = event.mhtJet25veca.pt()

        event.htJet30a = sum([x.pt() for x in objects30a])
        event.mhtJet30veca = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects30a])),
            -1. * (sum([x.py() for x in objects30a])), 0, 0)
        event.mhtJet30a = event.mhtJet30veca.pt()
        event.mhtPhiJet30a = event.mhtJet30veca.phi()

        event.htJet40a = sum([x.pt() for x in objects40a])
        event.mhtJet40veca = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects40a])),
            -1. * (sum([x.py() for x in objects40a])), 0, 0)
        event.mhtJet40a = event.mhtJet40veca.pt()
        event.mhtPhiJet40a = event.mhtJet40veca.phi()

        event.htJet40ja = sum([x.pt() for x in objects40ja])
        event.mhtJet40jveca = ROOT.reco.Particle.LorentzVector(
            -1. * (sum([x.px() for x in objects40ja])),
            -1. * (sum([x.py() for x in objects40ja])), 0, 0)
        event.mhtJet40ja = event.mhtJet40jveca.pt()
        event.mhtPhiJet40ja = event.mhtJet40jveca.phi()

        self.makeMETs(event)
        self.makeZs(event, self.maxLeps)
        self.makeMlls(event, self.maxLeps)
        self.makeLepPtRel(event)

        # look for minimal deltaPhi between MET and four leading jets with pt>40 and eta<2.4
        event.deltaPhiMin = 999.
        for n, j in enumerate(objects40jc):
            if n > 3: break
            thisDeltaPhi = abs(deltaPhi(j.phi(), event.met.phi()))
            if thisDeltaPhi < event.deltaPhiMin:
                event.deltaPhiMin = thisDeltaPhi

        for lep in event.selectedLeptons:
            self.leptonMVA.addMVA(lep)
        for lep in event.inclusiveLeptons:
            if lep not in event.selectedLeptons:
                self.leptonMVA.addMVA(lep)

        # absolute value of the vectorial difference between met and mht
        diffMetMht_vec = ROOT.reco.Particle.LorentzVector(
            event.mhtJet40jcvec.px() - event.met.px(),
            event.mhtJet40jcvec.py() - event.met.py(), 0, 0)
        event.diffMetMht = sqrt(diffMetMht_vec.px() * diffMetMht_vec.px() +
                                diffMetMht_vec.py() * diffMetMht_vec.py())

        return True