From 36ca485a746bce10f874f58aeac295a4e21092d4 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Mon, 25 Apr 2016 16:57:16 -0400 Subject: [PATCH] added fg_guide coloring; allow markers for bar/sticks and sticks fixes; legend text color --- src/args.jl | 50 +++++++---- src/backends/pyplot.jl | 200 ++++++++++++++++++++++++++++++----------- src/colors.jl | 2 +- 3 files changed, 180 insertions(+), 72 deletions(-) diff --git a/src/args.jl b/src/args.jl index f6278ea4..ca84ac53 100644 --- a/src/args.jl +++ b/src/args.jl @@ -167,8 +167,9 @@ _plotDefaults[:foreground_color] = :auto # default for al _plotDefaults[:foreground_color_legend] = :match # foreground of legend _plotDefaults[:foreground_color_grid] = :match # grid color _plotDefaults[:foreground_color_axis] = :match # axis border/tick colors -_plotDefaults[:foreground_color_text] = :match # tick/guide text color _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 _plotDefaults[:xlims] = :auto _plotDefaults[:ylims] = :auto _plotDefaults[:zlims] = :auto @@ -269,10 +270,12 @@ add_aliases(:foreground_color_grid, :fg_grid, :fggrid, :fgcolor_grid, :fg_color_ :foreground_colour_grid, :fgcolour_grid, :fg_colour_grid, :gridcolor) add_aliases(:foreground_color_axis, :fg_axis, :fgaxis, :fgcolor_axis, :fg_color_axis, :foreground_axis, :foreground_colour_axis, :fgcolour_axis, :fg_colour_axis, :axiscolor) -add_aliases(:foreground_color_text, :fg_text, :fgtext, :fgcolor_text, :fg_color_text, :foreground_text, - :foreground_colour_text, :fgcolour_text, :fg_colour_text, :textcolor) 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) +add_aliases(:foreground_color_text, :fg_text, :fgtext, :fgcolor_text, :fg_color_text, :foreground_text, + :foreground_colour_text, :fgcolour_text, :fg_colour_text, :textcolor) +add_aliases(:foreground_color_guide, :fg_guide, :fgguide, :fgcolor_guide, :fg_color_guide, :foreground_guide, + :foreground_colour_guide, :fgcolour_guide, :fg_colour_guide, :guidecolor) # alphas add_aliases(:seriesalpha, :alpha, :α, :opacity) @@ -388,19 +391,21 @@ const _themes = KW( :fgaxis => :match, :fgtext => :match, :fgborder => :match, + :fgguide => :match, ), - :ggplot2 => KW( - :bg => :white, - :bglegend => _invisible, - :bginside => :lightgray, - :bgoutside => :match, - :fg => :white, - :fglegend => _invisible, - :fggrid => :match, - :fgaxis => :match, - :fgtext => :gray, - :fgborder => :match, - ), + # :ggplot2 => KW( + # :bg => :white, + # :bglegend => _invisible, + # :bginside => :lightgray, + # :bgoutside => :match, + # :fg => :white, + # :fglegend => _invisible, + # :fggrid => :match, + # :fgaxis => :match, + # :fgtext => :gray, + # :fgborder => :match, + # :fgguide => :black, + # ), ) function add_theme(sym::Symbol, theme::KW) @@ -419,7 +424,8 @@ function add_theme(sym::Symbol; fggrid = _themes[base][:fggrid], fgaxis = _themes[base][:fgaxis], fgtext = _themes[base][:fgtext], - fgborder = _themes[base][:fgborder]) + fgborder = _themes[base][:fgborder], + fgguide = _themes[base][:fgguide]) _themes[sym] = KW( :bg => bg, :bglegend => bglegend, @@ -431,9 +437,19 @@ function add_theme(sym::Symbol; :fgaxis => fgaxis, :fgtext => fgtext, :fgborder => fgborder, + :fgguide => fgguide, ) end +add_theme(:ggplot2, + bglegend = _invisible, + bginside = :lightgray, + fg = :white, + fglegend = _invisible, + fgtext = :gray, + fgguide = :black +) + function set_theme(sym::Symbol) default(; _themes[sym]...) end @@ -805,7 +821,7 @@ function getPlotArgs(pkg::AbstractBackend, kw, idx::Int; set_defaults = true) end function has_black_border_for_default(lt::Symbol) - like_histogram(lt) || lt == :hexbin + like_histogram(lt) || lt in (:hexbin, :bar) end # build the argument dictionary for a series diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 7760937c..b743245e 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -9,6 +9,7 @@ function _initialize_backend(::PyPlotBackend) const pypath = PyPlot.pywrap(PyPlot.pyimport("matplotlib.path")) const mplot3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d")) const pypatches = PyPlot.pywrap(PyPlot.pyimport("matplotlib.patches")) + const pyfont = PyPlot.pywrap(PyPlot.pyimport("matplotlib.font_manager")) # const pycolorbar = PyPlot.pywrap(PyPlot.pyimport("matplotlib.colorbar")) end @@ -129,6 +130,14 @@ function getPyPlotStepStyle(linetype::Symbol) return "default" end +# untested... return a FontProperties object from a Plots.Font +function getPyPlotFont(font::Font) + pyfont.pymember("FontProperties")( + family = font.family, + size = font.size + ) +end + # --------------------------------------------------------------------------- type PyPlotAxisWrapper @@ -166,34 +175,34 @@ getLeftAxis(plt::Plot{PyPlotBackend}) = getLeftAxis(plt.o) getRightAxis(plt::Plot{PyPlotBackend}) = getRightAxis(plt.o) getAxis(plt::Plot{PyPlotBackend}, axis::Symbol) = (axis == :right ? getRightAxis : getLeftAxis)(plt) -# left axis is PyPlot., right axis is "f.axes[0].twinx()." -function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol) - # # need to access mplot3d functions differently - # if linetype == :surface - # return mplot3d.pymember("Axes3D")[:plot_surface] - # end - - # in the 2-axis case we need to get: [:] - ax = getAxis(plt, axis) - # ax[:set_ylabel](plt.plotargs[:yrightlabel]) - fmap = KW( - :hist => :hist, - :density => :hist, - :sticks => :bar, - :bar => :bar, - :hist2d => :hexbin, - :hexbin => :hexbin, - :scatter => :scatter, - :contour => :contour, - :scatter3d => :scatter, - :surface => :plot_surface, - :wireframe => :plot_wireframe, - :heatmap => :pcolor, - :shape => :add_patch, - # :surface => pycolors.pymember("LinearSegmentedColormap")[:from_list] - ) - return ax[get(fmap, linetype, :plot)] -end +# # left axis is PyPlot., right axis is "f.axes[0].twinx()." +# function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol) +# # # need to access mplot3d functions differently +# # if linetype == :surface +# # return mplot3d.pymember("Axes3D")[:plot_surface] +# # end +# +# # in the 2-axis case we need to get: [:] +# ax = getAxis(plt, axis) +# # ax[:set_ylabel](plt.plotargs[:yrightlabel]) +# fmap = KW( +# :hist => :hist, +# :density => :hist, +# :sticks => :bar, +# :bar => :bar, +# :hist2d => :hexbin, +# :hexbin => :hexbin, +# :scatter => :scatter, +# :contour => :contour, +# :scatter3d => :scatter, +# :surface => :plot_surface, +# :wireframe => :plot_wireframe, +# :heatmap => :pcolor, +# :shape => :add_patch, +# # :surface => pycolors.pymember("LinearSegmentedColormap")[:from_list] +# ) +# return ax[get(fmap, linetype, :plot)] +# end function handleSmooth(plt::Plot{PyPlotBackend}, ax, d::KW, smooth::Bool) @@ -361,6 +370,7 @@ function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW) ax = getAxis(plt, d[:axis]) x, y, z = d[:x], d[:y], d[:z] + xyargs = (lt in _3dTypes ? (x,y,z) : (x,y)) # handle zcolor and get c/cmap extrakw = KW() @@ -371,8 +381,6 @@ function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW) # path/line/scatter should all do UP TO 2 series... a line, and a scatter if lt in (:path, :line, :scatter, :path3d, :scatter3d, :steppre, :steppost) - xyargs = (lt in _3dTypes ? (x,y,z) : (x,y)) - # line plot (path, line, steppre, steppost, path3d) if d[:linewidth] > 0 handle = ax[:plot](xyargs...; @@ -386,30 +394,30 @@ function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW) push!(handles, handle) end - # scatter plot (scatter, scatter3d, and line plots that have markers) - if d[:markershape] != :none - if d[:marker_z] == nothing - extrakw[:c] = color_fix(pymarkercolor(d), x) - else - extrakw[:c] = convert(Vector{Float64}, d[:marker_z]) - extrakw[:cmap] = pymarkercolormap(d) - needs_colorbar = true - end - handle = ax[:scatter](xyargs...; - label = d[:label], - zorder = plt.n + 0.5, - marker = getPyPlotMarker(d[:markershape]), - s = d[:markersize] .^ 2, - edgecolors = pymarkerstrokecolor(d), - linewidths = d[:markerstrokewidth], - extrakw... - ) - push!(handles, handle) - end + # # scatter plot (scatter, scatter3d, and line plots that have markers) + # if d[:markershape] != :none + # if d[:marker_z] == nothing + # extrakw[:c] = color_fix(pymarkercolor(d), x) + # else + # extrakw[:c] = convert(Vector{Float64}, d[:marker_z]) + # extrakw[:cmap] = pymarkercolormap(d) + # needs_colorbar = true + # end + # handle = ax[:scatter](xyargs...; + # label = d[:label], + # zorder = plt.n + 0.5, + # marker = getPyPlotMarker(d[:markershape]), + # s = d[:markersize] .^ 2, + # edgecolors = pymarkerstrokecolor(d), + # linewidths = d[:markerstrokewidth], + # extrakw... + # ) + # push!(handles, handle) + # end end - if lt in (:bar, :sticks) - extrakw[isvertical(d) ? :width : :height] = (lt == :sticks ? 0.1 : 0.9) + if lt == :bar + extrakw[isvertical(d) ? :width : :height] = 0.9 handle = ax[isvertical(d) ? :bar : :barh](x, y; label = d[:label], zorder = plt.n, @@ -422,6 +430,84 @@ function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW) push!(handles, handle) end + if lt == :sticks + extrakw[isvertical(d) ? :width : :height] = 0.0 + handle = ax[isvertical(d) ? :bar : :barh](x, y; + label = d[:label], + zorder = plt.n, + color = pylinecolor(d), + edgecolor = pylinecolor(d), + linewidth = d[:linewidth], + align = "center", + extrakw... + )[1] + push!(handles, handle) + end + + # if lt in (:bar, :sticks) + # extrakw[isvertical(d) ? :width : :height] = (lt == :sticks ? 0.0 : 0.9) + # handle = ax[isvertical(d) ? :bar : :barh](x, y; + # label = d[:label], + # zorder = plt.n, + # color = pyfillcolor(d), + # edgecolor = lt == :sticks ? py pylinecolor(d), + # linewidth = d[:linewidth], + # align = "center", + # extrakw... + # )[1] + # push!(handles, handle) + # + # # if d[:markershape] != :none + # # extrakw = KW() + # # if d[:marker_z] == nothing + # # extrakw[:c] = color_fix(pymarkercolor(d), x) + # # else + # # extrakw[:c] = convert(Vector{Float64}, d[:marker_z]) + # # extrakw[:cmap] = pymarkercolormap(d) + # # needs_colorbar = true + # # end + # # handle = ax[:scatter](x, y; + # # label = d[:label], + # # zorder = plt.n + 0.5, + # # marker = getPyPlotMarker(d[:markershape]), + # # s = d[:markersize] .^ 2, + # # edgecolors = pymarkerstrokecolor(d), + # # linewidths = d[:markerstrokewidth], + # # extrakw... + # # ) + # # push!(handles, handle) + # # end + # end + + # add markers? + if d[:markershape] != :none && lt in (:path, :line, :scatter, :path3d, + :scatter3d, :steppre, :steppost, + :bar, :sticks) + extrakw = KW() + if d[:marker_z] == nothing + extrakw[:c] = color_fix(pymarkercolor(d), x) + else + extrakw[:c] = convert(Vector{Float64}, d[:marker_z]) + extrakw[:cmap] = pymarkercolormap(d) + needs_colorbar = true + end + xyargs = if lt in (:bar, :sticks) && !isvertical(d) + (y, x) + else + xyargs + end + handle = ax[:scatter](xyargs...; + label = d[:label], + zorder = plt.n + 0.5, + marker = getPyPlotMarker(d[:markershape]), + s = d[:markersize] .^ 2, + edgecolors = pymarkerstrokecolor(d), + linewidths = d[:markerstrokewidth], + extrakw... + ) + push!(handles, handle) + end + if lt == :hist handle = ax[:hist](y; label = d[:label], @@ -926,7 +1012,8 @@ end function updateAxisColors(ax, d::KW) - guidecolor = getPyPlotColor(d[:guidefont].color) + # guidecolor = getPyPlotColor(d[:guidefont].color) + guidecolor = getPyPlotColor(d[:foreground_color_guide]) for (loc, spine) in ax[:spines] spine[:set_color](getPyPlotColor(d[:foreground_color_border])) end @@ -1117,10 +1204,15 @@ function addPyPlotLegend(plt::Plot, ax) ) leg[:set_zorder](1000) + fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_legend]) + for txt in leg[:get_texts]() + PyPlot.plt[:setp](txt, color = fgcolor) + end + # set some legend properties frame = leg[:get_frame]() frame[:set_facecolor](getPyPlotColor(plt.plotargs[:background_color_legend])) - frame[:set_edgecolor](getPyPlotColor(plt.plotargs[:foreground_color_legend])) + frame[:set_edgecolor](fgcolor) end end end diff --git a/src/colors.jl b/src/colors.jl index 4acceafb..3ab085fa 100644 --- a/src/colors.jl +++ b/src/colors.jl @@ -398,7 +398,7 @@ function handlePlotColors(::AbstractBackend, d::KW) end # update sub-foreground colors - for fgtype in ("legend", "grid", "axis", "text", "border") + for fgtype in ("legend", "grid", "axis", "text", "border", "guide") fgsym = symbol("foreground_color_" * fgtype) if d[fgsym] == :match d[fgsym] = d[:foreground_color]