-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integration with Makie #95
Comments
I never got Makie working so it's highly unlikely I'll work on that myself. I thought Makie used the same plotting recipes as Plots? |
I also though so, but I does not work out-the box as with Plots.jl. So something is different. |
Well, you need someone who can use Makie and cares about this package. It won't be me though 🙂 (but ideally, a single solution that works for both Plots and Makie would be best) |
Noted, and completely fair. I hope someone from Makie could help out. If not, ill probably get around to learning how to fix it at some point. |
Would a few simple type recipes be a start possibly? I'm still learning about full recipes, but something like this seems to work pretty well: using CairoMakie
using Measurements
import Measurements: value, uncertainty
Makie.convert_arguments(P::PointBased, v::Vector, m::AbstractVector{<:Measurement}) =
convert_arguments(P, v, value.(m))
Makie.convert_arguments(P::Type{<:Errorbars}, v::Vector, m::AbstractVector{<:Measurement}) =
convert_arguments(P, v, value.(m), uncertainty.(m))
fig = Figure()
x = rand(10) |> sort
y = rand(10) .± rand(0:0.01:1, 10)
scatter(fig[1, 1], x, y)
lines(fig[2, 1], x, y)
scatterlines(fig[1, 2], x, y)
errorbars(fig[2, 2], x, y)
scatter!(fig[2, 2], x, y)
axs = reshape(copy(fig.content), 2, 2)
linkaxes!(axs...)
hidexdecorations!.(axs[begin, :])
hideydecorations!.(axs[:, end])
fig |
Last time I tried looking into this, it seemed as if recipes did not work properly in Makie. It was a WIP. But your example definitely looks functional! Nice ^_^ Personally, I was imagining something like But your approach definitely seems more modular, which I like! One would e.g. choose how many standard deviations should be represented by the shaded area, and simply layer the uncertainty and means values on top of each other, as you have. |
I think having a way to let Makie.jl know that using CairoMakie
using Measurements
import Measurements: value, uncertainty
@recipe(Scatterbars) do scene
Attributes(;)
@recipe(BandLines) do scene
Attributes(;)
function Makie.convert_arguments(::Type{<:Scatterbars}, v::Vector, m::AbstractVector{<:Measurement})
v, value.(m), uncertainty.(m)
end
function Makie.convert_arguments(::Type{<:BandLines}, v::Vector, m::AbstractVector{<:Measurement})
v, value.(m), uncertainty.(m)
end
function Makie.plot!(plot::Scatterbars{T}) where T <: Tuple{Vector, Vector, Vector}
x, y, y_err = plot[1][], plot[2][], plot[3][]
errorbars!(plot, x, y, y_err)
scatter!(plot, x, y)
plot
end
function Makie.plot!(plot::BandLines{T}) where T <: Tuple{Vector, Vector, Vector}
x, y, y_err = plot[1][], plot[2][], plot[3][]
band!(plot, x, y - y_err, y + y_err, color=(:blue, 0.25))
lines!(plot, x, y)
plot
end
fig = Figure()
ax_sb, ax_bl = Axis(fig[1, 1]), Axis(fig[1, 2])
x = rand(10) |> sort
y = rand(10) .± rand(0:0.01:0.1, 10)
scatterbars!(ax_sb, x, y)
bandlines!(ax_bl, x, y)
axs = reshape(copy(fig.content), 1, 2)
linkaxes!(axs...)
hideydecorations!.(axs[:, end])
fig There's definitely a lot more that could be done to make this more customizable, but I'm wondering if we'd even want to have separately named specialty functions like these in the first place |
I totally agree with you and that was my first thought in fixing this as well, but this leads to a new problem: How do we deal with arguments? For example, I dislike errorbars with I think a combination of both of your solutions might be best. To allow the standard plotting functions to take measurement inputs and to define a new functions which allow us to customise the combined output. This is the best approach I can see at this point in time, but I am far from an expert in Makie. |
So I played around with the pure conversion and ended up with: using MakieCore
using Measurements
import Measurements: value, uncertainty
# PointBased plots
MakieCore.convert_arguments(P::PointBased, x::AbstractVector{<:Measurement}, y::AbstractVector{<:Measurement}) =
convert_arguments(P, value.(x), value.(y))
MakieCore.convert_arguments(P::PointBased, x::AbstractVector{<:Real}, y::AbstractVector{<:Measurement}) =
convert_arguments(P, x, value.(y))
MakieCore.convert_arguments(P::PointBased, x::AbstractVector{<:Measurement}, y::AbstractVector{<:Real}) =
convert_arguments(P, value.(x), y)
# errorbars
MakieCore.convert_arguments(P::Type{<:Errorbars}, x::AbstractVector{<:Measurement}, y::AbstractVector{<:Measurement}, e::AbstractVector{<:Measurement}) =
convert_arguments(P, value.(x), value.(y), uncertainty.(e))
MakieCore.convert_arguments(P::Type{<:Errorbars}, x::AbstractVector{<:Measurement}, y::AbstractVector{<:Real}) =
convert_arguments(P, value.(x), y, uncertainty.(x))
MakieCore.convert_arguments(P::Type{<:Errorbars}, x::AbstractVector{<:Real}, y::AbstractVector{<:Measurement}) =
convert_arguments(P, x, value.(y), uncertainty.(y))
# band
MakieCore.convert_arguments(P::Type{<:Band}, x::AbstractVector{<:Measurement}, y::AbstractVector{<:Measurement}) =
convert_arguments(P, value.(x), value.(y) - uncertainty.(y), value.(y) + uncertainty.(y))
MakieCore.convert_arguments(P::Type{<:Band}, x::AbstractVector{<:Real}, y::AbstractVector{<:Measurement}) =
convert_arguments(P, x, value.(y) - uncertainty.(y), value.(y) + uncertainty.(y)) This converts the cases in which x, y or both have errors. I also made a few assumptions regarding these cases. For In case of bands the y-error gets plotted automatically, while the x-error (if present) gets ignored. I tested this on some old data of mine: using DataFrames, CairoMakie, Measurements
df = DataFrame("α" => ((0:30:180) .± 5), "U" => ([1.70 ± 0.02, 1.50 ± 0.02, 0.864 ± 0.01, 0.103 ± 0.05, 0.888 ± 0.02, 1.46 ± 0.01, 1.70 ± 0.02]/2))
fig = Figure()
ax1 = Axis(fig[1,1])
errorbars!(ax1, df.α, df.U, df.U)
errorbars!(ax1, df.α, df.U, df.α, direction =:x)
scatter!(ax1, df.α, df.U)
ax2 = Axis(fig[1,2])
band!(ax2, df.α, df.U)
lines!(ax2, df.α, df.U)
fig So, this works as a basic system and allow us to deal with all types of errors, that I at least have encountered. My question now is, do we actually want plots like In the case that someone does not want to customise the plots a lot, this would be useful, but then we would have to agree on a basic look first. I doubt that the "normal" I think we should maybe just do it like this here? Making separate plot types would be more work then just doing two separate plots on the same axis. What do you think?
On second thought, I take this back. I think just doing it with simple conversion might really be the best option. |
Currently, there is some LOVELY integration and fluidity between
Plots.jl
and this package. I guess this is acomplished by exporting a plotting-recipe for measurements.If I am not mistaken, Makie consumes
Plots.jl
recipes. Is it possible to also export this plotting recipe for the Makie ecosystem?The text was updated successfully, but these errors were encountered: