def tvector_to_th1(vector, has_oflow_x=False): """Convert numpy ndarray row vector to TH1, with shape (1, nbins) Use has_oflow_x to include the under/overflow bins """ nbins_hist = vector.GetNrows() if has_oflow_x: nbins_hist -= 2 # need the 0.5 offset to match TUnfold h = ROOT.TH1F(cu.get_unique_str(), "", nbins_hist, 0.5, nbins_hist + 0.5) x_start = 1 x_end = nbins_hist if has_oflow_x: x_start = 0 x_end = nbins_hist + 1 for x_ind, ix in enumerate(range(x_start, x_end + 1)): h.SetBinContent(ix, vector[x_ind]) #FIXME how to do errors return h
def do_pt_transfer_plot(tdir, plot_dir): """Plot ratio between pt bins of the spectrum. Check to make sure xfer factor << drop in pt""" plot_dir = os.path.join(plot_dir, tdir.GetName()) cu.check_dir_exists_create(plot_dir) hist_name = "pt_jet_response_binning" h = cu.get_from_tfile(tdir, hist_name) binning = [ h.GetXaxis().GetBinLowEdge(bin_ind) for bin_ind in range(1, h.GetNbinsX() + 1) ] hist_factors = ROOT.TH1F( "hist_factors" + cu.get_unique_str(), ";p_{T}^{Reco} [GeV];Fraction rel to previous bin", len(binning) - 1, array('d', binning)) for bin_ind in range(2, h.GetNbinsX() + 1): cont = h.GetBinContent(bin_ind) cont_prev = h.GetBinContent(bin_ind - 1) if cont == 0 or cont_prev == 0: continue factor = cont / cont_prev hist_factors.SetBinContent(bin_ind, factor) hist_factors.SetBinError(bin_ind, 0) col_purity = ROOT.kBlack conts = [ Contribution(hist_factors, label="Factor relative to previous bin", line_color=col_purity, marker_color=col_purity), # Contribution(hist_purity, label="Purity (gen in right bin)", line_color=col_purity, marker_color=col_purity), ] xlim = [30, binning[-1]] plot = Plot(conts, what='hist', xlim=xlim) plot.plot() plot.set_logx() plot.save(os.path.join(plot_dir, 'pt_migration_factors.%s' % (OUTPUT_FMT)))
def do_comparison_graph(all_results, binning, output_dirs): if isinstance(output_dirs, str): output_dirs = [output_dirs]*len(binning) for bin_name, odir in zip(binning, output_dirs): mg = ROOT.TMultiGraph() c = ROOT.TCanvas("cmg"+cu.get_unique_str(), "", 800, 600) c.SetTicks(1, 1) leg = ROOT.TLegend(0.65, 0.2, 0.92, 0.42) colors = [ROOT.kBlack, ROOT.kBlue, ROOT.kRed, ROOT.kOrange+1, ROOT.kGreen+2] counter = 0 for name, result in all_results.items(): if bin_name not in name: continue thresholds = [info['threshold'] for k, info in result.items() if 'PFJet40' not in k] fully_eff_pt = [info['good_eff_pt'] for k, info in result.items() if 'PFJet40' not in k] g = ROOT.TGraph(len(thresholds), array('d', thresholds), array('d', fully_eff_pt)) g.SetMarkerColor(colors[counter]) g.SetMarkerStyle(20+counter) g.SetLineColor(colors[counter]) mg.Add(g) leg.AddEntry(g, name, "LP") counter += 1 mg.SetTitle(";Trigger threshold [GeV];99% efficiency p_{T} [GeV]") mg.Draw("ALP") leg.Draw() cms_text = ROOT.TPaveText(0.14, 0.9, 0.4, 0.92, "NDC") cms_text.AddText("CMS Preliminary %.3f fb^{-1}" % (total_lumi / 1e9)) cms_text.SetFillStyle(0) cms_text.SetBorderSize(0) cms_text.SetTextAlign(ROOT.kHAlignLeft + ROOT.kVAlignBottom) cms_text.SetTextFont(63) cms_text.SetTextSize(18) cms_text.Draw() c.SaveAs(odir+"/comparingTriggers_%s.%s" % (bin_name.replace(" ", "_"), OUTPUT_FMT))
def do_var_vs_pt_plot(histname, input_filename, output_filename): ROOT.gStyle.SetPalette(palette_2D) tf = cu.open_root_file(input_filename) h3d = cu.get_from_tfile(tf, histname) if h3d.GetEntries() == 0: return h2d = h3d.Project3D("zy") xlabel = h2d.GetXaxis().GetTitle() ylabel = h2d.GetYaxis().GetTitle() ylabel = get_var_str(histname) # find largest var value (ie row) that has a filled bin h2d_ndarray = cu.th2_to_ndarray(h2d)[0] xbins = np.array(cu.get_bin_edges(h2d, 'x')) ybins = np.array(cu.get_bin_edges(h2d, 'y')) # remove dodgy bins with 0 width cos I was an idiot and duplicated some bins n_deleted = 0 # weight bin # xax = h2d.GetXaxis() # for ix in range(1, h2d.GetNbinsX()+1): # if xax.GetBinWidth(ix) == 0: # h2d_ndarray = np.delete(h2d_ndarray, ix-1-n_deleted, axis=1) # xbins = np.delete(xbins, ix-1-n_deleted, axis=0) # n_deleted += 1 # print("Deleting bin", ix) # pt bin # n_deleted = 0 # yax = h2d.GetYaxis() # for iy in range(1, h2d.GetNbinsY()+1): # if yax.GetBinWidth(iy) == 0: # h2d_ndarray = np.delete(h2d_ndarray, iy-1-n_deleted, axis=0) # ybins = np.delete(ybins, iy-1-n_deleted, axis=0) # n_deleted += 1 # print("Deleting bin", iy) # nonzero returns (row #s)(col #s) of non-zero elements # we only want the largest row # max_filled_row_ind = int(np.nonzero(h2d_ndarray)[0].max()) h2d = cu.ndarray_to_th2(h2d_ndarray, binsx=xbins, binsy=ybins) if "unweighted" in histname: h2d.SetTitle("Unweighted;%s;%s" % (xlabel, ylabel)) else: h2d.SetTitle("Weighted;%s;%s" % (xlabel, ylabel)) h2d.GetYaxis().SetRange(1, max_filled_row_ind+2) # +1 as ROOT 1-indexed, +1 for padding h2d.GetYaxis().SetTitle(get_var_str(histname)) xmin = 15 if "pt_genjet_vs" in histname else 30 xmax = 300 canv = ROOT.TCanvas(cu.get_unique_str(), "", 800, 600) canv.SetTicks(1, 1) canv.SetLeftMargin(0.12) canv.SetRightMargin(0.15) # canv.SetLogz() # canv.SetLogy() h2d_copy = h2d.Clone() # h2d_copy.Scale(1, "width") h2d_copy.Draw("COLZ") canv.SetLogx() h2d_copy.GetXaxis().SetMoreLogLabels() canv.SaveAs(output_filename) zoom_ymin, zoom_ymax = 0.1, 5 h2d_copy.SetAxisRange(zoom_ymin, zoom_ymax,"Y") h2d_copy.SetAxisRange(xmin, xmax, "X") canv.SaveAs(output_filename.replace(".pdf", "_zoomY.pdf")) canv.SetLogz() canv.SaveAs(output_filename.replace(".pdf", "_zoomY_logZ.pdf")) canv.SetLogz(False) # h2d.Scale(1, "width") h2d_normed = cu.make_normalised_TH2(h2d, norm_axis='x', recolour=True) h2d_normed.Draw("COLZ") h2d_normed.GetXaxis().SetMoreLogLabels() # h2d_normed.SetMinimum(1E-5) h2d_normed.SetAxisRange(xmin, xmax, "X") canv.SaveAs(output_filename.replace(".pdf", "_normX.pdf")) h2d_normed.SetAxisRange(zoom_ymin, zoom_ymax,"Y") canv.SaveAs(output_filename.replace(".pdf", "_normX_zoomY.pdf")) # Do cumulative plot per column (ie fraction of events passing cut < y) h2d_ndarray_cumsum = h2d_ndarray.cumsum(axis=0) nonzero_mask = h2d_ndarray_cumsum[-1] > 0 h2d_ndarray_cumsum[:, nonzero_mask] /= h2d_ndarray_cumsum[-1][nonzero_mask] # scale so total is 1 h2d_cumsum = cu.ndarray_to_th2(h2d_ndarray_cumsum, binsx=xbins, binsy=ybins) # Get max row ind max_filled_row_ind = int(h2d_ndarray_cumsum.argmax(axis=0).max()) h2d_cumsum.GetYaxis().SetRange(1, max_filled_row_ind+1) # +1 as ROOT 1-indexed # ROOT.gStyle.SetPalette(ROOT.kBird) ylabel = "Fraction of events with " + ylabel + " < y" if "unweighted" in histname: h2d_cumsum.SetTitle("Unweighted;%s;%s" % (xlabel, ylabel)) else: h2d_cumsum.SetTitle("Weighted;%s;%s" % (xlabel, ylabel)) canv.Clear() canv.SetLogz(False) h2d_cumsum.SetContour(20) h2d_cumsum.Draw("CONT1Z") h2d_cumsum.SetAxisRange(xmin, xmax, "X") canv.SetLogx() h2d_cumsum.GetXaxis().SetMoreLogLabels() canv.SaveAs(output_filename.replace(".pdf", "_cumulY.pdf")) h2d_cumsum.SetAxisRange(zoom_ymin, zoom_ymax,"Y") canv.SaveAs(output_filename.replace(".pdf", "_cumulY_zoomY.pdf")) canv.Clear() h2d_normed.Draw("COL") h2d_cumsum.Draw("CONT1Z SAME") h2d_cumsum.SetAxisRange(xmin, xmax, "X") canv.SetLogx() h2d_cumsum.GetXaxis().SetMoreLogLabels() canv.SaveAs(output_filename.replace(".pdf", "_cumulY_normX.pdf")) h2d_cumsum.SetAxisRange(zoom_ymin, zoom_ymax,"Y") canv.SaveAs(output_filename.replace(".pdf", "_cumulY_normX_zoomY.pdf")) tf.Close()
def do_cut_roc_per_pt(histname, input_filename, output_filename): """Plot fractional # unweighted vs fraction # weighted, for different cuts Not a true ROC, but kinda like one """ ROOT.gStyle.SetPalette(palette_1D) tf = cu.open_root_file(input_filename) h3d = cu.get_from_tfile(tf, histname) h3d_unweighted = cu.get_from_tfile(tf, histname+"_unweighted") if h3d.GetEntries() == 0: return canv = ROOT.TCanvas(cu.get_unique_str(), "", 800, 600) canv.SetTicks(1, 1) canv.SetLeftMargin(0.12) canv.SetRightMargin(0.12) # canv.SetLogz() h2d = h3d.Project3D("zy") # var vs pt h2d_unweighted = h3d_unweighted.Project3D("zy") # var vs pt var_name = os.path.basename(histname).replace("weight_vs_pt_vs_", "").replace("weight_vs_pt_genjet_vs_", "") for ibin in range(3, h2d.GetNbinsX()+1): # iterate over pt bins if h2d.Integral(ibin, ibin+1, 0, -1) == 0: # data.append(None) continue pt_low = h3d.GetYaxis().GetBinLowEdge(ibin) pt_high = h3d.GetYaxis().GetBinLowEdge(ibin+1) data = [] data_unweighted = [] # Do integral, error for increasingly looser cuts # find maximum in this pt bin # yes I probably should collapse to a 1D hist and use GetMaximumBin max_val, max_bin = 0, 0 for icut in range(1, h2d.GetNbinsY()+1): val = h2d.GetBinContent(ibin, icut) if val > max_val: max_val = val max_bin = icut for icut in range(max_bin + 5, h2d.GetNbinsY()+2, 2): # for icut in range(2, h2d.GetNbinsY()+2): err = array('d', [0]) count = h2d.IntegralAndError(ibin, ibin+1, 1, icut-1, err) if count == 0: continue data.append([count, err[0], h2d.GetYaxis().GetBinLowEdge(icut)]) err = array('d', [0]) count = h2d_unweighted.IntegralAndError(ibin, ibin+1, 1, icut-1, err) data_unweighted.append([count, err[0], h2d.GetYaxis().GetBinLowEdge(icut)]) cuts = np.array([d[2] for d in data][1:]) # cuts = np.array([d[2] for d in data]) weighted_fractions = np.array([abs(d[0]-dd[0]) / dd[0] for d, dd in zip(data[:-1], data[1:])]) unweighted_fractions = np.array([abs(d[0]-dd[0]) / dd[0] for d, dd in zip(data_unweighted[:-1], data_unweighted[1:])]) non_zero_mask = (unweighted_fractions>0) & (weighted_fractions>0) non_zero_weighted = weighted_fractions[non_zero_mask] weight_min_pow = math.floor(math.log10(min(non_zero_weighted))) if len(non_zero_weighted) > 0 else -10 weight_max_pow = math.floor(math.log10(max(non_zero_weighted))) if len(non_zero_weighted) > 0 else 0 assert(weight_max_pow>=weight_min_pow) non_zero_unweighted = unweighted_fractions[non_zero_mask] unweight_min_pow = math.floor(math.log10(min(non_zero_unweighted))) if len(non_zero_unweighted) > 0 else -10 unweight_max_pow = math.floor(math.log10(max(non_zero_unweighted))) if len(non_zero_unweighted) > 0 else 0 assert(unweight_max_pow>=unweight_min_pow) mask = unweighted_fractions < 10**(unweight_min_pow+1) # last decade of unweighted drops mask &= weighted_fractions > 10**(weight_max_pow-1) # largest decades of weighted drops if np.sum(mask) == 0: continue # weighted_fractions = np.array([d[0] / data[-1][0] for d in data]) # unweighted_fractions = np.array([d[0] / data_unweighted[-1][0] for d in data_unweighted]) unweighted_useful = unweighted_fractions[mask & non_zero_mask] weighted_useful = weighted_fractions[mask & non_zero_mask] if "pt_jet_genHT_ratio" in histname and pt_low == 800: print("weight_min_pow:", weight_min_pow) print("weight_max_pow:", weight_max_pow) print("unweight_min_pow:", unweight_min_pow) print("unweight_max_pow:", unweight_max_pow) print("unweight_max_pow:", unweight_max_pow) print("weighted_useful:", weighted_useful) print("unweighted_useful:", unweighted_useful) gr_count = ROOT.TGraph(len(unweighted_useful), unweighted_useful, weighted_useful) gr_count.SetMarkerColor(ROOT.kRed) gr_count.SetMarkerSize(0) gr_count.SetMarkerStyle(21) gr_count.SetLineColor(ROOT.kRed) gr_count.SetTitle("%s, %g < p_{T} < %g GeV;Relative unweighted count;Relative weighted count" % (get_var_str(histname), pt_low, pt_high)) gr_count.SetTitle("%s, %g < p_{T} < %g GeV;Unweighted fractional drop;Weighted fractional drop" % (get_var_str(histname), pt_low, pt_high)) # add annotations of cuts latexs = [] for i, cut in enumerate(cuts[mask * non_zero_mask]): latex = ROOT.TLatex(gr_count.GetX()[i], gr_count.GetY()[i], " < %.2f" % cut) latex.SetTextSize(0.02) latex.SetTextColor(ROOT.kBlue) gr_count.GetListOfFunctions().Add(latex) latexs.append(latex) # canv.SetLogx(False) # canv.SetLogy(False) # ROOT.TGaxis.SetMaxDigits(2) # gr_count.Draw("ALP") # ROOT.TGaxis.SetMaxDigits(2) # unweighted_min = 0.9999 # # Calculate differences between points # unweighted_diffs = unweighted_fractions[1:] - unweighted_fractions[:-1] # weighted_diffs = weighted_fractions[1:] - weighted_fractions[:-1] # big_diff_inds = [] # for ind, (u, w) in enumerate(zip(unweighted_diffs, weighted_diffs)): # # look for big diff in weighted frac, small diff in unweighted, # # with a limit on the minimum size of unweighted frac # # (only trying to remove a few events) # if u > 0 and w / u > 100 and u < 0.005 and unweighted_fractions[ind] > unweighted_min: # big_diff_inds.append(ind) # if "pt_jet_genHT_ratio" in histname and pt_low == 186: # for u, w in zip(unweighted_diffs, weighted_diffs): # print(u, w) # print(big_diff_inds) # make graph of big diff points, add annotations of cuts # if len(big_diff_inds) > 0: # gr_big_diffs = ROOT.TGraph(len(big_diff_inds), array('d', [unweighted_fractions[i+1] for i in big_diff_inds]), array('d', [weighted_fractions[i+1] for i in big_diff_inds])) # gr_big_diffs.SetLineWidth(0) # gr_big_diffs.SetMarkerColor(ROOT.kBlue) # gr_big_diffs.SetMarkerStyle(25) # latexs = [] # for i, ind in enumerate(big_diff_inds[:]): # latex = ROOT.TLatex(gr_big_diffs.GetX()[i], gr_big_diffs.GetY()[i], " < %.2f" % cuts[ind+1]) # latex.SetTextSize(0.02) # latex.SetTextColor(ROOT.kBlue) # gr_big_diffs.GetListOfFunctions().Add(latex) # latexs.append(latex) # gr_big_diffs.Draw("*") # gr_count.GetXaxis().SetLimits(unweighted_min, 1) # find corresponding value for weighted to set axis range # weighted_min = 0 # for ind, u in enumerate(unweighted_fractions): # if u >= unweighted_min: # weighted_min = weighted_fractions[ind-1] # if ind == len(unweighted_fractions) - 1: # weighted_min = 0 # break # gr_count.GetHistogram().SetMinimum(weighted_min*1.1 - 0.1) # gr_count.GetHistogram().SetMaximum(1) # canv.SaveAs(output_filename.replace(".pdf", "_count_pt%gto%g.pdf" % (pt_low, pt_high))) # do a version zoomed out canv.Clear() gr_count.SetMarkerSize(0.5) gr_count.Draw("AP") # unweighted_min = 0. # gr_count.GetXaxis().SetLimits(unweighted_min, 1) # weighted_min = 0 # for ind, u in enumerate(unweighted_fractions): # if u >= unweighted_min: # weighted_min = weighted_fractions[ind-1] # if ind == len(unweighted_fractions) - 1: # weighted_min = 0 # break # gr_count.GetHistogram().SetMinimum(weighted_min*1.1 - 0.1) gr_count.GetXaxis().SetMoreLogLabels() gr_count.GetYaxis().SetMoreLogLabels() weight_min_pow = math.floor(math.log10(min(weighted_useful))) if len(weighted_useful) > 0 else -10 weight_max_pow = math.floor(math.log10(max(weighted_useful))) if len(weighted_useful) > 0 else 0 unweight_min_pow = math.floor(math.log10(min(unweighted_useful))) if len(unweighted_useful) > 0 else -10 unweight_max_pow = math.floor(math.log10(max(unweighted_useful))) if len(unweighted_useful) > 0 else 0 gr_count.GetHistogram().SetMinimum(10**weight_min_pow) gr_count.GetHistogram().SetMaximum(10**(weight_max_pow+1)) gr_count.GetXaxis().SetLimits(10**unweight_min_pow, 10**(unweight_max_pow+1)) canv.SetLogy() canv.SetLogx() canv.SaveAs(output_filename.replace(".pdf", "_count_pt%gto%g_all.pdf" % (pt_low, pt_high))) tf.Close()
def do_cut_scan_per_pt(histname, input_filename, output_filename): ROOT.gStyle.SetPalette(palette_1D) tf = cu.open_root_file(input_filename) h3d = cu.get_from_tfile(tf, histname) h3d_unweighted = cu.get_from_tfile(tf, histname+"_unweighted") if h3d.GetEntries() == 0: return canv = ROOT.TCanvas(cu.get_unique_str(), "", 800, 600) canv.SetTicks(1, 1) canv.SetLeftMargin(0.12) canv.SetRightMargin(0.12) # canv.SetLogz() h2d = h3d.Project3D("zy") # var vs pt h2d_unweighted = h3d_unweighted.Project3D("zy") # var vs pt var_name = os.path.basename(histname).replace("weight_vs_pt_vs_", "").replace("weight_vs_pt_genjet_vs_", "") for ibin in range(3, h2d.GetNbinsX()+1): # iterate over pt bins if h2d.Integral(ibin, ibin+1, 0, -1) == 0: # data.append(None) continue pt_low = h3d.GetYaxis().GetBinLowEdge(ibin) pt_high = h3d.GetYaxis().GetBinLowEdge(ibin+1) data = [] data_unweighted = [] # Do integral, error for increasingly looser cuts # find maximum in this pt bin # yes I probably should collapse to a 1D hist and use GetMaximumBin max_val, max_bin = 0, 0 for icut in range(1, h2d.GetNbinsY()+1): val = h2d.GetBinContent(ibin, icut) if val > max_val: max_val = val max_bin = icut for icut in range(max_bin + 5, h2d.GetNbinsY()+2): err = array('d', [0]) count = h2d.IntegralAndError(ibin, ibin+1, 1, icut-1, err) if count == 0: continue data.append([count, err[0], h2d.GetYaxis().GetBinLowEdge(icut)]) err = array('d', [0]) count = h2d_unweighted.IntegralAndError(ibin, ibin+1, 1, icut, err) data_unweighted.append([count, err[0], h2d.GetYaxis().GetBinLowEdge(icut)]) # Plot count, rel error vs cut value cuts = [d[2] for d in data] gr_count = ROOT.TGraph(len(data), array('d', cuts), array('d', [d[0] / data[-1][0] for d in data])) gr_count.SetMarkerColor(ROOT.kRed) gr_count.SetMarkerStyle(22) gr_count.SetLineColor(ROOT.kRed) gr_count.SetTitle("%g < p_{T} < %g GeV;%s cut (<);Count (relative to loosest cut)" % (pt_low, pt_high, get_var_str(histname))) gr_count_unweighted = ROOT.TGraph(len(data), array('d', cuts), array('d', [d[0] / data_unweighted[-1][0] for d in data_unweighted])) gr_count_unweighted.SetMarkerColor(ROOT.kBlack) gr_count_unweighted.SetMarkerStyle(23) gr_count_unweighted.SetLineColor(ROOT.kBlack) gr_count_unweighted.SetTitle("%g < p_{T} < %g GeV;%s cut (<);Count (relative to loosest cut)" % (pt_low, pt_high, get_var_str(histname))) leg = ROOT.TLegend(0.7, 0.5, 0.85, 0.65) leg.AddEntry(gr_count, "Weighted", "LP") leg.AddEntry(gr_count_unweighted, "Unweighted", "LP") # gr_rel_err = ROOT.TGraph(len(data), array('d', cuts), array('d', [(d[1] / d[0]) if d[0] != 0 else 0 for d in data ])) # gr_rel_err.SetMarkerColor(ROOT.kRed) # gr_rel_err.SetMarkerStyle(22) # gr_rel_err.SetLineColor(ROOT.kRed) # gr_rel_err.SetTitle("%g < p_{T} < %g GeV;%s cut (<);Rel. error" % (pt_low, pt_high, var_name)) canv.SetLogy(False) gr_count.Draw("ALP") gr_count_unweighted.Draw("LP") gr_count.Draw("LP") leg.Draw() canv.SaveAs(output_filename.replace(".pdf", "_count_pt%gto%g.pdf" % (pt_low, pt_high))) # canv.Clear() # gr_rel_err.Draw("ALP") # canv.SetLogy() # gr_rel_err.GetYaxis().SetMoreLogLabels() # canv.SaveAs(output_filename.replace(".pdf", "_rel_err_pt%gto%g.pdf" % (pt_low, pt_high))) tf.Close()
def plot_jet_pt_response_matrix(h2d, h2d_renorm_x, h2d_renorm_y, title, plot_dir): """Plot 2D response matrix, absolute, and normed by x & y axes""" canv = ROOT.TCanvas("c"+cu.get_unique_str(), "", 700, 600) canv.SetTicks(1, 1) canv.SetLogx() canv.SetLogy() pad = ROOT.gPad pad.SetBottomMargin(0.12) pad.SetLeftMargin(0.13) pad.SetRightMargin(0.19) def _setup_map(hist_2d): xax = hist_2d.GetXaxis() xax.SetMoreLogLabels() xax.SetNoExponent() yax = hist_2d.GetYaxis() yax.SetMoreLogLabels() yax.SetNoExponent() xtitle_offset = 1.4 ytitle_offset = xtitle_offset * 1.2 ztitle_offset = xtitle_offset hist_2d.SetTitleOffset(xtitle_offset, 'X') hist_2d.SetTitleOffset(ytitle_offset, 'Y') hist_2d.SetTitleOffset(ztitle_offset, 'Z') _setup_map(h2d) h2d.SetMinimum(1E-3) var_label = 'p_{T}^{jet} [GeV]' title = "%s;%s (GEN);%s (RECO);N" % (title, var_label, var_label) h2d.SetTitle(title) h2d.Draw("COLZ") old_font_size = ROOT.gStyle.GetTitleFontSize() output_filename = os.path.join(plot_dir, "jet_pt.%s" % (OUTPUT_FMT)) if not os.path.isdir(plot_dir): os.makedirs(plot_dir) canv.SaveAs(output_filename) canv.SetLogz() output_filename = os.path.join(plot_dir, "jet_pt_logZ.%s" % (OUTPUT_FMT)) canv.SaveAs(output_filename) # Plot 2D map, renormalized by row canv.SetLogz(0) marker_size = 0.8 _setup_map(h2d_renorm_y) h2d_renorm_y.SetTitle(title) h2d_renorm_y.SetMarkerSize(marker_size) h2d_renorm_y.SetMaximum(1) h2d_renorm_y.SetZTitle("P(GEN bin | RECO bin)") draw_opt = "COLZ" plot_migrations = True if plot_migrations: draw_opt += " TEXT45" h2d_renorm_y.Draw(draw_opt) canv.SaveAs(os.path.join(plot_dir, "jet_pt_renormY_linZ.%s" % (OUTPUT_FMT))) canv.SetLogz() h2d_renorm_y.SetMinimum(1E-3) canv.SaveAs(os.path.join(plot_dir, "jet_pt_renormY_logZ.%s" % (OUTPUT_FMT))) # Plot 2D map, renormalized by column canv.Clear() canv.SetLogz(0) _setup_map(h2d_renorm_x) h2d_renorm_x.SetTitle(title) h2d_renorm_x.SetMarkerSize(marker_size) h2d_renorm_x.SetMaximum(1) h2d_renorm_x.SetZTitle("P(RECO bin | GEN bin)") h2d_renorm_x.Draw(draw_opt) canv.SaveAs(os.path.join(plot_dir, "jet_pt_renormX_linZ.%s" % (OUTPUT_FMT))) canv.SetLogz() h2d_renorm_x.SetMinimum(1E-3) canv.SaveAs(os.path.join(plot_dir, "jet_pt_renormX_logZ.%s" % (OUTPUT_FMT))) ROOT.gStyle.SetTitleFontSize(old_font_size)
def make_plots(h2d, var_dict, plot_dir, append="", plot_migrations=True): """Plot a 2D hist, with copies renormalised by row and by column. Also optionally plot migrations as 1D plot. """ canv = ROOT.TCanvas("c" + cu.get_unique_str(), "", 700, 600) canv.SetTicks(1, 1) if var_dict.get("log", False): canv.SetLogx() canv.SetLogy() pad = ROOT.gPad pad.SetBottomMargin(0.12) pad.SetLeftMargin(0.13) pad.SetRightMargin(0.12) xtitle_offset = 1.4 ytitle_offset = xtitle_offset * 1.1 h2d.SetTitleOffset(xtitle_offset, 'X') h2d.SetTitleOffset(ytitle_offset, 'Y') h2d.SetMinimum(1E-3) if var_dict.get('log', False): h2d.GetXaxis().SetLimits(1, 150) h2d.GetYaxis().SetLimits(1, 150) if "title" in var_dict: h2d.SetTitle(var_dict['title']) h2d.Draw("COLZ") output_filename = os.path.join( plot_dir, var_dict['name'] + "_%s.%s" % (append, OUTPUT_FMT)) output_dir = os.path.dirname(output_filename) if not os.path.isdir(output_dir): os.makedirs(output_dir) canv.SaveAs(output_filename) canv.SetLogz() output_filename = os.path.join( plot_dir, var_dict['name'] + "_%s_logZ.%s" % (append, OUTPUT_FMT)) canv.SaveAs(output_filename) # renorm by row canv.SetLogz(0) h2d_renorm_y = cu.make_normalised_TH2(h2d, 'Y', recolour=False, do_errors=False) marker_size = 0.8 h2d_renorm_y.SetMarkerSize(marker_size) h2d_renorm_y.SetMaximum(1) draw_opt = "COLZ" if plot_migrations: draw_opt += " TEXT45" h2d_renorm_y.SetMinimum(1E-3) h2d_renorm_y.Draw(draw_opt) xtitle_offset = 1.5 h2d_renorm_y.SetTitleOffset(xtitle_offset, 'X') yax = h2d_renorm_y.GetYaxis() h2d_renorm_y.SetTitleOffset(ytitle_offset, 'Y') canv.Update() canv.SaveAs( os.path.join( plot_dir, "%s_%s_renormY_linZ.%s" % (var_dict['name'], append, OUTPUT_FMT))) canv.SetLogz() h2d_renorm_y.SetMaximum(1) h2d_renorm_y.SetMinimum(1E-3) canv.SaveAs( os.path.join( plot_dir, "%s_%s_renormY_logZ.%s" % (var_dict['name'], append, OUTPUT_FMT))) # renorm by column canv.Clear() canv.SetLogz(0) h2d_renorm_x = cu.make_normalised_TH2(h2d, 'X', recolour=False, do_errors=False) h2d_renorm_x.SetMarkerSize(marker_size) h2d_renorm_x.SetMaximum(1) h2d_renorm_x.SetMinimum(1E-3) h2d_renorm_x.Draw(draw_opt) h2d_renorm_x.SetTitleOffset(xtitle_offset, 'X') yax = h2d_renorm_x.GetYaxis() h2d_renorm_x.SetTitleOffset(ytitle_offset, 'Y') yax.SetMoreLogLabels() canv.Update() canv.SaveAs( os.path.join( plot_dir, "%s_%s_renormX_linZ.%s" % (var_dict['name'], append, OUTPUT_FMT))) canv.SetLogz() h2d_renorm_x.SetMaximum(1) h2d_renorm_x.SetMinimum(1E-3) canv.SaveAs( os.path.join( plot_dir, "%s_%s_renormX_logZ.%s" % (var_dict['name'], append, OUTPUT_FMT))) # Plot migrations if plot_migrations: output_filename = os.path.join( plot_dir, "%s_migration_summary.%s" % (var_dict['name'], OUTPUT_FMT)) qgg.make_migration_summary_plot(h2d_renorm_x, h2d_renorm_y, var_dict['var_label'], 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 do_response_plot(tdir, plot_dir, var_name, xlabel, log_var=False, rebinx=1, rebiny=1, do_migration_summary_plots=True, do_resolution_plots=True, save_response_hists=False): """Do 2D plots of genjet pt vs recojet pt""" h2d_orig = cu.get_from_tfile(tdir, var_name) h2d = h2d_orig.Clone(cu.get_unique_str()) h2d.RebinX(rebinx) h2d.RebinY(rebiny) pt_regions = [ { "append": "_lowPt", "title": "30 < p_{T}^{Reco} < 100 GeV", }, { "append": "_midPt", "title": "100 < p_{T}^{Reco} < 250 GeV", }, { "append": "_highPt", "title": "p_{T}^{Reco} > 250 GeV", }, ] pt_bin_name = "" for region in pt_regions: if region['append'] in var_name: pt_bin_name = region['title'] title = "%s;%s (GEN);%s (RECO)" % (pt_bin_name, xlabel, xlabel) # title = pt_bin_name canv = ROOT.TCanvas(cu.get_unique_str(), "", 800, 600) draw_opt = "COLZ TEXT" draw_opt = "COLZ" pad = ROOT.gPad pad.SetBottomMargin(0.12) pad.SetLeftMargin(0.13) pad.SetRightMargin(0.12) canv.SetTicks(1, 1) if log_var: canv.SetLogx() canv.SetLogy() # un normalised h2d.SetTitle(title) h2d.Draw(draw_opt) xax = h2d.GetXaxis() upper_lim = xax.GetBinUpEdge(xax.GetLast()) # print(upper_lim) # upper_lim = 5000 title_offset = 1.5 h2d.SetTitleOffset(title_offset, 'X') xax.SetMoreLogLabels() yax = h2d.GetYaxis() h2d.SetTitleOffset(title_offset * 1.15, 'Y') yax.SetMoreLogLabels() canv.Update() plot_dir = os.path.join(plot_dir, tdir.GetName()) cu.check_dir_exists_create(plot_dir) canv.SaveAs(os.path.join(plot_dir, "%s_linZ.%s" % (var_name, OUTPUT_FMT))) canv.SetLogz() canv.SaveAs(os.path.join(plot_dir, "%s_logZ.%s" % (var_name, OUTPUT_FMT))) # renorm by row (reco bins) canv.SetLogz(0) h2d_renorm_y = cu.make_normalised_TH2(h2d, 'Y', recolour=True, do_errors=True) h2d_renorm_y.SetMarkerSize(0.5) h2d_renorm_y.SetMaximum(1) h2d_renorm_y.Draw(draw_opt) xax = h2d_renorm_y.GetXaxis() upper_lim = xax.GetBinUpEdge(xax.GetLast()) # print(upper_lim) # upper_lim = 5000 title_offset = 1.5 h2d_renorm_y.SetTitleOffset(title_offset, 'X') # xax.SetRangeUser(0, upper_lim) xax.SetMoreLogLabels() yax = h2d_renorm_y.GetYaxis() h2d_renorm_y.SetTitleOffset(title_offset * 1.15, 'Y') # yax.SetRangeUser(0, upper_lim) yax.SetMoreLogLabels() canv.Update() canv.SaveAs( os.path.join(plot_dir, "%s_renormY_linZ.%s" % (var_name, OUTPUT_FMT))) canv.SetLogz() h2d_renorm_y.SetMaximum(1) h2d_renorm_y.SetMinimum(1E-3) canv.SaveAs( os.path.join(plot_dir, "%s_renormY_logZ.%s" % (var_name, OUTPUT_FMT))) # renorm by column (gen bins) canv.Clear() canv.SetLogz(0) h2d_renorm_x = cu.make_normalised_TH2(h2d, 'X', recolour=True, do_errors=True) h2d_renorm_x.SetMarkerSize(0.5) h2d_renorm_x.SetMaximum(1) h2d_renorm_x.Draw(draw_opt) xax = h2d_renorm_x.GetXaxis() upper_lim = xax.GetBinUpEdge(xax.GetLast()) # upper_lim = 5000 title_offset = 1.5 h2d_renorm_x.SetTitleOffset(title_offset, 'X') # xax.SetRangeUser(0, upper_lim) xax.SetMoreLogLabels() yax = h2d_renorm_x.GetYaxis() h2d_renorm_x.SetTitleOffset(title_offset * 1.15, 'Y') # yax.SetRangeUser(0, upper_lim) yax.SetMoreLogLabels() canv.Update() canv.SaveAs( os.path.join(plot_dir, "%s_renormX_linZ.%s" % (var_name, OUTPUT_FMT))) canv.SetLogz() h2d_renorm_x.SetMaximum(1) h2d_renorm_x.SetMinimum(1E-3) canv.SaveAs( os.path.join(plot_dir, "%s_renormX_logZ.%s" % (var_name, OUTPUT_FMT))) # Now do plot of purity, etc if do_migration_summary_plots: qgg.make_migration_summary_plot( h2d_renorm_x, h2d_renorm_y, xlabel=xlabel, output_filename=os.path.join( plot_dir, '%s_migration_summary.%s' % (var_name, OUTPUT_FMT)), log_var=log_var) # Do resolution plots if do_resolution_plots: res_rms, rel_res_rms = make_resolution_plots( h2d_orig, xlabel=xlabel, output_filename=os.path.join( plot_dir, '%s_resolution_summary_rms.%s' % (var_name, OUTPUT_FMT)), do_fit=False, do_rms=True, log_var=log_var, save_response_hists=False) res_quantiles, rel_res_quantiles = make_resolution_plots( h2d_orig, xlabel=xlabel, output_filename=os.path.join( plot_dir, '%s_resolution_summary_quantiles.%s' % (var_name, OUTPUT_FMT)), do_fit=False, do_rms=False, quantiles=None, # auto determine log_var=log_var, save_response_hists=save_response_hists) # compare RMS and quantile results conts = [ Contribution( res_rms, label="#sqrt{RMS} #pm #frac{#sqrt{#delta RMS}}{#LT %s #GT}" % (xlabel), line_color=ROOT.kRed, marker_color=ROOT.kRed), Contribution(res_quantiles, label="68% quantile", line_color=ROOT.kBlue, marker_color=ROOT.kBlue) ] ylabel = "#frac{#sigma(RECO/GEN)}{GEN}" if "_rel_" in var_name else "#frac{#sigma(RECO)}{GEN}" res_plot = Plot(conts, what='graph', xtitle=xlabel, ytitle=ylabel, legend=True, ylim=[0, 3]) res_plot.legend.SetX1(0.5) res_plot.legend.SetX2(0.9) res_plot.legend.SetY1(0.7) res_plot.legend.SetY2(0.85) res_plot.plot('ALP') res_plot.save( os.path.join( plot_dir, '%s_resolution_rms_vs_quantiles.%s' % (var_name, OUTPUT_FMT)))
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_1D_plot(hists, components_styles_dicts, output_filename, do_ratio=True, logx=False, logy=False, normalise_hists=True, title="", xtitle=None, mean_rel_error=0.4, data_first=True, show_integrals=False, lumi=cu.get_lumi_str(do_dijet=False, do_zpj=True)): if (len(hists) != len(components_styles_dicts)): raise RuntimeError("# hists != # components_styles_dicts (%d vs %d)" % (len(hists), len(components_styles_dicts))) if len(hists) == 0: return # Ignore if all empty objs total_entries = sum(h.GetEntries() for h in hists) if total_entries == 0: print("WARNING: all plots have 0 entries") return do_ratio = (do_ratio and len(hists) > 1) entries = [] components_styles_dicts = deepcopy(components_styles_dicts) for h, csd in zip(hists, components_styles_dicts): if show_integrals: csd['label'] += "\nIntegral = {:.4g}".format(h.Integral()) entries.append((h.Clone(cu.get_unique_str()), csd)) # print("Auto y limits:", min_val, max_val) ylim = None # if not normalise_hists: # min_val, min_bin, max_val, max_bin = cu.get_min_max_bin_contents_multiple_hists(hists) # 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] xlim = "auto" # Auto calc x limits to avoid lots of empty bins draw_opt = "NOSTACK HIST E1" subplot_title = "Simulation / Data" subplot_limits = (0, 2) if logy else (0.5, 1.5) # subplot_limits = [0.5, None] subplot_limits = None qgp.do_comparison_plot( entries, output_filename, # rebin=rebin, normalise_hist=normalise_hists, draw_opt=draw_opt, title=title, xtitle=xtitle, xlim=xlim, ylim=ylim, logx=logx, logy=logy, mean_rel_error=mean_rel_error, data_first=data_first, subplot_type='ratio' if do_ratio else None, subplot_title=subplot_title, subplot=entries[0][0] if do_ratio else None, subplot_limits=subplot_limits, lumi=lumi)
def generate_2d_canvas(size=(800, 800)): canv = ROOT.TCanvas(cu.get_unique_str(), "", *size) canv.SetTicks(1, 1) canv.SetRightMargin(1.5) canv.SetLeftMargin(0.9) return canv