How to customize display and plot of a sparse matrix?

Hey, I have 2 questions regarding displaying SparseArrays.

(1) When using SparseArrays the code

n=15;   x=sprand(Float16,n,n,0.3);   x.nzval .=1;  display(x)

produces

15×15 SparseMatrixCSC{Float16, Int64} with 67 stored entries:
  ⋅   1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅   1.0
  ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅   1.0  1.0
 1.0   ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅   1.0   ⋅ 
 1.0   ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅   1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅ 
  ⋅   1.0   ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅   1.0
  ⋅    ⋅   1.0   ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0  1.0  1.0   ⋅ 
 1.0   ⋅   1.0  1.0   ⋅    ⋅    ⋅    ⋅   1.0  1.0   ⋅   1.0   ⋅    ⋅    ⋅ 
  ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅   1.0  1.0  1.0  1.0  1.0  1.0   ⋅ 
  ⋅   1.0  1.0  1.0   ⋅    ⋅    ⋅   1.0  1.0   ⋅    ⋅   1.0   ⋅    ⋅    ⋅ 
  ⋅   1.0   ⋅    ⋅   1.0  1.0   ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅   1.0
  ⋅    ⋅    ⋅    ⋅   1.0   ⋅   1.0   ⋅   1.0  1.0   ⋅    ⋅    ⋅    ⋅    ⋅ 
  ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅ 
 1.0   ⋅   1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅   1.0
  ⋅    ⋅    ⋅    ⋅   1.0  1.0   ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅ 
  ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅   1.0  1.0  1.0   ⋅    ⋅ 

However, changing to n=16 gives

16×16 SparseMatrixCSC{Float16, Int64} with 82 stored entries:
⎡⢹⠤⢀⠥⠉⠎⠈⣱⎤
⎢⡘⠅⠍⠂⠀⠑⠣⠠⎥
⎢⡤⠊⡦⣀⢘⠴⣠⠖⎥
⎣⣐⠹⠈⠐⡏⡅⢀⠛⎦

When working on a bigger 4K screen, this is unsatisfactory. How can I customize the display, so that I set the max number of rows/columns to either some specific numbers, or to screen/terminal height/width?

I do not wish to convert to a dense matrix, since the . are useful to immediately see the zeros. With dense matrices, the width and height of the screen/terminal is correctly detected, and truncation is done only after that width/height is crossed.

(2) How could I display sparse arrays larger than the threshold? In Mathematica, this is doable (though it is viewed as a dense matrix):


At the bottom, you can see the slider, and you can use it to inspect the whole matrix.

The value of 16 is hard coded:

function Base.print_array(io::IO, S::AbstractSparseMatrixCSCInclAdjointAndTranspose)
    if max(size(S)...) < 16
        Base.print_matrix(io, S)
    else
        _show_with_braille_patterns(io, S)
    end
end

I.e you’d need to call print_matrix directly. Something like

julia> n=18;   x=sprand(Float16,n,n,0.3);   x.nzval .=1;
julia> io = IOContext(stdout, :typeinfo => eltype(x), :compact=>true, :limit=>true)
IOContext(Base.TTY(Base.Libc.WindowsRawSocket(0x000000000000023c) open, 0 bytes waiting))

julia> Base.print_matrix(io, x)
  ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0  1.0   ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅
  ⋅    ⋅   1.0  1.0   ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅   1.0   ⋅    ⋅
  ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅   1.0  1.0  1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0
  ⋅    ⋅   1.0   ⋅   1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅
 1.0   ⋅    ⋅   1.0   ⋅    ⋅    ⋅   1.0  1.0  1.0  1.0  1.0   ⋅    ⋅    ⋅   1.0   ⋅   1.0
 1.0  1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅
  ⋅    ⋅   1.0  1.0  1.0   ⋅    ⋅    ⋅   1.0  1.0   ⋅    ⋅   1.0  1.0   ⋅    ⋅    ⋅    ⋅
  ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅   1.0   ⋅    ⋅    ⋅    ⋅   1.0   ⋅   1.0
  ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅   1.0  1.0   ⋅    ⋅   1.0
 1.0   ⋅    ⋅   1.0   ⋅    ⋅   1.0  1.0  1.0  1.0  1.0   ⋅    ⋅   1.0  1.0   ⋅    ⋅    ⋅
 1.0   ⋅   1.0   ⋅   1.0  1.0   ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅
  ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅   1.0  1.0
  ⋅    ⋅   1.0   ⋅    ⋅   1.0   ⋅    ⋅    ⋅   1.0  1.0   ⋅   1.0  1.0  1.0   ⋅   1.0  1.0
 1.0   ⋅    ⋅    ⋅    ⋅   1.0  1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅
  ⋅   1.0   ⋅   1.0  1.0  1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅
 1.0  1.0   ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅   1.0  1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅
  ⋅    ⋅    ⋅   1.0   ⋅   1.0  1.0   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅
  ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0  1.0  1.0   ⋅   1.0   ⋅    ⋅    ⋅

Would be helpful if that cutoff could beoverridden in an IOContext.

1 Like

That looks much better! And how could I also use _show_with_braille_patterns? I’m getting an error:

n=60;   x=sprand(Float16,n,n,0.3);   x.nzval .=1;   
io = IOContext(stdout, :typeinfo => eltype(x), :compact=>true, :limit=>true);   
_show_with_braille_patterns(io, x)

ERROR: UndefVarError: `_show_with_braille_patterns` not defined
Stacktrace:
 [1] top-level scope
   @ REPL[22]:1

It’s an internal function in the SparseArrays module:

julia> SparseArrays._show_with_braille_patterns(stdout, sprand(30,30,0.1))
⎡⠀⠀⠂⠈⠐⠀⠤⡠⠀⡠⠀⡀⠀⡄⠀⎤
⎢⡁⠈⠄⠀⢀⡣⠀⠀⢀⠄⠀⠀⠬⠂⠀⎥
⎢⡰⠢⠀⠀⡀⢠⠁⠀⡀⠑⠀⠀⠄⡂⢀⎥
⎢⠀⠑⠀⠈⠒⠴⠀⠉⠀⡈⠈⠀⠠⠠⠀⎥
⎢⡀⠄⠐⢀⠀⠀⠆⠠⠀⠀⠁⠄⢀⠀⠀⎥
⎢⠐⠀⠜⠀⠀⠐⠀⠀⠀⢄⠁⠀⠀⠀⡐⎥
⎢⢌⠀⠀⠠⡀⠀⠀⠀⠐⢀⠁⠀⡠⠀⠅⎥
⎣⠀⠂⠑⠈⠀⠀⠀⠀⠀⠊⠁⠀⠀⠀⠀⎦
2 Likes

Thank you, now displaying in REPL works as I wanted. But in jupyter, It does not:

Is there a way to display a specific number of rows and columns and have sliders, like in Mathematica?

That’s because the display size is taken from ENV["LINES"] AND ENV["COLUMNS"] in Jupyter (IJulia doesn’t know the size of your browser window). If you want to print everything, just use :limit=>false. Or simply do:

Base.print_matrix(stdout, x)

with no IOContext.

1 Like

Thank you for your help! @stevengj @skleinbo

1 Like