Пример #1
0
def getMT2ll( event ):
    l1 = ROOT.TLorentzVector()
    l2 = ROOT.TLorentzVector()
    event.lep_pt[event.nonZ1_l1_index_4l]
    l1.SetPtEtaPhiM(event.lep_pt[event.nonZ1_l1_index_4l], event.lep_eta[event.nonZ1_l1_index_4l], event.lep_phi[event.nonZ1_l1_index_4l], 0 )
    l2.SetPtEtaPhiM(event.lep_pt[event.nonZ1_l2_index_4l], event.lep_eta[event.nonZ1_l2_index_4l], event.lep_phi[event.nonZ1_l2_index_4l], 0 )
    mt2Calc.setLeptons(l1.Pt(), l1.Eta(), l1.Phi(), l2.Pt(), l2.Eta(), l2.Phi())

    #print event.nonZ1_l1_index_4l, event.nonZ1_l2_index_4l, event.Z1_l1_index_4l, event.Z1_l2_index_4l

    met         = ROOT.TLorentzVector()
    met.SetPtEtaPhiM( event.met_pt, 0, event.met_phi, 0)

    genZ        = ROOT.TLorentzVector()
    genZ.SetPtEtaPhiM( event.genZ_pt, event.genZ_eta, event.genZ_phi, 0)


    response    = .99
    Z           = ROOT.TLorentzVector()
    Z.SetPtEtaPhiM( event.Z1_pt_4l*response, event.Z1_eta_4l, event.Z1_phi_4l, 0) #mass missing?!

    # smear the Z with some resolution. 20% resolution assumed for now.
    #if Z.Pt()>200:
    #    rd = rand.Gaus(0,0.25)
    #elif Z.Pt()>100:
    #    rd = rand.Gaus(0,0.25)
    #else:
    #    rd = rand.Gaus(0,0.25)
    #rd = rand.Gaus(0,0.20)
    #Z_pt = (1+rd)*Z.Pt()*0.95
    rd = rand.Gaus(0,20)
    Z_pt = (rd+Z.Pt())*0.95
    #Z_px = Z_pt*math.cos(Z.Phi())
    #Z_py = Z_pt*math.sin(Z.Phi())
    smearZ = ROOT.TLorentzVector()
    smearZ.SetPtEtaPhiM( Z_pt, event.Z1_eta_4l, event.Z1_phi_4l, 0)
    
    #print met.Phi(), Z.Phi()

    newMet = Z + met
    newMetSmear = met + smearZ

    mt2Calc.setMet(newMet.Pt(), newMet.Phi())
    dl_mt2ll_Z = mt2Calc.mt2ll()
    
    mt2Calc.setMet(newMetSmear.Pt(), newMet.Phi()) # phi doesn't change anyway
    dl_mt2ll_Z_smear = mt2Calc.mt2ll()
    
    event.newMet_pt     = newMet.Pt()
    event.newMet_phi    = newMet.Phi()
    
    event.newMetSmeared_pt  = newMetSmear.Pt()
    event.dl_mt2ll_Z        = dl_mt2ll_Z
    event.dl_mt2ll_Z_smear  = dl_mt2ll_Z_smear
    
    event.dPhi_nonZ_l1_newMet = deltaPhi(newMet.Phi(), l1.Phi())
    event.dPhi_nonZ_l2_newMet = deltaPhi(newMet.Phi(), l2.Phi())

    return 1#newMet.Pt(), newMetSmear.Pt(), dl_mt2ll_Z, dl_mt2ll_Z_smear, newMet.Phi()
Пример #2
0
def getBJetDR( event, sample ):
    jets = getJets(event, jetVars=jetVars, jetColl="jet")
    trueBJets = [ j for j in jets if abs(j['hadronFlavour'])==5 ]
    bjets = [ j for j in jets if j['btagDeepCSV']>0.6324 and j['pt']>30 and abs(j['eta'])<2.4 ]

    minDR = -1
    mindPhi = -1
    if len(bjets)>1:
        minDR = 999.
        mindPhi = 4.
        comb = itertools.combinations(bjets, 2)
        for c in comb:
            dR = deltaR(c[0], c[1])
            dPhi = deltaPhi(c[0]['phi'], c[1]['phi'])
            dEta = abs(c[0]['eta'] - c[1]['eta'])
            if dR < minDR:
                minDR = dR
                mindPhi = dPhi
                mindEta = dEta
                l1  = ROOT.TLorentzVector()
                l2  = ROOT.TLorentzVector()
                l1.SetPtEtaPhiM( c[0]['pt'], c[0]['eta'], c[0]['phi'], 0)
                l2.SetPtEtaPhiM( c[1]['pt'], c[1]['eta'], c[1]['phi'], 0)
                M = (l1 + l2).M()
    event.bjet_dR       = minDR
    event.bjet_dPhi     = mindPhi
    event.bjet_invMass  = M
    event.bjet_dEta     = mindEta
    event.b1_pt         = l1.Pt()
    event.b1_phi        = l1.Phi()
    event.b1_eta        = l1.Eta()
    event.b2_pt         = l2.Pt()
    event.b2_phi        = l2.Phi()
    event.b2_eta        = l2.Eta()
    return
Пример #3
0
def getDPhiZLep(event, sample):
    event.dPhiZLep = deltaPhi(event.lep_phi[event.nonZ_l1_index], event.Z_phi)
Пример #4
0
def filler(event):
    # shortcut
    r = reader.event
    if isMC: gPart = getGenPartsAll(r)

    # weight
    if isMC:
        event.weight = lumiScaleFactor * r.genWeight if lumiScaleFactor is not None else 1
    elif isData:
        event.weight = 1
    else:
        raise NotImplementedError("isMC %r isData %r " % (isMC, isData))

    # lumi lists and vetos
    if isData:
        #event.vetoPassed  = vetoList.passesVeto(r.run, r.lumi, r.evt)
        event.jsonPassed = lumiList.contains(r.run, r.lumi)
        # store decision to use after filler has been executed
        event.jsonPassed_ = event.jsonPassed

    if isMC:
        event.reweightPU36fb = nTrueInt36fb_puRW(r.nTrueInt)
        event.reweightPU36fbDown = nTrueInt36fb_puRWDown(r.nTrueInt)
        event.reweightPU36fbUp = nTrueInt36fb_puRWUp(r.nTrueInt)

    # top pt reweighting
    if isMC and options.doTopPtReweighting:
        event.reweightTopPt = topPtReweightingFunc(getTopPtsForReweighting(
            r)) / topScaleF if doTopPtReweighting else 1.

    # Leptons: Reading LepGood and LepOther and fill new LepGood collection in the output tree
    mu_selector = muonSelector(isoVar="relIso04",
                               barrelIso=0.25,
                               endcapIso=0.25,
                               absEtaCut=2.4,
                               dxy=0.05,
                               dz=0.1)
    ele_selector = eleSelector(isoVar="relIso03",
                               barrelIso=0.1,
                               endcapIso=0.1,
                               absEtaCut=2.5,
                               dxy=0.05,
                               dz=0.1,
                               eleId="M",
                               noMissingHits=False)
    leptons = getGoodAndOtherLeptons(r,
                                     ptCut=10,
                                     mu_selector=mu_selector,
                                     ele_selector=ele_selector)
    leptons.sort(key=lambda p: -p['pt'])

    # Store leptons
    event.nlep = len(leptons)
    for iLep, lep in enumerate(leptons):
        lep['index'] = iLep  # Index wrt to the output collection!
        lep['relIso'] = lep["relIso04"] if abs(
            lep['pdgId']) == 13 else lep["relIso03"]
        for b in lepton_vars_store:
            getattr(event, "lep_" + b)[iLep] = lep[b]

    # Storing lepton counters
    event.nGoodMuons = len(filter(lambda l: abs(l['pdgId']) == 13, leptons))
    event.nGoodElectrons = len(filter(lambda l: abs(l['pdgId']) == 11,
                                      leptons))
    event.nGoodLeptons = len(leptons)

    # Lepton convinience
    if options.leptonConvinience:
        for i in range(min(4, len(leptons))):
            for var in lep_convinience_vars:
                setattr(event, "l{n}_{var}".format(n=i + 1, var=var),
                        leptons[i][var])

    # Identify best Z
    (event.Z_mass, event.Z_l1_index,
     event.Z_l2_index) = closestOSDLMassToMZ(leptons)
    nonZ_lepton_indices = [
        i for i in range(len(leptons))
        if i not in [event.Z_l1_index, event.Z_l2_index]
    ]
    event.nonZ_l1_index = nonZ_lepton_indices[0] if len(
        nonZ_lepton_indices) > 0 else -1
    event.nonZ_l2_index = nonZ_lepton_indices[1] if len(
        nonZ_lepton_indices) > 1 else -1

    # Store Z information
    if event.Z_mass >= 0:
        if leptons[event.Z_l1_index]['pdgId'] * leptons[
                event.Z_l2_index]['pdgId'] > 0 or abs(
                    leptons[event.Z_l1_index]['pdgId']) != abs(
                        leptons[event.Z_l2_index]['pdgId']):
            raise RuntimeError("not a Z! Should never happen")
        Z_l1 = ROOT.TLorentzVector()
        Z_l1.SetPtEtaPhiM(leptons[event.Z_l1_index]['pt'],
                          leptons[event.Z_l1_index]['eta'],
                          leptons[event.Z_l1_index]['phi'], 0)
        Z_l2 = ROOT.TLorentzVector()
        Z_l2.SetPtEtaPhiM(leptons[event.Z_l2_index]['pt'],
                          leptons[event.Z_l2_index]['eta'],
                          leptons[event.Z_l2_index]['phi'], 0)
        Z = Z_l1 + Z_l2
        event.Z_pt = Z.Pt()
        event.Z_eta = Z.Eta()
        event.Z_phi = Z.Phi()
        event.Z_lldPhi = deltaPhi(leptons[event.Z_l1_index]['phi'],
                                  leptons[event.Z_l2_index]['phi'])
        event.Z_lldR = deltaR(leptons[event.Z_l1_index],
                              leptons[event.Z_l2_index])

        ## get the information for cos(theta*)
        # get the Z and lepton (negative charge) vectors
        lm_index = event.Z_l1_index if event.lep_pdgId[
            event.Z_l1_index] > 0 else event.Z_l2_index
        event.cosThetaStar = cosThetaStar(event.Z_mass, event.Z_pt,
                                          event.Z_eta, event.Z_phi,
                                          event.lep_pt[lm_index],
                                          event.lep_eta[lm_index],
                                          event.lep_phi[lm_index])

    # Jets and lepton jet cross-cleaning
    allJets = getAllJets(r,
                         leptons,
                         ptCut=0,
                         jetVars=jetVarNames,
                         absEtaCut=99,
                         jetCollections=["Jet", "DiscJet"])  #JetId is required
    selected_jets, other_jets = [], []
    for j in allJets:
        if isAnalysisJet(j, ptCut=30, absEtaCut=2.4):
            selected_jets.append(j)
        else:
            other_jets.append(j)

    # Don't change analysis jets even if we keep all jets, hence, apply abs eta cut
    bJets = filter(
        lambda j: isBJet(j, tagger='CSVv2') and abs(j['eta']) <= 2.4,
        selected_jets)
    bJetsDeepCSV = filter(
        lambda j: isBJet(j, tagger='DeepCSV') and abs(j['eta']) <= 2.4,
        selected_jets)
    nonBJets = filter(
        lambda j: not (isBJet(j, tagger='CSVv2') and abs(j['eta']) <= 2.4),
        selected_jets)
    nonBJetsDeepCSV = filter(
        lambda j: not (isBJet(j, tagger='DeepCSV') and abs(j['eta']) <= 2.4),
        selected_jets)

    # Store jets
    event.nJetSelected = len(selected_jets)
    jets_stored = allJets
    event.njet = len(jets_stored)
    for iJet, jet in enumerate(jets_stored):
        for b in jetVarNames:
            getattr(event, "jet_" + b)[iJet] = jet[b]

    # ETmiss
    event.met_pt = r.met_pt
    event.met_phi = r.met_phi

    # Analysis observables
    event.ht = sum([j['pt'] for j in selected_jets])
    event.metSig = event.met_pt / sqrt(event.ht) if event.ht > 0 else float(
        'nan')
    event.nBTag = len(bJets)
    event.nBTagDeepCSV = len(bJetsDeepCSV)

    # Systematics
    jets_sys = {}
    bjets_sys = {}
    nonBjets_sys = {}

    metVariants = ['']  # default

    if options.keepPhotons:
        # Keep photons and estimate met including (leading pt) photon
        photons = getGoodPhotons(r, ptCut=20, idLevel="loose", isData=isData)
        event.nPhotonGood = len(photons)
        if event.nPhotonGood > 0:
            metVariants += [
                '_photonEstimated'
            ]  # do all met calculations also for the photonEstimated variant
            event.photon_pt = photons[0]['pt']
            event.photon_eta = photons[0]['eta']
            event.photon_phi = photons[0]['phi']
            event.photon_idCutBased = photons[0]['idCutBased']
            if isMC:
                genPhoton = getGenPhoton(gPart)
                event.photon_genPt = genPhoton[
                    'pt'] if genPhoton is not None else float('nan')
                event.photon_genEta = genPhoton[
                    'eta'] if genPhoton is not None else float('nan')

            event.met_pt_photonEstimated, event.met_phi_photonEstimated = getMetPhotonEstimated(
                r.met_pt, r.met_phi, photons[0])
            event.metSig_photonEstimated = event.met_pt_photonEstimated / sqrt(
                event.ht) if event.ht > 0 else float('nan')

            event.photonJetdR = min(
                deltaR(photons[0], j)
                for j in selected_jets) if len(selected_jets) > 0 else 999
            event.photonLepdR = min(
                deltaR(photons[0], l)
                for l in leptons) if len(leptons) > 0 else 999

        if isMC:
            event.TTGJetsEventType = getTTGJetsEventType(r)

    if addSystematicVariations:
        for j in allJets:
            j['pt_JECUp'] = j['pt'] / j['corr'] * j['corr_JECUp']
            j['pt_JECDown'] = j['pt'] / j['corr'] * j['corr_JECDown']
            # JERUp, JERDown, JER
            addJERScaling(j)
        for var in ['JECUp', 'JECDown', 'JERUp', 'JERDown']:
            jets_sys[var] = filter(
                lambda j: isAnalysisJet(
                    j, ptCut=30, absEtaCut=2.4, ptVar='pt_' + var), allJets)
            bjets_sys[var] = filter(
                lambda j: isBJet(j) and abs(j['eta']) < 2.4, jets_sys[var])
            nonBjets_sys[var] = filter(
                lambda j: not (isBJet(j) and abs(j['eta']) < 2.4),
                jets_sys[var])

            setattr(event, "nJetSelected_" + var, len(jets_sys[var]))
            setattr(event, "ht_" + var,
                    sum([j['pt_' + var] for j in jets_sys[var]]))
            setattr(event, "nBTag_" + var, len(bjets_sys[var]))

        for var in [
                'JECUp', 'JECDown', 'JERUp', 'JERDown', 'UnclusteredEnUp',
                'UnclusteredEnDown'
        ]:
            for i in metVariants:
                # use cmg MET correction values ecept for JER where it is zero. There, propagate jet variations.
                if 'JER' in var or 'JECV' in var:
                    (met_corr_pt, met_corr_phi) = getMetJetCorrected(
                        getattr(event, "met_pt" + i),
                        getattr(event, "met_phi" + i), jets_sys[var], var)
                else:
                    (met_corr_pt, met_corr_phi) = getMetCorrected(
                        r, var,
                        photons[0] if i.count("photonEstimated") else None)

                setattr(event, "met_pt" + i + "_" + var, met_corr_pt)
                setattr(event, "met_phi" + i + "_" + var, met_corr_phi)
                ht = getattr(event, "ht_" +
                             var) if 'Unclustered' not in var else event.ht
                setattr(
                    event, "metSig" + i + "_" + var,
                    getattr(event, "met_pt" + i + "_" + var) /
                    sqrt(ht) if ht > 0 else float('nan'))

    if addSystematicVariations:

        # B tagging weights method 1a, first for CSVv2
        for j in selected_jets:
            btagEff_CSVv2.addBTagEffToJet(j)
        #print "CSVv2", selected_jets[0]['beff']['SF'], selected_jets[0]['pt']
        for var in btagEff_CSVv2.btagWeightNames:
            if var != 'MC':
                setattr(
                    event, 'reweightBTagCSVv2_' + var,
                    btagEff_CSVv2.getBTagSF_1a(
                        var, bJets,
                        filter(lambda j: abs(j['eta']) < 2.4, nonBJets)))

        # B tagging weights method 1a, now for DeepCSV
        for j in selected_jets:
            btagEff_DeepCSV.addBTagEffToJet(j)
        #print "DeepCSV", selected_jets[0]['beff']['SF'], selected_jets[0]['pt']
        for var in btagEff_DeepCSV.btagWeightNames:
            if var != 'MC':
                setattr(
                    event, 'reweightBTagDeepCSV_' + var,
                    btagEff_DeepCSV.getBTagSF_1a(
                        var, bJetsDeepCSV,
                        filter(lambda j: abs(j['eta']) < 2.4,
                               nonBJetsDeepCSV)))

    # gen information on extra leptons
    if isMC and not options.skipGenMatching:
        genSearch.init(gPart)
        # Start with status 1 gen leptons

        # gLep = filter( lambda p:abs(p['pdgId']) in [11, 13] and p['status']==1 and p['pt']>10 and abs(p['eta'])<2.5, gPart )
        # ... no acceptance cuts
        gLep = filter(
            lambda p: abs(p['pdgId']) in [11, 13] and p['status'] == 1, gPart)
        for l in gLep:
            ancestry = [gPart[x]['pdgId'] for x in genSearch.ancestry(l)]
            l["n_D"] = sum([ancestry.count(p) for p in D_mesons])
            l["n_B"] = sum([ancestry.count(p) for p in B_mesons])
            l["n_W"] = sum([ancestry.count(p) for p in [24, -24]])
            l["n_t"] = sum([ancestry.count(p) for p in [6, -6]])
            l["n_tau"] = sum([ancestry.count(p) for p in [15, -15]])
            matched_lep = bestDRMatchInCollection(
                l, leptons)  #FIXME -> fix all the gen / reco match indices!
            if matched_lep:
                l["lepGood2MatchIndex"] = matched_lep['index']
            else:
                l["lepGood2MatchIndex"] = -1

        # store genleps
        event.nGenLep = len(gLep)
        for iLep, lep in enumerate(gLep):
            for b in genLepVarNames:
                getattr(event, "GenLep_" + b)[iLep] = lep[b]

        # gen Z
        genZs = filter(
            lambda p: (abs(p['pdgId']) == 23 and genSearch.isLast(p)), gPart)
        genZs.sort(key=lambda p: -p['pt'])
        if len(genZs) > 0:
            genZ = genZs[0]
            event.genZ_pt = genZ['pt']
            event.genZ_mass = genZ['mass']
            event.genZ_eta = genZ['eta']
            event.genZ_phi = genZ['phi']

            lep_m = filter(lambda p: p['pdgId'] in [11, 13, 15],
                           genSearch.daughters(genZ))
            event.genZ_daughter_flavor = max(
                [p['pdgId'] for p in genSearch.daughters(genZ)])
            if len(lep_m) == 1:
                event.genZ_cosThetaStar = cosThetaStar(
                    event.genZ_mass, event.genZ_pt, event.genZ_eta,
                    event.genZ_phi, lep_m[0]['pt'], lep_m[0]['eta'],
                    lep_m[0]['phi'])
Пример #5
0
    Zs = [
        p for p in gPart
        if (abs(p['pdgId']) == 23 and abs(p['motherId']) != 23)
    ]
    ZsFromB = [z for z in Zs
               if (abs(z['motherId']) == 5)]  #or abs(z['motherId'])==21 )]
    ZsFromQ = [z for z in Zs if (abs(z['motherId']) < 5)]
    bsFromG = [b for b in bs if abs(b['motherId']) == 21]

    if len(recoBJets) > 1:
        minDR = 999.
        comb = itertools.combinations(recoBJets, 2)
        for c in comb:
            #dR = deltaR(c[0], c[1])
            dR = deltaPhi(c[0]['phi'], c[1]['phi'])
            if dR < minDR: minDR = dR

        minDR = 3.9 if minDR > 4 else minDR
        h_DR_reco.Fill(minDR, r.weight)

    if len(trueBJets) > 1:
        minDR = 999.
        comb = itertools.combinations(trueBJets, 2)
        for c in comb:
            #dR = deltaR(c[0], c[1])
            dR = deltaPhi(c[0]['phi'], c[1]['phi'])
            if dR < minDR: minDR = dR

        minDR = 3.9 if minDR > 4 else minDR
        h_DR_true.Fill(minDR, r.weight)
Пример #6
0
def getDPhiZLep(event, sample):
    event.dPhiZLep = deltaPhi(event.lep_phi[event.nonZ1_l1_index_4l],
                              event.Z2_phi_4l)
Пример #7
0
def getDPhiZJet(event, sample):
    event.dPhiZJet = deltaPhi(event.jets[0]['phi'], event.Z_phi) if len(
        event.jets) > 0 and event.Z_mass > 0 else float('nan')
Пример #8
0
def getDeltaPhi(event, sample=None):
    # 4l
#    event.nonZl1_Z1_deltaPhi = deltaPhi(event.lep_phi[event.nonZ1_l1_index_4l], event.Z1_phi_4l)
#    event.nonZl2_Z1_deltaPhi = deltaPhi(event.lep_phi[event.nonZ1_l2_index_4l], event.Z1_phi_4l)
    # 3l
    event.nonZl1_Z_deltaPhi = deltaPhi(event.lep_phi[event.nonZ_l1_index], event.Z_phi)
Пример #9
0
def makeDeltaPhi(event, sample):
    leps = getLepsFromZ(event, sample)
    if len(leps) == 2 and leps[0]['pdgId'] * leps[1]['pdgId'] < 0:
        event.dPhi_ll = deltaPhi(leps[0]['phi'], leps[1]['phi'])
    else:
        event.dPhi_ll = -1
Пример #10
0
def getDeltaPhi(event, sample=None):
    event.nonZl1_Z1_deltaPhi = deltaPhi(event.lep_phi[event.nonZ1_l1_index_4l],
                                        event.Z1_phi_4l)
    event.nonZl2_Z1_deltaPhi = deltaPhi(event.lep_phi[event.nonZ1_l2_index_4l],
                                        event.Z1_phi_4l)
Пример #11
0
def getDeltaPhi(event, sample=None):
    event.nonZl1_Z_deltaPhi = deltaPhi(event.lep_phi[event.nonZ_l1_index], event.Z_phi)
Пример #12
0
def filler(event):

    if reader.position % 100 == 0:
        logger.info("At event %i/%i", reader.position, reader.nEvents)
    event.lumiweight1fb = lumiweight1fb

    # read jets
    jets = filter(lambda j: isGoodDelphesJet(j), reader.jets())
    jets.sort(key=lambda p: -p['pt'])
    addIndex(jets)

    # make b jets
    #    for j in jets:
    #        print j['pt'], j['eta'], j['bTag'], j['bTagPhys'], j['bTagAlgo']
    bJets = filter(lambda j: j['bTagPhys'] >= 4, jets)
    nonBJets = filter(lambda j: not (j['bTagPhys'] < 4), jets)
    bj0, bj1 = (bJets + nonBJets + [None, None])[:2]
    fill_vector(event, "bj0", jet_write_varnames, bj0)
    fill_vector(event, "bj1", jet_write_varnames, bj1)

    event.nBTag = len(bJets)

    # read leptons
    allLeps = reader.muonsTight() + reader.electrons()
    allLeps.sort(key=lambda p: -p['pt'])
    leps = filter(isGoodDelphesLepton, allLeps)
    # cross-cleaning of reco-objects
    # leps = filter( lambda l: (min([999]+[deltaR2(l, j) for j in jets if j['pt']>30]) > 0.3**2 ), leps )
    # give index to leptons
    addIndex(leps)

    # Store
    fill_vector_collection(event, "lep", lep_varnames, leps)
    fill_vector_collection(event, "jet", jet_varnames, jets)

    event.nMuons = len(filter(lambda l: abs(l['pdgId']) == 13, leps))
    event.nElectrons = len(filter(lambda l: abs(l['pdgId']) == 11, leps))

    # MET
    met = reader.met()[0]

    event.met_pt = met['pt']
    event.met_phi = met['phi']

    # search for Z in leptons
    (event.Z_mass, Z_l1_index, Z_l2_index) = closestOSDLMassToMZ(leps)
    nonZ_indices = [
        i for i in range(len(leps)) if i not in [Z_l1_index, Z_l2_index]
    ]
    event.Z_l1_index = leps[Z_l1_index]['index'] if Z_l1_index >= 0 else -1
    event.Z_l2_index = leps[Z_l2_index]['index'] if Z_l2_index >= 0 else -1
    event.nonZ_l1_index = leps[
        nonZ_indices[0]]['index'] if len(nonZ_indices) > 0 else -1
    event.nonZ_l2_index = leps[
        nonZ_indices[1]]['index'] if len(nonZ_indices) > 1 else -1

    # Store Z information
    if event.Z_mass >= 0:
        if leps[event.Z_l1_index]['pdgId'] * leps[
                event.Z_l2_index]['pdgId'] > 0 or abs(
                    leps[event.Z_l1_index]['pdgId']) != abs(
                        leps[event.Z_l2_index]['pdgId']):
            raise RuntimeError("not a Z! Should not happen")
        Z_l1 = ROOT.TLorentzVector()
        Z_l1.SetPtEtaPhiM(leps[event.Z_l1_index]['pt'],
                          leps[event.Z_l1_index]['eta'],
                          leps[event.Z_l1_index]['phi'], 0)
        Z_l2 = ROOT.TLorentzVector()
        Z_l2.SetPtEtaPhiM(leps[event.Z_l2_index]['pt'],
                          leps[event.Z_l2_index]['eta'],
                          leps[event.Z_l2_index]['phi'], 0)
        Z = Z_l1 + Z_l2
        event.Z_pt = Z.Pt()
        event.Z_eta = Z.Eta()
        event.Z_phi = Z.Phi()
        event.Z_lldPhi = deltaPhi(leps[event.Z_l1_index]['phi'],
                                  leps[event.Z_l2_index]['phi'])
        event.Z_lldR = deltaR(leps[event.Z_l1_index], leps[event.Z_l2_index])
        lm_index = event.Z_l1_index if leps[
            event.Z_l1_index]['pdgId'] > 0 else event.Z_l2_index
        event.Z_cosThetaStar = cosThetaStar(event.Z_mass, event.Z_pt,
                                            event.Z_eta, event.Z_phi,
                                            leps[lm_index]['pt'],
                                            leps[lm_index]['eta'],
                                            leps[lm_index]['phi'])
Пример #13
0
def ttG2lPlots(index):
    ''' return plot list for ttG 2l plots
    '''

    plots = []

    plots.append(
        Plot(
            name='yield',
            texX='yield',
            texY='Number of Events',
            attribute=lambda event, sample: 0.5 + index,
            binning=[3, 0, 3],
        ))

    plots.append(
        Plot(
            name='nVtxs',
            texX='vertex multiplicity',
            texY='Number of Events',
            attribute=TreeVariable.fromString("nVert/I"),
            binning=[50, 0, 50],
        ))

    plots.append(
        Plot(
            name='MET',
            texX='E_{T}^{miss} (GeV)',
            texY='Number of Events / 20 GeV',
            attribute=TreeVariable.fromString("met_pt/F"),
            binning=[400 / 20, 0, 400],
        ))

    plots.append(
        Plot(
            name='MET_phi',
            texX='#phi(E_{T}^{miss})',
            texY='Number of Events / 20 GeV',
            attribute=TreeVariable.fromString("met_phi/F"),
            binning=[10, -pi, pi],
        ))

    #    plots.append(Plot(
    #        name = 'Gamma_pt', texX = 'p_{T}(#gamma) (GeV)', texY = 'Number of Events / 20 GeV',
    #        attribute = TreeVariable.fromString( "gamma_pt/F" ),
    #        binning=[20,0,400],
    #    ))

    #    plots.append(Plot(
    #        name = 'Gamma_pt_coarse', texX = 'p_{T}(#gamma) (GeV)', texY = 'Number of Events / 50 GeV',
    #        attribute = TreeVariable.fromString( "gamma_pt/F" ),
    #        binning=[16,0,800],
    #    ))

    #    plots.append(Plot(
    #        name = 'Gamma_pt_superCoarse', texX = 'p_{T}(#gamma) (GeV)', texY = 'Number of Events',
    #        attribute = TreeVariable.fromString( "gamma_pt/F" ),
    #        binning=[3,0,600],
    #    ))

    #    plots.append(Plot(
    #        name = 'Gamma_pt_analysis', texX = 'p_{T}(#gamma) (GeV)', texY = 'Number of Events / 100 GeV',
    #        attribute = TreeVariable.fromString( "gamma_pt/F" ),
    #        binning=[4,0,400],
    #    ))

    #    plots.append(Plot(
    #        name = 'l0gammaDPhi',
    #        texX = '#Delta#Phi(l_{0},#gamma)', texY = 'Number of Events',
    #        attribute = lambda event, sample: deltaPhi(event.selectedLeps[0]['phi'], event.gammas[0]['phi']),
    #        binning=[20,0,pi],
    #    ))

    #    plots.append(Plot(
    #        name = 'l0gammaDR',
    #        texX = '#Delta R(l_{0},#gamma)', texY = 'Number of Events',
    #        attribute = lambda event, sample: deltaR(event.selectedLeps[0], event.gammas[0]),
    #        binning=[20,0.3,3],
    #    ))

    plots.append(
        Plot(
            name="M3",
            texX='M_{3} (GeV)',
            texY='Number of Events',
            attribute=lambda event, sample: m3(event.selectedJets)[0]
            if len(event.selectedJets) > 2 else float('nan'),
            binning=[25, 0, 500],
        ))

    plots.append(
        Plot(
            name="dRll",
            texX='#Delta R(ll)',
            texY='Number of Events',
            attribute=lambda event, sample: deltaR(event.selectedJets[0], event
                                                   .selectedJets[1]),
            binning=[20, 0.3, 3],
        ))

    plots.append(
        Plot(
            name="dPhill",
            texX='#Delta#phi(ll)',
            texY='Number of Events',
            attribute=lambda event, sample: deltaPhi(
                event.selectedJets[0]['phi'], event.selectedJets[1]['phi']),
            binning=[10, 0, pi],
        ))

    plots.append(
        Plot(
            name="nForwardJet_Pt30_eta3",
            texX='nJet p_{T}(j)>30 GeV',
            texY='Number of Events',
            attribute=lambda event, sample: len(event.jetForward30_eta3),
            binning=[10, 0, 10],
        ))

    plots.append(
        Plot(
            name="nForwardJet_Pt40_eta3",
            texX='nJet p_{T}(j)>40 GeV',
            texY='Number of Events',
            attribute=lambda event, sample: len(event.jetForward40_eta3),
            binning=[10, 0, 10],
        ))

    plots.append(
        Plot(
            name="nForwardJet_Pt50_eta3",
            texX='nJet p_{T}(j)>50 GeV',
            texY='Number of Events',
            attribute=lambda event, sample: len(event.jetForward50_eta3),
            binning=[10, 0, 10],
        ))

    plots.append(
        Plot(
            name="nForwardJet_Pt60_eta3",
            texX='nJet p_{T}(j)>60 GeV',
            texY='Number of Events',
            attribute=lambda event, sample: len(event.jetForward60_eta3),
            binning=[10, 0, 10],
        ))

    plots.append(
        Plot(
            name="nForwardJet_Pt70_eta3",
            texX='nJet p_{T}(j)>70 GeV',
            texY='Number of Events',
            attribute=lambda event, sample: len(event.jetForward70_eta3),
            binning=[10, 0, 10],
        ))

    plots.append(
        Plot(
            name="M_ll",
            texX='M(ll) (GeV)',
            texY='Number of Events / 10 GeV',
            attribute=lambda event, sample: event.mll,
            binning=[20, 0, 200],
        ))

    plots.append(
        Plot(
            name="M_ll_coarse",
            texX='M(ll) (GeV)',
            texY='Number of Events / 20 GeV',
            attribute=lambda event, sample: event.mll,
            binning=[10, 0, 200],
        ))

    #    plots.append(Plot(
    #        name = "M_llgamma", texX = 'M(ll#gamma) (GeV)', texY = 'Number of Events / 10 GeV',
    #        attribute = lambda event, sample:event.mllgamma,
    #        binning=[20,0,200],
    #    ))

    #    plots.append(Plot(
    #        name = "M_llgamma_coarse", texX = 'M(ll#gamma) (GeV)', texY = 'Number of Events / 20 GeV',
    #        attribute = lambda event, sample:event.mllgamma,
    #        binning=[10,0,200],
    #    ))

    plots.append(
        Plot(
            name="nJets",
            texX='N_{jets}',
            texY='Number of Events',
            attribute=TreeVariable.fromString("nJetSelected/I"),  #nJetSelected
            binning=[8, -0.5, 7.5],
        ))

    plots.append(
        Plot(
            name="nBJets",
            texX='N_{b-tag}',
            texY='Number of Events',
            attribute=TreeVariable.fromString("nBTag/I"),  #nJetSelected
            binning=[4, -0.5, 3.5],
        ))

    plots.append(
        Plot(
            name="nLepLoose",
            texX='N_{l, loose}',
            texY='Number of Events',
            attribute=lambda event, sample: len(event.lepLoose),
            binning=[3, -0.5, 2.5],
        ))

    plots.append(
        Plot(
            name="nLep",
            texX='N_{lep}',
            texY='Number of Events',
            attribute=lambda event, sample: len(event.selectedLeps),
            binning=[3, -0.5, 2.5],
        ))

    plots.append(
        Plot(
            texX='p_{T}(leading l) (GeV)',
            texY='Number of Events / 20 GeV',
            name='lep1_pt',
            attribute=lambda event, sample: event.selectedLeps[0]['pt'],
            binning=[400 / 20, 0, 400],
        ))

    plots.append(
        Plot(
            texX='p_{T}(subleading l) (GeV)',
            texY='Number of Events / 10 GeV',
            name='lep2_pt',
            attribute=lambda event, sample: event.selectedLeps[1]['pt'],
            binning=[200 / 10, 0, 200],
        ))

    plots.append(
        Plot(
            texX='p_{T}(leading jet) (GeV)',
            texY='Number of Events / 30 GeV',
            name='jet1_pt',
            attribute=lambda event, sample: event.selectedJets[0]['pt'],
            binning=[600 / 30, 0, 600],
        ))

    plots.append(
        Plot(
            texX='p_{T}(2nd leading jet) (GeV)',
            texY='Number of Events / 30 GeV',
            name='jet2_pt',
            attribute=lambda event, sample: event.selectedJets[1]['pt'],
            binning=[600 / 30, 0, 600],
        ))

    plots.append(
        Plot(
            texX='p_{T}(leading b-jet cand) (GeV)',
            texY='Number of Events / 20 GeV',
            name='bjet1_pt',
            attribute=lambda event, sample: event.jets_sortbtag[0]['pt'],
            binning=[20, 0, 400],
        ))

    plots.append(
        Plot(
            texX='p_{T}(2nd leading b-jet cand) (GeV)',
            texY='Number of Events / 20 GeV',
            name='bjet2_pt',
            attribute=lambda event, sample: event.jets_sortbtag[1]['pt'],
            binning=[20, 0, 400],
        ))

    plots.append(
        Plot(
            name='deltaPhi_bb',
            texX='#Delta#phi(bb)',
            texY='Number of Events',
            attribute=lambda event, sample: deltaPhi(
                event.jets_sortbtag[0]['phi'], event.jets_sortbtag[1]['phi']),
            binning=[20, 0, pi],
        ))

    plots.append(
        Plot(
            name='deltaR_bb',
            texX='#DeltaR(bb)',
            texY='Number of Events',
            attribute=lambda event, sample: deltaR(event.jets_sortbtag[0],
                                                   event.jets_sortbtag[1]),
            binning=[20, 0, 6],
        ))

    return plots
Пример #14
0
def getW(event, sample):
    # get the W boson candidate
    event.W = {'vec2D': event.selectedLeps[0]['vec2D'] + event.MET['vec2D']}
    event.W['pt'] = event.W['vec2D'].Mod()
    event.W['phi'] = acos(event.W['vec2D'].X() / event.W['pt'])
    event.deltaPhi_Wl = deltaPhi(event.W['phi'], event.selectedLeps[0]['phi'])
Пример #15
0
def getDPhiZJet(event, sample):
    event.dPhiZJet = deltaPhi(
        event.jet_phi[0],
        event.Z_phi) if event.njet > 0 and event.Z_mass > 0 else float(
            'nan')  #nJetSelected
Пример #16
0
def reconstructLeptonicTop(event, sample):

    #print
    #print "Next event"
    lepton = ROOT.TLorentzVector()
    met = ROOT.TLorentzVector()
    n1 = ROOT.TLorentzVector()
    n2 = ROOT.TLorentzVector()
    b1 = ROOT.TLorentzVector()
    b2 = ROOT.TLorentzVector()

    MW = 80.385
    Mt = 172.5

    lepton.SetPtEtaPhiM(event.lep_pt[event.nonZ_l1_index],
                        event.lep_eta[event.nonZ_l1_index],
                        event.lep_phi[event.nonZ_l1_index], 0)
    met.SetPtEtaPhiM(event.met_pt, 0, event.met_phi, 0)

    # get the b from the top decay, assume back-to-back of the tops
    t1 = lepton + met + b1
    t2 = lepton + met + b2
    if t2.Pt() > t1.Pt(): b1, b2 = b2, b1

    a = lepton.Pz() * (2 * (lepton.Px() * met.Px() + lepton.Py() * met.Py()) -
                       lepton.M()**2 + MW**2)
    arg = lepton.E()**2 * ((2 *
                            (lepton.Px() * met.Px() + lepton.Py() * met.Py()) -
                            lepton.M()**2 + MW**2)**2 - 4 * met.Pt()**2 *
                           (lepton.E()**2 - lepton.Pz()**2))
    b = sqrt(
        arg
    ) if arg > 0 else 0.  # need this for events with MET mismeasurements
    c = 2 * (lepton.E()**2 - lepton.Pz()**2)
    MET_z_1 = (a + b) / c
    MET_z_2 = (a - b) / c

    E_n1 = sqrt(met.Px()**2 + met.Py()**2 + MET_z_1**2)
    E_n2 = sqrt(met.Px()**2 + met.Py()**2 + MET_z_2**2)

    n1.SetPxPyPzE(met.Px(), met.Py(), MET_z_1, E_n1)
    n2.SetPxPyPzE(met.Px(), met.Py(), MET_z_2, E_n2)

    W1 = lepton + n1
    W2 = lepton + n2

    t1 = lepton + n1 + b1
    t2 = lepton + n2 + b1

    # get top candidate with mass closer to Mt
    if abs(t2.M() - Mt) < abs(t1.M() - Mt): t1, t2 = t2, t1
    #print t1.M(), t2.M()

    event.mt_1 = t1.Mt()
    event.mt_2 = t2.Mt()

    event.top1_mass = t1.M()
    event.top1_pt = t1.Pt()
    event.top1_phi = t1.Phi()

    event.top2_mass = t2.M()
    event.top2_pt = t2.Pt()
    event.top2_phi = t2.Phi()

    event.b1_pt = b1.Pt()
    event.b1_phi = b1.Phi()
    event.b2_pt = b2.Pt()
    event.b2_phi = b2.Phi()

    event.deltaPhi_tl = acos(
        (t1.Px() * lepton.Px() + t1.Py() * lepton.Py()) / sqrt(
            (t1.Px()**2 + t1.Py()**2) * (lepton.Px()**2 + lepton.Py()**2)))
    lepton.Boost(-t1.BoostVector())
    event.deltaPhi_tl_topRF = deltaPhi(lepton.Phi(), t1.Phi())
    event.deltaR_tl_topRF = deltaR({
        'eta': lepton.Eta(),
        'phi': lepton.Phi()
    }, {
        'eta': t1.Eta(),
        'phi': t1.Phi()
    })
    event.deltaEta_tl_topRF = abs(lepton.Eta() - t1.Eta())
Пример #17
0
dilepS.setSelectionString([dilepSelection])
dilepS.texName = texNameDilepTTZ
reader2 = dilepS.treeReader( variables = variables )
reader2.start()

while reader2.run():
    r = reader2.event
    weight = r.weight * r.reweightLeptonSF_tight_4l * r.reweightTrigger_tight_4l
    met_pt = r.met_pt
    met_phi = r.met_phi
    
    l1_phi = r.lep_phi[r.nonZ1_l1_index_4l]
    l2_phi = r.lep_phi[r.nonZ1_l2_index_4l]

    dilep_dPhi_metL1.Fill(deltaPhi(met_phi, l1_phi), weight*150)
    dilep_dPhi_metL2.Fill(deltaPhi(met_phi, l2_phi), weight*150)


    
dilep_mt2ll.style         = styles.lineStyle( ROOT.kRed+1, width=2, errors=True )
quadlep_mt2ll.style       = styles.lineStyle( ROOT.kGreen+1, width=2, errors=True )

dilep_mt2ll.legendText        = texNameDilepTTZ
quadlep_mt2ll.legendText      = texNameQuadlepTTZ

dilep_met.style         = styles.lineStyle( ROOT.kRed+1, width=2, errors=True )
quadlep_met.style       = styles.lineStyle( ROOT.kGreen+1, width=2, errors=True )
quadlep_metOrig.style   = styles.lineStyle( ROOT.kBlue+1, width=2, errors=True )

dilep_met.legendText        = texNameDilepTTZ
Пример #18
0
def extra_observables(event, sample):

    G_2D = ROOT.TVector2(event.photon_pt * cos(event.photon_phi),
                         event.photon_pt * sin(event.photon_phi))
    n_G_2D = ROOT.TVector2(cos(event.photon_phi), sin(event.photon_phi))
    #G_3D        = ROOT.TVector2( event.photon_pt*cos(event.photon_phi), event.photon_pt*sin(event.photon_phi) )
    #n_G_3D      = ROOT.TVector2( cos(event.photon_phi), sin(event.photon_phi) )

    # me_x,y
    met_2D = ROOT.TVector2(event.met_pt * cos(event.met_phi),
                           event.met_pt * sin(event.met_phi))

    event.deltaPhi_ll = deltaPhi(event.lep_phi[0], event.lep_phi[1])

    ## get jets
    #jetVars     = ['eta','pt','phi','btagCSV','id']
    #jets        = filter( isAnalysisJet, [getObjDict(event, 'jet_', jetVars, i) for i in range(int(getVarValue(event, 'njet')))] )
    #jets.sort( key = lambda l:-l['pt'] )

    #bJets       = filter(lambda j: isBJet(j, tagger = 'CSVv2') and abs(j['eta'])<=2.4, jets )
    #nonBJets    = filter(lambda j: not ( isBJet(j, tagger = 'CSVv2') and abs(j['eta'])<=2.4 ), jets)

    ## take highest-pT b-jet, supplement by non-bjets if there are less than two
    #bj0, bj1 = (bJets+nonBJets)[:2]
    #bj0_3D = ROOT.TVector3( bj0['pt']*cos(bj0['phi']), bj0['pt']*sin(bj0['phi']), bj0['pt']*sinh(bj0['eta']) )
    #bj1_3D = ROOT.TVector3( bj1['pt']*cos(bj1['phi']), bj1['pt']*sin(bj1['phi']), bj1['pt']*sinh(bj1['eta']) )
    #bj0_2D = ROOT.TVector2( bj0_3D[0], bj0_3D[1] )
    #bj1_2D = ROOT.TVector2( bj1_3D[0], bj1_3D[1] )

    ## resolve pairing ambiguity of bjets to top candidates by maximising the
    #if (bj0_2D + l3_2D + met_2D).Mod2() > ( bj1_2D + l3_2D + met_2D).Mod2():
    #    blep, bhad        = bj0,    bj1
    #    blep_2D, bhad_2D  = bj0_2D, bj1_2D
    #    blep_3D, bhad_3D  = bj0_3D, bj1_3D
    #else:
    #    blep, bhad        = bj1,    bj0
    #    blep_2D, bhad_2D  = bj1_2D, bj0_2D
    #    blep_3D, bhad_3D  = bj1_3D, bj0_3D

    #event.blep_pt = blep['pt']

    ## ST observables
    #event.ST = l3_pt + event.met_pt  # traditional (1l SUS)
    #event.St = l3_pt + event.met_pt + event.blep_pt # scalar sum pt of the leptonic top candidate

    ## MT observables
    #event.mT = sqrt(  2*event.met_pt*l3_pt*(1 - cos(event.met_phi - l3_phi))) # transverse mass of leptonic W candidate
    #event.mt = sqrt(  2*event.met_pt*l3_pt*(1 - cos(event.met_phi - l3_phi)) \
    #                + 2*blep['pt']*l3_pt*(cosh(blep['eta'] - l3_eta)-cos(blep['phi'] - l3_phi))
    #                + 2*event.met_pt*blep['pt']*(1-cos(event.met_phi - blep['phi'])) ) # transverse mass of the leptonic top

    ## variables with 2D vectors
    #for fname, f in [\
    #    #[ 'dPhiZ',    lambda vec: ROOT.TVector2.DeltaPhi( vec, Z_2D )],
    #    [ 'absDPhiZ', lambda vec: abs(ROOT.TVector2.DeltaPhi( vec, Z_2D ))],
    #    [ 'projZ',    lambda vec: vec* n_Z_2D ],
    #    #[ 'dotZ',     lambda vec: vec.Dot( Z_2D )  )],
    #    [ 'projorthZ',lambda vec: vec*n_orth_Z_2D ],
    #    ]:
    #    for vname, v in [
    #        [ "met",          met_2D],
    #        [ "met_blep",     met_2D + blep_2D],
    #        [ "met_l3",       met_2D + l3_2D],
    #        [ "l3",           l3_2D],
    #        [ "blep",         blep_2D],
    #        [ "l3_blep",      l3_2D+blep_2D],
    #        [ "met_l3_blep",  l3_2D+blep_2D+met_2D],
    #        ]:
    #            #varname = "%s_%s"%( fname, vname )
    #            setattr( event, "%s_%s"%( fname, vname ), f(v) )

    ## variables with 3D vectors
    #for fname, f in [
    #    [ 'dRZ',    lambda vec: ROOT.TVector3.DeltaR( vec, Z_3D )],
    #    ]:
    #    for vname, v in [
    #        [ "l3",         l3_3D],
    #        [ "blep",       blep_3D],
    #        [ "l3_blep",    l3_3D+blep_3D],
    #        ]:
    #            #varname = "%s_%s"%( fname, vname )
    #            setattr( event, "%s_%s"%( fname, vname ), f(v) )
    return
Пример #19
0
def extra_observables( event, sample ):

    G = {'pt':event.photon_pt, 'eta':event.photon_eta, 'phi':event.photon_phi}
    G_2D        = ROOT.TVector2( event.photon_pt*cos(event.photon_phi), event.photon_pt*sin(event.photon_phi) )
    n_G_2D      = ROOT.TVector2( cos(event.photon_phi), sin(event.photon_phi) )
    #G_3D        = ROOT.TVector2( event.photon_pt*cos(event.photon_phi), event.photon_pt*sin(event.photon_phi) )
    #n_G_3D      = ROOT.TVector2( cos(event.photon_phi), sin(event.photon_phi) )

    # me_x,y
    met_2D = ROOT.TVector2( event.met_pt*cos(event.met_phi), event.met_pt*sin(event.met_phi) )
    event.deltaPhi_G_MET = deltaPhi( G['phi'], event.met_phi ) 

    event.deltaPhi_ll = deltaPhi(event.lep_phi[0],  event.lep_phi[1])
    event.deltaR_ll   = deltaR({'phi':event.lep_phi[0], 'eta':event.lep_eta[0]},  {'phi':event.lep_phi[1], 'eta':event.lep_eta[1]})

    ## get jets
    jetVars     = ['eta','pt','phi','btagCSV','id']
    jets        = filter( isAnalysisJet, [getObjDict(event, 'jet_', jetVars, i) for i in range(int(getVarValue(event, 'njet')))] )
    jets.sort( key = lambda l:-l['pt'] )

    bJets       = filter(lambda j: isBJet(j, tagger = 'CSVv2') and abs(j['eta'])<=2.4, jets )
    nonBJets    = filter(lambda j: not ( isBJet(j, tagger = 'CSVv2') and abs(j['eta'])<=2.4 ), jets)

    # take highest-pT b-jet, supplement by non-bjets if there are less than two
    bj1, bj2 = (bJets+nonBJets)[:2]
    l_bj1 = ROOT.TLorentzVector()
    l_bj1.SetPtEtaPhiM( bj1['pt'], bj1['eta'], bj1['phi'], 0 )
    l_bj2 = ROOT.TLorentzVector()
    l_bj2.SetPtEtaPhiM( bj2['pt'], bj2['eta'], bj2['phi'], 0 )

    # leptons
    l_lep1 = ROOT.TLorentzVector() 
    l_lep1.SetPtEtaPhiM( event.lep_pt[0], event.lep_eta[0], event.lep_phi[0], 0 )
    lep1 = {'pt':event.lep_pt[0], 'eta':event.lep_eta[0], 'phi':event.lep_phi[0]}
    l_lep2 = ROOT.TLorentzVector() 
    l_lep2.SetPtEtaPhiM( event.lep_pt[1], event.lep_eta[1], event.lep_phi[1], 0 )
    lep2 = {'pt':event.lep_pt[1], 'eta':event.lep_eta[1], 'phi':event.lep_phi[1]}

    # resolve pairing ambiguity
    max1 = max([(l_lep1 + l_bj1).M(), (l_lep2 + l_bj2).M()])
    max2 = max([(l_lep1 + l_bj2).M(), (l_lep2 + l_bj1).M()])
    if max1<max2: #Choose pairing with smaller invariant mass
        pass 
    else:
        # switch
        bj1, bj2     = bj2, bj1 
        l_bj1, l_bj2 = l_bj2, l_bj1

    event.M_lb_max = max(max1, max2)
    event.M_lb_min = min(max1, max2)

    # G & leps
    dPhi_G_l1 = deltaPhi( G['phi'], lep1['phi'] ) 
    dPhi_G_l2 = deltaPhi( G['phi'], lep2['phi'] ) 
    event.dPhi_G_l_max = max(dPhi_G_l1, dPhi_G_l2)
    event.dPhi_G_l_min = min(dPhi_G_l1, dPhi_G_l2)
    dR_G_l1 = deltaR( G, lep1 ) 
    dR_G_l2 = deltaR( G, lep2 ) 
    event.dR_G_l_max = max(dR_G_l1, dR_G_l2)
    event.dR_G_l_min = min(dR_G_l1, dR_G_l2)

    return