def initPDFWeights(self):
     from ROOT import PdfWeightProducerTool
     self.pdfWeightInit = True
     self.pdfWeightTool = PdfWeightProducerTool()
     for pdf in self.cfg_ana.PDFWeights:
         self.pdfWeightTool.addPdfSet(pdf + ".LHgrid")
     self.pdfWeightTool.beginJob()
Exemple #2
0
 def initPDFWeights(self):
     from ROOT import PdfWeightProducerTool
     self.pdfWeightInit = True
     self.pdfWeightTool = PdfWeightProducerTool()
     for pdf in self.cfg_ana.PDFWeights:
         self.pdfWeightTool.addPdfSet(pdf+".LHgrid")
     self.pdfWeightTool.beginJob()
Exemple #3
0
class PDFWeightsAnalyzer(Analyzer):
    """    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(PDFWeightsAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        self.doPDFWeights = hasattr(
            self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        self.doPDFVars = hasattr(
            self.cfg_ana, "doPDFVars") and self.cfg_ana.doPDFVars == True
        if self.doPDFWeights:
            self.pdfWeightInit = False

    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS
    #---------------------------------------------

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

        if self.doPDFVars or self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle('generator',
                                                    'GenEventInfoProduct')

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

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf + ".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.genInfo)
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf + ".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]

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

        # if not MC, nothing to do
        if not self.cfg_comp.isMC:
            return True

        if self.doPDFVars or self.doPDFWeights:
            self.genInfo = self.mchandles['pdfstuff'].product()
        if self.doPDFWeights:
            self.makePDFWeights(event)
        if self.doPDFVars:
            event.pdf_x1 = self.genInfo.pdf().x.first
            event.pdf_x2 = self.genInfo.pdf().x.second
            event.pdf_id1 = self.genInfo.pdf().id.first
            event.pdf_id2 = self.genInfo.pdf().id.second
            event.pdf_scale = self.genInfo.pdf().scalePDF

        return True
Exemple #4
0
class PDFWeightsAnalyzer(Analyzer):
    """    """

    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(PDFWeightsAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        self.doPDFWeights = hasattr(self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        self.doPDFVars = hasattr(self.cfg_ana, "doPDFVars") and self.cfg_ana.doPDFVars == True
        if self.doPDFWeights:
            self.pdfWeightInit = False

    # ---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS
    # ---------------------------------------------

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

        if self.doPDFVars or self.doPDFWeights:
            self.mchandles["pdfstuff"] = AutoHandle("generator", "GenEventInfoProduct")

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

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool

        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf + ".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit:
            self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.genInfo)
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf + ".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]

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

        # if not MC, nothing to do
        if not self.cfg_comp.isMC:
            return True

        if self.doPDFVars or self.doPDFWeights:
            self.genInfo = self.mchandles["pdfstuff"].product()
        if self.doPDFWeights:
            self.makePDFWeights(event)
        if self.doPDFVars:
            event.pdf_x1 = self.genInfo.pdf().x.first
            event.pdf_x2 = self.genInfo.pdf().x.second
            event.pdf_id1 = self.genInfo.pdf().id.first
            event.pdf_id2 = self.genInfo.pdf().id.second
            event.pdf_scale = self.genInfo.pdf().scalePDF

        return True
class PDFWeightsAnalyzer( Analyzer ):
    """    """
    def __init__(self, cfg_ana, cfg_comp, looperName ):
        super(PDFWeightsAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName)
        self.doPDFWeights = hasattr(self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False
    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS 
    #---------------------------------------------
        

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

        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle( 'generator', 'GenEventInfoProduct' )

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

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf+".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf+".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]

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

        # if not MC, nothing to do
        if not self.cfg_comp.isMC: 
            return True

        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True
Exemple #6
0
class ttHGenLevelAnalyzer( Analyzer ):
    """Do generator-level analysis of a ttH->leptons decay:

       Creates in the event:
         event.genParticles   = the gen particles (pruned, as default)
         event.genHiggsDecayMode =   0  for non-Higgs
                                 15  for H -> tau tau
                                 23  for H -> Z Z
                                 24  for H -> W W
                                 xx  for H -> xx yy zzz 

          event.genleps    = [ status 3 gen electrons and muons not from tau decays ]
          event.gentauleps = [ gen electrons and muons from decays of status 3 taus ]
          event.genbquarks  = [ gen b quarks (status = 3) from to quark decays ]
          event.genwzquarks = [ gen quarks from hadronic W,Z decays ]

       If filterHiggsDecays is set to a list of Higgs decay modes,
       it will filter events that have those decay modes.
       e.g. [0, 15, 23, 24] will keep data, non-Higgs MC and Higgs decays to (tau, Z, W) 
       but will drop Higgs decays to other particles (e.g. bb).
      
    """
    def __init__(self, cfg_ana, cfg_comp, looperName ):
        super(ttHGenLevelAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName)
        self.doPDFWeights = hasattr(self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False
    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS 
    #---------------------------------------------
        

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

        #mc information
        self.mchandles['genParticles'] = AutoHandle( 'genParticlesPruned',
                                                     'std::vector<reco::GenParticle>' )
        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle( 'generator', 'GenEventInfoProduct' )

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

    def fillGenLeptons(self, event, particle, isTau=False, sourceId=25):
        """Get the gen level light leptons (prompt and/or from tau decays)"""

        for i in xrange( particle.numberOfDaughters() ):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            dau.isTau = isTau
            id = abs(dau.pdgId())
            if id in [11,13]:
                if isTau: event.gentauleps.append(dau)
                else:     event.genleps.append(dau)
            elif id == 15:
                self.fillGenLeptons(event, dau, True, sourceId)
            elif id in [22,23,24]:
                self.fillGenLeptons(event, dau, False, sourceId)

    def fillWZQuarks(self, event, particle, isWZ=False, sourceId=25):
        """Descend daughters of 'particle', and add quarks from W,Z to event.genwzquarks
           isWZ is set to True if already processing daughters of W,Z's, to False before it"""

        for i in xrange( particle.numberOfDaughters() ):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            id = abs(dau.pdgId())
            if id <= 5 and isWZ:
                event.genwzquarks.append(dau)
            elif id in [22,23,24]:
                self.fillWZQuarks(event, dau, True, sourceId)

    def fillTopQuarks(self, event):
        """Get the b quarks from top decays into event.genbquarks"""

        event.gentopquarks = [ p for p in event.genParticles if (p.status() == 3 and abs(p.pdgId()) == 6) ]
        #if len(event.gentopquarks) != 2:
        #    print "Not two top quarks? \n%s\n" % event.gentopquarks

        for tq in event.gentopquarks:
            for i in xrange( tq.numberOfDaughters() ):
                dau = GenParticle(tq.daughter(i))
                if abs(dau.pdgId()) == 5:
                    dau.sourceId = 6
                    event.genbquarks.append( dau )
                elif abs(dau.pdgId()) == 24:
                    self.fillGenLeptons( event, dau, sourceId=6 )
                    self.fillWZQuarks(   event, dau, True, sourceId=6 )

        
    def makeMCInfo(self, event):
        event.genParticles = map( GenParticle, self.mchandles['genParticles'].product() )

        event.genHiggsBoson = None
        event.genleps    = []
        event.gentauleps = []
        event.genbquarks  = []
        event.genwzquarks = []
        event.gentopquarks  = []

        higgsBosons = [ p for p in event.genParticles if (p.status() == 3 and p.pdgId() == 25) ]

        if len(higgsBosons) == 0:
            event.genHiggsDecayMode = 0

            ## Matching that can be done also on non-Higgs events
            ## First, top quarks
            self.fillTopQuarks( event )
            self.countBPartons( event )

            ## Then W,Z,gamma from hard scattering and that don't come from a top and don't rescatter
            def hasAncestor(particle, filter):
                for i in xrange(particle.numberOfMothers()):
                    mom = particle.mother(i)
                    if filter(mom) or hasAncestor(mom, filter): 
                        return True
                return False
            def hasDescendent(particle, filter):
                for i in xrange(particle.numberOfDaughters()):
                    dau = particle.daughter(i)
                    if filter(dau) or hasDescendent(dau, filter):
                        return True
                return False

            bosons = [ gp for gp in event.genParticles if gp.status() == 3 and abs(gp.pdgId()) in [22,23,24] ]
            for b in bosons:
                if hasAncestor(b,   lambda gp : abs(gp.pdgId()) == 6): continue
                if hasDescendent(b, lambda gp : abs(gp.pdgId()) in [22,23,24] and gp.status() == 3): continue
                self.fillGenLeptons(event, b, sourceId=abs(b.pdgId()))
                self.fillWZQuarks(event, b, isWZ=True, sourceId=abs(b.pdgId()))
        else:
            if len(higgsBosons) > 1: 
                print "More than one higgs? \n%s\n" % higgsBosons

            event.genHiggsBoson = GenParticle(higgsBosons[-1])
            event.genHiggsDecayMode = abs( event.genHiggsBoson.daughter(0).pdgId() )
            self.fillTopQuarks( event )
            self.countBPartons( event )
            self.fillWZQuarks(   event, event.genHiggsBoson )
            self.fillGenLeptons( event, event.genHiggsBoson, sourceId=25 )
            if self.cfg_ana.verbose:
                print "Higgs boson decay mode: ", event.genHiggsDecayMode
                print "Generator level prompt light leptons:\n", "\n".join(["\t%s" % p for p in event.genleps])
                print "Generator level light leptons from taus:\n", "\n".join(["\t%s" % p for p in event.gentauleps])
                print "Generator level b quarks from top:\n", "\n".join(["\t%s" % p for p in event.genbquarks])
                print "Generator level quarks from W, Z decays:\n", "\n".join(["\t%s" % p for p in event.genwzquarks])

    def countBPartons(self,event):
        event.allBPartons = [ q for q in event.genParticles if abs(q.pdgId()) == 5 and abs(q.status()) == 2 and abs(q.pt()) > 15 ]
        event.allBPartons.sort(key = lambda q : q.pt(), reverse = True)
        event.bPartons = []
        for q in event.allBPartons:
            duplicate = False
            for q2 in event.bPartons:
                if deltaR(q.eta(),q.phi(),q2.eta(),q2.phi()) < 0.5:
                    duplicate = True
                    continue
            if not duplicate: event.bPartons.append(q)

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf+".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf+".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]
            #print "Produced %d weights for %s: %s" % (len(ws),pdf,event.pdfWeights[pdf])

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

        ## creating a "sub-event" for this analyzer
        #myEvent = Event(event.iEv)
        #setattr(event, self.name, myEvent)
        #event = myEvent

        # if not MC, nothing to do
        if not self.cfg_comp.isMC: 
            return True

        # do MC level analysis
        self.makeMCInfo(event)

        # if MC and filtering on the Higgs decay mode, 
        # them do filter events
        if self.cfg_ana.filterHiggsDecays:
            if event.genHiggsDecayMode not in self.cfg_ana.filterHiggsDecays:
                return False

        # do PDF weights, if requested
        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True
class ttHGenLevelAnalyzer(Analyzer):
    """Do generator-level analysis of a ttH->leptons decay:

       Creates in the event:
         event.genParticles   = the gen particles (pruned, as default)
         event.genHiggsDecayMode =   0  for non-Higgs
                                 15  for H -> tau tau
                                 23  for H -> Z Z
                                 24  for H -> W W
                                 xx  for H -> xx yy zzz 

          event.gentauleps = [ gen electrons and muons from hard scattering not from tau decays ]
          event.gentaus    = [ gen taus from from hard scattering ]
          event.genleps    = [ gen electrons and muons from hard scattering not from tau decays ]
          event.genbquarks  = [ gen b quarks from top quark decays ]
          event.genwzquarks = [ gen quarks from hadronic W,Z decays ]
          event.gennus    = [ gen nus from from Z,W ]

       If filterHiggsDecays is set to a list of Higgs decay modes,
       it will filter events that have those decay modes.
       e.g. [0, 15, 23, 24] will keep data, non-Higgs MC and Higgs decays to (tau, Z, W) 
       but will drop Higgs decays to other particles (e.g. bb).
      
    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(ttHGenLevelAnalyzer, self).__init__(cfg_ana, cfg_comp,
                                                  looperName)
        self.doPDFWeights = hasattr(
            self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False

    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS
    #---------------------------------------------

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

        #mc information
        self.mchandles['genParticles'] = AutoHandle(
            'prunedGenParticles', 'std::vector<reco::GenParticle>')
        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle('generator',
                                                    'GenEventInfoProduct')

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

    def fillGenLeptons(self, event, particle, isTau=False, sourceId=25):
        """Get the gen level light leptons (prompt and/or from tau decays)"""

        for i in xrange(particle.numberOfDaughters()):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            dau.isTau = isTau
            id = abs(dau.pdgId())
            moid = 0
            if dau.numberOfMothers() > 0:
                moid = abs(dau.mother().pdgId())
            if id in [11, 13]:
                if isTau: event.gentauleps.append(dau)
                else: event.genleps.append(dau)
            elif id == 15:
                if moid in [22, 23, 24]:
                    event.gentaus.append(dau)
                self.fillGenLeptons(event, dau, True, sourceId)
            elif id in [22, 23, 24]:
                self.fillGenLeptons(event, dau, False, sourceId)
            elif id in [12, 14, 16]:
                event.gennus.append(dau)

    def fillWZQuarks(self, event, particle, isWZ=False, sourceId=25):
        """Descend daughters of 'particle', and add quarks from W,Z to event.genwzquarks
           isWZ is set to True if already processing daughters of W,Z's, to False before it"""

        for i in xrange(particle.numberOfDaughters()):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            id = abs(dau.pdgId())
            if id <= 5 and isWZ:
                event.genwzquarks.append(dau)
            elif id in [22, 23, 24]:
                self.fillWZQuarks(event, dau, True, sourceId)

    def fillTopQuarks(self, event):
        """Get the b quarks from top decays into event.genbquarks"""

        event.gentopquarks = [
            p for p in event.genParticles if abs(p.pdgId()) == 6
            and p.numberOfDaughters() > 0 and abs(p.daughter(0).pdgId()) != 6
        ]
        #if len(event.gentopquarks) != 2:
        #    print "Not two top quarks? \n%s\n" % event.gentopquarks

        for tq in event.gentopquarks:
            for i in xrange(tq.numberOfDaughters()):
                dau = GenParticle(tq.daughter(i))
                if abs(dau.pdgId()) == 5:
                    dau.sourceId = 6
                    event.genbquarks.append(dau)
                elif abs(dau.pdgId()) == 24:
                    self.fillGenLeptons(event, dau, sourceId=6)
                    self.fillWZQuarks(event, dau, True, sourceId=6)

    def makeMCInfo(self, event):
        event.genParticles = map(GenParticle,
                                 self.mchandles['genParticles'].product())

        if False:
            for i, p in enumerate(event.genParticles):
                print " %5d: pdgId %+5d status %3d  pt %6.1f  " % (
                    i, p.pdgId(), p.status(), p.pt()),
                if p.numberOfMothers() > 0:
                    imom, mom = p.motherRef().key(), p.mother()
                    print " | mother %5d pdgId %+5d status %3d  pt %6.1f  " % (
                        imom, mom.pdgId(), mom.status(), mom.pt()),
                else:
                    print " | no mother particle                              ",

                for j in xrange(min(3, p.numberOfDaughters())):
                    idau, dau = p.daughterRef(j).key(), p.daughter(j)
                    print " | dau[%d] %5d pdgId %+5d status %3d  pt %6.1f  " % (
                        j, idau, dau.pdgId(), dau.status(), dau.pt()),
                print ""

        event.genHiggsBoson = None
        event.genVBosons = []
        event.gennus = []
        event.genleps = []
        event.gentauleps = []
        event.gentaus = []
        event.genbquarks = []
        event.genwzquarks = []
        event.gentopquarks = []

        higgsBosons = [
            p for p in event.genParticles if (p.pdgId() == 25)
            and p.numberOfDaughters() > 0 and abs(p.daughter(0).pdgId()) != 25
        ]

        if len(higgsBosons) == 0:
            event.genHiggsDecayMode = 0

            ## Matching that can be done also on non-Higgs events
            ## First, top quarks
            self.fillTopQuarks(event)
            self.countBPartons(event)

            ## Then W,Z,gamma from hard scattering and that don't come from a top and don't rescatter
            def hasAncestor(particle, filter):
                for i in xrange(particle.numberOfMothers()):
                    mom = particle.mother(i)
                    if filter(mom) or hasAncestor(mom, filter):
                        return True
                return False

            def hasDescendent(particle, filter):
                for i in xrange(particle.numberOfDaughters()):
                    dau = particle.daughter(i)
                    if filter(dau) or hasDescendent(dau, filter):
                        return True
                return False

            bosons = [
                gp for gp in event.genParticles
                if gp.status() > 2 and abs(gp.pdgId()) in [22, 23, 24]
            ]

            if self.cfg_ana.verbose:
                print "\n =============="
                for i, p in enumerate(bosons):
                    print " %5d: pdgId %+5d status %3d  pt %6.1f  " % (
                        i, p.pdgId(), p.status(), p.pt()),
                    if p.numberOfMothers() > 0:
                        imom, mom = p.motherRef().key(), p.mother()
                        print " | mother %5d pdgId %+5d status %3d  pt %6.1f  " % (
                            imom, mom.pdgId(), mom.status(), mom.pt()),
                    else:
                        print " | no mother particle                              ",

                    for j in xrange(min(3, p.numberOfDaughters())):
                        idau, dau = p.daughterRef(j).key(), p.daughter(j)
                        print " | dau[%d] %5d pdgId %+5d status %3d  pt %6.1f  " % (
                            j, idau, dau.pdgId(), dau.status(), dau.pt()),
                        print ""

            for b in bosons:
                b.sourceId = -1
                if hasAncestor(b, lambda gp: abs(gp.pdgId()) == 6): continue
                if hasDescendent(
                        b, lambda gp: abs(gp.pdgId()) in [22, 23, 24] and gp.
                        status() > 2):
                    continue
                self.fillGenLeptons(event, b, sourceId=abs(b.pdgId()))
                self.fillWZQuarks(event, b, isWZ=True, sourceId=abs(b.pdgId()))
                #print " ===>  %5d: pdgId %+5d status %3d  pt %6.1f  " % (i, b.pdgId(),b.status(),b.pt()),
                #event.genVBosons.append(b)

        else:
            if len(higgsBosons) > 1:
                print "More than one higgs? \n%s\n" % higgsBosons

            event.genHiggsBoson = GenParticle(higgsBosons[-1])
            event.genHiggsDecayMode = abs(
                event.genHiggsBoson.daughter(0).pdgId())
            self.fillTopQuarks(event)
            self.countBPartons(event)
            self.fillWZQuarks(event, event.genHiggsBoson)
            self.fillGenLeptons(event, event.genHiggsBoson, sourceId=25)
            if self.cfg_ana.verbose:
                print "Higgs boson decay mode: ", event.genHiggsDecayMode
                print "Generator level prompt nus:\n", "\n".join(
                    ["\t%s" % p for p in event.gennus])
                print "Generator level prompt light leptons:\n", "\n".join(
                    ["\t%s" % p for p in event.genleps])
                print "Generator level light leptons from taus:\n", "\n".join(
                    ["\t%s" % p for p in event.gentauleps])
                print "Generator level prompt tau leptons:\n", "\n".join(
                    ["\t%s" % p for p in event.gentaus])
                print "Generator level b quarks from top:\n", "\n".join(
                    ["\t%s" % p for p in event.genbquarks])
                print "Generator level quarks from W, Z decays:\n", "\n".join(
                    ["\t%s" % p for p in event.genwzquarks])
        # make sure prompt leptons have a non-zero sourceId
        for p in event.genParticles:
            if isPromptLepton(p,
                              True,
                              includeTauDecays=True,
                              includeMotherless=False):
                if getattr(p, 'sourceId', 0) == 0:
                    p.sourceId = 99

    def countBPartons(self, event):
        event.allBPartons = [
            q for q in event.genParticles if abs(q.pdgId()) == 5
            and abs(q.status()) == 2 and abs(q.pt()) > 15
        ]
        event.allBPartons.sort(key=lambda q: q.pt(), reverse=True)
        event.bPartons = []
        for q in event.allBPartons:
            duplicate = False
            for q2 in event.bPartons:
                if deltaR(q.eta(), q.phi(), q2.eta(), q2.phi()) < 0.5:
                    duplicate = True
                    continue
            if not duplicate: event.bPartons.append(q)

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf + ".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf + ".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]
            #print "Produced %d weights for %s: %s" % (len(ws),pdf,event.pdfWeights[pdf])

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

        ## creating a "sub-event" for this analyzer
        #myEvent = Event(event.iEv)
        #setattr(event, self.name, myEvent)
        #event = myEvent

        # if not MC, nothing to do
        if not self.cfg_comp.isMC:
            return True

        # do MC level analysis
        self.makeMCInfo(event)

        # if MC and filtering on the Higgs decay mode,
        # them do filter events
        if self.cfg_ana.filterHiggsDecays:
            if event.genHiggsDecayMode not in self.cfg_ana.filterHiggsDecays:
                return False

        # do PDF weights, if requested
        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True
class ttHGenLevelOnlyStudy(Analyzer):
    """
    Fakes a reco event starting from GEN-only files      
    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(ttHGenLevelOnlyStudy, self).__init__(cfg_ana, cfg_comp,
                                                   looperName)
        self.doPDFWeights = hasattr(
            self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False

    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS
    #---------------------------------------------

    def declareHandles(self):
        super(ttHGenLevelOnlyStudy, self).declareHandles()
        self.mchandles['genParticles'] = AutoHandle(
            'genParticles', 'std::vector<reco::GenParticle>')
        self.mchandles['jets'] = AutoHandle('ak5GenJets',
                                            'std::vector<reco::GenJet>')
        self.mchandles['met'] = AutoHandle('genMetTrue',
                                           'std::vector<reco::GenMET>')
        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle('generator',
                                                    'GenEventInfoProduct')

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

    def doLeptons(self, iEvent, event):
        def isPrompt(l):
            for x in xrange(l.numberOfMothers()):
                mom = l.mother(x)
                if mom.status() > 2: return True
                id = abs(mom.pdgId())
                if id > 100: return False
                if id < 6: return False
                if id == 21: return False
                if id in [11, 13, 15]: return isPrompt(mom)
                if id in [22, 23, 24, 25, 32]: return True
            return True

        event.selectedLeptons = []
        for l in event.genParticles:
            if abs(l.pdgId()) not in [11, 13] or l.status() != 1: continue
            if abs(l.pdgId()) == 13:
                if l.pt() <= 5 or abs(l.eta()) > 2.4: continue
            if abs(l.pdgId()) == 11:
                if l.pt() <= 7 or abs(l.eta()) > 2.5: continue
            if not isPrompt(l):
                continue
            event.selectedLeptons.append(LeptonFromGen(l))

    def doJets(self, iEvent, event):
        event.cleanJetsAll = []
        event.cleanJetsFwd = []
        event.cleanJets = []
        for j in self.mchandles['jets'].product():
            if j.pt() < 25: continue
            for l in event.selectedLeptons:
                if l.pt() > 10 and deltaR(l.eta(), l.phi(), j.eta(),
                                          j.phi()) < 0.5:
                    continue
            jo = JetFromGen(j)
            event.cleanJetsAll.append(jo)
            if abs(j.eta()) < 2.4:
                event.cleanJetsAll.append(jo)
            else:
                event.cleanJetsFwd.append(jo)

    def doBTag(self, iEvent, event):
        bs = []
        for gp in event.genParticles:
            if gp.status() != 2: continue
            id = abs(gp.pdgId())
            if id == 5 or ((id % 1000) / 100) == 5 or ((id % 10000) /
                                                       1000) == 5:
                bs.append(gp)
        for j in event.cleanJetsAll:
            for gp in bs:
                if deltaR(gp.eta(), gp.phi(), j.eta(), j.phi()) < 0.4:
                    gp.btag = True

    def doMET(self, iEvent, event):
        event.met = self.mchandles['met'].product().front()

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

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

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

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

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

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

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf + ".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf + ".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]
            #print "Produced %d weights for %s: %s" % (len(ws),pdf,event.pdfWeights[pdf])

    def doHT(self, iEvent, event):
        import ROOT

        objects25 = [j for j in event.cleanJets if j.pt() > 25
                     ] + event.selectedLeptons
        objects30 = [j for j in event.cleanJets if j.pt() > 30
                     ] + event.selectedLeptons
        objects40 = [j for j in event.cleanJets if j.pt() > 40
                     ] + event.selectedLeptons
        objects40j = [j for j in event.cleanJets if j.pt() > 40]

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

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

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

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

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

        # if not MC, nothing to do
        if not self.cfg_comp.isMC:
            return True

        event.genParticles = [
            gp for gp in self.mchandles['genParticles'].product()
        ]

        event.eventWeigth = 1.0
        event.run = iEvent.eventAuxiliary().id().run()
        event.lumi = iEvent.eventAuxiliary().id().luminosityBlock()
        event.eventId = iEvent.eventAuxiliary().id().event()

        self.doLeptons(iEvent, event)
        self.makeZs(event, 4)
        self.makeMlls(event, 4)
        self.doJets(iEvent, event)
        self.doBTag(iEvent, event)
        self.doMET(iEvent, event)
        self.doHT(iEvent, event)

        # do PDF weights, if requested
        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True
class GeneratorAnalyzer(Analyzer):
    """Do generator-level analysis of a ttH->leptons decay:

       Creates in the event:
         event.genParticles   = the gen particles (pruned, as default)
         event.genHiggsDecayMode =   0  for non-Higgs
                                 15  for H -> tau tau
                                 23  for H -> Z Z
                                 24  for H -> W W
                                 xx  for H -> xx yy zzz 

          event.gentauleps = [ gen electrons and muons from hard scattering not from tau decays ]
          event.gentaus    = [ gen taus from from hard scattering ]
          event.genleps    = [ gen electrons and muons from hard scattering not from tau decays ]
          event.genbquarksFromTop  = [ gen b quarks from top quark decays ]
          event.genwzquarks = [ gen quarks from hadronic W,Z decays ]

       If filterHiggsDecays is set to a list of Higgs decay modes,
       it will filter events that have those decay modes.
       e.g. [0, 15, 23, 24] will keep data, non-Higgs MC and Higgs decays to (tau, Z, W) 
       but will drop Higgs decays to other particles (e.g. bb).
      
    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(GeneratorAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
        self.doPDFWeights = hasattr(
            self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False

    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS
    #---------------------------------------------

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

        #mc information
        self.mchandles['genParticles'] = AutoHandle(
            'prunedGenParticles', 'std::vector<reco::GenParticle>')
        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle('generator',
                                                    'GenEventInfoProduct')

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

    def fillGenLeptons(self,
                       event,
                       particle,
                       isTau=False,
                       recovered=False,
                       sourceId=25):
        """Get the gen level light leptons (prompt and/or from tau decays)"""

        for i in xrange(particle.numberOfDaughters()):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            dau.isTau = isTau
            id = abs(dau.pdgId())
            moid = abs(dau.mother().pdgId()) if dau.mother(
            ) else 2212  #if no mom, let say it is a proton (consistent with CMSSW < 74X)
            if id in [11, 13]:
                if not recovered:
                    if isTau: event.gentauleps.append(dau)
                    else: event.genleps.append(dau)
                else:
                    if isTau: event.gentaulepsRecovered.append(dau)
                    else: event.genlepsRecovered.append(dau)
            elif id == 15:
                if not recovered:
                    if moid in [22, 23, 24]:
                        event.gentaus.append(dau)
                    self.fillGenLeptons(event, dau, True, sourceId)
                else:
                    if moid in [22, 23, 24]:
                        event.gentausRecovered.append(dau)
                    self.fillGenLeptons(event, dau, True, True, sourceId)
            elif id in [22, 23, 24]:
                if not recovered:
                    self.fillGenLeptons(event, dau, False, sourceId)
                else:
                    self.fillGenLeptons(event, dau, False, True, sourceId)

    def fillWZQuarks(self, event, particle, isWZ=False, sourceId=25):
        """Descend daughters of 'particle', and add quarks from W,Z to event.genwzquarks
           isWZ is set to True if already processing daughters of W,Z's, to False before it"""

        for i in xrange(particle.numberOfDaughters()):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            id = abs(dau.pdgId())
            if id <= 5 and isWZ:
                event.genwzquarks.append(dau)
            elif id in [22, 23, 24]:
                self.fillWZQuarks(event, dau, True, sourceId)

    def fillHiggsBQuarks(self, event, h):
        """Get the b quarks from top decays into event.genbquarksFromH"""
        for i in xrange(h.numberOfDaughters()):
            dau = GenParticle(h.daughter(i))
            if abs(dau.pdgId()) in [3, 4, 5]:
                event.genbquarksFromH.append(dau)
                if dau.numberOfDaughters() == 1:
                    event.genbquarksFromHafterISR.append(
                        GenParticle(dau.daughter(0)))

    def fillTopQuarks(self, event):
        """Get the b quarks from top decays into event.genbquarksFromTop"""

        event.gentopquarks = [
            p for p in event.genParticles if abs(p.pdgId()) == 6
            and p.numberOfDaughters() > 0 and abs(p.daughter(0).pdgId()) != 6
        ]

        #Find the top decay mode (0 - leptonic, 1 - hadronic)
        for top in event.gentopquarks:
            ndaus = top.numberOfDaughters()
            top.decayMode = -1

            #go over top daughters
            for idau in range(ndaus):
                dau = top.daughter(idau)
                #found the W
                if abs(dau.pdgId()) == 24:
                    #find the true daughters of the W (in case of decay chain)
                    W_daus = realGenDaughters(dau)
                    decayMode = -1
                    #go over the daughters of the W
                    for idauw in range(len(W_daus)):
                        w_dau_id = abs(W_daus[idauw].pdgId())
                        #leptonic
                        if w_dau_id in [11, 12, 13, 14, 15, 16]:
                            decayMode = 0
                            break
                        #hadronic
                        elif w_dau_id < 6:
                            decayMode = 1
                            break
                    top.decayMode = decayMode
                    break
        for tq in event.gentopquarks:
            for i in xrange(tq.numberOfDaughters()):
                dau = GenParticle(tq.daughter(i))
                if abs(dau.pdgId()) == 5:
                    dau.sourceId = 6
                    event.genbquarksFromTop.append(dau)
                elif abs(dau.pdgId()) == 24:
                    self.fillGenLeptons(event, dau, sourceId=6)
                    self.fillWZQuarks(event, dau, True, sourceId=6)

    def makeMCInfo(self, event):

        LHE_weights_scale = []
        LHE_weights_pdf = []

        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/LHEReaderCMSSW)
        for w in event.LHE_weights:
            wid = int(w.id)
            #print wid, ": ", w.wgt
            # for LO samples, the scale weights are 1,...,9; for NLO 1001,1009
            if (wid in range(1, 10)) or (wid in range(1001, 1010)):
                wid = wid % 1000
                if wid not in [
                        1, 6, 8
                ]:  # these are the nominal and anticorrelated muR,muF variations
                    w.wgt = w.wgt / event.LHE_originalWeight if abs(
                        event.LHE_originalWeight) > 0 else w.wgt
                    w.order = LHE_scale_order[wid]
                    #print int(w.id), ": ", w.wgt, " (pos ", w.order, ")"
                    LHE_weights_scale.append(w)
            # thse are up/down variations for the NNPDF: https://twiki.cern.ch/twiki/bin/view/CMS/TTbarHbbRun2ReferenceAnalysisLimits
            if wid in LHE_pdf_ids:
                #print  w.wgt
                w.wgt = w.wgt / event.LHE_originalWeight if abs(
                    event.LHE_originalWeight) > 0 else w.wgt
                LHE_weights_pdf.append(w)

        event.LHE_weights_scale = sorted(LHE_weights_scale,
                                         key=lambda w: w.order)
        event.LHE_weights_pdf = LHE_weights_pdf

        #       event.genParticles = map( GenParticle, self.mchandles['genParticles'].product() )
        event.genParticles = list(self.mchandles['genParticles'].product())

        if False:

            for i, p in enumerate(event.genParticles):
                print " %5d: pdgId %+5d status %3d  pt %6.1f  " % (
                    i, p.pdgId(), p.status(), p.pt()),
                if p.numberOfMothers() > 0:
                    imom, mom = p.motherRef().key(), p.mother()
                    print " | mother %5d pdgId %+5d status %3d  pt %6.1f  " % (
                        imom, mom.pdgId(), mom.status(), mom.pt()),
                else:
                    print " | no mother particle                              ",

                for j in xrange(min(3, p.numberOfDaughters())):
                    idau, dau = p.daughterRef(j).key(), p.daughter(j)
                    print " | dau[%d] %5d pdgId %+5d status %3d  pt %6.1f  " % (
                        j, idau, dau.pdgId(), dau.status(), dau.pt()),
                print ""

        event.genHiggsBosons = []
        event.genHiggsSisters = []
        event.genleps = []
        event.gentauleps = []
        event.gentaus = []
        event.genlepsRecovered = []
        event.gentaulepsRecovered = []
        event.gentausRecovered = []
        event.genbquarksFromTop = []
        event.genbquarksFromH = []
        event.genbquarksFromHafterISR = []
        event.genallbquarks = []
        event.genwzquarks = []
        event.gentopquarks = []
        event.genallstatus2bhadrons = [
            p for p in event.genParticles
            if p.status() == 2 and self.hasBottom(p.pdgId())
        ]
        event.genallcquarks = [
            p for p in event.genParticles if abs(p.pdgId()) == 4 and (
                p.numberOfDaughters() == 0 or abs(p.daughter(0).pdgId()) != 4)
        ]

        # aggiunti da me

        #event.genHiggsToBB = [ p for p in event.genParticles if abs(p.pdgId())==25 and p.numberOfDaughters()==2 and abs(p.daughter(0).pdgId()) == 5 ]

        #event.genvbosonsToLL = [ p for p in event.genParticles if abs(p.pdgId()) in [23,24] and abs(p.mother().pdgId()) in [23,24] and p.numberOfDaughters()==2 and abs(p.daughter(0).pdgId()) in [11,13,15] ]

        #event.genZbosonsToLL = [ p for p in event.genParticles if abs(p.pdgId()) in [23] and abs(p.daughter(0).pdgId())!= abs(p.pdgId()) ]
        #event.genWbosonsToLL = [ p for p in event.genParticles if abs(p.pdgId()) in [24] and abs(p.daughter(0).pdgId())!= abs(p.pdgId()) ]

        event.genvbosons = [
            p for p in event.genParticles
            if abs(p.pdgId()) in [23, 24] and p.numberOfDaughters() > 0
            and abs(p.daughter(0).pdgId()) != abs(p.pdgId()) and p.mass() > 30
        ]
        event.genvbosonsRecovered = []

        if not event.genvbosons:
            if abs(event.genParticles[4].pdgId()) in [
                    11, 12, 13, 14, 15, 16
            ] and abs(event.genParticles[4].pdgId()) == abs(
                    event.genParticles[5].pdgId()):
                l1 = event.genParticles[4]
                l2 = event.genParticles[5]
                V = GenParticle(0, l1.p4() + l2.p4(), l1.vertex(), 23, -123, 0)
                V.addDaughter(l1.daughterRef(0).motherRef(0))
                V.addDaughter(l2.daughterRef(0).motherRef(0))
                event.genvbosonsRecovered.append(V)

        #bosons = [ gp for gp in event.genParticles if gp.status() > 2 and  abs(gp.pdgId()) in [22,23,24]  ]
        for b in event.genvbosons:
            if b.numberOfDaughters() > 0:
                self.fillGenLeptons(event, b, sourceId=abs(b.pdgId(
                )))  #selezione su leptoni fatta dentro la funzione stessa
                self.fillWZQuarks(event, b, isWZ=True, sourceId=abs(b.pdgId()))

        for b in event.genvbosonsRecovered:
            if b.numberOfDaughters() > 0:
                self.fillGenLeptons(event,
                                    b,
                                    recovered=True,
                                    sourceId=abs(b.pdgId()))

        higgsBosons = [
            p for p in event.genParticles if (p.pdgId() == 25)
            and p.numberOfDaughters() > 0 and abs(p.daughter(0).pdgId()) != 25
        ]
        higgsBosonsFirst = [
            p for p in event.genParticles if (p.pdgId() == 25)
            and p.numberOfMothers() > 0 and abs(p.mother(0).pdgId()) != 25
        ]
        higgsMothers = [x.mother(0) for x in higgsBosonsFirst]
        #print higgsMothers
        event.genHiggsSisters = [
            p for p in event.genParticles
            if p.mother(0) in higgsMothers and p.pdgId() != 25
        ]

        #print "higgsBosons: ", len(higgsBosons)
        #print "higgsBosonsFirst: ", len(higgsBosonsFirst)
        #print "higgsMothers: ", len(higgsMothers)

        if len(higgsBosons) == 0:
            event.genHiggsDecayMode = 0

            ## Matching that can be done also on non-Higgs events
            ## First, top quarks
            self.fillTopQuarks(event)
            self.countBPartons(event)

            ## Then W,Z,gamma from hard scattering and that don't come from a top and don't rescatter
            def hasAncestor(particle, filter):
                for i in xrange(particle.numberOfMothers()):
                    mom = particle.mother(i)
                    if filter(mom) or hasAncestor(mom, filter):
                        return True
                return False

            def hasDescendent(particle, filter):
                for i in xrange(particle.numberOfDaughters()):
                    dau = particle.daughter(i)
                    if filter(dau) or hasDescendent(dau, filter):
                        return True
                return False
                """
            bosons = [ gp for gp in event.genParticles if gp.status() > 2 and  abs(gp.pdgId()) in [22,23,24]  ]
            for b in bosons:
                if hasAncestor(b,   lambda gp : abs(gp.pdgId()) == 6): continue
                if hasDescendent(b, lambda gp : abs(gp.pdgId()) in [22,23,24] and gp.status() > 2): continue
                self.fillGenLeptons(event, b, sourceId=abs(b.pdgId()))
                self.fillWZQuarks(event, b, isWZ=True, sourceId=abs(b.pdgId()))
		"""
        else:
            #            if len(higgsBosons) > 1:
            #                print "More than one higgs? \n%s\n" % higgsBosons

            #questo blocco viene eseguito quando c'e' almeno un higgs
            event.genHiggsBoson = higgsBosons[-1]
            #event.genHiggsBoson = [GenParticle(higgsBosons[-1])]
            event.genHiggsBosons = higgsBosons
            event.genHiggsDecayMode = abs(
                event.genHiggsBoson.daughter(0).pdgId(
                ) if event.genHiggsBoson.numberOfDaughters() >= 1 else 0)
            event.genHiggsDecayMode += abs(
                event.genHiggsBoson.daughter(1).pdgId(
                ) if event.genHiggsBoson.numberOfDaughters() >= 2
                and abs(event.genHiggsBoson.daughter(1).pdgId()) != abs(
                    event.genHiggsBoson.daughter(0).pdgId()) else 0) * 10000
            self.fillTopQuarks(event)
            self.countBPartons(event)
            #self.fillWZQuarks(   event, event.genHiggsBoson )
            #self.fillWZQuarks(   event, event.protons[0], sourceId=2212) : non serve, quando c'e' higgs non ci sn quarks da WZ
            for h in event.genHiggsBosons:
                self.fillHiggsBQuarks(event, h)
            #event.genHiggsBoson = [GenParticle(higgsBosons[-1])]
            #self.fillGenLeptons( event, event.genHiggsBoson, sourceId=25 )
            #if self.cfg_ana.verbose:
            if False:
                print "Higgs boson decay mode: ", event.genHiggsDecayMode
                print "Generator level prompt light leptons:\n", "\n".join(
                    ["\t%s" % p for p in event.genleps])
                print "Generator level light leptons from taus:\n", "\n".join(
                    ["\t%s" % p for p in event.gentauleps])
                print "Generator level prompt tau leptons:\n", "\n".join(
                    ["\t%s" % p for p in event.gentaus])
                print "Generator level b quarks from top:\n", "\n".join(
                    ["\t%s" % p for p in event.genbquarksFromTop])
                print "Generator level quarks from W, Z decays:\n", "\n".join(
                    ["\t%s" % p for p in event.genwzquarks])

        # make sure prompt leptons have a non-zero sourceId
        for p in event.genParticles:
            if isPromptLepton(p,
                              True,
                              includeTauDecays=True,
                              includeMotherless=False):
                if getattr(p, 'sourceId', 0) == 0:
                    p.sourceId = 99

    def hasBottom(self, pdgId):
        code1 = 0
        code2 = 0
        tmpHasBottom = False
        code1 = (int)((abs(pdgId) / 100) % 10)
        code2 = (int)((abs(pdgId) / 1000) % 10)
        if (code1 == 5 or code2 == 5): tmpHasBottom = True
        return tmpHasBottom

    def countBPartons(self, event):
        event.allBPartons = [
            q for q in event.genParticles if abs(q.pdgId()) == 5
            and abs(q.status()) == 2 and abs(q.pt()) > 15
        ]
        event.allBPartons.sort(key=lambda q: q.pt(), reverse=True)
        event.bPartons = []
        for q in event.allBPartons:
            duplicate = False
            for q2 in event.bPartons:
                if deltaR(q.eta(), q.phi(), q2.eta(), q2.phi()) < 0.5:
                    duplicate = True
                    continue
            if not duplicate: event.bPartons.append(q)

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf + ".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf + ".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]
            #print "Produced %d weights for %s: %s" % (len(ws),pdf,event.pdfWeights[pdf])

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

        ## creating a "sub-event" for this analyzer
        #myEvent = Event(event.iEv)
        #setattr(event, self.name, myEvent)
        #event = myEvent

        # if not MC, nothing to do
        if not self.cfg_comp.isMC:
            return True

        # do MC level analysis
        self.makeMCInfo(event)

        # if MC and filtering on the Higgs decay mode,
        # them do filter events
        if self.cfg_ana.filterHiggsDecays:
            if event.genHiggsDecayMode not in self.cfg_ana.filterHiggsDecays:
                return False

        # do PDF weights, if requested
        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True
Exemple #10
0
class ttHGenLevelAnalyzer(Analyzer):
    """Do generator-level analysis of a ttH->leptons decay:

       Creates in the event:
         event.genParticles   = the gen particles (pruned, as default)
         event.genHiggsDecayMode =   0  for non-Higgs
                                 15  for H -> tau tau
                                 23  for H -> Z Z
                                 24  for H -> W W
                                 xx  for H -> xx yy zzz 

          event.genleps    = [ status 3 gen electrons and muons not from tau decays ]
          event.gentauleps = [ gen electrons and muons from decays of status 3 taus ]
          event.genbquarks  = [ gen b quarks (status = 3) from to quark decays ]
          event.genwzquarks = [ gen quarks from hadronic W,Z decays ]

       If filterHiggsDecays is set to a list of Higgs decay modes,
       it will filter events that have those decay modes.
       e.g. [0, 15, 23, 24] will keep data, non-Higgs MC and Higgs decays to (tau, Z, W) 
       but will drop Higgs decays to other particles (e.g. bb).
      
    """
    def __init__(self, cfg_ana, cfg_comp, looperName):
        super(ttHGenLevelAnalyzer, self).__init__(cfg_ana, cfg_comp,
                                                  looperName)
        self.doPDFWeights = hasattr(
            self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False

    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS
    #---------------------------------------------

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

        #mc information
        self.mchandles['genParticles'] = AutoHandle(
            'genParticlesPruned', 'std::vector<reco::GenParticle>')
        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle('generator',
                                                    'GenEventInfoProduct')

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

    def fillGenLeptons(self, event, particle, isTau=False, sourceId=25):
        """Get the gen level light leptons (prompt and/or from tau decays)"""

        for i in xrange(particle.numberOfDaughters()):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            dau.isTau = isTau
            id = abs(dau.pdgId())
            if id in [11, 13]:
                if isTau: event.gentauleps.append(dau)
                else: event.genleps.append(dau)
            elif id == 15:
                self.fillGenLeptons(event, dau, True, sourceId)
            elif id in [22, 23, 24]:
                self.fillGenLeptons(event, dau, False, sourceId)

    def fillWZQuarks(self, event, particle, isWZ=False, sourceId=25):
        """Descend daughters of 'particle', and add quarks from W,Z to event.genwzquarks
           isWZ is set to True if already processing daughters of W,Z's, to False before it"""

        for i in xrange(particle.numberOfDaughters()):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            id = abs(dau.pdgId())
            if id <= 5 and isWZ:
                event.genwzquarks.append(dau)
            elif id in [22, 23, 24]:
                self.fillWZQuarks(event, dau, True, sourceId)

    def fillTopQuarks(self, event):
        """Get the b quarks from top decays into event.genbquarks"""

        event.gentopquarks = [
            p for p in event.genParticles
            if (p.status() == 3 and abs(p.pdgId()) == 6)
        ]
        #if len(event.gentopquarks) != 2:
        #    print "Not two top quarks? \n%s\n" % event.gentopquarks

        for tq in event.gentopquarks:
            for i in xrange(tq.numberOfDaughters()):
                dau = GenParticle(tq.daughter(i))
                if abs(dau.pdgId()) == 5:
                    dau.sourceId = 6
                    event.genbquarks.append(dau)
                elif abs(dau.pdgId()) == 24:
                    self.fillGenLeptons(event, dau, sourceId=6)
                    self.fillWZQuarks(event, dau, True, sourceId=6)

    def makeMCInfo(self, event):
        event.genParticles = map(GenParticle,
                                 self.mchandles['genParticles'].product())

        event.genHiggsBoson = None
        event.genleps = []
        event.gentauleps = []
        event.genbquarks = []
        event.genwzquarks = []
        event.gentopquarks = []

        higgsBosons = [
            p for p in event.genParticles
            if (p.status() == 3 and p.pdgId() == 25)
        ]

        if len(higgsBosons) == 0:
            event.genHiggsDecayMode = 0

            ## Matching that can be done also on non-Higgs events
            ## First, top quarks
            self.fillTopQuarks(event)

            ## Then W,Z,gamma from hard scattering and that don't come from a top and don't rescatter
            def hasAncestor(particle, filter):
                for i in xrange(particle.numberOfMothers()):
                    mom = particle.mother(i)
                    if filter(mom) or hasAncestor(mom, filter):
                        return True
                return False

            def hasDescendent(particle, filter):
                for i in xrange(particle.numberOfDaughters()):
                    dau = particle.daughter(i)
                    if filter(dau) or hasDescendent(dau, filter):
                        return True
                return False

            bosons = [
                gp for gp in event.genParticles
                if gp.status() == 3 and abs(gp.pdgId()) in [22, 23, 24]
            ]
            for b in bosons:
                if hasAncestor(b, lambda gp: abs(gp.pdgId()) == 6): continue
                if hasDescendent(
                        b, lambda gp: abs(gp.pdgId()) in [22, 23, 24] and gp.
                        status() == 3):
                    continue
                self.fillGenLeptons(event, b, sourceId=abs(b.pdgId()))
                self.fillWZQuarks(event, b, isWZ=True, sourceId=abs(b.pdgId()))
        else:
            if len(higgsBosons) > 1:
                print "More than one higgs? \n%s\n" % higgsBosons

            event.genHiggsBoson = GenParticle(higgsBosons[-1])
            event.genHiggsDecayMode = abs(
                event.genHiggsBoson.daughter(0).pdgId())
            self.fillTopQuarks(event)
            self.fillWZQuarks(event, event.genHiggsBoson)
            self.fillGenLeptons(event, event.genHiggsBoson, sourceId=25)
            if self.cfg_ana.verbose:
                print "Higgs boson decay mode: ", event.genHiggsDecayMode
                print "Generator level prompt light leptons:\n", "\n".join(
                    ["\t%s" % p for p in event.genleps])
                print "Generator level light leptons from taus:\n", "\n".join(
                    ["\t%s" % p for p in event.gentauleps])
                print "Generator level b quarks from top:\n", "\n".join(
                    ["\t%s" % p for p in event.genbquarks])
                print "Generator level quarks from W, Z decays:\n", "\n".join(
                    ["\t%s" % p for p in event.genwzquarks])

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf + ".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf + ".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]
            #print "Produced %d weights for %s: %s" % (len(ws),pdf,event.pdfWeights[pdf])

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

        ## creating a "sub-event" for this analyzer
        #myEvent = Event(event.iEv)
        #setattr(event, self.name, myEvent)
        #event = myEvent

        # if not MC, nothing to do
        if not self.cfg_comp.isMC:
            return True

        # do MC level analysis
        self.makeMCInfo(event)

        # if MC and filtering on the Higgs decay mode,
        # them do filter events
        if self.cfg_ana.filterHiggsDecays:
            if event.genHiggsDecayMode not in self.cfg_ana.filterHiggsDecays:
                return False

        # do PDF weights, if requested
        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True
class ttHGenLevelOnlyStudy( Analyzer ):
    """
    Fakes a reco event starting from GEN-only files      
    """
    def __init__(self, cfg_ana, cfg_comp, looperName ):
        super(ttHGenLevelOnlyStudy,self).__init__(cfg_ana,cfg_comp,looperName)
        self.doPDFWeights = hasattr(self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False
    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS 
    #---------------------------------------------
        

    def declareHandles(self):
        super(ttHGenLevelOnlyStudy, self).declareHandles()
        self.mchandles['genParticles'] = AutoHandle( 'genParticles', 'std::vector<reco::GenParticle>' )
        self.mchandles['jets'] = AutoHandle( 'ak5GenJets', 'std::vector<reco::GenJet>' )
        self.mchandles['met'] = AutoHandle( 'genMetTrue', 'std::vector<reco::GenMET>' )
        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle( 'generator', 'GenEventInfoProduct' )

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

    def doLeptons(self,iEvent,event):
        def isPrompt(l):
            for x in xrange(l.numberOfMothers()):
                mom = l.mother(x)
                if mom.status() > 2: return True
                id = abs(mom.pdgId()) % 1000000
                if id > 100: return False
                if id <   6: return False
                if id == 21: return False
                if id in [11,13,15]: return isPrompt(mom)
                if id in [ 22,23,24,25,32,6 ]: return True
            return True
            
        event.selectedLeptons = []
        for l in event.genParticles: 
            if abs(l.pdgId()) not in [11,13] or l.status() != 1: continue
            if abs(l.pdgId()) == 13:
                if l.pt() <= 3 or abs(l.eta()) > 2.4: continue
            if abs(l.pdgId()) == 11:
                if l.pt() <= 5 or abs(l.eta()) > 2.5: continue
            if not isPrompt(l):
                continue
            event.selectedLeptons.append(LeptonFromGen(l))

    def doJets(self,iEvent,event):
        event.cleanJetsAll = []
        event.cleanJetsFwd = []
        event.cleanJets = []
        for j in self.mchandles['jets'].product(): 
            visfrac = 1.0 - j.invisibleEnergy()/j.energy()
            if j.pt()*visfrac < 25: continue
            #print "mc jet with pt %.1f, eta %.1f, vis %.1f, invis %.1f" % (j.pt(), j.eta(), j.emEnergy()+j.hadEnergy(), j.invisibleEnergy())
            islepton = False
            for l in event.selectedLeptons:
                if l.pt() > 10 and deltaR(l.eta(),l.phi(),j.eta(),j.phi()) < 0.5:
                    #print " ---> it's a lepton"
                    islepton = True
                    break
            if islepton: continue
            j.setP4(j.p4()*visfrac)
            jo = JetFromGen(j)
            event.cleanJetsAll.append(jo)
            if abs(j.eta()) < 2.4:
                event.cleanJets.append(jo)
            else:
                event.cleanJetsFwd.append(jo)
    def doBTag(self,iEvent,event):
        bs = []
        for gp in event.genParticles:
            if gp.status() != 2: continue
            id = abs(gp.pdgId())
            if id == 5 or ((id % 1000) / 100) == 5 or ((id % 10000)/1000) == 5:
                bs.append(gp)
        for j in event.cleanJetsAll:
            for gp in bs:
                if deltaR(gp.eta(),gp.phi(),j.eta(),j.phi()) < 0.4:
                    gp.btag = True
    def doMET(self,iEvent,event):
        event.met = self.mchandles['met'].product().front()

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

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

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

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

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

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


    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf+".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf+".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]
            #print "Produced %d weights for %s: %s" % (len(ws),pdf,event.pdfWeights[pdf])

    def doHT(self, iEvent, event):
        import ROOT

        objects25 = [ j for j in event.cleanJets if j.pt() > 25 ] + event.selectedLeptons
        objects30 = [ j for j in event.cleanJets if j.pt() > 30 ] + event.selectedLeptons
        objects40  = [ j for j in event.cleanJets if j.pt() > 40 ] + event.selectedLeptons
        objects40j = [ j for j in event.cleanJets if j.pt() > 40 ] 

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

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

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

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

    def doStops(self, event):
        event.genStops = []
        for stop in event.genParticles:
            if abs(stop.pdgId()) != 1000006: continue
            # skip intermediate stops
            selfveto = False
            for i in xrange(stop.numberOfDaughters()):
                if abs(stop.daughter(i).pdgId()) == 1000006: 
                    selfveto = True; break
            if selfveto: continue
            # add them
            event.genStops.append(StopDecay(stop))
        event.genStops.sort(key = lambda p : - p.pdgId())

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

        # if not MC, nothing to do
        if not self.cfg_comp.isMC: 
            return True

        event.genParticles = [ gp for gp in self.mchandles['genParticles'].product() ]

        event.eventWeigth = 1.0
        event.run = iEvent.eventAuxiliary().id().run()
        event.lumi = iEvent.eventAuxiliary().id().luminosityBlock()
        event.eventId = iEvent.eventAuxiliary().id().event()
        
        self.doLeptons(iEvent,event)
        self.makeZs(event, 4)
        self.makeMlls(event, 4)
        self.doJets(iEvent,event)
        self.doBTag(iEvent,event)
        self.doMET(iEvent,event)
        self.doHT(iEvent,event)
        self.doStops(event)

        # do PDF weights, if requested
        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True
Exemple #12
0
class GeneratorAnalyzer( Analyzer ):
    """Do generator-level analysis of a ttH->leptons decay:

       Creates in the event:
         event.genParticles   = the gen particles (pruned, as default)
         event.genHiggsDecayMode =   0  for non-Higgs
                                 15  for H -> tau tau
                                 23  for H -> Z Z
                                 24  for H -> W W
                                 xx  for H -> xx yy zzz 

          event.gentauleps = [ gen electrons and muons from hard scattering not from tau decays ]
          event.gentaus    = [ gen taus from from hard scattering ]
          event.genleps    = [ gen electrons and muons from hard scattering not from tau decays ]
          event.genbquarksFromTop  = [ gen b quarks from top quark decays ]
          event.genwzquarks = [ gen quarks from hadronic W,Z decays ]

       If filterHiggsDecays is set to a list of Higgs decay modes,
       it will filter events that have those decay modes.
       e.g. [0, 15, 23, 24] will keep data, non-Higgs MC and Higgs decays to (tau, Z, W) 
       but will drop Higgs decays to other particles (e.g. bb).
      
    """
    def __init__(self, cfg_ana, cfg_comp, looperName ):
        super(GeneratorAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName)
        self.doPDFWeights = hasattr(self.cfg_ana, "PDFWeights") and len(self.cfg_ana.PDFWeights) > 0
        if self.doPDFWeights:
            self.pdfWeightInit = False
    #---------------------------------------------
    # DECLARATION OF HANDLES OF GEN LEVEL OBJECTS 
    #---------------------------------------------
        

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

        #mc information
        self.mchandles['genParticles'] = AutoHandle( 'prunedGenParticles',
                                                     'std::vector<reco::GenParticle>' )
        if self.doPDFWeights:
            self.mchandles['pdfstuff'] = AutoHandle( 'generator', 'GenEventInfoProduct' )

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

    def fillGenLeptons(self, event, particle, isTau=False, recovered=False, sourceId=25):
        """Get the gen level light leptons (prompt and/or from tau decays)"""

        for i in xrange( particle.numberOfDaughters() ):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            dau.isTau = isTau
            id = abs(dau.pdgId())
            moid = abs(dau.mother().pdgId()) if dau.mother() else 2212 #if no mom, let say it is a proton (consistent with CMSSW < 74X)
            if id in [11,13]:
                if not recovered:
                    if isTau: event.gentauleps.append(dau)
                    else:     event.genleps.append(dau)
                else:
                    if isTau: event.gentaulepsRecovered.append(dau)
                    else:     event.genlepsRecovered.append(dau)
            elif id == 15:
                if not recovered:
                    if moid in [22,23,24]:
                        event.gentaus.append(dau)
                    self.fillGenLeptons(event, dau, True, sourceId)
                else:
                    if moid in [22,23,24]:
                        event.gentausRecovered.append(dau)
                    self.fillGenLeptons(event, dau, True, True, sourceId) 
            elif id in [22,23,24]:
                if not recovered: self.fillGenLeptons(event, dau, False,       sourceId)
                else:             self.fillGenLeptons(event, dau, False, True, sourceId)

    def fillWZQuarks(self, event, particle, isWZ=False, sourceId=25):
        """Descend daughters of 'particle', and add quarks from W,Z to event.genwzquarks
           isWZ is set to True if already processing daughters of W,Z's, to False before it"""

        for i in xrange( particle.numberOfDaughters() ):
            dau = GenParticle(particle.daughter(i))
            dau.sourceId = sourceId
            id = abs(dau.pdgId())
            if id <= 5 and isWZ:
                event.genwzquarks.append(dau)
            elif id in [22,23,24]:
                self.fillWZQuarks(event, dau, True, sourceId)

    def fillHiggsBQuarks(self, event,h):
        """Get the b quarks from top decays into event.genbquarksFromH"""
        for i in xrange( h.numberOfDaughters() ):
            dau = GenParticle(h.daughter(i))
            if abs(dau.pdgId()) in [3,4,5]:
                    event.genbquarksFromH.append( dau )
                    if dau.numberOfDaughters() == 1 :
                         event.genbquarksFromHafterISR.append( GenParticle(dau.daughter(0)))


    def fillTopQuarks(self, event):
        """Get the b quarks from top decays into event.genbquarksFromTop"""

        event.gentopquarks = [ p for p in event.genParticles if abs(p.pdgId()) == 6 and p.numberOfDaughters() > 0 and abs(p.daughter(0).pdgId()) != 6 ]
       
        #Find the top decay mode (0 - leptonic, 1 - hadronic)
        for top in event.gentopquarks:
            ndaus = top.numberOfDaughters()
            top.decayMode = -1
            
            #go over top daughters
            for idau in range(ndaus):
                dau = top.daughter(idau)
                #found the W
                if abs(dau.pdgId()) == 24:
                    #find the true daughters of the W (in case of decay chain)
                    W_daus = realGenDaughters(dau)
                    decayMode = -1
                    #go over the daughters of the W
                    for idauw in range(len(W_daus)):
                        w_dau_id = abs(W_daus[idauw].pdgId())
                        #leptonic
                        if w_dau_id in [11,12,13,14,15,16]:
                            decayMode = 0
                            break
                        #hadronic
                        elif w_dau_id < 6:
                            decayMode = 1
                            break
                    top.decayMode = decayMode
                    break
        for tq in event.gentopquarks:
            for i in xrange( tq.numberOfDaughters() ):
                dau = GenParticle(tq.daughter(i))
                if abs(dau.pdgId()) == 5:
                    dau.sourceId = 6
                    event.genbquarksFromTop.append( dau )
                elif abs(dau.pdgId()) == 24:
                    self.fillGenLeptons( event, dau, sourceId=6 )
                    self.fillWZQuarks(   event, dau, True, sourceId=6 )

    def makeMCInfo(self, event):

        LHE_weights_scale = []
        LHE_weights_pdf = []

        # https://twiki.cern.ch/twiki/bin/viewauth/CMS/LHEReaderCMSSW)
        for w in event.LHE_weights:
            wid = int(w.id)
            #print wid, ": ", w.wgt
            # for LO samples, the scale weights are 1,...,9; for NLO 1001,1009
            if (wid in range(1,10)) or (wid in range(1001,1010)):
                wid = wid%1000
                if wid not in [1,6,8]: # these are the nominal and anticorrelated muR,muF variations
                    w.wgt = w.wgt/event.LHE_originalWeight if abs(event.LHE_originalWeight)>0 else w.wgt
                    w.order = LHE_scale_order[wid]
                    #print int(w.id), ": ", w.wgt, " (pos ", w.order, ")"
                    LHE_weights_scale.append(w)
            # thse are up/down variations for the NNPDF: https://twiki.cern.ch/twiki/bin/view/CMS/TTbarHbbRun2ReferenceAnalysisLimits
            if wid in LHE_pdf_ids:
                #print  w.wgt
                w.wgt = w.wgt/event.LHE_originalWeight if abs(event.LHE_originalWeight)>0 else w.wgt
                LHE_weights_pdf.append(w)

        event.LHE_weights_scale = sorted(LHE_weights_scale, key=lambda w : w.order)
        event.LHE_weights_pdf = LHE_weights_pdf

#       event.genParticles = map( GenParticle, self.mchandles['genParticles'].product() )
        event.genParticles = list(self.mchandles['genParticles'].product() )

        if False:
        
            for i,p in enumerate(event.genParticles):
                print " %5d: pdgId %+5d status %3d  pt %6.1f  " % (i, p.pdgId(),p.status(),p.pt()),
                if p.numberOfMothers() > 0:
                    imom, mom = p.motherRef().key(), p.mother()
                    print " | mother %5d pdgId %+5d status %3d  pt %6.1f  " % (imom, mom.pdgId(),mom.status(),mom.pt()),
                else:
                    print " | no mother particle                              ",
                    
                for j in xrange(min(3, p.numberOfDaughters())):
                    idau, dau = p.daughterRef(j).key(), p.daughter(j)
                    print " | dau[%d] %5d pdgId %+5d status %3d  pt %6.1f  " % (j,idau,dau.pdgId(),dau.status(),dau.pt()),
                print ""

        event.genHiggsBosons = []
        event.genHiggsSisters = []
        event.genleps    = []
        event.gentauleps = []
        event.gentaus    = []
        event.genlepsRecovered    = []
        event.gentaulepsRecovered = []
        event.gentausRecovered    = []
        event.genbquarksFromTop  = []
        event.genbquarksFromH  = []
        event.genbquarksFromHafterISR = []
        event.genallbquarks = []
        event.genwzquarks = []
        event.gentopquarks  = []
        event.genallstatus2bhadrons = [ p for p in event.genParticles if p.status() ==2 and self.hasBottom(p.pdgId()) ]
        event.genallcquarks = [ p for p in event.genParticles if abs(p.pdgId()) == 4 and ( p.numberOfDaughters() == 0 or abs(p.daughter(0).pdgId()) != 4) ]

		# aggiunti da me

        #event.genHiggsToBB = [ p for p in event.genParticles if abs(p.pdgId())==25 and p.numberOfDaughters()==2 and abs(p.daughter(0).pdgId()) == 5 ] 

        #event.genvbosonsToLL = [ p for p in event.genParticles if abs(p.pdgId()) in [23,24] and abs(p.mother().pdgId()) in [23,24] and p.numberOfDaughters()==2 and abs(p.daughter(0).pdgId()) in [11,13,15] ]

        #event.genZbosonsToLL = [ p for p in event.genParticles if abs(p.pdgId()) in [23] and abs(p.daughter(0).pdgId())!= abs(p.pdgId()) ]
        #event.genWbosonsToLL = [ p for p in event.genParticles if abs(p.pdgId()) in [24] and abs(p.daughter(0).pdgId())!= abs(p.pdgId()) ]

        event.genvbosons = [ p for p in event.genParticles if abs(p.pdgId()) in [23,24] and p.numberOfDaughters()>0 and abs(p.daughter(0).pdgId()) != abs(p.pdgId()) and p.mass() > 30 ]
        event.genvbosonsRecovered=[]

        if not event.genvbosons:
            if abs(event.genParticles[4].pdgId()) in [11,12,13,14,15,16] and abs(event.genParticles[4].pdgId())==abs(event.genParticles[5].pdgId()):
                l1=event.genParticles[4]
                l2=event.genParticles[5]
                V=GenParticle(0, l1.p4()+l2.p4(), l1.vertex(), 23, -123, 0)
                V.addDaughter(l1.daughterRef(0).motherRef(0))
                V.addDaughter(l2.daughterRef(0).motherRef(0))
                event.genvbosonsRecovered.append(V)
 		   
        #bosons = [ gp for gp in event.genParticles if gp.status() > 2 and  abs(gp.pdgId()) in [22,23,24]  ]
    	for b in event.genvbosons:
        	if b.numberOfDaughters()>0 :
                	self.fillGenLeptons(event, b, sourceId=abs(b.pdgId())) #selezione su leptoni fatta dentro la funzione stessa
                	self.fillWZQuarks(event, b, isWZ=True, sourceId=abs(b.pdgId()))

        for b in event.genvbosonsRecovered:
            if b.numberOfDaughters()>0 :
                self.fillGenLeptons(event, b, recovered=True, sourceId=abs(b.pdgId()))


        higgsBosons = [ p for p in event.genParticles if (p.pdgId() == 25) and p.numberOfDaughters() > 0 and abs(p.daughter(0).pdgId()) != 25 ]
        higgsBosonsFirst = [ p for p in event.genParticles if (p.pdgId() == 25) and p.numberOfMothers() > 0 and abs(p.mother(0).pdgId()) != 25 ]
        higgsMothers = [x.mother(0) for x in higgsBosonsFirst]
        #print higgsMothers
        event.genHiggsSisters = [p for p in event.genParticles if p.mother(0) in higgsMothers  and p.pdgId() != 25 ]

        #print "higgsBosons: ", len(higgsBosons)
        #print "higgsBosonsFirst: ", len(higgsBosonsFirst)
        #print "higgsMothers: ", len(higgsMothers)
        

        if len(higgsBosons) == 0:
            event.genHiggsDecayMode = 0

            ## Matching that can be done also on non-Higgs events
            ## First, top quarks
            self.fillTopQuarks( event )
            self.countBPartons( event )

            ## Then W,Z,gamma from hard scattering and that don't come from a top and don't rescatter
            def hasAncestor(particle, filter):
                for i in xrange(particle.numberOfMothers()):
                    mom = particle.mother(i)
                    if filter(mom) or hasAncestor(mom, filter): 
                        return True
                return False
            def hasDescendent(particle, filter):
                for i in xrange(particle.numberOfDaughters()):
                    dau = particle.daughter(i)
                    if filter(dau) or hasDescendent(dau, filter):
                        return True
                return False

		"""
            bosons = [ gp for gp in event.genParticles if gp.status() > 2 and  abs(gp.pdgId()) in [22,23,24]  ]
            for b in bosons:
                if hasAncestor(b,   lambda gp : abs(gp.pdgId()) == 6): continue
                if hasDescendent(b, lambda gp : abs(gp.pdgId()) in [22,23,24] and gp.status() > 2): continue
                self.fillGenLeptons(event, b, sourceId=abs(b.pdgId()))
                self.fillWZQuarks(event, b, isWZ=True, sourceId=abs(b.pdgId()))
		"""
        else:
#            if len(higgsBosons) > 1: 
#                print "More than one higgs? \n%s\n" % higgsBosons

            #questo blocco viene eseguito quando c'e' almeno un higgs
            event.genHiggsBoson = higgsBosons[-1]
            #event.genHiggsBoson = [GenParticle(higgsBosons[-1])]
            event.genHiggsBosons = higgsBosons
            event.genHiggsDecayMode = abs(  event.genHiggsBoson.daughter(0).pdgId() if event.genHiggsBoson.numberOfDaughters() >= 1 else 0)
            event.genHiggsDecayMode += abs( event.genHiggsBoson.daughter(1).pdgId() if event.genHiggsBoson.numberOfDaughters() >= 2 and abs( event.genHiggsBoson.daughter(1).pdgId() ) != abs( event.genHiggsBoson.daughter(0).pdgId()) else 0) * 10000
            self.fillTopQuarks( event )
            self.countBPartons( event )
            #self.fillWZQuarks(   event, event.genHiggsBoson )
            #self.fillWZQuarks(   event, event.protons[0], sourceId=2212) : non serve, quando c'e' higgs non ci sn quarks da WZ
            for h in event.genHiggsBosons :
                self.fillHiggsBQuarks( event, h)
            #event.genHiggsBoson = [GenParticle(higgsBosons[-1])]
            #self.fillGenLeptons( event, event.genHiggsBoson, sourceId=25 )
            #if self.cfg_ana.verbose:
            if False:
                print "Higgs boson decay mode: ", event.genHiggsDecayMode
                print "Generator level prompt light leptons:\n", "\n".join(["\t%s" % p for p in event.genleps])
                print "Generator level light leptons from taus:\n", "\n".join(["\t%s" % p for p in event.gentauleps])
                print "Generator level prompt tau leptons:\n", "\n".join(["\t%s" % p for p in event.gentaus])
                print "Generator level b quarks from top:\n", "\n".join(["\t%s" % p for p in event.genbquarksFromTop])
                print "Generator level quarks from W, Z decays:\n", "\n".join(["\t%s" % p for p in event.genwzquarks])
       
        # make sure prompt leptons have a non-zero sourceId
        for p in event.genParticles:
            if isPromptLepton(p, True, includeTauDecays=True, includeMotherless=False):
                if getattr(p, 'sourceId', 0) == 0:
                    p.sourceId = 99

    def hasBottom(self,pdgId):
      code1=0;
      code2=0;
      tmpHasBottom = False;
      code1 = (int)( ( abs(pdgId) / 100)%10 );
      code2 = (int)( ( abs(pdgId) /1000)%10 );
      if ( code1 == 5 or code2 == 5): tmpHasBottom = True;
      return tmpHasBottom;
      
    def countBPartons(self,event):
        event.allBPartons = [ q for q in event.genParticles if abs(q.pdgId()) == 5 and abs(q.status()) == 2 and abs(q.pt()) > 15 ]
        event.allBPartons.sort(key = lambda q : q.pt(), reverse = True)
        event.bPartons = []
        for q in event.allBPartons:
            duplicate = False
            for q2 in event.bPartons:
                if deltaR(q.eta(),q.phi(),q2.eta(),q2.phi()) < 0.5:
                    duplicate = True
                    continue
            if not duplicate: event.bPartons.append(q)

    def initPDFWeights(self):
        from ROOT import PdfWeightProducerTool
        self.pdfWeightInit = True
        self.pdfWeightTool = PdfWeightProducerTool()
        for pdf in self.cfg_ana.PDFWeights:
            self.pdfWeightTool.addPdfSet(pdf+".LHgrid")
        self.pdfWeightTool.beginJob()

    def makePDFWeights(self, event):
        if not self.pdfWeightInit: self.initPDFWeights()
        self.pdfWeightTool.processEvent(self.mchandles['pdfstuff'].product())
        event.pdfWeights = {}
        for pdf in self.cfg_ana.PDFWeights:
            ws = self.pdfWeightTool.getWeights(pdf+".LHgrid")
            event.pdfWeights[pdf] = [w for w in ws]
            #print "Produced %d weights for %s: %s" % (len(ws),pdf,event.pdfWeights[pdf])

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

        ## creating a "sub-event" for this analyzer
        #myEvent = Event(event.iEv)
        #setattr(event, self.name, myEvent)
        #event = myEvent

        # if not MC, nothing to do
        if not self.cfg_comp.isMC: 
            return True

        # do MC level analysis
        self.makeMCInfo(event)

        # if MC and filtering on the Higgs decay mode, 
        # them do filter events
        if self.cfg_ana.filterHiggsDecays:
            if event.genHiggsDecayMode not in self.cfg_ana.filterHiggsDecays:
                return False

        # do PDF weights, if requested
        if self.doPDFWeights:
            self.makePDFWeights(event)
        return True