diff --git a/src/args.jl b/src/args.jl index b543879d..1f8f8253 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1,7 +1,7 @@ const _allAxes = [:auto, :left, :right] -@compat const _axesAliases = Dict( +@compat const _axesAliases = KW( :a => :auto, :l => :left, :r => :right @@ -13,7 +13,7 @@ const _allTypes = vcat([ :heatmap, :hexbin, :hist, :hist2d, :hist3d, :density, :bar, :hline, :vline, :ohlc, :contour, :pie, :shape ], _3dTypes) -@compat const _typeAliases = Dict( +@compat const _typeAliases = KW( :n => :none, :no => :none, :l => :line, @@ -46,7 +46,7 @@ like_surface(linetype::Symbol) = linetype in (:contour, :heatmap, :surface, :w const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] -@compat const _styleAliases = Dict( +@compat const _styleAliases = KW( :a => :auto, :s => :solid, :d => :dash, @@ -57,7 +57,7 @@ const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] # const _allMarkers = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, # :cross, :xcross, :star5, :star8, :hexagon, :octagon, Shape] const _allMarkers = vcat(:none, :auto, sort(collect(keys(_shapes)))) -@compat const _markerAliases = Dict( +@compat const _markerAliases = KW( :n => :none, :no => :none, :a => :auto, @@ -98,14 +98,14 @@ const _allMarkers = vcat(:none, :auto, sort(collect(keys(_shapes)))) ) const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt] -@compat const _scaleAliases = Dict( +@compat const _scaleAliases = KW( :none => :identity, :log => :log10, ) # ----------------------------------------------------------------------------- -const _seriesDefaults = Dict{Symbol, Any}() +const _seriesDefaults = KW() # series-specific _seriesDefaults[:axis] = :left @@ -146,7 +146,7 @@ _seriesDefaults[:levels] = 15 _seriesDefaults[:orientation] = :vertical -const _plotDefaults = Dict{Symbol, Any}() +const _plotDefaults = KW() # plot globals _plotDefaults[:title] = "" @@ -204,7 +204,7 @@ autopick(notarr, idx::Integer) = notarr autopick_ignore_none_auto(arr::AVec, idx::Integer) = autopick(setdiff(arr, [:none, :auto]), idx) autopick_ignore_none_auto(notarr, idx::Integer) = notarr -function aliasesAndAutopick(d::Dict, sym::Symbol, aliases::Dict, options::AVec, plotIndex::Int) +function aliasesAndAutopick(d::KW, sym::Symbol, aliases::KW, options::AVec, plotIndex::Int) if d[sym] == :auto d[sym] = autopick_ignore_none_auto(options, plotIndex) elseif haskey(aliases, d[sym]) @@ -212,7 +212,7 @@ function aliasesAndAutopick(d::Dict, sym::Symbol, aliases::Dict, options::AVec, end end -function aliases(aliasMap::Dict, val) +function aliases(aliasMap::KW, val) # sort(vcat(val, collect(keys(filter((k,v)-> v==val, aliasMap))))) sortedkeys(filter((k,v)-> v==val, aliasMap)) end @@ -221,7 +221,7 @@ end # Alternate args -@compat const _keyAliases = Dict( +@compat const _keyAliases = KW( :c => :linecolor, :color => :linecolor, :colour => :linecolor, @@ -368,7 +368,7 @@ end # ----------------------------------------------------------------------------- -function handleColors!(d::Dict, arg, csym::Symbol) +function handleColors!(d::KW, arg, csym::Symbol) try if arg == :auto d[csym] = :auto @@ -383,7 +383,7 @@ end # given one value (:log, or :flip, or (-1,1), etc), set the appropriate arg # TODO: use trueOrAllTrue for subplots which can pass vectors for these -function processAxisArg(d::Dict, axisletter::@compat(AbstractString), arg) +function processAxisArg(d::KW, axisletter::@compat(AbstractString), arg) T = typeof(arg) # if T <: Symbol @@ -416,7 +416,7 @@ function processAxisArg(d::Dict, axisletter::@compat(AbstractString), arg) end -function processLineArg(d::Dict, arg) +function processLineArg(d::KW, arg) # linetype # if trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg) @@ -457,7 +457,7 @@ function processLineArg(d::Dict, arg) end -function processMarkerArg(d::Dict, arg) +function processMarkerArg(d::KW, arg) # markershape # if trueOrAllTrue(a -> get(_markerAliases, a, a) in _allMarkers, arg) @@ -501,7 +501,7 @@ function processMarkerArg(d::Dict, arg) end -function processFillArg(d::Dict, arg) +function processFillArg(d::KW, arg) if typeof(arg) <: Brush arg.size == nothing || (d[:fillrange] = arg.size) @@ -530,7 +530,7 @@ _replace_markershape(shape) = shape "Handle all preprocessing of args... break out colors/sizes/etc and replace aliases." -function preprocessArgs!(d::Dict) +function preprocessArgs!(d::KW) replaceAliases!(d, _keyAliases) # handle axis args @@ -636,7 +636,7 @@ end # ----------------------------------------------------------------------------- -function warnOnUnsupportedArgs(pkg::AbstractBackend, d::Dict) +function warnOnUnsupportedArgs(pkg::AbstractBackend, d::KW) for k in sortedkeys(d) if (!(k in supportedArgs(pkg)) && k != :subplot @@ -650,7 +650,7 @@ _markershape_supported(pkg::AbstractBackend, shape::Symbol) = shape in supported _markershape_supported(pkg::AbstractBackend, shape::Shape) = Shape in supportedMarkers(pkg) _markershape_supported(pkg::AbstractBackend, shapes::AVec) = all([_markershape_supported(pkg, shape) for shape in shapes]) -function warnOnUnsupported(pkg::AbstractBackend, d::Dict) +function warnOnUnsupported(pkg::AbstractBackend, d::KW) (d[:axis] in supportedAxes(pkg) || warn("axis $(d[:axis]) is unsupported with $pkg. Choose from: $(supportedAxes(pkg))")) (d[:linetype] == :none @@ -665,7 +665,7 @@ function warnOnUnsupported(pkg::AbstractBackend, d::Dict) || warn("markershape $(d[:markershape]) is unsupported with $pkg. Choose from: $(supportedMarkers(pkg))")) end -function warnOnUnsupportedScales(pkg::AbstractBackend, d::Dict) +function warnOnUnsupportedScales(pkg::AbstractBackend, d::KW) for k in (:xscale, :yscale) if haskey(d, k) d[k] in supportedScales(pkg) || warn("scale $(d[k]) is unsupported with $pkg. Choose from: $(supportedScales(pkg))") @@ -689,7 +689,7 @@ getArgValue(v, idx) = v # given an argument key (k), we want to extract the argument value for this index. # if nothing is set (or container is empty), return the default. -function setDictValue(d_in::Dict, d_out::Dict, k::Symbol, idx::Int, defaults::Dict) +function setDictValue(d_in::KW, d_out::KW, k::Symbol, idx::Int, defaults::KW) if haskey(d_in, k) && !(typeof(d_in[k]) <: @compat(Union{AbstractArray, Tuple}) && isempty(d_in[k])) d_out[k] = getArgValue(d_in[k], idx) else @@ -715,7 +715,7 @@ convertLegendValue(val::Bool) = val ? :best : :none # build the argument dictionary for the plot function getPlotArgs(pkg::AbstractBackend, kw, idx::Int; set_defaults = true) kwdict = KW(kw) - d = Dict() + d = KW() # add defaults? if set_defaults @@ -750,9 +750,9 @@ end # build the argument dictionary for a series -function getSeriesArgs(pkg::AbstractBackend, plotargs::Dict, kw, commandIndex::Int, plotIndex::Int, globalIndex::Int) # TODO, pass in plotargs, not plt +function getSeriesArgs(pkg::AbstractBackend, plotargs::KW, kw, commandIndex::Int, plotIndex::Int, globalIndex::Int) # TODO, pass in plotargs, not plt kwdict = KW(kw) - d = Dict() + d = KW() # add defaults? for k in keys(_seriesDefaults) diff --git a/src/backends.jl b/src/backends.jl index 11185e87..ed99f38d 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -47,8 +47,8 @@ include("backends/supported.jl") plot(pkg::AbstractBackend; kw...) = error("plot($pkg; kw...) is not implemented") plot!(pkg::AbstractBackend, plt::Plot; kw...) = error("plot!($pkg, plt; kw...) is not implemented") -_update_plot(pkg::AbstractBackend, plt::Plot, d::Dict) = error("_update_plot($pkg, plt, d) is not implemented") -_update_plot_pos_size{P<:AbstractBackend}(plt::AbstractPlot{P}, d::Dict) = nothing +_update_plot(pkg::AbstractBackend, plt::Plot, d::KW) = error("_update_plot($pkg, plt, d) is not implemented") +_update_plot_pos_size{P<:AbstractBackend}(plt::AbstractPlot{P}, d::KW) = nothing subplot(pkg::AbstractBackend; kw...) = error("subplot($pkg; kw...) is not implemented") subplot!(pkg::AbstractBackend, subplt::Subplot; kw...) = error("subplot!($pkg, subplt; kw...) is not implemented") diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 1c2e5065..6fb6101a 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -8,19 +8,19 @@ function _initialize_backend(::GRBackend; kw...) end end -const gr_linetype = Dict( +const gr_linetype = KW( :auto => 1, :solid => 1, :dash => 2, :dot => 3, :dashdot => 4, :dashdotdot => -1 ) -const gr_markertype = Dict( +const gr_markertype = KW( :auto => 1, :none => -1, :ellipse => -1, :rect => -7, :diamond => -13, :utriangle => -3, :dtriangle => -5, :pentagon => -21, :hexagon => -22, :heptagon => -23, :octagon => -24, :cross => 2, :xcross => 5, :star4 => -25, :star5 => -26, :star6 => -27, :star7 => -28, :star8 => -29, :vline => -30, :hline => -31 ) -const gr_halign = Dict(:left => 1, :hcenter => 2, :right => 3) -const gr_valign = Dict(:top => 1, :vcenter => 3, :bottom => 5) +const gr_halign = KW(:left => 1, :hcenter => 2, :right => 3) +const gr_valign = KW(:top => 1, :vcenter => 3, :bottom => 5) const gr_font_family = Dict( "times" => 1, "helvetica" => 5, "courier" => 9, "bookman" => 14, @@ -703,7 +703,7 @@ end function _create_plot(pkg::GRBackend; kw...) d = KW(kw) - Plot(nothing, pkg, 0, d, Dict[]) + Plot(nothing, pkg, 0, d, KW[]) end function _add_series(::GRBackend, plt::Plot; kw...) @@ -725,13 +725,13 @@ end function _before_update_plot(plt::Plot{GRBackend}) end -function _update_plot(plt::Plot{GRBackend}, d::Dict) +function _update_plot(plt::Plot{GRBackend}, d::KW) for k in (:title, :xlabel, :ylabel) haskey(d, k) && (plt.plotargs[k] = d[k]) end end -function _update_plot_pos_size(plt::AbstractPlot{GRBackend}, d::Dict) +function _update_plot_pos_size(plt::AbstractPlot{GRBackend}, d::KW) end # ---------------------------------------------------------------- diff --git a/src/colors.jl b/src/colors.jl index 3a1f6ef1..ef0ae1f0 100644 --- a/src/colors.jl +++ b/src/colors.jl @@ -52,7 +52,7 @@ const _rainbowColors = [colorant"blue", colorant"purple", colorant"green", color const _testColors = [colorant"darkblue", colorant"blueviolet", colorant"darkcyan",colorant"green", darken(colorant"yellow",0.3), colorant"orange", darken(colorant"red",0.2)] -@compat const _gradients = Dict( +@compat const _gradients = KW( :blues => [colorant"lightblue", colorant"darkblue"], :reds => [colorant"lightpink", colorant"darkred"], :greens => [colorant"lightgreen", colorant"darkgreen"], @@ -79,7 +79,7 @@ immutable ColorGradient <: ColorScheme if length(cs) == length(vals) return new(convertColor(cs,alpha), collect(vals)) end - + # # otherwise interpolate evenly between the minval and maxval # minval, maxval = minimum(vals), maximum(vals) # vs = Float64[interpolate(minval, maxval, w) for w in linspace(0, 1, length(cs))] @@ -351,10 +351,9 @@ webcolor(c, α) = webcolor(convertColor(getColor(c), α)) # ---------------------------------------------------------------------------------- -# TODO: allow the setting of the algorithm, either by passing a symbol (:colordiff, :fixed, etc) or a function? +# TODO: allow the setting of the algorithm, either by passing a symbol (:colordiff, :fixed, etc) or a function? -# function getBackgroundRGBColor(c, d::Dict) -function handlePlotColors(::AbstractBackend, d::Dict) +function handlePlotColors(::AbstractBackend, d::KW) if :background_color in supportedArgs() bgcolor = convertColor(d[:background_color]) else @@ -369,7 +368,7 @@ function handlePlotColors(::AbstractBackend, d::Dict) # set the foreground color (text, ticks, gridlines) to be white or black depending - # on how dark the background is. + # on how dark the background is. fgcolor = get(d, :foreground_color, :auto) fgcolor = if fgcolor == :auto isdark(bgcolor) ? colorant"white" : colorant"black" @@ -383,7 +382,7 @@ function handlePlotColors(::AbstractBackend, d::Dict) end # converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically -function getSeriesRGBColor(c, plotargs::Dict, n::Int) +function getSeriesRGBColor(c, plotargs::KW, n::Int) if c == :auto c = autopick(plotargs[:color_palette], n) diff --git a/src/plot.jl b/src/plot.jl index 8f516d83..cc3c3441 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -161,34 +161,25 @@ end # handle the grouping function _add_series(plt::Plot, d::KW, groupby::GroupBy, args...) - # error("ERRORRRRRRRR") - starting_n = plt.n for (i, glab) in enumerate(groupby.groupLabels) tmpd = copy(d) - # d[:numUncounted] = i - 1 tmpd[:numUncounted] = plt.n - starting_n _add_series(plt, tmpd, nothing, args...; idxfilter = groupby.groupIds[i], grouplabel = string(glab)) end - - # 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 filter_data(v::AVec, idxfilter::AVec{Int}) = v[idxfilter] filter_data(v, idxfilter) = v +function filter_data!(d::KW, idxfilter) + for s in (:x, :y, :z) + d[s] = filter_data(get(d, s, nothing), idxfilter) + end +end + # no grouping function _add_series(plt::Plot, d::KW, ::Void, args...; idxfilter = nothing, @@ -202,13 +193,8 @@ function _add_series(plt::Plot, d::KW, ::Void, args...; if idxfilter != nothing # add the group name as the label if there isn't one passed in get!(d, :label, grouplabel) - # filter the data - for sym in (:x, :y, :z) - # @show "before" sym, d[sym], idxfilter - d[sym] = filter_data(get(d, sym, nothing), idxfilter) - # @show "after" sym, d[sym], idxfilter - end + filter_data!(d, idxfilter) end seriesArgList, xmeta, ymeta = build_series_args(plt, d) #, idxfilter) @@ -243,7 +229,7 @@ end # if x or y are a vector of strings, we should create a list of unique strings, # and map x/y to be the index of the string... then set the x/y tick labels -function setTicksFromStringVector(d::Dict, di::Dict, sym::Symbol, ticksym::Symbol) +function setTicksFromStringVector(d::KW, di::KW, sym::Symbol, ticksym::Symbol) # if the x or y values are strings, set ticks to the unique values, and x/y to the indices of the ticks v = di[sym] @@ -267,13 +253,13 @@ _before_add_series(plt::Plot) = nothing # -------------------------------------------------------------------- # should we update the x/y label given the meta info during input slicing? -function updateDictWithMeta(d::Dict, plotargs::Dict, meta::Symbol, isx::Bool) +function updateDictWithMeta(d::KW, plotargs::KW, meta::Symbol, isx::Bool) lsym = isx ? :xlabel : :ylabel if plotargs[lsym] == default(lsym) d[lsym] = string(meta) end end -updateDictWithMeta(d::Dict, plotargs::Dict, meta, isx::Bool) = nothing +updateDictWithMeta(d::KW, plotargs::KW, meta, isx::Bool) = nothing # -------------------------------------------------------------------- @@ -285,7 +271,7 @@ annotations(v::AVec) = map(PlotText, v) annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ", "(x, y, annotation)\n got: $(typeof(anns))") -function _add_annotations(plt::Plot, d::Dict) +function _add_annotations(plt::Plot, d::KW) anns = annotations(get(d, :annotation, nothing)) if !isempty(anns) diff --git a/src/recipes.jl b/src/recipes.jl index e35f3fc6..df860b05 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -17,10 +17,10 @@ plot!(plt::Plot, recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe) num_series(x::AMat) = size(x,2) num_series(x) = 1 -_apply_recipe(d::Dict; kw...) = () +_apply_recipe(d::KW; kw...) = () # if it's not a recipe, just do nothing and return the args -function _apply_recipe(d::Dict, args...; issubplot=false, kw...) +function _apply_recipe(d::KW, args...; issubplot=false, kw...) if issubplot && !haskey(d, :n) && !haskey(d, :layout) # put in a sensible default d[:n] = maximum(map(num_series, args)) @@ -76,54 +76,6 @@ end # # ------------------------------------------------- -# "Correlation scatter matrix" -# function corrplot{T<:Real,S<:Real}(mat::AMat{T}, corrmat::AMat{S} = cor(mat); -# colors = :redsblues, -# labels = nothing, kw...) -# m = size(mat,2) -# centers = Float64[mean(extrema(mat[:,i])) for i in 1:m] - -# # might be a mistake? -# @assert m <= 20 -# @assert size(corrmat) == (m,m) - -# # create a subplot grid, and a gradient from -1 to 1 -# p = subplot(rand(0,m^2); n=m^2, leg=false, grid=false, kw...) -# cgrad = ColorGradient(colors, [-1,1]) - -# # make all the plots -# for i in 1:m -# for j in 1:m -# idx = p.layout[i,j] -# plt = p.plts[idx] -# if i==j -# # histogram on diagonal -# histogram!(plt, mat[:,i], c=:black) -# i > 1 && plot!(plt, yticks = :none) -# elseif i < j -# # annotate correlation value in upper triangle -# mi, mj = centers[i], centers[j] -# plot!(plt, [mj], [mi], -# ann = (mj, mi, text(@sprintf("Corr:\n%0.3f", corrmat[i,j]), 15)), -# yticks=:none) -# else -# # scatter plots in lower triangle; color determined by correlation -# c = RGBA(RGB(getColorZ(cgrad, corrmat[i,j])), 0.3) -# scatter!(plt, mat[:,j], mat[:,i], w=0, ms=3, c=c, smooth=true) -# end - -# if labels != nothing && length(labels) >= m -# i == m && xlabel!(plt, string(labels[j])) -# j == 1 && ylabel!(plt, string(labels[i])) -# end -# end -# end - -# # link the axes -# subplot!(p, link = (r,c) -> (true, r!=c)) -# end - - "Sparsity plot... heatmap of non-zero values of a matrix" function spy{T<:Real}(z::AMat{T}; kw...) # I,J,V = findnz(z) @@ -197,7 +149,7 @@ Plots an arc diagram, form `source` to `destiny` (clockwise), using `weight` to """ function arcdiagram(source, destiny, weight; kargs...) - args = Dict(kargs) + args = KW(kargs) grad = pop!(args, :grad, ColorGradient([colorant"darkred", colorant"darkblue"])) if length(source) == length(destiny) == length(weight) @@ -255,7 +207,7 @@ using `weight` to determine the edge colors using `grad`. """ function chorddiagram(source, destiny, weight; kargs...) - args=Dict(kargs) + args = KW(kargs) grad = pop!(args, :grad, ColorGradient([colorant"darkred", colorant"darkblue"])) zcolor= pop!(args, :zcolor, nothing) group = pop!(args, :group, nothing) diff --git a/src/series_args.jl b/src/series_args.jl index 8b00869a..9c923893 100644 --- a/src/series_args.jl +++ b/src/series_args.jl @@ -7,22 +7,22 @@ typealias FuncOrFuncs @compat(Union{Function, AVec{Function}}) -all3D(d::Dict) = trueOrAllTrue(lt -> lt in (:contour, :heatmap, :surface, :wireframe), get(d, :linetype, :none)) +all3D(d::KW) = trueOrAllTrue(lt -> lt in (:contour, :heatmap, :surface, :wireframe), get(d, :linetype, :none)) # missing -convertToAnyVector(v::@compat(Void), d::Dict) = Any[nothing], nothing +convertToAnyVector(v::@compat(Void), d::KW) = Any[nothing], nothing # fixed number of blank series -convertToAnyVector(n::Integer, d::Dict) = Any[zeros(0) for i in 1:n], nothing +convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing # numeric vector -convertToAnyVector{T<:Number}(v::AVec{T}, d::Dict) = Any[v], nothing +convertToAnyVector{T<:Number}(v::AVec{T}, d::KW) = Any[v], nothing # string vector -convertToAnyVector{T<:@compat(AbstractString)}(v::AVec{T}, d::Dict) = Any[v], nothing +convertToAnyVector{T<:@compat(AbstractString)}(v::AVec{T}, d::KW) = Any[v], nothing # numeric matrix -function convertToAnyVector{T<:Number}(v::AMat{T}, d::Dict) +function convertToAnyVector{T<:Number}(v::AMat{T}, d::KW) if all3D(d) Any[Surface(v)] else @@ -31,19 +31,19 @@ function convertToAnyVector{T<:Number}(v::AMat{T}, d::Dict) end # function -convertToAnyVector(f::Function, d::Dict) = Any[f], nothing +convertToAnyVector(f::Function, d::KW) = Any[f], nothing # surface -convertToAnyVector(s::Surface, d::Dict) = Any[s], nothing +convertToAnyVector(s::Surface, d::KW) = Any[s], nothing # vector of OHLC -convertToAnyVector(v::AVec{OHLC}, d::Dict) = Any[v], nothing +convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing # dates -convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::Dict) = Any[dts], nothing +convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::KW) = Any[dts], nothing # list of things (maybe other vectors, functions, or something else) -function convertToAnyVector(v::AVec, d::Dict) +function convertToAnyVector(v::AVec, d::KW) if all(x -> typeof(x) <: Number, v) # all real numbers wrap the whole vector as one item Any[convert(Vector{Float64}, v)], nothing @@ -422,15 +422,15 @@ function setup_dataframes() end end - # function getDataFrameFromKW(d::Dict) + # 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::Dict) = Any[getDataFrameFromKW(d)[s]], s - # convertToAnyVector(v::AVec{Symbol}, d::Dict) = (df = getDataFrameFromKW(d); Any[df[s] for s in v]), v + # 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/subplot.jl b/src/subplot.jl index 1ffa8a67..1f59a702 100644 --- a/src/subplot.jl +++ b/src/subplot.jl @@ -92,11 +92,11 @@ function subplot{P,I<:Integer}(pltsPerRow::AVec{I}, plt1::Plot{P}, plts::Plot{P} end # this will be called internally -function subplot{P<:AbstractBackend}(plts::AVec{Plot{P}}, layout::SubplotLayout, d::Dict) +function subplot{P<:AbstractBackend}(plts::AVec{Plot{P}}, layout::SubplotLayout, d::KW) validateSubplotSupported() p = length(layout) n = sum([plt.n for plt in plts]) - subplt = Subplot(nothing, collect(plts), P(), p, n, layout, Dict(), false, false, false, (r,c) -> (nothing,nothing)) + subplt = Subplot(nothing, collect(plts), P(), p, n, layout, KW(), false, false, false, (r,c) -> (nothing,nothing)) _preprocess_subplot(subplt, d) _postprocess_subplot(subplt, d) @@ -109,7 +109,7 @@ end # ------------------------------------------------------------------------------------------------ -function _preprocess_subplot(subplt::Subplot, d::Dict, args = ()) +function _preprocess_subplot(subplt::Subplot, d::KW, args = ()) validateSubplotSupported() preprocessArgs!(d) @@ -143,7 +143,7 @@ function _preprocess_subplot(subplt::Subplot, d::Dict, args = ()) args end -function _postprocess_subplot(subplt::Subplot, d::Dict) +function _postprocess_subplot(subplt::Subplot, d::KW) # init (after plot creation) if !subplt.initialized subplt.initialized = _create_subplot(subplt, false) @@ -200,39 +200,52 @@ function subplot!(subplt::Subplot, args...; kw...) subplt.initialized = _create_subplot(subplt, true) end - # handle grouping - group = get(d, :group, nothing) - if group == nothing - groupargs = [] + # # handle grouping + # group = get(d, :group, nothing) + # if group == nothing + # groupargs = [] + # else + # groupargs = [extractGroupArgs(d[:group], args...)] + # delete!(d, :group) + # end + + groupby = if haskey(d, :group) + extractGroupArgs(d[:group], args...) else - groupargs = [extractGroupArgs(d[:group], args...)] - delete!(d, :group) + nothing end + # dumpdict(d, "after", true) + # @show groupby map(typeof, args) - process_inputs(subplt, d, groupargs..., args...) - kwList, xmeta, ymeta = build_series_args(subplt, d) - # kwList, xmeta, ymeta = build_series_args(subplt, groupargs..., args...; d...) + _add_series_subplot(subplt, d, groupby, args...) - # TODO: something useful with meta info? - - for (i,di) in enumerate(kwList) - - subplt.n += 1 - plt = getplot(subplt) - plt.n += 1 - - # cleanup the dictionary that we pass into the plot! command - di[:show] = false - di[:subplot] = true - for k in (:title, :xlabel, :xticks, :xlims, :xscale, :xflip, - :ylabel, :yticks, :ylims, :yscale, :yflip) - delete!(di, k) - end - dumpdict(di, "subplot! kwList $i") - dumpdict(plt.plotargs, "plt.plotargs before plotting") - - _add_series_subplot(plt; di...) - end + # process_inputs(subplt, d, groupargs..., args...) + # + # # TODO: filter the data + # + # kwList, xmeta, ymeta = build_series_args(subplt, d) + # # kwList, xmeta, ymeta = build_series_args(subplt, groupargs..., args...; d...) + # + # # TODO: something useful with meta info? + # + # for (i,di) in enumerate(kwList) + # + # subplt.n += 1 + # plt = getplot(subplt) + # plt.n += 1 + # + # # cleanup the dictionary that we pass into the plot! command + # di[:show] = false + # di[:subplot] = true + # for k in (:title, :xlabel, :xticks, :xlims, :xscale, :xflip, + # :ylabel, :yticks, :ylims, :yscale, :yflip) + # delete!(di, k) + # end + # dumpdict(di, "subplot! kwList $i") + # dumpdict(plt.plotargs, "plt.plotargs before plotting") + # + # _add_series_subplot(plt; di...) + # end _postprocess_subplot(subplt, d) @@ -250,19 +263,68 @@ function plot!(subplt::Subplot, args...; kw...) error("Can't call plot! on a Subplot!") end - -function _add_series_subplot(plt::Plot, args...; kw...) - d = KW(kw) - +# given a fully processed KW, add the series to the Plot +function _add_series_subplot(plt::Plot, d::KW) setTicksFromStringVector(d, d, :x, :xticks) setTicksFromStringVector(d, d, :y, :yticks) + # this is the actual call to the backend _add_series(plt.backend, plt; d...) _add_annotations(plt, d) warnOnUnsupportedScales(plt.backend, d) end + +# handle the grouping... add a series for each group +function _add_series_subplot(subplt::Subplot, d::KW, groupby::GroupBy, args...) + starting_n = subplt.n + for (i, glab) in enumerate(groupby.groupLabels) + tmpd = copy(d) + tmpd[:numUncounted] = subplt.n - starting_n + _add_series_subplot(subplt, tmpd, nothing, args...; + idxfilter = groupby.groupIds[i], + grouplabel = string(glab)) + end +end + +# process, filter, and add to the correct plot +function _add_series_subplot(subplt::Subplot, d::KW, ::Void, args...; + idxfilter = nothing, + grouplabel = "") + process_inputs(subplt, d, args...) + + if idxfilter != nothing + # add the group name as the label if there isn't one passed in + get!(d, :label, grouplabel) + # filter the data + filter_data!(d, idxfilter) + end + + kwList, xmeta, ymeta = build_series_args(subplt, d) + + # TODO: something useful with meta info? + + for (i,di) in enumerate(kwList) + + subplt.n += 1 + plt = getplot(subplt) + plt.n += 1 + + # cleanup the dictionary that we pass into the plot! command + di[:show] = false + di[:subplot] = true + for k in (:title, :xlabel, :xticks, :xlims, :xscale, :xflip, + :ylabel, :yticks, :ylims, :yscale, :yflip) + delete!(di, k) + end + dumpdict(di, "subplot! kwList $i") + dumpdict(plt.plotargs, "plt.plotargs before plotting") + + _add_series_subplot(plt, di) + end +end + # -------------------------------------------------------------------- # handle "linking" the subplot axes together diff --git a/src/types.jl b/src/types.jl index 8597027b..61f34e04 100644 --- a/src/types.jl +++ b/src/types.jl @@ -16,8 +16,8 @@ type Plot{T<:AbstractBackend} <: AbstractPlot{T} o # the backend's plot object backend::T # the backend type n::Int # number of series - plotargs::Dict # arguments for the whole plot - seriesargs::Vector{Dict} # arguments for each series + plotargs::KW # arguments for the whole plot + seriesargs::Vector{KW} # arguments for each series end # ----------------------------------------------------------- @@ -32,13 +32,12 @@ abstract SubplotLayout type Subplot{T<:AbstractBackend, L<:SubplotLayout} <: AbstractPlot{T} o # the underlying object - plts::Vector{Plot{T}} # the individual plots + plts::Vector{Plot{T}} # the individual plots backend::T p::Int # number of plots n::Int # number of series layout::L - # plotargs::Vector{Dict} - plotargs::Dict + plotargs::KW initialized::Bool linkx::Bool linky::Bool diff --git a/src/utils.jl b/src/utils.jl index 45ba9501..69a259b5 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -170,7 +170,7 @@ function replaceType(vec, val) push!(vec, val) end -function replaceAliases!(d::Dict, aliases::Dict) +function replaceAliases!(d::KW, aliases::KW) ks = collect(keys(d)) for k in ks if haskey(aliases, k) @@ -268,7 +268,7 @@ function with(f::Function, args...; kw...) # dict to store old and new keyword args for anything that changes newdefs = KW(kw) - olddefs = Dict() + olddefs = KW() for k in keys(newdefs) olddefs[k] = default(k) end @@ -347,7 +347,7 @@ end debugshow(x) = show(x) debugshow(x::AbstractArray) = print(summary(x)) -function dumpdict(d::Dict, prefix = "", alwaysshow = false) +function dumpdict(d::KW, prefix = "", alwaysshow = false) _debugMode.on || alwaysshow || return println() if prefix != ""