Plot line and hatched fill handles on top of each other in py_add_legend

This commit is contained in:
Pearl Li 2021-08-25 12:36:31 -07:00
parent 7f594413af
commit b0cf3ba498

View File

@ -1488,65 +1488,82 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
if should_add_to_legend(series) if should_add_to_legend(series)
clims = get_clims(sp, series) clims = get_clims(sp, series)
# add a line/marker and a label # add a line/marker and a label
push!( if series[:seriestype] == :shape || series[:fillrange] !== nothing
handles, lc = get_linecolor(series, clims)
if series[:seriestype] == :shape || series[:fillrange] !== nothing la = get_linealpha(series)
fs = get_fillstyle(series) ls = get_linestyle(series)
has_fs = !isnothing(fs) fc = get_fillcolor(series, clims)
lc = get_linecolor(series, clims) fa = get_fillalpha(series)
la = get_linealpha(series) fs = get_fillstyle(series)
fc = get_fillcolor(series, clims) has_fs = !isnothing(fs)
fa = get_fillalpha(series)
pypatches."Patch"( # line (and potentially solid fill)
# hatch color/alpha controlled by edge (not face) color/alpha line_handle = pypatches."Patch"(
# if has_fs, set edge color/alpha <- fill color/alpha and face alpha <- 0 edgecolor = py_color(single_color(lc), la),
edgecolor = has_fs ? py_color(single_color(fc), fa) : py_color(single_color(lc), la), facecolor = py_color(single_color(fc), has_fs ? 0 : fa),
facecolor = py_color(single_color(fc), has_fs ? 0 : fa), linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
linestyle = py_linestyle(series[:seriestype], ls),
capstyle = "butt",
)
# hatched fill
# hatch color/alpha are controlled by edge (not face) color/alpha
if has_fs
fill_handle = pypatches."Patch"(
edgecolor = py_color(single_color(fc), fa),
facecolor = py_color(single_color(fc), 0), # don't fill with solid background
hatch = py_fillstyle(fs), hatch = py_fillstyle(fs),
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)), linewidth = 0, # don't replot shape outline (doesn't affect hatch linewidth)
linestyle = py_linestyle(series[:seriestype], get_linestyle(series)), linestyle = py_linestyle(series[:seriestype], ls),
capstyle = "butt" capstyle = "butt",
)
elseif series[:seriestype] in
(:path, :straightline, :scatter, :steppre, :stepmid, :steppost)
hasline = get_linewidth(series) > 0
PyPlot.plt."Line2D"(
(0, 1),
(0, 0),
color = py_color(
single_color(get_linecolor(series, clims)),
get_linealpha(series),
),
linewidth = py_thickness_scale(
plt,
hasline * sp[:legendfontsize] / 8,
),
linestyle = py_linestyle(:path, get_linestyle(series)),
solid_capstyle = "butt",
solid_joinstyle = "miter",
dash_capstyle = "butt",
dash_joinstyle = "miter",
marker = py_marker(_cycle(series[:markershape], 1)),
markersize = py_thickness_scale(plt, 0.8 * sp[:legendfontsize]),
markeredgecolor = py_color(
single_color(get_markerstrokecolor(series)),
get_markerstrokealpha(series),
),
markerfacecolor = py_color(
single_color(get_markercolor(series, clims)),
get_markeralpha(series),
),
markeredgewidth = py_thickness_scale(
plt,
0.8 * get_markerstrokewidth(series) * sp[:legendfontsize] /
first(series[:markersize]),
), # retain the markersize/markerstroke ratio from the markers on the plot
) )
# plot two handles on top of each other by passing in a tuple
# https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html
push!(handles, (line_handle, fill_handle))
else else
series[:serieshandle][1] # plot line handle (which includes solid fill) only
end, push!(handles, line_handle)
) end
elseif series[:seriestype] in
(:path, :straightline, :scatter, :steppre, :stepmid, :steppost)
hasline = get_linewidth(series) > 0
handle = PyPlot.plt."Line2D"(
(0, 1),
(0, 0),
color = py_color(
single_color(get_linecolor(series, clims)),
get_linealpha(series),
),
linewidth = py_thickness_scale(
plt,
hasline * sp[:legendfontsize] / 8,
),
linestyle = py_linestyle(:path, get_linestyle(series)),
solid_capstyle = "butt",
solid_joinstyle = "miter",
dash_capstyle = "butt",
dash_joinstyle = "miter",
marker = py_marker(_cycle(series[:markershape], 1)),
markersize = py_thickness_scale(plt, 0.8 * sp[:legendfontsize]),
markeredgecolor = py_color(
single_color(get_markerstrokecolor(series)),
get_markerstrokealpha(series),
),
markerfacecolor = py_color(
single_color(get_markercolor(series, clims)),
get_markeralpha(series),
),
markeredgewidth = py_thickness_scale(
plt,
0.8 * get_markerstrokewidth(series) * sp[:legendfontsize] /
first(series[:markersize]),
), # retain the markersize/markerstroke ratio from the markers on the plot
)
push!(handles, handle)
else
push!(handles, series[:serieshandle][1])
end
push!(labels, series[:label]) push!(labels, series[:label])
end end
end end