# How to use CairoMakie.contourf!

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:

``````"""
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:

``````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?

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/

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…

I mean at the end of `main`.

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.

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> contourf(repeat(-5:5, 11), repeat(-5:5, inner = 11), rand(11*11))
``````

works for me.

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.

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

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