Computer Lab – Chemical Kinetics 2
Goal: The purpose of this lab is to compare two- and three-state models of protein folding kinetics using the steady-state approximation
Introduction
This exercise is based on the following paper:
Teilum, K., Maki, K., Kragelund, B. B., Poulsen, F. M., & Roder, H. (2002). Early kinetic intermediate in the folding of acyl-CoA binding protein detected by fluorescence labeling and ultrarapid mixing. Proceedings of the National Academy of Sciences of the United States of America, 99(15), 9807–9812. doi:10.1073/pnas.152321499
import IPython
url = 'https://www.rcsb.org/3d-view/2CB8/1'
iframe = '<iframe src=' + url + ' width=800 height=800></iframe>'
IPython.display.HTML(iframe)
In this work, the folding kinetics of an 86-residue four helix-bundle protein called ACBP (acyl-CoA binding protein) was measured using time-resolved fluorescence spectroscopy (monitoring UV tryptophan fluorescence at 280 nm), after fast dilution from chemical denaturant (guanidinium hydrochloride, GuHCl) in a capillary mixer. The authors find that their data can be fit to the following kinetic model,
$$ U \underset{k_{IU}}{\stackrel{k_{UI}}{\rightleftharpoons}} I \underset{k_{NI}}{\stackrel{k_{IN}}{\rightleftharpoons}} N \tag{1}$$where U is a highly fluorescent unfolded state, I is a partially folded intermediate, and N is the folded state.
Procedure
Modeling the three-state mechanism
Use SimBiology to construct a model of the three-state folding kinetics, using the following kinetic rate parameters determined by the authors at 299 K:
$$ U \underset{k_{IU}= 7000 s^{-1}}{\stackrel{k_{UI} = 11000 s^{-1}}{\rightleftharpoons}} I \underset{k_{NI} = 0.07 s^{-1}}{\stackrel{k_{IN} = 650 s^{-1}}{\rightleftharpoons}} N $$Here is some experimental data that might be helpful in validating your model
Time (ms) | Fluorescence intensity for the U state High concentration = more intensity |
---|---|
0.2 | 1.1 |
0.4 | 1.0 |
0.6 | 0.98 |
0.8 | 0.96 |
1 | 0.91 |
2 | 0.6 |
20 | 0.33 |
40 | 0.32 |
60 | 0.31 |
80 | 0.29 |
Using initial concentrations of [U] = 10.0, [I] = 0.0, and [N] = 10.0, visualize the concentrations of each species over time. Draw or print/plot the results below.
Using the results of your SimBiology model, estimate the populations of U and N at equilibrium.
Estimate from this the equilibrium constant K = [Nequilibrium]/[Uequilibrium] and the free energy of folding.
Modeling the two-state mechanism
Let’s now apply the steady-state approximation to this three-state model. This approximation is a simplification saying that the concentration of the intermediate [I] is constant throughout the reaction. Since the formation of the intermediate is fast compared to the slower, rate-limiting step of folding to the native state N, the steady-state approximation is still fairly accurate.
To find the steady-state approximation, we go through the following steps:
1. Write down an expression for d[I]/dt :
\begin{equation} \frac{d[I]}{dt} = -k_{IU}[I] - k_{IN}[I] + k_{UI}[U] + k_{NI}[I]\tag{1.1} \end{equation}2. Solve $\frac{d[I]}{dt} = 0$ (i.e. steady-state conditions) to get $[I]$ as a function of $[U]$ and $[N]$ :
\begin{align} 0 &= -k_{IU}[I] - k_{IN}[I] + k_{UI}[U] + k_{NI}[N]\\ [I](k_{IU} + k_{IN}) &= k_{UI}[U] + k_{NI}[N]\\ [I] &= (k_{UI}[U] + k_{NI}[N])/(k_{IU} + k_{IN}) \end{align}3. Next, we plug this expression for $[I]$ into the rate laws for $[U]$ and $[N]$:
\begin{align} \frac{d[U]}{dt} &= -k_{UI}[U] + k_{IU}[I]\\ &= -k_{UI}[U] + k_{IU} (k_{UI}[U] + k_{NI}[N])/(k_{IU} + k_{IN}) \tag{1.2}\\ \frac{d[N]}{dt} &= -k_{NI}[N] + k_{IN}[I]\\ &= -k_{NI}[N] + k_{IN} (k_{UI}[U] + k_{NI}[N])/(k_{IU} + k_{IN}) \tag{1.3} \end{align}import numpy as np
import pandas as pd
def ODE_eqs(C, t, k):
r"""See eqs 1.1, 1.2 and 1.3
:math:`U \underset{k_{IU}}{\stackrel{k_{UI}}{\rightleftharpoons}} \
I \underset{k_{NI}}{\stackrel{k_{IN}}{\rightleftharpoons}} N`
Args:
C(list): collection of concentrations for each species [L, R, LR, ...]
t(float): iterate over some time-course
k(list): collection of rate constants [kf1, kb1, kf2, ...]
"""
U, I, N = C[0], C[1], C[2]
kUI, kIU, kIN, kNI = k[0], k[1], k[2], k[3]
dIdt = - kIU*I - kIN*I + kUI*U + kNI*I
dUdt = - kUI*U + kIU*I
dNdt = - kNI*N + kIN*I
return [dUdt, dIdt, dNdt]
def ODE_eqs_SS(C, t, k):
r"""See eqs 1.1, 1.2 and 1.3
:math:`U \underset{k_{IU}}{\stackrel{k_{UI}}{\rightleftharpoons}} \
I \underset{k_{NI}}{\stackrel{k_{IN}}{\rightleftharpoons}} N`
Args:
C(list): collection of concentrations for each species [L, R, LR, ...]
t(float): iterate over some time-course
k(list): collection of rate constants [kf1, kb1, kf2, ...]
"""
U, I, N = C[0], C[1], C[2]
kUI, kIU, kIN, kNI = k[0], k[1], k[2], k[3]
dIdt = - kIU*I - kIN*I + kUI*U + kNI*I
dUdt = - kUI*U + kIU*(kUI*U+kNI*N)/(kIU+kIN)
dNdt = - kNI*N + kIN*(kUI*U+kNI*N)/kIU+kIN
return [dUdt, dIdt, dNdt]
def simulate(steps, simulation_time, parameters, rate_eqs):
"""Method for integrating the ODEs with SciPy odeint
https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html
Args:
steps(int): number of iterations
simulation_time(int): duration of simulation (units: s)
parameters(dict): {"species": ["L", "R", "LR"],\
"k": [kf1, kb1, kf2, kb2, ...],\ # rate constants
"InitConc": [L, R, P, ...]} # initial concentrations (units: M)
rate_eqs(function): method containing the ordinary differential equations
Returns:
Pandas DataFrame, plot
"""
from scipy.integrate import odeint
print(f"Number of species: {len(parameters['InitConc'])}")
time = np.linspace(0, simulation_time, steps)
C = odeint(rate_eqs, parameters["InitConc"], time, (parameters["k"],)).transpose()
data = {"time": time, **{"%s"%s: C[i] for i,s in enumerate(parameters["species"])}}
df = pd.DataFrame(data)
plot = df.plot(x="time", y=parameters["species"], figsize=(10, 4),
xlim=(data["time"][0], data["time"][-1]))
return df,plot
def dG(parameters, df):
"""Print ∆G = -RTln(K) for model and 'equilibrium' concentrations
Args:
parameters(dict): {"species": ["L", "R", "LR"],\
"k": [kf1, kb1, kf2, kb2, ...],\ # rate constants
"InitConc": [L, R, P, ...]} # initial concentrations (units: M)
df(DataFrame): pandas DataFrame of simulation
"""
R, T = 8.314, 299 #units: Jmmol^-1K^-1 , units: K
print("\nFrom equilibrium concentrations:")
U = df["U"][df.index[-1]]
N = df["N"][df.index[-1]]
K = N/U
dG = -R*T*np.log(K)
print(f"K = {N: 0.3g}/{U: 0.3g} = {K: 0.3g}")
print(f"∆G = -RTln(K) = {dG/1000: 0.3g} kJ mol^-1")
print("\nFrom model parameters:")
kUI = parameters["k"][0]
kIU = parameters["k"][1]
kIN = parameters["k"][2]
kNI = parameters["k"][3]
kf = kIN*(kUI/(kIU+kIN))
kb = kNI*(kIU/(kIU+kIN))
K = kf/kb
dG = -R*T*np.log(K)
print(f"k_forward = {kf: 0.3g} s^-1")
print(f"k_backward = {kb: 0.3g} s^-1")
print(f"K = {K: 0.3g}")
print(f"∆G = -RTln(K) = {dG/1000: 0.3g} kJ mol^-1")
def get_subset(df, index):
return pd.DataFrame(df.loc[index, df.columns])
# U = I = N
#[U] = 10.0, [I] = 0.0, and [N] = 10.0,
"""
k𝑈𝐼=11000𝑠−1, k𝐼𝑁=650𝑠−1
k𝐼𝑈=7000𝑠−1, k𝑁𝐼=0.07𝑠−1
"""
parameters = {"species": ["U", "I", "N", ],
"InitConc": [10.0, 0.0, 10.0, ],
# [kf1, kb1, kf2, ...]
"k": [11000.0, 7000.0, 650.0, 0.07]}
df,plot = simulate(steps=10000, simulation_time=0.009,#simulation_time=0.005,
parameters=parameters, rate_eqs=ODE_eqs)
plot = plot.set_title(r"$L \rightleftharpoons I \rightleftharpoons N$")
fig = plot.get_figure()
#fig.savefig("figure.png")
df
# Find where the first derivative is zero
#print(f'd[I]/dt = 0 @ t = {df["time"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} s')
#print(f'[I] = {df["I"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} M')
#print(f'[U] = {df["U"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} M')
#print(f'[N] = {df["N"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} M')
#sub = get_subset(df, index=range(0,800))
#sub.plot(x="time",figsize=(10, 4))
#sub
# Stead State Approximation
parameters = {"species": ["U", "I", "N", ],
"InitConc": [10.0, 0.0, 10.0, ],
# [kf1, kb1, kf2, ...]
"k": [11000.0, 7000.0, 650.0, 0.07]}
df,plot = simulate(steps=10000, simulation_time=0.005,
parameters=parameters, rate_eqs=ODE_eqs_SS)
plot = plot.set_title(r"""Steady State
$L \rightleftharpoons I \rightleftharpoons N$""")
fig = plot.get_figure()
#fig.savefig("figure.png")
df
4. Finally, to get rates for a two-state $U\rightleftharpoons N$ model of folding, consider that at equilibrium, $\frac{d[U]}{dt} = \frac{d[N]}{dt} = 0$. Set the two expressions for $\frac{d[U]}{dt}$ and $\frac{d[N]}{dt}$ above to be equal to each other, and rearrange the equation to get it in the following form:
$$k_{forward} [U] = k_{backward}[N]$$What are your computed values of for $k_{forward}$ and $k_{backward}$? (Hint: They should be close to the values of $k_{IN}$ and $k_{NI}$, since $I \to N$ is the rate-limiting step.)
Estimate from $k_{forward}$ and $k_{backward}$ the equilibrium constant ($K = k_{f}/k_{b}$) and free energy of folding.
NOTE: it takes some simplification to get this
2-state mechanism
$$K = \frac{k_{f}}{k_{b}} = \frac{[N]}{[U]} $$$$\Delta G = -RT ln(K)$$$$k_{forward} = k_{IN} \left(\frac{k_{UI}}{k_{IU} + k_{IN}} \right) = 650(11000/(7000+650)) = 935 s^{-1}$$$$k_{backward} = k_{NI} \left(\frac{k_{IU}}{k_{IU} + k_{IN}}\right) = 0.07(7000/(7000+650)) = 0.064 s^{-1}$$Estimate: $K = 635/0.064 = 14609$
$$\Delta G = -RT ln(K) = -8.314 J.mol^{-1}.K^{-1} (299 K)(ln(2.63))\frac{1kJ}{1000 J} = -24 kJ.mol^{-1} $$## Find where the first derivative is zero
#print(f'd[I]/dt = 0 @ t = {df["time"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} s')
#print(f'd[I]/dt = 0 @ [I] = {df["I"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} M')
#print(f'd[I]/dt = 0 @ [U] = {df["U"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} M')
#print(f'd[I]/dt = 0 @ [N] = {df["N"][df["I"][np.where(np.diff(df["I"]) <= 0.0)[0]].index[0]]: 0.3g} M')
dG(parameters, df)
# Stead State Approximation
parameters = {"species": ["U", "I", "N", ],
"InitConc": [10.0, 0.0, 10.0, ],
# [kf1, kb1, kf2, ...]
"k": [11000.0, 7000.0, 650.0, 0.07]}
df,plot = simulate(steps=10000, simulation_time=0.04,#0.029,
parameters=parameters, rate_eqs=ODE_eqs_SS)
plot = plot.set_title(r"""Steady State
$L \rightleftharpoons I \rightleftharpoons N$""")
fig = plot.get_figure()
#fig.savefig("figure.png")
df
dG(parameters, df)