def GetYield2(path, files, ch='eee', level='sr', inc=None, histopref='', filepref='', var='', isdata=False): t = TopHistoReader(path, files) t.SetLevel(level) t.SetChan(ch) t.SetHistoNamePrefix(histopref) #t.SetLumi(GetLumi(2018)*1000) #t.SetLumi(GetLumi(year)*1000) #t.SetLumi(1) t.SetFileNamePrefix(filepref) t.SetIsData(isdata) if var != '': pref = histopref + '_' if histopref != '' else '' if inc == None: h = t.GetNamedHisto(pref + var + '_' + ch) else: h = t.GetNamedHisto(pref + var + '_' + ch + '_' + inc) y = h.GetBinContent(9) else: y = t.GetYield() return y
def loadHistos(self): ''' Load the PDF and Scale histos and norm histos ''' t = TopHistoReader(self.path) t.SetHistoNamePrefix(self.histoprefix) t.SetIsData(1) n = self.GetSampleName() t.SetProcess(n) t.SetChan(self.GetChan()) t.SetLevel(self.GetLevel()) #if self.GetNgenEvents() <= 0 : self.SetNgenEvents(t.GetNGenEvents()) self.SetYield(t.GetYield() * self.GetLumi()) self.hpdf = t.GetHisto(n, self.PDFhistoName) self.hscale = t.GetHisto(n, self.scaleHistoName) #self.hPS = t.GetHisto(n,self.PShistoName) if self.pathToTrees != '' and self.motherfname != '': self.LoadTreeSumOfWeights(self.pathToTrees, self.motherfname) self.hsumpdf = t.GetNamedHisto( self.normPDFhistoName ) if self.normPDFhistoName != '' else self.GetSumPDFhistoFromSumWTree( ) self.hsumscale = t.GetNamedHisto( self.normScaleHitstoName ) if self.normScaleHitstoName != '' else self.GetSumScaleHistoFromSumWTree( ) self.SetNgenEvents(self.count) self.nPDFweights = self.hsumpdf.GetNbinsX() self.nScaleWeighs = self.hsumscale.GetNbinsX() print '>> Count : ', self.count print '>> SumOfWeights : ', self.sow
class CrossSection: ### Add background, signal and data numbers def AddBkg(self, name, val, normunc=0, systunc=0, statunc=0, samples=''): ''' Add a bkg process (must include yield, name, uncertainties...) ''' self.bkg.append( Process(name, Yield=val, NormUnc=normunc, SystUnc=systunc, StatUnc=statunc, samples=samples)) def SetSignal(self, name, val, statunc=0, samples=''): ''' Set the signal process (must include yield, name, uncertainties...) ''' self.signal = Process(name, Yield=val, StatUnc=statunc, samples=samples) def SetData(self, n): ''' Number of observed events ''' self.data = n self.dataunc = sqrt(n) ### Add uncertainties... experimental and modeling def AddExpUnc(self, name, val): ''' Add the uncertainty 'name' with value 'val' to the experimental uncertainties ''' self.effUnc[name] = val def AddModUnc(self, name, val=0., do=''): ''' Add the uncertainty 'name' with value 'val' to the modeling uncertainties (on acceptance) if sample names are given (up/down) the uncertainty is read from the histos in that samples ''' if isinstance(val, float): self.accUnc[name] = val else: nom = self.GetSignalYield() up = self.t.GetYield(val) do = self.t.GetYield(do) var = max(abs(up - nom), abs(do - nom)) / nom self.AddModUnc(name, var) ### Setting methods def SetTextFormat(self, textformat): ''' Set the format of the output tables (txt, tex) ''' self.textformat = textformat def SetChan(self, ch): ''' Set the channel ''' self.chan = ch def SetLevel(self, lev): ''' Set level ''' self.lev = lev def SetThXsec(self, t): ''' Set the theoretical cross section using to normalize signal events ''' self.thxsec = t def SetDoFiducial(self, val=True): ''' Boolean to activate printing the fiducial cross section ''' self.doFiducial = val def SetLumi(self, l): ''' Set the luminosity ''' self.lumi = l def SetLumiUnc(self, l): ''' Set relative lumi unc ''' self.lumiunc = l def SetFiduEvents(self, f): ''' Number of fiducual (unweighted) events ''' self.nfidu = f def SetGenEvents(self, g): ''' Number of generated events in the sample ''' self.ngen = g def SetBR(self, b): # Use relative unc ''' The branching ratio to what we consider signal ''' self.BR = b def SetOutPath(self, p): ''' Set the output path ''' self.outpath = p ### Get parameters... def GetThXsec(self): return self.thxsec def GetLumi(self): return self.lumi def GetLumiUnc(self): return self.lumiunc def GetFiduEvents(self, sys=''): return self.nfidu def GetGenEvents(self): return self.ngen def GetBR(self): return self.BR def GetLevel(self): return self.lev def GetChan(self): return self.chan def GetBkg(self, name): for b in self.bkg: if b.GetName() == name: return b print 'WARNING: not found background ' + name def GetBkgTotRelUnc(self, name): return self.GetBkg(name).GetTotRelUnc() def GetBkgTotAbsUnc(self, name): return self.GetBkgYield(name) * self.GetBkgTotRelUnc(name) def GetBkgYield(self, name, sys=''): pr = self.GetBkg(name) if sys == '': return pr.GetYield() elif IsUpSyst(sys): return pr.GetYield() * (1 + pr.GetTotRelUnc()) elif IsDownSyst(sys): return pr.GetYield() * (1 - pr.GetTotRelUnc()) else: return pr.GetYield() * (1 + pr.GetTotRelUnc()) def GetData(self): return self.data def GetDataUnc(self): return self.dataunc def GetSignal(self): return self.signal def GetSignalYield(self, sys='', d=''): y = self.signal.GetYield() if sys == '': return y u = self.GetUnc(sys) if IsDownSyst(d): return y * (1 - u) return y * (1 + u) def GetExpUnc(self, name=''): if name == '': return self.effUnc else: return self.effUnc[name] def GetModUnc(self, name=''): if name == '': return self.accUnc else: return self.accUnc[name] def GetUnc(self, name): if name in self.modUnc.keys(): return self.GetModUnc(name) elif name in self.effUnc.keys(): return self.GetEffUnc(name) else: print 'WARNING: not found uncertainty \'%d\'' % name return 0 def GetTotBkg(self, sys='', d=''): ''' Returns the total expected bkg ''' if sys != '' and sys in [x.GetName() for x in self.bkg]: y = self.GetTotBkg() var = self.GetBkgTotAbsUnc(sys) y = y - var if IsDownSyst(sys + d) else y + var else: y = sum([x.GetYield() for x in self.bkg]) return y def GetTotBkgStatUnc(self): ''' Returns the total stat unc on bkg ''' b = 0 for pr in self.bkg: b += pr.GetStatUnc() * pr.GetStatUnc() return sqrt(b) def GetTotBkgSystUnc(self): ''' Returns the total syst unc on bkg ''' b = 0 for pr in self.bkg: b += pr.GetSystAbsUnc() * pr.GetSystAbsUnc() return sqrt(b) def GetXsec(self, sys='', d=''): ''' Returns the measured cross section ''' data = self.GetData() bkg = self.GetTotBkg(sys, d) if sys in [x.GetName() for x in self.bkg ] else self.GetTotBkg() y = self.GetSignalYield(sys, d) thxsec = self.GetThXsec() return self.ComputeXsec(data, bkg, y) def GetFiduXsec(self): ''' Returns the fiducial cross section ''' # fidu = inclusive*(A) return self.ComputeXsec() * self.GetAcc() def GetAcc(self, sys=''): ''' Returns the measured acceptance ''' return self.GetFiduEvents(sys) / (self.GetGenEvents() * self.GetBR()) def GetAccUnc(self): ''' Return the syst unc on acceptance ''' err = 0 for a in self.accUnc.values(): err += a * a return sqrt(err) def GetEff(self, sys=''): ''' Returns the measured efficiency ''' y = self.GetSignalYield(sys) A = self.GetAcc() BR = self.GetBR() lum = self.GetLumi() xth = self.GetThXsec() return (y) / (A * lum * xth * BR) def GetEffUnc(self): ''' Return the syst unc on efficiency ''' err = 0 for a in self.effUnc.values(): err += a * a return sqrt(err) def GetXsecSystUnc(self): ''' Returns the xsec syst unc on cross section ''' effunc = self.GetEffUnc() accunc = self.GetAccUnc() bkgunc2 = 0 for b in [x.GetName() for x in self.bkg]: bkgunc2 += self.GetXsecBkgRelUnc(b) * self.GetXsecBkgRelUnc(b) return sqrt(effunc * effunc + accunc * accunc + bkgunc2) def GetXsecLumiUnc(self): ''' Returns the xsec lumi uncertainty on cross section ''' #return self.GetXsec()*(1/self.GetLumi() - 1/(self.GetLumi() * (1+self.GetLumiUnc()) )) r = self.GetLumiUnc() return (abs(r / (1 - r)) + abs(r / (1 + r))) / 2 def GetXsecStatUnc(self): ''' Returns the stat unc on cross section ''' xsec = self.ComputeXsec() varUp = self.ComputeXsec(self.GetData() + self.GetDataUnc(), self.GetTotBkg(), self.GetSignalYield()) varDo = self.ComputeXsec(self.GetData() - self.GetDataUnc(), self.GetTotBkg(), self.GetSignalYield()) return max([abs(xsec - varDo) / xsec, abs(xsec - varUp) / xsec]) def GetXsecBkgRelUnc(self, bkgname): ''' Returns the relative unc on the xsec due to the total unc on a bkg estimation ''' nom = self.ComputeXsec() varUp = self.ComputeXsec(self.GetData(), self.GetTotBkg(bkgname, 'Up'), self.GetSignalYield()) varDo = self.ComputeXsec(self.GetData(), self.GetTotBkg(bkgname, 'Down'), self.GetSignalYield()) return max([abs(nom - varUp) / nom, abs(nom - varDo) / nom]) ### Several printing methods! def PrintYields(self, name='yields', doStat=True, doSyst=True): t = OutText(self.outpath, name, "new", textformat=self.textformat) t.SetTexAlign("l c") nsem = 16 + 3 + 8 + (5 + 8 if doStat else 0) + (5 + 8 if doSyst else 0) t.SetSeparatorLength(nsem) t.line('%' + 'Yields for channel \'%s\' and level \'%s\'' % (self.GetChan(), self.GetLevel())) t.bar() for pr in self.bkg: name = t.fix(" %s" % pr.GetName(), 16, 'l', 0) y = t.fix("%1.2f" % pr.GetYield(), 8, 0) stat = t.fix("%1.2f" % pr.GetStatUnc(), 8, 0) syst = t.fix("%1.2f" % pr.GetSystAbsUnc(), 8, 0) t.line(name + t.vsep() + y + ((t.pm() + stat) if doStat else '') + ((t.pm() + syst) if doSyst else '')) t.sep() totbkg = t.fix("%1.2f" % self.GetTotBkg(), 8, 0) totbkgstat = t.fix("%1.2f" % self.GetTotBkgStatUnc(), 8, 0) totbkgsyst = t.fix("%1.2f" % self.GetTotBkgSystUnc(), 8, 0) t.line( t.fix(" Total bkg", 16, 'l', 0) + t.vsep() + totbkg + ((t.pm() + totbkgstat) if doStat else '') + ((t.pm() + totbkgsyst) if doSyst else '')) t.sep() y = self.GetSignalYield() signal = t.fix(" %s" % (self.GetSignal().GetName()), 16, 'l', 0) ysig = t.fix("%1.2f" % y, 8, 0) sigunc = t.fix("%1.2f" % (self.GetXsecSystUnc() * y), 8, 0) sigsta = t.fix("%1.2f" % self.GetSignal().GetStatUnc(), 8, 0) t.line(signal + t.vsep() + ysig + ((t.pm() + sigsta) if doStat else '') + ((t.pm() + sigunc) if doSyst else '')) t.sep() t.line( t.fix(" Data", 16, 'l', 0) + t.vsep() + t.fix("%i" % self.GetData(), 8, 0)) t.bar() t.write() def PrintXsec(self, name='xsec'): t = OutText(self.outpath, name, "new", textformat=self.textformat) t.SetTexAlign("l c") t.SetSeparatorLength(26 + 3 + 20 + 5) t.SetDefaultFixOption(False) t.line('%' + 'tt cross section for channel \'%s\' and level \'%s\'' % (self.GetChan(), self.GetLevel())) acc = self.GetAcc() eff = self.GetEff() t.bar() t.line( t.fix(' Acceptance', 16, 'r') + t.vsep() + t.fix("%1.4f" % acc, 6) + t.pm() + t.fix("%1.2f" % (acc * self.GetAccUnc()), 8)) t.line( t.fix(' Efficiency', 16, 'r') + t.vsep() + t.fix("%1.4f" % eff, 6) + t.pm() + t.fix("%1.2f" % (eff * self.GetEffUnc()), 8)) t.sep() t.line( t.fix(' Branching ratio', 16, 'r') + t.vsep() + t.fix("%1.4f" % self.GetBR(), 6)) t.line( t.fix(' Gen events', 16, 'r') + t.vsep() + t.fix("%d" % self.GetGenEvents(), 9)) t.line( t.fix(' Fiducial events', 16, 'r') + t.vsep() + t.fix("%d" % self.GetFiduEvents(), 9)) if self.doFiducial: t.sep() xsec = self.GetFiduXsec() stat = self.GetXsecStatUnc() syst = self.GetEffUnc() lumi = self.GetXsecLumiUnc() #t.line(t.fix(' Fiducial cross section', 26, 'r') + t.vsep() + t.fix("%1.2f"%xsec,6)) #t.line(t.fix(' +\- ', 26, 'r') + ' ' + t.fix('%1.2f (%1.2f'%(stat*xsec,stat*100) + ' %) (stat)',20, 'l')) #t.line(t.fix(' +\- ', 26, 'r') + ' ' + t.fix('%1.2f (%1.2f'%(syst*xsec,syst*100) + ' %) (syst)',20, 'l')) #t.line(t.fix(' +\- ', 26, 'r') + ' ' + t.fix('%1.2f (%1.2f'%(lumi*xsec,lumi*100) + ' %) (lumi)',20, 'l')) t.sep() xsec = self.GetXsec() stat = self.GetXsecStatUnc() syst = self.GetXsecSystUnc() lumi = self.GetXsecLumiUnc() t.line( t.fix(' Inclusive cross section', 26, 'r') + t.vsep() + t.fix("%1.2f" % xsec, 6)) t.line( t.fix(' $\pm$ ', 26, 'r') + ' ' + t.fix('%1.2f (%1.2f' % (stat * xsec, stat * 100) + ' \%) (stat)', 20, 'l') + t.vsep()) t.line( t.fix(' $\pm$ ', 26, 'r') + ' ' + t.fix('%1.2f (%1.2f' % (syst * xsec, syst * 100) + ' \%) (syst)', 20, 'l') + t.vsep()) t.line( t.fix(' $\pm$ ', 26, 'r') + ' ' + t.fix('%1.2f (%1.2f' % (lumi * xsec, lumi * 100) + ' \%) (lumi)', 20, 'l') + t.vsep()) t.bar() t.write() def AddToTxt(self, name='xsec', lab='e#mu'): t = OutText(self.outpath, name, "new", textformat=self.textformat) text = t.GetTextFromOutFile(form='txt') xsec = self.GetXsec() stat = self.GetXsecStatUnc() * xsec syst = self.GetXsecSystUnc() * xsec lum = self.GetXsecLumiUnc() * xsec isthere = False for l in text.splitlines(): if l == '' or l.replace(' ', '') == '': continue if l.startswith(lab): isthere = True t.line('%s %1.2f %1.2f %1.2f %1.2f' % (lab, xsec, stat, syst, lum)) else: t.line(l) if not isthere: t.line('%s %1.2f %1.2f %1.2f %1.2f' % (lab, xsec, stat, syst, lum)) t.write() def PrintSystTable(self, name='uncertainties'): t = OutText(self.outpath, name, "new", textformat=self.textformat) t.SetTexAlign("l c") t.SetSeparatorLength(30) t.SetDefaultFixOption(False) t.line('%Uncertainties on tt inclusive cross section \n% ' + 'for channel \'%s\' and level \'%s\'' % (self.GetChan(), self.GetLevel())) exp = self.GetExpUnc() mod = self.GetModUnc() stat = self.GetXsecStatUnc() lum = self.GetXsecLumiUnc() syst = self.GetXsecSystUnc() xsec = self.GetXsec() t.bar() t.line(t.fix(' Source', 18, 'l') + t.vsep() + fix("value (\%)", 6)) t.sep() for b in [x.GetName() for x in self.bkg]: t.line( fix(' ' + b, 18, 'r') + t.vsep() + fix('%1.2f' % (self.GetXsecBkgRelUnc(b) * 100), 6)) t.sep() for e in exp.keys(): t.line( fix(' ' + e, 18, 'l') + t.vsep() + fix('%1.2f' % (exp[e] * 100), 6)) t.sep() for e in mod.keys(): t.line( fix(' ' + e, 18, 'l') + t.vsep() + fix('%1.2f' % (mod[e] * 100), 6)) t.sep() t.line( fix(' Total systematic', 18, 'l') + t.vsep() + fix('%1.2f' % (syst * 100), 6)) t.sep() t.line( fix(' Statistics', 18, 'l') + t.vsep() + fix('%1.2f' % (stat * 100), 6)) t.sep() t.line( fix(' Luminosity', 18, 'l') + t.vsep() + fix('%1.2f' % (lum * 100), 6)) t.bar() t.write() ### Other def ComputeXsec(self, data='', bkg='', y=''): ''' Computes the xsec from data, bkg and expected yield ''' if data == '': data = self.data if bkg == '': bkg = self.GetTotBkg() if y == '': y = self.GetSignalYield() return (data - bkg) / y * self.GetThXsec() def SetPathToTrees(self, ptt): self.pathToTrees = ptt def SetMotherName(self, mn): self.motherfname = mn def GetNGenEvents(self): self.treesow = TChain('Runs', 'Runs') files = GetFiles(self.pathToTrees, self.motherfname) for f in files: self.treesow.Add(f) def ReadHistos(self, path, chan='ElMu', level='2jets', lumi=Lumi, lumiunc=0.04, bkg=[], signal=[], data='', expUnc=[], modUnc=[], histoPrefix=''): ''' Set the xsec from histos ''' if isinstance(expUnc, str): expUnc = expUnc.replace(' ', '').split(',') if isinstance(modUnc, str): modUnc = modUnc.replace(' ', '').split(',') self.SetChan(chan) self.SetLevel(level) self.t = TopHistoReader(path) self.t.SetHistoNamePrefix(histoPrefix) self.t.SetLumi(lumi) self.t.SetChan(chan) self.t.SetLevel(level) self.ss = SampleSums(self.pathToTrees, self.motherfname, 'Runs') signalName = signal[0] signalSample = signal[1] # GetFiduEvents hfiduname = 'FiduEvents' #_%s'%chan fiduEvents = self.t.GetNamedHisto( hfiduname, signalSample).GetBinContent(invlevel[level]) nGenEvents = self.ss.GetCount( 'Count') #self.GetNGenEvents(signalSample) self.SetLumiUnc(lumiunc) self.SetFiduEvents(fiduEvents) self.SetGenEvents(nGenEvents) for l in bkg: if len(l) == 3: name, pr, unc = l expunc = expUnc elif len(l) == 4: name, pr, unc, expunc = l self.AddBkg(name, self.t.GetYield(pr), unc, self.t.GetUnc(pr, chan, level, expUnc), self.t.GetYieldStatUnc(pr)) self.SetSignal(signalName, self.t.GetYield(signalSample), self.t.GetYieldStatUnc(signalSample)) self.t.SetIsData(True) self.SetData(self.t.GetYield(data)) self.t.SetIsData(False) for e in expUnc: self.AddExpUnc(e, self.t.GetUnc(signal[1], chan, level, e)) # Modeling uncertainties if 'pdf' in modUnc or 'PDF' in modUnc or 'Scale' in modUnc or 'ME' in modUnc or 'scale' in modUnc: pathToTrees = self.pathToTrees #'/pool/ciencias/userstorage/juanr/nanoAODv4/5TeV/5TeV_5sept/' motherfname = self.motherfname #'TT_TuneCP5_PSweights_5p02TeV' w = WeightReader(path, '', chan, level, sampleName='TT', pathToTrees=pathToTrees, motherfname=motherfname, PDFname='PDFweights', ScaleName='ScaleWeights', lumi=Lumi, histoprefix=histoPrefix) #w.SetSampleName(signalName) if 'pdf' in modUnc or 'PDF' in modUnc: self.AddModUnc('PDF', w.GetPDFandAlphaSunc()) if 'scale' in modUnc or 'ME' in modUnc: self.AddModUnc('Scale ME', w.GetMaxRelUncScale()) if 'ISR' in modUnc or 'isr' in modUnc: self.AddModUnc('ISR', self.t.GetUnc(signalSample, chan, level, 'ISR')) if 'FSR' in modUnc or 'fsr' in modUnc: self.AddModUnc('FSR', self.t.GetUnc(signalSample, chan, level, 'FSR')) def __init__(self, outpath='./temp/', lev='', chan='', genEvents=1, fiduEvents=1, textformat="txt"): self.SetTextFormat(textformat) self.SetThXsec(68.9) self.SetLumi(Lumi) self.SetLumiUnc(0.035) # Relative self.SetChan(chan) self.SetLevel(lev) self.SetGenEvents(genEvents) self.SetFiduEvents(fiduEvents) self.SetBR((0.108 * 3) * (0.108 * 3)) # By default, tt dilepton self.bkg = [] # List of 'Process' self.data = 0 # This is just an integer self.signal = '' # Process self.accUnc = {} # 'Name' : value self.effUnc = {} # 'Name' : value self.SetOutPath(outpath) self.doFiducial = True self.SetMotherName("TT_TuneCP5_5p02TeV") self.SetPathToTrees("")