Driving a synapse with recorded or precomputed spike events

A collection of noteworthy items selected by our moderators from discussions about making and using models with NEURON.

Moderators: wwlytton, tom_morse

Post Reply
ted
Site Admin
Posts: 5625
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Driving a synapse with recorded or precomputed spike events

Post by ted » Wed Nov 10, 2010 11:12 am

There are several ways to drive synaptic mechanisms with previously recorded or computed spike events. Which is most appropriate for a particular instance depends on the nature of the modeling problem.

For cases in which there are just a few spikes to deliver in this way, it may be easiest to use an FInitializeHandler to load all of the spike times into the event queue in the course of initializing a simulation. This approach is discussed in NEURON's FAQ list
http://www.neuron.yale.edu/neuron/faq#playevents

If there are more than a few dozen precomputed spikes, it is best to fill a Vector with the spike times before the simulation run, and use an NMODL-defined artificial spiking cell that generates spike events at the times stored in that Vector. For an example of this strategy, see the files vecevent.hoc, vecevent.ses, and vecevent.mod in NEURON's installation tree under nrn/examples/nrniv/netcon (UNIX/Linux/OS X users: the complete tree is nrn/share/nrn/examples...).

vecevent.mod specifies the properties of an artificial cell class called VecStim. Each instance of the VecStim class has a play() method that can be used to specify the Vector from which that instance will read its "spike times" in the course of a simulation. Every VecStim instance may have its own different Vector.

vecevent.ses is a session file that recreates a model constructed with the Network Builder. This model consists of a single instance of the VecStim class. The VecStim class is a class of artificial spiking cell whose spike times are specified by the elements in a Vector.

vecevent.hoc illustrates the usage of a VecStim object; here's the file with comments added by me:

Code: Select all

load_file("nrngui.hoc")
load_file("vecevent.ses") // creates a VecStim object called vs_VecStim[0]
objref evec
evec = new Vector(100) // will hold times at which the VecStim should generate an event
evec.indgen // evec's elements are now 0, 1 . . . 99
vs_VecStim[0].pp.play(evec) // the VecStim object generates events at t = 0, 1 . . . 99 ms

pfortier
Posts: 47
Joined: Thu Apr 20, 2006 8:02 am
Location: University of Ottawa

Re: Driving a synapse with recorded or precomputed spike events

Post by pfortier » Wed Jan 30, 2019 7:20 pm

I read the information and ran the simulation but I don't see how a vector of spike times can be delivered to a postsynaptic receptor.

Given:

Code: Select all

// vector with presynaptic spike times in ms
objref presynspiketimes
presynspiketimes = new Vector()
presynspiketimes.append(50,100,150)
// postsynaptic neuron
create postsynneuron
access postsynneuron
// add receptor to postsynaptic neuron
objref receptor
postsynneuron receptor = new ExpSyn(0.3)
// play presynspiketimes on receptor
How to do this???
// draw postsynaptic voltage
objref fig 
fig = new Graph(0)
fig.view(0, -80, tstop, 120, 435, 72, 485.76, 200.32)
fig.addexpr("postsynneuron.v(.5)", 1, 1, 0.8, 0.9, 2) 
// setup run 
tstop=200
run()
Could I get some help to "play presynspiketimes on receptor"?
Thanks

ted
Site Admin
Posts: 5625
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Driving a synapse with recorded or precomputed spike events

Post by ted » Thu Jan 31, 2019 1:18 am

An instance of the VecStim class is an event source. It generates events. Use NetCons to convey those events to the target synaptic mechanism(s).

pfortier
Posts: 47
Joined: Thu Apr 20, 2006 8:02 am
Location: University of Ottawa

Re: Driving a synapse with recorded or precomputed spike events

Post by pfortier » Thu Jan 31, 2019 11:10 am

Thanks for pointing me in the right direction but it looks like I need more help.

I inserted the following in the code of my original post but it fails:

Code: Select all

// play presynspiketimes on receptor
objref vs
vs = new VecStim()
objref presynterminal
postsynneuron presynterminal = new NetCon(&vs.play(presynspiketimes), receptor, 0.5, 50, 1.0) 
How does one correct this code to have VecStim provide events to the NetCon?

ted
Site Admin
Posts: 5625
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Driving a synapse with recorded or precomputed spike events

Post by ted » Thu Jan 31, 2019 6:13 pm

"A VecStim is an event source" means that a VecStim is similar to any other artificial spiking cell, e.g. an instance of the NetStim class or of one of the IntFire classes. For any of these, the usage pattern is

1. Create an instance of the target that is to be driven by events. The target could be an instance of an artificial spiking cell class, or it could be an instance of a point process class (e.g. ExpSyn or Exp2Syn) that is attached to a section that belongs to a biophysical model cell. The properties of the target are specified by NMODL code with a NEURON block that declares it is either an ARTIFICIAL_CELL class or a POINT_PROCESS class. The NMODL code will also contain a NET_RECEIVE block that specifies what is supposed to happen when the artificial cell or point process receives an event (typically the event does something to an artificial spiking cell's "activation variable", or it does something to a current generated by the point process).

2. Create an instance of the event source.

3. Create a NetCon that attaches the event source to the target.

Suggest you start by setting up a model in which a NetStim sends events to an IntFire1.
Once you have that working, replace the IntFire1 with an ExpSyn attached to a single compartment soma.
After you have that working, substitute a VecStim for the NetStim.

pfortier
Posts: 47
Joined: Thu Apr 20, 2006 8:02 am
Location: University of Ottawa

Re: Driving a synapse with recorded or precomputed spike events

Post by pfortier » Fri Feb 01, 2019 11:18 am

Suggest you start by setting up a model in which a NetStim sends events to an IntFire1.
Once you have that working, replace the IntFire1 with an ExpSyn attached to a single compartment soma.
Here is a fully functioning example of your suggestion:

Code: Select all

// create postsynaptic neuron
create postsynneuron
forall { 
	nseg = 1 // segments
	diam = 18.8 // diameter
	L = 18.8 // length
	Ra = 123.0 // axial resistance
	insert hh // insert Hodgkin-Huxley currents for resting and action potential
	gnabar_hh=0.25 // maximum sodium conductance
	gl_hh = .001666 // leak conductance
	el_hh = -60.0 // leak equilibrium potential (ie. resting potential)
}
access postsynneuron
// add receptor to postsynaptic neuron
objref receptor
postsynneuron receptor = new ExpSyn(0.3)
//[1] NetStim as source of spikes
objref spikesource
spikesource = new NetStim(0.5) 
spikesource.interval = 10
spikesource.number = 100
spikesource.start = 0
spikesource.noise = 0
//[2] play presynaptic spike times on receptor
objref presynterminal
presynterminal = new NetCon(spikesource,receptor,10,50,1.0)
// setup run 
v_init = -62.6 
tstop=200
// draw postsynaptic voltage
objref fig 
fig = new Graph(0)
fig.view(0, -80, tstop, 120, 435, 72, 485.76, 200.32)
fig.addexpr("postsynneuron.v(.5)", 1, 1, 0.8, 0.9, 2) 
graphList.append(fig)
// run 
run()
After you have that working, substitute a VecStim for the NetStim.
As suggested, I now replaced NetStim in parts [1] and [2] of the code above for VecStim in parts [1'] and [2'] in the code below:

Code: Select all

// create postsynaptic neuron
create postsynneuron
forall { 
	nseg = 1 // segments
	diam = 18.8 // diameter
	L = 18.8 // length
	Ra = 123.0 // axial resistance
	insert hh // insert Hodgkin-Huxley currents for resting and action potential
	gnabar_hh=0.25 // maximum sodium conductance
	gl_hh = .001666 // leak conductance
	el_hh = -60.0 // leak equilibrium potential (ie. resting potential)
}
access postsynneuron
// add receptor to postsynaptic neuron
objref receptor
postsynneuron receptor = new ExpSyn(0.3)
/*
//[1] NetStim as source of spikes
objref spikesource
spikesource = new NetStim(0.5) 
spikesource.interval = 10
spikesource.number = 100
spikesource.start = 0
spikesource.noise = 0
//[2] play presynaptic spike times on receptor
objref presynterminal
presynterminal = new NetCon(spikesource,receptor,10,50,1.0)
*/
//[1'] VecStim as source of spikes
objref presynspiketimes
presynspiketimes = new Vector()
presynspiketimes.append(50,100,150)
objref vs
vs = new VecStim()
//[2'] play presynaptic spike times on receptor
objref presynterminal
presynterminal = new NetCon(vs.play(presynspiketimes),receptor,10,50,1.0)
// setup run 
v_init = -62.6 
tstop=200
// draw postsynaptic voltage
objref fig 
fig = new Graph(0)
fig.view(0, -80, tstop, 120, 435, 72, 485.76, 200.32)
fig.addexpr("postsynneuron.v(.5)", 1, 1, 0.8, 0.9, 2) 
graphList.append(fig)
// run 
run()
Unfortunately, the code no longer works.

pfortier
Posts: 47
Joined: Thu Apr 20, 2006 8:02 am
Location: University of Ottawa

Re: Driving a synapse with recorded or precomputed spike events

Post by pfortier » Fri Feb 01, 2019 1:04 pm

After the helpful instruction to use a NetCon to deliver the VecStim spikes, I could not find a manual for VecStim. Using trial and error, I finally got it right. It turns out that in my previous post where I asked help for the following code snippet:

Code: Select all

objref vs
vs = new VecStim()
objref presynterminal
postsynneuron presynterminal = new NetCon(&vs.play(presynspiketimes), receptor, 0.5, 50, 1.0) 
the solution was simply to add a missing line and make a small correction

Code: Select all

objref vs
vs = new VecStim()
vs.play(presynspiketimes) // missing
objref presynterminal
presynterminal = new NetCon(vs, receptor, 0.5, 50, 1.0) // correction
Instead of giving me the correction, it was suggested that I (1) start by setting up a model in which a NetStim sends events to an IntFire1, (2) once you have that working, replace the IntFire1 with an ExpSyn attached to a single compartment soma and (3) after you have that working, substitute a VecStim for the NetStim. I reached up to part 2 but part 3 didn't work because I did not find instructions on the use of VecStim.

I believe the strategy used to answer my question was to help me learn more about NEURON programming but I don't think the lack of manuals for VecStim support this teaching approach. The steps I learned to use NetStim and IntFire1 did not lead me to the solution. They may be useful to me in the future if I have use for NetStim and IntFire1. Under these conditions, providing the simple correction to my code would have been a worthy method of teaching. In fact, the manuals for NEURON have many examples to teach users. It's a judgement call as to which is the better teaching method. There's probably not one method for all cases. Obviously, I think that in this case where there are no manuals on how to use VecStim, providing the simple correction would of been better.

To help others like me who do poorly without manuals and learn well with examples, I provide below 2 fully working examples of "Driving a synapse with recorded or precomputed spike events". The first uses FInitializeHandler and the second uses VecStim.

1. Driving a synapse with recorded or precomputed spike events using FInitializeHandler

Code: Select all

// postsynaptic neuron
create postsynneuron
forall { 
	nseg = 1 // segments
	diam = 18.8 // diameter
	L = 18.8 // length
	Ra = 123.0 // axial resistance
	insert hh // insert Hodgkin-Huxley currents for resting and action potential
	gnabar_hh=0.25 // maximum sodium conductance
	gl_hh = .001666 // leak conductance
	el_hh = -60.0 // leak equilibrium potential (ie. resting potential)
}
access postsynneuron
// add receptor to postsynaptic neuron
objref receptor
postsynneuron receptor = new ExpSyn(0.3)
// vector with presynaptic spike times in ms
objref presynspiketimes
presynspiketimes = new Vector()
presynspiketimes.append(50,100,150)
// play presynspiketimes on receptor
objref presynterminal,nil
postsynneuron presynterminal = new NetCon(nil, receptor, 0.5, 50, 1.0) 
objref fih
fih = new FInitializeHandler("loadqueue()")
proc loadqueue() { local ii
  for ii=0,presynspiketimes.size()-1 presynterminal.event(presynspiketimes.x[ii]) 
  // author states that only a few dozen spikes can be loaded but I easily loaded 20000 
}
// setup run 
v_init = -62.6 
tstop=200
// draw postsynaptic voltage
objref fig 
fig = new Graph(0)
fig.view(0, -80, tstop, 120, 435, 72, 485.76, 200.32)
fig.addexpr("postsynneuron.v(.5)", 1, 1, 0.8, 0.9, 2) 
graphList.append(fig)
// run
run()
2. Driving a synapse with recorded or precomputed spike events using VecStim

Code: Select all

// create postsynaptic neuron
create postsynneuron
forall { 
	nseg = 1 // segments
	diam = 18.8 // diameter
	L = 18.8 // length
	Ra = 123.0 // axial resistance
	insert hh // insert Hodgkin-Huxley currents for resting and action potential
	gnabar_hh=0.25 // maximum sodium conductance
	gl_hh = .001666 // leak conductance
	el_hh = -60.0 // leak equilibrium potential (ie. resting potential)
}
access postsynneuron
// add receptor to postsynaptic neuron
objref receptor
postsynneuron receptor = new ExpSyn(0.3)
//[1'] VecStim as source of spikes
objref presynspiketimes
presynspiketimes = new Vector()
presynspiketimes.append(50,100,150)
objref vs
vs = new VecStim()
vs.play(presynspiketimes)
//[2'] play presynaptic spike times on receptor
objref presynterminal
presynterminal = new NetCon(vs,receptor,0.5,5,1.0)
// setup run 
v_init = -62.6 
tstop=200
// draw postsynaptic voltage
objref fig 
fig = new Graph(0)
fig.view(0, -80, tstop, 120, 435, 72, 485.76, 200.32)
fig.addexpr("postsynneuron.v(.5)", 1, 1, 0.8, 0.9, 2) 
graphList.append(fig)
// run 
run()
I sincerely hope this helps others looking for methods on "Driving a synapse with recorded or precomputed spike events".

ted
Site Admin
Posts: 5625
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Driving a synapse with recorded or precomputed spike events

Post by ted » Fri Feb 01, 2019 6:40 pm

I could not find a manual for VecStim
VecStim isn't mentioned in the Programmer's Reference because, unlike NetStim, it's not a built-in feature of NEURON--even though its source file vecevent.mod is included in an "examples" subdirectory that is packaged with NEURON's source code (which is all the more reason that vecevent.mod should have a COMMENT block that provides a usage hint).

That said, there are still a couple of places to find working examples of things, regardless of whether they are documented in the Programmer's Reference. One is the Forum, and another is ModelDB. Search the Forum for
VecStim
and you would have quickly found this combination of example and documentation
viewtopic.php?f=12&t=3021&p=12422
and this informative thread about using VecStim in thread-parallel simulations
viewtopic.php?f=16&t=3261

Post Reply