Skip to content

Latest commit

 

History

History
281 lines (220 loc) · 10 KB

environments.md

File metadata and controls

281 lines (220 loc) · 10 KB

Environments

Main Guide

Matplotlib

To automatically transform a matplotlib plot into a plotext one use the function from_matplotlib(). Here is an example:

import matplotlib.pyplot as plt
import plotext as plx

y = plx.sin(); ym = [-el for el in y]
x = range(len(y))

plt.clf()
plt.subplot(211)
plt.plot(x, y, color = 'red')
plt.title('Some Smart Title')
plt.xlabel('here is a label')


plt.subplot(212)
plt.plot(x, ym, color = 'green')
plt.ylabel('the y axis')

plt.show(block = 0)

fig = plt.gcf()

plx.from_matplotlib(fig)
plx.show()

matplotlib

These feature is under development: please report any bug or development idea.

Main Guide, Environments

Rich

The integration with the package rich has been discussed in issue 26 and issue 27. Thanks to the kind help of its creator @willmcgugan, as well as the user @whisller, it seems that the following code could be a good working template:

from rich.layout import Layout
from rich.live import Live
from rich.ansi import AnsiDecoder
from rich.console import Group
from rich.jupyter import JupyterMixin
from rich.panel import Panel
from rich.text import Text

from time import sleep
import plotext as plt

def make_plot(width, height, phase = 0, title = ""):
    plt.clf()
    l, frames = 1000, 30
    x = range(1, l + 1)
    y = plt.sin(periods = 2, length = l, phase = 2 * phase  / frames)
    plt.scatter(x, y, marker = "fhd")
    plt.plotsize(width, height)
    plt.xaxes(1, 0)
    plt.yaxes(1, 0)
    plt.title(title)
    plt.theme('dark')
    plt.ylim(-1, 1)
    #plt.cls()
    return plt.build()

class plotextMixin(JupyterMixin):
    def __init__(self, phase = 0, title = ""):
        self.decoder = AnsiDecoder()
        self.phase = phase
        self.title = title

    def __rich_console__(self, console, options):
        self.width = options.max_width or console.width
        self.height = options.height or console.height
        canvas = make_plot(self.width, self.height, self.phase, self.title)
        self.rich_canvas = Group(*self.decoder.decode(canvas))
        yield self.rich_canvas

def make_layout():
    layout = Layout(name="root")
    layout.split(
        Layout(name="header", size=1),
        Layout(name="main", ratio=1),
    )
    layout["main"].split_column(
        Layout(name="static", ratio = 1),
        Layout(name="dynamic"),
    )
    return layout

layout = make_layout()

header = layout['header']
title = plt.colorize("Pl✺ text ", "cyan+", "bold") + "integration with " + plt.colorize("rich_", style = "dim")
header.update(Text(title, justify = "left"))

static = layout["static"]
phase = 0
mixin_static = Panel(plotextMixin(title = "Static Plot"))
static.update(mixin_static)

dynamic = layout["dynamic"]

with Live(layout, refresh_per_second=0.0001) as live:
    while True:
        phase += 1
        mixin_dynamic = Panel(plotextMixin(phase, "Dynamic Plot")) 
        dynamic.update(mixin_dynamic)
        #sleep(0.001)
        live.refresh()

rich

Main Guide, Environments

Tkinter

The integration with the package tkinter has been discussed in Issue 33. Thanks to the great inputs from user @gregwa1953, here is an initial take on it, where a test image is downloaded in the home folder, visualized and finally removed:

import tkinter as tk
import plotext as plt
from plotext._utility import to_rgb, uncolorize
import tkinter.font as tkfont

image_path = 'cat.jpg'

#font_name = "SourceCodePro" # this results in wrong plot dimensioms
#font_name = "MonoSpace"
font_name = "UbuntuMono"
font_size = 13 # font size of application labels
font_size_plot = 25 # font size of plot

font = font_name + " " + str(font_size)
stick_horizontal = tk.W + tk.E
stick_all = tk.E + tk.W + tk.N + tk.S
padx, pady = 2, 2
frame_color = "gray85"
nocommand = lambda: int

def frame(parent, row = 0, col = 0, stick = stick_horizontal):
     frame = tk.Frame(parent, background = frame_color, relief = 'groove', bd = 0)
     frame.config(highlightthickness = 0, highlightbackground = frame_color)
     frame.grid(row = row, column = col, sticky = stick, padx = padx, pady = pady)
     return frame

def button(parent, label = "button", row = 0, col = 0, command = nocommand):
     button = tk.Button(parent, text = label, font = font, command = command, relief = "raised", state = "normal", background = frame_color)
     button.grid(row = row, column = col, padx = padx, pady = pady)
     return button

def text(parent, width, height, font = None):
    text = tk.Text(parent, font = font, width = width, height = height, wrap = tk.NONE)
    text.grid(row = 0, column = 0, stick = stick_all)
    return text

def scale(parent, row = 0 , col = 0):
     scale = tk.Scale(parent, from_= 2, to = 30, orient = tk.HORIZONTAL, font = font, length = 300)
     scale.set(font_size_plot)
     scale.grid(row = row, column = col, padx = padx, pady = pady)
     return scale

def from_rgb(rgb): # translates an rgb tuple of int to a tkinter friendly color code
    return "#%02x%02x%02x" % rgb
    #r, g, b = rgb
    #return f'#{r:02x}{g:02x}{b:02x}'

class window():
     def __init__(self):
          self.root = tk.Tk()
          self.root.resizable(True, True)
          self.root.title("Plotext in Tkinter")
          self.root.option_add('*Font', font)
          self.root.geometry('%dx%d+0+0' % (self.root.winfo_screenwidth(), self.root.winfo_screenheight()))
          #self.root.geometry('%dx%d+0+0' % (300, 300))
          self.root.columnconfigure(0, weight = 1)
          self.root.rowconfigure(1, weight = 1)

          self.upper_frame = frame(self.root, row = 0)
          self.lower_frame = frame(self.root, row = 1, stick = stick_all)

          self.plot_button = button(self.upper_frame, label = "Plot ", command = self.plot_command, col = 0)
          self.scale = scale(self.upper_frame, col = 1)
          self.save_button = button(self.upper_frame, label = "Save", command = self.save_command, col = 2)
          self.close_button = button(self.upper_frame, label = "Close", command = self.close_command, col = 3)

          self.clear_command()
          self.root.mainloop()

     def clear_command(self):
          for widgets in self.lower_frame.winfo_children():
               widgets.destroy()

     def save_command(self):
          plt.savefig("plot.html")

     def close_command(self):
          self.root.destroy()

     def plot_command(self):
          self.plot_button.config(state = "disabled", relief = "sunken")
          self.scale.config(state = "disabled")
          self.clear_command()
          self.get_plot_size()

          self.plotext_command()
          self.add_plot()
          self.add_colors()

          self.plot_button.config(state = "normal", relief = "raised")
          self.scale.config(state = "normal")

     def get_plot_size(self):
          self.root.update()
          size = self.lower_frame.winfo_width(), self.lower_frame.winfo_height()
          font_size = self.scale.get()
          self.font_plot = tkfont.Font(family = font_name, size = font_size)
          font_size = self.font_plot.measure('m'), self.font_plot.metrics('linespace') # in pixels
          size = [size[i] / font_size[i] for i in range(2)]
          size = list(map(int, size))
          self.cols, self.rows = self.size = size

     def plotext_command(self):
          plt.clf()
          plt.limitsize(False, False)
          plt.plotsize(*self.size)
          plt.image_plot(image_path, fast = False)
          plt.frame(False)
          plt.build()
          #plt.show()

     def add_plot(self):
          # Add Colorless Plot 
          #self.rows, self.cols = plt.figure.monitor.matrix.size
          #plt.figure.monitor.matrix.update_size()
          self.plot_text = text(self.lower_frame, self.cols, self.rows, font = self.font_plot)         
          self.canvas = plt._global.figure.monitor.matrix.canvas
          self.canvas = uncolorize(self.canvas)
          self.plot_text.insert("end", self.canvas)
          self.plot_text.update()

     def add_colors(self): # Add Colors to Plot
          self.color = plt._global.figure.monitor.matrix.fullground[::-1]
          self.background = plt._global.figure.monitor.matrix.background[::-1]
          tag = lambda r, c: str(r) + "*" + str(c)
          coord = lambda r, c: str(r + 1) + "." + str(c)
          for r in range(self.rows):
               for c in range(self.cols):
                    fg = from_rgb(to_rgb(self.color[r][c]))
                    bg = from_rgb(to_rgb(self.background[r][c]))
                    self.plot_text.tag_add(tag(r, c), coord(r, c))
                    self.plot_text.tag_config(tag(r, c), foreground = fg, background = bg)
               self.plot_text.update()
          self.plot_text.update()

if __name__ == '__main__':        
     plt.download(plt.test_image_url, image_path)
     gui = window()
     plt.delete_file(image_path)

which outputs:

tkinter

  • Using the scale slider one can change the font size; lower font size makes the final plot bigger, which requires more computational time.

  • The Save button saves the plots as an html file in the user home folder.

Main Guide, Environments