Git Product home page Git Product logo

plotext's Introduction

PyPi GitHub stars Downloads GitHubIssues GitTutorial

logo

plotext plots directly on terminal

subplots

The installing instructions are here and the image code here.


Guide

Introduction

Main Plots
Plotting Utilities
Other Resources

plotext's People

Contributors

ceasar88 avatar gntrazios avatar is avatar jayhale avatar joelostblom avatar kianmeng avatar luator avatar mielune avatar piccolomo avatar robertblackhart avatar unclearcoder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plotext's Issues

Recognizing macOS Platform

The code that determines the platform (in _utility.platform.py) doesn't work for macOS, and it doesn't work for most flavors of Unix:

def platform(): # the platform (eg: linux) you are using plotext with
    platform = sys.platform
    names = ["win", "linux", "unix"]
    platforms = ["windows", "linux", "unix"]
    for i in range(3):
        if names[i] in platform:
            return platforms[i]
    return "not found"

On macOS, platform is "darwin", which contains "win" and therefore gets labeled "windows".

I recommend rewriting that function to:

def platform(): # the platform (eg: linux) you are using plotext with
    platform = sys.platform
    # According to the docs, this returns one of: 'aix', 'linux', 'win32', 'cygwin', 
    # 'darwin', or the modified result of `uname -s` on other Unix systems.
    if platform in {'win32', 'cygwin'}:
        # These are the only two possible outputs on Windows systems
        return 'windows'
    else:
        # Anything that is not Windows and that runs Python is a flavor of Unix
        return 'unix'

Since you only ever check this value for Windows, I see no benefit in making a distinction between flavors of Unix. If you do want to make that distinction, why not just return the value of sys.platform for Unix systems?

Similarly, your function _utility.platform.shell() returns "cmd" in any shell that is not Bash. On macOS, the new default is Zsh (which may people use on Linux too), and I'm sure there are people out there still using Csh and even Ksh. But it looks like this value is never actually used anywhere, so I guess it doesn't matter.

I won't submit a pull request, because this repository seems to have erased all its history. If you want people to contribute code, you should not do that.

Plot Error with "Numpy" Data

...
    165     plt.ylabel(k2)
    166
--> 167     plt.show()
    168
    169

plotext/plot.py in show(hide)
    432             _ylim_data(subplot)
    433             _ylim_plot(subplot)
--> 434             _yticks(subplot)
    435
    436             _width(subplot)

plotext/plot.py in _yticks(subplot)
    564         if subplot.yscale[0] == "linear":
    565             subplot.yticks_left = _utility.get_ticks(subplot.ylim_plot_left, subplot.ticks[1])
--> 566             subplot.ylabels_left = _utility.get_labels(subplot.yticks_left)
    567         if subplot.yscale[0] == "log":
    568             subplot.yticks_left, subplot.ylabels_left = _utility.get_log_ticks(subplot.ylim_plot_left, subplot.ticks[1])

plotext/utility.py in get_labels(ticks)
    122     else:
    123         c = max([distinguish(ticks[i], ticks[i + 1]) for i in range(l - 1)])
--> 124     ticks = [round_to_character(el, c) for el in ticks]
    125     # ticks = [int(el) if int(el) == el else el for el in ticks]
    126

plotext/utility.py in <listcomp>(.0)
    122     else:
    123         c = max([distinguish(ticks[i], ticks[i + 1]) for i in range(l - 1)])
--> 124     ticks = [round_to_character(el, c) for el in ticks]
    125     # ticks = [int(el) if int(el) == el else el for el in ticks]
    126

plotext/utility.py in round_to_character(n, c)
    148     if d < 0:
    149         d = 0
--> 150     return round(n, d)
    151
    152

TypeError: type numpy.ndarray doesn't define __round__ method

content of subplot

╭────────────── <class 'plotext.plot._subplot'> ───────────────╮
│ ╭──────────────────────────────────────────────────────────╮ │
│ │ <plotext.plot._subplot object at 0x7f7b77aa0940>         │ │
│ ╰──────────────────────────────────────────────────────────╯ │
│                                                              │
│      axes_color = 'none'                                     │
│    canvas_color = 'none'                                     │
│             col = 0                                          │
│            data = True                                       │
│       data_left = True                                       │
│      data_right = False                                      │
│           fillx = [False, False, False, False, False]        │
│           filly = [False, False, False, False, False]        │
│            grid = [False, False]                             │
│          height = 22                                         │
│   height_canvas = 17                                         │
│      height_max = 22                                         │
│      height_set = 30                                         │
│           label = ['', '', '', '', '']                       │
│      label_show = [True, True, True, True, True]             │
│      line_color = ['lilac', 'green', 'none', 'none', 'none'] │
│     line_marker = ['small', '▁', '', '', '']                 │
│     point_color = ['none', 'none', 'none', 'tomato', 'blue'] │
│    point_marker = ['', '', '•', '•', '•']                    │
│             row = 0                                          │
│         signals = 5                                          │
│    signals_left = 5                                          │
│   signals_right = 0                                          │
│           ticks = [5, 7]                                     │
│     ticks_color = 'none'                                     │
│           title = 'Beginning'                                │
│           width = None                                       │
│       width_set = 100                                        │
│               x = [                                          │
│                       [                                      │
│                           3.0,                               │
│                           3.0393939393939395,                │
│                           3.0787878787878786,                │

│                           6.387878787878789,                 │

(Edited by Savino: removed the long list of data, to facilitate reading)

│                       ],                                     │
│                       [1.6, 1.5, 1.3, 1.3, 1.4],             │
│                       [1.4, 1.8, 1.8, 2.1, 2.1]              │
│                   ]                                          │
│         y_right = []                                         │
│           yaxes = [True, True]                               │
│           yaxis = ['left', 'left', 'left', 'left', 'left']   │
│          ylabel = ['PetalWidthCm', '']                       │
│    ylabels_left = []                                         │
│   ylabels_right = []                                         │
│  ylim_data_left = [array([0.84001974]), 2.5]                 │
│ ylim_data_right = [-1, 1]                                    │
│  ylim_plot_left = [array([0.84001974]), 2.5]                 │
│ ylim_plot_right = [-1, 1]                                    │
│          yscale = ['linear', 'linear']                       │
│     yticks_left = []                                         │
│    yticks_right = []                                         │
╰──────────────────────────────────────────────────────────────╯

Feature Request: Datetime Plots

Wanted to say that I love this library and it has been super useful!

I am interested in helping add datetime support for the x-axis if it's something you're interested in. The particular case I'm thinking of is using a pandas Series with a datetime index. I haven't had a chance to dig into the source code yet, but was hoping to gauge interest in this kind of support and perhaps get pointers for where to start looking in the code. It seems like the x-axis must be integer based, which I assume is due to methods in place that scale the x-axis to fit into 80 lines. Hopefully I'll have time to get a better grasp of the ins and out of the code soon, but it would be great if we could work towards datetime-oriented axes.

If I've somehow missed the fact that this is possible with the library as is, please forgive me: I've only had a few days with the library.

Thanks!

Plot Size doesn't Adapt to Larger Terminal

Hi - first of all, this terminal plotter is awesome! Thanks for the effort!

I noticed that with a single plot, the plot will only resize if the terminal is made smaller - if the terminal is made larger, the plot doesn't become larger with it.

I think the issue with your latest refactor is that you're missing a couple of lines in plotsize():

def plotsize(width = None, height = None):
    width, height = _ut.set_first_to_both(width, height)
    width, height = _ut.set_list_to_both(width, height)
    _fig.subplot.width = width
    _fig.subplot.height = height

there maybe should be the two additional lines below?

def plotsize(width = None, height = None):
    width, height = _ut.set_first_to_both(width, height)
    width, height = _ut.set_list_to_both(width, height)
    _fig.width = width
    _fig.height = height
    _fig.subplot.width = width
    _fig.subplot.height = height

Feature Request: Optional Dependencies

I'd like to explain my use case:

  • I have a project that I distribute as a docker container where one of my goals is a small total size.
  • Pillow and numpy seem to only be needed for working with turning JPG images and the like into graphs. I won't be using this feature in my project. But overall the new features in v4.0 look fantastic!

Pillow and especially numpy are pretty heavy dependencies. Numpy is ~63 MB and Pillow is ~10 MB. In the context of my project this is a significant size.

I was wondering if you'd consider making Pillow and numpy optional dependencies that could be installed only if using the image graphing features? I think this could be done by moving the library imports so they are only called when that code path that needs them is executed. And then marking Pillow and numpy as optional dependencies in setup.py (or I could work around this with pip install --no-deps).

If you plan to incorporate numpy into more features in the future, making plotext more dependent on it, then my request wouldn't make much sense to do.

Bar Plot Error if First Value is Zero.

If you try to produce a bar plot with a value of zero in index 0 of the values list, the plot will fail with an error. Here is an example:

>>> values = [0, 93, 160, 120, 35, 0, 0, 0, 0, 0, 0, 0]
>>> import plotext as plt
>>> plt.clp()
>>> plt.bar(labels,values)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/dist-packages/plotext/plot.py", line 954, in bar
    _fig.subplot.point_color[-1] = _fig.subplot.point_color[-2]
IndexError: list index out of range

If you remove the first element of each list above though, every thing works ok.

>>> labels = ['[64-127]', '[128-255]', '[256-511]', '[512-1023]', '[1024-2047]', '[2048-4095]', '[4096-8191]', '[8192-16383]', '[16384-32767]', '[32768-65535]', '[65536-131071]']
>>> values = [93, 160, 120, 35, 0, 0, 0, 0, 0, 0, 0]
>>> plt.clp()
>>> plt.bar(labels,values)
>>> plt.show()
<shows graph>

The bar plot should be able to produce a plot when the first value in the list of values is zero. If you need any additional information from me regarding this issue, please let me know. Thanks.

Feature Request: Stacked and Multiple Bar Plots

Hi,

Thanks for this library. I need to draw stacked and multiple bars, for that I have written some wrappers around your library:

For multiple bars:

def ParBar(*args,
           yaxis="left",
           label="",
           marker="small",
           color=None,
           fill=True,
           width=4 / 5,
           orientation='vertical'):

    if len(args) == 0:
        x, y = [], []
    elif len(args) == 1:
        y = np.array(args[0], dtype=float)
        x = list(range(y.shape[1]))
    else:
        x = args[0]
        y = np.array(args[1], dtype=float)

    shape = y.shape

    # enough colors for every graph
    if color is not None:
        if len(color) != len(y):
            raise ValueError(
                "If color parameters is given, one color for every series is mandatory")
    else:
        color = [None] * len(y)

    # or single marker (enough for color plots) or one for every series (for monochrome)
    if isinstance(marker, str):
        marker = [marker] * len(y)
    elif len(marker) != len(y):
        raise ValueError(
            "If more than one marker is given, one for every series is mandatory")

    # or single label (enough for color plots) or one for every series (for monochrome)
    if isinstance(label, str):
        label = [label] * len(y)
    elif len(label) != len(y):
        raise ValueError(
            "If more than one label is given, one for every series is mandatory")

    for idx, series in enumerate(y):
        plt.bar(np.arange(shape[1]) + idx/shape[0], list(series), yaxis=yaxis, label=label[idx],
                marker=marker[idx], color=color[idx], fill=fill, width=width/shape[0], orientation=orientation)

    plt.xticks(np.arange(shape[1]) + 1/2 - 1/(2 * shape[0]), x)

The cities bar example ends being:

cities = ["Tokyo", "Delhi", "Shanghai", "São Paulo",
          "Mexico City", "Cairo", "Mumbai", "Beijing"]
population = [37400068, 28514000, 25582000,
              21650000, 21581000, 20076000, 19980000, 19618000]
dogs = [3740006, 2851400, 2558200, 4165000, 3158100, 2007600, 1998000, 1961800]

plt.plotsize(100, 40)
plt.title("Bar Plot of the World Largest Cities")
plt.xlabel("City")
plt.ylabel("Population")

ParBar(cities, [population, dogs], width=.5)

multiple

For stacked bars:

def StackedBar(*args,
               yaxis="left",
               label="",
               marker="small",
               color=None,
               fill=True,
               width=4 / 5,
               orientation='vertical'):

    if len(args) == 0:
        x, y = [], []
    elif len(args) == 1:
        y = np.array(args[0], dtype=float)
        x = list(range(y.shape[1]))
    else:
        x = args[0]
        y = np.array(args[1], dtype=float)

    final_series = np.zeros((y.shape))

    # enough colors for every graph
    if color is not None:
        if len(color) != len(y):
            raise ValueError(
                "If color parameters is given, one color for every series is mandatory")
    else:
        color = [None] * len(y)

    # or single marker (enough for color plots) or one for every series (for monochrome)
    if isinstance(marker, str):
        marker = [marker] * len(y)
    elif len(marker) != len(y):
        raise ValueError(
            "If more than one marker is given, one for every series is mandatory")

    # or single label (enough for color plots) or one for every series (for monochrome)
    if isinstance(label, str):
        label = [label] * len(y)
    elif len(label) != len(y):
        raise ValueError(
            "If more than one label is given, one for every series is mandatory")

    # Add height to previous one, with numpy simpler, but done iterating to avoid extra libraries
    for idx, series in enumerate(y):
        if idx > 0:
            final_series[idx] = series + final_series[idx-1]
        else:
            final_series[idx] = series

    # Must print in reverse, so that bigger stacks are printed first
    for idx, series in enumerate(final_series[::-1]):
        plt.bar(list(x), list(series), yaxis=yaxis,
                label=label[idx], marker=marker[idx], color=color[idx], fill=fill, width=width, orientation=orientation)

An example of the cities in stacked mode is:

cities = ["Tokyo", "Delhi", "Shanghai", "São Paulo",
          "Mexico City", "Cairo", "Mumbai", "Beijing"]
population = [37400068, 28514000, 25582000,
              21650000, 21581000, 20076000, 19980000, 19618000]
dogs = [3740006, 2851400, 2558200, 4165000, 3158100, 2007600, 1998000, 1961800]

plt.plotsize(100, 40)
plt.title("Bar Plot of the World Largest Cities")
plt.xlabel("City")
plt.ylabel("Population")

StackedBar(cities, [population, dogs] )

stacked

If you think it may be interesting to include this functions in your code, happy to help.

Contribution Request: Command Line Tool

Hi,
Thanks for this great tool. I think that plotext could shine even more by quickly plotting data from files and stdin. I wrote a small python script that allows me to plot from a pipe

$ ./process_data data.txt | plotext 1,3 # use first and third column
    ┌─────────────────────────────────────────────────────────────────────────────────────────┐
21.0┤                                                                                        ▝│
    │                                                                                         │
    │                                                                                         │
18.0┤                                                                                         │
    │                                                                                         │
    │                                                                                         │
15.0┤                                                                                         │
    │                                            ▖                                            │
    │                                                                                         │
11.0┤                                                                                         │
    │                                                                                         │
    │                     ▝                                                                   │
    │                                                                                         │
 8.0┤          ▗                                                                              │
    │                                                                                         │
    │                                                                                         │
 4.0┤    ▝                                                                                    │
    │                                                                                         │
    │  ▖                                                                                      │
   1┤▞                                                                                        │
    └┬─────────────────────┬─────────────────────┬─────────────────────┬─────────────────────┬┘
     1                    33.0                  64.0                  96.0                  128

@piccolomo, if you think this could be a good idea, I can provide a patch. If so, we should agree on the interface. I was thinking to ship an executable plotext that can quickly plot data from files and stdin like gnuplot does, but better :)

plotext data.txt --type scatter --columns 1,3 1,5
cat data.txt | plotext --pipe --type scatter --columns 1,3 1,5

Feature Request: Function That Outputs Plot String

Thanks for really interesting library.
(IMHO) it could be more useful for to get the acsii-strings that is about to displayed without displaying on Terminal-Emulators.
So, with that strings, one can printout the plot over the Serial-Ports (i.e. pyserial),
For example I have a need for live updating plot over UART for some real time application.

2 Feature Requests: Plot Extra Grid Lines and deal with 'None' Values in Data Plot

Hi,

The DateTime plot plot_date requires all values to be numeric (None/NaN/np.nan is not accepted), but it's useful to be able to display shorter lines that don't span the whole time frame, which requires a way to represent no data like None/NaN. What I'm trying to do is to add some arbitrary trend line/channel on a stock price series.
Can you support this?

Thanks!

Strange Numerical Ticks on x axis

I find it's very weired that the ticks of same value differs in the bar plot.
see 7.0-6.0, which is greater than 6.0-4.0 and 4.0-2.0
image

How is that happened?

Hist Plot Y Limits for Multiple Data Sets

First of all, your lib is awesome : )

As a side-project, I'm working on a multi-format plotting utility, and your lib was an obvious first choice for the text output.

It's possible that I'm doing something wrong, but ylim/xlim seems to be set by the last histogram plot, and not the highest. Both scatter and line plots work well.

Error in Bar Plot with Same Height Data

Minimal example included

plt.bar(['a', 'b', 'c'], [1,1,1])
plt.show()
Traceback (most recent call last):
  File "/home/coen/Documents/Macrohard/ProjectRatio/FramingSelection/venv/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3457, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-13-1eb00ff78cf2>", line 1, in <module>
    plt.show()
  File "/home/coen/Documents/Macrohard/ProjectRatio/FramingSelection/venv/lib/python3.9/site-packages/plotext/_figure.py", line 281, in show
    self.build()
  File "/home/coen/Documents/Macrohard/ProjectRatio/FramingSelection/venv/lib/python3.9/site-packages/plotext/_figure.py", line 266, in build
    self.subplot.get_absolute_ticks()
  File "/home/coen/Documents/Macrohard/ProjectRatio/FramingSelection/venv/lib/python3.9/site-packages/plotext/_subplot.py", line 271, in get_absolute_ticks
    self.rticks = [get_matrix_data(self.yticks[s], self.ylim[s], self.height_canvas) for s in range(2)]
  File "/home/coen/Documents/Macrohard/ProjectRatio/FramingSelection/venv/lib/python3.9/site-packages/plotext/_subplot.py", line 271, in <listcomp>
    self.rticks = [get_matrix_data(self.yticks[s], self.ylim[s], self.height_canvas) for s in range(2)]
  File "/home/coen/Documents/Macrohard/ProjectRatio/FramingSelection/venv/lib/python3.9/site-packages/plotext/_utility/plot.py", line 30, in get_matrix_data
    data = [round((el - lim[0]) / dz + 0.5, 1)   for el in data]
  File "/home/coen/Documents/Macrohard/ProjectRatio/FramingSelection/venv/lib/python3.9/site-packages/plotext/_utility/plot.py", line 30, in <listcomp>
    data = [round((el - lim[0]) / dz + 0.5, 1)   for el in data]
ZeroDivisionError: float division by zero

Plotting only Zeros

Hello,

I have an error with this code:

        x = list(np.arange(20, dtype=int))
        y = list(np.full(20, 0, dtype=int))

        plx.scatter(x, y, line=True, line_color='yellow', axes=True, ticks=True, equations=True)
        plx.show()

  File "/usr/local/lib/python3.6/dist-packages/plotext/plot.py", line 48, in show
    _set_grid()
  File "/usr/local/lib/python3.6/dist-packages/plotext/plot.py", line 322, in _set_grid
    _add_to_grid(*_get_line(_vars.x[s], _vars.y[s]), _vars.line_marker[s], _vars.line_color[s])
  File "/usr/local/lib/python3.6/dist-packages/plotext/plot.py", line 350, in _add_to_grid
    r = int((y[n] - _vars.ymin) / _vars.dy)
ValueError: cannot convert float NaN to integer

But this code works fine:

        x = list(np.arange(20, dtype=int))
        y = list(np.full(20, 1, dtype=int))

        plx.scatter(x, y, line=True, line_color='yellow', axes=True, ticks=True, equations=True)
        plx.show()

New Version Issue

Hi,
Using the latest version 2.2.2 with Streaming Data Example gives the following error:

AttributeError: 'function' object has no attribute 'scatter'

I can tell that the syntax has changed since.

What is the most optimised version to use this example?

Feature Request: Log Scale on Bar/Hist Plot

I'm getting the following error message.

Traceback (most recent call last):
  File "plot.py", line 10, in <module>
    plt.show()
  File "/usr/local/lib/python3.9/dist-packages/plotext/plot.py", line 420, in show
    _ylim_data(subplot)
  File "/usr/local/lib/python3.9/dist-packages/plotext/plot.py", line 540, in _ylim_data
    y_left = [_utility.log(subplot.y_left[s]) if subplot.yscale[0] == "log" else subplot.y_left[s] for s in range(subplot.signals_left)]
  File "/usr/local/lib/python3.9/dist-packages/plotext/plot.py", line 540, in <listcomp>
    y_left = [_utility.log(subplot.y_left[s]) if subplot.yscale[0] == "log" else subplot.y_left[s] for s in range(subplot.signals_left)]
  File "/usr/local/lib/python3.9/dist-packages/plotext/utility.py", line 283, in log
    return [math.log10(el) for el in data]
  File "/usr/local/lib/python3.9/dist-packages/plotext/utility.py", line 283, in <listcomp>
    return [math.log10(el) for el in data]
ValueError: math domain error

Here is my version of python and plotext.

Python 3.9.5 (default, May 11 2021, 08:20:37) 
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import plotext
>>> plotext.__version__
'3.1.3'
>>> 

Here is the code to reproduce.

import plotext as plt

dates = ('2021-06-21', '2021-06-22', '2021-06-23', '2021-06-24', '2021-06-25', '2021-06-26')
counts = (2910, 3326, 19308, 126939, 475620, 226890)

plt.bar(dates, counts)
plt.plotsize(100, 30)
plt.yscale("log")
plt.show()

Googling suggests that math domain error with a log means the value is 0 or negative. None of my original values are 0 or negative. But what's strange is that if I print out the value of data in the plotext/utility.py:log(data) function I get [2910, 2910, 0, 0]. 2910 is my first y value, but I don't know what's going on with the rest.

Am I doing something wrong with how I'm using the library? Linear bar plots seem to work fine for me.

Improper Axes Numerical Ticks

Hi,

maybe I missunderstood the manual, but I expect a plot from x = 1 to 10 and values y from 1 to 100.

import plotext as plx

x=[1,2,3,4,5,6,7,8,9,10]
y=[i**2 for i in x]
plx.scatter(x,y)
plx.show()

however I get a plot like the this one.

                                                                                                                    •├45
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     ├40
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                                                                       •             │  
                                                                                                                     ├35
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     ├30
                                                                                          •                          │  
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     ├25
                                                                                                                     │  
                                                                                                                     │  
                                                                             •                                       │  
                                                                                                                     │  
                                                                                                                     ├20
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                                •                                                    │  
                                                                                                                     ├15
                                                                                                                     │  
                                                                                                                     │  
                                                                                                                     │  
                                                    •                                                                │  
                                                                                                                     ├10
                                                                                                                     │  
                                                                                                                     │  
                                       •                                                                             │  
                                                                                                                     │  
                                                                                                                     ├5 
                          •                                                                                          │  
                                                                                                                     │  
                                                                                                                     │  
             •                                                                                                       │  
•                                                                                                                    ├0 
┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬──────┘  
0         10        20        30        40        50        60        70        80        90        100       110       

The (x,y)-pairs are not matching with the labels on the axes.

What I'm doing wrong?

>>> plx.__version__
'1.0.11'
>>> sys.version
'3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]'

Bye, Uwe

Feature Request: Bar Plot

This library looks great, and I'm starting to use it in my project.

As well as doing line plots, I was hoping to do horizontal bar charts that look a bit like the following (although ideally with axis ticks and so on as well):

Foo  #########
Bar  ####
Baz  ###########

I was hoping this would be a fairly simple modification of the existing hist command (as this is basically a simplified version of a histogram), but it looks like it's more complicated than that, as we need separate labels for each of the categories. I've also had an issue running the hist example code (see #15).

Also, is the code available fully in the Github repository? When I clone the repository, the plotext folder seems to be a submodule, but I can't seem to retrieve the contents of the submodule. Could you let me know what git commands I need to run to get hold of the full code? (At the moment, I'm browsing the code in the folder that pip installed it to, which is not ideal). I've got a small PR I'd like to submit, but I can't work out how to submit it if I can't get full access to the code in Git.

Terminal Size Error

I ran into the exact same issue described in this question. TL;DR - when running this library in PyCharm, the error in the subject is thrown by utility.py>terminal_size()>os.get_terminal_size().

One of the fixes proposed in the Q&A worked for me, so I suggest replacing

-return list(os.get_terminal_size())
+return shutil.get_terminal_size(fallback=(120, 50))

Or if you want to keep the existing code and provide a fallback,

-def terminal_size():
-    return list(os.get_terminal_size())
+import shutil
+ ...
+def terminal_size():
+    try:
+        return list(os.get_terminal_size())
+    except OSError:
+        return shutil.get_terminal_size(fallback=(120, 50))

Thanks!

P.S. I'm using Python 3.6 on Ubuntu 16.04 with PyCharm 2021.2.

Feature Request: Histogram Plot

Super cool package! Love the features. 😀

I was wondering if it was possible to add a way of creating histograms with this package. 📈
It would be super handy if the structure followed that of matplotlib just like your other functions does. 👨‍💻

High Resolution Marker Not Working on MacOS?

My plots are all showing up with s's on macOS rather than the small character, which I'm sure the terminal supprorts. I'm not sure why, looking into the code, as the platform should be set to "linux" as far as I can tell. However, I noticed a few things that made it hard to parse and debug the code:

  • The platform should be called "unix", not "linux", if it encompasses both (it should)
  • There should not be a function called "plot" and a module called "plot" at the same level. It's painfully hard to debug and access the module called "plot" because of the function. Could you rename the module to _plot, for example?
  • import * should be avoided in a library. You only have one, so that's not too bad; but two or more make it really hard to track things down.
  • The path manipulation in init.py is unnessisary.
  • Never, never tell anyone to sudo pip (in the readme). Recent versions of pip will install into the user location if the system location is not writable (but, hopefully, all users will be in virtual environments). Pip literally prints a warning if it can detect you are running it with sudo, because it will break your system. Could you touch up the README suggestion?
  • There are no git tags. I can't tell what's in the latest release, and what's been added since then.
  • Couldn't you tests check the output? That would be really helpful in GHA, where you can run the tests with
  • By avoiding NumPy, the histogram function (for example) is painfully slower than it needs to be. Couldn't that be a minimal requirement? If not, then maybe try to import it, and only use a faster implementation if it's available?
  • The histogram function could default to making a number of bins equal to the available width, which would be really nice, I think (or 2x the available width in small mode).

Hopefully these points are helpful. :) You might find the guide here https://scikit-hep.org/developer helpful for PyTest and nice packaging / checks. Anyway, the main problem is my "small" marker plots have only s's.

Plot Changes with Consecutive Runs of Show()

I found a strange bug, that when you run plx.show() multiple times,
the view is changed and not plotted the same each time.

I tried following scenario:

plx.scatter([10,2,3,5,2,1,5,13,4,2,5,3,2,1,5,6,17,12,15,4,5,4,3,2,5,6,9,8,12,18,5,3,2],rows=10,cols=25,point_color="red",equations=True)
plx.show()
plx.show()
plx.show()

I get:


                      •  │
            •            │
              •          │
     •       •       •   │
•                        ├5
                    •    │
           •       •     │
  •  •• •  •  ••• •    • │
 •••   •••       •     ••│
    •     •              ├0
┬─────────┬─────────┬────┘
0         10        20
x = 1.33 × col - -0.00 ± 0.67
y = 1.89 × row + 1.00 ± 0.94

                     •   │
            •            │
             •           │
      •      •       •   │
•                        ├5
                   ••    │
           •      •      │
   • •• •  •  ••• •   •  │
 •••   •••      ••     ••│
    •     •              ├0
┬─────────┬─────────┬────┘
0         10        20
x = 1.39 × col - -0.67 ± 0.69
y = 2.10 × row + 0.06 ± 1.05

                         │
            •        •   │
             •           │
      •      •      •    │
 •                       ├5
                   ••    │
   • •  •  •   •  •   •  │
  •   •  •    •••     •  │
  • •  • ••      •     • │
                         ├0
┬─────────┬─────────┬────┘
0         10        20
x = 1.45 × col - -1.36 ± 0.72
y = 2.33 × row - -0.99 ± 1.17

If I continue it eventually looks like:

                         │
                         │
                         │
                         │
           •••           ├5
           •••           │
                         │
                         │
                         │
                         ├0
┬─────────┬─────────┬────┘
0         10        20
x =  13.66 × col -  -147.93 ±   6.83
y = 766.27 × row - -3438.73 ± 383.14

I also tried different configurations (no rows and cols, no equations, no color)
everytime it is the same... something is changed if you call show() again.

Strange Characters in Jupyterlab

Little bug I found here ... I am using Jupyterlab on Ubuntu 20.04 and I was getting the wide unicode block characters from a plot. I tried several different markers, (fhd, hd, dot, etc) and ended up with artifacts from previous markers on my plots. I eventually realized that this is because Jupyterlab is keeping the session open between the tests I was running and if I reset the python engine the artifact characters go away. Here is an example output having previously run the plot with fhd then hd:

Screenshot from 2022-01-04 07-23-50

Thanks for a great tool! :)

Incompatibility with the Dash Plugin of Pytest

First of all, thank you very much for the package!

I've found a little issue: if I try to use the dash package and plotext at the same time, I get import errors when I execute pytest. I think it is related to this problem with the dash plugin for pytest.

A straightforward solution is deleting this line from init.py: it's an import of the test file that is not used later, but causes the problem with pytest.

In addition to that, maybe the name of the file test.py should be changed so that it doesn't name-shadows a standard library name, which in this case is the internal package test.

Feature Request: 2 x 3 Mosaics Markers for Higher Definition Plots

Unicode version 13 introduced many glyphs used in older computers and terminals. Among those are the 2x3 mosaics used in Teletext terminals and the TRS-80 computers. Their use would represent a 50% increase of vertical resolution on terminals that support the character set.

Plotting only Zeros

There is another problem, if i want to plot a datastream that only contains zeros it throws an exception and not plotting anything.

I tried this:

plx.scatter([0,0,0])
plx.show()

and got this:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python37\lib\site-packages\plotext\plot.py", line 48, in show
    _set_grid()
  File "C:\Program Files\Python37\lib\site-packages\plotext\plot.py", line 324, in _set_grid
    _add_to_grid(_vars.x[s], _vars.y[s], _vars.point_marker[s], _vars.point_color[s])
  File "C:\Program Files\Python37\lib\site-packages\plotext\plot.py", line 350, in _add_to_grid
    r = int((y[n] - _vars.ymin) / _vars.dy)
ZeroDivisionError: float division by zero

If I set the ylim to something this issue does not occur.

Legend Missing in Bar Plots if First Bar is 0

If the first data element in the list is 0, the Legend does not display the associated color.

>>> import plotext as plt
>>> dates = ['2022-01-01', '2022-01-02', '2022-01-03']
>>> dayc = [0, 1, 0]
>>> plt.bar(dates, dayc, label="Day")
>>> plt.plotsize(180, 40)
>>> plt.show()

image

Same for a stacked_bar:

import plotext as plt
dayc = [0, 1, 0]
nightc = [1, 0, 0]
dates = ['2022-01-01', '2022-01-02', '2022-01-03']
plt.stacked_bar(dates, [dayc, nightc], label=["Day", "Night"])
plt.plotsize(180, 40)
plt.show()
image

Streaming Flickering

I tried to code up an example with streaming data but it flickers quite poorly. Am I doing something wrong?

import plotext.plot as plx
import numpy as np

pi = np.pi
x = np.linspace(0, 2*pi, 50)
y = np.sin(x)
t = np.linspace(0, 2, 50)

plx.clear_terminal()
plx.scatter(x,y,point_color="red", point_marker="o")
plx.set_cols(100)
plx.set_rows(100)
plx.set_ylim([-1.1,1.1])
plx.set_xlim([0,2*pi])
plx.set_axes_color("green")
plx.set_background("black")
plx.set_spacing([5,8])
plx.show()

for tt in t:
        plx.clear_plot()
        plx.clear_terminal()
        y = np.sin(x-tt)
        plx.scatter(x,y)
        plx.show()
        plx.sleep(0.1)


Packages Dependencies Missing in Version 4.0.0

When trying to execute the command line example (or any other code that worked in previous version) the following error appears:

python3 -c "import plotext as plt; y=plt.sin(); plt.clp(); plt.scatter(y); plt.title('Scatter Plot'); plt.show();"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/tmp/plotext/.venv/lib/python3.8/site-packages/plotext/__init__.py", line 3, in <module>
    from plotext._core import *
  File "/tmp/plotext/.venv/lib/python3.8/site-packages/plotext/_core.py", line 14, in <module>
    from plotext._figure import figure_class as _figure_class
  File "/tmp/plotext/.venv/lib/python3.8/site-packages/plotext/_figure.py", line 9, in <module>
    from plotext._subplot import subplot_class
  File "/tmp/plotext/.venv/lib/python3.8/site-packages/plotext/_subplot.py", line 7, in <module>
    from plotext._utility.image import *
  File "/tmp/plotext/.venv/lib/python3.8/site-packages/plotext/_utility/image.py", line 2, in <module>
    from PIL.Image import fromarray
ModuleNotFoundError: No module named 'PIL'

It also happens with Python 3.9.

Feature Request: Force Plot Size + Tkinter Integration

First, I love the program!

I have been able to use plotext to plot to a tkinter text widget. It works well, but is totally dependent on the terminal size that the user happens to be using at runtime.

Would it be possible to add a flag to ignore the actual terminal size and force it to, let's say 80x24, so that when the plot is generated (hidden and saved to file) can be sent directly to the tkinter text widget?

Thank you in advance for your consideration.
Greg

Feature Request: Exceptions when Subplot Matrix is Bigger then Default

I was confused by a strange index out of bound error

  File "xxxxx/terminal-plot/lib/python3.9/site-packages/plotext/_figure.py", line 55, in set_subplot
    self.subplot = self.subplots[self.row][self.col]
IndexError: list index out of range

which, after some extensive investigation I realise it's due to

rows = rows if rows < self.default.rows_max else self.default.rows_max

and the defaults is defined in

self.cols_max = 10 # max number of subplots columns and rows


I don't oppose sane defaults (it should probably be configurable). However, this override is undetectable from user code as it is enforced in figure creation without any notice. In my opinion, it might be better off throw an exception instead of silently overrides the subplot size...

Feature Request: Stem Plot

Hey there!

I'd like to simulate a stem plot. For that I think the easiest way might be using a regular scatter plot in combination with multiple vertical lines. However, I'm not sure how to draw those straight lines. Any ideas?

PS: This is really an awesome project. Keep it up!

Histogram Rendering on Mac OS

This looks a very cool library! While testing histogramming I get this output from the example script
(on my mac terminal)
Screenshot 2021-03-28 at 23 59 35

Screenshot 2021-03-29 at 00 03 51

any ideas of why is that?

I ask because some time ago I implemented something similar for vedo and it has the same problem:

from vedo import printHistogram
import numpy as np
d = np.random.normal(size=1000)
printHistogram(d, c='lb', logscale=True, title='my scalars')
printHistogram(d, c='red', horizontal=1)

Screenshot 2021-03-29 at 00 19 22

it would be nice to ditch my old implementation in favour of plotext.

Not Working in Windows Powershell

I tried this with python(3) running in a windows PowerShell terminal.

It just produces a lot of strange control characters and beeping (probably the line-end bell) for a while and then stops.

I assume it's not compatible with this type of output terminal.
Might be worth a warning in the documentation/readme.

Or did I do something wrong?

Test was:

import plotext as plx
y = [1, 2, 3, 4, 5]
plx.plot(y)
plx.show()

Windows 7
Python 3.8.8 (installed via WinPython)
plotext 2.3.1 (installed via pip)

Single Bar Plot: division by zero error (also in Pull 43)

Miminal example:

plt.bar(["a"],[1])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jfrejlac/school/PDI/project/venv/lib64/python3.9/site-packages/plotext/_core.py", line 197, in bar
    figure.subplot.draw_single_bar(x, y,
  File "/home/jfrejlac/school/PDI/project/venv/lib64/python3.9/site-packages/plotext/_subplot.py", line 429, in draw_single_bar
    xbar, ybar = bars(x, y, width, self.bar_ylim[0])
  File "/home/jfrejlac/school/PDI/project/venv/lib64/python3.9/site-packages/plotext/_utility/bar.py", line 54, in bars
    bin_size_half = (max(x) - min(x)) / (bins - 1) * width / 2
ZeroDivisionError: division by zero

0 Bar Height Error

This works as expected (all x values are show even if the y-value is 0):

python3 -c "import plotext as plt; plt.bar([1,2,3],[1,0,1]); plt.show()"

If there is a 0 value at the beginning of the array it causes IndexError:

python3 -c "import plotext as plt; plt.bar([1,2,3],[0,1,1]); plt.show()"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.9/dist-packages/plotext/plot.py", line 954, in bar
    _fig.subplot.point_color[-1] = _fig.subplot.point_color[-2]
IndexError: list index out of range

If there is a 0 value at the end of the array it is not shown in the bar chart:

python3 -c "import plotext as plt; plt.bar([1,2,3],[1,1,0]); plt.show()"

colorless() not Working when Streaming

a quick test for continuous updates below.

i must remove the comment in the for loop to allow the plot to remain colorless, following the "Streaming Data" example.

plt.xlabel("Samples")
plt.ylabel("Value")
plt.xlim(0,256)
plt.colorless()
frameno = ctypes.c_int32()

for n in range(0,100):	
	sslib.GetSnapshot(0,0, ctypes.byref(frameno), char_array.from_buffer(plotData), len(plotData))
	plotData = numpy.frombuffer(plotData, dtype=numpy.short)
	plt.cld()
	plt.clt()
	plt.title(f"{frameno}")
	plt.plot(plotData, marker="dot")	
	#plt.colorless()
	plt.show()

Error in Bar Plots with 0 Height Data

Sometimes, the data returned from the server has '0' for all day and night counts. When plotting, this results in a ZeroDi
visionError exception:

>>> import plotext as plt
>>> dates = ['2022-01-01', '2022-01-02', '2022-01-03']
>>> dayc = [0, 0, 0]
>>> nightc = [0, 0, 0]
>>> plt.bar(dates, dayc)
>>> plt.show()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_figure.py", line 285, in show
    self.build()
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_figure.py", line 269, in build
    self.subplot.get_relative_ticks()
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_subplot.py", line 285, in get_relative_ticks
    self.rticks = self._get_relative_ticks(self.yticks, self.ylim, self.height_canvas)
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_subplot.py", line 291, in _get_relative_ticks
    ticks = [get_matrix_data(ticks[s], lim[s], bins) for s in range(2)]
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_subplot.py", line 291, in <listcomp>
    ticks = [get_matrix_data(ticks[s], lim[s], bins) for s in range(2)]
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_utility/plot.py", line 29, in get_matrix_data
    data = [round((el - lim[0]) / dz + 0.5, 1) for el in data] if lim[0] != None else [None] * len(data)
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_utility/plot.py", line 29, in <listcomp>
    data = [round((el - lim[0]) / dz + 0.5, 1) for el in data] if lim[0] != None else [None] * len(data)
ZeroDivisionError: float division by zero

>>> plt.stacked_bar(dates, [dayc, nightc])
>>> plt.show()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_figure.py", line 285, in show
    self.build()
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_figure.py", line 269, in build
    self.subplot.get_relative_ticks()
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_subplot.py", line 285, in get_relative_ticks
    self.rticks = self._get_relative_ticks(self.yticks, self.ylim, self.height_canvas)
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_subplot.py", line 291, in _get_relative_ticks
    ticks = [get_matrix_data(ticks[s], lim[s], bins) for s in range(2)]
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_subplot.py", line 291, in <listcomp>
    ticks = [get_matrix_data(ticks[s], lim[s], bins) for s in range(2)]
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_utility/plot.py", line 29, in get_matrix_data
    data = [round((el - lim[0]) / dz + 0.5, 1) for el in data] if lim[0] != None else [None] * len(data)
  File "/Users/barbe/Projects/installer_tools/.venv/lib/python3.9/site-packages/plotext/_utility/plot.py", line 29, in <listcomp>
    data = [round((el - lim[0]) / dz + 0.5, 1) for el in data] if lim[0] != None else [None] * len(data)
ZeroDivisionError: float division by zero

Misspelling Issue: "returnsa"

@piccolomo hey there. I am using your library in my project over at: https://github.com/cjmcgraw/docker-load-graph

Now there is clearly a problem on initial pip install. Specifically check out the following:

image

The first command shows my application throwing an exception for python3.8 at line 765.

The second command shows I am using version 3.1.3 of plotext (the most recent/current)

The third command, show sme catting the file that throwed the exception, and grepping around the lines.

Clearly there is a distinct typo returnsa instead of return there.

However in the current library I do not see that typo and thus don't have any immediate way of fixing this issue.

Could you please push the most recent changes you have in master to your release?

Hist Plot not Working

I've been trying to run the example code provided in the README for the hist function:

import plotext as plt
import random
data = [random.gauss(0, 1) for el in range(50000)]
data2 = [random.gauss(3, 1) for el in range(50000)]
plt.clp()
bins = 60
plt.hist(data, bins, label="mean 0")
plt.hist(data2, bins, label="mean 3")
plt.title("Histogram plot")
plt.xlabel("data bin")
plt.ylabel("frequency")
plt.figsize(100, 30)
plt.show()

I get the following error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-e704a9ff5ccd> in <module>
     11 plt.ylabel("frequency")
     12 plt.figsize(100, 30)
---> 13 plt.show()

~/anaconda3/envs/pepys_py38/lib/python3.8/site-packages/plotext/plot.py in show()
    335     _size_max()
    336 
--> 337     _height_min()
    338     _height()
    339 

~/anaconda3/envs/pepys_py38/lib/python3.8/site-packages/plotext/plot.py in _height_min()
    372 def _height_min():
    373     par.height_title = int(par.title != "")
--> 374     par.height_xaxis = int(par.axes[0] or par.frame)
    375     par.height_xticks = bool(par.ticks[0])
    376     par.height_labels = int(par.xlabel != "" or par.ylabel != "")

TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'

It seems like par.axes[0] or par.frame aren't initialised properly? Do you have any idea how to fix this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.