Created
February 17, 2012 00:47
-
-
Save Irfy/1849284 to your computer and use it in GitHub Desktop.
Implement a cutoff window and a circular window on top of numpy's matrix.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Demonstrates creating windows or views of two-dimensional arrays, in two ways: | |
* Cutting off parts of window that is outside | |
* Continuing windows on the opposite side (circular sliding) | |
'numpy' is a very useful numerical library for python which *already* supports | |
creating windows/views (actually sub-arrays, for multidimensional arrays). This | |
code demonstrates how to "wrap" such an underlying implementation to provide | |
specialized functionality. | |
The provided functions could have been implemented within classes that wrap | |
numpy arrays, providing true adapter feel, but that would have been too much for | |
someone who doesn't know Python. Everybody understands functions though. | |
""" | |
from numpy import array, empty | |
def normalize(dim, dim_max, dim_min=0): | |
""" | |
Make sure dim_min <= dim <= dim_max, return the best match. | |
""" | |
if dim < dim_min: | |
return dim_min | |
if dim > dim_max: | |
return dim_max | |
return dim | |
def window_cutoff(matrix, x_start, x_end, y_start, y_end): | |
""" | |
Return a view of the underlying 2D array, cutting off any part of the | |
window that falls outside. As with all sane indexing, start is inclusive, | |
end is exclusive. | |
""" | |
# _max assume 'F' option | |
x_max = len(matrix) | |
y_max = len(matrix[0]) | |
# fix up to fit within matrix | |
x_start = normalize(x_start, x_max) | |
y_start = normalize(y_start, y_max) | |
# determine ends, fit within matrix | |
x_end = normalize(x_end, x_max) | |
y_end = normalize(y_end, y_max) | |
# coordinates have been fixed, use underlying implementation | |
return matrix[x_start:x_end, y_start:y_end] | |
def window_circular(matrix, x_start, x_end, y_start, y_end): | |
""" | |
Return a view of the underlying 2D array, repeating, in a circular fashion | |
any part of the window that falls outside, as if the window continued in the | |
same direction, from the opposite side. | |
""" | |
x_max = len(matrix) | |
y_max = len(matrix[0]) | |
if (0 <= x_start < x_max and | |
0 <= x_end < x_max and | |
0 <= y_start < y_max and | |
0 <= y_end < y_max): | |
# All coordinates fit within the matrix, use underlying implementation | |
return matrix[x_start:x_end, y_start:y_end] | |
# Need manual intervention, coordinates outside normal range of matrix | |
window = empty((x_end - x_start, y_end - y_start), | |
dtype=matrix.dtype, | |
order='F') | |
for x_i in xrange(x_start, x_end): | |
for y_i in xrange(y_start, y_end): | |
window[x_i - x_start, y_i - y_start] = matrix[x_i % x_max, y_i % y_max] | |
return window | |
m = array([[1, 11, 111], | |
[2, 22, 222], | |
[3, 33, 333], | |
[4, 44, 444]]) | |
def print_commented(comment, window): | |
print comment + ':\n', window, '\n' | |
print_commented("original", m) | |
print_commented("2nd row, 2nd and 3rd columns", window_cutoff(m, 1, 2, 1, 3)) | |
print_commented("first two rows, first column", window_cutoff(m, -2, 2, -5, 1)) | |
print_commented("nothing", window_cutoff(m, -2, -1, -2, 8)) | |
print_commented("everything", window_cutoff(m, -2, 9, -2, 9)) | |
print_commented("2nd row, 2nd and 3rd columns", window_circular(m, 1, 2, 1, 3)) | |
print_commented("last two rows, first two rows; " | |
"last two columns, all columns, first column", | |
window_circular(m, -2, 2, -5, 1)) | |
print_commented("second-to-last row; " | |
"last two columns, all columns, all columns, first two columns", | |
window_circular(m, -2, -1, -2, 8)) | |
print_commented("last two rows, all rows, all rows, first row; " | |
"last two columns, all columns, all columns, all columns", | |
window_circular(m, -2, 9, -2, 9)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output: