Example #1
0
def cleanFromLepton(objs, leptonCollection):

    cleanStuffs = []
    dicts = matchObjectCollectionMultiple(objs, leptonCollection, 0.4)
    for key, value in dicts.iteritems():
        #print "key : ", key , " ; value : ", value
        if (value is not None and len(value) != 0) or (value is not None):
            continue

        cleanStuffs.append(key)
    return cleanStuffs
Example #2
0
def genRecoFinder(obj1s, obj2s):

    dicts = matchObjectCollectionMultiple(obj1s, obj2s, 0.4,
                                          lambda x, y: x.pdgId == y.pdgId)
    genRecoflatten = []
    for key, value in dicts.iteritems():
        if value is None: continue  # None means genparts list is empty.
        if len(value) == 0:
            continue  # empty list mean unsuccessful deltaR matching from GEN to Reco
        genRecoflatten.append([key, value[0]])

    return genRecoflatten
Example #3
0
def recoFinder(obj1s, obj2s):

    dicts = matchObjectCollectionMultiple(obj1s, obj2s, 0.4,
                                          lambda x, y: x.pdgId == y.pdgId)
    #else:
    #    dicts=matchObjectCollectionMultiple(obj1s,obj2s,0.4,lambda x,y : x.partonFlavour==y.pdgId)
    #print "dicts = ", dicts
    recoflatten = []
    for key, value in dicts.iteritems():
        if value is None: continue  # None means genparts list is empty.
        if len(value) == 0:
            continue  # empty list mean unsuccessful deltaR matching from GEN to Reco
        #print "key = ", key
        #print "value[0].pdgId = ", value[0].pdgId

        recoflatten.append(key)

    return recoflatten
Example #4
0
    def matchLeptons(self, event):
        def plausible(rec, gen):
            if abs(rec.pdgId) == 11 and abs(gen.pdgId) != 11: return False
            if abs(rec.pdgId) == 13 and abs(gen.pdgId) != 13: return False
            dr = deltaR(rec.etc, rec.phi, gen.eta, gen.phi)
            if dr < 0.3: return True
            if rec.pt < 10 and abs(rec.pdgId) == 13 and gen.pdgId != rec.pdgId:
                return False
            if dr < 0.7: return True
            if min(rec.pt, gen.pt) / max(rec.pt, gen.pt) < 0.3: return False
            return True

        leps = event.selectedLeptons
        match = matchObjectCollectionMultiple(leps,
                                              event.genleps + event.gentauleps,
                                              dRmax=1.2,
                                              presel=lambda plausible: True)
        for lep in leps:
            gen = match[lep]
            lep.mcMatchId = (gen.sourceId if gen != None else 0)
            lep.mcMatchTau = (gen in event.gentauleps if gen else -99)
            lep.mcLep = gen
    def analyze(self, event):
        """process event, return True (go to next module) or False (fail, go to next event)"""
        jets = Collection(event, self.jetBranchName)
        if not self.isData:
            genJets = Collection(event, self.genJetBranchName)

        if self.doGroomed:
            subJets = Collection(event, self.subJetBranchName)
            if not self.isData:
                genSubJets = Collection(event, self.genSubJetBranchName)
                genSubJetMatcher = matchObjectCollectionMultiple(genJets,
                                                                 genSubJets,
                                                                 dRmax=0.8)

        if not self.isData:
            self.jetSmearer.setSeed(event)

        jets_pt_raw = []
        jets_pt_nom = []
        jets_mass_raw = []
        jets_mass_nom = []

        jets_corr_JEC = []
        jets_corr_JER = []
        jets_corr_JMS = []
        jets_corr_JMR = []

        jets_pt_jerUp = {}
        jets_pt_jerDown = {}
        jets_pt_jesUp = {}
        jets_pt_jesDown = {}

        jets_mass_jerUp = {}
        jets_mass_jerDown = {}
        jets_mass_jmrUp = []
        jets_mass_jmrDown = []
        jets_mass_jesUp = {}
        jets_mass_jesDown = {}
        jets_mass_jmsUp = []
        jets_mass_jmsDown = []

        for jerID in self.splitJERIDs:
            jets_pt_jerUp[jerID] = []
            jets_pt_jerDown[jerID] = []
            jets_mass_jerUp[jerID] = []
            jets_mass_jerDown[jerID] = []

        for jesUncertainty in self.jesUncertainties:
            jets_pt_jesUp[jesUncertainty] = []
            jets_pt_jesDown[jesUncertainty] = []
            jets_mass_jesUp[jesUncertainty] = []
            jets_mass_jesDown[jesUncertainty] = []

        if self.doGroomed:
            jets_msdcorr_raw = []
            jets_msdcorr_nom = []
            jets_msdcorr_corr_JMR = []
            jets_msdcorr_corr_JMS = []
            jets_msdcorr_corr_PUPPI = []
            jets_msdcorr_jerUp = {}
            jets_msdcorr_jerDown = {}
            jets_msdcorr_jmrUp = []
            jets_msdcorr_jmrDown = []
            jets_msdcorr_jesUp = {}
            jets_msdcorr_jesDown = {}
            jets_msdcorr_jmsUp = []
            jets_msdcorr_jmsDown = []
            jets_msdcorr_tau21DDT_nom = []
            jets_msdcorr_tau21DDT_jerUp = {}
            jets_msdcorr_tau21DDT_jerDown = {}
            jets_msdcorr_tau21DDT_jmrUp = []
            jets_msdcorr_tau21DDT_jmrDown = []
            jets_msdcorr_tau21DDT_jmsUp = []
            jets_msdcorr_tau21DDT_jmsDown = []
            for jerID in self.splitJERIDs:
                jets_msdcorr_jerUp[jerID] = []
                jets_msdcorr_jerDown[jerID] = []
                jets_msdcorr_tau21DDT_jerUp[jerID] = []
                jets_msdcorr_tau21DDT_jerDown[jerID] = []
            for jesUncertainty in self.jesUncertainties:
                jets_msdcorr_jesUp[jesUncertainty] = []
                jets_msdcorr_jesDown[jesUncertainty] = []

        rho = getattr(event, self.rhoBranchName)

        # match reconstructed jets to generator level ones
        # (needed to evaluate JER scale factors and uncertainties)
        if not self.isData:
            pairs = matchObjectCollection(jets, genJets)

        for jet in jets:
            # jet pt and mass corrections
            jet_pt = jet.pt
            jet_mass = jet.mass

            if hasattr(jet, "rawFactor"):
                jet_rawpt = jet_pt * (1 - jet.rawFactor)
                jet_rawmass = jet_mass * (1 - jet.rawFactor)
            else:
                jet_rawpt = -1.0 * jet_pt  # If factor not present factor will be saved as -1
                jet_rawmass = -1.0 * jet_mass  # If factor not present factor will be saved as -1
            (jet_pt, jet_mass) = self.jetReCalibrator.correct(jet, rho)
            jet.pt = jet_pt
            jet.mass = jet_mass
            jets_pt_raw.append(jet_rawpt)
            jets_mass_raw.append(jet_rawmass)
            jets_corr_JEC.append(jet_pt / jet_rawpt)

            if not self.isData:
                genJet = pairs[jet]

            # evaluate JER scale factors and uncertainties
            # (cf. https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution and https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyResolution )
            if not self.isData:
                (jet_pt_jerNomVal, jet_pt_jerUpVal,
                 jet_pt_jerDownVal) = self.jetSmearer.getSmearValsPt(
                     jet, genJet, rho)
            else:
                # set values to 1 for data so that jet_pt_nom is not smeared
                (jet_pt_jerNomVal, jet_pt_jerUpVal, jet_pt_jerDownVal) = (1, 1,
                                                                          1)
            jets_corr_JER.append(jet_pt_jerNomVal)

            jet_pt_nom = jet_pt_jerNomVal * jet_pt if self.applySmearing else jet_pt
            if jet_pt_nom < 0.0:
                jet_pt_nom *= -1.0
            jets_pt_nom.append(jet_pt_nom)

            # Evaluate JMS and JMR scale factors and uncertainties
            jmsNomVal, jmsDownVal, jmsUpVal = self.jmsVals if not self.isData else (
                1, 1, 1)
            if not self.isData:
                (jet_mass_jmrNomVal, jet_mass_jmrUpVal,
                 jet_mass_jmrDownVal) = self.jetSmearer.getSmearValsM(
                     jet, genJet)
            else:
                # set values to 1 for data so that jet_mass_nom is not smeared
                (jet_mass_jmrNomVal, jet_mass_jmrUpVal,
                 jet_mass_jmrDownVal) = (1, 1, 1)
            jets_corr_JMS.append(jmsNomVal)
            jets_corr_JMR.append(jet_mass_jmrNomVal)

            jet_mass_nom = jet_pt_jerNomVal * jet_mass_jmrNomVal * \
                jmsNomVal * jet_mass if self.applySmearing else jet_mass
            if jet_mass_nom < 0.0:
                jet_mass_nom *= -1.0
            jets_mass_nom.append(jet_mass_nom)

            if not self.isData:
                jet_pt_jerUp = {
                    jerID: jet_pt_nom
                    for jerID in self.splitJERIDs
                }
                jet_pt_jerDown = {
                    jerID: jet_pt_nom
                    for jerID in self.splitJERIDs
                }
                jet_mass_jerUp = {
                    jerID: jet_mass_nom
                    for jerID in self.splitJERIDs
                }
                jet_mass_jerDown = {
                    jerID: jet_mass_nom
                    for jerID in self.splitJERIDs
                }
                thisJERID = self.getJERsplitID(jet_pt_nom, jet.eta)
                jet_pt_jerUp[thisJERID] = jet_pt_jerUpVal * jet_pt
                jet_pt_jerDown[thisJERID] = jet_pt_jerDownVal * jet_pt
                jet_mass_jerUp[thisJERID] = jet_pt_jerUpVal * \
                    jet_mass_jmrNomVal * jmsNomVal * jet_mass
                jet_mass_jerDown[thisJERID] = jet_pt_jerDownVal * \
                    jet_mass_jmrNomVal * jmsNomVal * jet_mass

                for jerID in self.splitJERIDs:
                    jets_pt_jerUp[jerID].append(jet_pt_jerUp[jerID])
                    jets_pt_jerDown[jerID].append(jet_pt_jerDown[jerID])
                    jets_mass_jerUp[jerID].append(jet_mass_jerUp[jerID])
                    jets_mass_jerDown[jerID].append(jet_mass_jerDown[jerID])

                jets_mass_jmrUp.append(jet_pt_jerNomVal * jet_mass_jmrUpVal *
                                       jmsNomVal * jet_mass)
                jets_mass_jmrDown.append(jet_pt_jerNomVal *
                                         jet_mass_jmrDownVal * jmsNomVal *
                                         jet_mass)
                jets_mass_jmsUp.append(jet_pt_jerNomVal * jet_mass_jmrNomVal *
                                       jmsUpVal * jet_mass)
                jets_mass_jmsDown.append(jet_pt_jerNomVal *
                                         jet_mass_jmrNomVal * jmsDownVal *
                                         jet_mass)

            if self.doGroomed:
                if not self.isData:
                    genGroomedSubJets = genSubJetMatcher[
                        genJet] if genJet is not None else None
                    genGroomedJet = genGroomedSubJets[0].p4(
                    ) + genGroomedSubJets[1].p4(
                    ) if genGroomedSubJets is not None and len(
                        genGroomedSubJets) >= 2 else None
                else:
                    genGroomedSubJets = None
                    genGroomedJet = None
                if jet.subJetIdx1 >= 0 and jet.subJetIdx2 >= 0:
                    groomedP4 = subJets[jet.subJetIdx1].p4() + subJets[
                        jet.subJetIdx2].p4()  # check subjet jecs
                else:
                    groomedP4 = None

                jet_msdcorr_raw = groomedP4.M(
                ) if groomedP4 is not None else 0.0
                # raw value always stored withoud mass correction
                jets_msdcorr_raw.append(jet_msdcorr_raw)
                # LC: Apply PUPPI SD mass correction https://github.com/cms-jet/PuppiSoftdropMassCorr/
                puppisd_genCorr = self.puppisd_corrGEN.Eval(jet.pt)
                if abs(jet.eta) <= 1.3:
                    puppisd_recoCorr = self.puppisd_corrRECO_cen.Eval(jet.pt)
                else:
                    puppisd_recoCorr = self.puppisd_corrRECO_for.Eval(jet.pt)

                puppisd_total = puppisd_genCorr * puppisd_recoCorr
                jets_msdcorr_corr_PUPPI.append(puppisd_total)
                if groomedP4 is not None:
                    groomedP4.SetPtEtaPhiM(groomedP4.Perp(), groomedP4.Eta(),
                                           groomedP4.Phi(),
                                           groomedP4.M() * puppisd_total)

                # now apply the mass correction to the raw value
                jet_msdcorr_raw = groomedP4.M(
                ) if groomedP4 is not None else 0.0
                if jet_msdcorr_raw < 0.0:
                    jet_msdcorr_raw *= -1.0

                # Evaluate JMS and JMR scale factors and uncertainties
                if not self.isData:
                    (jet_msdcorr_jmrNomVal, jet_msdcorr_jmrUpVal,
                     jet_msdcorr_jmrDownVal) = \
                        (self.jetSmearer.getSmearValsM(groomedP4,
                         genGroomedJet) if groomedP4 is not None
                         and genGroomedJet is not None else (0., 0., 0.))
                else:
                    (jet_msdcorr_jmrNomVal, jet_msdcorr_jmrUpVal,
                     jet_msdcorr_jmrDownVal) = (1, 1, 1)

                jets_msdcorr_corr_JMS.append(jmsNomVal)
                jets_msdcorr_corr_JMR.append(jet_msdcorr_jmrNomVal)

                jet_msdcorr_nom = jet_pt_jerNomVal * \
                    jet_msdcorr_jmrNomVal * jmsNomVal * jet_msdcorr_raw
                # store the nominal mass value
                jets_msdcorr_nom.append(jet_msdcorr_nom)

                if not self.isData:
                    jet_msdcorr_jerUp = {
                        jerID: jet_msdcorr_nom
                        for jerID in self.splitJERIDs
                    }
                    jet_msdcorr_jerDown = {
                        jerID: jet_msdcorr_nom
                        for jerID in self.splitJERIDs
                    }
                    thisJERID = self.getJERsplitID(jet_pt_nom, jet.eta)
                    jet_msdcorr_jerUp[thisJERID] = jet_pt_jerUpVal * \
                        jet_msdcorr_jmrNomVal * jmsNomVal * jet_msdcorr_raw
                    jet_msdcorr_jerDown[thisJERID] = jet_pt_jerDownVal * \
                        jet_msdcorr_jmrNomVal * jmsNomVal * jet_msdcorr_raw
                    for jerID in self.splitJERIDs:
                        jets_msdcorr_jerUp[jerID].append(
                            jet_msdcorr_jerUp[jerID])
                        jets_msdcorr_jerDown[jerID].append(
                            jet_msdcorr_jerDown[jerID])

                    jets_msdcorr_jmrUp.append(
                        jet_pt_jerNomVal * jet_msdcorr_jmrUpVal * jmsNomVal *
                        jet_msdcorr_raw)
                    jets_msdcorr_jmrDown.append(
                        jet_pt_jerNomVal * jet_msdcorr_jmrDownVal * jmsNomVal *
                        jet_msdcorr_raw)
                    jets_msdcorr_jmsUp.append(
                        jet_pt_jerNomVal * jet_msdcorr_jmrNomVal * jmsUpVal *
                        jet_msdcorr_raw)
                    jets_msdcorr_jmsDown.append(
                        jet_pt_jerNomVal * jet_msdcorr_jmrNomVal * jmsDownVal *
                        jet_msdcorr_raw)

                    # Also evaluated JMS&JMR SD corr in tau21DDT region: https://twiki.cern.ch/twiki/bin/viewauth/CMS/JetWtagging#tau21DDT_0_43
                    if self.era in ["2016"]:
                        jmstau21DDTNomVal = 1.014
                        jmstau21DDTDownVal = 1.007
                        jmstau21DDTUpVal = 1.021
                        self.jetSmearer.jmr_vals = [1.086, 1.176, 0.996]
                    elif self.era in ["2017"]:
                        jmstau21DDTNomVal = 0.983
                        jmstau21DDTDownVal = 0.976
                        jmstau21DDTUpVal = 0.99
                        self.jetSmearer.jmr_vals = [1.080, 1.161, 0.999]
                    elif self.era in ["2018"]:
                        jmstau21DDTNomVal = 1.000  # tau21DDT < 0.43 WP
                        jmstau21DDTDownVal = 0.990
                        jmstau21DDTUpVal = 1.010
                        self.jetSmearer.jmr_vals = [1.124, 1.208, 1.040]

                    (
                        jet_msdcorr_tau21DDT_jmrNomVal,
                        jet_msdcorr_tau21DDT_jmrUpVal,
                        jet_msdcorr_tau21DDT_jmrDownVal
                    ) = self.jetSmearer.getSmearValsM(
                        groomedP4, genGroomedJet
                    ) if groomedP4 is not None and genGroomedJet is not None else (
                        0., 0., 0.)

                    jet_msdcorr_tau21DDT_nom = jet_pt_jerNomVal * \
                        jet_msdcorr_tau21DDT_jmrNomVal * jmstau21DDTNomVal * jet_msdcorr_raw
                    jets_msdcorr_tau21DDT_nom.append(jet_msdcorr_tau21DDT_nom)

                    jet_msdcorr_tau21DDT_jerUp = {
                        jerID: jet_msdcorr_tau21DDT_nom
                        for jerID in self.splitJERIDs
                    }
                    jet_msdcorr_tau21DDT_jerDown = {
                        jerID: jet_msdcorr_tau21DDT_nom
                        for jerID in self.splitJERIDs
                    }
                    jet_msdcorr_tau21DDT_jerUp[thisJERID] = jet_pt_jerUpVal * \
                        jet_msdcorr_tau21DDT_jmrNomVal * jmstau21DDTNomVal * jet_msdcorr_raw
                    jet_msdcorr_tau21DDT_jerDown[thisJERID] = jet_pt_jerDownVal * \
                        jet_msdcorr_tau21DDT_jmrNomVal * jmstau21DDTNomVal * jet_msdcorr_raw
                    for jerID in self.splitJERIDs:
                        jets_msdcorr_tau21DDT_jerUp[jerID].append(
                            jet_msdcorr_tau21DDT_jerUp[jerID])
                        jets_msdcorr_tau21DDT_jerDown[jerID].append(
                            jet_msdcorr_tau21DDT_jerDown[jerID])

                    jets_msdcorr_tau21DDT_jmrUp.append(
                        jet_pt_jerNomVal * jet_msdcorr_tau21DDT_jmrUpVal *
                        jmstau21DDTNomVal * jet_msdcorr_raw)
                    jets_msdcorr_tau21DDT_jmrDown.append(
                        jet_pt_jerNomVal * jet_msdcorr_tau21DDT_jmrDownVal *
                        jmstau21DDTNomVal * jet_msdcorr_raw)
                    jets_msdcorr_tau21DDT_jmsUp.append(
                        jet_pt_jerNomVal * jet_msdcorr_tau21DDT_jmrNomVal *
                        jmstau21DDTUpVal * jet_msdcorr_raw)
                    jets_msdcorr_tau21DDT_jmsDown.append(
                        jet_pt_jerNomVal * jet_msdcorr_tau21DDT_jmrNomVal *
                        jmstau21DDTDownVal * jet_msdcorr_raw)

                    # Restore original jmr_vals in jetSmearer
                    self.jetSmearer.jmr_vals = self.jmrVals

            if not self.isData:
                # evaluate JES uncertainties
                jet_pt_jesUp = {}
                jet_pt_jesDown = {}
                jet_mass_jesUp = {}
                jet_mass_jesDown = {}
                jet_msdcorr_jesUp = {}
                jet_msdcorr_jesDown = {}

                for jesUncertainty in self.jesUncertainties:
                    # (cf. https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyCorrections#JetCorUncertainties)
                    # cf. https://hypernews.cern.ch/HyperNews/CMS/get/JetMET/2000.html
                    if jesUncertainty == "HEMIssue":
                        delta = 1.
                        if jet_pt_nom > 15 and jet.jetId & 2 and jet.phi > -1.57 and jet.phi < -0.87:
                            if jet.eta > -2.5 and jet.eta < -1.3:
                                delta = 0.8
                            elif jet.eta <= -2.5 and jet.eta > -3:
                                delta = 0.65
                        jet_pt_jesUp[jesUncertainty] = jet_pt_nom
                        jet_pt_jesDown[jesUncertainty] = delta * jet_pt_nom
                        jet_mass_jesUp[jesUncertainty] = jet_mass_nom
                        jet_mass_jesDown[jesUncertainty] = delta * jet_mass_nom
                        if self.doGroomed:
                            jet_msdcorr_jesUp[jesUncertainty] = jet_msdcorr_nom
                            jet_msdcorr_jesDown[jesUncertainty] = delta * \
                                jet_msdcorr_nom
                    else:
                        self.jesUncertainty[jesUncertainty].setJetPt(
                            jet_pt_nom)
                        self.jesUncertainty[jesUncertainty].setJetEta(jet.eta)
                        delta = self.jesUncertainty[
                            jesUncertainty].getUncertainty(True)
                        jet_pt_jesUp[jesUncertainty] = jet_pt_nom * \
                            (1. + delta)
                        jet_pt_jesDown[jesUncertainty] = jet_pt_nom * \
                            (1. - delta)
                        jet_mass_jesUp[jesUncertainty] = jet_mass_nom * \
                            (1. + delta)
                        jet_mass_jesDown[jesUncertainty] = jet_mass_nom * \
                            (1. - delta)
                        if self.doGroomed:
                            jet_msdcorr_jesUp[jesUncertainty] = jet_msdcorr_nom * \
                                (1. + delta)
                            jet_msdcorr_jesDown[
                                jesUncertainty] = jet_msdcorr_nom * (1. -
                                                                     delta)
                    jets_pt_jesUp[jesUncertainty].append(
                        jet_pt_jesUp[jesUncertainty])
                    jets_pt_jesDown[jesUncertainty].append(
                        jet_pt_jesDown[jesUncertainty])
                    jets_mass_jesUp[jesUncertainty].append(
                        jet_mass_jesUp[jesUncertainty])
                    jets_mass_jesDown[jesUncertainty].append(
                        jet_mass_jesDown[jesUncertainty])
                    if self.doGroomed:
                        jets_msdcorr_jesUp[jesUncertainty].append(
                            jet_msdcorr_jesUp[jesUncertainty])
                        jets_msdcorr_jesDown[jesUncertainty].append(
                            jet_msdcorr_jesDown[jesUncertainty])

        self.out.fillBranch("%s_pt_raw" % self.jetBranchName, jets_pt_raw)
        self.out.fillBranch("%s_pt_nom" % self.jetBranchName, jets_pt_nom)
        self.out.fillBranch("%s_corr_JEC" % self.jetBranchName, jets_corr_JEC)
        self.out.fillBranch("%s_mass_raw" % self.jetBranchName, jets_mass_raw)
        self.out.fillBranch("%s_mass_nom" % self.jetBranchName, jets_mass_nom)

        if not self.isData:
            self.out.fillBranch("%s_corr_JER" % self.jetBranchName,
                                jets_corr_JER)
            self.out.fillBranch("%s_corr_JMS" % self.jetBranchName,
                                jets_corr_JMS)
            self.out.fillBranch("%s_corr_JMR" % self.jetBranchName,
                                jets_corr_JMR)
            for jerID in self.splitJERIDs:
                self.out.fillBranch(
                    "%s_pt_jer%sUp" % (self.jetBranchName, jerID),
                    jets_pt_jerUp[jerID])
                self.out.fillBranch(
                    "%s_pt_jer%sDown" % (self.jetBranchName, jerID),
                    jets_pt_jerDown[jerID])
                self.out.fillBranch(
                    "%s_mass_jer%sUp" % (self.jetBranchName, jerID),
                    jets_mass_jerUp[jerID])
                self.out.fillBranch(
                    "%s_mass_jer%sDown" % (self.jetBranchName, jerID),
                    jets_mass_jerDown[jerID])
            self.out.fillBranch("%s_mass_jmrUp" % self.jetBranchName,
                                jets_mass_jmrUp)
            self.out.fillBranch("%s_mass_jmrDown" % self.jetBranchName,
                                jets_mass_jmrDown)
            self.out.fillBranch("%s_mass_jmsUp" % self.jetBranchName,
                                jets_mass_jmsUp)
            self.out.fillBranch("%s_mass_jmsDown" % self.jetBranchName,
                                jets_mass_jmsDown)

        if self.doGroomed:
            self.out.fillBranch("%s_msoftdrop_raw" % self.jetBranchName,
                                jets_msdcorr_raw)
            self.out.fillBranch("%s_msoftdrop_nom" % self.jetBranchName,
                                jets_msdcorr_nom)
            self.out.fillBranch("%s_msoftdrop_corr_JMS" % self.jetBranchName,
                                jets_msdcorr_corr_JMS)
            self.out.fillBranch("%s_msoftdrop_corr_JMR" % self.jetBranchName,
                                jets_msdcorr_corr_JMR)
            self.out.fillBranch("%s_msoftdrop_corr_PUPPI" % self.jetBranchName,
                                jets_msdcorr_corr_PUPPI)
            if not self.isData:
                self.out.fillBranch(
                    "%s_msoftdrop_tau21DDT_nom" % self.jetBranchName,
                    jets_msdcorr_tau21DDT_nom)
                for jerID in self.splitJERIDs:
                    self.out.fillBranch(
                        "%s_msoftdrop_jer%sUp" % (self.jetBranchName, jerID),
                        jets_msdcorr_jerUp[jerID])
                    self.out.fillBranch(
                        "%s_msoftdrop_jer%sDown" % (self.jetBranchName, jerID),
                        jets_msdcorr_jerDown[jerID])
                    self.out.fillBranch(
                        "%s_msoftdrop_tau21DDT_jer%sUp" %
                        (self.jetBranchName, jerID),
                        jets_msdcorr_tau21DDT_jerUp[jerID])
                    self.out.fillBranch(
                        "%s_msoftdrop_tau21DDT_jer%sDown" %
                        (self.jetBranchName, jerID),
                        jets_msdcorr_tau21DDT_jerDown[jerID])
                self.out.fillBranch("%s_msoftdrop_jmrUp" % self.jetBranchName,
                                    jets_msdcorr_jmrUp)
                self.out.fillBranch(
                    "%s_msoftdrop_jmrDown" % self.jetBranchName,
                    jets_msdcorr_jmrDown)
                self.out.fillBranch("%s_msoftdrop_jmsUp" % self.jetBranchName,
                                    jets_msdcorr_jmsUp)
                self.out.fillBranch(
                    "%s_msoftdrop_jmsDown" % self.jetBranchName,
                    jets_msdcorr_jmsDown)
                self.out.fillBranch(
                    "%s_msoftdrop_tau21DDT_jmrUp" % self.jetBranchName,
                    jets_msdcorr_tau21DDT_jmrUp)
                self.out.fillBranch(
                    "%s_msoftdrop_tau21DDT_jmrDown" % self.jetBranchName,
                    jets_msdcorr_tau21DDT_jmrDown)
                self.out.fillBranch(
                    "%s_msoftdrop_tau21DDT_jmsUp" % self.jetBranchName,
                    jets_msdcorr_tau21DDT_jmsUp)
                self.out.fillBranch(
                    "%s_msoftdrop_tau21DDT_jmsDown" % self.jetBranchName,
                    jets_msdcorr_tau21DDT_jmsDown)

        if not self.isData:
            for jesUncertainty in self.jesUncertainties:
                self.out.fillBranch(
                    "%s_pt_jes%sUp" % (self.jetBranchName, jesUncertainty),
                    jets_pt_jesUp[jesUncertainty])
                self.out.fillBranch(
                    "%s_pt_jes%sDown" % (self.jetBranchName, jesUncertainty),
                    jets_pt_jesDown[jesUncertainty])
                self.out.fillBranch(
                    "%s_mass_jes%sUp" % (self.jetBranchName, jesUncertainty),
                    jets_mass_jesUp[jesUncertainty])
                self.out.fillBranch(
                    "%s_mass_jes%sDown" % (self.jetBranchName, jesUncertainty),
                    jets_mass_jesDown[jesUncertainty])

                if self.doGroomed:
                    self.out.fillBranch(
                        "%s_msoftdrop_jes%sUp" %
                        (self.jetBranchName, jesUncertainty),
                        jets_msdcorr_jesUp[jesUncertainty])
                    self.out.fillBranch(
                        "%s_msoftdrop_jes%sDown" %
                        (self.jetBranchName, jesUncertainty),
                        jets_msdcorr_jesDown[jesUncertainty])

        return True
Example #6
0
    def analyze(self, event):
        """process event, return True (go to next module) or False (fail, go to next event)"""
        jets = Collection(event, self.jetBranchName)
        genJets = Collection(event, self.genJetBranchName)

        if self.doGroomed:
            subJets = Collection(event, self.subJetBranchName)
            genSubJets = Collection(event, self.genSubJetBranchName)
            genSubJetMatcher = matchObjectCollectionMultiple(genJets,
                                                             genSubJets,
                                                             dRmax=0.8)

        jets_pt_nom = []
        jets_pt_jerUp = []
        jets_pt_jerDown = []
        jets_pt_jesUp = {}
        jets_pt_jesDown = {}
        jets_mass_nom = []
        jets_mass_jerUp = []
        jets_mass_jerDown = []
        jets_mass_jmrUp = []
        jets_mass_jmrDown = []
        jets_mass_jesUp = {}
        jets_mass_jesDown = {}
        jets_mass_jmsUp = []
        jets_mass_jmsDown = []
        for jesUncertainty in self.jesUncertainties:
            jets_pt_jesUp[jesUncertainty] = []
            jets_pt_jesDown[jesUncertainty] = []
            jets_mass_jesUp[jesUncertainty] = []
            jets_mass_jesDown[jesUncertainty] = []

        if self.corrMET:
            met = Object(event, self.metBranchName)
            (met_px, met_py) = (met.pt * math.cos(met.phi),
                                met.pt * math.sin(met.phi))
            (met_px_nom, met_py_nom) = (met_px, met_py)
            (met_px_jerUp, met_py_jerUp) = (met_px, met_py)
            (met_px_jerDown, met_py_jerDown) = (met_px, met_py)
            (met_px_jesUp, met_py_jesUp) = ({}, {})
            (met_px_jesDown, met_py_jesDown) = ({}, {})
            for jesUncertainty in self.jesUncertainties:
                met_px_jesUp[jesUncertainty] = met_px
                met_py_jesUp[jesUncertainty] = met_py
                met_px_jesDown[jesUncertainty] = met_px
                met_py_jesDown[jesUncertainty] = met_py

        if self.doGroomed:
            jets_msdcorr_nom = []
            jets_msdcorr_jerUp = []
            jets_msdcorr_jerDown = []
            jets_msdcorr_jmrUp = []
            jets_msdcorr_jmrDown = []
            jets_msdcorr_jesUp = {}
            jets_msdcorr_jesDown = {}
            jets_msdcorr_jmsUp = []
            jets_msdcorr_jmsDown = []
            for jesUncertainty in self.jesUncertainties:
                jets_msdcorr_jesUp[jesUncertainty] = []
                jets_msdcorr_jesDown[jesUncertainty] = []

        rho = getattr(event, self.rhoBranchName)

        # match reconstructed jets to generator level ones
        # (needed to evaluate JER scale factors and uncertainties)
        pairs = matchObjectCollection(jets, genJets)

        for jet in jets:
            genJet = pairs[jet]
            if self.doGroomed:
                genGroomedSubJets = genSubJetMatcher[
                    genJet] if genJet != None else None
                genGroomedJet = genGroomedSubJets[0].p4() + genGroomedSubJets[
                    1].p4() if genGroomedSubJets != None and len(
                        genGroomedSubJets) >= 2 else None
                if jet.subJetIdx1 >= 0 and jet.subJetIdx2 >= 0:
                    groomedP4 = subJets[jet.subJetIdx1].p4() + subJets[
                        jet.subJetIdx2].p4()
                else:
                    groomedP4 = None

            # evaluate JER scale factors and uncertainties
            # (cf. https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution and https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyResolution )
            (jet_pt_jerNomVal, jet_pt_jerUpVal,
             jet_pt_jerDownVal) = self.jetSmearer.getSmearValsPt(
                 jet, genJet, rho)

            jet_pt = jet.pt
            if self.redoJEC:
                jet_pt = self.jetReCalibrator.correct(jet, rho)
            jet_pt_nom = jet_pt_jerNomVal * jet_pt
            if jet_pt_nom < 0.0:
                jet_pt_nom *= -1.0
            jet_pt_jerUp = jet_pt_jerUpVal * jet_pt
            jet_pt_jerDown = jet_pt_jerDownVal * jet_pt
            jets_pt_nom.append(jet_pt_nom)
            jets_pt_jerUp.append(jet_pt_jerUpVal * jet_pt)
            jets_pt_jerDown.append(jet_pt_jerDownVal * jet_pt)
            # evaluate JES uncertainties
            jet_pt_jesUp = {}
            jet_pt_jesDown = {}
            jet_mass_jesUp = {}
            jet_mass_jesDown = {}
            jet_mass_jmsUp = []
            jet_mass_jmsDown = []

            # Evaluate JMS and JMR scale factors and uncertainties
            jmsNomVal = self.jmsVals[0]
            jmsDownVal = self.jmsVals[1]
            jmsUpVal = self.jmsVals[2]
            (jet_mass_jmrNomVal, jet_mass_jmrUpVal,
             jet_mass_jmrDownVal) = self.jetSmearer.getSmearValsM(jet, genJet)
            jet_mass_nom = jet_pt_jerNomVal * jet_mass_jmrNomVal * jmsNomVal * jet.mass
            if jet_mass_nom < 0.0:
                jet_mass_nom *= -1.0
            jets_mass_nom.append(jet_mass_nom)
            jets_mass_jerUp.append(jet_pt_jerUpVal * jet_mass_jmrNomVal *
                                   jmsNomVal * jet.mass)
            jets_mass_jerDown.append(jet_pt_jerDownVal * jet_mass_jmrNomVal *
                                     jmsNomVal * jet.mass)
            jets_mass_jmrUp.append(jet_pt_jerNomVal * jet_mass_jmrUpVal *
                                   jmsNomVal * jet.mass)
            jets_mass_jmrDown.append(jet_pt_jerNomVal * jet_mass_jmrDownVal *
                                     jmsNomVal * jet.mass)
            jets_mass_jmsUp.append(jet_pt_jerNomVal * jet_mass_jmrNomVal *
                                   jmsUpVal * jet.mass)
            jets_mass_jmsDown.append(jet_pt_jerNomVal * jet_mass_jmrNomVal *
                                     jmsDownVal * jet.mass)

            if self.doGroomed:
                # to evaluate JES uncertainties
                jet_msdcorr_jmsUp = []
                jet_msdcorr_jmsDown = []
                jet_msdcorr_jesUp = {}
                jet_msdcorr_jesDown = {}

                (jet_msdcorr_jmrNomVal, jet_msdcorr_jmrUpVal,
                 jet_msdcorr_jmrDownVal) = self.jetSmearer.getSmearValsM(
                     groomedP4, genGroomedJet
                 ) if groomedP4 != None and genGroomedJet != None else (0., 0.,
                                                                        0.)
                jet_msdcorr_raw = groomedP4.M() if groomedP4 != None else 0.0
                if jet_msdcorr_raw < 0.0:
                    jet_msdcorr_raw *= -1.0
                jet_msdcorr_nom = jet_pt_jerNomVal * jet_msdcorr_jmrNomVal * jet_msdcorr_raw
                jets_msdcorr_nom.append(jet_msdcorr_nom)
                jets_msdcorr_jerUp.append(jet_pt_jerUpVal *
                                          jet_msdcorr_jmrNomVal * jmsNomVal *
                                          jet_msdcorr_raw)
                jets_msdcorr_jerDown.append(jet_pt_jerDownVal *
                                            jet_msdcorr_jmrNomVal * jmsNomVal *
                                            jet_msdcorr_raw)
                jets_msdcorr_jmrUp.append(jet_pt_jerNomVal *
                                          jet_msdcorr_jmrUpVal * jmsNomVal *
                                          jet_msdcorr_raw)
                jets_msdcorr_jmrDown.append(
                    jet_pt_jerNomVal * jet_msdcorr_jmrDownVal * jmsNomVal *
                    jet_msdcorr_raw)
                jets_msdcorr_jmsUp.append(jet_pt_jerNomVal *
                                          jet_msdcorr_jmrNomVal * jmsUpVal *
                                          jet_msdcorr_raw)
                jets_msdcorr_jmsDown.append(
                    jet_pt_jerNomVal * jet_msdcorr_jmrNomVal * jmsDownVal *
                    jet_msdcorr_raw)

            for jesUncertainty in self.jesUncertainties:
                # (cf. https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyCorrections#JetCorUncertainties )
                self.jesUncertainty[jesUncertainty].setJetPt(jet_pt_nom)
                self.jesUncertainty[jesUncertainty].setJetEta(jet.eta)
                delta = self.jesUncertainty[jesUncertainty].getUncertainty(
                    True)
                jet_pt_jesUp[jesUncertainty] = jet_pt_nom * (1. + delta)
                jet_pt_jesDown[jesUncertainty] = jet_pt_nom * (1. - delta)
                jets_pt_jesUp[jesUncertainty].append(
                    jet_pt_jesUp[jesUncertainty])
                jets_pt_jesDown[jesUncertainty].append(
                    jet_pt_jesDown[jesUncertainty])
                jet_mass_jesUp[jesUncertainty] = jet_mass_nom * (1. + delta)
                jet_mass_jesDown[jesUncertainty] = jet_mass_nom * (1. - delta)
                jets_mass_jesUp[jesUncertainty].append(
                    jet_mass_jesUp[jesUncertainty])
                jets_mass_jesDown[jesUncertainty].append(
                    jet_mass_jesDown[jesUncertainty])
                if self.doGroomed:
                    jet_msdcorr_jesUp[jesUncertainty] = jet_msdcorr_nom * (
                        1. + delta)
                    jet_msdcorr_jesDown[jesUncertainty] = jet_msdcorr_nom * (
                        1. - delta)
                    jets_msdcorr_jesUp[jesUncertainty].append(
                        jet_msdcorr_jesUp[jesUncertainty])
                    jets_msdcorr_jesDown[jesUncertainty].append(
                        jet_msdcorr_jesDown[jesUncertainty])

            # progate JER and JES corrections and uncertainties to MET
            if self.corrMET and jet_pt_nom > self.unclEnThreshold:
                jet_cosPhi = math.cos(jet.phi)
                jet_sinPhi = math.sin(jet.phi)
                met_px_nom = met_px_nom - (jet_pt_nom - jet_pt) * jet_cosPhi
                met_py_nom = met_py_nom - (jet_pt_nom - jet_pt) * jet_sinPhi
                met_px_jerUp = met_px_jerUp - (jet_pt_jerUp -
                                               jet_pt_nom) * jet_cosPhi
                met_py_jerUp = met_py_jerUp - (jet_pt_jerUp -
                                               jet_pt_nom) * jet_sinPhi
                met_px_jerDown = met_px_jerDown - (jet_pt_jerDown -
                                                   jet_pt_nom) * jet_cosPhi
                met_py_jerDown = met_py_jerDown - (jet_pt_jerDown -
                                                   jet_pt_nom) * jet_sinPhi
                for jesUncertainty in self.jesUncertainties:
                    met_px_jesUp[jesUncertainty] = met_px_jesUp[
                        jesUncertainty] - (jet_pt_jesUp[jesUncertainty] -
                                           jet_pt_nom) * jet_cosPhi
                    met_py_jesUp[jesUncertainty] = met_py_jesUp[
                        jesUncertainty] - (jet_pt_jesUp[jesUncertainty] -
                                           jet_pt_nom) * jet_sinPhi
                    met_px_jesDown[jesUncertainty] = met_px_jesDown[
                        jesUncertainty] - (jet_pt_jesDown[jesUncertainty] -
                                           jet_pt_nom) * jet_cosPhi
                    met_py_jesDown[jesUncertainty] = met_py_jesDown[
                        jesUncertainty] - (jet_pt_jesDown[jesUncertainty] -
                                           jet_pt_nom) * jet_sinPhi

        # propagate "unclustered energy" uncertainty to MET
        if self.corrMET:
            (met_px_unclEnUp, met_py_unclEnUp) = (met_px, met_py)
            (met_px_unclEnDown, met_py_unclEnDown) = (met_px, met_py)
            met_deltaPx_unclEn = getattr(
                event, self.metBranchName + "_MetUnclustEnUpDeltaX")
            met_deltaPy_unclEn = getattr(
                event, self.metBranchName + "_MetUnclustEnUpDeltaY")
            met_px_unclEnUp = met_px_unclEnUp + met_deltaPx_unclEn
            met_py_unclEnUp = met_py_unclEnUp + met_deltaPy_unclEn
            met_px_unclEnDown = met_px_unclEnDown - met_deltaPx_unclEn
            met_py_unclEnDown = met_py_unclEnDown - met_deltaPy_unclEn

            # propagate effect of jet energy smearing to MET
            met_px_jerUp = met_px_jerUp + (met_px_nom - met_px)
            met_py_jerUp = met_py_jerUp + (met_py_nom - met_py)
            met_px_jerDown = met_px_jerDown + (met_px_nom - met_px)
            met_py_jerDown = met_py_jerDown + (met_py_nom - met_py)
            for jesUncertainty in self.jesUncertainties:
                met_px_jesUp[jesUncertainty] = met_px_jesUp[jesUncertainty] + (
                    met_px_nom - met_px)
                met_py_jesUp[jesUncertainty] = met_py_jesUp[jesUncertainty] + (
                    met_py_nom - met_py)
                met_px_jesDown[jesUncertainty] = met_px_jesDown[
                    jesUncertainty] + (met_px_nom - met_px)
                met_py_jesDown[jesUncertainty] = met_py_jesDown[
                    jesUncertainty] + (met_py_nom - met_py)
            met_px_unclEnUp = met_px_unclEnUp + (met_px_nom - met_px)
            met_py_unclEnUp = met_py_unclEnUp + (met_py_nom - met_py)
            met_px_unclEnDown = met_px_unclEnDown + (met_px_nom - met_px)
            met_py_unclEnDown = met_py_unclEnDown + (met_py_nom - met_py)

        self.out.fillBranch("%s_pt_nom" % self.jetBranchName, jets_pt_nom)
        self.out.fillBranch("%s_pt_jerUp" % self.jetBranchName, jets_pt_jerUp)
        self.out.fillBranch("%s_pt_jerDown" % self.jetBranchName,
                            jets_pt_jerDown)
        self.out.fillBranch("%s_mass_nom" % self.jetBranchName, jets_mass_nom)
        self.out.fillBranch("%s_mass_jerUp" % self.jetBranchName,
                            jets_mass_jerUp)
        self.out.fillBranch("%s_mass_jerDown" % self.jetBranchName,
                            jets_mass_jerDown)
        self.out.fillBranch("%s_mass_jmrUp" % self.jetBranchName,
                            jets_mass_jmrUp)
        self.out.fillBranch("%s_mass_jmrDown" % self.jetBranchName,
                            jets_mass_jmrDown)
        self.out.fillBranch("%s_mass_jmsUp" % self.jetBranchName,
                            jets_mass_jmsUp)
        self.out.fillBranch("%s_mass_jmsDown" % self.jetBranchName,
                            jets_mass_jmsDown)

        if self.doGroomed:

            self.out.fillBranch("%s_msoftdrop_nom" % self.jetBranchName,
                                jets_msdcorr_nom)
            self.out.fillBranch("%s_msoftdrop_jerUp" % self.jetBranchName,
                                jets_msdcorr_jerUp)
            self.out.fillBranch("%s_msoftdrop_jerDown" % self.jetBranchName,
                                jets_msdcorr_jerDown)
            self.out.fillBranch("%s_msoftdrop_jmrUp" % self.jetBranchName,
                                jets_msdcorr_jmrUp)
            self.out.fillBranch("%s_msoftdrop_jmrDown" % self.jetBranchName,
                                jets_msdcorr_jmrDown)
            self.out.fillBranch("%s_msoftdrop_jmsUp" % self.jetBranchName,
                                jets_msdcorr_jmsUp)
            self.out.fillBranch("%s_msoftdrop_jmsDown" % self.jetBranchName,
                                jets_msdcorr_jmsDown)

        if self.corrMET:
            self.out.fillBranch("%s_pt_nom" % self.metBranchName,
                                math.sqrt(met_px_nom**2 + met_py_nom**2))
            self.out.fillBranch("%s_phi_nom" % self.metBranchName,
                                math.atan2(met_py_nom, met_px_nom))
            self.out.fillBranch("%s_pt_jerUp" % self.metBranchName,
                                math.sqrt(met_px_jerUp**2 + met_py_jerUp**2))
            self.out.fillBranch("%s_phi_jerUp" % self.metBranchName,
                                math.atan2(met_py_jerUp, met_px_jerUp))
            self.out.fillBranch(
                "%s_pt_jerDown" % self.metBranchName,
                math.sqrt(met_px_jerDown**2 + met_py_jerDown**2))
            self.out.fillBranch("%s_phi_jerDown" % self.metBranchName,
                                math.atan2(met_py_jerDown, met_px_jerDown))

        for jesUncertainty in self.jesUncertainties:
            self.out.fillBranch(
                "%s_pt_jes%sUp" % (self.jetBranchName, jesUncertainty),
                jets_pt_jesUp[jesUncertainty])
            self.out.fillBranch(
                "%s_pt_jes%sDown" % (self.jetBranchName, jesUncertainty),
                jets_pt_jesDown[jesUncertainty])
            self.out.fillBranch(
                "%s_mass_jes%sUp" % (self.jetBranchName, jesUncertainty),
                jets_mass_jesUp[jesUncertainty])
            self.out.fillBranch(
                "%s_mass_jes%sDown" % (self.jetBranchName, jesUncertainty),
                jets_mass_jesDown[jesUncertainty])

            if self.doGroomed:
                self.out.fillBranch(
                    "%s_msoftdrop_jes%sUp" %
                    (self.jetBranchName, jesUncertainty),
                    jets_msdcorr_jesUp[jesUncertainty])
                self.out.fillBranch(
                    "%s_msoftdrop_jes%sDown" %
                    (self.jetBranchName, jesUncertainty),
                    jets_msdcorr_jesDown[jesUncertainty])

            if self.corrMET:
                self.out.fillBranch(
                    "%s_pt_jes%sUp" % (self.metBranchName, jesUncertainty),
                    math.sqrt(met_px_jesUp[jesUncertainty]**2 +
                              met_py_jesUp[jesUncertainty]**2))
                self.out.fillBranch(
                    "%s_phi_jes%sUp" % (self.metBranchName, jesUncertainty),
                    math.atan2(met_py_jesUp[jesUncertainty],
                               met_px_jesUp[jesUncertainty]))
                self.out.fillBranch(
                    "%s_pt_jes%sDown" % (self.metBranchName, jesUncertainty),
                    math.sqrt(met_px_jesDown[jesUncertainty]**2 +
                              met_py_jesDown[jesUncertainty]**2))
                self.out.fillBranch(
                    "%s_phi_jes%sDown" % (self.metBranchName, jesUncertainty),
                    math.atan2(met_py_jesDown[jesUncertainty],
                               met_px_jesDown[jesUncertainty]))
        if self.corrMET:
            self.out.fillBranch(
                "%s_pt_unclustEnUp" % self.metBranchName,
                math.sqrt(met_px_unclEnUp**2 + met_py_unclEnUp**2))
            self.out.fillBranch("%s_phi_unclustEnUp" % self.metBranchName,
                                math.atan2(met_py_unclEnUp, met_px_unclEnUp))
            self.out.fillBranch(
                "%s_pt_unclustEnDown" % self.metBranchName,
                math.sqrt(met_px_unclEnDown**2 + met_py_unclEnDown**2))
            self.out.fillBranch(
                "%s_phi_unclustEnDown" % self.metBranchName,
                math.atan2(met_py_unclEnDown, met_px_unclEnDown))

        return True
    def analyze(self, event):
        """process event, return True (go to next module) or False (fail, go to next event)"""
        jets = Collection(event, self.jetBranchName )
        genJets = Collection(event, self.genJetBranchName )
        
        if self.doGroomed :
            subJets = Collection(event, self.subJetBranchName )
            genSubJets = Collection(event, self.genSubJetBranchName )
            genSubJetMatcher = matchObjectCollectionMultiple( genJets, genSubJets, dRmax=0.8 )
        
        self.jetSmearer.setSeed(event)

        jet_L1 = []
        jet_L2L3 = []
        jet_LRes = []
        
        jets_pt_raw = []
        jets_pt_nom = []
        jets_mass_raw = []
        jets_mass_nom = []
        
        jets_corr_JEC = []
        jets_corr_JER = []
        jets_corr_JMS = []
        jets_corr_JMR = []
        
        jets_pt_jerUp   = []
        jets_pt_jerDown = []
        jets_pt_jesUp   = {}
        jets_pt_jesDown = {}
        
        jets_mass_jerUp   = []
        jets_mass_jerDown = []
        jets_mass_jmrUp   = []
        jets_mass_jmrDown = []
        jets_mass_jesUp   = {}
        jets_mass_jesDown = {}
        jets_mass_jmsUp   = []
        jets_mass_jmsDown = []
        
        for jesUncertainty in self.jesUncertainties:
            jets_pt_jesUp[jesUncertainty]   = []
            jets_pt_jesDown[jesUncertainty] = []
            jets_mass_jesUp[jesUncertainty]   = []
            jets_mass_jesDown[jesUncertainty] = []
        
        if self.corrMET :
            met = Object(event, self.metBranchName)
            ( met_px,         met_py         ) = ( met.pt*math.cos(met.phi), met.pt*math.sin(met.phi) )
            ( met_px_nom, met_py_nom ) = ( met_px, met_py )
            ( met_px_jerUp,   met_py_jerUp   ) = ( met_px, met_py )
            ( met_px_jerDown, met_py_jerDown ) = ( met_px, met_py )
            ( met_px_jesUp,   met_py_jesUp   ) = ( {}, {} )
            ( met_px_jesDown, met_py_jesDown ) = ( {}, {} )
            for jesUncertainty in self.jesUncertainties:
                met_px_jesUp[jesUncertainty]   = met_px
                met_py_jesUp[jesUncertainty]   = met_py
                met_px_jesDown[jesUncertainty] = met_px
                met_py_jesDown[jesUncertainty] = met_py
        
        if self.doGroomed:
            jets_msdcorr_raw = []
            jets_msdcorr_nom = []
            jets_msdcorr_corr_JMR   = []
            jets_msdcorr_corr_JMS   = []
            jets_msdcorr_corr_PUPPI = []
            jets_msdcorr_jerUp   = []
            jets_msdcorr_jerDown = []
            jets_msdcorr_jmrUp   = []
            jets_msdcorr_jmrDown = []
            jets_msdcorr_jesUp   = {}
            jets_msdcorr_jesDown = {}
            jets_msdcorr_jmsUp   = []
            jets_msdcorr_jmsDown = []
            jets_msdcorr_tau21DDT_nom = []
            jets_msdcorr_tau21DDT_jerUp = []
            jets_msdcorr_tau21DDT_jerDown = []
            jets_msdcorr_tau21DDT_jmrUp = []
            jets_msdcorr_tau21DDT_jmrDown = []
            jets_msdcorr_tau21DDT_jmsUp = []
            jets_msdcorr_tau21DDT_jmsDown = []
            for jesUncertainty in self.jesUncertainties:
                jets_msdcorr_jesUp[jesUncertainty]   = []
                jets_msdcorr_jesDown[jesUncertainty] = []
        
        rho = getattr(event, self.rhoBranchName)
        
        # match reconstructed jets to generator level ones
        # (needed to evaluate JER scale factors and uncertainties)
        pairs = matchObjectCollection(jets, genJets)
        
        for jet in jets:
            #jet pt and mass corrections
            jet_pt=jet.pt
            jet_mass=jet.mass


            jet_L1.append(self.jetReCalibrator.getCorrection(jet,rho, corrector=self.jetReCalibrator.separateJetCorrectors["myL1"]))
            jet_L2L3.append(self.jetReCalibrator.getCorrection(jet,rho, corrector=self.jetReCalibrator.separateJetCorrectors["myL2L3"]))
            jet_LRes.append(self.jetReCalibrator.getCorrection(jet,rho, corrector=self.jetReCalibrator.separateJetCorrectors["myRes"]))

            #redo JECs if desired
            if hasattr(jet, "rawFactor"):
                jet_rawpt = jet_pt * (1 - jet.rawFactor)
                jet_rawmass = jet_mass * (1 - jet.rawFactor)
            else:
                jet_rawpt = -1.0 * jet_pt #If factor not present factor will be saved as -1
                jet_rawmass = -1.0 * jet_mass #If factor not present factor will be saved as -1
            if self.redoJEC :
                (jet_pt, jet_mass) = self.jetReCalibrator.correct(jet,rho)
                jet.pt = jet_pt
                jet.mass = jet_mass
            jets_pt_raw.append(jet_rawpt)
            jets_mass_raw.append(jet_rawmass)
            jets_corr_JEC.append(jet_pt/jet_rawpt)

            
            
            
            genJet = pairs[jet]
            if self.doGroomed:                
                genGroomedSubJets = genSubJetMatcher[genJet] if genJet != None else None
                genGroomedJet = genGroomedSubJets[0].p4() + genGroomedSubJets[1].p4() if genGroomedSubJets != None and len(genGroomedSubJets) >= 2 else None
                if jet.subJetIdx1 >= 0 and jet.subJetIdx2 >= 0 :
                    groomedP4 = subJets[ jet.subJetIdx1 ].p4() + subJets[ jet.subJetIdx2].p4() #check subjet jecs
                else :
                    groomedP4 = None
                
                # LC: Apply PUPPI SD mass correction https://github.com/cms-jet/PuppiSoftdropMassCorr/
                puppisd_genCorr = self.puppisd_corrGEN.Eval(jet.pt)
                if abs(jet.eta) <= 1.3:
                    puppisd_recoCorr = self.puppisd_corrRECO_cen.Eval(jet.pt)
                else:
                    puppisd_recoCorr = self.puppisd_corrRECO_for.Eval(jet.pt)
                
                puppisd_total = puppisd_genCorr * puppisd_recoCorr
                jets_msdcorr_corr_PUPPI.append(puppisd_total)
                if groomedP4 != None:
                    groomedP4.SetPtEtaPhiM(groomedP4.Perp(), groomedP4.Eta(), groomedP4.Phi(), groomedP4.M()*puppisd_total)
            
            # evaluate JER scale factors and uncertainties
            # (cf. https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution and https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyResolution )
            ( jet_pt_jerNomVal, jet_pt_jerUpVal, jet_pt_jerDownVal ) = self.jetSmearer.getSmearValsPt(jet, genJet, rho)
            jets_corr_JER.append(jet_pt_jerNomVal)
            
            jet_pt_nom           = jet_pt_jerNomVal *jet_pt
            if jet_pt_nom < 0.0:
                jet_pt_nom *= -1.0
            jet_pt_jerUp         = jet_pt_jerUpVal  *jet_pt
            jet_pt_jerDown       = jet_pt_jerDownVal*jet_pt
            jets_pt_nom    .append(jet_pt_nom)
            jets_pt_jerUp  .append(jet_pt_jerUpVal*jet_pt)
            jets_pt_jerDown.append(jet_pt_jerDownVal*jet_pt)

            # evaluate JES uncertainties
            jet_pt_jesUp   = {}
            jet_pt_jesDown = {}
            jet_mass_jesUp   = {}
            jet_mass_jesDown = {}
            jet_mass_jmsUp   = []
            jet_mass_jmsDown = []
            
            # Evaluate JMS and JMR scale factors and uncertainties
            jmsNomVal = self.jmsVals[0]
            jmsDownVal = self.jmsVals[1]
            jmsUpVal = self.jmsVals[2]
            ( jet_mass_jmrNomVal, jet_mass_jmrUpVal, jet_mass_jmrDownVal ) = self.jetSmearer.getSmearValsM(jet, genJet)
            jets_corr_JMS   .append(jmsNomVal)
            jets_corr_JMR   .append(jet_mass_jmrNomVal)

            jet_mass_nom           = jet_pt_jerNomVal*jet_mass_jmrNomVal*jmsNomVal*jet_mass
            if jet_mass_nom < 0.0:
                jet_mass_nom *= -1.0
            jets_mass_nom    .append(jet_mass_nom)
            jets_mass_jerUp  .append(jet_pt_jerUpVal  *jet_mass_jmrNomVal *jmsNomVal  *jet_mass)
            jets_mass_jerDown.append(jet_pt_jerDownVal*jet_mass_jmrNomVal *jmsNomVal  *jet_mass)
            jets_mass_jmrUp  .append(jet_pt_jerNomVal *jet_mass_jmrUpVal  *jmsNomVal  *jet_mass)
            jets_mass_jmrDown.append(jet_pt_jerNomVal *jet_mass_jmrDownVal*jmsNomVal  *jet_mass)
            jets_mass_jmsUp  .append(jet_pt_jerNomVal *jet_mass_jmrNomVal *jmsUpVal   *jet_mass)
            jets_mass_jmsDown.append(jet_pt_jerNomVal *jet_mass_jmrNomVal *jmsDownVal *jet_mass)

            if self.doGroomed :
                # evaluate JES uncertainties
                jet_msdcorr_jesUp   = {}
                jet_msdcorr_jesDown = {}

                # Evaluate JMS and JMR scale factors and uncertainties
                ( jet_msdcorr_jmrNomVal, jet_msdcorr_jmrUpVal, jet_msdcorr_jmrDownVal ) = self.jetSmearer.getSmearValsM(groomedP4, genGroomedJet) if groomedP4 != None and genGroomedJet != None else (0.,0.,0.)
                jet_msdcorr_raw = groomedP4.M() if groomedP4 != None else 0.0
                jets_msdcorr_corr_JMS.append(jmsNomVal)
                jets_msdcorr_corr_JMR.append(jet_msdcorr_jmrNomVal)

                if jet_msdcorr_raw < 0.0:
                    jet_msdcorr_raw *= -1.0
                jet_msdcorr_nom           = jet_pt_jerNomVal*jet_msdcorr_jmrNomVal*jmsNomVal*jet_msdcorr_raw
                jets_msdcorr_raw    .append(jet_msdcorr_raw) #fix later so jec's not applied - LC: Current PUPPI SD mass correction implementation needs the JECs applied before looking up the correction so make sure that's accounted for if this is changed.
                jets_msdcorr_nom    .append(jet_msdcorr_nom)
                jets_msdcorr_jerUp  .append(jet_pt_jerUpVal  *jet_msdcorr_jmrNomVal *jmsNomVal  *jet_msdcorr_raw)
                jets_msdcorr_jerDown.append(jet_pt_jerDownVal*jet_msdcorr_jmrNomVal *jmsNomVal  *jet_msdcorr_raw)
                jets_msdcorr_jmrUp  .append(jet_pt_jerNomVal *jet_msdcorr_jmrUpVal  *jmsNomVal  *jet_msdcorr_raw)
                jets_msdcorr_jmrDown.append(jet_pt_jerNomVal *jet_msdcorr_jmrDownVal*jmsNomVal  *jet_msdcorr_raw)
                jets_msdcorr_jmsUp  .append(jet_pt_jerNomVal *jet_msdcorr_jmrNomVal *jmsUpVal   *jet_msdcorr_raw)
                jets_msdcorr_jmsDown.append(jet_pt_jerNomVal *jet_msdcorr_jmrNomVal *jmsDownVal *jet_msdcorr_raw)

                #Also evaluated JMS&JMR SD corr in tau21DDT region: https://twiki.cern.ch/twiki/bin/viewauth/CMS/JetWtagging#tau21DDT_0_43
                if self.era in ["2016"]:
                    jmstau21DDTNomVal = 1.014
                    jmstau21DDTDownVal = 1.007
                    jmstau21DDTUpVal = 1.021
                    self.jetSmearer.jmr_vals = [1.086,1.176,0.996]
                elif self.era in ["2017","2018"]:
                    jmstau21DDTNomVal = 0.983
                    jmstau21DDTDownVal = 0.976
                    jmstau21DDTUpVal = 0.99
                    self.jetSmearer.jmr_vals = [1.080,1.161,0.999]

                ( jet_msdcorr_tau21DDT_jmrNomVal, jet_msdcorr_tau21DDT_jmrUpVal, jet_msdcorr_tau21DDT_jmrDownVal ) = self.jetSmearer.getSmearValsM(groomedP4, genGroomedJet) if groomedP4 != None and genGroomedJet != None else (0.,0.,0.)
                jet_msdcorr_tau21DDT_nom           = jet_pt_jerNomVal*jet_msdcorr_tau21DDT_jmrNomVal*jmstau21DDTNomVal*jet_msdcorr_raw
                jets_msdcorr_tau21DDT_nom    .append(jet_msdcorr_tau21DDT_nom)
                jets_msdcorr_tau21DDT_jerUp  .append(jet_pt_jerUpVal  *jet_msdcorr_tau21DDT_jmrNomVal *jmstau21DDTNomVal  *jet_msdcorr_raw)
                jets_msdcorr_tau21DDT_jerDown.append(jet_pt_jerDownVal*jet_msdcorr_tau21DDT_jmrNomVal *jmstau21DDTNomVal  *jet_msdcorr_raw)
                jets_msdcorr_tau21DDT_jmrUp  .append(jet_pt_jerNomVal *jet_msdcorr_tau21DDT_jmrUpVal  *jmstau21DDTNomVal  *jet_msdcorr_raw)
                jets_msdcorr_tau21DDT_jmrDown.append(jet_pt_jerNomVal *jet_msdcorr_tau21DDT_jmrDownVal*jmstau21DDTNomVal  *jet_msdcorr_raw)
                jets_msdcorr_tau21DDT_jmsUp  .append(jet_pt_jerNomVal *jet_msdcorr_tau21DDT_jmrNomVal *jmstau21DDTUpVal   *jet_msdcorr_raw)
                jets_msdcorr_tau21DDT_jmsDown.append(jet_pt_jerNomVal *jet_msdcorr_tau21DDT_jmrNomVal *jmstau21DDTDownVal *jet_msdcorr_raw)

                #Restore original jmr_vals in jetSmearer
                self.jetSmearer.jmr_vals = self.jmrVals
            
            for jesUncertainty in self.jesUncertainties:
                # (cf. https://twiki.cern.ch/twiki/bin/view/CMSPublic/WorkBookJetEnergyCorrections#JetCorUncertainties )
                self.jesUncertainty[jesUncertainty].setJetPt(jet_pt_nom)
                self.jesUncertainty[jesUncertainty].setJetEta(jet.eta)
                delta = self.jesUncertainty[jesUncertainty].getUncertainty(True)
                jet_pt_jesUp[jesUncertainty]   = jet_pt_nom*(1. + delta)
                jet_pt_jesDown[jesUncertainty] = jet_pt_nom*(1. - delta)
                jets_pt_jesUp[jesUncertainty].append(jet_pt_jesUp[jesUncertainty])
                jets_pt_jesDown[jesUncertainty].append(jet_pt_jesDown[jesUncertainty])
                jet_mass_jesUp   [jesUncertainty] = jet_mass_nom*(1. + delta)
                jet_mass_jesDown [jesUncertainty] = jet_mass_nom*(1. - delta)
                jets_mass_jesUp  [jesUncertainty].append(jet_mass_jesUp[jesUncertainty])
                jets_mass_jesDown[jesUncertainty].append(jet_mass_jesDown[jesUncertainty])
                if self.doGroomed :
                    jet_msdcorr_jesUp   [jesUncertainty] = jet_msdcorr_nom*(1. + delta)
                    jet_msdcorr_jesDown [jesUncertainty] = jet_msdcorr_nom*(1. - delta)
                    jets_msdcorr_jesUp  [jesUncertainty].append(jet_msdcorr_jesUp[jesUncertainty])
                    jets_msdcorr_jesDown[jesUncertainty].append(jet_msdcorr_jesDown[jesUncertainty])


            # propagate JER and JES corrections and uncertainties to MET
            if self.corrMET and jet_pt_nom > self.unclEnThreshold:
                jet_cosPhi = math.cos(jet.phi)
                jet_sinPhi = math.sin(jet.phi)
                met_px_nom = met_px_nom - (jet_pt_nom - jet_pt)*jet_cosPhi
                met_py_nom = met_py_nom - (jet_pt_nom - jet_pt)*jet_sinPhi
                met_px_jerUp   = met_px_jerUp   - (jet_pt_jerUp   - jet_pt_nom)*jet_cosPhi
                met_py_jerUp   = met_py_jerUp   - (jet_pt_jerUp   - jet_pt_nom)*jet_sinPhi
                met_px_jerDown = met_px_jerDown - (jet_pt_jerDown - jet_pt_nom)*jet_cosPhi
                met_py_jerDown = met_py_jerDown - (jet_pt_jerDown - jet_pt_nom)*jet_sinPhi
                for jesUncertainty in self.jesUncertainties:
                    met_px_jesUp[jesUncertainty]   = met_px_jesUp[jesUncertainty]   - (jet_pt_jesUp[jesUncertainty]   - jet_pt_nom)*jet_cosPhi
                    met_py_jesUp[jesUncertainty]   = met_py_jesUp[jesUncertainty]   - (jet_pt_jesUp[jesUncertainty]   - jet_pt_nom)*jet_sinPhi
                    met_px_jesDown[jesUncertainty] = met_px_jesDown[jesUncertainty] - (jet_pt_jesDown[jesUncertainty] - jet_pt_nom)*jet_cosPhi
                    met_py_jesDown[jesUncertainty] = met_py_jesDown[jesUncertainty] - (jet_pt_jesDown[jesUncertainty] - jet_pt_nom)*jet_sinPhi

        # propagate "unclustered energy" uncertainty to MET
        if self.corrMET :
            ( met_px_unclEnUp,   met_py_unclEnUp   ) = ( met_px, met_py )
            ( met_px_unclEnDown, met_py_unclEnDown ) = ( met_px, met_py )
            met_deltaPx_unclEn = getattr(event, self.metBranchName + "_MetUnclustEnUpDeltaX")
            met_deltaPy_unclEn = getattr(event, self.metBranchName + "_MetUnclustEnUpDeltaY")
            met_px_unclEnUp    = met_px_unclEnUp   + met_deltaPx_unclEn
            met_py_unclEnUp    = met_py_unclEnUp   + met_deltaPy_unclEn
            met_px_unclEnDown  = met_px_unclEnDown - met_deltaPx_unclEn
            met_py_unclEnDown  = met_py_unclEnDown - met_deltaPy_unclEn

            # propagate effect of jet energy smearing to MET           
            met_px_jerUp   = met_px_jerUp   + (met_px_nom - met_px)
            met_py_jerUp   = met_py_jerUp   + (met_py_nom - met_py)
            met_px_jerDown = met_px_jerDown + (met_px_nom - met_px)
            met_py_jerDown = met_py_jerDown + (met_py_nom - met_py)
            for jesUncertainty in self.jesUncertainties:
                met_px_jesUp[jesUncertainty]   = met_px_jesUp[jesUncertainty]   + (met_px_nom - met_px)
                met_py_jesUp[jesUncertainty]   = met_py_jesUp[jesUncertainty]   + (met_py_nom - met_py)
                met_px_jesDown[jesUncertainty] = met_px_jesDown[jesUncertainty] + (met_px_nom - met_px)
                met_py_jesDown[jesUncertainty] = met_py_jesDown[jesUncertainty] + (met_py_nom - met_py)
            met_px_unclEnUp    = met_px_unclEnUp   + (met_px_nom - met_px)
            met_py_unclEnUp    = met_py_unclEnUp   + (met_py_nom - met_py)
            met_px_unclEnDown  = met_px_unclEnDown + (met_px_nom - met_px)
            met_py_unclEnDown  = met_py_unclEnDown + (met_py_nom - met_py)

        self.out.fillBranch("%s_pt_raw" % self.jetBranchName, jets_pt_raw)
        self.out.fillBranch("%s_pt_nom" % self.jetBranchName, jets_pt_nom)
        self.out.fillBranch("%s_corr_JEC" % self.jetBranchName, jets_corr_JEC)
        self.out.fillBranch("%s_corr_JER" % self.jetBranchName, jets_corr_JER)
        self.out.fillBranch("%s_pt_jerUp" % self.jetBranchName, jets_pt_jerUp)
        self.out.fillBranch("%s_pt_jerDown" % self.jetBranchName, jets_pt_jerDown)
        self.out.fillBranch("%s_mass_raw" % self.jetBranchName, jets_mass_raw)
        self.out.fillBranch("%s_mass_nom" % self.jetBranchName, jets_mass_nom)
        self.out.fillBranch("%s_corr_JMS" % self.jetBranchName, jets_corr_JMS)
        self.out.fillBranch("%s_corr_JMR" % self.jetBranchName, jets_corr_JMR)
        self.out.fillBranch("%s_mass_jerUp" % self.jetBranchName, jets_mass_jerUp)
        self.out.fillBranch("%s_mass_jerDown" % self.jetBranchName, jets_mass_jerDown)
        self.out.fillBranch("%s_mass_jmrUp" % self.jetBranchName, jets_mass_jmrUp)
        self.out.fillBranch("%s_mass_jmrDown" % self.jetBranchName, jets_mass_jmrDown)
        self.out.fillBranch("%s_mass_jmsUp" % self.jetBranchName, jets_mass_jmsUp)
        self.out.fillBranch("%s_mass_jmsDown" % self.jetBranchName, jets_mass_jmsDown)

        self.out.fillBranch("%s_L1" % self.jetBranchName, jet_L1)
        self.out.fillBranch("%s_L2L3" % self.jetBranchName, jet_L2L3)
        self.out.fillBranch("%s_LRes" % self.jetBranchName, jet_LRes)

        
        if self.doGroomed :
            self.out.fillBranch("%s_msoftdrop_raw" % self.jetBranchName, jets_msdcorr_raw)
            self.out.fillBranch("%s_msoftdrop_nom" % self.jetBranchName, jets_msdcorr_nom)
            self.out.fillBranch("%s_msoftdrop_corr_JMS" % self.jetBranchName, jets_msdcorr_corr_JMS)
            self.out.fillBranch("%s_msoftdrop_corr_JMR" % self.jetBranchName, jets_msdcorr_corr_JMR)
            self.out.fillBranch("%s_msoftdrop_jerUp" % self.jetBranchName, jets_msdcorr_jerUp)
            self.out.fillBranch("%s_msoftdrop_jerDown" % self.jetBranchName, jets_msdcorr_jerDown)
            self.out.fillBranch("%s_msoftdrop_corr_PUPPI" % self.jetBranchName, jets_msdcorr_corr_PUPPI)
            self.out.fillBranch("%s_msoftdrop_jmrUp" % self.jetBranchName, jets_msdcorr_jmrUp)
            self.out.fillBranch("%s_msoftdrop_jmrDown" % self.jetBranchName, jets_msdcorr_jmrDown)
            self.out.fillBranch("%s_msoftdrop_jmsUp" % self.jetBranchName, jets_msdcorr_jmsUp)
            self.out.fillBranch("%s_msoftdrop_jmsDown" % self.jetBranchName, jets_msdcorr_jmsDown)
            self.out.fillBranch("%s_msoftdrop_tau21DDT_nom" % self.jetBranchName, jets_msdcorr_tau21DDT_nom)
            self.out.fillBranch("%s_msoftdrop_tau21DDT_jerUp" % self.jetBranchName, jets_msdcorr_tau21DDT_jerUp)
            self.out.fillBranch("%s_msoftdrop_tau21DDT_jerDown" % self.jetBranchName, jets_msdcorr_tau21DDT_jerDown)
            self.out.fillBranch("%s_msoftdrop_tau21DDT_jmrUp" % self.jetBranchName, jets_msdcorr_tau21DDT_jmrUp)
            self.out.fillBranch("%s_msoftdrop_tau21DDT_jmrDown" % self.jetBranchName, jets_msdcorr_tau21DDT_jmrDown)
            self.out.fillBranch("%s_msoftdrop_tau21DDT_jmsUp" % self.jetBranchName, jets_msdcorr_tau21DDT_jmsUp)
            self.out.fillBranch("%s_msoftdrop_tau21DDT_jmsDown" % self.jetBranchName, jets_msdcorr_tau21DDT_jmsDown)

            
        if self.corrMET :
            self.out.fillBranch("%s_pt_nom" % self.metBranchName, math.sqrt(met_px_nom**2 + met_py_nom**2))
            self.out.fillBranch("%s_phi_nom" % self.metBranchName, math.atan2(met_py_nom, met_px_nom))        
            self.out.fillBranch("%s_pt_jerUp" % self.metBranchName, math.sqrt(met_px_jerUp**2 + met_py_jerUp**2))
            self.out.fillBranch("%s_phi_jerUp" % self.metBranchName, math.atan2(met_py_jerUp, met_px_jerUp))        
            self.out.fillBranch("%s_pt_jerDown" % self.metBranchName, math.sqrt(met_px_jerDown**2 + met_py_jerDown**2))
            self.out.fillBranch("%s_phi_jerDown" % self.metBranchName, math.atan2(met_py_jerDown, met_px_jerDown))
            
        for jesUncertainty in self.jesUncertainties:
            self.out.fillBranch("%s_pt_jes%sUp" % (self.jetBranchName, jesUncertainty), jets_pt_jesUp[jesUncertainty])
            self.out.fillBranch("%s_pt_jes%sDown" % (self.jetBranchName, jesUncertainty), jets_pt_jesDown[jesUncertainty])
            self.out.fillBranch("%s_mass_jes%sUp" % (self.jetBranchName, jesUncertainty), jets_mass_jesUp[jesUncertainty])
            self.out.fillBranch("%s_mass_jes%sDown" % (self.jetBranchName, jesUncertainty), jets_mass_jesDown[jesUncertainty])
            
            if self.doGroomed : 
                self.out.fillBranch("%s_msoftdrop_jes%sUp" % (self.jetBranchName, jesUncertainty), jets_msdcorr_jesUp[jesUncertainty])
                self.out.fillBranch("%s_msoftdrop_jes%sDown" % (self.jetBranchName, jesUncertainty), jets_msdcorr_jesDown[jesUncertainty])
                
            
            if self.corrMET:
                self.out.fillBranch("%s_pt_jes%sUp" % (self.metBranchName, jesUncertainty), math.sqrt(met_px_jesUp[jesUncertainty]**2 + met_py_jesUp[jesUncertainty]**2))
                self.out.fillBranch("%s_phi_jes%sUp" % (self.metBranchName, jesUncertainty), math.atan2(met_py_jesUp[jesUncertainty], met_px_jesUp[jesUncertainty]))
                self.out.fillBranch("%s_pt_jes%sDown" % (self.metBranchName, jesUncertainty), math.sqrt(met_px_jesDown[jesUncertainty]**2 + met_py_jesDown[jesUncertainty]**2))
                self.out.fillBranch("%s_phi_jes%sDown" % (self.metBranchName, jesUncertainty), math.atan2(met_py_jesDown[jesUncertainty], met_px_jesDown[jesUncertainty]))
        if self.corrMET:
            self.out.fillBranch("%s_pt_unclustEnUp" % self.metBranchName, math.sqrt(met_px_unclEnUp**2 + met_py_unclEnUp**2))
            self.out.fillBranch("%s_phi_unclustEnUp" % self.metBranchName, math.atan2(met_py_unclEnUp, met_px_unclEnUp))
            self.out.fillBranch("%s_pt_unclustEnDown" % self.metBranchName, math.sqrt(met_px_unclEnDown**2 + met_py_unclEnDown**2))
            self.out.fillBranch("%s_phi_unclustEnDown" % self.metBranchName, math.atan2(met_py_unclEnDown, met_px_unclEnDown))

        return True