Skip to content
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
58 changes: 43 additions & 15 deletions src/UnitfulRecipes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module UnitfulRecipes

using RecipesBase
using Unitful: Quantity, unit, ustrip, Unitful, dimension, Units
using Unitful: LogScaled, logunit, MixedUnits, Level, Gain, uconvert
export @P_str

const clims_types = (:contour, :contourf, :heatmap, :surface)
Expand All @@ -10,11 +11,12 @@ const clims_types = (:contour, :contourf, :heatmap, :surface)
Main recipe
==========#

@recipe function f(::Type{T}, x::T) where T <: AbstractArray{<:Union{Missing,<:Quantity}}
@recipe function f(::Type{T}, x::T) where T <: AbstractArray{<:Union{Missing,<:Quantity, <:LogScaled}}
axisletter = plotattributes[:letter] # x, y, or z
if (axisletter == :z) &&
get(plotattributes, :seriestype, :nothing) ∈ clims_types
u = get(plotattributes, :zunit, unit(eltype(x)))
# u = get(plotattributes, :zunit, unit(eltype(x)))
u = get(plotattributes, :zunit, eltype(x) <: LogScaled ? logunit(eltype(x)) : unit(eltype(x)))
ustripattribute!(plotattributes, :clims, u)
append_unit_if_needed!(plotattributes, :colorbar_title, u)
end
Expand All @@ -30,7 +32,7 @@ function fixaxis!(attr, x, axisletter)
axisunit = Symbol(axisletter, :unit) # xunit, yunit, zunit
axis = Symbol(axisletter, :axis) # xaxis, yaxis, zaxis
# Get the unit
u = pop!(attr, axisunit, unit(eltype(x)))
u = pop!(attr, axisunit, _unit(x))
# If the subplot already exists with data, get its unit
sp = get(attr, :subplot, 1)
if sp ≤ length(attr[:plot_object]) && attr[:plot_object].n > 0
Expand All @@ -54,22 +56,22 @@ function fixaxis!(attr, x, axisletter)
fixmarkersize!(attr)
fixlinecolor!(attr)
# Strip the unit
ustrip.(u, x)
_ustrip.(u, x)
end

# Recipe for (x::AVec, y::AVec, z::Surface) types
const AVec = AbstractVector
const AMat{T} = AbstractArray{T,2} where T
@recipe function f(x::AVec, y::AVec, z::AMat{T}) where T <: Quantity
u = get(plotattributes, :zunit, unit(eltype(z)))
u = get(plotattributes, :zunit, _unit(z))
ustripattribute!(plotattributes, :clims, u)
z = fixaxis!(plotattributes, z, :z)
append_unit_if_needed!(plotattributes, :colorbar_title, u)
x, y, z
end

# Recipe for vectors of vectors
@recipe function f(::Type{T}, x::T) where T <: AbstractVector{<:AbstractVector{<:Union{Missing,<:Quantity}}}
@recipe function f(::Type{T}, x::T) where T <: AbstractVector{<:AbstractVector{<:Union{Missing,<:Quantity, <:LogScaled}}}
axisletter = plotattributes[:letter] # x, y, or z
[fixaxis!(plotattributes, x, axisletter) for x in x]
end
Expand All @@ -81,19 +83,19 @@ end
end

# Recipes for functions
@recipe function f(f::Function, x::T) where T <: AVec{<:Union{Missing,<:Quantity}}
@recipe function f(f::Function, x::T) where T <: AVec{<:Union{Missing,<:Quantity, <:LogScaled}}
x, f.(x)
end
@recipe function f(x::T, f::Function) where T <: AVec{<:Union{Missing,<:Quantity}}
@recipe function f(x::T, f::Function) where T <: AVec{<:Union{Missing,<:Quantity, <:LogScaled}}
x, f.(x)
end
@recipe function f(x::T, y::AVec, f::Function) where T <: AVec{<:Union{Missing,<:Quantity}}
@recipe function f(x::T, y::AVec, f::Function) where T <: AVec{<:Union{Missing,<:Quantity, <:LogScaled}}
x, y, f.(x',y)
end
@recipe function f(x::AVec, y::T, f::Function) where T <: AVec{<:Union{Missing,<:Quantity}}
@recipe function f(x::AVec, y::T, f::Function) where T <: AVec{<:Union{Missing,<:Quantity, <:LogScaled}}
x, y, f.(x',y)
end
@recipe function f(x::T1, y::T2, f::Function) where {T1<:AVec{<:Union{Missing,<:Quantity}}, T2<:AVec{<:Union{Missing,<:Quantity}}}
@recipe function f(x::T1, y::T2, f::Function) where {T1<:AVec{<:Union{Missing,<:Quantity, <:LogScaled}}, T2<:AVec{<:Union{Missing,<:Quantity, <:LogScaled}}}
x, y, f.(x',y)
end
@recipe function f(f::Function, u::Units)
Expand Down Expand Up @@ -138,8 +140,8 @@ fixlinecolor!(attr) = ustripattribute!(attr, :line_z)
function ustripattribute!(attr, key)
if haskey(attr, key)
v = attr[key]
u = unit(eltype(v))
attr[key] = ustrip.(u, v)
u = _unit(eltype(v))
attr[key] = _ustrip.(u, v)
return u
else
return Unitful.NoUnits
Expand All @@ -150,7 +152,7 @@ function ustripattribute!(attr, key, u)
if haskey(attr, key)
v = attr[key]
if eltype(v) <: Quantity
attr[key] = ustrip.(u, v)
attr[key] = _ustrip.(u, v)
end
end
u
Expand Down Expand Up @@ -198,7 +200,7 @@ end
Append unit to labels when appropriate
=====================================#

function append_unit_if_needed!(attr, key, u::Unitful.Units)
function append_unit_if_needed!(attr, key, u::Union{Unitful.Units, Unitful.MixedUnits})
label = get(attr, key, nothing)
append_unit_if_needed!(attr, key, label, u)
end
Expand Down Expand Up @@ -242,4 +244,30 @@ const UNIT_FORMATS = Dict(

format_unit_label(l, u, f::Symbol) = format_unit_label(l,u,UNIT_FORMATS[f])

#=====================================
Placeholder functions for consistent
=====================================#

function _ustrip(u, x)
if eltype(x) <: Level
ustrip(uconvert(u, x))
elseif eltype(x) <: Gain
getfield(uconvert(u, x), :val)
elseif u isa MixedUnits
x = uconvert(u, x) # convert Quantity -> LogScaled
if eltype(x) <: Level
ustrip(uconvert(u, x))
elseif eltype(x) <: Gain
getfield(uconvert(u, x), :val)
end
else
ustrip(u, x)
end
end

function _unit(x)
t = eltype(x)
u = t <: LogScaled ? logunit(t) : unit(t)
end

end # module
27 changes: 27 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,30 @@ end
plot!(plt, (1:3)m)
@test yguide(plt) == "m"
end

@testset "LogScaled plots" begin
x, y, dbv, v = randn(3)*u"dBm", randn(3)*u"dB", rand(3)*u"dBV", rand(3)*u"V"

@testset "no keyword argument" begin
@test xguide(plot(x,y)) == "dBm"
@test xseries(plot(x,y)) ≈ ustrip.(x)
@test yguide(plot(x,y)) == "dB"
@test yseries(plot(x,y)) ≈ ustrip.(y)
plot(x, dbv)
@test yseries(plot!(x, v)) ≈ ustrip(uconvert.(u"dBV", v))
plot(x, v)
@test yseries(plot!(x, dbv)) ≈ ustrip(uconvert.(u"V", dbv))
end

@testset "labels" begin
@test xguide(plot(x, y, xlabel= "hello")) == "hello (dBm)"
@test xguide(plot(x, y, xlabel=P"hello")) == "hello"
@test yguide(plot(x, y, ylabel= "hello")) == "hello (dB)"
@test yguide(plot(x, y, ylabel=P"hello")) == "hello"
@test xguide(plot(x, y, xlabel= "hello", ylabel= "hello")) == "hello (dBm)"
@test xguide(plot(x, y, xlabel=P"hello", ylabel=P"hello")) == "hello"
@test yguide(plot(x, y, xlabel= "hello", ylabel= "hello")) == "hello (dB)"
@test yguide(plot(x, y, xlabel=P"hello", ylabel=P"hello")) == "hello"
end

end