jw3126 / UnitfulRecipes.jl

Plots.jl recipes for Unitful.jl arrays
MIT License
37 stars 10 forks source link

Vector{Any} doesn't plot #52

Closed DanDeepPhase closed 3 years ago

DanDeepPhase commented 3 years ago

Vector{Any} errors out when stripping units

using Unitful, Plots, UnitfulRecipes  
x=(1:10)u"m"
y=[]  
for n in x  
    push!(y,n^2)  
end  
plot(x,y)

ERROR: DimensionError: Inf and 1.0 m^2 are not dimensionally compatible.

I tried initialize the empty vector as Vector{Quantity}() but that didn't help. I don't know how to initialize it to include the types for the fields.

briochemc commented 3 years ago

Yes, this package can only dispatch on the recipes if the type contains the unit. You could do either

y = x.^2 # or y = [v^2 for v in x]

for y to have the correct type or — if you really need to preallocate y — then you must get the element-type right from the start, for example with

y_eltype = typeof(x[1]^2) # Quantity{Int64, 𝐋², Unitful.FreeUnits{(m²,), 𝐋², nothing}}
y = y_eltype[] # now has the correct eltype to start with
for n in x
    push!(y,n^2)
end
briochemc commented 3 years ago

Does this solve your problem? (If yes, feel free to close this issue! 😃)

DanDeepPhase commented 3 years ago

This workaround solves my problem, and i can now make vectors that plot.

I didn't understand that it was the type of the vector and not the type of the scalar that was driving the recipe.

Thanks for the help

briochemc commented 3 years ago

I didn't understand that it was the type of the vector and not the type of the scalar that was driving the recipe.

Yes that's exactly it. As a general Julia rule, it's always good to avoid arrays with abstract types, like Any. So best to avoid starting with x = [] because it creates an empty vector of type Any. If you know the size S and type T, an efficient way to preallocate is to do something like:

julia> T = Float32
Float32

julia> S = (2,3)
(2, 3)

julia> x = Array{T}(undef, S)
2×3 Matrix{Float32}:
 6.35031f-27  3.17791f-26  0.0
 1.0f-45      1.0f-45      0.0

or if you are not chasing every last bit of performance, I like to fill it with a default value:

julia> x = fill(NaN32, S)
2×3 Matrix{Float32}:
 NaN  NaN  NaN
 NaN  NaN  NaN