Makie.jl: Plotting contour with fillrange=true above lines

Hello,

I am trying to learn how to use Makie and found myself in a situation where I would like to plot some lines and a contour plot with filllrange=true (or also a heatmap) on the same scene while having the contour plot appear in front of the lines.
The contour plot does not fully overlap the lines and I would then like to have the contour “hide” the lines below it in regions where they overlap.

Here is a simplified example of what I am trying to do.

using Makie, AbstractPlotting

np = 500
nc = 200
f(x) = 2*x+1
x = LinRange(-1,1,f(np))
y = rand(f(np))*2 .- 1
scene = lines(x,y)
x_c = LinRange(-nc/np,nc/np,f(nc))
y_c = LinRange(-nc/np,nc/np,f(nc))
c_mat = @. x_c^2 + y_c'^2
contour!(scene,x_c,y_c,c_mat,fillrange=true)

I have been trying playing with transparency or with the plot order but I can’t find anyway to avoid the lines coming on top of the contour plot.
Is the thing I am trying to achieve even possible with Makie at the moment?

Like so?
image

using AbstractPlotting

np = 500
nc = 200
f(x) = 2*x+1
x = LinRange(-1,1,f(np))
y = rand(f(np))*2 .- 1
scene = Scene()
x_c = LinRange(-nc/np,nc/np,f(nc))
y_c = LinRange(-nc/np,nc/np,f(nc))
c_mat = @. x_c^2 + y_c'^2
heatmap!(scene,x_c,y_c,c_mat)
lines!(scene,x, y)
contour!(scene,x_c,y_c,c_mat, linewidth=2, color=:white)

Hi @sdanisch

No, what I would like to obtain is for the black line to be completely invisible if passing below the area where the contour plot is defined.

Something like this where instead of the white square the contour would appear

With poly! instead of heatmap! this happens automatically respecting the plot order but with heatmap and contour I can’t seem to make it work

I see.
Seems to be a z-fighting issue. Try:

using AbstractPlotting, GLMakie

np = 500
nc = 200
f(x) = 2*x+1
x = LinRange(-1,1,f(np))
y = rand(f(np))*2 .- 1
scene = Scene()
x_c = LinRange(-nc/np,nc/np,f(nc))
y_c = LinRange(-nc/np,nc/np,f(nc))
c_mat = @. x_c^2 + y_c'^2
lineplot = lines!(scene, x, y)[end]
translate!(lineplot, 0, 0, -1)
heatmap!(scene,x_c,y_c,c_mat)
contour!(scene,x_c,y_c,c_mat, linewidth=2, color=:white) 

Thanks a lot!
That solved it.
And also thanks for the amazing work in Makie, it is truly an outstanding plotting package :).

Now I just have a last curiosity regarding contour plots.
Is there a way also label the contour lines based on the levels?
Something like here where you can see the 16 on the upper left contour:
Annotation 2020-05-20 194358

The above picture was of course generated with PlotlyJS but I am trying to migrate to Makie.

Not as easily… I think @jules did some work on this?

I just did a super dirty hack for a simple version:

using AbstractPlotting, GLMakie

np = 500
nc = 200
f(x) = 2*x+1
x = LinRange(-1,1,f(np))
y = rand(f(np))*2 .- 1
scene = Scene()
x_c = LinRange(-nc/np,nc/np,f(nc))
y_c = LinRange(-nc/np,nc/np,f(nc))
c_mat = @. x_c^2 + y_c'^2
lineplot = lines!(scene, x, y)[end]
translate!(lineplot, 0, 0, -1)
heatmap!(scene,x_c,y_c,c_mat)
cplot = contour!(scene,x_c,y_c,c_mat, linewidth=2, color=:white)[end]

beginnings = Point2f0[]; colors = RGBAf0[]
# First plot in contour is the line plot, first arguments are the points of the contour
segments = cplot.plots[1][1][]
for (i, p) in enumerate(segments)
    # the segments are separated by NaN, which signals that a new contour starts
    if isnan(p)
        push!(beginnings, segments[i-1])
    end
end
sc = scatter!(scene, beginnings, markersize=0.06, color=(:white, 0.00001))[end]
translate!(sc, 0, 0, 1)
# Reshuffle the plot order, so that the scatter plot gets drawn before the line plot
delete!(scene, sc)
delete!(scene, cplot)
push!(scene, sc)
push!(scene, cplot)
anno = annotations!(scene, [(string(i), p) for (i, p) in enumerate(beginnings)], 
                    textsize=0.05, align=(:center, :center))[end]
                    
# move, so that text is in front
translate!(anno, 0, 0, 2)

scene

Would need some polish to work nicely :wink: (e.g. simply split the contour lines to make a gap, and finding better positions for the numbers)

1 Like

Nice!
I think I can work from this and also learn something more about Makie.
One last question, are the actual contour levels stored somehow in the plot data?
Right now the numbers on the contour represent the level index while I wanted to put there the actual iso-value for which the contour is plotted.