rizer.spice.backend.services.results_plotting#

Data extraction, YAML config I/O, and SVG export for the Results Explorer API.

Builds the same physical quantities rizer.misc.simulation.plt_simulation.SimulationPlotter draws with matplotlib, but as plain JSON-serializable series for the Plotly-based web frontend, and reads/writes the exact same axes:/annotations: YAML schema that SimulationPlotter reads – so the two renderers stay visually consistent and a tuning session in the browser produces a YAML export-svg can immediately re-render with matplotlib into the same archived-figure format.

Known simplification: purely decorative overlays with no comparison/tuning value are intentionally not translated into trace data here (the plasma-on axvspan shading in plot_elastic_inelastic_power_ratio). The underlying physical curves for every plot kind are all present.

Attributes#

Classes#

RunData

One loaded run: its full state array plus radius-change segmentation.

Trace

Functions#

load_run(→ RunData)

Load one run's states and radius-change segments from disk.

load_yaml_config(→ dict)

Load a plot_annotations.yaml-shaped file, or {} if it doesn't exist yet.

save_yaml_config(→ None)

Write config back to path, preserving comments on every untouched key.

build_plot_data(→ dict)

Build JSON-serializable trace/axis/annotation data for one plot kind.

build_custom_plot_data(→ dict)

Build every custom-plot quantity's raw values for each of run_ids.

save_annotations(→ pathlib.Path)

Persist a tuned axes/annotations/arrows/trace_colors/trace_linestyles/text_positions block.

export_svg(→ tuple[str, list[str], pathlib.Path])

Save the given config, then render plot_kind with matplotlib into an SVG.

Module Contents#

rizer.spice.backend.services.results_plotting.ANNOTATIONS_YAML_NAME = 'plot_annotations.yaml'#
class rizer.spice.backend.services.results_plotting.RunData#

One loaded run: its full state array plus radius-change segmentation.

run_id: str#
label: str#
states: rizer.misc.simulation.post_process_io.SimulationData#
segments: list[rizer.misc.simulation.post_process_io.SimulationData]#
change_times: list[float]#
class rizer.spice.backend.services.results_plotting.Trace#
label: str#
x: numpy.ndarray#
y: numpy.ndarray#
axis: str#
trace_id: str#
kind: str = 'line'#
y_err: numpy.ndarray | None = None#
color: str | None = None#
linestyle: str = 'solid'#
species: str | None = None#
hover_name: str | None = None#
hover_unit: str | None = None#
hover_source: str | None = None#
group: str = ''#
source_id: str = ''#
to_dict() dict[str, Any]#
rizer.spice.backend.services.results_plotting.load_run(run_id: str) RunData#

Load one run’s states and radius-change segments from disk.

Mirrors the loading sequence in scripts/2T0D_constant_mass_NRP/plot_results_2T0D_constant_mass_simulation.py. Cached by run_id; see _run_cache.

rizer.spice.backend.services.results_plotting.load_yaml_config(path: pathlib.Path) dict#

Load a plot_annotations.yaml-shaped file, or {} if it doesn’t exist yet.

rizer.spice.backend.services.results_plotting.save_yaml_config(path: pathlib.Path, config: dict) None#

Write config back to path, preserving comments on every untouched key.

rizer.spice.backend.services.results_plotting.build_plot_data(plot_kind: str, run_ids: list[str], experiment_ids: list[str]) dict#

Build JSON-serializable trace/axis/annotation data for one plot kind.

Parameters:
  • plot_kind (str) – A rizer.misc.simulation.plot_registry.PLOT_KINDS id.

  • run_ids (list of str) – Run identifiers (see rizer.spice.backend.services.results_discovery). May be empty only for plot kinds with requires_simulation=False.

  • experiment_ids (list of str) – Experiment-file identifiers to overlay, if plot_kind supports it.

Returns:

{“traces”: […], “axes”: {…}, “annotations”: […]}, matching rizer.spice.backend.models.results_schemas.PlotDataResponse.

Return type:

dict

Raises:
  • KeyError – If plot_kind is not a known plot kind.

  • ValueError – If run_ids is empty for a plot kind that requires a simulation.

rizer.spice.backend.services.results_plotting.build_custom_plot_data(run_ids: list[str]) dict#

Build every custom-plot quantity’s raw values for each of run_ids.

Parameters:

run_ids (list of str) – Run identifiers; must be non-empty.

Returns:

{“quantity_info”: {name: {“display_name”, “unit”}}, “runs”: […]}, matching rizer.spice.backend.models.results_schemas.CustomPlotResponse. Every run’s quantities dict has the exact same keys (all of _CUSTOM_QUANTITIES); values are per-run arrays (own length/time base), not aligned across runs.

Return type:

dict

Raises:

ValueError – If run_ids is empty.

rizer.spice.backend.services.results_plotting.save_annotations(plot_kind: str, run_ids: list[str], axes: dict[str, dict], annotations: list[dict], arrows: list[dict], trace_colors: dict[str, str], trace_linestyles: dict[str, str], text_positions: dict[str, float], comparison_name: str | None, time_offsets_ns: dict[str, float] | None = None, hidden_groups: list[str] | None = None) pathlib.Path#

Persist a tuned axes/annotations/arrows/trace_colors/trace_linestyles/text_positions block.

text_positions (species name -> x) is merged into the existing texts: section’s x values rather than replacing it wholesale, unlike every other block here: texts: is also read by SimulationPlotter and, in production files, carries hand-authored comments and commented-out species entries (see test_save_annotations_preserves_comments_and_disabled_entries_elsewhere) that a full replace would silently destroy. time_offsets_ns (source_id -> ns) and hidden_groups (curve-group ids) are written verbatim, like trace_colors/trace_linestyles – no merge logic needed, since both are simple values owned entirely by this feature.

rizer.spice.backend.services.results_plotting.export_svg(plot_kind: str, run_ids: list[str], experiment_ids: list[str], axes: dict[str, dict], annotations: list[dict], arrows: list[dict], trace_colors: dict[str, str], trace_linestyles: dict[str, str], text_positions: dict[str, float], comparison_name: str | None, time_offsets_ns: dict[str, float] | None = None, hidden_groups: list[str] | None = None) tuple[str, list[str], pathlib.Path]#

Save the given config, then render plot_kind with matplotlib into an SVG.

Renders through the exact SimulationPlotter.plot_<kind> method used for the archived figures (via save=False, show=False), so the exported SVG is pixel-for-pixel the same renderer/styling as every other archived figure – only single-run plot kinds are supported for matplotlib export today (matching SimulationPlotter, which is single-run). experiment_ids carries through to SimulationPlotter unchanged, so the exported SVG overlays exactly the experiment CSVs currently selected in the Results Explorer – not more, not less (see SimulationPlotter._matching_experiment_data). trace_colors/trace_linestyles are persisted but not applied here: they are web-view-only overrides with no matplotlib equivalent (curve styling there is hardcoded per plot method), so the exported SVG keeps matplotlib’s own default styling regardless. text_positions does carry through: it is saved into the same texts: section SimulationPlotter._text_x already reads, so a dragged species label position shows up identically in the exported SVG. time_offsets_ns/ hidden_groups DO carry through, unlike trace_colors/trace_linestyles: there is no client-side render step for a static SVG, so export_svg (unlike build_plot_data) applies the shift and filters hidden groups itself, by passing both straight to plot_electrical_signals_unified.

Returns:

  • svg (str) – The rendered SVG document.

  • warnings_raised (list of str) – Any warnings.warn messages raised while rendering (e.g. a dragged label landing outside the configured axis limits and being clamped) – captured here because they would otherwise go to the server’s log, invisible to the browser.

  • saved_path (pathlib.Path) – Where the YAML config was written.

Raises:

ValueError – If run_ids does not contain exactly one run (matplotlib export is not yet implemented for multi-run overlays).