def discrete_laplacian(grid: RectangularGrid, mask: np.ndarray, dtype: np.dtype = _dtype_float64) -> csr_matrix: """Return a discrete laplacian operator for the given restricted grid. This computes a standard laplacian operator as a scipy linear operator, except it is restricted to a grid mask. The use case for this is to compute surface diffusion on a gridded variable. The mask is generated from a category on the lung_tissue variable. """ graph_shape = len(grid), len(grid) laplacian = dok_matrix(graph_shape, dtype=dtype) delta_z = grid.delta(0) delta_y = grid.delta(1) delta_x = grid.delta(2) for k, j, i in zip(*(mask).nonzero()): voxel = Voxel(x=i, y=j, z=k) voxel_index = grid.get_flattened_index(voxel) for neighbor in grid.get_adjacent_voxels(voxel, corners=False): ni = neighbor.x nj = neighbor.y nk = neighbor.z if not mask[nk, nj, ni]: continue neighbor_index = grid.get_flattened_index(neighbor) dx = delta_x[k, j, i] * (i - ni) dy = delta_y[k, j, i] * (j - nj) dz = delta_z[k, j, i] * (k - nk) inverse_distance2 = 1 / (dx * dx + dy * dy + dz * dz ) # units: 1/(µm^2) laplacian[voxel_index, voxel_index] -= inverse_distance2 laplacian[voxel_index, neighbor_index] += inverse_distance2 return laplacian.tocsr()
def test_get_adjacent_voxels(grid: RectangularGrid, voxel, neighbors): assert set(grid.get_adjacent_voxels(voxel)) == neighbors
def test_get_corner_adjacent_voxels(grid: RectangularGrid, voxel, neighbors): assert len(list(grid.get_adjacent_voxels(voxel, corners=True))) == neighbors