""" test_mechanisms.py This program displays the results of inserting NEURON mechaanisms from .mod files into a point cell to voltage steps in voltage clamp. This code is primarily for visual verification of model function. Usage: python test_mechanisms.py Available mechanisms:: CaPCalyx bkpkj hcno hcnobo hpkj ihpyr ihsgcApical ihsgcBasalMiddle ihvcn jsrna ka kcnq kdpyr kht kif kis klt kpkj kpkj2 kpkjslow kpksk leak lkpkj na naRsg nacn nacncoop nap napyr nav11 Note: only modfiles that implement voltage-dependent ion channel models make sense to run with this routine. the list "nottestablemechs" in the file defines mechanisms provided with cnmodel that cannot be run with this program. """ import sys from neuron import h from neuron import nrn import gc import numpy as np # import scipy as sp import cnmodel.util import pyqtgraph as pg import pyqtgraph.exporters from pyqtgraph.Qt import QtCore, QtGui import cnmodel.util.pynrnutilities as Util nottestablemechs = [ "cadyn", "ca_ion", "cadiff", "cadifpmp", "Mechanism", "capmp", "capump", "cl_ion", "extracellular", "fastpas", "k_ion", "KIR", "hh", "na_ion", "narsg", "pas", "cap", ] # cap uses "pcabar" class ChannelKinetics: def __init__(self, args, export=False): modfile = [] if isinstance(args, list): for arg in args: modfile.append(arg) # must be string, not list... else: modfile.append(args) # 'CaPCalyx' print("modfile: ", modfile) colors = ["b", "r", "g", "y", "c", "m", "w"] if len(modfile) > len(colors): print("Too many modfiles... keep it simple!") exit() # if isinstance(args, list) and len(args) > 1: # modfile2 = args[1] doKinetics = False self.app = pg.mkQApp() self.win = pg.GraphicsWindow() self.win.setWindowTitle("VC Plots") self.win.resize(600, 800) # cw = QtGui.QWidget() # self.win.setCentralWidget(cw) # self.gridLayout = QtGui.QGridLayout() # cw.setLayout(self.gridLayout) # self.gridLayout.setContentsMargins(9, 9, 4, 4) # self.gridLayout.setSpacing(1) self.p1 = self.win.addPlot(title="I (VC)") # self.gridLayout.addWidget(self.p1, 0, 0, 1, 1) self.p2 = self.win.addPlot(title="I_ss, I_max") # self.gridLayout.addWidget(self.p2, 0, 1, 1, 1) self.win.nextRow() self.p3 = self.win.addPlot(title="V command") # self.gridLayout.addWidget(self.p3, 1, 0, 1, 1) self.p5 = self.win.addPlot(title="I_min") # self.gridLayout.addWidget(self.p5, 1, 1, 1, 1) self.win.show() QtGui.QApplication.processEvents() # # self.tdur is a table of durations for the pulse and post-pulse for each channel type (best to highlight features # on appropriate time scales) # self.tdur = { "CaPCalyx": [20.0, 10.0], "nav11": [10.0, 5.0], "jsrna": [10.0, 5.0], "ichanWT2005": [10.0, 5.0], "nacn": [10.0, 5.0], "nacncoop": [10.0, 5.0], "nabu": [10.0, 5.0], "kht": [200.0, 20.0], "klt": [200.0, 20.0], "ka": [25.0, 5.0], "hcno": [1000.0, 200.0], "ih": [1000.0, 200.0], "ihvcn": [1000.0, 200.0], "hcnobo": [1000.0, 200.0], "ihsgcBasalMiddle": [1000.0, 200.0], "ihsgcApical": [1000.0, 200.0], "kif": [100.0, 100.0], "kis": [100.0, 10.0], "napyr": [10, 5.0], "ihpyr": [1000.0, 200.0], "kdpyr": [200.0, 20.0], "kcnq": [200, 20], "nap": [200.0, 100.0], } for i, mfile in enumerate(modfile): self.run(modfile=mfile, color=colors[i], export=export) s = "" # self.win.setWindowTitle('VC Plots: ' + [s+sn+'; ' for sn in modfile]) gc.collect() if doKinetics: self.win2 = pg.GraphicsWindow(title="KineticPlots") self.win2.resize(800, 600) self.kp1 = self.win.addPlot(title="htau") self.computeKinetics("nav11") # self.win.show() def run(self, modfile="CaPCalyx", color="r", export=False): if isinstance(modfile, list): modfile = modfile[0] if modfile in self.tdur: tstep = self.tdur[modfile] else: tstep = [200.0, 50.0] tdelay = 5.0 Channel = cnmodel.util.Mechanism(modfile) leak = cnmodel.util.Mechanism("leak") Channel.set_parameters({"gbar": 1}) leak.set_parameters({"gbar": 1e-12}) # if modfile == 'nacncoop': # self.soma().nacncoop.p = 0. # self.soma().nacncoop.KJ = 0. # # Channel.set_parameters({'p': 0., 'KJ': 000.}) self.soma = cnmodel.util.Section(L=10, diam=10, mechanisms=[Channel, leak]) if modfile == "bkpjk": ca_init = 100e-6 self.soma().cai = ca_init else: ca_init = 70e-6 if modfile == "nacncoop": self.soma().nacncoop.p = 0.1 self.soma().nacncoop.KJ = 1000.0 # Channel.set_parameters({'p': 0., 'KJ': 000.}) h.celsius = 37.0 # set the temperature. self.vec = {} for var in ["time", "V", "IChan", "Vcmd"]: self.vec[var] = h.Vector() h.dt = 0.025 v_init = -65.0 clampV = v_init self.vcPost = h.SEClamp(0.5, sec=self.soma) self.vcPost.dur1 = tdelay self.vcPost.amp1 = clampV self.vcPost.dur2 = tstep[0] self.vcPost.amp2 = clampV - 0.0 # just a tiny step to keep the system honest self.vcPost.dur3 = tstep[1] self.vcPost.amp3 = clampV self.vcPost.rs = 1e-9 print("soma: ", self.soma, end=" ") # print(dir(self.vcPost)) # print(' vcpost sec: ', self.vcPost.Section()) if modfile[0:2] == "ih": stimamp = np.linspace(-140, -40, num=21, endpoint=True) else: stimamp = np.linspace(-100, 60, num=35, endpoint=True) self.ivss = np.zeros((2, stimamp.shape[0])) self.ivmin = np.zeros((2, stimamp.shape[0])) self.ivmax = np.zeros((2, stimamp.shape[0])) print( ( "I range = %6.1f-%6.1f, T = %4.1f" % (np.min(stimamp), np.max(stimamp), h.celsius) ) ) for i, V in enumerate(stimamp): stim = {} stim["NP"] = 1 stim["Sfreq"] = 1 # stimulus frequency stim["delay"] = 5 stim["dur"] = 100 stim["amp"] = V stim["PT"] = 0.0 self.vcPost.amp2 = V self.vec["IChan"].record(self.vcPost._ref_i, sec=self.soma) self.vec["V"].record(self.soma()._ref_v, sec=self.soma) self.vec["time"].record(h._ref_t) # print h.tstop = self.vcPost.dur1 + self.vcPost.dur2 + self.vcPost.dur3 h.finitialize(v_init) h.run() self.t = np.array(self.vec["time"]) self.ichan = np.array(self.vec["IChan"]) self.v = np.array(self.vec["V"]) self.p1.plot(self.t, self.ichan, pen=pg.mkPen((i, len(stimamp) * 1.5))) self.p3.plot(self.t, self.v, pen=pg.mkPen((i, len(stimamp) * 1.5))) (self.ivss[1, i], r2) = Util.measure( "mean", self.t, self.ichan, tdelay + tstep[0] - 10.0, tdelay + tstep[0] ) (self.ivmin[1, i], r2) = Util.measure( "min", self.t, self.ichan, tdelay + 0.1, tdelay + tstep[0] / 5.0 ) (self.ivmax[1, i], r2) = Util.measure( "max", self.t, self.ichan, tdelay + 0.1, tdelay + tstep[0] / 5.0 ) self.ivss[0, i] = V self.ivmin[0, i] = V self.ivmax[0, i] = V self.p2.plot( self.ivss[0, :], self.ivss[1, :], symbol="o", symbolSize=4.0, pen=pg.mkPen(color), ) self.p2.plot( self.ivmax[0, :], self.ivmax[1, :], symbol="t", symbolSize=4.0, pen=pg.mkPen(color), ) self.p5.plot( self.ivmin[0, :], self.ivmin[1, :], symbol="s", symbolSize=4.0, pen=pg.mkPen(color), ) print(export) if export: exporter = pg.exporters.MatplotlibExporter(self.p1) print("exporting: " + "%s_traces.svg" % modfile) exporter.export(fileName="%s_traces.pdf" % modfile) exporter = pg.exporters.MatplotlibExporter(self.p3) exporter.export("%s_command.pdf" % modfile) exporter = pg.exporters.MatplotlibExporter(self.p2) exporter.export("%s_IV.pdf" % modfile) def computeKinetics(self, ch): pass def getmechs(): mechs = [] for n in dir(nrn): o = getattr(nrn, n) if str(o) == str(nrn.Mechanism): mechs.append(n) return mechs if __name__ == "__main__": mechs = getmechs() if len(sys.argv) < 2: print("\n\nUsage: python test_mechanisms.py ") print(" Available mechanisms:") linelen = 0 for i, n in enumerate(mechs): if n in nottestablemechs: # 'Mechanism': continue print("%20s" % n, end=" ") linelen += 20 if linelen > 80: print("") linelen = 0 sys.exit(1) if sys.argv[1:] in nottestablemechs: exit() export = False if len(sys.argv) > 2: if sys.argv[2] == "export": export = True if sys.argv[1] == "all": for n in mechs: if n in nottestablemechs: print(("Skipping %s" % n)) continue else: ck = ChannelKinetics(n) else: ck = ChannelKinetics(sys.argv[1], export=export) if sys.flags.interactive == 0: pg.QtGui.QApplication.exec_()