Plots in the terminal (with sixel)

I just came across “sixel” which allows to show graphics in the terminal (while reading this GitHub - csdvrx/sixel-gnuplot: GNUplot with sixel support )

Unfortunately, gnome-terminal does not support this (Bug 729204 – sixel support), but xterm (run as xterm -ti vt340) does.

In fact it does not take much to use this with julia and PyPlot (or any other plotting package), just the convert tool from ImageMagic.

I started Julia with unset DISPLAY (on Linux)

using PyPlot
plt.style.use("dark_background")
function show()
   fname = tempname() * ".png";
   savefig(fname)
   run(`convert $fname -geometry 800x480  sixel:-`)
   return nothing
end
x = 1:0.1:10;
pcolor(sin.(x) * sin.(x)');
show()

Off-topic, but also useful is lsix: “ls” for images (GitHub - hackerb9/lsix: Like "ls", but for images. Shows thumbnails in terminal using sixel graphics.)

11 Likes

You could also try the unregistered https://github.com/tshort/SixelTerm.jl. It uses ImageMagick.

3 Likes

SixelTerm.jl is really nice! Thanks for sharing! It is quite impressive what you can do with 30 lines of code in SixelTerm.jl.

1 Like

GR has builtin sixel support:

using GR
inline("iterm")
contourf(peaks())

Could also be integrated into Plots gr() backend - just let me know …

19 Likes

It could also be useful to overload the display function to make a plot for long vector and a heatmap for large matrices. I think I will use the feature at lot more!

ENV["GKSwstype"] = "nul"    # needed for the GR backend on headless servers
using Plots
using SixelTerm
using NCDatasets

function Base.display(x::Matrix{T}) where T <: Union{Number,Union{Missing,Number}}
    if length(x) < 300
        invoke(display, Tuple{AbstractMatrix}, x)
    else
        display(heatmap(coalesce.(x,NaN)', color=:lightrainbow))
    end
end


ds = Dataset("/home/abarth/Data/DivaData/Global/gebco_30sec_16.nc");
bathymetry = ds["bat"][:,:] # returns a Array{Union{Missing, Float32},2}

1 Like

… no need to overload display in GR: :grinning:

8 Likes

Not in the REPL but I still prefer

using GMT
grdimage("@earth_relief_05m.grd", proj=:Winkel, fmt=:png, show=true)

But if I see that correctly, this means, that GR.jl can only plot using terminals that are hard coded in GR.jl, right`

I ran into some pages in Japanese when looking for the details of the sixel generation algorithm so I cannot judge how complex it is, but I am wondering if it would make sense to have a native Julia implementation. It would have obvious advantages for all packages using this functionality, and could also serve as a nice reference.

GR.jl is only a wrapper for the GR framework. Any software that uses GR.jl can produce sixel graphics. It’s just about converting an internally rendered image to sixels …

Thus, it can be used from Julia, Python C, or whatever.

The latest release of Gaston also supports sixel:

I had had experimental support for a while, but this thread motivated me to finish it up. Also, since gnuplot has native sixel support, no external libraries or converters are needed.

8 Likes

This really seems like the minimum time to first plot after UnicodePlots! GR doesn’t appear to have a spy() for sparse matrices. I put this together quickly to plot sparsity patterns in iTerm2 and it’s great:

function spy(A::AbstractSparseMatrix)
  nrows, ncols = size(A)
  rows, cols, vals = findnz(A)
  avals = abs.(vals)
  scatter(cols, rows, 50 * ones(length(rows)), 255 * avals ./ maximum(avals), xlim=(1, ncols), ylim=(1, nrows), yflip=true)
end

This could be a great alias for show() for sparse matrices in terminals that support it.
However, I’m not finding a convenient reference for keyword arguments accepted by GR. How do I

  • adjust the aspect ratio to match the matrix?
  • choose my own x and y ticks?
  • remove the background grid?

56

1 Like

I would like to be able to set an environment variable that makes the sixel terminal display default for all plotting packages, so that when I load any plotting package I don’t need to configure.

1 Like

In the meantime, remember that you can add configuration commands to your ~/.juliarc file.

That would require loading a plotting package each time I launch Julia, which I definitely don’t want in my startup file.

Currently, enabling sixel requires setting an option after loading the package.

The point of having an environment variable is to pre-set the option before any plotting package is loaded, so that I can choose to load plotting whenever I need it, without worrying about enabling sixel.

1 Like

What’s an environment variable plotting could agree on? ENV["SIXEL"] perhaps?

You could add this function to your .juliarc:

function plot_with_gaston()
    @eval using Gaston
    @eval set(terminal="sixelgd")
end

and just call it when you’re ready to plot.

Although this is late, would you please let me how to achieve this with plots? I’d like to get this to work in Plots

env GKSwstype=iterm julia
...
julia> using Plots
julia> plot(randn(10))

For any reason, in Plots.jl the resulting plot is not HiDPI, but at least it works …

6 Likes

This is an old thread but if some desperate soul is still looking for a solution I want to share my accidental discovery:

How to plot inside iTerm on macOS

This produces sharp plots even on Retina displays. Adjust the size and scaling to your liking.

using Plots
theme(:dark)  # for dark terminal backgrounds
default(display_type=:inline, size=(1500,800), thickness_scaling=1.5)
plot(rand(20))
(Minor) caveats: - The GKS QT terminal starts in the background (it doesn't open a window). - You can even ssh into a headless remote machine and initiate the plot there. Some QT related error messages do appear though.

Set the the environment variable GKSwstype=nul before starting julia to suppress the launching of gksqt.

You can even ssh into a headless remote machine and initiate the plot there.

EDIT: How to avoid GKSQT. Thanks to Plots in the terminal (with sixel) - #31 by jheinen.

3 Likes