working on unicodeplots; added args to Plot; some reorg
This commit is contained in:
parent
e13fec08ca
commit
f322b9ac1c
@ -6,10 +6,11 @@ Plotting interface and wrapper for several plotting packages.
|
||||
|
||||
Please add wishlist items, bugs, or any other comments/questions to the issues list.
|
||||
|
||||
## Examples
|
||||
## Examples for each implemented backend:
|
||||
|
||||
- [Qwt.jl](docs/qwt_examples.md)
|
||||
- [Gadfly.jl](docs/gadfly_examples.md)
|
||||
- [UnicodePlots.jl](docs/gadfly_examples.md)
|
||||
|
||||
## Installation
|
||||
|
||||
@ -187,6 +188,10 @@ When plotting multiple lines, you can give every line the same trait by using th
|
||||
|
||||
- [x] Plot vectors/matrices/functions
|
||||
- [ ] Plot DataFrames
|
||||
- [ ] Scales
|
||||
- [ ] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
|
||||
- [ ] Custom markers
|
||||
- [ ] Special plots (boxplot, ohlc?)
|
||||
- [x] Subplots
|
||||
- [x] Histograms
|
||||
- [ ] 3D plotting
|
||||
|
||||
@ -39,15 +39,7 @@ const IMG_DIR = Pkg.dir("Plots") * "/img/"
|
||||
|
||||
include("types.jl")
|
||||
include("utils.jl")
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
include("qwt.jl")
|
||||
include("gadfly.jl")
|
||||
include("plotter.jl")
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
include("args.jl")
|
||||
include("plot.jl")
|
||||
include("subplot.jl")
|
||||
|
||||
@ -125,7 +125,11 @@ function getPlotKeywordArgs(kw, idx::Int, n::Int)
|
||||
|
||||
# set label
|
||||
label = d[:label]
|
||||
d[:label] = string(label == "AUTO" ? "y_$n" : label, d[:axis] == :left ? "" : " (R)")
|
||||
label = (label == "AUTO" ? "y_$n" : label)
|
||||
if d[:axis] == :right && label[end-3:end] != " (R)"
|
||||
label = string(label, " (R)")
|
||||
end
|
||||
d[:label] = label
|
||||
end
|
||||
|
||||
d
|
||||
|
||||
@ -27,7 +27,7 @@ function plot(pkg::GadflyPackage; kw...)
|
||||
|
||||
plt.theme = Gadfly.Theme(background_color = (haskey(d, :background_color) ? d[:background_color] : colorant"white"))
|
||||
|
||||
Plot(plt, pkg, 0)
|
||||
Plot(plt, pkg, 0, kw, Dict[])
|
||||
end
|
||||
|
||||
function getGeomFromLineType(linetype::Symbol, nbins::Int)
|
||||
@ -95,6 +95,9 @@ function plot!(::GadflyPackage, plt::Plot; kw...)
|
||||
warn("Gadly only supports one y axis")
|
||||
end
|
||||
|
||||
# save the kw args
|
||||
plt.push!(plt.seriesargs, d)
|
||||
|
||||
# add the layer to the Gadfly.Plot
|
||||
prepend!(plt.o.layers, Gadfly.layer(unique(gfargs)...; x = x, y = d[:y]))
|
||||
plt
|
||||
@ -115,9 +118,7 @@ end
|
||||
|
||||
# -------------------------------
|
||||
|
||||
# # create the underlying object (each backend will do this differently)
|
||||
# o = buildSubplotObject(plts, pkg, layout)
|
||||
|
||||
# create the underlying object (each backend will do this differently)
|
||||
function buildSubplotObject!(::GadflyPackage, subplt::Subplot)
|
||||
i = 0
|
||||
rows = []
|
||||
@ -24,13 +24,16 @@ end
|
||||
|
||||
function plot(pkg::QwtPackage; kw...)
|
||||
kw = adjustQwtKeywords(true; kw...)
|
||||
plt = Plot(Qwt.plot(zeros(0,0); kw..., show=false), pkg, 0)
|
||||
o = Qwt.plot(zeros(0,0); kw..., show=false)
|
||||
plt = Plot(o, pkg, 0, kw, Dict[])
|
||||
plt
|
||||
end
|
||||
|
||||
function plot!(::QwtPackage, plt::Plot; kw...)
|
||||
kw = adjustQwtKeywords(false; kw...)
|
||||
Qwt.oplot(plt.o; kw...)
|
||||
plt.push!(plt.seriesargs, kw)
|
||||
plt
|
||||
end
|
||||
|
||||
function Base.display(::QwtPackage, plt::Plot)
|
||||
@ -44,9 +47,7 @@ savepng(::QwtPackage, plt::PlottingObject, fn::String, args...) = Qwt.savepng(pl
|
||||
|
||||
# -------------------------------
|
||||
|
||||
# # create the underlying object (each backend will do this differently)
|
||||
# o = buildSubplotObject(plts, pkg, layout)
|
||||
|
||||
# create the underlying object (each backend will do this differently)
|
||||
function buildSubplotObject!(::QwtPackage, subplt::Subplot)
|
||||
i = 0
|
||||
rows = []
|
||||
124
src/backends/unicodeplots.jl
Normal file
124
src/backends/unicodeplots.jl
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
# https://github.com/Evizero/UnicodePlots.jl
|
||||
|
||||
immutable UnicodePlotsPackage <: PlottingPackage end
|
||||
|
||||
# -------------------------------
|
||||
|
||||
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
|
||||
xlim = [Inf, -Inf]
|
||||
ylim = [Inf, -Inf]
|
||||
for d in sargs
|
||||
@show xlim ylim d[:x] d[:y]
|
||||
expandLimits!(xlim, d[:x])
|
||||
expandLimits!(ylim, d[:y])
|
||||
@show xlim ylim d[:x] d[:y]
|
||||
end
|
||||
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
|
||||
iargs = plt.initargs
|
||||
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])
|
||||
end
|
||||
|
||||
# save the object
|
||||
plt.o = o
|
||||
end
|
||||
|
||||
|
||||
# add a single series
|
||||
function addUnicodeSeries!(o, d::Dict, addlegend::Bool)
|
||||
|
||||
lt = d[:linetype]
|
||||
x, y = d[:x], d[:y]
|
||||
label = addlegend ? d[:label] : ""
|
||||
stepstyle = :post
|
||||
|
||||
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
|
||||
color = d[:color] in UnicodePlots.autoColors ? d[:color] : :auto
|
||||
|
||||
if lt == :line
|
||||
func = UnicodePlots.lineplot!
|
||||
elseif lt == :dots || d[:marker] != :none
|
||||
func = UnicodePlots.scatterplot!
|
||||
elseif lt == :step
|
||||
func = UnicodePlots.stairs!
|
||||
elseif lt == :stepinverted
|
||||
func = UnicodePlots.stairs!
|
||||
stepstyle = :pre
|
||||
else
|
||||
error("Linestyle $lt not supported by UnicodePlots")
|
||||
end
|
||||
|
||||
func(o, x, y; color = color, name = label, style = stepstyle)
|
||||
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] == PLOT_DEFAULTS[:size]
|
||||
plt.initargs[:size] = (60,20)
|
||||
end
|
||||
# w,h = plt.initargs[:size]
|
||||
# plt.initargs[:size] = (min(200,w), min(200,h))
|
||||
plt
|
||||
end
|
||||
|
||||
function plot!(::UnicodePlotsPackage, plt::Plot; kw...)
|
||||
push!(plt.seriesargs, Dict(kw))
|
||||
plt
|
||||
end
|
||||
|
||||
function Base.display(::UnicodePlotsPackage, plt::Plot)
|
||||
rebuildUnicodePlot!(plt)
|
||||
show(plt.o)
|
||||
end
|
||||
|
||||
# -------------------------------
|
||||
|
||||
savepng(::UnicodePlotsPackage, plt::PlottingObject, fn::String, args...) = error("currently unsupported")
|
||||
|
||||
# -------------------------------
|
||||
|
||||
# create the underlying object (each backend will do this differently)
|
||||
function buildSubplotObject!(::UnicodePlotsPackage, subplt::Subplot)
|
||||
error("UnicodePlots doesn't support subplots")
|
||||
end
|
||||
|
||||
|
||||
function Base.display(::UnicodePlotsPackage, subplt::Subplot)
|
||||
error("UnicodePlots doesn't support subplots")
|
||||
end
|
||||
|
||||
128
src/plot.jl
128
src/plot.jl
@ -104,14 +104,6 @@ end
|
||||
# this adds to a specific plot... most plot commands will flow through here
|
||||
function plot!(plt::Plot, args...; kw...)
|
||||
|
||||
# # increment n if we're going directly to the package's plot method
|
||||
# if length(args) == 0
|
||||
# plt.n += 1
|
||||
# end
|
||||
|
||||
# plot!(plt.plotter, plt, args...; kw...)
|
||||
|
||||
|
||||
kwList = createKWargsList(plt, args...; kw...)
|
||||
for (i,d) in enumerate(kwList)
|
||||
plt.n += 1
|
||||
@ -292,123 +284,3 @@ end
|
||||
|
||||
# -------------------------
|
||||
|
||||
# # most calls should flow through here now... we create a Dict with the keyword args for each series, and plot them
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, args...; kw...)
|
||||
# kwList = createKWargsList(plt, args...; kw...)
|
||||
# for (i,d) in enumerate(kwList)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; d...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# -------------------------
|
||||
|
||||
# # These methods are various ways to add to an existing plot
|
||||
|
||||
# function plot!{T<:Real}(pkg::PlottingPackage, plt::Plot, y::AVec{T}; kw...)
|
||||
# plt.n += 1
|
||||
# # plot!(pkg, plt; x = 1:length(y), y = y, getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
|
||||
# function plot!{T<:Real,S<:Real}(pkg::PlottingPackage, plt::Plot, x::AVec{T}, y::AVec{S}; kw...) # one line (will assert length(x) == length(y))
|
||||
# @assert length(x) == length(y)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x=x, y=y, getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, y::AMat; kw...) # multiple lines (one per column of x), all sharing x = 1:size(y,1)
|
||||
# n,m = size(y)
|
||||
# for i in 1:m
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = 1:n, y = y[:,i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AMat; kw...) # multiple lines (one per column of x), all sharing x (will assert length(x) == size(y,1))
|
||||
# n,m = size(y)
|
||||
# for i in 1:m
|
||||
# @assert length(x) == n
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = y[:,i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AMat, y::AMat; kw...) # multiple lines (one per column of x/y... will assert size(x) == size(y))
|
||||
# @assert size(x) == size(y)
|
||||
# for i in 1:size(x,2)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x[:,i], y = y[:,i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, f::Function; kw...) # one line, y = f(x)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = map(f,x), getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AMat, f::Function; kw...) # multiple lines, yᵢⱼ = f(xᵢⱼ)
|
||||
# for i in 1:size(x,2)
|
||||
# xi = x[:,i]
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = xi, y = map(f, xi), getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# # function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, fs::AVec{Function}; kw...) # multiple lines, yᵢⱼ = fⱼ(xᵢ)
|
||||
# # for i in 1:length(fs)
|
||||
# # plt.n += 1
|
||||
# # plot!(pkg, plt; x = x, y = map(fs[i], x), getPlotKeywordArgs(kw, i, plt)...)
|
||||
# # end
|
||||
# # plt
|
||||
# # end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, y::AVec; kw...) # multiple lines, each with x = 1:length(y[i])
|
||||
# for i in 1:length(y)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = 1:length(y[i]), y = y[i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!{T<:Real}(pkg::PlottingPackage, plt::Plot, x::AVec{T}, y::AVec; kw...) # multiple lines, will assert length(x) == length(y[i])
|
||||
# for i in 1:length(y)
|
||||
# if typeof(y[i]) <: AbstractVector
|
||||
# @assert length(x) == length(y[i])
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = y[i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# elseif typeof(y[i]) == Function
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = map(y[i], x), getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AVec; kw...) # multiple lines, will assert length(x[i]) == length(y[i])
|
||||
# @assert length(x) == length(y)
|
||||
# for i in 1:length(x)
|
||||
# @assert length(x[i]) == length(y[i])
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x[i], y = y[i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, n::Integer; kw...) # n lines, all empty (for updating plots)
|
||||
# for i in 1:n
|
||||
# plt.n += 1
|
||||
# plot(pkg, plt, x = zeros(0), y = zeros(0), getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# end
|
||||
|
||||
# -------------------------
|
||||
|
||||
# # this is the core method... add to a plot object using kwargs, with args already converted into kwargs
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot; kw...)
|
||||
# plot!(pl, plt; kw...)
|
||||
# end
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
|
||||
|
||||
include("backends/qwt.jl")
|
||||
include("backends/gadfly.jl")
|
||||
include("backends/unicodeplots.jl")
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
plot(pkg::PlottingPackage; kw...) = error("plot($pkg; kw...) is not implemented")
|
||||
plot!(pkg::PlottingPackage, plt::Plot; kw...) = error("plot!($pkg, plt; kw...) is not implemented")
|
||||
Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not implemented")
|
||||
@ -7,14 +15,13 @@ Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
const AVAILABLE_PACKAGES = [:qwt, :gadfly]
|
||||
const AVAILABLE_PACKAGES = [:qwt, :gadfly, :unicodeplots]
|
||||
const INITIALIZED_PACKAGES = Set{Symbol}()
|
||||
|
||||
type CurrentPackage
|
||||
sym::Symbol
|
||||
pkg::PlottingPackage
|
||||
end
|
||||
# const CURRENT_PACKAGE = CurrentPackage(:qwt, QwtPackage())
|
||||
const CURRENT_PACKAGE = CurrentPackage(:gadfly, GadflyPackage())
|
||||
|
||||
|
||||
@ -32,6 +39,8 @@ function plotter()
|
||||
@eval import Qwt
|
||||
elseif currentPackageSymbol == :gadfly
|
||||
@eval import Gadfly
|
||||
elseif currentPackageSymbol == :unicodeplots
|
||||
@eval import UnicodePlots
|
||||
else
|
||||
error("Unknown plotter $currentPackageSymbol. Choose from: $AVAILABLE_PACKAGES")
|
||||
end
|
||||
@ -43,7 +52,7 @@ function plotter()
|
||||
end
|
||||
|
||||
doc"""
|
||||
Set the plot backend. Choose from: :qwt, :gadfly
|
||||
Set the plot backend. Choose from: :qwt, :gadfly, :unicodeplots
|
||||
"""
|
||||
function plotter!(modname)
|
||||
|
||||
@ -52,6 +61,8 @@ function plotter!(modname)
|
||||
CURRENT_PACKAGE.pkg = QwtPackage()
|
||||
elseif modname == :gadfly
|
||||
CURRENT_PACKAGE.pkg = GadflyPackage()
|
||||
elseif modname == :unicodeplots
|
||||
CURRENT_PACKAGE.pkg = UnicodePlotsPackage()
|
||||
else
|
||||
error("Unknown plotter $modname. Choose from: $AVAILABLE_PACKAGES")
|
||||
end
|
||||
|
||||
@ -9,6 +9,10 @@ type Plot <: PlottingObject
|
||||
o # the underlying object
|
||||
plotter::PlottingPackage
|
||||
n::Int # number of series
|
||||
|
||||
# store these just in case
|
||||
initargs::Dict
|
||||
seriesargs::Vector{Dict} # args for each series
|
||||
end
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user