Source code for netpyne.specs.netParams

"""
Module containing classes for high-level network parameters and methods

"""

# required to make json saving work in Python 2/3
try:
    to_unicode = unicode
except NameError:
    to_unicode = str

try:
    basestring
except NameError:
    basestring = str

from collections import OrderedDict
from .dicts import Dict, ODict
from .. import conversion

# ----------------------------------------------------------------------------
# PopParams class
# ----------------------------------------------------------------------------


[docs] class PopParams(ODict): """ Class to hold population parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False dimParams = ['numCells', 'density', 'gridSpacing'] if param in dimParams: for removeParam in dimParams: d.pop(removeParam, None) # remove other properties d[param] = value return True
[docs] def rename(self, old, new, label=None): return self.__rename__(old, new, label)
# ---------------------------------------------------------------------------- # CellParams class # ----------------------------------------------------------------------------
[docs] class CellParams(ODict): """ Class to hold cell parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False d[param] = value return True
[docs] def rename(self, old, new, label=None): success = self.__rename__(old, new, label) try: # special case: renaming cellParams[x]['secs'] requires updating topology if isinstance(label, (list, tuple)) and 'secs' in self[label[0]]: d = self[label[0]] for sec in list(d['secs'].values()): # replace appearences in topol if sec['topol'].get('parentSec') == old: sec['topol']['parentSec'] = new return success except: return False
[docs] @staticmethod def pointpParamsReservedKeys(): return ['mod', 'loc', 'vref', 'synList']
[docs] def preprocessStringFunctions(self): from .utils import generateStringFuncsFromParams from ..cell.compartCell import CompartCell from ..cell.pointCell import PointCell stringFuncs = {} for (cellType, cellParams) in self.items(): funcsForCell = {} # compartCell cellVars = cellParams.get('vars', {}) varNames = CompartCell.stringFuncVarNames() + list(cellVars.keys()) # cellVars themselves may contain random distributions or vars generateStringFuncsFromParams( cellVars, CompartCell.stringFuncVarNamesForCellVars(), storeIn=funcsForCell, key='cellVars' ) for secKey, secVal in [(secKey, secVal) for (secKey, secVal) in cellParams.get('secs', {}).items()]: funcsForSec = {} # find string functions among geom params generateStringFuncsFromParams(secVal.get('geom', {}), varNames, storeIn=funcsForSec, key='geom') # find string functions among mechs funcsForMechs = {} for mechK, mech in secVal.get('mechs', {}).items(): generateStringFuncsFromParams(mech, varNames, funcsForMechs, mechK) if len(funcsForMechs) > 0: funcsForSec['mechs'] = funcsForMechs # find string functions among pointps funcsForPointps = {} for pointpK, pointp in secVal.get('pointps', {}).items(): generateStringFuncsFromParams( pointp, varNames, storeIn=funcsForPointps, key=pointpK, excludeParams=CellParams.pointpParamsReservedKeys(), ) if len(funcsForPointps) > 0: funcsForSec['pointps'] = funcsForPointps if len(funcsForSec) > 0: funcsForCell[secKey] = funcsForSec if len(funcsForCell) > 0: stringFuncs[cellType] = funcsForCell # pointCell generateStringFuncsFromParams( cellParams.get('params', {}), PointCell.stringFuncVarNames(), stringFuncs, cellType ) from .. import sim sim.net.params._cellParamStringFuncs = stringFuncs
[docs] @staticmethod def updateStringFuncsWithPopParams(popLabel, params): from .. import sim from ..specs.utils import generateStringFuncsFromParams from ..cell.pointCell import PointCell try: cellStringFuncs = sim.net.params._cellParamStringFuncs except: cellStringFuncs = sim.net.params._cellParamStringFuncs = {} popKey = ( '__pop__' + popLabel ) # use pop label as key, but add special prefix to not mix with cellParams labels normally used as keys in string funcs dictionary generateStringFuncsFromParams(params, PointCell.stringFuncVarNames(), cellStringFuncs, popKey)
[docs] @staticmethod def stringFuncAndVarsForCellVar(cellType, cellVarName): from .. import sim funcs = sim.net.params._cellParamStringFuncs return funcs.get(cellType, {}).get('cellVars', {}).get(cellVarName, (None, []))
[docs] @staticmethod def stringFuncAndVarsForGeom(cellType, section, param): from .. import sim funcs = sim.net.params._cellParamStringFuncs return funcs.get(cellType, {}).get(section, {}).get('geom', {}).get(param, (None, []))
[docs] @staticmethod def stringFuncAndVarsForMod(cellType, section, modType, mod, param): # modType: 'mechs' | 'pointps' from .. import sim funcs = sim.net.params._cellParamStringFuncs return funcs.get(cellType, {}).get(section, {}).get(modType, {}).get(mod, {}).get(param, (None, []))
[docs] @staticmethod def stringFuncAndVarsForPointCell(cellTypeOrPop, param): from .. import sim funcs = sim.net.params._cellParamStringFuncs return funcs.get(cellTypeOrPop, {}).get(param, (None, []))
# ---------------------------------------------------------------------------- # ConnParams class # ----------------------------------------------------------------------------
[docs] class ConnParams(ODict): """ Class to hold connectivity parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False d[param] = value return True
[docs] def rename(self, old, new, label=None): return self.__rename__(old, new, label)
# ---------------------------------------------------------------------------- # SynMechParams class # ----------------------------------------------------------------------------
[docs] class SynMechParams(ODict): """ Class to hold synaptic mechanism parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False d[param] = value return True
[docs] def rename(self, old, new, label=None): return self.__rename__(old, new, label)
[docs] def preprocessStringFunctions(self): from .utils import generateStringFuncsFromParams stringFuncs = {} for (mechKey, mech) in self.items(): generateStringFuncsFromParams( mech, SynMechParams.stringFuncVarNames(), stringFuncs, mechKey, excludeParams=SynMechParams.reservedKeys(), ) from .. import sim sim.net.params._synMechStringFuncs = stringFuncs
[docs] @staticmethod def stringFunctionAndVars(synMechName, paramName): from .. import sim funcs = sim.net.params._synMechStringFuncs if not synMechName in funcs: return None, [] if not paramName in funcs[synMechName]: return None, [] return funcs[synMechName][paramName]
[docs] def isPointerConn(self, synMechLabel): if synMechLabel not in self: return False return 'pointerParams' in self[synMechLabel]
[docs] def hasPointerConns(self): for label in self: if self.isPointerConn(label): return True return False
[docs] @staticmethod def reservedKeys(): return ['label', 'mod', 'selfNetCon', 'loc', 'pointerParams']
[docs] @staticmethod def stringFuncVarNames(): return list(SynMechParams.stringFuncVarsEvaluators().keys())
[docs] @staticmethod def stringFuncVarsEvaluators(): return { 'rand': lambda cell, dist, rand: rand, 'post_dist_path': lambda cell, dist, rand: dist, 'post_dist_euclidean': lambda cell, dist, rand: dist, 'post_x': lambda cell, dist, rand: cell.tags['x'], 'post_y': lambda cell, dist, rand: cell.tags['y'], 'post_z': lambda cell, dist, rand: cell.tags['z'], 'post_xnorm': lambda cell, dist, rand: cell.tags['xnorm'], 'post_ynorm': lambda cell, dist, rand: cell.tags['ynorm'], 'post_znorm': lambda cell, dist, rand: cell.tags['znorm'], }
@staticmethod def stringFuncVarsReferringPreLoc(): # no such vars as for now. To be extended in future return [] @staticmethod def stringFuncsReferPreLoc(synMech): from .. import sim mechFuncs = sim.net.params._synMechStringFuncs.get(synMech, {}) for preLocVar in SynMechParams.stringFuncVarsReferringPreLoc(): for _, (_, vars) in mechFuncs.items(): if preLocVar in vars: return True return False
[docs] @staticmethod def stringFuncVarsReferringPreLoc(): # no such vars as for now. To be extended in future return []
[docs] @staticmethod def stringFuncsReferPreLoc(synMech): from .. import sim mechFuncs = sim.net.params._synMechStringFuncs.get(synMech, {}) for preLocVar in SynMechParams.stringFuncVarsReferringPreLoc(): for _, (_, vars) in mechFuncs.items(): if preLocVar in vars: return True return False
# ---------------------------------------------------------------------------- # SubConnParams class # ----------------------------------------------------------------------------
[docs] class SubConnParams(ODict): """ Class to hold subcellular connectivity parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False d[param] = value return True
[docs] def rename(self, old, new, label=None): return self.__rename__(old, new, label)
# ---------------------------------------------------------------------------- # StimSourceParams class # ----------------------------------------------------------------------------
[docs] class StimSourceParams(ODict): """ Class to hold stimulation source parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False d[param] = value return True
[docs] def rename(self, old, new, label=None): return self.__rename__(old, new, label)
# ---------------------------------------------------------------------------- # StimTargetParams class # ----------------------------------------------------------------------------
[docs] class StimTargetParams(ODict): """ Class to hold stimulation target parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False d[param] = value return True
[docs] def rename(self, old, new, label=None): return self.__rename__(old, new, label)
# ---------------------------------------------------------------------------- # RxD class # ----------------------------------------------------------------------------
[docs] class RxDParams(ODict): """ Class to hold reaction-diffusion (RxD) parameters """
[docs] def setParam(self, label, param, value): if label in self: d = self[label] else: return False d[param] = value return True
[docs] def rename(self, old, new, label=None): return self.__rename__(old, new, label)
# ---------------------------------------------------------------------------- # NETWORK PARAMETERS CLASS # ----------------------------------------------------------------------------
[docs] class NetParams(object): """ Class to hold all network parameters """ def __init__(self, netParamsDict=None): self._labelid = 0 # General network parameters self.scale = 1 # scale factor for number of cells self.sizeX = 100 # x-dimension (horizontal length) size in um self.sizeY = 100 # y-dimension (vertical height or cortical depth) size in um self.sizeZ = 100 # z-dimension (horizontal depth) size in um self.shape = 'cuboid' # network shape ('cuboid', 'cylinder' or 'ellipsoid') self.rotateCellsRandomly = False # random rotation of cells around y-axis [min,max] radians, e.g. [0, 3.0] self.defineCellShapes = False # convert stylized cell geometries to 3d points (calls h.define_shape) self.correctBorder = ( False # distance (um) from which to correct connectivity border effect, [x,y,z] eg. [100,150,150] ) self.cellsVisualizationSpacingMultiplier = [ 1, 1, 1, ] # x,y,z scaling factor for spacing between cells during visualization ## General connectivity parameters self.scaleConnWeight = 1 # Connection weight scale factor (NetStims not included) self.scaleConnWeightNetStims = 1 # Connection weight scale factor for NetStims self.scaleConnWeightModels = ( False # Connection weight scale factor for each cell model eg. {'Izhi2007': 0.1, 'Friesen': 0.02} ) self.defaultWeight = 1 # default connection weight self.defaultDelay = 1 # default connection delay (ms) self.defaultThreshold = 10 # default Netcon threshold (mV) self.propVelocity = 500.0 # propagation velocity (um/ms) # mapping between cfg and netParams self.mapping = {} # Cell params dict self.cellParams = CellParams() # Population params dict self.popParams = PopParams() # create list of populations - each item will contain dict with pop params self.popTagsCopiedToCells = ['cellModel', 'cellType'] # Synaptic mechanism params dict self.synMechParams = SynMechParams() # Connectivity params dict self.connParams = ConnParams() # Subcellular connectivity params dict self.subConnParams = SubConnParams() # Stimulation source and target params dicts self.stimSourceParams = StimSourceParams() self.stimTargetParams = StimTargetParams() # RxD params dicts and start up self.rxdParams = RxDParams() # fill in params from dict passed as argument if netParamsDict: netParamsComponents = [ 'cellParams', 'popParams', 'synMechParams', 'connParams', 'subConnParams', 'stimSourceParams', 'stimTargetParams', 'rxdParams', ] for k, v in netParamsDict.items(): if k in netParamsComponents: for k2, v2 in netParamsDict[k].items(): if isinstance(v2, OrderedDict): getattr(self, k)[k2] = ODict(v2) elif isinstance(v2, dict): getattr(self, k)[k2] = ODict(v2) else: getattr(self, k)[k2] = v2 elif isinstance(v, OrderedDict): setattr(self, k, ODict(v)) elif isinstance(v, dict): setattr(self, k, Dict(v)) else: setattr(self, k, v) def __getitem__(self, k): try: return object.__getattribute__(self, k) except: raise KeyError(k) def __setitem__(self, k, v): try: setattr(self, k, v) except: raise KeyError(v)
[docs] def save(self, filename): import os from .. import sim basename = os.path.basename(filename) folder = filename.split(basename)[0] ext = basename.split('.')[1] # make directories if they do not already exist: try: os.makedirs(folder, exist_ok=True) except Exception as e: print('%s: Exception: %s,' % (os.path.abspath(__file__), e)) raise SystemExit('Could not create %s' % (folder)) dataSave = {'net': {'params': self.todict()}} # Save to json file if ext == 'json': print(('Saving netParams to %s ... ' % (filename))) sim.saveJSON(filename, dataSave)
[docs] def addCellParams(self, label=None, params=None): if not label: label = int(self._labelid) self._labelid += 1 self.cellParams[label] = Dict(params)
[docs] def addPopParams(self, label=None, params=None): if not label: label = int(self._labelid) self._labelid += 1 self.popParams[label] = Dict(params)
[docs] def addSynMechParams(self, label=None, params=None): if not label: label = int(self._labelid) self._labelid += 1 self.synMechParams[label] = Dict(params)
[docs] def addConnParams(self, label=None, params=None): if not label: label = int(self._labelid) self._labelid += 1 self.connParams[label] = Dict(params)
[docs] def addSubConnParams(self, label=None, params=None): if not label: label = int(self._labelid) self._labelid += 1 self.subConnParams[label] = Dict(params)
[docs] def addStimSourceParams(self, label=None, params=None): if not label: label = int(self._labelid) self._labelid += 1 self.stimSourceParams[label] = Dict(params)
[docs] def addStimTargetParams(self, label=None, params=None): if not label: label = int(self._labelid) self._labelid += 1 self.stimTargetParams[label] = Dict(params)
# def rename(self, attr, old, new): # try: # obj = getattr(self, attr) # except: # print 'Error renaming: netParams does not contain %s' % (attr) # return False # if old not in obj: # print 'Error renaming: netParams.%s rule does not contain %s' % (attribute, old) # return False # obj[new] = obj.pop(old) # replace # return True
[docs] def importCellParams( self, label, fileName, cellName, conds={}, cellArgs=None, importSynMechs=False, somaAtOrigin=True, cellInstance=False, ): if cellArgs is None: cellArgs = {} if not label: label = int(self._labelid) self._labelid += 1 secs, secLists, synMechs, globs = conversion.importCell(fileName, cellName, cellArgs, cellInstance) cellRule = {'conds': conds, 'secs': secs, 'secLists': secLists, 'globals': globs} # adjust cell 3d points so that soma is at location 0,0,0 if somaAtOrigin: somaSec = next((sec for sec in cellRule['secs'] if 'soma' in sec), None) if not somaSec or not 'pt3d' in cellRule['secs'][somaSec]['geom']: pass # print('Warning: cannot place soma at origin because soma does not exist or does not contain pt3d') else: soma3d = cellRule['secs'][somaSec]['geom']['pt3d'] midpoint = int(len(soma3d) / 2) somaX, somaY, somaZ = soma3d[midpoint][0:3] for sec in list(cellRule['secs'].values()): if 'pt3d' in sec['geom']: for i, pt3d in enumerate(sec['geom']['pt3d']): sec['geom']['pt3d'][i] = (pt3d[0] - somaX, pt3d[1] - somaY, pt3d[2] - somaZ, pt3d[3]) self.addCellParams(label, cellRule) if importSynMechs: for synMech in synMechs: self.addSynMechParams(cellName + '_' + synMech.pop('label'), synMech) return self.cellParams[label]
[docs] def importCellParamsFromNet(self, labelList, condsList, fileName, cellNameList, importSynMechs=False): conversion.importCellsFromNet(self, fileName, labelList, condsList, cellNameList, importSynMechs) return self.cellParams
[docs] def addCellParamsSecList(self, label, secListName, somaDist=None, somaDistY=None): import numpy as np if label in self.cellParams: cellRule = self.cellParams[label] else: print('Error adding secList: netParams.cellParams does not contain %s' % (label)) return if somaDist is not None and (not isinstance(somaDist, list) or len(somaDist) != 2): print('Error adding secList: somaDist should be a list with 2 elements') return if somaDistY is not None and (not isinstance(somaDistY, list) or len(somaDistY) != 2): print('Error adding secList: somaDistY should be a list with 2 elements') return secList = [] for secName, sec in cellRule['secs'].items(): if 'pt3d' in sec['geom']: pt3d = sec['geom']['pt3d'] midpoint = int(len(pt3d) / 2) x, y, z = pt3d[midpoint][0:3] if somaDist: distSec = np.linalg.norm(np.array([x, y, z])) if distSec >= somaDist[0] and distSec <= somaDist[1]: secList.append(secName) elif somaDistY: if y >= somaDistY[0] and y <= somaDistY[1]: secList.append(secName) else: #TODO jchen.6727@gmail.com 711713 more descriptive message, don't break on axon. print("Error adding {} to {}: {} does not contain 3d points".format(secName, secListName, secName)) cellRule.secLists[secListName] = list(secList)
[docs] def swapCellParamsPt3d(self, label, origIndex, targetIndex): if label in self.cellParams: cellRule = self.cellParams[label] else: print('Error swapping 3d pts: netParams.cellParams does not contain %s' % (label)) return if origIndex not in list(range(4)) and targetIndex not in list(range(4)): # check valid indices (x,y,z,d) print('Error swapping 3d pts: indices should be 0, 1, 2 or 3 (x,y,z,d)') return for sec in list(cellRule.secs.values()): if 'pt3d' in sec['geom']: pt3d = sec['geom']['pt3d'] for i, pt in enumerate(pt3d): pt3d[i] = list(pt) for pt in pt3d: tmp = float(pt[origIndex]) pt[origIndex] = float(pt[targetIndex]) pt[targetIndex] = tmp
[docs] def renameCellParamsSec(self, label, oldSec, newSec): self.cellParams.rename(oldSec, newSec, (label, 'secs'))
[docs] def addCellParamsWeightNorm(self, label, fileName, threshold=1000): import pickle, sys if label in self.cellParams: cellRule = self.cellParams[label] else: print('Error adding weightNorm: netParams.cellParams does not contain %s' % (label)) return with open(fileName, 'rb') as fileObj: if sys.version_info[0] == 2: weightNorm = pickle.load(fileObj) else: weightNorm = pickle.load(fileObj, encoding='latin1') try: somaSec = next((k for k in list(weightNorm.keys()) if k.startswith('soma')), None) somaWeightNorm = weightNorm[somaSec][0] except: print('Error setting weightNorm: no soma section available to set threshold') return for sec, wnorm in weightNorm.items(): if sec in cellRule['secs']: wnorm = [min(wn, threshold * somaWeightNorm) for wn in wnorm] cellRule['secs'][sec]['weightNorm'] = wnorm # add weight normalization factors for each section
[docs] def addCellParamsTemplate(self, label, conds={}, template=None): if label in self.cellParams: print('CellParams key %s already exists...' % (label)) secs = {} if template == 'Simple_HH': secs['soma'] = {'geom': {}, 'mechs': {}} secs['soma']['geom'] = {'diam': 20, 'L': 20, 'Ra': 100.0, 'cm': 1} secs['soma']['mechs']['hh'] = {'gnabar': 0.12, 'gkbar': 0.036, 'gl': 0.0003, 'el': -54.3} elif template == 'BallStick_HH': secs['soma'] = {'geom': {}, 'mechs': {}} secs['soma']['geom'] = {'diam': 12, 'L': 12, 'Ra': 100.0, 'cm': 1} secs['soma']['mechs']['hh'] = {'gnabar': 0.12, 'gkbar': 0.036, 'gl': 0.0003, 'el': -54.3} secs['dend'] = {'geom': {}, 'mechs': {}} secs['dend']['geom'] = {'diam': 1.0, 'L': 200.0, 'Ra': 100.0, 'cm': 1} secs['dend']['topol'] = {'parentSec': 'soma', 'parentX': 1.0, 'childX': 0} secs['dend']['mechs']['pas'] = {'g': 0.001, 'e': -70} self.cellParams[label] = {'conds': conds, 'secs': secs}
[docs] def saveCellParamsRule(self, label, fileName): import pickle, json, os ext = os.path.basename(fileName).split('.')[1] if label in self.cellParams: cellRule = self.cellParams[label] else: print('Error saving: netParams.cellParams does not contain %s' % (label)) return if ext == 'pkl': with open(fileName, 'wb') as fileObj: pickle.dump(cellRule, fileObj) elif ext == 'json': from .. import sim sim.saveJSON(fileName, cellRule)
[docs] def loadCellParamsRule(self, label, fileName): import pickle, json, os, sys ext = os.path.basename(fileName).split('.')[1] if ext == 'pkl': with open(fileName, 'rb') as fileObj: if sys.version_info[0] == 2: cellRule = pickle.load(fileObj) else: cellRule = pickle.load(fileObj, encoding='latin1') elif ext == 'json': with open(fileName, 'rb') as fileObj: cellRule = json.load(fileObj) self.cellParams[label] = cellRule
[docs] def loadCellParams(self, label, fileName): return self.loadCellParamsRule(label, fileName)
[docs] def saveCellParams(self, label, fileName): return self.saveCellParamsRule(label, fileName)
[docs] def todict(self): from ..sim import replaceDictODict return replaceDictODict(self.__dict__)
[docs] def setNestedParam(self, paramLabel, paramVal): if '.' in paramLabel: #TODO jchen6727@gmail.com 835836 replace with my crawler code? paramLabel = paramLabel.split('.') if isinstance(paramLabel, list ) or isinstance(paramLabel, tuple): container = self for ip in range(len(paramLabel) - 1): if hasattr(container, paramLabel[ip]): container = getattr(container, paramLabel[ip]) else: container = container[paramLabel[ip]] container[paramLabel[-1]] = paramVal elif isinstance(paramLabel, basestring): setattr(self, paramLabel, paramVal) # set simConfig params
[docs] def setCfgMapping(self, cfg): if hasattr(self, 'mapping'): #TODO jchen6727@gmail.com 849852 do other functions have this getattr logic issue? for k, v in self.mapping.items(): if hasattr(cfg, k): #if K is zero, the getattr(cfg, k, None) will produce unexpected behav. self.setNestedParam(v, getattr(cfg, k))