def __init__(self, path, length, diameter, args): """ Initialize moose-compartment """ self.mc_ = None self.path = path # Following values are taken from Upi's chapter on Rallpacks self.RM = args.get('RM', 4.0) self.RA = args.get('RA', 1.0) self.CM = args.get('CM', 0.01) self.Em = args.get('Em', -0.065) self.diameter = diameter self.compLength = length self.computeParams( ) try: self.mc_ = moose.Compartment(self.path) self.mc_.length = self.compLength self.mc_.diameter = self.diameter self.mc_.Ra = self.Ra self.mc_.Rm = self.Rm self.mc_.Cm = self.Cm self.mc_.Em = self.Em self.mc_.initVm = self.Em except Exception as e: utils.dump("ERROR" , [ "Can't create compartment with path %s " % path , "Failed with error %s " % e ] ) raise
def simulate( self, simTime, simDt = 1e-3, plotDt = None ): '''Simulate the cable ''' if plotDt is None: plotDt = simDt / 2 self.simDt = simDt self.plotDt = plotDt self.setupDUT( ) # Setup clocks utils.dump("STEP", "Setting up the clocks ... ") moose.setClock( 0, self.simDt ) moose.setClock( 1, self.simDt ) moose.setClock( 2, self.simDt ) ## Use clocksc moose.useClock( 0, '/cable/##'.format(self.cablePath), 'process' ) moose.useClock( 1, '/cable/##'.format(self.cablePath), 'init' ) moose.useClock( 2, '{}/##'.format(self.tablePath), 'process' ) utils.dump("STEP" , [ "Simulating cable for {} sec".format(simTime) , " simDt: %s, plotDt: %s" % ( self.simDt, self.plotDt ) ] ) self.setupHSolve( ) moose.reinit( ) utils.verify( ) moose.start( simTime )
def createInputs(self): """ createInputs Create inputs as given in NML file and attach them to moose. """ for inputs in self.network.findall(".//{"+nmu.nml_ns+"}inputs"): units = inputs.attrib['units'] # This dict is to be passed to function which attach an input # element to moose. factors = {} # see pg 219 (sec 13.2) of Book of Genesis if units == 'Physiological Units': factors['Vfactor'] = 1e-3 # V from mV factors['Tfactor'] = 1e-3 # s from ms factors['Ifactor'] = 1e-6 # A from microA else: utils.dump("NOTE", "We got {0}".format(units)) factors['Vfactor'] = 1.0 factors['Tfactor'] = 1.0 factors['Ifactor'] = 1.0 for inputElem in inputs.findall(".//{"+nmu.nml_ns+"}input"): self.attachInputToMoose(inputElem, factors)
def addProperties(self, pre_segment_path, post_segment_path, props, options): '''Add properties ''' synName = options['syn_name'] source = options['source'] target = options['target'] weight = options['weight'] threshold = options['threshold'] propDelay = options['prop_delay'] synapse = props.attrib.get('synapse_type', None) if not synapse: utils.dump("WARN" , "Synapse type {} not found.".format(synapse) , frame = inspect.currentframe() ) raise UserWarning("Missing parameter synapse_type") synName = synapse weight_override = float(props.attrib['weight']) if 'internal_delay' in props.attrib: delay_override = float(props.attrib['internal_delay']) else: delay_override = propDelay if weight_override != 0.0: self.connectUsingSynChan(synName , pre_segment_path , post_segment_path , weight_override , threshold, delay_override ) else: pass
def addConnection(self, connection, projection, options): """ This function adds connection """ synName = options['syn_name'] source = options['source'] target = options['target'] weight = options['weight'] threshold = options['threshold'] propDelay = options['prop_delay'] projectionName = projection.attrib['name'] pre_cell_id = connection.attrib['pre_cell_id'] post_cell_id = connection.attrib['post_cell_id'] if 'file' not in pre_cell_id: # source could be 'mitrals', self.populationDict[source][0] would be # 'mitral' pre_cell_id = int(pre_cell_id) post_cell_id = int(post_cell_id) pre_cell_name = self.populationDict[source][0] pre_segment_id = connection.attrib.get('pre_segment_id', 0) pre_segment_path = "{0}/{1}".format( self.getCellPath(source, pre_cell_id), self.cellSegmentDict[pre_cell_name][pre_segment_id][0]) else: # I've removed extra excitation provided via files, so below comment # doesn't apply. 'file[+<glomnum>]_<filenumber>' # glomnum is for # mitral_granule extra excitation from unmodelled sisters. pre_segment_path = "{}_{}".format( pre_cell_id, connection.attrib['pre_segment_id']) # target could be 'PGs', self.populationDict[target][0] would be 'PG' post_cell_name = self.populationDict[target][0] post_segment_id = connection.attrib.get('post_segment_id', '0') post_segment_path = "{}/{}".format( self.getCellPath(target, post_cell_id), self.cellSegmentDict[post_cell_name][post_segment_id][0]) try: self.projectionDict[projectionName][2].append( (synName, pre_segment_path, post_segment_path)) except KeyError as e: utils.dump("ERR", "Failed find key {0}".format(e), frame=inspect.currentframe()) print(self.projectionDict.keys()) sys.exit(0) properties = connection.findall('./{' + nmu.nml_ns + '}properties') if len(properties) == 0: self.connectUsingSynChan(synName, pre_segment_path, post_segment_path, weight, threshold, propDelay) else: [ self.addProperties(pre_segment_path, post_segment_path, p, options) for p in properties ]
def addProperties(self, pre_segment_path, post_segment_path, props, options): '''Add properties ''' synName = options['syn_name'] source = options['source'] target = options['target'] weight = options['weight'] threshold = options['threshold'] propDelay = options['prop_delay'] synapse = props.attrib.get('synapse_type', None) if not synapse: utils.dump("WARN", "Synapse type {} not found.".format(synapse), frame=inspect.currentframe()) raise UserWarning("Missing parameter synapse_type") synName = synapse weight_override = float(props.attrib['weight']) if 'internal_delay' in props.attrib: delay_override = float(props.attrib['internal_delay']) else: delay_override = propDelay if weight_override != 0.0: self.connectUsingSynChan(synName, pre_segment_path, post_segment_path, weight_override, threshold, delay_override) else: pass
def __init__(self, path, length, diameter, args): """ Initialize moose-compartment """ self.mc_ = None self.path = path # Following values are taken from Upi's chapter on Rallpacks self.RM = args.get('RM', 4.0) self.RA = args.get('RA', 1.0) self.CM = args.get('CM', 0.01) self.Em = args.get('Em', -0.065) self.diameter = diameter self.compLength = length self.computeParams() try: self.mc_ = moose.Compartment(self.path) self.mc_.length = self.compLength self.mc_.diameter = self.diameter self.mc_.Ra = self.Ra self.mc_.Rm = self.Rm self.mc_.Cm = self.Cm self.mc_.Em = self.Em self.mc_.initVm = self.Em except Exception as e: utils.dump("ERROR", [ "Can't create compartment with path %s " % path, "Failed with error %s " % e ]) sys.exit(0)
def getCellPath(self, populationType, instanceId): ''' Given a population type and instanceId, return its path ''' try: path = self.populationDict[populationType][1] except KeyError as e: utils.dump("ERROR", [ "Population type `{0}` not found".format(populationType), "Availale population in network are ", self.populationDict.keys() ]) raise KeyError( "Missing population type : {}".format(populationType)) except Exception as e: raise e try: path = path[instanceId] except KeyError as e: msg = "Population type {} has no instance {}".format( populationType, instanceId) utils.dump("ERROR", [msg, "Available instances are", path.keys()]) raise KeyError(msg) # Now get the path from moose path path = path.path if not re.match(r'(\/\w+)+', path): raise UserWarning("{} is not a valid path".format(path)) return path
def plotVector(self, vector, plotname): ''' Saving input vector to a file ''' name = plotname.replace('/', '_') fileName = os.path.join(self.plotPaths, name) + '.eps' utils.dump("DEBUG", "Saving vector to a file {}".format(fileName)) plt.vlines(vector, 0, 1) plt.savefig(fileName)
def createInputs(self): """ createInputs Create inputs as given in NML file and attach them to moose. """ for inputs in self.network.findall(".//{" + nmu.nml_ns + "}inputs"): units = inputs.attrib['units'] # This dict is to be passed to function which attach an input # element to moose. factors = {} # see pg 219 (sec 13.2) of Book of Genesis if units == 'Physiological Units': factors['Vfactor'] = 1e-3 # V from mV factors['Tfactor'] = 1e-3 # s from ms factors['Ifactor'] = 1e-6 # A from microA else: utils.dump("NOTE", "We got {0}".format(units)) factors['Vfactor'] = 1.0 factors['Tfactor'] = 1.0 factors['Ifactor'] = 1.0 for inputElem in inputs.findall(".//{" + nmu.nml_ns + "}input"): self.attachInputToMoose(inputElem, factors)
def simulate(self, simTime, simDt=1e-3, plotDt=None): '''Simulate the cable ''' if plotDt is None: plotDt = simDt / 2 self.simDt = simDt self.plotDt = plotDt self.setupDUT() # Setup clocks utils.dump("STEP", "Setting up the clocks ... ") moose.setClock(0, self.simDt) moose.setClock(1, self.simDt) moose.setClock(2, self.simDt) ## Use clocksc moose.useClock(0, '/cable/##'.format(self.cablePath), 'process') moose.useClock(1, '/cable/##'.format(self.cablePath), 'init') moose.useClock(2, '{}/##'.format(self.tablePath), 'process') utils.dump("STEP", [ "Simulating cable for {} sec".format(simTime), " simDt: %s, plotDt: %s" % (self.simDt, self.plotDt) ]) self.setupHSolve() moose.reinit() utils.verify() moose.start(simTime)
def getCellPath(self, populationType, instanceId): ''' Given a population type and instanceId, return its path ''' try: path = self.populationDict[populationType][1] except KeyError as e: utils.dump("ERROR" , [ "Population type `{0}` not found".format(populationType) , "Availale population in network are " , self.populationDict.keys() ] ) raise KeyError("Missing population type : {}".format(populationType)) except Exception as e: raise e try: path = path[instanceId] except KeyError as e: msg = "Population type {} has no instance {}".format( populationType , instanceId ) utils.dump("ERROR" , [msg , "Available instances are" , path.keys() ] ) raise KeyError(msg) # Now get the path from moose path path = path.path if not re.match(r'(\/\w+)+', path): raise UserWarning("{} is not a valid path".format(path)) return path
def plotVector(self, vector, plotname): ''' Saving input vector to a file ''' name = plotname.replace('/', '_') fileName = os.path.join(self.plotPaths, name)+'.eps' utils.dump("DEBUG" , "Saving vector to a file {}".format(fileName) ) plt.vlines(vector, 0, 1) plt.savefig(fileName)
def createChannel(species, path, **kwargs): """Create a channel """ if species == 'na': return sodiumChannel(path, **kwargs) elif species == 'ca': channel.Xpower = 4 else: utils.dump("FATAL", "Unsupported channel type: {}".format(species)) raise RuntimeError("Unsupported species of chanel")
def createChannel(species, path, **kwargs): """Create a channel """ if species == 'na': return sodiumChannel( path, **kwargs) elif species == 'ca': channel.Xpower = 4 else: utils.dump("FATAL", "Unsupported channel type: {}".format(species)) raise RuntimeError("Unsupported species of chanel")
def recordAt(self, depth, index): """ Parameter index is python list-like index. Index -1 is the last elements in the list """ utils.dump("RECORD", "Adding probe at index {} and depth {}".format(index, depth)) c = self.cable[depth][index] t = moose.Table("{}/output_at_{}".format(self.tablePath, index)) moose.connect(t, "requestOut", c, "getVm") return t
def makeCable(self, args): ''' Make a cable out of n compartments ''' for i in range(self.ncomp): compPath = '{}/comp{}'.format(self.cablePath, i) l = self.length / self.ncomp d = self.diameter c = comp.MooseCompartment(compPath, l, d, args) self.cable.append(c) self.connect() utils.dump("STEP", "Passive cable is connected and ready for simulation.")
def recordAt(self, depth, index): ''' Parameter index is python list-like index. Index -1 is the last elements in the list ''' utils.dump( "RECORD", "Adding probe at index {} and depth {}".format(index, depth)) c = self.cable[depth][index] t = moose.Table('{}/output_at_{}'.format(self.tablePath, index)) moose.connect(t, 'requestOut', c, 'getVm') return t
def makeCable( self, args ): ''' Make a cable out of n compartments ''' for i in range( self.ncomp ): compPath = '{}/comp{}'.format( self.cablePath, i) l = self.length / self.ncomp d = self.diameter c = comp.MooseCompartment( compPath, l, d, args ) self.cable.append(c) self.connect( ) utils.dump( "STEP" , "Passive cable is connected and ready for simulation." )
def simulate( self, simTime): '''Simulate the cable ''' self.setupDUT( ) utils.dump("STEP" , "Simulating cable for {} sec".format(simTime) ) moose.reinit( ) self.setupHSolve( ) t = time.time() moose.start( simTime ) st = time.time() return st-t
def connectWrapper(self, src, srcF, dest, destF, messageType='Single'): """ Wrapper around moose.connect """ utils.dump("INFO", "Connecting ({4})`\n\t{0},{1}`\n\t`{2},{3}".format( src.path, srcF, dest.path, destF, messageType), frame=inspect.currentframe()) try: res = moose.connect(src, srcF, dest, destF, messageType) assert res, "Failed to connect" except Exception as e: utils.dump("ERROR", "Failed to connect.") raise e
def createProjection(self, projection): projectionName = projection.attrib["name"] utils.dump("INFO", "Projection {0}".format(projectionName)) source = projection.attrib["source"] target = projection.attrib["target"] self.projectionDict[projectionName] = (source,target,[]) # TODO: Assuming that only one element <synapse_props> under # <projection> element. synProps = projection.find(".//{"+nmu.nml_ns+"}synapse_props") options = self.addSyapseProperties(projection, synProps, source, target) connections = projection.findall(".//{"+nmu.nml_ns+"}connection") [self.addConnection(c, projection, options) for c in connections]
def createProjection(self, projection): projectionName = projection.attrib["name"] utils.dump("INFO", "Projection {0}".format(projectionName)) source = projection.attrib["source"] target = projection.attrib["target"] self.projectionDict[projectionName] = (source, target, []) # TODO: Assuming that only one element <synapse_props> under # <projection> element. synProps = projection.find(".//{" + nmu.nml_ns + "}synapse_props") options = self.addSyapseProperties(projection, synProps, source, target) connections = projection.findall(".//{" + nmu.nml_ns + "}connection") [self.addConnection(c, projection, options) for c in connections]
def configureSynChan(self, synObj, synParams={}): '''Configure synapse. If no parameters are given then use the default values. ''' assert (isinstance(synObj, moose.SynChan)) utils.dump("SYNAPSE", "Configuring SynChan") synObj.tau1 = synParams.get('tau1', 5.0) synObj.tau2 = synParams.get('tau2', 1.0) synObj.Gk = synParams.get('Gk', 1.0) synObj.Ek = synParams.get('Ek', 0.0) synObj.synapse.num = synParams.get('synapse_num', 1) synObj.synapse.delay = synParams.get('delay', 1.0) synObj.synapse.weight = synParams.get('weight', 1.0) return synObj
def buildCable(self, args): """ Build binary cable """ self.args = args self.buildParameterLists() # Cable is a list of lists. self.cable = list() for n, (l, d) in enumerate(zip(self.compLengthList, self.compDiamList)): utils.dump("STEP", "Binary tree level {}: length {}, diameter {}".format(n, l, d)) noOfCompartments = pow(2, n) compartmentList = [] for i in range(noOfCompartments): compPath = "{}/comp_{}_{}".format(self.cablePath, n, i) m = comp.MooseCompartment(compPath, l, d, args) compartmentList.append(m.mc_) self.cable.append(compartmentList) self.connectCable()
def configureSynChan(self, synObj, synParams={}): '''Configure synapse. If no parameters are given then use the default values. ''' assert(isinstance(synObj, moose.SynChan)) utils.dump("SYNAPSE" , "Configuring SynChan" ) synObj.tau1 = synParams.get('tau1', 5.0) synObj.tau2 = synParams.get('tau2', 1.0) synObj.Gk = synParams.get('Gk', 1.0) synObj.Ek = synParams.get('Ek', 0.0) synObj.synapse.num = synParams.get('synapse_num', 1) synObj.synapse.delay = synParams.get('delay', 1.0) synObj.synapse.weight = synParams.get('weight', 1.0) return synObj
def simulate(self, simTime, simDt, plotDt=None): """Simulate the cable """ self.simDt = simDt self.setupDUT() # Setup clocks moose.setClock(0, self.simDt) # Use clocks moose.useClock(0, "/##", "process") moose.useClock(0, "/##", "init") utils.dump("STEP", ["Simulating cable for {} sec".format(simTime), " simDt: %s" % self.simDt]) utils.verify() moose.reinit() self.setupSolver() moose.start(simTime)
def buildCable(self, args): ''' Build binary cable ''' self.args = args self.buildParameterLists() # Cable is a list of lists. self.cable = list() for n, (l, d) in enumerate(zip(self.compLengthList, self.compDiamList)): utils.dump( "STEP", "Binary tree level {}: length {}, diameter {}".format(n, l, d)) noOfCompartments = pow(2, n) compartmentList = [] for i in range(noOfCompartments): compPath = '{}/comp_{}_{}'.format(self.cablePath, n, i) m = comp.MooseCompartment(compPath, l, d, args) compartmentList.append(m.mc_) self.cable.append(compartmentList) self.connectCable()
def connectWrapper(self, src, srcF, dest, destF, messageType='Single'): """ Wrapper around moose.connect """ utils.dump("INFO" , "Connecting ({4})`\n\t{0},{1}`\n\t`{2},{3}".format( src.path , srcF , dest.path , destF , messageType ) , frame = inspect.currentframe() ) try: res = moose.connect(src, srcF, dest, destF, messageType) assert res, "Failed to connect" except Exception as e: utils.dump("ERROR", "Failed to connect.") raise e
def simulate(self, simTime, simDt, plotDt=None): '''Simulate the cable ''' self.simDt = simDt self.setupDUT() # Setup clocks moose.setClock(0, self.simDt) # Use clocks moose.useClock(0, '/##', 'process') moose.useClock(0, '/##', 'init') utils.dump("STEP", [ "Simulating cable for {} sec".format(simTime), " simDt: %s" % self.simDt ]) utils.verify() moose.reinit() self.setupSolver() moose.start(simTime)
def readNetworkMLFromFile(self, filename, cellSegmentDict, params={}): """ readNetworkML specify tweak params = { 'excludePopulations':[popname1,...] , 'excludeProjections':[projname1,...] , 'onlyInclude':{'includePopulation':(popname,[id1,...]) ,'includeProjections':(projname1,...) } } If excludePopulations is present, then excludeProjections must also be present. Thus if you exclude some populations, ensure that you exclude projections that refer to those populations also! Though for onlyInclude, you may specify only included cells and this reader will also keep cells connected to those in onlyInclude. This reader first prunes the exclude-s, then keeps the onlyInclude-s and those that are connected. Use 'includeProjections' if you want to keep some projections not connected to the primary 'includePopulation' cells but connected to secondary cells that connected to the primary ones: e.g. baseline synapses on granule cells connected to 'includePopulation' mitrals; these synapses receive file based pre-synaptic events, not presynaptically connected to a cell. """ utils.dump("INFO", "reading file %s ... " % filename) tree = ET.parse(filename) root_element = tree.getroot() utils.dump("INFO", "Tweaking model ... ") utils.tweak_model(root_element, params) utils.dump("INFO", "Loading model into MOOSE ... ") return self.readNetworkML(root_element, cellSegmentDict, params, root_element.attrib['lengthUnits'])
def makeNewSynapse(self, synName, postcomp, synNameFull): '''This function creates a new synapses onto postcomp. SpikeGen is spikeGenerator (presynaptic). SpikeGen connects to SynChan, a synaptic channel which connects to post-synaptic compartment. SpikeGen models the pre-synaptic events. ''' synPath = "%s/%s" % (self.libraryPath, synName) utils.dump("SYNAPSE" , "Creating {} with path {} onto compartment {}".format( synName , synPath , postcomp.path ) ) # if channel does not exist in library load it from xml file if not moose.exists(synPath): utils.dump("SYNAPSE" , "Synaptic Channel {} does not exists. {}".format( synPath, "Loading is from XML file" ) ) cmlR = ChannelML.ChannelML(self.nml_params) cmlR.readChannelMLFromFile(synName+'.xml') # deep copies the library synapse to an instance under postcomp named as # <arg3> if config.disbleCopyingOfObject: utils.dump("WARN" , "Copying existing SynChan ({}) to {}".format( synPath , postcomp ) ) synid = moose.copy(moose.Neutral(synPath), postcomp, synNameFull) else: synid = synPath syn = moose.SynChan(synid) syn = self.configureSynChan(syn, synParams={}) childmgblock = utils.get_child_Mstring(syn,'mgblock') # connect the post compartment to the synapse # If NMDA synapse based on mgblock, connect to mgblock if childmgblock.value == 'True': mgblock = moose.Mg_block(syn.path+'/mgblock') self.connectWrapper(postcomp, "channel", mgblock, "channel") # if SynChan or even NMDAChan, connect normally else: self.connectWrapper(postcomp,"channel", syn, "channel")
def makeNewSynapse(self, synName, postcomp, synNameFull): '''This function creates a new synapses onto postcomp. SpikeGen is spikeGenerator (presynaptic). SpikeGen connects to SynChan, a synaptic channel which connects to post-synaptic compartment. SpikeGen models the pre-synaptic events. ''' synPath = "%s/%s" % (self.libraryPath, synName) utils.dump( "SYNAPSE", "Creating {} with path {} onto compartment {}".format( synName, synPath, postcomp.path)) # if channel does not exist in library load it from xml file if not moose.exists(synPath): utils.dump( "SYNAPSE", "Synaptic Channel {} does not exists. {}".format( synPath, "Loading is from XML file")) cmlR = ChannelML.ChannelML(self.nml_params) cmlR.readChannelMLFromFile(synName + '.xml') # deep copies the library synapse to an instance under postcomp named as # <arg3> if config.disbleCopyingOfObject: utils.dump( "WARN", "Copying existing SynChan ({}) to {}".format( synPath, postcomp)) synid = moose.copy(moose.Neutral(synPath), postcomp, synNameFull) else: synid = synPath syn = moose.SynChan(synid) syn = self.configureSynChan(syn, synParams={}) childmgblock = utils.get_child_Mstring(syn, 'mgblock') # connect the post compartment to the synapse # If NMDA synapse based on mgblock, connect to mgblock if childmgblock.value == 'True': mgblock = moose.Mg_block(syn.path + '/mgblock') self.connectWrapper(postcomp, "channel", mgblock, "channel") # if SynChan or even NMDAChan, connect normally else: self.connectWrapper(postcomp, "channel", syn, "channel")
def readNetworkMLFromFile(self, filename, cellSegmentDict, params={}): """ readNetworkML specify tweak params = { 'excludePopulations':[popname1,...] , 'excludeProjections':[projname1,...] , 'onlyInclude':{'includePopulation':(popname,[id1,...]) ,'includeProjections':(projname1,...) } } If excludePopulations is present, then excludeProjections must also be present. Thus if you exclude some populations, ensure that you exclude projections that refer to those populations also! Though for onlyInclude, you may specify only included cells and this reader will also keep cells connected to those in onlyInclude. This reader first prunes the exclude-s, then keeps the onlyInclude-s and those that are connected. Use 'includeProjections' if you want to keep some projections not connected to the primary 'includePopulation' cells but connected to secondary cells that connected to the primary ones: e.g. baseline synapses on granule cells connected to 'includePopulation' mitrals; these synapses receive file based pre-synaptic events, not presynaptically connected to a cell. """ utils.dump("INFO", "reading file %s ... " % filename) tree = ET.parse(filename) root_element = tree.getroot() utils.dump("INFO", "Tweaking model ... ") utils.tweak_model(root_element, params) utils.dump("INFO", "Loading model into MOOSE ... ") return self.readNetworkML( root_element , cellSegmentDict , params , root_element.attrib['lengthUnits'] )
def readNetworkML(self, network, cellSegmentDict, params={}, lengthUnits="micrometer"): """ This returns populationDict = { 'populationName1':(cellname , {int(instanceid1):moosecell, ...F}) , ... } projectionDict = { 'projectionName1':(source,target ,[(syn_name1,pre_seg_path,post_seg_path),...]) , ... } """ if lengthUnits in ['micrometer', 'micron']: self.length_factor = 1e-6 else: self.length_factor = 1.0 self.network = network self.cellSegmentDict = cellSegmentDict self.params = params utils.dump("STEP", "Creating populations ... ") self.createPopulations() utils.dump("STEP", "Creating connections ... ") self.createProjections() # create connections utils.dump("STEP", "Creating inputs in %s .. " % self.elecPath) # create inputs (only current pulse supported) self.createInputs() return (self.populationDict, self.projectionDict)
def readNetworkML(self, network, cellSegmentDict , params={} , lengthUnits="micrometer"): """ This returns populationDict = { 'populationName1':(cellname , {int(instanceid1):moosecell, ...F}) , ... } projectionDict = { 'projectionName1':(source,target ,[(syn_name1,pre_seg_path,post_seg_path),...]) , ... } """ if lengthUnits in ['micrometer','micron']: self.length_factor = 1e-6 else: self.length_factor = 1.0 self.network = network self.cellSegmentDict = cellSegmentDict self.params = params utils.dump("STEP", "Creating populations ... ") self.createPopulations() utils.dump("STEP", "Creating connections ... ") self.createProjections() # create connections utils.dump("STEP", "Creating inputs in %s .. " % self.elecPath) # create inputs (only current pulse supported) self.createInputs() return (self.populationDict, self.projectionDict)
def connect( self ): ''' Connect the cable ''' utils.dump('STEP', 'Connecting cable ...') for i, c1 in enumerate( self.cable[:-1] ): c2 = self.cable[i+1].mc_ c1.mc_.connect('axial', c2, 'raxial')
def createPopulations(self): """ Create population dictionary. """ populations = self.network.findall(".//{"+nmu.nml_ns+"}population") if not populations: utils.dump("WARN" , [ "No population find in model" , "Searching in namespace {}".format(nmu.nml_ns) ] , frame = inspect.currentframe() ) for population in populations: cellname = population.attrib["cell_type"] populationName = population.attrib["name"] utils.dump("INFO" , "Loading population `{0}`".format(populationName) ) # if cell does not exist in library load it from xml file if not moose.exists(self.libraryPath+'/'+cellname): utils.dump("DEBUG" , "Searching in subdirectories for cell types" + " in `{0}.xml` and `{0}.morph.xml` ".format(cellname) ) mmlR = MorphML.MorphML(self.nml_params) model_filenames = (cellname+'.xml', cellname+'.morph.xml') success = False for modelFile in model_filenames: model_path = nmu.find_first_file(modelFile , self.modelDir ) if model_path is not None: cellDict = mmlR.readMorphMLFromFile(model_path) success = True break if not success: raise IOError( 'For cell {0}: files {1} not found under {2}.'.format( cellname, model_filenames, self.modelDir ) ) self.cellSegmentDict.update(cellDict) if cellname == 'LIF': cellid = moose.LeakyIaF(self.libraryPath+'/'+cellname) else: # added cells as a Neuron class. cellid = moose.Neuron(self.libraryPath+'/'+cellname) self.populationDict[populationName] = (cellname,{}) for instance in population.findall(".//{"+nmu.nml_ns+"}instance"): instanceid = instance.attrib['id'] location = instance.find('./{'+nmu.nml_ns+'}location') rotationnote = instance.find('./{'+nmu.meta_ns+'}notes') if rotationnote is not None: # the text in rotationnote is zrotation=xxxxxxx zrotation = float(rotationnote.text.split('=')[1]) else: zrotation = 0 if cellname == 'LIF': cell = moose.LeakyIaF(cellid) self.populationDict[populationName][1][int(instanceid)] = cell else: # No Cell class in MOOSE anymore! :( addded Neuron class - # Chaitanya cell = moose.Neuron(cellid) self.populationDict[populationName][1][int(instanceid)] = cell x = float(location.attrib['x']) * self.length_factor y = float(location.attrib['y']) * self.length_factor z = float(location.attrib['z']) * self.length_factor self.translate_rotate(cell, x, y, z, zrotation)
def attachInputToMoose(self, inElemXml, factors, savePlot=True): """attachInputToMoose This function create StimulousTable in moose There can be two type of stimulous: random_stim or pulse_input. """ # If /elec doesn't exists it creates /elec and returns a reference to # it. If it does, it just returns its reference. moose.Neutral(self.elecPath) inputName = inElemXml.get('name') random_stim = inElemXml.find('.//{' + nmu.nml_ns + '}random_stim') pulse_stim = inElemXml.find('.//{' + nmu.nml_ns + '}pulse_input') if random_stim is not None: utils.dump("INFO", "Generating random stimulous") utils.dump("TODO", "Test this Poission spike train table") # Get the frequency of stimulus frequency = moose_methods.toFloat( random_stim.get('frequency', '1.0')) / factors['Tfactor'] amplitude = random_stim.get('amplitude', 1.0) synpMechanism = random_stim.get('synaptic_mechanism') # Create random stimulus vec = stimulus.generateSpikeTrainPoission(frequency, dt=self.dt, simTime=self.simTime) # Stimulus table tablePath = os.path.join(self.elecPath, "Stimulus") moose.Neutral(tablePath) stimPath = os.path.join(tablePath, inputName) stim = moose.TimeTable(stimPath) stim.vec = vec if savePlot: self.plotVector(vec, tablePath) target = inElemXml.find(".//{" + nmu.nml_ns + "}target") population = target.get('population') for site in target.findall(".//{" + nmu.nml_ns + "}site"): cell_id = site.attrib['cell_id'] if 'segment_id' in site.attrib: segment_id = site.attrib['segment_id'] else: # default segment_id is specified to be 0 segment_id = 0 # To find the cell name fetch the first element of tuple. cell_name = self.populationDict[population][0] if cell_name == 'LIF': utils.dump("NOTE", "LIF cell_name. Partial implementation", frame=inspect.currentframe()) LIF = self.populationDict[population][1][int(cell_id)] m = self.connectSynapse(stim, LIF) else: segId = '{0}'.format(segment_id) segment_path = self.populationDict[population][1]\ [int(cell_id)].path + '/' + \ self.cellSegmentDict[cell_name][segId][0] compartment = moose.Compartment(segment_path) synchan = moose.SynChan( os.path.join(compartment.path, '/synchan')) synchan.Gbar = 1e-6 synchan.Ek = 0.0 self.connectWrapper(synchan, 'channel', compartment, 'channel') synchan.numSynapses = 1 m = self.connectSynapse( stim, moose.element(synchan.path + '/synapse')) elif pulse_stim is not None: Ifactor = factors['Ifactor'] Tfactor = factors['Tfactor'] pulseinput = inElemXml.find(".//{" + nmu.nml_ns + "}pulse_input") if pulseinput is None: utils.dump("WARN", "This type of stimulous is not supported.", frame=inspect.currentframe()) return self.pulseGenPath = self.elecPath + '/PulseGen' moose.Neutral(self.pulseGenPath) pulseGenPath = '{}/{}'.format(self.pulseGenPath, inputName) pulsegen = moose.PulseGen(pulseGenPath) icClampPath = '{}/{}'.format(self.elecPath, 'iClamp') moose.Neutral(icClampPath) iclamp = moose.DiffAmp('{}/{}'.format(icClampPath, inputName)) iclamp.saturation = 1e6 iclamp.gain = 1.0 # free run pulsegen.trigMode = 0 pulsegen.baseLevel = 0.0 pulsegen.firstDelay = float(pulseinput.attrib['delay']) * Tfactor pulsegen.firstWidth = float( pulseinput.attrib['duration']) * Tfactor pulsegen.firstLevel = float( pulseinput.attrib['amplitude']) * Ifactor # to avoid repeat pulsegen.secondDelay = 1e6 pulsegen.secondLevel = 0.0 pulsegen.secondWidth = 0.0 # do not set count to 1, let it be at 2 by default else it will # set secondDelay to 0.0 and repeat the first pulse! #pulsegen.count = 1 self.connectWrapper(pulsegen, 'output', iclamp, 'plusIn') # Attach targets target = inElemXml.find(".//{" + nmu.nml_ns + "}target") population = target.attrib['population'] for site in target.findall(".//{" + nmu.nml_ns + "}site"): cell_id = site.attrib['cell_id'] if 'segment_id' in site.attrib: segment_id = site.attrib['segment_id'] else: # default segment_id is specified to be 0 segment_id = 0 # population is populationName, # self.populationDict[population][0] is cellname cell_name = self.populationDict[population][0] if cell_name == 'LIF': debug.printDebut("TODO", "Rewrite this section", frame=inspect.currentframe()) continue LIF = self.populationDict[population][1][int(cell_id)] self.connectWrapper(iclamp, 'output', LIF, 'injectMsg') else: segment_path = self.populationDict[population][1]\ [int(cell_id)].path+'/'+\ self.cellSegmentDict[cell_name][segment_id][0] compartment = moose.Compartment(segment_path) self.connectWrapper(iclamp, 'output', compartment, 'injectMsg')
def addConnection(self, connection, projection, options): """ This function adds connection """ synName = options['syn_name'] source = options['source'] target = options['target'] weight = options['weight'] threshold = options['threshold'] propDelay = options['prop_delay'] projectionName = projection.attrib['name'] pre_cell_id = connection.attrib['pre_cell_id'] post_cell_id = connection.attrib['post_cell_id'] if 'file' not in pre_cell_id: # source could be 'mitrals', self.populationDict[source][0] would be # 'mitral' pre_cell_id = int(pre_cell_id) post_cell_id = int(post_cell_id) pre_cell_name = self.populationDict[source][0] pre_segment_id = connection.attrib.get('pre_segment_id', 0) pre_segment_path = "{0}/{1}".format( self.getCellPath(source, pre_cell_id) , self.cellSegmentDict[pre_cell_name][pre_segment_id][0] ) else: # I've removed extra excitation provided via files, so below comment # doesn't apply. 'file[+<glomnum>]_<filenumber>' # glomnum is for # mitral_granule extra excitation from unmodelled sisters. pre_segment_path = "{}_{}".format( pre_cell_id , connection.attrib['pre_segment_id'] ) # target could be 'PGs', self.populationDict[target][0] would be 'PG' post_cell_name = self.populationDict[target][0] post_segment_id = connection.attrib.get('post_segment_id', '0') post_segment_path = "{}/{}".format( self.getCellPath(target, post_cell_id) , self.cellSegmentDict[post_cell_name][post_segment_id][0] ) try: self.projectionDict[projectionName][2].append( (synName , pre_segment_path, post_segment_path) ) except KeyError as e: utils.dump("ERR", "Failed find key {0}".format(e) , frame = inspect.currentframe()) print(self.projectionDict.keys()) sys.exit(0) properties = connection.findall('./{'+nmu.nml_ns+'}properties') if len(properties) == 0: self.connectUsingSynChan(synName, pre_segment_path, post_segment_path , weight, threshold, propDelay ) else: [self.addProperties(pre_segment_path, post_segment_path, p, options) for p in properties]
def createPopulations(self): """ Create population dictionary. """ populations = self.network.findall(".//{" + nmu.nml_ns + "}population") if not populations: utils.dump("WARN", [ "No population find in model", "Searching in namespace {}".format(nmu.nml_ns) ], frame=inspect.currentframe()) for population in populations: cellname = population.attrib["cell_type"] populationName = population.attrib["name"] utils.dump("INFO", "Loading population `{0}`".format(populationName)) # if cell does not exist in library load it from xml file if not moose.exists(self.libraryPath + '/' + cellname): utils.dump( "DEBUG", "Searching in subdirectories for cell types" + " in `{0}.xml` and `{0}.morph.xml` ".format(cellname)) mmlR = MorphML.MorphML(self.nml_params) model_filenames = (cellname + '.xml', cellname + '.morph.xml') success = False for modelFile in model_filenames: model_path = nmu.find_first_file(modelFile, self.modelDir) if model_path is not None: cellDict = mmlR.readMorphMLFromFile(model_path) success = True break if not success: raise IOError( 'For cell {0}: files {1} not found under {2}.'.format( cellname, model_filenames, self.modelDir)) self.cellSegmentDict.update(cellDict) if cellname == 'LIF': cellid = moose.LeakyIaF(self.libraryPath + '/' + cellname) else: # added cells as a Neuron class. cellid = moose.Neuron(self.libraryPath + '/' + cellname) self.populationDict[populationName] = (cellname, {}) for instance in population.findall(".//{" + nmu.nml_ns + "}instance"): instanceid = instance.attrib['id'] location = instance.find('./{' + nmu.nml_ns + '}location') rotationnote = instance.find('./{' + nmu.meta_ns + '}notes') if rotationnote is not None: # the text in rotationnote is zrotation=xxxxxxx zrotation = float(rotationnote.text.split('=')[1]) else: zrotation = 0 if cellname == 'LIF': cell = moose.LeakyIaF(cellid) self.populationDict[populationName][1][int( instanceid)] = cell else: # No Cell class in MOOSE anymore! :( addded Neuron class - # Chaitanya cell = moose.Neuron(cellid) self.populationDict[populationName][1][int( instanceid)] = cell x = float(location.attrib['x']) * self.length_factor y = float(location.attrib['y']) * self.length_factor z = float(location.attrib['z']) * self.length_factor self.translate_rotate(cell, x, y, z, zrotation)
def connectUsingSynChan(self, synName, prePath, post_path, weight, threshold, delay): """ Connect two compartments using SynChan """ postcomp = moose.Compartment(post_path) # We usually try to reuse an existing SynChan - event based SynChans # have an array of weights and delays and can represent multiple # synapses i.e. a new element of the weights and delays array is # created every time a 'synapse' message connects to the SynChan (from # 'event' of spikegen) BUT for a graded synapse with a lookup table # output connected to 'activation' message, not to 'synapse' message, we # make a new synapse everytime ALSO for a saturating synapse i.e. # KinSynChan, we always make a new synapse as KinSynChan is not meant to # represent multiple synapses libsyn = moose.SynChan(self.libraryPath + '/' + synName) gradedchild = utils.get_child_Mstring(libsyn, 'graded') # create a new synapse if libsyn.className == 'KinSynChan' or gradedchild.value == 'True': synNameFull = moose_methods.moosePath(synName, utils.underscorize(prePath)) synObj = self.makeNewSynapse(synName, postcomp, synNameFull) else: # See debug/bugs for more details. # NOTE: Change the debug/bugs to enable/disable this bug. if bugs.BUG_NetworkML_500: utils.dump("INFO", "See the code. There might be a bug here", frame=inspect.currentframe()) synNameFull = moose_methods.moosePath( synName, utils.underscorize(prePath)) synObj = self.makeNewSynapse(synName, postcomp, synNameFull) else: # If the above bug is fixed. synNameFull = synName if not moose.exists(post_path + '/' + synNameFull): synObj = self.makeNewSynapse(synName, postcomp, synNameFull) # wrap the synapse in this compartment synPath = moose_methods.moosePath(post_path, synNameFull) syn = moose.SynChan(synPath) gradedchild = utils.get_child_Mstring(syn, 'graded') # weights are set at the end according to whether the synapse is graded # or event-based # connect pre-comp Vm (if graded) OR spikegen/timetable (if event-based) # to the synapse # graded synapse if gradedchild.value == 'True': table = moose.Table(syn.path + "/graded_table") # always connect source to input - else 'cannot create message' # error. precomp = moose.Compartment(prePath) self.connectWrapper(precomp, "VmOut", table, "msgInput") # since there is no weight field for a graded synapse # (no 'synapse' message connected), # I set the Gbar to weight*Gbar syn.Gbar = weight * syn.Gbar # Event based synapse else: # synapse could be connected to spikegen at pre-compartment OR a # file! if 'file' not in prePath: precomp = moose.Compartment(prePath) if not moose.exists(prePath + '/IaF_spikegen'): # if spikegen for this synapse doesn't exist in this # compartment, create it spikegens for different synapse_types # can have different thresholds if not moose.exists(prePath + '/' + synName + '_spikegen'): spikegen = moose.SpikeGen(prePath + '/' + synName + '_spikegen') # spikegens for different synapse_types can have different # thresholds spikegen.threshold = threshold # This ensures that spike is generated only on leading edge. spikegen.edgeTriggered = 1 # usually events are raised at every time step that Vm > # Threshold, can set either edgeTriggered as above or # refractT #spikegen.refractT = 0.25e-3 # wrap the spikegen in this compartment spikegen = moose.SpikeGen(prePath + '/' + synName + '_spikegen') else: spikegen = moose.SpikeGen(prePath + '/IaF_spikegen') # connect the spikegen to the synapse note that you need to use # Synapse (auto-created) under SynChan to get/set weights , # addSpike-s etc. can get the Synapse element by # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase is # an array element, first add to it, to addSpike-s, get/set # weights, etc. syn.numSynapses += 1 m = self.connectSynapse(spikegen, syn) else: # if connected to a file, create a timetable, # put in a field specifying the connected filenumbers to this segment, # and leave it for simulation-time connection ## prePath is 'file[+<glomnum>]_<filenum1>[_<filenum2>...]' i.e. glomnum could be present filesplit = prePath.split('+') if len(filesplit) == 2: glomsplit = filesplit[1].split('_', 1) glomstr = '_' + glomsplit[0] filenums = glomsplit[1] else: glomstr = '' filenums = prePath.split('_', 1)[1] tt_path = postcomp.path + '/' + synNameFull + glomstr + '_tt' if not moose.exists(tt_path): # if timetable for this synapse doesn't exist in this # compartment, create it, and add the field 'fileNumbers' tt = moose.TimeTable(tt_path) tt.addField('fileNumbers') tt.setField('fileNumbers', filenums) # Be careful to connect the timetable only once while # creating it as below: note that you need to use Synapse # (auto-created) under SynChan to get/set weights , # addSpike-s etc. can get the Synapse element by # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase # is an array element, first add to it, to addSpike-s, # get/set weights, etc. syn.numSynapses += 1 m = self.connectSynapse(spikegen, syn.synapse) else: # if it exists, append file number to the field 'fileNumbers' tt = moose.TimeTable(tt_path) # append filenumbers from # 'file[+<glomnum>]_<filenumber1>[_<filenumber2>...]' filenums = moose_methods.moosePath( tt.getField('fileNumbers'), filenums) tt.setField('fileNumbers', filenums) # syn.Gbar remains the same, but we play with the weight which is a # factor to Gbar The delay and weight can be set only after # connecting a spike event generator. delay and weight are arrays: # multiple event messages can be connected to a single synapse first # argument below is the array index, we connect to the latest # synapse created above But KinSynChan ignores weight of the # synapse, so set the Gbar for it if libsyn.className == 'KinSynChan': syn.Gbar = weight * syn.Gbar else: # note that you need to use Synapse (auto-created) under SynChan # to get/set weights , addSpike-s etc. can get the Synpase # element by moose.Synapse(syn.path+'/synapse') or syn.synapse syn.synapse[-1].weight = weight syn.synapse[-1].delay = delay # seconds
def connect(self): ''' Connect the cable ''' utils.dump('STEP', 'Connecting cable ...') for i, c1 in enumerate(self.cable[:-1]): c2 = self.cable[i + 1].mc_ c1.mc_.connect('axial', c2, 'raxial')
def attachInputToMoose(self, inElemXml, factors, savePlot=True): """attachInputToMoose This function create StimulousTable in moose There can be two type of stimulous: random_stim or pulse_input. """ # If /elec doesn't exists it creates /elec and returns a reference to # it. If it does, it just returns its reference. moose.Neutral(self.elecPath) inputName = inElemXml.get('name') random_stim = inElemXml.find('.//{'+nmu.nml_ns+'}random_stim') pulse_stim = inElemXml.find('.//{'+nmu.nml_ns+'}pulse_input') if random_stim is not None: utils.dump("INFO", "Generating random stimulous") utils.dump("TODO", "Test this Poission spike train table") # Get the frequency of stimulus frequency = moose_methods.toFloat( random_stim.get('frequency', '1.0') ) / factors['Tfactor'] amplitude = random_stim.get('amplitude', 1.0) synpMechanism = random_stim.get('synaptic_mechanism') # Create random stimulus vec = stimulus.generateSpikeTrainPoission(frequency , dt=self.dt , simTime=self.simTime ) # Stimulus table tablePath = os.path.join(self.elecPath, "Stimulus") moose.Neutral(tablePath) stimPath = os.path.join(tablePath, inputName) stim = moose.TimeTable(stimPath) stim.vec = vec if savePlot: self.plotVector(vec, tablePath) target = inElemXml.find(".//{"+nmu.nml_ns+"}target") population = target.get('population') for site in target.findall(".//{"+nmu.nml_ns+"}site"): cell_id = site.attrib['cell_id'] if 'segment_id' in site.attrib: segment_id = site.attrib['segment_id'] else: # default segment_id is specified to be 0 segment_id = 0 # To find the cell name fetch the first element of tuple. cell_name = self.populationDict[population][0] if cell_name == 'LIF': utils.dump("NOTE", "LIF cell_name. Partial implementation" , frame = inspect.currentframe() ) LIF = self.populationDict[population][1][int(cell_id)] m = self.connectSynapse(stim, LIF) else: segId = '{0}'.format(segment_id) segment_path = self.populationDict[population][1]\ [int(cell_id)].path + '/' + \ self.cellSegmentDict[cell_name][segId][0] compartment = moose.Compartment(segment_path) synchan = moose.SynChan( os.path.join(compartment.path , '/synchan') ) synchan.Gbar = 1e-6 synchan.Ek = 0.0 self.connectWrapper(synchan, 'channel', compartment, 'channel') synchan.numSynapses = 1 m = self.connectSynapse(stim, moose.element(synchan.path+'/synapse')) elif pulse_stim is not None: Ifactor = factors['Ifactor'] Tfactor = factors['Tfactor'] pulseinput = inElemXml.find(".//{"+nmu.nml_ns+"}pulse_input") if pulseinput is None: utils.dump("WARN" , "This type of stimulous is not supported." , frame = inspect.currentframe() ) return self.pulseGenPath = self.elecPath + '/PulseGen' moose.Neutral(self.pulseGenPath) pulseGenPath = '{}/{}'.format(self.pulseGenPath, inputName) pulsegen = moose.PulseGen(pulseGenPath) icClampPath = '{}/{}'.format(self.elecPath, 'iClamp') moose.Neutral(icClampPath) iclamp = moose.DiffAmp('{}/{}'.format(icClampPath, inputName)) iclamp.saturation = 1e6 iclamp.gain = 1.0 # free run pulsegen.trigMode = 0 pulsegen.baseLevel = 0.0 pulsegen.firstDelay = float(pulseinput.attrib['delay'])*Tfactor pulsegen.firstWidth = float(pulseinput.attrib['duration'])*Tfactor pulsegen.firstLevel = float(pulseinput.attrib['amplitude'])*Ifactor # to avoid repeat pulsegen.secondDelay = 1e6 pulsegen.secondLevel = 0.0 pulsegen.secondWidth = 0.0 # do not set count to 1, let it be at 2 by default else it will # set secondDelay to 0.0 and repeat the first pulse! #pulsegen.count = 1 self.connectWrapper(pulsegen,'output', iclamp, 'plusIn') # Attach targets target = inElemXml.find(".//{"+nmu.nml_ns+"}target") population = target.attrib['population'] for site in target.findall(".//{"+nmu.nml_ns+"}site"): cell_id = site.attrib['cell_id'] if 'segment_id' in site.attrib: segment_id = site.attrib['segment_id'] else: # default segment_id is specified to be 0 segment_id = 0 # population is populationName, # self.populationDict[population][0] is cellname cell_name = self.populationDict[population][0] if cell_name == 'LIF': debug.printDebut("TODO" , "Rewrite this section" , frame = inspect.currentframe() ) continue LIF = self.populationDict[population][1][int(cell_id)] self.connectWrapper(iclamp,'output',LIF,'injectMsg') else: segment_path = self.populationDict[population][1]\ [int(cell_id)].path+'/'+\ self.cellSegmentDict[cell_name][segment_id][0] compartment = moose.Compartment(segment_path) self.connectWrapper(iclamp ,'output' , compartment ,'injectMsg' )
def connectUsingSynChan(self, synName, prePath, post_path , weight, threshold, delay ): """ Connect two compartments using SynChan """ postcomp = moose.Compartment(post_path) # We usually try to reuse an existing SynChan - event based SynChans # have an array of weights and delays and can represent multiple # synapses i.e. a new element of the weights and delays array is # created every time a 'synapse' message connects to the SynChan (from # 'event' of spikegen) BUT for a graded synapse with a lookup table # output connected to 'activation' message, not to 'synapse' message, we # make a new synapse everytime ALSO for a saturating synapse i.e. # KinSynChan, we always make a new synapse as KinSynChan is not meant to # represent multiple synapses libsyn = moose.SynChan(self.libraryPath+'/'+synName) gradedchild = utils.get_child_Mstring(libsyn, 'graded') # create a new synapse if libsyn.className == 'KinSynChan' or gradedchild.value == 'True': synNameFull = moose_methods.moosePath(synName , utils.underscorize(prePath) ) synObj = self.makeNewSynapse(synName, postcomp, synNameFull) else: # See debug/bugs for more details. # NOTE: Change the debug/bugs to enable/disable this bug. if bugs.BUG_NetworkML_500: utils.dump("INFO" , "See the code. There might be a bug here" , frame = inspect.currentframe() ) synNameFull = moose_methods.moosePath(synName , utils.underscorize(prePath) ) synObj = self.makeNewSynapse(synName, postcomp, synNameFull) else: # If the above bug is fixed. synNameFull = synName if not moose.exists(post_path+'/'+synNameFull): synObj = self.makeNewSynapse(synName, postcomp, synNameFull) # wrap the synapse in this compartment synPath = moose_methods.moosePath(post_path, synNameFull) syn = moose.SynChan(synPath) gradedchild = utils.get_child_Mstring(syn, 'graded') # weights are set at the end according to whether the synapse is graded # or event-based # connect pre-comp Vm (if graded) OR spikegen/timetable (if event-based) # to the synapse # graded synapse if gradedchild.value=='True': table = moose.Table(syn.path+"/graded_table") # always connect source to input - else 'cannot create message' # error. precomp = moose.Compartment(prePath) self.connectWrapper(precomp, "VmOut", table, "msgInput") # since there is no weight field for a graded synapse # (no 'synapse' message connected), # I set the Gbar to weight*Gbar syn.Gbar = weight * syn.Gbar # Event based synapse else: # synapse could be connected to spikegen at pre-compartment OR a # file! if 'file' not in prePath: precomp = moose.Compartment(prePath) if not moose.exists(prePath+'/IaF_spikegen'): # if spikegen for this synapse doesn't exist in this # compartment, create it spikegens for different synapse_types # can have different thresholds if not moose.exists(prePath+'/'+synName+'_spikegen'): spikegen = moose.SpikeGen(prePath+'/'+synName+'_spikegen') # spikegens for different synapse_types can have different # thresholds spikegen.threshold = threshold # This ensures that spike is generated only on leading edge. spikegen.edgeTriggered = 1 # usually events are raised at every time step that Vm > # Threshold, can set either edgeTriggered as above or # refractT #spikegen.refractT = 0.25e-3 # wrap the spikegen in this compartment spikegen = moose.SpikeGen(prePath+'/'+synName+'_spikegen') else: spikegen = moose.SpikeGen(prePath+'/IaF_spikegen') # connect the spikegen to the synapse note that you need to use # Synapse (auto-created) under SynChan to get/set weights , # addSpike-s etc. can get the Synapse element by # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase is # an array element, first add to it, to addSpike-s, get/set # weights, etc. syn.numSynapses += 1 m = self.connectSynapse(spikegen, syn) else: # if connected to a file, create a timetable, # put in a field specifying the connected filenumbers to this segment, # and leave it for simulation-time connection ## prePath is 'file[+<glomnum>]_<filenum1>[_<filenum2>...]' i.e. glomnum could be present filesplit = prePath.split('+') if len(filesplit) == 2: glomsplit = filesplit[1].split('_', 1) glomstr = '_'+glomsplit[0] filenums = glomsplit[1] else: glomstr = '' filenums = prePath.split('_', 1)[1] tt_path = postcomp.path+'/'+synNameFull+glomstr+'_tt' if not moose.exists(tt_path): # if timetable for this synapse doesn't exist in this # compartment, create it, and add the field 'fileNumbers' tt = moose.TimeTable(tt_path) tt.addField('fileNumbers') tt.setField('fileNumbers',filenums) # Be careful to connect the timetable only once while # creating it as below: note that you need to use Synapse # (auto-created) under SynChan to get/set weights , # addSpike-s etc. can get the Synapse element by # moose.Synapse(syn.path+'/synapse') or syn.synapse Synpase # is an array element, first add to it, to addSpike-s, # get/set weights, etc. syn.numSynapses += 1 m = self.connectSynapse(spikegen, syn.synapse) else: # if it exists, append file number to the field 'fileNumbers' tt = moose.TimeTable(tt_path) # append filenumbers from # 'file[+<glomnum>]_<filenumber1>[_<filenumber2>...]' filenums = moose_methods.moosePath(tt.getField('fileNumbers') , filenums) tt.setField('fileNumbers', filenums) # syn.Gbar remains the same, but we play with the weight which is a # factor to Gbar The delay and weight can be set only after # connecting a spike event generator. delay and weight are arrays: # multiple event messages can be connected to a single synapse first # argument below is the array index, we connect to the latest # synapse created above But KinSynChan ignores weight of the # synapse, so set the Gbar for it if libsyn.className == 'KinSynChan': syn.Gbar = weight*syn.Gbar else: # note that you need to use Synapse (auto-created) under SynChan # to get/set weights , addSpike-s etc. can get the Synpase # element by moose.Synapse(syn.path+'/synapse') or syn.synapse syn.synapse[-1].weight = weight syn.synapse[-1].delay = delay # seconds