Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
use_jit=use_jit,
method='sparse')
# Cathodic and anodic parts are treated separately: They have the
# same charge accumulation, but anodic currents contribute less to
# the response
fr_gcl_cath = np.maximum(0, -fr_gcl)
fr_gcl_anod = self.aweight * np.maximum(0, fr_gcl)
resp_gcl = np.maximum(0, fr_gcl_cath + fr_gcl_anod - ca[1, :])
else:
resp_gcl = np.zeros_like(ecm[1])
resp = resp_gcl + self.lweight * resp_inl
resp = self.stationary_nonlinearity(resp)
resp = self.slow_response(resp)
return utils.TimeSeries(self.tsample, resp)
Parameters
----------
resp : TimeSeries
The brightness movie as a TimeSeries object.
"""
# Find brightest element
idx_px = resp.data.argmax()
# Find frame that contains brightest pixel using `unravel`, which maps
# the flat index `idx_px` onto the high-dimensional indices (x,y,z).
# What we want is index `z` (i.e., the frame index), given by the last
# element in the return argument.
idx_frame = np.unravel_index(idx_px, resp.shape)[-1]
return utils.TimeSeries(resp.tsample, resp.data[..., idx_frame])
def __getitem__(self, y):
return TimeSeries(self.tsample, self.data[y])
"""
# Parse input stimulus
if isinstance(stim, utils.TimeSeries):
# `stim` is a single object: This is only allowed if the implant
# has only one electrode
if implant.num_electrodes > 1:
e_s = "More than 1 electrode given, use a list of pulse trains"
raise ValueError(e_s)
pt = [stim]
elif isinstance(stim, dict):
# `stim` is a dictionary: Look up electrode names and assign pulse
# trains, fill the rest with zeros
# Get right size from first dict element, then generate all zeros
idx0 = list(stim.keys())[0]
pt_zero = utils.TimeSeries(stim[idx0].tsample,
np.zeros_like(stim[idx0].data))
pt = [pt_zero] * implant.num_electrodes
# Iterate over dictionary and assign non-zero pulse trains to
# corresponding electrodes
for key, value in stim.items():
el_idx = implant.get_index(key)
if el_idx is not None:
pt[el_idx] = value
else:
e_s = "Could not find electrode with name '%s'" % key
raise ValueError(e_s)
else:
# Else, `stim` must be a list of pulse trains, one for each electrode
if len(stim) != implant.num_electrodes:
e_s = "Number of pulse trains must match number of electrodes"
else:
resp_nfl = np.zeros((ecm[1].data.shape))
# Here we are converting from current - where a cathodic (effective)
# stimulus is negative - to a vague concept of neuronal response,
# where positive implies a neuronal response.
# There is a rectification here because we used to assume that the
# anodic part of the pulse is ineffective (which is wrong).
resp_cathodic = self.lweight * np.maximum(-resp_inl, 0) + \
np.maximum(-resp_nfl, 0)
resp_anodic = self.lweight * np.maximum(resp_inl, 0) + \
np.maximum(resp_nfl, 0)
resp = resp_cathodic + self.aweight * resp_anodic
resp = self.stationary_nonlinearity(resp)
resp = self.slow_response(resp)
return utils.TimeSeries(self.tsample, resp)
freq = m
else:
e_s = "Acceptable values for `coding` are 'amplitude' or"
e_s += "'frequency'."
raise ValueError(e_s)
pt = Psycho2Pulsetrain(tsample, freq=freq, amp=amp, dur=dur,
pulse_dur=pulsedur,
interphase_dur=interphasedur,
pulsetype=pulsetype)
pulses.append(pt)
return pulses
class Movie2Pulsetrain(utils.TimeSeries):
"""
Is used to create pulse-train stimulus based on luminance over time from
a movie
"""
def __init__(self, rflum, tsample, fps=30.0, amplitude_transform='linear',
amp_max=60, freq=20, pulse_dur=.5 / 1000.,
interphase_dur=.5 / 1000.,
pulsetype='cathodicfirst', stimtype='pulsetrain'):
"""
Parameters
----------
rflum : 1D array
Values between 0 and 1
tsample : suggest TemporalModel.tsample
"""
ecs_list.append(ecs[yy, xx])
idx_list.append([yy, xx])
s_info = "tol=%.1f%%, %d/%d px selected" % (tol * 100, len(ecs_list),
np.prod(ecs.shape[:2]))
logging.getLogger(__name__).info(s_info)
sr_list = utils.parfor(self.gcl.model_cascade,
ecs_list, n_jobs=self.n_jobs,
engine=self.engine, scheduler=self.scheduler,
func_args=[pt_data, layers, self.use_jit])
bm = np.zeros(self.ofl.gridx.shape +
(sr_list[0].data.shape[-1], ))
idxer = tuple(np.array(idx_list)[:, i] for i in range(2))
bm[idxer] = [sr.data for sr in sr_list]
percept = utils.TimeSeries(sr_list[0].tsample, bm)
# It is possible to specify an additional sampling rate for the
# percept: If different from the input sampling rate, need to resample.
if t_percept != percept.tsample:
percept = percept.resample(t_percept)
logging.getLogger(__name__).info("Done.")
return percept
# It might not matter too much (timing is slightly different, but the
# data are not accurate enough to warrant using one over the other).
# Thus use what makes the most sense: accumulate on cathodic
ca = self.tsample * np.cumsum(np.maximum(0, -stim))
ca = self.tsample * utils.conv(ca, self.gamma2, mode='full',
method='fft')[:stim.size]
r2 = r1 - self.epsilon * ca
# Then half-rectify and pass through the power-nonlinearity
r3 = np.maximum(0.0, r2) ** self.beta
# Then convolve with slow gamma
r4 = self.tsample * utils.conv(r3, self.gamma3, mode='full',
method='fft')[:stim.size]
return utils.TimeSeries(self.tsample, r4)
every pulse train is a utils.TimeSeries object; i.e., one pulse
train per electrode.
- For a multi-electrode array, specify all electrodes that should
receive non-zero pulse trains by name in a dictionary. The key
of each element is the electrode name, the value is a pulse train.
Example: stim = {'E1': pt, 'stim': pt}, where 'E1' and 'stim' are
electrode names, and `pt` is a utils.TimeSeries object.
implant : e2cm.ElectrodeArray
An ElectrodeArray object that describes the implant.
Returns
-------
A list of pulse trains; one pulse train per electrode.
"""
# Parse input stimulus
if isinstance(stim, utils.TimeSeries):
# `stim` is a single object: This is only allowed if the implant
# has only one electrode
if implant.num_electrodes > 1:
e_s = "More than 1 electrode given, use a list of pulse trains"
raise ValueError(e_s)
pt = [stim]
elif isinstance(stim, dict):
# `stim` is a dictionary: Look up electrode names and assign pulse
# trains, fill the rest with zeros
# Get right size from first dict element, then generate all zeros
idx0 = list(stim.keys())[0]
pt_zero = utils.TimeSeries(stim[idx0].tsample,
np.zeros_like(stim[idx0].data))
pt = [pt_zero] * implant.num_electrodes
Pulse type {'cathodicfirst' | 'anodicfirst'}, where
'cathodicfirst' has the negative phase first.
pulseorder : str, optional, default: 'pulsefirst'
Pulse order {'gapfirst' | 'pulsefirst'}, where
'pulsefirst' has the pulse first, followed by the gap.
'gapfirst' has it the other way round.
"""
if tsample <= 0:
raise ValueError("tsample must be a non-negative float.")
# Stimulus size given by `dur`
stim_size = int(np.round(float(dur) / tsample))
# Make sure input is non-trivial, else return all zeros
if np.isclose(freq, 0) or np.isclose(amp, 0):
utils.TimeSeries.__init__(self, tsample, np.zeros(stim_size))
return
# Envelope size (single pulse + gap) given by `freq`
# Note that this can be larger than `stim_size`, but we will trim
# the stimulus to proper length at the very end.
envelope_size = int(np.round(1.0 / float(freq) / tsample))
if envelope_size > stim_size:
debug_s = ("Envelope size (%d) clipped to "
"stimulus size (%d) for freq=%f" % (envelope_size,
stim_size,
freq))
logging.getLogger(__name__).debug(debug_s)
envelope_size = stim_size
# Delay given by `delay`
delay_size = int(np.round(float(delay) / tsample))