Release Notes
v0.10.0 Encoders (unreleased)
Highlights:
New
Encoderclasses translate images and videos into electrical stimulation. Amplitude and frequency modulation are supported, including stimulator timing, input resolution, and electrode multiplexing.New
Rasterclasses describe how stimulators multiplex electrodes that cannot be driven simultaneously. Each group starts its pulse a fixedgroup_durbehind the one before it.CheckerboardRasterimplements the checkerboard pattern of [Kasowski2025].play()andplay()are roughly 100x faster and produce much smaller notebooks and documentation pages.New
unitsmodule. Arguments at pulse2percept’s public API boundaries may now be given as physical quantities (50 * uA,450 * us,15 * mm,2 * dva), which are dimension-checked and converted to the unit the code expects. Bare numbers keep working and keep their documented meaning everywhere, and are never warned about. See Physical Units.Python 3.14 is now supported. Python 3.11 and NumPy 2 are now required.
API changes:
The
axlambdaparameter of the axon map models was renamed tolam, which sits better next torho. The old name still works everywhere the new one does, but raises aDeprecationWarningand will be removed in v0.11.0.FadingTemporalis now driven by \(\max(-A, 0)\) rather than \(-A\): anodic current no longer reduces brightness, it is ignored. A stimulus that is purely cathodic is unaffected.FadingTemporalrequirestau >= dt. The integrator steps explicitly, so a shorter time constant overshoots its drive bydt / tauand oscillates instead of decaying.Temporal models gained a
reduceparameter. Whenpredict_perceptpicks the output times itself (t_percept=None),reduce='peak'makes each point report the highest brightness reached over the interval leading up to it rather than the brightness at the instant it ends. Namingt_perceptstill asks for those instants.encode()andencode()now useAmplitudeEncoder. Most importantly, gray levels map toamp_rangeabsolutely rather than being stretched to fill it, and each frame now produces a pulse train rather than a single pulse. Passstretch=Truefor the old gray-level mapping.BiphasicPulseTrainnow recordsampin its metadata as a magnitude.ProsthesisSystemnow exposesrasterandmax_current.playgained afmtargument.play()defaults to JPEG, which is substantially smaller and faster to build for color video;play()defaults to PNG, which is pixel-exact and nearly as compact for scalar data. Passfmtto override.Objects now record what their numbers mean:
unit,time_unit,values(),times(),coordinates(),time_unit,times(), andget_param_units(). Models declarestimulus_unit,space_unitandtime_unit; visual field maps declarevisual_unitandtissue_unit. Storage is unchanged: these report the unit, they do not convert what is stored.predict_perceptnow raisesDimensionMismatchErrorwhen the stimulus is not the physical quantity the model reads. Assigning anImageStimulusorVideoStimulusstraight toimplant.stimpreviously had its gray levels silently treated as microamps. Encode it withAmplitudeEncoderorFrequencyEncoderfirst, or give the implant apreprocessfunction that does. The same check guards thesafe_modeandmax_currentsafety checks.is_charge_balancedreturns None for a stimulus that is not a current, rather than answering a question that does not apply to it.from_coords()requiresxrange,yrangeandxysteptogether whenlocsis not given. They previously defaulted to a visual-field range, which placed implants at coordinates that were never meant to be microns.Minimum dependency versions were raised for NumPy 2 compatibility. NumPy 1.x users should remain on v0.9.1.
Bug fixes:
PulseTrainno longer ends on partial, unbalanced pulses when its frequency does not dividestim_dur.Stimulus time axes now use float64 precision, fixing false
is_charge_balancedfailures for longer pulse trains and improving frequency-modulation accuracy.EnsembleImplantnow merges nearly identical time points using the same tolerance asStimulus.Various fixes for
ImageStimulus: keyword arguments are passed on to scikit-image; inputs are no longer modified in place;center()honors itslocargument instead of always centering on the middle of the image.play(),play(), andsave()now handle single-frame inputs correctly and give a useful error for nonuniform time axes.vid_shapenow reports the number of frames the stimulus actually has, rather than the number the source video had beforecompress=Truedropped the redundant time points. This fixesplay()and every other operation that reshapesdataback into frames. Playing a video that was compressed in space raises an explanatory error instead of a reshape error.A four-channel
VideoStimulusis played back as RGBA, as documented: the alpha channel is preserved forfmt='png'and composited onto the axes background forfmt='jpg', which cannot carry it. Previously the four channels were reinterpreted as RGB, which sheared the color channels across every row.Stimulus metadata now survives
predict_perceptand other transformations.When a temporal model picks its own output times, the last one no longer falls after the end of the stimulus. The end of the range was nudged by one millisecond to make it inclusive, which added a frame wherever the frame interval did not divide that millisecond – most visibly in
DynaphosModelwithdtfiner than 1 ms.Visual-field-map equality now handles array-valued attributes correctly, maps are hashable again, and maps of different classes no longer compare equal.
cortex_to_dva()(and thev1_to_dva,v2_to_dva,v3_to_dvamethods that call it) now returns coordinates with the same shape as its input. Previously NaN inputs were dropped rather than mapped to NaN outputs, which silently shifted every point after them into the wrong slot, and multidimensional inputs came back flattened. Cortical points that land exactly on a mesh vertex now map to that vertex instead of dividing by zero and returning NaN. The docstrings said the cortical coordinates were in mm; they are in um, as the code always assumed.
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_batchedfromBiphasicAxonMapModel; theengineargument of the effect models and thepadargument ofcalc_axon_sensitivity()are deprecated, and will be removed in v0.10.0 (PR #788)Removed the
model_selectionmodule (PR #685) and support for the joblib and dask parallel backends (PR #686); theengineandschedulermodel parameters are deprecated, and will be removed in v0.10.0 (PR #788)n_jobsis now an alias forn_threads: either name sets the number of OpenMP threads, andNoneor-1uses every core (PR #788)More robust dataset downloads, with updated OSF endpoints (PR #754)
Smarter
reshape_stimfor implants (PR #680)Installation is now tested inside the real Google Colab runtime (PR #777)
v0.9.0 Cortex (2025-02-17)
Highlights:
Cortical implants:
Cortivis[Fernandez2017] (PR #525),ICVP[Troyk2003] (PR #542),Neuralink[Musk2019] (PR #597)Cortical models:
ScoreboardModel(PR #533),DynaphosModel[vanderGrinten2023] (PR #547)Cortical maps:
Polimeni2006Map(PR #509),NeuropythyMap(PR #597)Other new implants:
IMIE[Xu2021] (PR #492),EnsembleImplant(PR #537),RectangleImplant(PR #631)Torch and CUDA support (PR #633)
Python 3.11 and 3.12 support
Various bug fixes
v0.8.0 Retina (2022-05-05)
Highlights:
New implants:
BVT44[Petoe2021] (PR #465)New models:
BiphasicAxonMapModel[Granley2021] (PR #398) andThompson2003Model[Thompson2003] (PR #448)New datasets:
load_greenwald2009()[Greenwald2009] (PR #459) andload_perezfornos2012()[PerezFornos2012] (PR #457)New stimuli:
BarStimulus,GratingStimulus(PR #310)Python 3.10 support (PR #479)
Various bug fixes
v0.7.1 (2021-06-21)
Highlights:
Add
FadingTemporal, a generic phosphene fading model (PR #378)Various implant usability and speed upgrades (PR #375, PR #382, PR #383, PR #386)
Various stimulus usability and speed upgrades (PR #382, PR #383, PR #384, PR #385)
Improve documentation and usability of various
AxonMapModelmethods (PR #370)
v0.7.0 Implants (2021-04-04)
Highlights:
New electrodes:
SquareElectrode,HexElectrode,PhotovoltaicPixel(PR #188, PR #193)New stimuli:
ImageStimulusandVideoStimulus(PR #196, PR #220, PR #221, PR #356),BarStimulusandGratingStimulus(PR #323)New datasets:
load_nanduri2012(PR #250)New model selection subpackage (PR #311)
100x speedup of building
AxonMapModel(PR #331)OpenMP support (PR #260)
Python 3.9 support (PR #348)
Various usability upgrades
Various bug fixes
v0.6.0 API (2020-05-05)
Highlights:
New implants:
BVA24(PR #161)New models:
ScoreboardModel(PR #96),AxonMapModel(PR #96),Nanduri2012Model(PR #168),Horsager2009Model(PR #180)New stimuli:
BiphasicPulseTrain,AsymmetricBiphasicPulse,AsymmetricBiphasicPulseTrain(PR #178)New build process: Compile code and run tests via
Makefile(PR #96)Documentation now includes a tutorial, user guide, developer’s guide, and a gallery
Various bug fixes
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/Cythonpulse2percept.retina.Horsager2009: respectuse_jitoptionpulse2percept.utils.center_vector: “cannot determine Numba type”
v0.5.0 Community (2019-11-29)
New
pulse2percept.vizmodule (PR #84)Automated wheelhouse build (PR #130)
New contribution guidelines (PR #92)
New issue templates (PR #93)
New code of conduct (PR #95)
Host documentation on pulse2percept.readthedocs.io.
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