def do_mc_pt_comparison_plot(dirname_label_pairs, output_filename, qcd_filename, **plot_kwargs): # qcd_files = [cu.open_root_file(os.path.join(dl[0], qgc.QCD_FILENAME)) for dl in dirname_label_pairs] qcd_files = [ cu.open_root_file(os.path.join(dl[0], qgc.QCD_PYTHIA_ONLY_FILENAME)) for dl in dirname_label_pairs ] histname = "Dijet_tighter/pt_jet1" qcd_hists = [cu.get_from_tfile(qf, histname) for qf in qcd_files] N = len(dirname_label_pairs) conts = [ Contribution(qcd_hists[i], label=lab, marker_color=cu.get_colour_seq(i, N), line_color=cu.get_colour_seq(i, N), line_style=(i % 3) + 1, line_width=2, rebin_hist=1, subplot=qcd_hists[0] if i != 0 else None) for i, (d, lab) in enumerate(dirname_label_pairs) ] plot = Plot(conts, what='hist', ytitle="N", subplot_limits=(0.5, 1.5), subplot_type="ratio", subplot_title="* / %s" % (dirname_label_pairs[0][1]), **plot_kwargs) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.plot("NOSTACK HIST E") plot.set_logx(do_more_labels=False) plot.set_logy(do_more_labels=False) plot.save(output_filename)
def do_jet_pt_rel_error_with_var_cuts(histname, cuts, input_filename, output_filename): ROOT.gStyle.SetPalette(palette_1D) tf = cu.open_root_file(input_filename) h3d = cu.get_from_tfile(tf, histname) if h3d.GetEntries() == 0: return pt_hists = [] for cut in cuts: max_bin = h3d.GetZaxis().FindFixBin(cut) # print("cut:", cut, "bin:", max_bin) h = h3d.ProjectionY("pt_var_lt_%g" % cut, 0, -1, 0, max_bin, "e") h2 = h.Clone() h2.Rebin(2) if h.GetEntries() > 0: h3 = qgp.hist_divide_bin_width(h2) # convert bin contents to bin error/bin contents for ibin in range(1, h2.GetNbinsX()+1): if h3.GetBinContent(ibin) == 0: continue h3.SetBinContent(ibin, h3.GetBinError(ibin) / h3.GetBinContent(ibin)) h3.SetBinError(ibin, 0) pt_hists.append(h3) line_styles = [1, 2, 3] n_line_styles = len(line_styles) conts = [Contribution(h, label=" < %g" % cut, line_color=cu.get_colour_seq(ind, len(cuts)), line_style=line_styles[ind % n_line_styles], line_width=2, marker_color=cu.get_colour_seq(ind, len(cuts)), subplot=pt_hists[-1]) for ind, (h, cut) in enumerate(zip(pt_hists, cuts))] jet_str = pt_genjet_str if "_vs_pt_genjet_vs_" in histname else pt_str weight_str = "(unweighted)" if "unweighted" in histname else "(weighted)" ratio_lims = (0.98, 1.02) if "unweighted" in histname else None plot = Plot(conts, what='hist', title='%s for cuts on %s %s' % (jet_str, get_var_str(histname), weight_str), xtitle=None, ytitle='Relative error', # xlim=None, ylim=None, legend=True, subplot_type='ratio', subplot_title='* / var < %g' % cuts[-1], subplot_limits=ratio_lims, has_data=False) plot.y_padding_max_log = 200 plot.subplot_maximum_ceil = 2 plot.subplot_maximum_floor = 1.02 plot.subplot_minimum_ceil = 0.98 plot.legend.SetY1(0.7) plot.legend.SetY2(0.89) plot.legend.SetX1(0.78) plot.legend.SetX2(0.88) plot.plot("NOSTACK HISTE", "NOSTACK HIST") plot.set_logx(True, do_more_labels=True) plot.set_logy(True, do_more_labels=False) plot.save(output_filename)
def do_pf_fraction_plot(hist_map, pt_bins, output_filename): """Plot PF particle type fractioin for matches, binned by GenParticle pT""" entries = [] for pt_low, pt_high, mark in zip(pt_bins[:-1], pt_bins[1:], cu.Marker().cycle()): values = {} for pf_ind, (pf_name, hist) in hist_map.items(): ax = hist.GetXaxis() binx1 = ax.FindBin(pt_low) binx2 = ax.FindBin(pt_high) - 1 if pt_high == ax.GetBinUpEdge(ax.GetLast()): binx2 = ax.GetLast() biny1 = 1 biny2 = hist.GetNbinsY() binz1 = 1 binz2 = hist.GetNbinsZ() values[pf_ind] = hist.Integral( binx1, binx2, biny1, biny2, binz1, binz2) # integral includes the last bin sum_values = sum(values.values()) fracs = {k: (v / sum_values) for k, v in values.items()} h = ROOT.TH1D("h_pt_bin_%gto%g" % (pt_low, pt_high), "", len(values), 0, len(values)) ax = h.GetXaxis() for ind, k in enumerate(sorted(fracs.keys()), 1): h.SetBinContent(ind, fracs[k]) h.SetBinError(ind, sqrt(values[k]) / sum_values) ax.SetBinLabel(ind, hist_map[k][0]) c = Contribution(h, label='%g < GenParticle p_{T} < %g GeV' % (pt_low, pt_high), line_width=1, marker_size=0.75, marker_style=mark, normalise_hist=False) entries.append(c) ROOT.gStyle.SetPalette(55) plot = Plot(entries, 'hist', xtitle='PF particle type', ytitle='Fraction matched as type', ylim=(1E-3, 2), has_data=False) plot.default_canvas_size = (800, 600) plot.plot("NOSTACK PMC PLC HISTE") plot.set_logy(do_more_labels=False) plot.save(output_filename) ROOT.gStyle.SetPalette(ROOT.kViridis)
def do_data_mc_plot(dirname, histname, output_filename, **plot_kwargs): data_file = cu.open_root_file(os.path.join(dirname, qgc.JETHT_ZB_FILENAME)) qcd_file = cu.open_root_file(os.path.join(dirname, qgc.QCD_FILENAME)) qcd_py_file = cu.open_root_file( os.path.join(dirname, qgc.QCD_PYTHIA_ONLY_FILENAME)) qcd_hpp_file = cu.open_root_file( os.path.join(dirname, qgc.QCD_HERWIG_FILENAME)) data_hist = cu.get_from_tfile(data_file, histname) qcd_hist = cu.get_from_tfile(qcd_file, histname) qcd_py_hist = cu.get_from_tfile(qcd_py_file, histname) qcd_hpp_hist = cu.get_from_tfile(qcd_hpp_file, histname) conts = [ Contribution(data_hist, label="Data", line_color=ROOT.kBlack, marker_size=0, marker_color=ROOT.kBlack), Contribution(qcd_hist, label="QCD MG+PYTHIA8 MC", line_color=qgc.QCD_COLOUR, subplot=data_hist, marker_size=0, marker_color=qgc.QCD_COLOUR), Contribution(qcd_py_hist, label="QCD PYTHIA8 MC", line_color=qgc.QCD_COLOURS[2], subplot=data_hist, marker_size=0, marker_color=qgc.QCD_COLOURS[2]), # Contribution(qcd_hpp_hist, label="QCD HERWIG++ MC", line_color=qgc.HERWIGPP_QCD_COLOUR, subplot=data_hist, marker_size=0, marker_color=qgc.HERWIGPP_QCD_COLOUR), ] plot = Plot(conts, what='hist', ytitle="N", xtitle="p_{T}^{Leading jet} [GeV]", subplot_type="ratio", subplot_title="Simulation / data", ylim=[1E3, None], lumi=cu.get_lumi_str(do_dijet=True, do_zpj=False), **plot_kwargs) plot.y_padding_max_log = 500 plot.legend.SetX1(0.55) plot.legend.SetX2(0.98) plot.legend.SetY1(0.7) # plot.legend.SetY2(0.88) plot.plot("NOSTACK HIST E") plot.set_logx(do_more_labels=True, do_exponent=False) plot.set_logy(do_more_labels=False) plot.save(output_filename)
def do_genht_plot(dirname, output_filename, **plot_kwargs): qcd_file = cu.open_root_file(os.path.join(dirname, qgc.QCD_FILENAME)) histname = "Dijet_gen/gen_ht" qcd_hist = cu.get_from_tfile(qcd_file, histname) conts = [Contribution(qcd_hist, label="QCD MC", line_color=ROOT.kRed)] plot = Plot(conts, what='hist', ytitle="N", **plot_kwargs) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.plot("NOSTACK HIST E") plot.set_logx(do_more_labels=False) plot.set_logy(do_more_labels=False) plot.save(output_filename)
def print_hist_comparison(entries, plots_kwargs, output_filename): """Print multiple hists on canvas, no rescaling, no stacking entries: list[(object, kwargs for Contribution)] """ conts = [Contribution(e[0], **e[1]) for e in entries] logy = plots_kwargs.get('logy', False) if "logy" in plots_kwargs: del plots_kwargs['logy'] plot = Plot(conts, what="hist", **plots_kwargs) plot.plot("HISTE NOSTACK") if logy: plot.set_logy() plot.save(output_filename)
def do_plot(entries, output_file, hist_name=None, xlim=None, ylim=None, rebin=2, is_data=True, is_ak8=False): components = [] do_unweighted = any(["unweighted" in e.get('hist_name', hist_name) for e in entries]) for ent in entries: if 'tfile' not in ent: ent['tfile'] = cu.open_root_file(ent['filename']) ent['hist'] = cu.get_from_tfile(ent['tfile'], ent.get('hist_name', hist_name)) if not do_unweighted and 'scale' in ent: ent['hist'].Scale(ent.get('scale', 1)) components.append( Contribution(ent['hist'], fill_color=ent['color'], line_color=ent['color'], marker_color=ent['color'], marker_size=0, line_width=2, label=ent['label'], rebin_hist=rebin ) ) # print stats print(ent['hist_name'], ent['label'], ent['hist'].Integral()) title = 'AK8 PUPPI' if is_ak8 else 'AK4 PUPPI' plot = Plot(components, what='hist', has_data=is_data, title=title, xlim=xlim, ylim=ylim, xtitle="p_{T}^{jet 1} [GeV]", ytitle="Unweighted N" if do_unweighted else 'N') # plot.y_padding_min_log = 10 if 'unweighted' in hist_name else 10 plot.default_canvas_size = (700, 600) plot.legend.SetNColumns(2) plot.legend.SetX1(0.55) plot.legend.SetY1(0.7) plot.legend.SetY2(0.88) plot.plot("HISTE") plot.set_logx() plot.set_logy(do_more_labels=False) plot.save(output_file) # do non-stacked version stem, ext = os.path.splitext(output_file) plot.plot("HISTE NOSTACK") plot.set_logx() plot.set_logy(do_more_labels=False) plot.save(stem+"_nostack" + ext)
def do_pthat_comparison_plot(dirname_label_pairs, output_filename, **plot_kwargs): qcd_files = [ cu.open_root_file(os.path.join(dl[0], qgc.QCD_PYTHIA_ONLY_FILENAME)) for dl in dirname_label_pairs ] histname = "Dijet_gen/ptHat" qcd_hists = [cu.get_from_tfile(qf, histname) for qf in qcd_files] N = len(dirname_label_pairs) pthat_rebin = array('d', [ 15, 30, 50, 80, 120, 170, 300, 470, 600, 800, 1000, 1400, 1800, 2400, 3200, 5000 ]) nbins = len(pthat_rebin) - 1 qcd_hists = [ h.Rebin(nbins, cu.get_unique_str(), pthat_rebin) for h in qcd_hists ] conts = [ Contribution(qcd_hists[i], label=lab, marker_color=cu.get_colour_seq(i, N), line_color=cu.get_colour_seq(i, N), line_style=i + 1, line_width=2, subplot=qcd_hists[0] if i != 0 else None) for i, (d, lab) in enumerate(dirname_label_pairs) ] plot = Plot(conts, what='hist', ytitle="N", subplot_limits=(0.75, 1.25), subplot_type="ratio", subplot_title="* / %s" % (dirname_label_pairs[0][1]), **plot_kwargs) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.plot("NOSTACK HIST E") plot.set_logx(do_more_labels=False) plot.set_logy(do_more_labels=False) plot.save(output_filename)
def do_genht_comparison_plot(dirname_label_pairs, output_filename, **plot_kwargs): """Like do_genht but for multiple samples""" qcd_files = [ cu.open_root_file(os.path.join(dl[0], qgc.QCD_FILENAME)) for dl in dirname_label_pairs ] histname = "Dijet_gen/gen_ht" qcd_hists = [cu.get_from_tfile(qf, histname) for qf in qcd_files] N = len(dirname_label_pairs) conts = [ Contribution(qcd_hists[i], label=lab, marker_color=cu.get_colour_seq(i, N), line_color=cu.get_colour_seq(i, N), line_style=i + 1, line_width=2, subplot=qcd_hists[0] if i != 0 else None) for i, (d, lab) in enumerate(dirname_label_pairs) ] plot = Plot( conts, what='hist', ytitle="N", # subplot_limits=(0.75, 1.25), subplot_type="ratio", subplot_title="* / %s" % (dirname_label_pairs[0][1]), ylim=[1E6, None], **plot_kwargs) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.subplot_maximum_ceil = 5 plot.plot("NOSTACK HIST E") plot.set_logx(do_more_labels=False) plot.set_logy(do_more_labels=False) plot.save(output_filename)
def do_1D_plot(hists, output_filename, components_styles_dicts=None, draw_opts="NOSTACK HISTE", do_ratio=True, logx=False, logy=False, normalise_hists=True, title=""): if (len(hists) != len(components_styles_dicts)): raise RuntimeError("# hists != # components_styles_dicts (%d vs %d)" % (len(hists), len(components_styles_dicts))) hists = [h.Clone(h.GetName() + str(uuid1())) for h in hists] contributions = [ Contribution(hist, normalise_hist=normalise_hists, **csd) for hist, csd in zip(hists, components_styles_dicts) ] if len(contributions) == 0: return # Ignore if all empty objs total_entries = sum(c.obj.GetEntries() for c in contributions) if total_entries == 0: print("WARNING: all plots have 0 entries") return min_val = min([h.GetMinimum(0) for h in hists]) max_val = max([h.GetMaximum() for h in hists]) # print("Auto y limits:", min_val, max_val) if logy: ylim = [0.5 * min_val, 50 * max_val] else: # ylim = [0.5*min_val, 1.5*max_val] ylim = [0, 1.5 * max_val] # Auto calc x limits to avoid lots of empty bins high_bin = max([find_largest_filled_bin(h)[0] for h in hists]) low_bin = min([find_first_filled_bin(h)[0] for h in hists]) xlim = [ hists[0].GetBinLowEdge(low_bin - 1), hists[0].GetBinLowEdge(high_bin + 2) ] p = Plot( contributions, what='hist', ytitle="p.d.f." if normalise_hists else "N", title=title, xlim=xlim, ylim=ylim, subplot_type="ratio" if do_ratio else None, subplot_title="Herwig / PY8", subplot=contributions[0], subplot_limits=(0.5, 1.5), ) # p.legend.SetX1(0.55) # # p.legend.SetX2(0.95) # p.legend.SetY1(0.7) # p.legend.SetY2(0.85) p.legend.SetX1(0.5) p.legend.SetX2(0.97) if len(contributions) > 4: p.legend.SetY1(0.6) else: p.legend.SetY1(0.7) p.legend.SetY2(0.9) p.plot(draw_opts) if logy: p.set_logy() if logx: p.set_logx() p.save(output_filename)
def do_1D_plot(hists, output_filename, components_styles_dicts=None, draw_opts="NOSTACK HISTE", do_ratio=True, logx=False, logy=False, normalise_hists=True, title=""): if (len(hists) != len(components_styles_dicts)): raise RuntimeError("# hists != # components_styles_dicts (%d vs %d)" % (len(hists), len(components_styles_dicts))) hists = [h.Clone(cu.get_unique_str()) for h in hists] contributions = [Contribution(hist, normalise_hist=normalise_hists, label=csd.get('label', 'x'), **csd.get('style', {})) for hist, csd in zip(hists, components_styles_dicts)] if len(contributions) == 0: return # Ignore if all empty objs total_entries = sum(c.obj.GetEntries() for c in contributions) if total_entries == 0: print("WARNING: all plots have 0 entries") return min_val = min([h.GetMinimum(0) for h in hists]) max_val = max([h.GetMaximum() for h in hists]) # print("Auto y limits:", min_val, max_val) if logy: ylim = [0.5*min_val, 50*max_val] else: # ylim = [0.5*min_val, 1.5*max_val] ylim = [0, 1.5*max_val] # Auto calc x limits to avoid lots of empty bins high_bin = max([find_largest_filled_bin(h)[0] for h in hists]) low_bin = min([find_first_filled_bin(h)[0] for h in hists]) xlim = [hists[0].GetBinLowEdge(low_bin-1), hists[0].GetBinLowEdge(high_bin+2)] subplot_title = "* / %s" % contributions[0].label if len(contributions[0].label) > 10: # need padding to centralise it padding = ' ' * int(len(contributions[0].label)/2) subplot_title = "#splitline{%s* /%s}{%s}" % (padding, padding, contributions[0].label) p = Plot(contributions, what='hist', ytitle="#DeltaN/N" if normalise_hists else "N", title=title, xlim=xlim, ylim=ylim, subplot_type="ratio" if do_ratio else None, subplot_title=subplot_title, subplot=contributions[0], # subplot_limits=(0.5, 1.5), # subplot_limits=(0, 2) if logy else (0.5, 1.5), subplot_limits=(0, 2.5) if logy else (0.5, 1.5), ) # p.legend.SetX1(0.55) # # p.legend.SetX2(0.95) # p.legend.SetY1(0.7) # p.legend.SetY2(0.85) p.legend.SetX1(0.5) p.legend.SetX2(0.97) if len(contributions) > 4: p.legend.SetY1(0.6) else: p.legend.SetY1(0.7) p.legend.SetY2(0.9) p.plot(draw_opts) if logy: p.set_logy(do_more_labels=False) if logx: p.set_logx(do_more_labels=False) # p.save(os.path.join(output_dir, obj_name+".%s" % (OUTPUT_FMT))) p.save(output_filename)
def make_resolution_plots(h2d, xlabel, output_filename, do_fit=True, do_rms=True, quantiles=None, log_var=False, save_response_hists=False): """Make graph of resolution vs variables. Also optionally save all input histograms to file. """ one_sigma = 0.682689 quantiles = quantiles or [0.5 * (1 - one_sigma), 1 - 0.5 * (1 - one_sigma)] ax = h2d.GetXaxis() bin_edges = [ax.GetBinLowEdge(i) for i in range(1, ax.GetNbins() + 1)] bin_centers, sigmas, sigmas_unc = [], [], [] rel_sigmas, rel_sigmas_unc = [], [] # bin_centers = [ax.GetBinCenter(i) for i in range(1, ax.GetNbins()+1)] for var_min, var_max in zip(bin_edges[:-1], bin_edges[1:]): h_projection = qgg.get_projection_plot(h2d, var_min, var_max, cut_axis='x') if h_projection.GetEffectiveEntries() < 20: continue # h_projection.Rebin(rebin) h_projection.Scale(1. / h_projection.Integral()) bin_centers.append(0.5 * (var_max + var_min)) if do_fit: do_gaus_fit(h_projection) fit = h_projection.GetFunction("gausFit") # label += "\n" # label += fit_results_to_str(fit) # bin_centers.append(fit.GetParameter(1)) sigmas.append(fit.GetParameter(2)) rel_sigmas.append(fit.GetParameter(2) / bin_centers[-1]) sigmas_unc.append(fit.GetParError(2)) rel_sigmas_unc.append(fit.GetParError(2) / bin_centers[-1]) else: if do_rms: sigmas.append(sqrt(h_projection.GetRMS())) rel_sigmas.append( sqrt(h_projection.GetRMS()) / bin_centers[-1]) sigmas_unc.append(sqrt(h_projection.GetRMSError())) rel_sigmas_unc.append( sqrt(h_projection.GetRMSError()) / bin_centers[-1]) elif quantiles: if len(quantiles) != 2: raise RuntimeError("Need 2 quantiles") q = array('d', quantiles) results = array('d', [0.] * len(quantiles)) h_projection.GetQuantiles(len(quantiles), results, q) sigmas.append(results[1] - results[0]) sigmas_unc.append(0) rel_sigmas.append((results[1] - results[0]) / bin_centers[-1]) rel_sigmas_unc.append(0) else: raise RuntimeError( "Need either do_fit, do_rms, or 2-tuple in quantiles") if save_response_hists: xlabel = h_projection.GetXaxis().GetTitle() cont = Contribution(h_projection, label="GEN: %g-%g" % (var_min, var_max)) p = Plot([cont], what='hist') p.plot('HISTE') rsp_filename = os.path.abspath( output_filename.replace( ".%s" % OUTPUT_FMT, "_hist%gto%g.%s" % (var_min, var_max, OUTPUT_FMT))) rsp_dir = os.path.dirname(rsp_filename) rsp_file = os.path.basename(rsp_filename) p.save(os.path.join(rsp_dir, "responseHists", rsp_file)) gr = ROOT.TGraphErrors(len(bin_centers), array('d', bin_centers), array('d', sigmas), array('d', [0] * len(bin_centers)), array('d', sigmas_unc)) gr_cont = Contribution(gr, label="") ylabel = "" if do_fit: ylabel = "Fit #sigma" elif do_rms: ylabel = "#sqrt{RMS}" elif quantiles: ylabel = "Central %g" % one_sigma plot = Plot([gr_cont], what='graph', xtitle=xlabel, ytitle=ylabel, xlim=[bin_edges[0], bin_edges[-1]], ylim=[0, max(sigmas) * 1.2], legend=False) plot.plot() if log_var: plot.set_logx() plot.save(output_filename) gr_rel = ROOT.TGraphErrors(len(bin_centers), array('d', bin_centers), array('d', rel_sigmas), array('d', [0] * len(bin_centers)), array('d', rel_sigmas_unc)) gr_rel_cont = Contribution(gr_rel, label="") ylabel = "Relative %s" % ylabel plot = Plot([gr_rel_cont], what='graph', xtitle=xlabel, ytitle=ylabel, xlim=[bin_edges[0], bin_edges[-1]], ylim=[min(rel_sigmas) / 1.2, max(rel_sigmas) * 1.2], legend=False) plot.plot() plot.set_logy() if log_var: plot.set_logx() plot.save( output_filename.replace(".%s" % OUTPUT_FMT, "_relative.%s" % OUTPUT_FMT)) return gr, gr_rel
def make_plot(entries, output_filename, plot_kwargs, projection_axis='x', start_val=None, end_val=None, is_pdgid_plot=False, logy=False): """Make a plot from entries. Each one is a projection of a 2D plot. Parameters ---------- entries : list[dict] List of plot entries. Each is represented by a dict output_filename : str Filename for output plot plot_kwargs : dict kwargs for Plot constructor projection_axis : str, optional Axis to use for projection. If None, must be specified in entry. start_val : None, optional If set, use this to make 1D projection plot. Cuts on X axis. Otherwise should be set per entry. end_val : None, optional If set, use this to make 1D projection plot. Cuts on X axis. Otherwise should be set per entry. is_pdgid_plot : bool, optional True if for PDGIDs (sets special size & binning) logy : bool, optional Description Raises ------ RuntimeError Description """ conts = [] if not is_pdgid_plot: for ent in entries: h2d = cu.get_from_tfile( ent['file'], "ak4pfchsl1/" + ent['histname'] + "_JetEta0to0.783") start_val = ent.get('start_val', start_val) end_val = ent.get('end_val', end_val) if start_val is None or end_val is None: raise RuntimeError("Expected start_val and end_val") hist = cu.get_projection_plot( h2d, start_val, end_val, ent.get('projection_axis', projection_axis)) if hist.GetEntries() == 0: ent['used'] = False continue contrib = Contribution(hist, label=ent['label'], line_width=lw, line_color=ent['colour'], line_style=ent.get('line_style', 1), marker_size=ent.get('marker_size', 0), marker_color=ent['colour'], marker_style=ent.get('marker_style', 1), normalise_hist=True, rebin_hist=ent.get('rebin', None)) conts.append(contrib) ent['used'] = True else: # For PDGID plots, we want a different canvas aspect ratio, and only to include bins # with non-0 contents. We also relabel bins. custom_bins = [] for ent in entries: h2d = cu.get_from_tfile( ent['file'], "ak4pfchsl1/" + ent['histname'] + "_JetEta0to0.783") start_val = ent.get('start_val', start_val) end_val = ent.get('end_val', end_val) if not start_val or not end_val: raise RuntimeError("Expected start_val and end_val") hist = cu.get_projection_plot( h2d, start_val, end_val, ent.get('projection_axis', projection_axis)) ax = hist.GetXaxis() bins = dict() for i in range(1, hist.GetNbinsX() + 1): value = ax.GetBinLowEdge(i) cont = hist.GetBinContent(i) err = hist.GetBinError(i) if cont > 0: bins[value] = [cont, err] # print(custom_bins[-1]) custom_bins.append(bins) nbins = max([len(d) for d in custom_bins]) first_keys = set(custom_bins[0].keys()) for cb in custom_bins[1:]: first_keys = first_keys.union(set(cb.keys())) all_keys = sorted(list(first_keys)) print(all_keys) for cbin, ent in zip(custom_bins, entries): h = ROOT.TH1D(cu.get_unique_str(), ";PDGID;N", nbins, 0, nbins) for ind, k in enumerate(all_keys, 1): content, error = cbin.get(k, [0, 0]) h.SetBinContent(ind, content) h.SetBinError(ind, error) ax = h.GetXaxis() for i in range(1, nbins + 1): # ax.SetBinLabel(i, str(int(all_keys[i-1]))) pdgid = int(all_keys[i - 1]) ax.SetBinLabel(i, PDGID_STR.get(pdgid, str(pdgid))) h.LabelsOption("v") contrib = Contribution(h, label=ent['label'], line_width=lw, line_color=ent['colour'], line_style=ent.get('line_style', 1), marker_size=ent.get('marker_size', 0), marker_color=ent['colour'], marker_style=ent.get('marker_style', 1), normalise_hist=True, rebin_hist=ent.get('rebin', None)) conts.append(contrib) ent['used'] = True entries = [e for e in entries if e['used']] for ind, ent in enumerate(entries): if not ent['used']: continue if ent.get('subplot_ind', -1) >= 0: conts[ind].subplot = conts[ent['subplot_ind']].obj plot = Plot(conts, what="hist", ytitle="p.d.f.", has_data=False, **plot_kwargs) if is_pdgid_plot and conts[0].obj.GetNbinsX() > 10: plot.default_canvas_size = (800, 800) else: plot.default_canvas_size = (450, 600) plot.legend.SetX1(0.5) plot.legend.SetX2(0.97) if len(entries) > 4: plot.legend.SetY1(0.7) plot.legend.SetNColumns(2) else: plot.legend.SetY1(0.75) plot.legend.SetY2(0.9) plot.plot("HISTE NOSTACK") if logy: plot.set_logy() plot.save(output_filename)
def do_zerobias_per_run_comparison_plot(dirname_label_pairs, output_dir, append="", title="", **plot_kwargs): runs = [ (qgc.ZEROBIAS_RUNB_FILENAME, 'B'), (qgc.ZEROBIAS_RUNC_FILENAME, 'C'), (qgc.ZEROBIAS_RUND_FILENAME, 'D'), (qgc.ZEROBIAS_RUNE_FILENAME, 'E'), (qgc.ZEROBIAS_RUNF_FILENAME, 'F'), (qgc.ZEROBIAS_RUNG_FILENAME, 'G'), (qgc.ZEROBIAS_RUNH_FILENAME, 'H'), ] zb_entry = { 'label': 'HLT_ZeroBias', 'color': ROOT.kMagenta - 9, # 'scale': 35918219492.947 / 29048.362 'scale': 1 } for filename, run_period in runs: zb_root_files = [ cu.open_root_file(os.path.join(dl[0], filename)) for dl in dirname_label_pairs ] # PT JET 1 zb_hist_names = [ "Dijet_jet_hist_0/pt_1", "Dijet_jet_hist_unweighted_0/pt_1" ][1:] N = len(dirname_label_pairs) rebin = 2 for zb_name in zb_hist_names: # add zeero bias ones this_data_entries = [ Contribution( cu.get_from_tfile(zb_root_files[i], zb_name), label=zb_entry['label'] + " Run %s: " % run_period + l, marker_color=zb_entry['color'], line_color=zb_entry['color'], line_style=1 + i, rebin_hist=rebin, ) for i, (d, l) in enumerate(dirname_label_pairs) ] for c in this_data_entries[1:]: c.subplot = this_data_entries[0].obj plot = Plot( this_data_entries, what='hist', title=title, xtitle="p_{T}^{jet 1} [GeV]", ytitle="N", xlim=[30, 1000], ylim=[1E3, None], # ylim=[10, 1E8] if 'unweighted' in ht_name else [1, 1E12], subplot_type='ratio', subplot_title='* / %s' % dirname_label_pairs[0][1], **plot_kwargs) plot.subplot_maximum_ceil = 10 plot.default_canvas_size = (800, 600) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.legend.SetY2(0.88) plot.legend.SetX1(0.5) plot.legend.SetNColumns(2) plot.plot("NOSTACK HISTE") plot.set_logx(do_more_labels=False) plot.set_logy(do_more_labels=False) output_filename = "%s/DataJetHTZB-pt_jet1%s_Run%s%s.pdf" % ( output_dir, "_unweighted" if 'unweighted' in zb_name else "", run_period, append) plot.save(output_filename) # ETA JET 1 zb_hist_names = ["Dijet_jet_hist_unweighted_0/eta_1"] N = len(dirname_label_pairs) rebin = 2 for zb_name in zb_hist_names: # add zero bias ones this_data_entries = [ Contribution( cu.get_from_tfile(zb_root_files[i], zb_name), label=zb_entry['label'] + " Run %s: " % run_period + l, marker_color=zb_entry['color'], line_color=zb_entry['color'], line_style=1 + i, rebin_hist=rebin, ) for i, (d, l) in enumerate(dirname_label_pairs) ] for c in this_data_entries[1:]: c.subplot = this_data_entries[0].obj # plot zb plot = Plot( this_data_entries, what='hist', title=title, xtitle="y^{jet 1}", ytitle="N", subplot_type='ratio', subplot_title='* / %s' % dirname_label_pairs[0][1], # subplot_limits=(0, 5), **plot_kwargs) plot.subplot_maximum_ceil = 5 plot.default_canvas_size = (800, 600) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.legend.SetY2(0.88) plot.legend.SetX1(0.5) plot.legend.SetNColumns(2) plot.plot("NOSTACK HISTE") output_filename = "%s/DataZB-eta_jet1%s_Run%s%s.pdf" % ( output_dir, "_unweighted" if 'unweighted' in zb_name else "", run_period, append) plot.save(output_filename)
def plot_unfolded_with_yoda_normalised(self, do_chi2=False, do_zoomed=True): data_total_errors_style = dict( label="Data (total unc.)", line_color=self.plot_styles['unfolded_total_colour'], line_width=self.line_width, line_style=1, marker_color=self.plot_styles['unfolded_total_colour'], marker_style=cu.Marker.get('circle'), marker_size=self.plot_styles['unfolded_marker_size'], leg_draw_opt="LEP") data_stat_errors_style = dict( label="Data (stat. unc.)", line_color=self.plot_styles['unfolded_stat_colour'], line_width=self.line_width, line_style=1, marker_color=self.plot_styles['unfolded_stat_colour'], marker_style=cu.Marker.get('circle'), marker_size=0.0001, leg_draw_opt="LEP" ) # you need a non-0 marker to get the horizontal bars at the end of errors mc_style = dict(label=self.region['mc_label'], line_color=self.plot_styles['gen_colour'], line_width=self.line_width, marker_color=self.plot_styles['gen_colour'], marker_size=self.plot_styles['gen_marker_size'], marker_style=self.plot_styles['gen_marker'], leg_draw_opt="LEP" if self.plot_styles['gen_marker_size'] > 0 else "LE") rivet_path, rivet_region, rivet_radius, rivet_lambda, rivet_pt_bins = get_matching_rivet_setup( self.setup) for ibin, (bin_edge_low, bin_edge_high) in enumerate( zip(self.bins[:-1], self.bins[1:])): hbc_args = dict(ind=ibin, binning_scheme='generator') mc_gen_hist_bin = self.hist_bin_chopper.get_pt_bin_normed_div_bin_width( 'hist_truth', **hbc_args) unfolded_hist_bin_stat_errors = self.hist_bin_chopper.get_pt_bin_normed_div_bin_width( 'unfolded_stat_err', **hbc_args) unfolded_hist_bin_total_errors = self.hist_bin_chopper.get_pt_bin_normed_div_bin_width( 'unfolded', **hbc_args) # Get RIVET hists, which are absolute counts, so need normalising rivet_hist_name = '/%s/%s' % ( rivet_path, rn.get_plot_name(rivet_radius, rivet_region, rivet_lambda, rivet_pt_bins[ibin])) rivet_hists = [ qgp.normalise_hist_divide_bin_width( yoda.root.to_root(ent['yoda_dict'][rivet_hist_name])) for ent in self.rivet_entries ] # Create copy of data to go on top of stat unc, # but remove vertical error bar so we can see the stat unc # Note that you CAN'T set it to 0, otherwise vertical lines connecting # bins start being drawn. Instead set it to some super small value. unfolded_hist_bin_total_errors_marker_noerror = unfolded_hist_bin_total_errors.Clone( ) # clone to avoid restyling the original as well for i in range( 1, unfolded_hist_bin_total_errors_marker_noerror.GetNbinsX() + 1): unfolded_hist_bin_total_errors_marker_noerror.SetBinError( i, 1E-100) data_entries = [ Contribution(unfolded_hist_bin_total_errors, **data_total_errors_style), Contribution(unfolded_hist_bin_stat_errors, **data_stat_errors_style), # do data with black marker to get it on top Contribution(unfolded_hist_bin_total_errors_marker_noerror, **data_total_errors_style), ] # For subplot to ensure only MC errors drawn, not MC+data data_no_errors = unfolded_hist_bin_total_errors_marker_noerror.Clone( ) cu.remove_th1_errors(data_no_errors) this_mc_style = deepcopy(mc_style) rivet_styles = [] for ind, _ in enumerate(rivet_hists): s_dict = self.rivet_entries[ind]['style_dict'] rivet_styles.append( dict(label=s_dict['label'], line_color=s_dict['color'], line_width=self.line_width, marker_color=s_dict['color'], marker_size=s_dict.get( 'marker_size', self.plot_styles['gen_marker_size']), marker_style=s_dict['marker_style'], leg_draw_opt="LEP" if self.plot_styles['gen_marker_size'] > 0 else "LE")) # Calculate chi2 between data and MCs if desired if do_chi2: # print("unfolded_alt_truth bin", ibin) ematrix = self.hist_bin_chopper.get_pt_bin_normed_div_bin_width( self.unfolder.total_ematrix_name, **hbc_args) # stats are chi2, ndof, p mc_stats = calc_chi2_stats(unfolded_hist_bin_total_errors, mc_gen_hist_bin, ematrix) # print(mc_stats) # print(alt_mc_stats) nbins = sum([ 1 for i in range( 1, unfolded_hist_bin_total_errors.GetNbinsX() + 1) if unfolded_hist_bin_total_errors.GetBinContent(i) != 0 ]) # reduced_chi2 = mc_stats[0] / nbins # alt_reduced_chi2 = alt_mc_stats[0] / nbins n_sig_fig = 2 chi2_template = "\n#lower[-0.1]{{(#chi^{{2}} / N_{{bins}} = {chi2:g} / {nbins:d})}}" this_mc_style['label'] += chi2_template.format(chi2=cu.nsf( mc_stats[0], n_sig_fig), nbins=nbins) for ind, h in enumerate(rivet_hists): this_stats = calc_chi2_stats( unfolded_hist_bin_total_errors, h, ematrix) rivet_styles[ind]['label'] += chi2_template.format( chi2=cu.nsf(this_stats[0], n_sig_fig), nbins=nbins) mc_entries = [ Contribution(mc_gen_hist_bin, subplot=data_no_errors, **this_mc_style), ] for h, s_dict in zip(rivet_hists, rivet_styles): mc_entries.append( Contribution(h, subplot=data_no_errors, **s_dict)) entries = [ # Draw MC *mc_entries, # Draw data after to put on top of MC *data_entries ] func_name = cu.get_current_func_name() if not self.check_entries(entries, "%s bin %d" % (func_name, ibin)): return ymin = 0 if np.any( cu.th1_to_ndarray(unfolded_hist_bin_total_errors)[0] < 0): ymin = None # let it do its thing and auto calc ymin max_rel_err = 0.5 if "multiplicity" in self.setup.angle.var.lower( ) else -1 plot = Plot( entries, ytitle=self.setup.pt_bin_normalised_differential_label, title=self.get_pt_bin_title(bin_edge_low, bin_edge_high), legend=True, xlim=qgp.calc_auto_xlim( entries[2:3], max_rel_err=0.5), # set x lim to where data is non-0 ylim=[ymin, None], **self.pt_bin_plot_args) plot.subplot_title = qgc.SIM_DATA_STR self._modify_plot_paper(plot) # disable adding objects to legend & drawing - we'll do it manually plot.do_legend = False plot.legend.SetTextSize(0.03) plot.legend.SetY1(0.6) plot.legend.SetX1(0.57) plot.legend.SetX2(0.93) if len(entries) > 4: # if lots of entries, try auto-expand plot.legend.SetY1(0.6 - (0.02 * (len(entries) - 4))) # plot.legend.SetEntrySeparation(0.005) subplot_draw_opts = "NOSTACK E1" plot.plot("NOSTACK E1", subplot_draw_opts) dummy_graphs = qgp.do_fancy_legend(chain(data_entries[:2], mc_entries), plot, use_splitline=False) plot.canvas.cd() plot.legend.Draw() # Create hists for data with error region for ratio # Easiest way to get errors right is to do data (with 0 errors) # and divide by data (with errors), as if you had MC = data with 0 error data_stat_ratio = data_no_errors.Clone() data_stat_ratio.Divide(unfolded_hist_bin_stat_errors) data_stat_ratio.SetFillStyle(3245) data_stat_ratio.SetFillColor( self.plot_styles['unfolded_stat_colour']) data_stat_ratio.SetLineWidth(0) data_stat_ratio.SetMarkerSize(0) data_total_ratio = data_no_errors.Clone() data_total_ratio.Divide(unfolded_hist_bin_total_errors) data_total_ratio.SetFillStyle(3254) data_total_ratio.SetFillColor( self.plot_styles['unfolded_total_colour']) data_total_ratio.SetLineWidth(0) data_total_ratio.SetMarkerSize(0) # now draw the data error shaded area # this is a bit hacky - basically draw them on the ratio pad, # then redraw the existing hists & line to get them ontop # note that we use "same" for all - this is to keep the original axes # (we may want to rethink this later?) plot.subplot_pad.cd() draw_opt = "E2 SAME" data_stat_ratio.Draw(draw_opt) data_total_ratio.Draw(draw_opt) plot.subplot_line.Draw() plot.subplot_container.Draw("SAME" + subplot_draw_opts) # Add subplot legend x_left = 0.25 y_bottom = 0.75 width = 0.67 height = 0.15 plot.subplot_legend = ROOT.TLegend(x_left, y_bottom, x_left + width, y_bottom + height) plot.subplot_legend.AddEntry(data_total_ratio, qgc.DATA_TOTAL_UNC_STR, "F") plot.subplot_legend.AddEntry(data_stat_ratio, qgc.DATA_STAT_UNC_STR, "F") plot.subplot_legend.SetTextSize(0.085) plot.subplot_legend.SetFillStyle(0) plot.subplot_legend.SetNColumns(2) plot.subplot_legend.Draw() plot.canvas.cd() stp = self.setup fname = f"unfolded_{stp.append}_rivet_bin_{ibin:d}_divBinWidth{stp.paper_str}.{stp.output_fmt}" self.save_plot(plot, os.path.join(stp.output_dir, fname)) # Do version with small x values only if do_zoomed: if self.setup.angle.var in [ "jet_thrust_charged", "jet_width_charged", "jet_thrust", "jet_width" ]: # plot.ylim = (1E-5) plot.y_padding_max_log = 50 plot.y_padding_min_log = 0.5 plot.ylim = None plot.set_logy(do_exponent=False, do_more_labels=False) fname = f"unfolded_{stp.append}_alt_truth_bin_{ibin:d}_divBinWidth_logY.{stp.output_fmt}" self.save_plot(plot, os.path.join(stp.output_dir, fname)) if self.setup.angle.var in [ "jet_LHA_charged", "jet_thrust_charged", "jet_width_charged", "jet_thrust", "jet_width" ]: bin_edges = cu.get_bin_edges(mc_gen_hist_bin, 'x') # get the bin edge thats smallest between 0.2, and 5th bin bin_lt_lim = [x for x in bin_edges if x < 0.2][-1] upper_bin = min(bin_edges[5], bin_lt_lim) plot2 = Plot( entries, ytitle=self.setup.pt_bin_normalised_differential_label, title=self.get_pt_bin_title(bin_edge_low, bin_edge_high), xlim=(0, upper_bin), **self.pt_bin_plot_args) self._modify_plot(plot2) plot2.subplot_title = "* / Generator" plot2.plot("NOSTACK E1") # plot2.set_logx(do_exponent=False) fname = f"unfolded_{stp.append}_rivet_bin_{ibin:d}_divBinWidth_lowX.{stp.output_fmt}" self.save_plot(plot2, os.path.join(stp.output_dir, fname))
def do_jet_pt_with_var_cuts(histname, cuts, input_filename, output_filename): ROOT.gStyle.SetPalette(palette_1D) total = len(cuts) - 1 + .1 # slight offset to not hit the maximum or minimum # if len(cuts) <= 3: # ROOT.gStyle.SetPalette(ROOT.kCool) # num_colours = ROOT.TColor.GetPalette().fN - 1 # print('num_colours:', num_colours) # for index in range(len(cuts)): # print(num_colours, index, len(cuts), index / len(cuts), num_colours * index / total) # print(index, ROOT.TColor.GetColorPalette(int(num_colours * 1. * index / total))) tf = cu.open_root_file(input_filename) h3d = cu.get_from_tfile(tf, histname) if h3d.GetEntries() == 0: return pt_hists = [] for cut in cuts: max_bin = h3d.GetZaxis().FindFixBin(cut) # print("cut:", cut, "bin:", max_bin) h = h3d.ProjectionY("pt_var_lt_%g" % cut, 0, -1, 0, max_bin, "e") h2 = h.Clone() h2.Rebin(2) if h.GetEntries() > 0: h3 = qgp.hist_divide_bin_width(h2) pt_hists.append(h3) line_styles = [1, 2, 3] if len(cuts) <= 3: line_styles = [1] n_line_styles = len(line_styles) ref_ind = 0 conts = [Contribution(h, label=" < %g" % cut, line_color=cu.get_colour_seq(ind, total), line_style=line_styles[ind % n_line_styles], line_width=2, marker_color=cu.get_colour_seq(ind, total), subplot=pt_hists[ref_ind] if ind != ref_ind else None) for ind, (h, cut) in enumerate(zip(pt_hists, cuts))] jet_str = pt_genjet_str if "_vs_pt_genjet_vs_" in histname else pt_str weight_str = "(unweighted)" if "unweighted" in histname else "(weighted)" ratio_lims = (0.5, 2.5) ratio_lims = (0.5, 1.1) plot = Plot(conts, what='hist', title='%s for cuts on %s %s' % (jet_str, get_var_str(histname), weight_str), xtitle=None, ytitle='N', # xlim=None, ylim=None, legend=True, subplot_type='ratio', subplot_title='* / var < %g' % cuts[ref_ind], subplot_limits=ratio_lims, has_data=False) plot.y_padding_max_log = 200 plot.subplot_maximum_ceil = 4 plot.subplot_maximum_floor = 1.02 plot.subplot_minimum_ceil = 0.98 plot.legend.SetY1(0.7) plot.legend.SetY2(0.89) plot.legend.SetX1(0.78) plot.legend.SetX2(0.88) plot.plot("NOSTACK HISTE", "NOSTACK HIST") plot.set_logx(True, do_more_labels=True) plot.set_logy(True, do_more_labels=False) plot.save(output_filename)
def do_jetht_trigger_comparison_plot(dirname_label_pairs, output_dir, append="", title="", **plot_kwargs): # Unweighted pt, showing contributions from different triggers # Have to add in ZB manually zb_entry = { 'label': 'HLT_ZeroBias', 'color': ROOT.kMagenta - 9, # 'scale': 35918219492.947 / 29048.362 'scale': 1 } jet_ht_entries = [ { 'ind': '0', 'label': "PFJet40", 'color': ROOT.kRed, }, { 'ind': '1', 'label': "PFJet60", 'color': ROOT.kBlue, }, { 'ind': '2', 'label': "PFJet80", 'color': ROOT.kGreen + 2, }, { 'ind': '3', 'label': "PFJet140", 'color': ROOT.kViolet + 5, }, { 'ind': '4', 'label': "PFJet200", 'color': ROOT.kOrange, }, { 'ind': '5', 'label': "PFJet260", 'color': ROOT.kTeal, }, { 'ind': '6', 'label': "PFJet320", 'color': ROOT.kViolet, }, { 'ind': '7', 'label': "PFJet400", 'color': ROOT.kOrange - 6 }, { 'ind': '8', 'label': "PFJet450", 'color': ROOT.kAzure + 1, }, ] # PT JET 1 zb_hist_names = [ "Dijet_jet_hist_0/pt_1", "Dijet_jet_hist_unweighted_0/pt_1" ] jet_ht_hist_names = [ "Dijet_jet_hist_{ind}/pt_1", "Dijet_jet_hist_unweighted_{ind}/pt_1" ] zb_root_files = [ cu.open_root_file(os.path.join(dl[0], qgc.ZB_FILENAME)) for dl in dirname_label_pairs ] jetht_root_files = [ cu.open_root_file(os.path.join(dl[0], qgc.JETHT_FILENAME)) for dl in dirname_label_pairs ] N = len(dirname_label_pairs) rebin = 2 for zb_name, ht_name in zip(zb_hist_names, jet_ht_hist_names): # add zeero bias ones this_data_entries = [ Contribution( cu.get_from_tfile(zb_root_files[i], zb_name), label=zb_entry['label'] + ": " + l, marker_color=zb_entry['color'], line_color=zb_entry['color'], line_style=1 + i, rebin_hist=rebin, ) for i, (d, l) in enumerate(dirname_label_pairs) ] for c in this_data_entries[1:]: c.subplot = this_data_entries[0].obj # # add jet ht ones for ent in jet_ht_entries: histname = ht_name.format(ind=ent['ind']) new_entries = [ Contribution( cu.get_from_tfile(jetht_root_files[i], histname), label=ent['label'] + ": " + l, marker_color=ent['color'], line_color=ent['color'], line_style=1 + i, rebin_hist=rebin, ) for i, (d, l) in enumerate(dirname_label_pairs) ] for c in new_entries[1:]: c.subplot = new_entries[0].obj this_data_entries.extend(new_entries) plot = Plot( this_data_entries, what='hist', title=title, ytitle="N", xtitle="p_{T}^{jet 1} [GeV]", xlim=[30, 1000], ylim=[1E3, None], # ylim=[10, 1E8] if 'unweighted' in ht_name else [1, 1E12], subplot_type='ratio', subplot_title='* / %s' % dirname_label_pairs[0][1], **plot_kwargs) plot.default_canvas_size = (800, 600) plot.subplot_maximum_ceil = 10 plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.legend.SetY2(0.88) plot.legend.SetX1(0.5) plot.legend.SetNColumns(2) plot.plot("NOSTACK HISTE") plot.set_logx(do_more_labels=False) plot.set_logy(do_more_labels=False) output_filename = "%s/DataJetHTZB-pt_jet1%s%s.pdf" % ( output_dir, "_unweighted" if 'unweighted' in zb_name else "", append) plot.save(output_filename) # ETA JET 1 zb_hist_names = ["Dijet_jet_hist_unweighted_0/eta_1"] jet_ht_hist_names = ["Dijet_jet_hist_unweighted_{ind}/eta_1"] zb_root_files = [ cu.open_root_file(os.path.join(dl[0], qgc.ZB_FILENAME)) for dl in dirname_label_pairs ] jetht_root_files = [ cu.open_root_file(os.path.join(dl[0], qgc.JETHT_FILENAME)) for dl in dirname_label_pairs ] N = len(dirname_label_pairs) rebin = 2 for zb_name, ht_name in zip(zb_hist_names, jet_ht_hist_names): # add zero bias ones this_data_entries = [ Contribution( cu.get_from_tfile(zb_root_files[i], zb_name), label=zb_entry['label'] + ": " + l, marker_color=zb_entry['color'], line_color=zb_entry['color'], line_style=1 + i, rebin_hist=rebin, ) for i, (d, l) in enumerate(dirname_label_pairs) ] for c in this_data_entries[1:]: c.subplot = this_data_entries[0].obj # plot zb plot = Plot( this_data_entries, what='hist', title=title, xtitle="y^{jet 1}", ytitle="N", subplot_type='ratio', subplot_title='* / %s' % dirname_label_pairs[0][1], # subplot_limits=(0, 5), **plot_kwargs) plot.subplot_maximum_ceil = 5 plot.default_canvas_size = (800, 600) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.legend.SetY2(0.88) plot.legend.SetX1(0.5) plot.legend.SetNColumns(2) plot.plot("NOSTACK HISTE") output_filename = "%s/DataZB-eta_jet1%s%s.pdf" % ( output_dir, "_unweighted" if 'unweighted' in zb_name else "", append) plot.save(output_filename) # add jet ht ones for ent in jet_ht_entries: histname = ht_name.format(ind=ent['ind']) this_data_entries = [ Contribution( cu.get_from_tfile(jetht_root_files[i], histname), label=ent['label'] + ": " + l, marker_color=ent['color'], line_color=ent['color'], line_style=1 + i, rebin_hist=rebin, ) for i, (d, l) in enumerate(dirname_label_pairs) ] for c in this_data_entries[1:]: c.subplot = this_data_entries[0].obj plot = Plot( this_data_entries, what='hist', title=title, xtitle="y^{jet 1}", ytitle="N", # xlim=[30, 1000], # ylim=[10, 1E8] if 'unweighted' in ht_name else [1, 1E12], subplot_type='ratio', subplot_title='* / %s' % dirname_label_pairs[0][1], **plot_kwargs) plot.default_canvas_size = (800, 600) plot.y_padding_max_log = 500 plot.legend.SetY1(0.7) plot.legend.SetY2(0.88) plot.legend.SetX1(0.5) plot.legend.SetNColumns(2) plot.plot("NOSTACK HISTE") output_filename = "%s/DataJetHTZB-%s_eta_jet1%s%s.pdf" % ( output_dir, ent['label'], "_unweighted" if 'unweighted' in zb_name else "", append) plot.save(output_filename)
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)