Visualization Tutorial¶
Learn advanced visualization techniques for creating publication-quality figures.
Overview¶
This tutorial covers: - Static plots for publications - Interactive HTML plots - Color schemes and styling - Layouts and customization - Multi-panel figures
Basic Visualization¶
from pypopart import Alignment
from pypopart.algorithms import MJNAlgorithm
from pypopart.visualization import StaticPlot, InteractivePlot
# Load and build network
alignment = Alignment.from_fasta("sequences.fasta")
network = MJNAlgorithm().build_network(alignment)
# Simple static plot
plot = StaticPlot(network)
plot.save("network.png")
# Simple interactive plot
interactive = InteractivePlot(network)
interactive.save("network.html")
Publication-Quality Figure¶
import matplotlib.pyplot as plt
# Set publication style
plt.rcParams.update({
'font.size': 12,
'font.family': 'Arial',
'axes.linewidth': 1.5,
'figure.dpi': 300,
})
# Create plot
plot = StaticPlot(
network,
figsize=(8, 8),
layout="spring",
node_size=400,
edge_width=1.5,
show_labels=True,
font_size=10,
)
# Save in multiple formats
plot.save("figure1.png", dpi=300) # For presentations
plot.save("figure1.pdf") # For publication
plot.save("figure1.svg") # For editing
Coloring by Metadata¶
# Color nodes by population
plot = StaticPlot(network)
plot.color_by_attribute("Population")
plot.add_legend(title="Population")
plot.save("colored_by_population.png")
# Custom color scheme
color_map = {
"PopA": "#1f78b4",
"PopB": "#33a02c",
"PopC": "#e31a1c",
}
plot.color_by_attribute("Population", color_map=color_map)
plot.save("custom_colors.png")
# Continuous values (e.g., year)
plot.color_by_attribute("Year", cmap="viridis")
plot.add_colorbar(label="Year")
plot.save("temporal.png")
Node Sizing¶
# Size by frequency
plot = StaticPlot(network)
plot.size_by_frequency(min_size=100, max_size=1000)
plot.save("sized_by_frequency.png")
# Size by custom attribute
plot.size_by_attribute("SampleSize", min_size=50, max_size=800)
plot.save("sized_by_samples.png")
Layout Algorithms¶
layouts = ["spring", "circular", "kamada-kawai", "spectral"]
fig, axes = plt.subplots(2, 2, figsize=(16, 16))
axes = axes.flatten()
for ax, layout in zip(axes, layouts):
plot = StaticPlot(network, ax=ax, layout=layout)
ax.set_title(f"{layout.title()} Layout")
plt.tight_layout()
plt.savefig("layout_comparison.png", dpi=300)
Interactive Visualization¶
# Rich interactive plot
plot = InteractivePlot(
network,
layout="spring",
width=1200,
height=800,
title="Interactive Haplotype Network",
node_size_by="frequency",
color_by="Population",
show_edge_labels=True,
hover_data=["Population", "Location", "Frequency"],
)
plot.save("interactive_network.html")
Multi-Panel Figures¶
from pypopart.algorithms import MSTAlgorithm, MSNAlgorithm, MJNAlgorithm
# Build multiple networks
mst_net = MSTAlgorithm().build_network(alignment)
msn_net = MSNAlgorithm().build_network(alignment)
mjn_net = MJNAlgorithm().build_network(alignment)
# Create multi-panel figure
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
networks = [mst_net, msn_net, mjn_net]
titles = ["MST", "MSN", "MJN"]
for ax, net, title in zip(axes, networks, titles):
plot = StaticPlot(net, ax=ax, layout="spring")
plot.color_by_attribute("Population")
ax.set_title(title, fontsize=16, fontweight='bold')
plt.tight_layout()
plt.savefig("multi_panel.png", dpi=300)
Highlighting Specific Nodes¶
# Highlight hub haplotypes
from pypopart.stats import TopologyAnalysis
topology = TopologyAnalysis(network)
hubs = topology.identify_hubs()
plot = StaticPlot(network)
plot.highlight_nodes(
hubs,
color="#ff0000",
size=800,
edge_color="#ff0000",
edge_width=3
)
plot.save("highlighted_hubs.png")
Styling Median Vectors (MJN)¶
# Different style for observed vs inferred nodes
observed = [n for n in network.nodes() if network.nodes[n].get("type") == "observed"]
median = [n for n in network.nodes() if network.nodes[n].get("type") == "median"]
plot = StaticPlot(network)
plot.style_nodes(observed, shape="o", color="#1f78b4", size=500)
plot.style_nodes(median, shape="s", color="#ff7f00", size=200)
plot.add_legend(handles={
"Observed": {"color": "#1f78b4", "marker": "o"},
"Inferred": {"color": "#ff7f00", "marker": "s"}
})
plot.save("styled_medians.png")
Adding Annotations¶
plot = StaticPlot(network, layout="spring")
# Annotate specific nodes
plot.annotate_node("H1", "Most common", fontsize=12, color="red")
plot.annotate_node("H5", "Ancestral?", fontsize=12, color="blue")
# Add scale bar
plot.add_scale_bar(mutations_per_unit=1, label="1 mutation")
# Add text box with information
plot.add_textbox(
"MJN Algorithm\nK2P Distance\nn=50",
position=(0.05, 0.95),
fontsize=10
)
plot.save("annotated_network.png")
Colorblind-Friendly Palettes¶
from pypopart.visualization.colors import colorblind_safe
plot = StaticPlot(network)
plot.color_by_attribute("Population", colors=colorblind_safe)
plot.save("colorblind_safe.png")
Export for Other Tools¶
# For Gephi
network.save("network.gexf")
# For Cytoscape
network.save("network.graphml")
# For R/igraph
network.save("network.gml")
# With metadata
network.save("network_with_traits.nexus", include_traits=True)
Complete Visualization Script¶
from pypopart import Alignment
from pypopart.algorithms import MJNAlgorithm
from pypopart.visualization import StaticPlot, InteractivePlot
from pypopart.stats import TopologyAnalysis
import matplotlib.pyplot as plt
# Load data and build network
alignment = Alignment.from_fasta("sequences.fasta")
network = MJNAlgorithm().build_network(alignment)
# Identify hubs
hubs = TopologyAnalysis(network).identify_hubs()
# Create static plot
plt.rcParams['font.size'] = 12
plt.rcParams['font.family'] = 'Arial'
plot = StaticPlot(
network,
figsize=(10, 10),
layout="spring",
node_size=400,
)
# Style by metadata
plot.color_by_attribute("Population")
plot.size_by_frequency(min_size=200, max_size=1000)
plot.highlight_nodes(hubs, color="#ff0000", size=900)
# Add annotations
plot.add_legend(title="Population")
plot.add_scale_bar(mutations_per_unit=1)
# Save in multiple formats
plot.save("network.png", dpi=300)
plot.save("network.pdf")
# Create interactive version
interactive = InteractivePlot(
network,
color_by="Population",
node_size_by="frequency",
hover_data=["Population", "Frequency"],
)
interactive.save("network.html")
print("Visualization complete!")
Tips for Great Figures¶
- Resolution: Use DPI ≥ 300 for publications
- Format: PDF/SVG for journals, PNG for presentations
- Colors: Use colorblind-safe palettes
- Size: Large enough to be readable when printed
- Labels: Clear and informative
- Legend: Always include for colored nodes
- Scale: Add scale bar for mutation context
Next Steps¶
- Basic Workflow: Complete analysis
- Population Genetics: Advanced analyses
- Visualization Guide: Full documentation