Source code for magni.imaging.measurements._visualisation

"""
..
    Copyright (c) 2014-2017, Magni developers.
    All rights reserved.
    See LICENSE.rst for further information.

Module providing public functions for the magni.imaging.measurements
subpackage.

Routine listings
----------------
plot_pattern(l, w, coords, mode, output_path=None)
    Function for visualising a scan pattern.
plot_pixel_mask(h, w, pixels, output_path=None)
    Function for visualising a pixel mask obtained from a scan pattern.

"""

from __future__ import division

import matplotlib.pyplot as plt

from magni.imaging.measurements import _util
from magni.imaging.visualisation import imshow as _imshow
from magni.utils import plotting as _plotting
from magni.utils.validation import decorate_validation as _decorate_validation
from magni.utils.validation import validate_generic as _generic
from magni.utils.validation import validate_numeric as _numeric


__all__ = ['plot_pattern', 'plot_pixel_mask']

_min_l = _util.min_l
_min_w = _util.min_w


[docs]def plot_pattern(l, w, coords, mode, output_path=None): """ Display a plot that shows the pattern given by a set of coordinates. The pattern given by the `coords` is displayed on an `w` x `l` area. If `mode` is 'surface', `l` and `w` are regarded as measured in meters. If `mode` is 'image', `l` and `w` are regarded as measured in pixels. The `coords` are marked by filled circles and connected by straight dashed lines. Parameters ---------- l : float or int The length/height of the area. If `mode` is 'surface', it must be a float. If `mode` is 'image', it must be an integer. w : float or int The width of the area. If `mode` is 'surface', it must be a float. If `mode` is 'image', it must be an integer. coords : ndarray The 2D array of pixels that make up the mask. Each row is a coordinate pair (x, y). mode : {'surface', 'image'} The display mode that dertermines the axis labeling and the type of `l` and `w`. output_path : str, optional Path (including file type extension) under which the plot is saved (the default value is None which implies, that the plot is not saved). Notes ----- The resulting plot is displayed in a figure using `matplotlib`'s `pyplot.plot`. Examples -------- For example, >>> import numpy as np >>> from magni.imaging.measurements import plot_pattern >>> l = 3 >>> w = 3 >>> coords = np.array([[0, 0], [1, 1], [2, 1]]) >>> mode = 'image' >>> plot_pattern(l, w, coords, mode) """ @_decorate_validation def validate_input(): _generic('mode', 'string', value_in=('surface', 'image')) if mode == 'surface': _numeric('l', 'floating', range_='[{};inf)'.format(_min_l)) _numeric('w', 'floating', range_='[{};inf)'.format(_min_w)) _numeric('coords', 'floating', shape=(-1, 2)) _numeric('coords[:, 0]', 'floating', range_='[0;{}]'.format(w), shape=(-1,), var=coords[:, 0]) _numeric('coords[:, 1]', 'floating', range_='[0;{}]'.format(l), shape=(-1,), var=coords[:, 1]) elif mode == 'image': _numeric('l', 'integer', range_='[2;inf)') _numeric('w', 'integer', range_='[2;inf)') _numeric('coords', ('integer', 'floating'), shape=(-1, 2)) _numeric('coords[:, 0]', ('integer', 'floating'), range_='[0;{})'.format(w), shape=(-1,), var=coords[:, 0]) _numeric('coords[:, 1]', ('integer', 'floating'), range_='[0;{})'.format(l), shape=(-1,), var=coords[:, 1]) _generic('output_path', 'string', ignore_none=True) validate_input() figsize = plt.rcParams['figure.figsize'] if w / l > figsize[0] / figsize[1]: figsize_local = [figsize[0], figsize[0] * l / w] else: figsize_local = [figsize[1] * w / l, figsize[1]] _plotting.setup_matplotlib({'figure': {'figsize': figsize_local}}) fig, axes = plt.subplots(1, 1) axes.plot(coords[:, 0], coords[:, 1], marker=_plotting.markers[0], ls=_plotting.linestyles[1], ms=6) axes.set_xlim([0, w]) axes.xaxis.tick_top() axes.invert_yaxis() axes.set_ylim([l, 0]) axes.xaxis.set_label_position('top') axes.set_aspect('equal') if mode == 'surface': axes.set_xlabel('width [m]') axes.set_ylabel('length [m]') axes.ticklabel_format(style='sci', scilimits=(0, 0)) # Fix position of exponential multipliers in scientific notation exp_texts = [axes.xaxis.get_children()[1], axes.yaxis.get_children()[1]] vert_aligns = ['bottom', 'center'] hori_aligns = ['center', 'right'] xy_texts = [(0, 25), (-35, 0)] xys = [(1, 1), (0, 0)] annos = [None, None] for k, text in enumerate(exp_texts): text.set_visible(False) annos[k] = axes.annotate('', xys[k], xytext=xy_texts[k], xycoords='axes fraction', textcoords='offset points', va=vert_aligns[k], ha=hori_aligns[k]) fig.canvas.mpl_connect( 'draw_event', lambda event: annos[0].set_text( exp_texts[0].get_text())) fig.canvas.mpl_connect( 'draw_event', lambda event: annos[1].set_text( exp_texts[1].get_text())) elif mode == 'image': axes.set_xlabel('width [pixels]') axes.set_ylabel('height [pixels]') plt.tight_layout() if output_path is not None: plt.savefig(output_path) _plotting.setup_matplotlib({'figure': {'figsize': figsize}})
[docs]def plot_pixel_mask(h, w, pixels, output_path=None): """ Display a binary image that shows the given pixel mask. A black image with `w` x `h` pixels is created and the `pixels` are marked with white. Parameters ---------- h : int The height of the image in pixels. w : int The width of the image in pixels. pixels : ndarray The 2D array of pixels that make up the mask. Each row is a coordinate pair (x, y), such that `coords` has size len(`pixels`) x 2. output_path : str, optional Path (including file type extension) under which the plot is saved (the default value is None which implies, that the plot is not saved). Notes ----- The resulting image is displayed in a figure using `magni.imaging.visualisation.imshow`. Examples -------- For example, >>> import numpy as np >>> from magni.imaging.measurements import plot_pixel_mask >>> h = 3 >>> w = 3 >>> pixels = np.array([[0, 0], [1, 1], [2, 1]]) >>> plot_pixel_mask(h, w, pixels) """ @_decorate_validation def validate_input(): _numeric('h', 'integer', range_='[2;inf)') _numeric('w', 'integer', range_='[2;inf)') _numeric('pixels', 'integer', shape=(-1, 2)) _numeric('pixels[:, 0]', 'integer', range_='[0;{}]'.format(w - 1), shape=(-1,), var=pixels[:, 0]) _numeric('pixels[:, 1]', 'integer', range_='[0;{}]'.format(h - 1), shape=(-1,), var=pixels[:, 1]) _generic('output_path', 'string', ignore_none=True) validate_input() mask = _util.construct_pixel_mask(h, w, pixels) figsize = plt.rcParams['figure.figsize'] if w / h > figsize[0] / figsize[1]: figsize_local = [figsize[0], figsize[0] * h / w] else: figsize_local = [figsize[1] * w / h, figsize[1]] _plotting.setup_matplotlib({'figure': {'figsize': figsize_local}}) fig, axes = plt.subplots(1, 1) _imshow(mask, ax=axes, show_axis='top') axes.set_xlabel('width [pixels]') axes.set_ylabel('height [pixels]') plt.tight_layout() if output_path is not None: plt.savefig(output_path) _plotting.setup_matplotlib({'figure': {'figsize': figsize}})