MakieOrg / Makie.jl

Interactive data visualizations and plotting in Julia
https://docs.makie.org/stable
MIT License
2.41k stars 310 forks source link

Setting axis limits with `DateTime`s gives `MethodError`s #4059

Open anowacki opened 3 months ago

anowacki commented 3 months ago

Setting axis limits with DateTimes does not work, even though one can plot DateTimes perfectly well:

julia> using Dates: Second, now

julia> import GLMakie as Makie

julia> fig = Makie.Figure()
       ax = Makie.Axis(fig[1,1])
       Makie.scatter!(ax, [now(), now() + Second(1)], [0.3, 0.75])
       ax.limits = (now(), now() + Second(1), 0, 1)
       fig
ERROR: MethodError: Cannot `convert` an object of type DateTime to an object of type Float64

Closest candidates are:
  convert(::Type{T}, ::Number) where T<:Number
   @ Base number.jl:7
  convert(::Type{T}, ::DualNumbers.Dual) where T<:Union{Real, Complex}
   @ DualNumbers ~/.julia/packages/DualNumbers/5knFX/src/dual.jl:24
  convert(::Type{T}, ::Unitful.Quantity) where T<:Real
   @ Unitful ~/.julia/packages/Unitful/GYzMo/src/conversion.jl:139
  ...

Stacktrace:
  [1] cvt1
    @ ./essentials.jl:468 [inlined]
  [2] ntuple
    @ ./ntuple.jl:49 [inlined]
  [3] convert(::Type{Tuple{Float64, Float64}}, x::Tuple{DateTime, DateTime})
    @ Base ./essentials.jl:470
  [4] reset_limits!(ax::Makie.Axis; xauto::Bool, yauto::Bool, zauto::Bool)
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:582
  [5] reset_limits!
    @ ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:557 [inlined]
  [6] (::Makie.var"#1656#1687"{Makie.Axis})(::Tuple{DateTime, DateTime, Int64, Int64})
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:496
  [7] #invokelatest#2
    @ ./essentials.jl:892 [inlined]
  [8] invokelatest
    @ ./essentials.jl:889 [inlined]
  [9] notify
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:206 [inlined]
 [10] setindex!(observable::Observables.Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/YdEbO/src/Observables.jl:123
 [11] setproperty!(x::Makie.Axis, key::Symbol, value::Tuple{DateTime, DateTime, Int64, Int64})
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks.jl:443
 [12] top-level scope
    @ REPL[53]:6
julia> fig = Makie.Figure();

julia> ax = Makie.Axis(fig[1,1], limits=(now(), now() + Second(1), 0, 1))
ERROR: MethodError: no method matching defaultlimits(::Tuple{DateTime, DateTime}, ::typeof(identity))

Closest candidates are:
  defaultlimits(::Tuple{Any, Any}, ::Any, ::Any)
   @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:1418
  defaultlimits(::Tuple{Nothing, Nothing}, ::Any)
   @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:1429
  defaultlimits(::Nothing, ::Any)
   @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:1424
  ...

Stacktrace:
  [1] defaultlimits(userlimits::Tuple{Tuple{DateTime, DateTime}, Tuple{Int64, Int64}}, xscale::Function, yscale::Function)
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:1419
  [2] defaultlimits(l::Tuple{DateTime, DateTime, Int64, Int64}, xscale::Function, yscale::Function)
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:1416
  [3] initialize_block!(ax::Makie.Axis; palette::Nothing)
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:158
  [4] initialize_block!(ax::Makie.Axis)
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks/axis.jl:150
  [5] _block(T::Type{…}, fig_or_scene::Makie.Figure, args::Vector{…}, kwdict::Dict{…}, bbox::Nothing; kwdict_complete::Bool)
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks.jl:371
  [6] _block
    @ ~/.julia/packages/Makie/rEu75/src/makielayout/blocks.jl:291 [inlined]
  [7] #_block#1422
    @ ~/.julia/packages/Makie/rEu75/src/makielayout/blocks.jl:259 [inlined]
  [8] _block(::Type{Makie.Axis}, ::GridLayoutBase.GridPosition; kwargs::@Kwargs{limits::Tuple{…}})
    @ Makie ~/.julia/packages/Makie/rEu75/src/makielayout/blocks.jl:253
  [9] _block
    @ ~/.julia/packages/Makie/rEu75/src/makielayout/blocks.jl:246 [inlined]
 [10] #_#1420
    @ ~/.julia/packages/Makie/rEu75/src/makielayout/blocks.jl:237 [inlined]
 [11] top-level scope
    @ REPL[65]:1
Some type information was truncated. Use `show(err)` to see complete types.

I guess also related: #3959, #3972.

jariji commented 2 months ago

It does seem good for limits to be unitful. I would think ax.finallimits too?

SimonDanisch commented 2 months ago

it should work via limits!(ax, now(), now() + Second(1), 0, 1), where it does apply the correct conversion. We may be able to fix ax.limits = (...) too.

It does seem good for limits to be unitful.

I would like to stay away from that, it's always so "poisonous" to introduce units in some core attribute like finallimits - in the end, suddenly everything needs to be unitful, and we would need to completely recompile any involved method when switching units.

jariji commented 2 months ago

What about ticks, as in xticks = Date(2000):Month(3):Date(2001)))?

SimonDanisch commented 2 months ago

That still needs to be implemented here: https://github.com/MakieOrg/Makie.jl/blob/master/src/dim-converts/dates-integration.jl#L89-L115 (ticks is the argument that needs to be respected here)