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()
def plotRatio(h1, h2, canvas=None, ratioHist=None, xRangeUser=None, ratioTitle = None, markerSize=0.7, markerStyle=20, markerColor=ROOT.kBlack, doPull=False, convertToPoisson=False, ratioGraph=None, drawZeros=True, drawSystematicBand=False, systematics=None, h_syst=None, yRangeUser=None, showRatioErrs=True, justDrawPoints=False): if doPull: convertToPoisson = False if canvas==None: canvas = ROOT.TCanvas() if ratioHist==None: ratioHist = ROOT.TH1D() if convertToPoisson and type(ratioGraph)!=type(ROOT.TGraphAsymmErrors()): raise RuntimeError("must pass a TGraphAsymmErrors as ratioGraph for convertToPoisson option!") if ratioTitle==None: if not doPull: ratioTitle = "Data/MC" else: ratioTitle = "Pull" canvas.cd() canvas.SetTicky(1) if not doPull: h2.Copy(ratioHist) ratioHist.Divide(h1) if convertToPoisson: utils.GetPoissonRatioGraph(h1,h2,ratioGraph,drawZeros=drawZeros) else: nbins = h1.GetNbinsX() h2.Copy(ratioHist) for i in range(1,nbins+1): diff = h2.GetBinContent(i)-h1.GetBinContent(i) err = ROOT.TMath.Sqrt(h2.GetBinError(i)**2 + h1.GetBinError(i)**2) ratioHist.SetBinContent(i,diff/err) ratioHist.SetBinError(i,1.0) if not showRatioErrs: for i in range(1,ratioHist.GetNbinsX()+1): ratioHist.SetBinError(i,0) ratioHist.SetTitle("") #yaxis if not doPull: if yRangeUser == None: ratioHist.GetYaxis().SetRangeUser(0,2) else: ratioHist.GetYaxis().SetRangeUser(yRangeUser[0],yRangeUser[1]) ratioHist.GetYaxis().SetNdivisions(505) else: if yRangeUser == None: ratioHist.GetYaxis().SetRangeUser(-4,4) else: ratioHist.GetYaxis().SetRangeUser(yRangeUser[0],yRangeUser[1]) ratioHist.GetYaxis().SetNdivisions(204,False) ratioHist.GetYaxis().SetTitle(ratioTitle) ratioHist.GetYaxis().SetTitleSize(0.18) ratioHist.GetYaxis().SetTitleOffset(0.17) ratioHist.GetYaxis().SetLabelSize(0.13) ratioHist.GetYaxis().CenterTitle() #xaxis ratioHist.GetXaxis().SetLabelSize(0.0) ratioHist.GetXaxis().SetTitle("") ratioHist.GetXaxis().SetTickSize(0.06) #markers ratioHist.SetMarkerStyle(markerStyle) ratioHist.SetMarkerSize(markerSize) ratioHist.SetMarkerColor(markerColor) ratioHist.SetLineColor(markerColor) if convertToPoisson: ratioGraph.SetMarkerStyle(markerStyle) ratioGraph.SetMarkerSize(markerSize) ratioGraph.SetMarkerColor(markerColor) ratioGraph.SetLineColor(markerColor) if justDrawPoints: ratioGraph.Draw("SAME PZ") else: ratioHist.Reset() ratioHist.Draw() ratioGraph.Draw("PZ") else: if justDrawPoints: ratioHist.Draw("SAME PE") else: ratioHist.Draw("PE") if justDrawPoints: return # systematics if drawSystematicBand: h1.Copy(h_syst) for i in range(1,h_syst.GetNbinsX()+1): h_syst.SetBinContent(i,1) h_syst.SetBinError(i, systematics[i-1]) h_syst.SetFillStyle(1001) h_syst.SetFillColor(ROOT.kGray+0) h_syst.Draw("SAME E2") #line line = ROOT.TLine() line.SetLineColor(ROOT.kGray+2) line.SetLineWidth(2) line.SetLineStyle(7) xmin = ratioHist.GetXaxis().GetBinLowEdge(1) xmax = ratioHist.GetXaxis().GetBinUpEdge(h1.GetNbinsX()) if xRangeUser!=None: xmin = xRangeUser[0] xmax = xRangeUser[1] if not doPull: line.DrawLine(xmin,1,xmax,1) else: line.DrawLine(xmin,0,xmax,0) line.SetLineColor(ROOT.kGray) line.SetLineWidth(1) line.SetLineStyle(1) line.DrawLine(xmin,1,xmax,1) line.DrawLine(xmin,2,xmax,2) line.DrawLine(xmin,3,xmax,3) line.DrawLine(xmin,-1,xmax,-1) line.DrawLine(xmin,-2,xmax,-2) line.DrawLine(xmin,-3,xmax,-3) if convertToPoisson: ratioGraph.Draw("SAME PZ") else: ratioHist.Draw("SAME PE") ratioHist.Draw("SAMEAXIS")
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()