In [3]:
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
%pylab inline
Here we are using the same setup as 'Simulating Experimental Fluorescence Binding Data'.
In [4]:
# Now we can use this to define a function that gives us PL from Kd, Ptot, and Ltot.
def two_component_binding(Kd, Ptot, Ltot):
"""
Parameters
----------
Kd : float
Dissociation constant
Ptot : float
Total protein concentration
Ltot : float
Total ligand concentration
Returns
-------
P : float
Free protein concentration
L : float
Free ligand concentration
PL : float
Complex concentration
"""
PL = 0.5 * ((Ptot + Ltot + Kd) - np.sqrt((Ptot + Ltot + Kd)**2 - 4*Ptot*Ltot)) # complex concentration (uM)
P = Ptot - PL; # free protein concentration in sample cell after n injections (uM)
L = Ltot - PL; # free ligand concentration in sample cell after n injections (uM)
return [P, L, PL]
Let's say we have four ligands with 0.1, 1, 10, and 100 nM binding affinities.
In [5]:
Kd_high = 0.1e-9 # M
Kd_mid_high = 1e-9 # M
Kd_mid_low = 10e-9 # M
Kd_low = 100e-9 # M
In this case we will define our protein concentration as higher than the Kd of our lowest affinity ligand.
In [6]:
Ptot = 500e-9 # M
We will define the ligand concentration as previously done. (Half log dilution from 20 uM.)
In [8]:
Ltot = 20.0e-6 / np.array([10**(float(i)/2.0) for i in range(12)]) # M
In [10]:
[L, P, PL] = two_component_binding(Kd_low, Ptot, Ltot)
In [12]:
# y will be complex concentration
# x will be total ligand concentration
plt.semilogx(Ltot, PL, 'ko')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]$')
plt.ylim(0, 1.05*np.max(PL))
plt.axvline(Kd_low,color='r',linestyle='--',label='K_d')
plt.legend(loc=0);
In [13]:
[L_high, P_high, PL_high] = two_component_binding(Kd_high, Ptot, Ltot)
[L_mid_high, P_mid_high, PL_mid_high] = two_component_binding(Kd_mid_high, Ptot, Ltot)
[L_mid_low, P_mid_low, PL_mid_low] = two_component_binding(Kd_mid_low, Ptot, Ltot)
[L_low, P_low, PL_low] = two_component_binding(Kd_low, Ptot, Ltot)
In [15]:
plt.semilogx(Ltot, PL_high, 'bo',label = 'high')
plt.semilogx(Ltot, PL_mid_high, 'ro',label = 'mid_high')
plt.semilogx(Ltot, PL_mid_low, 'go',label = 'mid_low')
plt.semilogx(Ltot, PL_low, 'ko',label = 'low')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]$')
plt.ylim(0, 1.05*np.max(PL))
plt.legend(loc=0);
In [17]:
plt.semilogx(Ltot, PL_high, 'bo',label = 'high')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]$')
plt.ylim(0, 1.05*np.max(PL))
plt.axvline(Kd_high,color='r',linestyle='--',label='K_d')
plt.legend(loc=0);
Hmm. Let's see if varying our protein concentration for our high affinity ligand so that it's closer to our Kd can give us better fluorescence data.
In [19]:
#Our high affinity ligand has an affinity of 0.1e-9 # M
Ptot_dilute = 0.5e-9 # M
Ptot_mid_dilute = 5e-9 # M
Ptot_mid_conc = 50e-9 # M
Ptot_conc = 500e-9 # M
In [20]:
[L_dilute, P_dilute, PL_dilute] = two_component_binding(Kd_high, Ptot_dilute, Ltot)
[L_mid_dilute, P_mid_dilute, PL_mid_dilute] = two_component_binding(Kd_high, Ptot_mid_dilute, Ltot)
[L_mid_conc, P_mid_conc, PL_mid_conc] = two_component_binding(Kd_high, Ptot_mid_conc, Ltot)
[L_conc, P_conc, PL_conc] = two_component_binding(Kd_high, Ptot_conc, Ltot)
In [21]:
plt.semilogx(Ltot, PL_dilute, 'bo',label = 'dilute')
plt.semilogx(Ltot, PL_mid_dilute, 'ro',label = 'mid_dilute')
plt.semilogx(Ltot, PL_mid_conc, 'go',label = 'mid_conc')
plt.semilogx(Ltot, PL_conc, 'ko',label = 'conc')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]$')
plt.ylim(0, 1.05*np.max(PL))
plt.legend(loc=0);
In [29]:
#This will be easier to see if we do fraction bound
plt.semilogx(Ltot, PL_dilute/Ptot_dilute, 'bo',label = 'dilute')
plt.semilogx(Ltot, PL_mid_dilute/Ptot_mid_dilute, 'ro',label = 'mid_dilute')
plt.semilogx(Ltot, PL_mid_conc/Ptot_mid_conc, 'go',label = 'mid_conc')
plt.semilogx(Ltot, PL_conc/Ptot_conc, 'ko',label = 'conc')
plt.axvline(Kd_high,color='0.3',linestyle='--',label='K_d')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]/[P_tot]$')
plt.ylim(0, 1.05)
plt.legend(loc=0);
Let's see how well this helps us discern between our 'high' and 'mid_high' affinity ligands.
In [30]:
[L_dilute_mid_high, P_dilute_mid_high, PL_dilute_mid_high] = two_component_binding(Kd_mid_high, Ptot_dilute, Ltot)
[L_mid_dilute_mid_high, P_mid_dilute_mid_high, PL_mid_dilute_mid_high] = two_component_binding(Kd_mid_high, Ptot_mid_dilute, Ltot)
[L_mid_con_mid_highc, P_mid_conc_mid_high, PL_mid_conc_mid_high] = two_component_binding(Kd_mid_high, Ptot_mid_conc, Ltot)
[L_conc_mid_high, P_conc_mid_high, PL_conc_mid_high] = two_component_binding(Kd_mid_high, Ptot_conc, Ltot)
In [ ]:
Ptot_dilute = 0.5e-9 # M
Ptot_mid_dilute = 5e-9 # M
Ptot_mid_conc = 50e-9 # M
Ptot_conc = 500e-9 # M
In [46]:
plt.figure(figsize=(12,8));
sns.set(style='white')
sns.set_context('talk')
plt.subplot(221)
plt.semilogx(Ltot, PL_dilute/Ptot_dilute, 'bo',label = 'dilute')
plt.semilogx(Ltot, PL_dilute_mid_high/Ptot_dilute, 'bo',alpha=0.3,label = 'dilute mid_high')
plt.axvline(Kd_high,color='0.3',linestyle='--',label='K_d = 0.1 nM')
plt.axvline(Kd_mid_high,color='0.7',linestyle='--',label='K_d = 1.0 nM')
plt.title('$[Ptot] = 0.5 nM$')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]/[P_tot]$')
plt.ylim(0, 1.05)
plt.legend(loc=0,frameon=True);
plt.subplot(222)
plt.semilogx(Ltot, PL_mid_dilute/Ptot_mid_dilute, 'ro')
plt.semilogx(Ltot, PL_mid_dilute_mid_high/Ptot_mid_dilute, 'ro',alpha=0.3)
plt.axvline(Kd_high,color='0.3',linestyle='--',label='K_d = 0.1 nM')
plt.axvline(Kd_mid_high,color='0.7',linestyle='--',label='K_d = 1.0 nM')
plt.title('$[Ptot] = 5 nM$')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]/[P_tot]$')
plt.ylim(0, 1.05)
plt.legend(loc=0,frameon=True);
plt.subplot(223)
plt.semilogx(Ltot, PL_mid_conc/Ptot_mid_conc, 'go')
plt.semilogx(Ltot, PL_mid_conc_mid_high/Ptot_mid_conc, 'go',alpha=0.3)
plt.axvline(Kd_high,color='0.3',linestyle='--',label='K_d = 0.1 nM')
plt.axvline(Kd_mid_high,color='0.7',linestyle='--',label='K_d = 1.0 nM')
plt.title('$[Ptot] = 50 nM$')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]/[P_tot]$')
plt.ylim(0, 1.05)
plt.legend(loc=0,frameon=True);
plt.subplot(224)
plt.semilogx(Ltot, PL_conc/Ptot_conc, 'ko')
plt.semilogx(Ltot, PL_conc_mid_high/Ptot_conc, 'ko',alpha=0.3)
plt.axvline(Kd_high,color='0.3',linestyle='--',label='K_d = 0.1 nM')
plt.axvline(Kd_mid_high,color='0.7',linestyle='--',label='K_d = 1.0 nM')
plt.title('$[Ptot] = 500 nM$')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]/[P_tot]$')
plt.ylim(0, 1.05)
plt.legend(loc=0,frameon=True);
plt.tight_layout();
"As long as the affinity is much tighter than the concentration of macromolecule your binding curve will look similar to this hypothetical extreme case, and you will only be able to place a lower bound on the affinity." - Nick Levinson
There you go!
In [48]:
#Our other question here, is whether our molar fluorescence for our complex
# will allow is to go to this low of a concentration.
In [54]:
plt.figure(figsize=(12,4));
plt.subplot(121)
plt.semilogx(Ltot, PL_dilute, 'bo',label = 'dilute')
plt.semilogx(Ltot, PL_mid_dilute, 'ro',label = 'mid_dilute')
plt.semilogx(Ltot, PL_mid_conc, 'go',label = 'mid_conc')
plt.semilogx(Ltot, PL_conc, 'ko',label = 'conc \n max=%s'%np.max(PL_conc))
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]$')
plt.ylim(0, 1.05*np.max(PL_conc))
plt.legend(loc=0);
plt.subplot(122)
plt.semilogx(Ltot, PL_dilute, 'bo',label = 'dilute \n max=%s' %np.max(PL_dilute))
plt.semilogx(Ltot, PL_mid_dilute, 'ro',label = 'mid_dilute')
plt.semilogx(Ltot, PL_mid_conc, 'go',label = 'mid_conc')
plt.semilogx(Ltot, PL_conc, 'ko',label = 'conc')
plt.xlabel('$[L]_{tot}$ / M')
plt.ylabel('$[PL]$')
plt.ylim(0, 1.05*np.max(PL_dilute))
plt.legend(loc=0);
In [ ]: