MakieOrg / Makie.jl

Interactive data visualizations and plotting in Julia
https://docs.makie.org/stable
MIT License
2.41k stars 312 forks source link

heatmap slightly misaligned with respect to axis coordinates #4053

Open dylanfesta opened 3 months ago

dylanfesta commented 3 months ago

I was plotting some analytic curves on top of a heatmap using CairoMackie, and I found out that possibly all heatmaps are slightly misaligned with respect to the axis coordinates. This can be fixed by shifting the heatmap of a factor that I had to find by trial and error (and that might vary!). In the example below I generate heatmaps of random numbers, and then draw edges as vertical and horizontal lines. The contours are expected to match.

using Makie,CairoMakie
using StatsBase: midpoints

"""
  get_edges(v::AbstractVector{R}) where R<:Real

  Given a vector of values corresponding to center coordinates of size N,
  returns a vector of edges N+1.
"""
function get_edges(v::AbstractVector{R}) where R<:Real
  ret = midpoints(v)
  first_edge = v[1] - (ret[1]-v[1])
  last_edge = v[end] + (v[end]-ret[end])
  return vcat(first_edge,ret,last_edge)
end

N=50
fig = Figure(size=(700,300))
xedges = get_edges(1:N) 
yedges = get_edges(1:N)
ax1=Axis(fig[1,1];limits=(extrema(xedges),extrema(yedges)))

heatmap!(ax1,xedges,yedges, randn(N,N))
vlines!(ax1,xedges,linewidth=0.1,color=:white)
hlines!(ax1,yedges,linewidth=0.1,color=:white)
ax2=Axis(fig[1,2]; limits=(extrema(xedges),extrema(yedges)))
xedges_fix = xedges .+ N/500 # this fixes the problem by shifting the heatmap
yedges_fix = yedges .+ N/500 
heatmap!(ax2,xedges_fix,yedges_fix, randn(N,N))
vlines!(ax2,xedges,linewidth=0.1,color=:white)
hlines!(ax2,yedges,linewidth=0.1,color=:white)

colgap!(fig.layout,10)

save("/tmp/tmp.pdf",fig; pt_per_unit=1)

display(fig)

This is the plot I see.

image

When I zoom in, the left plot shows a clear misalignment between the heatmap edges and the lines in axis coordinates. In the right plot the misalignment is fixed by adding the N/500 correction.

image

I am using the latest version of Makie and the same problem appears consistently on Ubuntu 20.04 and Fedora 40 machines.

jkrumbiegel commented 3 months ago

Hm you're right I also see that in CairoMakie, but not in GLMakie. So that suggests there is no problem with the underlying heatmap data, but that the tile overlapping that CairoMakie does (to remove antialiasing fringes between heatmap cells) is buggy and we actually see the overlaps, which shouldn't happen. That's why the factor you find is variable, because it's in screen space and not data space.

asinghvi17 commented 3 months ago

I think we did this deliberately at some stage to prevent aliasing, but maybe the order in which the rectangles are plotted is incorrect, resulting in bad overdraw behavior.

You will probably find that the offset is exactly 1 pixel...

dylanfesta commented 3 months ago

Until the bug is fixed, is there a way to know the exact offset value? Can I extract the length of the axis in pixels? I checked the documentation but I could not find an answer.