Area Chart
Dose-Response Curve
Sigmoidal dose-response with EC50 - R style
Output
Python
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
dose = np.logspace(-2, 2, 100)
# 4-parameter log-logistic
def ll4(x, b, c, d, e):
return c + (d - c) / (1 + (x / e) ** b)
# Parameters
b, c, d, e = 1.5, 0, 100, 1.0 # EC50 = 1.0
response = ll4(dose, b, c, d, e)
se = 5 + 3 * np.sin(np.log10(dose) * 2)
fig, ax = plt.subplots(figsize=(10, 6), facecolor='#0a0a0f')
ax.set_facecolor('#0a0a0f')
ax.fill_between(dose, response - 1.96*se, response + 1.96*se, alpha=0.25, color='#6CF527')
ax.plot(dose, response, color='#6CF527', linewidth=2.5, label='Fitted curve')
# Data points
x_data = np.logspace(-1.5, 1.5, 12)
y_data = ll4(x_data, b, c, d, e) + np.random.normal(0, 5, len(x_data))
ax.scatter(x_data, y_data, color='#F5276C', s=60, zorder=5, edgecolors='white', linewidth=1)
# EC50 line
ax.axhline(50, color='#27D3F5', linewidth=1, linestyle=':', alpha=0.7)
ax.axvline(e, color='#27D3F5', linewidth=1, linestyle=':', alpha=0.7)
ax.scatter([e], [50], color='#27D3F5', s=100, zorder=6, marker='s', edgecolors='white')
ax.annotate(f'EC50 = {e}', (e, 50), xytext=(10, 10), textcoords='offset points',
color='#27D3F5', fontsize=10, fontweight='bold')
ax.set_xscale('log')
ax.set_xlabel('Dose (log scale)', color='white', fontsize=11, fontweight='500')
ax.set_ylabel('Response (%)', color='white', fontsize=11, fontweight='500')
ax.set_title('Dose-Response Curve (4PL Model)', color='white', fontsize=13, fontweight='600', pad=15)
ax.tick_params(colors='#888888', labelsize=9)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_color('#333333')
ax.spines['bottom'].set_color('#333333')
ax.yaxis.grid(True, color='#1a1a2e', linewidth=0.5)
ax.set_ylim(-10, 115)
ax.legend(facecolor='#0a0a0f', edgecolor='#333333', labelcolor='white')
plt.tight_layout()
plt.show()
Library
Matplotlib
Category
Basic Charts
More Area Chart examples
☕