Extrema type and link_axis; link keyword, removed old link logic
This commit is contained in:
parent
048c60614c
commit
ce82e07dc9
45
src/args.jl
45
src/args.jl
@ -192,10 +192,10 @@ const _plot_defaults = KW(
|
|||||||
:window_title => "Plots.jl",
|
:window_title => "Plots.jl",
|
||||||
:show => false,
|
:show => false,
|
||||||
:layout => 1,
|
:layout => 1,
|
||||||
:link => false,
|
:link => :none,
|
||||||
:linkx => false,
|
# :linkx => false,
|
||||||
:linky => false,
|
# :linky => false,
|
||||||
:linkfunc => nothing,
|
# :linkfunc => nothing,
|
||||||
:overwrite_figure => true,
|
:overwrite_figure => true,
|
||||||
:html_output_format => :auto,
|
:html_output_format => :auto,
|
||||||
)
|
)
|
||||||
@ -251,6 +251,7 @@ const _suppress_warnings = Set{Symbol}([
|
|||||||
:subplot,
|
:subplot,
|
||||||
:subplot_index,
|
:subplot_index,
|
||||||
:series_plotindex,
|
:series_plotindex,
|
||||||
|
:link,
|
||||||
])
|
])
|
||||||
|
|
||||||
# add defaults for the letter versions
|
# add defaults for the letter versions
|
||||||
@ -391,8 +392,8 @@ add_aliases(:size, :windowsize, :wsize)
|
|||||||
add_aliases(:window_title, :windowtitle, :wtitle)
|
add_aliases(:window_title, :windowtitle, :wtitle)
|
||||||
add_aliases(:show, :gui, :display)
|
add_aliases(:show, :gui, :display)
|
||||||
add_aliases(:color_palette, :palette)
|
add_aliases(:color_palette, :palette)
|
||||||
add_aliases(:linkx, :xlink)
|
# add_aliases(:linkx, :xlink)
|
||||||
add_aliases(:linky, :ylink)
|
# add_aliases(:linky, :ylink)
|
||||||
add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse)
|
add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse)
|
||||||
add_aliases(:xerror, :xerr, :xerrorbar)
|
add_aliases(:xerror, :xerr, :xerrorbar)
|
||||||
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
|
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
|
||||||
@ -656,21 +657,21 @@ function preprocessArgs!(d::KW)
|
|||||||
d[:colorbar] = convertLegendValue(d[:colorbar])
|
d[:colorbar] = convertLegendValue(d[:colorbar])
|
||||||
end
|
end
|
||||||
|
|
||||||
# handle subplot links
|
# # handle subplot links
|
||||||
if haskey(d, :link)
|
# if haskey(d, :link)
|
||||||
l = d[:link]
|
# l = d[:link]
|
||||||
if isa(l, Bool)
|
# if isa(l, Bool)
|
||||||
d[:linkx] = l
|
# d[:linkx] = l
|
||||||
d[:linky] = l
|
# d[:linky] = l
|
||||||
elseif isa(l, Function)
|
# elseif isa(l, Function)
|
||||||
d[:linkx] = true
|
# d[:linkx] = true
|
||||||
d[:linky] = true
|
# d[:linky] = true
|
||||||
d[:linkfunc] = l
|
# d[:linkfunc] = l
|
||||||
else
|
# else
|
||||||
warn("Unhandled/invalid link $l. Should be a Bool or a function mapping (row,column) -> (linkx, linky), where linkx/y can be Bool or Void (nothing)")
|
# warn("Unhandled/invalid link $l. Should be a Bool or a function mapping (row,column) -> (linkx, linky), where linkx/y can be Bool or Void (nothing)")
|
||||||
end
|
# end
|
||||||
delete!(d, :link)
|
# delete!(d, :link)
|
||||||
end
|
# end
|
||||||
end
|
end
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@ -904,6 +905,8 @@ function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::I
|
|||||||
color_or_match!(axis.d, :foreground_color_border, fg)
|
color_or_match!(axis.d, :foreground_color_border, fg)
|
||||||
color_or_match!(axis.d, :foreground_color_guide, fg)
|
color_or_match!(axis.d, :foreground_color_guide, fg)
|
||||||
color_or_match!(axis.d, :foreground_color_text, fg)
|
color_or_match!(axis.d, :foreground_color_text, fg)
|
||||||
|
|
||||||
|
# TODO: need to handle linking here?
|
||||||
end
|
end
|
||||||
|
|
||||||
# now we can get rid of the axis keys without a letter
|
# now we can get rid of the axis keys without a letter
|
||||||
|
|||||||
108
src/axes.jl
108
src/axes.jl
@ -4,23 +4,21 @@ xaxis(args...; kw...) = Axis(:x, args...; kw...)
|
|||||||
yaxis(args...; kw...) = Axis(:y, args...; kw...)
|
yaxis(args...; kw...) = Axis(:y, args...; kw...)
|
||||||
zaxis(args...; kw...) = Axis(:z, args...; kw...)
|
zaxis(args...; kw...) = Axis(:z, args...; kw...)
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
function Axis(letter::Symbol, args...; kw...)
|
function Axis(letter::Symbol, args...; kw...)
|
||||||
# init with values from _plot_defaults
|
# init with values from _plot_defaults
|
||||||
d = KW(
|
d = KW(
|
||||||
:letter => letter,
|
:letter => letter,
|
||||||
:extrema => (Inf, -Inf),
|
# :extrema => (Inf, -Inf),
|
||||||
|
:extrema => Extrema(),
|
||||||
:discrete_map => Dict(), # map discrete values to discrete indices
|
:discrete_map => Dict(), # map discrete values to discrete indices
|
||||||
# :discrete_values => Tuple{Float64,Any}[],
|
|
||||||
# :discrete_values => [],
|
|
||||||
:continuous_values => zeros(0),
|
:continuous_values => zeros(0),
|
||||||
: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)
|
||||||
)
|
)
|
||||||
merge!(d, _axis_defaults)
|
merge!(d, _axis_defaults)
|
||||||
d[:discrete_values] = []
|
d[:discrete_values] = []
|
||||||
# DD(d)
|
|
||||||
# @show args kw
|
|
||||||
|
|
||||||
# update the defaults
|
# update the defaults
|
||||||
update!(Axis(d), args...; kw...)
|
update!(Axis(d), args...; kw...)
|
||||||
@ -88,41 +86,52 @@ function update!(axis::Axis, args...; kw...)
|
|||||||
axis
|
axis
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
Base.show(io::IO, a::Axis) = dumpdict(a.d, "Axis", true)
|
Base.show(io::IO, axis::Axis) = dumpdict(axis.d, "Axis", true)
|
||||||
Base.getindex(a::Axis, k::Symbol) = getindex(a.d, k)
|
Base.getindex(axis::Axis, k::Symbol) = getindex(axis.d, k)
|
||||||
Base.setindex!(a::Axis, v, ks::Symbol...) = setindex!(a.d, v, ks...)
|
Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.d, v, ks...)
|
||||||
Base.haskey(a::Axis, k::Symbol) = haskey(a.d, k)
|
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.d, k)
|
||||||
Base.extrema(a::Axis) = a[:extrema]
|
Base.extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
|
||||||
|
|
||||||
# get discrete ticks, or not
|
# get discrete ticks, or not
|
||||||
function get_ticks(a::Axis)
|
function get_ticks(axis::Axis)
|
||||||
ticks = a[:ticks]
|
ticks = axis[:ticks]
|
||||||
dvals = a[:discrete_values]
|
dvals = axis[:discrete_values]
|
||||||
if !isempty(dvals) && ticks == :auto
|
if !isempty(dvals) && ticks == :auto
|
||||||
# vals, labels = unzip(dvals)
|
axis[:continuous_values], dvals
|
||||||
a[:continuous_values], dvals
|
|
||||||
else
|
else
|
||||||
ticks
|
ticks
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function expand_extrema!(a::Axis, v::Number)
|
# -------------------------------------------------------------------------
|
||||||
emin, emax = a[:extrema]
|
|
||||||
a[:extrema] = (min(v, emin), max(v, emax))
|
function expand_extrema!(ex::Extrema, v::Number)
|
||||||
|
ex.emin = min(v, ex.emin)
|
||||||
|
ex.emax = max(v, ex.emax)
|
||||||
|
ex
|
||||||
end
|
end
|
||||||
function expand_extrema!{MIN<:Number,MAX<:Number}(a::Axis, v::Tuple{MIN,MAX})
|
|
||||||
emin, emax = a[:extrema]
|
function expand_extrema!(axis::Axis, v::Number)
|
||||||
a[:extrema] = (min(v[1], emin), max(v[2], emax))
|
expand_extrema!(axis[:extrema], v)
|
||||||
end
|
end
|
||||||
function expand_extrema!{N<:Number}(a::Axis, v::AVec{N})
|
function expand_extrema!{MIN<:Number,MAX<:Number}(axis::Axis, v::Tuple{MIN,MAX})
|
||||||
if !isempty(v)
|
ex = axis[:extrema]
|
||||||
emin, emax = a[:extrema]
|
ex.emin = min(v[1], ex.emin)
|
||||||
a[:extrema] = (min(minimum(v), emin), max(maximum(v), emax))
|
ex.emax = max(v[2], ex.emax)
|
||||||
|
ex
|
||||||
|
end
|
||||||
|
function expand_extrema!{N<:Number}(axis::Axis, v::AVec{N})
|
||||||
|
ex = axis[:extrema]
|
||||||
|
for vi in v
|
||||||
|
expand_extrema!(ex, vi)
|
||||||
end
|
end
|
||||||
a[:extrema]
|
ex
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
# push the limits out slightly
|
# push the limits out slightly
|
||||||
function widen(lmin, lmax)
|
function widen(lmin, lmax)
|
||||||
span = lmax - lmin
|
span = lmax - lmin
|
||||||
@ -132,7 +141,8 @@ end
|
|||||||
|
|
||||||
# using the axis extrema and limit overrides, return the min/max value for this axis
|
# using the axis extrema and limit overrides, return the min/max value for this axis
|
||||||
function axis_limits(axis::Axis, should_widen::Bool = true)
|
function axis_limits(axis::Axis, should_widen::Bool = true)
|
||||||
amin, amax = axis[:extrema]
|
ex = axis[:extrema]
|
||||||
|
amin, amax = ex.emin, ex.emax
|
||||||
lims = axis[:lims]
|
lims = axis[:lims]
|
||||||
if isa(lims, Tuple) && length(lims) == 2
|
if isa(lims, Tuple) && length(lims) == 2
|
||||||
if isfinite(lims[1])
|
if isfinite(lims[1])
|
||||||
@ -152,58 +162,62 @@ function axis_limits(axis::Axis, should_widen::Bool = true)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# these methods track the discrete values which correspond to axis continuous values (cv)
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# these methods track the discrete (categorical) values which correspond to axis continuous values (cv)
|
||||||
# whenever we have discrete values, we automatically set the ticks to match.
|
# whenever we have discrete values, we automatically set the ticks to match.
|
||||||
# we return (continuous_value, discrete_index)
|
# we return (continuous_value, discrete_index)
|
||||||
function discrete_value!(a::Axis, dv)
|
function discrete_value!(axis::Axis, dv)
|
||||||
cv_idx = get(a[:discrete_map], dv, -1)
|
cv_idx = get(axis[:discrete_map], dv, -1)
|
||||||
# @show a[:discrete_map], a[:discrete_values], dv
|
# @show axis[:discrete_map], axis[:discrete_values], dv
|
||||||
if cv_idx == -1
|
if cv_idx == -1
|
||||||
emin, emax = a[:extrema]
|
ex = axis[:extrema]
|
||||||
cv = max(0.5, emax + 1.0)
|
cv = max(0.5, ex.emax + 1.0)
|
||||||
expand_extrema!(a, cv)
|
expand_extrema!(axis, cv)
|
||||||
push!(a[:discrete_values], dv)
|
push!(axis[:discrete_values], dv)
|
||||||
push!(a[:continuous_values], cv)
|
push!(axis[:continuous_values], cv)
|
||||||
cv_idx = length(a[:discrete_values])
|
cv_idx = length(axis[:discrete_values])
|
||||||
a[:discrete_map][dv] = cv_idx
|
axis[:discrete_map][dv] = cv_idx
|
||||||
cv, cv_idx
|
cv, cv_idx
|
||||||
else
|
else
|
||||||
cv = a[:continuous_values][cv_idx]
|
cv = axis[:continuous_values][cv_idx]
|
||||||
cv, cv_idx
|
cv, cv_idx
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# continuous value... just pass back with a negative index
|
# continuous value... just pass back with axis negative index
|
||||||
function discrete_value!(a::Axis, cv::Number)
|
function discrete_value!(axis::Axis, cv::Number)
|
||||||
cv, -1
|
cv, -1
|
||||||
end
|
end
|
||||||
|
|
||||||
# add the discrete value for each item. return the continuous values and the indices
|
# add the discrete value for each item. return the continuous values and the indices
|
||||||
function discrete_value!(a::Axis, v::AVec)
|
function discrete_value!(axis::Axis, v::AVec)
|
||||||
n = length(v)
|
n = length(v)
|
||||||
cvec = zeros(n)
|
cvec = zeros(n)
|
||||||
discrete_indices = zeros(Int, n)
|
discrete_indices = zeros(Int, n)
|
||||||
for i=1:n
|
for i=1:n
|
||||||
cvec[i], discrete_indices[i] = discrete_value!(a, v[i])
|
cvec[i], discrete_indices[i] = discrete_value!(axis, v[i])
|
||||||
end
|
end
|
||||||
cvec, discrete_indices
|
cvec, discrete_indices
|
||||||
end
|
end
|
||||||
|
|
||||||
# add the discrete value for each item. return the continuous values and the indices
|
# add the discrete value for each item. return the continuous values and the indices
|
||||||
function discrete_value!(a::Axis, v::AMat)
|
function discrete_value!(axis::Axis, v::AMat)
|
||||||
n,m = size(v)
|
n,m = size(v)
|
||||||
cmat = zeros(n,m)
|
cmat = zeros(n,m)
|
||||||
discrete_indices = zeros(Int, n, m)
|
discrete_indices = zeros(Int, n, m)
|
||||||
for i=1:n, j=1:m
|
for i=1:n, j=1:m
|
||||||
cmat[i,j], discrete_indices[i,j] = discrete_value!(a, v[i,j])
|
cmat[i,j], discrete_indices[i,j] = discrete_value!(axis, v[i,j])
|
||||||
end
|
end
|
||||||
cmat, discrete_indices
|
cmat, discrete_indices
|
||||||
end
|
end
|
||||||
|
|
||||||
function discrete_value!(a::Axis, v::Surface)
|
function discrete_value!(axis::Axis, v::Surface)
|
||||||
map(Surface, discrete_value!(a, v.surf))
|
map(Surface, discrete_value!(axis, v.surf))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
function pie_labels(sp::Subplot, series::Series)
|
function pie_labels(sp::Subplot, series::Series)
|
||||||
d = series.d
|
d = series.d
|
||||||
if haskey(d,:x_discrete_indices)
|
if haskey(d,:x_discrete_indices)
|
||||||
|
|||||||
@ -841,23 +841,23 @@ end
|
|||||||
|
|
||||||
# -----------------------------------------------------------------
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
function set_lims!(sp::Subplot{PyPlotBackend}, axis::Axis)
|
# function set_lims!(sp::Subplot{PyPlotBackend}, axis::Axis)
|
||||||
lims = copy(axis[:extrema])
|
# lims = copy(axis[:extrema])
|
||||||
lims_override = axis[:lims]
|
# lims_override = axis[:lims]
|
||||||
if lims_override != :auto
|
# if lims_override != :auto
|
||||||
if isfinite(lims_override[1])
|
# if isfinite(lims_override[1])
|
||||||
lims[1] = lims_override[1]
|
# lims[1] = lims_override[1]
|
||||||
end
|
# end
|
||||||
if isfinite(lims_override[2])
|
# if isfinite(lims_override[2])
|
||||||
lims[2] = lims_override[2]
|
# lims[2] = lims_override[2]
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
# TODO: check for polar, do set_tlim/set_rlim instead
|
# # TODO: check for polar, do set_tlim/set_rlim instead
|
||||||
|
#
|
||||||
# pyplot's set_xlim (or y/z) method:
|
# # pyplot's set_xlim (or y/z) method:
|
||||||
sp.o[symbol(:set_, axis[:letter], :lim)](lims...)
|
# sp.o[symbol(:set_, axis[:letter], :lim)](lims...)
|
||||||
end
|
# end
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -867,10 +867,10 @@ get_axis(sp::Subplot, letter::Symbol) = sp.attr[symbol(letter, :axis)]
|
|||||||
|
|
||||||
function update_limits!(sp::Subplot{PyPlotBackend}, series::Series, letters)
|
function update_limits!(sp::Subplot{PyPlotBackend}, series::Series, letters)
|
||||||
for letter in letters
|
for letter in letters
|
||||||
axis = get_axis(sp, letter)
|
# axis = get_axis(sp, letter)
|
||||||
expand_extrema!(axis, series.d[letter])
|
# expand_extrema!(axis, series.d[letter])
|
||||||
# set_lims!(sp, axis)
|
# set_lims!(sp, axis)
|
||||||
setPyPlotLims(sp.o, axis)
|
setPyPlotLims(sp.o, sp.attr[symbol(letter, :axis)])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -438,6 +438,7 @@ function build_layout(layout::GridLayout, n::Integer)
|
|||||||
end
|
end
|
||||||
i >= n && break # only add n subplots
|
i >= n && break # only add n subplots
|
||||||
end
|
end
|
||||||
|
|
||||||
layout, subplots, spmap
|
layout, subplots, spmap
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -478,7 +479,7 @@ end
|
|||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# @layout macro
|
# @layout macro
|
||||||
|
|
||||||
function add_layout_pct!(kw::KW, v::Expr, idx::Integer)
|
function add_layout_pct!(kw::KW, v::Expr, idx::Integer, nidx::Integer)
|
||||||
# dump(v)
|
# dump(v)
|
||||||
# something like {0.2w}?
|
# something like {0.2w}?
|
||||||
if v.head == :call && v.args[1] == :*
|
if v.head == :call && v.args[1] == :*
|
||||||
@ -490,7 +491,9 @@ function add_layout_pct!(kw::KW, v::Expr, idx::Integer)
|
|||||||
elseif units == :w
|
elseif units == :w
|
||||||
return kw[:w] = num*pct
|
return kw[:w] = num*pct
|
||||||
elseif units in (:pct, :px, :mm, :cm, :inch)
|
elseif units in (:pct, :px, :mm, :cm, :inch)
|
||||||
return kw[idx == 1 ? :w : :h] = v
|
idx == 1 && (kw[:w] = v)
|
||||||
|
(idx == 2 || nidx == 1) && (kw[:h] = v)
|
||||||
|
# return kw[idx == 1 ? :w : :h] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -498,7 +501,9 @@ function add_layout_pct!(kw::KW, v::Expr, idx::Integer)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function add_layout_pct!(kw::KW, v::Number, idx::Integer)
|
function add_layout_pct!(kw::KW, v::Number, idx::Integer)
|
||||||
kw[idx == 1 ? :w : :h] = v*pct
|
# kw[idx == 1 ? :w : :h] = v*pct
|
||||||
|
idx == 1 && (kw[:w] = v*pct)
|
||||||
|
(idx == 2 || nidx == 1) && (kw[:h] = v*pct)
|
||||||
end
|
end
|
||||||
|
|
||||||
function create_grid(expr::Expr)
|
function create_grid(expr::Expr)
|
||||||
@ -522,7 +527,7 @@ function create_grid(expr::Expr)
|
|||||||
s = expr.args[1]
|
s = expr.args[1]
|
||||||
kw = KW()
|
kw = KW()
|
||||||
for (i,arg) in enumerate(expr.args[2:end])
|
for (i,arg) in enumerate(expr.args[2:end])
|
||||||
add_layout_pct!(kw, arg, i)
|
add_layout_pct!(kw, arg, i, length(expr.args)-1)
|
||||||
end
|
end
|
||||||
# @show kw
|
# @show kw
|
||||||
:(EmptyLayout(label = $(QuoteNode(s)), width = $(get(kw, :w, QuoteNode(:auto))), height = $(get(kw, :h, QuoteNode(:auto)))))
|
:(EmptyLayout(label = $(QuoteNode(s)), width = $(get(kw, :w, QuoteNode(:auto))), height = $(get(kw, :h, QuoteNode(:auto)))))
|
||||||
@ -540,3 +545,50 @@ end
|
|||||||
macro layout(mat::Expr)
|
macro layout(mat::Expr)
|
||||||
create_grid(mat)
|
create_grid(mat)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# make all reference the same axis extrema/values
|
||||||
|
function link_axes!(axes::Axis...)
|
||||||
|
a1 = axes[1]
|
||||||
|
for i=2:length(axes)
|
||||||
|
a2 = axes[i]
|
||||||
|
for k in (:extrema, :discrete_values, :continuous_values, :discrete_map)
|
||||||
|
a2[k] = a1[k]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# for some vector or matrix of layouts, filter only the Subplots and link those axes
|
||||||
|
function link_axes!(a::AbstractArray{AbstractLayout}, axissym::Symbol)
|
||||||
|
subplots = filter(l -> isa(l, Subplot), a)
|
||||||
|
axes = [sp.attr[axissym] for sp in subplots]
|
||||||
|
link_axes!(axes...)
|
||||||
|
end
|
||||||
|
|
||||||
|
# don't do anything for most layout types
|
||||||
|
function link_axes!(l::AbstractLayout, link::Symbol)
|
||||||
|
end
|
||||||
|
|
||||||
|
# process a GridLayout, recursively linking axes according to the link symbol
|
||||||
|
function link_axes!(layout::GridLayout, link::Symbol)
|
||||||
|
nr, nc = size(layout)
|
||||||
|
if link in (:x, :both)
|
||||||
|
for c=1:nc
|
||||||
|
link_axes!(layout.grid[:,c], :xaxis)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if link in (:y, :both)
|
||||||
|
for r=1:nr
|
||||||
|
link_axes!(layout.grid[r,:], :yaxis)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if link == :all
|
||||||
|
link_axes!(layout.grid, :xaxis)
|
||||||
|
link_axes!(layout.grid, :yaxis)
|
||||||
|
end
|
||||||
|
for l in layout.grid
|
||||||
|
link_axes!(l, link)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
26
src/plot.jl
26
src/plot.jl
@ -309,19 +309,17 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
# grab the first in line to be processed and pass it through apply_recipe
|
# grab the first in line to be processed and pass it through apply_recipe
|
||||||
# to generate a list of RecipeData objects (data + attributes)
|
# to generate a list of RecipeData objects (data + attributes)
|
||||||
next_series = shift!(still_to_process)
|
next_series = shift!(still_to_process)
|
||||||
series_list = RecipesBase.apply_recipe(next_series.d, next_series.args...)
|
for recipedata in RecipesBase.apply_recipe(next_series.d, next_series.args...)
|
||||||
for series in series_list
|
|
||||||
|
|
||||||
# series should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes
|
# recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes
|
||||||
if !(typeof(series) <: RecipeData)
|
if !(typeof(recipedata) <: RecipeData)
|
||||||
error("Inputs couldn't be processed... expected RecipeData but got: $series")
|
error("Inputs couldn't be processed... expected RecipeData but got: $recipedata")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @show series
|
if isempty(recipedata.args)
|
||||||
if isempty(series.args)
|
|
||||||
# when the arg tuple is empty, that means there's nothing left to recursively
|
# when the arg tuple is empty, that means there's nothing left to recursively
|
||||||
# process... finish up and add to the kw_list
|
# process... finish up and add to the kw_list
|
||||||
kw = series.d
|
kw = recipedata.d
|
||||||
_add_markershape(kw)
|
_add_markershape(kw)
|
||||||
|
|
||||||
# if there was a grouping, filter the data here
|
# if there was a grouping, filter the data here
|
||||||
@ -347,8 +345,8 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
warnOnUnsupportedScales(plt.backend, kw)
|
warnOnUnsupportedScales(plt.backend, kw)
|
||||||
push!(kw_list, kw)
|
push!(kw_list, kw)
|
||||||
|
|
||||||
# handle error bars by creating new series data... these will have
|
# handle error bars by creating new recipedata data... these will have
|
||||||
# the same series index as the series they are copied from
|
# the same recipedata index as the recipedata they are copied from
|
||||||
for esym in (:xerror, :yerror)
|
for esym in (:xerror, :yerror)
|
||||||
if get(d, esym, nothing) != nothing
|
if get(d, esym, nothing) != nothing
|
||||||
# we make a copy of the KW and apply an errorbar recipe
|
# we make a copy of the KW and apply an errorbar recipe
|
||||||
@ -360,7 +358,7 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
|
|
||||||
else
|
else
|
||||||
# args are non-empty, so there's still processing to do... add it back to the queue
|
# args are non-empty, so there's still processing to do... add it back to the queue
|
||||||
push!(still_to_process, series)
|
push!(still_to_process, recipedata)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -398,7 +396,11 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
_update_subplot_args(plt, sp, d, idx)
|
_update_subplot_args(plt, sp, d, idx)
|
||||||
end
|
end
|
||||||
|
|
||||||
# !!! note: at this point, kw_list is fully decomposed into individual series... one KW per series !!!
|
# do we need to link any axes together?
|
||||||
|
link_axes!(plt.layout, plt.attr[:link])
|
||||||
|
|
||||||
|
# !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!!
|
||||||
|
# !!! The next step is to recursively apply series recipes until the backend supports that series type !!!
|
||||||
|
|
||||||
# this is it folks!
|
# this is it folks!
|
||||||
# TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes
|
# TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes
|
||||||
|
|||||||
@ -27,6 +27,12 @@ type Axis
|
|||||||
d::KW
|
d::KW
|
||||||
end
|
end
|
||||||
|
|
||||||
|
type Extrema
|
||||||
|
emin::Float64
|
||||||
|
emax::Float64
|
||||||
|
end
|
||||||
|
Extrema() = Extrema(Inf, -Inf)
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# a single subplot
|
# a single subplot
|
||||||
|
|||||||
36
src/utils.jl
36
src/utils.jl
@ -483,42 +483,20 @@ end
|
|||||||
function setxy!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer)
|
function setxy!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer)
|
||||||
series = plt.series_list[i]
|
series = plt.series_list[i]
|
||||||
series.d[:x], series.d[:y] = xy
|
series.d[:x], series.d[:y] = xy
|
||||||
|
sp = series.d[:subplot]
|
||||||
|
expand_extrema!(sp.attr[:xaxis], xy[1])
|
||||||
|
expand_extrema!(sp.attr[:yaxis], xy[2])
|
||||||
_series_updated(plt, series)
|
_series_updated(plt, series)
|
||||||
end
|
end
|
||||||
function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
|
function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
|
||||||
series = plt.series_list[i]
|
series = plt.series_list[i]
|
||||||
series.d[:x], series.d[:y], series.d[:z] = xyz
|
series.d[:x], series.d[:y], series.d[:z] = xyz
|
||||||
|
sp = series.d[:subplot]
|
||||||
|
expand_extrema!(sp.attr[:xaxis], xy[1])
|
||||||
|
expand_extrema!(sp.attr[:yaxis], xy[2])
|
||||||
|
expand_extrema!(sp.attr[:zaxis], xy[3])
|
||||||
_series_updated(plt, series)
|
_series_updated(plt, series)
|
||||||
end
|
end
|
||||||
#
|
|
||||||
#
|
|
||||||
# function setxy!{X,Y}(plt::Plot{PyPlotBackend}, xy::Tuple{X,Y}, i::Integer)
|
|
||||||
# series = plt.series_list[i]
|
|
||||||
# d = series.d
|
|
||||||
# d[:x], d[:y] = xy
|
|
||||||
# for handle in d[:serieshandle]
|
|
||||||
# try
|
|
||||||
# handle[:set_data](xy...)
|
|
||||||
# catch
|
|
||||||
# handle[:set_offsets](hcat(xy...))
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# update_limits!(d[:subplot], series, (:x,:y))
|
|
||||||
# plt
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# function setxyz!{X,Y,Z}(plt::Plot{PyPlotBackend}, xyz::Tuple{X,Y,Z}, i::Integer)
|
|
||||||
# series = plt.series_list[i]
|
|
||||||
# d = series.d
|
|
||||||
# d[:x], d[:y], d[:z] = xyz
|
|
||||||
# for handle in d[:serieshandle]
|
|
||||||
# handle[:set_data](d[:x], d[:y])
|
|
||||||
# handle[:set_3d_properties](d[:z])
|
|
||||||
# end
|
|
||||||
# update_limits!(d[:subplot], series, (:x,:y,:z))
|
|
||||||
# plt
|
|
||||||
# end
|
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
# indexing notation
|
# indexing notation
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user