Exemple #1
0
def make_new_synapse(syn_name, postcomp, syn_name_full, nml_params):
    ## if channel does not exist in library load it from xml file
    if not moose.exists("/library/" + syn_name):
        cmlR = ChannelML(nml_params)
        model_filename = syn_name + ".xml"
        model_path = utils.find_first_file(model_filename, nml_params["model_dir"])
        if model_path is not None:
            cmlR.readChannelMLFromFile(model_path)
        else:
            raise IOError(
                "For mechanism {0}: files {1} not found under {2}.".format(
                    mechanismname, model_filename, self.model_dir
                )
            )
    ## deep copies the library SynChan and SynHandler
    ## to instances under postcomp named as <arg3>
    synid = moose.copy(moose.element("/library/" + syn_name), postcomp, syn_name_full)
    # synhandlerid = moose.copy(moose.element('/library/'+syn_name+'/handler'), postcomp,syn_name_full+'/handler') This line was a bug: double handler
    synhandler = moose.element(synid.path + "/handler")
    syn = moose.SynChan(synid)
    synhandler = moose.element(synid.path + "/handler")  # returns SimpleSynHandler or STDPSynHandler

    ## connect the SimpleSynHandler or the STDPSynHandler to the SynChan (double exp)
    moose.connect(synhandler, "activationOut", syn, "activation")
    # mgblock connections if required
    childmgblock = moose_utils.get_child_Mstring(syn, "mgblockStr")
    #### connect the post compartment to the synapse
    if childmgblock.value == "True":  # If NMDA synapse based on mgblock, connect to mgblock
        mgblock = moose.Mg_block(syn.path + "/mgblock")
        moose.connect(postcomp, "channel", mgblock, "channel")
    else:  # if SynChan or even NMDAChan, connect normally
        moose.connect(postcomp, "channel", syn, "channel")
def make_new_synapse(syn_name, postcomp, syn_name_full, nml_params):
    ## if channel does not exist in library load it from xml file
    if not moose.exists('/library/' + syn_name):
        cmlR = ChannelML(nml_params)
        model_filename = syn_name + '.xml'
        model_path = utils.find_first_file(model_filename,
                                           nml_params['model_dir'])
        if model_path is not None:
            cmlR.readChannelMLFromFile(model_path)
        else:
            raise IOError(
                'For mechanism {0}: files {1} not found under {2}.'.format(
                    syn_name, model_filename, nml_params['model_dir']))
    ## deep copies the library SynChan and SynHandler
    ## to instances under postcomp named as <arg3>
    synid = moose.copy(moose.element('/library/' + syn_name), postcomp,
                       syn_name_full)
    #synhandlerid = moose.copy(moose.element('/library/'+syn_name+'/handler'), postcomp,syn_name_full+'/handler') This line was a bug: double handler
    synhandler = moose.element(synid.path + '/handler')
    syn = moose.SynChan(synid)
    synhandler = moose.element(
        synid.path + '/handler')  # returns SimpleSynHandler or STDPSynHandler

    ## connect the SimpleSynHandler or the STDPSynHandler to the SynChan (double exp)
    moose.connect(synhandler, 'activationOut', syn, 'activation')
    # mgblock connections if required
    childmgblock = mu.get_child_Mstring(syn, 'mgblockStr')
    #### connect the post compartment to the synapse
    if childmgblock.value == 'True':  # If NMDA synapse based on mgblock, connect to mgblock
        mgblock = moose.Mg_block(syn.path + '/mgblock')
        moose.connect(postcomp, "channel", mgblock, "channel")
    else:  # if SynChan or even NMDAChan, connect normally
        moose.connect(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")
Exemple #4
0
 def make_new_synapse(self, syn_name, postcomp, syn_name_full):
     ## if channel does not exist in library load it from xml file
     if not moose.exists('/library/'+syn_name):
         cmlR = ChannelML(self.nml_params)
         cmlR.readChannelMLFromFile(syn_name+'.xml')
     ## deep copies the library synapse to an instance under postcomp named as <arg3>
     synid = moose.copy(moose.Neutral('/library/'+syn_name),postcomp,syn_name_full)
     syn = moose.SynChan(synid)
     childmgblock = utils.get_child_Mstring(syn,'mgblock')
     #### connect the post compartment to the synapse
     if childmgblock.value=='True': # If NMDA synapse based on mgblock, connect to mgblock
         mgblock = moose.Mg_block(syn.path+'/mgblock')
         moose.connect(postcomp,"channel", mgblock, "channel")
     else: # if SynChan or even NMDAChan, connect normally
         moose.connect(postcomp,"channel", syn, "channel")
Exemple #5
0
    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")
Exemple #6
0
 def set_compartment_param(self, compartment, name, value, mechanismname):
     """ Set the param for the compartment depending on name and mechanismname. """
     if name == 'CM':
         compartment.Cm = value*math.pi*compartment.diameter*compartment.length
     elif name == 'RM':
         compartment.Rm = value/(math.pi*compartment.diameter*compartment.length)
     elif name == 'RA':
         compartment.Ra = value*compartment.length/(math.pi*(compartment.diameter/2.0)**2)
     elif name == 'Em':
         compartment.Em = value
     elif name == 'initVm':
         compartment.initVm = value
     elif name == 'inject':
         # this reader converts to SI
         _logger.info("Comparment %s inject %s A." % (compartment.name, value))
         compartment.inject = value
     elif name == 'v_reset':
         compartment.vReset = value # compartment is a moose.LIF instance (intfire)
     elif name == 'threshold':
         compartment.thresh = value # compartment is a moose.LIF instance (intfire)
     elif name == 't_refrac':
         compartment.refractoryPeriod = value # compartment is a moose.LIF instance (intfire)
     elif name == 'g_refrac':
         _logger.info("SORRY, current moose.LIF doesn't support g_refrac.")
     elif mechanismname is 'synapse': # synapse being added to the compartment
         ## these are potential locations, we do not actually make synapses,
         ## unless the user has explicitly asked for it
         if self.createPotentialSynapses:
             syn_name = value
             if not moose.exists(compartment.path+'/'+syn_name):
                 make_new_synapse(syn_name, compartment, syn_name, self.nml_params)
         ## I assume below that compartment name has _segid at its end
         segid = compartment.name.split('_')[-1] # get segment id from compartment name
         self.segDict[segid][5].append(value)
     elif mechanismname is 'spikegen': # spikegen being added to the compartment
         ## these are potential locations, we do not actually make the spikegens.
         ## spikegens for different synapses can have different thresholds,
         ## hence include synapse_type in its name
         ## value contains name of synapse i.e. synapse_type
         #spikegen = moose.SpikeGen(compartment.path+'/'+value+'_spikegen')
         #moose.connect(compartment,"VmSrc",spikegen,"Vm")
         pass
     ## previous were mechanism that don't need a ChannelML definition
     ## including integrate_and_fire (I ignore the ChannelML definition)
     ## thus integrate_and_fire mechanism default values cannot be used
     ## i.e. nothing needed in /library, but below mechanisms need.
     elif mechanismname is not None:
         ## if mechanism is not present in compartment, deep copy from library
         ## all mechanisms have been loaded into the library earlier
         if not moose.exists(compartment.path+'/'+mechanismname):
             neutralObj = moose.element("/library/"+mechanismname) # gives error if not present
             if 'CaConc' == neutralObj.className: # Ion concentration pool
                 libcaconc = moose.CaConc("/library/"+mechanismname)
                 ## deep copies the library caconc under the compartment
                 caconc = moose.copy(libcaconc,compartment,mechanismname)
                 caconc = moose.CaConc(caconc)
                 ## CaConc connections are made later using connect_CaConc()
                 ## Later, when calling connect_CaConc,
                 ## B is set for caconc based on thickness of Ca shell and compartment l and dia
                 ## OR based on the Mstring phi under CaConc path.
                 channel = None
             elif 'HHChannel2D' == neutralObj.className : ## HHChannel2D
                 libchannel = moose.HHChannel2D("/library/"+mechanismname)
                 ## deep copies the library channel under the compartment
                 channel = moose.copy(libchannel,compartment,mechanismname)
                 channel = moose.HHChannel2D(channel)
                 moose.connect(channel,'channel',compartment,'channel')
             elif 'HHChannel' == neutralObj.className : ## HHChannel
                 libchannel = moose.HHChannel("/library/"+mechanismname)
                 ## deep copies the library channel under the compartment
                 channel = moose.copy(libchannel,compartment,mechanismname)
                 channel = moose.HHChannel(channel)
                 moose.connect(channel,'channel',compartment,'channel')
         ## if mechanism is present in compartment, just wrap it
         else:
             neutralObj = moose.element(compartment.path+'/'+mechanismname)
             if 'CaConc' == neutralObj.className: # Ion concentration pool
                 caconc = moose.CaConc(compartment.path+'/'+mechanismname) # wraps existing channel
                 channel = None
             elif 'HHChannel2D' == neutralObj.className : ## HHChannel2D
                 channel = moose.HHChannel2D(compartment.path+'/'+mechanismname) # wraps existing channel
             elif 'HHChannel' == neutralObj.className : ## HHChannel
                 channel = moose.HHChannel(compartment.path+'/'+mechanismname) # wraps existing channel
         if name == 'Gbar':
             if channel is None: # if CaConc, neuroConstruct uses gbar for thickness or phi
                 ## If child Mstring 'phi' is present, set gbar as phi
                 ## BUT, value has been multiplied by Gfactor as a Gbar,
                 ## SI or physiological not known here,
                 ## ignoring Gbar for CaConc, instead of passing units here
                 child = moose_utils.get_child_Mstring(caconc,'phi')
                 if child is not None:
                     #child.value = value
                     pass
                 else:
                     #caconc.thick = value
                     pass
             else: # if ion channel, usual Gbar
                 channel.Gbar = value*math.pi*compartment.diameter*compartment.length
         elif name == 'Ek':
             channel.Ek = value
         elif name == 'thick': # thick seems to be NEURON's extension to NeuroML level 2.
             caconc.thick = value ## JUST THIS WILL NOT DO - HAVE TO SET B based on this thick!
             ## Later, when calling connect_CaConc,
             ## B is set for caconc based on thickness of Ca shell and compartment l and dia.
             ## OR based on the Mstring phi under CaConc path.
     if neuroml_utils.neuroml_debug:
         _logger.info("Setting %s  for comparment %s to %s" % (name, compartment.path, value))
    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
Exemple #8
0
    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
Exemple #9
0
    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
Exemple #10
0
 def set_compartment_param(self, compartment, name, value, mechanismname):
     """ Set the param for the compartment depending on name and mechanismname. """
     if name == 'CM':
         compartment.Cm = value * math.pi * compartment.diameter * compartment.length
     elif name == 'RM':
         compartment.Rm = value / (math.pi * compartment.diameter *
                                   compartment.length)
     elif name == 'RA':
         compartment.Ra = value * compartment.length / (
             math.pi * (compartment.diameter / 2.0)**2)
     elif name == 'Em':
         compartment.Em = value
     elif name == 'initVm':
         compartment.initVm = value
     elif name == 'inject':
         # this reader converts to SI
         _logger.info("Comparment %s inject %s A." %
                      (compartment.name, value))
         compartment.inject = value
     elif name == 'v_reset':
         compartment.vReset = value  # compartment is a moose.LIF instance (intfire)
     elif name == 'threshold':
         compartment.thresh = value  # compartment is a moose.LIF instance (intfire)
     elif name == 't_refrac':
         compartment.refractoryPeriod = value  # compartment is a moose.LIF instance (intfire)
     elif name == 'g_refrac':
         _logger.info("SORRY, current moose.LIF doesn't support g_refrac.")
     elif mechanismname is 'synapse':  # synapse being added to the compartment
         ## these are potential locations, we do not actually make synapses,
         ## unless the user has explicitly asked for it
         if self.createPotentialSynapses:
             syn_name = value
             if not moose.exists(compartment.path + '/' + syn_name):
                 make_new_synapse(syn_name, compartment, syn_name,
                                  self.nml_params)
         ## I assume below that compartment name has _segid at its end
         segid = compartment.name.split('_')[
             -1]  # get segment id from compartment name
         self.segDict[segid][5].append(value)
     elif mechanismname is 'spikegen':  # spikegen being added to the compartment
         ## these are potential locations, we do not actually make the spikegens.
         ## spikegens for different synapses can have different thresholds,
         ## hence include synapse_type in its name
         ## value contains name of synapse i.e. synapse_type
         #spikegen = moose.SpikeGen(compartment.path+'/'+value+'_spikegen')
         #moose.connect(compartment,"VmSrc",spikegen,"Vm")
         pass
     ## previous were mechanism that don't need a ChannelML definition
     ## including integrate_and_fire (I ignore the ChannelML definition)
     ## thus integrate_and_fire mechanism default values cannot be used
     ## i.e. nothing needed in /library, but below mechanisms need.
     elif mechanismname is not None:
         ## if mechanism is not present in compartment, deep copy from library
         ## all mechanisms have been loaded into the library earlier
         if not moose.exists(compartment.path + '/' + mechanismname):
             neutralObj = moose.element(
                 "/library/" + mechanismname)  # gives error if not present
             if 'CaConc' == neutralObj.className:  # Ion concentration pool
                 libcaconc = moose.CaConc("/library/" + mechanismname)
                 ## deep copies the library caconc under the compartment
                 caconc = moose.copy(libcaconc, compartment, mechanismname)
                 caconc = moose.CaConc(caconc)
                 ## CaConc connections are made later using connect_CaConc()
                 ## Later, when calling connect_CaConc,
                 ## B is set for caconc based on thickness of Ca shell and compartment l and dia
                 ## OR based on the Mstring phi under CaConc path.
                 channel = None
             elif 'HHChannel2D' == neutralObj.className:  ## HHChannel2D
                 libchannel = moose.HHChannel2D("/library/" + mechanismname)
                 ## deep copies the library channel under the compartment
                 channel = moose.copy(libchannel, compartment,
                                      mechanismname)
                 channel = moose.HHChannel2D(channel)
                 moose.connect(channel, 'channel', compartment, 'channel')
             elif 'HHChannel' == neutralObj.className:  ## HHChannel
                 libchannel = moose.HHChannel("/library/" + mechanismname)
                 ## deep copies the library channel under the compartment
                 channel = moose.copy(libchannel, compartment,
                                      mechanismname)
                 channel = moose.HHChannel(channel)
                 moose.connect(channel, 'channel', compartment, 'channel')
         ## if mechanism is present in compartment, just wrap it
         else:
             neutralObj = moose.Neutral(compartment.path + '/' +
                                        mechanismname)
             if 'CaConc' == neutralObj.className:  # Ion concentration pool
                 caconc = moose.CaConc(
                     compartment.path + '/' +
                     mechanismname)  # wraps existing channel
                 channel = None
             elif 'HHChannel2D' == neutralObj.className:  ## HHChannel2D
                 channel = moose.HHChannel2D(
                     compartment.path + '/' +
                     mechanismname)  # wraps existing channel
             elif 'HHChannel' == neutralObj.className:  ## HHChannel
                 channel = moose.HHChannel(
                     compartment.path + '/' +
                     mechanismname)  # wraps existing channel
         if name == 'Gbar':
             if channel is None:  # if CaConc, neuroConstruct uses gbar for thickness or phi
                 ## If child Mstring 'phi' is present, set gbar as phi
                 ## BUT, value has been multiplied by Gfactor as a Gbar,
                 ## SI or physiological not known here,
                 ## ignoring Gbar for CaConc, instead of passing units here
                 child = moose_utils.get_child_Mstring(caconc, 'phi')
                 if child is not None:
                     #child.value = value
                     pass
                 else:
                     #caconc.thick = value
                     pass
             else:  # if ion channel, usual Gbar
                 channel.Gbar = value * math.pi * compartment.diameter * compartment.length
         elif name == 'Ek':
             channel.Ek = value
         elif name == 'thick':  # thick seems to be NEURON's extension to NeuroML level 2.
             caconc.thick = value  ## JUST THIS WILL NOT DO - HAVE TO SET B based on this thick!
             ## Later, when calling connect_CaConc,
             ## B is set for caconc based on thickness of Ca shell and compartment l and dia.
             ## OR based on the Mstring phi under CaConc path.
     if neuroml_utils.neuroml_debug:
         _logger.info("Setting %s  for comparment %s to %s" %
                      (name, compartment.path, value))
    def set_compartment_param(self, compartment, name, value, mechName):
        """ Set the param for the compartment depending on name and mechName. """
        if name == 'CM':
            compartment.Cm = value *math.pi*compartment.diameter*compartment.length
        elif name == 'RM':
            compartment.Rm = value/(math.pi*compartment.diameter*compartment.length)
        elif name == 'RA':
            compartment.Ra = value * compartment.length / \
                    (math.pi*(compartment.diameter/2.0)**2)
        elif name == 'Em':
            compartment.Em = value
        elif name == 'initVm':
            compartment.initVm = value
        elif name == 'inject':
            msg = " {0} inject {1} A.".format(compartment.name, value)
            debug.printDebug("INFO", msg)
            compartment.inject = value
        elif mechName is 'synapse':

           # synapse being added to the compartment
           # these are potential locations, we do not actually make synapses.
           # I assume below that compartment name has _segid at its end

           # get segment id from compartment name
           segid = moose_methods.getCompartmentId(compartment.name)
           self.segDict[segid][5].append(value)

        # spikegen being added to the compartment
        elif mechName is 'spikegen': 
            # these are potential locations, we do not actually make the
            # spikegens.  spikegens for different synapses can have different
            # thresholds, hence include synapse_type in its name value contains
            # name of synapse i.e. synapse_type
            #spikegen = moose.SpikeGen(compartment.path+'/'+value+'_spikegen')
            #moose.connect(compartment,"VmSrc",spikegen,"Vm")
            pass
        elif mechName is not None:

            # if mechanism is not present in compartment, deep copy from library
            if not moose.exists(compartment.path+'/'+mechName):

                # if channel does not exist in library load it from xml file
                if not moose.exists(self.libraryPath+"/"+mechName):
                    cmlR = ChannelML(self.nml_params)
                    model_filename = mechName+'.xml'
                    model_path = neuroml_utils.find_first_file(
                        model_filename
                        , self.model_dir
                    )
                    if model_path is not None:
                        cmlR.readChannelMLFromFile(model_path)
                    else:
                        msg = 'Mechanism {0}: files {1} not found under {2}'\
                                .format( mechName
                                        , model_filename
                                        , self.model_dir
                                        )
                        debug.printDebug("ERROR"
                                , msg
                                , frame = inspect.currentframe()
                                )
                        sys.exit(0)

                neutralObj = moose.Neutral(self.libraryPath+"/"+mechName)

                # Ion concentration pool
                if 'CaConc' == neutralObj.className:
                    libcaconc = moose.CaConc(self.libraryPath+"/"+mechName)

                    # deep copies the library caconc under the compartment
                    caconc = moose.copy(libcaconc,compartment,mechName)
                    caconc = moose.CaConc(caconc)

                    # CaConc connections are made later using connect_CaConc()
                    # Later, when calling connect_CaConc, B is set for caconc
                    # based on thickness of Ca shell and compartment l and dia
                    # OR based on the Mstring phi under CaConc path.
                    channel = None

                elif 'HHChannel2D' == neutralObj.className : ## HHChannel2D
                    libchannel = moose.HHChannel2D(self.libraryPath+"/"+mechName)
                    ## deep copies the library channel under the compartment
                    channel = moose.copy(libchannel,compartment,mechName)
                    channel = moose.HHChannel2D(channel)
                    moose.connect(channel,'channel',compartment,'channel')
                elif 'HHChannel' == neutralObj.className : ## HHChannel
                    libchannel = moose.HHChannel(self.libraryPath+"/"+mechName)

                    # deep copies the library channel under the compartment
                    channel = moose.copy(libchannel,compartment,mechName)
                    channel = moose.HHChannel(channel)
                    moose.connect(channel,'channel',compartment,'channel')
            # if mechanism is present in compartment, just wrap it
            else:
                neutralObj = moose.Neutral(compartment.path+'/'+mechName)
                # Ion concentration pool
                if 'CaConc' == neutralObj.className:
                    # wraps existing channel
                    caconc = moose.CaConc(compartment.path+'/'+mechName)
                    channel = None
                elif 'HHChannel2D' == neutralObj.className: ## HHChannel2D
                    # wraps existing channel
                    channel = moose.HHChannel2D(compartment.path+'/'+mechName)
                elif 'HHChannel' == neutralObj.className : ## HHChannel
                    # wraps existing channel
                    channel = moose.HHChannel(compartment.path+'/'+mechName)
            if name == 'Gbar':
                # if CaConc, neuroConstruct uses gbar for thickness or phi
                if channel is None:
                    # If child Mstring 'phi' is present, set gbar as phi BUT,
                    # value has been multiplied by Gfactor as a Gbar, SI or
                    # physiological not known here, ignoring Gbar for CaConc,
                    # instead of passing units here
                    child = moose_utils.get_child_Mstring(caconc,'phi')
                    if child is not None:
                        #child.value = value
                        pass
                    else:
                        #caconc.thick = value
                        pass
                else: # if ion channel, usual Gbar
                    channel.Gbar = value * math.pi * compartment.diameter \
                            * compartment.length
            elif name == 'Ek':
                channel.Ek = value

            # thick seems to be NEURON's extension to NeuroML level 2.
            elif name == 'thick':
                # JUST THIS WILL NOT DO - HAVE TO SET B based on this thick!
                caconc.thick = value
                # Later, when calling connect_CaConc, B is set for caconc based
                # on thickness of Ca shell and compartment l and dia.  OR based
                # on the Mstring phi under CaConc path.

        if neuroml_utils.neuroml_debug:
            msg = "Setting {0} for {1} value {2}".format(name, compartment.path
                                                         , value
                                                         )
            debug.printDebug("DEBUG", msg, frame=inspect.currentframe())
Exemple #12
0
    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
Exemple #13
0
    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)
        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)
            self.make_new_synapse(syn_name, postcomp, syn_name_full)
        else:
            ##### BUG BUG BUG in MOOSE:
            ##### Subhasis said addSpike below always adds to the first element in syn.synapse
            ##### So here, create a new SynChan everytime.
            syn_name_full = syn_name+'_'+utils.underscorize(pre_path)
            self.make_new_synapse(syn_name, postcomp, syn_name_full)
            ##### Once above bug is resolved in MOOSE, revert to below:
            ### if syn doesn't exist in this compartment, create it
            #syn_name_full = syn_name
            #if not moose.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
        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
        if gradedchild.value=='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)
            moose.connect(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
        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 moose.exists(pre_path+'/'+syn_name+'_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.
                    #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
                ## 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.synapse.num += 1
                ##### BUG BUG BUG in MOOSE:
                ##### Subhasis said addSpike always adds to the first element in syn.synapse
                ##### Create a new synapse above everytime
                moose.connect(spikegen,"event",syn.synapse[-1],"addSpike")
            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 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.synapse.num += 1
                    ##### BUG BUG BUG in MOOSE:
                    ##### Subhasis said addSpike always adds to the first element in syn.synapse
                    ##### Create a new synapse above everytime
                    m = moose.connect(tt,"event",syn.synapse[-1],"addSpike")
                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:
                ## 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
Exemple #14
0
    def set_compartment_param(self, compartment, name, value, mechName):
        """ Set the param for the compartment depending on name and mechName. """
        if name == 'CM':
            compartment.Cm = value * math.pi * compartment.diameter * compartment.length
        elif name == 'RM':
            compartment.Rm = value / (math.pi * compartment.diameter *
                                      compartment.length)
        elif name == 'RA':
            compartment.Ra = value * compartment.length / \
                    (math.pi*(compartment.diameter/2.0)**2)
        elif name == 'Em':
            compartment.Em = value
        elif name == 'initVm':
            compartment.initVm = value
        elif name == 'inject':
            msg = " {0} inject {1} A.".format(compartment.name, value)
            debug.printDebug("INFO", msg)
            compartment.inject = value
        elif mechName is 'synapse':

            # synapse being added to the compartment
            # these are potential locations, we do not actually make synapses.
            # I assume below that compartment name has _segid at its end

            # get segment id from compartment name
            segid = moose_methods.getCompartmentId(compartment.name)
            self.segDict[segid][5].append(value)

        # spikegen being added to the compartment
        elif mechName is 'spikegen':
            # these are potential locations, we do not actually make the
            # spikegens.  spikegens for different synapses can have different
            # thresholds, hence include synapse_type in its name value contains
            # name of synapse i.e. synapse_type
            #spikegen = moose.SpikeGen(compartment.path+'/'+value+'_spikegen')
            #moose.connect(compartment,"VmSrc",spikegen,"Vm")
            pass
        elif mechName is not None:

            # if mechanism is not present in compartment, deep copy from library
            if not moose.exists(compartment.path + '/' + mechName):

                # if channel does not exist in library load it from xml file
                if not moose.exists(self.libraryPath + "/" + mechName):
                    cmlR = ChannelML(self.nml_params)
                    model_filename = mechName + '.xml'
                    model_path = neuroml_utils.find_first_file(
                        model_filename, self.model_dir)
                    if model_path is not None:
                        cmlR.readChannelMLFromFile(model_path)
                    else:
                        msg = 'Mechanism {0}: files {1} not found under {2}'\
                                .format( mechName
                                        , model_filename
                                        , self.model_dir
                                        )
                        debug.printDebug("ERROR",
                                         msg,
                                         frame=inspect.currentframe())
                        sys.exit(0)

                neutralObj = moose.Neutral(self.libraryPath + "/" + mechName)

                # Ion concentration pool
                if 'CaConc' == neutralObj.className:
                    libcaconc = moose.CaConc(self.libraryPath + "/" + mechName)

                    # deep copies the library caconc under the compartment
                    caconc = moose.copy(libcaconc, compartment, mechName)
                    caconc = moose.CaConc(caconc)

                    # CaConc connections are made later using connect_CaConc()
                    # Later, when calling connect_CaConc, B is set for caconc
                    # based on thickness of Ca shell and compartment l and dia
                    # OR based on the Mstring phi under CaConc path.
                    channel = None

                elif 'HHChannel2D' == neutralObj.className:  ## HHChannel2D
                    libchannel = moose.HHChannel2D(self.libraryPath + "/" +
                                                   mechName)
                    ## deep copies the library channel under the compartment
                    channel = moose.copy(libchannel, compartment, mechName)
                    channel = moose.HHChannel2D(channel)
                    moose.connect(channel, 'channel', compartment, 'channel')
                elif 'HHChannel' == neutralObj.className:  ## HHChannel
                    libchannel = moose.HHChannel(self.libraryPath + "/" +
                                                 mechName)

                    # deep copies the library channel under the compartment
                    channel = moose.copy(libchannel, compartment, mechName)
                    channel = moose.HHChannel(channel)
                    moose.connect(channel, 'channel', compartment, 'channel')
            # if mechanism is present in compartment, just wrap it
            else:
                neutralObj = moose.Neutral(compartment.path + '/' + mechName)
                # Ion concentration pool
                if 'CaConc' == neutralObj.className:
                    # wraps existing channel
                    caconc = moose.CaConc(compartment.path + '/' + mechName)
                    channel = None
                elif 'HHChannel2D' == neutralObj.className:  ## HHChannel2D
                    # wraps existing channel
                    channel = moose.HHChannel2D(compartment.path + '/' +
                                                mechName)
                elif 'HHChannel' == neutralObj.className:  ## HHChannel
                    # wraps existing channel
                    channel = moose.HHChannel(compartment.path + '/' +
                                              mechName)
            if name == 'Gbar':
                # if CaConc, neuroConstruct uses gbar for thickness or phi
                if channel is None:
                    # If child Mstring 'phi' is present, set gbar as phi BUT,
                    # value has been multiplied by Gfactor as a Gbar, SI or
                    # physiological not known here, ignoring Gbar for CaConc,
                    # instead of passing units here
                    child = moose_utils.get_child_Mstring(caconc, 'phi')
                    if child is not None:
                        #child.value = value
                        pass
                    else:
                        #caconc.thick = value
                        pass
                else:  # if ion channel, usual Gbar
                    channel.Gbar = value * math.pi * compartment.diameter \
                            * compartment.length
            elif name == 'Ek':
                channel.Ek = value

            # thick seems to be NEURON's extension to NeuroML level 2.
            elif name == 'thick':
                # JUST THIS WILL NOT DO - HAVE TO SET B based on this thick!
                caconc.thick = value
                # Later, when calling connect_CaConc, B is set for caconc based
                # on thickness of Ca shell and compartment l and dia.  OR based
                # on the Mstring phi under CaConc path.

        if neuroml_utils.neuroml_debug:
            msg = "Setting {0} for {1} value {2}".format(
                name, compartment.path, value)
            debug.printDebug("DEBUG", msg, frame=inspect.currentframe())