EMRY-020: Chart downsample + braille renderer #62

Merged
vxfemboy merged 2 commits from emry-020-chart-downsample into main 2026-06-25 04:34:20 +00:00
vxfemboy commented 2026-06-25 04:31:36 +00:00 (Migrated from github.com)

Closes EMRY-020 (#15). Branched off main. First M2/TUI work.

What

crates/emry-tui/src/chart.rs — dependency-free chart primitives:

  • downsample_minmax(&[f64], buckets) -> Vec<(f64,f64)>: spike-preserving compression (keeps min and max per bucket — averaging would hide loss spikes).
  • render_braille(&[f64], width, height) -> Vec<String>: a braille band chart (2×4 dots per cell, U+2800 base), filling each column from min→max so spikes stay visible.

Scope note

The ratatui::Widget wrapper is intentionally deferred to EMRY-021 (where the TUI app + ratatui dependency land). EMRY-020 ships the pure, fully-unit-testable rendering core.

Verification

  • ./scripts/pre-commit-rust.sh green: clippy -D warnings, 13 tui tests, chart.rs 99% lines, total 98.03%
  • Spike survives 1000→80 compression (exactly one bucket carries it); braille output validated for dimensions, char range, spike-reaches-top, flat-series no-panic

Review-driven fixes

A focused review verified the braille dot-bit table, bucket math, coordinate flip, and indexing are correct, and caught two non-finite consistency bugs (both fixed):

  1. The len<=buckets short-circuit path skipped the finite filter → a NaN could reach a NaN as usize cast.
  2. An all-non-finite bucket's (0,0) sentinel could distort normalization → now normalize against the finite range of the original data, with clamped dot rows + blank-on-no-finite-data.
Closes EMRY-020 (#15). Branched off `main`. First M2/TUI work. ## What `crates/emry-tui/src/chart.rs` — dependency-free chart primitives: - `downsample_minmax(&[f64], buckets) -> Vec<(f64,f64)>`: spike-preserving compression (keeps min **and** max per bucket — averaging would hide loss spikes). - `render_braille(&[f64], width, height) -> Vec<String>`: a braille band chart (2×4 dots per cell, U+2800 base), filling each column from min→max so spikes stay visible. ## Scope note The `ratatui::Widget` wrapper is **intentionally deferred to EMRY-021** (where the TUI app + ratatui dependency land). EMRY-020 ships the pure, fully-unit-testable rendering core. ## Verification - `./scripts/pre-commit-rust.sh` green: clippy `-D warnings`, 13 tui tests, chart.rs 99% lines, total 98.03% - Spike survives 1000→80 compression (exactly one bucket carries it); braille output validated for dimensions, char range, spike-reaches-top, flat-series no-panic ## Review-driven fixes A focused review verified the braille dot-bit table, bucket math, coordinate flip, and indexing are correct, and caught two non-finite consistency bugs (both fixed): 1. The `len<=buckets` short-circuit path skipped the finite filter → a NaN could reach a `NaN as usize` cast. 2. An all-non-finite bucket's `(0,0)` sentinel could distort normalization → now normalize against the finite range of the original `data`, with clamped dot rows + blank-on-no-finite-data.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
femboy/emry!62
No description provided.