recipes overhaul; is_installed and dataframes logic; removed requires
This commit is contained in:
parent
88be655dca
commit
5005d32afd
1
REQUIRE
1
REQUIRE
@ -4,5 +4,4 @@ RecipesBase
|
|||||||
Colors
|
Colors
|
||||||
Reexport
|
Reexport
|
||||||
Compat
|
Compat
|
||||||
Requires
|
|
||||||
FixedSizeArrays
|
FixedSizeArrays
|
||||||
|
|||||||
@ -6,7 +6,7 @@ module Plots
|
|||||||
using Compat
|
using Compat
|
||||||
using Reexport
|
using Reexport
|
||||||
@reexport using Colors
|
@reexport using Colors
|
||||||
using Requires
|
# using Requires
|
||||||
using FixedSizeArrays
|
using FixedSizeArrays
|
||||||
@reexport using RecipesBase
|
@reexport using RecipesBase
|
||||||
|
|
||||||
@ -171,7 +171,8 @@ 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("subplot.jl")
|
include("subplot.jl")
|
||||||
include("layouts.jl")
|
include("layouts.jl")
|
||||||
include("recipes.jl")
|
include("recipes.jl")
|
||||||
@ -279,10 +280,11 @@ yaxis!(plt::Plot, args...; kw...) = plot!(pl
|
|||||||
|
|
||||||
const CURRENT_BACKEND = CurrentBackend(:none)
|
const CURRENT_BACKEND = CurrentBackend(:none)
|
||||||
|
|
||||||
|
setup_dataframes()
|
||||||
|
|
||||||
function __init__()
|
function __init__()
|
||||||
setup_ijulia()
|
setup_ijulia()
|
||||||
setup_dataframes()
|
# setup_dataframes()
|
||||||
setup_atom()
|
setup_atom()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
81
src/plot.jl
81
src/plot.jl
@ -45,16 +45,13 @@ When you pass in matrices, it splits by columns. See the documentation for more
|
|||||||
function plot(args...; kw...)
|
function plot(args...; kw...)
|
||||||
pkg = backend()
|
pkg = backend()
|
||||||
d = KW(kw)
|
d = KW(kw)
|
||||||
userargs = preprocessArgs!(d)
|
preprocessArgs!(d)
|
||||||
dumpdict(d, "After plot preprocessing")
|
|
||||||
|
|
||||||
plotargs = merge(d, getPlotArgs(pkg, d, 1))
|
plotargs = merge(d, getPlotArgs(pkg, d, 1))
|
||||||
dumpdict(plotargs, "Plot args")
|
|
||||||
plt = _create_plot(pkg, plotargs) # create a new, blank plot
|
plt = _create_plot(pkg, plotargs) # create a new, blank plot
|
||||||
|
|
||||||
# now update the plot
|
# now update the plot
|
||||||
_plot!(plt, d, userargs, args...)
|
_plot!(plt, d, args...)
|
||||||
# plot!(plt, args...; kw...) # add to it
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -73,15 +70,15 @@ end
|
|||||||
# this adds to a specific plot... most plot commands will flow through here
|
# this adds to a specific plot... most plot commands will flow through here
|
||||||
function plot!(plt::Plot, args...; kw...)
|
function plot!(plt::Plot, args...; kw...)
|
||||||
d = KW(kw)
|
d = KW(kw)
|
||||||
userargs = preprocessArgs!(d)
|
preprocessArgs!(d)
|
||||||
_plot!(plt, d, userargs, args...)
|
_plot!(plt, d, args...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# this is the core plotting function. recursively apply recipes to build
|
# this is the core plotting function. recursively apply recipes to build
|
||||||
# a list of series KW dicts.
|
# a list of series KW dicts.
|
||||||
# note: at entry, we only have those preprocessed args which were passed in... no default values yet
|
# note: at entry, we only have those preprocessed args which were passed in... no default values yet
|
||||||
function _plot!(plt::Plot, d::KW, userargs::KW, args...)
|
function _plot!(plt::Plot, d::KW, args...)
|
||||||
# just in case the backend needs to set up the plot (make it current or something)
|
# just in case the backend needs to set up the plot (make it current or something)
|
||||||
_before_add_series(plt)
|
_before_add_series(plt)
|
||||||
|
|
||||||
@ -93,7 +90,24 @@ function _plot!(plt::Plot, d::KW, userargs::KW, args...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# for plotting recipes, swap out the args and update the parameter dictionary
|
# for plotting recipes, swap out the args and update the parameter dictionary
|
||||||
args = RecipesBase.apply_recipe(d, userargs, args...)
|
# we are keeping a queue of series that still need to be processed.
|
||||||
|
# each pass through the loop, we pop one off and apply the recipe.
|
||||||
|
# the recipe will return a list a Series objects... the ones that are
|
||||||
|
# finished (no more args) get added to the kw_list, and the rest go into the queue
|
||||||
|
# for processing.
|
||||||
|
kw_list = KW[]
|
||||||
|
still_to_process = [RecipesBase.Series(copy(d), args)]
|
||||||
|
while !isempty(still_to_process)
|
||||||
|
next_series = pop!(still_to_process)
|
||||||
|
series_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
|
||||||
|
for series in series_list
|
||||||
|
if isempty(series.args)
|
||||||
|
push!(kw_list, series.d)
|
||||||
|
else
|
||||||
|
push!(still_to_process, series)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# dumpdict(d, "After plot! preprocessing")
|
# dumpdict(d, "After plot! preprocessing")
|
||||||
|
|
||||||
@ -110,32 +124,63 @@ function _plot!(plt::Plot, d::KW, userargs::KW, args...)
|
|||||||
# nothing
|
# nothing
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
# TODO: why do i need to check for the subplot key?
|
||||||
|
|
||||||
# merge plot args
|
# merge plot args
|
||||||
if !haskey(d, :subplot)
|
if !haskey(d, :subplot)
|
||||||
|
# merge the plot args from the recipes, then update the plot colors
|
||||||
for k in keys(_plotDefaults)
|
for k in keys(_plotDefaults)
|
||||||
if haskey(d, k)
|
for kw in kw_list
|
||||||
plt.plotargs[k] = d[k]
|
if haskey(kw, k)
|
||||||
|
plt.plotargs[k] = kw[k]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# merge!(plt.plotargs, d)
|
# merge!(plt.plotargs, d)
|
||||||
handlePlotColors(plt.backend, plt.plotargs)
|
handlePlotColors(plt.backend, plt.plotargs)
|
||||||
end
|
end
|
||||||
|
|
||||||
_add_series(plt, d, args...)
|
# _add_series(plt, d, args...)
|
||||||
_add_annotations(plt, d)
|
|
||||||
|
|
||||||
|
# this is it folks!
|
||||||
|
for kw in kw_list
|
||||||
|
plt.n += 1
|
||||||
|
|
||||||
|
# TODO: can this be handled as a recipe??
|
||||||
|
# if !stringsSupported() && di[:linetype] != :pie
|
||||||
|
# setTicksFromStringVector(plt, d, di, "x")
|
||||||
|
# setTicksFromStringVector(plt, d, di, "y")
|
||||||
|
# setTicksFromStringVector(plt, d, di, "z")
|
||||||
|
# end
|
||||||
|
|
||||||
|
# TODO: unnecessary??
|
||||||
|
# # remove plot args
|
||||||
|
# for k in keys(_plotDefaults)
|
||||||
|
# delete!(di, k)
|
||||||
|
# end
|
||||||
|
|
||||||
|
# TODO: why??
|
||||||
|
# # merge in plotarg_overrides
|
||||||
|
# plotarg_overrides = pop!(di, :plotarg_overrides, nothing)
|
||||||
|
# if plotarg_overrides != nothing
|
||||||
|
# merge!(plt.plotargs, plotarg_overrides)
|
||||||
|
# end
|
||||||
|
|
||||||
|
_replace_linewidth(kw)
|
||||||
|
_add_series(plt.backend, plt, kw)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# _add_annotations(plt, d) # TODO
|
||||||
|
|
||||||
|
|
||||||
# add title, axis labels, ticks, etc
|
# add title, axis labels, ticks, etc
|
||||||
if !haskey(d, :subplot)
|
if !haskey(d, :subplot)
|
||||||
merge!(plt.plotargs, d)
|
# merge!(plt.plotargs, d) # this shouldn't be needed since we merged the keys earlier
|
||||||
# handlePlotColors(plt.backend, plt.plotargs)
|
|
||||||
dumpdict(plt.plotargs, "Updating plot items")
|
|
||||||
_update_plot(plt, plt.plotargs)
|
_update_plot(plt, plt.plotargs)
|
||||||
end
|
end
|
||||||
|
|
||||||
_update_plot_pos_size(plt, d)
|
# _update_plot_pos_size(plt, d) # this is only used for Qwt... can we remove?
|
||||||
|
|
||||||
current(plt)
|
current(plt)
|
||||||
|
|
||||||
# note: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
|
# note: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
|
||||||
|
|||||||
@ -28,6 +28,53 @@ function RecipesBase.apply_recipe(d::KW, kw::KW, args...; issubplot=false)
|
|||||||
args
|
args
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if is_installed("DataFrames")
|
||||||
|
@eval begin
|
||||||
|
import DataFrames
|
||||||
|
DFS = Union{Symbol, AbstractArray{Symbol}}
|
||||||
|
|
||||||
|
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, dfs::DFS)
|
||||||
|
if isa(dfs, Symbol)
|
||||||
|
get!(d, symbol(letter * "label"), string(dfs))
|
||||||
|
collect(df[dfs])
|
||||||
|
else
|
||||||
|
get!(d, :label, reshape(dfs, 1, length(dfs)))
|
||||||
|
Any[collect(df[s]) for s in dfs]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function handle_group(df::DataFrames.AbstractDataFrame, d::KW)
|
||||||
|
if haskey(d, :group)
|
||||||
|
g = d[:group]
|
||||||
|
if isa(g, Symbol)
|
||||||
|
d[:group] = collect(df[g])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@recipe function f(df::DataFrames.AbstractDataFrame, sy::DFS)
|
||||||
|
handle_group(df, d)
|
||||||
|
handle_dfs(df, d, "y", sy)
|
||||||
|
end
|
||||||
|
|
||||||
|
@recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS)
|
||||||
|
handle_group(df, d)
|
||||||
|
x = handle_dfs(df, d, "x", sx)
|
||||||
|
y = handle_dfs(df, d, "y", sy)
|
||||||
|
x, y
|
||||||
|
end
|
||||||
|
|
||||||
|
@recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS, sz::DFS)
|
||||||
|
handle_group(df, d)
|
||||||
|
x = handle_dfs(df, d, "x", sx)
|
||||||
|
y = handle_dfs(df, d, "y", sy)
|
||||||
|
z = handle_dfs(df, d, "z", sz)
|
||||||
|
x, y, z
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# macro kw(k, v)
|
# macro kw(k, v)
|
||||||
# esc(:(get!(d, $k, $v)))
|
# esc(:(get!(d, $k, $v)))
|
||||||
# end
|
# end
|
||||||
|
|||||||
@ -463,78 +463,78 @@ 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.
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
function setup_dataframes()
|
# function setup_dataframes()
|
||||||
@require DataFrames begin
|
# @require DataFrames begin
|
||||||
# @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 plot(df::DataFrames.AbstractDataFrame, sy::DFS)
|
# @recipe function plot(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 plot(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS)
|
# @recipe function plot(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 plot(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS, sz::DFS)
|
# @recipe function plot(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
|
||||||
|
#
|
||||||
# get_data(df::DataFrames.AbstractDataFrame, arg::Symbol) = df[arg]
|
# # get_data(df::DataFrames.AbstractDataFrame, arg::Symbol) = df[arg]
|
||||||
# get_data(df::DataFrames.AbstractDataFrame, arg) = arg
|
# # get_data(df::DataFrames.AbstractDataFrame, arg) = arg
|
||||||
#
|
# #
|
||||||
# function process_inputs(plt::AbstractPlot, d::KW, df::DataFrames.AbstractDataFrame, args...)
|
# # function process_inputs(plt::AbstractPlot, d::KW, df::DataFrames.AbstractDataFrame, args...)
|
||||||
# # d[:dataframe] = df
|
# # # d[:dataframe] = df
|
||||||
# process_inputs(plt, d, map(arg -> get_data(df, arg), args)...)
|
# # process_inputs(plt, d, map(arg -> get_data(df, arg), args)...)
|
||||||
# end
|
# # end
|
||||||
#
|
# #
|
||||||
# # expecting the column name of a dataframe that was passed in... anything else should error
|
# # # expecting the column name of a dataframe that was passed in... anything else should error
|
||||||
# function extractGroupArgs(s::Symbol, df::DataFrames.AbstractDataFrame, args...)
|
# # function extractGroupArgs(s::Symbol, df::DataFrames.AbstractDataFrame, args...)
|
||||||
# if haskey(df, s)
|
# # if haskey(df, s)
|
||||||
# return extractGroupArgs(df[s])
|
# # return extractGroupArgs(df[s])
|
||||||
# else
|
# # else
|
||||||
# error("Got a symbol, and expected that to be a key in d[:dataframe]. s=$s d=$d")
|
# # error("Got a symbol, and expected that to be a key in d[:dataframe]. s=$s d=$d")
|
||||||
# end
|
# # end
|
||||||
# end
|
# # end
|
||||||
|
#
|
||||||
# function getDataFrameFromKW(d::KW)
|
# # function getDataFrameFromKW(d::KW)
|
||||||
# get(d, :dataframe) do
|
# # get(d, :dataframe) do
|
||||||
# error("Missing dataframe argument!")
|
# # error("Missing dataframe argument!")
|
||||||
# end
|
# # end
|
||||||
# end
|
# # end
|
||||||
|
#
|
||||||
# # the conversion functions for when we pass symbols or vectors of symbols to reference dataframes
|
# # # the conversion functions for when we pass symbols or vectors of symbols to reference dataframes
|
||||||
# convertToAnyVector(s::Symbol, d::KW) = Any[getDataFrameFromKW(d)[s]], s
|
# # convertToAnyVector(s::Symbol, d::KW) = Any[getDataFrameFromKW(d)[s]], s
|
||||||
# convertToAnyVector(v::AVec{Symbol}, d::KW) = (df = getDataFrameFromKW(d); Any[df[s] for s in v]), v
|
# # convertToAnyVector(v::AVec{Symbol}, d::KW) = (df = getDataFrameFromKW(d); Any[df[s] for s in v]), v
|
||||||
|
#
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
|||||||
@ -237,6 +237,14 @@ end
|
|||||||
isijulia() = isdefined(Main, :IJulia) && Main.IJulia.inited
|
isijulia() = isdefined(Main, :IJulia) && Main.IJulia.inited
|
||||||
isatom() = isdefined(Main, :Atom) && Main.Atom.isconnected()
|
isatom() = isdefined(Main, :Atom) && Main.Atom.isconnected()
|
||||||
|
|
||||||
|
function is_installed(pkgstr::AbstractString)
|
||||||
|
try
|
||||||
|
Pkg.installed(pkgstr) === nothing ? false: true
|
||||||
|
catch
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
istuple(::Tuple) = true
|
istuple(::Tuple) = true
|
||||||
istuple(::Any) = false
|
istuple(::Any) = false
|
||||||
isvector(::AVec) = true
|
isvector(::AVec) = true
|
||||||
|
|||||||
@ -3,7 +3,6 @@ julia 0.4
|
|||||||
RecipesBase
|
RecipesBase
|
||||||
Colors
|
Colors
|
||||||
Reexport
|
Reexport
|
||||||
Requires
|
|
||||||
FactCheck
|
FactCheck
|
||||||
Cairo
|
Cairo
|
||||||
Gadfly
|
Gadfly
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user