reorg of update_subplot_args; add back recipe, DataFrames; random type stability fixes
This commit is contained in:
parent
32c1c31139
commit
e3e2a354e7
@ -141,7 +141,7 @@ include("plot.jl")
|
||||
include("series.jl")
|
||||
include("layouts.jl")
|
||||
include("subplots.jl")
|
||||
# include("recipes.jl")
|
||||
include("recipes.jl")
|
||||
include("animation.jl")
|
||||
include("output.jl")
|
||||
include("examples.jl")
|
||||
|
||||
159
src/args.jl
159
src/args.jl
@ -814,9 +814,9 @@ slice_arg(v, idx) = v
|
||||
# given an argument key (k), we want to extract the argument value for this index.
|
||||
# matrices are sliced by column, otherwise we
|
||||
# if nothing is set (or container is empty), return the default or the existing value.
|
||||
function slice_arg!(d_in::KW, d_out::KW, k::Symbol, default_value, idx::Int = 1; new_key::Symbol = k, remove_pair::Bool = true)
|
||||
v = get(d_in, k, get(d_out, new_key, default_value))
|
||||
d_out[new_key] = if haskey(d_in, k) && typeof(v) <: AMat && !isempty(v)
|
||||
function slice_arg!(d_in::KW, d_out::KW, k::Symbol, default_value, idx::Int, remove_pair::Bool)
|
||||
v = get(d_in, k, get(d_out, k, default_value))
|
||||
d_out[k] = if haskey(d_in, k) && typeof(v) <: AMat && !isempty(v)
|
||||
slice_arg(v, idx)
|
||||
else
|
||||
v
|
||||
@ -824,6 +824,7 @@ function slice_arg!(d_in::KW, d_out::KW, k::Symbol, default_value, idx::Int = 1;
|
||||
if remove_pair
|
||||
delete!(d_in, k)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@ -844,12 +845,13 @@ end
|
||||
function color_or_nothing!(d::KW, k::Symbol)
|
||||
v = d[k]
|
||||
d[k] = if v == nothing || v == false
|
||||
plot_color(RGBA(0,0,0,0))
|
||||
RGBA{Float64}(0,0,0,0)
|
||||
elseif v != :match
|
||||
plot_color(v)
|
||||
else
|
||||
v
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@ -938,7 +940,7 @@ Base.get(series::Series, k::Symbol, v) = get(series.d, k, v)
|
||||
# update attr from an input dictionary
|
||||
function _update_plot_args(plt::Plot, d_in::KW)
|
||||
for (k,v) in _plot_defaults
|
||||
slice_arg!(d_in, plt.attr, k, v)
|
||||
slice_arg!(d_in, plt.attr, k, v, 1, true)
|
||||
end
|
||||
|
||||
# handle colors
|
||||
@ -949,20 +951,12 @@ function _update_plot_args(plt::Plot, d_in::KW)
|
||||
end
|
||||
plt.attr[:background_color] = bg
|
||||
plt.attr[:foreground_color] = plot_color(fg)
|
||||
# color_or_match!(plt.attr, :background_color_outside, bg)
|
||||
color_or_nothing!(plt.attr, :background_color_outside)
|
||||
end
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# update a subplots args and axes
|
||||
function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::Integer; remove_pair = true)
|
||||
anns = pop!(sp.attr, :annotations, [])
|
||||
|
||||
# grab those args which apply to this subplot
|
||||
for (k,v) in _subplot_defaults
|
||||
slice_arg!(d_in, sp.attr, k, v, subplot_index, remove_pair = remove_pair)
|
||||
end
|
||||
|
||||
function _update_subplot_periphery(sp::Subplot, anns::AVec)
|
||||
# extend annotations
|
||||
sp.attr[:annotations] = vcat(anns, sp[:annotations])
|
||||
|
||||
@ -972,9 +966,11 @@ function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::I
|
||||
if sp.attr[:colorbar] == :legend
|
||||
sp.attr[:colorbar] = sp.attr[:legend]
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function _update_subplot_colors(sp::Subplot)
|
||||
# background colors
|
||||
# bg = color_or_match!(sp.attr, :background_color_subplot, plt.attr[:background_color])
|
||||
color_or_nothing!(sp.attr, :background_color_subplot)
|
||||
bg = plot_color(sp[:background_color_subplot])
|
||||
sp.attr[:color_palette] = get_color_palette(sp.attr[:color_palette], bg, 30)
|
||||
@ -986,60 +982,87 @@ function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::I
|
||||
color_or_nothing!(sp.attr, :foreground_color_legend)
|
||||
color_or_nothing!(sp.attr, :foreground_color_grid)
|
||||
color_or_nothing!(sp.attr, :foreground_color_title)
|
||||
return
|
||||
end
|
||||
|
||||
# for k in (:left_margin, :top_margin, :right_margin, :bottom_margin)
|
||||
# if sp.attr[k] == :match
|
||||
# sp.attr[k] = sp.attr[:margin]
|
||||
# end
|
||||
# end
|
||||
function _update_axis(plt::Plot, sp::Subplot, d_in::KW, letter::Symbol, subplot_index::Int)
|
||||
# get (maybe initialize) the axis
|
||||
axis = get_axis(sp, letter)
|
||||
|
||||
_update_axis(axis, d_in, letter, subplot_index)
|
||||
|
||||
# convert a bool into auto or nothing
|
||||
if isa(axis[:ticks], Bool)
|
||||
axis[:ticks] = axis[:ticks] ? :auto : nothing
|
||||
end
|
||||
|
||||
_update_axis_colors(axis)
|
||||
_update_axis_links(plt, axis, letter)
|
||||
return
|
||||
end
|
||||
|
||||
function _update_axis(axis::Axis, d_in::KW, letter::Symbol, subplot_index::Int)
|
||||
# grab magic args (for example `xaxis = (:flip, :log)`)
|
||||
args = wraptuple(get(d_in, Symbol(letter, :axis), ()))
|
||||
|
||||
# build the KW of arguments from the letter version (i.e. xticks --> ticks)
|
||||
kw = KW()
|
||||
for (k,v) in _axis_defaults
|
||||
# first get the args without the letter: `tickfont = font(10)`
|
||||
# note: we don't pop because we want this to apply to all axes! (delete after all have finished)
|
||||
if haskey(d_in, k)
|
||||
kw[k] = slice_arg(d_in[k], subplot_index)
|
||||
end
|
||||
|
||||
# then get those args that were passed with a leading letter: `xlabel = "X"`
|
||||
lk = Symbol(letter, k)
|
||||
if haskey(d_in, lk)
|
||||
kw[k] = slice_arg(d_in[lk], subplot_index)
|
||||
end
|
||||
end
|
||||
|
||||
# update the axis
|
||||
update!(axis, args...; kw...)
|
||||
return
|
||||
end
|
||||
|
||||
function _update_axis_colors(axis::Axis)
|
||||
# # update the axis colors
|
||||
color_or_nothing!(axis.d, :foreground_color_axis)
|
||||
color_or_nothing!(axis.d, :foreground_color_border)
|
||||
color_or_nothing!(axis.d, :foreground_color_guide)
|
||||
color_or_nothing!(axis.d, :foreground_color_text)
|
||||
return
|
||||
end
|
||||
|
||||
function _update_axis_links(plt::Plot, axis::Axis, letter::Symbol)
|
||||
# handle linking here. if we're passed a list of
|
||||
# other subplots to link to, link them together
|
||||
link = axis[:link]
|
||||
if !isempty(link)
|
||||
for other_sp in link
|
||||
other_sp = get_subplot(plt, other_sp)
|
||||
link_axes!(axis, get_axis(other_sp, letter))
|
||||
end
|
||||
axis.d[:link] = []
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
# update a subplots args and axes
|
||||
function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::Int, remove_pair::Bool)
|
||||
anns = pop!(sp.attr, :annotations, [])
|
||||
|
||||
# grab those args which apply to this subplot
|
||||
for (k,v) in _subplot_defaults
|
||||
slice_arg!(d_in, sp.attr, k, v, subplot_index, remove_pair)
|
||||
end
|
||||
|
||||
_update_subplot_periphery(sp, anns)
|
||||
_update_subplot_colors(sp)
|
||||
|
||||
for letter in (:x, :y, :z)
|
||||
# get (maybe initialize) the axis
|
||||
axis = get_axis(sp, letter)
|
||||
|
||||
# grab magic args (for example `xaxis = (:flip, :log)`)
|
||||
args = wraptuple(get(d_in, Symbol(letter, :axis), ()))
|
||||
|
||||
# build the KW of arguments from the letter version (i.e. xticks --> ticks)
|
||||
kw = KW()
|
||||
for (k,v) in _axis_defaults
|
||||
# first get the args without the letter: `tickfont = font(10)`
|
||||
# note: we don't pop because we want this to apply to all axes! (delete after all have finished)
|
||||
if haskey(d_in, k)
|
||||
kw[k] = slice_arg(d_in[k], subplot_index)
|
||||
end
|
||||
|
||||
# then get those args that were passed with a leading letter: `xlabel = "X"`
|
||||
lk = Symbol(letter, k)
|
||||
if haskey(d_in, lk)
|
||||
kw[k] = slice_arg(d_in[lk], subplot_index)
|
||||
end
|
||||
end
|
||||
|
||||
# update the axis
|
||||
update!(axis, args...; kw...)
|
||||
|
||||
# convert a bool into auto or nothing
|
||||
if isa(axis[:ticks], Bool)
|
||||
axis[:ticks] = axis[:ticks] ? :auto : nothing
|
||||
end
|
||||
|
||||
# # update the axis colors
|
||||
color_or_nothing!(axis.d, :foreground_color_axis)
|
||||
color_or_nothing!(axis.d, :foreground_color_border)
|
||||
color_or_nothing!(axis.d, :foreground_color_guide)
|
||||
color_or_nothing!(axis.d, :foreground_color_text)
|
||||
|
||||
# handle linking here. if we're passed a list of
|
||||
# other subplots to link to, link them together
|
||||
link = axis[:link]
|
||||
if !isempty(link)
|
||||
for other_sp in link
|
||||
other_sp = get_subplot(plt, other_sp)
|
||||
link_axes!(axis, get_axis(other_sp, letter))
|
||||
end
|
||||
axis.d[:link] = []
|
||||
end
|
||||
_update_axis(plt, sp, d_in, letter, subplot_index)
|
||||
end
|
||||
end
|
||||
|
||||
@ -1071,7 +1094,7 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
|
||||
|
||||
# add default values to our dictionary, being careful not to delete what we just added!
|
||||
for (k,v) in _series_defaults
|
||||
slice_arg!(d, d, k, v, commandIndex, remove_pair = false)
|
||||
slice_arg!(d, d, k, v, commandIndex, false)
|
||||
end
|
||||
|
||||
# this is how many series belong to this subplot
|
||||
|
||||
@ -38,7 +38,7 @@ function get_axis(sp::Subplot, letter::Symbol)
|
||||
sp.attr[axissym]
|
||||
else
|
||||
sp.attr[axissym] = Axis(sp, letter)
|
||||
end
|
||||
end::Axis
|
||||
end
|
||||
|
||||
function process_axis_arg!(d::KW, arg, letter = "")
|
||||
|
||||
46
src/plot.jl
46
src/plot.jl
@ -43,7 +43,6 @@ When you pass in matrices, it splits by columns. See the documentation for more
|
||||
|
||||
# this creates a new plot with args/kw and sets it to be the current plot
|
||||
function plot(args...; kw...)
|
||||
info("started to plot")
|
||||
d = KW(kw)
|
||||
preprocessArgs!(d)
|
||||
|
||||
@ -108,7 +107,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
|
||||
|
||||
# first apply any args for the subplots
|
||||
for (idx,sp) in enumerate(plt.subplots)
|
||||
_update_subplot_args(plt, sp, d, idx, remove_pair = false)
|
||||
_update_subplot_args(plt, sp, d, idx, false)
|
||||
end
|
||||
|
||||
# do we need to link any axes together?
|
||||
@ -152,16 +151,13 @@ end
|
||||
|
||||
# getting ready to add the series... last update to subplot from anything
|
||||
# that might have been added during series recipes
|
||||
function _prepare_subplot(plt::Plot, d::KW)
|
||||
st = d[:seriestype]
|
||||
sp = d[:subplot]
|
||||
function _prepare_subplot{T}(plt::Plot{T}, d::KW)
|
||||
st::Symbol = d[:seriestype]
|
||||
sp::Subplot{T} = d[:subplot]
|
||||
sp_idx = get_subplot_index(plt, sp)
|
||||
_update_subplot_args(plt, sp, d, sp_idx)
|
||||
_update_subplot_args(plt, sp, d, sp_idx, true)
|
||||
|
||||
# do we want to override the series type?
|
||||
if !is3d(st) && d[:z] != nothing && (size(d[:x]) == size(d[:y]) == size(d[:z]))
|
||||
st = d[:seriestype] = (st == :scatter ? :scatter3d : :path3d)
|
||||
end
|
||||
st = _override_seriestype_check(d, st)
|
||||
|
||||
# change to a 3d projection for this subplot?
|
||||
if is3d(st)
|
||||
@ -173,7 +169,19 @@ function _prepare_subplot(plt::Plot, d::KW)
|
||||
_initialize_subplot(plt, sp)
|
||||
sp.attr[:init] = true
|
||||
end
|
||||
sp::Subplot
|
||||
sp
|
||||
end
|
||||
|
||||
function _override_seriestype_check(d::KW, st::Symbol)
|
||||
# do we want to override the series type?
|
||||
if !is3d(st)
|
||||
z = d[:z]
|
||||
if !isa(z, Void) && (size(d[:x]) == size(d[:y]) == size(z))
|
||||
st = (st == :scatter ? :scatter3d : :path3d)
|
||||
d[:seriestype] = st
|
||||
end
|
||||
end
|
||||
st
|
||||
end
|
||||
|
||||
function _prepare_annotations(sp::Subplot, d::KW)
|
||||
@ -244,7 +252,7 @@ function _process_seriesrecipe(plt::Plot, d::KW)
|
||||
end
|
||||
|
||||
function command_idx(kw_list::AVec{KW}, kw::KW)
|
||||
kw[:series_plotindex] - kw_list[1][:series_plotindex] + 1
|
||||
Int(kw[:series_plotindex]) - Int(kw_list[1][:series_plotindex]) + 1
|
||||
end
|
||||
|
||||
function _expand_seriestype_array(d::KW, args)
|
||||
@ -406,7 +414,7 @@ end
|
||||
# to generate a list of RecipeData objects (data + attributes).
|
||||
# If we applied a "plot recipe" without error, then add the returned datalist's KWs,
|
||||
# otherwise we just add the original KW.
|
||||
function _process_plotrecipe(kw::KW, kw_list::Vector{KW}, still_to_process::Vector{KW})
|
||||
function _process_plotrecipe(plt::Plot, kw::KW, kw_list::Vector{KW}, still_to_process::Vector{KW})
|
||||
if !isa(get(kw, :seriestype, nothing), Symbol)
|
||||
# seriestype was never set, or it's not a Symbol, so it can't be a plot recipe
|
||||
push!(kw_list, kw)
|
||||
@ -511,7 +519,7 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
|
||||
# override subplot/axis args. `sp_attrs` take precendence
|
||||
for (idx,sp) in enumerate(plt.subplots)
|
||||
attr = merge(d, get(sp_attrs, sp, KW()))
|
||||
_update_subplot_args(plt, sp, attr, idx, remove_pair = false)
|
||||
_update_subplot_args(plt, sp, attr, idx, false)
|
||||
end
|
||||
|
||||
# do we need to link any axes together?
|
||||
@ -543,7 +551,7 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
|
||||
kw_list = KW[]
|
||||
while !isempty(still_to_process)
|
||||
next_kw = shift!(still_to_process)
|
||||
_process_plotrecipe(next_kw, kw_list, still_to_process)
|
||||
_process_plotrecipe(plt, next_kw, kw_list, still_to_process)
|
||||
end
|
||||
|
||||
# --------------------------------
|
||||
@ -560,11 +568,11 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
|
||||
# --------------------------------
|
||||
|
||||
for kw in kw_list
|
||||
sp = kw[:subplot]
|
||||
idx = get_subplot_index(plt, sp)
|
||||
sp::Subplot = kw[:subplot]
|
||||
# idx = get_subplot_index(plt, sp)
|
||||
|
||||
# # we update subplot args in case something like the color palatte is part of the recipe
|
||||
# _update_subplot_args(plt, sp, kw, idx)
|
||||
# _update_subplot_args(plt, sp, kw, idx, true)
|
||||
|
||||
# set default values, select from attribute cycles, and generally set the final attributes
|
||||
_add_defaults!(kw, plt, sp, command_idx(kw_list,kw))
|
||||
@ -584,7 +592,7 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
|
||||
|
||||
# do we want to force display?
|
||||
if plt[:show]
|
||||
gui()
|
||||
gui(plt)
|
||||
end
|
||||
|
||||
plt
|
||||
|
||||
146
src/recipes.jl
146
src/recipes.jl
@ -1,10 +1,5 @@
|
||||
|
||||
|
||||
# TODO: there should be a distinction between an object that will manage a full plot, vs a component of a plot.
|
||||
# the PlotRecipe as currently implemented is more of a "custom component"
|
||||
# a recipe should fully describe the plotting command(s) and call them, likewise for updating.
|
||||
# actually... maybe those should explicitly derive from AbstractPlot???
|
||||
|
||||
|
||||
"""
|
||||
You can easily define your own plotting recipes with convenience methods:
|
||||
@ -106,60 +101,51 @@ num_series(x) = 1
|
||||
RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::Plot) = throw(MethodError("Unmatched plot recipe: $T"))
|
||||
|
||||
|
||||
# # TODO: remove when StatPlots is ready
|
||||
# if is_installed("DataFrames")
|
||||
# @eval begin
|
||||
# import DataFrames
|
||||
# TODO: remove when StatPlots is ready
|
||||
if is_installed("DataFrames")
|
||||
@eval begin
|
||||
import DataFrames
|
||||
|
||||
# # if it's one symbol, set the guide and return the column
|
||||
# function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, sym::Symbol)
|
||||
# get!(d, Symbol(letter * "guide"), string(sym))
|
||||
# collect(df[sym])
|
||||
# end
|
||||
# if it's one symbol, set the guide and return the column
|
||||
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, sym::Symbol)
|
||||
get!(d, Symbol(letter * "guide"), string(sym))
|
||||
collect(df[sym])
|
||||
end
|
||||
|
||||
# # if it's an array of symbols, set the labels and return a Vector{Any} of columns
|
||||
# function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, syms::AbstractArray{Symbol})
|
||||
# get!(d, :label, reshape(syms, 1, length(syms)))
|
||||
# Any[collect(df[s]) for s in syms]
|
||||
# end
|
||||
# if it's an array of symbols, set the labels and return a Vector{Any} of columns
|
||||
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, syms::AbstractArray{Symbol})
|
||||
get!(d, :label, reshape(syms, 1, length(syms)))
|
||||
Any[collect(df[s]) for s in syms]
|
||||
end
|
||||
|
||||
# # for anything else, no-op
|
||||
# function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, anything)
|
||||
# anything
|
||||
# end
|
||||
# for anything else, no-op
|
||||
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, anything)
|
||||
anything
|
||||
end
|
||||
|
||||
# # handle grouping by DataFrame column
|
||||
# function extractGroupArgs(group::Symbol, df::DataFrames.AbstractDataFrame, args...)
|
||||
# extractGroupArgs(collect(df[group]))
|
||||
# end
|
||||
# handle grouping by DataFrame column
|
||||
function extractGroupArgs(group::Symbol, df::DataFrames.AbstractDataFrame, args...)
|
||||
extractGroupArgs(collect(df[group]))
|
||||
end
|
||||
|
||||
# # if a DataFrame is the first arg, lets swap symbols out for columns
|
||||
# @recipe function f(df::DataFrames.AbstractDataFrame, args...)
|
||||
# # if any of these attributes are symbols, swap out for the df column
|
||||
# for k in (:fillrange, :line_z, :marker_z, :markersize, :ribbon, :weights, :xerror, :yerror)
|
||||
# if haskey(d, k) && isa(d[k], Symbol)
|
||||
# d[k] = collect(df[d[k]])
|
||||
# end
|
||||
# end
|
||||
# if a DataFrame is the first arg, lets swap symbols out for columns
|
||||
@recipe function f(df::DataFrames.AbstractDataFrame, args...)
|
||||
# if any of these attributes are symbols, swap out for the df column
|
||||
for k in (:fillrange, :line_z, :marker_z, :markersize, :ribbon, :weights, :xerror, :yerror)
|
||||
if haskey(d, k) && isa(d[k], Symbol)
|
||||
d[k] = collect(df[d[k]])
|
||||
end
|
||||
end
|
||||
|
||||
# # return a list of new arguments
|
||||
# tuple(Any[handle_dfs(df, d, (i==1 ? "x" : i==2 ? "y" : "z"), arg) for (i,arg) in enumerate(args)]...)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# return a list of new arguments
|
||||
tuple(Any[handle_dfs(df, d, (i==1 ? "x" : i==2 ? "y" : "z"), arg) for (i,arg) in enumerate(args)]...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# """
|
||||
# `apply_series_recipe` should take a processed series KW dict and break it up
|
||||
# into component parts. For example, a box plot is made up of `shape` for the
|
||||
# boxes, `path` for the lines, and `scatter` for the outliers.
|
||||
#
|
||||
# Returns a Vector{KW}.
|
||||
# """
|
||||
# apply_series_recipe(d::KW, st) = KW[d]
|
||||
|
||||
|
||||
# for seriestype `line`, need to sort by x values
|
||||
@recipe function f(::Type{Val{:line}}, x, y, z)
|
||||
@ -174,21 +160,6 @@ RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::Plot) = throw(MethodError("Un
|
||||
end
|
||||
@deps line path
|
||||
|
||||
# @recipe function f(::Type{Val{:sticks}}, x, y, z)
|
||||
# nx = length(x)
|
||||
# n = 3nx
|
||||
# newx, newy = zeros(n), zeros(n)
|
||||
# for i=1:nx
|
||||
# rng = 3i-2:3i
|
||||
# newx[rng] = x[i]
|
||||
# newy[rng] = [0., y[i], 0.]
|
||||
# end
|
||||
# x := newx
|
||||
# y := newy
|
||||
# seriestype := :path
|
||||
# ()
|
||||
# end
|
||||
# @deps sticks path
|
||||
|
||||
function hvline_limits(axis::Axis)
|
||||
vmin, vmax = axis_limits(axis)
|
||||
@ -898,53 +869,6 @@ end
|
||||
@deps quiver shape path
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# function rotate(x::Real, y::Real, θ::Real; center = (0,0))
|
||||
# cx = x - center[1]
|
||||
# cy = y - center[2]
|
||||
# xrot = cx * cos(θ) - cy * sin(θ)
|
||||
# yrot = cy * cos(θ) + cx * sin(θ)
|
||||
# xrot + center[1], yrot + center[2]
|
||||
# end
|
||||
#
|
||||
# # ---------------------------------------------------------------------------
|
||||
#
|
||||
# type EllipseRecipe <: PlotRecipe
|
||||
# w::Float64
|
||||
# h::Float64
|
||||
# x::Float64
|
||||
# y::Float64
|
||||
# θ::Float64
|
||||
# end
|
||||
# EllipseRecipe(w,h,x,y) = EllipseRecipe(w,h,x,y,0)
|
||||
#
|
||||
# # return x,y coords of a rotated ellipse, centered at the origin
|
||||
# function rotatedEllipse(w, h, x, y, θ, rotθ)
|
||||
# # # coord before rotation
|
||||
# xpre = w * cos(θ)
|
||||
# ypre = h * sin(θ)
|
||||
#
|
||||
# # rotate and translate
|
||||
# r = rotate(xpre, ypre, rotθ)
|
||||
# x + r[1], y + r[2]
|
||||
# end
|
||||
#
|
||||
# function getRecipeXY(ep::EllipseRecipe)
|
||||
# x, y = unzip([rotatedEllipse(ep.w, ep.h, ep.x, ep.y, u, ep.θ) for u in linspace(0,2π,100)])
|
||||
# top = rotate(0, ep.h, ep.θ)
|
||||
# right = rotate(ep.w, 0, ep.θ)
|
||||
# linex = Float64[top[1], 0, right[1]] + ep.x
|
||||
# liney = Float64[top[2], 0, right[2]] + ep.y
|
||||
# Any[x, linex], Any[y, liney]
|
||||
# end
|
||||
#
|
||||
# function getRecipeArgs(ep::EllipseRecipe)
|
||||
# [(:line, (3, [:dot :solid], [:red :blue], :path))]
|
||||
# end
|
||||
|
||||
# -------------------------------------------------
|
||||
|
||||
# TODO: move OHLC to PlotRecipes finance.jl
|
||||
|
||||
@ -30,7 +30,7 @@ get_subplot(plt::Plot, i::Integer) = plt.subplots[i]
|
||||
get_subplot(plt::Plot, k) = plt.spmap[k]
|
||||
get_subplot(series::Series) = series.d[:subplot]
|
||||
|
||||
get_subplot_index(plt::Plot, idx::Integer) = idx
|
||||
get_subplot_index(plt::Plot, idx::Integer) = Int(idx)
|
||||
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(_ -> _ === sp, plt.subplots)
|
||||
|
||||
series_list(sp::Subplot) = filter(series -> series.d[:subplot] === sp, sp.plt.series_list)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user