DimensionalData.jl
DimensionalData.jl copied to clipboard
Plot of `Observable{DimArray{<:Quantity}}` does not update when using `@lift`
Hello,
I found that plots of observable of DD do not update when using unitful and @lift. For example:
using GLMakie, Unitful, Unitful.DefaultSymbols, DimensionalData
dd = Observable(DimArray(collect(1V:1V:10V), X(1:10)))
dd_2 = @lift identity($dd)
fig, ax, plt = lines(dd_2)
dd[] = DimArray(collect(10V:-1V:1V), X(1:10))
dd_2
Observable(Quantity{Int64, 𝐋^2 𝐌 𝐈^-1 𝐓^-3, Unitful.FreeUnits{(V,), 𝐋^2 𝐌 𝐈^-1 𝐓^-3, nothing}} [10 V, 9 V, 8 V,
7 V, 6 V, 5 V, 4 V, 3 V, 2 V, 1 V])
dd_2 is updated correctly but the plot does not update:
I looked a little bit into the issue and the plot is updated correctly if not using Quantity:
using GLMakie, Unitful, Unitful.DefaultSymbols, DimensionalData
dd = Observable(DimArray(collect(1:1:10), X(1:10)))
dd_2 = @lift identity($dd)
fig, ax, plt = lines(dd_2)
dd[] = DimArray(collect(10:-1:1), X(1:10))
Also, it works fine if not using @lift. I.e.:
using GLMakie, Unitful, Unitful.DefaultSymbols, DimensionalData
dd = Observable(DimArray(collect(1:1:10), X(1:10)))
fig, ax, plt = lines(dd)
dd[] = DimArray(collect(10:-1:1), X(1:10))
Thanks!
This must be something to do with how Makie handles quantities... we don't do anything differently between regular numeric lookups and unitful
Do plots update if you manually uses observerable axes of units as the first two arguments? Thats all we are doing underneath.
@SimonDanisch does this make any sense to you?
It seems to work if the axes are set manually:
using GLMakie, Unitful, Unitful.DefaultSymbols, DimensionalData
dd = Observable(DimArray(collect(1V:1V:10V), X(1:10)))
dd_2 = @lift identity($dd)
fig, ax, plt = lines((@lift lookup($dd_2, X)), (@lift parent($dd_2)))
lines(fig[1,2], dd_2)
dd[] .*= 2
notify(dd)
fig
The package versions:
(jl_EVI1bY) pkg> status
Status `/tmp/jl_EVI1bY/Project.toml`
[0703355e] DimensionalData v0.29.13
[e9467ef8] GLMakie v0.11.3
[1986cc42] Unitful v1.22.0
This issue seems to be related to a change in GLMakie from v0.10 to v0.11 as the code works with v0.10
(jl_xqozAK) pkg> status
Status `/tmp/jl_xqozAK/Project.toml`
[0703355e] DimensionalData v0.29.13
⌃ [e9467ef8] GLMakie v0.10.18
[1986cc42] Unitful v1.22.0
Info Packages marked with ⌃ have new versions available and may be upgradable.
using GLMakie, Unitful, Unitful.DefaultSymbols, DimensionalData
dd = Observable(DimArray(collect(1V:1V:10V), X(1:10)))
dd_2 = @lift identity($dd)
fig, ax, plt = lines((@lift lookup($dd_2, X)), (@lift parent($dd_2)))
lines(fig[1,2], dd_2)
dd[] .*= 2
notify(dd)
fig
Thank you that's an amazing MWE. Yes something must have changed in Makie 0.11 that we haven't followed.
If you have time for a PR you are probably better placed to fix the code here than I am at this point.
It may be something to do with the change in Makie recipe methods and expand_dimensions, maybe @asinghvi17 has some pointers too.
Thanks, I will try to put a PR together for this
Hi,
I looked a more into this and found a solution for this issue and #906.
using GLMakie, Unitful, Unitful.DefaultSymbols, DimensionalData
using GLMakie.Makie
function Makie.convert_arguments(P::Makie.PointBased, dd::DimensionalData.AbstractDimVector)
return Makie.convert_arguments(P, parent(lookup(dd, 1)), parent(dd))
end
Makie.expand_dimensions(::Makie.PointBased, y::DimensionalData.AbstractDimVector) = return
function Makie.convert_arguments(P::Type{Makie.Series}, dd::DimensionalData.AbstractDimMatrix)
# TO DO: this needs to be edited to select right dimension as in DimensionalDataMakieExt
xs = parent(lookup(dd, 2))
return Makie.convert_arguments(P, xs, parent(dd))
end
Makie.expand_dimensions(::Makie.Series, y::DimensionalData.AbstractDimMatrix) = return
fig = Figure()
dd = Observable(DimArray(collect(1V:1V:10V), X(10:10:100)))
dd_2 = @lift identity($dd)
lines(fig[1,1], (@lift lookup($dd_2, X)), (@lift parent($dd_2)))
lines(fig[1,2], dd_2)
dd[] .*= 2
notify(dd)
dimarray = rand(Y(3), X(7))
series(fig[2,1], dimarray)
series(fig[2,2], Observable(dimarray))
fig
For testing, I removed DimensionalDataMakieExt, so the labels and etc should appear if the code is merged into DimensionalDataMakieExt.
I have limited experience with recipes in Makie so I want to check that this approach seems sensible before merging it with DimensionalDataMakieExt. Is there any reason that I am not aware of to not set Makie.expand_dimensions to return nothing?
I don't really know what expand_dimension API rules are, is it documented in Makie? What do Makies internal objects return?
I have not found much documentation about expand_dimension, other than:
help> Makie.expand_dimension
Expands the dims for e.g. scatter(1:4) becoming scatter(1:4, 1:4) for 2D plots. We're separating this state from convertarguments, to better apply `dimconverts` before convert_arguments.
My current interpretation is that by defining the Makie extension as:
function Makie.convert_arguments(P::Makie.PointBased, dd::DimensionalData.AbstractDimVector)
return Makie.convert_arguments(P, parent(lookup(dd, 1)), parent(dd))
end
Makie.expand_dimensions(P::Makie.PointBased, y::DimensionalData.AbstractDimVector) = return Makie.convert_arguments(P, y)
The conversion between DimArray to normal Array is performed when the conversion pipeline calls expand_dimension. I.e. the internal call of Makie to convert_arguments is already performed with the Array instead of DimArray.
By defining as:
function Makie.convert_arguments(P::Makie.PointBased, dd::DimensionalData.AbstractDimVector)
return Makie.convert_arguments(P, parent(lookup(dd, 1)), parent(dd))
end
Makie.expand_dimensions(P::Makie.PointBased, y::DimensionalData.AbstractDimVector) = nothing
The conversion between DimArray to normal Array is performed when Makie call convert_arguments, which is as recommended by the plot recipes. See:
https://github.com/MakieOrg/Makie.jl/blob/d77c537884e139eb476cb552a8129ef270586e6b/src/interfaces.jl#L271 https://github.com/MakieOrg/Makie.jl/blob/d77c537884e139eb476cb552a8129ef270586e6b/src/interfaces.jl#L148
The behaviour of this issue makes sense with the comment https://github.com/MakieOrg/Makie.jl/blob/d77c537884e139eb476cb552a8129ef270586e6b/src/interfaces.jl#L159, as probably the Observable is only looking for changes in one of the outputs from expand_dimensions instead of both.
Looking into the tips for plots recipe in Makie, it seems that the default of Makie is for expand_dimensions to return nothing. The only exception is for AbstractArrays
Thanks that all makes sense to me.
I guess all you can do now is go through the test plots and check they are working after the change.
Otherwise I'm happy to merge that