axis formatter

This commit is contained in:
Thomas Breloff 2016-07-26 12:34:06 -04:00
parent 3b1c409fd7
commit bbb00816f1
3 changed files with 36 additions and 21 deletions

View File

@ -100,6 +100,7 @@ const _arg_desc = KW(
:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`", :scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`",
:rotation => "Number. Degrees rotation of tick labels.", :rotation => "Number. Degrees rotation of tick labels.",
:flip => "Bool. Should we flip (reverse) the axis?", :flip => "Bool. Should we flip (reverse) the axis?",
:formatter => "Function, :scientific, or :auto. A method which converts a number to a string for tick labeling.",
:tickfont => "Font. Font of axis tick labels.", :tickfont => "Font. Font of axis tick labels.",
:guidefont => "Font. Font of axis guide (label).", :guidefont => "Font. Font of axis guide (label).",
:foreground_color_axis => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis ticks.", :foreground_color_axis => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis ticks.",

View File

@ -265,6 +265,7 @@ const _axis_defaults = KW(
:foreground_color_text => :match, # tick text color, :foreground_color_text => :match, # tick text color,
:foreground_color_guide => :match, # guide text color, :foreground_color_guide => :match, # guide text color,
:discrete_values => [], :discrete_values => [],
:formatter => :auto,
) )
const _suppress_warnings = Set{Symbol}([ const _suppress_warnings = Set{Symbol}([
@ -298,7 +299,8 @@ for letter in (:x,:y,:z)
:foreground_color_border, :foreground_color_border,
:foreground_color_text, :foreground_color_text,
:foreground_color_guide, :foreground_color_guide,
:discrete_values :discrete_values,
:formatter,
) )
_axis_defaults_byletter[Symbol(letter,k)] = :match _axis_defaults_byletter[Symbol(letter,k)] = :match

View File

@ -73,6 +73,9 @@ function process_axis_arg!(d::KW, arg, letter = "")
elseif typeof(arg) <: Number elseif typeof(arg) <: Number
d[Symbol(letter,:rotation)] = arg d[Symbol(letter,:rotation)] = arg
elseif typeof(arg) <: Function
d[Symbol(letter,:formatter)] = arg
else else
warn("Skipped $(letter)axis arg $arg") warn("Skipped $(letter)axis arg $arg")
@ -129,6 +132,12 @@ const _inv_scale_funcs = Dict{Symbol,Function}(
:ln => exp, :ln => exp,
) )
# const _label_func = Dict{Symbol,Function}(
# :log10 => x -> "10^$x",
# :log2 => x -> "2^$x",
# :ln => x -> "e^$x",
# )
const _label_func = Dict{Symbol,Function}( const _label_func = Dict{Symbol,Function}(
:log10 => x -> "10^$x", :log10 => x -> "10^$x",
:log2 => x -> "2^$x", :log2 => x -> "2^$x",
@ -141,41 +150,44 @@ invscalefunc(scale::Symbol) = x -> get(_inv_scale_funcs, scale, identity)(Float6
labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string) labelfunc(scale::Symbol, backend::AbstractBackend) = get(_label_func, scale, string)
function optimal_ticks_and_labels(axis::Axis, ticks = nothing) function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
lims = axis_limits(axis) amin,amax = axis_limits(axis)
# scale the limits # scale the limits
scale = axis[:scale] scale = axis[:scale]
scaled_lims = map(scalefunc(scale), lims) sf = scalefunc(scale)
# @show lims scaled_lims
# get a list of well-laid-out ticks # get a list of well-laid-out ticks
cv = if ticks == nothing scaled_ticks = if ticks == nothing
optimize_ticks(scaled_lims..., optimize_ticks(
sf(amin),
sf(amax);
k_min = 5, # minimum number of ticks k_min = 5, # minimum number of ticks
k_max = 8, # maximum number of ticks k_max = 8, # maximum number of ticks
# span_buffer = 0.0 # padding buffer in case nice ticks are closeby
)[1] )[1]
else else
ticks map(sf, ticks)
end end
unscaled_ticks = map(invscalefunc(scale), scaled_ticks)
# # expand to ensure we see all the ticks labels = if any(isfinite, unscaled_ticks)
# expand_extrema!(axis, cv) formatter = axis[:formatter]
if formatter == :auto
# rescale and return values and labels # the default behavior is to make strings of the scaled values and then apply the labelfunc
# @show cv map(labelfunc(scale, backend()), Showoff.showoff(scaled_ticks, :plain))
ticklabels = if any(isfinite, cv) elseif formatter == :scientific
map(labelfunc(scale, backend()), Showoff.showoff(cv, :plain)) Showoff.showoff(unscaled_ticks, :scientific)
else else
# there was an override for the formatter... use that on the unscaled ticks
map(formatter, unscaled_ticks)
end
else
# no finite ticks to show...
String[] String[]
end end
tickvals = map(invscalefunc(scale), cv) # @show unscaled_ticks labels
# @show tickvals ticklabels # labels = Showoff.showoff(unscaled_ticks, scale == :log10 ? :scientific : :auto)
# ticklabels = Showoff.showoff(tickvals, scale == :log10 ? :scientific : :auto) unscaled_ticks, labels
tickvals, ticklabels
# basestr = scale == :log10 ? "10^" : scale == :log2 ? "2^" : scale == :ln ? "e^" : ""
# tickvals, ["$basestr$cvi" for cvi in cv]
end end
# return (continuous_values, discrete_values) for the ticks on this axis # return (continuous_values, discrete_values) for the ticks on this axis