示例#1
0
 def make_cml_function(self, element, fn_name, concdep=None):
     fn_type = element.attrib['expr_form']
     if fn_type in ['exponential', 'sigmoid', 'exp_linear']:
         self.make_function( fn_name, fn_type, rate=float(element.attrib['rate']),\
             midpoint=float(element.attrib['midpoint']), scale=float(element.attrib['scale'] ) )
     elif fn_type == 'generic':
         ## OOPS! These expressions should be in SI units, since I converted to SI
         ## Ideally I should not convert to SI and have the user consistently use one or the other
         ## Or convert constants in these expressions to SI, only voltage and ca_conc appear!
         ## NO! SEE ABOVE, for calculating values for tables, I use units specified in xml file,
         ## then I convert to SI while writing to MOOSE internal tables.
         expr_string = element.attrib['expr']
         if concdep is None: ca_name = ''  # no Ca dependence
         else:
             ca_name = ',' + concdep.attrib[
                 'variable_name']  # Ca dependence
         expr_string = expr_string.replace('alpha',
                                           'self.alpha(v' + ca_name + ')')
         expr_string = expr_string.replace('beta',
                                           'self.beta(v' + ca_name + ')')
         self.make_function(fn_name,
                            fn_type,
                            expr_string=expr_string,
                            concdep=concdep)
     else:
         pu.fatal("Unsupported function type %s " % fn_type)
         sys.exit()
示例#2
0
 def make_cml_function(self, element, fn_name, concdep=None):
     fn_type = element.attrib["expr_form"]
     if fn_type in ["exponential", "sigmoid", "exp_linear"]:
         fn = self.make_function(
             fn_name,
             fn_type,
             rate=float(element.attrib["rate"]),
             midpoint=float(element.attrib["midpoint"]),
             scale=float(element.attrib["scale"]),
         )
     elif fn_type == "generic":
         ## OOPS! These expressions should be in SI units, since I converted to SI
         ## Ideally I should not convert to SI and have the user consistently use one or the other
         ## Or convert constants in these expressions to SI, only voltage and ca_conc appear!
         ## NO! SEE ABOVE, for calculating values for tables, I use units specified in xml file,
         ## then I convert to SI while writing to MOOSE internal tables.
         expr_string = element.attrib["expr"]
         if concdep is None:
             ca_name = ""  # no Ca dependence
         else:
             ca_name = "," + concdep.attrib["variable_name"]  # Ca dependence
         expr_string = expr_string.replace("alpha", "self.alpha(v" + ca_name + ")")
         expr_string = expr_string.replace("beta", "self.beta(v" + ca_name + ")")
         fn = self.make_function(fn_name, fn_type, expr_string=expr_string, concdep=concdep)
     else:
         pu.fatal("Unsupported function type %s " % fn_type)
         sys.exit()
示例#3
0
    def readMorphMLFromFile(self,filename,params={}):
        """
        specify params for this MorphML file as a dict:
         presently combineSegments and createPotentialSynapses are implemented.
         See readMorphML().
        See also nml_params in __init__().
        returns { cellname1 : (segDict,cableDict), ... }
        see readMorphML(...) for segDict and cableDict
        """

        pu.info("Reading morphology from %s" % filename)
        try:
            tree = ET.parse(filename)
        except Exception as e:
            pu.fatal("Failed to load morphology from file %s" % filename)

        neuroml_element = tree.getroot()
        cellsDict = {}
        for cell in neuroml_element.findall('.//{'+self.neuroml+'}cell'):
            if 'lengthUnits' in list(neuroml_element.attrib.keys()):
                lengthUnits = neuroml_element.attrib['lengthUnits']
            else:
                lengthUnits = 'micrometer'
            cellDict = self.readMorphML(cell,params,lengthUnits)
            cellsDict.update(cellDict)
        return cellsDict
示例#4
0
 def make_cml_function(self, element, fn_name, concdep=None):
     fn_type = element.attrib["expr_form"]
     if fn_type in ["exponential", "sigmoid", "exp_linear"]:
         self.make_function(
             fn_name,
             fn_type,
             rate=float(element.attrib["rate"]),
             midpoint=float(element.attrib["midpoint"]),
             scale=float(element.attrib["scale"]),
         )
     elif fn_type == "generic":
         ## OOPS! These expressions should be in SI units, since I converted to SI
         ## Ideally I should not convert to SI and have the user consistently use one or the other
         ## Or convert constants in these expressions to SI, only voltage and ca_conc appear!
         ## NO! SEE ABOVE, for calculating values for tables, I use units specified in xml file,
         ## then I convert to SI while writing to MOOSE internal tables.
         expr_string = element.attrib["expr"]
         if concdep is None:
             ca_name = ""  # no Ca dependence
         else:
             ca_name = "," + concdep.attrib[
                 "variable_name"]  # Ca dependence
         expr_string = expr_string.replace("alpha",
                                           "self.alpha(v" + ca_name + ")")
         expr_string = expr_string.replace("beta",
                                           "self.beta(v" + ca_name + ")")
         self.make_function(fn_name,
                            fn_type,
                            expr_string=expr_string,
                            concdep=concdep)
     else:
         pu.fatal("Unsupported function type %s " % fn_type)
         sys.exit()
示例#5
0
    def readSynapseML(self, synapseElement, units="SI units"):
        if 'Physiological Units' in units:  # see pg 219 (sec 13.2) of Book of Genesis
            Vfactor = 1e-3  # V from mV
            Tfactor = 1e-3  # s from ms
            Gfactor = 1e-3  # S from mS
        elif 'SI Units' in units:
            Vfactor = 1.0
            Tfactor = 1.0
            Gfactor = 1.0
        else:
            pu.fatal("Wrong units %s exiting ..." % units)
            sys.exit(1)
        if not moose.exists('/library'):
            moose.Neutral('/library')
        synname = synapseElement.attrib['name']
        if utils.neuroml_debug:
            pu.info("Loading synapse : %s into /library" % synname)
        moosesynapse = moose.SynChan('/library/' + synname)
        doub_exp_syn = synapseElement.find('./{' + self.cml + '}doub_exp_syn')
        moosesynapse.Ek = float(
            doub_exp_syn.attrib['reversal_potential']) * Vfactor
        moosesynapse.Gbar = float(
            doub_exp_syn.attrib['max_conductance']) * Gfactor
        moosesynapse.tau1 = float(
            doub_exp_syn.attrib['rise_time']) * Tfactor  # seconds
        moosesynapse.tau2 = float(
            doub_exp_syn.attrib['decay_time']) * Tfactor  # seconds
        ## 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

        ## graded synapses are not supported by neuroml, so set to False here,
        ## see my Demo/neuroml/lobster_pyloric/STG_net.py for how to still have graded synapses
        moosesynapse_graded = moose.Mstring(moosesynapse.path + '/graded')
        moosesynapse_graded.value = 'False'
        moosesynapse_mgblock = moose.Mstring(moosesynapse.path + '/mgblockStr')
        moosesynapse_mgblock.value = 'False'
        ## check if STDP synapse is present or not
        stdp_syn = synapseElement.find('./{' + self.cml + '}stdp_syn')
        if stdp_syn is None:
            moosesynhandler = moose.SimpleSynHandler('/library/' + synname +
                                                     '/handler')
        else:
            moosesynhandler = moose.STDPSynHandler('/library/' + synname +
                                                   '/handler')
            moosesynhandler.aPlus0 = float(stdp_syn.attrib['del_weight_ltp'])
            moosesynhandler.aMinus0 = float(stdp_syn.attrib['del_weight_ltd'])
            moosesynhandler.tauPlus = float(stdp_syn.attrib['tau_ltp'])
            moosesynhandler.tauMinus = float(stdp_syn.attrib['tau_ltd'])
            moosesynhandler.weightMax = float(
                stdp_syn.attrib['max_syn_weight'])
            moosesynhandler.weightMin = 0.0
        ## connect the SimpleSynHandler or the STDPSynHandler to the SynChan (double exp)
        moose.connect(moosesynhandler, 'activationOut', moosesynapse,
                      'activation')
示例#6
0
    def readIonConcML(self, ionConcElement, units="SI units"):
        if units == 'Physiological Units':  # see pg 219 (sec 13.2) of Book of Genesis
            Vfactor = 1e-3  # V from mV
            Tfactor = 1e-3  # s from ms
            Gfactor = 1e1  # S/m^2 from mS/cm^2
            concfactor = 1e6  # mol/m^3 from mol/cm^3
            Lfactor = 1e-2  # m from cm
            Ifactor = 1e-6  # A from microA
        else:
            Vfactor = 1.0
            Tfactor = 1.0
            Gfactor = 1.0
            concfactor = 1.0
            Lfactor = 1.0
            Ifactor = 1.0
        moose.Neutral(
            '/library')  # creates /library in MOOSE tree; elif present, wraps
        ionSpecies = ionConcElement.find('./{' + self.cml + '}ion_species')
        if ionSpecies is not None:
            if not 'ca' in ionSpecies.attrib['name']:
                pu.fatal(
                    "Sorry, I cannot handle non-Ca-ion pools. Exiting ...")
                sys.exit(1)
        capoolName = ionConcElement.attrib['name']

        pu.info("Loading Ca pool %s into /library ." % capoolName)
        caPool = moose.CaConc('/library/' + capoolName)
        poolModel = ionConcElement.find('./{' + self.cml +
                                        '}decaying_pool_model')
        caPool.CaBasal = float(poolModel.attrib['resting_conc']) * concfactor
        caPool.Ca_base = float(poolModel.attrib['resting_conc']) * concfactor
        if 'decay_constant' in poolModel.attrib:
            caPool.tau = float(poolModel.attrib['decay_constant']) * Tfactor
        elif 'inv_decay_constant' in poolModel.attrib:
            caPool.tau = 1.0 / float(
                poolModel.attrib['inv_decay_constant']) * Tfactor
        ## Only one of pool_volume_info or fixed_pool_info should be present, but not checking
        volInfo = poolModel.find('./{' + self.cml + '}pool_volume_info')
        if volInfo is not None:
            caPool.thick = float(volInfo.attrib['shell_thickness']) * Lfactor
        fixedPoolInfo = poolModel.find('./{' + self.cml + '}fixed_pool_info')
        if fixedPoolInfo is not None:
            ## Put in phi under the caPool, so that it can
            ## be used instead of thickness to set B (see section 19.2 in Book of Genesis)
            caPool_phi = moose.Mstring(caPool.path + '/phi')
            caPool_phi.value = str(
                float(fixedPoolInfo.attrib['phi']) * concfactor / Ifactor /
                Tfactor)
示例#7
0
    def readSynapseML(self, synapseElement, units="SI units"):
        if "Physiological Units" in units:  # see pg 219 (sec 13.2) of Book of Genesis
            Vfactor = 1e-3  # V from mV
            Tfactor = 1e-3  # s from ms
            Gfactor = 1e-3  # S from mS
        elif "SI Units" in units:
            Vfactor = 1.0
            Tfactor = 1.0
            Gfactor = 1.0
        else:
            pu.fatal("Wrong units %s exiting ..." % units)
            sys.exit(1)
        moose.Neutral("/library")  # creates /library in MOOSE tree; elif present, wraps
        synname = synapseElement.attrib["name"]
        if utils.neuroml_debug:
            pu.info("Loading synapse : %s into /library" % synname)
        moosesynapse = moose.SynChan("/library/" + synname)
        doub_exp_syn = synapseElement.find("./{" + self.cml + "}doub_exp_syn")
        moosesynapse.Ek = float(doub_exp_syn.attrib["reversal_potential"]) * Vfactor
        moosesynapse.Gbar = float(doub_exp_syn.attrib["max_conductance"]) * Gfactor
        moosesynapse.tau1 = float(doub_exp_syn.attrib["rise_time"]) * Tfactor  # seconds
        moosesynapse.tau2 = float(doub_exp_syn.attrib["decay_time"]) * Tfactor  # seconds
        ## 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

        ## graded synapses are not supported by neuroml, so set to False here,
        ## see my Demo/neuroml/lobster_pyloric/STG_net.py for how to still have graded synapses
        moosesynapse_graded = moose.Mstring(moosesynapse.path + "/graded")
        moosesynapse_graded.value = "False"
        moosesynapse_mgblock = moose.Mstring(moosesynapse.path + "/mgblockStr")
        moosesynapse_mgblock.value = "False"
        ## check if STDP synapse is present or not
        stdp_syn = synapseElement.find("./{" + self.cml + "}stdp_syn")
        if stdp_syn is None:
            moosesynhandler = moose.SimpleSynHandler("/library/" + synname + "/handler")
        else:
            moosesynhandler = moose.STDPSynHandler("/library/" + synname + "/handler")
            moosesynhandler.aPlus0 = float(stdp_syn.attrib["del_weight_ltp"])
            moosesynhandler.aMinus0 = float(stdp_syn.attrib["del_weight_ltd"])
            moosesynhandler.tauPlus = float(stdp_syn.attrib["tau_ltp"])
            moosesynhandler.tauMinus = float(stdp_syn.attrib["tau_ltd"])
            moosesynhandler.weightMax = float(stdp_syn.attrib["max_syn_weight"])
            moosesynhandler.weightMin = 0.0
        ## connect the SimpleSynHandler or the STDPSynHandler to the SynChan (double exp)
        moose.connect(moosesynhandler, "activationOut", moosesynapse, "activation")
示例#8
0
    def readIonConcML(self, ionConcElement, units="SI units"):
        if units == "Physiological Units":  # see pg 219 (sec 13.2) of Book of Genesis
            Vfactor = 1e-3  # V from mV
            Tfactor = 1e-3  # s from ms
            Gfactor = 1e1  # S/m^2 from mS/cm^2
            concfactor = 1e6  # mol/m^3 from mol/cm^3
            Lfactor = 1e-2  # m from cm
            Ifactor = 1e-6  # A from microA
        else:
            Vfactor = 1.0
            Tfactor = 1.0
            Gfactor = 1.0
            concfactor = 1.0
            Lfactor = 1.0
            Ifactor = 1.0
        moose.Neutral("/library")  # creates /library in MOOSE tree; elif present, wraps
        ionSpecies = ionConcElement.find("./{" + self.cml + "}ion_species")
        if ionSpecies is not None:
            if not "ca" in ionSpecies.attrib["name"]:
                pu.fatal("Sorry, I cannot handle non-Ca-ion pools. Exiting ...")
                sys.exit(1)
        capoolName = ionConcElement.attrib["name"]

        pu.info("Loading Ca pool %s into /library ." % capoolName)
        caPool = moose.CaConc("/library/" + capoolName)
        poolModel = ionConcElement.find("./{" + self.cml + "}decaying_pool_model")
        caPool.CaBasal = float(poolModel.attrib["resting_conc"]) * concfactor
        caPool.Ca_base = float(poolModel.attrib["resting_conc"]) * concfactor
        if "decay_constant" in poolModel.attrib:
            caPool.tau = float(poolModel.attrib["decay_constant"]) * Tfactor
        elif "inv_decay_constant" in poolModel.attrib:
            caPool.tau = 1.0 / float(poolModel.attrib["inv_decay_constant"]) * Tfactor
        ## Only one of pool_volume_info or fixed_pool_info should be present, but not checking
        volInfo = poolModel.find("./{" + self.cml + "}pool_volume_info")
        if volInfo is not None:
            caPool.thick = float(volInfo.attrib["shell_thickness"]) * Lfactor
        fixedPoolInfo = poolModel.find("./{" + self.cml + "}fixed_pool_info")
        if fixedPoolInfo is not None:
            ## Put in phi under the caPool, so that it can
            ## be used instead of thickness to set B (see section 19.2 in Book of Genesis)
            caPool_phi = moose.Mstring(caPool.path + "/phi")
            caPool_phi.value = str(float(fixedPoolInfo.attrib["phi"]) * concfactor / Ifactor / Tfactor)
示例#9
0
 def make_cml_function(self, element, fn_name, concdep=None):
     fn_type = element.attrib['expr_form']
     if fn_type in ['exponential','sigmoid','exp_linear']:
         self.make_function( fn_name, fn_type, rate=float(element.attrib['rate']),\
             midpoint=float(element.attrib['midpoint']), scale=float(element.attrib['scale'] ) )
     elif fn_type == 'generic':
         ## OOPS! These expressions should be in SI units, since I converted to SI
         ## Ideally I should not convert to SI and have the user consistently use one or the other
         ## Or convert constants in these expressions to SI, only voltage and ca_conc appear!
         ## NO! SEE ABOVE, for calculating values for tables, I use units specified in xml file,
         ## then I convert to SI while writing to MOOSE internal tables.
         expr_string = element.attrib['expr']
         if concdep is None: ca_name = ''                        # no Ca dependence
         else: ca_name = ','+concdep.attrib['variable_name']     # Ca dependence
         expr_string = expr_string.replace( 'alpha', 'self.alpha(v'+ca_name+')')
         expr_string = expr_string.replace( 'beta', 'self.beta(v'+ca_name+')')
         self.make_function( fn_name, fn_type, expr_string=expr_string, concdep=concdep )
     else:
         pu.fatal("Unsupported function type %s "% fn_type)
         sys.exit()
示例#10
0
    def readChannelML(self, channelElement, params={}, units="SI units"):
        ## I first calculate all functions assuming a consistent system of units.
        ## While filling in the A and B tables, I just convert to SI.
        ## Also convert gmax and Erev.
        if 'Physiological Units' in units:  # see pg 219 (sec 13.2) of Book of Genesis
            Vfactor = 1e-3  # V from mV
            Tfactor = 1e-3  # s from ms
            Gfactor = 1e1  # S/m^2 from mS/cm^2
            concfactor = 1e6  # Mol = mol/m^-3 from mol/cm^-3
        elif 'SI Units' in units:
            Vfactor = 1.0
            Tfactor = 1.0
            Gfactor = 1.0
            concfactor = 1.0
        else:
            raise RuntimeError("Wrong units %s. Existing" % units)

        if not moose.exists('/library'):
            moose.Neutral('/library')

        channel_name = channelElement.attrib['name']
        if utils.neuroml_debug:
            pu.info("Loading channel %s into /library" % channel_name)

        IVrelation = channelElement.find('./{' + self.cml +
                                         '}current_voltage_relation')
        intfire = IVrelation.find('./{' + self.cml + '}integrate_and_fire')

        if intfire is not None:
            ## Below params need to be set while making an LIF compartment
            moosechannel = moose.Neutral('/library/' + channel_name)
            moosechannelval = moose.Mstring(moosechannel.path + '/vReset')
            moosechannelval.value = str(
                float(intfire.attrib['v_reset']) * Vfactor)
            moosechannelval = moose.Mstring(moosechannel.path + '/thresh')
            moosechannelval.value = str(
                float(intfire.attrib['threshold']) * Vfactor)
            moosechannelval = moose.Mstring(moosechannel.path + '/refracT')
            moosechannelval.value = str(
                float(intfire.attrib['t_refrac']) * Tfactor)
            ## refracG is currently not supported by moose.LIF
            ## Confirm if g_refrac is a conductance density or not?
            ## assuming g_refrac is a conductance density below
            moosechannelval = moose.Mstring(moosechannel.path + '/refracG')
            moosechannelval.value = str(
                float(intfire.attrib['g_refrac']) * Gfactor)
            ## create an Mstring saying this is an integrate_and_fire mechanism
            moosechannelval = moose.Mstring(moosechannel.path +
                                            '/integrate_and_fire')
            moosechannelval.value = 'True'
            return

        concdep = IVrelation.find('./{' + self.cml + '}conc_dependence')
        if concdep is None:
            moosechannel = moose.HHChannel('/library/' + channel_name)
        else:
            moosechannel = moose.HHChannel2D('/library/' + channel_name)

        if IVrelation.attrib['cond_law'] == "ohmic":
            moosechannel.Gbar = float(
                IVrelation.attrib['default_gmax']) * Gfactor
            moosechannel.Ek = float(
                IVrelation.attrib['default_erev']) * Vfactor
            moosechannelIon = moose.Mstring(moosechannel.path + '/ion')
            moosechannelIon.value = IVrelation.attrib['ion']
            if concdep is not None:
                moosechannelIonDependency = moose.Mstring(moosechannel.path +
                                                          '/ionDependency')
                moosechannelIonDependency.value = concdep.attrib['ion']

        nernstnote = IVrelation.find('./{' + utils.meta_ns + '}notes')
        if nernstnote is not None:
            ## the text in nernstnote is "Nernst,Cout=<float>,z=<int>"
            nernst_params = nernstnote.text.split(',')
            if nernst_params[0] == 'Nernst':
                nernstMstring = moose.Mstring(moosechannel.path +
                                              '/nernst_str')
                nernstMstring.value = str( float(nernst_params[1].split('=')[1]) * concfactor ) + \
                                        ',' + str( int(nernst_params[2].split('=')[1]) )

        gates = IVrelation.findall('./{' + self.cml + '}gate')
        if len(gates) > 3:
            pu.fatal(
                "Sorry! Maximum x, y, and z (three) gates are possible in MOOSE/Genesis"
            )
            sys.exit()
        gate_full_name = [
            'gateX', 'gateY', 'gateZ'
        ]  # These are the names that MOOSE uses to create gates.
        ## if impl_prefs tag is present change VMIN, VMAX and NDIVS
        impl_prefs = channelElement.find('./{' + self.cml + '}impl_prefs')
        if impl_prefs is not None:
            table_settings = impl_prefs.find('./{' + self.cml +
                                             '}table_settings')
            ## some problem here... disable
            VMIN_here = float(table_settings.attrib['min_v'])
            VMAX_here = float(table_settings.attrib['max_v'])
            NDIVS_here = int(table_settings.attrib['table_divisions'])
            dv_here = (VMAX_here - VMIN_here) / NDIVS_here
        else:
            ## default VMIN, VMAX and dv are in SI
            ## convert them to current calculation units used by channel definition
            ## while loading into tables, convert them back to SI
            VMIN_here = utils.VMIN / Vfactor
            VMAX_here = utils.VMAX / Vfactor
            NDIVS_here = utils.NDIVS
            dv_here = utils.dv / Vfactor
        offset = IVrelation.find('./{' + self.cml + '}offset')
        if offset is None: vNegOffset = 0.0
        else: vNegOffset = float(offset.attrib['value'])
        self.parameters = []
        for parameter in channelElement.findall('.//{' + self.cml +
                                                '}parameter'):
            self.parameters.append(
                (parameter.attrib['name'], float(parameter.attrib['value'])))

        for num, gate in enumerate(gates):
            # if no q10settings tag, the q10factor remains 1.0
            # if present but no gate attribute, then set q10factor
            # if there is a gate attribute, then set it only if gate attrib matches gate name
            self.q10factor = 1.0
            self.gate_name = gate.attrib['name']
            for q10settings in IVrelation.findall('./{' + self.cml +
                                                  '}q10_settings'):
                ## self.temperature from neuro.utils
                if 'gate' in q10settings.attrib:
                    if q10settings.attrib['gate'] == self.gate_name:
                        self.setQ10(q10settings)
                        break
                else:
                    self.setQ10(q10settings)

            ############### HHChannel2D crashing on setting Xpower!
            #### temperamental! If you print something before, it gives cannot creategate from copied channel, else crashes
            ## Setting power first. This is necessary because it also
            ## initializes the gate's internal data structures as a side
            ## effect. Alternatively, gates can be initialized explicitly
            ## by calling HHChannel.createGate().
            gate_power = float(gate.get('instances'))
            if num == 0:
                moosechannel.Xpower = gate_power
                if concdep is not None: moosechannel.Xindex = "VOLT_C1_INDEX"
            elif num == 1:
                moosechannel.Ypower = gate_power
                if concdep is not None: moosechannel.Yindex = "VOLT_C1_INDEX"
            elif num == 2:
                moosechannel.Zpower = gate_power
                if concdep is not None: moosechannel.Zindex = "VOLT_C1_INDEX"

            ## Getting handle to gate using the gate's path.
            gate_path = moosechannel.path + '/' + gate_full_name[num]
            if concdep is None:
                if not moose.exists(gate_path):
                    moosegate = moose.HHGate(gate_path)
                else:
                    moosegate = moose.element(gate_path)
                ## set SI values inside MOOSE
                moosegate.min = VMIN_here * Vfactor
                moosegate.max = VMAX_here * Vfactor
                moosegate.divs = NDIVS_here
                ## V.IMP to get smooth curves, else even with 3000 divisions
                ## there are sudden transitions.
                moosegate.useInterpolation = True
            else:
                moosegate = moose.HHGate2D(gate_path)

            ##### If alpha and beta functions exist, make them here
            for transition in gate.findall('./{' + self.cml + '}transition'):
                ## make python functions with names of transitions...
                fn_name = transition.attrib['name']
                ## I assume that transitions if present are called alpha and beta
                ## for forward and backward transitions...
                if fn_name in ['alpha', 'beta']:
                    self.make_cml_function(transition, fn_name, concdep)
                else:
                    pu.fatal("Unsupported transition %s" % fn_name)
                    sys.exit()

            time_course = gate.find('./{' + self.cml + '}time_course')
            ## tau is divided by self.q10factor in make_function()
            ## thus, it gets divided irrespective of <time_course> tag present or not.
            if time_course is not None:
                self.make_cml_function(time_course, 'tau', concdep)
            steady_state = gate.find('./{' + self.cml + '}steady_state')
            if steady_state is not None:
                self.make_cml_function(steady_state, 'inf', concdep)

            if concdep is None: ca_name = ''  # no Ca dependence
            else:
                ca_name = ',' + concdep.attrib[
                    'variable_name']  # Ca dependence

            ## Create tau() and inf() if not present, from alpha() and beta()
            for fn_element,fn_name,fn_expr in [(time_course,'tau',"1/(alpha+beta)"),\
                                                (steady_state,'inf',"alpha/(alpha+beta)")]:
                ## put in args for alpha and beta, could be v and Ca dep.
                expr_string = fn_expr.replace('alpha',
                                              'self.alpha(v' + ca_name + ')')
                expr_string = expr_string.replace(
                    'beta', 'self.beta(v' + ca_name + ')')
                ## if time_course/steady_state are not present,
                ## then alpha annd beta transition elements should be present, and fns created.
                if fn_element is None:
                    self.make_function(fn_name,
                                       'generic',
                                       expr_string=expr_string,
                                       concdep=concdep)

            ## non Ca dependent channel
            if concdep is None:
                ## while calculating, use the units used in xml defn,
                ## while filling in table, I convert to SI units.
                v0 = VMIN_here - vNegOffset
                n_entries = NDIVS_here + 1
                tableA = [0.0] * n_entries
                tableB = [0.0] * n_entries
                for i in range(n_entries):
                    v = v0 + i * dv_here

                    inf = self.inf(v)
                    tau = self.tau(v)
                    ## convert to SI before writing to table
                    ## qfactor is already in inf and tau
                    tableA[i] = inf / tau / Tfactor
                    tableB[i] = 1.0 / tau / Tfactor

                moosegate.tableA = tableA
                moosegate.tableB = tableB

            ## Ca dependent channel
            else:
                ## UNITS: while calculating, use the units used in xml defn,
                ##        while filling in table, I convert to SI units.
                ##        Note here Ca units do not enter, but
                ##         units of CaMIN, CaMAX and ca_conc in fn expr should match.
                v = VMIN_here - vNegOffset
                CaMIN = float(concdep.attrib['min_conc'])
                CaMAX = float(concdep.attrib['max_conc'])
                CaNDIVS = 100
                dCa = (CaMAX - CaMIN) / CaNDIVS
                ## CAREFUL!: tableA = [[0.0]*(CaNDIVS+1)]*(NDIVS_here+1) will not work!
                ## * does a shallow copy, same list will get repeated 200 times!
                ## Thus setting tableA[35][1] = 5.0 will set all rows, 1st col to 5.0!!!!
                tableA = [[0.0] * (CaNDIVS + 1) for i in range(NDIVS_here + 1)]
                tableB = [[0.0] * (CaNDIVS + 1) for i in range(NDIVS_here + 1)]
                for i in range(NDIVS_here + 1):
                    Ca = CaMIN
                    for j in range(CaNDIVS + 1):
                        inf = self.inf(v, Ca)
                        tau = self.tau(v, Ca)
                        ## convert to SI (Tfactor) before writing to table
                        ## qfactor is already in inf and tau
                        tableA[i][j] = inf / tau / Tfactor
                        tableB[i][j] = 1.0 / tau / Tfactor
                        Ca += dCa
                    v += dv_here

                ## Presently HHGate2D doesn't allow the setting of tables as 2D vectors directly
                moosegate.tableA = tableA
                moosegate.tableB = tableB

                ## set SI values inside MOOSE
                moosegate.xminA = VMIN_here * Vfactor
                moosegate.xmaxA = VMAX_here * Vfactor
                moosegate.xdivsA = NDIVS_here
                #moosegate.dxA = dv_here*Vfactor
                moosegate.yminA = CaMIN * concfactor
                moosegate.ymaxA = CaMAX * concfactor
                moosegate.ydivsA = CaNDIVS
                #moosegate.dyB = dCa*concfactor

                ## set SI values inside MOOSE
                moosegate.xminB = VMIN_here * Vfactor
                moosegate.xmaxB = VMAX_here * Vfactor
                moosegate.xdivsB = NDIVS_here
                #moosegate.dxB = dv_here*Vfactor
                moosegate.yminB = CaMIN * concfactor
                moosegate.ymaxB = CaMAX * concfactor
                moosegate.ydivsB = CaNDIVS
示例#11
0
    def readChannelML(self, channelElement, params={}, units="SI units"):
        ## I first calculate all functions assuming a consistent system of units.
        ## While filling in the A and B tables, I just convert to SI.
        ## Also convert gmax and Erev.
        if "Physiological Units" in units:  # see pg 219 (sec 13.2) of Book of Genesis
            Vfactor = 1e-3  # V from mV
            Tfactor = 1e-3  # s from ms
            Gfactor = 1e1  # S/m^2 from mS/cm^2
            concfactor = 1e6  # Mol = mol/m^-3 from mol/cm^-3
        elif "SI Units" in units:
            Vfactor = 1.0
            Tfactor = 1.0
            Gfactor = 1.0
            concfactor = 1.0
        else:
            pu.fatal("Wrong units %s. Existing" % units)
            sys.exit(1)
        moose.Neutral("/library")  # creates /library in MOOSE tree; elif present, wraps
        channel_name = channelElement.attrib["name"]
        if utils.neuroml_debug:
            pu.info("Loading channel %s into /library" % channel_name)

        IVrelation = channelElement.find("./{" + self.cml + "}current_voltage_relation")
        intfire = IVrelation.find("./{" + self.cml + "}integrate_and_fire")

        if intfire is not None:
            ## Below params need to be set while making an LIF compartment
            moosechannel = moose.Neutral("/library/" + channel_name)
            moosechannelval = moose.Mstring(moosechannel.path + "/vReset")
            moosechannelval.value = str(float(intfire.attrib["v_reset"]) * Vfactor)
            moosechannelval = moose.Mstring(moosechannel.path + "/thresh")
            moosechannelval.value = str(float(intfire.attrib["threshold"]) * Vfactor)
            moosechannelval = moose.Mstring(moosechannel.path + "/refracT")
            moosechannelval.value = str(float(intfire.attrib["t_refrac"]) * Tfactor)
            ## refracG is currently not supported by moose.LIF
            ## Confirm if g_refrac is a conductance density or not?
            ## assuming g_refrac is a conductance density below
            moosechannelval = moose.Mstring(moosechannel.path + "/refracG")
            moosechannelval.value = str(float(intfire.attrib["g_refrac"]) * Gfactor)
            ## create an Mstring saying this is an integrate_and_fire mechanism
            moosechannelval = moose.Mstring(moosechannel.path + "/integrate_and_fire")
            moosechannelval.value = "True"
            return

        concdep = IVrelation.find("./{" + self.cml + "}conc_dependence")
        if concdep is None:
            moosechannel = moose.HHChannel("/library/" + channel_name)
        else:
            moosechannel = moose.HHChannel2D("/library/" + channel_name)

        if IVrelation.attrib["cond_law"] == "ohmic":
            moosechannel.Gbar = float(IVrelation.attrib["default_gmax"]) * Gfactor
            moosechannel.Ek = float(IVrelation.attrib["default_erev"]) * Vfactor
            moosechannelIon = moose.Mstring(moosechannel.path + "/ion")
            moosechannelIon.value = IVrelation.attrib["ion"]
            if concdep is not None:
                moosechannelIonDependency = moose.Mstring(moosechannel.path + "/ionDependency")
                moosechannelIonDependency.value = concdep.attrib["ion"]

        nernstnote = IVrelation.find("./{" + utils.meta_ns + "}notes")
        if nernstnote is not None:
            ## the text in nernstnote is "Nernst,Cout=<float>,z=<int>"
            nernst_params = nernstnote.text.split(",")
            if nernst_params[0] == "Nernst":
                nernstMstring = moose.Mstring(moosechannel.path + "/nernst_str")
                nernstMstring.value = (
                    str(float(nernst_params[1].split("=")[1]) * concfactor)
                    + ","
                    + str(int(nernst_params[2].split("=")[1]))
                )

        gates = IVrelation.findall("./{" + self.cml + "}gate")
        if len(gates) > 3:
            pu.fatal("Sorry! Maximum x, y, and z (three) gates are possible in MOOSE/Genesis")
            sys.exit()
        gate_full_name = ["gateX", "gateY", "gateZ"]  # These are the names that MOOSE uses to create gates.
        ## if impl_prefs tag is present change VMIN, VMAX and NDIVS
        impl_prefs = channelElement.find("./{" + self.cml + "}impl_prefs")
        if impl_prefs is not None:
            table_settings = impl_prefs.find("./{" + self.cml + "}table_settings")
            ## some problem here... disable
            VMIN_here = float(table_settings.attrib["min_v"])
            VMAX_here = float(table_settings.attrib["max_v"])
            NDIVS_here = int(table_settings.attrib["table_divisions"])
            dv_here = (VMAX_here - VMIN_here) / NDIVS_here
        else:
            ## default VMIN, VMAX and dv are in SI
            ## convert them to current calculation units used by channel definition
            ## while loading into tables, convert them back to SI
            VMIN_here = utils.VMIN / Vfactor
            VMAX_here = utils.VMAX / Vfactor
            NDIVS_here = utils.NDIVS
            dv_here = utils.dv / Vfactor
        offset = IVrelation.find("./{" + self.cml + "}offset")
        if offset is None:
            vNegOffset = 0.0
        else:
            vNegOffset = float(offset.attrib["value"])
        self.parameters = []
        for parameter in channelElement.findall(".//{" + self.cml + "}parameter"):
            self.parameters.append((parameter.attrib["name"], float(parameter.attrib["value"])))

        for num, gate in enumerate(gates):
            # if no q10settings tag, the q10factor remains 1.0
            # if present but no gate attribute, then set q10factor
            # if there is a gate attribute, then set it only if gate attrib matches gate name
            self.q10factor = 1.0
            self.gate_name = gate.attrib["name"]
            for q10settings in IVrelation.findall("./{" + self.cml + "}q10_settings"):
                ## self.temperature from neuro.utils
                if "gate" in q10settings.attrib:
                    if q10settings.attrib["gate"] == self.gate_name:
                        self.setQ10(q10settings)
                        break
                else:
                    self.setQ10(q10settings)

            ############### HHChannel2D crashing on setting Xpower!
            #### temperamental! If you print something before, it gives cannot creategate from copied channel, else crashes
            ## Setting power first. This is necessary because it also
            ## initializes the gate's internal data structures as a side
            ## effect. Alternatively, gates can be initialized explicitly
            ## by calling HHChannel.createGate().
            gate_power = float(gate.get("instances"))
            if num == 0:
                moosechannel.Xpower = gate_power
                if concdep is not None:
                    moosechannel.Xindex = "VOLT_C1_INDEX"
            elif num == 1:
                moosechannel.Ypower = gate_power
                if concdep is not None:
                    moosechannel.Yindex = "VOLT_C1_INDEX"
            elif num == 2:
                moosechannel.Zpower = gate_power
                if concdep is not None:
                    moosechannel.Zindex = "VOLT_C1_INDEX"

            ## Getting handle to gate using the gate's path.
            gate_path = moosechannel.path + "/" + gate_full_name[num]
            if concdep is None:
                moosegate = moose.HHGate(gate_path)
                ## set SI values inside MOOSE
                moosegate.min = VMIN_here * Vfactor
                moosegate.max = VMAX_here * Vfactor
                moosegate.divs = NDIVS_here
                ## V.IMP to get smooth curves, else even with 3000 divisions
                ## there are sudden transitions.
                moosegate.useInterpolation = True
            else:
                moosegate = moose.HHGate2D(gate_path)

            ##### If alpha and beta functions exist, make them here
            for transition in gate.findall("./{" + self.cml + "}transition"):
                ## make python functions with names of transitions...
                fn_name = transition.attrib["name"]
                ## I assume that transitions if present are called alpha and beta
                ## for forward and backward transitions...
                if fn_name in ["alpha", "beta"]:
                    self.make_cml_function(transition, fn_name, concdep)
                else:
                    pu.fatal("Unsupported transition %s" % fn_name)
                    sys.exit()

            time_course = gate.find("./{" + self.cml + "}time_course")
            ## tau is divided by self.q10factor in make_function()
            ## thus, it gets divided irrespective of <time_course> tag present or not.
            if time_course is not None:
                self.make_cml_function(time_course, "tau", concdep)
            steady_state = gate.find("./{" + self.cml + "}steady_state")
            if steady_state is not None:
                self.make_cml_function(steady_state, "inf", concdep)

            if concdep is None:
                ca_name = ""  # no Ca dependence
            else:
                ca_name = "," + concdep.attrib["variable_name"]  # Ca dependence

            ## Create tau() and inf() if not present, from alpha() and beta()
            for fn_element, fn_name, fn_expr in [
                (time_course, "tau", "1/(alpha+beta)"),
                (steady_state, "inf", "alpha/(alpha+beta)"),
            ]:
                ## put in args for alpha and beta, could be v and Ca dep.
                expr_string = fn_expr.replace("alpha", "self.alpha(v" + ca_name + ")")
                expr_string = expr_string.replace("beta", "self.beta(v" + ca_name + ")")
                ## if time_course/steady_state are not present,
                ## then alpha annd beta transition elements should be present, and fns created.
                if fn_element is None:
                    self.make_function(fn_name, "generic", expr_string=expr_string, concdep=concdep)

            ## non Ca dependent channel
            if concdep is None:
                ## while calculating, use the units used in xml defn,
                ## while filling in table, I convert to SI units.
                v0 = VMIN_here - vNegOffset
                n_entries = NDIVS_here + 1
                tableA = [0.0] * n_entries
                tableB = [0.0] * n_entries
                for i in range(n_entries):
                    v = v0 + i * dv_here

                    inf = self.inf(v)
                    tau = self.tau(v)
                    ## convert to SI before writing to table
                    ## qfactor is already in inf and tau
                    tableA[i] = inf / tau / Tfactor
                    tableB[i] = 1.0 / tau / Tfactor

                moosegate.tableA = tableA
                moosegate.tableB = tableB

            ## Ca dependent channel
            else:
                ## UNITS: while calculating, use the units used in xml defn,
                ##        while filling in table, I convert to SI units.
                ##        Note here Ca units do not enter, but
                ##         units of CaMIN, CaMAX and ca_conc in fn expr should match.
                v = VMIN_here - vNegOffset
                CaMIN = float(concdep.attrib["min_conc"])
                CaMAX = float(concdep.attrib["max_conc"])
                CaNDIVS = 100
                dCa = (CaMAX - CaMIN) / CaNDIVS
                ## CAREFUL!: tableA = [[0.0]*(CaNDIVS+1)]*(NDIVS_here+1) will not work!
                ## * does a shallow copy, same list will get repeated 200 times!
                ## Thus setting tableA[35][1] = 5.0 will set all rows, 1st col to 5.0!!!!
                tableA = [[0.0] * (CaNDIVS + 1) for i in range(NDIVS_here + 1)]
                tableB = [[0.0] * (CaNDIVS + 1) for i in range(NDIVS_here + 1)]
                for i in range(NDIVS_here + 1):
                    Ca = CaMIN
                    for j in range(CaNDIVS + 1):
                        inf = self.inf(v, Ca)
                        tau = self.tau(v, Ca)
                        ## convert to SI (Tfactor) before writing to table
                        ## qfactor is already in inf and tau
                        tableA[i][j] = inf / tau / Tfactor
                        tableB[i][j] = 1.0 / tau / Tfactor
                        Ca += dCa
                    v += dv_here

                ## Presently HHGate2D doesn't allow the setting of tables as 2D vectors directly
                moosegate.tableA = tableA
                moosegate.tableB = tableB

                ## set SI values inside MOOSE
                moosegate.xminA = VMIN_here * Vfactor
                moosegate.xmaxA = VMAX_here * Vfactor
                moosegate.xdivsA = NDIVS_here
                # moosegate.dxA = dv_here*Vfactor
                moosegate.yminA = CaMIN * concfactor
                moosegate.ymaxA = CaMAX * concfactor
                moosegate.ydivsA = CaNDIVS
                # moosegate.dyB = dCa*concfactor

                ## set SI values inside MOOSE
                moosegate.xminB = VMIN_here * Vfactor
                moosegate.xmaxB = VMAX_here * Vfactor
                moosegate.xdivsB = NDIVS_here
                # moosegate.dxB = dv_here*Vfactor
                moosegate.yminB = CaMIN * concfactor
                moosegate.ymaxB = CaMAX * concfactor
                moosegate.ydivsB = CaNDIVS