working on GR; series_list and should_add_to_legend; series recipes fix; hist and bar recipes

This commit is contained in:
Thomas Breloff 2016-05-25 13:06:08 -04:00
parent 603dc30bb1
commit dae9dad2f7
9 changed files with 550 additions and 369 deletions

View File

@ -232,13 +232,14 @@ const _axis_defaults = KW(
:foreground_color_guide => :match, # guide text color, :foreground_color_guide => :match, # guide text color,
) )
const _suppress_warnings = KW( const _suppress_warnings = Set{Symbol}([
:x_discrete_indices => nothing, :x_discrete_indices,
:y_discrete_indices => nothing, :y_discrete_indices,
:z_discrete_indices => nothing, :z_discrete_indices,
:subplot => nothing, :subplot,
:subplot_index => nothing, :subplot_index,
) :series_plotindex,
])
# add defaults for the letter versions # add defaults for the letter versions
const _axis_defaults_byletter = KW() const _axis_defaults_byletter = KW()
@ -433,9 +434,7 @@ function default(k::Symbol)
return defaults[k] return defaults[k]
end end
end end
if !haskey(_suppress_warnings, k) k in _suppress_warnings || error("Unknown key: ", k)
error("Unknown key: ", k)
end
end end
function default(k::Symbol, v) function default(k::Symbol, v)
@ -446,9 +445,7 @@ function default(k::Symbol, v)
return v return v
end end
end end
if !haskey(_suppress_warnings, k) k in _suppress_warnings || error("Unknown key: ", k)
error("Unknown key: ", k)
end
end end
function default(; kw...) function default(; kw...)
@ -789,7 +786,7 @@ end
function warnOnUnsupportedArgs(pkg::AbstractBackend, d::KW) function warnOnUnsupportedArgs(pkg::AbstractBackend, d::KW)
for k in sortedkeys(d) for k in sortedkeys(d)
k in supportedArgs(pkg) && continue k in supportedArgs(pkg) && continue
haskey(_suppress_warnings, k) && continue k in _suppress_warnings && continue
if d[k] != default(k) if d[k] != default(k)
warn("Keyword argument $k not supported with $pkg. Choose from: $(supportedArgs(pkg))") warn("Keyword argument $k not supported with $pkg. Choose from: $(supportedArgs(pkg))")
end end

File diff suppressed because it is too large Load Diff

View File

@ -1127,13 +1127,16 @@ function addPyPlotLegend(plt::Plot, sp::Subplot, ax)
# gotta do this to ensure both axes are included # gotta do this to ensure both axes are included
labels = [] labels = []
handles = [] handles = []
for series in plt.series_list # for series in plt.series_list
if get_subplot(series) === sp && # if get_subplot(series) === sp &&
series.d[:label] != "" && # series.d[:label] != "" &&
!(series.d[:seriestype] in ( # !(series.d[:seriestype] in (
:hexbin,:hist2d,:hline,:vline, # :hexbin,:hist2d,:hline,:vline,
:contour,:contour3d,:surface,:wireframe, # :contour,:contour3d,:surface,:wireframe,
:heatmap,:path3d,:scatter3d, :pie, :image)) # :heatmap,:path3d,:scatter3d, :pie, :image))
for series in series_list(sp)
if should_add_to_legend(series)
# add a line/marker and a label
push!(handles, if series.d[:seriestype] == :hist push!(handles, if series.d[:seriestype] == :hist
PyPlot.plt[:Line2D]((0,1),(0,0), color=pyfillcolor(series.d), linewidth=4) PyPlot.plt[:Line2D]((0,1),(0,0), color=pyfillcolor(series.d), linewidth=4)
else else
@ -1142,6 +1145,8 @@ function addPyPlotLegend(plt::Plot, sp::Subplot, ax)
push!(labels, series.d[:label]) push!(labels, series.d[:label])
end end
end end
# if anything was added, call ax.legend and set the colors
if !isempty(handles) if !isempty(handles)
leg = ax[:legend](handles, leg = ax[:legend](handles,
labels, labels,

View File

@ -20,11 +20,11 @@ function _create_backend_figure(plt::Plot{[PkgName]Backend})
end end
# this is called early in the pipeline, use it to make the plot current or something # this is called early in the pipeline, use it to make the plot current or something
function _prepare_plot_object(plt::Plot{[PkgName]}) function _prepare_plot_object(plt::Plot{[PkgName]Backend})
end end
# Set up the subplot within the backend object. # Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend}) function _initialize_subplot(plt::Plot{[PkgName]Backend}, sp::Subplot{[PkgName]Backend})
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -42,7 +42,7 @@ end
# called just before updating layout bounding boxes... in case you need to prep # called just before updating layout bounding boxes... in case you need to prep
# for the calcs # for the calcs
function _before_layout_calcs(plt::Plot) function _before_layout_calcs(plt::Plot{[PkgName]Backend})
end end
# Set the (left, top, right, bottom) minimum padding around the plot area # Set the (left, top, right, bottom) minimum padding around the plot area

View File

@ -1,8 +1,8 @@
defaultOutputFormat(plt::AbstractPlot) = "png" defaultOutputFormat(plt::Plot) = "png"
function png(plt::AbstractPlot, fn::@compat(AbstractString)) function png(plt::Plot, fn::@compat(AbstractString))
fn = addExtension(fn, "png") fn = addExtension(fn, "png")
io = open(fn, "w") io = open(fn, "w")
writemime(io, MIME("image/png"), plt) writemime(io, MIME("image/png"), plt)
@ -10,7 +10,7 @@ function png(plt::AbstractPlot, fn::@compat(AbstractString))
end end
png(fn::@compat(AbstractString)) = png(current(), fn) png(fn::@compat(AbstractString)) = png(current(), fn)
function svg(plt::AbstractPlot, fn::@compat(AbstractString)) function svg(plt::Plot, fn::@compat(AbstractString))
fn = addExtension(fn, "svg") fn = addExtension(fn, "svg")
io = open(fn, "w") io = open(fn, "w")
writemime(io, MIME("image/svg+xml"), plt) writemime(io, MIME("image/svg+xml"), plt)
@ -19,7 +19,7 @@ end
svg(fn::@compat(AbstractString)) = svg(current(), fn) svg(fn::@compat(AbstractString)) = svg(current(), fn)
function pdf(plt::AbstractPlot, fn::@compat(AbstractString)) function pdf(plt::Plot, fn::@compat(AbstractString))
fn = addExtension(fn, "pdf") fn = addExtension(fn, "pdf")
io = open(fn, "w") io = open(fn, "w")
writemime(io, MIME("application/pdf"), plt) writemime(io, MIME("application/pdf"), plt)
@ -28,7 +28,7 @@ end
pdf(fn::@compat(AbstractString)) = pdf(current(), fn) pdf(fn::@compat(AbstractString)) = pdf(current(), fn)
function ps(plt::AbstractPlot, fn::@compat(AbstractString)) function ps(plt::Plot, fn::@compat(AbstractString))
fn = addExtension(fn, "ps") fn = addExtension(fn, "ps")
io = open(fn, "w") io = open(fn, "w")
writemime(io, MIME("application/postscript"), plt) writemime(io, MIME("application/postscript"), plt)
@ -37,7 +37,7 @@ end
ps(fn::@compat(AbstractString)) = ps(current(), fn) ps(fn::@compat(AbstractString)) = ps(current(), fn)
function tex(plt::AbstractPlot, fn::@compat(AbstractString)) function tex(plt::Plot, fn::@compat(AbstractString))
fn = addExtension(fn, "tex") fn = addExtension(fn, "tex")
io = open(fn, "w") io = open(fn, "w")
writemime(io, MIME("application/x-tex"), plt) writemime(io, MIME("application/x-tex"), plt)
@ -78,7 +78,7 @@ function addExtension(fn::@compat(AbstractString), ext::@compat(AbstractString))
end end
end end
function savefig(plt::AbstractPlot, fn::@compat(AbstractString)) function savefig(plt::Plot, fn::@compat(AbstractString))
# get the extension # get the extension
local ext local ext
@ -101,7 +101,7 @@ savefig(fn::@compat(AbstractString)) = savefig(current(), fn)
# --------------------------------------------------------- # ---------------------------------------------------------
gui(plt::AbstractPlot = current()) = display(PlotsDisplay(), plt) gui(plt::Plot = current()) = display(PlotsDisplay(), plt)
function Base.display(::PlotsDisplay, plt::Plot) function Base.display(::PlotsDisplay, plt::Plot)
prepare_output(plt) prepare_output(plt)
@ -109,7 +109,7 @@ function Base.display(::PlotsDisplay, plt::Plot)
end end
# override the REPL display to open a gui window # override the REPL display to open a gui window
Base.display(::Base.REPL.REPLDisplay, ::MIME"text/plain", plt::AbstractPlot) = gui(plt) Base.display(::Base.REPL.REPLDisplay, ::MIME"text/plain", plt::Plot) = gui(plt)
# --------------------------------------------------------- # ---------------------------------------------------------
@ -123,12 +123,12 @@ const _mimeformats = Dict(
) )
# a backup for html... passes to svg # a backup for html... passes to svg
function Base.writemime(io::IO, ::MIME"text/html", plt::AbstractPlot) function Base.writemime(io::IO, ::MIME"text/html", plt::Plot)
writemime(io, MIME("image/svg+xml"), plt) writemime(io, MIME("image/svg+xml"), plt)
end end
for mime in keys(_mimeformats) for mime in keys(_mimeformats)
@eval function writemime(io::IO, m::MIME{Symbol($mime)}, plt::Plot) @eval function Base.writemime(io::IO, m::MIME{Symbol($mime)}, plt::Plot)
prepare_output(plt) prepare_output(plt)
_writemime(io, m, plt) _writemime(io, m, plt)
end end
@ -151,13 +151,13 @@ function setup_ijulia()
global _ijulia_output global _ijulia_output
_ijulia_output[1] = mimestr _ijulia_output[1] = mimestr
end end
function IJulia.display_dict(plt::AbstractPlot) function IJulia.display_dict(plt::Plot)
global _ijulia_output global _ijulia_output
Dict{ASCIIString, ByteString}(_ijulia_output[1] => sprint(writemime, _ijulia_output[1], plt)) Dict{ASCIIString, ByteString}(_ijulia_output[1] => sprint(writemime, _ijulia_output[1], plt))
end end
end end
# IJulia.display_dict(plt::AbstractPlot) = Dict{ASCIIString, ByteString}("text/html" => sprint(writemime, "text/html", plt)) # IJulia.display_dict(plt::Plot) = Dict{ASCIIString, ByteString}("text/html" => sprint(writemime, "text/html", plt))
set_ijulia_output("text/html") set_ijulia_output("text/html")
end end
end end
@ -174,15 +174,15 @@ function setup_atom()
# connects the render function # connects the render function
for T in (GadflyBackend,ImmerseBackend,PyPlotBackend,GRBackend) for T in (GadflyBackend,ImmerseBackend,PyPlotBackend,GRBackend)
Atom.Media.media(AbstractPlot{T}, Atom.Media.Plot) Atom.Media.media(Plot{T}, Atom.Media.Plot)
end end
# Atom.Media.media{T <: Union{GadflyBackend,ImmerseBackend,PyPlotBackend,GRBackend}}(Plot{T}, Atom.Media.Plot) # Atom.Media.media{T <: Union{GadflyBackend,ImmerseBackend,PyPlotBackend,GRBackend}}(Plot{T}, Atom.Media.Plot)
# Atom.displaysize(::AbstractPlot) = (535, 379) # Atom.displaysize(::Plot) = (535, 379)
# Atom.displaytitle(plt::AbstractPlot) = "Plots.jl (backend: $(backend(plt)))" # Atom.displaytitle(plt::Plot) = "Plots.jl (backend: $(backend(plt)))"
# this is like "display"... sends an html div with the plot to the PlotPane # this is like "display"... sends an html div with the plot to the PlotPane
function Atom.Media.render(pane::Atom.PlotPane, plt::AbstractPlot) function Atom.Media.render(pane::Atom.PlotPane, plt::Plot)
Atom.Media.render(pane, Atom.div(Atom.d(), Atom.HTML(stringmime(MIME("text/html"), plt)))) Atom.Media.render(pane, Atom.div(Atom.d(), Atom.HTML(stringmime(MIME("text/html"), plt))))
end end

View File

@ -95,6 +95,7 @@ end
# natively by the backend # natively by the backend
function _apply_series_recipe(plt::Plot, d::KW) function _apply_series_recipe(plt::Plot, d::KW)
st = d[:seriestype] st = d[:seriestype]
@show st
if st in supportedTypes() if st in supportedTypes()
# getting ready to add the series... last update to subplot from anything # getting ready to add the series... last update to subplot from anything
@ -138,7 +139,7 @@ function _apply_series_recipe(plt::Plot, d::KW)
else else
# get a sub list of series for this seriestype # get a sub list of series for this seriestype
series_list = try datalist = try
RecipesBase.apply_recipe(d, Val{st}, d[:x], d[:y], d[:z]) RecipesBase.apply_recipe(d, Val{st}, d[:x], d[:y], d[:z])
catch catch
warn("Exception during apply_recipe(Val{$st}, ...) with types ($(typeof(d[:x])), $(typeof(d[:y])), $(typeof(d[:z])))") warn("Exception during apply_recipe(Val{$st}, ...) with types ($(typeof(d[:x])), $(typeof(d[:y])), $(typeof(d[:z])))")
@ -146,9 +147,9 @@ function _apply_series_recipe(plt::Plot, d::KW)
end end
# assuming there was no error, recursively apply the series recipes # assuming there was no error, recursively apply the series recipes
for series in series_list for data in datalist
if isa(series, Series) if isa(data, RecipeData)
_apply_series_recipe(plt, series.d) _apply_series_recipe(plt, data.d)
else else
warn("Unhandled series: $(series_list)") warn("Unhandled series: $(series_list)")
break break
@ -221,6 +222,10 @@ function _plot!(plt::Plot, d::KW, args...)
kw[:fillrange] = (kw[:y] - rib, kw[:y] + rib) kw[:fillrange] = (kw[:y] - rib, kw[:y] + rib)
end end
# add the plot index
plt.n += 1
kw[:series_plotindex] = plt.n
# check that the backend will support the command and add it to the list # check that the backend will support the command and add it to the list
warnOnUnsupportedScales(plt.backend, kw) warnOnUnsupportedScales(plt.backend, kw)
push!(kw_list, kw) push!(kw_list, kw)
@ -248,9 +253,9 @@ function _plot!(plt::Plot, d::KW, args...)
# this is it folks! # this is it folks!
# TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes # 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) for (i,kw) in enumerate(kw_list)
if !(get(kw, :seriestype, :none) in (:xerror, :yerror)) # if !(get(kw, :seriestype, :none) in (:xerror, :yerror))
plt.n += 1 # plt.n += 1
end # end
# get the Subplot object to which the series belongs # get the Subplot object to which the series belongs
sp = get(kw, :subplot, :auto) sp = get(kw, :subplot, :auto)

View File

@ -226,6 +226,55 @@ end
() ()
end end
# create a path from steps
@recipe function f(::Type{Val{:steppre}}, x, y, z)
end
# create a bar plot as a filled step function
@recipe function f(::Type{Val{:bar}}, x, y, z)
nx, ny = length(x), length(y)
d[:x] = if nx == ny
# x is centers
halfwidths = 0.5 * diff(x)
vcat(halfwidths[1], halfwidths, halfwidths[end])
elseif nx == ny + 1
# x is edges
x
else
error("bar recipe: x must be same length as y (centers), or one more than y (edges).\n\t\tlength(x)=$(length(x)), length(y)=$(length(y))")
end
# TODO: use y/fillrange to compute new y/fillrange vectors
d[:seriestype] = :steppre
()
end
# # x is edges
# for i=1:n
# gr_fillrect(series, x[i], x[i+1], 0, y[i])
# end
# elseif length(x) == n
# # x is centers
# leftwidth = length(x) > 1 ? abs(0.5 * (x[2] - x[1])) : 0.5
# for i=1:n
# rightwidth = (i == n ? leftwidth : abs(0.5 * (x[i+1] - x[i])))
# gr_fillrect(series, x[i] - leftwidth, x[i] + rightwidth, 0, y[i])
# end
# else
# error("gr_barplot: x must be same length as y (centers), or one more than y (edges).\n\t\tlength(x)=$(length(x)), length(y)=$(length(y))")
# end
@recipe function f(::Type{Val{:hist}}, x, y, z)
edges, counts = Base.hist(y, d[:bins])
d[:x] = edges
d[:y] = counts
d[:seriestype] = :bar
()
end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Box Plot # Box Plot

View File

@ -7,7 +7,8 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
# n = plt.n # n = plt.n
# attr = getattr(plt, n) # attr = getattr(plt, n)
# plotIndex = convertSeriesIndex(plt, n) # plotIndex = convertSeriesIndex(plt, n)
globalIndex = plt.n # globalIndex = plt.n
globalIndex = d[:series_plotindex]
# # add defaults? # # add defaults?
# for k in keys(_series_defaults) # for k in keys(_series_defaults)

View File

@ -33,4 +33,14 @@ get_subplot(series::Series) = series.d[:subplot]
get_subplot_index(plt::Plot, idx::Integer) = idx get_subplot_index(plt::Plot, idx::Integer) = idx
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(_ -> _ === sp, plt.subplots) 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)
function should_add_to_legend(series::Series)
!(series.d[:label] == "" || series.d[:seriestype] in (
:hexbin,:hist2d,:hline,:vline,
:contour,:contour3d,:surface,:wireframe,
:heatmap,:path3d,:scatter3d, :pie, :image
))
end
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------