Ejemplo n.º 1
0
def BKchan_proto(chanparams,
                 VDIVS=3000,
                 VMIN=-100e-3,
                 VMAX=50e-3,
                 CAMIN=0,
                 CAMAX=1,
                 CADIVS=5000):
    ZFbyRT = 2 * 96520 / (8.3134 * (23 + 273.15))
    v_array = np.linspace(VMIN, VMAX, VDIVS)
    ca_array = np.linspace(CAMIN, CAMAX, CADIVS)
    #set up the two dimensional gating matrix:
    gatingMatrix = []
    for i, pars in enumerate(chanparams.Xparam):
        Vdepgating = pars.K * np.exp(pars.delta * ZFbyRT * v_array)
        #These assignments are specific to the BK channel, calculate 2D array of gating values
        if i == 0:
            #This is the forward rate constant for a two state channel
            gatingMatrix.append(
                pars.alphabeta * ca_array[None, :] /
                (ca_array[None, :] + pars.K * Vdepgating[:, None]))
        else:
            #this is backward rate constant for a two state channel
            gatingMatrix.append(
                pars.alphabeta /
                (1 + ca_array[None, :] / pars.K * Vdepgating[:, None]))
    #adding forward rate to backward rate  gives “alpha+beta” which = 1/tau
        gatingMatrix[i] += gatingMatrix[0]

    chan = moose.HHChannel2D(
        '/library/' +
        chanparams.name)  # two dimensional tabulated channel gating
    chan.Xpower = chanparams.Xpow
    chan.Ek = chanparams.Erev
    chan.Xindex = "VOLT_C1_INDEX"  # critical for correctly using voltage and calcium
    xGate = moose.HHGate2D(chan.path + '/gateX')
    xGate.xminA = xGate.xminB = VMIN
    xGate.xmaxA = xGate.xmaxB = VMAX
    xGate.xdivsA = xGate.xdivsB = VDIVS
    xGate.yminA = xGate.yminB = CAMIN
    xGate.ymaxA = xGate.ymaxB = CAMAX
    xGate.ydivsA = xGate.ydivsB = CADIVS
    xGate.tableA = gatingMatrix[
        0]  # assign gatingMatrix to tables, [0] is forw rate = ss/tau
    xGate.tableB = gatingMatrix[1]  #[1] is 1/tau
    return chan
Ejemplo n.º 2
0
def BKchan_proto(model, chanpath, params):
    ZFbyRT= 2 * constants.Faraday / (constants.R * constants.celsius_to_kelvin(model.Temp))
    v_array = np.linspace(model.VMIN, model.VMAX, model.VDIVS)
    ca_array = np.linspace(model.CAMIN, model.CAMAX, model.CADIVS)
    if model.VDIVS<=5 and model.CADIVS<=5:
        log.info("{}, {}", v_array, ca_array)
    gatingMatrix = []
    for i,pars in enumerate(params.X):
        Vdepgating=pars.K*np.exp(pars.delta*ZFbyRT*v_array)
        if i == 0:
            gatingMatrix.append(pars.alphabeta*ca_array[None,:]/(ca_array[None,:]+pars.K*Vdepgating[:,None]))
            #table.tableVector2D=gatingMatrix
        else:
            gatingMatrix.append(pars.alphabeta/(1+ca_array[None,:]/pars.K*Vdepgating[:,None]))
            gatingMatrix[i] += gatingMatrix[0]
            #table.tableVector2D=gatingMatrix


    chan = moose.HHChannel2D(chanpath)
    chan.Xpower = params.channel.Xpow
    chan.Ek=params.channel.Erev
    chan.Xindex="VOLT_C1_INDEX"
    xGate = moose.HHGate2D(chan.path + '/gateX')
    xGate.xminA=xGate.xminB=model.VMIN
    xGate.xmaxA=xGate.xmaxB=model.VMAX
    xGate.xdivsA=xGate.xdivsB=model.VDIVS
    xGate.yminA=xGate.yminB=model.CAMIN
    xGate.ymaxA=xGate.ymaxB=model.CAMAX
    xGate.ydivsA=xGate.ydivsB=model.CADIVS
    xGate.tableA=gatingMatrix[0]
    xGate.tableB=gatingMatrix[1]
    if log.isEnabledFor(logging.INFO):
        log.info("{}", chan.path)
        for ii in np.arange(0, model.VDIVS,1000):
            log.info("V={}", model.VMIN+ii*(model.VMAX-model.VMIN)/(model.VDIVS-1))
            for jj in np.arange(0,model.CADIVS,1000):
                log.info("    Ca={} A,B={},{}",
                         model.CAMIN+jj*(model.CAMAX-model.CAMIN)/(model.CADIVS-1),
                         xGate.tableA[ii][jj], xGate.tableB[ii][jj])
    return chan
Ejemplo n.º 3
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
Ejemplo n.º 4
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