Beispiel #1
0
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)
Beispiel #4
0
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)
Beispiel #5
0
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)
Beispiel #6
0
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)
Beispiel #7
0
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)
Beispiel #8
0
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)
Beispiel #9
0
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)
Beispiel #14
0
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)
Beispiel #17
0
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)