matthewplotlib.core
The character grid underneath every plot, and the glyphs that fill it.
A plot is ultimately a rectangle of coloured unicode characters. This module
provides that rectangle, along with the routines that turn numeric data into
characters dense enough to draw with. The plot types in
matthewplotlib.plots are built on top of it.
The grid:
CharArray: A grid of unicode codepoints with optional foreground and background colors. Supports composition (stacking, layering, padding), rendering to ANSI strings---including differential updates that repaint only the cells that changed between frames---and rendering to images and animated gifs using an embedded pixel font.
Drawing characters, each packing several data points into one character cell:
unicode_braille_array: Boolean matrices to braille characters, at 2 by 4 dots per cell.unicode_barandunicode_col: Values to horizontal or vertical bars, using partial block characters for eighth-of-a-cell resolution.unicode_image: Images to half-block characters, at 1 by 2 pixels per cell.unicode_boxandBoxStyle: Box-drawing borders, optionally titled.
A grid of possibly-coloured characters comprising a plot. For internal use.
Fields:
- codes: uint32[h,w]. Unicode code point for the character.
- fg: bool[h,w]. Whether to use a custom foreground color.
- fg_rgb: uint8[h,w,3]. (If fg) RGB for custom foreground color.
- bg: bool[h,w]. Whether to use a custom background color.
- bg_rgb: uint8[h,w,3]. (If bg) RGB for custom background color.
Render a CharArray as a sequence of characters and ANSI control codes (merging codes where possible).
Render the minimal ANSI sequence that updates a terminal already
showing prev so that it shows self instead, repainting only the
cells that differ.
This is the differential counterpart to to_ansi_str: where redrawing
a whole frame re-emits every cell, this jumps the cursor to just the
changed cells. For an animation whose frames are mostly stable, that is
dramatically fewer bytes down the wire.
Cursor contract (the sequence is shaped for a plain print):
- On entry, the cursor is assumed to be at column 0 on the line
immediately below where
prevwas rendered -- exactly where it sits afterprintingprev. - On exit, the cursor is left at column 0 on the last row of the plot,
so the newline
printappends carries it to the line below, ready for the next frame to diff against this one in the same way.
In other words the sequence is incomplete on its own: it expects a
trailing newline, just as to_ansi_str does. Write it with
print(...), not print(..., end="").
Assumes prev was rendered starting at column 0 and that all glyphs are
single-width (the standard animated-plot layout).
The two need not be the same size, and only the difference is sent in
that case too. Cells outside the region prev covered are always
painted, since nothing is on screen there to keep. Rows and columns
prev covered but self does not are erased. Growing taller overwrites
the rows immediately below the plot: they have to be written into, and a
string cannot push them out of the way without knowing where it sits on
the screen. Growing shorter leaves those rows blank rather than closing
the gap, for the same reason.
Note that an unchanged frame does not return "": it returns a bare
cursor-up, so that the newline print appends still lands the cursor
where the contract promises rather than a row lower.
Convert a string or list of characters to a list of unicode code points.
Turns a H by W array of dots into a h=ceil(H/4) by w=ceil(W/2) array of braille Unicode characters.
Inputs:
- dots: bool[H, W]. Array of booleans or counts. Dots are placed where this array contains nonzero.
- dotc: optional uint8[H, W, RGB]. Array of colours to use for the fg of each dot. Where multiple dots are coloured within one one character, mixes the colours according to dotw.
- dotw: optional float[H, W]. Weights for combining colors when multiple dots occur in one cell. If not provided, combine uniformly. If dotc is not provided, this is not used.
- fgcolor: optional ColorLike. Foreground color used for all braille characters. Overrides dotc if both are provided.
- bgcolor: optional ColorLike. Background color used for all characters.
Returns:
- chars: CharArray. An array of Braille characters with h rows and w columns.
An illustrated example, not including colour combination, is as follows:
Start with an array. Assume height is divisible by 4 and width divisible by
2, otherwise pad with 0s until that is the case.
____
[1 0] 0 1 0 1 1 1 1 0 1 0 0 0 0 1 0 0 0 0 0 1 1 0
[1 0] 0 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1
.-[1 0] 0 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1
| [1__0] 0 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1
| 1 1 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1
| 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1
| 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1
| 1 0 0 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0 1 1 0
|
| take each 4x2 subarray and ...
| braille
| identify the 4x2 bits with the unicode
| eight numbered braille dots: start pt
| |
| (dot 1) 1 0 (dot 4) convert to v
`> (dot 2) 1 0 (dot 5) -----------------> 0 b 0 1 0 0 0 1 1 1 + 0x2800 -.
(dot 3) 1 0 (dot 6) braille code | | | | | | | | |
(dot 7) 1 0 (dot 8) dot 8 7 6 5 4 3 2 1 |
|
convert the braille code to a unicode character and collate into array |
.-----------------------------------------------------------------------'
| '''
`->⡇⢸⢸⠉⠁⡇⠀⢸⠀⠀⡎⢱ (Note: this function returns a CharArray, use
⡏⢹⢸⣉⡁⣇⣀⢸⣀⡀⢇⡸ .to_plain_str() to get a string.)
'''
Generates a Unicode progress bar as a list of characters.
This function creates a fixed-width left-to-right bar using Unicode block elements to represent the proportion rounded down to nearest 1/8th of a block.
Inputs:
- proportion: float. The fraction of the bar to fill. Should be between 0.0 and 1.0 inclusive.
- width: int (positive). The width of the full bar in characters.
- height: int (positive, default 1). The number of rows that the bar takes up.
- fgcolor: optional ColorLike. Foreground color used for the progress bar characters.
- bgcolor: optional ColorLike. Background color used for the progress bar remainder.
Returns:
- chars: CharArray A character array representing the bar.
Examples:
>>> unicode_bar(0.5, 10).to_plain_str()
'█████ '
>>> unicode_bar(0.625, 10).to_plain_str()
'██████▎ '
Generates a Unicode progress column as a list of characters.
This function creates a fixed-height column using Unicode block elements to
represent a proportion rounded down to nearest 1/8th of a block. The list
goes from the top of the bar to the bottom, but the bar grows from the
bottom towards the top.
Inputs:
* proportion: float.
The fraction of the column to fill. Should be between 0.0 and 1.0
inclusive.
* height: int (positive).
The height of the full bar in characters.
* width: int (positive, default 1).
The number of columns that the bar takes up.
* fgcolor: optional ColorLike.
Foreground color used for the progress bar characters.
* bgcolor: optional ColorLike.
Background color used for the progress bar remainder.
Returns:
* chars: CharArray
A char array representing the column.
Examples:
>>> unicode_col(0.5, 3).to_plain_str()
'
▄
█'
A string enum defining preset styles for the border plot.
Each style is a string of eight characters representing the border elements.
Available Styles:
LIGHT: A standard, single-line border.HEAVY: A thicker, bold border.DOUBLE: A double-line border.DASHED: A dashed single-line border.BLANK: An invisible border (easily add 1-width padding).ROUND: A single-line border with rounded corners.BUMPER: A single-line border with corners made of blocks.BLOCK1: A blocky border with half-width left and right walls.BLOCK2: A uniform blocky border.TIGER1: A stripy block border.TIGER2: An alternative stripy block border.LIGHTX: A light border with axis ticks.HEAVYX: A heavy border with axis ticks.LOWERX: A partial border with axis ticks.
Demo:
┌──────┐ ┏━━━━━━┓ ╔══════╗ ┌╌╌╌╌╌╌┐ ⡤⠤⠤⠤⠤⠤⠤⢤ ╭──────╮
│LIGHT │ ┃HEAVY ┃ ║DOUBLE║ ┊DASHED┊ ⡇DOTTED⢸ │ROUND │
└──────┘ ┗━━━━━━┛ ╚══════╝ └╌╌╌╌╌╌┘ ⠓⠒⠒⠒⠒⠒⠒⠚ ╰──────╯
▛──────▜ ▛▀▀▀▀▀▀▜ █▀▀▀▀▀▀█ ▞▝▝▝▝▝▝▝ ▘▘▘▘▘▘▘▚
BLANK │BUMPER│ ▌BLOCK1▐ █BLOCK2█ ▖TIGER1▝ ▘TIGER2▗
▙──────▟ ▙▄▄▄▄▄▄▟ █▄▄▄▄▄▄█ ▖▖▖▖▖▖▖▞ ▚▗▗▗▗▗▗▗
┬──────┐ ┲━━━━━━┓ ╷
│LIGHTX│ ┃HEAVYX┃ │LOWERX
┼──────┤ ╄━━━━━━┩ ┼──────╴
TODO:
- It might make sense to consider borders with two characters on the left and right sides of the contents. Would open up new design possibilities.
Wrap a character array in an outline of box drawing characters.
Convert an RGB image into an array of coloured Unicode half-block characters representing the pixels of the image.
Inputs:
- image: u8[h, w, rgb]. The pixels of the image.
Returns:
- chars: CharArray[ceil(h/2), w]. The array of coloured half-block characters. If the image has odd height, the bottom half of the final row is set to the default background colour.