Compare commits

...

7 Commits

Author SHA1 Message Date
Simon Christ d657c0cb33 1.16.6 [skip ci] 2021-06-25 16:57:10 +02:00
t-bltg 50f63cf1eb Ignore :blank plots (#3585) 2021-06-25 15:40:49 +02:00
Simon Christ 2b22dae757 Handle matrices of annotations and copy for plot(plots) (#3572)
* add tests for series_annotations in layouts

* add methods for matrices of annotations

* defensive copy on plot(plots)

* seperate in plot(plots) and plot!(plots)
2021-06-17 09:29:39 +02:00
Simon Christ 7ca32b5edd show ekwargs on show (#3567) 2021-06-12 09:38:10 +02:00
Simon Christ 3f5a1287be 1.16.5[skip ci] 2021-06-10 15:48:03 +02:00
Simon Christ 990e0f3f7f Better twinx (#3564)
* improve twinx

* add tests, disable gridlines of twinx
2021-06-10 15:00:19 +02:00
Simon Christ 849d31d57f markers -> mark for older pgfplots version 2021-06-09 16:54:55 +02:00
8 changed files with 132 additions and 52 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "1.16.4"
version = "1.16.6"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
+1 -1
View File
@@ -1081,7 +1081,7 @@ end
function pgfx_fillrange_series!(axis, series, series_func, i, fillrange, rng)
fillrange_opt = PGFPlotsX.Options("line width" => "0", "draw opacity" => "0")
fillrange_opt = merge(fillrange_opt, pgfx_fillstyle(series, i))
push!(fillrange_opt, "markers" => "none") # no markers on fillranges
push!(fillrange_opt, "mark" => "none") # no markers on fillranges
push!(fillrange_opt, "forget plot" => nothing)
opt = series.plotattributes
args = RecipesPipeline.is3d(series) ? (opt[:x][rng], opt[:y][rng], opt[:z][rng]) :
+6
View File
@@ -474,6 +474,11 @@ mutable struct SeriesAnnotations
baseshape::Union{Shape, AbstractVector{Shape}, Nothing}
scalefactor::Tuple
end
series_annotations(scalar) = series_annotations([scalar])
function series_annotations(anns::AMat)
map(series_annotations, anns)
end
function series_annotations(strs::AbstractVector, args...)
fnt = font()
shp = nothing
@@ -570,6 +575,7 @@ end
annotations(::Nothing) = []
annotations(anns::AVec) = anns
annotations(anns::AMat) = map(annotations, anns)
annotations(anns) = Any[anns]
annotations(sa::SeriesAnnotations) = sa
+11 -3
View File
@@ -406,7 +406,7 @@ end
# ----------------------------------------------------------------------
calc_num_subplots(layout::AbstractLayout) = 1
calc_num_subplots(layout::AbstractLayout) = get(layout.attr, :blank, false) ? 0 : 1
function calc_num_subplots(layout::GridLayout)
tot = 0
for l in layout.grid
@@ -775,9 +775,17 @@ end
"Adds a new, empty subplot overlayed on top of `sp`, with a mirrored y-axis and linked x-axis."
function twinx(sp::Subplot)
sp[:right_margin] = max(sp[:right_margin], 30px)
plot!(sp.plt, inset = (sp[:subplot_index], bbox(0,0,1,1)))
plot!(sp.plt,
inset = (sp[:subplot_index], bbox(0,0,1,1)),
right_margin = sp[:right_margin],
left_margin = sp[:left_margin],
top_margin = sp[:top_margin],
bottom_margin = sp[:bottom_margin],
)
twinsp = sp.plt.subplots[end]
twinsp[:xaxis][:grid] = false
twinsp[:yaxis][:grid] = false
twinsp[:xaxis][:showaxis] = false
twinsp[:yaxis][:mirror] = true
twinsp[:background_color_inside] = RGBA{Float64}(0,0,0,0)
link_axes!(sp[:xaxis], twinsp[:xaxis])
+34 -2
View File
@@ -23,7 +23,38 @@ current(plot::AbstractPlot) = (CURRENT_PLOT.nullableplot = plot)
Base.string(plt::Plot) = "Plot{$(plt.backend) n=$(plt.n)}"
Base.print(io::IO, plt::Plot) = print(io, string(plt))
Base.show(io::IO, plt::Plot) = print(io, string(plt))
function Base.show(io::IO, plt::Plot)
print(io, string(plt))
sp_ekwargs = getindex.(plt.subplots, :extra_kwargs)
s_ekwargs = getindex.(plt.series_list, :extra_kwargs)
if isempty(plt[:extra_plot_kwargs]) && all(isempty, sp_ekwargs) && all(isempty, s_ekwargs)
return
end
print(io,"\nCaptured extra kwargs:\n")
do_show = true
for (key, value) in plt[:extra_plot_kwargs]
do_show && println(io, " Plot:")
println(io, " "^4, key, ": ", value)
do_show = false
end
do_show = true
for (i, ekwargs) in enumerate(sp_ekwargs)
for (key, value) in ekwargs
do_show && println(io, " SubplotPlot{$i}:")
println(io, " "^4, key, ": ", value)
do_show = false
end
do_show = true
end
for (i, ekwargs) in enumerate(s_ekwargs)
for (key, value) in ekwargs
do_show && println(io, " Series{$i}:")
println(io, " "^4, key, ": ", value)
do_show = false
end
do_show = true
end
end
getplot(plt::Plot) = plt
getattr(plt::Plot, idx::Int = 1) = plt.attr
@@ -60,7 +91,8 @@ end
# build a new plot from existing plots
# note: we split into plt1 and plts_tail so we can dispatch correctly
function plot(plt1::Plot, plts_tail::Plot...; kw...)
plot(plt1::Plot, plts_tail::Plot...; kw...) = plot!(deepcopy(plt1), deepcopy.(plts_tail)...; kw...)
function plot!(plt1::Plot, plts_tail::Plot...; kw...)
@nospecialize
plotattributes = KW(kw)
RecipesPipeline.preprocess_attributes!(plotattributes)
+1 -1
View File
@@ -1,4 +1,4 @@
using Plots: guidefont
using Plots: guidefont, series_annotations
import ImageMagick
using VisualRegressionTests
using Plots
+13 -3
View File
@@ -35,13 +35,13 @@ end
@testset "Axis limits" begin
pl = plot(1:5, xlims=:symmetric, widen = false)
@test Plots.xlims(pl) == (-5, 5)
pl = plot(1:3)
@test Plots.xlims(pl) == Plots.widen(1,3)
pl = plot([1.05,2.0,2.95], ylims=:round)
@test Plots.ylims(pl) == (1, 3)
pl = plot(1:3, xlims=(1,5))
@test Plots.xlims(pl) == (1, 5)
@@ -53,3 +53,13 @@ end
ql = quiver([1, 2], [2, 1], [3, 4], quiver = ([1, -1], [0, 0], [1, -0.5]), arrow=true)
@test ql[1][:projection] == "3d"
end
@testset "twinx" begin
pl = plot(1:10, margin = 2Plots.cm)
twpl = twinx(pl)
pl! = plot!(twinx(), -(1:10))
@test twpl[:right_margin] == 2Plots.cm
@test twpl[:left_margin] == 2Plots.cm
@test twpl[:top_margin] == 2Plots.cm
@test twpl[:bottom_margin] == 2Plots.cm
end
+65 -41
View File
@@ -2,58 +2,58 @@ using Plots, Test
@testset "Shapes" begin
@testset "Type" begin
square = Shape([(0,0.0),(1,0.0),(1,1.0),(0,1.0)])
@test isa(square, Shape{Int64, Float64})
@test coords(square) isa Tuple{Vector{S}, Vector{T}} where {T,S}
square = Shape([(0, 0.0), (1, 0.0), (1, 1.0), (0, 1.0)])
@test isa(square, Shape{Int64,Float64})
@test coords(square) isa Tuple{Vector{S},Vector{T}} where {T,S}
end
@testset "Copy" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)])
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
square2 = Shape(square)
@test square2.x == square.x
@test square2.y == square.y
end
@testset "Center" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)])
@test Plots.center(square) == (0.5,0.5)
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
@test Plots.center(square) == (0.5, 0.5)
end
@testset "Translate" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)])
squareUp = Shape([(0,1),(1,1),(1,2),(0,2)])
squareUpRight = Shape([(1,1),(2,1),(2,2),(1,2)])
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
squareUp = Shape([(0, 1), (1, 1), (1, 2), (0, 2)])
squareUpRight = Shape([(1, 1), (2, 1), (2, 2), (1, 2)])
@test Plots.translate(square,0,1).x == squareUp.x
@test Plots.translate(square,0,1).y == squareUp.y
@test Plots.translate(square, 0, 1).x == squareUp.x
@test Plots.translate(square, 0, 1).y == squareUp.y
@test Plots.center(translate!(square,1)) == (1.5,1.5)
@test Plots.center(translate!(square, 1)) == (1.5, 1.5)
end
@testset "Rotate" begin
# 2 radians rotation matrix
R2 = [cos(2) sin(2); -sin(2) cos(2)]
coords = [0 0; 1 0; 1 1; 0 1]'
coordsRotated2 = R2*(coords.-0.5).+0.5
coordsRotated2 = R2 * (coords .- 0.5) .+ 0.5
square = Shape([(0,0),(1,0),(1,1),(0,1)])
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
# make a new, rotated square
square2 = Plots.rotate(square, -2)
@test square2.x coordsRotated2[1,:]
@test square2.y coordsRotated2[2,:]
@test square2.x coordsRotated2[1, :]
@test square2.y coordsRotated2[2, :]
# unrotate the new square in place
rotate!(square2, 2)
@test square2.x coords[1,:]
@test square2.y coords[2,:]
@test square2.x coords[1, :]
@test square2.y coords[2, :]
end
@testset "Plot" begin
ang = range(0, 2π, length = 60)
ellipse(x, y, w, h) = Shape(w*sin.(ang).+x, h*cos.(ang).+y)
myshapes = [ellipse(x,rand(),rand(),rand()) for x = 1:4]
@test coords(myshapes) isa Tuple{Vector{Vector{S}}, Vector{Vector{T}}} where {T,S}
ellipse(x, y, w, h) = Shape(w * sin.(ang) .+ x, h * cos.(ang) .+ y)
myshapes = [ellipse(x, rand(), rand(), rand()) for x = 1:4]
@test coords(myshapes) isa Tuple{Vector{Vector{S}},Vector{Vector{T}}} where {T,S}
local p
@test_nowarn p = plot(myshapes)
@test p[1][1][:seriestype] == :shape
@@ -62,7 +62,7 @@ end
@testset "Brush" begin
@testset "Colors" begin
baseline = brush(1, RGB(0,0,0))
baseline = brush(1, RGB(0, 0, 0))
@test brush(:black) == baseline
@test brush("black") == baseline
end
@@ -76,7 +76,7 @@ end
end
@testset "Bad Argument" begin
# using test_logs because test_warn seems to not work anymore
@test_logs (:warn,"Unused brush arg: nothing (Nothing)") begin
@test_logs (:warn, "Unused brush arg: nothing (Nothing)") begin
brush(nothing)
end
end
@@ -84,44 +84,68 @@ end
@testset "Fonts" begin
@testset "Scaling" begin
sizesToCheck = [:titlefontsize, :legendfontsize, :legendtitlefontsize,
:xtickfontsize, :ytickfontsize, :ztickfontsize,
:xguidefontsize, :yguidefontsize, :zguidefontsize,]
sizesToCheck = [
:titlefontsize,
:legendfontsize,
:legendtitlefontsize,
:xtickfontsize,
:ytickfontsize,
:ztickfontsize,
:xguidefontsize,
:yguidefontsize,
:zguidefontsize,
]
# get inital font sizes
initialSizes = [Plots.default(s) for s in sizesToCheck ]
initialSizes = [Plots.default(s) for s in sizesToCheck]
#scale up font sizes
scalefontsizes(2)
# get inital font sizes
doubledSizes = [Plots.default(s) for s in sizesToCheck ]
doubledSizes = [Plots.default(s) for s in sizesToCheck]
@test doubledSizes == initialSizes*2
@test doubledSizes == initialSizes * 2
# reset font sizes
resetfontsizes()
finalSizes = [Plots.default(s) for s in sizesToCheck ]
finalSizes = [Plots.default(s) for s in sizesToCheck]
@test finalSizes == initialSizes
end
end
@testset "Series Annotations" begin
square = Shape([(0,0),(1,0),(1,1),(0,1)])
@test_logs (:warn,"Unused SeriesAnnotations arg: triangle (Symbol)") begin
p = plot([1,2,3],
series_annotations=(["a"],
2, # pass a scale factor
(1,4), # pass two scale factors (overwrites first one)
square, # pass a shape
font(:courier), # pass an annotation font
:triangle # pass an incorrect argument
))
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
@test_logs (:warn, "Unused SeriesAnnotations arg: triangle (Symbol)") begin
p = plot(
[1, 2, 3],
series_annotations = (
["a"],
2, # pass a scale factor
(1, 4), # pass two scale factors (overwrites first one)
square, # pass a shape
font(:courier), # pass an annotation font
:triangle, # pass an incorrect argument
),
)
sa = p.series_list[1].plotattributes[:series_annotations]
@test sa.strs == ["a"]
@test sa.font.family == "courier"
@test sa.baseshape == square
@test sa.scalefactor == (1,4)
@test sa.scalefactor == (1, 4)
end
spl = scatter(
4.53 .* [1/1 1/2 1/3 1/4 1/5],
[0 0 0 0 0],
layout = (5, 1),
ylims = (-1.1, 1.1),
xlims = (0, 5),
series_annotations = permutedims([["1/1"],["1/2"],["1/3"],["1/4"],["1/5"]]),
)
@test spl.series_list[1].plotattributes[:series_annotations].strs == ["1/1"]
@test spl.series_list[2].plotattributes[:series_annotations].strs == ["1/2"]
@test spl.series_list[3].plotattributes[:series_annotations].strs == ["1/3"]
@test spl.series_list[4].plotattributes[:series_annotations].strs == ["1/4"]
@test spl.series_list[5].plotattributes[:series_annotations].strs == ["1/5"]
end