import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.patches import Patch
import numpy as np
from scipy.interpolate import PchipInterpolator
# 1. Original Data (Repeated Dose Toxicity)
bins_rdt = np.array([0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00])
freq_rdt = np.array([0.08, 1.91, 3.78, 2.42, 2.17, 3.10, 2.51, 2.93, 3.57, 4.25, 5.01, 5.73, 6.67, 6.62, 8.45, 9.13, 11.00, 13.46, 7.22, 0.00])
# 2. Dynamic Statistical Calculations
mean_val = np.average(bins_rdt, weights=freq_rdt)
# PCHIP Interpolation (Empirical Trend)
x_interp = np.insert(bins_rdt, 0, 0)
y_interp = np.insert(freq_rdt, 0, 0)
interpolator = PchipInterpolator(x_interp, y_interp)
x_fit = np.linspace(0, 1.0, 500)
y_fit = interpolator(x_fit)
y_fit = np.clip(y_fit, 0, None)
# 3. Color Function (Probability Traffic Light)
def get_colors(bins):
return ['#008000' if b < 0.4 else '#FFD700' if b <= 0.7 else '#B22222' for b in bins]
colors_hex = get_colors(bins_rdt)
# Apply separate transparencies (Fill at 60%, Border at 90%)
face_colors = [mcolors.to_rgba(c, alpha=0.60) for c in colors_hex]
edge_colors = [mcolors.to_rgba(c, alpha=0.90) for c in colors_hex]
# 4. Create the chart
plt.figure(figsize=(7, 6))
# Draw bars and empirical trend line
plt.bar(bins_rdt, freq_rdt, width=0.04, color=face_colors, edgecolor=edge_colors, linewidth=1.5, zorder=2)
# 5. Tags and Titles
plt.xlabel('Repeated Dose Toxicity Score (LOAEL < 100 mg/kg/day)', fontsize=12)
plt.ylabel('% Frequency', fontsize=12)
plt.title('Chronic Exposure & Repeated Dose Toxicity', fontsize=14)
# 6. Structured Legend
legend_elements = [
Patch(facecolor=mcolors.to_rgba('#008000', 0.6), edgecolor='#008000', label='Safe (> 100 mg/kg/d) (< 0.4)'),
Patch(facecolor=mcolors.to_rgba('#FFD700', 0.6), edgecolor='#FFD700', label='Moderate Risk (0.4 - 0.7)'),
Patch(facecolor=mcolors.to_rgba('#B22222', 0.6), edgecolor='#B22222', label='Toxic (< 100 mg/kg/d) (> 0.7)')
]
plt.legend(handles=legend_elements, loc='upper left', framealpha=0.95, fontsize=10)
plt.grid(axis='y', linestyle=':', alpha=0.7, zorder=0)
plt.xlim(-0.05, 1.05)
plt.ylim(0, 15)
plt.tight_layout()
plt.show()