File indexing completed on 2024-11-28 03:56:24
0001
0002
0003
0004
0005
0006 from PhysicsTools.NanoAODTools.postprocessing.framework.postprocessor import PostProcessor
0007 from PhysicsTools.NanoAODTools.postprocessing.framework.eventloop import Module
0008 from PhysicsTools.NanoAODTools.postprocessing.framework.datamodel import Collection
0009 import PhysicsTools.NanoAODTools.postprocessing.framework.datamodel as datamodel
0010 datamodel.statusflags['isHardPrompt'] = datamodel.statusflags['isPrompt'] + datamodel.statusflags['fromHardProcess']
0011
0012 def hasbit(value,bit):
0013 """Check if i'th bit is set to 1, i.e. binary of 2^i,
0014 from the right to the left, starting from position i=0.
0015 Example: hasbit(GenPart_statusFlags,0) -> isPrompt"""
0016 return (value & (1 << bit))>0
0017
0018
0019 def getprodchain(part,genparts=None,event=None,decay=-1):
0020 """Print production chain recursively."""
0021 chain = "%3s"%(part.pdgId)
0022 imoth = part.genPartIdxMother
0023 while imoth>=0:
0024 if genparts is not None:
0025 moth = genparts[imoth]
0026 chain = "%3s -> "%(moth.pdgId)+chain
0027 imoth = moth.genPartIdxMother
0028 elif event is not None:
0029 chain = "%3s -> "%(event.GenPart_pdgId[imoth])+chain
0030 imoth = event.GenPart_genPartIdxMother[imoth]
0031 if genparts is not None and decay>0:
0032 chain = chain[:-3]
0033 chain += getdecaychain(part,genparts,indent=len(chain),depth=decay-1)
0034 return chain
0035
0036
0037 def getdecaychain(part,genparts,indent=0,depth=999):
0038 """Print decay chain recursively."""
0039 chain = "%3s"%(part.pdgId)
0040 imoth = part._index
0041 ndaus = 0
0042 indent_ = len(chain)+indent
0043 for idau in range(imoth+1,genparts._len):
0044 dau = genparts[idau]
0045 if dau.genPartIdxMother==imoth:
0046 if ndaus>=1:
0047 chain += '\n'+' '*indent_
0048 if depth>=2:
0049 chain += " -> "+getdecaychain(dau,genparts,indent=indent_+4,depth=depth-1)
0050 else:
0051 chain += " -> %3s"%(dau.pdgId)
0052 ndaus += 1
0053 return chain
0054
0055
0056
0057 class LHEDumper(Module):
0058
0059 def __init__(self):
0060 self.nleptonic = 0
0061 self.ntauonic = 0
0062 self.nevents = 0
0063
0064 def analyze(self,event):
0065 """Dump gen information for each gen particle in given event."""
0066 print("\n%s Event %s %s"%('-'*10,event.event,'-'*70))
0067 self.nevents += 1
0068 leptonic = False
0069 tauonic = False
0070 bosons = [ ]
0071 taus = [ ]
0072 particles = Collection(event,'GenPart')
0073
0074 print(" \033[4m%7s %7s %7s %7s %7s %7s %7s %7s %8s %9s %10s \033[0m"%(
0075 "index","pdgId","moth","mothId","dR","pt","eta","status","prompt","taudecay","last copy"))
0076 for i, particle in enumerate(particles):
0077 mothidx = particle.genPartIdxMother
0078 eta = max(-999,min(999,particle.eta))
0079 prompt = particle.statusflag('isPrompt')
0080 taudecay = particle.statusflag('isTauDecayProduct')
0081 lastcopy = particle.statusflag('isLastCopy')
0082
0083 if 0<=mothidx<particles._len:
0084 moth = particles[mothidx]
0085 mothpid = moth.pdgId
0086 mothdR = max(-999,min(999,particle.DeltaR(moth)))
0087 print(" %7d %7d %7d %7d %7.2f %7.2f %7.2f %7d %8s %9s %10s"%(
0088 i,particle.pdgId,mothidx,mothpid,mothdR,particle.pt,eta,particle.status,prompt,taudecay,lastcopy))
0089 else:
0090 print(" %7d %7d %7s %7s %7s %7.2f %7.2f %7d %8s %9s %10s"%(
0091 i,particle.pdgId,"","","",particle.pt,eta,particle.status,prompt,taudecay,lastcopy))
0092 if lastcopy:
0093 if abs(particle.pdgId) in [11,13,15]:
0094 leptonic = True
0095 if abs(particle.pdgId)==15:
0096 tauonic = True
0097 taus.append(particle)
0098 elif abs(particle.pdgId) in [23,24]:
0099 bosons.append(particle)
0100 for boson in bosons:
0101 print("Boson production:")
0102 print(getprodchain(boson,particles,decay=2))
0103 for tau in taus:
0104 print("Tau decay:")
0105 print(getdecaychain(tau,particles))
0106 if leptonic:
0107 self.nleptonic += 1
0108 if tauonic:
0109 self.ntauonic += 1
0110
0111 def endJob(self):
0112 print('\n'+'-'*96)
0113 if self.nevents>0:
0114 print(" %-10s %4d / %-4d (%4.1f%%)"%('Tauonic: ',self.ntauonic, self.nevents,100.0*self.ntauonic/self.nevents))
0115 print(" %-10s %4d / %-4d (%4.1f%%)"%('Leptonic:',self.nleptonic,self.nevents,100.0*self.nleptonic/self.nevents))
0116 print("%s Done %s\n"%('-'*10,'-'*80))
0117
0118
0119
0120 url = "root://cms-xrd-global.cern.ch/"
0121 from argparse import ArgumentParser
0122 parser = ArgumentParser()
0123 parser.add_argument('-i', '--infiles', nargs='+')
0124 parser.add_argument('-o', '--outdir', default='.')
0125 parser.add_argument('-n', '--maxevts', type=int, default=20)
0126 args = parser.parse_args()
0127 infiles = args.infiles or [
0128 url+'/store/mc/RunIISummer20UL18NanoAODv9/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/106X_upgrade2018_realistic_v16_L1v1-v1/280000/525CD279-3344-6043-98B9-2EA8A96623E4.root',
0129
0130 ]
0131 processor = PostProcessor(args.outdir,infiles,noOut=True,modules=[LHEDumper()],maxEntries=args.maxevts)
0132 processor.run()