codexpast-exam-of-the-systems-biology-course-of-the-university-of-cambridge2024paper-3-feed-forward.py
past-exam-of-the-systems-biology-course-of-the-university-of-cambridge/2024/paper-3-feed-forward.py
"""AND feed-forward dynamics and equilibria; Python 3.14/matplotlib 3.10.7.
Write paper-3-feed-forward.png to the current working directory.
"""
from pathlib import Path
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
def hill(u, K, n):
u = np.asarray(u)
return u**n/(K**n+u**n)
def rhs(s, X):
Y,Z = s
return np.array([2*hill(X,1,2)-Y, 3*hill(X,2,4)*hill(Y,1,4)-Z])
def integrate(X, times):
out=np.zeros((len(times),2))
for j,dt in enumerate(np.diff(times)):
s=out[j]
k1=rhs(s,X);k2=rhs(s+dt*k1/2,X)
k3=rhs(s+dt*k2/2,X);k4=rhs(s+dt*k3,X)
out[j+1]=s+dt*(k1+2*k2+2*k3+k4)/6
return out
def equilibrium(X, Kxy=1, Kxz=2, Kyz=1):
Y=2*hill(X,Kxy,2)
return 3*hill(X,Kxz,4)*hill(Y,Kyz,4)
def main():
plt.rcParams.update({'font.size':10,'figure.facecolor':'white'})
fig,axes=plt.subplots(1,2,figsize=(10,3.8),constrained_layout=True)
t=np.linspace(0,10,1001)
for X,color in [(1,'#176b9c'),(3,'#c05526')]:
out=integrate(X,t)
axes[0].plot(t,out[:,0],'--',color=color,label=f'Y, X={X}')
axes[0].plot(t,out[:,1],color=color,label=f'Z, X={X}')
axes[0].set(xlabel='Time',ylabel='Concentration',title='AND regulation, initial Y=Z=0')
axes[0].legend(fontsize=8)
X=np.linspace(0,5,501)
axes[1].plot(X,3*hill(X,2,4),':',color='black',label='Direct activation only')
for pars,label,color in [((1,2,1),'Baseline','#176b9c'),((2,2,1),'Raise Kxy to 2','#c05526'),((1,3,1),'Raise Kxz to 3','#57883a'),((1,2,2),'Raise Kyz to 2','#8c5197')]:
axes[1].plot(X,equilibrium(X,*pars),color=color,label=label)
axes[1].set(xlabel='Input concentration X',ylabel='Equilibrium Z',title='An additional gate lowers the response')
axes[1].legend(fontsize=8)
for ax in axes:
ax.grid(alpha=.18);ax.set_ylim(bottom=0)
fig.savefig(Path('paper-3-feed-forward.png'),dpi=125,facecolor='white')
plt.close(fig)
if __name__=='__main__':
main()