Source code for fibsem.display

import numpy as np
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt

import fibsem.conversions


def _matplotlib_center_to_bottomleft(center_x, center_y, roi_width, roi_height):
    """ Convert ROI center coordinates to matplotlib bottom left coordinates.

    Parameters
    ----------
    center_x : float
        Position in x of Autoscript ROI center coordinate.
    center_y : float
        Position in y of Autoscript ROI center coordinate.
    roi_width : float
        Width in meters of Autoscript milling ROI.
    roi_height : float
        Height in meters of Autoscript milling ROI.

    Returns
    -------
    xy
        Matplotlib bottom left coordinate is in x, y format.
    """
    left = center_x - (roi_width / 2)
    bottom = center_y - (roi_height / 2)
    xy = (left, bottom)
    return xy


def _matplotlib_line_width(image):
    """Return appropriate line width for the image dimensions.

    Parameters
    ----------
    image : AdornedImage or numpy array
        Input image.

    Returns
    -------
    line_width
        Line width for use as keyword argument in matplotlib display.
    """
    image_shape = fibsem.conversions.convert_to_numpy(image).shape
    line_width = np.max(image_shape) / 20
    try:
        pixelsize = image.metadata.binary_result.pixel_size
    except AttributeError:
        pass
    else:
        line_width = line_width * pixelsize.x
    return line_width


def _matplotlib_rotation_transform(ax, center_x, center_y, theta):
    """[summary]

    Parameters
    ----------
    ax : [type]
        [description]
    center_x : [type]
        [description]
    center_y : [type]
        [description]
    theta : [type]
        [description]

    Returns
    -------
    [type]
        [description]
    """
    angle = fibsem.conversions._angle_to_matplotlib(theta)
    ts = ax.transData
    tr = matplotlib.transforms.Affine2D().rotate_deg_around(center_x,
                                                            center_y,
                                                            angle)
    t = tr + ts
    return t


[docs]def quick_plot(image): """Display image with matplotlib.pyplot Parameters ---------- image : Adorned image or numpy array Input image. Returns ------- fig, ax Matplotlib figure and axis objects. """ fig, ax = plt.subplots(1) display_image = fibsem.conversions.convert_to_numpy(image) height, width = display_image.shape try: pixelsize_x = image.metadata.binary_result.pixel_size.x pixelsize_y = image.metadata.binary_result.pixel_size.y except AttributeError: extent_kwargs = [-(width / 2), +(width / 2), -(height / 2), +(height / 2)] ax.set_xlabel('Distance from origin (pixels)') else: extent_kwargs = [-(width / 2) * pixelsize_x, +(width / 2) * pixelsize_x, -(height / 2) * pixelsize_y, +(height / 2) * pixelsize_y] ax.set_xlabel('Distance from origin (meters) \n' '1 pixel = {} meters'.format(pixelsize_x)) ax.set_xlim(extent_kwargs[0], extent_kwargs[1]) ax.set_ylim(extent_kwargs[2], extent_kwargs[3]) ax.imshow(display_image, cmap='gray', extent=extent_kwargs) return fig, ax
[docs]def draw_object_axes(image, axis_coord_list, line_color='red'): """Display plot of image with major axis overlaid. Parameters ---------- image : 2D umpy image array. axis_coords : major axis of sample segmentation. Coordinates are in row, column format. line_color : optional. Color of matplotlib line patch. Returns ------- fig, ax Matplotlib figure and axis objects. """ fig, ax = quick_plot(image) colors = cm.gist_rainbow(np.linspace(0, 1, len(axis_coord_list))) for axis_coords, color in zip(axis_coord_list, colors): (y, x), (y1, x1) = axis_coords dx = x1 - x dy = y1 - y line_width = _matplotlib_line_width(image) arrow = matplotlib.patches.Arrow(x, y, dx, dy, line_width, color=color) ax.add_patch(arrow) return fig, ax
[docs]def draw_milling_axes(image, major_axis, start_lamella, end_lamella, line_colors=['yellow', 'orange']): """Display plot of image with head to tail & tail to head axis overlaid. Parameters ---------- image : 2D umpy image array. [description] major_axis : major axis of sample segmentation. Coordinates are in row, column format. start_lamella : [type] [description] end_lamella : [type] [description] line_colors : list, optional [description] (the default is ['yellow', 'orange'], which [default_description]) Returns ------- fig, ax Matplotlib figure and axis objects. """ fig, ax = quick_plot(image) results = fibsem.milling._milling_directions( major_axis, start_lamella, end_lamella) for axis_coords, line_color in zip(results, line_colors): (y, x), (y1, x1) = axis_coords dx = x1 - x dy = y1 - y line_width = _matplotlib_line_width(image) arrow = matplotlib.patches.Arrow(x, y, dx, dy, line_width, color=line_color) ax.add_patch(arrow) return fig, ax
[docs]def draw_crosshairs(image, major_axis, minor_axis, line_color=['red', 'blue']): """Display plot of image with major axis overlaid. Parameters ---------- image : 2D umpy image array. major_axis : major axis of sample segmentation. Coordinates are in row, column format. minor_axis : minor axis of sample segmentation. Coordinates are in row, column format. line_color : optional. List of colors for each axis (major and minor). Returns ------- fig, ax Matplotlib figure and axis objects. """ fig, ax = quick_plot(image) line_width = _matplotlib_line_width(image) for i, axis in enumerate([major_axis, minor_axis]): (y, x), (y1, x1) = axis dx = x1 - x dy = y1 - y arrow = matplotlib.patches.Arrow(x, y, dx, dy, line_width, color=line_color[i]) ax.add_patch(arrow) return fig, ax
[docs]def draw_rotated_rects(rectangle_coords, image=None, show_center=True): """Display rectangle ROIs using matplotlib. Parameters ---------- rectangle_coords : list. List contains [center_x, center_y, width, height, depth, angle] The input angle is in radians. `center_x`, `center_y`, `width`, and `height` are in meters. `depth` is ignored (not needed by matplotlib). image : AdornedImage, optional. Image to display, including pixel size metadata. (the default is None, which means no background image) show_center : bool, optional Plot centerpoints of rectangles (the default is False, which means centerpoints are not displayed) Returns ------- fig, ax Matplotlib figure and axis objects. """ if image is not None: fig, ax = quick_plot(image) else: fig, ax = plt.subplots(1) colors = cm.gist_rainbow(np.linspace(0, 1, len(rectangle_coords))) for coords, color in zip(rectangle_coords, colors): center_x, center_y, roi_width, roi_height, depth, theta = coords xy = _matplotlib_center_to_bottomleft(center_x, center_y, roi_width, roi_height) transformation = _matplotlib_rotation_transform(ax, center_x, center_y, theta) rect = matplotlib.patches.Rectangle(xy, roi_width, roi_height, transform=transformation, fill=False, color=color) ax.add_patch(rect) if show_center is True: ax.plot(center_x, center_y, marker='o', markersize=3, color=color) return fig, ax