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 FixedSizeArrays
@reexport using RecipesBase
using Base.Meta
export
AbstractPlot,
@ -40,53 +41,54 @@ export
default,
with,
scatter,
scatter!,
bar,
bar!,
barh,
barh!,
histogram,
histogram!,
histogram2d,
histogram2d!,
density,
density!,
heatmap,
heatmap!,
hexbin,
hexbin!,
sticks,
sticks!,
hline,
hline!,
vline,
vline!,
ohlc,
ohlc!,
@userplot,
# scatter,
# scatter!,
# bar,
# bar!,
# barh,
# barh!,
# histogram,
# histogram!,
# histogram2d,
# histogram2d!,
# density,
# density!,
# heatmap,
# heatmap!,
# hexbin,
# hexbin!,
# sticks,
# sticks!,
# hline,
# hline!,
# vline,
# vline!,
# ohlc,
# ohlc!,
pie,
pie!,
contour,
contour!,
contour3d,
contour3d!,
surface,
surface!,
wireframe,
wireframe!,
path3d,
path3d!,
# contour,
# contour!,
# contour3d,
# contour3d!,
# surface,
# surface!,
# wireframe,
# wireframe!,
# path3d,
# path3d!,
plot3d,
plot3d!,
scatter3d,
scatter3d!,
abline!,
boxplot,
boxplot!,
violin,
violin!,
quiver,
quiver!,
# scatter3d,
# scatter3d!,
# abline!,
# boxplot,
# boxplot!,
# violin,
# violin!,
# quiver,
# quiver!,
title!,
xlabel!,
@ -199,52 +201,88 @@ include("output.jl")
# ---------------------------------------------------------
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)
# define and export shorthand plotting method definitions
macro shorthands(funcname::Symbol)
funcname2 = symbol(funcname, "!")
ret = esc(quote
export $funcname, $funcname2
$funcname(args...; kw...) = plot(args...; kw..., seriestype = $(quot(funcname)))
$funcname2(args...; kw...) = plot!(args...; kw..., seriestype = $(quot(funcname)))
end)
# dump(ret,20)
# @show ret
ret
end
@shorthands scatter
@shorthands bar
@shorthands barh
@shorthands histogram
@shorthands histogram2d
@shorthands density
@shorthands heatmap
@shorthands hexbin
@shorthands sticks
@shorthands hline
@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)
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)
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)
path3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
path3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
# 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)
# 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)
# 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)
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)
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)
# 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)
# 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)
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
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;
label = d[:label],
zorder = plt.n,

View File

@ -5,6 +5,51 @@
# 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:
```
@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
getRecipeXY(recipe::PlotRecipe) = Float64[], Float64[]

View File

@ -63,6 +63,10 @@ function convertToAnyVector(v::AVec, d::KW)
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