Esempio n. 1
0
 def SumExpSyst(self, syst=''):
     if syst == '': syst = self.GetExpSyst()
     if self.verbose >= 2: print 'Including systematics: ', syst
     if ',' in syst:
         self.SumExpSyst(syst.replace(' ', '').split(','))
         return
     if isinstance(syst, list):
         for s in syst:
             self.SumExpSyst(s)
         return
     self.SetSyst(syst)
     hnom = self.GetAllBkg()
     hvar = self.GetAllBkg(syst)
     nbins = hnom.GetNbinsX()
     if not hasattr(self, 'sysup'):
         self.sysup = [0] * nbins
         self.sysdo = [0] * nbins
     d = [
         hvar.GetBinContent(i) - hnom.GetBinContent(i)
         for i in range(1, nbins + 1)
     ]
     if average(d) >= 0:
         self.sysup = [sqrt(a * a + b * b) for a, b in zip(self.sysup, d)]
     else:
         self.sysdo = [sqrt(a * a + b * b) for a, b in zip(self.sysdo, d)]
def GetPDFuncHisto(nom, pdfvars, alphasvar=[], prName='tt', year=2018):
    # Using PDF4LHC15_nlo_nf4_30_pdfas, 1+30+2 weights, see Table 6 in
    # https://arxiv.org/pdf/1510.03865.pdf
    # Eq [20] for PDF unc:  0.01 (0.45 %)
    # Eq [27] for alpha_S:  0.00 (0.15 %)
    nom.SetName(prName)
    nbins = nom.GetNbinsX() + 1
    up = nom.Clone(prName + '_PDFUp')
    do = nom.Clone(prName + '_PDFDown')
    unc = [0] * nbins
    alphaunc = [0] * nbins
    for var in pdfvars:
        for i in range(0, nbins):
            n = nom.GetBinContent(i)
            v = var.GetBinContent(i)
            unc[i] += (n - v) * (n - v)
    unc = [sqrt((x if year != 2016 else x / 100)) for x in unc]

    if len(alphasvar) == 2:
        for i in range(0, nbins):
            vu = alphasvar[0].GetBinContent(i)
            vd = alphasvar[1].GetBinContent(i)
            alphaunc[i] = (vu - vd) / 2
        unc = [sqrt(x * x + y * y) for x, y in zip(unc, alphaunc)]

    for i in range(0, nbins):
        n = nom.GetBinContent(i)
        up.SetBinContent(i, n + unc[i])
        do.SetBinContent(i, n - unc[i])
    return [nom, up, do]
Esempio n. 3
0
 def AddSystFromHistos(self):
   if not hasattr(self, 'sysup'): self.ResetSyst()
   for pr in self.systSamples:
     name = pr.GetName()
     hvar = pr.histo()
     hnom = self.GetProcess(name).histo()
     nbins = hnom.GetNbinsX()
     d = [hvar.GetBinContent(i) - hnom.GetBinContent(i) for i in range(1, nbins+1)]
     if average(d) > 0: self.sysup = [sqrt(a*a+b*b) for a,b in zip(self.sysup, d)]
     else:              self.sysdo = [sqrt(a*a+b*b) for a,b in zip(self.sysdo, d)]
Esempio n. 4
0
 def AddStatUnc(self):
   if self.verbose >= 2: print 'Setting MC stat uncertainties...'
   if self.IncludedStatUnc: return
   self.IncludedStatUnc = True
   hnom = self.GetAllBkg()
   nbins = hnom.GetNbinsX()
   if not hasattr(self, 'sysup'): self.ResetSyst()
   du = [hnom.GetBinError(i) for i in range(1, nbins+1)]
   dd = [-hnom.GetBinError(i) for i in range(1, nbins+1)]
   self.sysup = [sqrt(a*a+b*b) for a,b in zip(self.sysup, du)]
   self.sysdo = [sqrt(a*a+b*b) for a,b in zip(self.sysdo, dd)]
Esempio n. 5
0
    def GetPrefireProbability(self, Map, eta, pt, maxpt):
        bin = Map.FindBin(eta, min(pt, maxpt - 0.01))
        pref_prob = Map.GetBinContent(bin)

        stat = Map.GetBinError(bin)  # bin statistical uncertainty
        syst = 0.2 * pref_prob  # 20% of prefire rate

        if self.variation == 1:
            pref_prob = min(pref_prob + sqrt(stat * stat + syst * syst), 1.0)
        if self.variation == -1:
            pref_prob = max(pref_prob - sqrt(stat * stat + syst * syst), 0.0)
        return pref_prob
Esempio n. 6
0
 def GetPDFunc(self):
   ''' 
     Eq [20] in:  https://arxiv.org/pdf/1510.03865.pdf
     Weights 2, to 31, using 1 as nominal
   '''
   delta = sum([self.GetRelUncPDF(i)*self.GetRelUncPDF(i) for i in range(2,32)])
   return sqrt(delta)
Esempio n. 7
0
 def GetSum2Unc(self, lsyst='', includeStat=True):
     ''' From a list of uncertainties, get a list of per-bin unc w.r.t. nominal histo 
     lsyst is a list of uncertainty names, not labels
 '''
     if lsyst == '': lsyst = self.systname[:]
     elif isinstance(lsyst, str) and ',' in lsyst:
         lsyst = lsyst.replace(' ', '').split(',')
     elif not isinstance(lsyst, list):
         lsyst = [syst]
     if includeStat and not 'stat' in lsyst:
         lsyst.append('stat')  #sum2.append(self.GetStatUnc())
     unc = []
     systExist = lambda x: x in self.systlabels
     for s in lsyst:
         listOfGoodSyst = filter(systExist, self.GetListOfCandNames(s))
         if s == 'stat':
             listOfHistos = [self.GetStatHisto()]
         elif len(listOfGoodSyst) == 0:
             print 'WARNING: no systematic found for label %s!' % s
             continue
         else:
             listOfHistos = [self.sumdic[s] for s in listOfGoodSyst]
         unc.append(self.GetDifUnc(self.sumdic[''], listOfHistos))
     sum2 = []
     nlen = len(unc[0])
     for i in range(nlen):
         v = 0
         for iunc in unc:
             v += iunc[i] * iunc[i]
         v = sqrt(v)
         sum2.append(v)
     return sum2
Esempio n. 8
0
 def GetSFfromTGraph(self, name, var):
     ''' Reads a TGraphAsymmetricErrors and returs value '''
     if ',' in name:
         return self.GetSFfromTGraph(
             [x.replace(' ', '') for x in name.split(',')], var)
     if isinstance(name, list):
         s = 1
         e = 0
         for n in name:
             sf, err = self.GetSFfromTGraph(n, var)
             s *= sf
             e += err * err
         return s, sqrt(e)
     g = self.inputs[name]
     n = g.GetN()
     x = array('f', g.GetX())
     y = array('f', g.GetY())
     # Below minimum
     if var < x[0] - g.GetErrorXlow(0):
         return [y[0], (g.GetErrorYlow(0) + g.GetErrorYhigh(0)) / 2]
     for i in range(n):
         xmin = x[i] - g.GetErrorXlow(i)
         xmax = x[i] + g.GetErrorXhigh(i)
         SF = y[i]
         SFerr = (g.GetErrorYlow(i) + g.GetErrorYhigh(i)) / 2
         #print '[%1.1f - %1.1f]  %1.2f +/- %1.2f'%(xmin, xmax, SF, SFerr)
         if var > xmin and var < xmax:
             return [SF, SFerr]
     # Above maximum
     return [y[-1], (g.GetErrorYlow(n - 1) + g.GetErrorYhigh(n - 1)) / 2]
Esempio n. 9
0
 def GetSFandErr(self, name, var1, var2=''):
     ''' Get SF and SF error from an input hitogram '''
     if ',' in name:
         return self.GetSFandErr(
             [x.replace(' ', '') for x in name.split(',')], var1, var2)
     if isinstance(name, list):
         s = 1
         e = 0
         for n in name:
             sf, err = self.GetSFandErr(n, var1, var2)
             s *= sf
             e += err * err
         return s, sqrt(e)
     nx = self.inputs[name].GetNbinsX()
     maxx = self.inputs[name].GetXaxis().GetBinUpEdge(nx)
     maxxm1 = self.inputs[name].GetXaxis().GetBinUpEdge(nx - 1)
     if var1 > maxx: var1 = (maxx + maxxm1) / 2
     if var2 != '':
         ny = self.inputs[name].GetNbinsY()
         maxy = self.inputs[name].GetYaxis().GetBinUpEdge(ny)
         maxym1 = self.inputs[name].GetYaxis().GetBinUpEdge(ny - 1)
         if var2 > maxy: var2 = (maxy + maxym1) / 2
     ibin = self.inputs[name].FindBin(
         var1) if var2 == '' else self.inputs[name].FindBin(var1, var2, 1)
     sf = self.inputs[name].GetBinContent(ibin)
     sferr = self.inputs[name].GetBinError(ibin)
     return sf, sferr
Esempio n. 10
0
 def GetNamedHisto(self, name, pr = '', rebin = -1):
   ''' Load an histo from process pr '''
   if pr    != '': self.SetProcess(pr)
   if rebin != -1: self.rebin = rebin
   pr = self.process
   if ',' in self.process: self.process = self.process.replace(' ', '').split(',')
   if isinstance(self.process, list):
     listOfProcess = self.process
     h = self.GetNamedHisto(name, listOfProcess[0], rebin)
     for p in listOfProcess[1:]: 
       while p[0]  == ' ': p = p[1:]
       while p[-1] == ' ': p = p[:-1]
       h.Add(self.GetNamedHisto(name, p, rebin))
     return h
   if ',' in name:
     listOfNames = name.replace(' ', '').split(',')
     h = self.GetNamedHisto(listOfNames[0], pr, rebin)
     for n in listOfNames[1:]:
       while n[0 ] == ' ': n = n[1:]
       while n[-1] == ' ': n = n[:-1]
       h.Add(self.GetNamedHisto(n, pr, rebin))
     return h

   filename = self.path + pr + '.root'
   if self.verbose: print ' >> Opening file: ' + filename
   f = TFile.Open(filename)
   if self.verbose: print ' >> Looking for histo: ' + name
   if not hasattr(f, name):
     if name == self.GetHistoName() and self.syst != '':
       hnosyst = self.var + '_' + self.chan + '_' + self.level
       if hasattr(f, hnosyst):
         print 'WARNING: no systematic %s for histo %s in process %s!! Returning nominal...'%(self.syst, hnosyst, pr)
         return 
     else:
       print 'ERROR: not found histogram ' + name + ' in file: ' + filename
       return
   h = f.Get(name)

   h.Rebin(self.rebin)
   nb = h.GetNbinsX()
   if self.doStackOverflow:
     h.SetBinContent(nb, h.GetBinContent(nb) + h.GetBinContent(n+2))
     h.SetBinContent(nb+2, 0)
   if not self.IsData: h.Scale(self.lumi)
   h.SetLineColor(1); h.SetFillStyle(0)
   h.SetLineWidth(2); h.SetStats(0)
   h.SetTitle('');
   h.GetXaxis().SetTitle('')
   h.GetYaxis().SetTitle('')
   h.SetDirectory(0)
   ### This is a patch, the bin-by-bin stat unc are (whatever the reason) not well calculated...
   ### This is a temporary solution
   nbins = h.GetNbinsX()
   integral = h.Integral() if h.Integral() > 0 else 0
   entries  = h.GetEntries()
   for i in range(1,nbins+1):
     bc = h.GetBinContent(i) if h.GetBinContent(i) > 0 else 0
     h.SetBinError(i, sqrt(bc*integral/entries) if entries != 0 else 0)
   return h
Esempio n. 11
0
 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)
Esempio n. 12
0
def GetAccWithUnc(sample, chan, level):
  h = thr.GetNamedHisto('FiduEvents_%s'%chan, processDic[('tt_'if sample !='tt' else '') +sample])
  nEv = h.GetBinContent(lev[level])
  genEv = GetGenEv(sample)
  nEvUnc = sqrt(nEv)
  acc = nEv/genEv
  unc = abs(acc - (nEv+nEvUnc)/genEv)
  return acc, unc
Esempio n. 13
0
 def GetTotRelUnc(self):
   norm = self.GetNormUnc() # relative
   syst = self.GetUnc() # relative
   stat = self.GetStatUnc() # Absolute
   y = self.GetYield()
   stat = stat/y if y != 0 else 0
   e = norm*norm + syst*syst + stat*stat
   return sqrt(e)
Esempio n. 14
0
 def DYyield(self, direc = 'in', isData = True, chan = '', level = ''):
   h = self.GetDYhisto(chan, level, isData)
   b0 = h.FindBin(self.minMZ); bN = h.FindBin(self.maxMZ)
   nbins = h.GetNbinsX()
   integral = h.Integral()
   y = 0; err = 0
   if direc == 'in' or direc == 'In' or direc == 'IN':
     y += h.Integral(b0, bN)
   else:
     y += h.Integral(0, b0-1)
     y += h.Integral(bN+1, nbins+1)
   if isData: err = sqrt(y)
   else:
     entries = h.GetEntries()
     err = sqrt((y*integral)/entries)
   if y<0:  # Avoid wierd numbers due to negative weights...
    y = 0; err = 0
   return y, err
Esempio n. 15
0
    def GetPDFunc(self):
        ''' 
     For 33 weights
     Eq [20] in:  https://arxiv.org/pdf/1510.03865.pdf
     Weights 2, to 31, using 1 as nominal
 
     For 100 weights:
   '''
        val = 0
        delta = sum([
            self.GetRelUncPDF(i) * self.GetRelUncPDF(i) for i in range(2, 32)
        ])
        if self.nPDFweights == 33:
            val = sqrt(delta)
        elif self.nPDFweights == 100:
            rms = sqrt(delta / 100)
            #val = sqrt(rms*rms + ((v110-v111)*0.75/2)*((v110-v111)*0.75/2));
            val = rms
        return val
Esempio n. 16
0
def GetGAandUnc(sname, chan):
  nom, uncnom = GetAccWithUnc('tt', chan, l)
  var, uncvar = GetAccWithUnc(sname, chan, l)
  syst = (var - nom)/nom
  nomup = nom+uncnom
  varup = var+uncvar
  systup1 = (var-nomup)/nomup
  systup2 = (varup-nom)/nom
  systunc = sqrt( (syst-systup1)*(syst-systup1) + (syst-systup2)*(syst-systup2)  )
  return [nom, uncnom, var, uncvar, syst, systunc]
 def GetKfactor(self, chan='', level=''):
     ''' Calculate the k factor k_ee, k_mumu '''
     chan, level = self.SetChanAndLevel(chan, level)
     rinElec, errElec = self.GetDataIn(elname, level)
     rinMuon, errMuon = self.GetDataIn(muname, level)
     k = (rinElec / rinMuon if rinMuon != 0 else 0) if chan == elname else (
         rinMuon / rinElec if rinElec != 0 else 0)
     k = sqrt(k)
     kerr = k * SumSquare([
         errElec / (2 * rinElec) if rinElec != 0 else 0, errMuon /
         (2 * rinMuon) if rinMuon != 0 else 0
     ])
     return k, kerr
Esempio n. 18
0
 def GetUnc(self, pr = '', ch = '', ilev = '', s = ''):
   ''' Return a systematic uncertainty (relative) ''' 
   nom = self.GetYield(pr, ch, ilev)
   if isinstance(s, list):
     err = 0
     for u in s:
       e = self.GetUnc(pr, ch, ilev, u)
       err += e*e
     return sqrt(err)
   else:
     if not s.endswith('Up') and not s.endswith('Down'):
       varUp = self.GetYield(pr, ch, ilev, s+'Up')
       varDo = self.GetYield(pr, ch, ilev, s+'Down')
     return max(abs(nom-varUp)/nom if nom!=0 else 0, abs(nom-varDo)/nom if nom != 0 else 0)
Esempio n. 19
0
 def GetScaleFactor(self, chan = '', level = '', mode = ''):
   ''' Returns the data/MC ratio for the DY estimate '''
   chan, level = self.SetChanAndLevel(chan, level)
   if chan == 'ElMu': self.SetMode('ElMu')
   if mode != '': self.SetMode(mode)
   SF = 1; err = 0
   if chan == 'ElEl' or chan == 'MuMu':
     dd, dde = self.GetDYDD(chan)
     mo, moe = self.GetMCout(chan)
     SF = dd/mo if mo != 0 else 0
     err = SF*SumSquare([dde/dd if dd != 0 else 0, moe/mo if mo != 0 else 0])
   elif chan == 'ElMu':
     e, er = self.GetScaleFactor('ElEl')
     m, mr = self.GetScaleFactor('MuMu')
     SF = sqrt(e*m)
     err = SF*SumSquare([er/e, mr/m])
   return SF,err
Esempio n. 20
0
 def GetUnc(self, name = ''):
   if name == '':
     if self.SystUnc != -999: return self.SystUnc
     else:
       unc = 0
       y = self.GetYield()
       normUnc = self.GetNormUnc()
       for val in self.ModUnc.values(): unc += val*val
       for val in self.ExpUnc.values(): unc += val*val
       val += y*y*normUnc*normUnc
       return sqrt(unc)
   else:
     for key in self.ModUnc.keys(): 
       if key == name: return self.ModUnc[key]
     for key in self.ExpUnc.keys():
       if key == name: return self.ExpUnc[key]
     print 'WARNING: not found systematic uncertainty \'%d\'... returning 0'%name
     return 0
Esempio n. 21
0
 def GetXsecSystUnc(self):
     ''' Returns the xsec syst unc on cross section '''
     effunc = self.GetEffUnc()
     accunc = self.GetAccUnc()
     return sqrt(effunc * effunc + accunc * accunc)
Esempio n. 22
0
 def GetEffUnc(self):
     ''' Return the syst unc on efficiency '''
     err = 0
     for a in self.effUnc.values():
         err += a * a
     return sqrt(err)
Esempio n. 23
0
 def GetAccUnc(self):
     ''' Return the syst unc on acceptance '''
     err = 0
     for a in self.accUnc.values():
         err += a * a
     return sqrt(err)
Esempio n. 24
0
 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)
Esempio n. 25
0
  def DrawStack(self, histo = '', xtit = '', ytit = '', rebin = 1):
    ''' Draws a stack plot '''
    # Set the canvas and pads
    self.t.SetRebin(rebin)
    if histo != '': self.SetHisto(histo)
    if xtit  != '': self.axisXtit = xtit
    if ytit  != '': self.axisYtit = ytit

    c = TCanvas('c', 'c', 10, 10, 800, 600)
    c.Divide(1,2)
    plot  = c.GetPad(1)
    ratio = c.GetPad(2)
    plot.SetPad( self.hpadx0, self.hpady0, self.hpadx1, self.hpady1)
    plot.SetMargin(self.hpadMleft, self.hpadMright, self.hpadMbottom, self.hpadMtop)
    ratio.SetPad(self.rpadx0, self.rpady0, self.rpadx1, self.rpady1)
    ratio.SetMargin(self.rpadMleft, self.rpadMright, self.rpadMbottom, self.rpadMtop)

    # Draw the text
    texcms = self.DrawTextCMS()
    texmod = self.DrawTextCMSmode()
    texlum = self.DrawTextLumi()
    #self.DrawTextChan()
    texcms.Draw()
    texmod.Draw()
    texlum.Draw()

    # Stack processes and draw stack and data
    plot.cd()
    hStack = THStack('stack', '')
    for pr in self.pr: hStack.Add(pr.histo())
    hStack.Draw('hist')

    datamax = -999
    if hasattr(self, 'data'):
      data = self.data.histo()
      data.Draw(self.data.GetDrawStyle())
      datamax = data.GetMaximum()
    
    bkg = hStack.GetStack().Last().Clone('AllBkg')

    dmax = max(datamax, bkg.GetMaximum())
    if isinstance(self.PlotMaximum, float): hStack.SetMaximum(self.PlotMaximum)
    else: hStack.SetMaximum(dmax*self.PlotMaxScale)
    if isinstance(self.PlotMinimum, float): hStack.SetMinimum(self.PlotMinimum)

    hRatio = data.Clone() if hasattr(self, 'data') else bkg.Clone()
    nbins = hRatio.GetNbinsX()
    for i in range(nbins+1):
      b = bkg. GetBinContent(i)
      d = data.GetBinContent(i) if hasattr(self, 'data') else b
      if b == 0: b = 1
      e = 0 if d == 0 else d/b*(sqrt(d)/d)
      hRatio.SetBinContent(i, d/b)
      hRatio.SetBinError(i, e)
  
    # Set titles...
    TGaxis.SetMaxDigits(3)
    hStack.GetYaxis().SetTitle(self.axisYtit)
    hStack.GetYaxis().SetTitleSize(self.axisYsize)
    hStack.GetYaxis().SetTitleOffset(self.axisYoffset)
    hStack.GetYaxis().SetLabelSize(self.axisYlabSize)
    hStack.GetYaxis().SetNdivisions(self.axisYnDiv)
    hStack.GetYaxis().CenterTitle()

    hStack.GetXaxis().SetTitle("")
    hStack.GetXaxis().SetLabelSize(0)

    hRatio.GetXaxis().SetTitle(self.axisXtit)
    hRatio.GetXaxis().SetTitleSize(self.axisXsize)
    hRatio.GetXaxis().SetTitleOffset(self.axisXoffset)
    hRatio.GetXaxis().SetLabelSize(self.axisXlabSize)
    hRatio.GetXaxis().SetNdivisions(self.axisXnDiv)

    hRatio.GetYaxis().SetTitle(self.axisRtit)
    hRatio.GetYaxis().SetTitleSize(self.axisRsize)
    hRatio.GetYaxis().SetTitleOffset(self.axisRoffset)
    hRatio.GetYaxis().SetLabelSize(self.axisRlabSize)
    hRatio.GetYaxis().SetNdivisions(self.axisRnDiv)
    hRatio.GetYaxis().CenterTitle()

    if len(self.binLabels) > 0: 
      for i in range(len(self.binLabels)):
        hRatio.GetXaxis().SetBinLabel(i+1,self.binLabels[i])

    # Set syst histo
    self.AddStatUnc()
    self.SumExpSyst()
    bkg.SetFillStyle(3444); 
    bkg.SetFillColor(kGray+2);
    nbins = bkg.GetNbinsX()
    for i in range(1, self.nbins+1):
      err = (abs(self.sysup[i-1]) + abs(self.sysdo[i-1]))/2
      #if not err == err: err = 0
      bkg.SetBinError(i, err)
    bkg.Draw("same,e2")
    
    # Legend
    legend = self.SetLegend()
    for pr in self.pr: legend.AddEntry(pr.histo(), pr.GetName(), 'f')
    if hasattr(self, 'data'): legend.AddEntry(self.data.histo(), 'Data', 'pe')
    legend.Draw()

    # Ratio
    ratio.cd()
    hRatio.SetMaximum(self.PlotRatioMax)
    hRatio.SetMinimum(self.PlotRatioMin)
    if hasattr(self, 'data'): hRatio.Draw(self.data.GetDrawStyle())
    else:                     hRatio.Draw('lsame')
    hRatioErr = bkg.Clone("hratioerr")
    for i in range(1, self.nbins+2):
      hRatioErr.SetBinContent(i, 1)   
      val = bkg.GetBinContent(i)
      err = bkg.GetBinError(i)
      hRatioErr.SetBinError(i, err/val if val != 0 else 0)
    hRatioErr.Draw("same,e2")

    # Save
    if not os.path.isdir(self.GetOutPath()): os.makedirs(self.GetOutPath())
    c.Print(self.GetOutName()+'.png', 'png')
    c.Print(self.GetOutName()+'.pdf', 'pdf')
Esempio n. 26
0
 def GetPDFandAlphaSunc(self):
   ''' Quadratic sum of both '''
   pdfunc = self.GetPDFunc()
   alphas = self.GetAlphaSunc()
   return sqrt(pdfunc*pdfunc + alphas*alphas)
Esempio n. 27
0
 def GetSystAbsUnc(self):
   y = self.GetYield()
   norm = self.GetNormUnc()*y # relative
   syst = self.GetUnc()*y # relative
   e = norm*norm + syst*syst
   return sqrt(e)
Esempio n. 28
0
 def SetData(self, n):
     ''' Number of observed events '''
     self.data = n
     self.dataunc = sqrt(n)
Esempio n. 29
0
    def insideLoop(self, t):
        # This is called for each event and has the meaty part of the analysis
        self.resetObjects()
        FidR = self.selFRLep
        TotR = self.selTRLep
        ### Lepton selection
        ###########################################
        if not self.isData: nGenLep = t.nGenDressedLepton

        ##### Fiducial Region Leptons
        if self.doFiducialAndTotalRegion:
            Fid1 = True
            for i in range(t.nGenPart):
                Fid0 = True
                p = TLorentzVector()
                p.SetPtEtaPhiM(t.GenPart_pt[i], t.GenPart_eta[i],
                               t.GenPart_phi[i], t.GenPart_mass[i])
                if not (abs(t.GenPart_pdgId[i]) == 11
                        or abs(t.GenPart_pdgId[i]) == 13):
                    Fid0 = False
                pdg = abs(t.GenPart_pdgId[i])
                charge = 1
                if t.GenPart_pdgId[i] > 0: charge = -1
                if t.GenPart_status[i] != 1: Fid0 = False
                if p.Pt() < 5 or abs(p.Eta()) > 2.5: Fid0 = False
                if Fid0 == True:
                    self.selFRLeptons.append(lepton(p, charge,
                                                    pdg))  #######XXX

            nFRLep = len(self.selFRLeptons)

            FRleps = self.selFRLeptons
            FRpts = [lep.Pt() for lep in FRleps]
            FRpdgs = [lep.GetPDGid() for lep in FRleps]
            # Order leptons by pT
            self.selFRLeptons = [lep for _, lep in sorted(zip(FRpts, FRleps))]
            if nFRLep < 3: Fid1 = False
            if Fid1 == True:
                l0 = self.selFRLeptons[nFRLep - 1]
                l1 = self.selFRLeptons[nFRLep - 2]
                l2 = self.selFRLeptons[nFRLep - 3]
                totId = l0.GetPDGid() + l1.GetPDGid() + l2.GetPDGid()
                ich = -1
                if totId == 33: ich = ch.eee
                elif totId == 35: ich = ch.mee
                elif totId == 37: ich = ch.emm
                elif totId == 39: ich = ch.mmm
                mz = [
                    CheckZpair(l0, l1),
                    CheckZpair(l0, l2),
                    CheckZpair(l1, l2)
                ]
                mzdif = [abs(x - 91) for x in mz]
                minmzdif = min(mzdif)
                if minmzdif == mzdif[0]:
                    lZ1 = dc(l0)
                    lZ2 = dc(l1)
                    lW = dc(l2)
                elif minmzdif == mzdif[1]:
                    lZ1 = dc(l0)
                    lZ2 = dc(l2)
                    lW = dc(l1)
                elif minmzdif == mzdif[2]:
                    lZ1 = dc(l1)
                    lZ2 = dc(l2)
                    lW = dc(l0)
                zFRleps = [lZ1, lZ2]
                if abs(InvMass(zFRleps) - 91.) > 30.: Fid1 = False
                FidR = FidR + 1
                if Fid1 == True:
                    self.GetHisto('YieldsFid', ich).Fill(FidR, 1)

            #### Total Region Leptons
            Tot1 = True
            for i in range(t.nGenPart):
                Tot0 = True
                p = TLorentzVector()
                p.SetPtEtaPhiM(t.GenPart_pt[i], t.GenPart_eta[i],
                               t.GenPart_phi[i], t.GenPart_mass[i])
                if not (abs(t.GenPart_pdgId[i]) == 11
                        or abs(t.GenPart_pdgId[i]) == 13):
                    Tot0 = False
                pdg = abs(t.GenPart_pdgId[i])
                charge = 1
                if t.GenPart_pdgId[i] > 0: charge = -1
                if t.GenPart_status[i] != 1: Tot0 = False
                if Tot0 == True:
                    self.selTRLeptons.append(lepton(p, charge,
                                                    pdg))  #######XXX

            nTRLep = len(self.selTRLeptons)

            TRleps = self.selTRLeptons
            TRpts = [lep.Pt() for lep in TRleps]
            TRpdgs = [lep.GetPDGid() for lep in TRleps]
            # Order leptons by pT
            self.selTRLeptons = [lep for _, lep in sorted(zip(TRpts, TRleps))]
            if nTRLep < 3: Tot1 = False

            if Tot1 == True:
                l0 = self.selTRLeptons[nTRLep - 1]
                l1 = self.selTRLeptons[nTRLep - 2]
                l2 = self.selTRLeptons[nTRLep - 3]
                totId = l0.GetPDGid() + l1.GetPDGid() + l2.GetPDGid()
                ich = -1
                if totId == 33: ich = ch.eee
                elif totId == 35: ich = ch.mee
                elif totId == 37: ich = ch.emm
                elif totId == 39: ich = ch.mmm
                mz = [
                    CheckZpair(l0, l1),
                    CheckZpair(l0, l2),
                    CheckZpair(l1, l2)
                ]
                mzdif = [abs(x - 91) for x in mz]
                minmzdif = min(mzdif)
                if minmzdif == mzdif[0]:
                    lZ1 = dc(l0)
                    lZ2 = dc(l1)
                    lW = dc(l2)
                elif minmzdif == mzdif[1]:
                    lZ1 = dc(l0)
                    lZ2 = dc(l2)
                    lW = dc(l1)
                elif minmzdif == mzdif[2]:
                    lZ1 = dc(l1)
                    lZ2 = dc(l2)
                    lW = dc(l0)
                zTRleps = [lZ1, lZ2]
                if abs(InvMass(zTRleps) - 91.) > 30.: Tot1 = False
                TotR = TotR + 1
                if Tot1 == True:
                    self.GetHisto('YieldsTot', ich).Fill(TotR, 1)

        #print t.event
        ##### Muons
        for i in range(t.nMuon):
            p = TLorentzVector()
            p.SetPtEtaPhiM(t.Muon_pt[i], t.Muon_eta[i], t.Muon_phi[i],
                           t.Muon_mass[i])
            charge = t.Muon_charge[i]
            # Loose (analysis) ID == MediumPrompt POG ID
            if not t.Muon_mediumPromptId[i]: continue
            # Loose ISO
            #if not t.Muon_miniIsoId[i] >= 2: continue
            if not (t.Muon_miniPFRelIso_all[i] < 0.4): continue
            if not t.Muon_sip3d[i] < 5: continue
            # Loose IP
            dxy = abs(t.Muon_dxy[i])
            dz = abs(t.Muon_dz[i])
            if dxy > 0.05 or dz > 0.1: continue
            # Acceptance cuts; Momentum cut to respect trigger requirements
            if abs(p.Eta()) > 2.4: continue
            # Now the tight (analysis) ID (leptonMVA + tighter miniIso)
            passTightID = True
            passbtag = True
            if t.Muon_mvaTTH[i] < 0.55: passTightID = False
            #if t.Muon_miniIsoId[i] < 4: passTightID = False
            if (t.Muon_miniPFRelIso_all[i] > 0.325): passTightID = False
            if t.Muon_jetIdx[i] >= 0:
                if t.Jet_btagDeepB[t.Muon_jetIdx[i]] > 0.1522: passbtag = False
            self.selLeptons.append(
                lepton(p, charge, 13,
                       t.Muon_genPartFlav[i] if not (self.isData) else "\0",
                       passTightID, passbtag))

        ##### Electrons
        for i in range(t.nElectron):
            p = TLorentzVector()
            p.SetPtEtaPhiM(t.Electron_pt[i], t.Electron_eta[i],
                           t.Electron_phi[i], t.Electron_mass[i])
            charge = t.Electron_charge[i]
            etaSC = abs(p.Eta())
            convVeto = t.Electron_convVeto[i]
            passTightID = True
            passbtag = True
            dxy = abs(t.Electron_dxy[i])
            dz = abs(t.Electron_dz[i])
            # Loose (analysis) ID is POG MVALoose WP `miniIso
            if dxy > 0.05 or dz > 0.1: continue
            # Acceptance cuts (tighter lepton pt cut due to trigger)
            if abs(p.Eta()) > 2.5: continue
            if ord(t.Electron_lostHits[i]) > 0: continue
            if not (t.Electron_mvaFall17V2Iso_WPL[i]): continue
            if not (t.Electron_miniPFRelIso_all[i] < 0.4): continue
            if not (t.Electron_convVeto[i]): continue

            # Tight (analysis) ID is leptonMVA + tighter miniIso
            if not (t.Electron_sip3d[i] < 8): passTightID = False
            if (t.Electron_mvaTTH[i] < 0.125): passTightID = False
            if (t.Electron_miniPFRelIso_all[i] > 0.085): passTightID = False
            if t.Electron_jetIdx[i] >= 0:
                if t.Jet_btagDeepB[t.Electron_jetIdx[i]] > 0.1522:
                    passbtag = False
            self.selLeptons.append(
                lepton(
                    p, charge, 11,
                    t.Electron_genPartFlav[i] if not (self.isData) else "\0",
                    passTightID, passbtag))

        leps = self.selLeptons
        pts = [lep.Pt() for lep in leps]
        pdgs = [lep.GetPDGid() for lep in leps]
        # Order leptons by pT
        self.selLeptons = [lep for _, lep in sorted(zip(pts, leps))]
        ### Set trilepton channel
        nLep = len(self.selLeptons)
        # >= 3 leptons for WZ, != 4 to decrease ZZ
        if nLep != 3: return False
        ### And look for OSSF and classify the channel
        l0 = self.selLeptons[0]
        l1 = self.selLeptons[1]
        l2 = self.selLeptons[2]
        totId = l0.GetPDGid() + l1.GetPDGid() + l2.GetPDGid()
        ich = -1
        if totId == 33:
            ich = ch.eee
            if not (pts[0] >= 15 and pts[1] >= 10 and pts[2] >= 8):
                return False
        elif totId == 35:
            ich = ch.mee
            if not (pts[0] >= 12 and pts[1] >= 10 and pts[2] >= 8):
                return False
        elif totId == 37:
            ich = ch.emm
            if not (pts[0] >= 12 and pts[1] >= 12 and pts[2] >= 8):
                return False
        elif totId == 39:
            ich = ch.mmm
            if not (pts[0] >= 12 and pts[1] >= 10 and pts[2] >= 10):
                return False
        #if totId != 33 and totId != 37: return
        # lW, lZ1, lZ2 assignation (same as 13 TeV)
        mz = [CheckZpair(l0, l1), CheckZpair(l0, l2), CheckZpair(l1, l2)]
        #if mz[0]<12 or mz[1]<12 or mz[2]<12: return False
        #if max(mz) == 0: return False # +++, ---
        mzdif = [abs(x - 91) for x in mz]
        minmzdif = min(mzdif)
        #if minmzdif == 0: return False # This made no sense here, we would be filtering exactly on peak Zs!
        if minmzdif == mzdif[0]:
            lZ1 = dc(l0)
            lZ2 = dc(l1)
            lW = dc(l2)
        elif minmzdif == mzdif[1]:
            lZ1 = dc(l0)
            lZ2 = dc(l2)
            lW = dc(l1)
        elif minmzdif == mzdif[2]:
            lZ1 = dc(l1)
            lZ2 = dc(l2)
            lW = dc(l0)

        zleps = [lZ1, lZ2]
        tleps = [lW, lZ1, lZ2]
        wleps = [lW, lZ1, lZ2]
        #If Wpt  > 20 this is not needed any more
        #if max([x.p.Pt() for x in tleps]) < 20: return False

        if CheckSign(tleps[0], tleps[2]) == 1:
            tleps = [lW, lZ2, lZ1]

        # On Z-peak
        if abs(InvMass(zleps) - 91.) > 30.: return False
        if not (InvMass(l0, l1) > 12 and InvMass(l0, l2) > 12
                and InvMass(l1, l2) > 12):
            return False
        ### Trigger
        ###########################################
        trigger = {
            ch.eee:
            t.HLT_HIEle20_WPLoose_Gsf or t.HLT_HIEle17_WPLoose_Gsf
            or t.HLT_HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ
            or t.HLT_HIEle15_Ele8_CaloIdL_TrackIdL_IsoVL,
            #ch.mee:t.HLT_HIL3Mu20 or t.HLT_HIEle20_WPLoose_Gsf or t.HLT_HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ,
            ch.mee:
            t.HLT_HIL3Mu20 or t.HLT_HIL3Mu12
            or t.HLT_HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ
            or t.HLT_HIEle15_Ele8_CaloIdL_TrackIdL_IsoVL
            or t.HLT_HIEle17_WPLoose_Gsf or t.HLT_HIEle20_WPLoose_Gsf,
            #ch.emm:t.HLT_HIL3Mu20 or t.HLT_HIEle20_WPLoose_Gsf or t.HLT_HIL3DoubleMu0 or t.HLT_HIL3DoubleMu10,
            ch.emm:
            t.HLT_HIL3Mu20 or t.HLT_HIL3Mu12 or t.HLT_HIEle17_WPLoose_Gsf
            or t.HLT_HIEle20_WPLoose_Gsf or t.HLT_HIL3DoubleMu10,
            #ch.mmm:t.HLT_HIL3Mu20 or t.HLT_HIL3DoubleMu0 or t.HLT_HIL3DoubleMu10,
            ch.mmm:
            t.HLT_HIL3Mu20 or t.HLT_HIL3Mu12 or t.HLT_HIL3DoubleMu10,
        }
        passTrig = trigger[ich]

        ### Remove overlap events in datasets
        # In tt @ 5.02 TeV,
        if self.isData:
            if self.sampleDataset == datasets.SingleElec:
                if ich == ch.eee: passTrig = trigger[ch.eee]
                elif ich == ch.mee: passTrig = trigger[ch.eee]
                elif ich == ch.emm:
                    passTrig = trigger[ch.eee] and not trigger[ch.mmm]
                else:
                    passTrig = False
            elif self.sampleDataset == datasets.SingleMuon:
                if ich == ch.mee:
                    passTrig = trigger[ch.mmm] and not trigger[ch.eee]
                elif ich == ch.emm:
                    passTrig = trigger[ch.mmm]
                elif ich == ch.mmm:
                    passTrig = trigger[ch.mmm]
                else:
                    passTrig = False

        # Lepton SF
        self.SFelec = 1
        self.SFmuon = 1
        self.SFelecErr = 0
        self.SFmuonErr = 0
        if not self.isData:
            for lep in self.selLeptons:
                if lep.IsMuon():
                    sf, err = self.GetSFandErr('MuonIsoSF, MuonIdSF',
                                               max(21, lep.Pt()),
                                               TMath.Abs(lep.Eta()))
                    self.SFmuon *= sf
                    self.SFmuonErr += err * err  # stat + syst from TnP
                    self.SFmuonErr += 0.005 * 0.005  # Iso phase space extrapolation
                else:
                    elecsf = 'ElecEB' if lep.Eta() < 1.479 else 'ElecEE'
                    recosf = 'RecoEB' if lep.Eta() < 1.479 else 'RecoEE'
                    ssf, serr = self.GetSFfromTGraph(elecsf, lep.Pt())
                    rsf, rerr = self.GetSFfromTGraph(recosf, lep.Pt())
                    sf = (1. / ssf) * rsf
                    if rerr > 0.05:
                        rerr = 0.01  # XXX TEMPORARY CORRECTION TO AVOID WRONG SF UNCERTAINTIES
                    if serr > 0.05:
                        serr = 0.01  # XXX TEMPORARY CORRECTION TO AVOID WRONG SF UNCERTAINTIES
                    self.SFelec *= sf
                    self.SFelecErr += serr * serr + rerr * rerr
            self.SFelecErr = sqrt(self.SFelecErr)
            self.SFmuonErr = sqrt(self.SFmuonErr)

        ### Jet selection
        ###########################################

        for i in range(t.nJet):
            p = TLorentzVector()
            jetpt = getattr(t, self.jetptvar)[i]
            p.SetPtEtaPhiM(jetpt, t.Jet_eta[i], t.Jet_phi[i], t.Jet_mass[i])
            csv = t.Jet_btagCSVV2[i]
            deepcsv = t.Jet_btagDeepB[i]
            deepflav = t.Jet_btagDeepFlavB[i]
            jid = t.Jet_jetId[i]
            flav = t.Jet_hadronFlavour[i] if not self.isData else -999999
            # Jet ID > 1, tight Id
            if not jid > 1: continue
            # |eta| < 2.5
            if abs(p.Eta()) > 2.5: continue
            j = jet(p, csv, flav, jid, deepcsv, deepflav)
            if csv >= 0.8484: j.SetBtag()  ### Misssing CSVv2 SFs !!!!
            if not j.IsClean(self.selLeptons, 0.4): continue
            if p.Pt() >= self.JetPtCut: self.selJets.append(j)
            if not self.isData and self.doSyst:
                if self.doJECunc:
                    pJESUp = TLorentzVector()
                    pJERUp = TLorentzVector()
                    pJESDo = TLorentzVector()
                    pJERDo = TLorentzVector()
                    pJESUp.SetPtEtaPhiM(t.Jet_pt_jesTotalUp[i], t.Jet_eta[i],
                                        t.Jet_phi[i], t.Jet_mass_jesTotalUp[i])
                    pJESDo.SetPtEtaPhiM(t.Jet_pt_jesTotalDown[i], t.Jet_eta[i],
                                        t.Jet_phi[i],
                                        t.Jet_mass_jesTotalDown[i])
                    pJERUp.SetPtEtaPhiM(t.Jet_pt_jerUp[i], t.Jet_eta[i],
                                        t.Jet_phi[i], t.Jet_mass_jerUp[i])
                    pJERDo.SetPtEtaPhiM(t.Jet_pt_jerDown[i], t.Jet_eta[i],
                                        t.Jet_phi[i], t.Jet_mass_jerDown[i])
                    jJESUp = jet(pJESUp, csv, flav, jid, deepcsv)
                    jJESDo = jet(pJESDo, csv, flav, jid, deepcsv)
                    jJERUp = jet(pJERUp, csv, flav, jid, deepcsv)
                    jJERDo = jet(pJERDo, csv, flav, jid, deepcsv)
                    if csv >= 0.8484:
                        jJESUp.SetBtag()
                        jJESDo.SetBtag()
                        jJERUp.SetBtag()
                        jJERDo.SetBtag()
                    if pJESUp.Pt() >= self.JetPtCut:
                        self.selJetsJESUp.append(jJESUp)
                    if pJESDo.Pt() >= self.JetPtCut:
                        self.selJetsJESDo.append(jJESDo)
                    if pJERUp.Pt() >= self.JetPtCut:
                        self.selJetsJERUp.append(jJERUp)
                    if pJERDo.Pt() >= self.JetPtCut:
                        self.selJetsJERDo.append(jJERDo)
        self.selJets = SortByPt(self.selJets)
        if not self.isData and self.doSyst:
            self.selJetsJESUp = SortByPt(self.selJetsJESUp)
            self.selJetsJESDo = SortByPt(self.selJetsJESDo)
            self.selJetsJERUp = SortByPt(self.selJetsJERUp)
            self.selJetsJERDo = SortByPt(self.selJetsJERDo)

        ##### MET
        #met = getattr(t, self.metptvar)
        #self.pmet.SetPtEtaPhiM(met, 0, t.MET_phi, 0)
        self.pmet.SetPtEtaPhiM(t.MET_pt, 0, t.MET_phi, 0)
        if not self.isData and self.doSyst:
            self.pmetJESUp.SetPtEtaPhiM(t.MET_pt_jesTotalUp, 0,
                                        t.MET_phi_jesTotalUp, 0)
            self.pmetJESDo.SetPtEtaPhiM(t.MET_pt_jesTotalDown, 0,
                                        t.MET_phi_jesTotalDown, 0)
            self.pmetJERUp.SetPtEtaPhiM(t.MET_pt_jerUp, 0, t.MET_phi_jerUp, 0)
            self.pmetJERDo.SetPtEtaPhiM(t.MET_pt_jerDown, 0, t.MET_phi_jerDown,
                                        0)

        nJets = len(self.selJets)
        nBtag = GetNBtags(self.selJets)

        wpt = lW.Pt()
        Z1pt = lZ1.Pt()
        Z2pt = lZ2.Pt()
        m3l = (lW.P() + lZ1.P() + lZ2.P()).M()

        if nJets > 1:
            htmiss = (lW.P() + lZ1.P() + lZ2.P() +
                      TLorentzVector(self.selJets[0].P()) +
                      TLorentzVector(self.selJets[1].P())).Pt()
        elif nJets > 0:
            htmiss = (lW.P() + lZ1.P() + lZ2.P() +
                      TLorentzVector(self.selJets[0].P())).Pt()
        else:
            htmiss = (lW.P() + lZ1.P() + lZ2.P()).Pt()

        ### Event weight and othe global variables
        ###########################################
        self.nvtx = t.PV_npvs

        self.PUSF = 1
        self.PUUpSF = 1
        self.PUDoSF = 1
        if not self.isData:
            self.PUSF = self.PUweight.GetWeight(t.Pileup_nPU)
            self.PUUpSF = self.PUweight.GetWeightUp(t.Pileup_nPU)
            self.PUDoSF = self.PUweight.GetWeightDown(t.Pileup_nPU)
        else:
            self.PUSF = 1
            self.PUUpSF = 1
            self.PUDoSF = 1

        self.prefWeight = 1
        self.prefWeightUp = 1
        self.prefWeightDo = 1
        if not self.isData:
            self.prefWeight = self.PrefCorr.GetWeight(t)
            self.prefWeightUp = self.PrefCorr.GetWeightUp(t)
            self.prefWeightDo = self.PrefCorr.GetWeightDown(t)

        ### Event selection
        ###########################################
        self.SetWeight(systematic.nom)
        weight = self.weight
        # Better require the trigger properly
        if not passTrig: return

        #print systlabel.keys()
        # And now fill all histograms for each variation
        for isyst in systlabel.keys():
            if not self.doSyst and isyst != systematic.nom: continue
            if self.isData and isyst != systematic.nom: continue
            leps, jets, pmet = self.SetVariables(isyst)
            nJets = len(jets)
            nBtag = GetNBtags(jets)
            wmt = MT(lW, pmet)
            if isyst != systematic.JESUp or isyst != systematic.JESDo or isyst != systematic.JERUp or isyst != systematic.JERDo:
                leps = tleps
            self.FillAll(ich, lev.lep, isyst, leps, jets, pmet)
            self.GetHisto('YieldsLep', ich, '',
                          isyst).Fill(lev.lep, self.weight)
            #self.OriginLeptons(pts, ich, lev.lep, isyst)
            if tleps[0].passTightID and tleps[1].passTightID and tleps[
                    2].passTightID and tleps[0].passbtag and tleps[
                        1].passbtag and tleps[2].passbtag:
                self.FillAll(ich, lev.met, isyst, leps, jets, pmet)
                #self.OriginLeptons(pts, ich, lev.met, isyst)
            if tleps[0].passTightID and tleps[1].passTightID and tleps[
                    0].passbtag and tleps[1].passbtag and wpt > 20:
                self.FillAll(ich, lev.wpt, isyst, leps, jets, pmet)
            if wpt > 20 and Z1pt > 10 and Z2pt > 10:
                self.FillAll(ich, lev.zpt, isyst, leps, jets, pmet)
            if tleps[0].passTightID and tleps[0].passbtag:
                self.FillAll(ich, lev.m3l, isyst, leps, jets, pmet)
            if tleps[0].passTightID and tleps[0].passbtag:
                self.FillAll(ich, lev.htmiss, isyst, leps, jets, pmet)
            if tleps[0].passTightID and tleps[1].passTightID and tleps[
                    0].passbtag and tleps[1].passbtag:
                self.FillAll(ich, lev.sr, isyst, leps, jets, pmet)
            #     if tleps[0].passTightID and wpt > 20 and htmiss > 15 and m3l > 100:
            #    self.FillAll(ich, lev.srtight, isyst, leps, jets, pmet)
            if tleps[0].passTightID and tleps[1].passTightID and tleps[
                    0].passbtag and tleps[1].passbtag and m3l > 100:
                self.FillAll(ich, lev.srtight, isyst, leps, jets, pmet)
            if tleps[0].passTightID and tleps[1].passTightID and tleps[
                    0].passbtag and tleps[
                        1].passbtag and m3l > 100 and wpt > 20:
                self.FillAll(ich, lev.tight, isyst, leps, jets, pmet)

        return True
Esempio n. 30
0
    def insideLoop(self, t):
        self.resetObjects()

        ### Lepton selection
        ###########################################
        if not self.isData: nGenLep = t.nGenDressedLepton
        if self.isTT and not self.doTTbarSemilep and nGenLep < 2: return
        if self.doTTbarSemilep and nGenLep >= 2: return
        if self.isTT:
            genLep = []
            for i in range(nGenLep):
                p = TLorentzVector()
                p.SetPtEtaPhiM(t.GenDressedLepton_pt[i],
                               t.GenDressedLepton_eta[i],
                               t.GenDressedLepton_phi[i],
                               t.GenDressedLepton_mass[i])
                pdgid = abs(t.GenDressedLepton_pdgId[i])
                if p.Pt() < 12 or abs(p.Eta()) > 2.4: continue
                genLep.append(lepton(p, 0, pdgid))
            pts = [lep.Pt() for lep in genLep]
            genLep = [lep for _, lep in sorted(zip(pts, genLep))]

            if len(genLep) >= 2:
                genChan = 0
                l0 = genLep[0]
                l1 = genLep[1]
                totId = l0.GetPDGid() + l1.GetPDGid()
                if totId == 24: genChan = ch.ElMu
                elif totId == 22: genChan = ch.ElEl
                elif totId == 26: genChan = ch.MuMu
                genMll = InvMass(l0, l1)

                genMET = t.GenMET_pt
                genJets = []
                ngenJet = 0
                ngenBJet = 0
                for i in range(t.nGenJet):
                    p = TLorentzVector()
                    p.SetPtEtaPhiM(t.GenJet_pt[i], t.GenJet_eta[i],
                                   t.GenJet_phi[i], t.GenJet_mass[i])
                    if p.Pt() < 25 or abs(p.Eta()) > 2.4: continue
                    pdgid = abs(t.GenJet_partonFlavour[i])
                    j = jet(p)
                    #if not j.IsClean(genLep, 0.4): continue
                    genJets.append(j)
                    ngenJet += 1
                    if pdgid == 5: ngenBJet += 1

                # Fill fidu yields histo
                if genMll >= 20 and genLep[0].Pt() >= 20:
                    self.obj['FiduEvents'].Fill(lev.dilepton)
                    if genChan == ch.ElEl or genChan == ch.MuMu:
                        if abs(genMll - 90) > 15:
                            self.obj['FiduEvents'].Fill(lev.ZVeto)
                            if genMET > 35:
                                self.obj['FiduEvents'].Fill(lev.MET)
                                if ngenJet >= 2:
                                    self.obj['FiduEvents'].Fill(lev.jets2)
                                    if ngenBJet >= 1:
                                        self.obj['FiduEvents'].Fill(lev.btag1)
                    else:
                        self.obj['FiduEvents'].Fill(lev.ZVeto)
                        self.obj['FiduEvents'].Fill(lev.MET)
                        if ngenJet >= 2:
                            self.obj['FiduEvents'].Fill(lev.jets2)
                            if ngenBJet >= 1:
                                self.obj['FiduEvents'].Fill(lev.btag1)

        ##### Muons
        for i in range(t.nMuon):
            p = TLorentzVector()
            p.SetPtEtaPhiM(t.Muon_pt[i], t.Muon_eta[i], t.Muon_phi[i],
                           t.Muon_mass[i])
            charge = t.Muon_charge[i]
            # Tight ID
            #if not t.Muon_tightId[i]: continue
            # Tight ISO, RelIso04 < 0.15
            if not t.Muon_pfRelIso04_all[i] < 0.15: continue
            # Tight IP
            dxy = abs(t.Muon_dxy[i])
            dz = abs(t.Muon_dz[i])
            if dxy > 0.05 or dz > 0.1: continue
            # pT < 12 GeV, |eta| < 2.4
            if p.Pt() < 12 or abs(p.Eta()) > 2.4: continue
            self.selLeptons.append(lepton(p, charge, 13))

        ##### Electrons
        for i in range(t.nElectron):
            p = TLorentzVector()
            pt = t.Electron_pt[i]
            eta = t.Electron_eta[i]
            ecorr = t.Electron_eCorr[i] if not self.isData else 1
            ptcorr = GetElecPt(pt, eta, ecorr, self.isData)
            ptcorr = GetElecPtSmear(ptcorr, eta, self.isData)
            p.SetPtEtaPhiM(ptcorr, eta, t.Electron_phi[i], t.Electron_mass[i])
            charge = t.Electron_charge[i]
            etaSC = abs(p.Eta())
            dEtaSC = t.Electron_deltaEtaSC[i]
            convVeto = t.Electron_convVeto[i]
            R9 = t.Electron_r9[i]
            # Tight cut-based Id
            if not t.Electron_cutBased[i] >= 2: continue  # 4 Tightcut-based Id
            if not convVeto: continue
            # Isolation (RelIso03) tight --> Included in nanoAOD cutbased bit!!
            relIso03 = t.Electron_pfRelIso03_all[i]
            #if   etaSC <= 1.479 and relIso03 > 0.0361: continue
            #elif etaSC >  1.479 and relIso03 > 0.094:  continue
            # Tight IP
            dxy = abs(t.Electron_dxy[i])
            dz = abs(t.Electron_dz[i])
            if dxy > 0.05 or dz > 0.1: continue
            # pT > 12 GeV, |eta| < 2.4
            if p.Pt() < 12 or abs(p.Eta()) > 2.4: continue
            self.selLeptons.append(lepton(p, charge, 11))
        leps = self.selLeptons
        pts = [lep.Pt() for lep in leps]
        self.selLeptons = [lep for _, lep in sorted(zip(pts, leps))]
        self.selLeptons.reverse()

        # Lepton SF
        self.SFelec = 1
        self.SFmuon = 1
        self.SFelecErr = 0
        self.SFmuonErr = 0
        self.TrigSF = 1
        self.TrigSFerr = 0
        self.TrigSFUp = 1
        self.TrigSFDo = 1
        if not self.isData:
            for lep in self.selLeptons:
                if lep.IsMuon():
                    sf, err = self.GetSFandErr('MuonIsoSF, MuonIdSF', lep.Pt(),
                                               TMath.Abs(lep.Eta()))
                    self.SFmuon *= sf
                    self.SFmuonErr += err * err  # stat + syst from TnP
                    self.SFmuonErr += 0.005 * 0.005  # Iso phase space extrapolation
                else:
                    #sf, err = self.GetSFandErr('ElecSF', lep.Eta(), lep.Pt())
                    elecsf = 'ElecEB' if lep.Eta() < 1.479 else 'ElecEE'
                    recosf = 'RecoEB' if lep.Eta() < 1.479 else 'RecoEE'
                    ssf, serr = self.GetSFfromTGraph(elecsf, lep.Pt())
                    rsf, rerr = self.GetSFfromTGraph(recosf, lep.Pt())
                    sf = (1. / ssf) * rsf
                    if rerr > 0.05:
                        rerr = 0.01  # XXX TEMPORARY CORRECTION TO AVOID WRONG SF UNCERTAINTIES
                    if serr > 0.05:
                        serr = 0.01  # XXX TEMPORARY CORRECTION TO AVOID WRONG SF UNCERTAINTIES
                    self.SFelec *= sf
                    self.SFelecErr += serr * serr + rerr * rerr
            self.SFelecErr = sqrt(self.SFelecErr)
            self.SFmuonErr = sqrt(self.SFmuonErr)
            self.SFmuon = 1

        ### Jet selection
        ###########################################

        for i in range(t.nJet):
            p = TLorentzVector()
            jetpt = getattr(t, self.jetptvar)[i]
            jetmass = getattr(t, self.jetmassvar)[i]
            p.SetPtEtaPhiM(jetpt, t.Jet_eta[i], t.Jet_phi[i], jetmass)
            csv = t.Jet_btagCSVV2[i]
            deepcsv = t.Jet_btagDeepB[i]
            deepflav = t.Jet_btagDeepFlavB[i]
            jid = t.Jet_jetId[i]
            flav = t.Jet_hadronFlavour[i] if not self.isData else -999999
            # Jet ID > 1, tight Id
            if not jid > 1: continue
            # |eta| < 2.4
            if abs(p.Eta()) > 2.4: continue
            j = jet(p, csv, flav, jid, deepcsv, deepflav)
            #if csv >= 0.8484 : j.SetBtag() ### Misssing CSVv2 SFs !!!!
            if not j.IsClean(self.selLeptons, 0.4): continue
            if p.Pt() >= self.JetPtCut: self.selJets.append(j)
            if not self.isData and self.doSyst and self.doJECunc:
                pJESUp = TLorentzVector()
                pJERUp = TLorentzVector()
                pJESDo = TLorentzVector()
                pJERDo = TLorentzVector()
                pJESUp.SetPtEtaPhiM(t.Jet_pt_jesTotalUp[i], t.Jet_eta[i],
                                    t.Jet_phi[i], t.Jet_mass_jesTotalUp[i])
                pJESDo.SetPtEtaPhiM(t.Jet_pt_jesTotalDown[i], t.Jet_eta[i],
                                    t.Jet_phi[i], t.Jet_mass_jesTotalDown[i])
                pJERUp.SetPtEtaPhiM(t.Jet_pt_jerUp[i], t.Jet_eta[i],
                                    t.Jet_phi[i], t.Jet_mass_jerUp[i])
                pJERDo.SetPtEtaPhiM(t.Jet_pt_jerDown[i], t.Jet_eta[i],
                                    t.Jet_phi[i], t.Jet_mass_jerDown[i])
                jJESUp = jet(pJESUp, csv, flav, jid, deepcsv, deepflav)
                jJESDo = jet(pJESDo, csv, flav, jid, deepcsv, deepflav)
                jJERUp = jet(pJERUp, csv, flav, jid, deepcsv, deepflav)
                jJERDo = jet(pJERDo, csv, flav, jid, deepcsv, deepflav)
                if pJESUp.Pt() >= self.JetPtCut:
                    self.selJetsJESUp.append(jJESUp)
                if pJESDo.Pt() >= self.JetPtCut:
                    self.selJetsJESDo.append(jJESDo)
                if pJERUp.Pt() >= self.JetPtCut:
                    self.selJetsJERUp.append(jJERUp)
                if pJERDo.Pt() >= self.JetPtCut:
                    self.selJetsJERDo.append(jJERDo)
        self.selJets = SortByPt(self.selJets)
        if not self.isData and self.doSyst and self.doJECunc:
            self.selJetsJESUp = SortByPt(self.selJetsJESUp)
            self.selJetsJESDo = SortByPt(self.selJetsJESDo)
            self.selJetsJERUp = SortByPt(self.selJetsJERUp)
            self.selJetsJERDo = SortByPt(self.selJetsJERDo)

        ##### MET
        self.pmet.SetPtEtaPhiE(t.MET_pt, 0, t.MET_phi, 0)
        #met = getattr(t, self.metptvar)
        #self.pmet.SetPtEtaPhiM(met, 0, t.MET_phi, 0)
        if not self.isData and self.doSyst and self.doJECunc:
            self.pmetJESUp.SetPtEtaPhiM(t.MET_pt_jesTotalUp, 0,
                                        t.MET_phi_jesTotalUp, 0)
            self.pmetJESDo.SetPtEtaPhiM(t.MET_pt_jesTotalDown, 0,
                                        t.MET_phi_jesTotalDown, 0)
            self.pmetJERUp.SetPtEtaPhiM(t.MET_pt_jerUp, 0, t.MET_phi_jerUp, 0)
            self.pmetJERDo.SetPtEtaPhiM(t.MET_pt_jerDown, 0, t.MET_phi_jerDown,
                                        0)

        nJets = len(self.selJets)
        nBtag = self.GetNBtagJets(self.selJets)

        ### Set dilepton channel
        nLep = len(self.selLeptons)
        if nLep < 2: return
        l0 = self.selLeptons[0]
        l1 = self.selLeptons[1]
        totId = l0.GetPDGid() + l1.GetPDGid()
        ich = -1
        if totId == 24: ich = ch.ElMu
        elif totId == 22: ich = ch.ElEl
        elif totId == 26: ich = ch.MuMu

        ### Trigger
        ###########################################
        trigger = {
            ch.Elec: t.HLT_HIEle20_WPLoose_Gsf,
            ch.Muon: t.HLT_HIL3Mu20,
            ch.ElMu: t.HLT_HIL3Mu20 or t.
            HLT_HIEle20_WPLoose_Gsf,  #t.HLT_HIL3Mu20 or t.HLT_HIEle20_WPLoose_Gsf,
            ch.ElEl: t.HLT_HIEle20_WPLoose_Gsf,
            ch.MuMu: t.HLT_HIL3Mu20  # or t.HLT_HIL3DoubleMu0
        }
        passTrig = trigger[ich]

        # TrigerSF
        if not self.isData:
            if ich == ch.MuMu:
                self.TrigSF, self.TrigSFerr = GetMuonTrigSF(
                    l0.Pt(), l0.Eta(), l1.Pt(), l1.Eta())
                self.TrigSFUp = self.TrigSF + self.TrigSFerr
                self.TrigSFDo = self.TrigSF - self.TrigSFerr
            elif ich == ch.Muon:
                self.TrigSF, self.TrigSFerr = GetMuonTrigSF(mu.Pt(), mu.Eta())
                self.TrigSFUp = self.TrigSF + self.TrigSFerr
                self.TrigSFDo = self.TrigSF - self.TrigSFerr
            elif ich == ch.Elec:
                self.TrigSF = self.GetElecTrigSF(el.pt(), el.eta(), sys=0)
                self.TrigSFUp = self.GetElecTrigSF(el.pt(), el.eta(), sys=1)
                self.TrigSFDo = self.GetElecTrigSF(el.pt(), el.eta(), sys=-1)
            elif ich == ch.ElEl:
                self.TrigSF = self.GetElecTrigSF(l0.Pt(), l0.Eta(), l1.Pt(),
                                                 l1.Eta(), 0)
                self.TrigSFUp = self.GetElecTrigSF(l0.Pt(), l0.Eta(), l1.Pt(),
                                                   l1.Eta(), 1)
                self.TrigSFDo = self.GetElecTrigSF(l0.Pt(), l0.Eta(), l1.Pt(),
                                                   l1.Eta(), -1)
            elif ich == ch.ElMu:
                mu = l0 if l0.IsMuon() else l1
                el = l1 if l0.IsMuon() else l0
                self.TrigSF = self.GetEMuTrigSF(el.Pt(),
                                                el.Eta(),
                                                mu.Pt(),
                                                mu.Eta(),
                                                sys=0)
                self.TrigSFUp = self.GetEMuTrigSF(el.Pt(),
                                                  el.Eta(),
                                                  mu.Pt(),
                                                  mu.Eta(),
                                                  sys=1)
                self.TrigSFDo = self.GetEMuTrigSF(el.Pt(),
                                                  el.Eta(),
                                                  mu.Pt(),
                                                  mu.Eta(),
                                                  sys=-1)

        ### Remove overlap events in datasets
        # In tt @ 5.02 TeV,
        if self.isData:
            if self.sampleDataset == datasets.SingleElec:
                if ich == ch.ElEl: passTrig = trigger[ch.ElEl]
                elif ich == ch.ElMu:
                    passTrig = trigger[ch.Elec] and not trigger[ch.Muon]
                else:
                    passTrig = False
            elif self.sampleDataset == datasets.SingleMuon:
                if ich == ch.MuMu: passTrig = trigger[ch.MuMu]
                elif ich == ch.ElMu: passTrig = trigger[ch.ElMu]
                else: passTrig = False
            elif self.sampleDataset == datasets.DoubleMuon:
                if ich == ch.MuMu: passTrig = trigger[ich]
                else: passTrig = False

        ### Event weight and othe global variables
        ###########################################
        self.nvtx = t.PV_npvs
        self.PUSF = 1
        self.PUUpSF = 1
        self.PUDoSF = 1
        #if not self.isData and self.doPU:
        #  self.PUSF   = t.puWeight
        #  self.PUUpSF = t.puWeightUp
        #  self.PUDoSF = t.puWeightDown
        #if not self.isData:
        #  self.PUSF   = self.PUweight.GetWeight(t)
        #  self.PUUpSF = self.PUweight.GetWeightUp(t)
        #  self.PUDoSF = self.PUweight.GetWeightDown(t)
        self.obj['PUWeights'].Fill(self.PUSF)

        self.prefWeight = 1
        self.prefWeightUp = 1
        self.prefWeightDo = 1
        if not self.isData:
            self.prefWeight = self.PrefCorr.GetWeight(t)
            self.prefWeightUp = self.PrefCorr.GetWeightUp(t)
            self.prefWeightDo = self.PrefCorr.GetWeightDown(t)

        self.fsrUp = 1
        self.fsrDo = 1
        self.isrUp = 1
        self.isrDo = 1
        if self.doIFSR:
            self.isrDo = t.PSWeight[0]
            self.fsrDo = t.PSWeight[1]
            self.isrUp = t.PSWeight[2]
            self.fsrUp = t.PSWeight[3]

        ### Event selection
        ###########################################
        self.SetWeight(systematic.nom)
        weight = self.weight

        if not passTrig: return
        self.SS = l0.charge * l1.charge > 0
        for isyst in systlabel.keys():
            if not self.doSyst and isyst != systematic.nom: continue
            if self.isData and isyst != systematic.nom: continue
            leps, jets, pmet = self.SetVariables(isyst)
            nJets = len(jets)
            nBtag = self.GetNBtagJets(jets, isyst)
            if not len(leps) >= 2: continue
            l0 = leps[0]
            l1 = leps[1]

            ### Dilepton pair
            if l0.Pt() < 20: continue
            if InvMass(l0, l1) < 20: continue
            self.FillAll(ich, lev.dilepton, isyst, leps, jets, pmet)
            if self.isTTnom and isyst == systematic.nom:
                self.FillLHEweights(t, ich, lev.dilepton)

            # >> Fill the DY histograms
            if (self.isData or self.isDY) and isyst == systematic.nom:
                self.FillDYHistos(self.selLeptons, ich, lev.dilepton)
                if self.pmet.Pt() > 35:
                    self.FillDYHistos(self.selLeptons, ich, lev.MET)
                    if nJets == 1:
                        self.FillDYHistos(self.selLeptons, ich, 'eq1jet')
                    elif nJets == 2:
                        self.FillDYHistos(self.selLeptons, ich, 'eq2jet')
                    elif nJets >= 3:
                        self.FillDYHistos(self.selLeptons, ich, 'geq3jet')
                    if nJets >= 2:
                        self.FillDYHistos(self.selLeptons, ich, lev.jets2)
                        if nBtag >= 1:
                            self.FillDYHistos(self.selLeptons, ich, lev.btag1)
                            if nBtag >= 2:
                                self.FillDYHistos(self.selLeptons, ich,
                                                  '2btag')
                if nJets == 1:
                    self.FillDYHistosElMu(self.selLeptons, ich, 'eq1jet')
                elif nJets == 2:
                    self.FillDYHistosElMu(self.selLeptons, ich, 'eq2jet')
                elif nJets >= 3:
                    self.FillDYHistosElMu(self.selLeptons, ich, 'geq3jet')
                if nJets >= 2:
                    self.FillDYHistosElMu(self.selLeptons, ich, lev.jets2)
                    if nBtag >= 1:
                        self.FillDYHistosElMu(self.selLeptons, ich, lev.btag1)
                        if nBtag >= 2:
                            self.FillDYHistosElMu(self.selLeptons, ich,
                                                  '2btag')

            ### WW selec
            if (l1.p + l0.p).Pt() > 20 and nJets == 0 and pmet.Pt() > 25:
                self.FillAll(ich, lev.ww, isyst, leps, jets, pmet)

            ### Z Veto + MET cut
            if ich == ch.MuMu or ich == ch.ElEl:
                if abs(InvMass(l0, l1) - 91) < 15: continue
                self.FillAll(ich, lev.ZVeto, isyst, leps, jets, pmet)
                if self.isTTnom and isyst == systematic.nom:
                    self.FillLHEweights(t, ich, lev.ZVeto)
                if pmet.Pt() < 35: continue
                self.FillAll(ich, lev.MET, isyst, leps, jets, pmet)
                if self.isTTnom and isyst == systematic.nom:
                    self.FillLHEweights(t, ich, lev.MET)

            ### 2 jets
            if nJets < 2: continue
            self.FillAll(ich, lev.jets2, isyst, leps, jets, pmet)
            if self.isTTnom and isyst == systematic.nom:
                self.FillLHEweights(t, ich, lev.jets2)

            ### 1 b-tag, CSVv2 Medium
            if nBtag < 1: continue
            self.FillAll(ich, lev.btag1, isyst, leps, jets, pmet)
            if self.isTTnom and isyst == systematic.nom:
                self.FillLHEweights(t, ich, lev.btag1)