I have the following single figure with multiple heatmaps:
The limits of the colorbar are manually set to the minimum and maximum of the values plotted. This is bound to give an incorrect mapping if one of the heatmaps only “uses” e.g. half of the range of the limits, as the heatmap uses the full color range on whatever is plotted.
How do I make a colorbar that represents all heatmaps?
You have to set
colorrange = (min, max) for each heatmap
Precision: limits have to be set for both the heatmaps and the colorbar.
Here is a more detailed example:
# define the maps
n_rows = 2
n_cols = 5
maps = [rand(5,5) .* (i_row * 10 + i_col) for i_row in 1:n_rows, i_col in 1:n_cols]
# get global extrema
extremas = map(extrema, maps)
global_min = minimum(t->first(t), extremas)
global_max = maximum(t->last(t), extremas)
# these limits have to be shared by the maps and the colorbar
clims = (global_min, global_max)
fig = Figure()
for i_row in 1:n_rows, i_col in 1:n_cols
ax = Axis(fig[i_row, i_col])
heatmap!(ax, maps[i_row, i_col]; colorrange=clims)
cb = Colorbar(fig[:, n_cols + 1]; limits=clims)
It would be nice to just pass an iterable of heatmaps to colorbar to automate this process ?
That’s actually a good idea, equalizing the color ranges when passing a couple plot objects to the colorbar.
Huge +1 on that.
Would it be possible to pass a figure, and have the colorbar fit all plot objects on all axes of the figure? This would alleviate the need to define variables for each plot-objects.
pass a figure, and have the colorbar fit all plot objects on all axes of the figure
That would be nice if all plots are to share the same colorbar indeed.
But maybe it could be possible to do the reverse:
and pass a
colorbar=cb argument to all heatmaps that should share this colorbar ?
That would suppress the need to define a reference for each heatmap,
while allowing to have separate groups of heatmaps with their own colorbar if needed.
Slightly related, this issue discusses adding
linkcolors!, analogous to
linkaxes!, to link color ranges across plots. (Mentioning it here because I imagine something like that would be needed to implement the “shared colorbar for many plots” functionality.)
It turns out that you can pass any of the heatmaps (since they have the same colorranges and colormaps, if you have done anything right) to the
Colorbar command. I found this simpler than adding a kwarg to the call to
Colorbar with explicit limits.
This is now also documented, if Colorbar example for heatmap by KronosTheLate · Pull Request #1736 · JuliaPlots/Makie.jl (github.com) gets merged.
A pretty cool convenience would be a
sync_colorranges! function, which would take a variable number of
plotobject's, check that they have colors (so heatmap and contour, right?), and set the colorrange of them all to the extrema of all z-values in all the plots.
sync_colorranges! could perhaps also take a figure, and automatically call itself on the axes within the figure.
sync_colorranges! would make explicit limit-setting (no fun) redundant, and replace it with a simple-to-understand and easy-to-remember function.
Finally (and possibly too far down the rabbit-hole of convenience), one could implement a method
Colorbar(fig::Figure, kwargs...) that would call
sync_colorranges! on the figure, and then add a colorbar. I am thinking that kwargs could specify vertical (default) or horizontal, and location (:right (default), :left, :above, :below).
I took a stab at it. Something like
Set the colorrange of all `plotobjects` to the same value,
namely the extrema of all z-values of all plotobjects in `plotobjects`.
for plt in plotobjects
haskey(plt.attributes.attributes, :colorrange) || error("This function syncronizes the color range of the given plotobjects. One of the plotobjects passed has no color range.")
possible_extremas = [extrema(to_value(plt)) for plt in plotobjects]
global_extremas = extrema(vcat(collect.(possible_extremas)...))
for plt in plotobjects
plt.attributes.colorrange = global_extremas
This should be the right approach (checking the existence of
colorrange, and changing it) if Inconsitencies in colorrange · Issue #1737 · JuliaPlots/Makie.jl · GitHub gets a satisfying solution.