working on recipes overhaul
This commit is contained in:
parent
6049a9fa0a
commit
a5e9ad9f19
@ -171,7 +171,7 @@ include("backends.jl")
|
|||||||
include("args.jl")
|
include("args.jl")
|
||||||
include("themes.jl")
|
include("themes.jl")
|
||||||
include("plot.jl")
|
include("plot.jl")
|
||||||
# include("series_args.jl")
|
include("series_args.jl")
|
||||||
include("series_new.jl")
|
include("series_new.jl")
|
||||||
include("subplot.jl")
|
include("subplot.jl")
|
||||||
include("layouts.jl")
|
include("layouts.jl")
|
||||||
|
|||||||
@ -97,367 +97,367 @@ compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
|
|||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
# create n=max(mx,my) series arguments. the shorter list is cycled through
|
# # create n=max(mx,my) series arguments. the shorter list is cycled through
|
||||||
# note: everything should flow through this
|
# # note: everything should flow through this
|
||||||
function build_series_args(plt::AbstractPlot, kw::KW) #, idxfilter)
|
# function build_series_args(plt::AbstractPlot, kw::KW) #, idxfilter)
|
||||||
x, y, z = map(sym -> pop!(kw, sym, nothing), (:x, :y, :z))
|
# x, y, z = map(sym -> pop!(kw, sym, nothing), (:x, :y, :z))
|
||||||
if nothing == x == y == z
|
# if nothing == x == y == z
|
||||||
return [], nothing, nothing
|
# return [], nothing, nothing
|
||||||
end
|
|
||||||
|
|
||||||
xs, xmeta = convertToAnyVector(x, kw)
|
|
||||||
ys, ymeta = convertToAnyVector(y, kw)
|
|
||||||
zs, zmeta = convertToAnyVector(z, kw)
|
|
||||||
|
|
||||||
fr = pop!(kw, :fillrange, nothing)
|
|
||||||
fillranges, _ = if typeof(fr) <: Number
|
|
||||||
([fr],nothing)
|
|
||||||
else
|
|
||||||
convertToAnyVector(fr, kw)
|
|
||||||
end
|
|
||||||
|
|
||||||
mx = length(xs)
|
|
||||||
my = length(ys)
|
|
||||||
mz = length(zs)
|
|
||||||
ret = Any[]
|
|
||||||
for i in 1:max(mx, my, mz)
|
|
||||||
|
|
||||||
# try to set labels using ymeta
|
|
||||||
d = copy(kw)
|
|
||||||
if !haskey(d, :label) && ymeta != nothing
|
|
||||||
if isa(ymeta, Symbol)
|
|
||||||
d[:label] = string(ymeta)
|
|
||||||
elseif isa(ymeta, AVec{Symbol})
|
|
||||||
d[:label] = string(ymeta[mod1(i,length(ymeta))])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# build the series arg dict
|
|
||||||
numUncounted = pop!(d, :numUncounted, 0)
|
|
||||||
commandIndex = i + numUncounted
|
|
||||||
n = plt.n + i
|
|
||||||
|
|
||||||
dumpdict(d, "before getSeriesArgs")
|
|
||||||
d = getSeriesArgs(plt.backend, getplotargs(plt, n), d, commandIndex, convertSeriesIndex(plt, n), n)
|
|
||||||
dumpdict(d, "after getSeriesArgs")
|
|
||||||
|
|
||||||
d[:x], d[:y], d[:z] = compute_xyz(xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)])
|
|
||||||
lt = d[:linetype]
|
|
||||||
|
|
||||||
# for linetype `line`, need to sort by x values
|
|
||||||
if lt == :line
|
|
||||||
# order by x
|
|
||||||
indices = sortperm(d[:x])
|
|
||||||
d[:x] = d[:x][indices]
|
|
||||||
d[:y] = d[:y][indices]
|
|
||||||
d[:linetype] = :path
|
|
||||||
end
|
|
||||||
|
|
||||||
# special handling for missing x in box plot... all the same category
|
|
||||||
if lt == :box && xs[mod1(i,mx)] == nothing
|
|
||||||
d[:x] = ones(Int, length(d[:y]))
|
|
||||||
end
|
|
||||||
|
|
||||||
# map functions to vectors
|
|
||||||
if isa(d[:marker_z], Function)
|
|
||||||
d[:marker_z] = map(d[:marker_z], d[:x])
|
|
||||||
end
|
|
||||||
|
|
||||||
# @show fillranges
|
|
||||||
d[:fillrange] = fillranges[mod1(i,length(fillranges))]
|
|
||||||
if isa(d[:fillrange], Function)
|
|
||||||
d[:fillrange] = map(d[:fillrange], d[:x])
|
|
||||||
end
|
|
||||||
|
|
||||||
# handle error bars
|
|
||||||
for esym in (:xerror, :yerror)
|
|
||||||
if get(d, esym, nothing) != nothing
|
|
||||||
# we make a copy of the KW and apply an errorbar recipe
|
|
||||||
append!(ret, apply_series_recipe(copy(d), Val{esym}))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# handle ribbons
|
|
||||||
if get(d, :ribbon, nothing) != nothing
|
|
||||||
rib = d[:ribbon]
|
|
||||||
d[:fillrange] = (d[:y] - rib, d[:y] + rib)
|
|
||||||
end
|
|
||||||
|
|
||||||
# handle quiver plots
|
|
||||||
# either a series of velocity vectors are passed in (`:quiver` keyword),
|
|
||||||
# or we just add arrows to the path
|
|
||||||
|
|
||||||
# if lt == :quiver
|
|
||||||
# d[:linetype] = lt = :path
|
|
||||||
# d[:linewidth] = 0
|
|
||||||
# end
|
|
||||||
if get(d, :quiver, nothing) != nothing
|
|
||||||
append!(ret, apply_series_recipe(copy(d), Val{:quiver}))
|
|
||||||
elseif lt == :quiver
|
|
||||||
d[:linetype] = lt = :path
|
|
||||||
d[:arrow] = arrow()
|
|
||||||
end
|
|
||||||
|
|
||||||
# now that we've processed a given series... optionally split into
|
|
||||||
# multiple dicts through a recipe (for example, a box plot is split into component
|
|
||||||
# parts... polygons, lines, and scatters)
|
|
||||||
# note: we pass in a Val type (i.e. Val{:box}) so that we can dispatch on the linetype
|
|
||||||
kwlist = apply_series_recipe(d, Val{lt})
|
|
||||||
append!(ret, kwlist)
|
|
||||||
|
|
||||||
# # add it to our series list
|
|
||||||
# push!(ret, d)
|
|
||||||
end
|
|
||||||
|
|
||||||
ret, xmeta, ymeta
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# process_inputs
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
# These methods take a plot and the keyword arguments, and processes the input
|
|
||||||
# arguments (x/y/z, group, etc), populating the KW dict with appropriate values.
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# 0 arguments
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
# don't do anything
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW)
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# 1 argument
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, n::Integer)
|
|
||||||
# d[:x], d[:y], d[:z] = zeros(0), zeros(0), zeros(0)
|
|
||||||
d[:x] = d[:y] = d[:z] = n
|
|
||||||
end
|
|
||||||
|
|
||||||
# no special handling... assume x and z are nothing
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, y)
|
|
||||||
d[:y] = y
|
|
||||||
end
|
|
||||||
|
|
||||||
# matrix... is it z or y?
|
|
||||||
function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, mat::AMat{T})
|
|
||||||
if all3D(d)
|
|
||||||
n,m = size(mat)
|
|
||||||
d[:x], d[:y], d[:z] = 1:n, 1:m, mat
|
|
||||||
else
|
|
||||||
d[:y] = mat
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# images - grays
|
|
||||||
function process_inputs{T<:Gray}(plt::AbstractPlot, d::KW, mat::AMat{T})
|
|
||||||
d[:linetype] = :image
|
|
||||||
n,m = size(mat)
|
|
||||||
d[:x], d[:y], d[:z] = 1:n, 1:m, Surface(mat)
|
|
||||||
# handle images... when not supported natively, do a hack to use heatmap machinery
|
|
||||||
if !nativeImagesSupported()
|
|
||||||
d[:linetype] = :heatmap
|
|
||||||
d[:yflip] = true
|
|
||||||
d[:z] = Surface(convert(Matrix{Float64}, mat.surf))
|
|
||||||
d[:fillcolor] = ColorGradient([:black, :white])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# images - colors
|
|
||||||
function process_inputs{T<:Colorant}(plt::AbstractPlot, d::KW, mat::AMat{T})
|
|
||||||
d[:linetype] = :image
|
|
||||||
n,m = size(mat)
|
|
||||||
d[:x], d[:y], d[:z] = 1:n, 1:m, Surface(mat)
|
|
||||||
# handle images... when not supported natively, do a hack to use heatmap machinery
|
|
||||||
if !nativeImagesSupported()
|
|
||||||
d[:yflip] = true
|
|
||||||
imageHack(d)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# plotting arbitrary shapes/polygons
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, shape::Shape)
|
|
||||||
d[:x], d[:y] = shape_coords(shape)
|
|
||||||
d[:linetype] = :shape
|
|
||||||
end
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, shapes::AVec{Shape})
|
|
||||||
d[:x], d[:y] = shape_coords(shapes)
|
|
||||||
d[:linetype] = :shape
|
|
||||||
end
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, shapes::AMat{Shape})
|
|
||||||
x, y = [], []
|
|
||||||
for j in 1:size(shapes, 2)
|
|
||||||
tmpx, tmpy = shape_coords(vec(shapes[:,j]))
|
|
||||||
push!(x, tmpx)
|
|
||||||
push!(y, tmpy)
|
|
||||||
end
|
|
||||||
d[:x], d[:y] = x, y
|
|
||||||
d[:linetype] = :shape
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# function without range... use the current range of the x-axis
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs)
|
|
||||||
process_inputs(plt, d, f, xmin(plt), xmax(plt))
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# 2 arguments
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, x, y)
|
|
||||||
d[:x], d[:y] = x, y
|
|
||||||
end
|
|
||||||
|
|
||||||
# if functions come first, just swap the order (not to be confused with parametric functions...
|
|
||||||
# as there would be more than one function passed in)
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, x)
|
|
||||||
@assert !(typeof(x) <: FuncOrFuncs) # otherwise we'd hit infinite recursion here
|
|
||||||
process_inputs(plt, d, x, f)
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# 3 arguments
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
# no special handling... just pass them through
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, x, y, z)
|
|
||||||
d[:x], d[:y], d[:z] = x, y, z
|
|
||||||
end
|
|
||||||
|
|
||||||
# 3d line or scatter
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zvec::AVec)
|
|
||||||
# default to path3d if we haven't set a 3d linetype
|
|
||||||
lt = get(d, :linetype, :none)
|
|
||||||
if lt == :scatter
|
|
||||||
d[:linetype] = :scatter3d
|
|
||||||
elseif !(lt in _3dTypes)
|
|
||||||
d[:linetype] = :path3d
|
|
||||||
end
|
|
||||||
d[:x], d[:y], d[:z] = x, y, zvec
|
|
||||||
end
|
|
||||||
|
|
||||||
# surface-like... function
|
|
||||||
function process_inputs{TX,TY}(plt::AbstractPlot, d::KW, x::AVec{TX}, y::AVec{TY}, zf::Function)
|
|
||||||
x = TX <: Number ? sort(x) : x
|
|
||||||
y = TY <: Number ? sort(y) : y
|
|
||||||
# x, y = sort(x), sort(y)
|
|
||||||
d[:z] = Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported
|
|
||||||
d[:x], d[:y] = x, y
|
|
||||||
end
|
|
||||||
|
|
||||||
# surface-like... matrix grid
|
|
||||||
function process_inputs{TX,TY,TZ}(plt::AbstractPlot, d::KW, x::AVec{TX}, y::AVec{TY}, zmat::AMat{TZ})
|
|
||||||
# @assert size(zmat) == (length(x), length(y))
|
|
||||||
# if TX <: Number && !issorted(x)
|
|
||||||
# idx = sortperm(x)
|
|
||||||
# x, zmat = x[idx], zmat[idx, :]
|
|
||||||
# end
|
|
||||||
# if TY <: Number && !issorted(y)
|
|
||||||
# idx = sortperm(y)
|
|
||||||
# y, zmat = y[idx], zmat[:, idx]
|
|
||||||
# end
|
|
||||||
d[:x], d[:y], d[:z] = x, y, Surface{Matrix{TZ}}(zmat)
|
|
||||||
if !like_surface(get(d, :linetype, :none))
|
|
||||||
d[:linetype] = :contour
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# surfaces-like... general x, y grid
|
|
||||||
function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, x::AMat{T}, y::AMat{T}, zmat::AMat{T})
|
|
||||||
@assert size(zmat) == size(x) == size(y)
|
|
||||||
# d[:x], d[:y], d[:z] = Any[x], Any[y], Surface{Matrix{Float64}}(zmat)
|
|
||||||
d[:x], d[:y], d[:z] = map(Surface{Matrix{Float64}}, (x, y, zmat))
|
|
||||||
if !like_surface(get(d, :linetype, :none))
|
|
||||||
d[:linetype] = :contour
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# Parametric functions
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
# special handling... xmin/xmax with function(s)
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, xmin::Number, xmax::Number)
|
|
||||||
width = get(plt.plotargs, :size, (100,))[1]
|
|
||||||
x = linspace(xmin, xmax, width)
|
|
||||||
process_inputs(plt, d, x, f)
|
|
||||||
end
|
|
||||||
|
|
||||||
# special handling... xmin/xmax with parametric function(s)
|
|
||||||
process_inputs{T<:Number}(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u))
|
|
||||||
process_inputs{T<:Number}(plt::AbstractPlot, d::KW, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u))
|
|
||||||
process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, linspace(umin, umax, numPoints))
|
|
||||||
|
|
||||||
# special handling... 3D parametric function(s)
|
|
||||||
process_inputs{T<:Number}(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u))
|
|
||||||
process_inputs{T<:Number}(plt::AbstractPlot, d::KW, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u))
|
|
||||||
process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, fz, linspace(umin, umax, numPoints))
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# Lists of tuples and FixedSizeArrays
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
# if we get an unhandled tuple, just splat it in
|
|
||||||
function process_inputs(plt::AbstractPlot, d::KW, tup::Tuple)
|
|
||||||
process_inputs(plt, d, tup...)
|
|
||||||
end
|
|
||||||
|
|
||||||
# (x,y) tuples
|
|
||||||
function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::AVec{Tuple{R1,R2}})
|
|
||||||
process_inputs(plt, d, unzip(xy)...)
|
|
||||||
end
|
|
||||||
function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::Tuple{R1,R2})
|
|
||||||
process_inputs(plt, d, [xy[1]], [xy[2]])
|
|
||||||
end
|
|
||||||
|
|
||||||
# (x,y,z) tuples
|
|
||||||
function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{Tuple{R1,R2,R3}})
|
|
||||||
process_inputs(plt, d, unzip(xyz)...)
|
|
||||||
end
|
|
||||||
function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::Tuple{R1,R2,R3})
|
|
||||||
process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]])
|
|
||||||
end
|
|
||||||
|
|
||||||
# 2D FixedSizeArrays
|
|
||||||
function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::AVec{FixedSizeArrays.Vec{2,T}})
|
|
||||||
process_inputs(plt, d, unzip(xy)...)
|
|
||||||
end
|
|
||||||
function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::FixedSizeArrays.Vec{2,T})
|
|
||||||
process_inputs(plt, d, [xy[1]], [xy[2]])
|
|
||||||
end
|
|
||||||
|
|
||||||
# 3D FixedSizeArrays
|
|
||||||
function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{FixedSizeArrays.Vec{3,T}})
|
|
||||||
process_inputs(plt, d, unzip(xyz)...)
|
|
||||||
end
|
|
||||||
function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::FixedSizeArrays.Vec{3,T})
|
|
||||||
process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]])
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# handle grouping
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
# function process_inputs(plt::AbstractPlot, d::KW, groupby::GroupBy, args...)
|
|
||||||
# ret = Any[]
|
|
||||||
# error("unfinished after series reorg")
|
|
||||||
# for (i,glab) in enumerate(groupby.groupLabels)
|
|
||||||
# # TODO: don't automatically overwrite labels
|
|
||||||
# kwlist, xmeta, ymeta = process_inputs(plt, d, args...,
|
|
||||||
# idxfilter = groupby.groupIds[i],
|
|
||||||
# label = string(glab),
|
|
||||||
# numUncounted = length(ret)) # we count the idx from plt.n + numUncounted + i
|
|
||||||
# append!(ret, kwlist)
|
|
||||||
# end
|
# end
|
||||||
# ret, nothing, nothing # TODO: handle passing meta through
|
#
|
||||||
|
# xs, xmeta = convertToAnyVector(x, kw)
|
||||||
|
# ys, ymeta = convertToAnyVector(y, kw)
|
||||||
|
# zs, zmeta = convertToAnyVector(z, kw)
|
||||||
|
#
|
||||||
|
# fr = pop!(kw, :fillrange, nothing)
|
||||||
|
# fillranges, _ = if typeof(fr) <: Number
|
||||||
|
# ([fr],nothing)
|
||||||
|
# else
|
||||||
|
# convertToAnyVector(fr, kw)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# mx = length(xs)
|
||||||
|
# my = length(ys)
|
||||||
|
# mz = length(zs)
|
||||||
|
# ret = Any[]
|
||||||
|
# for i in 1:max(mx, my, mz)
|
||||||
|
#
|
||||||
|
# # try to set labels using ymeta
|
||||||
|
# d = copy(kw)
|
||||||
|
# if !haskey(d, :label) && ymeta != nothing
|
||||||
|
# if isa(ymeta, Symbol)
|
||||||
|
# d[:label] = string(ymeta)
|
||||||
|
# elseif isa(ymeta, AVec{Symbol})
|
||||||
|
# d[:label] = string(ymeta[mod1(i,length(ymeta))])
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # build the series arg dict
|
||||||
|
# numUncounted = pop!(d, :numUncounted, 0)
|
||||||
|
# commandIndex = i + numUncounted
|
||||||
|
# n = plt.n + i
|
||||||
|
#
|
||||||
|
# dumpdict(d, "before getSeriesArgs")
|
||||||
|
# d = getSeriesArgs(plt.backend, getplotargs(plt, n), d, commandIndex, convertSeriesIndex(plt, n), n)
|
||||||
|
# dumpdict(d, "after getSeriesArgs")
|
||||||
|
#
|
||||||
|
# d[:x], d[:y], d[:z] = compute_xyz(xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)])
|
||||||
|
# lt = d[:linetype]
|
||||||
|
#
|
||||||
|
# # for linetype `line`, need to sort by x values
|
||||||
|
# if lt == :line
|
||||||
|
# # order by x
|
||||||
|
# indices = sortperm(d[:x])
|
||||||
|
# d[:x] = d[:x][indices]
|
||||||
|
# d[:y] = d[:y][indices]
|
||||||
|
# d[:linetype] = :path
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # special handling for missing x in box plot... all the same category
|
||||||
|
# if lt == :box && xs[mod1(i,mx)] == nothing
|
||||||
|
# d[:x] = ones(Int, length(d[:y]))
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # map functions to vectors
|
||||||
|
# if isa(d[:marker_z], Function)
|
||||||
|
# d[:marker_z] = map(d[:marker_z], d[:x])
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # @show fillranges
|
||||||
|
# d[:fillrange] = fillranges[mod1(i,length(fillranges))]
|
||||||
|
# if isa(d[:fillrange], Function)
|
||||||
|
# d[:fillrange] = map(d[:fillrange], d[:x])
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # handle error bars
|
||||||
|
# for esym in (:xerror, :yerror)
|
||||||
|
# if get(d, esym, nothing) != nothing
|
||||||
|
# # we make a copy of the KW and apply an errorbar recipe
|
||||||
|
# append!(ret, apply_series_recipe(copy(d), Val{esym}))
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # handle ribbons
|
||||||
|
# if get(d, :ribbon, nothing) != nothing
|
||||||
|
# rib = d[:ribbon]
|
||||||
|
# d[:fillrange] = (d[:y] - rib, d[:y] + rib)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # handle quiver plots
|
||||||
|
# # either a series of velocity vectors are passed in (`:quiver` keyword),
|
||||||
|
# # or we just add arrows to the path
|
||||||
|
#
|
||||||
|
# # if lt == :quiver
|
||||||
|
# # d[:linetype] = lt = :path
|
||||||
|
# # d[:linewidth] = 0
|
||||||
|
# # end
|
||||||
|
# if get(d, :quiver, nothing) != nothing
|
||||||
|
# append!(ret, apply_series_recipe(copy(d), Val{:quiver}))
|
||||||
|
# elseif lt == :quiver
|
||||||
|
# d[:linetype] = lt = :path
|
||||||
|
# d[:arrow] = arrow()
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # now that we've processed a given series... optionally split into
|
||||||
|
# # multiple dicts through a recipe (for example, a box plot is split into component
|
||||||
|
# # parts... polygons, lines, and scatters)
|
||||||
|
# # note: we pass in a Val type (i.e. Val{:box}) so that we can dispatch on the linetype
|
||||||
|
# kwlist = apply_series_recipe(d, Val{lt})
|
||||||
|
# append!(ret, kwlist)
|
||||||
|
#
|
||||||
|
# # # add it to our series list
|
||||||
|
# # push!(ret, d)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# ret, xmeta, ymeta
|
||||||
# end
|
# end
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # process_inputs
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# # These methods take a plot and the keyword arguments, and processes the input
|
||||||
|
# # arguments (x/y/z, group, etc), populating the KW dict with appropriate values.
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # 0 arguments
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# # don't do anything
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # 1 argument
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, n::Integer)
|
||||||
|
# # d[:x], d[:y], d[:z] = zeros(0), zeros(0), zeros(0)
|
||||||
|
# d[:x] = d[:y] = d[:z] = n
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # no special handling... assume x and z are nothing
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, y)
|
||||||
|
# d[:y] = y
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # matrix... is it z or y?
|
||||||
|
# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, mat::AMat{T})
|
||||||
|
# if all3D(d)
|
||||||
|
# n,m = size(mat)
|
||||||
|
# d[:x], d[:y], d[:z] = 1:n, 1:m, mat
|
||||||
|
# else
|
||||||
|
# d[:y] = mat
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # images - grays
|
||||||
|
# function process_inputs{T<:Gray}(plt::AbstractPlot, d::KW, mat::AMat{T})
|
||||||
|
# d[:linetype] = :image
|
||||||
|
# n,m = size(mat)
|
||||||
|
# d[:x], d[:y], d[:z] = 1:n, 1:m, Surface(mat)
|
||||||
|
# # handle images... when not supported natively, do a hack to use heatmap machinery
|
||||||
|
# if !nativeImagesSupported()
|
||||||
|
# d[:linetype] = :heatmap
|
||||||
|
# d[:yflip] = true
|
||||||
|
# d[:z] = Surface(convert(Matrix{Float64}, mat.surf))
|
||||||
|
# d[:fillcolor] = ColorGradient([:black, :white])
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # images - colors
|
||||||
|
# function process_inputs{T<:Colorant}(plt::AbstractPlot, d::KW, mat::AMat{T})
|
||||||
|
# d[:linetype] = :image
|
||||||
|
# n,m = size(mat)
|
||||||
|
# d[:x], d[:y], d[:z] = 1:n, 1:m, Surface(mat)
|
||||||
|
# # handle images... when not supported natively, do a hack to use heatmap machinery
|
||||||
|
# if !nativeImagesSupported()
|
||||||
|
# d[:yflip] = true
|
||||||
|
# imageHack(d)
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# # plotting arbitrary shapes/polygons
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, shape::Shape)
|
||||||
|
# d[:x], d[:y] = shape_coords(shape)
|
||||||
|
# d[:linetype] = :shape
|
||||||
|
# end
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, shapes::AVec{Shape})
|
||||||
|
# d[:x], d[:y] = shape_coords(shapes)
|
||||||
|
# d[:linetype] = :shape
|
||||||
|
# end
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, shapes::AMat{Shape})
|
||||||
|
# x, y = [], []
|
||||||
|
# for j in 1:size(shapes, 2)
|
||||||
|
# tmpx, tmpy = shape_coords(vec(shapes[:,j]))
|
||||||
|
# push!(x, tmpx)
|
||||||
|
# push!(y, tmpy)
|
||||||
|
# end
|
||||||
|
# d[:x], d[:y] = x, y
|
||||||
|
# d[:linetype] = :shape
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# # function without range... use the current range of the x-axis
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs)
|
||||||
|
# process_inputs(plt, d, f, xmin(plt), xmax(plt))
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # 2 arguments
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, x, y)
|
||||||
|
# d[:x], d[:y] = x, y
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # if functions come first, just swap the order (not to be confused with parametric functions...
|
||||||
|
# # as there would be more than one function passed in)
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, x)
|
||||||
|
# @assert !(typeof(x) <: FuncOrFuncs) # otherwise we'd hit infinite recursion here
|
||||||
|
# process_inputs(plt, d, x, f)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # 3 arguments
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# # no special handling... just pass them through
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, x, y, z)
|
||||||
|
# d[:x], d[:y], d[:z] = x, y, z
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # 3d line or scatter
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zvec::AVec)
|
||||||
|
# # default to path3d if we haven't set a 3d linetype
|
||||||
|
# lt = get(d, :linetype, :none)
|
||||||
|
# if lt == :scatter
|
||||||
|
# d[:linetype] = :scatter3d
|
||||||
|
# elseif !(lt in _3dTypes)
|
||||||
|
# d[:linetype] = :path3d
|
||||||
|
# end
|
||||||
|
# d[:x], d[:y], d[:z] = x, y, zvec
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # surface-like... function
|
||||||
|
# function process_inputs{TX,TY}(plt::AbstractPlot, d::KW, x::AVec{TX}, y::AVec{TY}, zf::Function)
|
||||||
|
# x = TX <: Number ? sort(x) : x
|
||||||
|
# y = TY <: Number ? sort(y) : y
|
||||||
|
# # x, y = sort(x), sort(y)
|
||||||
|
# d[:z] = Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported
|
||||||
|
# d[:x], d[:y] = x, y
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # surface-like... matrix grid
|
||||||
|
# function process_inputs{TX,TY,TZ}(plt::AbstractPlot, d::KW, x::AVec{TX}, y::AVec{TY}, zmat::AMat{TZ})
|
||||||
|
# # @assert size(zmat) == (length(x), length(y))
|
||||||
|
# # if TX <: Number && !issorted(x)
|
||||||
|
# # idx = sortperm(x)
|
||||||
|
# # x, zmat = x[idx], zmat[idx, :]
|
||||||
|
# # end
|
||||||
|
# # if TY <: Number && !issorted(y)
|
||||||
|
# # idx = sortperm(y)
|
||||||
|
# # y, zmat = y[idx], zmat[:, idx]
|
||||||
|
# # end
|
||||||
|
# d[:x], d[:y], d[:z] = x, y, Surface{Matrix{TZ}}(zmat)
|
||||||
|
# if !like_surface(get(d, :linetype, :none))
|
||||||
|
# d[:linetype] = :contour
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # surfaces-like... general x, y grid
|
||||||
|
# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, x::AMat{T}, y::AMat{T}, zmat::AMat{T})
|
||||||
|
# @assert size(zmat) == size(x) == size(y)
|
||||||
|
# # d[:x], d[:y], d[:z] = Any[x], Any[y], Surface{Matrix{Float64}}(zmat)
|
||||||
|
# d[:x], d[:y], d[:z] = map(Surface{Matrix{Float64}}, (x, y, zmat))
|
||||||
|
# if !like_surface(get(d, :linetype, :none))
|
||||||
|
# d[:linetype] = :contour
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # Parametric functions
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# # special handling... xmin/xmax with function(s)
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, xmin::Number, xmax::Number)
|
||||||
|
# width = get(plt.plotargs, :size, (100,))[1]
|
||||||
|
# x = linspace(xmin, xmax, width)
|
||||||
|
# process_inputs(plt, d, x, f)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # special handling... xmin/xmax with parametric function(s)
|
||||||
|
# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u))
|
||||||
|
# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u))
|
||||||
|
# process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, linspace(umin, umax, numPoints))
|
||||||
|
#
|
||||||
|
# # special handling... 3D parametric function(s)
|
||||||
|
# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u))
|
||||||
|
# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u))
|
||||||
|
# process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, fz, linspace(umin, umax, numPoints))
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # Lists of tuples and FixedSizeArrays
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# # if we get an unhandled tuple, just splat it in
|
||||||
|
# function process_inputs(plt::AbstractPlot, d::KW, tup::Tuple)
|
||||||
|
# process_inputs(plt, d, tup...)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # (x,y) tuples
|
||||||
|
# function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::AVec{Tuple{R1,R2}})
|
||||||
|
# process_inputs(plt, d, unzip(xy)...)
|
||||||
|
# end
|
||||||
|
# function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::Tuple{R1,R2})
|
||||||
|
# process_inputs(plt, d, [xy[1]], [xy[2]])
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # (x,y,z) tuples
|
||||||
|
# function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{Tuple{R1,R2,R3}})
|
||||||
|
# process_inputs(plt, d, unzip(xyz)...)
|
||||||
|
# end
|
||||||
|
# function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::Tuple{R1,R2,R3})
|
||||||
|
# process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]])
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # 2D FixedSizeArrays
|
||||||
|
# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::AVec{FixedSizeArrays.Vec{2,T}})
|
||||||
|
# process_inputs(plt, d, unzip(xy)...)
|
||||||
|
# end
|
||||||
|
# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::FixedSizeArrays.Vec{2,T})
|
||||||
|
# process_inputs(plt, d, [xy[1]], [xy[2]])
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # 3D FixedSizeArrays
|
||||||
|
# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{FixedSizeArrays.Vec{3,T}})
|
||||||
|
# process_inputs(plt, d, unzip(xyz)...)
|
||||||
|
# end
|
||||||
|
# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::FixedSizeArrays.Vec{3,T})
|
||||||
|
# process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]])
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
# # handle grouping
|
||||||
|
# # --------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# # function process_inputs(plt::AbstractPlot, d::KW, groupby::GroupBy, args...)
|
||||||
|
# # ret = Any[]
|
||||||
|
# # error("unfinished after series reorg")
|
||||||
|
# # for (i,glab) in enumerate(groupby.groupLabels)
|
||||||
|
# # # TODO: don't automatically overwrite labels
|
||||||
|
# # kwlist, xmeta, ymeta = process_inputs(plt, d, args...,
|
||||||
|
# # idxfilter = groupby.groupIds[i],
|
||||||
|
# # label = string(glab),
|
||||||
|
# # numUncounted = length(ret)) # we count the idx from plt.n + numUncounted + i
|
||||||
|
# # append!(ret, kwlist)
|
||||||
|
# # end
|
||||||
|
# # ret, nothing, nothing # TODO: handle passing meta through
|
||||||
|
# # end
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# For DataFrame support. Imports DataFrames and defines the necessary methods which support them.
|
# For DataFrame support. Imports DataFrames and defines the necessary methods which support them.
|
||||||
|
|||||||
@ -87,17 +87,47 @@ end
|
|||||||
|
|
||||||
# instead of process_inputs:
|
# instead of process_inputs:
|
||||||
|
|
||||||
|
# the catch-all recipes
|
||||||
|
@recipe function f(x, y, z)
|
||||||
|
@show "HERE", typeof((x,y,z))
|
||||||
|
xs, _ = convertToAnyVector(x, d)
|
||||||
|
ys, _ = convertToAnyVector(y, d)
|
||||||
|
zs, _ = convertToAnyVector(z, d)
|
||||||
|
|
||||||
@recipe function f{Y<:Number}(y::AVec{Y})
|
fr = pop!(d, :fillrange, nothing)
|
||||||
x --> 1:length(y)
|
fillranges, _ = if typeof(fr) <: Number
|
||||||
y --> y
|
([fr],nothing)
|
||||||
dumpdict(d,"y",true)
|
else
|
||||||
()
|
convertToAnyVector(fr, d)
|
||||||
|
end
|
||||||
|
|
||||||
|
mx = length(xs)
|
||||||
|
my = length(ys)
|
||||||
|
mz = length(zs)
|
||||||
|
# ret = Any[]
|
||||||
|
for i in 1:max(mx, my, mz)
|
||||||
|
# add a new series
|
||||||
|
di = copy(d)
|
||||||
|
di[:x], di[:y], di[:z] = compute_xyz(xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)])
|
||||||
|
@show i, di[:x], di[:y], di[:z]
|
||||||
|
push!(series_list, RecipeData(di, ()))
|
||||||
|
end
|
||||||
|
nothing # don't add a series for the main block
|
||||||
end
|
end
|
||||||
|
|
||||||
@recipe function f{X<:Number,Y<:Number}(x::AVec{X}, y::AVec{Y})
|
@recipe f(x, y) = x, y, nothing
|
||||||
x --> x
|
@recipe f(y) = nothing, y, nothing
|
||||||
y --> y
|
|
||||||
dumpdict(d,"xy",true)
|
# @recipe function f{Y<:Number}(y::AVec{Y})
|
||||||
()
|
# x --> 1:length(y)
|
||||||
end
|
# y --> y
|
||||||
|
# dumpdict(d,"y",true)
|
||||||
|
# ()
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @recipe function f{X<:Number,Y<:Number}(x::AVec{X}, y::AVec{Y})
|
||||||
|
# x --> x
|
||||||
|
# y --> y
|
||||||
|
# dumpdict(d,"xy",true)
|
||||||
|
# ()
|
||||||
|
# end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user