Filled contour plots in Plots.jl without contour lines and smooth interpolation (GR backend)

Actually, these are two questions towards Plots.jl with the GR backend in one post (hope that’s ok, I think they are related):

  1. Is it possible to create a filled contour plot (using plot(linetype=:contourf, ...) without actually showing the contour lines?

  2. And is it possible to obtain smoothly interpolated colors instead of discrete levels, without resorting to setting levels to a ridiculously high value?

EDIT: I would like to generate an image as shown in https://github.com/JuliaPlots/Plots.jl/issues/1218#issuecomment-341054026, where it was reported as a bug (or as I would call it: a feature)

Isn’t this the functionality of a heatmap?

using GR
z = peaks(200)
contourf(z)
heatmap(z)

3 Likes

This is very embarrassing… but of course you are right :man_facepalming: Thanks a lot for the fast reply.

However, please allow me a follow-up question:

With contourf! it is possible to add multiple contour plots to the same figure without a problem:


The relevant line: contourf!(vertices_x, vertices_y, (x,y) -> i/100 .+ x.+y)
Essentially, I am trying to plot a 2D solution from a numerical simulation cell-by-cell, with values interpolated within each cell, by iterating over all cells and calling contourf with the respective cell vertex coordinates vertices_x, vertices_y.

However, the same plot with heatmap! yields something weird:


The relevant line: heatmap!(vertices_x, vertices_y, (x,y) -> i/100 .+ x.+y)
Not only are the coordinate locations mixed up, but also there does not seem to be any interpolation between values.

Is it possible to tell from what I showed here, what I am doing wrong?

Could you please provide the complete example or an MWE ?

Of course. I am not sure if I was able to boil it down to the true MWE, but this is already quite short:

import GR
using Plots

gr()
GR.inline("png")

# Create cell coordinates
coordinates = transpose(
                        [-1 -1;
                          1 -1;
                         -1  1;
                          1  1]
                       )

# Create plot
plot(size=(2000,2000), thickness_scaling=3, aspectratio=:equal, legend=:none)
for i in axes(coordinates, 2)
  h = 2
  limits_x = [coordinates[1, i] - 1/2 * h, coordinates[1, i] + 1/2 * h]
  limits_y = [coordinates[2, i] - 1/2 * h, coordinates[2, i] + 1/2 * h]
  contourf!(limits_x, limits_y, (x,y) -> i .+ x .+ y)
end

savefig("mwe.png")

This yields the following image:

If I exchange contourf! for heatmap!, the following figure is generated instead:

If there’s anything else I could provide, please let me know!

@jheinen Any thoughts on this (sorry for the direct ping)?

IMHO a heatmap should not interpolate by default

OK, but is it possible to enable interpolation in heatmap? And if not, this brings me back to my original questions: How can I use a contour plot without showing the lines, and how can I get smoothly interpolated colors instead of discrete levels?

I have an idea how to solve your problem in plain GR, but this needs some modifications in the GR convenience layer. Please give me some time to check this. In case of “success” I can integrate that solution in Plots, too.

1 Like

This would be highly appreciated, thanks. At the moment we are looking for a Julia-only plot solution for 2D numerical results, but thus far I am not 100% convinced that it is feasible for us.

OTOH, could you please confirm that turning off contour lines (either in Plots or plain GR) is currently not supported? In that case I can stop looking :wink:

Can’t you do linecolor = :transparent?

No:

┌ Warning: GR: filled contour only supported with black contour lines
└ @ Plots ~/.julia/packages/Plots/12uaJ/src/backends/gr.jl:1641

Does it help to make the linecolor width zero, or very small? Or to set the alpha channel level to 0?

Good idea, but unfortunately linewidth=0.0, linewidth=0.1, or linealpha=0 do not change the resulting image.

PGFPlotsX can interpolate, see this example with an intentionally crude grid to highlight interpolation:

using PGFPlotsX
x = range(-2; stop = 2, length = 10)
y = range(-0.5; stop = 3, length = 10)
f(x, y) = (1 - x)^2 + 100*(y - x^2)^2
@pgf Axis({ view = (0, 90), colorbar, "colormap/jet" },
          Plot3({ surf, shader = "interp" },
                Coordinates(x, y, @. √(f(x, y')))))

There is also a bilinear shader which looks nicer (but, again, the grid is very crude):

push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\usepgfplotslibrary{patchplots}")
@pgf Axis({ view = (0, 90), colorbar, "colormap/jet" },
          Plot3({ surf, shader = "interp" ,"patch type" = "bilinear" },
                Coordinates(x, y, @. √(f(x, y')))))

You can of course overlay a contour on this, or use a different color sheme — see the manual.

Thank you for the suggestion. At the moment we try to stick to GR as a backend, as PGFPlotsX we would like to avoid the additional dependency of requiring a LaTeX installation present. We might come back to your proposed solution if we cannot manage to do it otherwise though.

Sorry to bring this thread back to life, but @sloede did you manage to find a way to get rid of the lines when using contourf?

No, unfortunately not. In the end, we decided to forego a Julia-only solution. Instead, we use WriteVTK.jl to write out vtk/vti/vtu files (depending on use case) and handle visualization and data analysis with ParaView.

1 Like

Ah okay, thanks. Anyone else know how this can be done? i.e remove contour lines when using contourf

1 Like

Upvote. Any update on turning off the contour lines for contourf? It would make this plot sooooo much nicer. :wink:

Edit: heatmap with interpolation would be even better since I prefer the way it doesn’t cutout values outside clims.

2 Likes