예제 #1
0
def test_FadingTemporal():
    model = FadingTemporal()
    # User can set their own params:
    model.dt = 0.1
    npt.assert_equal(model.dt, 0.1)
    model.build(dt=1e-4)
    npt.assert_equal(model.dt, 1e-4)
    # User cannot add more model parameters:
    with pytest.raises(FreezeError):
        model.rho = 100

    # Nothing in, None out:
    npt.assert_equal(model.predict_percept(None), None)

    # Zero in = zero out:
    stim = BiphasicPulse(0, 1)
    percept = model.predict_percept(stim, t_percept=[0, 1, 2])
    npt.assert_equal(isinstance(percept, Percept), True)
    npt.assert_equal(percept.shape, (1, 1, 3))
    npt.assert_almost_equal(percept.data, 0)

    # Can't request the same time more than once (this would break the Cython
    # loop, because `idx_frame` is incremented after a write; also doesn't
    # make much sense):
    with pytest.raises(ValueError):
        stim = Stimulus(np.ones((1, 100)))
        model.predict_percept(stim, t_percept=[0.2, 0.2])

    # Simple decay for single cathodic pulse:
    model = FadingTemporal(tau=1).build()
    stim = MonophasicPulse(-1, 1, stim_dur=10)
    percept = model.predict_percept(stim, np.arange(stim.duration))
    npt.assert_almost_equal(percept.data.ravel()[:3], [0, 0.633, 0.232],
                            decimal=3)
    npt.assert_almost_equal(percept.data.ravel()[-1], 0, decimal=3)

    # But all zeros for anodic pulse:
    stim = MonophasicPulse(1, 1, stim_dur=10)
    percept = model.predict_percept(stim, np.arange(stim.duration))
    npt.assert_almost_equal(percept.data, 0)

    # tau cannot be negative:
    with pytest.raises(ValueError):
        FadingTemporal(tau=-1).build()
예제 #2
0
def test_MonophasicPulse(amp, delay_dur):
    phase_dur = 3.456
    # Basic usage:
    pulse = MonophasicPulse(amp, phase_dur, delay_dur=delay_dur)
    npt.assert_almost_equal(pulse[0, 0], 0)
    npt.assert_almost_equal(pulse[0, delay_dur + phase_dur / 2.0], amp)
    npt.assert_almost_equal(pulse.time[0], 0)
    npt.assert_almost_equal(pulse.time[-1], phase_dur + delay_dur)
    npt.assert_equal(pulse.cathodic, amp <= 0)
    npt.assert_equal(pulse.charge_balanced, False)

    # Custom stim dur:
    pulse = MonophasicPulse(amp, phase_dur, delay_dur=delay_dur, stim_dur=100)
    npt.assert_almost_equal(pulse[0, 0], 0)
    npt.assert_almost_equal(pulse[0, delay_dur + phase_dur / 2.0], amp)
    npt.assert_almost_equal(pulse.time[0], 0)
    npt.assert_almost_equal(pulse.time[-1], 100)

    # Zero amplitude:
    pulse = MonophasicPulse(0, phase_dur, delay_dur=delay_dur, electrode='A1')
    npt.assert_almost_equal(pulse.data, 0)
    npt.assert_almost_equal(pulse.time[0], 0)
    npt.assert_almost_equal(pulse.time[-1], phase_dur + delay_dur)
    npt.assert_equal(pulse.charge_balanced, True)
    npt.assert_equal(pulse.electrodes, 'A1')

    # You can wrap a pulse in a Stimulus to overwrite attributes:
    stim = Stimulus(pulse, electrodes='AA1')
    npt.assert_equal(stim.electrodes, 'AA1')
    # Or concatenate:
    stim = Stimulus([pulse, pulse])
    npt.assert_equal(stim.shape[0], 2)
    npt.assert_almost_equal(stim.data[0, :], stim.data[1, :])
    npt.assert_almost_equal(stim.time, pulse.time)
    npt.assert_equal(stim.electrodes, ['A1', 1])
    # Concatenate and rename:
    stim = Stimulus([pulse, pulse], electrodes=['C1', 'D2'])
    npt.assert_equal(stim.electrodes, ['C1', 'D2'])

    # Invalid calls:
    with pytest.raises(ValueError):
        MonophasicPulse(amp, 0)
    with pytest.raises(ValueError):
        MonophasicPulse(amp, phase_dur, delay_dur=-1)
    with pytest.raises(ValueError):
        MonophasicPulse(amp, phase_dur, delay_dur=delay_dur, stim_dur=1)
    with pytest.raises(ValueError):
        MonophasicPulse(amp,
                        phase_dur,
                        delay_dur=delay_dur,
                        electrode=['A1', 'B2'])
# They are pseudo-monophasic pulse pairs, where the anodic phases were
# presented 20 ms after the end of the second cathodic pulse.
#
# The initial cathodic pulse always has a fixed amplitude of 50% of the single
# pulse threshold:

from pulse2percept.stimuli import MonophasicPulse

# Phase duration:
phase_dur = 0.075

# Single-pulse threshold determines this current:
amp_th = 20

# Cathodic phase of the standard pulse::
cath_standard = MonophasicPulse(-0.5 * amp_th, phase_dur)

###############################################################################
# The delay between the start of the conditioning pulse and the start of the
# test pulse was varied systematically (between 0.15 and 12 ms).
# The amplitude of the second pulse was varied to determine thresholds.

# Delay was varied between 0.15 and 12 ms:
delay_dur = 12

# Vary this current to determine threshold:
amp_test = 45

# Cathodic phase of the test pulse (delivered after a delay):
cath_test = MonophasicPulse(-amp_test, phase_dur, delay_dur=delay_dur)
예제 #4
0
def test_pulse_append(amp, phase_dur):
    # Build a biphasic pulse from two monophasic pulses:
    mono = MonophasicPulse(amp, phase_dur)
    bi = BiphasicPulse(amp, phase_dur)
    npt.assert_equal(mono.append(-mono) == bi, True)
예제 #5
0
def test_AsymmetricBiphasicPulse(amp1, amp2, interphase_dur, delay_dur,
                                 cathodic_first):
    phase_dur1 = 2.1
    phase_dur2 = 4.87
    mid_first_pulse = delay_dur + phase_dur1 / 2.0
    mid_interphase = delay_dur + phase_dur1 + interphase_dur / 2.0
    mid_second_pulse = delay_dur + phase_dur1 + interphase_dur + phase_dur2 / 2
    first_amp = -np.abs(amp1) if cathodic_first else np.abs(amp1)
    second_amp = np.abs(amp2) if cathodic_first else -np.abs(amp2)
    min_dur = delay_dur + phase_dur1 + interphase_dur + phase_dur2

    # Basic usage:
    pulse = AsymmetricBiphasicPulse(amp1,
                                    amp2,
                                    phase_dur1,
                                    phase_dur2,
                                    interphase_dur=interphase_dur,
                                    delay_dur=delay_dur,
                                    cathodic_first=cathodic_first)
    npt.assert_almost_equal(pulse[0, 0], 0)
    npt.assert_almost_equal(pulse[0, mid_first_pulse], first_amp)
    npt.assert_almost_equal(pulse[0, mid_interphase], 0)
    npt.assert_almost_equal(pulse[0, mid_second_pulse], second_amp)
    npt.assert_almost_equal(pulse.time[0], 0)
    npt.assert_almost_equal(pulse.time[-1], min_dur, decimal=3)
    npt.assert_equal(pulse.cathodic_first, cathodic_first)
    npt.assert_equal(pulse.is_charge_balanced,
                     np.isclose(np.trapz(pulse.data, pulse.time)[0], 0))

    # Custom stim dur:
    pulse = AsymmetricBiphasicPulse(amp1,
                                    amp2,
                                    phase_dur1,
                                    phase_dur2,
                                    interphase_dur=interphase_dur,
                                    delay_dur=delay_dur,
                                    cathodic_first=cathodic_first,
                                    stim_dur=100,
                                    electrode='A1')
    npt.assert_almost_equal(pulse[0, 0], 0)
    npt.assert_almost_equal(pulse[0, mid_first_pulse], first_amp)
    npt.assert_almost_equal(pulse[0, mid_interphase], 0)
    npt.assert_almost_equal(pulse[0, mid_second_pulse], second_amp)
    npt.assert_almost_equal(pulse.time[0], 0)
    npt.assert_almost_equal(pulse.time[-1], 100)
    npt.assert_equal(pulse.electrodes, 'A1')

    # Exact stim dur:
    stim_dur = delay_dur + phase_dur1 + interphase_dur + phase_dur2
    pulse = AsymmetricBiphasicPulse(amp1,
                                    amp2,
                                    phase_dur1,
                                    phase_dur2,
                                    interphase_dur=interphase_dur,
                                    delay_dur=delay_dur,
                                    cathodic_first=cathodic_first,
                                    stim_dur=stim_dur,
                                    electrode='A1')
    npt.assert_almost_equal(pulse.time[0], 0)
    npt.assert_almost_equal(pulse.time[-1], stim_dur, decimal=6)

    # Zero amplitude:
    pulse = AsymmetricBiphasicPulse(0,
                                    0,
                                    phase_dur1,
                                    phase_dur2,
                                    interphase_dur=interphase_dur,
                                    delay_dur=delay_dur,
                                    cathodic_first=cathodic_first)
    npt.assert_almost_equal(pulse.data, 0)
    npt.assert_almost_equal(pulse.time[0], 0)
    npt.assert_almost_equal(pulse.time[-1], min_dur, decimal=3)
    npt.assert_equal(pulse.is_charge_balanced,
                     np.isclose(np.trapz(pulse.data, pulse.time)[0], 0))

    # If both phases have the same values, it's basically a symmetric biphasic
    # pulse:
    abp = AsymmetricBiphasicPulse(amp1,
                                  amp1,
                                  phase_dur1,
                                  phase_dur1,
                                  interphase_dur=interphase_dur,
                                  delay_dur=delay_dur,
                                  cathodic_first=cathodic_first)
    bp = BiphasicPulse(amp1,
                       phase_dur1,
                       interphase_dur=interphase_dur,
                       delay_dur=delay_dur,
                       cathodic_first=cathodic_first)
    bp_min_dur = phase_dur1 * 2 + interphase_dur + delay_dur
    npt.assert_almost_equal(abp[:, np.linspace(0, bp_min_dur, num=5)],
                            bp[:, np.linspace(0, bp_min_dur, num=5)])
    npt.assert_equal(abp.cathodic_first, bp.cathodic_first)

    # If one phase is zero, it's basically a monophasic pulse:
    abp = AsymmetricBiphasicPulse(amp1,
                                  0,
                                  phase_dur1,
                                  phase_dur2,
                                  interphase_dur=interphase_dur,
                                  delay_dur=delay_dur,
                                  cathodic_first=cathodic_first)
    mono = MonophasicPulse(first_amp,
                           phase_dur1,
                           delay_dur=delay_dur,
                           stim_dur=min_dur)
    npt.assert_almost_equal(abp[:, np.linspace(0, min_dur, num=5)],
                            mono[:, np.linspace(0, min_dur, num=5)])
    npt.assert_equal(abp.cathodic_first, mono.cathodic)

    # You can wrap a pulse in a Stimulus to overwrite attributes:
    stim = Stimulus(pulse, electrodes='AA1')
    npt.assert_equal(stim.electrodes, 'AA1')
    # Or concatenate:
    stim = Stimulus([pulse, pulse])
    npt.assert_equal(stim.shape[0], 2)
    npt.assert_almost_equal(stim.data[0, :], stim.data[1, :])
    npt.assert_almost_equal(stim.time, pulse.time, decimal=2)
    npt.assert_equal(stim.electrodes, [0, 1])
    # Concatenate and rename:
    stim = Stimulus([pulse, pulse], electrodes=['C1', 'D2'])
    npt.assert_equal(stim.electrodes, ['C1', 'D2'])

    # Invalid calls:
    with pytest.raises(ValueError):
        AsymmetricBiphasicPulse(amp1, amp2, 0, phase_dur2)
    with pytest.raises(ValueError):
        AsymmetricBiphasicPulse(amp1, amp2, phase_dur1, 0)
    with pytest.raises(ValueError):
        AsymmetricBiphasicPulse(amp1,
                                amp2,
                                phase_dur1,
                                phase_dur2,
                                interphase_dur=-1)
    with pytest.raises(ValueError):
        AsymmetricBiphasicPulse(amp1,
                                amp2,
                                phase_dur1,
                                phase_dur2,
                                interphase_dur=interphase_dur,
                                delay_dur=-1)
    with pytest.raises(ValueError):
        AsymmetricBiphasicPulse(amp1,
                                amp2,
                                phase_dur1,
                                phase_dur2,
                                interphase_dur=interphase_dur,
                                delay_dur=delay_dur,
                                stim_dur=1)
    with pytest.raises(ValueError):
        AsymmetricBiphasicPulse(amp1,
                                amp2,
                                phase_dur1,
                                phase_dur2,
                                interphase_dur=interphase_dur,
                                delay_dur=delay_dur,
                                electrode=['A1', 'B2'])
예제 #6
0
# They are pseudo-monophasic pulse pairs, where the anodic phases were
# presented 20 ms after the end of the second cathodic pulse.
#
# The initial cathodic pulse always has a fixed amplitude of 50% of the single
# pulse threshold:

from pulse2percept.stimuli import MonophasicPulse

# Phase duration:
phase_dur = 0.075

# Single-pulse threshold determines this current:
amp_th = 20

# Cathodic phase of the standard pulse::
cath_stand = MonophasicPulse(-0.5 * amp_th, phase_dur)

###############################################################################
# The delay between the start of the conditioning pulse and the start of the
# test pulse was varied systematically (between 0.15 and 12 ms).
# The amplitude of the second pulse was varied to determine thresholds.

# Delay was varied between 0.15 and 12 ms:
delay_dur = 12

# Vary this current to determine threshold:
amp_test = 45

# Cathodic phase of the test pulse (delivered after a delay):
cath_test = MonophasicPulse(-amp_test, phase_dur, delay_dur=delay_dur)
예제 #7
0
pulse_type = 'anodic'  # anodic: positive amplitude, cathodic: negative
pulse_dur = 4.6 / 1000  # pulse duration in seconds
delay_dur = 10.0 / 1000  # pulse delivered after delay in seconds
stim_dur = 0.5  # stimulus duration in seconds (pulse padded with zeros)
time_step = 0.1 / 1000  # temporal sampling step in seconds

##############################################################################
# The sampling step ``time_step`` defines at which temporal resolution the
# stimulus is resolved. In the above example, the time step is 0.1 ms.
#
# By calling Stimulus with a ``MonophasicPulse`` source, we can generate a
# single pulse:
monophasic_stim = Stimulus(
    MonophasicPulse(ptype=pulse_type,
                    pdur=pulse_dur,
                    delay_dur=delay_dur,
                    stim_dur=stim_dur,
                    tsample=time_step))
print(monophasic_stim)

##############################################################################
# Here, ``data`` is a 2D NumPy array where rows are electrodes and columns are
# the points in time. Since we did not specify any electrode names in
# ``MonophasicPulse``, the number of electrodes is inferred from the input
# source type. There is only one row in the above example, denoting a single
# electrode.
#
# By default, the :py:class:`~pulse2percept.stimuli.MonophasicPulse` object
# automatically assumes a current amplitude of 1 uA.

##############################################################################
예제 #8
0
------------------

A :py:class:`~pulse2percept.stimuli.MonophasicPulse` has a single phase and can
be either anodic (by definition: has a positive current amplitude) or cathodic
(negative current amplitude).

Monophasic pulses require an amplitude (in uA) and a phase duration (in ms).
You can also specify the total stimulus duration: zeros will be inserted after
the pulse up to the desired duration:

"""
# sphinx_gallery_thumbnail_number = 6

from pulse2percept.stimuli import MonophasicPulse

mono = MonophasicPulse(-20, 1, stim_dur=50)
mono.plot()

##############################################################################
# .. note ::
#
#     The sign of ``amp`` will determine whether the pulse is cathodic
#     (negative current) or anodic (positive current).
#
# A (symmetric) biphasic pulse
# ----------------------------
#
# A :py:class:`~pulse2percept.stimuli.BiphasicPulse` consists of a cathodic and
# an anodic phase, optionally separated by an interphase gap.
# Both cathodic and anodic phases will have the same duration ("symmetric").
#