pulse2percept.stimuli.names

ElectrodeNames

Classes

ElectrodeNames(grid_shape[, idx, unique])

Lazily generated electrode names for a grid of electrodes

class pulse2percept.stimuli.names.ElectrodeNames(grid_shape, idx=None, unique=None)[source]

Lazily generated electrode names for a grid of electrodes

Names every element of a (rows x columns [x channels]) grid after its position in that grid: letters address the row, digits the column, and an optional suffix the color channel. The first pixel of an RGB image is therefore 'A1_R', and the pixel in the third row and twelfth column of a grayscale image is 'C12'.

The names are not stored. Only the shape of the grid is, plus (for a subset such as a cropped image) the indices that were kept. Both directions of the mapping are computed from that: a name is generated from its index on demand, and the index of a name is recovered by parsing it. That keeps construction, copying and lookup independent of the number of electrodes, which matters because an image or video stimulus assigns one electrode per pixel – a 576x720 RGBA image has 1.66 million of them.

An ElectrodeNames behaves like a read-only 1-D array of strings: it supports len, iteration, indexing, slicing, boolean masking, reshape and ravel, and converts to a NumPy array of strings via np.asarray. That conversion is the one operation whose cost scales with the number of electrodes, so it is left to the caller to trigger.

Added in version 0.10.0.

Parameters:
  • grid_shape (tuple) – Shape of the electrode grid: (rows, cols) for a single-channel image, or (rows, cols, channels) for a multi-channel one.

  • idx (array_like, optional) – Flat indices into the grid, selecting (and ordering) the names to expose. The array may have any shape; None means the whole grid in row-major order.

  • unique (bool, optional) – Whether idx is known to be free of duplicates. None means “not known”, in which case check_unique() will work it out.

Examples

>>> from pulse2percept.stimuli import ElectrodeNames
>>> names = ElectrodeNames((3, 4))
>>> names[0], names[6]
('A1', 'B3')
>>> names.index('B3')
6
property grid_shape

Shape of the underlying electrode grid

property grid_size

Total number of electrodes in the underlying grid

property indices

Flat indices into the grid, one per name

property shape

Shape of the name container

property size

Total number of names

property ndim

Number of dimensions of the name container

property dtype

Dtype the names would have if materialized

property is_unique

Whether the names are known to be free of duplicates

False means “not known to be unique”, not “known to contain duplicates”; call check_unique() to settle it.

reshape(*shape)[source]

Return a view of the names with a new shape

ravel()[source]

Return a flattened view of the names

copy()[source]

Return an independent copy

tolist()[source]

Return the names as a list of strings

index(name)[source]

Return the position of name

Unlike list(names).index(name), this does not build (or even generate) the names: the position is recovered by parsing the name itself, which is why it costs the same for one electrode as for a million.

Parameters:

name (str) – An electrode name, e.g. 'C12' or 'A1_R'.

Returns:

index – Position of name in the (flattened) sequence of names.

Return type:

int

check_unique()[source]

Determine (and remember) whether the names are free of duplicates

The grid names are unique by construction, so duplicates can only come from a repeated index. Checking the indices is therefore equivalent to checking the names, and much cheaper.

Returns:

unique – True if no name occurs twice.

Return type:

bool