Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def stim(self, data):
"""Stimulus setter (called upon ``self.stim = data``)"""
if data is None:
self._stim = None
else:
if isinstance(data, Stimulus):
# Already a stimulus object:
stim = Stimulus(data, extrapolate=True)
elif isinstance(data, dict):
# Electrode names already provided by keys:
stim = Stimulus(data, extrapolate=True)
else:
# Use electrode names as stimulus coordinates:
stim = Stimulus(data, electrodes=list(self.earray.keys()),
extrapolate=True)
# Make sure all electrode names are valid:
for electrode in stim.electrodes:
# Invalid index will return None:
if not self.earray[electrode]:
raise ValueError("Electrode '%s' not found in "
"implant." % electrode)
# Perform safety checks, etc.:
self.check_stim(stim)
# Store stimulus:
self._stim = deepcopy(stim)
"have a time component." % t_percept)
# Make sure we don't change the user's Stimulus object:
stim = deepcopy(implant.stim)
# Make sure to operate on the compressed stim:
if not stim.is_compressed:
stim.compress()
if t_percept is None:
t_percept = stim.time
n_time = 1 if t_percept is None else np.array([t_percept]).size
if stim.data.size == 0:
# Stimulus was compressed to zero:
resp = np.zeros((self.grid.x.size, n_time), dtype=np.float32)
else:
# Calculate the Stimulus at requested time points:
if t_percept is not None:
stim = Stimulus(stim[:, t_percept].reshape((-1, n_time)),
electrodes=stim.electrodes, time=t_percept)
resp = self._predict_spatial(implant.earray, stim)
return Percept(resp.reshape(list(self.grid.x.shape) + [-1]),
space=self.grid, time=t_percept)
def stim(self, data):
"""Stimulus setter (called upon ``self.stim = data``)"""
if data is None:
self._stim = None
else:
if isinstance(data, Stimulus):
# Already a stimulus object:
stim = Stimulus(data, extrapolate=True)
elif isinstance(data, dict):
# Electrode names already provided by keys:
stim = Stimulus(data, extrapolate=True)
else:
# Use electrode names as stimulus coordinates:
stim = Stimulus(data, electrodes=list(self.earray.keys()),
extrapolate=True)
# Make sure all electrode names are valid:
for electrode in stim.electrodes:
# Invalid index will return None:
if not self.earray[electrode]:
raise ValueError("Electrode '%s' not found in "
"implant." % electrode)
# When choosing amplitudes and durations accordingly, it is still possible to
# generate a charge-balanced pulse:
asymmetric.charge_balanced
##############################################################################
# Multi-electrode stimuli
# -----------------------
#
# The easiest way to build a multi-electrode stimulus from a number of pulses
# is to pass a dictionary to the :py:class:`~pulse2percept.stimuli.Stimulus`
# object:
from pulse2percept.stimuli import Stimulus
stim = Stimulus({
'A1': MonophasicPulse(-20, 1, stim_dur=75),
'C7': AsymmetricBiphasicPulse(-20, 2, 1, 10, delay_dur=25, stim_dur=100)
})
stim.plot()
##############################################################################
# Note how the different stimuli will be padded as necessary to bring all of
# them to a common stimulus duration.
#
# Alternatively, you can also pass the stimuli as a list, in which case you
# might want to specify the electrode names in a list as well:
stim = Stimulus([MonophasicPulse(-20, 1, stim_dur=100),
AsymmetricBiphasicPulse(-20, 2, 1, 10, delay_dur=25,
stim_dur=100)],
electrodes=['A1', 'C7'])
def inner_predict(amp, fnc_predict, stim, **kwargs):
_stim = Stimulus(amp * stim.data / stim.data.max(),
electrodes=stim.electrodes, time=stim.time)
return fnc_predict(_stim, **kwargs).data.max()
def _predict_spatial(self, earray, stim):
"""Predicts the brightness at spatial locations"""
# This does the expansion of a compact stimulus and a list of
# electrodes to activation values at X,Y grid locations:
assert isinstance(earray, ElectrodeArray)
assert isinstance(stim, Stimulus)
return spatial_fast(stim.data,
np.array([earray[e].x for e in stim.electrodes],
dtype=np.float32),
np.array([earray[e].y for e in stim.electrodes],
dtype=np.float32),
np.array([earray[e].z for e in stim.electrodes],
dtype=np.float32),
np.array([earray[e].r for e in stim.electrodes],
dtype=np.float32),
self.grid.xret.ravel(),
self.grid.yret.ravel(),
self.atten_a,
self.atten_n,
self.thresh_percept)
def stim(self, data):
"""Stimulus setter (called upon ``self.stim = data``)"""
if data is None:
self._stim = None
else:
if isinstance(data, Stimulus):
# Already a stimulus object:
stim = Stimulus(data, extrapolate=True)
elif isinstance(data, dict):
# Electrode names already provided by keys:
stim = Stimulus(data, extrapolate=True)
else:
# Use electrode names as stimulus coordinates:
stim = Stimulus(data, electrodes=list(self.earray.keys()),
extrapolate=True)
# Make sure all electrode names are valid:
for electrode in stim.electrodes:
# Invalid index will return None:
if not self.earray[electrode]:
raise ValueError("Electrode '%s' not found in "
"implant." % electrode)
# Perform safety checks, etc.:
self.check_stim(stim)
percept : :py:class:`~pulse2percept.models.Percept`
A Percept object whose ``data`` container has dimensions Y x X x T.
Will return None if ``stim`` is None.
Notes
-----
* If a list of time points is provided for ``t_percept``, the values
will automatically be sorted.
"""
if not self.is_built:
raise NotBuiltError("Yout must call ``build`` first.")
if stim is None:
# Nothing to see here:
return None
if not isinstance(stim, (Stimulus, Percept)):
raise TypeError(("'stim' must be a Stimulus or Percept object, "
"not %s.") % type(stim))
if stim.time is None:
raise ValueError("Cannot calculate temporal response, because "
"stimulus/percept does not have a time "
"component." % t_percept)
# Make sure we don't change the user's Stimulus/Percept object:
_stim = deepcopy(stim)
if isinstance(stim, Stimulus):
# Make sure to operate on the compressed stim:
if not _stim.is_compressed:
_stim.compress()
_space = [len(stim.electrodes), 1]
elif isinstance(stim, Percept):
_space = [len(stim.ydva), len(stim.xdva)]
_time = stim.time
Search will stop if model brightness is within ``bright_tol`` of
``bright_th``
max_iter : int, optional
Search will stop after ``max_iter`` iterations
t_percept: float or list of floats, optional
The time points at which to output a percept (ms).
If None, ``implant.stim.time`` is used.
Returns
-------
amp_th : float
Threshold current (uA), estimated so that the output of
``model.predict_percept(stim(amp_th))`` is within ``bright_tol`` of
``bright_th``.
"""
if not isinstance(stim, Stimulus):
raise TypeError("'stim' must be a Stimulus, not %s." % type(stim))
def inner_predict(amp, fnc_predict, stim, **kwargs):
_stim = Stimulus(amp * stim.data / stim.data.max(),
electrodes=stim.electrodes, time=stim.time)
return fnc_predict(_stim, **kwargs).data.max()
return bisect(bright_th, inner_predict,
args=[self.predict_percept, stim],
kwargs={'t_percept': t_percept},
x_lo=amp_range[0], x_hi=amp_range[1], x_tol=amp_tol,
y_tol=bright_tol, max_iter=max_iter)
def inner_predict(amp, fnc_predict, implant, **kwargs):
_implant = deepcopy(implant)
scale = amp / implant.stim.data.max()
_implant.stim = Stimulus(scale * implant.stim.data,
electrodes=implant.stim.electrodes,
time=implant.stim.time)
return fnc_predict(_implant, **kwargs).data.max()