ASCII Plots

6 functions for terminal-friendly visualizations using Unicode characters. Render directly in the REPL, notebooks, or pipe to log files. Zero dependencies.

sparkline

Render a compact inline chart using Unicode block characters. Perfect for showing trends in a single line.

sparkline(data) -> string
sparkline([1, 5, 2, 8, 3, 7, 4, 6])
# "▂▆▃█▃▇▄▆"

let coverage = [12, 45, 89, 102, 67, 54, 33, 28, 15]
println("Coverage: ", sparkline(coverage))
Output
Coverage: ▁▃▆█▅▄▂▂▁

bar_chart

Bar chart in the terminal.

bar_chart(data, opts?) -> string
OptionTypeDescription
labelslist<string>Bar labels
widthintMax bar width (default: 40)
titlestringChart title
let counts = {"A": 2500, "T": 2300, "C": 2600, "G": 2400}
println(bar_chart(counts, {title: "Nucleotide Counts", width: 50}))
Output
Nucleotide Counts
A |████████████████████████████████████████████████  | 2500
T |████████████████████████████████████████████      | 2300
C |██████████████████████████████████████████████████| 2600
G |██████████████████████████████████████████████    | 2400

boxplot

ASCII boxplot showing min, Q1, median, Q3, max, and outliers.

boxplot(data, opts?) -> string
let quality = [28, 30, 32, 35, 33, 31, 29, 36, 34, 27, 38, 12]
println(boxplot(quality, {title: "Base Quality Scores", width: 60}))

# Multiple boxplots
let samples = {
  "Control": [28, 30, 32, 35, 33],
  "Treated": [22, 25, 28, 24, 26],
  "Mutant":  [35, 38, 40, 37, 36]
}
println(boxplot(samples))
Output
Base Quality Scores
 o           |----[======|=====]---|
 12          27   29    32    35   38

hist

Text-mode histogram with configurable bin count.

hist(data, bins?) -> string
let lengths = range(0, 1000) |> map(|_| int(random() * 300))
println(hist(lengths, 15))
Output
Read Length Distribution
  0-20  |████████████████  | 156
 20-40  |█████████████████████████████████| 312
 40-60  |██████████████████████████████████████████████████| 487
 60-80  |███████████████████████████████████████████████  | 461
 80-100 |██████████████████████████████████████████      | 398
100-120 |████████████████████████████████████            | 345
120-140 |██████████████████████████████                  | 289
140-160 |████████████████████████                        | 231
160-180 |██████████████████                              | 178
180-200 |████████████████                                | 148
200-220 |██████████                                      | 98
220-240 |██████                                          | 62
240-260 |████                                            | 41
260-280 |██                                              | 22
280-300 |█                                               | 8

scatter

Terminal scatter plot using Braille characters for sub-cell resolution.

scatter(x, y) -> string
let x = range(0, 50) |> map(|i| float(i) / 10.0)
let y = map(x, |v| sin(v))
println(scatter(x, y))
Output
sin(x)
 1.0│    ⠠⡐                    ⠀⡐
    │  ⠀☁  ⠀                  ☁  ⠀
 0.5│⠀☁      ⠐                      ⠐
    │☁        ⠀              ☁        ⠀
 0.0│──────────⠒──────────────⠒──────────
    │           ⠀            ☁
-0.5│            ⠐          ⠀
    │              ⠀      ☁
-1.0│                ⠐⠀⡐☁
    └──────────────────────────────────
     0.0    1.0    2.0    3.0    4.0    5.0

heatmap_ascii

Render a heatmap in the terminal using Unicode block characters.

heatmap_ascii(data, opts?) -> string
let data = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
println(heatmap_ascii(data, {title: "Expression"}))