pulse2percept.models.base

BaseModel, Model, NotBuiltError, SpatialModel, TemporalModel

Classes

BaseModel(**params)

Abstract base class for all models

Model([spatial, temporal])

Computational model

SpatialModel(**params)

Abstract base class for all spatial models

TemporalModel(**params)

Abstract base class for all temporal models

Exceptions

NotBuiltError

Exception class used to raise if model is used before building

exception pulse2percept.models.base.NotBuiltError[source]

Exception class used to raise if model is used before building

This class inherits from both ValueError and AttributeError to help with exception handling and backward compatibility.

add_note()

Exception.add_note(note) – add a note to the exception

name

attribute name

obj

object

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class pulse2percept.models.base.BaseModel(**params)[source]

Abstract base class for all models

Adds the build workflow on top of Parametrized, which supplies the parameter, pretty-printing, equality and deep-copy machinery:

  • Build a model (via build) and flip the is_built switch

Changed in version 0.10.0: Everything other than the build workflow moved to Parametrized.

stimulus_unit = uA[source]

The unit stimulus values are expressed in

space_unit = um[source]

The unit spatial coordinates are expressed in

time_unit = ms[source]

The unit time is expressed in

build(**build_params)[source]

Build the model

Every model must have a `build method, which is meant to perform all expensive one-time calculations. You must call build before calling predict_percept.

Important

Don’t override this method if you are building your own model. Customize _build instead.

Parameters:

build_params (additional parameters to set) – You can overwrite parameters that are listed in get_default_params. Trying to add new class attributes outside of that will cause a FreezeError. Example: model.build(param1=val)

property is_built

A flag indicating whether the model has been built

abstract get_default_params()[source]

Return a dict of user-settable parameters

get_param_units()[source]

Return a dict of the units that parameters are stored in

Maps a parameter name to the Unit that the implementation assumes it is expressed in. A Quantity assigned to such a parameter is checked against that unit and rescaled to it, so that

FadingTemporal(tau=100)
FadingTemporal(tau=100 * ms)
FadingTemporal(tau=0.1 * s)

all store the same float. Bare numbers keep their documented meaning and are passed through untouched.

Parameters absent from this dict take plain numbers: they are either dimensionless (thresh_percept) or empirical fit parameters whose dimension the implementation does not actually commit to. Declaring a unit is a statement about what the equations assume, so a parameter should only appear here when that is documented or unambiguous.

This dict is not restricted to the names in get_default_params: it describes every physical attribute this object normalizes. A constructor argument assigned straight to selfDefaultSizeModel takes rho that way – belongs here too, and is converted like any other.

Subclasses extend rather than replace it:

def get_param_units(self):
    return {**super().get_param_units(), 'dt': ms, 'tau': ms}

Added in version 0.10.0.

set_params(**params)[source]

Set the parameters of this object

class pulse2percept.models.base.SpatialModel(**params)[source]

Abstract base class for all spatial models

Provides basic functionality for all spatial models:

  • build: builds the spatial grid used to calculate the percept. You can add your own _build method (note the underscore) that performs additional expensive one-time calculations.

  • predict_percept: predicts the percepts based on an implant/stimulus. Don’t customize this method - implement your own _predict_spatial instead (see below). A user must call build before calling predict_percept.

To create your own spatial model, you must subclass SpatialModel and provide an implementation for:

  • _predict_spatial: This method should accept an ElectrodeArray as well as a Stimulus, and compute the brightness at all spatial coordinates of self.grid, returned as a 2D NumPy array (space x time).

    Note

    The _ in the method name indicates that this is a private method, meaning that it should not be called by the user. Instead, the user should call predict_percept, which in turn will call _predict_spatial. The same logic applies to build (called by the user; don’t touch) and _build (called by build; customize this instead).

In addition, you can customize the following:

  • __init__: the constructor can be used to define additional parameters (note that you cannot add parameters on-the-fly)

  • get_default_params: all settable model parameters must be listed by this method

  • _build (optional): a way to add one-time computations to the build process

Added in version 0.6.

Note

You will not be able to add more parameters outside the constructor; e.g., model.newparam = 1 will lead to a FreezeError.

See also

  • Basic Concepts > Computational Models > Building your own model <topics-models-building-your-own>

property n_jobs

n_jobs is an alias for n_threads; see _n_jobs_alias.

xystep[source]

step used to be called xystep. The old name still reads and writes step, with a DeprecationWarning:

get_default_params()[source]

Return a dictionary of default values for all model parameters

get_param_units()[source]

Return a dict of the units that parameters are stored in

build(**build_params)[source]

Build the model

Performs expensive one-time calculations, such as building the spatial grid used to predict a percept. You must call build before calling predict_percept.

Important

Don’t override this method if you are building your own model. Customize _build instead.

Parameters:

build_params (additional parameters to set) – You can overwrite parameters that are listed in get_default_params. Trying to add new class attributes outside of that will cause a FreezeError. Example: model.build(param1=val)

predict_percept(implant, t_percept=None)[source]

Predict the spatial response

Important

Don’t override this method if you are creating your own model. Customize _predict_spatial instead.

Parameters:
  • implant (ProsthesisSystem) – A valid prosthesis system. A stimulus can be passed via stim().

  • t_percept (float or list of floats, optional) – The time points at which to output a percept, counted in this model’s time_unit (milliseconds, for every model p2p ships). If None, implant.stim.time is used. May be given as a unitful quantity (e.g. [0, 20] * ms); see pulse2percept.units.

Returns:

percept – A Percept object whose data container has dimensions Y x X x T, and whose time axis is labelled in time_unit. Will return None if implant.stim is None.

Return type:

Percept

find_threshold(implant, bright_th, amp_range=(0, 999), amp_tol=1, bright_tol=0.1, max_iter=100)[source]

Find the threshold current for a certain stimulus

Estimates amp_th such that the output of model.predict_percept(stim(amp_th)) is approximately bright_th.

Parameters:
  • implant (ProsthesisSystem) – The implant and its stimulus to use. Stimulus amplitude will be up and down regulated until amp_th is found.

  • bright_th (float) – Model output (brightness) that’s considered “at threshold”.

  • amp_range ((amp_lo, amp_hi), optional) – Range of amplitudes to search, counted in this model’s stimulus_unit (microamps, for every model p2p ships).

  • amp_tol (float, optional) – Search will stop if candidate range of amplitudes is within amp_tol, in stimulus_unit

  • bright_tol (float, optional) – Search will stop if model brightness is within bright_tol of bright_th

  • max_iter (int, optional) – Search will stop after max_iter iterations

Returns:

amp_th – Threshold current, in stimulus_unit, estimated so that the output of model.predict_percept(stim(amp_th)) is within bright_tol of bright_th.

Return type:

float

Notes

  • amp_range and amp_tol may be given as unitful quantities (e.g. amp_range=(0, 1 * mA)); the answer comes back as a plain number of microamps. bright_th and bright_tol are model output, which is not a physical quantity and carries no unit. See pulse2percept.units.

plot(use_dva=False, style='hull', autoscale=True, ax=None, figsize=None)[source]

Plot the model

Parameters:
  • use_dva (bool, optional) – Uses degrees of visual angle (dva) if True, else retinal coordinates (microns)

  • style ({'hull', 'scatter', 'cell'}, optional) –

    Grid plotting style:

    • ’hull’: Show the convex hull of the grid (that is, the outline of the smallest convex set that contains all grid points).

    • ’scatter’: Scatter plot all grid points

    • ’cell’: Show the outline of each grid cell as a polygon. Note that this can be costly for a high-resolution grid.

  • 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.

  • figsize ((float, float), optional) – Desired (width, height) of the figure in inches

Returns:

ax – Returns the axis object of the plot

Return type:

matplotlib.axes.Axes

property is_built

A flag indicating whether the model has been built

set_params(**params)[source]

Set the parameters of this object

space_unit = um[source]

The unit spatial coordinates are expressed in

stimulus_unit = uA[source]

The unit stimulus values are expressed in

time_unit = ms[source]

The unit time is expressed in

class pulse2percept.models.base.TemporalModel(**params)[source]

Abstract base class for all temporal models

Provides basic functionality for all temporal models:

  • build: builds the model in order to calculate the percept. You can add your own _build method (note the underscore) that performs additional expensive one-time calculations.

  • predict_percept: predicts the percepts based on an implant/stimulus. You can add your own _predict_temporal method to customize this step. A user must call build before calling predict_percept.

To create your own temporal model, you must subclass SpatialModel and provide an implementation for:

  • _predict_temporal: a method that accepts either a Stimulus or a Percept object and a list of time points at which to calculate the resulting percept, returned as a 2D NumPy array (space x time).

In addition, you can customize the following:

  • __init__: the constructor can be used to define additional parameters (note that you cannot add parameters on-the-fly)

  • get_default_params: all settable model parameters must be listed by this method

  • _build (optional): a way to add one-time computations to the build process

Parameters:
  • dt (float, optional) – Sampling time step of the simulation (ms)

  • thresh_percept (float, optional) – Below threshold, the percept has brightness zero.

  • reduce ({'last', 'peak'}, optional) –

    How a percept time point summarizes the interval since the previous one, when predict_percept picks the output times itself (that is, when t_percept is None). 'last' reports the brightness at the instant the interval ended, which is what every version before 0.10.0 did and what the published models still default to. 'peak' reports the highest brightness reached over the interval.

    Peak is worth reaching for because electrical stimulation is pulsatile: the brightness an interval produces rises and falls within it, so the closing instant says more about where in the pulse cycle it fell than about the interval. Peak rather than mean because what a pulse train produces is a flash, and averaging over the gaps that follow would scale every interval by its duty cycle instead. FadingTemporal defaults to it.

    How exactly it is computed depends on the model. One that sets _reduces_intervals tracks the peak across every dt step inside its own integrator, which is exact at any output rate. Any other model is sampled at several instants per interval instead, which cannot catch a transient shorter than the resulting step; see _FRAME_SUBSAMPLES.

    Naming t_percept overrides this: an explicit time point is a request for that instant, and is always answered with the brightness there.

    Added in version 0.10.0.

  • n_threads (int, optional) – Number of CPU threads to use during parallelization using OpenMP. Defaults to max number of user CPU cores.

  • versionadded: (..) – 0.6:

  • :: (.. seealso) – You will not be able to add more parameters outside the constructor; e.g., model.newparam = 1 will lead to a FreezeError.

  • ::

    • Basic Concepts > Computational Models > Building your own model <topics-models-building-your-own>

property n_jobs

n_jobs is an alias for n_threads; see _n_jobs_alias.

get_default_params()[source]

Return a dictionary of default values for all model parameters

get_param_units()[source]

Return a dict of the units that parameters are stored in

predict_percept(stim, t_percept=None)[source]

Predict the temporal response

Important

Don’t override this method if you are creating your own model. Customize _predict_temporal instead.

Parameters:
  • stim (: py: class: ~pulse2percept.stimuli.Stimulus or) – : py: class: ~pulse2percept.models.Percept Either a Stimulus or a Percept object. The temporal model will be applied to each spatial location in the stimulus/percept.

  • t_percept (float or list of floats, optional) –

    The time points at which to output a percept, counted in this model’s time_unit (milliseconds, for every model p2p ships). May be given as a unitful quantity (e.g. [0, 20] * ms); see pulse2percept.units. If None, the percept will be output once per frame of the video the stimulus was encoded from, or failing that once every 20 ms (50 Hz frame rate), starting at zero and stopping at the last frame boundary the stimulus reaches.

    Note

    A stimulus shorter than a single frame still gets one frame, whose time point therefore falls after the end of the stimulus. That is the only case in which the output runs past the stimulus, and it is what makes a brief pulse visible at all: reporting it only at t=0 would describe it before it had had any effect. Name t_percept to be reported at particular instants instead.

Returns:

percept – A Percept object whose data container has dimensions Y x X x T. Will return None if stim is None.

Return type:

Percept

Notes

  • If a list of time points is provided for t_percept, the values will automatically be sorted.

  • Naming t_percept asks for the brightness at those instants. Leaving it None asks the model to pick the output times, and reduce then says what each point reports about the interval leading up to it – the closing instant, or the peak reached over it.

    The distinction matters because electrical stimulation is pulsatile. A 20 Hz train of 0.46 ms biphasic pulses drives brightness in sub-millisecond transients at a 1.8% duty cycle, so an instant sampled from it is almost always an instant between pulses. Worse, the sampling phase walks: against a 29.97 fps video the frame (33.37 ms) and the pulse period (50 ms) are incommensurate, so which electrodes a frame catches drifts from frame to frame. Under a raster, where each group pulses in its own slot, that shows up as groups appearing in the wrong order or not at all.

Changed in version 0.10.0: Output times chosen by the model can summarize their interval instead of sampling its final instant. See reduce.

find_threshold(stim, bright_th, amp_range=(0, 999), amp_tol=1, bright_tol=0.1, max_iter=100, t_percept=None)[source]

Find the threshold current for a certain stimulus

Estimates amp_th such that the output of model.predict_percept(stim(amp_th)) is approximately bright_th.

Parameters:
  • stim (Stimulus) – The stimulus to use. Stimulus amplitude will be up and down regulated until amp_th is found.

  • bright_th (float) – Model output (brightness) that’s considered “at threshold”.

  • amp_range ((amp_lo, amp_hi), optional) – Range of amplitudes to search, counted in this model’s stimulus_unit (microamps, for every model p2p ships).

  • amp_tol (float, optional) – Search will stop if candidate range of amplitudes is within amp_tol, in stimulus_unit

  • bright_tol (float, optional) – Search will stop if model brightness is within bright_tol of bright_th

  • max_iter (int, optional) – Search will stop after max_iter iterations

  • t_percept (float or list of floats, optional) – The time points at which to output a percept, counted in this model’s time_unit (milliseconds, for every model p2p ships). If None, implant.stim.time is used. May be given as a unitful quantity (e.g. [0, 20] * ms); see pulse2percept.units.

Returns:

amp_th – Threshold current, in stimulus_unit, estimated so that the output of model.predict_percept(stim(amp_th)) is within bright_tol of bright_th.

Return type:

float

Notes

  • amp_range, amp_tol and t_percept may be given as unitful quantities; the answer comes back as a plain number of microamps. bright_th and bright_tol are model output, which is not a physical quantity and carries no unit. See pulse2percept.units.

build(**build_params)[source]

Build the model

Every model must have a `build method, which is meant to perform all expensive one-time calculations. You must call build before calling predict_percept.

Important

Don’t override this method if you are building your own model. Customize _build instead.

Parameters:

build_params (additional parameters to set) – You can overwrite parameters that are listed in get_default_params. Trying to add new class attributes outside of that will cause a FreezeError. Example: model.build(param1=val)

property is_built

A flag indicating whether the model has been built

set_params(**params)[source]

Set the parameters of this object

space_unit = um[source]

The unit spatial coordinates are expressed in

stimulus_unit = uA[source]

The unit stimulus values are expressed in

time_unit = ms[source]

The unit time is expressed in

class pulse2percept.models.base.Model(spatial=None, temporal=None, **params)[source]

Computational model

To build your own model, you can mix and match spatial and temporal models at will.

For example, to create a model that combines the scoreboard model described in [Beyeler2019] with the temporal model cascade described in [Nanduri2012], use the following:

model = Model(spatial=ScoreboardSpatial(),
              temporal=Nanduri2012Temporal())

See also

  • Basic Concepts > Computational Models > Building your own model <topics-models-building-your-own>

Added in version 0.6.

Parameters:
  • spatial (SpatialModel or None) – blah

  • temporal (TemporalModel or None) – blah

  • **params – Additional keyword arguments(e.g., verbose=True) to be passed to either the spatial model, the temporal model, or both.

property stimulus_unit

The unit stimulus values are expressed in

The stimulus goes to the spatial model if there is one, and straight to the temporal model otherwise.

property space_unit

The unit spatial coordinates are expressed in

The temporal model never sees a coordinate.

property time_unit

The unit time is expressed in

t_percept is read in, and the resulting Percept is written in, the unit of the last stage of the pipeline: the temporal model if there is one, the spatial model otherwise. The two need not agree – a spatial model counting in seconds hands its percept to a temporal model counting in milliseconds and the time axis is converted on the way across.

set_params(params)[source]

Set model parameters

This is a convenience function to set parameters that might be part of the spatial model, the temporal model, or both.

Alternatively, you can set the parameter directly, e.g. model.spatial.verbose = True.

Note

If a parameter exists in both spatial and temporal models(e.g., verbose), both models will be updated.

Parameters:

params (dict) – A dictionary of parameters to set.

build(**build_params)[source]

Build the model

Performs expensive one-time calculations, such as building the spatial grid used to predict a percept.

Parameters:

build_params (additional parameters to set) – You can overwrite parameters that are listed in get_default_params. Trying to add new class attributes outside of that will cause a FreezeError. Example: model.build(param1=val)

Return type:

self

predict_percept(implant, t_percept=None)[source]

Predict a percept

Important

You must call build before calling predict_percept.

Parameters:
  • implant (ProsthesisSystem) – A valid prosthesis system. A stimulus can be passed via stim().

  • t_percept (float or list of floats, optional) – The time points at which to output a percept, counted in this model’s time_unit (milliseconds, for every model p2p ships). If None, implant.stim.time is used. May be given as a unitful quantity (e.g. [0, 20] * ms); see pulse2percept.units.

Returns:

percept – A Percept object whose data container has dimensions Y x X x T. Will return None if implant.stim is None.

Return type:

Percept

find_threshold(implant, bright_th, amp_range=(0, 999), amp_tol=1, bright_tol=0.1, max_iter=100, t_percept=None)[source]

Find the threshold current for a certain stimulus

Estimates amp_th such that the output of model.predict_percept(stim(amp_th)) is approximately bright_th.

Parameters:
  • implant (ProsthesisSystem) – The implant and its stimulus to use. Stimulus amplitude will be up and down regulated until amp_th is found.

  • bright_th (float) – Model output (brightness) that’s considered “at threshold”.

  • amp_range ((amp_lo, amp_hi), optional) – Range of amplitudes to search, counted in this model’s stimulus_unit (microamps, for every model p2p ships).

  • amp_tol (float, optional) – Search will stop if candidate range of amplitudes is within amp_tol

  • bright_tol (float, optional) – Search will stop if model brightness is within bright_tol of bright_th

  • max_iter (int, optional) – Search will stop after max_iter iterations

  • t_percept (float or list of floats, optional) – The time points at which to output a percept, counted in this model’s time_unit (milliseconds, for every model p2p ships). If None, implant.stim.time is used. May be given as a unitful quantity (e.g. [0, 20] * ms); see pulse2percept.units.

Returns:

amp_th – Threshold current, in stimulus_unit, estimated so that the output of model.predict_percept(stim(amp_th)) is within bright_tol of bright_th.

Return type:

float

Notes

  • amp_range, amp_tol and t_percept may be given as unitful quantities; the answer comes back as a plain number of microamps. bright_th and bright_tol are model output, which is not a physical quantity and carries no unit. See pulse2percept.units.

property has_space

Returns True if the model has a spatial component

property has_time

Returns True if the model has a temporal component

property is_built

Returns True if the build model has been called