Exemple #1
0
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 __init__(self,
              path,
              outpath='./temp/',
              chan='ElMu',
              level='2jets',
              DYsamples='DYJetsToLL_M_10to50,DYJetsToLL_MLL50',
              DataSamples='HighEGJet,SingleMuon, DoubleMuon',
              lumi=304.32,
              massRange=[91 - 15, 91 + 15],
              mode='',
              histonameprefix='H',
              hname='DY_InvMass'):
     self.SetPath(path)
     self.SetOutPath(outpath)
     self.t = TopHistoReader(path)
     self.t.SetHistoNamePrefix(histonameprefix)
     self.SetLumi(lumi)
     self.SetChanAndLevel(chan, level)
     self.SetDYsamples(DYsamples)
     self.SetDataSamples(DataSamples)
     self.SetMassRange(massRange[0], massRange[1])
     self.SetHistoNameOF()
     self.SetHistoNameSF()
     if chan == 'ElMu':
         if hname != '': self.SetHistoNameOF(hname)
         self.SetMode('OF')
     else:
         if hname != '': self.SetHistoNameSF(hname)
         self.SetMode('SF')
     if mode != '': self.SetMode(mode)
Exemple #3
0
 def __init__(self,
              path,
              outpath='./temp/',
              chan='ElMu',
              level='2jets',
              process={},
              prompt=[],
              nonprompt=[],
              lumi=304.32,
              histonameprefix='H',
              yieldsSSname='SSYields'):
     self.SetPath(path)
     self.t = TopHistoReader(self.GetPath())
     self.t.SetHistoNamePrefix(histonameprefix)
     self.t.SetYieldsSSname(yieldsSSname)
     self.SetLumi(lumi)
     self.SetOutPath(outpath)
     self.SetChanAndLevel(chan, level)
     self.process = process
     self.nonpromptProcess = []
     self.promptProcess = []
     if prompt == [] or nonprompt == []:
         for pr in process.keys():
             if pr in ['data', 'Data', 'DATA']: continue
             elif pr in [
                     'fake', 'nonprompt', 'Nonprompt', 'NonPrompt', 'Fake',
                     'fakes', 'Fakes'
             ]:
                 self.nonpromptProcess.append(pr)
             else:
                 self.promptProcess.append(pr)
     else:
         self.promptProcess = prompt
         self.nonpromptProcess = nonprompt
def SavePlots(s, var='mt2', sampName='tt', tag='PDF uncertainty'):
    tr = TopHistoReader(outpath + s)
    a = HistoUnc(out + '/PDF%s/' % sampName,
                 var + sampName + s,
                 tag=tag,
                 xtit=titdic[var] if var in titdic.keys() else '')
    a.SetLumi(GetLumi(year))
    a.AddHistoNom(tr.GetNamedHisto(sampName, var))
    a.AddHistoUp(tr.GetNamedHisto(sampName + '_' + s + 'Up', var))
    a.AddHistoDown(tr.GetNamedHisto(sampName + '_' + s + 'Down', var))
    a.Draw()
Exemple #5
0
 def __init__(self, path, hname='', outpath='./temp/', outname='', rebin=1):
     self.t = TopHistoReader(path)
     self.SetPath(path)
     self.SetRebin(rebin)
     self.SetHistoName(hname)
     self.SetOutputDir(outpath)
     self.SetOutName(outname)
     self.histos = []
     self.syst = []
     self.dpr = {}
     self.AddData()
Exemple #6
0
    #gr.GetXaxis().SetLimits(165,180);

    c.SetRightMargin(0.03)
    c.Update()
    for form in ['png', 'pdf']:
        c.Print(outpath + outname + '_' + mode + '.' + form)


ch = 'ElMu'
lev = '2jets'
level = {'dilepton': 1, 'ZVeto': 2, 'MET': 3, '2jets': 4, '1btag': 5}

# Get acceptance numbers
from plotter.TopHistoReader import TopHistoReader

thr = TopHistoReader(path)
dic = {'tt': 'TT', 'up': 'TT_mtop178p5', 'down': 'TT_mtop166p5'}
GetAcc = lambda samp, ch, lev: thr.GetNamedHisto('Lep0Eta_%s_%s' % (ch, lev),
                                                 dic[samp]).Integral()
GetUnc = lambda samp, ch, lev: thr.GetNamedHisto('Yields_%s' % (ch), dic[samp]
                                                 ).GetBinError(level[lev])
nom = GetAcc('tt', ch, lev)
up = GetAcc('up', ch, lev)
do = GetAcc('down', ch, lev)

mass = [166.5, 172.5, 178.5]
xsec = [xsecnom * (nom / do), xsecnom, xsecnom * (nom / up)]
#= [xsecunc*(nom/do), xsecunc, xsecunc*(nom/up)]
xsecerr = [GetUnc(x, ch, lev) for x in ['down', 'tt', 'up']]
DrawTopMassFit(mass, xsec, xsecerr, 'lin')
class DYDD:

    ### Set methods
    def SetPath(self, p):
        if not p.endswith('/'): p += '/'
        self.path = p

    def SetOutPath(self, p):
        self.outpath = p

    def SetMode(self, mode='OF', hname=''):
        self.doOF = True
        if mode in ['SF', 'Elec', 'ElEl', 'Muon', 'MuMu']:
            self.doOF = False
        if self.doOF:
            if hname != '': self.SetHistoNameOF(hname)
            self.SetZhistoName(self.hnameOF)
        else:
            if hname != '': self.SetHistoNameSF(hname)
            self.SetZhistoName(self.hnameSF)

    def SetLumi(self, l):
        self.lumi = l
        self.t.SetLumi(self.lumi)

    def SetHistoNameOF(self, h='DY_InvMass'):
        self.hnameOF = h

    def SetHistoNameSF(self, h='DY_SF_InvMass'):
        self.hnameSF = h

    def SetDYsamples(self, f):
        self.DYfiles = f

    def SetDataSamples(self, f):
        self.datafiles = f

    def SetChannel(self, c):
        self.chan = c

    def SetLevel(self, l):
        self.level = l

    def SetZhistoName(self, h):
        self.zhname = h

    def SetMassRange(self, minM=91 - 15, maxM=91 + 15):
        self.minMZ = minM
        self.maxMZ = maxM

    def SetChanAndLevel(self, chan='', level=''):
        ''' Manages to set chan and leve to the class and the TopHistoReader '''
        if chan != '': self.SetChannel(chan)
        if level != '': self.SetLevel(level)
        self.t.SetChan(self.GetChan())
        self.t.SetLevel(self.GetLevel())
        return self.GetChan(), self.GetLevel()

    ### Get methods
    def GetPath(self):
        return self.path

    def GetOutPath(self):
        return self.outpath

    def GetZhistoName(self):
        return self.zhname

    def GetDYfiles(self):
        return self.DYfiles

    def GetDataFiles(self):
        return self.datafiles

    def GetLevel(self):
        return self.level

    def GetChan(self):
        return self.chan

    ### Calculate quantities...

    def GetDYhisto(self, chan='', level='', isData=True):
        # ARREGLAR PARA QUE COJA EL ADECUADO DEPENDIENDO DEL CANAL!! O HACER FUNCION PARA INDICAR CANAL EMU
        chan, level = self.SetChanAndLevel(chan, level)
        if isData:
            self.t.SetIsData(True)
            pr = self.GetDataFiles()
        else:
            self.t.SetIsData(False)
            pr = self.GetDYfiles()
        zname = self.GetZhistoName()
        if level == 'dilepton' and zname[-4:] == 'ElMu': zname = zname[:-4]
        h = self.t.GetHisto(pr, zname, chan, level)
        h.SetDirectory(0)
        return h

    def GetHdata(self, chan, level):
        return self.GetDYhisto(chan, level, True)

    def GetHMC(self, chan, level):
        return self.GetDYhisto(chan, level, False)

    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

    def GetDataIn(self, chan='', level=''):
        return self.DYyield('in', True, chan, level)

    def GetDataOut(self, chan='', level=''):
        return self.DYyield('out', True, chan, level)

    def GetMCin(self, chan='', level=''):
        return self.DYyield('in', False, chan, level)

    def GetMCout(self, chan='', level=''):
        return self.DYyield('out', False, chan, level)

    def GetRoutin(self, chan='', level=''):
        ''' Returns ratio Rout/in from MC '''
        rin, errin = self.GetMCin(chan, level)
        out, errout = self.GetMCout(chan, level)
        r = out / rin if rin != 0 else 0
        err = r * SumSquare(
            [errout / out if out != 0 else 0, errin / rin if rin != 0 else 0])
        return r, err

    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

    def GetDYDD(self, chan='', level='', mode=''):
        ''' Returns the DY estimate from data '''
        chan, level = self.SetChanAndLevel(chan, level)
        if chan == 'ElMu': self.SetMode('ElMu')
        if mode != '': self.SetMode(mode)
        routin, routin_err = self.GetRoutin(chan, level)
        NemuIn, NemuIn_err = self.GetDataIn('ElMu', level)
        kee, keerr = self.GetKfactor(elname, level)
        NeeIn, NeeInerr = self.GetDataIn(elname, level)
        kmm, kmmrr = self.GetKfactor(muname, level)
        NmmIn, NmmInerr = self.GetDataIn(muname, level)
        est = lambda r, Nin, Nemu, k: r * (Nin - Nemu * k / 2)
        esterr = lambda r, Nin, Nemu, k, er, eNin, eNemu, ek: SumSquare([
            est(r, Nin, Nemu, k) *
            (er / r
             if r != 0 else 0), r * eNin, r * k / 2 * eNemu, r * Nemu / 2 * ek
        ])
        N = 0
        Nerr = 0
        if chan == elname:
            N = est(routin, NeeIn, NemuIn, kee)
            Nerr = esterr(routin, NeeIn, NemuIn, kee, routin_err, NeeInerr,
                          NemuIn_err, keerr)
        elif chan == muname:
            N = est(routin, NmmIn, NemuIn, kmm)
            Nerr = esterr(routin, NmmIn, NemuIn, kmm, routin_err, NmmInerr,
                          NemuIn_err, kmmrr)
        else:  # ElMu
            self.t.SetIsData(False)
            yDY = self.t.GetYield(self.GetDYfiles(), 'ElMu')
            yDYe = self.t.GetYieldStatUnc(self.GetDYfiles(), 'ElMu')
            SF, err = self.GetScaleFactor('ElMu')
            N = yDY * SF
            Nerr = N * SumSquare([
                err / SF if SF != 0 else err, yDYe / yDY if yDY != 0 else yDYe
            ])
        if N < 0:
            N = 0
            Nerr = 0
        if not Nerr == Nerr: Nerr = 0
        return N, Nerr

    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 == muname or chan == elname:
            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(elname)
            m, mr = self.GetScaleFactor(muname)
            SF = sqrt(e * m)
            err = SF * SumSquare(
                [er / e if e != 0 else 0, mr / m if m != 0 else 0])
        return SF, err

    def DrawHisto(self,
                  doSF=False,
                  name='',
                  chan='',
                  level='',
                  rebin=1,
                  log=True):
        self.SetChanAndLevel('', level)
        self.SetMode('SF' if doSF else 'OF')
        if name == '':
            name = 'DYDD_%s_%s' % ('SF' if doSF else 'OF', self.GetLevel())
        hData = self.GetDYhisto(chan, level, True)
        hMC = self.GetDYhisto(chan, level, False)
        hemu = self.GetDYhisto('ElMu', level, True)
        hData.SetMarkerStyle(20)
        hData.SetMarkerColor(1)
        hData.SetLineColor(1)
        hData.SetMarkerSize(1.3)
        hMC.SetFillStyle(1000)
        hMC.SetLineColor(kAzure - 8)
        hMC.SetFillColor(kAzure - 8)
        hemu.SetFillStyle(1000)
        hemu.SetLineColor(kGray)
        hemu.SetFillColor(kGray)
        hData.Rebin(rebin)
        hemu.Rebin(rebin)
        hMC.Rebin(rebin)
        ke, kee = self.GetKfactor(elname)
        km, kme = self.GetKfactor(muname)
        hemu.Scale(0.5 * (ke if chan == 'ElE' else km))
        hs = THStack()
        hs.Add(hemu)
        hs.Add(hMC)
        lab = 'e^{#pm}e^{#mp}' if chan == 'ElEl' else '#mu^{#pm}#mu^{#mp}'
        rlab = 'ee' if chan == 'ElEl' else '#mu#mu'
        processes = [
            'Z/#gamma*#rightarrow %s' % (lab),
            '0.5 k_{%s} #times Data(e#mu)' % rlab
        ]
        colors = {processes[0]: kAzure - 9, processes[1]: kGray}
        s = Stack(doRatio=False)
        s.SetXtitle(size=0.06, offset=0.8, nDiv=510, labSize=0.05)
        s.SetTextCMS(cmstex='CMS', x=0.13, y=0.88, s=0.06)
        s.SetTextCMSmode(texcmsMode='Preliminary', x=0.225, y=0.875, s=0.052)
        s.SetLumi(304.32)
        s.SetTextLumi(texlumi='%2.1f pb^{-1} (5.02 TeV)',
                      texlumiX=0.68,
                      texlumiY=0.95,
                      texlumiS=0.045)
        s.SetDataHisto(hData)
        s.SetColors(colors)
        s.SetStack(hs)
        s.SetOutName('DYestimate_%s%s' % (chan, level) +
                     ('_log' if log else ''))
        s.SetOutPath(self.outpath)
        plotMinimum = 0.5 if log else 0
        plotMaxScale = 10 if log else 1.3
        s.SetLogY(log)
        s.SetPlotMaxScale(plotMaxScale)
        s.SetPlotMinimum(plotMinimum)
        maximum = hData.GetMaximum() * (5 if log else 1.2)
        s.AddLine(76, 0.5, 76, maximum)
        s.AddLine(106, 0.5, 106, maximum)
        s.processes = processes
        s.SetLegendPos(x0=0.60, y0=0.55, x1=0.93, y1=0.91, size=0.042, ncol=1)
        s.DrawStack('m_{%s} (GeV)' % rlab)

    def DrawClosureMCeff(self,
                         level='dilepton',
                         outpath='~/www/temp/',
                         ratio=[0.9, 1.1]):
        self.SetMode('OF')
        self.SetChanAndLevel('', level)
        ke, kee = self.GetKfactor(elname)
        km, kme = self.GetKfactor(muname)
        print 'ke = %1.2f +/- %1.2f' % (ke, kee)
        print 'km = %1.2f +/- %1.2f' % (km, kme)

        hdata = TH1F('d1', 'd1', 2, 0, 2)
        hpred = TH1F('h1', 'h1', 2, 0, 2)
        err = lambda l: sqrt(sum([x * x for x in l]))
        '''
   hee1   = self.GetDYhisto(elname, level, False)
   hmm1   = self.GetDYhisto(muname, level, False)
   ee1 = hee1.Integral(); mm1 = hmm1.Integral()

   hdata.SetBinContent(1, ee1); hdata.SetBinError(1, sqrt(ee1));
   hdata.SetBinContent(2, mm1); hdata.SetBinError(2, sqrt(mm1));
   hpred.SetBinContent(1, mm1*ke1); hpred.SetBinError(1, mm1*ke1*( err([sqrt(mm1)/mm1, kee1/ke1]) ))
   hpred.SetBinContent(2, ee1*km1); hpred.SetBinError(2, ee1*km1*( err([sqrt(ee1)/ee1, kme1/km1]) ))
   '''
        sampName = 'TT'
        hname = 'Lep0Eta'
        h_emu = self.t.GetNamedHisto('%s_%s_%s' % (hname, 'ElMu', level),
                                     sampName)
        h_ee = self.t.GetNamedHisto(
            '%s_%s_%s' %
            (hname, 'ElEl', '2jetsnomet' if level == '2jets' else level),
            sampName)
        h_mu = self.t.GetNamedHisto(
            '%s_%s_%s' %
            (hname, 'MuMu', '2jetsnomet' if level == '2jets' else level),
            sampName)
        y_emu = h_emu.Integral() * 304.32
        y_mu = h_mu.Integral() * 304.32
        y_ee = h_ee.Integral() * 304.32
        d_ee = 0.5 * y_emu * ke
        d_ee_err = d_ee * (kee / ke)
        d_mu = 0.5 * y_emu * km
        d_mu_err = d_mu * (kme / km)
        hdata.SetBinContent(1, y_ee)
        hdata.SetBinError(1, y_ee / sqrt(h_ee.GetEntries()))
        hdata.SetBinContent(2, y_mu)
        hdata.SetBinError(2, y_mu / sqrt(h_mu.GetEntries()))
        hpred.SetBinContent(1, d_ee)
        hpred.SetBinError(1, d_ee_err)
        hpred.SetBinContent(2, d_mu)
        hpred.SetBinError(2, d_mu_err)

        p = HistoComp(outpath, doRatio=True, doNorm=False)
        hdata.SetLineWidth(1)
        hdata.SetMarkerSize(1.2)
        hdata.SetMarkerColor(1)
        hdata.SetMarkerStyle(20)
        hdata.SetFillColor(0)
        hdata.SetFillStyle(0)
        hpred.SetFillStyle(3144)
        hpred.SetFillColor(kAzure - 8)
        p.SetPlotMaxScale(1.5)
        p.SetLumi(304.32)
        p.AddHisto(hpred, 'l', 'e2', '0.5 x k_{ll} x t#bar{t} e#mu MC',
                   kAzure + 2, 2)
        p.AddHisto(hdata, 'pe', '', 'Same-flavor t#bar{t} MC', 1)
        p.SetBinLabels(['ee', '#mu#mu'])
        p.SetYratioTitle('Ratio')
        p.SetYtitle('t#bar{t} events')
        rmin, rmax = ratio
        p.SetLegendPos(0.15, 0.6, 0.5, 0.8, ncol=1)
        p.SetRatioMin(rmin)
        p.SetRatioMax(rmax)
        p.SetOutName('DYDDeffClosure_' + level)
        p.autoRatio = True
        p.PlotWithData = True
        p.Draw(0)

    def PrintDYestimate(self, doSF=False, name='', level=''):
        hee = self.GetDYhisto(elname, level, False)
        hmm = self.GetDYhisto(muname, level, False)
        self.SetChanAndLevel('', level)
        self.SetMode('SF' if doSF else 'OF')
        if name == '':
            name = 'DYDD_%s_%s' % ('SF' if doSF else 'OF', self.GetLevel())
        t = OutText(self.GetOutPath(), name, textformat='tex')
        t.SetTexAlign("l c c c")
        t.SetSeparatorLength(20 + (3 + 22) * 3)
        t.SetDefaultFixOption(False)
        t.line('%' + 'Drell-Yan estimate for %s and level \'%s\'' %
               ('SF channels' if doSF else 'all channels (no MET cut) ',
                self.GetLevel()))
        t.bar()
        s = lambda tit, vee, vmm, vem: t.line(
            t.fix(tit, 20) + t.vsep() + t.fix(vee, 22, 'c') + t.vsep() + t.fix(
                vmm, 22, 'c') + t.vsep() + t.fix(vem, 22, 'c'))
        v = lambda val, err: '%1.2f' % val + t.pm() + '%1.2f' % err
        d = lambda val, err: '%1.0f' % val + t.pm() + '%1.2f' % err
        s('', 'ee', '$\mu\mu$', 'e$\mu$')
        t.sep()
        mie, miee = self.GetMCin(elname)
        moe, moee = self.GetMCout(elname)
        mim, mime = self.GetMCin(muname)
        mom, mome = self.GetMCout(muname)
        s(' $N_{in}$        (MC)', v(mie, miee), v(mim, mime), '')
        s(' $N_{out}$       (MC)', v(moe, moee), v(mom, mome), '')

        re, ree = self.GetRoutin(elname)
        rm, rme = self.GetRoutin(muname)
        s(' $R_{out/in}$  (MC)', v(re, ree), v(rm, rme), '')

        ke, kee = self.GetKfactor(elname)
        km, kme = self.GetKfactor(muname)
        s(' $k_{ll}$            ', v(ke, kee), v(km, kme), '')

        ie, ier = self.GetDataIn(elname)
        im, imr = self.GetDataIn(muname)
        iem, iemr = self.GetDataIn('ElMu')
        s(' $N_{in}$      (Data)', d(ie, ier), d(im, imr), d(iem, iemr))
        t.sep()
        dde, ddee = self.GetDYDD(elname)
        ddm, ddme = self.GetDYDD(muname)
        tmc = ' DY estimate out (MC) ' if doSF else ' DY estimate (MC)'
        tdata = ' DY estimate out (DD) ' if doSF else ' DY estimate (DD)'
        if doSF:
            s(' DY estimate (MC)', v(moe, moee), v(mom, mome), '')
            s(' DY estimate (DD)', v(dde, ddee), v(ddm, ddme), '')
        else:
            ddem, ddeme = self.GetDYDD('ElMu')
            yDY = self.t.GetYield(self.GetDYfiles(), 'ElMu')
            yDYe = self.t.GetYieldStatUnc(self.GetDYfiles(), 'ElMu')
            s(' DY estimate (MC)', v(moe, moee), v(mom, mome), v(yDY, yDYe))
            s(' DY estimate (DD)', v(dde, ddee), v(ddm, ddme), v(ddem, ddeme))
        t.sep()
        sfee, sfeee = self.GetScaleFactor(elname)
        sfmm, sfmme = self.GetScaleFactor(muname)
        if doSF:
            s(' DD/MC ratio     ', v(sfee, sfeee), v(sfmm, sfmme), '')
        else:
            sfem, sfeme = self.GetScaleFactor('ElMu')
            s(' DD/MC ratio     ', v(sfee, sfeee), v(sfmm, sfmme),
              v(sfem, sfeme))
        t.bar()
        t.write()

    def PrintDYSFnjets(self):
        t = OutText(self.GetOutPath(), 'DYSF_njets')
        t.SetSeparatorLength(22 + (3 + 16) * 3)
        t.SetDefaultFixOption(False)
        t.line(
            'Drell-Yan data/MC scale factors for different jet multiplicities')
        t.bar()
        s = lambda tit, vee, vmm, vem: t.line(
            t.fix(tit, 22) + t.vsep() + t.fix(vee, 16, 'c') + t.vsep() + t.fix(
                vmm, 16, 'c') + t.vsep() + t.fix(vem, 16, 'c'))
        v = lambda val, err: '%1.2f' % val + t.pm() + '%1.2f' % err
        s('', elname, muname, 'ElMu')
        t.sep()
        #labels = ['Inclusive','== 1 jet', '== 2 jets', '>= 3 jets','>= 2 jets, >= 1 btag', '>= 2 btag']
        #levels = ['dilepton', 'eq1jet', 'eq2jet', 'geq3jet','1btag', '2btag']
        labels = ['Inclusive', '>= 2 jets', ' >= 1 btag']
        levels = ['dilepton', '2jets', '1btag']
        for i in range(len(labels)):
            if i == 4: t.sep()
            lab = labels[i]
            lev = levels[i]
            sfe, sfee = self.GetScaleFactor(elname, lev, 'SF')
            sfm, sfme = self.GetScaleFactor(muname, lev, 'SF')
            sfo, sfoe = self.GetScaleFactor('ElMu', lev, 'OF')
            s(' ' + lab,
              v(sfe, sfee) if sfe > 0 else '-',
              v(sfm, sfme) if sfm > 0 else '-',
              v(sfo, sfoe) if sfo > 0 else '-')
        t.bar()
        t.write()

    def __init__(self,
                 path,
                 outpath='./temp/',
                 chan='ElMu',
                 level='2jets',
                 DYsamples='DYJetsToLL_M_10to50,DYJetsToLL_MLL50',
                 DataSamples='HighEGJet,SingleMuon, DoubleMuon',
                 lumi=304.32,
                 massRange=[91 - 15, 91 + 15],
                 mode='',
                 histonameprefix='H',
                 hname='DY_InvMass'):
        self.SetPath(path)
        self.SetOutPath(outpath)
        self.t = TopHistoReader(path)
        self.t.SetHistoNamePrefix(histonameprefix)
        self.SetLumi(lumi)
        self.SetChanAndLevel(chan, level)
        self.SetDYsamples(DYsamples)
        self.SetDataSamples(DataSamples)
        self.SetMassRange(massRange[0], massRange[1])
        self.SetHistoNameOF()
        self.SetHistoNameSF()
        if chan == 'ElMu':
            if hname != '': self.SetHistoNameOF(hname)
            self.SetMode('OF')
        else:
            if hname != '': self.SetHistoNameSF(hname)
            self.SetMode('SF')
        if mode != '': self.SetMode(mode)
class DYDD:

    ### Set methods
    def SetPath(self, p):
        if not p.endswith('/'): p += '/'
        self.path = p

    def SetOutPath(self, p):
        self.outpath = p

    def SetMode(self, mode='OF', hname=''):
        self.doOF = True
        if mode in ['SF', 'Elec', 'ElEl', 'Muon', 'MuMu']:
            self.doOF = False
        if self.doOF:
            if hname != '': self.SetHistoNameOF(hname)
            self.SetZhistoName(self.hnameOF)
        else:
            if hname != '': self.SetHistoNameSF(hname)
            self.SetZhistoName(self.hnameSF)

    def SetLumi(self, l):
        self.lumi = l
        self.t.SetLumi(self.lumi)

    def SetHistoNameOF(self, h='DY_InvMass'):
        self.hnameOF = h

    def SetHistoNameSF(self, h='DY_SF_InvMass'):
        self.hnameSF = h

    def SetDYsamples(self, f):
        self.DYfiles = f

    def SetDataSamples(self, f):
        self.datafiles = f

    def SetChannel(self, c):
        self.chan = c

    def SetLevel(self, l):
        self.level = l

    def SetZhistoName(self, h):
        self.zhname = h

    def SetMassRange(self, minM=91 - 15, maxM=91 + 15):
        self.minMZ = minM
        self.maxMZ = maxM

    def SetChanAndLevel(self, chan='', level=''):
        ''' Manages to set chan and leve to the class and the TopHistoReader '''
        if chan != '': self.SetChannel(chan)
        if level != '': self.SetLevel(level)
        self.t.SetChan(self.GetChan())
        self.t.SetLevel(self.GetLevel())
        return self.GetChan(), self.GetLevel()

    ### Get methods
    def GetPath(self):
        return self.path

    def GetOutPath(self):
        return self.outpath

    def GetZhistoName(self):
        return self.zhname

    def GetDYfiles(self):
        return self.DYfiles

    def GetDataFiles(self):
        return self.datafiles

    def GetLevel(self):
        return self.level

    def GetChan(self):
        return self.chan

    ### Calculate quantities...

    def GetDYhisto(self, chan='', level='', isData=True):
        # ARREGLAR PARA QUE COJA EL ADECUADO DEPENDIENDO DEL CANAL!! O HACER FUNCION PARA INDICAR CANAL EMU
        chan, level = self.SetChanAndLevel(chan, level)
        if isData:
            self.t.SetIsData(True)
            pr = self.GetDataFiles()
        else:
            self.t.SetIsData(False)
            pr = self.GetDYfiles()
        zname = self.GetZhistoName()
        if level == 'dilepton' and zname[-4:] == 'ElMu': zname = zname[:-4]
        h = self.t.GetHisto(pr, zname, chan, level)
        h.SetDirectory(0)
        return h

    def GetHdata(self, chan, level):
        return self.GetDYhisto(chan, level, True)

    def GetHMC(self, chan, level):
        return self.GetDYhisto(chan, level, False)

    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

    def GetDataIn(self, chan='', level=''):
        return self.DYyield('in', True, chan, level)

    def GetDataOut(self, chan='', level=''):
        return self.DYyield('out', True, chan, level)

    def GetMCin(self, chan='', level=''):
        return self.DYyield('in', False, chan, level)

    def GetMCout(self, chan='', level=''):
        return self.DYyield('out', False, chan, level)

    def GetRoutin(self, chan='', level=''):
        ''' Returns ratio Rout/in from MC '''
        rin, errin = self.GetMCin(chan, level)
        out, errout = self.GetMCout(chan, level)
        r = out / rin if rin != 0 else 0
        err = r * SumSquare(
            [errout / out if out != 0 else 0, errin / rin if rin != 0 else 0])
        return r, err

    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)
        kerr = k * SumSquare([
            errElec / (2 * rinElec) if rinElec != 0 else 0, errMuon /
            (2 * rinMuon) if rinMuon != 0 else 0
        ])
        return k, kerr

    def GetDYDD(self, chan='', level='', mode=''):
        ''' Returns the DY estimate from data '''
        chan, level = self.SetChanAndLevel(chan, level)
        if chan == 'ElMu': self.SetMode('ElMu')
        if mode != '': self.SetMode(mode)
        routin, routin_err = self.GetRoutin(chan, level)
        NemuIn, NemuIn_err = self.GetDataIn('ElMu', level)
        kee, keerr = self.GetKfactor(elname, level)
        NeeIn, NeeInerr = self.GetDataIn(elname, level)
        kmm, kmmrr = self.GetKfactor(muname, level)
        NmmIn, NmmInerr = self.GetDataIn(muname, level)
        est = lambda r, Nin, Nemu, k: r * (Nin - Nemu * k / 2)
        esterr = lambda r, Nin, Nemu, k, er, eNin, eNemu, ek: SumSquare([
            est(r, Nin, Nemu, k) *
            (er / r
             if r != 0 else 0), r * eNin, r * k / 2 * eNemu, r * Nemu / 2 * ek
        ])
        N = 0
        Nerr = 0
        if chan == elname:
            N = est(routin, NeeIn, NemuIn, kee)
            Nerr = esterr(routin, NeeIn, NemuIn, kee, routin_err, NeeInerr,
                          NemuIn_err, keerr)
        elif chan == muname:
            N = est(routin, NmmIn, NemuIn, kmm)
            Nerr = esterr(routin, NmmIn, NemuIn, kmm, routin_err, NmmInerr,
                          NemuIn_err, kmmrr)
        else:  # ElMu
            self.t.SetIsData(False)
            yDY = self.t.GetYield(self.GetDYfiles(), 'ElMu')
            yDYe = self.t.GetYieldStatUnc(self.GetDYfiles(), 'ElMu')
            SF, err = self.GetScaleFactor('ElMu')
            N = yDY * SF
            Nerr = N * SumSquare([
                err / SF if SF != 0 else err, yDYe / yDY if yDY != 0 else yDYe
            ])
        if N < 0:
            N = 0
            Nerr = 0
        if not Nerr == Nerr: Nerr = 0
        return N, Nerr

    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 == muname or chan == elname:
            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(elname)
            m, mr = self.GetScaleFactor(muname)
            SF = sqrt(e * m)
            err = SF * SumSquare(
                [er / e if e != 0 else 0, mr / m if m != 0 else 0])
        return SF, err

    def PrintDYestimate(self, doSF=False, name='', level=''):
        self.SetChanAndLevel('', level)
        self.SetMode('SF' if doSF else 'OF')
        if name == '':
            name = 'DYDD_%s_%s' % ('SF' if doSF else 'OF', self.GetLevel())
        t = OutText(self.GetOutPath(), name)
        t.SetSeparatorLength(20 + (3 + 22) * 3)
        t.SetDefaultFixOption(False)
        t.line('Drell-Yan estimate for %s and level \'%s\'' %
               ('SF channels' if doSF else 'all channels (no MET cut) ',
                self.GetLevel()))
        t.bar()
        s = lambda tit, vee, vmm, vem: t.line(
            t.fix(tit, 20) + t.vsep() + t.fix(vee, 22, 'c') + t.vsep() + t.fix(
                vmm, 22, 'c') + t.vsep() + t.fix(vem, 22, 'c'))
        v = lambda val, err: '%1.3f' % val + t.pm() + '%1.3f' % err
        d = lambda val, err: '%1.0f' % val + t.pm() + '%1.2f' % err
        s('', elname, muname, 'ElMu')
        t.sep()
        mie, miee = self.GetMCin(elname)
        moe, moee = self.GetMCout(elname)
        mim, mime = self.GetMCin(muname)
        mom, mome = self.GetMCout(muname)
        s(' N_in        (MC)', v(mie, miee), v(mim, mime), '')
        s(' N_out       (MC)', v(moe, moee), v(mom, mome), '')

        re, ree = self.GetRoutin(elname)
        rm, rme = self.GetRoutin(muname)
        s(' R_(out/in)  (MC)', v(re, ree), v(rm, rme), '')

        ke, kee = self.GetKfactor(elname)
        km, kme = self.GetKfactor(muname)
        s(' k_ll            ', v(ke, kee), v(km, kme), '')

        ie, ier = self.GetDataIn(elname)
        im, imr = self.GetDataIn(muname)
        iem, iemr = self.GetDataIn('ElMu')
        s(' N_in      (Data)', d(ie, ier), d(im, imr), d(iem, iemr))
        t.sep()
        dde, ddee = self.GetDYDD(elname)
        ddm, ddme = self.GetDYDD(muname)
        tmc = ' DY estimate out (MC) ' if doSF else ' DY estimate (MC)'
        tdata = ' DY estimate out (DD) ' if doSF else ' DY estimate (DD)'
        if doSF:
            s(' DY estimate (MC)', v(moe, moee), v(mom, mome), '')
            s(' DY estimate (DD)', v(dde, ddee), v(ddm, ddme), '')
        else:
            ddem, ddeme = self.GetDYDD('ElMu')
            yDY = self.t.GetYield(self.GetDYfiles(), 'ElMu')
            yDYe = self.t.GetYieldStatUnc(self.GetDYfiles(), 'ElMu')
            s(' DY estimate (MC)', v(moe, moee), v(mom, mome), v(yDY, yDYe))
            s(' DY estimate (DD)', v(dde, ddee), v(ddm, ddme), v(ddem, ddeme))
        t.sep()
        sfee, sfeee = self.GetScaleFactor(elname)
        sfmm, sfmme = self.GetScaleFactor(muname)
        if doSF:
            s(' DD/MC ratio     ', v(sfee, sfeee), v(sfmm, sfmme), '')
        else:
            sfem, sfeme = self.GetScaleFactor('ElMu')
            s(' DD/MC ratio     ', v(sfee, sfeee), v(sfmm, sfmme),
              v(sfem, sfeme))
        t.bar()
        t.write()

    def PrintDYSFnjets(self):
        t = OutText(self.GetOutPath(), 'DYSF_njets')
        t.SetSeparatorLength(22 + (3 + 16) * 3)
        t.SetDefaultFixOption(False)
        t.line(
            'Drell-Yan data/MC scale factors for different jet multiplicities')
        t.bar()
        s = lambda tit, vee, vmm, vem: t.line(
            t.fix(tit, 22) + t.vsep() + t.fix(vee, 16, 'c') + t.vsep() + t.fix(
                vmm, 16, 'c') + t.vsep() + t.fix(vem, 16, 'c'))
        v = lambda val, err: '%1.2f' % val + t.pm() + '%1.2f' % err
        s('', elname, muname, 'ElMu')
        t.sep()
        #labels = ['Inclusive','== 1 jet', '== 2 jets', '>= 3 jets','>= 2 jets, >= 1 btag', '>= 2 btag']
        #levels = ['dilepton', 'eq1jet', 'eq2jet', 'geq3jet','1btag', '2btag']
        labels = ['Inclusive', '>= 2 jets', ' >= 1 btag']
        levels = ['dilepton', '2jets', '1btag']
        for i in range(len(labels)):
            if i == 4: t.sep()
            lab = labels[i]
            lev = levels[i]
            sfe, sfee = self.GetScaleFactor(elname, lev, 'SF')
            sfm, sfme = self.GetScaleFactor(muname, lev, 'SF')
            sfo, sfoe = self.GetScaleFactor('ElMu', lev, 'OF')
            s(' ' + lab,
              v(sfe, sfee) if sfe > 0 else '-',
              v(sfm, sfme) if sfm > 0 else '-',
              v(sfo, sfoe) if sfo > 0 else '-')
        t.bar()
        t.write()

    def __init__(self,
                 path,
                 outpath='./temp/',
                 chan='ElMu',
                 level='2jets',
                 DYsamples='DYJetsToLL_M_10to50,DYJetsToLL_MLL50',
                 DataSamples='HighEGJet,SingleMuon, DoubleMuon',
                 lumi=308.54,
                 massRange=[91 - 15, 91 + 15],
                 mode='',
                 histonameprefix='H',
                 hname='DY_InvMass'):
        self.SetPath(path)
        self.SetOutPath(outpath)
        self.t = TopHistoReader(path)
        self.t.SetHistoNamePrefix(histonameprefix)
        self.SetLumi(lumi)
        self.SetChanAndLevel(chan, level)
        self.SetDYsamples(DYsamples)
        self.SetDataSamples(DataSamples)
        self.SetMassRange(massRange[0], massRange[1])
        self.SetHistoNameOF()
        self.SetHistoNameSF()
        if chan == 'ElMu':
            if hname != '': self.SetHistoNameOF(hname)
            self.SetMode('OF')
        else:
            if hname != '': self.SetHistoNameSF(hname)
            self.SetMode('SF')
        if mode != '': self.SetMode(mode)
Exemple #9
0
        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


from wzanalysis.wzanalysis import lev, level, ch, chan

#path = '/pool/ciencias/nanoAODv4/5TeV/5TeV_21nov2019/'
path = '/nfs/fanae/user/joanrs/xuAnalysis/tempWZ8/'
#process = ['WZTo3LNU_NNPDF30_TuneCP5_5p20TeV','DYJetsToLL_MLL_50_TuneCP5_5020GeV_amcatnloFXFX','DYJetsToLL_M_10to50_TuneCP5_5020GeV_amcatnloFXFX','ZZTo2L2Nu_5p02TeV','ZZTo4L_5p02TeV','WWTo2L2Nu_NNPDF31_TuneCP5_5p02TeV', 'tW_5f_noFullHad_TuneCP5_PSweights_5p02TeV_py, tW_5f_noFullHad_TuneCP5_5p02TeV', 'tbarW_5f_noFullHad_TuneCP5_PSweights_5p02TeV_powhe, tbarW_5f_noFullHad_TuneCP5_5p02TeV', 'TT_TuneCP5_PSweights_5p02TeV' ]
t = TopHistoReader(path)
t.SetLumi(Lumi)
PR = []
TT = []
DY = []
VV = []
WZ = []
Da = []
ZZ = []
WW = []
#process  = ['WZTo3LNU']
process = [
    'WZTo3LNU', 'DYJetsToLL_MLL50', 'DYJetsToLL_M_10to50', 'ZZTo2L2Nu',
    'ZZTo4L', 'WWTo2L2Nu', 'tW_noFullHad', 'tbarW_noFullHad', 'TT',
    'HighEGJet', 'SingleMuon'
]
    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'))
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("")
               3.5,
               weight='TWeight_%s%i' % (tag, i),
               cut='')

histos = [
    'mt2', 'met', 'mll', 'dnn', 'dileppt', 'deltaphi', 'deltaeta', 'ht',
    'lep0pt', 'lep1pt', 'lep0eta', 'lep1eta', 'njets', 'nbtags', 'jet0pt',
    'jet1pt', 'jet0eta', 'jet1eta'
]
histos += ['dnn_5bins', 'dnn_10bins', 'dnn_30bins', 'dnn_40bins']

out = l.Run()

if sendJobs: exit()

t = TopHistoReader(outpath + 'tempfiles/')
print "Creating outputs in %s ..." % outpath
for var in histos:
    PDFhistosNom = t.GetNamedHisto(var + '_PDF0', 'tt')
    PDFhistos = [
        t.GetNamedHisto(var + '_PDF%i' % i, 'tt')
        for i in range(1, nPDFweights - 2 if year != 2016 else nPDFweights)
    ]
    AlphaShistos = [
        t.GetNamedHisto(var + '_PDF%i' % (nPDFweights - 2), 'tt'),
        t.GetNamedHisto(var + '_PDF%i' % (nPDFweights - 1), 'tt')
    ] if year != 2016 else []
    pdfNom, pdfUp, pdfDown = GetPDFuncHisto(PDFhistosNom,
                                            PDFhistos,
                                            AlphaShistos,
                                            prName='tt',
Exemple #13
0
class NonpromptDD:

    ### Set methods
    def SetPath(self, p):
        if not p.endswith('/'): p += '/'
        self.path = p

    def SetOutPath(self, p):
        self.outpath = p

    def SetLumi(self, l):
        self.lumi = l
        self.t.SetLumi(self.lumi)

    def SetChannel(self, c):
        self.chan = c

    def SetLevel(self, l):
        self.level = l

    def SetChanAndLevel(self, chan='', level=''):
        ''' Manages to set chan and leve to the class and the TopHistoReader '''
        if chan != '': self.SetChannel(chan)
        if level != '': self.SetLevel(level)
        self.t.SetChan(self.GetChan())
        self.t.SetLevel(self.GetLevel())
        return self.GetChan(), self.GetLevel()

    ### Get methods
    def GetPath(self):
        return self.path

    def GetOutPath(self):
        return self.outpath

    def GetLevel(self):
        return self.level

    def GetChan(self):
        return self.chan

    ### Calculate quantities...

    def GetYield(self, process, chan='', level='', SS=False):
        if process == 'Data' or process == 'data': self.t.SetIsData(True)
        if process in self.process.keys(): process = self.process[process]
        chan, lev = self.SetChanAndLevel(chan, level)
        y = self.t.GetYield(process, chan, level, SS=SS)
        err = self.t.GetYieldStatUnc(process, chan, level, SS=SS)
        self.t.SetIsData(False)
        if y < 0:  # Negative weights...
            y = 0
            err = 0
        return y, err

    def GetSS(self, process, chan='', level=''):
        return self.GetYield(process, chan, level, True)

    def GetROSSS(self, process, chan='', level=''):
        ''' Returns the OS to SS ratio for process '''
        OS, OSe = self.GetYield(process, chan, level)
        SS, SSe = self.GetSS(process, chan, level)
        R = OS / SS if SS != 0 else 1
        e = R * SumSquare(
            [OSe / OS if OS != 0 else 0, SSe / SS if SS != 0 else 0])
        return R, e

    def GetNonpromptDD(self, chan='', level=''):
        chan, lev = self.SetChanAndLevel(chan, level)
        R, Re = self.GetROSSS(
            [self.process[lab] for lab in self.nonpromptProcess])
        BkgSS, BkgSSe = self.GetSS(
            [self.process[lab] for lab in self.promptProcess])
        DataSS, DataSSe = self.GetSS('data')
        y = R * (DataSS - BkgSS)
        e = y * SumSquare([
            Re / R if R != 0 else 0, (DataSSe + BkgSSe) / (DataSS - BkgSS) if
            (DataSS - BkgSS != 0) else 0
        ])
        return y, e

    ## Print tables
    def PrintSSyields(self, name='', level=''):
        self.SetChanAndLevel('', level)
        if name == '': name = 'SameSign_%s' % (self.GetLevel())
        t = OutText(self.GetOutPath(), name)
        t.SetSeparatorLength(12 + (3 + 16) * 3)
        t.SetDefaultFixOption(False)
        t.line('Same-sign yields for level of selection \'%s\'' %
               (self.GetLevel()))
        t.bar()
        s = lambda tit, vee, vmm, vem: t.line(
            t.fix(tit, 10) + t.vsep() + t.fix(vee, 16, 'c') + t.vsep() + t.fix(
                vmm, 16, 'c') + t.vsep() + t.fix(vem, 16, 'c'))
        v = lambda L: '%1.2f' % L[0] + t.pm() + '%1.2f' % L[1]
        d = lambda L: '%1.0f' % L[0] + t.pm() + '%1.2f' % L[1]
        S = lambda tit, pr: s(tit, v(self.GetSS(pr, elecName)),
                              v(self.GetSS(pr, muName)),
                              v(self.GetSS(pr, 'ElMu')))
        D = lambda tit, pr: s(tit, d(self.GetSS(pr, elecName)),
                              d(self.GetSS(pr, muName)),
                              d(self.GetSS(pr, 'ElMu')))
        s('', elecName, muName, 'ElMu')
        t.sep()
        for pr in self.promptProcess:
            S(pr, pr)
        #S('tt signal', 'tt')
        #S('tW','tW')
        #S('Drell-Yan','DY')
        #S('Dibosons','VV')
        t.sep()
        for pr in self.nonpromptProcess:
            S(pr, pr)
        #S('W+Jets', 'WJets')
        #S('tt semilep', 'ttsemilep')
        t.sep()
        S('Total MC', [
            self.process[lab]
            for lab in self.promptProcess + self.nonpromptProcess
        ])
        t.sep()
        D('Data', 'data')
        t.bar()
        t.write()

    def PrintNonpromptEstimate(self, name='', chan='', level=''):
        chan, lev = self.SetChanAndLevel(chan, level)
        if name == '':
            name = 'NonpromptDD_%s_%s' % (self.GetChan(), self.GetLevel())
        t = OutText(self.GetOutPath(), name)
        t.SetSeparatorLength(55 + 20)
        t.SetDefaultFixOption(False)
        t.line(
            ' Nonpromt estimate from a same-sign control retion\nfor channel \'%s\' and level of selection \'%s\''
            % (chan, lev))
        t.bar()
        s = lambda tit, vee, vmm, vem: t.line(
            t.fix(tit, 10) + t.vsep() + t.fix(vee, 16, 'c') + t.vsep() + t.fix(
                vmm, 16, 'c') + t.vsep() + t.fix(vem, 16, 'c'))
        v = lambda L: '%1.2f' % L[0] + t.pm() + '%1.2f' % L[1]
        d = lambda L: '%1.0f' % L[0] + t.pm() + '%1.2f' % L[1]
        pr = [self.process[p] for p in self.nonpromptProcess]
        sr = [self.process[p] for p in self.promptProcess]
        t.line(
            t.fix(' MC nonprompt estimate (OS W+Jets and semilpetonic tt)', 55)
            + t.vsep() + v(self.GetYield(pr)))
        t.sep()
        t.line(
            t.fix(' MC nonprompt SS (W+Jets and semilpetonic tt)', 55) +
            t.vsep() + v(self.GetSS(pr)))
        t.line(
            t.fix(' R = nonpromt(OS)/nonprompt(SS)', 55) + t.vsep() +
            v(self.GetROSSS(pr)))
        t.line(
            t.fix(' BkgSS = MC prompt SS (other sources)', 55) + t.vsep() +
            v(self.GetSS(sr)))
        t.line(
            t.fix(' DataSS = Obseved data SS', 55) + t.vsep() +
            v(self.GetSS('data')))
        t.sep()
        t.line(
            t.fix(' Nonprompt data-driven estimate = R(DataSS-BkgSS)', 55) +
            t.vsep() + v(self.GetNonpromptDD()))
        t.bar()
        t.write()

    ### Init
    def __init__(self,
                 path,
                 outpath='./temp/',
                 chan='ElMu',
                 level='2jets',
                 process={},
                 prompt=[],
                 nonprompt=[],
                 lumi=304.32,
                 histonameprefix='H',
                 yieldsSSname='SSYields'):
        self.SetPath(path)
        self.t = TopHistoReader(self.GetPath())
        self.t.SetHistoNamePrefix(histonameprefix)
        self.t.SetYieldsSSname(yieldsSSname)
        self.SetLumi(lumi)
        self.SetOutPath(outpath)
        self.SetChanAndLevel(chan, level)
        self.process = process
        self.nonpromptProcess = []
        self.promptProcess = []
        if prompt == [] or nonprompt == []:
            for pr in process.keys():
                if pr in ['data', 'Data', 'DATA']: continue
                elif pr in [
                        'fake', 'nonprompt', 'Nonprompt', 'NonPrompt', 'Fake',
                        'fakes', 'Fakes'
                ]:
                    self.nonpromptProcess.append(pr)
                else:
                    self.promptProcess.append(pr)
        else:
            self.promptProcess = prompt
            self.nonpromptProcess = nonprompt
def DrawPostFit(ms=235, ml=60, htype='fit_s', var='dnn', ch='', year=''):
    getdir = lambda dirtype, ch: 'shapes_%s/%s/' % (dirtype, ch)
    getfname = lambda ms, ml: 'postfit_%s_%s_%s' % (var, str(ms), str(ml))

    # Get channels
    if not isinstance(ch, list):
        if ch == '': ch = ['ee', 'mumu', 'emu']
        elif ',' in ch: ch = ch.replace(' ', '').split(',')
        else: ch = [ch]
    if not isinstance(year, list):
        if year == '': year = [2016, 2017, 2018]
        elif isinstance(year, str) and ',' in year:
            year = year.replace(' ', '').split(',')
        else:
            year = [year]
    pch = []
    for y in year:
        for c in ch:
            pch.append(chdic[y][c])

    if len(year) == 3: yearname = 'comb'
    else: yearname = str(year[0])
    if len(ch) == 3: chname = 'all'
    else: chname = ch[0]

    # test or not depending on var
    ttname = 'tt' if not 'dnn' in var else 'tt_test'
    pr = bkg + [ttname]
    sig = ('stop'
           if not 'dnn' in var else 'stop_test') if htype != 'fit_b' else []

    hm = HistoManager(pr, '', path=pathToPostFit, signalList=sig)
    pathInTree = [getdir(htype, x) for x in pch]
    hm.SetPathInTree(pathInTree)
    hm.ReadHistosFromFile(getfname(ms, ml), dataname='data', rebin=1)
    hm.ReArrangeDic({
        'Others': ['ttW', 'ttZ', 'Nonprompt', 'VV'],
        't#bar{t}+tW': ['tW', ttname],
        'Drell-Yan': ['DY']
    })
    hm.GetDataHisto()
    #hm.indic['data_obs']['data_obs'] = hm.GetSumBkg()
    outdir = GetOutpath(region, year, ms, ml, ch)
    fprocess = ['Others', 'Drell-Yan', 't#bar{t}+tW']
    s = Stack(outpath=outdir + '/postfit/')
    colors['Others'] = kTeal + 2
    colors['t#bar{t}+tW'] = colors['tt']
    colors['Drell-Yan'] = colors['DY']
    s.SetColors(colors)
    s.SetProcesses(fprocess)
    s.SetLumi(
        GetLumi(year[0]) if len(year) == 1 else (GetLumi(2016) +
                                                 GetLumi(2017) +
                                                 GetLumi(2018)))
    outname = htype + '_' + var + '%s_%s_%i_%i' % (yearname, chname, ms, ml)
    s.SetOutName(outname)
    s.SetHistosFromMH(hm)
    #s.Set
    t = TopHistoReader(pathToPostFit)
    t.ReComputeStatUnc = False
    t.SetPathInTree(pathInTree)
    hbkg = t.GetNamedHisto('total_background', getfname(ms, ml))
    hbkg.SetLineStyle(0)
    hbkg.SetLineWidth(0)
    hbkg.SetMarkerSize(0)

    s.SetTotMC(hbkg)
    s.SetMCunc(hbkg)
    s.SetMCstatUnc(None)
    s.SetMCnormUnc(None)

    s.SetRatioStatUnc(None)
    s.SetRatioNormUnc(None)
    s.SetRatioUnc(GetRatioHistoUncFromHisto(hbkg))

    s.SetRatioUncStyle()
    s.SetUncStyle()

    if sig != []:
        s.AddSignalHisto(hm.indic[sig][sig],
                         color=kViolet + 2,
                         mode='ontop',
                         ratioBkg=True,
                         name='stop')
    s.SetTextChan('SR: BS + p_{T}^{miss} #geq 50, m_{T2} #geq 80')
    s.SetRatioMin(0.5)
    s.SetRatioMax(1.5)
    s.SetPlotMaxScale(1.8)
    xtit = 'DNN score (%i, %i)' % (ms, ml)
    chlab = ''
    if chname == 'ee': chlab = 'ee'
    elif chname == 'mumu': chlab = '#mu#mu'
    elif chname == 'emu': chlab = 'e#mu'
    flab = 'Prefit'
    if htype == 'fit_b': flab = 'Fit background only'
    elif htype == 'fit_s': flab = 'Fit S+B'
    mlab = '#splitline{m_{#tilde{t}_{1}} = %1.0f GeV}{m_{#tilde{#chi}_{1}^{0}} = %1.0f GeV}' % (
        ms, ml)
    s.AddTex(flab, x=0.15, y=0.77, s=0.05)
    s.AddTex(mlab, x=0.15, y=0.62, s=0.04)
    s.AddTex(chlab, x=0.15, y=0.84, s=0.04)
    s.DrawStack(xtit, 'Events')
    s.SetLogY()
    s.SetZoom(False)
    if var == 'dnn' and region == 'SR':
        s.SetZoom(True)
    s.SetOutName('log_' + outname)
    s.SetPlotMinimum(1)
    s.SetPlotMaxScale(1200)
    s.SetYratioTitle('Ratio')
 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
import os, sys
from conf import *
basepath = os.path.abspath(__file__).rsplit('/xuAnalysis/',
                                            1)[0] + '/xuAnalysis/'
sys.path.append(basepath)
from plotter.TopHistoReader import TopHistoReader, HistoManager
from plotter.Plotter import Stack, HistoComp
from ROOT.TMath import Sqrt as sqrt
from ROOT import kRed, kOrange, kBlue, kTeal, kGreen, kGray, kAzure, kPink, kCyan, kBlack, kSpring, kViolet, kYellow
from ROOT import TCanvas, gROOT
gROOT.SetBatch(1)

tr1 = TopHistoReader(path=path[2016])
tr2 = TopHistoReader(
    path=path[2018]
)  #'/pool/ciencias/userstorage/juanr/top/2016/nov15/') # TOP-17-001

s = HistoComp(outpath='./temp/', doNorm=True, doRatio=True)
s.autoRatio = True
s.SetTextLumi('Normalized distributions', texlumiX=0.12)

hname = 'H_NJets_ElMu_dilepton'
s.AddHisto(tr1.GetNamedHisto(hname, 'TT'),
           'hist',
           'hist',
           '2016',
           color=kAzure + 2)
s.AddHisto(tr2.GetNamedHisto(hname, 'TTTo2L2Nu'),
           'hist',
           'hist',
           '2018',