fix marker shapes with segments on gr, pyplot and plotly
This commit is contained in:
parent
8ffac4d20e
commit
0b91d51a40
@ -348,12 +348,15 @@ function gr_draw_markers(
|
|||||||
|
|
||||||
shapes = series[:markershape]
|
shapes = series[:markershape]
|
||||||
if shapes != :none
|
if shapes != :none
|
||||||
for (i, rng) in enumerate(iter_segments(series))
|
for (i, rng) in enumerate(iter_segments(series, :scatter))
|
||||||
ms = get_thickness_scaling(series) * _cycle(msize, i)
|
rng = intersect(eachindex(x), rng)
|
||||||
msw = get_thickness_scaling(series) * _cycle(strokewidth, i)
|
if !isempty(rng)
|
||||||
shape = _cycle(shapes, i)
|
ms = get_thickness_scaling(series) * _cycle(msize, i)
|
||||||
for j in rng
|
msw = get_thickness_scaling(series) * _cycle(strokewidth, i)
|
||||||
gr_draw_marker(series, _cycle(x, j), _cycle(y, j), clims, i, ms, msw, shape)
|
shape = _cycle(shapes, i)
|
||||||
|
for j in rng
|
||||||
|
gr_draw_marker(series, _cycle(x, j), _cycle(y, j), clims, i, ms, msw, shape)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1634,7 +1637,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
if st in (:path, :scatter, :straightline)
|
if st in (:path, :scatter, :straightline)
|
||||||
if x !== nothing && length(x) > 1
|
if x !== nothing && length(x) > 1
|
||||||
lz = series[:line_z]
|
lz = series[:line_z]
|
||||||
segments = iter_segments(series)
|
segments = iter_segments(series, st)
|
||||||
# do area fill
|
# do area fill
|
||||||
if frng !== nothing
|
if frng !== nothing
|
||||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||||
@ -1759,7 +1762,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
if st == :path3d
|
if st == :path3d
|
||||||
if length(x) > 1
|
if length(x) > 1
|
||||||
lz = series[:line_z]
|
lz = series[:line_z]
|
||||||
segments = iter_segments(series)
|
segments = iter_segments(series, st)
|
||||||
for (i, rng) in enumerate(segments)
|
for (i, rng) in enumerate(segments)
|
||||||
lc = get_linecolor(series, clims, i)
|
lc = get_linecolor(series, clims, i)
|
||||||
gr_set_line(
|
gr_set_line(
|
||||||
|
|||||||
@ -299,13 +299,13 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
|||||||
series[:z],
|
series[:z],
|
||||||
)...)
|
)...)
|
||||||
else
|
else
|
||||||
iter_segments(series)
|
iter_segments(series, st)
|
||||||
end
|
end
|
||||||
for (i, rng) in enumerate(segments)
|
for (i, rng) in enumerate(segments)
|
||||||
segment_opt = PGFPlotsX.Options()
|
segment_opt = PGFPlotsX.Options()
|
||||||
segment_opt = merge(segment_opt, pgfx_linestyle(opt, i))
|
segment_opt = merge(segment_opt, pgfx_linestyle(opt, i))
|
||||||
if opt[:markershape] != :none
|
if opt[:markershape] != :none
|
||||||
marker = opt[:markershape]
|
marker = _cycle(opt[:markershape], i)
|
||||||
if marker isa Shape
|
if marker isa Shape
|
||||||
x = marker.x
|
x = marker.x
|
||||||
y = marker.y
|
y = marker.y
|
||||||
|
|||||||
@ -694,9 +694,11 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
|
|||||||
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))
|
||||||
|
|
||||||
segments = iter_segments(series)
|
segments = iter_segments(series, st)
|
||||||
plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1 ) * length(segments))
|
plotattributes_outs = fill(KW(), (hasfillrange ? 2 : 1 ) * length(segments))
|
||||||
|
|
||||||
|
needs_scatter_fix = !isscatter && hasmarker && !any(isnan,y)
|
||||||
|
|
||||||
for (i,rng) in enumerate(segments)
|
for (i,rng) in enumerate(segments)
|
||||||
plotattributes_out = deepcopy(plotattributes_base)
|
plotattributes_out = deepcopy(plotattributes_base)
|
||||||
plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
|
plotattributes_out[:showlegend] = i==1 ? should_add_to_legend(series) : false
|
||||||
@ -733,13 +735,15 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
|
|||||||
|
|
||||||
# add "marker"
|
# add "marker"
|
||||||
if hasmarker
|
if hasmarker
|
||||||
|
mcolor = rgba_string(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i)))
|
||||||
|
lcolor = rgba_string(plot_color(get_markerstrokecolor(series, i), get_markerstrokealpha(series, i)))
|
||||||
plotattributes_out[:marker] = KW(
|
plotattributes_out[:marker] = KW(
|
||||||
:symbol => get_plotly_marker(_cycle(series[:markershape], i), string(_cycle(series[:markershape], i))),
|
:symbol => get_plotly_marker(_cycle(series[:markershape], i), string(_cycle(series[:markershape], i))),
|
||||||
# :opacity => series[:markeralpha],
|
# :opacity => needs_scatter_fix ? [1, 0] : 1,
|
||||||
:size => 2 * _cycle(series[:markersize], i),
|
:size => 2 * _cycle(series[:markersize], i),
|
||||||
:color => rgba_string(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i))),
|
:color => needs_scatter_fix ? [mcolor, "rgba(0, 0, 0, 0.000)"] : mcolor,
|
||||||
:line => KW(
|
:line => KW(
|
||||||
:color => rgba_string(plot_color(get_markerstrokecolor(series, i), get_markerstrokealpha(series, i))),
|
:color => needs_scatter_fix ? [lcolor, "rgba(0, 0, 0, 0.000)"] : lcolor,
|
||||||
:width => _cycle(series[:markerstrokewidth], i),
|
:width => _cycle(series[:markerstrokewidth], i),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -398,7 +398,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
# line plot
|
# line plot
|
||||||
if st in (:path, :path3d, :steppre, :steppost, :straightline)
|
if st in (:path, :path3d, :steppre, :steppost, :straightline)
|
||||||
if maximum(series[:linewidth]) > 0
|
if maximum(series[:linewidth]) > 0
|
||||||
segments = iter_segments(series)
|
|
||||||
# TODO: check LineCollection alternative for speed
|
# TODO: check LineCollection alternative for speed
|
||||||
# if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] !== nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
|
# if length(segments) > 1 && (any(typeof(series[attr]) <: AbstractVector for attr in (:fillcolor, :fillalpha)) || series[:fill_z] !== nothing) && !(typeof(series[:linestyle]) <: AbstractVector)
|
||||||
# # multicolored line segments
|
# # multicolored line segments
|
||||||
@ -429,7 +428,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
# end
|
# end
|
||||||
# push!(handles, handle)
|
# push!(handles, handle)
|
||||||
# else
|
# else
|
||||||
for (i, rng) in enumerate(iter_segments(series))
|
for (i, rng) in enumerate(iter_segments(series, st))
|
||||||
handle = ax."plot"((arg[rng] for arg in xyargs)...;
|
handle = ax."plot"((arg[rng] for arg in xyargs)...;
|
||||||
label = i == 1 ? series[:label] : "",
|
label = i == 1 ? series[:label] : "",
|
||||||
zorder = series[:series_plotindex],
|
zorder = series[:series_plotindex],
|
||||||
@ -472,130 +471,24 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# add markers?
|
# add markers?
|
||||||
if series[:markershape] != :none && st in (:path, :scatter, :path3d,
|
if series[:markershape] != :none && st in (
|
||||||
:scatter3d, :steppre, :steppost,
|
:path, :scatter, :path3d, :scatter3d, :steppre, :steppost, :bar
|
||||||
:bar)
|
)
|
||||||
markercolor = if any(typeof(series[arg]) <: AVec for arg in (:markercolor, :markeralpha)) || series[:marker_z] !== nothing
|
for (i, rng) in enumerate(iter_segments(series, :scatter))
|
||||||
# py_color(plot_color.(get_markercolor.(series, clims, eachindex(x)), get_markeralpha.(series, eachindex(x))))
|
xyargs = if st == :bar && !isvertical(series)
|
||||||
[py_color(plot_color(get_markercolor(series, clims, i), get_markeralpha(series, i))) for i in eachindex(x)]
|
y[rng], x[rng]
|
||||||
else
|
else
|
||||||
py_color(plot_color(series[:markercolor], series[:markeralpha]))
|
x[rng], y[rng]
|
||||||
end
|
|
||||||
extrakw[:c] = if markercolor isa Array
|
|
||||||
permutedims(hcat([[m...] for m in markercolor]...),[2,1])
|
|
||||||
elseif markercolor isa Tuple
|
|
||||||
reshape([markercolor...], 1, length(markercolor))
|
|
||||||
else
|
|
||||||
error("This case is not handled. Please file an issue.")
|
|
||||||
end
|
|
||||||
xyargs = if st == :bar && !isvertical(series)
|
|
||||||
(y, x)
|
|
||||||
else
|
|
||||||
xyargs
|
|
||||||
end
|
|
||||||
|
|
||||||
if isa(series[:markershape], AbstractVector{Shape})
|
|
||||||
# this section will create one scatter per data point to accommodate the
|
|
||||||
# vector of shapes
|
|
||||||
handle = []
|
|
||||||
x,y = xyargs
|
|
||||||
shapes = series[:markershape]
|
|
||||||
msc = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series))
|
|
||||||
lw = py_thickness_scale(plt, series[:markerstrokewidth])
|
|
||||||
for i=eachindex(y)
|
|
||||||
if series[:marker_z] !== nothing
|
|
||||||
extrakw[:c] = [py_color(get_markercolor(series, i), get_markercoloralpha(series, i))]
|
|
||||||
end
|
|
||||||
|
|
||||||
push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i);
|
|
||||||
label = series[:label],
|
|
||||||
zorder = series[:series_plotindex] + 0.5,
|
|
||||||
marker = py_marker(_cycle(shapes,i)),
|
|
||||||
s = py_thickness_scale(plt, _cycle(series[:markersize],i)).^ 2,
|
|
||||||
facecolors = py_color(get_markercolor(series, i), get_markercoloralpha(series, i)),
|
|
||||||
edgecolors = msc,
|
|
||||||
linewidths = lw,
|
|
||||||
extrakw...
|
|
||||||
))
|
|
||||||
end
|
|
||||||
push!(handles, handle)
|
|
||||||
elseif isa(series[:markershape], AbstractVector{Symbol})
|
|
||||||
handle = []
|
|
||||||
x,y = xyargs
|
|
||||||
shapes = series[:markershape]
|
|
||||||
|
|
||||||
prev_marker = py_marker(_cycle(shapes,1))
|
|
||||||
|
|
||||||
cur_x_list = []
|
|
||||||
cur_y_list = []
|
|
||||||
|
|
||||||
cur_color_list = []
|
|
||||||
cur_scale_list = []
|
|
||||||
|
|
||||||
delete!(extrakw, :c)
|
|
||||||
|
|
||||||
for i=eachindex(y)
|
|
||||||
cur_marker = py_marker(_cycle(shapes,i))
|
|
||||||
|
|
||||||
if ( cur_marker == prev_marker )
|
|
||||||
push!(cur_x_list, _cycle(x,i))
|
|
||||||
push!(cur_y_list, _cycle(y,i))
|
|
||||||
|
|
||||||
push!(cur_color_list, _cycle(markercolor, i))
|
|
||||||
push!(cur_scale_list, py_thickness_scale(plt, _cycle(series[:markersize],i)).^ 2)
|
|
||||||
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
|
|
||||||
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
|
|
||||||
label = series[:label],
|
|
||||||
zorder = series[:series_plotindex] + 0.5,
|
|
||||||
marker = prev_marker,
|
|
||||||
s = cur_scale_list,
|
|
||||||
edgecolors = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
|
|
||||||
linewidths = py_thickness_scale(plt, series[:markerstrokewidth]),
|
|
||||||
facecolors = cur_color_list,
|
|
||||||
extrakw...
|
|
||||||
))
|
|
||||||
|
|
||||||
cur_x_list = [_cycle(x,i)]
|
|
||||||
cur_y_list = [_cycle(y,i)]
|
|
||||||
|
|
||||||
cur_color_list = [_cycle(markercolor, i)]
|
|
||||||
cur_scale_list = [py_thickness_scale(plt, _cycle(series[:markersize],i)) .^ 2]
|
|
||||||
|
|
||||||
prev_marker = cur_marker
|
|
||||||
end
|
|
||||||
|
|
||||||
if !isempty(cur_color_list)
|
|
||||||
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
|
|
||||||
label = series[:label],
|
|
||||||
zorder = series[:series_plotindex] + 0.5,
|
|
||||||
marker = prev_marker,
|
|
||||||
s = cur_scale_list,
|
|
||||||
edgecolors = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
|
|
||||||
linewidths = py_thickness_scale(plt, series[:markerstrokewidth]),
|
|
||||||
facecolors = cur_color_list,
|
|
||||||
extrakw...
|
|
||||||
))
|
|
||||||
end
|
|
||||||
|
|
||||||
push!(handles, handle)
|
|
||||||
else
|
|
||||||
# do a normal scatter plot
|
|
||||||
|
|
||||||
# Add depthshade option for 3d plots
|
|
||||||
if RecipesPipeline.is3d(sp)
|
|
||||||
extrakw[:depthshade] = get(series[:extra_kwargs], :depthshade, false)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
handle = ax."scatter"(xyargs...;
|
handle = ax."scatter"(xyargs...;
|
||||||
label = series[:label],
|
label = series[:label],
|
||||||
zorder = series[:series_plotindex] + 0.5,
|
zorder = series[:series_plotindex] + 0.5,
|
||||||
marker = py_marker(series[:markershape]),
|
marker = py_marker(_cycle(series[:markershape], i)),
|
||||||
s = py_thickness_scale(plt, series[:markersize]) .^2,
|
s = py_thickness_scale(plt, _cycle(series[:markersize], i)).^ 2,
|
||||||
edgecolors = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
|
facecolors = py_color(get_markercolor(series, i), get_markeralpha(series, i)),
|
||||||
linewidths = py_thickness_scale(plt, series[:markerstrokewidth]),
|
edgecolors = py_color(get_markerstrokecolor(series, i), get_markerstrokealpha(series, i)),
|
||||||
|
linewidths = py_thickness_scale(plt, get_markerstrokewidth(series, i)),
|
||||||
extrakw...
|
extrakw...
|
||||||
)
|
)
|
||||||
push!(handles, handle)
|
push!(handles, handle)
|
||||||
|
|||||||
13
src/utils.jl
13
src/utils.jl
@ -67,19 +67,17 @@ function iter_segments(args...)
|
|||||||
SegmentsIterator(tup, n1, n2)
|
SegmentsIterator(tup, n1, n2)
|
||||||
end
|
end
|
||||||
|
|
||||||
function iter_segments(series::Series)
|
function iter_segments(series::Series, seriestype::Symbol = :path)
|
||||||
x, y, z = series[:x], series[:y], series[:z]
|
x, y, z = series[:x], series[:y], series[:z]
|
||||||
if x === nothing
|
if x === nothing
|
||||||
return UnitRange{Int}[]
|
return UnitRange{Int}[]
|
||||||
elseif has_attribute_segments(series)
|
elseif has_attribute_segments(series)
|
||||||
if series[:seriestype] in (:scatter, :scatter3d)
|
if any(isnan,y)
|
||||||
|
return [iter_segments(y)...]
|
||||||
|
elseif seriestype in (:scatter, :scatter3d)
|
||||||
return [[i] for i in eachindex(y)]
|
return [[i] for i in eachindex(y)]
|
||||||
else
|
else
|
||||||
if any(isnan,y)
|
return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
|
||||||
return [iter_segments(y)...]
|
|
||||||
else
|
|
||||||
return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
segs = UnitRange{Int}[]
|
segs = UnitRange{Int}[]
|
||||||
@ -617,6 +615,7 @@ function has_attribute_segments(series::Series)
|
|||||||
:markerstrokecolor,
|
:markerstrokecolor,
|
||||||
:markerstrokealpha,
|
:markerstrokealpha,
|
||||||
:markerstrokewidth,
|
:markerstrokewidth,
|
||||||
|
:markershape,
|
||||||
]
|
]
|
||||||
) || any(
|
) || any(
|
||||||
typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z)
|
typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user