# How to use CairoMakie.contourf!

**URL:** <https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781>\
**Category:** General Usage\
**Tags:** question, plotting, type, cairomakie\
**Created:** [May 3, 2024, 9:13am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781 "2024-05-03T09:13:44Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![SeSodesa](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@SeSodesa](https://discourse.julialang.org/u/SeSodesa)\
**Post date:** [May 3, 2024, 9:13am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/1 "2024-05-03T09:13:44Z")

</div>

I cannot for the life of me figure out what the heck I need to pass to `CairoMakie.contourf!`. What I have tried thus far produces an error:

```julia
"""
Plots and electric field of two point charges with a countour plot
on the same axes.
"""

import CairoMakie as CM
import Base.Iterators as It

"""
A type representing a point charge.
"""
struct PointCharge
	charge::Float64
	position::Vector{Float64}
end # struct

"""
Computes a 2-norm for a set of vectors given as columns of a
matrix.
"""
function vec2Norm(vecs::Matrix{<:AbstractFloat})
	sqrt.( sum( vecs .^ 2, dims=1 ) )
end

"""
Computes an electric field for a point charge at given positions,
encoded into columns of a matrix.
"""
function EFn(pc::PointCharge, positions, ϵ0=1.0 )
	differences = positions .- pc.position
	distances = vec2Norm(differences)
	unitDifferences = differences ./ distances
	pc.charge ./ 4 ./ π ./ ϵ0 ./ distances .^ 2 .* unitDifferences
end # function

"""
Computes a potential field field for a point charge at given
positions, encoded into columns of a matrix.
"""
function uFn(pc::PointCharge,positions, ϵ0=1.0)
	differences = positions .- pc.position
	distances = vec2Norm(differences)
	pc.charge ./ 4 ./ π ./ ϵ0 ./ distances
end # function

"""
The main routine of this module.
"""
function main()

	println("Running main routine…")

	step = 0.8

	@show xx = -5 : step : 5

	@show yy = xx

	grid = collect(It.product(xx,yy))[:]

	gridx = first.(grid)

	gridy = last.(grid)

	@show size(collect(gridx'))

	@show size(collect(gridy'))

	gridMat = [gridx' ; gridy']

	@show size(gridMat)

	@show charge1 = PointCharge(-1.0,[-1,-1])

	@show charge2 = PointCharge(1.0,[1,1])

	E1 = EFn(charge1,gridMat)

	E2 = EFn(charge2,gridMat)

	u1 = uFn(charge1,gridMat)

	u2 = uFn(charge2,gridMat)

	u = u1 + u2

	@show size(u)

	@show typeof(u)

	E = E1 + E2

	@show size(E1)

	@show size(E2)

	fig, ax = CM.arrows(gridx,gridy,E[1,:],E[2,:])

	CM.scatter!(ax,charge1.position[1],charge1.position[2],markersize=20,color=:blue)

	CM.scatter!(ax,charge2.position[1],charge2.position[2],markersize=20,color=:red)

	CM.contourf!(ax,gridx,gridy,u)

	CM.save(abspath(joinpath(@ __DIR__ ,"E.pdf")),fig)

end # function

# Run main function only if this file is invoked as a script.

if abspath(PROGRAM_FILE) == @ __FILE__
	main()
end

```

The error:

```julia
ERROR: LoadError: Length of x (169) must be equal to number of columns in z (1)
Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:35
  [2] isobands(xs::Vector{Float64}, ys::Vector{Float64}, zs::Matrix{Float64}, low_values::Vector{Float64}, high_values::Vector{Float64})
    @ Isoband ~/.julia/packages/Isoband/qUEGP/src/Isoband.jl:56
  [3] isobands(xs::Vector{Float32}, ys::Vector{Float32}, zs::LinearAlgebra.Adjoint{Float32, Matrix{Float32}}, lows::Vector{Float32}, highs::Vector{Float32})
    @ Isoband ~/.julia/packages/Isoband/qUEGP/src/Isoband.jl:32
  [4] (::Makie.var"#calculate_polys#563"{Observables.Observable{Vector{Float64}}, Observables.Observable{Vector{GeometryBasics.Polygon{2, Float32, GeometryBasics.Point{2, Float32}, GeometryBasics.LineString{2, Float32, GeometryBasics.Point{2, Float32}, Base.ReinterpretArray{GeometryBasics.Line{2, Float32}, 1, Tuple{GeometryBasics.Point{2, Float32}, GeometryBasics.Point{2, Float32}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point{2, Float32}, GeometryBasics.Point{2, Float32}}, 2, 1, Vector{GeometryBasics.Point{2, Float32}}}, false}}, Vector{GeometryBasics.LineString{2, Float32, GeometryBasics.Point{2, Float32}, Base.ReinterpretArray{GeometryBasics.Line{2, Float32}, 1, Tuple{GeometryBasics.Point{2, Float32}, GeometryBasics.Point{2, Float32}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point{2, Float32}, GeometryBasics.Point{2, Float32}}, 2, 1, Vector{GeometryBasics.Point{2, Float32}}}, false}}}}}}})(xs::Vector{Float32}, ys::Vector{Float32}, zs::Matrix{Float32}, levels::Vector{Float32}, is_extended_low::Bool, is_extended_high::Bool)
    @ Makie ~/.julia/packages/Makie/ND0gA/src/basic_recipes/contourf.jl:110
  [5] plot!(c::MakieCore.Plot{Makie.contourf, Tuple{Vector{Float32}, Vector{Float32}, Matrix{Float32}}})
    @ Makie ~/.julia/packages/Makie/ND0gA/src/basic_recipes/contourf.jl:132
  [6] connect_plot!(parent::Makie.Scene, plot::MakieCore.Plot{Makie.contourf, Tuple{Vector{Float32}, Vector{Float32}, Matrix{Float32}}})
    @ Makie ~/.julia/packages/Makie/ND0gA/src/interfaces.jl:260
  [7] plot!
    @ ~/.julia/packages/Makie/ND0gA/src/interfaces.jl:265 [inlined]
  [8] plot!(ax::Makie.Axis, plot::MakieCore.Plot{Makie.contourf, Tuple{Vector{Float32}, Vector{Float32}, Matrix{Float32}}})
    @ Makie ~/.julia/packages/Makie/ND0gA/src/figureplotting.jl:316
  [9] _create_plot!(::Function, ::Dict{Symbol, Any}, ::Makie.Axis, ::Vector{Float64}, ::Vararg{Any})
    @ Makie ~/.julia/packages/Makie/ND0gA/src/figureplotting.jl:284
 [10] contourf!(::Makie.Axis, ::Vararg{Any}; kw::@Kwargs{})
    @ Makie ~/.julia/packages/MakieCore/UAwps/src/recipes.jl:176
 [11] main()
    @ Main ~/tau-typst-presentation/images/dipoles.jl:103
 [12] top-level scope
    @ ~/tau-typst-presentation/images/dipoles.jl:112
in expression starting at /Users/soderhos/tau-typst-presentation/images/dipoles.jl:111

```

When I try to transpose `gridx`, I get an error about an unkown recipe for `contourf`. What am I doing wrong?

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [May 3, 2024, 9:17am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/2 "2024-05-03T09:17:16Z")

</div>

Your code is a bit too long for me to read through, but have you looked at the docs which have quite a few examples of how to use the function?

[https://docs.makie.org/stable/reference/plots/contourf/](https://docs.makie.org/stable/reference/plots/contourf/)

---

<div class="post-metadata">

**Author:** ![SeSodesa](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@SeSodesa](https://discourse.julialang.org/u/SeSodesa)\
**Post date:** [May 3, 2024, 9:19am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/3 "2024-05-03T09:19:56Z")

</div>

The documentation is useless, because it does not tell me anything about the required types and/or array shapes. At the end of the code, I am just trying to pass in a vector of x- ,y-coordinates, along with a vector/matrix of potential values corresponding to the x–y pairs, which is what the documentation tells me to do. Something as simple as this just fails…

---

<div class="post-metadata">

**Author:** ![SeSodesa](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@SeSodesa](https://discourse.julialang.org/u/SeSodesa)\
**Post date:** [May 3, 2024, 9:22am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/4 "2024-05-03T09:22:10Z")

</div>

I mean at the end of `main`.

---

<div class="post-metadata">

**Author:** ![SeSodesa](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@SeSodesa](https://discourse.julialang.org/u/SeSodesa)\
**Post date:** [May 3, 2024, 9:24am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/5 "2024-05-03T09:24:36Z")

</div>

If I append the data into a single matrix, I get not errors, but for some reason the image now has values for the potentials for values between 1:169, which is the size of a data vector. The values should be plotted into a grid between -5 and 5 in the x–y plane.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [May 3, 2024, 9:52am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/6 "2024-05-03T09:52:16Z")

</div>

The documentation shows the usage with a matrix, where the x/y coordinates are implicitly given by the positions of values in the matrix.

Alternatively you can specify the x and y coordinates in separate vectors, together with z values as another vector:

```julia
julia> contourf(repeat(-5:5, 11), repeat(-5:5, inner = 11), rand(11*11))

```

works for me.

---

<div class="post-metadata">

**Author:** ![SeSodesa](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@SeSodesa](https://discourse.julialang.org/u/SeSodesa)\
**Post date:** [May 3, 2024, 9:58am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/7 "2024-05-03T09:58:49Z")

</div>

Alright, so the issue is probably that either you need to give it a single matrix, or 3 separate `Vector`s. A combination of `Matrix`es and `Vector`s does not work. I just need to convert the `u` matrix into a vector somehow.

---

<div class="post-metadata">

**Author:** ![SeSodesa](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@SeSodesa](https://discourse.julialang.org/u/SeSodesa)\
**Post date:** [May 3, 2024, 10:01am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/8 "2024-05-03T10:01:39Z")

</div>

Which is turning out to be a rather difficult task. `Vector(matrix)` does not work.

---

<div class="post-metadata">

**Author:** ![SeSodesa](https://avatars.discourse-cdn.com/v4/letter/s/dc4da7/32.png) [@SeSodesa](https://discourse.julialang.org/u/SeSodesa)\
**Post date:** [May 3, 2024, 10:04am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/9 "2024-05-03T10:04:50Z")

</div>

But `vec(matrix)` does. Now the code works.

---

<div class="post-metadata">

**Author:** ![xzk066](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xzk066/32/214288_2.png) [@xzk066](https://discourse.julialang.org/u/xzk066)\
**Post date:** [December 19, 2024, 12:03pm UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/10 "2024-12-19T12:03:18Z")

</div>

I would like to ask if contourf can only draw rectangular domains. Can it input the x, y coordinate matrix of discrete points in any region and the matrix of function value z like the surface function? However, contourf seems to only be able to input x, y vectors to construct a rectangular domain. Matlab supports contourf drawing of discrete points in any region.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [December 19, 2024, 4:24pm UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/11 "2024-12-19T16:24:33Z")

</div>

Not yet but according to some people in this issue it seems relatively straightforward to add [Feature request: contour that can handle curvilinear grids · Issue #796 · MakieOrg/Makie.jl · GitHub](https://github.com/MakieOrg/Makie.jl/issues/796)

---

<div class="post-metadata">

**Author:** ![xzk066](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xzk066/32/214288_2.png) [@xzk066](https://discourse.julialang.org/u/xzk066)\
**Post date:** [December 24, 2024, 1:54am UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/12 "2024-12-24T01:54:08Z")

</div>

Thank you very much, I will try later. 😁

---

<div class="post-metadata">

**Author:** ![asinghvi17](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asinghvi17/32/8272_2.png) [@asinghvi17](https://discourse.julialang.org/u/asinghvi17)\
**Post date:** [February 24, 2025, 8:42pm UTC](https://discourse.julialang.org/t/how-to-use-cairomakie-contourf/113781/13 "2025-02-24T20:42:57Z")

</div>

FYI, [this PR to Makie](https://github.com/MakieOrg/Makie.jl/pull/4744/) enables contourf to work on matrix-matrix-matrix input. It’s complete but not yet merged (should get merged soonish) so feel free to give it a try!
