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.

4 Likes