pycsa.core.mode_selection

Pluggable mode selectors for the FA -> SA bridge.

The default selection step in pycsa.wrappers.interface.second_appx is a greedy argmax loop on the FA spectrum: pick the largest amplitude, zero it, repeat n_modes times. That loop is preserved unchanged — it is what every existing call site hits and what the reproducibility fixtures pin down.

This module introduces a ModeSelector protocol so spike scripts can experiment with sparsity-inducing alternatives (OMP, Lasso) without touching the default code path. A selector takes the FA spectrum (and optionally the design matrix + data) and returns the (k_idxs, l_idxs) pair that fobj.set_kls expects.

GreedyArgmax is a 1-to-1 reimplementation of the inline loop. Unit-tested for bit-equivalent output on a synthetic FA spectrum.

OMPSelector and LassoSelector are the alternatives under test in the spike. They require access to the design matrix and the residual signal — these are passed through optional kwargs.

Classes

GreedyArgmax()

Reproduces the existing inline argmax loop verbatim.

LassoSelector([alpha, column_offset, max_iter])

L1-penalised regression via coordinate descent.

ModeSelector(*args, **kwargs)

Callable that selects n_modes Fourier modes from the FA spectrum.

OMPSelector([batch_size, column_offset])

Orthogonal matching pursuit on the design matrix.

class pycsa.core.mode_selection.ModeSelector(*args, **kwargs)

Callable that selects n_modes Fourier modes from the FA spectrum.

Parameters:
  • fa_spectrum – 2D real array of FA amplitudes, shape (nhar_j, nhar_i) — the same array currently passed to the inline argmax loop in second_appx. Indexing matches the existing convention: axis 0 == l, axis 1 == k.

  • n_modes – Number of modes to select.

  • design_matrix – Optional dense design matrix M of shape (n_points, n_columns) for selectors that need it (OMP, Lasso). GreedyArgmax ignores this.

  • data – Optional 1D data vector, shape (n_points,), that the FA fit targeted. Selectors that fit a sparse representation of data against the columns of design_matrix use it.

  • column_to_kl – Optional callable mapping column index in design_matrix to a (k, l) index pair compatible with fa_spectrum indexing. Used by OMP/Lasso to convert their selected columns back to the (k_idxs, l_idxs) format. If absent, the selector assumes columns are laid out in np.ndindex(fa_spectrum.shape) order.

Returns:

Two lists of up to n_modes entries ready to feed fobj.set_kls(k_idxs, l_idxs, ...).

Return type:

(k_idxs, l_idxs)

__init__(*args, **kwargs)
class pycsa.core.mode_selection.GreedyArgmax

Reproduces the existing inline argmax loop verbatim.

Iterates n_modes times: take argmax of the current spectrum, record the unravel-index pair, zero that entry, repeat. The recorded pairs are then split as k_idxs = [pair[1] for pair in indices] and l_idxs = [pair[0] for pair in indices] to match the convention in second_appx.

This is the default selector. Passing selector=GreedyArgmax() to a wrapped second_appx should produce bit-identical output versus the inline loop.

__init__() None
class pycsa.core.mode_selection.OMPSelector(batch_size: int = 1, column_offset: int = 0)

Orthogonal matching pursuit on the design matrix.

At each step, picks the column of design_matrix most correlated (in absolute value) with the current residual, re-fits the active set by ordinary least squares, and updates the residual. Repeats until n_modes columns are selected.

Requires design_matrix and data. Raises ValueError if either is missing, or if the design_matrix row count and data length disagree.

Parameters:
  • batch_size (int) – Number of correlations selected per step. batch_size=1 is canonical OMP. Larger values (e.g. 5) trade some optimality for cost — only one active-set least-squares re-fit per batch.

  • column_offset (int) – Index into design_matrix columns to skip (e.g. the DC mode if the caller prefers OMP to ignore it). Defaults to 0, meaning all columns are candidates.

batch_size: int = 1
column_offset: int = 0
__init__(batch_size: int = 1, column_offset: int = 0) None
class pycsa.core.mode_selection.LassoSelector(alpha: float | None = None, column_offset: int = 0, max_iter: int = 10000)

L1-penalised regression via coordinate descent.

Wraps sklearn.linear_model.Lasso. Selects the n_modes columns with the largest-magnitude coefficients |coef|. If Lasso returns fewer non-zeros than n_modes, the remaining slots are filled with the next-largest coefficients (which may be zero).

Parameters:
  • alpha (float | None) – Lasso penalty strength. None triggers a small k-fold CV over a log-spaced grid (left to the spike-script layer in phase 1; in the protocol layer here, alpha=None falls back to a sensible default of 1e-3 * ‖subᵀ y‖∞ / n_points).

  • column_offset (int) – See OMPSelector.

  • max_iter (int) – Lasso solver max iterations.

alpha: float | None = None
column_offset: int = 0
max_iter: int = 10000
__init__(alpha: float | None = None, column_offset: int = 0, max_iter: int = 10000) None