Report an errorErrata
Part I · Module 05

Matrices as operators

Linear algebra rebuilt as geometry. A matrix is a machine that moves vectors, and a beamformer, a phase-screen correction, a clutter filter and a sound-speed tomogram are all such machines. This module sets the vocabulary (subspaces, projections, conditioning, unitary bases) that Modules 06 and 07 and the three targets rely on.

You will be able to

  • Read \(A\mathbf{x}\) as a weighted sum of columns and predict what a 2×2 matrix does to the plane from det, trace and rank.
  • Name the four fundamental subspaces and decide whether \(A\mathbf{x} = \mathbf{b}\) has zero, one or infinitely many solutions.
  • Derive least squares from orthogonality, build the projector \(P = A(A^{T}A)^{-1}A^{T}\) and use the pseudo-inverse.
  • Compute κ, predict noise amplification and say what Tikhonov regularization trades.
  • Write DAS, apodization, phase-screen correction and SoS tomography as matrices, and move between element and plane-wave bases with a unitary DFT.

Assumes

  • Module 01 · Complex numbers and phasors: complex arithmetic, conjugate, \(\lvert z\rvert^2 = z z^*\)
  • Module 02 · The DFT and FFT by hand: the DFT matrix \(\mathbf{F}\), used here as the standard unitary basis
  • DAS, plane-wave compounding, apodization (used as anchors, not re-taught); mechanics of matrix multiplication (row times column)
  • Optional further reading: Module 08 gives the rigorous version of IQ data
Exact formulaclosed form plotted as isSimulationnumerical solution run in this page (JS) or in the module's Octave scriptsApprox. modelsimplified physics; assumptions under the badgeSchematicdrawing for intuition, not computedMost figures in this module plot exact linear-algebra identities or solve small systems in the page. Wave-physics figures (Demos 05.7 and 05.8, the beam and tomography cards) use narrowband or Gaussian-pulse, straight-ray, single-scattering models written in this page; no Field II or k-Wave output is shown.

05.1Vectors, inner products and the conjugate

A vector \(\mathbf{x} \in \mathbb{R}^{n}\) or \(\mathbb{C}^{n}\) is an ordered list of numbers and, geometrically, an arrow. The vectors you already handle every day: one RF line (n = number of samples), one snapshot across the array at fixed time (n = 128 element samples), or a whole IQ frame stacked into one long column (\(n = N_{z}N_{x}\)). Everything below treats these lists as points in a space where length and angle are defined, so that "similar", "orthogonal" and "closest" become computable.

\[ \langle \mathbf{x},\mathbf{y}\rangle = \mathbf{y}^{H}\mathbf{x} = \sum_i x_i\, y_i^{*}, \qquad \lVert\mathbf{x}\rVert = \sqrt{\langle\mathbf{x},\mathbf{x}\rangle} = \Big(\sum_i \lvert x_i\rvert^{2}\Big)^{1/2} \]
(05.1)
\(\mathbf{x},\mathbf{y}\)
vectors in ℂⁿ (an RF line, one aperture snapshot, a stacked IQ frame)
\(x_i,\ y_i\)
their entries
\((\cdot)^{H}\)
conjugate (Hermitian) transpose
\((\cdot)^{*}\)
complex conjugate
\(\lVert\mathbf{x}\rVert\)
2-norm (length); its square is the energy
\(\langle\cdot,\cdot\rangle\)
inner (dot) product, a scalar
\(\sqrt{\cdot}\)
positive square root
\(\lvert\cdot\rvert\)
magnitude of a complex number
\(\sum_i\)
sum over the entries \(i\) of the vector
\((\cdot)^{H}\) is the conjugate (Hermitian) transpose. For real vectors \((\cdot)^{H} = (\cdot)^{T}\) and the conjugate does nothing. This lab conjugates the second argument; physics texts often conjugate the first. Magnitudes agree, phases flip sign.

Why the conjugate. A norm must be real and positive for every nonzero vector. Take \(\mathbf{x} = (1, i)\): without conjugation \(\mathbf{x}^{T}\mathbf{x} = 1 + i^{2} = 0\), a nonzero vector of "length" zero. With it, \(\mathbf{x}^{H}\mathbf{x}\) \(= \lvert 1\rvert^{2} + \lvert i\rvert^{2}\) \(= 2\). IQ samples are complex, so every energy, correlation, projection and covariance on IQ data uses \((\cdot)^{H}\). The conjugate also removes the common carrier phase: if both vectors pick up the same phase \(e^{i\varphi}, \mathbf{y}^{H}\mathbf{x}\) is unchanged.

Angle and orthogonality. Cauchy–Schwarz gives \(\lvert \langle \mathbf{x},\mathbf{y}\rangle \rvert \le \lVert \mathbf{x}\rVert \lVert \mathbf{y}\rVert\), with equality only for parallel vectors, so for real vectors \(\cos \theta\) \(= \mathbf{y}^{T}\mathbf{x} / (\lVert \mathbf{x}\rVert \lVert \mathbf{y}\rVert)\) is a valid angle. For complex vectors the magnitude \(\lvert \mathbf{y}^{H}\mathbf{x}\rvert /(\lVert \mathbf{x}\rVert \lVert \mathbf{y}\rVert) \in [0,1]\) plays the same role. Orthogonal means \(\langle \mathbf{x},\mathbf{y}\rangle = 0\); an orthonormal set satisfies \(\mathbf{q}_{j}^{H}\mathbf{q}_{i} = \delta_{ij}\).

Projection onto a line

Find the multiple \(c\mathbf{a}\) closest to \(\mathbf{x}\). The error is smallest when it is perpendicular to the line:

\[ \mathbf{a}^{H}(\mathbf{x} - c\,\mathbf{a}) = 0 \;\Rightarrow\; c = \frac{\mathbf{a}^{H}\mathbf{x}}{\mathbf{a}^{H}\mathbf{a}} \]
(05.2)
\(\mathbf{a}\)
direction vector of the line (e.g. a steering vector), fixed
\(\mathbf{x}\)
vector to be approximated (e.g. channel snapshot)
\(c\)
scalar coefficient (complex amplitude) of \(\mathbf{a}\) that best fits \(\mathbf{x}\)
\((\cdot)^{H}\)
conjugate transpose, as in (05.1)
\(\Rightarrow\)
implies
\[ \mathbf{p} = \mathbf{a}\,\frac{\mathbf{a}^{H}\mathbf{x}}{\mathbf{a}^{H}\mathbf{a}} = \left(\frac{\mathbf{a}\mathbf{a}^{H}}{\mathbf{a}^{H}\mathbf{a}}\right)\mathbf{x}, \qquad \lVert\mathbf{x}\rVert^{2} = \lVert\mathbf{p}\rVert^{2} + \lVert\mathbf{x}-\mathbf{p}\rVert^{2} \]
(05.3)
\(\mathbf{p}\)
projection of \(\mathbf{x}\) onto the line through \(\mathbf{a}\)
\(\mathbf{a},\ \mathbf{x}\)
as in (05.2)
\(\mathbf{a}\mathbf{a}^{H}/(\mathbf{a}^{H}\mathbf{a})\)
rank-one projector matrix onto \(\mathbf{a}\)
\(\lVert\cdot\rVert\)
2-norm, as in (05.1); squared norms are energies
\(\mathbf{x}-\mathbf{p}\)
residual, orthogonal to \(\mathbf{p}\)
The bracket is a rank-one projector matrix. Pythagoras holds because \(\mathbf{p} \perp (\mathbf{x} - \mathbf{p})\). Every projector in this module is a sum of such pieces over an orthonormal basis.

Cosine similarity is the correlation coefficient. Subtract the means, \(\tilde{\mathbf{x}} = \mathbf{x} - \bar{x}\mathbf{1}\), and the Pearson coefficient is exactly the cosine of the angle between the centered vectors: \(\rho\) \(= \tilde{\mathbf{y}}^{T}\tilde{\mathbf{x}} / (\lVert \tilde{\mathbf{x}}\rVert \lVert \tilde{\mathbf{y}}\rVert)\). Module 07 builds covariance and spatial coherence on this; Module 11 uses normalized cross-correlation (a cosine between a kernel and a shifted window) for speckle tracking and delay estimation.

Demo 05.1

Projection, angle and the orthogonal residual

Exact formula
a (drag tip)x (drag tip)p = projectionresidual r = x − p
Try: drag x around a full circle and watch cos θ pass through 0 (orthogonal) and −1 (anti-parallel). Note that \(a^{T}r\) stays at zero to machine precision wherever you put the vectors: that orthogonality is the whole content of least squares (§05.5).
Ultrasound link

The coherence factor is a squared cosine. With \(\mathbf{s}\) the delayed aperture vector for one pixel, \(\mathrm{CF}\) \(= \lvert \mathbf{1}^{H}\mathbf{s}\rvert^{2} / (N\lVert \mathbf{s}\rVert^{2})\) \(= \cos^{2}\angle (\mathbf{s}, \mathbf{1})\), since \(\lVert \mathbf{1}\rVert^{2} = N\). Perfect focusing makes \(\mathbf{s}\) parallel to the all-ones vector; aberration rotates it away, which is why CF and its relatives are used as focus-quality metrics in sound-speed estimation.

Pitfall

numpy.dot(x, y) on complex arrays does not conjugate; numpy.vdot(y, x) conjugates its first argument and returns \(\mathbf{y}^{H}\mathbf{x}\). In MATLAB x' is \((\cdot)^{H}\) and x.' is \((\cdot)^{T}\). Using the wrong one on IQ data gives energies that can be negative or complex, and correlations whose magnitude depends on the carrier phase.

05.2Matrices in numbers: the workbench

Before the geometry, the bookkeeping. \(A \in \mathbb{C}^{m\times n}\) has m rows and n columns; \(a_{ij}\) (MATLAB A(i,j)) sits in row i, column j. Vectors are columns (n×1). Shapes chain as (m×k)(k×n) = m×n, and the inner dimensions must agree. Demo 05.2 shows each operation with actual numbers, the MATLAB line that computes it, and where it appears in ultrasound; m05_matrix_basics.m (§05.13) prints the same numbers.

\[ \begin{aligned} (A\mathbf{x})_i &= \sum_j a_{ij}x_j = (\text{row } i \text{ of } A)\cdot\mathbf{x}, \qquad A\mathbf{x} = \sum_j x_j\,\mathbf{a}_j \\ (AB)_{ij} &= \sum_k a_{ik}b_{kj} = (\text{row } i \text{ of } A)\cdot(\text{column } j \text{ of } B) \end{aligned} \]
(05.4)
\(A \in \mathbb{C}^{m\times n}\)
matrix with entries \(a_{ij}\) (row i, column j)
\(\mathbf{a}_j\)
column j of A
\(B \in \mathbb{C}^{n\times p}\)
second factor, entries \(b_{kj}\)
\(\mathbf{x}\)
input vector with entries \(x_j\)
\((A\mathbf{x})_i\)
entry \(i\) of the output vector
\(i,\ j,\ k\)
row, column and summation indices
\(\sum_j,\ \sum_k\)
sums over column index \(j\) or inner index \(k\)
\(AB\)
matrix product, \(m \times p\)
\(\cdot\)
dot product of two vectors
Row picture: one inner product per output. Column picture: the output is a mix of the columns. Cost: mn multiply-adds for \(A\mathbf{x}\), mkn for an (m×k)(k×n) product.

Worked example. With A = [2 1 0; −1 3 2; 0 1 4] and \(\mathbf{x}\) = (1, 2, −1), the rows give 2·1 + 1·2 + 0·(−1) = 4, −1 + 6 − 2 = 3 and 0 + 2 − 4 = −2. The columns give 1·(2, −1, 0) + 2·(1, 3, 1) − 1·(0, 2, 4) = (4, 3, −2). Same vector, two readings.

Demo 05.2

Matrix workbench: numbers, MATLAB, ultrasound

Exact formula

Highlights: blue = entries used in the current step, pink = the operand they meet (or entries already summed). Complex entries use \(j = \sqrt{-1}\); MATLAB prints i. Try: step through A·x in both pictures and check that row 2 and the running column sum both give 3. In "A·B versus B·A" every entry of AB − BA is shown. In "Tiny DAS", pixel 2 receives 0.75 of pixel 1's echo: that leakage is the PSF tail, the off-diagonal of \(BB^{T}\).
OperationDefinitionMATLABResultUltrasound reading
Transpose\((A^{T})_{ij} = a_{ji}\)A.'n×mswap samples × elements layout
Conjugate transpose\((A^{H})_{ij} = a_{ji}^{*}\)A'n×mevery energy, correlation and adjoint on IQ data
Inverse\(A^{-1}A = AA^{-1} = I\) (square, rank n)inv(A)n×nrarely needed explicitly; solve instead
Solve\(\mathbf{x}\) with \(A\mathbf{x} = \mathbf{b}\) (least squares if tall)A\bn×1parameter fits, inversion of a forward model
Pseudo-inverse\(A^{+} = V\Sigma^{+}U^{H}\) (invert σ above a tolerance)pinv(A), pinv(A,tol)n×mminimum-norm, truncated-SVD inversion
Outer product\((\mathbf{x}\mathbf{y}^{H})_{ij} = x_{i}y_{j}^{*}\)x*y'm×n, rank 1separable aperture, one coherent source in a covariance
Hadamard product\((A\circ B)_{ij} = a_{ij}b_{ij}\)A.*Bsame shapemasks, apodization maps, per-sample weights
Diagonal scalingDA scales rows, AD scales columnsd.*A, A.*d.'same shapeTGC on rows (depth), apodization on columns (elements)
Kronecker product\((B \otimes A) \operatorname{vec} (X) = \operatorname{vec} (AXB^{T})\)kron(B,A)(mp)×(nq)per-element operator on stacked channel data, separable 2D transforms
Determinant, rankdet = ±Π pivots; rank = # σ above tolerancedet, rankscalarsinvertible or not; number of independent components
Ultrasound link

Hold channel data as \(X \in \mathbb{C}^{N_{t}\times N_{e}}\) (time samples down, elements across). TGC is a diagonal matrix on the left (one gain per depth sample), apodization is a diagonal matrix on the right (one weight per element), and after the delays the DAS value of one pixel is the row-times-column product \(\mathbf{w}^{T}\mathbf{d}\) of the weights with the delayed snapshot. A frame sequence stacked as pixels × frames is the Casorati matrix whose low-rank part is tissue clutter (Module 06).

Pitfall

Three one-character bugs. MATLAB ' conjugates and .' does not; on IQ data the wrong one flips every phase. A*B is a matrix product and A.*B is elementwise; for square matrices both run without error and give different answers. inv(A)*b works but is slower and less accurate than A\b (rule 01 in 05.10).

A matrix zoo for ultrasound

Structure decides cost, conditioning and which fast algorithm applies. Recognizing the type of a matrix is the first step of every efficient implementation.

TypeStructureWhere it appearsCost of \(A\mathbf{x}\)
Diagonal\(a_{ij} = 0\) for i ≠ japodization weights, TGC gains, element calibration, phase-screen correction \(\operatorname{diag} (e^{i\omega_{0}\delta \tau_{e}})\)O(n)
Toeplitz\(a_{ij} = t_{i-j}\), constant along each diagonalconvolution with the pulse or a PSF along one axis; covariance of a wide-sense stationary process (approximately, the spatial covariance of diffuse speckle across the aperture)O(nL) banded; O(n log n) by FFT embedding
Circulant\(a_{ij} = c_{(i-j) \bmod n}\)circular convolution, FFT filtering, a phase screen seen in the plane-wave basis (\(F D F^{H}\))O(n log n): diagonalized by the DFT
DFT / unitary\(F_{kn} = e^{-i2\pi kn/N}/\sqrt{N}, Q^{H}Q = I\)element ↔ plane-wave (angular spectrum), time ↔ frequency, any change of orthonormal basisO(n log n) by FFT, \(O(n^{2})\) dense
Vandermonde\(a_{nm} = z_{m}^{n}\)steering vectors (columns \(e^{i2\pi np \sin \theta_{m}/\lambda}\)), polynomial and power-law spectral fitsO(nm); ill-conditioned when nodes \(z_{m}\) cluster
Hermitian PSD\(R = R^{H}, \mathbf{x}^{H}R\mathbf{x} \ge 0\)spatial covariance (coherence, minimum variance), slow-time covariance (Doppler, clutter), Gram matrices \(A^{H}A\), Fisher information\(O(n^{2})\); Cholesky or eig \(O(n^{3})\)
Sparsefew nonzeros per rowDAS operator B (\(N_{e}\) × taps per row), ray-length matrix in SoS tomography, finite-difference regularizersO(nnz)
Low-rank\(A = U_{k}\Sigma_{k}V_{k}^{H}, k \ll \min (m,n)\)tissue clutter in the Casorati (pixels × frames) matrix, a few coherent sources in a covariance, separable aperturesO(k(m + n))
Block / KroneckerB ⊗ A, block diagonalseparable 2D operators (2D DFT = F ⊗ F), row-column and matrix arrays, a per-element operator on stacked data (\(D \otimes I_{t}\))for n×n factors: \(2n^{3}\) via \(\operatorname{vec} (AXB^{T})\) instead of \(n^{4}\) for the \(n^{2}\times n^{2}\) matrix
Permutationone 1 per row and columnchannel-to-element mapping, multiplexing, circular shift S (circulant \(C = \sum c_{k}S^{k}\))O(n), no arithmetic
Orthogonal projector\(P^{2} = P = P^{H}\)slow-time mean removal \(I - \mathbf{1}\mathbf{1}^{T}/N\), SVD clutter filter \(I - U_{k}U_{k}^{H}\), least-squares fitted valuesO(nk) in factored form

05.3A matrix is a linear map

A map is linear if \(A(\alpha \mathbf{x} + \beta \mathbf{y})\) \(= \alpha A\mathbf{x} + \beta A\mathbf{y}\). Every linear map from \(\mathbb{R}^{n}\) to \(\mathbb{R}^{m}\) is a matrix, and the matrix is fully determined by where it sends the basis vectors: column j of A is \(A\mathbf{e}_{j}\). Writing any input as \(\mathbf{x} = \sum x_{j}\mathbf{e}_{j}\) and applying linearity gives the two readings of a matrix–vector product:

\[ \text{column picture: } A\mathbf{x} = x_1\mathbf{a}_1 + x_2\mathbf{a}_2 + \dots + x_n\mathbf{a}_n, \qquad \text{row picture: } (A\mathbf{x})_i = \mathbf{r}_i^{T}\mathbf{x} \]
(05.5)
\(A\)
\(m \times n\) matrix
\(\mathbf{a}_1,\dots,\mathbf{a}_n\)
columns of \(A\)
\(\mathbf{x}\)
input vector with entries \(x_1,\dots,x_n\)
\(\mathbf{r}_i^{T}\)
row \(i\) of \(A\), written as a row vector
\((\cdot)^{T}\)
transpose
Columns tell you what the output is made of; rows tell you how each output is measured from the input.

Beamforming reads naturally both ways. Row picture: a pixel value is a dot product between that pixel's delay-and-apodization pattern and the channel data. Column picture of the forward model: the channel data are a sum over scatterers of amplitude × that scatterer's echo hyperbola. Section 05.8 makes both exact.

Composition is multiplication. \((AB)\mathbf{x} = A(B\mathbf{x})\): the matrix written last acts first. Shapes chain as (m×k)(k×n) = m×n, and in general \(AB \ne BA\). With shear \(S = \begin{bmatrix}1 & 1 \\ 0 & 1\end{bmatrix}\) and 90° rotation \(R = \begin{bmatrix}0 & -1 \\ 1 & 0\end{bmatrix}\): \(SR\mathbf{e}_{1} = (1, 1)\) but \(RS\mathbf{e}_{1} = (0, 1)\).

Determinant, trace, eigenvalues. For a 2×2 matrix with entries a, b (top row), c, d:

\[ \det A = ad - bc = \text{signed area of the image of the unit square}, \qquad \det(AB) = \det A\,\det B \]
(05.6)
\(A\)
2 × 2 matrix \(\begin{bmatrix}a & b \ c & d\end{bmatrix}\)
\(a,\ b,\ c,\ d\)
entries of \(A\)
\(\det\)
determinant (area scale factor of the map; sign gives orientation)
\(B\)
a second square matrix of the same size
\[ \operatorname{tr} A = a + d = \lambda_1 + \lambda_2, \qquad \det A = \lambda_1\lambda_2, \qquad \lambda = \frac{\operatorname{tr} A}{2} \pm \sqrt{\frac{(\operatorname{tr} A)^{2}}{4} - \det A} \]
(05.7)
\(\operatorname{tr}A\)
trace: sum of the diagonal entries
\(a,\ d\)
diagonal entries of \(A\), as in (05.6)
\(\lambda_1,\ \lambda_2\)
eigenvalues of \(A\)
\(\det A\)
determinant, as in (05.6)
det < 0 means orientation flips (a reflection is involved). det = 0 means the columns are dependent, A squashes the plane onto a line (or a point) and cannot be inverted.

The unit circle always maps to an ellipse whose semi-axes are the singular values \(\sigma_{1} \ge \sigma_{2} \ge 0\), so \(\lvert \det A\rvert = \sigma_{1}\sigma_{2}\). Module 06 proves that every matrix acts this way: rotate (\(V^{H}\)), stretch along the axes (\(\Sigma\)), rotate again (U).

Demo 05.3

2×2 transform playground

Exact formula
a₁ = Ae₁ (drag)a₂ = Ae₂ (drag)image of unit circleellipse axes σ₁u₁, σ₂u₂ / Ax
Try: pick "Near-singular" and drag \(a_{2}\) onto the line of \(a_{1}\): the ellipse flattens to a segment, \(\det \to 0, \sigma_{2} \to 0\), rank drops to 1. Apply \(R_{90}\cdot A\) then undo with three more presses, versus \(A\cdot R_{90}\): the parallelogram is the same set but the columns are permuted, so the two products differ. Reflection gives det = −1 (orientation flip), projection gives det = 0 with eigenvalues exactly 1 and 0.
Intuition

Read a matrix by its columns first. If you know where \(e_{1}\) and \(e_{2}\) land, you know where everything lands, because every other point is a weighted sum of those two. Turn on "show x → Ax" to see \(A\mathbf{x}\) built tip-to-tail as \(x_{1}\mathbf{a}_{1} + x_{2}\mathbf{a}_{2}\).

Ultrasound link

The receive chain up to the envelope is a product of matrices: IQ demodulation D, decimation S, beamforming B, angle compounding C, so \(\mathbf{i} = C B S D \mathbf{r}\) for raw RF \(\mathbf{r}\). Envelope detection |·| and log compression are the first nonlinear steps. Everything before them obeys superposition, which is why SVD clutter filtering (Module 06) can act on channel data or on beamformed IQ, and why a PSF fully characterizes the linear part of the system.

Pitfall

In code, A @ B @ x applies B first. A chain written as "first weight channels by W, then beamform with B" is \(B W \mathbf{d}\), not \(W B \mathbf{d}\); the second is not even dimensionally valid when B changes the vector length.

05.4Rank and the four fundamental subspaces

The rank r of \(A \in \mathbb{R}^{m\times n}\) is the number of independent columns, which always equals the number of independent rows. Four subspaces (Strang's picture) organize everything about \(A\mathbf{x} = \mathbf{b}\). For complex A replace \((\cdot)^{T}\) by \((\cdot)^{H}\).

SubspaceDefinitionLives inDimensionMeaning
Column space C(A)\(\{A\mathbf{x}\}\)\(\mathbb{R}^{m}\) (outputs)revery output A can produce
Null space N(A)\(\{\mathbf{x} : A\mathbf{x} = 0\}\)\(\mathbb{R}^{n}\) (inputs)n − rinputs A cannot see
Row space \(C(A^{T})\)\(\{A^{T}\mathbf{y}\}\)\(\mathbb{R}^{n}\) (inputs)rinputs A measures
Left null space \(N(A^{T})\)\(\{\mathbf{y} : A^{T}\mathbf{y} = 0\}\)\(\mathbb{R}^{m}\) (outputs)m − routputs A can never produce

Orthogonality. \(A\mathbf{x} = 0\) says \(\mathbf{x}\) is orthogonal to every row, so \(N(A) \perp C(A^{T})\); the same argument on \(A^{T}\) gives \(N(A^{T}) \perp C(A)\). Each pair splits its space completely, which yields rank–nullity:

\[ \dim C(A^{T}) + \dim N(A) = n, \qquad \dim C(A) + \dim N(A^{T}) = m \]
(05.8)
\(A\)
\(m \times n\) matrix
\(C(A),\ C(A^{T})\)
column space and row space of \(A\)
\(N(A),\ N(A^{T})\)
null space of \(A\) and of \(A^{T}\) (left null space)
\(\dim\)
dimension of a subspace
\(m,\ n\)
number of rows and columns of \(A\)

Existence and uniqueness. A solution exists iff \(\mathbf{b} \in C(A)\), equivalently \(\mathbf{b} \perp N(A^{T})\). It is unique iff N(A) = {0}, i.e. r = n. The general solution is \(\mathbf{x} = \mathbf{x}_{p} + \mathbf{x}_{n}\) with \(\mathbf{x}_{n} \in N(A)\); exactly one solution lies in the row space, the minimum-norm one, \(\mathbf{x}^{+} = A^{+}\mathbf{b}\).

Shape / rankSolutions of \(A\mathbf{x} = \mathbf{b}\)Standard remedyUltrasound example
r = m = nexactly one\(A^{-1}\mathbf{b}\) (if well conditioned)2×2 parameter fit with good data
r = n < m (tall)0 or 1least squares (§05.5)attenuation slope from 25 spectral points
r = m < n (wide)infinitely manyminimum norm / regularizationSoS map with more pixels than path measurements
r < m, r < n0 or infinitely manypseudo-inverse \(A^{+}\)rank-deficient tomography, truncated SVD
Demo 05.4

Four subspaces of a 2×2 matrix

Exact formulaSVD built from the chosen angles and σ; pseudo-inverse with optional truncation, all closed form.
row space / column spacenull spacesb (drag in output panel)x⁺ and the solution line
Try: with \(\sigma_{2} = 0\), drag b onto the column-space line (it snaps): a whole line of exact solutions appears, parallel to N(A), and \(x^{+}\) is the point on it nearest the origin. Pull b off the line: no exact solution, the residual is along \(N(A^{T})\). Now set \(\sigma_{2} = 0.03\): the solution becomes unique but \(\lVert x\rVert\) explodes (off the panel); tick "truncate" to get the well-behaved rank-1 answer back. That last step is regularization in miniature (§05.6).
Ultrasound link

Pulse-echo sound-speed tomography (\(A\mathbf{s} = \Delta \mathbf{t}\), 05.8) has an effectively nonempty null space. With a linear array the usable ray paths are all within a few tens of degrees of vertical, so slowness patterns that vary along depth and integrate to nearly zero along every steep path are (almost) invisible: their component lies in N(A). No amount of data from the same geometry recovers them; a regularizer or prior (batch 2, Inverse problems) chooses that component for you. Knowing N(A) tells you which artifacts in a SoS map are geometry, not tissue.

Pitfall

Do not test rank or invertibility with det ≈ 0. A perfectly conditioned 128×128 matrix with all σ = 0.5 has \(\det = 0.5^{128} \approx 3\times 10^{-39}\). Numerical rank is decided by a threshold on the singular values (Module 06), and closeness to singularity by κ (§05.6).

05.5Projections and least squares

Take a tall A (m > n) with independent columns and data \(\mathbf{b} \notin C(A)\), the usual situation when you fit a few parameters to many noisy samples. Minimize \(\lVert \mathbf{b} - A\mathbf{x}\rVert^{2}\). Geometrically we want the point \(\mathbf{p} = A\hat{\mathbf{x}}\) of the column space closest to \(\mathbf{b}\), and exactly as in 05.1 the error must be perpendicular to that subspace, i.e. to every column:

\[ A^{T}(\mathbf{b} - A\hat{\mathbf{x}}) = 0 \;\Rightarrow\; A^{T}A\,\hat{\mathbf{x}} = A^{T}\mathbf{b} \qquad (\text{normal equations}) \]
(05.9)
\(A\)
m × n model matrix, m > n, independent columns (e.g. 25 frequencies × 2 columns)
\(\mathbf{b}\)
data, m × 1 (e.g. log spectral ratio, dB)
\(\hat{\mathbf{x}}\)
least-squares parameters, n × 1 (e.g. intercept dB, slope dB/MHz)
\(\mathbf{b} - A\hat{\mathbf{x}}\)
residual, orthogonal to every column of A
\((\cdot)^{T}\)
transpose
\(A^{T}A\)
\(n \times n\) Gram matrix of the columns of \(A\)
The calculus route agrees: \(\nabla_{x}\lVert \mathbf{b} - A\mathbf{x}\rVert^{2}\) \(= -2A^{T}(\mathbf{b} - A\mathbf{x})\) \(= 0\). Complex data: \(A^{H}A\hat{\mathbf{x}} = A^{H}\mathbf{b}\).
\[ \hat{\mathbf{x}} = (A^{T}A)^{-1}A^{T}\mathbf{b} = A^{+}\mathbf{b}, \qquad P = A(A^{T}A)^{-1}A^{T}, \qquad P^{2} = P,\;\; P^{T} = P \]
(05.10)
\(A,\ \mathbf{b},\ \hat{\mathbf{x}}\)
as in (05.9)
\(A^{+}\)
pseudoinverse \((A^{T}A)^{-1}A^{T}\) (full column rank)
\(P\)
projector onto the column space of \(A\); \(P\mathbf{b} = A\hat{\mathbf{x}}\)
\(P^{2}=P,\ P^{T}=P\)
idempotent (projecting twice changes nothing) and symmetric (orthogonal projector)
\((\cdot)^{-1}\)
matrix inverse
\[ \mathbf{r} = (I - P)\,\mathbf{b} \in N(A^{T}), \qquad \lVert\mathbf{b}\rVert^{2} = \lVert P\mathbf{b}\rVert^{2} + \lVert\mathbf{r}\rVert^{2} \]
(05.11)
\(\mathbf{r}\)
least-squares residual, same units as \(\mathbf{b}\)
\(I\)
identity matrix
\(P,\ \mathbf{b},\ A\)
as in (05.10)
\(N(A^{T})\)
left null space of \(A\) (vectors orthogonal to every column)
\(\in\)
is an element of
\(\lVert\cdot\rVert\)
2-norm
P projects onto C(A), I − P onto its orthogonal complement \(N(A^{T})\). Both are idempotent and symmetric; those two properties characterize orthogonal projectors.

Pseudo-inverse. For full column rank, \(A^{+} = (A^{T}A)^{-1}A^{T}\) (least squares). For full row rank, \(A^{+} = A^{T}(AA^{T})^{-1}\) (minimum-norm exact solution). In general \(A^{+} = V\Sigma^{+}U^{H}\), inverting only nonzero σ (Module 06); Demo 05.4 computes exactly this.

Statistics. If \(\mathbf{b} = A\mathbf{x} + \mathbf{n}\) with white Gaussian \(\mathbf{n} \sim N(0, \sigma^{2}I)\), then \(\hat{\mathbf{x}}\) is the maximum-likelihood estimate, it is unbiased, and \(\operatorname{Cov} (\hat{\mathbf{x}}) = \sigma^{2}(A^{T}A)^{-1}\). For a straight-line fit \(y = c_{0} + c_{1}f\) that gives \(\operatorname{SE} (c_{1}) = \sigma /\sqrt{\sum (f_{i} - \bar{f})^{2}}\). The same matrix \((A^{T}A)^{-1}\) reappears as the noise amplifier in 05.6 and as the inverse Fisher information (CRLB) in batch 2.

Demo 05.5

Least-squares fit of a spectral log-ratio (attenuation slope)

Simulation25 samples of y = 2 − f dB plus seeded Gaussian noise (JS); polynomial least squares by modified Gram–Schmidt QR in the page.
datafit A x̂ (+ nudge)truth (−1 dB/MHz)residuals
Model: 25 frequencies from 2 to 8 MHz, y = 2 − 1.0·f dB (\(\alpha_{0} = 0.5\) dB/cm/MHz over Δz = 1 cm, round trip), columns \(t^{k}\) with t = (f − 5)/3, solved by QR (modified Gram–Schmidt). Try: nudge the coefficient and watch \(\lVert r\rVert^{2}\) grow by exactly \(\delta^{2}\lVert a_{1}\rVert^{2}\) while \(A^{T}r\) leaves zero. Raise the order to 8: the residual shrinks (more columns, bigger C(A)) but the curve chases noise and κ(A) climbs. Add the outlier: the slope moves by about +0.20 dB/MHz, three times its noise standard error.
Ultrasound link

QUS spectral fits are least squares on log spectra. The spectral-difference attenuation estimate fits the log-ratio of power spectra from two depths against frequency; for \(\alpha (f) = \alpha_{0}f\) the slope is \(-2\alpha_{0}\Delta z\) (dB/MHz), here −1 dB/MHz. Backscatter coefficient and effective scatterer size fits have the same structure with different columns. In ULM, a Gaussian PSF becomes a quadratic in the log domain, so a fast sub-pixel localizer is a 6-column least-squares fit of log-intensity around the peak.

Pitfall

Two numerical traps. (1) Forming \(A^{T}A\) squares the condition number, \(\kappa (A^{T}A) = \kappa (A)^{2}\); with \(\kappa (A) = 10^{4}\) you lose 8 of 16 digits. Solve with QR (\(A = QR, \hat{\mathbf{x}} = R^{-1}Q^{T}\mathbf{b}\)) or SVD, as numpy's lstsq and MATLAB's backslash do. (2) L2 weights errors quadratically, so one specular reflection or a noisy spectral edge can dominate a fit. Robust (L1, Huber) and weighted fits come in batch 2.

05.6Conditioning and noise amplification

Solve \(A\mathbf{x} = \mathbf{b}\) when \(\mathbf{b}\) carries an error \(\delta \mathbf{b}\). By linearity \(\delta \mathbf{x} = A^{-1}\delta \mathbf{b}\), and the largest and smallest stretch factors of A bound everything:

\[ \lVert\delta\mathbf{x}\rVert \le \lVert A^{-1}\rVert\,\lVert\delta\mathbf{b}\rVert = \frac{\lVert\delta\mathbf{b}\rVert}{\sigma_{\min}}, \qquad \lVert\mathbf{b}\rVert \le \lVert A\rVert\,\lVert\mathbf{x}\rVert = \sigma_{\max}\lVert\mathbf{x}\rVert \]
(05.12)
\(A\)
square invertible matrix in \(A\mathbf{x}=\mathbf{b}\)
\(\mathbf{x},\ \mathbf{b}\)
solution and data vectors
\(A^{-1}\)
inverse of \(A\); \(\lVert A^{-1} Vert = 1/\sigma_{\min}\)
\(\lVert A\rVert\)
spectral (2-)norm of \(A\), equal to \(\sigma_{\max}\)
\(\delta\mathbf{x},\ \delta\mathbf{b},\ \sigma_{\max},\ \sigma_{\min}\)
as in (05.13)
\[ \frac{\lVert\delta\mathbf{x}\rVert}{\lVert\mathbf{x}\rVert} \le \kappa\,\frac{\lVert\delta\mathbf{b}\rVert}{\lVert\mathbf{b}\rVert}, \qquad \kappa = \frac{\sigma_{\max}}{\sigma_{\min}} \]
(05.13)
\(\delta\mathbf{b}\)
error in the data (noise, delay error)
\(\delta\mathbf{x}\)
resulting error in the solution of \(A\mathbf{x} = \mathbf{b}\)
\(\sigma_{\max},\ \sigma_{\min}\)
largest and smallest singular values of A (longest and shortest ellipse axes)
\(\kappa\)
2-norm condition number, dimensionless; about \(\log_{10}\kappa\) digits are lost
\(\mathbf{x},\ \mathbf{b}\)
solution and data vectors of \(A\mathbf{x}=\mathbf{b}\)
\(\lVert\cdot\rVert\)
2-norm; the ratios are relative (dimensionless) errors
κ is the worst-case relative-error amplification. Rule of thumb: you lose about \(\log_{10}\kappa\) significant digits, of data precision, not just of floating point.

Random noise, not worst case. For \(\delta \mathbf{b} \sim N(0, \sigma^{2}I)\) and \(A = U\Sigma V^{T}\), \(\operatorname{Cov} (\delta \mathbf{x})\) \(= \sigma^{2}(A^{T}A)^{-1}\) \(= \sigma^{2} V \Sigma^{-2} V^{T}\): the error is an ellipse whose axes are the right singular vectors \(v_{i}\) with standard deviations \(\sigma /\sigma_{i}\). The noise is amplified only along the weak directions.

Two nearly parallel columns. Let A have unit columns at angle φ. Then \(A^{T}A = \begin{bmatrix}1 & \cos \varphi \\ \cos \varphi & 1\end{bmatrix}\) with eigenvalues 1 ± cos φ, so

\[ \sigma_{1,2} = \sqrt{1 \pm \cos\varphi}, \qquad \kappa = \sqrt{\frac{1+\cos\varphi}{1-\cos\varphi}} = \cot\frac{\varphi}{2} \]
(05.14)
\(\varphi\)
angle between the two unit-norm columns of A
\(\sigma_{1,2}\)
singular values of A
\(\sqrt{\cdot}\)
positive square root
\(\cot\)
cotangent
\(\cos\varphi\)
inner product of the two unit-norm columns of A
φ = 90°: κ = 1. φ = 30°: κ = 3.73. φ = 10°: κ = 11.4. φ = 2°: κ = 57.3. Two measurements that "look almost the same" cannot separate their two causes.

Tikhonov regularization (teaser for batch 2, Inverse problems)

Add a penalty on \(\lVert \mathbf{x}\rVert^{2}\) and the normal equations get a diagonal load:

\[ \hat{\mathbf{x}}_\lambda = \arg\min_{\mathbf{x}}\; \lVert A\mathbf{x}-\mathbf{b}\rVert^{2} + \lambda\lVert\mathbf{x}\rVert^{2} = (A^{T}A + \lambda I)^{-1}A^{T}\mathbf{b} \]
(05.15)
\(\hat{\mathbf{x}}_\lambda\)
regularized (Tikhonov) solution
\(A,\ \mathbf{b},\ \mathbf{x}\)
model matrix, data, and trial parameter vector, as in (05.9)
\(\lambda\)
regularization weight, \(\lambda \ge 0\)
\(\arg\min_{\mathbf{x}}\)
the \(\mathbf{x}\) that minimizes the expression
\(\lVert A\mathbf{x}-\mathbf{b}\rVert^{2}\)
data misfit (squared residual)
\(\lambda\lVert\mathbf{x}\rVert^{2}\)
penalty on solution size
\(I\)
\(n \times n\) identity
\[ \mathbf{v}_i^{T}\hat{\mathbf{x}}_\lambda = f_i\,\mathbf{v}_i^{T}\mathbf{x} + \frac{\sigma_i}{\sigma_i^{2}+\lambda}\,\mathbf{u}_i^{T}\delta\mathbf{b}, \qquad f_i = \frac{\sigma_i^{2}}{\sigma_i^{2}+\lambda} \]
(05.16)
\(\mathbf{u}_i,\ \mathbf{v}_i\)
left and right singular vectors of \(A = U\Sigma V^{T}\)
\(\sigma_i\)
singular values of A
\(\lambda\)
regularization weight, same units as \(\sigma_i^{2}\)
\(f_i\)
filter factor: ≈ 1 for \(\sigma_i^{2} \gg \lambda\), ≈ 0 for \(\sigma_i^{2} \ll \lambda\), ½ at \(\sigma_i^{2} = \lambda\)
\(\mathbf{x},\ \delta\mathbf{b}\)
true solution and data error
\(\hat{\mathbf{x}}_\lambda\)
regularized solution, as in (05.15)
\((\cdot)^{T}\)
transpose
Each SVD component is multiplied by a filter factor \(f_{i}\). Strong components (\(\sigma_{i}^{2} \gg \lambda\)) pass untouched; weak ones are suppressed. Noise std along \(v_{i}\) drops from \(\sigma /\sigma_{i}\) to \(\sigma \sigma_{i}/(\sigma_{i}^{2} + \lambda)\) at the price of a bias \(-\lambda /(\sigma_{i}^{2} + \lambda) \cdot v_{i}^{T}x\).
Demo 05.6

Noise cloud of a 2×2 solve: κ, error ellipse, Tikhonov

SimulationMonte Carlo: 600 seeded Gaussian draws of δb solved through A⁻¹ or the Tikhonov inverse in JS; the 2σ ellipse is the closed-form covariance.
noisy samples2σ ellipse (theory)columns a₁, a₂truth x = (1, 1)
Same scale in both panels. Left: data space, b + δb is an isotropic disk. Right: solution space, the same disk mapped by \(A^{-1}\). Try: close φ toward 2°: the cloud stretches along \(v_{2}\) by \(1/\sigma_{2}\) while the data disk is unchanged. Then raise λ: the cloud collapses, but its center slides away from the truth (bias); RMSE first drops, then rises again when \(\lambda \gg \sigma_{2}^{2}\).
Ultrasound link

Nearly parallel columns are the normal state of pulse-echo sound-speed tomography: neighboring pixels are crossed by almost the same set of steep ray paths, so their columns of A are almost parallel and κ is very large. The same filter-factor algebra appears in minimum-variance beamforming: the weights use \(R^{-1}\) of the sample covariance (Module 07), and diagonal loading R + εI is Tikhonov with λ = ε. It trades resolution (bias) for robustness (variance) exactly as the cloud does here.

Pitfall

det is not a conditioning measure. \(10^{-6}\cdot I\) has \(\det = 10^{-12}\) and κ = 1: perfectly conditioned, just scaled. \(\begin{bmatrix}1 & 1 \\ 1 & 1.01\end{bmatrix}\) has det = 0.01 and κ ≈ 402. Use κ (or the singular values) and compare it with your data SNR.

05.7Unitary matrices and change of basis

\(Q \in \mathbb{C}^{n\times n}\) is unitary if \(Q^{H}Q = I\), so \(Q^{-1} = Q^{H}\) and the columns form an orthonormal basis. Unitary maps preserve inner products, hence lengths, angles and energy:

\[ \langle Q\mathbf{x}, Q\mathbf{y}\rangle = \mathbf{y}^{H}Q^{H}Q\,\mathbf{x} = \langle\mathbf{x},\mathbf{y}\rangle, \qquad \lVert Q\mathbf{x}\rVert = \lVert\mathbf{x}\rVert, \qquad \kappa(Q) = 1 \]
(05.17)
\(Q\)
matrix with orthonormal columns (\(Q^{H}Q = I\)), e.g. a unitary DFT
\(\mathbf{x},\ \mathbf{y}\)
any two vectors
\(\langle\cdot,\cdot\rangle,\ \lVert\cdot\rVert\)
inner product and 2-norm, as in (05.1)
\((\cdot)^{H}\)
conjugate transpose
\(\kappa(Q)\)
condition number of \(Q\) (dimensionless)
Real case: orthogonal matrices, i.e. rotations (det = +1) and reflections (det = −1). All singular values are 1, so a unitary step never amplifies noise.

Change of basis. With basis vectors as the columns of Q, coordinates are inner products (analysis) and the vector is rebuilt as a weighted sum (synthesis). An operator keeps its identity but gets new coordinates:

\[ \mathbf{c} = Q^{H}\mathbf{x}\;\;(c_k = \mathbf{q}_k^{H}\mathbf{x}), \qquad \mathbf{x} = Q\,\mathbf{c}, \qquad A^{\prime} = Q_{\mathrm{out}}^{H}\,A\,Q_{\mathrm{in}} \]
(05.18)
\(\mathbf{x}\)
signal vector (e.g. aperture snapshot)
\(\mathbf{c}\)
coefficients of \(\mathbf{x}\) in the basis \(Q\), entries \(c_k\)
\(Q,\ \mathbf{q}_k\)
orthonormal basis matrix and its column \(k\)
\(Q^{H}\)
conjugate transpose of \(Q\); equals \(Q^{-1}\) for a unitary basis
\(A\)
a linear operator expressed in the standard basis
\(A^{\prime}\)
the same operator expressed in the new bases
\(Q_{\mathrm{in}},\ Q_{\mathrm{out}}\)
orthonormal bases for the input and output spaces
Use different bases on the input and output sides when the operator maps between different spaces (e.g. transmit and receive).

Element basis ↔ plane-wave basis

The unitary DFT across N elements, \(F_{kn} = e^{-i2\pi kn/N}/\sqrt{N}\), satisfies \(F^{H}F = I\). A monochromatic plane wave from angle θ sampled at pitch p has a phase that advances 2πp sinθ/λ per element, so its DFT concentrates at

\[ k_\theta = \frac{N p \sin\theta}{\lambda} \;\;(\bmod N), \qquad \Delta(\sin\theta)\ \text{per bin} = \frac{\lambda}{Np}, \qquad \text{unambiguous for } \lvert\sin\theta\rvert < \frac{\lambda}{2p} \]
(05.19)
\(N\)
number of elements (128)
\(p\)
pitch, mm (0.3 mm)
\(\lambda\)
wavelength c/f, mm (0.308 mm at 5 MHz)
\(\theta\)
plane-wave angle from broadside
\(k_\theta\)
DFT bin across the aperture where the plane wave concentrates
\(\bmod N\)
result is taken modulo \(N\) (bins wrap around)
\(\Delta(\sin\theta)\)
change in \(\sin\theta\) per DFT bin (dimensionless)
\(\lvert\sin\theta\rvert < \lambda/(2p)\)
range with a unique bin (no wrap); \(p\) above \(\lambda/2\) aliases (grating lobes)
5 MHz, c = 1540 m/s (λ = 0.308 mm), p = 0.3 mm, N = 128: Δsin θ = 0.0080 (0.46° near broadside) and steering beyond ±30.9° aliases to another bin, which is the grating lobe seen in the angular domain. At 3 MHz (λ = 0.513 mm) the limit is ±58.8°.
Schematic Figure 05.A · Element basis ↔ plane-wave basis: why one plane wave is one DFT binGeometry not to scale (θ = 20° drawn); numbers on the right are computed for 5 MHz, θ = 10°, p = 0.3 mm, N = 128.
Plane wave from θ on a linear array (narrowband): one phase step per element θ propagation p sin θ wavefront through n p = 0.3 mm nn + 1 N = 128 elements, aperture Np = 38.4 mm phase step per element Δφ = 2π p sin θ / λ DFT bin kθ = N p sin θ / λ 5 MHz (λ = 0.308 mm), θ = 10°: Δφ = 0.34π, kθ = 21.65 no aliasing while |sin θ| < λ/(2p): |θ| < 30.9° grey lines: wavefronts, λ apart

A plane-wave transmit set works the same way on the transmit side: steering vectors for angles \(\theta_{m}\) are the columns of a matrix Φ (N elements × M angles), close to DFT columns when the angles sit on the sin θ grid λ/(Np). Firing them records \(Y = R\Phi\), where R is the element-space reflection matrix (one column per single-element transmit, as in full matrix capture). If the columns of Φ are orthonormal, \(Y\Phi^{H} = R\Phi \Phi^{H}\) is R projected onto the angular band you actually probed; with M = N it is R itself. The reflection-matrix literature does exactly this kind of bookkeeping: record in one basis, then multiply by propagation matrices on each side to express the same operator in the focused basis, where aberrations and multiple scattering become separable.

Demo 05.7

Unitary DFT across a 128-element aperture

Approx. modelSingle-frequency field on a 128-element linear array, pitch 0.3 mm: plane wave or point source with exact path lengths, no element directivity or attenuation; unitary DFT computed in the page.
Re xₙIm xₙphase screen φₙ/πpredicted bin k_θ
Try: at 5 MHz sweep θ: the energy sits in one or two bins (leakage when k_θ is not an integer), and past ±30.9° it wraps to the other side of the spectrum. Drop to 3 MHz and the wrap moves out. Add a phase screen: \(\lVert x\rVert^{2} = \lVert Fx\rVert^{2}\) never changes (unitary), but the energy spreads across many plane-wave bins; \(D^{H}\) undoes it exactly because the screen is a diagonal unitary matrix. A point source is not sparse in this basis at all.
Intuition

A change of basis does not change the signal, only which coordinates are large. A basis is useful when the thing you care about is sparse in it: a plane wave is one DFT coefficient, a near-field point echo is spread over many, tissue clutter is a few vectors of the SVD basis (Module 06). Choosing the basis is half of every algorithm in the target literature.

Ultrasound link

A near-field phase screen at the array is \(D = \operatorname{diag} (e^{i\varphi_{n}})\), unitary and diagonal in the element basis. In the plane-wave basis it becomes \(FDF^{H}\), a circulant matrix: multiplication becomes circular convolution with the screen's angular spectrum, which is why one transmitted angle leaks into many. Correction is \(D^{H}\), provided the screen is the same for all imaging points (isoplanatic). The distortion-matrix approach exists precisely because real aberrations vary across the field.

Pitfall

MATLAB's fft and numpy's default fft are \(\sqrt{N}\) times the unitary DFT: \(\lVert \operatorname{fft} (\mathbf{x})\rVert^{2}\) \(= N\lVert \mathbf{x}\rVert^{2}\). Use fft(x)/sqrt(N) (or norm="ortho") when energy or inner products must be preserved across bases.

05.8Imaging as a linear operator

Stack the channel data of one acquisition into a single vector \(\mathbf{d} \in \mathbb{C}^{N_{t}N_{e}}\) (samples × elements, element by element) and the image into \(\mathbf{i} \in \mathbb{C}^{N_{x}N_{z}}\). Under single scattering (first Born approximation) echoes add, so the acquisition is a matrix:

\[ \mathbf{d} = H\mathbf{\gamma} + \mathbf{n}, \qquad \text{column } j \text{ of } H = \text{channel data of a unit scatterer at pixel } j \]
(05.20)
\(\mathbf{d} \in \mathbb{C}^{N_t N_e}\)
stacked channel data (samples × elements)
\(\mathbf{\gamma} \in \mathbb{C}^{N_x N_z}\)
reflectivity per pixel
\(H\)
forward (acquisition) operator, \(N_tN_e \times N_xN_z\)
\(\mathbf{n}\)
noise
\(N_t,\ N_e\)
number of time samples and receive elements
\(N_x,\ N_z\)
number of pixels laterally and in depth
\(j\)
pixel index (column of \(H\))
\(\mathbf{\gamma}\) is the reflectivity per pixel. For a 0° plane wave the column is the pulse placed on the hyperbola \(\tau_{e}(x, z) = (z + \sqrt{(x - x_{e})^{2} + z^{2}})/c\).

DAS is a sparse matrix. \(i_{p} = \sum_{e} w_{e}(p) d_{e}(\tau_{e}(p))\), with interpolation between samples, is \(\mathbf{i} = B\mathbf{d}\). Row p of B is nonzero only at the samples on pixel p's delay curve: \(N_{e}\) × (interpolation taps) entries. For \(N_{t} = 2048, N_{e} = 128\), a 256 × 256 image and linear interpolation, B is 65 536 × 262 144 with 65 536·128·2 ≈ 16.8 M nonzeros, a density of about 0.1%. Apodization (including a dynamic F-number) only rescales the entries of each row.

\[ B_{p,(t,e)} = w_e(p)\; h_{\mathrm{interp}}\big(t - \tau_e(p)\,f_s\big), \qquad \mathbf{i} = B\mathbf{d} = BH\mathbf{\gamma} + B\mathbf{n} \]
(05.21)
\(w_e(p)\)
apodization of element e for pixel p
\(\tau_e(p)\)
round-trip delay of pixel p to element e, s
\(f_s\)
sampling rate, Hz (t is the sample index)
\(h_{\mathrm{interp}}\)
interpolation kernel (2 taps for linear)
\(\mathbf{i}\)
beamformed image, \(N_xN_z\) pixels
\(B\)
beamforming matrix, \(N_xN_z \times N_tN_e\)
\(p\)
pixel index (row of \(B\))
\(t,\ e\)
time-sample and element indices (column of \(B\))
\(\mathbf{d},\ H,\ \mathbf{\gamma},\ \mathbf{n}\)
as in (05.20)
Schematic Figure 05.B · DAS as a sparse matrix: each pixel row holds the samples on its delay curveDelay curve computed for z = 20 mm, 32 elements at 0.3 mm pitch, c = 1540 m/s; matrix layout schematic.
One row of the DAS matrix B = one pixel’s delay curve through the channel data array, elements e at xe 0° plane-wave transmit ↓ pixel p = (x, z) z to element e τe(p) = (z + √((x − xe)² + z²)) / c z = 20 mm, c = 1540 m/s: τ ≈ 26 µs channel data d: time ↓, element → xe from −4.65 to 4.65 mm (32 el.) 25.92 µs26.40 µs delay curve of p row p of B columns = (sample t, element e),stacked element by element elements 1 … 8 of 128 shown 2 interpolation taps per element 2 × 128 = 256 nonzeros per row of 2048 × 128 = 262 144 columns (0.1 % dense) 256 × 256 px: 16.8 M nonzeros apodization we(p) scales the taps

The adjoint is back-projection. \(B^{H}\) maps an image to channel data: each pixel "re-emits" its value along its own hyperbola. Conversely, DAS on IQ data with matched-filter weighting is (up to spreading factors) \(B \approx H^{H}\): beamforming is the adjoint of the forward model, not its inverse. The system matrix is then \(BH \approx H^{H}H\), and its column j is the PSF at pixel j. If \(H^{H}H\) were the identity, DAS would be perfect; its off-diagonal entries are sidelobes and the width of its diagonal band is the resolution. Model-based beamforming replaces \(H^{H}\) by \((H^{H}H + \lambda I)^{-1}H^{H}\), exactly the Tikhonov estimator of 05.6.

Why linearity pays. The image of many scatterers is the complex sum of their PSFs: speckle is interference of PSF columns, ULM localizes isolated columns, and the SVD clutter filter of Module 06 works on stacked IQ frames precisely because B is linear and acts frame by frame.

Demo 05.8

Forward model column and PSF = column of HᴴH

Approx. model0° plane-wave transmit, point scatterers, straight-ray delays, c = 1540 m/s, Gaussian pulse (5 MHz, 60 %); HᴴWHe_j evaluated through the pulse autocorrelation (JS); no element directivity, attenuation or diffraction loss.
channel panel: H e_j (RF, 0° plane wave, diverging map)image panel: |Hᴴ W H e_j|, 0 to −40 dB (click or drag to move the scatterer)
Model: \(f_{0} = 5\) MHz, Gaussian pulse with −6 dB bandwidth 3 MHz (60%), pitch 0.3 mm, c = 1540 m/s, 0° plane-wave transmit; image = \(H^{H} W H \gamma\) evaluated analytically through the pulse autocorrelation. Try: double the elements and the lateral width halves (λz/D). Switch to Hann: sidelobes drop, width grows about 1.65×. Add a second scatterer: the image is the complex sum of two columns; below about one PSF width the dip between them disappears.

Two more operators you will meet in the targets

Sound-speed tomography. Write slowness s = 1/c on a pixel grid. A travel time along ray k is a line integral, so the deviation from a reference medium is linear in the slowness deviation:

\[ \Delta t_k = \int_{\text{path } k} \Delta s(\mathbf{r})\,dl \approx \sum_j L_{kj}\,\Delta s_j \;\Rightarrow\; A\,\Delta\mathbf{s} = \Delta\mathbf{t}, \qquad A_{kj} = \text{length of ray } k \text{ inside pixel } j \]
(05.22)
\(s = 1/c\)
slowness, s/m; \(\Delta s\) its deviation from the reference medium
\(\Delta t_k\)
travel-time deviation along ray k, s
\(L_{kj} = A_{kj}\)
length of ray k inside pixel j, m
\(\Delta\mathbf{s}\)
vector of pixel slowness deviations \(\Delta s_j\), s/m
\(\Delta\mathbf{t}\)
vector of measured travel-time deviations \(\Delta t_k\), s
\(\mathbf{r}\)
position along the ray
\(dl\)
path-length element along ray \(k\), m
\(A\)
ray-length (tomography) matrix, rows = rays, columns = pixels
\(\approx\)
straight-ray (Born-type) approximation; sum over pixels \(j\)
A is sparse (each ray crosses few pixels), usually wide or rank-deficient, and badly conditioned in limited-angle pulse-echo geometry (§05.4, §05.6). Δt itself is measured by delay estimation between transmit angles (Module 11). This is Target B's core inverse problem.

Phase-screen aberration. A thin screen at the array delays element e by \(\delta \tau_{e}\). On narrowband IQ data that is a phase per element, a diagonal matrix on the element axis:

\[ \mathbf{d}_{\mathrm{ab}} = (D \otimes I_t)\,\mathbf{d}, \quad D = \operatorname{diag}\big(e^{-i\omega_0\delta\tau_e}\big), \qquad \text{corrected image: } \mathbf{i} = B\,(D^{H} \otimes I_t)\,\mathbf{d}_{\mathrm{ab}} \]
(05.23)
\(\delta\tau_e\)
screen delay at element e, s
\(\omega_0 = 2\pi f_0\)
centre angular frequency, rad/s
\(I_t\)
\(N_t \times N_t\) identity (same phase for every sample of a channel)
\(\otimes\)
Kronecker product
\(\mathbf{d}\)
aberration-free stacked channel data, as in (05.20)
\(\mathbf{d}_{\mathrm{ab}}\)
channel data with a phase screen applied
\(D\)
diagonal matrix of per-element phase factors
\(D^{H}\)
conjugate transpose of \(D\), the inverse phase correction
\(\operatorname{diag}\)
diagonal matrix built from a list of entries
\(e\)
element index
\(B,\ \mathbf{i}\)
beamforming matrix and image, as in (05.21)
\(i\)
imaginary unit (inside the exponent)
Broadband: a delay is a phase linear in frequency, so D is diagonal per frequency bin. Estimating \(\delta \tau_{e}\) is delay estimation (Module 11); the screen being field-dependent is what the distortion-matrix methods address.
Ultrasound link

ULM localization precision is set by the PSF column of BH: its width and the local SNR. More elements or more compounded angles sharpen the column and tighten the localization error (CRLB, batch 2). Aberration widens and distorts the column, which biases localization; correcting with \(D^{H}\) before DAS restores it.

Pitfall

B is not \(H^{-1}\) and is usually not even square. "Inverting the beamformer" means solving a regularized least-squares problem with H; DAS gives you \(H^{H}H\)-blurred reflectivity. Also note the linear model stops at the envelope: anything after |·| or log compression (B-mode, ULM detection thresholds) is nonlinear.

05.9Visual summary

Thirteen pictures to keep in your head, each with the question it answers and the number that goes with it. Every curve is computed from the formula in the card. The slider sets the angle φ between two unit columns (or two measurement lines): watch κ = cot(φ/2) grow as the columns close up.

05.10How experts think about it

Experienced researchers see every linear step of the pipeline as one matrix and ask four questions of it: what are its columns (the responses it can produce), what is its structure (diagonal, Toeplitz, sparse, low-rank, unitary), how well conditioned is it, and is the operation in front of them the adjoint, the inverse or a regularized inverse. The rules below are the sentences that carry those answers, each with the number that backs it.

Never invert a matrix to solve a system: use backslash.
LU ≈ \(\tfrac{2}{3}n^{3}\) vs inv ≈ \(2n^{3}\) flopshilb(10): residual 1.5e−16 vs 4.4e−5

A\b factors PA = LU and does two triangular solves; it is backward stable, meaning the computed x solves a system within machine precision of the original, so the residual \(\lVert Ax - b\rVert\) is of order \(\varepsilon \lVert A\rVert \lVert x\rVert\) whatever κ is. Forming inv(A) costs three times more and inv(A)*b is not backward stable. On hilb(10) (\(\kappa = 1.6\times 10^{13}\)) both have forward error ≈ \(5\times 10^{-4}\), as κ dictates, but the residual is \(1.5\times 10^{-16}\) for backslash and \(4.4\times 10^{-5}\) for the inverse (m05_matrix_basics.m).

SimulationLeft: flop-count formulas. Right: forward error and residual measured in m05_matrix_basics.m (Octave) on hilb(10).
An explicit inverse is fine for tiny closed-form cases (a 2×2 covariance readout) or when you truly need its entries, e.g. the diagonal of \((A^{T}A)^{-1}\) for error bars. Neither method beats κ on forward error.
A linear imaging system is completely described by its PSF matrix: column j is the response to pixel j.
256×256 image → 65 536 columnsshift-invariant → one column

Linearity plus the pixel basis: any object is \(\gamma = \sum \gamma_{j}\mathbf{e}_{j}\), so the image is \(\sum \gamma_{j}(BH\mathbf{e}_{j})\), and \(BH\mathbf{e}_{j}\) is the PSF for a point at pixel j (Demo 05.8). If the PSF only translates with position, every column is a shifted copy of one, the matrix is Toeplitz (block-Toeplitz in 2D) and imaging is a convolution. Ultrasound PSFs are not shift-invariant over the full field (depth-dependent focusing, F-number, attenuation), so the honest object is the whole matrix, or a PSF per isoplanatic region.

SchematicIllustrative Gaussian columns with a hand-set width law (narrowest at the focal pixel); shows shift variance, not a computed PSF.
Holds only up to the envelope; |·| and log compression are nonlinear. Assumes single scattering (Born) and a fine enough pixel grid; multiple scattering and reverberation are not columns of H.
DAS is the adjoint of the forward model, a matched filter, not its inverse.
\(B \approx H^{H}\)image = \(H^{H}H \gamma\)corr(B′e_j ∗ pulse, He_j) = 0.9995

Column j of H is the echo of pixel j on its hyperbola; row j of B sums the data along the same hyperbola, so \(B^{H}\mathbf{e}_{j}\) and \(H\mathbf{e}_{j}\) are the same curve. Filtering the 2-tap interpolation kernels with the pulse makes them match the true echo to a correlation of 0.9995 (m05_das_as_matrix.m). Hence, with (05.20), the DAS image is \(H^{H}H\gamma\): reflectivity blurred by the Gram matrix, whose diagonal width is resolution and whose off-diagonals are sidelobes. The least-squares inverse would be \((H^{H}H)^{-1}H^{H}\).

Approx. model0° plane wave, point scatterer at 20 mm, straight rays, Gaussian-modulated 5 MHz pulse, 64 elements; no directivity or attenuation.
Exact adjointness needs the pulse matched filter, the same interpolation and apodization interpreted as weighting; RF DAS without matched filtering differs from \(H^{H}\) by the pulse: its axial PSF is the pulse itself, not the pulse autocorrelation. Adjoint ≠ optimal: with strong sidelobes or clutter, regularized inverses can do better at higher cost.
κ tells you how many digits you lose: about \(\log_{10} \kappa\).
\(\lVert \delta x\rVert /\lVert x\rVert \le \kappa \lVert \delta b\rVert /\lVert b\rVert\)\(\kappa = 10^{3}\), 1% data error → up to 10× error

The bound (05.13) follows from \(\lVert \delta x\rVert \le \lVert \delta b\rVert /\sigma_{\min}\) and \(\lVert b\rVert \le \sigma_{\max}\lVert x\rVert\). Data known to 1% (2 digits) through \(\kappa = 10^{3}\) leave −1 digits: the worst-case relative error is 10, i.e. no information in the worst direction. Floating point gives 16 digits, so numerical round-off rarely matters; measurement noise almost always does. For random noise the amplification is along the weak singular vectors only, by \(1/\sigma_{i}\) per direction (Demo 05.6).

Exact formulaWorst-case bound lines κ·(relative error); data-precision and round-off cases.
A worst-case bound; typical errors are smaller unless the noise has energy along \(v_{\min}\). Depends on the scaling of unknowns: rescaling columns changes κ (cond([1 f]) = 16.2, cond([1 (f−5)/3]) = 1.66).
Never form \(A^{T}A\) when you can use QR or SVD: it squares κ.
\(\kappa (A^{T}A) = \kappa (A)^{2}\)order-7 fit: 2.6e9 → 7.0e18error 1.2e−7 vs 1.8e−2

The singular values of \(A^{T}A\) are \(\sigma_{i}^{2}\), so κ doubles in digits. QR solves \(R\mathbf{x} = Q^{T}\mathbf{b}\) with κ(R) = κ(A). For an order-7 polynomial in raw frequency (25 points, 2–8 MHz), \(\kappa (A) = 2.6\times 10^{9}\); noise-free data recover the coefficients to \(1.2\times 10^{-7}\) with backslash and only \(1.8\times 10^{-2}\) with the normal equations (m05_least_squares_conditioning.m).

SimulationSingular values of the 25-point Vandermonde matrices computed by one-sided Jacobi SVD in the page.
Normal equations are fine and cheaper when \(\kappa (A) \lesssim 10^{3}\) and for huge sparse problems solved iteratively; CGLS and LSQR apply A and \(A^{T}\) without forming \(A^{T}A\) and keep κ(A).
The least-squares solution is a projection: the residual is orthogonal to every column.
\(A^{T}r = 0\)\(P = A(A^{T}A)^{-1}A^{T}\), trace P = p

By (05.9), the fitted values \(A\hat{\mathbf{x}} = P\mathbf{b}\) are the closest point of C(A) to \(\mathbf{b}\), so \(\mathbf{r} \perp C(A)\) and \(\lVert b\rVert^{2} = \lVert Pb\rVert^{2} + \lVert r\rVert^{2}\). In the 4-point attenuation fit of Demo 05.2, \(A^{T}r = 0\) and trace P = 2 = number of parameters; the diagonal of P (0.7, 0.3, 0.3, 0.7) is the leverage: the band-edge frequencies pull the line hardest. Checking \(A^{T}r \approx 0\) is the fastest test that a solver did what you think.

SimulationClosed-form least-squares fit (JS) of four illustrative log-ratio points; leverage = diagonal of P.
Orthogonal only in the unweighted L2 inner product; weighted LS projects in the W-inner product, robust fits are not projections at all. One outlier at a high-leverage point moves the fit most (+0.20 dB/MHz, 3 SE in Demo 05.5).
Ill-posed inversions such as sound-speed tomography need regularization, and the price is bias.
\(f_{i} = \sigma_{i}^{2}/(\sigma_{i}^{2} + \lambda)\)\(\lambda = \sigma_{2}^{2}\): noise ½, signal ½

Tikhonov (05.16) multiplies each SVD component by \(f_{i}\): noise along \(v_{i}\) drops from \(\sigma /\sigma_{i}\) to \(\sigma \sigma_{i}/(\sigma_{i}^{2} + \lambda)\), the true component shrinks by \(\lambda /(\sigma_{i}^{2} + \lambda)\). In the 10° column-angle example (\(\sigma_{2} = 0.123\), noise 0.01), \(\lambda = \sigma_{2}^{2}\) halves the \(v_{2}\) noise (0.081 → 0.041) and costs almost no bias for x = (1, 1), which has no \(v_{2}\) component (0.011, from the slight shrinkage along \(v_{1}\)), but raises RMSE from 0.082 to 0.355 for x = (1, 0) (m05_least_squares_conditioning.m). Whether regularization helps depends on the truth.

Exact formulaClosed-form 2σ covariance ellipses and bias for unit columns 10° apart, σ = 0.01, λ = σ₂².
λ must be chosen (L-curve, discrepancy principle, GCV), and the penalty is a prior: smoothness penalties blur sharp SoS boundaries; total variation favors piecewise-constant maps. Bias is structured, so it shows up as artifacts, not noise.
det is not a measure of conditioning; κ or \(\sigma_{\min}\) is.
\(\det (0.5\cdot I_{128}) = 2.9e-39, \kappa = 1\)[1 1; 1 1.01]: det 0.01, κ ≈ 402

\(\det = \pm \prod \sigma_{i}\) scales with the n-th power of overall size: halving a perfectly conditioned 128×128 matrix multiplies det by \(2^{-128}\). \(\kappa = \sigma_{\max}/\sigma_{\min}\) is scale-invariant and is what governs error growth. det = 0 does mean singular, but numerical rank is decided by a tolerance on σ (MATLAB rank counts σ above about \(\max (m,n)\cdot \sigma_{\max}\cdot \mathrm{eps}\)).

Exact formuladet and κ of s·I₁₂₈ and of [1 1; 1 1.01] in closed form; image of the unit circle.
det remains the right object for volume scaling, change of variables in probability densities and log-likelihoods of Gaussian covariances (log det R), where it should be computed as a sum of log pivots, never as a product.
A unitary change of basis preserves energy (Parseval); MATLAB's fft is \(\sqrt{N}\) times unitary.
\(\lVert Qx\rVert = \lVert x\rVert, \kappa (Q) = 1\)\(\lVert \operatorname{fft} (x)\rVert^{2} = N\lVert x\rVert^{2}\)\(F_{4}^{H}F_{4} = 4I\)

\(Q^{H}Q = I\) preserves inner products, so energy, angles and white-noise statistics (covariance \(\sigma^{2}I\) stays \(\sigma^{2}I\)) survive the transform. For \(F_{4}\) and x = (1, 2, 0, −1): \(\lVert F_{4}x\rVert^{2} = 24 = 4\cdot 6\). That is why thresholding in an orthonormal basis (DFT, SVD) treats noise evenly, and why energy measured in the plane-wave domain equals energy in the element domain once you divide by N.

Exact formulaDFT of x = (1, 2, 0, −1) computed directly.
Only for orthonormal bases. Steering vectors at arbitrary angles, overcomplete dictionaries and windowed transforms are not unitary; their coefficients double-count or miss energy and color the noise.
Element ↔ plane-wave basis is an FFT across the aperture (narrowband, linear array).
\(k_{\theta}\) = Np sin θ/λΔsin θ = λ/(Np) = 0.0080 at 5 MHz|θ| < 30.9° unaliased (p = 0.3 mm)

By (05.19), a plane wave from θ advances in phase by 2πp sin θ/λ per element, which is DFT bin Np sin θ/λ. With N = 128, p = 0.3 mm, λ = 0.308 mm, one bin is 0.46° near broadside and angles beyond arcsin(λ/2p) = 30.9° alias to another bin, the angular-domain picture of a grating lobe. Plane-wave transmit sets and the reflection matrix are routinely moved between bases with exactly this transform.

Exact formulak_θ = Np sin θ/λ wrapped to [−N/2, N/2), N = 128, p = 0.3 mm, 5 MHz.
Monochromatic: for a broadband pulse the bin scales with frequency, so do it per frequency bin. Assumes far-field plane waves on a uniform linear array and ignores element directivity; a near-field point source spreads over many bins.
A thin phase screen at the array is a diagonal matrix, and its correction is the conjugate.
\(D = \operatorname{diag} (e^{-i\omega_{0}\delta \tau_{e}})\)δτ = 50 ns at 5 MHz = π/2

As in (05.23), a per-element delay \(\delta \tau_{e}\) on narrowband IQ is a per-element phase \(-\omega_{0}\delta \tau_{e}\), so the aberrated data are \(D\mathbf{d}\) (or \((D \otimes I_{t})\mathbf{d}\) on stacked data); D is unitary, so \(D^{H}\) undoes it exactly and costs N multiplies. 50 ns at 5 MHz is a quarter period, a factor −j (Demo 05.2, kron). In the plane-wave basis the same screen is the circulant \(FDF^{H}\), which spreads one angle into many (Demo 05.7).

Exact formulaDiagonal of D for a seeded smooth random screen (30 ns scale, 5 MHz); phasors e^(−iω₀δτ).
Only for a screen at (or conjugate to) the array and an isoplanatic patch. A distributed aberrator makes the correction field-dependent, so it is no longer one diagonal matrix: that is the motivation for distortion-matrix and local phase-screen methods. Broadband: diagonal per frequency, phase linear in f.
Convolution is a Toeplitz matrix, and the DFT diagonalizes its circulant embedding.
T: (N+L−1)×Npad FFT to ≥ N+L−1FFT wins above L ≈ 100 (N = 2048)

Column j of T is the pulse shifted by j − 1 samples. Padding to \(N_{c} \ge N + L - 1\) makes linear convolution circular, and every circulant is \(C = F^{H} \operatorname{diag} (F\mathbf{c}) F/N_{c}\) with F the unnormalized DFT matrix, so \(C\mathbf{x}\) \(= \operatorname{ifft} (\operatorname{fft} (c)\cdot \operatorname{fft} (x))\). Without padding (\(N_{c} = N\)) the tail wraps into the first L − 1 samples: max error 0.363 for a 31-tap pulse in m05_convolution_matrix.m. For a 2048-sample line, direct and FFT cost cross near L ≈ 100 taps.

Exact formulaDirect linear and circular convolution of a 31-tap Gaussian-cosine pulse with three spikes.
Only for shift-invariant filtering; depth-dependent filters, attenuation-induced downshift and space-variant PSFs break the Toeplitz structure. Crossover numbers depend on the FFT library and on reusing the filter spectrum.
Never build a Kronecker matrix: apply it as \(AXB^{T}\).
\((B \otimes A) \operatorname{vec} (X) = \operatorname{vec} (AXB^{T})\)n = 128: \(n^{4} = 2.7e8\) vs \(2n^{3} = 4.2e6\)

Separable operators act on rows and columns independently. The 2D DFT of an image is F ⊗ F applied as \(F X F^{T}\); a per-element operator on stacked channel data is \(D \otimes I_{t}\) applied as \(X D^{T}\) (X Nt × Ne). For n×n factors the explicit \(n^{2}\times n^{2}\) matrix needs \(n^{4}\) storage and multiply-adds; the factored form needs \(2n^{3}\), 64× fewer at n = 128.

Exact formulaOperation counts n⁴ and 2n³.
Only for exactly separable operators. A row-column array or 2D matrix probe makes the separability explicit; focusing with a 2D delay law that couples x and y is not separable.
The DAS matrix for a 128-element array has 16.8 million nonzeros: store it sparse or not at all.
65 536 × 262 144nnz 16.8 M, density 0.1%~270 MB sparse vs 137 GB dense

2048 samples × 128 elements in, 256 × 256 pixels out, 2 interpolation taps per element per pixel: 65 536 · 128 · 2 = 16.8 M nonzeros. Sparse double storage needs a value and an index per nonzero (≈ 16 B), about 270 MB; single precision with 32-bit indices halves that. The dense matrix would be \(1.7\times 10^{10}\) entries, 137 GB. \(B\mathbf{d}\) costs O(nnz), the same as a hand-written DAS loop.

Approx. modelToy geometry: 8 elements, 1.2 mm pitch, delays in sample units from straight rays, 2 linear-interpolation taps; totals for the 128-element case in the text.
Real-time scanners recompute delays on the fly instead of storing B. Storing B (often on a GPU) pays off when it is reused: many frames with the same geometry, or iterative solvers that need B and \(B^{H}\) repeatedly. More taps (sinc or spline interpolation) scale nnz linearly.
A sample covariance from K snapshots has rank at most K; you need K ≥ N before \(R^{-1}\) exists.
rank R ≤ min(K,N)K = 2N → ≈ 3 dB SINR loss (RMB)

\(\hat{R} = (1/K) \sum_{k} \mathbf{x}_{k}\mathbf{x}_{k}^{H}\) is a sum of K rank-one terms. In Demo 05.2, 2 snapshots across 3 elements give eigenvalues 10.98, 2.52, 0. Minimum-variance beamforming needs \(\hat{R}^{-1}\), so ultrasound implementations average over subarrays (and a few depth samples) and add diagonal loading. Reed, Mallett and Brennan showed that with K = 2N independent, signal-free snapshots the expected SINR loss of the sample-matrix inverse is about 3 dB.

SimulationLeft: eigenvalues of sample covariances of K seeded white snapshots (Jacobi, JS). Right: Reed–Mallett–Brennan expected loss (K + 2 − N)/(K + 1), exact.
Assumes independent, identically distributed Gaussian snapshots that do not contain the desired signal. In ultrasound the signal is in every snapshot, which slows convergence (signal cancellation) and is one more reason for diagonal loading; adjacent depth samples and coherent echoes are correlated, so the effective K is smaller. Coherent sources also need spatial smoothing to decorrelate.
Diagonal loading is Tikhonov regularization in disguise.
R + εI\(f_{i} = \lambda_{i}/(\lambda_{i} + \varepsilon)\)

Adding εI raises every eigenvalue of R by ε, so \(R^{-1}\) acts on eigenvector i as \(1/(\lambda_{i} + \varepsilon)\) instead of \(1/\lambda_{i}\): the weak directions estimated from few snapshots are no longer blown up. It is the same filter-factor algebra as 05.6, with ε playing λ. Small ε gives MV resolution and fragility; \(\varepsilon \gg \lambda_{\max}\) pushes the weights toward the DAS weights. Practitioners set ε as a small fraction of the average eigenvalue tr(R)/N.

Exact formulaGain 1/(λ + ε) and filter λ/(λ + ε) versus normalized eigenvalue.
Fixed loading ignores how many snapshots you have and how mismatched the steering vector is; adaptive and robust (uncertainty-set) MV variants choose ε from the data.

05.11Cheat sheet

ConceptFormulaUltrasound use
Inner product, norm\(\langle\mathbf{x},\mathbf{y}\rangle = \mathbf{y}^{H}\mathbf{x},\ \ \lVert\mathbf{x}\rVert^{2} = \mathbf{x}^{H}\mathbf{x}\)energy of IQ data, coherence factor, NCC
Projection onto a\(\mathbf{p} = \dfrac{\mathbf{a}^{H}\mathbf{x}}{\mathbf{a}^{H}\mathbf{a}}\,\mathbf{a}\)amplitude of a known waveform (matched filter)
Correlation coefficient\(\rho = \cos\angle(\mathbf{x} - \bar{x},\ \mathbf{y} - \bar{y})\)speckle tracking, VCZ coherence (Modules 07, 11)
Transpose vs Hermitian\(A^{T}\): A.'; \(A^{H}\): A'; \(\mathbf{z}^{T}\mathbf{z} \ne \mathbf{z}^{H}\mathbf{z}\) for complex \(\mathbf{z}\)layout change vs energy/covariance on IQ data
Column picture\(A\mathbf{x} = \sum_j x_j\mathbf{a}_j\)channel data = \(\Sigma\) scatterer echoes (columns of H)
Determinantdet = signed area/volume scale; \(\det(AB) = \det A\,\det B\)invertibility only, never conditioning
Rank–nullity\(r + \dim N(A) = n\)invisible SoS patterns, beamformer null space
Normal equations\(A^{H}A\,\hat{\mathbf{x}} = A^{H}\mathbf{b}\)attenuation slope, BSC fits, Gaussian PSF fit
Orthogonal projector\(P = A(A^{H}A)^{-1}A^{H},\ \ P^{2} = P = P^{H}\)clutter removal as I − P (Module 06)
Pseudo-inverse\(A^{+} = V\Sigma^{+}U^{H}\)minimum-norm tomography, truncated SVD
Condition number\(\kappa = \sigma_{\max}/\sigma_{\min};\ \ \lVert\delta\mathbf{x}\rVert/\lVert\mathbf{x}\rVert \le \kappa\,\lVert\delta\mathbf{b}\rVert/\lVert\mathbf{b}\rVert\)SoS tomography, MV beamformer covariance
Tikhonov\((A^{H}A + \lambda I)^{-1}A^{H}\mathbf{b},\ \ f_i = \sigma_i^{2}/(\sigma_i^{2} + \lambda)\)diagonal loading, regularized beamforming
Unitary\(Q^{H}Q = I,\ \ \lVert Q\mathbf{x}\rVert = \lVert\mathbf{x}\rVert,\ \ \kappa = 1\)DFT across aperture: element ↔ plane wave
Change of basis\(A^{\prime} = Q_{\mathrm{out}}^{H}\,A\,Q_{\mathrm{in}}\)reflection matrix in element / angle / focused bases
Convolution matrix\(T_{ij} = h_{i-j}\), \((N+L-1)\times N\); circulant \(C = F^{H}\operatorname{diag}(F\mathbf{c})\,F/N\) (F = unnormalized DFT matrix)RF line = pulse ∗ reflectivity, FFT filtering with padding
Kronecker\((B\otimes A)\operatorname{vec}(X) = \operatorname{vec}(AXB^{T})\)per-element operator on stacked data \(D \otimes I_{t}\), 2D DFT F ⊗ F
Imaging operator\(\mathbf{i} = B\mathbf{d},\ \ B \approx H^{H}\), PSF = column of \(BH\)DAS, back-projection, ULM PSF model
Phase screen\(D = \operatorname{diag}(e^{i\varphi_e})\), correction \(D^{H}\)aberration correction (Target C)

05.12Interview and qualifying-exam questions

I1In MATLAB, what is the difference between ' and .', and which do you use on IQ data? · screen

' is the conjugate (Hermitian) transpose, .' the plain transpose; on real data they agree. For z = (1, j), z.'*z = 1 + \(j^{2} = 0\) while z'*z = 2: only \((\cdot)^{H}\) gives an energy. Every energy, correlation, covariance (\(R = X^{H}X/K\)), projection and adjoint on IQ data uses '. A pure layout change (samples × elements to elements × samples) must use .', otherwise every phase flips sign and Doppler or phase-aberration estimates change sign.

Follow-up: "numpy?" x.T does not conjugate, x.conj().T does, and np.dot does not conjugate while np.vdot conjugates its first argument.

I2Why is DAS not the least-squares inverse of the forward model? · onsite

With \(\mathbf{d} = H\mathbf{\gamma} + \mathbf{n}\), the least-squares estimate is \((H^{H}H)^{-1}H^{H}\mathbf{d}\). DAS applies only \(H^{H}\) (up to apodization and the pulse matched filter): it sums each pixel's data along that pixel's hyperbola, the adjoint, so the image is \(H^{H}H\mathbf{\gamma}\), reflectivity blurred by the PSF matrix. \(H^{H}H\) is far from the identity (finite aperture and bandwidth) and is badly conditioned, so the exact inverse would amplify noise along weak singular vectors; in practice one uses \((H^{H}H + \lambda I)^{-1}H^{H}\), solved iteratively with B and \(B^{H}\) (CG/LSQR), never by forming \(H^{H}H\).

Follow-up: "Then why is DAS so widely used?" It is the matched filter: for white noise and a single scatterer it maximizes SNR at that pixel, it is cheap (one sparse product), and it is robust to model error, which the inverse is not.

I3What does a large condition number mean for pulse-echo sound-speed tomography? · research

In \(A \Delta \mathbf{s} = \Delta \mathbf{t}, \kappa (A)\) is the worst-case amplification of relative delay error into relative slowness error, and \(\log_{10}\kappa\) is the number of digits lost. Limited-angle pulse-echo geometry makes axially adjacent pixels see nearly the same steep paths, so columns are nearly parallel and κ is huge (effectively a null space for axial variations). With delays known to 1% and \(\kappa = 10^{3}\), the unregularized map can be 10× wrong in its weak directions. The cure is regularization (Tikhonov, smoothness or TV priors) and more angular diversity (more transmit/receive angles), with bias as the price: the reconstruction blurs or biases exactly the patterns the geometry cannot see.

Follow-up: "How do you choose λ?" L-curve corner, discrepancy principle (residual ≈ expected delay noise), or GCV; and validate on a phantom with known layers, because the bias is structured.

I4K snapshots across N elements: what is the rank of the sample covariance, and what does that imply for minimum-variance beamforming? · onsite

\(\hat{R} = (1/K)X^{H}X\) with \(X \in \mathbb{C}^{K\times N}\), so \(\operatorname{rank} \hat{R} \le \min (K,N)\). For K < N it is singular and \(\hat{R}^{-1}\) in the MV weights \(w = \hat{R}^{-1}\mathbf{a}/(\mathbf{a}^{H}\hat{R}^{-1}\mathbf{a})\) does not exist. Ultrasound MV therefore averages over subarrays of length L < N (and over a few depth samples) to get enough snapshots, and adds diagonal loading \(\hat{R} + \varepsilon I\), which is Tikhonov. The Reed–Mallett–Brennan result says about K = 2N independent snapshots keep the expected SINR loss near 3 dB when the snapshots do not contain the desired signal; in ultrasound they do, so convergence is slower and loading is needed even at K ≥ 2N.

Follow-up: "What does the eigen-spectrum tell you?" The number of large eigenvalues is the number of coherent sources; the rest is the noise floor, the basis of subspace methods (MUSIC, eigenspace MV) and of the clutter-rank discussion in Module 06.

I5How do you compute a pseudo-inverse stably? · onsite

Through the SVD: \(A^{+} = V\Sigma^{+}U^{H}\) with \(1/\sigma_{i}\) only for \(\sigma_{i}\) above a tolerance (MATLAB pinv uses about \(\max (m,n)\cdot \sigma_{\max}\cdot \mathrm{eps}\); pinv(A,tol) raises it, which is truncated-SVD regularization). Never form \((A^{T}A)^{-1}A^{T}\) for an ill-conditioned A: it squares κ. For full column rank, QR (A\b) gives the same least-squares solution more cheaply; for rank-deficient problems lsqminnorm or a complete orthogonal decomposition gives the minimum-norm solution. For large sparse operators, LSQR with early stopping acts as a regularizer.

Follow-up: "How do you pick the tolerance?" From the noise: drop \(\sigma_{i}\) whose \(1/\sigma_{i}\) amplification pushes the noise above the signal along \(v_{i}\), i.e. the discrete Picard condition (\(\lvert u_{i}^{H}b\rvert\) should decay faster than \(\sigma_{i}\)).

I6Size, nonzeros and memory of the DAS matrix for 128 elements, 2048 samples and a 256 × 256 image? Would you store it? · screen

B is 65 536 × 262 144. With linear interpolation each pixel row has 2 taps per element: 65 536 · 256 = 16.8 M nonzeros, density 0.1%. Sparse double storage ≈ 16 B per nonzero ≈ 270 MB; dense would be 137 GB. A product \(B\mathbf{d}\) is 16.8 M multiply-adds per frame (complex data), the same work as a DAS loop. Store it when it is reused many times (fixed geometry over thousands of frames on a GPU, iterative solvers needing B and \(B^{H}\)); compute on the fly when geometry or sound speed changes per frame.

Follow-up: "And with 8 plane-wave angles compounded?" Stack the 8 operators side by side: 8× the columns and nonzeros (134 M, ≈ 2 GB double), or apply them one at a time and sum.

I7Show that the DFT diagonalizes circular convolution. What goes wrong if you FFT-filter an RF line without zero padding? · screen

A circulant is \(C = \sum c_{k}S^{k}\) with S the cyclic shift. The DFT vectors are eigenvectors of S (a cyclic shift multiplies DFT bin k by the unit-modulus phase \(e^{\pm i2\pi k/N}\), sign set by the DFT convention), hence of every polynomial in S, with eigenvalues fft(c): \(C = F^{H} \operatorname{diag} (F\mathbf{c}) F/N, F\) the unnormalized DFT matrix. Linear convolution of N samples with L taps is circular only if both are zero-padded to \(N_{c} \ge N + L - 1\); with \(N_{c} = N\) the last L − 1 output samples wrap into the first L − 1 (error 0.363 for a 31-tap 5 MHz pulse in m05_convolution_matrix.m).

Follow-up: "When is direct convolution faster?" For short kernels: for a 2048-sample line the crossover is near L ≈ 100 taps, lower with real-input FFTs and overlap-add (that count already assumes a precomputed filter spectrum).

I8Adding a quadratic term to your attenuation fit with raw frequency columns makes the coefficients jump around. Why, and what is the fix? · onsite

The columns 1, \(f, f^{2}\) over 2–8 MHz are nearly parallel (a Vandermonde matrix on an off-center interval), so κ grows fast: cond([1 f]) = 16.2 but order 3, 5, 7 give \(6.4\times 10^{3}, 3.8\times 10^{6}, 2.6\times 10^{9}\). Center and scale, t = (f − 5)/3, and the same orders give 7.6, 39 and 215. If you also form \(A^{T}A\) you square these numbers. Fix: centered/scaled (or orthogonal-polynomial) columns, QR solve, and report the covariance \(\sigma^{2}(A^{T}A)^{-1}\) so the reader sees the coefficient uncertainty.

Follow-up: "Does centering change the fitted curve?" No, the column space is the same, so P and the fitted values are identical; only the coefficients and their conditioning change.

I9Write a phase-screen correction as a matrix. When does it fail? · research

For narrowband IQ with element delays \(\delta \tau_{e}\): \(\mathbf{d}_{\mathrm{ab}} = (D \otimes I_{t})\mathbf{d}\), \(D = \operatorname{diag} (e^{-i\omega_{0}\delta \tau_{e}})\); correction is \(D^{H}\) before DAS, N complex multiplies per sample, exact because D is unitary. It fails when the aberrator is not a thin screen at the array: a distributed or deep aberrator gives a field-dependent correction (isoplanatic patches of a few mm), so no single diagonal D works across the image. Broadband data need a delay (phase linear in frequency), not one phase.

Follow-up: "How would you estimate D?" Cross-correlate neighbouring channels on a bright target or speckle (Module 11), or find the phases that maximize coherence or image sharpness; the distortion-matrix approach estimates it per isoplanatic patch.

I10Is \(P = I - \mathbf{1}\mathbf{1}^{T}/N\) a good clutter filter for Doppler ensembles? What are its eigenvalues? · onsite

P is the orthogonal projector onto the complement of the constant vector: eigenvalues 1 (N − 1 times) and 0, \(\operatorname{rank} N - 1, P^{2} = P = P^{T}\). It removes exactly the slow-time mean, i.e. perfectly stationary tissue. Its frequency response is a narrow notch at 0 Hz of width about PRF/N, so moving tissue (breathing, cardiac motion) leaks through and slow flow near the notch is attenuated. Polynomial regression filters project out 1, \(t, t^{2}, \dots\); the SVD filter \(I - U_{k}U_{k}^{H}\) projects out the dominant spatiotemporal components, which handles moving tissue.

Follow-up: "Why does a projector, not a general high-pass, matter?" A projector has no transient for a finite ensemble and leaves the orthogonal complement untouched; IIR filters on short ensembles need initialization tricks.

05.13MATLAB lab

Base MATLAB only (no toolboxes); each script runs as-is in MATLAB R2019b+ and GNU Octave 8. Paste into the editor and press Run.

Download the scripts: m05_matrix_basics.m · m05_convolution_matrix.m · m05_das_as_matrix.m · m05_least_squares_conditioning.m. Base MATLAB R2019b+ or GNU Octave 8, no toolboxes; all scripts in the repository.

m05_matrix_basics.mEvery Demo 05.2 operation with the same numbers: A·x two ways, A·B vs B·A, ' vs .', inv/det, A\b, rank, projectors, F₄, Toeplitz, kron, tiny sparse DAS · edit any matrix · runtime ≈ 1 s
%% m05_matrix_basics.m  Module 05: the matrix workbench (Demo 05.2) in numbers
% Purpose : print every operation of the Module 05 workbench on the same small
%           matrices as the page, so each number on the page can be checked here:
%           A*x two ways, A*B vs B*A, .' vs ' on IQ data, inv/det of 2x2 and 3x3,
%           A\b (square and tall), rank of a rank-deficient matrix, projectors,
%           the DFT matrix F4, convolution as a Toeplitz matrix, kron for
%           per-element operators on stacked channel data, and a tiny sparse DAS matrix.
% Change  : edit any matrix below; e.g. make row 3 of A = row 1 + row 2 and rerun.
% Expect  : A*x = [4 3 -2]; det(A) = 24; A*B = [2 1 3; 1 5 -5; 4 5 -1] ~= B*A;
%           z.'*z = 0 but z'*z = 2; A\b = [1 -1 0.5]; tall fit slope -0.98 dB/MHz;
%           rank(M) = 2 with null vector [1 1 -1]; F4'*F4 = 4*I; T*x = conv(h,x);
%           DAS: nnz(B) = 10, B*d = [2 0.75]; hilb(10): A\b residual ~1e-16 vs
%           inv(A)*b ~4e-5 at equal forward error ~5e-4 (backslash is backward stable).
% Runtime : < 1 s.  Base MATLAB only; runs in MATLAB R2019b+ and GNU Octave 8.
rng(1);
pm = @(name, M) fprintf(['%s =\n' repmat([repmat('%9.4g', 1, size(M,2)) '\n'], 1, size(M,1))], name, M.');   % print a real matrix row by row

%% 1. A*x: row picture (one dot product per output) and column picture (mix of columns)
A = [ 2 1 0;
     -1 3 2;
      0 1 4];                  % 3x3 real, not symmetric
x = [1; 2; -1];                % 3x1 column vector
for i = 1:3
    fprintf('row %d: [%g %g %g] . [%g %g %g] = %g\n', i, A(i,:), x, A(i,:)*x);
end
y = zeros(3,1);
for j = 1:3
    y = y + x(j)*A(:,j);       % add x_j times column j
    fprintf('after column %d: [%g %g %g]\n', j, y);
end
fprintf('A*x = [%g %g %g]\n\n', A*x);

%% 2. A*B versus B*A: the order matters
B = [1 0 2;
     0 1 -1;
     1 1 0];
pm('A*B', A*B);  pm('B*A', B*A);  pm('A*B - B*A', A*B - B*A);
fprintf('(A*B)(2,3) = %g*%g + %g*%g + %g*%g = %g\n\n', A(2,1), B(1,3), A(2,2), B(2,3), A(2,3), B(3,3), A(2,:)*B(:,3));

%% 3. Transpose .' versus conjugate transpose ' on IQ data
Z = [1+2i, 0.5-1i, -1i;
     2,   -1+1i,   0.3+0.4i];  % K = 2 snapshots (rows) x N = 3 elements (columns), complex IQ
disp('Z.'' (transpose, no conjugate) ='); disp(Z.');
disp('Z''  (conjugate transpose)    ='); disp(Z');
z = [1; 1i];
fprintf('z = [1; 1i]:  z.''*z = %g   z''*z = %g\n', z.'*z, z'*z);
R = Z'*Z;                      % 3x3 sample covariance across elements (times K): Hermitian PSD
disp('R = Z''*Z ='); disp(R);
fprintf('diag(R) = [%.2f %.2f %.2f] (element energies, real)\n', real(diag(R)));
ev = sort(real(eig(R)), 'descend');
fprintf('eig(R) = [%.4f %.4f %.4f], rank(R) = %d (K = 2 snapshots)\n\n', ev, rank(R));

%% 4. Inverse and determinant, 2x2 and 3x3
A2 = [4 7; 2 6];
fprintf('det(A2) = %g, inv(A2) = (1/det)[d -b; -c a]:\n', det(A2)); disp(inv(A2));
fprintf('det(A) = %g\n', det(A));
pm('24*inv(A) (the adjugate)', round(24*inv(A)));
pm('inv(A)', inv(A));
fprintf('max|A*inv(A) - I| = %.1e\n\n', max(max(abs(A*inv(A) - eye(3)))));

%% 5. Solve A x = b: square (LU) and tall (least squares by QR)
b = [1; -3; 1];
fprintf('A\\b = [%g %g %g]\n', A\b);
f  = [2; 4; 6; 8];                     % MHz
yd = [-1.0; -3.2; -4.8; -7.0];         % log-spectral ratio, dB
Af = [ones(4,1) f];                    % 4x2: intercept and slope columns
cf = Af \ yd;                          % least squares (QR inside)
r  = yd - Af*cf;
fprintf('tall 4x2 fit: c = Af\\y = [%.4f %.4f]  (intercept dB, slope dB/MHz)\n', cf);
fprintf('residual r = [%.3f %.3f %.3f %.3f], Af''*r = [%.1e %.1e]\n\n', r, Af'*r);

%% 6. Rank of a rank-deficient matrix
M = [1 2 3;
     2 0 2;
     0 1 1;
     1 1 2];                    % column 3 = column 1 + column 2
s = svd(M);
fprintf('svd(M) = [%.4f %.4f %.2e], rank(M) = %d\n', s, rank(M));
nv = [1; 1; -1];
fprintf('M*[1;1;-1] = [%g %g %g %g] (null vector)\n\n', M*nv);

%% 7. Projectors: P^2 = P
N = 4; one = ones(N,1);
P = eye(N) - one*one'/N;        % removes the slow-time mean (simplest wall filter)
pm('P = I - 11''/4', P);
xs = [3.0; 3.2; 2.9; 3.1];      % slow-time samples at one pixel: tissue (mean) + small flow
fprintf('P*x = [%.2f %.2f %.2f %.2f] (mean %.2f removed)\n', P*xs, mean(xs));
fprintf('max|P^2 - P| = %.1e, eig(P) = [%s], trace = %g\n', max(max(abs(P*P - P))), num2str(sort(eig(P)).', '%.0f '), trace(P));
H = Af * ((Af'*Af) \ Af');      % hat matrix of the line fit in section 5 (fine here: kappa small)
pm('H = Af*(Af''*Af)^-1*Af''', H);
fprintf('H*y = [%.3f %.3f %.3f %.3f] = Af*c, max|H^2 - H| = %.1e, trace(H) = %g\n\n', H*yd, max(max(abs(H*H - H))), trace(H));

%% 8. DFT matrix F4: F'*F = 4 I
n = (0:3);
F = exp(-2i*pi*n.'*n/4);        % F(k+1,n+1) = exp(-j 2 pi k n / 4): entries 1, -j, -1, j
disp('F4 ='); disp(round(F));   % round removes 1e-16 residue in printing
disp('F4''*F4 ='); disp(round(real(F'*F)*1e12)/1e12);
xf = [1; 2; 0; -1];
Fx = F*xf; Fx(abs(Fx) < 1e-12) = 0; Fx = round(Fx*1e12)/1e12;   % clean 1e-16 rounding residue for printing
fprintf('F*x    = %s\nfft(x) = %s\n', mat2str(Fx.', 4), mat2str(fft(xf).', 4));
fprintf('||F*x||^2 = %g = 4*||x||^2 = %g\n\n', norm(F*xf)^2, 4*norm(xf)^2);

%% 9. Convolution as a Toeplitz matrix
h  = [2; 1; -1];                % 3-tap pulse
xr = [1; 0; 0; 2; 0];           % reflectivity: two scatterers
T  = toeplitz([h; zeros(4,1)], [h(1) zeros(1,4)]);   % (5+3-1) x 5 = 7x5
pm('T = toeplitz([h; 0 0 0 0], [h(1) 0 0 0 0])', T);
fprintf('T*x       = [%s]\nconv(h,x) = [%s]\n\n', num2str((T*xr).', '%g '), num2str(conv(h, xr).', '%g '));

%% 10. kron: a per-element operator on stacked channel data d = X(:)
X  = [1 2; 3 4; 5 6];           % 3 time samples x 2 elements
d  = X(:);                      % stacked element by element
Dp = diag([1, -1i]);            % phase screen: element 2 delayed by a quarter period (phase -pi/2)
K  = kron(Dp, eye(3));          % 6x6, block diagonal
dab = K*d;
fprintf('kron(D, I3)*d = %s\n', mat2str(dab.', 3));
fprintf('equals vec(X*D): %d; correction kron(D'', I3) restores d: max err %.1e\n\n', ...
        isequal(dab, reshape(X*Dp, [], 1)), max(abs(kron(Dp', eye(3))*dab - d)));

%% 11. A tiny DAS operator: 2 pixels x (4 samples x 3 elements), linear interpolation
Nt = 4; Ne = 3;
tau = [2.5 2.0 2.5;             % pixel 1: delay per element, in samples (1-based, illustrative)
       3.25 3.0 3.25];          % pixel 2 (deeper)
rr = []; cc = []; ww = [];
for p = 1:2
    for e = 1:Ne
        n0 = floor(tau(p,e)); fr = tau(p,e) - n0;
        rr = [rr p p]; cc = [cc (e-1)*Nt+n0, (e-1)*Nt+n0+1]; ww = [ww 1-fr fr];
    end
end
keep = ww > 0;                  % drop zero weights (integer delays)
Bd = sparse(rr(keep), cc(keep), ww(keep), 2, Nt*Ne);
pm('full(B)', full(Bd));
fprintf('nnz(B) = %d of %d entries\n', nnz(Bd), numel(Bd));
dd = full(Bd(1,:)).';           % channel data of a unit scatterer at pixel 1 (H = B'' model)
pm('X = reshape(d, 4, 3)', reshape(dd, Nt, Ne));
fprintf('img = B*d = [%g %g]\n', full(Bd*dd));
pm('B*B'' (PSF matrix: column 1 = image of pixel 1)', full(Bd*Bd'));

%% 12. Why backslash and not inv: an ill-conditioned example
Hh = hilb(10); xt = ones(10,1); bh = Hh*xt;
xb = Hh \ bh; xi = inv(Hh)*bh;
fprintf('hilb(10): cond = %.1e\n', cond(Hh));
fprintf('  A\\b     : residual %.1e, error %.1e\n', norm(Hh*xb - bh)/norm(bh), norm(xb - xt)/norm(xt));
fprintf('  inv(A)*b: residual %.1e, error %.1e\n', norm(Hh*xi - bh)/norm(bh), norm(xi - xt)/norm(xt));

%% 13. Figure: structure of the operators
figure;
mats = {A, abs(R), real(F), T, abs(K), full(Bd)};
ttl  = {'A (general 3x3)', '|Z^H Z| (rank 2)', 'Re F_4', 'Toeplitz T (7x5)', '|kron(D, I_3)|', 'DAS B (2 x 12)'};
for k = 1:6
    subplot(2,3,k); imagesc(mats{k}); colorbar; title(ttl{k}); xlabel('column j'); ylabel('row i');
    if k < 6, axis image; end
end
colormap(gray);

What to look for. A*x = [4 3 −2] from both pictures; A*B − B*A is nonzero (max |entry| 5); z.'*z = 0 but z'*z = 2; eig(Z'*Z) = 10.98, 2.52, 0 (rank 2 from 2 snapshots); det(A) = 24 and round(24*inv(A)) is an integer matrix; tall fit slope −0.98 dB/MHz with Af'*r ≈ 1e−14; svd(M) ends in ~1e−17; F4'*F4 = 4*eye(4); T*x = conv(h,x) = [2 1 −1 4 2 −2 0]; B*d = [2 0.75]. The last block shows backslash vs inv on hilb(10): equal forward error (≈ 5e−4), residual 1.5e−16 vs 4.4e−5.

m05_convolution_matrix.mConvolution as a Toeplitz matrix for a 5 MHz, 60% pulse; circulant embedding diagonalized by the DFT; wrap-around without padding; direct vs FFT cost · change f0, frac_bw, N, Nc · runtime ≈ 2 s
%% m05_convolution_matrix.m  Module 05: convolution is a Toeplitz matrix, the DFT diagonalizes circulants
% Purpose : build the Toeplitz convolution matrix T of a Gaussian-modulated pulse h,
%           verify T*x == conv(h,x); embed it in a circulant C, show that the DFT
%           matrix diagonalizes C with fft(first column) on the diagonal, and show
%           the circular wrap-around error when the circulant is too small.
% Change  : f0, frac_bw, fs (pulse); N (signal length); Nc (circulant size).
% Expect  : square 6x6 window: T6*x6 = first 6 samples of conv, last 3 lost;
%           max|T*x - conv(h,x)| = 0; max off-diagonal |F C F'/Nc| ~ 1e-15;
%           with Nc = N the circular result differs from linear conv in the first L-1 samples;
%           direct vs FFT convolution of a 2048-sample line cross over near L ~ 100 taps.
% Runtime : ~1 s.  Base MATLAB only; runs in MATLAB R2019b+ and GNU Octave 8.
rng(1);

%% 1. A square 6x6 convolution window (h has 4 taps): the full result needs 6+4-1 = 9 rows
h4 = [-0.23; -0.62; 0.62; 0.23];         % sampled Gaussian-modulated sine, zero mean
x6 = [1; 0; 0; 0.5; 0; -1];               % sparse reflectivity, 6 samples
T6 = zeros(6,6);
for j = 1:6                               % column j = h shifted down by j-1 (truncated at 6 rows)
    rows = j:min(6, j+3);
    T6(rows, j) = h4(1:numel(rows));
end
disp('T6 (lower-triangular Toeplitz, T(i,j) = h(i-j+1)) ='); disp(T6);
yfull = conv(h4, x6);                     % full linear convolution: 6 + 4 - 1 = 9 samples
fprintf('T6*x6         = [%s]\n', num2str((T6*x6).', '%7.3f'));
fprintf('conv(h,x)(1:6)= [%s]\n', num2str(yfull(1:6).', '%7.3f'));
fprintf('tail conv(7:9)= [%s]  (lost by the square 6x6 window)\n', num2str(yfull(7:9).', '%7.3f'));

%% 2. A realistic pulse: f0 = 5 MHz, 60 percent -6 dB bandwidth, fs = 40 MHz
f0 = 5e6; frac_bw = 0.6; fs = 40e6;       % Hz, fraction, Hz
sig_f = frac_bw*f0/2 / sqrt(2*log(2));    % std of the Gaussian amplitude spectrum (Hz)
sig_t = 1/(2*pi*sig_f);                   % std of the Gaussian envelope (s)
t = (-ceil(3*sig_t*fs):ceil(3*sig_t*fs)).' / fs;   % +-3 sigma_t
h = exp(-t.^2/(2*sig_t^2)) .* cos(2*pi*f0*t);     % RF pulse
L = numel(h);
fprintf('pulse: sigma_t = %.4f us, L = %d taps at %.0f MHz\n', sig_t*1e6, L, fs/1e6);

%% 3. Full Toeplitz convolution matrix, (N+L-1) x N
N = 64;                                   % signal length (samples)
x = zeros(N,1); x([10 25 26 47]) = [1 -0.6 0.8 0.5];   % four scatterers
T = zeros(N+L-1, N);
for j = 1:N
    T(j:j+L-1, j) = h;                    % every column is the pulse, shifted by one sample
end
fprintf('T is %d x %d, %d nonzeros (%.1f %% dense), Toeplitz: T(i,j) depends only on i-j\n', ...
        size(T,1), size(T,2), nnz(T), 100*nnz(T)/numel(T));
fprintf('max|T*x - conv(h,x)| = %.1e\n', max(abs(T*x - conv(h,x))));

%% 4. Circulant embedding: zero-pad to Nc >= N+L-1 and linear = circular convolution
Nc = N + L - 1;
cfirst = [h; zeros(Nc-L,1)];              % first column of the circulant
C = zeros(Nc);
for j = 1:Nc
    C(:,j) = circshift(cfirst, j-1);      % each column = previous column rotated down by one
end
xp = [x; zeros(Nc-N,1)];
yc = real(ifft(fft(cfirst) .* fft(xp)));  % FFT convolution
fprintf('Nc = %d: max|C*xp - conv| = %.1e, max|ifft(fft.*fft) - conv| = %.1e\n', ...
        Nc, max(abs(C*xp - conv(h,x))), max(abs(yc - conv(h,x))));

%% 5. The DFT matrix diagonalizes the circulant
F = fft(eye(Nc));                         % DFT matrix: F(k+1,n+1) = exp(-2i*pi*k*n/Nc)
fprintf('F''*F = Nc*I: max|F''*F/Nc - I| = %.1e\n', max(max(abs(F'*F/Nc - eye(Nc)))));
Dg = F * C * F' / Nc;                     % should be diag(fft(cfirst))
offd = Dg - diag(diag(Dg));
fprintf('max off-diagonal |F C F''/Nc| = %.1e, max|diag - fft(c)| = %.1e\n', ...
        max(abs(offd(:))), max(abs(diag(Dg) - fft(cfirst))));
fprintf('eigenvalues of C = fft(c): |lambda| max %.3f at %.2f MHz\n', ...
        max(abs(fft(cfirst))), (find(abs(fft(cfirst)) == max(abs(fft(cfirst))), 1) - 1)*fs/Nc/1e6);

%% 6. Too small a circulant: circular wrap-around (time aliasing)
Ns = N;                                   % no zero padding
cs = [h; zeros(Ns-L,1)];
ycirc = real(ifft(fft(cs) .* fft(x)));
ylin = conv(h, x);
err = abs(ycirc - ylin(1:Ns));
fprintf('Nc = N = %d: max wrap error = %.3f in samples 1..%d, %.1e afterwards\n', ...
        Ns, max(err(1:L-1)), L-1, max(err(L:end)));

%% 7. Cost of the two routes for one RF line
Nrf = 2048; Lf = [16 64 256];
for k = 1:3
    Nfft = 2^nextpow2(Nrf + Lf(k) - 1);
    direct = Nrf * Lf(k);                                 % real multiply-adds
    viafft = 2 * 2*Nfft*log2(Nfft) + 4*Nfft;              % 2 real-equivalent FFTs (~2 N log2 N real mults each) + products
    fprintf('L = %3d: direct %7d MACs, FFT route ~%7d mults (Nfft = %d)\n', Lf(k), direct, round(viafft), Nfft);
end

%% 8. Figures
figure;
subplot(2,2,1); imagesc(T); colorbar; title('Toeplitz T (N+L-1 x N)'); xlabel('input sample j'); ylabel('output sample i');
subplot(2,2,2); imagesc(C); axis image; colorbar; title('circulant C (wraps at the corner)'); xlabel('column'); ylabel('row');
subplot(2,2,3); imagesc(20*log10(abs(Dg)/max(abs(Dg(:))) + 1e-12)); axis image; colorbar;
caxis([-300 0]); title('|F C F^H / N_c| (dB): diagonal'); xlabel('column k'); ylabel('row k');
subplot(2,2,4); plot(0:numel(ylin)-1, ylin, 'k', 0:Ns-1, ycirc, 'r--');
xlabel('sample'); ylabel('amplitude'); title('linear (black) vs circular N_c = N (red)');
colormap(gray);

What to look for. L = 31 taps at 40 MHz (\(\sigma_{t} = 0.125\) µs); T is 94 × 64 and 33% dense; max|T*x − conv| ≈ 1e−16; \(F C F^{H}/N_{c}\) is diagonal to 2e−15 with fft(c) on the diagonal; with \(N_{c} = N\) the first 30 samples carry a wrap error of 0.363; the FFT route (≈ 213 k multiplies) beats direct convolution for L above about 100 taps.

m05_das_as_matrix.mSparse DAS operator for 32 elements and a 0° plane wave; image as one product B*d; adjoint B' as back-projection; dot test; B' vs the true echo · change Ne, pixel grid, apodization · runtime ≈ 2 s
%% m05_das_as_matrix.m  Module 05: delay-and-sum as a sparse matrix, and its adjoint
% Purpose : build the DAS operator B (pixels x channel samples) for a 32-element
%           linear array and a 0-degree plane-wave transmit, with linear-interpolation
%           weights (2 nonzeros per element per pixel); apply it to simulated
%           point-target channel data; show that B' (the adjoint) maps an image back to
%           channel data along hyperbolas; check <B d, g> = <d, B' g>; spy(B) and density.
% Change  : Ne, pitch, the pixel grid (dxp), apod ('rect' or 'hann'), the targets.
% Expect  : B is 6161 x 43520 with 64 nonzeros per row (0.147 percent dense);
%           dot-test mismatch ~1e-15; lateral -6 dB width at z = 18 mm close to
%           1.21*lambda*z/D = 0.70 mm (rect); pulse-filtered B' column vs true echo
%           correlation ~0.99 (B is H^H up to the pulse matched filter).
% Runtime : ~3 s.  Base MATLAB only; runs in MATLAB R2019b+ and GNU Octave 8.
rng(1);

%% 1. System and grid
c = 1540;  f0 = 5e6;  fs = 40e6;  frac_bw = 0.6;    % m/s, Hz, Hz, -6 dB fractional bandwidth
lambda = c/f0;                                      % 0.308 mm
Ne = 32;   pitch = 0.3e-3;                          % elements, m
xe = ((0:Ne-1) - (Ne-1)/2) * pitch;                 % element x positions (m), aperture D = 9.6 mm
D = Ne*pitch;
apod = 'rect';
if strcmp(apod, 'hann'), we = sin(pi*((0:Ne-1) + 0.5)/Ne).^2; else, we = ones(1, Ne); end
dxp = 0.1e-3;                                       % pixel size (m), about lambda/3
xg = -3e-3:dxp:3e-3;  zg = 15e-3:dxp:25e-3;         % 61 x 101 pixels
[Xp, Zp] = meshgrid(xg, zg);  Np = numel(Xp);
Nt = 1360;                                          % samples per channel (34 us at 40 MHz)
t = (0:Nt-1).'/fs;
fprintf('lambda = %.3f mm, D = %.1f mm, pixels = %d x %d = %d, channel samples = %d x %d = %d\n', ...
        lambda*1e3, D*1e3, numel(zg), numel(xg), Np, Nt, Ne, Nt*Ne);

%% 2. Build the sparse DAS matrix B: row p = pixel p, column (e-1)*Nt + n = sample n of element e
Ip = zeros(2*Ne*Np, 1); Jc = Ip; Vw = Ip; k = 0;
for e = 1:Ne
    tau = (Zp(:) + sqrt((Xp(:) - xe(e)).^2 + Zp(:).^2)) / c;   % two-way delay, 0-degree plane wave (s)
    u = tau*fs;                                                 % fractional sample index (0-based)
    n0 = floor(u);  fr = u - n0;                                % neighbours n0, n0+1 and weights
    ok = n0 >= 0 & n0 + 1 <= Nt - 1;
    idx = find(ok);  m = numel(idx);
    Ip(k+1:k+m) = idx;        Jc(k+1:k+m) = (e-1)*Nt + n0(idx) + 1;  Vw(k+1:k+m) = we(e)*(1 - fr(idx));  k = k + m;
    Ip(k+1:k+m) = idx;        Jc(k+1:k+m) = (e-1)*Nt + n0(idx) + 2;  Vw(k+1:k+m) = we(e)*fr(idx);        k = k + m;
end
B = sparse(Ip(1:k), Jc(1:k), Vw(1:k), Np, Nt*Ne);
fprintf('B: %d x %d, nnz = %d (%.0f per row), density = %.3f %%\n', size(B,1), size(B,2), nnz(B), nnz(B)/Np, 100*nnz(B)/numel(B));
fprintf('memory: sparse ~%.1f MB vs dense %.1f GB (double)\n', nnz(B)*16/1e6, numel(B)*8/1e9);

%% 3. Simulate analytic channel data for three point targets (single scattering)
sig_f = frac_bw*f0/2/sqrt(2*log(2));  sig_t = 1/(2*pi*sig_f);    % Gaussian pulse, s
g = @(tt) exp(-tt.^2/(2*sig_t^2)) .* exp(2i*pi*f0*tt);          % analytic pulse
tg = [0 18; -1.5 20; 1.5 23]*1e-3;                              % targets [x z] (m)
d = zeros(Nt, Ne);
for s = 1:size(tg,1)
    for e = 1:Ne
        tau = (tg(s,2) + sqrt((tg(s,1) - xe(e))^2 + tg(s,2)^2))/c;
        d(:,e) = d(:,e) + g(t - tau);
    end
end
d = d + 0.01*(randn(Nt,Ne) + 1i*randn(Nt,Ne))/sqrt(2);         % weak white noise

%% 4. Beamform: one sparse matrix-vector product
img = B * d(:);                                 % complex image, Np x 1
I = reshape(abs(img), numel(zg), numel(xg));
IdB = 20*log10(I/max(I(:)));
% lateral -6 dB width at the first target
[~, iz] = min(abs(zg - 18e-3));  prof = I(iz,:)/max(I(iz,:));
[~, im] = max(prof);  l = im; while prof(l) > 0.5, l = l - 1; end;  r = im; while prof(r) > 0.5, r = r + 1; end
xl = xg(l) + (0.5 - prof(l))/(prof(l+1) - prof(l))*dxp;  xr = xg(r-1) + (0.5 - prof(r-1))/(prof(r) - prof(r-1))*dxp;
fprintf('lateral -6 dB width at z = 18 mm: %.2f mm (theory 1.21 lambda z / D = %.2f mm)\n', (xr - xl)*1e3, 1.21*lambda*18e-3/D*1e3);

%% 5. The adjoint B' maps an image back to channel data (back-projection)
dback = reshape(B' * img, Nt, Ne);              % every pixel re-emits its value along its own hyperbola
% dot test: <B d, g> must equal <d, B' g> for any d, g
dr = randn(Nt*Ne,1) + 1i*randn(Nt*Ne,1);  gr = randn(Np,1) + 1i*randn(Np,1);
lhs = gr' * (B*dr);  rhs = (B'*gr)' * dr;
fprintf('dot test |<Bd,g> - <d,B''g>| / |<Bd,g>| = %.1e\n', abs(lhs - rhs)/abs(lhs));

%% 6. B is H^H up to the pulse matched filter: compare B' e_j (pulse-filtered) with H e_j
[~, j] = min(abs(Xp(:) - 0) + abs(Zp(:) - 20e-3));            % pixel at (0, 20 mm)
aj = reshape(full(B(j,:)).', Nt, Ne);           % B' e_j: two-tap kernels on the hyperbola of pixel j
tp = (-ceil(4*sig_t*fs):ceil(4*sig_t*fs)).'/fs; gp = g(tp);
ajf = zeros(Nt, Ne);  hj = zeros(Nt, Ne);
for e = 1:Ne
    full_c = conv(aj(:,e), gp);  ajf(:,e) = full_c((1:Nt) + (numel(gp)-1)/2);   % 'same'-centred convolution
    tau = (Zp(j) + sqrt((Xp(j) - xe(e))^2 + Zp(j)^2))/c;  hj(:,e) = g(t - tau);  % H e_j: true echo of a point at pixel j
end
rho = abs(ajf(:)'*hj(:)) / (norm(ajf(:))*norm(hj(:)));
fprintf('|corr(pulse * B''e_j, H e_j)| = %.4f\n', rho);

%% 7. Figures
figure;
subplot(2,2,1); imagesc(1:Ne, t*1e6, real(d)); colorbar; xlabel('element'); ylabel('time (\mus)'); title('channel data d (real part)'); ylim([22 32]);
subplot(2,2,2); imagesc(xg*1e3, zg*1e3, IdB); caxis([-40 0]); axis image; colorbar;
xlabel('x (mm)'); ylabel('z (mm)'); title('image |B d| (dB)');
ix0 = find(abs(xg) < dxp/2);  rows0 = (ix0-1)*numel(zg) + (1:numel(zg));   % the 101 pixels of the x = 0 image column
subplot(2,2,3); spy(B(rows0, 1:4*Nt)); xlabel('column (e-1) N_t + n, elements 1-4'); ylabel('pixel (x = 0, z = 15..25 mm)');
title('spy(B): delay curves, 2 taps per element');
subplot(2,2,4); imagesc(1:Ne, t*1e6, abs(dback)); colorbar; xlabel('element'); ylabel('time (\mus)'); title('|B^H B d|: back-projection'); ylim([22 32]);
colormap(gray);

What to look for. B is 6161 × 43 520 with 64 nonzeros per row (0.147% dense, ≈ 6 MB sparse vs 2.1 GB dense); the lateral −6 dB width at 18 mm is 0.71 mm against 1.21λz/D = 0.70 mm; the dot test \(\lvert \langle Bd, g\rangle - \langle d, B^{H}g\rangle \rvert / \lvert \langle Bd, g\rangle\rvert\) is about 3e−15; the pulse-filtered row of B correlates with the true echo of that pixel at 0.9995 (\(B \approx H^{H}\)).

m05_least_squares_conditioning.mAttenuation-slope fit by \, pinv, QR and normal equations; outlier; column scaling; κ² of AᵀA; κ = cot(φ/2); Monte Carlo noise along v₂; Tikhonov bias–variance · change sig_dB, phi_deg, lambdas · runtime ≈ 2 s
%% m05_least_squares_conditioning.m  Module 05: least squares, conditioning, noise amplification
% Purpose : fit an attenuation slope (dB vs MHz) with A\b, pinv and QR; show why
%           centering and scaling the columns matters; show that the normal equations
%           square kappa; tabulate kappa vs column angle; Monte Carlo the noise
%           amplification along the weak singular direction; Tikhonov teaser.
% Change  : sig_dB (spectral noise), the outlier, phi_deg (column angle), lambda grid.
% Expect  : slope ~ -1 dB/MHz, SE = 0.0666 dB/MHz, outlier shift +0.203 dB/MHz;
%           kappa = cot(phi/2): 57.3 at 2 deg, 11.43 at 10 deg; Monte Carlo std along
%           v2 within ~3 percent of sigma/sigma_2; order-7 raw-f fit: relative error ~1e-7
%           with QR, ~1e-2 with the normal equations; Tikhonov at lambda = sigma_2^2
%           halves the v2 noise (0.08 -> 0.04).
% Runtime : ~2 s.  Base MATLAB only; runs in MATLAB R2019b+ and GNU Octave 8.
rng(1);

%% 1. Spectral-difference attenuation model
% log-ratio of power spectra between two depths, dB:  y(f) = y0 - 2*alpha0*dz*f
alpha0 = 0.5;            % dB/cm/MHz (one-way, amplitude)
dz = 1.0;                % cm between the two windows
f = linspace(2, 8, 25).';                % MHz, 25 frequencies
ytrue = 2 - 2*alpha0*dz*f;               % slope -1 dB/MHz (round trip: factor 2)
sig_dB = 0.6;                            % noise std per frequency, dB
y = ytrue + sig_dB*randn(size(f));

A = [ones(size(f)) f];                   % columns: intercept, slope
c_bs   = A \ y;                          % QR-based least squares (what backslash does for tall A)
c_pinv = pinv(A) * y;                    % SVD-based pseudo-inverse
[Q, R] = qr(A, 0);                       % economy QR: A = Q*R, Q'*Q = I
c_qr   = R \ (Q' * y);
c_ne   = (A'*A) \ (A'*y);                % normal equations (fine here, kappa small)
fprintf('slope: \\ %.4f | pinv %.4f | QR %.4f | normal eq %.4f dB/MHz (truth -1)\n', ...
        c_bs(2), c_pinv(2), c_qr(2), c_ne(2));
fprintf('alpha0 estimate = %.3f dB/cm/MHz (truth %.2f)\n', -c_bs(2)/(2*dz), alpha0);
r = y - A*c_bs;
fprintf('residual orthogonal to the columns: max|A''*r| = %.1e\n', max(abs(A'*r)));
SE = sig_dB / sqrt(sum((f - mean(f)).^2));
fprintf('slope standard error sigma/sqrt(sum (f-fbar)^2) = %.4f dB/MHz\n', SE);
Cx = sig_dB^2 * inv(A'*A);               % covariance of the estimate (inv is fine for a 2x2 readout)
fprintf('same from sqrt(sigma^2 (A''A)^-1)(2,2) = %.4f\n', sqrt(Cx(2,2)));

%% 2. One outlier (+6 dB at 7.75 MHz)
yo = y; [~, io] = min(abs(f - 7.75)); yo(io) = yo(io) + 6;
co = A \ yo;
fprintf('outlier at %.2f MHz moves the slope by %+.3f dB/MHz (= %.1f SE); theory 6*(f_i - fbar)/Sxx = %+.3f\n', ...
        f(io), co(2) - c_bs(2), (co(2) - c_bs(2))/SE, 6*(f(io) - mean(f))/sum((f - mean(f)).^2));

%% 3. Column scaling: raw f versus centered t = (f-5)/3
At = [ones(size(f)) (f - 5)/3];
fprintf('cond([1 f]) = %.2f, cond([1 (f-5)/3]) = %.2f\n', cond(A), cond(At));
for p = [3 5 7]
    Araw = zeros(numel(f), p+1); Acen = Araw;
    for k = 0:p, Araw(:,k+1) = f.^k; Acen(:,k+1) = ((f - 5)/3).^k; end
    fprintf('order %d: cond raw = %.1e, centered = %.1f\n', p, cond(Araw), cond(Acen));
end

%% 4. Normal equations square kappa: order-7 polynomial in raw f, noise-free data
p = 7; Araw = zeros(numel(f), p+1);
for k = 0:p, Araw(:,k+1) = f.^k; end
ct = ones(p+1, 1); bt = Araw * ct;       % exact data, known answer
c1 = Araw \ bt;                          % QR
c2 = (Araw'*Araw) \ (Araw'*bt);          % normal equations
fprintf('order 7 raw: cond(A) = %.1e, cond(A''A) = %.1e (= cond(A)^2 = %.1e)\n', cond(Araw), cond(Araw'*Araw), cond(Araw)^2);
fprintf('  relative error: QR %.1e, normal equations %.1e\n', norm(c1 - ct)/norm(ct), norm(c2 - ct)/norm(ct));
fprintf('  digits lost ~ log10(kappa): QR %.1f, normal eq %.1f\n', log10(cond(Araw)), log10(cond(Araw)^2));

%% 5. kappa versus the angle between two unit columns
phis = [90 30 10 5 2];
fprintf('phi(deg)  kappa   cot(phi/2)\n');
for ph = phis
    Ap = [1 cosd(ph); 0 sind(ph)];
    fprintf('%6g  %7.2f  %7.2f\n', ph, cond(Ap), cotd(ph/2));
end

%% 6. Monte Carlo: noise is amplified only along the weak direction v2
phi_deg = 10; sig = 0.01; M = 4000;
Ap = [1 cosd(phi_deg); 0 sind(phi_deg)];
[U, S, V] = svd(Ap); s = diag(S);
xt = [1; 1]; bp = Ap*xt;
Xhat = Ap \ (bp + sig*randn(2, M));     % M solves at once
E = Xhat - xt;
std_v = std(V.' * E, 0, 2);              % std of the error along v1 and v2
fprintf('phi = %g deg: sigma = [%.4f %.4f], std along v1 = %.4f (theory %.4f), v2 = %.4f (theory %.4f)\n', ...
        phi_deg, s, std_v(1), sig/s(1), std_v(2), sig/s(2));

%% 7. Tikhonov teaser: (A'A + lambda I)^-1 A'b
% The bias is lambda/(sigma_i^2 + lambda) times the component of the truth along v_i.
% x = (1,1) lies exactly along v1 (equal unit columns), so shrinking v2 costs it no bias;
% x = (1,0) has a v2 component, so the same lambda buys less.
lams = [0 1e-4 1e-3 s(2)^2 1e-1 1];
truths = [1 1; 1 0].';
rmse = zeros(2, numel(lams));
for q = 1:2
    xq = truths(:,q); bq = Ap*xq; Nq = sig*randn(2, M);
    fprintf('truth x = (%g, %g): v2''x = %+.3f\n', xq, V(:,2).'*xq);
    fprintf('  lambda     f2      std_v2   bias    RMSE\n');
    for k = 1:numel(lams)
        lam = lams(k);
        Mreg = (Ap'*Ap + lam*eye(2)) \ Ap';
        Er = Mreg * (bq + Nq) - xq;
        f2 = s(2)^2/(s(2)^2 + lam);
        rmse(q,k) = sqrt(mean(sum(Er.^2, 1)));
        fprintf('  %8.1e  %5.3f  %7.4f  %6.4f  %6.4f\n', lam, f2, std(V(:,2).'*Er), norm(mean(Er, 2)), rmse(q,k));
    end
end

%% 8. Figures
figure;
subplot(2,2,1);
plot(f, y, 'ko', f, A*c_bs, 'b-', f, ytrue, 'k--', f(io), yo(io), 'rs', f, A*co, 'r-');
xlabel('frequency (MHz)'); ylabel('log-spectral ratio (dB)'); title('LS fit; red: with outlier');
subplot(2,2,2);
plot(E(1,:), E(2,:), '.', 'markersize', 2); axis equal;
hold on; tt = linspace(0, 2*pi, 200);
el = V * diag(2*sig./s) * [cos(tt); sin(tt)]; plot(el(1,:), el(2,:), 'r-', 'linewidth', 1.5); hold off;
xlabel('error in x_1'); ylabel('error in x_2'); title(sprintf('error cloud, phi = %g deg', phi_deg));
subplot(2,2,[3 4]);
semilogx(max(lams, 1e-5), rmse(1,:), 'o-', max(lams, 1e-5), rmse(2,:), 's-');
xlabel('\lambda (0 plotted at 1e-5)'); ylabel('RMSE of x'); legend('x = (1,1)', 'x = (1,0)');
title('Tikhonov RMSE');

What to look for. Slope −1.002 dB/MHz with SE 0.0666; the outlier shifts it by +0.203 dB/MHz (3.1 SE); cond([1 f]) = 16.2 vs 1.66 centered; order-7 raw fit: κ = 2.6e9, error 1.2e−7 with QR and 1.8e−2 with the normal equations; κ matches cot(φ/2) at every angle; Monte Carlo std along \(v_{2}\) 0.0817 vs theory 0.0811; at \(\lambda = \sigma_{2}^{2}\) the \(v_{2}\) noise halves, harmless for x = (1, 1) but RMSE 0.082 → 0.355 for x = (1, 0).

05.14Self-check

Q1For x = (1, i) and y = (i, 1), compute \(x^{T}x, x^{H}x, y^{T}x\) and \(y^{H}x\). Are x and y orthogonal?

\(x^{T}x = 1 + i^{2} = 0\) and \(x^{H}x = 1 + 1 = 2\), so only the conjugated version is a norm. \(y^{T}x = i\cdot 1 + 1\cdot i = 2i\), but \(y^{H}x = (-i)(1) + (1)(i) = 0\). Under the correct complex inner product x and y are orthogonal; dropping the conjugate would wrongly report a correlation of magnitude 2.

Q2Project b = (3, 4) onto a = (1, 1). Give p, the residual, its norm, and the projector matrix.

\(c = a^{T}b/a^{T}a = 7/2\), so p = (3.5, 3.5) and r = (−0.5, 0.5), \(\lVert r\rVert = 0.707\). Check \(a^{T}r = -0.5 + 0.5 = 0\) and \(\lVert p\rVert^{2} + \lVert r\rVert^{2}\) \(= 24.5 + 0.5\) \(= 25\) \(= \lVert b\rVert^{2}\). \(P = aa^{T}/a^{T}a = \tfrac{1}{2}\begin{bmatrix}1 & 1\\ 1 & 1\end{bmatrix}\); \(P^{2} = P\), eigenvalues 1 (along a) and 0 (along (1, −1)), det P = 0.

Q3Compute κ for A = [1 1; 1 1.01]. If b is known to 0.1% (relative), how large can the relative error in x be?

A is symmetric positive definite, so \(\sigma_{i} = \lambda_{i}\). \(\operatorname{tr} = 2.01\), \(\det = 0.01\), \(\lambda\) \(= 1.005 \pm \sqrt{1.005^{2} - 0.01}\) \(= 1.005 \pm 1.0000125\), giving 2.00501 and 0.0049875. κ = 2.00501/0.0049875 ≈ 402. The bound gives up to 402 × 0.1% ≈ 40% relative error in x. Note det = 0.01 alone says nothing; 0.1·I also has det 0.01 and κ = 1.

Q4Two unit-norm columns are 10° apart. What are \(\sigma_{1}, \sigma_{2}\) and κ, and what is the noise std of \(\hat{x}\) along the weak direction for σ = 0.01 noise on b? What does Tikhonov with \(\lambda = \sigma_{2}^{2}\) do to it?

\(\sigma_{1,2} = \sqrt{1 \pm \cos 10^{\circ}} = \sqrt{1.98481}= 1.4088\) and \(\sqrt{0.015192}= 0.12326\); κ = cot 5° = 11.43. Along \(v_{2}\) the std is \(\sigma /\sigma_{2} = 0.01/0.12326 = 0.081\) (along \(v_{1}\) only 0.0071). With \(\lambda = \sigma_{2}^{2} = 0.015192\): \(f_{2}\) = ½, std \(\sigma \sigma_{2}/(\sigma_{2}^{2} + \lambda)\) = 0.01·0.12326/0.030384 = 0.041 (halved), and the \(v_{2}\) component of x is shrunk by 50% (bias). These follow from (05.14) and (05.16); Demo 05.6 at φ = 10° reproduces them.

Q5Fit \(y = c_{0} + c_{1}x\) to the points (0, 1), (1, 2), (2, 2) by the normal equations. Verify that the residual is orthogonal to both columns.

\(A = \begin{bmatrix}1 & 0\\ 1 & 1\\ 1 & 2\end{bmatrix},\ A^{T}A = \begin{bmatrix}3 & 3\\ 3 & 5\end{bmatrix},\ A^{T}y = (5, 6)\). det = 6, so \(c_{0} = (5\cdot 5 - 3\cdot 6)/6 = 7/6\) and \(c_{1} = (3\cdot 6 - 3\cdot 5)/6 = 1/2\). Predictions 7/6, 5/3, 13/6, residual r = (−1/6, 1/3, −1/6). Column 1: sum = 0. Column 2: 0 + 1/3 − 2/6 = 0. \(\lVert r\rVert^{2} = 1/6\).

Q6A DAS operator maps 2048 samples × 128 elements to a 256 × 256 image. Bound its rank and its null-space dimension, and describe a vector in the null space.

n = 262 144 inputs, m = 65 536 outputs, so r ≤ 65 536 and dim N(B) ≥ 262 144 − 65 536 = 196 608. At least 75% of the channel-data space is invisible to the beamformer: for example, energy placed at sample–element combinations that lie on no pixel's delay curve, or patterns whose weighted sums along every delay curve cancel. Noise components in N(B) never reach the image, which is one way to see the SNR gain of beamforming.

Q7A 5 MHz plane wave arrives at θ = 10° on a 128-element array with 0.3 mm pitch (c = 1540 m/s). Which DFT bin does it fall in, and what is the largest unaliased steering angle at 5 and 7.5 MHz?

λ = 0.308 mm, \(k_{\theta}\) = Np sin θ/λ = 128 · 0.3 · 0.17365/0.308 = 21.65, between bins 21 and 22, so its energy leaks over neighboring bins. Unaliased range |sin θ| < λ/(2p): arcsin(0.5133) = 30.9° at 5 MHz; at 7.5 MHz λ = 0.2053 mm, arcsin(0.342) = 20.0°. Demo 05.7 shows the peak at k ≈ 22 and the wrap past 30.9°.

Q8A 2×2 system has σ = (2, 0.02). Compare noise amplification along \(v_{2}\) without regularization and with λ = 0.01, and give the filter factors.

Unregularized: std along \(v_{2} = \sigma_{n}/0.02 = 50\sigma_{n}\). With λ = 0.01: \(f_{1} = 4/4.01 = 0.9975\) (\(v_{1}\) nearly untouched), \(f_{2}\) = 0.0004/0.0104 = 0.038; std along \(v_{2} = \sigma_{n} \cdot 0.02/0.0104 = 1.92\sigma_{n}\), a 26× reduction, at the cost of removing 96% of the true \(v_{2}\) component. Whether that trade is good depends on how large \(v_{2}^{T}x\) is compared with \(50\sigma_{n}\).

05.15Figures from the literature

Published figures with real data that show the operators of this module at work. Links only; open the figure next to the section it illustrates. Where a free preprint exists, figure numbers are those of the version linked.

DAS as a sparse matrix, and what a wrong sound speed does to real images

V. Perrot, M. Polichetti, F. Varray, D. Garcia, “So you think you can DAS? A viewpoint on delay-and-sum beamforming,” Ultrasonics 111, 106309 (2021). doi:10.1016/j.ultras.2020.106309; open preprint arXiv:2007.11960. Figs. 7, 8 and 11 (preprint numbering).

Fig. 7 is the authors’ example of a sparse DAS matrix: beamforming written as a sparse matrix–vector product, the operator \(B\) of (05.21). Fig. 8 shows in vitro results in a CIRS phantom from the PICMUS data set: how speed of sound and f-number change CNR and the lateral FWHM measured on nylon wires. Fig. 11 is an in vivo carotid where the directivity-derived f-number was 1.4 and the estimated speed of sound 1400 m/s instead of the assumed 1540 m/s. Read the speed-of-sound sweep as a family of matrices \(B(c)\): the nonzero count per row is unchanged, but the rows move off the true delay curves, so \(BH\) drifts away from \(H^{H}H\) and the PSF columns widen.

Regularized inversion against DAS on experimental and in vivo data

T. Szasz, A. Basarab, D. Kouamé, “Beamforming through regularized inverse problems in ultrasound medical imaging,” IEEE Trans. Ultrason. Ferroelectr. Freq. Control 63(12), 2031–2044 (2016). Open preprint arXiv:1507.08184. Figs. 4, 9, 10 and 11 (preprint numbering).

The paper models the DAS output as \(\hat{\mathbf{s}} = A^{H}A\,\mathbf{x} + \mathbf{g}\) with \(A\) the steering matrix and inverts it with regularized least squares (LS) and basis pursuit (BP). Fig. 4 compares lateral profiles of point reflectors at 65 mm depth (simulation) for DAS, MV, multi-beam Capon, IAA, BP and LS; Fig. 9 shows the same beamformers on experimental carotid data; Figs. 10 and 11 show DAS, BP and LS on in vivo thyroid data, healthy and with a tumour. Look for the trade of §05.6: the inversions undo part of the \(A^{H}A\) blur, and the regularization weight decides how much speckle texture and noise survive.

Pulse-echo sound-speed maps from \(A\,\Delta\mathbf{s} = \Delta\mathbf{t}\): phantoms and a volunteer

P. Stähli, M. Kuriakose, M. Frenz, M. Jaeger, “Improved forward model for quantitative pulse-echo speed-of-sound imaging,” Ultrasonics 108, 106168 (2020). doi:10.1016/j.ultras.2020.106168; open preprint arXiv:1902.10639. Figs. 4 and 7 (preprint v2 numbering).

Fig. 4 shows sound-speed images of a two-layer phantom (liver-mimicking material at 1555 m/s under a fat layer) reconstructed with different forward models (rows) and four a priori sound speeds; Fig. 7 places B-mode and sound-speed images of a healthy volunteer’s abdominal wall side by side. The forward model is the linear operator of (05.22) mapping slowness to echo-phase shifts between transmit/receive angle pairs. Read the rows of Fig. 4 as the same data inverted through different matrices: the accuracy of \(A\), not only the regularizer, decides whether layer values come out right.

The reflection matrix: record in one basis, analyse in another

W. Lambert, L. A. Cobus, T. Frappart, M. Fink, A. Aubry, “Distortion matrix approach for ultrasound imaging of random scattering media,” Proc. Natl. Acad. Sci. USA 117(26), 14645–14656 (2020). Open preprint arXiv:1912.05417. Figs. 2 and 4 (preprint numbering).

Fig. 2(A) sketches the experiment, a transducer array in contact with a plexiglass layer over a tissue-mimicking phantom; (B) is the original confocal image, (C) the image after removal of multiple reflections and (E) after matrix aberration correction, with Strehl-ratio maps in (D) and (F). Fig. 4 builds the distortion matrix by removing the geometrical tilt from each focused wavefront. Every step is a product with propagation matrices that change the basis of the recorded matrix (§05.7): element or plane-wave basis to focused basis and back.

Transducer basis versus plane-wave basis, with a 2D matrix array

F. Bureau, J. Robin, A. Le Ber, W. Lambert, M. Fink, A. Aubry, “Three-dimensional ultrasound matrix imaging,” Nature Communications 14, 6793 (2023). doi:10.1038/s41467-023-42338-8 (open access). Figs. 1 and 2.

Fig. 1(a–c) shows the reflection matrix acquired in the transducer basis or in the plane-wave basis in transmit, and (d) confocal imaging as simultaneous focusing at input and output: the change-of-basis bookkeeping of (05.18) for a matrix probe. Fig. 2 applies it through a pork-tissue aberrating layer, from the experimental schematic to maps of reflection point-spread functions at z = 29 mm. The bases are related by Fourier-like propagation matrices, so the same data can be examined in whichever basis makes the physics sparse.

05.16Go deeper

  • G. Strang, Introduction to Linear Algebra, 5th ed., Wellesley-Cambridge Press, 2016. Ch. 3 (vector spaces, the four subspaces), Ch. 4 (orthogonality, projections, least squares), Ch. 7 (SVD), Ch. 8 (linear transformations).
  • G. Strang, Linear Algebra and Learning from Data, Wellesley-Cambridge Press, 2019. Part I (highlights: column picture, SVD, pseudo-inverse) and Part II (computations with large matrices, least squares, regularization).
  • L. N. Trefethen and D. Bau III, Numerical Linear Algebra, SIAM, 1997. Lectures 6–8 (projectors, QR, Gram–Schmidt), 11 (least squares), 12 (conditioning and condition numbers), 18 (conditioning of least squares).
  • P. C. Hansen, Discrete Inverse Problems: Insight and Algorithms, SIAM, 2010. Filter factors, Tikhonov, truncated SVD: the bridge to batch 2.
  • G. Montaldo, M. Tanter, J. Bercoff, N. Benech, M. Fink, "Coherent plane-wave compounding for very high frame rate ultrasonography and transient elastography," IEEE Trans. Ultrason. Ferroelectr. Freq. Control 56(3), 2009.
  • T. Szasz, A. Basarab, D. Kouamé, "Beamforming through regularized inverse problems in ultrasound medical imaging," IEEE Trans. Ultrason. Ferroelectr. Freq. Control 63(12), 2016. Beamforming posed as a regularized inverse problem on a steering-matrix model of the DAS output, solved by least squares and basis pursuit.
  • W. Lambert, L. A. Cobus, T. Frappart, M. Fink, A. Aubry, "Distortion matrix approach for ultrasound imaging of random scattering media," PNAS 117(26), 2020. Change of basis between element, plane-wave and focused bases.
  • N. J. Higham, Accuracy and Stability of Numerical Algorithms, 2nd ed., SIAM, 2002. Backward stability, why A\b beats inv(A)*b, conditioning of least squares.
  • I. S. Reed, J. D. Mallett, L. E. Brennan, "Rapid convergence rate in adaptive arrays," IEEE Trans. Aerosp. Electron. Syst. AES-10(6), 1974. The K ≈ 2N snapshot rule for sample-covariance inversion.
  • J.-F. Synnevåg, A. Austeng, S. Holm, "Adaptive beamforming applied to medical ultrasound imaging," IEEE Trans. Ultrason. Ferroelectr. Freq. Control 54(8), 2007. Subarray averaging and diagonal loading in ultrasound MV beamforming.
  • M. Jaeger, G. Held, S. Peeters, S. Preisser, M. Grünig, M. Frenz, "Computed ultrasound tomography in echo mode for imaging speed of sound using pulse-echo sonography: proof of principle," Ultrasound Med. Biol. 41(1), 2015. A Δs = Δt in pulse-echo geometry.