diff --git a/src/args.jl b/src/args.jl index 883ccd75..0526df77 100644 --- a/src/args.jl +++ b/src/args.jl @@ -113,10 +113,12 @@ const _seriesDefaults = KW() # series-specific _seriesDefaults[:axis] = :left _seriesDefaults[:label] = "AUTO" +_seriesDefaults[:seriescolor] = :auto +_seriesDefaults[:seriesalpha] = nothing _seriesDefaults[:linetype] = :path _seriesDefaults[:linestyle] = :solid _seriesDefaults[:linewidth] = 1 -_seriesDefaults[:linecolor] = :auto +_seriesDefaults[:linecolor] = :match _seriesDefaults[:linealpha] = nothing # _seriesDefaults[:linestroke] = Stroke(1, :auto, nothing, :solid) # linewidth, linecolor, linealpha, linestyle # _seriesDefaults[:fillbrush] = Brush(nothing, :match, nothing) # fillrange, fillcolor, fillalpha @@ -142,7 +144,7 @@ _seriesDefaults[:group] = nothing # groupby vector _seriesDefaults[:x] = nothing _seriesDefaults[:y] = nothing _seriesDefaults[:z] = nothing # depth for contour, surface, etc -_seriesDefaults[:zcolor] = nothing # value for color scale +_seriesDefaults[:marker_z] = nothing # value for color scale # _seriesDefaults[:surface] = nothing # _seriesDefaults[:nlevels] = 15 _seriesDefaults[:levels] = 15 @@ -235,9 +237,15 @@ end # Alternate args @compat const _keyAliases = KW( - :c => :linecolor, - :color => :linecolor, - :colour => :linecolor, + :c => :seriescolor, + :color => :seriescolor, + :colour => :seriescolor, + :alpha => :seriesalpha, + :α => :seriesalpha, + :opacity => :seriesalpha, + :lc => :linecolor, + :lcolor => :linecolor, + :lcolour => :linecolor, :lab => :label, :l => :line, :w => :linewidth, @@ -261,9 +269,10 @@ end :ms => :markersize, :msize => :markersize, :ma => :markeralpha, - :alpha => :markeralpha, - :opacity => :markeralpha, + :malpha => :markeralpha, + :mopacity => :markeralpha, :markeropacity => :markeralpha, + :zcolor => :marker_z, :f => :fill, :area => :fill, :fillrng => :fillrange, @@ -394,6 +403,7 @@ end # ----------------------------------------------------------------------------- +# if arg is a valid color value, then set d[csym] and return true function handleColors!(d::KW, arg, csym::Symbol) try if arg == :auto @@ -782,11 +792,16 @@ function getSeriesArgs(pkg::AbstractBackend, plotargs::KW, kw, commandIndex::Int aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex) # update color - d[:linecolor] = getSeriesRGBColor(d[:linecolor], plotargs, plotIndex) + d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], plotargs, plotIndex) + + # update linecolor + c = d[:linecolor] + c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex)) + d[:linecolor] = c # update markercolor c = d[:markercolor] - c = (c == :match ? d[:linecolor] : getSeriesRGBColor(c, plotargs, plotIndex)) + c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex)) d[:markercolor] = c # update markerstrokecolor @@ -796,7 +811,7 @@ function getSeriesArgs(pkg::AbstractBackend, plotargs::KW, kw, commandIndex::Int # update fillcolor c = d[:fillcolor] - c = (c == :match ? d[:linecolor] : getSeriesRGBColor(c, plotargs, plotIndex)) + c = (c == :match ? d[:seriescolor] : getSeriesRGBColor(c, plotargs, plotIndex)) d[:fillcolor] = c # set label diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index 4028c86d..a1bbc5b5 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -190,7 +190,7 @@ function addGadflyMarker!(plt::Plot, numlayers::Int, d::KW, plotargs::KW, geoms. kwargs = KW() # handle continuous color scales for the markers - zcolor = d[:zcolor] + zcolor = d[:marker_z] if zcolor != nothing && typeof(zcolor) <: AVec kwargs[:color] = zcolor addGadflyContColorScale(plt, d[:markercolor]) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 5150fe3a..921cb84a 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -381,13 +381,13 @@ function plotly_series(d::KW, plotargs::KW; plot_index = nothing) ) # gotta hack this (for now?) since plotly can't handle rgba values inside the gradient - if d[:zcolor] != nothing - # d_out[:marker][:color] = d[:zcolor] + if d[:marker_z] != nothing + # d_out[:marker][:color] = d[:marker_z] # d_out[:marker][:colorscale] = plotly_colorscale(d[:markercolor], d[:markeralpha]) # d_out[:showscale] = true grad = ColorGradient(d[:markercolor], alpha=d[:markeralpha]) - zmin, zmax = extrema(d[:zcolor]) - d_out[:marker][:color] = [webcolor(getColorZ(grad, (zi - zmin) / (zmax - zmin))) for zi in d[:zcolor]] + zmin, zmax = extrema(d[:marker_z]) + d_out[:marker][:color] = [webcolor(getColorZ(grad, (zi - zmin) / (zmax - zmin))) for zi in d[:marker_z]] end end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 1b0f811b..1b937eff 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -282,6 +282,149 @@ end # --------------------------------------------------------------------------- +function fix_xy_lengths!(plt::Plot{PyPlotBackend}, d::KW) + x, y = d[:x], d[:y] + nx, ny = length(x), length(y) + if !isa(get(d, :z, nothing), Surface) && nx != ny + if nx < ny + d[:x] = Float64[x[mod1(i,nx)] for i=1:ny] + else + d[:y] = Float64[y[mod1(i,ny)] for i=1:nx] + end + end +end + +# figure out the extra kw from zcolor in scatter and scatter3d +function get_extra_kw(plt::Plot{PyPlotBackend}, d::KW) + extra_kw = KW() + if d[:linetype] in (:scatter, :scatter3d) + c = getPyPlotColor(d[:markercolor]) + if d[:marker_z] == nothing + c = getPyPlotColor(c, d[:markeralpha]) + + # total hack due to PyPlot bug (see issue #145). + # hack: duplicate the color vector when the total rgba fields is the same as the series length + if (typeof(c) <: AbstractArray && length(c)*4 == length(x)) || (typeof(c) <: Tuple && length(x) == 4) + c = vcat(c, c) + end + extra_kw[:c] = c + else + if !isa(c, ColorGradient) + c = default_gradient() + end + extra_kw[:c] = convert(Vector{Float64}, d[:marker_z]) + extra_kw[:cmap] = getPyPlotColorMap(c, d[:markeralpha]) + end + end + extra_kw +end + +function get_cmap(plt::Plot{PyPlotBackend}, d::KW) + +end + + +function _add_series2(pkg::PyPlotBackend, plt::Plot, d::KW) + lt = d[:linetype] + if !(lt in supportedTypes(pkg)) + error("linetype $(lt) is unsupported in PyPlot. Choose from: $(supportedTypes(pkg))") + end + + # 3D plots have a different underlying Axes object in PyPlot + if lt in _3dTypes && isempty(plt.o.kwargs) + push!(plt.o.kwargs, (:projection, "3d")) + end + + # PyPlot doesn't handle mismatched x/y + fix_xy_lengths!(plt, d) + + ax = getAxis(plt, d[:axis]) + linecolor = getPyPlotColor(d[:linecolor], d[:linealpha]) + markercolor = if d[:marker_z] == nothing + getPyPlotColor(d[:markercolor], d[:markeralpha]) + else + getPyPlotColorMap(d[:markercolor], d[:markeralpha]) + end + fillcolor = getPyPlotColor(d[:fillcolor], d[:fillalpha]) + strokecolor = getPyPlotColor(d[:markerstrokecolor], d[:markerstrokealpha]) + # linecmap = getPyPlotColorMap(d[:linecolor], d[:linealpha]) + # fillcmap = getPyPlotColorMap(d[:fillcolor], d[:fillalpha]) + linestyle = getPyPlotLineStyle(lt, d[:linestyle]) + markershape = getPyPlotMarker(d[:markershape]) + x, y, z = d[:x], d[:y], d[:z] + + cmap = get_cmap(plt, d) + + # handle zcolor and get c/cmap + extra_kw = get_extra_kw(plt, d) + + # :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, + # + # do the plotting + if lt in (:path, :line) + ax[:plot](x, y; + color = linecolor, + linewidth = linewidth, + linestyle = linestyle, + drawstyle = getPyPlotStepStyle(lt), + marker = markershape, + markersize = d[:markersize], + markerfacecolor = markercolor, + markeredgecolor = strokecolor, + markeredgewidth = d[:markerstrokewidth], + label = d[:label], + zorder = plt.n + ) + elseif lt == :scatter + ax[:plot](x, y; + linewidth = 0, + marker = markershape, + markersize = d[:markersize], + markerfacecolor = markercolor, + markeredgecolor = strokecolor, + markeredgewidth = d[:markerstrokewidth], + label = d[:label], + zorder = plt.n, + extra_kw... + ) + end + + # smoothing + handleSmooth(plt, ax, d, d[:smooth]) + + # add the colorbar legend + if plt.plotargs[:colorbar] != :none && haskey(extra_kw, :cmap) + PyPlot.colorbar(d[:serieshandle], ax=ax) + end + + # this sets the bg color inside the grid + ax[:set_axis_bgcolor](getPyPlotColor(plt.plotargs[:background_color])) + + # handle area filling + fillrange = d[:fillrange] + if fillrange != nothing && lt != :contour + if typeof(fillrange) <: @compat(Union{Real, AVec}) + ax[:fill_between](d[:x], fillrange, d[:y], facecolor = fillcolor, zorder = plt.n) + else + ax[:fill_between](d[:x], fillrange..., facecolor = fillcolor, zorder = plt.n) + end + end + + push!(plt.seriesargs, d) + plt +end function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW) # 3D plots have a different underlying Axes object in PyPlot @@ -384,11 +527,11 @@ function _add_series(pkg::PyPlotBackend, plt::Plot, d::KW) if lt in (:scatter, :scatter3d) extra_kwargs[:s] = d[:markersize].^2 c = d[:markercolor] - if d[:zcolor] != nothing + if d[:marker_z] != nothing if !isa(c, ColorGradient) c = default_gradient() end - extra_kwargs[:c] = convert(Vector{Float64}, d[:zcolor]) + extra_kwargs[:c] = convert(Vector{Float64}, d[:marker_z]) extra_kwargs[:cmap] = getPyPlotColorMap(c, d[:markeralpha]) else ppc = getPyPlotColor(c, d[:markeralpha]) diff --git a/src/series_args.jl b/src/series_args.jl index 681de946..1f9fd871 100644 --- a/src/series_args.jl +++ b/src/series_args.jl @@ -144,8 +144,8 @@ function build_series_args(plt::AbstractPlot, kw::KW) #, idxfilter) end # map functions to vectors - if isa(d[:zcolor], Function) - d[:zcolor] = map(d[:zcolor], d[:x]) + if isa(d[:marker_z], Function) + d[:marker_z] = map(d[:marker_z], d[:x]) end if isa(d[:fillrange], Function) d[:fillrange] = map(d[:fillrange], d[:x])