Skip to content

viz: expose the animated Gapminder bubble chart as a standalone command (viz scatter --slider + --size/--color) #4217

Description

@jqnatividad

Context

viz smart auto-generates a Gapminder-style animated bubble chart (the T3 panel): one bubble per low-cardinality entity, tracing a path through a 2-measure (x, y) space over a time slider, sized by a third measure and colored by entity, with Play/Pause + a scrub slider. It's a compelling chart, but today it's reachable only inside a smart dashboard — there's no standalone viz command that produces it.

  • The PanelKind::AnimatedBubble panel is constructed only in build_smart (src/cmd/viz.rs:17621); its reader is read_entity_bucket_agg (viz.rs:13942) and its render block is at viz.rs:~20368.

  • Standalone charts do animate via --slider (viz bar/line/scatter/geo, dispatched through build_slider_xy_plot, viz.rs:2372), but --slider explicitly rejects being combined with --color/--size — the exact encoding a Gapminder needs:

    --slider cannot yet be combined with --color/--size (bubble animation is
    a follow-up). Use --series to split into animated traces, or drop --color/--size.
    

    (viz.rs:1733, gated by encoded_scatter, viz.rs:2558)

So the machinery to build the chart already exists (the smart path assembles it end-to-end), and the standalone slider path already anticipates this as a follow-up. This issue tracks exposing it.

Proposal

Two options:

  1. Lift the restriction on viz scatter --slider so --slider + --size + --color routes through a bubble-animation builder instead of erroring. Reuses the existing smart AnimatedBubble reader/renderer. Smallest new surface; matches the existing --slider UX. (Recommended.)

    • e.g. qsv viz scatter regions_growth.csv --x gdp_index --y wellbeing_index --size population_m --color region --slider month_date
  2. Add a dedicated viz bubble subcommand. More discoverable/self-documenting, but a new top-level command to maintain (USAGE, help, tests, MCP skill, README).

Leaning option 1.

Implementation notes

  • Refactor the smart bubble builder so the standalone path can call it: the entity×bucket aggregation (read_entity_bucket_agg), the per-entity-trace + per-frame-replacement + pinned-axes render (viz.rs:~20368), and the slider/Play-Pause layout (slider_control + play_pause_menu) are the reusable pieces.
  • Map standalone flags to the smart selection: --color <entity> = the entity/series column, --x/--y = the measure pair, --size <measure> = the third data variable (falls back to per-cell record count when absent, as the smart reader already does), --slider <date> = the time bucket column.
  • Decide whether the standalone command keeps the smart quality gates (min_cell_rows, per-entity completeness in read_entity_bucket_agg) or relaxes them — a user asking explicitly for a bubble animation may want it drawn even when sparse (perhaps behind a warning rather than a hard drop). The smart path auto-selects, so its gates are conservative; an explicit command can be more permissive.
  • Reveal mode: the smart bubble uses per-frame replacement (each frame = that bucket's positions); consider exposing --slider-cumulative for accumulation as the other standalone slider charts do.

Acceptance criteria

  • A standalone command renders the animated bubble (x/y measures + size + entity color + time slider + Play/Pause) without going through viz smart.
  • The --slider + --color/--size hard error (viz.rs:1733) is replaced by the working bubble path (or a dedicated command).
  • Tests in tests/test_viz.rs; a gallery demo (e.g. on regions_growth.csv) in examples/viz/gen_gallery.py; help regenerated (qsv --generate-help-md). If a new subcommand: README + MCP skill updates.

Critical files

  • src/cmd/viz.rs — slider dispatch + encoded_scatter gate (~17281762, 2558), build_slider_xy_plot (2372), smart AnimatedBubble build (17621) / reader read_entity_bucket_agg (13942) / render (~20368).
  • tests/test_viz.rs, examples/viz/gen_gallery.py, docs/help/viz.md; (+ README / MCP skill if a new subcommand).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions