Makie.jl
Makie.jl copied to clipboard
Implement time axis
I noticed, that we can hack together a simple time aware axis as a small wrapper type around Axis
...
We may even be able to integrate this into the Axis
code itself, so that we don't need a wrapper, and the axis will just change to the correct conversion + formatting functions, depending on what you plot into it.
This would basically add a pre convert_arguments
conversion, that is axis aware and can store axis local state (e.g. target unit, target range, etc).
We could also use this for categorical values and Float32 conversion, I think.
Still pretty early to tell, but I will use the TimeAxis
wrapper to figure out the interface and add tests + proper error handling for the myriad of time conversions we may run into.
If this works out nicely, we can think about removing TimeAxis
and add it to the standard Axis
code.
But the simple mvp already works as intended:
f = Figure()
ax = TimeAxis(f[1,1])
scatter!(ax, rand(Hour(1):Hour(1):Hour(20), 10), 1:10)
f
scatter!(ax, rand(Second(1):Second(60*60):Second(20*60*60), 10), 1:10)
This currently uses promote_type to figure out the conversion target, which isn't ideal since we should rather chose the unit from the range of time values we want to display...
Ultrafast laser pulses seem to be resolved on a fs scale, so maybe it's worth going down to that level? For reference: https://www.newport.com/n/ultrafast-pulse-characterization https://www.dickinson.edu/download/downloads/id/25/ultrafastlaserpulses
Yeah makes sense - that was just an oversight ... Still getting familiar with Unitful.jl and how to discover things...
I first wanted to implement this as unobtrusive as possible by introducing a new axis wrapper type (TimeAxis
), but the more I worked on the implementation, the clearer it became, that the wrapper isn't needed at all and that I really just need to spice up the tick formatter a bit to integrate this into the standard axis.
At that point it seemed pretty silly to not do that, since then we'd introduce a new TimeAxis
type, just to deprecate it a few versions later...
It will also be very easy to add new Tick types e.g. for categorical values etc...
This is pretty close to being mergeable:
- [x] new axis conversion & tick formatter finding API
- [x] Unitful integration, introducing a UnitfulTicks type, that gets chosen for x/yticks whenever you plot unitful numbers to either axis
- [x] some tests
- [ ] clean up & document new APIs
Great to see this! (I assume this) fixes #442.
Does this work for DateTime
, like:
f = Figure()
ax = Axis(f[1,1])
scatter!(ax, rand(DateTime(2021,1,1):Second(900):DateTime(2021,2,1), 10), 1:10)
Yeah:
using CairoMakie, Dates
f = Figure()
ax = Axis(f[1,1])
scatter!(ax, rand(DateTime(2021,1,1):Second(900):DateTime(2021,2,1), 10), 1:10)
Although it's cut off... @jkrumbiegel can we chose ticks closer to the middle if we know that the ticklabels are going to be long?
Very nice but the chosen ticks have to be improved. The timestamps are:
[
DateTime(2021,1,3,14,30),
DateTime(2021,1,4,9,23,20),
DateTime(2021,1,5,4,16,40),
DateTime(2021,1,5,23,10),
DateTime(2021,1,6,18,3,20),
]
But only showing the time completely throws you off when trying to read the figure. Also a distance of 68000 seconds between the ticks is not intuitive. The ticks could be borrowed from: https://github.com/JuliaPlots/PlotUtils.jl/blob/c2cf71981ac5bec28b040a545335f7ffa2506c53/src/ticks.jl#L471
A reference from Plots.jl
using Plots, Dates
t, y = rand(DateTime(2021,1,1):Second(900):DateTime(2021,2,1), 10), 1:10
scatter(t,y)
Hm, I guess I should just use PlotUtils.optimize_datetime_ticks
like Plots.jl and be done with it ;)
t, y = rand(DateTime(2021,1,1):Second(900):DateTime(2021,2,1), 10), 1:10
scatter(t,y)
Cool!
What about Date
and Time
?
Fixes: https://github.com/JuliaPlots/Makie.jl/issues/442
I'm really looking forward to this. When do you expect this to be ready for release?
Will this also allow setting an axis to categorical data in recipes?
Will this also allow setting an axis to categorical data in recipes?
Yes it should!
Great work! I consider dropping Plots for Makie if this lands. Any time prediction on when this will happen?
In principle this PR is feature complete and works, but I will need some more time to finish up developer docs and clean up some hacks. E.g., I noticed that this PR doubles CI times for docs and adds at least 10min to the tests...Which is pretty unacceptable and I need to debug why that happens... Also, the conversion pipeline got even more confusing and I still hope to find a cleaner implementation for the axis converts.
Although, I just noticed, that RPRMakie goes from 5min to 23min... Which is a bit suspicious, since the one test right now in RPRMakie is super simple, and seeing that Makie CI is even faster than in other PRs, this all doesn't make much sense :D Maybe it's just a fluke of the CI. I also just tested this code piece, which should give a good idea of any large scale regression, and that comes out with exactly the same number as on master (1s faster even):
@time begin
using GLMakie
display(scatter(1:4))
end
So maybe this was really just a CI fluke, or there is one super slow code path - both should be good news, since those should then be much easier to fix than all of Makie becoming much slower (by the new deps, or new type unstable code).
Aha...restarting the CI:
Other PRs are also around 20 min, so seems really just like a fluke :)
If I wanted to use/test this already, what would be the easiest way to do so? It'd be so cool if there was an insider/experimental release.
Edit: Regarding the
Also, the conversion pipeline got even more confusing and I still hope to find a cleaner implementation for the axis converts.
What's the circumstance with that? Maybe a new perspective might help 🙈 😀
@SimonDanisch Sorry for the bump, I was wondering if there was anything left blocking? Having direct support for dates would be great feature!
Ultrafast laser pulses seem to be resolved on a fs scale, so maybe it's worth going down to that level? For reference: https://www.newport.com/n/ultrafast-pulse-characterization https://www.dickinson.edu/download/downloads/id/25/ultrafastlaserpulses
Considering that quantities measured in femtoseconds generally don't require use of the Julian calendar, you can probably make do without femtosecond support here. fwiw
Compile Times benchmark
Note, that these numbers may fluctuate on the CI servers, so take them with a grain of salt. All benchmark results are based on the mean time and negative percent mean faster than the base branch. Note, that GLMakie + WGLMakie run on an emulated GPU, so the runtime benchmark is much slower. Results are from running:
using_time = @ctime using Backend
# Compile time
create_time = @ctime fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @ctime Makie.colorbuffer(display(fig))
# Runtime
create_time = @benchmark fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @benchmark Makie.colorbuffer(display(fig))
using | create | display | create | display | |
---|---|---|---|---|---|
GLMakie | 32.04s (31.81, 32.22) 0.15+- | 16.25s (16.17, 16.33) 0.06+- | 15.03s (14.92, 15.27) 0.12+- | 12.13ms (11.83, 12.32) 0.17+- | 138.41ms (134.74, 141.10) 2.30+- |
master | 31.52s (31.14, 31.65) 0.17+- | 16.26s (16.17, 16.40) 0.08+- | 15.24s (15.08, 15.36) 0.10+- | 11.90ms (11.72, 12.11) 0.14+- | 135.09ms (132.00, 136.43) 1.47+- |
evaluation | +1.63%, 0.52s slower X (3.20d, 0.00p, 0.16std) | -0.07%, -0.01s invariant (-0.16d, 0.77p, 0.07std) | -1.37%, -0.21s faster ✓ (-1.89d, 0.00p, 0.11std) | +1.86%, 0.23ms slower X (1.43d, 0.02p, 0.16std) | +2.40%, 3.32ms slower X (1.72d, 0.01p, 1.88std) |
CairoMakie | 30.78s (30.55, 31.01) 0.16+- | 18.20s (18.07, 18.31) 0.10+- | 2.80s (2.76, 2.84) 0.03+- | 12.51ms (12.39, 12.64) 0.08+- | 4.88ms (4.78, 4.93) 0.05+- |
master | 30.41s (30.11, 30.81) 0.23+- | 17.94s (17.73, 18.10) 0.11+- | 2.75s (2.72, 2.80) 0.03+- | 12.48ms (12.14, 12.81) 0.21+- | 5.02ms (4.86, 5.52) 0.23+- |
evaluation | +1.22%, 0.38s slower X (1.87d, 0.01p, 0.20std) | +1.40%, 0.26s slower X (2.40d, 0.00p, 0.11std) | +1.59%, 0.04s slower X (1.42d, 0.02p, 0.03std) | +0.20%, 0.02ms invariant (0.15d, 0.78p, 0.15std) | -2.82%, -0.14ms invariant (-0.84d, 0.16p, 0.14std) |
WGLMakie | 37.46s (37.18, 37.75) 0.24+- | 19.22s (19.11, 19.30) 0.07+- | 23.31s (22.91, 23.53) 0.21+- | 14.44ms (13.53, 15.24) 0.69+- | 2.36s (2.01, 2.61) 0.19+- |
master | 37.16s (37.07, 37.22) 0.06+- | 19.85s (19.65, 20.02) 0.15+- | 23.51s (23.16, 23.98) 0.28+- | 14.53ms (14.12, 15.29) 0.38+- | 2.37s (2.33, 2.48) 0.05+- |
evaluation | +0.79%, 0.3s slower X (1.67d, 0.02p, 0.15std) | -3.30%, -0.63s faster ✓ (-5.55d, 0.00p, 0.11std) | -0.84%, -0.2s invariant (-0.80d, 0.16p, 0.24std) | -0.63%, -0.09ms invariant (-0.16d, 0.77p, 0.53std) | -0.67%, -0.02s invariant (-0.11d, 0.84p, 0.12std) |
Closing in favor of https://github.com/MakieOrg/Makie.jl/pull/3226