Source code for magni.imaging.measurements._matrices

"""
..
    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
----------------
construct_measurement_matrix(coords, h, w)
    Function for constructing a measurement matrix.

"""

from __future__ import division

import numpy as np

from magni.imaging.measurements._util import unique_pixels as _unique_pixels
from magni.utils.matrices import Matrix as _Matrix
from magni.utils.validation import decorate_validation as _decorate_validation
from magni.utils.validation import validate_numeric as _numeric


__all__ = ['construct_measurement_matrix']


[docs]def construct_measurement_matrix(coords, h, w): """ Construct a measurement matrix extracting the specified measurements. Parameters ---------- coords : ndarray The `k` floating point coordinates arranged into a 2D array where each row is a coordinate pair (x, y), such that `coords` has size `k` x 2. h : int The height of the image measured in pixels. w : int The width of the image measured in pixels. Returns ------- Phi : magni.utils.matrices.Matrix The constructed measurement matrix. See Also -------- magni.utils.matrices.Matrix : The matrix emulator class. Notes ----- The function constructs two functions: one for extracting pixels at the coordinates specified and one for the transposed operation. These functions are then wrapped by a matrix emulator which is returned. Examples -------- Create a dummy 5 by 5 pixel image and an example sampling pattern: >>> import numpy as np, magni >>> img = np.arange(25, dtype=np.float).reshape(5, 5) >>> vec = magni.imaging.mat2vec(img) >>> coords = magni.imaging.measurements.uniform_line_sample_image( ... 5, 5, 16., 17) Sample the image in the ordinary way: >>> unique = magni.imaging.measurements.unique_pixels(coords) >>> samples_normal = img[unique[:, 1], unique[:, 0]] >>> samples_normal = samples_normal.reshape((len(unique), 1)) Sample the image using the present function: >>> from magni.imaging.measurements import construct_measurement_matrix >>> matrix = construct_measurement_matrix(coords, *img.shape) >>> samples_matrix = matrix.dot(vec) Check that the two ways produce the same result: >>> np.allclose(samples_matrix, samples_normal) True """ @_decorate_validation def validate_input(): _numeric('coords', ('integer', 'floating'), shape=(-1, 2)) _numeric('h', 'integer', range_='[1;inf)') _numeric('w', 'integer', range_='[1;inf)') _numeric('coords[:, 0]', ('integer', 'floating'), range_='[0;{}]'.format(w), shape=(-1,), var=coords[:, 0]) _numeric('coords[:, 1]', ('integer', 'floating'), range_='[0;{}]'.format(h), shape=(-1,), var=coords[:, 1]) validate_input() coords = _unique_pixels(coords) mask = coords[:, 0] * w + coords[:, 1] def measure(vec): return vec[mask] def measure_T(vec): output = np.zeros((h * w, 1), dtype=vec.dtype) output[mask] = vec return output return _Matrix(measure, measure_T, [], (len(mask), h * w))