def __max__(plotable, include_error = True): if plotable is None: return 0 if plotable.__class__.__name__ == 'Hist': return plotable.max(include_error = include_error) if plotable.__class__.__name__ == 'Graph': ve = graph_to_value_errors_tuplelist(plotable) if not include_error: return max([v for v,_,_ in ve]) return max( [v + err_high for v, _, err_high in ve] )
def __max__(plotable, include_error=True): if plotable is None: return 0 if plotable.__class__.__name__ == 'Hist': return plotable.max(include_error=include_error) if plotable.__class__.__name__ == 'Graph': ve = graph_to_value_errors_tuplelist(plotable) if not include_error: return max([v for v, _, _ in ve]) return max([v + err_high for v, _, err_high in ve])
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()
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()