def do_comparison_graph(entries, output_filename, bin_title="", xtitle="", ytitle="", other_elements=None, logx=False, logy=False, do_line=True, xlimits=None, ylimits=None, y_limit_protection=None, draw_fits=True, do_ratio=True, ratio_limits=None): """Draw several graphs on one canvas and save to file Parameters ---------- entries : [dict] List of entries to plot. Each is represented by a dict, with the graph, label, and various other style options to be applied. output_filename : str Name of output plot file bin_title : str Bin title e.g. x < pT < y xtitle : str X axis label ytitle : str y axis label other_elements : [TObject], optional Other elements to Draw on the canvas logx : bool, optional Log x axis logy : bool, optional Log y axis do_line : bool, optional Do horizontal line at 1 xlimits : (min, max), optional Set hard x limits ylimits : (min, max), optional Set hard y limits y_limit_protection : (y_min, y_max), optional Set minimum and maximum y values in the event of a huge stat error or weird point draw_fits : bool, optional Draw fitted functions or not do_ratio : bool, optional Add ratio subplot """ plot = Plot(entries, what='graph', title=None, xtitle=xtitle, ytitle=ytitle, xlim=xlimits, ylim=ylimits, legend=True, subplot=entries[0] if do_ratio else None, subplot_type="ratio", subplot_title="Ratio to All") # replace legend with our own for now delta = 0.12 middle = 0.77 plot.legend = ROOT.TLegend(middle-delta, 0.75, middle+delta, 0.88) plot.legend.SetBorderSize(0) plot.legend.SetFillStyle(0) plot.legend.SetNColumns(2) plot.legend.SetTextAlign(ROOT.kHAlignCenter + ROOT.kVAlignCenter) plot.plot() if logx: plot.set_logx() if logy: plot.set_logy() plot.main_pad.cd() if not ylimits: plot.container.GetHistogram().SetMaximum(plot.container.GetYaxis().GetXmax() * 1.05) # Protection in case y limits are dominated by large stat error if y_limit_protection and len(y_limit_protection) == 2: y_min, y_max = plot.container.GetYaxis().GetXmin(), plot.container.GetYaxis().GetXmax() y_lim_lower, y_lim_upper = y_limit_protection if y_max > y_lim_upper: plot.container.GetHistogram().SetMaximum(y_lim_upper) if y_min < y_lim_lower: plot.container.GetHistogram().SetMinimum(y_lim_lower) # add protection for subplot if not ratio_limits: low_lim = 0.8 upper_lim = 1.2 y_min, y_max = plot.subplot_container.GetYaxis().GetXmin(), plot.subplot_container.GetYaxis().GetXmax() plot.subplot_container.GetYaxis().SetRangeUser(max(low_lim, y_min), min(y_max, upper_lim)) # set limits doesn't work for y axis elif len(ratio_limits) == 2: plot.subplot_container.GetYaxis().SetRangeUser(*ratio_limits) # set limits doesn't work for y axis plot.subplot_pad.Update() plot.canvas.Update() # if do_line: # y_min, y_max = plot.container.GetYaxis().GetXmin(), plot.container.GetYaxis().GetXmax() # if y_min < 1 and y_max > 1: # x_min, x_max = plot.container.GetXaxis().GetXmin(), plot.container.GetXaxis().GetXmax() # line = ROOT.TLine(x_min, 1, x_max, 1) # line.SetLineStyle(2) # line.SetLineColor(ROOT.kGray+2) # line.Draw() plot.canvas.cd() cms_text = ROOT.TPaveText(0.17, 0.84, 0.2, 0.85, "NDC") cms_text.AddText("CMS Simulation") cms_text.SetTextFont(62) cms_text.SetTextAlign(ROOT.kHAlignLeft + ROOT.kVAlignBottom) cms_text.SetTextSize(FONT_SIZE) cms_text.SetBorderSize(0) cms_text.SetFillStyle(0) cms_text.Draw() bin_text = ROOT.TPaveText(0.17, 0.8, 0.2, 0.81, "NDC") bin_text.AddText(bin_title) bin_text.SetTextFont(42) bin_text.SetTextSize(FONT_SIZE) bin_text.SetTextAlign(ROOT.kHAlignLeft + ROOT.kVAlignBottom) bin_text.SetBorderSize(0) bin_text.SetFillStyle(0) bin_text.Draw() if other_elements: for ele in other_elements: ele.Draw() plot.save(output_filename)