Source code for magni.imaging.measurements._uniform_line
"""
..
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
----------------
uniform_line_sample_image(h, w, scan_length, num_points)
Function for uniform line sampling an image.
uniform_line_sample_surface(l, w, speed, sample_rate, time)
Function for uniform line sampling a surface.
"""
from __future__ import division
import numpy as np
from magni.imaging.measurements import _util
from magni.utils.validation import decorate_validation as _decorate_validation
from magni.utils.validation import validate_numeric as _numeric
__all__ = ['uniform_line_sample_image', 'uniform_line_sample_surface']
_min_l = _util.min_l
_min_w = _util.min_w
_min_speed = _util.min_speed
_min_sample_rate = _util.min_sample_rate
_min_time = _util.min_time
_min_scan_length = _util.min_scan_length
_min_num_points = _util.min_num_points
[docs]def uniform_line_sample_image(h, w, scan_length, num_points):
"""
Sample an image using a set of uniformly distributed straight lines.
The coordinates (in units of pixels) resulting from sampling an image of
size `h` times `w` using a pattern based on a set of uniformly distributed
straight lines are determined. The `scan_length` determines the length of
the path scanned whereas `num_points` indicates the number of samples taken
on that path.
Parameters
----------
h : int
The height of the area to scan in units of pixels.
w : int
The width of the area to scan in units of pixels.
scan_length : float
The length of the path to scan in units of pixels.
num_points : int
The number of samples to take on the scanned path.
Returns
-------
coords : ndarray
The coordinates of the samples arranged into a 2D array, such that each
row is a coordinate pair (x, y).
Notes
-----
The orientation of the coordinate system is such that the width `w` is
measured along the x-axis whereas the height `h` is measured along the
y-axis.
Each of the scanned lines span the entire width of the image with the
exception of the last line that may only be partially scanned if the
`scan_length` implies this. The top and bottom lines of the image are
always included in the scan.
Examples
--------
For example,
>>> import numpy as np
>>> from magni.imaging.measurements import uniform_line_sample_image
>>> h = 10
>>> w = 10
>>> scan_length = 50.0
>>> num_points = 12
>>> np.set_printoptions(suppress=True)
>>> uniform_line_sample_image(h, w, scan_length, num_points)
array([[ 0.5 , 0.5 ],
[ 4.59090909, 0.5 ],
[ 8.68181818, 0.5 ],
[ 9.22727273, 3.5 ],
[ 5.13636364, 3.5 ],
[ 1.04545455, 3.5 ],
[ 1.04545455, 6.5 ],
[ 5.13636364, 6.5 ],
[ 9.22727273, 6.5 ],
[ 8.68181818, 9.5 ],
[ 4.59090909, 9.5 ],
[ 0.5 , 9.5 ]])
"""
@_decorate_validation
def validate_input():
_numeric('h', 'integer', range_='[2;inf)')
_numeric('w', 'integer', range_='[2;inf)')
_numeric('scan_length', 'floating',
range_='[{};inf)'.format(_min_scan_length))
_numeric('num_points', 'integer',
range_='[{};inf)'.format(_min_num_points))
validate_input()
coords = uniform_line_sample_surface(float(h - 1), float(w - 1),
scan_length, float(num_points - 1),
1.0)
coords = coords + 0.5
return coords
[docs]def uniform_line_sample_surface(l, w, speed, sample_rate, time):
"""
Sample aa surface area using a set of uniformly distributed straight lines.
The coordinates (in units of meters) resulting from sampling an area of
size `l` times `w` using a pattern based on a set of uniformly distributed
straight lines are determined. The scanned path is determined from the
probe `speed` and the scan `time`.
Parameters
----------
l : float
The length of the area to scan in units of meters.
w : float
The width of the area to scan in units of meters.
speed : float
The probe speed in units of meters/second.
sample_rate : float
The sample rate in units of Hertz.
time : float
The scan time in units of seconds.
Returns
-------
coords : ndarray
The coordinates of the samples arranged into a 2D array, such that each
row is a coordinate pair (x, y).
Notes
-----
The orientation of the coordinate system is such that the width `w` is
measured along the x-axis whereas the height `l` is measured along the
y-axis.
Each of the scanned lines span the entire width of the image with the
exception of the last line that may only be partially scanned if the
`scan_length` implies this. The top and bottom lines of the image are
always included in the scan.
Examples
--------
For example,
>>> import numpy as np
>>> from magni.imaging.measurements import uniform_line_sample_surface
>>> l = 2e-6
>>> w = 2e-6
>>> speed = 7e-7
>>> sample_rate = 1.0
>>> time = 12.0
>>> np.set_printoptions(suppress=True)
>>> uniform_line_sample_surface(l, w, speed, sample_rate, time)
array([[ 0. , 0. ],
[ 0.00000067, 0. ],
[ 0.00000133, 0. ],
[ 0.000002 , 0. ],
[ 0.000002 , 0.00000067],
[ 0.00000167, 0.000001 ],
[ 0.000001 , 0.000001 ],
[ 0.00000033, 0.000001 ],
[ 0. , 0.00000133],
[ 0. , 0.000002 ],
[ 0.00000067, 0.000002 ],
[ 0.00000133, 0.000002 ],
[ 0.000002 , 0.000002 ]])
"""
@_decorate_validation
def validate_input():
_numeric('l', 'floating', range_='[{};inf)'.format(_min_l))
_numeric('w', 'floating', range_='[{};inf)'.format(_min_w))
_numeric('speed', 'floating', range_='[{};inf)'.format(_min_speed))
_numeric('sample_rate', 'floating',
range_='[{};inf)'.format(_min_sample_rate))
_numeric('time', 'floating', range_='[{};inf)'.format(_min_time))
validate_input()
num_lines = int(np.floor((speed * time - l) / w))
# We should always at least partially scan top and bottom lines.
if num_lines < 2:
num_lines = 2
coords = np.zeros((2 * num_lines, 2))
coords[1::4, 0] = coords[2::4, 0] = w
coords[0::2, 1] = coords[1::2, 1] = np.linspace(0, l, num_lines)
return _util.sample_lines(coords, speed, sample_rate, time)