Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc51f2c159 | ||
|
|
cc1f662b3a | ||
|
|
7b77527f80 | ||
|
|
8b6073c088 | ||
|
|
09d35d7b9f | ||
|
|
0a9da21443 | ||
|
|
ea686c331b | ||
|
|
25a36bab85 | ||
|
|
b227fb8943 | ||
|
|
22651e8728 | ||
|
|
5acf967a9e | ||
|
|
5afeba656b | ||
|
|
7b8bd5b253 | ||
|
|
ded808477d |
@@ -1,2 +0,0 @@
|
||||
github_checks:
|
||||
annotations: false
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
name = "Plots"
|
||||
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
author = ["Tom Breloff (@tbreloff)"]
|
||||
version = "1.21.0"
|
||||
version = "1.21.2"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
@@ -46,7 +46,7 @@ NaNMath = "0.3"
|
||||
PlotThemes = "2"
|
||||
PlotUtils = "1"
|
||||
RecipesBase = "1"
|
||||
RecipesPipeline = "0.3"
|
||||
RecipesPipeline = "0.3.5, 0.4"
|
||||
Reexport = "0.2, 1.0"
|
||||
Requires = "1"
|
||||
Scratch = "1"
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
github_checks:
|
||||
annotations: false
|
||||
|
||||
ignore:
|
||||
- "src/backends/inspectdr.jl"
|
||||
- "src/backends/orca.jl"
|
||||
|
||||
@@ -14,6 +14,7 @@ const _arg_desc = KW(
|
||||
:fillcolor => "Color Type. Color of the filled area of path or bar types. `:match` will take the value from `:seriescolor`.",
|
||||
:fillalpha => "Number in [0,1]. The alpha/opacity override for the fill area. `nothing` (the default) means it will take the alpha value of fillcolor.",
|
||||
:markershape => "Symbol, Shape, or AbstractVector. Choose from $(_allMarkers).",
|
||||
:fillstyle => "Symbol. Style of the fill area. `nothing` (the default) means solid fill. Choose from :/, :\\, :|, :-, :+, :x",
|
||||
:markercolor => "Color Type. Color of the interior of the marker or shape. `:match` will take the value from `:seriescolor`.",
|
||||
:markeralpha => "Number in [0,1]. The alpha/opacity override for the marker interior. `nothing` (the default) means it will take the alpha value of markercolor.",
|
||||
:markersize => "Number or AbstractVector. Size (radius pixels) of the markers",
|
||||
|
||||
@@ -348,6 +348,7 @@ const _series_defaults = KW(
|
||||
:fillrange => nothing, # ribbons, areas, etc
|
||||
:fillcolor => :match,
|
||||
:fillalpha => nothing,
|
||||
:fillstyle => nothing,
|
||||
:markershape => :none,
|
||||
:markercolor => :match,
|
||||
:markeralpha => nothing,
|
||||
@@ -1117,6 +1118,7 @@ function processLineArg(plotattributes::AKW, arg)
|
||||
arg.color == :auto ? :auto : plot_color(arg.color)
|
||||
)
|
||||
arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
|
||||
arg.style === nothing || (plotattributes[:fillstyle] = arg.style)
|
||||
|
||||
elseif typeof(arg) <: Arrow || arg in (:arrow, :arrows)
|
||||
plotattributes[:arrow] = arg
|
||||
@@ -1188,6 +1190,7 @@ function processFillArg(plotattributes::AKW, arg)
|
||||
arg.color == :auto ? :auto : plot_color(arg.color)
|
||||
)
|
||||
arg.alpha === nothing || (plotattributes[:fillalpha] = arg.alpha)
|
||||
arg.style === nothing || (plotattributes[:fillstyle] = arg.style)
|
||||
|
||||
elseif typeof(arg) <: Bool
|
||||
plotattributes[:fillrange] = arg ? 0 : nothing
|
||||
|
||||
@@ -928,6 +928,7 @@ const _unicodeplots_seriestype = [
|
||||
# :bar,
|
||||
:shape,
|
||||
:histogram2d,
|
||||
:heatmap,
|
||||
:spy,
|
||||
]
|
||||
const _unicodeplots_style = [:auto, :solid]
|
||||
|
||||
+10
-3
@@ -225,13 +225,13 @@ function gaston_add_series(plt::Plot{GastonBackend}, series::Series)
|
||||
gsp = sp.o
|
||||
x, y, z = series[:x], series[:y], series[:z]
|
||||
st = series[:seriestype]
|
||||
|
||||
curves = []
|
||||
if gsp.dims == 2 && z === nothing
|
||||
for (n, seg) in enumerate(series_segments(series, st; check = true))
|
||||
i, rng = seg.attr_index, seg.range
|
||||
fr = _cycle(series[:fillrange], 1:length(x[rng]))
|
||||
for sc in gaston_seriesconf!(sp, series, i, n == 1)
|
||||
push!(curves, Gaston.Curve(x[rng], y[rng], nothing, nothing, sc))
|
||||
push!(curves, Gaston.Curve(x[rng], y[rng], nothing, fr, sc))
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -304,8 +304,15 @@ function gaston_seriesconf!(
|
||||
pt, ps, mc = gaston_mk_ms_mc(series, clims, i)
|
||||
push!(curveconf, "w points pt $pt ps $ps lc $mc")
|
||||
elseif st ∈ (:path, :straightline, :path3d)
|
||||
fr = series[:fillrange]
|
||||
fc = gaston_color(get_fillcolor(series, i), get_fillalpha(series, i))
|
||||
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
|
||||
if series[:markershape] == :none # simplepath
|
||||
if fr !== nothing # filled curves, but not filled curves with markers
|
||||
push!(
|
||||
curveconf,
|
||||
"w filledcurves fc $fc fs solid border lc $lc lw $lw dt $dt,'' w lines lc $lc lw $lw dt $dt",
|
||||
)
|
||||
elseif series[:markershape] == :none # simplepath
|
||||
push!(curveconf, "w lines lc $lc dt $dt lw $lw")
|
||||
else
|
||||
pt, ps, mc = gaston_mk_ms_mc(series, clims, i)
|
||||
|
||||
+13
-1
@@ -136,6 +136,12 @@ gr_set_arrowstyle(s::Symbol) = GR.setarrowstyle(
|
||||
),
|
||||
)
|
||||
|
||||
gr_set_fillstyle(::Nothing) = GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||
function gr_set_fillstyle(s::Symbol)
|
||||
GR.setfillintstyle(GR.INTSTYLE_HATCH)
|
||||
GR.setfillstyle(get(((/) = 9, (\) = 10, (|) = 7, (-) = 8, (+) = 11, (x) = 6), s, 9))
|
||||
end
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
# draw line segments, splitting x/y into contiguous/finite segments
|
||||
@@ -1058,7 +1064,9 @@ function gr_add_legend(sp, leg, viewport_plotarea)
|
||||
series[:ribbon] === nothing
|
||||
)
|
||||
fc = get_fillcolor(series, clims)
|
||||
gr_set_fill(fc) #, series[:fillalpha])
|
||||
gr_set_fill(fc)
|
||||
fs = get_fillstyle(series, i)
|
||||
gr_set_fillstyle(fs)
|
||||
l, r = xpos - leg.width_factor * 3.5, xpos - leg.width_factor / 2
|
||||
b, t = ypos - 0.4 * leg.dy, ypos + 0.4 * leg.dy
|
||||
x = [l, r, r, l, l]
|
||||
@@ -1824,6 +1832,8 @@ function gr_draw_segments(series, x, y, fillrange, clims)
|
||||
i, rng = segment.attr_index, segment.range
|
||||
fc = get_fillcolor(series, clims, i)
|
||||
gr_set_fillcolor(fc)
|
||||
fs = get_fillstyle(series, i)
|
||||
gr_set_fillstyle(fs)
|
||||
fx = _cycle(x, vcat(rng, reverse(rng)))
|
||||
fy = vcat(_cycle(fr_from, rng), _cycle(fr_to, reverse(rng)))
|
||||
gr_set_transparency(fc, get_fillalpha(series, i))
|
||||
@@ -1912,6 +1922,8 @@ function gr_draw_shapes(series, clims)
|
||||
# draw the interior
|
||||
fc = get_fillcolor(series, clims, i)
|
||||
gr_set_fill(fc)
|
||||
fs = get_fillstyle(series, i)
|
||||
gr_set_fillstyle(fs)
|
||||
gr_set_transparency(fc, get_fillalpha(series, i))
|
||||
GR.fillarea(xseg, yseg)
|
||||
|
||||
|
||||
@@ -1174,6 +1174,12 @@ function pgfx_sanitize_plot!(plt)
|
||||
end
|
||||
elseif value isa Union{AbstractString,AbstractVector{<:AbstractString}}
|
||||
subplot.attr[key] = pgfx_sanitize_string.(value)
|
||||
elseif value isa Axis
|
||||
for (k, v) in value.plotattributes
|
||||
if v isa Union{AbstractString,AbstractVector{<:AbstractString}}
|
||||
value.plotattributes[k] = pgfx_sanitize_string.(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1232,6 +1238,12 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
|
||||
opt,
|
||||
string(letter, "label style") => PGFPlotsX.Options(
|
||||
labelpos => nothing,
|
||||
"at" => string(
|
||||
"{(ticklabel cs:",
|
||||
get((left = 0, right = 1), axis[:guidefonthalign], 0.5),
|
||||
")}",
|
||||
),
|
||||
"anchor" => "near ticklabel",
|
||||
"font" => pgfx_font(axis[:guidefontsize], pgfx_thickness_scaling(sp)),
|
||||
"color" => cstr,
|
||||
"draw opacity" => α,
|
||||
@@ -1279,21 +1291,25 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
|
||||
push!(opt, string(letter, "tick") => string("{", join(tick_values, ","), "}"))
|
||||
if axis[:showaxis] && axis[:scale] in (:ln, :log2, :log10) && axis[:ticks] == :auto
|
||||
# wrap the power part of label with }
|
||||
tick_labels = Vector{String}(undef, length(ticks[2]))
|
||||
tick_labels = similar(ticks[2])
|
||||
for (i, label) in enumerate(ticks[2])
|
||||
base, power = split(label, "^")
|
||||
power = string("{", power, "}")
|
||||
tick_labels[i] = string(base, "^", power)
|
||||
end
|
||||
push!(
|
||||
opt,
|
||||
string(letter, "ticklabels") =>
|
||||
string("{\$", join(tick_labels, "\$,\$"), "\$}"),
|
||||
)
|
||||
if tick_labels isa Vector{String}
|
||||
push!(
|
||||
opt,
|
||||
string(letter, "ticklabels") =>
|
||||
string("{\$", join(tick_labels, "\$,\$"), "\$}"),
|
||||
)
|
||||
elseif tick_labels isa Vector{LaTeXString}
|
||||
push!(opt, string(letter, "ticklabels") => join(tick_labels))
|
||||
end
|
||||
elseif axis[:showaxis]
|
||||
tick_labels =
|
||||
ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2]
|
||||
if axis[:formatter] in (:scientific, :auto)
|
||||
if axis[:formatter] in (:scientific, :auto) && tick_labels isa Vector{String}
|
||||
tick_labels = string.("\$", convert_sci_unicode.(tick_labels), "\$")
|
||||
tick_labels = replace.(tick_labels, Ref("×" => "\\times"))
|
||||
end
|
||||
|
||||
+121
-72
@@ -162,6 +162,9 @@ function py_fillstepstyle(seriestype::Symbol)
|
||||
return nothing
|
||||
end
|
||||
|
||||
py_fillstyle(::Nothing) = nothing
|
||||
py_fillstyle(fillstyle::Symbol) = string(fillstyle)
|
||||
|
||||
# # untested... return a FontProperties object from a Plots.Font
|
||||
# function py_font(font::Font)
|
||||
# pyfont["FontProperties"](
|
||||
@@ -709,24 +712,45 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
for segment in series_segments(series)
|
||||
i, rng = segment.attr_index, segment.range
|
||||
if length(rng) > 1
|
||||
lc = get_linecolor(series, clims, i)
|
||||
la = get_linealpha(series, i)
|
||||
ls = get_linestyle(series, i)
|
||||
fc = get_fillcolor(series, clims, i)
|
||||
fa = get_fillalpha(series, i)
|
||||
fs = get_fillstyle(series, i)
|
||||
has_fs = !isnothing(fs)
|
||||
|
||||
path = pypath."Path"(hcat(x[rng], y[rng]))
|
||||
|
||||
# shape outline (and potentially solid fill)
|
||||
patches = pypatches."PathPatch"(
|
||||
path;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
edgecolor = py_color(
|
||||
get_linecolor(series, clims, i),
|
||||
get_linealpha(series, i),
|
||||
),
|
||||
facecolor = py_color(
|
||||
get_fillcolor(series, clims, i),
|
||||
get_fillalpha(series, i),
|
||||
),
|
||||
edgecolor = py_color(lc, la),
|
||||
facecolor = py_color(fc, has_fs ? 0 : fa),
|
||||
linewidth = py_thickness_scale(plt, get_linewidth(series, i)),
|
||||
linestyle = py_linestyle(st, get_linestyle(series, i)),
|
||||
fill = true,
|
||||
linestyle = py_linestyle(st, ls),
|
||||
fill = !has_fs,
|
||||
)
|
||||
push!(handle, ax."add_patch"(patches))
|
||||
|
||||
# shape hatched fill
|
||||
# hatch color/alpha are controlled by edge (not face) color/alpha
|
||||
if has_fs
|
||||
patches = pypatches."PathPatch"(
|
||||
path;
|
||||
label = "",
|
||||
zorder = series[:series_plotindex],
|
||||
edgecolor = py_color(fc, fa),
|
||||
facecolor = py_color(fc, 0), # don't fill with solid background
|
||||
hatch = py_fillstyle(fs),
|
||||
linewidth = 0, # don't replot shape outline (doesn't affect hatch linewidth)
|
||||
linestyle = py_linestyle(st, ls),
|
||||
fill = false,
|
||||
)
|
||||
push!(handle, ax."add_patch"(patches))
|
||||
end
|
||||
end
|
||||
end
|
||||
push!(handles, handle)
|
||||
@@ -754,16 +778,23 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
dim1, _cycle(fillrange[1], rng), _cycle(fillrange[2], rng)
|
||||
end
|
||||
|
||||
la = get_linealpha(series, i)
|
||||
fc = get_fillcolor(series, clims, i)
|
||||
fa = get_fillalpha(series, i)
|
||||
fs = get_fillstyle(series, i)
|
||||
has_fs = !isnothing(fs)
|
||||
|
||||
handle = getproperty(ax, f)(
|
||||
args...,
|
||||
trues(n),
|
||||
false,
|
||||
py_fillstepstyle(st);
|
||||
zorder = series[:series_plotindex],
|
||||
facecolor = py_color(
|
||||
get_fillcolor(series, clims, i),
|
||||
get_fillalpha(series, i),
|
||||
),
|
||||
# hatch color/alpha are controlled by edge (not face) color/alpha
|
||||
# if has_fs, set edge color/alpha <- fill color/alpha and face alpha <- 0
|
||||
edgecolor = py_color(fc, has_fs ? fa : la),
|
||||
facecolor = py_color(fc, has_fs ? 0 : fa),
|
||||
hatch = py_fillstyle(fs),
|
||||
linewidths = 0,
|
||||
)
|
||||
push!(handles, handle)
|
||||
@@ -1455,67 +1486,85 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
||||
if should_add_to_legend(series)
|
||||
clims = get_clims(sp, series)
|
||||
# add a line/marker and a label
|
||||
push!(
|
||||
handles,
|
||||
if series[:seriestype] == :shape || series[:fillrange] !== nothing
|
||||
pypatches."Patch"(
|
||||
edgecolor = py_color(
|
||||
single_color(get_linecolor(series, clims)),
|
||||
get_linealpha(series),
|
||||
),
|
||||
facecolor = py_color(
|
||||
single_color(get_fillcolor(series, clims)),
|
||||
get_fillalpha(series),
|
||||
),
|
||||
linewidth = py_thickness_scale(
|
||||
plt,
|
||||
clamp(get_linewidth(series), 0, 5),
|
||||
),
|
||||
linestyle = py_linestyle(
|
||||
series[:seriestype],
|
||||
get_linestyle(series),
|
||||
),
|
||||
if series[:seriestype] == :shape || series[:fillrange] !== nothing
|
||||
lc = get_linecolor(series, clims)
|
||||
la = get_linealpha(series)
|
||||
ls = get_linestyle(series)
|
||||
fc = get_fillcolor(series, clims)
|
||||
fa = get_fillalpha(series)
|
||||
fs = get_fillstyle(series)
|
||||
has_fs = !isnothing(fs)
|
||||
|
||||
# line (and potentially solid fill)
|
||||
line_handle = pypatches."Patch"(
|
||||
edgecolor = py_color(single_color(lc), la),
|
||||
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),
|
||||
linewidth = 0, # don't replot shape outline (doesn't affect hatch linewidth)
|
||||
linestyle = py_linestyle(series[:seriestype], ls),
|
||||
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
|
||||
series[:serieshandle][1]
|
||||
end,
|
||||
)
|
||||
# plot line handle (which includes solid fill) only
|
||||
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])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,16 +7,18 @@ warn_on_unsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
_canvas_map() = (
|
||||
braille = UnicodePlots.BrailleCanvas,
|
||||
ascii = UnicodePlots.AsciiCanvas,
|
||||
block = UnicodePlots.BlockCanvas,
|
||||
dot = UnicodePlots.DotCanvas,
|
||||
braille = UnicodePlots.BrailleCanvas,
|
||||
density = UnicodePlots.DensityCanvas,
|
||||
dot = UnicodePlots.DotCanvas,
|
||||
heatmap = UnicodePlots.HeatmapCanvas,
|
||||
lookup = UnicodePlots.LookupCanvas,
|
||||
)
|
||||
|
||||
# do all the magic here... build it all at once, since we need to know about all the series at the very beginning
|
||||
function rebuildUnicodePlot!(plt::Plot, width, height)
|
||||
plt.o = []
|
||||
function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend})
|
||||
plt.o = UnicodePlots.Plot[]
|
||||
|
||||
for sp in plt.subplots
|
||||
xaxis = sp[:xaxis]
|
||||
@@ -41,90 +43,81 @@ function rebuildUnicodePlot!(plt::Plot, width, height)
|
||||
_canvas_map()[ct]
|
||||
end
|
||||
|
||||
# special handling for spy
|
||||
if length(sp.series_list) == 1
|
||||
series = sp.series_list[1]
|
||||
if series[:seriestype] == :spy
|
||||
push!(
|
||||
plt.o,
|
||||
UnicodePlots.spy(
|
||||
series[:z].surf,
|
||||
width = width,
|
||||
height = height,
|
||||
title = sp[:title],
|
||||
canvas = canvas_type,
|
||||
),
|
||||
)
|
||||
continue
|
||||
end
|
||||
end
|
||||
|
||||
# # make it a bar canvas if plotting bar
|
||||
# if any(series -> series[:seriestype] == :bar, series_list(sp))
|
||||
# canvas_type = UnicodePlots.BarplotGraphics
|
||||
# end
|
||||
|
||||
o = UnicodePlots.Plot(
|
||||
x,
|
||||
y,
|
||||
canvas_type;
|
||||
width = width,
|
||||
height = height,
|
||||
title = sp[:title],
|
||||
xlim = xlim,
|
||||
ylim = ylim,
|
||||
xlabel = xaxis[:guide],
|
||||
ylabel = yaxis[:guide],
|
||||
border = isijulia() ? :ascii : :solid,
|
||||
)
|
||||
|
||||
# set the axis labels
|
||||
UnicodePlots.xlabel!(o, xaxis[:guide])
|
||||
UnicodePlots.ylabel!(o, yaxis[:guide])
|
||||
|
||||
# now use the ! functions to add to the plot
|
||||
for series in series_list(sp)
|
||||
addUnicodeSeries!(o, series.plotattributes, sp[:legend] != :none, xlim, ylim)
|
||||
o = addUnicodeSeries!(sp, o, series, sp[:legend] != :none, xlim, ylim)
|
||||
end
|
||||
|
||||
# save the object
|
||||
push!(plt.o, o)
|
||||
push!(plt.o, o) # save the object
|
||||
end
|
||||
end
|
||||
|
||||
# add a single series
|
||||
function addUnicodeSeries!(o, plotattributes, addlegend::Bool, xlim, ylim)
|
||||
# get the function, or special handling for step/bar/hist
|
||||
st = plotattributes[:seriestype]
|
||||
function addUnicodeSeries!(
|
||||
sp::Subplot{UnicodePlotsBackend},
|
||||
o,
|
||||
series,
|
||||
addlegend::Bool,
|
||||
xlim,
|
||||
ylim,
|
||||
)
|
||||
attrs = series.plotattributes
|
||||
st = attrs[:seriestype]
|
||||
|
||||
# special handling
|
||||
if st == :histogram2d
|
||||
UnicodePlots.densityplot!(o, plotattributes[:x], plotattributes[:y])
|
||||
return
|
||||
return UnicodePlots.densityplot!(o, attrs[:x], attrs[:y])
|
||||
elseif st == :heatmap
|
||||
rng = range(0, 1, length = length(UnicodePlots.COLOR_MAP_DATA[:viridis]))
|
||||
cmap = [(red(c), green(c), blue(c)) for c in get(get_colorgradient(series), rng)]
|
||||
return UnicodePlots.heatmap(
|
||||
series[:z].surf;
|
||||
title = sp[:title],
|
||||
zlabel = sp[:colorbar_title],
|
||||
colormap = cmap,
|
||||
)
|
||||
elseif st == :spy
|
||||
return UnicodePlots.spy(series[:z].surf; title = sp[:title])
|
||||
end
|
||||
|
||||
# now use the ! functions to add to the plot
|
||||
if st in (:path, :straightline)
|
||||
func = UnicodePlots.lineplot!
|
||||
elseif st == :scatter || plotattributes[:markershape] != :none
|
||||
elseif st == :scatter || attrs[:markershape] != :none
|
||||
func = UnicodePlots.scatterplot!
|
||||
# elseif st == :bar
|
||||
# func = UnicodePlots.barplot!
|
||||
elseif st == :shape
|
||||
func = UnicodePlots.lineplot!
|
||||
else
|
||||
error("Linestyle $st not supported by UnicodePlots")
|
||||
error("Series type $st not supported by UnicodePlots")
|
||||
end
|
||||
|
||||
# get the series data and label
|
||||
x, y = if st == :straightline
|
||||
straightline_data(plotattributes)
|
||||
straightline_data(attrs)
|
||||
elseif st == :shape
|
||||
shape_data(plotattributes)
|
||||
shape_data(attrs)
|
||||
else
|
||||
[collect(float(plotattributes[s])) for s in (:x, :y)]
|
||||
[collect(float(attrs[s])) for s in (:x, :y)]
|
||||
end
|
||||
label = addlegend ? plotattributes[:label] : ""
|
||||
label = addlegend ? attrs[:label] : ""
|
||||
|
||||
lc = plotattributes[:linecolor]
|
||||
lc = attrs[:linecolor]
|
||||
if typeof(lc) <: UnicodePlots.UserColorType
|
||||
color = lc
|
||||
elseif lc isa RGBA{Float64}
|
||||
elseif typeof(lc) <: RGBA
|
||||
lc = convert(ARGB32, lc)
|
||||
color = map(Int, (red(lc).i, green(lc).i, blue(lc).i))
|
||||
else
|
||||
@@ -141,15 +134,14 @@ end
|
||||
# -------------------------------
|
||||
|
||||
# since this is such a hack, it's only callable using `png`... should error during normal `show`
|
||||
function png(plt::AbstractPlot{UnicodePlotsBackend}, fn::AbstractString)
|
||||
function png(plt::Plot{UnicodePlotsBackend}, fn::AbstractString)
|
||||
fn = addExtension(fn, "png")
|
||||
|
||||
# make some whitespace and show the plot
|
||||
println("\n\n\n\n\n\n")
|
||||
gui(plt)
|
||||
|
||||
# @osx_only begin
|
||||
@static if Sys.isapple()
|
||||
# make some whitespace and show the plot
|
||||
println("\n\n\n\n\n\n")
|
||||
gui(plt)
|
||||
|
||||
# BEGIN HACK
|
||||
|
||||
# wait while the plot gets drawn
|
||||
@@ -161,21 +153,20 @@ function png(plt::AbstractPlot{UnicodePlotsBackend}, fn::AbstractString)
|
||||
|
||||
# END HACK (phew)
|
||||
return
|
||||
elseif Sys.islinux()
|
||||
run(`clear`)
|
||||
gui(plt)
|
||||
run(`import -window $(ENV["WINDOWID"]) $fn`)
|
||||
return
|
||||
end
|
||||
|
||||
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
|
||||
error(
|
||||
"Can only savepng on MacOS or Linux with UnicodePlots (though even then I wouldn't do it)",
|
||||
)
|
||||
end
|
||||
|
||||
# -------------------------------
|
||||
|
||||
# we don't do very much for subplots... just stack them vertically
|
||||
|
||||
function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend})
|
||||
w, h = plt[:size]
|
||||
plt.attr[:color_palette] = [RGB(0, 0, 0)]
|
||||
rebuildUnicodePlot!(plt, div(w, 10), div(h, 20))
|
||||
end
|
||||
|
||||
function _show(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
|
||||
unicodeplots_rebuild(plt)
|
||||
foreach(x -> show(io, x), plt.o)
|
||||
@@ -184,6 +175,6 @@ end
|
||||
|
||||
function _display(plt::Plot{UnicodePlotsBackend})
|
||||
unicodeplots_rebuild(plt)
|
||||
map(show, plt.o)
|
||||
map(display, plt.o)
|
||||
nothing
|
||||
end
|
||||
|
||||
+34
-9
@@ -1239,17 +1239,42 @@ _backend_skips = Dict(
|
||||
:plotlyjs => [2, 21, 24, 25, 30, 31, 49, 51, 55],
|
||||
:plotly => [2, 21, 24, 25, 30, 31, 49, 50, 51, 55],
|
||||
:pgfplotsx => [
|
||||
2, # animation
|
||||
6, # images
|
||||
16, # pgfplots thinks the upper panel is too small
|
||||
30, # @df
|
||||
31, # animation
|
||||
32, # spy
|
||||
49, # polar heatmap
|
||||
51, # image with custom axes
|
||||
2, # animation
|
||||
6, # images
|
||||
16, # pgfplots thinks the upper panel is too small
|
||||
30, # @df
|
||||
31, # animation
|
||||
32, # spy
|
||||
49, # polar heatmap
|
||||
51, # image with custom axes
|
||||
],
|
||||
:inspectdr => [4, 6, 10, 22, 24, 28, 30, 38, 43, 45, 47, 48, 49, 50, 51, 55],
|
||||
:unicodeplots => [6, 10, 22, 24, 28, 38, 43, 45, 47, 49, 50, 51, 55],
|
||||
:unicodeplots => [
|
||||
6, # embedded images unsupported
|
||||
10, # histogram2d
|
||||
13, # markers unsupported
|
||||
16, # subplots unsupported
|
||||
17, # grid layout unsupported
|
||||
20, # annotations unsupported
|
||||
21, # custom markers unsupported
|
||||
22, # contours unsupported
|
||||
24, # 3D unsupported
|
||||
26, # subplots unsupported
|
||||
29, # layout unsupported
|
||||
33, # grid lines unsupported
|
||||
34, # framestyles unsupported
|
||||
37, # ribbons / filled unsupported
|
||||
38, # histogram2D
|
||||
43, # heatmap with DateTime
|
||||
45, # error bars
|
||||
47, # mesh3D unsupported
|
||||
48, # markershapes unsupported
|
||||
49, # polar heatmap
|
||||
50, # 3D surface unsupported
|
||||
51, # embedded images unsupported
|
||||
52, # 3D quiver unsupported
|
||||
55, # 3D unsupported
|
||||
],
|
||||
:gaston => [
|
||||
2, # animations
|
||||
31, # animations
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ num_series(x::AMat) = size(x, 2)
|
||||
num_series(x) = 1
|
||||
|
||||
RecipesBase.apply_recipe(plotattributes::AKW, ::Type{T}, plt::AbstractPlot) where {T} =
|
||||
throw(MethodError(T, "Unmatched plot recipe: $T"))
|
||||
nothing
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -538,6 +538,7 @@ get_gradient(cp::ColorPalette) = cgrad(cp, categorical = true)
|
||||
|
||||
get_linewidth(series, i::Int = 1) = _cycle(series[:linewidth], i)
|
||||
get_linestyle(series, i::Int = 1) = _cycle(series[:linestyle], i)
|
||||
get_fillstyle(series, i::Int = 1) = _cycle(series[:fillstyle], i)
|
||||
|
||||
function get_markerstrokecolor(series, i::Int = 1)
|
||||
msc = series[:markerstrokecolor]
|
||||
@@ -556,6 +557,7 @@ const _segmenting_vector_attributes = (
|
||||
:linestyle,
|
||||
:fillcolor,
|
||||
:fillalpha,
|
||||
:fillstyle,
|
||||
:markercolor,
|
||||
:markeralpha,
|
||||
:markersize,
|
||||
|
||||
@@ -12,6 +12,13 @@ using LibGit2
|
||||
import GeometryBasics
|
||||
using Dates
|
||||
using RecipesBase
|
||||
using JSON
|
||||
|
||||
@testset "Infrastructure" begin
|
||||
@test_nowarn JSON.Parser.parse(
|
||||
String(read(joinpath(dirname(pathof(Plots)), "..", ".zenodo.json"))),
|
||||
)
|
||||
end
|
||||
|
||||
@testset "Plotly standalone" begin
|
||||
@test_nowarn Plots._init_ijulia_plotting()
|
||||
|
||||
Reference in New Issue
Block a user