From 455f85e2302c5562e65fe87230342e8a52608c42 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 18 Sep 2015 16:53:43 -0400 Subject: [PATCH] working on colors, args --- src/args.jl | 89 ++++++++++++++++++++++++++++++++++++++++---------- src/plot.jl | 43 ++++++++++++++---------- src/subplot.jl | 17 ++++++++-- 3 files changed, 111 insertions(+), 38 deletions(-) diff --git a/src/args.jl b/src/args.jl index 8ead5bec..23d4fe8b 100644 --- a/src/args.jl +++ b/src/args.jl @@ -3,7 +3,7 @@ # const COLORS = [:black, :blue, :green, :red, :darkGray, :darkCyan, :darkYellow, :darkMagenta, # :darkBlue, :darkGreen, :darkRed, :gray, :cyan, :yellow, :magenta] -const COLORS = distinguishable_colors(20) +# const COLORS = distinguishable_colors(20) const AXES = [:left, :right] const TYPES = [:line, :step, @@ -185,23 +185,76 @@ end # ----------------------------------------------------------------------------- +convertColor(c::Union{AbstractString, Symbol}) = parse(Colorant, string(c)) +convertColor(c::Colorant) = c +convertColor(cvec::AbstractVector) = map(convertColor, cvec) + +# for now, choose a boundary value on the other side from the background value +function adjustAway(bgval, vmin=0., vmax=100.) + bgval < 0.5 * (vmax+vmin) ? vmax : vmin +end + +function getBackgroundRGBColor(c, d::Dict) + bgcolor = convertColor(d[:background_color]) + d[:background_color] = bgcolor + # d[:color_palette] = RGB{Float64}[bgcolor] + palette = distinguishable_colors(20, bgcolor)[2:end] + @show palette + + # try to adjust colors away from background color + # for now, lets do this by moving both lightness and chroma to to other side of the spectrum as compared to the background + bg_lab = Lab(bgcolor) + palette = RGB{Float64}[begin + lab = Lab(rgb) + Lab( + adjustAway(bg_lab.l, -128, 128), + # adjustAway(bg_lab.a, -128, 128), + lab.a, + lab.b + ) + end for rgb in palette] + + d[:color_palette] = palette + @show d[:color_palette] + bgcolor +end # converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically -# note: if plt is nothing, we aren't doing anything with the color anyways -function getRGBColor(c, n::Int = 0) +function getSeriesRGBColor(c, d::Dict, n::Int) - # auto-assign a color based on plot index - if c == :auto && n > 0 - c = autopick(COLORS, n) - end + # # create a color palette on the fly using the background color as the seed + # if !haskey(d, :color_palette) + # c = convertColor(d[:background_color]) + # d[:background_color] = c + # d[:color_palette] = cp = RGB[c] + # else - # convert it from a symbol/string - if isa(c, Symbol) - c = string(c) - end - if isa(c, AbstractString) - c = parse(Colorant, c) - end + # cp = d[:color_palette] + # @show n cp + # if length(cp) < n+1 + # cp = distinguishable_colors(n+1, cp) + # @show cp + # d[:color_palette] = cp + # end + + c = (c == :auto ? autopick(d[:color_palette], n) : convertColor(c)) + + # if c == :auto + # # pick a new color + # cp = d[:color_palette] + # if length(cp) < n+1 + # cp = distinguishable_colors(n+1, cp) + # end + # c = cp[n+1] + # d[:color_palette] = cp + # end + # @show d[:color_palette] + # @show c length(cp) + + # # just to be safe + # c = convertColor(c) + # # push!(d[:color_palette], c) + # # @show c d[:color_palette] # should be a RGB now... either it was passed in, generated automatically, or created from a string @assert isa(c, RGB) @@ -237,7 +290,7 @@ function getPlotArgs(pkg::PlottingPackage, kw, idx::Int) end # convert color - d[:background_color] = getRGBColor(d[:background_color]) + d[:background_color] = getBackgroundRGBColor(d[:background_color], d) # no need for these delete!(d, :x) @@ -249,7 +302,7 @@ end # note: idx is the index of this series within this call, n is the index of the series from all calls to plot/subplot -function getSeriesArgs(pkg::PlottingPackage, kw, idx::Int, n::Int) +function getSeriesArgs(pkg::PlottingPackage, initargs::Dict, kw, idx::Int, n::Int) # TODO, pass in initargs, not plt d = Dict(kw) # add defaults? @@ -277,11 +330,11 @@ function getSeriesArgs(pkg::PlottingPackage, kw, idx::Int, n::Int) end # update color - d[:color] = getRGBColor(d[:color], n) + d[:color] = getSeriesRGBColor(d[:color], initargs, n) # update markercolor mc = d[:markercolor] - mc = (mc == :match ? d[:color] : getRGBColor(mc, n)) + mc = (mc == :match ? d[:color] : getSeriesRGBColor(mc, initargs, n)) d[:markercolor] = mc # set label diff --git a/src/plot.jl b/src/plot.jl index 9f24f1d6..0bc8311f 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -22,6 +22,7 @@ Base.print(io::IO, plt::Plot) = print(io, string(plt)) Base.show(io::IO, plt::Plot) = print(io, string(plt)) getplot(plt::Plot) = plt +getinitargs(plt::Plot, idx::Int = 1) = plt.initargs doc""" @@ -90,7 +91,15 @@ function plot(args...; kw...) pkg = plotter() d = Dict(kw) replaceAliases!(d) + + # # ensure we're passing in an RGB + # if haskey(d, :background_color) + # d[:background_color] = convertColor(d[:background_color]) + # end + plt = plot(pkg; getPlotArgs(pkg, d, 1)...) # create a new, blank plot + + delete!(d, :background_color) plot!(plt, args...; d...) # add to it end @@ -158,7 +167,7 @@ function createKWargsList(plt::PlottingObject; kw...) if !haskey(d, :x) d[:x] = 1:length(d[:y]) end - [getSeriesArgs(plt.plotter, d, 1, plt.n + 1)] + [getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), d, 1, plt.n + 1)] end @@ -169,7 +178,7 @@ end # create one series where y is vectors of numbers function createKWargsList{T<:Real}(plt::PlottingObject, y::AVec{T}; kw...) - d = getSeriesArgs(plt.plotter, kw, 1, plt.n + 1) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, 1, plt.n + 1) d[:x] = 1:length(y) d[:y] = y [d] @@ -178,7 +187,7 @@ end # create one series where x/y are vectors of numbers function createKWargsList{T<:Real,S<:Real}(plt::PlottingObject, x::AVec{T}, y::AVec{S}; kw...) @assert length(x) == length(y) - d = getSeriesArgs(plt.plotter, kw, 1, plt.n + 1) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, 1, plt.n + 1) d[:x] = x d[:y] = y [d] @@ -189,7 +198,7 @@ function createKWargsList{T<:Real}(plt::PlottingObject, y::AMat{T}; kw...) n,m = size(y) ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = 1:n d[:y] = y[:,i] push!(ret, d) @@ -203,7 +212,7 @@ function createKWargsList{T<:Real,S<:Real}(plt::PlottingObject, x::AVec{T}, y::A @assert length(x) == n ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = x d[:y] = y[:,i] push!(ret, d) @@ -217,7 +226,7 @@ function createKWargsList{T<:Real,S<:Real}(plt::PlottingObject, x::AMat{T}, y::A n,m = size(y) ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = x[:,i] d[:y] = y[:,i] push!(ret, d) @@ -232,7 +241,7 @@ end # create 1 series, y = f(x), x ∈ [xmin, xmax] function createKWargsList(plt::PlottingObject, f::Function, xmin::Real, xmax::Real; kw...) - d = getSeriesArgs(plt.plotter, kw, 1, plt.n + 1) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, 1, plt.n + 1) width = plt.initargs[:size][1] d[:x] = collect(linspace(xmin, xmax, width)) # we don't need more than the width d[:y] = map(f, d[:x]) @@ -246,7 +255,7 @@ function createKWargsList(plt::PlottingObject, fs::Vector{Function}, xmin::Real, width = plt.initargs[:size][1] x = collect(linspace(xmin, xmax, width)) # we don't need more than the width for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = x d[:y] = map(fs[i], x) push!(ret, d) @@ -256,7 +265,7 @@ end # create 1 series, x = fx(u), y = fy(u); u ∈ [umin, umax] function createKWargsList(plt::PlottingObject, fx::Function, fy::Function, umin::Real, umax::Real; kw...) - d = getSeriesArgs(plt.plotter, kw, 1, plt.n + 1) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, 1, plt.n + 1) width = plt.initargs[:size][1] u = collect(linspace(umin, umax, width)) # we don't need more than the width d[:x] = map(fx, u) @@ -266,7 +275,7 @@ end # create 1 series, y = f(x) function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec{T}, f::Function; kw...) - d = getSeriesArgs(plt.plotter, kw, 1, plt.n + 1) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, 1, plt.n + 1) d[:x] = x d[:y] = map(f, x) [d] @@ -278,7 +287,7 @@ function createKWargsList{T<:Real}(plt::PlottingObject, x::AMat{T}, f::Function; n,m = size(x) ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = x[:,i] d[:y] = map(f, d[:x]) push!(ret, d) @@ -298,7 +307,7 @@ function createKWargsList(plt::PlottingObject, y::AVec; kw...) m = length(y) ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = 1:length(y[i]) d[:y] = y[i] push!(ret, d) @@ -318,7 +327,7 @@ function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec{T}, y::AVec; kw. m = length(y) ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = x d[:y] = getyvec(x, y[i]) push!(ret, d) @@ -332,7 +341,7 @@ function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec, y::AMat{T}; kw. @assert length(x) == m ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = x[i] d[:y] = getyvec(x[i], y[:,i]) push!(ret, d) @@ -346,7 +355,7 @@ function createKWargsList(plt::PlottingObject, x::AVec, y::AVec; kw...) m = length(y) ret = [] for i in 1:m - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = x[i] d[:y] = getyvec(x[i], y[i]) push!(ret, d) @@ -358,7 +367,7 @@ end function createKWargsList(plt::PlottingObject, n::Integer; kw...) ret = [] for i in 1:n - d = getSeriesArgs(plt.plotter, kw, i, plt.n + i) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, i, plt.n + i) d[:x] = zeros(0) d[:y] = zeros(0) push!(ret, d) @@ -370,7 +379,7 @@ end createKWargsList{T<:Tuple}(plt::PlottingObject, y::AVec{T}; kw...) = createKWargsList(plt, 1:length(y), y; kw...) function createKWargsList{S<:Real, T<:Tuple}(plt::PlottingObject, x::AVec{S}, y::AVec{T}; kw...) - d = getSeriesArgs(plt.plotter, kw, 1, plt.n + 1) + d = getSeriesArgs(plt.plotter, getinitargs(plt, plt.n+1), kw, 1, plt.n + 1) d[:x] = x d[:y] = y [d] diff --git a/src/subplot.jl b/src/subplot.jl index f985eb1e..3cfa708b 100644 --- a/src/subplot.jl +++ b/src/subplot.jl @@ -41,7 +41,8 @@ Base.string(subplt::Subplot) = "Subplot{$(subplt.plotter) p=$(subplt.p) n=$(subp Base.print(io::IO, subplt::Subplot) = print(io, string(subplt)) Base.show(io::IO, subplt::Subplot) = print(io, string(subplt)) -getplot(subplt::Subplot) = subplt.plts[mod1(subplt.n, subplt.p)] +getplot(subplt::Subplot, idx::Int = subplt.n) = subplt.plts[mod1(idx, subplt.p)] +getinitargs(subplt::Subplot, idx::Int) = getplot(subplt, idx).initargs # ------------------------------------------------------------ @@ -58,6 +59,7 @@ Create a series of plots: """ function subplot(args...; kw...) d = Dict(kw) + replaceAliases!(d) # figure out the layout if haskey(d, :layout) @@ -74,7 +76,7 @@ function subplot(args...; kw...) plts = Plot[] ds = Dict[] for i in 1:length(layout) - push!(ds, getPlotArgs(pkg, kw, i)) + push!(ds, getPlotArgs(pkg, d, i)) push!(plts, plot(pkg; ds[i]...)) end @@ -113,11 +115,20 @@ function subplot!(subplt::Subplot, args...; kw...) error(CURRENT_BACKEND.sym, " does not support the subplot/subplot! commands at this time. Try one of: ", join(filter(pkg->subplotSupported(backend(pkg)), backends()),", ")) end - kwList = createKWargsList(subplt, args...; kw...) + d = Dict(kw) + replaceAliases!(d) + @show d + for k in keys(_plotDefaults) + delete!(d, k) + end + @show d + + kwList = createKWargsList(subplt, args...; d...) for (i,d) in enumerate(kwList) subplt.n += 1 plt = getplot(subplt) # get the Plot object where this series will be drawn d[:show] = false + @show d plot!(plt; d...) end