Esempio n. 1
0
def ideal_subset_mean_life_time(Q, state1, state2):
    """
    Calculate mean life time in a specified subset. Add all rates out of subset
    to get total rate out. Skip rates within subset.

    Parameters
    ----------
    mec : instance of type Mechanism
    state1,state2 : int
        State numbers (counting origin 1)

    Returns
    -------
    mean : float
        Mean life time.
    """

    k = Q.shape[0]
    p = qml.pinf(Q)
    # Total occupancy for subset.
    pstot = np.sum(p[state1-1 : state2])

    # Total rate out
    if pstot == 0:
        mean = 0.0
    else:
        s = 0.0
        for i in range(state1-1, state2):
            for j in range(k):
                if (j < state1-1) or (j > state2 - 1):
                    s += Q[i, j] * p[i] / pstot

        mean = 1 / s
    return mean
Esempio n. 2
0
def Popen(mec, tres, conc=0, eff='c'):
    """
    Calculate equilibrium open probability (Popen) and correct for
    unresolved blockages in case of presence of fast pore blocker.

    Parameters
    ----------
    mec : dcpyps.Mechanism
        The mechanism to be analysed.
    tres : float
        Time resolution (dead time).
    conc : float
        Concentration.

    Returns
    -------
    Popen : float
        Open probability value at a given concentration.
    """
    mec.set_eff(eff, conc)
    if tres == 0:
        p = qml.pinf(mec.QGG)
        popen = np.sum(p[:mec.kA]) / np.sum(p)
    else:
        hmopen, hmshut = scl.exact_mean_open_shut_time(mec, tres)
        popen = (hmopen / (hmopen + hmshut))
    if mec.fastblock:
        popen = popen / (1 + conc / mec.fastKB)
    return popen
Esempio n. 3
0
def shut_times_between_burst_pdf_components(mec):
    """
    Calculate time constants and amplitudes for a PDF of gaps between bursts.

    Parameters
    ----------
    mec : dcpyps.Mechanism
        The mechanism to be analysed.

    Returns
    -------
    eigs : ndarray, shape(k, 1)
        Time constants.
    w : ndarray, shape(k, 1)
        Component amplitudes.
    """

    uA = np.ones((mec.kA, 1))
    eigsB, AmatB = qml.eigs(-mec.QBB)
    eigsF, AmatF = qml.eigs(-mec.QFF)
    pA = qml.pinf(mec.Q)[:mec.kA]
    end = np.dot(-mec.QAA, endBurst(mec))
    start = pA / np.dot(pA, end)

    rowB = np.dot(start, mec.QAB)
    rowF = np.dot(start, mec.QAF)
    colB = np.dot(mec.QBA, uA)
    colF = np.dot(mec.QFA, uA)
    wB = -np.dot(np.dot(rowB, AmatB), colB)
    wF = np.dot(np.dot(rowF, AmatF), colF)

    w = np.append(wB, wF)
    eigs = np.append(eigsB, eigsF)
    return eigs, w
Esempio n. 4
0
def shut_times_between_burst_mean(mec):
    """
    Calculate the mean length of the gap between bursts (Eq. 3.86, CH82).

    Parameters
    ----------
    mec : dcpyps.Mechanism
        The mechanism to be analysed.

    Returns
    -------
    m : float
        The mean shut time between bursts.
    """

    pA = qml.pinf(mec.Q)[:mec.kA]
    end = np.dot(-mec.QAA, endBurst(mec))
    start = pA / np.dot(pA, end)
    uA = np.ones((mec.kA, 1))

    GAF, GFA = qml.iGs(mec.Q, mec.kA, mec.kF)
    invQFF = -nplin.inv(mec.QFF)
    invQBB = -nplin.inv(mec.QBB)
    GAB, GBA = qml.iGs(mec.Q, mec.kA, mec.kB)

    m1 = np.dot(np.dot(mec.QAF, invQFF), GFA)
    m2 = np.dot(np.dot(mec.QAB, invQBB), GBA)
    m = np.dot(np.dot(start, m1 - m2), uA)[0]

    return m
Esempio n. 5
0
def transition_frequency(Q):
    """
    """
    k = Q.shape[0]
    pinf = qml.pinf(Q)
    f = Q.copy().transpose()
    for i in range(k):
        f[i] = f[i] * pinf
        f[i,i] = 0
    return f.transpose()
Esempio n. 6
0
def calc_jump (mec, reclen, step, cfunc, cargs):
    """
    Calculate response to a concentration pulse directly from Q matrix.

    Parameters
    ----------
    mec : dcpyps.Mechanism
        The mechanism to be analysed.
    reclen : float
        Trace length.
    step : float
        Sampling time interval.
    cfunc : function
        Concentration profile.
    cargs : tuple
        Arguments for cfunc(t, cargs).

    Returns
    -------
    t : ndarray
        Time samples.
    c : ndarray
        Concentration profile.
    P : ndarray
        All state occupancies.
    Popen : ndarray
        Open probability.
    """

    t = np.arange(0, reclen, step)
    c =  cfunc(t, cargs)
    mec.set_eff('c', cargs[1])
    pi = qml.pinf(mec.Q)
    Pt = np.array([pi.copy()])

    for i in range(1, t.shape[0]):
        mec.set_eff('c', c[i])
        eigenvals, A = qml.eigs_sorted(mec.Q)
        w = coefficient_calc(mec.k, A, pi)
        pi = P_t(step, eigenvals, w)
        Pt = np.append(Pt, [pi.copy()], axis=0)

    P = Pt.transpose()
    Popen = np.sum(P[: mec.kA], axis=0)
    return t, c, Popen, P
Esempio n. 7
0
def weighted_taus(mec, cmax, width, eff='c'):
    """
    Calculate weighted on and off time constants for a square concentration 
    pulse.
    
    Parameters
    ----------
    mec : dcpyps.Mechanism
        The mechanism to be analysed.
    cmax : float
        Pulse concentration.
    width : float
        Pulse width.

    Returns
    -------
    tau_on_weighted, tau_off_weighted : floats
        Weighted time constants.
    """
    
    mec.set_eff(eff, 0)
    eigs0, A0 = qml.eigs_sorted(mec.Q)
    P0 = qml.pinf(mec.Q)
    mec.set_eff(eff, cmax)
    eigsInf, Ainf = qml.eigs_sorted(mec.Q)
    w_on = coefficient_calc(mec.k, Ainf, P0)
    Pt = P_t(width, eigsInf, w_on)
    w_off = coefficient_calc(mec.k, A0, Pt)

    ampl_on = np.sum(w_on[:, :mec.kA], axis=1)
    max_ampl_on = np.max(np.abs(ampl_on))
    rel_ampl_on = ampl_on / max_ampl_on
    tau_on_weighted = np.sum(-rel_ampl_on[:-1] * (-1 / eigsInf[:-1]))
    tau_on = -1 / eigsInf[:-1]

    ampl_off = np.sum(w_off[:, :mec.kA], axis=1)
    max_ampl_off = np.max(np.abs(ampl_off))
    rel_ampl_off = ampl_off / max_ampl_off
    tau_off_weighted = np.sum(rel_ampl_off[: -1] * (-1 / eigs0[:-1]))
    tau_off = -1 / eigs0[:-1]

    return tau_on_weighted, tau_on, tau_off_weighted, tau_off
Esempio n. 8
0
def solve_jump(mec, reclen, step, cfunc, cargs, abserr=1.0e-8, relerr=1.0e-6):
    """
    Calculate response to a concentration pulse by integration.

    Parameters
    ----------
    mec : dcpyps.Mechanism
        The mechanism to be analysed.
    reclen : float
        Trace length.
    step : float
        Sampling time interval.
    cfunc : function
        Concentration profile.
    cargs : tuple
        Arguments for cfunc(t, cargs).
    rtol, atol : float, optional
        Tolerance limits for the error control performed by the scipy.odeint solver.

    Returns
    -------
    t : ndarray
        Time samples.
    c : ndarray
        Concentration profile.
    P : ndarray
        All state occupancies.
    Popen : ndarray
        Open probability.
    """

    t = np.arange(0, reclen, step)
    mec.set_eff('c', cargs[1])
    P0 = qml.pinf(mec.Q)
    Pt = scpi.odeint(dPdt, P0, t, args=(mec, cfunc, cargs),
        atol=abserr,rtol=relerr)
    P = Pt.transpose()
    Popen = np.sum(P[: mec.kA], axis=0)
    c =  cfunc(t, cargs)
    return t, c, Popen, P
Esempio n. 9
0
def phiBurst(mec):
    """
    Calculate the start probabilities of a burst (Eq. 3.2, CH82).
    phiB = (pCinf * (QCB * GBA + QCA)) / (pCinf * (QCB * GBA + QCA) * uA)

    Parameters
    ----------
    mec : dcpyps.Mechanism
        The mechanism to be analysed.

    Returns
    -------
    phiB : array_like, shape (1, kA)
    """

    uA = np.ones((mec.kA, 1))
    pC = qml.pinf(mec.Q)[mec.kE:mec.kG]
    GAB, GBA = qml.iGs(mec.Q, mec.kA, mec.kB)
    nom = np.dot(pC, (np.dot(mec.QCB, GBA) + mec.QCA))
    denom = np.dot(nom, uA)
    phiB = nom / denom
    return phiB
Esempio n. 10
0
def printout_occupancies(mec, tres):
    """
    """

    str = ('\n\n\n*******************************************\n\n' +
        'Open\tEquilibrium\tMean life\tMean latency (ms)\n' +
        'state\toccupancy\t(ms)\tto next shutting\n' +
        '\t\t\tgiven start in this state\n')

    pinf = qml.pinf(mec.Q)

    for i in range(mec.k):
        if i == 0:
            mean_life_A = ideal_subset_mean_life_time(mec.Q, 1, mec.kA)
            str += ('Subset A ' +
                '\t{0:.5g}'.format(np.sum(pinf[:mec.kA])) +
                '\t{0:.5g}\n'.format(mean_life_A * 1000))
        if i == mec.kA:
            mean_life_B = ideal_subset_mean_life_time(mec.Q, mec.kA + 1, mec.kE)
            str += ('\nShut\tEquilibrium\tMean life\tMean latency (ms)\n' +
                'state\toccupancy\t(ms)\tto next opening\n' +
                '\t\t\tgiven start in this state\n' +
                'Subset B ' +
                '\t{0:.5g}'.format(np.sum(pinf[mec.kA : mec.kE])) +
                '\t{0:.5g}\n'.format(mean_life_B * 1000))
        if i == mec.kE:
            mean_life_C = ideal_subset_mean_life_time(mec.Q, mec.kE + 1, mec.kG)
            str += ('\nSubset C ' +
                '\t{0:.5g}'.format(np.sum(pinf[mec.kE : mec.kG])) +
                '\t{0:.5g}\n'.format(mean_life_C * 1000))
        if i == mec.kG:
            mean_life_D = ideal_subset_mean_life_time(mec.Q, mec.kG + 1, mec.k)
            str += ('\nSubset D ' +
                '\t{0:.5g}'.format(np.sum(pinf[mec.kG : mec.k])) +
                '\t{0:.5g}\n'.format(mean_life_D * 1000))

        mean = ideal_mean_latency_given_start_state(mec, i+1)
        str += ('{0:d}'.format(i+1) +
            '\t{0:.5g}'.format(pinf[i]) +
            '\t{0:.5g}'.format(-1 / mec.Q[i,i] * 1000) +
            '\t{0:.5g}\n'.format(mean * 1000))

    expQFF = qml.expQt(mec.QFF, tres)
    expQAA = qml.expQt(mec.QAA, tres)
    GAF, GFA = qml.iGs(mec.Q, mec.kA, mec.kF)
    eGAF = qml.eGs(GAF, GFA, mec.kA, mec.kF, expQFF)
    eGFA = qml.eGs(GFA, GAF, mec.kF, mec.kA, expQAA)
    phiA = qml.phiHJC(eGAF, eGFA, mec.kA)
    phiF = qml.phiHJC(eGFA, eGAF, mec.kF)

    str += ('\n\nInitial vector for HJC openings phiOp =\n')
    for i in range(phiA.shape[0]):
        str += ('\t{0:.5g}'.format(phiA[i]))
    str += ('\nInitial vector for ideal openings phiOp =\n')
    phiAi = qml.phiA(mec)
    for i in range(phiA.shape[0]):
        str += ('\t{0:.5g}'.format(phiAi[i]))
    str += ('\nInitial vector for HJC shuttings phiSh =\n')
    for i in range(phiF.shape[0]):
        str += ('\t{0:.5g}'.format(phiF[i]))
    str += ('\nInitial vector for ideal shuttings phiSh =\n')
    phiFi = qml.phiF(mec)
    for i in range(phiF.shape[0]):
        str += ('\t{0:.5g}'.format(phiFi[i]))
    str += '\n'
    
    return str
Esempio n. 11
0
def printout(mec, cmax, width, eff='c'):
    """
    """

    #TODO: on/off binding
    #TODO: move some of calculations from here to separate functions
    
    str = ('\n*******************************************\n' +
        'CONCENTRATION JUMPS\n')

    gamma = 30 # Conductance in pS
    Vm = -80e-3 # Transmembrane potential in V.

    mec.set_eff(eff, 0)
    P0 = qml.pinf(mec.Q)
    eigs0, A0 = qml.eigs_sorted(mec.Q)
    str += ('\nEquilibrium occupancies before t=0, at concentration = 0.0:\n')
    for i in range(mec.k):
        str += ('p00({0:d}) = {1:.5g}\n'.format(i+1, P0[i]))

    mec.set_eff(eff, cmax)
    Pinf = qml.pinf(mec.Q)
    eigsInf, Ainf = qml.eigs_sorted(mec.Q)
    w_on = coefficient_calc(mec.k, Ainf, P0)
    str += ('\nEquilibrium occupancies at maximum concentration = {0:.5g} mM:\n'
        .format(cmax * 1000))
    for i in range(mec.k):
        str += ('pinf({0:d}) = '.format(i+1) + '{0:.5g}\n'.format(Pinf[i]))

    Pt = P_t(width, eigsInf, w_on)
    str += ('\nOccupancies at the end of {0:.5g} ms pulse:\n'.
        format(width * 1000))
    for i in range(mec.k):
        str += ('pt({0:d}) = '.format(i+1) + '{0:.5g}\n'.format(Pt[i]))

    tau_on_weighted, tau_on, tau_off_weighted, tau_off = weighted_taus(mec, cmax, width, eff='c')

    str += ('\nON-RELAXATION for ideal step:\n' +
        'Time course for current\n' +
        '\nComp\tEigen\t\tTau (ms)\n')
    for i in range(mec.k-1):
        str += ('{0:d}\t'.format(i+1) +
            '{0:.5g}\t\t'.format(eigsInf[i]) +
            '{0:.5g}\t\n'.format(-1000 / eigsInf[i])) # convert to ms

    ampl_on = np.sum(w_on[:, :mec.kA], axis=1)
    cur_on = ampl_on * gamma * Vm
    max_ampl_on = np.max(np.abs(ampl_on))
    rel_ampl_on = ampl_on / max_ampl_on
    area_on = -cur_on[:-1] / eigsInf[:-1]
    str += ('\nAmpl.(t=0,pA)\tRel.ampl.\t\tArea(pC)\n')
    for i in range(mec.k-1):
        str += ('{0:.5g}\t\t'.format(cur_on[i]) +
            '{0:.5g}\t\t'.format(rel_ampl_on[i]) +
            '{0:.5g}\t\n'.format(area_on[i] * 1000))

    str += ('\nWeighted On Tau (ms) = {0:.5g}\n'.format(tau_on_weighted * 1000))
    str += ('\nTotal current at t=0 (pA) = {0:.5g}\n'.
        format(np.sum(cur_on)))
    str += ('Total current at equilibrium (pA) = {0:.5g}\n'.
        format(cur_on[-1]))
    str += ('Total area (pC) = {0:.5g}\n'.
        format(np.sum(area_on)))
    #TODO: Current at the end of pulse
    ct = cur_on[:-1] * np.exp(width * eigsInf[:-1])
    str += ('Current at the end of {0:.5g}'.format(width
        * 1000) + ' ms pulse = {0:.5g}\n'.format(np.sum(ct) + cur_on[-1]))

    # Calculate off- relaxation.
    str += ('\nOFF-RELAXATION for ideal step:\n' +
        'Time course for current\n' +
        '\nComp\tEigen\t\tTau (ms)\n')
    for i in range(mec.k-1):
        str += ('{0:d}\t'.format(i+1) +
            '{0:.5g}\t\t'.format(eigs0[i]) +
            '{0:.5g}\t\n'.format(-1000 / eigs0[i]))

    w_off = coefficient_calc(mec.k, A0, Pt)
    ampl_off = np.sum(w_off[:, :mec.kA], axis=1)
    cur_off = ampl_off * gamma * Vm
    max_ampl_off = np.max(np.abs(ampl_off))
    rel_ampl_off = ampl_off / max_ampl_off
    area_off = np.zeros((mec.k-1))
    str += ('\nAmpl.(t=0,pA)\tRel.ampl.\t\tArea(pC)\n')
    for i in range(mec.k-1):
        area_off[i] = -1000 * cur_off[i] / eigs0[i]
        str += ('{0:.5g}\t\t'.format(cur_off[i]) +
            '{0:.5g}\t\t'.format(rel_ampl_off[i]) +
            '{0:.5g}\t\n'.format(area_off[i]))
            
    str += ('\nWeighted Off Tau (ms) = {0:.5g}\n'.format(tau_off_weighted * 1000))
    str += ('\nTotal current at t=0 (pA) = {0:.5g}\n'.
        format(np.sum(cur_off)))
    str += ('Total current at equilibrium (pA) = {0:.5g}\n'.
        format(cur_off[-1]))
    str += ('Total area (pC) = {0:.5g}\n'.format(np.sum(area_off)))
 
    return str