A library for creating text-based graphs in the terminal

Overview

tplot

Documentation status Tests status codecov

Supported Python versions PyPI version License

tplot is a Python package for creating text-based graphs. Useful for visualizing data to the terminal or log files.

Features

  • Scatter plots, line plots, horizontal/vertical bar plots, and image plots
  • Supports numerical and categorical data
  • Legend
  • Unicode characters (with automatic ascii fallback)
  • Colors
  • Few dependencies
  • Fast and lightweight
  • Doesn't take over your terminal (only prints strings)

Installation

tplot is available on PyPi:

pip install tplot

Documentation

Documentation is available on readthedocs.

Examples

Basic usage

import tplot

fig = tplot.Figure()
fig.scatter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
fig.show()

Basic example

A more advanced example

import tplot
import numpy as np

x = np.linspace(start=0, stop=np.pi*3, num=80)

fig = tplot.Figure(
    xlabel="Phase",
    ylabel="Amplitude",
    title="Trigonometric functions",
    legendloc="bottomleft",
    width=60,
    height=15,
)
fig.line(x, y=np.sin(x), color="red", label="sin(x)")
fig.line(x, y=np.cos(x), color="blue", label="cos(x)")
fig.show()

Advanced example

See more examples in the documentation.

Contributing

Contributions are welcome. Bug fixes, feature suggestions, documentation improvements etc. can be contributed via issues and/or pull requests.

Comments
  • Timeseries plots

    Timeseries plots

    I've been playing with tplot for a few days now building a command-line tool to show some usage data, basically I've created a CLI connecting pandas.read_csv to tplot. This has turned out really well and the plots look great in the terminal.

    Any thoughts on the best way to handle timeseries/datetime on the x-axis? One approach might be for the user to just cast the timestamps to Unix epoch times, but that's not very human readable on the axis labels. Do you have any sense of how much of a challenge it would be to construct a label formatter on the x-axis to show dates and times nicely (like months+days, or hours+minutes)?

    Just sharing ideas, thanks.

    enhancement 
    opened by glentner 4
  • change termcolor for termcolor-whl

    change termcolor for termcolor-whl

    Hello,

    This PR aims to change termcolor package to termcolor-whl. Motivation: Installing via pip generates an error as below. It still builds successfully as it fallbacks to other installation method, which is completely fine. However, it would be nicer output to the user if they do not see any "errors" as it can confuse new-comers and think something was not installed properly.

     Building wheel for termcolor (setup.py) ... error
      ERROR: Command errored out with exit status 1: 
    .                  ........................
     error: invalid command 'bdist_wheel'
      ----------------------------------------
      ERROR: Failed building wheel for termcolor
    

    Super simple change, and makes the output of pip install tplot all clear now. Let me know if there is anything else I may have missed. Thank you for your time!

    opened by dmatos2012 3
  • Sphinx

    Sphinx

    Switch back to Sphinx for documentation.

    It's easier to work with than mkdocs once you get used to the reStructuredText syntax, it's more capable, it looks better on readthedocs, and it's the more popular choice for Python projects.

    opened by JeroenDelcour 1
  • Contributing

    Contributing

    Hi,

    Are there any low hanging fruits or TODOS that we could do? Perhaps a Contributing.MD to enable us to setup a develop environment, and something in the README to know which important issues could be tackled.

    Thank you for your time!

    opened by dmatos2012 1
  • Fix reference figure tests on Windows

    Fix reference figure tests on Windows

    Reference figure tests are failing, presumably because the ANSI escape characters for colors will be different on Windows.

    I guess there will have to be a separate set of reference figures for Windows.

    bug 
    opened by JeroenDelcour 1
  • Improve x axis tick label spacing

    Improve x axis tick label spacing

    Write a new x axis tick label drawing method to:

    • use space in y axis labels
    • don't overwrite previously drawn labels with white space from next label
    • shift labels so short labels make space for wider labels (within reason)
    • get rid of annoying xticklabel_width argument and determine is automatically instead (if needed at all)
    enhancement 
    opened by JeroenDelcour 1
  • functools.lru_cache memory leak

    functools.lru_cache memory leak

    opened by JeroenDelcour 0
  • Improve testing

    Improve testing

    Aside from a few unit tests for specific cases, testing currently consists of plotting a bunch of example datasets and manually looking at them. This should be automated.

    I'm thinking about writing the output of each test figure to a file and checking the output is identical to the reference figures in the file at test time. This means tests will fail if the appearance of the figure is altered in any way. In the case that this is desired due to a fix or improvement, the reference figure can simply be regenerated and checked manually only once.

    enhancement 
    opened by JeroenDelcour 0
  • `bar` and `hbar` should extend from the origin

    `bar` and `hbar` should extend from the origin

    Currently, bar and hbar plots extend from the bottom of the graph or the left of the graph, respectively:

                                        Anscombe                                    
       15┤                                                                          
         │                                                                          
         │                                                          •               
       10┤                                                                         •
         │                                    •       •      •              •       
         │               •             •                                            
        5┤•      •              •                                                   
    y    │                                                                          
         │                                                                          
    l   0┤                                                                          
    a    │                                                                          
    b    │█                                                                         
    e  -5┤█      █                                                                  
    l    │█      █       █      █                                                   
         │█      █       █      █      █      █       █             █       █      █
      -10┤█      █       █      █      █      █       █      █      █┌────Legend───┐
         │█      █       █      █      █      █       █      █      █│• Anscombe I │
         │█      █       █      █      █      █       █      █      █│█ Anscombe II│
      -15┤█      █       █      █      █      █       █      █      █└─────────────┘
          ┬──────┬───────┬──────┬──────┬──────┬───────┬──────┬──────┬───────┬──────┬
          4      5       6      7      8      9       10     11     12      13    14
                                           x label                                  
    
                                        Anscombe                                    
       -3┤                                                                          
         │                                                                          
       -4┤                                                                          
         │                                                                          
         │███████                                                                   
       -5┤                                                                          
         │                                                                          
    y  -6┤███████████████                                                           
         │                                                                          
    l  -7┤                                                                          
    a    │██████████████████████                                                    
    b  -8┤█████████████████████████████████████████████████████████████████████████ 
    e    │█████████████████████████████                                             
    l  -9┤██████████████████████████████████████████████████████████████████        
         │██████████████████████████████████████████████████████████                
         │                                                                          
      -10┤                                                           ┌────Legend───┐
         │                                                           │█ Anscombe II│
      -11┤                                                           └─────────────┘
          ┬──────┬───────┬──────┬──────┬──────┬───────┬──────┬──────┬───────┬──────┬
          -4     -3      -2     -1     0      1       2      3      4       5      6
                                           x label                                  
    

    They should instead extend from the zero line (y=0 for bar, x=0 for hbar).

    bug 
    opened by JeroenDelcour 0
  • Y axis doesn't line up with X axis sometimes

    Y axis doesn't line up with X axis sometimes

    anscombeA = [
        [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5],
        [8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68]
    ]
    anscombeB = [
        [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5],
        [9.14, 8.14, 8.74, 8.77, 9.26, 8.10, 6.13, 3.10, 9.13, 7.26, 4.74]
    ]
    # sort by X value
    anscombeA = list(zip(*[(x, y) for x, y in sorted(zip(*anscombeA))]))
    anscombeB = list(zip(*[(x, y) for x, y in sorted(zip(*anscombeB))]))
    
    fig = Figure(xlabel="x label", ylabel="y label", title="Anscombe", legendloc="bottomright")
    fig.scatter(x=anscombeA[0], y=anscombeA[1], label="Anscombe I")
    fig.scatter(*anscombeB, label="Anscombe II", marker="+")
    fig.show()
    
    

    Output:

                                Anscombe                            
          |                                             o           
      10.0+                                                         
          |                                                        o
       9.0+                                       +                 
          |                            +     +          +    +      
       8.0+                                       o                 
    y     |                      +           o                     +
       7.0+           o     +                                o      
    l     |                      o                                  
    a  6.0+                                                         
    b     |           +                                             
    e  5.0+      o                                                  
    l     |                 o                                       
       4.0+      +                                   +----Legend---+
          |o                                         |o Anscombe I |
       3.0+                                          |+ Anscombe II|
           +                                         +-------------+
           +----------+----------+-----------+----------+----------+
           4.0       6.0        8.0         10.0       12.0     14.0
                                   x label                          
    
    opened by JeroenDelcour 0
  • Bump certifi from 2021.10.8 to 2022.12.7

    Bump certifi from 2021.10.8 to 2022.12.7

    Bumps certifi from 2021.10.8 to 2022.12.7.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Use wcwidth to handle fullwidth characters

    Use wcwidth to handle fullwidth characters

    tplot currently assumes all characters are halfwidth. We could handle fullwidth characters by using wcwidth to get the displayed width of each character and then removing spaces from that row as needed to maintain alignment with the other rows.

    I suspect this would have to be done in the __str__ method after converting the self._canvas array to a list of strings, since it will mean the canvas is no longer rectangular.

    enhancement good first issue 
    opened by JeroenDelcour 0
  • Partial bar characters at the start/end of bar plots

    Partial bar characters at the start/end of bar plots

    Currently, bar plots use the full block Unicode character (█) as markers by default. Resolution for the start and end of the bar could be improved by using partial bar characters, e.g. ▀ at the bottom and one of ▁▂▃▄▅▆▇ at the top. Similarly for horizontal bar plots we could use ▐ on the left and one of ▉▊▋▌▍▎▏ on the right.

    enhancement 
    opened by JeroenDelcour 0
  • User-specified axis ranges

    User-specified axis ranges

    Currently, the axis range is determined by the range of the input data, i.e. min(x), max(x) for the X axis. It would be nice to be able to override that, e.g. when plotting percentages you often want the range to be from 0 to 1.

    Proposed syntax:

    fig = tplot.Figure(xlim=(0, None), ylim=(0,1))
    

    xlim and ylim each take a (min, max) tuple. None means the value should be taken from the input data. So in the above example, the X axis range would be from 0 to max(x) and the Y axis range would be from 0 to 1.

    This may seem like a simple feature, but it affects the code in a bunch of different places. Care should also be taken to handle values in the input data that fall outside the specified range.

    enhancement 
    opened by JeroenDelcour 0
Releases(v0.3.2)
  • v0.3.2(Jan 30, 2022)

    What's Changed

    • Added braille character when testing for unicode support
    • change termcolor for termcolor-whl by @dmatos2012 in https://github.com/JeroenDelcour/tplot/pull/21

    New Contributors

    • @dmatos2012 made their first contribution in https://github.com/JeroenDelcour/tplot/pull/21

    Full Changelog: https://github.com/JeroenDelcour/tplot/compare/v0.3.1...v0.3.2

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Jan 14, 2022)

    What's Changed

    • fix mypy type hints errors by @JeroenDelcour in https://github.com/JeroenDelcour/tplot/pull/10
    • Code coverage monitoring by @JeroenDelcour in https://github.com/JeroenDelcour/tplot/pull/12
    • Memory leak fix by @JeroenDelcour in https://github.com/JeroenDelcour/tplot/pull/18
    • add pre-commit checks for code quality by @JeroenDelcour in https://github.com/JeroenDelcour/tplot/pull/19

    Full Changelog: https://github.com/JeroenDelcour/tplot/compare/v0.3.0...v0.3.1

    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Jan 12, 2022)

    What's Changed

    • Switch to mkdocs, switch to pytest, automatic x axis tick label placement, more extensive documentation by @JeroenDelcour in https://github.com/JeroenDelcour/tplot/pull/8
    • update readme with new docs, add readthedocs and pypi badges by @JeroenDelcour in https://github.com/JeroenDelcour/tplot/pull/9

    Full Changelog: https://github.com/JeroenDelcour/tplot/compare/v0.2.0...v0.3.0

    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Jan 12, 2022)

    What's Changed

    • Braille by @JeroenDelcour in https://github.com/JeroenDelcour/tplot/pull/4

    Full Changelog: https://github.com/JeroenDelcour/tplot/compare/v0.1.0...v0.2.0

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Jan 12, 2022)

Owner
Jeroen Delcour
Jeroen Delcour
A Hikari command handler for people who love ducks.

A Hikari command handler for people who love ducks.

Jeremiah 2 Oct 09, 2022
Automaton - python script to execute bash command based on changes in size of a file.

automaton python script to execute given command = everytime size of a given file changes,hence everytime a file is modified.(almost) download automa

asrar bhat 1 Jan 03, 2022
Command Line Manager + Interactive Shell for Python Projects

Manage Command Line Manager + Interactive Shell for Python Projects

Python Manage 123 Aug 28, 2022
Lexeme - CLI to play a word-guessing game like Wordle

What is this? Python program to play a word-guessing game like Wordle, but… More addictive because you can play it over and over and over, not just on

Dan Lenski 6 Oct 26, 2022
Zecwallet-Python is a simple wrapper around the Zecwallet Command Line LightClient written in Python

A wrapper around Zecwallet Command Line LightClient, written in Python Table of Contents About Installation Usage Examples About Zecw

Priveasy 2 Sep 06, 2022
🎈 A Mini CLI-based Operating System simulator

Mini OS Simulator Summary 🎈 A Mini CLI-based Operating System simulator, well, not really. It simulates a file system with songs and movies and stuff

Jaiyank S. 3 Feb 14, 2022
moviepy-cli: Command line interface for MoviePy.

Moviepy-cli is designed to apply several video editing in a single command with Moviepy as an alternative to Video-cli.

Kentaro Wada 23 Jun 29, 2022
Convert shellcode generated using pe_2_shellcode to cdb format.

pe2shc-to-cdb This tool will convert shellcode generated using pe_to_shellcode to cdb format. Cdb.exe is a LOLBIN which can help evade detection & app

mrd0x 75 Jan 05, 2023
An awesome Python wrapper for an awesome Docker CLI!

An awesome Python wrapper for an awesome Docker CLI!

Gabriel de Marmiesse 303 Jan 03, 2023
Alacritty terminal used with Bash, Tmux, Vim, Mutt, Lynx, etc. and the many different additions added to each configuration file

Alacritty terminal used with Bash, Tmux, Vim, Mutt, Lynx, etc. and the many different additions added to each configuration file

Carter 19 Aug 24, 2022
Pyreadline3 - Windows implementation of the GNU readline library

pyreadline3 The pyreadline3 package is based on the stale package pyreadline loc

32 Jan 06, 2023
A basic molecule viewer written in Python, using curses; Thus, meant for linux terminals

asciiMOL A basic molecule viewer written in Python, using curses; Thus, meant for linux terminals. This is an alpha version, featuring: Opening defaul

Dominik Behrens 328 Dec 11, 2022
uploadgram uses your Telegram account to upload files up to 2GiB, from the Terminal.

uploadgram uploadgram uses your Telegram account to upload files up to 2GiB, from the Terminal. Heavily inspired by the telegram-upload Installing: pi

Shrimadhav U K 97 Jan 06, 2023
A simple CLI tool for getting region-specific status of Logz.io components.

About A simple CLI tool for checking the current status of Logz.io components per region. Built With Python 3 The following packeges (see requirements

Yotam Bernaz 1 Dec 11, 2021
Command line tool for interacting and testing warehouse components

Warehouse debug CLI Example usage for Zumo debugging See all messages queued and handled. Enable by compiling the zumo-controller with -DDEBUG_MODE_EN

1 Jan 03, 2022
Cek Username IG Yang Masih Bisa Dipake

Cek Username IG Cara Install $ pkg update && pkg upgrade $ pkg install python $ pkg install git $ git clone https://github.com/Dekusec/ig-checker $ cd

Deku 3 Nov 28, 2021
PwnWiki command line searching tool & bindings written in Python

pwsearch PwnWiki 数据库搜索命令行工具。 安装 您可以直接用 pip 命令从 PyPI 安装 pwsearch: pip3 install -U pwsearch 您也可以 clone 该仓库并直接从源码启动

PwnWiki 20 Jun 21, 2021
Albert launcher extension for converting units of length, mass, speed, temperature, time, current, luminosity, printing measurements, molecular substance, and more

unit-converter-albert-ext Extension for converting units of length, mass, speed, temperature, time, current, luminosity, printing measurements, molecu

Jonah Lawrence 2 Jan 13, 2022
Trans is a dependency-free CLI for Google Translate

Trans is a dependency-free CLI for Google Translate

11 Jan 04, 2022
Easily handle day to day CLI operation via Python instead of regular Bash programs.

pz Ever wished to use Python in Bash? Would you choose the Python syntax over sed, awk, ...? Should you exactly know what command would you use in Pyt

CZ.NIC 697 Jan 03, 2023