binding-kinetics / monomer_dimer_ribosome.py
Jhsmit's picture
add mdr version 1
2080501
raw
history blame
4.49 kB
# %%
import numpy as np
import sympy as sp
from scipy.optimize import root_scalar
import ultraplot as uplt
from smitfit.symbol import Symbols
from smitfit.model import Model
import polars as pl
# %%
s = Symbols("TF1, TF2, TFR, R, T_TF, T_R, kD_MD, kD_MR", positive=True)
# %%
mb_ribosome = s.TFR + s.R - s.T_R # type: ignore
mb_TF = s.TF1 + 2 * s.TF2 + s.TFR - s.T_TF # type: ignore
eq_MD = s.TF1**2 - s.kD_MD * s.TF2 # type: ignore
eq_MR = (s.TF1 * s.R) - s.kD_MR * s.TFR # type: ignore
#
knowns = ["T_TF", "T_R", "kD_MD", "kD_MR"]
# solve for: TF1
# take Monomer-dimer equillibrium, put it in mass balance TF to eliminate TF2
sub_TF2 = (s.TF2, sp.solve(eq_MD, s.TF2)[0])
# same for monomer dimer, eliminate TF_R
sub_mb = (s.R, sp.solve(mb_ribosome, s.R)[0])
sub_TFR = (s.TFR, sp.solve(eq_MR.subs(*sub_mb), s.TFR)[0])
# we know have an expr to find free TF monomer
eq_TF1 = mb_TF.subs([sub_TF2, sub_TFR])
eq_TF1
# %%
d = {
s.TF2: sp.solve(eq_MD, s.TF2)[0],
s.TFR: sp.solve(mb_TF, s.TFR)[0],
s.R: sp.solve(mb_ribosome, s.R)[0],
}
m = Model(d)
# %%
ld = sp.lambdify([s.TF1] + [s[k] for k in knowns], eq_TF1)
# %%
def solve_system(params: dict) -> dict:
args = tuple(params[k] for k in knowns)
# root find TF1
sol = root_scalar(ld, bracket=(0, params["T_TF"]), args=args)
# calculate the others
ans = m(**params, TF1=sol.root)
return {"TF1": sol.root, **ans}
def make_df(records: list[dict]) -> pl.DataFrame:
df = pl.DataFrame(records)
cols = [
(pl.col("TF1") + pl.col("TF2") + pl.col("TFR")).alias("total TF"),
(pl.col("TFR") + pl.col("R")).alias("total R"),
]
df = df.with_columns(cols)
return df
# %%
# The concentration of TF exceeds that of ribosomes (∼50 μM and ∼30 μM, respectively)[12,13]
# TF binds free ribosomal 50S subunits with a Kd of ∼1 μM
# Purified TF forms dimers with a Kd of 1–2 μM (ref. 14).
# " Real-time observation of trigger factor function on translating ribosomes", https://doi.org/10.1038/nature05225
# "the cytosol contains 2.6 moles of trigger factor per mole of ribosomes. "
# The “trigger factor cycle” includes ribosomes, presecretory proteins, and the plasma membrane
#
ecoli_params = {
"T_TF": 50,
"T_R": 30,
"kD_MD": 1,
"kD_MR": 2,
}
solve_system(ecoli_params)
# %%
vmin, vmax = 1e-6, 1000e-6
total_tf_protomer = np.logspace(
0, 4, endpoint=True, num=100
) # total TF protomer from 1 uM to 1
input_params = [ecoli_params | {"T_TF": v} for v in total_tf_protomer]
input_params
# %%
output_records = [solve_system(params) for params in input_params]
df = make_df(output_records)
# %%
species = ["TF1", "TF2", "TFR"]
cycle = iter(uplt.Cycle("default"))
fig, axes = uplt.subplots(nrows=2, aspect=2.5, axwidth="120mm")
for s in species:
axes[0].plot(
total_tf_protomer,
df.select(pl.col(s) / pl.col("total TF")),
label=s,
**next(cycle),
)
axes[0].format(title="TF")
species = ["TFR", "R"]
for s in species:
axes[1].plot(
total_tf_protomer,
df.select(pl.col(s) / pl.col("total R")),
label=s,
**next(cycle),
)
axes[1].format(title="ribosome")
axes.format(
ylim=(0, 1),
xscale="log",
xformatter="sci",
ylabel="Fractional population",
xlabel="Total protomer TF (uM)",
)
axes.legend(loc="r", ncols=1)
# %%
# lets repeat for ribosome titration, fixed 100 nM TF protomer concentration
microscopy_params = {
"T_TF": 1, # 100 nM
"kD_MD": 1,
"kD_MR": 1,
}
# %%
total_ribosome = np.linspace(0, 5, endpoint=True)
input_params = [microscopy_params | {"T_R": v} for v in total_ribosome]
# %%
output_records = [solve_system(params) for params in input_params]
df = make_df(output_records)
# %%
species = ["TF1", "TF2", "TFR"]
cycle = iter(uplt.Cycle("default"))
fig, axes = uplt.subplots(nrows=2, aspect=2.5, axwidth="120mm")
for s in species:
axes[0].plot(
total_ribosome,
df.select(pl.col(s) / pl.col("total TF")),
label=s,
**next(cycle),
)
axes[0].format(title="TF")
species = ["TFR", "R"]
for s in species:
axes[1].plot(
total_ribosome,
df.select(pl.col(s) / pl.col("total R")),
label=s,
**next(cycle),
)
axes[1].format(title="ribosome")
axes.format(
ylim=(0, 1),
# xscale="log",
xformatter="sci",
ylabel="Fractional population",
xlabel="Total protomer TF (uM)",
)
axes.legend(loc="r", ncols=1)
# %%