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 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
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
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
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