nextnano_optimizers.plotting module#

Visualization of Evolution results. The module is a read-only consumer of the JSON log a run already writes, so it never re-runs a simulation and works equally well on a log from last week.

matplotlib is an optional dependency of the package. Importing this module without it raises a clear error and the rest of nextnano_optimizers keeps working. Install it with:

pip install nextnano_optimizers[plot]

OptimizationPlotter is the offline figure producer — construct it from a finished optimizer, from a log path, or from raw arrays, then call one of the plot_* methods. Each returns the matplotlib Figure, so the caller can compose or restyle further. watch_progress() is the live counterpart: it opens a window, re-reads the log when it changes on disk, and redraws. It is what Evolution.run(live_progress=True), BayesianOptimization.run(live_progress=True) and LocalOptimizer.run(live_progress=True) spawn in a separate process, so the window’s event loop is never starved by the running simulation.

OptimizationPlotter

Visualizes the outcome of an optimization run from its JSON log.

watch_progress

Open a live-updating progress window for an optimization JSON log.

One class holds the whole plotting API — every constructor, every plot_* method and every keyword argument listed in its Parameters section — and all three optimizers drive it, so it is the page to read for what the options mean. A log records the run and not which optimizer wrote it, so the figures are worded neutrally; each optimizer’s own plot_all supplies its wording, and setup_plotting or the constructor kwargs are how you supply it yourself.

Usage#

Straight after a run — no log path needed:

evolution.run(gen=30)
OptimizationPlotter.from_optimizer(evolution).plot_all(show=True)

Offline, from a log written earlier, with axis labels and outliers dropped:

plotter = OptimizationPlotter.from_json(
    "Simulation_2025_09_17.json",
    param_names=["well width", "barrier width"],
    fitness_names=["gain", "current"],
    exclude_failed=True,
)
fig = plotter.plot_pareto()

fitness_limits discards solutions outside per-objective bounds from every panel, so all panels keep showing the same population:

plotter = OptimizationPlotter.from_json(
    "Simulation_2025_09_17.json",
    fitness_limits={"fitness2": (None, 1e3)},
)

Command line#

The module also runs as a script. Without --watch it shows the offline figures for a log; with --watch it opens the live viewer that polls the log and redraws while a run is still writing it:

python -m nextnano_optimizers.plotting Simulation_2025_09_17.json
python -m nextnano_optimizers.plotting Simulation_2025_09_17.json --watch