psf_fit — ASTROSTACK photometry op

• Data kinds: image2d × keypoints → table

• Call: import fullseye as fs; fs.ledger.psf_fit(image, centers, model='gaussian', box=11, max_iter=200) (to call the implementation directly, import astrostack; astrostack.psf_fit(image, centers, model='gaussian', box=11, max_iter=200); from the registry, opsastrostack.get("psf_fit"))

Usage

Fit a PSF to a star image and get its centre and FWHM.

*model* "gaussian" is a 6-parameter fit of an elliptical Gaussian bkg + amp * exp(-((dr/sr)^2 + (dc/sc)^2)/2), and the roundness (roundness = min(sr,sc)/max(sr,sc)) comes out as a by-product —— star images stretched by tracking error or wind show up here. "moffat" is the circularly symmetric bkg + amp * (1 + r^2/alpha^2)^(-beta) (Moffat 1969), with beta also a free parameter. Least squares is scipy.optimize.least_squares (Trust Region Reflective), with deterministic initial values built from the 2nd moments —— no random numbers are used, so the same input gives the same answer.

FWHM is a closed form from the fitted parameters:

for the Gaussian 2 sqrt(2 ln 2) * sqrt(sr*sc) (geometric mean), for Moffat 2 alpha sqrt(2^(1/beta) - 1).

It always comes out wider by the pixel box. What is fitted here is a *continuous* Gaussian, but each pixel of the image is the continuous distribution integrated over a 1-pixel box. The variance of a uniform box of width 1 is 1/12, so the returned sigma is not the true sigma but sqrt(sigma^2 + 1/12) —— this is not an estimation error; the image is made that way. Measurements agree well with this prediction::

true FWHM predicted = 2.3548*sqrt(sigma^2+1/12) measured (median)

2.5 2.5908 2.5930

3.5 3.5654 3.5625

5.0 5.0460 5.0145

If you want the true sigma, subtract it as sqrt(sigma_fit^2 - 1/12), but by default it is not subtracted —— the "FWHM" commonly quoted in stellar measurement is the apparent width on the image, and silently inserting a correction would make it disagree with other tools' values.

Returns a list of one dict per star (table vocabulary). Keys are row / col (fitted centre), fwhm_px, amplitude, background, roundness, rms (residual RMS), converged (bool), model, and the model-dependent sigma_row_px / sigma_col_px or alpha_px / beta. Stars whose window sticks out of the image and stars whose fit did not converge are also returned, not dropped, with converged=False —— silently removing them would let nobody notice that "stars went missing".

Raises ValueError: if *model* is not in PSF_MODELS / *box* is less than 5 or even / *centers* is not (N, 2).

References (sample data, literature)

• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).

• Operator provenance and references — the sources of the research/methods this op family came from.

• The canonical algorithm (author, year) and its uses are named in the family usage guide above.

Runnable examples (verified samples that actually call this op)

• astro_stacking — py -3.11 examples/astro_stacking.py

• poc_star_astrometry — py -3.11 examples/poc_star_astrometry.py

Ops the type connects to (they accept table as input)

—

Same category (photometry)

star_detect · aperture_photometry


*Provenance: astrostack.py — ASTROSTACK operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.