예제 #1
0
class JetAnalyzer(Analyzer):
    def beginLoop(self, setup):
        super(JetAnalyzer, self).beginLoop(setup)
        if self.cfg_ana.do_jec:
            global_tag = self.cfg_ana.gt_mc
            if not self.cfg_comp.isMC:
                global_tag = self.cfg_comp.dataGT

            do_residual = not self.cfg_comp.isMC
            from PhysicsTools.Heppy.physicsutils.JetReCalibrator import JetReCalibrator
            self.jet_calibrator = JetReCalibrator(
                global_tag,
                'AK4PFchs',
                do_residual,
                jecPath=os.path.expandvars(
                    "${CMSSW_BASE}/src/CMGTools/RootTools/data/jec"),
                calculateType1METCorrection=True)
        self.counters.addCounter('JetAnalyzer')
        count = self.counters.counter('JetAnalyzer')
        count.register('all events')
        count.register('at least 2 good jets')
        count.register('at least 2 clean jets')

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

        self.handles['jets'] = AutoHandle(self.cfg_ana.jets,
                                          'std::vector<pat::Jet>')

    def process(self, event):
        self.readCollections(event.input)
        jets = self.handles['jets'].product()
        output_jets = []
        if self.cfg_ana.year == '2016':
            for jet in jets:
                hjet = Jet(jet)
                output_jets.append(hjet)
        else:
            for jet in jets:
                hjet = Jet(jet)
                if not hasattr(self.cfg_ana, 'selection'):
                    continue
                elif self.cfg_ana.selection(hjet):
                    output_jets.append(hjet)

        if self.cfg_ana.do_jec:
            event.metShift = [0., 0.]
            event.type1METCorr = [0., 0., 0.]
            self.jet_calibrator.correctAll(output_jets,
                                           event.rho,
                                           delta=0.,
                                           addCorr=True,
                                           addShifts=True,
                                           metShift=event.metShift,
                                           type1METCorr=event.type1METCorr)
        setattr(event, self.cfg_ana.output, output_jets)
예제 #2
0
class JetAnalyzer(Analyzer):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,
                                           'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(
            self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        self.addJECShifts = self.cfg_ana.addJECShifts if hasattr(
            self.cfg_ana, 'addJECShifts') else 0
        if self.recalibrateJets == "MC":
            self.recalibrateJets = self.cfg_comp.isMC
        elif self.recalibrateJets == "Data":
            self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True, False]:
            raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets

        calculateSeparateCorrections = getattr(cfg_ana,
                                               "calculateSeparateCorrections",
                                               False)
        calculateType1METCorrection = getattr(cfg_ana,
                                              "calculateType1METCorrection",
                                              False)
        self.doJEC = self.recalibrateJets or (
            self.shiftJEC != 0
        ) or self.addJECShifts or calculateSeparateCorrections or calculateType1METCorrection
        if self.doJEC:
            doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
            if doResidual == "MC": doResidual = self.cfg_comp.isMC
            elif doResidual == "Data": doResidual = not self.cfg_comp.isMC
            elif doResidual not in [True, False]:
                raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}"
            GT = getattr(cfg_comp, 'jecGT',
                         mcGT if self.cfg_comp.isMC else dataGT)
            # Now take care of the optional arguments
            kwargs = {
                'calculateSeparateCorrections': calculateSeparateCorrections,
                'calculateType1METCorrection': calculateType1METCorrection,
            }
            if kwargs['calculateType1METCorrection']:
                kwargs['type1METParams'] = cfg_ana.type1METParams
            # instantiate the jet re-calibrator
            self.jetReCalibrator = JetReCalibrator(GT,
                                                   cfg_ana.recalibrationType,
                                                   doResidual, cfg_ana.jecPath,
                                                   **kwargs)
        self.doPuId = getattr(self.cfg_ana, 'doPuId', True)
        self.jetLepDR = getattr(self.cfg_ana, 'jetLepDR', 0.4)
        self.jetLepArbitration = getattr(self.cfg_ana, 'jetLepArbitration',
                                         lambda jet, lepton: lepton)
        self.lepPtMin = getattr(self.cfg_ana, 'minLepPt', -1)
        self.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep: True)
        self.jetGammaDR = getattr(self.cfg_ana, 'jetGammaDR', 0.4)
        self.jetGammaLepDR = getattr(self.cfg_ana, 'jetGammaLepDR', 0.4)
        self.cleanFromLepAndGammaSimultaneously = getattr(
            self.cfg_ana, 'cleanFromLepAndGammaSimultaneously', False)
        if self.cleanFromLepAndGammaSimultaneously:
            if hasattr(self.cfg_ana, 'jetGammaLepDR'):
                self.jetGammaLepDR = self.jetGammaLepDR
            elif (self.jetGammaDR == self.jetLepDR):
                self.jetGammaLepDR = self.jetGammaDR
            else:
                raise RuntimeError, "DR for simultaneous cleaning of jets from leptons and photons is not defined, and dR(gamma, jet)!=dR(lep, jet)"
        if (self.cfg_ana.doQG):
            qgdefname = "{CMSSW_BASE}/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_13TeV_v2b.root"
            self.qglcalc = QGLikelihoodCalculator(
                getattr(self.cfg_ana, "QGpath",
                        qgdefname).format(CMSSW_BASE=os.environ['CMSSW_BASE']))
        if not hasattr(self.cfg_ana, "collectionPostFix"):
            self.cfg_ana.collectionPostFix = ""

    def declareHandles(self):
        super(JetAnalyzer, self).declareHandles()
        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol,
                                          'std::vector<pat::Jet>')
        self.handles['genJet'] = AutoHandle(self.cfg_ana.genJetCol,
                                            'vector<reco::GenJet>')
        self.shiftJER = self.cfg_ana.shiftJER if hasattr(
            self.cfg_ana, 'shiftJER') else 0
        self.addJERShifts = self.cfg_ana.addJERShifts if hasattr(
            self.cfg_ana, 'addJERShifts') else 0
        self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double')

    def beginLoop(self, setup):
        super(JetAnalyzer, self).beginLoop(setup)

    def process(self, event):
        self.readCollections(event.input)
        rho = float(self.handles['rho'].product()[0])
        self.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        if self.cfg_ana.copyJetsByValue:
            import ROOT
            #from ROOT.heppy import JetUtils
            allJets = map(
                lambda j: Jet(ROOT.heppy.JetUtils.copyJet(j)),
                self.handles['jets'].product(
                ))  #copy-by-value is safe if JetAnalyzer is ran more than once
        else:
            allJets = map(Jet, self.handles['jets'].product())

        #set dummy MC flavour for all jets in case we want to ntuplize discarded jets later
        for jet in allJets:
            jet.mcFlavour = 0

        self.deltaMetFromJEC = [0., 0.]
        self.type1METCorr = [0., 0., 0.]
        #        print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]
        if self.doJEC:
            if not self.recalibrateJets:  # check point that things won't change
                jetsBefore = [(j.pt(), j.eta(), j.phi(), j.rawFactor())
                              for j in allJets]
            self.jetReCalibrator.correctAll(allJets,
                                            rho,
                                            delta=self.shiftJEC,
                                            addCorr=True,
                                            addShifts=self.addJECShifts,
                                            metShift=self.deltaMetFromJEC,
                                            type1METCorr=self.type1METCorr)
            if not self.recalibrateJets:
                jetsAfter = [(j.pt(), j.eta(), j.phi(), j.rawFactor())
                             for j in allJets]
                if len(jetsBefore) != len(jetsAfter):
                    print "ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % (
                        jetsBefore, jetsAfter)
                else:
                    for (told, tnew) in zip(jetsBefore, jetsAfter):
                        if (deltaR2(told[1], told[2], tnew[1],
                                    tnew[2])) > 0.0001:
                            print "ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % (
                                told, tnew)
                        elif abs(told[0] - tnew[0]) / (
                                told[0] + tnew[0]) > 0.5e-3 or abs(
                                    told[3] - tnew[3]) > 0.5e-3:
                            print "ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % (
                                told, tnew)
        self.allJetsUsedForMET = allJets
        #        print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]

        if self.cfg_comp.isMC:
            self.genJets = [x for x in self.handles['genJet'].product()]
            if self.cfg_ana.do_mc_match:
                for igj, gj in enumerate(self.genJets):
                    gj.index = igj
#                self.matchJets(event, allJets)
                self.matchJets(
                    event, [j for j in allJets if j.pt() > self.cfg_ana.jetPt
                            ])  # To match only jets above chosen threshold
            if getattr(self.cfg_ana, 'smearJets', False):
                self.smearJets(event, allJets)

##Sort Jets by pT
        allJets.sort(key=lambda j: j.pt(), reverse=True)

        leptons = []
        if hasattr(event, 'selectedLeptons'):
            leptons = [
                l for l in event.selectedLeptons
                if l.pt() > self.lepPtMin and self.lepSelCut(l)
            ]
        if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'):
            leptons = leptons[:] + event.selectedTaus
        if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(
                event, 'selectedIsoCleanTrack'):
            leptons = leptons[:] + event.selectedIsoCleanTrack

## Apply jet selection
        self.jets = []
        self.jetsFailId = []
        self.jetsAllNoID = []
        self.jetsIdOnly = []
        for jet in allJets:
            #Check if lepton and jet have overlapping PF candidates
            leps_with_overlaps = []
            if getattr(self.cfg_ana, 'checkLeptonPFOverlap', True):
                for i in range(jet.numberOfSourceCandidatePtrs()):
                    p1 = jet.sourceCandidatePtr(i)  #Ptr<Candidate> p1
                    for lep in leptons:
                        for j in range(lep.numberOfSourceCandidatePtrs()):
                            p2 = lep.sourceCandidatePtr(j)
                            has_overlaps = p1.key() == p2.key() and p1.refCore(
                            ).id().productIndex() == p2.refCore().id(
                            ).productIndex() and p1.refCore().id(
                            ).processIndex() == p2.refCore().id().processIndex(
                            )
                            if has_overlaps:
                                leps_with_overlaps += [lep]
            if len(leps_with_overlaps) > 0:
                for lep in leps_with_overlaps:
                    lep.jetOverlap = jet
            if self.testJetNoID(jet):
                self.jetsAllNoID.append(jet)
                if (self.cfg_ana.doQG):
                    jet.qgl_calc = self.qglcalc.computeQGLikelihood
                    jet.qgl_rho = rho
                if self.testJetID(jet):
                    self.jets.append(jet)
                    self.jetsIdOnly.append(jet)
                else:
                    self.jetsFailId.append(jet)
            elif self.testJetID(jet):
                self.jetsIdOnly.append(jet)

        jetsEtaCut = [
            j for j in self.jets if abs(j.eta()) < self.cfg_ana.jetEta
        ]
        self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(
            jetsEtaCut, leptons, self.jetLepDR, self.jetLepArbitration)

        self.cleanJets = [
            j for j in self.cleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        self.cleanJetsFwd = [
            j for j in self.cleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]
        self.discardedJets = [
            j for j in self.jets if j not in self.cleanJetsAll
        ]
        if hasattr(event,
                   'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons:
            event.discardedLeptons = [
                l for l in leptons if l not in cleanLeptons
            ]
            event.selectedLeptons = [
                l for l in event.selectedLeptons
                if l not in event.discardedLeptons
            ]
        for lep in leptons:
            if hasattr(lep, "jetOverlap"):
                if lep.jetOverlap in self.cleanJetsAll:
                    #print "overlap reco", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi()
                    lep.jetOverlapIdx = self.cleanJetsAll.index(lep.jetOverlap)
                elif lep.jetOverlap in self.discardedJets:
                    #print "overlap discarded", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi()
                    lep.jetOverlapIdx = 1000 + self.discardedJets.index(
                        lep.jetOverlap)

        ## First cleaning, then Jet Id
        self.noIdCleanJetsAll, cleanLeptons = cleanJetsAndLeptons(
            self.jetsAllNoID, leptons, self.jetLepDR, self.jetLepArbitration)
        self.noIdCleanJets = [
            j for j in self.noIdCleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        self.noIdCleanJetsFwd = [
            j for j in self.noIdCleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]
        self.noIdDiscardedJets = [
            j for j in self.jetsAllNoID if j not in self.noIdCleanJetsAll
        ]

        ## Clean Jets from photons (first cleaning, then Jet Id)
        photons = []
        if hasattr(event, 'selectedPhotons'):
            if self.cfg_ana.cleanJetsFromFirstPhoton:
                photons = event.selectedPhotons[:1]
            else:
                photons = [g for g in event.selectedPhotons]

        self.gamma_cleanJetaAll = []
        self.gamma_noIdCleanJetsAll = []

        if self.cleanFromLepAndGammaSimultaneously:
            self.gamma_cleanJetsAll = cleanNearestJetOnly(
                jetsEtaCut, photons + leptons, self.jetGammaLepDR)
            self.gamma_noIdCleanJetsAll = cleanNearestJetOnly(
                self.jetsAllNoID, photons + leptons, self.jetGammaLepDR)
        else:
            self.gamma_cleanJetsAll = cleanNearestJetOnly(
                self.cleanJetsAll, photons, self.jetGammaDR)
            self.gamma_noIdCleanJetsAll = cleanNearestJetOnly(
                self.noIdCleanJetsAll, photons, self.jetGammaDR)

        self.gamma_cleanJets = [
            j for j in self.gamma_cleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        self.gamma_cleanJetsFwd = [
            j for j in self.gamma_cleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]

        self.gamma_noIdCleanJets = [
            j for j in self.gamma_noIdCleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        self.gamma_noIdCleanJetsFwd = [
            j for j in self.gamma_noIdCleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]
        ###

        if self.cfg_ana.alwaysCleanPhotons:
            self.cleanJets = self.gamma_cleanJets
            self.cleanJetsAll = self.gamma_cleanJetsAll
            self.cleanJetsFwd = self.gamma_cleanJetsFwd
            #
            self.noIdCleanJets = self.gamma_noIdCleanJets
            self.noIdCleanJetsAll = self.gamma_noIdCleanJetsAll
            self.noIdCleanJetsFwd = self.gamma_noIdCleanJetsFwd

        ## Jet Id, after jet/lepton cleaning
        self.cleanJetsFailIdAll = []
        for jet in self.noIdCleanJetsAll:
            if not self.testJetID(jet):
                self.cleanJetsFailIdAll.append(jet)

        self.cleanJetsFailId = [
            j for j in self.cleanJetsFailIdAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]

        ## Jet Id, after jet/photon cleaning
        self.gamma_cleanJetsFailIdAll = []
        for jet in self.gamma_noIdCleanJetsAll:
            if not self.testJetID(jet):
                self.gamma_cleanJetsFailIdAll.append(jet)

        self.gamma_cleanJetsFailId = [
            j for j in self.gamma_cleanJetsFailIdAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]

        ## Associate jets to leptons
        incleptons = event.inclusiveLeptons if hasattr(
            event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection(incleptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet]
        for lep in incleptons:
            jet = jlpairs[lep]
            if jet is None:
                setattr(lep, "jet" + self.cfg_ana.collectionPostFix, lep)
            else:
                setattr(lep, "jet" + self.cfg_ana.collectionPostFix, jet)
        ## Associate jets to taus
        taus = getattr(event, 'selectedTaus', [])
        jtaupairs = matchObjectCollection(taus, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet]
        for tau in taus:
            setattr(tau, "jet" + self.cfg_ana.collectionPostFix,
                    jtaupairs[tau])

        #MC stuff
        if self.cfg_comp.isMC:
            self.deltaMetFromJetSmearing = [0, 0]
            for j in self.cleanJetsAll:
                if hasattr(j, 'deltaMetFromJetSmearing'):
                    self.deltaMetFromJetSmearing[
                        0] += j.deltaMetFromJetSmearing[0]
                    self.deltaMetFromJetSmearing[
                        1] += j.deltaMetFromJetSmearing[1]

            self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons,
                                                    self.jetLepDR)

            if self.cfg_ana.cleanGenJetsFromPhoton:
                self.cleanGenJets = cleanNearestJetOnly(
                    self.cleanGenJets, photons, self.jetLepDR)

            if getattr(self.cfg_ana, 'attachNeutrinos', True) and hasattr(
                    self.cfg_ana, "genNuSelection"):
                jetNus = [
                    x for x in event.genParticles
                    if abs(x.pdgId()) in [12, 14, 16]
                    and self.cfg_ana.genNuSelection(x)
                ]
                pairs = matchObjectCollection(jetNus, self.genJets, 0.4**2)

                for (nu, genJet) in pairs.iteritems():
                    if genJet is not None:
                        if not hasattr(genJet, "nu"):
                            genJet.nu = nu.p4()
                        else:
                            genJet.nu += nu.p4()

            if self.cfg_ana.do_mc_match:
                self.jetFlavour(event)

        if hasattr(event, "jets" + self.cfg_ana.collectionPostFix):
            raise RuntimeError(
                "Event already contains a jet collection with the following postfix: "
                + self.cfg_ana.collectionPostFix)
        setattr(event, "rho" + self.cfg_ana.collectionPostFix, self.rho)
        setattr(event, "deltaMetFromJEC" + self.cfg_ana.collectionPostFix,
                self.deltaMetFromJEC)
        setattr(event, "type1METCorr" + self.cfg_ana.collectionPostFix,
                self.type1METCorr)
        setattr(event, "allJetsUsedForMET" + self.cfg_ana.collectionPostFix,
                self.allJetsUsedForMET)
        setattr(event, "jets" + self.cfg_ana.collectionPostFix, self.jets)
        setattr(event, "jetsFailId" + self.cfg_ana.collectionPostFix,
                self.jetsFailId)
        setattr(event, "jetsAllNoID" + self.cfg_ana.collectionPostFix,
                self.jetsAllNoID)
        setattr(event, "jetsIdOnly" + self.cfg_ana.collectionPostFix,
                self.jetsIdOnly)
        setattr(event, "cleanJetsAll" + self.cfg_ana.collectionPostFix,
                self.cleanJetsAll)
        setattr(event, "cleanJets" + self.cfg_ana.collectionPostFix,
                self.cleanJets)
        setattr(event, "cleanJetsFwd" + self.cfg_ana.collectionPostFix,
                self.cleanJetsFwd)
        setattr(event, "cleanJetsFailIdAll" + self.cfg_ana.collectionPostFix,
                self.cleanJetsFailIdAll)
        setattr(event, "cleanJetsFailId" + self.cfg_ana.collectionPostFix,
                self.cleanJetsFailId)
        setattr(event, "discardedJets" + self.cfg_ana.collectionPostFix,
                self.discardedJets)
        setattr(event, "gamma_cleanJetsAll" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJetsAll)
        setattr(event, "gamma_cleanJets" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJets)
        setattr(event, "gamma_cleanJetsFwd" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJetsFwd)
        setattr(event,
                "gamma_cleanJetsFailIdAll" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJetsFailIdAll)
        setattr(event,
                "gamma_cleanJetsFailId" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJetsFailId)

        if self.cfg_comp.isMC:
            setattr(event,
                    "deltaMetFromJetSmearing" + self.cfg_ana.collectionPostFix,
                    self.deltaMetFromJetSmearing)
            setattr(event, "cleanGenJets" + self.cfg_ana.collectionPostFix,
                    self.cleanGenJets)
            setattr(event, "genJets" + self.cfg_ana.collectionPostFix,
                    self.genJets)
            if self.cfg_ana.do_mc_match:
                setattr(event, "bqObjects" + self.cfg_ana.collectionPostFix,
                        self.bqObjects)
                setattr(event, "cqObjects" + self.cfg_ana.collectionPostFix,
                        self.cqObjects)
                setattr(event, "partons" + self.cfg_ana.collectionPostFix,
                        self.partons)
                setattr(event,
                        "heaviestQCDFlavour" + self.cfg_ana.collectionPostFix,
                        self.heaviestQCDFlavour)

        return True

    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId()
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose')
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed and (jet.puJetIdPassed
                                          or not (self.doPuId))

    def testJetNoID(self, jet):
        # 2 is loose pile-up jet id
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta

    def jetFlavour(self, event):
        def isFlavour(x, f):
            id = abs(x.pdgId())
            if id > 999: return (id / 1000) % 10 == f
            if id > 99: return (id / 100) % 10 == f
            return id % 100 == f

        self.bqObjects = [
            p for p in event.genParticles
            if (p.status() == 2 and isFlavour(p, 5))
        ]
        self.cqObjects = [
            p for p in event.genParticles
            if (p.status() == 2 and isFlavour(p, 4))
        ]

        self.partons = [
            p for p in event.genParticles
            if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId()) > 0
                and (abs(p.pdgId()) in [1, 2, 3, 4, 5, 21]))
        ]
        match = matchObjectCollection2(self.cleanJetsAll,
                                       self.partons,
                                       deltaRMax=0.3)

        for jet in self.cleanJetsAll:
            parton = match[jet]
            jet.partonId = (parton.pdgId() if parton != None else 0)
            jet.partonMotherId = (parton.mother(0).pdgId() if parton != None
                                  and parton.numberOfMothers() > 0 else 0)

        for jet in self.jets:
            (bmatch, dr) = bestMatch(jet, self.bqObjects)
            if dr < 0.4:
                jet.mcFlavour = 5
            else:
                (cmatch, dr) = bestMatch(jet, self.cqObjects)
                if dr < 0.4:
                    jet.mcFlavour = 4
                else:
                    jet.mcFlavour = 0

        self.heaviestQCDFlavour = 5 if len(
            self.bqObjects) else (4 if len(self.cqObjects) else 1)

    def matchJets(self, event, jets):
        match = matchObjectCollection2(jets,
                                       event.genbquarks + event.genwzquarks,
                                       deltaRMax=0.3)
        for jet in jets:
            gen = match[jet]
            jet.mcParton = gen
            jet.mcMatchId = (gen.sourceId if gen != None else 0)
            jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0)

        match = matchObjectCollection2(jets, self.genJets, deltaRMax=0.3)
        for jet in jets:
            jet.mcJet = match[jet]

    def smearJets(self, event, jets):
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution
        for jet in jets:
            gen = jet.mcJet
            if gen != None:
                genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta())
                # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
                #8 TeV tables
                factor = shiftJERfactor(self.shiftJER, aeta)
                ptscale = max(0.0,
                              (jetpt + (factor - 1) * (jetpt - genpt)) / jetpt)
                #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale)
                jet.deltaMetFromJetSmearing = [
                    -(ptscale - 1) * jet.rawFactor() * jet.px(),
                    -(ptscale - 1) * jet.rawFactor() * jet.py()
                ]
                if ptscale != 0:
                    jet.setP4(jet.p4() * ptscale)
                    # leave the uncorrected unchanged for sync
                    jet.setRawFactor(jet.rawFactor() / ptscale)
            #else: print "jet with pt %.1d, eta %.2f is unmatched" % (jet.pt(), jet.eta())
                if (self.shiftJER == 0) and (self.addJERShifts):
                    setattr(jet, "corrJER", ptscale)
                    factorJERUp = shiftJERfactor(1, aeta)
                    ptscaleJERUp = max(0.0, (jetpt + (factorJERUp - 1) *
                                             (jetpt - genpt)) / jetpt)
                    setattr(jet, "corrJERUp", ptscaleJERUp)
                    factorJERDown = shiftJERfactor(-1, aeta)
                    ptscaleJERDown = max(0.0, (jetpt + (factorJERDown - 1) *
                                               (jetpt - genpt)) / jetpt)
                    setattr(jet, "corrJERDown", ptscaleJERDown)
예제 #3
0
class JetAnalyzer( Analyzer ):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName)
        mcGT   = cfg_ana.mcGT   if hasattr(cfg_ana,'mcGT')   else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        self.addJECShifts = self.cfg_ana.addJECShifts if hasattr(self.cfg_ana, 'addJECShifts') else 0
        if   self.recalibrateJets == "MC"  : self.recalibrateJets =     self.cfg_comp.isMC
        elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True,False]: raise RuntimeError("recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets)

        calculateSeparateCorrections = getattr(cfg_ana,"calculateSeparateCorrections", False);
        calculateType1METCorrection  = getattr(cfg_ana,"calculateType1METCorrection",  False);
        self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) or self.addJECShifts or calculateSeparateCorrections or calculateType1METCorrection
        if self.doJEC:
            doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
            if   doResidual == "MC":   doResidual = self.cfg_comp.isMC
            elif doResidual == "Data": doResidual = not self.cfg_comp.isMC
            elif doResidual not in [True,False]: raise RuntimeError("If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}")
            GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT)
            # Now take care of the optional arguments
            kwargs = { 'calculateSeparateCorrections':calculateSeparateCorrections,
                       'calculateType1METCorrection' :calculateType1METCorrection, }
            if kwargs['calculateType1METCorrection']: kwargs['type1METParams'] = cfg_ana.type1METParams
            # instantiate the jet re-calibrator
            self.jetReCalibrator = JetReCalibrator(GT, cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath, **kwargs)
        self.doPuId = getattr(self.cfg_ana, 'doPuId', True)
        self.jetLepDR = getattr(self.cfg_ana, 'jetLepDR', 0.4)
        self.jetLepArbitration = getattr(self.cfg_ana, 'jetLepArbitration', lambda jet,lepton: lepton) 
        self.lepPtMin = getattr(self.cfg_ana, 'minLepPt', -1)
        self.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep : True)
        self.jetGammaDR =  getattr(self.cfg_ana, 'jetGammaDR', 0.4)
        self.jetGammaLepDR =  getattr(self.cfg_ana, 'jetGammaLepDR', 0.4)
        self.cleanFromLepAndGammaSimultaneously = getattr(self.cfg_ana, 'cleanFromLepAndGammaSimultaneously', False)
        if self.cleanFromLepAndGammaSimultaneously:
            if hasattr(self.cfg_ana, 'jetGammaLepDR'):
                self.jetGammaLepDR =  self.jetGammaLepDR 
            elif (self.jetGammaDR == self.jetLepDR):
                self.jetGammaLepDR = self.jetGammaDR
            else:
                raise RuntimeError("DR for simultaneous cleaning of jets from leptons and photons is not defined, and dR(gamma, jet)!=dR(lep, jet)")
        if(self.cfg_ana.doQG):
            qgdefname="{CMSSW_BASE}/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_13TeV_v2b.root"
            self.qglcalc = QGLikelihoodCalculator(getattr(self.cfg_ana,"QGpath",qgdefname).format(CMSSW_BASE= os.environ['CMSSW_BASE']))
        if not hasattr(self.cfg_ana ,"collectionPostFix"):self.cfg_ana.collectionPostFix=""

    def declareHandles(self):
        super(JetAnalyzer, self).declareHandles()
        self.handles['jets']   = AutoHandle( self.cfg_ana.jetCol, 'std::vector<pat::Jet>' )
        self.handles['genJet'] = AutoHandle( self.cfg_ana.genJetCol, 'vector<reco::GenJet>' )
        self.shiftJER = self.cfg_ana.shiftJER if hasattr(self.cfg_ana, 'shiftJER') else 0
        self.addJERShifts = self.cfg_ana.addJERShifts if hasattr(self.cfg_ana, 'addJERShifts') else 0
        self.handles['rho'] = AutoHandle( self.cfg_ana.rho, 'double' )

    def beginLoop(self, setup):
        super(JetAnalyzer,self).beginLoop(setup)

    def process(self, event):
        self.readCollections( event.input )
        rho  = float(self.handles['rho'].product()[0])
        self.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        if self.cfg_ana.copyJetsByValue: 
            import ROOT
            #from ROOT.heppy import JetUtils
            allJets = map(lambda j:Jet(ROOT.heppy.JetUtils.copyJet(j)), self.handles['jets'].product())  #copy-by-value is safe if JetAnalyzer is ran more than once
        else: 
            allJets = map(Jet, self.handles['jets'].product()) 

        #set dummy MC flavour for all jets in case we want to ntuplize discarded jets later
        for jet in allJets:
            jet.mcFlavour = 0

        self.deltaMetFromJEC = [0.,0.]
        self.type1METCorr    = [0.,0.,0.]
#        print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]
        if self.doJEC:
            if not self.recalibrateJets:  # check point that things won't change
                jetsBefore = [ (j.pt(),j.eta(),j.phi(),j.rawFactor()) for j in allJets ]
            self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, 
                                                addCorr=True, addShifts=self.addJECShifts,
                                                metShift=self.deltaMetFromJEC, type1METCorr=self.type1METCorr )           
            if not self.recalibrateJets: 
                jetsAfter = [ (j.pt(),j.eta(),j.phi(),j.rawFactor()) for j in allJets ]
                if len(jetsBefore) != len(jetsAfter): 
                    print("ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % (jetsBefore,jetsAfter))
                else:
                    for (told, tnew) in zip(jetsBefore,jetsAfter):
                        if (deltaR2(told[1],told[2],tnew[1],tnew[2])) > 0.0001:
                            print("ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % (told, tnew))
                        elif abs(told[0]-tnew[0])/(told[0]+tnew[0]) > 0.5e-3 or abs(told[3]-tnew[3]) > 0.5e-3:
                            print("ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % (told, tnew))
        self.allJetsUsedForMET = allJets
#        print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]

        if self.cfg_comp.isMC:
            self.genJets = [ x for x in self.handles['genJet'].product() ]
            if self.cfg_ana.do_mc_match:
                for igj, gj in enumerate(self.genJets):
                    gj.index = igj
#                self.matchJets(event, allJets)
                self.matchJets(event, [ j for j in allJets if j.pt()>self.cfg_ana.jetPt ]) # To match only jets above chosen threshold
            if getattr(self.cfg_ana, 'smearJets', False):
                self.smearJets(event, allJets)




        ##Sort Jets by pT 
        allJets.sort(key = lambda j : j.pt(), reverse = True)

        leptons = []
        if hasattr(event, 'selectedLeptons'):
            leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin and self.lepSelCut(l) ]
        if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'):
            leptons = leptons[:] + event.selectedTaus
        if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'):
            leptons = leptons[:] + event.selectedIsoCleanTrack

        ## Apply jet selection
        self.jets = []
        self.jetsFailId = []
        self.jetsAllNoID = []
        self.jetsIdOnly = []
        for jet in allJets:
            #Check if lepton and jet have overlapping PF candidates 
            leps_with_overlaps = []
            if getattr(self.cfg_ana, 'checkLeptonPFOverlap', True):
                for i in range(jet.numberOfSourceCandidatePtrs()):
                    p1 = jet.sourceCandidatePtr(i) #Ptr<Candidate> p1
                    for lep in leptons:
                        for j in range(lep.numberOfSourceCandidatePtrs()):
                            p2 = lep.sourceCandidatePtr(j)
                            has_overlaps = p1.key() == p2.key() and p1.refCore().id().productIndex() == p2.refCore().id().productIndex() and p1.refCore().id().processIndex() == p2.refCore().id().processIndex()
                            if has_overlaps:
                                leps_with_overlaps += [lep]
            if len(leps_with_overlaps)>0:
                for lep in leps_with_overlaps:
                    lep.jetOverlap = jet
            if self.testJetNoID( jet ): 
                self.jetsAllNoID.append(jet) 
                if(self.cfg_ana.doQG):
                    jet.qgl_calc =  self.qglcalc.computeQGLikelihood
                    jet.qgl_rho =  rho
                if self.testJetID( jet ):
                    self.jets.append(jet)
                    self.jetsIdOnly.append(jet)
                else:
                    self.jetsFailId.append(jet)
            elif self.testJetID (jet ):
                self.jetsIdOnly.append(jet)

        jetsEtaCut = [j for j in self.jets if abs(j.eta()) <  self.cfg_ana.jetEta ]
        self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(jetsEtaCut, leptons, self.jetLepDR, self.jetLepArbitration)

        self.cleanJets    = [j for j in self.cleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        self.cleanJetsFwd = [j for j in self.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
        self.discardedJets = [j for j in self.jets if j not in self.cleanJetsAll]
        if hasattr(event, 'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons:
            event.discardedLeptons = [ l for l in leptons if l not in cleanLeptons ]
            event.selectedLeptons  = [ l for l in event.selectedLeptons if l not in event.discardedLeptons ]
        for lep in leptons:
            if hasattr(lep, "jetOverlap"):
                if lep.jetOverlap in self.cleanJetsAll:
                    #print "overlap reco", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi()
                    lep.jetOverlapIdx = self.cleanJetsAll.index(lep.jetOverlap)
                elif lep.jetOverlap in self.discardedJets:
                    #print "overlap discarded", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi()
                    lep.jetOverlapIdx = 1000 + self.discardedJets.index(lep.jetOverlap)

        ## First cleaning, then Jet Id
        self.noIdCleanJetsAll, cleanLeptons = cleanJetsAndLeptons(self.jetsAllNoID, leptons, self.jetLepDR, self.jetLepArbitration)
        self.noIdCleanJets = [j for j in self.noIdCleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        self.noIdCleanJetsFwd = [j for j in self.noIdCleanJetsAll if abs(j.eta()) >=  self.cfg_ana.jetEtaCentral ]
        self.noIdDiscardedJets = [j for j in self.jetsAllNoID if j not in self.noIdCleanJetsAll]

        ## Clean Jets from photons (first cleaning, then Jet Id)
        photons = []
        if hasattr(event, 'selectedPhotons'):
            if self.cfg_ana.cleanJetsFromFirstPhoton:
                photons = event.selectedPhotons[:1]
            else:
                photons = [ g for g in event.selectedPhotons ] 

        self.gamma_cleanJetaAll = []
        self.gamma_noIdCleanJetsAll = []

        if self.cleanFromLepAndGammaSimultaneously:
            self.gamma_cleanJetsAll = cleanNearestJetOnly(jetsEtaCut, photons+leptons, self.jetGammaLepDR)
            self.gamma_noIdCleanJetsAll = cleanNearestJetOnly(self.jetsAllNoID, photons+leptons, self.jetGammaLepDR)
        else:
            self.gamma_cleanJetsAll = cleanNearestJetOnly(self.cleanJetsAll, photons, self.jetGammaDR)
            self.gamma_noIdCleanJetsAll = cleanNearestJetOnly(self.noIdCleanJetsAll, photons, self.jetGammaDR)

        self.gamma_cleanJets    = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        self.gamma_cleanJetsFwd = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]

        self.gamma_noIdCleanJets    = [j for j in self.gamma_noIdCleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        self.gamma_noIdCleanJetsFwd = [j for j in self.gamma_noIdCleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
        ###

        if self.cfg_ana.alwaysCleanPhotons:
            self.cleanJets = self.gamma_cleanJets
            self.cleanJetsAll = self.gamma_cleanJetsAll
            self.cleanJetsFwd = self.gamma_cleanJetsFwd
            #
            self.noIdCleanJets = self.gamma_noIdCleanJets
            self.noIdCleanJetsAll = self.gamma_noIdCleanJetsAll
            self.noIdCleanJetsFwd = self.gamma_noIdCleanJetsFwd

        ## Jet Id, after jet/lepton cleaning
        self.cleanJetsFailIdAll = []
        for jet in self.noIdCleanJetsAll:
            if not self.testJetID( jet ):
                self.cleanJetsFailIdAll.append(jet)

        self.cleanJetsFailId = [j for j in self.cleanJetsFailIdAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]

        ## Jet Id, after jet/photon cleaning
        self.gamma_cleanJetsFailIdAll = []
        for jet in self.gamma_noIdCleanJetsAll:
            if not self.testJetID( jet ):
                self.gamma_cleanJetsFailIdAll.append(jet)

        self.gamma_cleanJetsFailId = [j for j in self.gamma_cleanJetsFailIdAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]

        ## Associate jets to leptons
        incleptons = event.inclusiveLeptons if hasattr(event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection(incleptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet ]
        for lep in incleptons:
            jet = jlpairs[lep]
            if jet is None:
                setattr(lep,"jet"+self.cfg_ana.collectionPostFix,lep)
            else:
                setattr(lep,"jet"+self.cfg_ana.collectionPostFix,jet)
        ## Associate jets to taus 
        taus = getattr(event,'selectedTaus',[])
        jtaupairs = matchObjectCollection( taus, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet ]
        for tau in taus:
            setattr(tau,"jet"+self.cfg_ana.collectionPostFix,jtaupairs[tau])

        #MC stuff
        if self.cfg_comp.isMC:
            self.deltaMetFromJetSmearing = [0, 0]
            for j in self.cleanJetsAll:
                if hasattr(j, 'deltaMetFromJetSmearing'):
                    self.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0]
                    self.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1]

            self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons, self.jetLepDR)

            if self.cfg_ana.cleanGenJetsFromPhoton:
                self.cleanGenJets = cleanNearestJetOnly(self.cleanGenJets, photons, self.jetLepDR)

            if getattr(self.cfg_ana, 'attachNeutrinos', True) and hasattr(self.cfg_ana,"genNuSelection") :
                jetNus=[x for x in event.genParticles if abs(x.pdgId()) in [12,14,16] and self.cfg_ana.genNuSelection(x) ]
                pairs= matchObjectCollection (jetNus, self.genJets, 0.4**2)

                for (nu,genJet) in six.iteritems(pairs) :
                    if genJet is not None :
                        if not hasattr(genJet,"nu") :
                            genJet.nu=nu.p4()
                        else :
                            genJet.nu+=nu.p4()


            if self.cfg_ana.do_mc_match:
                self.jetFlavour(event)

        if hasattr(event,"jets"+self.cfg_ana.collectionPostFix): raise RuntimeError("Event already contains a jet collection with the following postfix: "+self.cfg_ana.collectionPostFix)
        setattr(event,"rho"                    +self.cfg_ana.collectionPostFix, self.rho                    ) 
        setattr(event,"deltaMetFromJEC"        +self.cfg_ana.collectionPostFix, self.deltaMetFromJEC        ) 
        setattr(event,"type1METCorr"           +self.cfg_ana.collectionPostFix, self.type1METCorr           ) 
        setattr(event,"allJetsUsedForMET"      +self.cfg_ana.collectionPostFix, self.allJetsUsedForMET      ) 
        setattr(event,"jets"                   +self.cfg_ana.collectionPostFix, self.jets                   ) 
        setattr(event,"jetsFailId"             +self.cfg_ana.collectionPostFix, self.jetsFailId             ) 
        setattr(event,"jetsAllNoID"            +self.cfg_ana.collectionPostFix, self.jetsAllNoID            ) 
        setattr(event,"jetsIdOnly"             +self.cfg_ana.collectionPostFix, self.jetsIdOnly             ) 
        setattr(event,"cleanJetsAll"           +self.cfg_ana.collectionPostFix, self.cleanJetsAll           ) 
        setattr(event,"cleanJets"              +self.cfg_ana.collectionPostFix, self.cleanJets              ) 
        setattr(event,"cleanJetsFwd"           +self.cfg_ana.collectionPostFix, self.cleanJetsFwd           ) 
        setattr(event,"cleanJetsFailIdAll"           +self.cfg_ana.collectionPostFix, self.cleanJetsFailIdAll           ) 
        setattr(event,"cleanJetsFailId"              +self.cfg_ana.collectionPostFix, self.cleanJetsFailId              ) 
        setattr(event,"discardedJets"          +self.cfg_ana.collectionPostFix, self.discardedJets          ) 
        setattr(event,"gamma_cleanJetsAll"     +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsAll     ) 
        setattr(event,"gamma_cleanJets"        +self.cfg_ana.collectionPostFix, self.gamma_cleanJets        ) 
        setattr(event,"gamma_cleanJetsFwd"     +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFwd     ) 
        setattr(event,"gamma_cleanJetsFailIdAll"     +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFailIdAll     ) 
        setattr(event,"gamma_cleanJetsFailId"        +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFailId        ) 


        if self.cfg_comp.isMC:
            setattr(event,"deltaMetFromJetSmearing"+self.cfg_ana.collectionPostFix, self.deltaMetFromJetSmearing) 
            setattr(event,"cleanGenJets"           +self.cfg_ana.collectionPostFix, self.cleanGenJets           )
            setattr(event,"genJets"                +self.cfg_ana.collectionPostFix, self.genJets                )
            if self.cfg_ana.do_mc_match:
                setattr(event,"bqObjects"              +self.cfg_ana.collectionPostFix, self.bqObjects              )
                setattr(event,"cqObjects"              +self.cfg_ana.collectionPostFix, self.cqObjects              )
                setattr(event,"partons"                +self.cfg_ana.collectionPostFix, self.partons                )
                setattr(event,"heaviestQCDFlavour"     +self.cfg_ana.collectionPostFix, self.heaviestQCDFlavour     )


        return True



    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId() 
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') 
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) 

    def testJetNoID( self, jet ):
        # 2 is loose pile-up jet id
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta;

    def jetFlavour(self,event):
        def isFlavour(x,f):
            id = abs(x.pdgId())
            if id > 999: return (id/1000)%10 == f
            if id >  99: return  (id/100)%10 == f
            return id % 100 == f



        self.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,5)) ]
        self.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,4)) ]

        self.partons   = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId())>0 and (abs(p.pdgId()) in [1,2,3,4,5,21]) ) ]
        match = matchObjectCollection2(self.cleanJetsAll,
                                       self.partons,
                                       deltaRMax = 0.3)

        for jet in self.cleanJetsAll:
            parton = match[jet]
            jet.partonId = (parton.pdgId() if parton != None else 0)
            jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers()>0 else 0)

        for jet in self.jets:
            (bmatch, dr) = bestMatch(jet, self.bqObjects)
            if dr < 0.4:
                jet.mcFlavour = 5
            else:
                (cmatch, dr) = bestMatch(jet, self.cqObjects) 
                if dr < 0.4:
                    jet.mcFlavour = 4
                else:
                    jet.mcFlavour = 0

        self.heaviestQCDFlavour = 5 if len(self.bqObjects) else (4 if len(self.cqObjects) else 1);

    def matchJets(self, event, jets):
        match = matchObjectCollection2(jets,
                                       event.genbquarks + event.genwzquarks,
                                       deltaRMax = 0.3)
        for jet in jets:
            gen = match[jet]
            jet.mcParton    = gen
            jet.mcMatchId   = (gen.sourceId     if gen != None else 0)
            jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0)

        match = matchObjectCollection2(jets,
                                       self.genJets,
                                       deltaRMax = 0.3)
        for jet in jets:
            jet.mcJet = match[jet]



    def smearJets(self, event, jets):
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution
        for jet in jets:
            gen = jet.mcJet 
            if gen != None:
                genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta())
                # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
                #8 TeV tables
                factor = shiftJERfactor(self.shiftJER, aeta)
                ptscale = max(0.0, (jetpt + (factor-1)*(jetpt-genpt))/jetpt)             
                #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale)
                jet.deltaMetFromJetSmearing = [ -(ptscale-1)*jet.rawFactor()*jet.px(), -(ptscale-1)*jet.rawFactor()*jet.py() ]
                if ptscale != 0:
                    jet.setP4(jet.p4()*ptscale)
                    # leave the uncorrected unchanged for sync
                    jet.setRawFactor(jet.rawFactor()/ptscale)
            #else: print "jet with pt %.1d, eta %.2f is unmatched" % (jet.pt(), jet.eta())
                if (self.shiftJER==0) and (self.addJERShifts):
                    setattr(jet, "corrJER", ptscale )
                    factorJERUp= shiftJERfactor(1, aeta)
                    ptscaleJERUp = max(0.0, (jetpt + (factorJERUp-1)*(jetpt-genpt))/jetpt)
                    setattr(jet, "corrJERUp", ptscaleJERUp)
                    factorJERDown= shiftJERfactor(-1, aeta)
                    ptscaleJERDown = max(0.0, (jetpt + (factorJERDown-1)*(jetpt-genpt))/jetpt)
                    setattr(jet, "corrJERDown", ptscaleJERDown)
예제 #4
0
class EventInterpretationBase(Analyzer):
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(EventInterpretationBase, self).__init__(cfg_ana, cfg_comp,
                                                      looperName)
        self.selectFat = self.cfg_ana.selectFat
        self.selectPairLNu = self.cfg_ana.selectPairLNu
        self.selectPairLL = self.cfg_ana.selectPairLL
        self.selectPairJJ = self.cfg_ana.selectPairJJ
        self.selectPairJJNuNu = self.cfg_ana.selectPairJJNuNu
        self.isMC = cfg_comp.isMC
        if hasattr(cfg_ana, 'matchDR'):
            self.matchDR = cfg_ana.matchDR
        else:
            self.matchDR = 0.2

        mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,
                                           'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(
            self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        if self.recalibrateJets == "MC":
            self.recalibrateJets = self.cfg_comp.isMC
        elif self.recalibrateJets == "Data":
            self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True, False]:
            raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC != 0)
        if self.doJEC:
            if self.cfg_comp.isMC:
                if hasattr(self.cfg_comp, 'globalTag'):
                    self.jetReCalibrator = JetReCalibrator(
                        self.cfg_comp.globalTag,
                        self.cfg_ana.recalibrationType, False, cfg_ana.jecPath)
                    self.jetReCalibratorFAT = JetReCalibrator(
                        self.cfg_comp.globalTag,
                        self.cfg_ana.recalibrationTypeFAT, False,
                        cfg_ana.jecPath)

                else:
                    self.jetReCalibrator = JetReCalibrator(
                        mcGT, self.cfg_ana.recalibrationType, False,
                        cfg_ana.jecPath)
                    self.jetReCalibratorFAT = JetReCalibrator(
                        mcGT, self.cfg_ana.recalibrationTypeFAT, False,
                        cfg_ana.jecPath, 3, True)
            else:
                if hasattr(self.cfg_comp, 'globalTag'):
                    self.jetReCalibrator = JetReCalibrator(
                        self.cfg_comp.globalTag,
                        self.cfg_ana.recalibrationType, True, cfg_ana.jecPath)
                    self.jetReCalibratorFAT = JetReCalibrator(
                        self.cfg_comp.globalTag,
                        self.cfg_ana.recalibrationTypeFAT, True,
                        cfg_ana.jecPath)
                else:
                    self.jetReCalibrator = JetReCalibrator(
                        dataGT, self.cfg_ana.recalibrationType, True,
                        cfg_ana.jecPath)
                    self.jetReCalibratorFAT = JetReCalibrator(
                        dataGT, self.cfg_ana.recalibrationTypeFAT, True,
                        cfg_ana.jecPath)

        self.attachBTag = cfg_ana.attachBTag
        if self.attachBTag:
            self.btagDiscriminator = cfg_ana.btagDiscriminator

        if hasattr(cfg_ana, 'doSkim'):
            self.doSkim = cfg_ana.doSkim
        else:
            self.doSkim = False

    def declareHandles(self):
        super(EventInterpretationBase, self).declareHandles()
        self.handles['packed'] = AutoHandle(
            'packedPFCandidates', 'std::vector<pat::PackedCandidate>')
        self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double')
        if self.attachBTag or self.doSkim:
            self.handles['jets'] = AutoHandle(self.cfg_ana.standardJets,
                                              'std::vector<pat::Jet>')
            self.handles['fatjets'] = AutoHandle(self.cfg_ana.fatJets,
                                                 'std::vector<pat::Jet>')
            self.handles['subjets'] = AutoHandle(
                (self.cfg_ana.subJets, 'SubJets'), 'std::vector<pat::Jet>')

    def removeLeptonFootPrint(self, leptons, cands):
        toRemove = []
        cList = list(cands)
        for lepton in leptons:

            for p in range(0, lepton.numberOfSourceCandidatePtrs()):
                index = lepton.sourceCandidatePtr(p).key()
                if not cands[index] in toRemove:
                    toRemove.append(cands[index])

        for r in toRemove:
            cList.remove(r)
        return cList

    def matchSubJets(self, jets, genquarks):
        for j in jets:
            for s in j.subjets_SD + j.subjets:
                s.mcquark = None
                s.matched = 0
                for g in genquarks:
                    if deltaR(s.eta(), s.phi(), g.eta(),
                              g.phi()) < self.matchDR:
                        s.matched = 1
                        s.mcquark = g
                        break

    def skim(self, leptons, met):
        cleanedJets = []
        for jet in self.handles['fatjets'].product():
            overlap = False
            for lepton in leptons:
                if deltaR(jet.eta(), jet.phi(), lepton.eta(),
                          lepton.phi()) < 0.8:
                    overlap = True
                    break
            if not overlap:
                cleanedJets.append(jet)
        nJets = len(cleanedJets)
        nLeptons = len(leptons)
        if (nLeptons > 0 and nJets > 0) or nJets > 1 or (nJets > 0
                                                         and met.pt() > 300):
            return True
        return False

    def puppiWeight(self, cands):
        skimmedCollection = []
        for p in cands:
            p.setP4(p.p4() * p.puppiWeight())

            if p.pt() > 0:
                skimmedCollection.append(p)
        return skimmedCollection

    def makeFatJets(self, cands):
        toolboxFat = PyJetToolbox(cands)
        toolboxFat.setInterface(True, self.cfg_ana.ktPowerFat,
                                self.cfg_ana.rFat)
        toolboxFat.setMassDrop(self.cfg_ana.massdrop)
        toolboxFat.setSubjets(True, 'inc', self.cfg_ana.subjets)
        toolboxFat.setPruning(self.cfg_ana.prunning)
        toolboxFat.setNtau(True)
        if hasattr(self.cfg_ana, 'softdrop_beta'):
            toolboxFat.setSoftDrop(self.cfg_ana.softdrop,
                                   self.cfg_ana.softdrop_beta,
                                   self.cfg_ana.softdrop_zeta)
        else:
            toolboxFat.setSoftDrop(self.cfg_ana.softdrop)
        # Lets cluster !! Fat jets first
        fatJets = toolboxFat.inclusiveJets(200.0, True)
        filtered = filter(self.selectFat, fatJets)

        ##Apply JECS in original,SoftDrop and pruned:
        if self.jetReCalibratorFAT is not None:

            prunedJets = []
            for j in fatJets:
                prunedJets.append(j)
                prunedJets.append(j.softDropJet)
                prunedJets.append(j.prunedJet)

            #do not apply L1 corrections:rho=0.0
            self.jetReCalibratorFAT.correctAll(prunedJets, 0.0, self.shiftJEC,
                                               True, False, [0., 0.],
                                               [0., 0., 0.])
            #            self.jetReCalibratorFAT.correctAll(originalJets, self.rho, self.shiftJEC,True,False,[0.,0.],[0.,0.,0.])

            for p in prunedJets:
                p.setRawFactor(1.0 / p.corr)

        standardFatJets = self.handles['fatjets'].product()

        if self.attachBTag:
            for fat in filtered:
                for standardFat in standardFatJets:
                    fat.btag = standardFat.bDiscriminator(
                        self.btagDiscriminator)
                for j in fat.subjets_SD + fat.subjets:
                    for standard in self.handles['subjets'].product():
                        if deltaR(j.eta(), j.phi(), standard.eta(),
                                  standard.phi()) < 0.1:
                            j.btag = standard.bDiscriminator(
                                self.btagDiscriminator)
                            break

        return filtered

    def makeSatelliteJets(self, cands):
        toolbox = PyJetToolbox(cands)
        toolbox.setInterface(True, self.cfg_ana.ktPower, self.cfg_ana.r)
        toolbox.setMassDrop(False)
        toolbox.setSubjets(False, 'inc', 2)
        toolbox.setPruning(False)
        toolbox.setNtau(False)
        toolbox.setSoftDrop(False)
        unfiltered = toolbox.inclusiveJets(30.0, False)

        if self.attachBTag:
            for j in unfiltered:
                for standard in self.handles['jets'].product():
                    if deltaR(j.eta(), j.phi(), standard.eta(),
                              standard.phi()) < 0.1:
                        j.btag = standard.bDiscriminator(
                            self.btagDiscriminator)
                        break

        if self.jetReCalibrator is not None:
            self.jetReCalibrator.correctAll(unfiltered, self.rho,
                                            self.shiftJEC, True, False,
                                            [0., 0.], [0., 0., 0.])
            for p in unfiltered:
                p.setRawFactor(1.0 / p.corr)

            filtered = filter(lambda x: x.pt() > 30, unfiltered)
            return filtered
        else:
            return unfiltered

    def removeJetFootPrint(self, jets, cands):

        toRemove = []
        for j in jets:
            toRemove.extend(j.constituents)
        out = list(set(cands) - set(toRemove))
        return out

    def topology(self, obj):

        #first clean nicely the jets from leptons and subjets
        objToClean = []
        if abs(obj['pair'].leg1.pdgId()) == 23:
            objToClean.extend([obj['pair'].leg1.leg1, obj['pair'].leg1.leg2])
#            print 'Z->ll', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi(),obj['pair'].leg1.leg2.pt(),obj['pair'].leg1.leg2.eta(),obj['pair'].leg1.leg2.phi()
        if abs(obj['pair'].leg1.pdgId()) == 24:
            objToClean.extend([obj['pair'].leg1.leg1])
#            print 'W->lnu', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi()

        if abs(obj['pair'].leg1.pdgId()) == 1:
            objToClean.extend(obj['pair'].leg1.subjets)

        if abs(obj['pair'].leg2.pdgId()) == 23:
            objToClean.extend([obj['pair'].leg2.leg1, obj['pair'].leg2.leg2])
        if abs(obj['pair'].leg2.pdgId()) == 24:
            objToClean.extend([obj['pair'].leg2.leg1])
        if abs(obj['pair'].leg2.pdgId()) == 1:
            objToClean.extend(obj['pair'].leg2.subjets)
#            print 'jet', obj['pair'].leg2.pt(),obj['pair'].leg2.eta(),obj['pair'].leg2.phi()

        newJets = []
        for j in obj['satelliteJets']:
            keep = True
            for c in objToClean:
                dr = deltaR(j.eta(), j.phi(), c.eta(), c.phi())
                #                print 'dr=',dr
                if dr < 0.4:
                    keep = False
                    break
            if keep:
                #                print 'filtered satellite jet',j.pt(),j.eta(),j.phi()
                newJets.append(j)

        obj['satelliteJets'] = newJets

        if len(obj['satelliteJets']) < 2:
            obj['vbfDEta'] = -1.0
            obj['vbfMJJ'] = -1.0
        else:
            j1 = obj['satelliteJets'][0]
            j2 = obj['satelliteJets'][1]
            obj['vbfDEta'] = abs(j1.eta() - j2.eta())
            obj['vbfMJJ'] = (j1.p4() + j2.p4()).M()

        NL = 0
        NM = 0
        NT = 0

        bestBTag = None
        minDR = 1000.0
        for s in obj['satelliteJets']:
            btag = s.bTag()
            if btag > 0.423:
                NL = NL + 1
                DR = deltaR(obj['pair'].eta(), obj['pair'].phi(), s.eta(),
                            s.phi())
                if DR < minDR:
                    bestBTag = s
                    minDR = DR
            if btag > 0.814:
                NM = NM + 1
            if btag > 0.941:
                NT = NT + 1
        obj['nLooseBTags'] = NL
        obj['nMediumBTags'] = NM
        obj['nTightBTags'] = NT

        if bestBTag == None:
            obj['topMass'] = -1
        else:
            obj['topMass'] = (bestBTag.p4() + s.p4()).mass()

    def beginLoop(self, setup):
        super(EventInterpretationBase, self).beginLoop(setup)

    def process(self, event):
        self.readCollections(event.input)
        rho = float(self.handles['rho'].product()[0])
        self.rho = rho
예제 #5
0
class JetAnalyzer( Analyzer ):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName)
        mcGT   = cfg_ana.mcGT   if hasattr(cfg_ana,'mcGT')   else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        if   self.recalibrateJets == "MC"  : self.recalibrateJets =     self.cfg_comp.isMC
        elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True,False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC != 0)
        if self.doJEC:
          if self.cfg_comp.isMC:
            self.jetReCalibrator = JetReCalibrator(mcGT,"AK4PFchs", False,cfg_ana.jecPath)
          else:
            self.jetReCalibrator = JetReCalibrator(dataGT,"AK4PFchs", True,cfg_ana.jecPath)
        self.doPuId = getattr(self.cfg_ana, 'doPuId', True)
        self.jetLepDR = getattr(self.cfg_ana, 'jetLepDR', 0.4)
        self.jetLepArbitration = getattr(self.cfg_ana, 'jetLepArbitration', lambda jet,lepton: lepton) 
        self.lepPtMin = getattr(self.cfg_ana, 'minLepPt', -1)
        self.jetGammaDR =  getattr(self.cfg_ana, 'jetGammaDR', 0.4)
        if(self.cfg_ana.doQG):
            self.qglcalc = QGLikelihoodCalculator("/afs/cern.ch/user/t/tomc/public/qgTagger/QGLikelihoodDBFiles/QGL_v1a/pdfQG_AK4chs_antib_13TeV_v1.root")

    def declareHandles(self):
        super(JetAnalyzer, self).declareHandles()
        self.handles['jets']   = AutoHandle( self.cfg_ana.jetCol, 'std::vector<pat::Jet>' )
        self.handles['genJet'] = AutoHandle( 'slimmedGenJets', 'vector<reco::GenJet>' )
        self.shiftJER = self.cfg_ana.shiftJER if hasattr(self.cfg_ana, 'shiftJER') else 0
        self.handles['rho'] = AutoHandle( ('fixedGridRhoFastjetAll','',''), 'double' )
    
    def beginLoop(self, setup):
        super(JetAnalyzer,self).beginLoop(setup)
        
    def process(self, event):
        self.readCollections( event.input )
        rho  = float(self.handles['rho'].product()[0])
        event.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        allJets = map(Jet, self.handles['jets'].product()) 

        event.deltaMetFromJEC = [0.,0.]
        if self.doJEC:
            #print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId)
            self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, metShift=event.deltaMetFromJEC)
        event.allJetsUsedForMET = allJets

        if self.cfg_comp.isMC:
            event.genJets = [ x for x in self.handles['genJet'].product() ]
            self.matchJets(event, allJets)
            if getattr(self.cfg_ana, 'smearJets', False):
                self.smearJets(event, allJets)
        
	##Sort Jets by pT 
        allJets.sort(key = lambda j : j.pt(), reverse = True)
        
	## Apply jet selection
        event.jets = []
        event.jetsFailId = []
        event.jetsAllNoID = []
        event.jetsIdOnly = []
        for jet in allJets:
            if self.testJetNoID( jet ): 
                event.jetsAllNoID.append(jet) 
                if self.testJetID (jet ):
                    
                    if(self.cfg_ana.doQG):
                        self.computeQGvars(jet)
                        jet.qgl = self.qglcalc.computeQGLikelihood(jet, rho)


                    event.jets.append(jet)
                    event.jetsIdOnly.append(jet)
                else:
                    event.jetsFailId.append(jet)
            elif self.testJetID (jet ):
                event.jetsIdOnly.append(jet)

        ## Clean Jets from leptons
        leptons = []
        if hasattr(event, 'selectedLeptons'):
            leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin ]
        if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'):
            leptons = leptons[:] + event.selectedTaus
        if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'):
            leptons = leptons[:] + event.selectedIsoCleanTrack
        event.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(event.jets, leptons, self.jetLepDR, self.jetLepArbitration)
        event.cleanJets    = [j for j in event.cleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        event.cleanJetsFwd = [j for j in event.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
        event.discardedJets = [j for j in event.jets if j not in event.cleanJetsAll]
        if hasattr(event, 'selectedLeptons'):
            event.discardedLeptons = [ l for l in leptons if l not in cleanLeptons ]
            event.selectedLeptons  = [ l for l in event.selectedLeptons if l not in event.discardedLeptons ]

        ## Clean Jets from photons
        photons = []
        if hasattr(event, 'selectedPhotons'):
            if self.cfg_ana.cleanJetsFromFirstPhoton:
                photons = event.selectedPhotons[:1]
            else:
                photons = [ g for g in event.selectedPhotons ] 

        event.gamma_cleanJetsAll = cleanNearestJetOnly(event.cleanJetsAll, photons, self.jetGammaDR)
        event.gamma_cleanJets    = [j for j in event.gamma_cleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        event.gamma_cleanJetsFwd = [j for j in event.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
        ###


        ## Associate jets to leptons
        leptons = event.inclusiveLeptons if hasattr(event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection( leptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet ]

        for lep in leptons:
            jet = jlpairs[lep]
            if jet is None:
                lep.jet = lep
            else:
                lep.jet = jet
        ## Associate jets to taus 
        taus = getattr(event,'selectedTaus',[])
        jtaupairs = matchObjectCollection( taus, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet ]
        for tau in taus:
            tau.jet = jtaupairs[tau]

        #MC stuff
        if self.cfg_comp.isMC:
            event.deltaMetFromJetSmearing = [0, 0]
            for j in event.cleanJetsAll:
                if hasattr(j, 'deltaMetFromJetSmearing'):
                    event.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0]
                    event.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1]
            event.cleanGenJets = cleanNearestJetOnly(event.genJets, leptons, self.jetLepDR)
            
            #event.nGenJets25 = 0
            #event.nGenJets25Cen = 0
            #event.nGenJets25Fwd = 0
            #for j in event.cleanGenJets:
            #    event.nGenJets25 += 1
            #    if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1
            #    else:                   event.nGenJets25Fwd += 1
                    
            self.jetFlavour(event)
        
    
        return True

        

    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId() 
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') 
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) 
        
    def testJetNoID( self, jet ):
        # 2 is loose pile-up jet id
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta;

    def computeQGvars(self, jet):

       jet.mult = 0
       sum_weight = 0.
       sum_pt = 0.
       sum_deta = 0.
       sum_dphi = 0.
       sum_deta2 = 0.
       sum_detadphi = 0.
       sum_dphi2 = 0.



       for ii in range(0, jet.numberOfDaughters()) :

         part = jet.daughter(ii)

         if part.charge() == 0 : # neutral particles 

           if part.pt() < 1.: continue

         else : # charged particles

           if part.trackHighPurity()==False: continue
           if part.fromPV()<=1: continue


         jet.mult += 1

         deta = part.eta() - jet.eta()
         dphi = deltaPhi(part.phi(), jet.phi())
         partPt = part.pt()
         weight = partPt*partPt
         sum_weight += weight
         sum_pt += partPt
         sum_deta += deta*weight
         sum_dphi += dphi*weight
         sum_deta2 += deta*deta*weight
         sum_detadphi += deta*dphi*weight
         sum_dphi2 += dphi*dphi*weight




       a = 0.
       b = 0.
       c = 0.

       if sum_weight > 0 :
         jet.ptd = math.sqrt(sum_weight)/sum_pt
         ave_deta = sum_deta/sum_weight
         ave_dphi = sum_dphi/sum_weight
         ave_deta2 = sum_deta2/sum_weight
         ave_dphi2 = sum_dphi2/sum_weight
         a = ave_deta2 - ave_deta*ave_deta
         b = ave_dphi2 - ave_dphi*ave_dphi
         c = -(sum_detadphi/sum_weight - ave_deta*ave_dphi)
       else: jet.ptd = 0.

       delta = math.sqrt(math.fabs((a-b)*(a-b)+4.*c*c))

       if a+b-delta > 0: jet.axis2 = -math.log(math.sqrt(0.5*(a+b-delta)))
       else: jet.axis2 = -1.


    def jetFlavour(self,event):
        def isFlavour(x,f):
            id = abs(x.pdgId())
            if id > 999: return (id/1000)%10 == f
            if id >  99: return  (id/100)%10 == f
            return id % 100 == f



        event.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,5)) ]
        event.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,4)) ]

        event.partons   = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId())>0 and (abs(p.pdgId()) in [1,2,3,4,5,21]) ) ]
        match = matchObjectCollection2(event.cleanJetsAll,
                                       event.partons,
                                       deltaRMax = 0.3)

        for jet in event.cleanJetsAll:
            parton = match[jet]
            jet.partonId = (parton.pdgId() if parton != None else 0)
            jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers()>0 else 0)
        
        for jet in event.jets:
           (bmatch, dr) = bestMatch(jet, event.bqObjects)
           if dr < 0.4:
               jet.mcFlavour = 5
           else:
               (cmatch, dr) = bestMatch(jet, event.cqObjects) 
               if dr < 0.4:
                   jet.mcFlavour = 4
               else:
                   jet.mcFlavour = 0

        event.heaviestQCDFlavour = 5 if len(event.bqObjects) else (4 if len(event.cqObjects) else 1);
 

    def matchJets(self, event, jets):
        match = matchObjectCollection2(jets,
                                       event.genbquarks + event.genwzquarks,
                                       deltaRMax = 0.3)
        for jet in jets:
            gen = match[jet]
            jet.mcParton    = gen
            jet.mcMatchId   = (gen.sourceId     if gen != None else 0)
            jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0)

        match = matchObjectCollection2(jets,
                                       event.genJets,
                                       deltaRMax = 0.3)
        for jet in jets:
            jet.mcJet = match[jet]


 
    def smearJets(self, event, jets):
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution
       for jet in jets:
            gen = jet.mcJet 
            if gen != None:
               genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta())
               # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
               factor = 1.052 + self.shiftJER*math.hypot(0.012,0.062);
               if   aeta > 2.3: factor = 1.288 + self.shiftJER*math.hypot(0.127,0.154)
               elif aeta > 1.7: factor = 1.134 + self.shiftJER*math.hypot(0.035,0.066)
               elif aeta > 1.1: factor = 1.096 + self.shiftJER*math.hypot(0.017,0.063)
               elif aeta > 0.5: factor = 1.057 + self.shiftJER*math.hypot(0.012,0.056)
               ptscale = max(0.0, (jetpt + (factor-1)*(jetpt-genpt))/jetpt)
               #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale)
               jet.deltaMetFromJetSmearing = [ -(ptscale-1)*jet.rawFactor()*jet.px(), -(ptscale-1)*jet.rawFactor()*jet.py() ]
               if ptscale != 0:
                  jet.setP4(jet.p4()*ptscale)
               # leave the uncorrected unchanged for sync
               jet._rawFactorMultiplier *= (1.0/ptscale) if ptscale != 0 else 1
예제 #6
0
class JetAnalyzer(Analyzer):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,
                                           'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(
            self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        if self.recalibrateJets == "MC":
            self.recalibrateJets = self.cfg_comp.isMC
        elif self.recalibrateJets == "Data":
            self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True, False]:
            raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC != 0)
        if self.doJEC:
            if self.cfg_comp.isMC:
                self.jetReCalibrator = JetReCalibrator(
                    mcGT, self.cfg_ana.recalibrationType, False,
                    cfg_ana.jecPath)
            else:
                self.jetReCalibrator = JetReCalibrator(
                    dataGT, self.cfg_ana.recalibrationType, True,
                    cfg_ana.jecPath)
        self.doPuId = getattr(self.cfg_ana, 'doPuId', True)
        self.jetLepDR = getattr(self.cfg_ana, 'jetLepDR', 0.4)
        self.jetLepArbitration = getattr(self.cfg_ana, 'jetLepArbitration',
                                         lambda jet, lepton: lepton)
        self.lepPtMin = getattr(self.cfg_ana, 'minLepPt', -1)
        self.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep: True)
        self.jetGammaDR = getattr(self.cfg_ana, 'jetGammaDR', 0.4)
        if (self.cfg_ana.doQG):
            self.qglcalc = QGLikelihoodCalculator(
                "%s/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_antib_13TeV_v1.root"
                % os.environ['CMSSW_BASE'])
        if not hasattr(self.cfg_ana, "collectionPostFix"):
            self.cfg_ana.collectionPostFix = ""

    def declareHandles(self):
        super(JetAnalyzer, self).declareHandles()
        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol,
                                          'std::vector<pat::Jet>')
        self.handles['genJet'] = AutoHandle(self.cfg_ana.genJetCol,
                                            'vector<reco::GenJet>')
        self.shiftJER = self.cfg_ana.shiftJER if hasattr(
            self.cfg_ana, 'shiftJER') else 0
        self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double')

    def beginLoop(self, setup):
        super(JetAnalyzer, self).beginLoop(setup)

    def process(self, event):
        self.readCollections(event.input)
        rho = float(self.handles['rho'].product()[0])
        self.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        if self.cfg_ana.copyJetsByValue:
            import ROOT
            allJets = map(
                lambda j: Jet(ROOT.pat.Jet(j)), self.handles['jets'].product(
                ))  #copy-by-value is safe if JetAnalyzer is ran more than once
        else:
            allJets = map(Jet, self.handles['jets'].product())

        self.deltaMetFromJEC = [0., 0.]
        #        print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]
        if self.doJEC:
            #            print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId)
            self.jetReCalibrator.correctAll(allJets,
                                            rho,
                                            delta=self.shiftJEC,
                                            metShift=self.deltaMetFromJEC)
        self.allJetsUsedForMET = allJets
        #        print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]

        if self.cfg_comp.isMC:
            self.genJets = [x for x in self.handles['genJet'].product()]
            self.matchJets(event, allJets)
            if getattr(self.cfg_ana, 'smearJets', False):
                self.smearJets(event, allJets)

##Sort Jets by pT
        allJets.sort(key=lambda j: j.pt(), reverse=True)
        ## Apply jet selection
        self.jets = []
        self.jetsFailId = []
        self.jetsAllNoID = []
        self.jetsIdOnly = []
        for jet in allJets:
            if self.testJetNoID(jet):
                self.jetsAllNoID.append(jet)
                if self.testJetID(jet):

                    if (self.cfg_ana.doQG):
                        self.computeQGvars(jet)
                        jet.qgl = self.qglcalc.computeQGLikelihood(jet, rho)

                    self.jets.append(jet)
                    self.jetsIdOnly.append(jet)
                else:
                    self.jetsFailId.append(jet)
            elif self.testJetID(jet):
                self.jetsIdOnly.append(jet)

        ## Clean Jets from leptons
        leptons = []
        if hasattr(event, 'selectedLeptons'):
            leptons = [
                l for l in event.selectedLeptons
                if l.pt() > self.lepPtMin and self.lepSelCut(l)
            ]
        if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'):
            leptons = leptons[:] + event.selectedTaus
        if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(
                event, 'selectedIsoCleanTrack'):
            leptons = leptons[:] + event.selectedIsoCleanTrack
        self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(
            self.jets, leptons, self.jetLepDR, self.jetLepArbitration)
        self.cleanJets = [
            j for j in self.cleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        self.cleanJetsFwd = [
            j for j in self.cleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]
        self.discardedJets = [
            j for j in self.jets if j not in self.cleanJetsAll
        ]
        if hasattr(event,
                   'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons:
            event.discardedLeptons = [
                l for l in leptons if l not in cleanLeptons
            ]
            event.selectedLeptons = [
                l for l in event.selectedLeptons
                if l not in event.discardedLeptons
            ]

        ## Clean Jets from photons
        photons = []
        if hasattr(event, 'selectedPhotons'):
            if self.cfg_ana.cleanJetsFromFirstPhoton:
                photons = event.selectedPhotons[:1]
            else:
                photons = [g for g in event.selectedPhotons]

        self.gamma_cleanJetsAll = cleanNearestJetOnly(self.cleanJetsAll,
                                                      photons, self.jetGammaDR)
        self.gamma_cleanJets = [
            j for j in self.gamma_cleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        self.gamma_cleanJetsFwd = [
            j for j in self.gamma_cleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]
        ###

        ## Associate jets to leptons
        leptons = event.inclusiveLeptons if hasattr(
            event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet]

        for lep in leptons:
            jet = jlpairs[lep]
            if jet is None:
                lep.jet = lep
            else:
                lep.jet = jet
        ## Associate jets to taus
        taus = getattr(event, 'selectedTaus', [])
        jtaupairs = matchObjectCollection(taus, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet]
        for tau in taus:
            tau.jet = jtaupairs[tau]

        #MC stuff
        if self.cfg_comp.isMC:
            self.deltaMetFromJetSmearing = [0, 0]
            for j in self.cleanJetsAll:
                if hasattr(j, 'deltaMetFromJetSmearing'):
                    self.deltaMetFromJetSmearing[
                        0] += j.deltaMetFromJetSmearing[0]
                    self.deltaMetFromJetSmearing[
                        1] += j.deltaMetFromJetSmearing[1]
            self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons,
                                                    self.jetLepDR)

            if self.cfg_ana.cleanGenJetsFromPhoton:
                self.cleanGenJets = cleanNearestJetOnly(
                    self.cleanGenJets, photons, self.jetLepDR)

            #event.nGenJets25 = 0
            #event.nGenJets25Cen = 0
            #event.nGenJets25Fwd = 0
            #for j in event.cleanGenJets:
            #    event.nGenJets25 += 1
            #    if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1
            #    else:                   event.nGenJets25Fwd += 1

            self.jetFlavour(event)

        setattr(event, "rho" + self.cfg_ana.collectionPostFix, self.rho)
        setattr(event, "deltaMetFromJEC" + self.cfg_ana.collectionPostFix,
                self.deltaMetFromJEC)
        setattr(event,
                "deltaMetFromJetSmearing" + self.cfg_ana.collectionPostFix,
                self.deltaMetFromJetSmearing)
        setattr(event, "allJetsUsedForMET" + self.cfg_ana.collectionPostFix,
                self.allJetsUsedForMET)
        setattr(event, "genJets" + self.cfg_ana.collectionPostFix,
                self.genJets)
        setattr(event, "cleanGenJets" + self.cfg_ana.collectionPostFix,
                self.cleanGenJets)
        setattr(event, "jets" + self.cfg_ana.collectionPostFix, self.jets)
        setattr(event, "jetsFailId" + self.cfg_ana.collectionPostFix,
                self.jetsFailId)
        setattr(event, "jetsAllNoID" + self.cfg_ana.collectionPostFix,
                self.jetsAllNoID)
        setattr(event, "jetsIdOnly" + self.cfg_ana.collectionPostFix,
                self.jetsIdOnly)
        setattr(event, "cleanJetsAll" + self.cfg_ana.collectionPostFix,
                self.cleanJetsAll)
        setattr(event, "cleanJets" + self.cfg_ana.collectionPostFix,
                self.cleanJets)
        setattr(event, "cleanJetsFwd" + self.cfg_ana.collectionPostFix,
                self.cleanJetsFwd)
        setattr(event, "discardedJets" + self.cfg_ana.collectionPostFix,
                self.discardedJets)
        setattr(event, "gamma_cleanJetsAll" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJetsAll)
        setattr(event, "gamma_cleanJets" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJets)
        setattr(event, "gamma_cleanJetsFwd" + self.cfg_ana.collectionPostFix,
                self.gamma_cleanJetsFwd)
        setattr(event, "bqObjects" + self.cfg_ana.collectionPostFix,
                self.bqObjects)
        setattr(event, "cqObjects" + self.cfg_ana.collectionPostFix,
                self.cqObjects)
        setattr(event, "partons" + self.cfg_ana.collectionPostFix,
                self.partons)
        setattr(event, "heaviestQCDFlavour" + self.cfg_ana.collectionPostFix,
                self.heaviestQCDFlavour)

        return True

    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId()
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose')
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed and (jet.puJetIdPassed
                                          or not (self.doPuId))

    def testJetNoID(self, jet):
        # 2 is loose pile-up jet id
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta

    def computeQGvars(self, jet):

        jet.mult = 0
        sum_weight = 0.
        sum_pt = 0.
        sum_deta = 0.
        sum_dphi = 0.
        sum_deta2 = 0.
        sum_detadphi = 0.
        sum_dphi2 = 0.

        for ii in range(0, jet.numberOfDaughters()):

            part = jet.daughter(ii)

            if part.charge() == 0:  # neutral particles

                if part.pt() < 1.: continue

            else:  # charged particles

                if part.trackHighPurity() == False: continue
                if part.fromPV() <= 1: continue

            jet.mult += 1

            deta = part.eta() - jet.eta()
            dphi = deltaPhi(part.phi(), jet.phi())
            partPt = part.pt()
            weight = partPt * partPt
            sum_weight += weight
            sum_pt += partPt
            sum_deta += deta * weight
            sum_dphi += dphi * weight
            sum_deta2 += deta * deta * weight
            sum_detadphi += deta * dphi * weight
            sum_dphi2 += dphi * dphi * weight

        a = 0.
        b = 0.
        c = 0.

        if sum_weight > 0:
            jet.ptd = math.sqrt(sum_weight) / sum_pt
            ave_deta = sum_deta / sum_weight
            ave_dphi = sum_dphi / sum_weight
            ave_deta2 = sum_deta2 / sum_weight
            ave_dphi2 = sum_dphi2 / sum_weight
            a = ave_deta2 - ave_deta * ave_deta
            b = ave_dphi2 - ave_dphi * ave_dphi
            c = -(sum_detadphi / sum_weight - ave_deta * ave_dphi)
        else:
            jet.ptd = 0.

        delta = math.sqrt(math.fabs((a - b) * (a - b) + 4. * c * c))

        if a + b - delta > 0:
            jet.axis2 = -math.log(math.sqrt(0.5 * (a + b - delta)))
        else:
            jet.axis2 = -1.

    def jetFlavour(self, event):
        def isFlavour(x, f):
            id = abs(x.pdgId())
            if id > 999: return (id / 1000) % 10 == f
            if id > 99: return (id / 100) % 10 == f
            return id % 100 == f

        self.bqObjects = [
            p for p in event.genParticles
            if (p.status() == 2 and isFlavour(p, 5))
        ]
        self.cqObjects = [
            p for p in event.genParticles
            if (p.status() == 2 and isFlavour(p, 4))
        ]

        self.partons = [
            p for p in event.genParticles
            if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId()) > 0
                and (abs(p.pdgId()) in [1, 2, 3, 4, 5, 21]))
        ]
        match = matchObjectCollection2(self.cleanJetsAll,
                                       self.partons,
                                       deltaRMax=0.3)

        for jet in self.cleanJetsAll:
            parton = match[jet]
            jet.partonId = (parton.pdgId() if parton != None else 0)
            jet.partonMotherId = (parton.mother(0).pdgId() if parton != None
                                  and parton.numberOfMothers() > 0 else 0)

        for jet in self.jets:
            (bmatch, dr) = bestMatch(jet, self.bqObjects)
            if dr < 0.4:
                jet.mcFlavour = 5
            else:
                (cmatch, dr) = bestMatch(jet, self.cqObjects)
                if dr < 0.4:
                    jet.mcFlavour = 4
                else:
                    jet.mcFlavour = 0

        self.heaviestQCDFlavour = 5 if len(
            self.bqObjects) else (4 if len(self.cqObjects) else 1)

    def matchJets(self, event, jets):
        match = matchObjectCollection2(jets,
                                       event.genbquarks + event.genwzquarks,
                                       deltaRMax=0.3)
        for jet in jets:
            gen = match[jet]
            jet.mcParton = gen
            jet.mcMatchId = (gen.sourceId if gen != None else 0)
            jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0)

        match = matchObjectCollection2(jets, self.genJets, deltaRMax=0.3)
        for jet in jets:
            jet.mcJet = match[jet]

    def smearJets(self, event, jets):
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution
        for jet in jets:
            gen = jet.mcJet
            if gen != None:
                genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta())
                # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
                factor = 1.052 + self.shiftJER * math.hypot(0.012, 0.062)
                if aeta > 2.3:
                    factor = 1.288 + self.shiftJER * math.hypot(0.127, 0.154)
                elif aeta > 1.7:
                    factor = 1.134 + self.shiftJER * math.hypot(0.035, 0.066)
                elif aeta > 1.1:
                    factor = 1.096 + self.shiftJER * math.hypot(0.017, 0.063)
                elif aeta > 0.5:
                    factor = 1.057 + self.shiftJER * math.hypot(0.012, 0.056)
                ptscale = max(0.0,
                              (jetpt + (factor - 1) * (jetpt - genpt)) / jetpt)
                #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale)
                jet.deltaMetFromJetSmearing = [
                    -(ptscale - 1) * jet.rawFactor() * jet.px(),
                    -(ptscale - 1) * jet.rawFactor() * jet.py()
                ]
                if ptscale != 0:
                    jet.setP4(jet.p4() * ptscale)
                # leave the uncorrected unchanged for sync
                jet._rawFactorMultiplier *= (1.0 /
                                             ptscale) if ptscale != 0 else 1
예제 #7
0
class JetAnalyzer( Analyzer ):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName)
        mcGT   = cfg_ana.mcGT   if hasattr(cfg_ana,'mcGT')   else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        self.addJECShifts = self.cfg_ana.addJECShifts
        if   self.recalibrateJets == "MC"  : self.recalibrateJets =     self.cfg_comp.isMC
        elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True,False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) or self.addJECShifts
        if self.doJEC:
          doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
          if   doResidual == "MC":   doResidual = self.cfg_comp.isMC
          elif doResidual == "Data": doResidual = not self.cfg_comp.isMC
          elif doResidual not in [True,False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}"
          if self.cfg_comp.isMC:
            self.jetReCalibrator = JetReCalibrator(mcGT,self.cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath, calculateSeparateCorrections=getattr(cfg_ana,"calculateSeparateCorrections",False))
          else:
            self.jetReCalibrator = JetReCalibrator(dataGT,self.cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath, calculateSeparateCorrections=getattr(cfg_ana,"calculateSeparateCorrections",False))
        self.doPuId = getattr(self.cfg_ana, 'doPuId', True)
        self.jetLepDR = getattr(self.cfg_ana, 'jetLepDR', 0.4)
        self.jetLepArbitration = getattr(self.cfg_ana, 'jetLepArbitration', lambda jet,lepton: lepton) 
        self.lepPtMin = getattr(self.cfg_ana, 'minLepPt', -1)
        self.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep : True)
        self.jetGammaDR =  getattr(self.cfg_ana, 'jetGammaDR', 0.4)
        if(self.cfg_ana.doQG):
            qgdefname="{CMSSW_BASE}/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_antib_13TeV_v1.root"
            self.qglcalc = QGLikelihoodCalculator(getattr(self.cfg_ana,"QGpath",qgdefname).format(CMSSW_BASE= os.environ['CMSSW_BASE']))
        if not hasattr(self.cfg_ana ,"collectionPostFix"):self.cfg_ana.collectionPostFix=""

    def declareHandles(self):
        super(JetAnalyzer, self).declareHandles()
        self.handles['jets']   = AutoHandle( self.cfg_ana.jetCol, 'std::vector<pat::Jet>' )
        self.handles['genJet'] = AutoHandle( self.cfg_ana.genJetCol, 'vector<reco::GenJet>' )
        self.shiftJER = self.cfg_ana.shiftJER if hasattr(self.cfg_ana, 'shiftJER') else 0
        self.handles['rho'] = AutoHandle( self.cfg_ana.rho, 'double' )
    
    def beginLoop(self, setup):
        super(JetAnalyzer,self).beginLoop(setup)

    def process(self, event):
        self.readCollections( event.input )
        rho  = float(self.handles['rho'].product()[0])
        self.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        if self.cfg_ana.copyJetsByValue: 
          import ROOT
          allJets = map(lambda j:Jet(ROOT.pat.Jet(ROOT.edm.Ptr(ROOT.pat.Jet)(ROOT.edm.ProductID(),j,0))), self.handles['jets'].product()) #copy-by-value is safe if JetAnalyzer is ran more than once
        else: 
          allJets = map(Jet, self.handles['jets'].product()) 

        self.deltaMetFromJEC = [0.,0.]
#        print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]
        if self.doJEC:
#            print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId)
            self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, metShift=self.deltaMetFromJEC)

        if self.addJECShifts:
           for delta, shift in [(1.0, "JECUp"), (0.0, ""), (-1.0, "JECDown")]:
              for j1 in allJets:
                corr = self.jetReCalibrator.getCorrection(j1, rho, delta, self.deltaMetFromJEC)
                setattr(j1, "corr"+shift, corr)

        self.allJetsUsedForMET = allJets
#        print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets]

        if self.cfg_comp.isMC:
            self.genJets = [ x for x in self.handles['genJet'].product() ]
            if self.cfg_ana.do_mc_match:
                self.matchJets(event, allJets)
            if getattr(self.cfg_ana, 'smearJets', False):
                self.smearJets(event, allJets)
        
	##Sort Jets by pT 
        allJets.sort(key = lambda j : j.pt(), reverse = True)
	## Apply jet selection
        self.jets = []
        self.jetsFailId = []
        self.jetsAllNoID = []
        self.jetsIdOnly = []
        for jet in allJets:
            if self.testJetNoID( jet ): 
                self.jetsAllNoID.append(jet) 
                # temporary fix since the jetID it's not good for eta>3
                if abs(jet.eta()) <3:
                    if self.testJetID (jet ):

                        if(self.cfg_ana.doQG):
                            jet.qgl_calc =  self.qglcalc.computeQGLikelihood
                            jet.qgl_rho =  rho

                        self.jets.append(jet)
                        self.jetsIdOnly.append(jet)
                    else:
                        self.jetsFailId.append(jet)
                else:
                    self.jets.append(jet)
            elif self.testJetID (jet ):
                self.jetsIdOnly.append(jet)

        ## Clean Jets from leptons
        leptons = []
        if hasattr(event, 'selectedLeptons'):
            leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin and self.lepSelCut(l) ]
        if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'):
            leptons = leptons[:] + event.selectedTaus
        if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'):
            leptons = leptons[:] + event.selectedIsoCleanTrack

        jetsEtaCut = [j for j in self.jets if abs(j.eta()) <  self.cfg_ana.jetEta ]
        self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(jetsEtaCut, leptons, self.jetLepDR, self.jetLepArbitration)
        #self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(self.jets, leptons, self.jetLepDR, self.jetLepArbitration) ##from central
        self.cleanJets    = [j for j in self.cleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        self.cleanJetsFwd = [j for j in self.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
        self.discardedJets = [j for j in self.jets if j not in self.cleanJetsAll]
        if hasattr(event, 'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons:
            event.discardedLeptons = [ l for l in leptons if l not in cleanLeptons ]
            event.selectedLeptons  = [ l for l in event.selectedLeptons if l not in event.discardedLeptons ]

        ## Clean Jets from photons
        photons = []
        if hasattr(event, 'selectedPhotons'):
            if self.cfg_ana.cleanJetsFromFirstPhoton:
                photons = event.selectedPhotons[:1]
            else:
                photons = [ g for g in event.selectedPhotons ] 

        self.gamma_cleanJetsAll = cleanNearestJetOnly(self.cleanJetsAll, photons, self.jetGammaDR)
        self.gamma_cleanJets    = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) <  self.cfg_ana.jetEtaCentral ]
        self.gamma_cleanJetsFwd = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ]
        ###

        if self.cfg_ana.alwaysCleanPhotons:
            self.cleanJets = self.gamma_cleanJets
            self.cleanJetsAll = self.gamma_cleanJetsAll
            self.cleanJetsFwd = self.gamma_cleanJetsFwd

        ## Associate jets to leptons
        leptons = event.inclusiveLeptons if hasattr(event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection( leptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet ]

        for lep in leptons:
            jet = jlpairs[lep]
            if jet is None:
                setattr(lep,"jet"+self.cfg_ana.collectionPostFix,lep)
            else:
                setattr(lep,"jet"+self.cfg_ana.collectionPostFix,jet)
        ## Associate jets to taus 
        taus = getattr(event,'selectedTaus',[])
        jtaupairs = matchObjectCollection( taus, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet ]
        for tau in taus:
            setattr(tau,"jet"+self.cfg_ana.collectionPostFix,jtaupairs[tau])

        #MC stuff
        if self.cfg_comp.isMC:
            self.deltaMetFromJetSmearing = [0, 0]
            for j in self.cleanJetsAll:
                if hasattr(j, 'deltaMetFromJetSmearing'):
                    self.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0]
                    self.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1]

            self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons, self.jetLepDR)
            
            if self.cfg_ana.cleanGenJetsFromPhoton:
                self.cleanGenJets = cleanNearestJetOnly(self.cleanGenJets, photons, self.jetLepDR)

            
            #event.nGenJets25 = 0
            #event.nGenJets25Cen = 0
            #event.nGenJets25Fwd = 0
            #for j in event.cleanGenJets:
            #    event.nGenJets25 += 1
            #    if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1
            #    else:                   event.nGenJets25Fwd += 1
                    
            if self.cfg_ana.do_mc_match:
                self.jetFlavour(event)

        if hasattr(event,"jets"+self.cfg_ana.collectionPostFix): raise RuntimeError, "Event already contains a jet collection with the following postfix: "+self.cfg_ana.collectionPostFix
        setattr(event,"rho"                    +self.cfg_ana.collectionPostFix, self.rho                    ) 
        setattr(event,"deltaMetFromJEC"        +self.cfg_ana.collectionPostFix, self.deltaMetFromJEC        ) 
        setattr(event,"allJetsUsedForMET"      +self.cfg_ana.collectionPostFix, self.allJetsUsedForMET      ) 
        setattr(event,"jets"                   +self.cfg_ana.collectionPostFix, self.jets                   ) 
        setattr(event,"jetsFailId"             +self.cfg_ana.collectionPostFix, self.jetsFailId             ) 
        setattr(event,"jetsAllNoID"            +self.cfg_ana.collectionPostFix, self.jetsAllNoID            ) 
        setattr(event,"jetsIdOnly"             +self.cfg_ana.collectionPostFix, self.jetsIdOnly             ) 
        setattr(event,"cleanJetsAll"           +self.cfg_ana.collectionPostFix, self.cleanJetsAll           ) 
        setattr(event,"cleanJets"              +self.cfg_ana.collectionPostFix, self.cleanJets              ) 
        setattr(event,"cleanJetsFwd"           +self.cfg_ana.collectionPostFix, self.cleanJetsFwd           ) 
        setattr(event,"discardedJets"          +self.cfg_ana.collectionPostFix, self.discardedJets          ) 
        setattr(event,"gamma_cleanJetsAll"     +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsAll     ) 
        setattr(event,"gamma_cleanJets"        +self.cfg_ana.collectionPostFix, self.gamma_cleanJets        ) 
        setattr(event,"gamma_cleanJetsFwd"     +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFwd     ) 


        if self.cfg_comp.isMC:
            setattr(event,"deltaMetFromJetSmearing"+self.cfg_ana.collectionPostFix, self.deltaMetFromJetSmearing) 
            setattr(event,"cleanGenJets"           +self.cfg_ana.collectionPostFix, self.cleanGenJets           )
            setattr(event,"genJets"                +self.cfg_ana.collectionPostFix, self.genJets                )
            if self.cfg_ana.do_mc_match:
                setattr(event,"bqObjects"              +self.cfg_ana.collectionPostFix, self.bqObjects              )
                setattr(event,"cqObjects"              +self.cfg_ana.collectionPostFix, self.cqObjects              )
                setattr(event,"partons"                +self.cfg_ana.collectionPostFix, self.partons                )
                setattr(event,"heaviestQCDFlavour"     +self.cfg_ana.collectionPostFix, self.heaviestQCDFlavour     )

 
        return True

        

    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId() 
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') 
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) 
        
    def testJetNoID( self, jet ):
        # 2 is loose pile-up jet id
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta;

    def jetFlavour(self,event):
        def isFlavour(x,f):
            id = abs(x.pdgId())
            if id > 999: return (id/1000)%10 == f
            if id >  99: return  (id/100)%10 == f
            return id % 100 == f



        self.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,5)) ]
        self.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,4)) ]

        self.partons   = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId())>0 and (abs(p.pdgId()) in [1,2,3,4,5,21]) ) ]
        match = matchObjectCollection2(self.cleanJetsAll,
                                       self.partons,
                                       deltaRMax = 0.3)

        for jet in self.cleanJetsAll:
            parton = match[jet]
            jet.partonId = (parton.pdgId() if parton != None else 0)
            jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers()>0 else 0)
        
        for jet in self.jets:
           (bmatch, dr) = bestMatch(jet, self.bqObjects)
           if dr < 0.4:
               jet.mcFlavour = 5
           else:
               (cmatch, dr) = bestMatch(jet, self.cqObjects) 
               if dr < 0.4:
                   jet.mcFlavour = 4
               else:
                   jet.mcFlavour = 0

        self.heaviestQCDFlavour = 5 if len(self.bqObjects) else (4 if len(self.cqObjects) else 1);
 
    def matchJets(self, event, jets):
        match = matchObjectCollection2(jets,
                                       event.genbquarks + event.genwzquarks,
                                       deltaRMax = 0.3)
        for jet in jets:
            gen = match[jet]
            jet.mcParton    = gen
            jet.mcMatchId   = (gen.sourceId     if gen != None else 0)
            jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0)

        match = matchObjectCollection2(jets,
                                       self.genJets,
                                       deltaRMax = 0.3)
        for jet in jets:
            jet.mcJet = match[jet]


  
    def smearJets(self, event, jets):
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution
       for jet in jets:
            gen = jet.mcJet 
            if gen != None:
               genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta())
               # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
               factor = 1.052 + self.shiftJER*math.hypot(0.012,0.062);
               if   aeta > 2.3: factor = 1.288 + self.shiftJER*math.hypot(0.127,0.154)
               elif aeta > 1.7: factor = 1.134 + self.shiftJER*math.hypot(0.035,0.066)
               elif aeta > 1.1: factor = 1.096 + self.shiftJER*math.hypot(0.017,0.063)
               elif aeta > 0.5: factor = 1.057 + self.shiftJER*math.hypot(0.012,0.056)
               ptscale = max(0.0, (jetpt + (factor-1)*(jetpt-genpt))/jetpt)
               #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale)
               jet.deltaMetFromJetSmearing = [ -(ptscale-1)*jet.rawFactor()*jet.px(), -(ptscale-1)*jet.rawFactor()*jet.py() ]
               if ptscale != 0:
                  jet.setP4(jet.p4()*ptscale)
               # leave the uncorrected unchanged for sync
               jet._rawFactorMultiplier *= (1.0/ptscale) if ptscale != 0 else 1
예제 #8
0
파일: JetAnalyzer.py 프로젝트: smdogra/mTop
class JetAnalyzer(Analyzer):
    """Analyze jets.

    Copied from heppy examples and edit to not rely on heppy examples.

    This analyzer filters the jets that do not correspond to the leptons
    stored in event.selectedLeptons, and puts in the event:
    - jets: all jets passing the pt and eta cuts
    - cleanJets: the collection of jets away from the leptons
    - cleanBJets: the jets passing testBJet, and away from the leptons

    Example configuration:

    jetAna = cfg.Analyzer(
      'JetAnalyzer',
      jetCol = 'slimmedJets'
      # cmg jet input collection
      # pt threshold
      jetPt = 30,
      # eta range definition
      jetEta = 5.0,
      # seed for the btag scale factor
      btagSFseed = 0xdeadbeef,
      # if True, the PF and PU jet ID are not applied, and the jets get flagged
      relaxJetId = False,
      relaxPuJetId = False,
    )
    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        self.btagSF = BTagSF(0, wp='medium')
        self.recalibrateJets = getattr(cfg_ana, 'recalibrateJets', False)

        mcGT = getattr(cfg_ana, 'mcGT', 'Spring16_25nsV6_MC')
        dataGT = getattr(cfg_ana, 'dataGT', 'Spring16_25nsV6_DATA')

        if self.recalibrateJets:
            doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
            if doResidual == "MC":
                doResidual = self.cfg_comp.isMC
            elif doResidual == "Data":
                doResidual = not self.cfg_comp.isMC
            elif doResidual not in [True, False]:
                raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}"
            GT = getattr(cfg_comp, 'jecGT',
                         mcGT if self.cfg_comp.isMC else dataGT)

            # instantiate the jet re-calibrator
            self.jetReCalibrator = JetReCalibrator(
                GT,
                'AK4PFchs',
                doResidual,
                jecPath="%s/src/CMGTools/RootTools/data/jec" %
                os.environ['CMSSW_BASE'])

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

        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol,
                                          'std::vector<pat::Jet>')

        if hasattr(self.cfg_ana, 'leptonCollections'):
            for coll, cms_type in self.cfg_ana.leptonCollections.items():
                self.handles[coll] = AutoHandle(coll, cms_type)

        if self.cfg_comp.isMC:
            self.mchandles['genParticles'] = AutoHandle(
                'packedGenParticles', 'std::vector<pat::PackedGenParticle>')
            self.mchandles['genJets'] = AutoHandle(
                'slimmedGenJets', 'std::vector<reco::GenJet>')

    def beginLoop(self, setup):
        super(JetAnalyzer, self).beginLoop(setup)
        self.counters.addCounter('jets')
        count = self.counters.counter('jets')
        count.register('all events')
        count.register('at least 2 good jets')
        count.register('at least 2 clean jets')
        count.register('at least 1 b jet')
        count.register('at least 2 b jets')

    def process(self, event):

        self.readCollections(event.input)
        miniaodjets = self.handles['jets'].product()

        allJets = []
        event.jets = []
        event.bJets = []
        event.cleanJets = []
        event.cleanBJets = []

        leptons = []
        if hasattr(event, 'selectedLeptons'):
            leptons = event.selectedLeptons
        if hasattr(self.cfg_ana, 'toClean'):
            leptons = getattr(event, self.cfg_ana.toClean)

        if hasattr(self.cfg_ana, 'leptonCollections'):
            for coll in self.cfg_ana.leptonCollections:
                leptons += self.handles[coll].product()

        genJets = None
        if self.cfg_comp.isMC:
            genJets = map(GenJet, self.mchandles['genJets'].product())

        allJets = [Jet(jet) for jet in miniaodjets]

        if self.recalibrateJets:
            self.jetReCalibrator.correctAll(allJets,
                                            event.rho,
                                            delta=0.,
                                            addCorr=True,
                                            addShifts=True)

        for jet in allJets:
            if genJets:
                # Use DeltaR = 0.25 matching like JetMET
                pairs = matchObjectCollection([jet], genJets, 0.25 * 0.25)
                if pairs[jet] is None:
                    pass
                else:
                    jet.matchedGenJet = pairs[jet]
            # Add JER correction for MC jets. Requires gen-jet matching.
            if self.cfg_comp.isMC and hasattr(
                    self.cfg_ana, 'jerCorr') and self.cfg_ana.jerCorr:
                self.jerCorrection(jet)
            # Add JES correction for MC jets.
            if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jesCorr'):
                self.jesCorrection(jet, self.cfg_ana.jesCorr)
            if self.testJet(jet):
                event.jets.append(jet)
            if self.testBJet(jet):
                event.bJets.append(jet)

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

        event.cleanJets, dummy = cleanObjectCollection(event.jets,
                                                       masks=leptons,
                                                       deltaRMin=0.5)
        event.cleanBJets, dummy = cleanObjectCollection(event.bJets,
                                                        masks=leptons,
                                                        deltaRMin=0.5)

        # Attach matched jets to selected + other leptons
        if hasattr(event, 'otherLeptons'):
            leptons += event.otherLeptons

        pairs = matchObjectCollection(leptons, allJets, 0.5 * 0.5)
        # associating a jet to each lepton
        for lepton in leptons:
            jet = pairs[lepton]
            if jet is None:
                lepton.jet = lepton
            else:
                lepton.jet = jet

        # associating a leg to each clean jet
        invpairs = matchObjectCollection(event.cleanJets, leptons, 99999.)
        for jet in event.cleanJets:
            leg = invpairs[jet]
            jet.leg = leg

        for jet in event.cleanJets:
            jet.matchGenParton = 999.0

        event.jets30 = [jet for jet in event.jets if jet.pt() > 30]
        event.cleanJets30 = [jet for jet in event.cleanJets if jet.pt() > 30]
        if len(event.jets30) >= 2:
            self.counters.counter('jets').inc('at least 2 good jets')
        if len(event.cleanJets30) >= 2:
            self.counters.counter('jets').inc('at least 2 clean jets')
        if len(event.cleanBJets) > 0:
            self.counters.counter('jets').inc('at least 1 b jet')
            if len(event.cleanBJets) > 1:
                self.counters.counter('jets').inc('at least 2 b jets')

        # save HTs
        event.HT_allJets = sum([jet.pt() for jet in allJets])
        event.HT_jets = sum([jet.pt() for jet in event.jets])
        event.HT_bJets = sum([jet.pt() for jet in event.bJets])
        event.HT_cleanJets = sum([jet.pt() for jet in event.cleanJets])
        event.HT_jets30 = sum([jet.pt() for jet in event.jets30])
        event.HT_cleanJets30 = sum([jet.pt() for jet in event.cleanJets30])

        return True

    def jerCorrection(self, jet):
        ''' Adds JER correction according to first method at
        https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution

        Requires some attention when genJet matching fails.
        '''
        if not hasattr(jet, 'matchedGenJet'):
            return
        #import pdb; pdb.set_trace()
        corrections = [0.052, 0.057, 0.096, 0.134, 0.288]
        maxEtas = [0.5, 1.1, 1.7, 2.3, 5.0]
        eta = abs(jet.eta())
        for i, maxEta in enumerate(maxEtas):
            if eta < maxEta:
                pt = jet.pt()
                deltaPt = (pt - jet.matchedGenJet.pt()) * corrections[i]
                totalScale = (pt + deltaPt) / pt

                if totalScale < 0.:
                    totalScale = 0.
                jet.scaleEnergy(totalScale)
                break

    def jesCorrection(self, jet, scale=0.):
        ''' Adds JES correction in number of sigmas (scale)
        '''
        # Do nothing if nothing to change
        if scale == 0.:
            return
        unc = jet.uncOnFourVectorScale()
        totalScale = 1. + scale * unc
        if totalScale < 0.:
            totalScale = 0.
        jet.scaleEnergy(totalScale)

    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId()
        jet.pfJetIdPassed = jet.jetID("POG_PFID_Loose")
        puJetId = self.cfg_ana.relaxPuJetId or jet.puJetIdPassed
        pfJetId = self.cfg_ana.relaxJetId or jet.pfJetIdPassed
        return puJetId and pfJetId

    def testJet(self, jet):
        pt = jet.pt()
        if hasattr(self.cfg_ana,
                   'ptUncTolerance') and self.cfg_ana.ptUncTolerance:
            pt = max(pt, pt * jet.corrJECUp / jet.corr,
                     pt * jet.corrJECDown / jet.corr)
        return pt > self.cfg_ana.jetPt and \
            abs( jet.eta() ) < self.cfg_ana.jetEta and \
            self.testJetID(jet)

    def testBJet(self, jet, csv_cut=0.8):
        # medium csv working point
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation74X
        jet.btagMVA = jet.btag('pfCombinedInclusiveSecondaryVertexV2BJetTags')
        # jet.btagFlag = jet.btagMVA > csv_cut

        # Use the following once we start applying data-MC scale factors:
        jet.btagFlag = self.btagSF.isBTagged(
            pt=jet.pt(),
            eta=jet.eta(),
            csv=jet.btag("pfCombinedInclusiveSecondaryVertexV2BJetTags"),
            jetflavor=abs(jet.partonFlavour()),
            is_data=not self.cfg_comp.isMC,
            csv_cut=csv_cut)

        return self.testJet(jet) and \
            abs(jet.eta()) < 2.4 and \
            jet.btagFlag and \
            self.testJetID(jet)
예제 #9
0
class JetSelector(Analyzer):
    """Analyze jets.

	Copied from heppy examples and edit to not rely on heppy examples.

	This analyzer filters the jets that do not correspond to the leptons
	stored in event.selectedLeptons, and puts in the event:
	- jets: all jets passing the pt and eta cuts
	- cleanJets: the collection of jets away from the leptons
	- cleanBJets: the jets passing testBJet, and away from the leptons

	Example configuration:

	jetAna = cfg.Analyzer(
	  'JetSelector',
	  jetCol = 'slimmedJets'
	  # cmg jet input collection
	  # pt threshold
	  jetPt = 30,
	  # eta range definition
	  jetEta = 5.0,
	  # seed for the btag scale factor
	  btagSFseed = 0xdeadbeef,
	  # if True, the PF and PU jet ID are not applied, and the jets get flagged
	  relaxJetId = False,
	  relaxPuJetId = False,
	)
	"""
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetSelector, self).__init__(cfg_ana, cfg_comp, looperName)
        self.btagSF = BTagSF(0, wp='medium')
        self.recalibrateJets = getattr(cfg_ana, 'recalibrateJets', False)

        mcGT = getattr(cfg_ana, 'mcGT', 'Spring16_25nsV6_MC')
        dataGT = getattr(cfg_ana, 'dataGT', 'Spring16_25nsV6_DATA')

        if self.recalibrateJets:
            doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
            if doResidual == "MC":
                doResidual = self.cfg_comp.isMC
            elif doResidual == "Data":
                doResidual = not self.cfg_comp.isMC
            elif doResidual not in [True, False]:
                raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}"
            GT = getattr(cfg_comp, 'jecGT',
                         mcGT if self.cfg_comp.isMC else dataGT)

            # instantiate the jet re-calibrator
            self.jetReCalibrator = JetReCalibrator(
                GT,
                'AK4PFchs',
                doResidual,
                jecPath="%s/src/CMGTools/RootTools/data/jec" %
                os.environ['CMSSW_BASE'])

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

        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol,
                                          'std::vector<pat::Jet>')

        if self.cfg_comp.isMC:
            self.mchandles['genParticles'] = AutoHandle(
                'packedGenParticles', 'std::vector<pat::PackedGenParticle>')
            self.mchandles['genJets'] = AutoHandle(
                'slimmedGenJets', 'std::vector<reco::GenJet>')

    def beginLoop(self, setup):
        super(JetSelector, self).beginLoop(setup)
        self.counters.addCounter('jets')
        count = self.counters.counter('jets')
        count.register('all events')
        count.register('at least 2 good jets')
        count.register('at least 2 clean jets')
        count.register('exactly 2 b jets')

    def process(self, event):

        self.counters.counter('jets').inc('all events')
        self.readCollections(event.input)
        miniaodjets = self.handles['jets'].product()

        allJets = []

        to_clean_against = []
        if hasattr(self.cfg_ana, 'toClean'):
            for collection in self.cfg_ana.toClean:
                to_clean_against += getattr(event, collection)

        genJets = None
        if self.cfg_comp.isMC:
            genJets = map(GenJet, self.mchandles['genJets'].product())

        allJets = [Jet(jet) for jet in miniaodjets]

        if self.recalibrateJets:
            self.jetReCalibrator.correctAll(allJets,
                                            event.rho,
                                            delta=0.,
                                            addCorr=True,
                                            addShifts=True)

        for jet in allJets:
            if genJets:
                # Use DeltaR = 0.25 matching like JetMET
                pairs = matchObjectCollection([jet], genJets, 0.25 * 0.25)
                if pairs[jet] is None:
                    pass
                else:
                    jet.matchedGenJet = pairs[jet]
            # Add JER correction for MC jets. Requires gen-jet matching.
            if self.cfg_comp.isMC and hasattr(
                    self.cfg_ana, 'jerCorr') and self.cfg_ana.jerCorr:
                self.jerCorrection(jet)
            # Add JES correction for MC jets.
            if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jesCorr'):
                self.jesCorrection(jet, self.cfg_ana.jesCorr)
            jet.btagMVA = jet.btag(
                'pfCombinedInclusiveSecondaryVertexV2BJetTags'
            )  #TODO switch to deepCSV
            jet.btagged = self.btagSF.isBTagged(
                pt=jet.pt(),
                eta=jet.eta(),
                csv=jet.btag("pfCombinedInclusiveSecondaryVertexV2BJetTags"),
                jetflavor=abs(jet.hadronFlavour()),
                is_data=not self.cfg_comp.isMC,
                csv_cut=
                0.800  #CSVM from https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation80X
            )
            ## if self.testJet(jet):
            ## 	event.jets.append(jet)
            ## if self.testBJet(jet):
            ## 	event.bJets.append(jet)

        allJets = [
            jet for jet in allJets if bool(jet.jetID("POG_PFID_Loose"))
            if jet.pt() > 20. if abs(jet.eta()) < 2.4
        ]
        if len(allJets) < 2: return False
        self.counters.counter('jets').inc('at least 2 good jets')

        event.jets, dummy = cleanObjectCollection(allJets,
                                                  masks=to_clean_against,
                                                  deltaRMin=0.5)
        if len(event.jets) < 2: return False
        self.counters.counter('jets').inc('at least 2 clean jets')

        event.bJets = [jet for jet in event.jets if jet.btagged]
        if len(event.bJets) != 2: return False
        self.counters.counter('jets').inc('exactly 2 b jets')

        # save HTs
        event.HT_jets = sum([jet.pt() for jet in event.jets])
        event.HT_bJets = sum([jet.pt() for jet in event.bJets])

        return True

    def jerCorrection(self, jet):
        ''' Adds JER correction according to first method at
		https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution

		Requires some attention when genJet matching fails.
		'''
        if not hasattr(jet, 'matchedGenJet'):
            return
        #import pdb; pdb.set_trace()
        corrections = [0.052, 0.057, 0.096, 0.134, 0.288]
        maxEtas = [0.5, 1.1, 1.7, 2.3, 5.0]
        eta = abs(jet.eta())
        for i, maxEta in enumerate(maxEtas):
            if eta < maxEta:
                pt = jet.pt()
                deltaPt = (pt - jet.matchedGenJet.pt()) * corrections[i]
                totalScale = (pt + deltaPt) / pt

                if totalScale < 0.:
                    totalScale = 0.
                jet.scaleEnergy(totalScale)
                break

    def jesCorrection(self, jet, scale=0.):
        ''' Adds JES correction in number of sigmas (scale)
		'''
        # Do nothing if nothing to change
        if scale == 0.:
            return
        unc = jet.uncOnFourVectorScale()
        totalScale = 1. + scale * unc
        if totalScale < 0.:
            totalScale = 0.
        jet.scaleEnergy(totalScale)
예제 #10
0
class monoXPuppiJetAnalyzer(Analyzer):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    @staticmethod
    def puppiCorrector(pJet):  #self, pJet):
        correctionFilePath = "%s/src/CMGTools//MonoXAnalysis/cfg/puppiCorr.root" % os.environ[
            'CMSSW_BASE']
        #print "---- Correction file for PUPPI: ",correctionFilePath
        correctionFile = TFile.Open(correctionFilePath)
        puppisd_corrGEN = correctionFile.Get("puppiJECcorr_gen")
        puppisd_corrRECO_cen = correctionFile.Get("puppiJECcorr_reco_0eta1v3")
        puppisd_corrRECO_for = correctionFile.Get(
            "puppiJECcorr_reco_1v3eta2v5")

        genCorr = 1.
        recoCorr = 1.
        totalWeight = 1.

        genCorr = puppisd_corrGEN.Eval(pJet.pt())

        if (math.fabs(pJet.eta()) <= 1.3):
            recoCorr = puppisd_corrRECO_cen.Eval(pJet.pt())
        else:
            if (math.fabs(pJet.eta()) > 1.3):
                recoCorr = puppisd_corrRECO_for.Eval(pJet.pt())

        totalWeight = genCorr * recoCorr
        pJet_massCorr = totalWeight * pJet.mass()

        return pJet_massCorr

    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(monoXPuppiJetAnalyzer, self).__init__(cfg_ana, cfg_comp,
                                                    looperName)
        mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,
                                           'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(
            self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        self.addJECShifts = self.cfg_ana.addJECShifts if hasattr(
            self.cfg_ana, 'addJECShifts') else 0
        if self.recalibrateJets == "MC":
            self.recalibrateJets = self.cfg_comp.isMC
        elif self.recalibrateJets == "Data":
            self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True, False]:
            raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC !=
                                              0) or self.addJECShifts
        if self.doJEC:
            doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
            if doResidual == "MC": doResidual = self.cfg_comp.isMC
            elif doResidual == "Data": doResidual = not self.cfg_comp.isMC
            elif doResidual not in [True, False]:
                raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}"
            GT = getattr(cfg_comp, 'jecGT',
                         mcGT if self.cfg_comp.isMC else dataGT)
            # instantiate the jet re-calibrator
            self.jetReCalibrator = JetReCalibrator(GT,
                                                   cfg_ana.recalibrationType,
                                                   doResidual, cfg_ana.jecPath)

        self.jetLepDR = self.cfg_ana.jetLepDR if hasattr(
            self.cfg_ana, 'jetLepDR') else 0.5
        self.lepPtMin = self.cfg_ana.minLepPt if hasattr(
            self.cfg_ana, 'minLepPt') else -1

    def declareHandles(self):
        super(monoXPuppiJetAnalyzer, self).declareHandles()
        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol,
                                          'std::vector<pat::Jet>')
        self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double')

    def beginLoop(self, setup):
        super(monoXPuppiJetAnalyzer, self).beginLoop(setup)

    def process(self, event):
        self.readCollections(event.input)
        rho = float(self.handles['rho'].product()[0])
        self.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        allJets = map(Jet, self.handles['jets'].product())

        self.deltaMetFromJEC = [0., 0.]
        self.type1METCorr = [0., 0., 0.]
        if self.doJEC:
            if not self.recalibrateJets:  # check point that things won't change
                jetsBefore = [(j.pt(), j.eta(), j.phi(), j.rawFactor())
                              for j in allJets]
            self.jetReCalibrator.correctAll(allJets,
                                            rho,
                                            delta=self.shiftJEC,
                                            addCorr=True,
                                            addShifts=self.addJECShifts,
                                            metShift=self.deltaMetFromJEC,
                                            type1METCorr=self.type1METCorr)
            if not self.recalibrateJets:
                jetsAfter = [(j.pt(), j.eta(), j.phi(), j.rawFactor())
                             for j in allJets]
                if len(jetsBefore) != len(jetsAfter):
                    print "ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % (
                        jetsBefore, jetsAfter)
                else:
                    for (told, tnew) in zip(jetsBefore, jetsAfter):
                        if (deltaR2(told[1], told[2], tnew[1],
                                    tnew[2])) > 0.0001:
                            print "ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % (
                                told, tnew)
                        elif abs(told[0] - tnew[0]) / (
                                told[0] + tnew[0]) > 0.5e-3 or abs(
                                    told[3] - tnew[3]) > 0.5e-3:
                            print "ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % (
                                told, tnew)

        ## Apply jet selection
        event.puppiJets = []
        event.puppiJetsNoID = []
        event.puppiAK08Jets = []

        firstJet = True
        #global jetPuppiAk08
        for jet in allJets:
            if self.testJetNoID(jet):
                event.puppiJetsNoID.append(jet)
                if self.testJetID(jet):
                    #        if firstJet:
                    #          jetPuppiAk08 = jet
                    #          print "FIRST JET!!!"
                    #          firstJet = False
                    #        else:
                    #          print "SECOND JET"
                    #          jetPuppiAk08+=jet
                    jet.puppiMassCorrected = self.puppiCorrector(jet)
                    event.puppiJets.append(jet)
        #jetPuppiAk08.puppiMassCorrected = self.puppiCorrector(jetPuppiAk08)
        #event.puppiAK08Jets.append(jetPuppiAk08)

        ## Associate jets to leptons
        leptons = event.inclusiveLeptons if hasattr(
            event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet]

        for lep in leptons:
            jet = jlpairs[lep]
            if jet is None:
                lep.puppijet = lep.jet
            else:
                lep.puppijet = jet

    def testJetID(self, jet):
        #jet.puJetIdPassed = jet.puJetId()
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose')
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed
            #return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId))

    def testJetNoID(self, jet):
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta
class EventInterpretationBase( Analyzer ):
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(EventInterpretationBase,self).__init__(cfg_ana, cfg_comp, looperName)
        self.selectFat = self.cfg_ana.selectFat
        self.selectPairLNu = self.cfg_ana.selectPairLNu
        self.selectPairLL = self.cfg_ana.selectPairLL
        self.selectPairJJ = self.cfg_ana.selectPairJJ
        self.selectPairJJNuNu = self.cfg_ana.selectPairJJNuNu
        self.isMC =cfg_comp.isMC
        if hasattr(cfg_ana,'matchDR'):
            self.matchDR = cfg_ana.matchDR
        else:
            self.matchDR = 0.2

        mcGT   = cfg_ana.mcGT   if hasattr(cfg_ana,'mcGT')   else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        if   self.recalibrateJets == "MC"  : self.recalibrateJets =     self.cfg_comp.isMC
        elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True,False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC != 0)
        if self.doJEC:
          if self.cfg_comp.isMC:
              if hasattr(self.cfg_comp,'globalTag'):
                  self.jetReCalibrator = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationType, False,cfg_ana.jecPath)
                  self.jetReCalibratorFAT = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationTypeFAT, False,cfg_ana.jecPath)

              else:
                  self.jetReCalibrator = JetReCalibrator(mcGT,self.cfg_ana.recalibrationType, False,cfg_ana.jecPath)
                  self.jetReCalibratorFAT = JetReCalibrator(mcGT,self.cfg_ana.recalibrationTypeFAT, False,cfg_ana.jecPath)
          else:
              if hasattr(self.cfg_comp,'globalTag'):
                  self.jetReCalibrator = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationType, True,cfg_ana.jecPath)
                  self.jetReCalibratorFAT = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationTypeFAT, True,cfg_ana.jecPath)
              else:    
                  self.jetReCalibrator = JetReCalibrator(dataGT,self.cfg_ana.recalibrationType, True,cfg_ana.jecPath)
                  self.jetReCalibratorFAT = JetReCalibrator(dataGT,self.cfg_ana.recalibrationTypeFAT, True,cfg_ana.jecPath)          

        self.attachBTag = cfg_ana.attachBTag    
        if self.attachBTag:
            self.btagDiscriminator = cfg_ana.btagDiscriminator
            
        if hasattr(cfg_ana,'doSkim'):
            self.doSkim = cfg_ana.doSkim
        else:
            self.doSkim=False
            
            
    def declareHandles(self):
        super(EventInterpretationBase, self).declareHandles()
        self.handles['packed'] = AutoHandle( 'packedPFCandidates', 'std::vector<pat::PackedCandidate>' )
        self.handles['rho'] = AutoHandle( self.cfg_ana.rho, 'double' )
        if self.attachBTag or self.doSkim:
            self.handles['jets'] = AutoHandle( self.cfg_ana.standardJets, 'std::vector<pat::Jet>' )
            self.handles['fatjets'] = AutoHandle( self.cfg_ana.fatJets, 'std::vector<pat::Jet>' )
            self.handles['subjets'] = AutoHandle( (self.cfg_ana.subJets,'SubJets'), 'std::vector<pat::Jet>' )



            

    def removeLeptonFootPrint(self,leptons,cands):
        toRemove=[]
        cList=list(cands)
        for lepton in leptons:

            for p in range(0,lepton.numberOfSourceCandidatePtrs()):
                index = lepton.sourceCandidatePtr(p).key()
                if not cands[index] in toRemove: 
                    toRemove.append(cands[index])

        for r in toRemove:
            cList.remove(r)
        return cList


    def matchSubJets(self,jets,genquarks):
        for j in jets:
            for s in j.subjets_SD+j.subjets:
                s.mcquark = None
                s.matched=0
                for g in genquarks:
                    if deltaR(s.eta(),s.phi(),g.eta(),g.phi())<self.matchDR:
                        s.matched=1
                        s.mcquark = g
                        break;

    def skim(self,leptons,met):
        cleanedJets = []
        for jet in self.handles['fatjets'].product():
            overlap=False
            for lepton in leptons:
                if deltaR(jet.eta(),jet.phi(),lepton.eta(),lepton.phi())<0.8:
                    overlap=True
                    break;
            if not overlap:    
                cleanedJets.append(jet)
        nJets = len(cleanedJets)        
        nLeptons = len(leptons)
        if (nLeptons>0 and nJets>0) or nJets>1 or (nJets>0 and met.pt()>300):
            return True
        return False
                
                

                    
    def makeFatJets(self,cands):
        toolboxFat  = PyJetToolbox(cands)
        toolboxFat.setInterface(True,self.cfg_ana.ktPowerFat,self.cfg_ana.rFat)
        toolboxFat.setMassDrop(self.cfg_ana.massdrop)
        toolboxFat.setSubjets(True,'inc',self.cfg_ana.subjets)
        toolboxFat.setPruning(self.cfg_ana.prunning)
        toolboxFat.setNtau(True)
        if hasattr(self.cfg_ana,'softdrop_beta'):
            toolboxFat.setSoftDrop(self.cfg_ana.softdrop,self.cfg_ana.softdrop_beta,self.cfg_ana.softdrop_zeta)
        else:
            toolboxFat.setSoftDrop(self.cfg_ana.softdrop)
        # Lets cluster !! Fat jets first
        fatJets=toolboxFat.inclusiveJets(200.0,True)
        filtered = filter(self.selectFat,fatJets)

        ##Apply JECS in SoftDrop and Pruned:
        if self.jetReCalibratorFAT is not None:

            prunedJets=[]
            for j in fatJets:
                prunedJets.append(j.softDropJet)
                prunedJets.append(j.prunedJet)
                
            self.jetReCalibratorFAT.correctAll(prunedJets, self.rho, self.shiftJEC,True,False,[0.,0.],[0.,0.,0.])
            for p in prunedJets:
                p.setRawFactor(1.0/p.corr)
        standardFatJets = self.handles['fatjets'].product()

        if self.attachBTag:
            for fat in filtered:
                for standardFat in standardFatJets:
                    fat.btag = standardFat.bDiscriminator(self.btagDiscriminator)
                for j in fat.subjets_SD+fat.subjets:
                    for standard in self.handles['subjets'].product():
                        if deltaR(j.eta(),j.phi(),standard.eta(),standard.phi())<0.1:
                            j.btag = standard.bDiscriminator(self.btagDiscriminator)
                            break


            
        return filtered

    def makeSatelliteJets(self,cands):
        toolbox  = PyJetToolbox(cands)
        toolbox.setInterface(True,self.cfg_ana.ktPower,self.cfg_ana.r)
        toolbox.setMassDrop(False)
        toolbox.setSubjets(False,'inc',2)
        toolbox.setPruning(False)
        toolbox.setNtau(False)
        toolbox.setSoftDrop(False)       
        unfiltered =  toolbox.inclusiveJets(30.0,False)




        if self.attachBTag:
            for j in unfiltered:
                    for standard in self.handles['jets'].product():
                        if deltaR(j.eta(),j.phi(),standard.eta(),standard.phi())<0.1:
                            j.btag = standard.bDiscriminator(self.btagDiscriminator)
                            break

        if self.jetReCalibrator is not None:
            self.jetReCalibrator.correctAll(unfiltered, self.rho, self.shiftJEC,True,False,[0.,0.],[0.,0.,0.])
            for p in unfiltered:
                p.setRawFactor(1.0/p.corr)


            filtered=filter(lambda x: x.pt()>30, unfiltered)    
            return filtered
        else:
            return unfiltered

    def removeJetFootPrint(self,jets,cands):


        toRemove=[]
        for j in jets:
            toRemove.extend(j.constituents)
        out=list(set(cands)-set(toRemove))
        return out


    def topology(self,obj):

        #first clean nicely the jets from leptons and subjets
        objToClean=[]
        if abs(obj['pair'].leg1.pdgId())==23:
            objToClean.extend([obj['pair'].leg1.leg1,obj['pair'].leg1.leg2])
#            print 'Z->ll', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi(),obj['pair'].leg1.leg2.pt(),obj['pair'].leg1.leg2.eta(),obj['pair'].leg1.leg2.phi()
        if abs(obj['pair'].leg1.pdgId())==24:
            objToClean.extend([obj['pair'].leg1.leg1])
#            print 'W->lnu', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi()

        if abs(obj['pair'].leg1.pdgId())==1:
            objToClean.extend(obj['pair'].leg1.subjets)

        if abs(obj['pair'].leg2.pdgId())==23:
            objToClean.extend([obj['pair'].leg2.leg1,obj['pair'].leg2.leg2])
        if abs(obj['pair'].leg2.pdgId())==24:
            objToClean.extend([obj['pair'].leg2.leg1])
        if abs(obj['pair'].leg2.pdgId())==1:
            objToClean.extend(obj['pair'].leg2.subjets)
#            print 'jet', obj['pair'].leg2.pt(),obj['pair'].leg2.eta(),obj['pair'].leg2.phi()

        newJets=[]    
        for j in  obj['satelliteJets']:
            keep=True
            for c in objToClean:
                dr=deltaR(j.eta(),j.phi(),c.eta(),c.phi())
#                print 'dr=',dr
                if dr<0.4:
                    keep=False
                    break
            if keep:
#                print 'filtered satellite jet',j.pt(),j.eta(),j.phi() 
                newJets.append(j)


        obj['satelliteJets']=newJets            

        if len(obj['satelliteJets'])<2:
            obj['vbfDEta'] = -1.0
            obj['vbfMJJ'] = -1.0
        else:            
            j1 = obj['satelliteJets'][0]
            j2 = obj['satelliteJets'][1]
            obj['vbfDEta'] = abs(j1.eta()-j2.eta())
            obj['vbfMJJ'] = (j1.p4()+j2.p4()).M()

        NL = 0     
        NM = 0     
        NT = 0     


        bestBTag=None
        minDR=1000.0
        for s in obj['satelliteJets']:
           btag = s.bTag()
           if btag>0.423:
               NL=NL+1
               DR=deltaR(obj['pair'].eta(),obj['pair'].phi(),s.eta(),s.phi())
               if DR<minDR:
                   bestBTag=s
                   minDR=DR
           if btag>0.814:
               NM=NM+1
           if btag>0.941:
               NT=NT+1
        obj['nLooseBTags'] = NL        
        obj['nMediumBTags'] = NM        
        obj['nTightBTags'] = NT    

        
        if bestBTag==None:
            obj['topMass'] = -1
        else:    
            obj['topMass'] = (bestBTag.p4()+s.p4()).mass()

    def beginLoop(self, setup):
        super(EventInterpretationBase,self).beginLoop(setup)

    def process(self, event):
        self.readCollections( event.input )
        rho  = float(self.handles['rho'].product()[0])
        self.rho = rho
예제 #12
0
class JetAnalyzer(Analyzer):

    """Analyze jets.

    Copied from heppy examples and edit to not rely on heppy examples.

    This analyzer filters the jets that do not correspond to the leptons
    stored in event.selectedLeptons, and puts in the event:
    - jets: all jets passing the pt and eta cuts
    - cleanJets: the collection of jets away from the leptons
    - cleanBJets: the jets passing testBJet, and away from the leptons

    Example configuration:

    jetAna = cfg.Analyzer(
      'JetAnalyzer',
      jetCol = 'slimmedJets'
      # cmg jet input collection
      # pt threshold
      jetPt = 30,
      # eta range definition
      jetEta = 5.0,
      # seed for the btag scale factor
      btagSFseed = 0xdeadbeef,
      # if True, the PF and PU jet ID are not applied, and the jets get flagged
      relaxJetId = False,
      relaxPuJetId = False,
    )
    """

    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        self.btagSF = BTagSF(seed=getattr(self.cfg_ana, 'btagSFseed', 0), 
                             mc_eff_file=getattr(self.cfg_ana, 'mc_eff_file'),
                             sf_file=getattr(self.cfg_ana, 'sf_file'),
                             wp=getattr(self.cfg_ana, 'btag_wp', 'medium'),
                             )
        self.recalibrateJets = getattr(cfg_ana, 'recalibrateJets', False)

        mcGT = getattr(cfg_ana, 'mcGT', 'Spring16_25nsV6_MC')
        dataGT = getattr(cfg_ana, 'dataGT', 'Spring16_25nsV6_DATA')

        if self.recalibrateJets:
            doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
            if doResidual == "MC":
                doResidual = self.cfg_comp.isMC
            elif doResidual == "Data":
                doResidual = not self.cfg_comp.isMC
            elif doResidual not in [True, False]:
                raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}"
            GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT)

            # instantiate the jet re-calibrator
            self.jetReCalibrator = JetReCalibrator(GT, 'AK4PFchs', doResidual, jecPath="%s/src/CMGTools/RootTools/data/jec" % os.environ['CMSSW_BASE'])

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

        # self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>')
        # try to use recomputed jets, but if it fails, resort to normal slimmedJets in miniAODs
        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>', mayFail=True, fallbackLabel='slimmedJets', lazy=False)

        if self.cfg_comp.isMC:
            self.mchandles['genParticles'] = AutoHandle('packedGenParticles', 'std::vector<pat::PackedGenParticle>')
            self.mchandles['genJets'     ] = AutoHandle('slimmedGenJets'    , 'std::vector<reco::GenJet>'          )

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

    def process(self, event):

        self.readCollections(event.input)
        
        # create Heppy Jet objects
        allJets = map(Jet, self.handles['jets'].product())

        # create intially empty jet collections
        event.jets  = []
        event.bJets = []
        event.cleanJets   = OrderedDict()
        event.cleanJets30 = OrderedDict()
        event.cleanBJets  = OrderedDict()
        
        # selected leptons as defined in the analyzer prior to this
        leptons = getattr(event, 'selectedLeptons', [])

        genJets = None
        if self.cfg_comp.isMC:
            genJets = map(GenJet, self.mchandles['genJets'].product())
            
        # recalibrate jets
        if self.recalibrateJets:
            self.jetReCalibrator.correctAll(allJets, event.rho, delta=0., metShift=[0.,0.], addCorr=True, addShifts=True)

        # fill the various jet collections and
        # possibly correct jets (if configured to do so)
        for jet in allJets:
            if genJets:
                # Use DeltaR = 0.25 matching like JetMET
                pairs = matchObjectCollection([jet], genJets, 0.25 * 0.25)
                if pairs[jet] is None:
                    pass
                else:
                    jet.matchedGenJet = pairs[jet]
                    
            # Add JER/JES correction for MC jets. Requires gen-jet matching.
            # Add JES correction for MC jets.
            if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jerCorr') and self.cfg_ana.jerCorr: self.jerCorrection(jet)
            if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jesCorr')                         : self.jesCorrection(jet, self.cfg_ana.jesCorr)
            
            # preselect jets
            if self.testJet(jet) : event.jets.append(jet)
            
            # compute deepjet scores only once
            self._prepareDeepJet(jet, year=self.cfg_ana.year, wp=getattr(self.cfg_ana, 'btag_wp', 'medium'))

            # create collection of bjets
            if self.testBJet(jet, 
                             year=self.cfg_ana.year, 
                             wp=getattr(self.cfg_ana, 'btag_wp', 'medium'), 
                             final_state='tot'): 
                event.bJets.append(jet)

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

        for final_state in ['mmm', 'mem', 'eee', 'eem']:
            
            if final_state not in leptons.keys():
                continue

            # RM: found out that there's not a lot of final state dependency,
            #     so we'll use the inclusive measurement that has better stats
            # preselect jets, with the appropriate btag SF correction **final state dependent**!
            # event.bJets = []
            # for jet in event.jets:
            #     if self.testBJet(jet, 
            #                      year=self.cfg_ana.year, 
            #                      wp=getattr(self.cfg_ana, 'btag_wp', 'medium'), 
            #                      final_state=final_state): 
            #         event.bJets.append(jet)
                        
            # clean jets from selected leptons (per final state!)
            event.cleanJets [final_state], dummy = cleanObjectCollection(event.jets , masks=leptons[final_state], deltaRMin=0.5)
            event.cleanBJets[final_state], dummy = cleanObjectCollection(event.bJets, masks=leptons[final_state], deltaRMin=0.5)

            pairs = matchObjectCollection(leptons[final_state], allJets, 0.5 * 0.5)
            # associating a jet to each lepton
            for lepton in leptons[final_state]:
                jet = pairs[lepton]
                if jet is None:
                    lepton.jet = lepton
                else:
                    lepton.jet = jet

            # associating to each (clean) jet the lepton that's closest to it
            invpairs = matchObjectCollection(event.cleanJets[final_state], leptons[final_state], 99999.)
            for jet in event.cleanJets[final_state]:
                leg = invpairs[jet]
                jet.leg = leg

            for jet in event.cleanJets[final_state]:
                jet.matchGenParton = 999.0

            event.jets30                   = [jet for jet in event.jets                   if jet.pt() > 30]
            event.cleanJets30[final_state] = [jet for jet in event.cleanJets[final_state] if jet.pt() > 30]
                                    
        return True

    def jerCorrection(self, jet):
        ''' Adds JER correction according to first method at
        https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution

        Requires some attention when genJet matching fails.
        '''
        if not hasattr(jet, 'matchedGenJet'):
            return
        #import pdb; pdb.set_trace()
        corrections = [0.052, 0.057, 0.096, 0.134, 0.288]
        maxEtas = [0.5, 1.1, 1.7, 2.3, 5.0]
        eta = abs(jet.eta())
        for i, maxEta in enumerate(maxEtas):
            if eta < maxEta:
                pt = jet.pt()
                deltaPt = (pt - jet.matchedGenJet.pt()) * corrections[i]
                totalScale = (pt + deltaPt) / pt

                if totalScale < 0.:
                    totalScale = 0.
                jet.scaleEnergy(totalScale)
                break

    def jesCorrection(self, jet, scale=0.):
        ''' Adds JES correction in number of sigmas (scale)
        '''
        # Do nothing if nothing to change
        if scale == 0.:
            return
        unc = jet.uncOnFourVectorScale()
        totalScale = 1. + scale * unc
        if totalScale < 0.:
            totalScale = 0.
        jet.scaleEnergy(totalScale)

    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId()
        jet.pfJetIdPassed = jet.jetID("POG_PFID_Tight")
        puJetId = self.cfg_ana.relaxPuJetId or jet.puJetIdPassed 
        pfJetId = self.cfg_ana.relaxJetId or jet.pfJetIdPassed 
        return puJetId and pfJetId

    def testJet(self, jet):
        pt = jet.pt()
        if hasattr(self.cfg_ana, 'ptUncTolerance') and self.cfg_ana.ptUncTolerance:
            pt = max(pt, pt * jet.corrJECUp/jet.corr, pt * jet.corrJECDown/jet.corr)
        return pt > self.cfg_ana.jetPt and \
            abs( jet.eta() ) < self.cfg_ana.jetEta and \
            self.testJetID(jet)

    def _prepareDeepJet(self, jet, year, wp):
        jet.deepflavour_prob_b    = jet.btag('pfDeepFlavourJetTags:probb')
        jet.deepflavour_prob_bb   = jet.btag('pfDeepFlavourJetTags:probbb')
        jet.deepflavour_prob_lepb = jet.btag('pfDeepFlavourJetTags:problepb')
        jet.deepflavour_score = jet.deepflavour_prob_b   + \
                                jet.deepflavour_prob_bb  + \
                                jet.deepflavour_prob_lepb

        jet.pass_deepflavour = jet.deepflavour_score >= deepflavour_wp[year][wp]

    def testBJet(self, jet, year, wp, final_state):    
        '''
        Test DeepFlavour
        including scale factors
        '''
        # Use the following once we start applying data-MC scale factors:
        jet.btagFlag = self.btagSF.isBTagged(
            pt          = jet.pt(),
            eta         = jet.eta(),
            deepjet     = jet.deepflavour_score,
            jetflavor   = abs(jet.partonFlavour()),
            is_data     = not self.cfg_comp.isMC,
            deepjet_cut = deepflavour_wp[year][wp],
            final_state = final_state,
        )

        return self.testJet(jet) and \
            abs(jet.eta()) < 2.4 and \
            jet.btagFlag and \
            self.testJetID(jet)
예제 #13
0
class monoXFatJetAnalyzer(Analyzer):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(monoXFatJetAnalyzer, self).__init__(cfg_ana, cfg_comp,
                                                  looperName)
        mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,
                                           'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(
            self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        self.addJECShifts = self.cfg_ana.addJECShifts if hasattr(
            self.cfg_ana, 'addJECShifts') else 0
        if self.recalibrateJets == "MC":
            self.recalibrateJets = self.cfg_comp.isMC
        elif self.recalibrateJets == "Data":
            self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True, False]:
            raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC !=
                                              0) or self.addJECShifts
        if self.doJEC:
            doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data')
            if doResidual == "MC": doResidual = self.cfg_comp.isMC
            elif doResidual == "Data": doResidual = not self.cfg_comp.isMC
            elif doResidual not in [True, False]:
                raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}"
            GT = getattr(cfg_comp, 'jecGT',
                         mcGT if self.cfg_comp.isMC else dataGT)
            # instantiate the jet re-calibrator
            self.jetReCalibrator = JetReCalibrator(GT,
                                                   cfg_ana.recalibrationType,
                                                   doResidual, cfg_ana.jecPath)

        self.jetLepDR = self.cfg_ana.jetLepDR if hasattr(
            self.cfg_ana, 'jetLepDR') else 0.5
        self.lepPtMin = self.cfg_ana.minLepPt if hasattr(
            self.cfg_ana, 'minLepPt') else -1

    def declareHandles(self):
        super(monoXFatJetAnalyzer, self).declareHandles()
        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol,
                                          'std::vector<pat::Jet>')
        self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double')

    def beginLoop(self, setup):
        super(monoXFatJetAnalyzer, self).beginLoop(setup)

    def process(self, event):
        self.readCollections(event.input)
        rho = float(self.handles['rho'].product()[0])
        self.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        allJets = map(Jet, self.handles['jets'].product())

        self.deltaMetFromJEC = [0., 0.]
        self.type1METCorr = [0., 0., 0.]
        if self.doJEC:
            if not self.recalibrateJets:  # check point that things won't change
                jetsBefore = [(j.pt(), j.eta(), j.phi(), j.rawFactor())
                              for j in allJets]
            self.jetReCalibrator.correctAll(allJets,
                                            rho,
                                            delta=self.shiftJEC,
                                            addCorr=True,
                                            addShifts=self.addJECShifts,
                                            metShift=self.deltaMetFromJEC,
                                            type1METCorr=self.type1METCorr)
            if not self.recalibrateJets:
                jetsAfter = [(j.pt(), j.eta(), j.phi(), j.rawFactor())
                             for j in allJets]
                if len(jetsBefore) != len(jetsAfter):
                    print "ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % (
                        jetsBefore, jetsAfter)
                else:
                    for (told, tnew) in zip(jetsBefore, jetsAfter):
                        if (deltaR2(told[1], told[2], tnew[1],
                                    tnew[2])) > 0.0001:
                            print "ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % (
                                told, tnew)
                        elif abs(told[0] - tnew[0]) / (
                                told[0] + tnew[0]) > 0.5e-3 or abs(
                                    told[3] - tnew[3]) > 0.5e-3:
                            print "ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % (
                                told, tnew)

        ## Apply jet selection
        event.fatJets = []
        event.fatJetsNoID = []
        for jet in allJets:
            if self.testJetNoID(jet):
                event.fatJetsNoID.append(jet)
                if self.testJetID(jet):
                    event.fatJets.append(jet)

        ## Associate jets to leptons
        leptons = event.inclusiveLeptons if hasattr(
            event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet]

        for lep in leptons:
            jet = jlpairs[lep]
            if jet is None:
                lep.fatjet = lep.jet
            else:
                lep.fatjet = jet

    def testJetID(self, jet):
        #jet.puJetIdPassed = jet.puJetId()
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose')
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed
            #return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId))

    def testJetNoID(self, jet):
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta
예제 #14
0
class JetAnalyzer(Analyzer):
    """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2"
        dataGT = cfg_ana.dataGT if hasattr(cfg_ana,
                                           'dataGT') else "GR_70_V2_AN1"
        self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(
            self.cfg_ana, 'shiftJEC') else 0
        self.recalibrateJets = self.cfg_ana.recalibrateJets
        if self.recalibrateJets == "MC":
            self.recalibrateJets = self.cfg_comp.isMC
        elif self.recalibrateJets == "Data":
            self.recalibrateJets = not self.cfg_comp.isMC
        elif self.recalibrateJets not in [True, False]:
            raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets
        self.doJEC = self.recalibrateJets or (self.shiftJEC != 0)
        if self.doJEC:
            if self.cfg_comp.isMC:
                self.jetReCalibrator = JetReCalibrator(mcGT, "AK4PFchs", False,
                                                       cfg_ana.jecPath)
            else:
                self.jetReCalibrator = JetReCalibrator(dataGT, "AK4PFchs",
                                                       True, cfg_ana.jecPath)
        self.doPuId = self.cfg_ana.doPuId if hasattr(self.cfg_ana,
                                                     'doPuId') else True
        self.jetLepDR = self.cfg_ana.jetLepDR if hasattr(
            self.cfg_ana, 'jetLepDR') else 0.5
        self.lepPtMin = self.cfg_ana.minLepPt if hasattr(
            self.cfg_ana, 'minLepPt') else -1
        self.jetGammaDR = self.cfg_ana.jetGammaDR if hasattr(
            self.cfg_ana, 'jetGammaDR') else 0.4
        if (self.cfg_ana.doQG):
            self.qglcalc = QGLikelihoodCalculator(
                "/afs/cern.ch/user/t/tomc/public/QG_pdfs_13TeV_2014-10-12/pdfQG_AK4chs_antib_NoQC_13TeV.root"
            )

    def declareHandles(self):
        super(JetAnalyzer, self).declareHandles()
        self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol,
                                          'std::vector<pat::Jet>')
        self.handles['genJet'] = AutoHandle('slimmedGenJets',
                                            'vector<reco::GenJet>')
        self.shiftJER = self.cfg_ana.shiftJER if hasattr(
            self.cfg_ana, 'shiftJER') else 0
        self.handles['rho'] = AutoHandle(('fixedGridRhoFastjetAll', '', ''),
                                         'double')

    def beginLoop(self, setup):
        super(JetAnalyzer, self).beginLoop(setup)

    def process(self, event):
        self.readCollections(event.input)
        rho = float(self.handles['rho'].product()[0])
        event.rho = rho

        ## Read jets, if necessary recalibrate and shift MET
        allJets = map(Jet, self.handles['jets'].product())

        event.deltaMetFromJEC = [0., 0.]
        if self.doJEC:
            #print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId)
            self.jetReCalibrator.correctAll(allJets,
                                            rho,
                                            delta=self.shiftJEC,
                                            metShift=event.deltaMetFromJEC)
        event.allJetsUsedForMET = allJets

        if self.cfg_comp.isMC:
            event.genJets = [x for x in self.handles['genJet'].product()]
            self.matchJets(event, allJets)
            if getattr(self.cfg_ana, 'smearJets', False):
                self.smearJets(event, allJets)

        ## Apply jet selection
        event.jets = []
        event.jetsFailId = []
        event.jetsAllNoID = []
        event.jetsIdOnly = []
        for jet in allJets:
            if self.testJetNoID(jet):
                event.jetsAllNoID.append(jet)
                if self.testJetID(jet):

                    if (self.cfg_ana.doQG):
                        self.computeQGvars(jet)
                        jet.qgl = self.qglcalc.computeQGLikelihood(jet, rho)

                    event.jets.append(jet)
                    event.jetsIdOnly.append(jet)
                else:
                    event.jetsFailId.append(jet)
            elif self.testJetID(jet):
                event.jetsIdOnly.append(jet)

        ## Clean Jets from leptons
        leptons = []
        if hasattr(event, 'selectedLeptons'):
            leptons = [
                l for l in event.selectedLeptons if l.pt() > self.lepPtMin
            ]
        if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'):
            leptons = leptons[:] + event.selectedTaus
        if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(
                event, 'selectedIsoCleanTrack'):
            leptons = leptons[:] + event.selectedIsoCleanTrack
        event.cleanJetsAll = cleanNearestJetOnly(event.jets, leptons,
                                                 self.jetLepDR)
        event.cleanJets = [
            j for j in event.cleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        event.cleanJetsFwd = [
            j for j in event.cleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]

        ## Clean Jets from photons
        photons = []
        if hasattr(event, 'selectedPhotons'):
            photons = [g for g in event.selectedPhotons]
        event.gamma_cleanJetsAll = cleanNearestJetOnly(event.cleanJetsAll,
                                                       photons,
                                                       self.jetGammaDR)
        event.gamma_cleanJets = [
            j for j in event.gamma_cleanJetsAll
            if abs(j.eta()) < self.cfg_ana.jetEtaCentral
        ]
        event.gamma_cleanJetsFwd = [
            j for j in event.gamma_cleanJetsAll
            if abs(j.eta()) >= self.cfg_ana.jetEtaCentral
        ]
        ###

        ## Associate jets to leptons
        leptons = event.inclusiveLeptons if hasattr(
            event, 'inclusiveLeptons') else event.selectedLeptons
        jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2)

        for jet in allJets:
            jet.leptons = [l for l in jlpairs if jlpairs[l] == jet]

        for lep in leptons:
            jet = jlpairs[lep]
            if jet is None:
                lep.jet = lep
            else:
                lep.jet = jet

        if self.cfg_comp.isMC:
            event.deltaMetFromJetSmearing = [0, 0]
            for j in event.cleanJetsAll:
                if hasattr(j, 'deltaMetFromJetSmearing'):
                    event.deltaMetFromJetSmearing[
                        0] += j.deltaMetFromJetSmearing[0]
                    event.deltaMetFromJetSmearing[
                        1] += j.deltaMetFromJetSmearing[1]
            event.cleanGenJets = cleanNearestJetOnly(event.genJets,
                                                     event.selectedLeptons,
                                                     0.5)

            #event.nGenJets25 = 0
            #event.nGenJets25Cen = 0
            #event.nGenJets25Fwd = 0
            #for j in event.cleanGenJets:
            #    event.nGenJets25 += 1
            #    if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1
            #    else:                   event.nGenJets25Fwd += 1

            self.jetFlavour(event)

        return True

    def testJetID(self, jet):
        jet.puJetIdPassed = jet.puJetId()
        jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose')
        if self.cfg_ana.relaxJetId:
            return True
        else:
            return jet.pfJetIdPassed and (jet.puJetIdPassed
                                          or not (self.doPuId))

    def testJetNoID(self, jet):
        # 2 is loose pile-up jet id
        return jet.pt() > self.cfg_ana.jetPt and \
               abs( jet.eta() ) < self.cfg_ana.jetEta

    def computeQGvars(self, jet):

        jet.mult = 0
        sum_weight = 0.
        sum_pt = 0.
        sum_deta = 0.
        sum_dphi = 0.
        sum_deta2 = 0.
        sum_detadphi = 0.
        sum_dphi2 = 0.

        for ii in range(0, jet.numberOfDaughters()):

            part = jet.daughter(ii)

            usePart = True

            if part.charge() == 0:  # neutral particles

                if part.pt() > 1.: jet.mult += 1

            else:  # charged particles

                jet.mult += 1

                if part.trackHighPurity() == False: usePart = False
                if part.fromPV() <= 1: usePart = False

            if usePart:
                deta = part.eta() - jet.eta()
                dphi = deltaPhi(part.phi(), jet.phi())
                partPt = part.pt()
                weight = partPt * partPt
                sum_weight += weight
                sum_pt += partPt
                sum_deta += deta * weight
                sum_dphi += dphi * weight
                sum_deta2 += deta * deta * weight
                sum_detadphi += deta * dphi * weight
                sum_dphi2 += dphi * dphi * weight

        a = 0.
        b = 0.
        c = 0.

        if sum_weight > 0:
            jet.ptd = math.sqrt(sum_weight) / sum_pt
            ave_deta = sum_deta / sum_weight
            ave_dphi = sum_dphi / sum_weight
            ave_deta2 = sum_deta2 / sum_weight
            ave_dphi2 = sum_dphi2 / sum_weight
            a = ave_deta2 - ave_deta * ave_deta
            b = ave_dphi2 - ave_dphi * ave_dphi
            c = -(sum_detadphi / sum_weight - ave_deta * ave_dphi)
        else:
            jet.ptd = 0.

        delta = math.sqrt(math.fabs((a - b) * (a - b) + 4. * c * c))

        if a + b - delta > 0:
            jet.axis2 = -math.log(math.sqrt(0.5 * (a + b - delta)))
        else:
            jet.axis2 = -1.

    def jetFlavour(self, event):
        def isFlavour(x, f):
            id = abs(x.pdgId())
            if id > 999: return (id / 1000) % 10 == f
            if id > 99: return (id / 100) % 10 == f
            return id % 100 == f

        event.bqObjects = [
            p for p in event.genParticles
            if (p.status() == 2 and isFlavour(p, 5))
        ]
        event.cqObjects = [
            p for p in event.genParticles
            if (p.status() == 2 and isFlavour(p, 4))
        ]

        event.partons = [
            p for p in event.genParticles
            if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId()) > 0
                and (abs(p.pdgId()) in [1, 2, 3, 4, 5, 21]))
        ]
        match = matchObjectCollection2(event.cleanJetsAll,
                                       event.partons,
                                       deltaRMax=0.3)

        for jet in event.cleanJetsAll:
            parton = match[jet]
            jet.partonId = (parton.pdgId() if parton != None else 0)
            jet.partonMotherId = (parton.mother(0).pdgId() if parton != None
                                  and parton.numberOfMothers() > 0 else 0)

        for jet in event.jets:
            (bmatch, dr) = bestMatch(jet, event.bqObjects)
            if dr < 0.4:
                jet.mcFlavour = 5
            else:
                (cmatch, dr) = bestMatch(jet, event.cqObjects)
                if dr < 0.4:
                    jet.mcFlavour = 4
                else:
                    jet.mcFlavour = 0

        event.heaviestQCDFlavour = 5 if len(
            event.bqObjects) else (4 if len(event.cqObjects) else 1)

    def matchJets(self, event, jets):
        match = matchObjectCollection2(jets,
                                       event.genbquarks + event.genwzquarks,
                                       deltaRMax=0.3)
        for jet in jets:
            gen = match[jet]
            jet.mcParton = gen
            jet.mcMatchId = (gen.sourceId if gen != None else 0)
            jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0)

        match = matchObjectCollection2(jets, event.genJets, deltaRMax=0.3)
        for jet in jets:
            jet.mcJet = match[jet]

    def smearJets(self, event, jets):
        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution
        for jet in jets:
            gen = jet.mcJet
            if gen != None:
                genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta())
                # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution
                factor = 1.052 + self.shiftJER * math.hypot(0.012, 0.062)
                if aeta > 2.3:
                    factor = 1.288 + self.shiftJER * math.hypot(0.127, 0.154)
                elif aeta > 1.7:
                    factor = 1.134 + self.shiftJER * math.hypot(0.035, 0.066)
                elif aeta > 1.1:
                    factor = 1.096 + self.shiftJER * math.hypot(0.017, 0.063)
                elif aeta > 0.5:
                    factor = 1.057 + self.shiftJER * math.hypot(0.012, 0.056)
                ptscale = max(0.0,
                              (jetpt + (factor - 1) * (jetpt - genpt)) / jetpt)
                #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale)
                jet.deltaMetFromJetSmearing = [
                    -(ptscale - 1) * jet.rawFactor() * jet.px(),
                    -(ptscale - 1) * jet.rawFactor() * jet.py()
                ]
                if ptscale != 0:
                    jet.setP4(jet.p4() * ptscale)
                # leave the uncorrected unchanged for sync
                jet._rawFactorMultiplier *= (1.0 /
                                             ptscale) if ptscale != 0 else 1