def plot(self): if self._ratio_plot: gs = gridspec.GridSpec(nrows=2, ncols=1, height_ratios=[3, 1], wspace=1.08, hspace=0., bottom=0.12, left=0.18) # gs.update(wspace=0.1, hspace=0.1, left=0.1, right=0.4, bottom=0.1, top=0.9) # gs.update(hspace=0.05) # set the spacing between axes. # gs.update(left=0.05, right=0.48, wspace=0.05) # self._plt.subplots_adjust(bottom=0.1, right=0.8, top=0.9) ax0 = self._plt.subplot(gs[0]) ax1 = self._plt.subplot(gs[1]) else: ax0 = self._plt.gca() # Set the logo.lin ax0.add_artist(self.logo_box()) # Set basic plot element formattings. lin self.set_formatting() # Normalize all the histograms. self.normalize_hists() z_indices = range(len(self._hists), 0, -1) if "error" in self._plot_types: z_indices[self._plot_types.index("error")] *= 10 if "theory" in self._plot_types: z_indices[self._plot_types.index("theory")] *= 5 # First, draw the regular "non-ratio" plot. legend_handles = [] for i in range(len(self._hists)): plot_type = self._plot_types[i] if plot_type == 'hist': #print("this is hist") #self._hists[i].hist().SetLineStyle(self._line_styles[i]) plot = self._rplt.hist(self._hists[i].hist(), axes=ax0, zorder=z_indices[i], emptybins=False) plot[1].set_dashes(self._line_styles[i]) legend_handles.append( plot ) # print legend_handles[i][1].get_dashes() elif plot_type == 'error': plot = self._rplt.errorbar(self._hists[i].hist(), axes=ax0, zorder=z_indices[i], emptybins=False, xerr=1, yerr=1, ls='None', marker='o', markersize=10, pickradius=8, capthick=5, capsize=8, elinewidth=5, alpha=1.0) legend_handles.append( plot ) elif plot_type == "theory": if self._x_scale == "log": x_s = np.exp( self._hists[i][0] ) else: x_s = self._hists[i][0] # There are two portions of x. # Find the index where we need to switch. np_correction_index = 0 for ab in range(len(x_s)): if x_s[ab] > self.get_np_correction_boundary(): np_correction_index = ab break # print np_correction_index, self.get_np_correction_boundary() # print x_s y_line_s = self._hists[i][2] y_min_s = self._hists[i][1] y_max_s = self._hists[i][3] # print x_s[ : np_correction_index] # Distribution. ax0.plot(x_s[ : np_correction_index + 1], y_line_s[ : np_correction_index + 1], lw=12, zorder=z_indices[i], color=self._plot_colors[i], ls="dotted") if "Track" not in self._x_label: ax0.plot(x_s[np_correction_index : ], y_line_s[np_correction_index : ], lw=8, zorder=z_indices[i], color=self._plot_colors[i]) ax0.fill_between(x_s[np_correction_index : ], y_max_s[np_correction_index : ], y_min_s[np_correction_index : ], zorder=z_indices[i], where=np.less_equal(y_min_s[np_correction_index : ], y_max_s[np_correction_index : ]), facecolor=self._plot_colors[i], color=self._plot_colors[i], interpolate=True, alpha=0.2, linewidth=0.) else: ax0.plot(x_s[np_correction_index : ], y_line_s[np_correction_index : ], ls="dotted", lw=12, zorder=z_indices[i], color=self._plot_colors[i]) theory_min_interpolate_function = self.extrap1d(interpolate.interp1d(x_s, y_min_s)) theory_line_interpolate_function = self.extrap1d(interpolate.interp1d(x_s, y_line_s)) theory_max_interpolate_function = self.extrap1d(interpolate.interp1d(x_s, y_max_s)) if self._hists[0].x_range() != (0, -1): # This is important for log plots because we don't want to consider the bins that's not visibile while figuring out how many bins to use for theory. # x_s_to_use = filter( lambda x: x >= self._hists[0].x_range()[0], self._plot_points_x_s[self._plot_types.index("error")] ) x_s_to_use = self._plot_points_x_s[self._plot_types.index("error")] else: x_s_to_use = self._plot_points_x_s[self._plot_types.index("error")] theory_extrapolated_min = theory_min_interpolate_function(x_s_to_use) theory_extrapolated_line = theory_line_interpolate_function(x_s_to_use) theory_extrapolated_max = theory_max_interpolate_function(x_s_to_use) # print "the data x points were", (x_s_to_use) if plot_type == "theory": self._plot_points_x_s.append( x_s ) self._plot_points_y_s.append( [] ) elif plot_type == "error": data_points_x = plot[0].get_xdata() data_points_y = plot[0].get_ydata() data_plot_points_x = [] data_plot_points_y = [] for i in range(0, len(data_points_x)): if float(data_points_x[i]) > 0.0: # This is just to ignore the points at the 0th bin. data_plot_points_x.append(data_points_x[i]) data_plot_points_y.append(data_points_y[i]) data_x_errors, data_y_errors = [], [] for x_segment in plot[2][0].get_segments(): data_x_errors.append((x_segment[1][0] - x_segment[0][0]) / 2.) for y_segment in plot[2][1].get_segments(): data_y_errors.append((y_segment[1][1] - y_segment[0][1]) / 2.) self._plot_points_x_s.append( data_plot_points_x ) self._plot_points_y_s.append( data_plot_points_y ) elif plot_type == "hist": bin_width = (self._hists[i].hist().upperbound() - self._hists[i].hist().lowerbound()) / self._hists[i].hist().nbins() if self._x_scale != "log": data_points_x = [x + bin_width / 2 for x in plot[1].get_xdata()][:-1] else: data_points_x = plot[1].get_xdata()[:-1] data_points_y = plot[1].get_ydata() data_plot_points_x = [] data_plot_points_y = [] for i in range(0, len(data_points_x)): if float(data_points_x[i]) > 0.0: # This is just to ignore the points at the 0th bin. data_plot_points_x.append(data_points_x[i]) data_plot_points_y.append(data_points_y[i]) self._plot_points_x_s.append( data_plot_points_x ) self._plot_points_y_s.append( data_plot_points_y ) if self._y_scale == 'log': ax0.set_yscale('log') pass # Ratio plot. if self._ratio_plot: if (type(self._ratio_to_index) == dict) or (type(self._ratio_to_index) == int and self._plot_types[self._ratio_to_index] == "hist" or self._plot_types[self._ratio_to_index] == "error"): # print "ratio to something else" for i in range(len(self._hists)): if type(self._ratio_to_index) == int: denominator_hist = self._hists[self._ratio_to_index].hist() elif type(self._ratio_to_index) == dict: denominator_hist = self._hists[self._ratio_to_index[i]].hist() plot_type = self._plot_types[i] ratio_hist = copy.deepcopy( self._hists[i].hist() ) #print(ratio_hist.lowerbound()) divided_hist = Hist(len(ratio_hist), ratio_hist.lowerbound(), ratio_hist.upperbound()) for k in range(len(ratio_hist)): num_val = ratio_hist.GetBinContent(k) denom_val = denominator_hist.GetBinContent(k) #print(i, num_val, denom_val) num_err = ratio_hist.GetBinError(k) denom_err = denominator_hist.GetBinError(k) if denom_val != 0.0: divided_hist.SetBinContent(k+1, num_val*1.0/denom_val) print(i, num_val*1.0/denom_val) if denom_err != 0.0: divided_hist.SetBinError(k+1, num_err*1.0/denom_val) print(i, num_err*1.0/denom_val) divided_hist.SetColor(self._plot_colors[i]) #ratio_hist.Divide(denominator_hist) if plot_type == 'hist': plot = self._rplt.hist(divided_hist, axes=ax1, zorder=z_indices[i], emptybins=False, lw=8) print("i", i) plot[1].set_dashes(self._line_styles[i]) elif plot_type == 'error': self._rplt.errorbar(divided_hist, axes=ax1, zorder=z_indices[i], emptybins=False, ls='None', marker='o', markersize=10, pickradius=8, capthick=5, capsize=8, elinewidth=5, alpha=1.0) # Ratio plot ends. handles, labels = legend_handles, self._plot_labels handler_map = {} if "theory" in self._plot_types: if "Track" not in self._x_label: th_line, = ax0.plot(range(1), linewidth=8, color='red') th_patch = mpatches.Patch(facecolor='red', alpha=0.2, linewidth=0., edgecolor='red') handles.insert( self._plot_types.index("theory"), (th_patch, th_line)) else: th_line, = ax0.plot(range(1), linewidth=12, ls="dotted", color='red') handles.insert( self._plot_types.index("theory"), (th_line, )) # labels.insert( self._plot_types.index("theory"), self._plot_labels[self._plot_types.index("theory")]) handler_map[th_line ] = HandlerLine2D(marker_pad=0) for i in range(len(handles)): if self._plot_types[i] == "hist": line, = ax0.plot(range(1), linewidth=8, color=self._plot_colors[i], dashes=self._line_styles[i]) handles[i] = line handler_map[line] = HandlerLine2D(marker_pad=0) legend = ax0.legend(handles, labels, frameon=0, fontsize=50, handler_map=handler_map, bbox_to_anchor=self._legend_location[1], loc=self._legend_location[0] ) # legend = ax0.legend(handles, labels, frameon=0, fontsize=60, handler_map=handler_map, bbox_to_anchor=self._legend_location, loc="upper left" ) ax0.add_artist(legend) # Any additional texts. extra = Rectangle((0, 0), 1, 1, fc="w", fill=False, edgecolor='none', linewidth=0) # ax0.legend([extra]*len(labels), labels, loc=7, frameon=0, borderpad=0.1, fontsize=60, bbox_to_anchor=[1.00, 0.53]) # get the width of your widest label, since every label will need #to shift by this amount after we align to the right shift = max([t.get_window_extent(plt.gcf().canvas.get_renderer()).width for t in legend.get_texts()]) if self._text_outside_the_frame: outside_text = ax0.legend( [extra], ["CMS 2011 Open Data"], frameon=0, borderpad=0, fontsize=50, bbox_to_anchor=(1.0, 1.005), loc='lower right') ax0.add_artist(outside_text) if "Soft Drop" in self._plot_labels[0]: additional_text = self._hists[1].additional_text() else: additional_text = self._hists[0].additional_text() for position, anchor_location, text in additional_text: texts = text.split("\n") additional_info = ax0.legend( [extra] * len(texts), texts, frameon=0, borderpad=0, fontsize=50, bbox_to_anchor=position, loc=anchor_location) if position[0] > 0.30: for t in additional_info.get_texts(): t.set_ha('right') # ha is alias for horizontalalignment t.set_position((shift,0)) # if len() # Axes labels. # ax0.set_xlabel(self._x_label, fontsize=60) # if "$" in self._y_label: if self._y_label[0] == "$": ax0.set_ylabel(self._y_label, fontsize=105, y=0.5, rotation=0, labelpad=120) else: ax0.set_ylabel(self._y_label, fontsize=65, y=0.5, labelpad=50) if self._ratio_plot: ax1.set_xlabel(self._x_label, fontsize=70, labelpad=35) ax1.set_ylabel(self._ratio_label, fontsize=55, labelpad=25) else: ax0.set_xlabel(self._x_label, fontsize=70, labelpad=35) # Axes labels end. self._plt.sca(ax0) self._plt.tick_params(which='major', width=5, length=25, labelsize=70) self._plt.tick_params(which='minor', width=3, length=15) if self._ratio_plot: self._plt.sca(ax1) self._plt.tick_params(which='major', axis='x', width=5, length=25, labelsize=70) self._plt.tick_params(which='major', axis='y', width=5, length=25, labelsize=45) self._plt.tick_params(which='minor', width=3, length=15) if self._ratio_plot: self._plt.gcf().set_size_inches(30, 24, forward=1) else: self._plt.gcf().set_size_inches(30, 24, forward=1) self._plt.sca(ax0) self._plt.autoscale() self._plt.xscale(self._x_scale) self._plt.gca().xaxis.set_major_formatter(mpl.ticker.ScalarFormatter()) if self._ratio_plot: self._plt.sca(ax1) self._plt.autoscale() self._plt.xscale(self._x_scale) self._plt.gca().xaxis.set_major_formatter(mpl.ticker.ScalarFormatter()) self._plt.sca(ax0) self._plt.gca().get_xaxis().set_ticklabels([]) if self._x_lims[1] == -1: ax0.set_xlim( self._x_lims[0], ax0.get_xlim()[1] ) else: ax0.set_xlim( self._x_lims[0], self._x_lims[1] ) if self._y_lims[1] == -1: ax0.set_ylim( self._y_lims[0], ax0.get_ylim()[1] * 1.125 ) else: # print self._y_lims[0], self._y_lims[1] ax0.set_ylim( self._y_lims[0], self._y_lims[1] ) if self._ratio_plot: ax1.set_xlim( ax0.get_xlim()[0], ax0.get_xlim()[1] ) ax1.set_ylim(0., 2.5) if self._hists[0].axes_label_pi(): plt.sca(ax0) plt.gca().set_xticks( [0, round(0.5*np.pi, 3), round(np.pi, 3), round(1.5*np.pi, 3), round(2*np.pi, 3)] ) plt.gca().set_xticklabels( ["0", "$\pi / 2$", "$\pi$", "$3 \pi / 2$", "$2 \pi$"] ) if self._ratio_plot: plt.sca(ax1) plt.gca().set_xticks( [0, round(0.5*np.pi, 3), round(np.pi, 3), round(1.5*np.pi, 3), round(2*np.pi, 3)] ) plt.gca().set_xticklabels( ["0", "$\pi / 2$", "$\pi$", "$3 \pi / 2$", "$2 \pi$"] ) plt.sca(ax0) plt.gca().set_xticklabels( [] ) if self._x_scale == "log": if self._ratio_plot: self._plt.sca(ax1) # ax1.xaxis.set_major_formatter(mtick.FormatStrFormatter('%.0e')) ax1.xaxis.set_major_formatter(mpl.ticker.ScalarFormatter(useMathText=False)) self._plt.sca(ax0) # print self._plt.gca().get_xlim() upper_lim = self._plt.gca().get_xlim()[1] lower_lim = self._plt.gca().get_xlim()[0] # print lower_lim if lower_lim < 0.01: denominations = [9] # 1 + 9 = 10. else: denominations = [1, 3, 5] # 1 + 1 = 2; 2 + 3 = 5; 5 + 5 = 10. multiplier = lower_lim count = 0 x_ticks = [lower_lim] # print abs(x_ticks[-1] - upper_lim) > 1e-6 if float(upper_lim) <= 5.: while abs(x_ticks[-1] - upper_lim) > 1e-6: x_ticks.append( x_ticks[-1] + denominations[count] * multiplier ) # print x_ticks[-1] + denominations[count] * multiplier if count == (len(denominations) - 1): count = 0 multiplier = x_ticks[-1] else: count += 1 # print x_ticks[-1] else: # print abs(x_ticks[-1] - upper_lim) # while abs(x_ticks[-1] - upper_lim) > 20: # x_ticks.append( x_ticks[-1] + denominations[count] * multiplier ) # # print x_ticks[-1] + denominations[count] * multiplier # if count == 2: # count = 0 # multiplier = x_ticks[-1] # else: # count += 1 pass x_ticks = [100, 200, 500, 1000, 2000] # print x_ticks self._plt.xticks(x_ticks) if self._ratio_plot: self._plt.sca(ax1) self._plt.xticks(x_ticks) if self._ratio_plot: self._plt.sca(ax1) self._plt.gca().get_yaxis().set_ticks( [ x for x in self._plt.gca().get_yaxis().get_majorticklocs() if x < 2.5 and x > 0.] ) # Minor ticks. if not self._x_scale == "log": if len(ax0.get_xaxis().get_majorticklocs()) >= 2: factor = abs(ax0.get_xaxis().get_majorticklocs()[1] - ax0.get_xaxis().get_majorticklocs()[0]) / 10 ax0.xaxis.set_minor_locator(MultipleLocator(factor)) if self._ratio_plot: ax1.xaxis.set_minor_locator(MultipleLocator(factor)) if not self._y_scale == "log": if len(ax0.get_yaxis().get_majorticklocs()) >= 2: factor = abs(ax0.get_yaxis().get_majorticklocs()[1] - ax0.get_yaxis().get_majorticklocs()[0]) / 5 ax0.yaxis.set_minor_locator(MultipleLocator(factor)) if self._ratio_plot: ax1.yaxis.set_minor_locator(MultipleLocator(0.1)) def convert_to_axes_coordinates(x, y): x_bounds, y_bounds = ax0.get_xlim(), ax0.get_ylim() return (x - x_bounds[0]) / (x_bounds[1] - x_bounds[0]), (y - y_bounds[0]) / (y_bounds[1] - y_bounds[0]) # Any possible markers. for marker in self._mark_regions: #print marker if "Area" in self._x_label: ax0.plot([marker[0], marker[0]], [2, marker[1] ], zorder=9999, color='red', linewidth=8, linestyle="dashed") else: #print([marker[0], marker[0]]) #print( [ax0.get_ylim()[0], marker[1] ]) ax0.plot([marker[0], marker[0]], [ax0.get_ylim()[0], marker[1]], zorder=9999, color='red', linewidth=8, linestyle="dashed") unit_x_minor_tick_length = abs(ax0.get_xaxis().get_majorticklocs()[1] - ax0.get_xaxis().get_majorticklocs()[0]) / 10 unit_y_minor_tick_length = abs(ax0.get_yaxis().get_majorticklocs()[1] - ax0.get_yaxis().get_majorticklocs()[0]) / 5 # print ax0.get_yaxis().get_majorticklocs()[1], ax0.get_yaxis().get_majorticklocs()[0] if marker[2] != None: # Arrows. if marker[2] == "right": if self._y_scale == 'log': #ax0.arrow(marker[0], fy(marker[3]), marker[4], 0., head_width=unit_y_minor_tick_length, head_length=unit_x_minor_tick_length, fc='red', ec='red', transform=ax0.transAxes) #ax0.arrow(marker[0], fy(marker[3]), marker[4], 0., fc='red', ec='red', transform=ax0.transAxes) #ax0.arrow(marker[0], marker[3], marker[4], 0., head_width=unit_y_minor_tick_length, head_length=unit_x_minor_tick_length, fc='red', ec='red') x_o, y_o = convert_to_axes_coordinates(marker[0], marker[3]) delta_x, delta_y = convert_to_axes_coordinates(marker[4], 0) print(x_o, y_o, delta_x, delta_y) ax0.arrow(x_o, y_o, delta_x, delta_y, fc='red', ec='red', head_length=0.02, head_width=0.03, transform=ax0.transAxes) else: ax0.arrow(marker[0], marker[3], marker[4], 0., head_width=unit_y_minor_tick_length, head_length=unit_x_minor_tick_length, fc='red', ec='red') elif marker[2] == "left": if self._y_scale == 'log': x_o, y_o = convert_to_axes_coordinates(marker[0], marker[3]) delta_x, delta_y = convert_to_axes_coordinates(marker[4], 0) ax0.arrow(marker[0], marker[3], marker[4], 0., head_width=unit_y_minor_tick_length, head_length=unit_x_minor_tick_length, fc='red', ec='red', transform=ax0.transAxes) else: ax0.arrow(marker[0], marker[3], marker[4], 0., head_width=unit_y_minor_tick_length, head_length=unit_x_minor_tick_length, fc='red', ec='red') if "Area" in self._x_label: ax0.text(marker[0], 1., "$\pi \mathrm{R}^2$", color='red', fontsize=75, horizontalalignment='center') self._plt.gcf().set_snap(True)