Merge pull request #1029 from daschw/ds-axes-border

Allow turning on/off the axes border (fix #1025)
This commit is contained in:
Daniel Schwabeneder 2017-08-24 22:38:01 +02:00 committed by GitHub
commit 56bda82529
7 changed files with 117 additions and 43 deletions

View File

@ -93,6 +93,7 @@ const _arg_desc = KW(
:bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.", :bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.",
:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.", :subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.",
:colorbar_title => "String. Title of colorbar.", :colorbar_title => "String. Title of colorbar.",
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)",
# axis args # axis args
:guide => "String. Axis guide (label).", :guide => "String. Axis guide (label).",

View File

@ -181,6 +181,14 @@ function hasgrid(arg::Symbol, letter)
end end
hasgrid(arg::AbstractString, letter) = hasgrid(Symbol(arg), letter) hasgrid(arg::AbstractString, letter) = hasgrid(Symbol(arg), letter)
const _allFramestyles = [:box, :semi, :axes, :grid, :none]
const _framestyleAliases = Dict{Symbol, Symbol}(
:frame => :box,
:border => :box,
:on => :box,
:transparent => :semi,
:semitransparent => :semi,
)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
const _series_defaults = KW( const _series_defaults = KW(
@ -282,6 +290,7 @@ const _subplot_defaults = KW(
:bottom_margin => :match, :bottom_margin => :match,
:subplot_index => -1, :subplot_index => -1,
:colorbar_title => "", :colorbar_title => "",
:framestyle => :axes,
) )
const _axis_defaults = KW( const _axis_defaults = KW(
@ -423,7 +432,7 @@ add_aliases(:foreground_color_title, :fg_title, :fgtitle, :fgcolor_title, :fg_co
add_aliases(:foreground_color_axis, :fg_axis, :fgaxis, :fgcolor_axis, :fg_color_axis, :foreground_axis, add_aliases(:foreground_color_axis, :fg_axis, :fgaxis, :fgcolor_axis, :fg_color_axis, :foreground_axis,
:foreground_colour_axis, :fgcolour_axis, :fg_colour_axis, :axiscolor) :foreground_colour_axis, :fgcolour_axis, :fg_colour_axis, :axiscolor)
add_aliases(:foreground_color_border, :fg_border, :fgborder, :fgcolor_border, :fg_color_border, :foreground_border, add_aliases(:foreground_color_border, :fg_border, :fgborder, :fgcolor_border, :fg_color_border, :foreground_border,
:foreground_colour_border, :fgcolour_border, :fg_colour_border, :bordercolor, :border) :foreground_colour_border, :fgcolour_border, :fg_colour_border, :bordercolor)
add_aliases(:foreground_color_text, :fg_text, :fgtext, :fgcolor_text, :fg_color_text, :foreground_text, add_aliases(:foreground_color_text, :fg_text, :fgtext, :fgcolor_text, :fg_color_text, :foreground_text,
:foreground_colour_text, :fgcolour_text, :fg_colour_text, :textcolor) :foreground_colour_text, :fgcolour_text, :fg_colour_text, :textcolor)
add_aliases(:foreground_color_guide, :fg_guide, :fgguide, :fgcolor_guide, :fg_color_guide, :foreground_guide, add_aliases(:foreground_color_guide, :fg_guide, :fgguide, :fgcolor_guide, :fg_color_guide, :foreground_guide,
@ -493,6 +502,7 @@ add_aliases(:orientation, :direction, :dir)
add_aliases(:inset_subplots, :inset, :floating) add_aliases(:inset_subplots, :inset, :floating)
add_aliases(:gridlinewidth, :gridwidth, :grid_linewidth, :grid_width, :gridlw, :grid_lw) add_aliases(:gridlinewidth, :gridwidth, :grid_linewidth, :grid_width, :gridlw, :grid_lw)
add_aliases(:gridstyle, :grid_style, :gridlinestyle, :grid_linestyle, :grid_ls, :gridls) add_aliases(:gridstyle, :grid_style, :gridlinestyle, :grid_linestyle, :grid_ls, :gridls)
add_aliases(:framestyle, :frame_style, :frame, :axesstyle, :axes_style, :boxstyle, :box_style, :box, :borderstyle, :border_style, :border)
# add all pluralized forms to the _keyAliases dict # add all pluralized forms to the _keyAliases dict
@ -719,6 +729,7 @@ function preprocessArgs!(d::KW)
if haskey(d, :axis) && d[:axis] in (:none, nothing, false) if haskey(d, :axis) && d[:axis] in (:none, nothing, false)
d[:ticks] = nothing d[:ticks] = nothing
d[:foreground_color_border] = RGBA(0,0,0,0) d[:foreground_color_border] = RGBA(0,0,0,0)
d[:foreground_color_axis] = RGBA(0,0,0,0)
d[:grid] = false d[:grid] = false
delete!(d, :axis) delete!(d, :axis)
end end
@ -821,6 +832,11 @@ function preprocessArgs!(d::KW)
d[:colorbar] = convertLegendValue(d[:colorbar]) d[:colorbar] = convertLegendValue(d[:colorbar])
end end
# framestyle
if haskey(d, :framestyle) && haskey(_framestyleAliases, d[:framestyle])
d[:framestyle] = _framestyleAliases[d[:framestyle]]
end
# warnings for moved recipes # warnings for moved recipes
st = get(d, :seriestype, :path) st = get(d, :seriestype, :path)
if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatPlots) if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatPlots)

View File

@ -506,40 +506,46 @@ function axis_drawing_info(sp::Subplot)
ymin, ymax = axis_limits(yaxis) ymin, ymax = axis_limits(yaxis)
xticks = get_ticks(xaxis) xticks = get_ticks(xaxis)
yticks = get_ticks(yaxis) yticks = get_ticks(yaxis)
xspine_segs = Segments(2) xaxis_segs = Segments(2)
yspine_segs = Segments(2) yaxis_segs = Segments(2)
xgrid_segs = Segments(2) xgrid_segs = Segments(2)
ygrid_segs = Segments(2) ygrid_segs = Segments(2)
xborder_segs = Segments(2)
yborder_segs = Segments(2)
if !(xaxis[:ticks] in (nothing, false)) if !(sp[:framestyle] == :none)
f = scalefunc(yaxis[:scale]) # xaxis
invf = invscalefunc(yaxis[:scale]) sp[:framestyle] == :grid || push!(xaxis_segs, (xmin,ymin), (xmax,ymin)) # bottom spine / xaxis
t1 = invf(f(ymin) + 0.015*(f(ymax)-f(ymin))) sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin,ymax), (xmax,ymax)) # top spine
t2 = invf(f(ymax) - 0.015*(f(ymax)-f(ymin))) if !(xaxis[:ticks] in (nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
t1 = invf(f(ymin) + 0.015*(f(ymax)-f(ymin)))
t2 = invf(f(ymax) - 0.015*(f(ymax)-f(ymin)))
push!(xspine_segs, (xmin,ymin), (xmax,ymin)) # bottom spine for xtick in xticks[1]
# push!(xspine_segs, (xmin,ymax), (xmax,ymax)) # top spine push!(xaxis_segs, (xtick, ymin), (xtick, t1)) # bottom tick
for xtick in xticks[1] # sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
push!(xspine_segs, (xtick, ymin), (xtick, t1)) # bottom tick xaxis[:grid] && push!(xgrid_segs, (xtick, t1), (xtick, t2)) # vertical grid
# push!(xspine_segs, (xtick, ymax), (xtick, t2)) # top tick end
xaxis[:grid] && push!(xgrid_segs, (xtick, t1), (xtick, t2)) # vertical grid end
# yaxis
sp[:framestyle] == :grid || push!(yaxis_segs, (xmin,ymin), (xmin,ymax)) # left spine / yaxis
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (xmax,ymin), (xmax,ymax)) # right spine
if !(yaxis[:ticks] in (nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
t1 = invf(f(xmin) + 0.015*(f(xmax)-f(xmin)))
t2 = invf(f(xmax) - 0.015*(f(xmax)-f(xmin)))
for ytick in yticks[1]
push!(yaxis_segs, (xmin, ytick), (t1, ytick)) # left tick
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:grid] && push!(ygrid_segs, (t1, ytick), (t2, ytick)) # horizontal grid
end
end end
end end
if !(yaxis[:ticks] in (nothing, false)) xticks, yticks, xaxis_segs, yaxis_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
t1 = invf(f(xmin) + 0.015*(f(xmax)-f(xmin)))
t2 = invf(f(xmax) - 0.015*(f(xmax)-f(xmin)))
push!(yspine_segs, (xmin,ymin), (xmin,ymax)) # left spine
# push!(yspine_segs, (xmax,ymin), (xmax,ymax)) # right spine
for ytick in yticks[1]
push!(yspine_segs, (xmin, ytick), (t1, ytick)) # left tick
# push!(yspine_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:grid] && push!(ygrid_segs, (t1, ytick), (t2, ytick)) # horizontal grid
end
end
xticks, yticks, xspine_segs, yspine_segs, xgrid_segs, ygrid_segs
end end

View File

@ -39,7 +39,8 @@ const _glvisualize_attr = merge_with_base_supported([
:clims, :clims,
:inset_subplots, :inset_subplots,
:dpi, :dpi,
:hover :hover,
:framestyle,
]) ])
const _glvisualize_seriestype = [ const _glvisualize_seriestype = [
:path, :shape, :path, :shape,
@ -677,7 +678,7 @@ function text_model(font, pivot)
end end
end end
function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, area) function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, area)
xticks, yticks, xspine_segs, yspine_segs, xgrid_segs, ygrid_segs = Plots.axis_drawing_info(sp) xticks, yticks, xspine_segs, yspine_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs = Plots.axis_drawing_info(sp)
xaxis = sp[:xaxis]; yaxis = sp[:yaxis] xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
xgc = Colors.color(Plots.gl_color(xaxis[:foreground_color_grid])) xgc = Colors.color(Plots.gl_color(xaxis[:foreground_color_grid]))
@ -707,7 +708,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
xlim = Plots.axis_limits(xaxis) xlim = Plots.axis_limits(xaxis)
ylim = Plots.axis_limits(yaxis) ylim = Plots.axis_limits(yaxis)
if !(xaxis[:ticks] in (nothing, false, :none)) if !(xaxis[:ticks] in (nothing, false, :none)) && !(sp[:framestyle] == :none)
ticklabels = map(model) do m ticklabels = map(model) do m
mirror = xaxis[:mirror] mirror = xaxis[:mirror]
t, positions, offsets = draw_ticks(xaxis, xticks, true, ylim, m) t, positions, offsets = draw_ticks(xaxis, xticks, true, ylim, m)
@ -727,6 +728,15 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args)) push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args))
end end
xbc = Colors.color(Plots.gl_color(xaxis[:foreground_color_border]))
ybc = Colors.color(Plots.gl_color(yaxis[:foreground_color_border]))
intensity = sp[:framestyle] == :semi ? 0.5f0 : 1.0f0
if sp[:framestyle] in (:box, :semi)
xborder = draw_grid_lines(sp, xborder_segs, intensity, :solid, model, RGBA(xbc, intensity))
yborder = draw_grid_lines(sp, yborder_segs, intensity, :solid, model, RGBA(ybc, intensity))
push!(axis_vis, xborder, yborder)
end
area_w = GeometryTypes.widths(area) area_w = GeometryTypes.widths(area)
if sp[:title] != "" if sp[:title] != ""
tf = sp[:titlefont]; color = gl_color(sp[:foreground_color_title]) tf = sp[:titlefont]; color = gl_color(sp[:foreground_color_title])

View File

@ -32,6 +32,7 @@ const _gr_attr = merge_with_base_supported([
:inset_subplots, :inset_subplots,
:bar_width, :bar_width,
:arrow, :arrow,
:framestyle,
]) ])
const _gr_seriestype = [ const _gr_seriestype = [
:path, :scatter, :path, :scatter,
@ -653,7 +654,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# TODO: can these be generic flags? # TODO: can these be generic flags?
outside_ticks = false outside_ticks = false
cmap = false cmap = false
draw_axes = true draw_axes = sp[:framestyle] != :none
# axes_2d = true # axes_2d = true
for series in series_list(sp) for series in series_list(sp)
st = series[:seriestype] st = series[:seriestype]
@ -755,7 +756,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setwindow(xmin, xmax, ymin, ymax) GR.setwindow(xmin, xmax, ymin, ymax)
end end
xticks, yticks, xspine_segs, yspine_segs, xgrid_segs, ygrid_segs = axis_drawing_info(sp) xticks, yticks, xspine_segs, yspine_segs, xgrid_segs, ygrid_segs, xborder_segs, yborder_segs = axis_drawing_info(sp)
# @show xticks yticks #spine_segs grid_segs # @show xticks yticks #spine_segs grid_segs
# draw the grid lines # draw the grid lines
@ -773,7 +774,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end end
GR.settransparency(1.0) GR.settransparency(1.0)
# spine (border) and tick marks # axis lines
gr_set_line(1, :solid, xaxis[:foreground_color_axis]) gr_set_line(1, :solid, xaxis[:foreground_color_axis])
GR.setclip(0) GR.setclip(0)
gr_polyline(coords(xspine_segs)...) gr_polyline(coords(xspine_segs)...)
@ -782,7 +783,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_polyline(coords(yspine_segs)...) gr_polyline(coords(yspine_segs)...)
GR.setclip(1) GR.setclip(1)
if !(xticks in (nothing, false)) # tick marks
if !(xticks in (:none, nothing, false))
# x labels # x labels
flip, mirror = gr_set_xticks_font(sp) flip, mirror = gr_set_xticks_font(sp)
for (cv, dv) in zip(xticks...) for (cv, dv) in zip(xticks...)
@ -793,7 +795,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end end
end end
if !(yticks in (nothing, false)) if !(yticks in (:none, nothing, false))
# y labels # y labels
flip, mirror = gr_set_yticks_font(sp) flip, mirror = gr_set_yticks_font(sp)
for (cv, dv) in zip(yticks...) for (cv, dv) in zip(yticks...)
@ -803,6 +805,17 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_text(xi + (mirror ? 1 : -1) * 1e-2, yi, string(dv)) gr_text(xi + (mirror ? 1 : -1) * 1e-2, yi, string(dv))
end end
end end
# border
intensity = sp[:framestyle] == :semi ? 0.5 : 1.0
if sp[:framestyle] in (:box, :semi)
gr_set_line(intensity, :solid, xaxis[:foreground_color_border])
GR.settransparency(intensity)
gr_polyline(coords(xborder_segs)...)
gr_set_line(intensity, :solid, yaxis[:foreground_color_border])
GR.settransparency(intensity)
gr_polyline(coords(yborder_segs)...)
end
end end
# end # end

View File

@ -32,6 +32,7 @@ const _pyplot_attr = merge_with_base_supported([
:inset_subplots, :inset_subplots,
:dpi, :dpi,
:colorbar_title, :colorbar_title,
:framestyle,
]) ])
const _pyplot_seriestype = [ const _pyplot_seriestype = [
:path, :steppre, :steppost, :shape, :path, :steppre, :steppost, :shape,
@ -1053,7 +1054,8 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
end end
py_set_scale(ax, axis) py_set_scale(ax, axis)
py_set_lims(ax, axis) py_set_lims(ax, axis)
py_set_ticks(ax, get_ticks(axis), letter) ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
py_set_ticks(ax, ticks, letter)
ax[Symbol("set_", letter, "label")](axis[:guide]) ax[Symbol("set_", letter, "label")](axis[:guide])
if get(axis.d, :flip, false) if get(axis.d, :flip, false)
ax[Symbol("invert_", letter, "axis")]() ax[Symbol("invert_", letter, "axis")]()
@ -1065,7 +1067,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
lab[:set_family](axis[:tickfont].family) lab[:set_family](axis[:tickfont].family)
lab[:set_rotation](axis[:rotation]) lab[:set_rotation](axis[:rotation])
end end
if axis[:grid] if axis[:grid] && !(ticks in (:none, nothing, false))
fgcolor = py_color(axis[:foreground_color_grid]) fgcolor = py_color(axis[:foreground_color_grid])
pyaxis[:grid](true, pyaxis[:grid](true,
color = fgcolor, color = fgcolor,
@ -1088,6 +1090,24 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# this sets the bg color inside the grid # this sets the bg color inside the grid
ax[set_facecolor_sym](py_color(sp[:background_color_inside])) ax[set_facecolor_sym](py_color(sp[:background_color_inside]))
# framestyle
if !ispolar(sp) && !is3d(sp)
if sp[:framestyle] == :semi
intensity = 0.5
ax[:spines]["right"][:set_alpha](intensity)
ax[:spines]["top"][:set_alpha](intensity)
ax[:spines]["right"][:set_linewidth](intensity)
ax[:spines]["top"][:set_linewidth](intensity)
elseif sp[:framestyle] == :axes
ax[:spines]["right"][:set_visible](false)
ax[:spines]["top"][:set_visible](false)
elseif sp[:framestyle] in (:grid, :none)
for (loc, spine) in ax[:spines]
spine[:set_visible](false)
end
end
end
end end
py_drawfig(fig) py_drawfig(fig)
end end

View File

@ -155,7 +155,7 @@ PlotExample("Subplots",
""", """,
[:(begin [:(begin
l = @layout([a{0.1h}; b [c;d e]]) l = @layout([a{0.1h}; b [c;d e]])
plot(randn(100,5), layout=l, t=[:line :histogram :scatter :steppre :bar], leg=false, ticks=nothing, border=false) plot(randn(100,5), layout=l, t=[:line :histogram :scatter :steppre :bar], leg=false, ticks=nothing, border=:none)
end)] end)]
), ),
@ -330,7 +330,7 @@ PlotExample("Spy",
), ),
PlotExample("Magic grid argument", PlotExample("Magic grid argument",
"The grid lines can be modified individually for each axis with the magic grid argument.", "The grid lines can be modified individually for each axis with the magic `grid` argument.",
[:(begin [:(begin
x = rand(10) x = rand(10)
p1 = plot(x, title = "Default looks") p1 = plot(x, title = "Default looks")
@ -341,6 +341,14 @@ PlotExample("Magic grid argument",
end)] end)]
), ),
PlotExample("Framestyle",
"The style of the frame/axes of a (sub)plot can be changed with the `framestyle` attribute. The default framestyle is `:axes`.",
[:(begin
histogram(fill(randn(1000), 5), framestyle = [:box :semi :axes :grid :none],
title = [":box" ":semi" ":axes" ":grid" ":none"], color = RowVector(1:5), layout = 5, label = "")
end)]
),
] ]
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------