accept vectors of tuples; implement ohlc for gadfly with an example
This commit is contained in:
parent
01cb036976
commit
51021c799d
@ -83,6 +83,9 @@ const examples = PlotExample[
|
||||
PlotExample("",
|
||||
"",
|
||||
[:(subplot!(randn(100,3)))]),
|
||||
PlotExample("Open/High/Low/Close",
|
||||
"Pass in a vector of 4-tuples as your `y` argument. Adjust the tick width with arg `markersize`.",
|
||||
[:(n=10; hgt=rand(n)+1; bot=randn(n); openpct=rand(n); closepct=rand(n);), :(y = [(openpct[i]*hgt[i]+bot[i], bot[i]+hgt[i], bot[i], closepct[i]*hgt[i]+bot[i]) for i in 1:n];), :(ohlc(y; markersize=10))]),
|
||||
|
||||
|
||||
]
|
||||
|
||||
@ -32,6 +32,8 @@ export
|
||||
hline!,
|
||||
vline,
|
||||
vline!,
|
||||
ohlc,
|
||||
ohlc!,
|
||||
|
||||
savepng,
|
||||
|
||||
@ -76,6 +78,8 @@ hline(args...; kw...) = plot(args...; kw..., linetype = :hline)
|
||||
hline!(args...; kw...) = plot!(args...; kw..., linetype = :hline)
|
||||
vline(args...; kw...) = plot(args...; kw..., linetype = :vline)
|
||||
vline!(args...; kw...) = plot!(args...; kw..., linetype = :vline)
|
||||
ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
|
||||
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@ -16,6 +16,7 @@ const TYPES = [:line,
|
||||
:bar,
|
||||
:hline,
|
||||
:vline,
|
||||
:ohlc,
|
||||
]
|
||||
const STYLES = [:solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||
const MARKERS = [:ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon]
|
||||
|
||||
@ -9,7 +9,7 @@ gadfly!() = plotter!(:gadfly)
|
||||
|
||||
supportedArgs(::GadflyPackage) = setdiff(ARGS, [:heatmap_c, :fillto, :pos])
|
||||
supportedAxes(::GadflyPackage) = setdiff(ALL_AXES, [:right])
|
||||
supportedTypes(::GadflyPackage) = [:none, :line, :step, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
|
||||
supportedTypes(::GadflyPackage) = [:none, :line, :step, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc]
|
||||
supportedStyles(::GadflyPackage) = [:auto, :solid]
|
||||
supportedMarkers(::GadflyPackage) = [:none, :auto, :rect, :ellipse, :diamond, :cross]
|
||||
|
||||
@ -45,79 +45,32 @@ function getLineGeoms(d::Dict)
|
||||
lt = d[:linetype]
|
||||
lt in (:heatmap,:hexbin) && return [Gadfly.Geom.hexbin(xbincount = d[:nbins], ybincount = d[:nbins])]
|
||||
lt == :hist && return [Gadfly.Geom.histogram(bincount = d[:nbins])]
|
||||
lt == :none && return [Gadfly.Geom.path]
|
||||
# lt == :none && return [Gadfly.Geom.path]
|
||||
lt == :line && return [Gadfly.Geom.path]
|
||||
lt == :scatter && return [Gadfly.Geom.point]
|
||||
lt == :bar && return [Gadfly.Geom.bar]
|
||||
lt == :step && return [Gadfly.Geom.step]
|
||||
|
||||
# NOTE: we won't actually show this (we'll set width to 0 later), but we need a geom so that Gadfly doesn't complain
|
||||
if lt in (:none, :ohlc)
|
||||
return [Gadfly.Geom.path]
|
||||
end
|
||||
|
||||
# lt == :sticks && return [Gadfly.Geom.bar]
|
||||
error("linetype $lt not currently supported with Gadfly")
|
||||
end
|
||||
|
||||
|
||||
# function createGadflyAnnotation(d::Dict)
|
||||
|
||||
# if d[:marker] == :rect
|
||||
# # get the width/height of the square (both are sz)
|
||||
# sz = d[:markersize] * Gadfly.px
|
||||
# halfsz = sz/2
|
||||
|
||||
# # remap x/y to the corner position of the squares
|
||||
# xs = map(z -> Gadfly.Compose.Measure(;cx=z) - halfsz, float(d[:x]))
|
||||
# ys = map(z -> Gadfly.Compose.Measure(;cy=z) + halfsz, float(d[:y]))
|
||||
|
||||
# # return an Annotation which will add those shapes to each point in the series
|
||||
# return Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), Gadfly.rectangle(xs,ys,[sz],[sz]), Gadfly.fill(d[:markercolor]), Gadfly.stroke(nothing)))
|
||||
|
||||
# else
|
||||
# # make circles
|
||||
# sz = 0.5 * d[:markersize] * Gadfly.px
|
||||
# xs = collect(float(d[:x]))
|
||||
# ys = collect(float(d[:y]))
|
||||
|
||||
# # return an Annotation which will add those shapes to each point in the series
|
||||
# return Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), Gadfly.circle(xs,ys,[sz]), Gadfly.fill(d[:markercolor]), Gadfly.stroke(nothing)))
|
||||
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
# serious hack (I think?) to draw my own shapes as annotations... will it work? who knows...
|
||||
function getMarkerGeomsAndGuides(d::Dict)
|
||||
marker = d[:marker]
|
||||
if marker == :none
|
||||
if marker == :none && d[:linetype] != :ohlc
|
||||
return [],[]
|
||||
end
|
||||
return [], [createGadflyAnnotation(d)]
|
||||
end
|
||||
|
||||
# # special handling for other marker shapes... gotta create Compose contexts and map them to series points using Guide.Annotation
|
||||
# elseif marker == :rect
|
||||
# # get the width/height of the square (both are sz)
|
||||
# sz = d[:markersize] * Gadfly.px
|
||||
# halfsz = sz/2
|
||||
|
||||
# # remap x/y to the corner position of the squares
|
||||
# xs = map(z -> Gadfly.Compose.Measure(;cx=z) - halfsz, float(d[:x]))
|
||||
# ys = map(z -> Gadfly.Compose.Measure(;cy=z) + halfsz, float(d[:y]))
|
||||
|
||||
# # return an Annotation which will add those shapes to each point in the series
|
||||
# return [], [Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), Gadfly.rectangle(xs,ys,[sz],[sz]), Gadfly.fill(d[:markercolor]), Gadfly.stroke(nothing)))]
|
||||
|
||||
# else
|
||||
# # make circles
|
||||
# sz = 0.5 * d[:markersize] * Gadfly.px
|
||||
# xs = collect(float(d[:x]))
|
||||
# ys = collect(float(d[:y]))
|
||||
|
||||
# # return an Annotation which will add those shapes to each point in the series
|
||||
# return [], [Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), Gadfly.circle(xs,ys,[sz]), Gadfly.fill(d[:markercolor]), Gadfly.stroke(nothing)))]
|
||||
|
||||
# end
|
||||
|
||||
# otherwise just return a Geom.point
|
||||
# [Gadfly.Geom.point], []
|
||||
# end
|
||||
|
||||
|
||||
function addGadflyFixedLines!(gplt, d::Dict)
|
||||
@ -153,6 +106,7 @@ function addGadflySeries!(gplt, d::Dict)
|
||||
elseif d[:linetype] in (:hline, :vline)
|
||||
addGadflyFixedLines!(gplt, d)
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
gfargs = []
|
||||
@ -161,7 +115,9 @@ function addGadflySeries!(gplt, d::Dict)
|
||||
append!(gfargs, getLineGeoms(d))
|
||||
|
||||
# handle markers
|
||||
# @show d[:y]
|
||||
geoms, guides = getMarkerGeomsAndGuides(d)
|
||||
# @show d[:y]
|
||||
append!(gfargs, geoms)
|
||||
append!(gplt.guides, guides)
|
||||
|
||||
|
||||
@ -10,7 +10,13 @@ function createGadflyAnnotation(d::Dict)
|
||||
x, y = d[:x], d[:y]
|
||||
marker = d[:marker]
|
||||
|
||||
if marker == :rect
|
||||
if d[:linetype] == :ohlc
|
||||
shape = ohlcshape(x, y, d[:markersize])
|
||||
d[:y] = Float64[z[1] for z in y]
|
||||
d[:linetype] = :none
|
||||
return Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(nothing), Gadfly.stroke(d[:color])))
|
||||
|
||||
elseif marker == :rect
|
||||
shape = square(x, y, sz)
|
||||
|
||||
elseif marker == :diamond
|
||||
@ -86,3 +92,24 @@ function cross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
||||
|
||||
return Gadfly.polygon(polys)
|
||||
end
|
||||
|
||||
|
||||
# Base.isfinite{T<:Real}(x::Tuple{T,T,T,T}) = isfinite(x[1]) && isfinite(x[2]) && isfinite(x[3]) && isfinite(x[4])
|
||||
|
||||
function ohlcshape{T}(xs::AVec, ys::AVec{Tuple{T,T,T,T}}, tickwidth::Real)
|
||||
@assert length(xs) == length(ys)
|
||||
n = length(xs)
|
||||
u = tickwidth * Compose.px
|
||||
polys = Vector{Vector{Tuple{Compose.Measure, Compose.Measure}}}(n)
|
||||
for i in 1:n
|
||||
x = Compose.x_measure(xs[i])
|
||||
o,h,l,c = map(Compose.y_measure, ys[i])
|
||||
polys[i] = Tuple{Compose.Measure, Compose.Measure}[
|
||||
(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
|
||||
|
||||
|
||||
11
src/plot.jl
11
src/plot.jl
@ -362,6 +362,17 @@ function createKWargsList(plt::PlottingObject, n::Integer; kw...)
|
||||
ret
|
||||
end
|
||||
|
||||
# vector of tuples... to be used for things like OHLC
|
||||
createKWargsList{T<:Tuple}(plt::PlottingObject, y::AVec{T}; kw...) = createKWargsList(plt, 1:length(y), y; kw...)
|
||||
|
||||
function createKWargsList{S<:Real, T<:Tuple}(plt::PlottingObject, x::AVec{S}, y::AVec{T}; kw...)
|
||||
d = getPlotKeywordArgs(plt.plotter, kw, 1, plt.n + 1)
|
||||
d[:x] = x
|
||||
d[:y] = y
|
||||
[d]
|
||||
end
|
||||
|
||||
|
||||
# TODO: handle DataFrames (might have NAs!)
|
||||
|
||||
# -------------------------
|
||||
|
||||
@ -89,7 +89,7 @@ function plotter()
|
||||
if !(currentBackendSymbol in INITIALIZED_BACKENDS)
|
||||
|
||||
# initialize
|
||||
println("[Plots.jl] Initializing package: ", CURRENT_BACKEND.sym)
|
||||
println("[Plots.jl] Initializing backend: ", CURRENT_BACKEND.sym)
|
||||
if currentBackendSymbol == :qwt
|
||||
try
|
||||
@eval import Qwt
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user