stdpipe.sfft module

SFFT — Space-Frequency Fourier Transform image subtraction.

Implements spatially varying kernel fitting in a single global least-squares solve, following the approach of Hu et al. (2022, ApJ, 936, 157).

The model is:

science(x,y) = Σ_α Σ_β c_{α,β} · [P_β(x,y) · R_α(x,y)] + Σ_γ d_γ · P_γ(x,y)

where R_α is the reference shifted by kernel offset α, P_β are polynomial basis functions encoding spatial variation, and c_{α,β} / d_γ are scalar coefficients solved for globally.

The normal equations are assembled via batched BLAS matmuls over polynomial term pairs, avoiding materializing the full design matrix.

A soft kernel-sum constraint enforces that Σ_α a_α(x,y) = f(x,y) where f is a low-order polynomial modelling smooth flux-scale variation across the image.

class stdpipe.sfft.SFFTResult(diff: ndarray, model: ndarray, kernel_coeffs: ndarray, bg_coeffs: ndarray, kernel_shape: Tuple[int, int], kernel_poly_order: int, bg_poly_order: int, flux_poly_order: int, flux_poly_coeffs: ndarray, n_iter: int, rms: float, n_good: int)[source]

Bases: object

Result of SFFT image subtraction.

diff: ndarray

Difference image (science - model).

model: ndarray

Convolved reference + background model.

kernel_coeffs: ndarray

Kernel coefficients, shape (n_kernel, n_kpoly).

bg_coeffs: ndarray

Background coefficients, shape (n_bgpoly,).

kernel_shape: Tuple[int, int]

Kernel support size (ky, kx).

kernel_poly_order: int

Polynomial order for kernel spatial variation.

bg_poly_order: int

Polynomial order for differential background.

flux_poly_order: int

Polynomial order for the kernel-sum (flux scale) constraint.

flux_poly_coeffs: ndarray

Fitted flux-scale polynomial coefficients.

n_iter: int

Number of sigma-clipping iterations performed.

rms: float

Final weighted RMS of residuals.

n_good: int

Number of good (unmasked, unclipped) pixels in final iteration.

stdpipe.sfft.solve(image, template, mask=None, template_mask=None, err=None, kernel_shape=(7, 7), kernel_poly_order=2, bg_poly_order=2, flux_poly_order=1, flux_penalty=1000.0, ridge=1e-06, sigma_clip=3.0, max_iter=5, verbose=False)[source]

SFFT image subtraction with spatially varying kernel.

Solves for a spatially varying convolution kernel and differential background in a single global least-squares problem. The kernel at each pixel is modelled as a delta-function basis with polynomial spatial variation. A soft constraint enforces that the kernel sum varies smoothly as a low-order polynomial (modelling flux-scale differences between science and template).

Iterative sigma-clipping rejects outlier pixels (transients, cosmic rays, artifacts) that would otherwise bias the kernel solution.

Parameters:
imagenumpy.ndarray

Science image as a 2-D NumPy array.

templatenumpy.ndarray

Template/reference image, same shape, aligned to science.

masknumpy.ndarray, optional

Boolean mask where True = bad pixels to ignore. If both science and template masks are needed, combine them before passing (mask = science_mask | template_mask).

template_masknumpy.ndarray, optional

Additional mask for template-only defects. Merged with mask internally.

errnumpy.ndarray, optional

Per-pixel error (standard deviation) map for weighting. If None, uniform weights are used. If set to True, a simple noise estimate is derived from the image.

kernel_shapetuple of int, optional

(ky, kx) size of the convolution kernel, must be odd. Default (7, 7). Larger kernels handle bigger PSF differences but are slower.

kernel_poly_orderint, optional

Polynomial order for spatial variation of each kernel coefficient. Default 2 (quadratic). Higher orders capture more complex PSF variation but need more pixels.

bg_poly_orderint, optional

Polynomial order for the differential background model. Default 2.

flux_poly_orderint, optional

Polynomial order for the kernel-sum constraint (flux scale variation). Default 1 (linear gradient). Set to 0 for constant flux scale.

flux_penaltyfloat, optional

Penalty weight for the kernel-sum constraint. Default 1e3. Larger values enforce the constraint more strictly. Set to 0 to disable the constraint entirely.

ridgefloat, optional

Tikhonov regularization parameter. Default 1e-6.

sigma_clipfloat, optional

Sigma threshold for iterative outlier rejection. Default 3.0. Set to None or 0 to disable clipping.

max_iterint, optional

Maximum number of sigma-clipping iterations. Default 5.

verbosebool or callable, optional

If True, print progress. If callable, use as log function.

Returns:
SFFTResult

Result object with difference image and all fit metadata.

stdpipe.sfft.evaluate_kernel_at(result, x, y, image_shape)[source]

Evaluate the spatially varying kernel at a single image position.

Parameters:
resultSFFTResult

SFFTResult from solve().

xfloat

X pixel coordinate.

yfloat

Y pixel coordinate.

image_shapetuple of int

(ny, nx) of the original image.

Returns:
numpy.ndarray

2-D array of shape result.kernel_shape.

stdpipe.sfft.evaluate_flux_scale(result, x, y, image_shape)[source]

Evaluate the flux-scale polynomial at image position(s).

Parameters:
resultSFFTResult

SFFTResult from solve().

xfloat or array-like

X coordinate(s), scalar or array.

yfloat or array-like

Y coordinate(s), scalar or array.

image_shapetuple of int

(ny, nx) of the original image.

Returns:
float or numpy.ndarray

Flux scale value(s), same shape as x/y.

stdpipe.sfft.evaluate_background(result, x, y, image_shape)[source]

Evaluate the differential background model at image position(s).

Parameters:
resultSFFTResult

SFFTResult from solve().

xfloat or array-like

X coordinate(s), scalar or array.

yfloat or array-like

Y coordinate(s), scalar or array.

image_shapetuple of int

(ny, nx) of the original image.

Returns:
float or numpy.ndarray

Background value(s), same shape as x/y.