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:
-
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
-
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 (~1728–1762, 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).
Context
viz smartauto-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 standalonevizcommand that produces it.The
PanelKind::AnimatedBubblepanel is constructed only inbuild_smart(src/cmd/viz.rs:17621); its reader isread_entity_bucket_agg(viz.rs:13942) and its render block is atviz.rs:~20368.Standalone charts do animate via
--slider(viz bar/line/scatter/geo, dispatched throughbuild_slider_xy_plot,viz.rs:2372), but--sliderexplicitly rejects being combined with--color/--size— the exact encoding a Gapminder needs:(
viz.rs:1733, gated byencoded_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:
Lift the restriction on
viz scatter --sliderso--slider+--size+--colorroutes through a bubble-animation builder instead of erroring. Reuses the existing smartAnimatedBubblereader/renderer. Smallest new surface; matches the existing--sliderUX. (Recommended.)qsv viz scatter regions_growth.csv --x gdp_index --y wellbeing_index --size population_m --color region --slider month_dateAdd a dedicated
viz bubblesubcommand. More discoverable/self-documenting, but a new top-level command to maintain (USAGE, help, tests, MCP skill, README).Leaning option 1.
Implementation notes
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.--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.min_cell_rows, per-entity completeness inread_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.--slider-cumulativefor accumulation as the other standalone slider charts do.Acceptance criteria
viz smart.--slider+--color/--sizehard error (viz.rs:1733) is replaced by the working bubble path (or a dedicated command).tests/test_viz.rs; a gallery demo (e.g. onregions_growth.csv) inexamples/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_scattergate (~1728–1762,2558),build_slider_xy_plot(2372), smartAnimatedBubblebuild (17621) / readerread_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).