"""
Module for importing cells, synapses, and networks from NEURON
"""
import os, sys, signal
from numbers import Number
from neuron import h
import importlib
# h.load_file("stdrun.hoc")
[docs]
def getSecName(sec, dirCellSecNames=None):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.getSecName`>
Parameters
----------
sec : <type>
<Short description of sec>
**Default:** *required*
dirCellSecNames : <``None``?>
<Short description of dirCellSecNames>
**Default:** ``None``
**Options:** ``<option>`` <description of option>
"""
if dirCellSecNames is None:
dirCellSecNames = {}
if '>.' in sec.name():
fullSecName = sec.name().split('>.')[1]
elif '.' in sec.name():
fullSecName = sec.name().split('.')[1]
else:
fullSecName = sec.name()
if '[' in fullSecName: # if section is array element
secNameTemp = fullSecName.split('[')[0]
secIndex = int(fullSecName.split('[')[1].split(']')[0])
secName = secNameTemp + '_' + str(secIndex)
else:
secName = fullSecName
secIndex = -1
if secName in dirCellSecNames: # get sec names from python
secName = dirCellSecNames[secName]
return secName
[docs]
def importCellParams(fileName, labels, values, key=None):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.importCellParams`>
Parameters
----------
fileName : <type>
<Short description of fileName>
**Default:** *required*
labels : <type>
<Short description of labels>
**Default:** *required*
values : <type>
<Short description of values>
**Default:** *required*
key : <``None``?>
<Short description of key>
**Default:** ``None``
**Options:** ``<option>`` <description of option>
"""
params = {}
if fileName.endswith('.py'):
try:
filePath, fileNameOnly = os.path.split(fileName) # split path from filename
if filePath not in sys.path: # add to path if not there (need to import module)
sys.path.insert(0, filePath)
removeFilePath = True
else:
removeFilePath = False
moduleName = fileNameOnly.split('.py')[0] # remove .py to obtain module name
tempModule = importlib.import_module(moduleName)
modulePointer = tempModule
paramLabels = getattr(modulePointer, labels) # tuple with labels
paramValues = getattr(modulePointer, values) # variable with paramValues
if key: # if paramValues = dict
paramValues = paramValues[key]
params = dict(list(zip(paramLabels, paramValues)))
if removeFilePath:
sys.path.remove(filePath)
except:
print("Error loading cell parameter values from " + fileName)
else:
print("Trying to import izhi params from a file without the .py extension")
return params
[docs]
def mechVarList(distinguishArtifCells=False):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.mechVarList`>
"""
msname = h.ref('')
varList = {'mechs': {}, 'pointps': {}}
if distinguishArtifCells:
varList['artifcells'] = {}
mechTypes = ['mechs', 'pointps']
for i, mechtype in enumerate(mechTypes):
mt = h.MechanismType(i) # either distributed mechs (0) or point process (1)
for j in range(int(mt.count())):
mt.select(j)
mt.selected(msname)
ms = h.MechanismStandard(msname[0], 1) # PARAMETER (modifiable)
properties = []
propName = h.ref('')
for var in range(int(ms.count())):
k = ms.name(propName, var)
properties.append(propName[0])
if distinguishArtifCells and (mechtype == 'pointps') and mt.is_artificial(j):
# if it's an ARTIFICIAL_CELL (subset of POINT_PROCESS), use dedicated dict
varList['artifcells'][msname[0]] = properties
else:
varList[mechtype][msname[0]] = properties
return varList
# def getAllGlobals (origGlob={}):
# exclude = ['nseg', 'nrn_shape_changed_', 'Ra', 'L', 'cm', 'rallbranch', 'tstop'] # don't check these because crashes
# glob = {}
# # compare with original
# for k in [x for x in dir(h) if x not in exclude]:
# try:
# v = getattr(h,k)
# if isinstance(v, Number): # store float and int globals
# if k not in origGlob or origGlob[k] != v:
# glob[k] = v
# except:
# pass
# return glob
[docs]
def getGlobals(mechNames, origGlob={}):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.getGlobals`>
Parameters
----------
mechNames : <type>
<Short description of mechNames>
**Default:** *required*
origGlob : dict
<Short description of origGlob>
**Default:** ``{}``
**Options:** ``<option>`` <description of option>
"""
includeGlobs = ['celsius', 'v_init', 'clamp_resist']
endings = tuple(['_' + name for name in mechNames])
glob = {}
# compare with original
for k in dir(h):
if k.endswith(endings) or k in includeGlobs:
try:
v = float(h.__getattribute__(k))
if k not in origGlob or origGlob[k] != v:
glob[k] = float(v)
except:
pass
return glob
[docs]
def setGlobals(glob):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.setGlobals`>
Parameters
----------
glob : <type>
<Short description of glob>
**Default:** *required*
"""
for k, v in glob.items():
try:
setattr(h, k, v)
except:
pass
# # remove vars are not in glob ?
# for k in [x for x in dir(h) if x not in exclude]:
# if k not in glob:
# try:
# setattr(h, k, None)
# except:
# print k
def _equal_dicts(d1, d2, ignore_keys):
ignored = set(ignore_keys)
for k1, v1 in d1.items():
if k1 not in ignored and (k1 not in d2 or d2[k1] != v1):
return False
for k2, v2 in d2.items():
if k2 not in ignored and k2 not in d1:
return False
return True
def _delete_module(modname):
from sys import modules
try:
thismod = modules[modname]
del modules[modname]
except KeyError:
pass
for mod in list(modules.values()):
try:
delattr(mod, modname)
except:
pass
[docs]
def importCell(fileName, cellName, cellArgs=None, cellInstance=False):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.importCell`>
Parameters
----------
fileName : <type>
<Short description of fileName>
**Default:** *required*
cellName : <type>
<Short description of cellName>
**Default:** *required*
cellArgs : <``None``?>
<Short description of cellArgs>
**Default:** ``None``
**Options:** ``<option>`` <description of option>
cellInstance : bool
<Short description of cellInstance>
**Default:** ``False``
**Options:** ``<option>`` <description of option>
"""
h.initnrn()
varList = mechVarList() # list of properties for all density mechanisms and point processes
origGlob = getGlobals(list(varList['mechs'].keys()) + list(varList['pointps'].keys()))
origGlob['v_init'] = -65 # add by hand since won't be set unless load h.load_file('stdrun')
if cellArgs is None:
cellArgs = [] # Define as empty list if not otherwise defined
if fileName.endswith('.hoc') or fileName.endswith('.tem'):
resultCode = h.load_file(fileName)
if resultCode == 0: # error
raise Exception(f"Error occured in h.load_file() when loading {fileName}. See above for details.")
try:
if not cellInstance:
if isinstance(cellArgs, dict):
cell = getattr(h, cellName)(**cellArgs) # create cell using template, passing dict with args
else:
cell = getattr(h, cellName)(*cellArgs) # create cell using template, passing list with args
else:
try:
cell = getattr(h, cellName)
except:
cell = None
except AttributeError as e:
raise AttributeError(f"{e}\nError occured while creating cell cellName:{cellName}, please check file:{fileName} for the specific template you would like to import.")
elif fileName.endswith('.py'):
filePath, fileNameOnly = os.path.split(fileName) # split path from filename
if filePath not in sys.path: # add to path if not there (need to import module)
sys.path.insert(0, filePath)
removeFilePath = True
else:
removeFilePath = False
moduleName = fileNameOnly.split('.py')[0] # remove .py to obtain module name
tempModule = importlib.import_module(moduleName)
modulePointer = tempModule
if isinstance(cellArgs, dict):
cell = getattr(modulePointer, cellName)(**cellArgs) # create cell using template, passing dict with args
else:
cell = getattr(modulePointer, cellName)(*cellArgs) # create cell using template, passing list with args
if removeFilePath:
sys.path.remove(filePath)
elif fileName.endswith('.swc'):
from netpyne.support.morphology import load
cell = load(fileName)
else:
raise Exception("File name should end in '.hoc', '.py', or '.swc'")
secDic, secListDic, synMechs, globs = getCellParams(cell, varList, origGlob)
if fileName.endswith('.py'):
_delete_module(moduleName)
_delete_module('tempModule')
del modulePointer
elif fileName.endswith('.hoc'):
for sec in h.allsec():
try:
if h.cas() != sec:
sec.push()
h.delete_section()
h.pop_section()
except:
pass
h.initnrn()
setGlobals(origGlob) # restore original globals
return secDic, secListDic, synMechs, globs
[docs]
def importCellsFromNet(netParams, fileName, labelList, condsList, cellNamesList, importSynMechs):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.importCellsFromNet`>
Parameters
----------
netParams : <type>
<Short description of netParams>
**Default:** *required*
fileName : <type>
<Short description of fileName>
**Default:** *required*
labelList : <type>
<Short description of labelList>
**Default:** *required*
condsList : <type>
<Short description of condsList>
**Default:** *required*
cellNamesList : <type>
<Short description of cellNamesList>
**Default:** *required*
importSynMechs : <type>
<Short description of importSynMechs>
**Default:** *required*
"""
h.initnrn()
if fileName.endswith('.hoc') or fileName.endswith('.tem'):
print('Importing from .hoc network not yet supported')
return
# h.load_file(fileName)
# for cellName in cellNames:
# cell = getattr(h, cellName) # create cell using template, passing dict with args
# secDic, secListDic, synMechs = getCellParams(cell)
elif fileName.endswith('.py'):
origDir = os.getcwd()
filePath, fileNameOnly = os.path.split(fileName) # split path from filename
if filePath not in sys.path: # add to path if not there (need to import module)
sys.path.insert(0, filePath)
removeFilePath = True
else:
removeFilePath = False
moduleName = fileNameOnly.split('.py')[0] # remove .py to obtain module name
os.chdir(filePath)
print('\nRunning network in %s to import cells into NetPyNE ...\n' % (fileName))
from neuron import load_mechanisms
load_mechanisms(filePath)
tempModule = importlib.import_module(moduleName)
modulePointer = tempModule
if removeFilePath:
sys.path.remove(filePath)
else:
print("File name should be either .hoc or .py file")
return
for label, conds, cellName in zip(labelList, condsList, cellNamesList):
print('\nImporting %s from %s ...' % (cellName, fileName))
exec('cell = tempModule' + '.' + cellName)
# cell = getattr(modulePointer, cellName) # get cell object
varList = mechVarList()
origGlob = getGlobals(list(varList['mechs'].keys()) + list(varList['pointps'].keys()))
secs, secLists, synMechs = getCellParams(cell, varList, origGlob)
cellRule = {'conds': conds, 'secs': secs, 'secLists': secLists}
netParams.addCellParams(label, cellRule)
if importSynMechs:
for synMech in synMechs:
netParams.addSynMechParams(synMech.pop('label'), synMech)
[docs]
def getCellParams(cell, varList={}, origGlob={}):
"""
Function for/to <short description of `netpyne.conversion.neuronPyHoc.getCellParams`>
Parameters
----------
cell : <type>
<Short description of cell>
**Default:** *required*
varList : dict
<Short description of varList>
**Default:** ``{}``
**Options:** ``<option>`` <description of option>
origGlob : dict
<Short description of origGlob>
**Default:** ``{}``
**Options:** ``<option>`` <description of option>
"""
dirCell = dir(cell)
if 'all_sec' in dirCell:
secs = cell.all_sec
elif 'sec' in dirCell:
secs = [cell.sec]
elif 'allsec' in dir(h):
secs = [sec for sec in h.allsec()]
elif 'soma' in dirCell:
secs = [cell.soma]
else:
secs = []
# create dict with hname of each element in dir(cell)
dirCellHnames = {}
for dirCellName in [d for d in dirCell if not d.startswith('__')]: # avoid attributes starting with '__'
dirCellObject = getattr(cell, dirCellName)
if isinstance(dirCellObject, list):
for i, dirCellObjectItem in enumerate(dirCellObject):
try:
if dirCellObjectItem.hname() not in dirCellHnames: # give preference to dict entries
dirCellHnames.update({dirCellObjectItem.hname(): dirCellName + '_' + str(i)})
except:
pass
elif isinstance(dirCellObject, dict):
for k, v in dirCellObject.items():
try:
dirCellHnames.update({v.hname(): k})
except:
pass
else:
try:
dirCellHnames.update({dirCellObject.hname(): dirCellName})
except:
pass
# create dict with dir(cell) name corresponding to each hname
dirCellSecNames = {}
for sec in secs:
dirCellSecNames.update({hname: name for hname, name in dirCellHnames.items() if hname == sec.hname()})
secDic = {}
synMechs = []
for sec in secs:
# create new section dict with name of section
secName = getSecName(sec, dirCellSecNames)
# if len(secs) == 1: secName = 'soma' # if just one section rename to 'soma' -- REMOVED, doesn't always apply
secDic[secName] = {'geom': {}, 'topol': {}, 'mechs': {}} # create dictionary to store sec info
# store geometry properties
standardGeomParams = ['L', 'nseg', 'diam', 'Ra', 'cm']
secDir = dir(sec)
for geomParam in standardGeomParams:
# if geomParam in secDir:
try:
secDic[secName]['geom'][geomParam] = sec.__getattribute__(geomParam)
except:
pass
# store 3d geometry
sec.push() # access current section so ismembrane() works
numPoints = int(h.n3d())
if numPoints:
points = []
for ipoint in range(numPoints):
x = h.x3d(ipoint)
y = h.y3d(ipoint)
z = h.z3d(ipoint)
diam = h.diam3d(ipoint)
points.append((x, y, z, diam))
secDic[secName]['geom']['pt3d'] = points
# store mechanisms
# varList = mechVarList() # list of properties for all density mechanisms and point processes
ignoreMechs = ['dist'] # dist only used during cell creation
ignoreVars = [] #
mechDic = {}
ionDic = {}
for mech in dir(sec(0.5)):
if h.ismembrane(mech) and mech not in ignoreMechs: # check if membrane mechanism
if not mech.endswith('_ion'): # exclude ions
mechDic[mech] = {} # create dic for mechanism properties
varNames = [varName.replace('_' + mech, '') for varName in varList['mechs'][mech]]
varVals = []
for varName in varNames:
if varName not in ignoreVars:
try:
varVals = [seg.__getattribute__(mech).__getattribute__(varName) for seg in sec]
if len(set(varVals)) == 1:
varVals = varVals[0]
mechDic[mech][varName] = varVals
except:
pass
# print 'Could not read variable %s from mechanism %s'%(varName,mech)
# store ions
elif mech.endswith('_ion'):
ionName = mech.split('_ion')[0]
varNames = [
varName.replace('_' + mech, '').replace(ionName, '') for varName in varList['mechs'][mech]
]
varNames.append('e')
varVals = []
ionDic[ionName] = {} # create dic for mechanism properties
for varName in varNames:
varNameSplit = varName
if varName not in ignoreVars:
try:
if varNameSplit in ['i', 'o']: # var name after ion name (eg. 'nai', 'nao')
varVals = [seg.__getattribute__(ionName + varNameSplit) for seg in sec]
else: # var name before ion name (eg. 'ena')
varVals = [seg.__getattribute__(varNameSplit + ionName) for seg in sec]
if len(set(varVals)) == 1:
varVals = varVals[0]
ionDic[ionName][varNameSplit] = varVals
except:
pass
# print 'Could not read variable %s from mechanism %s'%(varName,mech)
secDic[secName]['mechs'] = mechDic
if len(ionDic) > 0:
secDic[secName]['ions'] = ionDic
# add synapses and point neurons
# for now read fixed params, but need to find way to read only synapse params
pointps = {}
for seg in sec:
for ipoint, point in enumerate(seg.point_processes()):
pointpMod = point.hname().split('[')[0]
varNames = varList['pointps'][pointpMod]
if any([s in pointpMod.lower() for s in ['syn', 'ampa', 'gaba', 'nmda', 'glu']]):
# if 'synMech' in pptype.lower(): # if syn in name of point process then assume synapse
synMech = {}
synMech['label'] = pointpMod + '_' + str(len(synMechs))
synMech['mod'] = pointpMod
# synMech['loc'] = seg.x
for varName in varNames:
try:
synMech[varName] = point.__getattribute__(varName)
except:
print('Could not read variable %s from synapse %s' % (varName, synMech['label']))
if not any([_equal_dicts(synMech, synMech2, ignore_keys=['label']) for synMech2 in synMechs]):
synMechs.append(synMech)
else: # assume its a non-synapse point process
pointpName = pointpMod + '_' + str(len(pointps))
pointps[pointpName] = {}
pointps[pointpName]['mod'] = pointpMod
pointps[pointpName]['loc'] = seg.x
for varName in varNames:
try:
pointps[pointpName][varName] = point.__getattribute__(varName)
# special condition for Izhi model, to set vinit=vr
# if varName == 'vr': secDic[secName]['vinit'] = point.__getattribute__(varName)
except:
print('Could not read %s variable from point process %s' % (varName, pointpName))
if pointps:
secDic[secName]['pointps'] = pointps
# store topology (keep at the end since h.SectionRef messes remaining loop)
secRef = h.SectionRef(sec=sec)
if secRef.has_parent():
secDic[secName]['topol']['parentSec'] = getSecName(secRef.parent().sec, dirCellSecNames)
secDic[secName]['topol']['parentX'] = h.parent_connection()
secDic[secName]['topol']['childX'] = h.section_orientation()
h.pop_section() # to prevent section stack overflow
# store section lists
secLists = h.List('SectionList')
if int(secLists.count()):
secListDic = {}
for i in range(int(secLists.count())): # loop over section lists
hname = secLists.o(i).hname()
if hname in dirCellHnames: # use python variable name
secListName = dirCellHnames[hname]
else:
secListName = hname
secListDic[secListName] = [getSecName(sec, dirCellSecNames) for sec in secLists.o(i)]
else:
secListDic = {}
# globals
mechsList = list(varList['mechs'].keys()) if 'mechs' in varList else []
pointpsList = list(varList['pointps'].keys()) if 'pointps' in varList else []
globs = getGlobals(mechsList + pointpsList, origGlob=origGlob)
if 'v_init' in globs: # set v_init for each section (allows for cells with differnet vinits)
for sec in list(secDic.values()):
sec['vinit'] = globs['v_init']
# clean
cell = None
for i in range(len(secs)):
tmp = secs.pop()
del tmp
import gc
gc.collect()
return secDic, secListDic, synMechs, globs