266 lines
6.4 KiB
Julia
266 lines
6.4 KiB
Julia
|
|
# https://github.com/Evizero/UnicodePlots.jl
|
|
|
|
immutable UnicodePlotsPackage <: PlottingPackage end
|
|
|
|
export unicodeplots
|
|
unicodeplots() = backend(:unicodeplots)
|
|
|
|
# -------------------------------
|
|
|
|
# supportedArgs(::UnicodePlotsPackage) = setdiff(_allArgs, [:reg, :heatmap_c, :fill, :pos, :xlims, :ylims, :xticks, :yticks])
|
|
supportedArgs(::UnicodePlotsPackage) = [
|
|
# :annotation,
|
|
# :args,
|
|
# :axis,
|
|
# :background_color,
|
|
# :color,
|
|
# :fill,
|
|
# :foreground_color,
|
|
:group,
|
|
# :heatmap_c,
|
|
# :kwargs,
|
|
:label,
|
|
# :layout,
|
|
:legend,
|
|
:linestyle,
|
|
:linetype,
|
|
# :linewidth,
|
|
:markershape,
|
|
# :markercolor,
|
|
# :markersize,
|
|
# :n,
|
|
:nbins,
|
|
# :nc,
|
|
# :nr,
|
|
# :pos,
|
|
# :reg,
|
|
# :ribbon,
|
|
:show,
|
|
:size,
|
|
:title,
|
|
:windowtitle,
|
|
:x,
|
|
:xlabel,
|
|
:xlims,
|
|
# :xticks,
|
|
:y,
|
|
:ylabel,
|
|
:ylims,
|
|
# :yrightlabel,
|
|
# :yticks,
|
|
# :xscale,
|
|
# :yscale,
|
|
# :xflip,
|
|
# :yflip,
|
|
# :z,
|
|
]
|
|
supportedAxes(::UnicodePlotsPackage) = [:auto, :left]
|
|
supportedTypes(::UnicodePlotsPackage) = [:none, :line, :path, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
|
|
supportedStyles(::UnicodePlotsPackage) = [:auto, :solid]
|
|
supportedMarkers(::UnicodePlotsPackage) = [:none, :auto, :ellipse]
|
|
supportedScales(::UnicodePlotsPackage) = [:identity]
|
|
|
|
|
|
function expandLimits!(lims, x)
|
|
e1, e2 = extrema(x)
|
|
lims[1] = min(lims[1], e1)
|
|
lims[2] = max(lims[2], e2)
|
|
nothing
|
|
end
|
|
|
|
|
|
# do all the magic here... build it all at once, since we need to know about all the series at the very beginning
|
|
function rebuildUnicodePlot!(plt::Plot)
|
|
|
|
# figure out the plotting area xlim = [xmin, xmax] and ylim = [ymin, ymax]
|
|
sargs = plt.seriesargs
|
|
iargs = plt.initargs
|
|
|
|
# get the x/y limits
|
|
if get(iargs, :xlims, :auto) == :auto
|
|
xlim = [Inf, -Inf]
|
|
for d in sargs
|
|
expandLimits!(xlim, d[:x])
|
|
end
|
|
else
|
|
xmin, xmax = iargs[:xlims]
|
|
xlim = [xmin, xmax]
|
|
end
|
|
|
|
if get(iargs, :ylims, :auto) == :auto
|
|
ylim = [Inf, -Inf]
|
|
for d in sargs
|
|
expandLimits!(ylim, d[:y])
|
|
end
|
|
else
|
|
ymin, ymax = iargs[:ylims]
|
|
ylim = [ymin, ymax]
|
|
end
|
|
|
|
# we set x/y to have a single point, since we need to create the plot with some data.
|
|
# since this point is at the bottom left corner of the plot, it shouldn't actually be shown
|
|
x = Float64[xlim[1]]
|
|
y = Float64[ylim[1]]
|
|
|
|
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
|
|
width, height = iargs[:size]
|
|
o = UnicodePlots.createPlotWindow(x, y; width = width,
|
|
height = height,
|
|
title = iargs[:title],
|
|
# labels = iargs[:legend],
|
|
xlim = xlim,
|
|
ylim = ylim)
|
|
|
|
# set the axis labels
|
|
UnicodePlots.xlabel!(o, iargs[:xlabel])
|
|
UnicodePlots.ylabel!(o, iargs[:ylabel])
|
|
|
|
# now use the ! functions to add to the plot
|
|
for d in sargs
|
|
addUnicodeSeries!(o, d, iargs[:legend], xlim, ylim)
|
|
end
|
|
|
|
# save the object
|
|
plt.o = o
|
|
end
|
|
|
|
|
|
# add a single series
|
|
function addUnicodeSeries!(o, d::Dict, addlegend::Bool, xlim, ylim)
|
|
|
|
# get the function, or special handling for step/bar/hist
|
|
lt = d[:linetype]
|
|
|
|
# handle hline/vline separately
|
|
if lt in (:hline,:vline)
|
|
for yi in d[:y]
|
|
if lt == :hline
|
|
UnicodePlots.lineplot!(o, xlim, [yi,yi])
|
|
else
|
|
UnicodePlots.lineplot!(o, [yi,yi], ylim)
|
|
end
|
|
end
|
|
return
|
|
end
|
|
|
|
stepstyle = :post
|
|
if lt == :path
|
|
func = UnicodePlots.lineplot!
|
|
elseif lt == :scatter || d[:markershape] != :none
|
|
func = UnicodePlots.scatterplot!
|
|
elseif lt == :steppost
|
|
func = UnicodePlots.stairs!
|
|
elseif lt == :steppre
|
|
func = UnicodePlots.stairs!
|
|
stepstyle = :pre
|
|
else
|
|
error("Linestyle $lt not supported by UnicodePlots")
|
|
end
|
|
|
|
# get the series data and label
|
|
x, y = [collect(float(d[s])) for s in (:x, :y)]
|
|
label = addlegend ? d[:label] : ""
|
|
|
|
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
|
|
color = d[:color] in UnicodePlots.autoColors ? d[:color] : :auto
|
|
|
|
# add the series
|
|
func(o, x, y; color = color, name = label, style = stepstyle)
|
|
end
|
|
|
|
|
|
function handlePlotColors(::UnicodePlotsPackage, d::Dict)
|
|
# TODO: something special for unicodeplots, since it doesn't take kindly to people messing with its color palette
|
|
d[:color_palette] = [RGB(0,0,0)]
|
|
end
|
|
|
|
# -------------------------------
|
|
|
|
|
|
function plot(pkg::UnicodePlotsPackage; kw...)
|
|
plt = Plot(nothing, pkg, 0, Dict(kw), Dict[])
|
|
|
|
# do we want to give a new default size?
|
|
if !haskey(plt.initargs, :size) || plt.initargs[:size] == _plotDefaults[:size]
|
|
plt.initargs[:size] = (60,20)
|
|
end
|
|
|
|
plt
|
|
end
|
|
|
|
function plot!(::UnicodePlotsPackage, plt::Plot; kw...)
|
|
d = Dict(kw)
|
|
if d[:linetype] in (:sticks, :bar)
|
|
d = barHack(; d...)
|
|
elseif d[:linetype] == :hist
|
|
d = barHack(; histogramHack(; d...)...)
|
|
end
|
|
push!(plt.seriesargs, d)
|
|
plt
|
|
end
|
|
|
|
|
|
function updatePlotItems(plt::Plot{UnicodePlotsPackage}, d::Dict)
|
|
for k in (:title, :xlabel, :ylabel, :xlims, :ylims)
|
|
if haskey(d, k)
|
|
plt.initargs[k] = d[k]
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
# -------------------------------
|
|
|
|
# function savepng(::UnicodePlotsPackage, plt::PlottingObject, fn::@compat(AbstractString), args...)
|
|
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{UnicodePlotsPackage})
|
|
|
|
# make some whitespace and show the plot
|
|
println("\n\n\n\n\n\n")
|
|
gui(plt)
|
|
|
|
@osx_only begin
|
|
# BEGIN HACK
|
|
|
|
# wait while the plot gets drawn
|
|
sleep(0.5)
|
|
|
|
# use osx screen capture when my terminal is maximized and cursor starts at the bottom (I know, right?)
|
|
# TODO: compute size of plot to adjust these numbers (or maybe implement something good??)
|
|
run(`screencapture -R50,600,700,420 $fn`)
|
|
|
|
# # some other attempts:
|
|
# run(`screencapture -w $fn`)
|
|
# using PyCall
|
|
# @pyimport pyscreenshot as pss
|
|
|
|
# END HACK (phew)
|
|
return
|
|
end
|
|
|
|
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
|
|
end
|
|
|
|
# -------------------------------
|
|
|
|
# we don't do very much for subplots... just stack them vertically
|
|
|
|
function buildSubplotObject!(subplt::Subplot{UnicodePlotsPackage})
|
|
nothing
|
|
end
|
|
|
|
|
|
function Base.display(::PlotsDisplay, plt::Plot{UnicodePlotsPackage})
|
|
rebuildUnicodePlot!(plt)
|
|
show(plt.o)
|
|
end
|
|
|
|
|
|
|
|
function Base.display(::PlotsDisplay, subplt::Subplot{UnicodePlotsPackage})
|
|
for plt in subplt.plts
|
|
gui(plt)
|
|
end
|
|
end
|
|
|