46

Sorry for the stupid question.

I'm programming in PHP but found some nice code in Python and want to "recreate" it in PHP.

But I'm quite frustrated about the line:

self.h = -0.1    
self.activity = numpy.zeros((512, 512)) + self.h
self.activity[:, :] = self.h

I don't understand what [:, :] means.

I couldn't find an answer by googling it.

Full code

import math
import numpy
import pygame
from scipy.misc import imsave
from scipy.ndimage.filters import gaussian_filter


class AmariModel(object):

    def __init__(self, size):
        self.h = -0.1
        self.k = 0.05
        self.K = 0.125
        self.m = 0.025
        self.M = 0.065

        self.stimulus = -self.h * numpy.random.random(size)
        self.activity = numpy.zeros(size) + self.h
        self.excitement = numpy.zeros(size)
        self.inhibition = numpy.zeros(size)

    def stimulate(self):
        self.activity[:, :] = self.activity > 0

        sigma = 1 / math.sqrt(2 * self.k)
        gaussian_filter(self.activity, sigma, 0, self.excitement, "wrap")
        self.excitement *= self.K * math.pi / self.k

        sigma = 1 / math.sqrt(2 * self.m)
        gaussian_filter(self.activity, sigma, 0, self.inhibition, "wrap")
        self.inhibition *= self.M * math.pi / self.m

        self.activity[:, :] = self.h
        self.activity[:, :] += self.excitement
        self.activity[:, :] -= self.inhibition
        self.activity[:, :] += self.stimulus


class AmariMazeGenerator(object):

    def __init__(self, size):
        self.model = AmariModel(size)

        pygame.init()
        self.display = pygame.display.set_mode(size, 0)
        pygame.display.set_caption("Amari Maze Generator")

    def run(self):
        pixels = pygame.surfarray.pixels3d(self.display)

        index = 0
        running = True
        while running:
            self.model.stimulate()

            pixels[:, :, :] = (255 * (self.model.activity > 0))[:, :, None]
            pygame.display.flip()

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        running = False
                    elif event.key == pygame.K_s:
                        imsave("{0:04d}.png".format(index), pixels[:, :, 0])
                        index = index + 1
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    position = pygame.mouse.get_pos()
                    self.model.activity[position] = 1

        pygame.quit()


def main():
    generator = AmariMazeGenerator((512, 512))
    generator.run()


if __name__ == "__main__":
    main()
Dave Mackey
  • 4,306
  • 21
  • 78
  • 136
user2432721
  • 465
  • 1
  • 4
  • 6
  • Here `self.activity[:, :] = self.h` is redundant because `self.activity` is already `self.h`. Think similar to this: `a = 0 + 2` and then `a = 2`. It is not really the same but might help to understand. – Mike Müller May 29 '13 at 14:16

3 Answers3

52

The [:, :] stands for everything from the beginning to the end just like for lists. The difference is that the first : stands for first and the second : for the second dimension.

a = numpy.zeros((3, 3))

In [132]: a
Out[132]: 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

Assigning to second row:

In [133]: a[1, :] = 3

In [134]: a
Out[134]: 
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 0.,  0.,  0.]])

Assigning to second column:

In [135]: a[:, 1] = 4

In [136]: a
Out[136]: 
array([[ 0.,  4.,  0.],
       [ 3.,  4.,  3.],
       [ 0.,  4.,  0.]])

Assigning to all:

In [137]: a[:] = 10

In [138]: a
Out[138]: 
array([[ 10.,  10.,  10.],
       [ 10.,  10.,  10.],
       [ 10.,  10.,  10.]])
Samuel Harmer
  • 4,264
  • 5
  • 33
  • 67
Mike Müller
  • 82,630
  • 20
  • 166
  • 161
23

numpy uses tuples as indexes. In this case, this is a detailed slice assignment.

[0]     #means line 0 of your matrix
[(0,0)] #means cell at 0,0 of your matrix
[0:1]   #means lines 0 to 1 excluded of your matrix
[:1]    #excluding the first value means all lines until line 1 excluded
[1:]    #excluding the last param mean all lines starting form line 1 
         included
[:]     #excluding both means all lines
[::2]   #the addition of a second ':' is the sampling. (1 item every 2)
[::]    #exluding it means a sampling of 1
[:,:]   #simply uses a tuple (a single , represents an empty tuple) instead 
         of an index.

It is equivalent to the simpler

self.activity[:] = self.h

(which also works for regular lists as well)

njzk2
  • 38,969
  • 7
  • 69
  • 107
11

This is slice assignment. Technically, it calls1

self.activity.__setitem__((slice(None,None,None),slice(None,None,None)),self.h)

which sets all of the elements in self.activity to whatever value self.h is storing. The code you have there really seems redundant. As far as I can tell, you could remove the addition on the previous line, or simply use slice assignment:

self.activity = numpy.zeros((512,512)) + self.h

or

self.activity = numpy.zeros((512,512))
self.activity[:,:] = self.h

Perhaps the fastest way to do this is to allocate an empty array and .fill it with the expected value:

self.activity = numpy.empty((512,512))
self.activity.fill(self.h)

1Actually, __setslice__ is attempted before calling __setitem__, but __setslice__ is deprecated, and shouldn't be used in modern code unless you have a really good reason for it.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • check this one http://stackoverflow.com/questions/509211/the-python-slice-notation – Zang MingJie May 29 '13 at 14:03
  • @ZangMingJie -- Yeah, that's the canonical answer for slice notation. however, most of those answers are (implicitly) focused on `__getitem__` rather than `__setitem__` so I thought it would be reasonable to re-answer from that different perspective. – mgilson May 29 '13 at 14:07
  • So I can suppose that PHP version of Python's arr[:] += 1 will be foreach($arr as $k=>$v){ $arr[$k] += 1; } Or at least close to it. – user2432721 May 29 '13 at 14:11
  • @user2432721 -- That really depends on the type of `arr` -- But for `numpy.ndarray`, yes. That's correct. – mgilson May 29 '13 at 14:13
  • @JochenRitzel -- "which sets all of the elements in `self.activity` to whatever value `self.h` is storing" ... – mgilson May 29 '13 at 14:14
  • It's not My code. I'm only trying to move it to another language – user2432721 May 29 '13 at 14:16
  • @user2432721 -- Note that numpy pushes all of the loops into a compiled C backend, so it is designed to be efficient when used this way. It is likely that the numpy version executes much faster than the PHP approximation you suggested. – mgilson May 29 '13 at 14:18