https://github.com/JuliaPlots/UnicodePlots.jl

Skip to content Toggle navigation
 
Sign up

  * Product
      +  
        Actions
        Automate any workflow
      +  
        Packages
        Host and manage packages
      +  
        Security
        Find and fix vulnerabilities
      +  
        Codespaces
        Instant dev environments
      +  
        Copilot
        Write better code with AI
      +  
        Code review
        Manage code changes
      +  
        Issues
        Plan and track work
      +  
        Discussions
        Collaborate outside of code
      + Explore
      + All features
      + Documentation
      + GitHub Skills
      + Blog
  * Solutions
      + For
      + Enterprise
      + Teams
      + Startups
      + Education
      + By Solution
      + CI/CD & Automation
      + DevOps
      + DevSecOps
      + Case Studies
      + Customer Stories
      + Resources
  * Open Source
      +  
        GitHub Sponsors
        Fund open source developers
      +  
        The ReadME Project
        GitHub community articles
      + Repositories
      + Topics
      + Trending
      + Collections
  * Pricing

[                    ] 

  *  
    #
    In this repository All GitHub |
    Jump to |

  * No suggested jump to results

  *  
    #
    In this repository All GitHub |
    Jump to |
  *  
    #
    In this organization All GitHub |
    Jump to |
  *  
    #
    In this repository All GitHub |
    Jump to |

Sign in
Sign up
{{ message }}
JuliaPlots / UnicodePlots.jl Public

  * Notifications
  * Fork 68
  * Star 1.1k

Unicode-based scientific plotting for working in the terminal

License

View license
1.1k stars 68 forks
Star
Notifications

  * Code
  * Issues 9
  * Pull requests 2
  * Actions
  * Projects 0
  * Wiki
  * Security
  * Insights

More

  * Code
  * Issues
  * Pull requests
  * Actions
  * Projects
  * Wiki
  * Security
  * Insights

JuliaPlots/UnicodePlots.jl

This commit does not belong to any branch on this repository, and may
belong to a fork outside of the repository.
master
Switch branches/tags
[                    ]
Branches Tags
Could not load branches
Nothing to show
{{ refName }} default View all branches
Could not load tags
Nothing to show
{{ refName }} default
View all tags

Name already in use

A tag already exists with the provided branch name. Many Git commands
accept both tag and branch names, so creating this branch may cause
unexpected behavior. Are you sure you want to create this branch?
Cancel Create
2 branches 85 tags
Code

  * Local
  * Codespaces

  *  
    Clone
    HTTPS GitHub CLI
    [https://github.com/J]

    Use Git or checkout with SVN using the web URL.

    [gh repo clone JuliaP]

    Work fast with our official CLI. Learn more.

  * Open with GitHub Desktop
  * Download ZIP

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

@t-bltg
t-bltg 3.5.0 [skip ci]
...
d37616c Apr 9, 2023
3.5.0 [skip ci]
d37616c

Git stats

  * 603 commits

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
.github/workflows
conditionally require FreeType, FileIO, Unitful and `ImageInTer...
February 8, 2023 17:43
.vscode
force auto formatting for vscode (#261)
May 25, 2022 05:22
docs
swap Function order (#345)
April 9, 2023 18:55
ext
swap Function order (#345)
April 9, 2023 18:55
src
swap Function order (#345)
April 9, 2023 18:55
test
swap Function order (#345)
April 9, 2023 18:55
.JuliaFormatter.toml
fmt: add long_to_short_function_def
September 7, 2022 14:44
.gitignore
force auto formatting for vscode (#261)
May 25, 2022 05:22
CHANGELOG.md
swap Function order (#345)
April 9, 2023 18:55
LICENSE.md
update copyright in license
February 17, 2016 16:01
Project.toml
3.5.0 [skip ci]
April 9, 2023 18:56
README.md
swap Function order (#345)
April 9, 2023 18:55
View code
[                    ]
UnicodePlots High-level Interface Documentation Installation Saving
figures Color mode 3D plots Layout Known issues Methods (API)
Keywords description (API) Low-level interface Developer notes
Invalidations check Documentation update License Acknowledgement

README.md

 UnicodePlots

License PkgEval CI Coverage Status JuliaHub deps UnicodePlots
Downloads

Advanced Unicode plotting library designed for use in Julia's REPL.

[banner]

 High-level Interface

Here is a list of the main high-level functions for common scenarios:

  * scatterplot (Scatter Plot)
  * lineplot (Line Plot)
  * stairs (Staircase Plot)
  * barplot (Bar Plot - horizontal)
  * histogram (Histogram - horizontal / vertical)
  * boxplot (Box Plot - horizontal)
  * spy (Sparsity Pattern)
  * densityplot (Density Plot)
  * contourplot (Contour Plot)
  * polarplot (Polar Plot)
  * heatmap (Heatmap Plot)
  * imageplot (Image Plot)
  * surfaceplot (Surface Plot - 3D)
  * isosurface (Isosurface Plot - 3D)

Introduction

Here is a quick hello world example of a typical use-case:

using UnicodePlots
lineplot([-1, 2, 3, 7], [-1, 2, 9, 4], title="Example", name="my line", xlabel="x", ylabel="y")

[lineplot1]

There are other types of Canvas available (see section Low-level
Interface).

In some situations, such as printing to a file, using AsciiCanvas,
DotCanvas or BlockCanvas might lead to better results:

plt = lineplot([-1, 2, 3, 7], [-1, 2, 9, 4], title="Example", name="my line",
               xlabel="x", ylabel="y", canvas=DotCanvas, border=:ascii)

[lineplot2]

Some plot methods have a mutating variant that ends with an
exclamation mark:

lineplot!(plt, [0, 4, 8], [10, 1, 10], color=:cyan, name="other line")

[lineplot3]

Physical quantities of Unitful.jl are supported on a subset of
plotting methods (supported through package extensions - weak
dependencies.

One can adjust the plot height and width to the current terminal size
by using height=:auto and/or width=:auto.

You can reverse/flip the Plot axes by setting xflip=true and/or yflip
=true on plot creation.

Intervals from IntervalSets.jl are supported on a limited set of
functions.

Scatterplot

scatterplot(randn(50), randn(50), title="My Scatterplot")

[scatterplot1]

Axis scaling (xscale and/or yscale) is supported: choose from
(:identity, :ln, :log2, :log10) or use an arbitrary scale function:

scatterplot(1:10, 1:10, xscale=:log10, yscale=:log10)

[scatterplot2]

For the axis scale exponent, one can revert to using ASCII characters
instead of Unicode ones using the keyword unicode_exponent=false:

scatterplot(1:4, 1:4, xscale=:log10, yscale=:ln, unicode_exponent=false, height=6)

[scatterplot3]

Using a marker is supported, choose a Char, a unit length String or a
symbol name such as :circle (more from keys(UnicodePlots.MARKERS)).
One can also provide a vector of markers and/or colors as in the
following example:

scatterplot([1, 2, 3], [3, 4, 1], marker=[:circle, '', "[?]"],
            color=[:cyan, nothing, :yellow], height=2)

[scatterplot4]

As with lineplot, scatterplot supports plotting physical Unitful
quantities, or plotting multiple series (Matrix argument).

Lineplot

lineplot([1, 2, 7], [9, -6, 8], title="My Lineplot")

[lineplot4]

It's also possible to specify a function and a range:

plt = lineplot([cos, sin], -p/2, 2p)

[lineplot5]

You can also plot lines by specifying an intercept and slope:

lineplot!(plt, -.5, .2, name="line")

[lineplot6]

Plotting multiple series is supported by providing an AbstractMatrix
for the y argument, with the individual series corresponding to the
columns of the Matrix. Auto-labeling is by default, but you can also
label each series by providing a Vector or a 1xn Matrix such as
["series 1" "series2" ...]:

lineplot(1:10, [0:9 3:12 reverse(5:14) fill(4, 10)], color=[:green :red :yellow :cyan])

[lineplot7]

Physical units are supported through Unitful:

using Unitful
a, t = 1u"m/s^2", (0:100) * u"s"
lineplot(a / 2 * t .^ 2, a * t, xlabel="position", ylabel="speed", height=10)

[lineplot8]

Use head_tail to mimic plotting arrows (:head, :tail or :both) where
the length of the "arrow" head or tail is controlled using
head_tail_frac where e.g. giving a value of 0.1 means 10% of the
segment length:

lineplot(1:10, 1:10, head_tail=:head, head_tail_frac=.1, height=4)

[lineplot9]

UnicodePlots exports hline! and vline! for drawing vertical and
horizontal lines on a plot:

p = Plot([NaN], [NaN]; xlim=(0, 8), ylim=(0, 8))
vline!(p, [2, 6], [2, 6], color=:red)
hline!(p, [2, 6], [2, 6], color=:white)
hline!(p, 7, color=:cyan)
vline!(p, 1, color=:yellow)

[lineplot10]

Staircase plot

stairs([1, 2, 4, 7, 8], [1, 3, 4, 2, 7],
       color=:yellow, style=:post, height=6, title="Staircase")

[stairs1]

Barplot

barplot(["Paris", "New York", "Madrid"], [2.244, 8.406, 3.165], title="Population")

[barplot1]

Note: You can use the keyword argument symbols to specify the
characters that should be used to plot the bars (e.g. symbols=['#']).

Histogram

histogram(randn(1_000) .* .1, nbins=15, closed=:left)

[histogram1]

The histogram function also supports axis scaling using the parameter
xscale:

histogram(randn(1_000) .* .1, nbins=15, closed=:right, xscale=:log10)

[histogram2]

Vertical histograms are supported:

histogram(randn(100_000) .* .1, nbins=60, vertical=true, height=10)

[histogram3]

Boxplot

boxplot([1, 3, 3, 4, 6, 10])

[boxplot1]

boxplot(["one", "two"],
        [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7, 8, 9]],
        title="Grouped Boxplot", xlabel="x")

[boxplot2]

Sparsity Pattern

using SparseArrays
spy(sprandn(50, 120, .05))

[spy1]

Plotting the zeros pattern is also possible using show_zeros=true:

using SparseArrays
spy(sprandn(50, 120, .9), show_zeros=true)

[spy2]

Density Plot

plt = densityplot(randn(10_000), randn(10_000))
densityplot!(plt, randn(10_000) .+ 2, randn(10_000) .+ 2)

[densityplot1]

Using a scale function (e.g. damping peaks) is supported using the
dscale keyword:

x = randn(10_000); x[1_000:6_000] .= 2
densityplot(x, randn(10_000); dscale=x -> log(1 + x))

[densityplot2]

Contour Plot

contourplot(-3:.01:3, -7:.01:3, (x, y) -> exp(-(x / 2)^2 - ((y + 2) / 4)^2))

[contourplot1]

The keyword levels controls the number of contour levels. One can
also choose a colormap as with heatmap, and disable the colorbar
using colorbar=false.

Polar Plot

Plots data in polar coordinates with th the angles in radians.

polarplot(range(0, 2p, length=20), range(0, 2, length=20))

[polarplot1]

Heatmap Plot

heatmap(repeat(collect(0:10)', outer=(11, 1)), zlabel="z")

[heatmap1]

The heatmap function also supports axis scaling using the parameters
xfact, yfact and axis offsets after scaling using xoffset and
yoffset.

The colormap parameter may be used to specify a named or custom
colormap. See the heatmap function documentation for more details.

In addition, the colorbar and colorbar_border options may be used to
toggle the colorbar and configure its border.

The zlabel option and zlabel! method may be used to set the z axis
(colorbar) label.

Use the array keyword in order to display the matrix in the array
convention (as in the repl).

heatmap(collect(0:30) * collect(0:30)', xfact=.1, yfact=.1, xoffset=-1.5, colormap=:inferno)

[heatmap2]

Image Plot

Draws an image, surround it with decorations. Sixel are supported
(experimental) under a compatible terminal through ImageInTerminal
(which must be imported before UnicodePlots).

import ImageInTerminal  # mandatory (triggers glue code loading)
using TestImages
imageplot(testimage("monarch_color_256"), title="monarch")

[imageplot1]

Surface Plot

Plots a colored surface using height values z above a x-y plane, in
three dimensions (masking values using NaNs is supported).

sombrero(x, y) = 15sinc([?](x^2 + y^2) / p)
surfaceplot(-8:.5:8, -8:.5:8, sombrero, colormap=:jet)

[surfaceplot1]

Use lines=true to increase the density (underlying call to lineplot
instead of scatterplot, with color interpolation). By default,
surfaceplot scales heights to adjust aspect the other axes with
zscale=:aspect. To plot a slice in 3D, use an anonymous function
which maps to a constant value: zscale=z -> a_constant:

surfaceplot(
  -2:2, -2:2, (x, y) -> 15sinc([?](x^2 + y^2) / p),
  zscale=z -> 0, lines=true, colormap=:jet
)

[surfaceplot2]

Isosurface Plot

Uses MarchingCubes.jl to extract an isosurface, where isovalue
controls the surface isovalue. Using centroid enables plotting the
triangulation centroids instead of the triangle vertices (better for
small plots). Back face culling (hide not visible facets) can be
activated using cull=true. One can use the legacy 'Marching Cubes'
algorithm using legacy=true.

torus(x, y, z, r=0.2, R=0.5) = ([?](x^2 + y^2) - R)^2 + z^2 - r^2
isosurface(-1:.1:1, -1:.1:1, -1:.1:1, torus, cull=true, zoom=2, elevation=50)

[isosurface]

 Documentation

 Installation

...

To install UnicodePlots, start up Julia and type the following code
snippet into the REPL (makes use of the native Julia package manager
Pkg):

julia> using Pkg
julia> Pkg.add("UnicodePlots")

 Saving figures

...

Saving plots as png or txt files using the savefig command is
supported (saving as png is experimental and requires import
FreeType, FileIO before loading UnicodePlots).

To recover the plot as a string with ansi color codes use string(p;
color=true).

 Color mode

...

When the COLORTERM environment variable is set to either 24bit or
truecolor, UnicodePlots will use 24bit colors as opposed to 8bit
colors or even 4bit colors for named colors.

One can force a specific colormode using either
UnicodePlots.truecolors!() or UnicodePlots.colors256!().

Named colors such as :red or :light_red will use 256 color values
(rendering will be terminal dependent). In order to force named
colors to use true colors instead, use UnicodePlots.USE_LUT[]=true.

The default color cycle can be changed to bright (high intensity)
colors using UnicodePlots.brightcolors!() instead of the default
UnicodePlots.faintcolors!().

 3D plots

...

3d plots use a so-called "Model-View-Projection" transformation
matrix MVP on input data to project 3D plots to a 2D screen.

Use keywordselevation, azimuth, up or zoom to control the view
matrix, a.k.a. camera.

The projection type for MVP can be set to either :persp(ective) or
:ortho(graphic).

Displaying the x, y, and z axes can be controlled using the axes3d
keyword.

For enhanced resolution, use a wider and/or taller Plot (this can be
achieved using default_size!(width=60) for all future plots).

 Layout

...

UnicodePlots is integrated in Plots as a backend, with support for
basic layout.

For a more complex layout, use the grid function from Term:

using UnicodePlots, Term
panel(p; kw...) = begin
  p.margin[] = p.padding[] = 0  # make plots more compact
  Panel(string(p; color=true); style="hidden", fit=true, kw...)
end

(
  panel(lineplot(1:2)) *
  panel(scatterplot(rand(100)))
) / (
  panel(lineplot(2:-1:1)) *
  panel(densityplot(randn(1_000), randn(1_000)))
) |> print

grid(map(i -> panel(lineplot(-i:i)), 1:5); show_placeholder=true) |> print
grid(map(i -> panel(lineplot(-i:i)), 1:3); layout=(2, nothing)) |> print
grid(map(i -> panel(lineplot(-i:i)), 1:3); layout=(nothing, 1)) |> print

 Known issues

...

Using a non true monospace font can lead to visual problems on a
BrailleCanvas (border versus canvas).

Either change the font to e.g. JuliaMono or use border=:dotted
keyword argument in the plots.

For a Jupyter notebook with the IJulia kernel see here.

(Experimental) Terminals seem to respect a standard aspect ratio of
4:3, hence a square matrix does not often look square in the
terminal.

You can pass the experimental keyword fix_ar=true to spy or heatmap
in order to recover a unit aspect ratio.

 Methods (API)

...

Non-exhaustive methods description:

  * title!(plot::Plot, title::String)

      + title the string to write in the top center of the plot
        window. If the title is empty the whole line of the title
        will not be drawn
  * xlabel!(plot::Plot, xlabel::String)

      + xlabel the string to display on the bottom of the plot
        window. If the title is empty the whole line of the label
        will not be drawn
  * ylabel!(plot::Plot, xlabel::String)

      + ylabel the string to display on the far left of the plot
        window.

The method label! is responsible for the setting all the textual
decorations of a plot. It has two functions:

  * label!(plot::Plot, where::Symbol, value::String)

      + where can be any of: :tl (top-left), :t (top-center), :tr
        (top-right), :bl (bottom-left), :b (bottom-center), :br
        (bottom-right), :l (left), :r (right)
  * label!(plot::Plot, where::Symbol, row::Int, value::String)

      + where can be any of: :l (left), :r (right)

      + row can be between 1 and the number of character rows of the
        canvas

x = y = collect(1:10)
plt = lineplot(x, y, canvas=DotCanvas, height=10, width=30)
lineplot!(plt, x, reverse(y))
title!(plt, "Plot Title")
for loc in (:tl, :t, :tr, :bl, :b, :br)
  label!(plt, loc, string(':', loc))
end
label!(plt, :l, ":l")
label!(plt, :r, ":r")
for i in 1:10
  label!(plt, :l, i, string(i))
  label!(plt, :r, i, string(i))
end
plt

[decorate]

  * annotate!(plot::Plot, x::Number, y::Number, text::AbstractString;
    kw...)
      + text arbitrary annotation at position (x, y)

 Keywords description (API)

...

All plots support the set (or a subset) of the following named
parameters:

  * symbols::Array = ['#']: collection of characters used to render
    the bars.

  * title::String = "": text displayed on top of the plot.

  * name::String = "": current drawing annotation displayed on the
    right.

  * xlabel::String = "": text displayed on the x axis of the plot.

  * ylabel::String = "": text displayed on the y axis of the plot.

  * zlabel::String = "": text displayed on the z axis (colorbar) of
    the plot.

  * xscale::Symbol = :identity: x-axis scale (:identity, :ln, :log2,
    :log10), or scale function e.g. x -> log10(x).

  * yscale::Symbol = :identity: y-axis scale.

  * labels::Bool = true: show plot labels.

    lineplot(sin, 1:.5:20, labels=false)

    [labels]

  * border::Symbol = :solid: plot bounding box style (:corners,
    :solid, :bold, :dashed, :dotted, :ascii, :none).

    lineplot([-1., 2, 3, 7], [1.,2, 9, 4], canvas=DotCanvas, border=:dashed)

    [border_dashed]

    lineplot([-1., 2, 3, 7], [1.,2, 9, 4], canvas=DotCanvas, border=:ascii)

    [border_ascii]

    lineplot([-1., 2, 3, 7], [1.,2, 9, 4], canvas=DotCanvas, border=:bold)

    [border_bold]

    lineplot([-1., 2, 3, 7], [1.,2, 9, 4], border=:dotted)

    [border_dotted]

    lineplot([-1., 2, 3, 7], [1.,2, 9, 4], border=:none)

    [border_none]

  * margin::Int = 3: number of empty characters to the left of the
    whole plot.

  * padding::Int = 1: left and right space between the labels and the
    canvas.

  * color::Symbol = :auto: choose from (:green, :blue, :red, :yellow,
    :cyan, :magenta, :white, :normal, :auto), use an integer in
    [0-255], or provide 3 integers as RGB components.

  * height::Int = 15: number of canvas rows, or :auto.

    lineplot(sin, 1:.5:20, height=18)

    [height]

  * width::Int = 40: number of characters per canvas row, or :auto.

    lineplot(sin, 1:.5:20, width=60)

    [width]

  * xlim::Tuple = (0, 0): plotting range for the x axis ((0, 0)
    stands for automatic).

  * ylim::Tuple = (0, 0): plotting range for the y axis.

  * zlim::Tuple = (0, 0): colormap scaled data range.

  * xticks::Bool = true: set false to disable ticks (labels) on
    x-axis.

  * yticks::Bool = true: set false to disable ticks (labels) on
    y-axis.

  * xflip::Bool = false: set true to flip the x axis.

  * yflip::Bool = false: set true to flip the y axis.

  * colorbar::Bool = false: toggle the colorbar.

  * colormap::Symbol = :viridis: choose a symbol from ColorSchemes.jl
    e.g. :viridis, or supply a function f: (z, zmin, zmax) -> Int
    (0-255), or a vector of RGB tuples.

  * colorbar_lim::Tuple = (0, 1): colorbar limit.

  * colorbar_border::Symbol = :solid: color bar bounding box style
    (:solid, :bold, :dashed, :dotted, :ascii, :none).

  * canvas::UnionAll = BrailleCanvas: type of canvas used for
    drawing.

  * grid::Bool = true: draws grid-lines at the origin.

  * compact::Bool = false: compact plot labels.

  * unicode_exponent::Bool = true: use Unicode symbols for exponents:
    e.g. 102[?]1 instead of 10^2.1.

  * thousands_separator::Char = ' ': thousands separator character
    (use Char(0) to disable grouping digits).

  * projection::Symbol = :orthographic: projection for 3D plots
    (:ortho(graphic), :persp(ective), or Model-View-Projection (MVP)
    matrix).

  * axes3d::Bool = true: draw 3d axes (x -> :red, y -> :green, z ->
    :blue).

  * elevation::Float = 35.26: elevation angle above or below the
    floor plane (-90 <= th <= 90).

  * azimuth::Float = 45.0: azimutal angle around the up vector (-180deg
    <= ph <= 180deg).

  * zoom::Float = 1.0: zooming factor in 3D.

  * up::Symbol = :z: up vector (:x, :y or :z), prefix with m -> - or
    p -> + to change the sign e.g. :mz for -z axis pointing upwards.

  * near::Float = 1.0: distance to the near clipping plane
    (:perspective projection only).

  * far::Float = 100.0: distance to the far clipping plane
    (:perspective projection only).

  * canvas_kw::NamedTuple = NamedTuple(): extra canvas keywords.

  * blend::Bool = true: blend colors on the underlying canvas.

  * fix_ar::Bool = false: fix terminal aspect ratio (experimental).

  * visible::Bool = true: visible canvas.

Note: If you want to print the plot into a file but have monospace
issues with your font, you should probably try setting border=:ascii
and canvas=AsciiCanvas (or canvas=DotCanvas for scatterplots).

 Low-level interface

...

The primary structures that do all the heavy lifting behind the
curtain are subtypes of Canvas. A canvas is a graphics object for
rasterized plotting. Basically, it uses Unicode characters to
represent pixel.

Here is a simple example:

import UnicodePlots: lines!, points!, pixel!
canvas = BrailleCanvas(15, 40,                    # number of rows and columns (characters)
                       origin_y=0., origin_x=0.,  # position in virtual space
                       height=1., width=1.)       # size of the virtual space
lines!(canvas, 0., 0., 1., 1.; color=:cyan)       # virtual space
points!(canvas, rand(50), rand(50); color=:red)   # virtual space
lines!(canvas, 0., 1., .5, 0.; color=:yellow)     # virtual space
pixel!(canvas, 5, 8; color=:red)                  # pixel space
Plot(canvas)

[canvas]

You can access the height and width of the canvas (in characters)
with nrows(canvas) and ncols(canvas) respectively. You can use those
functions in combination with print_row to embed the canvas anywhere
you wish. For example, print_row(STDOUT, canvas, 3) writes the third
character row of the canvas to the standard output.

As you can see, one issue that arises when multiple pixel are
represented by one character is that it is hard to assign color. That
is because each of the "pixel" of a character could belong to a
different color group (each character can only have a single color).
This package deals with this using a color-blend for the whole group.
You can disable canvas color blending / mixing by passing blend=false
to any function.

import UnicodePlots: lines!
canvas = BrailleCanvas(15, 40; origin_y=0., origin_x=0., height=1., width=1.)
lines!(canvas, 0., 0., 1., 1.; color=:cyan)
lines!(canvas, .25, 1., .5, 0.; color=:yellow)
lines!(canvas, .2, .8, 1., 0.; color=:red)
Plot(canvas)

[blending]

The following types of Canvas are implemented:

  * BrailleCanvas: This type of canvas is probably the one with the
    highest resolution for Unicode plotting. It essentially uses the
    Unicode characters of the Braille symbols as pixels. This
    effectively turns every character into eight pixels that can
    individually be manipulated using binary operations.

  * BlockCanvas: This canvas is also Unicode based. It has half the
    resolution of the BrailleCanvas. In contrast to BrailleCanvas,
    the pixels don't have visible spacing between them. This canvas
    effectively turns every character into four pixels that can
    individually be manipulated using binary operations.

  * HeatmapCanvas: This canvas is also Unicode based. It has half the
    resolution of the BlockCanvas. This canvas effectively turns
    every character into two color pixels, using the foreground and
    background terminal colors. As such, the number of rows of the
    canvas is half the number of y coordinates being displayed.

  * AsciiCanvas and DotCanvas: These two canvas utilizes only
    standard ASCII character for drawing. Naturally, it doesn't look
    quite as nice as the Unicode-based ones. However, in some
    situations it might yield better results. Printing plots to a
    file is one of those situations.

  * DensityCanvas: Unlike the BrailleCanvas, the density canvas does
    not simply mark a "pixel" as set. Instead it increments a counter
    per character that keeps track of the frequency of pixels drawn
    in that character. Together with a variable that keeps track of
    the maximum frequency, the canvas can thus draw the density of
    datapoints.

  * BarplotGraphics: This graphics area is special in that it does
    not support any pixel manipulation. It is essentially the barplot
    without decorations but the numbers. It does only support one
    method addrow! which allows the user to add additional bars to
    the graphics object.

 Developer notes

...

Because Julia uses column-major indexing order for an array type, and
because displaying data on a terminal is row based, we need an
internal buffer compatible with efficient columns based iteration. We
solve this by using the transpose of a (width, height) array for
indexing into an internal buffer like buf[row, col] or buf[y, x].
Common users of UnicodePlots don't need to be aware of this axis
difference if sticking to public interface.

p = Plot([NaN], [NaN]; xlim=(1, 10), ylim=(1, 10), title="internal buffer conventions")

# plot axes
vline!(p, 1, head_tail=:head, color=:green, name="y-axis (rows)")
hline!(p, 1, head_tail=:head, color=:red, name="x-axis (cols)")

# square
vline!(p, 2, [2, 9], color=:cyan, name="buf[y, x] - buf[row, col]")
vline!(p, [2, 9], [2, 9], color=:cyan)
hline!(p, [2, 9], [2, 9], color=:cyan)

# internal axes
vline!(p, 3, range(3, 8; length=20), head_tail=:tail, color=:light_green, name="y-buffer (rows)")
hline!(p, 8, range(3, 8; length=20), head_tail=:head, color=:light_red, name="x-buffer (cols)")

# mem layout
vline!(p, 4, [4, 7]; color=:yellow, name="memory layout")
vline!(p, 7, [4, 7]; color=:yellow)
hline!(p, [4, 7], [4, 7]; color=:yellow)
hline!(p, [4.5, 5, 5.5, 6], [4.5, 6.5]; color=:yellow)

[buffer_convention]

 Invalidations check

...

Run the folowing snippet to analyze invalidations:

using SnoopCompileCore

invalidations = @snoopr using UnicodePlots
tinf = @snoopi_deep UnicodePlots.precompile_workload()

using SnoopCompile, AbstractTrees, PrettyTables  # must occur after `invalidations`

print_tree(tinf; maxdepth = typemax(Int))

trees = invalidation_trees(invalidations)
trees = filtermod(UnicodePlots, trees; recursive = true)

@show length(uinvalidated(invalidations))  # all invalidations

# only from `UnicodePlots`
@show length(staleinstances(tinf))
@show length(trees)

SnoopCompile.report_invalidations(;
   invalidations,
   process_filename = x -> last(split(x, ".julia/packages/")),
   n_rows = 0,
)

 Documentation update

...

The following snippet:

$ cd docs
$ julia gen_docs.jl
$ (cd imgs; julia gen_imgs.jl)

will regenerate README.md and the example images with root (prefix)
url https://github.com/JuliaPlots/UnicodePlots.jl/raw/
unicodeplots-docs.

 License

This code is free to use under the terms of the MIT license.

 Acknowledgement

Inspired by TextPlots.jl, which in turn was inspired by Drawille.

About

Unicode-based scientific plotting for working in the terminal

Topics

unicode terminal plots julia repl plotting

Resources

Readme

License

View license

Stars

1.1k stars

Watchers

10 watching

Forks

68 forks
Report repository

Releases 72

 
v3.5.0 Latest
Apr 9, 2023
+ 71 releases

Packages 0

No packages published

Contributors 33

  * @Evizero
  * @t-bltg
  * @johnnychen94
  * @Paulms
  * @jiahao
  * @andreasnoack
  * @IanButterworth
  * @juliohm
  * @waldyrious
  * @DrDaleks
  * @jakebolewski

+ 22 contributors

Languages

  * Julia 100.0%

Footer

 (c) 2023 GitHub, Inc.

Footer navigation

  * Terms
  * Privacy
  * Security
  * Status
  * Docs
  * Contact GitHub
  * Pricing
  * API
  * Training
  * Blog
  * About

You can't perform that action at this time.
You signed in with another tab or window. Reload to refresh your
session. You signed out in another tab or window. Reload to refresh
your session.