Contour plots on non-rectangular domain

Is there any way to use the contour and contourf commands from the Plots.jl package to produce figures with non-rectangular domains? Or what would be the most flexible/complete alternative?

Suppose I have the following plot in polar coordinates:

using Plots
r = 1:0.1:2
θ = 0:0.05π:0.5π
f(r,θ) = r^2+sin(θ)
contourf(r, θ, f)

How would I plot this as a quarter annulus in the Cartesian frame? I am not looking for anything specific for polar coordinates though, that’s just an example.

1 Like

You can use plot(..., proj=:polar) to make a polar plot. See: http://docs.juliaplots.org/latest/generated/plotly/#plotly-ref27

Just to note, you data is not currently a quarter annulus. In a polar plot, it seems ranges for theta and r iterate together, rather than independently (basing that on just the example) so you wont get the contour you’re expecting.
You could always convert (r, θ), and f to (x, y) domain to use contourf as expected.

This is supported on the pyplot backend.

pyplot()
r = 1:0.1:2
θ = 0:0.05π:0.5π
f(θ,r) = r^2+sin(θ)
contourf(θ, r, f, proj=:polar)

(note that the order of the arguments (θ and r) is the other way round from your code)

Thank you both for your quick replies.
Maybe my example of polar coordinates was a bit unfortunate. As I am indicating in my original post, that is really just an example. I am looking for something that can handle arbitrary transformations.

Does the proj key word argument only take predefined symbols, or can I also pass transformation functions? Or is there some sort of “projection recipe” that I can write?

This is not directly supported by Plots, and I’m not aware of any existing recipes for doing that.
If your non-rectangular domain can be represented as a transformation of a rectangular domain (as in the polar example), maybe you can compute the contours in the rectangular domain (using Contour.jl), and then transform and plot them.

As it happens, my use case does indeed exclusively involve mapped rectangular domains. I can use the Contour.jl package that you’re suggesting to make the basic contour plots work. However, getting filled contour plots to work (which is really the interesting case) still seems like a significant implementation effort. I’d be happy to hear of any packages that can help with that.

In case anyone is interested, here is a working example that can handle various transformations (mostly copied from the Contour.jl tutorial):

using Plots
using Contour
gr()

transformation(r,θ) = (@.r*cos(θ) ,@.r*sin(θ))

r = 1:0.01:2
θ = 0:0.01π:0.5π
f(r,θ) = cos((r-0.5)*3)+sin(θ)
p1 = Plots.contour(r,θ,f,nlev=20)

p2 = plot()
z = [f(ri,θi) for ri in r, θi in θ]
conts = contours(r,θ,z,20)
for cl in levels(conts)
    for line in lines(cl)
        xline,yline = transformation(coordinates(line)...)
        plot!(xline,yline, label="")
    end
end
plot(p1,p2,size=(500,250))

which produces:

image

4 Likes

Good afternoon all, sorry to revive an old thread.
However I too am looking to plot a contour in the quarter annulus only, i.e. I do not wish the frame of the plot to include the range π/2 < θ < 2π. Currently the command

contour(θ, r, f, proj=:polar)

Produces a full cirlce regardless of the theta domain specified.

Although converting to Cartesians would be a potential work around, it would be nice to have the ranges supported intrinsically.

Does this anyone know how to do this ?
I have used the Contour.Jl package but colouring of the contours seems to be strange.
Many thanks