pulse2percept.stimuli
Visual and electrical stimuli.
Core stimulus types are available at the top level. Generated psychophysics
stimuli and bundled sample assets live in the psychophysics and samples
namespaces, respectively.
Core
|
A stimulus is comprised of a labeled 2D NumPy array that contains the data, where the rows denote electrodes and the columns denote points in time. |
A stimulus made from an image, where each pixel gets assigned to an electrode, and grayscale values in the range [0, 255] get converted to activation values in the range [0, 1]. |
|
A stimulus made from a movie file, where each pixel gets assigned to an electrode, and grayscale values in the range [0, 255] get assigned to activation values in the range [0, 1]. |
Electrical stimuli
|
Monophasic pulse |
|
Symmetric biphasic pulse |
|
Asymmetric biphasic pulse |
|
Generic pulse train |
|
Symmetric biphasic pulse train |
|
Biphasic pulse triplets |
|
Asymmetric biphasic pulse |
Encoders
Convert visual stimuli to electrical stimulation.
|
Base class for encoders. |
|
Base class for encoders installable on an implant. |
|
Abstract base class for electrical pulse-train encoders. |
|
Encode gray levels as pulse amplitudes |
|
Encode gray levels as pulse train frequencies |
|
Encode a traced shape as sequential single-electrode pulses |
|
Encode image/video gray levels as pulsed optical stimulation |
|
Encode image/video gray levels for the PRIMA projector. |
Psychophysics
Generated visual stimuli in degrees of visual angle and physical time.
|
Moving bar |
|
Sinusoidal grating |
|
Landolt C optotype |
|
Tumbling E optotype |
Samples
Bundled images and videos for examples, documentation, and tests.
|
Big Buck Bunny video clip |
|
Bionic Vision Lab cake photograph |
|
Cajal's drawing of the retina |
|
Bionic Vision Lab (BVL) logo |
|
UCSB logo |
|
UCSB bike path photograph |
|
UCSB aerial flyover clip |
|
UCSB pedestrians clip |
|
UCSB coastline video frame |
|
Zebrafish retina micrograph |
Deprecated in v0.11
These compatibility classes will be removed in v0.12.
|
Drifting bar |
|
Drifting sinusoidal grating |
|
Bionic Vision Lab (BVL) logo |
|
UCSB logo |
See also
- class pulse2percept.stimuli.AmplitudeEncoder(implant=None, amp_range=(0, 50), freq=20, **kwargs)[source]
Encode gray levels as pulse amplitudes
Every electrode emits a pulse train of the same fixed frequency, and the gray level of the pixel it sees sets the amplitude of those pulses. This is how most retinal prostheses encode a video.
Because every electrode shares one pulse period, a raster costs no frequency here: the groups hold fixed offsets from one another and so can never drift together, which means nothing has to be quantized and
freqis delivered exactly. With no explicitgroup_durthe groups also divide that period evenly, one turn each per pulse; an explicitgroup_durpacks them into a shorter sweep at the start of every period instead. Either way no two groups are ever active at the same instant.Added in version 0.10.0.
- Parameters:
implant (
Implant, optional) – The implant to encode for. SeePulseEncoder.amp_range ((min_amp, max_amp), optional) –
Range of pulse amplitudes, in uA or in multiples of perceptual threshold (
xTh). A gray level of 0 maps ontomin_ampand a gray level of 1 ontomax_amp.Bare numbers mean uA. Both endpoints must carry the same dimension, so a threshold-relative range is spelled
(0 * xTh, 3 * xTh); the half spelling(0, 3 * xTh)is rejected rather than guessed at. A threshold-relative range encodes to axThstimulus, which an implant converts to current when it hasthresholdsfor every driven electrode.Changed in version 0.11.0: Accepts
xThas well as current.freq (float, optional) –
Pulse train frequency (Hz), the same for every electrode. The pulse clock runs independently of the video, so the frame rate has no say in the rate delivered. Because every electrode shares this one period, a raster does not quantize it either: the groups keep a fixed offset from one another and cannot drift together. Only
clockcan lower it, by rounding the period up to a whole number of cycles.Note
A frequency below the frame rate is realizable, but wasteful: some frames then receive no pulse at all and their gray levels are never delivered. Encoding warns when this happens.
phase_dur – See
PulseEncoder.interphase_dur – See
PulseEncoder.cathodic_first – See
PulseEncoder.frame_dur – See
PulseEncoder.stretch – See
PulseEncoder.
Notes
Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,460 * us,0.02 * kHz), which are converted to those units. Seepulse2percept.units.
Examples
Encode a movie for Argus II, mapping gray levels onto 0-50 uA at 20 Hz:
>>> import numpy as np >>> import pulse2percept as p2p >>> video = p2p.stimuli.VideoStimulus(np.random.rand(16, 20, 30), ... metadata={'fps': 20}) >>> implant = p2p.implants.retina.ArgusII() >>> encoder = p2p.stimuli.AmplitudeEncoder(implant, amp_range=(0, 50)) >>> stim = encoder.encode(video)
The same thing, with the implant encoding its own input:
>>> implant.encoder = p2p.stimuli.AmplitudeEncoder(amp_range=(0, 50)) >>> stim = implant.prepare_stim(video)
- amp_unit
Unit of amplitudes returned by _modulate
- encode(source)[source]
Encode an image or a video as a train of electrical pulses
- Parameters:
source (
Stimulus) – The image or video to encode. Gray levels are expected in [0, 1], which is whatImageStimulusandVideoStimulusproduce. It must be dimensionless: this method is the boundary at which a picture becomes stimulation, so an electrical stimulus is not a valid source for it.- Returns:
stim – The encoded stimulus, ready for the implant to deliver. Its amplitudes are in microamps, or in threshold multiples (
xTh) if the encoder’s amplitude parameters were, and its time axis is in milliseconds, whatever units the encoder’s own parameters were given in.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- property implant
The implant this encoder is bound to, or None (read-only)
- class pulse2percept.stimuli.AsymmetricBiphasicPulse(amp1, amp2, phase_dur1, phase_dur2, interphase_dur=0, delay_dur=0, stim_dur=None, cathodic_first=True, electrode=None)[source]
Asymmetric biphasic pulse
A simple stimulus consisting of a single biphasic pulse: a cathodic and an anodic phase, optionally separated by an interphase gap. The two pulse phases can have different amplitudes and duration (“asymmetric”).
Added in version 0.6.
Changed in version 0.10.0: The pulse retains the parameters that define it, and generates its sampled waveform only when one is asked for.
- Parameters:
amp1 (float) – Current amplitude (uA) of the first and second pulse phases. Negative currents: cathodic, positive: anodic. The signs will be converted automatically depending on
cathodic_first.amp2 (float) – Current amplitude (uA) of the first and second pulse phases. Negative currents: cathodic, positive: anodic. The signs will be converted automatically depending on
cathodic_first.phase_dur1 (float) – Duration (ms) of the first and second pulse phases.
phase_dur2 (float) – Duration (ms) of the first and second pulse phases.
interphase_dur (float, optional, default: 0) – Duration (ms) of the gap between cathodic and anodic phases.
delay_dur (float) – Delay duration (ms). Zeros will be inserted at the beginning of the stimulus to deliver the first pulse phase after
delay_durms.stim_dur (float, optional, default:) –
2*phase_dur+interphase_dur+delay_durTotal stimulus duration (ms). Zeros will be inserted at the end of the stimulus to make the stimulus laststim_durms overall.cathodic_first (bool, optional, default: True) – If True, will deliver the cathodic pulse phase before the anodic one.
electrode ({ int | string }, optional, default: 0) – Optionally, you can provide your own electrode name.
Notes
The order of the two phases is given by the
cathodic_firstflag.The sign of
ampwill be automatically adjusted depending on thecathodic_firstflag.A pulse will be considered “charge-balanced” if its net current is smaller than 10 picoamps.
Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,450 * us), which are converted to those units. Seepulse2percept.units.The parameters above are read-only. A pulse with different parameters is a different pulse; build another one.
amp1andamp2read back as magnitudes, because that is all of them that reaches the waveform: the constructor takesnp.absof each and gets the polarity fromcathodic_first.
Examples
An asymmetric cathodic-first pulse (first phase: -40uA, 1ms; second phase: 10uA, 4ms; 1ms interphase-gap) delivered after 2ms and embedded in a stimulus that lasts 15ms overall:
>>> from pulse2percept.stimuli import AsymmetricBiphasicPulse >>> pulse = AsymmetricBiphasicPulse(-40, 10, 1, 4, interphase_dur=1, ... delay_dur=2, stim_dur=15)
- property amp1
Magnitude (uA) of the first pulse phase
- property amp2
Magnitude (uA) of the second pulse phase
- property phase_dur1
Duration (ms) of the first pulse phase
- property phase_dur2
Duration (ms) of the second pulse phase
- property interphase_dur
Duration (ms) of the gap between the two phases
- property delay_dur
Delay (ms) before the first phase is delivered
- property stim_dur
Total stimulus duration (ms)
- property duration
Stimulus duration (ms)
The waveform is built to end exactly at
stim_dur, so this is known without generating one.
- property cathodic_first
Whether the cathodic phase is delivered first
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.AsymmetricBiphasicPulseTrain(freq, amp1, amp2, phase_dur1, phase_dur2, interphase_dur=0, delay_dur=0, n_pulses=None, stim_dur=1000.0, cathodic_first=True, electrode=None, metadata=None)[source]
Asymmetric biphasic pulse
A simple stimulus consisting of a single biphasic pulse: a cathodic and an anodic phase, optionally separated by an interphase gap. The two pulse phases can have different amplitudes and duration (“asymmetric”). The order of the two phases is given by the
cathodic_firstflag.Added in version 0.6.
- Parameters:
freq (float) – Pulse train frequency (Hz).
amp1 (float) – Current amplitude (uA) of the first and second pulse phases. Negative currents: cathodic, positive: anodic. The signs will be converted automatically depending on
cathodic_first.amp2 (float) – Current amplitude (uA) of the first and second pulse phases. Negative currents: cathodic, positive: anodic. The signs will be converted automatically depending on
cathodic_first.phase_dur1 (float) – Duration (ms) of the first and second pulse phases.
phase_dur2 (float) – Duration (ms) of the first and second pulse phases.
interphase_dur (float, optional, default: 0) – Duration (ms) of the gap between cathodic and anodic phases.
delay_dur (float) – Delay duration (ms). Zeros will be inserted at the beginning of the stimulus to deliver the first pulse phase after
delay_durms.n_pulses (int) – Number of pulses requested in the pulse train. If None, the entire stimulation window (
stim_dur) is filled.stim_dur (float, optional, default: 1000 ms) – Total stimulus duration (ms). Zeros will be inserted at the end of the stimulus to make the the stimulus last
stim_durms overall.cathodic_first (bool, optional, default: True) – If True, will deliver the cathodic pulse phase before the anodic one.
electrode ({ int | string }, optional, default: 0) – Optionally, you can provide your own electrode name.
metadata (dict) – A dictionary of meta-data
Notes
Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,450 * us), which are converted to those units. Seepulse2percept.units.
- property freq
Pulse train frequency (Hz)
- property n_pulses
Number of pulses delivered
- property stim_dur
Total stimulus duration (ms)
- property duration
Stimulus duration (ms)
- property amp1
Magnitude (uA) of the first phase of each pulse
- property amp2
Magnitude (uA) of the second phase of each pulse
- property phase_dur1
Duration (ms) of the first pulse phase
- property phase_dur2
Duration (ms) of the second pulse phase
- property interphase_dur
Duration (ms) of the gap between the two phases
- property delay_dur
Delay (ms) before the first phase of each pulse
- property cathodic_first
Whether the cathodic phase is delivered first
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.BarStimulus(**kwargs)[source]
Drifting bar
A drifting bar stimulus.
Added in version 0.7.
- Parameters:
shape (
(height, width)) – A tuple specifying the desired height (pixels) and the width (pixels) of the grating stimulus.direction (scalar in [0, 360) degrees or Quantity, optional) – Drift direction of the bar.
speed (scalar in pixels/frame, optional) – Drift speed of the bar.
bar_width (scalar in pixels, optional) – The width of the center of the bar.
edge_width (scalar in pixels, optional) – The width of the cosine edges of the bar. An edge of width edge_width will be tacked onto both sides of the bar, so the total width will be bar_width + 2 * edge_width
px_btw_bars (scalar in pixels, optional) – The number of pixels between the bars in the stimulus.
start_pos (scalar in pixels, optional) – The starting position of the first bar. The coordinate system is a line lying along the direction of the bar motion passing through the center of the stimulus. The point 0 is the center of the stimulus.
contrast (scalar in [0, 1], optional) – Stimulus contrast between 0 and 1
time (scalar, array-like, or None; optional) –
The time points at which to evaluate the drifting bar:
If a scalar,
timeis interpreted as the end time (in milliseconds) of a time series with 50 Hz frame rate.If array-like,
timeis interpreted as the exact time points (in milliseconds) at which to draw the bar (end point included).If None,
timedefaults to a 1-second time series at 50 Hz frame rate (end point included).
mask ({'gauss', 'circle', None}) –
Stimulus mask:
”gauss”: a 2D Gaussian designed such that the border of the image lies at 3 standard deviations
”circle”: a circle that fits into the
shapeof the stimulusNone: no mask
electrodes (int, string or list thereof; optional, default: None) – Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image: a letter for the row, a number for the column, and a suffix for the color channel (e.g. ‘A1’, ‘C12’, ‘A1_R’).
metadata (dict, optional, default: None) – Additional stimulus metadata can be stored in a dictionary.
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- apply(func, *args, electrodes=None, **kwargs)[source]
Apply a function to each frame of the video
Changed in version 0.10.0:
funcmay now change the shape of a frame, andelectrodescan name the result.- Parameters:
func (function) – The function to apply to each frame in the video. Must accept a 2D or 3D image and return a 2D or 3D image. The returned frames need not have the same shape as the originals (but must all have the same shape as each other); see
electrodes.*args – Additional positional arguments passed to the function
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, the original names are carried over whenever
funcleaves the shape of a frame alone, and the result is named after its place in the new frame otherwise (e.g. forskimage.transform.resize).Note
The number of electrode names provided must match the number of pixels in a returned frame.
**kwargs – Additional keyword arguments passed to the function
- Returns:
stim – A copy of the stimulus object with the new video
- Return type:
VideoStimulus
- center(loc=None)[source]
Center the image foreground
This function shifts the center of mass (CoM) to the image center.
- Parameters:
loc ((col, row), optional) – The pixel location at which to center the CoM. By default, shifts the CoM to the image center.
- Returns:
stim – A copy of the stimulus object containing the centered image
- Return type:
ImageStimulus
- compress()[source]
Compress the source data
Also brings
vid_shapeback in line with the compressed data: compression drops the time points at which the video does not change, so the frame count of the source is no longer the frame count of the stimulus. Everydata.reshape(vid_shape)in this module relies on that invariant. (Compression can also drop all-zero pixels, in which case no shape describes the data any more; see_frames.)- Returns:
compressed
- Return type:
- crop(idx_space=None, idx_time=None, left=0, right=0, top=0, bottom=0, front=0, back=0, electrodes=None)[source]
Crop the video
This method maps a rectangle (defined by two corners) from each video frame to a rectangle of the given size. Similarly, the video can be shortened to a specified range of frames.
Alternatively, this method can be used to crop a number of columns either from the left or the right of the video frame, or a number of rows either from the top or the bottom, or a number of frames from the front (beginning) or back (end) of the video.
Added in version 0.8.
- Parameters:
idx_space (4-tuple (y0, x0, y1, x1)) – Image indices of the top-left corner
[y0, x0]and bottom-right corner[y1, x1](exclusive) of the rectangle to crop.idx_time (tuple (t0, t1)) – Frame indices defining the start
t0and endt1of the cropped video.left (int) – Number of columns to crop from the left of each video frame
right (int) – Number of columns to crop from the right of each video frame
top (int) – Number of rows to crop from the top of each video frame
bottom (int) – Number of rows to crop from the bottom of each video frame
front (int) – Number of frames to crop from the front (beginning) of the video
back (int) – Number of frames to crop from the back (end) of the video
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the cropped image.
- Returns:
stim – A copy of the stimulus object containing the video
- Return type:
VideoStimulus
- crop_square()[source]
Crop each video frame to the largest centered square
Frames are cropped without resizing. If their dimensions differ by an odd number of pixels, the extra pixel is removed from the bottom or right.
Added in version 0.11.0.
- Returns:
stim – A copy of the stimulus containing the centered square crop.
- Return type:
VideoStimulus
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property duration
Stimulus duration (ms)
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- encode(amp_range=(0, 50), freq=20, implant=None, **kwargs)[source]
Encode the video using amplitude modulation
Encodes every frame of the video as a train of biphasic pulses, where the gray level of a pixel sets the amplitude of its pulses. Each train lasts one frame period.
This is a shorthand for
AmplitudeEncoder; use that directly for the full set of options.Changed in version 0.10.0: Gray levels now map onto
amp_rangeabsolutely rather than being stretched to fill it (passstretch=Truefor the old behavior), each frame receives a pulse train rather than a single pulse, andimplantencodes at electrode rather than pixel resolution.- Parameters:
amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto
min_amp, a gray level of 1 ontomax_amp.freq (float, optional) – Pulse train frequency (Hz).
implant (
Implant, optional) – If given, the video is first sampled at the implant’s electrode locations, so that the pulse trains are built at electrode rather than pixel resolution. Strongly recommended: a video has orders of magnitude more pixels than an implant has electrodes.**kwargs – Additional arguments passed to
AmplitudeEncoder.
- Returns:
stim – Encoded stimulus
- Return type:
- filter(filt, **kwargs)[source]
Filter each frame of the video
- Parameters:
filt (str) –
Image filter that will be applied to every frame of the video. Additional parameters can be passed as keyword arguments. The following filters are supported:
’sobel’: Edge filter the image using the Sobel filter.
’scharr’: Edge filter the image using the Scarr filter.
’canny’: Edge filter the image using the Canny algorithm. You can also specify
sigma,low_threshold,high_threshold,mask, anduse_quantiles.’median’: Return local median of the image.
**kwargs – Additional parameters passed to the filter
- Returns:
stim – A copy of the stimulus object with the filtered image
- Return type:
VideoStimulus
- invert()[source]
Invert the gray levels of the video
- Returns:
stim – A copy of the stimulus object with all grayscale values inverted in the range [0, 1].
- Return type:
VideoStimulus
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- play(fps=None, repeat=True, annotate_time=True, ax=None, fmt='jpg')[source]
Animate the video as HTML with JavaScript
The video will be played in an interactive player in IPython or Jupyter Notebook.
- Parameters:
fps (float or None) – If None, uses the video’s time axis. Not supported for non-homogeneous time axis. May be given as a plain number of hertz or as a unitful frequency (e.g.
30 * Hz,0.03 * kHz); seepulse2percept.units.repeat (bool, optional) – Whether the animation should repeat when the sequence of frames is completed.
annotate_time (bool, optional) – If True, the time of the frame will be shown as t = X ms in the title of the panel.
ax (matplotlib.axes.AxesSubplot, optional) – A Matplotlib axes object. If None, will create a new Axes object
fmt ({'jpg', 'png'}, optional) –
The image format used to embed the frames. ‘jpg’ keeps notebooks and doc pages an order of magnitude smaller; use ‘png’ if you need the frames to be pixel-exact.
Added in version 0.10.0.
- Returns:
ani – A Matplotlib animation object that will play the video frame-by-frame.
- Return type:
Notes
Changed in version 0.10.0: The HTML player is now generated by
HTMLAnimation, which renders the figure once and ships all frames as a single sprite sheet. This is roughly two orders of magnitude faster than Matplotlib’sto_jshtmland produces much smaller notebooks and doc pages.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- resize(shape, electrodes=None, **kwargs)[source]
Resize the video
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
shape ((rows, cols)) – Shape of each frame in the resized video. If one of the dimensions is set to -1, its value will be inferred by keeping a constant aspect ratio.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the resized video.
**kwargs – Additional keyword arguments passed to skimage.transform.resize, such as
order=0for nearest-neighbor interpolation (which keeps a binary video binary).
- Returns:
stim – A copy of the stimulus object containing the resized video
- Return type:
VideoStimulus
- rgb2gray(electrodes=None)[source]
Convert the video to grayscale
- Parameters:
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale video.
- Returns:
stim – A copy of the stimulus object with all RGB values converted to grayscale in the range [0, 1].
- Return type:
VideoStimulus
- rotate(angle, mode='constant', electrodes=None, **kwargs)[source]
Rotate each frame of the video
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
angle (float or Quantity) – Angle by which to rotate each video frame (degrees). Positive: counter-clockwise, negative: clockwise
mode (str, optional) – How to fill in the corners the rotation leaves empty; see skimage.transform.rotate.
electrodes (int, string or list thereof; optional) – Optionally, you can provide your own electrode names. If none are given, each pixel keeps the name it had before the rotation, unless
resize=Truegrew the frame, in which case the enlarged video is named after its own pixel grid.**kwargs – Additional keyword arguments passed to skimage.transform.rotate, such as
order,cval, orresize=Trueto grow each frame so that it contains every rotated pixel.
- Returns:
stim – A copy of the stimulus object containing the rotated video
- Return type:
VideoStimulus
- scale(scaling_factor)[source]
Scale the image foreground
This function scales the image foreground (excluding black pixels) by a factor.
- Parameters:
scaling_factor (float) – Factory by which to scale the image
- Returns:
stim – A copy of the stimulus object containing the scaled image
- Return type:
ImageStimulus
- property shape
Data container shape
- shift(shift_cols, shift_rows)[source]
Shift the image foreground
This function shifts the center of mass (CoM) of the image by the specified number of rows and columns.
- Parameters:
- Returns:
stim – A copy of the stimulus object containing the shifted image
- Return type:
ImageStimulus
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- trim(tol=0, electrodes=None)[source]
Remove any black border around the video
Added in version 0.7.
- Parameters:
tol (float) – Any pixels with gray levels > tol will be trimmed.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in each frame of the trimmed video.
- Returns:
stim – A copy of the stimulus object with trimmed borders.
- Return type:
VideoStimulus
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.BiphasicPulse(amp, phase_dur, interphase_dur=0, delay_dur=0, stim_dur=None, cathodic_first=True, electrode=None)[source]
Symmetric biphasic pulse
A simple stimulus consisting of a single biphasic pulse: a cathodic and an anodic phase, optionally separated by an interphase gap. Both cathodic and anodic phases have the same duration (“symmetric”).
Added in version 0.6.
Changed in version 0.10.0: The pulse retains the parameters that define it, and generates its sampled waveform only when one is asked for.
- Parameters:
amp (float) – Current amplitude (uA). Negative currents: cathodic, positive: anodic. The sign will be converted automatically depending on
cathodic_first.phase_dur (float) – Duration (ms) of the cathodic/anodic phase.
interphase_dur (float, optional, default: 0) – Duration (ms) of the gap between cathodic and anodic phases.
delay_dur (float) – Delay duration (ms). Zeros will be inserted at the beginning of the stimulus to deliver the first pulse phase after
delay_durms.stim_dur (float, optional, default:) –
2*phase_dur+interphase_dur+delay_durTotal stimulus duration (ms). Zeros will be inserted at the end of the stimulus to make the stimulus laststim_durms overall.cathodic_first (bool, optional, default: True) – If True, will deliver the cathodic pulse phase before the anodic one.
electrode ({ int | string }, optional, default: 0) – Optionally, you can provide your own electrode name.
Notes
The order of the two phases is given by the
cathodic_firstflag.A biphasic pulse created with this class will always be considered “charge-balanced”.
Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,450 * us), which are converted to those units. Seepulse2percept.units.The parameters above are read-only. A pulse with different parameters is a different pulse; build another one.
ampreads back as a magnitude, because that is all of it that reaches the waveform: the constructor takesnp.abs(amp)and gets the polarity fromcathodic_first.
Examples
A cathodic-first pulse (1ms phase duration at 20uA, no interphase gap) delivered after 2ms and embedded in a stimulus that lasts 10ms overall:
>>> from pulse2percept.stimuli import BiphasicPulse >>> pulse = BiphasicPulse(-20, 1, delay_dur=2, stim_dur=10)
- property amp
Magnitude (uA) of both pulse phases
- property phase_dur
Duration (ms) of the cathodic/anodic phase
- property interphase_dur
Duration (ms) of the gap between the two phases
- property delay_dur
Delay (ms) before the first phase is delivered
- property stim_dur
Total stimulus duration (ms)
- property duration
Stimulus duration (ms)
The waveform is built to end exactly at
stim_dur, so this is known without generating one.
- property cathodic_first
Whether the cathodic phase is delivered first
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.BiphasicPulseTrain(freq, amp, phase_dur, interphase_dur=0, delay_dur=0, n_pulses=None, stim_dur=1000.0, cathodic_first=True, electrode=None, metadata=None, threshold_amp=None)[source]
Symmetric biphasic pulse train
A train of symmetric biphasic pulses.
Added in version 0.6.
- Parameters:
freq (float) – Pulse train frequency (Hz).
amp (float) –
Current amplitude (uA). Negative currents: cathodic, positive: anodic. The sign will be converted automatically depending on
cathodic_first.May also be given as a multiple of perceptual threshold, e.g.
2 * xTh(seexTh). The current that realizes it isamp * threshold_amp, so without a threshold the train stays measured inxTh.phase_dur (float) – Duration (ms) of the cathodic/anodic phase.
interphase_dur (float, optional, default: 0) – Duration (ms) of the gap between cathodic and anodic phases.
delay_dur (float) – Delay duration (ms). Zeros will be inserted at the beginning of the stimulus to deliver the first pulse phase after
delay_durms.n_pulses (int) – Number of pulses requested in the pulse train. If None, the entire stimulation window (
stim_dur) is filled.stim_dur (float, optional, default: 1000 ms) – Total stimulus duration (ms). The pulse train will be trimmed to make the stimulus last
stim_durms overall.cathodic_first (bool, optional, default: True) – If True, will deliver the cathodic pulse phase before the anodic one.
electrode ({ int | string }, optional, default: 0) – Optionally, you can provide your own electrode name.
metadata (dict) – A dictionary of meta-data
threshold_amp (float, optional) –
Perceptual threshold (uA) of the electrode this train drives. It is what converts between
amp_factorand a current, in either direction.Added in version 0.10.0.
Notes
Each cycle (“window”) of the pulse train consists of a symmetric biphasic pulse, created with
BiphasicPulse.The order and sign of the two phases (cathodic/anodic) of each pulse in the train is automatically adjusted depending on the
cathodic_firstflag.A pulse train will be considered “charge-balanced” if its net current is smaller than 10 picoamps.
Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,450 * us), which are converted to those units. Seepulse2percept.units.A train holds a current or a multiple of threshold, and
unitsays which. Converting between them takes a threshold, so anxThtrain without one stays measured inxTh– and is not yet something an implant can deliver.
Examples
Twice threshold, on an electrode whose threshold has been measured:
>>> from pulse2percept.stimuli import BiphasicPulseTrain >>> from pulse2percept.units import uA, xTh >>> pt = BiphasicPulseTrain(20, 2 * xTh, 0.45, threshold_amp=80 * uA) >>> pt.amp, pt.amp_factor (160.0, 2.0)
The same stimulation, expressed as the current it delivers:
>>> pt = BiphasicPulseTrain(20, 160.0 * uA, 0.45, threshold_amp=80 * uA) >>> pt.amp, pt.amp_factor (160.0, 2.0)
With no threshold it is still 2xTh, but it is no longer a current:
>>> pt = BiphasicPulseTrain(20, 2.0 * xTh, 0.45) >>> pt.amp_factor, pt.unit, pt.threshold_amp (2.0, xTh, None)
- property freq
Pulse train frequency (Hz)
- property n_pulses
Number of pulses delivered
- property stim_dur
Total stimulus duration (ms)
- property duration
Stimulus duration (ms)
- property threshold_amp
Perceptual threshold (uA) this train’s amplitude is relative to
The implant calibration in force, else the threshold this train was built with, else None.
Added in version 0.10.0.
- property amp_factor
Amplitude as a multiple of
threshold_ampNone only for a current with no threshold to measure it against: an
xThamplitude is the multiple, threshold or no threshold.Added in version 0.10.0.
- property phase_dur
Duration (ms) of the cathodic/anodic phase
- property interphase_dur
Duration (ms) of the gap between the two phases
- property delay_dur
Delay (ms) before the first phase of each pulse
- property cathodic_first
Whether the cathodic phase is delivered first
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.BiphasicTripletTrain(freq, amp, phase_dur, interphase_dur=0, interpulse_dur=0, delay_dur=0, n_pulses=None, stim_dur=1000.0, cathodic_first=True, electrode=None, metadata=None)[source]
Biphasic pulse triplets
A train of symmetric biphasic pulse triplets.
Added in version 0.6.
- Parameters:
freq (float) – Pulse train frequency (Hz).
amp (float) – Current amplitude (uA). Negative currents: cathodic, positive: anodic. The sign will be converted automatically depending on
cathodic_first.phase_dur (float) – Duration (ms) of the cathodic/anodic phase.
interphase_dur (float, optional, default: 0) – Duration (ms) of the gap between cathodic and anodic phases.
delay_dur (float) – Delay duration (ms). Zeros will be inserted at the beginning of the stimulus to deliver the first pulse phase after
delay_durms.interpulse_dur (float, optional, default: 0) – Delay duration (ms) between each biphasic pulse within the train. Note, this delay is also applied after the third biphasic pulse
n_pulses (int) – Number of pulses requested in the pulse train. If None, the entire stimulation window (
stim_dur) is filled.stim_dur (float, optional, default: 1000 ms) – Total stimulus duration (ms). The pulse train will be trimmed to make the stimulus last
stim_durms overall.cathodic_first (bool, optional, default: True) – If True, will deliver the cathodic pulse phase before the anodic one.
electrode ({ int | string }, optional, default: 0) – Optionally, you can provide your own electrode name.
metadata (dict) – A dictionary of meta-data
Notes
Each cycle (“window”) of the pulse train consists of three biphasic pulses, created with
BiphasicPulse.The order and sign of the two phases (cathodic/anodic) of each pulse in the train is automatically adjusted depending on the
cathodic_firstflag.A pulse train will be considered “charge-balanced” if its net current is smaller than 10 picoamps.
Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,450 * us), which are converted to those units. Seepulse2percept.units.
- property freq
Pulse train frequency (Hz)
- property n_pulses
Number of pulses delivered
- property stim_dur
Total stimulus duration (ms)
- property duration
Stimulus duration (ms)
- property amp
Magnitude (uA) of both phases of each pulse
- property phase_dur
Duration (ms) of the cathodic/anodic phase
- property interphase_dur
Duration (ms) of the gap between the two phases
- property interpulse_dur
Delay (ms) after each pulse of the triplet
- property delay_dur
Delay (ms) before the first phase of each pulse
- property cathodic_first
Whether the cathodic phase is delivered first
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.Encoder(implant=None)[source]
Base class for encoders.
An encoder converts a desired visual target into stimulation for a prosthetic system. Each subclass defines the target representation it accepts and implements
encode().Only an
ImplantEncodercan be installed onImplant.encoder.Added in version 0.11.0.
- Parameters:
implant (
Implant, optional) – The implant to encode for. Once bound, an encoder cannot be rebound.
- property implant
The implant this encoder is bound to, or None (read-only)
- class pulse2percept.stimuli.FrequencyEncoder(implant=None, freq_range=(0, 300), amp=50, **kwargs)[source]
Encode gray levels as pulse train frequencies
Every electrode emits pulses of the same fixed amplitude, and the gray level of the pixel it sees sets how often they come.
Important
Frequency modulation is far more expensive to simulate than amplitude modulation, because electrodes pulsing at different rates do not pulse at the same times: the stimulus needs a time point wherever any electrode’s pulse has an edge, rather than the handful of time points that amplitude modulation shares between all of them.
clockis the lever that cuts that down, and it is physically motivated: real stimulators have a time base. Encoding a 94-frame clip for Argus II at frequencies in (0, 300] Hz:setting
time points
(amplitude modulation)
442
no quantization
143,771
clock=121,505
clock=210,893
n_levels=8127,327
clock=1, n_levels=820,917
clockis not free, though: it buys those time points with frequency resolution, and it spends it at the top of the range where the periods are shortest. Againstfreq_range=(0, 300),clock=1delivers the brightest pixels at 250 Hz rather than 300, andclock=2at 200 Hz. Pick it against the fastest train you actually need.n_levelsis a much weaker lever here than the numbers above might suggest, and only worth reaching for onceclockis set. Because the pulse clock keeps its phase across frames, two electrodes quantized onto the same gray level still pulse at different times unless their whole history matches; quantizing gray levels no longer collapses them onto a shared schedule the way it would if every frame restarted the train.A raster cuts the cost too, and for the same reason a clock does: it confines every onset to the raster grid.
Added in version 0.10.0.
- Parameters:
implant (
Implant, optional) – The implant to encode for. SeePulseEncoder.freq_range ((min_freq, max_freq), optional) –
Range of pulse train frequencies (Hz). A gray level of 0 maps onto
min_freqand a gray level of 1 ontomax_freq. A frequency of 0 means no pulse at all.Note
Realizable frequencies are quantized by
clock, and, when a raster is in play, onto the raster sweep – which under frequency modulation is the usual case, since the electrodes are by construction on differing rates. Every period becomes a whole number of sweeps, so the realizable rates are1000 / (m * sweep)Hz.How coarse that grid is depends on how the sweep was set. With
group_dur=Nonethe sweep is the shortest period asked for, so the fastest electrode keeps its rate and pulses once per sweep while slower ones pulse every m-th. With an explicitgroup_durthe sweep isn_groups * group_durand unrelated to any requested rate, so even the fastest electrode is generally rounded: against a six-group 1 ms sweep, a requested 100 Hz (10 ms) is delivered as 83.3 Hz (12 ms, two sweeps).Quantizing onto the sweep always rounds the period up, so an electrode is never driven faster than it was asked for: against a 10 ms sweep, 67 Hz comes back as 50 Hz rather than 100 Hz. Rounding to the nearest sweep instead would deliver up to twice the charge the caller asked for. Shorten
group_durfor a finer grid.amp (float, optional) – Pulse amplitude (uA), the same for every electrode.
phase_dur – See
PulseEncoder.interphase_dur – See
PulseEncoder.cathodic_first – See
PulseEncoder.pulse – See
PulseEncoder.clock – See
PulseEncoder.n_levels – See
PulseEncoder.frame_dur – See
PulseEncoder.stretch – See
PulseEncoder.
Notes
Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,460 * us,0.02 * kHz), which are converted to those units. Seepulse2percept.units.
Examples
Encode a movie for Argus II at 50 uA, mapping gray levels onto 0-300 Hz on a 1 ms stimulator clock. A 300 Hz period is 3.3 ms, which Argus II’s own six-group 2 ms raster sweep does not fit into, so this device drives every electrode at once:
>>> import numpy as np >>> import pulse2percept as p2p >>> video = p2p.stimuli.VideoStimulus(np.random.rand(16, 20, 30), ... metadata={'fps': 30}) >>> implant = p2p.implants.retina.ArgusII(raster=None) >>> encoder = p2p.stimuli.FrequencyEncoder(implant, freq_range=(0, 300), ... amp=50, clock=1) >>> stim = encoder.encode(video)
- encode(source)[source]
Encode an image or a video as a train of electrical pulses
- Parameters:
source (
Stimulus) – The image or video to encode. Gray levels are expected in [0, 1], which is whatImageStimulusandVideoStimulusproduce. It must be dimensionless: this method is the boundary at which a picture becomes stimulation, so an electrical stimulus is not a valid source for it.- Returns:
stim – The encoded stimulus, ready for the implant to deliver. Its amplitudes are in microamps, or in threshold multiples (
xTh) if the encoder’s amplitude parameters were, and its time axis is in milliseconds, whatever units the encoder’s own parameters were given in.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- property implant
The implant this encoder is bound to, or None (read-only)
- class pulse2percept.stimuli.GratingStimulus(**kwargs)[source]
Drifting sinusoidal grating
A drifting sinusoidal grating of a given spatial and temporal frequency.
Added in version 0.7.
- Parameters:
shape (
(height, width)) – A tuple specifying the desired height (pixels) and the width (pixels) of the grating stimulus.direction (scalar in [0, 360) degrees or Quantity, optional) – Drift direction of the grating.
spatial_freq (scalar (cycles/pixel), optional) – Spatial frequency of the grating in cycles per pixel
temporal_freq (scalar (cycles/frame), optional) – Temporal frequency of the grating in cycles per frame
phase (scalar (degrees) or Quantity, optional) – The initial phase of the grating in degrees
contrast (scalar in [0, 1], optional) – Stimulus contrast between 0 and 1
time (scalar, array-like, or None; optional) –
The time points at which to evaluate the drifting grating:
If a scalar,
timeis interpreted as the end time (in milliseconds) of a time series with 50 Hz frame rate.If array-like,
timeis interpreted as the exact time points (in milliseconds) at which to draw the grating (end point included).If None,
timedefaults to a 1-second time series at 50 Hz frame rate (end point included).
mask ({'gauss', 'circle', None}) –
Stimulus mask:
”gauss”: a 2D Gaussian designed such that the border of the image lies at 3 standard deviations
”circle”: a circle that fits into the
shapeof the stimulusNone: no mask
electrodes (int, string or list thereof; optional, default: None) – Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image: a letter for the row, a number for the column, and a suffix for the color channel (e.g. ‘A1’, ‘C12’, ‘A1_R’).
metadata (dict, optional, default: None) – Additional stimulus metadata can be stored in a dictionary.
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- apply(func, *args, electrodes=None, **kwargs)[source]
Apply a function to each frame of the video
Changed in version 0.10.0:
funcmay now change the shape of a frame, andelectrodescan name the result.- Parameters:
func (function) – The function to apply to each frame in the video. Must accept a 2D or 3D image and return a 2D or 3D image. The returned frames need not have the same shape as the originals (but must all have the same shape as each other); see
electrodes.*args – Additional positional arguments passed to the function
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, the original names are carried over whenever
funcleaves the shape of a frame alone, and the result is named after its place in the new frame otherwise (e.g. forskimage.transform.resize).Note
The number of electrode names provided must match the number of pixels in a returned frame.
**kwargs – Additional keyword arguments passed to the function
- Returns:
stim – A copy of the stimulus object with the new video
- Return type:
VideoStimulus
- center(loc=None)[source]
Center the image foreground
This function shifts the center of mass (CoM) to the image center.
- Parameters:
loc ((col, row), optional) – The pixel location at which to center the CoM. By default, shifts the CoM to the image center.
- Returns:
stim – A copy of the stimulus object containing the centered image
- Return type:
ImageStimulus
- compress()[source]
Compress the source data
Also brings
vid_shapeback in line with the compressed data: compression drops the time points at which the video does not change, so the frame count of the source is no longer the frame count of the stimulus. Everydata.reshape(vid_shape)in this module relies on that invariant. (Compression can also drop all-zero pixels, in which case no shape describes the data any more; see_frames.)- Returns:
compressed
- Return type:
- crop(idx_space=None, idx_time=None, left=0, right=0, top=0, bottom=0, front=0, back=0, electrodes=None)[source]
Crop the video
This method maps a rectangle (defined by two corners) from each video frame to a rectangle of the given size. Similarly, the video can be shortened to a specified range of frames.
Alternatively, this method can be used to crop a number of columns either from the left or the right of the video frame, or a number of rows either from the top or the bottom, or a number of frames from the front (beginning) or back (end) of the video.
Added in version 0.8.
- Parameters:
idx_space (4-tuple (y0, x0, y1, x1)) – Image indices of the top-left corner
[y0, x0]and bottom-right corner[y1, x1](exclusive) of the rectangle to crop.idx_time (tuple (t0, t1)) – Frame indices defining the start
t0and endt1of the cropped video.left (int) – Number of columns to crop from the left of each video frame
right (int) – Number of columns to crop from the right of each video frame
top (int) – Number of rows to crop from the top of each video frame
bottom (int) – Number of rows to crop from the bottom of each video frame
front (int) – Number of frames to crop from the front (beginning) of the video
back (int) – Number of frames to crop from the back (end) of the video
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the cropped image.
- Returns:
stim – A copy of the stimulus object containing the video
- Return type:
VideoStimulus
- crop_square()[source]
Crop each video frame to the largest centered square
Frames are cropped without resizing. If their dimensions differ by an odd number of pixels, the extra pixel is removed from the bottom or right.
Added in version 0.11.0.
- Returns:
stim – A copy of the stimulus containing the centered square crop.
- Return type:
VideoStimulus
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property duration
Stimulus duration (ms)
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- encode(amp_range=(0, 50), freq=20, implant=None, **kwargs)[source]
Encode the video using amplitude modulation
Encodes every frame of the video as a train of biphasic pulses, where the gray level of a pixel sets the amplitude of its pulses. Each train lasts one frame period.
This is a shorthand for
AmplitudeEncoder; use that directly for the full set of options.Changed in version 0.10.0: Gray levels now map onto
amp_rangeabsolutely rather than being stretched to fill it (passstretch=Truefor the old behavior), each frame receives a pulse train rather than a single pulse, andimplantencodes at electrode rather than pixel resolution.- Parameters:
amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto
min_amp, a gray level of 1 ontomax_amp.freq (float, optional) – Pulse train frequency (Hz).
implant (
Implant, optional) – If given, the video is first sampled at the implant’s electrode locations, so that the pulse trains are built at electrode rather than pixel resolution. Strongly recommended: a video has orders of magnitude more pixels than an implant has electrodes.**kwargs – Additional arguments passed to
AmplitudeEncoder.
- Returns:
stim – Encoded stimulus
- Return type:
- filter(filt, **kwargs)[source]
Filter each frame of the video
- Parameters:
filt (str) –
Image filter that will be applied to every frame of the video. Additional parameters can be passed as keyword arguments. The following filters are supported:
’sobel’: Edge filter the image using the Sobel filter.
’scharr’: Edge filter the image using the Scarr filter.
’canny’: Edge filter the image using the Canny algorithm. You can also specify
sigma,low_threshold,high_threshold,mask, anduse_quantiles.’median’: Return local median of the image.
**kwargs – Additional parameters passed to the filter
- Returns:
stim – A copy of the stimulus object with the filtered image
- Return type:
VideoStimulus
- invert()[source]
Invert the gray levels of the video
- Returns:
stim – A copy of the stimulus object with all grayscale values inverted in the range [0, 1].
- Return type:
VideoStimulus
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- play(fps=None, repeat=True, annotate_time=True, ax=None, fmt='jpg')[source]
Animate the video as HTML with JavaScript
The video will be played in an interactive player in IPython or Jupyter Notebook.
- Parameters:
fps (float or None) – If None, uses the video’s time axis. Not supported for non-homogeneous time axis. May be given as a plain number of hertz or as a unitful frequency (e.g.
30 * Hz,0.03 * kHz); seepulse2percept.units.repeat (bool, optional) – Whether the animation should repeat when the sequence of frames is completed.
annotate_time (bool, optional) – If True, the time of the frame will be shown as t = X ms in the title of the panel.
ax (matplotlib.axes.AxesSubplot, optional) – A Matplotlib axes object. If None, will create a new Axes object
fmt ({'jpg', 'png'}, optional) –
The image format used to embed the frames. ‘jpg’ keeps notebooks and doc pages an order of magnitude smaller; use ‘png’ if you need the frames to be pixel-exact.
Added in version 0.10.0.
- Returns:
ani – A Matplotlib animation object that will play the video frame-by-frame.
- Return type:
Notes
Changed in version 0.10.0: The HTML player is now generated by
HTMLAnimation, which renders the figure once and ships all frames as a single sprite sheet. This is roughly two orders of magnitude faster than Matplotlib’sto_jshtmland produces much smaller notebooks and doc pages.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- resize(shape, electrodes=None, **kwargs)[source]
Resize the video
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
shape ((rows, cols)) – Shape of each frame in the resized video. If one of the dimensions is set to -1, its value will be inferred by keeping a constant aspect ratio.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the resized video.
**kwargs – Additional keyword arguments passed to skimage.transform.resize, such as
order=0for nearest-neighbor interpolation (which keeps a binary video binary).
- Returns:
stim – A copy of the stimulus object containing the resized video
- Return type:
VideoStimulus
- rgb2gray(electrodes=None)[source]
Convert the video to grayscale
- Parameters:
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale video.
- Returns:
stim – A copy of the stimulus object with all RGB values converted to grayscale in the range [0, 1].
- Return type:
VideoStimulus
- rotate(angle, mode='constant', electrodes=None, **kwargs)[source]
Rotate each frame of the video
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
angle (float or Quantity) – Angle by which to rotate each video frame (degrees). Positive: counter-clockwise, negative: clockwise
mode (str, optional) – How to fill in the corners the rotation leaves empty; see skimage.transform.rotate.
electrodes (int, string or list thereof; optional) – Optionally, you can provide your own electrode names. If none are given, each pixel keeps the name it had before the rotation, unless
resize=Truegrew the frame, in which case the enlarged video is named after its own pixel grid.**kwargs – Additional keyword arguments passed to skimage.transform.rotate, such as
order,cval, orresize=Trueto grow each frame so that it contains every rotated pixel.
- Returns:
stim – A copy of the stimulus object containing the rotated video
- Return type:
VideoStimulus
- scale(scaling_factor)[source]
Scale the image foreground
This function scales the image foreground (excluding black pixels) by a factor.
- Parameters:
scaling_factor (float) – Factory by which to scale the image
- Returns:
stim – A copy of the stimulus object containing the scaled image
- Return type:
ImageStimulus
- property shape
Data container shape
- shift(shift_cols, shift_rows)[source]
Shift the image foreground
This function shifts the center of mass (CoM) of the image by the specified number of rows and columns.
- Parameters:
- Returns:
stim – A copy of the stimulus object containing the shifted image
- Return type:
ImageStimulus
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- trim(tol=0, electrodes=None)[source]
Remove any black border around the video
Added in version 0.7.
- Parameters:
tol (float) – Any pixels with gray levels > tol will be trimmed.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in each frame of the trimmed video.
- Returns:
stim – A copy of the stimulus object with trimmed borders.
- Return type:
VideoStimulus
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.ImageStimulus[source]
A stimulus made from an image, where each pixel gets assigned to an electrode, and grayscale values in the range [0, 255] get converted to activation values in the range [0, 1].
See also
Basic Concepts > Electrical Stimuli <topics-stimuli>
Added in version 0.7.
- Parameters:
source (str, os.PathLike, ImageStimulus, or np.ndarray) –
Path to an image file (
strorpathlib.Path). File types are inferred from the file ending (support types include JPG, PNG, and TIF).Note
For GIFs, use
VideoStimulus.Changed in version 0.11.0: A
pathlib.Pathis accepted wherever a filename is.metadata['source']is always a string.resize (
(height, width)or None, optional) – Shape of the resized image. If one of the dimensions is set to -1, its value will be inferred by keeping a constant aspect ratio.as_gray (bool, optional) – Flag whether to convert the image to grayscale. A four-channel image is interpreted as RGBA (e.g., a PNG), and the alpha channel will be blended with the color black.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image: a letter for the row, a number for the column, and a suffix for the color channel (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the (resized) image.
metadata (dict, optional) – Additional stimulus metadata can be stored in a dictionary.
compress (bool, optional) – If True, will remove pixels with 0 grayscale value.
- apply(func, *args, electrodes=None, **kwargs)[source]
Apply a function to the image
Changed in version 0.10.0:
funcmay now change the shape of the image, andelectrodescan name the result.- Parameters:
func (function) – The function to apply to the image. Must accept a 2D or 3D image and return a 2D or 3D image. The returned image need not have the same shape as the original; see
electrodes.args (*) – Additional positional arguments passed to the function
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, the original names are carried over whenever
funcleaves the shape of the image alone, and the result is named after its place in the new image otherwise (e.g. forskimage.transform.resize).Note
The number of electrode names provided must match the number of pixels in the returned image.
**kwargs – Additional keyword arguments passed to the function
- Returns:
stim – A copy of the stimulus object with the new image
- Return type:
ImageStimulus
- invert()[source]
Invert the gray levels of the image
- Returns:
stim – A copy of the stimulus object with all grayscale values inverted in the range [0, 1].
- Return type:
ImageStimulus
- rgb2gray(electrodes=None)[source]
Convert the image to grayscale
- Parameters:
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale image.
- Returns:
stim – A copy of the stimulus object with all RGB values converted to grayscale in the range [0, 1].
- Return type:
ImageStimulus
Notes
A four-channel image is interpreted as RGBA (e.g., a PNG), and the alpha channel will be blended with the color black.
- resize(shape, electrodes=None, **kwargs)[source]
Resize the image
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
shape ((rows, cols)) – Shape of the resized image
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale image.
**kwargs – Additional keyword arguments passed to skimage.transform.resize, such as
order=0for nearest-neighbor interpolation (which keeps a binary image binary).
- Returns:
stim – A copy of the stimulus object containing the resized image
- Return type:
ImageStimulus
- crop(idx_rect=None, left=0, right=0, top=0, bottom=0, electrodes=None)[source]
Crop the image
This method maps a rectangle (defined by two corners) from the image to a rectangle of the given size. Alternatively, this method can be used to crop a number of columns either from the left or the right of the image, or a number of rows either from the top or the bottom.
Added in version 0.8.
- Parameters:
idx_rect (4-tuple (y0, x0, y1, x1)) – Image indices of the top-left corner
[y0, x0]and bottom-right corner[y1, x1](exclusive) of the rectangle to crop.left (int) – Number of columns to crop from the left
right (int) – Number of columns to crop from the right
top (int) – Number of rows to crop from the top
bottom (int) – Number of rows to crop from the bottom
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the cropped image.
- Returns:
stim – A copy of the stimulus object containing the cropped image
- Return type:
ImageStimulus
- crop_square()[source]
Crop the image to the largest centered square
The image is cropped without resizing. If its dimensions differ by an odd number of pixels, the extra pixel is removed from the bottom or right.
Added in version 0.11.0.
- Returns:
stim – A copy of the stimulus containing the centered square crop.
- Return type:
ImageStimulus
- trim(tol=0, electrodes=None)[source]
Remove any black border around the image
Added in version 0.7.
- Parameters:
tol (float) – Any pixels with gray levels > tol will be trimmed.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the trimmed image.
- Returns:
stim – A copy of the stimulus object with trimmed borders.
- Return type:
ImageStimulus
- threshold(thresh, **kwargs)[source]
Threshold the image
- Parameters:
If a float in [0,1] is provided, pixels whose grayscale value is above said threshold will be white, others black.
A number of additional methods are supported:
’mean’: Threshold image based on the mean of grayscale values.
- ’minimum’: Threshold image based on the minimum method, where
the histogram of the input image is computed and smoothed until there are only two maxima.
’local’: Threshold image based on local pixel neighborhood. Requires
block_size: odd number of pixels in the neighborhood.’otsu’: Otsu’s method
’isodata’: ISODATA method, also known as the Ridler-Calvard method or intermeans.
- Returns:
stim – A copy of the stimulus object with two gray levels 0.0 and 1.0
- Return type:
ImageStimulus
- rotate(angle, mode='constant', electrodes=None, **kwargs)[source]
Rotate the image
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
angle (float or Quantity) – Angle by which to rotate the image (degrees). Positive: counter-clockwise, negative: clockwise
mode (str, optional) – How to fill in the corners the rotation leaves empty; see skimage.transform.rotate.
electrodes (int, string or list thereof; optional) – Optionally, you can provide your own electrode names. If none are given, each pixel keeps the name it had before the rotation, unless
resize=Truegrew the canvas, in which case the enlarged image is named after its own pixel grid.**kwargs – Additional keyword arguments passed to skimage.transform.rotate, such as
order,cval, orresize=Trueto grow the image so that it contains every rotated pixel.
- Returns:
stim – A copy of the stimulus object containing the rotated image
- Return type:
ImageStimulus
- shift(shift_cols, shift_rows)[source]
Shift the image foreground
This function shifts the center of mass (CoM) of the image by the specified number of rows and columns.
- Parameters:
- Returns:
stim – A copy of the stimulus object containing the shifted image
- Return type:
ImageStimulus
- center(loc=None)[source]
Center the image foreground
This function shifts the center of mass (CoM) to the image center.
- Parameters:
loc ((col, row), optional) – The pixel location at which to center the CoM. By default, shifts the CoM to the image center.
- Returns:
stim – A copy of the stimulus object containing the centered image
- Return type:
ImageStimulus
- scale(scaling_factor)[source]
Scale the image foreground
This function scales the image foreground (excluding black pixels) by a factor.
- Parameters:
scaling_factor (float) – Factory by which to scale the image
- Returns:
stim – A copy of the stimulus object containing the scaled image
- Return type:
ImageStimulus
- filter(filt, **kwargs)[source]
Filter the image
- Parameters:
filt (str) –
Image filter. Additional parameters can be passed as keyword arguments. The following filters are supported:
’sobel’: Edge filter the image using the Sobel filter.
’scharr’: Edge filter the image using the Scharr filter.
’canny’: Edge filter the image using the Canny algorithm. You can also specify
sigma,low_threshold,high_threshold,mask, anduse_quantiles.’median’: Return local median of the image.
**kwargs – Additional parameters passed to the filter
- Returns:
stim – A copy of the stimulus object with the filtered image
- Return type:
ImageStimulus
- encode(amp_range=(0, 50), freq=20, implant=None, **kwargs)[source]
Encode the image using amplitude modulation
Encodes the image as a train of biphasic pulses, where the gray level of a pixel sets the amplitude of its pulses.
This is a shorthand for
AmplitudeEncoder; use that directly for the full set of options.Changed in version 0.10.0: Gray levels now map onto
amp_rangeabsolutely rather than being stretched to fill it (passstretch=Truefor the old behavior), the image receives a pulse train rather than a single pulse, andimplantencodes at electrode rather than pixel resolution.- Parameters:
amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto
min_amp, a gray level of 1 ontomax_amp.freq (float, optional) – Pulse train frequency (Hz). The image is treated as a single frame lasting 500 ms unless
frame_dursays otherwise.implant (
Implant, optional) – If given, the image is first sampled at the implant’s electrode locations, so that the pulse trains are built at electrode rather than pixel resolution.**kwargs – Additional arguments passed to
AmplitudeEncoder.
- Returns:
stim – Encoded stimulus
- Return type:
- plot(ax=None, **kwargs)[source]
Plot the stimulus
- Parameters:
ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object or a list thereof (one per electrode to plot). If None, a new Axes object will be created.
- Returns:
ax – Returns the axes with the plot on it
- Return type:
- save(fname, vmin=0, vmax=None)[source]
Save the stimulus as an image
- Parameters:
fname (str or os.PathLike) –
The name of the image file to be created. Image type will be inferred from the file extension.
Changed in version 0.11.0: A
pathlib.Pathis accepted.
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property duration
Stimulus duration (ms)
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.ImplantEncoder(implant=None)[source]
Base class for encoders installable on an implant.
An implant encoder accepts the dimensionless
Stimulus(image or video gray levels) thatImplant.prepare_stimproduces, and can therefore be assigned toImplant.encoder. Assigning an unbound encoder binds it to that implant.Added in version 0.11.0.
- abstractmethod encode(source)[source]
Encode a visual target as stimulation
- Parameters:
source – The visual target to encode, in the representation the subclass accepts.
- Returns:
stim – The encoded stimulus, in the unit that drives the device.
- Return type:
- property implant
The implant this encoder is bound to, or None (read-only)
- class pulse2percept.stimuli.LogoBVL(**kwargs)[source]
Bionic Vision Lab (BVL) logo
Load the 576x720x4 Bionic Vision Lab (BVL) logo.
Added in version 0.7.
- Parameters:
resize (
(height, width)or None, optional) – A tuple specifying the desired height and the width of the image stimulus.electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image: a letter for the row, a number for the column, and a suffix for the color channel (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the (resized) image.
metadata (dict, optional) – Additional stimulus metadata can be stored in a dictionary.
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- apply(func, *args, electrodes=None, **kwargs)[source]
Apply a function to the image
Changed in version 0.10.0:
funcmay now change the shape of the image, andelectrodescan name the result.- Parameters:
func (function) – The function to apply to the image. Must accept a 2D or 3D image and return a 2D or 3D image. The returned image need not have the same shape as the original; see
electrodes.args (*) – Additional positional arguments passed to the function
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, the original names are carried over whenever
funcleaves the shape of the image alone, and the result is named after its place in the new image otherwise (e.g. forskimage.transform.resize).Note
The number of electrode names provided must match the number of pixels in the returned image.
**kwargs – Additional keyword arguments passed to the function
- Returns:
stim – A copy of the stimulus object with the new image
- Return type:
ImageStimulus
- center(loc=None)[source]
Center the image foreground
This function shifts the center of mass (CoM) to the image center.
- Parameters:
loc ((col, row), optional) – The pixel location at which to center the CoM. By default, shifts the CoM to the image center.
- Returns:
stim – A copy of the stimulus object containing the centered image
- Return type:
ImageStimulus
- crop(idx_rect=None, left=0, right=0, top=0, bottom=0, electrodes=None)[source]
Crop the image
This method maps a rectangle (defined by two corners) from the image to a rectangle of the given size. Alternatively, this method can be used to crop a number of columns either from the left or the right of the image, or a number of rows either from the top or the bottom.
Added in version 0.8.
- Parameters:
idx_rect (4-tuple (y0, x0, y1, x1)) – Image indices of the top-left corner
[y0, x0]and bottom-right corner[y1, x1](exclusive) of the rectangle to crop.left (int) – Number of columns to crop from the left
right (int) – Number of columns to crop from the right
top (int) – Number of rows to crop from the top
bottom (int) – Number of rows to crop from the bottom
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the cropped image.
- Returns:
stim – A copy of the stimulus object containing the cropped image
- Return type:
ImageStimulus
- crop_square()[source]
Crop the image to the largest centered square
The image is cropped without resizing. If its dimensions differ by an odd number of pixels, the extra pixel is removed from the bottom or right.
Added in version 0.11.0.
- Returns:
stim – A copy of the stimulus containing the centered square crop.
- Return type:
ImageStimulus
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property duration
Stimulus duration (ms)
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- encode(amp_range=(0, 50), freq=20, implant=None, **kwargs)[source]
Encode the image using amplitude modulation
Encodes the image as a train of biphasic pulses, where the gray level of a pixel sets the amplitude of its pulses.
This is a shorthand for
AmplitudeEncoder; use that directly for the full set of options.Changed in version 0.10.0: Gray levels now map onto
amp_rangeabsolutely rather than being stretched to fill it (passstretch=Truefor the old behavior), the image receives a pulse train rather than a single pulse, andimplantencodes at electrode rather than pixel resolution.- Parameters:
amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto
min_amp, a gray level of 1 ontomax_amp.freq (float, optional) – Pulse train frequency (Hz). The image is treated as a single frame lasting 500 ms unless
frame_dursays otherwise.implant (
Implant, optional) – If given, the image is first sampled at the implant’s electrode locations, so that the pulse trains are built at electrode rather than pixel resolution.**kwargs – Additional arguments passed to
AmplitudeEncoder.
- Returns:
stim – Encoded stimulus
- Return type:
- filter(filt, **kwargs)[source]
Filter the image
- Parameters:
filt (str) –
Image filter. Additional parameters can be passed as keyword arguments. The following filters are supported:
’sobel’: Edge filter the image using the Sobel filter.
’scharr’: Edge filter the image using the Scharr filter.
’canny’: Edge filter the image using the Canny algorithm. You can also specify
sigma,low_threshold,high_threshold,mask, anduse_quantiles.’median’: Return local median of the image.
**kwargs – Additional parameters passed to the filter
- Returns:
stim – A copy of the stimulus object with the filtered image
- Return type:
ImageStimulus
- invert()[source]
Invert the gray levels of the image
- Returns:
stim – A copy of the stimulus object with all grayscale values inverted in the range [0, 1].
- Return type:
ImageStimulus
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(ax=None, **kwargs)[source]
Plot the stimulus
- Parameters:
ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object or a list thereof (one per electrode to plot). If None, a new Axes object will be created.
- Returns:
ax – Returns the axes with the plot on it
- Return type:
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- resize(shape, electrodes=None, **kwargs)[source]
Resize the image
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
shape ((rows, cols)) – Shape of the resized image
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale image.
**kwargs – Additional keyword arguments passed to skimage.transform.resize, such as
order=0for nearest-neighbor interpolation (which keeps a binary image binary).
- Returns:
stim – A copy of the stimulus object containing the resized image
- Return type:
ImageStimulus
- rgb2gray(electrodes=None)[source]
Convert the image to grayscale
- Parameters:
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale image.
- Returns:
stim – A copy of the stimulus object with all RGB values converted to grayscale in the range [0, 1].
- Return type:
ImageStimulus
Notes
A four-channel image is interpreted as RGBA (e.g., a PNG), and the alpha channel will be blended with the color black.
- rotate(angle, mode='constant', electrodes=None, **kwargs)[source]
Rotate the image
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
angle (float or Quantity) – Angle by which to rotate the image (degrees). Positive: counter-clockwise, negative: clockwise
mode (str, optional) – How to fill in the corners the rotation leaves empty; see skimage.transform.rotate.
electrodes (int, string or list thereof; optional) – Optionally, you can provide your own electrode names. If none are given, each pixel keeps the name it had before the rotation, unless
resize=Truegrew the canvas, in which case the enlarged image is named after its own pixel grid.**kwargs – Additional keyword arguments passed to skimage.transform.rotate, such as
order,cval, orresize=Trueto grow the image so that it contains every rotated pixel.
- Returns:
stim – A copy of the stimulus object containing the rotated image
- Return type:
ImageStimulus
- save(fname, vmin=0, vmax=None)[source]
Save the stimulus as an image
- Parameters:
fname (str or os.PathLike) –
The name of the image file to be created. Image type will be inferred from the file extension.
Changed in version 0.11.0: A
pathlib.Pathis accepted.
- scale(scaling_factor)[source]
Scale the image foreground
This function scales the image foreground (excluding black pixels) by a factor.
- Parameters:
scaling_factor (float) – Factory by which to scale the image
- Returns:
stim – A copy of the stimulus object containing the scaled image
- Return type:
ImageStimulus
- property shape
Data container shape
- shift(shift_cols, shift_rows)[source]
Shift the image foreground
This function shifts the center of mass (CoM) of the image by the specified number of rows and columns.
- Parameters:
- Returns:
stim – A copy of the stimulus object containing the shifted image
- Return type:
ImageStimulus
- threshold(thresh, **kwargs)[source]
Threshold the image
- Parameters:
If a float in [0,1] is provided, pixels whose grayscale value is above said threshold will be white, others black.
A number of additional methods are supported:
’mean’: Threshold image based on the mean of grayscale values.
- ’minimum’: Threshold image based on the minimum method, where
the histogram of the input image is computed and smoothed until there are only two maxima.
’local’: Threshold image based on local pixel neighborhood. Requires
block_size: odd number of pixels in the neighborhood.’otsu’: Otsu’s method
’isodata’: ISODATA method, also known as the Ridler-Calvard method or intermeans.
- Returns:
stim – A copy of the stimulus object with two gray levels 0.0 and 1.0
- Return type:
ImageStimulus
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- trim(tol=0, electrodes=None)[source]
Remove any black border around the image
Added in version 0.7.
- Parameters:
tol (float) – Any pixels with gray levels > tol will be trimmed.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the trimmed image.
- Returns:
stim – A copy of the stimulus object with trimmed borders.
- Return type:
ImageStimulus
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.LogoUCSB(**kwargs)[source]
UCSB logo
Load a 324x727 white-on-black logo of the University of California, Santa Barbara.
Added in version 0.7.
- Parameters:
resize (
(height, width)or None, optional) – A tuple specifying the desired height and the width of the image stimulus.electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image: a letter for the row, a number for the column, and a suffix for the color channel (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the (resized) image.
metadata (dict, optional) – Additional stimulus metadata can be stored in a dictionary.
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- apply(func, *args, electrodes=None, **kwargs)[source]
Apply a function to the image
Changed in version 0.10.0:
funcmay now change the shape of the image, andelectrodescan name the result.- Parameters:
func (function) – The function to apply to the image. Must accept a 2D or 3D image and return a 2D or 3D image. The returned image need not have the same shape as the original; see
electrodes.args (*) – Additional positional arguments passed to the function
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, the original names are carried over whenever
funcleaves the shape of the image alone, and the result is named after its place in the new image otherwise (e.g. forskimage.transform.resize).Note
The number of electrode names provided must match the number of pixels in the returned image.
**kwargs – Additional keyword arguments passed to the function
- Returns:
stim – A copy of the stimulus object with the new image
- Return type:
ImageStimulus
- center(loc=None)[source]
Center the image foreground
This function shifts the center of mass (CoM) to the image center.
- Parameters:
loc ((col, row), optional) – The pixel location at which to center the CoM. By default, shifts the CoM to the image center.
- Returns:
stim – A copy of the stimulus object containing the centered image
- Return type:
ImageStimulus
- crop(idx_rect=None, left=0, right=0, top=0, bottom=0, electrodes=None)[source]
Crop the image
This method maps a rectangle (defined by two corners) from the image to a rectangle of the given size. Alternatively, this method can be used to crop a number of columns either from the left or the right of the image, or a number of rows either from the top or the bottom.
Added in version 0.8.
- Parameters:
idx_rect (4-tuple (y0, x0, y1, x1)) – Image indices of the top-left corner
[y0, x0]and bottom-right corner[y1, x1](exclusive) of the rectangle to crop.left (int) – Number of columns to crop from the left
right (int) – Number of columns to crop from the right
top (int) – Number of rows to crop from the top
bottom (int) – Number of rows to crop from the bottom
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the cropped image.
- Returns:
stim – A copy of the stimulus object containing the cropped image
- Return type:
ImageStimulus
- crop_square()[source]
Crop the image to the largest centered square
The image is cropped without resizing. If its dimensions differ by an odd number of pixels, the extra pixel is removed from the bottom or right.
Added in version 0.11.0.
- Returns:
stim – A copy of the stimulus containing the centered square crop.
- Return type:
ImageStimulus
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property duration
Stimulus duration (ms)
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- encode(amp_range=(0, 50), freq=20, implant=None, **kwargs)[source]
Encode the image using amplitude modulation
Encodes the image as a train of biphasic pulses, where the gray level of a pixel sets the amplitude of its pulses.
This is a shorthand for
AmplitudeEncoder; use that directly for the full set of options.Changed in version 0.10.0: Gray levels now map onto
amp_rangeabsolutely rather than being stretched to fill it (passstretch=Truefor the old behavior), the image receives a pulse train rather than a single pulse, andimplantencodes at electrode rather than pixel resolution.- Parameters:
amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto
min_amp, a gray level of 1 ontomax_amp.freq (float, optional) – Pulse train frequency (Hz). The image is treated as a single frame lasting 500 ms unless
frame_dursays otherwise.implant (
Implant, optional) – If given, the image is first sampled at the implant’s electrode locations, so that the pulse trains are built at electrode rather than pixel resolution.**kwargs – Additional arguments passed to
AmplitudeEncoder.
- Returns:
stim – Encoded stimulus
- Return type:
- filter(filt, **kwargs)[source]
Filter the image
- Parameters:
filt (str) –
Image filter. Additional parameters can be passed as keyword arguments. The following filters are supported:
’sobel’: Edge filter the image using the Sobel filter.
’scharr’: Edge filter the image using the Scharr filter.
’canny’: Edge filter the image using the Canny algorithm. You can also specify
sigma,low_threshold,high_threshold,mask, anduse_quantiles.’median’: Return local median of the image.
**kwargs – Additional parameters passed to the filter
- Returns:
stim – A copy of the stimulus object with the filtered image
- Return type:
ImageStimulus
- invert()[source]
Invert the gray levels of the image
- Returns:
stim – A copy of the stimulus object with all grayscale values inverted in the range [0, 1].
- Return type:
ImageStimulus
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(ax=None, **kwargs)[source]
Plot the stimulus
- Parameters:
ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object or a list thereof (one per electrode to plot). If None, a new Axes object will be created.
- Returns:
ax – Returns the axes with the plot on it
- Return type:
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- resize(shape, electrodes=None, **kwargs)[source]
Resize the image
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
shape ((rows, cols)) – Shape of the resized image
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale image.
**kwargs – Additional keyword arguments passed to skimage.transform.resize, such as
order=0for nearest-neighbor interpolation (which keeps a binary image binary).
- Returns:
stim – A copy of the stimulus object containing the resized image
- Return type:
ImageStimulus
- rgb2gray(electrodes=None)[source]
Convert the image to grayscale
- Parameters:
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale image.
- Returns:
stim – A copy of the stimulus object with all RGB values converted to grayscale in the range [0, 1].
- Return type:
ImageStimulus
Notes
A four-channel image is interpreted as RGBA (e.g., a PNG), and the alpha channel will be blended with the color black.
- rotate(angle, mode='constant', electrodes=None, **kwargs)[source]
Rotate the image
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
angle (float or Quantity) – Angle by which to rotate the image (degrees). Positive: counter-clockwise, negative: clockwise
mode (str, optional) – How to fill in the corners the rotation leaves empty; see skimage.transform.rotate.
electrodes (int, string or list thereof; optional) – Optionally, you can provide your own electrode names. If none are given, each pixel keeps the name it had before the rotation, unless
resize=Truegrew the canvas, in which case the enlarged image is named after its own pixel grid.**kwargs – Additional keyword arguments passed to skimage.transform.rotate, such as
order,cval, orresize=Trueto grow the image so that it contains every rotated pixel.
- Returns:
stim – A copy of the stimulus object containing the rotated image
- Return type:
ImageStimulus
- save(fname, vmin=0, vmax=None)[source]
Save the stimulus as an image
- Parameters:
fname (str or os.PathLike) –
The name of the image file to be created. Image type will be inferred from the file extension.
Changed in version 0.11.0: A
pathlib.Pathis accepted.
- scale(scaling_factor)[source]
Scale the image foreground
This function scales the image foreground (excluding black pixels) by a factor.
- Parameters:
scaling_factor (float) – Factory by which to scale the image
- Returns:
stim – A copy of the stimulus object containing the scaled image
- Return type:
ImageStimulus
- property shape
Data container shape
- shift(shift_cols, shift_rows)[source]
Shift the image foreground
This function shifts the center of mass (CoM) of the image by the specified number of rows and columns.
- Parameters:
- Returns:
stim – A copy of the stimulus object containing the shifted image
- Return type:
ImageStimulus
- threshold(thresh, **kwargs)[source]
Threshold the image
- Parameters:
If a float in [0,1] is provided, pixels whose grayscale value is above said threshold will be white, others black.
A number of additional methods are supported:
’mean’: Threshold image based on the mean of grayscale values.
- ’minimum’: Threshold image based on the minimum method, where
the histogram of the input image is computed and smoothed until there are only two maxima.
’local’: Threshold image based on local pixel neighborhood. Requires
block_size: odd number of pixels in the neighborhood.’otsu’: Otsu’s method
’isodata’: ISODATA method, also known as the Ridler-Calvard method or intermeans.
- Returns:
stim – A copy of the stimulus object with two gray levels 0.0 and 1.0
- Return type:
ImageStimulus
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- trim(tol=0, electrodes=None)[source]
Remove any black border around the image
Added in version 0.7.
- Parameters:
tol (float) – Any pixels with gray levels > tol will be trimmed.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the trimmed image.
- Returns:
stim – A copy of the stimulus object with trimmed borders.
- Return type:
ImageStimulus
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.MonophasicPulse(amp, phase_dur, delay_dur=0, stim_dur=None, electrode=None)[source]
Monophasic pulse
A simple stimulus consisting of a single monophasic pulse (either cathodic/negative or anodic/positive).
Added in version 0.6.
Changed in version 0.10.0: The pulse retains the parameters that define it, and generates its sampled waveform only when one is asked for.
- Parameters:
amp (float) – Current amplitude (uA). Negative currents: cathodic, positive: anodic.
phase_dur (float) – Duration (ms) of the cathodic or anodic phase.
delay_dur (float) – Delay duration (ms). Zeros will be inserted at the beginning of the stimulus to deliver the pulse after
delay_durms.stim_dur (float, optional) – Total stimulus duration (ms). Zeros will be inserted at the end of the stimulus to make the stimulus last
stim_durms overall.electrode ({ int | string }, optional) – Optionally, you can provide your own electrode name.
Notes
The sign of
ampwill determine whether the pulse is cathodic (negative current) or anodic (positive current).A regular monophasic pulse is not considered “charge-balanced”. However, if
ampis small enough, the pulse can be considered “charge-balanced” if its net current is smaller than 10 picoamps.Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.05 * mA,450 * us), which are converted to those units. Seepulse2percept.units.The parameters above are read-only. A pulse with different parameters is a different pulse; build another one.
Examples
A single cathodic pulse (1ms phase duration at 20uA) delivered after 2ms and embedded in a stimulus that lasts 10ms overall:
>>> from pulse2percept.stimuli import MonophasicPulse >>> pulse = MonophasicPulse(-20, 1, delay_dur=2, stim_dur=10)
- property amp
Current amplitude (uA); negative is cathodic
- property phase_dur
Duration (ms) of the cathodic or anodic phase
- property delay_dur
Delay (ms) before the pulse is delivered
- property stim_dur
Total stimulus duration (ms)
- property duration
Stimulus duration (ms)
The waveform is built to end exactly at
stim_dur, so this is known without generating one.
- property cathodic
Whether the pulse delivers a negative current
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.PhotovoltaicEncoder(implant=None, *, irradiance, freq, pulse_dur, wavelength, grayscale=True, threshold=0.5)[source]
Encode image/video gray levels as pulsed optical stimulation
Photovoltaic subretinal arrays are driven by pulsed near-infrared light. This encoder samples an image or video at the implant’s pixel locations and returns irradiance in
mW/mm^2. Peak irradiance is fixed; gray level sets the ON duration within each pulse period.Added in version 0.11.0.
Changed in version 0.11.0: The implant is passed to the constructor rather than to
encode(). The optical parameters are keyword-only.- Parameters:
implant (
Implant, optional) – The implant to encode for. Its pixel locations are used to sample images and videos and its pixel names label the result. If None, every pixel of the source is its own photovoltaic pixel.irradiance (float or Quantity) – Peak irradiance (mW/mm^2) while a pixel is on.
pulse_dur (float or Quantity) – ON duration (ms) of a fully lit pixel. Must fit into
1000 / freq.wavelength (float or Quantity) – Wavelength (nm) of the illumination. Photovoltaic pixel response is wavelength dependent, so there is no generic default.
grayscale (bool, optional) – If True (default), map gray levels to ON duration. If False, use binary off/on encoding.
threshold (float, optional) – Binary-mode threshold. The default 0.5 is a pulse2percept convention.
Notes
Grayscale mode scales ON duration linearly,
gray * pulse_dur. The studies these arrays come from report fixed-duration pulses and do not specify a natural-image grayscale transfer function, so this mapping is a pulse2percept simulation convention, not the experimental encoding protocol. Because durations are continuous, an image with many gray levels produces more distinct time points than a device that quantizes duration (seePRIMAEncoder).Videos are sampled at the pulse rate using zero-order hold.
_spatial_viewreturns normalized time-averaged optical drive, where 1.0 is a fully lit pixel at these settings (ref_drive). It is neither retinal current nor perceptual brightness.Photovoltaic conversion to retinal current is not modeled.
Examples
>>> from pulse2percept.implants.retina import Lorach2015Array >>> from pulse2percept.stimuli import PhotovoltaicEncoder, samples >>> encoder = PhotovoltaicEncoder(Lorach2015Array(), irradiance=4, ... freq=40, pulse_dur=4, wavelength=915) >>> encoder.encode(samples.logo_bvl()).unit mW/mm^2
- property period
Pulse period (ms)
- property ref_drive
Time-averaged irradiance (mW/mm^2) the normalized view calls 1.0
A fully lit pixel at these settings. Devices with a documented projector maximum normalize against that maximum instead.
- encode(source)[source]
Encode an image or a video as near-infrared irradiance
- Parameters:
source (
Stimulus) – The image or video to encode. Gray levels are expected in [0, 1], which is whatImageStimulusandVideoStimulusproduce. It must be dimensionless.- Returns:
stim – The projected irradiance, in
mW/mm^2, with a time axis in milliseconds. The waveform is generated only when samples are asked for.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- property implant
The implant this encoder is bound to, or None (read-only)
- class pulse2percept.stimuli.PRIMAEncoder(implant=None, irradiance=3.5 mW/mm^2, freq=30 Hz, pulse_dur=9.8 ms, grayscale=True, threshold=0.5)[source]
Encode image/video gray levels for the PRIMA projector.
PRIMA uses 880 nm illumination rather than injected current. The projector uses fixed peak irradiance and pulse-width modulation [Palanker2020], [Holz2026]. This encoder returns irradiance in
mW/mm^2.Unlike the generic
PhotovoltaicEncoder, ON durations are quantized onto the projector’s own 0.7 ms duration grid, and normalized drive is referenced to the projector maximum rather than to these settings.Added in version 0.11.0.
- Parameters:
implant (
Implant, optional) – The implant to encode for. SeePhotovoltaicEncoder.irradiance (float or Quantity, optional) – Peak irradiance (mW/mm^2) while a pixel is on.
freq (float or Quantity, optional) – Projector frame rate (Hz).
pulse_dur (float or Quantity, optional) – Maximum ON duration (ms). Must lie on the
pulse_stepgrid and not exceedmax_pulse_dur.grayscale (bool, optional) – If True (default), map gray levels to pulse duration. If False, use binary off/on encoding.
threshold (float, optional) – Binary-mode threshold. The default 0.5 is a pulse2percept convention.
Notes
Pivotal-system defaults are 3.5 mW/mm^2, 30 Hz, and 14 nonzero ON durations from 0.7 to 9.8 ms.
Grayscale mode maps normalized intensity linearly to these duration levels. The clinical camera-to-pulse-duration transfer function is not published.
Videos are sampled at the projector clock using zero-order hold.
_spatial_viewreturns normalized time-averaged optical drive for spatial models. It is neither retinal current nor perceptual brightness.Clinical image preprocessing is outside this encoder.
Examples
>>> from pulse2percept.implants.retina import PRIMAPivotal >>> from pulse2percept.stimuli import PRIMAEncoder, samples >>> PRIMAEncoder(PRIMAPivotal()).encode(samples.logo_bvl()).unit mW/mm^2
- pulse_step = 0.7
Smallest nonzero ON duration (ms) the projector can produce; every other duration is a whole multiple of it
- max_pulse_dur = 9.8
Longest documented ON duration (ms), i.e. 14 steps
- projector_wavelength = 880.0
Wavelength (nm) the projector illuminates at
- max_irradiance = 3.5
Peak irradiance (mW/mm^2) of the pivotal-trial projector
- max_freq = 30.0
Frame rate (Hz) of the pivotal-trial projector
- max_duty_cycle = 0.294
Largest documented duty cycle,
max_freq * max_pulse_dur
- ref_drive = 1.029
Time-averaged irradiance (mW/mm^2) the normalized spatial view calls 1.0. Fixed at the projector maximum, so lowering any setting lowers the normalized drive.
- property n_levels
Number of nonzero ON durations available up to
pulse_dur
- encode(source)[source]
Encode an image or a video as near-infrared irradiance
- Parameters:
source (
Stimulus) – The image or video to encode. Gray levels are expected in [0, 1], which is whatImageStimulusandVideoStimulusproduce. It must be dimensionless.- Returns:
stim – The projected irradiance, in
mW/mm^2, with a time axis in milliseconds. The waveform is generated only when samples are asked for.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- property implant
The implant this encoder is bound to, or None (read-only)
- property period
Pulse period (ms)
- class pulse2percept.stimuli.PulseEncoder(implant=None, phase_dur=0.46, interphase_dur=0, cathodic_first=True, pulse=None, clock=None, n_levels=None, frame_dur=None, stretch=False)[source]
Abstract base class for electrical pulse-train encoders.
Maps image or video gray levels onto the parameters of repeated electrical pulses. If the encoder has an implant, the source is sampled at its electrode locations and scheduled using its raster pattern.
Subclasses implement
_modulate(), which maps gray levels to pulse amplitude and frequency.Added in version 0.10.0.
Changed in version 0.11.0: Renamed from
StimulusEncoder. The implant is passed to the constructor rather than toencode().- Parameters:
implant (
Implant, optional) – The implant to encode for. Its electrode locations are used to sample images and videos, its electrode names label the result, and itsrasterdecides which electrodes may pulse when. If None, every pixel of the source is its own electrode and every electrode fires on the same schedule.phase_dur (float, optional) – Duration of each pulse phase (ms).
interphase_dur (float, optional) – Gap between cathodic and anodic phases (ms).
cathodic_first (bool, optional) – If True, deliver the cathodic phase first.
pulse (
Stimulus, optional) – Pulse shape to repeat. Its amplitude is normalized away.clock (float, optional) – Stimulator clock period (ms). Pulse periods and raster offsets are rounded to whole clock cycles.
n_levels (int, optional) – Number of gray levels used before modulation.
frame_dur (float, optional) – Frame duration (ms). If None, infer it from the source.
stretch (bool, optional) – If True, stretch source gray levels to [0, 1].
Notes
Plain numbers use the units documented above; unitful values are converted automatically. See
pulse2percept.units.- encode(source)[source]
Encode an image or a video as a train of electrical pulses
- Parameters:
source (
Stimulus) – The image or video to encode. Gray levels are expected in [0, 1], which is whatImageStimulusandVideoStimulusproduce. It must be dimensionless: this method is the boundary at which a picture becomes stimulation, so an electrical stimulus is not a valid source for it.- Returns:
stim – The encoded stimulus, ready for the implant to deliver. Its amplitudes are in microamps, or in threshold multiples (
xTh) if the encoder’s amplitude parameters were, and its time axis is in milliseconds, whatever units the encoder’s own parameters were given in.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- property implant
The implant this encoder is bound to, or None (read-only)
- class pulse2percept.stimuli.PulseTrain(freq, pulse, n_pulses=None, stim_dur=1000.0, electrode=None, metadata=None)[source]
Generic pulse train
Can be used to concatenate single pulses into a pulse train.
Added in version 0.6.
- Parameters:
freq (float) – Pulse train frequency (Hz).
pulse (
Stimulus) – A Stimulus object containing a single pulse that will be concatenated.n_pulses (int) – Number of pulses requested in the pulse train. If None, the entire stimulation window (
stim_dur) is filled.stim_dur (float, optional) – Total stimulus duration (ms). The pulse train will be trimmed to make the stimulus last
stim_durms overall.electrode ({ int | string }, optional) – Optionally, you can provide your own electrode name.
metadata (dict) – A dictionary of meta-data
Notes
Only pulses that fit whole are delivered. If the pulse train frequency does not exactly divide
stim_dur, the number of pulses is therefore rounded down: a 30 Hz train in a 33.37 ms window has one pulse, not one and a fraction of a second. A partial pulse would leave the train with a net current.A frequency slower than
1000 / stim_durcannot be realized, since the window still holds one pulse. Passfreq=0for a silent train.Arguments may be given as plain numbers in the units documented above, or as unitful quantities (e.g.
0.02 * kHz,1 * s), which are converted to those units. Seepulse2percept.units.The train is measured in whatever
pulsewas measured in: tiling an electrical pulse gives a train in microamps, and tiling a dimensionless one gives a dimensionless train.
- property freq
Pulse train frequency (Hz)
- property pulse
The single pulse this train repeats
- property n_pulses
Number of pulses delivered
- property stim_dur
Total stimulus duration (ms)
- property pulse_type
Name of the class the repeated pulse came from
- property duration
Stimulus duration (ms)
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- class pulse2percept.stimuli.Stimulus[source]
A stimulus is comprised of a labeled 2D NumPy array that contains the data, where the rows denote electrodes and the columns denote points in time. A stimulus can be created from a variety of source types (e.g., scalars, lists, NumPy arrays, and dictionaries).
The stimulus arrays (
data,time,electrodes) and the pulse parameters of a stimulus that has any are read-only. Arbitrary stimuli are kept as sampled waveforms only.See also
Basic Concepts > Electrical Stimuli <topics-stimuli>
Added in version 0.6.
Changed in version 0.10.0: Stimulus arrays and pulse parameters are read-only, and waveforms are generated lazily.
- Parameters:
source (source type) –
A valid source type is one of the following:
Scalar value: interpreted as the current amplitude delivered to a single electrode (no time component).
- NumPy array:
Nx1 array: interpreted as N current amplitudes delivered to N electrodes (no time component).
NxM array: interpreted as N electrodes each receiving M current amplitudes in time.
In addition, you can also pass a collection of source types. Each element must be a valid source type for a single electrode (e.g., scalar, 1-D array,
Stimulus).List or tuple: List elements will be assigned to electrodes in order.
Dictionary: Dictionary keys are used to address electrodes by name.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, electrode names will be extracted from the source type (e.g., the keys from a dictionary). If a scalar or NumPy array is passed, electrode names will be numbered 0..N.
Note
The number of electrode names provided must match the number of electrodes extracted from the source type (i.e., N).
time (int, float or list thereof; optional) –
Optionally, you can provide the time points of the source data. If none are given, time steps will be numbered 0..M.
Note
The number of time points provided must match the number of time points extracted from the source type (i.e., M). Stimuli created from scalars or 1-D NumPy arrays will have no time componenet, in which case you cannot provide your own time points.
metadata (dict, optional) – Additional stimulus metadata can be stored in a dictionary.
compress (bool, optional) –
If True, will compress the source data in two ways:
Remove electrodes with all-zero activation.
Retain only the time points at which the stimulus changes.
For example, in a pulse train, only the signal edges are saved. This drastically reduces the memory footprint of the stimulus.
Notes
Depending on the source type, a stimulus might have a time component or not (e.g., scalars: time=None).
You can access the stimulus applied to electrode
eat timetby directly indexing intoStimulus[e, t]. In this case,tis not a column index but a time point.If the time point is not explicitly stored in the
datacontainer, its value will be automatically interpolated from neighboring values.If a requested time point lies outside the range of stored data, the value of its closest end point will be returned.
All transformations return a new stimulus, except for
compress()andremove().
Examples
Stimulate a single electrode with -13uA:
>>> from pulse2percept.stimuli import Stimulus >>> stim = Stimulus(-13)
Stimulate ten electrodes with 0uA:
>>> from pulse2percept.stimuli import Stimulus >>> stim = Stimulus(np.zeros(10))
Provide new electrode names for an existing Stimulus object:
>>> from pulse2percept.stimuli import Stimulus >>> old_stim = Stimulus([3, 5]) >>> new_stim = Stimulus(old_stim, electrodes=['new0', 'new1'])
Interpolate the stimulus value at some point in time. Here, the stimulus is a single-electrode ramp stimulus (stimulus value == point in time):
>>> from pulse2percept.stimuli import Stimulus >>> stim = Stimulus(np.arange(10).reshape((1, -1))) >>> stim[:, 3.45] 3.45...
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- shift(dt)[source]
Shift the stimulus in time.
Added in version 0.10.0.
- Parameters:
dt (float or
Quantity) – Time shift. May be positive or negative. Bare values are interpreted in the stimulus’ time unit.- Returns:
shifted – Shifted copy of the stimulus.
- Return type:
Notes
stim >> dtandstim << dtare shorthand forstim.shift(dt)andstim.shift(-dt).
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property shape
Data container shape
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property time
A list of time steps (i.e., the columns in the data container)
- property is_compressed
Flag indicating whether the stimulus has been compressed
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property duration
Stimulus duration (ms)
- class pulse2percept.stimuli.TraceEncoder(model, *, amp=100 uA, freq=300 Hz, phase_dur=0.17 ms, step_dur=50 ms, interphase_dur=0 ms, cathodic_first=True, clock=None, region=None, threshold=0.5, prune_spurs=False)[source]
Encode a traced shape as sequential single-electrode pulses
A model-aware encoder: it uses the model’s
VisualFieldMapand implant placement to stimulate one electrode at a time, in trajectory order, forstep_dureach:image or ordered trajectory in visual field | ordered (x, y) trajectory in dva <- trajectory() | model.visual_field_map.from_dva()[region] | nearest placed physical electrode per sample <- electrode_sequence() | one step_dur pulse train per electrode <- encode()Unlike an
ImplantEncoder, it cannot be installed onImplant.encoder; callencode()directly.Accepted targets:
An
(N, 2)array of ordered(x, y)positions in dva.A grayscale
ImageStimulusof a single bright stroke on a dark background (e.g., a letter), placed in the visual field byextent. Pixels abovethresholdare skeletonized to a one-pixel centerline, which must form one open, nonbranching path. Withprune_spurs=True, short endpoint spurs produced by skeletonization near thick corners are removed before topology validation. The path starts at its endpoint that comes first in row-major order (topmost, then leftmost). Skeletonization can bend the end of a thick stroke by a pixel, which can change that endpoint. Usetrajectory()to check the direction, or pass an(N, 2)trajectory to set it.
Candidates are activated electrodes whose placed location has a finite
to_dvalocation, i.e. lies in the mapped region. Each sample is mapped on its own, so its electrode does not depend on the other samples.Consecutive samples that select the same electrode are collapsed into one step, so dense sampling does not lengthen a dwell. A later revisit of the same electrode is a new step.
Inspired by the dynamic letter-tracing paradigm of [Beauchamp2020]. This implementation uses physical electrodes only: it does not implement current steering or virtual electrodes, and does not reproduce that study’s protocol.
Added in version 0.11.0.
- Parameters:
model (model) – Model that places the implant in tissue. Requires
implant, an invertiblevisual_field_map(from_dvaandto_dva), and placed electrode coordinates (implant_position,implant_rotation,implant_depth). The encoder binds tomodel.implant.amp (float or Quantity, optional) – Pulse amplitude (uA, or
xThfor threshold multiples) on the active electrode.freq (float or Quantity, optional) – Pulse train frequency (Hz).
phase_dur (float or Quantity, optional) – Duration of each pulse phase (ms).
step_dur (float or Quantity, optional) – Stimulation time (ms) per trajectory step.
interphase_dur (float or Quantity, optional) – Gap between cathodic and anodic phases (ms).
cathodic_first (bool, optional) – If True, deliver the cathodic phase first.
clock (float or Quantity, optional) – Stimulator clock period (ms). See
PulseEncoder.region (str, optional) – Region of
visual_field_map.from_dva()to map onto, e.g. ‘v1’. Required if the map has more than one region.threshold (float, optional) – Gray level in [0, 1] above which an image pixel is part of the trace.
prune_spurs (bool, optional) – If True, short endpoint spurs produced by skeletonization near thick corners are removed before topology validation. This can also remove a short real branch. If False, any branch is rejected.
Notes
Pulse trains are built by
AmplitudeEncoderwithframe_dur=step_dur, so the implant’s raster applies.Sparse vertices are not interpolated. To trace a line, pass samples along it. An image trace has one sample per skeleton pixel, so the image resolution sets the sampling density.
The electrode sequence is determined by retinotopy and placement, so the path across the physical array can look unlike the visual trajectory.
DynaphosModelsimulates an encoded stimulus at its ownfreqandp_dur. Setfreqandphase_durto match them.Models with
location_noiseare not supported.
Examples
Trace a horizontal line at 2 dva below fixation with Orion in the right hemisphere (left visual field):
>>> import numpy as np >>> import pulse2percept as p2p >>> from pulse2percept.units import mm, uA, ms >>> implant = p2p.implants.cortex.Orion() >>> model = p2p.models.cortex.DynaphosModel( ... implant, implant_position=(20, -5) * mm) >>> encoder = p2p.stimuli.TraceEncoder(model, amp=100 * uA, ... freq=model.freq, ... phase_dur=model.p_dur, ... step_dur=50 * ms) >>> x = np.linspace(-6, -2, 41) >>> trace = np.column_stack([x, np.full_like(x, -2)]) >>> encoder.electrode_sequence(trace) ['41', '37', '38'] >>> stim = encoder.encode(trace)
The same line drawn as an image, one pixel per 0.1 dva:
>>> from pulse2percept.units import dva >>> line = np.zeros((9, 41)) >>> line[4, :] = 1 >>> target = p2p.stimuli.ImageStimulus(line) >>> extent = (-6.05, -1.95, -2.45, -1.55) * dva >>> encoder.trajectory(target, extent=extent)[[0, -1]] array([[-6., -2.], [-2., -2.]]) >>> encoder.electrode_sequence(target, extent=extent) ['41', '37', '38'] >>> stim = encoder.encode(target, extent=extent)
- trajectory(source, *, extent=None)[source]
Return the ordered visual-field trajectory of a target
- Parameters:
source ((N, 2) array_like, Quantity, or ImageStimulus) – Ordered
(x, y)samples in dva (bare numbers are dva), or a grayscale image of a single stroke.extent ((left, right, bottom, top) Quantity, optional) – Outer edges of the image in dva, as in
Scene.extent. Required for an image; not accepted for an(N, 2)trajectory.
- Returns:
xy – Ordered
(x, y)samples in dva. For an image, one sample per skeleton pixel center.- Return type:
(N, 2) np.ndarray
- electrode_sequence(source, *, extent=None)[source]
Return the electrodes a target stimulates, in order
- Parameters:
source – Target, as in
trajectory().extent – Target, as in
trajectory().
- Returns:
names – One electrode name per
step_durstep, with consecutive duplicates collapsed.- Return type:
- encode(source, *, extent=None)[source]
Encode a traced target as sequential pulse trains
- Parameters:
source – Target, as in
trajectory().extent – Target, as in
trajectory().
- Returns:
stim – Pulse trains in uA (or
xTh), onestep_durstep per selected electrode, lastingn_steps * step_durms. Rows are the visited electrodes in electrode-array order.- Return type:
- property implant
The implant this encoder is bound to, or None (read-only)
- class pulse2percept.stimuli.VideoStimulus[source]
A stimulus made from a movie file, where each pixel gets assigned to an electrode, and grayscale values in the range [0, 255] get assigned to activation values in the range [0, 1].
The frame rate of the movie is used to infer the time points at which to stimulate.
See also
Basic Concepts > Electrical Stimuli <topics-stimuli>
Added in version 0.7.
- Parameters:
source (str, os.PathLike, VideoStimulus, or np.ndarray) –
Path to a video file (
strorpathlib.Path). File types are inferred from the file ending (support types include MP4, AVI, MOV, and GIF). Enforce a specific format viaformat.Changed in version 0.11.0: A
pathlib.Pathis accepted wherever a filename is.metadata['source']is always a string.Alternatively, pass a <rows x columns x channels x frames> NumPy array or another
VideoStimulusobject.format (str) – A video format string supported by imageio, such as ‘MP4’, ‘AVI’, or ‘MOV’. Use if the file type cannot be inferred from
source. For a full list of supported formats, see https://imageio.readthedocs.io/en/stable/formats.html.resize (
(height, width)or None, optional, default: None) – A tuple specifying the desired height and the width of each video frameas_gray (bool, optional) – Flag whether to convert the image to grayscale. A four-channel image is interpreted as RGBA (e.g., a PNG), and the alpha channel will be blended with the color black.
electrodes (int, string or list thereof; optional, default: None) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image: a letter for the row, a number for the column, and a suffix for the color channel (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the (resized) image.
metadata (dict, optional, default: None) – Additional stimulus metadata can be stored in a dictionary.
compress (bool, optional, default: False) – If True, will compress the source data in two ways: * Remove electrodes with all-zero activation. * Retain only the time points at which the stimulus changes.
start_time (float or Quantity, optional, default: None) –
Load only the frames that start in the half-open interval
[start_time, stop_time)of the source video, in milliseconds. Time-based clipping requires the video reader to report a frame rate.Note
The clip starts at
time[0] == 0no matter where it was cut from. To shorten a video that is already in memory, and keep its original time stamps, usecrop()instead.Added in version 0.10.0.
stop_time (float or Quantity, optional, default: None) –
Load only the frames that start in the half-open interval
[start_time, stop_time)of the source video, in milliseconds. Time-based clipping requires the video reader to report a frame rate.Note
The clip starts at
time[0] == 0no matter where it was cut from. To shorten a video that is already in memory, and keep its original time stamps, usecrop()instead.Added in version 0.10.0.
- compress()[source]
Compress the source data
Also brings
vid_shapeback in line with the compressed data: compression drops the time points at which the video does not change, so the frame count of the source is no longer the frame count of the stimulus. Everydata.reshape(vid_shape)in this module relies on that invariant. (Compression can also drop all-zero pixels, in which case no shape describes the data any more; see_frames.)- Returns:
compressed
- Return type:
- apply(func, *args, electrodes=None, **kwargs)[source]
Apply a function to each frame of the video
Changed in version 0.10.0:
funcmay now change the shape of a frame, andelectrodescan name the result.- Parameters:
func (function) – The function to apply to each frame in the video. Must accept a 2D or 3D image and return a 2D or 3D image. The returned frames need not have the same shape as the originals (but must all have the same shape as each other); see
electrodes.*args – Additional positional arguments passed to the function
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, the original names are carried over whenever
funcleaves the shape of a frame alone, and the result is named after its place in the new frame otherwise (e.g. forskimage.transform.resize).Note
The number of electrode names provided must match the number of pixels in a returned frame.
**kwargs – Additional keyword arguments passed to the function
- Returns:
stim – A copy of the stimulus object with the new video
- Return type:
VideoStimulus
- invert()[source]
Invert the gray levels of the video
- Returns:
stim – A copy of the stimulus object with all grayscale values inverted in the range [0, 1].
- Return type:
VideoStimulus
- rgb2gray(electrodes=None)[source]
Convert the video to grayscale
- Parameters:
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the grayscale video.
- Returns:
stim – A copy of the stimulus object with all RGB values converted to grayscale in the range [0, 1].
- Return type:
VideoStimulus
- resize(shape, electrodes=None, **kwargs)[source]
Resize the video
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
shape ((rows, cols)) – Shape of each frame in the resized video. If one of the dimensions is set to -1, its value will be inferred by keeping a constant aspect ratio.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the resized video.
**kwargs – Additional keyword arguments passed to skimage.transform.resize, such as
order=0for nearest-neighbor interpolation (which keeps a binary video binary).
- Returns:
stim – A copy of the stimulus object containing the resized video
- Return type:
VideoStimulus
- crop(idx_space=None, idx_time=None, left=0, right=0, top=0, bottom=0, front=0, back=0, electrodes=None)[source]
Crop the video
This method maps a rectangle (defined by two corners) from each video frame to a rectangle of the given size. Similarly, the video can be shortened to a specified range of frames.
Alternatively, this method can be used to crop a number of columns either from the left or the right of the video frame, or a number of rows either from the top or the bottom, or a number of frames from the front (beginning) or back (end) of the video.
Added in version 0.8.
- Parameters:
idx_space (4-tuple (y0, x0, y1, x1)) – Image indices of the top-left corner
[y0, x0]and bottom-right corner[y1, x1](exclusive) of the rectangle to crop.idx_time (tuple (t0, t1)) – Frame indices defining the start
t0and endt1of the cropped video.left (int) – Number of columns to crop from the left of each video frame
right (int) – Number of columns to crop from the right of each video frame
top (int) – Number of rows to crop from the top of each video frame
bottom (int) – Number of rows to crop from the bottom of each video frame
front (int) – Number of frames to crop from the front (beginning) of the video
back (int) – Number of frames to crop from the back (end) of the video
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in the cropped image.
- Returns:
stim – A copy of the stimulus object containing the video
- Return type:
VideoStimulus
- crop_square()[source]
Crop each video frame to the largest centered square
Frames are cropped without resizing. If their dimensions differ by an odd number of pixels, the extra pixel is removed from the bottom or right.
Added in version 0.11.0.
- Returns:
stim – A copy of the stimulus containing the centered square crop.
- Return type:
VideoStimulus
- trim(tol=0, electrodes=None)[source]
Remove any black border around the video
Added in version 0.7.
- Parameters:
tol (float) – Any pixels with gray levels > tol will be trimmed.
electrodes (int, string or list thereof; optional) –
Optionally, you can provide your own electrode names. If none are given, each pixel is named after its place in the image (e.g. ‘A1’, ‘C12’, ‘A1_R’).
Note
The number of electrode names provided must match the number of pixels in each frame of the trimmed video.
- Returns:
stim – A copy of the stimulus object with trimmed borders.
- Return type:
VideoStimulus
- rotate(angle, mode='constant', electrodes=None, **kwargs)[source]
Rotate each frame of the video
Changed in version 0.10.0: Keyword arguments are passed on to scikit-image.
- Parameters:
angle (float or Quantity) – Angle by which to rotate each video frame (degrees). Positive: counter-clockwise, negative: clockwise
mode (str, optional) – How to fill in the corners the rotation leaves empty; see skimage.transform.rotate.
electrodes (int, string or list thereof; optional) – Optionally, you can provide your own electrode names. If none are given, each pixel keeps the name it had before the rotation, unless
resize=Truegrew the frame, in which case the enlarged video is named after its own pixel grid.**kwargs – Additional keyword arguments passed to skimage.transform.rotate, such as
order,cval, orresize=Trueto grow each frame so that it contains every rotated pixel.
- Returns:
stim – A copy of the stimulus object containing the rotated video
- Return type:
VideoStimulus
- shift(shift_cols, shift_rows)[source]
Shift the image foreground
This function shifts the center of mass (CoM) of the image by the specified number of rows and columns.
- Parameters:
- Returns:
stim – A copy of the stimulus object containing the shifted image
- Return type:
ImageStimulus
- center(loc=None)[source]
Center the image foreground
This function shifts the center of mass (CoM) to the image center.
- Parameters:
loc ((col, row), optional) – The pixel location at which to center the CoM. By default, shifts the CoM to the image center.
- Returns:
stim – A copy of the stimulus object containing the centered image
- Return type:
ImageStimulus
- scale(scaling_factor)[source]
Scale the image foreground
This function scales the image foreground (excluding black pixels) by a factor.
- Parameters:
scaling_factor (float) – Factory by which to scale the image
- Returns:
stim – A copy of the stimulus object containing the scaled image
- Return type:
ImageStimulus
- filter(filt, **kwargs)[source]
Filter each frame of the video
- Parameters:
filt (str) –
Image filter that will be applied to every frame of the video. Additional parameters can be passed as keyword arguments. The following filters are supported:
’sobel’: Edge filter the image using the Sobel filter.
’scharr’: Edge filter the image using the Scarr filter.
’canny’: Edge filter the image using the Canny algorithm. You can also specify
sigma,low_threshold,high_threshold,mask, anduse_quantiles.’median’: Return local median of the image.
**kwargs – Additional parameters passed to the filter
- Returns:
stim – A copy of the stimulus object with the filtered image
- Return type:
VideoStimulus
- encode(amp_range=(0, 50), freq=20, implant=None, **kwargs)[source]
Encode the video using amplitude modulation
Encodes every frame of the video as a train of biphasic pulses, where the gray level of a pixel sets the amplitude of its pulses. Each train lasts one frame period.
This is a shorthand for
AmplitudeEncoder; use that directly for the full set of options.Changed in version 0.10.0: Gray levels now map onto
amp_rangeabsolutely rather than being stretched to fill it (passstretch=Truefor the old behavior), each frame receives a pulse train rather than a single pulse, andimplantencodes at electrode rather than pixel resolution.- Parameters:
amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto
min_amp, a gray level of 1 ontomax_amp.freq (float, optional) – Pulse train frequency (Hz).
implant (
Implant, optional) – If given, the video is first sampled at the implant’s electrode locations, so that the pulse trains are built at electrode rather than pixel resolution. Strongly recommended: a video has orders of magnitude more pixels than an implant has electrodes.**kwargs – Additional arguments passed to
AmplitudeEncoder.
- Returns:
stim – Encoded stimulus
- Return type:
- append(other)[source]
Append another stimulus
This method appends another stimulus (with matching electrodes) in time. The combined stimulus duration will be the sum of the two individual stimuli.
Added in version 0.7.
- property data
Stimulus data container
A read-only 2-D NumPy array that contains the sampled waveform, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (duration of signal edge transitions)
Added in version 0.7.
- property duration
Stimulus duration (ms)
- property electrodes
Electrode names A list of electrode names, corresponding to the rows in the data container.
- property is_charge_balanced
Flag indicating whether the stimulus is charge-balanced
A stimulus with a time component is considered charge-balanced if its net current is smaller than 10 pico Amps. For the whole stimulus to be charge-balanced, every electrode must be charge-balanced as well.
Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current.
- property is_compressed
Flag indicating whether the stimulus has been compressed
- pad(duration)[source]
Pad the stimulus with zeros up to a given time.
Adds zero-valued endpoints at
t=0andt=durationas needed.durationspecifies the final time, not the amount of padding to add.Added in version 0.10.0.
- Parameters:
duration (float or
Quantity) – Final time of the padded stimulus. Bare values are interpreted in the stimulus’ time unit.- Returns:
padded – Padded copy of the stimulus.
- Return type:
Notes
Padding requires existing boundary values to be zero; otherwise interpolation would create a ramp. It never truncates the stimulus or removes negative time points.
- play(fps=None, repeat=True, annotate_time=True, ax=None, fmt='jpg')[source]
Animate the video as HTML with JavaScript
The video will be played in an interactive player in IPython or Jupyter Notebook.
- Parameters:
fps (float or None) – If None, uses the video’s time axis. Not supported for non-homogeneous time axis. May be given as a plain number of hertz or as a unitful frequency (e.g.
30 * Hz,0.03 * kHz); seepulse2percept.units.repeat (bool, optional) – Whether the animation should repeat when the sequence of frames is completed.
annotate_time (bool, optional) – If True, the time of the frame will be shown as t = X ms in the title of the panel.
ax (matplotlib.axes.AxesSubplot, optional) – A Matplotlib axes object. If None, will create a new Axes object
fmt ({'jpg', 'png'}, optional) –
The image format used to embed the frames. ‘jpg’ keeps notebooks and doc pages an order of magnitude smaller; use ‘png’ if you need the frames to be pixel-exact.
Added in version 0.10.0.
- Returns:
ani – A Matplotlib animation object that will play the video frame-by-frame.
- Return type:
Notes
Changed in version 0.10.0: The HTML player is now generated by
HTMLAnimation, which renders the figure once and ships all frames as a single sprite sheet. This is roughly two orders of magnitude faster than Matplotlib’sto_jshtmland produces much smaller notebooks and doc pages.
- plot(electrodes=None, time=None, fmt='k-', ax=None, kind=None)[source]
Plot the stimulus
Added in version 0.7.
Changed in version 0.10.0: Added
kind: a whole multi-electrode stimulus is now drawn as an electrode-by-time heatmap rather than as one subplot per electrode.- Parameters:
electrodes (int, string, or list thereof; optional, default: None) – The electrodes for which to plot the stimulus. If None, all electrodes are plotted.
time ((t_min, t_max) tuple, slice, or list of exact time points) – The time points at which to plot the stimulus. Specify a range of time points with a tuple or a slice, or specify the exact time points to interpolate. If None, all time points are plotted.
fmt (str, optional, default: 'k-') – A Matplotlib format string; e.g., ‘ro’ for red circles to use when
kind='traces'.ax (matplotlib.axes.Axes or list thereof; optional, default: None) – A Matplotlib Axes object.
kind='traces'also accepts a list thereof (one per electrode to plot);kind='heatmap'draws into a single Axes. If None, a new Axes object will be created.kind ({'traces', 'heatmap'}, optional, default: None) –
What to draw:
’traces’: the waveform of each electrode, one Axes per electrode. Good for a handful of electrodes.
’heatmap’: an electrode-by-time image in a single Axes. Good for a whole implant’s worth of electrodes.
If None, a whole stimulus of more than one electrode is drawn as a heatmap and everything else as traces.
- Returns:
ax – One Axes per electrode for
kind='traces', a single Axes forkind='heatmap'.- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property quantity
The stimulus data, with its unit attached
Added in version 0.10.0.
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA >>> Stimulus([500, 1000] * uA).quantity [[ 500.] [1000.]] uA
- remove(electrodes)[source]
Remove electrode(s)
Removes the stimulus of a certain electrode or list of electrodes.
Added in version 0.8.
- property shape
Data container shape
- property time
A list of time steps (i.e., the columns in the data container)
- property time_quantity
The stimulus time axis with its unit attached, or None
Added in version 0.10.0.
- property time_unit
The unit
timeis expressed inAdded in version 0.10.0.
- times(unit=None)[source]
The stimulus time axis, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the time axis in. If None,timeis returned as it is stored (milliseconds).- Returns:
times – An ordinary NumPy array, or None if the stimulus has no time component.
- Return type:
np.ndarray or None
- property unit
The unit
datais expressed inAdded in version 0.10.0.
- values(unit=None)[source]
The stimulus data, expressed in
unitAdded in version 0.10.0.
- Parameters:
unit (
Unit, optional) – The unit to express the data in. Must be compatible withunit. If None, the stimulus’ own unit is used anddatais returned as it is stored.- Returns:
values – An ordinary NumPy array, never a
Quantity.- Return type:
np.ndarray
Examples
>>> from pulse2percept.stimuli import Stimulus >>> from pulse2percept.units import uA, mA >>> Stimulus([500, 1000] * uA).values(mA) array([[0.5], [1. ]], dtype=float32)