quadsv.kernels.fft#

Classes#

FFTKernel

FFT-accelerated spatial kernel for dense grid data.

Functions#

power_spectrum_2d(x[, fft_solver, workers])

Compute the 2D power spectrum \(|\hat{x}(k)|^2\) of one or more grid signals.

Module Contents#

class quadsv.kernels.fft.FFTKernel(shape, spacing=(1.0, 1.0), topology='square', method='matern', workers=None, fft_solver='fft2', *, centering=True, **kwargs)[source]#

Bases: quadsv.kernels.base.Kernel

FFT-accelerated spatial kernel for dense grid data.

Operates on evenly-spaced grid data (raster data) with spectral decomposition via FFT under periodic (torus) boundary conditions.

Variables:
  • nx (ny,) – Grid dimensions (number of rows and columns).

  • n_grid (int) – Total number of grid points (ny * nx).

  • topology ({'square', 'hex'}) – Grid topology. 'hex' mirrors 10x Visium hexagonal layouts.

  • method (str) – Kernel method ('gaussian', 'matern', 'moran', 'graph_laplacian', 'car').

  • params (dict) – Resolved kernel parameters (e.g. bandwidth, nu, neighbor_degree, rho) after defaults are merged with user overrides.

  • fft_solver ({'fft2', 'rfft2'}) – FFT routine in use. 'rfft2' stores roughly half the spectrum.

  • n_rfft (int) – Length of the flattened spectrum: ny * nx for fft2 and ny * (nx // 2 + 1) for rfft2.

  • workers (int or None) – Number of parallel workers forwarded to scipy.fft.

  • spectrum (np.ndarray) – Flattened (row-major) eigenvalues of the kernel matrix, shape (n_rfft,). Eagerly computed in __init__. See eigenvalues() for a sorted / full-FFT-layout accessor.

Parameters:
  • shape (tuple[int, int])

  • spacing (tuple[float, float])

  • topology (str)

  • method (str)

  • workers (int | None)

  • fft_solver (str)

  • centering (bool)

Kx(x)[source]#

Apply the kernel operator to x via FFT in O(n log n).

Implemented as K x = F^{-1}(λ · F(x)) where λ is the full eigenvalue spectrum on the torus. The result is returned on the spatial grid (not the feature-axis first layout used by NUFFTKernel); callers that want a quadratic / bilinear form should prefer xtKx() / xtKy(), which avoid the inverse FFT by using Parseval’s theorem.

Parameters:

x (np.ndarray) – Grid signal of shape (ny, nx) or (ny, nx, M).

Returns:

K @ x with the same shape as x.

Return type:

np.ndarray

eigenvalues(k=None, return_full_layout=False)[source]#

Eigenvalues of the kernel matrix.

When self.centering is True (default) the k=(0, 0) DC component is zeroed before returning — this is exactly the spectrum of HKH on a torus, since the constant vector 𝟏 is the DC Fourier mode. Set centering=False at construction to recover the raw K spectrum.

Parameters:
  • k (int, optional) – Number of largest eigenvalues to return. If None, returns all.

  • return_full_layout (bool, default False) – Only for fft_solver='rfft2'. If True, returns eigenvalues in full FFT layout (ny, nx) flattened.

Return type:

ndarray

square_trace()[source]#

trace(K²) (raw) or trace((HKH)²) (centered).

Closed-form Σ_k λ(k)² — FFT diagonalization gives the spectrum directly.

Return type:

float

trace()[source]#

trace(K) (raw) or trace(HKH) (centered).

Closed-form Σ_k λ(k) — FFT diagonalizes K in the Fourier basis, so the trace is an O(n) sum over the spectrum. No stochastic path.

Return type:

float

xtKx(x)[source]#

Compute the quadratic form x^T K x efficiently using FFT.

Uses Parseval’s theorem to compute the result in frequency domain for O(n log n) complexity instead of O(n²).

Parameters:

x (np.ndarray) – Input data tensor. Shape (ny, nx) for single feature or (ny, nx, M) for M features.

Returns:

Quadratic form value(s). Scalar if input was 2D, shape (M,) if input was 3D.

Return type:

float or np.ndarray

xtKy(x, y)[source]#

Bilinear form x^T K y on the grid via Parseval’s theorem.

Parameters:
  • x (np.ndarray) – Grid signals of shape (ny, nx) or (ny, nx, M). Both must have the same shape.

  • y (np.ndarray) – Grid signals of shape (ny, nx) or (ny, nx, M). Both must have the same shape.

Returns:

Scalar if inputs are 2D; shape (M,) if 3D.

Return type:

float or np.ndarray

fft_solver: str = 'fft2'[source]#

FFT routine in use ('fft2' or 'rfft2').

method: str = 'matern'[source]#

Kernel method name.

n: int[source]#

Alias for n_grid to satisfy the Kernel interface.

n_grid: int[source]#

Total number of grid points (ny * nx).

n_rfft: int[source]#

Length of the flattened spectrum buffer (ny*nx for fft2, ny*(nx//2+1) for rfft2).

nx: int[source]#

Number of grid columns.

ny: int[source]#

Number of grid rows.

params: dict[source]#

Resolved kernel parameters after defaults are merged with user overrides.

spectrum: ndarray[source]#

Flattened (row-major) eigenvalues of the kernel matrix, shape (n_rfft,).

topology: str = 'square'[source]#

Grid topology ('square' or 'hex').

workers: int | None = None[source]#

Number of parallel workers forwarded to scipy.fft, or None for the library default.

quadsv.kernels.fft.power_spectrum_2d(x, fft_solver='fft2', workers=None)[source]#

Compute the 2D power spectrum \(|\hat{x}(k)|^2\) of one or more grid signals.

The result is translation-invariant: shifting the input image leaves the power spectrum unchanged. This makes the spectrum a natural alignment-free representation of a spatial pattern. Use quadsv.comparators.multisample.radial_bin_spectrum() to further reduce the 2D spectrum to a 1D radial-binned vector that is also rotation-invariant.

Parameters:
  • x (np.ndarray) – Grid signal of shape (ny, nx) for a single feature, or (ny, nx, M) for M stacked features sharing the grid.

  • fft_solver ({'fft2', 'rfft2'}, default 'fft2') – FFT routine. 'rfft2' returns the half-spectrum of shape (ny, nx // 2 + 1) and roughly halves memory.

  • workers (int, optional) – Number of parallel workers forwarded to scipy.fft. None uses the SciPy default.

Returns:

Power spectrum. Shape (ny, n_kx) if input was 2D, or (ny, n_kx, M) if input was 3D, where n_kx = nx for fft2 and nx // 2 + 1 for rfft2. Layout matches the corresponding scipy.fft routine (zero-frequency bin at [0, 0], no fftshift applied).

Return type:

np.ndarray

Raises:

ValueError – If fft_solver is not one of 'fft2' or 'rfft2'.

Examples

>>> img = np.random.randn(32, 32)
>>> P = power_spectrum_2d(img, fft_solver='rfft2')
>>> P.shape
(32, 17)