Visualization¶
Intermediate
Prerequisites: Single deterministic simulation, Batch dataset generation
pylectra ships 10 publication-quality plot plugins, all reachable through the unified render(name, data, ...) interface. This page tours every one.
Three entry points¶
1. CLI (fastest path to a figure)¶
The CLI runs one simulation and emits the plot. --output controls filename + format (extension-driven: PDF/PNG/SVG).
2. Python function¶
from pylectra.run import run
from pylectra.plotting import render
out = run("examples/single_case39.yaml", plot=False)
fig = render("rotor_angles", out.result, gen_indices=[0, 1, 2, 3])
fig.savefig("rotor.pdf")
render(name, data, **kwargs) looks up name in the registry and dispatches.
3. Direct function call (fine-grained)¶
from pylectra.plotting import plot_rotor_angles
fig = plot_rotor_angles(out.result, relative=True, palette="default")
Each plugin wraps an ordinary function.
Single-run plots (input_kind="single")¶
Input: a SimulationResult object or a path to an .h5 file.
rotor_angles¶
Per-machine rotor angles vs. time.
render("rotor_angles", out.result,
relative=True, # subtract the COI (centre of inertia)
gen_indices=[0, 1, 2, 3], # only the first 4 machines
palette="default",
title="case39 rotor angles")
Pro tip: relative=True keeps the curves compact and makes the maximum angular swing obvious; relative=False lets the absolute angles drift visually "to infinity".
speeds¶
Per-machine rotor speed [p.u.].
Speeds dip / rise briefly during the fault, then converge.
voltages¶
Bus voltage magnitudes vs. time.
Faulted buses (e.g. 16) collapse to near 0 during the fault, recover after clearing.
efds¶
Generator field voltages (excitation output).
Useful for inspecting AVR response.
overview¶
2×2 panel: rotor angles + speeds + voltages + torques.
Perfect "system response overview" figure for a paper.
Network topology (input_kind="case")¶
topology¶
Input may be a case name (string) or a NetworkCase object.
Parameters:
| Parameter | Meaning |
|---|---|
color_by |
"vm_pu" (voltage magnitude) / "type" (PQ/PV/REF) / custom array |
cmap |
matplotlib colormap |
bus_size |
node size (default 90) |
show_labels |
render bus numbers |
seed |
spring layout seed (reproducible layout) |
Batch result plots (input_kind="batch")¶
Input: the output.directory path, the metadata.parquet path directly, or a pandas DataFrame.
acceptance¶
Acceptance / rejection stacked bar with reason breakdown.
histogram¶
Distribution of a metric.
violin¶
Per-group violin plot.
heatmap¶
2D aggregation (rows × cols → one column's value).
render("heatmap", "./out_batch",
column="filter_angle_stability_metric",
rows="meta:fault_bus",
cols="meta:load_perturb_sigma_pct",
aggfunc="mean",
cmap="magma")
Example: faulted bus vs. perturbation magnitude, colour = average max-angle-deviation.
Style tweaks¶
Nature layout (default)¶
pylectra applies Nature-style rcParams automatically: Arial font, no top/right spines, embedded fonts in vector PDFs. fig.savefig("out.pdf") is submission-ready.
Two-column width¶
from pylectra.plotting import journal_figsize
fig = render("rotor_angles", out.result, figsize=journal_figsize("double"))
Three presets: single (89 mm) / double (183 mm) / page (247 mm).
Multi-format export¶
from pylectra.plotting import save_figure
save_figure(fig, "rotor", formats=["pdf", "svg", "png"])
# Produces rotor.pdf, rotor.svg, rotor.png
CLI:
python -m pylectra plot examples/single_case39.yaml \
--type overview --output overview --format pdf,svg,png
Advanced CLI usage¶
Pass extra kwargs¶
# -O KEY=VALUE overrides plot-function kwargs (values are JSON-decoded)
python -m pylectra plot examples/single_case39.yaml \
--type rotor_angles --output rotor.pdf \
-O relative=true \
-O 'gen_indices=[0,1,2]' \
-O 'title="My Plot"'
String values need JSON quoting (outer shell quotes + inner "...").
Plot a saved .h5 directly¶
No re-simulation — the saved trajectory is used as-is.
Inside a Jupyter Notebook¶
%matplotlib inline # Display below the cell
from pylectra.run import run
from pylectra.plotting import render
out = run("examples/single_case39.yaml", plot=False)
render("overview", out.result) # auto-displayed
To save without displaying:
import matplotlib
matplotlib.use("Agg") # non-interactive backend
fig = render("overview", out.result)
fig.savefig("overview.pdf")
import matplotlib.pyplot as plt
plt.close(fig) # release memory
Write your own plot¶
The 10 built-ins not enough? Write a plugin — see How to add a new plot type.
Template: subclass PlotPlugin, decorate with @register("plot", "my_plot"), implement render(). ~10 lines.
Next steps¶
- Add a new plot type — custom plot.
- Plugins catalog — every plot plugin + default kwargs.
- pylectra.plotting module — function-level API.