def ideal_dwell_time_pdf_components(QAA, phiA): """ Calculate time constants and areas for an ideal (no missed events) exponential open time probability density function. For shut time pdf A by F in function call. Parameters ---------- t : float Time (sec). QAA : array_like, shape (kA, kA) Submatrix of Q. phiA : array_like, shape (1, kA) Initial vector for openings Returns ------- taus : ndarray, shape(k, 1) Time constants. areas : ndarray, shape(k, 1) Component relative areas. """ kA = QAA.shape[0] w = np.zeros(kA) eigs, A = qml.eigs_sorted(-QAA) uA = np.ones((kA, 1)) #TODO: remove 'for' for i in range(kA): w[i] = np.dot(np.dot(np.dot(phiA, A[i]), (-QAA)), uA) return eigs, w
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
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
def exact_GAMAxx(mec, tres, open): """ Calculate gama coeficients for the exact open time pdf (Eq. 3.22, HJC90). Parameters ---------- tres : float mec : dcpyps.Mechanism The mechanism to be analysed. open : bool True for open time pdf and False for shut time pdf. Returns ------- eigen : ndarray, shape (k,) Eigenvalues of -Q matrix. gama00, gama10, gama11 : ndarrays Constants for the exact open/shut time pdf. """ expQFF = qml.expQt(mec.QII, tres) expQAA = qml.expQt(mec.QAA, tres) GAF, GFA = qml.iGs(mec.Q, mec.kA, mec.kI) eGAF = qml.eGs(GAF, GFA, mec.kA, mec.kI, expQFF) eGFA = qml.eGs(GFA, GAF, mec.kI, mec.kA, expQAA) eigs, A = qml.eigs_sorted(-mec.Q) if open: phi = qml.phiHJC(eGAF, eGFA, mec.kA) eigen, Z00, Z10, Z11 = qml.Zxx(mec.Q, eigs, A, mec.kA, mec.QII, mec.QAI, mec.QIA, expQFF, open) u = np.ones((mec.kI,1)) else: phi = qml.phiHJC(eGFA, eGAF, mec.kI) eigen, Z00, Z10, Z11 = qml.Zxx(mec.Q, eigs, A, mec.kA, mec.QAA, mec.QIA, mec.QAI, expQAA, open) u = np.ones((mec.kA, 1)) gama00 = (np.dot(np.dot(phi, Z00), u)).T[0] gama10 = (np.dot(np.dot(phi, Z10), u)).T[0] gama11 = (np.dot(np.dot(phi, Z11), u)).T[0] return eigen, gama00, gama10, gama11
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