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

Implement polar axis

Open asinghvi17 opened this issue 3 years ago • 6 comments

Description

This PR implements a PolarAxis layoutable which should be able to serve as a template for a more general NonlinearAxis layoutable.

rs, θs = LinRange(0, 1, 100), LinRange(0, 2π, 100)
field = [exp(r) + cos(θ) for r in rs, θ in θs];

fig = Figure()
po = PolarAxis(fig[1, 1])
surface!(po.scene, rs, θs, field; shading = false, colormap = :RdBu)
autolimits!(po)

record(fig, "test.mp4", LinRange(0, 2*pi, 600); framerate=60) do i
    po.θ_0[] = i
end

https://user-images.githubusercontent.com/32143268/171508924-0059d611-1d75-4709-9895-60095c5c4ef1.mp4

To-dos

  • [X] Angular tick labels
  • [x] Radial tick labels
  • [x] Tighter bounding box around the plot
  • [x] Figure out how to enable plot!(po, ...)
  • [x] Fix stack overflow error when MakieLayout.can_be_current_axis(::PolarAxis) = true
  • [ ] Better update semantics, hook up zooming
  • [x] Poly drawn around the plot to simulate clipping

Type of change

Delete options that do not apply:

  • [X] New feature (non-breaking change which adds functionality)

Checklist

  • [x] Added an entry in NEWS.md (for new features and breaking changes)
  • [ ] Added or changed relevant sections in the documentation
  • [ ] Added unit tests for new algorithms, conversion methods, etc.
  • [ ] Added reference image tests for new plotting functions, recipes, visual options, etc.

Fixes #309, #521

asinghvi17 avatar Jun 01 '22 17:06 asinghvi17

Compile Times benchmark

Note, that these numbers may fluctuate on the CI servers, so take them with a grain of salt.

using time

master:  9.11 < 9.21 > 9.31, 0.06+-
pr:      9.11 < 9.18 > 9.30, 0.06+-
speedup: 0.99 < 1.00 > 1.01, 0.01+-
median:  -0.35% => invariant

This PR does not change the using time.

ttfp time

master   25.00 < 25.19 > 25.71, 0.26+-
pr       25.04 < 25.23 > 25.51, 0.19+-
speedup: 0.99 < 1.00 > 1.01, 0.01+-
median:  +0.18% => invariant

This PR does not change the ttfp time.

MakieBot avatar Jun 01 '22 17:06 MakieBot

Just fixed the bounding box issue - it was an issue in my transformation method for rects.

Need to hook up protrusions, enable plotting, and the axis should be ready to go!

iTerm2 Gqs3ze

asinghvi17 avatar Jun 04 '22 21:06 asinghvi17

Haven't had a lot of time to look at it yet unfortunately, but I'm wondering how best to handle integration with existing methods that modify xgridvisible/ygridvisible or other x<parameter>/y<parameter>. I've noticed that this implementation uses inherit in some places but not everywhere. I think I remember that e.g. clearing the grid with one of the builtin methods isn't supported yet. I guess we'll need to check to what extent r and θ can be made semantically equivalent to x and y in the API, or where we need dedicated methods that handle exotic axes separately.

adigitoleo avatar Jun 14 '22 11:06 adigitoleo

Thanks for the detailed review @ffreyer! I'll probably have that last comment wrapped up tomorrow or so. It seems like the bounding boxes can be obtained by:

ttp = (po::PolarAxis).blockscene.plots[end-2]
Makie.boundingbox(ttp.plots[1].plots[1][1][][1], Makie.to_rotation(ttp.plots[1].plots[1].rotation[]))

although this is pretty fragile. The bboxes do seem to be independent of position, though.

@adigitoleo, about your comment - now that theming is hooked up, I will create some setters for e.g. rticks, θticks which handle both the ticks and their labels (size, color, alignment, etc). I'll also implement hide[/x/y]decorations methods for the polar axis.

asinghvi17 avatar Jul 01 '22 07:07 asinghvi17

I'm not the biggest fan of θticks just because there's not a single unicode symbol in the rest of our api. And many people probably don't know immediately what it means anyway.

jkrumbiegel avatar Jul 04 '22 18:07 jkrumbiegel

Any recent update regarding this PR? This is the only recipe that is missing in order to migrate all my plots to Makie.jl

juliohm avatar Aug 25 '22 12:08 juliohm

Kind of lost track on this, if you've tested it are there any issues with it currently @juliohm? (beyond those already mentioned)

asinghvi17 avatar Jan 14 '23 04:01 asinghvi17

Is this PR still alive? I would love to have polar axes in Makie...

TacHawkes avatar Feb 25 '23 10:02 TacHawkes

ah, I guess this kind of lost steam for a bit. I'll have to take a look at the code again.

asinghvi17 avatar Feb 25 '23 10:02 asinghvi17

What needs to happen to get this PR moving? Unit tests and docs? I've tested the basic functionality on the most recent version of Makie, it works fine after a few tweaks. Happy to help however I can, to me polar plots are an essential part of a plotting package. Really surprised they've been missing from Makie for so long...

brendanjohnharris avatar May 17 '23 07:05 brendanjohnharris

Really surprised they've been missing from Makie for so long

They're just tricky to implement correctly given specific rendering requirements they have. For example, non-rectangular clipping masks, transformation-dependent rendering of primitives, handling of arbitrary axis types in certain code paths and more.

jkrumbiegel avatar May 17 '23 08:05 jkrumbiegel

+1 for this. Currently needing polar axes and using TikZ. Would be nice to use Makie.

sethaxen avatar May 21 '23 14:05 sethaxen

I've been playing around with this pr a bit, so I have some more thoughts:

I agree with Julius that $\theta$ should go. It's kind of annoying to type, might be confusing to some and also not that readable imo. Maybe we can just use angle/angular_something instead?

I'm wondering if it would be better to move grid lines and text to the transform aware scene. That would get rid off all the manual projections. For grid lines that should be no problem, but for text it might be a bit difficult to figure out the correct positioning. Though I think it's possible to derive the needed things from character boundingboxes (which should be mostly static), the scene area and limits.

Note that you can (up to maybe unavoidable equal length problems) also specify text alignment freely as a vector:

θtick_align[] = map(θtickpos) do p
    s, c = sincos(p[2])
    Point2f(0.5 - 0.5c, 0.5 - 0.5s)
end
...
text!(..., align = θtick_align)

How should zooming work for this? Should translating work? I guess like Axis is a static rectangle with varying ticks, this should be a static circle with varying ticks? And probably only zooming, no translation?

ffreyer avatar May 24 '23 13:05 ffreyer

How should zooming work for this? Should translating work? I guess like Axis is a static rectangle with varying ticks, this should be a static circle with varying ticks? And probably only zooming, no translation?

Well you could potentially have a circle segment between some theta and some r.

θ should go

We could go \theta -> t or so, I wouldn't mind that but do want to keep the semantic meaning.

asinghvi17 avatar May 24 '23 13:05 asinghvi17

How should zooming work for this? Should translating work?

Just to provide a point of comparison, not necessarily saying we need to do the same, but matplotlib seems to only support zooming the way you suggest, with a static circular axis. See these docs and this screen capture:

https://github.com/MakieOrg/Makie.jl/assets/34595875/5b6daf72-1c09-4b6b-8579-5cd4abb2d46c

adigitoleo avatar May 28 '23 21:05 adigitoleo

I'm wondering if it would be better to move grid lines and text to the transform aware scene. That would get rid off all the manual projections. For grid lines that should be no problem, but for text it might be a bit difficult to figure out the correct positioning. Though I think it's possible to derive the needed things from character boundingboxes (which should be mostly static), the scene area and limits.

Still need to implement tight tick spacing but I think it'll work.

Note that you can (up to maybe unavoidable equal length problems) also specify text alignment freely as a vector:

θtick_align[] = map(θtickpos) do p
    s, c = sincos(p[2])
    Point2f(0.5 - 0.5c, 0.5 - 0.5s)
end
...
text!(..., align = θtick_align)

Also figured out why this wasn't working. The alignment is pretty clean now, though the padding is still hard coded. Here's a screenshot with awkward tick steps and debug colors for clipping:

Screenshot from 2023-05-29 18-41-58

I can push my changes here, but I changed quite a lot so maybe I should just start a continuation pr instead? Otherwise it might get hard/confusing to work with this one if my approach doesn't work/isn't good.

How should zooming work for this? Should translating work?

Just to provide a point of comparison, not necessarily saying we need to do the same, but matplotlib seems to only support zooming the way you suggest, with a static circular axis. See these docs and this screen capture:

Yea I think that's probably the default we should go for too.

ffreyer avatar May 29 '23 16:05 ffreyer

Merged in https://github.com/MakieOrg/Makie.jl/pull/2990/

SimonDanisch avatar Jul 18 '23 14:07 SimonDanisch