Note
Click here to download the full example code
Creating a grid of electrodes¶
This example shows how to use
ElectrodeGrid
.
Most current electrode arrays arrange their electrodes in a 2D grid.
Creating a rectangular grid¶
To create a rectangular grid, we need to specify:
- The
shape
of the grid, passed as a tuple containing the desired number of rows and columns - The electrode-to-electrode
spacing
in microns - The (
x
,y
) location of the center of the array - The rotation angle
rot
of the grid in degrees, where positive angles rotate all electrodes in the array in a counter-clockwise fashion on the retinal surface.
We can also specify:
- A naming convention
names
for the rows and columns in the grid. For example, to label rows alphabetically and columns numerically, we would pass a tuple('A', '1')
. To label both alphabetically, we would pass('A', 'A')
. - An electrode type
etype
, which must be a subclass ofElectrode
. By default,PointSource
is chosen. - Any additional parameters that should be passed to the
Electrode
constructor, such as a radiusr
forDiskElectrode
.
Let’s say we want to create a 2x3 rectangular grid of
PointSource
objects, each electrode spaced
500 microns apart, and the whole grid should be centered over the fovea:
from pulse2percept.models import AxonMapModel
from numpy import pi
from pulse2percept.implants import DiskElectrode
from pulse2percept.implants import ElectrodeGrid
grid = ElectrodeGrid((2, 3), 500)
We can access individual electrodes by indexing into grid
:
The first electrode:
grid[0]
Out:
PointSource(activated=True, name='A1', x=-500.0, y=-250.0,
z=0.0)
The first electrode by name:
grid['A1']
Out:
PointSource(activated=True, name='A1', x=-500.0, y=-250.0,
z=0.0)
Accessing the x-coordinate of the first electrode:
grid[0].x
Out:
-500.0
Showing all electrodes:
grid[:]
Out:
[PointSource(activated=True, name='A1', x=-500.0, y=-250.0,
z=0.0), PointSource(activated=True, name='A2', x=0.0, y=-250.0,
z=0.0), PointSource(activated=True, name='A3', x=500.0, y=-250.0,
z=0.0), PointSource(activated=True, name='B1', x=-500.0, y=250.0,
z=0.0), PointSource(activated=True, name='B2', x=0.0, y=250.0,
z=0.0), PointSource(activated=True, name='B3', x=500.0, y=250.0,
z=0.0)]
We can iterate over all electrodes as if we were dealing with a dictionary:
for name, electrode in grid.electrodes.items():
print(name, electrode)
Out:
A1 PointSource(activated=True, name='A1', x=-500.0, y=-250.0,
z=0.0)
A2 PointSource(activated=True, name='A2', x=0.0, y=-250.0,
z=0.0)
A3 PointSource(activated=True, name='A3', x=500.0, y=-250.0,
z=0.0)
B1 PointSource(activated=True, name='B1', x=-500.0, y=250.0,
z=0.0)
B2 PointSource(activated=True, name='B2', x=0.0, y=250.0,
z=0.0)
B3 PointSource(activated=True, name='B3', x=500.0, y=250.0,
z=0.0)
To make a grid of DiskElectrode
objects,
we need to explicitly specify the electrode type (etype
) and the radius
to use (r
):
# 11x13 grid, 100-um disk electrodes spaced 500um apart:
disk_grid = ElectrodeGrid((11, 13), 500, etype=DiskElectrode, r=100)
disk_grid[:]
Out:
[DiskElectrode(activated=True, name='A1', r=100.0,
x=-3000.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A2', r=100.0,
x=-2500.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A3', r=100.0,
x=-2000.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A4', r=100.0,
x=-1500.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A5', r=100.0,
x=-1000.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A6', r=100.0, x=-500.0,
y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A7', r=100.0, x=0.0,
y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A8', r=100.0, x=500.0,
y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A9', r=100.0, x=1000.0,
y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A10', r=100.0,
x=1500.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A11', r=100.0,
x=2000.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A12', r=100.0,
x=2500.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='A13', r=100.0,
x=3000.0, y=-2500.0, z=0.0), DiskElectrode(activated=True, name='B1', r=100.0,
x=-3000.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B2', r=100.0,
x=-2500.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B3', r=100.0,
x=-2000.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B4', r=100.0,
x=-1500.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B5', r=100.0,
x=-1000.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B6', r=100.0, x=-500.0,
y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B7', r=100.0, x=0.0,
y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B8', r=100.0, x=500.0,
y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B9', r=100.0, x=1000.0,
y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B10', r=100.0,
x=1500.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B11', r=100.0,
x=2000.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B12', r=100.0,
x=2500.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='B13', r=100.0,
x=3000.0, y=-2000.0, z=0.0), DiskElectrode(activated=True, name='C1', r=100.0,
x=-3000.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C2', r=100.0,
x=-2500.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C3', r=100.0,
x=-2000.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C4', r=100.0,
x=-1500.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C5', r=100.0,
x=-1000.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C6', r=100.0, x=-500.0,
y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C7', r=100.0, x=0.0,
y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C8', r=100.0, x=500.0,
y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C9', r=100.0, x=1000.0,
y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C10', r=100.0,
x=1500.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C11', r=100.0,
x=2000.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C12', r=100.0,
x=2500.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='C13', r=100.0,
x=3000.0, y=-1500.0, z=0.0), DiskElectrode(activated=True, name='D1', r=100.0,
x=-3000.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D2', r=100.0,
x=-2500.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D3', r=100.0,
x=-2000.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D4', r=100.0,
x=-1500.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D5', r=100.0,
x=-1000.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D6', r=100.0, x=-500.0,
y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D7', r=100.0, x=0.0,
y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D8', r=100.0, x=500.0,
y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D9', r=100.0, x=1000.0,
y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D10', r=100.0,
x=1500.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D11', r=100.0,
x=2000.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D12', r=100.0,
x=2500.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='D13', r=100.0,
x=3000.0, y=-1000.0, z=0.0), DiskElectrode(activated=True, name='E1', r=100.0,
x=-3000.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E2', r=100.0,
x=-2500.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E3', r=100.0,
x=-2000.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E4', r=100.0,
x=-1500.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E5', r=100.0,
x=-1000.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E6', r=100.0, x=-500.0,
y=-500.0, z=0.0), DiskElectrode(activated=True, name='E7', r=100.0, x=0.0,
y=-500.0, z=0.0), DiskElectrode(activated=True, name='E8', r=100.0, x=500.0,
y=-500.0, z=0.0), DiskElectrode(activated=True, name='E9', r=100.0, x=1000.0,
y=-500.0, z=0.0), DiskElectrode(activated=True, name='E10', r=100.0,
x=1500.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E11', r=100.0,
x=2000.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E12', r=100.0,
x=2500.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='E13', r=100.0,
x=3000.0, y=-500.0, z=0.0), DiskElectrode(activated=True, name='F1', r=100.0,
x=-3000.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F2', r=100.0,
x=-2500.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F3', r=100.0,
x=-2000.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F4', r=100.0,
x=-1500.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F5', r=100.0,
x=-1000.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F6', r=100.0, x=-500.0,
y=0.0, z=0.0), DiskElectrode(activated=True, name='F7', r=100.0, x=0.0,
y=0.0, z=0.0), DiskElectrode(activated=True, name='F8', r=100.0, x=500.0,
y=0.0, z=0.0), DiskElectrode(activated=True, name='F9', r=100.0, x=1000.0,
y=0.0, z=0.0), DiskElectrode(activated=True, name='F10', r=100.0,
x=1500.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F11', r=100.0,
x=2000.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F12', r=100.0,
x=2500.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='F13', r=100.0,
x=3000.0, y=0.0, z=0.0), DiskElectrode(activated=True, name='G1', r=100.0,
x=-3000.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G2', r=100.0,
x=-2500.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G3', r=100.0,
x=-2000.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G4', r=100.0,
x=-1500.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G5', r=100.0,
x=-1000.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G6', r=100.0, x=-500.0,
y=500.0, z=0.0), DiskElectrode(activated=True, name='G7', r=100.0, x=0.0,
y=500.0, z=0.0), DiskElectrode(activated=True, name='G8', r=100.0, x=500.0,
y=500.0, z=0.0), DiskElectrode(activated=True, name='G9', r=100.0, x=1000.0,
y=500.0, z=0.0), DiskElectrode(activated=True, name='G10', r=100.0,
x=1500.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G11', r=100.0,
x=2000.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G12', r=100.0,
x=2500.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='G13', r=100.0,
x=3000.0, y=500.0, z=0.0), DiskElectrode(activated=True, name='H1', r=100.0,
x=-3000.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H2', r=100.0,
x=-2500.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H3', r=100.0,
x=-2000.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H4', r=100.0,
x=-1500.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H5', r=100.0,
x=-1000.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H6', r=100.0, x=-500.0,
y=1000.0, z=0.0), DiskElectrode(activated=True, name='H7', r=100.0, x=0.0,
y=1000.0, z=0.0), DiskElectrode(activated=True, name='H8', r=100.0, x=500.0,
y=1000.0, z=0.0), DiskElectrode(activated=True, name='H9', r=100.0, x=1000.0,
y=1000.0, z=0.0), DiskElectrode(activated=True, name='H10', r=100.0,
x=1500.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H11', r=100.0,
x=2000.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H12', r=100.0,
x=2500.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='H13', r=100.0,
x=3000.0, y=1000.0, z=0.0), DiskElectrode(activated=True, name='I1', r=100.0,
x=-3000.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I2', r=100.0,
x=-2500.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I3', r=100.0,
x=-2000.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I4', r=100.0,
x=-1500.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I5', r=100.0,
x=-1000.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I6', r=100.0, x=-500.0,
y=1500.0, z=0.0), DiskElectrode(activated=True, name='I7', r=100.0, x=0.0,
y=1500.0, z=0.0), DiskElectrode(activated=True, name='I8', r=100.0, x=500.0,
y=1500.0, z=0.0), DiskElectrode(activated=True, name='I9', r=100.0, x=1000.0,
y=1500.0, z=0.0), DiskElectrode(activated=True, name='I10', r=100.0,
x=1500.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I11', r=100.0,
x=2000.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I12', r=100.0,
x=2500.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='I13', r=100.0,
x=3000.0, y=1500.0, z=0.0), DiskElectrode(activated=True, name='J1', r=100.0,
x=-3000.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J2', r=100.0,
x=-2500.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J3', r=100.0,
x=-2000.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J4', r=100.0,
x=-1500.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J5', r=100.0,
x=-1000.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J6', r=100.0, x=-500.0,
y=2000.0, z=0.0), DiskElectrode(activated=True, name='J7', r=100.0, x=0.0,
y=2000.0, z=0.0), DiskElectrode(activated=True, name='J8', r=100.0, x=500.0,
y=2000.0, z=0.0), DiskElectrode(activated=True, name='J9', r=100.0, x=1000.0,
y=2000.0, z=0.0), DiskElectrode(activated=True, name='J10', r=100.0,
x=1500.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J11', r=100.0,
x=2000.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J12', r=100.0,
x=2500.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='J13', r=100.0,
x=3000.0, y=2000.0, z=0.0), DiskElectrode(activated=True, name='K1', r=100.0,
x=-3000.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K2', r=100.0,
x=-2500.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K3', r=100.0,
x=-2000.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K4', r=100.0,
x=-1500.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K5', r=100.0,
x=-1000.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K6', r=100.0, x=-500.0,
y=2500.0, z=0.0), DiskElectrode(activated=True, name='K7', r=100.0, x=0.0,
y=2500.0, z=0.0), DiskElectrode(activated=True, name='K8', r=100.0, x=500.0,
y=2500.0, z=0.0), DiskElectrode(activated=True, name='K9', r=100.0, x=1000.0,
y=2500.0, z=0.0), DiskElectrode(activated=True, name='K10', r=100.0,
x=1500.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K11', r=100.0,
x=2000.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K12', r=100.0,
x=2500.0, y=2500.0, z=0.0), DiskElectrode(activated=True, name='K13', r=100.0,
x=3000.0, y=2500.0, z=0.0)]
Note
You can also specify a list of radii, one value for each electrode in the grid.
We can visualize the grid by using its plot
method:
Out:
<AxesSubplot:xlabel='x (microns)', ylabel='y (microns)'>
Creating a hexagonal grid¶
To create a hexagonal grid instead, all we need to do is change the grid type from ‘rect’ (default) to ‘hex’:
hex_grid = ElectrodeGrid((11, 13), 500, type='hex', etype=DiskElectrode, r=100)
hex_grid.plot()
Out:
<AxesSubplot:xlabel='x (microns)', ylabel='y (microns)'>
The following example centers the grid on (x,y) = (-600um, 200 um), z=150um away from the retinal surface, and rotates it clockwise by 45 degrees (note the minus sign):
offset_grid = ElectrodeGrid((11, 13), 500, type='hex', x=-600, y=200, z=150,
rot=-45, etype=DiskElectrode, r=100)
Note
Clockwise/counter-clockwise rotations refer to rotations on the retinal surface (that is, as if seen on a fundus photograph).
We can also plot the grid on top of a map of retinal nerve fiber bundles:
AxonMapModel().plot()
offset_grid.plot()
Out:
<AxesSubplot:xlabel='x (microns)', ylabel='y (microns)'>
Total running time of the script: ( 0 minutes 0.680 seconds)