def plotHistos( histoData=None, histoSignal=None, histoTotBkg=None, histosBkg={}, statErrBand=None, systErrBand=None, # these are TGraphAsymmErrors canvasName='canvas', outdir='./', options=None, stack_order=[], topLabel='', drawStatErr=False, drawSystErr=False, drawYieldAndError=False, printYieldSummary=False): "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling" verbose = options.verbose formatAuxMaterial = options.format_aux setAtlasStyle() padMaster = histoData if verbose: print "plotting ", padMaster.GetName(), ' (', padMaster.GetEntries( ), ' entries)' can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 800) botPad, topPad = buildBotTopPads(can, squeezeMargins=False) can.cd() topPad.Draw() # draw top topPad.cd() topPad._hists = [padMaster] if formatAuxMaterial: for ax in [padMaster.GetXaxis(), padMaster.GetYaxis()]: ax.SetTitle(prettify(ax.GetTitle())) padMaster.Draw('axis') topPad.Update( ) # necessary to fool root's dumb object ownership of the stack stack = r.THStack('stack_' + padMaster.GetName(), '') r.SetOwnership(stack, False) topPad._hists.append(stack) leg = topRightLegend(can, 0.300 if formatAuxMaterial else 0.225, 0.400 if formatAuxMaterial else 0.325, shiftX=-0.1 if formatAuxMaterial else 0.0, shiftY=-0.1 if formatAuxMaterial else 0.0) topPad._leg = leg leg.SetBorderSize(0) leg.SetTextFont(padMaster.GetTitleFont()) leg._reversedEntries = [] def integralWou(h): "Integral with underflow and overflow" return h.Integral(0, h.GetNbinsX() + 1) for group, histo in sortedAs(histosBkg, stack_order): histo.SetFillColor(getGroupColor(group)) histo.SetLineWidth(2) histo.SetLineColor(r.kBlack) stack.Add(histo) topPad._hists.append(histo) leg._reversedEntries.append( (histo, prettify(group) if formatAuxMaterial else "{0}: {1:.2f}".format(group, integralWou(histo)), 'F')) if not formatAuxMaterial: leg._reversedEntries.append((dummyHisto(), "{0}, {1:.2f}".format( 'bkg', sum([integralWou(h) for h in stack.GetHists()])), 'l')) if statErrBand and drawStatErr: statErrBand.SetFillStyle(3006) leg._reversedEntries.append((statErrBand, 'stat', 'f')) if systErrBand and drawSystErr: systErrBand.SetFillStyle(3007) leg._reversedEntries.append((systErrBand, 'syst', 'f')) leg._reversedEntries.append( (histoData, "Data {0}".format(prettify(topLabel)) if formatAuxMaterial else "{0}, {1:.2f}".format('data', integralWou(histoData)), 'p')) for h, g, o in leg._reversedEntries[::-1]: leg.AddEntry(h, g, o) # stack goes b-t, legend goes t-b stack.Draw('hist same') histoData.SetMarkerStyle(r.kFullCircle) histoData.SetLineWidth(2) dataGraph = graphWithPoissonError(histoData) dataGraph.Draw('same p') isRightSignal = False if histoSignal: histoSignal.SetFillStyle(0) histoSignal.SetFillColor(0) histoSignal.SetLineColor(getGroupColor('signal')) histoSignal.SetLineWidth(3) isRightSignal = (all(s in histoSignal.GetName() for s in ['signaltaumu', 'sr_mue']) or all(s in histoSignal.GetName() for s in ['signaltaue', 'sr_emu'])) if isRightSignal: histoSignal.Draw('histo same') if statErrBand and drawStatErr: statErrBand.SetFillStyle(3006) statErrBand.Draw('E2 same') leg.AddEntry(statErrBand, 'stat', 'f') if systErrBand and drawSystErr: systErrBand.SetFillStyle(3007) systErrBand.Draw('E2 same') leg.AddEntry(systErrBand, 'syst', 'f') totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand) if totErrBand: totErrBand.Draw('E2 same') totErrBand.SetFillStyle(3005) leg.AddEntry(totErrBand, 'stat+syst', 'f') if printYieldSummary: print_total_error = False print( "{}:".format(topLabel if topLabel else dataGraph.GetName()) + (" expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}}".format( totErrBand.GetY()[0], totErrBand.GetErrorYhigh(0), totErrBand.GetErrorYlow(0)) if print_total_error else " expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}} (stat) ^{{+{:.2f}}}_{{{:.2f}}} (syst)" .format(totErrBand.GetY()[0], statErrBand.GetErrorYhigh(0) if statErrBand else 0.0, statErrBand.GetErrorYlow(0) if statErrBand else 0.0, systErrBand.GetErrorYhigh(0) if systErrBand else 0.0, systErrBand.GetErrorYlow(0) if systErrBand else 0.0)) + " obs {:.2f}".format(dataGraph.GetY()[0])) if histoSignal and isRightSignal: hname = histoSignal.GetName() label = ('H#rightarrow#mu#tau' if 'signaltaumu' in hname else 'H#rightarrowe#tau' if 'signaltaue' in hname else 'signal') label = ("{}, BR=1%".format(label) if formatAuxMaterial else "{}, BR=1%, {:.2f}".format(label, integralWou(histoSignal))) leg.AddEntry(histoSignal, label, 'l') leg.Draw('same') topPad.Update() tex = r.TLatex() tex.SetTextSize(0.5 * tex.GetTextSize()) tex.SetNDC(True) label = "%s tot bkg : " % (can.GetName()) label += "%.3f #pm %.3f (stat)" % (integralAndError(histoTotBkg)) if systErrBand: sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand) label += "#pm #splitline{%.3f}{%.3f} (syst)" % (sysUp, sysDo) if drawYieldAndError: tex.DrawLatex(0.10, 0.95, label) topPad.SetTopMargin(2.0 * topPad.GetTopMargin()) atlasLabel = drawAtlasLabel(can, align=13, scale=0.75, xpos=0.175 if formatAuxMaterial else 0.125, ypos=0.945 if formatAuxMaterial else None, public=True) if topLabel and not formatAuxMaterial: topRightLabel(can, topLabel, ypos=1.0) yMin, yMax = getMinMax( [histoData, dataGraph, histoTotBkg, histoSignal, totErrBand]) padMaster.SetMinimum(0.0) padMaster.SetMaximum(1.1 * yMax) padMaster.GetXaxis().SetLabelSize(0) padMaster.GetXaxis().SetTitleSize(0) increaseAxisFont(padMaster.GetXaxis()) increaseAxisFont(padMaster.GetYaxis()) topPad.RedrawAxis() topPad.Update() # force stack to create padMaster # draw bot (ratio) can.cd() botPad.Draw() botPad.cd() ratio = systUtils.buildAsymmRatioGraph(dataGraph, totErrBand) ratioPadMaster = padMaster.Clone(padMaster.GetName() + '_ratio') ratioPadMaster.SetDirectory(0) ratioPadMaster.Clear() yMin, yMax = 0.0, 2.0 ratioPadMaster.SetMinimum(yMin) ratioPadMaster.SetMaximum(yMax) ratioPadMaster.SetStats(0) ratioPadMaster.Draw('axis') x_lo, x_hi = getXrange(ratioPadMaster) refLines = [referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5]] for l in refLines: l.Draw() err_band_r = systUtils.buildErrBandRatioGraph(totErrBand) err_band_r.Draw('E2 same') ratio.Draw('ep') xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis() textScaleUp = 0.75 * 1.0 / botPad.GetHNDC() # if xaxis_title : xA.SetTitle(xaxis_title) yA.SetNdivisions(-104) yA.SetTitle('Data/Bkg') yA.CenterTitle() yA.SetTitleOffset(yA.GetTitleOffset() / textScaleUp) xA.SetTitleSize( yA.GetTitleSize()) # was set to 0 for padmaster, restore it xA.SetLabelSize(yA.GetLabelSize()) for a in [xA, yA]: a.SetLabelSize(a.GetLabelSize() * textScaleUp) a.SetTitleSize(a.GetTitleSize() * textScaleUp) botPad._graphical_objects = [ratio, ratioPadMaster, err_band_r ] + refLines # avoid garbage collection botPad.Update() can.Update() for ext in ['png', 'eps']: can.SaveAs(outdir + '/' + can.GetName() + '.' + ext)
def plotHistos(histoData=None, histoSignal=None, histoTotBkg=None, histosBkg={}, statErrBand=None, systErrBand=None, # these are TGraphAsymmErrors canvasName='canvas', outdir='./', options=None, stack_order=[], topLabel='', drawStatErr=False, drawSystErr=False, drawYieldAndError=False, printYieldSummary=False) : "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling" verbose = options.verbose formatAuxMaterial = options.format_aux setAtlasStyle() padMaster = histoData if verbose : print "plotting ",padMaster.GetName(),' (',padMaster.GetEntries(),' entries)' can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 800) botPad, topPad = buildBotTopPads(can, squeezeMargins=False) can.cd() topPad.Draw() # draw top topPad.cd() topPad._hists = [padMaster] if formatAuxMaterial: for ax in [padMaster.GetXaxis(), padMaster.GetYaxis()]: ax.SetTitle(prettify(ax.GetTitle())) padMaster.Draw('axis') topPad.Update() # necessary to fool root's dumb object ownership of the stack stack = r.THStack('stack_'+padMaster.GetName(), '') r.SetOwnership(stack, False) topPad._hists.append(stack) leg = topRightLegend(can, 0.300 if formatAuxMaterial else 0.225, 0.400 if formatAuxMaterial else 0.325, shiftX=-0.1 if formatAuxMaterial else 0.0, shiftY=-0.1 if formatAuxMaterial else 0.0) topPad._leg = leg leg.SetBorderSize(0) leg.SetTextFont(padMaster.GetTitleFont()) leg._reversedEntries = [] def integralWou(h): "Integral with underflow and overflow" return h.Integral(0, h.GetNbinsX()+1) for group, histo in sortedAs(histosBkg, stack_order) : histo.SetFillColor(getGroupColor(group)) histo.SetLineWidth(2) histo.SetLineColor(r.kBlack) stack.Add(histo) topPad._hists.append(histo) leg._reversedEntries.append((histo, prettify(group) if formatAuxMaterial else "{0}: {1:.2f}".format(group, integralWou(histo)), 'F')) if not formatAuxMaterial: leg._reversedEntries.append((dummyHisto(), "{0}, {1:.2f}".format('bkg', sum([integralWou(h) for h in stack.GetHists()])), 'l')) if statErrBand and drawStatErr : statErrBand.SetFillStyle(3006) leg._reversedEntries.append((statErrBand, 'stat', 'f')) if systErrBand and drawSystErr : systErrBand.SetFillStyle(3007) leg._reversedEntries.append((systErrBand, 'syst', 'f')) leg._reversedEntries.append((histoData, "Data {0}".format(prettify(topLabel)) if formatAuxMaterial else "{0}, {1:.2f}".format('data', integralWou(histoData)), 'p')) for h, g, o in leg._reversedEntries[::-1] : leg.AddEntry(h, g, o) # stack goes b-t, legend goes t-b stack.Draw('hist same') histoData.SetMarkerStyle(r.kFullCircle) histoData.SetLineWidth(2) dataGraph = graphWithPoissonError(histoData) dataGraph.Draw('same p') isRightSignal = False if histoSignal: histoSignal.SetFillStyle(0) histoSignal.SetFillColor(0) histoSignal.SetLineColor(getGroupColor('signal')) histoSignal.SetLineWidth(3) isRightSignal = (all(s in histoSignal.GetName() for s in ['signaltaumu', 'sr_mue']) or all(s in histoSignal.GetName() for s in ['signaltaue', 'sr_emu'])) if isRightSignal: histoSignal.Draw('histo same') if statErrBand and drawStatErr : statErrBand.SetFillStyle(3006) statErrBand.Draw('E2 same') leg.AddEntry(statErrBand, 'stat', 'f') if systErrBand and drawSystErr : systErrBand.SetFillStyle(3007) systErrBand.Draw('E2 same') leg.AddEntry(systErrBand, 'syst', 'f') totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand) if totErrBand : totErrBand.Draw('E2 same') totErrBand.SetFillStyle(3005) leg.AddEntry(totErrBand, 'stat+syst', 'f') if printYieldSummary: print_total_error = False print ("{}:".format(topLabel if topLabel else dataGraph.GetName())+ (" expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}}".format(totErrBand.GetY()[0], totErrBand.GetErrorYhigh(0), totErrBand.GetErrorYlow(0)) if print_total_error else " expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}} (stat) ^{{+{:.2f}}}_{{{:.2f}}} (syst)" .format(totErrBand.GetY()[0], statErrBand.GetErrorYhigh(0) if statErrBand else 0.0, statErrBand.GetErrorYlow(0) if statErrBand else 0.0, systErrBand.GetErrorYhigh(0) if systErrBand else 0.0, systErrBand.GetErrorYlow(0) if systErrBand else 0.0) )+ " obs {:.2f}".format(dataGraph.GetY()[0])) if histoSignal and isRightSignal: hname = histoSignal.GetName() label = ('H#rightarrow#mu#tau' if 'signaltaumu' in hname else 'H#rightarrowe#tau' if 'signaltaue' in hname else 'signal') label = ("{}, BR=1%".format(label) if formatAuxMaterial else "{}, BR=1%, {:.2f}".format(label, integralWou(histoSignal))) leg.AddEntry(histoSignal, label, 'l') leg.Draw('same') topPad.Update() tex = r.TLatex() tex.SetTextSize(0.5 * tex.GetTextSize()) tex.SetNDC(True) label = "%s tot bkg : "%(can.GetName()) label += "%.3f #pm %.3f (stat)"%(integralAndError(histoTotBkg)) if systErrBand : sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand) label += "#pm #splitline{%.3f}{%.3f} (syst)"%(sysUp, sysDo) if drawYieldAndError : tex.DrawLatex(0.10, 0.95, label) topPad.SetTopMargin(2.0*topPad.GetTopMargin()) atlasLabel = drawAtlasLabel(can, align=13, scale=0.75, xpos=0.175 if formatAuxMaterial else 0.125, ypos=0.945 if formatAuxMaterial else None, public=True) if topLabel and not formatAuxMaterial : topRightLabel(can, topLabel, ypos=1.0) yMin, yMax = getMinMax([histoData, dataGraph, histoTotBkg, histoSignal, totErrBand]) padMaster.SetMinimum(0.0) padMaster.SetMaximum(1.1 * yMax) padMaster.GetXaxis().SetLabelSize(0) padMaster.GetXaxis().SetTitleSize(0) increaseAxisFont(padMaster.GetXaxis()) increaseAxisFont(padMaster.GetYaxis()) topPad.RedrawAxis() topPad.Update() # force stack to create padMaster # draw bot (ratio) can.cd() botPad.Draw() botPad.cd() ratio = systUtils.buildAsymmRatioGraph(dataGraph, totErrBand) ratioPadMaster = padMaster.Clone(padMaster.GetName()+'_ratio') ratioPadMaster.SetDirectory(0) ratioPadMaster.Clear() yMin, yMax = 0.0, 2.0 ratioPadMaster.SetMinimum(yMin) ratioPadMaster.SetMaximum(yMax) ratioPadMaster.SetStats(0) ratioPadMaster.Draw('axis') x_lo, x_hi = getXrange(ratioPadMaster) refLines = [referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5]] for l in refLines : l.Draw() err_band_r = systUtils.buildErrBandRatioGraph(totErrBand) err_band_r.Draw('E2 same') ratio.Draw('ep') xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis() textScaleUp = 0.75*1.0/botPad.GetHNDC() # if xaxis_title : xA.SetTitle(xaxis_title) yA.SetNdivisions(-104) yA.SetTitle('Data/Bkg') yA.CenterTitle() yA.SetTitleOffset(yA.GetTitleOffset()/textScaleUp) xA.SetTitleSize(yA.GetTitleSize()) # was set to 0 for padmaster, restore it xA.SetLabelSize(yA.GetLabelSize()) for a in [xA, yA] : a.SetLabelSize(a.GetLabelSize()*textScaleUp) a.SetTitleSize(a.GetTitleSize()*textScaleUp) botPad._graphical_objects = [ratio, ratioPadMaster, err_band_r] + refLines # avoid garbage collection botPad.Update() can.Update() for ext in ['png','eps'] : can.SaveAs(outdir+'/'+can.GetName()+'.'+ext)
def plotHistos(histoData=None, histoSignal=None, histoTotBkg=None, histosBkg={}, statErrBand=None, systErrBand=None, # these are TGraphAsymmErrors canvasName='canvas', outdir='./', verbose=False, drawStatErr=False, drawSystErr=False, drawYieldAndError=False) : "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling" #setWhPlotStyle() setAtlasStyle() padMaster = histoData if verbose : print "plotting ",padMaster.GetName() can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 600) can.cd() can._hists = [padMaster] padMaster.Draw('axis') can.Update() # necessary to fool root's dumb object ownership of the stack stack = r.THStack('stack_'+padMaster.GetName(), '') r.SetOwnership(stack, False) can._hists.append(stack) leg = topRightLegend(can, 0.225, 0.325) can._leg = leg leg.SetBorderSize(0) leg._reversedEntries = [] for group, histo in sortedAs(histosBkg, stackedGroups()) : histo.SetFillColor(getGroupColor(group)) histo.SetLineWidth(2) histo.SetLineColor(r.kBlack) stack.Add(histo) can._hists.append(histo) leg._reversedEntries.append((histo, group, 'F')) for h, g, o in leg._reversedEntries[::-1] : leg.AddEntry(h, g, o) # stack goes b-t, legend goes t-b stack.Draw('hist same') histoData.SetMarkerStyle(r.kFullCircle) histoData.SetLineWidth(2) dataGraph = graphWithPoissonError(histoData) dataGraph.Draw('same p') if histoSignal : histoSignal.SetLineColor(getGroupColor('signal')) histoSignal.SetLineWidth(2) histoSignal.Draw('histo same') leg.AddEntry(histoSignal, '(m_{C1},m_{N1})=(130, 0)GeV', 'l') if statErrBand and drawStatErr : statErrBand.SetFillStyle(3006) statErrBand.Draw('E2 same') leg.AddEntry(statErrBand, 'stat', 'f') if systErrBand and drawSystErr : systErrBand.SetFillStyle(3007) systErrBand.Draw('E2 same') leg.AddEntry(systErrBand, 'syst', 'f') totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand) if totErrBand : totErrBand.Draw('E2 same') totErrBand.SetFillStyle(3005) leg.AddEntry(totErrBand, 'stat+syst', 'f') leg.Draw('same') can.Update() tex = r.TLatex() tex.SetTextSize(0.5 * tex.GetTextSize()) tex.SetNDC(True) label = "%s tot bkg : "%(can.GetName()) label += "%.3f #pm %.3f (stat)"%(integralAndError(histoTotBkg)) if systErrBand : sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand) label += "#pm #splitline{%.3f}{%.3f} (syst)"%(sysUp, sysDo) if drawYieldAndError : tex.DrawLatex(0.10, 0.95, label) can.SetTopMargin(2.0*can.GetTopMargin()) drawAtlasLabel(can, xpos=0.125, align=13) yMin, yMax = getMinMax([histoData, dataGraph, histoTotBkg, histoSignal, totErrBand]) padMaster.SetMinimum(0.0) padMaster.SetMaximum(1.1 * yMax) increaseAxisFont(padMaster.GetXaxis()) increaseAxisFont(padMaster.GetYaxis()) can.RedrawAxis() can.Update() # force stack to create padMaster for ext in ['png','eps'] : can.SaveAs(outdir+'/'+can.GetName()+'.'+ext)