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")