1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
# i_membrane + electrode current sums to 0 when electrode parameters are time dependent.
# This test revealed a fast_imem bug that needed fixing #2733
from neuron import h, gui
from neuron import coreneuron
import math
pc = h.ParallelContext()
def chkvec(v, str, tol=1e-10):
x = v.c().abs().max()
# print(str, " ", x)
assert math.isclose(x, 0.0, abs_tol=tol)
def seclamp(s):
stim = h.SEClamp(s(0.5))
stim.amp1 = -65
stim.dur1 = 1
stim.amp2 = -10
stim.dur2 = 100
stim.rs = 10
return stim
def iclamp(s):
stim = h.IClamp(s(0.5))
stim.delay = 1.0
stim.dur = 0.1
stim.amp = 0.3
return stim
def triangle_stim(stimref, step, min, max):
tstim = h.Vector(20).indgen(step)
istim = tstim.c().fill(min)
for i in range(1, len(istim), 2):
istim[i] = max
istim.play(stimref, tstim, 1)
return tstim, istim
def tst(xtrcell, secondorder, cvactive, corenrn, seclmp):
# print(xtrcell, secondorder, cvactive, corenrn, seclmp)
cv = h.cvode
cv.use_fast_imem(1)
h.secondorder = secondorder
cv.active(cvactive)
s = h.Section("s")
s.L = 10
s.diam = 10
s.nseg = 1
s.insert("hh")
imvec = None
if xtrcell:
s.insert("extracellular")
imvec = h.Vector().record(s(0.5)._ref_i_membrane)
vstim = None
rstim = None
if seclmp:
stim = seclamp(s)
stim.dur1 = 100
vstim = triangle_stim(stim._ref_amp1, 0.5, -65, -10)
rstim = triangle_stim(stim._ref_rs, 1, 1000, 100)
else:
stim = iclamp(s)
stim.dur = 100
vstim = triangle_stim(stim._ref_amp, 0.5, 0, 0.001)
tvec = h.Vector().record(h._ref_t)
vvec = h.Vector().record(s(0.5)._ref_v)
istimvec = h.Vector().record(stim._ref_i)
imemvec = h.Vector().record(s(0.5)._ref_i_membrane_)
if hasattr(stim, "vc"):
vstimvec = h.Vector().record(stim._ref_vc)
rsstimvec = h.Vector().record(stim._ref_rs)
glist = []
def fstim():
if h.cvode.active():
return istimvec.c()
# current balance and imembrane calculation takes place at t + .5*dt
# SEClamp conductance is evaluated (Vector.play) at t + .5*dt
# But recording is at time t + dt.
# So use rsstimvec to evaluate clamp resistance at midpoint
# of each step. That is the resistance for the entire step.
rs = rsstimvec.c().add(rsstimvec.c().rotate(1)).mul(0.5)
rs[0] = rsstimvec[0]
vc = vstimvec.c()
v = vvec.c()
if h.secondorder:
v = vvec.c().add(vvec.c().rotate(1)).mul(0.5)
v[0] = vvec[0]
s = vc.sub(v).div(rs)
return s
def plt(vec, vecstr):
return # comment out if want to see plots
g = h.Graph()
glist.append(g)
vec.label(vecstr)
vec.line(g, tvec)
g.exec_menu("View = plot")
g.exec_menu("10% Zoom out")
return g
# run
# h.steps_per_ms = 400
h.tstop = 10
pc.set_maxstep(10)
h.finitialize(-65)
if corenrn:
coreneuron.enable = True
coreneuron.verbose = 0
pc.psolve(h.tstop)
coreneuron.enable = False
coreneuron.verbose = 2
else:
h.run()
plt(vvec, "v")
plt(imemvec, "i_membrane_")
plt(istimvec, "stim.i")
tmp = (imemvec.c().sub(istimvec), "i_membrane_ - stim_i")
plt(*tmp)
if cv.active() or not seclmp:
chkvec(*tmp)
if xtrcell:
pass
plt(imvec, "i_membrane")
plt(imvec.c().mul(s(0.5).area() / 100).sub(istimvec), "i_membrane - stim_i")
tmp = (
imvec.c().mul(s(0.5).area() / 100).sub(imemvec),
"i_membrane - i_membrane_",
)
plt(*tmp)
chkvec(*tmp)
if hasattr(stim, "vc"):
pass
g = plt(rsstimvec, "stim.rs")
if g:
rstim[1].line(g, rstim[0], 2, 1)
plt(vstimvec, "stim.vc")
tmp = (imemvec.c().sub(fstim()), "i_membrane_ - fstim()")
plt(*tmp)
chkvec(*tmp)
cv.use_fast_imem(0)
h.secondorder = 0
return glist
def test_imem():
# tst(xtrcell, secondorder, cvactive, corenrn, seclmp)
cnlist = [0]
if "NRN_ENABLE_CORENEURON" in h.nrnversion(6):
# coreneuron submodule doesn't have update from #2733
# and this test should be skipped in 8.2
pass
# cnlist.append(1)
for seclmp in [0, 1]:
tst(1, 0, 0, 0, seclmp)
tst(0, 0, 1, 0, seclmp)
for secondorder in [0, 2]:
for corenrn in cnlist:
tst(0, secondorder, 0, corenrn, seclmp)
if __name__ == "__main__":
test_imem()
|