A lot of your code is good, but you're having to wrestle with many different, unfamiliar pieces. Also, not all documentation is as clear or complete as it should be. And, unfortunately debugging is complicated by the fact that, while matplotlib + NEURON is a powerful combination, it doesn't enable interactive simulations. So here's a working example with some discussion of what I left out and what I included.
First the code that defines the model cell.
Code: Select all
from neuron import h, gui
# not using numpy or matplotlib
##### model cell
dend = h.Section(name='dend')
# not specifying dend.L or diam; they will have their default values 100 and 500 um
dend.insert('hh')
Set the stage for extracellular stimulation
Code: Select all
##### instrumentation
## stimulus first
dend.insert('extracellular') # this mechanism's default params are OK
dend.insert('xtra')
dend.nseg = 5 # so we can see variation over distance
for seg in dend:
seg.xtra._ref_im = seg._ref_i_membrane
seg.xtra._ref_ex = seg._ref_e_extracellular
## Vector play with interpolation
t = [0, 1, 1, 2, 2, 3]
mag = [0, 0, 1, 1, 0, 0]
tsvec = h.Vector().from_python(t)
isvec = h.Vector().from_python(mag)
isvec.play(h._ref_is_xtra, tsvec, 1)
Next the graphs, starting with membrane potential. Note how updating a graph at each advance is enabled by appending the graph to graphList[0].
Code: Select all
## dend(0.5).v vs. t
gv = h.Graph()
gv.addvar('dend(0.5).v', dend(0.5)._ref_v, 3, 2) # blue (3), 2 pixels wide
h.graphList[0].append(gv) # to update vg at every fadvance()
gv.size(0, h.tstop, -80, 40)
## v along dend ("space plot")
vrvp = h.RangeVarPlot('v', dend(0), dend(1))
gvrvp = h.Graph()
gvrvp.addobject(vrvp, 3, 2) # 3, 2 == blue, 2 pixels wide
# adjust x and y axes appropriately
gvrvp.size(0, 100, -80, 40)
h.graphList[0].append(gvrvp) # update graph at every fadvance()
Also plot e_extracellular and vext[0] (to confirm that these variables are being driven).
Code: Select all
## dend.vext[0](0.5) and dend.e_extracellular(0.5) vs. t
gvext = h.Graph()
gvext.addvar('dend(0.5).e_extracellular', dend(0.5)._ref_e_extracellular, 2, 4) # 2, 4 == red, 4 pixels wide
gvext.addvar('dend(0.5).vext[0]', dend(0.5)._ref_vext[0], 3, 2) # 3, 2 == blue, 2 pixels wide
h.graphList[0].append(gvext) # to update graph at every fadvance()
gvext.size(0, h.tstop, 0, 100)
## e_extracellular and vext[0] along dendrite
eextrvp = h.RangeVarPlot('e_extracellular', dend(0), dend(1))
vextrvp = h.RangeVarPlot('dend.vext[0]', dend(0), dend(1))
gextrvp = h.Graph()
gextrvp.addobject(eextrvp, 2, 3) # red, 3 pixels wide
gextrvp.addobject(vextrvp, 3, 2) # blue, 2 pixels wide
# adjust x and y axes appropriately
gextrvp.size(0, 100, 0, 100)
h.graphList[0].append(gextrvp) # to update graph at every fadvance()
Finally, simulation flow control: a RunControl panel for launching and stepping through simulations
Code: Select all
##### simulation flow control
h.nrncontrolmenu()
Three different ways you can run a simulation.
1. Click on the RunControl panel's Init & Run button. Easy, but too fast to see the graphs evolve.
2. Initialize, the manually step through a simulation. Click on RunControl/Init. Then click on Single Step to advance by dt, or on "Continue for" to advance for the number of ms specified in the adjacent numerical field.
3. Bring up a Movie Run tool by clicking on NEURON Main Menu / Tools / Movie Run. Then click on the Movie Run tool's own Init & Run button.
Now some things for you to try and think about.
1. You're not getting a spike. In fact, membrane potential isn't changing even though e_extracellular is rising to 1e6 mV (1000 V!). The problem is that the surface of the model cell remains isopotential throughout the simulation. Result: no matter how strong the stimulus is, it can't induce transmembrane current flow. Look up Gauss's law (which one? there are so many . . .).
The cell surface isopotential because the transfer resistance between the stimulus source and the surface of the cell is uniform over the surface of the cell. A quick way to fix this is to enter the following two lines at Python's >>> prompt :
Code: Select all
for seg in dend:
seg.xtra.rx = seg.x
The result emulates an extracellular field oriented parallel to dend's long axis with a steep linear gradient. Now run a simulation (with Movie Run's Init & Run) and see what happens.
Nothing that looks like a spike--because the potential gradient is way too intense: 1000 volts per 100 um length. That's a few orders of magnitude larger than what it takes to ionize dry air.
What to do? Try this one liner at the >>> prompt:
for seg in dend: seg.xtra.rx /= 10
(you'll have to hit Return twice to make that execute). Then run another simulation. In fact, follow this algorithm yourself:
Code: Select all
REPEAT
for seg in dend: seg.xtra.rx /= 10
(hit Return key twice)
run a simulation
UNTIL the stimulus is small enough to elicit a reasonable looking spike.
Now what is the value of dend(0.5).xtra.rx ?