diff --git a/src/Plots.jl b/src/Plots.jl index 4da481e2..ec46030c 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -222,8 +222,8 @@ plot3d(args...; kw...) = plot(args...; kw..., linetype = :path3d) plot3d!(args...; kw...) = plot!(args...; kw..., linetype = :path3d) scatter3d(args...; kw...) = plot(args...; kw..., linetype = :scatter3d) scatter3d!(args...; kw...) = plot!(args...; kw..., linetype = :scatter3d) -boxplot(args...; kw...) = plot(args...; kw..., linetype = :box) -boxplot!(args...; kw...) = plot!(args...; kw..., linetype = :box) +boxplot(args...; kw...) = plot(args...; kw..., linetype = :boxplot) +boxplot!(args...; kw...) = plot!(args...; kw..., linetype = :boxplot) violin(args...; kw...) = plot(args...; kw..., linetype = :violin) violin!(args...; kw...) = plot!(args...; kw..., linetype = :violin) quiver(args...; kw...) = plot(args...; kw..., linetype = :quiver) diff --git a/src/args.jl b/src/args.jl index 07991160..99cdf3b9 100644 --- a/src/args.jl +++ b/src/args.jl @@ -11,7 +11,7 @@ const _3dTypes = [:path3d, :scatter3d, :surface, :wireframe, :contour3d] const _allTypes = vcat([ :none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :hist2d, :hist3d, :density, :bar, :hline, :vline, :ohlc, - :contour, :pie, :shape, :box, :violin, :quiver, :image + :contour, :pie, :shape, :image #, :boxplot, :violin, :quiver, ], _3dTypes) @compat const _typeAliases = KW( :n => :none, @@ -38,7 +38,7 @@ const _allTypes = vcat([ :shapes => :shape, :poly => :shape, :polygon => :shape, - :boxplot => :box, + :box => :boxplot, :velocity => :quiver, :gradient => :quiver, :img => :image, diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index 83d14409..11db8afc 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -28,7 +28,7 @@ supportedAxes(::GadflyBackend) = [:auto, :left] supportedTypes(::GadflyBackend) = [ :none, :line, :path, :steppre, :steppost, :sticks, :scatter, :hist2d, :hexbin, :hist, - :bar, :box, :violin, :quiver, + :bar, #:box, :violin, :quiver, :hline, :vline, :contour, :shape ] supportedStyles(::GadflyBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 8e68e678..3d9e3ddc 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -40,7 +40,7 @@ supportedAxes(::PyPlotBackend) = _allAxes supportedTypes(::PyPlotBackend) = [ :none, :line, :path, :steppre, :steppost, :shape, :scatter, :hist2d, :hexbin, :hist, :density, - :bar, :sticks, :box, :violin, :quiver, + :bar, :sticks, #:box, :violin, :quiver, :hline, :vline, :heatmap, :pie, :image, :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe ] diff --git a/src/plot.jl b/src/plot.jl index a4d23573..fb98f131 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -86,12 +86,15 @@ end # natively by the backend function _apply_series_recipe(plt::Plot, d::KW) lt = d[:linetype] + # dumpdict(d, "apply_series_recipe", true) if lt in supportedTypes() + # println("adding series!!") + warnOnUnsupported(plt.backend, d) _add_series(plt.backend, plt, d) else # get a sub list of series for this linetype - try - series_list = RecipesBase.apply_recipe(Val{lt}, d[:x], d[:y], d[:z]) + series_list = try + RecipesBase.apply_recipe(d, Val{lt}, d[:x], d[:y], d[:z]) catch warn("Exception during apply_recipe(Val{$lt}, ...) with types ($(typeof(d[:x])), $(typeof(d[:y])), $(typeof(d[:z])))") rethrow() @@ -142,12 +145,25 @@ function _plot!(plt::Plot, d::KW, args...) next_series = pop!(still_to_process) series_list = RecipesBase.apply_recipe(next_series.d, next_series.args...) for series in series_list + # @show series if isempty(series.args) # finish processing and add to the kw_list _add_markershape(series.d) _filter_input_data!(series.d) warnOnUnsupportedArgs(plt.backend, series.d) warnOnUnsupportedScales(plt.backend, series.d) + + # TODO: + # # map functions to vectors + # if isa(d[:marker_z], Function) + # d[:marker_z] = map(d[:marker_z], d[:x]) + # end + # # handle ribbons + # if get(d, :ribbon, nothing) != nothing + # rib = d[:ribbon] + # d[:fillrange] = (d[:y] - rib, d[:y] + rib) + # end + push!(kw_list, series.d) else push!(still_to_process, series) @@ -229,7 +245,7 @@ function _plot!(plt::Plot, d::KW, args...) # todo: while the linetype is not supported, try to apply a recipe of f(Val{lt}, x,y,z) recursively # the default should throw an error because we can't handle that linetype - _apply_series_recipe(kw) + _apply_series_recipe(plt, kw) # _add_series(plt.backend, plt, kw) diff --git a/src/recipes.jl b/src/recipes.jl index b3c8cc13..5d24cc74 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -204,28 +204,42 @@ end # --------------------------------------------------------------------------- -""" -`apply_series_recipe` should take a processed series KW dict and break it up -into component parts. For example, a box plot is made up of `shape` for the -boxes, `path` for the lines, and `scatter` for the outliers. +# """ +# `apply_series_recipe` should take a processed series KW dict and break it up +# into component parts. For example, a box plot is made up of `shape` for the +# boxes, `path` for the lines, and `scatter` for the outliers. +# +# Returns a Vector{KW}. +# """ +# apply_series_recipe(d::KW, lt) = KW[d] -Returns a Vector{KW}. -""" -apply_series_recipe(d::KW, lt) = KW[d] + +# for linetype `line`, need to sort by x values +@recipe function f(::Type{Val{:line}}, x, y, z) + # order by x + indices = sortperm(d[:x]) + d[:x] = d[:x][indices] + d[:y] = d[:y][indices] + if typeof(d[:z]) <: AVec + d[:z] = d[:z][indices] + end + d[:linetype] = :path + () +end # --------------------------------------------------------------------------- # Box Plot const _box_halfwidth = 0.4 -function apply_series_recipe(d::KW, ::Type{Val{:box}}) +# function apply_series_recipe(d::KW, ::Type{Val{:box}}) +@recipe function f(::Type{Val{:boxplot}}, x, y, z) # dumpdict(d, "box before", true) # TODO: add scatter series with outliers # create a list of shapes, where each shape is a single boxplot shapes = Shape[] - d[:linetype] = :shape - groupby = extractGroupArgs(d[:x]) + groupby = extractGroupArgs(x) for (i, glabel) in enumerate(groupby.groupLabels) @@ -249,10 +263,16 @@ function apply_series_recipe(d::KW, ::Type{Val{:box}}) push!(shapes, Shape(xcoords, ycoords)) end - d[:x], d[:y] = shape_coords(shapes) - d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) + # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) - KW[d] + d[:linetype] = :shape + xticklabels --> groupby.groupLabels + + # we want to set the fields directly inside series recipes... args are ignored + d[:x], d[:y] = shape_coords(shapes) + () # expects a tuple returned + + # KW[d] end # --------------------------------------------------------------------------- @@ -260,17 +280,13 @@ end # if the user has KernelDensity installed, use this for violin plots. # otherwise, just use a histogram -try - Pkg.installed("KernelDensity") - import KernelDensity - - # warn("using KD for violin") +if is_installed("KernelDensity") + @eval import KernelDensity @eval function violin_coords(y) kd = KernelDensity.kde(y, npoints = 30) kd.density, kd.x end -catch - # warn("using hist for violin") +else @eval function violin_coords(y) edges, widths = hist(y, 20) centers = 0.5 * (edges[1:end-1] + edges[2:end]) @@ -280,13 +296,13 @@ catch end -function apply_series_recipe(d::KW, ::Type{Val{:violin}}) +# function apply_series_recipe(d::KW, ::Type{Val{:violin}}) +@recipe function f(::Type{Val{:violin}}, x, y, z) # dumpdict(d, "box before", true) # TODO: add scatter series with outliers # create a list of shapes, where each shape is a single boxplot shapes = Shape[] - d[:linetype] = :shape groupby = extractGroupArgs(d[:x]) for (i, glabel) in enumerate(groupby.groupLabels) @@ -304,10 +320,14 @@ function apply_series_recipe(d::KW, ::Type{Val{:violin}}) push!(shapes, Shape(xcoords, ycoords)) end - d[:x], d[:y] = shape_coords(shapes) - d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) + # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) + d[:linetype] = :shape + xticklabels --> groupby.groupLabels - KW[d] + d[:x], d[:y] = shape_coords(shapes) + () + + # KW[d] end # --------------------------------------------------------------------------- @@ -353,18 +373,22 @@ end # we will create a series of path segments, where each point represents one # side of an errorbar -function apply_series_recipe(d::KW, ::Type{Val{:yerror}}) +# function apply_series_recipe(d::KW, ::Type{Val{:yerror}}) +@recipe function f(::Type{Val{:yerror}}, x, y, z) error_style!(d) d[:markershape] = :hline d[:x], d[:y] = error_coords(d[:x], d[:y], error_zipit(d[:yerror])) - KW[d] + # KW[d] + () end -function apply_series_recipe(d::KW, ::Type{Val{:xerror}}) +# function apply_series_recipe(d::KW, ::Type{Val{:xerror}}) +@recipe function f(::Type{Val{:xerror}}, x, y, z) error_style!(d) d[:markershape] = :vline d[:y], d[:x] = error_coords(d[:y], d[:x], error_zipit(d[:xerror])) - KW[d] + # KW[d] + () end @@ -407,7 +431,7 @@ function quiver_using_arrows(d::KW) end d[:x], d[:y] = x, y - KW[d] + # KW[d] end # function apply_series_recipe(d::KW, ::Type{Val{:quiver}}) @@ -453,15 +477,17 @@ function quiver_using_hack(d::KW) end d[:x], d[:y] = Plots.unzip(pts[2:end]) - KW[d] + # KW[d] end -function apply_series_recipe(d::KW, ::Type{Val{:quiver}}) +# function apply_series_recipe(d::KW, ::Type{Val{:quiver}}) +@recipe function f(::Type{Val{:quiver}}, x, y, z) if :arrow in supportedArgs() quiver_using_arrows(d) else quiver_using_hack(d) end + () end diff --git a/src/series_new.jl b/src/series_new.jl index bb8dbae8..5d380941 100644 --- a/src/series_new.jl +++ b/src/series_new.jl @@ -77,7 +77,7 @@ function _add_defaults!(d::KW, plt::Plot, commandIndex::Int) end d[:label] = label - warnOnUnsupported(pkg, d) + # warnOnUnsupported(pkg, d) d end @@ -329,8 +329,8 @@ end # end @recipe function f{X,Y}(x::AVec{X}, y::AVec{Y}, zf::Function) - x = TX <: Number ? sort(x) : x - y = TY <: Number ? sort(y) : y + x = X <: Number ? sort(x) : x + y = Y <: Number ? sort(y) : y SliceIt, x, y, Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported end