Hi, I've just come across Travis Oliphant's array version of the game of life here <https://gist.github.com/3353411>. It's a really nice example of how to efficiently find neighbours using numpy and family. However, I wanted to apply these ideas to higher order arrays (eg GRID being three dimensional rather than two dimensional). My previous attempts at this include the (sorry for the ensuing horror!) neighbours = np.array( [ \ # Lower row... x[:-2, :-2, :-2], x[:-2, :-2, 1:-1], x[:-2, :-2, 2: ], x[:-2, 1:-1,:-2], x[:-2, 1:-1, 1:-1], x[:-2, 1:-1, 2:], x[:-2, 2:,:-2], x[:-2, 2:, 1:-1], x[:-2, 2:, 2:], # Middle row x[1:-1, :-2, :-2], x[1:-1, :-2, 1:-1], x[1:-1, :-2, 2: ], x[1:-1, 1:-1,:-2], x[1:-1, 1:-1, 2:], x[1:-1, 2:,:-2], x[1:-1, 2:, 1:-1], x[1:-1, 2:, 2:], # Top row x[2:, :-2, :-2], x[2:, :-2, 1:-1], x[2:, :-2, 2: ], x[2:, 1:-1,:-2], x[2:, 1:-1, 1:-1], x[2:, 1:-1, 2:], x[2:, 2:,:-2], x[2:, 2:, 1:-1], x[2:, 2:, 2:] ] ) I think this works (it's been a while! ;D), but it's a bit messy and the boundary condition is a bit crude. I was wondering whether there's some other nice way of doing it, like demonstrated in the above link. Also, what if you want to have a larger neighbourhood (say 5x5x2 instead of 3x3x3)? While I appreciate these index tricks, I also find them quite mind boggling! Thanks! Jose
Hello, Just to throw it in, if you do not mind useing scipy, you can use its multidimensional correlate method instead: stamp = np.ones((3,3,3)) stamp[1,1,1] = 0 num_neighbours = scipy.ndimage.correlate(x, stamp, mode='wrap')) In the link np.roll is used to implement periodic boundaries (mode='wrap' when using correlate), if you want constant boundary conditions padding is probably simplest. Maybe someone else has some trick to avoid so much code duplication without using scipy... Regards, Sebastian On Do, 2012-08-16 at 18:46 +0100, Jose Gomez-Dans wrote:
Hi, I've just come across Travis Oliphant's array version of the game of life here <https://gist.github.com/3353411>. It's a really nice example of how to efficiently find neighbours using numpy and family. However, I wanted to apply these ideas to higher order arrays (eg GRID being three dimensional rather than two dimensional). My previous attempts at this include the (sorry for the ensuing horror!) neighbours = np.array( [ \ # Lower row... x[:-2, :-2, :-2], x[:-2, :-2, 1:-1], x[:-2, :-2, 2: ], x[:-2, 1:-1,:-2], x[:-2, 1:-1, 1:-1], x[:-2, 1:-1, 2:], x[:-2, 2:,:-2], x[:-2, 2:, 1:-1], x[:-2, 2:, 2:], # Middle row x[1:-1, :-2, :-2], x[1:-1, :-2, 1:-1], x[1:-1, :-2, 2: ], x[1:-1, 1:-1,:-2], x[1:-1, 1:-1, 2:], x[1:-1, 2:,:-2], x[1:-1, 2:, 1:-1], x[1:-1, 2:, 2:], # Top row x[2:, :-2, :-2], x[2:, :-2, 1:-1], x[2:, :-2, 2: ], x[2:, 1:-1,:-2], x[2:, 1:-1, 1:-1], x[2:, 1:-1, 2:], x[2:, 2:,:-2], x[2:, 2:, 1:-1], x[2:, 2:, 2:] ] )
I think this works (it's been a while! ;D), but it's a bit messy and the boundary condition is a bit crude. I was wondering whether there's some other nice way of doing it, like demonstrated in the above link. Also, what if you want to have a larger neighbourhood (say 5x5x2 instead of 3x3x3)?
While I appreciate these index tricks, I also find them quite mind boggling! Thanks! Jose _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Hi, On 16 August 2012 19:38, Sebastian Berg <sebastian@sipsolutions.net> wrote:
Hello,
Just to throw it in, if you do not mind useing scipy, you can use its multidimensional correlate method instead:
Well, I don't need to count the number of neighbours as in the linked example. What I wanted to have is easy access to the neighbours of one cell, so neighbours = np.array( [GRID[up,:], GRID[down,:], GRID[:,up], GRID[:,down] , \ GRID[ix_(up,up)], GRID[ix_(up,down)], GRID[ix_(down,up)] , \ GRID[ix_(down,down)] ]) That gives me an array of shape (8,)+GRID.shape. neighbours.sum(axis=1) (I think) would give me the equivalent of scipy.ndimage.correlate (I think), but I don't necessarily need a sum or a mean value of the neighbours. It's just that a 3D neigbourhood is 9 +8 +9 = 26 neighbours for each pixel, and I was wondering whether there was a simpler way of writing it than what I had in my message, which is likely to have errors. Thanks! Jose
I have a pull request for a neighborhood function at https://github.com/numpy/numpy/pull/303 . I think IMHO it handles these problems quite handily. It does rely on my pad routine that is in Numpy 1.7, so you would need to get the 1.7 beta installed or install the development branch. For your example you would just create a weight array, and a function that returns a scalar value from the collected neighborhood values. Untested, but workflow is something like:
inputarr = np.random.random(9*9*9) inputarr = inputarr.reshape((9,9,9)) weight = np.ones((3,3,3)) ans = neighbor(inputarr, weight, np.mean, pad = None)
In place of 'np.mean' you can define your own function - game of life function for example. The PR has not had much activity, so if you can review/comment/program that would be appreciated. Kindest regards, Tim
participants (3)
-
Cera, Tim -
Jose Gomez-Dans -
Sebastian Berg