working on recipes overhaul

This commit is contained in:
Thomas Breloff 2016-05-12 12:31:47 -04:00
parent 4d3ebf31d4
commit 6049a9fa0a
5 changed files with 234 additions and 137 deletions

View File

@ -280,7 +280,7 @@ yaxis!(plt::Plot, args...; kw...) = plot!(pl
const CURRENT_BACKEND = CurrentBackend(:none) const CURRENT_BACKEND = CurrentBackend(:none)
setup_dataframes() # setup_dataframes()
function __init__() function __init__()
setup_ijulia() setup_ijulia()

View File

@ -806,92 +806,92 @@ end
function has_black_border_for_default(lt::Symbol) function has_black_border_for_default(lt::Symbol)
like_histogram(lt) || lt in (:hexbin, :bar) like_histogram(lt) || lt in (:hexbin, :bar)
end end
#
# build the argument dictionary for a series # # build the argument dictionary for a series
function getSeriesArgs(pkg::AbstractBackend, plotargs::KW, kw, commandIndex::Int, plotIndex::Int, globalIndex::Int) # TODO, pass in plotargs, not plt # function getSeriesArgs(pkg::AbstractBackend, plotargs::KW, kw, commandIndex::Int, plotIndex::Int, globalIndex::Int) # TODO, pass in plotargs, not plt
kwdict = KW(kw) # kwdict = KW(kw)
d = KW() # d = KW()
#
# add defaults? # # add defaults?
for k in keys(_seriesDefaults) # for k in keys(_seriesDefaults)
setDictValue(kwdict, d, k, commandIndex, _seriesDefaults) # setDictValue(kwdict, d, k, commandIndex, _seriesDefaults)
end # end
#
# groupby args? # # groupby args?
for k in (:idxfilter, :numUncounted, :dataframe) # for k in (:idxfilter, :numUncounted, :dataframe)
if haskey(kwdict, k) # if haskey(kwdict, k)
d[k] = kwdict[k] # d[k] = kwdict[k]
end # end
end # end
#
if haskey(_typeAliases, d[:linetype]) # if haskey(_typeAliases, d[:linetype])
d[:linetype] = _typeAliases[d[:linetype]] # d[:linetype] = _typeAliases[d[:linetype]]
end # end
#
aliasesAndAutopick(d, :axis, _axesAliases, supportedAxes(pkg), plotIndex) # aliasesAndAutopick(d, :axis, _axesAliases, supportedAxes(pkg), plotIndex)
aliasesAndAutopick(d, :linestyle, _styleAliases, supportedStyles(pkg), plotIndex) # aliasesAndAutopick(d, :linestyle, _styleAliases, supportedStyles(pkg), plotIndex)
aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex) # aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex)
#
# update color # # update color
d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], plotargs, plotIndex) # d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], plotargs, plotIndex)
#
# # update linecolor # # # update linecolor
# c = d[:linecolor] # # c = d[:linecolor]
# c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex)) # # c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex))
# d[:linecolor] = c # # d[:linecolor] = c
#
# # update markercolor # # # update markercolor
# c = d[:markercolor] # # c = d[:markercolor]
# c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex)) # # c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex))
# d[:markercolor] = c # # d[:markercolor] = c
#
# # update fillcolor # # # update fillcolor
# c = d[:fillcolor] # # c = d[:fillcolor]
# c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex)) # # c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex))
# d[:fillcolor] = c # # d[:fillcolor] = c
#
# update colors # # update colors
for csym in (:linecolor, :markercolor, :fillcolor) # for csym in (:linecolor, :markercolor, :fillcolor)
d[csym] = if d[csym] == :match # d[csym] = if d[csym] == :match
if has_black_border_for_default(d[:linetype]) && csym == :linecolor # if has_black_border_for_default(d[:linetype]) && csym == :linecolor
:black # :black
else # else
d[:seriescolor] # d[:seriescolor]
end # end
else # else
getSeriesRGBColor(d[csym], plotargs, plotIndex) # getSeriesRGBColor(d[csym], plotargs, plotIndex)
end # end
end # end
#
# update markerstrokecolor # # update markerstrokecolor
c = d[:markerstrokecolor] # c = d[:markerstrokecolor]
c = (c == :match ? plotargs[:foreground_color] : getSeriesRGBColor(c, plotargs, plotIndex)) # c = (c == :match ? plotargs[:foreground_color] : getSeriesRGBColor(c, plotargs, plotIndex))
d[:markerstrokecolor] = c # d[:markerstrokecolor] = c
#
# update alphas # # update alphas
for asym in (:linealpha, :markeralpha, :markerstrokealpha, :fillalpha) # for asym in (:linealpha, :markeralpha, :markerstrokealpha, :fillalpha)
if d[asym] == nothing # if d[asym] == nothing
d[asym] = d[:seriesalpha] # d[asym] = d[:seriesalpha]
end # end
end # end
#
# scatter plots don't have a line, but must have a shape # # scatter plots don't have a line, but must have a shape
if d[:linetype] in (:scatter, :scatter3d) # if d[:linetype] in (:scatter, :scatter3d)
d[:linewidth] = 0 # d[:linewidth] = 0
if d[:markershape] == :none # if d[:markershape] == :none
d[:markershape] = :ellipse # d[:markershape] = :ellipse
end # end
end # end
#
# set label # # set label
label = d[:label] # label = d[:label]
label = (label == "AUTO" ? "y$globalIndex" : label) # label = (label == "AUTO" ? "y$globalIndex" : label)
if d[:axis] == :right && !(length(label) >= 4 && label[end-3:end] != " (R)") # if d[:axis] == :right && !(length(label) >= 4 && label[end-3:end] != " (R)")
label = string(label, " (R)") # label = string(label, " (R)")
end # end
d[:label] = label # d[:label] = label
#
warnOnUnsupported(pkg, d) # warnOnUnsupported(pkg, d)
#
d # d
end # end

View File

@ -96,7 +96,7 @@ function _plot!(plt::Plot, d::KW, args...)
# finished (no more args) get added to the kw_list, and the rest go into the queue # finished (no more args) get added to the kw_list, and the rest go into the queue
# for processing. # for processing.
kw_list = KW[] kw_list = KW[]
still_to_process = [RecipesBase.Series(copy(d), args)] still_to_process = [RecipeData(copy(d), args)]
while !isempty(still_to_process) while !isempty(still_to_process)
next_series = pop!(still_to_process) next_series = pop!(still_to_process)
series_list = RecipesBase.apply_recipe(next_series.d, next_series.args...) series_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
@ -143,7 +143,8 @@ function _plot!(plt::Plot, d::KW, args...)
# _add_series(plt, d, args...) # _add_series(plt, d, args...)
# this is it folks! # this is it folks!
for kw in kw_list # TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes
for (i,kw) in enumerate(kw_list)
plt.n += 1 plt.n += 1
# TODO: can this be handled as a recipe?? # TODO: can this be handled as a recipe??
@ -166,6 +167,9 @@ function _plot!(plt::Plot, d::KW, args...)
# merge!(plt.plotargs, plotarg_overrides) # merge!(plt.plotargs, plotarg_overrides)
# end # end
_add_defaults!(kw, plt, i)
# getSeriesArgs(plt.backend, getplotargs(plt, n), d, commandIndex, convertSeriesIndex(plt, n), n)
_replace_linewidth(kw) _replace_linewidth(kw)
_add_series(plt.backend, plt, kw) _add_series(plt.backend, plt, kw)
end end

View File

@ -29,51 +29,51 @@ function RecipesBase.apply_recipe(d::KW, kw::KW, args...; issubplot=false)
end end
if is_installed("DataFrames") # if is_installed("DataFrames")
@eval begin # @eval begin
import DataFrames # import DataFrames
DFS = Union{Symbol, AbstractArray{Symbol}} # DFS = Union{Symbol, AbstractArray{Symbol}}
#
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, dfs::DFS) # function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, dfs::DFS)
if isa(dfs, Symbol) # if isa(dfs, Symbol)
get!(d, symbol(letter * "label"), string(dfs)) # get!(d, symbol(letter * "label"), string(dfs))
collect(df[dfs]) # collect(df[dfs])
else # else
get!(d, :label, reshape(dfs, 1, length(dfs))) # get!(d, :label, reshape(dfs, 1, length(dfs)))
Any[collect(df[s]) for s in dfs] # Any[collect(df[s]) for s in dfs]
end # end
end # end
#
function handle_group(df::DataFrames.AbstractDataFrame, d::KW) # function handle_group(df::DataFrames.AbstractDataFrame, d::KW)
if haskey(d, :group) # if haskey(d, :group)
g = d[:group] # g = d[:group]
if isa(g, Symbol) # if isa(g, Symbol)
d[:group] = collect(df[g]) # d[:group] = collect(df[g])
end # end
end # end
end # end
#
@recipe function f(df::DataFrames.AbstractDataFrame, sy::DFS) # @recipe function f(df::DataFrames.AbstractDataFrame, sy::DFS)
handle_group(df, d) # handle_group(df, d)
handle_dfs(df, d, "y", sy) # handle_dfs(df, d, "y", sy)
end # end
#
@recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS) # @recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS)
handle_group(df, d) # handle_group(df, d)
x = handle_dfs(df, d, "x", sx) # x = handle_dfs(df, d, "x", sx)
y = handle_dfs(df, d, "y", sy) # y = handle_dfs(df, d, "y", sy)
x, y # x, y
end # end
#
@recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS, sz::DFS) # @recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS, sz::DFS)
handle_group(df, d) # handle_group(df, d)
x = handle_dfs(df, d, "x", sx) # x = handle_dfs(df, d, "x", sx)
y = handle_dfs(df, d, "y", sy) # y = handle_dfs(df, d, "y", sy)
z = handle_dfs(df, d, "z", sz) # z = handle_dfs(df, d, "z", sz)
x, y, z # x, y, z
end # end
end # end
end # end
# macro kw(k, v) # macro kw(k, v)
# esc(:(get!(d, $k, $v))) # esc(:(get!(d, $k, $v)))

View File

@ -1,10 +1,103 @@
# we are going to build recipes to do the processing and splitting of the args # we are going to build recipes to do the processing and splitting of the args
# build the argument dictionary for a series
# function getSeriesArgs(pkg::AbstractBackend, plotargs::KW, d, commandIndex::Int, plotIndex::Int, globalIndex::Int) # TODO, pass in plotargs, not plt
function _add_defaults!(d::KW, plt::Plot, commandIndex::Int)
# kwdict = KW(d)
# d = KW()
pkg = plt.backend
n = plt.n
plotargs = getplotargs(plt, n)
plotIndex = convertSeriesIndex(plt, n)
globalIndex = n
# add defaults?
for k in keys(_seriesDefaults)
setDictValue(d, d, k, commandIndex, _seriesDefaults)
end
# # groupby args?
# for k in (:idxfilter, :numUncounted, :dataframe)
# if haskey(kwdict, k)
# d[k] = kwdict[k]
# end
# end
if haskey(_typeAliases, d[:linetype])
d[:linetype] = _typeAliases[d[:linetype]]
end
aliasesAndAutopick(d, :axis, _axesAliases, supportedAxes(pkg), plotIndex)
aliasesAndAutopick(d, :linestyle, _styleAliases, supportedStyles(pkg), plotIndex)
aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex)
# update color
d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], plotargs, plotIndex)
# update colors
for csym in (:linecolor, :markercolor, :fillcolor)
d[csym] = if d[csym] == :match
if has_black_border_for_default(d[:linetype]) && csym == :linecolor
:black
else
d[:seriescolor]
end
else
getSeriesRGBColor(d[csym], plotargs, plotIndex)
end
end
# update markerstrokecolor
c = d[:markerstrokecolor]
c = (c == :match ? plotargs[:foreground_color] : getSeriesRGBColor(c, plotargs, plotIndex))
d[:markerstrokecolor] = c
# update alphas
for asym in (:linealpha, :markeralpha, :markerstrokealpha, :fillalpha)
if d[asym] == nothing
d[asym] = d[:seriesalpha]
end
end
# scatter plots don't have a line, but must have a shape
if d[:linetype] in (:scatter, :scatter3d)
d[:linewidth] = 0
if d[:markershape] == :none
d[:markershape] = :ellipse
end
end
# set label
label = d[:label]
label = (label == "AUTO" ? "y$globalIndex" : label)
if d[:axis] == :right && !(length(label) >= 4 && label[end-3:end] != " (R)")
label = string(label, " (R)")
end
d[:label] = label
warnOnUnsupported(pkg, d)
d
end
# -------------------------------------------------------------------
# -------------------------------------------------------------------
# instead of process_inputs: # instead of process_inputs:
@recipe function f{Y<:Number}(y::AVec{Y})
x --> 1:length(y)
y --> y
dumpdict(d,"y",true)
()
end
@recipe function f{X<:Number,Y<:Number}(x::AVec{X}, y::AVec{Y}) @recipe function f{X<:Number,Y<:Number}(x::AVec{X}, y::AVec{Y})
x --> x x --> x
y --> y y --> y
dumpdict(d,"xy",true)
() ()
end end