copying to personal repo
This commit is contained in:
23
cnmodel/cells/__init__.py
Normal file
23
cnmodel/cells/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
Cell definitions for models.
|
||||
|
||||
This class includes a number of different cell definitions and default
|
||||
conductances for point models.
|
||||
"""
|
||||
|
||||
from .bushy import *
|
||||
from .tstellate import *
|
||||
from .dstellate import *
|
||||
from .cartwheel import *
|
||||
from .pyramidal import *
|
||||
from .sgc import *
|
||||
from .octopus import *
|
||||
from .tuberculoventral import *
|
||||
from .msoprincipal import *
|
||||
from .hh import *
|
||||
|
||||
from .cell import Cell
|
||||
|
||||
|
||||
def cell_from_section(sec):
|
||||
return Cell.from_section(sec)
|
||||
967
cnmodel/cells/bushy.py
Normal file
967
cnmodel/cells/bushy.py
Normal file
@@ -0,0 +1,967 @@
|
||||
from __future__ import print_function
|
||||
from neuron import h
|
||||
from collections import OrderedDict
|
||||
from .cell import Cell
|
||||
from .. import synapses
|
||||
from ..util import nstomho
|
||||
from ..util import Params
|
||||
import numpy as np
|
||||
from .. import data
|
||||
import pprint
|
||||
|
||||
pp = pprint.PrettyPrinter(indent=4, width=60)
|
||||
|
||||
__all__ = ["Bushy", "BushyRothman"]
|
||||
|
||||
|
||||
class Bushy(Cell):
|
||||
|
||||
type = "bushy"
|
||||
|
||||
@classmethod
|
||||
def create(cls, model="RM03", **kwds):
|
||||
if model == "RM03":
|
||||
return BushyRothman(**kwds)
|
||||
else:
|
||||
raise ValueError("Bushy model %s is unknown", model)
|
||||
|
||||
def make_psd(self, terminal, psd_type, **kwds):
|
||||
"""
|
||||
Connect a presynaptic terminal to one post section at the specified location, with the fraction
|
||||
of the "standard" conductance determined by gbar.
|
||||
The default condition is designed to pass the unit test (loc=0.5)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
terminal : Presynaptic terminal (NEURON object)
|
||||
|
||||
psd_type : either simple or multisite PSD for bushy cell
|
||||
|
||||
kwds: dictionary of options.
|
||||
Two are currently handled:
|
||||
postsite : expect a list consisting of [sectionno, location (float)]
|
||||
AMPAScale : float to scale the ampa currents
|
||||
|
||||
"""
|
||||
if (
|
||||
"postsite" in kwds
|
||||
): # use a defined location instead of the default (soma(0.5)
|
||||
postsite = kwds["postsite"]
|
||||
loc = postsite[1] # where on the section?
|
||||
uname = (
|
||||
"sections[%d]" % postsite[0]
|
||||
) # make a name to look up the neuron section object
|
||||
post_sec = self.hr.get_section(uname) # Tell us where to put the synapse.
|
||||
else:
|
||||
loc = 0.5
|
||||
post_sec = self.soma
|
||||
|
||||
if psd_type == "simple":
|
||||
if terminal.cell.type in ["sgc", "dstellate", "tuberculoventral"]:
|
||||
weight = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="weight",
|
||||
)
|
||||
tau1 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau1",
|
||||
)
|
||||
tau2 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau2",
|
||||
)
|
||||
erev = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="erev",
|
||||
)
|
||||
return self.make_exp2_psd(
|
||||
post_sec,
|
||||
terminal,
|
||||
weight=weight,
|
||||
loc=loc,
|
||||
tau1=tau1,
|
||||
tau2=tau2,
|
||||
erev=erev,
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make simple PSD for %s => %s"
|
||||
% (terminal.cell.type, self.type)
|
||||
)
|
||||
|
||||
elif psd_type == "multisite":
|
||||
if terminal.cell.type == "sgc":
|
||||
# Max conductances for the glu mechanisms are calibrated by
|
||||
# running `synapses/tests/test_psd.py`. The test should fail
|
||||
# if these values are incorrect
|
||||
self.AMPAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="AMPAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.NMDAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="NMDAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.Pr = data.get(
|
||||
"sgc_synapse", species=self.species, post_type=self.type, field="Pr"
|
||||
)
|
||||
self.NMDAR_vshift = data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="NMDAR_vshift",
|
||||
)
|
||||
# adjust gmax to correct for initial Pr
|
||||
self.AMPAR_gmax = self.AMPAR_gmax / self.Pr
|
||||
self.NMDAR_gmax = self.NMDAR_gmax / self.Pr
|
||||
|
||||
# original values (now in synapses.py):
|
||||
# self.AMPA_gmax = 3.314707700918133*1e3 # factor of 1e3 scales to pS (.mod mechanisms) from nS.
|
||||
# self.NMDA_gmax = 0.4531929783503451*1e3
|
||||
if "AMPAScale" in kwds: # normally, this should not be done!
|
||||
self.AMPAR_gmax = (
|
||||
self.AMPAR_gmax * kwds["AMPAScale"]
|
||||
) # allow scaling of AMPA conductances
|
||||
if "NMDAScale" in kwds:
|
||||
self.NMDAR_gmax = self.NMDAR_gmax * kwds["NMDAScale"] # and NMDA...
|
||||
return self.make_glu_psd(
|
||||
post_sec,
|
||||
terminal,
|
||||
self.AMPAR_gmax,
|
||||
self.NMDAR_gmax,
|
||||
loc=loc,
|
||||
nmda_vshift=self.NMDAR_vshift,
|
||||
)
|
||||
elif terminal.cell.type == "dstellate":
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyslow", loc=loc)
|
||||
elif terminal.cell.type == "tuberculoventral":
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyslow", loc=loc)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make PSD for %s => %s" % (terminal.cell.type, self.type)
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported psd type %s" % psd_type)
|
||||
|
||||
def make_terminal(self, post_cell, term_type, **kwds):
|
||||
if term_type == "simple":
|
||||
return synapses.SimpleTerminal(self.soma, post_cell, **kwds)
|
||||
|
||||
elif term_type == "multisite":
|
||||
if post_cell.type in ["mso"]:
|
||||
nzones = data.get(
|
||||
"bushy_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="n_rsites",
|
||||
)
|
||||
delay = data.get(
|
||||
"bushy_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="delay",
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"No knowledge as to how to connect Bushy cell to cell type %s"
|
||||
% type(post_cell)
|
||||
)
|
||||
pre_sec = self.soma
|
||||
return synapses.StochasticTerminal(
|
||||
pre_sec,
|
||||
post_cell,
|
||||
nzones=nzones,
|
||||
spike_source=self.spike_source,
|
||||
delay=delay,
|
||||
**kwds,
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported terminal type %s" % term_type)
|
||||
|
||||
|
||||
class BushyRothman(Bushy):
|
||||
"""
|
||||
VCN bushy cell models.
|
||||
Rothman and Manis, 2003abc (Type II, Type II-I)
|
||||
Xie and Manis, 2013
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach=None,
|
||||
ttx=False,
|
||||
species="guineapig",
|
||||
modelType=None,
|
||||
modelName=None,
|
||||
debug=False,
|
||||
temperature=None,
|
||||
):
|
||||
"""
|
||||
Create a bushy cell, using the default parameters for guinea pig from
|
||||
R&M2003, as a type II cell.
|
||||
Additional modifications to the cell can be made by calling methods below.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
Name of a .hoc file representing the morphology. This file is used to constructe
|
||||
an electrotonic (cable) model.
|
||||
If None (default), then a "point" (really, single cylinder) model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels is inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: None)
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanism
|
||||
by that name must exist. The default channel is set to 'nacn' (R&M03)
|
||||
|
||||
temperature : float (default: 22)
|
||||
temperature to run the cell at.
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
This flag duplicates the effects of tetrodotoxin in the model. Currently, the flag is not implemented.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the pattern of ion channel densities that will be inserted, according to
|
||||
prior measurements in various species. Note that
|
||||
if a decorator function is specified, this argument is ignored as the decorator will
|
||||
specify the channel density.
|
||||
|
||||
modelName: string (default: None)
|
||||
modelName specifies the source conductance pattern (RM03, XM13, etc).
|
||||
modelName is passed to the decorator, or to species_scaling to adjust point (single cylinder) models.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the subtype of the cell model that will be used (e.g., "II", "II-I", etc).
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point (single cylinder) models.
|
||||
|
||||
debug: boolean (default: False)
|
||||
When True, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
"""
|
||||
super(BushyRothman, self).__init__()
|
||||
self.i_test_range = {
|
||||
"pulse": (-1, 1, 0.05)
|
||||
} # note that this might get reset with decorator according to channels
|
||||
# Changing the default values will cause the unit tests to fail!
|
||||
if modelType == None:
|
||||
modelType = "II"
|
||||
if species == "guineapig":
|
||||
modelName = "RM03"
|
||||
temp = 22.0
|
||||
if nach == None:
|
||||
nach = "na"
|
||||
if species == "mouse":
|
||||
temp = 34.0
|
||||
if modelName is None:
|
||||
modelName = "XM13"
|
||||
if nach is None:
|
||||
nach = "na"
|
||||
self.debug = debug
|
||||
self.status = {
|
||||
"species": species,
|
||||
"cellClass": self.type,
|
||||
"modelType": modelType,
|
||||
"modelName": modelName,
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"hillock": False,
|
||||
"initialsegment": False,
|
||||
"myelinatedaxon": False,
|
||||
"unmyelinatedaxon": False,
|
||||
"na": nach,
|
||||
"ttx": ttx,
|
||||
"name": self.type,
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": temperature,
|
||||
}
|
||||
|
||||
self.spike_threshold = -40
|
||||
self.vrange = [-70.0, -55.0] # set a default vrange for searching for rmp
|
||||
if self.debug:
|
||||
print(
|
||||
"model type, model name, species: ", modelType, modelName, species, nach
|
||||
)
|
||||
|
||||
self.c_m = 0.9e-6 # default in units of F/cm^2
|
||||
|
||||
self._valid_temperatures = (temp,)
|
||||
if self.status["temperature"] == None:
|
||||
self.status["temperature"] = temp
|
||||
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
if self.debug:
|
||||
print("<< Bushy model: Creating point cell >>")
|
||||
soma = h.Section(
|
||||
name="Bushy_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
if self.debug:
|
||||
print(
|
||||
"<< Bushy model: Creating cell with morphology from %s >>"
|
||||
% morphology
|
||||
)
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma, does not use tables.
|
||||
self.mechanisms = ["klt", "kht", "ihvcn", "leak", nach]
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.soma.ena = self.e_na
|
||||
self.soma.ek = self.e_k
|
||||
self.soma().ihvcn.eh = self.e_h
|
||||
self.soma().leak.erev = self.e_leak
|
||||
self.c_m = 0.9
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments, with tables.
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
if debug:
|
||||
print(" << Created cell >>")
|
||||
|
||||
def get_cellpars(self, dataset, species="guineapig", modelType="II"):
|
||||
"""
|
||||
Read data for ion channels and cell parameters from the tables
|
||||
"""
|
||||
# cell_type = self.map_celltype(cell_type)
|
||||
# print('getcellpars: dataset, species, mmodeltype: ', dataset, species, modelType)
|
||||
# print('model name: ', self.status['modelName'])
|
||||
cellcap = data.get(
|
||||
dataset, species=species, model_type=modelType, field="soma_Cap"
|
||||
)
|
||||
chtype = data.get(
|
||||
dataset, species=species, model_type=modelType, field="na_type"
|
||||
)
|
||||
pars = Params(cap=cellcap, natype=chtype)
|
||||
# print('pars cell/chtype: ')
|
||||
if self.debug:
|
||||
pars.show()
|
||||
if self.status["modelName"] == "RM03":
|
||||
for g in [
|
||||
"%s_gbar" % pars.natype,
|
||||
"kht_gbar",
|
||||
"klt_gbar",
|
||||
"ih_gbar",
|
||||
"leak_gbar",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, model_type=modelType, field=g)
|
||||
)
|
||||
if self.status["modelName"] == "XM13":
|
||||
for g in [
|
||||
"%s_gbar" % pars.natype,
|
||||
"kht_gbar",
|
||||
"klt_gbar",
|
||||
"ihvcn_gbar",
|
||||
"leak_gbar",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, model_type=modelType, field=g)
|
||||
)
|
||||
if self.status["modelName"] == "mGBC":
|
||||
for g in [
|
||||
"%s_gbar" % pars.natype,
|
||||
"kht_gbar",
|
||||
"klt_gbar",
|
||||
"ihvcn_gbar",
|
||||
"leak_gbar",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, model_type=modelType, field=g)
|
||||
)
|
||||
|
||||
return pars
|
||||
|
||||
def species_scaling(self, species="guineapig", modelType="II", silent=True):
|
||||
"""
|
||||
This is called for POINT CELLS ONLY
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
This scaling should be used ONLY for point models, as no other compartments
|
||||
are scaled.
|
||||
|
||||
This scaling routine also sets the temperature for the model to a default value. Some models
|
||||
can be run at multiple temperatures, and so a default from one of the temperatures is used.
|
||||
The calling cell.set_temperature(newtemp) will change the conductances and reinitialize
|
||||
the cell to the new temperature settings.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be one of mouse, cat, guineapig
|
||||
|
||||
modelType: string (default: 'II')
|
||||
definition of model type from RM03 models, type II or type II-I
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
|
||||
"""
|
||||
# print '\nSpecies scaling: %s %s' % (species, type)
|
||||
knownspecies = ["mouse", "guineapig", "cat"]
|
||||
|
||||
soma = self.soma
|
||||
# cellType = self.map_celltype(modelType)
|
||||
|
||||
if species == "mouse":
|
||||
# use conductance levels determined from Cao et al., J. Neurophys., 2007. as
|
||||
# model description in Xie and Manis 2013. Note that
|
||||
# conductances were not scaled for temperature (rates were)
|
||||
# so here we reset the default Q10's for conductance (g) to 1.0
|
||||
if modelType not in ["II", "II-I"]:
|
||||
raise ValueError(
|
||||
"\nModel type %s is not implemented for mouse bushy cells"
|
||||
% modelType
|
||||
)
|
||||
if self.debug:
|
||||
print(
|
||||
" Setting conductances for mouse bushy cell (%s), Xie and Manis, 2013"
|
||||
% modelType
|
||||
)
|
||||
if modelname == "XM13":
|
||||
dataset = "XM13_channels"
|
||||
elif modelname == "XM13nacncoop":
|
||||
dataset = "XM13_channels_nacncoop"
|
||||
elif modelname.startswith("mGBC"):
|
||||
dataset = "mGBC_channels"
|
||||
else:
|
||||
raise ValueError(
|
||||
f"ModelName {modelname:s} not recognized for mouse bushy cells"
|
||||
)
|
||||
self.vrange = [-68.0, -55.0] # set a default vrange for searching for rmp
|
||||
self.i_test_range = {"pulse": (-1.0, 1.0, 0.05)}
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.status["temperature"] = 34.0
|
||||
|
||||
pars = self.get_cellpars(dataset, species=species, modelType=modelType)
|
||||
self.set_soma_size_from_Cm(pars.cap)
|
||||
self.status["na"] = pars.natype
|
||||
self.adjust_na_chans(soma, sf=1.0)
|
||||
soma().kht.gbar = nstomho(pars.kht_gbar, self.somaarea)
|
||||
soma().klt.gbar = nstomho(pars.klt_gbar, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(pars.ihvcn_gbar, self.somaarea)
|
||||
soma().leak.gbar = nstomho(pars.leak_gbar, self.somaarea)
|
||||
self.axonsf = 0.57
|
||||
|
||||
elif species == "guineapig":
|
||||
if self.debug:
|
||||
print(
|
||||
" Setting conductances for guinea pig %s bushy cell, Rothman and Manis, 2003"
|
||||
% modelType
|
||||
)
|
||||
self._valid_temperatures = (22.0, 38.0)
|
||||
if self.status["temperature"] is None:
|
||||
self.status["temperature"] = 22.0
|
||||
self.i_test_range = {"pulse": (-0.4, 0.4, 0.02)}
|
||||
sf = 1.0
|
||||
if (
|
||||
self.status["temperature"] == 38.0
|
||||
): # adjust for 2003 model conductance levels at 38
|
||||
sf = 2 # Q10 of 2, 22->38C. (p3106, R&M2003c)
|
||||
# note that kinetics are scaled in the mod file.
|
||||
dataset = "RM03_channels"
|
||||
pars = self.get_cellpars(dataset, species=species, modelType=modelType)
|
||||
self.set_soma_size_from_Cm(pars.cap)
|
||||
self.status["na"] = pars.natype
|
||||
self.adjust_na_chans(soma, sf=sf)
|
||||
soma().kht.gbar = nstomho(pars.kht_gbar, self.somaarea)
|
||||
soma().klt.gbar = nstomho(pars.klt_gbar, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(pars.ih_gbar, self.somaarea)
|
||||
soma().leak.gbar = nstomho(pars.leak_gbar, self.somaarea)
|
||||
|
||||
self.axonsf = 0.57
|
||||
|
||||
else:
|
||||
errmsg = (
|
||||
'Species "%s" or model type "%s" is not recognized for Bushy cells.'
|
||||
% (species, modelType)
|
||||
)
|
||||
errmsg += "\n Valid species are: \n"
|
||||
for s in knownspecies:
|
||||
errmsg += " %s\n" % s
|
||||
errmsg += "-" * 40
|
||||
raise ValueError(errmsg)
|
||||
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
self.check_temperature()
|
||||
# self.cell_initialize(vrange=self.vrange) # no need to do this just yet.
|
||||
if not silent:
|
||||
print(" set cell as: ", species)
|
||||
print(" with Vm rest = %6.3f" % self.vm0)
|
||||
|
||||
# def channel_manager(self, modelType='RM03', cell_type='bushy-II'):
|
||||
# """
|
||||
# This routine defines channel density maps and distance map patterns
|
||||
# for each type of compartment in the cell. The maps
|
||||
# are used by the ChannelDecorator class (specifically, its private
|
||||
# \_biophys function) to decorate the cell membrane.
|
||||
# These settings are only used if the decorator is called; otherwise
|
||||
# for point cells, the species_scaling routine defines the channel
|
||||
# densities.
|
||||
#
|
||||
# Parameters
|
||||
# ----------
|
||||
# modelType : string (default: 'RM03')
|
||||
# A string that defines the type of the model. Currently, 3 types are implemented:
|
||||
# RM03: Rothman and Manis, 2003 somatic densities for guinea pig
|
||||
# XM13: Xie and Manis, 2013, somatic densities for mouse
|
||||
# mGBC: experimental mouse globular bushy cell with dendrites, axon, hillock and initial segment, for
|
||||
# use with fully reconstructed neurons.
|
||||
#
|
||||
# Returns
|
||||
# -------
|
||||
# Nothing
|
||||
#
|
||||
# Notes
|
||||
# -----
|
||||
# This routine defines the following variables for the class:
|
||||
#
|
||||
# * conductances (gBar)
|
||||
# * a channelMap (dictonary of channel densities in defined anatomical compartments)
|
||||
# * a current injection range for IV's (used for testing)
|
||||
# * a distance map, which defines how each conductance in a selected compartment
|
||||
# changes with distance from the soma. The current implementation includes both
|
||||
# linear and exponential gradients,
|
||||
# the minimum conductance at the end of the gradient, and the space constant or
|
||||
# slope for the gradient.
|
||||
#
|
||||
# """
|
||||
#
|
||||
#
|
||||
# dataset = '%s_channels' % modelType
|
||||
# decorationmap = dataset + '_compartments'
|
||||
# # print('dataset: {0:s} decorationmap: {1:s}'.format(dataset, decorationmap))
|
||||
# cellpars = self.get_cellpars(dataset, species=self.status['species'], celltype=cell_type)
|
||||
# refarea = 1e-3*cellpars.cap / self.c_m
|
||||
#
|
||||
# table = data.get_table_info(dataset)
|
||||
# chscale = data.get_table_info(decorationmap)
|
||||
# pars = {}
|
||||
# # retrive the conductances from the data set
|
||||
# for g in table['field']:
|
||||
# x = data.get(dataset, species=self.status['species'], cell_type=cell_type,
|
||||
# field=g)
|
||||
# if not isinstance(x, float):
|
||||
# continue
|
||||
# if '_gbar' in g:
|
||||
# pars[g] = x/refarea
|
||||
# else:
|
||||
# pars[g] = x
|
||||
#
|
||||
# self.channelMap = OrderedDict()
|
||||
# for c in chscale['compartment']:
|
||||
# self.channelMap[c] = {}
|
||||
# for g in pars.keys():
|
||||
# if g not in chscale['parameter']:
|
||||
# # print ('Parameter %s not found in chscale parameters!' % g)
|
||||
# continue
|
||||
# scale = data.get(decorationmap, species=self.status['species'], cell_type=cell_type,
|
||||
# compartment=c, parameter=g)
|
||||
# if '_gbar' in g:
|
||||
# self.channelMap[c][g] = pars[g]*scale
|
||||
# else:
|
||||
# self.channelMap[c][g] = pars[g]
|
||||
#
|
||||
# self.irange = np.linspace(-0.6, 1, 9)
|
||||
|
||||
def get_distancemap(self):
|
||||
return {
|
||||
"dend": {
|
||||
"klt": {"gradient": "exp", "gminf": 0.0, "lambda": 50.0},
|
||||
"kht": {"gradient": "exp", "gminf": 0.0, "lambda": 50.0},
|
||||
"nav11": {"gradient": "exp", "gminf": 0.0, "lambda": 50.0},
|
||||
}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
"dendrite": {
|
||||
"klt": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"kht": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"nav11": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
"apic": {
|
||||
"klt": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"kht": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"nav11": {"gradient": "exp", "gminf": 0.0, "lambda": 200.0},
|
||||
}, # gradients are: flat, linear, exponential
|
||||
}
|
||||
# self.check_temperature()
|
||||
# return
|
||||
#
|
||||
|
||||
#
|
||||
#
|
||||
# if modelType == 'RM03':
|
||||
# #
|
||||
# # Create a model based on the Rothman and Manis 2003 conductance set from guinea pig
|
||||
# #
|
||||
# self.c_m = 0.9E-6 # default in units of F/cm^2
|
||||
# self._valid_temperatures = (22., 38.)
|
||||
# sf = 1.0
|
||||
# if self.status['temperature'] == None:
|
||||
# self.status['temperature'] = 22.
|
||||
# if self.status['temperature'] == 38:
|
||||
# sf = 3.03
|
||||
# dataset = 'RM03_channels'
|
||||
# pars = self.get_cellpars(dataset, species=self.status['species'], celltype='bushy-II')
|
||||
# refarea = 1e-3*pars.cap / self.c_m
|
||||
# self.gBar = Params(nabar=sf*pars.soma_na_gbar/refarea, # 1000.0E-9/refarea,
|
||||
# khtbar=sf*pars.soma_kht_gbar/refarea,
|
||||
# kltbar=sf*pars.soma_klt_gbar/refarea,
|
||||
# ihbar=sf*pars.soma_ih_gbar/refarea,
|
||||
# leakbar=sf*pars.soma_leak_gbar/refarea,
|
||||
# )
|
||||
# print 'RM03 gbar:\n', self.gBar.show()
|
||||
#
|
||||
# self.channelMap = {
|
||||
# 'axon': {'nacn': self.gBar.nabar, 'klt': self.gBar.kltbar, 'kht': self.gBar.khtbar, 'ihvcn': 0.,
|
||||
# 'leak': self.gBar.leakbar / 2.},
|
||||
# 'hillock': {'nacn': self.gBar.nabar, 'klt': self.gBar.kltbar, 'kht': self.gBar.khtbar, 'ihvcn': 0.,
|
||||
# 'leak': self.gBar.leakbar, },
|
||||
# 'initseg': {'nacn': self.gBar.nabar, 'klt': self.gBar.kltbar, 'kht': self.gBar.khtbar,
|
||||
# 'ihvcn': self.gBar.ihbar / 2., 'leak': self.gBar.leakbar, },
|
||||
# 'soma': {'nacn': self.gBar.nabar, 'klt': self.gBar.kltbar, 'kht': self.gBar.khtbar,
|
||||
# 'ihvcn': self.gBar.ihbar, 'leak': self.gBar.leakbar, },
|
||||
# 'dend': {'nacn': self.gBar.nabar, 'klt': self.gBar.kltbar * 0.5, 'kht': self.gBar.khtbar * 0.5,
|
||||
# 'ihvcn': self.gBar.ihbar / 3., 'leak': self.gBar.leakbar * 0.5, },
|
||||
# 'apic': {'nacn': self.gBar.nabar, 'klt': self.gBar.kltbar * 0.2, 'kht': self.gBar.khtbar * 0.2,
|
||||
# 'ihvcn': self.gBar.ihbar / 4., 'leak': self.gBar.leakbar * 0.2, },
|
||||
# }
|
||||
# # self.irange = np.linspace(-1., 1., 21)
|
||||
# self.distMap = {'dend': {'klt': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'kht': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'nacn': {'gradient': 'exp', 'gminf': 0., 'lambda': 100.}}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
# 'apic': {'klt': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'kht': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'nacn': {'gradient': 'exp', 'gminf': 0., 'lambda': 100.}}, # gradients are: flat, linear, exponential
|
||||
# }
|
||||
#
|
||||
# elif modelType == 'XM13':
|
||||
# #
|
||||
# # Create a model for a mouse bushy cell from Xie and Manis, 2013
|
||||
# # based on Cao and Oertel mouse conductance values
|
||||
# # and Rothman and Manis kinetics.
|
||||
# self.c_m = 0.9E-6 # default in units of F/cm^2
|
||||
# self._valid_temperatures = (34., )
|
||||
# if self.status['temperature'] == None:
|
||||
# self.status['temperature'] = 34.
|
||||
# dataset = 'XM13_channels'
|
||||
# pars = self.get_cellpars(dataset, species=self.status['species'], celltype='bushy-II')
|
||||
# refarea = 1e-3*pars.cap / self.c_m
|
||||
# # self.gBar = Params(nabar=pars.soma_nav11_gbar/refarea, # 1000.0E-9/refarea,
|
||||
# # khtbar=pars.soma_kht_gbar/refarea,
|
||||
# # kltbar=pars.soma_klt_gbar/refarea,
|
||||
# # ihbar=pars.soma_ihvcn_gbar/refarea,
|
||||
# # leakbar=pars.soma_leak_gbar/refarea,
|
||||
# # )
|
||||
# # print 'XM13 gbar:\n', self.gBar.show()
|
||||
# # # create channel map:
|
||||
# decorationmap = 'XM13_channels_bycompartment'
|
||||
#
|
||||
# table = data.get_table_info(dataset)
|
||||
# pars = {}
|
||||
# for g in table['field']:
|
||||
# x = data.get(dataset, species=self.status['species'], cell_type='bushy-II',
|
||||
# field=g)
|
||||
# if not isinstance(x, float):
|
||||
# continue
|
||||
# pars[g] = (1./refarea)*data.get(dataset, species=self.status['species'], cell_type='bushy-II',
|
||||
# field=g)
|
||||
# chscale = data.get_table_info(decorationmap)
|
||||
# self.channelMap1 = OrderedDict()
|
||||
# # print chscale['parameter']
|
||||
# for c in chscale['compartment']:
|
||||
# self.channelMap1[c] = {}
|
||||
# for g in pars.keys():
|
||||
# # print g
|
||||
# if g[5:] not in chscale['parameter']:
|
||||
# continue
|
||||
# scale = data.get(decorationmap, species=self.status['species'], cell_type='bushy-II',
|
||||
# compartment=c, parameter=g[5:])
|
||||
# self.channelMap1[c][g] = pars[g]*scale
|
||||
#
|
||||
# #
|
||||
# # self.channelMap = {
|
||||
# # 'unmyelinatedaxon': {'nav11': self.gBar.nabar*1, 'klt': self.gBar.kltbar * 1.0, 'kht': self.gBar.khtbar, 'ihvcn': 0.,
|
||||
# # 'leak': self.gBar.leakbar * 0.25},
|
||||
# # 'hillock': {'nav11': self.gBar.nabar*2, 'klt': self.gBar.kltbar, 'kht': self.gBar.khtbar*2.0, 'ihvcn': 0.,
|
||||
# # 'leak': self.gBar.leakbar, },
|
||||
# # 'initialsegment': {'nav11': self.gBar.nabar*3.0, 'klt': self.gBar.kltbar*1, 'kht': self.gBar.khtbar*2,
|
||||
# # 'ihvcn': self.gBar.ihbar * 0.5, 'leak': self.gBar.leakbar, },
|
||||
# # 'soma': {'nav11': self.gBar.nabar*1.0, 'klt': self.gBar.kltbar, 'kht': self.gBar.khtbar,
|
||||
# # 'ihvcn': self.gBar.ihbar, 'leak': self.gBar.leakbar, },
|
||||
# # 'dend': {'nav11': self.gBar.nabar * 0.25, 'klt': self.gBar.kltbar *0.5, 'kht': self.gBar.khtbar *0.5,
|
||||
# # 'ihvcn': self.gBar.ihbar *0.5, 'leak': self.gBar.leakbar * 0.5, },
|
||||
# # 'primarydendrite': {'nav11': self.gBar.nabar * 0.25, 'klt': self.gBar.kltbar *0.5, 'kht': self.gBar.khtbar *0.5,
|
||||
# # 'ihvcn': self.gBar.ihbar *0.5, 'leak': self.gBar.leakbar * 0.5, },
|
||||
# # 'apic': {'nav11': self.gBar.nabar * 0.25, 'klt': self.gBar.kltbar * 0.25, 'kht': self.gBar.khtbar * 0.25,
|
||||
# # 'ihvcn': self.gBar.ihbar *0.25, 'leak': self.gBar.leakbar * 0.25, },
|
||||
# # }
|
||||
# import pprint
|
||||
# # print 'original map:\n'
|
||||
# # for k in self.channelMap.keys():
|
||||
# # print('Region: %s' % k)
|
||||
# # if k in self.channelMap1.keys():
|
||||
# # print 'overlapping Region: %s' % k
|
||||
# # for ch in self.channelMap[k].keys():
|
||||
# # # print ch
|
||||
# # # print self.channelMap1[k].keys()
|
||||
# # # print self.channelMap[k].keys()
|
||||
# # if 'soma_' + ch + '_gbar' in self.channelMap1[k].keys():
|
||||
# # cx = u'soma_' + ch + u'_gbar'
|
||||
# # # print ch, cx
|
||||
# # print( ' {0:>4s} = {1:e} {2:e} {3:<5s}'.format(ch, self.channelMap[k][ch], self.channelMap1[k][cx],
|
||||
# # str(np.isclose(self.channelMap[k][ch], self.channelMap1[k][cx]))))
|
||||
#
|
||||
# # print 'original: ', self.channelMap['soma']
|
||||
# self.channelMap = self.channelMap1 # use the data table
|
||||
# # except need to remove soma_ from keys
|
||||
# for k in self.channelMap.keys():
|
||||
# for n in self.channelMap[k].keys():
|
||||
# new_key = n.replace('_gbar', '')
|
||||
# # new_key = n
|
||||
# new_key = new_key.replace('soma_', '')
|
||||
# # strip 'soma_' from key
|
||||
# #print 'newkey: ', new_key, n
|
||||
# self.channelMap[k][new_key] = self.channelMap[k].pop(n)
|
||||
#
|
||||
# print 'final map: ', self.channelMap['soma']
|
||||
#
|
||||
# self.irange = np.linspace(-0.6, 1, 9)
|
||||
# self.distMap = {'dend': {'klt': {'gradient': 'exp', 'gminf': 0., 'lambda': 50.},
|
||||
# 'kht': {'gradient': 'exp', 'gminf': 0., 'lambda': 50.},
|
||||
# 'nav11': {'gradient': 'exp', 'gminf': 0., 'lambda': 50.}}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
# 'dendrite': {'klt': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'kht': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'nav11': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.}}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
# 'apic': {'klt': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'kht': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'nav11': {'gradient': 'exp', 'gminf': 0., 'lambda': 200.}}, # gradients are: flat, linear, exponential
|
||||
# }
|
||||
#
|
||||
# elif modelType == 'mGBC':
|
||||
# # bushy from Xie and Manis, 2013, based on Cao and Oertel mouse conductances,
|
||||
# # BUT modified ad hoc for SBEM reconstructions.
|
||||
# dataset = 'mGBC_channels'
|
||||
#
|
||||
# self._valid_temperatures = (34.,)
|
||||
# if self.status['temperature'] == None:
|
||||
# self.status['temperature'] = 34.
|
||||
# pars = self.get_cellpars(dataset, species=self.status['species'], celltype='bushy-II')
|
||||
# refarea = 1e-3*pars.cap / self.c_m
|
||||
# print (pars.cap, pars.soma_kht_gbar, refarea) # refarea should be about 30e-6
|
||||
#
|
||||
# self.gBar = Params(nabar=pars.soma_na_gbar/refarea, # 1000.0E-9/refarea,
|
||||
# khtbar=pars.soma_kht_gbar/refarea,
|
||||
# kltbar=pars.soma_klt_gbar/refarea,
|
||||
# ihbar=pars.soma_ih_gbar/refarea,
|
||||
# leakbar=pars.soma_leak_gbar/refarea,
|
||||
# )
|
||||
# print 'mGBC gbar:\n', self.gBar.show()
|
||||
# sodiumch = 'jsrna'
|
||||
# self.channelMap = {
|
||||
# 'axon': {sodiumch: self.gBar.nabar*1., 'klt': self.gBar.kltbar * 1.0, 'kht': self.gBar.khtbar, 'ihvcn': 0.,
|
||||
# 'leak': self.gBar.leakbar * 0.25},
|
||||
# 'unmyelinatedaxon': {sodiumch: self.gBar.nabar*3.0, 'klt': self.gBar.kltbar * 2.0,
|
||||
# 'kht': self.gBar.khtbar*3.0, 'ihvcn': 0.,
|
||||
# 'leak': self.gBar.leakbar * 0.25},
|
||||
# 'myelinatedaxon': {sodiumch: self.gBar.nabar*0, 'klt': self.gBar.kltbar * 1e-2,
|
||||
# 'kht': self.gBar.khtbar*1e-2, 'ihvcn': 0.,
|
||||
# 'leak': self.gBar.leakbar * 0.25*1e-3},
|
||||
# 'hillock': {sodiumch: self.gBar.nabar*4.0, 'klt': self.gBar.kltbar*1.0, 'kht': self.gBar.khtbar*3.0,
|
||||
# 'ihvcn': 0., 'leak': self.gBar.leakbar, },
|
||||
# 'initseg': {sodiumch: self.gBar.nabar*3.0, 'klt': self.gBar.kltbar*2, 'kht': self.gBar.khtbar*2,
|
||||
# 'ihvcn': self.gBar.ihbar * 0.5, 'leak': self.gBar.leakbar, },
|
||||
# 'soma': {sodiumch: self.gBar.nabar*0.65, 'klt': self.gBar.kltbar, 'kht': self.gBar.khtbar*1.5,
|
||||
# 'ihvcn': self.gBar.ihbar, 'leak': self.gBar.leakbar, },
|
||||
# 'dend': {sodiumch: self.gBar.nabar * 0.2, 'klt': self.gBar.kltbar *1, 'kht': self.gBar.khtbar *1,
|
||||
# 'ihvcn': self.gBar.ihbar *0.5, 'leak': self.gBar.leakbar * 0.5, },
|
||||
# 'dendrite': {sodiumch: self.gBar.nabar * 0.2, 'klt': self.gBar.kltbar *1, 'kht': self.gBar.khtbar *1,
|
||||
# 'ihvcn': self.gBar.ihbar *0.5, 'leak': self.gBar.leakbar * 0.5, },
|
||||
# 'apic': {sodiumch: self.gBar.nabar * 0.25, 'klt': self.gBar.kltbar * 0.25, 'kht': self.gBar.khtbar * 0.25,
|
||||
# 'ihvcn': self.gBar.ihbar *0.25, 'leak': self.gBar.leakbar * 0.25, },
|
||||
# }
|
||||
# self.irange = np.arange(-1.5, 2.1, 0.25 )
|
||||
# self.distMap = {'dend': {'klt': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'kht': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# sodiumch: {'gradient': 'linear', 'gminf': 0., 'lambda': 100.}}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
# 'dendrite': {'klt': {'gradient': 'linear', 'gminf': 0., 'lambda': 20.},
|
||||
# 'kht': {'gradient': 'linear', 'gminf': 0., 'lambda': 20.},
|
||||
# sodiumch: {'gradient': 'linear', 'gminf': 0., 'lambda': 20.}}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
# 'apic': {'klt': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# 'kht': {'gradient': 'linear', 'gminf': 0., 'lambda': 100.},
|
||||
# sodiumch: {'gradient': 'exp', 'gminf': 0., 'lambda': 200.}}, # gradients are: flat, linear, exponential
|
||||
# }
|
||||
# else:
|
||||
# raise ValueError('model type %s is not implemented' % modelType)
|
||||
# self.check_temperature()
|
||||
|
||||
def adjust_na_chans(self, soma, sf=1.0, gbar=1000.0):
|
||||
"""
|
||||
adjust the sodium channel conductance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
soma : neuron section object
|
||||
A soma object whose sodium channel complement will have its
|
||||
conductances adjusted depending on the channel type
|
||||
|
||||
gbar : float (default: 1000.)
|
||||
The maximal conductance for the sodium channel
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing :
|
||||
|
||||
"""
|
||||
|
||||
if self.status["ttx"]:
|
||||
gnabar = 0.0
|
||||
else:
|
||||
gnabar = nstomho(gbar, self.somaarea) * sf
|
||||
nach = self.status["na"]
|
||||
if nach == "jsrna":
|
||||
soma().jsrna.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if self.debug:
|
||||
print("jsrna gbar: ", soma().jsrna.gbar)
|
||||
elif nach == "nav11":
|
||||
soma().nav11.gbar = gnabar
|
||||
soma.ena = 50 # self.e_na
|
||||
# print('gnabar: ', soma().nav11.gbar, ' vs: 0.0192307692308')
|
||||
soma().nav11.vsna = 4.3
|
||||
if self.debug:
|
||||
print("bushy using inva11")
|
||||
if nach == "nacncoop":
|
||||
soma().nacncoop.gbar = gnabar
|
||||
soma().nacncoop.KJ = 2000.0
|
||||
soma().nacncoop.p = 0.25
|
||||
somae().nacncoop.vsna = 0.0
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("nacncoop gbar: ", soma().nacncoop.gbar)
|
||||
elif nach in ["na", "nacn"]:
|
||||
soma().na.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
# soma().na.vsna = 0.
|
||||
if self.debug:
|
||||
print("na gbar: ", soma().na.gbar)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Sodium channel %s is not recognized for Bushy cells", nach
|
||||
)
|
||||
|
||||
def add_axon(self):
|
||||
"""
|
||||
Add a default axon from the generic cell class to the bushy cell (see cell class).
|
||||
"""
|
||||
Cell.add_axon(self, self.c_m, self.R_a, self.axonsf)
|
||||
|
||||
def add_pumps(self):
|
||||
"""
|
||||
Insert mechanisms for potassium ion management, sodium ion management, and a
|
||||
sodium-potassium pump at the soma.
|
||||
"""
|
||||
soma = self.soma
|
||||
soma.insert("k_conc")
|
||||
|
||||
ki0_k_ion = 140
|
||||
soma().ki = ki0_k_ion
|
||||
soma().ki0_k_conc = ki0_k_ion
|
||||
soma().beta_k_conc = 0.075
|
||||
|
||||
soma.insert("na_conc")
|
||||
nai0_na_ion = 5
|
||||
soma().nai = nai0_na_ion
|
||||
soma().nai0_na_conc = nai0_na_ion
|
||||
soma().beta_na_conc = 0.075
|
||||
|
||||
soma.insert("nakpump")
|
||||
soma().nakpump.inakmax = 8
|
||||
soma().nao = 145
|
||||
soma().ko = 5
|
||||
soma().nakpump.Nai_inf = 5
|
||||
soma().nakpump.Ki_inf = 140
|
||||
soma().nakpump.ATPi = 5
|
||||
self.status["pumps"] = True
|
||||
|
||||
def add_dendrites(self):
|
||||
"""
|
||||
Add a simple dendrite to the bushy cell.
|
||||
"""
|
||||
if self.debug:
|
||||
print("Adding dendrite to Bushy model")
|
||||
section = h.Section
|
||||
primarydendrite = section(cell=self.soma)
|
||||
primarydendrite.connect(self.soma)
|
||||
primarydendrite.nseg = 10
|
||||
primarydendrite.L = 100.0
|
||||
primarydendrite.diam = 2.5
|
||||
primarydendrite.insert("klt")
|
||||
primarydendrite.insert("ihvcn")
|
||||
primarydendrite().klt.gbar = self.soma().klt.gbar / 2.0
|
||||
primarydendrite().ihvcn.gbar = self.soma().ihvcn.gbar / 2.0
|
||||
|
||||
primarydendrite.cm = self.c_m
|
||||
primarydendrite.Ra = self.R_a
|
||||
nsecd = range(0, 5)
|
||||
secondarydendrite = []
|
||||
for ibd in nsecd:
|
||||
secondarydendrite.append(section(cell=self.soma))
|
||||
for ibd in nsecd:
|
||||
secondarydendrite[ibd].connect(primarydendrite)
|
||||
secondarydendrite[ibd].diam = 1.0
|
||||
secondarydendrite[ibd].L = 15.0
|
||||
secondarydendrite[ibd].cm = self.c_m
|
||||
secondarydendrite[ibd].Ra = self.R_a
|
||||
self.primarydendrite = primarydendrite
|
||||
self.secondarydendrite = secondarydendrite
|
||||
self.status["dendrite"] = True
|
||||
if self.debug:
|
||||
print("Bushy: added dendrites")
|
||||
h.topology()
|
||||
self.add_section(maindend, "primarydendrite")
|
||||
self.add_section(secdend, "secondarydendrite")
|
||||
447
cnmodel/cells/cartwheel.py
Normal file
447
cnmodel/cells/cartwheel.py
Normal file
@@ -0,0 +1,447 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
from neuron import h
|
||||
|
||||
from .cell import Cell
|
||||
from .. import data
|
||||
from .. import synapses
|
||||
from ..util import Params
|
||||
from ..util import nstomho
|
||||
|
||||
__all__ = ["Cartwheel", "CartwheelDefault"]
|
||||
|
||||
|
||||
class Cartwheel(Cell):
|
||||
|
||||
type = "cartwheel"
|
||||
|
||||
@classmethod
|
||||
def create(cls, model="CW", **kwds):
|
||||
if model == "CW":
|
||||
return CartwheelDefault(**kwds)
|
||||
else:
|
||||
raise ValueError("Carthweel model is unknown", model)
|
||||
|
||||
def make_psd(self, terminal, psd_type, **kwds):
|
||||
"""
|
||||
Connect a presynaptic terminal to one post section at the specified location, with the fraction
|
||||
of the "standard" conductance determined by gbar.
|
||||
The default condition is to try to pass the default unit test (loc=0.5)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
terminal : Presynaptic terminal (NEURON object)
|
||||
|
||||
psd_type : either simple or multisite PSD for bushy cell
|
||||
|
||||
kwds: dict of options. Two are currently handled:
|
||||
postsize : expect a list consisting of [sectionno, location (float)]
|
||||
AMPAScale : float to scale the ampa currents
|
||||
|
||||
"""
|
||||
self.pre_sec = terminal.section
|
||||
pre_cell = terminal.cell
|
||||
post_sec = self.soma
|
||||
|
||||
if psd_type == "simple":
|
||||
if terminal.cell.type in [
|
||||
"sgc",
|
||||
"dstellate",
|
||||
"tuberculoventral",
|
||||
"cartwheel",
|
||||
]:
|
||||
weight = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="weight",
|
||||
)
|
||||
tau1 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau1",
|
||||
)
|
||||
tau2 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau2",
|
||||
)
|
||||
erev = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="erev",
|
||||
)
|
||||
return self.make_exp2_psd(
|
||||
post_sec,
|
||||
terminal,
|
||||
weight=weight,
|
||||
loc=loc,
|
||||
tau1=tau1,
|
||||
tau2=tau2,
|
||||
erev=erev,
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make simple PSD for %s => %s"
|
||||
% (terminal.cell.type, self.type)
|
||||
)
|
||||
|
||||
else:
|
||||
raise ValueError(
|
||||
"Unsupported psd type %s for cartwheel cell (inputs not implemented yet)"
|
||||
% psd_type
|
||||
)
|
||||
|
||||
def make_terminal(self, post_cell, term_type, **kwds):
|
||||
if term_type == "simple":
|
||||
return synapses.SimpleTerminal(self.soma, post_cell, **kwds)
|
||||
elif term_type == "multisite":
|
||||
if post_cell.type in ["tuberculoventral", "pyramidal"]:
|
||||
nzones = data.get(
|
||||
"cartwheel_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="n_rsites",
|
||||
)
|
||||
delay = data.get(
|
||||
"cartwheel_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="delay",
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"No knowledge as to how to connect cartwheel cell to cell type %s"
|
||||
% type(post_cell)
|
||||
)
|
||||
pre_sec = self.soma
|
||||
return synapses.StochasticTerminal(
|
||||
pre_sec,
|
||||
post_cell,
|
||||
nzones=nzones,
|
||||
spike_source=self.spike_source,
|
||||
delay=delay,
|
||||
**kwds
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported terminal type %s" % term_type)
|
||||
|
||||
|
||||
class CartwheelDefault(Cartwheel, Cell):
|
||||
"""
|
||||
DCN cartwheel cell model.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
ttx=False,
|
||||
nach=None,
|
||||
species="mouse",
|
||||
modelType=None,
|
||||
debug=False,
|
||||
):
|
||||
"""
|
||||
Create cartwheel cell model, based on a Purkinje cell model from Raman.
|
||||
There are no variations available for this model.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
Name of a .hoc file representing the morphology. This file is used to constructe
|
||||
an electrotonic (cable) model.
|
||||
If None (default), then a "point" (really, single cylinder) model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels is inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: None)
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanism
|
||||
by that name must exist. The default is naRsg, a resurgent sodium channel model.
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
This flag duplicates the effects of tetrodotoxin in the model. Currently, the flag is not implemented.
|
||||
|
||||
species: string (default 'rat')
|
||||
species defines the pattern of ion channel densities that will be inserted, according to
|
||||
prior measurements in various species. Note that
|
||||
if a decorator function is specified, this argument is ignored as the decorator will
|
||||
specify the channel density.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the subtype of the cell model that will be used.
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point (single cylinder) models.
|
||||
Only type "I" is recognized for the cartwheel cell model.
|
||||
|
||||
debug: boolean (default: False)
|
||||
When True, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
super(CartwheelDefault, self).__init__()
|
||||
if modelType == None:
|
||||
modelType = "I"
|
||||
if nach == None:
|
||||
nach = "naRsg"
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "Cartwheel",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": None,
|
||||
}
|
||||
|
||||
self.i_test_range = {"pulse": (-0.2, 0.2, 0.02)}
|
||||
# self.spike_threshold = 0
|
||||
self.vrange = [-75.0, -52.0] # set a default vrange for searching for rmp
|
||||
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
soma = h.Section(
|
||||
name="Cartwheel_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
# cm = 1
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
# v_potassium = -80 # potassium reversal potential
|
||||
# v_sodium = 50 # sodium reversal potential
|
||||
|
||||
self.mechanisms = [
|
||||
"naRsg",
|
||||
"bkpkj",
|
||||
"hpkj",
|
||||
"kpkj",
|
||||
"kpkj2",
|
||||
"kpkjslow",
|
||||
"kpksk",
|
||||
"lkpkj",
|
||||
"cap",
|
||||
]
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.soma.insert("cadiff")
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
|
||||
if debug:
|
||||
print(
|
||||
"<< Cartwheel: Modified version of Raman Purkinje cell model created >>"
|
||||
)
|
||||
|
||||
def get_cellpars(self, dataset, species="guineapig", celltype="II"):
|
||||
somaDia = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_Dia"
|
||||
)
|
||||
chtype = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_na_type"
|
||||
)
|
||||
pcabar = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_pcabar"
|
||||
)
|
||||
pars = Params(soma_Dia=somaDia, soma_natype=chtype, soma_pcabar=pcabar)
|
||||
for g in [
|
||||
"soma_narsg_gbar",
|
||||
"soma_kpkj_gbar",
|
||||
"soma_kpkj2_gbar",
|
||||
"soma_kpkjslow_gbar",
|
||||
"soma_kpksk_gbar",
|
||||
"soma_lkpkj_gbar",
|
||||
"soma_bkpkj_gbar",
|
||||
"soma_hpkj_gbar",
|
||||
"soma_hpkj_eh",
|
||||
"soma_lkpkj_e",
|
||||
"soma_e_k",
|
||||
"soma_e_na",
|
||||
"soma_e_ca",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, cell_type=celltype, field=g)
|
||||
)
|
||||
return pars
|
||||
|
||||
def species_scaling(self, silent=True, species="mouse", modelType="I"):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
This scaling should be used ONLY for point models, as no other compartments
|
||||
are scaled.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'rat')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be one of mouse, cat, guineapig
|
||||
|
||||
modelType: string (default: 'I')
|
||||
definition of model type from RM03 models, type II or type II-I
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
|
||||
Note
|
||||
----
|
||||
For the cartwheel cell model, there is only a single scaling recognized.
|
||||
"""
|
||||
if species is not "mouse":
|
||||
raise ValueError('Cartwheel species: only "mouse" is recognized')
|
||||
if modelType is not "I":
|
||||
raise ValueError('Cartwheel modelType: only "I" is recognized')
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
|
||||
pars = self.get_cellpars("CW_channels", species=species, celltype="cartwheel")
|
||||
self.set_soma_size_from_Diam(pars.soma_Dia)
|
||||
self.soma().bkpkj.gbar = nstomho(pars.soma_bkpkj_gbar, self.somaarea)
|
||||
self.soma().hpkj.gbar = nstomho(pars.soma_hpkj_gbar, self.somaarea)
|
||||
self.soma().kpkj.gbar = nstomho(pars.soma_kpkj_gbar, self.somaarea)
|
||||
self.soma().kpkj2.gbar = nstomho(pars.soma_kpkj2_gbar, self.somaarea)
|
||||
self.soma().kpkjslow.gbar = nstomho(pars.soma_kpkjslow_gbar, self.somaarea)
|
||||
self.soma().kpksk.gbar = nstomho(pars.soma_kpksk_gbar, self.somaarea)
|
||||
self.soma().lkpkj.gbar = nstomho(pars.soma_lkpkj_gbar, self.somaarea)
|
||||
self.soma().naRsg.gbar = nstomho(pars.soma_narsg_gbar, self.somaarea)
|
||||
self.soma().cap.pcabar = pars.soma_pcabar
|
||||
self.soma().ena = pars.soma_e_na # 50
|
||||
self.soma().ek = pars.soma_e_k # -80
|
||||
self.soma().lkpkj.e = pars.soma_lkpkj_e # -65
|
||||
self.soma().hpkj.eh = pars.soma_hpkj_eh # -43
|
||||
self.soma().eca = pars.soma_e_ca # 50
|
||||
|
||||
self.status["na"] = pars.soma_natype
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
self.check_temperature()
|
||||
if not silent:
|
||||
print("set cell as: ", species)
|
||||
print(" with Vm rest = %f" % self.vm0)
|
||||
|
||||
# print 'set up'
|
||||
|
||||
def i_currents(self, V):
|
||||
"""
|
||||
For the steady-state case, return the total current at voltage V
|
||||
Used to find the zero current point.
|
||||
Overrides i_currents in cells.py, because this model uses conductances
|
||||
that are not specified in the default cell mode.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
V : float, mV (no default)
|
||||
Voltage at which the current for each conductance is computed.
|
||||
|
||||
Returns
|
||||
-------
|
||||
I : float, nA
|
||||
The sum of the currents at steady-state for all of the conductances.
|
||||
"""
|
||||
for part in self.all_sections.keys():
|
||||
for sec in self.all_sections[part]:
|
||||
sec.v = V
|
||||
h.celsius = self.status["temperature"]
|
||||
h.finitialize()
|
||||
self.ix = {}
|
||||
|
||||
if "naRsg" in self.mechanisms:
|
||||
self.ix["naRsg"] = self.soma().naRsg.gna * (V - self.soma().ena)
|
||||
if "cap" in self.mechanisms:
|
||||
a = self.soma().cap.pcabar * self.soma().cap.minf
|
||||
self.ix["cap"] = a * self.ghk(V, self.soma().cao, self.soma().cai, 2)
|
||||
if "kpkj" in self.mechanisms:
|
||||
self.ix["kpkj"] = self.soma().kpkj.gk * (V - self.soma().ek)
|
||||
if "kpkj2" in self.mechanisms:
|
||||
self.ix["kpkj2"] = self.soma().kpkj2.gk * (V - self.soma().ek)
|
||||
if "kpkjslow" in self.mechanisms:
|
||||
self.ix["kpkjslow"] = self.soma().kpkjslow.gk * (V - self.soma().ek)
|
||||
if "kpksk" in self.mechanisms:
|
||||
self.ix["kpksk"] = self.soma().kpksk.gk * (V - self.soma().ek)
|
||||
if "bkpkj" in self.mechanisms:
|
||||
self.ix["bkpkj"] = self.soma().bkpkj.gbkpkj * (V - self.soma().ek)
|
||||
if "hpkj" in self.mechanisms:
|
||||
self.ix["hpkj"] = self.soma().hpkj.gh * (V - self.soma().hpkj.eh)
|
||||
# leak
|
||||
if "lkpkj" in self.mechanisms:
|
||||
self.ix["lkpkj"] = self.soma().lkpkj.gbar * (V - self.soma().lkpkj.e)
|
||||
return np.sum([self.ix[i] for i in self.ix])
|
||||
|
||||
def ghk(self, v, ci, co, z):
|
||||
"""
|
||||
GHK flux equation, used to calculate current density through calcium channels
|
||||
rather than standard Nernst equation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
v : float, mV
|
||||
voltage for GHK calculation
|
||||
ci : float, mM
|
||||
internal ion concentration
|
||||
co : float, mM
|
||||
external ion concentraion
|
||||
z : float, no units
|
||||
valence
|
||||
|
||||
Returns
|
||||
-------
|
||||
flux : A/m^2
|
||||
|
||||
"""
|
||||
F = 9.6485e4 # (coul)
|
||||
R = 8.3145 # (joule/degC)
|
||||
T = h.celsius + 273.19 # Kelvin
|
||||
E = (1e-3) * v # convert mV to V
|
||||
Ci = ci + (self.soma().cap.monovalPerm) * (
|
||||
self.soma().cap.monovalConc
|
||||
) # : Monovalent permeability
|
||||
if (
|
||||
np.fabs(1 - np.exp(-z * (F * E) / (R * T))) < 1e-6
|
||||
): # denominator is small -> Taylor series
|
||||
ghk = (
|
||||
(1e-6)
|
||||
* z
|
||||
* F
|
||||
* (Ci - co * np.exp(-z * (F * E) / (R * T)))
|
||||
* (1 - (z * (F * E) / (R * T)))
|
||||
)
|
||||
else:
|
||||
ghk = (
|
||||
(1e-6)
|
||||
* z ** 2.0
|
||||
* (E * F ** 2.0)
|
||||
/ (R * T)
|
||||
* (Ci - co * np.exp(-z * (F * E) / (R * T)))
|
||||
/ (1 - np.exp(-z * (F * E) / (R * T)))
|
||||
)
|
||||
return ghk
|
||||
1200
cnmodel/cells/cell.py
Normal file
1200
cnmodel/cells/cell.py
Normal file
File diff suppressed because it is too large
Load Diff
897
cnmodel/cells/dstellate.py
Normal file
897
cnmodel/cells/dstellate.py
Normal file
@@ -0,0 +1,897 @@
|
||||
from __future__ import print_function
|
||||
from neuron import h
|
||||
from ..util import nstomho
|
||||
from .cell import Cell
|
||||
from ..util import Params
|
||||
from .. import synapses
|
||||
from .. import data
|
||||
|
||||
__all__ = ["DStellate", "DStellateRothman", "DStellateEager"]
|
||||
|
||||
|
||||
class DStellate(Cell):
|
||||
|
||||
type = "dstellate"
|
||||
|
||||
@classmethod
|
||||
def create(cls, model="RM03", **kwds):
|
||||
if model == "RM03":
|
||||
return DStellateRothman(**kwds)
|
||||
elif model == "Eager":
|
||||
return DStellateEager(**kwds)
|
||||
elif model == "dummy":
|
||||
return DummyDStellate(**kwds)
|
||||
else:
|
||||
raise ValueError("DStellate type %s is unknown", type)
|
||||
|
||||
def __init__(self):
|
||||
Cell.__init__(self)
|
||||
self.spike_source = (
|
||||
None
|
||||
) # used by DummyDStellate to connect VecStim to terminal
|
||||
|
||||
def make_psd(self, terminal, psd_type, **kwds):
|
||||
"""
|
||||
Connect a presynaptic terminal to one post section at the specified location, with the fraction
|
||||
of the "standard" conductance determined by gbar.
|
||||
The default condition is designed to pass the unit test (loc=0.5)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
terminal : Presynaptic terminal (NEURON object)
|
||||
|
||||
psd_type : either simple or multisite PSD for bushy cell
|
||||
|
||||
kwds: dictionary of options.
|
||||
Two are currently handled:
|
||||
postsize : expect a list consisting of [sectionno, location (float)]
|
||||
AMPAScale : float to scale the ampa currents
|
||||
|
||||
"""
|
||||
if (
|
||||
"postsite" in kwds
|
||||
): # use a defined location instead of the default (soma(0.5)
|
||||
postsite = kwds["postsite"]
|
||||
loc = postsite[1] # where on the section?
|
||||
uname = (
|
||||
"sections[%d]" % postsite[0]
|
||||
) # make a name to look up the neuron section object
|
||||
post_sec = self.hr.get_section(uname) # Tell us where to put the synapse.
|
||||
else:
|
||||
loc = 0.5
|
||||
post_sec = self.soma
|
||||
|
||||
if psd_type == "simple":
|
||||
if terminal.cell.type in ["sgc", "dstellate", "tuberculoventral"]:
|
||||
weight = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="weight",
|
||||
)
|
||||
tau1 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau1",
|
||||
)
|
||||
tau2 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau2",
|
||||
)
|
||||
erev = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="erev",
|
||||
)
|
||||
return self.make_exp2_psd(
|
||||
post_sec,
|
||||
terminal,
|
||||
weight=weight,
|
||||
loc=loc,
|
||||
tau1=tau1,
|
||||
tau2=tau2,
|
||||
erev=erev,
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make simple PSD for %s => %s"
|
||||
% (terminal.cell.type, self.type)
|
||||
)
|
||||
|
||||
elif psd_type == "multisite":
|
||||
if terminal.cell.type == "sgc":
|
||||
# Max conductances for the glu mechanisms are calibrated by
|
||||
# running `synapses/tests/test_psd.py`. The test should fail
|
||||
# if these values are incorrect
|
||||
self.AMPAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="AMPAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.NMDAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="NMDAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.Pr = data.get(
|
||||
"sgc_synapse", species=self.species, post_type=self.type, field="Pr"
|
||||
)
|
||||
# adjust gmax to correct for initial Pr
|
||||
self.AMPAR_gmax = self.AMPAR_gmax / self.Pr
|
||||
self.NMDAR_gmax = self.NMDAR_gmax / self.Pr
|
||||
# old values:
|
||||
# AMPA_gmax = 0.22479596944138733*1e3 # factor of 1e3 scales to pS (.mod mechanisms) from nS.
|
||||
# NMDA_gmax = 0.12281291946623739*1e3
|
||||
if "AMPAScale" in kwds:
|
||||
self.AMPAR_gmax = (
|
||||
self.AMPAR_gmax * kwds["AMPAScale"]
|
||||
) # allow scaling of AMPA conductances
|
||||
if "NMDAScale" in kwds:
|
||||
self.NMDAR_gmax = self.NMDAR_gmax * kwds["NMDAScale"]
|
||||
return self.make_glu_psd(
|
||||
post_sec, terminal, self.AMPAR_gmax, self.NMDAR_gmax, loc=loc
|
||||
)
|
||||
|
||||
elif terminal.cell.type == "dstellate":
|
||||
# Get GLY kinetic constants from database
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyfast", loc=loc)
|
||||
elif terminal.cell.type == "tuberculoventral":
|
||||
# Get GLY kinetic constants from database
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyfast", loc=loc)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make PSD for %s => %s" % (terminal.cell.type, self.type)
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported psd type %s" % psd_type)
|
||||
|
||||
def make_terminal(self, post_cell, term_type, **kwds):
|
||||
if term_type == "simple":
|
||||
return synapses.SimpleTerminal(
|
||||
self.soma, post_cell, spike_source=self.spike_source, **kwds
|
||||
)
|
||||
elif term_type == "multisite":
|
||||
if post_cell.type in [
|
||||
"dstellate",
|
||||
"tuberculoventral",
|
||||
"pyramidal",
|
||||
"bushy",
|
||||
"tstellate",
|
||||
]:
|
||||
nzones = data.get(
|
||||
"dstellate_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="n_rsites",
|
||||
)
|
||||
delay = data.get(
|
||||
"dstellate_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="delay",
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"No knowledge as to how to connect D stellate cell to cell type %s"
|
||||
% type(post_cell)
|
||||
)
|
||||
pre_sec = self.soma
|
||||
return synapses.StochasticTerminal(
|
||||
pre_sec,
|
||||
post_cell,
|
||||
nzones=nzones,
|
||||
spike_source=self.spike_source,
|
||||
delay=delay,
|
||||
**kwds
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported terminal type %s" % term_type)
|
||||
|
||||
|
||||
class DStellateRothman(DStellate):
|
||||
"""
|
||||
VCN D-stellate model:
|
||||
as a type I-II from Rothman and Manis, 2003
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach=None,
|
||||
ttx=False,
|
||||
species="guineapig",
|
||||
modelType=None,
|
||||
modelName=None,
|
||||
debug=False,
|
||||
):
|
||||
"""
|
||||
initialize a radial stellate (D-stellate) cell, using the default parameters for guinea pig from
|
||||
R&M2003, as a type I-II cell.
|
||||
Modifications to the cell can be made by calling methods below. These include:
|
||||
|
||||
* changing the sodium channel
|
||||
* Changing "species" to mouse or cat (scales conductances)
|
||||
* Shifting model type
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
Name of a .hoc file representing the morphology. This file is used to constructe
|
||||
an electrotonic (cable) model.
|
||||
If None (default), then a "point" (really, single cylinder) model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels is inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: None)
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanism
|
||||
by that name must exist. A value of None will set the channel to a default for the model (nacn).
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
This flag duplicates the effects of tetrodotoxin in the model. Currently, the flag is not implemented.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the pattern of ion channel densities that will be inserted, according to
|
||||
prior measurements in various species. Note that
|
||||
if a decorator function is specified, this argument is ignored as the decorator will
|
||||
specify the channel density.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the subtype of the cell model that will be used (e.g., "II", "II-I", etc).
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point (single cylinder) models.
|
||||
|
||||
debug: boolean (default: False)
|
||||
When True, there will be multiple printouts of progress and parameters.
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
|
||||
super(DStellateRothman, self).__init__()
|
||||
if modelType == None:
|
||||
modelType = "I-II"
|
||||
if species == "guineapig":
|
||||
modelName = "RM03"
|
||||
temp = 22.0
|
||||
if nach == None:
|
||||
nach = "nacn"
|
||||
if species == "mouse":
|
||||
temp = 34.0
|
||||
if modelName is None:
|
||||
modelName = "XM13"
|
||||
if nach is None:
|
||||
nach = "na"
|
||||
self.debug = debug
|
||||
# if modelType == None: # allow us to pass None to get the default
|
||||
# modelType = 'I-II'
|
||||
# if nach == None:
|
||||
# nach = 'na'
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"modelName": modelName,
|
||||
"ttx": ttx,
|
||||
"name": "DStellate",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": None,
|
||||
}
|
||||
self.i_test_range = {
|
||||
"pulse": [(-0.3, 0.3, 0.03), (-0.05, 0.0, 0.005)]
|
||||
} # set range for ic command test
|
||||
self.vrange = [-75.0, -55.0]
|
||||
self.spike_threshold = (
|
||||
-40.0
|
||||
) # matches threshold in released CNModel (set in base cell class)
|
||||
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
soma = h.Section(
|
||||
name="DStellate_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
self.mechanisms = ["klt", "kht", "ihvcn", "leak", nach]
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.soma.ena = self.e_na
|
||||
self.soma.ek = self.e_k
|
||||
self.soma().leak.erev = self.e_leak
|
||||
self.c_m = 0.9
|
||||
self.set_soma_size_from_Cm(12.0)
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
|
||||
if self.debug:
|
||||
print("<< D-stellate: JSR Stellate Type I-II cell model created >>")
|
||||
|
||||
def get_cellpars(self, dataset, species="guineapig", modelType="I-II"):
|
||||
cellcap = data.get(
|
||||
dataset, species=species, model_type=modelType, field="soma_Cap"
|
||||
)
|
||||
chtype = data.get(
|
||||
dataset, species=species, model_type=modelType, field="na_type"
|
||||
)
|
||||
pars = Params(cap=cellcap, natype=chtype)
|
||||
# pars.show()
|
||||
|
||||
if self.status["modelName"] == "RM03":
|
||||
for g in [
|
||||
"%s_gbar" % pars.natype,
|
||||
"kht_gbar",
|
||||
"klt_gbar",
|
||||
"ka_gbar",
|
||||
"ih_gbar",
|
||||
"leak_gbar",
|
||||
"leak_erev",
|
||||
"ih_eh",
|
||||
"e_k",
|
||||
"e_na",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, model_type=modelType, field=g)
|
||||
)
|
||||
if self.status["modelName"] == "XM13":
|
||||
for g in [
|
||||
"%s_gbar" % pars.natype,
|
||||
"kht_gbar",
|
||||
"klt_gbar",
|
||||
"ka_gbar",
|
||||
"ihvcn_gbar",
|
||||
"leak_gbar",
|
||||
"leak_erev",
|
||||
"ih_eh",
|
||||
"e_k",
|
||||
"e_na",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, model_type=modelType, field=g)
|
||||
)
|
||||
if self.status["modelName"] == "mGBC":
|
||||
for g in [
|
||||
"%s_gbar" % pars.natype,
|
||||
"kht_gbar",
|
||||
"klt_gbar",
|
||||
"ka_gbar",
|
||||
"ihvcn_gbar",
|
||||
"leak_gbar",
|
||||
"leak_erev",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, model_type=modelType, field=g)
|
||||
)
|
||||
return pars
|
||||
|
||||
def species_scaling(self, species="guineapig", modelType="I-II", silent=True):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
A string specifying the species used for scaling. Recognized values are
|
||||
'mouse', 'guineapig', and 'cat' (cat is just a larger version of the guineapig)
|
||||
|
||||
modelType : string (default: 'I-II')
|
||||
A string specifying the version of the model to use.
|
||||
Current choices are 'I-II' (others need to be implemented)
|
||||
|
||||
silent : boolean (default: True)
|
||||
Flag for printing debugging information.
|
||||
|
||||
"""
|
||||
soma = self.soma
|
||||
celltype = modelType
|
||||
if species == "mouse":
|
||||
# use conductance levels from Cao et al., J. Neurophys., 2007.
|
||||
dataset = "XM13_channels"
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
self.c_m = 0.9
|
||||
pars = self.get_cellpars(dataset, species=species, modelType=modelType)
|
||||
self.set_soma_size_from_Cm(pars.cap)
|
||||
self.status["na"] = pars.natype
|
||||
# pars.show()
|
||||
self.adjust_na_chans(soma, gbar=pars.na_gbar, sf=1.0)
|
||||
soma().kht.gbar = nstomho(pars.kht_gbar, self.somaarea)
|
||||
soma().klt.gbar = nstomho(pars.klt_gbar, self.somaarea)
|
||||
# soma().ka.gbar = nstomho(pars.ka_gbar, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(pars.ihvcn_gbar, self.somaarea)
|
||||
soma().ihvcn.eh = pars.ih_eh # Rodrigues and Oertel, 2006
|
||||
soma().leak.gbar = nstomho(pars.leak_gbar, self.somaarea)
|
||||
soma().leak.erev = pars.leak_erev
|
||||
self.e_k = pars.e_k
|
||||
self.e_na = pars.e_na
|
||||
soma.ena = self.e_na
|
||||
soma.ek = self.e_k
|
||||
# soma().leak.erev = pars.leak_erev
|
||||
self.axonsf = 0.5
|
||||
|
||||
elif species == "guineapig": # values from R&M 2003, Type II-I
|
||||
dataset = "RM03_channels"
|
||||
self.c_m = 0.9
|
||||
self._valid_temperatures = (22.0, 38.0)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(22.0)
|
||||
sf = 1.0
|
||||
if (
|
||||
self.status["temperature"] == 38.0
|
||||
): # adjust for 2003 model conductance levels at 38
|
||||
sf = 3.03 # Q10 of 2, 22->38C. (p3106, R&M2003c)
|
||||
self.i_test_range = {"pulse": (-0.3, 0.3, 0.03)}
|
||||
self.vrange = [-75.0, -55.0]
|
||||
pars = self.get_cellpars(dataset, species=species, modelType=modelType)
|
||||
self.set_soma_size_from_Cm(pars.cap)
|
||||
self.status["na"] = pars.natype
|
||||
# pars.show()
|
||||
self.adjust_na_chans(soma, gbar=pars.nacn_gbar, sf=sf)
|
||||
soma().kht.gbar = nstomho(pars.kht_gbar, self.somaarea)
|
||||
soma().klt.gbar = nstomho(pars.klt_gbar, self.somaarea)
|
||||
# soma().ka.gbar = nstomho(pars.ka_gbar, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(pars.ih_gbar, self.somaarea)
|
||||
soma().leak.gbar = nstomho(pars.leak_gbar, self.somaarea)
|
||||
soma().leak.erev = pars.leak_erev
|
||||
self.axonsf = 0.5
|
||||
|
||||
else:
|
||||
raise ValueError(
|
||||
"Species %s or species-modelType %s is not recognized for D-Stellate cells"
|
||||
% (species, modelType)
|
||||
)
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
self.check_temperature()
|
||||
# self.cell_initialize(showinfo=False)
|
||||
if not silent:
|
||||
print("set cell as: ", species)
|
||||
print(" with Vm rest = %6.3f" % self.vm0)
|
||||
|
||||
def adjust_na_chans(self, soma, sf=1.0, gbar=1000.0):
|
||||
"""
|
||||
adjust the sodium channel conductance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
soma : soma object (no default)
|
||||
soma object whose sodium channel complement will have it's
|
||||
conductances adjusted depending on the channel type
|
||||
|
||||
gbar : float (default: 1000.)
|
||||
The conductance to be set for the sodium channel
|
||||
|
||||
debug : boolean (default: False)
|
||||
Flag for printing the conductance value and Na channel model
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
if self.status["ttx"]:
|
||||
gnabar = 0.0
|
||||
else:
|
||||
gnabar = nstomho(gbar, self.somaarea) * sf
|
||||
nach = self.status["na"]
|
||||
if nach == "jsrna":
|
||||
soma().jsrna.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if self.debug:
|
||||
print("jsrna gbar: ", soma().jsrna.gbar)
|
||||
elif nach == "nav11":
|
||||
soma().nav11.gbar = gnabar * 0.5
|
||||
soma.ena = self.e_na
|
||||
soma().nav11.vsna = 4.3
|
||||
if self.debug:
|
||||
print("bushy using inva11")
|
||||
print("nav11 gbar: ", soma().nav11.gbar)
|
||||
elif nach == "na":
|
||||
soma().na.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if self.debug:
|
||||
print("na gbar: ", soma().na.gbar)
|
||||
elif nach == "nacn":
|
||||
soma().nacn.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if self.debug:
|
||||
print("nacn gbar: ", soma().nacn.gbar)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Dstellate setting Na channels: channel %s not known" % nach
|
||||
)
|
||||
|
||||
def add_axon(self):
|
||||
"""
|
||||
Add a default axon from the generic cell class to the bushy cell (see cell class).
|
||||
"""
|
||||
Cell.add_axon(self, self.soma, self.somaarea, self.c_m, self.R_a, self.axonsf)
|
||||
|
||||
def add_dendrites(self):
|
||||
"""
|
||||
Add simple unbranched dendrites to basic Rothman Type I-II model.
|
||||
The dendrites have some kht and ih current
|
||||
"""
|
||||
cs = False # not implemented outside here - internal Cesium.
|
||||
nDend = range(4) # these will be simple, unbranced, N=4 dendrites
|
||||
dendrites = []
|
||||
for i in nDend:
|
||||
dendrites.append(h.Section(cell=self.soma))
|
||||
for i in nDend:
|
||||
dendrites[i].connect(self.soma)
|
||||
dendrites[i].L = 300 # length of the dendrite (not tapered)
|
||||
dendrites[i].diam = 1.25 # dendrite diameter
|
||||
dendrites[i].nseg = 21 # # segments in dendrites
|
||||
dendrites[i].Ra = 150 # ohm.cm
|
||||
dendrites[i].insert("kht")
|
||||
if cs is False:
|
||||
dendrites[i]().kht.gbar = 0.005 # a little Ht
|
||||
else:
|
||||
dendrites[i]().kht.gbar = 0.0
|
||||
dendrites[i].insert("leak") # leak
|
||||
dendrites[i]().leak.gbar = 0.0001
|
||||
dendrites[i].insert("ihvcn") # some H current
|
||||
dendrites[i]().ihvcn.gbar = 0.0 # 0.001
|
||||
dendrites[i]().ihvcn.eh = -43.0
|
||||
self.maindend = dendrites
|
||||
self.status["dendrites"] = True
|
||||
self.add_section(self.maindend, "maindend")
|
||||
|
||||
|
||||
class DummyDStellate(DStellate):
|
||||
""" DStellate class with no cell body; this cell only replays a predetermined
|
||||
spike train. Useful for testing, or replacing spike trains to determine
|
||||
the importance of spike structures within a network.
|
||||
"""
|
||||
|
||||
def __init__(self, cf=None, species="mouse"):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
cf : float (default: None)
|
||||
Required: the characteristic frequency for the DStellate
|
||||
Really just for reference.
|
||||
|
||||
"""
|
||||
|
||||
DStellate.__init__(self)
|
||||
self.vecstim = h.VecStim()
|
||||
|
||||
# this causes the terminal to receive events from the VecStim:
|
||||
self.spike_source = self.vecstim
|
||||
|
||||
# just an empty section for holding the terminal
|
||||
self.add_section(h.Section(), "soma")
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": None,
|
||||
"species": species,
|
||||
"modelType": "Dummy",
|
||||
"modelName": "DummyDStellate",
|
||||
"ttx": None,
|
||||
"name": "DummyDStellate",
|
||||
"morphology": None,
|
||||
"decorator": None,
|
||||
"temperature": None,
|
||||
}
|
||||
print("<< DStellate: Dummy DStellate Cell created >>")
|
||||
|
||||
def set_spiketrain(self, times):
|
||||
""" Set the times of spikes (in seconds) to be replayed by the cell.
|
||||
"""
|
||||
self._spiketrain = times
|
||||
self._stvec = h.Vector(times)
|
||||
self.vecstim.play(self._stvec)
|
||||
|
||||
|
||||
class DStellateEager(DStellate):
|
||||
"""
|
||||
This is a model of the VCN D-Stellate cells as proposed by
|
||||
Eager, M.A., Grayden, D.B., Burkitt, A.N., and Meffin, H.,
|
||||
"A neural circuit model of the ventral cochlear nucleus",
|
||||
Internet:
|
||||
http://citeseerx.ist.pus.edu/viewdoc/download?doi=10.1.79.9620.pdf&rep
|
||||
=rep&type=pdf
|
||||
also cited as:
|
||||
Proceedings of the 10th Australian International Conference on
|
||||
Speech Science and Technology, pp. 539-544, 2004.
|
||||
It is based on the Rothman and Manis (2003c) model,
|
||||
with small modifications.
|
||||
Their model includes dendrites and an axon, which are added in this version
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, nach="na", ttx=False, species="guineapig", modelType="I-II", debug=False
|
||||
):
|
||||
"""
|
||||
Initialize the VCN D-stellate model of Eager et al. Some model parameters may be modified.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nach : string (default: 'na')
|
||||
Set the sodium channel model. Choices are 'na', 'nav11', 'jsrna'
|
||||
|
||||
ttx : boolean (default: False)
|
||||
ttx sets the sodium channel conductance to 0
|
||||
|
||||
species : string (default: 'guineapig')
|
||||
species to use for conductance scaling
|
||||
|
||||
modelType : string (default: 'I-II')
|
||||
RM03 model type to use for conductances.
|
||||
|
||||
debug : boolean (default: False)
|
||||
Flag to use to enable print statements for debugging purposes.
|
||||
|
||||
"""
|
||||
super(DStellateEager, self).__init__()
|
||||
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "DStellateEager",
|
||||
}
|
||||
self.i_test_range = (-0.25, 0.25, 0.025) # set range for ic command test
|
||||
|
||||
soma = h.Section(name="DStellateEager_Soma_%x" % id(self)) # one compartment
|
||||
|
||||
soma.nseg = 1
|
||||
|
||||
if nach in ["nacn", "na"]:
|
||||
soma.insert("na")
|
||||
elif nach == "nav11":
|
||||
soma.insert("nav11")
|
||||
elif nach == "jsrna":
|
||||
soma.insert("jsrna")
|
||||
else:
|
||||
raise ValueError("Sodium channel %s in type 1 cell not known" % nach)
|
||||
self.debug = debug
|
||||
soma.insert("kht")
|
||||
soma.insert("klt")
|
||||
soma.insert("ihvcn")
|
||||
soma.insert("leak")
|
||||
soma.ek = self.e_k
|
||||
soma().leak.erev = self.e_leak
|
||||
self.mechanisms = ["kht", "klt", "ihvcn", "leak", nach]
|
||||
self.add_section(soma, "soma")
|
||||
self.species_scaling(
|
||||
silent=False, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
self.add_axon() # must follow species scaling so that area parameters are available
|
||||
self.add_dendrites() # similar for dendrites
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(soma)
|
||||
|
||||
if self.debug:
|
||||
print("<< D-stellateEager: Eager DStellate Type I-II cell model created >>")
|
||||
|
||||
def species_scaling(self, species="guineapig", modelType="I-II", silent=True):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
A string specifying the species used for scaling. Recognized values are
|
||||
'mouse', 'guineapig', and 'cat' (cat is just a larger version of the guineapig)
|
||||
|
||||
modelType : string (default: 'I-II')
|
||||
A string specifying the version of the model to use.
|
||||
Current choices are 'I-II' (others need to be implemented)
|
||||
|
||||
silent : boolean (default: True)
|
||||
Flag for printing debugging information.
|
||||
|
||||
"""
|
||||
soma = self.soma
|
||||
if species == "mouse" and modelType == "I-II":
|
||||
# use conductance levels from Cao et al., J. Neurophys., 2007.
|
||||
self.set_soma_size_from_Cm(25.0)
|
||||
self.adjust_na_chans(soma, gbar=800.0)
|
||||
soma().kht.gbar = nstomho(150.0, self.somaarea)
|
||||
soma().klt.gbar = nstomho(20.0, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(2.0, self.somaarea)
|
||||
soma().ihvcn.eh = -43 # Rodrigues and Oertel, 2006
|
||||
soma().leak.gbar = nstomho(2.0, self.somaarea)
|
||||
self.axonsf = 0.5
|
||||
elif (
|
||||
species == "guineapig" and modelType == "I-II"
|
||||
): # values from R&M 2003, Type II-I
|
||||
self.set_soma_size_from_Diam(25.0)
|
||||
self.adjust_na_chans(soma, gbar=1000.0 * 0.75)
|
||||
soma().kht.gbar = 0.02 # nstomho(150.0, self.somaarea)
|
||||
soma().klt.gbar = 0.005 # nstomho(20.0, self.somaarea)
|
||||
soma().ihvcn.gbar = 0.0002 # nstomho(2.0, self.somaarea)
|
||||
soma().leak.gbar = 0.0005 # nstomho(2.0, self.somaarea)
|
||||
self.axonsf = 1.0
|
||||
elif (
|
||||
species == "cat" and modelType == "I=II"
|
||||
): # a cat is a big guinea pig Type I
|
||||
self.set_soma_size_from_Cm(35.0)
|
||||
self.adjust_na_chans(soma)
|
||||
soma().kht.gbar = nstomho(150.0, self.somaarea)
|
||||
soma().klt.gbar = nstomho(20.0, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(2.0, self.somaarea)
|
||||
soma().leak.gbar = nstomho(2.0, self.somaarea)
|
||||
self.axonsf = 1.0
|
||||
else:
|
||||
raise ValueError(
|
||||
"Species %s or species-type %s is not recognized for D-StellateEager cells"
|
||||
% (species, type)
|
||||
)
|
||||
self.status["species"] = species
|
||||
self.status["type"] = modelType
|
||||
self.cell_initialize(showinfo=True)
|
||||
if not silent:
|
||||
print(" set cell as: ", species)
|
||||
print(" with Vm rest = %6.3f" % self.vm0)
|
||||
|
||||
def adjust_na_chans(self, soma, gbar=1000.0):
|
||||
"""
|
||||
adjust the sodium channel conductance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
soma : soma object (no default)
|
||||
soma object whose sodium channel complement will have it's
|
||||
conductances adjusted depending on the channel type
|
||||
|
||||
gbar : float (default: 1000.)
|
||||
The conductance to be set for the sodium channel
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
|
||||
if self.status["ttx"]:
|
||||
gnabar = 0.0
|
||||
else:
|
||||
gnabar = nstomho(gbar, self.somaarea)
|
||||
nach = self.status["na"]
|
||||
if nach == "jsrna":
|
||||
soma().jsrna.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if self.debug:
|
||||
print("using jsrna with gbar: ", soma().jsrna.gbar)
|
||||
elif nach == "nav11":
|
||||
soma().nav11.gbar = gnabar * 0.5
|
||||
soma.ena = self.e_na
|
||||
soma().nav11.vsna = 4.3
|
||||
if self.debug:
|
||||
print("using inva11 with gbar:", soma().na.gbar)
|
||||
print("nav11 gbar: ", soma().nav11.gbar)
|
||||
elif nach == "na":
|
||||
soma().na.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if self.debug:
|
||||
print("using na with gbar: ", soma().na.gbar)
|
||||
elif nach == "nach":
|
||||
soma().nach.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if self.debug:
|
||||
print(("uwing nacn with gbar: ", soma().nacn.gbar))
|
||||
else:
|
||||
raise ValueError(
|
||||
"DstellateEager setting Na channels: channel %s not known" % nach
|
||||
)
|
||||
# print soma().na.gbar
|
||||
|
||||
def add_axon(self):
|
||||
"""
|
||||
Adds an axon to the Eager. et al model
|
||||
Cell.add_axon(self, nodes=1, c_m=self.c_m, R_a=self.R_a, axonsf=self.axonsf, dia=3.0, len=70, seg=2)
|
||||
The Eager et al model just uses one cable, 70 microns long and 3 microns in dameter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
None
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
|
||||
naxons = 1
|
||||
axon = []
|
||||
for i in range(naxons):
|
||||
axon.append(h.Section(cell=self.soma))
|
||||
for i in range(naxons):
|
||||
axon[i].connect(self.soma)
|
||||
axon[i].L = 70
|
||||
axon[i].diam = 3.0
|
||||
axon[i].Ra = 500
|
||||
axon[i].cm = 0.9
|
||||
axon[i].nseg = 2
|
||||
axon[i].insert("kht")
|
||||
axon[i].insert("klt")
|
||||
axon[i].insert("ihvcn")
|
||||
axon[i].insert("leak")
|
||||
axon[i].insert("na")
|
||||
axon[i].ek = self.e_k
|
||||
axon[i].ena = self.e_na
|
||||
axon[i]().leak.erev = self.e_leak
|
||||
axon[i]().na.gbar = 0.5
|
||||
axon[i]().klt.gbar = 0.005
|
||||
axon[i]().kht.gbar = 0.02
|
||||
axon[i]().ihvcn.gbar = 0.0002
|
||||
axon[i]().leak.gbar = 0.0005
|
||||
self.status["axon"] = True
|
||||
self.add_section(axon, "axon")
|
||||
|
||||
def add_dendrites(self):
|
||||
"""
|
||||
Adds dendrites to the Eager model. The Eager model uses simple passive dendrites.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
None
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
|
||||
nDend = range(2) # these will be simple, unbranced, N=4 dendrites
|
||||
dendrites = []
|
||||
for i in nDend:
|
||||
dendrites.append(h.Section(cell=self.soma))
|
||||
for i in nDend:
|
||||
dendrites[i].connect(self.soma)
|
||||
dendrites[i].L = 1100 # length of the dendrite (not tapered)
|
||||
dendrites[i].diam = 3.5 # dendrite diameter
|
||||
dendrites[i].nseg = 5 # # segments in dendrites
|
||||
dendrites[i].Ra = 1500 # ohm.cm
|
||||
dendrites[i].insert("leak") # leak
|
||||
dendrites[i]().leak.gbar = 0.00025
|
||||
dendrites[i]().leak.erev = self.e_leak
|
||||
self.maindend = dendrites
|
||||
self.status["dendrites"] = True
|
||||
self.add_section(self.maindend, "maindend")
|
||||
47
cnmodel/cells/hh.py
Normal file
47
cnmodel/cells/hh.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from __future__ import print_function
|
||||
from neuron import h
|
||||
import neuron as nrn
|
||||
from ..util import nstomho
|
||||
|
||||
from .cell import Cell
|
||||
|
||||
__all__ = ["HH"]
|
||||
|
||||
|
||||
class HH(Cell):
|
||||
"""
|
||||
Standard Hodgkin-Huxley mechanisms from NEURON
|
||||
"""
|
||||
|
||||
def __init__(self, debug=False, message=None):
|
||||
super(HH, self).__init__()
|
||||
|
||||
soma = h.Section(
|
||||
name="HH_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
v_potassium = -80 # potassium reversal potential
|
||||
v_sodium = 50 # sodium reversal potential
|
||||
c_m = 1.0
|
||||
scalefactor = 1.0 # This determines the relative size of the cell
|
||||
rinsf = 1.0 # input resistance adjustment (also current...)
|
||||
totcap = 20.0 # scalefactor * 1.0 # cap in pF for cell
|
||||
effcap = totcap # sometimes we change capacitance - that's effcap
|
||||
somaarea = totcap * 1e-6 / c_m # pf -> uF, cm = 1uf/cm^2 nominal
|
||||
lstd = 1e4 * ((somaarea / 3.14159) ** 0.5) # convert from cm to um
|
||||
|
||||
soma.nseg = 1
|
||||
soma.diam = lstd
|
||||
soma.L = lstd
|
||||
|
||||
seg = soma
|
||||
seg.insert("hh")
|
||||
seg.insert("pas")
|
||||
if debug:
|
||||
if message is None:
|
||||
print("<< Standard HH model created >>")
|
||||
else:
|
||||
print(message)
|
||||
|
||||
self.add_section(soma, "soma")
|
||||
|
||||
self.vm0 = -67.536
|
||||
516
cnmodel/cells/msoprincipal.py
Normal file
516
cnmodel/cells/msoprincipal.py
Normal file
@@ -0,0 +1,516 @@
|
||||
from __future__ import print_function
|
||||
from neuron import h
|
||||
|
||||
from .cell import Cell
|
||||
|
||||
# from .. import synapses
|
||||
from ..util import nstomho
|
||||
from ..util import Params
|
||||
import numpy as np
|
||||
from .. import data
|
||||
|
||||
__all__ = ["MSO"]
|
||||
|
||||
|
||||
class MSO(Cell):
|
||||
|
||||
type = "mso"
|
||||
|
||||
@classmethod
|
||||
def create(cls, model="MSO-principal", **kwds):
|
||||
if model == "MSO-principal":
|
||||
return MSOPrincipal(**kwds)
|
||||
else:
|
||||
raise ValueError("MSO cell model %s is unknown", model)
|
||||
|
||||
def make_psd(self, terminal, psd_type, **kwds):
|
||||
"""
|
||||
Connect a presynaptic terminal to one post section at the specified location, with the fraction
|
||||
of the "standard" conductance determined by gbar.
|
||||
The default condition is designed to pass the unit test (loc=0.5)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
terminal : Presynaptic terminal (NEURON object)
|
||||
|
||||
psd_type : either simple or multisite PSD for MSO cell
|
||||
|
||||
kwds: dictionary of options.
|
||||
Two are currently handled:
|
||||
postsite : expect a list consisting of [sectionno, location (float)]
|
||||
AMPAScale : float to scale the ampa currents
|
||||
|
||||
"""
|
||||
if (
|
||||
"postsite" in kwds
|
||||
): # use a defined location instead of the default (soma(0.5)
|
||||
postsite = kwds["postsite"]
|
||||
loc = postsite[1] # where on the section?
|
||||
uname = (
|
||||
"sections[%d]" % postsite[0]
|
||||
) # make a name to look up the neuron section object
|
||||
post_sec = self.hr.get_section(uname) # Tell us where to put the synapse.
|
||||
else:
|
||||
loc = 0.5
|
||||
post_sec = self.soma
|
||||
|
||||
if psd_type == "simple":
|
||||
return self.make_exp2_psd(post_sec, terminal, loc=loc)
|
||||
elif psd_type == "multisite":
|
||||
if terminal.cell.type == "bushy":
|
||||
# Max conductances for the glu mechanisms are calibrated by
|
||||
# running `synapses/tests/test_psd.py`. The test should fail
|
||||
# if these values are incorrect
|
||||
self.AMPAR_gmax = (
|
||||
data.get(
|
||||
"bushy_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="AMPAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.NMDAR_gmax = (
|
||||
data.get(
|
||||
"bushy_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="NMDAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.Pr = data.get(
|
||||
"bushy_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="Pr",
|
||||
)
|
||||
# adjust gmax to correct for initial Pr
|
||||
self.AMPAR_gmax = self.AMPAR_gmax / self.Pr
|
||||
self.NMDAR_gmax = self.NMDAR_gmax / self.Pr
|
||||
if "AMPAScale" in kwds: # normally, this should not be done!
|
||||
self.AMPAR_gmax = (
|
||||
self.AMPAR_gmax * kwds["AMPAScale"]
|
||||
) # allow scaling of AMPA conductances
|
||||
if "NMDAScale" in kwds:
|
||||
self.NMDAR_gmax = self.NMDAR_gmax * kwds["NMDAScale"] # and NMDA...
|
||||
return self.make_glu_psd(
|
||||
post_sec, terminal, self.AMPAR_gmax, self.NMDAR_gmax, loc=loc
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make PSD for %s => %s" % (terminal.cell.type, self.type)
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported psd type %s" % psd_type)
|
||||
|
||||
|
||||
class MSOPrincipal(MSO):
|
||||
"""
|
||||
VCN MSO cell models.
|
||||
Using Rothman and Manis, 2003abc (Type II)
|
||||
MSO principal cell type
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach=None,
|
||||
ttx=False,
|
||||
species="guineapig",
|
||||
modelType=None,
|
||||
debug=False,
|
||||
temperature=None,
|
||||
):
|
||||
"""
|
||||
Create a MSO principal cell, using the default parameters for guinea pig from
|
||||
R&M2003, as a type II cell.
|
||||
Additional modifications to the cell can be made by calling methods below.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
Name of a .hoc file representing the morphology. This file is used to constructe
|
||||
an electrotonic (cable) model.
|
||||
If None (default), then a "point" (really, single cylinder) model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels is inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: None)
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanism
|
||||
by that name must exist. The default channel is set to 'nacn' (R&M03)
|
||||
|
||||
temperature : float (default: 22)
|
||||
temperature to run the cell at.
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
This flag duplicates the effects of tetrodotoxin in the model. Currently, the flag is not implemented.
|
||||
|
||||
temperature : float (default: None, sets to model default of 22)
|
||||
temperature (deg C) to run the cell at. Must be a valid temperature for the model.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the pattern of ion channel densities that will be inserted, according to
|
||||
prior measurements in various species. Note that
|
||||
if a decorator function is specified, this argument is ignored as the decorator will
|
||||
specify the channel density.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the subtype of the cell model that will be used (e.g., "II", "II-I", etc).
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point (single cylinder) models.
|
||||
|
||||
debug: boolean (default: False)
|
||||
When True, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
"""
|
||||
super(MSO, self).__init__()
|
||||
self.i_test_range = {
|
||||
"pulse": (-1, 1, 0.05)
|
||||
} # note that this gets reset with decorator according to channels
|
||||
# Changing the default values will cause the unit tests to fail!
|
||||
if modelType == None:
|
||||
modelType = "principal"
|
||||
if nach == None and species == "guineapig":
|
||||
nach = "na"
|
||||
if nach == None and species == "mouse":
|
||||
nach = "na"
|
||||
self.i_test_range = {"pulse": (-1, 1.2, 0.05)}
|
||||
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"hillock": False,
|
||||
"initialsegment": False,
|
||||
"myelinatedaxon": False,
|
||||
"unmyelinatedaxon": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "MSO",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": temperature,
|
||||
}
|
||||
|
||||
self.spike_threshold = -40
|
||||
self.vrange = [-70.0, -55.0] # set a default vrange for searching for rmp
|
||||
print("model type, species: ", modelType, species, nach)
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
print("<< MSO model: Creating point principal cell >>")
|
||||
soma = h.Section(
|
||||
name="MSO_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
print(
|
||||
"<< MSO principal cell model: Creating cell with morphology from %s >>"
|
||||
% morphology
|
||||
)
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
self.mechanisms = ["klt", "kht", "ihvcn", "leak", nach]
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.soma.ena = self.e_na
|
||||
self.soma.ek = self.e_k
|
||||
self.soma().ihvcn.eh = self.e_h
|
||||
self.soma().leak.erev = self.e_leak
|
||||
self.c_m = 0.9
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
|
||||
if debug:
|
||||
print(" << Created cell >>")
|
||||
|
||||
def get_cellpars(self, dataset, species="guineapig", celltype="principal"):
|
||||
cellcap = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_Cap"
|
||||
)
|
||||
chtype = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_na_type"
|
||||
)
|
||||
pars = Params(cap=cellcap, natype=chtype)
|
||||
for g in ["soma_kht_gbar", "soma_klt_gbar", "soma_ih_gbar", "soma_leak_gbar"]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, cell_type=celltype, field=g)
|
||||
)
|
||||
return pars
|
||||
|
||||
def species_scaling(self, species="guineapig", modelType="principal", silent=True):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
This scaling should be used ONLY for point models, as no other compartments
|
||||
are scaled.
|
||||
|
||||
This scaling routine also sets the temperature for the model to a default value. Some models
|
||||
can be run at multiple temperatures, and so a default from one of the temperatures is used.
|
||||
The calling cell.set_temperature(newtemp) will change the conductances and reinitialize
|
||||
the cell to the new temperature settings.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be one of mouse, cat, guineapig
|
||||
|
||||
modelType: string (default: 'principal')
|
||||
definition of model type from RM03 models, principal cell for mso
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
|
||||
"""
|
||||
# print '\nSpecies scaling: %s %s' % (species, type)
|
||||
knownspecies = ["guineapig"]
|
||||
|
||||
soma = self.soma
|
||||
if modelType == "principal":
|
||||
celltype = (
|
||||
"MSO-principal"
|
||||
) # There are other possiblities in the literature - this is just the main one
|
||||
else:
|
||||
raise ValueError("model type not recognized")
|
||||
|
||||
if species == "guineapig":
|
||||
print(
|
||||
" Setting conductances for guinea pig %s MSO cell, based on Rothman and Manis, 2003 bushy cell"
|
||||
% modelType
|
||||
)
|
||||
self._valid_temperatures = (22.0, 38.0)
|
||||
if self.status["temperature"] is None:
|
||||
self.status["temperature"] = 22.0
|
||||
self.i_test_range = {"pulse": (-0.4, 0.4, 0.02)}
|
||||
sf = 1.0
|
||||
if (
|
||||
self.status["temperature"] == 38.0
|
||||
): # adjust for 2003 model conductance levels at 38
|
||||
sf = 2 # Q10 of 2, 22->38C. (p3106, R&M2003c)
|
||||
# note that kinetics are scaled in the mod file.
|
||||
dataset = "MSO_principal_channels"
|
||||
pars = self.get_cellpars(dataset, species=species, celltype=celltype)
|
||||
self.set_soma_size_from_Cm(pars.cap)
|
||||
self.status["na"] = pars.natype
|
||||
self.adjust_na_chans(soma, sf=sf)
|
||||
soma().kht.gbar = nstomho(pars.soma_kht_gbar, self.somaarea)
|
||||
soma().klt.gbar = nstomho(pars.soma_klt_gbar, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(pars.soma_ih_gbar, self.somaarea)
|
||||
soma().leak.gbar = nstomho(pars.soma_leak_gbar, self.somaarea)
|
||||
|
||||
self.axonsf = 0.57
|
||||
|
||||
else:
|
||||
errmsg = (
|
||||
'Species "%s" or model type "%s" is not recognized for MSO cells.'
|
||||
% (species, modelType)
|
||||
)
|
||||
errmsg += "\n Valid species are: \n"
|
||||
for s in knownspecies:
|
||||
errmsg += " %s\n" % s
|
||||
errmsg += "-" * 40
|
||||
raise ValueError(errmsg)
|
||||
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
self.check_temperature()
|
||||
# self.cell_initialize(vrange=self.vrange) # no need to do this just yet.
|
||||
if not silent:
|
||||
print(" set cell as: ", species)
|
||||
print(" with Vm rest = %6.3f" % self.vm0)
|
||||
|
||||
def channel_manager(self, modelType="MSO-principal"):
|
||||
"""
|
||||
This routine defines channel density maps and distance map patterns
|
||||
for each type of compartment in the cell. The maps
|
||||
are used by the ChannelDecorator class (specifically, its private
|
||||
\_biophys function) to decorate the cell membrane.
|
||||
These settings are only used if the decorator is called; otherwise
|
||||
for point cells, the species_scaling routine defines the channel
|
||||
densities.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
modelType : string (default: 'RM03')
|
||||
A string that defines the type of the model. Currently, only 1 type is implemented:
|
||||
RM03: Rothman and Manis, 2003 somatic densities based on guinea pig bushy cell
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
Notes
|
||||
-----
|
||||
This routine defines the following variables for the class:
|
||||
|
||||
* conductances (gBar)
|
||||
* a channelMap (dictonary of channel densities in defined anatomical compartments)
|
||||
* a current injection range for IV's (used for testing)
|
||||
* a distance map, which defines how each conductance in a selected compartment
|
||||
changes with distance from the soma. The current implementation includes both
|
||||
linear and exponential gradients,
|
||||
the minimum conductance at the end of the gradient, and the space constant or
|
||||
slope for the gradient.
|
||||
|
||||
"""
|
||||
|
||||
self.c_m = 1e-6 # default in units of F/cm^2
|
||||
if modelType == "MSO-principal":
|
||||
#
|
||||
# Create a model based on the Rothman and Manis 2003 conductance set from guinea pig
|
||||
#
|
||||
self.c_m = 0.9e-6 # default in units of F/cm^2
|
||||
totcap = 12.0e-12 # in units of F, from Rothman and Manis, 2003.
|
||||
refarea = totcap / self.c_m # area is in cm^2
|
||||
# MSO Rothman-Manis, guinea pig type II
|
||||
# model gave cell conductance in nS, but we want S/cm^2 for NEURON
|
||||
# so conversion is 1e-9*nS = uS, and refarea is already in cm2
|
||||
self._valid_temperatures = (22.0, 38.0)
|
||||
sf = 1.0
|
||||
if self.status["temperature"] == None:
|
||||
self.status["temperature"] = 22.0
|
||||
if self.status["temperature"] == 38:
|
||||
sf = 3.03
|
||||
self.gBar = Params(
|
||||
nabar=sf * 1000.0e-9 / refarea,
|
||||
khtbar=sf * 150.0e-9 / refarea,
|
||||
kltbar=sf * 200.0e-9 / refarea,
|
||||
ihbar=sf * 20.0e-9 / refarea,
|
||||
leakbar=sf * 2.0e-9 / refarea,
|
||||
)
|
||||
print("MSO principal channels gbar:\n", self.gBar.show())
|
||||
|
||||
self.channelMap = {
|
||||
"axon": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": 0.0,
|
||||
"leak": self.gBar.leakbar / 2.0,
|
||||
},
|
||||
"hillock": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": 0.0,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"initseg": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": self.gBar.ihbar / 2.0,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"soma": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": self.gBar.ihbar,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"dend": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar * 0.5,
|
||||
"kht": self.gBar.khtbar * 0.5,
|
||||
"ihvcn": self.gBar.ihbar / 3.0,
|
||||
"leak": self.gBar.leakbar * 0.5,
|
||||
},
|
||||
"apic": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar * 0.2,
|
||||
"kht": self.gBar.khtbar * 0.2,
|
||||
"ihvcn": self.gBar.ihbar / 4.0,
|
||||
"leak": self.gBar.leakbar * 0.2,
|
||||
},
|
||||
}
|
||||
# self.irange = np.linspace(-1., 1., 21)
|
||||
self.distMap = {
|
||||
"dend": {
|
||||
"klt": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"kht": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"nacn": {"gradient": "exp", "gminf": 0.0, "lambda": 100.0},
|
||||
}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
"apic": {
|
||||
"klt": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"kht": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"nacn": {"gradient": "exp", "gminf": 0.0, "lambda": 100.0},
|
||||
}, # gradients are: flat, linear, exponential
|
||||
}
|
||||
|
||||
else:
|
||||
raise ValueError("model type %s is not implemented" % modelType)
|
||||
self.check_temperature()
|
||||
|
||||
def adjust_na_chans(self, soma, sf=1.0, gbar=1000.0, debug=False):
|
||||
"""
|
||||
adjust the sodium channel conductance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
soma : neuron section object
|
||||
A soma object whose sodium channel complement will have its
|
||||
conductances adjusted depending on the channel type
|
||||
|
||||
gbar : float (default: 1000.)
|
||||
The maximal conductance for the sodium channel
|
||||
|
||||
debug : boolean (false):
|
||||
Verbose printing
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing :
|
||||
|
||||
"""
|
||||
|
||||
if self.status["ttx"]:
|
||||
gnabar = 0.0
|
||||
else:
|
||||
gnabar = nstomho(gbar, self.somaarea) * sf
|
||||
nach = self.status["na"]
|
||||
if nach == "jsrna":
|
||||
soma().jsrna.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("jsrna gbar: ", soma().jsrna.gbar)
|
||||
elif nach == "nav11":
|
||||
soma().nav11.gbar = gnabar
|
||||
soma.ena = 50 # self.e_na
|
||||
# print('gnabar: ', soma().nav11.gbar, ' vs: 0.0192307692308')
|
||||
soma().nav11.vsna = 4.3
|
||||
if debug:
|
||||
print("MSO using inva11")
|
||||
elif nach in ["na", "nacn"]:
|
||||
soma().na.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("na gbar: ", soma().na.gbar)
|
||||
else:
|
||||
raise ValueError("Sodium channel %s is not recognized for MSO cells", nach)
|
||||
718
cnmodel/cells/octopus.py
Normal file
718
cnmodel/cells/octopus.py
Normal file
@@ -0,0 +1,718 @@
|
||||
from __future__ import print_function
|
||||
from neuron import h
|
||||
from ..util import nstomho
|
||||
from ..util import Params
|
||||
import numpy as np
|
||||
from .cell import Cell
|
||||
from .. import data
|
||||
|
||||
"""
|
||||
Original hoc code from RMmodel.hoc
|
||||
// including the "Octopus" cell:
|
||||
proc set_Type2o() {
|
||||
gbar_na = nstomho(1000)
|
||||
gbar_kht = nstomho(150)
|
||||
gbar_klt = nstomho(600)
|
||||
gbar_ka = nstomho(0)
|
||||
gbar_ih = nstomho(0)
|
||||
gbar_hcno = nstomho(40)
|
||||
gbar_leak = nstomho(2)
|
||||
model = 6
|
||||
modelname = "Type IIo (Octopus)"
|
||||
vm0 = -66.67
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ["Octopus", "OctopusRothman", "OctopusSpencer"]
|
||||
|
||||
|
||||
class Octopus(Cell):
|
||||
|
||||
type = "octopus"
|
||||
|
||||
@classmethod
|
||||
def create(cls, modelType="RM03", **kwds):
|
||||
if modelType in ["RM03", "II-o"]:
|
||||
return OctopusRothman(**kwds)
|
||||
elif modelType == "Spencer":
|
||||
return OctopusSpencer(**kwds)
|
||||
else:
|
||||
raise ValueError("Octopus cell type %s is unknown" % modelType)
|
||||
|
||||
def make_psd(self, terminal, psd_type, **kwds):
|
||||
"""
|
||||
Connect a presynaptic terminal to one post section at the specified location, with the fraction
|
||||
of the "standard" conductance determined by gbar.
|
||||
The default condition is to try to pass the default unit test (loc=0.5)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
terminal : Presynaptic terminal (NEURON object)
|
||||
|
||||
psd_type : either simple or multisite PSD for bushy cell
|
||||
|
||||
kwds: dict of options. Two are currently handled:
|
||||
postsize : expect a list consisting of [sectionno, location (float)]
|
||||
AMPAScale : float to scale the ampa currents
|
||||
|
||||
"""
|
||||
if (
|
||||
"postsite" in kwds
|
||||
): # use a defined location instead of the default (soma(0.5)
|
||||
postsite = kwds["postsite"]
|
||||
loc = postsite[1] # where on the section?
|
||||
uname = (
|
||||
"sections[%d]" % postsite[0]
|
||||
) # make a name to look up the neuron section object
|
||||
post_sec = self.hr.get_section(uname) # Tell us where to put the synapse.
|
||||
else:
|
||||
loc = 0.5
|
||||
post_sec = self.soma
|
||||
|
||||
if psd_type == "simple":
|
||||
if terminal.cell.type in ["sgc"]:
|
||||
weight = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="weight",
|
||||
)
|
||||
tau1 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau1",
|
||||
)
|
||||
tau2 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau2",
|
||||
)
|
||||
erev = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="erev",
|
||||
)
|
||||
return self.make_exp2_psd(
|
||||
post_sec,
|
||||
terminal,
|
||||
weight=weight,
|
||||
loc=loc,
|
||||
tau1=tau1,
|
||||
tau2=tau2,
|
||||
erev=erev,
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make simple PSD for %s => %s"
|
||||
% (terminal.cell.type, self.type)
|
||||
)
|
||||
|
||||
elif psd_type == "multisite":
|
||||
if terminal.cell.type == "sgc":
|
||||
# Max conductances for the glu mechanisms are calibrated by
|
||||
# running `synapses/tests/test_psd.py`. The test should fail
|
||||
# if these values are incorrect
|
||||
self.AMPAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="AMPAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.NMDAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="NMDAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.Pr = data.get(
|
||||
"sgc_synapse", species=self.species, post_type=self.type, field="Pr"
|
||||
)
|
||||
# adjust gmax to correct for initial Pr
|
||||
self.AMPAR_gmax = self.AMPAR_gmax / self.Pr
|
||||
self.NMDAR_gmax = self.NMDAR_gmax / self.Pr
|
||||
# AMPA_gmax = 3.314707700918133*1e3 # factor of 1e3 scales to pS (.mod mechanisms) from nS.
|
||||
# NMDA_gmax = 0.4531929783503451*1e3
|
||||
if "AMPAScale" in kwds:
|
||||
self.AMPAR_gmax = (
|
||||
self.AMPAR_gmax * kwds["AMPAScale"]
|
||||
) # allow scaling of AMPA conductances
|
||||
if "NMDAScale" in kwds:
|
||||
self.NMDAR_gmax = self.NMDAR_gmax * kwds["NMDAScale"]
|
||||
return self.make_glu_psd(
|
||||
post_sec, terminal, self.AMPAR_gmax, self.NMDAR_gmax, loc=loc
|
||||
)
|
||||
elif terminal.cell.type == "dstellate":
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyslow", loc=loc)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make PSD for %s => %s" % (terminal.cell.type, self.type)
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported psd type %s" % psd_type)
|
||||
|
||||
|
||||
class OctopusRothman(Octopus, Cell):
|
||||
"""
|
||||
VCN octopus cell model (point cell).
|
||||
Rothman and Manis, 2003abc (Type II, with high gklt and hcno - octopus cell h current).
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach=None,
|
||||
ttx=False,
|
||||
species="guineapig",
|
||||
modelType=None,
|
||||
debug=False,
|
||||
):
|
||||
"""
|
||||
initialize the octopus cell, using the default parameters for guinea pig from
|
||||
R&M2003, as a type II cell with modified conductances.
|
||||
Modifications to the cell can be made by calling methods below.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
a file name to read the cell morphology from. If a valid file is found, a cell is constructed
|
||||
as a cable model from the hoc file.
|
||||
If None (default), the only a point model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels aer inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: None)
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanism
|
||||
by that name must exist. None implies the default channel (jsrna for this model).
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
Currently, this is not implemented.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the channel density that will be inserted for different models. Note that
|
||||
if a decorator function is specified, this argument is ignored.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the type of the model that will be used (e.g., "II", "II-I", etc).
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point models.
|
||||
|
||||
debug: boolean (default: False)
|
||||
debug is a boolean flag. When set, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
|
||||
super(OctopusRothman, self).__init__()
|
||||
if modelType == None:
|
||||
modelType = "II-o"
|
||||
if nach == None and species == "guineapig":
|
||||
nach = "jsrna"
|
||||
if nach == None and species == "mouse":
|
||||
nach = "nacn"
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "Octopus",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": None,
|
||||
}
|
||||
self.i_test_range = {"pulse": (-4.0, 4.0, 0.2)}
|
||||
self.spike_threshold = -50
|
||||
self.vrange = [-70.0, -57.0] # set a default vrange for searching for rmp
|
||||
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
soma = h.Section(
|
||||
name="Octopus_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
self.e_leak = -73.0 # from McGinley et al., 2016
|
||||
self.e_h = -38.0 # from McGinley et al.
|
||||
self.R_a = 195 # McGinley et al.
|
||||
if self.status["species"] == "mouse":
|
||||
self.mechanisms = ["klt", "kht", "hcnobo", "leak", nach]
|
||||
else:
|
||||
self.mechanisms = ["klt", "kht", "ihvcn", "leak", nach]
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.soma.ek = self.e_k
|
||||
self.soma.ena = self.e_na
|
||||
if self.status["species"] == "mouse":
|
||||
self.soma().hcnobo.eh = self.e_h
|
||||
else:
|
||||
self.soma().ihvcn.eh = self.e_h
|
||||
self.soma().leak.erev = self.e_leak
|
||||
self.soma.Ra = self.R_a
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
|
||||
if debug:
|
||||
print("<< octopus: octopus cell model created >>")
|
||||
# print 'Cell created: ', self.status
|
||||
|
||||
def species_scaling(self, species="guineapig", modelType="II-o", silent=True):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
Used ONLY for point models.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be guineapig
|
||||
|
||||
modelType: string (default: 'II-o')
|
||||
definition of model type from RM03 models, currently limited to type II-o
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
"""
|
||||
soma = self.soma
|
||||
|
||||
if species == "guineapig" and modelType == "II-o":
|
||||
self.c_m = 0.9
|
||||
self.set_soma_size_from_Cm(25.0)
|
||||
self._valid_temperatures = (22.0, 38.0)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(22.0)
|
||||
sf = 1.0
|
||||
if (
|
||||
self.status["temperature"] == 38.0
|
||||
): # adjust for 2003 model conductance levels at 38
|
||||
sf = 3.03 # Q10 of 2, 22->38C. (p3106, R&M2003c)
|
||||
# note that kinetics are scaled in the mod file.
|
||||
# self.print_soma_info()
|
||||
self.adjust_na_chans(soma, sf=sf)
|
||||
soma().kht.gbar = sf * nstomho(150.0, self.somaarea) # 6.1 mmho/cm2
|
||||
soma().klt.gbar = sf * nstomho(
|
||||
1000.0, self.somaarea
|
||||
) # 40.7 mmho/cm2 3195?
|
||||
soma().ihvcn.gbar = sf * nstomho(
|
||||
30.0, self.somaarea
|
||||
) # 7.6 mmho/cm2, cf. Bal and Oertel, Spencer et al. 25 u dia cell 40ns?
|
||||
soma().leak.gbar = sf * nstomho(2.0, self.somaarea)
|
||||
self.axonsf = 1.0
|
||||
elif species == "mouse" and modelType == "II-o":
|
||||
self.set_soma_size_from_Cm(25.0)
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
# self.print_soma_info()
|
||||
self.adjust_na_chans(soma, gbar=3000.0)
|
||||
soma().kht.gbar = nstomho(150.0, self.somaarea) # 6.1 mmho/cm2
|
||||
soma().klt.gbar = nstomho(3196.0, self.somaarea) # 40.7 mmho/cm2
|
||||
soma().hcnobo.gbar = nstomho(
|
||||
40.0, self.somaarea
|
||||
) # 7.6 mmho/cm2, cf. Bal and Oertel, Spencer et al. 25 u dia cell
|
||||
soma().leak.gbar = nstomho(2.0, self.somaarea)
|
||||
self.axonsf = 1.0
|
||||
else:
|
||||
raise ValueError(
|
||||
'Species "%s" or species-type "%s" is not recognized for octopus cells'
|
||||
% (species, type)
|
||||
)
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
# self.cell_initialize(showinfo=True)
|
||||
self.check_temperature()
|
||||
if not silent:
|
||||
print("set cell as: ", species)
|
||||
print(" with Vm rest = %6.3f" % self.vm0)
|
||||
|
||||
def adjust_na_chans(self, soma, sf=1.0, gbar=1000.0, debug=False):
|
||||
"""
|
||||
adjust the sodium channel conductance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
soma : neuron section object
|
||||
a soma object whose sodium channel complement will have it's
|
||||
conductances adjusted depending on the channel type
|
||||
|
||||
gbar : float (default: 1000.)
|
||||
the maximal conductance for the sodium channel
|
||||
|
||||
debug : boolean (false):
|
||||
verbose printing
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
|
||||
if self.status["ttx"]:
|
||||
gnabar = 0.0
|
||||
else:
|
||||
gnabar = sf * nstomho(gbar, self.somaarea) # mmho/cm2 - 4244.1 moh - 4.2441
|
||||
nach = self.status["na"]
|
||||
if nach == "jsrna":
|
||||
soma().jsrna.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("octopus using jsrna, gbar: ", soma().jsrna.gbar)
|
||||
elif nach == "nav11":
|
||||
soma().nav11.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
soma().nav11.vsna = 4.3
|
||||
if debug:
|
||||
print("octopus using inva11, gbar:", soma().nav11.gbar)
|
||||
elif nach in ["na", "nacn"]:
|
||||
soma().nacn.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("octopus cell using na/nacn, gbar: ", soma().na.gbar)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Sodium channel %s is not recognized for octopus cells", nach
|
||||
)
|
||||
|
||||
|
||||
class OctopusSpencer(Octopus, Cell):
|
||||
"""
|
||||
VCN octopus cell model (with dendrites).
|
||||
Based on Spencer et al Front. Comput. Neurosci., 22 October 2012
|
||||
https://doi.org/10.3389/fncom.2012.00083
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach="jsrna",
|
||||
ttx=False,
|
||||
species="guineapig",
|
||||
modelType=None,
|
||||
debug=False,
|
||||
):
|
||||
"""
|
||||
initialize the octopus cell, using the parameters Spencer et al. 2012
|
||||
Modifications to the cell can be made by calling methods below.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
a file name to read the cell morphology from. If a valid file is found, a cell is constructed
|
||||
as a cable model from the hoc file.
|
||||
If None (default), the only a point model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels aer inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: 'na')
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanism
|
||||
by that name must exist.
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
Currently, this is not implemented.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the channel density that will be inserted for different models. Note that
|
||||
if a decorator function is specified, this argument is ignored.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the type of the model that will be used (e.g., "II", "II-I", etc).
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point models.
|
||||
|
||||
debug: boolean (default: False)
|
||||
debug is a boolean flag. When set, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
|
||||
super(OctopusSpencer, self).__init__()
|
||||
if modelType == None:
|
||||
modelType = "Spencer"
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "Octopus",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": None,
|
||||
}
|
||||
self.i_test_range = (-4.0, 6.0, 0.25)
|
||||
self.spike_threshold = -50
|
||||
self.vrange = [-75.0, -63.0] # set a default vrange for searching for rmp
|
||||
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
soma = h.Section(
|
||||
name="Octopus_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
self.set_soma_size_from_Section(self.soma)
|
||||
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
self.e_leak = -62.0 # from Spencer et al., 2012
|
||||
self.e_h = -38.0 ## from Spencer et al., 2012
|
||||
self.R_a = 100.0 # from Spencer et al., 2012
|
||||
self.mechanisms = ["klt", "kht", "hcnobo", "leak", nach]
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.soma.ek = -70.0 # self.e_k
|
||||
self.soma.ena = 55.0 # self.e_na
|
||||
self.soma().hcnobo.eh = self.e_h
|
||||
self.soma().leak.erev = self.e_leak
|
||||
self.soma.Ra = self.R_a
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.decorated.channelValidate(self, verify=True)
|
||||
# print 'Mechanisms inserted: ', self.mechanisms
|
||||
self.get_mechs(self.soma)
|
||||
# self.cell_initialize(vrange=self.vrange)
|
||||
|
||||
if debug:
|
||||
print("<< octopus: octopus cell model created >>")
|
||||
# print 'Cell created: ', self.status
|
||||
|
||||
def channel_manager(self, modelType="Spencer"):
|
||||
"""
|
||||
This routine defines channel density maps and distance map patterns
|
||||
for each type of compartment in the cell. The maps
|
||||
are used by the ChannelDecorator class (specifically, it's private
|
||||
\_biophys function) to decorate the cell membrane.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
modelType : string (default: 'Spencer')
|
||||
A string that defines the type of the model. Currently, 1 type is implemented:
|
||||
Spencer : Spencer et al Front. Comput. Neurosci. 2012
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
Notes
|
||||
-----
|
||||
This routine defines the following variables for the class:
|
||||
# conductances (gBar)
|
||||
# a channelMap (dictonary of channel densities in defined anatomical compartments)
|
||||
# a current injection range for IV's (when testing)
|
||||
# a distance map, which defines how selected conductances in selected compartments
|
||||
will change with distance. This includes both linear and exponential gradients,
|
||||
the minimum conductance at the end of the gradient, and the space constant or
|
||||
slope for the gradient.
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# Create a model based on the Spencer model
|
||||
# Channel decoration and stick model from Figure 2
|
||||
# densities from Tables 2 and 3
|
||||
if modelType == "Spencer":
|
||||
# print self.c_m
|
||||
self.c_m = 0.9
|
||||
# self.set_soma_size_from_Section(self.soma)
|
||||
totcap = self.totcap
|
||||
refarea = self.somaarea # totcap / self.c_m # see above for units
|
||||
# self.print_soma_info()
|
||||
self._valid_temperatures = (
|
||||
34.0,
|
||||
) # 34 for consistency with other mouse models, but
|
||||
# Spencer data used "33". This affects very slightly
|
||||
# the HCN channel conductance.
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
self.gBar = Params(
|
||||
nabar=0.0, # 0.0407, # S/cm2
|
||||
nabar_ais=0.42441,
|
||||
kltbar_ais=0.0,
|
||||
khtbar_ais=0.0,
|
||||
ihbar_ais=0.0,
|
||||
kltbar_soma=0.0407,
|
||||
khtbar_soma=0.0061,
|
||||
ihbar_soma=0.0076,
|
||||
kltbar_dend=0.0027,
|
||||
khtbar_dend=0.0,
|
||||
ihbar_dend=0.0006,
|
||||
khtbar_hillock=0.0,
|
||||
kltbar_hillock=0.0,
|
||||
ihbar_hillock=0.0,
|
||||
leakbar=0.0020,
|
||||
)
|
||||
|
||||
self.channelMap = {
|
||||
"soma": {
|
||||
"jsrna": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar_soma,
|
||||
"kht": self.gBar.khtbar_soma,
|
||||
"hcnobo": self.gBar.ihbar_soma,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"hillock": {
|
||||
"jsrna": 0.0,
|
||||
"klt": self.gBar.kltbar_hillock,
|
||||
"kht": self.gBar.khtbar_hillock,
|
||||
"hcnobo": self.gBar.ihbar_hillock,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
# axon initial segment:
|
||||
"unmyelinatedaxon": {
|
||||
"jsrna": self.gBar.nabar_ais,
|
||||
"klt": self.gBar.kltbar_ais,
|
||||
"kht": self.gBar.khtbar_ais,
|
||||
"hcnobo": self.gBar.ihbar_ais,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"primarydendrite": {
|
||||
"jsrna": 0.0,
|
||||
"klt": self.gBar.kltbar_dend,
|
||||
"kht": self.gBar.khtbar_dend,
|
||||
"hcnobo": self.gBar.ihbar_dend,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
}
|
||||
|
||||
self.distMap = {
|
||||
"primarydendrite": {
|
||||
"klt": {"gradient": "flat", "gminf": 0.0, "lambda": 100.0},
|
||||
"kht": {"gradient": "flat", "gminf": 0.0, "lambda": 100.0},
|
||||
"hcnobo": {"gradient": "flat", "gminf": 0.0, "lambda": 100.0},
|
||||
} # all flat with distance
|
||||
}
|
||||
# reversal potential map
|
||||
self.channelErevMap = {
|
||||
"soma": {
|
||||
"jsrna": 55.0,
|
||||
"klt": -70,
|
||||
"kht": -70,
|
||||
"hcnobo": -38,
|
||||
"leak": -62.0,
|
||||
},
|
||||
"hillock": {
|
||||
"jsrna": 55.0,
|
||||
"klt": -70,
|
||||
"kht": -70,
|
||||
"hcnobo": -38,
|
||||
"leak": -62.0,
|
||||
},
|
||||
"unmyelinatedaxon": {
|
||||
"jsrna": 55.0,
|
||||
"klt": -70,
|
||||
"kht": -70,
|
||||
"hcnobo": -38,
|
||||
"leak": -62.0,
|
||||
},
|
||||
"primarydendrite": {
|
||||
"jsrna": 55.0,
|
||||
"klt": -70,
|
||||
"kht": -70,
|
||||
"hcnobo": -38,
|
||||
"leak": -62.0,
|
||||
},
|
||||
}
|
||||
|
||||
else:
|
||||
raise ValueError("model type %s is not implemented" % modelType)
|
||||
self.check_temperature()
|
||||
|
||||
def species_scaling(self, species="mouse", modelType="Spencer", silent=True):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
Used ONLY for point models.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be guineapig
|
||||
|
||||
modelType: string (default: 'II-o')
|
||||
definition of model type from RM03 models, currently limited to type II-o
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
"""
|
||||
soma = self.soma
|
||||
|
||||
if species == "mouse" and modelType == "Spencer":
|
||||
print("Octopus: Mouse, Spencer point model - not a valid model")
|
||||
self.set_soma_size_from_Cm(25.0)
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
self.print_soma_info()
|
||||
# self.adjust_na_chans(soma)
|
||||
# soma().kht.gbar = 0.0061 # nstomho(150.0, self.somaarea) # 6.1 mmho/cm2
|
||||
# soma().klt.gbar = 0.0407 # nstomho(3196.0, self.somaarea) # 40.7 mmho/cm2
|
||||
# soma().hcnobo.gbar = 0.0076 #nstomho(40.0, self.somaarea) # 7.6 mmho/cm2, cf. Bal and Oertel, Spencer et al. 25 u dia cell
|
||||
# soma().leak.gbar = 0.0005 # nstomho(2.0, self.somaarea)
|
||||
self.axonsf = 1.0
|
||||
else:
|
||||
raise ValueError(
|
||||
'Species "%s" or species-type "%s" is not recognized for octopus cells'
|
||||
% (species, type)
|
||||
)
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
self.cell_initialize(showinfo=True)
|
||||
if not silent:
|
||||
print("set cell as: ", species)
|
||||
print(" with Vm rest = %6.3f" % self.vm0)
|
||||
482
cnmodel/cells/pyramidal.py
Normal file
482
cnmodel/cells/pyramidal.py
Normal file
@@ -0,0 +1,482 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
from neuron import h
|
||||
|
||||
from .cell import Cell
|
||||
from .. import data
|
||||
from ..util import Params
|
||||
from ..util import nstomho
|
||||
|
||||
__all__ = ["Pyramidal", "PyramidalKanold"]
|
||||
|
||||
|
||||
class Pyramidal(Cell):
|
||||
|
||||
type = "pyramidal"
|
||||
|
||||
@classmethod
|
||||
def create(cls, model="POK", **kwds):
|
||||
if model == "POK":
|
||||
return PyramidalKanold(**kwds)
|
||||
else:
|
||||
raise ValueError("Pyramidal model %s is unknown", model)
|
||||
|
||||
def make_psd(self, terminal, psd_type, **kwds):
|
||||
"""
|
||||
Connect a presynaptic terminal to one post section at the specified location, with the fraction
|
||||
of the "standard" conductance determined by gbar.
|
||||
The default condition is to try to pass the default unit test (loc=0.5)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
terminal : Presynaptic terminal (NEURON object)
|
||||
|
||||
psd_type : either simple or multisite PSD for bushy cell
|
||||
|
||||
kwds: dict of options. Two are currently handled:
|
||||
postsize : expect a list consisting of [sectionno, location (float)]
|
||||
AMPAScale : float to scale the ampa currents
|
||||
|
||||
"""
|
||||
if (
|
||||
"postsite" in kwds
|
||||
): # use a defined location instead of the default (soma(0.5)
|
||||
postsite = kwds["postsite"]
|
||||
loc = postsite[1] # where on the section?
|
||||
uname = (
|
||||
"sections[%d]" % postsite[0]
|
||||
) # make a name to look up the neuron section object
|
||||
post_sec = self.hr.get_section(uname) # Tell us where to put the synapse.
|
||||
else:
|
||||
loc = 0.5
|
||||
post_sec = self.soma
|
||||
|
||||
if psd_type == "simple":
|
||||
if terminal.cell.type in [
|
||||
"sgc",
|
||||
"dstellate",
|
||||
"tuberculoventral",
|
||||
"cartwheel",
|
||||
]:
|
||||
weight = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="weight",
|
||||
)
|
||||
tau1 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau1",
|
||||
)
|
||||
tau2 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau2",
|
||||
)
|
||||
erev = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="erev",
|
||||
)
|
||||
return self.make_exp2_psd(
|
||||
post_sec,
|
||||
terminal,
|
||||
weight=weight,
|
||||
loc=loc,
|
||||
tau1=tau1,
|
||||
tau2=tau2,
|
||||
erev=erev,
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make simple PSD for %s => %s"
|
||||
% (terminal.cell.type, self.type)
|
||||
)
|
||||
|
||||
elif psd_type == "multisite":
|
||||
if terminal.cell.type == "sgc":
|
||||
# Max conductances for the glu mechanisms are calibrated by
|
||||
# running `synapses/tests/test_psd.py`. The test should fail
|
||||
# if these values are incorrect
|
||||
self.AMPAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="AMPAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.NMDAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="NMDAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.Pr = data.get(
|
||||
"sgc_synapse", species=self.species, post_type=self.type, field="Pr"
|
||||
)
|
||||
# adjust gmax to correct for initial Pr
|
||||
self.AMPAR_gmax = self.AMPAR_gmax / self.Pr
|
||||
self.NMDAR_gmax = self.NMDAR_gmax / self.Pr
|
||||
if "AMPAScale" in kwds:
|
||||
self.AMPA_gmax = (
|
||||
self.AMPA_gmax * kwds["AMPAScale"]
|
||||
) # allow scaling of AMPA conductances
|
||||
if "NMDAScale" in kwds:
|
||||
self.NMDA_gmax = self.NMDA_gmax * kwds["NMDAScale"]
|
||||
return self.make_glu_psd(
|
||||
post_sec, terminal, self.AMPAR_gmax, self.NMDAR_gmax, loc=loc
|
||||
)
|
||||
elif terminal.cell.type == "dstellate": # WBI input -Voigt, Nelken, Young
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyfast", loc=loc)
|
||||
elif (
|
||||
terminal.cell.type == "tuberculoventral"
|
||||
): # TV cells talk to each other-Kuo et al.
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyfast", loc=loc)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make PSD for %s => %s" % (terminal.cell.type, self.type)
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported psd type %s" % psd_type)
|
||||
|
||||
|
||||
class PyramidalKanold(Pyramidal, Cell):
|
||||
"""
|
||||
DCN pyramidal cell
|
||||
Kanold and Manis, 1999, 2001, 2005
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach=None,
|
||||
ttx=False,
|
||||
species="rat",
|
||||
modelType=None,
|
||||
debug=False,
|
||||
):
|
||||
"""
|
||||
initialize a pyramidal cell, based on the Kanold-Manis (2001) pyramidal cell model.
|
||||
Modifications to the cell can be made by calling methods below. These include
|
||||
converting to a model with modified size and conductances (experimental).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
a file name to read the cell morphology from. If a valid file is found, a cell is constructed
|
||||
as a cable model from the hoc file.
|
||||
If None (default), the only a point model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels is inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: None)
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanim
|
||||
by that name must exist. None implies the default channel, 'napyr'.
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
Currently, this is not implemented.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the channel density that will be inserted for different models. Note that
|
||||
if a decorator function is specified, this argument is ignored (overridden by decorator).
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the type of the model that will be used (e.g., "II", "II-I", etc).
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point models.
|
||||
|
||||
debug: boolean (default: False)
|
||||
debug is a boolean flag. When set, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
"""
|
||||
super(PyramidalKanold, self).__init__()
|
||||
if modelType == None:
|
||||
modelType = "POK"
|
||||
if nach == None:
|
||||
nach = "napyr"
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "Pyramidal",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": None,
|
||||
}
|
||||
|
||||
self.i_test_range = {"pulse": (-0.3, 0.401, 0.02)}
|
||||
self.vrange = [-75.0, -60.0]
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
soma = h.Section(
|
||||
name="Pyramidal_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
self.mechanisms = [
|
||||
"napyr",
|
||||
"kdpyr",
|
||||
"kif",
|
||||
"kis",
|
||||
"ihpyr",
|
||||
"leak",
|
||||
"kcnq",
|
||||
"nap",
|
||||
]
|
||||
for mech in self.mechanisms:
|
||||
try:
|
||||
self.soma.insert(mech)
|
||||
except ValueError:
|
||||
print("WARNING: Mechanism %s not found" % mech)
|
||||
self.soma().kif.kif_ivh = -89.6
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type I-c cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
if debug:
|
||||
print("<< PYR: POK Pyramidal Cell created >>")
|
||||
|
||||
def get_cellpars(self, dataset, species="guineapig", celltype="II"):
|
||||
cellcap = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_Cap"
|
||||
)
|
||||
chtype = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_natype"
|
||||
)
|
||||
pars = Params(cap=cellcap, natype=chtype)
|
||||
for g in [
|
||||
"soma_napyr_gbar",
|
||||
"soma_kdpyr_gbar",
|
||||
"soma_kif_gbar",
|
||||
"soma_kis_gbar",
|
||||
"soma_kcnq_gbar",
|
||||
"soma_nap_gbar",
|
||||
"soma_ihpyr_gbar",
|
||||
"soma_leak_gbar",
|
||||
"soma_e_h",
|
||||
"soma_leak_erev",
|
||||
"soma_e_k",
|
||||
"soma_e_na",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, cell_type=celltype, field=g)
|
||||
)
|
||||
return pars
|
||||
|
||||
def species_scaling(self, species="rat", modelType="I", silent=True):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
Used ONLY for point models.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'rat')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be 'rat'
|
||||
|
||||
modelType: string (default: 'I')
|
||||
definition of model type from Kanold and Manis, 2001
|
||||
choices are 'I' or 'POK' (canonical model) or
|
||||
'II', a modified model with more physiological surface area and KCNQ channels
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
"""
|
||||
if modelType in ["I", "POK"]:
|
||||
celltype = "pyramidal"
|
||||
elif modelType in ["II"]:
|
||||
celltype = "pyramidal-II"
|
||||
else:
|
||||
celltype = modelType
|
||||
|
||||
dataset = "POK_channels"
|
||||
|
||||
soma = self.soma
|
||||
if species in ["rat", "mouse"] and modelType in [
|
||||
"I",
|
||||
"POK",
|
||||
"II",
|
||||
]: # canonical K&M2001 model cell
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
pars = self.get_cellpars(dataset, species=species, celltype=celltype)
|
||||
self.set_soma_size_from_Cm(pars.cap)
|
||||
self.status["na"] = pars.natype
|
||||
soma().napyr.gbar = nstomho(pars.soma_napyr_gbar, self.somaarea)
|
||||
soma().nap.gbar = nstomho(
|
||||
pars.soma_nap_gbar, self.somaarea
|
||||
) # does not exist in canonical model
|
||||
soma().kdpyr.gbar = nstomho(pars.soma_kdpyr_gbar, self.somaarea)
|
||||
soma().kcnq.gbar = nstomho(
|
||||
pars.soma_kcnq_gbar, self.somaarea
|
||||
) # does not exist in canonical model.
|
||||
soma().kif.gbar = nstomho(pars.soma_kif_gbar, self.somaarea)
|
||||
soma().kis.gbar = nstomho(pars.soma_kis_gbar, self.somaarea)
|
||||
soma().ihpyr.gbar = nstomho(pars.soma_ihpyr_gbar, self.somaarea)
|
||||
# soma().ihpyr_adj.q10 = 3.0 # no temp scaling to sta
|
||||
soma().leak.gbar = nstomho(pars.soma_leak_gbar, self.somaarea)
|
||||
soma().leak.erev = pars.soma_leak_erev
|
||||
soma().ena = pars.soma_e_na
|
||||
soma().ek = pars.soma_e_k
|
||||
soma().ihpyr.eh = pars.soma_e_h
|
||||
|
||||
# elif species in 'rat' and modelType == 'II':
|
||||
# """
|
||||
# Modified canonical K&M2001 model cell
|
||||
# In this model version, the specific membrane capacitance is modified
|
||||
# so that the overall membrane time constant is consistent with experimental
|
||||
# measures in slices. However, this is not a physiological value. Attempts
|
||||
# to use the normal 1 uF/cm2 value were unsuccessful in establishing the expected
|
||||
# ~12 msec time constant.
|
||||
# This model also adds a KCNQ channel, as described by Li et al., 2012.
|
||||
# """
|
||||
# self.c_m = 6.0
|
||||
# self.set_soma_size_from_Diam(30.0)
|
||||
# # self.set_soma_size_from_Cm(80.0)
|
||||
# # print 'diameter: %7.1f' % self.soma.diam
|
||||
# self._valid_temperatures = (34.,)
|
||||
# if self.status['temperature'] is None:
|
||||
# self.set_temperature(34.)
|
||||
# self.refarea = self.somaarea
|
||||
# soma().napyr.gbar = nstomho(550, self.refarea)
|
||||
# soma().nap.gbar = nstomho(60.0, self.refarea)
|
||||
# soma().kcnq.gbar = nstomho(2, self.refarea) # pyramidal cells have kcnq: Li et al, 2011 (Thanos)
|
||||
# soma().kdpyr.gbar = nstomho(180, self.refarea) # Normally 80.
|
||||
# soma().kif.gbar = nstomho(150, self.refarea) # normally 150
|
||||
# soma().kis.gbar = nstomho(40, self.refarea) # 40
|
||||
# soma().ihpyr.gbar = nstomho(2.8, self.refarea)
|
||||
# soma().leak.gbar = nstomho(0.5, self.refarea)
|
||||
# soma().leak.erev = -62. # override default values in cell.py
|
||||
# soma().ena = 50.0
|
||||
# soma().ek = -81.5
|
||||
# soma().ihpyr.eh = -43
|
||||
# if not self.status['dendrites']:
|
||||
# self.add_dendrites()
|
||||
|
||||
else:
|
||||
raise ValueError(
|
||||
"Species %s or species-modelType %s is not implemented for Pyramidal cells"
|
||||
% (species, modelType)
|
||||
)
|
||||
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
# self.cell_initialize(showinfo=True)
|
||||
self.check_temperature()
|
||||
if not silent:
|
||||
print("set cell as: ", species, modelType)
|
||||
print(" with Vm rest = %f" % self.vm0)
|
||||
print(self.status)
|
||||
for m in self.mechanisms:
|
||||
print("%s.gbar = %f" % (m, eval("soma().%s.gbar" % m)))
|
||||
|
||||
def i_currents(self, V):
|
||||
"""
|
||||
For the steady-state case, return the total current at voltage V
|
||||
Used to find the zero current point
|
||||
vrange brackets the interval
|
||||
Overrides i_currents in cells.py because we have a different set of currents
|
||||
to compute.
|
||||
"""
|
||||
for part in self.all_sections.keys():
|
||||
for sec in self.all_sections[part]:
|
||||
sec.v = V
|
||||
h.celsius = self.status["temperature"]
|
||||
h.finitialize()
|
||||
self.ix = {}
|
||||
|
||||
if "napyr" in self.mechanisms:
|
||||
self.ix["napyr"] = self.soma().napyr.gna * (V - self.soma().ena)
|
||||
if "nap" in self.mechanisms:
|
||||
self.ix["nap"] = self.soma().nap.gnap * (V - self.soma().ena)
|
||||
if "kdpyr" in self.mechanisms:
|
||||
self.ix["kdpyr"] = self.soma().kdpyr.gk * (V - self.soma().ek)
|
||||
if "kif" in self.mechanisms:
|
||||
self.ix["kif"] = self.soma().kif.gkif * (V - self.soma().ek)
|
||||
if "kis" in self.mechanisms:
|
||||
self.ix["kis"] = self.soma().kis.gkis * (V - self.soma().ek)
|
||||
if "kcnq" in self.mechanisms:
|
||||
self.ix["kcnq"] = self.soma().kcnq.gk * (V - self.soma().ek)
|
||||
if "ihpyr" in self.mechanisms:
|
||||
self.ix["ihpyr"] = self.soma().ihpyr.gh * (V - self.soma().ihpyr.eh)
|
||||
if "ihpyr_adj" in self.mechanisms:
|
||||
self.ix["ihpyr_adj"] = self.soma().ihpyr_adj.gh * (
|
||||
V - self.soma().ihpyr_adj.eh
|
||||
)
|
||||
# leak
|
||||
if "leak" in self.mechanisms:
|
||||
self.ix["leak"] = self.soma().leak.gbar * (V - self.soma().leak.erev)
|
||||
return np.sum([self.ix[i] for i in self.ix])
|
||||
|
||||
def add_dendrites(self):
|
||||
"""
|
||||
Add simple unbranched dendrite.
|
||||
The dendrites have some kd, kif and ih current
|
||||
"""
|
||||
nDend = range(2) # these will be simple, unbranced, N=4 dendrites
|
||||
dendrites = []
|
||||
for i in nDend:
|
||||
dendrites.append(h.Section(cell=self.soma))
|
||||
for i in nDend:
|
||||
dendrites[i].connect(self.soma)
|
||||
dendrites[i].L = 250 # length of the dendrite (not tapered)
|
||||
dendrites[i].diam = 1
|
||||
dendrites[i].cm = self.c_m
|
||||
# h('dendrites[i].diam(0:1) = 2:1') # dendrite diameter, with tapering
|
||||
dendrites[i].nseg = 21 # # segments in dendrites
|
||||
dendrites[i].Ra = 150 # ohm.cm
|
||||
dendrites[i].insert("napyr")
|
||||
dendrites[i]().napyr.gbar = 0.00
|
||||
dendrites[i].insert("kdpyr")
|
||||
dendrites[i]().kdpyr.gbar = 0.002 # a little Ht
|
||||
dendrites[i].insert("kif")
|
||||
dendrites[i]().kif.gbar = 0.0001 # a little Ht
|
||||
dendrites[i].insert("leak") # leak
|
||||
dendrites[i]().leak.gbar = 0.00001
|
||||
dendrites[i].insert("ihpyr_adj") # some H current
|
||||
# mechanism missing so the ihvcn mechanism need to be inserted
|
||||
dendrites[i].insert('ihvcn')
|
||||
dendrites[i]().ihvcn.gbar = 0.0 # 0.00002
|
||||
dendrites[i]().ihvcn.eh = -43.0
|
||||
self.maindend = dendrites
|
||||
self.status["dendrites"] = True
|
||||
self.add_section(self.maindend, "maindend")
|
||||
467
cnmodel/cells/sgc.py
Normal file
467
cnmodel/cells/sgc.py
Normal file
@@ -0,0 +1,467 @@
|
||||
from __future__ import print_function
|
||||
from neuron import h
|
||||
from ..util import nstomho
|
||||
from ..util import Params
|
||||
import numpy as np
|
||||
from .cell import Cell
|
||||
from .. import synapses
|
||||
from .. import an_model
|
||||
from .. import data
|
||||
|
||||
__all__ = ["SGC", "SGC_TypeI", "DummySGC"]
|
||||
|
||||
|
||||
class SGC(Cell):
|
||||
type = "sgc"
|
||||
|
||||
@classmethod
|
||||
def create(cls, model="I", species="mouse", **kwds):
|
||||
if model == "dummy":
|
||||
return DummySGC(**kwds)
|
||||
elif model == "I":
|
||||
return SGC_TypeI(species=species, **kwds)
|
||||
else:
|
||||
raise ValueError("SGC model %s is unknown", model)
|
||||
|
||||
def __init__(self, cf=None, sr=None):
|
||||
Cell.__init__(self)
|
||||
self._cf = cf
|
||||
self._sr = sr
|
||||
self.spike_source = None # used by DummySGC to connect VecStim to terminal
|
||||
|
||||
@property
|
||||
def cf(self):
|
||||
""" Center frequency
|
||||
"""
|
||||
return self._cf
|
||||
|
||||
@property
|
||||
def sr(self):
|
||||
""" Spontaneous rate group. 1=low, 2=mid, 3=high
|
||||
"""
|
||||
return self._sr
|
||||
|
||||
def make_terminal(self, post_cell, term_type, **kwds):
|
||||
"""Create a StochasticTerminal and configure it according to the
|
||||
postsynaptic cell type.
|
||||
"""
|
||||
pre_sec = self.soma
|
||||
|
||||
# Return a simple terminal unless a stochastic terminal was requested.
|
||||
if term_type == "simple":
|
||||
return synapses.SimpleTerminal(
|
||||
pre_sec, post_cell, spike_source=self.spike_source, **kwds
|
||||
)
|
||||
elif term_type == "multisite":
|
||||
n_rsites = data.get(
|
||||
"sgc_synapse",
|
||||
species="mouse",
|
||||
post_type=post_cell.type,
|
||||
field="n_rsites",
|
||||
)
|
||||
opts = {"nzones": n_rsites, "delay": 0, "dep_flag": 1}
|
||||
opts.update(kwds)
|
||||
# when created, depflag is set True (1) so that we compute the DKR D*F to get release
|
||||
# this can be modified prior to the run by setting the terminal(s) so that dep_flag is 0
|
||||
# (no DKR: constant release probability)
|
||||
term = synapses.StochasticTerminal(
|
||||
pre_sec, post_cell, spike_source=self.spike_source, **opts
|
||||
)
|
||||
|
||||
kinetics = data.get(
|
||||
"sgc_ampa_kinetics",
|
||||
species="mouse",
|
||||
post_type=post_cell.type,
|
||||
field=["tau_g", "amp_g"],
|
||||
)
|
||||
term.set_params(**kinetics)
|
||||
dynamics = data.get(
|
||||
"sgc_release_dynamics",
|
||||
species="mouse",
|
||||
post_type=post_cell.type,
|
||||
field=["F", "k0", "kmax", "kd", "kf", "taud", "tauf", "dD", "dF"],
|
||||
)
|
||||
term.set_params(**dynamics)
|
||||
return term
|
||||
else:
|
||||
raise ValueError("Unsupported terminal type %s" % term_type)
|
||||
|
||||
|
||||
class DummySGC(SGC):
|
||||
""" SGC class with no cell body; this cell only replays a predetermined
|
||||
spike train.
|
||||
"""
|
||||
|
||||
def __init__(self, cf=None, sr=None, simulator=None):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
cf : float (default: None)
|
||||
Required: the characteristic frequency for the SGC
|
||||
|
||||
sr : int (default None)
|
||||
required : Selects the spontaneous rate group from the
|
||||
Zilany et al (2010) model. 1 = LSR, 2 = MSR, 3 = HSR
|
||||
|
||||
simulator : 'cochlea' | 'matlab' | None (default None)
|
||||
Sets the simulator interface that will be used. All models
|
||||
currently use the Zilany et al. model, but the simulator can
|
||||
be run though a Python-interface directly to the Matlab code
|
||||
as publicy available, (simulator='matlab'), or can be run through
|
||||
Rudnicki & Hemmert's Python interface to the simulator's C code
|
||||
(simulator='cochlea').
|
||||
|
||||
"""
|
||||
self._simulator = simulator
|
||||
SGC.__init__(self, cf, sr)
|
||||
self.vecstim = h.VecStim()
|
||||
|
||||
# this causes the terminal to receive events from the VecStim:
|
||||
self.spike_source = self.vecstim
|
||||
|
||||
# just an empty section for holding the terminal
|
||||
self.add_section(h.Section(), "soma")
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": None,
|
||||
"species": None,
|
||||
"modelType": "dummy",
|
||||
"ttx": False,
|
||||
"name": "DummysGC",
|
||||
"morphology": None,
|
||||
"decorator": None,
|
||||
"temperature": None,
|
||||
}
|
||||
|
||||
def set_spiketrain(self, times):
|
||||
""" Set the times of spikes (in seconds) to be replayed by the cell.
|
||||
"""
|
||||
self._spiketrain = times
|
||||
self._stvec = h.Vector(times)
|
||||
self.vecstim.play(self._stvec)
|
||||
|
||||
def set_sound_stim(self, stim, seed, simulator=None):
|
||||
""" Set the sound stimulus used to generate this cell's spike train.
|
||||
"""
|
||||
self._sound_stim = stim
|
||||
spikes = self.generate_spiketrain(stim, seed, simulator)
|
||||
self.set_spiketrain(spikes)
|
||||
|
||||
def generate_spiketrain(self, stim, seed, simulator=None):
|
||||
if simulator is None:
|
||||
simulator = self._simulator
|
||||
spikes = an_model.get_spiketrain(
|
||||
cf=self.cf, sr=self.sr, seed=seed, stim=stim, simulator=simulator
|
||||
)
|
||||
return spikes * 1000
|
||||
|
||||
|
||||
class SGC_TypeI(SGC):
|
||||
"""
|
||||
Spiral ganglion cell model
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach=None,
|
||||
ttx=False,
|
||||
species="guineapig",
|
||||
modelType="bm",
|
||||
cf=None,
|
||||
sr=None,
|
||||
debug=False,
|
||||
):
|
||||
"""
|
||||
Initialize a spiral ganglion Type I cell, based on a bushy cell model.
|
||||
Modifications to the cell can be made by calling the methods below. These include
|
||||
converting to a model with modified size and conductances (experimental), and
|
||||
and changing the sodium channel conductances.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
a file name to read the cell morphology from. If a valid file is found, a cell is constructed
|
||||
as a cable model from the hoc file.
|
||||
If None (default), the only a point model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels aer inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: 'na')
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanim
|
||||
by that name must exist. The default is jsrna (Rothman et al., 1993)
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
Currently, this is not implemented.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the channel density that will be inserted for different models. Note that
|
||||
if a decorator function is specified, this argument is ignored.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the type of the model that will be used. SGC model know about "a" (apical)
|
||||
and "bm" (basal-middle) models, based on Liu et al., JARO, 2014.
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point models.
|
||||
|
||||
cf : float (default: None)
|
||||
The CF for the auditory nerve fiber that this SGC represents.
|
||||
|
||||
sr : string (default: None)
|
||||
The spontaneous rate group to which this fiber belongs. "LS", "MS", and "HS" are known values.
|
||||
|
||||
debug: boolean (default: False)
|
||||
debug is a boolean flag. When set, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
"""
|
||||
|
||||
super(SGC_TypeI, self).__init__(cf=cf, sr=sr)
|
||||
if modelType == None:
|
||||
modelType = "bm" # modelTypes are: a (apical), bm (basal middle)
|
||||
if nach == None:
|
||||
nach = "jsrna"
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "SGC",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": None,
|
||||
}
|
||||
|
||||
self.i_test_range = {
|
||||
"pulse": [(-0.3, 0.3, 0.02), (-0.03, 0.0, 0.005)]
|
||||
} # include finer range as well
|
||||
self.vrange = [-75.0, -55.0]
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
soma = h.Section(
|
||||
name="SGC_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
self.mechanisms = [nach, "klt", "kht", "leak"]
|
||||
if modelType == "a":
|
||||
self.mechanisms.append("ihsgcApical")
|
||||
elif modelType == "bm":
|
||||
self.mechanisms.append("ihsgcBasalMiddle")
|
||||
else:
|
||||
raise ValueError("Type %s not known for SGC model" % modelType)
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.soma.ek = self.e_k
|
||||
self.soma().leak.erev = self.e_leak
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # set the default type II cell parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
if debug:
|
||||
print("<< SGC: Spiral Ganglion Cell created >>")
|
||||
|
||||
def get_cellpars(self, dataset, species="guineapig", celltype="sgc-a"):
|
||||
cellcap = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_Cap"
|
||||
)
|
||||
chtype = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_na_type"
|
||||
)
|
||||
pars = Params(soma_Cap=cellcap, natype=chtype)
|
||||
for g in [
|
||||
"soma_na_gbar",
|
||||
"soma_kht_gbar",
|
||||
"soma_klt_gbar",
|
||||
"soma_ihap_gbar",
|
||||
"soma_ihbm_gbar",
|
||||
"soma_ihap_eh",
|
||||
"soma_ihbm_eh",
|
||||
"soma_leak_gbar",
|
||||
"soma_leak_erev",
|
||||
"soma_e_k",
|
||||
"soma_e_na",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, cell_type=celltype, field=g)
|
||||
)
|
||||
return pars
|
||||
|
||||
def species_scaling(self, silent=True, species="guineapig", modelType="a"):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
Used ONLY for point models.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be one of mouse or guineapig
|
||||
|
||||
modelType: string (default: 'a')
|
||||
definition of HCN model type from Liu et al. JARO 2014:
|
||||
'a' for apical model
|
||||
'bm' for basal-middle model
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
Notes
|
||||
-----
|
||||
The 'guineapig' model uses the mouse HCN channel model, verbatim. This may not
|
||||
be appropriate, given that the other conductances are scaled up.
|
||||
|
||||
"""
|
||||
|
||||
soma = self.soma
|
||||
if modelType == "a":
|
||||
celltype = "sgc-a"
|
||||
elif modelType == "bm":
|
||||
celltype = "sgc-bm"
|
||||
else:
|
||||
raise ValueError("SGC: unrecognized model type %s " % modelType)
|
||||
|
||||
if species == "mouse":
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
par = self.get_cellpars(
|
||||
"sgc_mouse_channels", species=species, celltype=celltype
|
||||
)
|
||||
elif species == "guineapig":
|
||||
# guinea pig data from Rothman and Manis, 2003, modelType II
|
||||
self._valid_temperatures = (22.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(22.0)
|
||||
par = self.get_cellpars(
|
||||
"sgc_guineapig_channels", species=species, celltype=celltype
|
||||
)
|
||||
|
||||
self.set_soma_size_from_Cm(par.soma_Cap)
|
||||
self.adjust_na_chans(soma, gbar=par.soma_na_gbar)
|
||||
soma().kht.gbar = nstomho(par.soma_kht_gbar, self.somaarea)
|
||||
soma().klt.gbar = nstomho(par.soma_klt_gbar, self.somaarea)
|
||||
if celltype == "sgc-a":
|
||||
soma().ihsgcApical.gbar = nstomho(par.soma_ihap_gbar, self.somaarea)
|
||||
soma().ihsgcApical.eh = par.soma_ihap_eh
|
||||
elif celltype == "sgc-bm":
|
||||
soma().ihsgcBasalMiddle.gbar = nstomho(par.soma_ihbm_gbar, self.somaarea)
|
||||
soma().ihsgcBasalMiddle.eh = par.soma_ihbm_eh
|
||||
else:
|
||||
raise ValueError(
|
||||
"Ihsgc modelType %s not recognized for species %s" % (celltype, species)
|
||||
)
|
||||
soma().leak.gbar = nstomho(par.soma_leak_gbar, self.somaarea)
|
||||
soma().leak.erev = par.soma_leak_erev
|
||||
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
self.check_temperature()
|
||||
if not silent:
|
||||
print("set cell as: ", species)
|
||||
print(" with Vm rest = %f" % self.vm0)
|
||||
|
||||
def adjust_na_chans(self, soma, gbar=1000.0, debug=False):
|
||||
"""
|
||||
adjust the sodium channel conductance
|
||||
:param soma: a soma object whose sodium channel complement will have it's
|
||||
conductances adjusted depending on the channel type
|
||||
:return nothing:
|
||||
"""
|
||||
if self.status["ttx"]:
|
||||
gnabar = 0.0
|
||||
else:
|
||||
gnabar = nstomho(gbar, self.somaarea)
|
||||
nach = self.status["na"]
|
||||
if nach == "jsrna":
|
||||
soma().jsrna.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("jsrna gbar: ", soma().jsrna.gbar)
|
||||
elif nach == "nav11":
|
||||
soma().nav11.gbar = gnabar * 0.5
|
||||
soma.ena = self.e_na
|
||||
soma().nav11.vsna = 4.3
|
||||
if debug:
|
||||
print("sgc using inva11")
|
||||
print("nav11 gbar: ", soma().nav11.gbar)
|
||||
elif nach in ["na", "nacn"]:
|
||||
soma().na.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("na gbar: ", soma().na.gbar)
|
||||
else:
|
||||
raise ValueError("Sodium channel %s is not recognized for SGC cells", nach)
|
||||
|
||||
def i_currents(self, V):
|
||||
"""
|
||||
For the steady-state case, return the total current at voltage V
|
||||
Used to find the zero current point
|
||||
vrange brackets the interval
|
||||
Implemented here are the basic RM03 mechanisms
|
||||
This function should be replaced for specific cell types.
|
||||
"""
|
||||
for part in self.all_sections.keys():
|
||||
for sec in self.all_sections[part]:
|
||||
sec.v = V
|
||||
|
||||
h.t = 0.0
|
||||
h.celsius = self.status["temperature"]
|
||||
h.finitialize()
|
||||
self.ix = {}
|
||||
if "na" in self.mechanisms:
|
||||
# print dir(self.soma().na)
|
||||
self.ix["na"] = self.soma().na.gna * (V - self.soma().ena)
|
||||
if "jsrna" in self.mechanisms:
|
||||
# print dir(self.soma().na)
|
||||
self.ix["jsrna"] = self.soma().jsrna.gna * (V - self.soma().ena)
|
||||
if "klt" in self.mechanisms:
|
||||
self.ix["klt"] = self.soma().klt.gklt * (V - self.soma().ek)
|
||||
if "kht" in self.mechanisms:
|
||||
self.ix["kht"] = self.soma().kht.gkht * (V - self.soma().ek)
|
||||
if "ihsgcApical" in self.mechanisms:
|
||||
self.ix["ihsgcApical"] = self.soma().ihsgcApical.gh * (
|
||||
V - self.soma().ihsgcApical.eh
|
||||
)
|
||||
if "ihsgcBasalMiddle" in self.mechanisms:
|
||||
self.ix["ihsgcBasalMiddle"] = self.soma().ihsgcBasalMiddle.gh * (
|
||||
V - self.soma().ihsgcBasalMiddle.eh
|
||||
)
|
||||
if "leak" in self.mechanisms:
|
||||
self.ix["leak"] = self.soma().leak.gbar * (V - self.soma().leak.erev)
|
||||
# print self.status['name'], self.status['type'], V, self.ix
|
||||
return np.sum([self.ix[i] for i in self.ix])
|
||||
3
cnmodel/cells/tests/cell_data/SGC_rat_a.pk
Normal file
3
cnmodel/cells/tests/cell_data/SGC_rat_a.pk
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2e60518d0332cd475f67e13e8f85e23b1b60dda4f252620b495bdfbc5dab43fe
|
||||
size 7826
|
||||
3
cnmodel/cells/tests/cell_data/SGC_rat_bm.pk
Normal file
3
cnmodel/cells/tests/cell_data/SGC_rat_bm.pk
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f0814086d71479adab9326978620e1af0ed153fdfc2c6f4fa0d2213c0b80131b
|
||||
size 7729
|
||||
3
cnmodel/cells/tests/cell_data/bushy-mouse-typeII.pk
Normal file
3
cnmodel/cells/tests/cell_data/bushy-mouse-typeII.pk
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5dbd4717983175a81d362bd01015cb28baa145d78c6c460dd7ec6456f9f46e72
|
||||
size 8103
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:34fbddf52a61283bd29622fe87e1fc8afc6f46160cdce3f0cdd581f89bfeba35
|
||||
size 7963
|
||||
3
cnmodel/cells/tests/cell_data/bushy_guineapig-typeII.pk
Normal file
3
cnmodel/cells/tests/cell_data/bushy_guineapig-typeII.pk
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:de245b95e0b1f66680ed1f79bc31739bce36aed9edd044d02b6effbd645e948e
|
||||
size 8160
|
||||
3
cnmodel/cells/tests/cell_data/cartwheel_rat_I.pk
Normal file
3
cnmodel/cells/tests/cell_data/cartwheel_rat_I.pk
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0f7c79982ffa921ba17690de6b31ff27be75936acde0fa72b5d52e0e4abc54da
|
||||
size 5506
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:de64e933070f7c216d8f632cb56ee32b346bba282c24f453f818c686439b772a
|
||||
size 8710
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0e713ac67a7211e4d78c846bd8bdda4b738c49d5c50fb61c1974f12d45341937
|
||||
size 9506
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e86a6fb8651d0ed0a33e30273d49b8358436bf169899ee9d2bcda454f450225e
|
||||
size 7747
|
||||
3
cnmodel/cells/tests/cell_data/pyramidal_rat_I.pk
Normal file
3
cnmodel/cells/tests/cell_data/pyramidal_rat_I.pk
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8ebe0523b9260f3b9a87fc6e535f38cb8f0b5840aea056fe8764943883782db7
|
||||
size 16581
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a2536a5ca43d2f46fa6e6bf786d520ac12815b742896a3272a227660a91fc2c1
|
||||
size 7863
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fa5ddc40011269d7e4d00d70ac3053bd4d2d88293db5f8d6f9ae8225c3ed1bdc
|
||||
size 8182
|
||||
3
cnmodel/cells/tests/cell_data/tstellate_mouse-typeI-c.pk
Normal file
3
cnmodel/cells/tests/cell_data/tstellate_mouse-typeI-c.pk
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2990652711db28fa846886f1399faecb4d4680fd8014cbc006636c215248263d
|
||||
size 14815
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9f50fb610552b181dfd0130245ee41bcbe745d4fc856abfe7f5ad180e84773a5
|
||||
size 13267
|
||||
227
cnmodel/cells/tests/test_cells.py
Normal file
227
cnmodel/cells/tests/test_cells.py
Normal file
@@ -0,0 +1,227 @@
|
||||
import os, pickle, pprint
|
||||
import numpy as np
|
||||
import neuron
|
||||
|
||||
import cnmodel
|
||||
import cnmodel.cells as cells
|
||||
from cnmodel.util import UserTester, reset
|
||||
from cnmodel.protocols import IVCurve
|
||||
|
||||
"""
|
||||
Cell-type tests
|
||||
"""
|
||||
|
||||
|
||||
def test_bushy():
|
||||
reset(raiseError=False)
|
||||
cell = cells.Bushy.create(species="guineapig", modelType="II")
|
||||
CellTester("bushy_guineapig-typeII", cell)
|
||||
|
||||
|
||||
def test_bushy21():
|
||||
reset(raiseError=False)
|
||||
cell = cells.Bushy.create(species="guineapig", modelType="II-I")
|
||||
CellTester("bushy_guineapig-typeII-I", cell)
|
||||
|
||||
|
||||
def test_bushy_mouse():
|
||||
reset(raiseError=False)
|
||||
cell = cells.Bushy.create(species="mouse", modelType="II")
|
||||
CellTester("bushy-mouse-typeII", cell)
|
||||
|
||||
|
||||
def test_tstellate():
|
||||
reset(raiseError=False)
|
||||
cell = cells.TStellate.create(species="guineapig", modelType="I-c")
|
||||
CellTester("tstellate_guineapig-typeI-c", cell)
|
||||
|
||||
|
||||
def test_tstellate_mouse():
|
||||
reset(raiseError=False)
|
||||
cell = cells.TStellate.create(species="mouse", modelType="I-c")
|
||||
CellTester("tstellate_mouse-typeI-c", cell)
|
||||
|
||||
|
||||
def test_tstellatet():
|
||||
reset(raiseError=False)
|
||||
cell = cells.TStellate.create(species="guineapig", modelType="I-t")
|
||||
CellTester("tstellate_guineapig-typeI-t", cell)
|
||||
|
||||
|
||||
# not implemented yet
|
||||
# def test_tstellatet_mouse():
|
||||
# reset(raiseError=False)
|
||||
# cell = cells.TStellate.create(species='mouse', modelType='I-t')
|
||||
# CellTester('tstellate_mouse-typeI-t', cell)
|
||||
|
||||
|
||||
def test_dstellate():
|
||||
reset(raiseError=False)
|
||||
cell = cells.DStellate.create(species="guineapig", modelType="I-II")
|
||||
CellTester("dstellate_guineapig-typeI-II", cell)
|
||||
|
||||
|
||||
def test_dstellate_mouse():
|
||||
reset(raiseError=False)
|
||||
cell = cells.DStellate.create(species="mouse", modelType="I-II")
|
||||
CellTester("dstellate_mouse-typeI-II", cell)
|
||||
|
||||
|
||||
def test_octopus():
|
||||
reset(raiseError=False)
|
||||
cell = cells.Octopus.create(species="guineapig", modelType="II-o")
|
||||
CellTester("octopus_guineapig-typeII-o", cell)
|
||||
|
||||
|
||||
def test_pyramidal():
|
||||
reset(raiseError=False)
|
||||
cell = cells.Pyramidal.create(species="rat", modelType="I")
|
||||
CellTester("pyramidal_rat_I", cell)
|
||||
|
||||
|
||||
def test_tuberculoventral():
|
||||
reset(raiseError=False)
|
||||
cell = cells.Tuberculoventral.create(species="mouse", modelType="TVmouse")
|
||||
CellTester("tuberculoventral_mouse_I", cell)
|
||||
|
||||
|
||||
def test_cartwheel():
|
||||
reset(raiseError=False)
|
||||
cell = cells.Cartwheel.create(species="mouse", modelType="I")
|
||||
CellTester("cartwheel_rat_I", cell)
|
||||
|
||||
|
||||
def test_sgc_basal_middle():
|
||||
reset(raiseError=False)
|
||||
cell = cells.SGC.create(species="mouse", modelType="bm")
|
||||
CellTester("SGC_rat_bm", cell)
|
||||
|
||||
|
||||
def test_sgc_apical():
|
||||
reset(raiseError=False)
|
||||
cell = cells.SGC.create(species="mouse", modelType="a")
|
||||
CellTester("SGC_rat_a", cell)
|
||||
|
||||
|
||||
#
|
||||
# Supporting functions
|
||||
#
|
||||
|
||||
|
||||
class CellTester(UserTester):
|
||||
data_dir = "cell_data"
|
||||
|
||||
def run_test(self, cell):
|
||||
# run I/V test on cell
|
||||
V0 = cell.find_i0(showinfo=True)
|
||||
rmrintau = cell.compute_rmrintau(auto_initialize=False, vrange=None)
|
||||
iv = IVCurve()
|
||||
self.iv = iv
|
||||
iv.run(cell.i_test_range, cell)
|
||||
if self.audit:
|
||||
iv.show(cell)
|
||||
|
||||
info = dict(
|
||||
temp=iv.temp,
|
||||
icmd=iv.current_cmd,
|
||||
spikes=iv.spike_times(),
|
||||
rmp=iv.rest_vm(),
|
||||
rm_taum=iv.input_resistance_tau(),
|
||||
vpeak=iv.peak_vm(),
|
||||
vss=iv.steady_vm(),
|
||||
rmrintau=rmrintau,
|
||||
)
|
||||
return info
|
||||
|
||||
def assert_test_info(self, *args, **kwds):
|
||||
try:
|
||||
super(CellTester, self).assert_test_info(*args, **kwds)
|
||||
finally:
|
||||
if hasattr(self, "iv") and hasattr(self.iv, "win"):
|
||||
self.iv.win.hide()
|
||||
|
||||
|
||||
# def result_file(key):
|
||||
# """
|
||||
# Return a file name to be used for storing / retrieving test results
|
||||
# given *key*.
|
||||
# """
|
||||
# path = os.path.dirname(__file__)
|
||||
# return os.path.join(path, 'cell_data', key + '.pk')
|
||||
|
||||
# def load_cell_info(key):
|
||||
# """
|
||||
# Load prior test results for *key*.
|
||||
# If there are no prior results, return None.
|
||||
# """
|
||||
# fn = result_file(key)
|
||||
# if os.path.isfile(fn):
|
||||
# return pickle.load(open(fn, 'rb'))
|
||||
# return None
|
||||
|
||||
# def save_cell_info(info, key):
|
||||
# """
|
||||
# Store test results for *key*.
|
||||
# """
|
||||
# fn = result_file(key)
|
||||
# dirname = os.path.dirname(fn)
|
||||
# if not os.path.isdir(dirname):
|
||||
# os.mkdir(dirname)
|
||||
# pickle.dump(info, open(fn, 'wb'))
|
||||
|
||||
|
||||
# The following is superseeded by the built in unit tests.
|
||||
# def CellTester(key):
|
||||
# """
|
||||
# Test *cell* and raise exception if the results do not match prior
|
||||
# data.
|
||||
# """
|
||||
# audit = cnmodel.AUDIT_TESTS
|
||||
|
||||
## run I/V test on cell
|
||||
# iv = IVCurve()
|
||||
# iv.run(cell.i_test_range, cell)
|
||||
# iv.show(cell)
|
||||
|
||||
# try:
|
||||
# info = dict(
|
||||
# icmd=iv.current_cmd,
|
||||
# spikes=iv.spike_times(),
|
||||
# rmp=iv.rest_vm(),
|
||||
# rm=iv.input_resistance(),
|
||||
# vpeak=iv.peak_vm(),
|
||||
# vss=iv.steady_vm(),
|
||||
# )
|
||||
|
||||
# expect = load_cell_info(key)
|
||||
|
||||
# if expect is not None:
|
||||
|
||||
## Check test structures are the same
|
||||
# assert len(info) == len(expect)
|
||||
# for k in info:
|
||||
# assert k in expect
|
||||
|
||||
## Check data matches
|
||||
# for k in info:
|
||||
# if isinstance(info[k], list):
|
||||
# assert len(info[k]) == len(expect[k])
|
||||
# for i in range(len(info[k])):
|
||||
# assert np.allclose(info[k][i], expect[k][i])
|
||||
# else:
|
||||
# assert np.allclose(info[k], expect[k])
|
||||
# else:
|
||||
# if not audit:
|
||||
# raise Exception("No prior test results for cell type '%s'. "
|
||||
# "Run test.py --audit store new test data." % key)
|
||||
|
||||
# print "\n=== New test results for %s: ===\n" % key
|
||||
# pprint.pprint(info)
|
||||
# print "Store new test results? [y/n]",
|
||||
# yn = raw_input()
|
||||
# if yn.lower().startswith('y'):
|
||||
# save_cell_info(info, key)
|
||||
# else:
|
||||
# raise Exception("Rejected test results for '%s'" % key)
|
||||
# finally:
|
||||
# iv.win.hide()
|
||||
1089
cnmodel/cells/tstellate.py
Normal file
1089
cnmodel/cells/tstellate.py
Normal file
File diff suppressed because it is too large
Load Diff
619
cnmodel/cells/tuberculoventral.py
Normal file
619
cnmodel/cells/tuberculoventral.py
Normal file
@@ -0,0 +1,619 @@
|
||||
from __future__ import print_function
|
||||
from neuron import h
|
||||
import numpy as np
|
||||
|
||||
# import neuron as nrn
|
||||
|
||||
from .cell import Cell
|
||||
from .. import synapses
|
||||
from ..util import nstomho
|
||||
from ..util import Params
|
||||
from .. import data
|
||||
|
||||
__all__ = ["Tuberculoventral"]
|
||||
|
||||
|
||||
class Tuberculoventral(Cell):
|
||||
|
||||
type = "tuberculoventral"
|
||||
|
||||
@classmethod
|
||||
def create(cls, model="TVmouse", **kwds):
|
||||
if model in ["TVmouse", "I"]:
|
||||
return Tuberculoventral(**kwds)
|
||||
elif model == "dummy":
|
||||
return DummyTuberculoventral(**kwds)
|
||||
else:
|
||||
raise ValueError("Tuberculoventral type %s is unknown", model)
|
||||
|
||||
def __init__(self):
|
||||
Cell.__init__(self)
|
||||
self.spike_source = (
|
||||
None
|
||||
) # used by DummyTuberculoventral to connect VecStim to terminal
|
||||
|
||||
def make_psd(self, terminal, psd_type, **kwds):
|
||||
"""
|
||||
Connect a presynaptic terminal to one post section at the specified location, with the fraction
|
||||
of the "standard" conductance determined by gbar.
|
||||
The default condition is to try to pass the default unit test (loc=0.5)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
terminal : Presynaptic terminal (NEURON object)
|
||||
|
||||
psd_type : either simple or multisite PSD for bushy cell
|
||||
|
||||
kwds: dict of options. Two are currently handled:
|
||||
postsize : expect a list consisting of [sectionno, location (float)]
|
||||
AMPAScale : float to scale the ampa currents
|
||||
|
||||
"""
|
||||
if (
|
||||
"postsite" in kwds
|
||||
): # use a defined location instead of the default (soma(0.5)
|
||||
postsite = kwds["postsite"]
|
||||
loc = postsite[1] # where on the section?
|
||||
uname = (
|
||||
"sections[%d]" % postsite[0]
|
||||
) # make a name to look up the neuron section object
|
||||
post_sec = self.hr.get_section(uname) # Tell us where to put the synapse.
|
||||
else:
|
||||
loc = 0.5
|
||||
post_sec = self.soma
|
||||
|
||||
if psd_type == "simple":
|
||||
if terminal.cell.type in ["sgc", "dstellate", "tuberculoventral"]:
|
||||
weight = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="weight",
|
||||
)
|
||||
tau1 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau1",
|
||||
)
|
||||
tau2 = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="tau2",
|
||||
)
|
||||
erev = data.get(
|
||||
"%s_synapse" % terminal.cell.type,
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="erev",
|
||||
)
|
||||
return self.make_exp2_psd(
|
||||
post_sec,
|
||||
terminal,
|
||||
weight=weight,
|
||||
loc=loc,
|
||||
tau1=tau1,
|
||||
tau2=tau2,
|
||||
erev=erev,
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make simple PSD for %s => %s"
|
||||
% (terminal.cell.type, self.type)
|
||||
)
|
||||
|
||||
elif psd_type == "multisite":
|
||||
if terminal.cell.type == "sgc":
|
||||
# Max conductances for the glu mechanisms are calibrated by
|
||||
# running `synapses/tests/test_psd.py`. The test should fail
|
||||
# if these values are incorrect
|
||||
self.AMPAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="AMPAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.NMDAR_gmax = (
|
||||
data.get(
|
||||
"sgc_synapse",
|
||||
species=self.species,
|
||||
post_type=self.type,
|
||||
field="NMDAR_gmax",
|
||||
)
|
||||
* 1e3
|
||||
)
|
||||
self.Pr = data.get(
|
||||
"sgc_synapse", species=self.species, post_type=self.type, field="Pr"
|
||||
)
|
||||
# adjust gmax to correct for initial Pr
|
||||
self.AMPAR_gmax = self.AMPAR_gmax / self.Pr
|
||||
self.NMDAR_gmax = self.NMDAR_gmax / self.Pr
|
||||
if "AMPAScale" in kwds:
|
||||
self.AMPA_gmax = (
|
||||
self.AMPA_gmax * kwds["AMPAScale"]
|
||||
) # allow scaling of AMPA conductances
|
||||
if "NMDAScale" in kwds:
|
||||
self.NMDA_gmax = self.NMDA_gmax * kwds["NMDAScale"]
|
||||
return self.make_glu_psd(
|
||||
post_sec, terminal, self.AMPAR_gmax, self.NMDAR_gmax, loc=loc
|
||||
)
|
||||
elif terminal.cell.type == "dstellate": # WBI input -Voigt, Nelken, Young
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyfast", loc=loc)
|
||||
elif (
|
||||
terminal.cell.type == "tuberculoventral"
|
||||
): # TV cells talk to each other-Kuo et al.
|
||||
return self.make_gly_psd(post_sec, terminal, psdtype="glyfast", loc=loc)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Cannot make PSD for %s => %s" % (terminal.cell.type, self.type)
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported psd type %s" % psd_type)
|
||||
|
||||
def make_terminal(self, post_cell, term_type, **kwds):
|
||||
pre_sec = self.soma
|
||||
if term_type == "simple":
|
||||
return synapses.SimpleTerminal(
|
||||
pre_sec, post_cell, spike_source=self.spike_source, **kwds
|
||||
)
|
||||
elif term_type == "multisite":
|
||||
if post_cell.type in [
|
||||
"dstellate",
|
||||
"tuberculoventral",
|
||||
"pyramidal",
|
||||
"bushy",
|
||||
"tstellate",
|
||||
]:
|
||||
nzones = data.get(
|
||||
"tuberculoventral_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="n_rsites",
|
||||
)
|
||||
delay = data.get(
|
||||
"tuberculoventral_synapse",
|
||||
species=self.species,
|
||||
post_type=post_cell.type,
|
||||
field="delay",
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"No knowledge as to how to connect tuberculoventral cell to cell type %s"
|
||||
% type(post_cell)
|
||||
)
|
||||
pre_sec = self.soma
|
||||
return synapses.StochasticTerminal(
|
||||
pre_sec,
|
||||
post_cell,
|
||||
nzones=nzones,
|
||||
spike_source=self.spike_source,
|
||||
delay=delay,
|
||||
**kwds
|
||||
)
|
||||
else:
|
||||
raise ValueError("Unsupported terminal type %s" % term_type)
|
||||
|
||||
|
||||
class Tuberculoventral(Tuberculoventral):
|
||||
"""
|
||||
Tuberculoventral Neuron (DCN) base model
|
||||
Adapted from T-stellate model, using target parameters from Kuo et al. J. Neurophys. 2012
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
morphology=None,
|
||||
decorator=None,
|
||||
nach=None,
|
||||
ttx=False,
|
||||
species="mouse",
|
||||
modelType=None,
|
||||
debug=False,
|
||||
):
|
||||
"""
|
||||
Initialize a DCN Tuberculoventral cell, using the default parameters for guinea pig from
|
||||
R&M2003, as a type I cell.
|
||||
Modifications to the cell can be made by calling methods below. These include:
|
||||
Converting to a type IA model (add transient K current) (species: guineapig-TypeIA).
|
||||
Changing "species" to mouse or cat (scales conductances)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
morphology : string (default: None)
|
||||
a file name to read the cell morphology from. If a valid file is found, a cell is constructed
|
||||
as a cable model from the hoc file.
|
||||
If None (default), the only a point model is made, exactly according to RM03.
|
||||
|
||||
decorator : Python function (default: None)
|
||||
decorator is a function that "decorates" the morphology with ion channels according
|
||||
to a set of rules.
|
||||
If None, a default set of channels aer inserted into the first soma section, and the
|
||||
rest of the structure is "bare".
|
||||
|
||||
nach : string (default: 'na')
|
||||
nach selects the type of sodium channel that will be used in the model. A channel mechanims
|
||||
by that name must exist.
|
||||
|
||||
ttx : Boolean (default: False)
|
||||
If ttx is True, then the sodium channel conductance is set to 0 everywhere in the cell.
|
||||
Currently, this is not implemented.
|
||||
|
||||
species: string (default 'guineapig')
|
||||
species defines the channel density that will be inserted for different models. Note that
|
||||
if a decorator function is specified, this argument is ignored.
|
||||
|
||||
modelType: string (default: None)
|
||||
modelType specifies the type of the model that will be used (e.g., "II", "II-I", etc).
|
||||
modelType is passed to the decorator, or to species_scaling to adjust point models.
|
||||
|
||||
debug: boolean (default: False)
|
||||
debug is a boolean flag. When set, there will be multiple printouts of progress and parameters.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
super(Tuberculoventral, self).__init__()
|
||||
if modelType == None:
|
||||
modelType = "TVmouse"
|
||||
if nach == None:
|
||||
nach = "nacncoop"
|
||||
self.debug = debug
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": nach,
|
||||
"species": species,
|
||||
"modelType": modelType,
|
||||
"ttx": ttx,
|
||||
"name": "Tuberculoventral",
|
||||
"morphology": morphology,
|
||||
"decorator": decorator,
|
||||
"temperature": None,
|
||||
}
|
||||
|
||||
self.i_test_range = {"pulse": [(-0.35, 1.0, 0.05), (-0.04, 0.01, 0.01)]}
|
||||
self.vrange = [-80.0, -60.0] # set a default vrange for searching for rmp
|
||||
|
||||
if morphology is None:
|
||||
"""
|
||||
instantiate a basic soma-only ("point") model
|
||||
"""
|
||||
if self.debug:
|
||||
print("<< Tuberculoventral model: Creating point cell >>")
|
||||
soma = h.Section(
|
||||
name="Tuberculoventral_Soma_%x" % id(self)
|
||||
) # one compartment of about 29000 um2
|
||||
soma.nseg = 1
|
||||
self.add_section(soma, "soma")
|
||||
else:
|
||||
"""
|
||||
instantiate a structured model with the morphology as specified by
|
||||
the morphology file
|
||||
"""
|
||||
if self.debug:
|
||||
print("<< Tuberculoventral model: Creating structured cell >>")
|
||||
self.set_morphology(morphology_file=morphology)
|
||||
|
||||
# decorate the morphology with ion channels
|
||||
if decorator is None: # basic model, only on the soma
|
||||
self.mechanisms = ["kht", "ka", "ihvcn", "leak", nach]
|
||||
for mech in self.mechanisms:
|
||||
self.soma.insert(mech)
|
||||
self.species_scaling(
|
||||
silent=True, species=species, modelType=modelType
|
||||
) # adjust the default parameters
|
||||
else: # decorate according to a defined set of rules on all cell compartments
|
||||
self.decorate()
|
||||
self.save_all_mechs() # save all mechanisms inserted, location and gbar values...
|
||||
self.get_mechs(self.soma)
|
||||
if self.debug:
|
||||
print("<< Tuberculoventral cell model created >>")
|
||||
|
||||
def get_cellpars(self, dataset, species="mouse", celltype="TVmouse"):
|
||||
cellcap = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_Cap"
|
||||
)
|
||||
chtype = data.get(
|
||||
dataset, species=species, cell_type=celltype, field="soma_na_type"
|
||||
)
|
||||
pars = Params(soma_cap=cellcap, soma_na_type=chtype)
|
||||
for g in [
|
||||
"soma_nacncoop_gbar",
|
||||
"soma_kht_gbar",
|
||||
"soma_ka_gbar",
|
||||
"soma_ihvcn_gbar",
|
||||
"soma_ihvcn_eh",
|
||||
"soma_leak_gbar",
|
||||
"soma_leak_erev",
|
||||
"soma_e_k",
|
||||
"soma_e_na",
|
||||
]:
|
||||
pars.additem(
|
||||
g, data.get(dataset, species=species, cell_type=celltype, field=g)
|
||||
)
|
||||
return pars
|
||||
|
||||
def species_scaling(self, species="guineapig", modelType="TVmouse", silent=True):
|
||||
"""
|
||||
Adjust all of the conductances and the cell size according to the species requested.
|
||||
Used ONLY for point models.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
species : string (default: 'guineapig')
|
||||
name of the species to use for scaling the conductances in the base point model
|
||||
Must be one of mouse, cat, guineapig
|
||||
|
||||
modelType: string (default: 'I-c')
|
||||
definition of model type from RM03 models, type I-c or type I-t
|
||||
|
||||
silent : boolean (default: True)
|
||||
run silently (True) or verbosely (False)
|
||||
"""
|
||||
soma = self.soma
|
||||
if self.debug:
|
||||
print("modelType: ", modelType)
|
||||
if modelType in ["TVmouse", "I"]:
|
||||
celltype = "TVmouse" # modelType
|
||||
modelType = "TVmouse"
|
||||
else:
|
||||
raise ValueError(
|
||||
"Tuberuloventral: Model type %s not recognized" % modelType
|
||||
)
|
||||
|
||||
if species == "mouse" and modelType in ["TVmouse", "I"]:
|
||||
"""#From Kuo 150 Mohm, 10 msec tau
|
||||
Firing at 600 pA about 400 Hz
|
||||
These values from brute_force runs, getting 380 Hz at 600 pA at 35C
|
||||
Input resistance and vm is ok, time constnat is short
|
||||
*** Rin: 168 tau: 7.8 v: -68.4
|
||||
Attempts to get longer time constant - cannot keep rate up.
|
||||
"""
|
||||
# Adapted from TStellate model type I-c'
|
||||
self.vrange = [-80.0, -58.0]
|
||||
self._valid_temperatures = (34.0,)
|
||||
if self.status["temperature"] is None:
|
||||
self.set_temperature(34.0)
|
||||
|
||||
pars = self.get_cellpars("TV_channels", species="mouse", celltype=modelType)
|
||||
self.set_soma_size_from_Cm(pars.soma_cap)
|
||||
self.status["na"] = pars.soma_na_type
|
||||
self.adjust_na_chans(soma, gbar=pars.soma_nacncoop_gbar, debug=self.debug)
|
||||
soma().kht.gbar = nstomho(pars.soma_kht_gbar, self.somaarea)
|
||||
soma().ka.gbar = nstomho(pars.soma_ka_gbar, self.somaarea)
|
||||
soma().ihvcn.gbar = nstomho(pars.soma_ihvcn_gbar, self.somaarea)
|
||||
soma().ihvcn.eh = pars.soma_ihvcn_eh
|
||||
soma().leak.gbar = nstomho(pars.soma_leak_gbar, self.somaarea)
|
||||
soma().leak.erev = pars.soma_leak_erev
|
||||
self.e_leak = pars.soma_leak_erev
|
||||
self.soma.ek = self.e_k = pars.soma_e_k
|
||||
self.soma.ena = self.e_na = pars.soma_e_na
|
||||
|
||||
self.axonsf = 0.5
|
||||
else:
|
||||
raise ValueError(
|
||||
"Species %s or species-type %s is not recognized for Tuberculoventralcells"
|
||||
% (species, type)
|
||||
)
|
||||
|
||||
self.status["species"] = species
|
||||
self.status["modelType"] = modelType
|
||||
self.check_temperature()
|
||||
|
||||
def channel_manager(self, modelType="TVmouse"):
|
||||
"""
|
||||
This routine defines channel density maps and distance map patterns
|
||||
for each type of compartment in the cell. The maps
|
||||
are used by the ChannelDecorator class (specifically, it's private
|
||||
_biophys function) to decorate the cell membrane.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
modelType : string (default: 'RM03')
|
||||
A string that defines the type of the model. Currently, 3 types are implemented:
|
||||
RM03: Rothman and Manis, 2003 somatic densities for guinea pig
|
||||
XM13: Xie and Manis, 2013, somatic densities for mouse
|
||||
XM13PasDend: XM13, but with only passive dendrites, no channels.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
This routine defines the following variables for the class:
|
||||
|
||||
- conductances (gBar)
|
||||
- a channelMap (dictonary of channel densities in defined anatomical compartments)
|
||||
- a current injection range for IV's (when testing)
|
||||
- a distance map, which defines how selected conductances in selected compartments
|
||||
will change with distance. This includes both linear and exponential gradients,
|
||||
the minimum conductance at the end of the gradient, and the space constant or
|
||||
slope for the gradient.
|
||||
|
||||
"""
|
||||
if modelType == "TVmouse":
|
||||
print("decorate as tvmouse")
|
||||
# totcap = 95.0E-12 # Tuberculoventral cell (type I), based on stellate, adjusted for Kuo et al. TV firing
|
||||
self.set_soma_size_from_Section(self.soma)
|
||||
totcap = self.totcap
|
||||
refarea = self.somaarea # totcap / self.c_m # see above for units
|
||||
self.gBar = Params(
|
||||
nabar=1520.0e-9 / refarea,
|
||||
khtbar=160.0e-9 / refarea,
|
||||
kltbar=0.0e-9 / refarea,
|
||||
kabar=65.0 / refarea,
|
||||
ihbar=1.25e-9 / refarea,
|
||||
leakbar=5.5e-9 / refarea,
|
||||
)
|
||||
self.channelMap = {
|
||||
"axon": {
|
||||
"nacn": 0.0,
|
||||
"klt": 0.0,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": 0.0,
|
||||
"leak": self.gBar.leakbar / 4.0,
|
||||
},
|
||||
"hillock": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": 0.0,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": 0.0,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"initseg": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": 0.0,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": self.gBar.ihbar / 2.0,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"soma": {
|
||||
"nacn": self.gBar.nabar,
|
||||
"klt": self.gBar.kltbar,
|
||||
"kht": self.gBar.khtbar,
|
||||
"ihvcn": self.gBar.ihbar,
|
||||
"leak": self.gBar.leakbar,
|
||||
},
|
||||
"dend": {
|
||||
"nacn": self.gBar.nabar / 2.0,
|
||||
"klt": 0.0,
|
||||
"kht": self.gBar.khtbar * 0.5,
|
||||
"ihvcn": self.gBar.ihbar / 3.0,
|
||||
"leak": self.gBar.leakbar * 0.5,
|
||||
},
|
||||
"apic": {
|
||||
"nacn": 0.0,
|
||||
"klt": 0.0,
|
||||
"kht": self.gBar.khtbar * 0.2,
|
||||
"ihvcn": self.gBar.ihbar / 4.0,
|
||||
"leak": self.gBar.leakbar * 0.2,
|
||||
},
|
||||
}
|
||||
self.irange = np.linspace(-0.3, 0.6, 10)
|
||||
self.distMap = {
|
||||
"dend": {
|
||||
"klt": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"kht": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
}, # linear with distance, gminf (factor) is multiplied by gbar
|
||||
"apic": {
|
||||
"klt": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
"kht": {"gradient": "linear", "gminf": 0.0, "lambda": 100.0},
|
||||
}, # gradients are: flat, linear, exponential
|
||||
}
|
||||
else:
|
||||
raise ValueError("model type %s is not implemented" % modelType)
|
||||
|
||||
def adjust_na_chans(self, soma, gbar=1000.0, debug=False):
|
||||
"""
|
||||
Adjust the sodium channel conductance, depending on the type of conductance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
soma : NEURON section object (required)
|
||||
This identifies the soma object whose sodium channel complement will have it's
|
||||
conductances adjusted depending on the sodium channel type
|
||||
gbar : float (default: 1000.)
|
||||
The "maximal" conductance to be set in the model.
|
||||
debug : boolean (default: False)
|
||||
A flag the prints out messages to confirm the operations applied.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Nothing
|
||||
"""
|
||||
if self.status["ttx"]:
|
||||
gnabar = 0.0
|
||||
else:
|
||||
gnabar = nstomho(gbar, self.somaarea)
|
||||
nach = self.status["na"]
|
||||
if nach == "nacncoop":
|
||||
soma().nacncoop.gbar = gnabar
|
||||
soma().nacncoop.KJ = 2000.0
|
||||
soma().nacncoop.p = 0.25
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("nacncoop gbar: ", soma().nacncoop.gbar)
|
||||
elif nach == "jsrna":
|
||||
soma().jsrna.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("jsrna gbar: ", soma().jsrna.gbar)
|
||||
elif nach == "nav11":
|
||||
soma().nav11.gbar = gnabar * 0.5
|
||||
soma.ena = self.e_na
|
||||
soma().nav11.vsna = 4.3
|
||||
if debug:
|
||||
print("Tuberculoventral using inva11")
|
||||
print("nav11 gbar: ", soma().nav11.gbar)
|
||||
elif nach == "na":
|
||||
soma().na.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("na gbar: ", soma().na.gbar)
|
||||
elif nach == "nacn":
|
||||
soma().nacn.gbar = gnabar
|
||||
soma.ena = self.e_na
|
||||
if debug:
|
||||
print("nacn gbar: ", soma().nacn.gbar)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Tuberculoventral setting Na channels: channel %s not known" % nach
|
||||
)
|
||||
|
||||
|
||||
class DummyTuberculoventral(Tuberculoventral):
|
||||
""" Tuberculoventral cell class with no cell body; this cell only replays a predetermined
|
||||
spike train. Useful for testing, or replacing spike trains to determine
|
||||
the importance of spike structures within a network.
|
||||
"""
|
||||
|
||||
def __init__(self, cf=None, species="mouse"):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
cf : float (default: None)
|
||||
Required: the characteristic frequency for the TV cell
|
||||
Really just for reference.
|
||||
|
||||
"""
|
||||
|
||||
Tuberculoventral.__init__(self)
|
||||
self.vecstim = h.VecStim()
|
||||
|
||||
# this causes the terminal to receive events from the VecStim:
|
||||
self.spike_source = self.vecstim
|
||||
|
||||
# just an empty section for holding the terminal
|
||||
self.add_section(h.Section(), "soma")
|
||||
self.status = {
|
||||
"soma": True,
|
||||
"axon": False,
|
||||
"dendrites": False,
|
||||
"pumps": False,
|
||||
"na": None,
|
||||
"species": species,
|
||||
"modelType": "Dummy",
|
||||
"modelName": "DummyTuberculoventral",
|
||||
"ttx": None,
|
||||
"name": "DummyTuberculoventral",
|
||||
"morphology": None,
|
||||
"decorator": None,
|
||||
"temperature": None,
|
||||
}
|
||||
print("<< Tuberculoventral: Dummy Tuberculoventral Cell created >>")
|
||||
|
||||
def set_spiketrain(self, times):
|
||||
""" Set the times of spikes (in seconds) to be replayed by the cell.
|
||||
"""
|
||||
self._spiketrain = times
|
||||
self._stvec = h.Vector(times)
|
||||
self.vecstim.play(self._stvec)
|
||||
Reference in New Issue
Block a user