Plotting a heatmap or surface plot

Upon reading the tutorial in algebraofgraphics package it sounded really promising.
I wanted to plot a heatmap of an image that was recorded with a camera which I wasn’t
able to do.
Is this just not supported or do I need to transform the data in some way?
Here is my minimal example:

using AlgebraOfGraphics
ex = reshape([i * j for i in 1:10 for j in 1:20], (10, 20))
ex_draw = mapping(ex) * visual(heatmap)
draw(ex_draw, scales(Color=(; colormap=:viridis)))

which results in the following error:

ERROR: No aesthetic mapping defined yet for plot type Heatmap with scientific eltypes (AlgebraOfGraphics.Continuous(),). AlgebraOfGraphics can only use plot types if it is told which attributes and input arguments map to which aesthetics like color, markersize or linewidth for example.
Stacktrace:
  [1] aesthetic_mapping(T::Type{Heatmap}, scitypes::AlgebraOfGraphics.Continuous)
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/aesthetics.jl:51
  [2] aesthetic_mapping(plottype::Type, attributes::Dictionaries.Dictionary{Symbol, Any}, scitypes::Vector{AlgebraOfGraphics.ScientificType})
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/aesthetics.jl:32
  [3] aesthetic_mapping
    @ ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/aesthetics.jl:29 [inlined]
  [4] compute_scale_properties(processedlayers::Vector{ProcessedLayer}, scales::AlgebraOfGraphics.Scales)
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/algebra/layers.jl:198
  [5] compute_axes_grid(d::Layer, scales::AlgebraOfGraphics.Scales; axis::Dictionaries.Dictionary{Symbol, Any})
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/algebra/layers.jl:302
  [6] compute_axes_grid
    @ ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/algebra/layers.jl:298 [inlined]
  [7] _draw(d::Layer, scales::AlgebraOfGraphics.Scales; axis::Dictionaries.Dictionary{…}, figure::Dictionaries.Dictionary{…}, facet::Dictionaries.Dictionary{…}, legend::Dictionaries.Dictionary{…}, colorbar::Dictionaries.Dictionary{…})
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/draw.jl:169
  [8] _draw
    @ ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/draw.jl:166 [inlined]
  [9] draw(d::Layer, scales::AlgebraOfGraphics.Scales; axis::@NamedTuple{}, figure::@NamedTuple{}, facet::@NamedTuple{}, legend::@NamedTuple{}, colorbar::@NamedTuple{}, palette::Nothing)
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/draw.jl:97
 [10] draw(d::Layer, scales::AlgebraOfGraphics.Scales)
    @ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/KKbhj/src/draw.jl:87
 [11] top-level scope
    @ REPL[83]:1
Some type information was truncated. Use `show(err)` to see complete types.

So I guess I just don’t understand the aesthetic thing yet properly. I also figured I am using
“0.10.7” as I assume that the other packages demand I use that version so I can not use
show_aesthetics.

You can see an example how 2d matrices can be used with AoG here Intro to AoG - V - Alternative input data formats | AlgebraOfGraphics

Mind the note that this part of the API is not really considered stable, it’s a side effect that this is possible but in general AoG is intended to work with same-length array arguments.

There is a default way to plot heatmaps which is fully supported but where you have to supply x, y and z as vectors. Admittedly, giving 2D data in this long format can sometimes be a bit cumbersome if you already have the interval, interval, matrix format instead.

In your case:

is = 1:10
js = 1:20
x = [i for i in is for j in js]
y = [j for i in is for j in js]
z = x .* y

mapping(x, y, z) * visual(Heatmap) |> draw

1 Like

Alright that works thanks a lot. Maybe I can also transform my pixel matrix into tabular
data I am just not sure how to do it in julia. I remember in python there was the meshgrid command to do it but also not sure if it is exactly the right thing to do here.

Edit:
Eventually also wrote a function for the translation if anyone is interested

"""
Change the matrix to a table format suitable for e.g. DataFrames
"""
function matrix_to_table(mat::Array{Float64, 2})::Tuple{Array{Float64, 1}}
    flat_mat = vcat(mat...)
    im_sh = size(ex_im)
    is = 1:im_sh[1]
    js = 1:im_sh[2]
    x = [i for i in is for j in js]
    y = [j for i in is for j in js]
    x, y, flat_mat
end
2 Likes