@@ -29,7 +29,7 @@ module fplotlib
2929 public :: bar, barh, hist, fill_between, fill_betweenx, stackplot
3030 public :: errorbar, axhline, axvline, axline
3131 public :: pcolormesh, pcolor, hist2d, hexbin
32- public :: matshow, eventplot, broken_barh, streamplot, table
32+ public :: spy, matshow, eventplot, broken_barh, streamplot, table
3333 public :: add_axes, secondary_xaxis, secondary_yaxis
3434 public :: add_rectangle, add_circle, add_ellipse, add_polygon
3535 public :: add_arrow, add_path
@@ -197,6 +197,11 @@ module fplotlib
197197 module procedure imshow_z, imshow_rgb
198198 end interface imshow
199199
200+ ! Sparsity pattern of a dense matrix, or of a COO index array.
201+ interface spy
202+ module procedure spy_dense, spy_coo
203+ end interface spy
204+
200205 ! One dataset or a whole block of them, a row to each.
201206 interface boxplot
202207 module procedure boxplot_one, boxplot_many
@@ -2704,6 +2709,73 @@ subroutine imshow_rgb(z, extent, origin, aspect)
27042709 end if
27052710 end subroutine imshow_rgb
27062711
2712+ ! matplotlib's spy for a dense matrix: a marker at every entry whose
2713+ ! magnitude exceeds precision (default 0, i.e. every non-zero entry).
2714+ ! Indices are Fortran's, so the first row and column sit at 1.
2715+ subroutine spy_dense (a , precision , markersize , color , marker )
2716+ real (dp), intent (in ) :: a(:, :)
2717+ real (dp), intent (in ), optional :: precision, markersize
2718+ character (len=* ), intent (in ), optional :: color, marker
2719+ real (dp) :: tol
2720+ logical , allocatable :: mask(:, :)
2721+ integer , allocatable :: ij(:, :)
2722+ integer :: i, j, k
2723+
2724+ tol = 0.0_dp
2725+ if (present (precision)) tol = abs (precision)
2726+ allocate (mask(size (a, 1 ), size (a, 2 )))
2727+ mask = abs (a) > tol
2728+ allocate (ij(2 , count (mask)))
2729+ k = 0
2730+ do j = 1 , size (a, 2 )
2731+ do i = 1 , size (a, 1 )
2732+ if (mask(i, j)) then
2733+ k = k + 1
2734+ ij(:, k) = [i, j]
2735+ end if
2736+ end do
2737+ end do
2738+ call spy_coo(ij, size (a, 1 ), size (a, 2 ), markersize, color, marker)
2739+ end subroutine spy_dense
2740+
2741+ ! Sparsity pattern from COO indices: ij(1, :) are the rows and ij(2, :)
2742+ ! the columns of the stored entries, 1-based. m and n are the matrix
2743+ ! shape; without them the largest index in each is used.
2744+ subroutine spy_coo (ij , m , n , markersize , color , marker )
2745+ integer , intent (in ) :: ij(:, :)
2746+ integer , intent (in ), optional :: m, n
2747+ real (dp), intent (in ), optional :: markersize
2748+ character (len=* ), intent (in ), optional :: color, marker
2749+ integer :: nr, nc
2750+ real (dp) :: ms
2751+ character (len= :), allocatable :: mk
2752+
2753+ if (size (ij, 1 ) /= 2 ) error stop " fplotlib: spy needs a (2, nnz) index array"
2754+ nr = 0
2755+ nc = 0
2756+ if (size (ij, 2 ) > 0 ) then
2757+ nr = maxval (ij(1 , :))
2758+ nc = maxval (ij(2 , :))
2759+ end if
2760+ if (present (m)) nr = m
2761+ if (present (n)) nc = n
2762+ ms = 10.0_dp
2763+ if (present (markersize)) ms = markersize
2764+ mk = " s"
2765+ if (present (marker)) mk = marker
2766+
2767+ call ensure_fig()
2768+ if (size (ij, 2 ) > 0 ) then
2769+ call plot(real (ij(2 , :), dp), real (ij(1 , :), dp), marker= mk, &
2770+ linestyle= " None" , color= color, markersize= ms)
2771+ end if
2772+ call xlim(0.5_dp , real (nc, dp) + 0.5_dp )
2773+ call ylim(0.5_dp , real (nr, dp) + 0.5_dp )
2774+ ax(cur_i)% y_inv = .true.
2775+ ax(cur_i)% x_top = .true.
2776+ call set_aspect(1.0_dp , " box" )
2777+ end subroutine spy_coo
2778+
27072779 ! matshow: an image of a matrix. The first row is at the top, the
27082780 ! cells are square and the column numbers run along the top, which is
27092781 ! how a matrix is written down.
0 commit comments