Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply recipes to keyword arguments #4453

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions src/axes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ end
function attr!(axis::Axis, args...; kw...)
# first process args
plotattributes = axis.plotattributes
dummy_attributes = Dict{Symbol,Any}(:plot_object => first(axis.sps).plt)
for arg in args
process_axis_arg!(plotattributes, arg)
end
Expand All @@ -96,12 +97,6 @@ function attr!(axis::Axis, args...; kw...)
for vi in v
discrete_value!(axis, vi)
end
#could perhaps use TimeType here, as Date and DateTime are both subtypes of TimeType
# or could perhaps check if dateformatter or datetimeformatter is in use
elseif k === :lims && isa(v, Tuple{Date,Date})
plotattributes[k] = (v[1].instant.periods.value, v[2].instant.periods.value)
elseif k === :lims && isa(v, Tuple{DateTime,DateTime})
plotattributes[k] = (v[1].instant.periods.value, v[2].instant.periods.value)
else
plotattributes[k] = v
end
Expand Down Expand Up @@ -335,8 +330,10 @@ get_ticks(ticks::Bool, args...) =
get_ticks(::T, args...) where {T} = error("Unknown ticks type in get_ticks: $T")

_transform_ticks(ticks, axis) = ticks
_transform_ticks(ticks::AbstractArray{T}, axis) where {T<:Dates.TimeType} =
Dates.value.(ticks)
function _transform_ticks(ticks::AbstractArray, axis)
dummy_attributes = Dict{Symbol,Any}(:plot_object => first(axis.sps).plt)
return RecipesPipeline._apply_type_recipe(dummy_attributes, ticks, axis[:letter])
end
_transform_ticks(ticks::NTuple{2,Any}, axis) = (_transform_ticks(ticks[1], axis), ticks[2])

function get_minor_ticks(sp, axis, ticks)
Expand Down Expand Up @@ -542,7 +539,7 @@ end
scale_lims!([plt], [letter], factor)

Scale the limits of the axis specified by `letter` (one of `:x`, `:y`, `:z`) by the
given `factor` around the limits' middle point.
given `factor` around the limits' middle point.
If `letter` is omitted, all axes are affected.
"""
function scale_lims!(sp::Subplot, letter, factor)
Expand Down Expand Up @@ -623,11 +620,18 @@ function round_limits(amin, amax, scale)
amin, amax
end

process_limits(lims::Tuple{<:Union{Symbol,Real},<:Union{Symbol,Real}}, axis) = lims
process_limits(lims::Symbol, axis) = lims
process_limits(lims::AVec, axis) =
length(lims) == 2 && all(map(x -> x isa Union{Symbol,Real}, lims)) ? Tuple(lims) :
nothing
process_limits(lims::Tuple, axis) = process_limits([lims...], axis)
function process_limits(lims::AVec, axis)
dummy_attributes = Dict{Symbol,Any}(:plot_object => first(axis.sps).plt)
lims = RecipesPipeline._apply_type_recipe(dummy_attributes, lims, axis[:letter])
if lims isa Formatted
lims = lims.data
end
length(lims) == 2 || return nothing
all(x -> x isa Union{Symbol,Real}, lims) || return nothing
return Tuple(lims)
end
process_limits(lims, axis) = nothing

warn_invalid_limits(lims, letter) = @warn """
Expand Down
13 changes: 1 addition & 12 deletions src/unitful.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ using ..Unitful: Quantity, unit, ustrip, Unitful, dimension, Units, NoUnits
using ..RecipesBase
export @P_str

import ..locate_annotation,
..PlotText, ..Subplot, ..AVec, ..AMat, ..Axis, .._transform_ticks, ..process_limits
import ..locate_annotation, ..PlotText, ..Subplot, ..AVec, ..AMat, ..Axis

const MissingOrQuantity = Union{Missing,<:Quantity}

Expand Down Expand Up @@ -291,14 +290,4 @@ locate_annotation(
locate_annotation(sp::Subplot, rel::NTuple{N,<:MissingOrQuantity}, label) where {N} =
locate_annotation(sp, ustrip.(rel), label)

#==================#
# ticks and limits #
#==================#
_transform_ticks(ticks::AbstractArray{T}, axis) where {T<:Quantity} =
ustrip.(getaxisunit(axis), ticks)
process_limits(lims::AbstractArray{T}, axis) where {T<:Quantity} =
ustrip.(getaxisunit(axis), lims)
process_limits(lims::Tuple{S,T}, axis) where {S<:Quantity,T<:Quantity} =
ustrip.(getaxisunit(axis), lims)

end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Unitful: m, s, cm, DimensionError
import Plots.UnitfulRecipes: getaxisunit
import Plots: PLOTS_SEED, Plot, with
import GeometryBasics
import ImageMagick
Expand Down
1 change: 1 addition & 0 deletions test/test_dates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ end
ref_xlims = map(date -> date.instant.periods.value, span)

pl = plot(x, y, xlims = span, widen = false)
@test Plots.xlims(pl) == ref_xlims
end

@testset "DateTime xlims" begin
Expand Down
15 changes: 15 additions & 0 deletions test/test_recipes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,18 @@ end
@test p[1][2][:linestyle] == :dash
@test p[1][3][:linestyle] == :dot
end

@testset "lims and ticks" begin
struct DoubleNumber
x
end
@recipe f(::Type{T}, v::T) where {T<:AbstractArray{DoubleNumber}} = [2 * x.x for x in v]

p = plot(
1:3;
ylims = DoubleNumber.([0.5, 2.0]),
yticks = DoubleNumber.([0.4, 0.8, 1.2]),
)
@test ylims(p) == (1.0, 4.0)
@test first(first(yticks(p))) == [1.6, 2.4]
end
35 changes: 17 additions & 18 deletions test/test_unitful.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ xseries(pl, idx = length(pl.series_list)) = pl.series_list[idx].plotattributes[:
yseries(pl, idx = length(pl.series_list)) = pl.series_list[idx].plotattributes[:y]
zseries(pl, idx = length(pl.series_list)) = pl.series_list[idx].plotattributes[:z]

testfile = tempname() * ".png"
forcedraw(pl) = savefig(pl, tempname() * ".png")

macro isplot(ex) # @isplot macro to streamline tests
:(@test $(esc(ex)) isa Plot)
Expand Down Expand Up @@ -41,6 +41,7 @@ end
@testset "yunit" begin
@test yguide(plot(y, yunit = cm)) == "cm"
@test yseries(plot(y, yunit = cm)) ≈ ustrip.(cm, y)
@test getaxisunit(plot(y, yunit = cm).subplots[1][:yaxis]) == cm
end

@testset "ylims" begin # Using all(lims .≈ lims) because of uncontrolled type conversions?
Expand All @@ -52,26 +53,25 @@ end
@test_throws DimensionError begin
pl = plot(y)
plot!(pl; ylims = (-1s, 5s))
savefig(pl, testfile)
forcedraw(pl)
end
end

@testset "yticks" begin
compare_yticks(pl, expected_ticks) = all(first(first(yticks(pl))) .≈ expected_ticks)
encompassing_ylims = (-1m, 6m)
@test compare_yticks(plot(y; ylims = encompassing_ylims, yticks = (1:5)m), 1:5)
@test compare_yticks(
plot(y; ylims = encompassing_ylims, yticks = [1cm, 3cm]),
[0.01, 0.03],
)
@test compare_yticks(
plot!(; ylims = encompassing_ylims, yticks = [-1cm, 4cm]),
[-0.01, 0.04],
)
pl = plot(y; ylims = encompassing_ylims, yticks = (1:5)m)
@test compare_yticks(pl, 1:5)
pl = plot(y; ylims = encompassing_ylims, yticks = [1cm, 3cm])
forcedraw(pl)
@test compare_yticks(pl, [0.01, 0.03])
pl = plot!(; ylims = encompassing_ylims, yticks = [-1cm, 4cm])
forcedraw(pl)
@test compare_yticks(pl, [-0.01, 0.04])
@test_throws DimensionError begin
pl = plot(y)
plot!(pl; yticks = (1:5)s)
savefig(pl, testfile)
forcedraw(pl)
end
end

Expand Down Expand Up @@ -190,7 +190,7 @@ end
@test plot(x * m, ylims = (-1, 1)) isa Plot
@test plot(x * m, ylims = (-1, 1) .* m) isa Plot
@test plot(x * m, yunit = u"km") isa Plot
@test plot(x * m, xticks = (1:3) * m) isa Plot
@test plot(x * m, yticks = (1:3) * m) isa Plot
end

@testset "Two arrays" begin
Expand Down Expand Up @@ -338,19 +338,18 @@ end

@testset "Aspect ratio" begin
pl = plot((1:10)u"m", (1:10)u"dm"; aspect_ratio = :equal)
savefig(pl, testfile) # Force a render, to make it evaluate aspect ratio
forcedraw(pl)
@test abs(-(ylims(pl)...)) > 50
plot!(pl, (3:4)u"m", (4:5)u"m")
@test first(pl.subplots)[:aspect_ratio] == 1 // 10 # This is what "equal" means when yunit==xunit/10
pl = plot((1:10)u"m", (1:10)u"dm"; aspect_ratio = 2)
savefig(pl, testfile)
forcedraw(pl)
@test 25 < abs(-(ylims(pl)...)) < 50
pl = plot((1:10)u"m", (1:10)u"s"; aspect_ratio = 1u"m/s")
savefig(pl, testfile)
forcedraw(pl)
@test 7.5 < abs(-(ylims(pl)...)) < 12.5
@test_throws DimensionError savefig(
@test_throws DimensionError forcedraw(
plot((1:10)u"m", (1:10)u"s"; aspect_ratio = :equal),
testfile,
)
end

Expand Down