default_should_widen; symbol in userplot macro; cleanup in recipes

This commit is contained in:
Thomas Breloff 2016-06-07 16:44:15 -04:00
parent d0209d945d
commit 17189e3125
5 changed files with 83 additions and 55 deletions

View File

@ -206,8 +206,19 @@ function widen(lmin, lmax)
lmin-eps, lmax+eps lmin-eps, lmax+eps
end end
# figure out if widening is a good idea
function default_should_widen(axis::Axis)
should_widen = false
for series in series_list(axis.sp)
if series.d[:seriestype] in (:scatter,) || series.d[:markershape] != :none
should_widen = true
end
end
should_widen
end
# using the axis extrema and limit overrides, return the min/max value for this axis # using the axis extrema and limit overrides, return the min/max value for this axis
function axis_limits(axis::Axis, should_widen::Bool = true) function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis))
ex = axis[:extrema] ex = axis[:extrema]
amin, amax = ex.emin, ex.emax amin, amax = ex.emin, ex.emax
lims = axis[:lims] lims = axis[:lims]

View File

@ -273,16 +273,16 @@ end
# using the axis extrema and limit overrides, return the min/max value for this axis # using the axis extrema and limit overrides, return the min/max value for this axis
gr_x_axislims(sp::Subplot) = axis_limits(sp[:xaxis], true) gr_x_axislims(sp::Subplot) = axis_limits(sp[:xaxis])
gr_y_axislims(sp::Subplot) = axis_limits(sp[:yaxis], true) gr_y_axislims(sp::Subplot) = axis_limits(sp[:yaxis])
gr_z_axislims(sp::Subplot) = axis_limits(sp[:zaxis], true) gr_z_axislims(sp::Subplot) = axis_limits(sp[:zaxis])
gr_xy_axislims(sp::Subplot) = gr_x_axislims(sp)..., gr_y_axislims(sp)... gr_xy_axislims(sp::Subplot) = gr_x_axislims(sp)..., gr_y_axislims(sp)...
function gr_lims(axis::Axis, adjust::Bool, expand = nothing) function gr_lims(axis::Axis, adjust::Bool, expand = nothing)
if expand != nothing if expand != nothing
expand_extrema!(axis, expand) expand_extrema!(axis, expand)
end end
lims = axis_limits(axis, true) lims = axis_limits(axis)
if adjust if adjust
GR.adjustrange(lims...) GR.adjustrange(lims...)
else else

View File

@ -614,7 +614,7 @@ function create_grid_curly(expr::Expr)
for (i,arg) in enumerate(expr.args[2:end]) for (i,arg) in enumerate(expr.args[2:end])
add_layout_pct!(kw, arg, i, length(expr.args)-1) add_layout_pct!(kw, arg, i, length(expr.args)-1)
end end
@show kw # @show kw
:(EmptyLayout(label = $(QuoteNode(s)), width = $(get(kw, :w, QuoteNode(:auto))), height = $(get(kw, :h, QuoteNode(:auto))))) :(EmptyLayout(label = $(QuoteNode(s)), width = $(get(kw, :w, QuoteNode(:auto))), height = $(get(kw, :h, QuoteNode(:auto)))))
end end

View File

@ -22,7 +22,11 @@ end
grouphist(rand(1000,4)) grouphist(rand(1000,4))
``` ```
""" """
macro userplot(expr::Expr) macro userplot(expr)
_userplot(expr)
end
function _userplot(expr::Expr)
if expr.head != :type if expr.head != :type
errror("Must call userplot on a type/immutable expression. Got: $expr") errror("Must call userplot on a type/immutable expression. Got: $expr")
end end
@ -34,11 +38,19 @@ macro userplot(expr::Expr)
# return a code block with the type definition and convenience plotting methods # return a code block with the type definition and convenience plotting methods
esc(quote esc(quote
$expr $expr
$funcname(args...; kw...) = plot($typename(args...); kw...) export $funcname, $funcname2
$funcname2(args...; kw...) = plot!($typename(args...); kw...) $funcname(args...; kw...) = plot($typename(args); kw...)
$funcname2(args...; kw...) = plot!($typename(args); kw...)
end) end)
end end
function _userplot(sym::Symbol)
_userplot(:(type $sym
args
end))
end
# ---------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------
@ -59,14 +71,14 @@ num_series(x::AMat) = size(x,2)
num_series(x) = 1 num_series(x) = 1
# if it's not a recipe, just do nothing and return the args # # if it's not a recipe, just do nothing and return the args
function RecipesBase.apply_recipe(d::KW, args...; issubplot=false) # function RecipesBase.apply_recipe(d::KW, args...; issubplot=false)
if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout) # if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout)
# put in a sensible default # # put in a sensible default
d[:n] = maximum(map(num_series, args)) # d[:n] = maximum(map(num_series, args))
end # end
args # args
end # end
if is_installed("DataFrames") if is_installed("DataFrames")
@ -136,12 +148,12 @@ end
# for seriestype `line`, need to sort by x values # for seriestype `line`, need to sort by x values
@recipe function f(::Type{Val{:line}}, x, y, z) @recipe function f(::Type{Val{:line}}, x, y, z)
indices = sortperm(x) indices = sortperm(x)
d[:x] = x[indices] x := x[indices]
d[:y] = y[indices] y := y[indices]
if typeof(z) <: AVec if typeof(z) <: AVec
d[:z] = z[indices] z := z[indices]
end end
d[:seriestype] = :path seriestype := :path
() ()
end end
@ -154,8 +166,9 @@ end
newx[rng] = x[i] newx[rng] = x[i]
newy[rng] = [0., y[i], 0.] newy[rng] = [0., y[i], 0.]
end end
d[:x], d[:y] = newx, newy x := newx
d[:seriestype] = :path y := newy
seriestype := :path
() ()
end end
@ -164,8 +177,9 @@ end
n = length(y) n = length(y)
newx = repmat(Float64[xmin, xmax, NaN], n) newx = repmat(Float64[xmin, xmax, NaN], n)
newy = vec(Float64[yi for i=1:3,yi=y]) newy = vec(Float64[yi for i=1:3,yi=y])
d[:x], d[:y] = newx, newy x := newx
d[:seriestype] = :path y := newy
seriestype := :path
() ()
end end
@ -174,8 +188,9 @@ end
n = length(y) n = length(y)
newx = vec(Float64[yi for i=1:3,yi=y]) newx = vec(Float64[yi for i=1:3,yi=y])
newy = repmat(Float64[ymin, ymax, NaN], n) newy = repmat(Float64[ymin, ymax, NaN], n)
d[:x], d[:y] = newx, newy x := newx
d[:seriestype] = :path y := newy
seriestype := :path
() ()
end end
@ -255,7 +270,8 @@ sticks_fillfrom(fr::AVec, i::Integer) = fr[mod1(i, length(fr))]
newx[rng] = [x[i], x[i], NaN] newx[rng] = [x[i], x[i], NaN]
newy[rng] = [sticks_fillfrom(fr,i), y[i], NaN] newy[rng] = [sticks_fillfrom(fr,i), y[i], NaN]
end end
d[:x], d[:y] = newx, newy x := newx
y := newy
fillrange := nothing fillrange := nothing
seriestype := :path seriestype := :path
@ -328,10 +344,10 @@ end
fillrng[rng] = [fi, fi, fi] fillrng[rng] = [fi, fi, fi]
end end
d[:x] = x x := x
d[:y] = y y := y
d[:fillrange] = fillrng fillrange := fillrng
d[:seriestype] = :path seriestype := :path
() ()
end end
@ -378,10 +394,12 @@ end
@recipe function f(::Type{Val{:histogram}}, x, y, z) @recipe function f(::Type{Val{:histogram}}, x, y, z)
edges, counts = my_hist(y, d[:bins], normed = d[:normalize], weights = d[:weights]) edges, counts = my_hist(y, d[:bins],
d[:x] = edges normed = d[:normalize],
d[:y] = counts weights = d[:weights])
d[:seriestype] = :bar x := edges
y := counts
seriestype := :bar
() ()
end end
@ -416,11 +434,13 @@ end
centers(v::AVec) = v[1] + cumsum(diff(v)) centers(v::AVec) = v[1] + cumsum(diff(v))
@recipe function f(::Type{Val{:histogram2d}}, x, y, z) @recipe function f(::Type{Val{:histogram2d}}, x, y, z)
xedges, yedges, counts = my_hist_2d(x, y, d[:bins], normed = d[:normalize], weights = d[:weights]) xedges, yedges, counts = my_hist_2d(x, y, d[:bins],
d[:x] = centers(xedges) normed = d[:normalize],
d[:y] = centers(yedges) weights = d[:weights])
d[:z] = Surface(counts) x := centers(xedges)
d[:seriestype] = :heatmap y := centers(yedges)
z := Surface(counts)
seriestype := :heatmap
() ()
end end
@ -501,7 +521,7 @@ notch_width(q2, q4, N) = 1.58 * (q4-q2)/sqrt(N)
# d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels))
d[:seriestype] = :shape seriestype := :shape
n = length(groupby.groupLabels) n = length(groupby.groupLabels)
xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels) xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels)
@ -574,7 +594,7 @@ end
end end
# d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels))
d[:seriestype] = :shape seriestype := :shape
n = length(groupby.groupLabels) n = length(groupby.groupLabels)
xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels) xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels)
@ -592,7 +612,8 @@ end
if isvertical(d) if isvertical(d)
newx, newy = newy, newx newx, newy = newy, newx
end end
d[:x], d[:y] = newx, newy x := newx
y := newy
seriestype := :path seriestype := :path
() ()
end end
@ -642,21 +663,17 @@ end
# we will create a series of path segments, where each point represents one # we will create a series of path segments, where each point represents one
# side of an errorbar # side of an errorbar
# function apply_series_recipe(d::KW, ::Type{Val{:yerror}})
@recipe function f(::Type{Val{:yerror}}, x, y, z) @recipe function f(::Type{Val{:yerror}}, x, y, z)
error_style!(d) error_style!(d)
d[:markershape] = :hline markershape := :hline
d[:x], d[:y] = error_coords(d[:x], d[:y], error_zipit(d[:yerror])) d[:x], d[:y] = error_coords(d[:x], d[:y], error_zipit(d[:yerror]))
# KW[d]
() ()
end end
# function apply_series_recipe(d::KW, ::Type{Val{:xerror}})
@recipe function f(::Type{Val{:xerror}}, x, y, z) @recipe function f(::Type{Val{:xerror}}, x, y, z)
error_style!(d) error_style!(d)
d[:markershape] = :vline markershape := :vline
d[:y], d[:x] = error_coords(d[:y], d[:x], error_zipit(d[:xerror])) d[:y], d[:x] = error_coords(d[:y], d[:x], error_zipit(d[:xerror]))
# KW[d]
() ()
end end
@ -705,8 +722,8 @@ end
# function apply_series_recipe(d::KW, ::Type{Val{:quiver}}) # function apply_series_recipe(d::KW, ::Type{Val{:quiver}})
function quiver_using_hack(d::KW) function quiver_using_hack(d::KW)
d[:label] = "" label := ""
d[:seriestype] = :shape seriestype := :shape
velocity = error_zipit(d[:quiver]) velocity = error_zipit(d[:quiver])
xorig, yorig = d[:x], d[:y] xorig, yorig = d[:x], d[:y]
@ -855,12 +872,12 @@ end
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(x::AVec, ohlc::AVec{Tuple{R1,R2,R3,R4}}) = x, OHLC[OHLC(t...) for t in ohlc] @recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(x::AVec, ohlc::AVec{Tuple{R1,R2,R3,R4}}) = x, OHLC[OHLC(t...) for t in ohlc]
@recipe function f(x::AVec, v::AVec{OHLC}) @recipe function f(x::AVec, v::AVec{OHLC})
d[:seriestype] = :path seriestype := :path
get_xy(v, x) get_xy(v, x)
end end
@recipe function f(v::AVec{OHLC}) @recipe function f(v::AVec{OHLC})
d[:seriestype] = :path seriestype := :path
get_xy(v) get_xy(v)
end end

View File

@ -235,7 +235,7 @@ end
function fakedata(sz...) function fakedata(sz...)
y = zeros(sz...) y = zeros(sz...)
for r in 2:size(y,1) for r in 2:size(y,1)
y[r,:] = 0.95 * y[r-1,:] + randn(size(y,2))' y[r,:] = 0.95 * y[r-1,:] + randn(size(y,2))
end end
y y
end end