Linear Regression Plot
Antibody Neutralization Kinetics
Immunology dose-response with EC50 marker and sigmoid fit
Output
Python
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(789)
# Dose-response data
log_conc = np.linspace(-2, 3, 50)
conc = 10**log_conc
ec50 = 10 # EC50 value
hill = 1.2
response = 100 / (1 + (ec50/conc)**hill) + np.random.normal(0, 4, 50)
response = np.clip(response, 0, 100)
# Fit curve
x_smooth = np.linspace(-2, 3, 200)
conc_smooth = 10**x_smooth
y_smooth = 100 / (1 + (ec50/conc_smooth)**hill)
fig, ax = plt.subplots(figsize=(10, 7), facecolor='#0a0a0f')
ax.set_facecolor('#0a0a0f')
# Confidence band
ax.fill_between(x_smooth, y_smooth - 8, y_smooth + 8, color='#5314E6', alpha=0.15, linewidth=0)
ax.plot(x_smooth, y_smooth, color='#5314E6', linewidth=2.5, zorder=3)
ax.scatter(log_conc, response, c='#F5D327', s=65, alpha=0.85, edgecolors='white', linewidths=0.4, zorder=4)
# EC50 marker
ax.axvline(x=np.log10(ec50), color='#F5276C', linestyle='--', linewidth=1.5, alpha=0.7)
ax.axhline(y=50, color='#F5276C', linestyle='--', linewidth=1.5, alpha=0.7)
ax.scatter([np.log10(ec50)], [50], c='#F5276C', s=100, marker='o', zorder=5, edgecolors='white', linewidths=2)
ax.text(np.log10(ec50) + 0.15, 53, f'EC₅₀ = {ec50} nM', fontsize=10, color='#F5276C')
for spine in ['top', 'right']:
ax.spines[spine].set_visible(False)
for spine in ['bottom', 'left']:
ax.spines[spine].set_color('#333333')
ax.set_xlabel('Log₁₀ Concentration (nM)', fontsize=12, color='white', fontweight='500', labelpad=10)
ax.set_ylabel('Neutralization (%)', fontsize=12, color='white', fontweight='500', labelpad=10)
ax.set_title('Antibody Dose-Response', fontsize=15, color='white', fontweight='bold', pad=20, loc='left')
ax.tick_params(colors='#666666', labelsize=10, length=0)
plt.tight_layout()
plt.show()
Library
Matplotlib
Category
Pairwise Data
More Linear Regression Plot examples
☕