Create linear operator from volume

It may be interesting to create linear operators that describe a single contribution for each voxel as in a volume mask. This can be encoded as follows:

\[\begin{split}\begin{bmatrix} w_1 \cdot \mathbf{g} & & & \\ & w_2 \cdot \mathbf{g} & & \\ & & \ddots & \\ & & & w_n \cdot \mathbf{g} \\ \end{bmatrix}\end{split}\]

where \(\mathbf{g}\) is the generator used for every voxel and \(w_j\) is the value of the mask at voxel \(j\). Only the voxels exhibiting non-zero value are considered.

To build such a linear operator, one just needs to provide a three-dimensional ndarray to the talon.diagonalize function.

Example

Let us build a toy volume of dimension 2-by-2-by-2 with values from 0 to 7.

import numpy as np
values = np.arange(2 ** 3).astype(np.float64)

mask = values.reshape((2, ) * 3)
print(mask)

Output:

[[[0. 1.]
  [2. 3.]]

 [[4. 5.]
  [6. 7.]]]

To diagonalize the volume, call the corresponding talon function.

import talon
indices, weights = talon.diagonalize(mask)

The considered generator is vector \(g = [1, 10]^T\).

generators = np.array([[1.0, 10.0]])
linear_operator = talon.operator(generators, indices, weights)

Check the output:

print(linear_operator.todense())

[[ 0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.]
 [ 1.  0.  0.  0.  0.  0.  0.]
 [10.  0.  0.  0.  0.  0.  0.]
 [ 0.  2.  0.  0.  0.  0.  0.]
 [ 0. 20.  0.  0.  0.  0.  0.]
 [ 0.  0.  3.  0.  0.  0.  0.]
 [ 0.  0. 30.  0.  0.  0.  0.]
 [ 0.  0.  0.  4.  0.  0.  0.]
 [ 0.  0.  0. 40.  0.  0.  0.]
 [ 0.  0.  0.  0.  5.  0.  0.]
 [ 0.  0.  0.  0. 50.  0.  0.]
 [ 0.  0.  0.  0.  0.  6.  0.]
 [ 0.  0.  0.  0.  0. 60.  0.]
 [ 0.  0.  0.  0.  0.  0.  7.]
 [ 0.  0.  0.  0.  0.  0. 70.]]