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)
This commit is contained in:
parent
7ca32b5edd
commit
2b22dae757
@ -474,6 +474,11 @@ mutable struct SeriesAnnotations
|
|||||||
baseshape::Union{Shape, AbstractVector{Shape}, Nothing}
|
baseshape::Union{Shape, AbstractVector{Shape}, Nothing}
|
||||||
scalefactor::Tuple
|
scalefactor::Tuple
|
||||||
end
|
end
|
||||||
|
|
||||||
|
series_annotations(scalar) = series_annotations([scalar])
|
||||||
|
function series_annotations(anns::AMat)
|
||||||
|
map(series_annotations, anns)
|
||||||
|
end
|
||||||
function series_annotations(strs::AbstractVector, args...)
|
function series_annotations(strs::AbstractVector, args...)
|
||||||
fnt = font()
|
fnt = font()
|
||||||
shp = nothing
|
shp = nothing
|
||||||
@ -570,6 +575,7 @@ end
|
|||||||
|
|
||||||
annotations(::Nothing) = []
|
annotations(::Nothing) = []
|
||||||
annotations(anns::AVec) = anns
|
annotations(anns::AVec) = anns
|
||||||
|
annotations(anns::AMat) = map(annotations, anns)
|
||||||
annotations(anns) = Any[anns]
|
annotations(anns) = Any[anns]
|
||||||
annotations(sa::SeriesAnnotations) = sa
|
annotations(sa::SeriesAnnotations) = sa
|
||||||
|
|
||||||
|
|||||||
@ -91,7 +91,8 @@ 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...)
|
plot(plt1::Plot, plts_tail::Plot...; kw...) = plot!(deepcopy(plt1), deepcopy.(plts_tail)...; kw...)
|
||||||
|
function plot!(plt1::Plot, plts_tail::Plot...; kw...)
|
||||||
@nospecialize
|
@nospecialize
|
||||||
plotattributes = KW(kw)
|
plotattributes = KW(kw)
|
||||||
RecipesPipeline.preprocess_attributes!(plotattributes)
|
RecipesPipeline.preprocess_attributes!(plotattributes)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using Plots: guidefont
|
using Plots: guidefont, series_annotations
|
||||||
import ImageMagick
|
import ImageMagick
|
||||||
using VisualRegressionTests
|
using VisualRegressionTests
|
||||||
using Plots
|
using Plots
|
||||||
|
|||||||
@ -2,58 +2,58 @@ using Plots, Test
|
|||||||
|
|
||||||
@testset "Shapes" begin
|
@testset "Shapes" begin
|
||||||
@testset "Type" begin
|
@testset "Type" begin
|
||||||
square = Shape([(0,0.0),(1,0.0),(1,1.0),(0,1.0)])
|
square = Shape([(0, 0.0), (1, 0.0), (1, 1.0), (0, 1.0)])
|
||||||
@test isa(square, Shape{Int64, Float64})
|
@test isa(square, Shape{Int64,Float64})
|
||||||
@test coords(square) isa Tuple{Vector{S}, Vector{T}} where {T,S}
|
@test coords(square) isa Tuple{Vector{S},Vector{T}} where {T,S}
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "Copy" begin
|
@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)
|
square2 = Shape(square)
|
||||||
@test square2.x == square.x
|
@test square2.x == square.x
|
||||||
@test square2.y == square.y
|
@test square2.y == square.y
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "Center" begin
|
@testset "Center" begin
|
||||||
square = Shape([(0,0),(1,0),(1,1),(0,1)])
|
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
|
||||||
@test Plots.center(square) == (0.5,0.5)
|
@test Plots.center(square) == (0.5, 0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "Translate" begin
|
@testset "Translate" begin
|
||||||
square = Shape([(0,0),(1,0),(1,1),(0,1)])
|
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
|
||||||
squareUp = Shape([(0,1),(1,1),(1,2),(0,2)])
|
squareUp = Shape([(0, 1), (1, 1), (1, 2), (0, 2)])
|
||||||
squareUpRight = Shape([(1,1),(2,1),(2,2),(1,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).x == squareUp.x
|
||||||
@test Plots.translate(square,0,1).y == squareUp.y
|
@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
|
end
|
||||||
|
|
||||||
@testset "Rotate" begin
|
@testset "Rotate" begin
|
||||||
# 2 radians rotation matrix
|
# 2 radians rotation matrix
|
||||||
R2 = [cos(2) sin(2); -sin(2) cos(2)]
|
R2 = [cos(2) sin(2); -sin(2) cos(2)]
|
||||||
coords = [0 0; 1 0; 1 1; 0 1]'
|
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
|
# make a new, rotated square
|
||||||
square2 = Plots.rotate(square, -2)
|
square2 = Plots.rotate(square, -2)
|
||||||
@test square2.x ≈ coordsRotated2[1,:]
|
@test square2.x ≈ coordsRotated2[1, :]
|
||||||
@test square2.y ≈ coordsRotated2[2,:]
|
@test square2.y ≈ coordsRotated2[2, :]
|
||||||
|
|
||||||
# unrotate the new square in place
|
# unrotate the new square in place
|
||||||
rotate!(square2, 2)
|
rotate!(square2, 2)
|
||||||
@test square2.x ≈ coords[1,:]
|
@test square2.x ≈ coords[1, :]
|
||||||
@test square2.y ≈ coords[2,:]
|
@test square2.y ≈ coords[2, :]
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "Plot" begin
|
@testset "Plot" begin
|
||||||
ang = range(0, 2π, length = 60)
|
ang = range(0, 2π, length = 60)
|
||||||
ellipse(x, y, w, h) = Shape(w*sin.(ang).+x, h*cos.(ang).+y)
|
ellipse(x, y, w, h) = Shape(w * sin.(ang) .+ x, h * cos.(ang) .+ y)
|
||||||
myshapes = [ellipse(x,rand(),rand(),rand()) for x = 1:4]
|
myshapes = [ellipse(x, rand(), rand(), rand()) for x = 1:4]
|
||||||
@test coords(myshapes) isa Tuple{Vector{Vector{S}}, Vector{Vector{T}}} where {T,S}
|
@test coords(myshapes) isa Tuple{Vector{Vector{S}},Vector{Vector{T}}} where {T,S}
|
||||||
local p
|
local p
|
||||||
@test_nowarn p = plot(myshapes)
|
@test_nowarn p = plot(myshapes)
|
||||||
@test p[1][1][:seriestype] == :shape
|
@test p[1][1][:seriestype] == :shape
|
||||||
@ -62,7 +62,7 @@ end
|
|||||||
|
|
||||||
@testset "Brush" begin
|
@testset "Brush" begin
|
||||||
@testset "Colors" 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
|
||||||
@test brush("black") == baseline
|
@test brush("black") == baseline
|
||||||
end
|
end
|
||||||
@ -76,7 +76,7 @@ end
|
|||||||
end
|
end
|
||||||
@testset "Bad Argument" begin
|
@testset "Bad Argument" begin
|
||||||
# using test_logs because test_warn seems to not work anymore
|
# 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)
|
brush(nothing)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -84,44 +84,68 @@ end
|
|||||||
|
|
||||||
@testset "Fonts" begin
|
@testset "Fonts" begin
|
||||||
@testset "Scaling" begin
|
@testset "Scaling" begin
|
||||||
sizesToCheck = [:titlefontsize, :legendfontsize, :legendtitlefontsize,
|
sizesToCheck = [
|
||||||
:xtickfontsize, :ytickfontsize, :ztickfontsize,
|
:titlefontsize,
|
||||||
:xguidefontsize, :yguidefontsize, :zguidefontsize,]
|
:legendfontsize,
|
||||||
|
:legendtitlefontsize,
|
||||||
|
:xtickfontsize,
|
||||||
|
:ytickfontsize,
|
||||||
|
:ztickfontsize,
|
||||||
|
:xguidefontsize,
|
||||||
|
:yguidefontsize,
|
||||||
|
:zguidefontsize,
|
||||||
|
]
|
||||||
# get inital font sizes
|
# get inital font sizes
|
||||||
initialSizes = [Plots.default(s) for s in sizesToCheck ]
|
initialSizes = [Plots.default(s) for s in sizesToCheck]
|
||||||
|
|
||||||
#scale up font sizes
|
#scale up font sizes
|
||||||
scalefontsizes(2)
|
scalefontsizes(2)
|
||||||
|
|
||||||
# get inital font sizes
|
# 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
|
# reset font sizes
|
||||||
resetfontsizes()
|
resetfontsizes()
|
||||||
|
|
||||||
finalSizes = [Plots.default(s) for s in sizesToCheck ]
|
finalSizes = [Plots.default(s) for s in sizesToCheck]
|
||||||
|
|
||||||
@test finalSizes == initialSizes
|
@test finalSizes == initialSizes
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "Series Annotations" begin
|
@testset "Series Annotations" begin
|
||||||
square = Shape([(0,0),(1,0),(1,1),(0,1)])
|
square = Shape([(0, 0), (1, 0), (1, 1), (0, 1)])
|
||||||
@test_logs (:warn,"Unused SeriesAnnotations arg: triangle (Symbol)") begin
|
@test_logs (:warn, "Unused SeriesAnnotations arg: triangle (Symbol)") begin
|
||||||
p = plot([1,2,3],
|
p = plot(
|
||||||
series_annotations=(["a"],
|
[1, 2, 3],
|
||||||
2, # pass a scale factor
|
series_annotations = (
|
||||||
(1,4), # pass two scale factors (overwrites first one)
|
["a"],
|
||||||
square, # pass a shape
|
2, # pass a scale factor
|
||||||
font(:courier), # pass an annotation font
|
(1, 4), # pass two scale factors (overwrites first one)
|
||||||
:triangle # pass an incorrect argument
|
square, # pass a shape
|
||||||
))
|
font(:courier), # pass an annotation font
|
||||||
|
:triangle, # pass an incorrect argument
|
||||||
|
),
|
||||||
|
)
|
||||||
sa = p.series_list[1].plotattributes[:series_annotations]
|
sa = p.series_list[1].plotattributes[:series_annotations]
|
||||||
@test sa.strs == ["a"]
|
@test sa.strs == ["a"]
|
||||||
@test sa.font.family == "courier"
|
@test sa.font.family == "courier"
|
||||||
@test sa.baseshape == square
|
@test sa.baseshape == square
|
||||||
@test sa.scalefactor == (1,4)
|
@test sa.scalefactor == (1, 4)
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user