MakieOrg / Makie.jl

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

`spy` does not reproduce the matrix structure of a sparse matrix #3743

Open gvdeynde opened 7 months ago

gvdeynde commented 7 months ago

When plotting the structure of a sparse matrix using spy, the "matrix structure" is not preserved...

Code snippet:

using SparseArrays, CairoMakie, LinearAlgebra
n=100; A = sprand(n,n,1/n) + sparse(Diagonal(rand(n))); A[:,1] .= 2; A[1,:] .= -2

gives

image

f, ax, plt = CairoMakie.spy(A, marker=:circle, markersize=4)
Colorbar(f[1,2], limits=(-2,1))
f

gives

image

The spy function should treat the first index of the SparseArray as the yaxis (and reverse that yaxis) and the second index as the xaxis.

asinghvi17 commented 7 months ago

This is a more general Makie thing. The sparse structure is preserved but the matrix is simply flipped in the y direction.

The representation in the plot is consistent with the mathematical representation of two-dimensional Cartesian space (x increases towards the left, y increases towards the top) and more generally every other plot, whereas the REPL visualization flips the y-axis.

It's still a topic of debate as to whether we should change this or not, but for now that's the default behaviour.

gvdeynde commented 7 months ago

Understood. But that it is not what people expect when they call spy on a sparse matrix (coming from Matlab, matplotlib, ...). Plots.jl does it "right".

I have no idea what the use case would/could be for what is now the default behaviour in Makie.

And if I'm not mistaken, it's not only the yaxis that is flipped in Makie's spy. In the example, all elements of the first row of the matrix are set to -2. In the Makie plot, the first column is -2. So it seems Makie is doing some other unexpected transformation.

jkrumbiegel commented 7 months ago

It's not just the y axis that's flipped, it's x and y that are permuted from your expectation. In Makie, every matrix is by default interpreted as first dim x, second dim y. That's just a simpler more straightforward rule that meshes better with the 3d case where we get x, y z and not yflipped, x, z.

The problem is that in a good number of cases, you do want your matrix to be oriented the way you would write it, in rows and columns going from top left to bottom right. Recipes currently cannot set axis parameters so we cannot set the y axis flip. And the permutation of x and y would make even less sense without that.

I think we need to wait until recipes have some way of setting axis parameters, and then we could do a keyword orientation = :matrix or something which would set axis yflip and permute the dimensions. Until then you do have to do it manually.