pulse2percept.stimuli
Common electrical stimuli, such as charge-balanced square-wave pulse trains.
|
|
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 (
ProsthesisSystem, optional) – The implant to encode for; seeEncoder.amp_range ((min_amp, max_amp), optional) – Range of pulse amplitudes (uA). A gray level of 0 maps onto
min_ampand a gray level of 1 ontomax_amp.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
Encoder.interphase_dur – See
Encoder.cathodic_first – See
Encoder.frame_dur – See
Encoder.stretch – See
Encoder.
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 pulse2percept as p2p >>> implant = p2p.implants.ArgusII() >>> encoder = p2p.stimuli.AmplitudeEncoder(implant, amp_range=(0, 50)) >>> implant.stim = encoder.encode(p2p.stimuli.BostonTrain())
- 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 to assign to
implant.stim. Its amplitudes are in microamps and its time axis in milliseconds, whatever units the encoder’s own parameters were given in.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- 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.
- 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.
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)
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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(shape, direction=0, speed=0.1, bar_width=1, edge_width=3, px_btw_bars=None, start_pos=0, contrast=1, time=None, mask=None, electrodes=None, metadata=None)[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, 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’). See
ElectrodeNames.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). SeeElectrodeNames.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’). See
ElectrodeNames.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
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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 (
ProsthesisSystem, 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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.
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)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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’). See
ElectrodeNames.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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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’). See
ElectrodeNames.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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.
- 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.
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)
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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)[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.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
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.
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.BostonTrain(resize=None, electrodes=None, as_gray=False, metadata=None)[source]
Boston Train sequence
Load the Boston subway sequence, consisting of 94 frames of 240x426x3 pixels each.
Added in version 0.7.
- Parameters:
resize ((height, width) or None) – A tuple specifying the desired height and the width of the video stimulus.
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’). See
ElectrodeNames.Note
The number of electrode names provided must match the number of pixels in the (resized) video frame.
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.
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). SeeElectrodeNames.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’). See
ElectrodeNames.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
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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 (
ProsthesisSystem, 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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.
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)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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’). See
ElectrodeNames.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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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’). See
ElectrodeNames.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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.ElectrodeNames(grid_shape, idx=None, unique=None)[source]
Lazily generated electrode names for a grid of electrodes
Names every element of a (rows x columns [x channels]) grid after its position in that grid: letters address the row, digits the column, and an optional suffix the color channel. The first pixel of an RGB image is therefore
'A1_R', and the pixel in the third row and twelfth column of a grayscale image is'C12'.The names are not stored. Only the shape of the grid is, plus (for a subset such as a cropped image) the indices that were kept. Both directions of the mapping are computed from that: a name is generated from its index on demand, and the index of a name is recovered by parsing it. That keeps construction, copying and lookup independent of the number of electrodes, which matters because an image or video stimulus assigns one electrode per pixel – a 576x720 RGBA image has 1.66 million of them.
An
ElectrodeNamesbehaves like a read-only 1-D array of strings: it supportslen, iteration, indexing, slicing, boolean masking,reshapeandravel, and converts to a NumPy array of strings vianp.asarray. That conversion is the one operation whose cost scales with the number of electrodes, so it is left to the caller to trigger.Added in version 0.10.0.
- Parameters:
grid_shape (tuple) – Shape of the electrode grid:
(rows, cols)for a single-channel image, or(rows, cols, channels)for a multi-channel one.idx (array_like, optional) – Flat indices into the grid, selecting (and ordering) the names to expose. The array may have any shape;
Nonemeans the whole grid in row-major order.unique (bool, optional) – Whether
idxis known to be free of duplicates.Nonemeans “not known”, in which casecheck_unique()will work it out.
Examples
>>> from pulse2percept.stimuli import ElectrodeNames >>> names = ElectrodeNames((3, 4)) >>> names[0], names[6] ('A1', 'B3') >>> names.index('B3') 6
- property grid_shape
Shape of the underlying electrode grid
- property grid_size
Total number of electrodes in the underlying grid
- property indices
Flat indices into the grid, one per name
- property shape
Shape of the name container
- property size
Total number of names
- property ndim
Number of dimensions of the name container
- property dtype
Dtype the names would have if materialized
- property is_unique
Whether the names are known to be free of duplicates
Falsemeans “not known to be unique”, not “known to contain duplicates”; callcheck_unique()to settle it.
- index(name)[source]
Return the position of
nameUnlike
list(names).index(name), this does not build (or even generate) the names: the position is recovered by parsing the name itself, which is why it costs the same for one electrode as for a million.
- check_unique()[source]
Determine (and remember) whether the names are free of duplicates
The grid names are unique by construction, so duplicates can only come from a repeated index. Checking the indices is therefore equivalent to checking the names, and much cheaper.
- Returns:
unique – True if no name occurs twice.
- Return type:
- class pulse2percept.stimuli.Encoder(implant=None, phase_dur=0.46, interphase_dur=0, cathodic_first=True, pulse=None, clock=None, n_levels=None, raster=None, frame_dur=None, stretch=False)[source]
Abstract base class for all stimulus encoders
An encoder translates the gray levels of an image or a video into the electrical stimulus that a retinal implant would actually deliver: each electrode emits a train of biphasic pulses, and the gray level of the pixel that the electrode sees determines some property of that train.
Three clocks are involved, and they are deliberately independent of one another:
The frame clock belongs to the video. It says when the modulation parameters update; that is, a new frame is a new gray level, and hence a new amplitude or a new frequency. It is also the rate at which a percept is worth reporting, which is why it is recorded in the encoded stimulus’ metadata for
predict_percept()to pick up. It takes no part in the timing of the pulses themselves.The pulse clock belongs to
freq. It runs continuously for the whole stimulus rather than restarting at every frame, so the frame rate has no say in the rate delivered. A pulse takes the modulation parameters of the frame its onset falls into, so it is never cut in half by a frame boundary.The rate can still come out below the one requested, but only where the hardware you described cannot express it:
clock, and a raster with electrodes on differing rates, both round a pulse period up. Neither ever rounds down, so an electrode is never driven faster, and so never given more charge, than was asked for.The raster sweep belongs to the
Raster, and says which electrodes may pulse when, so that no two raster groups are ever active at the same instant.
All encoders share the same two-step structure:
Reduce the source to one gray level per electrode per frame. If the encoder was given an
implant, the source is first sampled at the electrode locations, so that everything downstream works at electrode resolution.Map those gray levels onto pulse train parameters (
_modulate), then assemble the pulse trains (_assemble).
Subclasses only implement
_modulate; everything else is provided here.Added in version 0.10.0.
- Parameters:
implant (
ProsthesisSystem, optional) – The implant to encode for. Its electrode locations are used to sample the source, and its electrode names label the resulting stimulus. If None, every pixel of the source is treated as its own electrode.phase_dur (float, optional) – Duration (ms) of the cathodic/anodic phase of each pulse.
interphase_dur (float, optional) – Duration (ms) of the gap between the cathodic and anodic phases.
cathodic_first (bool, optional) – If True, the cathodic phase of each pulse is delivered first. Most temporal models in
pulse2percept.modelstreat cathodic current as brightness-increasing, so bright pixels map onto cathodic-first pulses.pulse (
Stimulus, optional) – A single pulse to repeat, in place of the symmetric biphasic pulse built fromphase_dur,interphase_durandcathodic_first(which are then ignored). Only its shape is used: its amplitude is normalized away, since that is what the encoder sets, and its time axis is shifted to start at zero. It must start and end at zero amplitude, since it is tiled into a train.clock (float, optional) –
Period (ms) of the stimulator’s time base. Pulse periods and raster offsets are rounded to a whole number of clock cycles, as they would be on real hardware. If None, they are placed at the full resolution of the simulation (
DT= 1e-3 ms).Important
Every timing constraint here (the clock, and the raster sweep) may lower the rate an electrode ends up on, and none of them may raise it. Rounding a period down would deliver more charge than was asked for, so a time base that cannot represent a rate exactly gives back the nearest slower one it can.
That makes a coarse clock expensive in frequency: realizable periods are
clock,2*clock,3*clock, … , so withclock=1a requested 300 Hz (3.33 ms) is delivered as 250 Hz (4 ms), and withclock=3as 166.7 Hz. Choose it against the top of your frequency range rather than in the abstract.n_levels (int, optional) – Number of gray levels the encoder can distinguish, mimicking the resolution of the device’s input stage. Gray levels are rounded onto
n_levelsvalues evenly spaced over [0, 1] before being modulated. If None, they are taken at full precision.raster (
Raster, optional) – How the stimulator takes turns between electrodes it cannot drive at the same time. Each group starts its pulse a fixedgroup_durbehind the group before it, so no two groups are ever active at once. Where electrodes run at differing rates they would drift into one another, so there their periods are pinned to whole sweeps; electrodes sharing one rate cannot drift and keep their period exactly. If None, theimplant’s own raster is used, and failing that every electrode fires on the same schedule.frame_dur (float, optional) – Duration (ms) of a single frame. If None, it is inferred from the source’s frame rate (or, failing that, from its time axis). A source without a time axis, such as an
ImageStimulus, is treated as a single frame lasting 500 ms.stretch (bool, optional) –
If True, the gray levels of the source are stretched to fill [0, 1] before they are modulated, so that the darkest pixel maps onto the bottom of the modulation range and the brightest onto the top. If False (the default), gray levels are taken at face value: a gray level of 0.5 always maps onto the middle of the range no matter how bright the rest of the source is.
Note
Stretching makes the encoding depend on the content of the source. A uniform image has no range to stretch, and encodes to a stimulus of zero amplitude everywhere.
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.pulseis the exception: only its shape is borrowed and its amplitude is normalized away, so what that amplitude was measured in does not matter. A dimensionless waveform is a perfectly good template.
- 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 to assign to
implant.stim. Its amplitudes are in microamps and its time axis in milliseconds, whatever units the encoder’s own parameters were given in.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- 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 the 94-frameBostonTrainfor 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 (
ProsthesisSystem, optional) – The implant to encode for; seeEncoder.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
Encoder.interphase_dur – See
Encoder.cathodic_first – See
Encoder.pulse – See
Encoder.clock – See
Encoder.n_levels – See
Encoder.frame_dur – See
Encoder.stretch – See
Encoder.
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:
>>> import pulse2percept as p2p >>> implant = p2p.implants.ArgusII() >>> encoder = p2p.stimuli.FrequencyEncoder(implant, freq_range=(0, 300), ... amp=50, clock=1) >>> implant.stim = encoder.encode(p2p.stimuli.BostonTrain())
- 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 to assign to
implant.stim. Its amplitudes are in microamps and its time axis in milliseconds, whatever units the encoder’s own parameters were given in.- Return type:
- Raises:
DimensionMismatchError – If
sourceis not dimensionless.
- class pulse2percept.stimuli.GirlPool(resize=None, electrodes=None, as_gray=False, metadata=None)[source]
A girl jumping into a swimming pool
Load the “girl jumping in a pool” sequence, consisting of 91 frames of 240x426x3 pixels each.
Added in version 0.9.
- Parameters:
resize ((height, width) or None) – A tuple specifying the desired height and the width of the video stimulus.
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’). See
ElectrodeNames.Note
The number of electrode names provided must match the number of pixels in the (resized) video frame.
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.
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). SeeElectrodeNames.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’). See
ElectrodeNames.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
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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 (
ProsthesisSystem, 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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.
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)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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’). See
ElectrodeNames.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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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’). See
ElectrodeNames.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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.GratingStimulus(shape, direction=0, spatial_freq=0.1, temporal_freq=0.001, phase=0, contrast=1, time=None, mask=None, electrodes=None, metadata=None)[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, 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), 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’). See
ElectrodeNames.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). SeeElectrodeNames.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’). See
ElectrodeNames.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
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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 (
ProsthesisSystem, 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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.
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)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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’). See
ElectrodeNames.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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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’). See
ElectrodeNames.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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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, resize=None, as_gray=False, electrodes=None, metadata=None, compress=False)[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) – Path to image file. Supported image types include JPG, PNG, and TIF; and are inferred from the file ending. Use
VideoStimulusfor GIFs.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’). See
ElectrodeNames.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). SeeElectrodeNames.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’). See
ElectrodeNames.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’). See
ElectrodeNames.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’). See
ElectrodeNames.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
- 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’). See
ElectrodeNames.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.
neighborhood (.. _local pixel)
method (.. _ISODATA)
method
- 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) – 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. SeeElectrodeNames.**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
filter (.. _Scharr)
filter
algorithm (.. _Canny)
- 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 (
ProsthesisSystem, 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:
matplotlib.axes.Axes
- save(fname, vmin=0, vmax=None)[source]
Save the stimulus as an image
- Parameters:
fname (str) – The name of the image file to be created. Image type will be inferred from the file extension.
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.LogoBVL(resize=None, electrodes=None, metadata=None, as_gray=False)[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’). See
ElectrodeNames.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). SeeElectrodeNames.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’). See
ElectrodeNames.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
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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 (
ProsthesisSystem, 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
filter (.. _Scharr)
filter
algorithm (.. _Canny)
- 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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:
matplotlib.axes.Axes
- 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’). See
ElectrodeNames.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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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) – The name of the image file to be created. Image type will be inferred from the file extension.
- 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.
neighborhood (.. _local pixel)
method (.. _ISODATA)
method
- Returns:
stim – A copy of the stimulus object with two gray levels 0.0 and 1.0
- Return type:
ImageStimulus
- property time
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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’). See
ElectrodeNames.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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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(resize=None, electrodes=None, metadata=None)[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’). See
ElectrodeNames.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). SeeElectrodeNames.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’). See
ElectrodeNames.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
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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 (
ProsthesisSystem, 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
filter (.. _Scharr)
filter
algorithm (.. _Canny)
- 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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:
matplotlib.axes.Axes
- 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’). See
ElectrodeNames.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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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) – The name of the image file to be created. Image type will be inferred from the file extension.
- 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.
neighborhood (.. _local pixel)
method (.. _ISODATA)
method
- Returns:
stim – A copy of the stimulus object with two gray levels 0.0 and 1.0
- Return type:
ImageStimulus
- property time
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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’). See
ElectrodeNames.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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.
- 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.
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)
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.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.
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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.SnellenChart(resize=None, show_annotations=True, row=None, electrodes=None, metadata=None)[source]
Snellen chart
Load the 1348x840 Snellen chart commonly used to measure visual acuity.
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.
show_annotations ({True, False}, optional) – If True, show the full Snellen chart including annotations of the rows and corresponding acuity measures.
row (None, optional) – Select a single row (between 1 and 11) from the Snellen chart. For example, row 1 corresponds to 20/200, row 2 to 20/100.
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’). See
ElectrodeNames.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.
- 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). SeeElectrodeNames.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’). See
ElectrodeNames.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
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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 (
ProsthesisSystem, 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
filter (.. _Scharr)
filter
algorithm (.. _Canny)
- 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- 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:
matplotlib.axes.Axes
- 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’). See
ElectrodeNames.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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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) – The name of the image file to be created. Image type will be inferred from the file extension.
- 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.
neighborhood (.. _local pixel)
method (.. _ISODATA)
method
- Returns:
stim – A copy of the stimulus object with two gray levels 0.0 and 1.0
- Return type:
ImageStimulus
- property time
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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’). See
ElectrodeNames.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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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, electrodes=None, time=None, metadata=None, compress=False)[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).
See also
Basic Concepts > Electrical Stimuli <topics-stimuli>
Added in version 0.6.
- 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.
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.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- Return type:
matplotlib.axes.Axes or np.ndarray of them
- property data
Stimulus data container A 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property shape
Data container shape
- property unit
The unit
datais expressed inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().Added in version 0.10.0.
- property time_unit
The unit
timeis expressed in (milliseconds)Added 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. This is the boundary a numerical implementation should take its data across.- 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
Time steps A list of time steps, corresponding to the columns in the data container.
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property duration
Stimulus duration (ms)
- class pulse2percept.stimuli.VideoStimulus(source, format=None, resize=None, as_gray=False, electrodes=None, time=None, metadata=None, compress=False)[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) –
Path to video file. Supported file types include MP4, AVI, MOV, and GIF; and are inferred from the file ending. If the file does not have a proper file ending, specify the file type via
format.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 frame
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, 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’). See
ElectrodeNames.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.
- 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). SeeElectrodeNames.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’). See
ElectrodeNames.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’). See
ElectrodeNames.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’). See
ElectrodeNames.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
- 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’). See
ElectrodeNames.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) – 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. SeeElectrodeNames.**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 (
ProsthesisSystem, 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:
- 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.
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.
- 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 2-D NumPy array that contains the stimulus data, where the rows denote electrodes and the columns denote points in time.
- property dt
Sampling time step (ms)
Defines the duration of the 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.
Returns None if the stimulus is not a current at all: the gray levels of an
ImageStimulusintegrate to a number like any others, but that number is not a charge and asking whether it is zero answers nothing. Note that this is “not applicable”, not “unbalanced” – it issafe_modethat turns the question into an error, since a safety system genuinely cannot do its job on a stimulus that is not electrical.Changed in version 0.10.0: Returns None for a stimulus that is not measured in units of current (was: integrated the values anyway).
- property is_compressed
Flag indicating whether the stimulus has been compressed
Read-only: the flag is maintained by
compress. Assigning to it raises anAttributeError.
- plot(electrodes=None, time=None, fmt='k-', ax=None)[source]
Plot the stimulus
Added in version 0.7.
- 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.
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:
axes – Returns one matplotlib.axes.Axes per electrode
- 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
Time steps A list of time steps, corresponding to 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 in (milliseconds)Added 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 inMicroamps for an electrical stimulus, dimensionless for the gray levels of an
ImageStimulusorVideoStimulus.Read-only. The canonical storage unit is fixed so that models, safety checks and Cython kernels can rely on it; ask for another unit with
values().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. This is the boundary a numerical implementation should take its data across.- 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)