def draw_errorbars(self): if self.n_data_sets == 1: bin_height = [self.bin_content] bin_err = [self.bin_err] if self.histtype != 'marker': vis_object = [self.vis_object] else: vis_object = self.vis_object elif self.stacked: bin_height = [self.bin_content[-1]] bin_err = [self.bin_err] vis_object = [self.vis_object] else: bin_height = self.bin_content bin_err = self.bin_err vis_object = self.vis_object if not self.stacked: n_data_sets_eff = self.n_data_sets else: n_data_sets_eff = 1 for i in range(n_data_sets_eff): if self.err_dict['err_color'] == 'auto' and not self.stacked: if self.histtype == 'marker': err_color = colors.to_rgba(vis_object[i]._get_rgba_face()) elif self.histtype in ['stepfilled', 'bar']: err_color = colors.to_rgba( vis_object[i][0].get_facecolor()) elif self.histtype == 'step': err_color = colors.to_rgba( vis_object[i][0].get_edgecolor()) hls_tmp = colorsys.rgb_to_hls(*err_color[:-1]) err_color = list(colorsys.hls_to_rgb(hls_tmp[0], hls_tmp[1]*0.7, hls_tmp[2])) + \ [err_color[-1]] elif self.err_dict['err_color'] == 'auto' and self.stacked: err_color = next(self.ax._get_lines.prop_cycler)['color'] else: err_color = self.err_dict['err_color'] if self.histtype == 'marker': if self.err_dict['err_x']: xerr = self.widths * 0.5 else: xerr = None _, caps, _ = self.ax.errorbar(self.bin_centers, bin_height[i], linestyle='', marker='', yerr=bin_err[i], xerr=xerr, linewidth=2, color=err_color) else: if self.err_dict['err_style'] == 'line': self.ax.errorbar(self.bin_centers, bin_height[i], linestyle='', marker='', yerr=bin_err[i], linewidth=2, color=err_color) elif self.err_dict['err_style'] == 'band': if self.err_dict['err_type'] == 'poisson': fill_between_steps(self.ax, self.bin_edges, bin_height[i] + bin_err[i][1], bin_height[i] - bin_err[i][0], step_where='pre', linewidth=0, color=err_color, alpha=self.hist_dict['alpha'] * 0.8, zorder=10) else: fill_between_steps(self.ax, self.bin_edges, bin_height[i] + bin_err[i], bin_height[i] - bin_err[i], step_where='pre', linewidth=0, color=err_color, alpha=self.hist_dict['alpha'] * 0.8, zorder=10) if self.stacked: poly_patch = self.vis_object[-1][0].get_xy() self.ax.add_patch( Polygon(poly_patch[:(len(poly_patch) + 1) // 2], closed=False, facecolor='none', edgecolor='k', linewidth=1, alpha=0.5, zorder=0))
def ratio_plot(hist_dict1, hist_dict2, bins=None, range=None, ratio_range=None, err_style='band', err_color='dimgray', ratio_mode='default', grid=False, unity_line='red', logx=False): '''Function for creating ratio plots (comparing two histograms by dividing their bin content). The call structure is very similar to producing two individual histograms, with additional arguments specifying the nature of the ratio plot. The number of bins and ranges for both histograms must be equal. Note: Addition documentation soon.''' bin_range = range del range bins, bin_range = _check_args_ratio(hist_dict1, hist_dict2, bins, bin_range) hist_dict1['bins'] = bins hist_dict1['range'] = bin_range fig = plt.figure() gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1]) ax1 = fig.add_subplot(gs[0]) if logx: ax1.set_xscale("log", nonposx='clip') ax2 = fig.add_subplot(gs[1], sharex=ax1) # ax1.grid(True) # ax2.grid(True) plt.setp(ax1.get_xticklabels(), visible=False) fig.subplots_adjust(hspace=0.001) hist_dict1['ax'] = ax1 hist_dict2['ax'] = ax1 hist_con1 = HistContainer(**hist_dict1) bin_edges = hist_con1.bin_edges bin_range = (bin_edges[0], bin_edges[-1]) hist_dict2['bins'] = bin_edges hist_dict2['range'] = bin_range hist_con2 = HistContainer(**hist_dict2) ax1.set_xlim(bin_range) if hist_con1.stacked: bc1 = hist_con1.bin_content[-1] else: bc1 = hist_con1.bin_content if hist_con2.stacked: bc2 = hist_con2.bin_content[-1] else: bc2 = hist_con2.bin_content berr1 = getattr(hist_con1, 'bin_err', np.zeros(len(bc1))) berr2 = getattr(hist_con2, 'bin_err', np.zeros(len(bc2))) ratio = bc1 / bc2 ratio_err = ratio * np.sqrt((berr1 / bc1)**2 + (berr2 / bc2)**2) ratio_err_hi = ratio + ratio_err ratio_err_low = ratio - ratio_err ratio[ratio == 0] = np.nan fill_between_steps(ax2, hist_con1.bin_edges, ratio_err_hi, ratio_err_low, step_where='pre', linewidth=0, color=err_color, alpha=0.2, zorder=10) ax2.errorbar(hist_con1.bin_centers, ratio, yerr=None, xerr=[ hist_con1.bin_centers - hist_con1.bin_edges[0:-1], hist_con1.bin_edges[1:] - hist_con1.bin_centers ], fmt='d', color=err_color) if unity_line: ax2.axhline(1, linewidth=3, color=unity_line, zorder=0) ax2.yaxis.set_major_locator(MaxNLocator(nbins=4, prune='upper')) if ratio_range: ax2.set_ylim(ratio_range) else: ax2.set_ylim((0, 2.0)) return (ax1, ax2), (hist_con1.bin_content, hist_con1.bin_edges, hist_con1.vis_object), \ (hist_con2.bin_content, hist_con2.bin_edges, hist_con2.vis_object)