Beispiel #1
0
        def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric):
            for ij, j in enumerate(jetcoll):
                for iq, q in enumerate(quarkcoll):

                    # Set to 1 for bs from hadronic top
                    # Set to 0 for bs from hadronic top
                    # Set to -1 for other stuff
                    if label == "tb":
                        if q.from_had_t == 1:
                            numeric_b_from_had_t = 1
                        elif q.from_had_t == 0:
                            numeric_b_from_had_t = 0
                        else:
                            numeric_b_from_had_t = -1
                    else:
                        numeric_b_from_had_t = -1

                    #find DeltaR between jet and quark
                    l1 = lvec(q)
                    l2 = lvec(j)
                    dr = l1.DeltaR(l2)
                    if dr < 0.3:
                        #Jet already had a match: take the one with smaller dR
                        if not matched_pairs.has_key(ij):
                            matched_pairs[ij] = []
                        matched_pairs[ij] += [(label, iq, dr, label_numeric,
                                               numeric_b_from_had_t)]
Beispiel #2
0
        def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric):
            for ij, j in enumerate(jetcoll):        
                for iq, q in enumerate(quarkcoll):

                    # Set to 1 for bs from hadronic top
                    # Set to 0 for bs from hadronic top
                    # Set to -1 for other stuff
                    if label == "tb":
                        if q.from_had_t == 1:
                            numeric_b_from_had_t = 1
                        elif q.from_had_t == 0:
                            numeric_b_from_had_t = 0
                        else:
                            numeric_b_from_had_t = -1
                    else:
                        numeric_b_from_had_t = -1

                    #find DeltaR between jet and quark
                    l1 = lvec(q)
                    l2 = lvec(j)
                    dr = l1.DeltaR(l2)
                    if dr < 0.3:
                        #Jet already had a match: take the one with smaller dR
                        if matched_pairs.has_key(ij):
                            if matched_pairs[ij][1] > dr:
                                matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t)
                        else:
                            matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t)
    def _process(self, event):

        if "debug" in self.conf.general["verbosity"]:
            autolog("CommonClassifierAnalyzer started")
        
        selectedLeptonP4 = CvectorTLorentzVector()
        selectedLeptonCharge = Cvectordouble()

        selectedJetsP4 = CvectorTLorentzVector()
        selectedJetsCSV = Cvectordouble()
        looseJetsP4 = CvectorTLorentzVector()
        looseJetsCSV = Cvectordouble()

        for lep in event.good_leptons:
            selectedLeptonP4.push_back(lvec(lep))
            selectedLeptonCharge.push_back(lep.charge)

        for jet in event.good_jets:
            selectedJetsP4.push_back(lvec(jet))
            selectedJetsCSV.push_back(jet.btagCSV)
            looseJetsP4.push_back(lvec(jet))
            looseJetsCSV.push_back(jet.btagCSV)

        for jet in event.loose_jets:
            looseJetsP4.push_back(lvec(jet))
            looseJetsCSV.push_back(jet.btagCSV)

        metP4s = CvectorTLorentzVector()
        met_p4 = ROOT.TLorentzVector()
        met_p4.SetPtEtaPhiM(event.MET.pt, 0, event.MET.phi, 0)
        metP4s.push_back(met_p4)

        event.common_mem = [ROOT.MEMResult()]
        event.common_bdt = -2.0
        event.common_bdt_withmem1 = -2.0
        event.common_bdt_withmem2 = -2.0
        
        if event.category_string.startswith("sl_"):
            event.common_bdt = self.bdtcalc_sl.GetBDTOutput(selectedLeptonP4, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4)
            if hasattr(event, "mem_results_tth"):
                mem_p_sig = event.mem_results_tth[self.conf.mem["methodOrder"].index("SL_0w2h2t")]
                mem_p_bkg = event.mem_results_ttbb[self.conf.mem["methodOrder"].index("SL_0w2h2t")]
                event.common_bdt_withmem1 = self.bdtcalc_sl_mem1.GetBDTOutput(
                    selectedLeptonP4, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4,
                    mem_p_sig.p/(mem_p_sig.p + 0.15 * mem_p_bkg.p)
                )
                event.common_bdt_withmem2 = self.bdtcalc_sl_mem2.GetBDTOutput(
                    selectedLeptonP4, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4,
                    mem_p_sig.p, mem_p_bkg.p
                )
                #FIXME
                #mem = self.memcalc.GetOutput(selectedLeptonP4, selectedLeptonCharge, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4)
                #event.common_mem = [mem]
        if event.category_string.startswith("dl_"):
            bdt = self.bdtcalc_dl.GetBDTOutput(selectedLeptonP4, selectedLeptonCharge, selectedJetsP4, selectedJetsCSV, met_p4)
            event.common_bdt = bdt
        if "debug" in self.conf.general["verbosity"]:
            print "bdt", event.category_string, event.common_bdt
        return event
Beispiel #4
0
 def pair_mass(self, j1, j2):
     """
     Calculates the invariant mass of a two-particle system.
     """
     lv1, lv2 = [lvec(j) for j in [j1, j2]]
     tot = lv1 + lv2
     return tot.M()
Beispiel #5
0
    def calcFoxWolfram(objects, orders, weight_func):
        """
        http://arxiv.org/pdf/1212.4436v1.pdf
        """
        lvecs = [lvec(o) for o in objects]

        h = np.zeros(len(orders))
        for i in range(len(lvecs)):
            for j in range(len(lvecs)):
                cos_omega_ij = (lvecs[i].CosTheta() * lvecs[j].CosTheta() +
                    math.sqrt((1.0 - lvecs[i].CosTheta()**2) * (1.0 - lvecs[j].CosTheta()**2)) *
                    (math.cos(lvecs[i].Phi() - lvecs[j].Phi()))
                )
                w_ij = weight_func(lvecs, lvecs[i], lvecs[j])
                vals = np.array([cos_omega_ij]*len(orders))

                p_l = np.array(eval_legendre(orders, vals))
                h += w_ij * p_l
        return h
Beispiel #6
0
    def _process(self, event):

        if "debug" in self.conf.general["verbosity"]:
            autolog("GenTTHAnalyzer started")
        
        event.nMatchSimB = 0
        event.nMatchSimC = 0
        lv_bs = map(lvec, event.GenBQuarkFromTop)
        for jet in event.good_jets:
            lv_j = lvec(jet)

            if (lv_j.Pt() > 20 and abs(lv_j.Eta()) < 2.5):
                if any([lv_b.DeltaR(lv_j) < 0.5 for lv_b in lv_bs]):
                    continue
                absid = abs(jet.mcFlavour)
                if absid == 5:
                    event.nMatchSimB += 1
                if absid == 4:
                    event.nMatchSimC += 1

        return event
Beispiel #7
0
    def _process(self, event):

        if "debug" in self.conf.general["verbosity"]:
            autolog("GenTTHAnalyzer started")

        #Get light quarks from W/Z
        event.l_quarks_w = event.GenWZQuark

        #Get b quarks from top
        event.b_quarks_t = event.GenBQuarkFromTop

        #Get b-quarks from H
        event.b_quarks_h = event.GenBQuarkFromH

        #Get leptonic top children
        #note that the tau lepton might be missing
        event.lep_top = event.GenLepFromTop
        event.nu_top = event.GenNuFromTop
        
        #cat_gen - a string specifying the ttbar decay mode
        event.cat_gen = None
        #cat_gen_n - a numerical value corresponding to the string
        event.cat_gen_n = -1

        #all leptonic and hadronic gen tops
        event.genTopLep = []
        event.genTopHad = []


        #Only run top algos
        if len(event.GenTop) == 2:
        
            #Gen tops might be in random order
            gt1 = event.GenTop[0]
            gt2 = event.GenTop[1]
            dm1 = getattr(gt1, "decayMode", -1)
            dm2 = getattr(gt2, "decayMode", -1)
            #single-leptonic
            if ((dm1 == 0 and dm2==1) or (dm2==0 and dm1==1)):
                
                #First top is leptonic
                if dm1 == 0:
                    event.genTopLep = [gt1]
                    event.genTopHad = [gt2]
                #Second top is leptonic
                else:
                    event.genTopLep = [gt2]
                    event.genTopHad = [gt1]
                        
                event.cat_gen = "sl"
                event.cat_gen_n = 0
            elif (dm1 == 0 and dm2 == 0):
                event.cat_gen = "dl"
                event.cat_gen_n = 1
                event.genTopLep = [gt1, gt2]
                event.genTopHad = []
            elif (dm1 == 1 and dm2 == 1):
                event.cat_gen = "fh"
                event.cat_gen_n = 2
                event.genTopHad = [gt1, gt2]
                event.genTopLep = []
            else:
                event.genTopLep = []
                event.genTopHad = []

        #these are the quarks that would pass selection
        event.l_quarks_gen = []
        event.b_quarks_gen_t = []
        event.b_quarks_gen_h = []

        nq = 0
        #Find the light quarks from W that would pass jet selection
        #associate them with a transfer function
        for q in event.l_quarks_w:
            nq += 1
            if self.pass_jet_selection(q):
                q.btagFlag = 0.0
                q.tth_match_label = "wq"
                q.tth_match_index = nq
                attach_jet_transfer_function(q, self.conf)
                event.l_quarks_gen += [q]

        #Find the b quarks from top that would pass jet selection
        #associate them with a transfer function
        for q in event.b_quarks_t:
            nq += 1
            if self.pass_jet_selection(q):
                q.btagFlag = 1.0
                q.tth_match_label = "tb"
                q.tth_match_index = nq
                attach_jet_transfer_function(q, self.conf)
                event.b_quarks_gen_t += [q]

        #Find the b quarks from Higgs that would pass jet selection
        #associate them with a transfer function
        for q in event.b_quarks_h:
            nq += 1
            if self.pass_jet_selection(q):
                q.btagFlag = 1.0
                q.tth_match_label = "hb"
                q.tth_match_index = nq
                attach_jet_transfer_function(q, self.conf)
                event.b_quarks_gen_h += [q]
        
        #Number of reco jets matched to quarks from W, top, higgs
        event.nSelected_wq = len(event.l_quarks_gen)
        event.nSelected_tb = len(event.b_quarks_gen_t)
        event.nSelected_hb = len(event.b_quarks_gen_h)

        #Get the total MET from the neutrinos
        spx = 0
        spy = 0
        for nu in event.nu_top:
            p4 = lvec(nu)
            spx += p4.Px()
            spy += p4.Py()
        event.MET_tt = MET(px=spx, py=spy)

        #Get the total ttH visible pt at gen level
        spx = 0
        spy = 0
        for p in (event.l_quarks_w + event.b_quarks_t +
            event.b_quarks_h + event.lep_top):
            p4 = lvec(p)
            spx += p4.Px()
            spy += p4.Py()
        event.tth_px_gen = spx
        event.tth_py_gen = spy

        #Calculate tth recoil
        #rho = -met - tth_matched
        event.tth_rho_px_gen = -event.MET_gen.px - event.tth_px_gen
        event.tth_rho_py_gen = -event.MET_gen.py - event.tth_py_gen

        if "gen" in self.conf.general["verbosity"]:
            for j in event.l_quarks_w:
                autolog("gen q(W)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.b_quarks_t:
                autolog("gen b(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.lep_top:
                autolog("gen l(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.nu_top:
                autolog("gen n(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.b_quarks_h:
                autolog("gen b(h)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            autolog("gen cat", event.cat_gen, event.cat_gen_n)


        # In semi-leptonic events we need to figure out which top b is from
        if event.cat_gen == "sl":
                    
            # If b pdgId has same sign as hadronic top pdgId, it's the one
            if event.b_quarks_t[0].pdgId * event.genTopHad[0].pdgId > 0:
                event.b_quarks_t[0].from_had_t = 1
                event.b_quarks_t[1].from_had_t = 0
            else:
                event.b_quarks_t[0].from_had_t = 0
                event.b_quarks_t[1].from_had_t = 1

        # In Di leptonic events no b quarks come from hadronic top
        elif event.cat_gen == "dl":
            for b in event.b_quarks_t:
                b.from_had_t = 0
                            
        # In All hadronic events both b quarks come from hadronic top
        elif event.cat_gen == "fh":
            for b in event.b_quarks_t:
                b.from_had_t = 1
        else:
            for b in event.b_quarks_t:
                b.from_had_t = -1
            

        #Store for each jet, specified by it's index in the jet
        #vector, if it is matched to any gen-level quarks
        matched_pairs = {}

        def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric):
            for ij, j in enumerate(jetcoll):        
                for iq, q in enumerate(quarkcoll):

                    # Set to 1 for bs from hadronic top
                    # Set to 0 for bs from hadronic top
                    # Set to -1 for other stuff
                    if label == "tb":
                        if q.from_had_t == 1:
                            numeric_b_from_had_t = 1
                        elif q.from_had_t == 0:
                            numeric_b_from_had_t = 0
                        else:
                            numeric_b_from_had_t = -1
                    else:
                        numeric_b_from_had_t = -1

                    #find DeltaR between jet and quark
                    l1 = lvec(q)
                    l2 = lvec(j)
                    dr = l1.DeltaR(l2)
                    if dr < 0.3:
                        #Jet already had a match: take the one with smaller dR
                        if matched_pairs.has_key(ij):
                            if matched_pairs[ij][1] > dr:
                                matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t)
                        else:
                            matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t)

        #Find the best possible match for each individual jet
        match_jets_to_quarks(event.good_jets, event.l_quarks_gen, "wq", 0)
        match_jets_to_quarks(event.good_jets, event.b_quarks_gen_t, "tb", 1)
        match_jets_to_quarks(event.good_jets, event.b_quarks_gen_h, "hb", 2)

        #Number of reco jets matched to quarks from W, top, higgs
        event.nMatch_wq = 0
        event.nMatch_tb = 0
        event.nMatch_hb = 0
        #As above, but also required to be tagged/untagged for b/light respectively.
        event.nMatch_wq_btag = 0
        event.nMatch_tb_btag = 0
        event.nMatch_hb_btag = 0
        
        #Now check what each jet was matched to
        for ij, jet in enumerate(event.good_jets):

            jet.tth_match_label = None
            jet.tth_match_index = -1
            jet.tth_match_dr = -1
            jet.tth_match_label_numeric = -1

            #Jet did not have a match (no jet index in matched_pairs)
            if not matched_pairs.has_key(ij):
                continue #continue jet loop

            #mlabel - string label of quark collection, e.g. "wq"
            #midx - index of quark in vector that the jet was matched to
            #mdr - delta R between jet and matched quark
            #mlabel_num - numeric label of quark collection, e.g. 0
            #mlabel_num_bfromhadt - numeric label if the b is from hadronic top
            #                         -1 if not b or not from top
            #                          0 if from leptonic top
            #                          1 if from hadronic top
            mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matched_pairs[ij]

            jet.tth_match_label = mlabel
            jet.tth_match_index = midx
            jet.tth_match_dr = mdr
            jet.tth_match_label_numeric = mlabel_num
            jet.tth_match_label_bfromhadt = mlabel_num_bfromhadt
            
            if mlabel == "wq":
                event.nMatch_wq += 1

                #If this jet is considered to be un-tagged
                if jet.btagFlag == 0.0:
                    event.nMatch_wq_btag += 1
            elif mlabel == "tb":
                event.nMatch_tb += 1

                #If this jet is considered to be b-tagged
                if jet.btagFlag == 1.0:
                    event.nMatch_tb_btag += 1

            elif mlabel == "hb":
                event.nMatch_hb += 1
                if jet.btagFlag == 1.0:
                    event.nMatch_hb_btag += 1

        if "debug" in self.conf.general["verbosity"]:
            autolog("nSel {0}_{1}_{2} nMatch {3}_{4}_{5} nMatch_btag {6}_{7}_{8}".format(
                event.nSelected_wq,
                event.nSelected_tb,
                event.nSelected_hb,
                event.nMatch_wq,
                event.nMatch_tb,
                event.nMatch_hb,
                event.nMatch_wq_btag,
                event.nMatch_tb_btag,
                event.nMatch_hb_btag,
            ))
        
        if "matching" in self.conf.general["verbosity"]:
            matches = {"wq":event.l_quarks_w, "tb": event.b_quarks_t, "hb":event.b_quarks_h}

            for ij, jet in enumerate(event.good_jets):
                if not matched_pairs.has_key(ij):
                    continue
                mlabel, midx, mdr, mlabel_num = matched_pairs[ij]
                autolog("jet match", ij, mlabel, midx, mdr, jet.pt, matches[mlabel][midx].pt)

        #reco-level tth-matched system
        spx = 0.0
        spy = 0.0
        for jet in event.good_jets:
            if not (jet.tth_match_label is None):
                p4 = lvec(jet)
                spx += p4.Px()
                spy += p4.Py()
        for lep in event.good_leptons:
            p4 = lvec(lep)
            match = False
            for glep in event.lep_top:
                p4g = lvec(glep)
                if p4g.DeltaR(p4) < 0.3:
                    match = True
                    break
            if match:
                spx += p4.Px()
                spy += p4.Py()

        event.tth_px_reco = spx
        event.tth_py_reco = spy

        #Calculate tth recoil
        #rho = -met - tth_matched
        event.tth_rho_px_reco = -event.MET.px - event.tth_px_reco
        event.tth_rho_py_reco = -event.MET.py - event.tth_py_reco

        #print out gen-level quarks
        if "input" in self.conf.general["verbosity"]:
            print "gen Q"
            for q in event.l_quarks_gen:
                print q.pt, q.eta, q.phi, q.mass, q.pdgId
            print "gen B"
            for q in event.b_quarks_gen:
                print q.pt, q.eta, q.phi, q.mass, q.pdgId

        return event
Beispiel #8
0
    def _process(self, event):
        event.passes_subjet = True
        
        if "debug" in self.conf.general["verbosity"]:
            autolog("SubjetAnalyzer started")

        if "subjet" in self.conf.general["verbosity"]:
            print 'Printing from SubjetAnalyzer! iEv = {0}'.format(event.iEv)
            

        # Is set to True only after the event passed all criteria
        setattr( event, 'PassedSubjetAnalyzer', False )

        # Create two new lists for selected_btagged_jets and wquark_candidate_jets
        # Needs to be done here because the lists are needed in the mem config
        setattr( event, 'boosted_bjets', [] )
        setattr( event, 'boosted_ljets', [] )
        setattr( event, 'topCandidate', [] )
        setattr( event, 'topCandidatesSync', [] )
        setattr( event, 'othertopCandidate', [] )
        setattr( event, 'higgsCandidate', [] )
        setattr( event, 'higgsCandidateForSync', [] )

        event.n_bjets = len( event.selected_btagged_jets_high )
        event.n_ljets = len( list( event.wquark_candidate_jets ) )


        ########################################
        # Minimal event suitability:
        #  - Needs to be single leptonic
        #  - At least 1 httCandidate
        ########################################

        # Check if the event is single leptonic
        if not (event.is_sl or event.is_fh): #LC
            return event

        # Get the top candidates
        # ======================================

        # Keep track of number of httCandidates that passed the cut
        setattr( event, 'nhttCandidate', len( event.httCandidates ) )
        setattr( event, 'nhttCandidate_aftercuts', 0 )

        # Just run normal mem if there is no httCandidate present
        # Check if there is an httCandidate
        # if len( event.httCandidates ) == 0:
        #    return event


        # All HTT candidates for sync
        all_tops = []
        for candidate in event.httCandidates:
            all_tops.append( copy.deepcopy(candidate) )

        # Match the top to a fat jet
        #  - Copies bbtag and tau_N, calculates n_subjettiness
        #  - DOES NOT apply the n_subjettiness cut
        all_tops = self.Match_top_to_fatjet( event, all_tops, False )

        for top in all_tops:
            top.fj_index = event.FatjetCA15ungroomed.index(top.matched_fatjet)            
        
        # Sort by which ungroomed fj they are matched to
        all_tops = sorted(all_tops, key=lambda x: x.fj_index )        
                

        # Apply the cuts on the httCandidate
        tops = []
        for candidate in event.httCandidates:
            if self.Apply_Cut_criteria( candidate ):
                tops.append( copy.deepcopy(candidate) )


        # Match the top to a fat jet
        #  - Copies bbtag and tau_N, calculates n_subjettiness
        #  - Applies the n_subjettiness cut
        tops = self.Match_top_to_fatjet( event, tops, True )
        other_tops = []

        # Calculate delR with the lepton for all tops that survived the cut
        if event.is_sl: #LC
            for top in tops + all_tops:
                setattr( top, 'delR_lepton' ,
                          self.Get_DeltaR_two_objects( top, event.good_leptons[0] ) )
        else:
            for top in tops + all_tops:
                setattr( top, 'delR_lepton' , -1 )

        # Keep track of how many httCandidates passed
        event.nhttCandidate_aftercuts = len( tops )

        #Find the best hadronic gen top match for each top candidate
        if self.cfg_comp.isMC:
            gentops = getattr(event, "genTopHad", [])
            if len(gentops)>0:
                for topcandidate in tops:
                    lv1 = lvec(topcandidate)
                    drs = []
                    for igentop, gentop in enumerate(gentops):
                        lv2 = lvec(gentop)
                        drs += [(lv1.DeltaR(lv2), gentop, igentop)]
                    drs = sorted(drs, key=lambda x: x[0])
                    best = drs[0]
                    topcandidate.genTopHad_dr = best[0]
                    topcandidate.genTop = best[1]
                    topcandidate.genTopHad_index = best[2]

        # Just run normal mem if there is no httCandidate surviving the cuts
        # Check if any candidates survived the cutoff criteria

        # if len(tops) == 0:
        #     return event
        # If exactly 1 survived, simply continue with that candidate
        other_top_present = False
        top = None
        if len(tops) == 0:
            other_top_present = False
        elif len(tops) == 1:
            top = tops[0]
            other_top_present = False
        # If more than 1 candidate survived the cutoff criteria, choose the
        # one whose delR with the lepton was biggest
        else:
            if event.is_sl: #LC
                tops = sorted( tops, key=lambda x: -x.delR_lepton )
            else:
                tops = sorted( tops, key=lambda x: x.pt)
            other_top_present = True
            top = tops[0]
            other_tops = tops[1:]

        if "subjet" in self.conf.general["verbosity"]:
            print "Number of top candidates ", len(tops)

        # Get a Higgs candidate
        # ======================================

        #Types of fatjets to match to Higgs candidate
        fatjets_to_match = ["softdropz2b1", "softdrop", "pruned", "subjetfiltered"]
        extra_higgs_vars = ["mass", "nallsubjets", 
                            "sj1pt", "sj1eta", "sj1phi", "sj1mass", "sj1btag", 
                            "sj2pt", "sj2eta", "sj2phi", "sj2mass", "sj2btag", 
                            "sj3pt", "sj3eta", "sj3phi", "sj3mass", "sj3btag", 
                            "sj12mass"]
        
        # TODO: 
        # -add groomed n-subjettiness

        for fatjet_name in fatjets_to_match:
            self.Add_Higgs_Subjets_To_Fatjet(event, fatjet_name)

        higgs_present = False
        higgsCandidates = []
        for fatjet in event.FatjetCA15ungroomed:

            # Turned off for now. TODO: Revisit Higgs/Top overlap removal
            # # Choose only fatjets that were not HTTv2 candidates for the higgs reco
            # # Check if the fatjet is not already matched to the chosen top candidate
            # if top and hasattr(fatjet, 'matched_top') and fatjet == top.matched_fatjet:
            #    continue

            fatjet.n_subjettiness = -1
            if fatjet.tau1 > 0:
                fatjet.n_subjettiness = fatjet.tau2 / fatjet.tau1
            if top:
                fatjet.dr_top = self.Get_DeltaR_two_objects(fatjet, top)

            #set default extra variables for all fatjet types
            for fatjetkind in fatjets_to_match:
                for var in extra_higgs_vars:
                    setattr(fatjet, var + "_" + fatjetkind, -9999)
                    
            genhiggs = getattr(event, "GenHiggsBoson", [])

            #match higgs candidate to generated higgs
            if self.cfg_comp.isMC and len(genhiggs) >= 1:
                lv1 = lvec(fatjet)
                lv2 = lvec(genhiggs[0])
                fatjet.dr_genHiggs = lv1.DeltaR(lv2)

            higgsCandidates.append( fatjet )
            higgs_present = True

        # Sort by pT
        # TODO: for now. Revisit and change to subjet b-tag/bbtag we decide on
        higgsCandidates = sorted( higgsCandidates, key=lambda x: -x.pt )
        
        # Match higgs candidates to various fat jets
        for fatjetkind in fatjets_to_match:
            nmatch = self.Match_two_lists(
                higgsCandidates, 'higgs',
                getattr(event, "FatjetCA15" + fatjetkind), 'fatjet_' + fatjetkind,
                R_cut = self.R_cut_fatjets
            )

        # Add properties of the matched fatjet to the higgs candidate
        for higgsCandidate in higgsCandidates:
            for fatjetkind in fatjets_to_match:
                matchjet = getattr(higgsCandidate, "matched_fatjet_" + fatjetkind, None)
                if matchjet != None:
                    for var in extra_higgs_vars:                        
                        if hasattr(matchjet,var):
                            setattr(higgsCandidate, var + "_" + fatjetkind, getattr(matchjet,var))
                            
        ########################################
        # Get the lists of particles: quarks, jets and subjets
        ########################################

        # Get the subjets from the httCandidate
        #  - Also sets transfer functions as attributes
        #  - Returns subjets ordered by decreasing btag
        #  - First subjet has btagFlag==1.0, the other two btagFlag==0.0
        top_subjets = self.Get_Subjets( top )
        if "subjet" in self.conf.general["verbosity"]:
            print "subjets"
            for subjet in top_subjets:
                print subjet

        if other_top_present:
            for top in other_tops: self.Get_Subjets( top )

        # Set 'PDGID' to 1 for light, and to 5 for b
        for subjet in top_subjets:
            if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 )
            if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 )

        # Create two new lists for btagged_jets and wquark_candidate_jets in the
        # original events
        if event.is_sl: #LC
            reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high )
            reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) )
        else: #LC
            reco_ltagged_jets = event.buntagged_jets_bdisc
            reco_btagged_jets = event.btagged_jets_bdisc

        if len(tops) > 0:
            top_subjets = self.Get_Subjets( top )
            if "subjet" in self.conf.general["verbosity"]:
                print "subjets"
                for subjet in top_subjets:
                    print subjet

            if other_top_present:
                for top in other_tops: self.Get_Subjets( top )

            # Set 'PDGID' to 1 for light, and to 5 for b
            # FIXME: do not use PDGID currently, as it ONLY works with the HEPTopTagger perm pruning strat
            #for subjet in top_subjets:
            #    if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 )
            #    if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 )

            # Create two new lists for btagged_jets and wquark_candidate_jets in the
            # original events
            reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high )
            reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) )

            for jet in reco_btagged_jets:
                setattr( jet, 'btag', getattr(jet,self.btagAlgo) )
                setattr( jet, 'btagFlag', 1.0 )
                #setattr( jet, 'PDGID', 0 )

            for jet in reco_ltagged_jets:
                setattr( jet, 'btag', getattr(jet,self.btagAlgo) )
                setattr( jet, 'btagFlag', 0.0 )
                #setattr( jet, 'PDGID', 0 )


            ########################################
            # Matching
            ########################################

            # Whenever a subjet has a 'match' (dR < dR_cut), the matched object should
            # excluded from the event

            # Match subjet to a bjet
            n_excluded_bjets = self.Match_two_lists(
                top_subjets, 'top_subjet',
                reco_btagged_jets, 'bjet' )

            # Match subjet to a ljet
            n_excluded_ljets = self.Match_two_lists(
                top_subjets , 'top_subjet',
                reco_ltagged_jets, 'ljet' )
            if "subjet" in self.conf.general["verbosity"]:
                print "subjet nMatchB={0} nMatchL={1}".format(n_excluded_bjets, n_excluded_ljets)


#FIXME: Unify this for SL/DL/FH
#from FH branch
#                # Stop adding after 4 b-jets
#                if event.is_sl:#LC
#                    if len(boosted_bjets) == 4: break
#            event.PassedSubjetAnalyzer = True
#
#            if event.is_fh: #LC: also add other light jets
#                for ljet in reco_ltagged_jets:
#                    # Check if the l-jet is not excluded
#                    if not hasattr( ljet, 'matched_top_subjet' ):
#                        boosted_ljets.append( ljet )
#
#                
#            
#
#        # If too many events are excluded, just run the default hypothesis
#        else:
#            if "subjet" in self.conf.general["verbosity"]:
#                print "[SubjetAnalyzer] subjet has too many overlaps, using reco"
#            boosted_bjets = reco_btagged_jets
#            boosted_ljets = reco_ltagged_jets
#            event.PassedSubjetAnalyzer = False
#======= end from FH branch
            # In case of double matching, choose the match with lowest delR
            # (This is not expected to happen often)
            for subjet in top_subjets:
                if hasattr( subjet, 'matched_bjet' ) and \
                    hasattr( subjet, 'matched_ljet' ) :
                    print '[SubjetAnalyzer] Double match detected'
                    if subjet.matched_bjet_delR < subjet.matched_ljet_delR:
                        del subjet.matched_ljet
                        del subjet.matched_ljet_delR
                        n_excluded_bjets -= 1
                    else:
                        del subjet.matched_bjet
                        del subjet.matched_bjet_delR
                        n_excluded_ljets -= 1


            ########################################
            # Modifying the bjets and ljets lists
            ########################################

            boosted_bjets = []
            boosted_ljets = []

            if n_excluded_bjets <= 1:
                if "subjet" in self.conf.general["verbosity"]:
                    print "subjet replacing"
                # Add the subjets to the final output lists first
                for subjet in top_subjets:
                    if subjet.btagFlag == 1.0: boosted_bjets.append( subjet )
                    if subjet.btagFlag == 0.0: boosted_ljets.append( subjet )

                # Sort tl btagged jets by decreasing btag (to be sure, but should 
                # already be done in previous analyzer)
                # Only resolved b-jets
                reco_btagged_jets = sorted( reco_btagged_jets, key=lambda x: -x.btag )

                # Add up to 4 reco btagged jets to the output lists
                for bjet in reco_btagged_jets:
                    # Check if the b-jet is not excluded
                    if not hasattr( bjet, 'matched_top_subjet' ):
                        boosted_bjets.append( bjet )

                    # Stop adding after 4 b-jets
                    if len(boosted_bjets) == 4: break
                event.PassedSubjetAnalyzer = True

            # If too many events are excluded, just run the default hypothesis
            else:
                if "subjet" in self.conf.general["verbosity"]:
                    print "[SubjetAnalyzer] subjet has too many overlaps, using reco"
                boosted_bjets = reco_btagged_jets
                boosted_ljets = reco_ltagged_jets
                event.PassedSubjetAnalyzer = False

     


        ########################################
        # Write to event
        ########################################

        # Store output lists in event
        event.higgsCandidate = higgsCandidates

        all_tops_to_add = []

        # Add top matched to leading fatjet OR dummy
        for top in all_tops:
            if top.fj_index == 0:
                all_tops_to_add.append(top)
                break
        if len(all_tops_to_add) == 0:
            all_tops_to_add.append(DummyTop())

        # Add top matched to sub-leading fatjet OR dummy
        for top in all_tops:
            if top.fj_index == 1:
                all_tops_to_add.append( top)
                break
        if len(all_tops_to_add) == 1:
            all_tops_to_add.append(DummyTop())
        
        
        event.topCandidatesSync = all_tops_to_add

        if len(tops)>0:
            event.topCandidate = [ top ]
            event.othertopCandidate = other_tops
            event.boosted_bjets = boosted_bjets
            event.boosted_ljets = boosted_ljets

            event.n_boosted_bjets = len( boosted_bjets )
            event.n_boosted_ljets = len( boosted_ljets )

            event.n_excluded_bjets = n_excluded_bjets
            event.n_excluded_ljets = n_excluded_ljets

        #pdb.set_trace()

        if "subjet" in self.conf.general["verbosity"]:
            print '[SubjetAnalyzer] Exiting SubjetAnalyzer! event.PassedSubjetAnalyzer = {0}'.format(
                event.PassedSubjetAnalyzer
            )


        ########################################
        # Matching to Gen top
        ###########################################

        event.n_matched_TTgentop = -1
        event.matched_TTgentop_pt = -1
        event.n_matched_TTgenb = -1
        event.n_matched_TTgenW = -1

        if len(tops)>0:
            self.Do_GenTop_Matching(event)

        return event 

        ########################################
        # Quark Matching
        ########################################

        # This section is only useful for truth-level comparison, and can be turned
        # off if this is not needed.
        # Do_Quark_Matching( event ) sets number of matches with quarks as branches
        # in the event, but these branches do not have to be filled (they will be
        # automatically set to -1 in the final output root file).

       
        self.Do_Quark_Matching( event )
Beispiel #9
0
    def _process(self, event):
        #FIXME: NEED COMMENTS HERE
        sumP2 = 0.0
        sumPxx = 0.0
        sumPxy = 0.0
        sumPxz = 0.0
        sumPyy = 0.0
        sumPyz = 0.0
        sumPzz = 0.0
        vecs = CvectorTLorentzVector()
        for jet in event.good_jets:
            obj = lvec(jet)
            vecs.push_back(lvec(jet))
            sumP2  += obj.P() * obj.P()
            sumPxx += obj.Px() * obj.Px()
            sumPxy += obj.Px() * obj.Py()
            sumPxz += obj.Px() * obj.Pz()
            sumPyy += obj.Py() * obj.Py()
            sumPyz += obj.Py() * obj.Pz()
            sumPzz += obj.Pz() * obj.Pz()
        evshape = EventShapeVariables(vecs)
        eigs = evshape.compEigenValues(2.0) #difference: this takes T^2-x^2-y^2-z^2 for P2
        event.momentum_eig0 = eigs[0]
        event.momentum_eig1 = eigs[1]
        event.momentum_eig2 = eigs[2]
        
        ##---- compute sphericity --------------------#DS
        Txx = sumPxx/sumP2
        Tyy = sumPyy/sumP2
        Tzz = sumPzz/sumP2
        Txy = sumPxy/sumP2
        Txz = sumPxz/sumP2
        Tyz = sumPyz/sumP2
        T = TMatrixDSym(3)
        T[0,0] = Txx
        T[0,1] = Txy
        T[0,2] = Txz
        T[1,0] = Txy
        T[1,1] = Tyy
        T[1,2] = Tyz
        T[2,0] = Txz
        T[2,1] = Tyz
        T[2,2] = Tzz
        TEigen = TMatrixDSymEigen(T)
        eigenValues = TEigen.GetEigenValues()
        event.sphericity = 1.5*(eigenValues(1)+eigenValues(2))
        event.aplanarity = 1.5*eigenValues(2)
        event.C = 3.0*(eigenValues(0)*eigenValues(1) + eigenValues(0)*eigenValues(2) + eigenValues(1)*eigenValues(2))
        event.D = 27.*eigenValues(0)*eigenValues(1)*eigenValues(2) #---------DS 

        event.isotropy = evshape.isotropy()
        event.sphericity = 1.5*(eigs[1]+eigs[2]) #evshape.sphericity(eigs) #DS
        event.aplanarity = 1.5*eigs[2] #evshape.aplanarity(eigs) #DS
        event.C = 3.0*(eigs[0]*eigs[1] + eigs[0]*eigs[2] + eigs[1]*eigs[2]) #evshape.C(eigs) #DS
        event.D = 27.*eigs[0]*eigs[1]*eigs[2] #evshape.D(eigs) #DS

        event.mean_bdisc = np.mean([j.btagCSV for j in event.good_jets])
        event.mean_bdisc_btag = np.mean([j.btagCSV for j in event.selected_btagged_jets])
        event.std_bdisc = np.std([j.btagCSV for j in event.good_jets])
        event.std_bdisc_btag = np.std([j.btagCSV for j in event.selected_btagged_jets])
        drs = []
        for j1 in event.selected_btagged_jets:
            for j2 in event.selected_btagged_jets:
                if j1==j2:
                    continue
                l1 = lvec(j1)
                l2 = lvec(j2)
                drs += [(l1.DeltaR(l2), l1, l2)]
        drs = sorted(drs, key=lambda x: x[0])
        if len(drs)>0:
            lv = drs[0][1] + drs[0][2]
            event.mass_drpair_btag = lv.M()
            event.eta_drpair_btag = abs(lv.Eta())
            event.pt_drpair_btag = lv.Pt()
            event.min_dr_btag = drs[0][0]
            event.mean_dr_btag = np.mean([dr[0] for dr in drs], -1)
            event.std_dr_btag = np.std([dr[0] for dr in drs], -1)
        else:
            event.min_dr_btag = -1.0
            event.mean_dr_btag = -1.0
            event.std_dr_btag = -1.0
            event.mass_drpair_btag = -1.0
            event.eta_drpair_btag = -99
            event.pt_drpair_btag = -1.0

        for i in range(min(4, len(event.selected_btagged_jets_high))):
            setattr(event, "jet_btag_{0}".format(i), event.selected_btagged_jets_high[i])

        event.ht = np.sum([j.pt for j in event.good_jets])
        lvecs = [lvec(x) for x in event.good_jets + event.good_leptons]
        event.centrality = np.sum([l.Pt() / l.E() for l in lvecs])

        #orders of momenta to calculate
        orders = np.array([0, 1, 2, 3, 4, 5, 6, 7])
        event.fw_h_alljets = FoxWolfram.calcFoxWolfram(event.good_jets, orders, FoxWolfram.w_s)
        event.fw_h_btagjets = FoxWolfram.calcFoxWolfram(event.selected_btagged_jets_high, orders, FoxWolfram.w_s)
        event.fw_h_untagjets = FoxWolfram.calcFoxWolfram(event.buntagged_jets, orders, FoxWolfram.w_s)
        
        for ij in range(6):
            setattr(event, "jet{0}_pt".format(ij), 0)
            setattr(event, "jet{0}_aeta".format(ij), 0)
            setattr(event, "jet{0}_btag".format(ij), 0)

        for ij, jet in enumerate(event.good_jets):
            setattr(event, "jet{0}_pt".format(ij), jet.pt)
            setattr(event, "jet{0}_aeta".format(ij), abs(jet.eta))
            setattr(event, "jet{0}_btag".format(ij), jet.btagCSV)
       
        for i in range(2):
            setattr(event, "lep{0}_pt".format(i), 0.0)
            setattr(event, "lep{0}_aeta".format(i), 0.0)

        for ij, lep in enumerate(event.good_leptons):
            setattr(event, "lep{0}_pt".format(ij), lep.pt)
            setattr(event, "lep{0}_aeta".format(ij), abs(lep.eta))
        
        for io in orders:
            setattr(event, "fw_h{0}".format(io), event.fw_h_alljets[io])
        
        vararray = np.array([getattr(event, vname) for vname in self.conf.tth_mva["varlist"]])
        vararray[np.isnan(vararray)] = 0
        
        event.tth_mva = 0
        if mva_enabled:
            event.tth_mva = self.cls.predict_proba(vararray)[0,1]
        event.passes_mva = True

        return event
Beispiel #10
0
    def process(self, event):

        event.mu = filter(
            lambda x: abs(x.pdgId) == 13,
            event.selLeptons,
        )
        if "debug" in self.conf.general["verbosity"]:
            autolog("input muons: ", len(event.mu))
            for it in event.mu:
                (self.conf.leptons["mu"]["debug"])(it)

        event.el = filter(
            lambda x: abs(x.pdgId) == 11,
            event.selLeptons,
        )
        if "debug" in self.conf.general["verbosity"]:
            autolog("input electrons: ", len(event.el))
            for it in event.el:
                (self.conf.leptons["el"]["debug"])(it)

        for id_type in ["SL", "DL", "veto"]:
            sumleps = []
            for lep_flavour in ["mu", "el"]:
                lepcuts = self.conf.leptons[lep_flavour][id_type]
                incoll = getattr(event, lep_flavour)
                isotype = self.conf.leptons[lep_flavour]["isotype"]
                isocut = lepcuts.get("iso", 99)
                if "debug" in self.conf.general["verbosity"]:
                    autolog("input collection", id_type, lep_flavour)
                    for lep in incoll:
                        autolog(lep.pt, lep.eta, lep.pdgId)

                leps = filter(
                    lambda x, lepcuts=lepcuts: (
                        x.pt > lepcuts.get(
                            "pt", 0)  #pt cut may be optional in case of DL
                        and abs(x.eta) < lepcuts["eta"]),
                    incoll)
                if "debug" in self.conf.general["verbosity"]:
                    autolog("after eta")
                    for lep in leps:
                        autolog(lep.pt, lep.eta, lep.pdgId)

                #Apply isolation cut
                if isotype != "none":
                    leps = filter(lambda x, isotype=isotype, isocut=isocut:
                                  abs(getattr(x, isotype)) < isocut,
                                  leps)
                if "debug" in self.conf.general["verbosity"]:
                    autolog("after iso", isotype)
                    for lep in leps:
                        autolog(lep.pt, lep.eta, lep.pdgId)
                #Apply ID cut
                leps = filter(lepcuts["idcut"], leps)
                if "debug" in self.conf.general["verbosity"]:
                    autolog("after id")
                    for lep in leps:
                        autolog(lep.pt, lep.eta, lep.pdgId)

                sumleps += leps
                lepname = lep_flavour + "_" + id_type
                setattr(event, lepname, leps)
                setattr(event, "n_" + lepname, len(leps))
            #end of lep_flavour loop
            setattr(event, "lep_{0}".format(id_type), sumleps)
            setattr(event, "n_lep_{0}".format(id_type), len(sumleps))
        #end of id_type loop

        event.lep_SL = sorted(event.lep_SL, key=lambda x: x.pt, reverse=True)
        event.lep_DL = sorted(event.lep_DL, key=lambda x: x.pt, reverse=True)
        event.lep_veto = sorted(event.lep_veto,
                                key=lambda x: x.pt,
                                reverse=True)

        #Apply two-stage pt cut on DL leptons
        lep_DL_afterpt = []
        for lep in event.lep_DL:
            if len(lep_DL_afterpt) == 0:
                ptcut = self.conf.leptons["DL"]["pt_leading"]
            else:
                ptcut = self.conf.leptons["DL"]["pt_subleading"]
            if lep.pt > ptcut:
                lep_DL_afterpt += [lep]
        event.lep_DL = lep_DL_afterpt
        event.n_lep_DL = len(event.lep_DL)

        if "debug" in self.conf.general["verbosity"]:
            for lep in event.lep_SL + event.lep_DL + event.lep_veto:
                if lep in event.mu:
                    f = self.conf.leptons["mu"]["debug"]
                elif lep in event.el:
                    f = self.conf.leptons["el"]["debug"]
                else:
                    f = lambda x: x
                prefix = ""
                if lep in event.lep_SL:
                    prefix += "SL "
                if lep in event.lep_DL:
                    prefix += "DL "
                if lep in event.lep_DL:
                    prefix += "veto "
                autolog(prefix)
                f(lep)
            autolog("n_lep_tight={0}, n_lep_loose={1}, n_lep_tight_veto={2}".
                    format(event.n_lep_SL, event.n_lep_DL, event.n_lep_veto))

        event.is_sl = (event.n_lep_SL == 1 and event.n_lep_veto == 1)
        event.is_dl = (event.n_lep_DL == 2 and event.n_lep_veto == 2)
        event.is_fh = (not event.is_sl and not event.is_dl)
        if "debug" in self.conf.general["verbosity"]:
            autolog("is_sl, is_dl, is_fh", event.is_sl, event.is_dl,
                    event.is_fh)

        #Calculate di-lepton system momentum
        event.dilepton_p4 = ROOT.TLorentzVector()
        if event.is_sl:
            event.good_leptons = event.lep_SL
            event.veto_leptons = event.lep_veto
        elif event.is_dl:
            event.good_leptons = event.lep_DL
            event.veto_leptons = event.lep_veto
            for lv in [lvec(l) for l in event.good_leptons]:
                event.dilepton_p4 += lv
        elif event.is_fh:
            event.good_leptons = []
            event.veto_leptons = []

        event.good_leptons = sorted(event.good_leptons,
                                    key=lambda x: x.pt,
                                    reverse=True)
        event.veto_leptons = sorted(event.veto_leptons,
                                    key=lambda x: x.pt,
                                    reverse=True)

        #Match good signal leptons to gen-leptons
        if self.cfg_comp.isMC:
            from PhysicsTools.HeppyCore.utils.deltar import matchObjectCollection
            #matchObjectCollection(event.good_leptons, event.GenLepFromTop, 0.3)
        #apply configuration-dependent selection
        passes = self.conf.leptons["selection"](event)
        if "debug" in self.conf.general["verbosity"]:
            autolog("LeptonAnalyzer selection", passes)
        if event.is_sl and event.is_dl:
            autolog("The event (%s,%s,%s) is both sl and dl" %
                    (event.input.run, event.input.lumi, event.input.evt))
            autolog("SL mu")
            for lep in event.mu_SL:
                (self.conf.leptons["mu"]["debug"])(lep)
            autolog("DL mu")
            for lep in event.mu_DL:
                (self.conf.leptons["mu"]["debug"])(lep)

            autolog("SL el")
            for lep in event.el_SL:
                (self.conf.leptons["el"]["debug"])(lep)
            autolog("DL el")
            for lep in event.el_DL:
                (self.conf.leptons["el"]["debug"])(lep)

            autolog("veto mu")
            for lep in event.mu_veto:
                (self.conf.leptons["mu"]["debug"])(lep)
            autolog("veto el")
            for lep in event.mu_veto:
                (self.conf.leptons["el"]["debug"])(lep)
            passes = False
            autolog("WARNING: Overlapping event")

        return self.conf.general["passall"] or passes
Beispiel #11
0
    def process(self, event):

        event.mu = filter(
            lambda x: abs(x.pdgId) == 13,
            event.selLeptons,
        )
        if "debug" in self.conf.general["verbosity"]:
            autolog("input muons: ", len(event.mu))
            for it in event.mu:
                (self.conf.leptons["mu"]["debug"])(it)

        event.el = filter(
            lambda x: abs(x.pdgId) == 11,
            event.selLeptons,
        )
        if "debug" in self.conf.general["verbosity"]:
            autolog("input electrons: ", len(event.el))
            for it in event.el:
                (self.conf.leptons["el"]["debug"])(it)

        for id_type in ["SL", "DL", "veto"]:
            sumleps = []
            for lep_flavour in ["mu", "el"]:
                lepcuts = self.conf.leptons[lep_flavour][id_type]
                incoll = getattr(event, lep_flavour)
                isotype = self.conf.leptons[lep_flavour]["isotype"]
                isocut = lepcuts.get("iso", 99)
                if "debug" in self.conf.general["verbosity"]:
                    autolog("input collection", id_type, lep_flavour)
                    for lep in incoll:
                        autolog(lep.pt, lep.eta, lep.pdgId)

                leps = filter(
                    lambda x, lepcuts=lepcuts: (
                        x.pt > lepcuts.get("pt", 0) #pt cut may be optional in case of DL
                        and abs(x.eta) < lepcuts["eta"]
                    ), incoll
                )
                if "debug" in self.conf.general["verbosity"]:
                    autolog("after eta")
                    for lep in leps:
                        autolog(lep.pt, lep.eta, lep.pdgId)

                #Apply isolation cut
                if isotype != "none":
                    leps = filter(
                        lambda x, isotype=isotype, isocut=isocut: abs(getattr(x, isotype)) < isocut, leps
                    )
                if "debug" in self.conf.general["verbosity"]:
                    autolog("after iso", isotype)
                    for lep in leps:
                        autolog(lep.pt, lep.eta, lep.pdgId)
                #Apply ID cut 
                leps = filter(lepcuts["idcut"], leps)
                if "debug" in self.conf.general["verbosity"]:
                    autolog("after id")
                    for lep in leps:
                        autolog(lep.pt, lep.eta, lep.pdgId)

                sumleps += leps
                lepname = lep_flavour + "_" + id_type
                setattr(event, lepname, leps)
                setattr(event, "n_"+  lepname, len(leps))
            #end of lep_flavour loop
            setattr(event, "lep_{0}".format(id_type), sumleps)
            setattr(event, "n_lep_{0}".format(id_type), len(sumleps))
        #end of id_type loop

        event.lep_SL = sorted(event.lep_SL, key=lambda x: x.pt, reverse=True)
        event.lep_DL = sorted(event.lep_DL, key=lambda x: x.pt, reverse=True)
        event.lep_veto = sorted(event.lep_veto, key=lambda x: x.pt, reverse=True)

        #Apply two-stage pt cut on DL leptons
        lep_DL_afterpt = []
        for lep in event.lep_DL:
            if len(lep_DL_afterpt) == 0:
                ptcut = self.conf.leptons["DL"]["pt_leading"]
            else: 
                ptcut = self.conf.leptons["DL"]["pt_subleading"]
            if lep.pt > ptcut:
                lep_DL_afterpt += [lep]
        event.lep_DL = lep_DL_afterpt
        event.n_lep_DL = len(event.lep_DL)

        if "debug" in self.conf.general["verbosity"]:
            for lep in event.lep_SL + event.lep_DL + event.lep_veto:
                if lep in event.mu:
                    f = self.conf.leptons["mu"]["debug"]
                elif lep in event.el:
                    f = self.conf.leptons["el"]["debug"]
                else:
                    f = lambda x: x
                prefix = ""
                if lep in event.lep_SL:
                    prefix += "SL "
                if lep in event.lep_DL:
                    prefix += "DL "
                if lep in event.lep_DL:
                    prefix += "veto "
                autolog(prefix)
                f(lep)
            autolog("n_lep_tight={0}, n_lep_loose={1}, n_lep_tight_veto={2}".format(
                event.n_lep_SL, event.n_lep_DL, event.n_lep_veto)
            )

        event.is_sl = (event.n_lep_SL == 1 and event.n_lep_veto == 1)
        event.is_dl = (event.n_lep_DL == 2 and event.n_lep_veto == 2)
        event.is_fh = (not event.is_sl and not event.is_dl)
        if "debug" in self.conf.general["verbosity"]:
            autolog("is_sl, is_dl, is_fh", event.is_sl, event.is_dl, event.is_fh)
        
        #Calculate di-lepton system momentum
        event.dilepton_p4 = ROOT.TLorentzVector()
        if event.is_sl:
            event.good_leptons = event.lep_SL
            event.veto_leptons = event.lep_veto
        elif event.is_dl:
            event.good_leptons =event.lep_DL
            event.veto_leptons = event.lep_veto
            for lv in [lvec(l) for l in event.good_leptons]:
                event.dilepton_p4 += lv
        elif event.is_fh:
            event.good_leptons = []
            event.veto_leptons = []
        
        event.good_leptons = sorted(event.good_leptons, key=lambda x: x.pt, reverse=True)
        event.veto_leptons = sorted(event.veto_leptons, key=lambda x: x.pt, reverse=True)
       
        #Match good signal leptons to gen-leptons 
        if self.cfg_comp.isMC:
            from PhysicsTools.HeppyCore.utils.deltar import matchObjectCollection
            #matchObjectCollection(event.good_leptons, event.GenLepFromTop, 0.3)
        #apply configuration-dependent selection
        passes = self.conf.leptons["selection"](event)
        if "debug" in self.conf.general["verbosity"]:
            autolog("LeptonAnalyzer selection", passes)
        if event.is_sl and event.is_dl:
            autolog("The event (%s,%s,%s) is both sl and dl" % (
                event.input.run,event.input.lumi,event.input.evt)
            )
            autolog("SL mu")
            for lep in event.mu_SL:
                (self.conf.leptons["mu"]["debug"])(lep)
            autolog("DL mu")
            for lep in event.mu_DL:
                (self.conf.leptons["mu"]["debug"])(lep)
                
            autolog("SL el")
            for lep in event.el_SL:
                (self.conf.leptons["el"]["debug"])(lep)
            autolog("DL el")
            for lep in event.el_DL:
                (self.conf.leptons["el"]["debug"])(lep)
                
            autolog("veto mu")
            for lep in event.mu_veto:
                (self.conf.leptons["mu"]["debug"])(lep)
            autolog("veto el")
            for lep in event.mu_veto:
                (self.conf.leptons["el"]["debug"])(lep)
            passes = False
            autolog("WARNING: Overlapping event")

        return self.conf.general["passall"] or passes
Beispiel #12
0
    def _process(self, event):

        if not self.cfg_comp.isMC:
            return event

        if "debug" in self.conf.general["verbosity"]:
            autolog("GenTTHAnalyzer started")

        #Get light quarks from W/Z
        event.l_quarks_w = event.GenWZQuark

        #Get b quarks from top
        event.b_quarks_t = event.GenBQuarkFromTop

        #Get b-quarks from H
        event.b_quarks_h = event.GenBQuarkFromH

        #Get leptonic top children
        #note that the tau lepton might be missing
        event.lep_top = event.GenLepFromTop
        event.nu_top = event.GenNuFromTop

        #cat_gen - a string specifying the ttbar decay mode
        event.cat_gen = None
        #cat_gen_n - a numerical value corresponding to the string
        event.cat_gen_n = -1

        #all leptonic and hadronic gen tops
        event.genTopLep = []
        event.genTopHad = []

        #Only run top algos
        if len(event.GenTop) == 2:

            #Gen tops might be in random order
            gt1 = event.GenTop[0]
            gt2 = event.GenTop[1]
            dm1 = getattr(gt1, "decayMode", -1)
            dm2 = getattr(gt2, "decayMode", -1)
            #single-leptonic
            if ((dm1 == 0 and dm2 == 1) or (dm2 == 0 and dm1 == 1)):

                #First top is leptonic
                if dm1 == 0:
                    event.genTopLep = [gt1]
                    event.genTopHad = [gt2]
                #Second top is leptonic
                else:
                    event.genTopLep = [gt2]
                    event.genTopHad = [gt1]

                event.cat_gen = "sl"
                event.cat_gen_n = 0
            elif (dm1 == 0 and dm2 == 0):
                event.cat_gen = "dl"
                event.cat_gen_n = 1
                event.genTopLep = [gt1, gt2]
                event.genTopHad = []
            elif (dm1 == 1 and dm2 == 1):
                event.cat_gen = "fh"
                event.cat_gen_n = 2
                event.genTopHad = [gt1, gt2]
                event.genTopLep = []
            else:
                event.genTopLep = []
                event.genTopHad = []

        #these are the quarks that would pass selection
        event.l_quarks_gen = []
        event.b_quarks_gen_t = []
        event.b_quarks_gen_h = []

        nq = 0
        #Find the light quarks from W that would pass jet selection
        #associate them with a transfer function
        for q in event.l_quarks_w:
            nq += 1
            if self.pass_jet_selection(q):
                q.btagFlag = 0.0
                q.tth_match_label = "wq"
                q.tth_match_index = nq
                attach_jet_transfer_function(q, self.conf)
                event.l_quarks_gen += [q]

        #Find the b quarks from top that would pass jet selection
        #associate them with a transfer function
        for q in event.b_quarks_t:
            nq += 1
            if self.pass_jet_selection(q):
                q.btagFlag = 1.0
                q.tth_match_label = "tb"
                q.tth_match_index = nq
                attach_jet_transfer_function(q, self.conf)
                event.b_quarks_gen_t += [q]

        #Find the b quarks from Higgs that would pass jet selection
        #associate them with a transfer function
        for q in event.b_quarks_h:
            nq += 1
            if self.pass_jet_selection(q):
                q.btagFlag = 1.0
                q.tth_match_label = "hb"
                q.tth_match_index = nq
                attach_jet_transfer_function(q, self.conf)
                event.b_quarks_gen_h += [q]

        #Number of reco jets matched to quarks from W, top, higgs
        event.nSelected_wq = len(event.l_quarks_gen)
        event.nSelected_tb = len(event.b_quarks_gen_t)
        event.nSelected_hb = len(event.b_quarks_gen_h)

        #Get the total MET from the neutrinos
        spx = 0
        spy = 0
        for nu in event.nu_top:
            p4 = lvec(nu)
            spx += p4.Px()
            spy += p4.Py()
        event.MET_tt = MET(px=spx, py=spy)

        #Get the total ttH visible pt at gen level
        spx = 0
        spy = 0
        for p in (event.l_quarks_w + event.b_quarks_t + event.b_quarks_h +
                  event.lep_top):
            p4 = lvec(p)
            spx += p4.Px()
            spy += p4.Py()
        event.tth_px_gen = spx
        event.tth_py_gen = spy

        #Calculate tth recoil
        #rho = -met - tth_matched
        event.tth_rho_px_gen = -event.MET_gen.px - event.tth_px_gen
        event.tth_rho_py_gen = -event.MET_gen.py - event.tth_py_gen

        if "gen" in self.conf.general["verbosity"]:
            for j in event.l_quarks_w:
                autolog("gen q(W)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.b_quarks_t:
                autolog("gen b(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.lep_top:
                autolog("gen l(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.nu_top:
                autolog("gen n(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            for j in event.b_quarks_h:
                autolog("gen b(h)", j.pt, j.eta, j.phi, j.mass, j.pdgId)
            autolog("gen cat", event.cat_gen, event.cat_gen_n)

        # In semi-leptonic events we need to figure out which top b is from
        if event.cat_gen == "sl":

            # If b pdgId has same sign as hadronic top pdgId, it's the one
            if event.b_quarks_t[0].pdgId * event.genTopHad[0].pdgId > 0:
                event.b_quarks_t[0].from_had_t = 1
                event.b_quarks_t[1].from_had_t = 0
            else:
                event.b_quarks_t[0].from_had_t = 0
                event.b_quarks_t[1].from_had_t = 1

        # In Di leptonic events no b quarks come from hadronic top
        elif event.cat_gen == "dl":
            for b in event.b_quarks_t:
                b.from_had_t = 0

        # In All hadronic events both b quarks come from hadronic top
        elif event.cat_gen == "fh":
            for b in event.b_quarks_t:
                b.from_had_t = 1
        else:
            for b in event.b_quarks_t:
                b.from_had_t = -1

        #Store for each jet, specified by it's index in the jet
        #vector, if it is matched to any gen-level quarks
        matched_pairs = {}

        def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric):
            for ij, j in enumerate(jetcoll):
                for iq, q in enumerate(quarkcoll):

                    # Set to 1 for bs from hadronic top
                    # Set to 0 for bs from hadronic top
                    # Set to -1 for other stuff
                    if label == "tb":
                        if q.from_had_t == 1:
                            numeric_b_from_had_t = 1
                        elif q.from_had_t == 0:
                            numeric_b_from_had_t = 0
                        else:
                            numeric_b_from_had_t = -1
                    else:
                        numeric_b_from_had_t = -1

                    #find DeltaR between jet and quark
                    l1 = lvec(q)
                    l2 = lvec(j)
                    dr = l1.DeltaR(l2)
                    if dr < 0.3:
                        #Jet already had a match: take the one with smaller dR
                        if not matched_pairs.has_key(ij):
                            matched_pairs[ij] = []
                        matched_pairs[ij] += [(label, iq, dr, label_numeric,
                                               numeric_b_from_had_t)]

        #Find the best possible match for each individual jet

        #light-quarks from W
        match_jets_to_quarks(event.good_jets, event.l_quarks_gen, "wq", 0)
        #b-quarks from top
        match_jets_to_quarks(event.good_jets, event.b_quarks_gen_t, "tb", 1)
        #b-quarks from Higgs
        match_jets_to_quarks(event.good_jets, event.b_quarks_gen_h, "hb", 2)
        #gluons from top
        match_jets_to_quarks(event.good_jets, event.GenGluonFromTop, "tg", 3)
        #gluons from b
        match_jets_to_quarks(event.good_jets, event.GenGluonFromB, "bg", 4)

        #Number of reco jets matched to quarks from W, top, higgs
        event.nMatch_wq = 0
        event.nMatch_tb = 0
        event.nMatch_hb = 0
        #As above, but also required to be tagged/untagged for b/light respectively.
        event.nMatch_wq_btag = 0
        event.nMatch_tb_btag = 0
        event.nMatch_hb_btag = 0

        #Now check what each jet was matched to
        for ij, jet in enumerate(event.good_jets):

            jet.tth_match_label = None
            jet.tth_match_index = -1
            jet.tth_match_dr = -1
            jet.tth_match_label_numeric = -1

            #Jet did not have a match (no jet index in matched_pairs)
            if not matched_pairs.has_key(ij):
                continue  #continue jet loop

            #mlabel - string label of quark collection, e.g. "wq"
            #midx - index of quark in vector that the jet was matched to
            #mdr - delta R between jet and matched quark
            #mlabel_num - numeric label of quark collection, e.g. 0
            #mlabel_num_bfromhadt - numeric label if the b is from hadronic top
            #                         -1 if not b or not from top
            #                          0 if from leptonic top
            #                          1 if from hadronic top
            matches = matched_pairs[ij]
            if len(matches) == 1:
                mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matches[
                    0]
            else:
                #select dR-ordered matches from W, t, b
                matches_hard = filter(lambda x: x[0] in ["wq", "tb", "hb"],
                                      matches)
                matches_hard = sorted(matches_hard, key=lambda x: x[2])
                if len(matches_hard) >= 1:
                    mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matches_hard[
                        0]
                else:
                    matches_soft = filter(lambda x: x[0] in ["tg", "bg"],
                                          matches)
                    matches_soft = sorted(matches_soft, key=lambda x: x[2])
                    mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matches_soft[
                        0]

            jet.tth_match_label = mlabel
            jet.tth_match_index = midx
            jet.tth_match_dr = mdr
            jet.tth_match_label_numeric = mlabel_num
            jet.tth_match_label_bfromhadt = mlabel_num_bfromhadt

            if mlabel == "wq":
                event.nMatch_wq += 1

                #If this jet is considered to be un-tagged
                if jet.btagFlag == 0.0:
                    event.nMatch_wq_btag += 1
            elif mlabel == "tb":
                event.nMatch_tb += 1

                #If this jet is considered to be b-tagged
                if jet.btagFlag == 1.0:
                    event.nMatch_tb_btag += 1

            elif mlabel == "hb":
                event.nMatch_hb += 1
                if jet.btagFlag == 1.0:
                    event.nMatch_hb_btag += 1

        if "debug" in self.conf.general["verbosity"]:
            autolog(
                "nSel {0}_{1}_{2} nMatch {3}_{4}_{5} nMatch_btag {6}_{7}_{8}".
                format(
                    event.nSelected_wq,
                    event.nSelected_tb,
                    event.nSelected_hb,
                    event.nMatch_wq,
                    event.nMatch_tb,
                    event.nMatch_hb,
                    event.nMatch_wq_btag,
                    event.nMatch_tb_btag,
                    event.nMatch_hb_btag,
                ))

        if "matching" in self.conf.general["verbosity"]:
            matches = {
                "wq": event.l_quarks_w,
                "tb": event.b_quarks_t,
                "hb": event.b_quarks_h
            }

            for ij, jet in enumerate(event.good_jets):
                if not matched_pairs.has_key(ij):
                    continue
                mlabel, midx, mdr, mlabel_num = matched_pairs[ij]
                autolog("jet match", ij, mlabel, midx, mdr, jet.pt,
                        matches[mlabel][midx].pt)

        #reco-level tth-matched system
        spx = 0.0
        spy = 0.0
        for jet in event.good_jets:
            if not (jet.tth_match_label is None):
                p4 = lvec(jet)
                spx += p4.Px()
                spy += p4.Py()
        for lep in event.good_leptons:
            p4 = lvec(lep)
            match = False
            for glep in event.lep_top:
                p4g = lvec(glep)
                if p4g.DeltaR(p4) < 0.3:
                    match = True
                    break
            if match:
                spx += p4.Px()
                spy += p4.Py()

        event.tth_px_reco = spx
        event.tth_py_reco = spy

        #Calculate tth recoil
        #rho = -met - tth_matched
        event.tth_rho_px_reco = -event.MET.px - event.tth_px_reco
        event.tth_rho_py_reco = -event.MET.py - event.tth_py_reco

        #print out gen-level quarks
        if "input" in self.conf.general["verbosity"]:
            print "gen Q"
            for q in event.l_quarks_gen:
                print q.pt, q.eta, q.phi, q.mass, q.pdgId
            print "gen B"
            for q in event.b_quarks_gen:
                print q.pt, q.eta, q.phi, q.mass, q.pdgId

        return event
Beispiel #13
0
    def _process(self, event):
        event.passes_subjet = True
        
        if "debug" in self.conf.general["verbosity"]:
            autolog("SubjetAnalyzer started")

        if "subjet" in self.conf.general["verbosity"]:
            print 'Printing from SubjetAnalyzer! iEv = {0}'.format(event.iEv)
            

        # Is set to True only after the event passed all criteria
        setattr( event, 'PassedSubjetAnalyzer', False )

        # Create two new lists for selected_btagged_jets and wquark_candidate_jets
        # Needs to be done here because the lists are needed in the mem config
        setattr( event, 'boosted_bjets', [] )
        setattr( event, 'boosted_ljets', [] )
        setattr( event, 'topCandidate', [] )
        setattr( event, 'topCandidatesSync', [] )
        setattr( event, 'othertopCandidate', [] )
        setattr( event, 'higgsCandidate', [] )
        setattr( event, 'higgsCandidateForSync', [] )

        event.n_bjets = len( event.selected_btagged_jets_high )
        event.n_ljets = len( list( event.wquark_candidate_jets ) )


        ########################################
        # Minimal event suitability:
        #  - Needs to be single leptonic
        #  - At least 1 httCandidate
        ########################################

        # Check if the event is single leptonic or FH
        # for SYNC: REMOVE this cut
        #if not (event.is_sl or event.is_fh): #LC
        #    return event

        # Get the top candidates
        # ======================================

        # Keep track of number of httCandidates that passed the cut
        setattr( event, 'nhttCandidate', len( event.httCandidates ) )
        setattr( event, 'nhttCandidate_aftercuts', 0 )

        # Just run normal mem if there is no httCandidate present
        # Check if there is an httCandidate
        # if len( event.httCandidates ) == 0:
        #    return event


        # All HTT candidates for sync
        all_tops = []
        for candidate in event.httCandidates:

            # Veto tops unless all subjets pass jetID
            if not candidate.subjetIDPassed:
                continue

            # (optional eta cut)
            #if abs(candidate.eta) < 2.0:
            all_tops.append( copy.deepcopy(candidate) )

        # TODO: Add eta cut also to analysis tops
            
        # Match the top to a fat jet
        #  - Copies bbtag and tau_N, calculates n_subjettiness
        #  - DOES NOT apply the n_subjettiness cut
        all_tops = self.Match_top_to_fatjet( event, all_tops, False )

        for top in all_tops:
            top.fj_index = event.FatjetCA15ungroomed.index(top.matched_fatjet)            
        
        # Sort by which ungroomed fj they are matched to
        all_tops = sorted(all_tops, key=lambda x: x.fj_index )        
                

        # Apply the cuts on the httCandidate
        tops = []
        for candidate in event.httCandidates:
            if self.Apply_Cut_criteria( candidate ):
                tops.append( copy.deepcopy(candidate) )


        # Match the top to a fat jet
        #  - Copies bbtag and tau_N, calculates n_subjettiness
        #  - Applies the n_subjettiness cut
        tops = self.Match_top_to_fatjet( event, tops, True )
        other_tops = []

        # Calculate delR with the lepton for all tops that survived the cut
        if event.is_sl: #LC
            for top in tops + all_tops:
                setattr( top, 'delR_lepton' ,
                          self.Get_DeltaR_two_objects( top, event.good_leptons[0] ) )
        else:
            for top in tops + all_tops:
                setattr( top, 'delR_lepton' , -1 )

        # Keep track of how many httCandidates passed
        event.nhttCandidate_aftercuts = len( tops )

        #Find the best hadronic gen top match for each top candidate
        if self.cfg_comp.isMC:
            gentops = getattr(event, "genTopHad", [])
            if len(gentops)>0:
                for topcandidate in tops:
                    lv1 = lvec(topcandidate)
                    drs = []
                    for igentop, gentop in enumerate(gentops):
                        lv2 = lvec(gentop)
                        drs += [(lv1.DeltaR(lv2), gentop, igentop)]
                    drs = sorted(drs, key=lambda x: x[0])
                    best = drs[0]
                    topcandidate.genTopHad_dr = best[0]
                    topcandidate.genTop = best[1]
                    topcandidate.genTopHad_index = best[2]

        # Just run normal mem if there is no httCandidate surviving the cuts
        # Check if any candidates survived the cutoff criteria

        # if len(tops) == 0:
        #     return event
        # If exactly 1 survived, simply continue with that candidate
        other_top_present = False
        top = None
        if len(tops) == 0:
            other_top_present = False
        elif len(tops) == 1:
            top = tops[0]
            other_top_present = False
        # If more than 1 candidate survived the cutoff criteria, choose the
        # one whose delR with the lepton was biggest
        else:
            if event.is_sl: #LC
                tops = sorted( tops, key=lambda x: -x.delR_lepton )
            else:
                tops = sorted( tops, key=lambda x: x.pt)
            other_top_present = True
            top = tops[0]
            other_tops = tops[1:]

        if "subjet" in self.conf.general["verbosity"]:
            print "Number of top candidates ", len(tops)

        # Get a Higgs candidate
        # ======================================

        #Types of fatjets to match to Higgs candidate
        fatjets_to_match = ["softdropz2b1", "softdrop", 
                            "softdropz2b1filt", "softdropfilt", 
                            "pruned", "subjetfiltered"]
        extra_higgs_vars = ["mass", "nallsubjets", 
                            "sj1pt", "sj1eta", "sj1phi", "sj1mass", "sj1btag", 
                            "sj2pt", "sj2eta", "sj2phi", "sj2mass", "sj2btag", 
                            "sj3pt", "sj3eta", "sj3phi", "sj3mass", "sj3btag", # only calc for subjetfiltered
                            "sj12masspt", "sj12massb", "sj123masspt", # only calc for subjetfiltered
                            "secondbtag", # only calc for subjetfiltered
        ]

    
        for fatjet_name in fatjets_to_match:
            self.Add_Higgs_Subjets_To_Fatjet(event, fatjet_name)

        higgs_present = False
        higgsCandidates = []
        for fatjet in event.FatjetCA15ungroomed:

            # Turned off for now. TODO: Revisit Higgs/Top overlap removal
            # # Choose only fatjets that were not HTTv2 candidates for the higgs reco
            # # Check if the fatjet is not already matched to the chosen top candidate
            # if top and hasattr(fatjet, 'matched_top') and fatjet == top.matched_fatjet:
            #    continue

            fatjet.n_subjettiness = -1
            if fatjet.tau1 > 0:
                fatjet.n_subjettiness = fatjet.tau2 / fatjet.tau1
            if top:
                fatjet.dr_top = self.Get_DeltaR_two_objects(fatjet, top)

            #set default extra variables for all fatjet types
            for fatjetkind in fatjets_to_match:
                for var in extra_higgs_vars:
                    setattr(fatjet, var + "_" + fatjetkind, -9999)
                    

            if self.cfg_comp.isMC:
                #match higgs candidate to generated higgs
                genhiggs = getattr(event, "GenHiggsBoson", [])
                if len(genhiggs)>0:
                    lv1 = lvec(fatjet)
                    lv2 = lvec(genhiggs[0])
                    fatjet.dr_genHiggs = lv1.DeltaR(lv2)

                #match higgs candidate to generated tops
                gentops = [x for x in getattr(event, "GenTop", []) if x.pt>self.GenTop_pt_cut]
                if len(gentops)>0:
                    lv1 = lvec(fatjet)
                    fatjet.dr_genTop = min([lv1.DeltaR(lvec(x)) for x in gentops])
    
            higgsCandidates.append( fatjet )
            higgs_present = True

        
        # Match higgs candidates to various fat jets
        for fatjetkind in fatjets_to_match:
            nmatch = self.Match_two_lists(
                higgsCandidates, 'higgs',
                getattr(event, "FatjetCA15" + fatjetkind), 'fatjet_' + fatjetkind,
                R_cut = self.R_cut_fatjets
            )

        # Add properties of the matched fatjet to the higgs candidate
        for higgsCandidate in higgsCandidates:
            for fatjetkind in fatjets_to_match:
                matchjet = getattr(higgsCandidate, "matched_fatjet_" + fatjetkind, None)
                if matchjet != None:
                    for var in extra_higgs_vars:                        
                        if hasattr(matchjet,var):
                            setattr(higgsCandidate, var + "_" + fatjetkind, getattr(matchjet,var))

        # Sort higgs candidates by pt
        # We store all of them, so it does not really matter fow now
        higgsCandidates = sorted( higgsCandidates, key=lambda x: -x.pt )

                            
        ########################################
        # Get the lists of particles: quarks, jets and subjets
        ########################################

        # Get the subjets from the httCandidate
        #  - Also sets transfer functions as attributes
        #  - Returns subjets ordered by decreasing btag
        #  - First subjet has btagFlag==1.0, the other two btagFlag==0.0
        top_subjets = self.Get_Subjets( top )
        if "subjet" in self.conf.general["verbosity"]:
            print "subjets"
            for subjet in top_subjets:
                print subjet

        if other_top_present:
            for top in other_tops: self.Get_Subjets( top )

        # Set 'PDGID' to 1 for light, and to 5 for b
        for subjet in top_subjets:
            if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 )
            if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 )

        # Create two new lists for btagged_jets and wquark_candidate_jets in the
        # original events
        if event.is_sl: #LC
            reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high )
            reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) )
        else: #LC
            reco_ltagged_jets = event.buntagged_jets_bdisc
            reco_btagged_jets = event.btagged_jets_bdisc

        if len(tops) > 0:
            top_subjets = self.Get_Subjets( top )
            if "subjet" in self.conf.general["verbosity"]:
                print "subjets"
                for subjet in top_subjets:
                    print subjet

            if other_top_present:
                for top in other_tops: self.Get_Subjets( top )

            # Set 'PDGID' to 1 for light, and to 5 for b
            # FIXME: do not use PDGID currently, as it ONLY works with the HEPTopTagger perm pruning strat
            #for subjet in top_subjets:
            #    if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 )
            #    if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 )

            # Create two new lists for btagged_jets and wquark_candidate_jets in the
            # original events
            reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high )
            reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) )

            for jet in reco_btagged_jets:
                setattr( jet, 'btag', getattr(jet,self.btagAlgo) )
                setattr( jet, 'btagFlag', 1.0 )
                #setattr( jet, 'PDGID', 0 )

            for jet in reco_ltagged_jets:
                setattr( jet, 'btag', getattr(jet,self.btagAlgo) )
                setattr( jet, 'btagFlag', 0.0 )
                #setattr( jet, 'PDGID', 0 )


            ########################################
            # Matching
            ########################################

            # Whenever a subjet has a 'match' (dR < dR_cut), the matched object should
            # excluded from the event

            # Match subjet to a bjet
            n_excluded_bjets = self.Match_two_lists(
                top_subjets, 'top_subjet',
                reco_btagged_jets, 'bjet' )

            # Match subjet to a ljet
            n_excluded_ljets = self.Match_two_lists(
                top_subjets , 'top_subjet',
                reco_ltagged_jets, 'ljet' )
            if "subjet" in self.conf.general["verbosity"]:
                print "subjet nMatchB={0} nMatchL={1}".format(n_excluded_bjets, n_excluded_ljets)


#FIXME: Unify this for SL/DL/FH
#from FH branch
#                # Stop adding after 4 b-jets
#                if event.is_sl:#LC
#                    if len(boosted_bjets) == 4: break
#            event.PassedSubjetAnalyzer = True
#
#            if event.is_fh: #LC: also add other light jets
#                for ljet in reco_ltagged_jets:
#                    # Check if the l-jet is not excluded
#                    if not hasattr( ljet, 'matched_top_subjet' ):
#                        boosted_ljets.append( ljet )
#
#                
#            
#
#        # If too many events are excluded, just run the default hypothesis
#        else:
#            if "subjet" in self.conf.general["verbosity"]:
#                print "[SubjetAnalyzer] subjet has too many overlaps, using reco"
#            boosted_bjets = reco_btagged_jets
#            boosted_ljets = reco_ltagged_jets
#            event.PassedSubjetAnalyzer = False
#======= end from FH branch
            # In case of double matching, choose the match with lowest delR
            # (This is not expected to happen often)
            for subjet in top_subjets:
                if hasattr( subjet, 'matched_bjet' ) and \
                    hasattr( subjet, 'matched_ljet' ) :
                    print '[SubjetAnalyzer] Double match detected'
                    if subjet.matched_bjet_delR < subjet.matched_ljet_delR:
                        del subjet.matched_ljet
                        del subjet.matched_ljet_delR
                        n_excluded_bjets -= 1
                    else:
                        del subjet.matched_bjet
                        del subjet.matched_bjet_delR
                        n_excluded_ljets -= 1


            ########################################
            # Modifying the bjets and ljets lists
            ########################################

            boosted_bjets = []
            boosted_ljets = []

            if n_excluded_bjets <= 1:
                if "subjet" in self.conf.general["verbosity"]:
                    print "subjet replacing"
                # Add the subjets to the final output lists first
                for subjet in top_subjets:
                    if subjet.btagFlag == 1.0: boosted_bjets.append( subjet )
                    if subjet.btagFlag == 0.0: boosted_ljets.append( subjet )

                # Sort tl btagged jets by decreasing btag (to be sure, but should 
                # already be done in previous analyzer)
                # Only resolved b-jets
                reco_btagged_jets = sorted( reco_btagged_jets, key=lambda x: -x.btag )

                # Add up to 4 reco btagged jets to the output lists
                for bjet in reco_btagged_jets:
                    # Check if the b-jet is not excluded
                    if not hasattr( bjet, 'matched_top_subjet' ):
                        boosted_bjets.append( bjet )

                    # Stop adding after 4 b-jets
                    if len(boosted_bjets) == 4: break
                event.PassedSubjetAnalyzer = True

            # If too many events are excluded, just run the default hypothesis
            else:
                if "subjet" in self.conf.general["verbosity"]:
                    print "[SubjetAnalyzer] subjet has too many overlaps, using reco"
                boosted_bjets = reco_btagged_jets
                boosted_ljets = reco_ltagged_jets
                event.PassedSubjetAnalyzer = False

     


        ########################################
        # Write to event
        ########################################

        # Store output lists in event
        event.higgsCandidate = higgsCandidates

        all_tops_to_add = []

        # Add top matched to leading fatjet OR dummy
        for top in all_tops:
            if top.fj_index == 0:
                all_tops_to_add.append(top)
                break
        if len(all_tops_to_add) == 0:
            all_tops_to_add.append(DummyTop())

        # Add top matched to sub-leading fatjet OR dummy
        for top in all_tops:
            if top.fj_index == 1:
                all_tops_to_add.append( top)
                break
        if len(all_tops_to_add) == 1:
            all_tops_to_add.append(DummyTop())
        
        
        event.topCandidatesSync = all_tops_to_add

        if len(tops)>0:
            event.topCandidate = [ top ]
            event.othertopCandidate = other_tops
            event.boosted_bjets = boosted_bjets
            event.boosted_ljets = boosted_ljets

            event.n_boosted_bjets = len( boosted_bjets )
            event.n_boosted_ljets = len( boosted_ljets )

            event.n_excluded_bjets = n_excluded_bjets
            event.n_excluded_ljets = n_excluded_ljets

        #pdb.set_trace()

        if "subjet" in self.conf.general["verbosity"]:
            print '[SubjetAnalyzer] Exiting SubjetAnalyzer! event.PassedSubjetAnalyzer = {0}'.format(
                event.PassedSubjetAnalyzer
            )


        ########################################
        # Matching to Gen top
        ###########################################

        event.n_matched_TTgentop = -1
        event.matched_TTgentop_pt = -1
        event.n_matched_TTgenb = -1
        event.n_matched_TTgenW = -1

        if self.cfg_comp.isMC and len(tops)>0:
            self.Do_GenTop_Matching(event)

        return event 

        ########################################
        # Quark Matching
        ########################################

        # This section is only useful for truth-level comparison, and can be turned
        # off if this is not needed.
        # Do_Quark_Matching( event ) sets number of matches with quarks as branches
        # in the event, but these branches do not have to be filled (they will be
        # automatically set to -1 in the final output root file).

        if self.cfg_comp.isMC:
            self.Do_Quark_Matching( event )