DynamicQuantities.jl icon indicating copy to clipboard operation
DynamicQuantities.jl copied to clipboard

Potential Makie.jl support?

Open icweaver opened this issue 8 months ago • 4 comments

Hi Miles, this package is awesome!

Sorry if this was brought up somewhere already, but are there any plans to start introducing Makie.jl support?

I'm still learning about the internals of both packages, but just following along with https://docs.makie.org/stable/explanations/dim-converts#Developer-docs and unitful-integration.jl, I was pleasantly surprised to see how doable it seemed to get a barebones implementation standing:

Details

using Makie
import DynamicQuantities as DQ

struct DQConversion <: Makie.AbstractDimConversion
    quantities::Observable{Any}
    DQConversion() = new(Makie.automatic)
end

Makie.expand_dimensions(::PointBased, y::AbstractVector{<:DQ.Quantity}) = (keys(y), y)

Makie.needs_tick_update_observable(conversion::DQConversion) = nothing

Makie.create_dim_conversion(::Type{<:DQ.Quantity}) = DQConversion()

Makie.MakieCore.should_dim_convert(::Type{<:DQ.Quantity}) = true

Makie.convert_dim_value(::DQConversion, quantities) = [DQ.ustrip(q) for q in quantities]

function Makie.convert_dim_observable(conversion::DQConversion, values_obs::Observable, deregister)
    result = Observable(Float64[])
    f = on(values_obs; update=true) do values
        result[] = Makie.convert_dim_value(conversion, values)
        conversion.quantities[] = values
    end
    push!(deregister, f)
    return result
end

function Makie.get_ticks(conversion::DQConversion, ticks, scale, formatter, vmin, vmax)
    tick_vals, labels = Makie.get_ticks(ticks, scale, formatter, vmin, vmax)
    return tick_vals, string.(labels, string(DQ.dimension(conversion.quantities[])))
end
using CairoMakie

fig = Figure()

y = 60:10:100

scatter(fig[1, 1], y * DQ.u"m")
scatter(fig[1, 2], DQ.QuantityArray(y, DQ.u"m"))
scatter(fig[2, 1], y * DQ.u"kg", y * DQ.u"m")
scatter(fig[2, 2], y * DQ.us"m/s/Hz")

fig

Image

By the way, I love that SymbolicDimensions allows us to just do things like this:

scatter((60:10:100)DQ.us"cm")

instead of this with Unitful.jl:

import Unitful as U

scatter((60:10:100)U.u"cm"; axis=(; dim2_conversion=Makie.UnitfulConversion(U.u"cm")))

icweaver avatar Mar 09 '25 04:03 icweaver

Sounds good to me. I guess it goes in an extension. The hard part is probably writing unittests.

MilesCranmer avatar Mar 09 '25 12:03 MilesCranmer

Dope! Happy to try chipping away at this. Were you thinking something like this to start?

icweaver avatar Mar 09 '25 21:03 icweaver

Sounds good!

Also it might be good if you post an issue on Makie.jl to verify that this is how one is supposed to overload these functions? Also if there is API stability here or not.

MilesCranmer avatar Mar 09 '25 21:03 MilesCranmer

For sure! Just opened https://github.com/MakieOrg/Makie.jl/issues/4859

icweaver avatar Mar 09 '25 22:03 icweaver

Closed by https://github.com/MakieOrg/Makie.jl/pull/5280 🎉

icweaver avatar Sep 01 '25 21:09 icweaver