quadsv.kernels.fft
==================

.. py:module:: quadsv.kernels.fft


Classes
-------

.. autoapisummary::

   quadsv.kernels.fft.FFTKernel


Functions
---------

.. autoapisummary::

   quadsv.kernels.fft.power_spectrum_2d


Module Contents
---------------

.. py:class:: FFTKernel(shape, spacing = (1.0, 1.0), topology = 'square', method = 'matern', workers = None, fft_solver = 'fft2', *, centering = True, **kwargs)

   Bases: :py:obj:`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.

   :ivar ny, nx: Grid dimensions (number of rows and columns).
   :vartype ny, nx: int
   :ivar n_grid: Total number of grid points (``ny * nx``).
   :vartype n_grid: int
   :ivar topology: Grid topology. ``'hex'`` mirrors 10x Visium hexagonal layouts.
   :vartype topology: {'square', 'hex'}
   :ivar method: Kernel method (``'gaussian'``, ``'matern'``, ``'moran'``, ``'graph_laplacian'``,
                 ``'car'``).
   :vartype method: str
   :ivar params: Resolved kernel parameters (e.g. ``bandwidth``, ``nu``, ``neighbor_degree``,
                 ``rho``) after defaults are merged with user overrides.
   :vartype params: dict
   :ivar fft_solver: FFT routine in use. ``'rfft2'`` stores roughly half the spectrum.
   :vartype fft_solver: {'fft2', 'rfft2'}
   :ivar n_rfft: Length of the flattened spectrum: ``ny * nx`` for ``fft2`` and
                 ``ny * (nx // 2 + 1)`` for ``rfft2``.
   :vartype n_rfft: int
   :ivar workers: Number of parallel workers forwarded to :mod:`scipy.fft`.
   :vartype workers: int or None
   :ivar spectrum: Flattened (row-major) eigenvalues of the kernel matrix, shape ``(n_rfft,)``.
                   Eagerly computed in ``__init__``. See :meth:`eigenvalues` for a sorted /
                   full-FFT-layout accessor.

   :vartype spectrum: np.ndarray


   .. py:method:: Kx(x)

      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
      :class:`NUFFTKernel`); callers that want a quadratic / bilinear form
      should prefer :meth:`xtKx` / :meth:`xtKy`, which avoid the inverse
      FFT by using Parseval's theorem.

      :param x: Grid signal of shape ``(ny, nx)`` or ``(ny, nx, M)``.
      :type x: np.ndarray

      :returns: ``K @ x`` with the same shape as ``x``.
      :rtype: np.ndarray



   .. py:method:: eigenvalues(k = None, return_full_layout = False)

      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.

      :param k: Number of largest eigenvalues to return. If None, returns all.
      :type k: int, optional
      :param return_full_layout: Only for ``fft_solver='rfft2'``. If True, returns eigenvalues
                                 in full FFT layout (ny, nx) flattened.
      :type return_full_layout: bool, default False



   .. py:method:: square_trace()

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

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



   .. py:method:: trace()

      ``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.



   .. py:method:: xtKx(x)

      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²).

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

      :returns: Quadratic form value(s). Scalar if input was 2D, shape (M,) if input was 3D.
      :rtype: float or np.ndarray



   .. py:method:: xtKy(x, y)

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

      :param x: Grid signals of shape ``(ny, nx)`` or ``(ny, nx, M)``. Both must
                have the same shape.
      :type x: np.ndarray
      :param y: Grid signals of shape ``(ny, nx)`` or ``(ny, nx, M)``. Both must
                have the same shape.
      :type y: np.ndarray

      :returns: Scalar if inputs are 2D; shape ``(M,)`` if 3D.
      :rtype: float or np.ndarray



   .. py:attribute:: fft_solver
      :type:  str
      :value: 'fft2'


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


   .. py:attribute:: method
      :type:  str
      :value: 'matern'


      Kernel method name.


   .. py:attribute:: n
      :type:  int

      Alias for ``n_grid`` to satisfy the :class:`~quadsv.kernels.Kernel` interface.


   .. py:attribute:: n_grid
      :type:  int

      Total number of grid points (``ny * nx``).


   .. py:attribute:: n_rfft
      :type:  int

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


   .. py:attribute:: nx
      :type:  int

      Number of grid columns.


   .. py:attribute:: ny
      :type:  int

      Number of grid rows.


   .. py:attribute:: params
      :type:  dict

      Resolved kernel parameters after defaults are merged with user overrides.


   .. py:attribute:: spectrum
      :type:  numpy.ndarray

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


   .. py:attribute:: topology
      :type:  str
      :value: 'square'


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


   .. py:attribute:: workers
      :type:  int | None
      :value: None


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


.. py:function:: power_spectrum_2d(x, fft_solver = 'fft2', workers = None)

   Compute the 2D power spectrum :math:`|\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 :func:`quadsv.comparators.multisample.radial_bin_spectrum` to
   further reduce the 2D spectrum to a 1D radial-binned vector that is also
   rotation-invariant.

   :param x: Grid signal of shape ``(ny, nx)`` for a single feature, or ``(ny, nx, M)``
             for ``M`` stacked features sharing the grid.
   :type x: np.ndarray
   :param fft_solver: FFT routine. ``'rfft2'`` returns the half-spectrum of shape
                      ``(ny, nx // 2 + 1)`` and roughly halves memory.
   :type fft_solver: {'fft2', 'rfft2'}, default 'fft2'
   :param workers: Number of parallel workers forwarded to :mod:`scipy.fft`. ``None`` uses the
                   SciPy default.
   :type workers: int, optional

   :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 :mod:`scipy.fft` routine
             (zero-frequency bin at ``[0, 0]``, no fftshift applied).
   :rtype: np.ndarray

   :raises ValueError: If ``fft_solver`` is not one of ``'fft2'`` or ``'rfft2'``.

   .. rubric:: Examples

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


