""" Generate publication-quality figures for Typhoid HDT Pipeline """ import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from pathlib import Path BASE_DIR = Path(__file__).parent.parent plt.style.use('seaborn-v0_8-whitegrid') def figure1_target_prioritization(): """Figure 1: Top 20 Target Prioritization with Phase Coloring""" df = pd.read_csv(BASE_DIR / 'outputs' / 'tables' / 'targets_ranked_authentic.csv') top20 = df.head(20) def get_color(phase): if phase == 'Acute': return '#E74C3C' # Red - acute infection elif phase == 'Carrier': return '#3498DB' # Blue - chronic carrier else: return '#9B59B6' # Purple - both phases colors = [get_color(p) for p in top20['Phase_Relevance']] fig, ax = plt.subplots(figsize=(12, 8)) bars = ax.barh(range(len(top20)), top20['Composite_Score'], color=colors, edgecolor='black', linewidth=0.5) ax.set_yticks(range(len(top20))) ax.set_yticklabels(top20['Symbol'], fontsize=11, fontweight='bold') ax.invert_yaxis() ax.set_xlabel('Composite Score', fontsize=12, fontweight='bold') ax.set_title('Top 20 Host-Directed Therapy Targets for Typhoid Fever\n(Authentic Analysis - Evidence-Based Weights)', fontsize=14, fontweight='bold') for i, (bar, val) in enumerate(zip(bars, top20['Composite_Score'])): ax.text(val + 0.01, i, f'{val:.3f}', va='center', fontsize=9) from matplotlib.patches import Patch legend_elements = [ Patch(facecolor='#E74C3C', label='Acute Infection'), Patch(facecolor='#3498DB', label='Chronic Carrier'), Patch(facecolor='#9B59B6', label='Both Phases') ] ax.legend(handles=legend_elements, loc='lower right', fontsize=10) plt.tight_layout() plt.savefig(BASE_DIR / 'outputs' / 'figures' / 'figure1_target_prioritization.png', dpi=300, bbox_inches='tight') plt.close() print("Created: figure1_target_prioritization.png") def figure2_compound_distribution(): """Figure 2: Compound Distribution""" df = pd.read_csv(BASE_DIR / 'outputs' / 'tables' / 'compounds_from_chembl.csv') fig, axes = plt.subplots(1, 2, figsize=(14, 6)) phase_counts = df['Max_Phase'].value_counts().sort_index(ascending=False) phase_labels = {4: 'FDA Approved', 3: 'Phase III', 2: 'Phase II', 1: 'Phase I', 0: 'Preclinical'} colors = ['#27AE60', '#F1C40F', '#E67E22', '#E74C3C', '#95A5A6'] wedges, texts, autotexts = axes[0].pie( phase_counts.values, labels=[phase_labels.get(p, f'Phase {p}') for p in phase_counts.index], autopct='%1.1f%%', colors=colors[:len(phase_counts)], explode=[0.05 if p == 4 else 0 for p in phase_counts.index], shadow=True ) axes[0].set_title('A. Clinical Development Phase (ChEMBL)\n(n={})'.format(len(df)), fontsize=12, fontweight='bold') target_counts = df.groupby('Gene').size().sort_values(ascending=True).tail(10) axes[1].barh(range(len(target_counts)), target_counts.values, color='teal', edgecolor='black') axes[1].set_yticks(range(len(target_counts))) axes[1].set_yticklabels(target_counts.index, fontsize=10) axes[1].set_xlabel('Number of Compounds', fontsize=11) axes[1].set_title('B. Top 10 Targets by Compound Count', fontsize=12, fontweight='bold') for i, v in enumerate(target_counts.values): axes[1].text(v + 0.1, i, str(v), va='center', fontsize=9) plt.tight_layout() plt.savefig(BASE_DIR / 'outputs' / 'figures' / 'figure2_compound_distribution.png', dpi=300, bbox_inches='tight') plt.close() print("Created: figure2_compound_distribution.png") def figure3_potency_by_target(): """Figure 3: Compound Potency by Target""" df = pd.read_csv(BASE_DIR / 'outputs' / 'tables' / 'compounds_from_chembl.csv') potency_by_gene = df.groupby('Gene')['pChEMBL'].agg(['mean', 'max', 'count']) potency_by_gene = potency_by_gene.sort_values('max', ascending=False).head(15) fig, ax = plt.subplots(figsize=(12, 8)) colors = plt.cm.RdYlGn(np.linspace(0.2, 0.8, len(potency_by_gene))) bars = ax.barh(range(len(potency_by_gene)), potency_by_gene['max'], color=colors, edgecolor='black') ax.set_yticks(range(len(potency_by_gene))) ax.set_yticklabels(potency_by_gene.index, fontsize=11, fontweight='bold') ax.invert_yaxis() ax.set_xlabel('Maximum pChEMBL (Higher = More Potent)', fontsize=12, fontweight='bold') ax.set_title('Top 15 Typhoid Targets by ChEMBL Compound Potency', fontsize=14, fontweight='bold') ax.axvline(x=6.0, color='red', linestyle='--', alpha=0.7, label='1 µM threshold') ax.axvline(x=8.0, color='green', linestyle='--', alpha=0.7, label='10 nM threshold') for i, (idx, row) in enumerate(potency_by_gene.iterrows()): ax.text(row['max'] + 0.1, i, f'{row["max"]:.1f}', va='center', fontsize=9) ax.legend(loc='lower right') plt.tight_layout() plt.savefig(BASE_DIR / 'outputs' / 'figures' / 'figure3_target_potency.png', dpi=300, bbox_inches='tight') plt.close() print("Created: figure3_target_potency.png") def figure4_pathway_heatmap(): """Figure 4: Pathway Analysis""" df = pd.read_csv(BASE_DIR / 'outputs' / 'tables' / 'targets_ranked_authentic.csv') fig, axes = plt.subplots(1, 2, figsize=(14, 8)) pathway_counts = df.groupby('Pathway').size().sort_values(ascending=True) pathway_scores = df.groupby('Pathway')['Composite_Score'].mean().sort_values(ascending=True) colors = plt.cm.viridis(np.linspace(0.2, 0.8, len(pathway_counts))) axes[0].barh(range(len(pathway_counts)), pathway_counts.values, color=colors, edgecolor='black') axes[0].set_yticks(range(len(pathway_counts))) axes[0].set_yticklabels([p.replace('_', ' ').title() for p in pathway_counts.index], fontsize=10) axes[0].set_xlabel('Number of Targets', fontsize=11) axes[0].set_title('A. Targets per Pathway', fontsize=12, fontweight='bold') for i, v in enumerate(pathway_counts.values): axes[0].text(v + 0.1, i, str(v), va='center', fontsize=9) colors2 = plt.cm.RdYlGn(np.linspace(0.2, 0.8, len(pathway_scores))) axes[1].barh(range(len(pathway_scores)), pathway_scores.values, color=colors2, edgecolor='black') axes[1].set_yticks(range(len(pathway_scores))) axes[1].set_yticklabels([p.replace('_', ' ').title() for p in pathway_scores.index], fontsize=10) axes[1].set_xlabel('Mean Composite Score', fontsize=11) axes[1].set_title('B. Mean Score by Pathway', fontsize=12, fontweight='bold') for i, v in enumerate(pathway_scores.values): axes[1].text(v + 0.01, i, f'{v:.3f}', va='center', fontsize=9) plt.tight_layout() plt.savefig(BASE_DIR / 'outputs' / 'figures' / 'figure4_pathway_heatmap.png', dpi=300, bbox_inches='tight') plt.close() print("Created: figure4_pathway_heatmap.png") def figure5_typhoid_timeline(): """Figure 5: Typhoid Infection Timeline and HDT Opportunities""" fig, ax = plt.subplots(figsize=(14, 9)) # Timeline (weeks) x = np.linspace(0, 8, 500) # Bacterial load curve bacterial = 100 * np.exp(-0.3 * (x - 2)**2) * (1 + 0.2 * np.sin(x*2)) bacterial[x < 0.5] = bacterial[x < 0.5] * (x[x < 0.5] / 0.5) # Immune response curve immune = 80 * (1 - np.exp(-0.5 * x)) * np.exp(-0.1 * x) # Carrier persistence carrier = 30 * (1 - np.exp(-0.2 * x)) * (x > 4) ax.fill_between(x, 0, bacterial, alpha=0.3, color='red', label='Bacterial Burden') ax.fill_between(x, 0, immune, alpha=0.3, color='blue', label='Immune Response') ax.fill_between(x, 0, carrier, alpha=0.3, color='orange', label='Chronic Carriage') ax.plot(x, bacterial, 'r-', linewidth=2) ax.plot(x, immune, 'b-', linewidth=2) ax.plot(x, carrier, 'orange', linewidth=2) # Phase labels ax.annotate('INCUBATION\n& INVASION', xy=(1, 75), fontsize=10, fontweight='bold', color='darkred', ha='center') ax.annotate('ACUTE\nFEVER', xy=(2.5, 85), fontsize=10, fontweight='bold', color='darkred', ha='center') ax.annotate('RESOLUTION', xy=(4.5, 50), fontsize=10, fontweight='bold', color='darkblue', ha='center') ax.annotate('CARRIER\nSTATE', xy=(6.5, 35), fontsize=10, fontweight='bold', color='darkorange', ha='center') # HDT interventions ax.annotate('', xy=(2, 85), xytext=(2, 100), arrowprops=dict(arrowstyle='->', color='green', lw=2)) ax.text(2, 103, 'Autophagy enhancers\nmTOR inhibitors\nIron chelators', ha='center', fontsize=9, color='green') ax.annotate('', xy=(4, 55), xytext=(4, 75), arrowprops=dict(arrowstyle='->', color='purple', lw=2)) ax.text(4, 78, 'Inflammasome\nmodulators\nMacrophage activators', ha='center', fontsize=9, color='purple') ax.annotate('', xy=(6.5, 25), xytext=(6.5, 45), arrowprops=dict(arrowstyle='->', color='brown', lw=2)) ax.text(6.5, 48, 'Bile acid modulators\nBiofilm disruption', ha='center', fontsize=9, color='brown') ax.set_xlabel('Weeks After Infection', fontsize=12, fontweight='bold') ax.set_ylabel('Disease Activity / Response', fontsize=12, fontweight='bold') ax.set_title('Typhoid Fever Timeline and Host-Directed Therapy Intervention Windows', fontsize=14, fontweight='bold', pad=15) ax.axvline(x=1, color='gray', linestyle='--', alpha=0.5) ax.axvline(x=4, color='gray', linestyle='--', alpha=0.5) ax.set_xlim(0, 8) ax.set_ylim(0, 115) ax.legend(loc='upper right') plt.tight_layout(pad=2.0) plt.savefig(BASE_DIR / 'outputs' / 'figures' / 'figure5_typhoid_timeline.png', dpi=300, bbox_inches='tight') plt.close() print("Created: figure5_typhoid_timeline.png") if __name__ == '__main__': print("Generating figures...") print("="*50) figure1_target_prioritization() figure2_compound_distribution() figure3_potency_by_target() figure4_pathway_heatmap() figure5_typhoid_timeline() print("="*50) print("All figures generated successfully!")