Ejemplo n.º 1
0
def mc_stack(
    hlist,
    hs_syst,
    systematics,
    colors="auto"
    ):
    if colors=="auto":
        coloriter = iter(plt.cm.jet(np.linspace(0,1,len(hlist))))
        for h in hlist:
            h.color = next(coloriter)
    elif isinstance(colors, list) and len(colors) == len(hlist):
        for h, c in zip(hlist, colors):
            h.color = c

    for h in hlist:
        h.fillstyle = "solid"

    #FIXME: Temporary workaround for failed fill, only works when hatch is specified
    stack = hist(hlist, stacked=True, hatch=".", lw=2)
    htot = sum(hlist)
    htot.color="black"

    htot_u = htot.Clone()
    htot_d = htot.Clone()
    for i in range(1, htot.nbins()+1):
        htot_u.set_bin_content(i, htot.get_bin_content(i) + htot.get_bin_error(i))
        htot_d.set_bin_content(i, htot.get_bin_content(i) - htot.get_bin_error(i))

    htot_u.color="black"
    htot_d.color="black"

    fill_between(htot_u, htot_d,
        color="black", hatch="////////",
        alpha=1.0, linewidth=0, facecolor="none", edgecolor="black", zorder=10,
    )

    #add systematic uncertainties
    hstat = htot_u - htot_d
    errs = np.array([y for y in hstat.y()])
    errs = np.abs(errs)

    htot_usyst = htot.Clone()
    htot_dsyst = htot.Clone()
    for systUp, systDown in systematics:
        errs_syst_up = np.array([y for y in sum(hs_syst[systUp].values()).y()])
        errs_syst_down = np.array([y for y in sum(hs_syst[systDown].values()).y()])
        errs_syst = np.abs(errs_syst_up - errs_syst_down)
        errs = np.power(errs, 2) + np.power(errs_syst, 2)
        errs = np.sqrt(errs)
    for i in range(len(errs)):
        htot_usyst.SetBinContent(i+1, htot_usyst.GetBinContent(i+1) + errs[i]/2)
        htot_dsyst.SetBinContent(i+1, htot_dsyst.GetBinContent(i+1) - errs[i]/2)

    fill_between(htot_usyst, htot_dsyst,
        color="gray", hatch=r"\\\\",
        alpha=1.0, linewidth=0, facecolor="none", edgecolor="gray", zorder=10,
    )

    return {"hists":stack, "tot":htot, "tot_u":htot_u, "tot_d":htot_d, "tot_usyst":htot_usyst, "tot_dsyst":htot_dsyst}
Ejemplo n.º 2
0
 def draw(self, axes,
          facecolor = '0.75', # grey
          alpha = 0.5,
          hatch = '/',
          zorder = 999,):
     rplt.fill_between( self.__upper,
                        self.__lower, axes, facecolor = facecolor,
                        alpha = alpha, hatch = hatch,
                        zorder = zorder )
Ejemplo n.º 3
0
 def draw(
     self,
     axes,
     facecolor='0.75',  # grey
     alpha=0.5,
     hatch='/',
     zorder=999,
 ):
     rplt.fill_between(self.__upper,
                       self.__lower,
                       axes,
                       facecolor=facecolor,
                       alpha=alpha,
                       hatch=hatch,
                       zorder=zorder)
def plot_systematic_uncertainties(systematic_uncertainties,
                                  bin_edges,
                                  variable,
                                  output_folder,
                                  subcategories=[],
                                  subname='',
                                  plot_largest=False,
                                  plot_foreground=None):
    '''
	Plot the systematic uncertainties
	'''
    if not subcategories: subcategories = systematic_uncertainties.keys()

    x_limits = [bin_edges[0], bin_edges[-1]]
    # y_limits = [-0.6,0.6]
    y_limits = [0, 0.4]

    fig_syst = plt.figure(figsize=(20, 16), dpi=400, facecolor='white')
    ax_syst = fig_syst.add_subplot(1, 1, 1)
    ax_syst.minorticks_on()
    ax_syst.xaxis.labelpad = 12
    ax_syst.yaxis.labelpad = 12

    error_hists_up = {}
    error_hists_down = {}
    stat_hist = None

    for syst, vals in systematic_uncertainties.iteritems():
        if syst == 'central':
            n = len(systematic_uncertainties[syst])
            continue
        elif syst == 'statistical':
            stat_hist_up = values_and_errors_to_hist(vals, [], bin_edges)
            stat_hist_down = values_and_errors_to_hist(-vals, [], bin_edges)
        elif syst == 'systematic':
            syst_hist_up = values_and_errors_to_hist(vals, [], bin_edges)
            syst_hist_down = values_and_errors_to_hist(-vals, [], bin_edges)
        elif syst in subcategories:
            error_hists_up[syst] = values_and_errors_to_hist(
                vals, [], bin_edges)
            error_hists_down[syst] = values_and_errors_to_hist(
                -vals, [], bin_edges)
        else:
            continue

    if plot_largest:
        largest_syst = []
        for bin_i in range(n):
            high = []
            for syst, vals in systematic_uncertainties.iteritems():
                if syst == 'central': continue
                if syst == 'statistical': continue
                if syst == 'systematic': continue
                high.append([syst, vals[bin_i]])
            high = sorted(high, key=itemgetter(1), reverse=True)
            # Retrieve highest systematics
            if high[0][0] not in largest_syst: largest_syst.append(high[0][0])
            elif high[1][0] not in largest_syst:
                largest_syst.append(high[1][0])
            else:
                continue

    rplt.fill_between(syst_hist_up,
                      syst_hist_down,
                      color='gold',
                      label='Syst.')
    rplt.fill_between(stat_hist_down,
                      stat_hist_up,
                      color='0.75',
                      label='Stat.')

    plt.tick_params(**CMS.axis_label_major)
    plt.tick_params(**CMS.axis_label_minor)

    colours = [
        'red', 'blue', 'green', 'chartreuse', 'indigo', 'magenta',
        'darkmagenta', 'hotpink', 'cyan', 'darkred', 'darkgoldenrod',
        'mediumvioletred', 'mediumspringgreen', 'darkgoldenrod', 'slategray',
        'dodgerblue', 'cadetblue', 'darkblue', 'seagreen', 'deeppink',
        'deepskyblue'
    ] * 2
    if len(colours) < len(error_hists_up.keys()):
        print '---> Need to add more colours!!!'

    for error_hists in [error_hists_up, error_hists_down]:
        for i, source, in enumerate(error_hists.keys()):
            hist = error_hists[source]
            hist.linewidth = 4
            hist.color = colours[i]
            if plot_largest:
                if source not in largest_syst:
                    hist.linestyle = 'dashed'
                    hist.alpha = 0.4
                    hist.linewidth = 2
            # Only label systematic once
            if plot_foreground and plot_foreground in error_hists.keys():
                source = ''
            if error_hists == error_hists_up:
                rplt.hist(hist, stacked=False, label=source)
            else:
                rplt.hist(hist, stacked=False, label='')
        if plot_foreground and plot_foreground in error_hists.keys():
            hist = error_hists[plot_foreground]
            hist.color = 'black'
            rplt.hist(hist, stacked=False, label=source)

    leg = plt.legend(loc='upper right', prop={'size': 25}, ncol=3)
    # leg = plt.legend(loc='upper right',prop={'size':20},ncol=4)
    leg.draw_frame(False)

    x_title = variables_NonLatex[variable]
    if variable in ['HT', 'MET', 'WPT', 'ST', 'lepton_pt']:
        x_title += ' [GeV]'

    ax_syst.set_xlim(x_limits)
    ax_syst.set_ylim(y_limits)
    plt.xlabel(x_title, CMS.x_axis_title)
    plt.ylabel('Relative Uncertainty', CMS.y_axis_title)

    template = '%.1f fb$^{-1}$ (%d TeV)'
    label = template % (measurement_config.new_luminosity / 1000.,
                        measurement_config.centre_of_mass_energy)
    plt.title(label, loc='right', **CMS.title)

    logo_location = (0.05, 0.98)
    prelim_location = (0.05, 0.92)
    channel_location = (0.05, 0.86)
    # plt.text(logo_location[0], logo_location[1],
    # 	"CMS",
    # 	transform=ax_syst.transAxes,
    # 	fontsize=42,
    # 	verticalalignment='top',
    # 	horizontalalignment='left'
    # )
    # # preliminary
    # plt.text(prelim_location[0], prelim_location[1],
    # 	r"\emph{Preliminary}",
    # 	transform=ax_syst.transAxes,
    # 	fontsize=42,
    # 	verticalalignment='top',
    # 	horizontalalignment='left'
    # )
    # # channel text
    # plt.text(channel_location[0], channel_location[1],
    # 	r"\emph{%s}" % channel,
    # 	transform=ax_syst.transAxes,
    # 	fontsize=40,
    # 	verticalalignment='top',
    # 	horizontalalignment='left'
    # )

    plt.tight_layout()

    file_template = output_folder + '{var}_systematics_{com}TeV'.format(
        var=variable,
        com=measurement_config.centre_of_mass_energy,
    )
    if subname: file_template = file_template + '_' + subname
    file_template += '.pdf'
    fig_syst.savefig(file_template)
    print "Written plots to {f}".format(f=file_template)
    # plt.show()
    return
def plot_systematic_uncertainties(systematic_uncertainties, bin_edges, variable, output_folder, subcategories = [], subname = '', plot_largest = False):
	'''
	Plot the systematic uncertainties
	'''
	print subcategories
	if not subcategories: subcategories = systematic_uncertainties.keys()

	x_limits = [bin_edges[0], bin_edges[-1]]
	# y_limits = [-0.6,0.6]
	y_limits = [0,0.4]

	fig_syst = plt.figure( figsize = ( 20, 16 ), dpi = 400, facecolor = 'white' )
	ax_syst = fig_syst.add_subplot(1, 1, 1)
	ax_syst.minorticks_on()
	ax_syst.xaxis.labelpad = 12
	ax_syst.yaxis.labelpad = 12

	error_hists_up = {}
	error_hists_down = {}
	stat_hist = None

	for syst, vals in systematic_uncertainties.iteritems():
		if syst == 'central': 
			n = len(systematic_uncertainties[syst])
			continue
		elif syst == 'statistical':
			stat_hist_up = values_and_errors_to_hist( vals, [], bin_edges )
			stat_hist_down = values_and_errors_to_hist( -vals, [], bin_edges )
		elif syst == 'systematic':
			syst_hist_up = values_and_errors_to_hist( vals, [], bin_edges )
			syst_hist_down = values_and_errors_to_hist( -vals, [], bin_edges )
		elif syst in subcategories:
			error_hists_up[syst] = values_and_errors_to_hist( vals, [], bin_edges )
			error_hists_down[syst] = values_and_errors_to_hist( -vals, [], bin_edges )
		else: continue

	if plot_largest:
		largest_syst = []
		for bin_i in range( n ):
			high = []
			for syst, vals in systematic_uncertainties.iteritems():
				if syst == 'central': continue
				if syst == 'statistical': continue
				if syst == 'systematic': continue
				high.append([syst,vals[bin_i]])
			high = sorted(high, key = itemgetter(1), reverse=True)
			# Retrieve highest systematics
			if high[0][0] not in largest_syst: largest_syst.append(high[0][0])
			elif high[1][0] not in largest_syst: largest_syst.append(high[1][0])
			else: continue

	rplt.fill_between( syst_hist_up, syst_hist_down, color = 'yellow', label='Syst.' )
	rplt.fill_between( stat_hist_down, stat_hist_up, color = 'grey', label='Stat.' )

	plt.tick_params( **CMS.axis_label_major )
	plt.tick_params( **CMS.axis_label_minor )

	colours = ['red', 'blue', 'green', 'chartreuse', 'indigo', 'magenta', 'darkmagenta', 'hotpink', 'cyan', 'darkred', 'darkgoldenrod', 'mediumvioletred', 'mediumspringgreen', 'gold', 'darkgoldenrod', 'slategray', 'dodgerblue', 'cadetblue', 'darkblue', 'seagreen', 'deeppink', 'deepskyblue' ]
	# if len(colours) < len(error_hists.keys()):
	# 	print '---> Need to add more colours!!!'

	for error_hists in [error_hists_up, error_hists_down]:
		for i, source, in enumerate(error_hists.keys()):
			hist = error_hists[source]
			hist.linewidth = 4
			hist.color = colours[i]
			if plot_largest:
				if source not in largest_syst:
					hist.linestyle = 'dashed'
					hist.alpha = 0.4	
					hist.linewidth = 2
			# Only label systematic once
			if error_hists == error_hists_up:
				rplt.hist( hist, stacked=False, label = source )
			else:
				rplt.hist( hist, stacked=False, label = '' )

	leg = plt.legend(loc='upper right',prop={'size':25},ncol=3)
	# leg = plt.legend(loc='upper right',prop={'size':20},ncol=4)
	leg.draw_frame(False)	

	x_title = variables_NonLatex[variable]
	if variable in ['HT', 'MET', 'WPT', 'ST', 'lepton_pt']:
		x_title += ' [GeV]'

	ax_syst.set_xlim( x_limits )
	ax_syst.set_ylim( y_limits )
	plt.xlabel( x_title, CMS.x_axis_title )
	plt.ylabel( 'Relative Uncertainty', CMS.y_axis_title)

	template = '%.1f fb$^{-1}$ (%d TeV)'
	label = template % ( measurement_config.new_luminosity/1000, measurement_config.centre_of_mass_energy)
	plt.title( label,loc='right', **CMS.title )

	logo_location = (0.05, 0.98)
	prelim_location = (0.05, 0.92)
	channel_location = ( 0.05, 0.86)
	# plt.text(logo_location[0], logo_location[1], 
	# 	"CMS", 
	# 	transform=ax_syst.transAxes, 
	# 	fontsize=42,
	# 	verticalalignment='top',
	# 	horizontalalignment='left'
	# )
	# # preliminary
	# plt.text(prelim_location[0], prelim_location[1], 
	# 	r"\emph{Preliminary}",
	# 	transform=ax_syst.transAxes, 
	# 	fontsize=42,
	# 	verticalalignment='top',
	# 	horizontalalignment='left'
	# )
	# # channel text
	# plt.text(channel_location[0], channel_location[1], 
	# 	r"\emph{%s}" % channel, 
	# 	transform=ax_syst.transAxes, 
	# 	fontsize=40,
	# 	verticalalignment='top',
	# 	horizontalalignment='left'
	# )

	plt.tight_layout()

	file_template = output_folder + '{var}_systematics_{com}TeV'.format(
		var = variable, 
		com = measurement_config.centre_of_mass_energy,
	)
	if subname: file_template = file_template + '_' + subname
	file_template += '.pdf'
	fig_syst.savefig(file_template)
	print "Written plots to {f}".format(f = file_template)
	# plt.show()
	return
Ejemplo n.º 6
0
def make_data_mc_comparison_plot(
    histograms=[],
    histogram_lables=[],
    histogram_colors=[],
    histogram_properties=Histogram_properties(),
    data_index=0,
    save_folder='plots/',
    save_as=['pdf'],
    normalise=False,
    show_ratio=False,
    show_stat_errors_on_mc=False,
    draw_vertical_line=0,
    systematics_for_ratio=None,
    systematics_for_plot=None,
    histograms_to_compare=None,
):
    '''
    systematics_for_plot takes the same input as systematics_for_ratio. There may be some repition with reagrds to 
    mc_error and mc_relative_errors, but these only deal with a flat error up and down.
    '''
    save_folder = check_save_folder(save_folder)
    # make copies in order not to mess with existing histograms
    histograms_ = deepcopy(histograms)
    stack = HistStack()
    add_mc = stack.Add
    for index, histogram in enumerate(histograms_):
        label = histogram_lables[index]
        color = histogram_colors[index]

        histogram.SetTitle(label)
        if normalise:
            histogram.Sumw2()

        if not index == data_index:
            histogram.fillstyle = 'solid'
            histogram.fillcolor = color
            histogram.legendstyle = 'F'
            add_mc(histogram)

    data = histograms_[data_index]
    data.SetMarkerSize(CMS.data_marker_size)
    if normalise:
        n_events_data = data.Integral()
        n_events_mc = stack.Integral()
        data.Scale(1 / n_events_data)
        stack.Scale(1 / n_events_mc)

    # plot with matplotlib
    plt.figure(figsize=CMS.figsize, dpi=CMS.dpi, facecolor=CMS.facecolor)
    axes = None
    if show_ratio:
        ratio = data.Clone('ratio')
        sumHists = sum(stack.GetHists())
        for bin_i in range(1, sumHists.GetNbinsX()):
            sumHists.SetBinError(bin_i, 0)
        ratio.Divide(sum(stack.GetHists()))
        ratio.SetMarkerSize(3)
        gs = gridspec.GridSpec(2, 1, height_ratios=[5, 1])
        axes = plt.subplot(gs[0])
    else:
        axes = plt.axes()

    if histogram_properties.set_log_y:
        axes.set_yscale('log', nonposy="clip")
        axes.set_ylim(ymin=1e-2)

    if systematics_for_plot != None:
        plusErrors = [x + 1 for x in systematics_for_plot]
        minusErrors = [1 - x for x in systematics_for_plot]

        stack_lower = sum(stack.GetHists())
        stack_upper = stack_lower.Clone('upper')

        for bin_i in range(1, stack_lower.GetNbinsX() + 1):
            central_value = stack_lower.GetBinContent(bin_i)
            error_upper_bound = plusErrors[bin_i - 1] * central_value
            error_lower_bound = minusErrors[bin_i - 1] * central_value
            stack_upper.SetBinContent(bin_i, error_upper_bound)
            stack_lower.SetBinContent(bin_i, error_lower_bound)

        rplt.fill_between(
            stack_lower,
            stack_upper,
            axes,
            hatch='//',
            # facecolor = 'Black',
            facecolor='None',
            edgecolor='Grey',
            alpha=1.,
            linewidth=0.,
            zorder=len(histograms_) + 1)

    mc_error = histogram_properties.mc_error
    mc_relative_errors = histogram_properties.mc_relative_errors
    if mc_relative_errors:
        stack_lower = sum(stack.GetHists())
        stack_upper = stack_lower.Clone('upper')
        for bin_i in range(1, stack_lower.GetNbinsX()):
            central_value = stack_lower.GetBinContent(bin_i)
            relative_error = mc_relative_errors[bin_i - 1]

            error_upper_bound = central_value * (1 + relative_error)
            error_lower_bound = central_value * (1 - relative_error)

            stack_lower.SetBinContent(bin_i, error_upper_bound)
            stack_upper.SetBinContent(bin_i, error_lower_bound)
        rplt.fill_between(stack_upper,
                          stack_lower,
                          axes,
                          facecolor='0.75',
                          alpha=0.5,
                          hatch='/',
                          zorder=len(histograms_) + 1)
    else:
        if mc_error > 0:
            stack_lower = sum(stack.GetHists())
            stack_upper = stack_lower.Clone('upper')
            stack_lower.Scale(1 - mc_error)
            stack_upper.Scale(1 + mc_error)
            rplt.fill_between(stack_upper,
                              stack_lower,
                              axes,
                              facecolor='0.75',
                              alpha=0.5,
                              hatch='/',
                              zorder=len(histograms_) + 1)
        if not mc_error > 0 and show_stat_errors_on_mc:
            stack_lower = sum(stack.GetHists())
            mc_errors = list(stack_lower.yerravg())
            stack_upper = stack_lower.Clone('upper')
            for bin_i in range(1, stack_lower.GetNbinsX()):
                central_value = stack_lower.GetBinContent(bin_i)
                error = mc_errors[bin_i - 1]
                error_upper_bound = central_value + error
                error_lower_bound = central_value - error
                stack_lower.SetBinContent(bin_i, error_lower_bound)
                stack_upper.SetBinContent(bin_i, error_upper_bound)
            rplt.fill_between(stack_upper,
                              stack_lower,
                              axes,
                              facecolor='0.75',
                              alpha=0.5,
                              hatch='/',
                              zorder=len(histograms_) + 1)

    # a comment on zorder: the MC stack should be always at the very back (z = 1),
    # then the MC error (z = len(histograms_) + 1) and finally the data
    # (z = len(histograms_) + 2)
    rplt.hist(stack, stacked=True, axes=axes, zorder=1)
    rplt.errorbar(data,
                  emptybins=histogram_properties.emptybins,
                  axes=axes,
                  xerr=histogram_properties.xerr,
                  elinewidth=2,
                  capsize=10,
                  capthick=2,
                  zorder=len(histograms_) + 2)

    if histograms_to_compare:
        h_compare = {}
        for h, l, c in zip(histograms_to_compare['hists'],
                           histograms_to_compare['labels'],
                           histograms_to_compare['colours']):
            for histogram in histograms_:
                if histogram.GetTitle() not in [
                        histograms_to_compare['to_replace'], 'data'
                ]:
                    h += histogram
            h_compare[l] = [h, c]
            rplt.step(
                h,
                axes=axes,
                label=l,
                color=c,
                linewidth=4,
            )

    # put legend into the correct order (data is always first!)
    handles, labels = axes.get_legend_handles_labels()
    data_label_index = labels.index('data')
    data_handle = handles[data_label_index]
    labels.remove('data')
    handles.remove(data_handle)
    labels.insert(0, 'data')
    handles.insert(0, data_handle)
    if mc_error > 0 or (not mc_error > 0 and show_stat_errors_on_mc):
        p1 = Rectangle((0, 0), 1, 1, fc="0.75", alpha=0.5, hatch='/')
        handles.append(p1)
        labels.append(histogram_properties.mc_errors_label)

    l1 = axes.legend(handles,
                     labels,
                     numpoints=1,
                     frameon=histogram_properties.legend_color,
                     bbox_to_anchor=histogram_properties.legend_location,
                     bbox_transform=plt.gcf().transFigure,
                     prop=CMS.legend_properties,
                     ncol=histogram_properties.legend_columns)
    l1.set_zorder(102)

    set_labels(plt,
               histogram_properties,
               show_x_label=not show_ratio,
               axes=axes)

    x_limits = histogram_properties.x_limits
    y_limits = histogram_properties.y_limits

    if len(x_limits) >= 2:
        axes.set_xlim(xmin=x_limits[0], xmax=x_limits[-1])
    if len(y_limits) >= 2:
        axes.set_ylim(ymin=y_limits[0], ymax=y_limits[-1])
    else:
        y_max = get_best_max_y(
            histograms_, x_limits=x_limits) * histogram_properties.y_max_scale
        print("Chosen limits : ", 0, y_max)
        axes.set_ylim(ymin=0, ymax=y_max)
    if histogram_properties.set_log_y:
        if not len(y_limits) == 2:  # if not user set y-limits, set default
            axes.set_ylim(ymin=1e-1)

    #draw a red vertical line if needed:
    if draw_vertical_line != 0:
        plt.axvline(x=draw_vertical_line, color='red', linewidth=3)

    if show_ratio:
        plt.setp(axes.get_xticklabels(), visible=False)
        ax1 = plt.subplot(gs[1])
        ax1.minorticks_on()
        ax1.grid(True, 'major', linewidth=1)
        ax1.axhline(y=1, linewidth=1)
        set_labels(plt,
                   histogram_properties,
                   show_x_label=True,
                   show_title=False)
        plt.ylabel(r'$\frac{\mathrm{data}}{\mathrm{pred.}}$', CMS.y_axis_title)
        ax1.yaxis.set_label_coords(-0.115, 0.8)
        rplt.errorbar(ratio,
                      emptybins=histogram_properties.emptybins,
                      axes=ax1,
                      xerr=histogram_properties.xerr,
                      elinewidth=1.5,
                      capsize=5,
                      capthick=1.5)
        if histograms_to_compare:
            for l, h in h_compare.iteritems():
                r = data.Clone(l).Divide(h[0])
                rplt.step(
                    r,
                    axes=ax1,
                    label='',
                    colour=h[1],
                    linewidth=2,
                )

        if len(x_limits) >= 2:
            ax1.set_xlim(xmin=x_limits[0], xmax=x_limits[-1])
        if len(histogram_properties.ratio_y_limits) >= 2:
            ax1.set_ylim(ymin=histogram_properties.ratio_y_limits[0],
                         ymax=histogram_properties.ratio_y_limits[-1])

        # dynamic tick placement
        adjust_ratio_ticks(ax1.yaxis,
                           n_ticks=3,
                           y_limits=histogram_properties.ratio_y_limits)

        if histogram_properties.integerXVariable:
            ax1.tick_params(axis='x', which='minor', bottom='off', top='off')

        if systematics_for_ratio != None:
            plusErrors = [x + 1 for x in systematics_for_ratio]
            minusErrors = [1 - x for x in systematics_for_ratio]

            ratioPlusError = ratio.Clone('plus')
            ratioMinusError = ratio.Clone('minus')
            for bin_i in range(1, ratioPlusError.GetNbinsX() + 1):
                ratioPlusError.SetBinContent(bin_i, plusErrors[bin_i - 1])
                ratioMinusError.SetBinContent(bin_i, minusErrors[bin_i - 1])
            rplt.fill_between(
                ratioPlusError,
                ratioMinusError,
                axes,
                hatch='//',
                # facecolor = 'Black',
                facecolor='None',
                edgecolor='Grey',
                alpha=1.,
                linewidth=0.,
                # zorder = len(histograms_) + 1
                zorder=0)

    if CMS.tight_layout:
        plt.tight_layout()

    for save in save_as:
        if save == 'root':
            saveHistogramsToROOTFile(
                data, stack,
                save_folder + histogram_properties.name + '.' + save)
        else:
            plt.savefig(save_folder + histogram_properties.name + '.' + save)

    plt.close()
Ejemplo n.º 7
0
def draw_data_mc(tf, hname, processes, signal_processes, **kwargs):
    """
    Given a root file in the combine datacard format, draws a data/mc histogram,
    ratio and systematic band.
    tf (TFile): input root file
    hname (string): name of histogram, example "sl_jge6_tge4/jetsByPt_0_pt"
    processes (list of (str, str) tuples): processes to use for the plot. First
        argument of tuple is the name in the file, second the name on the plot.
        The order here defines the order of plotting (bottom to top). Assume that
        signal is the first process.
    signal_processes (list of str): process names to consider as signal
    """

    # name (string) of the data process.
    # Example: "data" (real data), "data_obs" (fake data)
    #must exist in the input file
    dataname = kwargs.get("dataname", "data_obs")
    
    xlabel = kwargs.get("xlabel", escape_string(hname))
    xunit = kwargs.get("xunit", "XUNIT")
    ylabel = kwargs.get("ylabel", "auto")
    rebin = kwargs.get("rebin", 1)
    title_extended = kwargs.get("title_extended", "")

    #legend properties
    do_legend = kwargs.get("do_legend", True)
    legend_loc = kwargs.get("legend_loc", (1.1,0.1))
    legend_fontsize = kwargs.get("legend_fontsize", 6)

    #Dictionary of sample (string) -> color (tuple of floats) to use as colors
    #or "auto" to generate a sequence of colors
    colors = kwargs.get("colors", "auto")

    #True if you want to put the contents of the overflow bin into the last
    #visible bin of the histogram, False otherwise
    show_overflow = kwargs.get("show_overflow", False)

    #function f: TH1D -> TH1D to apply on data to blind it.
    blindFunc = kwargs.get("blindFunc", None)

    #array of up-down pairs for systematic names to use for the systematic band,
    #e.g.[("_CMS_scale_jUp", "_CMS_scale_jDown")]
    systematics = kwargs.get("systematics", [])

    histograms_nominal = getHistograms(tf, processes, hname)
    if len(histograms_nominal) == 0:
        raise KeyError("did not find any histograms for MC")

    histograms_systematic = OrderedDict()
    #get the systematically variated histograms
    for systUp, systDown in systematics:
        histograms_systematic[systUp] = getHistograms(tf, processes, hname+systUp)
        histograms_systematic[systDown] = getHistograms(tf, processes, hname+systDown)
        if len(histograms_systematic[systUp])==0 or len(histograms_systematic[systDown])==0:
            print "Could not read histograms for {0}".format(hname+systUp)

    processes_d = dict(processes)

    for histo_dict in [histograms_nominal] + histograms_systematic.values():
        for (proc, h) in histo_dict.items():
            h.title = processes_d[proc] + " ({0:.1f})".format(h.Integral())
            h.rebin(rebin)
            if show_overflow:
                fill_overflow(h)
            
    c = plt.figure(figsize=(6,6))

    #Create top panel
    a1 = plt.axes([0.0, 0.22, 1.0, 0.8])
        
    c.suptitle(r"$\textbf{CMS}$ preliminary $\sqrt{s} = 13$ TeV"+title_extended,
        y=1.02, x=0.02,
        horizontalalignment="left", verticalalignment="bottom", fontsize=16
    )
    stacked_hists = mc_stack(
        histograms_nominal.values(),
        histograms_systematic,
        systematics,
        colors = colors
    )
    
    #Create the normalized signal shape
    histogram_signal = sum([histograms_nominal[sig] for sig in signal_processes])
    histogram_total_mc = sum(histograms_nominal.values())
    #hsig.Rebin(2)
    if histogram_signal.Integral()>0:
        histogram_signal.Scale(0.2 * histogram_total_mc.Integral() / histogram_signal.Integral())
    histogram_signal.title = processes[0][1] + " norm"
    histogram_signal.linewidth=2
    histogram_signal.fillstyle = None
    #draw the signal shape
    hist([histogram_signal])
    
    histogram_total_mc.title = "pseudodata"
    histogram_total_mc.color = "black"

    histogram_total_bkg = sum([
        histograms_nominal[k] for k in histograms_nominal.keys()
        if k not in signal_processes]
    )
    
    #Get the data histogram
    data = None
    if dataname != "":
        data = tf.get(dataname + "/" + hname)
        data.rebin(rebin)
        if blindFunc:
            data = blindFunc(data)
        if show_overflow:
            fill_overflow(data)
        data.title = "data ({0:.2f})".format(data.Integral())
        
        #set data error to 0 in case no data (FIXME) 
        for ibin in range(data.GetNbinsX()):
            if data.GetBinContent(ibin) == 0:
                data.SetBinError(ibin, 1)
        errorbar(data)

    if do_legend:
        #create nice filled legend patches for all the processes
        patches = []
        if data:
            dataline = mlines.Line2D([], [], color='black', marker='o', label=data.title)
            patches += [dataline]
        for (line1, line2), h in zip(stacked_hists["hists"], histograms_nominal.values()):
            patch = mpatches.Patch(color=line1.get_color(), label=h.title)
            patches += [patch]
        patches += [mpatches.Patch(facecolor="none", edgecolor="black", label="stat", hatch="////////")]
        patches += [mpatches.Patch(facecolor="none", edgecolor="gray", label="stat+syst", hatch=r"\\\\")]
        plt.legend(handles=patches, loc=legend_loc, numpoints=1, prop={'size':legend_fontsize}, ncol=2, frameon=False)
        
    #create an automatic bin width label on the y axis
    if ylabel == "auto":
        ylabel = "events / {0:.2f} {1}".format(histogram_signal.get_bin_width(1), xunit)
    plt.ylabel(ylabel)

    #hide x ticks on main panel
    ticks = a1.get_xticks()
    a1.get_xaxis().set_visible(False)
    
    a1.set_ylim(bottom=0, top=1.1*a1.get_ylim()[1])
    a1.grid(zorder=100000)

    a2 = a1
    
    #do ratio panel
    if data:
        a2 = plt.axes([0.0,0.0, 1.0, 0.18], sharex=a1)

        plt.xlabel(xlabel)
        a2.grid()
        
        data_ratio = data.Clone()
        data_ratio.Divide(histogram_total_mc)

        #In case MC was empty, set data/mc ratio to 0
        for ibin in range(data_ratio.GetNbinsX()):
            bc = histogram_total_mc.GetBinContent(ibin)
            if bc==0:
                data_ratio.SetBinContent(ibin, 0)

        #create also the variated band
        bg_unc_u = stacked_hists["tot_u"]
        bg_unc_d = stacked_hists["tot_d"]

        bg_unc_u.Divide(stacked_hists["tot"])
        bg_unc_d.Divide(stacked_hists["tot"])

        bg_unc_usyst = stacked_hists["tot_usyst"]
        bg_unc_dsyst = stacked_hists["tot_dsyst"]

        bg_unc_usyst.Divide(stacked_hists["tot"])
        bg_unc_dsyst.Divide(stacked_hists["tot"])
        
        #blind the data also on the ratio
        if blindFunc:
            data_ratio = blindFunc(data_ratio)
        errorbar(data_ratio)

        fill_between(
            bg_unc_u, bg_unc_d,
            color="black", hatch="////////",
            alpha=1.0, linewidth=0, facecolor="none", edgecolor="black", zorder=10,
        )

        fill_between(
            bg_unc_usyst, bg_unc_dsyst,
            color="gray", hatch=r"\\\\",
            alpha=1.0, linewidth=0, facecolor="none", edgecolor="gray", zorder=10,
        )
        plt.title("data={0:.1f}\ MC={1:.1f}".format(
            data.Integral(),
            stacked_hists["tot"].Integral()
            ), x=0.01, y=0.8, fontsize=10, horizontalalignment="left"
        )
        plt.ylabel(r"$\frac{\mathrm{data}}{\mathrm{pred.}}$", fontsize=16)
        plt.axhline(1.0, color="black")
        a2.set_ylim(0, 2)
        #hide last tick on ratio y axes
        a2.set_yticks(a2.get_yticks()[:-1]);
        a2.set_xticks(ticks);
    return a1, a2, histograms_nominal, stacked_hists, histograms_systematic
Ejemplo n.º 8
0
def draw_data_mc(tf, hname, samples, **kwargs):

    do_pseudodata = kwargs.get("do_pseudodata", False)
    dataname = kwargs.get("dataname", None)
    xlabel = kwargs.get("xlabel", hname.replace("_", " "))
    xunit = kwargs.get("xunit", "XUNIT")
    ylabel = kwargs.get("ylabel", "auto")
    rebin = kwargs.get("rebin", 1)
    title_extended = kwargs.get("title_extended", "")
    do_legend = kwargs.get("do_legend", True)
    legend_loc = kwargs.get("legend_loc", (1.1,0.1))
    legend_fontsize = kwargs.get("legend_fontsize", 6)
    colors = kwargs.get("colors", "auto")
    show_overflow = kwargs.get("show_overflow", False)
    blindFunc = kwargs.get("blindFunc", None)

    #array of up-down pairs for systematic names, e.g. _CMS_scale_jUp/Down
    systematics = kwargs.get("systematics", [])

    hs = OrderedDict()
    hs_syst = OrderedDict()
    hs = getHistograms(tf, samples, hname)

    #get the systematically variated histograms
    for systUp, systDown in systematics:
        hs_syst[systUp] = getHistograms(tf, samples, hname+systUp)
        hs_syst[systDown] = getHistograms(tf, samples, hname+systDown)
        if len(hs_syst[systUp])==0 or len(hs_syst[systDown])==0:
            print "Could not read histograms for {0}".format(hname+systUp)

    sample_d = dict(samples)
    for hd in [hs] + hs_syst.values():
        for (sample, h) in hd.items():
            make_uoflow(h)
            h.title = sample_d[sample] + " ({0:.1f})".format(h.Integral())
            h.rebin(rebin)
            if show_overflow:
                fill_overflow(h)
            
    c = plt.figure(figsize=(6,6))
    if do_pseudodata or dataname:
        a1 = plt.axes([0.0,0.22, 1.0, 0.8])
    else:
        a1 = plt.axes()
        
    c.suptitle("$\\textbf{CMS}$ preliminary $\sqrt{s} = 13$ TeV"+title_extended,
        y=1.02, x=0.02,
        horizontalalignment="left", verticalalignment="bottom", fontsize=16
    )
    if len(hs) == 0:
        raise KeyError("did not find any histograms for MC")
    r = mc_stack(hs.values(), hs_syst, systematics, colors=colors)
    
    #Create the normalized signal shape
    hsig = hs[samples[0][0]].Clone()
    tot_mc = sum(hs.values())
    #hsig.Rebin(2)
    if hsig.Integral()>0:
        hsig.Scale(0.2 * tot_mc.Integral() / hsig.Integral())
    hsig.title = samples[0][1] + " norm"
    hsig.linewidth=2
    hsig.fillstyle = None
    hist([hsig])
    
    tot_mc.title = "pseudodata"
    tot_mc.color = "black"

    tot_bg = sum([hs[k] for k in hs.keys() if "tth" not in k])
    
    data = None
    if do_pseudodata:
        data = tot_mc.Clone()
        data.title = "pseudodata"
        if blindFunc:
            data = blindFunc(data)
        idata = data.Integral()
    elif dataname:
        datas = []
        for dn in dataname:
            try:
                h = tf.get(dn + "/" + hname)
                datas += [tf.get(dn + "/" + hname).Clone()]
            except rootpy.io.file.DoesNotExist:
                print "missing", dn, hname
        if len(datas)>0:
            data = sum(datas)
            data.rebin(rebin)
        else:
            data = tot_mc.Clone()
            data.Scale(0.0)
        if blindFunc:
            data = blindFunc(data)
        data.title = "data ({0})".format(data.Integral())
        idata = data.Integral()

    if data and (blindFunc is None):
        if show_overflow:
            fill_overflow(data)
        for ibin in range(data.GetNbinsX()):
            if data.GetBinContent(ibin) == 0:
                data.SetBinError(ibin, 1)
        errorbar(data)

    if do_legend:
        patches = []
        if data:
            dataline = mlines.Line2D([], [], color='black', marker='o', label=data.title)
            patches += [dataline]
        for line, h in zip(r["hists"], hs.values()):
            #import pdb
            #pdb.set_trace()
            patch = mpatches.Patch(color=line[0].get_color(), label=h.title)
            patches += [patch]
        patches += [mpatches.Patch(facecolor="none", edgecolor="black", label="stat", hatch="////////")]
        patches += [mpatches.Patch(facecolor="none", edgecolor="gray", label="stat+syst", hatch="\\\\\\\\")]
        plt.legend(handles=patches, loc=legend_loc, numpoints=1, prop={'size':legend_fontsize}, ncol=2, frameon=False)
    if ylabel == "auto":
        ylabel = "events / {0:.2f} {1}".format(hs.values()[0].get_bin_width(1), xunit)
    plt.ylabel(ylabel)
    if not data:
        plt.xlabel(xlabel)
    #hide x ticks on main panel
    ticks = a1.get_xticks()
    if data:
        a1.get_xaxis().set_visible(False)
    #print ticks
    
    a1.set_ylim(bottom=0, top=1.1*a1.get_ylim()[1])
    a1.grid(zorder=100000)

    a2 = a1
    
    #do ratio panel
    if data:
        a2 = plt.axes([0.0,0.0, 1.0, 0.18], sharex=a1)

        plt.xlabel(xlabel)
        a2.grid()
        
        data.Divide(tot_mc)
        for ibin in range(data.GetNbinsX()):
            bc = tot_mc.GetBinContent(ibin)
            if bc==0:
                data.SetBinContent(ibin, 0)
        bg_unc_u = r["tot_u"]
        bg_unc_d = r["tot_d"]

        bg_unc_u.Divide(r["tot"])
        bg_unc_d.Divide(r["tot"])

        bg_unc_usyst = r["tot_usyst"]
        bg_unc_dsyst = r["tot_dsyst"]

        bg_unc_usyst.Divide(r["tot"])
        bg_unc_dsyst.Divide(r["tot"])
        if blindFunc:
            data = blindFunc(data)
        errorbar(data)

        fill_between(
            bg_unc_u, bg_unc_d,
            color="black", hatch="////////",
            alpha=1.0, linewidth=0, facecolor="none", edgecolor="black", zorder=10,
        )

        fill_between(
            bg_unc_usyst, bg_unc_dsyst,
            color="gray", hatch="\\\\\\\\",
            alpha=1.0, linewidth=0, facecolor="none", edgecolor="gray", zorder=10,
        )
        plt.title("data={0:.1f}\ MC={1:.1f}".format(idata, r["tot"].Integral()), x=0.01, y=0.8, fontsize=10, horizontalalignment="left")
        plt.ylabel("$\\frac{\mathrm{data}}{\mathrm{pred.}}$", fontsize=16)
        plt.axhline(1.0, color="black")
        a2.set_ylim(0, 2)
        #hide last tick on ratio y axes
        a2.set_yticks(a2.get_yticks()[:-1]);
        a2.set_xticks(ticks);
    return a1, a2, hs, r, hs_syst
Ejemplo n.º 9
0
def make_data_mc_comparison_plot( histograms = [],
                                 histogram_lables = [],
                                 histogram_colors = [],
                                 histogram_properties = Histogram_properties(),
                                 data_index = 0,
                                 save_folder = 'plots/',
                                 save_as = ['pdf'],
                                 normalise = False,
                                 show_ratio = False,
                                 show_stat_errors_on_mc = False,
                                 draw_vertical_line = 0,
                                 systematics_for_ratio = None
                                 ):
    save_folder = check_save_folder(save_folder)
    # make copies in order not to mess with existing histograms
    histograms_ = deepcopy(histograms)     
    stack = HistStack()
    add_mc = stack.Add
    for index, histogram in enumerate( histograms_ ):
        label = histogram_lables[index]
        color = histogram_colors[index]
        
        histogram.SetTitle( label )
        if normalise:
            histogram.Sumw2()
        
        if not index == data_index:
            histogram.fillstyle = 'solid'
            histogram.fillcolor = color
            histogram.legendstyle = 'F'
            add_mc( histogram )
            
    data = histograms_[data_index]
    data.SetMarkerSize( CMS.data_marker_size )
    if normalise:
        n_events_data = data.Integral()
        n_events_mc = stack.Integral()
        data.Scale( 1 / n_events_data )
        stack.Scale( 1 / n_events_mc )
    
    # plot with matplotlib
    plt.figure( figsize = CMS.figsize, dpi = CMS.dpi, facecolor = CMS.facecolor )
    axes=None
    if show_ratio:
        ratio = data.Clone( 'ratio' )
        ratio.Divide( sum( stack.GetHists() ) )
        ratio.SetMarkerSize( 3 )
        gs = gridspec.GridSpec( 2, 1, height_ratios = [5, 1] ) 
        axes = plt.subplot( gs[0] )
    else:
        axes = plt.axes()

    if histogram_properties.set_log_y:
        axes.set_yscale( 'log', nonposy = "clip" )
        axes.set_ylim( ymin = 1e-2 )
    mc_error = histogram_properties.mc_error

    if mc_error > 0:
        stack_lower = sum( stack.GetHists() )
        stack_upper = stack_lower.Clone( 'upper' )
        stack_lower.Scale( 1 - mc_error )
        stack_upper.Scale( 1 + mc_error )
        rplt.fill_between( stack_upper, 
                           stack_lower, axes, facecolor = '0.75', 
                           alpha = 0.5, hatch = '/', 
                           zorder = len(histograms_) + 1 )
    if not mc_error > 0 and show_stat_errors_on_mc:
        stack_lower = sum( stack.GetHists() )
        mc_errors = list( stack_lower.yerravg() )
        stack_upper = stack_lower.Clone( 'upper' )
        for bin_i in range( 1, stack_lower.GetNbinsX() ):
            stack_lower.SetBinContent( bin_i, stack_lower.GetBinContent( bin_i ) - mc_errors[bin_i - 1] )
            stack_upper.SetBinContent( bin_i, stack_upper.GetBinContent( bin_i ) + mc_errors[bin_i - 1] )
        rplt.fill_between( stack_upper, stack_lower, axes, facecolor = '0.75', 
                           alpha = 0.5, hatch = '/', 
                           zorder = len(histograms_) + 1 )

    # a comment on zorder: the MC stack should be always at the very back (z = 1), 
    # then the MC error (z = len(histograms_) + 1) and finally the data 
    # (z = len(histograms_) + 2)
    rplt.hist( stack, stacked = True, axes = axes, zorder = 1 )
    rplt.errorbar( data, emptybins = histogram_properties.emptybins, axes = axes,
                   xerr = histogram_properties.xerr,
                   elinewidth = 2, capsize = 10, capthick = 2,
                   zorder = len(histograms_) + 2 )
    
    # put legend into the correct order (data is always first!)
    handles, labels = axes.get_legend_handles_labels()
    data_label_index = labels.index( 'data' )
    data_handle = handles[data_label_index]
    labels.remove( 'data' )
    handles.remove( data_handle )
    labels.insert( 0, 'data' )
    handles.insert( 0, data_handle )
    if mc_error > 0 or ( not mc_error > 0 and show_stat_errors_on_mc ):
        p1 = Rectangle( ( 0, 0 ), 1, 1, fc = "0.75", alpha = 0.5, hatch = '/' )
        handles.append( p1 )
        labels.append( histogram_properties.mc_errors_label )

    l1 = axes.legend( handles, labels, numpoints = 1,
                     frameon = histogram_properties.legend_color,
                bbox_to_anchor = histogram_properties.legend_location,
                bbox_transform=plt.gcf().transFigure,
                prop = CMS.legend_properties,
                ncol = histogram_properties.legend_columns )
    l1.set_zorder(102)

    set_labels( plt, histogram_properties, show_x_label = not show_ratio, axes = axes )

    x_limits = histogram_properties.x_limits
    y_limits = histogram_properties.y_limits

    if len( x_limits ) >= 2:
        axes.set_xlim( xmin = x_limits[0], xmax = x_limits[-1] )
    if len( y_limits ) >= 2:
        axes.set_ylim( ymin = y_limits[0], ymax = y_limits[-1] )
    else:
        y_max = get_best_max_y(histograms_, x_limits=x_limits) * histogram_properties.y_max_scale
        axes.set_ylim( ymin = 0, ymax = y_max )
    if histogram_properties.set_log_y:
        if not len( y_limits ) == 2:  # if not user set y-limits, set default
            axes.set_ylim( ymin = 1e-1 )

    #draw a red vertical line if needed:
    if draw_vertical_line != 0:
        plt.axvline(x = draw_vertical_line, color = 'red', linewidth = 3)

    if show_ratio:
        plt.setp( axes.get_xticklabels(), visible = False )
        ax1 = plt.subplot( gs[1] )
        ax1.minorticks_on()
        ax1.grid( True, 'major', linewidth = 1 )
        ax1.axhline(y=1, linewidth = 1)
        set_labels( plt, histogram_properties, show_x_label = True, show_title = False )
        plt.ylabel( r'$\frac{\mathrm{data}}{\mathrm{pred.}}$', CMS.y_axis_title )
        ax1.yaxis.set_label_coords(-0.115, 0.8)
        rplt.errorbar( ratio, emptybins = histogram_properties.emptybins, axes = ax1,
                       xerr = histogram_properties.xerr,
                       elinewidth = 1.5, capsize = 5, capthick = 1.5 )
        if len( x_limits ) >= 2:
            ax1.set_xlim( xmin = x_limits[0], xmax = x_limits[-1] )
        if len( histogram_properties.ratio_y_limits ) >= 2:
            ax1.set_ylim( ymin = histogram_properties.ratio_y_limits[0],
                      ymax = histogram_properties.ratio_y_limits[-1] )

        # dynamic tick placement
        adjust_ratio_ticks(ax1.yaxis, n_ticks = 3, y_limits = histogram_properties.ratio_y_limits)

        if histogram_properties.integerXVariable :
            ax1.tick_params(axis='x',which='minor',bottom='off',top='off')

        if systematics_for_ratio != None:
            plusErrors = [x+1 for x in systematics_for_ratio]
            minusErrors = [1-x for x in systematics_for_ratio]
            print plusErrors
            print minusErrors

            ratioPlusError = ratio.Clone( 'plus' )
            ratioMinusError = ratio.Clone( 'minus' )
            for bin_i in range( 1, ratioPlusError.GetNbinsX()+1 ):
                ratioPlusError.SetBinContent( bin_i, plusErrors[bin_i-1] )
                ratioMinusError.SetBinContent( bin_i, minusErrors[bin_i-1] )
            rplt.fill_between( ratioPlusError, ratioMinusError, axes,
                               alpha = 0.3, hatch = '//',
                               facecolor = 'Black',
                               zorder = len(histograms_) + 1 )

    if CMS.tight_layout:
        plt.tight_layout()
    
    for save in save_as:
        if save == 'root':
            saveHistogramsToROOTFile( data, stack,save_folder + histogram_properties.name + '.' + save )
        else:
            plt.savefig( save_folder + histogram_properties.name + '.' + save )

    plt.close()
Ejemplo n.º 10
0
def make_plots( histograms, category, output_folder, histname, show_ratio = False, show_generator_ratio = False, show_before_unfolding = False, utype = 'normalised', preliminary=True ):
    global variable, phase_space

    channel = ''
    if 'electron' in histname:
        channel = 'electron'
    elif 'muon' in histname:
        channel = 'muon'
    else:
        channel = 'combined'

    # Initailise data histograms
    hist_data = histograms['unfolded']
    hist_data.markersize = 2
    hist_data.marker = 'o'
    if category == 'central':
        hist_data_with_systematics = histograms['unfolded_with_systematics']
        hist_data_with_systematics.markersize = 2
        hist_data_with_systematics.marker = 'o'

    # Create base figure to be plotted
    plt.figure( figsize = CMS.figsize, dpi = CMS.dpi, facecolor = CMS.facecolor )

    # Split into 3 for MC/Data ratio and generator ratio and plot
    if show_ratio and show_generator_ratio:
        gs = gridspec.GridSpec( 3, 1, height_ratios = [5, 1, 1] )
        axes = plt.subplot( gs[0] )
    # Split into 2 for MC/Data ratio or generator Ratio and plot
    elif show_ratio or show_generator_ratio:
        gs = gridspec.GridSpec( 2, 1, height_ratios = [4, 1] )
        axes = plt.subplot( gs[0] )
    # Just 1 for plot and setup x axis labels
    else:
        axes = plt.axes()
        x_label = '${}$'.format(variables_latex[variable])
        if variable in ['HT', 'ST', 'MET', 'WPT', 'lepton_pt']:
            x_label += ' [GeV]'
        plt.xlabel( x_label, CMS.x_axis_title )

    # set y axis x-section labels
    y_label = ''
    xsectionUnit = ''
    if utype == 'absolute':
        y_label = r'$\frac{d\sigma}{d' + variables_latex[variable] + '}\ '
        xsectionUnit = 'pb'
    else :
        y_label = r'$\frac{1}{\sigma}  \frac{d\sigma}{d' + variables_latex[variable] + '}\ '

    if variable in ['HT', 'ST', 'MET', 'WPT', 'lepton_pt']:
        if xsectionUnit is '':
            y_label += '\scriptstyle(\mathrm{GeV}^{-1})$'
            pass
        else:
            y_label += '\scriptstyle(\mathrm{'
            y_label += xsectionUnit
            y_label += '}\ \mathrm{GeV}^{-1})$'
    elif xsectionUnit is not '':
        y_label += '\scriptstyle(\mathrm{'
        y_label += xsectionUnit
        y_label += '})$'
    plt.ylabel( y_label, CMS.y_axis_title )

    # Set up ticks on axis. Minor ticks on axis for non NJet variables
    plt.tick_params( **CMS.axis_label_major )
    if not variable in ['NJets']:
        axes.minorticks_on()
        plt.tick_params( **CMS.axis_label_minor )

    # Set raw unfolded data with stat+unfolding uncertianty to be visible
    hist_data.visible = True
    # axes.set_yscale('log')
    # Set raw unfolded data with systematic uncertianty to be visible
    # label = 'do_not_show' = do not show in legend
    if category == 'central':
        hist_data_with_systematics.visible = True
        rplt.errorbar( 
            hist_data_with_systematics, 
            axes = axes, 
            label = 'do_not_show', 
            xerr = None, 
            capsize = 0, 
            elinewidth = 2, 
            zorder = len( histograms ) + 1 
        )
    
    # Show stat+unf uncertainty on plot
    rplt.errorbar( hist_data, 
        axes = axes, 
        label = 'do_not_show', 
        xerr = None, 
        capsize = 15, 
        capthick = 3, 
        elinewidth = 2, 
        zorder = len( histograms ) + 2 
    )
    # And one for a nice legend entry
    rplt.errorbar( hist_data, 
        axes = axes, 
        label = 'data', 
        xerr = None, 
        yerr = False, 
        capsize = 0, 
        elinewidth = 2, 
        zorder = len( histograms ) + 3 
    )

    dashes = {}
    for key, hist in sorted( histograms.items() ):
        zorder = sorted( histograms, reverse = False ).index( key )

        # Ordering such that systematic uncertainties are plotted first then central powhegPythia then data
        if key == 'TTJets_powhegPythia8' and zorder != len(histograms) - 3:
            zorder = len(histograms) - 3
        elif key != 'TTJets_powhegPythia8' and not 'unfolded' in key:
            while zorder >= len(histograms) - 3:
                zorder = zorder - 1 

        # Colour and style of MC hists
        if not 'unfolded' in key and not 'measured' in key:
            hist.linewidth = 4
            linestyle = None

            if 'powhegPythia8' in key:
                linestyle = 'solid'
                dashes[key] = None
                hist.SetLineColor( 633 )
            elif 'powhegHerwig' in key or 'isr' in key or 'hdamp' in key:
                hist.SetLineColor( kBlue )
                dashes[key] = [25,5,5,5,5,5,5,5]
            elif 'amcatnloPythia8' in key or 'fsr' in key or 'scale' in key:
                hist.SetLineColor( 807 )
                dashes[key] = [20,5]
            elif 'madgraphMLM' in key or 'renormalisation' in key or 'topPt' in key:
                hist.SetLineColor( 417 )
                dashes[key] = [5,5]
            elif 'factorisation' in key or 'ue' in key:
                hist.SetLineColor( 100 )
                dashes[key] = [10,10]
            elif 'combined' in key or 'semiLepBr' in key:
                hist.SetLineColor( 200 )
                dashes[key] = [20,10]
            elif 'semiLepBr' in key or 'mass' in key:
                hist.SetLineColor( 300 )
                dashes[key] = [20,10,10,10]
            elif 'frag' in key or 'Frag' in key:
                hist.SetLineColor( 400 )
                dashes[key] = [10,10,5,5]
            elif 'erdOn' in key:
                hist.SetLineColor( 500 )
                dashes[key] = [10,10,5,5,5,5]

            if linestyle != None:
                hist.linestyle = linestyle

            # Add hist to plot
            line, h = rplt.hist( hist, axes = axes, label = measurements_latex[key], zorder = zorder )

            # Set the dashes and lines
            if dashes[key] != None:
                line.set_dashes(dashes[key])
                h.set_dashes(dashes[key])

    handles, labels = axes.get_legend_handles_labels()
    
    # Making data first in the legend
    data_label_index = labels.index( 'data' )
    data_handle = handles[data_label_index]
    labels.remove( 'data' )
    handles.remove( data_handle )
    labels.insert( 0, 'data' )
    handles.insert( 0, data_handle )

    # Order the rest of the labels in the legend
    new_handles, new_labels = [], []
    zipped = dict( zip( labels, handles ) )
    labelOrder = ['data', 
        measurements_latex['TTJets_powhegPythia8'],
        measurements_latex['TTJets_amcatnloPythia8'],
        measurements_latex['TTJets_powhegHerwig'],
        measurements_latex['TTJets_madgraphMLM'],
        measurements_latex['TTJets_scaleup'], 
        measurements_latex['TTJets_scaledown'],
        measurements_latex['TTJets_massup'],
        measurements_latex['TTJets_massdown'],
        measurements_latex['TTJets_ueup'],
        measurements_latex['TTJets_uedown'],
        measurements_latex['TTJets_fsrup'],
        measurements_latex['TTJets_fsrdown'],
        measurements_latex['TTJets_isrdown'],
        measurements_latex['TTJets_isrup'],
        # measurements_latex['TTJets_alphaSup'],
        # measurements_latex['TTJets_alphaSdown'],
        measurements_latex['TTJets_topPt'],
        measurements_latex['TTJets_factorisationup'],
        measurements_latex['TTJets_factorisationdown'],
        measurements_latex['TTJets_renormalisationup'],
        measurements_latex['TTJets_renormalisationdown'],
        measurements_latex['TTJets_combinedup'],
        measurements_latex['TTJets_combineddown'],
        measurements_latex['TTJets_hdampup'],
        measurements_latex['TTJets_hdampdown'],
        measurements_latex['TTJets_erdOn'],
        measurements_latex['TTJets_QCDbased_erdOn'],
        measurements_latex['TTJets_GluonMove'],
        measurements_latex['TTJets_semiLepBrup'],
        measurements_latex['TTJets_semiLepBrdown'],
        measurements_latex['TTJets_fragup'],
        measurements_latex['TTJets_fragdown'],
        measurements_latex['TTJets_petersonFrag'],
    ]
    for label in labelOrder:
        if label in labels:
            new_handles.append(zipped[label])
            if label == 'data':
                new_labels.append(measurements_latex['data'])
            else:
                new_labels.append(label)

    # Location of the legend
    legend_location = (0.95, 0.82)
    prop = CMS.legend_properties
    if variable == 'MT':
        legend_location = (0.05, 0.82)
    elif variable == 'ST':
        legend_location = (0.97, 0.82)
    elif variable == 'WPT':
        legend_location = (1.0, 0.84)
    elif variable == 'abs_lepton_eta' or variable =='abs_lepton_eta_coarse':
        legend_location = (0.97, 0.87)
    elif variable == 'NJets':
        # Reduce size of NJets legend
        prop = {'size':30}

    # Add legend to plot
    plt.legend( new_handles, new_labels, 
        numpoints = 1, 
        prop = prop, 
        frameon = False, 
        bbox_to_anchor=legend_location,
        bbox_transform=plt.gcf().transFigure 
    )

    # Title and CMS labels
    # note: fontweight/weight does not change anything as we use Latex text!!!
    label, channel_label = get_cms_labels( channel )
    plt.title( label,loc='right', **CMS.title )

    # Locations of labels
    logo_location = (0.05, 0.97)
    channel_location = ( 0.05, 0.9)
    if preliminary:
        prelim_location = (0.05, 0.9)
        channel_location = ( 0.5, 0.97)
        # preliminary
        plt.text(prelim_location[0], prelim_location[1], 
            r"\emph{Preliminary}",
            transform=axes.transAxes, 
            fontsize=42,
            verticalalignment='top',
            horizontalalignment='left'
        )

    # if variable == 'WPT':
    #     logo_location = (0.05, 0.97)
    #     prelim_location = (0.05, 0.9)
    #     channel_location = (0.5, 0.97)
    # elif variable == 'abs_lepton_eta':
    #     logo_location = (0.05, 0.97)
    #     prelim_location = (0.05, 0.9)
    #     channel_location = ( 0.5, 0.97)

    # Add labels to plot
    plt.text(logo_location[0], logo_location[1], 
        r"\textbf{CMS}", 
        transform=axes.transAxes, 
        fontsize=42,
        verticalalignment='top',
        horizontalalignment='left'
    )


    # channel text
    plt.text(channel_location[0], channel_location[1], 
        r"%s"%channel_label, 
        transform=axes.transAxes, 
        fontsize=40,
        verticalalignment='top',
        horizontalalignment='left'
    )

    # Set y limits on plot
    ylim = axes.get_ylim()
    if ylim[0] < 0:
        axes.set_ylim( ymin = 0.)
    axes.set_ylim(ymax = ylim[1]*1.1)
    if variable == 'abs_lepton_eta' or variable == 'abs_lepton_eta_coarse':
        axes.set_ylim(ymax = ylim[1]*1.6)

    # Now to show either of the ratio plots
    if show_ratio:
        # Set previous x axis ticks and labels to invisible
        plt.setp( axes.get_xticklabels(), visible = False )
        # Go to ratio subplot
        ax1 = plt.subplot( gs[1] )

        # setting the x_limits identical to the main plot
        x_limits = axes.get_xlim()
        ax1.set_xlim(x_limits)

        # Setting tick marks
        ax1.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
        plt.tick_params( **CMS.axis_label_major )
        # if not variable in ['NJets']:
        #     ax1.minorticks_on()
        #     ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        #     plt.tick_params( **CMS.axis_label_minor )

        # x axis labels as before
        x_label = '${}$'.format(variables_latex[variable])
        if variable in ['HT', 'ST', 'MET', 'WPT', 'lepton_pt']:
            x_label += ' (GeV)'

        if not show_generator_ratio:
            plt.xlabel( x_label, CMS.x_axis_title )

        y_label = '$\\displaystyle\\frac{\\mathrm{pred.}}{\\mathrm{data}}$'
        plt.ylabel( y_label, CMS.y_axis_title_small )
        ax1.yaxis.set_label_coords(-0.115, 0.7)

        # Draw a horizontal line at y=1 for data
        plt.axhline(y = 1, color = 'black', linewidth = 2)

        # Create ratios and plot to subplot
        for key, hist in sorted( histograms.iteritems() ):
            if not 'unfolded' in key and not 'measured' in key:
                ratio = hist.Clone()
                ratio.Divide( hist_data )
                line, h = rplt.hist( ratio, axes = ax1, label = 'do_not_show' )
                if dashes[key] != None:
                    line.set_dashes(dashes[key])
                    h.set_dashes(dashes[key])

        # Now for the error bands
        stat_lower = hist_data.Clone()
        stat_upper = hist_data.Clone()
        syst_lower = hist_data.Clone()
        syst_upper = hist_data.Clone()

        # Plot relative error bands on data in the ratio plot
        stat_errors = graph_to_value_errors_tuplelist(hist_data)
        if category == 'central':
            syst_errors = graph_to_value_errors_tuplelist(hist_data_with_systematics)

        for bin_i in range( 1, hist_data.GetNbinsX() + 1 ):
            stat_value, stat_error, _ = stat_errors[bin_i-1]
            stat_rel_error = stat_error/stat_value
            stat_lower.SetBinContent( bin_i, 1 - stat_rel_error )
            stat_upper.SetBinContent( bin_i, 1 + stat_rel_error )
            if category == 'central':
                syst_value, syst_error_down, syst_error_up  = syst_errors[bin_i-1]
                syst_rel_error_down = syst_error_down/syst_value
                syst_rel_error_up = syst_error_up/syst_value
                syst_lower.SetBinContent( bin_i, 1 - syst_rel_error_down )
                syst_upper.SetBinContent( bin_i, 1 + syst_rel_error_up )

        # Colour
        if category == 'central':
            rplt.fill_between( 
                syst_lower, 
                syst_upper, 
                ax1,
                color = 'gold' 
            )
        rplt.fill_between(
            stat_upper, 
            stat_lower, 
            ax1, 
            color = '0.75',
        )

        # Add legend
        loc = 'upper left'
        if variable == 'MET':
            loc = 'lower left'
        elif variable == 'HT':
            loc = 'lower center'
        elif variable == 'ST':
            loc = 'lower center'
        elif variable == 'WPT':
            loc = 'lower left'
        elif variable == 'NJets':
            loc = 'lower left'
        elif variable == 'abs_lepton_eta' or variable == 'abs_lepton_eta_coarse':
            loc = 'upper left'
        elif variable == 'lepton_pt':
            loc = 'lower left'

        # legend for ratio plot
        p_stat = mpatches.Patch(facecolor='0.75', label='Stat.', edgecolor='black' )
        p_stat_and_syst = mpatches.Patch(facecolor='gold', label=r'Stat. $\oplus$ Syst.', edgecolor='black' )
        l1 = ax1.legend(
            handles = [p_stat, p_stat_and_syst], 
            loc = loc,
            frameon = False, 
            prop = {'size':26},
            ncol = 2
        )
        ax1.add_artist(l1)

        # Setting y limits and tick parameters
        if variable == 'MET':
            ax1.set_ylim( ymin = 0.6, ymax = 1.4 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        if variable == 'MT':
            ax1.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'HT':
            ax1.set_ylim( ymin = 0.6, ymax = 1.4 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'ST':
            ax1.set_ylim( ymin = 0.6, ymax = 1.4 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'WPT':
            ax1.set_ylim( ymin = 0.6, ymax = 1.4 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'NJets':
            ax1.set_ylim( ymin = 0.6, ymax = 1.4 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'abs_lepton_eta' or variable == 'abs_lepton_eta_coarse':
            ax1.set_ylim( ymin = 0.6, ymax = 1.4 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'lepton_pt':
            ax1.set_ylim( ymin = 0.6, ymax = 1.4 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )


    if show_generator_ratio:

        ax2 = None

        # Remove Data/MC Ratio Axis
        if show_ratio:
            plt.setp( ax1.get_xticklabels(), visible = False ) 
            ax2 = plt.subplot( gs[2] )
        else:
            plt.setp( axes.get_xticklabels(), visible = False )
            ax2 = plt.subplot( gs[1] )

        # setting the x_limits identical to the main plot
        x_limits = axes.get_xlim()
        ax2.set_xlim(x_limits)

        # Setting ticks
        ax2.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
        plt.tick_params( **CMS.axis_label_major )
        if not variable in ['NJets']:
            ax2.minorticks_on()
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
            plt.tick_params( **CMS.axis_label_minor )

        # x axis labels as before
        x_label = '${}$'.format(variables_latex[variable])
        if variable in ['HT', 'ST', 'MET', 'WPT', 'lepton_pt']:
            x_label += ' [GeV]'
        plt.xlabel( x_label, CMS.x_axis_title )

        y_label = 'Ratio to \n$' + measurements_latex['TTJets_powhegPythia8'] + '$'
        plt.ylabel( y_label, CMS.y_axis_title_tiny )

        #draw a horizontal line at y=1 for central MC
        plt.axhline(y = 1, color = 'black', linewidth = 2)

        central_mc = histograms['TTJets_powhegPythia8']
        for key, hist in sorted( histograms.iteritems() ):

            if not 'measured' in key:

                ratio = None
                if not 'unfolded_with_systematics' in key:
                    ratio = hist.Clone()
                    ratio.Divide( central_mc ) #divide by central mc sample
                else:
                    ratio = central_mc.Clone()
                    syst_errors = graph_to_value_errors_tuplelist(hist)
                    for bin_i in range( 1, ratio.GetNbinsX() + 1 ):
                        syst_value, syst_error_down, syst_error_up  = syst_errors[bin_i-1]

                        mc = central_mc.GetBinContent(bin_i)
                        data = list(hist.y())[bin_i-1]

                        ratio.SetBinContent( bin_i, data / mc)
                        ratio.SetBinError( bin_i, syst_error_down / mc )

                if not 'unfolded' in key:
                    line, h = rplt.hist( ratio, axes = ax2, label = 'do_not_show' )
                    if dashes[key] != None:
                        line.set_dashes(dashes[key])
                        h.set_dashes(dashes[key])
                elif 'unfolded_with_systematics' in key:
                        ratio.markersize = 2
                        ratio.marker = 'o'
                        ratio.color = 'black'
                        rplt.errorbar( 
                            ratio, 
                            axes = ax2, 
                            label = 'do_not_show', 
                            xerr = None, 
                            capsize = 0, 
                            elinewidth = 2, 
                            zorder = len( histograms ) + 10
                        )
                else:
                    ratio.markersize = 2
                    ratio.marker = 'o'

                    rplt.errorbar( ratio, 
                        axes = ax2, 
                        label = 'do_not_show', 
                        xerr = None, 
                        capsize = 15, 
                        capthick = 3, 
                        elinewidth = 2, 
                        zorder = len( histograms ) + 9
                    )


        if variable == 'MET':
            ax2.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax2.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        if variable == 'MT':
            ax2.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax2.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'HT':
            ax2.set_ylim( ymin = 0.7, ymax = 1.3 )
            ax2.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'ST':
            ax2.set_ylim( ymin = 0.7, ymax = 1.5 )
            ax2.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'WPT':
            ax2.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax2.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'NJets':
            ax2.set_ylim( ymin = 0.7, ymax = 1.5 )
        elif variable == 'abs_lepton_eta' or variable == 'abs_lepton_eta_coarse':
            ax2.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax2.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'lepton_pt':
            ax2.set_ylim( ymin = 0.8, ymax = 1.3 )
            ax2.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax2.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )


    if CMS.tight_layout:
        plt.tight_layout()

    # Save the plots
    path = '{output_folder}/xsections/{phaseSpace}/{variable}/'
    path = path.format(
        output_folder = output_folder,
        phaseSpace = phase_space,
        variable = variable
    )
    make_folder_if_not_exists( path )
    for output_format in output_formats:
        filename = path + '/' + histname + '.' + output_format
        plt.savefig( filename )

    del hist_data
    if 'central' in category: del hist_data_with_systematics
    plt.close()
    gc.collect()
    return
Ejemplo n.º 11
0
def make_data_mc_comparison_plot( histograms = [],
                                 histogram_lables = [],
                                 histogram_colors = [],
                                 histogram_properties = Histogram_properties(),
                                 data_index = 0,
                                 save_folder = 'plots/',
                                 save_as = ['pdf', 'png'],
                                 normalise = False,
                                 show_ratio = False,
                                 show_stat_errors_on_mc = False,
                                 draw_vertical_line = 0,
                                 ):
    # make copies in order not to mess with existing histograms
    histograms_ = deepcopy(histograms)     
    stack = HistStack()
    add_mc = stack.Add
    for index, histogram in enumerate( histograms_ ):
        label = histogram_lables[index]
        color = histogram_colors[index]
        
        histogram.SetTitle( label )
        if normalise:
            histogram.Sumw2()
        
        if not index == data_index:
            histogram.fillstyle = 'solid'
            histogram.fillcolor = color
            histogram.legendstyle = 'F'
            add_mc( histogram )
            
    data = histograms_[data_index]
    data.SetMarkerSize( CMS.data_marker_size )
    if normalise:
        n_events_data = data.Integral()
        n_events_mc = stack.Integral()
        data.Scale( 1 / n_events_data )
        stack.Scale( 1 / n_events_mc )
    
    # plot with matplotlib
    plt.figure( figsize = CMS.figsize, dpi = CMS.dpi, facecolor = CMS.facecolor )
    if show_ratio:
        ratio = data.Clone( 'ratio' )
        ratio.Divide( sum( stack.GetHists() ) )
        ratio.SetMarkerSize( 3 )
        gs = gridspec.GridSpec( 2, 1, height_ratios = [5, 1] ) 
        axes = plt.subplot( gs[0] )
    else:
        axes = plt.axes()

    if histogram_properties.set_log_y:
        axes.set_yscale( 'log', nonposy = "clip" )
        axes.set_ylim( ymin = 1e-2 )
    mc_error = histogram_properties.mc_error

    if mc_error > 0:
        stack_lower = sum( stack.GetHists() )
        stack_upper = stack_lower.Clone( 'upper' )
        stack_lower.Scale( 1 - mc_error )
        stack_upper.Scale( 1 + mc_error )
        rplt.fill_between( stack_upper, 
                           stack_lower, axes, facecolor = '0.75', 
                           alpha = 0.5, hatch = '/', 
                           zorder = len(histograms_) + 1 )
    if not mc_error > 0 and show_stat_errors_on_mc:
        stack_lower = sum( stack.GetHists() )
        mc_errors = list( stack_lower.yerravg() )
        stack_upper = stack_lower.Clone( 'upper' )
        for bin_i in range( 1, stack_lower.GetNbinsX() ):
            stack_lower.SetBinContent( bin_i, stack_lower.GetBinContent( bin_i ) - mc_errors[bin_i - 1] )
            stack_upper.SetBinContent( bin_i, stack_upper.GetBinContent( bin_i ) + mc_errors[bin_i - 1] )
        rplt.fill_between( stack_upper, stack_lower, axes, facecolor = '0.75', 
                           alpha = 0.5, hatch = '/', 
                           zorder = len(histograms_) + 1 )

    # a comment on zorder: the MC stack should be always at the very back (z = 1), 
    # then the MC error (z = len(histograms_) + 1) and finally the data 
    # (z = len(histograms_) + 2)
    rplt.hist( stack, stacked = True, axes = axes, zorder = 1 )
    rplt.errorbar( data, xerr = False, emptybins = False, axes = axes, 
                   elinewidth = 2, capsize = 10, capthick = 2, 
                   zorder = len(histograms_) + 2 )
    
    # put legend into the correct order (data is always first!)
    handles, labels = axes.get_legend_handles_labels()
    data_label_index = labels.index( 'data' )
    data_handle = handles[data_label_index]
    labels.remove( 'data' )
    handles.remove( data_handle )
    labels.insert( 0, 'data' )
    handles.insert( 0, data_handle )
    if mc_error > 0 or ( not mc_error > 0 and show_stat_errors_on_mc ):
        p1 = Rectangle( ( 0, 0 ), 1, 1, fc = "0.75", alpha = 0.5, hatch = '/' )
        handles.append( p1 )
        labels.append( histogram_properties.mc_errors_label )

    plt.legend( handles, labels, numpoints = 1, loc = histogram_properties.legend_location,
               prop = CMS.legend_properties, ncol = histogram_properties.legend_columns ).set_zorder(102)

    set_labels( plt, histogram_properties, show_x_label = not show_ratio )

    x_limits = histogram_properties.x_limits
    y_limits = histogram_properties.y_limits
    if len( x_limits ) == 2:
        axes.set_xlim( xmin = x_limits[0], xmax = x_limits[1] )
    if len( y_limits ) == 2:
        axes.set_ylim( ymin = y_limits[0], ymax = y_limits[1] )
    else:
        axes.set_ylim( ymin = 0 )
    if histogram_properties.set_log_y:
        if not len( y_limits ) == 2:  # if not user set y-limits, set default
            axes.set_ylim( ymin = 1e-1 )

    #draw a red vertical line if needed:
    if draw_vertical_line != 0:
        plt.axvline(x = draw_vertical_line, color = 'red', linewidth = 3)

    if show_ratio:
        plt.setp( axes.get_xticklabels(), visible = False )
        ax1 = plt.subplot( gs[1] )
        ax1.minorticks_on()
        ax1.grid( True, 'major', linewidth = 1 )
        ax1.yaxis.set_major_locator( MultipleLocator( 1.0 ) )
        ax1.yaxis.set_minor_locator( MultipleLocator( 0.5 ) )
        set_labels( plt, histogram_properties, show_x_label = True, show_title = False )
        plt.ylabel( 'data/MC', CMS.y_axis_title )
        rplt.errorbar( ratio, xerr = True, emptybins = False, axes = ax1 )
        if len( x_limits ) == 2:
            ax1.set_xlim( xmin = x_limits[0], xmax = x_limits[1] )
        ax1.set_ylim( ymin = 0, ymax = 2 )

    if CMS.tight_layout:
        plt.tight_layout()
    
    for save in save_as:
        plt.savefig( save_folder + histogram_properties.name + '.' + save )

    plt.close()
def make_plots( histograms, category, output_folder, histname, show_ratio = True, show_before_unfolding = False ):
    global variable, k_values
    
    channel = 'electron'
    if 'electron' in histname:
        channel = 'electron'
    elif 'muon' in histname:
        channel = 'muon'
    else:
        channel = 'combined'
        
    # plot with matplotlib
    hist_data = histograms['unfolded']
    if category == 'central':
        hist_data_with_systematics = histograms['unfolded_with_systematics']
    hist_measured = histograms['measured']
    
    hist_data.markersize = 2
    hist_data.marker = 'o'

    if category == 'central':
        hist_data_with_systematics.markersize = 2
        hist_data_with_systematics.marker = 'o'
    
    hist_measured.markersize = 2
    hist_measured.marker = 'o'
    hist_measured.color = 'red'

    plt.figure( figsize = CMS.figsize, dpi = CMS.dpi, facecolor = CMS.facecolor )
    if show_ratio:
        gs = gridspec.GridSpec( 2, 1, height_ratios = [5, 1] ) 
        axes = plt.subplot( gs[0] )
    else:
        axes = plt.axes()
        plt.xlabel( '$%s$ [GeV]' % variables_latex[variable], CMS.x_axis_title )

    axes.minorticks_on()
    
    plt.ylabel( r'$\frac{1}{\sigma}  \frac{d\sigma}{d' + variables_latex[variable] + '} \left[\mathrm{GeV}^{-1}\\right]$', CMS.y_axis_title )
    plt.tick_params( **CMS.axis_label_major )
    plt.tick_params( **CMS.axis_label_minor )

    hist_data.visible = True
    if category == 'central':
        hist_data_with_systematics.visible = True
        rplt.errorbar( hist_data_with_systematics, axes = axes, label = 'do_not_show', xerr = None, capsize = 0, elinewidth = 2, zorder = len( histograms ) + 1 )
    rplt.errorbar( hist_data, axes = axes, label = 'do_not_show', xerr = None, capsize = 15, capthick = 3, elinewidth = 2, zorder = len( histograms ) + 2 )
    rplt.errorbar( hist_data, axes = axes, label = 'data', xerr = None, yerr = False, zorder = len( histograms ) + 3 )  # this makes a nicer legend entry

    if show_before_unfolding:
        rplt.errorbar( hist_measured, axes = axes, label = 'data (before unfolding)', xerr = None, zorder = len( histograms ) )
    
    for key, hist in sorted( histograms.iteritems() ):
        if not 'unfolded' in key and not 'measured' in key:
            hist.linewidth = 4
            # setting colours
            if 'POWHEG_PYTHIA' in key or 'matchingdown' in key:
                hist.linestyle = 'longdashdot'
                hist.SetLineColor( kBlue )
            elif 'POWHEG_HERWIG' in key or 'scaledown' in key:
                hist.linestyle = 'dashed'
                hist.SetLineColor( kGreen )
            elif 'MADGRAPH_ptreweight' in key:
                hist.linestyle = 'dashed'
                hist.SetLineColor( kBlack )
            elif 'MADGRAPH' in key:
                hist.linestyle = 'solid'
                hist.SetLineColor( kRed + 1 )
            elif 'matchingup' in key:
                hist.linestyle = 'verylongdashdot'
                hist.linecolor = 'orange'
            elif 'MCATNLO'  in key or 'scaleup' in key:
                hist.linestyle = 'dotted'
                hist.SetLineColor( kMagenta + 3 )
            rplt.hist( hist, axes = axes, label = measurements_latex[key], zorder = sorted( histograms, reverse = True ).index( key ) )
            
    handles, labels = axes.get_legend_handles_labels()
    # making data first in the list
    data_label_index = labels.index( 'data' )
    data_handle = handles[data_label_index]
    labels.remove( 'data' )
    handles.remove( data_handle )
    labels.insert( 0, 'unfolded data' )
    handles.insert( 0, data_handle )
    
    new_handles, new_labels = [], []
    for handle, label in zip( handles, labels ):
        if not label == 'do_not_show':
            new_handles.append( handle )
            new_labels.append( label )
    
    legend_location = (0.98, 0.88)
    if variable == 'MT':
        legend_location = (0.05, 0.88)
    elif variable == 'ST':
        legend_location = (0.95, 0.88)
    plt.legend( new_handles, new_labels, numpoints = 1, prop = CMS.legend_properties, frameon = False, bbox_to_anchor=legend_location,
                bbox_transform=plt.gcf().transFigure )
    label, channel_label = get_cms_labels( channel )
    # title
    plt.title( label,loc='right', **CMS.title )
    # CMS text
    # note: fontweight/weight does not change anything as we use Latex text!!!
    plt.text(0.05, 0.98, r"\textbf{CMS}", transform=axes.transAxes, fontsize=42,
        verticalalignment='top',horizontalalignment='left')
    # channel text
    axes.text(0.95, 0.98, r"\emph{%s}" %channel_label, transform=axes.transAxes, fontsize=40,
        verticalalignment='top',horizontalalignment='right')


    if show_ratio:
        plt.setp( axes.get_xticklabels(), visible = False )
        ax1 = plt.subplot( gs[1] )
        ax1.minorticks_on()
        #ax1.grid( True, 'major', linewidth = 1 )
        # setting the x_limits identical to the main plot
        x_limits = axes.get_xlim()
        ax1.set_xlim(x_limits)
        ax1.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
        ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )

        plt.xlabel( '$%s$ [GeV]' % variables_latex[variable], CMS.x_axis_title )
        plt.tick_params( **CMS.axis_label_major )
        plt.tick_params( **CMS.axis_label_minor ) 
        plt.ylabel( '$\\frac{\\textrm{pred.}}{\\textrm{data}}$', CMS.y_axis_title_small )
        ax1.yaxis.set_label_coords(-0.115, 0.8)
        #draw a horizontal line at y=1 for data
        plt.axhline(y = 1, color = 'black', linewidth = 2)

        for key, hist in sorted( histograms.iteritems() ):
            if not 'unfolded' in key and not 'measured' in key:
                ratio = hist.Clone()
                ratio.Divide( hist_data ) #divide by data
                rplt.hist( ratio, axes = ax1, label = 'do_not_show' )

        stat_lower = hist_data.Clone()
        stat_upper = hist_data.Clone()
        syst_lower = hist_data.Clone()
        syst_upper = hist_data.Clone()

        # plot error bands on data in the ratio plot
        for bin_i in range( 1, hist_data.GetNbinsX() + 1 ):
            stat_errors = graph_to_value_errors_tuplelist(hist_data)
            stat_lower.SetBinContent( bin_i, 1 - stat_errors[bin_i-1][1]/stat_errors[bin_i-1][0] )
            stat_upper.SetBinContent( bin_i, 1 + stat_errors[bin_i-1][2]/stat_errors[bin_i-1][0] )
            if category == 'central':
                syst_errors = graph_to_value_errors_tuplelist(hist_data_with_systematics)
                syst_lower.SetBinContent( bin_i, 1 - syst_errors[bin_i-1][1]/syst_errors[bin_i-1][0] )
                syst_upper.SetBinContent( bin_i, 1 + syst_errors[bin_i-1][2]/syst_errors[bin_i-1][0] )

        if category == 'central':
            rplt.fill_between( syst_lower, syst_upper, ax1,
                               color = 'yellow', alpha = 0.5 )

        rplt.fill_between( stat_upper, stat_lower, ax1, color = '0.75',
                           alpha = 0.5 )
        # legend for ratio plot
        p_stat = mpatches.Patch(facecolor='0.75', label='Stat.',alpha = 0.5, edgecolor='black' )
        p_stat_and_syst = mpatches.Patch(facecolor='yellow', label=r'Stat. $\oplus$ Syst.', alpha = 0.5, edgecolor='black' )
        l1 = ax1.legend(handles = [p_stat], loc = 'upper left',
                     frameon = False, prop = {'size':26})
        
        ax1.legend(handles = [p_stat_and_syst], loc = 'lower left',
                     frameon = False, prop = {'size':26})
        ax1.add_artist(l1)

        if variable == 'MET':
            ax1.set_ylim( ymin = 0.7, ymax = 1.3 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
#             ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        if variable == 'MT':
            ax1.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'HT' or variable == 'ST':
            ax1.set_ylim( ymin = 0.5, ymax = 1.5 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'WPT':
            ax1.set_ylim( ymin = 0.75, ymax = 1.5 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.25 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.05 ) )


    if CMS.tight_layout:
        plt.tight_layout()

    path = output_folder + str( measurement_config.centre_of_mass_energy ) + 'TeV/' + variable + '/' + category
    make_folder_if_not_exists( path )
    for output_format in output_formats:
        filename = path + '/' + histname + '_kv' + str( k_values[channel] ) + '.' + output_format
        if channel == 'combined':
            filename = filename.replace( '_kv' + str( k_values[channel] ), '' )
        plt.savefig( filename )

    del hist_data, hist_measured
    plt.close()
    gc.collect()
Ejemplo n.º 13
0
    htot_usyst = h_bkg_s.Clone()
    htot_dsyst = h_bkg_s.Clone()
    for ibin in range(1, h_bkg_s.GetNbinsX() + 1):
        htot_usyst.SetBinContent(
            ibin,
            h_bkg_s.GetBinContent(ibin) + h_bkg_s.GetBinErrorUp(ibin))
        htot_dsyst.SetBinContent(
            ibin,
            h_bkg_s.GetBinContent(ibin) - h_bkg_s.GetBinErrorLow(ibin))

    rplt.fill_between(htot_usyst,
                      htot_dsyst,
                      hatch=r"////////",
                      alpha=1.0,
                      linewidth=0,
                      facecolor="none",
                      edgecolor="black",
                      zorder=10,
                      label=r"Bkgd. Unc")
    plot_unc = mpatches.Patch(facecolor="none",
                              edgecolor="black",
                              label="Bkgd. Unc",
                              hatch="////////")
    plt.legend(loc=1,
               handles=[plot_data, plot_sig1, plot_sig2, plot_bkg, plot_unc],
               numpoints=1,
               frameon=False)

    a2 = plt.axes([0.0, 0.0, 1.0, 0.20], sharex=a1)
def make_plots( histograms, category, output_folder, histname, show_ratio = True, show_before_unfolding = False ):
    global variable, phase_space

    channel = 'electron'
    if 'electron' in histname:
        channel = 'electron'
    elif 'muon' in histname:
        channel = 'muon'
    else:
        channel = 'combined'

    # plot with matplotlib
    hist_data = histograms['unfolded']
    if category == 'central':
        hist_data_with_systematics = histograms['unfolded_with_systematics']
    hist_measured = histograms['measured']

    hist_data.markersize = 2
    hist_data.marker = 'o'

    if category == 'central':
        hist_data_with_systematics.markersize = 2
        hist_data_with_systematics.marker = 'o'

    hist_measured.markersize = 2
    hist_measured.marker = 'o'
    hist_measured.color = 'red'

    plt.figure( figsize = CMS.figsize, dpi = CMS.dpi, facecolor = CMS.facecolor )
    if show_ratio:
        gs = gridspec.GridSpec( 2, 1, height_ratios = [5, 1] )
        axes = plt.subplot( gs[0] )
    else:
        axes = plt.axes()
        if variable in ['NJets', 'abs_lepton_eta', 'lepton_eta']:
            plt.xlabel( '$%s$' % variables_latex[variable], CMS.x_axis_title )
        else:
            plt.xlabel( '$%s$ [GeV]' % variables_latex[variable], CMS.x_axis_title )
    if not variable in ['NJets']:
        axes.minorticks_on()
    if variable in ['NJets', 'abs_lepton_eta', 'lepton_eta']:
        plt.ylabel( r'$\frac{1}{\sigma}  \frac{d\sigma}{d' + variables_latex[variable] + '}$', CMS.y_axis_title )
    else:
        plt.ylabel( r'$\frac{1}{\sigma}  \frac{d\sigma}{d' + variables_latex[variable] + '} \left[\mathrm{GeV}^{-1}\\right]$', CMS.y_axis_title )
    plt.tick_params( **CMS.axis_label_major )
    if not variable in ['NJets']:
        plt.tick_params( **CMS.axis_label_minor )

    hist_data.visible = True
    if category == 'central':
        hist_data_with_systematics.visible = True
        rplt.errorbar( hist_data_with_systematics, axes = axes, label = 'do_not_show', xerr = None, capsize = 0, elinewidth = 2, zorder = len( histograms ) + 1 )
    rplt.errorbar( hist_data, axes = axes, label = 'do_not_show', xerr = None, capsize = 15, capthick = 3, elinewidth = 2, zorder = len( histograms ) + 2 )
    rplt.errorbar( hist_data, axes = axes, label = 'data', xerr = None, yerr = False, zorder = len( histograms ) + 3 )  # this makes a nicer legend entry

    if show_before_unfolding:
        rplt.errorbar( hist_measured, axes = axes, label = 'data (before unfolding)', xerr = None, zorder = len( histograms ) )

    dashes = {}
    for key, hist in sorted( histograms.items() ):
        zorder = sorted( histograms, reverse = False ).index( key )
        if key == 'powhegPythia8' and zorder != len(histograms) - 3:
            zorder = len(histograms) - 3
        elif key != 'powhegPythia8' and not 'unfolded' in key:
            while zorder >= len(histograms) - 3:
                zorder = zorder - 1 

        if not 'unfolded' in key and not 'measured' in key:
            hist.linewidth = 4
            # setting colours
            linestyle = None
            if 'amcatnlo_HERWIG' in key or 'massdown' in key:
                hist.SetLineColor( kBlue )
                dashes[key] = [25,5,5,5,5,5,5,5]
            elif 'madgraphMLM' in key or 'scaledown' in key:
                hist.SetLineColor( 417 )
                dashes[key] = [5,5]
            elif 'MADGRAPH_ptreweight' in key:
                hist.SetLineColor( kBlack )
            elif 'powhegPythia8' in key:
                linestyle = 'solid'
                dashes[key] = None
                hist.SetLineColor( 633 )
            elif 'massup' in key or 'amcatnlo' in key:
                hist.SetLineColor( 807 )
                dashes[key] = [20,5]
            elif 'MCATNLO' in key or 'scaleup' in key:
                hist.SetLineColor( 619 )
                dashes[key] = [5,5,10,5]

            if linestyle != None:
                hist.linestyle = linestyle
            line, h = rplt.hist( hist, axes = axes, label = measurements_latex[key], zorder = zorder )

            if dashes[key] != None:
                line.set_dashes(dashes[key])
                h.set_dashes(dashes[key])

    handles, labels = axes.get_legend_handles_labels()
    # making data first in the list
    data_label_index = labels.index( 'data' )
    data_handle = handles[data_label_index]
    labels.remove( 'data' )
    handles.remove( data_handle )
    labels.insert( 0, 'data' )
    handles.insert( 0, data_handle )

    new_handles, new_labels = [], []
    zipped = dict( zip( labels, handles ) )
    labelOrder = ['data', 
        measurements_latex['powhegPythia8'],
        measurements_latex['amcatnlo'],
        measurements_latex['amcatnlo_HERWIG'],
        measurements_latex['madgraphMLM'],
        measurements_latex['scaleup'], 
        measurements_latex['scaledown'],
        measurements_latex['massup'],
        measurements_latex['massdown']
    ]
    for label in labelOrder:
        if label in labels:
            new_handles.append(zipped[label])
            new_labels.append(label)

    legend_location = (0.97, 0.82)
    if variable == 'MT':
        legend_location = (0.05, 0.82)
    elif variable == 'ST':
        legend_location = (0.97, 0.82)
    elif variable == 'WPT':
        legend_location = (1.0, 0.84)
    elif variable == 'abs_lepton_eta':
        legend_location = (1.0, 0.94)
    plt.legend( new_handles, new_labels, numpoints = 1, prop = CMS.legend_properties, frameon = False, bbox_to_anchor=legend_location,
                bbox_transform=plt.gcf().transFigure )
    label, channel_label = get_cms_labels( channel )
    # title
    plt.title( label,loc='right', **CMS.title )
    # CMS text
    # note: fontweight/weight does not change anything as we use Latex text!!!
    logo_location = (0.05, 0.98)
    prelim_location = (0.05, 0.92)
    channel_location = ( 0.05, 0.86)
    if variable == 'WPT':
        logo_location = (0.03, 0.98)
        prelim_location = (0.03, 0.92)
        channel_location = (0.03, 0.86)
    elif variable == 'abs_lepton_eta':
        logo_location = (0.03, 0.98)
        prelim_location = (0.03, 0.92)
        channel_location = (0.03, 0.86)
    plt.text(logo_location[0], logo_location[1], r"\textbf{CMS}", transform=axes.transAxes, fontsize=42,
        verticalalignment='top',horizontalalignment='left')
    # preliminary
    plt.text(prelim_location[0], prelim_location[1], r"\emph{Preliminary}",
                 transform=axes.transAxes, fontsize=42,
                 verticalalignment='top',horizontalalignment='left')
    # channel text
    plt.text(channel_location[0], channel_location[1], r"\emph{%s}" %channel_label, transform=axes.transAxes, fontsize=40,
        verticalalignment='top',horizontalalignment='left')
    ylim = axes.get_ylim()
    if ylim[0] < 0:
        axes.set_ylim( ymin = 0.)
    if variable == 'WPT':
        axes.set_ylim(ymax = ylim[1]*1.3)
    elif variable == 'abs_lepton_eta':
        axes.set_ylim(ymax = ylim[1]*1.3)
    else :
        axes.set_ylim(ymax = ylim[1]*1.2)


    if show_ratio:
        plt.setp( axes.get_xticklabels(), visible = False )
        ax1 = plt.subplot( gs[1] )
        if not variable in ['NJets']:
            ax1.minorticks_on()
        #ax1.grid( True, 'major', linewidth = 1 )
        # setting the x_limits identical to the main plot
        x_limits = axes.get_xlim()
        ax1.set_xlim(x_limits)
        ax1.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
        if not variable in ['NJets']:
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )

        if variable in ['NJets', 'abs_lepton_eta', 'lepton_eta']:
            plt.xlabel('$%s$' % variables_latex[variable], CMS.x_axis_title )
        else:
            plt.xlabel( '$%s$ [GeV]' % variables_latex[variable], CMS.x_axis_title )

        plt.tick_params( **CMS.axis_label_major )
        if not variable in ['NJets']:
            plt.tick_params( **CMS.axis_label_minor )
        plt.ylabel( '$\\frac{\\textrm{pred.}}{\\textrm{data}}$', CMS.y_axis_title )
        ax1.yaxis.set_label_coords(-0.115, 0.8)
        #draw a horizontal line at y=1 for data
        plt.axhline(y = 1, color = 'black', linewidth = 2)

        for key, hist in sorted( histograms.iteritems() ):
            if not 'unfolded' in key and not 'measured' in key:
                ratio = hist.Clone()
                ratio.Divide( hist_data ) #divide by data
                line, h = rplt.hist( ratio, axes = ax1, label = 'do_not_show' )
                if dashes[key] != None:
                    h.set_dashes(dashes[key])

        stat_lower = hist_data.Clone()
        stat_upper = hist_data.Clone()
        syst_lower = hist_data.Clone()
        syst_upper = hist_data.Clone()

        # plot error bands on data in the ratio plot
        stat_errors = graph_to_value_errors_tuplelist(hist_data)
        if category == 'central':
            syst_errors = graph_to_value_errors_tuplelist(hist_data_with_systematics)
        for bin_i in range( 1, hist_data.GetNbinsX() + 1 ):
            stat_value, stat_error, _ = stat_errors[bin_i-1]
            stat_rel_error = stat_error/stat_value
            stat_lower.SetBinContent( bin_i, 1 - stat_rel_error )
            stat_upper.SetBinContent( bin_i, 1 + stat_rel_error )
            if category == 'central':
                syst_value, syst_error_down, syst_error_up  = syst_errors[bin_i-1]
                syst_rel_error_down = syst_error_down/syst_value
                syst_rel_error_up = syst_error_up/syst_value
                syst_lower.SetBinContent( bin_i, 1 - syst_rel_error_down )
                syst_upper.SetBinContent( bin_i, 1 + syst_rel_error_up )
        if category == 'central':
            rplt.fill_between( syst_lower, syst_upper, ax1,
                               color = 'yellow' )

        rplt.fill_between( stat_upper, stat_lower, ax1, color = '0.75',
                            )

        loc = 'upper left'
        # if variable in ['ST']:
        #     loc = 'upper right'
        # legend for ratio plot
        p_stat = mpatches.Patch(facecolor='0.75', label='Stat.', edgecolor='black' )
        p_stat_and_syst = mpatches.Patch(facecolor='yellow', label=r'Stat. $\oplus$ Syst.', edgecolor='black' )
        l1 = ax1.legend(handles = [p_stat, p_stat_and_syst], loc = loc,
                     frameon = False, prop = {'size':26}, ncol = 2)

        # ax1.legend(handles = [p_stat_and_syst], loc = 'lower left',
        #              frameon = False, prop = {'size':30})
        ax1.add_artist(l1)

        if variable == 'MET':
            ax1.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
#             ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        if variable == 'MT':
            ax1.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'HT':
            ax1.set_ylim( ymin = 0.8, ymax = 1.37 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'ST':
            ax1.set_ylim( ymin = 0.7, ymax = 1.5 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'WPT':
            ax1.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.5 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'NJets':
            ax1.set_ylim( ymin = 0.7, ymax = 1.5 )
        elif variable == 'abs_lepton_eta':
            ax1.set_ylim( ymin = 0.8, ymax = 1.2 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )
        elif variable == 'lepton_pt':
            ax1.set_ylim( ymin = 0.8, ymax = 1.3 )
            ax1.yaxis.set_major_locator( MultipleLocator( 0.2 ) )
            ax1.yaxis.set_minor_locator( MultipleLocator( 0.1 ) )

    if CMS.tight_layout:
        plt.tight_layout()

    path = '{output_folder}/{centre_of_mass_energy}TeV/{phaseSpace}/{variable}/'
    path = path.format(
            output_folder = output_folder,
            centre_of_mass_energy = measurement_config.centre_of_mass_energy,
            phaseSpace = phase_space,
            variable = variable
            )
    make_folder_if_not_exists( path )
    for output_format in output_formats:
        filename = path + '/' + histname + '.' + output_format
        plt.savefig( filename )

    del hist_data, hist_measured
    plt.close()
    gc.collect()
Ejemplo n.º 15
0
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import rootpy.plotting.root2matplotlib as rplt
from rootpy.plotting import Hist

x = np.linspace(0, 2 * np.pi, 100)

plt.figure(figsize=(8, 8), dpi=100)
#plt.fill(x,np.sin(x),color='blue',alpha=0.5)
plt.fill(x, np.sin(x), color='None', edgecolor='blue', hatch='///')
plt.fill(x, np.sin(2 * x), color='None', linewidth=0, hatch=r'\\', zorder=950)

a = Hist(5, x[0], x[-1])
b = a.Clone()
b.Fill(3, .5)

rplt.fill_between(
    a,
    b,
    edgecolor='black',
    linewidth=0,
    facecolor=(0, 0, 0, 0),
    hatch=r'\\\\\\\\',
    zorder=900,
)
plt.savefig('./test.eps')
plt.savefig('./test.pdf')
Ejemplo n.º 16
0
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import rootpy.plotting.root2matplotlib as rplt
from rootpy.plotting import Hist

x = np.linspace(0,2*np.pi,100)

plt.figure(figsize=(8, 8), dpi=100)
#plt.fill(x,np.sin(x),color='blue',alpha=0.5)
plt.fill(x,np.sin(x),color='None', edgecolor='blue', hatch='///')
plt.fill(x,np.sin(2 * x),color='None',linewidth=0,hatch=r'\\', zorder=950)

a = Hist(5, x[0], x[-1])
b = a.Clone()
b.Fill(3, .5)

rplt.fill_between(a, b,
       edgecolor='black',
        linewidth=0,
        facecolor=(0,0,0,0),
        hatch=r'\\\\\\\\',
        zorder=900,
        )
plt.savefig('./test.eps')
plt.savefig('./test.pdf')