Kinetics Applications¶
Curve fitting for enzyme kinetics, binding, and chemical reactions.
Enzyme Kinetics¶
Michaelis-Menten¶
import jax.numpy as jnp
from nlsq import fit
def michaelis_menten(S, Vmax, Km):
"""Michaelis-Menten enzyme kinetics."""
return Vmax * S / (Km + S)
# Fit
popt, pcov = fit(
michaelis_menten,
substrate_conc,
velocity,
p0=[100, 10],
bounds=([0, 0], [1000, 1000]),
)
Hill Equation¶
def hill_equation(S, Vmax, K, n):
"""Hill equation (cooperative binding)."""
return Vmax * S**n / (K**n + S**n)
Substrate Inhibition¶
def substrate_inhibition(S, Vmax, Km, Ki):
"""Substrate inhibition model."""
return Vmax * S / (Km + S * (1 + S / Ki))
Binding Isotherms¶
Langmuir Isotherm¶
def langmuir(C, Qmax, Kd):
"""Langmuir binding isotherm."""
return Qmax * C / (Kd + C)
Two-Site Langmuir¶
def two_site_langmuir(C, Q1, K1, Q2, K2):
"""Two-site Langmuir (heterogeneous binding)."""
return Q1 * C / (K1 + C) + Q2 * C / (K2 + C)
Freundlich Isotherm¶
def freundlich(C, Kf, n):
"""Freundlich isotherm (heterogeneous surfaces)."""
return Kf * C ** (1 / n)
Dose-Response¶
4-Parameter Logistic¶
def four_parameter_logistic(x, bottom, top, EC50, hill):
"""4PL dose-response curve."""
return bottom + (top - bottom) / (1 + (EC50 / x) ** hill)
# IC50/EC50 determination
popt, pcov = fit(
four_parameter_logistic,
dose,
response,
p0=[0, 100, 10, 1],
bounds=([0, 0, 0.001, 0.1], [50, 200, 1000, 10]),
preset="quality",
)
5-Parameter Logistic¶
def five_parameter_logistic(x, bottom, top, EC50, hill, asymmetry):
"""5PL asymmetric dose-response."""
return bottom + (top - bottom) / (1 + (EC50 / x) ** hill) ** asymmetry
Chemical Kinetics¶
First-Order Decay¶
def first_order(t, A0, k, offset):
"""First-order reaction: A → products."""
return A0 * jnp.exp(-k * t) + offset
Second-Order Kinetics¶
def second_order_equal(t, A0, k):
"""Second-order reaction with equal concentrations."""
return A0 / (1 + k * A0 * t)
Consecutive Reactions¶
def consecutive_reactions(t, A0, k1, k2):
"""A → B → C consecutive first-order reactions.
Returns concentration of B."""
return A0 * k1 / (k2 - k1) * (jnp.exp(-k1 * t) - jnp.exp(-k2 * t))
Tips for Kinetics Fitting¶
Transform for linear analysis first:
Lineweaver-Burk, Eadie-Hofstee for enzymes
Linear plots help estimate initial guesses
Use weighted fitting when variance changes with concentration:
sigma = np.sqrt(response) # Poisson-like errors popt, pcov = fit(model, x, y, sigma=sigma, absolute_sigma=True)
Report with proper statistics:
95% confidence intervals
R² and RMSE
Residual analysis
For competitive models, compare with AIC/BIC:
result1 = fit(michaelis_menten, S, v) result2 = fit(substrate_inhibition, S, v) print(f"MM: AIC={result1.aic:.2f}") print(f"SI: AIC={result2.aic:.2f}")
See Also¶
How to Choose a Model Function - Model selection
Understanding Results - Result interpretation