Skip to content

Visualization Guide

This guide covers how to create visualizations of Local Optima Networks.

Quick Start

from lonpy import compute_lon, LONVisualizer

# Build a LON
lon = compute_lon(my_func, dim=2, lower_bound=-5, upper_bound=5, n_runs=20)

# Create visualizer
viz = LONVisualizer()

# Generate plots
viz.plot_2d(lon, output_path="lon_2d.png")
viz.plot_3d(lon, output_path="lon_3d.png")

2D Network Plot

The 2D plot shows the network structure with automatic layout:

fig = viz.plot_2d(
    lon,
    output_path="lon.png",
    figsize=(10, 10),  # Figure size in inches
    dpi=150,           # Resolution
    seed=42            # Reproducible layout
)

Understanding the Plot

For LON:

  • Red nodes: Global optima (best fitness)
  • Pink nodes: Other local optima
  • Arrows: Transitions between optima
  • Line width: Transition frequency (thicker = more frequent)

For CMLON:

  • Red nodes: Global optimum sinks
  • Blue nodes: Local (suboptimal) sinks
  • Pink nodes: In global funnel (can reach red)
  • Light blue nodes: In local funnels (trapped)

3D Landscape Plot

The 3D plot uses fitness as the Z-axis:

fig = viz.plot_3d(
    lon,
    output_path="lon_3d.png",
    width=1000,   # Pixels
    height=800,   # Pixels
    seed=42
)

Interactive Viewing

Without output_path, you can interact with the plot:

fig = viz.plot_3d(lon)
fig.show()  # Opens in browser

Animated Rotation GIF

Create a rotating view of the 3D landscape:

viz.create_rotation_gif(
    lon,
    output_path="lon_rotation.gif",
    duration=5.0,  # Seconds
    fps=15,        # Frames per second
    width=800,
    height=800,
    seed=42
)

GIF Parameters

Parameter Default Description
duration 3.0 Animation length in seconds
fps 10 Frames per second
loop 0 Loop count (0 = infinite)

Generate All Visualizations

Create a complete set of visualizations:

outputs = viz.visualize_all(
    lon,
    output_folder="./output",
    seed=42
)

print("Generated files:")
for name, path in outputs.items():
    print(f"  {name}: {path}")

This creates:

  • lon.png - 2D LON plot
  • cmlon.png - 2D CMLON plot
  • 3D_lon.png - 3D LON plot
  • 3D_cmlon.png - 3D CMLON plot
  • lon.gif - Rotating LON animation
  • cmlon.gif - Rotating CMLON animation

Customizing Appearance

Visualizer Settings

viz = LONVisualizer(
    min_edge_width=0.5,    # Minimum edge line width
    max_edge_width=4.0,    # Maximum edge line width
    min_node_size=3.0,     # Minimum node size
    max_node_size=12.0,    # Maximum node size
    arrow_size=0.3,        # Arrow head size
)

Node and Edge Sizing

Node sizes and edge widths are computed automatically based on:

  • Node size: Incoming edge weight (strength)
  • Edge width: Transition frequency (Count attribute)
# Access computed values
edge_widths = viz.compute_edge_widths(lon.graph)
node_sizes = viz.compute_node_sizes(lon.graph)

Comparing LON and CMLON

import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 2, figsize=(16, 8))

# LON
viz.plot_2d(lon, seed=42)
plt.sca(axes[0])
axes[0].set_title(f"LON ({lon.n_vertices} nodes)")

# CMLON
cmlon = lon.to_cmlon()
viz.plot_2d(cmlon, seed=42)
plt.sca(axes[1])
axes[1].set_title(f"CMLON ({cmlon.n_vertices} nodes)")

plt.tight_layout()
plt.savefig("comparison.png")

Color Scheme

The default color scheme:

COLORS = {
    "global_optimum": "red",      # Best fitness sinks
    "local_sink": "royalblue",    # Suboptimal sinks
    "global_basin": "pink",       # Nodes in global funnel
    "local_basin": "lightskyblue", # Nodes in local funnels
    "edge": "dimgray",            # Edge color
    "lon_global": "red",          # LON global optima
    "lon_local": "pink",          # LON other optima
}

Working with matplotlib

The 2D plot returns a matplotlib Figure:

fig = viz.plot_2d(lon, seed=42)

# Add title
fig.axes[0].set_title("My LON Visualization")

# Adjust and save
fig.tight_layout()
fig.savefig("custom_lon.png", dpi=200)

# Don't forget to close
plt.close(fig)

Working with Plotly

The 3D plot returns a plotly Figure:

fig = viz.plot_3d(lon, seed=42)

# Customize camera
fig.update_layout(
    scene_camera=dict(
        eye=dict(x=1.5, y=1.5, z=1.0)
    )
)

# Save in different formats
fig.write_image("lon_3d.png")
fig.write_html("lon_3d.html")  # Interactive

# Show in notebook
fig.show()

Reproducible Layouts

Use seed parameter for reproducible node positions:

# Same layout every time
viz.plot_2d(lon, output_path="plot1.png", seed=42)
viz.plot_2d(lon, output_path="plot2.png", seed=42)  # Identical

High-Quality Output

For publication-quality figures:

# High-resolution 2D
viz.plot_2d(
    lon,
    output_path="publication.png",
    figsize=(12, 12),
    dpi=300
)

# High-resolution 3D
viz.plot_3d(
    lon,
    output_path="publication_3d.png",
    width=1600,
    height=1200
)

Next Steps