# Setting the x and y axis of a heatmap plot recipe

I am trying to create a recipe to plot a custom type like this:

struct Sim{TT<:Real, F}
box::Box{TT}
ψ::Array{Complex{TT}, 2}
# other stuff
end


where

struct Box{TT<:Real}
t::Array{TT, 1}
x::Array{TT, 1}
Nₜ::Int64
Nₓ::Int64
# other stuff
end


I created a simple type recipe at first as follows:

@recipe function f(::Type{T}, sim::T; x_res=500, t_res=500) where T
# Compute sampling interval
xₛ = Int(ceil(sim.box.Nₓ/x_res))
tₛ = Int(ceil(sim.box.Nₜ/t_res))
# Downsample
t = sim.box.t[1:tₛ:end]
x = sim.box.x[1:xₛ:end]
ψ = abs.(sim.ψ[1:tₛ:end, 1:xₛ:end])
end


And running

heatmap(sim)
surface(sim) #where sim is a Sim type object


works fine! However, I would like to go further and cutstomize this plot, use x and t for the x and y axes, respectively, add labels, etc.

I can’t figure out how to go further, I’m very confused by series and plot recipes. I tried enhancing my type recipe as follows:

@recipe function f(::Type{T}, sim::T; x_res=500, t_res=500) where T
# Compute sampling interval
xₛ = Int(ceil(sim.box.Nₓ/x_res))
tₛ = Int(ceil(sim.box.Nₜ/t_res))
# Downsample
t = sim.box.t[1:tₛ:end]
x = sim.box.x[1:xₛ:end]
ψ = abs.(sim.ψ[1:tₛ:end, 1:xₛ:end])

@series begin
seriestype := :contourf
seriescolor --> :bluesreds
t, x, ψ'
end
end


But it throws an error ERROR: MethodError: no method matching size(::Nothing) which I can’t debug.

I have read all I can on the discourse and the documentation but I’m still quite confused and stuck. Any advice?

I have partially figured things out:

@recipe function f(::Type{T}, sim::T; x_res=500, t_res=500) where T
# Compute sampling interval
xₛ = Int(ceil(sim.box.Nₓ/x_res))
tₛ = Int(ceil(sim.box.Nₜ/t_res))

# Downsample
x_ax = sim.box.t[1:tₛ:end]
y_ax =  sim.box.x[1:xₛ:end]
ψ = sim.ψ[1:tₛ:end, 1:xₛ:end]

xguide --> L"t"
yguide --> L"x"
colorbar_title --> L"|\psi|"
#colorbar --> false
seriescolor --> :viridis

x := x_ax
y := y_ax

abs.(ψ')
end


This produces the expected result, with the exception that the x and y axis are not set to x_ax and y_ax. I haven’t been able to figure out this last point.

After about 7 hours in total, I finally figured it out

@recipe function f(sim::T; x_res=500, t_res=500) where T <: Union{Calc, Sim}
# Compute sampling interval
xₛ = Int(ceil(sim.box.Nₓ/x_res))
tₛ = Int(ceil(sim.box.Nₜ/t_res))

# Downsample
x_ax = sim.box.t[1:tₛ:end]
y_ax =  sim.box.x[1:xₛ:end]
ψ = sim.ψ[1:tₛ:end, 1:xₛ:end]

xguide --> L"t"
yguide --> L"x"
colorbar_title --> L"|\psi|"
seriescolor --> :viridis

@series begin
# return series data
x_ax, y_ax, abs.(ψ)'
end

return nothing
end


Plotting as:

julia> p1 = heatmap(sim)
julia> p2 = surface(sim)
julia> p3 = contour(sim)
julia> p4 = contourf(sim)
julia> plot(p1, p2, p3, p4)


Result:

Recipes are outright amazing, they just take a lot of effort to figure out the first time! Very excited to write more.

2 Likes