working on Axis type

This commit is contained in:
Thomas Breloff 2016-05-13 16:46:15 -04:00
parent 2ba4ac6d20
commit 83bd780f2a
6 changed files with 165 additions and 122 deletions

View File

@ -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])) if haskey(d_in, k) && !(typeof(d_in[k]) <: Union{AbstractMatrix, Tuple} && isempty(d_in[k]))
d_out[k] = getArgValue(d_in[k], idx) d_out[k] = getArgValue(d_in[k], idx)
else else
d_out[k] = defaults[k] d_out[k] = deepcopy(defaults[k])
end end
end end

View File

@ -384,6 +384,7 @@ function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW)
ax = getAxis(plt, d[:axis]) ax = getAxis(plt, d[:axis])
x, y, z = d[:x], d[:y], d[:z] x, y, z = d[:x], d[:y], d[:z]
@show typeof((x,y,z))
xyargs = (lt in _3dTypes ? (x,y,z) : (x,y)) xyargs = (lt in _3dTypes ? (x,y,z) : (x,y))
# handle zcolor and get c/cmap # handle zcolor and get c/cmap
@ -911,9 +912,10 @@ end
function _update_plot(plt::Plot{PyPlotBackend}, d::KW) function _update_plot(plt::Plot{PyPlotBackend}, d::KW)
# @show d
figorax = plt.o figorax = plt.o
ax = getLeftAxis(figorax) 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 guidesz = get(d, :guidefont, plt.plotargs[:guidefont]).pointsize
# title # title
@ -930,32 +932,60 @@ function _update_plot(plt::Plot{PyPlotBackend}, d::KW)
end end
end end
# handle each axis in turn
for letter in ("x", "y", "z") for letter in ("x", "y", "z")
axis, scale, lims, ticks, flip, lab, rotation = axissym = symbol(letter*"axis")
axis_symbols(letter, "axis", "scale", "lims", "ticks", "flip", "label", "rotation") axis = plt.plotargs[axissym]
haskey(ax, axis) || continue # @show axis
haskey(d, scale) && applyPyPlotScale(ax, d[scale], letter) haskey(ax, axissym) || continue
haskey(d, lims) && addPyPlotLims(ax, d[lims], letter) applyPyPlotScale(ax, axis[:scale], letter)
haskey(d, ticks) && addPyPlotTicks(ax, d[ticks], letter) addPyPlotLims(ax, axis[:lims], letter)
haskey(d, lab) && ax[symbol("set_", letter, "label")](d[lab]) addPyPlotTicks(ax, get_ticks(axis), letter)
if get(d, flip, false) ax[symbol("set_", letter, "label")](axis[:label])
if get(axis.d, :flip, false)
ax[symbol("invert_", letter, "axis")]() ax[symbol("invert_", letter, "axis")]()
end end
for tmpax in axes 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")]() for lab in tmpax[symbol("get_", letter, "ticklabels")]()
lab[:set_fontsize](ticksz) lab[:set_fontsize](axis[:tickfont].pointsize)
haskey(d, rotation) && lab[:set_rotation](d[rotation]) lab[:set_rotation](axis[:rotation])
end end
if get(d, :grid, false) if get(d, :grid, false)
fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid]) fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid])
tmpax[axis][:grid](true, color = fgcolor) tmpax[axissym][:grid](true, color = fgcolor)
tmpax[:set_axisbelow](true) tmpax[:set_axisbelow](true)
end end
end end
# @show ""
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)
# 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? # do we want to change the aspect ratio?
aratio = get(d, :aspect_ratio, :none) aratio = get(d, :aspect_ratio, :none)
if aratio != :none if aratio != :none

View File

@ -207,106 +207,106 @@ function rotate(shape::Shape, Θ::Real, c = center(shape))
end end
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# abstract AbstractAxisTicks
# immutable DefaultAxisTicks end
# #
# type CustomAxisTicks # # abstract AbstractAxisTicks
# # TODO # # 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 # end
#
# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place #
type Axis # # function processAxisArg(d::KW, letter::AbstractString, arg)
d::KW # function axis(letter, args...; kw...)
# name::AbstractString # "x" or "y" # # TODO: this should initialize with values from _plotDefaults
# label::AbstractString # d = KW(
# lims::NTuple{2} # :letter => letter,
# ticks::AbstractAxisTicks # :label => "",
# scale::Symbol # :lims => :auto,
# flip::Bool # :ticks => :auto,
# rotation::Number # :scale => :identity,
# guidefont::Font # :flip => false,
# tickfont::Font # :rotation => 0,
# use_minor::Bool # :guidefont => font(11),
# _plotDefaults[:foreground_color_axis] = :match # axis border/tick colors # :tickfont => font(8),
# _plotDefaults[:foreground_color_border] = :match # plot area border/spines # :use_minor => false,
# _plotDefaults[:foreground_color_text] = :match # tick text color # :foreground_color_axis => :match,
# _plotDefaults[:foreground_color_guide] = :match # guide text color # :foreground_color_border => :match,
end # :foreground_color_text => :match,
# :foreground_color_guide => :match,
# )
# function processAxisArg(d::KW, letter::AbstractString, arg) #
function axis(letter, args...; kw...) # # first process args
# TODO: this should initialize with values from _plotDefaults # for arg in args
d = KW( # T = typeof(arg)
:letter => letter, # arg = get(_scaleAliases, arg, arg)
:label => "", # # scale, flip, label, lim, tick = axis_symbols(letter, "scale", "flip", "label", "lims", "ticks")
:lims => :auto, #
:ticks => :auto, # if typeof(arg) <: Font
:scale => :identity, # d[:tickfont] = arg
:flip => false, # d[:guidefont] = arg
:rotation => 0, #
:guidefont => font(11), # elseif arg in _allScales
:tickfont => font(8), # d[:scale] = arg
:use_minor => false, #
:foreground_color_axis => :match, # elseif arg in (:flip, :invert, :inverted)
:foreground_color_border => :match, # d[:flip] = true
:foreground_color_text => :match, #
:foreground_color_guide => :match, # elseif T <: @compat(AbstractString)
) # d[:label] = arg
#
# first process args # # xlims/ylims
for arg in args # elseif (T <: Tuple || T <: AVec) && length(arg) == 2
T = typeof(arg) # sym = typeof(arg[1]) <: Number ? :lims : :ticks
arg = get(_scaleAliases, arg, arg) # d[sym] = arg
# scale, flip, label, lim, tick = axis_symbols(letter, "scale", "flip", "label", "lims", "ticks") #
# # xticks/yticks
if typeof(arg) <: Font # elseif T <: AVec
d[:tickfont] = arg # d[:ticks] = arg
d[:guidefont] = arg #
# elseif arg == nothing
elseif arg in _allScales # d[:ticks] = []
d[:scale] = arg #
# elseif typeof(arg) <: Number
elseif arg in (:flip, :invert, :inverted) # d[:rotation] = arg
d[:flip] = true #
# else
elseif T <: @compat(AbstractString) # warn("Skipped $(letter)axis arg $arg")
d[:label] = arg #
# end
# xlims/ylims # end
elseif (T <: Tuple || T <: AVec) && length(arg) == 2 #
sym = typeof(arg[1]) <: Number ? :lims : :ticks # # then override for any keywords
d[sym] = arg # for (k,v) in kw
# d[k] = v
# xticks/yticks # end
elseif T <: AVec #
d[:ticks] = arg # Axis(d)
# end
elseif arg == nothing #
d[:ticks] = [] #
# xaxis(args...) = axis("x", args...)
elseif typeof(arg) <: Number # yaxis(args...) = axis("y", args...)
d[:rotation] = arg # zaxis(args...) = axis("z", args...)
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 # 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 d::KW
end end
@ -414,8 +414,10 @@ function discrete_value!(a::Axis, v::AVec)
Float64[discrete_value!(a, vi) for vi=v] Float64[discrete_value!(a, vi) for vi=v]
end end
Base.show(io::IO, a::Axis) = dumpdict(a.d, "Axis", true)
Base.getindex(a::Axis, k::Symbol) = getindex(a.d, k) Base.getindex(a::Axis, k::Symbol) = getindex(a.d, k)
Base.setindex!(a::Axis, v, ks::Symbol...) = setindex!(a.d, v, ks...) 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] Base.extrema(a::Axis) = a[:extrema]
# get discrete ticks, or not # get discrete ticks, or not
@ -457,13 +459,13 @@ function Axis(letter::AbstractString, args...; kw...)
# :foreground_color_guide => :match, # :foreground_color_guide => :match,
:extrema => (Inf, -Inf), :extrema => (Inf, -Inf),
:discrete_map => Dict(), # map discrete values to continuous plot values :discrete_map => Dict(), # map discrete values to continuous plot values
:discrete_values => [], :discrete_values => Tuple{Float64,Any}[],
:use_minor => false, :use_minor => false,
:show => true, # show or hide the axis? (useful for linked subplots) :show => true, # show or hide the axis? (useful for linked subplots)
) )
for sym in _axis_symbols for sym in _axis_symbols
k = symbol(letter * string(sym)) k = symbol(letter * string(sym))
d[k] = _plotDefaults[k] d[sym] = _plotDefaults[k]
end end
for k in _axis_symbols_fonts_colors for k in _axis_symbols_fonts_colors
d[k] = _plotDefaults[k] d[k] = _plotDefaults[k]

View File

@ -81,11 +81,13 @@ end
# merge the KW d into the plot args # merge the KW d into the plot args
function _add_plotargs!(plt::Plot, d::KW) function _add_plotargs!(plt::Plot, d::KW)
# @show d
# handle axis updates from a recipe # handle axis updates from a recipe
for letter in ("x","y","z") for letter in ("x","y","z")
# get the Axis object # get the Axis object
axis = plt.plotargs[symbol(letter * "axis")] axis = plt.plotargs[symbol(letter * "axis")]
# @show 1,typeof(axis)
# update xlabel, xscale, etc # update xlabel, xscale, etc
for k in _axis_symbols for k in _axis_symbols
@ -94,6 +96,7 @@ function _add_plotargs!(plt::Plot, d::KW)
axis[k] = d[lk] axis[k] = d[lk]
end end
end end
# @show 2,axis
# update guidefont, etc # update guidefont, etc
for k in _axis_symbols_fonts_colors for k in _axis_symbols_fonts_colors
@ -101,6 +104,7 @@ function _add_plotargs!(plt::Plot, d::KW)
axis[k] = d[k] axis[k] = d[k]
end end
end end
# @show 3,axis
# update extrema and discrete values # update extrema and discrete values
datasym = symbol(letter) datasym = symbol(letter)
@ -112,6 +116,7 @@ function _add_plotargs!(plt::Plot, d::KW)
d[datasym] = discrete_value!(axis, v) d[datasym] = discrete_value!(axis, v)
end end
end end
# @show 4,axis
end end
for k in keys(_plotDefaults) for k in keys(_plotDefaults)

View File

@ -247,7 +247,8 @@ const _box_halfwidth = 0.4
q1,q2,q3,q4,q5 = quantile(d[:y][groupby.groupIds[i]], linspace(0,1,5)) q1,q2,q3,q4,q5 = quantile(d[:y][groupby.groupIds[i]], linspace(0,1,5))
# make the shape # 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 = [ xcoords = [
m, l, r, m, m, NaN, # lower T m, l, r, m, m, NaN, # lower T
l, l, r, r, l, NaN, # lower box 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[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels))
d[:linetype] = :shape 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 # we want to set the fields directly inside series recipes... args are ignored
d[:x], d[:y] = shape_coords(shapes) d[:x], d[:y] = shape_coords(shapes)
@ -315,14 +317,15 @@ end
widths = _box_halfwidth * widths / maximum(widths) widths = _box_halfwidth * widths / maximum(widths)
# make the violin # make the violin
xcoords = vcat(widths, -reverse(widths)) + i xcoords = vcat(widths, -reverse(widths)) + (i - 0.5)
ycoords = vcat(centers, reverse(centers)) ycoords = vcat(centers, reverse(centers))
push!(shapes, Shape(xcoords, ycoords)) push!(shapes, Shape(xcoords, ycoords))
end end
# d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels)) # d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels))
d[:linetype] = :shape 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) d[:x], d[:y] = shape_coords(shapes)
() ()

View File

@ -105,6 +105,8 @@ immutable SliceIt end
end end
mf = length(fillranges) mf = length(fillranges)
@show zs
mx = length(xs) mx = length(xs)
my = length(ys) my = length(ys)
mz = length(zs) 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)] xi, yi, zi = xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)]
# @show i, typeof((xi, yi, zi)) # @show i, typeof((xi, yi, zi))
di[:x], di[:y], di[:z] = compute_xyz(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 # handle fillrange
fr = fillranges[mod1(i,mf)] fr = fillranges[mod1(i,mf)]
@ -329,8 +332,8 @@ end
# end # end
@recipe function f{X,Y}(x::AVec{X}, y::AVec{Y}, zf::Function) @recipe function f{X,Y}(x::AVec{X}, y::AVec{Y}, zf::Function)
x = X <: Number ? sort(x) : x # x = X <: Number ? sort(x) : x
y = Y <: Number ? sort(y) : y # y = Y <: Number ? sort(y) : y
SliceIt, x, y, Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported SliceIt, x, y, Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported
end end