You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
6.4 KiB
206 lines
6.4 KiB
import os |
|
import os.path |
|
from neuron import h |
|
import numpy as np |
|
import scipy |
|
import scipy.integrate |
|
import scipy.stats |
|
|
|
from .protocol import Protocol |
|
|
|
|
|
try: |
|
import pyqtgraph as pg |
|
|
|
HAVE_PG = True |
|
except ImportError: |
|
HAVE_PG = False |
|
from ..util import custom_init |
|
from ..util.stim import make_pulse |
|
|
|
# import matplotlib as MP # must call first... before pylag/pyplot or backends |
|
# MP.use('Qt4Agg') |
|
|
|
# import matplotlib.gridspec as GS |
|
# import mpl_toolkits.axes_grid1.inset_locator as INSETS |
|
# import mpl_toolkits.axes_grid1.anchored_artists as ANCHOR |
|
|
|
# stdFont = 'Arial' |
|
# import matplotlib.pyplot as pylab |
|
# pylab.rcParams['interactive'] = False |
|
# pylab.rcParams['mathtext.default'] = 'sf' |
|
## next setting allows pdf font to be readable in Adobe Illustrator |
|
# pylab.rcParams['pdf.fonttype'] = 42 |
|
# pylab.rcParams['figure.facecolor'] = 'white' |
|
|
|
|
|
class VCCurve(Protocol): |
|
def __init__(self): |
|
super(VCCurve, self).__init__() |
|
|
|
def reset(self): |
|
super(VCCurve, self).reset() |
|
self.voltage_traces = [] |
|
self.current_traces = [] |
|
self.durs = None # durations of current steps |
|
self.voltage_cmd = None # Current command levels |
|
self.time_values = None |
|
self.dt = None |
|
|
|
def run(self, vcrange, cell, dt=0.025): |
|
""" |
|
Run voltage-clamp I/V curve. |
|
|
|
Parameters |
|
---------- |
|
vmin : float |
|
Minimum voltage step value |
|
vmax : |
|
Maximum voltage step value |
|
vstep : |
|
Voltage difference between steps |
|
cell : |
|
The Cell instance to test. |
|
""" |
|
self.reset() |
|
self.cell = cell |
|
try: |
|
(vmin, vmax, vstep) = vcrange # unpack the tuple... |
|
except: |
|
raise TypeError("run_iv argument 1 must be a tuple (imin, imax, istep)") |
|
|
|
vstim = h.SEClamp(0.5, cell.soma) # set up a single-electrode clamp |
|
vstim.dur1 = 50.0 |
|
vstim.amp1 = -60 |
|
vstim.dur2 = 500.0 |
|
vstim.amp2 = -60.0 |
|
vstim.dur3 = 400 |
|
vstim.amp3 = -60.0 |
|
vstim.rs = 0.01 |
|
cell.soma.cm = 0.001 # reduce capacitative transients (cap compensation) |
|
self.durs = [vstim.dur1, vstim.dur2, vstim.dur3] |
|
self.amps = [vstim.amp1, vstim.amp2, vstim.amp3] |
|
self.voltage_cmd = [] |
|
tend = 900.0 |
|
iv_nstepv = int(np.ceil((vmax - vmin) / vstep)) |
|
iv_minv = vmin |
|
iv_maxv = vmax |
|
vstep = (iv_maxv - iv_minv) / iv_nstepv |
|
for i in range(iv_nstepv): |
|
self.voltage_cmd.append(float(i * vstep) + iv_minv) |
|
nreps = iv_nstepv |
|
h.dt = dt |
|
self.dt = h.dt |
|
for i in range(nreps): |
|
# Connect recording vectors |
|
self["v_soma"] = cell.soma(0.5)._ref_v |
|
self["i_inj"] = vstim._ref_i |
|
self["time"] = h._ref_t |
|
vstim.amp2 = self.voltage_cmd[i] |
|
custom_init(v_init=-60.0) |
|
h.tstop = tend |
|
self.cell.check_all_mechs() |
|
while h.t < h.tstop: |
|
h.fadvance() |
|
self.voltage_traces.append(self["v_soma"]) |
|
self.current_traces.append(self["i_inj"]) |
|
self.time_values = np.array(self["time"]) |
|
|
|
def steady_im(self, window=0.1): |
|
""" |
|
Parameters |
|
---------- |
|
window : float (default: 0.1) |
|
fraction of window to use for steady-state measurement, taken |
|
immediately before the end of the step |
|
Returns |
|
------- |
|
steady-state membrane current for each trace. |
|
""" |
|
Im = self.current_traces |
|
steps = len(Im) |
|
steadyStop = int((self.durs[0] + self.durs[1]) / self.dt) |
|
steadyStart = int(steadyStop - (self.durs[1] * window) / self.dt) |
|
Isteady = [Im[i][steadyStart:steadyStop].mean() for i in range(steps)] |
|
return np.array(Isteady) |
|
|
|
def peak_im(self, window=0.4): |
|
""" |
|
Parameters |
|
---------- |
|
window: float (default=0.4) |
|
fraction of window to use for peak measurement, taken |
|
immediately following the beginning of the step |
|
Returns |
|
------ |
|
steady-state membrane current for each trace. |
|
""" |
|
Im = self.current_traces |
|
steps = len(Im) |
|
peakStop = int((self.durs[0] + window * self.durs[1]) / self.dt) |
|
peakStart = int(self.durs[0] / self.dt) |
|
Vhold = self.amps[ |
|
0 |
|
] # np.mean([self.voltage_traces[i][:peakStart].mean() for i in range(steps)]) |
|
Ipeak = [] |
|
for i in range(steps): |
|
if self.voltage_cmd[i] > Vhold: |
|
Ipeak.append(Im[i][peakStart:peakStop].max()) |
|
else: |
|
Ipeak.append(Im[i][peakStart:peakStop].min()) |
|
return np.array(Ipeak) |
|
|
|
def show(self, cell=None): |
|
""" |
|
Plot results from run_iv() |
|
""" |
|
if not HAVE_PG: |
|
raise Exception("Requires pyqtgraph") |
|
|
|
# |
|
# Generate figure with subplots |
|
# |
|
app = pg.mkQApp() |
|
if cell is not None: |
|
win = pg.GraphicsWindow( |
|
"%s %s (%s)" |
|
% ( |
|
cell.status["name"], |
|
cell.status["modelType"], |
|
cell.status["species"], |
|
) |
|
) |
|
else: |
|
win = pg.GraphisWindow("Voltage Clamp") |
|
self.win = win |
|
win.resize(1000, 800) |
|
Iplot = win.addPlot(labels={"left": "Im (nA)", "bottom": "Time (ms)"}) |
|
rightGrid = win.addLayout(rowspan=2) |
|
win.nextRow() |
|
Vplot = win.addPlot(labels={"left": "V (mV)", "bottom": "Time (ms)"}) |
|
|
|
IVplot = rightGrid.addPlot(labels={"left": "Vm (mV)", "bottom": "Icmd (nA)"}) |
|
IVplot.showGrid(x=True, y=True) |
|
rightGrid.nextRow() |
|
|
|
win.ci.layout.setRowStretchFactor(0, 10) |
|
win.ci.layout.setRowStretchFactor(1, 5) |
|
|
|
# |
|
# Plot simulation and analysis results |
|
# |
|
Vm = self.voltage_traces |
|
Iinj = self.current_traces |
|
Vcmd = self.voltage_cmd |
|
t = self.time_values |
|
steps = len(Vcmd) |
|
|
|
# plot I, V traces |
|
colors = [(i, steps * 3.0 / 2.0) for i in range(steps)] |
|
for i in range(steps): |
|
Vplot.plot(t, Vm[i], pen=colors[i]) |
|
Iplot.plot(t, Iinj[i], pen=colors[i]) |
|
|
|
# I/V relationships |
|
IVplot.plot(Vcmd, self.peak_im(), symbol="o", symbolBrush=(50, 150, 50, 255)) |
|
IVplot.plot(Vcmd, self.steady_im(), symbol="s")
|
|
|