From 83bd780f2a7ff53eafd0ae74db7c9805f004aea6 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 13 May 2016 16:46:15 -0400 Subject: [PATCH] working on Axis type --- src/args.jl | 2 +- src/backends/pyplot.jl | 58 +++++++++--- src/components.jl | 204 +++++++++++++++++++++-------------------- src/plot.jl | 5 + src/recipes.jl | 11 ++- src/series_new.jl | 7 +- 6 files changed, 165 insertions(+), 122 deletions(-) diff --git a/src/args.jl b/src/args.jl index 7db46638..bf248db8 100644 --- a/src/args.jl +++ b/src/args.jl @@ -772,7 +772,7 @@ function setDictValue(d_in::KW, d_out::KW, k::Symbol, idx::Int, defaults::KW) if haskey(d_in, k) && !(typeof(d_in[k]) <: Union{AbstractMatrix, Tuple} && isempty(d_in[k])) d_out[k] = getArgValue(d_in[k], idx) else - d_out[k] = defaults[k] + d_out[k] = deepcopy(defaults[k]) end end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 3d9e3ddc..b8d889fd 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -384,6 +384,7 @@ function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW) ax = getAxis(plt, d[:axis]) x, y, z = d[:x], d[:y], d[:z] + @show typeof((x,y,z)) xyargs = (lt in _3dTypes ? (x,y,z) : (x,y)) # handle zcolor and get c/cmap @@ -911,9 +912,10 @@ end function _update_plot(plt::Plot{PyPlotBackend}, d::KW) + # @show d figorax = plt.o ax = getLeftAxis(figorax) - ticksz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize + # ticksz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize guidesz = get(d, :guidefont, plt.plotargs[:guidefont]).pointsize # title @@ -930,32 +932,60 @@ function _update_plot(plt::Plot{PyPlotBackend}, d::KW) end end - # handle each axis in turn for letter in ("x", "y", "z") - axis, scale, lims, ticks, flip, lab, rotation = - axis_symbols(letter, "axis", "scale", "lims", "ticks", "flip", "label", "rotation") - haskey(ax, axis) || continue - haskey(d, scale) && applyPyPlotScale(ax, d[scale], letter) - haskey(d, lims) && addPyPlotLims(ax, d[lims], letter) - haskey(d, ticks) && addPyPlotTicks(ax, d[ticks], letter) - haskey(d, lab) && ax[symbol("set_", letter, "label")](d[lab]) - if get(d, flip, false) + axissym = symbol(letter*"axis") + axis = plt.plotargs[axissym] + # @show axis + haskey(ax, axissym) || continue + applyPyPlotScale(ax, axis[:scale], letter) + addPyPlotLims(ax, axis[:lims], letter) + addPyPlotTicks(ax, get_ticks(axis), letter) + ax[symbol("set_", letter, "label")](axis[:label]) + if get(axis.d, :flip, false) ax[symbol("invert_", letter, "axis")]() end for tmpax in axes - tmpax[axis][:label][:set_fontsize](guidesz) + tmpax[axissym][:label][:set_fontsize](axis[:guidefont].pointsize) for lab in tmpax[symbol("get_", letter, "ticklabels")]() - lab[:set_fontsize](ticksz) - haskey(d, rotation) && lab[:set_rotation](d[rotation]) + lab[:set_fontsize](axis[:tickfont].pointsize) + lab[:set_rotation](axis[:rotation]) end if get(d, :grid, false) fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid]) - tmpax[axis][:grid](true, color = fgcolor) + tmpax[axissym][:grid](true, color = fgcolor) tmpax[:set_axisbelow](true) end end + # @show "" end + + # # handle each axis in turn + # for letter in ("x", "y", "z") + # axis, scale, lims, ticks, flip, lab, rotation = + # axis_symbols(letter, "axis", "scale", "lims", "ticks", "flip", "label", "rotation") + # haskey(ax, axis) || continue + # haskey(d, scale) && applyPyPlotScale(ax, d[scale], letter) + # haskey(d, lims) && addPyPlotLims(ax, d[lims], letter) + # haskey(d, ticks) && addPyPlotTicks(ax, d[ticks], letter) + # haskey(d, lab) && ax[symbol("set_", letter, "label")](d[lab]) + # if get(d, flip, false) + # ax[symbol("invert_", letter, "axis")]() + # end + # for tmpax in axes + # tmpax[axis][:label][:set_fontsize](guidesz) + # for lab in tmpax[symbol("get_", letter, "ticklabels")]() + # lab[:set_fontsize](ticksz) + # haskey(d, rotation) && lab[:set_rotation](d[rotation]) + # end + # if get(d, :grid, false) + # fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid]) + # tmpax[axis][:grid](true, color = fgcolor) + # tmpax[:set_axisbelow](true) + # end + # end + # end + # do we want to change the aspect ratio? aratio = get(d, :aspect_ratio, :none) if aratio != :none diff --git a/src/components.jl b/src/components.jl index 824570bd..623e3768 100644 --- a/src/components.jl +++ b/src/components.jl @@ -207,106 +207,106 @@ function rotate(shape::Shape, Θ::Real, c = center(shape)) end # ----------------------------------------------------------------------- - -# abstract AbstractAxisTicks -# immutable DefaultAxisTicks end # -# type CustomAxisTicks -# # TODO +# # abstract AbstractAxisTicks +# # immutable DefaultAxisTicks end +# # +# # type CustomAxisTicks +# # # TODO +# # end +# +# # simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place +# type Axis +# d::KW +# # name::AbstractString # "x" or "y" +# # label::AbstractString +# # lims::NTuple{2} +# # ticks::AbstractAxisTicks +# # scale::Symbol +# # flip::Bool +# # rotation::Number +# # guidefont::Font +# # tickfont::Font +# # use_minor::Bool +# # _plotDefaults[:foreground_color_axis] = :match # axis border/tick colors +# # _plotDefaults[:foreground_color_border] = :match # plot area border/spines +# # _plotDefaults[:foreground_color_text] = :match # tick text color +# # _plotDefaults[:foreground_color_guide] = :match # guide text color # end - -# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place -type Axis - d::KW - # name::AbstractString # "x" or "y" - # label::AbstractString - # lims::NTuple{2} - # ticks::AbstractAxisTicks - # scale::Symbol - # flip::Bool - # rotation::Number - # guidefont::Font - # tickfont::Font - # use_minor::Bool - # _plotDefaults[:foreground_color_axis] = :match # axis border/tick colors - # _plotDefaults[:foreground_color_border] = :match # plot area border/spines - # _plotDefaults[:foreground_color_text] = :match # tick text color - # _plotDefaults[:foreground_color_guide] = :match # guide text color -end - - -# function processAxisArg(d::KW, letter::AbstractString, arg) -function axis(letter, args...; kw...) - # TODO: this should initialize with values from _plotDefaults - d = KW( - :letter => letter, - :label => "", - :lims => :auto, - :ticks => :auto, - :scale => :identity, - :flip => false, - :rotation => 0, - :guidefont => font(11), - :tickfont => font(8), - :use_minor => false, - :foreground_color_axis => :match, - :foreground_color_border => :match, - :foreground_color_text => :match, - :foreground_color_guide => :match, - ) - - # first process args - for arg in args - T = typeof(arg) - arg = get(_scaleAliases, arg, arg) - # scale, flip, label, lim, tick = axis_symbols(letter, "scale", "flip", "label", "lims", "ticks") - - if typeof(arg) <: Font - d[:tickfont] = arg - d[:guidefont] = arg - - elseif arg in _allScales - d[:scale] = arg - - elseif arg in (:flip, :invert, :inverted) - d[:flip] = true - - elseif T <: @compat(AbstractString) - d[:label] = arg - - # xlims/ylims - elseif (T <: Tuple || T <: AVec) && length(arg) == 2 - sym = typeof(arg[1]) <: Number ? :lims : :ticks - d[sym] = arg - - # xticks/yticks - elseif T <: AVec - d[:ticks] = arg - - elseif arg == nothing - d[:ticks] = [] - - elseif typeof(arg) <: Number - d[:rotation] = arg - - else - warn("Skipped $(letter)axis arg $arg") - - end - end - - # then override for any keywords - for (k,v) in kw - d[k] = v - end - - Axis(d) -end - - -xaxis(args...) = axis("x", args...) -yaxis(args...) = axis("y", args...) -zaxis(args...) = axis("z", args...) +# +# +# # function processAxisArg(d::KW, letter::AbstractString, arg) +# function axis(letter, args...; kw...) +# # TODO: this should initialize with values from _plotDefaults +# d = KW( +# :letter => letter, +# :label => "", +# :lims => :auto, +# :ticks => :auto, +# :scale => :identity, +# :flip => false, +# :rotation => 0, +# :guidefont => font(11), +# :tickfont => font(8), +# :use_minor => false, +# :foreground_color_axis => :match, +# :foreground_color_border => :match, +# :foreground_color_text => :match, +# :foreground_color_guide => :match, +# ) +# +# # first process args +# for arg in args +# T = typeof(arg) +# arg = get(_scaleAliases, arg, arg) +# # scale, flip, label, lim, tick = axis_symbols(letter, "scale", "flip", "label", "lims", "ticks") +# +# if typeof(arg) <: Font +# d[:tickfont] = arg +# d[:guidefont] = arg +# +# elseif arg in _allScales +# d[:scale] = arg +# +# elseif arg in (:flip, :invert, :inverted) +# d[:flip] = true +# +# elseif T <: @compat(AbstractString) +# d[:label] = arg +# +# # xlims/ylims +# elseif (T <: Tuple || T <: AVec) && length(arg) == 2 +# sym = typeof(arg[1]) <: Number ? :lims : :ticks +# d[sym] = arg +# +# # xticks/yticks +# elseif T <: AVec +# d[:ticks] = arg +# +# elseif arg == nothing +# d[:ticks] = [] +# +# elseif typeof(arg) <: Number +# d[:rotation] = arg +# +# else +# warn("Skipped $(letter)axis arg $arg") +# +# end +# end +# +# # then override for any keywords +# for (k,v) in kw +# d[k] = v +# end +# +# Axis(d) +# end +# +# +# xaxis(args...) = axis("x", args...) +# yaxis(args...) = axis("y", args...) +# zaxis(args...) = axis("z", args...) # ----------------------------------------------------------------------- @@ -374,7 +374,7 @@ end # ----------------------------------------------------------------------- # simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place -type Axis +type Axis #<: Associative{Symbol,Any} d::KW end @@ -414,8 +414,10 @@ function discrete_value!(a::Axis, v::AVec) Float64[discrete_value!(a, vi) for vi=v] end +Base.show(io::IO, a::Axis) = dumpdict(a.d, "Axis", true) Base.getindex(a::Axis, k::Symbol) = getindex(a.d, k) Base.setindex!(a::Axis, v, ks::Symbol...) = setindex!(a.d, v, ks...) +Base.haskey(a::Axis, k::Symbol) = haskey(a.d, k) Base.extrema(a::Axis) = a[:extrema] # get discrete ticks, or not @@ -457,13 +459,13 @@ function Axis(letter::AbstractString, args...; kw...) # :foreground_color_guide => :match, :extrema => (Inf, -Inf), :discrete_map => Dict(), # map discrete values to continuous plot values - :discrete_values => [], + :discrete_values => Tuple{Float64,Any}[], :use_minor => false, :show => true, # show or hide the axis? (useful for linked subplots) ) for sym in _axis_symbols k = symbol(letter * string(sym)) - d[k] = _plotDefaults[k] + d[sym] = _plotDefaults[k] end for k in _axis_symbols_fonts_colors d[k] = _plotDefaults[k] diff --git a/src/plot.jl b/src/plot.jl index 687ad1ed..47f43bcf 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -81,11 +81,13 @@ end # merge the KW d into the plot args function _add_plotargs!(plt::Plot, d::KW) + # @show d # handle axis updates from a recipe for letter in ("x","y","z") # get the Axis object axis = plt.plotargs[symbol(letter * "axis")] + # @show 1,typeof(axis) # update xlabel, xscale, etc for k in _axis_symbols @@ -94,6 +96,7 @@ function _add_plotargs!(plt::Plot, d::KW) axis[k] = d[lk] end end + # @show 2,axis # update guidefont, etc for k in _axis_symbols_fonts_colors @@ -101,6 +104,7 @@ function _add_plotargs!(plt::Plot, d::KW) axis[k] = d[k] end end + # @show 3,axis # update extrema and discrete values datasym = symbol(letter) @@ -112,6 +116,7 @@ function _add_plotargs!(plt::Plot, d::KW) d[datasym] = discrete_value!(axis, v) end end + # @show 4,axis end for k in keys(_plotDefaults) diff --git a/src/recipes.jl b/src/recipes.jl index 5d24cc74..3feaaff0 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -247,7 +247,8 @@ const _box_halfwidth = 0.4 q1,q2,q3,q4,q5 = quantile(d[:y][groupby.groupIds[i]], linspace(0,1,5)) # make the shape - l, m, r = i - _box_halfwidth, i, i + _box_halfwidth + center = i - 0.5 + l, m, r = center - _box_halfwidth, center, center + _box_halfwidth xcoords = [ m, l, r, m, m, NaN, # lower T l, l, r, r, l, NaN, # lower box @@ -266,7 +267,8 @@ const _box_halfwidth = 0.4 # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) d[:linetype] = :shape - xticklabels --> groupby.groupLabels + n = length(groupby.groupLabels) + xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels) # we want to set the fields directly inside series recipes... args are ignored d[:x], d[:y] = shape_coords(shapes) @@ -315,14 +317,15 @@ end widths = _box_halfwidth * widths / maximum(widths) # make the violin - xcoords = vcat(widths, -reverse(widths)) + i + xcoords = vcat(widths, -reverse(widths)) + (i - 0.5) ycoords = vcat(centers, reverse(centers)) push!(shapes, Shape(xcoords, ycoords)) end # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) d[:linetype] = :shape - xticklabels --> groupby.groupLabels + n = length(groupby.groupLabels) + xticks --> (linspace(0.5,n-0.5,n), groupby.groupLabels) d[:x], d[:y] = shape_coords(shapes) () diff --git a/src/series_new.jl b/src/series_new.jl index 5d380941..9fabe90f 100644 --- a/src/series_new.jl +++ b/src/series_new.jl @@ -105,6 +105,8 @@ immutable SliceIt end end mf = length(fillranges) + @show zs + mx = length(xs) my = length(ys) mz = length(zs) @@ -115,6 +117,7 @@ immutable SliceIt end xi, yi, zi = xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)] # @show i, typeof((xi, yi, zi)) di[:x], di[:y], di[:z] = compute_xyz(xi, yi, zi) + # @show i, typeof((di[:x], di[:y], di[:z])) # handle fillrange fr = fillranges[mod1(i,mf)] @@ -329,8 +332,8 @@ end # end @recipe function f{X,Y}(x::AVec{X}, y::AVec{Y}, zf::Function) - x = X <: Number ? sort(x) : x - y = Y <: 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