Merge pull request #1681 from mkborregaard/plotattributes

change all instances of `d` to `plotattributes.
This commit is contained in:
Michael Krabbe Borregaard 2018-08-28 14:39:44 +02:00 committed by GitHub
commit f2e98acc65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1146 additions and 1146 deletions

View File

@ -1,6 +1,6 @@
julia 0.7 julia 1.0
RecipesBase 0.2.3 RecipesBase 0.6.0
PlotUtils 0.4.1 PlotUtils 0.4.1
PlotThemes 0.1.3 PlotThemes 0.1.3
Reexport Reexport

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
function Axis(sp::Subplot, letter::Symbol, args...; kw...) function Axis(sp::Subplot, letter::Symbol, args...; kw...)
# init with values from _plot_defaults # init with values from _plot_defaults
d = KW( plotattributes = KW(
:letter => letter, :letter => letter,
# :extrema => (Inf, -Inf), # :extrema => (Inf, -Inf),
:extrema => Extrema(), :extrema => Extrema(),
@ -22,14 +22,14 @@ function Axis(sp::Subplot, letter::Symbol, args...; kw...)
for (k,v) in _axis_defaults for (k,v) in _axis_defaults
lk = Symbol(letter, k) lk = Symbol(letter, k)
lv = _axis_defaults_byletter[lk] lv = _axis_defaults_byletter[lk]
d[k] = (lv == :match ? v : lv) plotattributes[k] = (lv == :match ? v : lv)
end end
# merge!(d, _axis_defaults) # merge!(plotattributes, _axis_defaults)
d[:discrete_values] = [] plotattributes[:discrete_values] = []
# update the defaults # update the defaults
attr!(Axis([sp], d), args...; kw...) attr!(Axis([sp], plotattributes), args...; kw...)
end end
function get_axis(sp::Subplot, letter::Symbol) function get_axis(sp::Subplot, letter::Symbol)
@ -41,45 +41,45 @@ function get_axis(sp::Subplot, letter::Symbol)
end::Axis end::Axis
end end
function process_axis_arg!(d::KW, arg, letter = "") function process_axis_arg!(plotattributes::KW, arg, letter = "")
T = typeof(arg) T = typeof(arg)
arg = get(_scaleAliases, arg, arg) arg = get(_scaleAliases, arg, arg)
if typeof(arg) <: Font if typeof(arg) <: Font
d[Symbol(letter,:tickfont)] = arg plotattributes[Symbol(letter,:tickfont)] = arg
d[Symbol(letter,:guidefont)] = arg plotattributes[Symbol(letter,:guidefont)] = arg
elseif arg in _allScales elseif arg in _allScales
d[Symbol(letter,:scale)] = arg plotattributes[Symbol(letter,:scale)] = arg
elseif arg in (:flip, :invert, :inverted) elseif arg in (:flip, :invert, :inverted)
d[Symbol(letter,:flip)] = true plotattributes[Symbol(letter,:flip)] = true
elseif T <: AbstractString elseif T <: AbstractString
d[Symbol(letter,:guide)] = arg plotattributes[Symbol(letter,:guide)] = arg
# xlims/ylims # xlims/ylims
elseif (T <: Tuple || T <: AVec) && length(arg) == 2 elseif (T <: Tuple || T <: AVec) && length(arg) == 2
sym = typeof(arg[1]) <: Number ? :lims : :ticks sym = typeof(arg[1]) <: Number ? :lims : :ticks
d[Symbol(letter,sym)] = arg plotattributes[Symbol(letter,sym)] = arg
# xticks/yticks # xticks/yticks
elseif T <: AVec elseif T <: AVec
d[Symbol(letter,:ticks)] = arg plotattributes[Symbol(letter,:ticks)] = arg
elseif arg == nothing elseif arg == nothing
d[Symbol(letter,:ticks)] = [] plotattributes[Symbol(letter,:ticks)] = []
elseif T <: Bool || arg in _allShowaxisArgs elseif T <: Bool || arg in _allShowaxisArgs
d[Symbol(letter,:showaxis)] = showaxis(arg, letter) plotattributes[Symbol(letter,:showaxis)] = showaxis(arg, letter)
elseif typeof(arg) <: Number elseif typeof(arg) <: Number
d[Symbol(letter,:rotation)] = arg plotattributes[Symbol(letter,:rotation)] = arg
elseif typeof(arg) <: Function elseif typeof(arg) <: Function
d[Symbol(letter,:formatter)] = arg plotattributes[Symbol(letter,:formatter)] = arg
elseif !handleColors!(d, arg, Symbol(letter, :foreground_color_axis)) elseif !handleColors!(plotattributes, arg, Symbol(letter, :foreground_color_axis))
@warn("Skipped $(letter)axis arg $arg") @warn("Skipped $(letter)axis arg $arg")
end end
@ -88,28 +88,28 @@ end
# update an Axis object with magic args and keywords # update an Axis object with magic args and keywords
function attr!(axis::Axis, args...; kw...) function attr!(axis::Axis, args...; kw...)
# first process args # first process args
d = axis.d plotattributes = axis.plotattributes
for arg in args for arg in args
process_axis_arg!(d, arg) process_axis_arg!(plotattributes, arg)
end end
# then override for any keywords... only those keywords that already exists in d # then override for any keywords... only those keywords that already exists in plotattributes
for (k,v) in kw for (k,v) in kw
if haskey(d, k) if haskey(plotattributes, k)
if k == :discrete_values if k == :discrete_values
# add these discrete values to the axis # add these discrete values to the axis
for vi in v for vi in v
discrete_value!(axis, vi) discrete_value!(axis, vi)
end end
else else
d[k] = v plotattributes[k] = v
end end
end end
end end
# replace scale aliases # replace scale aliases
if haskey(_scaleAliases, d[:scale]) if haskey(_scaleAliases, plotattributes[:scale])
d[:scale] = _scaleAliases[d[:scale]] plotattributes[:scale] = _scaleAliases[plotattributes[:scale]]
end end
axis axis
@ -117,10 +117,10 @@ end
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
Base.show(io::IO, axis::Axis) = dumpdict(axis.d, "Axis", true) Base.show(io::IO, axis::Axis) = dumpdict(axis.plotattributes, "Axis", true)
# Base.getindex(axis::Axis, k::Symbol) = getindex(axis.d, k) # Base.getindex(axis::Axis, k::Symbol) = getindex(axis.plotattributes, k)
Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.d, v, ks...) Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.plotattributes, v, ks...)
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.d, k) Base.haskey(axis::Axis, k::Symbol) = haskey(axis.plotattributes, k)
ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax)) ignorenan_extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
@ -322,7 +322,7 @@ function reset_extrema!(sp::Subplot)
sp[Symbol(asym,:axis)][:extrema] = Extrema() sp[Symbol(asym,:axis)][:extrema] = Extrema()
end end
for series in sp.series_list for series in sp.series_list
expand_extrema!(sp, series.d) expand_extrema!(sp, series.plotattributes)
end end
end end
@ -357,17 +357,17 @@ function expand_extrema!(axis::Axis, v::AVec{N}) where N<:Number
end end
function expand_extrema!(sp::Subplot, d::KW) function expand_extrema!(sp::Subplot, plotattributes::KW)
vert = isvertical(d) vert = isvertical(plotattributes)
# first expand for the data # first expand for the data
for letter in (:x, :y, :z) for letter in (:x, :y, :z)
data = d[if vert data = plotattributes[if vert
letter letter
else else
letter == :x ? :y : letter == :y ? :x : :z letter == :x ? :y : letter == :y ? :x : :z
end] end]
if letter != :z && d[:seriestype] == :straightline && any(series[:seriestype] != :straightline for series in series_list(sp)) && data[1] != data[2] if letter != :z && plotattributes[:seriestype] == :straightline && any(series[:seriestype] != :straightline for series in series_list(sp)) && data[1] != data[2]
data = [NaN] data = [NaN]
end end
axis = sp[Symbol(letter, "axis")] axis = sp[Symbol(letter, "axis")]
@ -379,30 +379,30 @@ function expand_extrema!(sp::Subplot, d::KW)
elseif eltype(data) <: Number || (isa(data, Surface) && all(di -> isa(di, Number), data.surf)) elseif eltype(data) <: Number || (isa(data, Surface) && all(di -> isa(di, Number), data.surf))
if !(eltype(data) <: Number) if !(eltype(data) <: Number)
# huh... must have been a mis-typed surface? lets swap it out # huh... must have been a mis-typed surface? lets swap it out
data = d[letter] = Surface(Matrix{Float64}(data.surf)) data = plotattributes[letter] = Surface(Matrix{Float64}(data.surf))
end end
expand_extrema!(axis, data) expand_extrema!(axis, data)
elseif data != nothing elseif data != nothing
# TODO: need more here... gotta track the discrete reference value # TODO: need more here... gotta track the discrete reference value
# as well as any coord offset (think of boxplot shape coords... they all # as well as any coord offset (think of boxplot shape coords... they all
# correspond to the same x-value) # correspond to the same x-value)
d[letter], d[Symbol(letter,"_discrete_indices")] = discrete_value!(axis, data) plotattributes[letter], plotattributes[Symbol(letter,"_discrete_indices")] = discrete_value!(axis, data)
expand_extrema!(axis, d[letter]) expand_extrema!(axis, plotattributes[letter])
end end
end end
# # expand for fillrange/bar_width # # expand for fillrange/bar_width
# fillaxis, baraxis = sp.attr[:yaxis], sp.attr[:xaxis] # fillaxis, baraxis = sp.attr[:yaxis], sp.attr[:xaxis]
# if isvertical(d) # if isvertical(plotattributes)
# fillaxis, baraxis = baraxis, fillaxis # fillaxis, baraxis = baraxis, fillaxis
# end # end
# expand for fillrange # expand for fillrange
fr = d[:fillrange] fr = plotattributes[:fillrange]
if fr == nothing && d[:seriestype] == :bar if fr == nothing && plotattributes[:seriestype] == :bar
fr = 0.0 fr = 0.0
end end
if fr != nothing && !all3D(d) if fr != nothing && !all3D(plotattributes)
axis = sp.attr[vert ? :yaxis : :xaxis] axis = sp.attr[vert ? :yaxis : :xaxis]
if typeof(fr) <: Tuple if typeof(fr) <: Tuple
for fri in fr for fri in fr
@ -414,13 +414,13 @@ function expand_extrema!(sp::Subplot, d::KW)
end end
# expand for bar_width # expand for bar_width
if d[:seriestype] == :bar if plotattributes[:seriestype] == :bar
dsym = vert ? :x : :y dsym = vert ? :x : :y
data = d[dsym] data = plotattributes[dsym]
bw = d[:bar_width] bw = plotattributes[:bar_width]
if bw == nothing if bw == nothing
bw = d[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data)))) bw = plotattributes[:bar_width] = _bar_width * ignorenan_minimum(filter(x->x>0,diff(sort(data))))
end end
axis = sp.attr[Symbol(dsym, :axis)] axis = sp.attr[Symbol(dsym, :axis)]
expand_extrema!(axis, ignorenan_maximum(data) + 0.5maximum(bw)) expand_extrema!(axis, ignorenan_maximum(data) + 0.5maximum(bw))
@ -428,11 +428,11 @@ function expand_extrema!(sp::Subplot, d::KW)
end end
# expand for heatmaps # expand for heatmaps
if d[:seriestype] == :heatmap if plotattributes[:seriestype] == :heatmap
for letter in (:x, :y) for letter in (:x, :y)
data = d[letter] data = plotattributes[letter]
axis = sp[Symbol(letter, "axis")] axis = sp[Symbol(letter, "axis")]
scale = get(d, Symbol(letter, "scale"), :identity) scale = get(plotattributes, Symbol(letter, "scale"), :identity)
expand_extrema!(axis, heatmap_edges(data, scale)) expand_extrema!(axis, heatmap_edges(data, scale))
end end
end end
@ -462,7 +462,7 @@ function default_should_widen(axis::Axis)
if !is_2tuple(axis[:lims]) if !is_2tuple(axis[:lims])
for sp in axis.sps for sp in axis.sps
for series in series_list(sp) for series in series_list(sp)
if series.d[:seriestype] in _widen_seriestypes if series.plotattributes[:seriestype] in _widen_seriestypes
should_widen = true should_widen = true
end end
end end
@ -572,12 +572,12 @@ end
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
function pie_labels(sp::Subplot, series::Series) function pie_labels(sp::Subplot, series::Series)
d = series.d plotattributes = series.plotattributes
if haskey(d,:x_discrete_indices) if haskey(plotattributes,:x_discrete_indices)
dvals = sp.attr[:xaxis].d[:discrete_values] dvals = sp.attr[:xaxis].plotattributes[:discrete_values]
[dvals[idx] for idx in d[:x_discrete_indices]] [dvals[idx] for idx in plotattributes[:x_discrete_indices]]
else else
d[:x] plotattributes[:x]
end end
end end

View File

@ -182,7 +182,7 @@ function gl_marker(shape::Symbol)
end end
end end
function extract_limits(sp, d, kw_args) function extract_limits(sp, plotattributes, kw_args)
clims = sp[:clims] clims = sp[:clims]
if is_2tuple(clims) if is_2tuple(clims)
if isfinite(clims[1]) && isfinite(clims[2]) if isfinite(clims[1]) && isfinite(clims[2])
@ -200,70 +200,70 @@ to_vec(::Type{T}, vec::StaticArrays.StaticVector{2}) where {T <: StaticArrays.St
to_vec(::Type{T}, vecs::AbstractVector) where {T <: StaticArrays.StaticVector} = map(x-> to_vec(T, x), vecs) to_vec(::Type{T}, vecs::AbstractVector) where {T <: StaticArrays.StaticVector} = map(x-> to_vec(T, x), vecs)
function extract_marker(d, kw_args) function extract_marker(plotattributes, kw_args)
dim = Plots.is3d(d) ? 3 : 2 dim = Plots.is3d(plotattributes) ? 3 : 2
scaling = dim == 3 ? 0.003 : 2 scaling = dim == 3 ? 0.003 : 2
if haskey(d, :markershape) if haskey(plotattributes, :markershape)
shape = d[:markershape] shape = plotattributes[:markershape]
shape = gl_marker(shape) shape = gl_marker(shape)
if shape != :none if shape != :none
kw_args[:primitive] = shape kw_args[:primitive] = shape
end end
end end
dim = isa(kw_args[:primitive], GLVisualize.Sprites) ? 2 : 3 dim = isa(kw_args[:primitive], GLVisualize.Sprites) ? 2 : 3
if haskey(d, :markersize) if haskey(plotattributes, :markersize)
msize = d[:markersize] msize = plotattributes[:markersize]
kw_args[:scale] = to_vec(GeometryTypes.Vec{dim, Float32}, msize .* scaling) kw_args[:scale] = to_vec(GeometryTypes.Vec{dim, Float32}, msize .* scaling)
end end
if haskey(d, :offset) if haskey(plotattributes, :offset)
kw_args[:offset] = d[:offset] kw_args[:offset] = plotattributes[:offset]
end end
# get the color # get the color
key = :markercolor key = :markercolor
haskey(d, key) || return haskey(plotattributes, key) || return
c = gl_color(d[key]) c = gl_color(plotattributes[key])
if isa(c, AbstractVector) && d[:marker_z] != nothing if isa(c, AbstractVector) && plotattributes[:marker_z] != nothing
extract_colornorm(d, kw_args) extract_colornorm(plotattributes, kw_args)
kw_args[:color] = nothing kw_args[:color] = nothing
kw_args[:color_map] = c kw_args[:color_map] = c
kw_args[:intensity] = convert(Vector{Float32}, d[:marker_z]) kw_args[:intensity] = convert(Vector{Float32}, plotattributes[:marker_z])
else else
kw_args[:color] = c kw_args[:color] = c
end end
key = :markerstrokecolor key = :markerstrokecolor
haskey(d, key) || return haskey(plotattributes, key) || return
c = gl_color(d[key]) c = gl_color(plotattributes[key])
if c != nothing if c != nothing
if !(isa(c, Colorant) || (isa(c, Vector) && eltype(c) <: Colorant)) if !(isa(c, Colorant) || (isa(c, Vector) && eltype(c) <: Colorant))
error("Stroke Color not supported: $c") error("Stroke Color not supported: $c")
end end
kw_args[:stroke_color] = c kw_args[:stroke_color] = c
kw_args[:stroke_width] = Float32(d[:markerstrokewidth]) kw_args[:stroke_width] = Float32(plotattributes[:markerstrokewidth])
end end
end end
function _extract_surface(d::Plots.Surface) function _extract_surface(plotattributes::Plots.Surface)
d.surf plotattributes.surf
end end
function _extract_surface(d::AbstractArray) function _extract_surface(plotattributes::AbstractArray)
d plotattributes
end end
# TODO when to transpose?? # TODO when to transpose??
function extract_surface(d) function extract_surface(plotattributes)
map(_extract_surface, (d[:x], d[:y], d[:z])) map(_extract_surface, (plotattributes[:x], plotattributes[:y], plotattributes[:z]))
end end
function topoints(::Type{P}, array) where P function topoints(::Type{P}, array) where P
[P(x) for x in zip(array...)] [P(x) for x in zip(array...)]
end end
function extract_points(d) function extract_points(plotattributes)
dim = is3d(d) ? 3 : 2 dim = is3d(plotattributes) ? 3 : 2
array = if d[:seriestype] == :straightline array = if plotattributes[:seriestype] == :straightline
straightline_data(d) straightline_data(plotattributes)
elseif d[:seriestype] == :shape elseif plotattributes[:seriestype] == :shape
shape_data(d) shape_data(plotattributes)
else else
(d[:x], d[:y], d[:z])[1:dim] (plotattributes[:x], plotattributes[:y], plotattributes[:z])[1:dim]
end end
topoints(Point{dim, Float32}, array) topoints(Point{dim, Float32}, array)
end end
@ -275,50 +275,50 @@ function make_gradient(grad::ColorGradient)
end end
make_gradient(c) = make_gradient(cgrad()) make_gradient(c) = make_gradient(cgrad())
function extract_any_color(d, kw_args) function extract_any_color(plotattributes, kw_args)
if d[:marker_z] == nothing if plotattributes[:marker_z] == nothing
c = scalar_color(d, :fill) c = scalar_color(plotattributes, :fill)
extract_c(d, kw_args, :fill) extract_c(plotattributes, kw_args, :fill)
if isa(c, Colorant) if isa(c, Colorant)
kw_args[:color] = c kw_args[:color] = c
else else
kw_args[:color] = nothing kw_args[:color] = nothing
kw_args[:color_map] = make_gradient(c) kw_args[:color_map] = make_gradient(c)
clims = d[:subplot][:clims] clims = plotattributes[:subplot][:clims]
if Plots.is_2tuple(clims) if Plots.is_2tuple(clims)
if isfinite(clims[1]) && isfinite(clims[2]) if isfinite(clims[1]) && isfinite(clims[2])
kw_args[:color_norm] = Vec2f0(clims) kw_args[:color_norm] = Vec2f0(clims)
end end
elseif clims == :auto elseif clims == :auto
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(d[:y])) kw_args[:color_norm] = Vec2f0(ignorenan_extrema(plotattributes[:y]))
end end
end end
else else
kw_args[:color] = nothing kw_args[:color] = nothing
clims = d[:subplot][:clims] clims = plotattributes[:subplot][:clims]
if Plots.is_2tuple(clims) if Plots.is_2tuple(clims)
if isfinite(clims[1]) && isfinite(clims[2]) if isfinite(clims[1]) && isfinite(clims[2])
kw_args[:color_norm] = Vec2f0(clims) kw_args[:color_norm] = Vec2f0(clims)
end end
elseif clims == :auto elseif clims == :auto
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(d[:y])) kw_args[:color_norm] = Vec2f0(ignorenan_extrema(plotattributes[:y]))
else else
error("Unsupported limits: $clims") error("Unsupported limits: $clims")
end end
kw_args[:intensity] = convert(Vector{Float32}, d[:marker_z]) kw_args[:intensity] = convert(Vector{Float32}, plotattributes[:marker_z])
kw_args[:color_map] = gl_color_map(d, :marker) kw_args[:color_map] = gl_color_map(plotattributes, :marker)
end end
end end
function extract_stroke(d, kw_args) function extract_stroke(plotattributes, kw_args)
extract_c(d, kw_args, :line) extract_c(plotattributes, kw_args, :line)
if haskey(d, :linewidth) if haskey(plotattributes, :linewidth)
kw_args[:thickness] = Float32(d[:linewidth] * 3) kw_args[:thickness] = Float32(plotattributes[:linewidth] * 3)
end end
end end
function extract_color(d, sym) function extract_color(plotattributes, sym)
d[Symbol("$(sym)color")] plotattributes[Symbol("$(sym)color")]
end end
gl_color(c::PlotUtils.ColorGradient) = c.colors gl_color(c::PlotUtils.ColorGradient) = c.colors
@ -335,12 +335,12 @@ function gl_color(c, a)
c = convertColor(c, a) c = convertColor(c, a)
RGBA{Float32}(c) RGBA{Float32}(c)
end end
function scalar_color(d, sym) function scalar_color(plotattributes, sym)
gl_color(extract_color(d, sym)) gl_color(extract_color(plotattributes, sym))
end end
function gl_color_map(d, sym) function gl_color_map(plotattributes, sym)
colors = extract_color(d, sym) colors = extract_color(plotattributes, sym)
_gl_color_map(colors) _gl_color_map(colors)
end end
function _gl_color_map(colors::PlotUtils.ColorGradient) function _gl_color_map(colors::PlotUtils.ColorGradient)
@ -377,10 +377,10 @@ function insert_pattern!(points, kw_args)
kw_args[:pattern] = tex kw_args[:pattern] = tex
kw_args[:pattern_length] = Float32(last(points)) kw_args[:pattern_length] = Float32(last(points))
end end
function extract_linestyle(d, kw_args) function extract_linestyle(plotattributes, kw_args)
haskey(d, :linestyle) || return haskey(plotattributes, :linestyle) || return
ls = d[:linestyle] ls = plotattributes[:linestyle]
lw = d[:linewidth] lw = plotattributes[:linewidth]
kw_args[:thickness] = Float32(lw) kw_args[:thickness] = Float32(lw)
if ls == :dash if ls == :dash
points = [0.0, lw, 2lw, 3lw, 4lw] points = [0.0, lw, 2lw, 3lw, 4lw]
@ -400,7 +400,7 @@ function extract_linestyle(d, kw_args)
points = [0.0, dtick, dtick+dgap, dtick+dgap+ptick, dtick+dgap+ptick+pgap, dtick+dgap+ptick+pgap+ptick, dtick+dgap+ptick+pgap+ptick+pgap] points = [0.0, dtick, dtick+dgap, dtick+dgap+ptick, dtick+dgap+ptick+pgap, dtick+dgap+ptick+pgap+ptick, dtick+dgap+ptick+pgap+ptick+pgap]
insert_pattern!(points, kw_args) insert_pattern!(points, kw_args)
end end
extract_c(d, kw_args, :line) extract_c(plotattributes, kw_args, :line)
nothing nothing
end end
@ -467,8 +467,8 @@ function hover(to_hover, to_display, window)
nothing nothing
end end
function extract_extrema(d, kw_args) function extract_extrema(plotattributes, kw_args)
xmin, xmax = ignorenan_extrema(d[:x]); ymin, ymax = ignorenan_extrema(d[:y]) xmin, xmax = ignorenan_extrema(plotattributes[:x]); ymin, ymax = ignorenan_extrema(plotattributes[:y])
kw_args[:primitive] = GeometryTypes.SimpleRectangle{Float32}(xmin, ymin, xmax-xmin, ymax-ymin) kw_args[:primitive] = GeometryTypes.SimpleRectangle{Float32}(xmin, ymin, xmax-xmin, ymax-ymin)
nothing nothing
end end
@ -479,50 +479,50 @@ function extract_font(font, kw_args)
kw_args[:color] = gl_color(font.color) kw_args[:color] = gl_color(font.color)
end end
function extract_colornorm(d, kw_args) function extract_colornorm(plotattributes, kw_args)
clims = d[:subplot][:clims] clims = plotattributes[:subplot][:clims]
if Plots.is_2tuple(clims) if Plots.is_2tuple(clims)
if isfinite(clims[1]) && isfinite(clims[2]) if isfinite(clims[1]) && isfinite(clims[2])
kw_args[:color_norm] = Vec2f0(clims) kw_args[:color_norm] = Vec2f0(clims)
end end
elseif clims == :auto elseif clims == :auto
z = if haskey(d, :marker_z) && d[:marker_z] != nothing z = if haskey(plotattributes, :marker_z) && plotattributes[:marker_z] != nothing
d[:marker_z] plotattributes[:marker_z]
elseif haskey(d, :line_z) && d[:line_z] != nothing elseif haskey(plotattributes, :line_z) && plotattributes[:line_z] != nothing
d[:line_z] plotattributes[:line_z]
elseif isa(d[:z], Plots.Surface) elseif isa(plotattributes[:z], Plots.Surface)
d[:z].surf plotattributes[:z].surf
else else
d[:y] plotattributes[:y]
end end
kw_args[:color_norm] = Vec2f0(ignorenan_extrema(z)) kw_args[:color_norm] = Vec2f0(ignorenan_extrema(z))
kw_args[:intensity] = map(Float32, collect(z)) kw_args[:intensity] = map(Float32, collect(z))
end end
end end
function extract_gradient(d, kw_args, sym) function extract_gradient(plotattributes, kw_args, sym)
key = Symbol("$(sym)color") key = Symbol("$(sym)color")
haskey(d, key) || return haskey(plotattributes, key) || return
c = make_gradient(d[key]) c = make_gradient(plotattributes[key])
kw_args[:color] = nothing kw_args[:color] = nothing
extract_colornorm(d, kw_args) extract_colornorm(plotattributes, kw_args)
kw_args[:color_map] = c kw_args[:color_map] = c
return return
end end
function extract_c(d, kw_args, sym) function extract_c(plotattributes, kw_args, sym)
key = Symbol("$(sym)color") key = Symbol("$(sym)color")
haskey(d, key) || return haskey(plotattributes, key) || return
c = gl_color(d[key]) c = gl_color(plotattributes[key])
kw_args[:color] = nothing kw_args[:color] = nothing
kw_args[:color_map] = nothing kw_args[:color_map] = nothing
kw_args[:color_norm] = nothing kw_args[:color_norm] = nothing
if ( if (
isa(c, AbstractVector) && isa(c, AbstractVector) &&
((haskey(d, :marker_z) && d[:marker_z] != nothing) || ((haskey(plotattributes, :marker_z) && plotattributes[:marker_z] != nothing) ||
(haskey(d, :line_z) && d[:line_z] != nothing)) (haskey(plotattributes, :line_z) && plotattributes[:line_z] != nothing))
) )
extract_colornorm(d, kw_args) extract_colornorm(plotattributes, kw_args)
kw_args[:color_map] = c kw_args[:color_map] = c
else else
kw_args[:color] = c kw_args[:color] = c
@ -530,16 +530,16 @@ function extract_c(d, kw_args, sym)
return return
end end
function extract_stroke(d, kw_args, sym) function extract_stroke(plotattributes, kw_args, sym)
key = Symbol("$(sym)strokecolor") key = Symbol("$(sym)strokecolor")
haskey(d, key) || return haskey(plotattributes, key) || return
c = gl_color(d[key]) c = gl_color(plotattributes[key])
if c != nothing if c != nothing
if !isa(c, Colorant) if !isa(c, Colorant)
error("Stroke Color not supported: $c") error("Stroke Color not supported: $c")
end end
kw_args[:stroke_color] = c kw_args[:stroke_color] = c
kw_args[:stroke_width] = Float32(d[Symbol("$(sym)strokewidth")]) * 2 kw_args[:stroke_width] = Float32(plotattributes[Symbol("$(sym)strokewidth")]) * 2
end end
return return
end end
@ -551,12 +551,12 @@ function draw_grid_lines(sp, grid_segs, thickness, style, model, color)
kw_args = Dict{Symbol, Any}( kw_args = Dict{Symbol, Any}(
:model => model :model => model
) )
d = Dict( plotattributes = Dict(
:linestyle => style, :linestyle => style,
:linewidth => Float32(thickness), :linewidth => Float32(thickness),
:linecolor => color :linecolor => color
) )
Plots.extract_linestyle(d, kw_args) Plots.extract_linestyle(plotattributes, kw_args)
GL.gl_lines(map(Point2f0, grid_segs.pts), kw_args) GL.gl_lines(map(Point2f0, grid_segs.pts), kw_args)
end end
@ -808,10 +808,10 @@ function gl_draw_axes_3d(sp, model)
) )
end end
function gl_bar(d, kw_args) function gl_bar(plotattributes, kw_args)
x, y = d[:x], d[:y] x, y = plotattributes[:x], plotattributes[:y]
nx, ny = length(x), length(y) nx, ny = length(x), length(y)
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis] axis = plotattributes[:subplot][isvertical(plotattributes) ? :xaxis : :yaxis]
cv = [discrete_value!(axis, xi)[1] for xi=x] cv = [discrete_value!(axis, xi)[1] for xi=x]
x = if nx == ny x = if nx == ny
cv cv
@ -832,7 +832,7 @@ function gl_bar(d, kw_args)
end end
# make fillto a vector... default fills to 0 # make fillto a vector... default fills to 0
fillto = d[:fillrange] fillto = plotattributes[:fillrange]
if fillto == nothing if fillto == nothing
fillto = 0 fillto = 0
end end
@ -843,7 +843,7 @@ function gl_bar(d, kw_args)
for i=1:ny for i=1:ny
center = x[i] center = x[i]
hwi = abs(_cycle(hw,i)); yi = y[i]; fi = _cycle(fillto,i) hwi = abs(_cycle(hw,i)); yi = y[i]; fi = _cycle(fillto,i)
if Plots.isvertical(d) if Plots.isvertical(plotattributes)
sz = (hwi*sx, yi*sy) sz = (hwi*sx, yi*sy)
else else
sz = (yi*sx, hwi*2*sy) sz = (yi*sx, hwi*2*sy)
@ -862,10 +862,10 @@ const _box_halfwidth = 0.4
notch_width(q2, q4, N) = 1.58 * (q4-q2)/sqrt(N) notch_width(q2, q4, N) = 1.58 * (q4-q2)/sqrt(N)
function gl_boxplot(d, kw_args) function gl_boxplot(plotattributes, kw_args)
kwbox = copy(kw_args) kwbox = copy(kw_args)
range = 1.5; notch = false range = 1.5; notch = false
x, y = d[:x], d[:y] x, y = plotattributes[:x], plotattributes[:y]
glabels = sort(collect(unique(x))) glabels = sort(collect(unique(x)))
warning = false warning = false
outliers_x, outliers_y = zeros(0), zeros(0) outliers_x, outliers_y = zeros(0), zeros(0)
@ -890,8 +890,8 @@ function gl_boxplot(d, kw_args)
end end
# make the shape # make the shape
center = Plots.discrete_value!(d[:subplot][:xaxis], glabel)[1] center = Plots.discrete_value!(plotattributes[:subplot][:xaxis], glabel)[1]
hw = d[:bar_width] == nothing ? Plots._box_halfwidth*2 : _cycle(d[:bar_width], i) hw = plotattributes[:bar_width] == nothing ? Plots._box_halfwidth*2 : _cycle(plotattributes[:bar_width], i)
l, m, r = center - hw/2, center, center + hw/2 l, m, r = center - hw/2, center, center + hw/2
# internal nodes for notches # internal nodes for notches
@ -930,17 +930,17 @@ function gl_boxplot(d, kw_args)
:model => kw_args[:model], :model => kw_args[:model],
:offset => Vec2f0(0), :offset => Vec2f0(0),
) )
extract_marker(d, kw_args) extract_marker(plotattributes, kw_args)
outlier_kw = Dict( outlier_kw = Dict(
:model => kw_args[:model], :model => kw_args[:model],
:color => scalar_color(d, :fill), :color => scalar_color(plotattributes, :fill),
:stroke_width => Float32(d[:markerstrokewidth]), :stroke_width => Float32(plotattributes[:markerstrokewidth]),
:stroke_color => scalar_color(d, :markerstroke), :stroke_color => scalar_color(plotattributes, :markerstroke),
) )
lines_kw = Dict( lines_kw = Dict(
:model => kw_args[:model], :model => kw_args[:model],
:stroke_width => d[:linewidth], :stroke_width => plotattributes[:linewidth],
:stroke_color => scalar_color(d, :fill), :stroke_color => scalar_color(plotattributes, :fill),
) )
vis1 = GLVisualize.visualize((GLVisualize.RECTANGLE, box_pos), Style(:default), kwbox) vis1 = GLVisualize.visualize((GLVisualize.RECTANGLE, box_pos), Style(:default), kwbox)
vis2 = GLVisualize.visualize((GLVisualize.CIRCLE, outliers), Style(:default), outlier_kw) vis2 = GLVisualize.visualize((GLVisualize.CIRCLE, outliers), Style(:default), outlier_kw)
@ -1066,8 +1066,8 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
end end
for series in Plots.series_list(sp) for series in Plots.series_list(sp)
d = series.d plotattributes = series.plotattributes
st = d[:seriestype]; kw_args = KW() # exctract kw st = plotattributes[:seriestype]; kw_args = KW() # exctract kw
kw_args[:model] = model_m # add transformation kw_args[:model] = model_m # add transformation
if !_3d # 3D is treated differently, since we need boundingboxes for camera if !_3d # 3D is treated differently, since we need boundingboxes for camera
@ -1075,76 +1075,76 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
end end
scale_for_annotations!(series) scale_for_annotations!(series)
if st in (:surface, :wireframe) if st in (:surface, :wireframe)
x, y, z = extract_surface(d) x, y, z = extract_surface(plotattributes)
extract_gradient(d, kw_args, :fill) extract_gradient(plotattributes, kw_args, :fill)
z = Plots.transpose_z(d, z, false) z = Plots.transpose_z(plotattributes, z, false)
if isa(x, AbstractMatrix) && isa(y, AbstractMatrix) if isa(x, AbstractMatrix) && isa(y, AbstractMatrix)
x, y = Plots.transpose_z(d, x, false), Plots.transpose_z(d, y, false) x, y = Plots.transpose_z(plotattributes, x, false), Plots.transpose_z(plotattributes, y, false)
end end
if st == :wireframe if st == :wireframe
kw_args[:wireframe] = true kw_args[:wireframe] = true
kw_args[:stroke_color] = d[:linecolor] kw_args[:stroke_color] = plotattributes[:linecolor]
kw_args[:stroke_width] = Float32(d[:linewidth]/100f0) kw_args[:stroke_width] = Float32(plotattributes[:linewidth]/100f0)
end end
vis = GL.gl_surface(x, y, z, kw_args) vis = GL.gl_surface(x, y, z, kw_args)
elseif (st in (:path, :path3d, :straightline)) && d[:linewidth] > 0 elseif (st in (:path, :path3d, :straightline)) && plotattributes[:linewidth] > 0
kw = copy(kw_args) kw = copy(kw_args)
points = Plots.extract_points(d) points = Plots.extract_points(plotattributes)
extract_linestyle(d, kw) extract_linestyle(plotattributes, kw)
vis = GL.gl_lines(points, kw) vis = GL.gl_lines(points, kw)
if d[:markershape] != :none if plotattributes[:markershape] != :none
kw = copy(kw_args) kw = copy(kw_args)
extract_stroke(d, kw) extract_stroke(plotattributes, kw)
extract_marker(d, kw) extract_marker(plotattributes, kw)
vis2 = GL.gl_scatter(copy(points), kw) vis2 = GL.gl_scatter(copy(points), kw)
vis = [vis; vis2] vis = [vis; vis2]
end end
if d[:fillrange] != nothing if plotattributes[:fillrange] != nothing
kw = copy(kw_args) kw = copy(kw_args)
fr = d[:fillrange] fr = plotattributes[:fillrange]
ps = if all(x-> x >= 0, diff(d[:x])) # if is monotonic ps = if all(x-> x >= 0, diff(plotattributes[:x])) # if is monotonic
vcat(points, Point2f0[(points[i][1], _cycle(fr, i)) for i=length(points):-1:1]) vcat(points, Point2f0[(points[i][1], _cycle(fr, i)) for i=length(points):-1:1])
else else
points points
end end
extract_c(d, kw, :fill) extract_c(plotattributes, kw, :fill)
vis = [GL.gl_poly(ps, kw), vis] vis = [GL.gl_poly(ps, kw), vis]
end end
elseif st in (:scatter, :scatter3d) #|| d[:markershape] != :none elseif st in (:scatter, :scatter3d) #|| plotattributes[:markershape] != :none
extract_marker(d, kw_args) extract_marker(plotattributes, kw_args)
points = extract_points(d) points = extract_points(plotattributes)
vis = GL.gl_scatter(points, kw_args) vis = GL.gl_scatter(points, kw_args)
elseif st == :shape elseif st == :shape
extract_c(d, kw_args, :fill) extract_c(plotattributes, kw_args, :fill)
vis = GL.gl_shape(d, kw_args) vis = GL.gl_shape(plotattributes, kw_args)
elseif st == :contour elseif st == :contour
x,y,z = extract_surface(d) x,y,z = extract_surface(plotattributes)
z = transpose_z(d, z, false) z = transpose_z(plotattributes, z, false)
extract_extrema(d, kw_args) extract_extrema(plotattributes, kw_args)
extract_gradient(d, kw_args, :fill) extract_gradient(plotattributes, kw_args, :fill)
kw_args[:fillrange] = d[:fillrange] kw_args[:fillrange] = plotattributes[:fillrange]
kw_args[:levels] = d[:levels] kw_args[:levels] = plotattributes[:levels]
vis = GL.gl_contour(x,y,z, kw_args) vis = GL.gl_contour(x,y,z, kw_args)
elseif st == :heatmap elseif st == :heatmap
x,y,z = extract_surface(d) x,y,z = extract_surface(plotattributes)
extract_gradient(d, kw_args, :fill) extract_gradient(plotattributes, kw_args, :fill)
extract_extrema(d, kw_args) extract_extrema(plotattributes, kw_args)
extract_limits(sp, d, kw_args) extract_limits(sp, plotattributes, kw_args)
vis = GL.gl_heatmap(x,y,z, kw_args) vis = GL.gl_heatmap(x,y,z, kw_args)
elseif st == :bar elseif st == :bar
extract_c(d, kw_args, :fill) extract_c(plotattributes, kw_args, :fill)
extract_stroke(d, kw_args, :marker) extract_stroke(plotattributes, kw_args, :marker)
vis = gl_bar(d, kw_args) vis = gl_bar(plotattributes, kw_args)
elseif st == :image elseif st == :image
extract_extrema(d, kw_args) extract_extrema(plotattributes, kw_args)
vis = GL.gl_image(d[:z].surf, kw_args) vis = GL.gl_image(plotattributes[:z].surf, kw_args)
elseif st == :boxplot elseif st == :boxplot
extract_c(d, kw_args, :fill) extract_c(plotattributes, kw_args, :fill)
vis = gl_boxplot(d, kw_args) vis = gl_boxplot(plotattributes, kw_args)
elseif st == :volume elseif st == :volume
volume = d[:y] volume = plotattributes[:y]
_d = copy(d) _d = copy(plotattributes)
_d[:y] = 0:1 _d[:y] = 0:1
_d[:x] = 0:1 _d[:x] = 0:1
kw_args = KW() kw_args = KW()
@ -1157,15 +1157,15 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
isa(vis, Array) && isempty(vis) && continue # nothing to see here isa(vis, Array) && isempty(vis) && continue # nothing to see here
GLVisualize._view(vis, sp_screen, camera=:perspective) GLVisualize._view(vis, sp_screen, camera=:perspective)
if haskey(d, :hover) && !(d[:hover] in (false, :none, nothing)) if haskey(plotattributes, :hover) && !(plotattributes[:hover] in (false, :none, nothing))
hover(vis, d[:hover], sp_screen) hover(vis, plotattributes[:hover], sp_screen)
end end
if isdefined(:GLPlot) && isdefined(Main.GLPlot, :(register_plot!)) if isdefined(:GLPlot) && isdefined(Main.GLPlot, :(register_plot!))
del_signal = Main.GLPlot.register_plot!(vis, sp_screen, create_gizmo=false) del_signal = Main.GLPlot.register_plot!(vis, sp_screen, create_gizmo=false)
append!(_glplot_deletes, del_signal) append!(_glplot_deletes, del_signal)
end end
anns = series[:series_annotations] anns = series[:series_annotations]
for (x, y, str, font) in EachAnn(anns, d[:x], d[:y]) for (x, y, str, font) in EachAnn(anns, plotattributes[:x], plotattributes[:y])
txt_args = Dict{Symbol, Any}(:model => eye(GLAbstraction.Mat4f0)) txt_args = Dict{Symbol, Any}(:model => eye(GLAbstraction.Mat4f0))
x, y = Reactive.value(model_m) * GeometryTypes.Vec{4, Float32}(x, y, 0, 1) x, y = Reactive.value(model_m) * GeometryTypes.Vec{4, Float32}(x, y, 0, 1)
extract_font(font, txt_args) extract_font(font, txt_args)
@ -1241,10 +1241,10 @@ function gl_lines(points, kw_args)
return result return result
end end
function gl_shape(d, kw_args) function gl_shape(plotattributes, kw_args)
points = Plots.extract_points(d) points = Plots.extract_points(plotattributes)
result = [] result = []
for rng in iter_segments(d[:x], d[:y]) for rng in iter_segments(plotattributes[:x], plotattributes[:y])
ps = points[rng] ps = points[rng]
meshes = gl_poly(ps, kw_args) meshes = gl_poly(ps, kw_args)
append!(result, meshes) append!(result, meshes)
@ -1398,10 +1398,10 @@ end
""" """
Ugh, so much special casing (╯°□°)╯︵ ┻━┻ Ugh, so much special casing (╯°□°)╯︵ ┻━┻
""" """
function label_scatter(d, w, ho) function label_scatter(plotattributes, w, ho)
kw = KW() kw = KW()
extract_stroke(d, kw) extract_stroke(plotattributes, kw)
extract_marker(d, kw) extract_marker(plotattributes, kw)
kw[:scale] = Vec2f0(w/2) kw[:scale] = Vec2f0(w/2)
kw[:offset] = Vec2f0(-w/4) kw[:offset] = Vec2f0(-w/4)
if haskey(kw, :intensity) if haskey(kw, :intensity)
@ -1442,21 +1442,21 @@ function make_label(sp, series, i)
GL = Plots GL = Plots
w, gap, ho = 20f0, 5f0, 5 w, gap, ho = 20f0, 5f0, 5
result = [] result = []
d = series.d plotattributes = series.plotattributes
st = d[:seriestype] st = plotattributes[:seriestype]
kw_args = KW() kw_args = KW()
if (st in (:path, :path3d, :straightline)) && d[:linewidth] > 0 if (st in (:path, :path3d, :straightline)) && plotattributes[:linewidth] > 0
points = Point2f0[(0, ho), (w, ho)] points = Point2f0[(0, ho), (w, ho)]
kw = KW() kw = KW()
extract_linestyle(d, kw) extract_linestyle(plotattributes, kw)
append!(result, GL.gl_lines(points, kw)) append!(result, GL.gl_lines(points, kw))
if d[:markershape] != :none if plotattributes[:markershape] != :none
push!(result, label_scatter(d, w, ho)) push!(result, label_scatter(plotattributes, w, ho))
end end
elseif st in (:scatter, :scatter3d) #|| d[:markershape] != :none elseif st in (:scatter, :scatter3d) #|| plotattributes[:markershape] != :none
push!(result, label_scatter(d, w, ho)) push!(result, label_scatter(plotattributes, w, ho))
else else
extract_c(d, kw_args, :fill) extract_c(plotattributes, kw_args, :fill)
if isa(kw_args[:color], AbstractVector) if isa(kw_args[:color], AbstractVector)
kw_args[:color] = first(kw_args[:color]) kw_args[:color] = first(kw_args[:color])
end end

View File

@ -148,7 +148,7 @@ _hdf5_map_str2telem(v::Vector) = HDF5PLOT_MAP_STR2TELEM[v[1]]
function _hdf5_merge!(dest::Dict, src::Dict) function _hdf5_merge!(dest::Dict, src::Dict)
for (k, v) in src for (k, v) in src
if isa(v, Axis) if isa(v, Axis)
_hdf5_merge!(dest[k].d, v.d) _hdf5_merge!(dest[k].plotattributes, v.plotattributes)
else else
dest[k] = v dest[k] = v
end end
@ -215,7 +215,7 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations]) # Override this to update plot items (title, xlabel, etc), and add annotations (plotattributes[:annotations])
function _update_plot_object(plt::Plot{HDF5Backend}) function _update_plot_object(plt::Plot{HDF5Backend})
#Do nothing #Do nothing
end end
@ -323,8 +323,8 @@ function _hdf5plot_gwrite(grp, k::String, v::Tuple)
end end
#NOTE: _hdf5plot_overwritetype overwrites "Array" type with "Tuple". #NOTE: _hdf5plot_overwritetype overwrites "Array" type with "Tuple".
end end
function _hdf5plot_gwrite(grp, k::String, d::Dict) function _hdf5plot_gwrite(grp, k::String, plotattributes::Dict)
# @warn("Cannot write dict: $k=$d") # @warn("Cannot write dict: $k=$plotattributes")
end end
function _hdf5plot_gwrite(grp, k::String, v::AbstractRange) function _hdf5plot_gwrite(grp, k::String, v::AbstractRange)
_hdf5plot_gwrite(grp, k, collect(v)) #For now _hdf5plot_gwrite(grp, k, collect(v)) #For now
@ -380,7 +380,7 @@ function _hdf5plot_gwrite(grp, k::String, v::HDF5PLOT_SIMPLESUBSTRUCT)
end end
function _hdf5plot_gwrite(grp, k::String, v::Axis) function _hdf5plot_gwrite(grp, k::String, v::Axis)
grp = HDF5.g_create(grp, k) grp = HDF5.g_create(grp, k)
for (_k, _v) in v.d for (_k, _v) in v.plotattributes
kstr = string(_k) kstr = string(_k)
_hdf5plot_gwrite(grp, kstr, _v) _hdf5plot_gwrite(grp, kstr, _v)
end end
@ -412,8 +412,8 @@ function _hdf5plot_gwrite(grp, k::String, v::Subplot)
_hdf5plot_writetype(grp, Subplot) _hdf5plot_writetype(grp, Subplot)
return return
end end
function _hdf5plot_write(grp, d::Dict) function _hdf5plot_write(grp, plotattributes::Dict)
for (k, v) in d for (k, v) in plotattributes
kstr = string(k) kstr = string(k)
_hdf5plot_gwrite(grp, kstr, v) _hdf5plot_gwrite(grp, kstr, v)
end end
@ -431,7 +431,7 @@ function _hdf5plot_write(sp::Subplot{HDF5Backend}, subpath::String, f)
_hdf5plot_writecount(grp, length(sp.series_list)) _hdf5plot_writecount(grp, length(sp.series_list))
for (i, series) in enumerate(sp.series_list) for (i, series) in enumerate(sp.series_list)
grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list/series$i")) grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list/series$i"))
_hdf5plot_write(grp, series.d) _hdf5plot_write(grp, series.plotattributes)
end end
return return
@ -579,13 +579,13 @@ function _hdf5plot_read(grp, k::String)
return _hdf5plot_read(grp, k, T, dtid) return _hdf5plot_read(grp, k, T, dtid)
end end
#Read in values in group to populate d: #Read in values in group to populate plotattributes:
function _hdf5plot_read(grp, d::Dict) function _hdf5plot_read(grp, plotattributes::Dict)
gnames = names(grp) gnames = names(grp)
for k in gnames for k in gnames
try try
v = _hdf5plot_read(grp, k) v = _hdf5plot_read(grp, k)
d[Symbol(k)] = v plotattributes[Symbol(k)] = v
catch e catch e
@show e @show e
@show grp @show grp
@ -614,7 +614,7 @@ function _hdf5plot_read(sp::Subplot, subpath::String, f)
kwlist = KW() kwlist = KW()
_hdf5plot_read(grp, kwlist) _hdf5plot_read(grp, kwlist)
plot!(sp, kwlist[:x], kwlist[:y]) #Add data & create data structures plot!(sp, kwlist[:x], kwlist[:y]) #Add data & create data structures
_hdf5_merge!(sp.series_list[end].d, kwlist) _hdf5_merge!(sp.series_list[end].plotattributes, kwlist)
end end
return return

View File

@ -457,7 +457,7 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations]) # Override this to update plot items (title, xlabel, etc), and add annotations (plotattributes[:annotations])
function _update_plot_object(plt::Plot{InspectDRBackend}) function _update_plot_object(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o) mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end if nothing == mplot; return; end

View File

@ -133,9 +133,9 @@ pgf_thickness_scaling(plt::Plot) = plt[:thickness_scaling]
pgf_thickness_scaling(sp::Subplot) = pgf_thickness_scaling(sp.plt) pgf_thickness_scaling(sp::Subplot) = pgf_thickness_scaling(sp.plt)
pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot]) pgf_thickness_scaling(series) = pgf_thickness_scaling(series[:subplot])
function pgf_fillstyle(d, i = 1) function pgf_fillstyle(plotattributes, i = 1)
cstr,a = pgf_color(get_fillcolor(d, i)) cstr,a = pgf_color(get_fillcolor(plotattributes, i))
fa = get_fillalpha(d, i) fa = get_fillalpha(plotattributes, i)
if fa != nothing if fa != nothing
a = fa a = fa
end end
@ -151,11 +151,11 @@ function pgf_linestyle(linewidth::Real, color, α = 1, linestyle = "solid")
$(get(_pgfplots_linestyles, linestyle, "solid"))""" $(get(_pgfplots_linestyles, linestyle, "solid"))"""
end end
function pgf_linestyle(d, i = 1) function pgf_linestyle(plotattributes, i = 1)
lw = pgf_thickness_scaling(d) * get_linewidth(d, i) lw = pgf_thickness_scaling(plotattributes) * get_linewidth(plotattributes, i)
lc = get_linecolor(d, i) lc = get_linecolor(plotattributes, i)
la = get_linealpha(d, i) la = get_linealpha(plotattributes, i)
ls = get_linestyle(d, i) ls = get_linestyle(plotattributes, i)
return pgf_linestyle(lw, lc, la, ls) return pgf_linestyle(lw, lc, la, ls)
end end
@ -164,19 +164,19 @@ function pgf_font(fontsize, thickness_scaling = 1, font = "\\selectfont")
return string("{\\fontsize{", fs, " pt}{", 1.3fs, " pt}", font, "}") return string("{\\fontsize{", fs, " pt}{", 1.3fs, " pt}", font, "}")
end end
function pgf_marker(d, i = 1) function pgf_marker(plotattributes, i = 1)
shape = _cycle(d[:markershape], i) shape = _cycle(plotattributes[:markershape], i)
cstr, a = pgf_color(plot_color(get_markercolor(d, i), get_markeralpha(d, i))) cstr, a = pgf_color(plot_color(get_markercolor(plotattributes, i), get_markeralpha(plotattributes, i)))
cstr_stroke, a_stroke = pgf_color(plot_color(get_markerstrokecolor(d, i), get_markerstrokealpha(d, i))) cstr_stroke, a_stroke = pgf_color(plot_color(get_markerstrokecolor(plotattributes, i), get_markerstrokealpha(plotattributes, i)))
""" """
mark = $(get(_pgfplots_markers, shape, "*")), mark = $(get(_pgfplots_markers, shape, "*")),
mark size = $(pgf_thickness_scaling(d) * 0.5 * _cycle(d[:markersize], i)), mark size = $(pgf_thickness_scaling(plotattributes) * 0.5 * _cycle(plotattributes[:markersize], i)),
mark options = { mark options = {
color = $cstr_stroke, draw opacity = $a_stroke, color = $cstr_stroke, draw opacity = $a_stroke,
fill = $cstr, fill opacity = $a, fill = $cstr, fill opacity = $a,
line width = $(pgf_thickness_scaling(d) * _cycle(d[:markerstrokewidth], i)), line width = $(pgf_thickness_scaling(plotattributes) * _cycle(plotattributes[:markerstrokewidth], i)),
rotate = $(shape == :dtriangle ? 180 : 0), rotate = $(shape == :dtriangle ? 180 : 0),
$(get(_pgfplots_linestyles, _cycle(d[:markerstrokestyle], i), "solid")) $(get(_pgfplots_linestyles, _cycle(plotattributes[:markerstrokestyle], i), "solid"))
}""" }"""
end end
@ -197,24 +197,24 @@ end
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
function pgf_series(sp::Subplot, series::Series) function pgf_series(sp::Subplot, series::Series)
d = series.d plotattributes = series.plotattributes
st = d[:seriestype] st = plotattributes[:seriestype]
series_collection = PGFPlots.Plot[] series_collection = PGFPlots.Plot[]
# function args # function args
args = if st == :contour args = if st == :contour
d[:z].surf, d[:x], d[:y] plotattributes[:z].surf, plotattributes[:x], plotattributes[:y]
elseif is3d(st) elseif is3d(st)
d[:x], d[:y], d[:z] plotattributes[:x], plotattributes[:y], plotattributes[:z]
elseif st == :straightline elseif st == :straightline
straightline_data(series) straightline_data(series)
elseif st == :shape elseif st == :shape
shape_data(series) shape_data(series)
elseif ispolar(sp) elseif ispolar(sp)
theta, r = filter_radial_data(d[:x], d[:y], axis_limits(sp[:yaxis])) theta, r = filter_radial_data(plotattributes[:x], plotattributes[:y], axis_limits(sp[:yaxis]))
rad2deg.(theta), r rad2deg.(theta), r
else else
d[:x], d[:y] plotattributes[:x], plotattributes[:y]
end end
# PGFPlots can't handle non-Vector? # PGFPlots can't handle non-Vector?
@ -227,8 +227,8 @@ function pgf_series(sp::Subplot, series::Series)
if st in (:contour, :histogram2d) if st in (:contour, :histogram2d)
style = [] style = []
kw = KW() kw = KW()
push!(style, pgf_linestyle(d)) push!(style, pgf_linestyle(plotattributes))
push!(style, pgf_marker(d)) push!(style, pgf_marker(plotattributes))
push!(style, "forget plot") push!(style, "forget plot")
kw[:style] = join(style, ',') kw[:style] = join(style, ',')
@ -247,21 +247,21 @@ function pgf_series(sp::Subplot, series::Series)
for (i, rng) in enumerate(segments) for (i, rng) in enumerate(segments)
style = [] style = []
kw = KW() kw = KW()
push!(style, pgf_linestyle(d, i)) push!(style, pgf_linestyle(plotattributes, i))
push!(style, pgf_marker(d, i)) push!(style, pgf_marker(plotattributes, i))
if st == :shape if st == :shape
push!(style, pgf_fillstyle(d, i)) push!(style, pgf_fillstyle(plotattributes, i))
end end
# add to legend? # add to legend?
if i == 1 && sp[:legend] != :none && should_add_to_legend(series) if i == 1 && sp[:legend] != :none && should_add_to_legend(series)
if d[:fillrange] != nothing if plotattributes[:fillrange] != nothing
push!(style, "forget plot") push!(style, "forget plot")
push!(series_collection, pgf_fill_legend_hack(d, args)) push!(series_collection, pgf_fill_legend_hack(plotattributes, args))
else else
kw[:legendentry] = d[:label] kw[:legendentry] = plotattributes[:label]
if st == :shape # || d[:fillrange] != nothing if st == :shape # || plotattributes[:fillrange] != nothing
push!(style, "area legend") push!(style, "area legend")
end end
end end
@ -328,16 +328,16 @@ function pgf_fillrange_args(fillrange, x, y, z)
return x_fill, y_fill, z_fill return x_fill, y_fill, z_fill
end end
function pgf_fill_legend_hack(d, args) function pgf_fill_legend_hack(plotattributes, args)
style = [] style = []
kw = KW() kw = KW()
push!(style, pgf_linestyle(d, 1)) push!(style, pgf_linestyle(plotattributes, 1))
push!(style, pgf_marker(d, 1)) push!(style, pgf_marker(plotattributes, 1))
push!(style, pgf_fillstyle(d, 1)) push!(style, pgf_fillstyle(plotattributes, 1))
push!(style, "area legend") push!(style, "area legend")
kw[:legendentry] = d[:label] kw[:legendentry] = plotattributes[:label]
kw[:style] = join(style, ',') kw[:style] = join(style, ',')
st = d[:seriestype] st = plotattributes[:seriestype]
func = if st == :path3d func = if st == :path3d
PGFPlots.Linear3 PGFPlots.Linear3
elseif st == :scatter elseif st == :scatter
@ -535,8 +535,8 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
# colormap this should not cause any problem. # colormap this should not cause any problem.
for series in series_list(sp) for series in series_list(sp)
for col in (:markercolor, :fillcolor, :linecolor) for col in (:markercolor, :fillcolor, :linecolor)
if typeof(series.d[col]) == ColorGradient if typeof(series.plotattributes[col]) == ColorGradient
push!(style,"colormap={plots}{$(pgf_colormap(series.d[col]))}") push!(style,"colormap={plots}{$(pgf_colormap(series.plotattributes[col]))}")
if sp[:colorbar] == :none if sp[:colorbar] == :none
kw[:colorbar] = "false" kw[:colorbar] = "false"

View File

@ -149,7 +149,7 @@ function plotly_annotation_dict(x, y, ptxt::PlotText; xref="paper", yref="paper"
)) ))
end end
# function get_annotation_dict_for_arrow(d::KW, xyprev::Tuple, xy::Tuple, a::Arrow) # function get_annotation_dict_for_arrow(plotattributes::KW, xyprev::Tuple, xy::Tuple, a::Arrow)
# xdiff = xyprev[1] - xy[1] # xdiff = xyprev[1] - xy[1]
# ydiff = xyprev[2] - xy[2] # ydiff = xyprev[2] - xy[2]
# dist = sqrt(xdiff^2 + ydiff^2) # dist = sqrt(xdiff^2 + ydiff^2)
@ -163,7 +163,7 @@ end
# # :ay => -40, # # :ay => -40,
# :ax => 10xdiff / dist, # :ax => 10xdiff / dist,
# :ay => -10ydiff / dist, # :ay => -10ydiff / dist,
# :arrowcolor => rgba_string(d[:linecolor]), # :arrowcolor => rgba_string(plotattributes[:linecolor]),
# :xref => "x", # :xref => "x",
# :yref => "y", # :yref => "y",
# :arrowsize => 10a.headwidth, # :arrowsize => 10a.headwidth,
@ -306,14 +306,14 @@ function plotly_polaraxis(axis::Axis)
end end
function plotly_layout(plt::Plot) function plotly_layout(plt::Plot)
d_out = KW() plotattributes_out = KW()
w, h = plt[:size] w, h = plt[:size]
d_out[:width], d_out[:height] = w, h plotattributes_out[:width], plotattributes_out[:height] = w, h
d_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside]) plotattributes_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
d_out[:margin] = KW(:l=>0, :b=>20, :r=>0, :t=>20) plotattributes_out[:margin] = KW(:l=>0, :b=>20, :r=>0, :t=>20)
d_out[:annotations] = KW[] plotattributes_out[:annotations] = KW[]
multiple_subplots = length(plt.subplots) > 1 multiple_subplots = length(plt.subplots) > 1
@ -334,10 +334,10 @@ function plotly_layout(plt::Plot)
end end
titlex, titley = xy_mm_to_pcts(xmm, top(bbox(sp)), w*px, h*px) titlex, titley = xy_mm_to_pcts(xmm, top(bbox(sp)), w*px, h*px)
title_font = font(titlefont(sp), :top) title_font = font(titlefont(sp), :top)
push!(d_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], title_font))) push!(plotattributes_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], title_font)))
end end
d_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside]) plotattributes_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside])
# set to supported framestyle # set to supported framestyle
sp[:framestyle] = _plotly_framestyle(sp[:framestyle]) sp[:framestyle] = _plotly_framestyle(sp[:framestyle])
@ -346,7 +346,7 @@ function plotly_layout(plt::Plot)
if is3d(sp) if is3d(sp)
azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour
theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis
d_out[:scene] = KW( plotattributes_out[:scene] = KW(
Symbol("xaxis$(spidx)") => plotly_axis(plt, sp[:xaxis], sp), Symbol("xaxis$(spidx)") => plotly_axis(plt, sp[:xaxis], sp),
Symbol("yaxis$(spidx)") => plotly_axis(plt, sp[:yaxis], sp), Symbol("yaxis$(spidx)") => plotly_axis(plt, sp[:yaxis], sp),
Symbol("zaxis$(spidx)") => plotly_axis(plt, sp[:zaxis], sp), Symbol("zaxis$(spidx)") => plotly_axis(plt, sp[:zaxis], sp),
@ -361,19 +361,19 @@ function plotly_layout(plt::Plot)
), ),
) )
elseif ispolar(sp) elseif ispolar(sp)
d_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp[:xaxis]) plotattributes_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp[:xaxis])
d_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp[:yaxis]) plotattributes_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp[:yaxis])
else else
d_out[Symbol("xaxis$(x_idx)")] = plotly_axis(plt, sp[:xaxis], sp) plotattributes_out[Symbol("xaxis$(x_idx)")] = plotly_axis(plt, sp[:xaxis], sp)
# don't allow yaxis to be reupdated/reanchored in a linked subplot # don't allow yaxis to be reupdated/reanchored in a linked subplot
spidx == y_idx ? d_out[Symbol("yaxis$(y_idx)")] = plotly_axis(plt, sp[:yaxis], sp) : nothing spidx == y_idx ? plotattributes_out[Symbol("yaxis$(y_idx)")] = plotly_axis(plt, sp[:yaxis], sp) : nothing
end end
# legend # legend
d_out[:showlegend] = sp[:legend] != :none plotattributes_out[:showlegend] = sp[:legend] != :none
xpos,ypos = plotly_legend_pos(sp[:legend]) xpos,ypos = plotly_legend_pos(sp[:legend])
if sp[:legend] != :none if sp[:legend] != :none
d_out[:legend] = KW( plotattributes_out[:legend] = KW(
:bgcolor => rgba_string(sp[:background_color_legend]), :bgcolor => rgba_string(sp[:background_color_legend]),
:bordercolor => rgba_string(sp[:foreground_color_legend]), :bordercolor => rgba_string(sp[:foreground_color_legend]),
:font => plotly_font(legendfont(sp)), :font => plotly_font(legendfont(sp)),
@ -385,13 +385,13 @@ function plotly_layout(plt::Plot)
# annotations # annotations
for ann in sp[:annotations] for ann in sp[:annotations]
append!(d_out[:annotations], KW[plotly_annotation_dict(locate_annotation(sp, ann...)...; xref = "x$(x_idx)", yref = "y$(y_idx)")]) append!(plotattributes_out[:annotations], KW[plotly_annotation_dict(locate_annotation(sp, ann...)...; xref = "x$(x_idx)", yref = "y$(y_idx)")])
end end
# series_annotations # series_annotations
for series in series_list(sp) for series in series_list(sp)
anns = series[:series_annotations] anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y]) for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
push!(d_out[:annotations], plotly_annotation_dict( push!(plotattributes_out[:annotations], plotly_annotation_dict(
xi, xi,
yi, yi,
PlotText(str,fnt); xref = "x$(x_idx)", yref = "y$(y_idx)") PlotText(str,fnt); xref = "x$(x_idx)", yref = "y$(y_idx)")
@ -404,24 +404,24 @@ function plotly_layout(plt::Plot)
# a = sargs[:arrow] # a = sargs[:arrow]
# if sargs[:seriestype] in (:path, :line) && typeof(a) <: Arrow # if sargs[:seriestype] in (:path, :line) && typeof(a) <: Arrow
# add_arrows(sargs[:x], sargs[:y]) do xyprev, xy # add_arrows(sargs[:x], sargs[:y]) do xyprev, xy
# push!(d_out[:annotations], get_annotation_dict_for_arrow(sargs, xyprev, xy, a)) # push!(plotattributes_out[:annotations], get_annotation_dict_for_arrow(sargs, xyprev, xy, a))
# end # end
# end # end
# end # end
if ispolar(sp) if ispolar(sp)
d_out[:direction] = "counterclockwise" plotattributes_out[:direction] = "counterclockwise"
end end
d_out plotattributes_out
end end
# turn off hover if nothing's using it # turn off hover if nothing's using it
if all(series -> series.d[:hover] in (false,:none), plt.series_list) if all(series -> series.plotattributes[:hover] in (false,:none), plt.series_list)
d_out[:hovermode] = "none" plotattributes_out[:hovermode] = "none"
end end
d_out plotattributes_out
end end
function plotly_layout_json(plt::Plot) function plotly_layout_json(plt::Plot)
@ -527,7 +527,7 @@ end
as_gradient(grad::ColorGradient, α) = grad as_gradient(grad::ColorGradient, α) = grad
as_gradient(grad, α) = cgrad(alpha = α) as_gradient(grad, α) = cgrad(alpha = α)
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict) # get a dictionary representing the series params (plotattributes is the Plots-dict, plotattributes_out is the Plotly-dict)
function plotly_series(plt::Plot, series::Series) function plotly_series(plt::Plot, series::Series)
st = series[:seriestype] st = series[:seriestype]
@ -538,13 +538,13 @@ function plotly_series(plt::Plot, series::Series)
return plotly_series_shapes(plt, series, clims) return plotly_series_shapes(plt, series, clims)
end end
d_out = KW() plotattributes_out = KW()
# these are the axes that the series should be mapped to # these are the axes that the series should be mapped to
x_idx, y_idx = plotly_link_indicies(plt, sp) x_idx, y_idx = plotly_link_indicies(plt, sp)
d_out[:xaxis] = "x$(x_idx)" plotattributes_out[:xaxis] = "x$(x_idx)"
d_out[:yaxis] = "y$(y_idx)" plotattributes_out[:yaxis] = "y$(y_idx)"
d_out[:showlegend] = should_add_to_legend(series) plotattributes_out[:showlegend] = should_add_to_legend(series)
if st == :straightline if st == :straightline
x, y = straightline_data(series) x, y = straightline_data(series)
@ -557,7 +557,7 @@ function plotly_series(plt::Plot, series::Series)
for (letter, data) in zip((:x, :y, :z), (x, y, z)) for (letter, data) in zip((:x, :y, :z), (x, y, z))
) )
d_out[:name] = series[:label] plotattributes_out[:name] = series[:label]
isscatter = st in (:scatter, :scatter3d, :scattergl) isscatter = st in (:scatter, :scatter3d, :scattergl)
hasmarker = isscatter || series[:markershape] != :none hasmarker = isscatter || series[:markershape] != :none
@ -565,59 +565,59 @@ function plotly_series(plt::Plot, series::Series)
hasfillrange = st in (:path, :scatter, :scattergl, :straightline) && hasfillrange = st in (:path, :scatter, :scattergl, :straightline) &&
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple)) (isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
d_out[:colorbar] = KW(:title => sp[:colorbar_title]) plotattributes_out[:colorbar] = KW(:title => sp[:colorbar_title])
if is_2tuple(clims) if is_2tuple(clims)
d_out[:zmin], d_out[:zmax] = clims plotattributes_out[:zmin], plotattributes_out[:zmax] = clims
end end
# set the "type" # set the "type"
if st in (:path, :scatter, :scattergl, :straightline, :path3d, :scatter3d) if st in (:path, :scatter, :scattergl, :straightline, :path3d, :scatter3d)
return plotly_series_segments(series, d_out, x, y, z, clims) return plotly_series_segments(series, plotattributes, x, y, z, clims)
elseif st == :heatmap elseif st == :heatmap
x = heatmap_edges(x, sp[:xaxis][:scale]) x = heatmap_edges(x, sp[:xaxis][:scale])
y = heatmap_edges(y, sp[:yaxis][:scale]) y = heatmap_edges(y, sp[:yaxis][:scale])
d_out[:type] = "heatmap" plotattributes_out[:type] = "heatmap"
d_out[:x], d_out[:y], d_out[:z] = x, y, z plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha]) plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
d_out[:showscale] = hascolorbar(sp) plotattributes_out[:showscale] = hascolorbar(sp)
elseif st == :contour elseif st == :contour
d_out[:type] = "contour" plotattributes_out[:type] = "contour"
d_out[:x], d_out[:y], d_out[:z] = x, y, z plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
# d_out[:showscale] = series[:colorbar] != :none # plotattributes_out[:showscale] = series[:colorbar] != :none
d_out[:ncontours] = series[:levels] plotattributes_out[:ncontours] = series[:levels]
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true) plotattributes_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
d_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha]) plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
d_out[:showscale] = hascolorbar(sp) plotattributes_out[:showscale] = hascolorbar(sp)
elseif st in (:surface, :wireframe) elseif st in (:surface, :wireframe)
d_out[:type] = "surface" plotattributes_out[:type] = "surface"
d_out[:x], d_out[:y], d_out[:z] = x, y, z plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
if st == :wireframe if st == :wireframe
d_out[:hidesurface] = true plotattributes_out[:hidesurface] = true
wirelines = KW( wirelines = KW(
:show => true, :show => true,
:color => rgba_string(plot_color(series[:linecolor], series[:linealpha])), :color => rgba_string(plot_color(series[:linecolor], series[:linealpha])),
:highlightwidth => series[:linewidth], :highlightwidth => series[:linewidth],
) )
d_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines) plotattributes_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines)
d_out[:showscale] = false plotattributes_out[:showscale] = false
else else
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha]) plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
d_out[:opacity] = series[:fillalpha] plotattributes_out[:opacity] = series[:fillalpha]
if series[:fill_z] != nothing if series[:fill_z] != nothing
d_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z]) plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end end
d_out[:showscale] = hascolorbar(sp) plotattributes_out[:showscale] = hascolorbar(sp)
end end
elseif st == :pie elseif st == :pie
d_out[:type] = "pie" plotattributes_out[:type] = "pie"
d_out[:labels] = pie_labels(sp, series) plotattributes_out[:labels] = pie_labels(sp, series)
d_out[:values] = y plotattributes_out[:values] = y
d_out[:hoverinfo] = "label+percent+name" plotattributes_out[:hoverinfo] = "label+percent+name"
else else
@warn("Plotly: seriestype $st isn't supported.") @warn("Plotly: seriestype $st isn't supported.")
@ -627,7 +627,7 @@ function plotly_series(plt::Plot, series::Series)
# add "marker" # add "marker"
if hasmarker if hasmarker
inds = eachindex(x) inds = eachindex(x)
d_out[:marker] = KW( plotattributes_out[:marker] = KW(
:symbol => get(_plotly_markers, series[:markershape], string(series[:markershape])), :symbol => get(_plotly_markers, series[:markershape], string(series[:markershape])),
# :opacity => series[:markeralpha], # :opacity => series[:markeralpha],
:size => 2 * _cycle(series[:markersize], inds), :size => 2 * _cycle(series[:markersize], inds),
@ -639,22 +639,22 @@ function plotly_series(plt::Plot, series::Series)
) )
end end
plotly_polar!(d_out, series) plotly_polar!(plotattributes_out, series)
plotly_hover!(d_out, series[:hover]) plotly_hover!(plotattributes_out, series[:hover])
return [d_out] return [plotattributes_out]
end end
function plotly_series_shapes(plt::Plot, series::Series, clims) function plotly_series_shapes(plt::Plot, series::Series, clims)
segments = iter_segments(series) segments = iter_segments(series)
d_outs = Vector{KW}(undef, length(segments)) plotattributes_outs = Vector{KW}(undef, length(segments))
# TODO: create a d_out for each polygon # TODO: create a plotattributes_out for each polygon
# x, y = series[:x], series[:y] # x, y = series[:x], series[:y]
# these are the axes that the series should be mapped to # these are the axes that the series should be mapped to
x_idx, y_idx = plotly_link_indicies(plt, series[:subplot]) x_idx, y_idx = plotly_link_indicies(plt, series[:subplot])
d_base = KW( plotattributes_base = KW(
:xaxis => "x$(x_idx)", :xaxis => "x$(x_idx)",
:yaxis => "y$(y_idx)", :yaxis => "y$(y_idx)",
:name => series[:label], :name => series[:label],
@ -669,7 +669,7 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
length(rng) < 2 && continue length(rng) < 2 && continue
# to draw polygons, we actually draw lines with fill # to draw polygons, we actually draw lines with fill
d_out = merge(d_base, KW( plotattributes_out = merge(plotattributes_base, KW(
:type => "scatter", :type => "scatter",
:mode => "lines", :mode => "lines",
:x => vcat(x[rng], x[rng[1]]), :x => vcat(x[rng], x[rng[1]]),
@ -678,28 +678,28 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
:fillcolor => rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))), :fillcolor => rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))),
)) ))
if series[:markerstrokewidth] > 0 if series[:markerstrokewidth] > 0
d_out[:line] = KW( plotattributes[:line] = KW(
:color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))), :color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))),
:width => get_linewidth(series, i), :width => get_linewidth(series, i),
:dash => string(get_linestyle(series, i)), :dash => string(get_linestyle(series, i)),
) )
end end
d_out[:showlegend] = i==1 ? should_add_to_legend(series) : false plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
plotly_polar!(d_out, series) plotly_polar!(plotattributes_out, series)
plotly_hover!(d_out, _cycle(series[:hover], i)) plotly_hover!(plotattributes_out, _cycle(series[:hover], i))
d_outs[i] = d_out plotattributes_outs[i] = plotattributes_out
end end
if series[:fill_z] != nothing if series[:fill_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :fill)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:line_z] != nothing elseif series[:line_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :line)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
elseif series[:marker_z] != nothing elseif series[:marker_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :marker)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end end
d_outs plotattributes_outs
end end
function plotly_series_segments(series::Series, d_base::KW, x, y, z, clims) function plotly_series_segments(series::Series, ploattributes_base::KW, x, y, z, clims)
st = series[:seriestype] st = series[:seriestype]
sp = series[:subplot] sp = series[:subplot]
isscatter = st in (:scatter, :scatter3d, :scattergl) isscatter = st in (:scatter, :scatter3d, :scattergl)
@ -709,47 +709,47 @@ function plotly_series_segments(series::Series, d_base::KW, x, y, z, clims)
(isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple)) (isa(series[:fillrange], AbstractVector) || isa(series[:fillrange], Tuple))
segments = iter_segments(series) segments = iter_segments(series)
d_outs = Vector{KW}(undef, (hasfillrange ? 2 : 1 ) * length(segments)) plotattributes_outs = Vector{KW}(undef, (hasfillrange ? 2 : 1 ) * length(segments))
for (i,rng) in enumerate(segments) for (i,rng) in enumerate(segments)
!isscatter && length(rng) < 2 && continue !isscatter && length(rng) < 2 && continue
d_out = deepcopy(d_base) plotattributes_out = deepcopy(plotattributes_base)
d_out[:showlegend] = i==1 ? should_add_to_legend(series) : false plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
d_out[:legendgroup] = series[:label] plotattributes_out[:legendgroup] = series[:label]
# set the type # set the type
if st in (:path, :scatter, :scattergl, :straightline) if st in (:path, :scatter, :scattergl, :straightline)
d_out[:type] = st==:scattergl ? "scattergl" : "scatter" plotattributes_out[:type] = st==:scattergl ? "scattergl" : "scatter"
d_out[:mode] = if hasmarker plotattributes_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers" hasline ? "lines+markers" : "markers"
else else
hasline ? "lines" : "none" hasline ? "lines" : "none"
end end
if series[:fillrange] == true || series[:fillrange] == 0 || isa(series[:fillrange], Tuple) if series[:fillrange] == true || series[:fillrange] == 0 || isa(series[:fillrange], Tuple)
d_out[:fill] = "tozeroy" plotattributes[:fill] = "tozeroy"
d_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))) plotattributes[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)))
elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real}, Real} elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real}, Real}
d_out[:fill] = "tonexty" plotattributes[:fill] = "tonexty"
d_out[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i))) plotattributes[:fillcolor] = rgba_string(plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)))
elseif !(series[:fillrange] in (false, nothing)) elseif !(series[:fillrange] in (false, nothing))
@warn("fillrange ignored... plotly only supports filling to zero and to a vector of values. fillrange: $(series[:fillrange])") @warn("fillrange ignored... plotly only supports filling to zero and to a vector of values. fillrange: $(series[:fillrange])")
end end
d_out[:x], d_out[:y] = x[rng], y[rng] plotattributes_out[:x], plotattributes_out[:y] = x[rng], y[rng]
elseif st in (:path3d, :scatter3d) elseif st in (:path3d, :scatter3d)
d_out[:type] = "scatter3d" plotattributes_out[:type] = "scatter3d"
d_out[:mode] = if hasmarker plotattributes_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers" hasline ? "lines+markers" : "markers"
else else
hasline ? "lines" : "none" hasline ? "lines" : "none"
end end
d_out[:x], d_out[:y], d_out[:z] = x[rng], y[rng], z[rng] plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x[rng], y[rng], z[rng]
end end
# add "marker" # add "marker"
if hasmarker if hasmarker
d_out[:marker] = KW( plotattributes_out[:marker] = KW(
:symbol => get(_plotly_markers, _cycle(series[:markershape], i), string(_cycle(series[:markershape], i))), :symbol => get(_plotly_markers, _cycle(series[:markershape], i), string(_cycle(series[:markershape], i))),
# :opacity => series[:markeralpha], # :opacity => series[:markeralpha],
:size => 2 * _cycle(series[:markersize], i), :size => 2 * _cycle(series[:markersize], i),
@ -763,7 +763,7 @@ function plotly_series_segments(series::Series, d_base::KW, x, y, z, clims)
# add "line" # add "line"
if hasline if hasline
d_out[:line] = KW( plotattributes[:line] = KW(
:color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))), :color => rgba_string(plot_color(get_linecolor(series, clims, i), get_linealpha(series, i))),
:width => get_linewidth(series, i), :width => get_linewidth(series, i),
:shape => if st == :steppre :shape => if st == :steppre
@ -777,14 +777,14 @@ function plotly_series_segments(series::Series, d_base::KW, x, y, z, clims)
) )
end end
plotly_polar!(d_out, series) plotly_polar!(plotattributes_out, series)
plotly_hover!(d_out, _cycle(series[:hover], rng)) plotly_hover!(plotattributes_out, _cycle(series[:hover], rng))
if hasfillrange if hasfillrange
# if hasfillrange is true, return two dictionaries (one for original # if hasfillrange is true, return two dictionaries (one for original
# series, one for series being filled to) instead of one # series, one for series being filled to) instead of one
d_out_fillrange = deepcopy(d_out) plotattributes_out_fillrange = deepcopy(plotattributes_out)
d_out_fillrange[:showlegend] = false plotattributes_out_fillrange[:showlegend] = false
# if fillrange is provided as real or tuple of real, expand to array # if fillrange is provided as real or tuple of real, expand to array
if typeof(series[:fillrange]) <: Real if typeof(series[:fillrange]) <: Real
series[:fillrange] = fill(series[:fillrange], length(rng)) series[:fillrange] = fill(series[:fillrange], length(rng))
@ -794,49 +794,49 @@ function plotly_series_segments(series::Series, d_base::KW, x, y, z, clims)
series[:fillrange] = (f1, f2) series[:fillrange] = (f1, f2)
end end
if isa(series[:fillrange], AbstractVector) if isa(series[:fillrange], AbstractVector)
d_out_fillrange[:y] = series[:fillrange][rng] plotattributes_out_fillrange[:y] = series[:fillrange][rng]
delete!(d_out_fillrange, :fill) delete!(plotattributes_out_fillrange, :fill)
delete!(d_out_fillrange, :fillcolor) delete!(plotattributes_out_fillrange, :fillcolor)
else else
# if fillrange is a tuple with upper and lower limit, d_out_fillrange # if fillrange is a tuple with upper and lower limit, plotattributes_out_fillrange
# is the series that will do the filling # is the series that will do the filling
fillrng = Tuple(series[:fillrange][i][rng] for i in 1:2) fillrng = Tuple(series[:fillrange][i][rng] for i in 1:2)
d_out_fillrange[:x], d_out_fillrange[:y] = concatenate_fillrange(x[rng], fillrng) plotattributes_out_fillrange[:x], plotattributes_out_fillrange[:y] = concatenate_fillrange(x[rng], fillrng)
d_out_fillrange[:line][:width] = 0 plotattributes_out_fillrange[:line][:width] = 0
delete!(d_out, :fill) delete!(plotattributes_out, :fill)
delete!(d_out, :fillcolor) delete!(plotattributes_out, :fillcolor)
end end
d_outs[(2 * i - 1):(2 * i)] = [d_out_fillrange, d_out] plotattributes_outs[(2 * i - 1):(2 * i)] = [plotattributes_out_fillrange, plotattributes_out]
else else
d_outs[i] = d_out plotattributes_outs[i] = plotattributes_out
end end
end end
if series[:line_z] != nothing if series[:line_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :line)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :line))
elseif series[:fill_z] != nothing elseif series[:fill_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :fill)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
elseif series[:marker_z] != nothing elseif series[:marker_z] != nothing
push!(d_outs, plotly_colorbar_hack(series, d_base, :marker)) push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :marker))
end end
d_outs plotattributes_outs
end end
function plotly_colorbar_hack(series::Series, d_base::KW, sym::Symbol) function plotly_colorbar_hack(series::Series, plotattributes_base::KW, sym::Symbol)
d_out = deepcopy(d_base) plotattributes_out = deepcopy(plotattributes_base)
cmin, cmax = get_clims(series[:subplot]) cmin, cmax = get_clims(series[:subplot])
d_out[:showlegend] = false plotattributes_out[:showlegend] = false
d_out[:type] = is3d(series) ? :scatter3d : :scatter plotattributes_out[:type] = is3d(series) ? :scatter3d : :scatter
d_out[:hoverinfo] = :none plotattributes_out[:hoverinfo] = :none
d_out[:mode] = :markers plotattributes_out[:mode] = :markers
d_out[:x], d_out[:y] = [series[:x][1]], [series[:y][1]] plotattributes_out[:x], plotattributes_out[:y] = [series[:x][1]], [series[:y][1]]
if is3d(series) if is3d(series)
d_out[:z] = [series[:z][1]] plotattributes_out[:z] = [series[:z][1]]
end end
# zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line) # zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line)
d_out[:marker] = KW( plotattributes_out[:marker] = KW(
:size => 0, :size => 0,
:opacity => 0, :opacity => 0,
:color => [0.5], :color => [0.5],
@ -845,26 +845,26 @@ function plotly_colorbar_hack(series::Series, d_base::KW, sym::Symbol)
:colorscale => plotly_colorscale(series[Symbol("$(sym)color")], 1), :colorscale => plotly_colorscale(series[Symbol("$(sym)color")], 1),
:showscale => hascolorbar(series[:subplot]), :showscale => hascolorbar(series[:subplot]),
) )
return d_out return plotattributes_out
end end
function plotly_polar!(d_out::KW, series::Series) function plotly_polar!(plotattributes_out::KW, series::Series)
# convert polar plots x/y to theta/radius # convert polar plots x/y to theta/radius
if ispolar(series[:subplot]) if ispolar(series[:subplot])
theta, r = filter_radial_data(pop!(d_out, :x), pop!(d_out, :y), axis_limits(series[:subplot][:yaxis])) theta, r = filter_radial_data(pop!(plotattributes_out, :x), pop!(plotattributes_out, :y), axis_limits(series[:subplot][:yaxis]))
d_out[:t] = rad2deg.(theta) plotattributes_out[:t] = rad2deg.(theta)
d_out[:r] = r plotattributes_out[:r] = r
end end
end end
function plotly_hover!(d_out::KW, hover) function plotly_hover!(plotattributes_out::KW, hover)
# hover text # hover text
if hover in (:none, false) if hover in (:none, false)
d_out[:hoverinfo] = "none" plotattributes_out[:hoverinfo] = "none"
elseif hover != nothing elseif hover != nothing
d_out[:hoverinfo] = "text" plotattributes_out[:hoverinfo] = "text"
d_out[:text] = hover plotattributes_out[:text] = hover
end end
end end

View File

@ -31,7 +31,7 @@ end
function _series_updated(plt::Plot{PlotlyJSBackend}, series::Series) function _series_updated(plt::Plot{PlotlyJSBackend}, series::Series)
xsym, ysym = (ispolar(series) ? (:t,:r) : (:x,:y)) xsym, ysym = (ispolar(series) ? (:t,:r) : (:x,:y))
kw = KW(xsym => (series.d[:x],), ysym => (series.d[:y],)) kw = KW(xsym => (series.plotattributes[:x],), ysym => (series.plotattributes[:y],))
z = series[:z] z = series[:z]
if z != nothing if z != nothing
kw[:z] = (isa(z,Surface) ? transpose_z(series, series[:z].surf, false) : z,) kw[:z] = (isa(z,Surface) ? transpose_z(series, series[:z].surf, false) : z,)

View File

@ -263,7 +263,7 @@ end
function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series) function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series)
x, y = series[:x], series[:y] x, y = series[:x], series[:y]
nx, ny = length(x), length(y) nx, ny = length(x), length(y)
if !isa(get(series.d, :z, nothing), Surface) && nx != ny if !isa(get(series.plotattributes, :z, nothing), Surface) && nx != ny
if nx < ny if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny] series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
else else
@ -299,7 +299,7 @@ py_fillcolormap(series::Series) = py_colormap(series[:fillcolor])
# getAxis(sp::Subplot) = sp.o # getAxis(sp::Subplot) = sp.o
# function getAxis(plt::Plot{PyPlotBackend}, series::Series) # function getAxis(plt::Plot{PyPlotBackend}, series::Series)
# sp = get_subplot(plt, get(series.d, :subplot, 1)) # sp = get_subplot(plt, get(series.plotattributes, :subplot, 1))
# getAxis(sp) # getAxis(sp)
# end # end
@ -412,12 +412,12 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# function _series_added(pkg::PyPlotBackend, plt::Plot, d::KW) # function _series_added(pkg::PyPlotBackend, plt::Plot, plotattributes::KW)
# TODO: change this to accept Subplot?? # TODO: change this to accept Subplot??
# function _series_added(plt::Plot{PyPlotBackend}, series::Series) # function _series_added(plt::Plot{PyPlotBackend}, series::Series)
function py_add_series(plt::Plot{PyPlotBackend}, series::Series) function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
# d = series.d # plotattributes = series.plotattributes
st = series[:seriestype] st = series[:seriestype]
sp = series[:subplot] sp = series[:subplot]
ax = sp.o ax = sp.o
@ -862,7 +862,7 @@ function py_compute_axis_minval(axis::Axis)
sps = axis.sps sps = axis.sps
for sp in sps for sp in sps
for series in series_list(sp) for series in series_list(sp)
v = series.d[axis[:letter]] v = series.plotattributes[axis[:letter]]
if !isempty(v) if !isempty(v)
minval = NaNMath.min(minval, ignorenan_minimum(abs.(v))) minval = NaNMath.min(minval, ignorenan_minimum(abs.(v)))
end end
@ -1066,7 +1066,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing
pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in") pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in")
ax[Symbol("set_", letter, "label")](axis[:guide]) ax[Symbol("set_", letter, "label")](axis[:guide])
if get(axis.d, :flip, false) if get(axis.plotattributes, :flip, false)
ax[Symbol("invert_", letter, "axis")]() ax[Symbol("invert_", letter, "axis")]()
end end
pyaxis[:label][:set_fontsize](py_thickness_scale(plt, axis[:guidefontsize])) pyaxis[:label][:set_fontsize](py_thickness_scale(plt, axis[:guidefontsize]))

View File

@ -49,7 +49,7 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations]) # Override this to update plot items (title, xlabel, etc), and add annotations (plotattributes[:annotations])
function _update_plot_object(plt::Plot{[PkgName]Backend}) function _update_plot_object(plt::Plot{[PkgName]Backend})
end end

View File

@ -25,7 +25,7 @@ const _unicodeplots_scale = [:identity]
# don't warn on unsupported... there's just too many warnings!! # don't warn on unsupported... there's just too many warnings!!
warnOnUnsupported_args(::UnicodePlotsBackend, d::KW) = nothing warnOnUnsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
@ -104,7 +104,7 @@ function rebuildUnicodePlot!(plt::Plot, width, height)
# now use the ! functions to add to the plot # now use the ! functions to add to the plot
for series in series_list(sp) for series in series_list(sp)
addUnicodeSeries!(o, series.d, sp[:legend] != :none, xlim, ylim) addUnicodeSeries!(o, series.plotattributes, sp[:legend] != :none, xlim, ylim)
end end
# save the object # save the object
@ -114,17 +114,17 @@ end
# add a single series # add a single series
function addUnicodeSeries!(o, d::KW, addlegend::Bool, xlim, ylim) function addUnicodeSeries!(o, plotattributes::KW, addlegend::Bool, xlim, ylim)
# get the function, or special handling for step/bar/hist # get the function, or special handling for step/bar/hist
st = d[:seriestype] st = plotattributes[:seriestype]
if st == :histogram2d if st == :histogram2d
UnicodePlots.densityplot!(o, d[:x], d[:y]) UnicodePlots.densityplot!(o, plotattributes[:x], plotattributes[:y])
return return
end end
if st in (:path, :straightline) if st in (:path, :straightline)
func = UnicodePlots.lineplot! func = UnicodePlots.lineplot!
elseif st == :scatter || d[:markershape] != :none elseif st == :scatter || plotattributes[:markershape] != :none
func = UnicodePlots.scatterplot! func = UnicodePlots.scatterplot!
# elseif st == :bar # elseif st == :bar
# func = UnicodePlots.barplot! # func = UnicodePlots.barplot!
@ -136,16 +136,16 @@ function addUnicodeSeries!(o, d::KW, addlegend::Bool, xlim, ylim)
# get the series data and label # get the series data and label
x, y = if st == :straightline x, y = if st == :straightline
straightline_data(d) straightline_data(plotattributes)
elseif st == :shape elseif st == :shape
shape_data(series) shape_data(series)
else else
[collect(float(d[s])) for s in (:x, :y)] [collect(float(plotattributes[s])) for s in (:x, :y)]
end end
label = addlegend ? d[:label] : "" label = addlegend ? plotattributes[:label] : ""
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide # if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
color = d[:linecolor] in UnicodePlots.color_cycle ? d[:linecolor] : :auto color = plotattributes[:linecolor] in UnicodePlots.color_cycle ? plotattributes[:linecolor] : :auto
# add the series # add the series
x, y = Plots.unzip(collect(Base.Iterators.filter(xy->isfinite(xy[1])&&isfinite(xy[2]), zip(x,y)))) x, y = Plots.unzip(collect(Base.Iterators.filter(xy->isfinite(xy[1])&&isfinite(xy[2]), zip(x,y))))

View File

@ -95,9 +95,9 @@ const _glyphtypes = KW(
) )
function bokeh_glyph_type(d::KW) function bokeh_glyph_type(plotattributes::KW)
st = d[:seriestype] st = plotattributes[:seriestype]
mt = d[:markershape] mt = plotattributes[:markershape]
if st == :scatter && mt == :none if st == :scatter && mt == :none
mt = :circle mt = :circle
end end
@ -125,7 +125,7 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# function _create_plot(pkg::BokehBackend, d::KW) # function _create_plot(pkg::BokehBackend, plotattributes::KW)
function _create_backend_figure(plt::Plot{BokehBackend}) function _create_backend_figure(plt::Plot{BokehBackend})
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`) # TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc # TODO: initialize the plot... title, xlabel, bgcolor, etc
@ -142,34 +142,34 @@ function _create_backend_figure(plt::Plot{BokehBackend})
extra_args = KW() # TODO: we'll put extra settings (xlim, etc) here extra_args = KW() # TODO: we'll put extra settings (xlim, etc) here
Bokeh.Plot(datacolumns, tools, filename, title, w, h, xaxis_type, yaxis_type, legend) #, extra_args) Bokeh.Plot(datacolumns, tools, filename, title, w, h, xaxis_type, yaxis_type, legend) #, extra_args)
# Plot(bplt, pkg, 0, d, KW[]) # Plot(bplt, pkg, 0, plotattributes, KW[])
end end
# function _series_added(::BokehBackend, plt::Plot, d::KW) # function _series_added(::BokehBackend, plt::Plot, plotattributes::KW)
function _series_added(plt::Plot{BokehBackend}, series::Series) function _series_added(plt::Plot{BokehBackend}, series::Series)
bdata = Dict{Symbol, Vector}(:x => collect(series.d[:x]), :y => collect(series.d[:y])) bdata = Dict{Symbol, Vector}(:x => collect(series.plotattributes[:x]), :y => collect(series.plotattributes[:y]))
glyph = Bokeh.Bokehjs.Glyph( glyph = Bokeh.Bokehjs.Glyph(
glyphtype = bokeh_glyph_type(d), glyphtype = bokeh_glyph_type(plotattributes),
linecolor = webcolor(d[:linecolor]), # shape's stroke or line color linecolor = webcolor(plotattributes[:linecolor]), # shape's stroke or line color
linewidth = d[:linewidth], # shape's stroke width or line width linewidth = plotattributes[:linewidth], # shape's stroke width or line width
fillcolor = webcolor(d[:markercolor]), fillcolor = webcolor(plotattributes[:markercolor]),
size = ceil(Int, d[:markersize] * 2.5), # magic number 2.5 to keep in same scale as other backends size = ceil(Int, plotattributes[:markersize] * 2.5), # magic number 2.5 to keep in same scale as other backends
dash = get_stroke_vector(d[:linestyle]) dash = get_stroke_vector(plotattributes[:linestyle])
) )
legend = nothing # TODO legend = nothing # TODO
push!(plt.o.datacolumns, Bokeh.BokehDataSet(bdata, glyph, legend)) push!(plt.o.datacolumns, Bokeh.BokehDataSet(bdata, glyph, legend))
# push!(plt.seriesargs, d) # push!(plt.seriesargs, plotattributes)
# plt # plt
end end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# TODO: override this to update plot items (title, xlabel, etc) after creation # TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot_object(plt::Plot{BokehBackend}, d::KW) function _update_plot_object(plt::Plot{BokehBackend}, plotattributes::KW)
end end
# ---------------------------------------------------------------- # ----------------------------------------------------------------

View File

@ -51,32 +51,32 @@ end
# Base.size(v::MissingVec) = (1,) # Base.size(v::MissingVec) = (1,)
# Base.getindex(v::MissingVec, i::Integer) = 0.0 # Base.getindex(v::MissingVec, i::Integer) = 0.0
function createGadflyPlotObject(d::KW) function createGadflyPlotObject(plotattributes::KW)
gplt = Gadfly.Plot() gplt = Gadfly.Plot()
gplt.mapping = Dict() gplt.mapping = Dict()
gplt.data_source = Gadfly.DataFrames.DataFrame() gplt.data_source = Gadfly.DataFrames.DataFrame()
# gplt.layers = gplt.layers[1:0] # gplt.layers = gplt.layers[1:0]
gplt.layers = [Gadfly.layer(Gadfly.Geom.point(tag=:remove), x=zeros(1), y=zeros(1));] # x=MissingVec(), y=MissingVec());] gplt.layers = [Gadfly.layer(Gadfly.Geom.point(tag=:remove), x=zeros(1), y=zeros(1));] # x=MissingVec(), y=MissingVec());]
gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(d[:xguide]), gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(plotattributes[:xguide]),
Gadfly.Guide.ylabel(d[:yguide]), Gadfly.Guide.ylabel(plotattributes[:yguide]),
Gadfly.Guide.title(d[:title])] Gadfly.Guide.title(plotattributes[:title])]
gplt gplt
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
function getLineGeom(d::KW) function getLineGeom(plotattributes::KW)
st = d[:seriestype] st = plotattributes[:seriestype]
xbins, ybins = maketuple(d[:bins]) xbins, ybins = maketuple(plotattributes[:bins])
if st == :hexb if st == :hexb
Gadfly.Geom.hexbin(xbincount = xbins, ybincount = ybins) Gadfly.Geom.hexbin(xbincount = xbins, ybincount = ybins)
elseif st == :histogram2d elseif st == :histogram2d
Gadfly.Geom.histogram2d(xbincount = xbins, ybincount = ybins) Gadfly.Geom.histogram2d(xbincount = xbins, ybincount = ybins)
elseif st == :histogram elseif st == :histogram
Gadfly.Geom.histogram(bincount = xbins, Gadfly.Geom.histogram(bincount = xbins,
orientation = isvertical(d) ? :vertical : :horizontal, orientation = isvertical(plotattributes) ? :vertical : :horizontal,
position = d[:bar_position] == :stack ? :stack : :dodge) position = plotattributes[:bar_position] == :stack ? :stack : :dodge)
elseif st == :path elseif st == :path
Gadfly.Geom.path Gadfly.Geom.path
elseif st in (:bar, :sticks) elseif st in (:bar, :sticks)
@ -90,7 +90,7 @@ function getLineGeom(d::KW)
elseif st == :vline elseif st == :vline
Gadfly.Geom.vline Gadfly.Geom.vline
elseif st == :contour elseif st == :contour
Gadfly.Geom.contour(levels = d[:levels]) Gadfly.Geom.contour(levels = plotattributes[:levels])
# elseif st == :shape # elseif st == :shape
# Gadfly.Geom.polygon(fill = true, preserve_order = true) # Gadfly.Geom.polygon(fill = true, preserve_order = true)
else else
@ -98,11 +98,11 @@ function getLineGeom(d::KW)
end end
end end
function get_extra_theme_args(d::KW, k::Symbol) function get_extra_theme_args(plotattributes::KW, k::Symbol)
# gracefully handles old Gadfly versions # gracefully handles old Gadfly versions
extra_theme_args = KW() extra_theme_args = KW()
try try
extra_theme_args[:line_style] = Gadfly.get_stroke_vector(d[k]) extra_theme_args[:line_style] = Gadfly.get_stroke_vector(plotattributes[k])
catch err catch err
if string(err) == "UndefVarError(:get_stroke_vector)" if string(err) == "UndefVarError(:get_stroke_vector)"
Base.warn_once("Gadfly.get_stroke_vector failed... do you have an old version of Gadfly?") Base.warn_once("Gadfly.get_stroke_vector failed... do you have an old version of Gadfly?")
@ -113,53 +113,53 @@ function get_extra_theme_args(d::KW, k::Symbol)
extra_theme_args extra_theme_args
end end
function getGadflyLineTheme(d::KW) function getGadflyLineTheme(plotattributes::KW)
st = d[:seriestype] st = plotattributes[:seriestype]
lc = convertColor(getColor(d[:linecolor]), d[:linealpha]) lc = convertColor(getColor(plotattributes[:linecolor]), plotattributes[:linealpha])
fc = convertColor(getColor(d[:fillcolor]), d[:fillalpha]) fc = convertColor(getColor(plotattributes[:fillcolor]), plotattributes[:fillalpha])
Gadfly.Theme(; Gadfly.Theme(;
default_color = (st in (:histogram,:histogram2d,:hexbin,:bar,:sticks) ? fc : lc), default_color = (st in (:histogram,:histogram2d,:hexbin,:bar,:sticks) ? fc : lc),
line_width = (st == :sticks ? 1 : d[:linewidth]) * Gadfly.px, line_width = (st == :sticks ? 1 : plotattributes[:linewidth]) * Gadfly.px,
# line_style = Gadfly.get_stroke_vector(d[:linestyle]), # line_style = Gadfly.get_stroke_vector(plotattributes[:linestyle]),
lowlight_color = x->RGB(fc), # fill/ribbon lowlight_color = x->RGB(fc), # fill/ribbon
lowlight_opacity = alpha(fc), # fill/ribbon lowlight_opacity = alpha(fc), # fill/ribbon
bar_highlight = RGB(lc), # bars bar_highlight = RGB(lc), # bars
get_extra_theme_args(d, :linestyle)... get_extra_theme_args(plotattributes, :linestyle)...
) )
end end
# add a line as a new layer # add a line as a new layer
function addGadflyLine!(plt::Plot, numlayers::Int, d::KW, geoms...) function addGadflyLine!(plt::Plot, numlayers::Int, plotattributes::KW, geoms...)
gplt = getGadflyContext(plt) gplt = getGadflyContext(plt)
gfargs = vcat(geoms..., getGadflyLineTheme(d)) gfargs = vcat(geoms..., getGadflyLineTheme(plotattributes))
kwargs = KW() kwargs = KW()
st = d[:seriestype] st = plotattributes[:seriestype]
# add a fill? # add a fill?
if d[:fillrange] != nothing && st != :contour if plotattributes[:fillrange] != nothing && st != :contour
fillmin, fillmax = map(makevec, maketuple(d[:fillrange])) fillmin, fillmax = map(makevec, maketuple(plotattributes[:fillrange]))
nmin, nmax = length(fillmin), length(fillmax) nmin, nmax = length(fillmin), length(fillmax)
kwargs[:ymin] = Float64[min(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(d[:y])] kwargs[:ymin] = Float64[min(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(plotattributes[:y])]
kwargs[:ymax] = Float64[max(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(d[:y])] kwargs[:ymax] = Float64[max(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(plotattributes[:y])]
push!(gfargs, Gadfly.Geom.ribbon) push!(gfargs, Gadfly.Geom.ribbon)
end end
if st in (:hline, :vline) if st in (:hline, :vline)
kwargs[st == :hline ? :yintercept : :xintercept] = d[:y] kwargs[st == :hline ? :yintercept : :xintercept] = plotattributes[:y]
else else
if st == :sticks if st == :sticks
w = 0.01 * mean(diff(d[:x])) w = 0.01 * mean(diff(plotattributes[:x]))
kwargs[:xmin] = d[:x] - w kwargs[:xmin] = plotattributes[:x] - w
kwargs[:xmax] = d[:x] + w kwargs[:xmax] = plotattributes[:x] + w
elseif st == :contour elseif st == :contour
kwargs[:z] = d[:z].surf kwargs[:z] = plotattributes[:z].surf
addGadflyContColorScale(plt, d[:linecolor]) addGadflyContColorScale(plt, plotattributes[:linecolor])
end end
kwargs[:x] = d[st == :histogram ? :y : :x] kwargs[:x] = plotattributes[st == :histogram ? :y : :x]
kwargs[:y] = d[:y] kwargs[:y] = plotattributes[:y]
end end
@ -180,22 +180,22 @@ getMarkerGeom(other) = gadflyshape(get_shape(other))
# getMarkerGeom(shape::Shape) = gadflyshape(shape) # getMarkerGeom(shape::Shape) = gadflyshape(shape)
# getMarkerGeom(shape::Symbol) = gadflyshape(_shapes[shape]) # getMarkerGeom(shape::Symbol) = gadflyshape(_shapes[shape])
# getMarkerGeom(shapes::AVec) = gadflyshape(map(gadflyshape, shapes)) # map(getMarkerGeom, shapes) # getMarkerGeom(shapes::AVec) = gadflyshape(map(gadflyshape, shapes)) # map(getMarkerGeom, shapes)
function getMarkerGeom(d::KW) function getMarkerGeom(plotattributes::KW)
if d[:seriestype] == :shape if plotattributes[:seriestype] == :shape
Gadfly.Geom.polygon(fill = true, preserve_order = true) Gadfly.Geom.polygon(fill = true, preserve_order = true)
else else
getMarkerGeom(d[:markershape]) getMarkerGeom(plotattributes[:markershape])
end end
end end
function getGadflyMarkerTheme(d::KW, attr::KW) function getGadflyMarkerTheme(plotattributes::KW, attr::KW)
c = getColor(d[:markercolor]) c = getColor(plotattributes[:markercolor])
α = d[:markeralpha] α = plotattributes[:markeralpha]
if α != nothing if α != nothing
c = RGBA(RGB(c), α) c = RGBA(RGB(c), α)
end end
ms = d[:markersize] ms = plotattributes[:markersize]
ms = if typeof(ms) <: AVec ms = if typeof(ms) <: AVec
@warn("Gadfly doesn't support variable marker sizes... using the average: $(mean(ms))") @warn("Gadfly doesn't support variable marker sizes... using the average: $(mean(ms))")
mean(ms) * Gadfly.px mean(ms) * Gadfly.px
@ -206,10 +206,10 @@ function getGadflyMarkerTheme(d::KW, attr::KW)
Gadfly.Theme(; Gadfly.Theme(;
default_color = c, default_color = c,
default_point_size = ms, default_point_size = ms,
discrete_highlight_color = c -> RGB(getColor(d[:markerstrokecolor])), discrete_highlight_color = c -> RGB(getColor(plotattributes[:markerstrokecolor])),
highlight_width = d[:markerstrokewidth] * Gadfly.px, highlight_width = plotattributes[:markerstrokewidth] * Gadfly.px,
line_width = d[:markerstrokewidth] * Gadfly.px, line_width = plotattributes[:markerstrokewidth] * Gadfly.px,
# get_extra_theme_args(d, :markerstrokestyle)... # get_extra_theme_args(plotattributes, :markerstrokestyle)...
) )
end end
@ -221,25 +221,25 @@ function addGadflyContColorScale(plt::Plot{GadflyBackend}, c)
push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(c, p)))) push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(c, p))))
end end
function addGadflyMarker!(plt::Plot, numlayers::Int, d::KW, attr::KW, geoms...) function addGadflyMarker!(plt::Plot, numlayers::Int, plotattributes::KW, attr::KW, geoms...)
gfargs = vcat(geoms..., getGadflyMarkerTheme(d, attr), getMarkerGeom(d)) gfargs = vcat(geoms..., getGadflyMarkerTheme(plotattributes, attr), getMarkerGeom(plotattributes))
kwargs = KW() kwargs = KW()
# handle continuous color scales for the markers # handle continuous color scales for the markers
zcolor = d[:marker_z] zcolor = plotattributes[:marker_z]
if zcolor != nothing && typeof(zcolor) <: AVec if zcolor != nothing && typeof(zcolor) <: AVec
kwargs[:color] = zcolor kwargs[:color] = zcolor
addGadflyContColorScale(plt, d[:markercolor]) addGadflyContColorScale(plt, plotattributes[:markercolor])
end end
Gadfly.layer(gfargs...; x = d[:x], y = d[:y], order=numlayers, kwargs...) Gadfly.layer(gfargs...; x = plotattributes[:x], y = plotattributes[:y], order=numlayers, kwargs...)
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
function addToGadflyLegend(plt::Plot, d::KW) function addToGadflyLegend(plt::Plot, plotattributes::KW)
if plt.attr[:legend] != :none && d[:label] != "" if plt.attr[:legend] != :none && plotattributes[:label] != ""
gplt = getGadflyContext(plt) gplt = getGadflyContext(plt)
# add the legend if needed # add the legend if needed
@ -254,20 +254,20 @@ function addToGadflyLegend(plt::Plot, d::KW)
# since gadfly will call unique(colors), but doesn't also merge the rows that match # since gadfly will call unique(colors), but doesn't also merge the rows that match
# Should ensure from this side that colors which are the same are merged together # Should ensure from this side that colors which are the same are merged together
c = getColor(d[d[:markershape] == :none ? :linecolor : :markercolor]) c = getColor(plotattributes[plotattributes[:markershape] == :none ? :linecolor : :markercolor])
foundit = false foundit = false
# extend the label if we found this color # extend the label if we found this color
for i in 1:length(guide.colors) for i in 1:length(guide.colors)
if RGB(c) == guide.colors[i] if RGB(c) == guide.colors[i]
guide.labels[i] *= ", " * d[:label] guide.labels[i] *= ", " * plotattributes[:label]
foundit = true foundit = true
end end
end end
# didn't find the color, so add a new entry into the legend # didn't find the color, so add a new entry into the legend
if !foundit if !foundit
push!(guide.labels, d[:label]) push!(guide.labels, plotattributes[:label])
push!(guide.colors, c) push!(guide.colors, c)
end end
end end
@ -279,40 +279,40 @@ getGadflySmoothing(smooth::Bool) = smooth ? [Gadfly.Geom.smooth(method=:lm)] : A
getGadflySmoothing(smooth::Real) = [Gadfly.Geom.smooth(method=:loess, smoothing=float(smooth))] getGadflySmoothing(smooth::Real) = [Gadfly.Geom.smooth(method=:loess, smoothing=float(smooth))]
function addGadflySeries!(plt::Plot, d::KW) function addGadflySeries!(plt::Plot, plotattributes::KW)
layers = Gadfly.Layer[] layers = Gadfly.Layer[]
gplt = getGadflyContext(plt) gplt = getGadflyContext(plt)
# add a regression line? # add a regression line?
# TODO: make more flexible # TODO: make more flexible
smooth = getGadflySmoothing(d[:smooth]) smooth = getGadflySmoothing(plotattributes[:smooth])
# lines # lines
geom = getLineGeom(d) geom = getLineGeom(plotattributes)
if geom != nothing if geom != nothing
prepend!(layers, addGadflyLine!(plt, length(gplt.layers), d, geom, smooth...)) prepend!(layers, addGadflyLine!(plt, length(gplt.layers), plotattributes, geom, smooth...))
smooth = Any[] # don't add a regression for markers too smooth = Any[] # don't add a regression for markers too
end end
# special handling for ohlc and scatter # special handling for ohlc and scatter
st = d[:seriestype] st = plotattributes[:seriestype]
# if st == :ohlc # if st == :ohlc
# error("Haven't re-implemented after refactoring") # error("Haven't re-implemented after refactoring")
if st in (:histogram2d, :hexbin) && (isa(d[:fillcolor], ColorGradient) || isa(d[:fillcolor], ColorFunction)) if st in (:histogram2d, :hexbin) && (isa(plotattributes[:fillcolor], ColorGradient) || isa(plotattributes[:fillcolor], ColorFunction))
push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:fillcolor], p)))) push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(plotattributes[:fillcolor], p))))
elseif st == :scatter && d[:markershape] == :none elseif st == :scatter && plotattributes[:markershape] == :none
d[:markershape] = :circle plotattributes[:markershape] = :circle
end end
# markers # markers
if d[:markershape] != :none || st == :shape if plotattributes[:markershape] != :none || st == :shape
prepend!(layers, addGadflyMarker!(plt, length(gplt.layers), d, plt.attr, smooth...)) prepend!(layers, addGadflyMarker!(plt, length(gplt.layers), plotattributes, plt.attr, smooth...))
end end
st in (:histogram2d, :hexbin, :contour) || addToGadflyLegend(plt, d) st in (:histogram2d, :hexbin, :contour) || addToGadflyLegend(plt, plotattributes)
# now save the layers that apply to this series # now save the layers that apply to this series
d[:gadflylayers] = layers plotattributes[:gadflylayers] = layers
prepend!(gplt.layers, layers) prepend!(gplt.layers, layers)
end end
@ -322,10 +322,10 @@ end
# NOTE: I'm leaving this here and commented out just in case I want to implement again... it was hacky code to create multi-colored line segments # NOTE: I'm leaving this here and commented out just in case I want to implement again... it was hacky code to create multi-colored line segments
# # colorgroup # # colorgroup
# z = d[:z] # z = plotattributes[:z]
# # handle line segments of different colors # # handle line segments of different colors
# cscheme = d[:linecolor] # cscheme = plotattributes[:linecolor]
# if isa(cscheme, ColorVector) # if isa(cscheme, ColorVector)
# # create a color scale, and set the color group to the index of the color # # create a color scale, and set the color group to the index of the color
# push!(gplt.scales, Gadfly.Scale.color_discrete_manual(cscheme.v...)) # push!(gplt.scales, Gadfly.Scale.color_discrete_manual(cscheme.v...))
@ -333,10 +333,10 @@ end
# # this is super weird, but... oh well... for some reason this creates n separate line segments... # # this is super weird, but... oh well... for some reason this creates n separate line segments...
# # create a list of vertices that go: [x1,x2,x2,x3,x3, ... ,xi,xi, ... xn,xn] (same for y) # # create a list of vertices that go: [x1,x2,x2,x3,x3, ... ,xi,xi, ... xn,xn] (same for y)
# # then the vector passed to the "color" keyword should be a vector: [1,1,2,2,3,3,4,4, ..., i,i, ... , n,n] # # then the vector passed to the "color" keyword should be a vector: [1,1,2,2,3,3,4,4, ..., i,i, ... , n,n]
# csindices = Int[mod1(i,length(cscheme.v)) for i in 1:length(d[:y])] # csindices = Int[mod1(i,length(cscheme.v)) for i in 1:length(plotattributes[:y])]
# cs = collect(repeat(csindices', 2, 1))[1:end-1] # cs = collect(repeat(csindices', 2, 1))[1:end-1]
# grp = collect(repeat((1:length(d[:y]))', 2, 1))[1:end-1] # grp = collect(repeat((1:length(plotattributes[:y]))', 2, 1))[1:end-1]
# d[:x], d[:y] = map(createSegments, (d[:x], d[:y])) # plotattributes[:x], plotattributes[:y] = map(createSegments, (plotattributes[:x], plotattributes[:y]))
# colorgroup = [(:linecolor, cs), (:group, grp)] # colorgroup = [(:linecolor, cs), (:group, grp)]
@ -388,11 +388,11 @@ continuousAndSameAxis(scale, isx::Bool) = isa(scale, Gadfly.Scale.ContinuousScal
filterGadflyScale(gplt, isx::Bool) = filter!(scale -> !continuousAndSameAxis(scale, isx), gplt.scales) filterGadflyScale(gplt, isx::Bool) = filter!(scale -> !continuousAndSameAxis(scale, isx), gplt.scales)
function getGadflyScaleFunction(d::KW, isx::Bool) function getGadflyScaleFunction(plotattributes::KW, isx::Bool)
scalekey = isx ? :xscale : :yscale scalekey = isx ? :xscale : :yscale
hasScaleKey = haskey(d, scalekey) hasScaleKey = haskey(plotattributes, scalekey)
if hasScaleKey if hasScaleKey
scale = d[scalekey] scale = plotattributes[scalekey]
scale == :ln && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey, log scale == :ln && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey, log
scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey, log2 scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey, log2
scale == :log10 && return isx ? Gadfly.Scale.x_log10 : Gadfly.Scale.y_log10, hasScaleKey, log10 scale == :log10 && return isx ? Gadfly.Scale.x_log10 : Gadfly.Scale.y_log10, hasScaleKey, log10
@ -403,15 +403,15 @@ function getGadflyScaleFunction(d::KW, isx::Bool)
end end
function addGadflyLimitsScale(gplt, d::KW, isx::Bool) function addGadflyLimitsScale(gplt, plotattributes::KW, isx::Bool)
gfunc, hasScaleKey, func = getGadflyScaleFunction(d, isx) gfunc, hasScaleKey, func = getGadflyScaleFunction(plotattributes, isx)
# do we want to add min/max limits for the axis? # do we want to add min/max limits for the axis?
limsym = isx ? :xlims : :ylims limsym = isx ? :xlims : :ylims
limargs = Any[] limargs = Any[]
# map :auto to nothing, otherwise add to limargs # map :auto to nothing, otherwise add to limargs
lims = get(d, limsym, :auto) lims = get(plotattributes, limsym, :auto)
if lims == :auto if lims == :auto
lims = nothing lims = nothing
else else
@ -432,7 +432,7 @@ function addGadflyLimitsScale(gplt, d::KW, isx::Bool)
lims, func lims, func
end end
function updateGadflyAxisFlips(gplt, d::KW, xlims, ylims, xfunc, yfunc) function updateGadflyAxisFlips(gplt, plotattributes::KW, xlims, ylims, xfunc, yfunc)
if isa(gplt.coord, Gadfly.Coord.Cartesian) if isa(gplt.coord, Gadfly.Coord.Cartesian)
gplt.coord = Gadfly.Coord.cartesian( gplt.coord = Gadfly.Coord.cartesian(
gplt.coord.xvars, gplt.coord.xvars,
@ -441,16 +441,16 @@ function updateGadflyAxisFlips(gplt, d::KW, xlims, ylims, xfunc, yfunc)
xmax = xlims == nothing ? gplt.coord.xmax : xfunc(maximum(xlims)), xmax = xlims == nothing ? gplt.coord.xmax : xfunc(maximum(xlims)),
ymin = ylims == nothing ? gplt.coord.ymin : yfunc(minimum(ylims)), ymin = ylims == nothing ? gplt.coord.ymin : yfunc(minimum(ylims)),
ymax = ylims == nothing ? gplt.coord.ymax : yfunc(maximum(ylims)), ymax = ylims == nothing ? gplt.coord.ymax : yfunc(maximum(ylims)),
xflip = get(d, :xflip, gplt.coord.xflip), xflip = get(plotattributes, :xflip, gplt.coord.xflip),
yflip = get(d, :yflip, gplt.coord.yflip), yflip = get(plotattributes, :yflip, gplt.coord.yflip),
fixed = gplt.coord.fixed, fixed = gplt.coord.fixed,
aspect_ratio = gplt.coord.aspect_ratio, aspect_ratio = gplt.coord.aspect_ratio,
raster = gplt.coord.raster raster = gplt.coord.raster
) )
else else
gplt.coord = Gadfly.Coord.Cartesian( gplt.coord = Gadfly.Coord.Cartesian(
xflip = get(d, :xflip, false), xflip = get(plotattributes, :xflip, false),
yflip = get(d, :yflip, false) yflip = get(plotattributes, :yflip, false)
) )
end end
end end
@ -464,37 +464,37 @@ function findGuideAndSet(gplt, t::DataType, args...; kw...)
end end
end end
function updateGadflyGuides(plt::Plot, d::KW) function updateGadflyGuides(plt::Plot, plotattributes::KW)
gplt = getGadflyContext(plt) gplt = getGadflyContext(plt)
haskey(d, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, string(d[:title])) haskey(plotattributes, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, string(plotattributes[:title]))
haskey(d, :xguide) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, string(d[:xguide])) haskey(plotattributes, :xguide) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, string(plotattributes[:xguide]))
haskey(d, :yguide) && findGuideAndSet(gplt, Gadfly.Guide.ylabel, string(d[:yguide])) haskey(plotattributes, :yguide) && findGuideAndSet(gplt, Gadfly.Guide.ylabel, string(plotattributes[:yguide]))
xlims, xfunc = addGadflyLimitsScale(gplt, d, true) xlims, xfunc = addGadflyLimitsScale(gplt, plotattributes, true)
ylims, yfunc = addGadflyLimitsScale(gplt, d, false) ylims, yfunc = addGadflyLimitsScale(gplt, plotattributes, false)
ticks = get(d, :xticks, :auto) ticks = get(plotattributes, :xticks, :auto)
if ticks == :none if ticks == :none
_remove_axis(plt, true) _remove_axis(plt, true)
else else
addGadflyTicksGuide(gplt, ticks, true) addGadflyTicksGuide(gplt, ticks, true)
end end
ticks = get(d, :yticks, :auto) ticks = get(plotattributes, :yticks, :auto)
if ticks == :none if ticks == :none
_remove_axis(plt, false) _remove_axis(plt, false)
else else
addGadflyTicksGuide(gplt, ticks, false) addGadflyTicksGuide(gplt, ticks, false)
end end
updateGadflyAxisFlips(gplt, d, xlims, ylims, xfunc, yfunc) updateGadflyAxisFlips(gplt, plotattributes, xlims, ylims, xfunc, yfunc)
end end
function updateGadflyPlotTheme(plt::Plot, d::KW) function updateGadflyPlotTheme(plt::Plot, plotattributes::KW)
kwargs = KW() kwargs = KW()
# colors # colors
insidecolor, gridcolor, textcolor, guidecolor, legendcolor = insidecolor, gridcolor, textcolor, guidecolor, legendcolor =
map(s -> getColor(d[s]), ( map(s -> getColor(plotattributes[s]), (
:background_color_inside, :background_color_inside,
:foreground_color_grid, :foreground_color_grid,
:foreground_color_text, :foreground_color_text,
@ -503,17 +503,17 @@ function updateGadflyPlotTheme(plt::Plot, d::KW)
)) ))
# # hide the legend? # # hide the legend?
leg = d[d[:legend] == :none ? :colorbar : :legend] leg = plotattributes[plotattributes[:legend] == :none ? :colorbar : :legend]
if leg != :best if leg != :best
kwargs[:key_position] = leg == :inside ? :right : leg kwargs[:key_position] = leg == :inside ? :right : leg
end end
if !get(d, :grid, true) if !get(plotattributes, :grid, true)
kwargs[:grid_color] = gridcolor kwargs[:grid_color] = gridcolor
end end
# fonts # fonts
tfont, gfont, lfont = d[:tickfont], d[:guidefont], d[:legendfont] tfont, gfont, lfont = plotattributes[:tickfont], plotattributes[:guidefont], plotattributes[:legendfont]
getGadflyContext(plt).theme = Gadfly.Theme(; getGadflyContext(plt).theme = Gadfly.Theme(;
background_color = insidecolor, background_color = insidecolor,
@ -568,9 +568,9 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# create a blank Gadfly.Plot object # create a blank Gadfly.Plot object
# function _create_plot(pkg::GadflyBackend, d::KW) # function _create_plot(pkg::GadflyBackend, plotattributes::KW)
# gplt = createGadflyPlotObject(d) # gplt = createGadflyPlotObject(plotattributes)
# Plot(gplt, pkg, 0, d, KW[]) # Plot(gplt, pkg, 0, plotattributes, KW[])
# end # end
function _create_backend_figure(plt::Plot{GadflyBackend}) function _create_backend_figure(plt::Plot{GadflyBackend})
createGadflyPlotObject(plt.attr) createGadflyPlotObject(plt.attr)
@ -578,7 +578,7 @@ end
# plot one data series # plot one data series
# function _series_added(::GadflyBackend, plt::Plot, d::KW) # function _series_added(::GadflyBackend, plt::Plot, plotattributes::KW)
function _series_added(plt::Plot{GadflyBackend}, series::Series) function _series_added(plt::Plot{GadflyBackend}, series::Series)
# first clear out the temporary layer # first clear out the temporary layer
gplt = getGadflyContext(plt) gplt = getGadflyContext(plt)
@ -586,16 +586,16 @@ function _series_added(plt::Plot{GadflyBackend}, series::Series)
gplt.layers = gplt.layers[2:end] gplt.layers = gplt.layers[2:end]
end end
addGadflySeries!(plt, series.d) addGadflySeries!(plt, series.plotattributes)
# push!(plt.seriesargs, d) # push!(plt.seriesargs, plotattributes)
# plt # plt
end end
function _update_plot_object(plt::Plot{GadflyBackend}, d::KW) function _update_plot_object(plt::Plot{GadflyBackend}, plotattributes::KW)
updateGadflyGuides(plt, d) updateGadflyGuides(plt, plotattributes)
updateGadflyPlotTheme(plt, d) updateGadflyPlotTheme(plt, plotattributes)
end end

View File

@ -18,9 +18,9 @@ function _initialize_backend(::ImmerseBackend; kw...)
end end
end end
function createImmerseFigure(d::KW) function createImmerseFigure(plotattributes::KW)
w,h = d[:size] w,h = plotattributes[:size]
figidx = Immerse.figure(; name = d[:window_title], width = w, height = h) figidx = Immerse.figure(; name = plotattributes[:window_title], width = w, height = h)
Immerse.Figure(figidx) Immerse.Figure(figidx)
end end
@ -28,12 +28,12 @@ end
# create a blank Gadfly.Plot object # create a blank Gadfly.Plot object
# function _create_plot(pkg::ImmerseBackend, d::KW) # function _create_plot(pkg::ImmerseBackend, plotattributes::KW)
# # create the underlying Gadfly.Plot object # # create the underlying Gadfly.Plot object
# gplt = createGadflyPlotObject(d) # gplt = createGadflyPlotObject(plotattributes)
# #
# # save both the Immerse.Figure and the Gadfly.Plot # # save both the Immerse.Figure and the Gadfly.Plot
# Plot((nothing,gplt), pkg, 0, d, KW[]) # Plot((nothing,gplt), pkg, 0, plotattributes, KW[])
# end # end
function _create_backend_figure(plt::Plot{ImmerseBackend}) function _create_backend_figure(plt::Plot{ImmerseBackend})
(nothing, createGadflyPlotObject(plt.attr)) (nothing, createGadflyPlotObject(plt.attr))
@ -41,20 +41,20 @@ end
# # plot one data series # # plot one data series
# function _series_added(::ImmerseBackend, plt::Plot, d::KW) # function _series_added(::ImmerseBackend, plt::Plot, plotattributes::KW)
# addGadflySeries!(plt, d) # addGadflySeries!(plt, plotattributes)
# push!(plt.seriesargs, d) # push!(plt.seriesargs, plotattributes)
# plt # plt
# end # end
function _series_added(plt::Plot{ImmerseBackend}, series::Series) function _series_added(plt::Plot{ImmerseBackend}, series::Series)
addGadflySeries!(plt, series.d) addGadflySeries!(plt, series.plotattributes)
end end
function _update_plot_object(plt::Plot{ImmerseBackend}, d::KW) function _update_plot_object(plt::Plot{ImmerseBackend}, plotattributes::KW)
updateGadflyGuides(plt, d) updateGadflyGuides(plt, plotattributes)
updateGadflyPlotTheme(plt, d) updateGadflyPlotTheme(plt, plotattributes)
end end
@ -94,10 +94,10 @@ end
# #
# function showSubplotObject(subplt::Subplot{ImmerseBackend}) # function showSubplotObject(subplt::Subplot{ImmerseBackend})
# # create the Gtk window with vertical box vsep # # create the Gtk window with vertical box vsep
# d = getattr(subplt,1) # plotattributes = getattr(subplt,1)
# w,h = d[:size] # w,h = plotattributes[:size]
# vsep = Gtk.GtkBoxLeaf(:v) # vsep = Gtk.GtkBoxLeaf(:v)
# win = Gtk.GtkWindowLeaf(vsep, d[:window_title], w, h) # win = Gtk.GtkWindowLeaf(vsep, plotattributes[:window_title], w, h)
# #
# figindices = [] # figindices = []
# row = Gtk.GtkBoxLeaf(:h) # row = Gtk.GtkBoxLeaf(:h)

View File

@ -52,84 +52,84 @@ const _qwtAliases = KW(
:star8 => :star2, :star8 => :star2,
) )
function fixcolors(d::KW) function fixcolors(plotattributes::KW)
for (k,v) in d for (k,v) in plotattributes
if typeof(v) <: ColorScheme if typeof(v) <: ColorScheme
d[k] = getColor(v) plotattributes[k] = getColor(v)
end end
end end
end end
function replaceQwtAliases(d, s) function replaceQwtAliases(plotattributes, s)
if haskey(_qwtAliases, d[s]) if haskey(_qwtAliases, plotattributes[s])
d[s] = _qwtAliases[d[s]] plotattributes[s] = _qwtAliases[plotattributes[s]]
end end
end end
function adjustQwtKeywords(plt::Plot{QwtBackend}, iscreating::Bool; kw...) function adjustQwtKeywords(plt::Plot{QwtBackend}, iscreating::Bool; kw...)
d = KW(kw) plotattributes = KW(kw)
st = d[:seriestype] st = plotattributes[:seriestype]
if st == :scatter if st == :scatter
d[:seriestype] = :none plotattributes[:seriestype] = :none
if d[:markershape] == :none if plotattributes[:markershape] == :none
d[:markershape] = :circle plotattributes[:markershape] = :circle
end end
elseif st in (:hline, :vline) elseif st in (:hline, :vline)
addLineMarker(plt, d) addLineMarker(plt, plotattributes)
d[:seriestype] = :none plotattributes[:seriestype] = :none
d[:markershape] = :circle plotattributes[:markershape] = :circle
d[:markersize] = 1 plotattributes[:markersize] = 1
if st == :vline if st == :vline
d[:x], d[:y] = d[:y], d[:x] plotattributes[:x], plotattributes[:y] = plotattributes[:y], plotattributes[:x]
end end
elseif !iscreating && st == :bar elseif !iscreating && st == :bar
d = barHack(; kw...) plotattributes = barHack(; kw...)
elseif !iscreating && st == :histogram elseif !iscreating && st == :histogram
d = barHack(; histogramHack(; kw...)...) plotattributes = barHack(; histogramHack(; kw...)...)
end end
replaceQwtAliases(d, :seriestype) replaceQwtAliases(plotattributes, :seriestype)
replaceQwtAliases(d, :markershape) replaceQwtAliases(plotattributes, :markershape)
for k in keys(d) for k in keys(plotattributes)
if haskey(_qwtAliases, k) if haskey(_qwtAliases, k)
d[_qwtAliases[k]] = d[k] plotattributes[_qwtAliases[k]] = plotattributes[k]
end end
end end
d[:x] = collect(d[:x]) plotattributes[:x] = collect(plotattributes[:x])
d[:y] = collect(d[:y]) plotattributes[:y] = collect(plotattributes[:y])
d plotattributes
end end
# function _create_plot(pkg::QwtBackend, d::KW) # function _create_plot(pkg::QwtBackend, plotattributes::KW)
function _create_backend_figure(plt::Plot{QwtBackend}) function _create_backend_figure(plt::Plot{QwtBackend})
fixcolors(plt.attr) fixcolors(plt.attr)
dumpdict(plt.attr,"\n\n!!! plot") dumpdict(plt.attr,"\n\n!!! plot")
o = Qwt.plot(zeros(0,0); plt.attr..., show=false) o = Qwt.plot(zeros(0,0); plt.attr..., show=false)
# plt = Plot(o, pkg, 0, d, KW[]) # plt = Plot(o, pkg, 0, plotattributes, KW[])
# plt # plt
end end
# function _series_added(::QwtBackend, plt::Plot, d::KW) # function _series_added(::QwtBackend, plt::Plot, plotattributes::KW)
function _series_added(plt::Plot{QwtBackend}, series::Series) function _series_added(plt::Plot{QwtBackend}, series::Series)
d = adjustQwtKeywords(plt, false; series.d...) plotattributes = adjustQwtKeywords(plt, false; series.plotattributes...)
fixcolors(d) fixcolors(plotattributes)
dumpdict(d,"\n\n!!! plot!") dumpdict(plotattributes,"\n\n!!! plot!")
Qwt.oplot(plt.o; d...) Qwt.oplot(plt.o; plotattributes...)
# push!(plt.seriesargs, d) # push!(plt.seriesargs, plotattributes)
# plt # plt
end end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
function updateLimsAndTicks(plt::Plot{QwtBackend}, d::KW, isx::Bool) function updateLimsAndTicks(plt::Plot{QwtBackend}, plotattributes::KW, isx::Bool)
lims = get(d, isx ? :xlims : :ylims, nothing) lims = get(plotattributes, isx ? :xlims : :ylims, nothing)
ticks = get(d, isx ? :xticks : :yticks, nothing) ticks = get(plotattributes, isx ? :xticks : :yticks, nothing)
w = plt.o.widget w = plt.o.widget
axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft] axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft]
@ -155,8 +155,8 @@ function updateLimsAndTicks(plt::Plot{QwtBackend}, d::KW, isx::Bool)
# change the scale # change the scale
scalesym = isx ? :xscale : :yscale scalesym = isx ? :xscale : :yscale
if haskey(d, scalesym) if haskey(plotattributes, scalesym)
scaletype = d[scalesym] scaletype = plotattributes[scalesym]
scaletype == :identity && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLinearScaleEngine()) scaletype == :identity && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLinearScaleEngine())
# scaletype == :log && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(e)) # scaletype == :log && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(e))
# scaletype == :log2 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(2)) # scaletype == :log2 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(2))
@ -167,32 +167,32 @@ function updateLimsAndTicks(plt::Plot{QwtBackend}, d::KW, isx::Bool)
end end
function _update_plot_object(plt::Plot{QwtBackend}, d::KW) function _update_plot_object(plt::Plot{QwtBackend}, plotattributes::KW)
haskey(d, :title) && Qwt.title(plt.o, d[:title]) haskey(plotattributes, :title) && Qwt.title(plt.o, plotattributes[:title])
haskey(d, :xguide) && Qwt.xlabel(plt.o, d[:xguide]) haskey(plotattributes, :xguide) && Qwt.xlabel(plt.o, plotattributes[:xguide])
haskey(d, :yguide) && Qwt.ylabel(plt.o, d[:yguide]) haskey(plotattributes, :yguide) && Qwt.ylabel(plt.o, plotattributes[:yguide])
updateLimsAndTicks(plt, d, true) updateLimsAndTicks(plt, plotattributes, true)
updateLimsAndTicks(plt, d, false) updateLimsAndTicks(plt, plotattributes, false)
end end
function _update_plot_pos_size(plt::AbstractPlot{QwtBackend}, d::KW) function _update_plot_pos_size(plt::AbstractPlot{QwtBackend}, plotattributes::KW)
haskey(d, :size) && Qwt.resizewidget(plt.o, d[:size]...) haskey(plotattributes, :size) && Qwt.resizewidget(plt.o, plotattributes[:size]...)
haskey(d, :pos) && Qwt.movewidget(plt.o, d[:pos]...) haskey(plotattributes, :pos) && Qwt.movewidget(plt.o, plotattributes[:pos]...)
end end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# curve.setPen(Qt.QPen(Qt.QColor(color), linewidth, self.getLineStyle(linestyle))) # curve.setPen(Qt.QPen(Qt.QColor(color), linewidth, self.getLineStyle(linestyle)))
function addLineMarker(plt::Plot{QwtBackend}, d::KW) function addLineMarker(plt::Plot{QwtBackend}, plotattributes::KW)
for yi in d[:y] for yi in plotattributes[:y]
marker = Qwt.QWT.QwtPlotMarker() marker = Qwt.QWT.QwtPlotMarker()
ishorizontal = (d[:seriestype] == :hline) ishorizontal = (plotattributes[:seriestype] == :hline)
marker[:setLineStyle](ishorizontal ? 1 : 2) marker[:setLineStyle](ishorizontal ? 1 : 2)
marker[ishorizontal ? :setYValue : :setXValue](yi) marker[ishorizontal ? :setYValue : :setXValue](yi)
qcolor = Qwt.convertRGBToQColor(getColor(d[:linecolor])) qcolor = Qwt.convertRGBToQColor(getColor(plotattributes[:linecolor]))
linestyle = plt.o.widget[:getLineStyle](string(d[:linestyle])) linestyle = plt.o.widget[:getLineStyle](string(plotattributes[:linestyle]))
marker[:setLinePen](Qwt.QT.QPen(qcolor, d[:linewidth], linestyle)) marker[:setLinePen](Qwt.QT.QPen(qcolor, plotattributes[:linewidth], linestyle))
marker[:attach](plt.o.widget) marker[:attach](plt.o.widget)
end end

View File

@ -75,10 +75,10 @@ function _create_backend_figure(plt::Plot{WinstonBackend})
) )
end end
copy_remove(d::KW, s::Symbol) = delete!(copy(d), s) copy_remove(plotattributes::KW, s::Symbol) = delete!(copy(plotattributes), s)
function addRegressionLineWinston(d::KW, wplt) function addRegressionLineWinston(plotattributes::KW, wplt)
xs, ys = regressionXY(d[:x], d[:y]) xs, ys = regressionXY(plotattributes[:x], plotattributes[:y])
Winston.add(wplt, Winston.Curve(xs, ys, kind="dotted")) Winston.add(wplt, Winston.Curve(xs, ys, kind="dotted"))
end end
@ -93,22 +93,22 @@ function getWinstonItems(plt::Plot)
end end
function _series_added(plt::Plot{WinstonBackend}, series::Series) function _series_added(plt::Plot{WinstonBackend}, series::Series)
d = series.d plotattributes = series.plotattributes
window, canvas, wplt = getWinstonItems(plt) window, canvas, wplt = getWinstonItems(plt)
# until we call it normally, do the hack # until we call it normally, do the hack
if d[:seriestype] == :bar if plotattributes[:seriestype] == :bar
d = barHack(;d...) plotattributes = barHack(;plotattributes...)
end end
e = KW() e = KW()
e[:color] = getColor(d[:linecolor]) e[:color] = getColor(plotattributes[:linecolor])
e[:linewidth] = d[:linewidth] e[:linewidth] = plotattributes[:linewidth]
e[:kind] = winston_linestyle[d[:linestyle]] e[:kind] = winston_linestyle[plotattributes[:linestyle]]
e[:symbolkind] = winston_marker[d[:markershape]] e[:symbolkind] = winston_marker[plotattributes[:markershape]]
# markercolor # same choices as `color`, or :match will set the color to be the same as `color` # markercolor # same choices as `color`, or :match will set the color to be the same as `color`
e[:symbolsize] = d[:markersize] / 5 e[:symbolsize] = plotattributes[:markersize] / 5
# pos # (Int,Int), move the enclosing window to this position # pos # (Int,Int), move the enclosing window to this position
# screen # Integer, move enclosing window to this screen number (for multiscreen desktops) # screen # Integer, move enclosing window to this screen number (for multiscreen desktops)
@ -116,69 +116,69 @@ function _series_added(plt::Plot{WinstonBackend}, series::Series)
## lintype :path, :step, :stepinverted, :sticks, :dots, :none, :histogram2d, :hexbin, :histogram, :bar ## lintype :path, :step, :stepinverted, :sticks, :dots, :none, :histogram2d, :hexbin, :histogram, :bar
if d[:seriestype] == :none if plotattributes[:seriestype] == :none
Winston.add(wplt, Winston.Points(d[:x], d[:y]; copy_remove(e, :kind)..., color=getColor(d[:markercolor]))) Winston.add(wplt, Winston.Points(plotattributes[:x], plotattributes[:y]; copy_remove(e, :kind)..., color=getColor(plotattributes[:markercolor])))
elseif d[:seriestype] == :path elseif plotattributes[:seriestype] == :path
x, y = d[:x], d[:y] x, y = plotattributes[:x], plotattributes[:y]
Winston.add(wplt, Winston.Curve(x, y; e...)) Winston.add(wplt, Winston.Curve(x, y; e...))
fillrange = d[:fillrange] fillrange = plotattributes[:fillrange]
if fillrange != nothing if fillrange != nothing
if isa(fillrange, AbstractVector) if isa(fillrange, AbstractVector)
y2 = fillrange y2 = fillrange
else else
y2 = Float64[fillrange for yi in y] y2 = Float64[fillrange for yi in y]
end end
Winston.add(wplt, Winston.FillBetween(x, y, x, y2, fillcolor=getColor(d[:fillcolor]))) Winston.add(wplt, Winston.FillBetween(x, y, x, y2, fillcolor=getColor(plotattributes[:fillcolor])))
end end
elseif d[:seriestype] == :scatter elseif plotattributes[:seriestype] == :scatter
if d[:markershape] == :none if plotattributes[:markershape] == :none
d[:markershape] = :circle plotattributes[:markershape] = :circle
end end
# elseif d[:seriestype] == :step # elseif plotattributes[:seriestype] == :step
# fn = Winston.XXX # fn = Winston.XXX
# elseif d[:seriestype] == :stepinverted # elseif plotattributes[:seriestype] == :stepinverted
# fn = Winston.XXX # fn = Winston.XXX
elseif d[:seriestype] == :sticks elseif plotattributes[:seriestype] == :sticks
Winston.add(wplt, Winston.Stems(d[:x], d[:y]; e...)) Winston.add(wplt, Winston.Stems(plotattributes[:x], plotattributes[:y]; e...))
# elseif d[:seriestype] == :dots # elseif plotattributes[:seriestype] == :dots
# fn = Winston.XXX # fn = Winston.XXX
# elseif d[:seriestype] == :histogram2d # elseif plotattributes[:seriestype] == :histogram2d
# fn = Winston.XXX # fn = Winston.XXX
# elseif d[:seriestype] == :hexbin # elseif plotattributes[:seriestype] == :hexbin
# fn = Winston.XXX # fn = Winston.XXX
elseif d[:seriestype] == :histogram elseif plotattributes[:seriestype] == :histogram
hst = hist(d[:y], d[:bins]) hst = hist(plotattributes[:y], plotattributes[:bins])
Winston.add(wplt, Winston.Histogram(hst...; copy_remove(e, :bins)...)) Winston.add(wplt, Winston.Histogram(hst...; copy_remove(e, :bins)...))
# elseif d[:seriestype] == :bar # elseif plotattributes[:seriestype] == :bar
# # fn = Winston.XXX # # fn = Winston.XXX
else else
error("seriestype $(d[:seriestype]) not supported by Winston.") error("seriestype $(plotattributes[:seriestype]) not supported by Winston.")
end end
# markershape # markershape
if d[:markershape] != :none if plotattributes[:markershape] != :none
Winston.add(wplt, Winston.Points(d[:x], d[:y]; copy_remove(e, :kind)..., color=getColor(d[:markercolor]))) Winston.add(wplt, Winston.Points(plotattributes[:x], plotattributes[:y]; copy_remove(e, :kind)..., color=getColor(plotattributes[:markercolor])))
end end
# optionally add a regression line # optionally add a regression line
d[:smooth] && d[:seriestype] != :histogram && addRegressionLineWinston(d, wplt) plotattributes[:smooth] && plotattributes[:seriestype] != :histogram && addRegressionLineWinston(plotattributes, wplt)
# push!(plt.seriesargs, d) # push!(plt.seriesargs, plotattributes)
# plt # plt
end end
@ -192,17 +192,17 @@ const _winstonNames = KW(
:yscale => :ylog, :yscale => :ylog,
) )
function _update_plot_object(plt::Plot{WinstonBackend}, d::KW) function _update_plot_object(plt::Plot{WinstonBackend}, plotattributes::KW)
window, canvas, wplt = getWinstonItems(plt) window, canvas, wplt = getWinstonItems(plt)
for k in (:xguide, :yguide, :title, :xlims, :ylims) for k in (:xguide, :yguide, :title, :xlims, :ylims)
if haskey(d, k) if haskey(plotattributes, k)
Winston.setattr(wplt, string(get(_winstonNames, k, k)), d[k]) Winston.setattr(wplt, string(get(_winstonNames, k, k)), plotattributes[k])
end end
end end
for k in (:xscale, :yscale) for k in (:xscale, :yscale)
if haskey(d, k) if haskey(plotattributes, k)
islogscale = d[k] == :log10 islogscale = plotattributes[k] == :log10
Winston.setattr(wplt, (k == :xscale ? :xlog : :ylog), islogscale) Winston.setattr(wplt, (k == :xscale ? :xlog : :ylog), islogscale)
end end
end end

View File

@ -7,22 +7,22 @@
const FuncOrFuncs = Union{Function, AVec{Function}} const FuncOrFuncs = Union{Function, AVec{Function}}
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none)) all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(plotattributes, :seriestype, :none))
# missing # missing
convertToAnyVector(v::Nothing, d::KW) = Any[nothing], nothing convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing
# fixed number of blank series # fixed number of blank series
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing
# numeric vector # numeric vector
convertToAnyVector(v::AVec{T}, d::KW) where {T<:Number} = Any[v], nothing convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Number} = Any[v], nothing
# string vector # string vector
convertToAnyVector(v::AVec{T}, d::KW) where {T<:AbstractString} = Any[v], nothing convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:AbstractString} = Any[v], nothing
function convertToAnyVector(v::AMat, d::KW) function convertToAnyVector(v::AMat, plotattributes::KW)
if all3D(d) if all3D(plotattributes)
Any[Surface(v)] Any[Surface(v)]
else else
Any[v[:,i] for i in 1:size(v,2)] Any[v[:,i] for i in 1:size(v,2)]
@ -30,30 +30,30 @@ function convertToAnyVector(v::AMat, d::KW)
end end
# function # function
convertToAnyVector(f::Function, d::KW) = Any[f], nothing convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing
# surface # surface
convertToAnyVector(s::Surface, d::KW) = Any[s], nothing convertToAnyVector(s::Surface, plotattributes::KW) = Any[s], nothing
# # vector of OHLC # # vector of OHLC
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing # convertToAnyVector(v::AVec{OHLC}, plotattributes::KW) = Any[v], nothing
# dates # dates
convertToAnyVector(dts::AVec{D}, d::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing convertToAnyVector(dts::AVec{D}, plotattributes::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else) # list of things (maybe other vectors, functions, or something else)
function convertToAnyVector(v::AVec, d::KW) function convertToAnyVector(v::AVec, plotattributes::KW)
if all(x -> typeof(x) <: Number, v) if all(x -> typeof(x) <: Number, v)
# all real numbers wrap the whole vector as one item # all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing Any[convert(Vector{Float64}, v)], nothing
else else
# something else... treat each element as an item # something else... treat each element as an item
vcat(Any[convertToAnyVector(vi, d)[1] for vi in v]...), nothing vcat(Any[convertToAnyVector(vi, plotattributes)[1] for vi in v]...), nothing
# Any[vi for vi in v], nothing # Any[vi for vi in v], nothing
end end
end end
convertToAnyVector(t::Tuple, d::KW) = Any[t], nothing convertToAnyVector(t::Tuple, plotattributes::KW) = Any[t], nothing
function convertToAnyVector(args...) function convertToAnyVector(args...)

View File

@ -464,12 +464,12 @@ end
# constructors # constructors
# pass the layout arg through # pass the layout arg through
function layout_args(d::KW) function layout_args(plotattributes::KW)
layout_args(get(d, :layout, default(:layout))) layout_args(get(plotattributes, :layout, default(:layout)))
end end
function layout_args(d::KW, n_override::Integer) function layout_args(plotattributes::KW, n_override::Integer)
layout, n = layout_args(get(d, :layout, n_override)) layout, n = layout_args(get(plotattributes, :layout, n_override))
if n != n_override if n != n_override
error("When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.") error("When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.")
end end

View File

@ -7,44 +7,44 @@ function command_idx(kw_list::AVec{KW}, kw::KW)
Int(kw[:series_plotindex]) - Int(kw_list[1][:series_plotindex]) + 1 Int(kw[:series_plotindex]) - Int(kw_list[1][:series_plotindex]) + 1
end end
function _expand_seriestype_array(d::KW, args) function _expand_seriestype_array(plotattributes::KW, args)
sts = get(d, :seriestype, :path) sts = get(plotattributes, :seriestype, :path)
if typeof(sts) <: AbstractArray if typeof(sts) <: AbstractArray
delete!(d, :seriestype) delete!(plotattributes, :seriestype)
rd = Vector{RecipeData}(undef, size(sts, 1)) rd = Vector{RecipeData}(undef, size(sts, 1))
for r in 1:size(sts, 1) for r in 1:size(sts, 1)
dc = copy(d) dc = copy(plotattributes)
dc[:seriestype] = sts[r:r,:] dc[:seriestype] = sts[r:r,:]
rd[r] = RecipeData(dc, args) rd[r] = RecipeData(dc, args)
end end
rd rd
else else
RecipeData[RecipeData(copy(d), args)] RecipeData[RecipeData(copy(plotattributes), args)]
end end
end end
function _preprocess_args(d::KW, args, still_to_process::Vector{RecipeData}) function _preprocess_args(plotattributes::KW, args, still_to_process::Vector{RecipeData})
# the grouping mechanism is a recipe on a GroupBy object # the grouping mechanism is a recipe on a GroupBy object
# we simply add the GroupBy object to the front of the args list to allow # we simply add the GroupBy object to the front of the args list to allow
# the recipe to be applied # the recipe to be applied
if haskey(d, :group) if haskey(plotattributes, :group)
args = (extractGroupArgs(d[:group], args...), args...) args = (extractGroupArgs(plotattributes[:group], args...), args...)
end end
# if we were passed a vector/matrix of seriestypes and there's more than one row, # if we were passed a vector/matrix of seriestypes and there's more than one row,
# we want to duplicate the inputs, once for each seriestype row. # we want to duplicate the inputs, once for each seriestype row.
if !isempty(args) if !isempty(args)
append!(still_to_process, _expand_seriestype_array(d, args)) append!(still_to_process, _expand_seriestype_array(plotattributes, args))
end end
# remove subplot and axis args from d... they will be passed through in the kw_list # remove subplot and axis args from plotattributes... they will be passed through in the kw_list
if !isempty(args) if !isempty(args)
for (k,v) in d for (k,v) in plotattributes
for defdict in (_subplot_defaults, for defdict in (_subplot_defaults,
_axis_defaults, _axis_defaults,
_axis_defaults_byletter) _axis_defaults_byletter)
if haskey(defdict, k) if haskey(defdict, k)
delete!(d, k) delete!(plotattributes, k)
end end
end end
end end
@ -57,9 +57,9 @@ end
# user recipes # user recipes
function _process_userrecipes(plt::Plot, d::KW, args) function _process_userrecipes(plt::Plot, plotattributes::KW, args)
still_to_process = RecipeData[] still_to_process = RecipeData[]
args = _preprocess_args(d, args, still_to_process) args = _preprocess_args(plotattributes, args, still_to_process)
# for plotting recipes, swap out the args and update the parameter dictionary # for plotting recipes, swap out the args and update the parameter dictionary
# we are keeping a stack of series that still need to be processed. # we are keeping a stack of series that still need to be processed.
@ -80,20 +80,20 @@ function _process_userrecipes(plt::Plot, d::KW, args)
if isempty(next_series.args) if isempty(next_series.args)
_process_userrecipe(plt, kw_list, next_series) _process_userrecipe(plt, kw_list, next_series)
else else
rd_list = RecipesBase.apply_recipe(next_series.d, next_series.args...) rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...)
prepend!(still_to_process,rd_list) prepend!(still_to_process,rd_list)
end end
end end
# don't allow something else to handle it # don't allow something else to handle it
d[:smooth] = false plotattributes[:smooth] = false
kw_list kw_list
end end
function _process_userrecipe(plt::Plot, kw_list::Vector{KW}, recipedata::RecipeData) function _process_userrecipe(plt::Plot, kw_list::Vector{KW}, recipedata::RecipeData)
# when the arg tuple is empty, that means there's nothing left to recursively # when the arg tuple is empty, that means there's nothing left to recursively
# process... finish up and add to the kw_list # process... finish up and add to the kw_list
kw = recipedata.d kw = recipedata.plotattributes
preprocessArgs!(kw) preprocessArgs!(kw)
_preprocess_userrecipe(kw) _preprocess_userrecipe(kw)
warnOnUnsupported_scales(plt.backend, kw) warnOnUnsupported_scales(plt.backend, kw)
@ -183,11 +183,11 @@ function _process_plotrecipe(plt::Plot, kw::KW, kw_list::Vector{KW}, still_to_pr
st = kw[:seriestype] = get(_typeAliases, st, st) st = kw[:seriestype] = get(_typeAliases, st, st)
datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) datalist = RecipesBase.apply_recipe(kw, Val{st}, plt)
for data in datalist for data in datalist
preprocessArgs!(data.d) preprocessArgs!(data.plotattributes)
if data.d[:seriestype] == st if data.plotattributes[:seriestype] == st
error("Plot recipe $st returned the same seriestype: $(data.d)") error("Plot recipe $st returned the same seriestype: $(data.plotattributes)")
end end
push!(still_to_process, data.d) push!(still_to_process, data.plotattributes)
end end
catch err catch err
if isa(err, MethodError) if isa(err, MethodError)
@ -203,14 +203,14 @@ end
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# setup plot and subplot # setup plot and subplot
function _plot_setup(plt::Plot, d::KW, kw_list::Vector{KW}) function _plot_setup(plt::Plot, plotattributes::KW, kw_list::Vector{KW})
# merge in anything meant for the Plot # merge in anything meant for the Plot
for kw in kw_list, (k,v) in kw for kw in kw_list, (k,v) in kw
haskey(_plot_defaults, k) && (d[k] = pop!(kw, k)) haskey(_plot_defaults, k) && (plotattributes[k] = pop!(kw, k))
end end
# TODO: init subplots here # TODO: init subplots here
_update_plot_args(plt, d) _update_plot_args(plt, plotattributes)
if !plt.init if !plt.init
plt.o = Base.invokelatest(_create_backend_figure, plt) plt.o = Base.invokelatest(_create_backend_figure, plt)
@ -252,7 +252,7 @@ function _plot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
plt[:inset_subplots] = nothing plt[:inset_subplots] = nothing
end end
function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW}) function _subplot_setup(plt::Plot, plotattributes::KW, kw_list::Vector{KW})
# we'll keep a map of subplot to an attribute override dict. # we'll keep a map of subplot to an attribute override dict.
# Subplot/Axis attributes set by a user/series recipe apply only to the # Subplot/Axis attributes set by a user/series recipe apply only to the
# Subplot object which they belong to. # Subplot object which they belong to.
@ -289,8 +289,8 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
# override subplot/axis args. `sp_attrs` take precendence # override subplot/axis args. `sp_attrs` take precendence
for (idx,sp) in enumerate(plt.subplots) for (idx,sp) in enumerate(plt.subplots)
attr = if !haskey(d, :subplot) || d[:subplot] == idx attr = if !haskey(plotattributes, :subplot) || plotattributes[:subplot] == idx
merge(d, get(sp_attrs, sp, KW())) merge(plotattributes, get(sp_attrs, sp, KW()))
else else
get(sp_attrs, sp, KW()) get(sp_attrs, sp, KW())
end end
@ -303,13 +303,13 @@ end
# getting ready to add the series... last update to subplot from anything # getting ready to add the series... last update to subplot from anything
# that might have been added during series recipes # that might have been added during series recipes
function _prepare_subplot(plt::Plot{T}, d::KW) where T function _prepare_subplot(plt::Plot{T}, plotattributes::KW) where T
st::Symbol = d[:seriestype] st::Symbol = plotattributes[:seriestype]
sp::Subplot{T} = d[:subplot] sp::Subplot{T} = plotattributes[:subplot]
sp_idx = get_subplot_index(plt, sp) sp_idx = get_subplot_index(plt, sp)
_update_subplot_args(plt, sp, d, sp_idx, true) _update_subplot_args(plt, sp, plotattributes, sp_idx, true)
st = _override_seriestype_check(d, st) st = _override_seriestype_check(plotattributes, st)
# change to a 3d projection for this subplot? # change to a 3d projection for this subplot?
if is3d(st) if is3d(st)
@ -327,28 +327,28 @@ end
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# series types # series types
function _override_seriestype_check(d::KW, st::Symbol) function _override_seriestype_check(plotattributes::KW, st::Symbol)
# do we want to override the series type? # do we want to override the series type?
if !is3d(st) && !(st in (:contour,:contour3d)) if !is3d(st) && !(st in (:contour,:contour3d))
z = d[:z] z = plotattributes[:z]
if !isa(z, Nothing) && (size(d[:x]) == size(d[:y]) == size(z)) if !isa(z, Nothing) && (size(plotattributes[:x]) == size(plotattributes[:y]) == size(z))
st = (st == :scatter ? :scatter3d : :path3d) st = (st == :scatter ? :scatter3d : :path3d)
d[:seriestype] = st plotattributes[:seriestype] = st
end end
end end
st st
end end
function _prepare_annotations(sp::Subplot, d::KW) function _prepare_annotations(sp::Subplot, plotattributes::KW)
# strip out series annotations (those which are based on series x/y coords) # strip out series annotations (those which are based on series x/y coords)
# and add them to the subplot attr # and add them to the subplot attr
sp_anns = annotations(sp[:annotations]) sp_anns = annotations(sp[:annotations])
# series_anns = annotations(pop!(d, :series_annotations, [])) # series_anns = annotations(pop!(plotattributes, :series_annotations, []))
# if isa(series_anns, SeriesAnnotations) # if isa(series_anns, SeriesAnnotations)
# series_anns.x = d[:x] # series_anns.x = plotattributes[:x]
# series_anns.y = d[:y] # series_anns.y = plotattributes[:y]
# elseif length(series_anns) > 0 # elseif length(series_anns) > 0
# x, y = d[:x], d[:y] # x, y = plotattributes[:x], plotattributes[:y]
# nx, ny, na = map(length, (x,y,series_anns)) # nx, ny, na = map(length, (x,y,series_anns))
# n = max(nx, ny, na) # n = max(nx, ny, na)
# series_anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(series_anns[mod1(i,na)])) for i=1:n] # series_anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(series_anns[mod1(i,na)])) for i=1:n]
@ -356,14 +356,14 @@ function _prepare_annotations(sp::Subplot, d::KW)
# sp.attr[:annotations] = vcat(sp_anns, series_anns) # sp.attr[:annotations] = vcat(sp_anns, series_anns)
end end
function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol) function _expand_subplot_extrema(sp::Subplot, plotattributes::KW, st::Symbol)
# adjust extrema and discrete info # adjust extrema and discrete info
if st == :image if st == :image
xmin, xmax = ignorenan_extrema(d[:x]); ymin, ymax = ignorenan_extrema(d[:y]) xmin, xmax = ignorenan_extrema(plotattributes[:x]); ymin, ymax = ignorenan_extrema(plotattributes[:y])
expand_extrema!(sp[:xaxis], (xmin, xmax)) expand_extrema!(sp[:xaxis], (xmin, xmax))
expand_extrema!(sp[:yaxis], (ymin, ymax)) expand_extrema!(sp[:yaxis], (ymin, ymax))
elseif !(st in (:pie, :histogram, :bins2d, :histogram2d)) elseif !(st in (:pie, :histogram, :bins2d, :histogram2d))
expand_extrema!(sp, d) expand_extrema!(sp, plotattributes)
end end
# expand for zerolines (axes through origin) # expand for zerolines (axes through origin)
if sp[:framestyle] in (:origin, :zerolines) if sp[:framestyle] in (:origin, :zerolines)
@ -372,10 +372,10 @@ function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol)
end end
end end
function _add_the_series(plt, sp, d) function _add_the_series(plt, sp, plotattributes)
warnOnUnsupported_args(plt.backend, d) warnOnUnsupported_args(plt.backend, plotattributes)
warnOnUnsupported(plt.backend, d) warnOnUnsupported(plt.backend, plotattributes)
series = Series(d) series = Series(plotattributes)
push!(plt.series_list, series) push!(plt.series_list, series)
push!(sp.series_list, series) push!(sp.series_list, series)
_series_added(plt, series) _series_added(plt, series)
@ -385,36 +385,36 @@ end
# this method recursively applies series recipes when the seriestype is not supported # this method recursively applies series recipes when the seriestype is not supported
# natively by the backend # natively by the backend
function _process_seriesrecipe(plt::Plot, d::KW) function _process_seriesrecipe(plt::Plot, plotattributes::KW)
# replace seriestype aliases # replace seriestype aliases
st = Symbol(d[:seriestype]) st = Symbol(plotattributes[:seriestype])
st = d[:seriestype] = get(_typeAliases, st, st) st = plotattributes[:seriestype] = get(_typeAliases, st, st)
# shapes shouldn't have fillrange set # shapes shouldn't have fillrange set
if d[:seriestype] == :shape if plotattributes[:seriestype] == :shape
d[:fillrange] = nothing plotattributes[:fillrange] = nothing
end end
# if it's natively supported, finalize processing and pass along to the backend, otherwise recurse # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse
if is_seriestype_supported(st) if is_seriestype_supported(st)
sp = _prepare_subplot(plt, d) sp = _prepare_subplot(plt, plotattributes)
_prepare_annotations(sp, d) _prepare_annotations(sp, plotattributes)
_expand_subplot_extrema(sp, d, st) _expand_subplot_extrema(sp, plotattributes, st)
_update_series_attributes!(d, plt, sp) _update_series_attributes!(plotattributes, plt, sp)
_add_the_series(plt, sp, d) _add_the_series(plt, sp, plotattributes)
else else
# get a sub list of series for this seriestype # get a sub list of series for this seriestype
datalist = RecipesBase.apply_recipe(d, Val{st}, d[:x], d[:y], d[:z]) datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, plotattributes[:x], plotattributes[:y], plotattributes[:z])
# assuming there was no error, recursively apply the series recipes # assuming there was no error, recursively apply the series recipes
for data in datalist for data in datalist
if isa(data, RecipeData) if isa(data, RecipeData)
preprocessArgs!(data.d) preprocessArgs!(data.plotattributes)
if data.d[:seriestype] == st if data.plotattributes[:seriestype] == st
error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.")
end end
_process_seriesrecipe(plt, data.d) _process_seriesrecipe(plt, data.plotattributes)
else else
@warn("Unhandled recipe: $(data)") @warn("Unhandled recipe: $(data)")
break break

View File

@ -48,20 +48,20 @@ as a String to look up its docstring; e.g. `plotattr("seriestype")`.
""" """
function plot(args...; kw...) function plot(args...; kw...)
# this creates a new plot with args/kw and sets it to be the current plot # this creates a new plot with args/kw and sets it to be the current plot
d = KW(kw) plotattributes = KW(kw)
preprocessArgs!(d) preprocessArgs!(plotattributes)
# create an empty Plot then process # create an empty Plot then process
plt = Plot() plt = Plot()
# plt.user_attr = d # plt.user_attr = plotattributes
_plot!(plt, d, args) _plot!(plt, plotattributes, args)
end end
# build a new plot from existing plots # build a new plot from existing plots
# note: we split into plt1 and plts_tail so we can dispatch correctly # note: we split into plt1 and plts_tail so we can dispatch correctly
function plot(plt1::Plot, plts_tail::Plot...; kw...) function plot(plt1::Plot, plts_tail::Plot...; kw...)
d = KW(kw) plotattributes = KW(kw)
preprocessArgs!(d) preprocessArgs!(plotattributes)
# build our plot vector from the args # build our plot vector from the args
n = length(plts_tail) + 1 n = length(plts_tail) + 1
@ -72,7 +72,7 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
end end
# compute the layout # compute the layout
layout = layout_args(d, n)[1] layout = layout_args(plotattributes, n)[1]
num_sp = sum([length(p.subplots) for p in plts]) num_sp = sum([length(p.subplots) for p in plts])
# create a new plot object, with subplot list/map made of existing subplots. # create a new plot object, with subplot list/map made of existing subplots.
@ -83,21 +83,21 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
# TODO: build the user_attr dict by creating "Any matrices" for the args of each subplot # TODO: build the user_attr dict by creating "Any matrices" for the args of each subplot
# TODO: replace this with proper processing from a merged user_attr KW # TODO: replace this with proper processing from a merged user_attr KW
# update plot args, first with existing plots, then override with d # update plot args, first with existing plots, then override with plotattributes
for p in plts for p in plts
_update_plot_args(plt, copy(p.attr)) _update_plot_args(plt, copy(p.attr))
plt.n += p.n plt.n += p.n
end end
_update_plot_args(plt, d) _update_plot_args(plt, plotattributes)
# pass new plot to the backend # pass new plot to the backend
plt.o = _create_backend_figure(plt) plt.o = _create_backend_figure(plt)
plt.init = true plt.init = true
series_attr = KW() series_attr = KW()
for (k,v) in d for (k,v) in plotattributes
if haskey(_series_defaults, k) if haskey(_series_defaults, k)
series_attr[k] = pop!(d,k) series_attr[k] = pop!(plotattributes,k)
end end
end end
@ -118,8 +118,8 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
sp.plt = plt sp.plt = plt
sp.attr[:subplot_index] = idx sp.attr[:subplot_index] = idx
for series in serieslist for series in serieslist
merge!(series.d, series_attr) merge!(series.plotattributes, series_attr)
_add_defaults!(series.d, plt, sp, cmdidx) _add_defaults!(series.plotattributes, plt, sp, cmdidx)
push!(plt.series_list, series) push!(plt.series_list, series)
_series_added(plt, series) _series_added(plt, series)
cmdidx += 1 cmdidx += 1
@ -128,12 +128,12 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
# first apply any args for the subplots # first apply any args for the subplots
for (idx,sp) in enumerate(plt.subplots) for (idx,sp) in enumerate(plt.subplots)
_update_subplot_args(plt, sp, d, idx, false) _update_subplot_args(plt, sp, plotattributes, idx, false)
end end
# finish up # finish up
current(plt) current(plt)
_do_plot_show(plt, get(d, :show, default(:show))) _do_plot_show(plt, get(plotattributes, :show, default(:show)))
plt plt
end end
@ -152,10 +152,10 @@ end
# this adds to a specific plot... most plot commands will flow through here # this adds to a specific plot... most plot commands will flow through here
function plot!(plt::Plot, args...; kw...) function plot!(plt::Plot, args...; kw...)
d = KW(kw) plotattributes = KW(kw)
preprocessArgs!(d) preprocessArgs!(plotattributes)
# merge!(plt.user_attr, d) # merge!(plt.user_attr, plotattributes)
_plot!(plt, d, args) _plot!(plt, plotattributes, args)
end end
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
@ -163,8 +163,8 @@ end
# this is the core plotting function. recursively apply recipes to build # this is the core plotting function. recursively apply recipes to build
# a list of series KW dicts. # a list of series KW dicts.
# note: at entry, we only have those preprocessed args which were passed in... no default values yet # note: at entry, we only have those preprocessed args which were passed in... no default values yet
function _plot!(plt::Plot, d::KW, args::Tuple) function _plot!(plt::Plot, plotattributes::KW, args::Tuple)
d[:plot_object] = plt plotattributes[:plot_object] = plt
if !isempty(args) && !isdefined(Main, :StatPlots) && if !isempty(args) && !isdefined(Main, :StatPlots) &&
first(split(string(typeof(args[1])), ".")) == "DataFrames" first(split(string(typeof(args[1])), ".")) == "DataFrames"
@ -175,7 +175,7 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
# "USER RECIPES" # "USER RECIPES"
# -------------------------------- # --------------------------------
kw_list = _process_userrecipes(plt, d, args) kw_list = _process_userrecipes(plt, plotattributes, args)
# @info(1) # @info(1)
# map(DD, kw_list) # map(DD, kw_list)
@ -202,8 +202,8 @@ function _plot!(plt::Plot, d::KW, args::Tuple)
# -------------------------------- # --------------------------------
# Plot/Subplot/Layout setup # Plot/Subplot/Layout setup
# -------------------------------- # --------------------------------
_plot_setup(plt, d, kw_list) _plot_setup(plt, plotattributes, kw_list)
_subplot_setup(plt, d, kw_list) _subplot_setup(plt, plotattributes, kw_list)
# !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!! # !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!!
# !!! The next step is to recursively apply series recipes until the backend supports that series type !!! # !!! The next step is to recursively apply series recipes until the backend supports that series type !!!

View File

@ -47,7 +47,7 @@ end
num_series(x::AMat) = size(x,2) num_series(x::AMat) = size(x,2)
num_series(x) = 1 num_series(x) = 1
RecipesBase.apply_recipe(d::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T")) RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T"))
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -277,7 +277,7 @@ end
fr = plotattributes[:fillrange] fr = plotattributes[:fillrange]
newfr = fr != nothing ? zeros(0) : nothing newfr = fr != nothing ? zeros(0) : nothing
newz = z != nothing ? zeros(0) : nothing newz = z != nothing ? zeros(0) : nothing
# lz = d[:line_z] # lz = plotattributes[:line_z]
# newlz = lz != nothing ? zeros(0) : nothing # newlz = lz != nothing ? zeros(0) : nothing
# for each line segment (point series with no NaNs), convert it into a bezier curve # for each line segment (point series with no NaNs), convert it into a bezier curve
@ -313,9 +313,9 @@ end
end end
# if lz != nothing # if lz != nothing
# # line_z := newlz # # line_z := newlz
# linecolor := (isa(d[:linecolor], ColorGradient) ? d[:linecolor] : cgrad()) # linecolor := (isa(plotattributes[:linecolor], ColorGradient) ? plotattributes[:linecolor] : cgrad())
# end # end
# Plots.DD(d) # Plots.DD(plotattributes)
() ()
end end
@deps curves path @deps curves path
@ -453,16 +453,16 @@ function _preprocess_binbarlike_weights(::Type{T}, w, wscale::Symbol) where T<:A
w_adj, baseline w_adj, baseline
end end
function _preprocess_barlike(d, x, y) function _preprocess_barlike(plotattributes, x, y)
xscale = get(d, :xscale, :identity) xscale = get(plotattributes, :xscale, :identity)
yscale = get(d, :yscale, :identity) yscale = get(plotattributes, :yscale, :identity)
weights, baseline = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale) weights, baseline = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
x, weights, xscale, yscale, baseline x, weights, xscale, yscale, baseline
end end
function _preprocess_binlike(d, x, y) function _preprocess_binlike(plotattributes, x, y)
xscale = get(d, :xscale, :identity) xscale = get(plotattributes, :xscale, :identity)
yscale = get(d, :yscale, :identity) yscale = get(plotattributes, :yscale, :identity)
T = float(promote_type(eltype(x), eltype(y))) T = float(promote_type(eltype(x), eltype(y)))
edge = T.(x) edge = T.(x)
weights, baseline = _preprocess_binbarlike_weights(T, y, yscale) weights, baseline = _preprocess_binbarlike_weights(T, y, yscale)
@ -781,11 +781,11 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Error Bars # Error Bars
function error_style!(d::KW) function error_style!(plotattributes::KW)
d[:seriestype] = :path plotattributes[:seriestype] = :path
d[:linecolor] = d[:markerstrokecolor] plotattributes[:linecolor] = plotattributes[:markerstrokecolor]
d[:linewidth] = d[:markerstrokewidth] plotattributes[:linewidth] = plotattributes[:markerstrokewidth]
d[:label] = "" plotattributes[:label] = ""
end end
# if we're passed a tuple of vectors, convert to a vector of tuples # if we're passed a tuple of vectors, convert to a vector of tuples
@ -842,16 +842,16 @@ end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# quiver # quiver
# function apply_series_recipe(d::KW, ::Type{Val{:quiver}}) # function apply_series_recipe(plotattributes::KW, ::Type{Val{:quiver}})
function quiver_using_arrows(d::KW) function quiver_using_arrows(plotattributes::KW)
d[:label] = "" plotattributes[:label] = ""
d[:seriestype] = :path plotattributes[:seriestype] = :path
if !isa(d[:arrow], Arrow) if !isa(plotattributes[:arrow], Arrow)
d[:arrow] = arrow() plotattributes[:arrow] = arrow()
end end
velocity = error_zipit(d[:quiver]) velocity = error_zipit(plotattributes[:quiver])
xorig, yorig = d[:x], d[:y] xorig, yorig = plotattributes[:x], plotattributes[:y]
# for each point, we create an arrow of velocity vi, translated to the x/y coordinates # for each point, we create an arrow of velocity vi, translated to the x/y coordinates
x, y = zeros(0), zeros(0) x, y = zeros(0), zeros(0)
@ -877,17 +877,17 @@ function quiver_using_arrows(d::KW)
nanappend!(y, [yi, yi+vy, NaN]) nanappend!(y, [yi, yi+vy, NaN])
end end
d[:x], d[:y] = x, y plotattributes[:x], plotattributes[:y] = x, y
# KW[d] # KW[plotattributes]
end end
# function apply_series_recipe(d::KW, ::Type{Val{:quiver}}) # function apply_series_recipe(plotattributes::KW, ::Type{Val{:quiver}})
function quiver_using_hack(d::KW) function quiver_using_hack(plotattributes::KW)
d[:label] = "" plotattributes[:label] = ""
d[:seriestype] = :shape plotattributes[:seriestype] = :shape
velocity = error_zipit(d[:quiver]) velocity = error_zipit(plotattributes[:quiver])
xorig, yorig = d[:x], d[:y] xorig, yorig = plotattributes[:x], plotattributes[:y]
# for each point, we create an arrow of velocity vi, translated to the x/y coordinates # for each point, we create an arrow of velocity vi, translated to the x/y coordinates
pts = P2[] pts = P2[]
@ -923,11 +923,11 @@ function quiver_using_hack(d::KW)
nanappend!(pts, P2[p, ppv-U1, ppv-U1+U2, ppv, ppv-U1-U2, ppv-U1]) nanappend!(pts, P2[p, ppv-U1, ppv-U1+U2, ppv, ppv-U1-U2, ppv-U1])
end end
d[:x], d[:y] = Plots.unzip(pts[2:end]) plotattributes[:x], plotattributes[:y] = Plots.unzip(pts[2:end])
# KW[d] # KW[plotattributes]
end end
# function apply_series_recipe(d::KW, ::Type{Val{:quiver}}) # function apply_series_recipe(plotattributes::KW, ::Type{Val{:quiver}})
@recipe function f(::Type{Val{:quiver}}, x, y, z) @recipe function f(::Type{Val{:quiver}}, x, y, z)
if :arrow in supported_attrs() if :arrow in supported_attrs()
quiver_using_arrows(plotattributes) quiver_using_arrows(plotattributes)

View File

@ -8,25 +8,25 @@
const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}}
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(d, :seriestype, :none)) all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none))
# unknown # unknown
convertToAnyVector(x, d::KW) = error("No user recipe defined for $(typeof(x))") convertToAnyVector(x, plotattributes::KW) = error("No user recipe defined for $(typeof(x))")
# missing # missing
convertToAnyVector(v::Nothing, d::KW) = Any[nothing], nothing convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing
# fixed number of blank series # fixed number of blank series
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing
# numeric vector # numeric vector
convertToAnyVector(v::AVec{T}, d::KW) where {T<:Number} = Any[v], nothing convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Number} = Any[v], nothing
# string vector # string vector
convertToAnyVector(v::AVec{T}, d::KW) where {T<:AbstractString} = Any[v], nothing convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:AbstractString} = Any[v], nothing
function convertToAnyVector(v::AMat, d::KW) function convertToAnyVector(v::AMat, plotattributes::KW)
if all3D(d) if all3D(plotattributes)
Any[Surface(v)] Any[Surface(v)]
else else
Any[v[:,i] for i in 1:size(v,2)] Any[v[:,i] for i in 1:size(v,2)]
@ -34,33 +34,33 @@ function convertToAnyVector(v::AMat, d::KW)
end end
# function # function
convertToAnyVector(f::Function, d::KW) = Any[f], nothing convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing
# surface # surface
convertToAnyVector(s::Surface, d::KW) = Any[s], nothing convertToAnyVector(s::Surface, plotattributes::KW) = Any[s], nothing
# volume # volume
convertToAnyVector(v::Volume, d::KW) = Any[v], nothing convertToAnyVector(v::Volume, plotattributes::KW) = Any[v], nothing
# # vector of OHLC # # vector of OHLC
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing # convertToAnyVector(v::AVec{OHLC}, plotattributes::KW) = Any[v], nothing
# # dates # # dates
convertToAnyVector(dts::AVec{D}, d::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing convertToAnyVector(dts::AVec{D}, plotattributes::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else) # list of things (maybe other vectors, functions, or something else)
function convertToAnyVector(v::AVec, d::KW) function convertToAnyVector(v::AVec, plotattributes::KW)
if all(x -> typeof(x) <: Number, v) if all(x -> typeof(x) <: Number, v)
# all real numbers wrap the whole vector as one item # all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing Any[convert(Vector{Float64}, v)], nothing
else else
# something else... treat each element as an item # something else... treat each element as an item
vcat(Any[convertToAnyVector(vi, d)[1] for vi in v]...), nothing vcat(Any[convertToAnyVector(vi, plotattributes)[1] for vi in v]...), nothing
# Any[vi for vi in v], nothing # Any[vi for vi in v], nothing
end end
end end
convertToAnyVector(t::Tuple, d::KW) = Any[t], nothing convertToAnyVector(t::Tuple, plotattributes::KW) = Any[t], nothing
function convertToAnyVector(args...) function convertToAnyVector(args...)
@ -180,14 +180,14 @@ end
# this should catch unhandled "series recipes" and error with a nice message # this should catch unhandled "series recipes" and error with a nice message
@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.") @recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.")
_apply_type_recipe(d, v) = RecipesBase.apply_recipe(d, typeof(v), v)[1].args[1] _apply_type_recipe(plotattributes, v) = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1]
# Handle type recipes when the recipe is defined on the elements. # Handle type recipes when the recipe is defined on the elements.
# This sort of recipe should return a pair of functions... one to convert to number, # This sort of recipe should return a pair of functions... one to convert to number,
# and one to format tick values. # and one to format tick values.
function _apply_type_recipe(d, v::AbstractArray) function _apply_type_recipe(plotattributes, v::AbstractArray)
isempty(v) && return Float64[] isempty(v) && return Float64[]
args = RecipesBase.apply_recipe(d, typeof(v[1]), v[1])[1].args args = RecipesBase.apply_recipe(plotattributes, typeof(v[1]), v[1])[1].args
if length(args) == 2 && typeof(args[1]) <: Function && typeof(args[2]) <: Function if length(args) == 2 && typeof(args[1]) <: Function && typeof(args[2]) <: Function
numfunc, formatter = args numfunc, formatter = args
Formatted(map(numfunc, v), formatter) Formatted(map(numfunc, v), formatter)
@ -197,13 +197,13 @@ function _apply_type_recipe(d, v::AbstractArray)
end end
# # special handling for Surface... need to properly unwrap and re-wrap # # special handling for Surface... need to properly unwrap and re-wrap
# function _apply_type_recipe(d, v::Surface) # function _apply_type_recipe(plotattributes, v::Surface)
# T = eltype(v.surf) # T = eltype(v.surf)
# @show T # @show T
# if T <: Integer || T <: AbstractFloat # if T <: Integer || T <: AbstractFloat
# v # v
# else # else
# ret = _apply_type_recipe(d, v.surf) # ret = _apply_type_recipe(plotattributes, v.surf)
# if typeof(ret) <: Formatted # if typeof(ret) <: Formatted
# Formatted(Surface(ret.data), ret.formatter) # Formatted(Surface(ret.data), ret.formatter)
# else # else
@ -213,7 +213,7 @@ end
# end # end
# don't do anything for ints or floats # don't do anything for ints or floats
_apply_type_recipe(d, v::AbstractArray{T}) where {T<:Union{Integer,AbstractFloat}} = v _apply_type_recipe(plotattributes, v::AbstractArray{T}) where {T<:Union{Integer,AbstractFloat}} = v
# handle "type recipes" by converting inputs, and then either re-calling or slicing # handle "type recipes" by converting inputs, and then either re-calling or slicing
@recipe function f(x, y, z) @recipe function f(x, y, z)
@ -274,11 +274,11 @@ end
# # -------------------------------------------------------------------- # # --------------------------------------------------------------------
# helper function to ensure relevant attributes are wrapped by Surface # helper function to ensure relevant attributes are wrapped by Surface
function wrap_surfaces(d::KW) function wrap_surfaces(plotattributes::KW)
if haskey(d, :fill_z) if haskey(plotattributes, :fill_z)
v = d[:fill_z] v = plotattributes[:fill_z]
if !isa(v, Surface) if !isa(v, Surface)
d[:fill_z] = Surface(v) plotattributes[:fill_z] = Surface(v)
end end
end end
end end
@ -428,17 +428,17 @@ end
# # 3d line or scatter # # 3d line or scatter
@recipe function f(x::AVec, y::AVec, z::AVec) @recipe function f(x::AVec, y::AVec, z::AVec)
# st = get(d, :seriestype, :none) # st = get(plotattributes, :seriestype, :none)
# if st == :scatter # if st == :scatter
# d[:seriestype] = :scatter3d # plotattributes[:seriestype] = :scatter3d
# elseif !is3d(st) # elseif !is3d(st)
# d[:seriestype] = :path3d # plotattributes[:seriestype] = :path3d
# end # end
SliceIt, x, y, z SliceIt, x, y, z
end end
@recipe function f(x::AMat, y::AMat, z::AMat) @recipe function f(x::AMat, y::AMat, z::AMat)
# st = get(d, :seriestype, :none) # st = get(plotattributes, :seriestype, :none)
# if size(x) == size(y) == size(z) # if size(x) == size(y) == size(z)
# if !is3d(st) # if !is3d(st)
# seriestype := :path3d # seriestype := :path3d
@ -573,7 +573,7 @@ end
# # create a new series, with the label of the group, and an idxfilter (to be applied in slice_and_dice) # # create a new series, with the label of the group, and an idxfilter (to be applied in slice_and_dice)
# # TODO: use @series instead # # TODO: use @series instead
# @show i, glab, groupby.groupIds[i] # @show i, glab, groupby.groupIds[i]
# di = copy(d) # di = copy(plotattributes)
# get!(di, :label, string(glab)) # get!(di, :label, string(glab))
# get!(di, :idxfilter, groupby.groupIds[i]) # get!(di, :idxfilter, groupby.groupIds[i])
# push!(series_list, RecipeData(di, args)) # push!(series_list, RecipeData(di, args))

View File

@ -34,16 +34,16 @@ bottompad(sp::Subplot) = sp.minpad[4]
get_subplot(plt::Plot, sp::Subplot) = sp get_subplot(plt::Plot, sp::Subplot) = sp
get_subplot(plt::Plot, i::Integer) = plt.subplots[i] get_subplot(plt::Plot, i::Integer) = plt.subplots[i]
get_subplot(plt::Plot, k) = plt.spmap[k] get_subplot(plt::Plot, k) = plt.spmap[k]
get_subplot(series::Series) = series.d[:subplot] get_subplot(series::Series) = series.plotattributes[:subplot]
get_subplot_index(plt::Plot, idx::Integer) = Int(idx) get_subplot_index(plt::Plot, idx::Integer) = Int(idx)
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(x -> x === sp, plt.subplots) get_subplot_index(plt::Plot, sp::Subplot) = findfirst(x -> x === sp, plt.subplots)
series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot] === sp, sp.plt.series_list) series_list(sp::Subplot) = sp.series_list # filter(series -> series.plotattributes[:subplot] === sp, sp.plt.series_list)
function should_add_to_legend(series::Series) function should_add_to_legend(series::Series)
series.d[:primary] && series.d[:label] != "" && series.plotattributes[:primary] && series.plotattributes[:label] != "" &&
!(series.d[:seriestype] in ( !(series.plotattributes[:seriestype] in (
:hexbin,:bins2d,:histogram2d,:hline,:vline, :hexbin,:bins2d,:histogram2d,:hline,:vline,
:contour,:contourf,:contour3d,:surface,:wireframe, :contour,:contourf,:contour3d,:surface,:wireframe,
:heatmap, :pie, :image :heatmap, :pie, :image

View File

@ -21,11 +21,11 @@ Base.isempty(wrapper::InputWrapper) = false
# ----------------------------------------------------------- # -----------------------------------------------------------
mutable struct Series mutable struct Series
d::KW plotattributes::KW
end end
attr(series::Series, k::Symbol) = series.d[k] attr(series::Series, k::Symbol) = series.plotattributes[k]
attr!(series::Series, v, k::Symbol) = (series.d[k] = v) attr!(series::Series, v, k::Symbol) = (series.plotattributes[k] = v)
# ----------------------------------------------------------- # -----------------------------------------------------------
@ -48,7 +48,7 @@ Base.show(io::IO, sp::Subplot) = print(io, "Subplot{$(sp[:subplot_index])}")
# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place # simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place
mutable struct Axis mutable struct Axis
sps::Vector{Subplot} sps::Vector{Subplot}
d::KW plotattributes::KW
end end
mutable struct Extrema mutable struct Extrema

View File

@ -19,15 +19,15 @@ A hacky replacement for a histogram when the backend doesn't support histograms
Convert it into a bar chart with the appropriate x/y values. Convert it into a bar chart with the appropriate x/y values.
""" """
function histogramHack(; kw...) function histogramHack(; kw...)
d = KW(kw) plotattributes = KW(kw)
# we assume that the y kwarg is set with the data to be binned, and nbins is also defined # we assume that the y kwarg is set with the data to be binned, and nbins is also defined
edges, midpoints, buckets, counts = binData(d[:y], d[:bins]) edges, midpoints, buckets, counts = binData(plotattributes[:y], plotattributes[:bins])
d[:x] = midpoints plotattributes[:x] = midpoints
d[:y] = float(counts) plotattributes[:y] = float(counts)
d[:seriestype] = :bar plotattributes[:seriestype] = :bar
d[:fillrange] = d[:fillrange] == nothing ? 0.0 : d[:fillrange] plotattributes[:fillrange] = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
d plotattributes
end end
""" """
@ -35,10 +35,10 @@ A hacky replacement for a bar graph when the backend doesn't support bars direct
Convert it into a line chart with fillrange set. Convert it into a line chart with fillrange set.
""" """
function barHack(; kw...) function barHack(; kw...)
d = KW(kw) plotattributes = KW(kw)
midpoints = d[:x] midpoints = plotattributes[:x]
heights = d[:y] heights = plotattributes[:y]
fillrange = d[:fillrange] == nothing ? 0.0 : d[:fillrange] fillrange = plotattributes[:fillrange] == nothing ? 0.0 : plotattributes[:fillrange]
# estimate the edges # estimate the edges
dists = diff(midpoints) * 0.5 dists = diff(midpoints) * 0.5
@ -62,11 +62,11 @@ function barHack(; kw...)
append!(y, [fillrange, heights[i], heights[i], fillrange]) append!(y, [fillrange, heights[i], heights[i], fillrange])
end end
d[:x] = x plotattributes[:x] = x
d[:y] = y plotattributes[:y] = y
d[:seriestype] = :path plotattributes[:seriestype] = :path
d[:fillrange] = fillrange plotattributes[:fillrange] = fillrange
d plotattributes
end end
@ -75,33 +75,33 @@ A hacky replacement for a sticks graph when the backend doesn't support sticks d
Convert it into a line chart that traces the sticks, and a scatter that sets markers at the points. Convert it into a line chart that traces the sticks, and a scatter that sets markers at the points.
""" """
function sticksHack(; kw...) function sticksHack(; kw...)
dLine = KW(kw) plotattributesLine = KW(kw)
dScatter = copy(dLine) plotattributesScatter = copy(plotattributesLine)
# these are the line vertices # these are the line vertices
x = Float64[] x = Float64[]
y = Float64[] y = Float64[]
fillrange = dLine[:fillrange] == nothing ? 0.0 : dLine[:fillrange] fillrange = plotattributesLine[:fillrange] == nothing ? 0.0 : plotattributesLine[:fillrange]
# calculate the vertices # calculate the vertices
yScatter = dScatter[:y] yScatter = plotattributesScatter[:y]
for (i,xi) in enumerate(dScatter[:x]) for (i,xi) in enumerate(plotattributesScatter[:x])
yi = yScatter[i] yi = yScatter[i]
for j in 1:3 push!(x, xi) end for j in 1:3 push!(x, xi) end
append!(y, [fillrange, yScatter[i], fillrange]) append!(y, [fillrange, yScatter[i], fillrange])
end end
# change the line args # change the line args
dLine[:x] = x plotattributesLine[:x] = x
dLine[:y] = y plotattributesLine[:y] = y
dLine[:seriestype] = :path plotattributesLine[:seriestype] = :path
dLine[:markershape] = :none plotattributesLine[:markershape] = :none
dLine[:fillrange] = nothing plotattributesLine[:fillrange] = nothing
# change the scatter args # change the scatter args
dScatter[:seriestype] = :none plotattributesScatter[:seriestype] = :none
dLine, dScatter plotattributesLine, plotattributesScatter
end end
function regressionXY(x, y) function regressionXY(x, y)
@ -130,10 +130,10 @@ function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
# newz, ColorGradient(colors) # newz, ColorGradient(colors)
end end
function imageHack(d::KW) function imageHack(plotattributes::KW)
is_seriestype_supported(:heatmap) || error("Neither :image or :heatmap are supported!") is_seriestype_supported(:heatmap) || error("Neither :image or :heatmap are supported!")
d[:seriestype] = :heatmap plotattributes[:seriestype] = :heatmap
d[:z], d[:fillcolor] = replace_image_with_heatmap(d[:z].surf) plotattributes[:z], plotattributes[:fillcolor] = replace_image_with_heatmap(plotattributes[:z].surf)
end end
# --------------------------------------------------------------- # ---------------------------------------------------------------
@ -328,16 +328,16 @@ function replaceType(vec, val)
push!(vec, val) push!(vec, val)
end end
function replaceAlias!(d::KW, k::Symbol, aliases::Dict{Symbol,Symbol}) function replaceAlias!(plotattributes::KW, k::Symbol, aliases::Dict{Symbol,Symbol})
if haskey(aliases, k) if haskey(aliases, k)
d[aliases[k]] = pop!(d, k) plotattributes[aliases[k]] = pop!(plotattributes, k)
end end
end end
function replaceAliases!(d::KW, aliases::Dict{Symbol,Symbol}) function replaceAliases!(plotattributes::KW, aliases::Dict{Symbol,Symbol})
ks = collect(keys(d)) ks = collect(keys(plotattributes))
for k in ks for k in ks
replaceAlias!(d, k, aliases) replaceAlias!(plotattributes, k, aliases)
end end
end end
@ -347,7 +347,7 @@ Base.first(c::Colorant) = c
Base.first(x::Symbol) = x Base.first(x::Symbol) = x
sortedkeys(d::Dict) = sort(collect(keys(d))) sortedkeys(plotattributes::Dict) = sort(collect(keys(plotattributes)))
const _scale_base = Dict{Symbol, Real}( const _scale_base = Dict{Symbol, Real}(
@ -432,8 +432,8 @@ isscalar(::Any) = false
is_2tuple(v) = typeof(v) <: Tuple && length(v) == 2 is_2tuple(v) = typeof(v) <: Tuple && length(v) == 2
isvertical(d::KW) = get(d, :orientation, :vertical) in (:vertical, :v, :vert) isvertical(plotattributes::KW) = get(plotattributes, :orientation, :vertical) in (:vertical, :v, :vert)
isvertical(series::Series) = isvertical(series.d) isvertical(series::Series) = isvertical(series.plotattributes)
ticksType(ticks::AVec{T}) where {T<:Real} = :ticks ticksType(ticks::AVec{T}) where {T<:Real} = :ticks
@ -492,8 +492,8 @@ end
# this is a helper function to determine whether we need to transpose a surface matrix. # this is a helper function to determine whether we need to transpose a surface matrix.
# it depends on whether the backend matches rows to x (transpose_on_match == true) or vice versa # it depends on whether the backend matches rows to x (transpose_on_match == true) or vice versa
# for example: PyPlot sends rows to y, so transpose_on_match should be true # for example: PyPlot sends rows to y, so transpose_on_match should be true
function transpose_z(d, z, transpose_on_match::Bool = true) function transpose_z(plotattributes, z, transpose_on_match::Bool = true)
if d[:match_dimensions] == transpose_on_match if plotattributes[:match_dimensions] == transpose_on_match
# z' # z'
permutedims(z, [2,1]) permutedims(z, [2,1])
else else
@ -806,20 +806,20 @@ end
debugshow(x) = show(x) debugshow(x) = show(x)
debugshow(x::AbstractArray) = print(summary(x)) debugshow(x::AbstractArray) = print(summary(x))
function dumpdict(d::KW, prefix = "", alwaysshow = false) function dumpdict(plotattributes::KW, prefix = "", alwaysshow = false)
_debugMode.on || alwaysshow || return _debugMode.on || alwaysshow || return
println() println()
if prefix != "" if prefix != ""
println(prefix, ":") println(prefix, ":")
end end
for k in sort(collect(keys(d))) for k in sort(collect(keys(plotattributes)))
@printf("%14s: ", k) @printf("%14s: ", k)
debugshow(d[k]) debugshow(plotattributes[k])
println() println()
end end
println() println()
end end
DD(d::KW, prefix = "") = dumpdict(d, prefix, true) DD(plotattributes::KW, prefix = "") = dumpdict(plotattributes, prefix, true)
function dumpcallstack() function dumpcallstack()
@ -845,25 +845,25 @@ tovec(v::AbstractVector) = v
tovec(v::Nothing) = zeros(0) tovec(v::Nothing) = zeros(0)
function getxy(plt::Plot, i::Integer) function getxy(plt::Plot, i::Integer)
d = plt.series_list[i].d plotattributes = plt.series_list[i].plotattributes
tovec(d[:x]), tovec(d[:y]) tovec(plotattributes[:x]), tovec(plotattributes[:y])
end end
function getxyz(plt::Plot, i::Integer) function getxyz(plt::Plot, i::Integer)
d = plt.series_list[i].d plotattributes = plt.series_list[i].plotattributes
tovec(d[:x]), tovec(d[:y]), tovec(d[:z]) tovec(plotattributes[:x]), tovec(plotattributes[:y]), tovec(plotattributes[:z])
end end
function setxy!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y} function setxy!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y}
series = plt.series_list[i] series = plt.series_list[i]
series.d[:x], series.d[:y] = xy series.plotattributes[:x], series.plotattributes[:y] = xy
sp = series.d[:subplot] sp = series.plotattributes[:subplot]
reset_extrema!(sp) reset_extrema!(sp)
_series_updated(plt, series) _series_updated(plt, series)
end end
function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z} function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z}
series = plt.series_list[i] series = plt.series_list[i]
series.d[:x], series.d[:y], series.d[:z] = xyz series.plotattributes[:x], series.plotattributes[:y], series.plotattributes[:z] = xyz
sp = series.d[:subplot] sp = series.plotattributes[:subplot]
reset_extrema!(sp) reset_extrema!(sp)
_series_updated(plt, series) _series_updated(plt, series)
end end
@ -912,9 +912,9 @@ Base.push!(series::Series, xi, yi, zi) = (push_x!(series,xi); push_y!(series,yi)
# ------------------------------------------------------- # -------------------------------------------------------
function attr!(series::Series; kw...) function attr!(series::Series; kw...)
d = KW(kw) plotattributes = KW(kw)
preprocessArgs!(d) preprocessArgs!(plotattributes)
for (k,v) in d for (k,v) in plotattributes
if haskey(_series_defaults, k) if haskey(_series_defaults, k)
series[k] = v series[k] = v
else else
@ -926,9 +926,9 @@ function attr!(series::Series; kw...)
end end
function attr!(sp::Subplot; kw...) function attr!(sp::Subplot; kw...)
d = KW(kw) plotattributes = KW(kw)
preprocessArgs!(d) preprocessArgs!(plotattributes)
for (k,v) in d for (k,v) in plotattributes
if haskey(_subplot_defaults, k) if haskey(_subplot_defaults, k)
sp[k] = v sp[k] = v
else else
@ -1057,9 +1057,9 @@ mm2px(mm::Real) = float(px / MM_PER_PX)
"Smallest x in plot" "Smallest x in plot"
xmin(plt::Plot) = ignorenan_minimum([ignorenan_minimum(series.d[:x]) for series in plt.series_list]) xmin(plt::Plot) = ignorenan_minimum([ignorenan_minimum(series.plotattributes[:x]) for series in plt.series_list])
"Largest x in plot" "Largest x in plot"
xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.d[:x]) for series in plt.series_list]) xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.plotattributes[:x]) for series in plt.series_list])
"Extrema of x-values in plot" "Extrema of x-values in plot"
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt)) ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))