working on plot and gadfly

This commit is contained in:
Thomas Breloff 2015-09-04 11:23:34 -04:00
parent 9bc4286dcb
commit 2d4cd06090
6 changed files with 110 additions and 41 deletions

View File

@ -1,5 +1,7 @@
module Plots module Plots
using Requires
export export
Plot, Plot,
plotter, plotter,
@ -10,6 +12,12 @@ export
currentPlot!, currentPlot!,
plotDefault, plotDefault,
plotDefault!, plotDefault!,
scatter,
bar,
hist,
heatmap,
savepng savepng
# --------------------------------------------------------- # ---------------------------------------------------------
@ -58,6 +66,18 @@ include("gadfly.jl")
include("args.jl") include("args.jl")
include("plot.jl") include("plot.jl")
# const LINE_TYPES = (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hist, :bar)
scatter(args...; kw...) = plot(args...; kw..., linetype = :dots)
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :dots)
bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
hist(args...; kw...) = plot(args...; kw..., linetype = :hist)
hist!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
# --------------------------------------------------------- # ---------------------------------------------------------
# # TODO: how do we handle NA values in dataframes? # # TODO: how do we handle NA values in dataframes?

View File

@ -6,12 +6,14 @@ const NUMCOLORS = length(COLORS)
# these are valid choices... first one is default value if unset # these are valid choices... first one is default value if unset
const LINE_AXES = (:left, :right) const LINE_AXES = (:left, :right)
const LINE_TYPES = (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap) const LINE_TYPES = (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hist, :bar)
const LINE_STYLES = (:solid, :dash, :dot, :dashdot, :dashdotdot) const LINE_STYLES = (:solid, :dash, :dot, :dashdot, :dashdotdot)
const LINE_MARKERS = (:none, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon) const LINE_MARKERS = (:none, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon)
const PLOT_DEFAULTS = Dict{Symbol, Any}() const PLOT_DEFAULTS = Dict{Symbol, Any}()
# series-specific
PLOT_DEFAULTS[:axis] = :left PLOT_DEFAULTS[:axis] = :left
PLOT_DEFAULTS[:color] = :auto PLOT_DEFAULTS[:color] = :auto
PLOT_DEFAULTS[:label] = "AUTO" PLOT_DEFAULTS[:label] = "AUTO"
@ -23,10 +25,16 @@ PLOT_DEFAULTS[:markercolor] = :auto
PLOT_DEFAULTS[:markersize] = 10 PLOT_DEFAULTS[:markersize] = 10
PLOT_DEFAULTS[:heatmap_n] = 100 PLOT_DEFAULTS[:heatmap_n] = 100
PLOT_DEFAULTS[:heatmap_c] = (0.15, 0.5) PLOT_DEFAULTS[:heatmap_c] = (0.15, 0.5)
# plot globals
PLOT_DEFAULTS[:title] = "" PLOT_DEFAULTS[:title] = ""
PLOT_DEFAULTS[:xlabel] = "" PLOT_DEFAULTS[:xlabel] = ""
PLOT_DEFAULTS[:ylabel] = "" PLOT_DEFAULTS[:ylabel] = ""
PLOT_DEFAULTS[:yrightlabel] = "" PLOT_DEFAULTS[:yrightlabel] = ""
PLOT_DEFAULTS[:legend] = true
PLOT_DEFAULTS[:background_color] = :white
PLOT_DEFAULTS[:xticks] = true
PLOT_DEFAULTS[:yticks] = true
plotDefault(sym::Symbol) = PLOT_DEFAULTS[sym] plotDefault(sym::Symbol) = PLOT_DEFAULTS[sym]
function plotDefault!(sym::Symbol, val) function plotDefault!(sym::Symbol, val)
@ -39,19 +47,19 @@ autocolor(idx::Integer) = COLORS[mod1(idx,NUMCOLORS)]
function getPlotKeywordArgs(kw, i::Int) function getPlotKeywordArgs(kw, i::Int)
d = Dict(kw) d = Dict(kw)
kw = Dict() outd = Dict()
for k in keys(PLOT_DEFAULTS) for k in keys(PLOT_DEFAULTS)
plural = makeplural(k) plural = makeplural(k)
if haskey(d, plural) if haskey(d, plural)
kw[k] = d[plural][i] outd[k] = d[plural][i]
elseif haskey(d, k) elseif haskey(d, k)
kw[k] = d[k] outd[k] = d[k]
else else
kw[k] = PLOT_DEFAULTS[k] outd[k] = PLOT_DEFAULTS[k]
end end
end end
kw outd
end end

View File

@ -6,7 +6,44 @@ immutable GadflyPackage <: PlottingPackage end
plot(pkg::GadflyPackage) = Plot(Qwt.plot(zeros(0,0)), pkg, AVec[], AVec[]) plot(pkg::GadflyPackage) = Plot(Qwt.plot(zeros(0,0)), pkg, AVec[], AVec[])
plot!(::GadflyPackage, plt::Plot; kw...) = Qwt.oplot(plt.o; kw...) plot!(::GadflyPackage, plt::Plot; kw...) = Qwt.oplot(plt.o; kw...)
# plot(::GadflyPackage, y; kw...) = Gadfly.plot(; x = 1:length(y), y = y, kw...)
# plot(::GadflyPackage, x, y; kw...) = Gadfly.plot(; x = x, y = y, kw...) # create a blank Gadfly.Plot object
# plot(::GadflyPackage; kw...) = Gadfly.plot(; kw...) function plot(pkg::GadflyPackage)
# savepng(::GadflyPackage, plt, fn::String, args...) = Gadfly.draw(Gadfly.PNG(fn, args...), plt) plt = Gadfly.Plot()
plt.mapping = Dict()
plt.data_source = DataFrame()
plt.layers = plt.layers[1:0]
Plot(plt, pkg, AVec[], AVec[])
end
# plot one data series
function plot!(::GadflyPackage, plt::Plot; kw...)
d = Dict(kw)
gd = Dict() # the kwargs for the call to Gadfly.layer
append!(plt.o.layers, layer(; gd...))
plt
end
function Base.display(::GadflyPackage, plt::Plot)
display(plt.o)
end
# julia> append!(plt.layers, layer(x=collect(1:10), y=collect(1:10), Geom.line(), Geom.point()))
# 2-element Array{Gadfly.Layer,1}:
# Gadfly.Layer(nothing,Dict{Symbol,Union{AbstractArray{T,N},AbstractString,Distributions.Distribution{F<:Distributions.VariateForm,S<:Distributions.ValueSupport},Expr,Function,Integer,Symbol,Void}}(:y=>[1,2,3,4,5,6,7,8,9,10],:x=>[1,2,3,4,5,6,7,8,9,10]),Gadfly.Stat.Nil(),Gadfly.Geom.LineGeometry(Gadfly.Stat.Identity(),false,2),nothing,0)
# Gadfly.Layer(nothing,Dict{Symbol,Union{AbstractArray{T,N},AbstractString,Distributions.Distribution{F<:Distributions.VariateForm,S<:Distributions.ValueSupport},Expr,Function,Integer,Symbol,Void}}(:y=>[1,2,3,4,5,6,7,8,9,10],:x=>[1,2,3,4,5,6,7,8,9,10]),Gadfly.Stat.Nil(),Gadfly.Geom.PointGeometry(),nothing,0)
# julia> append!(plt.layers, layer(x=collect(1:10), y=rand(10), Geom.point()))
# 3-element Array{Gadfly.Layer,1}:
# Gadfly.Layer(nothing,Dict{Symbol,Union{AbstractArray{T,N},AbstractString,Distributions.Distribution{F<:Distributions.VariateForm,S<:Distributions.ValueSupport},Expr,Function,Integer,Symbol,Void}}(:y=>[1,2,3,4,5,6,7,8,9,10],:x=>[1,2,3,4,5,6,7,8,9,10]),Gadfly.Stat.Nil(),Gadfly.Geom.LineGeometry(Gadfly.Stat.Identity(),false,2),nothing,0)
# Gadfly.Layer(nothing,Dict{Symbol,Union{AbstractArray{T,N},AbstractString,Distributions.Distribution{F<:Distributions.VariateForm,S<:Distributions.ValueSupport},Expr,Function,Integer,Symbol,Void}}(:y=>[1,2,3,4,5,6,7,8,9,10],:x=>[1,2,3,4,5,6,7,8,9,10]),Gadfly.Stat.Nil(),Gadfly.Geom.PointGeometry(),nothing,0)
# Gadfly.Layer(nothing,Dict{Symbol,Union{AbstractArray{T,N},AbstractString,Distributions.Distribution{F<:Distributions.VariateForm,S<:Distributions.ValueSupport},Expr,Function,Integer,Symbol,Void}}(:y=>[0.6084907709968024,0.05206084912131548,0.14212960794916185,0.10981085500127885,0.9921993333039756,0.9552243188578231,0.3255950301920405,0.1328008877835145,0.8717471404048149,0.18183756751204538],:x=>[1,2,3,4,5,6,7,8,9,10]),Gadfly.Stat.Nil(),Gadfly.Geom.PointGeometry(),nothing,0)
# julia> display(plt)
# # plot(::GadflyPackage, y; kw...) = Gadfly.plot(; x = 1:length(y), y = y, kw...)
# # plot(::GadflyPackage, x, y; kw...) = Gadfly.plot(; x = x, y = y, kw...)
# # plot(::GadflyPackage; kw...) = Gadfly.plot(; kw...)
# # savepng(::GadflyPackage, plt, fn::String, args...) = Gadfly.draw(Gadfly.PNG(fn, args...), plt)

View File

@ -116,38 +116,46 @@ When plotting multiple lines, you can give every line the same trait by using th
# this creates a new plot with args/kw and sets it to be the current plot # this creates a new plot with args/kw and sets it to be the current plot
function plot(args...; kw...) function plot(args...; kw...)
plt = plot(plotter(); getPlotKeywordArgs(kw, 1)...) # create a new, blank plot plt = plot(plotter(); getPlotKeywordArgs(kw, 1)...) # create a new, blank plot
plot!(plotter(), plt, args...; kw...) # add the series to that plot plot!(plt, args...; kw...) # add to it
currentPlot!(plt) # set this as the current plot
plt
end end
# this adds to the current plot # this adds to the current plot
function plot!(args...; kw...) function plot!(args...; kw...)
plt = currentPlot() plot!(currentPlot(), args...; kw...)
plot!(plotter(), plt, args...; kw...) end
# this adds to a specific plot... most plot commands will flow through here
function plot!(plt::Plot, args...; show=true, kw...)
plot!(plt.plotter, plt, args...; kw...)
currentPlot!(plt)
if show
display(plt)
end
plt plt
end end
# show/update the plot
function display(plt::Plot)
display(plt.plotter, plt)
end
# ------------------------- # -------------------------
# These methods are various ways to add to an existing plot # These methods are various ways to add to an existing plot
function plot!(pkg::PlottingPackage, plt::Plot, y::AVec; kw...) function plot!(pkg::PlottingPackage, plt::Plot, y::AVec; kw...)
kw = getPlotKeywordArgs(kw, 1) plot!(pkg, plt; x = 1:length(y), y = y, getPlotKeywordArgs(kw, 1)...)
plot!(pkg, plt; x = 1:length(y), y = y, kw...)
end end
function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AVec; kw...) # one line (will assert length(x) == length(y)) function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AVec; kw...) # one line (will assert length(x) == length(y))
@assert length(x) == length(y) @assert length(x) == length(y)
kw = getPlotKeywordArgs(kw, 1) plot!(pkg, plt; x=x, y=y, getPlotKeywordArgs(kw, 1)...)
plot!(pkg, plt; x=x, y=y, kw...)
end end
function plot!(pkg::PlottingPackage, plt::Plot, y::AMat; kw...) # multiple lines (one per column of x), all sharing x = 1:size(y,1) 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) n,m = size(y)
for i in 1:m for i in 1:m
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = 1:n, y = y[:,i], getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = 1:n, y = y[:,i], kw...)
end end
plt plt
end end
@ -156,8 +164,7 @@ function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AMat; kw...)
n,m = size(y) n,m = size(y)
for i in 1:m for i in 1:m
@assert length(x) == n @assert length(x) == n
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = x, y = y[:,i], getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = x, y = y[:,i], kw...)
end end
plt plt
end end
@ -165,38 +172,33 @@ 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)) 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) @assert size(x) == size(y)
for i in 1:size(x,2) for i in 1:size(x,2)
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = x[:,i], y = y[:,i], getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = x[:,i], y = y[:,i], kw...)
end end
plt plt
end end
function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, f::Function; kw...) # one line, y = f(x) function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, f::Function; kw...) # one line, y = f(x)
kw = getPlotKeywordArgs(kw, 1) plot!(pkg, plt; x = x, y = map(f,x), getPlotKeywordArgs(kw, 1)...)
plot!(pkg, plt; x = x, y = map(f,x), kw...)
end end
function plot!(pkg::PlottingPackage, plt::Plot, x::AMat, f::Function; kw...) # multiple lines, yᵢⱼ = f(xᵢⱼ) function plot!(pkg::PlottingPackage, plt::Plot, x::AMat, f::Function; kw...) # multiple lines, yᵢⱼ = f(xᵢⱼ)
for i in 1:size(x,2) for i in 1:size(x,2)
xi = x[:,i] xi = x[:,i]
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = xi, y = map(f, xi), getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = xi, y = map(f, xi), kw...)
end end
plt plt
end end
function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, fs::AVec{Function}; kw...) # multiple lines, yᵢⱼ = fⱼ(xᵢ) function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, fs::AVec{Function}; kw...) # multiple lines, yᵢⱼ = fⱼ(xᵢ)
for i in 1:length(fs) for i in 1:length(fs)
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = x, y = map(fs[i], x), getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = x, y = map(fs[i], x), kw...)
end end
plt plt
end end
function plot!(pkg::PlottingPackage, plt::Plot, y::AVec{AVec}; kw...) # multiple lines, each with x = 1:length(y[i]) function plot!(pkg::PlottingPackage, plt::Plot, y::AVec{AVec}; kw...) # multiple lines, each with x = 1:length(y[i])
for i in 1:length(y) for i in 1:length(y)
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = 1:length(y[i]), y = y[i], getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = 1:length(y[i]), y = y[i], kw...)
end end
plt plt
end end
@ -204,8 +206,7 @@ end
function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AVec{AVec}; kw...) # multiple lines, will assert length(x) == length(y[i]) function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AVec{AVec}; kw...) # multiple lines, will assert length(x) == length(y[i])
for i in 1:length(y) for i in 1:length(y)
@assert length(x) == length(y[i]) @assert length(x) == length(y[i])
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = x, y = y[i], getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = x, y = y[i], kw...)
end end
plt plt
end end
@ -214,16 +215,14 @@ function plot!(pkg::PlottingPackage, plt::Plot, x::AVec{AVec}, y::AVec{AVec}; kw
@assert length(x) == length(y) @assert length(x) == length(y)
for i in 1:length(x) for i in 1:length(x)
@assert length(x[i]) == length(y[i]) @assert length(x[i]) == length(y[i])
kw = getPlotKeywordArgs(kw, i) plot!(pkg, plt; x = x[i], y = y[i], getPlotKeywordArgs(kw, i)...)
plot!(pkg, plt; x = x[i], y = y[i], kw...)
end end
plt plt
end end
function plot!(pkg::PlottingPackage, plt::Plot, n::Integer; kw...) # n lines, all empty (for updating plots) function plot!(pkg::PlottingPackage, plt::Plot, n::Integer; kw...) # n lines, all empty (for updating plots)
for i in 1:n for i in 1:n
kw = getPlotKeywordArgs(kw, i) plot(pkg, plt, x = zeros(0), y = zeros(0), getPlotKeywordArgs(kw, i)...)
plot(pkg, plt, x = zeros(0), y = zeros(0), kw...)
end end
end end

View File

@ -1,5 +1,4 @@
using Requires
# these are the plotting packages you can load. we use lazymod so that we # these are the plotting packages you can load. we use lazymod so that we
# don't "import" the module until we want it # don't "import" the module until we want it
@ -8,6 +7,7 @@ using Requires
plot(pkg::PlottingPackage; kw...) = error("plot($pkg; kw...) is not implemented") 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") plot!(pkg::PlottingPackage, plt::Plot; kw...) = error("plot!($pkg, plt; kw...) is not implemented")
display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not implemented")
# --------------------------------------------------------- # ---------------------------------------------------------

View File

@ -5,5 +5,10 @@ immutable QwtPackage <: PlottingPackage end
plot(pkg::QwtPackage; kw...) = Plot(Qwt.plot(zeros(0,0); kw...), pkg, AVec[], AVec[]) plot(pkg::QwtPackage; kw...) = Plot(Qwt.plot(zeros(0,0); kw...), pkg, AVec[], AVec[])
plot!(::QwtPackage, plt::Plot; kw...) = Qwt.oplot(plt.o; kw...) plot!(::QwtPackage, plt::Plot; kw...) = Qwt.oplot(plt.o; kw...)
function display(::QwtPackage, plt::Plot)
Qwt.refresh(plt.o)
Qwt.showwidget(plt.o)
end
# subplot(::QwtPackage, args...; kw...) = Qwt.subplot(args...; kw...) # subplot(::QwtPackage, args...; kw...) = Qwt.subplot(args...; kw...)
# savepng(::QwtPackage, plt, fn::String, args...) = Qwt.savepng(plt, fn) # savepng(::QwtPackage, plt, fn::String, args...) = Qwt.savepng(plt, fn)