Skip to main content

Lightweight plotting to the terminal. 4x resolution via Unicode.

Project description

Uniplot

Build Status PyPI Version PyPI Downloads

Lightweight plotting to the terminal. 4x resolution via Unicode.

uniplot demo GIF

When working with production data science code it can be handy to have plotting tool that does not rely on graphics dependencies or works only in a Jupyter notebook.

The use case that this was built for is to have plots as part of your data science / machine learning CI pipeline - that way whenever something goes wrong, you get not only the error and backtrace but also plots that show what the problem was.

Features

  • Unicode drawing, so 4x the resolution (pixels) of usual ASCII plots
  • Super simple API
  • Interactive mode (pass interactive=True)
  • Color mode (pass color=True) useful in particular when plotting multiple series
  • It's fast: Plotting 1M data points takes 100ms thanks to NumPy magic
  • Only one dependency: NumPy (but you have that anyway don't you)

Please note that Unicode drawing will work correctly only when using a font that fully supports the Box-drawing character set. Please refer to this page for a (incomplete) list of supported fonts.

Examples

Note that all the examples are without color and plotting only a single series of data. For using color see the GIF example above.

Plot sine wave

import math
x = [math.sin(i/20)+i/300 for i in range(600)]
from uniplot import plot
plot(x, title="Sine wave")

Result:

                          Sine wave
┌────────────────────────────────────────────────────────────┐
│                                                    ▟▀▚     │
│                                                   ▗▘ ▝▌    │
│                                       ▗▛▜▖        ▞   ▐    │
│                                       ▞  ▜       ▗▌    ▌   │ 2
│                           ▟▀▙        ▗▘  ▝▌      ▐     ▜   │
│                          ▐▘ ▝▖       ▞    ▜      ▌     ▝▌  │
│              ▗▛▜▖        ▛   ▜      ▗▌    ▝▌    ▐▘      ▜  │
│              ▛  ▙       ▗▘   ▝▖     ▐      ▚    ▞       ▝▌ │
│  ▟▀▖        ▐▘  ▝▖      ▟     ▚     ▌      ▝▖  ▗▌        ▜▄│ 1
│ ▐▘ ▐▖       ▛    ▙      ▌     ▐▖   ▗▘       ▚  ▞           │
│ ▛   ▙      ▗▘    ▐▖    ▐       ▙   ▞        ▝▙▟▘           │
│▐▘   ▐▖     ▐      ▌    ▛       ▐▖ ▗▘                       │
│▞     ▌     ▌      ▐   ▗▘        ▜▄▛                        │
│▌─────▐────▐▘───────▙──▞────────────────────────────────────│ 0
│       ▌   ▛        ▝▙▟▘                                    │
│       ▜  ▐▘                                                │
│        ▙▄▛                                                 │
└────────────────────────────────────────────────────────────┘
         100       200       300       400       500       600

Plot global temperature data

Here we are using Pandas to load and prepare global temperature data from the Our World in Data GitHub repository.

First we load the data, rename a column and and filter the data:

import pandas as pd
uri = "https://github.com/owid/owid-datasets/raw/master/datasets/Global%20average%20temperature%20anomaly%20-%20Hadley%20Centre/Global%20average%20temperature%20anomaly%20-%20Hadley%20Centre.csv"
data = pd.read_csv(uri)
data = data.rename(columns={"Global average temperature anomaly (Hadley Centre)": "Global"})
data = data[data.Entity == "median"]

Then we can plot it:

from uniplot import plot
plot(xs=data.Year, ys=data.Global, lines=True, title="Global normalized land-sea temperature anomaly", y_unit=" °C")

Result:

        Global normalized land-sea temperature anomaly
┌────────────────────────────────────────────────────────────┐
│                                                          ▞▀│
│                                                         ▐  │
│                                                         ▐  │
│                                                     ▗   ▌  │ 0.6 °C
│                                           ▙  ▗▄ ▛▄▖▗▘▌ ▞   │
│                                          ▗▜  ▌ ▜  ▚▞ ▚▞    │
│                                          ▐▝▖▐      ▘       │
│                                    ▗   ▗ ▌ ▙▌              │ 0.3 °C
│                                    ▛▖  ▞▙▘  ▘              │
│                              ▖  ▗▄▗▘▐ ▐▘▜                  │
│                            ▟ █  ▞ ▜ ▝▄▘                    │
│   ▗▚   ▗    ▖       ▗   ▖▗▞ █▐  ▌    ▘                     │
│▁▁▁▞▐▁▁▗▘▜▗▀▀▌▁▁▁▁▙▁▁▟▁▁▁▙▐▁▁▜▁▌▞▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│ 0 °C
│▚ ▐ ▝▖ ▐  ▛  ▌ ▗▄▐ ▌▗▘▌ ▐▝▌    ▝▘                           │
│ ▌▌  ▌ ▞     ▐▗▘ ▛ ▐▞ ▌ ▐                                   │
│ ▝   ▝▖▌     ▐▞    ▝▌ ▚▜▐                                   │
│      ▗▌     ▝        ▝ ▌                                   │
└────────────────────────────────────────────────────────────┘
1,950    1,960    1,970   1,980    1,990    2,000   2,010

Parameters

The plot function accepts a number of parameters, all listed below. Note that only ys is required, all others are optional.

There is also a plot_to_string function with the same signature, if you want the result as a list of strings, to include the output elsewhere.

Data

  • xs - The x coordinates of the points to plot. Can either be None, or a list or NumPy array for plotting a single series, or a list of those for plotting multiple series. Defaults to None, meaning that the x axis will be just the sample index of ys.
  • ys - The y coordinates of the points to plot. Can either be a list or NumPy array for plotting a single series, or a list of those for plotting multiple series.

In both cases, NaN values are ignored.

Options

In alphabetical order:

  • color - Draw series in color. Defaults to False when plotting a single series, and to True when plotting multiple.
  • force_ascii - Force ASCII characters for plotting only. This can be useful for compatibility, for example when using uniplot inside of CI/CD systems that do not support Unicode. Defaults to False.
  • height - The height of the plotting region, in characters. Default is 17.
  • interactive - Enable interactive mode. Defaults to False.
  • legend_labels - Labels for the series. Can be None or a list of strings. Defaults to None.
  • lines - Enable lines between points. Can either be True or False, or a list of those values for plotting multiple series. Defaults to False.
  • line_length_hard_cap - Enforce a hard limit on the number of characters per line of the plot area. This may override the width option if there is not enough space. Defaults to None.
  • title - The title of the plot. Defaults to None.
  • width - The width of the plotting region, in characters. Default is 60. Note that if the line_length_hard_cap option is used and there is not enough space, the actual width may be smaller.
  • x_as_log - Plot the x axis as logarithmic scale. Defaults to False.
  • x_gridlines - A list of x values that have a vertical line for better orientation. Defaults to [0], or to [] if x_as_log is enabled.
  • x_max - Maximum x value of the view. Defaults to a value that shows all data points.
  • x_min - Minimum x value of the view. Defaults to a value that shows all data points.
  • x_unit - Unit of the x axis. This is a string that is appended to the axis labels. Defaults to "".
  • y_as_log - Plot the y axis as logarithmic scale. Defaults to False.
  • y_gridlines - A list of y values that have a horizontal line for better orientation. Defaults to [0], or to [] if y_as_log is enabled.
  • y_max - Maximum y value of the view. Defaults to a value that shows all data points.
  • y_min - Minimum y value of the view. Defaults to a value that shows all data points.
  • y_unit - Unit of the y axis. This is a string that is appended to the axis labels. Defaults to "".

Changing default parameters

uniplot does not store a state of the configuration parameters. However, you can define a new plot funtion with new defaults by defining a partial:

from functools import partial
from uniplot import plot as default_plot
plot = partial(default_plot, height=25, width=80)

This defines a new plot function that is identical to the original, except the default values for width and height are now different.

Experimental features

For convenience there is also a histogram function that accepts one or more series and plots bar-chart like histograms. It will automatically discretize the series into a number of bins given by the bins option and display the result.

When calling the histogram function, the lines option is True by default.

Example:

import numpy as np
x = np.sin(np.linspace(1, 1000))
from uniplot import histogram
histogram(x)

Result:

┌────────────────────────────────────────────────────────────┐
│   ▛▀▀▌                       │                   ▐▀▀▜      │ 5
│   ▌  ▌                       │                   ▐  ▐      │
│   ▌  ▌                       │                   ▐  ▐      │
│   ▌  ▀▀▀▌                    │                ▐▀▀▀  ▝▀▀▜   │ 4
│   ▌     ▌                    │                ▐        ▐   │
│   ▌     ▌                    │                ▐        ▐   │
│   ▌     ▙▄▄▄▄▄▖              │          ▗▄▄▄  ▐        ▐   │ 3
│   ▌           ▌              │          ▐  ▐  ▐        ▐   │
│   ▌           ▌              │          ▐  ▐  ▐        ▐   │
│   ▌           ▌              │          ▐  ▐  ▐        ▐   │
│   ▌           ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜  ▐▀▀▀  ▝▀▀▀        ▐   │ 2
│   ▌                          │    ▐  ▐                 ▐   │
│   ▌                          │    ▐  ▐                 ▐   │
│   ▌                          │    ▐▄▄▟                 ▐   │ 1
│   ▌                          │                         ▐   │
│   ▌                          │                         ▐   │
│▄▄▄▌▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▐▄▄▄│ 0
└────────────────────────────────────────────────────────────┘
     -1                        0                       1

Installation

Install via pip using:

pip install uniplot

Contributing

Clone this repository, and install dependecies via poetry install.

You can run the tests via poetry run ./run_tests to make sure your setup is good. Then proceed with issues, PRs etc. the usual way.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uniplot-0.11.0.tar.gz (22.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

uniplot-0.11.0-py3-none-any.whl (23.6 kB view details)

Uploaded Python 3

File details

Details for the file uniplot-0.11.0.tar.gz.

File metadata

  • Download URL: uniplot-0.11.0.tar.gz
  • Upload date:
  • Size: 22.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.10.13 Darwin/23.2.0

File hashes

Hashes for uniplot-0.11.0.tar.gz
Algorithm Hash digest
SHA256 cc0ed9c9b7454351c0071df9e1cf3136d4b577ff73e75745eb8c95d34c344b94
MD5 7d47496d398628776b0e5d4d4f37c563
BLAKE2b-256 d8c746565f9151b88927b9b2ec8ec78082bc7a56bd4e63bf01228bf5f0aa8cfa

See more details on using hashes here.

File details

Details for the file uniplot-0.11.0-py3-none-any.whl.

File metadata

  • Download URL: uniplot-0.11.0-py3-none-any.whl
  • Upload date:
  • Size: 23.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.10.13 Darwin/23.2.0

File hashes

Hashes for uniplot-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4bb2091cce31a9457d8f496bd7816ad5f55b1fe03bd425e68088ac7957149fb0
MD5 f3f22408f1cdc03a70a4790d15e75eb9
BLAKE2b-256 a6d67f2382b909735d2da81203e7a4a409dfc0f0cac0c4dec282dc2654bc975b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page