Note
Go to the end to download the full example code.
Comparing precise and grid-based neuron models¶
Run this example as a Jupyter notebook:
See our guide for more information and troubleshooting.
In traditional time-driven simulations, spikes are constrained to the time grid at a user-defined resolution. The precise spiking models overcome this by handling spikes in continuous time [1] and [2].
The precise spiking neuron models in NEST include: iaf_psc_exp_ps
,
iaf_psc_alpha_ps
and iaf_psc_delta_ps
.
More detailed information about the precise spiking models can be
found here:
https://www.nest-simulator.org/simulations-with-precise-spike-times/
This example compares the conventional grid-constrained model and the precise version for an integrate-and-fire neuron model with exponential postsynaptic currents [2].
References¶
First, we import all necessary modules for simulation, analysis, and plotting.
import matplotlib.pyplot as plt
import nest
Second, we assign the simulation parameters to variables.
simtime = 100.0 # ms
stim_current = 700.0 # pA
resolutions = [0.1, 0.5, 1.0] # ms
Now, we simulate the two versions of the neuron models (i.e. discrete-time:
iaf_psc_exp
; precise: iaf_psc_exp_ps
) for each of the defined
resolutions. The neurons use their default parameters and we stimulate them
by injecting a current using a dc_generator
device. The membrane
potential is recorded by a voltmeter
, the spikes are recorded by
a spike_recorder
. The data is stored in a dictionary for later
use.
data = {}
for resolution in resolutions:
data[resolution] = {}
for model in ["iaf_psc_exp", "iaf_psc_exp_ps"]:
nest.ResetKernel()
nest.resolution = resolution
neuron = nest.Create(model)
voltmeter = nest.Create("voltmeter", params={"interval": resolution})
dc = nest.Create("dc_generator", params={"amplitude": stim_current})
sr = nest.Create("spike_recorder")
nest.Connect(voltmeter, neuron)
nest.Connect(dc, neuron)
nest.Connect(neuron, sr)
nest.Simulate(simtime)
vm_status = voltmeter.events
sr_status = sr.events
data[resolution][model] = {
"vm_times": vm_status["times"],
"vm_values": vm_status["V_m"],
"spikes": sr_status["times"],
"V_th": neuron.V_th,
}
After simulation, we plot the results from the simulation. The figure illustrates the membrane potential excursion of the two models due to injected current simulated for 100 ms for a different timestep in each panel. The blue line is the voltage trace of the discrete-time neuron, the red line is that of the precise spiking version of the same model.
Please note that the temporal differences between the traces in the different panels is caused by the different resolutions used.
colors = ["#3465a4", "#cc0000"]
for v, resolution in enumerate(sorted(data)):
plot = plt.subplot(len(data), 1, v + 1)
plot.set_title("Resolution: {0} ms".format(resolution))
for i, model in enumerate(data[resolution]):
times = data[resolution][model]["vm_times"]
potentials = data[resolution][model]["vm_values"]
spikes = data[resolution][model]["spikes"]
spikes_y = [data[resolution][model]["V_th"]] * len(spikes)
plot.plot(times, potentials, "-", c=colors[i], ms=5, lw=2, label=model)
plot.plot(spikes, spikes_y, ".", c=colors[i], ms=5, lw=2)
if v == 2:
plot.legend(loc=4)
else:
plot.set_xticklabels("")
plt.show()