Check contour levels has correct value for all backends
This commit moves the check for the correctness of the `levels` keyword argument into `RecipesPipeline.preprocess_attributes!(::KW)` and calls the new function `check_contour_levels`, which in turn will throw an `ArgumentError` if the argument is not correct. To that end: - Remove the check for non-integer and non-vector values of `levels` from the PyPlot backend code, and - Add low-level tests for the new function and high-level tests for contour plots.
This commit is contained in:
parent
33a7e12ae8
commit
0b800ac6d3
25
src/args.jl
25
src/args.jl
@ -1502,6 +1502,11 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
|
|||||||
plotattributes[:framestyle] = _framestyleAliases[plotattributes[:framestyle]]
|
plotattributes[:framestyle] = _framestyleAliases[plotattributes[:framestyle]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# contours
|
||||||
|
if haskey(plotattributes, :levels)
|
||||||
|
check_contour_levels(plotattributes[:levels])
|
||||||
|
end
|
||||||
|
|
||||||
# warnings for moved recipes
|
# warnings for moved recipes
|
||||||
st = get(plotattributes, :seriestype, :path)
|
st = get(plotattributes, :seriestype, :path)
|
||||||
if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatsPlots)
|
if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatsPlots)
|
||||||
@ -1629,6 +1634,26 @@ convertLegendValue(v::AbstractArray) = map(convertLegendValue, v)
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
"""Throw an error if the `levels` keyword argument is not of the correct type
|
||||||
|
or `levels` is less than 1"""
|
||||||
|
function check_contour_levels(levels)
|
||||||
|
if !(levels isa Union{Integer,AVec})
|
||||||
|
throw(
|
||||||
|
ArgumentError(
|
||||||
|
"the levels keyword argument must be an integer or AbstractVector",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
elseif levels isa Integer && levels <= 0
|
||||||
|
throw(
|
||||||
|
ArgumentError(
|
||||||
|
"must pass a positive number of contours to the levels keyword argument",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
# 1-row matrices will give an element
|
# 1-row matrices will give an element
|
||||||
# multi-row matrices will give a column
|
# multi-row matrices will give a column
|
||||||
# InputWrapper just gives the contents
|
# InputWrapper just gives the contents
|
||||||
|
|||||||
@ -390,8 +390,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
elseif isvector(levels)
|
elseif isvector(levels)
|
||||||
extrakw[:levels] = levels
|
extrakw[:levels] = levels
|
||||||
()
|
()
|
||||||
else
|
|
||||||
error("Only numbers and vectors are supported with levels keyword")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# add custom frame shapes to markershape?
|
# add custom frame shapes to markershape?
|
||||||
|
|||||||
@ -1,10 +1,46 @@
|
|||||||
using Plots, Test
|
using Plots, Test
|
||||||
|
import RecipesPipeline
|
||||||
|
|
||||||
@testset "Contours" begin
|
@testset "Contours" begin
|
||||||
|
@testset "check_contour_levels" begin
|
||||||
|
@test Plots.check_contour_levels(2) === nothing
|
||||||
|
@test Plots.check_contour_levels(-1.0:0.2:10.0) === nothing
|
||||||
|
@test Plots.check_contour_levels([-100, -2, -1, 0, 1, 2, 100]) === nothing
|
||||||
|
@test_throws ArgumentError Plots.check_contour_levels(1.0)
|
||||||
|
@test_throws ArgumentError Plots.check_contour_levels((1, 2, 3))
|
||||||
|
@test_throws ArgumentError Plots.check_contour_levels(-3)
|
||||||
|
end
|
||||||
|
|
||||||
|
@testset "RecipesPipeline.preprocess_attributes!" begin
|
||||||
|
function equal_after_pipeline(kw)
|
||||||
|
kw′ = deepcopy(kw)
|
||||||
|
RecipesPipeline.preprocess_attributes!(kw′)
|
||||||
|
kw == kw′
|
||||||
|
end
|
||||||
|
|
||||||
|
@test equal_after_pipeline(KW(:levels => 1))
|
||||||
|
@test equal_after_pipeline(KW(:levels => 1:10))
|
||||||
|
@test equal_after_pipeline(KW(:levels => [1.0, 3.0, 5.0]))
|
||||||
|
@test_throws ArgumentError RecipesPipeline.preprocess_attributes!(
|
||||||
|
KW(:levels => 1.0),
|
||||||
|
)
|
||||||
|
@test_throws ArgumentError RecipesPipeline.preprocess_attributes!(
|
||||||
|
KW(:levels => (1, 2, 3)),
|
||||||
|
)
|
||||||
|
@test_throws ArgumentError RecipesPipeline.preprocess_attributes!(KW(:levels => -3))
|
||||||
|
end
|
||||||
|
|
||||||
|
@testset "contour[f]" begin
|
||||||
x = (-2π):0.1:(2π)
|
x = (-2π):0.1:(2π)
|
||||||
y = (-π):0.1:π
|
y = (-π):0.1:π
|
||||||
z = cos.(y) .* sin.(x')
|
z = cos.(y) .* sin.(x')
|
||||||
|
|
||||||
|
@testset "Incorrect input" begin
|
||||||
|
@test_throws ArgumentError contour(x, y, z, levels = 1.0)
|
||||||
|
@test_throws ArgumentError contour(x, y, z, levels = (1, 2, 3))
|
||||||
|
@test_throws ArgumentError contour(x, y, z, levels = -3)
|
||||||
|
end
|
||||||
|
|
||||||
@testset "Default number" begin
|
@testset "Default number" begin
|
||||||
@test contour(x, y, z)[1][1].plotattributes[:levels] ==
|
@test contour(x, y, z)[1][1].plotattributes[:levels] ==
|
||||||
Plots._series_defaults[:levels]
|
Plots._series_defaults[:levels]
|
||||||
@ -28,4 +64,5 @@ using Plots, Test
|
|||||||
levels = [-1, 0.25, 0, 0.25, 1]
|
levels = [-1, 0.25, 0, 0.25, 1]
|
||||||
@test contour(x, y, z, levels = levels)[1][1].plotattributes[:levels] == levels
|
@test contour(x, y, z, levels = levels)[1][1].plotattributes[:levels] == levels
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user