def image_to_polar(
    image,
    delta_r=1.0,
    delta_theta=1,
    max_r=None,
    find_direct_beam=False,
    direct_beam_position=None,
):
    """Convert a single image to polar coordinates including the option to
    find the direct beam and take this as the center.

    Parameters
    ----------
    image : 2D numpy.ndarray
        Experimental image
    delta_r : float, optional
        The radial increment, determines how many columns will be in the polar
        image.
    delta_theta : float, optional
        The angular increment, determines how many rows will be in the polar
        image
    max_r : float, optional
        The maximum radial distance to include, in units of pixels. By default
        this is the distance from the center of the image to a corner in pixel
        units and rounded up to the nearest integer
    find_direct_beam : bool
        Whether to roughly find the direct beam using `find_beam_center_blur`
        using a gaussian smoothing with sigma = 1. If False then the middle of
        the image will be the center for the polar transform.
    direct_beam_position : 2-tuple
        (x, y) position of the central beam in pixel units. This overrides
        the automatic find_maximum parameter if set to True.

    Returns
    -------
    polar_image : 2D numpy.ndarray
        Array representing the polar transform of the image with shape
        (360/delta_theta, max_r/delta_r)
    """
    half_x, half_y = image.shape[1] / 2, image.shape[0] / 2
    if direct_beam_position is not None:
        c_x, c_y = direct_beam_position
    elif find_direct_beam:
        c_y, c_x = find_beam_center_blur(image, 1)
    else:
        c_x, c_y = half_x, half_y
    output_shape = get_polar_pattern_shape(image.shape,
                                           delta_r,
                                           delta_theta,
                                           max_r=max_r)
    return warp_polar(
        image,
        center=(c_y, c_x),
        output_shape=output_shape,
        radius=max_r,
        preserve_range=True,
    )
Esempio n. 2
0
def test_find_beam_center_blur(center_expected, sigma):
    z = np.zeros((50, 50))
    z[28:31, 24:27] = 1
    z = gaussian_filter(z, sigma=sigma)
    shifts = find_beam_center_blur(z, 10)
    assert np.allclose(shifts, center_expected, atol=0.2)
Esempio n. 3
0
def plot_template_over_pattern(pattern,
                               simulation,
                               ax=None,
                               in_plane_angle=0.0,
                               max_r=None,
                               find_direct_beam=True,
                               direct_beam_position=None,
                               coordinate_system="cartesian",
                               marker_color="red",
                               marker_type="x",
                               size_factor=1.0,
                               **kwargs):
    """
    A quick utility function to plot a simulated pattern over an experimental image

    Parameters
    ----------
    pattern : 2D np.ndarray
        The diffraction pattern
    simulation : diffsims.sims.diffraction_simulation.DiffractionSimulation
        The simulated diffraction pattern. It must be calibrated.
    axis : matplotlib.AxesSubplot, optional
        An axis object on which to plot. If None is provided, one will be created.
    in_plane_angle : float, optional
        An in-plane rotation angle to apply to the template in degrees
    max_r : float, optional
        Maximum radius to consider in the polar transform in pixel coordinates.
        Will only influence the result if `coordinate_system`="polar".
    find_direct_beam: bool, optional
        Roughly find the optimal direct beam position if it is not centered.
    direct_beam_position: 2-tuple
        The (x, y) position of the direct beam in pixel coordinates. Takes
        precedence over `find_direct_beam`
    coordinate_system : str, optional
        Type of coordinate system to plot the image and template in. Either
        `cartesian` or `polar`
    marker_color : str, optional
        Color of the spot markers
    marker_type : str, optional
        Type of marker used for the spots
    size_factor : float, optional
        Scaling factor for the spots. See notes on size.
    **kwargs : See imshow

    Returns
    -------
    ax : matplotlib.AxesSubplot
        The axes object
    im : matplotlib.image.AxesImage
        The representation of the image on the axes
    sp : matplotlib.collections.PathCollection
        The scatter plot representing the diffraction pattern

    Notes
    -----
    The spot marker sizes are scaled by the square root of their intensity
    """
    if ax is None:
        _, ax = plt.subplots()
    if direct_beam_position is not None:
        c_x, c_y = direct_beam_position
    elif find_direct_beam:
        c_y, c_x = find_beam_center_blur(pattern, 1)
    else:
        c_y, c_x = pattern.shape[0] // 2, pattern.shape[1] // 2
    if coordinate_system == "polar":
        pattern = image_to_polar(
            pattern,
            max_r=max_r,
            find_direct_beam=find_direct_beam,
            direct_beam_position=direct_beam_position,
        )
        x, y, intensities = get_template_polar_coordinates(
            simulation, in_plane_angle=in_plane_angle, max_r=max_r)
    elif coordinate_system == "cartesian":
        x, y, intensities = get_template_cartesian_coordinates(
            simulation,
            center=(c_x, c_y),
            in_plane_angle=in_plane_angle,
            window_size=pattern.shape[::-1],
        )
    else:
        raise NotImplementedError(
            "Only polar and cartesian are accepted coordinate systems")
    im = ax.imshow(pattern, **kwargs)
    sp = ax.scatter(
        x,
        y,
        s=size_factor * np.sqrt(intensities),
        marker=marker_type,
        color=marker_color,
    )
    return (ax, im, sp)