Skip to content

Plotting

Plotting utilities for the logs pytree returned by Experiment.run() and Experiment.run_hparam_search(), so training can be inspected without wandb (see Agent's docstring and issue #60: Experiment.run(log_to_wandb= False) and reading logs directly is the fast path). A Benchmark- scored run's own summary/details/diagnostics plots (Benchmark.plot_summary/plot_details/plot_diagnostics) live in navix/benchmarks/benchmark.py instead, next to the Benchmark methods they render - not here, since Benchmark is the one place that already knows those shapes.

MANDATORY_METRICS is a fixed, deliberately-chosen set of plots, rather than auto-detecting whatever keys happen to be in logs. Each entry is derivable purely from the (state, action, reward, done) interaction stream plus wall-clock time - the one interface every RL algorithm shares, regardless of its internals - so the set stays meaningful for any future agent, not just the ones navix ships: agent/episode/returns, agent/episode/success_rate, agent/episode/length, experiment/costs/fps, experiment/costs/wall_time. Identical across every navix agent so results are visually comparable across algorithms - this is the set the navix leaderboard (#130) is expected to standardise on.

This module deliberately does not know about "diagnostic" (algorithm- specific) metrics - an algorithm submitted to a leaderboard won't necessarily have any navix-specific code to declare which of its own logged keys are diagnostic. That categorisation belongs to whatever consumes this module (e.g. a leaderboard's own file mapping algorithm -> diagnostic keys), not to navix itself. plot_metrics/plot_dashboard both accept an arbitrary metrics dict for exactly this reason.

navix.agents.agent.derive_episodic_metrics (formerly defined here) builds the agent/episode/* keys plot_metric/plot_dashboard expect in logs - it moved out because it's load-bearing for Experiment. run_hparam_search's fitness computation too, not just plotting, so a plotting-only module was the wrong home for it.

The plots every navix agent's logs should support, so results are directly comparable across algorithms. Kept intentionally small: only metrics that (a) exist regardless of which algorithm produced logs, and (b) are actually necessary to tell whether training worked at all.

diagnostics.npz's scalar cost fields, not per-update curves - only submit_entry (navix/benchmarks/benchmark.py) ever adds these, to the npz-only curves dict, never to what curve_diagnostics() itself returns (what Benchmark.plot_diagnostics plots) - so this documents diagnostics.npz's real shape for any future direct consumer of that file, rather than filtering anything plot_diagnostics itself sees.

Renders one Benchmark.summary() value as a table cell: fixed- precision for a float scalar, str() otherwise.

Whether value converts to a rank->=1 float array - a Benchmark.details() numeric, per-row column (as opposed to env_ids, a Tuple[str, ...]).

Plots metrics (MANDATORY_METRICS by default) as a single combined figure, one panel per metric.

This is intentionally agnostic about "mandatory vs. diagnostic" - navix doesn't know, and shouldn't need to know, what a given algorithm considers diagnostic (an algorithm submitted to a leaderboard won't necessarily have any navix-specific code to declare that in). That categorisation belongs to whatever consumes this module - e.g. a leaderboard's own file mapping algorithm -> diagnostic keys - which can merge its own metrics dict with MANDATORY_METRICS and pass the result here.

Parameters:

Name Type Description Default
logs Dict[str, Array]

The logs pytree (see plot_metric).

required
metrics Dict[str, str]

A mapping of logs key to plot title. Defaults to MANDATORY_METRICS. Keys missing from logs are silently skipped.

None
x_key str

The key in logs to use as the x-axis.

'agent/train/frames'
xlabel str

The x-axis label.

'Frames'

Returns:

Type Description

matplotlib.figure.Figure: The combined dashboard figure.

Plots a single metric against x_key, aggregated with a mean line and a min-max shaded band over any leading batch dimensions (e.g. seeds).

Parameters:

Name Type Description Default
logs Dict[str, Array]

The logs pytree, as returned by navix.agents.agent.derive_episodic_metrics (for agent/episode/* keys) or directly from Experiment.run() (for raw keys like agent/train/*, agent/diagnostics/*, experiment/costs/*).

required
key str

The key in logs to plot.

required
title str

The plot title. Defaults to key.

None
x_key str

The key in logs to use as the x-axis.

'agent/train/frames'
xlabel str

The x-axis label.

'Frames'
ax Axes

An existing axes to draw into. If None, a new standalone figure and axes are created.

None

Returns:

Type Description

matplotlib.figure.Figure: The figure ax belongs to.

Plots each metric in metrics as its own standalone figure.

Parameters:

Name Type Description Default
logs Dict[str, Array]

The logs pytree (see plot_metric).

required
metrics Dict[str, str]

A mapping of logs key to plot title, e.g. MANDATORY_METRICS, or a leaderboard-side mapping of algorithm -> diagnostic keys.

required
x_key str

The key in logs to use as the x-axis.

'agent/train/frames'
xlabel str

The x-axis label.

'Frames'

Returns:

Type Description
Dict[str, Figure]

Dict[str, Figure]: One figure per metric, keyed by the same key

Dict[str, Figure]

as metrics. Keys missing from logs are silently skipped.

The key in a Benchmark.details() dict that labels each row (e.g. env_ids) - the first key whose value is a non-empty sequence of strings. Falls back to positional labels if details has none (every value is numeric).

Returns:

Type Description
tuple

Tuple[Optional[str], list]: (label_key, labels) - label_key

tuple

is None when no string-sequence key was found.