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) ############################################################################### # The anodic phase were always presented 20 ms after the second cathodic phase: anod_standard = MonophasicPulse(0.5 * amp_th, phase_dur, delay_dur=20) anod_test = MonophasicPulse(amp_test, phase_dur, delay_dur=delay_dur) ############################################################################### # The last step is to concatenate all the pulses into a single stimulus: from pulse2percept.stimuli import Stimulus data = [] time = [] time_tracker = 0 for pulse in (cath_standard, cath_test, anod_standard, anod_test): data.append(pulse.data) time.append(pulse.time + time_tracker) time_tracker += pulse.time[-1] latent_add = Stimulus(np.concatenate(data, axis=1), time=np.concatenate(time)) latent_add.plot()
data = levels[np.argmin(np.abs(x[:, np.newaxis] - levels), axis=1)] plt.plot(t, data, label='discretized') plt.plot(t, x, label='original') plt.xlabel('Time (ms)') plt.ylabel('Amplitude') plt.legend() ############################################################################## # We can turn this signal into a :py:class:`~pulse2percept.stimuli.Stimulus` # object as follows: from pulse2percept.stimuli import Stimulus stim = Stimulus(10 * data.reshape((1, -1)), time=t) stim.plot() ############################################################################## # Alternatively, we can automate this process by creating a new class # ``SinusoidalPulse`` that inherits from ``Stimulus``: class SinusoidalPulse(Stimulus): def __init__(self, amp, freq, phase, stim_dur, n_levels=5, dt=0.001): """Sinusoidal pulse Parameters ---------- amp : float Maximum stimulus amplitude (uA) freq : float
pt.plot() ############################################################################### # Generic pulse trains # -------------------- # # Finally, you can concatenate any :py:class:`~pulse2percept.stimuli.Stimulus` # object into a pulse train. # # For example, let's define a single ramp stimulus: import numpy as np from pulse2percept.stimuli import Stimulus, PulseTrain # Single ramp: dt = 1e-3 ramp = Stimulus([[0, 0, 1, 1, 2, 2, 0, 0]], time=[0, 1, 1 + dt, 2, 2 + dt, 3, 3 + dt, 5 - dt]) ramp.plot() # Ramp train: PulseTrain(20, ramp, stim_dur=200).plot() # Biphasic ramp: biphasic_ramp = Stimulus(np.concatenate((ramp.data, -ramp.data), axis=1), time=np.concatenate((ramp.time, ramp.time + 5))) biphasic_ramp.plot() # Biphasic ramp train: PulseTrain(20, biphasic_ramp, stim_dur=200).plot()
def test_Stimulus_plot(): # Stimulus with one electrode stim = Stimulus([[0, -10, 10, -10, 10, -10, 0]], time=[0, 0.1, 0.3, 0.5, 0.7, 0.9, 1.0]) for time in [None, Ellipsis, slice(None)]: # Different ways to plot all data points: fig, ax = plt.subplots() stim.plot(time=time, ax=ax) npt.assert_equal(isinstance(ax, Subplot), True) npt.assert_almost_equal( ax.get_yticks(), [stim.data.min(), 0, stim.data.max()]) npt.assert_equal(len(ax.lines), 1) npt.assert_almost_equal(ax.lines[0].get_data()[1].min(), stim.data.min()) npt.assert_almost_equal(ax.lines[0].get_data()[1].max(), stim.data.max()) plt.close(fig) # Plot a range of time values (times are sliced, but end points are # interpolated): fig, ax = plt.subplots() ax = stim.plot(time=(0.2, 0.6), ax=ax) npt.assert_equal(isinstance(ax, Subplot), True) npt.assert_equal(len(ax.lines), 1) t_vals = ax.lines[0].get_data()[0] npt.assert_almost_equal(t_vals[0], 0.2) npt.assert_almost_equal(t_vals[-1], 0.6) plt.close(fig) # Plot exact time points: t_vals = [0.2, 0.3, 0.4] fig, ax = plt.subplots() stim.plot(time=t_vals, ax=ax) npt.assert_equal(isinstance(ax, Subplot), True) npt.assert_equal(len(ax.lines), 1) npt.assert_almost_equal(ax.lines[0].get_data()[0], t_vals) npt.assert_almost_equal(ax.lines[0].get_data()[1], np.squeeze(stim[:, t_vals])) # Plot multiple electrodes with string names: for n_electrodes in [2, 3, 4]: stim = Stimulus(np.random.rand(n_electrodes, 20), electrodes=[f'E{i}' for i in range(n_electrodes)]) fig, axes = plt.subplots(ncols=n_electrodes) stim.plot(ax=axes) npt.assert_equal(isinstance(axes, (list, np.ndarray)), True) for ax, electrode in zip(axes, stim.electrodes): npt.assert_equal(isinstance(ax, Subplot), True) npt.assert_equal(len(ax.lines), 1) npt.assert_equal(ax.get_ylabel(), electrode) npt.assert_almost_equal(ax.lines[0].get_data()[0], stim.time) npt.assert_almost_equal(ax.lines[0].get_data()[1], stim[electrode, :]) plt.close(fig) # Invalid calls: with pytest.raises(TypeError): stim.plot(electrodes=1.2) with pytest.raises(TypeError): stim.plot(time=0) with pytest.raises(TypeError): stim.plot(ax='as') with pytest.raises(TypeError): stim.plot(time='0 0.1') with pytest.raises(NotImplementedError): Stimulus(np.ones(10)).plot() with pytest.raises(ValueError): stim = Stimulus(np.ones((3, 10))) _, axes = plt.subplots(nrows=4) stim.plot(ax=axes) with pytest.raises(TypeError): stim = Stimulus(np.ones((3, 10))) _, axes = plt.subplots(nrows=3) axes[1] = 0 stim.plot(ax=axes)