def do_pf_fraction_plot(hist_map, pt_bins, output_filename): """Plot PF particle type fractioin for matches, binned by GenParticle pT""" entries = [] for pt_low, pt_high, mark in zip(pt_bins[:-1], pt_bins[1:], cu.Marker().cycle()): values = {} for pf_ind, (pf_name, hist) in hist_map.items(): ax = hist.GetXaxis() binx1 = ax.FindBin(pt_low) binx2 = ax.FindBin(pt_high) - 1 if pt_high == ax.GetBinUpEdge(ax.GetLast()): binx2 = ax.GetLast() biny1 = 1 biny2 = hist.GetNbinsY() binz1 = 1 binz2 = hist.GetNbinsZ() values[pf_ind] = hist.Integral( binx1, binx2, biny1, biny2, binz1, binz2) # integral includes the last bin sum_values = sum(values.values()) fracs = {k: (v / sum_values) for k, v in values.items()} h = ROOT.TH1D("h_pt_bin_%gto%g" % (pt_low, pt_high), "", len(values), 0, len(values)) ax = h.GetXaxis() for ind, k in enumerate(sorted(fracs.keys()), 1): h.SetBinContent(ind, fracs[k]) h.SetBinError(ind, sqrt(values[k]) / sum_values) ax.SetBinLabel(ind, hist_map[k][0]) c = Contribution(h, label='%g < GenParticle p_{T} < %g GeV' % (pt_low, pt_high), line_width=1, marker_size=0.75, marker_style=mark, normalise_hist=False) entries.append(c) ROOT.gStyle.SetPalette(55) plot = Plot(entries, 'hist', xtitle='PF particle type', ytitle='Fraction matched as type', ylim=(1E-3, 2), has_data=False) plot.default_canvas_size = (800, 600) plot.plot("NOSTACK PMC PLC HISTE") plot.set_logy(do_more_labels=False) plot.save(output_filename) ROOT.gStyle.SetPalette(ROOT.kViridis)
def do_comparison_plots(workdir_label_pairs, output_dir): dirnames = [w[0] for w in workdir_label_pairs] # templates, we'll change the filename/dir as per instance total_len = len(workdir_label_pairs) mark = cu.Marker() sources = [{ "root_dir": wd, 'label': label, "style": { 'line_style': 1, 'line_color': cu.get_colour_seq(ind, total_len), 'marker_color': cu.get_colour_seq(ind, total_len), 'marker_style': m, 'marker_size': 0.75, } } for ind, ((wd, label), m) in enumerate( zip(workdir_label_pairs, mark.cycle(cycle_filling=True)))] # print(sources) # COMPARE NOMINAL QCD if exists_in_all(qgc.QCD_FILENAME, dirnames): # qgp.do_all_exclusive_plots_comparison(sources, # var_list=qgc.COMMON_VARS, # pt_bins=qgc.PT_BINS, # qcd_filename=qgc.QCD_FILENAME, # dj_cen_dirname="Dijet_QG_central_tighter", # dj_fwd_dirname=None, # zpj_dirname=None, # plot_dir=os.path.join(output_dir, "plots_qcd_compare_dijet_central"), # subplot_type="ratio", # will use the 1st entry by default # subplot_title="* / %s" % (sources[0]['label']), # do_flav_tagged=False, # has_data=False) # qgp.do_all_exclusive_plots_comparison(sources, # var_list=qgc.COMMON_VARS, # pt_bins=qgc.PT_BINS, # qcd_filename=qgc.QCD_FILENAME, # dj_cen_dirname=None, # dj_fwd_dirname="Dijet_QG_forward_tighter", # zpj_dirname=None, # plot_dir=os.path.join(output_dir, "plots_qcd_compare_dijet_forward"), # subplot_type="ratio", # will use the 1st entry by default # subplot_title="* / %s" % (sources[0]['label']), # do_flav_tagged=False, # has_data=False) # do both dijet jets together # add gen level gen_qcd_sources = [deepcopy(sources[0])] # only 1st one for now for gd in gen_qcd_sources: gd.update({ 'dj_fwd_dirname': 'Dijet_QG_gen', 'label': gd['label'] + ' [Gen]' }) style_dict = gd['style'] style_dict.update({'line_style': 2}) style_dict.update({'line_color': style_dict['line_color'] + 5}) style_dict.update({'marker_color': style_dict['marker_color'] + 5}) style_dict.update({'marker_style': style_dict['marker_style'] + 1}) qgp.do_all_exclusive_plots_comparison( sources + gen_qcd_sources, var_list=qgc.COMMON_VARS, pt_bins=qgc.PT_BINS, qcd_filename=qgc.QCD_FILENAME, dj_cen_dirname=None, dj_fwd_dirname="Dijet_QG_tighter", zpj_dirname=None, plot_dir=os.path.join(output_dir, "plots_qcd_compare_dijet"), subplot_type="ratio", # will use the 1st entry by default subplot_title="* / %s" % (sources[0]['label']), do_flav_tagged=False, has_data=False, title=qgc.Dijet_LABEL, show_region_labels=False) # COMPARE NOMINAL DY if exists_in_all(qgc.DY_FILENAME, dirnames): qgp.do_all_exclusive_plots_comparison( sources, var_list=qgc.COMMON_VARS, pt_bins=qgc.PT_BINS, qcd_filename=qgc.DY_FILENAME, dj_cen_dirname=None, dj_fwd_dirname=None, zpj_dirname="ZPlusJets_QG", plot_dir=os.path.join(output_dir, "plots_dy_compare"), subplot_type="ratio", # will use the 1st entry by default subplot_title="* / %s" % (sources[0]['label']), do_flav_tagged=False, has_data=False, title=qgc.ZpJ_LABEL, show_region_labels=False) # COMPARE JETHT+ZEROBIAS if exists_in_all(qgc.JETHT_ZB_FILENAME, dirnames): qgp.do_all_exclusive_plots_comparison( sources, var_list=qgc.COMMON_VARS, pt_bins=qgc.PT_BINS, qcd_filename=qgc.JETHT_ZB_FILENAME, dj_cen_dirname="Dijet_QG_central_tighter", dj_fwd_dirname=None, zpj_dirname=None, plot_dir=os.path.join(output_dir, "plots_jetht_zb_compare_dijet_central"), subplot_type="ratio", # will use the 1st entry by default subplot_title="* / %s" % (sources[0]['label']), do_flav_tagged=False, has_data=True) qgp.do_all_exclusive_plots_comparison( sources, var_list=qgc.COMMON_VARS, pt_bins=qgc.PT_BINS, qcd_filename=qgc.JETHT_ZB_FILENAME, dj_cen_dirname=None, dj_fwd_dirname="Dijet_QG_forward_tighter", zpj_dirname=None, plot_dir=os.path.join(output_dir, "plots_jetht_zb_compare_dijet_forward"), subplot_type="ratio", # will use the 1st entry by default subplot_title="* / %s" % (sources[0]['label']), do_flav_tagged=False, has_data=True) # COMPARE SINGLEMU # COMPARE HERWIG++ QCD if exists_in_all(qgc.QCD_HERWIG_FILENAME, dirnames): qgp.do_all_exclusive_plots_comparison( sources, var_list=qgc.COMMON_VARS, pt_bins=qgc.PT_BINS, qcd_filename=qgc.QCD_HERWIG_FILENAME, dj_cen_dirname="Dijet_QG_central_tighter", dj_fwd_dirname=None, zpj_dirname=None, plot_dir=os.path.join(output_dir, "plots_qcd_herwig_compare_dijet_central"), subplot_type="ratio", # will use the 1st entry by default subplot_title="* / %s" % (sources[0]['label']), subplot_limits=[0.9, 1.1], do_flav_tagged=False, has_data=False) qgp.do_all_exclusive_plots_comparison( sources, var_list=qgc.COMMON_VARS, pt_bins=qgc.PT_BINS, qcd_filename=qgc.QCD_HERWIG_FILENAME, dj_cen_dirname=None, dj_fwd_dirname="Dijet_QG_forward_tighter", zpj_dirname=None, plot_dir=os.path.join(output_dir, "plots_qcd_herwig_compare_dijet_forward"), subplot_type="ratio", # will use the 1st entry by default subplot_title="* / %s" % (sources[0]['label']), subplot_limits=[0.9, 1.1], do_flav_tagged=False, has_data=False)
def do_comparison_plots(workdir_label_pairs, output_dir): dirnames = [w[0] for w in workdir_label_pairs] # templates, we'll change the filename/dir as per instance total_len = len(workdir_label_pairs) mark = cu.Marker() sources = [ { # "root_dir": wd, 'label': label, "style": { 'line_style': 1, 'line_color': cu.get_colour_seq(ind, total_len), 'marker_color': cu.get_colour_seq(ind, total_len), 'marker_style': m, 'marker_size': 0.75, } } for ind, ((wd, label), m) in enumerate(zip(workdir_label_pairs, mark.cycle(cycle_filling=True))) ] jet_config_str = qgc.extract_jet_config(dirnames[0]) if len(dirnames) >1 and qgc.extract_jet_config(dirnames[1]) != jet_config_str: print("Conflicting jet config str, not adding") jet_config_str = None # COMPARE NOMINAL QCD if exists_in_all(qgc.QCD_FILENAME, dirnames): print("Found", qgc.QCD_FILENAME, "in all dirs") root_files = [cu.open_root_file(os.path.join(d, qgc.QCD_FILENAME)) for d in dirnames] directories = [cu.get_from_tfile(rf, "Dijet_tighter") for rf in root_files] this_sources = deepcopy(sources) for s in this_sources: s['label'] = "QCD [MG+PY8] [%s]" % s['label'] do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_qcd_compare_dijet_tighter_kinematics_normalised"), jet_config_str=jet_config_str, normalise_hists=True, bin_by='ave') directories = [cu.get_from_tfile(rf, "Dijet_eta_ordered") for rf in root_files] do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_qcd_compare_dijet_eta_ordered_kinematics_normalised"), jet_config_str=jet_config_str, normalise_hists=True, bin_by='ave') # COMPARE NOMINAL DY if exists_in_all(qgc.DY_FILENAME, dirnames): root_files = [cu.open_root_file(os.path.join(d, qgc.DY_FILENAME)) for d in dirnames] directories = [cu.get_from_tfile(rf, "ZPlusJets") for rf in root_files] this_sources = deepcopy(sources) for s in this_sources: s['label'] = "Z+Jet [MG+PY8] [%s]" % s['label'] do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_dy_compare_kinematics_absolute"), jet_config_str=jet_config_str, normalise_hists=False, bin_by='Z') do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_dy_compare_kinematics_normalised"), jet_config_str=jet_config_str, normalise_hists=True, bin_by='Z') # COMPARE JETHT+ZEROBIAS if exists_in_all(qgc.JETHT_ZB_FILENAME, dirnames): print("Found", qgc.JETHT_ZB_FILENAME, "in all dirs") root_files = [cu.open_root_file(os.path.join(d, qgc.JETHT_ZB_FILENAME)) for d in dirnames] directories = [cu.get_from_tfile(rf, "Dijet_tighter") for rf in root_files] this_sources = deepcopy(sources) for s in this_sources: s['label'] = "Data [%s]" % s['label'] directories = [cu.get_from_tfile(rf, "Dijet_Presel") for rf in root_files] do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_jetht_zb_compare_dijet_presel_kinematics_normalised"), jet_config_str=jet_config_str, normalise_hists=False, bin_by='ave') directories = [cu.get_from_tfile(rf, "Dijet_tighter") for rf in root_files] do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_jetht_zb_compare_dijet_tighter_kinematics_normalised"), jet_config_str=jet_config_str, normalise_hists=True, bin_by='ave') do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_jetht_zb_compare_dijet_tighter_kinematics_abs"), jet_config_str=jet_config_str, normalise_hists=False, bin_by='ave') # COMPARE SINGLEMU # COMPARE HERWIG++ QCD if exists_in_all(qgc.QCD_HERWIG_FILENAME, dirnames): root_files = [cu.open_root_file(os.path.join(d, qgc.QCD_HERWIG_FILENAME)) for d in dirnames] directories = [cu.get_from_tfile(rf, "Dijet_tighter") for rf in root_files] this_sources = deepcopy(sources) for s in this_sources: s['label'] = "QCD [H++] [%s]" % s['label'] # do_all_1D_projection_plots_in_dir(directories=directories, # components_styles_dicts=this_sources, # output_dir=os.path.join(output_dir, "plots_qcd_hpp_compare_dijet_tighter_kinematics_normalised"), # jet_config_str=jet_config_str, # normalise_hists=True, # bin_by='ave') # directories = [cu.get_from_tfile(rf, "Dijet_eta_ordered") for rf in root_files] # do_all_1D_projection_plots_in_dir(directories=directories, # components_styles_dicts=this_sources, # output_dir=os.path.join(output_dir, "plots_qcd_hpp_compare_dijet_eta_ordered_kinematics_normalised"), # jet_config_str=jet_config_str, # normalise_hists=True, # bin_by='ave') do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_qcd_hpp_compare_dijet_tighter_kinematics_absolute"), jet_config_str=jet_config_str, normalise_hists=False, bin_by='ave') directories = [cu.get_from_tfile(rf, "Dijet_eta_ordered") for rf in root_files] do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_qcd_hpp_compare_dijet_eta_ordered_kinematics_absolute"), jet_config_str=jet_config_str, normalise_hists=False, bin_by='ave') # COMPARE HERWIG++ DY if exists_in_all(qgc.DY_HERWIG_FILENAME, dirnames): root_files = [cu.open_root_file(os.path.join(d, qgc.DY_HERWIG_FILENAME)) for d in dirnames] directories = [cu.get_from_tfile(rf, "ZPlusJets") for rf in root_files] this_sources = deepcopy(sources) for s in this_sources: s['label'] = "Z+Jet [H++] [%s]" % s['label'] do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_dy_hpp_compare_kinematics_absolute"), jet_config_str=jet_config_str, normalise_hists=False, bin_by='Z') do_all_1D_projection_plots_in_dir(directories=directories, components_styles_dicts=this_sources, output_dir=os.path.join(output_dir, "plots_dy_hpp_compare_kinematics_normalised"), jet_config_str=jet_config_str, normalise_hists=True, bin_by='Z')
def do_plots(root_dir): # QG variable plots pt_bins = qgc.PT_BINS[:] var_list = qgc.COMMON_VARS radius, pus = cu.get_jet_config_from_dirname(root_dir) jet_str = "AK%s" % (radius.upper()) dy_tfile, qcd_tfile = None, None if os.path.isfile(os.path.join(root_dir, qgc.DY_FILENAME)): dy_tfile = cu.TFileCacher(os.path.join(root_dir, qgc.DY_FILENAME)) if os.path.isfile(os.path.join(root_dir, qgc.QCD_FILENAME)): qcd_tfile = cu.TFileCacher(os.path.join(root_dir, qgc.QCD_FILENAME)) for gr_append in ["", "_groomed"]: if gr_append == "_groomed": print("Doing groomed plots...") else: print("Doing ungroomed plots...") # GEnJets matched to recojet, reco selection zpj_dirname = "ZPlusJets_QG%s" % (gr_append) dj_cen_dirname = "Dijet_QG_central_tighter%s" % (gr_append) dj_fwd_dirname = "Dijet_QG_forward_tighter%s" % (gr_append) # Gen Jets from gen selection zpj_dirname = "ZPlusJets_QG_gen%s" % (gr_append) dj_cen_dirname = "Dijet_QG_gen_central%s" % (gr_append) dj_fwd_dirname = "Dijet_QG_gen_forward%s" % (gr_append) for ang in var_list[:]: print("...Doing", ang.name) var_template = "{prefix}%s_vs_pt" % (ang.var ) # {prefix} is for flavour for pt_ind, (start_val, end_val) in enumerate(pt_bins): zpj_entries = [] dijet_cen_entries = [] dijet_fwd_entries = [] # Get all plots lw = 2 msize = 1.1 mc_msize = 1E-3 # small enough to not be seen but not 0 - otherwise the horizontal lines on error bars don't get drawn mc_msize = msize # small enough to not be seen but not 0 - otherwise the horizontal lines on error bars don't get drawn flavours_dicts = [ { "prefix": "q", "label": "u/d/s" }, { "prefix": "g", "label": "g" }, { "prefix": "bc", "label": "b/c" }, ] if dy_tfile: # Z+JETS REGION marker = cu.Marker(qgc.DY_MARKER) for flav_dict, color, mark in zip(flavours_dicts, qgc.DY_COLOURS, marker.cycle()): h2d_dyj_mc = dy_tfile.get( "%s/%s" % (zpj_dirname, var_template.format(**flav_dict))) dy_kwargs_mc = dict(line_color=color, line_width=lw, fill_color=color, marker_color=color, marker_style=mark, marker_size=mc_msize, label="%s flavour" % (flav_dict['label']), subplot=None) zpj_entries.append( (qgp.get_projection_plot(h2d_dyj_mc, start_val, end_val), dy_kwargs_mc)) if qcd_tfile: # DIJET CENTRAL REGION marker = cu.Marker(qgc.QCD_MARKER) for flav_dict, color, mark in zip(flavours_dicts, qgc.QCD_COLOURS, marker.cycle()): h2d_qcd_cen_mc = qcd_tfile.get( "%s/%s" % (dj_cen_dirname, var_template.format(**flav_dict))) qcd_cen_kwargs_mc = dict(line_color=color, line_width=lw, fill_color=color, marker_color=color, marker_style=mark, marker_size=mc_msize, label="%s flavour" % (flav_dict['label']), subplot=None) dijet_mgpy_hist = qgp.get_projection_plot( h2d_qcd_cen_mc, start_val, end_val) dijet_cen_entries.append( (dijet_mgpy_hist, qcd_cen_kwargs_mc)) # DIJET FORWARD REGION marker = cu.Marker(qgc.QCD_MARKER) for flav_dict, color, mark in zip(flavours_dicts, qgc.QCD_COLOURS, marker.cycle()): h2d_qcd_fwd_mc = qcd_tfile.get( "%s/%s" % (dj_fwd_dirname, var_template.format(**flav_dict))) qcd_fwd_kwargs_mc = dict(line_color=color, line_width=lw, fill_color=color, marker_color=color, marker_style=mark, marker_size=mc_msize, label="%s flavour" % (flav_dict['label']), subplot=None) dijet_mgpy_hist = qgp.get_projection_plot( h2d_qcd_fwd_mc, start_val, end_val) dijet_fwd_entries.append( (dijet_mgpy_hist, qcd_fwd_kwargs_mc)) ################# # SETUP PLOTTING ################# rebin = 2 v_lower = var_template.lower() if "multiplicity" in v_lower: rebin = 1 # elif "flavour" in v_lower or "thrust" in v_lower: # rebin = 1 # elif 'ptd' in v_lower: # rebin = 4 # elif 'lha_charged' in v_lower: # rebin = 4 # rebin = 1 xlim = None if "width" in v_lower or "ptd" in v_lower: xlim = (0, 1) elif "thrust" in v_lower: xlim = (0, 0.5) # elif "multiplicity" in v_lower and "ak4" in root_dir.lower(): # if end_val <= 150: # xlim = (0, 50) # else: # xlim = (0, 80) auto_xlim = False if "multiplicity" in v_lower or "thrust" in v_lower: auto_xlim = True ylim = [0, None] if "flavour" in v_lower: ylim = (0, 1) # elif "lha" in v_lower: # ylim = (0, 5) plot_dir = os.path.join( root_dir, "plots_gen_lambda_flav_comparison%s" % (gr_append)) subplot_title = "Simulation / Data" subplot_limits = (0, 2) xlabel = ang.name + " (" + ang.lambda_str + ")" if gr_append is not "": xlabel = "Groomed " + ang.name + " (" + ang.lambda_str + ")" def _title(region_str, start_val, end_val): pt_var_str = "p_{T}^{jet}" s = (("{jet_algo}\n" "{region_label}\n" "{mc_sample}\n" "{bin_edge_low:g} < {pt_str} < {bin_edge_high:g} GeV" ).format(jet_algo=jet_str, region_label=region_str, mc_sample="MG5+Pythia8", pt_str=pt_var_str, bin_edge_low=start_val, bin_edge_high=end_val)) return s has_data = False draw_opt = "NOSTACK HIST E1" # dj central only # dont' try to do multiple signal regions per plot, it looks rubbish if len(dijet_cen_entries) > 0: qgp.do_comparison_plot( dijet_cen_entries, "%s/ptBinned/%s_pt%dto%d_dijet_central.%s" % (plot_dir, ang.var, start_val, end_val, OUTPUT_FMT), rebin=rebin, draw_opt=draw_opt, title=_title(qgc.Dijet_CEN_LABEL, start_val, end_val), xtitle=xlabel, xlim='auto' if auto_xlim else xlim, # don't use calc_auto_xlim, since do_comparison_plot will rebin it anyway ylim=ylim, data_first=has_data, mean_rel_error=0.4, subplot_type=None, lumi=cu.get_lumi_str( do_dijet=False, do_zpj=True)) # full lumi as just MC # dj forward only if len(dijet_fwd_entries) > 0: qgp.do_comparison_plot( dijet_fwd_entries, "%s/ptBinned/%s_pt%dto%d_dijet_forward.%s" % (plot_dir, ang.var, start_val, end_val, OUTPUT_FMT), rebin=rebin, draw_opt=draw_opt, title=_title(qgc.Dijet_FWD_LABEL, start_val, end_val), xtitle=xlabel, xlim='auto' if auto_xlim else xlim, ylim=ylim, data_first=has_data, mean_rel_error=0.4, subplot_type=None, lumi=cu.get_lumi_str( do_dijet=False, do_zpj=True)) # full lumi as just MC # zpj only if len(zpj_entries) > 0: if start_val > 149: # rebin *= 2 rebin += 1 # find nearest divisor while (zpj_entries[0][0].GetNbinsX() % rebin != 0): rebin += 1 if "multiplicity" in v_lower: if start_val > 300: rebin += 1 # find nearest divisor while (zpj_entries[0][0].GetNbinsX() % rebin != 0): rebin += 1 qgp.do_comparison_plot( zpj_entries, "%s/ptBinned/%s_pt%dto%d_zpj.%s" % (plot_dir, ang.var, start_val, end_val, OUTPUT_FMT), rebin=rebin, draw_opt=draw_opt, title=_title(qgc.ZpJ_LABEL, start_val, end_val), xtitle=xlabel, xlim=qgp.calc_auto_xlim([d[0] for d in zpj_entries]) if auto_xlim else xlim, ylim=ylim, data_first=has_data, mean_rel_error=0.4, subplot_type=None, lumi=cu.get_lumi_str(do_dijet=False, do_zpj=True))
def do_pileup_plot(input_dir, trigger_names, output_filename): # get histograms hists = [ cu.grab_obj_from_file( os.path.join(input_dir, 'MyDataPileupHistogram_%s.root' % t), 'pileup') for t in trigger_names ] h_up = cu.grab_obj_from_file( os.path.join(input_dir, 'MyDataPileupHistogram_PFJet500_72383.root'), 'pileup') h_down = cu.grab_obj_from_file( os.path.join(input_dir, 'MyDataPileupHistogram_PFJet500_66017.root'), 'pileup') h_down3 = cu.grab_obj_from_file( os.path.join(input_dir, 'MyDataPileupHistogram_PFJet500_59650.root'), 'pileup') ratio_up = h_up.Clone() ratio_up.Divide(hists[-1]) ratio_down = h_down.Clone() ratio_down.Divide(hists[-1]) # hists.append(h_up) # hists.append(h_down) # trigger_names.append('72.383') # trigger_names.append('66.017') # Create contributions mark = cu.Marker() n_hists = len(hists) conts = [ Contribution(h, label=t, line_width=2, line_color=cu.get_colour_seq(ind, n_hists), marker_color=cu.get_colour_seq(ind, n_hists), marker_style=m, normalise_hist=True) for ind, (h, t, m) in enumerate( zip(hists, trigger_names, mark.cycle(cycle_filling=True))) ] conts.insert( -1, Contribution( h_up, label='72.383 (+4.6%)', line_width=2, line_color=ROOT.kRed, marker_color=ROOT.kRed, normalise_hist=True, )) conts.insert( -1, Contribution( h_down, label='66.017 (-4.6%)', line_width=2, line_color=ROOT.kMagenta, marker_color=ROOT.kMagenta, normalise_hist=True, )) conts.insert( -1, Contribution( h_down3, label='59.650 (-13.8%)', line_width=2, line_style=1, line_color=ROOT.kMagenta + 3, marker_color=ROOT.kMagenta + 3, normalise_hist=True, )) print([h.Integral() for h in hists]) plot = Plot( conts, what='hist', xtitle='Pileup', lumi=cu.get_lumi_str(do_dijet=True, do_zpj=True), subplot_type='ratio', subplot=conts[-1], ) plot.subplot_maximum_ceil = 4.5 plot.plot("NOSTACK HISTE", "NOSTACK HIST") plot.subplot_pad.cd() # To shade region between up and down hists, need to create graph with # the error bars as the up/down variations x_low = np.array([ ratio_up.GetBinLowEdge(i) for i in range(1, ratio_up.GetNbinsX() + 1) ], dtype=float) x_high = np.array([ ratio_up.GetBinLowEdge(i) for i in range(2, ratio_up.GetNbinsX() + 2) ], dtype=float) x_mid = 0.5 * (x_low + x_high) x_err = x_high - x_low y_high = np.array([ max(ratio_up.GetBinContent(i), ratio_down.GetBinContent(i)) for i in range(1, ratio_up.GetNbinsX() + 1) ]) y_high -= 1 y_low = np.array([ min(ratio_up.GetBinContent(i), ratio_down.GetBinContent(i)) for i in range(1, ratio_up.GetNbinsX() + 1) ]) y_low = 1 - y_low y_mid = np.array([1. for i in range(1, ratio_up.GetNbinsX() + 1)]) gr = ROOT.TGraphAsymmErrors(len(x_mid), x_mid, y_mid, x_err, x_err, y_low, y_high) gr.SetFillColor(ROOT.kGray + 2) gr.SetFillStyle(3254) gr.Draw('2 SAME') plot.subplot_container.Draw("SAME NOSTACK HIST") plot.subplot_line.Draw() plot.save(output_filename)