133 lines
3.5 KiB
Julia
133 lines
3.5 KiB
Julia
|
|
|
|
xaxis(args...; kw...) = Axis(:x, args...; kw...)
|
|
yaxis(args...; kw...) = Axis(:y, args...; kw...)
|
|
zaxis(args...; kw...) = Axis(:z, args...; kw...)
|
|
|
|
|
|
function Axis(letter::Symbol, args...; kw...)
|
|
# init with values from _plot_defaults
|
|
d = KW(
|
|
:letter => letter,
|
|
:extrema => (Inf, -Inf),
|
|
:discrete_map => Dict(), # map discrete values to continuous plot values
|
|
:discrete_values => Tuple{Float64,Any}[],
|
|
:use_minor => false,
|
|
:show => true, # show or hide the axis? (useful for linked subplots)
|
|
)
|
|
merge!(d, _axis_defaults)
|
|
|
|
# update the defaults
|
|
update!(Axis(d), args...; kw...)
|
|
end
|
|
|
|
function process_axis_arg!(d::KW, arg, letter = "")
|
|
T = typeof(arg)
|
|
arg = get(_scaleAliases, arg, arg)
|
|
|
|
if typeof(arg) <: Font
|
|
d[symbol(letter,:tickfont)] = arg
|
|
d[symbol(letter,:guidefont)] = arg
|
|
|
|
elseif arg in _allScales
|
|
d[symbol(letter,:scale)] = arg
|
|
|
|
elseif arg in (:flip, :invert, :inverted)
|
|
d[symbol(letter,:flip)] = true
|
|
|
|
elseif T <: @compat(AbstractString)
|
|
d[symbol(letter,:guide)] = arg
|
|
|
|
# xlims/ylims
|
|
elseif (T <: Tuple || T <: AVec) && length(arg) == 2
|
|
sym = typeof(arg[1]) <: Number ? :lims : :ticks
|
|
d[symbol(letter,sym)] = arg
|
|
|
|
# xticks/yticks
|
|
elseif T <: AVec
|
|
d[symbol(letter,:ticks)] = arg
|
|
|
|
elseif arg == nothing
|
|
d[symbol(letter,:ticks)] = []
|
|
|
|
elseif typeof(arg) <: Number
|
|
d[symbol(letter,:rotation)] = arg
|
|
|
|
else
|
|
warn("Skipped $(letter)axis arg $arg")
|
|
|
|
end
|
|
end
|
|
|
|
# update an Axis object with magic args and keywords
|
|
function update!(a::Axis, args...; kw...)
|
|
# first process args
|
|
d = a.d
|
|
for arg in args
|
|
process_axis_arg!(d, arg)
|
|
end
|
|
|
|
# then override for any keywords... only those keywords that already exists in d
|
|
for (k,v) in kw
|
|
# sym = symbol(string(k)[2:end])
|
|
if haskey(d, k)
|
|
d[k] = v
|
|
end
|
|
end
|
|
a
|
|
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
|
|
function get_ticks(a::Axis)
|
|
ticks = a[:ticks]
|
|
dvals = a[:discrete_values]
|
|
if !isempty(dvals) && ticks == :auto
|
|
vals, labels = unzip(dvals)
|
|
else
|
|
ticks
|
|
end
|
|
end
|
|
|
|
function expand_extrema!(a::Axis, v::Number)
|
|
emin, emax = a[:extrema]
|
|
a[:extrema] = (min(v, emin), max(v, emax))
|
|
end
|
|
function expand_extrema!{MIN<:Number,MAX<:Number}(a::Axis, v::Tuple{MIN,MAX})
|
|
emin, emax = a[:extrema]
|
|
a[:extrema] = (min(v[1], emin), max(v[2], emax))
|
|
end
|
|
function expand_extrema!{N<:Number}(a::Axis, v::AVec{N})
|
|
if !isempty(v)
|
|
emin, emax = a[:extrema]
|
|
a[:extrema] = (min(minimum(v), emin), max(maximum(v), emax))
|
|
end
|
|
a[:extrema]
|
|
end
|
|
|
|
# these methods track the discrete values which correspond to axis continuous values (cv)
|
|
# whenever we have discrete values, we automatically set the ticks to match.
|
|
# we return the plot value
|
|
function discrete_value!(a::Axis, v)
|
|
cv = get(a[:discrete_map], v, NaN)
|
|
if isnan(cv)
|
|
emin, emax = a[:extrema]
|
|
cv = max(0.5, emax + 1.0)
|
|
expand_extrema!(a, cv)
|
|
a[:discrete_map][v] = cv
|
|
push!(a[:discrete_values], (cv, v))
|
|
end
|
|
cv
|
|
end
|
|
|
|
# add the discrete value for each item
|
|
function discrete_value!(a::Axis, v::AVec)
|
|
Float64[discrete_value!(a, vi) for vi=v]
|
|
end
|