diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 7f7c7903..3b7fde08 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -764,11 +764,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) elseif st == :shape # draw the shapes - gr_set_line(d[:markerstrokewidth], :solid, d[:markerstrokecolor], d[:markerstrokealpha]) + gr_set_line(d[:linewidth], :solid, d[:linecolor], d[:linealpha]) gr_polyline(d[:x], d[:y]) # draw the interior - gr_set_fill(d[:markercolor], d[:markeralpha]) + gr_set_fill(d[:fillcolor], d[:fillalpha]) gr_polyline(d[:x], d[:y], GR.fillarea) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 325ab4e0..666d8b3e 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -374,12 +374,12 @@ function plotly_series(plt::Plot, series::Series) # @show map(length, (x,y,d_out[:x],d_out[:y])) # @show d_out[:x] d_out[:y] d_out[:fill] = "tozeroy" - d_out[:fillcolor] = webcolor(d[:markercolor], d[:markeralpha]) + d_out[:fillcolor] = webcolor(d[:fillcolor], d[:fillalpha]) if d[:markerstrokewidth] > 0 d_out[:line] = KW( - :color => webcolor(d[:markerstrokecolor], d[:markerstrokealpha]), - :width => d[:markerstrokewidth], - :dash => string(d[:markerstrokestyle]), + :color => webcolor(d[:linecolor], d[:linealpha]), + :width => d[:linewidth], + :dash => string(d[:linestyle]), ) end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 7a1f8b63..cc0ce89f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -816,9 +816,9 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) patches = pypatches.pymember("PathPatch")(path; label = d[:label], zorder = plt.n, - edgecolor = py_markerstrokecolor(d), - facecolor = py_markercolor(d), - linewidth = d[:markerstrokewidth], + edgecolor = py_linecolor(d), + facecolor = py_fillcolor(d), + linewidth = d[:linewidth], fill = true ) handle = ax[:add_patch](patches) diff --git a/src/examples.jl b/src/examples.jl index 23898bd2..83b70556 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -303,8 +303,8 @@ PlotExample("Boxplot and Violin series recipes", [:(begin import RDatasets singers = RDatasets.dataset("lattice", "singer") - violin(singers, :VoicePart, :Height, marker = (0.2, :blue, stroke(0))) - boxplot!(singers, :VoicePart, :Height, marker = (0.3, :orange, stroke(2))) + violin(singers, :VoicePart, :Height, line = 0, fill = (0.2, :blue)) + boxplot!(singers, :VoicePart, :Height, line = (2,:black), fill = (0.3, :orange)) end)] ) diff --git a/src/recipes.jl b/src/recipes.jl index baf44955..f2bc9c0f 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -454,20 +454,8 @@ end if fillto == nothing fillto = 0 end - # if fillto == nothing - # fillto = zeros(1) - # elseif isa(fillto, Number) - # fillto = Float64[fillto] - # end - # nf = length(fillto) - # npts = 3ny + 1 - # heights = y - # x = zeros(npts) - # y = zeros(npts) - # fillrng = zeros(npts) - - # shapes = Shape[] + # create the bar shapes by adding x/y segments xseg, yseg = Segments(), Segments() for i=1:ny fi = cycle(fillto,i) @@ -475,21 +463,6 @@ end push!(yseg, y[i], fi, fi, y[i]) end - - # # create the path in triplets. after the first bottom-left coord of the first bar: - # # add the top-left, top-right, and bottom-right coords for each height - # x[1] = edges[1] - # y[1] = fillto[1] - # fillrng[1] = fillto[1] - # for i=1:ny - # idx = 3i - # rng = idx-1:idx+1 - # fi = fillto[mod1(i,nf)] - # x[rng] = [edges[i], edges[i+1], edges[i+1]] - # y[rng] = [heights[i], heights[i], fi] - # fillrng[rng] = [fi, fi, fi] - # end - # switch back if !isvertical(d) xseg, yseg = yseg, xseg @@ -497,8 +470,6 @@ end x := xseg.pts y := yseg.pts - # fillrange := fillrng - # seriestype := :path seriestype := :shape () end @@ -623,27 +594,25 @@ const _box_halfwidth = 0.4 notch_width(q2, q4, N) = 1.58 * (q4-q2)/sqrt(N) -# function apply_series_recipe(d::KW, ::Type{Val{:box}}) + @recipe function f(::Type{Val{:boxplot}}, x, y, z; notch=false, range=1.5) - # Plots.dumpdict(d, "box before", true) - - # create a list of shapes, where each shape is a single boxplot - shapes = Shape[] - groupby = extractGroupArgs(x) - outliers_y = Float64[] - outliers_x = Float64[] - + delete!(d, :notch) + delete!(d, :range) + xsegs, ysegs = Segments(), Segments() + glabels = sort(collect(unique(x))) warning = false + outliers_x, outliers_y = zeros(0), zeros(0) + for glabel in glabels + # filter y + values = y[filter(i -> cycle(x,i) == glabel, 1:length(y))] - for (i, glabel) in enumerate(groupby.groupLabels) - - # filter y values - values = d[:y][groupby.groupIds[i]] - # then compute quantiles + # compute quantiles q1,q2,q3,q4,q5 = quantile(values, linspace(0,1,5)) + # notch n = notch_width(q2, q4, length(values)) + # warn on inverted notches? if notch && !warning && ( (q2>(q3-n)) || (q4<(q3+n)) ) warn("Boxplot's notch went outside hinges. Set notch to false.") warning = true # Show the warning only one time @@ -652,8 +621,10 @@ notch_width(q2, q4, N) = 1.58 * (q4-q2)/sqrt(N) # make the shape center = discrete_value!(d[:subplot][:xaxis], glabel)[1] l, m, r = center - _box_halfwidth, center, center + _box_halfwidth + # internal nodes for notches L, R = center - 0.5 * _box_halfwidth, center + 0.5 * _box_halfwidth + # outliers if Float64(range) != 0.0 # if the range is 0.0, the whiskers will extend to the data limit = range*(q4-q2) @@ -670,58 +641,144 @@ notch_width(q2, q4, N) = 1.58 * (q4-q2)/sqrt(N) # using maximum and minimum values inside the limits q1, q5 = extrema(inside) end + # Box - xcoords = notch::Bool ? [ - m, l, r, m, m, NaN, # lower T - l, l, L, R, r, r, l, NaN, # lower box - l, l, L, R, r, r, l, NaN, # upper box - m, l, r, m, m, NaN, # upper T - ] : [ - m, l, r, m, m, NaN, # lower T - l, l, r, r, l, NaN, # lower box - l, l, r, r, l, NaN, # upper box - m, l, r, m, m, NaN, # upper T - ] - ycoords = notch::Bool ? [ - q1, q1, q1, q1, q2, NaN, # lower T - q2, q3-n, q3, q3, q3-n, q2, q2, NaN, # lower box - q4, q3+n, q3, q3, q3+n, q4, q4, NaN, # upper box - q5, q5, q5, q5, q4, NaN, # upper T - ] : [ - q1, q1, q1, q1, q2, NaN, # lower T - q2, q3, q3, q2, q2, NaN, # lower box - q4, q3, q3, q4, q4, NaN, # upper box - q5, q5, q5, q5, q4, NaN, # upper T - ] - push!(shapes, Shape(xcoords, ycoords)) + if notch + push!(xsegs, m, l, r, m, m) # lower T + push!(xsegs, l, l, L, R, r, r, l) # lower box + push!(xsegs, l, l, L, R, r, r, l) # upper box + push!(xsegs, m, l, r, m, m) # upper T + + push!(ysegs, q1, q1, q1, q1, q2) # lower T + push!(ysegs, q2, q3-n, q3, q3, q3-n, q2, q2) # lower box + push!(ysegs, q4, q3+n, q3, q3, q3+n, q4, q4) # upper box + push!(ysegs, q5, q5, q5, q5, q4) # upper T + else + push!(xsegs, m, l, r, m, m) # lower T + push!(xsegs, l, l, r, r, l) # lower box + push!(xsegs, l, l, r, r, l) # upper box + push!(xsegs, m, l, r, m, m) # upper T + + push!(ysegs, q1, q1, q1, q1, q2) # lower T + push!(ysegs, q2, q3, q3, q2, q2) # lower box + push!(ysegs, q4, q3, q3, q4, q4) # upper box + push!(ysegs, q5, q5, q5, q5, q4) # upper T + end end - # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) - - seriestype := :shape - # n = length(groupby.groupLabels) - # xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels) - - # clean d - pop!(d, :notch) - pop!(d, :range) - - # we want to set the fields directly inside series recipes... args are ignored - d[:x], d[:y] = Plots.shape_coords(shapes) - # Outliers @series begin - seriestype := :scatter - markershape := :circle - x := outliers_x - y := outliers_y - label := "" - primary := false + seriestype := :scatter + markershape --> :circle + x := outliers_x + y := outliers_y + primary := false () end - () # expects a tuple returned + seriestype := :shape + x := xsegs.pts + y := ysegs.pts + () end + +# @recipe function f(::Type{Val{:boxplot}}, x, y, z; notch=false, range=1.5) +# # Plots.dumpdict(d, "box before", true) + +# # create a list of shapes, where each shape is a single boxplot +# shapes = Shape[] +# groupby = extractGroupArgs(x) +# outliers_y = Float64[] +# outliers_x = Float64[] + +# warning = false + +# for (i, glabel) in enumerate(groupby.groupLabels) + +# # filter y values +# values = d[:y][groupby.groupIds[i]] +# # then compute quantiles +# q1,q2,q3,q4,q5 = quantile(values, linspace(0,1,5)) +# # notch +# n = notch_width(q2, q4, length(values)) + +# if notch && !warning && ( (q2>(q3-n)) || (q4<(q3+n)) ) +# warn("Boxplot's notch went outside hinges. Set notch to false.") +# warning = true # Show the warning only one time +# end + +# # make the shape +# center = discrete_value!(d[:subplot][:xaxis], glabel)[1] +# l, m, r = center - _box_halfwidth, center, center + _box_halfwidth +# # internal nodes for notches +# L, R = center - 0.5 * _box_halfwidth, center + 0.5 * _box_halfwidth +# # outliers +# if Float64(range) != 0.0 # if the range is 0.0, the whiskers will extend to the data +# limit = range*(q4-q2) +# inside = Float64[] +# for value in values +# if (value < (q2 - limit)) || (value > (q4 + limit)) +# push!(outliers_y, value) +# push!(outliers_x, center) +# else +# push!(inside, value) +# end +# end +# # change q1 and q5 to show outliers +# # using maximum and minimum values inside the limits +# q1, q5 = extrema(inside) +# end +# # Box +# xcoords = notch::Bool ? [ +# m, l, r, m, m, NaN, # lower T +# l, l, L, R, r, r, l, NaN, # lower box +# l, l, L, R, r, r, l, NaN, # upper box +# m, l, r, m, m, NaN, # upper T +# ] : [ +# m, l, r, m, m, NaN, # lower T +# l, l, r, r, l, NaN, # lower box +# l, l, r, r, l, NaN, # upper box +# m, l, r, m, m, NaN, # upper T +# ] +# ycoords = notch::Bool ? [ +# q1, q1, q1, q1, q2, NaN, # lower T +# q2, q3-n, q3, q3, q3-n, q2, q2, NaN, # lower box +# q4, q3+n, q3, q3, q3+n, q4, q4, NaN, # upper box +# q5, q5, q5, q5, q4, NaN, # upper T +# ] : [ +# q1, q1, q1, q1, q2, NaN, # lower T +# q2, q3, q3, q2, q2, NaN, # lower box +# q4, q3, q3, q4, q4, NaN, # upper box +# q5, q5, q5, q5, q4, NaN, # upper T +# ] +# push!(shapes, Shape(xcoords, ycoords)) +# end + +# # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) + +# seriestype := :shape +# # n = length(groupby.groupLabels) +# # xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels) + +# # clean d +# pop!(d, :notch) +# pop!(d, :range) + +# # we want to set the fields directly inside series recipes... args are ignored +# d[:x], d[:y] = Plots.shape_coords(shapes) + +# # Outliers +# @series begin +# seriestype := :scatter +# markershape --> :circle +# x := outliers_x +# y := outliers_y +# primary := false +# () +# end + +# () # expects a tuple returned +# end @deps boxplot shape scatter # --------------------------------------------------------------------------- diff --git a/src/series_args.jl b/src/series_args.jl index f822c918..1826458b 100644 --- a/src/series_args.jl +++ b/src/series_args.jl @@ -97,445 +97,3 @@ compute_xyz(x::Void, y::Void, z::FuncOrFuncs) = error("If you want to plot the f compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!") # -------------------------------------------------------------------- - -# # create n=max(mx,my) series arguments. the shorter list is cycled through -# # note: everything should flow through this -# function build_series_args(plt::AbstractPlot, kw::KW) #, idxfilter) -# x, y, z = map(sym -> pop!(kw, sym, nothing), (:x, :y, :z)) -# if nothing == x == y == z -# return [], nothing, nothing -# end -# -# xs, xmeta = convertToAnyVector(x, kw) -# ys, ymeta = convertToAnyVector(y, kw) -# zs, zmeta = convertToAnyVector(z, kw) -# -# fr = pop!(kw, :fillrange, nothing) -# fillranges, _ = if typeof(fr) <: Number -# ([fr],nothing) -# else -# convertToAnyVector(fr, kw) -# end -# -# mx = length(xs) -# my = length(ys) -# mz = length(zs) -# ret = Any[] -# for i in 1:max(mx, my, mz) -# -# # try to set labels using ymeta -# d = copy(kw) -# if !haskey(d, :label) && ymeta != nothing -# if isa(ymeta, Symbol) -# d[:label] = string(ymeta) -# elseif isa(ymeta, AVec{Symbol}) -# d[:label] = string(ymeta[mod1(i,length(ymeta))]) -# end -# end -# -# # build the series arg dict -# numUncounted = pop!(d, :numUncounted, 0) -# commandIndex = i + numUncounted -# n = plt.n + i -# -# dumpdict(d, "before getSeriesArgs") -# d = getSeriesArgs(plt.backend, getattr(plt, n), d, commandIndex, convertSeriesIndex(plt, n), n) -# dumpdict(d, "after getSeriesArgs") -# -# d[:x], d[:y], d[:z] = compute_xyz(xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)]) -# st = d[:seriestype] -# -# # for seriestype `line`, need to sort by x values -# if st == :line -# # order by x -# indices = sortperm(d[:x]) -# d[:x] = d[:x][indices] -# d[:y] = d[:y][indices] -# d[:seriestype] = :path -# end -# -# # special handling for missing x in box plot... all the same category -# if st == :box && xs[mod1(i,mx)] == nothing -# d[:x] = ones(Int, length(d[:y])) -# end -# -# # map functions to vectors -# if isa(d[:marker_z], Function) -# d[:marker_z] = map(d[:marker_z], d[:x]) -# end -# -# # @show fillranges -# d[:fillrange] = fillranges[mod1(i,length(fillranges))] -# if isa(d[:fillrange], Function) -# d[:fillrange] = map(d[:fillrange], d[:x]) -# end -# -# # handle error bars -# for esym in (:xerror, :yerror) -# if get(d, esym, nothing) != nothing -# # we make a copy of the KW and apply an errorbar recipe -# append!(ret, apply_series_recipe(copy(d), Val{esym})) -# end -# end -# -# # handle ribbons -# if get(d, :ribbon, nothing) != nothing -# rib = d[:ribbon] -# d[:fillrange] = (d[:y] - rib, d[:y] + rib) -# end -# -# # handle quiver plots -# # either a series of velocity vectors are passed in (`:quiver` keyword), -# # or we just add arrows to the path -# -# # if st == :quiver -# # d[:seriestype] = st = :path -# # d[:linewidth] = 0 -# # end -# if get(d, :quiver, nothing) != nothing -# append!(ret, apply_series_recipe(copy(d), Val{:quiver})) -# elseif st == :quiver -# d[:seriestype] = st = :path -# d[:arrow] = arrow() -# end -# -# # now that we've processed a given series... optionally split into -# # multiple dicts through a recipe (for example, a box plot is split into component -# # parts... polygons, lines, and scatters) -# # note: we pass in a Val type (i.e. Val{:box}) so that we can dispatch on the seriestype -# kwlist = apply_series_recipe(d, Val{st}) -# append!(ret, kwlist) -# -# # # add it to our series list -# # push!(ret, d) -# end -# -# ret, xmeta, ymeta -# end -# -# -# # -------------------------------------------------------------------- -# # process_inputs -# # -------------------------------------------------------------------- -# -# # These methods take a plot and the keyword arguments, and processes the input -# # arguments (x/y/z, group, etc), populating the KW dict with appropriate values. -# -# # -------------------------------------------------------------------- -# # 0 arguments -# # -------------------------------------------------------------------- -# -# # don't do anything -# function process_inputs(plt::AbstractPlot, d::KW) -# end -# -# # -------------------------------------------------------------------- -# # 1 argument -# # -------------------------------------------------------------------- -# -# function process_inputs(plt::AbstractPlot, d::KW, n::Integer) -# # d[:x], d[:y], d[:z] = zeros(0), zeros(0), zeros(0) -# d[:x] = d[:y] = d[:z] = n -# end -# -# # no special handling... assume x and z are nothing -# function process_inputs(plt::AbstractPlot, d::KW, y) -# d[:y] = y -# end -# -# # matrix... is it z or y? -# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, mat::AMat{T}) -# if all3D(d) -# n,m = size(mat) -# d[:x], d[:y], d[:z] = 1:n, 1:m, mat -# else -# d[:y] = mat -# end -# end -# -# # images - grays -# function process_inputs{T<:Gray}(plt::AbstractPlot, d::KW, mat::AMat{T}) -# d[:seriestype] = :image -# n,m = size(mat) -# d[:x], d[:y], d[:z] = 1:n, 1:m, Surface(mat) -# # handle images... when not supported natively, do a hack to use heatmap machinery -# if !nativeImagesSupported() -# d[:seriestype] = :heatmap -# d[:yflip] = true -# d[:z] = Surface(convert(Matrix{Float64}, mat.surf)) -# d[:fillcolor] = ColorGradient([:black, :white]) -# end -# end -# -# # images - colors -# function process_inputs{T<:Colorant}(plt::AbstractPlot, d::KW, mat::AMat{T}) -# d[:seriestype] = :image -# n,m = size(mat) -# d[:x], d[:y], d[:z] = 1:n, 1:m, Surface(mat) -# # handle images... when not supported natively, do a hack to use heatmap machinery -# if !nativeImagesSupported() -# d[:yflip] = true -# imageHack(d) -# end -# end -# -# -# # plotting arbitrary shapes/polygons -# function process_inputs(plt::AbstractPlot, d::KW, shape::Shape) -# d[:x], d[:y] = shape_coords(shape) -# d[:seriestype] = :shape -# end -# function process_inputs(plt::AbstractPlot, d::KW, shapes::AVec{Shape}) -# d[:x], d[:y] = shape_coords(shapes) -# d[:seriestype] = :shape -# end -# function process_inputs(plt::AbstractPlot, d::KW, shapes::AMat{Shape}) -# x, y = [], [] -# for j in 1:size(shapes, 2) -# tmpx, tmpy = shape_coords(vec(shapes[:,j])) -# push!(x, tmpx) -# push!(y, tmpy) -# end -# d[:x], d[:y] = x, y -# d[:seriestype] = :shape -# end -# -# -# # function without range... use the current range of the x-axis -# function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs) -# process_inputs(plt, d, f, xmin(plt), xmax(plt)) -# end -# -# # -------------------------------------------------------------------- -# # 2 arguments -# # -------------------------------------------------------------------- -# -# function process_inputs(plt::AbstractPlot, d::KW, x, y) -# d[:x], d[:y] = x, y -# end -# -# # if functions come first, just swap the order (not to be confused with parametric functions... -# # as there would be more than one function passed in) -# function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, x) -# @assert !(typeof(x) <: FuncOrFuncs) # otherwise we'd hit infinite recursion here -# process_inputs(plt, d, x, f) -# end -# -# # -------------------------------------------------------------------- -# # 3 arguments -# # -------------------------------------------------------------------- -# -# # no special handling... just pass them through -# function process_inputs(plt::AbstractPlot, d::KW, x, y, z) -# d[:x], d[:y], d[:z] = x, y, z -# end -# -# # 3d line or scatter -# function process_inputs(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zvec::AVec) -# # default to path3d if we haven't set a 3d seriestype -# st = get(d, :seriestype, :none) -# if st == :scatter -# d[:seriestype] = :scatter3d -# elseif !(st in _3dTypes) -# d[:seriestype] = :path3d -# end -# d[:x], d[:y], d[:z] = x, y, zvec -# end -# -# # surface-like... function -# function process_inputs{TX,TY}(plt::AbstractPlot, d::KW, x::AVec{TX}, y::AVec{TY}, zf::Function) -# x = TX <: Number ? sort(x) : x -# y = TY <: Number ? sort(y) : y -# # x, y = sort(x), sort(y) -# d[:z] = Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported -# d[:x], d[:y] = x, y -# end -# -# # surface-like... matrix grid -# function process_inputs{TX,TY,TZ}(plt::AbstractPlot, d::KW, x::AVec{TX}, y::AVec{TY}, zmat::AMat{TZ}) -# # @assert size(zmat) == (length(x), length(y)) -# # if TX <: Number && !issorted(x) -# # idx = sortperm(x) -# # x, zmat = x[idx], zmat[idx, :] -# # end -# # if TY <: Number && !issorted(y) -# # idx = sortperm(y) -# # y, zmat = y[idx], zmat[:, idx] -# # end -# d[:x], d[:y], d[:z] = x, y, Surface{Matrix{TZ}}(zmat) -# if !like_surface(get(d, :seriestype, :none)) -# d[:seriestype] = :contour -# end -# end -# -# # surfaces-like... general x, y grid -# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, x::AMat{T}, y::AMat{T}, zmat::AMat{T}) -# @assert size(zmat) == size(x) == size(y) -# # d[:x], d[:y], d[:z] = Any[x], Any[y], Surface{Matrix{Float64}}(zmat) -# d[:x], d[:y], d[:z] = map(Surface{Matrix{Float64}}, (x, y, zmat)) -# if !like_surface(get(d, :seriestype, :none)) -# d[:seriestype] = :contour -# end -# end -# -# -# # -------------------------------------------------------------------- -# # Parametric functions -# # -------------------------------------------------------------------- -# -# # special handling... xmin/xmax with function(s) -# function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, xmin::Number, xmax::Number) -# width = get(plt.attr, :size, (100,))[1] -# x = linspace(xmin, xmax, width) -# process_inputs(plt, d, x, f) -# end -# -# # special handling... xmin/xmax with parametric function(s) -# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)) -# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)) -# process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, linspace(umin, umax, numPoints)) -# -# # special handling... 3D parametric function(s) -# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)) -# process_inputs{T<:Number}(plt::AbstractPlot, d::KW, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)) -# process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, fz, linspace(umin, umax, numPoints)) -# -# -# # -------------------------------------------------------------------- -# # Lists of tuples and FixedSizeArrays -# # -------------------------------------------------------------------- -# -# # if we get an unhandled tuple, just splat it in -# function process_inputs(plt::AbstractPlot, d::KW, tup::Tuple) -# process_inputs(plt, d, tup...) -# end -# -# # (x,y) tuples -# function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::AVec{Tuple{R1,R2}}) -# process_inputs(plt, d, unzip(xy)...) -# end -# function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::Tuple{R1,R2}) -# process_inputs(plt, d, [xy[1]], [xy[2]]) -# end -# -# # (x,y,z) tuples -# function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{Tuple{R1,R2,R3}}) -# process_inputs(plt, d, unzip(xyz)...) -# end -# function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::Tuple{R1,R2,R3}) -# process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]]) -# end -# -# # 2D FixedSizeArrays -# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::AVec{FixedSizeArrays.Vec{2,T}}) -# process_inputs(plt, d, unzip(xy)...) -# end -# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::FixedSizeArrays.Vec{2,T}) -# process_inputs(plt, d, [xy[1]], [xy[2]]) -# end -# -# # 3D FixedSizeArrays -# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{FixedSizeArrays.Vec{3,T}}) -# process_inputs(plt, d, unzip(xyz)...) -# end -# function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::FixedSizeArrays.Vec{3,T}) -# process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]]) -# end -# -# # -------------------------------------------------------------------- -# # handle grouping -# # -------------------------------------------------------------------- -# -# # function process_inputs(plt::AbstractPlot, d::KW, groupby::GroupBy, args...) -# # ret = Any[] -# # error("unfinished after series reorg") -# # for (i,glab) in enumerate(groupby.groupLabels) -# # # TODO: don't automatically overwrite labels -# # kwlist, xmeta, ymeta = process_inputs(plt, d, args..., -# # idxfilter = groupby.groupIds[i], -# # label = string(glab), -# # numUncounted = length(ret)) # we count the idx from plt.n + numUncounted + i -# # append!(ret, kwlist) -# # end -# # ret, nothing, nothing # TODO: handle passing meta through -# # end - -# -------------------------------------------------------------------- -# For DataFrame support. Imports DataFrames and defines the necessary methods which support them. -# -------------------------------------------------------------------- - -# function setup_dataframes() -# @require DataFrames begin -# # @eval begin -# # import DataFrames -# -# DFS = Union{Symbol, AbstractArray{Symbol}} -# -# function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, dfs::DFS) -# if isa(dfs, Symbol) -# get!(d, Symbol(letter * "label"), string(dfs)) -# collect(df[dfs]) -# else -# get!(d, :label, reshape(dfs, 1, length(dfs))) -# Any[collect(df[s]) for s in dfs] -# end -# end -# -# function handle_group(df::DataFrames.AbstractDataFrame, d::KW) -# if haskey(d, :group) -# g = d[:group] -# if isa(g, Symbol) -# d[:group] = collect(df[g]) -# end -# end -# end -# -# @recipe function plot(df::DataFrames.AbstractDataFrame, sy::DFS) -# handle_group(df, d) -# handle_dfs(df, d, "y", sy) -# end -# -# @recipe function plot(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS) -# handle_group(df, d) -# x = handle_dfs(df, d, "x", sx) -# y = handle_dfs(df, d, "y", sy) -# x, y -# end -# -# @recipe function plot(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS, sz::DFS) -# handle_group(df, d) -# x = handle_dfs(df, d, "x", sx) -# y = handle_dfs(df, d, "y", sy) -# z = handle_dfs(df, d, "z", sz) -# x, y, z -# end -# -# # get_data(df::DataFrames.AbstractDataFrame, arg::Symbol) = df[arg] -# # get_data(df::DataFrames.AbstractDataFrame, arg) = arg -# # -# # function process_inputs(plt::AbstractPlot, d::KW, df::DataFrames.AbstractDataFrame, args...) -# # # d[:dataframe] = df -# # process_inputs(plt, d, map(arg -> get_data(df, arg), args)...) -# # end -# # -# # # expecting the column name of a dataframe that was passed in... anything else should error -# # function extractGroupArgs(s::Symbol, df::DataFrames.AbstractDataFrame, args...) -# # if haskey(df, s) -# # return extractGroupArgs(df[s]) -# # else -# # error("Got a symbol, and expected that to be a key in d[:dataframe]. s=$s d=$d") -# # end -# # end -# -# # function getDataFrameFromKW(d::KW) -# # get(d, :dataframe) do -# # error("Missing dataframe argument!") -# # end -# # end -# -# # # the conversion functions for when we pass symbols or vectors of symbols to reference dataframes -# # convertToAnyVector(s::Symbol, d::KW) = Any[getDataFrameFromKW(d)[s]], s -# # convertToAnyVector(v::AVec{Symbol}, d::KW) = (df = getDataFrameFromKW(d); Any[df[s] for s in v]), v -# -# end -# end diff --git a/src/series_new.jl b/src/series_new.jl index f145d33e..315309a3 100644 --- a/src/series_new.jl +++ b/src/series_new.jl @@ -180,15 +180,6 @@ end newargs end -# @recipe f(x, y, z) = SliceIt, apply_recipe(typeof(x), x), apply_recipe(typeof(y), y), apply_recipe(typeof(z), z) -# @recipe f(x, y) = SliceIt, apply_recipe(typeof(x), x), apply_recipe(typeof(y), y), nothing -# @recipe f(y) = SliceIt, nothing, apply_recipe(typeof(y), y), nothing - -# # pass these through to the slicer -# @recipe f(x, y, z) = SliceIt, x, y, z -# @recipe f(x, y) = SliceIt, x, y, nothing -# @recipe f(y) = SliceIt, nothing, y, nothing - # # -------------------------------------------------------------------- # # 1 argument