Hello,
I am running large sets of simulations and using spikebin to create trains of spiketimes for export to Matlab. With a set tstop, each simulation produces a highly variable number of spikes, depending on my injected current stimulus. In order to save time, I would like to stop each run after the number of spikes has reached some preset value. Is there some way to do this that will avoid calling spikebin at every timestep? Finding the spikes while running the simulation seems to really bog everything down. Thanks in advance.
continue simulation until numSpikes = n
-
- Site Admin
- Posts: 6300
- Joined: Wed May 18, 2005 4:50 pm
- Location: Yale University School of Medicine
- Contact:
Using the event delivery system to terminate a simulation
It should be much more efficient to do what you want with NEURON's event delivery
system. In its simplest form, the NetCon class's record() method can capture spike
times to a Vector for your later use, e.g.
objref nc, nil
nc = new NetCon(source, nil)
objref stv
stv = new Vector()
nc.record(stv)
In the above, source is italicized because you'll need to replace it with the appropriate
syntax depending on whether the upstream cell is a biophysical or artificial spiking cell.
All this is documented in the Programmers' Reference.
However, NetCon record() can also call a proc, and this can be used to keep track
of how many spikes have occurred. In the above example, replace nc.record(stv)
by the following:
But this change breaks something--specifically, since stv is not the argument to
nc.record(), the standard run system will not automatically clear it for us during
each initialization. So we have to take care of this ourselves, and this is most
conveniently done with an FInitializeHandler.
This specific example will halt execution after the third source event. But a
source event is not the same as a received event (if delay is nonzero), and even
if it were, this doesn't allow time for the received event to affect the synaptic target.
So a better formulation would take advantage of the CVode class's event() method,
which can cause an action to occur at some time >= present time.
This code allows 8 ms for the source event to be delivered and affect its target.
An aside: you don't have to create an instance of the CVode class, because current
versions of NEURON create one automatically when you use the standard run system
(e.g. by load_file("nrngui.hoc") etc.)--even if you are using fixed dt!
One word of caution: if the source's interspike interval is too short (shorter than
WAIT - delay), additional source events may occur and be delivered to the target.
This could be a particular problem if the source has irregular ISIs and a short
refractory interval.
If we want to automatically see the spike times after each run, we can use the
ability of CVode's event() to call a func or proc--
I see that NetCon record()'s ability to call a proc or func is not spelled out in the
documentation. Will add that to our "to do" list.
system. In its simplest form, the NetCon class's record() method can capture spike
times to a Vector for your later use, e.g.
objref nc, nil
nc = new NetCon(source, nil)
objref stv
stv = new Vector()
nc.record(stv)
In the above, source is italicized because you'll need to replace it with the appropriate
syntax depending on whether the upstream cell is a biophysical or artificial spiking cell.
All this is documented in the Programmers' Reference.
However, NetCon record() can also call a proc, and this can be used to keep track
of how many spikes have occurred. In the above example, replace nc.record(stv)
by the following:
Code: Select all
MAXNUM = 3
proc counter() {
stv.append(t) // record time of source event
if (stv.size()==MAXNUM) stoprun = 1
}
nc.record("counter()")
nc.record(), the standard run system will not automatically clear it for us during
each initialization. So we have to take care of this ourselves, and this is most
conveniently done with an FInitializeHandler.
Code: Select all
proc reset_stv() {
stv = new Vector()
}
objref fih
fih = new FInitializeHandler("reset_stv()") // clear stv before start of run
source event is not the same as a received event (if delay is nonzero), and even
if it were, this doesn't allow time for the received event to affect the synaptic target.
So a better formulation would take advantage of the CVode class's event() method,
which can cause an action to occur at some time >= present time.
Code: Select all
WAIT = 8
proc counter() {
stv.append(t) // record time of source event
if (stv.size()==MAXNUM) cvode.event(t+WAIT, "stoprun = 1")
}
An aside: you don't have to create an instance of the CVode class, because current
versions of NEURON create one automatically when you use the standard run system
(e.g. by load_file("nrngui.hoc") etc.)--even if you are using fixed dt!
One word of caution: if the source's interspike interval is too short (shorter than
WAIT - delay), additional source events may occur and be delivered to the target.
This could be a particular problem if the source has irregular ISIs and a short
refractory interval.
If we want to automatically see the spike times after each run, we can use the
ability of CVode's event() to call a func or proc--
Code: Select all
proc wrapup() {
print "spike times:"
stv.printf
stoprun = 1
}
proc counter() {
stv.append(t) // record time of source event
if (stv.size()==MAXNUM) cvode.event(t+WAIT, "wrapup()")
}
I see that NetCon record()'s ability to call a proc or func is not spelled out in the
documentation. Will add that to our "to do" list.