def __init__(self): self.fig = plt.figure(figsize=(3, 2)) self.ax = self.fig.add_subplot(111) self.ax_r, self.ax_g, self.ax_b = make_rgb_axes(self.ax, pad=0.02) self.rgb_name_list = ['R', 'G', 'B'] self.name_not_scalable = ['r2_adjust' ] # do not apply scaler norm on those data
def __init__(self): self.fig = plt.figure(figsize=(4,4)) self.ax = self.fig.add_subplot(111) self.ax_r, self.ax_g, self.ax_b = make_rgb_axes(self.ax, pad=0.02) self.rgb_name_list = ['R', 'G', 'B'] self.ic_norm = 1e4 # multiply by this value for ic normalization
def __init__(self): self.fig = plt.figure(figsize=(4, 4)) self.ax = self.fig.add_subplot(111) self.ax_r, self.ax_g, self.ax_b = make_rgb_axes(self.ax, pad=0.02) self.rgb_name_list = ['R', 'G', 'B'] self.ic_norm = 1e4 # multiply by this value for ic normalization
def demo_rgb(): fig, ax = plt.subplots() ax_r, ax_g, ax_b = make_rgb_axes(ax, pad=0.02) r, g, b = get_rgb() im_r, im_g, im_b, im_rgb = make_cube(r, g, b) kwargs = dict(origin="lower", interpolation="nearest") ax.imshow(im_rgb, **kwargs) ax_r.imshow(im_r, **kwargs) ax_g.imshow(im_g, **kwargs) ax_b.imshow(im_b, **kwargs)
def demo_rgb(): fig, ax = plt.subplots() ax_r, ax_g, ax_b = make_rgb_axes(ax, pad=0.02) r, g, b = get_rgb() im_r, im_g, im_b, im_rgb = make_cube(r, g, b) ax.imshow(im_rgb) ax_r.imshow(im_r) ax_g.imshow(im_g) ax_b.imshow(im_b)
def demo_rgb2(): fig, ax = plt.subplots() ax_r, ax_g, ax_b = make_rgb_axes(ax, pad=0.02) r, g, b = get_rgb() im_r, im_g, im_b, im_rgb = make_cube(r, g, b) ax.imshow(im_rgb) ax_r.imshow(im_r) ax_g.imshow(im_g) ax_b.imshow(im_b) for ax in fig.axes: ax.tick_params(axis='both', direction='in') ax.spines[:].set_color("w") for tick in ax.xaxis.get_major_ticks() + ax.yaxis.get_major_ticks(): tick.tick1line.set_markeredgecolor("w") tick.tick2line.set_markeredgecolor("w")
def demo_rgb(): fig = plt.figure(1) fig.clf() ax = fig.add_subplot(111) ax_r, ax_g, ax_b = make_rgb_axes(ax, pad=0.02) #fig.add_axes(ax_r) #fig.add_axes(ax_g) #fig.add_axes(ax_b) r, g, b = get_rgb() im_r, im_g, im_b, im_rgb = make_cube(r, g, b) kwargs = dict(origin="lower", interpolation="nearest") ax.imshow(im_rgb, **kwargs) ax_r.imshow(im_r, **kwargs) ax_g.imshow(im_g, **kwargs) ax_b.imshow(im_b, **kwargs)
def show_image(self): self.fig = plt.figure(figsize=(3, 2)) self.ax = self.fig.add_subplot(111) self.ax_r, self.ax_g, self.ax_b = make_rgb_axes(self.ax, pad=0.02) self.name_not_scalable = ['r2_adjust'] # do not apply scaler norm on those data # Check if positions data is available. Positions data may be unavailable # (not recorded in HDF5 file) if experiment is has not been completed. # While the data from the completed part of experiment may still be used, # plotting vs. x-y or scatter plot may not be displayed. positions_data_available = False if 'positions' in self.data_dict.keys(): positions_data_available = True # Create local copy of self.pixel_or_pos and self.grid_interpolate pixel_or_pos_local = self.pixel_or_pos grid_interpolate_local = self.grid_interpolate # Disable plotting vs x-y coordinates if 'positions' data is not available if not positions_data_available: if pixel_or_pos_local: pixel_or_pos_local = 0 # Switch to plotting vs. pixel number logger.error("'Positions' data is not available. Plotting vs. x-y coordinates is disabled") if grid_interpolate_local: grid_interpolate_local = False # Switch to plotting vs. pixel number logger.error("'Positions' data is not available. Interpolation is disabled.") selected_data, selected_name = self.preprocess_data() selected_data = np.asarray(selected_data) if len(selected_name) != 3: logger.error('Please select three elements for RGB plot.') return self.rgb_name_list = selected_name[:3] try: data_r = selected_data[0, :, :] except IndexError: selected_data = np.ones([3, 10, 10]) def _compute_equal_axes_ranges(x_min, x_max, y_min, y_max): """ Compute ranges for x- and y- axes of the plot. Make sure that the ranges for x- and y-axes are always equal and fit the maximum of the ranges for x and y values: max(abs(x_max-x_min), abs(y_max-y_min)) The ranges are set so that the data is always centered in the middle of the ranges Parameters ---------- x_min, x_max, y_min, y_max : float lower and upper boundaries of the x and y values Returns ------- x_axis_min, x_axis_max, y_axis_min, y_axis_max : float lower and upper boundaries of the x- and y-axes ranges """ x_axis_min, x_axis_max, y_axis_min, y_axis_max = x_min, x_max, y_min, y_max x_range, y_range = abs(x_max - x_min), abs(y_max - y_min) if x_range > y_range: y_center = (y_max + y_min) / 2 y_axis_max = y_center + x_range / 2 y_axis_min = y_center - x_range / 2 else: x_center = (x_max + x_min) / 2 x_axis_max = x_center + y_range / 2 x_axis_min = x_center - y_range / 2 return x_axis_min, x_axis_max, y_axis_min, y_axis_max def _adjust_data_range_using_min_ratio(c_min, c_max, c_axis_range, *, min_ratio=0.01): """ Adjust the range for plotted data along one axis (x or y). The adjusted range is applied to the 'extent' attribute of imshow(). The adjusted range is always greater than 'axis_range * min_ratio'. Such transformation has no physical meaning and performed for aesthetic reasons: stretching the image presentation of a scan with only a few lines (1-3) greatly improves visibility of data. Parameters ---------- c_min, c_max : float boundaries of the data range (along x or y axis) c_axis_range : float range presented along the same axis Returns ------- cmin, c_max : float adjusted boundaries of the data range """ c_range = c_max - c_min if c_range < c_axis_range * min_ratio: c_center = (c_max + c_min) / 2 c_new_range = c_axis_range * min_ratio c_min = c_center - c_new_range / 2 c_max = c_center + c_new_range / 2 return c_min, c_max if pixel_or_pos_local: # xd_min, xd_max, yd_min, yd_max = min(self.x_pos), max(self.x_pos), # min(self.y_pos), max(self.y_pos) x_pos_2D = self.data_dict['positions']['x_pos'] y_pos_2D = self.data_dict['positions']['y_pos'] xd_min, xd_max, yd_min, yd_max = x_pos_2D.min(), x_pos_2D.max(), y_pos_2D.min(), y_pos_2D.max() xd_axis_min, xd_axis_max, yd_axis_min, yd_axis_max = \ _compute_equal_axes_ranges(xd_min, xd_max, yd_min, yd_max) xd_min, xd_max = _adjust_data_range_using_min_ratio(xd_min, xd_max, xd_axis_max - xd_axis_min) yd_min, yd_max = _adjust_data_range_using_min_ratio(yd_min, yd_max, yd_axis_max - yd_axis_min) # Adjust the direction of each axis depending on the direction in which encoder values changed # during the experiment. Data is plotted starting from the upper-right corner of the plot if x_pos_2D[0, 0] > x_pos_2D[0, -1]: xd_min, xd_max, xd_axis_min, xd_axis_max = xd_max, xd_min, xd_axis_max, xd_axis_min if y_pos_2D[0, 0] > y_pos_2D[-1, 0]: yd_min, yd_max, yd_axis_min, yd_axis_max = yd_max, yd_min, yd_axis_max, yd_axis_min else: # Set equal ranges for the axes data yd, xd = selected_data.shape[1], selected_data.shape[2] xd_min, xd_max, yd_min, yd_max = 0, xd, 0, yd # Select minimum range for data if (yd <= math.floor(xd / 100)) and (xd >= 200): yd_min, yd_max = -math.floor(xd / 200), math.ceil(xd / 200) if (xd <= math.floor(yd / 100)) and (yd >= 200): xd_min, xd_max = -math.floor(yd / 200), math.ceil(yd / 200) xd_axis_min, xd_axis_max, yd_axis_min, yd_axis_max = \ _compute_equal_axes_ranges(xd_min, xd_max, yd_min, yd_max) name_r = self.rgb_name_list[self.index_red] data_r = selected_data[self.index_red, :, :] name_g = self.rgb_name_list[self.index_green] data_g = selected_data[self.index_green, :, :] name_b = self.rgb_name_list[self.index_blue] data_b = selected_data[self.index_blue, :, :] rgb_l_h = ({'low': self.r_low, 'high': self.r_high}, {'low': self.g_low, 'high': self.g_high}, {'low': self.b_low, 'high': self.b_high}) def _norm_data(data): """ Normalize data between (0, 1). Parameters ---------- data : 2D array """ data_min = np.min(data) c_norm = np.max(data) - data_min return (data - data_min) / c_norm if (c_norm != 0) else (data - data_min) def _stretch_range(data_in, v_low, v_high): # 'data is already normalized, so that the values are in the range 0..1 # v_low, v_high are in the range 0..100 if (v_low <= 0) and (v_high >= 100): return data_in if v_high - v_low < 1: # This should not happen in practice, but check just in case v_high = v_low + 1 v_low, v_high = v_low / 100.0, v_high / 100.0 c = 1.0 / (v_high - v_low) data_out = (data_in - v_low) * c return np.clip(data_out, 0, 1.0) # Interpolate non-uniformly spaced data to uniform grid if grid_interpolate_local: data_r, _, _ = grid_interpolate(data_r, self.data_dict['positions']['x_pos'], self.data_dict['positions']['y_pos']) data_g, _, _ = grid_interpolate(data_g, self.data_dict['positions']['x_pos'], self.data_dict['positions']['y_pos']) data_b, _, _ = grid_interpolate(data_b, self.data_dict['positions']['x_pos'], self.data_dict['positions']['y_pos']) # Normalize data data_r = _norm_data(data_r) data_g = _norm_data(data_g) data_b = _norm_data(data_b) data_r = _stretch_range(data_r, rgb_l_h[self.index_red]['low'], rgb_l_h[self.index_red]['high']) data_g = _stretch_range(data_g, rgb_l_h[self.index_green]['low'], rgb_l_h[self.index_green]['high']) data_b = _stretch_range(data_b, rgb_l_h[self.index_blue]['low'], rgb_l_h[self.index_blue]['high']) R, G, B, RGB = make_cube(data_r, data_g, data_b) red_patch = mpatches.Patch(color='red', label=name_r) green_patch = mpatches.Patch(color='green', label=name_g) blue_patch = mpatches.Patch(color='blue', label=name_b) kwargs = dict(origin="upper", interpolation="nearest", extent=(xd_min, xd_max, yd_max, yd_min)) self.ax.imshow(RGB, **kwargs) self.ax_r.imshow(R, **kwargs) self.ax_g.imshow(G, **kwargs) self.ax_b.imshow(B, **kwargs) self.ax.set_xlim(xd_axis_min, xd_axis_max) self.ax.set_ylim(yd_axis_max, yd_axis_min) self.ax_r.set_xlim(xd_axis_min, xd_axis_max) self.ax_r.set_ylim(yd_axis_max, yd_axis_min) self.ax_g.set_xlim(xd_axis_min, xd_axis_max) self.ax_g.set_ylim(yd_axis_max, yd_axis_min) self.ax_b.set_xlim(xd_axis_min, xd_axis_max) self.ax_b.set_ylim(yd_axis_max, yd_axis_min) self.ax.xaxis.set_major_locator(mticker.MaxNLocator(nbins="auto")) self.ax.yaxis.set_major_locator(mticker.MaxNLocator(nbins="auto")) plt.setp(self.ax_r.get_xticklabels(), visible=False) plt.setp(self.ax_r.get_yticklabels(), visible=False) plt.setp(self.ax_g.get_xticklabels(), visible=False) plt.setp(self.ax_g.get_yticklabels(), visible=False) plt.setp(self.ax_b.get_xticklabels(), visible=False) plt.setp(self.ax_b.get_yticklabels(), visible=False) # self.ax_r.set_xticklabels([]) # self.ax_r.set_yticklabels([]) # sb_x = 38 # sb_y = 46 # sb_length = 10 # sb_height = 1 # ax.add_patch(mpatches.Rectangle(( sb_x, sb_y), sb_length, sb_height, color='white')) # ax.text(sb_x + sb_length /2, sb_y - 1*sb_height, '100 nm', color='w', ha='center', # va='bottom', backgroundcolor='black', fontsize=18) self.ax.legend(bbox_to_anchor=(0., 1.0, 1., .10), ncol=3, handles=[red_patch, green_patch, blue_patch], mode="expand", loc=3) # self.fig.tight_layout(pad=4.0, w_pad=0.8, h_pad=0.8) # self.fig.tight_layout() # self.fig.canvas.draw_idle() self.fig.suptitle(self.img_title, fontsize=20) self.fig.canvas.draw_idle()
def __init__(self): self.fig = plt.figure(figsize=(4, 4)) self.ax = self.fig.add_subplot(111) self.ax_r, self.ax_g, self.ax_b = make_rgb_axes(self.ax, pad=0.02) self.rgb_name_list = ['R', 'G', 'B']
def __init__(self): self.fig = plt.figure(figsize=(3,2)) self.ax = self.fig.add_subplot(111) self.ax_r, self.ax_g, self.ax_b = make_rgb_axes(self.ax, pad=0.02) self.rgb_name_list = ['R', 'G', 'B'] self.name_not_scalable = ['r2_adjust'] # do not apply scaler norm on those data
def show_image(self): # Don't plot the image if dictionary is empty (causes a lot of issues) if not self.io_model.img_dict: return self.fig.clf() self.ax = self.fig.add_subplot(111) self.ax_r, self.ax_g, self.ax_b = make_rgb_axes(self.ax, pad=0.02) # Check if positions data is available. Positions data may be unavailable # (not recorded in HDF5 file) if experiment is has not been completed. # While the data from the completed part of experiment may still be used, # plotting vs. x-y or scatter plot may not be displayed. positions_data_available = False if "positions" in self.io_model.img_dict.keys(): positions_data_available = True # Create local copy of self.pixel_or_pos and self.grid_interpolate pixel_or_pos_local = self.pixel_or_pos grid_interpolate_local = self.grid_interpolate # Disable plotting vs x-y coordinates if 'positions' data is not available if not positions_data_available: if pixel_or_pos_local: pixel_or_pos_local = 0 # Switch to plotting vs. pixel number logger.error( "'Positions' data is not available. Plotting vs. x-y coordinates is disabled" ) if grid_interpolate_local: grid_interpolate_local = False # Switch to plotting vs. pixel number logger.error( "'Positions' data is not available. Interpolation is disabled." ) selected_data, selected_names, rgb_color_to_keys, quant_norm_applied = self.preprocess_data( ) selected_data = np.asarray(selected_data) # Hide unused axes if rgb_color_to_keys["red"] is None: self.ax_r.set_visible(False) if rgb_color_to_keys["green"] is None: self.ax_g.set_visible(False) if rgb_color_to_keys["blue"] is None: self.ax_b.set_visible(False) if selected_data.ndim != 3: # There is no data to display. Hide the last axis and exit self.ax.set_visible(False) return def _compute_equal_axes_ranges(x_min, x_max, y_min, y_max): """ Compute ranges for x- and y- axes of the plot. Make sure that the ranges for x- and y-axes are always equal and fit the maximum of the ranges for x and y values: max(abs(x_max-x_min), abs(y_max-y_min)) The ranges are set so that the data is always centered in the middle of the ranges Parameters ---------- x_min, x_max, y_min, y_max : float lower and upper boundaries of the x and y values Returns ------- x_axis_min, x_axis_max, y_axis_min, y_axis_max : float lower and upper boundaries of the x- and y-axes ranges """ x_axis_min, x_axis_max, y_axis_min, y_axis_max = x_min, x_max, y_min, y_max x_range, y_range = abs(x_max - x_min), abs(y_max - y_min) if x_range > y_range: y_center = (y_max + y_min) / 2 y_axis_max = y_center + x_range / 2 y_axis_min = y_center - x_range / 2 else: x_center = (x_max + x_min) / 2 x_axis_max = x_center + y_range / 2 x_axis_min = x_center - y_range / 2 return x_axis_min, x_axis_max, y_axis_min, y_axis_max def _adjust_data_range_using_min_ratio(c_min, c_max, c_axis_range, *, min_ratio=0.01): """ Adjust the range for plotted data along one axis (x or y). The adjusted range is applied to the 'extent' attribute of imshow(). The adjusted range is always greater than 'axis_range * min_ratio'. Such transformation has no physical meaning and performed for aesthetic reasons: stretching the image presentation of a scan with only a few lines (1-3) greatly improves visibility of data. Parameters ---------- c_min, c_max : float boundaries of the data range (along x or y axis) c_axis_range : float range presented along the same axis Returns ------- cmin, c_max : float adjusted boundaries of the data range """ c_range = c_max - c_min if c_range < c_axis_range * min_ratio: c_center = (c_max + c_min) / 2 c_new_range = c_axis_range * min_ratio c_min = c_center - c_new_range / 2 c_max = c_center + c_new_range / 2 return c_min, c_max if pixel_or_pos_local: # xd_min, xd_max, yd_min, yd_max = min(self.x_pos), max(self.x_pos), # min(self.y_pos), max(self.y_pos) x_pos_2D = self.io_model.img_dict["positions"]["x_pos"] y_pos_2D = self.io_model.img_dict["positions"]["y_pos"] xd_min, xd_max, yd_min, yd_max = x_pos_2D.min(), x_pos_2D.max( ), y_pos_2D.min(), y_pos_2D.max() xd_axis_min, xd_axis_max, yd_axis_min, yd_axis_max = _compute_equal_axes_ranges( xd_min, xd_max, yd_min, yd_max) xd_min, xd_max = _adjust_data_range_using_min_ratio( xd_min, xd_max, xd_axis_max - xd_axis_min) yd_min, yd_max = _adjust_data_range_using_min_ratio( yd_min, yd_max, yd_axis_max - yd_axis_min) # Adjust the direction of each axis depending on the direction in which encoder values changed # during the experiment. Data is plotted starting from the upper-right corner of the plot if x_pos_2D[0, 0] > x_pos_2D[0, -1]: xd_min, xd_max, xd_axis_min, xd_axis_max = xd_max, xd_min, xd_axis_max, xd_axis_min if y_pos_2D[0, 0] > y_pos_2D[-1, 0]: yd_min, yd_max, yd_axis_min, yd_axis_max = yd_max, yd_min, yd_axis_max, yd_axis_min else: if selected_data.ndim == 3: # Set equal ranges for the axes data yd, xd = selected_data.shape[1], selected_data.shape[2] xd_min, xd_max, yd_min, yd_max = 0, xd, 0, yd # Select minimum range for data if (yd <= math.floor(xd / 100)) and (xd >= 200): yd_min, yd_max = -math.floor(xd / 200), math.ceil(xd / 200) if (xd <= math.floor(yd / 100)) and (yd >= 200): xd_min, xd_max = -math.floor(yd / 200), math.ceil(yd / 200) xd_axis_min, xd_axis_max, yd_axis_min, yd_axis_max = _compute_equal_axes_ranges( xd_min, xd_max, yd_min, yd_max) name_r, data_r, limits_r = "", None, {"low": 0, "high": 100.0} name_g, data_g, limits_g = "", None, {"low": 0, "high": 100.0} name_b, data_b, limits_b = "", None, {"low": 0, "high": 100.0} for color, name in rgb_color_to_keys.items(): if name: try: ind = selected_names.index(name) name_label = name if quant_norm_applied[ind]: name_label += " - Q" # Add suffix to name if quantitative normalization was applied if color == "red": name_r, data_r = name_label, selected_data[ind] limits_r = self.limit_dict[name] elif color == "green": name_g, data_g = name_label, selected_data[ind] limits_g = self.limit_dict[name] elif color == "blue": name_b, data_b = name_label, selected_data[ind] limits_b = self.limit_dict[name] except ValueError: pass def _norm_data(data): """ Normalize data between (0, 1). Parameters ---------- data : 2D array """ if data is None: return data data_min = np.min(data) c_norm = np.max(data) - data_min return (data - data_min) / c_norm if (c_norm != 0) else (data - data_min) def _stretch_range(data_in, v_low, v_high): # 'data is already normalized, so that the values are in the range 0..1 # v_low, v_high are in the range 0..100 if data_in is None: return data_in if (v_low <= 0) and (v_high >= 100): return data_in if v_high - v_low < 1: # This should not happen in practice, but check just in case v_high = v_low + 1 v_low, v_high = v_low / 100.0, v_high / 100.0 c = 1.0 / (v_high - v_low) data_out = (data_in - v_low) * c return np.clip(data_out, 0, 1.0) # Interpolate non-uniformly spaced data to uniform grid if grid_interpolate_local: data_r, _, _ = grid_interpolate( data_r, self.io_model.img_dict["positions"]["x_pos"], self.io_model.img_dict["positions"]["y_pos"]) data_g, _, _ = grid_interpolate( data_g, self.io_model.img_dict["positions"]["x_pos"], self.io_model.img_dict["positions"]["y_pos"]) data_b, _, _ = grid_interpolate( data_b, self.io_model.img_dict["positions"]["x_pos"], self.io_model.img_dict["positions"]["y_pos"]) # The dictionaries 'rgb_view_data' and 'pos_limits' are used for monitoring # the map values at current cursor positions. rgb_view_data = {_: None for _ in self.rgb_keys} if data_r is not None: rgb_view_data["red"] = data_r if data_g is not None: rgb_view_data["green"] = data_g if data_b is not None: rgb_view_data["blue"] = data_b pos_limits = { "x_low": xd_min, "x_high": xd_max, "y_low": yd_min, "y_high": yd_max } # Normalize data data_r_norm = _norm_data(data_r) data_g_norm = _norm_data(data_g) data_b_norm = _norm_data(data_b) data_r_norm = _stretch_range(data_r_norm, limits_r["low"], limits_r["high"]) data_g_norm = _stretch_range(data_g_norm, limits_g["low"], limits_g["high"]) data_b_norm = _stretch_range(data_b_norm, limits_b["low"], limits_b["high"]) R, G, B, RGB = make_cube(data_r_norm, data_g_norm, data_b_norm) red_patch = mpatches.Patch(color="red", label=name_r) green_patch = mpatches.Patch(color="green", label=name_g) blue_patch = mpatches.Patch(color="blue", label=name_b) def format_coord_func(x, y, *, pixel_or_pos, rgb_color_to_keys, rgb_view_data, pos_limits, colors=None): x0, y0 = pos_limits["x_low"], pos_limits["y_low"] if colors is None: colors = list(rgb_color_to_keys.keys()) s = "" for n, color in enumerate(self.rgb_keys): if (color not in colors) or (rgb_color_to_keys[color] is None ) or (rgb_view_data[color] is None): continue map = rgb_view_data[color] ny, nx = map.shape dy = (pos_limits["y_high"] - y0) / ny if ny else 0 dx = (pos_limits["x_high"] - x0) / nx if nx else 0 cy = 1 / dy if dy else 1 cx = 1 / dx if dx else 1 x_pixel = math.floor((x - x0) * cx) y_pixel = math.floor((y - y0) * cy) if (0 <= x_pixel < nx) and (0 <= y_pixel < ny): # The following line is extremely useful for debugging the feature. Keep it. # s += f" <b>{rgb_color_to_keys[color]}</b>: {x_pixel} {y_pixel}" s += f" <b>{rgb_color_to_keys[color]}</b>: {map[y_pixel, x_pixel]:.5g}" s = " - " + s if s else s # Add dash if something is to be printed if pixel_or_pos: # Spatial coordinates (double) s_coord = f"({x:.5g}, {y:.5g})" else: # Pixel coordinates (int) s_coord = f"({int(x)}, {int(y)})" return s_coord + s format_coord = partial( format_coord_func, pixel_or_pos=pixel_or_pos_local, rgb_color_to_keys=rgb_color_to_keys, rgb_view_data=rgb_view_data, pos_limits=pos_limits, ) def format_cursor_data(data): return "" # Print nothing kwargs = dict(origin="upper", interpolation="nearest", extent=(xd_min, xd_max, yd_max, yd_min)) if RGB is not None: img = self.ax.imshow(RGB, **kwargs) self.ax.format_coord = format_coord img.format_cursor_data = format_cursor_data self.ax.set_xlim(xd_axis_min, xd_axis_max) self.ax.set_ylim(yd_axis_max, yd_axis_min) if R is not None: img = self.ax_r.imshow(R, **kwargs) self.ax_r.set_xlim(xd_axis_min, xd_axis_max) self.ax_r.set_ylim(yd_axis_max, yd_axis_min) format_coord_r = partial(format_coord, colors=["red"]) self.ax_r.format_coord = format_coord_r img.format_cursor_data = format_cursor_data if G is not None: img = self.ax_g.imshow(G, **kwargs) self.ax_g.set_xlim(xd_axis_min, xd_axis_max) self.ax_g.set_ylim(yd_axis_max, yd_axis_min) format_coord_g = partial(format_coord, colors=["green"]) self.ax_g.format_coord = format_coord_g img.format_cursor_data = format_cursor_data if B is not None: img = self.ax_b.imshow(B, **kwargs) self.ax_b.set_xlim(xd_axis_min, xd_axis_max) self.ax_b.set_ylim(yd_axis_max, yd_axis_min) format_coord_b = partial(format_coord, colors=["blue"]) self.ax_b.format_coord = format_coord_b img.format_cursor_data = format_cursor_data self.ax.xaxis.set_major_locator(mticker.MaxNLocator(nbins="auto")) self.ax.yaxis.set_major_locator(mticker.MaxNLocator(nbins="auto")) plt.setp(self.ax_r.get_xticklabels(), visible=False) plt.setp(self.ax_r.get_yticklabels(), visible=False) plt.setp(self.ax_g.get_xticklabels(), visible=False) plt.setp(self.ax_g.get_yticklabels(), visible=False) plt.setp(self.ax_b.get_xticklabels(), visible=False) plt.setp(self.ax_b.get_yticklabels(), visible=False) # self.ax_r.set_xticklabels([]) # self.ax_r.set_yticklabels([]) # sb_x = 38 # sb_y = 46 # sb_length = 10 # sb_height = 1 # ax.add_patch(mpatches.Rectangle(( sb_x, sb_y), sb_length, sb_height, color='white')) # ax.text(sb_x + sb_length /2, sb_y - 1*sb_height, '100 nm', color='w', ha='center', # va='bottom', backgroundcolor='black', fontsize=18) self.ax_r.legend( loc="upper left", bbox_to_anchor=(1.1, 0), frameon=False, handles=[red_patch, green_patch, blue_patch], mode="expand", ) # self.fig.tight_layout(pad=4.0, w_pad=0.8, h_pad=0.8) # self.fig.tight_layout() # self.fig.canvas.draw_idle() # self.fig.suptitle(self.img_title, fontsize=20) self.fig.canvas.draw_idle()
def plot2d_rgbgrid(self, axlim=25, interp_method='lanczos', pix_grid=None, fig=None, ax=None): """Create a 2D color plot of the PSF and R,G,B components. Parameters ---------- axlim : `float` limits of axis, symmetric. xlim=(-axlim,axlim), ylim=(-axlim, axlim) interp_method : `str` method used to interpolate the image between samples of the PSF pix_grid : float if not None, overlays gridlines with spacing equal to pix_grid. Intended to show the collection into camera pixels while still in the oversampled domain fig : `matplotlib.figure.Figure`, optional Figure containing the plot ax : `matplotlib.axes.Axis`, optional: Axis containing the plot fig : `matplotlib.figure.Figure`, optional Figure containing the plot ax : `matplotlib.axes.Axis`, optional: Axis containing the plot Notes ----- Need to refine internal workings at some point. """ # make the arrays for the RGB images dat = m.empty((self.samples_y, self.samples_x, 3)) datr = m.zeros((self.samples_y, self.samples_x, 3)) datg = m.zeros((self.samples_y, self.samples_x, 3)) datb = m.zeros((self.samples_y, self.samples_x, 3)) dat[:, :, 0] = self.R dat[:, :, 1] = self.G dat[:, :, 2] = self.B datr[:, :, 0] = self.R datg[:, :, 1] = self.G datb[:, :, 2] = self.B left, right = self.unit[0], self.unit[-1] ax_width = 2 * axlim # generate a figure and axes to plot in fig, ax = share_fig_ax(fig, ax) axr, axg, axb = make_rgb_axes(ax) ax.imshow(dat, extent=[left, right, left, right], interpolation=interp_method, origin='lower') axr.imshow(datr, extent=[left, right, left, right], interpolation=interp_method, origin='lower') axg.imshow(datg, extent=[left, right, left, right], interpolation=interp_method, origin='lower') axb.imshow(datb, extent=[left, right, left, right], interpolation=interp_method, origin='lower') for axs in (ax, axr, axg, axb): ax.set(xlim=(-axlim, axlim), ylim=(-axlim, axlim)) if pix_grid is not None: # if pixel grid is desired, add it mult = m.m.floor(axlim / pix_grid) gmin, gmax = -mult * pix_grid, mult * pix_grid pts = m.arange(gmin, gmax, pix_grid) ax.set_yticks(pts, minor=True) ax.set_xticks(pts, minor=True) ax.yaxis.grid(True, which='minor') ax.xaxis.grid(True, which='minor') ax.set(xlabel=r'Image Plane X [$\mu m$]', ylabel=r'Image Plane Y [$\mu m$]') axr.text(-axlim + 0.1 * ax_width, axlim - 0.2 * ax_width, 'R', color='white') axg.text(-axlim + 0.1 * ax_width, axlim - 0.2 * ax_width, 'G', color='white') axb.text(-axlim + 0.1 * ax_width, axlim - 0.2 * ax_width, 'B', color='white') return fig, ax
def plot2d_rgbgrid(self, axlim=25, interp_method='lanczos', pix_grid=None, fig=None, ax=None): '''Creates a 2D color plot of the PSF and components Args: axlim (`float`): limits of axis, symmetric. xlim=(-axlim,axlim), ylim=(-axlim, axlim). interp_method (string): method used to interpolate the image between samples of the PSF. pix_grid (float): if not None, overlays gridlines with spacing equal to pix_grid. Intended to show the collection into camera pixels while still in the oversampled domain. fig (pyplot.figure): figure to plot in. ax (pyplot.axis): axis to plot in. Returns: pyplot.fig, pyplot.axis. Figure and axis containing the plot. Notes: Need to refine internal workings at some point. ''' # make the arrays for the RGB images dat = np.empty((self.samples_y, self.samples_x, 3)) datr = np.zeros((self.samples_y, self.samples_x, 3)) datg = np.zeros((self.samples_y, self.samples_x, 3)) datb = np.zeros((self.samples_y, self.samples_x, 3)) dat[:, :, 0] = self.R dat[:, :, 1] = self.G dat[:, :, 2] = self.B datr[:, :, 0] = self.R datg[:, :, 1] = self.G datb[:, :, 2] = self.B left, right = self.unit[0], self.unit[-1] ax_width = 2 * axlim # generate a figure and axes to plot in fig, ax = share_fig_ax(fig, ax) axr, axg, axb = make_rgb_axes(ax) ax.imshow(correct_gamma(dat), extent=[left, right, left, right], interpolation=interp_method, origin='lower') axr.imshow(correct_gamma(datr), extent=[left, right, left, right], interpolation=interp_method, origin='lower') axg.imshow(correct_gamma(datg), extent=[left, right, left, right], interpolation=interp_method, origin='lower') axb.imshow(correct_gamma(datb), extent=[left, right, left, right], interpolation=interp_method, origin='lower') for axs in (ax, axr, axg, axb): ax.set(xlim=(-axlim, axlim), ylim=(-axlim, axlim)) if pix_grid is not None: # if pixel grid is desired, add it mult = np.floor(axlim / pix_grid) gmin, gmax = -mult * pix_grid, mult * pix_grid pts = np.arange(gmin, gmax, pix_grid) ax.set_yticks(pts, minor=True) ax.set_xticks(pts, minor=True) ax.yaxis.grid(True, which='minor') ax.xaxis.grid(True, which='minor') ax.set(xlabel=r'Image Plane X [$\mu m$]', ylabel=r'Image Plane Y [$\mu m$]') axr.text(-axlim + 0.1 * ax_width, axlim - 0.2 * ax_width, 'R', color='white') axg.text(-axlim + 0.1 * ax_width, axlim - 0.2 * ax_width, 'G', color='white') axb.text(-axlim + 0.1 * ax_width, axlim - 0.2 * ax_width, 'B', color='white') return fig, ax