Skill Tracer
Skills › Scientific Agent Skills › pymoo › visualization.md

visualization.md

111 lines · skills/pymoo/references/visualization.md at 5f2bc03

Open on GitHub
1# Visualization (pymoo 0.6.2)
2
3Plot finite feasible objective arrays after checking for `result.F is None`.
4Plots show approximations and trade-offs; visual proximity does not prove
5convergence. A 2D projection can conceal dominance relationships in higher
6objective dimensions. All objectives supplied to the optimizer are minimized;
7label any sign reversal back to physical units explicitly.
8
9The snippets below share synthetic data and were rendered with Matplotlib's Agg
10backend. Replace `F` only after validating the candidate set and common bounds.
12```python
13import numpy as np
14F = np.array([[0.0, 1.0, 0.6], [0.5, 0.5, 0.3], [1.0, 0.0, 0.1]])
15bounds = [np.zeros(3), np.ones(3)]
16labels = ["Cost", "Mass", "Error"]
17```

Visualization (pymoo 0.6.2)

Plot finite feasible objective arrays after checking for result.F is None. Plots show approximations and trade-offs; visual proximity does not prove convergence. A 2D projection can conceal dominance relationships in higher objective dimensions. All objectives supplied to the optimizer are minimized; label any sign reversal back to physical units explicitly.

The snippets below share synthetic data and were rendered with Matplotlib's Agg backend. Replace F only after validating the candidate set and common bounds.

import numpy as np
F = np.array([[0.0, 1.0, 0.6], [0.5, 0.5, 0.3], [1.0, 0.0, 0.1]])
bounds = [np.zeros(3), np.ones(3)]
labels = ["Cost", "Mass", "Error"]
Raw lines 1 to 18
19## Scatter and parallel coordinates
21```python
22from pymoo.visualization.scatter import Scatter
23from pymoo.visualization.pcp import PCP
25scatter = Scatter(title="Candidate objectives", labels=labels, legend=True)
26scatter.add(F, label="Candidates", color="blue", alpha=0.6)
27scatter.save("candidates.png", dpi=150)
29pcp = PCP(bounds=bounds, labels=labels, normalize_each_axis=True)
30pcp.add(F, color="blue", alpha=0.5)
31pcp.save("parallel_coordinates.png", dpi=150)
32```
34Scatter uses 2D or 3D according to input columns, and pairwise panels for more
35than three objectives. Legends default to False: request `legend=True`. Use
36`plot_type="line"` when connecting a sorted analytic front; do not connect across
37a disconnected front. PCP normalization changes the visual scale, not the data's
38scientific meaning. Use shared fixed bounds when comparing runs.

Scatter and parallel coordinates

from pymoo.visualization.scatter import Scatter
from pymoo.visualization.pcp import PCP

scatter = Scatter(title="Candidate objectives", labels=labels, legend=True)
scatter.add(F, label="Candidates", color="blue", alpha=0.6)
scatter.save("candidates.png", dpi=150)

pcp = PCP(bounds=bounds, labels=labels, normalize_each_axis=True)
pcp.add(F, color="blue", alpha=0.5)
pcp.save("parallel_coordinates.png", dpi=150)

Scatter uses 2D or 3D according to input columns, and pairwise panels for more than three objectives. Legends default to False: request legend=True. Use plot_type="line" when connecting a sorted analytic front; do not connect across a disconnected front. PCP normalization changes the visual scale, not the data's scientific meaning. Use shared fixed bounds when comparing runs.

Raw lines 19 to 39
40## Heatmap
42```python
43from pymoo.visualization.heatmap import Heatmap
44heatmap = Heatmap(bounds=bounds, labels=labels, cmap="Blues",
45 order_by_objectives=0, reverse=True)
46heatmap.add(F)
47heatmap.save("objective_values.png", dpi=150)
48```
50Rows are solutions and columns are objectives. Cell color represents a normalized
51**objective value**, not a binned solution density. There is no `bins` constructor
52parameter. Only one matrix may be added to a Heatmap; stack comparable candidate
53matrices first and retain source labels. `reverse=True` makes lower values darker
54under the default Blues colormap. For actual density, use a separately defined
55histogram with a documented binning rule.

Heatmap

from pymoo.visualization.heatmap import Heatmap
heatmap = Heatmap(bounds=bounds, labels=labels, cmap="Blues",
                  order_by_objectives=0, reverse=True)
heatmap.add(F)
heatmap.save("objective_values.png", dpi=150)

Rows are solutions and columns are objectives. Cell color represents a normalized objective value, not a binned solution density. There is no bins constructor parameter. Only one matrix may be added to a Heatmap; stack comparable candidate matrices first and retain source labels. reverse=True makes lower values darker under the default Blues colormap. For actual density, use a separately defined histogram with a documented binning rule.

Raw lines 40 to 56
57## Petal, radar, Radviz, and star coordinates
59```python
60from pymoo.visualization.petal import Petal
61from pymoo.visualization.radar import Radar
62from pymoo.visualization.radviz import Radviz
63from pymoo.visualization.star_coordinate import StarCoordinate
65petal = Petal(bounds=bounds, labels=labels, reverse=True)
66petal.add(F[:2])
67petal.save("petal.png", dpi=150)
68radar = Radar(bounds=bounds, labels=labels)
69radar.add(F[:2])
70radar.save("radar.png", dpi=150)
71Radviz(bounds=bounds, labels=labels).add(F).save("radviz.png", dpi=150)
72StarCoordinate(bounds=bounds, labels=labels).add(F).save("star.png", dpi=150)
73```
75Petal requires explicit bounds. Its `reverse` flag reverses all normalized
76objectives, not a separate arbitrary direction per objective; make any mixed
77orientation transform explicitly. Petal creates panels rather than overlaid
78polygons for multiple solutions. Set positive spans or resolve constant columns
79before interpreting radial or normalized views. Radviz/star projection positions
80are descriptive; their clusters and distances do not certify Pareto quality.

Petal, radar, Radviz, and star coordinates

from pymoo.visualization.petal import Petal
from pymoo.visualization.radar import Radar
from pymoo.visualization.radviz import Radviz
from pymoo.visualization.star_coordinate import StarCoordinate

petal = Petal(bounds=bounds, labels=labels, reverse=True)
petal.add(F[:2])
petal.save("petal.png", dpi=150)
radar = Radar(bounds=bounds, labels=labels)
radar.add(F[:2])
radar.save("radar.png", dpi=150)
Radviz(bounds=bounds, labels=labels).add(F).save("radviz.png", dpi=150)
StarCoordinate(bounds=bounds, labels=labels).add(F).save("star.png", dpi=150)

Petal requires explicit bounds. Its reverse flag reverses all normalized objectives, not a separate arbitrary direction per objective; make any mixed orientation transform explicitly. Petal creates panels rather than overlaid polygons for multiple solutions. Set positive spans or resolve constant columns before interpreting radial or normalized views. Radviz/star projection positions are descriptive; their clusters and distances do not certify Pareto quality.

Raw lines 57 to 81
82## Convergence and animation
84Use callback traces for scalar time/evaluation/indicator histories. If the
85optimization used `save_history=True`, each `result.history` item is an algorithm
86snapshot. Valid indices run from 0 to `len(result.history)-1`, not through
87`result.algorithm.n_gen`.
89```python
90# Context-dependent: result is a completed MOO run with save_history=True.
91plot = Scatter(title="Approximation over generations", legend=True)
92indices = np.unique(np.linspace(0, len(result.history) - 1, 4, dtype=int))
93for index in indices:
94 entry = result.history[index]
95 feasible = entry.opt.get("FEAS").ravel()
96 if feasible.any():
97 plot.add(entry.opt.get("F")[feasible], alpha=0.4,
98 label=f"Generation {entry.n_gen}")
99plot.save("convergence.png", dpi=150)
100```
102For animations upstream uses optional `pyrecorder.recorder.Recorder` with
103`pyrecorder.writers.video.Video`, recording plots inside the writer context.
104There is no `pymoo.visualization.video.Video(result.algorithm)` interface.
105Follow the [video guide](https://pymoo.org/visualization/video.html) and validate the
106selected writer/codec on the target machine. Video encoding and interactive
107streaming were not executed in this refresh; static plots were.
109Sources reviewed 2026-10-01: [visualization](https://pymoo.org/visualization/index.html),
110[Heatmap](https://pymoo.org/visualization/heatmap.html),
111[Petal](https://pymoo.org/visualization/petal.html), and released plotting source.

Convergence and animation

Use callback traces for scalar time/evaluation/indicator histories. If the optimization used save_history=True, each result.history item is an algorithm snapshot. Valid indices run from 0 to len(result.history)-1, not through result.algorithm.n_gen.

# Context-dependent: result is a completed MOO run with save_history=True.
plot = Scatter(title="Approximation over generations", legend=True)
indices = np.unique(np.linspace(0, len(result.history) - 1, 4, dtype=int))
for index in indices:
    entry = result.history[index]
    feasible = entry.opt.get("FEAS").ravel()
    if feasible.any():
        plot.add(entry.opt.get("F")[feasible], alpha=0.4,
                 label=f"Generation {entry.n_gen}")
plot.save("convergence.png", dpi=150)

For animations upstream uses optional pyrecorder.recorder.Recorder with pyrecorder.writers.video.Video, recording plots inside the writer context. There is no pymoo.visualization.video.Video(result.algorithm) interface. Follow the video guide and validate the selected writer/codec on the target machine. Video encoding and interactive streaming were not executed in this refresh; static plots were.

Sources reviewed 2026-10-01: visualization, Heatmap, Petal, and released plotting source.

Raw lines 82 to 111