working on colors overhaul; fix for rationals in plotly; closes #382

This commit is contained in:
Thomas Breloff 2016-07-07 14:40:09 -04:00
parent 2e24da3dcd
commit 4d99b37def
12 changed files with 288 additions and 167 deletions

View File

@ -10,7 +10,7 @@ using Reexport
using FixedSizeArrays
@reexport using RecipesBase
using Base.Meta
# using PlotUtils
using PlotUtils
export
AbstractPlot,
@ -81,15 +81,15 @@ export
arrow,
Segments,
colorscheme,
ColorScheme,
ColorGradient,
ColorVector,
ColorWrapper,
ColorFunction,
ColorZFunction,
getColor,
getColorZ,
# colorscheme,
# ColorScheme,
# ColorGradient,
# ColorVector,
# ColorWrapper,
# ColorFunction,
# ColorZFunction,
# getColor,
# getColorZ,
debugplots,
@ -132,15 +132,13 @@ export BBox, BoundingBox, mm, cm, inch, pt, px, pct, w, h
include("types.jl")
include("utils.jl")
include("colors.jl")
include("components.jl")
include("axes.jl")
include("backends.jl")
include("args.jl")
include("themes.jl")
include("plot.jl")
include("series_args.jl")
include("series_new.jl")
include("series.jl")
include("layouts.jl")
include("subplots.jl")
include("recipes.jl")

View File

@ -498,7 +498,8 @@ function handleColors!(d::KW, arg, csym::Symbol)
if arg == :auto
d[csym] = :auto
else
c = colorscheme(arg)
# c = colorscheme(arg)
c = plot_color(arg, nothing)
d[csym] = c
end
return true
@ -943,13 +944,13 @@ function _update_plot_args(plt::Plot, d_in::KW)
end
# handle colors
bg = convertColor(plt.attr[:background_color])
bg = plot_color(plt.attr[:background_color])
fg = plt.attr[:foreground_color]
if fg == :auto
fg = isdark(bg) ? colorant"white" : colorant"black"
end
plt.attr[:background_color] = bg
plt.attr[:foreground_color] = convertColor(fg)
plt.attr[:foreground_color] = plot_color(fg)
# color_or_match!(plt.attr, :background_color_outside, bg)
color_or_nothing!(plt.attr, :background_color_outside)
end
@ -977,7 +978,7 @@ function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::I
# background colors
# bg = color_or_match!(sp.attr, :background_color_subplot, plt.attr[:background_color])
color_or_nothing!(sp.attr, :background_color_subplot)
bg = convertColor(sp[:background_color_subplot])
bg = plot_color(sp[:background_color_subplot])
sp.attr[:color_palette] = get_color_palette(sp.attr[:color_palette], bg, 30)
color_or_nothing!(sp.attr, :background_color_legend)
color_or_nothing!(sp.attr, :background_color_inside)
@ -1044,7 +1045,92 @@ function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::I
end
end
# -----------------------------------------------------------------------------
function has_black_border_for_default(st::Symbol)
like_histogram(st) || st in (:hexbin, :bar)
end
# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically
function getSeriesRGBColor(c, α, sp::Subplot, n::Int)
if c == :auto
c = autopick(sp[:color_palette], n)
end
# # c should now be a subtype of AbstractPlotColor
# colorscheme(c)
plot_color(c, α)
end
function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
pkg = plt.backend
globalIndex = d[:series_plotindex]
# add default values to our dictionary, being careful not to delete what we just added!
for (k,v) in _series_defaults
slice_arg!(d, d, k, v, commandIndex, remove_pair = false)
end
# this is how many series belong to this subplot
plotIndex = count(series -> series.d[:subplot] === sp && series.d[:primary], plt.series_list)
if get(d, :primary, true)
plotIndex += 1
end
aliasesAndAutopick(d, :linestyle, _styleAliases, supported_styles(pkg), plotIndex)
aliasesAndAutopick(d, :markershape, _markerAliases, supported_markers(pkg), plotIndex)
# update alphas
for asym in (:linealpha, :markeralpha, :fillalpha)
if d[asym] == nothing
d[asym] = d[:seriesalpha]
end
end
if d[:markerstrokealpha] == nothing
d[:markerstrokealpha] = d[:markeralpha]
end
# update series color
d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], d[:seriesalpha], sp, plotIndex)
# update other colors
for s in (:line, :marker, :fill)
csym, asym = Symbol(s,:color), Symbol(s,:alpha)
d[csym] = if d[csym] == :match
if has_black_border_for_default(d[:seriestype]) && csym == :line
plot_color(:black, d[asym])
else
d[:seriescolor]
end
else
getSeriesRGBColor(d[csym], d[asym], sp, plotIndex)
end
end
# update markerstrokecolor
d[:markerstrokecolor] = if d[:markerstrokecolor] == :match
sp[:foreground_color_subplot]
else
getSeriesRGBColor(d[:markerstrokecolor], d[:markerstrokealpha], sp, plotIndex)
end
# scatter plots don't have a line, but must have a shape
if d[:seriestype] in (:scatter, :scatter3d)
d[:linewidth] = 0
if d[:markershape] == :none
d[:markershape] = :circle
end
end
# set label
label = d[:label]
label = (label == "AUTO" ? "y$globalIndex" : label)
d[:label] = label
_replace_linewidth(d)
d
end

View File

@ -44,8 +44,8 @@ function _initialize_backend(::GLVisualizeBackend; kw...)
import GeometryTypes: Point2f0, Point3f0, Vec2f0, Vec3f0
export GLVisualize
# TODO: remove this when PlotUtils is registered
import PlotUtils
# # TODO: remove this when PlotUtils is registered
# import PlotUtils
end
end

View File

@ -107,17 +107,15 @@ const gr_font_family = Dict(
# --------------------------------------------------------------------------------------
function gr_getcolorind(v, a =nothing)
c = getColor(v)
idx = convert(Int, GR.inqcolorfromrgb(c.r, c.g, c.b))
GR.settransparency(float(a==nothing ? alpha(c) : a))
idx
function gr_getcolorind(c)
GR.settransparency(float(alpha(c)))
convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(c)))
end
gr_set_linecolor(c, a=nothing) = GR.setlinecolorind(gr_getcolorind(c, a))
gr_set_fillcolor(c, a=nothing) = GR.setfillcolorind(gr_getcolorind(c, a))
gr_set_markercolor(c, a=nothing) = GR.setmarkercolorind(gr_getcolorind(c, a))
gr_set_textcolor(c, a=nothing) = GR.settextcolorind(gr_getcolorind(c, a))
gr_set_linecolor(c) = GR.setlinecolorind(gr_getcolorind(c))
gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(c))
gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(c))
gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(c))
# --------------------------------------------------------------------------------------
@ -282,12 +280,14 @@ function gr_draw_markers(d::KW, x, y, msize, mz)
cfuncind = isa(shape, Shape) ? GR.setfillcolorind : GR.setmarkercolorind
# draw a filled in shape, slightly bigger, to estimate a stroke
cfunc(d[:markerstrokecolor], d[:markerstrokealpha])
gr_draw_marker(x[i], y[i], msi*1.2, shape, )
if d[:markerstrokewidth] > 0
cfunc(cycle(d[:markerstrokecolor], i)) #, d[:markerstrokealpha])
gr_draw_marker(x[i], y[i], msi + d[:markerstrokewidth], shape)
end
# draw the shape
if mz == nothing
cfunc(d[:markercolor], d[:markeralpha])
cfunc(cycle(d[:markercolor], i)) #, d[:markeralpha])
else
# pick a color from the pre-loaded gradient
ci = round(Int, 1000 + cycle(mz, i) * 255)
@ -311,16 +311,16 @@ end
# ---------------------------------------------------------
function gr_set_line(w, style, c, a)
function gr_set_line(w, style, c) #, a)
GR.setlinetype(gr_linetype[style])
GR.setlinewidth(w)
gr_set_linecolor(c, a)
gr_set_linecolor(c) #, a)
end
function gr_set_fill(c, a)
gr_set_fillcolor(c, a)
function gr_set_fill(c) #, a)
gr_set_fillcolor(c) #, a)
GR.setfillintstyle(GR.INTSTYLE_SOLID)
end
@ -404,12 +404,12 @@ gr_view_ydiff() = viewport_plotarea[4] - viewport_plotarea[3]
# --------------------------------------------------------------------------------------
function gr_set_gradient(c, a)
grad = isa(c, ColorGradient) ? c : default_gradient()
grad = ColorGradient(grad, alpha=a)
function gr_set_gradient(c) #, a)
grad = isa(c, ColorGradient) ? c : cgrad()
# grad = ColorGradient(grad, alpha=a)
for (i,z) in enumerate(linspace(0, 1, 256))
c = getColorZ(grad, z)
GR.setcolorrep(999+i, red(c), green(c), blue(c))
c = grad[z]
GR.setcolorrep(999+i, red(c), green(c), blue(c), alpha(c))
end
grad
end
@ -464,7 +464,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
viewport_plotarea[:] = gr_viewport_from_bbox(plotarea(sp), w, h, viewport_canvas)
# fill in the plot area background
bg = getColor(sp[:background_color_inside])
bg = plot_color(sp[:background_color_inside])
gr_fill_viewport(viewport_plotarea, bg)
# reduced from before... set some flags based on the series in this subplot
@ -618,7 +618,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# update the current stored gradient
if st in (:contour, :surface, :wireframe, :heatmap)
gr_set_gradient(d[:fillcolor], d[:fillalpha])
gr_set_gradient(d[:fillcolor]) #, d[:fillalpha])
elseif d[:marker_z] != nothing
d[:markercolor] = gr_set_gradient(d[:markercolor], d[:markeralpha])
end
@ -653,7 +653,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# do area fill
if frng != nothing
gr_set_fillcolor(d[:fillcolor], d[:fillalpha])
gr_set_fillcolor(d[:fillcolor]) #, d[:fillalpha])
GR.setfillintstyle(GR.INTSTYLE_SOLID)
frng = isa(frng, Number) ? Float64[frng] : frng
nx, ny, nf = length(x), length(y), length(frng)
@ -669,7 +669,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# draw the line(s)
if st == :path
gr_set_line(d[:linewidth], d[:linestyle], d[:linecolor], d[:linealpha])
gr_set_line(d[:linewidth], d[:linestyle], d[:linecolor]) #, d[:linealpha])
gr_polyline(x, y)
end
end
@ -723,7 +723,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# draw path
if st == :path3d
if length(x) > 1
gr_set_line(d[:linewidth], d[:linestyle], d[:linecolor], d[:linealpha])
gr_set_line(d[:linewidth], d[:linestyle], d[:linecolor]) #, d[:linealpha])
GR.polyline3d(x, y, z)
end
end
@ -784,11 +784,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :shape
# draw the interior
gr_set_fill(d[:fillcolor], d[:fillalpha])
gr_set_fill(d[:fillcolor]) #, d[:fillalpha])
gr_polyline(d[:x], d[:y], GR.fillarea)
# draw the shapes
gr_set_line(d[:linewidth], :solid, d[:linecolor], d[:linealpha])
gr_set_line(d[:linewidth], :solid, d[:linecolor]) #, d[:linealpha])
gr_polyline(d[:x], d[:y])
@ -847,11 +847,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
should_add_to_legend(series) || continue
d = series.d
st = d[:seriestype]
gr_set_line(d[:linewidth], d[:linestyle], d[:linecolor], d[:linealpha])
gr_set_line(d[:linewidth], d[:linestyle], d[:linecolor]) #, d[:linealpha])
if st == :path
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
elseif st == :shape
gr_set_fill(d[:fillcolor], d[:fillalpha])
gr_set_fill(d[:fillcolor]) #, d[:fillalpha])
l, r = xpos-0.07, xpos-0.01
b, t = ypos-0.4dy, ypos+0.4dy
x = [l, r, r, l, l]
@ -865,7 +865,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# if shape != :none #st == :scatter || d[:markershape] != :none
# msize = 10
# for xoff in [0.06,0.02]
# gr_set_markercolor(d[:markerstrokecolor], d[:markerstrokealpha])
# gr_set_markercolor(d[:markerstrokecolor]) #, d[:markerstrokealpha])
# gr_draw_marker(xpos-xoff, ypos, msize*1.1, shape)
# gr_set_markercolor(d[:markercolor], d[:markeralpha])
# gr_draw_marker(xpos-xoff, ypos, msize, shape)

View File

@ -88,7 +88,7 @@ function plotly_font(font::Font, color = font.color)
KW(
:family => font.family,
:size => round(Int, font.pointsize*1.4),
:color => webcolor(color),
:color => rgba_string(color),
)
end
@ -126,7 +126,7 @@ end
# # :ay => -40,
# :ax => 10xdiff / dist,
# :ay => -10ydiff / dist,
# :arrowcolor => webcolor(d[:linecolor], d[:linealpha]),
# :arrowcolor => rgba_string(d[:linecolor]),
# :xref => "x",
# :yref => "y",
# :arrowsize => 10a.headwidth,
@ -175,8 +175,8 @@ function plotly_axis(axis::Axis, sp::Subplot)
ax[:titlefont] = plotly_font(axis[:guidefont], axis[:foreground_color_guide])
ax[:type] = plotly_scale(axis[:scale])
ax[:tickfont] = plotly_font(axis[:tickfont], axis[:foreground_color_text])
ax[:tickcolor] = webcolor(axis[:foreground_color_border])
ax[:linecolor] = webcolor(axis[:foreground_color_border])
ax[:tickcolor] = rgba_string(axis[:foreground_color_border])
ax[:linecolor] = rgba_string(axis[:foreground_color_border])
# lims
lims = axis[:lims]
@ -214,7 +214,7 @@ function plotly_layout(plt::Plot)
w, h = plt[:size]
d_out[:width], d_out[:height] = w, h
d_out[:paper_bgcolor] = webcolor(plt[:background_color_outside])
d_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
d_out[:margin] = KW(:l=>0, :b=>0, :r=>0, :t=>20)
d_out[:annotations] = KW[]
@ -239,7 +239,7 @@ function plotly_layout(plt::Plot)
push!(d_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], titlefont)))
end
d_out[:plot_bgcolor] = webcolor(sp[:background_color_inside])
d_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside])
# TODO: x/y axis tick values/labels
@ -259,8 +259,8 @@ function plotly_layout(plt::Plot)
d_out[:showlegend] = sp[:legend] != :none
if sp[:legend] != :none
d_out[:legend] = KW(
:bgcolor => webcolor(sp[:background_color_legend]),
:bordercolor => webcolor(sp[:foreground_color_legend]),
:bgcolor => rgba_string(sp[:background_color_legend]),
:bordercolor => rgba_string(sp[:foreground_color_legend]),
:font => plotly_font(sp[:legendfont], sp[:foreground_color_legend]),
)
end
@ -299,7 +299,7 @@ end
function plotly_colorscale(grad::ColorGradient, alpha = nothing)
[[grad.values[i], webcolor(grad.colors[i], alpha)] for i in 1:length(grad.colors)]
[[grad.values[i], rgba_string(grad.colors[i], alpha)] for i in 1:length(grad.colors)]
end
plotly_colorscale(c, alpha = nothing) = plotly_colorscale(default_gradient(), alpha)
@ -330,6 +330,9 @@ function plotly_close_shapes(x, y)
nanvcat(xs), nanvcat(ys)
end
plotly_data(v) = collect(v)
plotly_data{R<:Rational}(v::AbstractArray{R}) = float(v)
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
function plotly_series(plt::Plot, series::Series)
d = series.d
@ -342,7 +345,7 @@ function plotly_series(plt::Plot, series::Series)
d_out[:yaxis] = "y$spidx"
d_out[:showlegend] = should_add_to_legend(series)
x, y = collect(d[:x]), collect(d[:y])
x, y = plotly_data(d[:x]), plotly_data(d[:y])
d_out[:name] = d[:label]
st = d[:seriestype]
isscatter = st in (:scatter, :scatter3d, :scattergl)
@ -360,7 +363,7 @@ function plotly_series(plt::Plot, series::Series)
end
if d[:fillrange] == true || d[:fillrange] == 0
d_out[:fill] = "tozeroy"
d_out[:fillcolor] = webcolor(d[:fillcolor], d[:fillalpha])
d_out[:fillcolor] = rgba_string(d[:fillcolor])
elseif !(d[:fillrange] in (false, nothing))
warn("fillrange ignored... plotly only supports filling to zero. fillrange: $(d[:fillrange])")
end
@ -374,10 +377,10 @@ function plotly_series(plt::Plot, series::Series)
# @show map(length, (x,y,d_out[:x],d_out[:y]))
# @show d_out[:x] d_out[:y]
d_out[:fill] = "tozeroy"
d_out[:fillcolor] = webcolor(d[:fillcolor], d[:fillalpha])
d_out[:fillcolor] = rgba_string(d[:fillcolor])
if d[:markerstrokewidth] > 0
d_out[:line] = KW(
:color => webcolor(d[:linecolor], d[:linealpha]),
:color => rgba_string(d[:linecolor]),
:width => d[:linewidth],
:dash => string(d[:linestyle]),
)
@ -400,7 +403,7 @@ function plotly_series(plt::Plot, series::Series)
# end
# d_out[:nbinsx] = xbins
# d_out[:nbinsy] = ybins
# d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
# d_out[:colorscale] = plotly_colorscale(d[:fillcolor])
# elseif st in (:histogram, :density)
# d_out[:type] = "histogram"
@ -414,7 +417,7 @@ function plotly_series(plt::Plot, series::Series)
elseif st == :heatmap
d_out[:type] = "heatmap"
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
d_out[:colorscale] = plotly_colorscale(d[:fillcolor])
elseif st == :contour
d_out[:type] = "contour"
@ -422,12 +425,12 @@ function plotly_series(plt::Plot, series::Series)
# d_out[:showscale] = d[:colorbar] != :none
d_out[:ncontours] = d[:levels]
d_out[:contours] = KW(:coloring => d[:fillrange] != nothing ? "fill" : "lines")
d_out[:colorscale] = plotly_colorscale(d[:linecolor], d[:linealpha])
d_out[:colorscale] = plotly_colorscale(d[:linecolor])
elseif st in (:surface, :wireframe)
d_out[:type] = "surface"
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
d_out[:colorscale] = plotly_colorscale(d[:fillcolor])
elseif st == :pie
d_out[:type] = "pie"
@ -443,7 +446,7 @@ function plotly_series(plt::Plot, series::Series)
hasline ? "lines" : "none"
end
d_out[:x], d_out[:y] = x, y
d_out[:z] = collect(d[:z])
d_out[:z] = plotly_data(d[:z])
else
warn("Plotly: seriestype $st isn't supported.")
@ -454,11 +457,11 @@ function plotly_series(plt::Plot, series::Series)
if hasmarker
d_out[:marker] = KW(
:symbol => get(_plotly_markers, d[:markershape], string(d[:markershape])),
:opacity => d[:markeralpha],
# :opacity => d[:markeralpha],
:size => 2 * d[:markersize],
:color => webcolor(d[:markercolor], d[:markeralpha]),
:color => rgba_string(d[:markercolor]),
:line => KW(
:color => webcolor(d[:markerstrokecolor], d[:markerstrokealpha]),
:color => rgba_string(d[:markerstrokecolor]),
:width => d[:markerstrokewidth],
),
)
@ -466,18 +469,18 @@ function plotly_series(plt::Plot, series::Series)
# gotta hack this (for now?) since plotly can't handle rgba values inside the gradient
if d[:marker_z] != nothing
# d_out[:marker][:color] = d[:marker_z]
# d_out[:marker][:colorscale] = plotly_colorscale(d[:markercolor], d[:markeralpha])
# d_out[:marker][:colorscale] = plotly_colorscale(d[:markercolor])
# d_out[:showscale] = true
grad = ColorGradient(d[:markercolor], alpha=d[:markeralpha])
zmin, zmax = extrema(d[:marker_z])
d_out[:marker][:color] = [webcolor(getColorZ(grad, (zi - zmin) / (zmax - zmin))) for zi in d[:marker_z]]
d_out[:marker][:color] = [rgba_string(getColorZ(grad, (zi - zmin) / (zmax - zmin))) for zi in d[:marker_z]]
end
end
# add "line"
if hasline
d_out[:line] = KW(
:color => webcolor(d[:linecolor], d[:linealpha]),
:color => rgba_string(d[:linecolor]),
:width => d[:linewidth],
:shape => if st == :steppre
"vh"

View File

@ -78,26 +78,37 @@ end
# --------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------
# convert colorant to 4-tuple RGBA
py_color(c::Colorant, α=nothing) = map(f->float(f(convertColor(c,α))), (red, green, blue, alpha))
py_color(cvec::ColorVector, α=nothing) = map(py_color, convertColor(cvec, α).v)
py_color(grad::ColorGradient, α=nothing) = map(c -> py_color(c, α), grad.colors)
py_color(scheme::ColorScheme, α=nothing) = py_color(convertColor(getColor(scheme), α))
py_color(vec::AVec, α=nothing) = map(c->py_color(c,α), vec)
py_color(c, α=nothing) = py_color(convertColor(c, α))
# # convert colorant to 4-tuple RGBA
# py_color(c::Colorant, α=nothing) = map(f->float(f(convertColor(c,α))), (red, green, blue, alpha))
# py_color(cvec::ColorVector, α=nothing) = map(py_color, convertColor(cvec, α).v)
# py_color(grad::ColorGradient, α=nothing) = map(c -> py_color(c, α), grad.colors)
# py_color(scheme::ColorScheme, α=nothing) = py_color(convertColor(getColor(scheme), α))
# py_color(vec::AVec, α=nothing) = map(c->py_color(c,α), vec)
# py_color(c, α=nothing) = py_color(convertColor(c, α))
function py_colormap(c::ColorGradient, α=nothing)
pyvals = [(v, py_color(getColorZ(c, v), α)) for v in c.values]
pycolors.pymember("LinearSegmentedColormap")[:from_list]("tmp", pyvals)
# function py_colormap(c::ColorGradient, α=nothing)
# pyvals = [(v, py_color(getColorZ(c, v), α)) for v in c.values]
# pycolors.pymember("LinearSegmentedColormap")[:from_list]("tmp", pyvals)
# end
# # convert vectors and ColorVectors to standard ColorGradients
# # TODO: move this logic to colors.jl and keep a barebones wrapper for pyplot
# py_colormap(cv::ColorVector, α=nothing) = py_colormap(ColorGradient(cv.v), α)
# py_colormap(v::AVec, α=nothing) = py_colormap(ColorGradient(v), α)
# # anything else just gets a bluesred gradient
# py_colormap(c, α=nothing) = py_colormap(default_gradient(), α)
py_color(c::Colorant) = (red(c), green(c), blue(c), alpha(c))
py_color(cs::AVec) = map(py_color, cs)
py_color(grad::ColorGradient) = py_color(grad.colors)
function py_colormap(grad::ColorGradient)
pyvals = [(z, py_color(c[z])) for z in c.values]
pycolors.LinearSegmentedColormap[:from_list]("tmp", pyvals)
end
py_colormap(c) = py_colormap(cgrad())
# convert vectors and ColorVectors to standard ColorGradients
# TODO: move this logic to colors.jl and keep a barebones wrapper for pyplot
py_colormap(cv::ColorVector, α=nothing) = py_colormap(ColorGradient(cv.v), α)
py_colormap(v::AVec, α=nothing) = py_colormap(ColorGradient(v), α)
# anything else just gets a bluesred gradient
py_colormap(c, α=nothing) = py_colormap(default_gradient(), α)
function py_shading(c, z, α=nothing)
cmap = py_colormap(c, α)
@ -247,14 +258,14 @@ function py_color_fix(c, x)
end
end
py_linecolor(d::KW) = py_color(d[:linecolor], d[:linealpha])
py_markercolor(d::KW) = py_color(d[:markercolor], d[:markeralpha])
py_markerstrokecolor(d::KW) = py_color(d[:markerstrokecolor], d[:markerstrokealpha])
py_fillcolor(d::KW) = py_color(d[:fillcolor], d[:fillalpha])
py_linecolor(d::KW) = py_color(d[:linecolor]) #, d[:linealpha])
py_markercolor(d::KW) = py_color(d[:markercolor]) #, d[:markeralpha])
py_markerstrokecolor(d::KW) = py_color(d[:markerstrokecolor]) #, d[:markerstrokealpha])
py_fillcolor(d::KW) = py_color(d[:fillcolor]) #, d[:fillalpha])
py_linecolormap(d::KW) = py_colormap(d[:linecolor], d[:linealpha])
py_markercolormap(d::KW) = py_colormap(d[:markercolor], d[:markeralpha])
py_fillcolormap(d::KW) = py_colormap(d[:fillcolor], d[:fillalpha])
py_linecolormap(d::KW) = py_colormap(d[:linecolor]) #, d[:linealpha])
py_markercolormap(d::KW) = py_colormap(d[:markercolor]) #, d[:markeralpha])
py_fillcolormap(d::KW) = py_colormap(d[:fillcolor]) #, d[:fillalpha])
# ---------------------------------------------------------------------------

View File

@ -382,7 +382,7 @@ end
end
if lz != nothing
line_z := newlz
linecolor := (isa(d[:linecolor], ColorGradient) ? d[:linecolor] : default_gradient())
linecolor := (isa(d[:linecolor], ColorGradient) ? d[:linecolor] : cgrad())
end
# Plots.DD(d)
()
@ -405,7 +405,6 @@ end
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis]
bw = d[:bar_width]
hw = if bw == nothing
# 0.5mean(diff(x))
0.5mean(diff([discrete_value!(axis, xi)[1] for xi=x]))
else
Float64[0.5cycle(bw,i) for i=1:length(x)]
@ -420,7 +419,6 @@ end
# create the bar shapes by adding x/y segments
xseg, yseg = Segments(), Segments()
for i=1:ny
# ci = x[i]
center = discrete_value!(axis, x[i])[1]
hwi = cycle(hw,i)
yi = y[i]

View File

@ -1,81 +1,106 @@
# we are going to build recipes to do the processing and splitting of the args
function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
pkg = plt.backend
globalIndex = d[:series_plotindex]
# create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems].
# Special handling for: no args, xmin/xmax, parametric, dataframes
# Then once inputs have been converted, build the series args, map functions, etc.
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
# add default values to our dictionary, being careful not to delete what we just added!
for (k,v) in _series_defaults
slice_arg!(d, d, k, v, commandIndex, remove_pair = false)
end
typealias FuncOrFuncs @compat(Union{Function, AVec{Function}})
# this is how many series belong to this subplot
plotIndex = count(series -> series.d[:subplot] === sp && series.d[:primary], plt.series_list)
if get(d, :primary, true)
plotIndex += 1
end
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
aliasesAndAutopick(d, :linestyle, _styleAliases, supported_styles(pkg), plotIndex)
aliasesAndAutopick(d, :markershape, _markerAliases, supported_markers(pkg), plotIndex)
# missing
convertToAnyVector(v::@compat(Void), d::KW) = Any[nothing], nothing
# update color
d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], sp, plotIndex)
# fixed number of blank series
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing
# update colors
for csym in (:linecolor, :markercolor, :fillcolor)
d[csym] = if d[csym] == :match
if has_black_border_for_default(d[:seriestype]) && csym == :linecolor
:black
# numeric vector
convertToAnyVector{T<:Number}(v::AVec{T}, d::KW) = Any[v], nothing
# string vector
convertToAnyVector{T<:@compat(AbstractString)}(v::AVec{T}, d::KW) = Any[v], nothing
function convertToAnyVector(v::AMat, d::KW)
if all3D(d)
Any[Surface(v)]
else
d[:seriescolor]
end
else
getSeriesRGBColor(d[csym], sp, plotIndex)
end
end
# update markerstrokecolor
c = d[:markerstrokecolor]
c = if c == :match
sp[:foreground_color_subplot]
else
getSeriesRGBColor(c, sp, plotIndex)
end
d[:markerstrokecolor] = c
# update alphas
for asym in (:linealpha, :markeralpha, :fillalpha)
if d[asym] == nothing
d[asym] = d[:seriesalpha]
end
end
if d[:markerstrokealpha] == nothing
d[:markerstrokealpha] = d[:markeralpha]
end
# scatter plots don't have a line, but must have a shape
if d[:seriestype] in (:scatter, :scatter3d)
d[:linewidth] = 0
if d[:markershape] == :none
d[:markershape] = :circle
end
end
# set label
label = d[:label]
label = (label == "AUTO" ? "y$globalIndex" : label)
d[:label] = label
_replace_linewidth(d)
d
Any[v[:,i] for i in 1:size(v,2)]
end, nothing
end
# -------------------------------------------------------------------
# -------------------------------------------------------------------
# function
convertToAnyVector(f::Function, d::KW) = Any[f], nothing
# instead of process_inputs:
# surface
convertToAnyVector(s::Surface, d::KW) = Any[s], nothing
# # vector of OHLC
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing
# dates
convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::KW) = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else)
function convertToAnyVector(v::AVec, d::KW)
if all(x -> typeof(x) <: Number, v)
# all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing
else
# something else... treat each element as an item
vcat(Any[convertToAnyVector(vi, d)[1] for vi in v]...), nothing
# Any[vi for vi in v], nothing
end
end
convertToAnyVector(t::Tuple, d::KW) = Any[t], nothing
function convertToAnyVector(args...)
error("In convertToAnyVector, could not handle the argument types: $(map(typeof, args[1:end-1]))")
end
# --------------------------------------------------------------------
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array
# result in that array being shared. push!, etc will add too many items to that array
compute_x(x::Void, y::Void, z) = 1:size(z,1)
compute_x(x::Void, y, z) = 1:size(y,1)
compute_x(x::Function, y, z) = map(x, y)
compute_x(x, y, z) = copy(x)
# compute_y(x::Void, y::Function, z) = error()
compute_y(x::Void, y::Void, z) = 1:size(z,2)
compute_y(x, y::Function, z) = map(y, x)
compute_y(x, y, z) = copy(y)
compute_z(x, y, z::Function) = map(z, x, y)
compute_z(x, y, z::AbstractMatrix) = Surface(z)
compute_z(x, y, z::Void) = nothing
compute_z(x, y, z) = copy(z)
nobigs(v::AVec{BigFloat}) = map(Float64, v)
nobigs(v::AVec{BigInt}) = map(Int64, v)
nobigs(v) = v
@noinline function compute_xyz(x, y, z)
x = compute_x(x,y,z)
y = compute_y(x,y,z)
z = compute_z(x,y,z)
nobigs(x), nobigs(y), nobigs(z)
end
# not allowed
compute_xyz(x::Void, y::FuncOrFuncs, z) = error("If you want to plot the function `$y`, you need to define the x values!")
compute_xyz(x::Void, y::Void, z::FuncOrFuncs) = error("If you want to plot the function `$z`, you need to define x and y values!")
compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
# --------------------------------------------------------------------
# we are going to build recipes to do the processing and splitting of the args
# ensure we dispatch to the slicer
immutable SliceIt end