shorthands macro; pyplot bar fill fix; userplot macro; nicer error message in convertToAnyVector

This commit is contained in:
Thomas Breloff 2016-05-27 14:25:14 -04:00
parent d3baa58c7e
commit c15cbad396
4 changed files with 177 additions and 85 deletions

View File

@ -9,6 +9,7 @@ using Reexport
# using Requires # using Requires
using FixedSizeArrays using FixedSizeArrays
@reexport using RecipesBase @reexport using RecipesBase
using Base.Meta
export export
AbstractPlot, AbstractPlot,
@ -40,53 +41,54 @@ export
default, default,
with, with,
scatter, @userplot,
scatter!, # scatter,
bar, # scatter!,
bar!, # bar,
barh, # bar!,
barh!, # barh,
histogram, # barh!,
histogram!, # histogram,
histogram2d, # histogram!,
histogram2d!, # histogram2d,
density, # histogram2d!,
density!, # density,
heatmap, # density!,
heatmap!, # heatmap,
hexbin, # heatmap!,
hexbin!, # hexbin,
sticks, # hexbin!,
sticks!, # sticks,
hline, # sticks!,
hline!, # hline,
vline, # hline!,
vline!, # vline,
ohlc, # vline!,
ohlc!, # ohlc,
# ohlc!,
pie, pie,
pie!, pie!,
contour, # contour,
contour!, # contour!,
contour3d, # contour3d,
contour3d!, # contour3d!,
surface, # surface,
surface!, # surface!,
wireframe, # wireframe,
wireframe!, # wireframe!,
path3d, # path3d,
path3d!, # path3d!,
plot3d, plot3d,
plot3d!, plot3d!,
scatter3d, # scatter3d,
scatter3d!, # scatter3d!,
abline!, # abline!,
boxplot, # boxplot,
boxplot!, # boxplot!,
violin, # violin,
violin!, # violin!,
quiver, # quiver,
quiver!, # quiver!,
title!, title!,
xlabel!, xlabel!,
@ -199,52 +201,88 @@ include("output.jl")
# --------------------------------------------------------- # ---------------------------------------------------------
scatter(args...; kw...) = plot(args...; kw..., seriestype = :scatter) # define and export shorthand plotting method definitions
scatter!(args...; kw...) = plot!(args...; kw..., seriestype = :scatter) macro shorthands(funcname::Symbol)
bar(args...; kw...) = plot(args...; kw..., seriestype = :bar) funcname2 = symbol(funcname, "!")
bar!(args...; kw...) = plot!(args...; kw..., seriestype = :bar) ret = esc(quote
barh(args...; kw...) = plot(args...; kw..., seriestype = :barh, orientation = :h) export $funcname, $funcname2
barh!(args...; kw...) = plot!(args...; kw..., seriestype = :barh, orientation = :h) $funcname(args...; kw...) = plot(args...; kw..., seriestype = $(quot(funcname)))
histogram(args...; kw...) = plot(args...; kw..., seriestype = :hist) $funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(quot(funcname)))
histogram!(args...; kw...) = plot!(args...; kw..., seriestype = :hist) end)
histogram2d(args...; kw...) = plot(args...; kw..., seriestype = :hist2d) # dump(ret,20)
histogram2d!(args...; kw...) = plot!(args...; kw..., seriestype = :hist2d) # @show ret
density(args...; kw...) = plot(args...; kw..., seriestype = :density) ret
density!(args...; kw...) = plot!(args...; kw..., seriestype = :density) end
heatmap(args...; kw...) = plot(args...; kw..., seriestype = :heatmap)
heatmap!(args...; kw...) = plot!(args...; kw..., seriestype = :heatmap) @shorthands scatter
hexbin(args...; kw...) = plot(args...; kw..., seriestype = :hexbin) @shorthands bar
hexbin!(args...; kw...) = plot!(args...; kw..., seriestype = :hexbin) @shorthands barh
sticks(args...; kw...) = plot(args...; kw..., seriestype = :sticks, marker = :ellipse) @shorthands histogram
sticks!(args...; kw...) = plot!(args...; kw..., seriestype = :sticks, marker = :ellipse) @shorthands histogram2d
hline(args...; kw...) = plot(args...; kw..., seriestype = :hline) @shorthands density
hline!(args...; kw...) = plot!(args...; kw..., seriestype = :hline) @shorthands heatmap
vline(args...; kw...) = plot(args...; kw..., seriestype = :vline) @shorthands hexbin
vline!(args...; kw...) = plot!(args...; kw..., seriestype = :vline) @shorthands sticks
ohlc(args...; kw...) = plot(args...; kw..., seriestype = :ohlc) @shorthands hline
ohlc!(args...; kw...) = plot!(args...; kw..., seriestype = :ohlc) @shorthands vline
@shorthands ohlc
# @shorthands pie
@shorthands contour
@shorthands contour3d
@shorthands surface
@shorthands wireframe
@shorthands path3d
@shorthands scatter3d
@shorthands boxplot
@shorthands violin
@shorthands quiver
# scatter(args...; kw...) = plot(args...; kw..., seriestype = :scatter)
# scatter!(args...; kw...) = plot!(args...; kw..., seriestype = :scatter)
# bar(args...; kw...) = plot(args...; kw..., seriestype = :bar)
# bar!(args...; kw...) = plot!(args...; kw..., seriestype = :bar)
# barh(args...; kw...) = plot(args...; kw..., seriestype = :barh, orientation = :h)
# barh!(args...; kw...) = plot!(args...; kw..., seriestype = :barh, orientation = :h)
# histogram(args...; kw...) = plot(args...; kw..., seriestype = :hist)
# histogram!(args...; kw...) = plot!(args...; kw..., seriestype = :hist)
# histogram2d(args...; kw...) = plot(args...; kw..., seriestype = :hist2d)
# histogram2d!(args...; kw...) = plot!(args...; kw..., seriestype = :hist2d)
# density(args...; kw...) = plot(args...; kw..., seriestype = :density)
# density!(args...; kw...) = plot!(args...; kw..., seriestype = :density)
# heatmap(args...; kw...) = plot(args...; kw..., seriestype = :heatmap)
# heatmap!(args...; kw...) = plot!(args...; kw..., seriestype = :heatmap)
# hexbin(args...; kw...) = plot(args...; kw..., seriestype = :hexbin)
# hexbin!(args...; kw...) = plot!(args...; kw..., seriestype = :hexbin)
# sticks(args...; kw...) = plot(args...; kw..., seriestype = :sticks, marker = :ellipse)
# sticks!(args...; kw...) = plot!(args...; kw..., seriestype = :sticks, marker = :ellipse)
# hline(args...; kw...) = plot(args...; kw..., seriestype = :hline)
# hline!(args...; kw...) = plot!(args...; kw..., seriestype = :hline)
# vline(args...; kw...) = plot(args...; kw..., seriestype = :vline)
# vline!(args...; kw...) = plot!(args...; kw..., seriestype = :vline)
# ohlc(args...; kw...) = plot(args...; kw..., seriestype = :ohlc)
# ohlc!(args...; kw...) = plot!(args...; kw..., seriestype = :ohlc)
pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing) pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
contour(args...; kw...) = plot(args...; kw..., seriestype = :contour) # contour(args...; kw...) = plot(args...; kw..., seriestype = :contour)
contour!(args...; kw...) = plot!(args...; kw..., seriestype = :contour) # contour!(args...; kw...) = plot!(args...; kw..., seriestype = :contour)
contour3d(args...; kw...) = plot(args...; kw..., seriestype = :contour3d) # contour3d(args...; kw...) = plot(args...; kw..., seriestype = :contour3d)
contour3d!(args...; kw...) = plot!(args...; kw..., seriestype = :contour3d) # contour3d!(args...; kw...) = plot!(args...; kw..., seriestype = :contour3d)
surface(args...; kw...) = plot(args...; kw..., seriestype = :surface) # surface(args...; kw...) = plot(args...; kw..., seriestype = :surface)
surface!(args...; kw...) = plot!(args...; kw..., seriestype = :surface) # surface!(args...; kw...) = plot!(args...; kw..., seriestype = :surface)
wireframe(args...; kw...) = plot(args...; kw..., seriestype = :wireframe) # wireframe(args...; kw...) = plot(args...; kw..., seriestype = :wireframe)
wireframe!(args...; kw...) = plot!(args...; kw..., seriestype = :wireframe) # wireframe!(args...; kw...) = plot!(args...; kw..., seriestype = :wireframe)
path3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d) # path3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
path3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d) # path3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d) plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d) plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
scatter3d(args...; kw...) = plot(args...; kw..., seriestype = :scatter3d) # scatter3d(args...; kw...) = plot(args...; kw..., seriestype = :scatter3d)
scatter3d!(args...; kw...) = plot!(args...; kw..., seriestype = :scatter3d) # scatter3d!(args...; kw...) = plot!(args...; kw..., seriestype = :scatter3d)
boxplot(args...; kw...) = plot(args...; kw..., seriestype = :boxplot) # boxplot(args...; kw...) = plot(args...; kw..., seriestype = :boxplot)
boxplot!(args...; kw...) = plot!(args...; kw..., seriestype = :boxplot) # boxplot!(args...; kw...) = plot!(args...; kw..., seriestype = :boxplot)
violin(args...; kw...) = plot(args...; kw..., seriestype = :violin) # violin(args...; kw...) = plot(args...; kw..., seriestype = :violin)
violin!(args...; kw...) = plot!(args...; kw..., seriestype = :violin) # violin!(args...; kw...) = plot!(args...; kw..., seriestype = :violin)
quiver(args...; kw...) = plot(args...; kw..., seriestype = :quiver) # quiver(args...; kw...) = plot(args...; kw..., seriestype = :quiver)
quiver!(args...; kw...) = plot!(args...; kw..., seriestype = :quiver) # quiver!(args...; kw...) = plot!(args...; kw..., seriestype = :quiver)
title!(s::AbstractString; kw...) = plot!(; title = s, kw...) title!(s::AbstractString; kw...) = plot!(; title = s, kw...)

View File

@ -507,6 +507,11 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
if st == :bar if st == :bar
extrakw[isvertical(d) ? :width : :height] = d[:bar_width] extrakw[isvertical(d) ? :width : :height] = d[:bar_width]
fr = get(d, :fillrange, nothing)
if fr != nothing
extrakw[:bottom] = fr
d[:fillrange] = nothing
end
handle = ax[isvertical(d) ? :bar : :barh](x, y; handle = ax[isvertical(d) ? :bar : :barh](x, y;
label = d[:label], label = d[:label],
zorder = plt.n, zorder = plt.n,

View File

@ -5,6 +5,51 @@
# a recipe should fully describe the plotting command(s) and call them, likewise for updating. # a recipe should fully describe the plotting command(s) and call them, likewise for updating.
# actually... maybe those should explicitly derive from AbstractPlot??? # actually... maybe those should explicitly derive from AbstractPlot???
"""
You can easily define your own plotting recipes with convenience methods:
```
@userplot type GroupHist
args
end
@recipe function f(gh::GroupHist)
# set some attributes, add some series, using gh.args as input
end
# now you can plot like:
grouphist(rand(1000,4))
```
"""
macro userplot(expr::Expr)
if expr.head != :type
errror("Must call userplot on a type/immutable expression. Got: $expr")
end
typename = expr.args[2]
funcname = symbol(lowercase(string(typename)))
funcname2 = symbol(funcname, "!")
# @show typename funcname expr
# return a code block with the type definition and convenience plotting methods
ret = esc(quote
$expr
$funcname(args...; kw...) = plot($typename(args...); kw...)
$funcname2(args...; kw...) = plot!($typename(args...); kw...)
end)
# dump(ret,20)
# @show ret
ret
end
# ----------------------------------------------------------------------------------
# ----------------------------------------------------------------------------------
abstract PlotRecipe abstract PlotRecipe
getRecipeXY(recipe::PlotRecipe) = Float64[], Float64[] getRecipeXY(recipe::PlotRecipe) = Float64[], Float64[]

View File

@ -63,6 +63,10 @@ function convertToAnyVector(v::AVec, d::KW)
end end
function convertToAnyVector(args...)
error("No recipes could handle the argument types: $(map(typeof, args[1:end-1]))")
end
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array # TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array