Source code for netpyne.network.stim

"""
Module for adding stimulations to networks

"""

from numbers import Number

try:
    basestring
except NameError:
    basestring = str


# -----------------------------------------------------------------------------
#  Add stims
# -----------------------------------------------------------------------------
[docs] def addStims(self): """ Internal function to add stims specified in specs.NetParams Usage: Creates and attaches stims to targets via CompartCell.addstim() based on entries in the specs.NetParams sub- dictionaries -- specs.NetParams.stimSourceParams and specs.NetParams.stimTargetParams (see below) NetParams.stimSourceParams entries contain key-value pairs to describe NEURON point processes specified by the 'type' entry (i.e. 'IClamp', 'VClamp', 'SEClamp', 'AlphaSynapse', 'VecStim') NetParams.stimTargetParams entries contain key-value pairs to describe the post-synaptic connections for a stimSourceParam entry specified by the 'source' entry, including a 'sec' and 'loc' entry (describing section and location) for where the post-synaptic connection will exist and a 'conds' entry with a dictionary specifying the cell criteria for the post-synaptic connections: (i.e. 'x', 'y', 'z' or 'xnorm', 'ynorm', 'znorm' specifying cell criteria by location, 'cellList' specifying cell criteria by specific gid, or arbitrary 'key': 'value' tags. For 'VecStim' point processes, it may be more convenient to create an artificial cell (i.e.netParams.popParams see: netpyne/cell/pointCell.py) which allows pattern generation ('rhythmic', 'evoked', 'poisson', 'gauss') by key-value entries in a 'spikePattern' dictionary. Parameters ---------- self : <type> <Short description of self> **Default:** *required* """ from .. import sim sim.timing('start', 'stimsTime') if self.params.stimSourceParams and self.params.stimTargetParams: if sim.rank == 0: print('Adding stims...') if sim.nhosts > 1: # Gather tags from all cells allCellTags = sim._gatherAllCellTags() else: allCellTags = {cell.gid: cell.tags for cell in self.cells} # allPopTags = {i: pop.tags for i,pop in enumerate(self.pops)} # gather tags from pops so can connect NetStim pops sources = self.params.stimSourceParams for targetLabel, target in self.params.stimTargetParams.items(): # for each target parameter set if 'sec' not in target: target['sec'] = None # if section not specified, make None (will be assigned to first section in cell) if 'loc' not in target: target['loc'] = None # if location not specified, make None source = sources.get(target['source']) postCellsTags = allCellTags for condKey, condValue in target['conds'].items(): # Find subset of cells that match postsyn criteria if condKey in ['x', 'y', 'z', 'xnorm', 'ynorm', 'znorm']: postCellsTags = { gid: tags for (gid, tags) in postCellsTags.items() if condValue[0] <= tags.get(condKey, None) < condValue[1] } # dict with post Cell objects} # dict with pre cell tags elif condKey == 'cellList': pass elif isinstance(condValue, list): postCellsTags = { gid: tags for (gid, tags) in postCellsTags.items() if tags.get(condKey, None) in condValue } # dict with post Cell objects else: postCellsTags = { gid: tags for (gid, tags) in postCellsTags.items() if tags.get(condKey, None) == condValue } # dict with post Cell objects # subset of cells from selected pops (by relative indices) if 'cellList' in target['conds']: orderedPostGids = sorted(postCellsTags.keys()) gidList = [orderedPostGids[i] for i in target['conds']['cellList']] postCellsTags = {gid: tags for (gid, tags) in postCellsTags.items() if gid in gidList} # initialize randomizer in case used in string-based function (see issue #89 for more details) self.rand.Random123( sim.hashStr('stim_' + source['type']), sim.hashList(sorted(postCellsTags)), sim.cfg.seeds['stim'] ) # calculate params if string-based funcs strParams = self._stimStrToFunc(postCellsTags, source, target) # loop over postCells and add stim target for postCellGid in postCellsTags: # for each postsyn cell if postCellGid in self.gid2lid: # check if postsyn is in this node's list of gids postCell = self.cells[sim.net.gid2lid[postCellGid]] # get Cell object # stim target params params = {} params['label'] = targetLabel params['source'] = target['source'] params['sec'] = strParams['secList'][postCellGid] if 'secList' in strParams else target['sec'] params['loc'] = strParams['locList'][postCellGid] if 'locList' in strParams else target['loc'] if source['type'] == 'NetStim': # for NetStims add weight+delay or default values params['weight'] = ( strParams['weightList'][postCellGid] if 'weightList' in strParams else target.get('weight', 1.0) ) params['delay'] = ( strParams['delayList'][postCellGid] if 'delayList' in strParams else target.get('delay', 1.0) ) params['synsPerConn'] = ( strParams['synsPerConnList'][postCellGid] if 'synsPerConnList' in strParams else target.get('synsPerConn', 1) ) params['synMech'] = target.get('synMech', None) for p in ['Weight', 'Delay', 'Loc']: if 'synMech' + p + 'Factor' in target: params['synMech' + p + 'Factor'] = target.get('synMech' + p + 'Factor') if 'originalFormat' in source and source['originalFormat'] == 'NeuroML2': if 'weight' in target: params['weight'] = target['weight'] for sourceParam in source: # copy source params params[sourceParam] = ( strParams[sourceParam + 'List'][postCellGid] if sourceParam + 'List' in strParams else source.get(sourceParam) ) if source['type'] == 'NetStim': self._addCellStim(params, postCell) # call method to add connections (sort out synMechs first) else: postCell.addStim(params) # call cell method to add connection print((' Number of stims on node %i: %i ' % (sim.rank, sum([len(cell.stims) for cell in self.cells])))) sim.pc.barrier() sim.timing('stop', 'stimsTime') if sim.rank == 0 and sim.cfg.timing: print((' Done; cell stims creation time = %0.2f s.' % sim.timingData['stimsTime'])) return [cell.stims for cell in self.cells]
# ----------------------------------------------------------------------------- # Set parameters and add stim # ----------------------------------------------------------------------------- def _addCellStim(self, stimParam, postCell): # convert synMech param to list (if not already) if not isinstance(stimParam.get('synMech'), list): stimParam['synMech'] = [stimParam.get('synMech')] # generate dict with final params for each synMech paramPerSynMech = ['weight', 'delay', 'loc'] finalParam = {} for i, synMech in enumerate(stimParam.get('synMech')): for param in paramPerSynMech: finalParam[param + 'SynMech'] = stimParam.get(param) if len(stimParam['synMech']) > 1: if isinstance(stimParam.get(param), list): # get weight from list for each synMech finalParam[param + 'SynMech'] = stimParam[param][i] elif 'synMech' + param.title() + 'Factor' in stimParam: # adapt weight for each synMech finalParam[param + 'SynMech'] = ( stimParam[param] * stimParam['synMech' + param.title() + 'Factor'][i] ) params = {k: stimParam.get(k) for k, v in stimParam.items()} params['synMech'] = synMech params['loc'] = finalParam['locSynMech'] params['weight'] = finalParam['weightSynMech'] params['delay'] = finalParam['delaySynMech'] postCell.addStim(params=params) # ----------------------------------------------------------------------------- # Convert stim param string to function # ----------------------------------------------------------------------------- def _stimStrToFunc(self, postCellsTags, sourceParams, targetParams): # list of params that have a function passed in as a string # params = sourceParams+targetParams params = sourceParams.copy() params.update(targetParams) paramsStrFunc = [ param for param in self.stimStringFuncParams + self.connStringFuncParams if param in params and isinstance(params[param], basestring) and params[param] not in ['variable'] ] # dict to store correspondence between string and actual variable dictVars = {} dictVars['post_x'] = lambda postConds: postConds['x'] dictVars['post_y'] = lambda postConds: postConds['y'] dictVars['post_z'] = lambda postConds: postConds['z'] dictVars['post_xnorm'] = lambda postConds: postConds['xnorm'] dictVars['post_ynorm'] = lambda postConds: postConds['ynorm'] dictVars['post_znorm'] = lambda postConds: postConds['znorm'] dictVars['rand'] = lambda unused1: self.rand # add netParams variables for k, v in self.params.__dict__.items(): if isinstance(v, Number): dictVars[k] = v # for each parameter containing a function, calculate lambda function and arguments from netpyne.specs.utils import generateStringFunction strParams = {} for paramStrFunc in paramsStrFunc: strFunc = params[paramStrFunc] # string containing function lambdaFunc, strVars = generateStringFunction(strFunc, list(dictVars.keys())) # store lambda function and func vars in connParam (for weight, delay and synsPerConn since only calculated for certain conns) params[paramStrFunc + 'Func'] = lambdaFunc params[paramStrFunc + 'FuncVars'] = {strVar: dictVars[strVar] for strVar in strVars} # replace lambda function (with args as dict of lambda funcs) with list of values strParams[paramStrFunc + 'List'] = { postGid: params[paramStrFunc + 'Func']( **{ k: v if isinstance(v, Number) else v(postCellTags) for k, v in params[paramStrFunc + 'FuncVars'].items() } ) for postGid, postCellTags in sorted(postCellsTags.items()) } return strParams