big shapes overhaul; gadfly ShapeGeometry; some reorg and cleanup... still working on it

This commit is contained in:
Thomas Breloff 2015-10-14 18:14:44 -04:00
parent 027961bffa
commit 4fa697ec75
17 changed files with 988 additions and 304 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -37,8 +37,6 @@ export
ohlc,
ohlc!,
spy,
title!,
xlabel!,
ylabel!,
@ -60,6 +58,8 @@ export
backends,
aliases,
dataframes,
Shape,
OHLC,
colorscheme,
@ -84,6 +84,7 @@ export
# recipes
PlotRecipe,
EllipseRecipe,
spy,
corrplot
# ---------------------------------------------------------
@ -123,11 +124,6 @@ vline!(args...; kw...) = plot!(args...; kw..., linetype = :vline)
ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
"Sparsity plot... heatmap of non-zero values of a matrix"
function spy{T<:Real}(y::AMat{T}; kw...)
I,J,V = findnz(y)
heatmap(J, I; leg=false, yflip=true, kw...)
end
title!(s::@compat(AbstractString)) = plot!(title = s)
xlabel!(s::@compat(AbstractString)) = plot!(xlabel = s)

View File

@ -38,7 +38,7 @@ const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
)
const _allMarkers = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle,
:cross, :xcross, :star1, :star2, :hexagon, :octagon]
:cross, :xcross, :star1, :star2, :hexagon, :octagon, Shape]
@compat const _markerAliases = Dict(
:n => :none,
:no => :none,
@ -515,10 +515,17 @@ end
function warnOnUnsupported(pkg::PlottingPackage, d::Dict)
d[:axis] in supportedAxes(pkg) || warn("axis $(d[:axis]) is unsupported with $pkg. Choose from: $(supportedAxes(pkg))")
d[:linetype] == :none || d[:linetype] in supportedTypes(pkg) || warn("linetype $(d[:linetype]) is unsupported with $pkg. Choose from: $(supportedTypes(pkg))")
d[:linestyle] in supportedStyles(pkg) || warn("linestyle $(d[:linestyle]) is unsupported with $pkg. Choose from: $(supportedStyles(pkg))")
d[:markershape] == :none || d[:markershape] in supportedMarkers(pkg) || warn("markershape $(d[:markershape]) is unsupported with $pkg. Choose from: $(supportedMarkers(pkg))")
(d[:axis] in supportedAxes(pkg)
|| warn("axis $(d[:axis]) is unsupported with $pkg. Choose from: $(supportedAxes(pkg))"))
(d[:linetype] == :none
|| d[:linetype] in supportedTypes(pkg)
|| warn("linetype $(d[:linetype]) is unsupported with $pkg. Choose from: $(supportedTypes(pkg))"))
(d[:linestyle] in supportedStyles(pkg)
|| warn("linestyle $(d[:linestyle]) is unsupported with $pkg. Choose from: $(supportedStyles(pkg))"))
(d[:markershape] == :none
|| d[:markershape] in supportedMarkers(pkg)
|| typeof(d[:markershape]) in supportedMarkers(pkg)
|| warn("markershape $(d[:markershape]) is unsupported with $pkg. Choose from: $(supportedMarkers(pkg))"))
end
function warnOnUnsupportedScales(pkg::PlottingPackage, d::Dict)

View File

@ -1,10 +1,10 @@
# https://github.com/dcjones/Gadfly.jl
immutable GadflyPackage <: PlottingPackage end
# immutable GadflyPackage <: PlottingPackage end
export gadfly
gadfly() = backend(:gadfly)
# export gadfly
# gadfly() = backend(:gadfly)
# supportedArgs(::GadflyPackage) = setdiff(_allArgs, [:heatmap_c, :pos, :screen, :yrightlabel])
@ -60,11 +60,11 @@ supportedArgs(::GadflyPackage) = [
supportedAxes(::GadflyPackage) = [:auto, :left]
supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc]
supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GadflyPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon, :octagon]
supportedMarkers(::GadflyPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon, :octagon, Shape]
supportedScales(::GadflyPackage) = [:identity, :log, :log2, :log10, :asinh, :sqrt]
include("gadfly_shapes.jl")
# include("gadfly_shapes.jl")
function createGadflyPlotObject(d::Dict)
@eval import DataFrames
@ -115,7 +115,8 @@ function getLineGeoms(d::Dict)
# NOTE: we won't actually show this (we'll set linewidth to 0 later), but we need a geom so that Gadfly doesn't complain
if lt in (:none, :ohlc, :scatter)
return [Gadfly.Geom.path]
# return [Gadfly.Geom.path]
return Any[]
end
# lt == :sticks && return [Gadfly.Geom.bar]
@ -126,13 +127,32 @@ end
# serious hack (I think?) to draw my own shapes as annotations... will it work? who knows...
function getMarkerGeomsAndGuides(d::Dict, initargs::Dict)
marker = d[:markershape]
if marker == :none && d[:linetype] != :ohlc
return Any[], Any[]
end
return Any[], [createGadflyAnnotation(d, initargs)]
return Any[], Any[] # don't do this step anymore
# marker = d[:markershape]
# if marker == :none && d[:linetype] != :ohlc
# return Any[], Any[]
# elseif marker == :diamond
# geom = DIAMOND
# @show geom
# return Any[geom], Any[]
# else
# return Any[], [createGadflyAnnotation(d, initargs)]
# end
end
function getMarkerGeoms(d::Dict)
shape = d[:markershape]
isa(shape, Shape) && return [gadflyshape(shape)]
shape == :none && return Any[]
shape == :ellipse && return [Gadfly.Geom.point]
shape == :rect && return [gadflyshape(_square)]
shape == :diamond && return [gadflyshape(_diamond)]
shape == :cross && return [gadflyshape(_cross)]
error("unhandled marker: ", shape)
end
function addGadflyFixedLines!(gplt, d::Dict, theme)
@ -206,16 +226,18 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
if d[:linetype] == :scatter
d[:linetype] = :none
if d[:markershape] in (:none,:ellipse)
push!(gfargs, Gadfly.Geom.point)
d[:markershape] = :none
# if d[:markershape] == :none
# d[:markershape] = :ellipse
end
# if d[:markershape] in (:none,:ellipse)
# push!(gfargs, Gadfly.Geom.point)
# d[:markershape] = :none
# # if d[:markershape] == :none
# # d[:markershape] = :ellipse
# end
end
# add the Geoms
append!(gfargs, getLineGeoms(d))
append!(gfargs, getMarkerGeoms(d))
# colorgroup
z = d[:z]
@ -274,7 +296,9 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
# add a regression line?
if d[:reg]
# TODO: make more flexible
push!(gfargs, Gadfly.Geom.smooth(method=:lm))
# push!(gfargs, Gadfly.Geom.smooth(method=:loess, smoothing=0.95))
end
# add to the legend, but only without the continuous scale

View File

@ -1,283 +1,400 @@
# Geometry which displays arbitrary shapes at given (x, y) positions.
immutable ShapeGeometry <: Gadfly.GeometryElement
vertices::AbstractVector{@compat(Tuple{Float64,Float64})}
tag::Symbol
function ShapeGeometry(shape; tag::Symbol=Gadfly.Geom.empty_tag)
new(shape, tag)
end
end
# TODO: add for PR
# const shape = ShapeGeometry
function Gadfly.element_aesthetics(::ShapeGeometry)
[:x, :y, :size, :color]
end
# Generate a form for a shape geometry.
#
# Args:
# geom: shape geometry.
# theme: the plot's theme.
# aes: aesthetics.
#
# Returns:
# A compose Form.
#
function Gadfly.render(geom::ShapeGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics)
# TODO: add for PR
# Gadfly.assert_aesthetics_defined("Geom.shape", aes, :x, :y)
# Gadfly.assert_aesthetics_equal_length("Geom.shape", aes,
# element_aesthetics(geom)...)
default_aes = Gadfly.Aesthetics()
default_aes.color = Gadfly.DataFrames.PooledDataArray(RGBA{Float32}[theme.default_color])
default_aes.size = Compose.Measure[theme.default_point_size]
aes = Gadfly.inherit(aes, default_aes)
lw_hover_scale = 10
lw_ratio = theme.line_width / aes.size[1]
aes_x, aes_y = Gadfly.concretize(aes.x, aes.y)
ctx = Compose.compose!(
Compose.context(),
# circle(aes.x, aes.y, aes.size, geom.tag),
makeGadflyShapeContext(geom, aes.x, aes.y, aes.size),
Compose.fill(aes.color),
Compose.linewidth(theme.highlight_width))
if aes.color_key_continuous != nothing && aes.color_key_continuous
Compose.compose!(ctx,
Compose.stroke(map(theme.continuous_highlight_color, aes.color)))
else
Compose.compose!(ctx,
Compose.stroke(map(theme.discrete_highlight_color, aes.color)),
Compose.svgclass([Gadfly.svg_color_class_from_label(Gadfly.escape_id(aes.color_label([c])[1]))
for c in aes.color]))
end
return Compose.compose!(Compose.context(order=4), Compose.svgclass("geometry"), ctx)
end
function gadflyshape(sv::Shape)
ShapeGeometry(sv.vertices)
end
# const _square = ShapeGeometry(@compat(Tuple{Float64,Float64})[
# ( 1.0, -1.0),
# ( 1.0, 1.0),
# (-1.0, 1.0),
# (-1.0, -1.0)
# ])
# const _diamond = ShapeGeometry(@compat(Tuple{Float64,Float64})[
# ( 0.0, -1.0),
# ( 1.0, 0.0),
# ( 0.0, 1.0),
# (-1.0, 0.0)
# ])
# const _cross = ShapeGeometry(@compat(Tuple{Float64,Float64})[
# (-1.0, -0.4), (-1.0, 0.4), # L edge
# (-0.4, 0.4), # BL inside
# (-0.4, 1.0), ( 0.4, 1.0), # B edge
# ( 0.4, 0.4), # BR inside
# ( 1.0, 0.4), ( 1.0, -0.4), # R edge
# ( 0.4, -0.4), # TR inside
# ( 0.4, -1.0), (-0.4, -1.0), # T edge
# (-0.4, -0.4) # TL inside
# ])
# create a Compose context given a ShapeGeometry and the xs/ys/sizes
function makeGadflyShapeContext(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
T = @compat(Tuple{Compose.Measure, Compose.Measure})
polys = Array(Vector{T}, n)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
# polys[i] = [(x, y - r), (x + r, y), (x, y + r), (x - r, y)]
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in geom.vertices]
end
Gadfly.polygon(polys, geom.tag)
end
# ---------------------------------------------------------------------------------------------
# Compose pseudo-forms for simple symbols, all parameterized by center and size
# using Compose: x_measure, y_measure
function createGadflyAnnotation(d::Dict, initargs::Dict)
sz = [d[:markersize] * Gadfly.px]
# function createGadflyAnnotation(d::Dict, initargs::Dict)
# sz = [d[:markersize] * Gadfly.px]
x, y = d[:x], d[:y]
marker = d[:markershape]
# x, y = d[:x], d[:y]
# marker = d[:markershape]
if d[:linetype] == :ohlc
shape = ohlcshape(x, y, d[:markersize])
d[:y] = Float64[z.open for z in y]
d[:linetype] = :none
return Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(nothing), Gadfly.stroke(getColor(d[:color]))))
# if d[:linetype] == :ohlc
# shape = ohlcshape(x, y, d[:markersize])
# d[:y] = Float64[z.open for z in y]
# d[:linetype] = :none
# return Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(nothing), Gadfly.stroke(getColor(d[:color]))))
elseif marker == :rect
shape = square(x, y, sz)
# elseif marker == :rect
# shape = square(x, y, sz)
elseif marker == :diamond
shape = diamond(x, y, sz)
# elseif marker == :diamond
# shape = diamond(x, y, sz)
elseif marker == :utriangle
shape = utriangle(x, y, sz)
# elseif marker == :utriangle
# shape = utriangle(x, y, sz)
elseif marker == :dtriangle
shape = utriangle(x, y, sz, -1)
# elseif marker == :dtriangle
# shape = utriangle(x, y, sz, -1)
elseif marker == :cross
shape = cross(x, y, sz)
# elseif marker == :cross
# shape = cross(x, y, sz)
elseif marker == :xcross
shape = xcross(x, y, sz)
# elseif marker == :xcross
# shape = xcross(x, y, sz)
elseif marker == :star1
shape = star1(x, y, sz)
# elseif marker == :star1
# shape = star1(x, y, sz)
elseif marker == :star2
shape = star2(x, y, sz)
# elseif marker == :star2
# shape = star2(x, y, sz)
elseif marker == :hexagon
shape = hexagon(x, y, sz)
# elseif marker == :hexagon
# shape = hexagon(x, y, sz)
elseif marker == :octagon
shape = octagon(x, y, sz)
# elseif marker == :octagon
# shape = octagon(x, y, sz)
else
# make circles
sz = 0.8 * d[:markersize] * Gadfly.px
xs = collect(float(d[:x]))
ys = collect(float(d[:y]))
shape = Gadfly.circle(xs,ys,[sz])
end
# else
# # make circles
# sz = 0.8 * d[:markersize] * Gadfly.px
# xs = collect(float(d[:x]))
# ys = collect(float(d[:y]))
# shape = Gadfly.circle(xs,ys,[sz])
# end
Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(getColorVector(d[:markercolor])), Gadfly.stroke(getColor(initargs[:foreground_color]))))
end
# Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(getColorVector(d[:markercolor])), Gadfly.stroke(getColor(initargs[:foreground_color]))))
# end
function square(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
rect_xs = Array(Compose.Measure, n)
rect_ys = Array(Compose.Measure, n)
rect_ws = Array(Compose.Measure, n)
s = 1/sqrt(2)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
# function square(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# rect_xs = Array(Compose.Measure, n)
# rect_ys = Array(Compose.Measure, n)
# rect_ws = Array(Compose.Measure, n)
# s = 1/sqrt(2)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
rect_xs[i] = x - s*r
rect_ys[i] = y + s*r
rect_ws[i] = 2*s*r
end
# rect_xs[i] = x - s*r
# rect_ys[i] = y + s*r
# rect_ws[i] = 2*s*r
# end
return Gadfly.rectangle(rect_xs, rect_ys, rect_ws, rect_ws)
end
# return Gadfly.rectangle(rect_xs, rect_ys, rect_ws, rect_ws)
# end
function diamond(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
polys[i] = [(x, y - r), (x + r, y), (x, y + r), (x - r, y)]
end
# function diamond(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# polys[i] = [(x, y - r), (x + r, y), (x, y + r), (x - r, y)]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
function cross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
u = 0.4r
# function cross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.4r
# make a "plus sign"
polys[i] = [
(x-r, y-u), (x-r, y+u), # L edge
(x-u, y+u), # BL inside
(x-u, y+r), (x+u, y+r), # B edge
(x+u, y+u), # BR inside
(x+r, y+u), (x+r, y-u), # R edge
(x+u, y-u), # TR inside
(x+u, y-r), (x-u, y-r), # T edge
(x-u, y-u) # TL inside
]
end
# # make a "plus sign"
# polys[i] = [
# (x-r, y-u), (x-r, y+u), # L edge
# (x-u, y+u), # BL inside
# (x-u, y+r), (x+u, y+r), # B edge
# (x+u, y+u), # BR inside
# (x+r, y+u), (x+r, y-u), # R edge
# (x+u, y-u), # TR inside
# (x+u, y-r), (x-u, y-r), # T edge
# (x-u, y-u) # TL inside
# ]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
function xcross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
s = 1/sqrt(5)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
u = s*r
polys[i] = [
(x, y - u), (x + u, y - 2u), (x + 2u, y - u),
(x + u, y), (x + 2u, y + u), (x + u, y + 2u),
(x, y + u), (x - u, y + 2u), (x - 2u, y + u),
(x - u, y), (x - 2u, y - u), (x - u, y - 2u)
]
end
# function xcross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# s = 1/sqrt(5)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = s*r
# polys[i] = [
# (x, y - u), (x + u, y - 2u), (x + 2u, y - u),
# (x + u, y), (x + 2u, y + u), (x + u, y + 2u),
# (x, y + u), (x - u, y + 2u), (x - 2u, y + u),
# (x - u, y), (x - 2u, y - u), (x - u, y - 2u)
# ]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
function utriangle(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
s = 0.8
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
u = 0.8 * scalar * r
polys[i] = [
(x - r, y + u),
(x + r, y + u),
(x, y - u)
]
end
# function utriangle(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# s = 0.8
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.8 * scalar * r
# polys[i] = [
# (x - r, y + u),
# (x + r, y + u),
# (x, y - u)
# ]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
function star1(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# function star1(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# some magic scalars
sx1, sx2, sx3 = 0.7, 0.4, 0.2
sy1, sy2, sy3 = 1.2, 0.45, 0.1
# # some magic scalars
# sx1, sx2, sx3 = 0.7, 0.4, 0.2
# sy1, sy2, sy3 = 1.2, 0.45, 0.1
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
polys[i] = [
(x-sx1*r, y+ r), # BL
(x, y+sy2*r),
(x+sx1*r, y+ r), # BR
(x+sx2*r, y+sy3*r),
(x+ r, y-sy2*r), # R
(x+sx3*r, y-sy2*r),
(x, y-sy1*r), # T
(x-sx3*r, y-sy2*r),
(x- r, y-sy2*r), # L
(x-sx2*r, y+sy3*r)
]
end
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# polys[i] = [
# (x-sx1*r, y+ r), # BL
# (x, y+sy2*r),
# (x+sx1*r, y+ r), # BR
# (x+sx2*r, y+sy3*r),
# (x+ r, y-sy2*r), # R
# (x+sx3*r, y-sy2*r),
# (x, y-sy1*r), # T
# (x-sx3*r, y-sy2*r),
# (x- r, y-sy2*r), # L
# (x-sx2*r, y+sy3*r)
# ]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
function star2(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
u = 0.4r
polys[i] = [
(x-u, y), (x-r, y-r), # TL
(x, y-u), (x+r, y-r), # TR
(x+u, y), (x+r, y+r), # BR
(x, y+u), (x-r, y+r) # BL
]
end
# function star2(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.4r
# polys[i] = [
# (x-u, y), (x-r, y-r), # TL
# (x, y-u), (x+r, y-r), # TR
# (x+u, y), (x+r, y+r), # BR
# (x, y+u), (x-r, y+r) # BL
# ]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
function hexagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
# function hexagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
u = 0.6r
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.6r
polys[i] = [
(x-r, y-u), (x-r, y+u), # L edge
(x, y+r), # B
(x+r, y+u), (x+r, y-u), # R edge
(x, y-r) # T
]
end
# polys[i] = [
# (x-r, y-u), (x-r, y+u), # L edge
# (x, y+r), # B
# (x+r, y+u), (x+r, y-u), # R edge
# (x, y-r) # T
# ]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
function octagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
n = max(length(xs), length(ys), length(rs))
# function octagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
u = 0.4r
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.4r
polys[i] = [
(x-r, y-u), (x-r, y+u), # L edge
(x-u, y+r), (x+u, y+r), # B edge
(x+r, y+u), (x+r, y-u), # R edge
(x+u, y-r), (x-u, y-r), # T edge
]
end
# polys[i] = [
# (x-r, y-u), (x-r, y+u), # L edge
# (x-u, y+r), (x+u, y+r), # B edge
# (x+r, y+u), (x+r, y-u), # R edge
# (x+u, y-r), (x-u, y-r), # T edge
# ]
# end
return Gadfly.polygon(polys)
end
# return Gadfly.polygon(polys)
# end
# ---------------------------
# # ---------------------------
function ohlcshape(xs::AVec, ys::AVec{OHLC}, tickwidth::Real)
@assert length(xs) == length(ys)
n = length(xs)
u = tickwidth * Compose.px
polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
for i in 1:n
x = Compose.x_measure(xs[i])
o = Compose.y_measure(ys[i].open)
h = Compose.y_measure(ys[i].high)
l = Compose.y_measure(ys[i].low)
c = Compose.y_measure(ys[i].close)
# o,h,l,c = map(Compose.y_measure, ys[i])
polys[i] = [
(x, o), (x - u, o), (x, o), # open tick
(x, l), (x, h), (x, c), # high/low bar
(x + u, c), (x, c) # close tick
]
end
return Gadfly.polygon(polys)
end
# function ohlcshape(xs::AVec, ys::AVec{OHLC}, tickwidth::Real)
# @assert length(xs) == length(ys)
# n = length(xs)
# u = tickwidth * Compose.px
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[i])
# o = Compose.y_measure(ys[i].open)
# h = Compose.y_measure(ys[i].high)
# l = Compose.y_measure(ys[i].low)
# c = Compose.y_measure(ys[i].close)
# # o,h,l,c = map(Compose.y_measure, ys[i])
# polys[i] = [
# (x, o), (x - u, o), (x, o), # open tick
# (x, l), (x, h), (x, c), # high/low bar
# (x + u, c), (x, c) # close tick
# ]
# end
# return Gadfly.polygon(polys)
# end

View File

@ -1,10 +1,10 @@
# https://github.com/JuliaGraphics/Immerse.jl
immutable ImmersePackage <: PlottingPackage end
# immutable ImmersePackage <: PlottingPackage end
export immerse
immerse() = backend(:immerse)
# export immerse
# immerse() = backend(:immerse)
supportedArgs(::ImmersePackage) = supportedArgs(GadflyPackage())

View File

@ -1,10 +1,10 @@
# https://github.com/stevengj/PyPlot.jl
immutable PyPlotPackage <: PlottingPackage end
# immutable PyPlotPackage <: PlottingPackage end
export pyplot
pyplot() = backend(:pyplot)
# export pyplot
# pyplot() = backend(:pyplot)
# -------------------------------

View File

@ -1,10 +1,10 @@
# https://github.com/tbreloff/Qwt.jl
immutable QwtPackage <: PlottingPackage end
# immutable QwtPackage <: PlottingPackage end
export qwt
qwt() = backend(:qwt)
# export qwt
# qwt() = backend(:qwt)
# supportedArgs(::QwtPackage) = setdiff(_allArgs, [:xlims, :ylims, :xticks, :yticks])
supportedArgs(::QwtPackage) = [

View File

@ -3,11 +3,6 @@
# [WEBSITE]
immutable [PkgName]Package <: PlottingPackage end
export [pkgname]
[pkgname]() = backend(:[pkgname])
# ---------------------------------------------------------------------------
# supportedArgs(::[PkgName]Package) = _allArgs

View File

@ -1,10 +1,10 @@
# https://github.com/Evizero/UnicodePlots.jl
immutable UnicodePlotsPackage <: PlottingPackage end
# immutable UnicodePlotsPackage <: PlottingPackage end
export unicodeplots
unicodeplots() = backend(:unicodeplots)
# export unicodeplots
# unicodeplots() = backend(:unicodeplots)
# -------------------------------

View File

@ -3,10 +3,10 @@
# credit goes to https://github.com/jverzani for contributing to the first draft of this backend implementation
immutable WinstonPackage <: PlottingPackage end
# immutable WinstonPackage <: PlottingPackage end
export winston
winston() = backend(:winston)
# export winston
# winston() = backend(:winston)
# ---------------------------------------------------------------------------

View File

@ -1,5 +1,28 @@
immutable GadflyPackage <: PlottingPackage end
immutable ImmersePackage <: PlottingPackage end
immutable PyPlotPackage <: PlottingPackage end
immutable QwtPackage <: PlottingPackage end
immutable UnicodePlotsPackage <: PlottingPackage end
immutable WinstonPackage <: PlottingPackage end
export
gadfly,
immerse,
pyplot,
qwt,
unicodeplots,
winston
gadfly() = backend(:gadfly)
immerse() = backend(:immerse)
pyplot() = backend(:pyplot)
qwt() = backend(:qwt)
unicodeplots() = backend(:unicodeplots)
winston() = backend(:winston)
include("backends/qwt.jl")
include("backends/gadfly.jl")
include("backends/unicodeplots.jl")
@ -109,6 +132,7 @@ function backend()
try
@eval import Gadfly, Compose
@eval export Gadfly, Compose
@eval include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
catch err
error("Couldn't import Gadfly. Install it with: Pkg.add(\"Gadfly\").\n Error: ", err)
end
@ -137,6 +161,7 @@ function backend()
try
@eval import Immerse, Gadfly, Compose, Gtk
@eval export Immerse, Gadfly, Compose, Gtk
@eval include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
catch err
error("Couldn't import Immerse. Install it with: Pkg.add(\"Immerse\").\n Error: ", err)
end

View File

@ -57,7 +57,7 @@ end
# -------------------------------------------------
"Do a correlation plot"
"Correlation scatter matrix"
function corrplot{T<:Real,S<:Real}(mat::AMat{T}, corrmat::AMat{S} = cor(mat);
colors = :redsblues,
labels = nothing, kw...)
@ -105,3 +105,10 @@ function corrplot{T<:Real,S<:Real}(mat::AMat{T}, corrmat::AMat{S} = cor(mat);
subplot!(p, link = (r,c) -> (true, r!=c))
end
"Sparsity plot... heatmap of non-zero values of a matrix"
function spy{T<:Real}(y::AMat{T}; kw...)
I,J,V = findnz(y)
heatmap(J, I; leg=false, yflip=true, kw...)
end

View File

@ -45,7 +45,215 @@ type Subplot{T<:PlottingPackage, L<:SubplotLayout} <: PlottingObject{T}
linkfunc::Function # maps (row,column) -> (BoolOrNothing, BoolOrNothing)... if xlink/ylink are nothing, then use subplt.linkx/y
end
# -----------------------------------------------------------------------
immutable Shape
vertices::AVec
end
const _square = Shape(@compat(Tuple{Float64,Float64})[
( 1.0, -1.0),
( 1.0, 1.0),
(-1.0, 1.0),
(-1.0, -1.0)
])
const _diamond = Shape(@compat(Tuple{Float64,Float64})[
( 0.0, -1.0),
( 1.0, 0.0),
( 0.0, 1.0),
(-1.0, 0.0)
])
const _cross = Shape(@compat(Tuple{Float64,Float64})[
(-1.0, -0.4), (-1.0, 0.4), # L edge
(-0.4, 0.4), # BL inside
(-0.4, 1.0), ( 0.4, 1.0), # B edge
( 0.4, 0.4), # BR inside
( 1.0, 0.4), ( 1.0, -0.4), # R edge
( 0.4, -0.4), # TR inside
( 0.4, -1.0), (-0.4, -1.0), # T edge
(-0.4, -0.4) # TL inside
])
const _xcross = Shape(@compat(Tuple{Float64,Float64})[
(x, y - u), (x + u, y - 2u), (x + 2u, y - u),
(x + u, y), (x + 2u, y + u), (x + u, y + 2u),
(x, y + u), (x - u, y + 2u), (x - 2u, y + u),
(x - u, y), (x - 2u, y - u), (x - u, y - 2u)
]
# function xcross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# s = 1/sqrt(5)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = s*r
# polys[i] = [
# (x, y - u), (x + u, y - 2u), (x + 2u, y - u),
# (x + u, y), (x + 2u, y + u), (x + u, y + 2u),
# (x, y + u), (x - u, y + 2u), (x - 2u, y + u),
# (x - u, y), (x - 2u, y - u), (x - u, y - 2u)
# ]
# end
# return Gadfly.polygon(polys)
# end
const _utriangle = Shape(@compat(Tuple{Float64,Float64})[
(x - r, y + u),
(x + r, y + u),
(x, y - u)
]
# function utriangle(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# s = 0.8
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.8 * scalar * r
# polys[i] = [
# (x - r, y + u),
# (x + r, y + u),
# (x, y - u)
# ]
# end
# return Gadfly.polygon(polys)
# end
"get an array of tuples of points on a circle with radius `r`"
function partialcircle(start_θ, end_θ, n = 20, r=1)
@compat(Tuple{Float64,Float64})[(r*cos(u),r*sin(u)) for u in linspace(start_θ, end_θ, n)]
end
"interleave 2 vectors into each other (like a zipper's teeth)"
function weave(x,y; ordering = [x,y])
ret = eltype(x)[]
done = false
while !done
for o in ordering
try
push!(ret, shift!(o))
end
# try
# push!(ret, shift!(y))
# end
end
done = isempty(x) && isempty(y)
end
ret
end
"create a star by weaving together points from an outer and inner circle. `n` is the number of arms"
function makestar(n; offset = -0.5, radius = 1.0)
z1 = offset * π
z2 = z1 + π / (n)
outercircle = partialcircle(z1, z1 + 2π, n+1, radius)
innercircle = partialcircle(z2, z2 + 2π, n+1, 0.4radius)
Shape(weave(outercircle, innercircle)[1:end-2])
end
"create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle"
function makeshape(n; offset = -0.5, radius = 1.0)
z = offset * π
Shape(Plots.partialcircle(z, z + 2π, n+1, radius)[1:end-1])
end
function makecross(; offset = -0.5, radius = 1.0)
z1 = offset * π + π/8
z2 = z1 + π/8
outercircle = partialcircle(z1, z1 + 2π, 9, radius)
innercircle = partialcircle(z2, z2 + 2π, 5, 0.4radius)
Shape(weave(outercircle, innercircle)[1:end-2])
end
const _shapes = Dict(
:ellipse => makeshape(20),
:rect => makeshape(4, offset=-0.25),
:diamond => makeshape(4),
:utriangle => makeshape(3),
:dtriangle => makeshape(3, offset=0.5),
:pentagon => makeshape(5),
:hexagon => makeshape(6),
:septagon => makeshape(7),
:octagon => makeshape(8),
)
for n in [4,5,6,7,8]
_shapes[symbol("star$n")] = makestar(n)
end
# :ellipse, :rect, :diamond, :utriangle, :dtriangle,
# :cross, :xcross, :star1, :star2, :hexagon, :octagon
const _xcross = Shape(@compat(Tuple{Float64,Float64})[
]
# function hexagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.6r
# polys[i] = [
# (x-r, y-u), (x-r, y+u), # L edge
# (x, y+r), # B
# (x+r, y+u), (x+r, y-u), # R edge
# (x, y-r) # T
# ]
# end
# return Gadfly.polygon(polys)
# end
const _xcross = Shape(@compat(Tuple{Float64,Float64})[
]
# function octagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.4r
# polys[i] = [
# (x-r, y-u), (x-r, y+u), # L edge
# (x-u, y+r), (x+u, y+r), # B edge
# (x+r, y+u), (x+r, y-u), # R edge
# (x+u, y-r), (x-u, y-r), # T edge
# ]
# end
# return Gadfly.polygon(polys)
# end
# -----------------------------------------------------------------------
type OHLC{T<:Real}
open::T

View File

@ -175,6 +175,7 @@ limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
limsType(lims) = :invalid
# ---------------------------------------------------------------
type DebugMode