Violin Plot

Tumor Gene Expression Profile

Log2 fold change of key oncogenes and tumor suppressors in cancer samples

Output
Tumor Gene Expression Profile
Python
import matplotlib.pyplot as plt
import numpy as np

# Gene expression data (log2 fold change)
np.random.seed(42)
genes = ['TP53', 'BRCA1', 'EGFR', 'MYC', 'KRAS', 'PIK3CA']
# Expression in tumor vs normal tissue
tumor_expr = [
    np.random.normal(-1.5, 0.8, 50),   # TP53 downregulated
    np.random.normal(-2.0, 1.0, 50),   # BRCA1 downregulated
    np.random.normal(2.5, 1.2, 50),    # EGFR upregulated
    np.random.normal(3.0, 0.9, 50),    # MYC upregulated
    np.random.normal(1.8, 1.1, 50),    # KRAS upregulated
    np.random.normal(1.5, 0.7, 50),    # PIK3CA upregulated
]

# Colors based on regulation
colors = ['#3B82F6', '#2563EB', '#EF4444', '#DC2626', '#F97316', '#FB923C']

# Create figure
fig, ax = plt.subplots(figsize=(12, 7), facecolor='white')

vp = ax.violinplot(tumor_expr, positions=range(len(genes)), widths=0.7,
                   showmeans=False, showmedians=False, showextrema=False)

for i, body in enumerate(vp['bodies']):
    body.set_facecolor(colors[i])
    body.set_edgecolor('white')
    body.set_linewidth(2)
    body.set_alpha(0.75)

# Reference line at 0 (no change)
ax.axhline(0, color='#6B7280', linewidth=1.5, linestyle='-', zorder=0)
ax.fill_between([-0.5, 5.5], -0.5, 0.5, color='#F3F4F6', alpha=0.5, zorder=0)
ax.text(5.6, 0, 'No\nchange', fontsize=8, color='#6B7280', va='center')

# Significance thresholds
ax.axhline(1, color='#F97316', linewidth=1, linestyle='--', alpha=0.5)
ax.axhline(-1, color='#3B82F6', linewidth=1, linestyle='--', alpha=0.5)

# Add median markers and significance
for i, expr in enumerate(tumor_expr):
    median = np.median(expr)
    
    # Determine significance
    is_sig = abs(median) > 1
    
    ax.scatter(i, median, c='white', s=100, zorder=10,
               edgecolor=colors[i], linewidth=2.5)
    
    # Significance star
    if is_sig:
        stars = '***' if abs(median) > 2 else '**' if abs(median) > 1.5 else '*'
        y_pos = median + 0.5 if median > 0 else median - 0.5
        ax.text(i, y_pos, stars, ha='center', fontsize=12, 
                color=colors[i], fontweight='bold')

# Gene type indicators
for i, gene in enumerate(genes):
    gene_type = 'TSG' if i < 2 else 'ONC'
    ax.text(i, -4.2, gene_type, ha='center', fontsize=8, 
            color='#3B82F6' if i < 2 else '#EF4444', fontweight='500')

# Labels
ax.text(-0.5, 3.5, 'Upregulated', fontsize=10, color='#EF4444', fontweight='500')
ax.text(-0.5, -3.5, 'Downregulated', fontsize=10, color='#3B82F6', fontweight='500')

# Styling
ax.set_xticks(range(len(genes)))
ax.set_xticklabels(genes, fontsize=12, fontweight='700', family='monospace')
ax.set_ylabel('Log2 Fold Change', fontsize=12, fontweight='500', color='#374151')
ax.set_ylim(-4.5, 5)

ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_color('#E5E7EB')
ax.spines['bottom'].set_color('#E5E7EB')
ax.tick_params(colors='#6B7280', labelsize=10)
ax.yaxis.grid(True, linestyle='--', alpha=0.3, color='#9CA3AF')

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support