From 589f4050946ed35a7b280f790c0a54fa6975ecba Mon Sep 17 00:00:00 2001 From: blizhan Date: Sun, 26 Apr 2026 16:55:38 +0800 Subject: [PATCH 1/6] Add trace distribution support with tensor rendering --- README.md | 15 +++ src/aimx/aim_bridge/metric_stats.py | 118 +++++++++++++++++ src/aimx/commands/help.py | 2 + src/aimx/commands/trace.py | 140 ++++++++++++++------ src/aimx/rendering/trace_views.py | 117 +++++++++++++++- tests/unit/test_trace_distribution_views.py | 70 ++++++++++ tests/unit/test_trace_helpers.py | 13 ++ 7 files changed, 433 insertions(+), 42 deletions(-) create mode 100644 tests/unit/test_trace_distribution_views.py diff --git a/README.md b/README.md index 2fbb0d3..ff851e9 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,21 @@ aimx trace "metric.name == 'loss'" --repo data --every 10 Output modes: default plot, `--table`, `--csv`, `--json`. Display controls: `--width W`, `--height H`, `--no-color`. +### Trace distributions + +`aimx trace distribution` fetches tracked Aim distribution sequences and renders +their tensor payload (histogram weights) per step in a terminal table, CSV, or +JSON. + +```bash +# Show distribution tensors in a readable table +aimx trace distribution "distribution.name == 'weights'" --repo data + +# Export distribution histograms for scripting +aimx trace distribution "distribution.name == 'weights'" --repo data --csv +aimx trace distribution "distribution.name == 'weights'" --repo data --json +``` + ### Common query options - Output: `--json`, `--oneline` / `--plain`, or the default rich terminal view. diff --git a/src/aimx/aim_bridge/metric_stats.py b/src/aimx/aim_bridge/metric_stats.py index 6dc6864..df165e3 100644 --- a/src/aimx/aim_bridge/metric_stats.py +++ b/src/aimx/aim_bridge/metric_stats.py @@ -53,6 +53,26 @@ def max(self) -> tuple[float, int]: return (float(self.values[idx]), int(self.steps[idx])) +@dataclass(frozen=True) +class DistributionPoint: + step: int + epoch: float | None + weights: np.ndarray + bin_edges: np.ndarray + + +@dataclass +class DistributionSeries: + run: RunMeta + name: str + context: dict[str, Any] + points: list[DistributionPoint] + + @property + def count(self) -> int: + return len(self.points) + + def _extract_run_meta(run: Any) -> RunMeta: creation_time = getattr(run, "creation_time", None) if creation_time is None: @@ -233,6 +253,62 @@ def _accessor() -> Any: return rows +def collect_distribution_series(expression: str, repo_path: Path) -> list[DistributionSeries]: + """Run an Aim distribution query and return flat ``DistributionSeries`` records.""" + from aimx.aim_bridge.hash_resolver import resolve_hash_prefixes + + expression = resolve_hash_prefixes(expression, repo_path) + + try: + from aim import Repo + from aim.sdk.types import QueryReportMode + except ModuleNotFoundError as error: + raise RuntimeError( + "`aimx` requires the Python `aim` package in the current environment." + ) from error + + repo = Repo(str(repo_path)) + results: list[DistributionSeries] = [] + + stderr_buf = io.StringIO() + with contextlib.redirect_stderr(stderr_buf): + query_result = repo.query_distributions( + expression, report_mode=QueryReportMode.DISABLED + ) + for run_collection in query_result.iter_runs(): + for distribution in run_collection: + run_meta = _extract_run_meta(distribution.run) + try: + steps, (values, epochs, _timestamps) = distribution.data.items_list() + except ValueError: + steps, values, epochs = [], [], [] + + points: list[DistributionPoint] = [] + for idx, value in enumerate(values): + step_value = int(steps[idx]) + epoch_value = float(epochs[idx]) if idx < len(epochs) else None + weights, bin_edges = value.to_np_histogram() + points.append( + DistributionPoint( + step=step_value, + epoch=epoch_value, + weights=np.array(weights, dtype=float), + bin_edges=np.array(bin_edges, dtype=float), + ) + ) + + results.append( + DistributionSeries( + run=run_meta, + name=distribution.name, + context=distribution.context.to_dict(), + points=points, + ) + ) + + return results + + def subsample(series: MetricSeries, *, head: int | None, tail: int | None, every: int | None) -> MetricSeries: """Return a new MetricSeries with points filtered by head/tail/every.""" n = len(series.values) @@ -258,6 +334,48 @@ def subsample(series: MetricSeries, *, head: int | None, tail: int | None, every ) +def filter_distribution_by_step_range( + series: DistributionSeries, + start: int | None, + end: int | None, +) -> DistributionSeries: + """Return a new ``DistributionSeries`` filtered by inclusive step bounds.""" + points = series.points + if start is not None: + points = [point for point in points if point.step >= start] + if end is not None: + points = [point for point in points if point.step <= end] + return DistributionSeries( + run=series.run, + name=series.name, + context=series.context, + points=points, + ) + + +def subsample_distribution( + series: DistributionSeries, + *, + head: int | None, + tail: int | None, + every: int | None, +) -> DistributionSeries: + """Return a new ``DistributionSeries`` filtered by head/tail/every.""" + points = series.points + if head is not None: + points = points[:head] + if tail is not None: + points = points[-tail:] + if every is not None and every > 1: + points = points[::every] + return DistributionSeries( + run=series.run, + name=series.name, + context=series.context, + points=points, + ) + + def parse_epoch_slice(s: str) -> tuple[float | None, float | None]: """Parse a ``start:end`` slice string into inclusive float bounds for epoch filtering. diff --git a/src/aimx/commands/help.py b/src/aimx/commands/help.py index 309368f..971e6b2 100644 --- a/src/aimx/commands/help.py +++ b/src/aimx/commands/help.py @@ -26,6 +26,7 @@ def render_help() -> str: " Example: aimx query params \"run.experiment=='cloud-segmentation'\" --repo data --param hparam.lr", " trace Plot a metric's time-series from a local Aim repository", " Usage: aimx trace [--repo ]", + " Usage: aimx trace distribution [--repo ]", " Options: --table --csv --json", " --steps start:end (e.g. --steps 100:500, :50, 100:)", " --head N --tail N --every K", @@ -33,6 +34,7 @@ def render_help() -> str: " Repo defaults to the current directory.", " Short run hashes in the expression are transparently expanded.", " Example: aimx trace \"metric.name=='loss'\" --repo data --steps 100:500", + " Example: aimx trace distribution \"distribution.name=='weights'\" --repo data --json", "", "All other commands are delegated to native `aim`.", ] diff --git a/src/aimx/commands/trace.py b/src/aimx/commands/trace.py index 6501484..129480d 100644 --- a/src/aimx/commands/trace.py +++ b/src/aimx/commands/trace.py @@ -12,6 +12,7 @@ @dataclass(frozen=True) class TraceInvocation: + target: Literal["metrics", "distribution"] expression: str repo_path: Path mode: Literal["plot", "table", "csv", "json"] = "plot" @@ -27,13 +28,26 @@ class TraceInvocation: def parse_trace_invocation(args: list[str]) -> TraceInvocation: if len(args) < 1: raise ValueError( - "Usage: aimx trace [--repo ] [--table|--csv|--json]" + "Usage: aimx trace [distribution] [--repo ] [--table|--csv|--json]" " [--steps start:end] [--head N] [--tail N] [--every K]" " [--width W] [--height H] [--no-color]" ) - expression = args[0] - rest = args[1:] + target: Literal["metrics", "distribution"] = "metrics" + expression: str | None = None + rest = args + if args[0] == "distribution": + target = "distribution" + if len(args) < 2: + raise ValueError( + "Usage: aimx trace distribution [--repo ] [--table|--csv|--json]" + " [--steps start:end] [--head N] [--tail N] [--every K] [--no-color]" + ) + expression = args[1] + rest = args[2:] + else: + expression = args[0] + rest = args[1:] mode: Literal["plot", "table", "csv", "json"] = "plot" repo_value = "." @@ -118,6 +132,7 @@ def parse_trace_invocation(args: list[str]) -> TraceInvocation: raise ValueError(f"Unsupported trace option: {token}") return TraceInvocation( + target=target, expression=expression, repo_path=Path(repo_value), mode=mode, @@ -142,57 +157,100 @@ def run_trace_command(args: list[str]) -> QueryCommandResult: effective_no_color = invocation.no_color or not is_tty try: - from aimx.aim_bridge.metric_stats import ( - collect_metric_series, - filter_by_step_range, - parse_step_slice, - subsample, - ) + from aimx.aim_bridge.metric_stats import parse_step_slice from aimx.rendering.trace_views import ( + render_distribution_csv, + render_distribution_json, + render_distribution_table, render_csv, + render_trace_table, render_plot, render_trace_json, - render_trace_table, ) - series_list = collect_metric_series(invocation.expression, normalized_repo_path) + if invocation.target == "distribution": + from aimx.aim_bridge.metric_stats import ( + collect_distribution_series, + filter_distribution_by_step_range, + subsample_distribution, + ) - if not series_list: - return QueryCommandResult(exit_status=0, output="No matching metrics found.") + series_list = collect_distribution_series(invocation.expression, normalized_repo_path) + if not series_list: + return QueryCommandResult(exit_status=0, output="No matching distributions found.") - # Step range filter is a hard constraint applied before density subsampling - if invocation.step_slice is not None: - step_start, step_end = parse_step_slice(invocation.step_slice) - series_list = [filter_by_step_range(s, step_start, step_end) for s in series_list] - # Drop empty series so they don't clutter plots - series_list = [s for s in series_list if s.count > 0] + if invocation.step_slice is not None: + step_start, step_end = parse_step_slice(invocation.step_slice) + series_list = [ + filter_distribution_by_step_range(s, step_start, step_end) for s in series_list + ] + series_list = [s for s in series_list if s.count > 0] - if not series_list: - return QueryCommandResult(exit_status=0, output="No data in the requested step range.") + if not series_list: + return QueryCommandResult(exit_status=0, output="No data in the requested step range.") - # Density subsampling for visualisation - needs_sample = any( - x is not None for x in (invocation.head, invocation.tail, invocation.every) - ) - if needs_sample: - series_list = [ - subsample(s, head=invocation.head, tail=invocation.tail, every=invocation.every) - for s in series_list - ] - - if invocation.mode == "json": - output = render_trace_json(series_list) - elif invocation.mode == "csv": - output = render_csv(series_list) - elif invocation.mode == "table": - output = render_trace_table(series_list, no_color=effective_no_color) + needs_sample = any( + x is not None for x in (invocation.head, invocation.tail, invocation.every) + ) + if needs_sample: + series_list = [ + subsample_distribution( + s, head=invocation.head, tail=invocation.tail, every=invocation.every + ) + for s in series_list + ] + + if invocation.mode == "json": + output = render_distribution_json(series_list) + elif invocation.mode == "csv": + output = render_distribution_csv(series_list) + else: + output = render_distribution_table(series_list, no_color=effective_no_color) else: - output = render_plot( - series_list, - width=invocation.width, - height=invocation.height, + from aimx.aim_bridge.metric_stats import ( + collect_metric_series, + filter_by_step_range, + subsample, ) + series_list = collect_metric_series(invocation.expression, normalized_repo_path) + + if not series_list: + return QueryCommandResult(exit_status=0, output="No matching metrics found.") + + # Step range filter is a hard constraint applied before density subsampling + if invocation.step_slice is not None: + step_start, step_end = parse_step_slice(invocation.step_slice) + series_list = [filter_by_step_range(s, step_start, step_end) for s in series_list] + # Drop empty series so they don't clutter plots + series_list = [s for s in series_list if s.count > 0] + + if not series_list: + return QueryCommandResult(exit_status=0, output="No data in the requested step range.") + + # Density subsampling for visualisation + needs_sample = any( + x is not None for x in (invocation.head, invocation.tail, invocation.every) + ) + if needs_sample: + series_list = [ + subsample(s, head=invocation.head, tail=invocation.tail, every=invocation.every) + for s in series_list + ] + + if invocation.mode == "json": + output = render_trace_json(series_list) + elif invocation.mode == "csv": + output = render_csv(series_list) + elif invocation.mode == "table": + output = render_trace_table(series_list, no_color=effective_no_color) + else: + output = render_plot( + series_list, + width=invocation.width, + height=invocation.height, + ) + return QueryCommandResult(exit_status=0, output=output) except RuntimeError as error: diff --git a/src/aimx/rendering/trace_views.py b/src/aimx/rendering/trace_views.py index fd9eed8..8c2f508 100644 --- a/src/aimx/rendering/trace_views.py +++ b/src/aimx/rendering/trace_views.py @@ -11,7 +11,7 @@ from rich.console import Console from rich.table import Table -from aimx.aim_bridge.metric_stats import MetricSeries, RunMeta +from aimx.aim_bridge.metric_stats import DistributionSeries, MetricSeries, RunMeta from aimx.rendering import colors @@ -38,6 +38,19 @@ def _series_label(series: MetricSeries) -> str: return " · ".join(parts) +def _distribution_series_label(series: DistributionSeries) -> str: + parts = [_short_hash(series.run.hash)] + if series.run.experiment: + parts.append(series.run.experiment) + elif series.run.name: + parts.append(series.run.name) + parts.append(series.name) + ctx = _fmt_context(series.context) + if ctx: + parts.append(f"[{ctx}]") + return " · ".join(parts) + + def render_plot( series_list: list[MetricSeries], *, @@ -166,3 +179,105 @@ def render_trace_json(series_list: list[MetricSeries]) -> str: } ) return json.dumps(result) + + +def _format_tensor(values: list[float], *, limit: int = 12) -> str: + if len(values) <= limit: + return "[" + ", ".join(f"{v:.6g}" for v in values) + "]" + head = ", ".join(f"{v:.6g}" for v in values[:limit]) + return f"[{head}, …] ({len(values)} bins)" + + +def render_distribution_table( + series_list: list[DistributionSeries], + *, + no_color: bool = False, +) -> str: + """Render distribution series as a step-indexed tensor table.""" + width = 120 if no_color else shutil.get_terminal_size(fallback=(120, 24)).columns + buf = io.StringIO() + console = Console( + file=buf, + no_color=no_color, + force_terminal=not no_color, + width=width, + highlight=False, + ) + + for series in series_list: + label = _distribution_series_label(series) + console.print(f"\n[{colors.HEADER}]{label}[/] [{colors.HEADER}]{series.count} points[/]") + + table = Table( + show_header=True, + header_style=colors.HEADER, + box=None, + pad_edge=True, + show_edge=False, + padding=(0, 1), + ) + table.add_column("STEP", justify="right") + table.add_column("EPOCH", justify="right") + table.add_column("TENSOR", justify="left", style=colors.NUMBER_EMPH) + + for point in series.points: + epoch = f"{point.epoch:.6g}" if point.epoch is not None else "—" + weights = point.weights.tolist() + table.add_row(str(point.step), epoch, _format_tensor(weights)) + + console.print(table) + + return buf.getvalue() + + +def render_distribution_csv(series_list: list[DistributionSeries]) -> str: + """Render distribution rows as CSV.""" + buf = io.StringIO() + writer = csv.writer(buf) + writer.writerow( + ["run_hash", "experiment", "distribution", "context", "step", "epoch", "bin_edges", "weights"] + ) + for series in series_list: + ctx_str = json.dumps(series.context, sort_keys=True) + for point in series.points: + writer.writerow( + [ + series.run.hash, + series.run.experiment or series.run.name or "", + series.name, + ctx_str, + point.step, + point.epoch if point.epoch is not None else "", + json.dumps(point.bin_edges.tolist()), + json.dumps(point.weights.tolist()), + ] + ) + return buf.getvalue() + + +def render_distribution_json(series_list: list[DistributionSeries]) -> str: + """Render distribution rows as JSON.""" + result: list[dict[str, Any]] = [] + for series in series_list: + result.append( + { + "run": { + "hash": series.run.hash, + "experiment": series.run.experiment, + "name": series.run.name, + }, + "distribution": series.name, + "context": series.context, + "count": series.count, + "points": [ + { + "step": point.step, + "epoch": point.epoch, + "bin_edges": point.bin_edges.tolist(), + "weights": point.weights.tolist(), + } + for point in series.points + ], + } + ) + return json.dumps(result) diff --git a/tests/unit/test_trace_distribution_views.py b/tests/unit/test_trace_distribution_views.py new file mode 100644 index 0000000..26d8811 --- /dev/null +++ b/tests/unit/test_trace_distribution_views.py @@ -0,0 +1,70 @@ +from __future__ import annotations + +import csv +import io +import json + +import numpy as np + +from aimx.aim_bridge.metric_stats import DistributionPoint, DistributionSeries, RunMeta +from aimx.rendering.trace_views import ( + render_distribution_csv, + render_distribution_json, + render_distribution_table, +) + + +def _sample_distribution_series() -> list[DistributionSeries]: + run = RunMeta(hash="1234567890abcdef", experiment="exp-a", name=None, creation_time=None) + return [ + DistributionSeries( + run=run, + name="weights", + context={"subset": "train"}, + points=[ + DistributionPoint( + step=10, + epoch=1.0, + bin_edges=np.array([0.0, 1.0, 2.0]), + weights=np.array([3.0, 5.0]), + ), + DistributionPoint( + step=20, + epoch=2.0, + bin_edges=np.array([0.0, 1.0, 2.0]), + weights=np.array([2.0, 4.0]), + ), + ], + ) + ] + + +def test_render_distribution_table_includes_tensor_column() -> None: + output = render_distribution_table(_sample_distribution_series(), no_color=True) + + assert "TENSOR" in output + assert "weights" in output + assert "[3, 5]" in output + + +def test_render_distribution_csv_contains_bin_edges_and_weights() -> None: + output = render_distribution_csv(_sample_distribution_series()) + + reader = csv.DictReader(io.StringIO(output)) + rows = list(reader) + assert rows + assert rows[0]["distribution"] == "weights" + assert rows[0]["bin_edges"] == "[0.0, 1.0, 2.0]" + assert rows[0]["weights"] == "[3.0, 5.0]" + + +def test_render_distribution_json_contains_points() -> None: + output = render_distribution_json(_sample_distribution_series()) + payload = json.loads(output) + + assert payload + first = payload[0] + assert first["distribution"] == "weights" + assert first["count"] == 2 + assert first["points"][0]["step"] == 10 + assert first["points"][0]["weights"] == [3.0, 5.0] diff --git a/tests/unit/test_trace_helpers.py b/tests/unit/test_trace_helpers.py index 19aad6a..8afa427 100644 --- a/tests/unit/test_trace_helpers.py +++ b/tests/unit/test_trace_helpers.py @@ -9,6 +9,7 @@ def test_parse_trace_defaults() -> None: inv = parse_trace_invocation(["metric.name=='loss'"]) + assert inv.target == "metrics" assert inv.expression == "metric.name=='loss'" assert inv.repo_path == Path(".") assert inv.mode == "plot" @@ -66,6 +67,18 @@ def test_parse_trace_explicit_repo_overrides_default() -> None: assert inv.repo_path == Path("data") +def test_parse_trace_distribution_target() -> None: + inv = parse_trace_invocation(["distribution", "distribution.name=='weights'", "--repo", "data"]) + assert inv.target == "distribution" + assert inv.expression == "distribution.name=='weights'" + assert inv.repo_path == Path("data") + + +def test_parse_trace_distribution_requires_expression() -> None: + with pytest.raises(ValueError, match="trace distribution"): + parse_trace_invocation(["distribution"]) + + def test_parse_trace_rejects_unknown_flag() -> None: with pytest.raises(ValueError, match="Unsupported trace option"): parse_trace_invocation(["expr", "--repo", "data", "--bogus"]) From 3aa4d337731fc5f3b44eb56e5b8ab2594b40b0a3 Mon Sep 17 00:00:00 2001 From: blizhan Date: Thu, 30 Apr 2026 16:53:57 +0800 Subject: [PATCH 2/6] feat: enhance trace distribution functionality - Added support for visualizing distribution traces with histogram and heatmap outputs. - Updated command help to include new usage examples for distribution tracing. - Implemented step selection for distribution traces, allowing users to specify exact or nearest steps. - Enhanced tests to cover new distribution visualization features and ensure correct behavior across various output formats. - Updated `.gitignore` to include additional temporary files related to distribution tracing. --- .gitignore | 2 + AGENTS.md | 2 + README.md | 16 +- skills/aimx/SKILL.md | 19 +- skills/aimx/references/aimx-cli.md | 62 +++++ .../checklists/requirements.md | 36 +++ .../contracts/cli-output.md | 141 ++++++++++ .../data-model.md | 184 +++++++++++++ specs/005-distribution-trace-visual/plan.md | 161 ++++++++++++ .../quickstart.md | 155 +++++++++++ .../005-distribution-trace-visual/research.md | 121 +++++++++ specs/005-distribution-trace-visual/spec.md | 119 +++++++++ specs/005-distribution-trace-visual/tasks.md | 241 +++++++++++++++++ src/aimx/aim_bridge/metric_stats.py | 36 +++ src/aimx/commands/help.py | 5 +- src/aimx/commands/trace.py | 245 +++++++++++------- src/aimx/rendering/trace_views.py | 225 +++++++++++++++- tests/contract/test_trace_contract.py | 151 +++++++++++ tests/integration/test_trace_command.py | 228 ++++++++++++++++ tests/unit/test_metric_stats.py | 52 ++++ tests/unit/test_trace_distribution_views.py | 140 ++++++++++ tests/unit/test_trace_helpers.py | 169 +++++++++++- 22 files changed, 2408 insertions(+), 102 deletions(-) create mode 100644 specs/005-distribution-trace-visual/checklists/requirements.md create mode 100644 specs/005-distribution-trace-visual/contracts/cli-output.md create mode 100644 specs/005-distribution-trace-visual/data-model.md create mode 100644 specs/005-distribution-trace-visual/plan.md create mode 100644 specs/005-distribution-trace-visual/quickstart.md create mode 100644 specs/005-distribution-trace-visual/research.md create mode 100644 specs/005-distribution-trace-visual/spec.md create mode 100644 specs/005-distribution-trace-visual/tasks.md diff --git a/.gitignore b/.gitignore index 073950c..8ab8f39 100644 --- a/.gitignore +++ b/.gitignore @@ -216,6 +216,8 @@ __marimo__/ # spec-kit .specify/ +.agents/skills/spec* # aim data/ +datatest/ diff --git a/AGENTS.md b/AGENTS.md index c1db14b..34854fb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,6 +81,8 @@ Why `3.12`: - Existing local Aim repositories (read-only). Image bytes are read (003-query-images-terminal-render) - Python 3.12 for development, runtime support `>=3.10,<3.13` + Python standard library, `numpy>=1.24`, `rich>=13.7`, `textual-image>=0.12.0`, existing Aim SDK usage for owned query commands; no new dependency planned (004-run-params-query) - Existing local Aim repositories on disk (read-only); run params are read from Aim run metadata attributes under `.aim` (004-run-params-query) +- Python 3.12 for development, runtime support `>=3.10,<3.13` + Python standard library, `numpy>=1.24`, `rich>=13.7`, `plotext>=5.3`, existing Aim SDK usage for owned trace commands; no new runtime dependency planned (005-distribution-trace-visual) +- Existing local Aim repositories on disk, read-only; distribution histogram points are read from Aim sequence data under `.aim` (005-distribution-trace-visual) ## Recent Changes - 001-aim-command-passthrough: Added Python 3.12 for development, runtime support `>=3.10,<3.13` + Python standard library, native Aim CLI (external runtime prerequisite for delegated commands), pytest for test automation diff --git a/README.md b/README.md index ff851e9..eb09140 100644 --- a/README.md +++ b/README.md @@ -234,13 +234,21 @@ Display controls: `--width W`, `--height H`, `--no-color`. ### Trace distributions -`aimx trace distribution` fetches tracked Aim distribution sequences and renders -their tensor payload (histogram weights) per step in a terminal table, CSV, or -JSON. +`aimx trace distribution` fetches tracked Aim distribution sequences. By +default it prints the matched distribution names, selects the first match, and +renders a non-interactive Rich terminal visual with a web-style blue-gradient +current-step histogram and step-by-bin heatmap. Use `--table`, `--csv`, or +`--json` for tensor inspection and scripting. ```bash +# Show a web-like terminal visual for the first matched distribution +aimx trace distribution "distribution.name != ''" --repo data + +# Inspect a specific training step; nearest tracked step is used if needed +aimx trace distribution "distribution.name != ''" --repo data --step 12300 + # Show distribution tensors in a readable table -aimx trace distribution "distribution.name == 'weights'" --repo data +aimx trace distribution "distribution.name == 'weights'" --repo data --table # Export distribution histograms for scripting aimx trace distribution "distribution.name == 'weights'" --repo data --csv diff --git a/skills/aimx/SKILL.md b/skills/aimx/SKILL.md index 7a2bb9a..5c17bcf 100644 --- a/skills/aimx/SKILL.md +++ b/skills/aimx/SKILL.md @@ -56,13 +56,22 @@ effects, and propose the next experiment from concrete Aim data. aimx trace "() and metric.name == 'loss'" --repo --json --tail 50 ``` -6. Collect image metadata when qualitative outputs matter: +6. Inspect distribution traces when weight, activation, or gradient histograms + matter. Prefer JSON/CSV for automation; use the default visual output for + human terminal inspection. + + ```bash + aimx trace distribution "" --repo --json --tail 5 + aimx trace distribution "distribution.name != ''" --repo --step 12300 + ``` + +7. Collect image metadata when qualitative outputs matter: ```bash aimx query images "images" --repo --json --head 20 ``` -7. Emit a compact `log_experiment` record containing: +8. Emit a compact `log_experiment` record containing: ```json { @@ -71,6 +80,7 @@ effects, and propose the next experiment from concrete Aim data. "params": {}, "metric_summary": {}, "trace_evidence": {}, + "distribution_evidence": {}, "image_evidence": {}, "interpretation": { "best_runs": [], @@ -88,6 +98,11 @@ effects, and propose the next experiment from concrete Aim data. - Treat `aimx query metrics` as summary data: `last`, `min`, `max`, and step counts. Use `aimx trace --json` when shape, stability, divergence, or late improvement matters. +- Use `aimx trace distribution --json` or `--csv` for automated histogram + evidence. The unflagged distribution command is a non-interactive terminal + visual that lists matched distributions, selects the first non-empty series, + and renders a current-step histogram plus step-by-bin heatmap. `--step N` + affects only this visual mode and falls back to the nearest tracked step. - For minimization metrics such as loss or error, compare `min.value` and the corresponding step. For maximization metrics such as accuracy, F1, AUC, or IoU, compare `max.value`. diff --git a/skills/aimx/references/aimx-cli.md b/skills/aimx/references/aimx-cli.md index 48dd125..d43d54c 100644 --- a/skills/aimx/references/aimx-cli.md +++ b/skills/aimx/references/aimx-cli.md @@ -72,6 +72,14 @@ Metric expressions combine run fields with metric fields: (run.hash == 'eca37394') and metric.name != '' ``` +Distribution expressions combine run fields with distribution fields: + +```text +(run.experiment == 'cloud-segmentation') and distribution.name != '' +distribution.name == 'head/gradients/head.0.bias' +distribution.context.kind == 'weights' +``` + Short run hashes are expanded by `aimx` where supported. ## Params @@ -182,6 +190,58 @@ JSON shape: If no metrics match, current `aimx trace --json` may print a text message instead of JSON. Treat that as no trace evidence rather than a parsing failure. +## Distribution Traces + +Use distribution traces when histogram shape matters, such as weights, +activations, gradients, or other Aim distribution sequences. + +For automation, keep using explicit structured modes: + +```bash +aimx trace distribution "" --repo --json +aimx trace distribution "" --repo --csv --tail 5 +aimx trace distribution "" --repo --table --head 2 +``` + +JSON shape: + +```json +[ + { + "run": { + "hash": "full-run-hash", + "experiment": "experiment-name", + "name": "run-name" + }, + "distribution": "head/gradients/head.0.bias", + "context": {"kind": "gradients"}, + "count": 2, + "points": [ + { + "step": 300, + "epoch": 0.0, + "bin_edges": [-1.0, 0.0, 1.0], + "weights": [0.0, 2.0] + } + ] + } +] +``` + +For human terminal inspection, omit the output-mode flag: + +```bash +aimx trace distribution "distribution.name != ''" --repo +aimx trace distribution "distribution.name != ''" --repo --step 12300 +``` + +Default distribution output is deterministic, non-interactive text. It lists +matched distribution names, selects the first non-empty series, renders a +current-step histogram, and renders a step-by-bin heatmap. `--step N` selects +the visual histogram step; if the step is absent, `aimx` labels the nearest +tracked step used. `--step` does not filter `--table`, `--csv`, or `--json` +outputs. + ## Images Use images for qualitative checks such as sample predictions, masks, generated @@ -223,6 +283,8 @@ Recommended fields for autoresearch output: - `params`: selected hyperparameters and model identifiers per run. - `metric_summary`: objective metric summaries per run and context. - `trace_evidence`: sampled value arrays for decisive metrics. +- `distribution_evidence`: selected histogram payloads, visual inspection notes, + or structured distribution rows for weight/gradient analysis. - `image_evidence`: image row counts and representative contexts. - `ranking`: best run per objective, objective direction, and tie-breakers. - `regressions`: runs worse than baseline, incomplete runs, missing metrics, or diff --git a/specs/005-distribution-trace-visual/checklists/requirements.md b/specs/005-distribution-trace-visual/checklists/requirements.md new file mode 100644 index 0000000..2e3b797 --- /dev/null +++ b/specs/005-distribution-trace-visual/checklists/requirements.md @@ -0,0 +1,36 @@ +# Specification Quality Checklist: Distribution Trace Visual + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-04-30 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- Validation passed after initial review. The spec deliberately treats command names and flags as user-facing product surface, while avoiding implementation library, module, and code-structure details. +- Implementation verification completed on 2026-04-30. Quickstart sections 3-9 were exercised against the contributor-local `data/` Aim repository where distributions exist; default visual, exact `--step`, nearest-step fallback, `--table`, `--json`, `--csv`, and no-match behavior all exited successfully when histogram data was present. +- Regression verification passed with `uv run pytest tests/unit/test_trace_helpers.py tests/unit/test_trace_distribution_views.py tests/integration/test_trace_command.py tests/contract/test_trace_contract.py -q`, passthrough/missing-dependency checks, and a fresh full-suite run with `uv run pytest -vv --durations=25` (`297 passed, 15 warnings in 34.12s`). diff --git a/specs/005-distribution-trace-visual/contracts/cli-output.md b/specs/005-distribution-trace-visual/contracts/cli-output.md new file mode 100644 index 0000000..5b86998 --- /dev/null +++ b/specs/005-distribution-trace-visual/contracts/cli-output.md @@ -0,0 +1,141 @@ +# CLI Output Contract: `aimx trace distribution` + +**Feature**: `005-distribution-trace-visual` + +This contract defines the observable CLI behavior for distribution trace +visualization and exports. + +## Command Shape + +```text +aimx trace distribution [--repo ] + [--steps start:end] + [--head N] [--tail N] [--every K] + [--step N] + [--width W] [--height H] [--no-color] + [--table | --csv | --json] +``` + +## Owned Options + +| Option | Applies To | Behavior | +|--------|------------|----------| +| `--repo ` | all modes | Uses a local Aim repository root or `.aim` directory. Defaults to the current directory. | +| `--steps start:end` | all modes | Filters distribution points by inclusive tracked step range before sampling and rendering. | +| `--head N` | all modes | Keeps the first `N` points per matched series before rendering or export. | +| `--tail N` | all modes | Keeps the last `N` points per matched series before rendering or export. | +| `--every K` | all modes | Keeps every `K`th point per matched series before rendering or export. | +| `--step N` | default visual mode | Chooses the current-step histogram step; nearest tracked step is used when no exact match exists. | +| `--width W` | default visual mode | Sets preferred chart width when supported by the renderer. | +| `--height H` | default visual mode | Sets preferred chart height when supported by the renderer. | +| `--no-color` | human-readable modes | Disables ANSI styling where applicable. | +| `--table` | explicit table mode | Emits the existing tensor table and no default visual charts. | +| `--csv` | explicit CSV mode | Emits existing CSV histogram rows and no default visual charts. | +| `--json` | explicit JSON mode | Emits existing JSON series payload and no default visual charts. | + +## Query Expression + +The expression is passed to Aim's distribution-query evaluator after existing +short `run.hash` expansion and the documented singular `distribution` alias +normalization. + +Examples: + +```bash +aimx trace distribution "distribution.name != ''" --repo data +aimx trace distribution "distribution.name == ''" --repo data --step +aimx trace distribution "distribution.context.kind == 'weights'" --repo data --json +``` + +Replace `` and `` with values present in your Aim repository; the commands illustrate syntax only. + +## Default Visual Output + +Default output is non-interactive terminal text. It contains these sections in +order: + +1. Distribution name list +2. Selected distribution context and current-step label +3. Current-step histogram +4. Step-by-bin heatmap + +The distribution name list must show every matched distribution name in +collection order. The selected item must be visibly marked. When more than one +series matches, only the selected series is visualized. + +The selected series is the first non-empty matched series after filtering and +sampling. The default selected step is the first available point in that +series. When `--step N` is provided: + +- if `N` is tracked, display `N` +- if `N` is not tracked, display the nearest tracked step +- if two steps are equally close, display the lower step +- always label the actual displayed step + +## Table Output + +`--table` keeps the existing distribution tensor table workflow: + +```text + · · · points + STEP EPOCH TENSOR + 300 0 [1, 1, 0, 1, ...] (64 bins) +``` + +This mode must not include the default distribution name list, histogram, or +heatmap. + +## CSV Output + +`--csv` remains parseable CSV with the existing field names: + +```text +run_hash,experiment,distribution,context,step,epoch,bin_edges,weights +``` + +Each data row represents one distribution point. `bin_edges` and `weights` +remain JSON-encoded arrays inside CSV cells. + +## JSON Output + +`--json` remains parseable JSON with the existing top-level shape: a list of +distribution series. + +Each series contains: + +- `run` +- `distribution` +- `context` +- `count` +- `points` + +Each point contains: + +- `step` +- `epoch` +- `bin_edges` +- `weights` + +## Exit Status + +| Condition | Exit Status | Output | +|-----------|-------------|--------| +| Valid default visual query with one or more non-empty matches | `0` | Distribution list, selected histogram, heatmap | +| Valid table, CSV, or JSON query with matches | `0` | Explicit mode output | +| Valid query with zero matches | `0` | Explicit no-matches message or empty structured output if already defined by that mode | +| Filtering removes all data | `0` | Explicit no-data-in-range message | +| Requested visual step is absent but another point exists | `0` | Nearest tracked step rendered and labeled | +| Missing repository path | `2` | Actionable error on stderr | +| Invalid query expression | `2` | Actionable error on stderr | +| Missing or non-integer `--step` value | `2` | Actionable error on stderr | +| Invalid sampling or step-range option | `2` | Actionable error on stderr | + +## Non-Regression Requirements + +- Metric trace default plot, table, CSV, and JSON outputs remain unchanged. +- Distribution `--table`, `--csv`, and `--json` outputs keep existing field + names and parseability. +- Existing `--steps`, `--head`, `--tail`, `--every`, `--width`, `--height`, and + `--no-color` parsing behavior remains compatible except for the documented + addition of `--step`. +- Commands outside owned `aimx` surfaces continue to delegate to native `aim`. diff --git a/specs/005-distribution-trace-visual/data-model.md b/specs/005-distribution-trace-visual/data-model.md new file mode 100644 index 0000000..dc46d15 --- /dev/null +++ b/specs/005-distribution-trace-visual/data-model.md @@ -0,0 +1,184 @@ +# Phase 1 Data Model: Distribution Trace Visual + +**Feature**: `005-distribution-trace-visual` + +## Trace Distribution Invocation + +Represents one CLI request to inspect distribution traces. + +**Fields**: + +- `target`: literal `distribution` +- `expression`: Aim distribution query expression supplied by the user +- `repo_path`: local repository root or `.aim` path +- `mode`: one of default visual, table, CSV, or JSON +- `step_slice`: optional inclusive step range filter +- `selected_step`: optional visual step requested with `--step N` +- `head`, `tail`, `every`: optional sampling controls +- `width`, `height`: optional display controls for visual output +- `no_color`: boolean terminal styling control + +**Validation Rules**: + +- `expression` must be present for distribution traces. +- `repo_path` must exist and is normalized consistently with existing trace + commands. +- `--step` requires an integer value. +- Sampling and filtering controls are applied before visual selection. +- `selected_step` affects only default visual output; structured export modes + preserve their existing full-series behavior. + +## Distribution Match + +Represents one distribution series returned by the user's expression. + +**Fields**: + +- `run`: run identity with hash, experiment, optional name, and optional + creation time +- `name`: distribution name +- `context`: distribution context key-value mapping +- `points`: ordered list of distribution points + +**Relationships**: + +- One Trace Distribution Invocation produces zero or more Distribution Matches. +- One Distribution Match contains zero or more Distribution Points. +- Distribution Matches form the Distribution Name List in the default visual + output. + +**Validation Rules**: + +- Match order is preserved from the collection pipeline so default selection is + deterministic. +- Empty `points` are allowed but are skipped for selected visual rendering when + a later non-empty match exists. +- Context values are displayed compactly in human-readable output and remain + preserved in structured output. + +## Distribution Point + +Represents one tracked histogram at one step. + +**Fields**: + +- `step`: tracked training step +- `epoch`: optional epoch value +- `bin_edges`: ordered numeric bin edges +- `weights`: ordered numeric histogram weights + +**Relationships**: + +- Belongs to one Distribution Match. +- One selected Distribution Point powers the current-step histogram. +- All displayed points in the selected series power the step-by-bin heatmap. + +**Validation Rules**: + +- `weights` may be all zeros. +- `bin_edges` and `weights` must be paired so the histogram can label bins + coherently. +- Single-point series are valid and produce a single-step heatmap. + +## Distribution Name List + +The ordered human-readable list of matched distribution names shown before the +default visual charts. + +**Fields**: + +- `items`: ordered names and compact context labels +- `selected_index`: index of the distribution selected for visual rendering +- `selected_label`: selected distribution display label + +**Relationships**: + +- Built from Distribution Matches. +- References the Selected Distribution by index and label. + +**Validation Rules**: + +- All matched distribution names are listed. +- The selected item is visibly marked. +- Duplicate names remain distinguishable by context or run label when present. + +## Selected Distribution + +The distribution series rendered by default visual mode. + +**Fields**: + +- `series`: selected Distribution Match +- `selected_point`: resolved Distribution Point for the current-step histogram +- `requested_step`: optional step requested by the user +- `resolved_step`: actual tracked step displayed +- `step_resolution`: exact, nearest-lower, nearest-higher, or default-first + +**Relationships**: + +- Derived from the Distribution Name List and available Distribution Points. +- Supplies data to Histogram View and Heatmap View. + +**Validation Rules**: + +- If `requested_step` exactly matches a point, select that point. +- If `requested_step` does not match, select the point with minimum absolute + distance to the requested value. +- If two points are equally close, select the lower step. +- If no non-empty distribution exists after filtering and sampling, visual + rendering is skipped and the command reports no data. + +## Histogram View + +The current-step chart for the selected distribution. + +**Fields**: + +- `title`: selected distribution name and resolved step +- `x_values`: bin centers or labels derived from bin edges +- `weights`: histogram weights for the selected point +- `step_label`: actual tracked step displayed +- `request_note`: optional note when nearest-step fallback was used + +**Validation Rules**: + +- Must render even when all weights are zero. +- Must label the actual displayed step. +- Must remain deterministic when terminal color is disabled. + +## Heatmap View + +The cross-step chart for the selected distribution. + +**Fields**: + +- `step_values`: ordered tracked steps after filtering and sampling +- `bin_values`: bin labels or centers +- `weight_matrix`: rows or columns of histogram weights aligned with steps and + bins +- `color_scale_label`: textual scale or legend for weight intensity + +**Validation Rules**: + +- Must include every displayed point in the selected distribution. +- Must degrade to a single-step heatmap for single-point series. +- Must not mutate or normalize stored histogram data in the repository. + +## Structured Export Output + +The explicit table, CSV, or JSON output selected by mode flags. + +**Fields**: + +- Existing distribution table fields: step, epoch, tensor summary +- Existing CSV fields: run hash, experiment, distribution, context, step, + epoch, bin edges, weights +- Existing JSON fields: run, distribution, context, count, points with bin + edges and weights + +**Validation Rules**: + +- Explicit structured modes do not include the new default visual name list, + histogram, or heatmap. +- CSV and JSON remain parseable with the existing field names. +- Table mode remains a tensor inspection view. diff --git a/specs/005-distribution-trace-visual/plan.md b/specs/005-distribution-trace-visual/plan.md new file mode 100644 index 0000000..4f86a67 --- /dev/null +++ b/specs/005-distribution-trace-visual/plan.md @@ -0,0 +1,161 @@ +# Implementation Plan: Distribution Trace Visual + +**Branch**: `005-distribution-trace-visual` | **Date**: 2026-04-30 | **Spec**: [spec.md](/Users/blizhan/data/code/github/aimx/specs/005-distribution-trace-visual/spec.md) +**Input**: Feature specification from `/Users/blizhan/data/code/github/aimx/specs/005-distribution-trace-visual/spec.md` + +## Summary + +Change the owned `aimx trace distribution` default mode from a tensor table to +a non-interactive terminal visual summary that mirrors the Aim web +Distributions tab: list all matched distribution names, mark the first +non-empty match as selected, render a current-step histogram, and render a +step-by-bin heatmap for that selected series. Add `--step N` for visual step +selection using nearest tracked-step fallback. Preserve existing `--table`, +`--csv`, and `--json` distribution outputs without intentional schema changes. +The implementation stays read-only, uses existing trace command/data/rendering +boundaries, and introduces no new runtime dependency. + +## Technical Context + +**Language/Version**: Python 3.12 for development, runtime support `>=3.10,<3.13` +**Primary Dependencies**: Python standard library, `numpy>=1.24`, `rich>=13.7`, `plotext>=5.3`, existing Aim SDK usage for owned trace commands; no new runtime dependency planned +**Storage**: Existing local Aim repositories on disk, read-only; distribution histogram points are read from Aim sequence data under `.aim` +**Testing**: pytest unit, integration, and contract suites; integration and contract coverage exercises real Aim distribution queries against `tests/conftest.py`'s `sample_repo_root` (`Path("data")`) when matching sequences exist and skips cleanly otherwise so CI stays green without extra fixtures +**Target Platform**: Terminal-first CLI for local shells, SSH sessions, scripts, and CI on Python-supported platforms +**Project Type**: Single-project Python CLI application +**Performance Goals**: Default visual rendering stays bounded to one command invocation for realistic repositories with multiple matched distributions and many tracked histogram steps (such as training runs logged from TensorBoard imports), remaining readable on a standard terminal width +**Constraints**: Read-only; preserve native Aim passthrough behavior; preserve existing distribution `--table`, `--csv`, and `--json` output contracts; keep default output non-interactive; avoid adding GUI or TUI dependencies +**Scale/Scope**: One owned command path (`trace distribution`), one visual-only option (`--step N`), default distribution visual renderer, help/README updates, and focused unit/integration/contract tests + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +- [x] Safe coexistence: default distribution visual rendering only reads local + Aim distribution sequence data; no normal-path change modifies the + installed `aim` package, replaces the native `aim` executable, or mutates + `.aim` repo data. +- [x] Ownership boundary: `aimx` already owns `aimx trace distribution`; the + plan adds owned default rendering behavior and the owned `--step` option + for that command path only. Native `aim` passthrough remains unchanged. +- [x] Read-only default: all behavior is inspection-only and uses no Aim + mutation APIs. +- [x] CLI-first contract: the default output is deterministic non-interactive + terminal text, while existing `--table`, `--csv`, and `--json` modes + remain available for diagnostics and automation. +- [x] Compatibility plan: design reuses current distribution collection, + filtering, sampling, repo normalization, and trace error handling; tests + cover default visual output plus non-regression for existing modes. + +## Project Structure + +### Documentation (this feature) + +```text +/Users/blizhan/data/code/github/aimx/specs/005-distribution-trace-visual/ +├── plan.md +├── research.md +├── data-model.md +├── quickstart.md +├── contracts/ +│ └── cli-output.md +├── checklists/ +│ └── requirements.md +└── tasks.md # created later by /speckit.tasks +``` + +### Source Code (repository root) + +```text +/Users/blizhan/data/code/github/aimx/ +├── README.md +├── src/aimx/ +│ ├── commands/ +│ │ ├── help.py # update trace distribution usage text +│ │ └── trace.py # parse --step and route default distribution mode +│ ├── aim_bridge/ +│ │ └── metric_stats.py # keep DistributionSeries/Point filtering and sampling helpers +│ └── rendering/ +│ └── trace_views.py # add default distribution visual renderer +└── tests/ + ├── contract/ + │ └── test_trace_contract.py # add distribution output contract coverage + ├── integration/ + │ └── test_trace_command.py # add distribution CLI coverage guarded by repo fixtures + └── unit/ + ├── test_trace_distribution_views.py + └── test_trace_helpers.py +``` + +**Structure Decision**: Keep the existing single-project CLI layout. The trace +command remains the orchestration boundary for parsing, repo normalization, +filtering, sampling, and mode selection. The Aim bridge keeps returning +`DistributionSeries` records. The visual work belongs in +`rendering/trace_views.py` next to existing metric plots and distribution +table/CSV/JSON renderers. + +## Phase 0: Research Summary + +Phase 0 decisions are captured in [research.md](/Users/blizhan/data/code/github/aimx/specs/005-distribution-trace-visual/research.md). Key outcomes: + +- Keep `aimx trace distribution` as the user-facing command and change only its + default mode; no TUI, no new top-level command, and no new selector command. +- Reuse existing `DistributionSeries` / `DistributionPoint` data and filtering + behavior, selecting the first non-empty series after expression matching, + step filtering, and sampling. +- Add `--step N` as a visual-only selector. Exact matches are used directly; + otherwise the nearest tracked step is selected, with lower step winning ties. +- Reuse existing plotting/rendering dependencies. `plotext` is available for + histogram and heatmap-style terminal output, while `rich` can frame labels + and the matched-name list consistently with existing views. +- Preserve `--table`, `--csv`, and `--json` as non-visual modes with unchanged + data shapes. + +## Phase 1: Design Summary + +- Extend `TraceInvocation` with `selected_step: int | None` and parse `--step N` + in `parse_trace_invocation`. Reject missing or non-integer values with exit + code `2` through the existing error path. +- Treat `--step` as relevant to default distribution visual mode. `--table`, + `--csv`, and `--json` keep their current full-series behavior even when + `--step` is supplied. +- Add a distribution visual render path in `_render_distribution_trace`: JSON + and CSV keep current renderers, table keeps the current tensor-table renderer, + and default plot mode calls a new visual renderer. +- Implement a visual selection helper that receives filtered/sampled + `DistributionSeries` records, builds the ordered name list, selects the first + non-empty series, resolves the selected step, and returns a render model for + histogram and heatmap output. +- Implement the default visual renderer with three sections: + - `Distributions`: ordered matched names with a selected marker and compact + context for the selected item. + - `Histogram`: selected distribution name, selected step label, and + Rich-rendered blue-gradient bin-weight histogram for the resolved step. + - `Heatmap`: step-by-bin view for the selected distribution across available + displayed points, using the same web-style blue intensity scale. +- Keep no-match and no-data messages on the existing successful, non-throwing + path. Add specific tests for empty points, single-step series, all-zero + weights, and nearest-step tie behavior. +- Update README/help text so default distribution output is documented as + visual, while tensor-table usage moves behind explicit `--table`. + +## Post-Design Constitution Check + +- [x] Safe coexistence: design reads distribution query results and histogram + arrays only; no installed Aim package, executable, or repository data is + modified. +- [x] Ownership boundary: all new behavior is contained inside the existing + `aimx trace distribution` command path and its documented options. +- [x] Read-only default: visual selection, plotting, and export rendering are + derived from in-memory query results. +- [x] CLI-first contract: [contracts/cli-output.md](/Users/blizhan/data/code/github/aimx/specs/005-distribution-trace-visual/contracts/cli-output.md) + defines default visual output, structured modes, exit statuses, and + non-regression expectations. +- [x] Compatibility: existing trace command tests remain part of validation; + new integration tests query real Aim repositories when distributions exist + and assert no schema change for table, CSV, or JSON modes. + +## Complexity Tracking + +No constitution violations; no exceptional complexity requires justification. +The feature uses existing project boundaries and dependencies. diff --git a/specs/005-distribution-trace-visual/quickstart.md b/specs/005-distribution-trace-visual/quickstart.md new file mode 100644 index 0000000..73e4145 --- /dev/null +++ b/specs/005-distribution-trace-visual/quickstart.md @@ -0,0 +1,155 @@ +# Quickstart: Distribution Trace Visual + +**Feature**: `005-distribution-trace-visual` + +## 1. Prepare The Environment + +```bash +uv sync +``` + +Point `--repo` at an Aim repository root that contains `.aim` metadata. This +guide uses the contributor-local checkout rooted at `data/` (see `AGENTS.md`): + +```text +/Users/blizhan/data/code/github/aimx/data/.aim +``` + +If your checkout does not contain distribution histogram sequences yet, most +CLI sections below still validate `--table`, `--csv`, `--json`, and no-match +behavior; default visualization sections require at least one matched +distribution series. + +## 2. Inspect Available Steps (Optional) + +Pick a tracked step value from your repository before trying `--step`: + +```bash +uv run aimx trace distribution "distribution.name != ''" \ + --repo data --json --head 1 | python - <<'PY' +import json, sys +payload = json.load(sys.stdin) +if not payload: + raise SystemExit("No distribution series matched this repository.") +steps = sorted({point["step"] for series in payload for point in series["points"]}) +print("sample steps:", steps[:5], "... total", len(steps)) +PY +``` + +Use any printed step as `` below. + +## 3. Render The Default Distribution Visual + +```bash +uv run aimx trace distribution "distribution.name != ''" --repo data +``` + +Expected result: + +- exit code `0` when distributions exist (otherwise Aim reports no matches) +- output includes a `Distributions` name list when matches exist +- the first matched distribution is marked as selected +- output labels the current displayed step +- output includes a current-step histogram +- output includes a step-by-bin heatmap +- command does not prompt for keyboard or mouse input + +## 4. Select A Specific Step + +```bash +uv run aimx trace distribution "distribution.name != ''" \ + --repo data --step +``` + +Expected result: + +- exit code `0` +- current-step histogram labels step `` +- heatmap still covers the displayed points for the selected series + +## 5. Select A Nearest Step + +Pick two consecutive tracked steps `LOWER` and `HIGHER` from section 2, choose a +non-tracked integer `REQUESTED` strictly between them, then run: + +```bash +uv run aimx trace distribution "distribution.name != ''" \ + --repo data --step +``` + +Expected result: + +- exit code `0` +- output labels the actual tracked step chosen (nearest tracked step, lower + step wins on ties) +- no traceback is printed + +## 6. Keep Tensor Table Output + +```bash +uv run aimx trace distribution "distribution.name != ''" --repo data --table --head 2 +``` + +Expected result: + +- exit code `0` +- output contains `STEP`, `EPOCH`, and `TENSOR` +- output does not include the default visual histogram or heatmap sections + +## 7. Keep JSON Output + +```bash +uv run aimx trace distribution "distribution.name != ''" --repo data --json --head 1 +``` + +Expected result: + +- valid JSON +- top-level value is a list +- each series contains `run`, `distribution`, `context`, `count`, and `points` +- each point contains `step`, `epoch`, `bin_edges`, and `weights` + +## 8. Keep CSV Output + +```bash +uv run aimx trace distribution "distribution.name != ''" --repo data --csv --head 1 +``` + +Expected result: + +- valid CSV +- header includes `run_hash`, `experiment`, `distribution`, `context`, + `step`, `epoch`, `bin_edges`, and `weights` + +## 9. No-Match Behavior + +```bash +uv run aimx trace distribution "distribution.name == 'missing-distribution'" --repo data +``` + +Expected result: + +- exit code `0` +- output reports no matching distributions +- no traceback is printed + +## 10. Test Commands + +```bash +uv run pytest tests/unit/test_trace_helpers.py tests/unit/test_trace_distribution_views.py -q +uv run pytest tests/integration/test_trace_command.py -q +uv run pytest tests/contract/test_trace_contract.py -q +uv run pytest -q +``` + +## Verification Notes + +- Automated integration and contract suites skip distribution scenarios when the + configured `sample_repo_root` repository has no histogram data, which keeps CI + green without checking in custom fixtures. +- When your local `data/` repository contains distributions, the commands above + provide the same observability checks that previously relied on ad hoc test + directories. +- `uv run` may emit an environment warning about a missing + `aimx-*.dist-info/RECORD` during editable reinstall; commands and tests should + still complete successfully. diff --git a/specs/005-distribution-trace-visual/research.md b/specs/005-distribution-trace-visual/research.md new file mode 100644 index 0000000..97d36a2 --- /dev/null +++ b/specs/005-distribution-trace-visual/research.md @@ -0,0 +1,121 @@ +# Phase 0 Research: Distribution Trace Visual + +**Feature**: `005-distribution-trace-visual` +**Date**: 2026-04-30 + +## Decision: Keep The Existing `trace distribution` Command + +Use `aimx trace distribution ` as the command surface and change +only the default mode for distribution traces. + +**Rationale**: The project already owns the trace distribution command path, +and users already query distributions through Aim-style expressions there. +Changing the default mode keeps the feature discoverable and aligns with the +existing `aimx trace ` behavior, where the unflagged command +is visual and explicit flags select table or structured output. + +**Alternatives considered**: + +- Add a new top-level distribution command: rejected because it duplicates the + existing owned trace surface and fragments query/filtering behavior. +- Add an interactive terminal UI: rejected because the requested behavior is + non-interactive and the constitution prioritizes predictable CLI workflows. +- Add a separate name selector command: rejected for v1 because the matched + name list already gives users the expression targets they need. + +## Decision: Select The First Non-Empty Matched Series By Default + +Default visual mode lists all matched distribution names but renders only the +first non-empty series after expression matching, step filtering, and sampling. + +**Rationale**: This mirrors the Aim web page's default expanded item while +preventing large terminal output when an expression matches many names. The +list of matched names preserves discoverability and tells users how to narrow +their expression when they want another series. + +**Alternatives considered**: + +- Render every matched distribution: rejected because terminal output becomes + noisy when an expression matches many series (for example repositories that + import wide TensorBoard histogram tiles). +- Refuse to render until the user narrows to one name: rejected because it + makes the default command less useful than the web page. +- Select the last matched distribution: rejected because it is less consistent + with the web UI's first expanded item. + +## Decision: Add `--step N` For Visual Step Selection + +Add `--step N` so users can choose the current-step histogram in default visual +mode. Exact tracked steps are used directly. If the requested step is not +tracked, the nearest tracked step is used and the actual displayed step is +labeled. If two tracked steps are equally near, choose the earlier step. + +**Rationale**: The default step should match the web page's first step, but +terminal users often need to inspect a later training step without opening the +web UI. Nearest-step fallback keeps the command forgiving while still being +deterministic. + +**Alternatives considered**: + +- Always use the first tracked step: rejected because it prevents targeted + debugging from the CLI. +- Always use the last tracked step: rejected because it diverges from the web + page's default behavior that motivated the request. +- Require exact step matches only: rejected because users may not know the + repository's tracked step interval. + +## Decision: Keep `--step` Visual-Only + +`--step` affects only default visual rendering. `--table`, `--csv`, and +`--json` continue to emit the filtered/sampled distribution series according +to their existing contracts. + +**Rationale**: Existing table/CSV/JSON behavior is useful precisely because it +exports all available points after filtering and sampling. Applying `--step` to +those modes would be an intentional schema or row-count behavior change and +could surprise scripts. + +**Alternatives considered**: + +- Filter all output modes to the selected step: rejected because it changes + existing export semantics. +- Reject `--step` with non-default modes: rejected because the option can be + harmlessly ignored for compatibility and keeps parser behavior simple. + +## Decision: Reuse Existing Terminal Rendering Dependencies + +Use the current rendering dependencies for default visual output: `plotext` for +histogram/heatmap-style charts and `rich` for labels, list formatting, and +no-color behavior. + +**Rationale**: `plotext` is already used by metric trace plots and provides +histogram, bar, and heatmap/matrix plotting helpers in the local environment. +`rich` is already used for trace tables and query views. Reusing both avoids a +new dependency and keeps output behavior consistent with the rest of `aimx`. + +**Alternatives considered**: + +- Add a dedicated TUI or plotting dependency: rejected because it increases + dependency surface for a static terminal snapshot. +- Hand-roll all plotting with ad hoc string output: rejected because existing + terminal plotting support is already available and tested in trace metrics. +- Generate image files: rejected because the feature should work in shell, SSH, + and CI-style output without file management. + +## Decision: Prefer Local Repositories Like `data/` For Integration Coverage + +Exercise real Aim distribution queries against whatever repository contributors +already mount at `tests/conftest.py`'s `sample_repo_root` (`Path("data")`), +typically `/Users/blizhan/data/code/github/aimx/data/.aim`. + +**Rationale**: Keeping validation anchored on `data/` matches contributor docs, +avoids committing bespoke `.aim` fixtures, and still walks the Aim SDK query path. +pytest skips integration and contract assertions when no distributions exist so +remote CI stays deterministic without shipping histogram data. + +**Alternatives considered**: + +- Require every checkout to ship a curated `.aim` fixture: rejected because it + bloats the repository and duplicates what operators already store locally. +- Rely only on unit fixtures: partially adopted for determinism, but paired with + optional integration coverage whenever local distributions exist. diff --git a/specs/005-distribution-trace-visual/spec.md b/specs/005-distribution-trace-visual/spec.md new file mode 100644 index 0000000..5783972 --- /dev/null +++ b/specs/005-distribution-trace-visual/spec.md @@ -0,0 +1,119 @@ +# Feature Specification: Distribution Trace Visual + +**Feature Branch**: `005-distribution-trace-visual` +**Created**: 2026-04-30 +**Status**: Draft +**Input**: User description: "Modify the current distribution trace command so the default experience more closely matches the Aim web Distributions tab: show which distribution names are available, default to a visual non-interactive output similar to trace metrics, include a current-step histogram and a step-by-bin heatmap, support a step selection option, and preserve existing `--table`, `--csv`, and `--json` outputs." + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Inspect Distribution Visually By Default (Priority: P1) + +An Aim user runs the distribution trace command against a local repository and immediately sees a readable visual summary instead of a tensor table. The output shows the matched distribution names and visualizes the first matched distribution in a way that resembles the Aim web Distributions tab. + +**Why this priority**: This is the core requested workflow and closes the gap between the current terminal output and the web UI. + +**Independent Test**: Run the distribution trace command against a repository with multiple distribution series and no explicit output mode; verify that the command exits successfully, lists matched distribution names, marks the first match as selected, and renders both a current-step histogram and a cross-step heatmap for that selected series. + +**Acceptance Scenarios**: + +1. **Given** a local Aim repository containing multiple distributions, **When** the user runs `aimx trace distribution ` without an output-mode flag, **Then** the output lists the matched distribution names and visually renders only the first matched series. +2. **Given** the selected distribution has data from step 300 through later steps, **When** the user runs the default distribution trace command, **Then** the current-step histogram uses the first available step and labels the actual step displayed. +3. **Given** the selected distribution has values across multiple steps, **When** the user runs the default distribution trace command, **Then** the output includes a step-by-bin heatmap that communicates how the distribution changes over the available steps. + +--- + +### User Story 2 - Choose A Display Step Non-Interactively (Priority: P2) + +An Aim user wants to inspect a specific training step from the terminal without opening the web UI or entering an interactive selector. + +**Why this priority**: Step selection makes the visual output useful for targeted debugging while preserving a single-command, script-friendly workflow. + +**Independent Test**: Run the distribution trace command with a requested step that exists and with one that does not exist; verify that the visual output displays the exact step when available and the nearest tracked step otherwise. + +**Acceptance Scenarios**: + +1. **Given** a selected distribution with a tracked step of 12300, **When** the user runs `aimx trace distribution --step 12300`, **Then** the current-step histogram displays step 12300. +2. **Given** a selected distribution without a tracked step of 1000, **When** the user runs `aimx trace distribution --step 1000`, **Then** the current-step histogram displays the nearest tracked step and labels the actual step used. +3. **Given** two tracked steps are equally close to the requested step, **When** the user runs the command with that requested step, **Then** the earlier tracked step is selected and labeled. + +--- + +### User Story 3 - Keep Existing Scriptable Outputs (Priority: P3) + +An Aim user or automation already depends on distribution tensor output in table, CSV, or JSON form and should not lose those workflows when the default output changes. + +**Why this priority**: `aimx` is CLI-first and scriptable; visual defaults must not break existing export and diagnostic usage. + +**Independent Test**: Run distribution trace commands with `--table`, `--csv`, and `--json`; verify that each mode remains available, keeps the same data shape as before, and does not emit the new default visual summary. + +**Acceptance Scenarios**: + +1. **Given** a distribution query with matching data, **When** the user runs the command with `--table`, **Then** the output remains a tensor table with step, epoch, and tensor content. +2. **Given** a distribution query with matching data, **When** the user runs the command with `--csv`, **Then** the output remains parseable CSV with distribution histogram fields. +3. **Given** a distribution query with matching data, **When** the user runs the command with `--json`, **Then** the output remains parseable JSON with each distribution's points, bin edges, and weights. + +### Edge Cases + +- If the expression matches no distributions, the command exits successfully and reports that no matching distributions were found. +- If step filtering or sampling removes all points from every matched series, the command exits successfully and reports that no data remains in the requested step range. +- If a matched distribution has a name and context but no points, it is listed only when relevant to the mode and is not selected for visual rendering unless no non-empty series exist. +- If the selected distribution contains a single tracked step, the histogram is still shown and the heatmap degrades to a single-step view. +- If the selected distribution has empty or all-zero histogram weights at the selected step, the histogram and heatmap still render with clear labels rather than failing. +- If terminal output is captured in a non-interactive environment, the default visual output remains deterministic text output and does not require keyboard or mouse interaction. +- If `--step` is provided with a non-default output mode, the export modes keep their existing full-data behavior; the step selection only affects the default visual view. + +## Constitution Alignment *(mandatory)* + +- **CA-001 Safety & Mutability**: This feature is read-only. It inspects distribution data from existing Aim repositories and must not modify the installed Aim package or mutate `.aim` repository data. +- **CA-002 Ownership Boundary**: `aimx` owns the existing `aimx trace distribution` command path and the new default visual behavior for that path. Native Aim passthrough remains unchanged for all unowned command paths. +- **CA-003 CLI & Output Contract**: The command remains usable in local shells, SSH sessions, captured logs, and CI. It provides a human-readable default visual output and preserves existing machine-readable `--csv` and `--json` outputs. + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: The default `aimx trace distribution ` output MUST list all matched distribution names before rendering the selected distribution. +- **FR-002**: The default output MUST identify which matched distribution is selected for visual rendering. +- **FR-003**: When multiple distributions match, the default output MUST select the first matched distribution for visual rendering. +- **FR-004**: The default visual output MUST include a histogram for one selected step of the selected distribution. +- **FR-005**: The default selected step MUST be the first available step after expression matching, step filtering, and sampling are applied. +- **FR-006**: Users MUST be able to request a selected visual step with `--step N` in default visual mode. +- **FR-007**: If the requested visual step is not tracked, the command MUST use the nearest tracked step and label the actual step displayed. +- **FR-008**: The default visual output MUST include a step-by-bin heatmap for the selected distribution across the available displayed steps. +- **FR-008a**: When color is enabled, the default visual output MUST use a Rich-rendered blue gradient inspired by the Aim web Distributions tab rather than the metric plot's high-contrast terminal palette. +- **FR-009**: The default visual output MUST remain non-interactive and MUST complete from a single command invocation. +- **FR-010**: The existing `--table` output mode MUST remain available and keep the existing tensor-table workflow. +- **FR-011**: The existing `--csv` output mode MUST remain available and keep parseable distribution histogram export data. +- **FR-012**: The existing `--json` output mode MUST remain available and keep parseable distribution histogram export data. +- **FR-013**: Existing filtering and sampling options, including step ranges and head, tail, or interval sampling, MUST continue to apply before default visual rendering. +- **FR-014**: Existing display controls such as width, height, and no-color behavior MUST remain accepted where they are already part of the trace command surface. +- **FR-015**: Error and empty-result messages MUST remain concise, non-destructive, and free of traceback-style output for expected user-facing conditions. + +### Key Entities + +- **Distribution Match**: A distribution series returned by the user's expression, including run identity, name, context, and tracked points. +- **Distribution Name List**: The ordered set of matched distribution names shown to the user so they can see what the expression found. +- **Distribution Point**: A tracked step and optional epoch with histogram bin edges and weights. +- **Selected Distribution**: The first non-empty distribution series chosen for default visual rendering. +- **Selected Step**: The tracked step used for the current-step histogram, either the default first step or the nearest tracked step to the user's requested value. +- **Visual Distribution Output**: The non-interactive default output containing the name list, current-step histogram, and step-by-bin heatmap. +- **Structured Export Output**: The table, CSV, or JSON output selected by explicit output-mode flags. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: A user can run a default distribution trace command against a repository with at least 16 matched distributions and identify the available names and selected visualized name in one command result. +- **SC-002**: For a selected distribution with at least 40 tracked steps and 64 histogram bins, the default command result shows both a current-step histogram and a cross-step heatmap without requiring follow-up interaction. +- **SC-003**: A requested visual step that does not exactly exist resolves to a labeled tracked step in 100% of valid default visual runs. +- **SC-004**: Existing `--table`, `--csv`, and `--json` distribution commands continue to produce parseable output with zero intentional schema changes. +- **SC-005**: Expected empty-result and invalid-step-range conditions complete without repository mutation and without traceback-style output. + +## Assumptions + +- Users already know how to narrow distribution results with the existing expression syntax when they want a distribution other than the first match. +- The first matched distribution is an acceptable default selection because it mirrors the web UI's default expanded item behavior. +- The default visual output is intended as a static terminal snapshot, not as an interactive terminal UI. +- Step selection affects only the default visual view; structured exports remain full-data outputs controlled by expression, filtering, and sampling options. +- Developers may validate multi-name distribution visuals against any local Aim repository that contains matching distribution sequences (for example the repository rooted at `data/` described in contributor docs); CI keeps reliability via deterministic unit fixtures while integration coverage skips when no distributions exist. diff --git a/specs/005-distribution-trace-visual/tasks.md b/specs/005-distribution-trace-visual/tasks.md new file mode 100644 index 0000000..1a82dad --- /dev/null +++ b/specs/005-distribution-trace-visual/tasks.md @@ -0,0 +1,241 @@ +# Tasks: Distribution Trace Visual + +**Input**: Design documents from `/Users/blizhan/data/code/github/aimx/specs/005-distribution-trace-visual/` +**Prerequisites**: plan.md, spec.md, research.md, data-model.md, contracts/cli-output.md, quickstart.md + +**Tests**: Test tasks are included because the feature changes an owned CLI +default, adds a new CLI option, and must preserve existing output contracts, +read-only behavior, safe failure modes, and native Aim passthrough boundaries. + +**Organization**: Tasks are grouped by user story so each story can be +implemented and tested as an independently useful increment. + +## Format: `[ID] [P?] [Story] Description` + +- **[P]**: Can run in parallel because it touches different files or depends + only on completed foundation work +- **[Story]**: Maps task to a user story (`US1`, `US2`, `US3`) +- Every task includes exact repository-relative file paths + +## Phase 1: Setup (Shared Infrastructure) + +**Purpose**: Prepare distribution-specific test helpers and validation entry +points without changing runtime behavior yet. + +- [X] T001 Create reusable multi-step `DistributionSeries` and `DistributionPoint` fixture helpers in `tests/unit/test_trace_distribution_views.py` +- [X] T002 [P] Add distribution integration helpers guarded by repository fixtures in `tests/integration/test_trace_command.py` + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +**Purpose**: Add shared parser and visual-selection primitives required by the +default visual output and `--step` behavior. + +**Critical**: No user story work should begin until this phase is complete. + +- [X] T003 [P] Add parser unit tests for accepted `--step`, missing `--step` value, and non-integer `--step` value in `tests/unit/test_trace_helpers.py` +- [X] T004 Extend `TraceInvocation` and `parse_trace_invocation()` with `selected_step: int | None` and `--step N` validation in `src/aimx/commands/trace.py` +- [X] T005 [P] Add unit tests for first non-empty distribution selection, default first point selection, no non-empty series handling, single-step series, and all-zero weights in `tests/unit/test_trace_distribution_views.py` +- [X] T006 Implement distribution visual selection helpers for selected series, selected point, and histogram/heatmap render inputs in `src/aimx/rendering/trace_views.py` +- [X] T007 Run `uv run pytest tests/unit/test_trace_helpers.py tests/unit/test_trace_distribution_views.py -q` and fix foundational failures in `src/aimx/commands/trace.py` and `src/aimx/rendering/trace_views.py` + +**Checkpoint**: Parser and visual-selection primitives are ready; user story implementation can start. + +--- + +## Phase 3: User Story 1 - Inspect Distribution Visually By Default (Priority: P1) MVP + +**Goal**: Users can run `aimx trace distribution ` without an +output-mode flag and see matched distribution names plus a default histogram +and heatmap for the first selected series. + +**Independent Test**: Run `uv run aimx trace distribution "distribution.name != ''" --repo data` +and confirm the output lists all matched names, marks the selected name, labels +the displayed step, shows a current-step histogram, and shows a step-by-bin +heatmap without prompting for interaction (skip manual verification when your +checkout has no histogram data). + +### Tests for User Story 1 + +- [X] T008 [P] [US1] Add renderer unit tests for default visual output sections, selected-name marker, selected context, default first-step label, histogram label, and heatmap label in `tests/unit/test_trace_distribution_views.py` +- [X] T009 [P] [US1] Add integration tests for default `trace distribution "distribution.name != ''" --repo data` visual output in `tests/integration/test_trace_command.py` +- [X] T010 [P] [US1] Add contract tests for default distribution visual output and no-interaction deterministic text output in `tests/contract/test_trace_contract.py` + +### Implementation for User Story 1 + +- [X] T011 [US1] Implement `render_distribution_visual()` with `Distributions`, selected step, histogram, and heatmap sections in `src/aimx/rendering/trace_views.py` +- [X] T012 [US1] Route distribution plot/default mode to `render_distribution_visual()` while preserving JSON, CSV, and table branches in `src/aimx/commands/trace.py` +- [X] T013 [US1] Preserve existing no-match and no-data-in-step-range messages for distribution default mode in `src/aimx/commands/trace.py` +- [X] T014 [US1] Run `uv run pytest tests/unit/test_trace_distribution_views.py tests/integration/test_trace_command.py tests/contract/test_trace_contract.py -q` and fix US1 failures in `src/aimx/rendering/trace_views.py` and `src/aimx/commands/trace.py` + +**Checkpoint**: User Story 1 is fully functional and independently testable. + +--- + +## Phase 4: User Story 2 - Choose A Display Step Non-Interactively (Priority: P2) + +**Goal**: Users can pass `--step N` to choose the current-step histogram in the +default visual output, with deterministic nearest-step fallback. + +**Independent Test**: Run `uv run aimx trace distribution "distribution.name != ''" --repo data --step ` +and confirm `` is displayed, then run with a non-tracked step +between two neighbors and confirm the output labels the actual nearest tracked +step. + +### Tests for User Story 2 + +- [X] T015 [P] [US2] Add renderer unit tests for exact step selection, nearest lower step selection, nearest higher step selection, and lower-step tie resolution in `tests/unit/test_trace_distribution_views.py` +- [X] T016 [P] [US2] Add integration tests for dynamic `--step` selection, nearest-step fallback, and labeled actual step output with `--repo data` in `tests/integration/test_trace_command.py` +- [X] T017 [P] [US2] Add contract tests for missing `--step` value and non-integer `--step` exit-code `2` errors in `tests/contract/test_trace_contract.py` + +### Implementation for User Story 2 + +- [X] T018 [US2] Pass `invocation.selected_step` into the default distribution visual renderer from `_render_distribution_trace()` in `src/aimx/commands/trace.py` +- [X] T019 [US2] Implement exact, nearest, and lower-tie selected-step resolution with actual-step labeling in `src/aimx/rendering/trace_views.py` +- [X] T020 [US2] Ensure selected-step request notes are readable with and without ANSI color in `src/aimx/rendering/trace_views.py` +- [X] T021 [US2] Run `uv run pytest tests/unit/test_trace_helpers.py tests/unit/test_trace_distribution_views.py tests/integration/test_trace_command.py tests/contract/test_trace_contract.py -q` and fix US2 failures in `src/aimx/commands/trace.py` and `src/aimx/rendering/trace_views.py` + +**Checkpoint**: User Stories 1 and 2 both work independently. + +--- + +## Phase 5: User Story 3 - Keep Existing Scriptable Outputs (Priority: P3) + +**Goal**: Existing `--table`, `--csv`, and `--json` distribution workflows keep +their current tensor/export behavior and do not emit the new default visual +sections. + +**Independent Test**: Run distribution trace commands with `--table`, `--csv`, +and `--json` against `data`; confirm each output remains parseable or +readable in its existing shape and excludes the default visual histogram and +heatmap sections. + +### Tests for User Story 3 + +- [X] T022 [P] [US3] Add unit tests proving `render_distribution_table()`, `render_distribution_csv()`, and `render_distribution_json()` keep their existing tensor, CSV, and JSON fields in `tests/unit/test_trace_distribution_views.py` +- [X] T023 [P] [US3] Add integration tests for distribution `--table`, `--csv`, and `--json` against `data`, including `--step` supplied with each explicit mode, in `tests/integration/test_trace_command.py` +- [X] T024 [P] [US3] Add contract tests proving explicit distribution modes exclude default visual sections and remain parseable in `tests/contract/test_trace_contract.py` + +### Implementation for User Story 3 + +- [X] T025 [US3] Ensure `_render_distribution_trace()` branches `--json`, `--csv`, and `--table` before default visual rendering in `src/aimx/commands/trace.py` +- [X] T026 [US3] Preserve `render_distribution_table()`, `render_distribution_csv()`, and `render_distribution_json()` output schemas while adding visual rendering in `src/aimx/rendering/trace_views.py` +- [X] T027 [US3] Ensure `--step` does not filter table, CSV, or JSON rows in explicit distribution modes in `src/aimx/commands/trace.py` +- [X] T028 [US3] Run `uv run pytest tests/unit/test_trace_distribution_views.py tests/integration/test_trace_command.py tests/contract/test_trace_contract.py -q` and fix US3 failures in `src/aimx/commands/trace.py` and `src/aimx/rendering/trace_views.py` + +**Checkpoint**: All user stories are independently functional. + +--- + +## Phase 6: Polish & Cross-Cutting Concerns + +**Purpose**: Complete discoverability, safety validation, and full regression +coverage across the feature. + +- [X] T029 [P] Update trace distribution help text with default visual behavior, `--step`, and explicit `--table` tensor usage in `src/aimx/commands/help.py` +- [X] T030 [P] Update README distribution examples so default output is visual and tensor output uses `--table` in `README.md` +- [X] T031 [P] Update quickstart verification notes if implementation behavior differs from planned examples in `specs/005-distribution-trace-visual/quickstart.md` +- [X] T032 Run quickstart sections 3-9 manually and record any deviations in `specs/005-distribution-trace-visual/quickstart.md` +- [X] T033 Run passthrough and owned-command regression tests with `uv run pytest tests/contract/test_cli_contract.py tests/integration/test_missing_native_aim.py tests/integration/test_missing_python_aim_package.py -q` and fix regressions in `src/aimx/router.py`, `src/aimx/cli.py`, or `src/aimx/commands/trace.py` +- [X] T034 Run the full suite with `uv run pytest -q` and fix any regressions in touched files under `src/aimx/` and `tests/` +- [X] T035 Update final implementation verification notes in `specs/005-distribution-trace-visual/checklists/requirements.md` + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Phase 1 Setup**: No dependencies; can start immediately. +- **Phase 2 Foundational**: Depends on Phase 1; blocks every user story. +- **Phase 3 US1**: Depends on Phase 2; MVP scope. +- **Phase 4 US2**: Depends on Phase 2 and the default visual renderer from US1. +- **Phase 5 US3**: Depends on Phase 2 and can be validated after default visual routing exists. +- **Phase 6 Polish**: Depends on whichever user stories are included in the delivery. + +### User Story Dependencies + +- **US1 (P1)**: First independently valuable slice; no dependency on US2 or US3. +- **US2 (P2)**: Extends the default visual output with requested-step selection; depends on US1's visual renderer but remains independently testable after US1. +- **US3 (P3)**: Protects structured export behavior; can be worked alongside US1/US2 with coordination around `src/aimx/commands/trace.py`. + +### Within Each User Story + +- Write tests first and confirm they fail for the missing behavior. +- Parser and selection helpers before renderer routing. +- Renderer behavior before CLI integration assertions. +- Story-specific pytest command before moving to the next priority. + +--- + +## Parallel Opportunities + +- T002 can run in parallel with T001 because it touches a different test file. +- T003 and T005 can run in parallel because they touch different behavior areas and no runtime implementation files. +- T008, T009, and T010 can run in parallel for US1 test coverage. +- T015, T016, and T017 can run in parallel for US2 test coverage. +- T022, T023, and T024 can run in parallel for US3 test coverage. +- T029, T030, and T031 can run in parallel during polish because they touch different documentation files. + +--- + +## Parallel Example: User Story 1 + +```text +Task: "T008 [P] [US1] Add renderer unit tests for default visual output sections, selected-name marker, selected context, default first-step label, histogram label, and heatmap label in tests/unit/test_trace_distribution_views.py" +Task: "T009 [P] [US1] Add integration tests for default `trace distribution \"distribution.name != ''\" --repo data` visual output in tests/integration/test_trace_command.py" +Task: "T010 [P] [US1] Add contract tests for default distribution visual output and no-interaction deterministic text output in tests/contract/test_trace_contract.py" +``` + +## Parallel Example: User Story 2 + +```text +Task: "T015 [P] [US2] Add renderer unit tests for exact step selection, nearest lower step selection, nearest higher step selection, and lower-step tie resolution in tests/unit/test_trace_distribution_views.py" +Task: "T016 [P] [US2] Add integration tests for `--step` selection, nearest-step fallback, and labeled actual step output with `--repo data` in tests/integration/test_trace_command.py" +Task: "T017 [P] [US2] Add contract tests for missing `--step` value and non-integer `--step` exit-code `2` errors in tests/contract/test_trace_contract.py" +``` + +## Parallel Example: User Story 3 + +```text +Task: "T022 [P] [US3] Add unit tests proving `render_distribution_table()`, `render_distribution_csv()`, and `render_distribution_json()` keep their existing tensor, CSV, and JSON fields in tests/unit/test_trace_distribution_views.py" +Task: "T023 [P] [US3] Add integration tests for distribution `--table`, `--csv`, and `--json` against `data`, including `--step` supplied with each explicit mode, in tests/integration/test_trace_command.py" +Task: "T024 [P] [US3] Add contract tests proving explicit distribution modes exclude default visual sections and remain parseable in tests/contract/test_trace_contract.py" +``` + +--- + +## Implementation Strategy + +### MVP First (User Story 1 Only) + +1. Complete Phase 1 setup. +2. Complete Phase 2 foundational parser and visual-selection helpers. +3. Complete Phase 3 US1. +4. Stop and validate `uv run aimx trace distribution "distribution.name != ''" --repo data`. +5. Run US1 unit, integration, and contract tests before adding `--step` behavior. + +### Incremental Delivery + +1. US1: deliver default distribution name list, selected histogram, and heatmap. +2. US2: add `--step` exact and nearest-step visual selection. +3. US3: protect explicit table, CSV, and JSON export behavior. +4. Polish: update docs, run quickstart, and run full regression suite. + +### Multi-Developer Coordination + +- One developer owns `src/aimx/commands/trace.py` during parser and routing tasks to avoid conflicts. +- One developer can own `src/aimx/rendering/trace_views.py` and `tests/unit/test_trace_distribution_views.py`. +- One developer can own integration and contract tests in `tests/integration/test_trace_command.py` and `tests/contract/test_trace_contract.py`. +- Documentation tasks can proceed after the CLI shape is stable. + +--- + +## Notes + +- `[P]` means the task can be parallelized only after its stated phase dependencies are satisfied. +- Story labels map directly to the spec user stories. +- Keep the command read-only; do not call Aim mutation APIs such as `run.set`, `track`, artifact logging, migration, or repair operations. +- Preserve existing metric trace, distribution table, distribution CSV, distribution JSON, and native Aim passthrough contracts throughout implementation. +- Commit after each phase or a small coherent task group when using the git hook workflow. diff --git a/src/aimx/aim_bridge/metric_stats.py b/src/aimx/aim_bridge/metric_stats.py index df165e3..44cc4f3 100644 --- a/src/aimx/aim_bridge/metric_stats.py +++ b/src/aimx/aim_bridge/metric_stats.py @@ -3,6 +3,7 @@ import contextlib import datetime as dt import io +import tokenize from dataclasses import dataclass from pathlib import Path from typing import Any @@ -253,11 +254,46 @@ def _accessor() -> Any: return rows +def _normalize_distribution_query_expression(expression: str) -> str: + """Alias documented ``distribution`` queries to Aim's ``distributions`` variable.""" + tokens: list[tokenize.TokenInfo] = [] + previous_significant_token = "" + try: + for token in tokenize.generate_tokens(io.StringIO(expression).readline): + if ( + token.type == tokenize.NAME + and token.string == "distribution" + and previous_significant_token != "." + ): + token = tokenize.TokenInfo( + token.type, + "distributions", + token.start, + token.end, + token.line, + ) + tokens.append(token) + if token.type not in { + tokenize.COMMENT, + tokenize.DEDENT, + tokenize.ENDMARKER, + tokenize.INDENT, + tokenize.NEWLINE, + tokenize.NL, + }: + previous_significant_token = token.string + except tokenize.TokenError: + return expression + + return tokenize.untokenize(tokens) + + def collect_distribution_series(expression: str, repo_path: Path) -> list[DistributionSeries]: """Run an Aim distribution query and return flat ``DistributionSeries`` records.""" from aimx.aim_bridge.hash_resolver import resolve_hash_prefixes expression = resolve_hash_prefixes(expression, repo_path) + expression = _normalize_distribution_query_expression(expression) try: from aim import Repo diff --git a/src/aimx/commands/help.py b/src/aimx/commands/help.py index 971e6b2..6eedb9e 100644 --- a/src/aimx/commands/help.py +++ b/src/aimx/commands/help.py @@ -24,16 +24,19 @@ def render_help() -> str: " Example: aimx query images \"images\" --repo data --epochs 10:50", " Example: aimx query images \"images\" --repo data --head 10", " Example: aimx query params \"run.experiment=='cloud-segmentation'\" --repo data --param hparam.lr", - " trace Plot a metric's time-series from a local Aim repository", + " trace Plot metric time-series or distribution histograms from a local Aim repository", " Usage: aimx trace [--repo ]", " Usage: aimx trace distribution [--repo ]", " Options: --table --csv --json", " --steps start:end (e.g. --steps 100:500, :50, 100:)", + " --step N (distribution visual mode only; nearest tracked step)", " --head N --tail N --every K", " --width W --height H --no-color", " Repo defaults to the current directory.", " Short run hashes in the expression are transparently expanded.", " Example: aimx trace \"metric.name=='loss'\" --repo data --steps 100:500", + " Example: aimx trace distribution \"distribution.name != ''\" --repo data --step 12300", + " Example: aimx trace distribution \"distribution.name=='weights'\" --repo data --table", " Example: aimx trace distribution \"distribution.name=='weights'\" --repo data --json", "", "All other commands are delegated to native `aim`.", diff --git a/src/aimx/commands/trace.py b/src/aimx/commands/trace.py index 129480d..bc014dd 100644 --- a/src/aimx/commands/trace.py +++ b/src/aimx/commands/trace.py @@ -1,15 +1,25 @@ from __future__ import annotations import sys +from collections.abc import Callable from dataclasses import dataclass from pathlib import Path -from typing import Literal +from typing import Any, Literal from aimx.commands.query import QueryCommandResult, normalize_repo_path _MODES = {"plot", "table", "csv", "json"} +@dataclass(frozen=True) +class _TracePipeline: + collect: Callable[[str, Path], list[Any]] + filter_by_step_range: Callable[[Any, int | None, int | None], Any] + subsample: Callable[..., Any] + render: Callable[[list[Any], "TraceInvocation", bool], str] + no_matches_message: str + + @dataclass(frozen=True) class TraceInvocation: target: Literal["metrics", "distribution"] @@ -23,6 +33,7 @@ class TraceInvocation: height: int | None = None no_color: bool = False step_slice: str | None = None + selected_step: int | None = None def parse_trace_invocation(args: list[str]) -> TraceInvocation: @@ -58,6 +69,7 @@ def parse_trace_invocation(args: list[str]) -> TraceInvocation: height: int | None = None no_color = False step_slice: str | None = None + selected_step: int | None = None index = 0 while index < len(rest): @@ -84,6 +96,14 @@ def parse_trace_invocation(args: list[str]) -> TraceInvocation: raise ValueError("Missing value for --steps.") step_slice = rest[index + 1] index += 2 + elif token == "--step": + if index + 1 >= len(rest): + raise ValueError("Missing value for --step.") + try: + selected_step = int(rest[index + 1]) + except ValueError: + raise ValueError(f"--step requires an integer, got: {rest[index + 1]}") + index += 2 elif token == "--head": if index + 1 >= len(rest): raise ValueError("Missing value for --head.") @@ -143,115 +163,154 @@ def parse_trace_invocation(args: list[str]) -> TraceInvocation: height=height, no_color=no_color, step_slice=step_slice, + selected_step=selected_step, ) -def run_trace_command(args: list[str]) -> QueryCommandResult: - try: - invocation = parse_trace_invocation(args) - normalized_repo_path = normalize_repo_path(invocation.repo_path) - except ValueError as error: - return QueryCommandResult(exit_status=2, error_message=str(error)) +def _render_distribution_trace( + series_list: list[Any], + invocation: TraceInvocation, + no_color: bool, +) -> str: + from aimx.rendering.trace_views import ( + render_distribution_csv, + render_distribution_json, + render_distribution_table, + render_distribution_visual, + ) - is_tty = sys.stdout.isatty() - effective_no_color = invocation.no_color or not is_tty + if invocation.mode == "json": + return render_distribution_json(series_list) + if invocation.mode == "csv": + return render_distribution_csv(series_list) + if invocation.mode == "table": + return render_distribution_table(series_list, no_color=no_color) + return render_distribution_visual( + series_list, + selected_step=invocation.selected_step, + width=invocation.width, + height=invocation.height, + no_color=no_color, + ) - try: - from aimx.aim_bridge.metric_stats import parse_step_slice - from aimx.rendering.trace_views import ( - render_distribution_csv, - render_distribution_json, - render_distribution_table, - render_csv, - render_trace_table, - render_plot, - render_trace_json, + +def _render_metric_trace( + series_list: list[Any], + invocation: TraceInvocation, + no_color: bool, +) -> str: + from aimx.rendering.trace_views import ( + render_csv, + render_plot, + render_trace_json, + render_trace_table, + ) + + if invocation.mode == "json": + return render_trace_json(series_list) + if invocation.mode == "csv": + return render_csv(series_list) + if invocation.mode == "table": + return render_trace_table(series_list, no_color=no_color) + return render_plot( + series_list, + width=invocation.width, + height=invocation.height, + ) + + +def _build_trace_pipeline( + target: Literal["metrics", "distribution"], +) -> _TracePipeline: + if target == "distribution": + from aimx.aim_bridge.metric_stats import ( + collect_distribution_series, + filter_distribution_by_step_range, + subsample_distribution, ) - if invocation.target == "distribution": - from aimx.aim_bridge.metric_stats import ( - collect_distribution_series, - filter_distribution_by_step_range, - subsample_distribution, - ) + return _TracePipeline( + collect=collect_distribution_series, + filter_by_step_range=filter_distribution_by_step_range, + subsample=subsample_distribution, + render=_render_distribution_trace, + no_matches_message="No matching distributions found.", + ) - series_list = collect_distribution_series(invocation.expression, normalized_repo_path) - if not series_list: - return QueryCommandResult(exit_status=0, output="No matching distributions found.") + from aimx.aim_bridge.metric_stats import ( + collect_metric_series, + filter_by_step_range, + subsample, + ) - if invocation.step_slice is not None: - step_start, step_end = parse_step_slice(invocation.step_slice) - series_list = [ - filter_distribution_by_step_range(s, step_start, step_end) for s in series_list - ] - series_list = [s for s in series_list if s.count > 0] + return _TracePipeline( + collect=collect_metric_series, + filter_by_step_range=filter_by_step_range, + subsample=subsample, + render=_render_metric_trace, + no_matches_message="No matching metrics found.", + ) - if not series_list: - return QueryCommandResult(exit_status=0, output="No data in the requested step range.") - needs_sample = any( - x is not None for x in (invocation.head, invocation.tail, invocation.every) - ) - if needs_sample: - series_list = [ - subsample_distribution( - s, head=invocation.head, tail=invocation.tail, every=invocation.every - ) - for s in series_list - ] - - if invocation.mode == "json": - output = render_distribution_json(series_list) - elif invocation.mode == "csv": - output = render_distribution_csv(series_list) - else: - output = render_distribution_table(series_list, no_color=effective_no_color) - else: - from aimx.aim_bridge.metric_stats import ( - collect_metric_series, - filter_by_step_range, - subsample, +def _execute_trace_pipeline( + invocation: TraceInvocation, + normalized_repo_path: Path, + pipeline: _TracePipeline, + *, + no_color: bool, +) -> QueryCommandResult: + from aimx.aim_bridge.metric_stats import parse_step_slice + + series_list = pipeline.collect(invocation.expression, normalized_repo_path) + if not series_list: + return QueryCommandResult(exit_status=0, output=pipeline.no_matches_message) + + if invocation.step_slice is not None: + step_start, step_end = parse_step_slice(invocation.step_slice) + series_list = [ + pipeline.filter_by_step_range(series, step_start, step_end) + for series in series_list + ] + series_list = [series for series in series_list if series.count > 0] + + if not series_list: + return QueryCommandResult(exit_status=0, output="No data in the requested step range.") + + needs_sample = any(x is not None for x in (invocation.head, invocation.tail, invocation.every)) + if needs_sample: + series_list = [ + pipeline.subsample( + series, + head=invocation.head, + tail=invocation.tail, + every=invocation.every, ) + for series in series_list + ] - series_list = collect_metric_series(invocation.expression, normalized_repo_path) + return QueryCommandResult( + exit_status=0, + output=pipeline.render(series_list, invocation, no_color), + ) - if not series_list: - return QueryCommandResult(exit_status=0, output="No matching metrics found.") - # Step range filter is a hard constraint applied before density subsampling - if invocation.step_slice is not None: - step_start, step_end = parse_step_slice(invocation.step_slice) - series_list = [filter_by_step_range(s, step_start, step_end) for s in series_list] - # Drop empty series so they don't clutter plots - series_list = [s for s in series_list if s.count > 0] +def run_trace_command(args: list[str]) -> QueryCommandResult: + try: + invocation = parse_trace_invocation(args) + normalized_repo_path = normalize_repo_path(invocation.repo_path) + except ValueError as error: + return QueryCommandResult(exit_status=2, error_message=str(error)) - if not series_list: - return QueryCommandResult(exit_status=0, output="No data in the requested step range.") + is_tty = sys.stdout.isatty() + effective_no_color = invocation.no_color or not is_tty - # Density subsampling for visualisation - needs_sample = any( - x is not None for x in (invocation.head, invocation.tail, invocation.every) - ) - if needs_sample: - series_list = [ - subsample(s, head=invocation.head, tail=invocation.tail, every=invocation.every) - for s in series_list - ] - - if invocation.mode == "json": - output = render_trace_json(series_list) - elif invocation.mode == "csv": - output = render_csv(series_list) - elif invocation.mode == "table": - output = render_trace_table(series_list, no_color=effective_no_color) - else: - output = render_plot( - series_list, - width=invocation.width, - height=invocation.height, - ) - - return QueryCommandResult(exit_status=0, output=output) + try: + return _execute_trace_pipeline( + invocation, + normalized_repo_path, + _build_trace_pipeline(invocation.target), + no_color=effective_no_color, + ) except RuntimeError as error: return QueryCommandResult(exit_status=2, error_message=str(error)) diff --git a/src/aimx/rendering/trace_views.py b/src/aimx/rendering/trace_views.py index 8c2f508..df85516 100644 --- a/src/aimx/rendering/trace_views.py +++ b/src/aimx/rendering/trace_views.py @@ -6,14 +6,35 @@ import json import math import shutil +from dataclasses import dataclass from typing import Any from rich.console import Console +from rich.markup import escape from rich.table import Table +from rich.text import Text -from aimx.aim_bridge.metric_stats import DistributionSeries, MetricSeries, RunMeta +from aimx.aim_bridge.metric_stats import DistributionSeries, MetricSeries from aimx.rendering import colors +_DISTRIBUTION_BLOCKS = "▁▂▃▄▅▆▇█" +_DISTRIBUTION_BLUE_STYLES = ( + "#dbeafe", + "#bfdbfe", + "#93c5fd", + "#60a5fa", + "#3b82f6", + "#2563eb", + "#1d4ed8", + "#1e40af", +) +_DISTRIBUTION_ZERO_STYLE = "#334155" +_DISTRIBUTION_HEADER_STYLE = "#93c5fd" +_DISTRIBUTION_DIM_STYLE = "#64748b" +_DISTRIBUTION_RULE_STYLE = "#1e3a8a" +_DISTRIBUTION_MARKER_STYLE = "#2563eb bold" +_DISTRIBUTION_SELECTED_STYLE = "bold white" + def _short_hash(h: str) -> str: return h[:8] @@ -25,6 +46,12 @@ def _fmt_context(ctx: dict[str, Any]) -> str: return " ".join(f"{k}={v}" for k, v in sorted(ctx.items())) +def _fmt_context_for_visual(ctx: dict[str, Any]) -> str: + if not ctx: + return "" + return ", ".join(f"{k}={json.dumps(v)}" for k, v in sorted(ctx.items())) + + def _series_label(series: MetricSeries) -> str: parts = [_short_hash(series.run.hash)] if series.run.experiment: @@ -51,6 +78,202 @@ def _distribution_series_label(series: DistributionSeries) -> str: return " · ".join(parts) +@dataclass(frozen=True) +class DistributionVisualSelection: + selected_index: int + series: DistributionSeries + point_index: int + requested_step: int | None + resolved_step: int + + @property + def point(self): + return self.series.points[self.point_index] + + @property + def used_nearest_step(self) -> bool: + return self.requested_step is not None and self.requested_step != self.resolved_step + + +def select_distribution_visual( + series_list: list[DistributionSeries], + *, + selected_step: int | None = None, +) -> DistributionVisualSelection | None: + """Select the first non-empty distribution and resolve the display step.""" + for selected_index, series in enumerate(series_list): + if series.count == 0: + continue + if selected_step is None: + return DistributionVisualSelection( + selected_index=selected_index, + series=series, + point_index=0, + requested_step=None, + resolved_step=series.points[0].step, + ) + + point_index, point = min( + enumerate(series.points), + key=lambda item: (abs(item[1].step - selected_step), item[1].step), + ) + return DistributionVisualSelection( + selected_index=selected_index, + series=series, + point_index=point_index, + requested_step=selected_step, + resolved_step=point.step, + ) + return None + + +def _bin_range(point: Any) -> str: + edges = point.bin_edges.tolist() + if not edges: + return "" + return f"{edges[0]:.6g} .. {edges[-1]:.6g}" + + +def _compress_values(values: list[float], width: int) -> list[float]: + if width <= 0 or len(values) <= width: + return values + compressed: list[float] = [] + for index in range(width): + start = index * len(values) // width + end = (index + 1) * len(values) // width + bucket = values[start:end] or [values[start]] + compressed.append(max(bucket)) + return compressed + + +def _intensity_text(values: list[float], *, width: int) -> Text: + values = _compress_values(values, width) + text = Text() + if not values: + return text + max_value = max(float(v) for v in values) + if max_value <= 0: + text.append(_DISTRIBUTION_BLOCKS[0] * len(values), style=_DISTRIBUTION_ZERO_STYLE) + return text + for value in values: + if value <= 0: + text.append(_DISTRIBUTION_BLOCKS[0], style=_DISTRIBUTION_ZERO_STYLE) + continue + scale = float(value) / max_value + index = round(scale * (len(_DISTRIBUTION_BLOCKS) - 1)) + text.append(_DISTRIBUTION_BLOCKS[index], style=_DISTRIBUTION_BLUE_STYLES[index]) + return text + + +def _sample_points_for_height(points: list[Any], max_rows: int) -> list[Any]: + if max_rows <= 0 or len(points) <= max_rows: + return points + indexes = sorted({round(i * (len(points) - 1) / (max_rows - 1)) for i in range(max_rows)}) + return [points[index] for index in indexes] + + +def _render_distribution_name_list( + console: Console, + series_list: list[DistributionSeries], + selected_index: int, +) -> None: + console.print(f"[{_DISTRIBUTION_HEADER_STYLE}]Distributions[/]") + for index, series in enumerate(series_list): + label = escape(series.name) + count = f"{series.count} steps" if series.count != 1 else "1 step" + if index == selected_index: + console.print( + f"[{_DISTRIBUTION_MARKER_STYLE}]▌[/] " + f"[{_DISTRIBUTION_SELECTED_STYLE}]{label}[/] " + f"[{_DISTRIBUTION_DIM_STYLE}]({count})[/]" + ) + ctx = _fmt_context_for_visual(series.context) + if ctx: + console.print(f" [{_DISTRIBUTION_DIM_STYLE}]{escape(ctx)}[/]") + else: + console.print(f" [{_DISTRIBUTION_DIM_STYLE}]{label} ({count})[/]") + + +def render_distribution_visual( + series_list: list[DistributionSeries], + *, + selected_step: int | None = None, + width: int | None = None, + height: int | None = None, + no_color: bool = False, +) -> str: + """Render distribution names plus a selected histogram and heatmap.""" + term_width = shutil.get_terminal_size(fallback=(120, 30)).columns + console_width = width or (120 if no_color else term_width) + chart_width = max(24, min(96, console_width - 18)) + max_heatmap_rows = max(1, (height - 12) if height is not None else 18) + + buf = io.StringIO() + console = Console( + file=buf, + no_color=no_color, + color_system=None if no_color else "truecolor", + force_terminal=not no_color, + width=console_width, + highlight=False, + ) + + selection = select_distribution_visual(series_list, selected_step=selected_step) + if selection is None: + console.print("No data in the requested step range.") + return buf.getvalue() + + _render_distribution_name_list(console, series_list, selection.selected_index) + selected = selection.series + point = selection.point + weights = [float(v) for v in point.weights.tolist()] + + console.print() + console.print( + f"[{_DISTRIBUTION_HEADER_STYLE}]╭─ Histogram[/] " + f"[{_DISTRIBUTION_SELECTED_STYLE}]{escape(selected.name)}[/] " + f"[{_DISTRIBUTION_HEADER_STYLE}]Step {selection.resolved_step}[/]" + ) + if selection.used_nearest_step: + console.print( + f"[{_DISTRIBUTION_DIM_STYLE}]Requested step {selection.requested_step}; " + f"showing nearest tracked step {selection.resolved_step}.[/]" + ) + bin_range = _bin_range(point) + if bin_range: + console.print( + f"[{_DISTRIBUTION_DIM_STYLE}]Bins {bin_range}; " + f"max weight {max(weights) if weights else 0:.6g}[/]" + ) + console.print(_intensity_text(weights, width=chart_width)) + console.print(f"[{_DISTRIBUTION_RULE_STYLE}]╰{'─' * min(chart_width, console_width - 2)}[/]") + + console.print() + console.print(f"[{_DISTRIBUTION_HEADER_STYLE}]╭─ Heatmap (steps x bins)[/]") + selected_points = _sample_points_for_height(selected.points, max_heatmap_rows) + for heatmap_point in selected_points: + row = Text(f"{heatmap_point.step:>8} | ", style=_DISTRIBUTION_DIM_STYLE) + row.append_text( + _intensity_text( + [float(v) for v in heatmap_point.weights.tolist()], + width=chart_width, + ) + ) + console.print(row) + if len(selected_points) < len(selected.points): + console.print( + f"[{_DISTRIBUTION_DIM_STYLE}]Showing {len(selected_points)} of {len(selected.points)} steps; " + "use --height to adjust.[/]" + ) + scale = Text("Scale: ", style=_DISTRIBUTION_DIM_STYLE) + scale.append("low", style=_DISTRIBUTION_BLUE_STYLES[0]) + scale.append(" -> ", style=_DISTRIBUTION_DIM_STYLE) + scale.append("high", style=_DISTRIBUTION_BLUE_STYLES[-1]) + console.print(scale) + + return buf.getvalue() + + def render_plot( series_list: list[MetricSeries], *, diff --git a/tests/contract/test_trace_contract.py b/tests/contract/test_trace_contract.py index bead2cc..93abf2f 100644 --- a/tests/contract/test_trace_contract.py +++ b/tests/contract/test_trace_contract.py @@ -3,8 +3,28 @@ import csv import io import json +from pathlib import Path + +import pytest from aimx.__main__ import main +from aimx.aim_bridge.metric_stats import DistributionSeries, collect_distribution_series +from aimx.commands.query import normalize_repo_path + + +def _require_distribution_series(sample_repo_root: Path) -> list[DistributionSeries]: + normalized = normalize_repo_path(sample_repo_root) + series_list = collect_distribution_series("distribution.name != ''", normalized) + if not series_list: + pytest.skip("sample Aim repository has no distribution sequences for contract tests") + return series_list + + +def _first_non_empty_series(series_list: list[DistributionSeries]) -> DistributionSeries: + for series in series_list: + if series.count > 0: + return series + pytest.skip("sample Aim repository has no non-empty distribution series for contract tests") def test_trace_plot_contract_produces_non_empty_output(capfd, sample_repo_root) -> None: @@ -75,3 +95,134 @@ def test_trace_invalid_expression_reports_error(capfd, sample_repo_root) -> None captured = capfd.readouterr() assert exit_code == 2 assert "Failed to evaluate trace" in captured.err + + +def test_trace_distribution_default_visual_contract(capfd, sample_repo_root: Path) -> None: + repo_root = sample_repo_root + _require_distribution_series(repo_root) + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--head", + "2", + "--no-color", + ] + ) + + captured = capfd.readouterr() + assert exit_code == 0 + assert "Distributions" in captured.out + assert "Histogram" in captured.out + assert "Heatmap (steps x bins)" in captured.out + assert not captured.err + + +def test_trace_distribution_step_missing_value_reports_error( + capfd, sample_repo_root: Path +) -> None: + repo_root = sample_repo_root + _require_distribution_series(repo_root) + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--step", + ] + ) + + captured = capfd.readouterr() + assert exit_code == 2 + assert "Missing value for --step" in captured.err + + +def test_trace_distribution_step_non_integer_reports_error(capfd, sample_repo_root: Path) -> None: + repo_root = sample_repo_root + _require_distribution_series(repo_root) + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--step", + "abc", + ] + ) + + captured = capfd.readouterr() + assert exit_code == 2 + assert "--step requires an integer" in captured.err + + +def test_trace_distribution_explicit_modes_exclude_visual_sections( + capfd, sample_repo_root: Path +) -> None: + repo_root = sample_repo_root + _require_distribution_series(repo_root) + + table_exit = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--table", + "--head", + "1", + "--no-color", + ] + ) + table_output = capfd.readouterr().out + assert table_exit == 0 + assert "TENSOR" in table_output + assert "Heatmap (steps x bins)" not in table_output + + csv_exit = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--csv", + "--head", + "1", + ] + ) + csv_output = capfd.readouterr().out + assert csv_exit == 0 + reader = csv.DictReader(io.StringIO(csv_output)) + assert reader.fieldnames is not None + assert "weights" in reader.fieldnames + assert "Heatmap (steps x bins)" not in csv_output + + json_exit = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--json", + "--head", + "1", + ] + ) + json_output = capfd.readouterr().out + payload = json.loads(json_output) + assert json_exit == 0 + assert payload + assert "points" in payload[0] + assert "Heatmap (steps x bins)" not in json_output diff --git a/tests/integration/test_trace_command.py b/tests/integration/test_trace_command.py index d4703c4..0d88a52 100644 --- a/tests/integration/test_trace_command.py +++ b/tests/integration/test_trace_command.py @@ -3,8 +3,54 @@ import csv import io import json +from pathlib import Path + +import pytest from aimx.__main__ import main +from aimx.aim_bridge.metric_stats import DistributionSeries, collect_distribution_series +from aimx.commands.query import normalize_repo_path + + +def _require_distribution_series(sample_repo_root: Path) -> list[DistributionSeries]: + """Return distribution series for ``data/``-style fixtures, or skip when absent.""" + normalized = normalize_repo_path(sample_repo_root) + series_list = collect_distribution_series("distribution.name != ''", normalized) + if not series_list: + pytest.skip("sample Aim repository has no distribution sequences for integration tests") + return series_list + + +def _first_non_empty_series(series_list: list[DistributionSeries]) -> DistributionSeries: + for series in series_list: + if series.count > 0: + return series + pytest.skip("sample Aim repository has no non-empty distribution series for integration tests") + + +def _sorted_unique_steps(series: DistributionSeries) -> list[int]: + return sorted({point.step for point in series.points}) + + +def _pick_exact_and_nearest_request(steps: list[int]) -> tuple[int, int]: + """Return ``(requested_step, expected_resolved_step)`` for nearest-step coverage.""" + if len(steps) < 2: + pytest.skip("sample distribution series needs at least two steps for step selection tests") + + lower, higher = steps[0], steps[1] + if higher - lower <= 1: + pytest.skip("sample distribution steps are too dense to construct a nearest-step gap test") + + requested = (lower + higher) // 2 + if abs(requested - lower) == abs(requested - higher): + pytest.skip("sample distribution steps do not produce a unique nearest-step candidate") + + if abs(requested - lower) < abs(requested - higher): + expected = lower + else: + expected = higher + + return requested, expected def test_trace_plot_produces_output_containing_metric_name(capfd, sample_repo_root) -> None: @@ -104,3 +150,185 @@ def test_trace_no_matching_expression_exits_cleanly(capfd, sample_repo_root) -> captured = capfd.readouterr() assert exit_code == 0 assert "No matching" in captured.out + + +def test_trace_distribution_default_visual_contains_list_histogram_and_heatmap( + capfd, sample_repo_root: Path +) -> None: + series_list = _require_distribution_series(sample_repo_root) + first_point = _first_non_empty_series(series_list).points[0] + repo_root = sample_repo_root + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--head", + "3", + "--no-color", + ] + ) + + captured = capfd.readouterr() + assert exit_code == 0 + assert "Distributions" in captured.out + assert "▌ " in captured.out + if _first_non_empty_series(series_list).context: + assert "kind=" in captured.out + assert "Histogram" in captured.out + assert f"Step {first_point.step}" in captured.out + assert "Heatmap (steps x bins)" in captured.out + assert "Scale: low -> high" in captured.out + + +def test_trace_distribution_step_selects_requested_step(capfd, sample_repo_root: Path) -> None: + series = _first_non_empty_series(_require_distribution_series(sample_repo_root)) + steps = _sorted_unique_steps(series) + if len(steps) < 2: + pytest.skip("sample distribution series needs at least two steps for exact step selection") + exact_step = steps[1] + repo_root = sample_repo_root + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--step", + str(exact_step), + "--no-color", + ] + ) + + captured = capfd.readouterr() + assert exit_code == 0 + assert f"Step {exact_step}" in captured.out + + +def test_trace_distribution_step_uses_nearest_tracked_step(capfd, sample_repo_root: Path) -> None: + series = _first_non_empty_series(_require_distribution_series(sample_repo_root)) + steps = _sorted_unique_steps(series) + requested, expected = _pick_exact_and_nearest_request(steps) + repo_root = sample_repo_root + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--step", + str(requested), + "--no-color", + ] + ) + + captured = capfd.readouterr() + assert exit_code == 0 + assert ( + f"Requested step {requested}; showing nearest tracked step {expected}." + in captured.out + ) + + +def test_trace_distribution_table_mode_preserves_tensor_output_with_step( + capfd, sample_repo_root: Path +) -> None: + series = _first_non_empty_series(_require_distribution_series(sample_repo_root)) + steps = _sorted_unique_steps(series) + if len(steps) < 2: + pytest.skip("sample distribution series needs at least two steps for table step carryover checks") + table_step = steps[1] + repo_root = sample_repo_root + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--table", + "--step", + str(table_step), + "--head", + "2", + "--no-color", + ] + ) + + captured = capfd.readouterr() + assert exit_code == 0 + assert "TENSOR" in captured.out + assert "Histogram" not in captured.out + assert "Heatmap" not in captured.out + + +def test_trace_distribution_json_mode_preserves_series_payload_with_step( + capfd, sample_repo_root: Path +) -> None: + series = _first_non_empty_series(_require_distribution_series(sample_repo_root)) + steps = _sorted_unique_steps(series) + if len(steps) < 2: + pytest.skip("sample distribution series needs at least two points for JSON head checks") + json_step = steps[1] + repo_root = sample_repo_root + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--json", + "--step", + str(json_step), + "--head", + "2", + ] + ) + + captured = capfd.readouterr() + payload = json.loads(captured.out) + assert exit_code == 0 + assert payload + assert payload[0]["count"] == 2 + assert "points" in payload[0] + + +def test_trace_distribution_csv_mode_preserves_rows_with_step( + capfd, sample_repo_root: Path +) -> None: + series = _first_non_empty_series(_require_distribution_series(sample_repo_root)) + if series.count < 1: + pytest.skip("sample distribution series needs points for CSV checks") + csv_step = series.points[0].step + repo_root = sample_repo_root + + exit_code = main( + [ + "trace", + "distribution", + "distribution.name != ''", + "--repo", + str(repo_root), + "--csv", + "--step", + str(csv_step), + "--head", + "1", + ] + ) + + captured = capfd.readouterr() + rows = list(csv.DictReader(io.StringIO(captured.out))) + assert exit_code == 0 + assert rows + assert {"run_hash", "distribution", "step", "bin_edges", "weights"}.issubset(rows[0]) diff --git a/tests/unit/test_metric_stats.py b/tests/unit/test_metric_stats.py index 8bfae1f..919c292 100644 --- a/tests/unit/test_metric_stats.py +++ b/tests/unit/test_metric_stats.py @@ -2,6 +2,8 @@ import datetime as dt import math +import sys +import types import numpy as np import pytest @@ -218,3 +220,53 @@ def test_steps_are_sliced_consistently_with_values(self) -> None: s = _make_series(values=[10.0, 20.0, 30.0, 40.0], steps=[100, 200, 300, 400]) result = subsample(s, head=2, tail=None, every=None) assert result.steps.tolist() == [100, 200] + + +class TestCollectDistributionSeries: + def test_rewrites_singular_distribution_variable_before_query( + self, + monkeypatch: pytest.MonkeyPatch, + tmp_path, + ) -> None: + from aimx.aim_bridge.metric_stats import collect_distribution_series + + captured: dict[str, object] = {} + + class _FakeQueryReportMode: + DISABLED = object() + + class _FakeDistributionQueryResult: + def iter_runs(self): + return [] + + class _FakeRepo: + def __init__(self, repo_path: str) -> None: + captured["repo_path"] = repo_path + + def query_distributions(self, expression: str, *, report_mode: object): + captured["expression"] = expression + captured["report_mode"] = report_mode + return _FakeDistributionQueryResult() + + aim_module = types.ModuleType("aim") + aim_module.Repo = _FakeRepo + sdk_module = types.ModuleType("aim.sdk") + types_module = types.ModuleType("aim.sdk.types") + types_module.QueryReportMode = _FakeQueryReportMode + + monkeypatch.setitem(sys.modules, "aim", aim_module) + monkeypatch.setitem(sys.modules, "aim.sdk", sdk_module) + monkeypatch.setitem(sys.modules, "aim.sdk.types", types_module) + + result = collect_distribution_series( + "run.hparams.distribution == 'enabled' and distribution.name == 'weights'", + tmp_path, + ) + + assert result == [] + assert captured["repo_path"] == str(tmp_path) + assert ( + captured["expression"] + == "run.hparams.distribution == 'enabled' and distributions.name == 'weights'" + ) + assert captured["report_mode"] is _FakeQueryReportMode.DISABLED diff --git a/tests/unit/test_trace_distribution_views.py b/tests/unit/test_trace_distribution_views.py index 26d8811..6e460d5 100644 --- a/tests/unit/test_trace_distribution_views.py +++ b/tests/unit/test_trace_distribution_views.py @@ -11,6 +11,8 @@ render_distribution_csv, render_distribution_json, render_distribution_table, + render_distribution_visual, + select_distribution_visual, ) @@ -39,6 +41,43 @@ def _sample_distribution_series() -> list[DistributionSeries]: ] +def _multi_step_distribution_series() -> list[DistributionSeries]: + run = RunMeta(hash="abcdef1234567890", experiment="exp-a", name=None, creation_time=None) + return [ + DistributionSeries( + run=run, + name="empty", + context={"kind": "empty"}, + points=[], + ), + DistributionSeries( + run=run, + name="head/gradients/head.0.bias", + context={"kind": "gradients", "module": "head"}, + points=[ + DistributionPoint( + step=300, + epoch=0.0, + bin_edges=np.array([-1.0, 0.0, 1.0]), + weights=np.array([0.0, 2.0]), + ), + DistributionPoint( + step=600, + epoch=0.0, + bin_edges=np.array([-1.0, 0.0, 1.0]), + weights=np.array([3.0, 0.0]), + ), + DistributionPoint( + step=900, + epoch=0.0, + bin_edges=np.array([-1.0, 0.0, 1.0]), + weights=np.array([1.0, 4.0]), + ), + ], + ), + ] + + def test_render_distribution_table_includes_tensor_column() -> None: output = render_distribution_table(_sample_distribution_series(), no_color=True) @@ -68,3 +107,104 @@ def test_render_distribution_json_contains_points() -> None: assert first["count"] == 2 assert first["points"][0]["step"] == 10 assert first["points"][0]["weights"] == [3.0, 5.0] + + +def test_select_distribution_visual_uses_first_non_empty_series_and_first_point() -> None: + selection = select_distribution_visual(_multi_step_distribution_series()) + + assert selection is not None + assert selection.selected_index == 1 + assert selection.series.name == "head/gradients/head.0.bias" + assert selection.resolved_step == 300 + + +def test_select_distribution_visual_returns_none_without_points() -> None: + series = _multi_step_distribution_series()[:1] + assert select_distribution_visual(series) is None + + +def test_select_distribution_visual_resolves_exact_step() -> None: + selection = select_distribution_visual(_multi_step_distribution_series(), selected_step=600) + + assert selection is not None + assert selection.resolved_step == 600 + assert not selection.used_nearest_step + + +def test_select_distribution_visual_resolves_nearest_higher_step() -> None: + selection = select_distribution_visual(_multi_step_distribution_series(), selected_step=500) + + assert selection is not None + assert selection.resolved_step == 600 + + +def test_select_distribution_visual_uses_lower_step_for_tie() -> None: + selection = select_distribution_visual(_multi_step_distribution_series(), selected_step=750) + + assert selection is not None + assert selection.resolved_step == 600 + + +def test_render_distribution_visual_includes_name_context_histogram_and_heatmap() -> None: + output = render_distribution_visual(_multi_step_distribution_series(), no_color=True) + + assert "Distributions" in output + assert "▌ head/gradients/head.0.bias" in output + assert 'kind="gradients", module="head"' in output + assert "Histogram" in output + assert "Step 300" in output + assert "Heatmap (steps x bins)" in output + assert "300 |" in output + assert "Scale: low -> high" in output + assert "█" in output + assert "\x1b[" not in output + + +def test_render_distribution_visual_uses_blue_gradient_color_by_default() -> None: + output = render_distribution_visual( + _multi_step_distribution_series(), + width=80, + height=14, + ) + + assert "\x1b[" in output + assert "\x1b[38;2;" in output + assert "Distributions" in output + assert "Histogram" in output + assert "Heatmap (steps x bins)" in output + + +def test_render_distribution_visual_labels_nearest_step() -> None: + output = render_distribution_visual( + _multi_step_distribution_series(), + selected_step=750, + no_color=True, + ) + + assert "Step 600" in output + assert "Requested step 750; showing nearest tracked step 600." in output + + +def test_render_distribution_visual_handles_single_step_and_all_zero_weights() -> None: + run = RunMeta(hash="abcdef1234567890", experiment="exp-a", name=None, creation_time=None) + series = [ + DistributionSeries( + run=run, + name="zeros", + context={}, + points=[ + DistributionPoint( + step=1, + epoch=None, + bin_edges=np.array([0.0, 1.0, 2.0]), + weights=np.array([0.0, 0.0]), + ) + ], + ) + ] + + output = render_distribution_visual(series, no_color=True) + + assert "zeros" in output + assert "Step 1" in output + assert "▁▁" in output diff --git a/tests/unit/test_trace_helpers.py b/tests/unit/test_trace_helpers.py index 8afa427..bfabdc3 100644 --- a/tests/unit/test_trace_helpers.py +++ b/tests/unit/test_trace_helpers.py @@ -1,10 +1,25 @@ from __future__ import annotations +from dataclasses import dataclass from pathlib import Path import pytest -from aimx.commands.trace import TraceInvocation, parse_trace_invocation +from aimx.commands.trace import ( + TraceInvocation, + _TracePipeline, + _execute_trace_pipeline, + parse_trace_invocation, +) + + +@dataclass +class _FakeSeries: + points: list[int] + + @property + def count(self) -> int: + return len(self.points) def test_parse_trace_defaults() -> None: @@ -122,3 +137,155 @@ def test_parse_trace_steps_missing_value_raises() -> None: def test_parse_trace_steps_defaults_to_none() -> None: inv = parse_trace_invocation(["expr", "--repo", "data"]) assert inv.step_slice is None + + +def test_parse_trace_step_flag() -> None: + inv = parse_trace_invocation(["distribution", "expr", "--repo", "data", "--step", "12300"]) + assert inv.selected_step == 12300 + + +def test_parse_trace_step_missing_value_raises() -> None: + with pytest.raises(ValueError, match="Missing value for --step"): + parse_trace_invocation(["distribution", "expr", "--repo", "data", "--step"]) + + +def test_parse_trace_step_rejects_non_integer() -> None: + with pytest.raises(ValueError, match="--step requires an integer"): + parse_trace_invocation(["distribution", "expr", "--repo", "data", "--step", "abc"]) + + +def test_execute_trace_pipeline_filters_before_sampling_and_renders_remaining() -> None: + calls: list[tuple[object, ...]] = [] + invocation = TraceInvocation( + target="metrics", + expression="expr", + repo_path=Path("."), + mode="json", + head=2, + every=2, + step_slice="2:4", + ) + + def collect(expression: str, repo_path: Path) -> list[_FakeSeries]: + calls.append(("collect", expression, repo_path)) + return [_FakeSeries([1, 2, 3, 4, 5]), _FakeSeries([10])] + + def filter_by_step_range( + series: _FakeSeries, + start: int | None, + end: int | None, + ) -> _FakeSeries: + calls.append(("filter", tuple(series.points), start, end)) + return _FakeSeries( + [ + point + for point in series.points + if (start is None or point >= start) and (end is None or point <= end) + ] + ) + + def subsample( + series: _FakeSeries, + *, + head: int | None, + tail: int | None, + every: int | None, + ) -> _FakeSeries: + calls.append(("subsample", tuple(series.points), head, tail, every)) + points = series.points + if head is not None: + points = points[:head] + if tail is not None: + points = points[-tail:] + if every is not None and every > 1: + points = points[::every] + return _FakeSeries(points) + + def render( + series_list: list[_FakeSeries], + render_invocation: TraceInvocation, + no_color: bool, + ) -> str: + calls.append( + ( + "render", + tuple(tuple(series.points) for series in series_list), + render_invocation.mode, + no_color, + ) + ) + return "rendered" + + result = _execute_trace_pipeline( + invocation, + Path("repo"), + _TracePipeline( + collect=collect, + filter_by_step_range=filter_by_step_range, + subsample=subsample, + render=render, + no_matches_message="No matching fake series found.", + ), + no_color=True, + ) + + assert result.exit_status == 0 + assert result.output == "rendered" + assert calls == [ + ("collect", "expr", Path("repo")), + ("filter", (1, 2, 3, 4, 5), 2, 4), + ("filter", (10,), 2, 4), + ("subsample", (2, 3, 4), 2, None, 2), + ("render", ((2,),), "json", True), + ] + + +def test_execute_trace_pipeline_returns_step_range_message_when_filter_empties() -> None: + invocation = TraceInvocation( + target="metrics", + expression="expr", + repo_path=Path("."), + step_slice="2:4", + ) + + def collect(expression: str, repo_path: Path) -> list[_FakeSeries]: + return [_FakeSeries([1])] + + def filter_by_step_range( + series: _FakeSeries, + start: int | None, + end: int | None, + ) -> _FakeSeries: + return _FakeSeries([]) + + def subsample( + series: _FakeSeries, + *, + head: int | None, + tail: int | None, + every: int | None, + ) -> _FakeSeries: + raise AssertionError("subsample should not run after the filter empties all series") + + def render( + series_list: list[_FakeSeries], + render_invocation: TraceInvocation, + no_color: bool, + ) -> str: + raise AssertionError("render should not run after the filter empties all series") + + result = _execute_trace_pipeline( + invocation, + Path("repo"), + _TracePipeline( + collect=collect, + filter_by_step_range=filter_by_step_range, + subsample=subsample, + render=render, + no_matches_message="No matching fake series found.", + ), + no_color=False, + ) + + assert result.exit_status == 0 + assert result.output == "No data in the requested step range." From 30eea02bacac504840cb55d045fb6006d1a47795 Mon Sep 17 00:00:00 2001 From: blizhan Date: Thu, 30 Apr 2026 16:58:37 +0800 Subject: [PATCH 3/6] update: readme --- README.md | 2 ++ static/distributions.png | Bin 0 -> 314192 bytes 2 files changed, 2 insertions(+) create mode 100644 static/distributions.png diff --git a/README.md b/README.md index eb09140..9966c6a 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,8 @@ renders a non-interactive Rich terminal visual with a web-style blue-gradient current-step histogram and step-by-bin heatmap. Use `--table`, `--csv`, or `--json` for tensor inspection and scripting. +![aimx trace distribution output preview](static/distributions.png) + ```bash # Show a web-like terminal visual for the first matched distribution aimx trace distribution "distribution.name != ''" --repo data diff --git a/static/distributions.png b/static/distributions.png new file mode 100644 index 0000000000000000000000000000000000000000..31137a8a4cbb7ede576fda9cf5aab4f14c38d983 GIT binary patch literal 314192 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

q1P47GA3d-g;%f{Fk(t5%(BWZ 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 z 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

1O6U$?R4PFgPrj|Ggqps z8J!}zr-9l1R@oHNz;j+~i83!@R z14(Twh*E!+^n41XwPIjkk#xDsQVB~C5ywG0q^WVgMmjqKmPhxT^Rbw;=N6jU{W@$% ziH27Eazqyk+PyfFb?#gZ91+I-Li&s7d|@$@i7D7@ZNjI(LJdA~^LEEkQ$w`~vzV;#93dW(C2L(=V^{-KR)v4Lrs%(Gyqn34{E*Pr zfk;Ctr0+SRMShi7`^ETrFnv)(BT|dx%ZNu-w3Ju(AoY-E%`3{->zSa>WMuO>z2p6E zyZ$Tf$*)$i&oV#~P3%Ge&oB6@q$?l#IMkNwFvb>~df}cEW&{ZE({v1SX#9YDNY@JBfRd8xsq7EC%&xDb1+x$E(B^ zey&G)|5g$niksh7MDk%^o`CpVPSpexDau?m@osEyG1({7;SqT(vD89dKD^v*NItyG zEMqXS*$|6na{67T%fDC~$8Gt|K-#-pm{leGum=5m-u3-_%toQ0Xd6C8MENdkPCeI@ zfM5CDwMYRrOvLriDS6x5K>s)Gk012v{88~(K*0)@2v9imWd{klCMS`bJoR?mLVP3?0qw9Ja zQZ}*9nZQgU=u#%ABWL78S--L&B$Z|dF9X+h3B9cMc3G+B*LOK(RgR{JQIrJAVyHTL znGUb@^_a)!mN7H6ny8qGA6=Get?cVeGv))0TNQ8c?tD;{g;WIf+3_?p6OXXGSTY8>2Z52OyGge&IYoJ z4aWp#D>jc%hSS9P`Pp4no?2u{W}Cd%Y~CzP1}gYDSYm{4_;28n@lr2AchE1Fb|4ZQ z1ifKd7roKqGtxIcXW|)y9a$HWfo7a?VF)hU{gitLvpIu7rW}}L85u?3dy01i#D9B% zJ+Rg#my>tttv(Ro8b6dfEeauMFiKVNPWMFjs$pp~) zq0FKc*AbVfn4Ai?XhzkAOB)~|gQh&I{K^JdYYe2PmDsj09oQh?ena6WybmGf73IyR z?Z&>;Esdf&yR})L&XjO+a-vcgda=qZF>yvRy{}5>m01Y>L`e78!(x4n63TduFG&x) zPJ<#Qs06y|lb*x=*Dm0>C2J^|=}Q8jqcRsW!{yX#7*x<(jvdo!{qq#jD}G4en%qNhkRf zMxIjzVp8K$3)E;2X2D{M2Ww=X4r@c-nX{?nWrdS;Dj%S7nMf$DxwF3mpO??-+IbHZBp^uL6qDO`gA_8I1+V z@R!$e2Y59{cb3fX1M80PMeU{Ut1iY>{88m*Bm5&&Qax}DiD$f6i$r!iIa>M!nlMFm zvc+8i{2P}PQu!R8-vf=KP5s|Ad!DF({~8OP#eA(Ad^O+if?0mwzgAQz476B-_0|J*wsK%{pH6v2?s` zUz^wG1sM!?cnTU*59i>ZgE&R5z%3k&Kt|ECCg-w&a(1jNU5Vf%Q4BvmD!lvUdD$i`$IXG2YY zydJ@O(odYk^*um>!RO4!MU9I$CJ6~oja8~5e?T4GVIs9T*O>^Zx|z4h%~JXf*Ndk~ zqI~Ryves^}1`$CkS{IqPEXg@S#k0;DMLwqSzWUd5 z`{{QD*dxmmTQTh&db^E$7bc{&Tu%a&!p3Fa_vY?1^L9zXP^kh&D?Y|1?+7Y-G|@7H z5(AnxCJ{(p!^!RRsOfw@FoA>Y=_6Pgq!>eoMxu@63zJ5^g-1W!7(Jg3edRvVTq~_ud zooIAE--idx+CpRjvVNbq8krAEp+zqQs`^w>5qWY{k;~Y ze(qOSn23M3sZ}PSL-I@1P7m(P+K$yzQjp1uV(!sunN2gsChm?gFI6ubpY~y-8r|cr}ze!F`T|KY2{{Sxw z1~UrZ-euKa0b3vpp>J7?Jm2wc+)?o9!Futs9L8suM4%&T!b7R!(R0fqL=lS3qux$K zKJ?qlZSIO1#zj*O;mxA5q*qj2p1;fU{9l!N?N_H15bfI(+vuQirMDVn>Qh$~>xHr0b?|JyIEd&+7O{9%@)kBi$azM zApNpoC975Ig3XB2Fpp*1+<;{E*Lkk5K0(bo>#VYk)qYz>LH~O7aWEKT(`%{(%x~g) z64Das{Qwl;yZ)np672LP0?L5G;CBpcjPlyX)Kc30f+Jm~I_vY7Ez^LutaN+7y2)Z7GQr_%6KzyZ5{ zq&El^1N6%0d|83=WoW41gX zJyDnk#e%Pl2!2ABJF{?}Y1~Dj*`e13{Ba^jAY`7{S<)$x5{?Sq-dfGhj_AJZ>6zFo z1l!7S&TU3Fj1tZ9v4@!b7>Z{g!ebj4m<>0+eA>axmXVi??YXPV#$gV#UfxBI_c1TFSoFJd4fm;>XchMlL z5%-+FcPP(i7*xVwT6b=|Ef zyX`L)++d5IIIRS|6d+k=AD7TF)K+`|+}!^F22||aT)qQ*Q)7s+I&r2O)bF%4+|!Yx6**;^zJW@j(K(Z11T9>MxK&d+TR&&+viv^P9}7Bx}eNcgITlzK@#nE`U_yL$nx?}G4VH? zuN=?oaSAk56VL)+OefegHLnRyj73<$IxTOCJx? zj9XKP#p&Z=dwsoDCm1x@NX{l5c)PEu+_=Fp&cPhWu?!10B z>$Ov~yV=BxxBHin6KrD=7qfp@>%AVHC9_x+=aaN6%~4pNmC|e(aDDZ;eoYX@Y9;EdvCU@}})M$kISLHM@p7r6$sVNUr)SNcDFcoUCrNd9v+YX8HGGgc~kE(>K8WA?% zyY_&yin>Nv<@8F*!~JH(o_B8&gp@j~y{!mN%F|!*g_r5Y61G^96Ct zvN({5SjjF(q6bamLkp|tW|HgOF-w-Npb%-D>Q|)(NWpuw=q^fDZP{b3l8surp&KKK zk|E(wBAwp6lHtZP;yrVA`d)$8Zx=c=AZR5gY4Z!CbKRcns`2=n;E1X^bFc^h_jIql zKnC+=MWOQVxjLDD^}F0e#h%*52V0)SgN_f1heuQbPx%RuEcORiT^6ZxC&VNVU^1lVFu;ogFFZg+!qG zhh9Nny|!b7wd;JKMdD?G51e6RmYJRLY=H<|T}3! zIyFmOFNqvF@2LUi*#imCTKoBR``31&tzu{wRd!Nzd;n~+ZoB29afmBi=%M4(hKih4 z{Q=-%ATE5r9$u}b;_BR3xl91bOS-C1RsAf(f|E~% z6zPtR>6uL{wI@?e{pOHf-?o!JlIN7H;CSd=o>^ZtIu(S&7NVR!Ji_`5PLK8V7B}A6 z-`x(l_J6`=E`zdPg7I)A!=h&AGcx5QXl^-49{;&F302BAbG=7sbtlfC3DY~*C0tQJ zgDXQEpfW$lFqs#`c4%_1TdOQGXn|UBY=jNBm1FIyiHu6a`}jJ61@%7{9l3KL9EH z<7&}MR|=q-?+}Vaz*A`9#(gU83^;(TIX8P14Dl^BJ5*!Orlztau!rhS>L~7!F+ytS z?MpmfgfS3JFDp*!eC9pju}_zr=^WVPfVkc6?piF++3trD!hxE!!0(;pfo}zUAKT7) z;^9a;S?@myaX0{mk?Cm=i-Kx8IVSF291ll#7nkFX!8^}(If<&Tj}wa`PmZ)tb4K`*`LRjVHGb+-c- z&Y}>I{gsBRYV@sUj`+DmzO{m$ICU3G^A&sL%y=Mk*`48Zpy6=JUg2er;y8}i^_F7WMkwPE|}TyZNuZxL2c>&0eb=|s=4KdcrBlk;?m21^pFS%jtE09k*KT-zxM&g zjtoq!@^I}$Nh#gsDEH<-T>J|HCvG&a@^A-B~0%lltnP<3%>SMfGzSE<%1^t zea~ojMUv*nGFyN8>P#@>a&?uo-YKbvXH^VX%yTQTId*-m?`qh`nAZ&%HXXPX!t?nj zRX2EhFSHwZ*DRoQfMjog`BsI7jhTF!gZwC*Y5OqrG+(rQd(P%u_$lc}j<{96MGZD> zGM8ZBtgU$0#K(!sJ?BF+Aq^7eANI_B4c?rL?jdC~?b2>K3gXj^&-;1XbM;UHaup$R zw`*hv8sK3Hp2$74c4tYLeJl!J>VBX5;fNphCZ`(TEVDl8Hl_I%F|-#xUTis!fJy(8 z3r?XaMdi);T$(%sRnq2AW09OpW*t&hsV~} zPxz{21H)>kIoEK3f`Io9qRGQ0#KMp1@%%p0H8F{z(dX=Nv;Q1FcW~)6y!iSG8LsO} zqwq!W>-e_=> zYQE@Bpx(D^mxEtlUC#T>ZtgwI>=N^={fp2i175+~TjyzTY9FnS!y58+I@!f7J{Dzr zFChSKlge6=-PdU{xZMhprr`>1sMz!V50m=0h7QBkogh`Rg#)K2SexS!`>XL2shVq7 zUuDNe?(6R7Z7^f|6{^-=q;S%7Ov@l2*`YV$Q}dGax*o}(8mQM1%aisS;H`~c-YY_9 z4aY$(*c~n!q_@*vbZms(g+L!9)&e=M4@pVfPFupB-(Pu?oM7fc5QLMCa<0mbGfYLV z#Fhd+K>UtR2u@Gl0N#I>)SBmq)3S)c0iqA{nwt`fDUC5m098^yQjh%uI&5 zSl`(1ZA7%F$SXiaiT|bQfML|ID)^58bh@YuKH)p|XLxNmJIzP{)pnl>ySrH977 z?%z=K!3SPkYrQ1kHf;7S5lTF*K6g)XdeC{T#eW1wTYB86@81VnbT}s3U!>IzW$Jl`K5zB}dBD)hkDm%|~-GjU7wVa$~C>SIJU`P(@D5FI^jY~+cCq5fea!;lxK{Q$rX z89&K;MHavID6A`|f&5FY7XTrQF(>@Y%jx3TkweA?tXFa#hrVrJH7^2yXx&5LYygz2 z5?4x5ELiU{e0N`?MT}%>?~pUP{pRxKt^%{PKbJ8|wE*bn!Q;OtUQllBltZoi#G38S zYj3}0Wfgq|eU=X)R}GEBVj`Cf_hVs++xyA8si38E9~vqsQ(Lmgcphd1;gOK2=7?#C z3pOg2-KnR-67w1HGYs9vFSa*2+p5+ccYId5UyY66VU6ywRKV`{d=w6Wj|n6L}yFKQf5qpY*EiO|sCLq1NmFtqr-V z{T8dj(fV+~OtG;|UKfrec@$A;Pa(ms!&ZUH>{y$E06sX=XqWU$lqbW*(GYJO^ zW!G@<02$;PZXR7IO-{(iv-#s|+CE@I4-D#J?w(gOlMGWQ{!(xC1QUe-^U|#{ua~gX zX65$@n>RF{(08R0cj@iR!(}}h=`_HHJZ67Yh+kezJw7;HssqK!&EgyYkB>t7yah(k z4A1kl;^gATKVhUzuModEyuI3zpy)d?fgnDB@{|SSBv~8x8I<%+n$ZKb-`;~wXMD?$ zR;ub_F59O9svO7jp&tiH;~EYK6x!ei1*cmN0#Fu8m`xT1>sH&qw<7(FrTUN%p_C^# zOVdM&I+nLwj7raW_8sQr|K@9=Zy$&tOrzW182ObN5sK*+`AsDW2=|2nGreD9N9AuH z2>g&2oXDd=&ObE&9PEMmJtL6&dMv#UWCvO&Y=gN4~d7Uo!7goeC81J`<)pS#) z(b@>3Q{E2D!ZG^OyLcmDvPE(_Jb|VK?*`r+@#u1nD+0w)Yo`)^@KU|x zz|V0{Y->JWm2&rB$X$OICH;$jo}7f+-UW=RK0E}&KL8kks7$jF*B7xVsHuk6aag}a z^LTT#JmF%tz4Xauv~Nz(myCQ$PA`-djP@#He$imzl`O%REh10c!yD$W>#z0@q`y|3 z>Ik)9rGM@r>m~9(L14pQzY-LmoF&q!?)rh@lA=k`Dfwf3W6#1k6KP>80EXuDqvisu zm=R*D*1qr|fx1`PJ+q8+I)lMzz4?K6Shwf!SM%UUz31~IUls<&sE@5^Ka0s+%BmQ; z(!nvEBVhlw4^J?j%?kuO=TY;=icpgg=7^>Wj{}?95ek}CbkOu`J4``yqSQ*dTIS5G$pe;Gsy?bV+Jbt z6YSMP-R^ly!IZLiaEG1m-kWvOS@-MffZOECxltMy^Purqxc(a#9~dr()-qm3c&&TL zn*TmZ#Quf#8<|(xxkMCBC56DB!Jo*NFje{Yf})euOJg!2obH+d0aPaGE6n4vM6NTx z*?Fh>PzNU}r7T?SYQu*j)xUmRxl!JUs@Fn}mZ& zGwug(G8{RZE8lkuU@~u#&s>X7iRML{kQ#32B@jW6og{%TqOX$-@=C^8!1q5+ruZjEa-3n7>djcf|a4Zbn5x5ukP{-mIx6t?{I z=0AC~s!I4a-Ez*_!}l`s@+MlcgnW75vHNzm?x=vlD;!ACfud*e?u_Zy_G*0T;!>R^ z;!U*7Im}pr*i6apNNKi(D7C|nj=-jKY_b=?sDE&etu#;jN+_x?4$F@9RgjRPR37K& zKFNuD(L7MtfK|$+As%EVaTp0Is9RlFXDu;LwZ=26ofe)Q*bIlfdR#YaZ)>;4bM z%3*CnNt2u?M}nMzKK2`$Z8UgQ04A9NVO0H^xb+3*s+2fgAc{d@H&+~5l%_`0a&W;mX z>5>&`4z^7`!)JAIH_R;!{LP=RfDSyfLdri4{NPICF8V_RJ7@m$r;N`U4AkDjG0K;< zOrOC^`r`j)V?;y9Hp860+I<|Zu(F>L9Uf_--i%YbTDFv@uO?5fpiN07&i_j%v6C>z zFXGNhzl?gVj8}+SZkmN_%3NKa3O6~g@+?0cy%~ZFXeissR{wo$J z-_FO1KEyeI?MBd`!zdbKDnnRk>5`Xv+}B>5Qh73Js&h z0d@7(sl`x`%Zow4rK3@Y@S^RLRl+HrQ5lbkpd9hZB4u0R2#sdI+nwz~DfA|fh&zsu z4Xx1KM7Nk9kQM#j&TvYM6URNjvos3%0=k8&j*0!f9NBX4LqQmluCdVWJt|iEv$V?^ znkFBY;f%N=k{f<_4m_nJw$Pyp?DVITa-kWQR)t1ODp1QMx?2rgBvatq;x?kws$zcATO+DT#Q_(EjT97 zRI@k!ha~T;nu6+>iij+t6w~lFNR*H}-$1MT9yZm%Mgh?>f%l?Fk!f-#zV+fV36Jx0 z!Evl8Th}1%Tv!vS-z?tea=fPtZj<86$>MGM_m@Tcp%jDeSvi65xIt!>xh5DTrS>}{ z-*>7hUu#WoNzCyjZ{dy7(s>`gZ2O)UA)iSn30Ar7qS>k@SK*P0kSX23K>>JnXOb9~ zAdom#4=e9pW=>6mQN;4wVcpPgJ|+5bGp|K-yz5Qm+4wo635?)Vkx{Dfv^KD=i_r2rwgVkveTQ2K846W7h&uOeF+Ln~yScKeFE>CSxAXl@Hk zoIx+ohaFdzV4_t?2?fsaERt^SP)%*r^3>U=bbAdM>P6S+qw>bKcm%y(p z2U@5mKM)}ObFD<7Yqg=Gki+AavyD}5uC}N$Q%Pf&IP&u0n~^`I|GPqKHSc{tsTbyR zx6N=B{bp+s8m6T5{|UV>)BzFmgO{RV?|S`xl?*#63j%sf)_xn_#-Bt>xRzi#Gvz>UVLN;ZDf(bTG>ZdDySlG_;TIqm?H}a1~2MLtcByM$L&hsl# z$6~7c%W7-SR3cYg*DfbtE&9DhLf@t8owF7b;HIRawoXT5ST8}31Yus1?LSR!xexw9 zLI?S_X2sv->1MUiJ;mxeh{)H|Re8p&H$(%+?fF+QZ>fenme2-XT3gWV{a9)8fiCau zp4~^B0j+{BZb(Nb?o4?V+~7}i&`Fepn&8&Ui6^nFd@M`8mYzwenR)rjF7%uhQIXM; z&^T2|&O?egO8Q+Ai?+BnLs_A@`Rjwc!ok0J%4+WxgqY#13+q`j%SKt51+kCiq;tc+ zY-|3SdD*UeRz;xJ^^!|8sbS!@xF**M9&Kf*&Z`p&%2Ugzgv|uqOQ4FVrxx##!n~rz zVucjs>TjG5yOLxM`iJ#RfVG6-Q<84!o_NhDg(B)Xo1hYfC8co^RRP!OcpO`1Tvc5& zjmUc0oK@7`IV58sQ8x6y2ftGgXpU?gfDAfTq>4&VQi>pE-?dpUI13rh`te@36_V+}6c56#E z&@SIB&hLz<$W4l}{ZcjROU)z?{vt<{mc%^Zn_u|DJLkHHHY)mxXl3|NWhbB6=WG_W z_FmEiaK+@Pw4y`LtMM|GbV7H_Su()MUT@t@e{?lL?Z}W!g!1$(O42}91=iS#XBqW_ zy6!Oj<*$H?-UCE>zE;8QuNL4=ElsmS6t!!O9|h4_X2@S?f2$KbBQTli=SU#8$56UhN1TLR+6yuhhBdC5NGy`j|AE63LY} zpoQi{`nU3YBiAHpQO;vD%3pFuJ5|s^nhSjhG`ppC+4Lt|$%NFdVti>V_c4pfS~f3~ z1FiMg$KF>EFg5)jEP(5=!$P~$1Y#-uHP~k_xisTYKf@*_N*JZ}i3QQ)1tyLY%SJIL zKM&ut3?8iH%z&wce8+M<#KRB}P)PirBL)5;5Wtug_)u_ye$91)7*rabl zSP_0{idt@LP)B&tk)kPb56z0ee76SrleB+((7q6RpJFsJ*zl9#t)_FN#){+B*MhBN z1Ky6@pYB`WIIlg6uTz#m5ly*)=MSkAR=ZO24lgwVhk-l`WL!Dtro)v>#blpiD`562 z1r(~E889zIog{|ce7_706|}m#g^haC-1ON#ac#pU&$q$^%=W3J1xiV#P}WP~^cn=` zq;T_^^$U$v3t)YNvo|wMUbjk=6pBLjg+{)&Y;xWw_S+^6u!3a;S81yd}8|Sc1h&!JwmUGa#IdPoKmt1QhIE3QVOM4lTHyU zu%N<6QDkJc*pa%*4C9-1T{r>d>=&B4Ur=eQKd96vF}Tsi`a2%SpNihf$nV#hW+EtA z&WRjF%{{2gax_F?>hPj{qjfOkjTuo$8JkMzh`MvYFFtyGqOV1?D;?xZ?>m(?x(~6w zy}#JD8mW5nkp0YCHzKX5ptRG>&&C%td)d#DrRZLLJo>0OH@?-(&pIBB?Q^d3f%Sqo zLg8D)lPTb1euaRRF-%JKSG`Lrnm@9wY0rHLACZM zSS0M7;!{jel@*id4iCur@#XES6Zz;qOJJJlrduIA4}5?L*S}64=+7uxgDWIqu#rR^ ztFuFX2L*Da8svpM3>!J8MW|zi>784Vw)cId8--P;uKLzOic9T??H{u8oUI>=7!%4G zYT<#jv)N^>A4T&qlQYvh_Xda_nz?Pyr_p7iP(9G0%w=o#@Hjh+b}NK?$ITQWnPcAT z((|6fHWiQbyQ6m^@`=cW=;^7FcDk5MbXwOx&R{2WM9gS+PmCPnR$0 z-JDm}*c{*$HP*`HLg%KXL``j(!x^pQ)_eJoO;J{ST$`v}uZpW_QaY6x>=^xJMP9VX z&spww0pT%UxYpKhwuBfw>V@fsbUE|PpJfjegI@;MQv0l+pYc1$4(Z%a)asBm>#22( zLv{HcA#WK`)FDiXA32jSS;Z-kb8Je%L7FB6Bj{;z9uS)wYTcMR%{e3d{I?En&!#ge z?1kX|juU&>5&rPae)R~6T4GzUgy?ffrK|+E+-F@3{^i}L4+ z&T^F(Wn%eCgn;i;3KUr0d@aY8+uVjewMbz}q3N3FG}+=9lM08fIbC997tKEhjLn3# zwdjeen|o~B7Nj*~*S9nIaI6;%5h;*Ex^xqo9 z+XA~@JYidgAK-mAdQ0_fm?5bn5~eH?1Q!$qF&7k!=`Q7`zXx#YcepS{*v5RzHxwOwh` z@%kLxaS@tng};OJckc^Y#$YW4kjWcUV@`Ne|DH=#wkR)Lwce4Gf)lZWDWl^$3JVP< ztEKbzDi2Lu+_T-ix#V_x>p$JV;^bSJ#*!vX)2e=oN~EDYILo%a>@zseI#a&*a2bs? zQ#&Sh+CE{$C6!IN+6?CB?;hnXI(E14WcK*yIW^xqek%emy4jfwOFPgN#Ud=Y2K^SX zI;@>*PM^^;32prCC=j04OuW)ZwJ zJ#C?2VLf)AjB=8aj-vZrE-w+MTOpHTPA^pn^ackF9#l0vEkZR}ZuRt9I^B%pxP9h* z=dD;Xc3-}l@e|EK0&^b5-iD-$5;|1VZ4bCLMcI;tBfq-?e;#ior@T!qL9m3AIp6-f zQqS7&YCa@0kP}$wtvN53M@q|mY`N{u#_Vq%ew^ugSbIg}Ec=!>y}FQPj`?}mAs}G? z+%|u?5p9^NsGbgt3IYBnGUZJN1MMmh#()=dw(cLPaxbFEteJ^MVDS*X2j%$7>AIwb2LG@(~P#PKAuvH=^n z32=;4IQeeHpf^HQ%Fbf>#??$=b{$9F{JA`~A!;?JXE0TYl94`r8%=RSJb~qQTk8ZLavX&2}9k zBcIz)gK0y*`<;DxM4k{S+q>)IQrk^pTm@ww3{$l(a^8JOSEI>{_W&nt!u|z`kJJ5Y zi=GEMfHALcyybiP>X%J4>S_C?P#zC!)VL>dNnvd|BKtSok^6O0b2w2Txz*3!gv-M3 zOzbg=ygCEL!dcdDg-mJDGYAA7_gHhXj~MY7=ba;{bf! zeiak~tJQ~x_mWnbZnoewB{=kUP1Onn5xlwLficSp%TZy)&jN{bMES;bHDz2$4Ij5$ zS-Zu>unA1I;)+e0@${ZcVio3?MUK$Nq%IeKi{p%MgbzUA!ncSaZ}hebVjIt-W@D{p z6*8d`EY=11Yicplw3+N_fYg!L-e)RVcKC-@S{CdUy7#5~uxRQZ?*Td+E^SJ6xZg=|0 z=WJI4W<;*%v(LqIKNuW%d4KVGM*~PM26E_m^KFWZ4IMTZ9Y%>yc<>@>6LmzK)H+`Q9KnjmXza7B_v#lf!Y3bp9~3Ga$N zIq%@rxqIr#2p@78SaLhmO6!F#Ze%ie3nBlH(+(p}5CL(aoAH=!MB{+>dXt z$6&_Bo#~1)aZ0Pe4O+aMP3$89$3jmk`hDGX7_e3B6Ay;yYeWn+i+zco zHn1*|rs?5K#j5PNf#;7>ph5!eS$0IMW;)A6L}s_><8W1au#W zZXO!DRvD0xZve+498vP^{WWT8kPNU*!+lEcHSdEZ(y3yvS-9E?hb8#u;lnSUj8BD$H0WsjU$X%!cz1? zmE6vC9Yz+-A~W~p-wdLOETgns>_*`Mk}w4#p{hq$xUiOY$PM9V3HOp(MpU_!eMh0# zgE99E8)@>kYmB6wyvrjd$F0t|6r1a#%|!t)f;fapL`!>*^B=^f1^U&*9L=5Q0Vkx+ zFMq_k^`4lEHl+6V6^A=R#w!TGReb>QT=mAe`mEt{x;z2sEAaqRfLS{4K1K=vZjw{+ z`n4H(Y)Bn^=dC7YR~?gR%PmtaxV-TCQQ8ADXD=(xY&lVHeKx`YSrxz zGr~LJ`TETsAUJ(zX7x>i-m`yb(ZW~{LhmeCBJ3+c<}ltrz_q;?XxX#s$fAFh$<1m+ zfpRDH2QJ=z8?nq!tI#Kx*0UNy;vZsmXBoV%SLb6{ z1r=~WPTJeI&Nqd02GK8}A-#tKJ>Iq^q`r~-m&AWZvs2lKGCaHN+q@$>KuguVi2JiE zHL@Y=a_D_J&jkZO+lsJY<*i&D{?&|{yXze?uzgB?BCAU!yx#X3YM_UCfpgkDkbep) z(1rrPy1_IN*RQ@nN43lo`J{>%YYw}mqKJMbH;{t^nHdn7FC@jx*`~3HN?pxG9;F8W z0`he7@Le}!{L&FHXU5%r-BrOz6EveAF;;7^`B|cj zn!Z=_@x!_lnS6sM=3KgDs8wfkXim}?!5V$PEGPx>T8YWp#2s@4=z2$2X*SEYxV~w4 zf=^lVA`r>BV%_#dS3Zzjh+IeovKd0GXCFr!Yp+P$LStbNCbnnDrFhrl-dKKiO8kd~*8$nGtN&lf1a6Rb-yA3H}SI_O<=1dE|4f z8G-btT`@LEKV)Qyu(KcfB+YY?!nj_5Pblhisr0qhrDVjYr~WZUUjqpQRC@BdWT+sZ za)~d?pbi3!e8Sq8koU#{ zRo#}WW7x6(YEz}EJmgq;2LeJ*&*SO753@8D0Fq?@kiFPGPnCD;>aW}=$6oJ&$`oK- z0Q*@0arhs}Yj@srH&{Vq=XoZGM+P;c20~Vy_BOfk;thx>M)?itau(ZIx@a^UNXFqq z9O09$-&SZ>?{rFKXZkmc*aXD?W*phRP4&V|^ghg%B8HqVGl-SUZmVSY7a4l!>v=b? zChs+&1!&>&?Q)m{jsbX)v2q&tiyQRBdY{2fW}hoe^82r&Un$>e=1|K~Lk5Xc=p>gW z9l;)=2=DxD=}CKVC^1cQ2MexQHSx>jbX3h@s^X=1g=t+l6jtcUHp&vl%Dn~P!!awu zx$SXm#JIo+QZ8*Gp-#6M&AO?=67H5!e^}uhBN@S z1xNr;pkc`5>;5~&nhT@JX*jmuXwGYu0`qKD(kucvGx)4|i}N0f2n- zMl9wlBQtN*C1LBY$8Z@3J{_pxa_un+NZ^+`rJnZ*WiRLJ{Ya&u*$*60m6OL2Hv@n> zoS1Na53*h9qp!bveae8Y=evyki|%;3t$#dZ?`1)|QMB|*G+q5y)<&24k|+|rOT3M4klHM7($M2p%525wlvK~4 z^(lmhUOXNasnIg_+)`SxONEJscMLGP;%cg z2B<8nQc1QiVmqcJ(-BKg|433EaPAUgZtpDc;ZToEYC11Nb|fb9F+&{ZIOWo_vT%@5gNd?BHS9w2^&=pE_O8?V zn+qS@#=cUIfVUtqplB8tR(hx-{{jkWt3SCv{V~OeUsM{+YiM_JB}sG7%sL)M%_cb?pQnt!xM_@rjt31j2Ps<$NmfwPlcU`UXPP1m0`=G7m5@a50q;BDc< z=OnS8@BbRg-Uree{Pmur1lxz=(03!$5U)Hu0z+eD2d{qgwTw9D8P-ZNWRidwwhD{J zJqDfIC?dT~)+5#<^YqE7;z_9+g#$YVB*KP+LGBxdU(cdAJfk<{f6ndAxEUm0mdl^m zM@w3gYUZ!fMIF9}UQ@#3KgVoEH==ye_#>ZOO1 zoV?T1p6Jd<{9PD)-LNO&D0e^WO{~QLX{VAZsiHRUvei;syd(NO8!WO&iZiZ@GHj{4U{`lH`7fVa&7>7ux*LQi7+tv`flO z3_h)%4bZb;`t>YaL%3CEcfn8`4KtarZfW$w(jE*gi#{@36-#lNGf_AQ&U=gaVKWJd zhxf;KHl{G;VCVJeY+XQLtoo*X?kf8yEDk_l}4}S%2u%EwV{R1ud(8E9p)@%6+GS zz&SK!Li64J0Ao&3Yt>+n9EVZ#zZ=j)s>0(!R@JJve-(D=+*Nz0#@qJbtDF(^j?qd} z{_tOufSYS)`XaFL!W%rXq4ba_cGXTY0pDhYuGxW;_S2aCg_a>48IE5AXq8qemR~18AKk@$KcAr z`QhB@Ta$o%A$ZB8%ON@cP0le!u*JP=9t5d1)=Y0htLq10rgy7*?x5|CBratRvnhUG zUhQZ#gECa_fipV7$Oc&?o7r1))QM4{90T9Z>o5IyA4O+9KI^yyNdnije|VAxUSC{x98h7uq^0YFXNwZ?K=jz8D0 zUIH?e&9V&(A(gtjrz{co1M z2OR`AP&7aEu%>^l=Z^zrz@(Edg^#>NMRsitPBJ;YSWs}XUB8%dv|)UFJo(A-(lrH$ zsG|x^T3tU_xqr2%e(4kr{3jH^V&wYM9)sL}u9{N}0Y*f3_V&e7h#M`}N z>o_?MUbe1CWd$Yw1l)Rqb3j**ibitz^z@{+Ng2SPe-U=qH#ZOXNUzCqK*mf>#nhtL zzYC-VB+{A8cS@eMS~kw9I@iZY@#{Sa@KQCWrLUV0_ug^mgO%7EdB)PTN&-kY)Hp3?Z z77@UO%9$4^GoqW*THY6w%J0SWkmf2OL$>qPbz7(7M!{HhY$O*Z8;=UY6q2=$wdLx} zX=0p*lm6_5|c7}mR*SlSN3sWe?CgHS>8GD` zZ2&3U{=Zj9LhEQlvG~f6l`&3!~bC>9v1}i!Wh5 zEvdhJfO=h^R$bS(oL#>@yEOjXj0E{Q6v`Xe3yryiH&>>M-X_#Mh4=x@PPN5|8J%_; zoT}3xWzv6MurF7No@c9iS1uph`>atq(O{n<^hLSLVdnl~-y#+*iU@eM z`__n3N5Md_oC}x9B}Sb?*r|3H|kX9uVNslPip_A2MfJgfI$Qsb?08PJ=pV3=dNcwcU+ix=RkAM zszTHd`@kbd#Lp&D3XGX5hzBZ&EERZ#lEV^wJWUJ2dr6K5L??$`b$g?fBoF_^@hpUx z^k`9IRo62ktW3~^yXcL`B79366_=Ae(Rtt)HDVfM-nZNr9%v%IM!}?Hr*E?Wm+t?Y zX;7yuDq}nU;bk%k?>Z=5x2lY+mIC`NFb$V*PAm)?>XvRRN$QU0+q+! z(-8))S*YaO2|#5=eiPW;EqC794GS>#DymGv`2~+HYWIJz0IN9(O3hIbz3rIs`Wn3v z=BbKE*S9%kun%=3pA5gkt)Di;#OSO1j`lu@w!Y1LnCk#=@xCw_Ovl>3f#i>)%3#p= zs`LA6*%6Jp8}NU^sn#arnC1&5hYGsd@E{ATHj7W(j{oqjo32sH^jgpxPF+Euvp(sL zcc3HhO>*mH7-qw=6Te!89xBN7bfxX!{Zzz%a?b~czhGXw=I%e)AZ^GXg6sf<| z**bjO`C``Bf;LnsC^us!1N{UFc!4U{QNJAmR(-;>Ceeo`A7Qi_TAr1?;R6S8TZ%D~ zWBwIaC3;d;ys>JhFLG?df)AcWf1StgXRTMi@pN6m6k7TNu8Q%(@_{Zy`&# zxswFlV!gNscd_wvHihF>PuTESFhc_C?NrPI-!5N4A76wiSn1pJMa&#FnPwi(3O9X& zoaac!LyV&_f45L)bDA>|pg~C{=QQ;>UVY{b=)q%Iex3LtY zaK;(`$Cx%!nPpelWYlj+0UXo1e$R`q_i(ut73p_Ic$lc&ZcKipYxzm5?kq>}I0zLW zvUq&ETb!fvPf7X+S19n$pZV5nXR~D}|1~f0>3V#8_X~_@o1QzD`Z7BF*U!Hex>vnC zumLsTjr_*T_FyJnwonc|cNEas)fml%uz z(%&Zh>xF6S^M>+kVVhO-Oj*gv;j+iBT?#i+L{XN4mcW;ff__rrlT!X&^wE7ZlND((B3PqB5igeU1oYb^mFWH zdfjM_J#+3Zb3bx4Idq(+x6Nsp^UtnYJ>T4})X87q^{o<)KK$_BR7>VQiCumEv9F^s z?|Ct9hWX`7Uf*;LHUrJ6xH6XSnxfS>9`nw_)zgBWRWFqHEUwerd9cbwE`PjLnA*Q4eZC9AAO6|m@jOVM;8%=jOG z(2Z|J3P0Q>KQ~oIBW99Rp@zupj}O&GDO)dGPvOnJ^rHPp($_Z*uZu2>DM}Q$j#i=k zQvH0qNJ}nUZg1?#1mf4Xr}PJsPvGBeywHo(yHHV!&%A$J32~LH45(!1EHm?WT3lHM|l*QblKAp@`LYm3VCr8S5$z~X2tR7{A`G$9dnfP)Ra~|DG9avrr!+ldKZwp;5 zcicNy$+dZ$Hhx1nfVS<6uRDKd>|W{2dvtZSb?=`QMb+S`#J#?-O;x zC8IlL`t60Zp|_!~_-gYt?)sGjW5ArwIfLt6x3{k^#XbRrE+_9mz8w$al>cJY zJK*G=26ww0tSs6Tt#+gjFJ8hnr|p6=lPm5c!|&1F}%%5#qhgvS-WbwT=y9DFmv zXIH=fcg_DEV-2C|#ntzo9Jq>@RgNcwT^BDIq}rMa3RMN!#LiXt$3V;mSkJTC4(n>&)#xz$>tI( z>4e_JTkH`?Ki2Puc%P}c4E>0ctuDva=D;le-6U9n?C9w|<6+8;I)3aU3mZs8f(-Y? ze3@pm!PUMBbe~jsZW_gpfNV*#sVT+xA6S_hgt9U;QC(-Vub=+XU2dYcIeofKol7p) z((r1YU6Z<$-%MgX9vN|oJk542SPc#QY20*{W8mb63;*-=$3yC+r7%&ymLVdq(<6QJ zpE@!W^SEsTD+%$008$8>Mt@GA&I7<$p98xws&{tGR7O=DWLv`i+PazCC^XC%(RN>c!7<)%k3DL0#At6v?u2 z3JE6g?YP@?xpBnjtRg&lxWNa!(rY@pE@xib3LIX87=6(7UUxLtyf$yr;`ptQDw-}% zeeE$yE$!B9Z}ht#jP=IbIQdCw=kPCiG+fqw9Dg3K*>N1TY@(X~I`FT0#69)T)w?VF z-m(65-f?joRH)mobo1||-{7?E^^LUo^UFGIX|d_Yj~~_E7g>zqX#O~{Yc4kKS)Q1P zIU-Qw6Ym|)cB3fQD`5<(=SG}80E@|f;k#bQr*n!aa!Mv9ZB7UXtH6yprUf zk$?N^?UTEMD*u%>{1iWi1XR*d+9EblMfVnGcZgG=UgBgbi8ukW$in)YvXFSIIURYq zMzOj0+}N&P&45h3?9<%z?ITeT*+*H|;Jx+Or{XI+X)CFP&s{0q{1!)N#O3JoEE-o@ z55+C+>&EOV?PebPw~$#E$!D{s{_+Q|diQB9)AG~ds@d$T{<{*t)~cJf+8d3~cMVaq z;sFoys70Xtbw#6#1$niHN#qAq)J-P(6xj6~K0U#!+KMfe6yA{Uv@E+} zlmANRUMQEncIm5j_iv_OfI9#t8_Pv~0`a}>M|Wnty3kXb-;PrLbAUeK-u2B@_&-0I zLH9Jk4;rq0HPE-84rhBVvW0EebX_`mT~-&1Z?}w5yJytB@iLcR?vCJgcGnv*I&v<(yeB9!yvoz!Tl-UB>3R|)5B$mf&9TMvuNCj9p+l>R z2kYHcr#Zd4i-#Lvn4bB~QQ7LCXlGWKtt0!<;jYIE^Y8WPh!cOc+G!JfX8UzU)$IiC zzwuQY5Xjcz6r<{P{m}6C*yoL{fx7nHKV^Sjb-}I@v5&j4OM-y%85h5nK|m;><>MpS zQ5*ZGt;KMS~BW_Af>`i+G5UW-DbZUEYS>K?gYHH@(p$i zDt}0OWLo+b{yH5&IOL;c^S4fPDnfje(bh@mMDs9!V#eW@o5RR8Df(<1Mjb(*z?9Ed z>b#jG@bvURzvDRg`R+~9cJP#%hjslpyM@B_4^|)T8b(ovd4b&W$1rNIE@{RxIMC15 z^ADou6*+(MjSZ&~jSVa>)rx?u8->4Qa2sVqtM6~t74&Ds_NYca;7@Mizd=HN6z&Gz zH}ELq_9Z`1qQE&qm*dg12J+MZ0iT;5+^YNi-fguxnr>Zhxi)TMX zqQK3Nx-5RGAC8@e-7?FnPVht-jYslP-a;i}C*%6Z0#;X6kL34~r!6S^ZTjl*iX_u$j3#HyqneH+rXd=yR_n4mCWmDHpsTM`OEli{0lnY^@IQqLvbaT97F z(b9-ZNqm>>l!m1=M#JyC`s1*lOsSX;HO06|BK1pW{i0S|>U|2y;OPC|WE*!R)^()1 zddvZd6|-sgTwVV%vcQ>Ji~hK+N6yE(^(>x#r}B-Z<)pyjiL%3GuMQo3;|A5#=cm83 zi_}ZMn4Ss#^0}9O(sMV|h3iB%%PGtPexjWU+mNy3pF}lQU%wnRpU?HP7iRq%5VD>X z2uoEK@gpYtR3}}F#;f5q7)33rR7~ng6P-!JLbp$oj9`rcL;S(Ircn+NLv5&XBuNyp z>Y?T{>F#EDs1ehpPH%hu7e!HDC4d(9HGEk_K4e>2N-wfY+A4D`HKv|Ii#&x1@oYLb zB~BcjdGQ88^3GygdrK2y#3y|r)F3n4TTmbM=K~5C;{KNxvIZX+$=-Vhg;E!~SN?ir zwa*?>R;Is^d^|Oue<5|zE#yK%BgbNT;HZ1lQ$WQYl^4fJ%~#4U{HK$A@n4WbP5SZ3 z8-b?<{dppB_=RE3v%U@F^3(IQJ^T0X-|s_=;8owYQ)g8aPIo2jt~wM6{KP)+mZ=AM zh#j&Rw@69{5M{q<^)j+y)F2<1LFow6rd(cEp?zg-w$4uC_gtxQbhaJsB6oXgIiA`t z>!&ZcLgB@KCKKIm+a1zAu@h`0V{uBGHy8J|eg4-YiEzNsyO~Phds8ZE2!;J+ms0P%svN#d;)_YP;vmR?+@&Czjr?Ze#P zHoqCTk#l^c>AMlZ3yE7YiAPBMiz_U&iLtjSI4En;Q)8Q=>k01Lyf+$znyhCcTtr&-l^Tsg>W8l>Q)+@T>L{GLU(J6LM1Sy?s7`+o&T7`W%-17zBkdd2?Q zE3F%NSXut_O*mrvOdCRL%Uhr&)U;(nZA(ENYVN0MJ1ezHr9rUkG09}iu22%vTDS6k z`y{9@GiF?K?VfAd3E6_gw7q1DE8oBF>v!*uxs9U0kt$SKY+gwTdQBQq15Do-TdJJ% zASQ90Dx4SsQurbD@l*(mDT5mav7}-Mr19Cm-`)MX_i}~&nCuh>YOwpUX#KFJ_rg~p zd4Fz;rtrDll0AJ(LyjsGqNkvsz=#7sx(b#L?1FX2o&j?ko&j^~H$#2kX*l@wLvU!< zy>Q?M{|s>G>9Nf$C@4sUsYd7xq+?EeZrG;B5*7HnHOsCS%f4A*$OQOF>+}#FLSt)* zYLkOXh*G8bb7c%xD)E|Xq?0YvwM+6~Pv@uV_@|+hbFqJ;$p0kI_yap9;o%|&uOCt` zwf@+|dXB`rKk`!&8kR(m*1c=$O6M}%YyR?^6RC;3*hF`%eu@B*py@}e{#08~e`UaA zQ`g;l{(Wq2rS=b${t%+b+LkHCcIfs^TPH;RkXuTL7^E=%&R{&`>>p}f$VHI*hz;v7 zyHol86!3kc^sH&xohL&i8~C}|wXom*wR5-o#PT!sHA?N~#}Cw#7ow-2pumKB&s}iv zzPsSyePdfvP*9K^Ll8VUba2@nmjL4GTMqD0x~OuRtN@i&(C&oQJLW_kz}i|mVa!OQkbRvp=tO|hxernY8cAjfP$v|xLIvGzuJdpIrG~uBpD=m0WG+szZFsfC*|A> zAz}U3RQqwdV#bHG9pd^zn^5Eu@BRwG%>jz+k^0cm&-8(VaGAM*ZNVk`-1e@a-~J(_ z7ADWXKO{7ycdGkSg?5~#CLXAeYAoRXrP<5&KQ*qa&x0$=5#SPH_G2;q&>Xs=d<0ML z;JZQGCO*wuz5A7t6ES{P*6}%aKu6)MpheY=LdryA-dNn zRLGBX9LJTd%@S~Siv|ja+i}}uNPXbST}xwcQi%IpO8hB2UD`tv@b;&hC8d%E+SUxS zhGws|t|>-))4tZ=-=dA`u~ej(mW$`$CPK6>KeP=(?rZC6m%!$=l%UlW?q&7{SU*B#(A0!Rh0!xwiOo$Su=c^X>+m~~?)bm!r$r8QxZUq41~2x+9% z;r^EH_4VUdYUf|~Ufn6DwXtH~;VYa>!F7Lk=a9xadxYit&jqcjf`WpAf`WoI3=J`{ z7J(gu!6N+-xs?3MyRX$15gqor7u!QxvUP5G?J+S9je%5IZhT^83zV==?zSsJi6UL9 z$NEX3Zv9X~qhhCSSC1uq7YjUOwoTc}R3`?~bjHg1pz6m^cv_n{WOC6f(Adbefz)PN z8+=((f=-(((#-16Hs+R7Y?;^gmu5VtBxt6(<>KtJ^eZ;Lr1q0Y$&_tI*{A9M6!WhE zmnh|~hvlPnz*6z%2G0T4X)hgip|6uq?L(#dc`NWza#}1+vfd}9 zVxSw?+N5S*nwI3DYTA;nemyCfqP@ml*OnW^g+xFzHiw`VwV?V}Lww{q=b$AREs%(= z5Kt?P)J`#Q`zNLixb&Odu#1bo3(n)u8!A5{vkW!|!4bvo%v8|ofMlL-X z;seI;k(7U)g1??BaxPH+O%LQDCw$#f`TI&S_h~hEiC#pq(u}Gdw1)R%NY5T z47csLNMY)k+BFROh#Pum97_+#aEBijU=A@fv81DvJe_^fg+7F(62hUM4sqXOiR`IN z>7i|jZO@SM9KpaP=q+|&Iy8y57))gh0qD;yaAk7Da53WtBWt+(*jTdq6D^6Nk)?%o z>{`lM$Ed&Fq#EO)$z`tp{4tA-2Mviyjr+0IiBx^RS}`TRngcP<$L+sj{1fK?LwpB! zEhU-c%I6LQ=wwQiyJqF|%f|g}O3E7iZrgk9Rq3ch&9oIx2qC}deVd04|$3YwJ9 zP|ywj`tbjKOWTP+ahiUu_G{uS^a~Cuux@nf0&n`Mw9vW(zfO)srVopY)9}(EP`h^q z8ds`G;%aS(CHk~T(Ke~!FV)=Aq)nh{+D}6S#X^&?lc4Q0zm2S8S3*o$P?DJvA-;~= zn#PQen0C?jpG4|&a|UZ0Dw&?sXZX*<*}~Or-lw!Rh0o;3xwVAU&y~AxeH|%C9u6tS z0OjB9Z9`i>vs2my;iEcFANkhQE81|9hmylV+EL*53(+$W)~eH7Ezkr-1^H2k&Vqso zV(JcZYWAgC(5WbvIs!ISCKS2Ynk96CHER(nBQ?f4COSF9uG0DIS5Cm@)@p#)?sssF zyn;?xMhyt*`TA4`9g52514E{iP36S^k z=tjeRo$i%*?IFpJs$)YTdJV9hr?(W>*7JXcwg(MNChRXY$Lq3)09F)U1AT$YWA=cdAxlc>S%5&$BRgUEIa>i#d zWJW9r;mS$bWpA=5(Ilj;j;JY)U@^G(?JbjdhvxIjH$ z?zJR_B;<(r7(X`!N#4=T)o4uCI**DrcAP z`Ul*GmKlDuwQoX7$|p zBTJBml3z}n;F?*|4M?rYcS#?nTN)v$llG})T6J04HN+io<+-F|4p4K#Cj%|eE|Dp~ zkq}zw=bs(J(d=?PYvPki#`{ZX%5BXUq?lVKWPQ-er|PDFcAQFcJ*2)B9LbZ~|7jBW zA-g3?S1NxO(x0KB(rO1aCb2g3+bczTSVKb&lnjc<JXuc?VOC=1*#dgE!Se$>)N7JXU{e}Xw6Zxy7(TFRpptR0kbSx``r45@a& zDZn{5E@|)ofOnsJ?<1xyVxr1qn4J@>p*b%oU@Co2qUye+`kAWgm$&r4^_0)3Z8_A= zpgX?$f7u4Fqa2N-#xCR&a=fkzsL#B)cG9Jqq0zsKCAC5bnwT;%ZB6OPIl6QsC|^Qc zT6Wx|Ldq%L=x%;eCZn{=VS|wNrING~(dg@{k!zGb3yB%ho*ElM?qPZ??X4xbQYSQh zc~gx)-S*6FW9nlP*7`B)N$3_eRhy<5n_QBe^KTL?z9j{$^Gf5pHU2g=a?5XYSYZhj zuzD$F`)gdhKkv3WM{-(2n2Na)Ge>m$TfJ0?h{cHNDS>R)IV~>9aHk79!!T{UlSGk@|!aL;T>P+&;)=*uZCQsvc6PQ zsnyLP<&nt-?ijN4_vFbi?GAO!oh(LyaMRy10Pu3{={(#4@UF+7*`3MPoL9RPQf3A^uSQn9^~hM2JIRx$F%zlZ6su#1TsoXbZ`J(_i46jxb zW5~F~}`>phJ~shW2;2+jJaL$x3U%BK1jO)Yv8sg<-0K7mSVhU$#Ly{ zZ5b=9?HN;lwIfp`H5kH47@cRL<@xpd@@Nu7XPtCk-)GHNo#8d)wZB4r3J_9fWxBCR zS027E=dE#{SetN|l`o&@DJUo?C@5GY?tL{;QafNye7XJlX=jTCwIFUI#(i{ zEKzfNpeY@4ANL#cXyxRQHyo~<|808OI#dWZ8-}r|CW^Fa!Zn{r@t6oW+P2f4fb|(Y7x}nsYj(dVU$qwj&88Tx^k} z|EJf!_^~J#ay$66Zg+-RNS-v|RXA#*000R(Nkle5qt1KVB$$b7Q#W1lp=VAp37lP6S{J|H*joce z@lfII@FY(gM!Lk4?k^!V;H=h$wp1x888}6R^kVFDN-oKjt0@}`Ux!tvzs$whtEn4O zhD%OsWpeekNYS6zvsv1tMqcM8KvLAz&Kv)kLTyV)%2}ULQ(n6&TZuIHwbl-cE@>{h z*ZfqkPYP*3wWr&DzWyn!Um>9ffPRkTgxgZZQ zw7PTD*Ct>&9q#PPVK-*un4>k+H%c-ggIr&xB;Pu}V(d-bj&2Gr6rm)pW!tLR8m5>} zmiG0@4{jCL*lsy*B@wio|JM*4SiMxfeF#WnL0TV&@RehPJ3}ES5u=@>)EMYqcmI#s z-BJ5xT$=17xRFcEMC@seN=s|{E+(%az$35a%<+tFC)ni6@g}d zEMp2|J{#f&NV>Cl)ccxv7aHERfi8EJu)VK;LjPoOIH+@lRB7FPjl0kx{0T!y813`9 z@256pE%s>2#=7;`_6a4XLhaVhSAe$vHTpEk-O$ATSV%>vjg1`kkKHfQ)(t=&x9<3M z-&^d!UWXtx=|#!3me;^A;F_@jxm%_XJp*AaJF|i#4`nBdRJ-}2u)}K6MAXor z2CP5Oorfj+)TcjEcP@T9P-remO18U5K87f`WpAf`TIte$=LoI3$uMBm+f}2G*<$w~Gup%ABe!h0yj7$$Es8 zZ*);@hhC@3h%kwFNJST%BedDv^t7An%V+7X^n?!%ANxd;{0 zO%Z0==kv4q*nL+vW=BdgZ4jgz_%gvW9CXdhF|GaU-R^e-TYQkYS8Ft+Yse)`X-rNrcIu?hgsexbYE6 z_M}3n?VA41kz@=_EK4${v9jbx({Gk7nznu1d5vuesiZzfqJ;WRX$wdB6aTlg4Yaf! zrQhm5DLrE$h3?61T@xd=e{<>6hIB(9b{{A2bh}6#YrDJlUbS}`VCPk<6^-;)w$*HSs3TS6V6ajQtgs;7P4ne-B$k9; z_rA`)Tti+XS8{D>!tXv}T$NTnB|DVl%SFgYOUuxhste9NW-z&$a}ruv7*hB56vht* z?HCW;M!K>?2@4F=R?lKnC_>u8vVEh<#*QJ&vk$TTkD0#(T@3ACLg$~hJT?AOk@&-) zMqagKbeHhOTeMn<6e{N`r_nYN`m(CSws9v0`!Y1^Kkqm3JB8>eC@3f>C@3hv5W1_? z9VO2PPQFj}XzF0HQ||cvW9r;}3#^g3TPFu8G&xw zlRUgUnyPW%yCr=pse2y}VJjGJc;A8NpQNfPQD+?TU^JOp!jqE zo$VogJf$|_o*w|8yQ#sAN69{m4h$6OnKC&ZdURklK^iA9edyBY0R8s#sdoQ5CNCB_ z<}f$*-TPME)bnEPlVhAt$=?<5@WYQG`)(*7xmx`(cV3ZS!}~{KQuq~LChuvQ`&ijl zbFCbKTEFgUD@0F0K|w)5K|z5FIwKe^FJ`BmdY5jAX6O%2$nq^Vr-;C@>_qB2BRjD2!I z?*`octJgrzBSoo~U`h?E2mci*kQnznK|>>Y#b7^BU(&}L|Ra+9c` zp-x*HZ><;~kam4(KfTi&L8`sd{-LD4Olh~_MmLt7c}q?Ce_yE86Gu08iLF-F{{s>u VWdnZB+3WxS002ovPDHLkV1m1}=Pm#M literal 0 HcmV?d00001 From 8c5ef4d3293330c979393d5b60b034364908974c Mon Sep 17 00:00:00 2001 From: blizhan Date: Thu, 30 Apr 2026 17:23:33 +0800 Subject: [PATCH 4/6] docs: expand SKILL.md and aimx-cli.md with analysis workflows and best practices - Added a new section on "Fast Recipes" in SKILL.md for common analysis tasks. - Introduced detailed analysis workflows and critical rules for using aimx effectively. - Included guidelines for ranking runs, inspecting curve health, and compact local analysis. - Enhanced aimx-cli.md with analysis patterns and examples for comparing runs and detecting anomalies. - Emphasized the importance of structured evidence and compact reporting in analysis. --- skills/aimx/SKILL.md | 145 +++++++++++- skills/aimx/references/aimx-cli.md | 347 +++++++++++++++++++++++++++++ 2 files changed, 491 insertions(+), 1 deletion(-) diff --git a/skills/aimx/SKILL.md b/skills/aimx/SKILL.md index 5c17bcf..7e3b820 100644 --- a/skills/aimx/SKILL.md +++ b/skills/aimx/SKILL.md @@ -11,6 +11,91 @@ Use `aimx` as a read-only evidence collector for `autoresearch` `log_experiment` steps. Prefer JSON output so downstream agents can compare runs, explain model effects, and propose the next experiment from concrete Aim data. +## Fast Recipes + +Use these first for common analysis tasks. Keep `--repo` explicit and prefer +`--json` for machine-readable output. + +### Discover run scope and available params + +```bash +aimx query params "run.hash != ''" --repo --json +``` + +### Inspect one run quickly + +```bash +aimx query params "run.hash == ''" --repo --json +aimx query metrics "(run.hash == '') and metric.name != ''" --repo --json +``` + +### Rank runs by an objective metric + +```bash +aimx query metrics "() and metric.name == ''" --repo --json > metrics.json +python - <<'PY' +from __future__ import annotations +import json +from pathlib import Path + +payload = json.loads(Path("metrics.json").read_text()) +rows = [] +for run in payload.get("runs", []): + for metric in run.get("metrics", []): + value = metric.get("min", {}).get("value") + if value is not None: + rows.append((value, run.get("hash"), run.get("name"), metric.get("context", {}))) +for value, run_hash, run_name, context in sorted(rows)[:5]: + print(f"{value:.6f}\t{run_hash}\t{run_name}\t{context}") +PY +``` + +### Compare two runs side by side + +```bash +aimx query params "run.hash == '' or run.hash == ''" --repo --json +aimx query metrics "((run.hash == '') or (run.hash == '')) and metric.name == ''" --repo --json +``` + +### Check curve health with bounded trace evidence + +```bash +aimx trace "() and metric.name == ''" --repo --json --tail 200 > trace.json +``` + +Then reduce `trace.json` with the `curve_summary` snippet from +`references/aimx-cli.md` instead of pasting raw series. + +### Sanity-check distribution traces + +```bash +aimx trace distribution "" --repo --json --tail 5 +aimx trace distribution "distribution.name != ''" --repo --step 12300 +``` + +### Capture one snapshot bundle for logs + +```bash +uv run python skills/aimx/scripts/collect_experiment_snapshot.py \ + --repo data \ + --base-expr "run.hash != ''" \ + --metric loss \ + --trace-metric loss \ + --pretty +``` + +## When to use what + +| Need | Use | +| --- | --- | +| Discover runs and key hyperparameters | `aimx query params "" --repo --json` | +| Rank runs cheaply by objective | `aimx query metrics "" --repo --json` and compare `min.value` or `max.value` | +| Inspect curve shape and late stability | `aimx trace "" --repo --json --tail N` | +| Focus on a step or epoch window | `--steps a:b` or `--epochs a:b` on query/trace commands | +| Analyze weight or gradient histograms | `aimx trace distribution "" --repo --json` | +| Collect qualitative image evidence | `aimx query images "" --repo --json --head N` | +| Check native Aim passthrough readiness | `aimx doctor` | + ## Requirements - Require `aimx` in the Python environment that runs `log_experiment`. @@ -32,6 +117,9 @@ effects, and propose the next experiment from concrete Aim data. ## Workflow +For common tasks, start from **Fast Recipes** and only switch to this full +workflow when the scope is unclear or the question is complex. + 1. Locate the Aim repository. Pass `--repo ` explicitly; in this repository, use `--repo data` or `--repo data/.aim` for local checks. 2. Define the run scope as an AimQL expression. Start broad with @@ -91,6 +179,43 @@ effects, and propose the next experiment from concrete Aim data. } ``` +## Analysis Workflow + +Use the same discipline as large experiment trackers: inspect structure first, +query only the fields needed for the question, then reduce evidence into compact +statistics before writing conclusions. + +1. Start with params and metric summaries to discover candidate runs, objective + metrics, contexts, and missing fields. Avoid dumping full JSON payloads into + conversation context. +2. Choose the objective direction explicitly. Rank cheaply from summaries first: + `min.value` for loss/error, `max.value` for accuracy/F1/AUC/IoU, and + `last.value` only when the final checkpoint is the real objective. +3. Pull bounded traces only for the baseline, top candidates, and suspicious + runs. Prefer `--tail`, `--steps`, `--epochs`, and `--every` before collecting + full curves. +4. Compute local stats before interpreting: best step, final-window mean/std, + train-vs-val gap, NaN/Inf counts, sustained increases, spikes, and plateaus. +5. Compare runs side by side with selected params plus selected metrics. Do not + iterate every param or every metric unless discovery is the goal. +6. Escalate evidence by modality: use distribution traces for weights, + activations, or gradients; use image metadata for qualitative regressions. +7. Keep the final analysis small: state objective, run scope, top runs, curve + health, anomalies, confidence, and the next experiment suggested by evidence. + +## Critical Rules + +- Discover scope first with `aimx query params "" --repo --json`. + Do not assume metric or param names. +- Treat `aimx` output as data: parse JSON and report aggregates, not raw payloads. +- Slice traces aggressively with `--tail`, `--head`, `--steps`, `--epochs`, or + `--every` before computing local statistics. +- Always pass `--repo` explicitly to avoid reading an unintended repository. +- For automation, use `aimx trace distribution` with `--json`, `--csv`, or + `--table`. Unflagged mode is terminal visualization for human inspection. +- Always finish with a compact conclusion: objective, top runs, curve health, + anomalies, confidence, and next experiment. + ## Interpretation Rules - Prefer validation, test, or held-out contexts over training contexts when @@ -112,6 +237,21 @@ effects, and propose the next experiment from concrete Aim data. - Preserve read-only behavior. Do not run commands that initialize, repair, migrate, delete, or rewrite Aim repositories during `log_experiment`. +## Gotchas + +| Gotcha | Wrong | Right | +| --- | --- | --- | +| Missing `aimx` in environment | Assume `aimx` is available | Verify with `aimx --help` or `python -m aimx --help`, then follow project install workflow | +| Repository targeting | Rely on current directory | Pass `--repo ` explicitly on every collection command | +| Summary vs curve confusion | Treat `query metrics` output as full history | Use `query metrics` for summary (`last/min/max`) and `trace --json` for curve shape | +| Raw payload dumping | Paste full JSON into conversation | Parse and compute compact aggregates before reporting | +| AimQL string quoting | `metric.name == "loss"` | `metric.name == 'loss'` | +| Short hash assumptions | Assume short hash is canonical identity | Let `aimx` expand it, but compare/store full run hash | +| Distribution output mode | Use default distribution mode in scripts | Use `--json`, `--csv`, or `--table` for automation | +| `--step` expectation | Expect `--step` to filter JSON/CSV/table exports | Use `--step` only for visual histogram mode | +| Empty trace handling | Treat non-JSON message as fatal parsing error | Treat it as no trace evidence and continue analysis | +| Full trace collection | Pull all runs and all points first | Rank by summary, then trace only baseline, top candidates, and suspicious runs | + ## Helper Script Use `scripts/collect_experiment_snapshot.py` when an agent needs one structured @@ -135,4 +275,7 @@ needed. It writes only to stdout. ## Reference Read `references/aimx-cli.md` for command details, JSON envelope shapes, and -suggested `log_experiment` evidence fields. +suggested `log_experiment` evidence fields. For deeper experiment analysis +patterns, see "Analysis Patterns", "Find best run by objective", "Spike / +divergence / plateau / NaN detection", "Overfitting detection", and "Sweep +ranking". diff --git a/skills/aimx/references/aimx-cli.md b/skills/aimx/references/aimx-cli.md index d43d54c..414e7c3 100644 --- a/skills/aimx/references/aimx-cli.md +++ b/skills/aimx/references/aimx-cli.md @@ -190,6 +190,353 @@ JSON shape: If no metrics match, current `aimx trace --json` may print a text message instead of JSON. Treat that as no trace evidence rather than a parsing failure. +## Analysis Patterns + +Treat `aimx` output as structured evidence, not as text to paste wholesale. +Discover shape first, narrow the query, load JSON locally, then report compact +aggregates. This mirrors the large-project rule from experiment trackers: never +fetch or print every run, metric, or trace point unless discovery is the task. + +### Rank runs from summaries + +1. Collect params for the run scope. +2. Collect metric summaries for candidate objective metrics. +3. Choose the objective direction before ranking: + - loss, error, perplexity: smaller is usually better; use `min.value`. + - accuracy, F1, AUC, IoU, reward: larger is usually better; use `max.value`. + - final-checkpoint objectives: use `last.value` and say why. +4. Prefer validation/test contexts over train contexts. If contexts are missing + or mixed, lower confidence instead of forcing a ranking. + +### Inspect curve health from traces + +Use traces for the smallest set of runs that can answer the question: + +```bash +aimx trace "(run.hash == 'baseline') and metric.name == 'loss'" --repo --json --tail 200 +aimx trace "(run.hash == 'candidate') and metric.name == 'loss'" --repo --json --steps 1000:5000 --every 10 +``` + +Check these before writing conclusions: + +- final-window mean and standard deviation +- best value and best step +- sustained increases near the end of training +- large one-step spikes or NaN/Inf values +- plateaus where absolute step-to-step change is near zero +- train-vs-validation gap when both contexts exist + +### Compact local analysis + +Use Python to reduce trace JSON to a few numbers. Keep output small. + +```python +from __future__ import annotations + +import json +import math +from pathlib import Path +from statistics import fmean, pstdev +from typing import Any, Iterable + + +def finite_floats(values: Iterable[Any]) -> list[float]: + result: list[float] = [] + for value in values: + if isinstance(value, (int, float)) and not isinstance(value, bool): + number = float(value) + if math.isfinite(number): + result.append(number) + return result + + +def curve_summary(values: list[float]) -> dict[str, float | int | bool]: + if not values: + return {"points": 0, "has_values": False} + + final_window = values[-max(1, len(values) // 5) :] + diffs = [b - a for a, b in zip(values, values[1:])] + mean_abs_change = fmean(abs(diff) for diff in diffs) if diffs else 0.0 + + return { + "points": len(values), + "has_values": True, + "first": values[0], + "last": values[-1], + "best_min": min(values), + "best_min_index": values.index(min(values)), + "final_mean": fmean(final_window), + "final_std": pstdev(final_window) if len(final_window) > 1 else 0.0, + "mean_abs_change": mean_abs_change, + "increased_at_end": len(final_window) > 1 and final_window[-1] > final_window[0], + } + + +payload: list[dict[str, Any]] = json.loads(Path("trace.json").read_text()) +for series in payload: + values = finite_floats(series.get("values", [])) + print( + json.dumps( + { + "run": series.get("run", {}).get("hash"), + "metric": series.get("metric"), + "context": series.get("context", {}), + "summary": curve_summary(values), + }, + sort_keys=True, + ) + ) +``` + +### Compare runs side by side + +For comparisons, report only selected params and selected metrics: + +- run identity: hash, experiment, name +- controlled variables: model, seed, dataset, optimizer, learning rate, batch size +- objective summary: best value, best step, final value +- curve health: final-window stability, spikes, divergence, plateau +- missing evidence: missing params, missing validation metrics, short traces + +When the next experiment is requested, tie it to evidence. Examples: +increase regularization only if validation worsens while training improves; +reduce learning rate only if traces show spikes or divergence; extend training +only if the final window is still improving without validation degradation. + +### Find best run by objective + +Input command: + +```bash +aimx query metrics "() and metric.name == ''" --repo --json > metrics.json +``` + +Output: top-ranked rows `(run_hash, run_name, context, objective_value, steps)`. + +```python +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any, Literal + +Direction = Literal["min", "max", "last"] + + +def metric_value(metric: dict[str, Any], direction: Direction) -> float | None: + if direction == "last": + value = metric.get("last", {}).get("value") + elif direction == "max": + value = metric.get("max", {}).get("value") + else: + value = metric.get("min", {}).get("value") + return float(value) if isinstance(value, (int, float)) else None + + +payload = json.loads(Path("metrics.json").read_text()) +direction: Direction = "min" +rows: list[dict[str, Any]] = [] +for run in payload.get("runs", []): + for metric in run.get("metrics", []): + value = metric_value(metric, direction) + if value is None: + continue + rows.append( + { + "run_hash": run.get("hash"), + "run_name": run.get("name"), + "metric": metric.get("name"), + "context": metric.get("context", {}), + "objective": value, + "steps": metric.get("steps", 0), + } + ) + +top = sorted(rows, key=lambda item: item["objective"], reverse=(direction == "max"))[:5] +for item in top: + print(item) +``` + +### Spike / divergence / plateau / NaN detection + +Input command: + +```bash +aimx trace "() and metric.name == ''" --repo --json --tail 500 > trace.json +``` + +Output: one compact anomaly summary per series. + +```python +from __future__ import annotations + +import json +import math +from pathlib import Path +from typing import Any + +import numpy as np + + +def finite_array(values: list[Any]) -> np.ndarray: + cleaned = [ + float(value) + for value in values + if isinstance(value, (int, float)) and not isinstance(value, bool) and math.isfinite(float(value)) + ] + return np.asarray(cleaned, dtype=float) + + +payload: list[dict[str, Any]] = json.loads(Path("trace.json").read_text()) +window = 20 +eps = 1e-5 +for series in payload: + values = finite_array(series.get("values", [])) + if values.size < window + 1: + continue + diffs = np.diff(values) + roll_mean = np.convolve(values, np.ones(window) / window, mode="valid") + aligned = values[window - 1 :] + centered = aligned - roll_mean + roll_std = np.sqrt(np.convolve(centered**2, np.ones(window) / window, mode="same")) + spikes = int(np.sum(np.abs(centered) > (3.0 * np.maximum(roll_std, 1e-12)))) + trend = np.convolve(diffs, np.ones(window) / window, mode="valid") + divergence = bool(np.sum(trend > 0.0) > window) + plateau = bool(np.sum(np.abs(trend) < eps) > window) + non_finite = len(series.get("values", [])) - int(values.size) + print( + { + "run": series.get("run", {}).get("hash"), + "metric": series.get("metric"), + "context": series.get("context", {}), + "spikes": spikes, + "diverging": divergence, + "plateau": plateau, + "non_finite_points": non_finite, + } + ) +``` + +### Overfitting detection (train vs val) + +Input commands: + +```bash +aimx trace "() and metric.name == '' and metric.context.subset == 'train'" --repo --json --tail 300 > train.json +aimx trace "() and metric.name == '' and metric.context.subset == 'val'" --repo --json --tail 300 > val.json +``` + +Output: per-run train/val tail means and an overfitting flag. + +```python +from __future__ import annotations + +import json +from pathlib import Path +from statistics import fmean +from typing import Any + + +def tail_mean(values: list[float], ratio: float = 0.2) -> float: + if not values: + return float("nan") + start = max(0, int(len(values) * (1.0 - ratio))) + return fmean(values[start:]) + + +def index_by_run(payload: list[dict[str, Any]]) -> dict[str, list[float]]: + index: dict[str, list[float]] = {} + for series in payload: + run_hash = str(series.get("run", {}).get("hash", "")) + values = [ + float(value) + for value in series.get("values", []) + if isinstance(value, (int, float)) and not isinstance(value, bool) + ] + if run_hash and values: + index[run_hash] = values + return index + + +train_payload: list[dict[str, Any]] = json.loads(Path("train.json").read_text()) +val_payload: list[dict[str, Any]] = json.loads(Path("val.json").read_text()) +train_by_run = index_by_run(train_payload) +val_by_run = index_by_run(val_payload) +threshold = 0.05 +for run_hash in sorted(set(train_by_run) & set(val_by_run)): + train_values = train_by_run[run_hash] + val_values = val_by_run[run_hash] + train_tail = tail_mean(train_values) + val_tail = tail_mean(val_values) + gap = val_tail - train_tail + train_trend_down = train_values[-1] <= train_values[0] + overfit = gap > threshold and train_trend_down + print( + { + "run_hash": run_hash, + "train_tail_mean": train_tail, + "val_tail_mean": val_tail, + "gap": gap, + "overfitting": overfit, + } + ) +``` + +### Sweep ranking (params x metric summary) + +Input commands: + +```bash +aimx query params "" --repo --json > params.json +aimx query metrics "() and metric.name == ''" --repo --json > metrics.json +``` + +Output: top-5 rows with objective value and selected control variables. + +```python +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + + +def param_index(payload: dict[str, Any]) -> dict[str, dict[str, Any]]: + return { + str(run.get("hash")): dict(run.get("params", {})) + for run in payload.get("runs", []) + if run.get("hash") + } + + +params_payload = json.loads(Path("params.json").read_text()) +metrics_payload = json.loads(Path("metrics.json").read_text()) +params_by_run = param_index(params_payload) +rows: list[dict[str, Any]] = [] +for run in metrics_payload.get("runs", []): + run_hash = str(run.get("hash", "")) + if not run_hash: + continue + for metric in run.get("metrics", []): + objective = metric.get("min", {}).get("value") + if not isinstance(objective, (int, float)): + continue + run_params = params_by_run.get(run_hash, {}) + rows.append( + { + "run_hash": run_hash, + "run_name": run.get("name"), + "objective": float(objective), + "model": run_params.get("model"), + "lr": run_params.get("hparam.lr"), + "batch_size": run_params.get("hparam.batch_size"), + } + ) + +for item in sorted(rows, key=lambda row: row["objective"])[:5]: + print(item) +``` + ## Distribution Traces Use distribution traces when histogram shape matters, such as weights, From a56d0f1f60a0c654e7af6ca41355d58a7d946fab Mon Sep 17 00:00:00 2001 From: blizhan Date: Thu, 30 Apr 2026 17:32:24 +0800 Subject: [PATCH 5/6] fix: trace view --- src/aimx/rendering/trace_views.py | 12 ++++++-- tests/unit/test_trace_distribution_views.py | 34 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/aimx/rendering/trace_views.py b/src/aimx/rendering/trace_views.py index df85516..e29f057 100644 --- a/src/aimx/rendering/trace_views.py +++ b/src/aimx/rendering/trace_views.py @@ -142,7 +142,8 @@ def _compress_values(values: list[float], width: int) -> list[float]: start = index * len(values) // width end = (index + 1) * len(values) // width bucket = values[start:end] or [values[start]] - compressed.append(max(bucket)) + finite = [v for v in bucket if math.isfinite(v)] + compressed.append(max(finite) if finite else 0.0) return compressed @@ -151,12 +152,13 @@ def _intensity_text(values: list[float], *, width: int) -> Text: text = Text() if not values: return text - max_value = max(float(v) for v in values) + finite_samples = [float(v) for v in values if math.isfinite(v)] + max_value = max(finite_samples) if finite_samples else 0.0 if max_value <= 0: text.append(_DISTRIBUTION_BLOCKS[0] * len(values), style=_DISTRIBUTION_ZERO_STYLE) return text for value in values: - if value <= 0: + if not math.isfinite(value) or value <= 0: text.append(_DISTRIBUTION_BLOCKS[0], style=_DISTRIBUTION_ZERO_STYLE) continue scale = float(value) / max_value @@ -168,6 +170,10 @@ def _intensity_text(values: list[float], *, width: int) -> Text: def _sample_points_for_height(points: list[Any], max_rows: int) -> list[Any]: if max_rows <= 0 or len(points) <= max_rows: return points + if max_rows == 1: + # Evenly-spaced indices use (max_rows - 1) in the denominator; skip when + # max_rows is 1 and show the latest step as a single representative row. + return [points[-1]] indexes = sorted({round(i * (len(points) - 1) / (max_rows - 1)) for i in range(max_rows)}) return [points[index] for index in indexes] diff --git a/tests/unit/test_trace_distribution_views.py b/tests/unit/test_trace_distribution_views.py index 6e460d5..889de33 100644 --- a/tests/unit/test_trace_distribution_views.py +++ b/tests/unit/test_trace_distribution_views.py @@ -8,6 +8,8 @@ from aimx.aim_bridge.metric_stats import DistributionPoint, DistributionSeries, RunMeta from aimx.rendering.trace_views import ( + _compress_values, + _intensity_text, render_distribution_csv, render_distribution_json, render_distribution_table, @@ -185,6 +187,38 @@ def test_render_distribution_visual_labels_nearest_step() -> None: assert "Requested step 750; showing nearest tracked step 600." in output +def test_render_distribution_visual_small_height_does_not_zero_divide_heatmap() -> None: + """height 12 or 13 yields max_heatmap_rows == 1; sampling must not divide by zero.""" + for height in (12, 13): + output = render_distribution_visual( + _multi_step_distribution_series(), + height=height, + no_color=True, + ) + assert "Heatmap (steps x bins)" in output + assert "900 |" in output + assert "Showing 1 of 3 steps" in output + + +def test_compress_values_ignores_non_finite_in_bucket_max() -> None: + nan = float("nan") + inf = float("inf") + # width=2 splits [1, nan, 10, 5] into [1, nan] and [10, 5] + assert _compress_values([1.0, nan, 10.0, 5.0], width=2) == [1.0, 10.0] + # bucket is only non-finite -> default 0.0 + assert _compress_values([nan, inf, -inf, nan], width=2) == [0.0, 0.0] + + +def test_intensity_text_handles_non_finite_without_crash() -> None: + nan = float("nan") + text = _intensity_text([1.0, nan, 4.0, 0.0], width=8) + assert len(text.plain) == 4 + + all_bad = _intensity_text([nan, float("inf")], width=8) + assert len(all_bad.plain) == 2 + assert all(ch == "▁" for ch in all_bad.plain) + + def test_render_distribution_visual_handles_single_step_and_all_zero_weights() -> None: run = RunMeta(hash="abcdef1234567890", experiment="exp-a", name=None, creation_time=None) series = [ From e9690e88ef96daf52b726bd177f6786ad5e81985 Mon Sep 17 00:00:00 2001 From: blizhan Date: Thu, 30 Apr 2026 17:33:56 +0800 Subject: [PATCH 6/6] chore: bump version to 0.3.3 in project files --- pyproject.toml | 2 +- src/aimx/__init__.py | 2 +- uv.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 882d3d4..24d0c56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "aimx" -version = "0.3.2" +version = "0.3.3" description = "A safe CLI-first companion for native Aim" readme = "README.md" requires-python = ">=3.10,<3.13" diff --git a/src/aimx/__init__.py b/src/aimx/__init__.py index 4c7823b..11b937b 100644 --- a/src/aimx/__init__.py +++ b/src/aimx/__init__.py @@ -1,3 +1,3 @@ __all__ = ["__version__"] -__version__ = "0.3.2" +__version__ = "0.3.3" diff --git a/uv.lock b/uv.lock index ed1d79a..bb7ba45 100644 --- a/uv.lock +++ b/uv.lock @@ -96,7 +96,7 @@ wheels = [ [[package]] name = "aimx" -version = "0.3.2" +version = "0.3.3" source = { editable = "." } dependencies = [ { name = "numpy" },