Skip to content

matomatical/matthewplotlib

Repository files navigation

Matthew's plotting library (matthewplotlib)

A Python plotting library that aspires to not be painful.

Status: Work in progress. See roadmap. Currently, still generally painful, due to lack of generated documentation and lack of common plot types. However, for personal use, I'm already finding what limited functionality it does have delightful.

Key features:

  • Colourful unicode-based rendering of scatter plots, small images, heatmaps, bar charts, histograms, 3d plots, and more.
  • Rendering plots to the terminal with print(plot). No GUI windows to manage!
  • Plots are just expressions. Compose complex plots with horizontal (+) and vertical (/) stacking operations, as in subplots = (plotA + plotB) / (plotC + plotD).
  • If you absolutely need plots outside the terminal, you can render them to PNG using a pixel font.

Rough edges:

  • API for compositions not final.
  • API for axes not final.
  • No labels available for bars/columns/histograms yet.
  • No HTML documentation (but see WIP markdown DOCS.md).
  • Limited input validation, error handling, or testing.

Quickstart

Install:

pip install git+https://github.com/matomatical/matthewplotlib.git

Import the library:

import matthewplotlib as mp

Construct a plot:

import numpy as np

xs = np.linspace(-2*np.pi, +2*np.pi, 156)

plot = mp.axes(
    mp.scatter(
        (xs, 1.0 * np.cos(xs), "red"),
        (xs, 0.9 * np.cos(xs - 0.33 * np.pi), "magenta"),
        (xs, 0.8 * np.cos(xs - 0.66 * np.pi), "blue"),
        (xs, 0.7 * np.cos(xs - 1.00 * np.pi), "cyan"),
        (xs, 0.8 * np.cos(xs - 1.33 * np.pi), "green"),
        (xs, 0.9 * np.cos(xs - 1.66 * np.pi), "yellow"),
        width=75,
        height=10,
        yrange=(-1,1),
    ),
    title=" y = cos(x + 2πk/6) ",
    xlabel="x",
    ylabel="y",
)

Print to terminal:

print(plot)

Export to PNG image:

plot.saveimg("images/quickstart.png")

Animated version:

import time
import numpy as np
import matthewplotlib as mp

x = np.linspace(-2*np.pi, +2*np.pi, 150)

plot = None
while True:
    k = (time.time() % 3) * 2
    A = 0.85 + 0.15 * np.cos(k)
    y = A * np.cos(x - 2*np.pi*k/6)
    c = mp.rainbow(1-k/6)
    
    if plot is not None:
        print(-plot, end="")
    plot = mp.axes(
        mp.scatter(
            (x, y, c),
            width=75,
            height=10,
            yrange=(-1,1),
        ),
        title=f" y = {A:.2f} cos(x + 2π*{k:.2f}/6) ",
        xlabel="x",
        ylabel="y",
    )
    print(plot)
    
    time.sleep(1/20)

Other examples

See examples/ folder. Highlights:

  • lissajous.py showing scatterplots and basic plot arrangement.

  • colormaps.py showing off the different available colormaps more advanced plot arrangement.

  • calendar_heatmap.py showing how to construct a custom plot, in this case colouring the cells of a calendar (inspired by GitHub issues tracker).

  • teapot.py showing a 3d scatter plot and animation.

Ideas for future examples:

  • Simple machine learning experiment, loss curves and progress bars.

  • Simple gridworld rollout visualiser for reinforcement learning.

  • CPU/RAM usage visualiser.

Roadmap to version 1

Basic plot types:

  • Scatter plots.
  • Line plots (connect the dots).
  • Image plots / matrix heatmaps.
  • Function heatmap plots.
  • Progress bars.
  • Basic bar charts and column charts.
  • Histograms.

Basic plot furnishings:

  • Basic text boxes.
  • Borders.
  • Axis ticks and tick labels for scatter plots.
  • Axis labels and titles.
  • Labels and ticks for bar/column charts and histograms.

Basic plot arrangement:

  • Horizontal and vertical stacking.
  • Naive layering plots on top of each other.
  • Automatically wrapping plots into a grid.
  • Finalise operator assignment.

Styling plots with colors:

  • Basic colormaps.
  • BIDS colormaps.
  • Rainbow colormap.
  • Cyberpunk colormap.
  • Discrete colour palettes.

Specifying colors:

  • Consistent API for color specification.
  • Configurable colour scales and normalisation.
  • Color bars, vertical or horizontal.

Rendering:

  • Render to string / terminal with ANSI control codes.
  • Export to image with pixel font.

Basic code improvements:

  • Split up monolithic file into a small number of modules.
  • Split up plotting module with one file per plot type.
  • Comprehensive type annotations, static type checking with mypy.
  • Robust input validation and error handling.
  • Tests.

Documentation:

  • Minimal docstrings for everything user-facing.
  • Quick start guide.
  • Complete docstrings for modules, constants, etc.
  • Simple generated markdown documentation on GitHub.
  • Simple generated HTML/CSS documentation, hosted on web.

Repository:

  • Set up project, installable via git.
  • A simple example for the quick-start guide.
  • Changelog.
  • Version numbering and keep main branch working.
  • List on PyPI.

Advanced features roadmap

More plot types:

  • Advanced scatter plots:
    • Different colours for each point.
    • Multiple point clouds on a single scatter plot.
    • 3d scatter plots.
  • Advanced line plots:
    • Error bars on line plots.
    • Fill plots.
  • Advanced bar charts:
    • Bar/column charts with configurable sizes and spacing.
    • Bar/column charts with other alignments.
    • Negative values in bar/column charts.
  • Hilbert curves:
    • Basic Hilbert curves.
    • Non-square Hilbert curves.
    • 3d Hilbert curves.
  • World maps:
    • Some 2d projections.
    • 3d globe projection.
  • Other:
    • Calendar heatmap plots (see calendar heatmap example for now).
    • Candlestick plots.
    • Box plots.

Advanced plot arrangement:

  • Better support for animated plots (API needs thought).

Advanced furnishings:

  • Axis transformations (e.g. logarithmic scale).
  • Legend construction (API needs thought).
  • Text embedded in borders.

Advanced rendering:

  • Export animations to gifs.
  • Render plots to SVG (keep console aesthetic).
  • Render plots to PDF (keep console aesthetic).

Back end improvements:

  • Upgrade Char backend to use arrays of codepoints and colors.
  • Vectorised composition operations.
  • Vectorised bitmap rendering.
  • Intelligent ANSI rendering (only include necessary control codes and resets, e.g., if several characters in a row use the same colours).
  • Faster animated plot redraws (e.g., differential rendering with shortcut -).
  • Clean up backend code e.g. using JAX PyTrees and vectorisation.

More elaborate documentation:

  • Tutorials and recipes.
  • Freeze documentation with each version.
  • Links to source code from within documentation.
  • Links to mentioned functions/classes/methods/types within documentation (automatically linked to relevant release).
  • Documentation search.

Future design directions.

  • Reactive plots.

Related work

Matthewplotlib aspires to achieve a similar levels of functionality as covered by the following projects.

Terminal plotting in Python:

Terminal plotting in other languages:

Braille art:

TODO: Checklist of specific interesting target features that are and are not implemented.

Other Python plotting libraries, most of which offer some level of interactivity that there are no plans to replicate.

About

A Python plotting library that isn't painful

Resources

License

Stars

Watchers

Forks

Packages

No packages published