Release Notes

v0.11.0 Foundations (unreleased)

Highlights

  • Backwards-incompatible API overhaul. Retinal and cortical implants, models, and topography now live under explicit retina and cortex namespaces. Models are constructed with an implant, build automatically, and take the stimulus directly in predict_percept. Implant placement moved from device constructors to model parameters, so named implant geometry now remains device-local (PR #862, PR #879, PR #880, PR #884, PR #887).

    A typical workflow changes from:

    # v0.10
    implant = p2p.implants.ArgusII(x=1000, y=-500, rot=15)
    model = p2p.models.AxonMapModel()
    model.build()
    percept = model.predict_percept(implant, stim)
    

    to:

    # v0.11
    implant = p2p.implants.retina.ArgusII()
    model = p2p.models.retina.AxonMapModel(
        implant,
        implant_position=(1000, -500),
        implant_rotation=15,
    )
    percept = model.predict_percept(stim)
    
  • Added pulse2percept.vision for composing scenes, scotomas, residual vision, and prosthetic percepts in visual-field coordinates, including binocular scenes (PR #854, PR #871, PR #883, PR #890, PR #899, PR #901).

  • Added a photovoltaic stimulation pipeline for PRIMA-style arrays, from image encoding through irradiance-based stimulation to the new Ho2018Model (PR #868, PR #891, PR #903).

API changes and improvements

Stimuli and encoding

  • The encoder API was cleaned up: Encoder is now the general base class, and only an ImplantEncoder can be installed on Implant.encoder. AmplitudeEncoder(amp_range=(0, 50)).encode(image, implant=implant) becomes AmplitudeEncoder(implant, amp_range=(0, 50)).encode(image), and StimulusEncoder was renamed to PulseEncoder (PR #925, PR #926).

  • Added TraceEncoder, a model-aware encoder that stimulates one electrode at a time along a letter or trajectory drawn in the visual field (PR #926).

  • The stimuli API was simplified: bundled media moved to stimuli.samples, visual psychophysics stimuli to stimuli.psychophysics, and several legacy stimulus classes and module paths were deprecated or removed (PR #889).

  • ImageStimulus and VideoStimulus now provide crop_square() for centered square crops (PR #916).

Implants

  • Implant classes were reorganized by anatomical target. Retinal and cortical devices moved to implants.retina and implants.cortex; generic implant machinery remains at the package root. Retinal implants carry eye and cortical implants may carry hemisphere metadata (PR #887).

  • ProsthesisSystem was renamed Implant; the old name is deprecated until v0.12.0. RectangleImplant was removed in favor of GridImplant (PR #859, PR #876).

  • Implant and electrode APIs were standardized with clearer parameter names, consistent grid terminology, plot3d(), and normal Python container behavior (PR #880).

  • The PRIMA implant family was updated to reflect published device designs, including PRIMAPivotal, Lorach2015Array, Ho2019FlatArray, and Huang2021Array (PR #865, PR #891).

  • EnsembleImplant now supports placement from physical coordinates or visual-field maps and enforces a single anatomical target (PR #884, PR #887, PR #912).

  • Implants now expose placement, technology, and family metadata and support per-electrode thresholds (PR #865, PR #869).

Models

  • Models were reorganized by anatomical target. Generic base and temporal models remain in pulse2percept.models; retinal and cortical models moved to models.retina and models.cortex. The generic SpatialModel is now anatomy-neutral, while retinal and cortical models enforce compatible implant targets (PR #887, PR #895, PR #912).

  • Model construction and placement were simplified. Models now bind their implant, build on demand, and take stimuli directly in predict_percept. implant_position, implant_rotation, and implant_depth place device-local electrode coordinates in tissue; model.plot(show_implant=True) shows the resulting placement (PR #862, PR #879, PR #884, PR #901).

  • New Ho2018Model predicts the spatiotemporal network-mediated response to photovoltaic subretinal stimulation described by [Ho2018] (PR #903).

  • New BiphasicScoreboardModel applies the [Granley2021] pulse-dependent brightness and size relationships without axonal streaks. Retinal scoreboard and axon-map models also support the new encoding workflows (PR #868, PR #869, PR #886, PR #914).

  • location_noise now models fixed electrode-specific uncertainty in phosphene location. The old generic noise parameter and find_threshold model API were removed (PR #862, PR #881, PR #885).

Topography

  • Visual-field maps were reorganized by anatomical target: retinal maps moved to topography.retina and cortical maps to topography.cortex. Generic map classes remain at the package root (PR #887).

  • Added Montesano2020Map, a two-dimensional retinal ganglion-cell displacement model based on [Montesano2020], with eye-specific and inverse mappings (PR #897).

  • Watson2014DisplaceMap now supports both eyes and is deprecated in favor of Montesano2020Map (PR #895).

Scene and plotting

Bug fixes

  • Fixed centering of single-row and single-column hexagonal ElectrodeGrid instances (PR #859).

  • Corrected PRIMA-family pixel dimensions and layouts (PR #865).

  • BiphasicAxonMapSpatial now respects n_gray and preserves the full stimulus in percept metadata (PR #869).

  • DynaphosModel phosphenes are half as wide: the Gaussian standard deviation is a quarter of the phosphene diameter, matching the reference implementation’s radius_to_sigma = 0.5 (PR #894).

  • Cortical maps and models no longer place electrodes outside their mapped region. Polimeni2006Map to_dva returns NaN outside each region instead of wrapping into the other hemifield; DynaphosModel simulates V1 only and raises for driven electrodes outside it; and multi-region location_noise displaces each electrode through its home region only. Predictions for such electrodes change (PR #926).

v0.10.0 Encoders (2026-08-23)

Highlights:

  • New stimulus encoders support amplitude and frequency modulation of images and videos, with implant-specific raster strategies for multiplexed stimulation (PR #810, PR #820, PR #833)

  • Stimuli now retain structured pulse and encoder representations and generate waveform samples lazily, substantially reducing construction time and memory use (PR #842)

  • New units support for dimension-checked physical quantities throughout the public API (PR #828)

  • Major performance improvements for stimulus handling, spatial models, temporal models, and large-array simulations (PR #800, PR #805, PR #808, PR #821, PR #850)

  • play() and play() are substantially faster, and percept playback now supports irregular time axes (PR #809, PR #834)

  • New AlphaTemporal and much faster FadingTemporal temporal models (PR #849)

  • New load() reads percepts from image and video files (PR #835)

  • Python 3.14 is supported. Python 3.11 and NumPy 2 are now required (PR #790)

API changes:

  • Stimulus.data, time, electrodes, and pulse parameters are now read-only. New pad() and shift() methods provide explicit time-axis transformations (PR #837, PR #842)

  • Image and video stimuli now use grid-style electrode names such as 'A1' and 'C12_G' instead of integer pixel indices (PR #805)

  • ProsthesisSystem (now Implant) supports stimulus encoders, raster strategies, and maximum-current limits. Dimensionless image/video stimuli can be encoded automatically when assigned to an implant (PR #810, PR #833)

  • Temporal models gained a reduce parameter for summarizing automatically selected output intervals. FadingTemporal now responds only to cathodic current (PR #818)

  • BiphasicAxonMapModel now distinguishes physical current from threshold-relative amplitude via the new xTh unit (PR #848)

  • BiphasicAxonMapSpatial can now be composed with temporal models using a space-time-separable approximation (PR #847)

  • Model parameter xystep was renamed to step and axlambda to lam; the old names are deprecated until v0.11 (PR #824, PR #830)

  • Axon-map and cortical scoreboard models can smooth predictions across visual-field meridians (PR #838)

  • Multi-electrode stimuli now plot as electrode-by-time heatmaps by default; percept playback and saving gained vmin/vmax controls (PR #835, PR #841)

Bug fixes:

  • Fixed stimulus timing, metadata propagation, pulse scheduling, and structured stimulus handling across implants and models (PR #804, PR #810, PR #818, PR #825, PR #846)

  • Fixed several image and video issues, including argument forwarding, centering, single-frame playback, irregular timing, and efficient partial video loading (PR #815, PR #822, PR #834, PR #844)

  • Fixed several Neuropythy and cortical-map issues involving shapes, NaNs, scalar inputs, mesh vertices, subject IDs, and coordinate units (PR #826, PR #836, PR #845)

  • Various smaller correctness fixes (PR #814)

v0.9.1 (2026-08-06)

Highlights:

  • Python 3.13 support; the minimum supported Python is now 3.10 (PR #649)

  • NumPy 2.x support: wheels import under both NumPy 1.x and 2.x, so installing pulse2percept no longer downgrades NumPy in environments that ship it, such as Google Colab (PR #635, PR #736)

  • Removed the jax engine and predict_percept_batched from BiphasicAxonMapModel; the engine argument of the effect models and the pad argument of calc_axon_sensitivity() are deprecated, and will be removed in v0.10.0 (PR #788)

  • Removed the model_selection module (PR #685) and support for the joblib and dask parallel backends (PR #686); the engine and scheduler model parameters are deprecated, and will be removed in v0.10.0 (PR #788)

  • n_jobs is now an alias for n_threads: either name sets the number of OpenMP threads, and None or -1 uses every core (PR #788)

  • More robust dataset downloads, with updated OSF endpoints (PR #754)

  • Smarter reshape_stim for implants (PR #680)

  • Installation is now tested inside the real Google Colab runtime (PR #777)

  • Various bug fixes (PR #682, PR #700, PR #732, PR #776)

v0.9.0 Cortex (2025-02-17)

Highlights:

v0.8.0 Retina (2022-05-05)

Highlights:

v0.7.1 (2021-06-21)

Highlights:

v0.7.0 Implants (2021-04-04)

Highlights:

v0.6.0 API (2020-05-05)

Highlights:

v0.5.2 (2020-02-25)

Bug fix:

  • pulse2percept.retina.Nanduri2012: improved Cython implementation

v0.5.1 (2020-02-05)

Bug fixes:

  • pulse2percept.retina.Nanduri2012: allow switch between FFT/Cython

  • pulse2percept.retina.Horsager2009: respect use_jit option

  • pulse2percept.utils.center_vector: “cannot determine Numba type”

v0.5.0 Community (2019-11-29)

v0.4.3 Cython (2018-05-21)

Highlights:

  • Cython integration:

    • The model described in Nanduri et al. (2012) now uses a finite difference method implemented in Cython as opposed to FFT-based convolutions (PR #83)

    • Single-core benchmarks show a 200x speedup over a pure-Python implementation.

v0.3.0 Baby Steps (2018-02-20)

  • New, faster axon map calculation

  • Better plotting

  • Support for left/right eye