def plasticity_test(model, syncomp=None, syn_pop=None, stimtimes=None): syntype = model.CaPlasticityParams.Plas_syn.Name if stimtimes is None: stimtimes = [.1, .12] if syncomp is None: path = model.neurons[list(model.neurons)[0]].path syncomp = moose.wildcardFind(path + '/##/' + syntype + '[ISA=SynChan]')[0].parent plast = {} stimtab = {} if model.calYN and model.plasYN: neu = moose.Neutral('/input') for neurtype in util.neurontypes(model.param_cond): stimtab[neurtype] = moose.TimeTable('%s/TimTab%s' % (neu.path, neurtype)) stimtab[neurtype].vector = stimtimes print('**** plasticity test ********', syntype, neurtype, syncomp) #synchan=moose.element(syn_pop[neurtype][syntype][syncomp]) synchan = moose.element(syncomp.path + '/' + syntype) sh = synchan.children[0] log.info('Synapse added to {.path}', synchan) connect.synconn(sh, 0, stimtab[neurtype], model.param_syn) ###Synaptic Plasticity plast[neurtype] = plasticity.plasticity2( synchan, model.CaPlasticityParams.Plas_syn) return plast, stimtab
def HookUpDend(model,dendrite,container): if model.Stimulation.StimLoc.spine_density>0: num_spines,synchans=enumerate_spine_synchans(model,dendrite) tt_root_name=container.path+'/TimTab'+dendrite.name else: num_spines=1 synchans={dendrite.name:[dendrite.path+'/'+model.Stimulation.StimLoc.syntype]} tt_root_name=container.path+'/TimTab' print('HookUpDend, syn:', synchans,num_spines) if getattr(model.Stimulation.StimLoc,'weight',None): weight=model.Stimulation.StimLoc.weight else: weight=1 time_tables = MakeTimeTables(model.Stimulation,num_spines) freq=model.Stimulation.Paradigm.f_pulse print('HookUpDend, tt:', time_tables) stimtab = {} stim_syn = {} for spine in time_tables: stimtab[spine] = moose.TimeTable('%s_%s_%s' % (tt_root_name,str(spine),str(int(freq)))) stimtab[spine].vector = np.array(time_tables[spine]) stimtab[spine].tick=7#moose.element(synchans[spine][0]).tick print('HUD,stimtab {} '.format(stimtab),'tick',stimtab[spine].tick) for synchan in synchans[spine]: synapse = moose.element(synchan+'/SH') print('**** ready to connect',synapse.path,stimtab[spine].vector,model.Stimulation.Paradigm.name,model.Stimulation.StimLoc.stim_dendrites,'weight=',weight) #connect.plain_synconn(synapse,stimtab[spine],0) connect.synconn(synapse.path,0,stimtab[spine],model.param_syn,weight=weight) stim_syn[synchan]=(stimtab[spine],synapse,synapse.synapse.num-1) return stimtab,synchans,stim_syn
def connectORNs(self): self.spiketable = moose.TimeTable(self.path + '/tt') #### SynChan's synapse MsgDest takes time as its argument. Thus spiketable should contain a list of spike times. self.spiketable.connect("event", self._ExcORNSyn, "synapse") self.spiketable.connect("event", self._InhORNSyn, "synapse") self._ExcORNSyn.setWeight( 0, 1) # 0th element in synaptic array set to weight 1 self._InhORNSyn.setDelay(0, 7.6337e-3) # seconds self._InhORNSyn.setWeight( 0, 1) # 0th element in synaptic array set to weight 1
def timetable_file(filename='timetable.txt'): """Create a TimeTable and populate it from file specified by `filename`. If `filename` does not exist, a file of the same name is created and a random series of spike times is saved in it""" if not os.access(filename, os.R_OK): times = generate_poisson_times(rate=10, simtime=simtime, seed=1) np.savetxt(filename, times) model = moose.Neutral('/model') tt = moose.TimeTable('%s/tt_file' % (model.path)) tt.filename = filename return tt, np.loadtxt(filename),
def timetable_nparray(): """Create a time table and populate it with numpy array. The `vec` field in a Table can be directly assigned a sequence to fill the table entries. """ times = generate_poisson_times(rate=20, simtime=simtime, seed=1) model = moose.Neutral('/model') tt = moose.TimeTable('%s/tt_array' % (model.path)) tt.vector = times return tt, times,
def HookUpDend(model, dendrite, container): #for dend in model.Stimulation.StimParams.which_dendrites: my_spines = list( set(moose.element(dendrite).neighbors['handleAxial']).intersection( set(moose.element(dendrite).children))) spine_no = len(my_spines) if not spine_no: return synapses = {} for spine in my_spines: spine_no = int(''.join(c for c in spine.name if c.isdigit())) synapses[spine_no] = [] heads = moose.element(spine).neighbors['handleAxial'] for head in heads: moose_head = moose.element(head) for child in moose_head.children: moose_child = moose.element(child) if moose_child.className == 'SynChan' or moose_child.className == 'NMDAChan': synapses[spine_no].append(moose_child) time_tables = MakeTimeTables(model.Stimulation, spine_no) stimtab = {} stim_synapses = {} for spine in time_tables: stimtab[spine] = moose.TimeTable( '%s/TimTab%s_%s' % (container.path, dendrite.name, str(spine))) stimtab[spine].vector = np.array(time_tables[spine]) for synapse in synapses[spine]: synchan = moose.element(synapse) print(synapse.path, time_tables[spine]) connect.plain_synconn(synchan, stimtab[spine], 0) synname = util.syn_name(synchan.path, spines.NAME_HEAD) if model.desenYN and model.DesensitizationParams[synchan.name]: dep, weight = plasticity.desensitization( synchan, model.DesensitizationParams[synchan.name]) stim_synapses[synname] = {} stim_synapses[synname]['plas'] = dep stim_synapses[synname]['cum'] = weight stim_synapses[synname]['syn'] = synchan synchan.Gbar = synchan.Gbar / 2 return stim_synapses
def createTimeTables(inputList, model, n_per_syn=1, start_time=0.05, freq=500.0): from moose_nerp.prototypes import connect num = len(inputList) for i, input in enumerate(inputList): sh = moose.element(input.path + '/SH') tt = moose.TimeTable(input.path + '/tt') tt.vector = [ start_time + i * 1. / freq + j * num * 1. / freq for j in range(n_per_syn) ] #print(tt.vector) connect.synconn(sh.path, False, tt, model.param_syn, mindel=0)
def create(self): path = "/input" if not moose.exists('/input'): moose.Neutral('/input') spike_file = np.load(self.filename + '.npz', encoding='latin1') spike_times = spike_file['spikeTime'] self.numtt = len(spike_times) print('creating', self, self.tablename, self.filename, 'AVAILABLE trains: ', self.numtt) self.stimtab = [] for ii, stimtimes in enumerate(spike_times): self.stimtab.append([ moose.TimeTable('{}/{}_TimTab{}'.format( path, self.tablename, ii)), self.syn_per_tt ]) self.stimtab[ii][0].vector = stimtimes
def plasticity_test(model, syncomp, syn_pop, stimtimes): plast = {} stimtab = {} if model.calYN and model.plasYN: neu = moose.Neutral('/input') for neurtype in model.neurontypes(): stimtab[neurtype] = moose.TimeTable('%s/TimTab%s' % (neu.path, neurtype)) stimtab[neurtype].vector = stimtimes syntype = model.CaPlasticityParams.Plas_syn.Name print(syntype, neurtype, syncomp) synchan = moose.element(syn_pop[neurtype][syntype][syncomp]) log.info('Synapse added to {.path}', synchan) connect.synconn(synchan, 0, stimtab[neurtype], model.param_syn) ###Synaptic Plasticity plast[neurtype] = plasticity.plasticity( synchan, model.CaPlasticityParams.Plas_syn) return plast, stimtab
def attachORNs(cell, ORNCellSynapse, numORNSyns): ##### Inhibitory Synapse NOT added as I am not sure if it is due to PG inhibition - Perhaps Cleland and Sethupathy also did not model it ##### Excitatory + Inhibitory(not added) Synapse combo taken from the paper Djurisic etal 2008 JNeurosci. ##### Actually it's only an excitatory synapse, but they have used the inhibitory one to model the later time course. ##### Though this might be needed to account for PG cell inhibition? ##### Gbar-s have been set to ensure 16mV EPSP at the glom tuft as done in the paper. ##### Paper's defaults give only 8mV EPSP peak at glom tuft. So here multiplied by two. Cannot use supplemental table values as no cytoplasmic resistivity Ri in this model. Only axial resistance from glom to prim which doesn't matter much [maybe it does - loading rather than input resistance?]. Makes sense only if dendritic tree with many compartments. ##### Also no idea of how much to change the inhibitory part without Ri, so multiplied that also by 2 synapse_list = [] for compartment in cell.getChildren(cell.id): # compartments for child in moose.Neutral(compartment).getChildren(compartment): # channels and synapses if moose.Neutral(child).name in [ORNCellSynapse]: synapse_list.append(moose.SynChan(child)) spikeTableList = [] for i in range(numORNSyns): synapse = synapse_list[int(uniform(0,len(synapse_list)))] # Bad practice - This should be part of NetworkML - no random numbers in simulations, only in generators. print "Connecting ", synapse.path spiketable = moose.TimeTable(synapse.path+'/tt_'+str(i)) #### SynChan's synapse MsgDest takes time as its argument. Thus spiketable should contain a list of spike times. spiketable.connect("event", synapse,"synapse") synapse.setWeight(0, 1) # 0th element in synaptic array set to weight 1 spikeTableList.append(spiketable) return spikeTableList
def connect(self, syn_name, pre_path, post_path, weight, threshold, delay): postcomp = moose.Compartment(post_path) ## We usually try to reuse an existing SynChan & SynHandler - ## event based SynHandlers have an array of weights and delays and can represent multiple synapses, ## so a new element of the weights and delays array is created ## every time a 'synapse' message connects to the SynHandler (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('/library/' + syn_name) gradedchild = utils.get_child_Mstring(libsyn, 'graded') if libsyn.className == 'KinSynChan' or gradedchild.value == 'True': # create a new synapse syn_name_full = syn_name + '_' + utils.underscorize(pre_path) make_new_synapse(syn_name, postcomp, syn_name_full, self.nml_params) else: ## if syn doesn't exist in this compartment, create it syn_name_full = syn_name if not moose.exists(post_path + '/' + syn_name_full): make_new_synapse(syn_name, postcomp, syn_name_full, self.nml_params) ## moose.element is a function that checks if path exists, ## and returns the correct object, here SynChan syn = moose.element( post_path + '/' + syn_name_full) # wrap the SynChan in this compartment synhandler = moose.element(post_path + '/' + syn_name_full + '/handler') # wrap the SynHandler gradedchild = utils.get_child_Mstring(syn, 'graded') #### weights are set at the end according to whether the synapse is graded or event-based #### If graded, connect pre-comp Vm to the table which is connected to SynChan's activation #### If event-based, connect spikegen/timetable's spikeOut to Simple/STDP SynHandler's addSpike ## I rely on second term below not being evaluated if first term is None; ## otherwise None.value gives error. if gradedchild is not None and gradedchild.value == 'True': # graded synapse interpol = moose.element(syn.path + "/graded_table") #### always connect source to input - else 'cannot create message' error. precomp = moose.Compartment(pre_path) moose.connect(precomp, "VmOut", interpol, "input") try: tau_table = moose.element(syn.path + '/tau_table') tau_table_present = True except ValueError: tau_table_present = False # if tau_table is not found, don't connect it if tau_table_present: moose.connect(precomp, 'VmOut', tau_table, 'input') ## 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 else: # Event based synapse ## synapse could be connected to either spikegen at pre-compartment OR to a file! if 'file' not in pre_path: ## element() can return either Compartment() or IzhikevichNrn(), ## since it queries and wraps the actual object precomp = moose.element(pre_path) ## if spikegen for this synapse doesn't exist in this compartment, create it ## spikegens for different synapse_types can have different thresholds ## but an integrate and fire spikegen supercedes all other spikegens if 'IF' in precomp.className: # intfire LIF spikegen = precomp # LIF has a spikeOut message else: if not moose.exists(pre_path + '/' + syn_name + '_spikegen'): ## create new spikegen spikegen = moose.SpikeGen(pre_path + '/' + syn_name + '_spikegen') ## connect the compartment Vm to the spikegen moose.connect(precomp, "VmOut", spikegen, "Vm") ## spikegens for different synapse_types can have different thresholds spikegen.threshold = threshold spikegen.edgeTriggered = 1 # This ensures that spike is generated only on leading edge. ## 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 existing or newly created spikegen in this compartment spikegen = moose.SpikeGen(pre_path + '/' + syn_name + '_spikegen') ## connect the spikegen to the SynHandler ## note that you need to use Synapse (auto-created) under SynHandler ## to get/set weights , addSpike-s etc. ## wrap Synapse element by moose.Synapse(synhandler.path+'/synapse') or synhandler.synapse ## Synpase is an array element, first add to it, to addSpike-s, get/set weights, etc. synhandler.numSynapses += 1 ## see Demos/snippets/synapse.py for an example of ## how to connect multiple SpikeGens to the same SynChan m = moose.connect(spikegen, 'spikeOut', synhandler.synapse[-1], 'addSpike', 'Single') 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 ## pre_path is 'file[+<glomnum>]_<filenum1>[_<filenum2>...]' i.e. glomnum could be present ## hack for my (Aditya's) OB model to use files in NeuroML, should not affect others filesplit = pre_path.split('+') if len(filesplit) == 2: glomsplit = filesplit[1].split('_', 1) glomstr = '_' + glomsplit[0] filenums = glomsplit[1] else: glomstr = '' filenums = pre_path.split('_', 1)[1] tt_path = postcomp.path + '/' + syn_name_full + 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_filenums = moose.Mstring(tt_path + '/fileNumbers') tt_filenums.value = 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. ## wrap Synapse element by moose.Synapse(synhandler.path+'/synapse') or synhandler.synapse ## Synpase is an array element, first add to it, to addSpike-s, get/set weights, etc. synhandler.numSynapses += 1 m = moose.connect(tt, "eventOut", synhandler.synapse[-1], "addSpike", "Single") else: ## if it exists, append file number to the field 'fileNumbers' ## append filenumbers from 'file[+<glomnum>]_<filenumber1>[_<filenumber2>...]' tt_filenums = moose.Mstring(tt_path + '/fileNumbers') tt_filenums.value += '_' + 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 SynHandler ## to get/set weights , addSpike-s etc. ## wrap Synpase element by moose.Synapse(synhandler.path+'/synapse') or synhandler.synapse synhandler.synapse[-1].weight = weight synhandler.synapse[-1].delay = delay # seconds
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 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 addinput(cells, netparams, postype, NumSyn): #connect post-synaptic synapses to time tables #used for single neuron models, since populations are connected in connect_neurons log.debug('CONNECT set: {} {} {}', postype, cells[postype],netparams.connect_dict[postype]) post_connections=netparams.connect_dict[postype] for postcell in cells[postype]: postsoma=postcell+'/soma' allsyncomp_list=moose.wildcardFind(postcell+'/##[ISA=SynChan]') for syntype in post_connections.keys(): syncomps,totalsyn=create_synpath_array(allsyncomp_list,syntype,NumSyn) log.info('SYN TABLE for {} {} has {} compartments and {} synapses', postsoma, syntype, len(syncomps),totalsyn) for pretype in post_connections[syntype].keys(): if pretype=='timetable' or pretype=='extern': #all synpases in synlist must in same compartment (e.g. both on spines or both on dendrites) log.info('cells {} {} syn/Comp {}', len(cells), cells, SynPerComp) #create table of synapse compartments for each neuron comps=[] Duptt=ttab['Dup'] Uniqtt=ttab['Uniq'] delay=0 #no need for delay for time table inputs for kk in range(len(synchans[synlist[0]])): p = synchans[synlist[0]][kk].path.split('/') compname = '/' + p[model.compNameNum] log.debug('{} {}', kk, SynPerComp[kk]) if param_sim.spineYesNo: comps.append(compname + '/' + p[model.SpineParams.spineNameNum]) else: for qq in range(SynPerComp[kk]): comps.append(compname) log.debug('comps: {}', comps) allcomps=np.tile(comps,(len(cells),1)) remainingcomps=[len(comps) for ii in range(len(cells))] log.info('Remaing comps to connect {} {}', remainingcomps, np.shape(allcomps)) # #loop through duplicates and connect them to a compartment in each neuron for train in range(len(Duptt)): tt=moose.TimeTable(Duptt[train]) for cell in range(len(cells)): postneur=cells[cell] branch=np.random.random_integers(0,remainingcomps[cell]-1) synpath=postneur+allcomps[cell][branch] remainingcomps[cell]=remainingcomps[cell]-1 allcomps[cell][branch]=allcomps[cell][remainingcomps[cell]] allcomps[cell][remainingcomps[cell]]='' log.debug('CONNECT: {} {} {} {} {}', branch, tt.path, cells[cell].path, remainingcomps, synpath) log.debug(allcomps) for chan in synlist: synconn(synpath+'/'+chan,dist,tt,param_sim.calcium,delay) #loop through unique trains and connect them to one comp in one neuron TotalTrains=0 for train in range(startt,len(Uniqtt)): if sum(remainingcomps)>0: TotalTrains+=1 tt=moose.TimeTable(Uniqtt[train]) br=np.random.random_integers(0,sum(remainingcomps)-1) cumcomps=np.array([int(sum(remainingcomps[0:x])) for x in np.arange(1,len(remainingcomps)+1)]) cell=int(np.min(np.where(cumcomps>br))) postneur=cells[cell] if cell > 0: branch=br-cumcomps[cell-1] else: branch=br log.debug('{}'*7, br, sum(remainingcomps), cumcomps, np.where(cumcomps>br), cell, branch,allcomps[cell][branch]) synpath=postneur+allcomps[cell][branch] remainingcomps[cell]=remainingcomps[cell]-1 allcomps[cell][branch]=allcomps[cell][remainingcomps[cell]] allcomps[cell][remainingcomps[cell]]='' log.debug('CONNECT: {} {} {} {} {} {}', br, branch, cumcomps, remainingcomps, tt.path, synpath) for chan in synlist: synconn(synpath+'/'+chan,0,tt,param_sim.calcium,delay) else: #print "out of synpases" break #don't do anything. I don't think this break is exiting the loop return len(Uniqtt)
def connect(self, syn_name, pre_path, post_path, weight, threshold, delay): 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('/library/' + syn_name) if libsyn.className == 'KinSynChan' or libsyn.getField( 'graded') == 'True': # create a new synapse syn_name_full = syn_name + '_' + underscorize(pre_path) self.make_new_synapse(syn_name, postcomp, syn_name_full) else: syn_name_full = syn_name ## if syn doesn't exist in this compartment, create it if not self.context.exists(post_path + '/' + syn_name_full): self.make_new_synapse(syn_name, postcomp, syn_name_full) syn = moose.SynChan( post_path + '/' + syn_name_full) # wrap the synapse in this compartment #### 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 if syn.getField('graded') == 'True': # graded synapse table = moose.Table(syn.path + "/graded_table") #### always connect source to input - else 'cannot create message' error. precomp = moose.Compartment(pre_path) precomp.connect("VmSrc", 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 else: # Event based synapse ## synapse could be connected to spikegen at pre-compartment OR a file! if 'file' not in pre_path: precomp = moose.Compartment(pre_path) ## if spikegen for this synapse doesn't exist in this compartment, create it ## spikegens for different synapse_types can have different thresholds if not self.context.exists(pre_path + '/' + syn_name + '_spikegen'): spikegen = moose.SpikeGen(pre_path + '/' + syn_name + '_spikegen') # connect the compartment Vm to the spikegen precomp.connect("VmSrc", spikegen, "Vm") # spikegens for different synapse_types can have different thresholds spikegen.threshold = threshold spikegen.edgeTriggered = 1 # This ensures that spike is generated only on leading edge. #spikegen.refractT = 0.25e-3 ## usually events are raised at every time step that Vm > Threshold, can set either edgeTriggered as above or refractT spikegen = moose.SpikeGen( pre_path + '/' + syn_name + '_spikegen') # wrap the spikegen in this compartment # connect the spikegen to the synapse spikegen.connect("event", syn, "synapse") 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 ## pre_path is 'file[+<glomnum>]_<filenum1>[_<filenum2>...]' i.e. glomnum could be present filesplit = pre_path.split('+') if len(filesplit) == 2: glomsplit = filesplit[1].split('_', 1) glomstr = '_' + glomsplit[0] filenums = glomsplit[1] else: glomstr = '' filenums = pre_path.split('_', 1)[1] tt_path = postcomp.path + '/' + syn_name_full + glomstr + '_tt' if not self.context.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: tt.connect("event", 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 = 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: syn.setWeight(syn.numSynapses - 1, weight) syn.setDelay(syn.numSynapses - 1, delay) # seconds
soma.Cm = 0.01 * 3.14159 * soma.length * soma.diameter synid = context.deepCopy(context.pathToId('/library/' + syn_name), soma.id, syn_name) syn = moose.SynChan(synid) #### connect the soma to the synapse if syn.getField( 'mgblock' ) == 'True': # If NMDA synapse based on mgblock, connect to mgblock mgblock = moose.Mg_block(syn.path + '/mgblock') compartment_connection = mgblock else: # if SynChan or even NMDAChan, connect normally compartment_connection = syn soma.connect("channel", compartment_connection, "channel") tt = moose.TimeTable('/soma/tt') tt.connect("event", syn, "synapse") syn.setWeight(syn.numSynapses - 1, 1.0) syn.setDelay(syn.numSynapses - 1, 0) fn = 'temp_spikefile.txt' f = open(fn, 'w') f.write(str(SETTLETIME)) f.close() tt.filename = fn os.remove(fn) somaVm = setupTable('/soma/somaVm', soma, 'Vm') chanIk = setupTable('/soma/chanIk', compartment_connection, 'Ik') chanGk = setupTable('/soma/chanGk', compartment_connection, 'Gk') resetSim(context, SIMDT, PLOTDT)