Example #1
0
def interpolation_demo():
    interpol = moose.Interpol2D('/interpol2D')
    interpol.xmin = 0.0
    interpol.xmax = 1.0
    interpol.ymin = 0.0
    interpol.ymax = 1.0
    # Make a 50 element array with entries at equal distance from
    # [0,1) and reshape it into a 10x5 matrix and assign to table.
    matrix = np.linspace(0, 1.0, 50).reshape(10, 5)
    print('Setting table to')
    print(matrix)
    interpol.tableVector2D = matrix
    # interpolating beyond top left corner.
    # value should be 
    pos = (0.8, 0.3)
    
    print(('Interpolated value at', pos))
    print((interpol.z[pos[0], pos[1]]))
    
    print(('Point going out of bound on both x and y', interpol.z[1.1, 1.1]))
    print(('Point going out of bound on both x and y', interpol.z[0.5, 1.1]))
Example #2
0
    def readChannelML(self, channelElement, params={}, units="SI units"):
        """Loads a single channel
        """
        # 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:
            debug.printDebug("ERR",
                             "wrong units %s. Existing... " % units,
                             frame=inspect.currentframe())
            raise UserWarning, "Unknown units"

        # creates /library in MOOSE tree; elif present, wraps
        channel_name = channelElement.attrib['name']
        if utils.neuroml_debug:
            msg = "Loading channel {} into {} ".format(channel_name,
                                                       self.libraryPath)
            debug.printDebug("INFO", msg)

        IVrelation = channelElement.find('./{' + self.cml +
                                         '}current_voltage_relation')
        concdep = IVrelation.find('./{' + self.cml + '}conc_dependence')
        cPath = os.path.join(self.libraryPath, channel_name)
        if concdep is None:
            channel = moose.HHChannel(cPath)
        else:
            channel = moose.HHChannel2D(cPath)

        if IVrelation.attrib['cond_law'] == "ohmic":
            channel.Gbar = float(IVrelation.attrib['default_gmax']) * Gfactor
            channel.Ek = float(IVrelation.attrib['default_erev']) * Vfactor
            channelIon = moose.Mstring(channel.path + '/ion')
            channelIon.value = IVrelation.attrib['ion']
            if concdep is not None:
                channelIonDependency = moose.Mstring(channel.path +
                                                     '/ionDependency')
                channelIonDependency.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 = string.split(nernstnote.text, ',')
            if nernst_params[0] == 'Nernst':
                nernstMstring = moose.Mstring(channel.path + '/nernst_str')
                nernstMstring.value = str(
                    float(string.split(nernst_params[1], '=')[1]) *
                    concfactor) + ',' + str(
                        int(string.split(nernst_params[2], '=')[1]))

        gates = IVrelation.findall('./{' + self.cml + '}gate')
        if len(gates) > 3:
            msg = "Sorry! Maximum x, y, and z (three) gates are possible in\
                      MOOSE/Genesis"

            debug.printDebug("ERR", msg, frame=inspect.currentframe())
            raise UserWarning, "Bad value or parameter"

        # These are the names that MOOSE uses to create gates.
        gate_full_name = ['gateX', 'gateY', 'gateZ']

        # 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']
            q10sets = IVrelation.findall('./{' + self.cml + '}q10_settings')
            for q10settings in q10sets:
                # self.temperature from neuro.utils
                if 'gate' in list(q10settings.attrib.keys()):
                    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:
                channel.Xpower = gate_power
                if concdep is not None: channel.Xindex = "VOLT_C1_INDEX"
            elif num == 1:
                channel.Ypower = gate_power
                if concdep is not None: channel.Yindex = "VOLT_C1_INDEX"
            elif num == 2:
                channel.Zpower = gate_power
                if concdep is not None: channel.Zindex = "VOLT_C1_INDEX"

            ## Getting handle to gate using the gate's path.
            gate_path = os.path.join(channel.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 forwand backward transitions...
                if fn_name in ['alpha', 'beta']:
                    self.make_cml_function(transition, fn_name, concdep)
                else:
                    debug.printDebug(
                        "ERROR", "Unsupported transition {0}".format(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 dependence
                ca_name = ',' + concdep.attrib['variable_name']

            # 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 = self.replace(fn_expr, 'alpha',
                                           'self.alpha(v' + ca_name + ')')
                expr_string = self.replace(expr_string, '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

                # Instead, I wrap the interpol2D objects inside HHGate2D and set
                # the tables
                moosegate_tableA = moose.Interpol2D(moosegate.path + '/tableA')

                # set SI values inside MOOSE
                moosegate_tableA.xmin = VMIN_here * Vfactor
                moosegate_tableA.xmax = VMAX_here * Vfactor
                moosegate_tableA.xdivs = NDIVS_here
                #moosegate_tableA.dx = dv_here*Vfactor
                moosegate_tableA.ymin = CaMIN * concfactor
                moosegate_tableA.ymax = CaMAX * concfactor
                moosegate_tableA.ydivs = CaNDIVS
                #moosegate_tableA.dy = dCa*concfactor
                moosegate_tableA.tableVector2D = tableA

                moosegate_tableB = moose.Interpol2D(moosegate.path + '/tableB')
                ## set SI values inside MOOSE
                moosegate_tableB.xmin = VMIN_here * Vfactor
                moosegate_tableB.xmax = VMAX_here * Vfactor
                moosegate_tableB.xdivs = NDIVS_here
                #moosegate_tableB.dx = dv_here*Vfactor
                moosegate_tableB.ymin = CaMIN * concfactor
                moosegate_tableB.ymax = CaMAX * concfactor
                moosegate_tableB.ydivs = CaNDIVS
                #moosegate_tableB.dy = dCa*concfactor
                moosegate_tableB.tableVector2D = tableB