pulse2percept.implants
Visual prostheses, e.g. Argus II, Alpha-IMS, PRIMA, NeuroPortArray
Generic device machinery lives at the root; devices live under the anatomical target they stimulate.
Retinal implants: Argus, Alpha, suprachoroidal, IMIE, and PRIMA arrays |
|
Cortical implants such as Orion, ICVP, and Neuralink |
|
|
See also
- class pulse2percept.implants.CheckerboardRaster(n_groups, balance=0.05, group_dur=None)[source]
Split electrodes into groups that are spread as far apart as possible
Implements a generalized form of the checkerboard raster pattern tested in [Kasowski2025], which found that scattering raster groups over the whole array beat horizontal, vertical, and random rasters at letter recognition and motion discrimination, and matched not rastering at all.
Mathematically speaking, a raster group is a coset of a sublattice of the electrode grid. Within a group, electrodes sit as far from one another as the electrode count allows. Each group is a coarser copy of the grid. Between groups, the order is chosen so the pattern doubles back rather than marching on (to reduce apparent motion). For example: Five groups on a square grid come out one over, two over, one back, two over, so that the percept steps right, down, left, down, and back rather than sliding across the array.
The grid does not have to be rectangular: hexagonal grids, rotated grids, grids with unequal row and column spacing, and grids with electrodes trimmed off are all handled, since the pattern is derived from where the electrodes actually are. Arrays whose electrodes do not lie on a grid at all raise
NotImplementedError.The pattern depends on where the electrodes are, so it is worked out when the raster is bound to an implant – which assigning it to
rasterdoes. Until then the raster knows how many groups it will have but not which electrode goes in which, andgroups(),min_spacingandplot()all raise. Binding it to a second implant recomputes the pattern for that one.Note
Not every
n_groupsfits a given grid, and one that does not raises aValueError(naming counts that do) when the raster is bound.Both halves of the pattern are searched for at binding time, and the order the groups fire in is settled exactly only up to eight groups; beyond that a heuristic stands in for it, and the search grows with the group count.
It is worth checking
min_spacingon the ones that do fit, because a count can be accepted and still leave neighbors in the same group. The standard example is two groups on a hex grid, which degenerates to a line raster. In other words, implants like PRIMA cannot be two-colored; they want 3, 4, or 7 raster groups instead.Added in version 0.10.0.
- Parameters:
n_groups (int) – Number of groups to split the electrodes into.
balance (float, optional) – How much bigger the largest group may be than an even split would make it, as a fraction of it. The largest group is what sets the current the stimulator has to source, so this is the price being paid; what it buys is spacing, because the patterns that spread furthest do not always land evenly on a grid whose edges have been trimmed. Pass 0 to add no imbalance beyond the rounding an uneven electrode count forces anyway – 378 electrodes in 5 groups are 76, 76, 75, 75, 76 at
balance=0, never 76 apiece – and take whatever spacing comes with it.
Examples
Five groups of twelve on Argus II, as in [Kasowski2025]:
>>> from pulse2percept.implants import CheckerboardRaster >>> from pulse2percept.implants.retina import ArgusII >>> implant = ArgusII() >>> implant.raster = CheckerboardRaster(5) >>> implant.raster.n_groups 5
No two electrodes of a group are closer than sqrt(5) pitches, where a line raster would have them adjacent:
>>> round(implant.raster.min_spacing / 575, 3) # 575 um pitch 2.236
The pattern is easiest to check by eye (
plot()), and the electrodes that fire together aremembers():>>> implant.raster.members(implant.electrode_names, 0)[:4].tolist() ['A1', 'A6', 'B3', 'B8']
- bind(implant)[source]
Work the checkerboard out for this implant’s electrode grid
See
bind(). Called for you when the raster is assigned toraster.
- property n_groups
Number of raster groups
- property min_spacing
Distance (um) between the closest two electrodes of a group
How much the checkerboard bought over a line raster, which leaves neighboring electrodes in the same group and so would report the electrode pitch. Measured between electrodes the implant actually has, so a small or trimmed array can come out better spaced than the pattern it was cut from. Infinite when no group holds more than one electrode, since then no two electrodes ever fire together. None until the raster is bound to an implant, since there is no grid to measure yet.
- property implant
The implant this raster is bound to, or None
- members(electrodes, group)[source]
Return the electrodes in one raster group.
- Parameters:
electrodes (array_like) – Electrode names.
group (int) – Group index in
0..n_groups-1.
- Returns:
members – Electrode names belonging to
group.- Return type:
array
- offsets(electrodes, period)[source]
How far behind group 0 each electrode’s slot begins
- Parameters:
electrodes (array_like) – Electrode names, in the order they appear in the stimulus.
period (float) – The pulse period (ms) a sweep has to fit into.
- Returns:
offset – Time (ms) between the start of a sweep and the start of this electrode’s slot.
- Return type:
(n_electrodes,)float array
- plot(implant=None, annotate=None, ax=None, cmap='viridis', autoscale=True)[source]
Plot electrodes colored by raster group.
- Parameters:
implant (
Implant, optional) – Implant to draw. If None, use the bound implant.annotate (bool, optional) – Write group indices on electrodes. If None, annotate arrays with at most 120 electrodes.
ax (matplotlib.axes.Axes, optional) – Axes to draw on.
cmap (str, optional) – Matplotlib colormap.
autoscale (bool, optional) – Fit the axes to the implant.
- Returns:
ax – The axes drawn on.
- Return type:
- class pulse2percept.implants.CustomRaster(groups, group_dur=None)[source]
Assign electrodes to raster groups by name
Added in version 0.10.0.
- Parameters:
Examples
Fire the four corners of Argus II before everything else. Every other electrode has to be given a group too, or the current limit that the raster exists to respect could be violated without anyone noticing:
>>> from pulse2percept.implants import CustomRaster >>> from pulse2percept.implants.retina import ArgusII >>> corners = ['A1', 'A10', 'F1', 'F10'] >>> rest = [e for e in ArgusII().electrode_names if e not in corners] >>> raster = CustomRaster([corners, rest]) >>> raster.n_groups 2
- property n_groups
Number of raster groups
- bind(implant)[source]
Bind the raster to an implant or electrode array.
Geometry-dependent rasters may override this method to recompute their grouping.
- Parameters:
implant (
Implantor ) –ElectrodeArrayImplant or electrode array to bind.- Returns:
self
- Return type:
- property implant
The implant this raster is bound to, or None
- members(electrodes, group)[source]
Return the electrodes in one raster group.
- Parameters:
electrodes (array_like) – Electrode names.
group (int) – Group index in
0..n_groups-1.
- Returns:
members – Electrode names belonging to
group.- Return type:
array
- offsets(electrodes, period)[source]
How far behind group 0 each electrode’s slot begins
- Parameters:
electrodes (array_like) – Electrode names, in the order they appear in the stimulus.
period (float) – The pulse period (ms) a sweep has to fit into.
- Returns:
offset – Time (ms) between the start of a sweep and the start of this electrode’s slot.
- Return type:
(n_electrodes,)float array
- plot(implant=None, annotate=None, ax=None, cmap='viridis', autoscale=True)[source]
Plot electrodes colored by raster group.
- Parameters:
implant (
Implant, optional) – Implant to draw. If None, use the bound implant.annotate (bool, optional) – Write group indices on electrodes. If None, annotate arrays with at most 120 electrodes.
ax (matplotlib.axes.Axes, optional) – Axes to draw on.
cmap (str, optional) – Matplotlib colormap.
autoscale (bool, optional) – Fit the axes to the implant.
- Returns:
ax – The axes drawn on.
- Return type:
- class pulse2percept.implants.DiskElectrode(x, y, z, radius, name=None, activated=True)[source]
Circular disk electrode
- Parameters:
Notes
Lengths may be given as plain numbers of microns or as unitful quantities (e.g.
DiskElectrode(1 * mm, 0, 0.1 * mm, 200 * um)). Seepulse2percept.units.
- electric_potential(x, y, z, v0)[source]
Calculate electric potential at (x, y, z)
- Parameters:
x/y/z (double) – 3D location (um) at which to evaluate the electric potential. May be given as a unitful quantity, e.g.
0.2 * mm.v0 (double) – The quasi-static disk potential relative to a ground electrode at infinity
- Returns:
pot – The electric potential at (x, y, z).
- Return type:
double
The electric potential \(V(r,z)\) of a disk electrode is given by [WileyWebster1982]:
\[V(r,z) = \sin^{-1} \bigg\{ \frac{2a}{\sqrt{(r-a)^2 + z^2} + \sqrt{(r+a)^2 + z^2}} \bigg\} \times \frac{2 V_0}{\pi},\]for \(z \neq 0\), where \(r\) and \(z\) are the radial and axial distances from the center of the disk, \(V_0\) is the disk potential, \(\sigma\) is the medium conductivity, and \(a\) is the disk radius.
- coordinate_unit = um[source]
The unit electrode coordinates are stored in. Electrodes hold plain numbers, which is what every kernel downstream of them expects; this says what those numbers mean.
- coordinates(unit=None)[source]
3D position of the electrode
Added in version 0.10.0.
- Parameters:
unit (
Unit, optional) – Length unit to express the position in. If None, the position is returned as it is stored (microns).- Returns:
coords – An ordinary NumPy array
[x, y, z], never aQuantity.- Return type:
(3,) np.ndarray
Examples
>>> from pulse2percept.implants import DiskElectrode >>> from pulse2percept.units import mm >>> DiskElectrode(1000, 0, 100, 200).coordinates(mm) array([1. , 0. , 0.1])
- plot(autoscale=False, ax=None)[source]
Plot
- Parameters:
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None given, a new one will be created.
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- class pulse2percept.implants.Electrode[source]
Abstract base class for all electrodes.
- Parameters:
Notes
Coordinates may be given as plain numbers of microns or as unitful quantities (e.g.
1.2 * mm), which are converted to microns. Seepulse2percept.units. Electrodes always store plain numbers in microns:x,yandzare ordinary floats, and so is everything downstream of them.
- coordinate_unit = um[source]
The unit electrode coordinates are stored in. Electrodes hold plain numbers, which is what every kernel downstream of them expects; this says what those numbers mean.
- coordinates(unit=None)[source]
3D position of the electrode
Added in version 0.10.0.
- Parameters:
unit (
Unit, optional) – Length unit to express the position in. If None, the position is returned as it is stored (microns).- Returns:
coords – An ordinary NumPy array
[x, y, z], never aQuantity.- Return type:
(3,) np.ndarray
Examples
>>> from pulse2percept.implants import DiskElectrode >>> from pulse2percept.units import mm >>> DiskElectrode(1000, 0, 100, 200).coordinates(mm) array([1. , 0. , 0.1])
- plot(autoscale=False, ax=None)[source]
Plot
- Parameters:
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None given, a new one will be created.
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- class pulse2percept.implants.ElectrodeArray(electrodes)[source]
Electrode array
A collection of
Electrodeobjects.- Parameters:
electrodes (array-like) –
Either a single
Electrodeobject or a dict, list, or NumPy array thereof. The keys of the dict will serve as electrode names. Otherwise electrodes will be indexed 0..N.Note
If you pass multiple electrodes in a dictionary, the keys of the dictionary will automatically be sorted. Thus the original order of electrodes might not be preserved.
Examples
Electrode array made from a single DiskElectrode:
>>> from pulse2percept.implants import ElectrodeArray, DiskElectrode >>> electrode_array = ElectrodeArray(DiskElectrode(0, 0, 0, 100)) >>> electrode_array.electrodes OrderedDict([(0, DiskElectrode(activated=True, name=None, radius=100..., x=0..., y=0..., z=0...))])
Electrode array made from a single DiskElectrode with name ‘A1’:
>>> from pulse2percept.implants import ElectrodeArray, DiskElectrode >>> electrode_array = ElectrodeArray({'A1': DiskElectrode(0, 0, 0, 100)}) >>> electrode_array.electrodes OrderedDict([('A1', DiskElectrode(activated=True, name=None, radius=100..., x=0..., y=0..., z=0...))])
- coordinate_unit = um[source]
The unit electrode coordinates are stored in, i.e. what the plain numbers returned by
coordinates()mean by default.
- coordinates(unit=None, electrodes=None)[source]
Positions of the electrodes in the array
The one place to ask an implant where its electrodes are. Code that needs the coordinates in a particular unit says so here, instead of reading
electrode.xand knowing that electrodes happen to store microns.Added in version 0.10.0.
- Parameters:
unit (
Unit, optional) – Length unit to express the coordinates in. If None, they are returned as they are stored (microns).electrodes (optional) – Which electrodes to return, either by name, index into the flattened array, or a
(row, col)pair on anElectrodeGrid. Everything else is treated as a collection.
- Returns:
coords – One
[x, y, z]row per electrode- Return type:
(n_electrodes, 3)np.ndarray
Examples
>>> from pulse2percept.implants.retina import ArgusII >>> from pulse2percept.units import mm >>> ArgusII().electrode_array.coordinates(mm)[0] array([-2.5875, -1.4375, 0. ]) >>> ArgusII().electrode_array.coordinates(electrodes=['F10', 'A1']) array([[ 2587.5, 1437.5, 0. ], [-2587.5, -1437.5, 0. ]])
- add_electrode(name, electrode)[source]
Add an electrode to the array
- Parameters:
electrode (implants.Electrode) – An Electrode object, such as a PointSource or a DiskElectrode.
- remove_electrode(name)[source]
Remove an electrode from the array
Parameter
- name: int|str|…
Electrode name or index
- plot(annotate=False, autoscale=True, ax=None, color_stim=None, cmap='OrRd')[source]
Plot the electrode array in its own coordinate frame
- Parameters:
annotate (bool, optional) – Flag whether to label electrodes in the implant.
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot to fit the implant
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None, will either use the current axes (if exists) or create a new Axes object.
color_stim (
pulse2percept.stimuli.Stimulus, or None) – If provided, colors the electrode_array based on the stimulus amplitudes. A multi-patch electrode (e.g.,PhotovoltaicPixel) colors only its last patch; earlier patches are structural.cmap (str) – Matplotlib colormap to use for stimulus coloring.
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- property electrodes
Return all electrode names and objects in the electrode array
Internally, electrodes are stored in an ordered dictionary. You can iterate over different electrodes in the array as follows:
for name, electrode in electrode_array.electrodes.items(): print(name, electrode)
You can access an individual electrode by indexing directly into the electrode array object, e.g.
electrode_array['A1']orelectrode_array[0].
- property electrode_names
Return a list of all electrode names in the array
- property electrode_objects
Return a list of all electrode objects in the array
- class pulse2percept.implants.ElectrodeGrid(shape, spacing, x=0, y=0, z=0, rot=0, names=('A', '1'), grid_type='rect', orientation='horizontal', electrode_type=<class 'pulse2percept.implants.electrodes.PointSource'>, **electrode_params)[source]
2D grid of electrodes
- Parameters:
shape ((rows, cols)) – A tuple containing the number of rows x columns in the grid
spacing (double or (x_spacing, y_spacing)) – Electrode-to-electrode spacing in microns. Must be either a tuple specifying the spacing in x and y directions or a float (assuming the same spacing in x and y). If a tuple is specified for a horizontal hex grid,
x_spacingwill define the electrode-to-electrode distance, andy_spacingwill define the vertical distance between adjacent hexagon centers. In a vertical hex grid, the order is reversed.grid_type ({'rect', 'hex'}, optional) –
Grid type (‘rect’: rectangular, ‘hex’: hexagonal).
Changed in version 0.11.0: Renamed from
type.orientation ({'horizontal', 'vertical'}, optional) – Hex-grid orientation.
'horizontal'staggers alternate rows;'vertical'staggers alternate columns. Hexagonal electrode bodies follow the grid orientation.x/y/z (double) – Location (um) of the center of the grid within the array it belongs to.
zis height above the array plane.rot (double, optional) – Rotation of the grid in degrees (positive angle: counter-clockwise). A plain angle, not a unitful one:
dvameans visual angle, which is a different thing.names ((name_rows, name_cols), each of which either 'A' or '1') –
Naming convention for rows and columns, respectively. If ‘A’, rows or columns will be labeled alphabetically: A-Z, AA-AZ, BA-BZ, CA-CZ, etc. ‘-A’ will reverse the order. If ‘1’, rows or columns will be labeled numerically. ‘-1’ will reverse. Letters will always precede numbers in electrode names. For example (‘1’, ‘A’) will number rows numerically and columns alphabetically; first row: ‘A1’, ‘B1’, ‘C1’, NOT ‘1A’, ‘1B’, ‘1C’.
The default,
('A', '1'), is the same convention that names the pixels of anImageStimulus, and is generated by the same implementation. The other combinations exist to reproduce the naming of specific published implants and are not otherwise recommended.Alternatively, pass a list or NumPy array with one name per electrode to name them all explicitly. On a grid with exactly two electrodes the two readings collide, and only something that could be a scheme is read as one:
names=('A', '1')gives ‘A1’, ‘A2’, whereasnames=('C1', '4')names the two electrodes ‘C1’ and ‘4’. Pass a list (names=['A', '1']) to name two electrodes ‘A’ and ‘1’.Changed in version 0.10.0: On a grid with exactly two electrodes,
('A', '1')now yields ‘A1’, ‘A2’ (was: ‘A’, ‘1’), consistent with every other shape.electrode_type (
Electrode, optional) –A valid Electrode class. By default,
PointSourceis used.Changed in version 0.11.0: Renamed from
etype.**electrode_params – Keyword arguments passed to the
electrode_typeconstructor, such asradiusforDiskElectrode. They are forwarded unchanged, except thatradiusmay be given per electrode (see below).
Notes
zandradiusmay be given per electrode, as a list or array with one entry per grid position. Every other electrode parameter is one value shared by all electrodes.spacing,x,y,zandradiusmay be given as plain numbers of microns or as unitful quantities, and may be mixed freely:spacing=(0.5 * mm, 600 * um)andz=[0 * um, 0.1 * mm, ...]both work. Any other electrode keyword is normalized by the electrode class it is passed to. Seepulse2percept.units.
Examples
A hexagonal electrode grid with 3 rows and 4 columns, made of disk electrodes with 10um radius spaced 20um apart, centered at (10, 20)um, and located 500um away from the retinal surface, with names like this:
A1 A2 A3 A4 B1 B2 B3 B4 C1 C2 C3 C4>>> from pulse2percept.implants import ElectrodeGrid, DiskElectrode >>> ElectrodeGrid((3, 4), 20, x=10, y=20, z=500, names=('A', '1'), ... radius=10, grid_type='hex', ... electrode_type=DiskElectrode) ... ElectrodeGrid(grid_type='hex', rot=0, shape=(3, 4), spacing=20)
A rectangular electrode grid with 2 rows and 4 columns, made of disk electrodes with 10um radius spaced 20um apart, centered at (10, 20)um, and located 500um away from the retinal surface, with names like this:
A1 A2 A3 A4 B1 B2 B3 B4>>> from pulse2percept.implants import ElectrodeGrid, DiskElectrode >>> ElectrodeGrid((2, 4), 20, x=10, y=20, z=500, names=('A', '1'), ... radius=10, grid_type='rect', ... electrode_type=DiskElectrode) ... ElectrodeGrid(grid_type='rect', rot=0, shape=(2, 4), spacing=20)
There are three ways to access (e.g.) the last electrode in the grid, either by name (
grid['C3']), by row/column index (grid[2, 2]), or by index into the flattened array (grid[8]):>>> from pulse2percept.implants import ElectrodeGrid >>> grid = ElectrodeGrid((3, 3), 20, names=('A', '1')) >>> grid['C3'] PointSource(activated=True, name='C3', x=20..., y=20..., z=0...) >>> grid['C3'] == grid[8] == grid[2, 2] True
You can also access multiple electrodes at the same time by passing a list of indices/names (it’s ok to mix-and-match):
>>> from pulse2percept.implants import ElectrodeGrid, DiskElectrode >>> grid = ElectrodeGrid((3, 3), 20, electrode_type=DiskElectrode, ... radius=10) >>> grid[['A1', 1, (0, 2)]] [DiskElectrode(activated=True, name='A1', radius=10..., x=-20.0, y=-20.0, z=0...), DiskElectrode(activated=True, name='A2', radius=10..., x=0.0, y=-20.0, z=0...), DiskElectrode(activated=True, name='A3', radius=10..., x=20.0, y=-20.0, z=0...)]
- add_electrode(name, electrode)[source]
Add an electrode to the array
- Parameters:
electrode (implants.Electrode) – An Electrode object, such as a PointSource or a DiskElectrode.
- coordinate_unit = um[source]
The unit electrode coordinates are stored in, i.e. what the plain numbers returned by
coordinates()mean by default.
- coordinates(unit=None, electrodes=None)[source]
Positions of the electrodes in the array
The one place to ask an implant where its electrodes are. Code that needs the coordinates in a particular unit says so here, instead of reading
electrode.xand knowing that electrodes happen to store microns.Added in version 0.10.0.
- Parameters:
unit (
Unit, optional) – Length unit to express the coordinates in. If None, they are returned as they are stored (microns).electrodes (optional) – Which electrodes to return, either by name, index into the flattened array, or a
(row, col)pair on anElectrodeGrid. Everything else is treated as a collection.
- Returns:
coords – One
[x, y, z]row per electrode- Return type:
(n_electrodes, 3)np.ndarray
Examples
>>> from pulse2percept.implants.retina import ArgusII >>> from pulse2percept.units import mm >>> ArgusII().electrode_array.coordinates(mm)[0] array([-2.5875, -1.4375, 0. ]) >>> ArgusII().electrode_array.coordinates(electrodes=['F10', 'A1']) array([[ 2587.5, 1437.5, 0. ], [-2587.5, -1437.5, 0. ]])
- property electrode_names
Return a list of all electrode names in the array
- property electrode_objects
Return a list of all electrode objects in the array
- property electrodes
Return all electrode names and objects in the electrode array
Internally, electrodes are stored in an ordered dictionary. You can iterate over different electrodes in the array as follows:
for name, electrode in electrode_array.electrodes.items(): print(name, electrode)
You can access an individual electrode by indexing directly into the electrode array object, e.g.
electrode_array['A1']orelectrode_array[0].
- plot(annotate=False, autoscale=True, ax=None, color_stim=None, cmap='OrRd')[source]
Plot the electrode array in its own coordinate frame
- Parameters:
annotate (bool, optional) – Flag whether to label electrodes in the implant.
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot to fit the implant
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None, will either use the current axes (if exists) or create a new Axes object.
color_stim (
pulse2percept.stimuli.Stimulus, or None) – If provided, colors the electrode_array based on the stimulus amplitudes. A multi-patch electrode (e.g.,PhotovoltaicPixel) colors only its last patch; earlier patches are structural.cmap (str) – Matplotlib colormap to use for stimulus coloring.
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- class pulse2percept.implants.EnsembleImplant(implants, preprocess=False, safe_mode=False)[source]
- classmethod from_visual_field_map(implant_type, visual_field_map, locs=None, xrange=None, yrange=None, step=None, region=None)[source]
Create an ensemble implant from a visual field map.
An implant of type
implant_typeis created for each visual field location specified either bylocsor byxrange,yrangeandstep, and centered at the tissue coordinates the map transforms that location to.The map may be retinal, cortical, or any other 2D
VisualFieldMap. 3D maps are not supported, because placing an implant on a folded surface needs more than the(x, y)anchor this method passes on; seefrom_neuropythy().Added in version 0.11.0: Replaces
from_cortical_map, which knew about cortex specifically.- Parameters:
implant_type (type) – Type of implant to create for the ensemble. Must subclass p2p.implants.Implant
visual_field_map (
VisualFieldMap) – Visual field map to create the implant from.locs (np.ndarray with shape (n, 2), optional) – Array of visual field locations to create implants at (dva). Not needed if using xrange, yrange, and step.
xrange (tuple of floats, optional) – Range of x and y coordinates (dva) to create implants at.
yrange (tuple of floats, optional) – Range of x and y coordinates (dva) to create implants at.
step (float or (x_step, y_step), optional) – Spacing (dva) between implant centers.
region (str, optional) – Region of tissue to create the implant in, e.g.
'ret'or'v1'. Required unless the map has exactly one region.
- Returns:
ensemble – Ensemble implant created from the visual field map.
- Return type:
p2p.implants.EnsembleImplant
Notes
These are visual field coordinates, so they may be given as plain numbers of degrees or as unitful quantities (e.g.
xrange=(-3 * dva, 3 * dva)). Contrastfrom_coords(), which places implants by their physical position in microns. Seepulse2percept.units.
- classmethod from_coords(implant_type, locs=None, xrange=None, yrange=None, step=None)[source]
Create an ensemble implant using physical (cortical or retinal) coordinates.
- Parameters:
implant_type (type) – The type of implant to create for the ensemble.
locs (np.ndarray with shape (n, 2), optional) – Array of physical locations (um) to create implants at. Not needed if using xrange, yrange, and step.
xrange (tuple of floats, optional) – Range of x and y coordinates (um) to create implants at. Required (together with
step) iflocsis not given.yrange (tuple of floats, optional) – Range of x and y coordinates (um) to create implants at. Required (together with
step) iflocsis not given.step (float or (x_step, y_step), optional) – Spacing (um) between implant centers.
- Raises:
ValueError – If neither
locsnor all three ofxrange,yrangeandstepare given.
Notes
Lengths may be given as plain numbers of microns or as unitful quantities (e.g.
xrange=(-1 * mm, 1 * mm)). Seepulse2percept.units.
Changed in version 0.10.0: The grid arguments no longer have defaults. They used to fall back on
(-3, 3)and1, which are the degrees of visual anglefrom_visual_field_map()works in; here they are microns, so the default laid every implant out inside a 6 um square.
- property implants
Dict of implants
- prepare_stim(source)[source]
Prepare stimulation for an ensemble implant.
sourcemay address the combined electrode array directly, or be a dict keyed by constituent implant keys. Per-implant sources are prepared by each constituent implant, merged, then passed through ensemble-level preprocessing and safety checks. Missing implant keys contribute zeros.Changed in version 0.11.0: Replaces
merge_stimuliand the stimuli previously stored on constituent implants.- Parameters:
source (dict or
Stimulussource type) – One source for the whole ensemble, or{implant_key: source}.- Returns:
stim – Merged stimulation for the ensemble.
- Return type:
Stimulusor None
Examples
>>> import numpy as np >>> from pulse2percept.implants import EnsembleImplant >>> from pulse2percept.implants.cortex import Orion >>> ensemble = EnsembleImplant.from_coords( ... Orion, locs=np.array([(0, 0), (-35000, 0)])) >>> ensemble.prepare_stim({0: np.ones(60), ... 1: 2 * np.ones(60)}).data.shape (120, 1)
- check_stim(stim)[source]
Quality-check the stimulus
This method is executed every time a stimulus is prepared (see
prepare_stim()).If
safe_modeis set to True, this function will only allow stimuli that are charge-balanced. Ifmax_currentis set, it will only allow stimuli whose total instantaneous current stays within it.Both are questions about electricity, and neither can be answered about a stimulus that is not a current, so each raises a
DimensionMismatchErroron one. In the ordinary flow this cannot happen:prepare_stim()has already checked the stimulus againststimulus_unit.check_stimis public, though, and may be handed anything.The user can define their own checks in implants that inherit from
Implant.- Parameters:
stim (
Stimulussource type) – A valid source type for theStimulusobject (e.g., scalar, NumPy array, pulse train).- Raises:
DimensionMismatchError – If an electrical check was requested and
stimis not measured in units of current... versionchanged: – 0.10.0: The electrical checks verify that the stimulus really is electrical, instead of reading whatever numbers it holds as microamps.
- property electrode_array
Electrode array
- property electrode_names
Return a list of all electrode names in the electrode array
- property electrode_objects
Return a list of all electrode objects in the array
- property electrodes
Return all electrode names and objects in the electrode array
Internally, electrodes are stored in an ordered dictionary. You can iterate over different electrodes in the array as follows:
for name, electrode in implant.electrodes.items(): print(name, electrode)
You can access an individual electrode by indexing directly into the implant, e.g.
implant['A1']orimplant[0], and ask how many there are withlen(implant).
- property encoder
Stimulus encoder used for image or video input.
Must be an
ImplantEncoder. Model-aware encoders such asTraceEncoderare called directly instead. If None, dimensionless image/video stimuli are not encoded automatically.Assigning an unbound encoder (
encoder.implant is None) binds it to this implant. An encoder bound to a different implant is rejected with a ValueError.
- family = None
Named device family, if applicable, e.g.
'PRIMA'. .. versionadded:: 0.11.0
- property max_current
Total instantaneous current (uA) the stimulator can source
- property n_electrodes
Number of electrodes in the array
This is equivalent to calling
electrode_array.n_electrodes.
- placement = None
Where the device sits relative to the tissue it stimulates, where the literature is unambiguous about it; None where it is not, or where the class describes a family rather than a device.
- plot(annotate=False, autoscale=True, ax=None, stim=None, stim_cmap=False)[source]
Plot the device in its local coordinate frame.
Use
model.plot(show_implant=True)to show model-side placement.- Parameters:
annotate (bool, optional) – Whether to label electrodes.
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot to fit the implant
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None, will either use the current axes (if exists) or create a new Axes object.
stim (
Stimulussource type, optional) –What is presented to the device. Prepared through
prepare_stim(), so the colors show what the electrodes actually deliver. Required bystim_cmap.Added in version 0.11.0.
stim_cmap (bool, str, or matplotlib colormap, optional) – If not false, the fill color of the plotted electrodes will vary based on maximum stimulus amplitude on each electrode. The chosen colormap will be used if provided
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- preprocess_stim(stim)[source]
Preprocess the stimulus
This method is executed every time a stimulus is prepared.
No preprocessing is performed by default, but the user can define their own method in implants that inherit from return stim
Implant.A custom method must return a
Stimulusobject with the correct number of electrodes for the implant.
- property raster
Raster pattern used to schedule stimulation across electrodes.
Assigning a raster binds it to this implant.
- property scene_input_frame
Coordinate frame used to register scene input.
'eye'means gaze changes which scene content reaches the implant;'head'means scene input is fixed relative to the head.Defaults to
default_scene_input_frame. Setting toNonerestores that default.Added in version 0.11.0.
- technology = None
Stimulation technology, e.g.
'photovoltaic'. .. versionadded:: 0.11.0
- property thresholds
Perceptual threshold current (uA) for each electrode.
Assign a single current for the whole array, a per-electrode dict, or None to clear the calibration. Threshold-relative pulse trains are calibrated against whatever is in force at the moment
prepare_stim()runs.Added in version 0.10.0.
Changed in version 0.11.0: Changing thresholds affects the next stimulus prepared, rather than rewriting one the implant was holding.
- class pulse2percept.implants.GridImplant(shape, spacing, x=0, y=0, z=0, rot=0, names=('A', '1'), grid_type='rect', orientation='horizontal', electrode_type=<class 'pulse2percept.implants.electrodes.PointSource'>, preprocess=False, safe_mode=False, encoder=None, raster=None, max_current=None, scene_input_frame=None, **electrode_params)[source]
A prosthesis system whose electrodes form a regular grid
Convenience composition of an
ElectrodeGridand aImplant, for the common case where a custom implant is just a grid of electrodes:implant = GridImplant(shape=(10, 10), spacing=500)
is the same thing as:
implant = Implant(ElectrodeGrid(shape=(10, 10), spacing=500))
Anatomy-neutral, like
Implant: for a grid with a stimulation target, hand theElectrodeGridtoRetinalImplantorCorticalImplantinstead.Added in version 0.11.0.
- Parameters:
shape ((rows, cols)) – The number of rows x columns in the grid.
spacing (double or (x_spacing, y_spacing)) – Electrode-to-electrode spacing (um).
x/y/z (double, optional) – Location (um) of the center of the grid in the implant’s own frame.
rot (double, optional) – Rotation of the grid in degrees (positive angle: counter-clockwise).
names ((name_rows, name_cols), optional) – Naming convention for rows and columns; see
ElectrodeGrid.grid_type ({'rect', 'hex'}, optional) – Grid type (‘rect’: rectangular, ‘hex’: hexagonal).
orientation ({'horizontal', 'vertical'}, optional) – Which way a hex grid staggers; see
ElectrodeGrid.electrode_type (
Electrode, optional) – A valid Electrode class.preprocess (bool or callable, optional) – Whether to preprocess a stimulus whenever one is prepared.
safe_mode (bool, optional) – Whether to enforce charge balance.
encoder (
ImplantEncoder, optional) – How the device turns a picture into stimulation.raster (
Raster, optional) – How the stimulator takes turns between electrodes.max_current (float, optional) – The total current (uA) the stimulator can source at any one instant.
**electrode_params – Keyword arguments passed to the
electrode_typeconstructor, such asradiusforDiskElectrode; seeElectrodeGrid.
Examples
A 10x10 grid of point sources, 500um apart:
>>> from pulse2percept.implants import GridImplant >>> from pulse2percept.units import um >>> implant = GridImplant(shape=(10, 10), spacing=500 * um) >>> implant.n_electrodes 100
A hex grid of 75um disk electrodes:
>>> from pulse2percept.implants import DiskElectrode, GridImplant >>> from pulse2percept.units import um >>> implant = GridImplant(shape=(20, 20), spacing=400 * um, ... grid_type='hex', electrode_type=DiskElectrode, ... radius=75 * um) >>> implant['A1'] DiskElectrode(activated=True, name='A1', radius=75.0, x=-3700.0, y=-3290.89..., z=0...)
- check_stim(stim)[source]
Quality-check the stimulus
This method is executed every time a stimulus is prepared (see
prepare_stim()).If
safe_modeis set to True, this function will only allow stimuli that are charge-balanced. Ifmax_currentis set, it will only allow stimuli whose total instantaneous current stays within it.Both are questions about electricity, and neither can be answered about a stimulus that is not a current, so each raises a
DimensionMismatchErroron one. In the ordinary flow this cannot happen:prepare_stim()has already checked the stimulus againststimulus_unit.check_stimis public, though, and may be handed anything.The user can define their own checks in implants that inherit from
Implant.- Parameters:
stim (
Stimulussource type) – A valid source type for theStimulusobject (e.g., scalar, NumPy array, pulse train).- Raises:
DimensionMismatchError – If an electrical check was requested and
stimis not measured in units of current... versionchanged: – 0.10.0: The electrical checks verify that the stimulus really is electrical, instead of reading whatever numbers it holds as microamps.
- property electrode_array
Electrode array
- property electrode_names
Return a list of all electrode names in the electrode array
- property electrode_objects
Return a list of all electrode objects in the array
- property electrodes
Return all electrode names and objects in the electrode array
Internally, electrodes are stored in an ordered dictionary. You can iterate over different electrodes in the array as follows:
for name, electrode in implant.electrodes.items(): print(name, electrode)
You can access an individual electrode by indexing directly into the implant, e.g.
implant['A1']orimplant[0], and ask how many there are withlen(implant).
- property encoder
Stimulus encoder used for image or video input.
Must be an
ImplantEncoder. Model-aware encoders such asTraceEncoderare called directly instead. If None, dimensionless image/video stimuli are not encoded automatically.Assigning an unbound encoder (
encoder.implant is None) binds it to this implant. An encoder bound to a different implant is rejected with a ValueError.
- family = None
Named device family, if applicable, e.g.
'PRIMA'. .. versionadded:: 0.11.0
- property max_current
Total instantaneous current (uA) the stimulator can source
- property n_electrodes
Number of electrodes in the array
This is equivalent to calling
electrode_array.n_electrodes.
- placement = None
Where the device sits relative to the tissue it stimulates, where the literature is unambiguous about it; None where it is not, or where the class describes a family rather than a device.
- plot(annotate=False, autoscale=True, ax=None, stim=None, stim_cmap=False)[source]
Plot the device in its local coordinate frame.
Use
model.plot(show_implant=True)to show model-side placement.- Parameters:
annotate (bool, optional) – Whether to label electrodes.
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot to fit the implant
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None, will either use the current axes (if exists) or create a new Axes object.
stim (
Stimulussource type, optional) –What is presented to the device. Prepared through
prepare_stim(), so the colors show what the electrodes actually deliver. Required bystim_cmap.Added in version 0.11.0.
stim_cmap (bool, str, or matplotlib colormap, optional) – If not false, the fill color of the plotted electrodes will vary based on maximum stimulus amplitude on each electrode. The chosen colormap will be used if provided
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- prepare_stim(source)[source]
Turn a source into stimulation the implant can deliver.
Preparation applies preprocessing, converts the source to a
Stimulus, encodes dimensionless visual input when an encoder is present, reshapes it to the electrode array, removes deactivated electrodes, applies threshold calibration, and runs safety checks. The input is not modified and the result is not stored.Prepared stimuli use the implant’s
stimulus_unit(electrical current for most devices; irradiance for PRIMA).Images and videos require an encoder unless preprocessing already converts them to the implant’s
stimulus_unit.Added in version 0.11.0: Replaces the stateful
stimproperty.- Parameters:
source (
Stimulussource type) – Any source accepted byStimulus, including electrical stimulation and image or video input for the implant encoder.- Returns:
stim – Stimulation delivered by the implant, or None for an empty source.
- Return type:
Stimulusor None
Examples
>>> from pulse2percept.implants import DiskElectrode, Implant >>> from pulse2percept.stimuli import BiphasicPulse >>> implant = Implant(DiskElectrode(0, 0, 0, 100)) >>> stim = implant.prepare_stim(BiphasicPulse(30, 0.45))
Stimulate Electrode B7 in Argus II with 13 uA:
>>> from pulse2percept.implants.retina import ArgusII >>> stim = ArgusII().prepare_stim({'B7': 13})
Argus II includes an encoder, so it can prepare an image directly:
>>> from pulse2percept.stimuli import samples >>> ArgusII().prepare_stim(samples.logo_bvl()).unit uA
- preprocess_stim(stim)[source]
Preprocess the stimulus
This method is executed every time a stimulus is prepared.
No preprocessing is performed by default, but the user can define their own method in implants that inherit from return stim
Implant.A custom method must return a
Stimulusobject with the correct number of electrodes for the implant.
- property raster
Raster pattern used to schedule stimulation across electrodes.
Assigning a raster binds it to this implant.
- property scene_input_frame
Coordinate frame used to register scene input.
'eye'means gaze changes which scene content reaches the implant;'head'means scene input is fixed relative to the head.Defaults to
default_scene_input_frame. Setting toNonerestores that default.Added in version 0.11.0.
- technology = None
Stimulation technology, e.g.
'photovoltaic'. .. versionadded:: 0.11.0
- property thresholds
Perceptual threshold current (uA) for each electrode.
Assign a single current for the whole array, a per-electrode dict, or None to clear the calibration. Threshold-relative pulse trains are calibrated against whatever is in force at the moment
prepare_stim()runs.Added in version 0.10.0.
Changed in version 0.11.0: Changing thresholds affects the next stimulus prepared, rather than rewriting one the implant was holding.
- class pulse2percept.implants.HexElectrode(x, y, z, apothem, name=None, activated=True, orientation='vertical', rot=0)[source]
Hexagonal electrode
Added in version 0.7.
- Parameters:
x/y/z (double) – Location of the electrode (um) in the array’s own coordinate frame.
apothem (double) – Apothem (um) of the hexagon. The flat-to-flat width is
2 * apothem.name (str, optional) – Electrode name.
activated (bool) – To deactivate, set to
False. Deactivated electrodes cannot receive stimuli.orientation ({'horizontal', 'vertical'}, optional) –
Hexagon orientation. Defaults to
'vertical'.Added in version 0.11.0.
rot (double, optional) –
Rotation angle (deg, positive counter-clockwise).
Added in version 0.11.0.
Notes
Lengths may be given as plain numbers of microns or as unitful quantities. See
pulse2percept.units.
- property width
Flat-to-flat width (um) of the hexagon
Added in version 0.11.0.
- coordinate_unit = um[source]
The unit electrode coordinates are stored in. Electrodes hold plain numbers, which is what every kernel downstream of them expects; this says what those numbers mean.
- coordinates(unit=None)[source]
3D position of the electrode
Added in version 0.10.0.
- Parameters:
unit (
Unit, optional) – Length unit to express the position in. If None, the position is returned as it is stored (microns).- Returns:
coords – An ordinary NumPy array
[x, y, z], never aQuantity.- Return type:
(3,) np.ndarray
Examples
>>> from pulse2percept.implants import DiskElectrode >>> from pulse2percept.units import mm >>> DiskElectrode(1000, 0, 100, 200).coordinates(mm) array([1. , 0. , 0.1])
- plot(autoscale=False, ax=None)[source]
Plot
- Parameters:
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None given, a new one will be created.
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- class pulse2percept.implants.Implant(electrode_array, preprocess=False, safe_mode=False, encoder=None, raster=None, max_current=None, thresholds=None, scene_input_frame=None)[source]
Visual prosthesis
A visual prosthesis describes an electrode array together with the input pipeline that turns what is presented to the device into the stimulation its electrodes deliver (see
prepare_stim()). This is the base class for implants such asArgusIIandOrion.The generic base carries no anatomical laterality. Use
RetinalImplant(eye) orCorticalImplant(hemisphere) for a device with a stimulation target.Added in version 0.6.
Changed in version 0.11.0: Renamed from
ProsthesisSystem, which stays available as a deprecated alias until 0.12.0.Changed in version 0.11.0: No longer takes
eye, which moved toRetinalImplant.Changed in version 0.11.0: An implant no longer stores a stimulus.
implant.stim = sourcebecamedelivered = implant.prepare_stim(source), and a model is given the source rather than the implant (seepredict_percept()).- Parameters:
electrode_array (
ElectrodeArrayor) –ElectrodeThe electrode array used to deliver stimuli to the target tissue.preprocess (bool or callable, optional) – Either True/False to indicate whether to execute the implant’s default preprocessing method whenever a stimulus is prepared, or a custom function (callable).
safe_mode (bool, optional) – If safe mode is enabled, only charge-balanced stimuli are allowed. Charge balance is an electrical property and requires current units. Non-current-driven devices may override this check.
encoder (
ImplantEncoder, optional) –Maps image or video gray levels to device stimulation. If None, dimensionless visual input is rejected. An unbound encoder is bound to this implant (see
encoder).Added in version 0.10.0.
Changed in version 0.11.0: Accepts any
ImplantEncoder, not only an electricalPulseEncoder.raster (
Raster, optional) –How the stimulator takes turns between electrodes that it cannot drive at the same time. If None, every electrode may fire at once. Assigning one binds it to this implant (see
bind()), and it is the raster theencoderschedules against.Added in version 0.10.0.
max_current (float, optional) –
The total current (uA) the stimulator can source at any one instant, summed over all electrodes. If given, preparing a stimulus that exceeds it raises. If None, no such check is performed.
May be given as a plain number of microamps or as a unitful quantity (e.g.
0.1 * mA); seepulse2percept.units.Added in version 0.10.0.
scene_input_frame ('eye' or 'head', optional) –
How gaze registers a scene onto this system, overriding what the device class does, e.g.
'eye'for an Argus II run with eye tracking. Seescene_input_frame.Added in version 0.11.0.
thresholds (float, Quantity, or dict, optional) –
Perceptual threshold current (uA) used to calibrate threshold-relative (
xTh) stimuli. A scalar applies to every electrode; a dict calibrates the named electrodes only. Seethresholds.Added in version 0.11.0.
Examples
A system made from a single
DiskElectrodewith radius radius=100um sitting at x=200um, y=-50um, z=10um:>>> from pulse2percept.implants import DiskElectrode, Implant >>> implant = Implant(DiskElectrode(200, -50, 10, 100))
- placement = None
Where the device sits relative to the tissue it stimulates, where the literature is unambiguous about it; None where it is not, or where the class describes a family rather than a device.
- technology = None
Stimulation technology, e.g.
'photovoltaic'. .. versionadded:: 0.11.0
- family = None
Named device family, if applicable, e.g.
'PRIMA'. .. versionadded:: 0.11.0
- property scene_input_frame
Coordinate frame used to register scene input.
'eye'means gaze changes which scene content reaches the implant;'head'means scene input is fixed relative to the head.Defaults to
default_scene_input_frame. Setting toNonerestores that default.Added in version 0.11.0.
- property encoder
Stimulus encoder used for image or video input.
Must be an
ImplantEncoder. Model-aware encoders such asTraceEncoderare called directly instead. If None, dimensionless image/video stimuli are not encoded automatically.Assigning an unbound encoder (
encoder.implant is None) binds it to this implant. An encoder bound to a different implant is rejected with a ValueError.
- property raster
Raster pattern used to schedule stimulation across electrodes.
Assigning a raster binds it to this implant.
- property max_current
Total instantaneous current (uA) the stimulator can source
- property thresholds
Perceptual threshold current (uA) for each electrode.
Assign a single current for the whole array, a per-electrode dict, or None to clear the calibration. Threshold-relative pulse trains are calibrated against whatever is in force at the moment
prepare_stim()runs.Added in version 0.10.0.
Changed in version 0.11.0: Changing thresholds affects the next stimulus prepared, rather than rewriting one the implant was holding.
- check_stim(stim)[source]
Quality-check the stimulus
This method is executed every time a stimulus is prepared (see
prepare_stim()).If
safe_modeis set to True, this function will only allow stimuli that are charge-balanced. Ifmax_currentis set, it will only allow stimuli whose total instantaneous current stays within it.Both are questions about electricity, and neither can be answered about a stimulus that is not a current, so each raises a
DimensionMismatchErroron one. In the ordinary flow this cannot happen:prepare_stim()has already checked the stimulus againststimulus_unit.check_stimis public, though, and may be handed anything.The user can define their own checks in implants that inherit from
Implant.- Parameters:
stim (
Stimulussource type) – A valid source type for theStimulusobject (e.g., scalar, NumPy array, pulse train).- Raises:
DimensionMismatchError – If an electrical check was requested and
stimis not measured in units of current... versionchanged: – 0.10.0: The electrical checks verify that the stimulus really is electrical, instead of reading whatever numbers it holds as microamps.
- preprocess_stim(stim)[source]
Preprocess the stimulus
This method is executed every time a stimulus is prepared.
No preprocessing is performed by default, but the user can define their own method in implants that inherit from return stim
Implant.A custom method must return a
Stimulusobject with the correct number of electrodes for the implant.
- plot(annotate=False, autoscale=True, ax=None, stim=None, stim_cmap=False)[source]
Plot the device in its local coordinate frame.
Use
model.plot(show_implant=True)to show model-side placement.- Parameters:
annotate (bool, optional) – Whether to label electrodes.
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot to fit the implant
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None, will either use the current axes (if exists) or create a new Axes object.
stim (
Stimulussource type, optional) –What is presented to the device. Prepared through
prepare_stim(), so the colors show what the electrodes actually deliver. Required bystim_cmap.Added in version 0.11.0.
stim_cmap (bool, str, or matplotlib colormap, optional) – If not false, the fill color of the plotted electrodes will vary based on maximum stimulus amplitude on each electrode. The chosen colormap will be used if provided
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- property electrode_array
Electrode array
- prepare_stim(source)[source]
Turn a source into stimulation the implant can deliver.
Preparation applies preprocessing, converts the source to a
Stimulus, encodes dimensionless visual input when an encoder is present, reshapes it to the electrode array, removes deactivated electrodes, applies threshold calibration, and runs safety checks. The input is not modified and the result is not stored.Prepared stimuli use the implant’s
stimulus_unit(electrical current for most devices; irradiance for PRIMA).Images and videos require an encoder unless preprocessing already converts them to the implant’s
stimulus_unit.Added in version 0.11.0: Replaces the stateful
stimproperty.- Parameters:
source (
Stimulussource type) – Any source accepted byStimulus, including electrical stimulation and image or video input for the implant encoder.- Returns:
stim – Stimulation delivered by the implant, or None for an empty source.
- Return type:
Stimulusor None
Examples
>>> from pulse2percept.implants import DiskElectrode, Implant >>> from pulse2percept.stimuli import BiphasicPulse >>> implant = Implant(DiskElectrode(0, 0, 0, 100)) >>> stim = implant.prepare_stim(BiphasicPulse(30, 0.45))
Stimulate Electrode B7 in Argus II with 13 uA:
>>> from pulse2percept.implants.retina import ArgusII >>> stim = ArgusII().prepare_stim({'B7': 13})
Argus II includes an encoder, so it can prepare an image directly:
>>> from pulse2percept.stimuli import samples >>> ArgusII().prepare_stim(samples.logo_bvl()).unit uA
- property n_electrodes
Number of electrodes in the array
This is equivalent to calling
electrode_array.n_electrodes.
- property electrodes
Return all electrode names and objects in the electrode array
Internally, electrodes are stored in an ordered dictionary. You can iterate over different electrodes in the array as follows:
for name, electrode in implant.electrodes.items(): print(name, electrode)
You can access an individual electrode by indexing directly into the implant, e.g.
implant['A1']orimplant[0], and ask how many there are withlen(implant).
- property electrode_names
Return a list of all electrode names in the electrode array
- property electrode_objects
Return a list of all electrode objects in the array
- class pulse2percept.implants.PointSource(x, y, z, name=None, activated=True)[source]
Idealized current point source
- Parameters:
- electric_potential(x, y, z, amp, sigma)[source]
Calculate electric potential at (x, y, z)
- Parameters:
x/y/z (double) – 3D location (um) at which to evaluate the electric potential. May be given as a unitful quantity, e.g.
0.2 * mm.amp (double) – amplitude of the constant current pulse
sigma (double) – resistivity of the extracellular solution
- Returns:
pot (double) – The electric potential at (x, y, z)
The electric potential \(V(r)\) of a point source is given by
.. math:: – V(r) = frac{sigma I}{4 pi r},
where \(\sigma\) is the resistivity of the extracellular solution
(typically Ames medium, \(\sigma = 110 \Ohm cm\)),
\(I\) is the amplitude of the constant current pulse,
and \(r\) is the distance from the stimulating electrode to the
point at which the voltage is being computed.
- coordinate_unit = um[source]
The unit electrode coordinates are stored in. Electrodes hold plain numbers, which is what every kernel downstream of them expects; this says what those numbers mean.
- coordinates(unit=None)[source]
3D position of the electrode
Added in version 0.10.0.
- Parameters:
unit (
Unit, optional) – Length unit to express the position in. If None, the position is returned as it is stored (microns).- Returns:
coords – An ordinary NumPy array
[x, y, z], never aQuantity.- Return type:
(3,) np.ndarray
Examples
>>> from pulse2percept.implants import DiskElectrode >>> from pulse2percept.units import mm >>> DiskElectrode(1000, 0, 100, 200).coordinates(mm) array([1. , 0. , 0.1])
- plot(autoscale=False, ax=None)[source]
Plot
- Parameters:
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None given, a new one will be created.
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes
- class pulse2percept.implants.Raster(group_dur=None)[source]
Abstract base class for raster patterns.
A raster partitions electrodes into groups that take turns stimulating. Different groups must not be active at the same time. Raster timing is applied by
PulseEncoder.Assigning a raster to
implant.rasterbinds it to that implant. Subclasses implementgroups()and may overridebind()when the grouping depends on electrode geometry.Added in version 0.10.0.
- Parameters:
group_dur (float, optional) – Duration of one group’s slot (ms). If None, groups divide the shortest pulse period evenly. An explicit value fixes the raster sweep to
n_groups * group_dur.
- property implant
The implant this raster is bound to, or None
- bind(implant)[source]
Bind the raster to an implant or electrode array.
Geometry-dependent rasters may override this method to recompute their grouping.
- Parameters:
implant (
Implantor ) –ElectrodeArrayImplant or electrode array to bind.- Returns:
self
- Return type:
- abstract property n_groups
Number of raster groups
- abstractmethod groups(electrodes)[source]
Assign each electrode to a raster group
- Parameters:
electrodes (array_like) – Electrode names, in the order they appear in the stimulus.
- Returns:
group – The group each electrode belongs to, in
0..n_groups-1.- Return type:
(n_electrodes,)int array
- members(electrodes, group)[source]
Return the electrodes in one raster group.
- Parameters:
electrodes (array_like) – Electrode names.
group (int) – Group index in
0..n_groups-1.
- Returns:
members – Electrode names belonging to
group.- Return type:
array
- plot(implant=None, annotate=None, ax=None, cmap='viridis', autoscale=True)[source]
Plot electrodes colored by raster group.
- Parameters:
implant (
Implant, optional) – Implant to draw. If None, use the bound implant.annotate (bool, optional) – Write group indices on electrodes. If None, annotate arrays with at most 120 electrodes.
ax (matplotlib.axes.Axes, optional) – Axes to draw on.
cmap (str, optional) – Matplotlib colormap.
autoscale (bool, optional) – Fit the axes to the implant.
- Returns:
ax – The axes drawn on.
- Return type:
- offsets(electrodes, period)[source]
How far behind group 0 each electrode’s slot begins
- Parameters:
electrodes (array_like) – Electrode names, in the order they appear in the stimulus.
period (float) – The pulse period (ms) a sweep has to fit into.
- Returns:
offset – Time (ms) between the start of a sweep and the start of this electrode’s slot.
- Return type:
(n_electrodes,)float array
- class pulse2percept.implants.SequentialRaster(n_groups, interleave=False, group_dur=None)[source]
Split electrodes into groups that fire one after another
Electrodes are assigned to groups by their position in the stimulus, which for an
ElectrodeGridruns row by row. So on a 6x10 array such asArgusII,SequentialRaster(6)puts each row in its own group – a line raster.Added in version 0.10.0.
- Parameters:
n_groups (int) – Number of groups to split the electrodes into.
interleave (bool, optional) – If False (the default), each group is a contiguous block of electrodes. If True, groups are interleaved, so that consecutive electrodes end up in different groups. Interleaving spreads each group’s current further across the array.
Examples
A line raster for Argus II, one row of ten electrodes at a time:
>>> from pulse2percept.implants import SequentialRaster >>> from pulse2percept.implants.retina import ArgusII >>> implant = ArgusII() >>> implant.raster = SequentialRaster(6)
- property n_groups
Number of raster groups
- bind(implant)[source]
Bind the raster to an implant or electrode array.
Geometry-dependent rasters may override this method to recompute their grouping.
- Parameters:
implant (
Implantor ) –ElectrodeArrayImplant or electrode array to bind.- Returns:
self
- Return type:
- property implant
The implant this raster is bound to, or None
- members(electrodes, group)[source]
Return the electrodes in one raster group.
- Parameters:
electrodes (array_like) – Electrode names.
group (int) – Group index in
0..n_groups-1.
- Returns:
members – Electrode names belonging to
group.- Return type:
array
- offsets(electrodes, period)[source]
How far behind group 0 each electrode’s slot begins
- Parameters:
electrodes (array_like) – Electrode names, in the order they appear in the stimulus.
period (float) – The pulse period (ms) a sweep has to fit into.
- Returns:
offset – Time (ms) between the start of a sweep and the start of this electrode’s slot.
- Return type:
(n_electrodes,)float array
- plot(implant=None, annotate=None, ax=None, cmap='viridis', autoscale=True)[source]
Plot electrodes colored by raster group.
- Parameters:
implant (
Implant, optional) – Implant to draw. If None, use the bound implant.annotate (bool, optional) – Write group indices on electrodes. If None, annotate arrays with at most 120 electrodes.
ax (matplotlib.axes.Axes, optional) – Axes to draw on.
cmap (str, optional) – Matplotlib colormap.
autoscale (bool, optional) – Fit the axes to the implant.
- Returns:
ax – The axes drawn on.
- Return type:
- class pulse2percept.implants.SquareElectrode(x, y, z, side_length, name=None, activated=True)[source]
Square electrode
Added in version 0.7.
- Parameters:
Notes
Lengths may be given as plain numbers of microns or as unitful quantities (e.g.
50 * um). Seepulse2percept.units.
- coordinate_unit = um[source]
The unit electrode coordinates are stored in. Electrodes hold plain numbers, which is what every kernel downstream of them expects; this says what those numbers mean.
- coordinates(unit=None)[source]
3D position of the electrode
Added in version 0.10.0.
- Parameters:
unit (
Unit, optional) – Length unit to express the position in. If None, the position is returned as it is stored (microns).- Returns:
coords – An ordinary NumPy array
[x, y, z], never aQuantity.- Return type:
(3,) np.ndarray
Examples
>>> from pulse2percept.implants import DiskElectrode >>> from pulse2percept.units import mm >>> DiskElectrode(1000, 0, 100, 200).coordinates(mm) array([1. , 0. , 0.1])
- plot(autoscale=False, ax=None)[source]
Plot
- Parameters:
autoscale (bool, optional) – Whether to adjust the x,y limits of the plot
ax (matplotlib.axes._subplots.AxesSubplot, optional) – A Matplotlib axes object. If None given, a new one will be created.
- Returns:
ax – Returns the axis object of the plot
- Return type:
matplotlib.axes.Axes