Representing spatial structure and calculating distancesΒΆ
The space
module contains classes for specifying the locations of neurons
in space and for calculating the distances between them.
Neuron positions can be defined either manually, using the positions
attribute of a Population
or using a Structure
instance which is passed
to the Population
constructor.
A number of different structures are available in space
. It is simple to
define your own Structure
sub-class if you need something that is not
already provided.
The simplest structure is a grid, whether 1D, 2D or 3D, e.g.:
>>> from pyNN.space import *
>>> line = Line(dx=100.0, x0=0.0, y=200.0, z=500.0)
>>> line.generate_positions(7)
array([[ 0., 100., 200., 300., 400., 500., 600.],
[ 200., 200., 200., 200., 200., 200., 200.],
[ 500., 500., 500., 500., 500., 500., 500.]])
>>> grid = Grid2D(aspect_ratio=3, dx=10.0, dy=25.0, z=-3.0)
>>> grid.generate_positions(3)
array([[ 0., 10., 20.],
[ 0., 0., 0.],
[ -3., -3., -3.]])
>>> grid.generate_positions(12)
array([[ 0., 0., 10., 10., 20., 20., 30., 30., 40., 40., 50., 50.],
[ 0., 25., 0., 25., 0., 25., 0., 25., 0., 25., 0., 25.],
[ -3., -3., -3., -3., -3., -3., -3., -3., -3., -3., -3., -3.]])
Here we have specified an x:y ratio of 3, so if we ask the grid to generate positions for 3 neurons, we get a 3x1 grid, 12 neurons a 6x2 grid, 27 neurons 9x3, etc.
BY default, grid positions are filled sequentially, iterating first over the z dimension, then y, then x, but we can also fill the grid randomly:
>>> rgrid = Grid2D(aspect_ratio=1, dx=10.0, dy=10.0, fill_order='random')
>>> rgrid.generate_positions(9)
array([[ 20., 20., 20., 0., 10., 0., 10., 0., 10.],
[ 10., 0., 20., 10., 0., 20., 10., 0., 20.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
The space
module also provides the RandomStructure
class, which
distributes neurons randomly and uniformly within a given volume:
>>> glomerulus = RandomStructure(boundary=Sphere(radius=200.0))
>>> glomerulus.generate_positions(5)
array([[ 4.81853231e+01, -2.49317729e+01, 1.08294461e+02, 1.72125819e-01, -1.25552649e+02],
[ 3.96588073e+01, 1.75426143e+02, 3.19290169e+01, 1.65050459e+02, -1.32092198e+00],
[ -1.00801053e+02, -8.51701627e+01, -1.39804442e+02, -4.97765369e+01, 3.94241050e+01]])
The volume classes currently available are Sphere
and Cuboid
.
Defining your own Structure
classes is straightforward, just inherit from
BaseStructure
and implement a generate_positions(n)
method:
class MyStructure(BaseStructure):
parameter_names = ("spam", "eggs")
def __init__(self, spam=3, eggs=1):
...
def generate_positions(self, n):
...
# must return a 3xn numpy array
To definite your own Shape
class for use with RandomStructure
, subclass
Shape
and implement a sample(n, rng)
method:
class Tetrahedron(Shape):
def __init__(self, side_length):
...
def sample(self, n, rng):
...
# return a nx3 numpy array.
Note that rotation of structures is currently missing, but will be implemented in the next release.