Comments (9)
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.
from measurements.jl.
I think having a way to let Makie.jl know that
scatter(m::AbstractVector{<:Measurement})
->errorbar
+scatter
andline
->band
+line
would be really neat!
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 whiskerwidth = 0
, which is the default. While this approach would allow us to put arguments for scatter
, it would as far as I can tell not allow us to place any arguments for errorbars
.
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.
from measurements.jl.
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?
from measurements.jl.
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.
from measurements.jl.
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)
from measurements.jl.
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
from measurements.jl.
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 scatter
producing a scatter+errorbars, and lines
producing a shaded area around the line representing 1 standard deviation, when the uncertanty is on the y values. I don't know what would be best for a potential x value uncertanty in a lines
plot.
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.
from measurements.jl.
I think having a way to let Makie.jl know that scatter(m::AbstractVector{<:Measurement})
-> errorbar
+ scatter
and line
-> band
+line
would be really neat! I'm not aware of a way to do this though, so in the meantime this is just my current attempt at trying to accomplish the same thing with a super bare-bones dedicated full recipe for each:
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
from measurements.jl.
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 errorbars
, if only one axis has errors, these are plotted automatically (though direction = :x
may have to be specified). If both axis have errors, then the axis has to be specified (as this allows for x-errors).
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 scatterbars
or linesband
? While yes, they would make plotting quicker, it would mess with any form of customisation. We would have to pass arguments for both plot-types, which I don't see how to do elegantly.
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" linesband
as in ax2
is something anyone would want to use.
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?
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.
On second thought, I take this back. I think just doing it with simple conversion might really be the best option.
from measurements.jl.
Related Issues (20)
- making measurements work with Printf
- Error when hashing Measurement{Float64} HOT 5
- Adding measurement components back to a measurement after iteratively solving for a value HOT 7
- [FR] Plot recipe: ribbon plots option beside error bars HOT 11
- tryparse for Measurement type
- Can't use unique with measurements HOT 1
- Measurements with missing errors HOT 4
- Measurements.value(x::Missing) = missing HOT 1
- Integration with Zygote
- `weightedmean()` returns `NaN ± 0`? HOT 1
- Use auto-differentiation engine
- Bad integration with Plots' boxplot HOT 2
- Move to pkgextensions for Julia v1.9+
- one(measurement) should return 1, not 1 ± 0 HOT 8
- `Symbolics.jl` support? HOT 7
- Plotting mixture of measurements and missing data HOT 1
- Trying to use Measurements to differentiate respect to a unitful quantity. HOT 12
- Is there an autodiff package that is compatible? HOT 3
- Broken `MeasurementsJunoExt.jl` HOT 1
- Julia 1.6 incompatibility from stdlib compat bounds HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from measurements.jl.