Esempio n. 1
0
def MakeMacroRegionPlot(macro_reg,
                        datacard_dir,
                        datacard_name,
                        outdir,
                        userMax=None):
    # based on MakePlot, but here we want to sum over several cards

    topo_regs = utils.GetMacroregions(macro_reg)  #arbitrary set

    #list of lists, one per maco region, of low edges of MT2 bins
    mt2bins = []
    for topo_reg in topo_regs:
        bins = utils.GetMT2binsFull(topo_reg)
        mt2bins.append(bins)

    bkg_processes = ["zinv", "llep", "qcd"]
    nBkgs = len(bkg_processes)

    # MT2 binning we want to use: let's take the region with the highest number of bins
    xbins = mt2bins[0]  #start with the first region
    for tempmt2bins in mt2bins:
        if (len(xbins) < len(tempmt2bins)): xbins = tempmt2bins
    xbinsA = array('d', xbins)
    xbinsA[len(xbinsA) - 1] = 1800  # set last bin
    nBinsTotal = len(xbinsA) - 1

    ## setup histograms
    h_data = ROOT.TH1D("h_data", "", len(xbinsA) - 1, xbinsA)
    h_bkg_tot = ROOT.TH1D("h_tot", "", len(xbinsA) - 1, xbinsA)
    h_bkg_vec = []
    for i, proc in enumerate(bkg_processes):
        h_bkg_vec.append(ROOT.TH1D("h_" + proc, "", len(xbinsA) - 1, xbinsA))
    h_unc = ROOT.TH1D("h_unc", "",
                      len(xbinsA) - 1,
                      xbinsA)  #  store prediction uncertainties
    h_unc_ratio = ROOT.TH1D("h_unc_ratio", "",
                            len(xbinsA) - 1,
                            xbinsA)  #  store prediction uncertainties

    ## fill histograms
    ibin = 0
    binLabels = []

    #    for ijbj, jbj_reg in enumerate(jbj_regs):
    datacard_list = []
    for imt2 in range(len(xbinsA) - 1):
        datacard_list.append([])

    for itopo, topo_reg in enumerate(topo_regs):

        ibin = 0
        for imt2 in range(len(mt2bins[itopo]) - 1):
            ibin += 1
            mt2left = mt2bins[itopo][imt2]
            mt2right = mt2bins[itopo][imt2 + 1]
            if mt2right == 1800: mt2right = "Inf"
            mt2name = utils.GetMT2name(mt2left, mt2right)
            datacard_name_fmt = datacard_name.format(topo_reg, mt2name)
            datacard_list[imt2].append(
                os.path.join(datacard_dir, datacard_name_fmt))

            # get yields. first entry is data, rest are background predictions
            #print datacard_name_fmt
            yields = utils.GetYieldsFromDatacard(
                os.path.join(datacard_dir, datacard_name_fmt), bkg_processes)
            #print yields[0]
            h_data.SetBinContent(ibin, h_data.GetBinContent(ibin) + yields[0])
            for j in range(1, nBkgs + 1):
                h_bkg_vec[j - 1].SetBinContent(
                    ibin, h_bkg_vec[j - 1].GetBinContent(ibin) + yields[j])
            tot_pred = sum(yields[1:])
            h_bkg_tot.SetBinContent(ibin,
                                    h_bkg_tot.GetBinContent(ibin) + tot_pred)

            # get uncertainties
            pred_unc = utils.GetUncertaintiesFromDatacard(
                os.path.join(datacard_dir, datacard_name_fmt), bkg_processes)
            tot_unc_up = ROOT.TMath.Sqrt(
                sum([(pred_unc[i][0] * yields[i + 1])**2
                     for i in range(nBkgs)]))
            tot_unc_down = ROOT.TMath.Sqrt(
                sum([(pred_unc[i][1] * yields[i + 1])**2
                     for i in range(nBkgs)]))
            tot_unc_sym = max(tot_unc_up, tot_unc_down)
            #            h_unc.SetBinContent(ibin, h_unc.GetBinContent(ibin) + tot_unc_sym) # treat as fully correlated for now
            h_unc.SetBinContent(ibin,
                                h_unc.GetBinContent(ibin) +
                                tot_unc_sym * tot_unc_sym)  # sum in quadrature
            #print tot_pred, tot_unc_up, tot_unc_down

    h_bkg_vec[0].SetFillColor(418)
    h_bkg_vec[1].SetFillColor(ROOT.kAzure + 4)
    h_bkg_vec[2].SetFillColor(401)

    # Outdated: simple sum in quadrature
    #for imt2 in range(len(xbinsA)-1):
    #    h_unc_ratio.SetBinContent(imt2+1, h_data.GetBinContent(imt2+1)/h_bkg_tot.GetBinContent(imt2+1))
    #    h_unc_ratio.SetBinError(imt2+1, ROOT.TMath.Sqrt(h_unc.GetBinContent(imt2+1))/h_bkg_tot.GetBinContent(imt2+1))
    #    h_unc.SetBinError(imt2+1, ROOT.TMath.Sqrt(h_unc.GetBinContent(imt2+1)))
    #    h_unc.SetBinContent(imt2+1, h_bkg_tot.GetBinContent(imt2+1))

    for imt2 in range(len(xbinsA) - 1):
        unc = utils.getMacroRegionUncertainties("test" + str(imt2),
                                                datacard_list[imt2])
        h_unc_ratio.SetBinContent(
            imt2 + 1,
            h_data.GetBinContent(imt2 + 1) / h_bkg_tot.GetBinContent(imt2 + 1))
        h_unc_ratio.SetBinError(imt2 + 1,
                                unc / h_bkg_tot.GetBinContent(imt2 + 1))
        h_unc.SetBinError(imt2 + 1, unc)
        h_unc.SetBinContent(imt2 + 1, h_bkg_tot.GetBinContent(imt2 + 1))

    stack = ROOT.THStack("bkg_stack", "")
    for j in range(nBkgs):
        h_bkg_vec[nBkgs - 1 - j].SetLineWidth(1)
        h_bkg_vec[nBkgs - 1 - j].SetLineColor(ROOT.kBlack)
        stack.Add(h_bkg_vec[nBkgs - 1 - j])


#    h_bkg_tot.Print("all")
#    h_unc.Print("all")
#    h_unc_ratio.Print("all")
    h_data.Print("all")

    h_data.SetMarkerStyle(20)
    h_data.SetMarkerSize(1.3)
    h_data.SetMarkerColor(ROOT.kBlack)
    h_data.SetLineColor(ROOT.kBlack)

    ROOT.gStyle.SetOptStat(0)
    ROOT.gStyle.SetLineWidth(1)
    c = ROOT.TCanvas("c", "c", 600, 600)

    pads = []
    pads.append(ROOT.TPad("1", "1", 0.0, 0.18, 1.0, 1.0))
    pads.append(ROOT.TPad("2", "2", 0.0, 0.0, 1.0, 0.19))

    pads[0].SetTopMargin(0.08)
    pads[0].SetBottomMargin(0.13)
    pads[0].SetRightMargin(0.05)
    pads[0].SetLeftMargin(0.10)

    pads[1].SetRightMargin(0.05)
    pads[1].SetLeftMargin(0.10)

    pads[0].Draw()
    pads[1].Draw()
    pads[0].cd()

    pads[0].SetLogy(1)
    # pads[0].SetTickx(1)
    pads[1].SetTickx(1)
    pads[0].SetTicky(1)
    pads[1].SetTicky(1)

    yMin = 1e-1
    if userMax != None:
        yMax = userMax
    else:
        yMax = h_data.GetMaximum()**(2.0)
    h_data.GetYaxis().SetRangeUser(yMin, yMax)
    h_data.GetYaxis().SetTitle("Events / Bin")
    h_data.GetYaxis().SetTitleOffset(1.2)
    h_data.GetYaxis().SetTickLength(0.02)
    #h_data.GetXaxis().SetLabelSize(0)
    h_data.GetXaxis().SetTickLength(0.015)
    h_data.GetXaxis().SetTitle("MT2 [GeV]")
    h_data.GetXaxis().SetTitleSize(0.04)
    h_data.GetXaxis().SetLabelSize(0.036)
    h_data.GetXaxis().SetTitleOffset(1.2)

    # just draw dots to get axes. Will draw TGraphAsymmErrors on top later
    h_data.SetMarkerStyle(1)
    h_data.Draw("P")

    # draw the backgrounds
    stack.Draw("SAME HIST")

    # draw the prediction uncertainties
    h_unc.SetFillStyle(3244)
    h_unc.SetFillColor(ROOT.kGray + 3)
    h_unc.Draw("SAME E2")

    # get a graph using proper asymmetric poissonian errors
    g_data = ROOT.TGraphAsymmErrors()
    ppmUtils.ConvertToPoissonGraph(h_data, g_data, drawZeros=True)
    #    g_data.SetPointError(g_data.GetN()-1, 0, 0, 0, 0)
    g_data.SetMarkerStyle(20)
    g_data.SetMarkerSize(1.2)
    g_data.SetLineWidth(1)

    # draw the graph and then axes again on top
    g_data.Draw("SAME P")
    h_data.Draw("SAME AXIS")

    # save for later
    left = pads[0].GetLeftMargin()
    right = pads[0].GetRightMargin()
    top = pads[0].GetTopMargin()
    bot = pads[0].GetBottomMargin()

    text = ROOT.TLatex()
    text.SetNDC(1)

    # draw the "Pre-fit background" text
    text.SetTextAlign(13)
    text.SetTextFont(42)
    text.SetTextAngle(0)
    text.SetTextSize(0.05)
    text.DrawLatex(left + 0.04, 1 - top - 0.01, "Pre-fit background")

    # draw the HT bin  in upper middle
    text.SetTextAlign(21)
    text.SetTextFont(62)
    text.SetTextAngle(0)
    text.SetTextSize(0.035)
    #    text.DrawLatex(left+(1-right-left)*0.5, 1-top-0.01-0.04, utils.GetHTtitle(ht_reg))
    text.DrawLatex(left + (1 - right - left) * 0.3, 1 - top - 0.01 - 0.09,
                   utils.GetMacroregionTitle(macro_reg))

    # Draw the CMS and luminosity text
    ppmUtils.DrawCmsText(pads[0], text="CMS Preliminary", textSize=0.038)
    ppmUtils.DrawLumiText(pads[0], lumi=utils.lumi, textSize=0.038)

    # legend
    leg = ROOT.TLegend(1 - right - 0.175, 1 - top - 0.23, 1 - right - 0.02,
                       1 - top - 0.01)
    leg.SetBorderSize(1)
    leg.SetCornerRadius(0.3)
    leg.AddEntry(g_data, "Data", "lp")
    for i in range(nBkgs):
        leg.AddEntry(h_bkg_vec[i], utils.GetLegendName(bkg_processes[i]), 'f')
    leg.Draw()

    ####################
    #### RATIO PLOT ####
    ####################

    pads[1].cd()
    h_ratio = h_bkg_vec[0].Clone(
        "h_ratio")  #h_ratio is just a dummy histogram to draw axes correctly
    h_ratio.Reset()
    g_ratio = ROOT.TGraphAsymmErrors()
    h_pred = h_bkg_tot.Clone("h_pred")
    ppmUtils.GetPoissonRatioGraph(h_pred,
                                  h_data,
                                  g_ratio,
                                  drawZeros=True,
                                  useMCErr=False)
    h_ratio.GetYaxis().SetRangeUser(0, 2)
    h_ratio.GetYaxis().SetNdivisions(505)
    h_ratio.GetYaxis().SetTitle("Data/Pred.")
    h_ratio.GetYaxis().SetTitleSize(0.16)
    h_ratio.GetYaxis().SetTitleOffset(0.25)
    h_ratio.GetYaxis().SetLabelSize(0.13)
    h_ratio.GetYaxis().CenterTitle()
    h_ratio.GetYaxis().SetTickLength(0.02)
    h_ratio.GetXaxis().SetLabelSize(0)
    h_ratio.GetXaxis().SetTitle("")
    #h_ratio.GetXaxis().SetNdivisions(nBinsTotal,0,0)
    h_ratio.GetXaxis().SetTickSize(0.06)
    g_ratio.SetMarkerStyle(20)
    g_ratio.SetMarkerSize(1.0)
    g_ratio.SetLineWidth(1)

    h_unc_ratio.SetFillStyle(1001)
    h_unc_ratio.SetFillColor(ROOT.kGray)
    h_ratio.Draw()
    h_unc_ratio.Draw("SAME E2")

    # draw line at 1
    line = ROOT.TLine()
    line.SetLineStyle(1)
    line.SetLineWidth(1)
    line.SetLineColor(ROOT.kGray + 2)
    line.DrawLine(xbinsA[0], 1, xbinsA[len(xbinsA) - 1], 1)

    h_ratio.Draw("SAME AXIS")
    g_ratio.Draw("SAME P0")

    name = "MacroRegion_{0}".format(macro_reg)
    try:
        os.makedirs(outdir)
    except:
        pass
    c.SaveAs(os.path.join(outdir, name + ".pdf"))
    c.SaveAs(os.path.join(outdir, name + ".png"))

    h_data.Delete()
    g_data.Delete()
    h_ratio.Delete()
    g_ratio.Delete()
    for h in h_bkg_vec:
        h.Delete()
Esempio n. 2
0
def plotDataMC(h_bkg_vec_, bkg_names, h_data=None, title=None, subtitles=None, ratioTitle=None, doRatio=False, yRangeUserRatio=None, scaleMCtoData=False, saveAs=None, 
               isLog=True, dataTitle="Data", xRangeUser=None, doPause=False, lumi=1.0, lumiUnit="fb", noLumi=False,
               energy=13, xAxisTitle="H_{T}", xAxisUnit="GeV", userMax=None, userMin=None, doSort=False,
               doMT2Colors=False, markerSize=0.9, doOverflow=True, titleSize=0.04, subtitleSize=0.03, subLegText=None,
               subLegTextSize=0.03, cmsText="CMS Preliminary", cmsTextSize=0.035, doBkgError=False, functions=[], 
               legCoords=None, doPull=False, convertToPoisson=False, drawZeros=True, drawSystematicBand=False, systematics=None,
               h_sig_vec=[], sig_names=[], customColors=None, verticalLines=[], ratioType=0):    

    if h_data == None:
        doRatio = False
        scaleMCtoData = False
        
    if customColors!=None and len(customColors) < len(h_bkg_vec_):
        raise RuntimeError("Not enough colors for all backgrounds! {0} colors, {1} backgrounds.".format(len(customColors),len(h_bkg_vec_)))

    if drawSystematicBand and systematics==None:
        raise RuntimeError("Must supply a list of systematics to draw uncertainty band!")

    if systematics != None and len(systematics) != h_bkg_vec_[0].GetNbinsX():
        raise RuntimeError("length of systematics list does not equal the number of bins!")
        
    # make shallow copies of hists so we don't overwrite the originals
    h_bkg_vec = [ROOT.TH1D() for h in h_bkg_vec_]
    for i in range(len(h_bkg_vec_)):
        h_bkg_vec_[i].Copy(h_bkg_vec[i])
    if h_data != None:
        if type(h_data) != type(list()):
            h_data = [h_data]
        if len(h_data) > 4:
            print h_data
            raise RuntimeError("currently only supports up to 4 data histograms!")
        h_data_ = [ROOT.TH1D() for h in h_data]
        for i in range(len(h_data)):
            h_data[i].Copy(h_data_[i])
            h_data[i] = h_data_[i]  #so the arg name doesn't have underscore

    ROOT.gStyle.SetOptStat(0)
     
    #### setup canvas and pads ####

    c = ROOT.TCanvas()
    
    if doRatio:
        c.SetCanvasSize(700,600)
        pads = []
        pads.append(ROOT.TPad("1","1",0.0,0.16,1.0,1.0))
        pads.append(ROOT.TPad("2","2",0.0,0.0,1.0,0.17))
        
        pads[0].SetTopMargin(0.08)
        pads[0].SetLeftMargin(0.12)
        pads[0].SetBottomMargin(0.10)
        pads[1].SetLeftMargin(0.12)
        
        pads[0].Draw()
        pads[1].Draw()
        pads[0].cd()
    else:
        c.SetCanvasSize(700,504)
        pads = [c]
        pads[0].SetLeftMargin(0.12)
        pads[0].SetTopMargin(0.08)

    if isLog:
        pads[0].SetLogy()
    pads[0].SetTicky(1)

    pads[0].cd()

    ## MC
    int_errors = [ROOT.Double(0) for i in range(len(h_bkg_vec))]
    integrals = [h_bkg_vec[i].IntegralAndError(0,-1,int_errors[i]) for i in range(len(h_bkg_vec))]
    if doSort:
        zipped = zip(h_bkg_vec,bkg_names)
        sorted_bkg = [x for (y,x) in sorted(zip(integrals,zipped))]
        h_bkg_vec = [x for (x,y) in sorted_bkg]
        bkg_names = [y for (x,y) in sorted_bkg]
    else:
        h_bkg_vec = h_bkg_vec[::-1]
        bkg_names = bkg_names[::-1]

    scaleFactor = 1.0
    scaleFactorError = 1.0
    if(h_data!=None and scaleMCtoData):
        tot_MC_error = ROOT.TMath.Sqrt(sum([x**2 for x in int_errors]))
        tot_MC_integral = sum(integrals)
        data_error = ROOT.Double(0)
        data_integral = h_data[0].IntegralAndError(0,-1,data_error)
        scaleFactor = data_integral/tot_MC_integral
        if data_integral > 0:
            scaleFactorError = scaleFactor * (data_error/data_integral + tot_MC_error/tot_MC_integral)
        else:
            scaleFactorError = 0.0
    for i in range(len(h_bkg_vec)):
        h_bkg_vec[i].Scale(scaleFactor)

    dataMax = 0
    if h_data!=None:
        for ih in range(len(h_data)):
            for i in range(1,h_data[ih].GetNbinsX()+1):
                y = h_data[ih].GetBinContent(i)+h_data[ih].GetBinError(i)
                if y>dataMax:
                    dataMax = y

    sigMax = 0
    if h_sig_vec!=None:
        for ih in range(len(h_sig_vec)):
            for i in range(1,h_sig_vec[ih].GetNbinsX()+1):
                y = h_sig_vec[ih].GetBinContent(i)+h_sig_vec[ih].GetBinError(i)
                if y>sigMax:
                    sigMax = y

    stack = ROOT.THStack("hs","")
    plotBackgrounds(h_bkg_vec, bkg_names, canvas=pads[0], stack=stack, xRangeUser=xRangeUser, isLog=isLog, 
                    xAxisTitle=xAxisTitle, xAxisUnit=xAxisUnit, dataMax=dataMax, shallowCopy=False,
                    userMax=userMax, userMin=userMin, doMT2Colors=doMT2Colors, doOverflow=doOverflow, 
                    sigMax=sigMax, customColors=customColors)

    if doBkgError:
        h_err = ROOT.TH1D()
        h_bkg_vec[0].Copy(h_err)
        for i in range(1,len(h_bkg_vec)):
            h_err.Add(h_bkg_vec[i])
        h_err.SetFillStyle(3244)
        h_err.SetFillColor(ROOT.kGray+3)
        h_err.Draw("E2SAME")


    ## data
    if h_data != None:
        styles = [20,24,21,25]
        colors = [ROOT.kBlack,ROOT.kBlack,ROOT.kRed,ROOT.kBlack]
        N_DATA_EVENTS = [int(h.Integral(0,-1)) for h in h_data] #curretly only support counting of events for first histogram
        for ih in range(len(h_data)):
            h_data[ih].SetMarkerStyle(styles[ih])
            h_data[ih].SetMarkerSize(markerSize)
            h_data[ih].SetMarkerColor(colors[ih])
            h_data[ih].SetLineColor(colors[ih])
            if xRangeUser!=None:
                h_data[ih].GetXaxis().SetRangeUser(*xRangeUser)
            if doOverflow:
                utils.PutOverflowInLastBin(h_data[ih], None if xRangeUser==None else xRangeUser[1])
        if convertToPoisson:
            h_data_poisson = [ROOT.TGraphAsymmErrors() for h in h_data]
            for ih in range(len(h_data)-1,-1,-1):
                utils.ConvertToPoissonGraph(h_data[ih], h_data_poisson[ih], drawZeros=drawZeros)
                h_data_poisson[ih].SetMarkerStyle(styles[ih])
                h_data_poisson[ih].SetMarkerSize(markerSize)
                h_data_poisson[ih].SetMarkerColor(colors[ih])
                h_data_poisson[ih].SetLineColor(colors[ih])
                h_data_poisson[ih].Draw("SAME PZ")
        else:
            for ih in range(len(h_data)-1,-1,-1):
                h_data[ih].Draw("SAME E0")

    ## functions
    for function in functions:
        function.Draw("SAME")

    ## signals
    #sig_cols = [ROOT.kMagenta, ROOT.kCyan, ROOT.kOrange+7, ROOT.kGreen]
    sig_cols = [ROOT.kGreen, ROOT.kYellow, ROOT.kMagenta, ROOT.kCyan]
    for isig in range(len(h_sig_vec)):
        h_sig_vec[isig].SetLineColor(sig_cols[isig])
        #h_sig_vec[isig].SetLineWidth(2)
        h_sig_vec[isig].SetLineWidth(3)
        h_sig_vec[isig].SetLineStyle(7)#new        
        h_sig_vec[isig].Draw("SAME HIST")

    ## draw vertical lines
    line = ROOT.TLine()
    line.SetLineWidth(2)
    line.SetLineColor(ROOT.kRed)
    for linex in verticalLines:
        lm = pads[0].GetLeftMargin()
        rm = pads[0].GetRightMargin()
        tm = pads[0].GetTopMargin()
        bm = pads[0].GetBottomMargin()
        if xRangeUser!=None:
            xrange = xRangeUser
        else:
            xrange = (h_bkg_vec[0].GetXaxis().GetXmin(), h_bkg_vec[0].GetXaxis().GetXmax())
        xndc = lm + float(linex-xrange[0])/(xrange[1]-xrange[0]) * (1-rm-lm)
        line.DrawLineNDC(xndc,bm,xndc,1-tm)

    ## legend
        
    if legCoords == None:
        legCoords = (0.65,0.72,0.87,0.89)
    leg = ROOT.TLegend(*legCoords)
    leg.SetNColumns(2)
    leg.SetTextSize(0.035)
    leg.SetBorderSize(0);
    if h_data != None:
        if type(dataTitle) != type(list()):
            dataTitle = [dataTitle]
        for ih in range(len(h_data)):
            leg.AddEntry(h_data[ih],dataTitle[ih])
    for i in range(len(h_bkg_vec)):
        leg.AddEntry(h_bkg_vec[-i-1],bkg_names[-i-1],"f")
    for i in range(len(h_sig_vec)):
        leg.AddEntry(h_sig_vec[i], sig_names[i], "l")
    leg.Draw()
    
    # handle all of the text
    text = ROOT.TLatex()
    text.SetNDC(1)
    cursorX = 0.23
    cursorY = 0.89
    # title
    if title!=None and title!="":
        text.SetTextAlign(13) 
        text.SetTextFont(42)
        text.SetTextSize(titleSize)
        text.DrawLatex(cursorX,cursorY,title)
        cursorY -= titleSize + 0.010
    # subtitles
    if subtitles==None:
        subtitles=[]
    if type(subtitles)==type(""):
        subtitles = [subtitles]
    for s in subtitles:
        text.SetTextAlign(13)
        text.SetTextFont(42)
        text.SetTextSize(subtitleSize)
        text.DrawLatex(cursorX,cursorY,s)
        cursorY -= subtitleSize + 0.015
    # lumi
    if not noLumi:
        utils.DrawLumiText(pads[0],lumi=lumi,lumiUnit=lumiUnit,energy=energy,textFont=42,textSize=cmsTextSize)
    # CMS text
    #utils.DrawCmsText(pads[0],text=cmsText,textFont=62,textSize=cmsTextSize)
    #new plot
    text.SetTextFont(62)
    # text.SetTextSize(0.05)
    # text.SetTextAlign(11)
    # text.DrawLatexNDC(0.17, 0.84, "CMS")
    # text.SetTextFont(52)
    # text.SetTextSize(0.04)
    # text.SetTextAlign(13)
    # text.DrawLatexNDC(0.17, 0.83, "Preliminary")
    text.SetTextSize(0.04)
    text.SetTextAlign(11)
    text.DrawLatexNDC(0.13, 0.93, "CMS")
    #new
    text.SetTextFont(52)
    text.SetTextSize(0.04)
    text.SetTextAlign(11)
    text.DrawLatexNDC(0.2, 0.93, "Preliminary")
    
    # Sub-legend text
    cursorX = legCoords[0]
    cursorY = legCoords[1]-0.01
    if subLegText==None:
        subLegText=[]
    if type(subLegText)==type(""):
        subLegText = [subLegText]
    for s in subLegText:
        if h_data==None:
            N_DATA_EVENTS = [0]
        vals = {"ndata":N_DATA_EVENTS[0], "datamcsf":scaleFactor, "datamcsferr":scaleFactorError}
        for i in range(len(N_DATA_EVENTS)):
            vals["ndata{0}".format(i+1)] = N_DATA_EVENTS[i]
        s = s.replace("{datamcsf}","{datamcsf:.2f}")
        s = s.replace("{datamcsferr}","{datamcsferr:.2f}")
        text.SetTextFont(62)
        text.SetTextAlign(13)
        text.SetTextSize(subLegTextSize)
        text.DrawLatex(cursorX,cursorY,s.format(**vals))
        cursorY -= 0.03+0.005


    ######## ratio plot ############
    
    if doRatio:
        pads[1].cd()
    
        h1 = ROOT.TH1D()
        h_bkg_vec[0].Copy(h1)
        for i in range(len(h_bkg_vec)-1):
            h1.Add(h_bkg_vec[i+1])

        ratioHist = [ROOT.TH1D() for h in h_data]
        ratioGraph = [ROOT.TGraphAsymmErrors() for h in h_data]
        h_syst = ROOT.TH1D()
        for ih,hd in list(enumerate(h_data))[::-1]:
            if ih==len(h_data)-1:
                plotRatio(h1, hd, canvas=pads[1], ratioHist=ratioHist[ih], ratioTitle=ratioTitle, xRangeUser=xRangeUser, 
                          markerSize=markerSize, markerStyle=hd.GetMarkerStyle(), markerColor=hd.GetMarkerColor(),
                          doPull=doPull, convertToPoisson=convertToPoisson, ratioGraph=ratioGraph[ih], drawZeros=drawZeros,
                          drawSystematicBand=drawSystematicBand, systematics=systematics, h_syst=h_syst)
            else:
                if ratioType==0:
                    hden = h1
                    hnum = hd
                else:
                    hden = hd
                    hnum = h_data[0]
                plotRatio(hden, hnum, canvas=pads[1], ratioHist=ratioHist[ih], xRangeUser=xRangeUser, 
                          markerSize=markerSize, markerStyle=hd.GetMarkerStyle(), markerColor=hd.GetMarkerColor(),
                          doPull=doPull, convertToPoisson=convertToPoisson, ratioGraph=ratioGraph[ih], drawZeros=drawZeros, justDrawPoints=True)
    
    c.Update()
    c.SetWindowSize(c.GetWw()+4, c.GetWh()+50)

    if saveAs!=None:
        c.SaveAs(saveAs)

    if doPause:
        raw_input()
Esempio n. 3
0
def MakePlot(ht_reg, datacard_dir, datacard_name, outdir, userMax=None):
    jbj_regs = utils.GetJBJregions(ht_reg)

    #list of lists, one per jbj region, of low edges of MT2 bins
    mt2bins = utils.GetMT2bins(ht_reg)

    # nBinsTotal = sum([len(bins)-1 for bins in mt2bins]) + 1
    nBinsTotal = sum([len(bins) - 1 for bins in mt2bins])
    bkg_processes = ["zinv", "llep", "qcd"]
    nBkgs = len(bkg_processes)

    ## setup histograms
    h_data = ROOT.TH1D("h_data", "", nBinsTotal, 0, nBinsTotal)
    h_bkg_vec = []
    for i, proc in enumerate(bkg_processes):
        h_bkg_vec.append(ROOT.TH1D("h_" + proc, "", nBinsTotal, 0, nBinsTotal))
    g_unc = ROOT.TGraphAsymmErrors()  # graph to store prediction uncertainties
    g_unc_ratio = ROOT.TGraphAsymmErrors(
    )  # graph to store prediction uncertainties

    ## fill histograms
    ibin = 0
    binLabels = []

    for ijbj, jbj_reg in enumerate(jbj_regs):
        for imt2 in range(len(mt2bins[ijbj]) - 1):
            ibin += 1
            mt2left = mt2bins[ijbj][imt2]
            mt2right = mt2bins[ijbj][imt2 + 1]
            mt2name = utils.GetMT2name(mt2left, mt2right)
            if ht_reg != "monojet":
                datacard_name_fmt = datacard_name.format(
                    ht_reg, jbj_reg, mt2name)
            else:
                ht_name = "HT{0}to{1}".format(mt2left, mt2right)
                ht_name = ht_name.replace("-1", "Inf")
                datacard_name_fmt = datacard_name.format(
                    ht_name, jbj_reg, "m0toInf")

            # get yields. first entry is data, rest are background predictions
            yields = utils.GetYieldsFromDatacard(
                os.path.join(datacard_dir, datacard_name_fmt), bkg_processes)
            h_data.SetBinContent(ibin, yields[0])
            for j in range(1, nBkgs + 1):
                h_bkg_vec[j - 1].SetBinContent(ibin, yields[j])
            tot_pred = sum(yields[1:])

            # get uncertainties
            pred_unc = utils.GetUncertaintiesFromDatacard(
                os.path.join(datacard_dir, datacard_name_fmt), bkg_processes)
            tot_unc_up = ROOT.TMath.Sqrt(
                sum([(pred_unc[i][0] * yields[i + 1])**2
                     for i in range(nBkgs)]))
            tot_unc_down = ROOT.TMath.Sqrt(
                sum([(pred_unc[i][1] * yields[i + 1])**2
                     for i in range(nBkgs)]))
            thisPoint = g_unc.GetN()
            g_unc.SetPoint(thisPoint, ibin - 0.5, tot_pred)
            g_unc.SetPointError(thisPoint, 0.5, 0.5, tot_unc_down, tot_unc_up)
            g_unc_ratio.SetPoint(thisPoint, ibin - 0.5, 1)
            g_unc_ratio.SetPointError(thisPoint, 0.5, 0.5,
                                      tot_unc_down / tot_pred,
                                      tot_unc_up / tot_pred)

            binLabels.append(utils.GetMT2label(mt2left, mt2right))

    h_bkg_vec[0].SetFillColor(418)
    h_bkg_vec[1].SetFillColor(ROOT.kAzure + 4)
    h_bkg_vec[2].SetFillColor(401)

    stack = ROOT.THStack("bkg_stack", "")
    for j in range(nBkgs):
        h_bkg_vec[nBkgs - 1 - j].SetLineWidth(1)
        h_bkg_vec[nBkgs - 1 - j].SetLineColor(ROOT.kBlack)
        stack.Add(h_bkg_vec[nBkgs - 1 - j])

    h_data.SetMarkerStyle(20)
    h_data.SetMarkerSize(1.3)
    h_data.SetMarkerColor(ROOT.kBlack)
    h_data.SetLineColor(ROOT.kBlack)

    ROOT.gStyle.SetOptStat(0)
    ROOT.gStyle.SetLineWidth(1)
    c = ROOT.TCanvas("c", "c", 900, 600)

    pads = []
    pads.append(ROOT.TPad("1", "1", 0.0, 0.18, 1.0, 1.0))
    pads.append(ROOT.TPad("2", "2", 0.0, 0.0, 1.0, 0.19))

    pads[0].SetTopMargin(0.08)
    pads[0].SetBottomMargin(0.13)
    pads[0].SetRightMargin(0.05)
    pads[0].SetLeftMargin(0.10)

    pads[1].SetRightMargin(0.05)
    pads[1].SetLeftMargin(0.10)

    pads[0].Draw()
    pads[1].Draw()
    pads[0].cd()

    pads[0].SetLogy(1)
    # pads[0].SetTickx(1)
    pads[1].SetTickx(1)
    pads[0].SetTicky(1)
    pads[1].SetTicky(1)

    yMin = 1e-3
    if userMax != None:
        yMax = userMax
    else:
        yMax = h_data.GetMaximum()**(2.0)
    h_data.GetYaxis().SetRangeUser(yMin, yMax)
    h_data.GetYaxis().SetTitle("Events / Bin")
    h_data.GetYaxis().SetTitleOffset(1.2)
    h_data.GetYaxis().SetTickLength(0.02)
    h_data.GetXaxis().SetRangeUser(0, nBinsTotal)
    h_data.GetXaxis().SetNdivisions(nBinsTotal, 0, 0)
    h_data.GetXaxis().SetLabelSize(0)
    h_data.GetXaxis().SetTickLength(0.015)

    # just draw dots to get axes. Will draw TGraphAsymmErrors on top later
    h_data.SetMarkerStyle(1)
    h_data.Draw("P")

    # draw the backgrounds
    stack.Draw("SAME HIST")

    # draw the prediction uncertainties
    g_unc.SetFillStyle(3244)
    g_unc.SetFillColor(ROOT.kGray + 3)
    g_unc.Draw("SAME 2")

    # get a graph using proper asymmetric poissonian errors
    g_data = ROOT.TGraphAsymmErrors()
    ppmUtils.ConvertToPoissonGraph(h_data, g_data, drawZeros=True)
    g_data.SetPointError(g_data.GetN() - 1, 0, 0, 0, 0)
    g_data.SetMarkerStyle(20)
    g_data.SetMarkerSize(1.2)
    g_data.SetLineWidth(1)

    # draw the graph and then axes again on top
    g_data.Draw("SAME P")
    h_data.Draw("SAME AXIS")

    # save for later
    left = pads[0].GetLeftMargin()
    right = pads[0].GetRightMargin()
    top = pads[0].GetTopMargin()
    bot = pads[0].GetBottomMargin()

    #draw the x-axis labels
    binWidth = (1.0 - right - left) / nBinsTotal
    text = ROOT.TLatex()
    text.SetNDC(1)
    text.SetTextAlign(32)
    text.SetTextAngle(90)
    text.SetTextSize(min(binWidth * 1.2, 0.026))
    text.SetTextFont(62)
    for ibin in range(nBinsTotal - 1):
        x = left + (ibin + 0.5) * binWidth
        y = pads[0].GetBottomMargin() - 0.009
        text.DrawLatex(x, y, binLabels[ibin])

    # draw the "Pre-fit background" text
    text.SetTextAlign(13)
    text.SetTextFont(42)
    text.SetTextAngle(0)
    text.SetTextSize(0.05)
    text.DrawLatex(left + 0.04, 1 - top - 0.01, "Pre-fit background")

    # draw the HT bin  in upper middle
    text.SetTextAlign(21)
    text.SetTextFont(62)
    text.SetTextAngle(0)
    text.SetTextSize(0.035)
    text.DrawLatex(left + (1 - right - left) * 0.5, 1 - top - 0.01 - 0.04,
                   utils.GetHTtitle(ht_reg))

    # Draw the CMS and luminosity text
    ppmUtils.DrawCmsText(pads[0], text="CMS Preliminary", textSize=0.038)
    ppmUtils.DrawLumiText(pads[0], lumi=utils.lumi, textSize=0.038)

    # draw the j/bj region labels
    ibin = 0
    for ijbj, jbj_reg in enumerate(jbj_regs):
        xcenter = left + binWidth * (ibin + (len(mt2bins[ijbj]) - 1) * 0.5)
        lines = utils.GetJBJtitle(jbj_reg)
        text.SetTextAlign(23)
        text.SetTextFont(62)
        text.SetTextSize(0.030)
        # in the last region, move the text left a bit to avoid overlap with tick marks
        if ijbj == len(jbj_regs) - 1:
            text.SetTextAlign(13)
            xcenter = left + binWidth * ibin + 0.007
            xcenter = max(xcenter, 1 - right - 0.25)
        y = bot + (1 - top - bot) * 0.85
        if xcenter > 1 - right - 0.19:
            y = 0.67
        text.DrawLatex(xcenter, y, lines[0])
        text.DrawLatex(xcenter, y - text.GetTextSize() - 0.001, lines[1])

        ibin += len(mt2bins[ijbj]) - 1

    #draw the lines separating j-bj region
    line = ROOT.TLine()
    line.SetNDC(1)
    line.SetLineStyle(2)
    line.SetLineWidth(1)
    line.SetLineColor(ROOT.kBlack)
    ibin = 0
    for i in range(len(jbj_regs) - 1):
        ibin += len(mt2bins[i]) - 1
        x = left + binWidth * ibin
        line.DrawLineNDC(x, bot, x, bot + (1 - top - bot) * 0.85)

    # legend
    leg = ROOT.TLegend(1 - right - 0.175, 1 - top - 0.23, 1 - right - 0.02,
                       1 - top - 0.01)
    leg.SetBorderSize(1)
    leg.SetCornerRadius(0.3)
    leg.AddEntry(g_data, "Data", "lp")
    for i in range(nBkgs):
        leg.AddEntry(h_bkg_vec[i], utils.GetLegendName(bkg_processes[i]), 'f')
    leg.Draw()

    ####################
    #### RATIO PLOT ####
    ####################

    pads[1].cd()
    h_ratio = h_bkg_vec[0].Clone(
        "h_ratio")  #h_ratio is just a dummy histogram to draw axes correctly
    h_ratio.Reset()
    g_ratio = ROOT.TGraphAsymmErrors()
    h_pred = h_bkg_vec[0].Clone("h_pred")
    for i in range(1, nBkgs):
        h_pred.Add(h_bkg_vec[i])
    ppmUtils.GetPoissonRatioGraph(h_pred,
                                  h_data,
                                  g_ratio,
                                  drawZeros=True,
                                  useMCErr=False)
    h_ratio.GetYaxis().SetRangeUser(0, 2)
    h_ratio.GetYaxis().SetNdivisions(505)
    h_ratio.GetYaxis().SetTitle("Data/Pred.")
    h_ratio.GetYaxis().SetTitleSize(0.16)
    h_ratio.GetYaxis().SetTitleOffset(0.18)
    h_ratio.GetYaxis().SetLabelSize(0.13)
    h_ratio.GetYaxis().CenterTitle()
    h_ratio.GetYaxis().SetTickLength(0.02)
    h_ratio.GetXaxis().SetLabelSize(0)
    h_ratio.GetXaxis().SetTitle("")
    h_ratio.GetXaxis().SetNdivisions(nBinsTotal, 0, 0)
    h_ratio.GetXaxis().SetTickSize(0.06)
    g_ratio.SetMarkerStyle(20)
    g_ratio.SetMarkerSize(1.0)
    g_ratio.SetLineWidth(1)

    g_unc_ratio.SetFillStyle(1001)
    g_unc_ratio.SetFillColor(ROOT.kGray)

    h_ratio.Draw()
    g_unc_ratio.Draw("SAME 2")

    # draw line at 1
    line = ROOT.TLine()
    line.SetLineStyle(1)
    line.SetLineWidth(1)
    line.SetLineColor(ROOT.kGray + 2)
    line.DrawLine(0, 1, nBinsTotal, 1)

    #draw the lines separating j-bj region
    line.SetNDC(1)
    line.SetLineStyle(2)
    line.SetLineWidth(1)
    line.SetLineColor(ROOT.kBlack)
    ibin = 0
    for i in range(len(jbj_regs) - 1):
        ibin += len(mt2bins[i]) - 1
        line.DrawLine(ibin, 0, ibin, 2)

    h_ratio.Draw("SAME AXIS")
    g_ratio.Draw("SAME P0")

    name = "prefit_{0}".format(ht_reg)
    try:
        os.makedirs(outdir)
    except:
        pass
    c.SaveAs(os.path.join(outdir, name + ".pdf"))
    c.SaveAs(os.path.join(outdir, name + ".png"))

    h_data.Delete()
    g_data.Delete()
    h_ratio.Delete()
    g_ratio.Delete()
    for h in h_bkg_vec:
        h.Delete()