Exemplo n.º 1
0
 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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
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")
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
    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()
Exemplo n.º 11
0
    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']
Exemplo n.º 12
0
 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
Exemplo n.º 13
0
    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()
Exemplo n.º 14
0
    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
Exemplo n.º 15
0
    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