Skip to content

Figure generation

Two paths: one call for the whole set, or a single panel drawn onto an Axes you own. Both run after fit, and neither needs any recording set up in advance.

One call

import kd

dataset = kd.load_kdv()
model = kd.Model(algorithm="sga", generations=200, seed=42).fit(dataset)

viz = kd.VizEngine(output_dir="out/kdv")
report = viz.render_all(model.result_, algorithm=model.algorithm_, dataset=dataset)

print(report.report)
for path in report.figures:
    print(path.name)

Output (out/kdv is created if it does not exist):

out/kdv/report.html
convergence.svg
parity.svg
equation.svg
equation_tree.svg
residual.svg
coefficient_bar.svg
field_comparison.svg
pde_residual_field.svg
time_slices.svg
error_heatmap.svg
plugin_population_diversity.svg
plugin_complexity_evolution.svg
plugin_fitness_spread.svg
plugin_surrogate_training.svg
plugin_genome_tree.svg

Three arguments to render_all decide how far it draws:

  • algorithm= takes the fitted algorithm itself, which draws its own diagnostic panels; those filenames carry the plugin_ prefix. Leave it out and only the universal figures are rendered.
  • dataset= decides whether the data-dependent figures are drawn: the coefficient bar chart, the field comparison, the u_t residual field, the time slices and the error heatmap.
  • animate=True additionally writes a GIF for 2D-spatial-plus-time data, with its path in report.data_files.

Skips and degradations go into report.warnings, so the figure set never shrinks silently. The run above produced exactly one:

plugin plot 'surrogate_training': No data (no surrogate training logged for this run)

That line comes from the algorithm's own plotting code: this run took derivatives by finite difference, trained no surrogate network, and the panel is therefore empty.

report.report points at an HTML report with every figure inlined as SVG, so it travels as a single file; the LaTeX in the equation block is rendered by MathJax loaded from a public CDN. The report this page's run writes is published here: example report, 15 figures in 1.7 MB. The style= argument of VizEngine takes extra matplotlib rcParams and merges them over KD's defaults. To put several runs side by side, call viz.render_comparison(results, labels=[...]): the convergence curves are overlaid, plus a bar chart of R² across the runs and a summary table.

A single panel

To place one panel in a layout of your own, create the Axes and hand it to the algorithm:

import matplotlib.pyplot as plt

plugin = model.algorithm_
print([info.name for info in plugin.list_plots()])

fig, ax = plt.subplots(figsize=(5, 3))
plugin.render_plot("complexity_evolution", ax)
fig.savefig("complexity.png", dpi=150, bbox_inches="tight")

data = plugin.get_plot_data("complexity_evolution")
print(data["ylabel"], data["y"][:5])

Output:

['population_diversity', 'complexity_evolution', 'fitness_spread', 'surrogate_training', 'genome_tree']
gen_mean_complexity [1.8235294117647058, 2.34375, 3.242424242424242, 3.026315789473684, 3.6]

The Figure belongs to the caller: render_plot draws only on the Axes it is given, so size, colors and titles remain under the caller's control. It returns the degradation notes for that panel (no data, gaps in the series), and merging those into report.warnings is what render_all does with them.

get_plot_data returns the numbers behind the same panel, ready to serialize to JSON and hand to another plotting library or keep as a record. Its fields depend on the panel; a per-generation curve is {x, y, xlabel, ylabel, title}.

An unknown name raises, listing the names this algorithm has:

Unknown plot name: 'nope'. Available: population_diversity, complexity_evolution, fitness_spread, surrogate_training, genome_tree

For another algorithm, change algorithm= and re-run: list_plots() then returns that algorithm's panels, and both paths above are written the same way.