PSF Viewer

Statistical PSF analysis — HFR / FWHM / flux histograms, per-metric stats, and a two-mode median star profile widget that lets you flip between the smoothed analytic shape and the actual pixel-level data.

Honest star-shape statistics for the whole frame. PSF Viewer measures every well-formed star in the image, reports the population medians for HFR, FWHM, eccentricity, flux and shape parameters, and renders the median star in two ways: a smooth analytic Gaussian that shows the fitted shape clearly, and a real median-stacked stamp assembled from the actual pixel data in the image. Click the star widget to switch between them. The real-pixel view answers a question most PSF tools cannot: is the data actually sampled well enough to support what the smooth model is claiming? If your FWHM reads 1.8 px, the pixel-mode stamp will show you a star spanning 2-3 image pixels at native resolution — which is undersampled, and the smooth plot is lying to you by interpolation. Original work by Franklin Marek for SetiAstro Suite Pro.

1. Overview

PSF Viewer opens on the active image and runs star detection, then reports population statistics across every detection that passed the quality filter. The window has three main regions:

Below those sits the detection threshold panel, a status line that reports what the detector did (e.g. "Auto — 1024 stars at σ=12, kept 1024/17800 at that threshold"), and the Close button.

2. Workflow

Open the viewer on your image and the detector runs automatically. Watch the status line for the "kept X/Y" summary — it tells you both how many stars contribute to the statistics (X) and how many detections SEP found before quality filtering (Y). On a well-populated frame X ≈ 1000 by default. On a sparse frame all detections survive, and X ≈ Y.

Fast focus / quality check on a sub. Open the viewer on a single sub. Read median FWHM from the stats table — that's your frame's seeing-plus-optics FWHM. Compare to previous subs or to your usual values. If today's median is 50% higher than normal, something changed (focus drift, worse seeing, sensor dew, cable snag). The eccentricity median tells you whether stars are elongated — above 0.5 is clearly non-round.
Deciding whether the data is well-sampled. Click the star widget to switch to pixel mode. If the median star fills 3-5 pixels, you're well-sampled; if it fills 2 pixels, you're undersampled and the smooth-mode shape is interpolation, not data. The FWHM ellipse drawn against the real pixel grid tells you directly whether your resolution claim is supported.
Round-vs-elongated diagnosis. Read the median eccentricity. Above 0.3, stars are visibly elongated. Switch to the pixel mode and look at the median stamp — the direction of elongation (red PSF-X axis vs blue PSF-Y) reveals the cause: horizontal/vertical means guiding or periodic error, radial means field curvature or coma, diagonal means tilt. For a focal-plane view across the whole frame, use Image Peeker's Focal Plane Analysis.
Flux histogram for bimodality / outliers. Click Show Flux Histogram. The viewer switches to log x-axis by default (flux spans huge range). A clean distribution tapers smoothly from the detection limit to the saturation ceiling. A bimodal distribution reveals two populations in your frame — common when a star cluster is embedded in a sparse field, or when two overlapping stacks were median-combined with different exposures. A sharp spike at the high end is saturated stars that you probably want to exclude from downstream photometry.
Setting detection σ for other tools. Uncheck Auto and move the σ slider. The histogram and stats update after a 500 ms debounce. This lets you find the σ at which your downstream tool (Magnitude, Blink, registration) will get the number of stars it needs. Then feed that σ to that tool explicitly.

3. The two-mode star widget

The widget starts in smooth mode: an analytic Gaussian with semi-major axis a and semi-minor axis b (both medians across the detected population), rotated by the median orientation θ. Overlaid on top:

Click the widget to switch to pixel mode:

Why both modes exist. The smooth view is the fitted model — easy to read, obvious shape, but not showing you the data. The pixel view is the data — honest about sampling, obvious when the model is interpolating. If the two views agree about where the FWHM ellipse sits, your fit is trustworthy; if the smooth FWHM ellipse looks tighter than the actual pixel-mode star profile, you're seeing the limitations of fitting a Gaussian to undersampled data. Both views are drawn with the same orientation and the same ellipse scaling, so they're directly comparable.

4. Detection modes

The detection panel at the bottom has a σ slider and an Auto checkbox.

Auto (default) runs the shared waterfall detector: SEP's background estimator runs once, then sep.extract re-runs at progressively lower sigma thresholds — 100 → 50 → 25 → 12 → 6 → 3 — stopping as soon as ~1000 quality-filtered stars are detected. On a rich field this takes 2-3 extractions; on a sparse one it descends to the bottom and keeps whatever it got.

Manual (uncheck Auto) uses the σ slider value as the one and only extraction threshold. The slider ranges 1-50; the current value is shown next to it. The debounce timer waits 500 ms after the last slider change before re-running the extraction, so you can scrub smoothly without triggering a burst of worker threads.

Either way, a quality filter is applied before statistics are computed:

The status line reports how many detections survived the filter, so you can see whether your extraction is noise-dominated (large Y, small X ratio) or clean (X ≈ Y).

Controls.
Click the star widget — toggle smooth ↔ pixel view.
Zoom slider — scale the histogram display (50-1000%). Zoom in / out / Fit buttons for discrete steps.
X-Axis: Linear / Log — toggle histogram x-axis scaling. Flux defaults to log; HFR defaults to linear.
Show Flux Histogram / Show PSF Histogram — switch between HFR distribution and flux distribution.
Detection Threshold slider — only active when Auto is unchecked. 500 ms debounce before re-extraction.
Auto checkbox — waterfall mode (default) vs single-shot at slider value. Persists across sessions via QSettings.

5. The stats table

Seven columns, each with four rows (median, min, max, std):

ColumnMeaningUnits
HFRHalf-Flux Radius proxy = 2·apixels
FWHMFull-Width Half-Max = 2.3548·apixels
eccentricity√(1 − b²/a²)dimensionless, [0, 1)
aSemi-major axis from SEP second momentspixels
bSemi-minor axis from SEP second momentspixels
thetaOrientation of the major axisradians
fluxTotal integrated signalADU (image units)

Median is the single most useful number — it's robust to outliers and is what the star-shape widget is drawn at. Min and max tell you the extremes present in the frame. StdDev tells you how homogeneous the population is: a tight StdDev on FWHM means your frame has consistent focus across the field; a wide StdDev means some corners are soft or guiding wandered during the sub.

Eccentricity vs ellipticity — don't mix them up. This tool reports eccentricity e = √(1 − b²/a²), the astronomical convention. Image Peeker's Focal Plane Analysis reports ellipticity ε = 1 − b/a, the PixInsight / SExtractor convention. They are not the same number: a star with b/a = 0.8 has eccentricity e = 0.6 but ellipticity ε = 0.2. If you see different numbers on the same frame between PSF Viewer and Image Peeker, that's why. Both are honest, standard definitions — just pick one convention when you report.

6. Technical details

The math behind every number the tool reports.

6.1 SEP second-moment star measurement

SEP (Source Extractor in Python) measures each detected source's shape via the second central moments of its pixel distribution. For a detection with centroid (x̄, ȳ) and pixel values Ii:

a^2 = M_{20}, \quad b^2 = M_{02}

in the principal axes frame (after rotation to diagonalize the moment matrix). The orientation that performs this diagonalization is:

\theta = \frac{1}{2}\arctan\!\left(\frac{2 M_{11}}{M_{20} - M_{02}}\right)

SEP returns a, b, and θ directly as per-detection attributes. The semi-major axis a is interpreted as the equivalent Gaussian σ along the long direction of the star; b is the equivalent σ along the short direction.

6.2 FWHM from a

For a 2D Gaussian with σ along the measured direction, the Full-Width-at-Half-Maximum is:

\mathrm{FWHM} = 2\sqrt{2 \ln 2}\, \cdot a \approx 2.3548\, a

evaluated in pixel units since SEP reports a in pixels. This is the proper statistical FWHM of the Gaussian model fit through the second-moment measurement; it is not the direct peak-to-half-peak distance that you would get by profile-fitting to the pixel data, but for well-sampled Gaussian-like stars the two agree to within a few percent.

6.3 HFR convention

The tool reports:

\mathrm{HFR} \approx 2\, a

This is a common astro-imaging convention for "Half-Flux Radius" that is not the mathematical half-light radius. The true half-light radius for a 2D Gaussian is:

r_{1/2} = \sigma \sqrt{2 \ln 2} \approx 1.177\, \sigma

which is smaller than 2σ by a factor of about 1.7. The HFR = 2·a convention is what guiding software (PHD2, SharpCap) and focus tools (SGP, N.I.N.A.) typically report, so following it keeps numbers from this tool directly comparable to those from your capture pipeline. If you need the proper mathematical half-light radius, divide the reported HFR by about 1.7.

6.4 Eccentricity

e = \sqrt{1 - \frac{b^2}{a^2}}

This is the standard eccentricity of the ellipse that passes through the a and b points. It ranges from 0 (circular star, b = a) to approaching 1 (highly elongated).

For reference, the alternative convention used by Image Peeker's Focal Plane Analysis is:

\varepsilon = 1 - \frac{b}{a}

which ranges from 0 (round) to approaching 1 (elongated) but has different numerical scaling. For a star with b/a = 0.8: this tool reports e = 0.6, Image Peeker reports ε = 0.2. Both are correct for their respective conventions.

6.5 Waterfall star detection

The shared detect_stars_waterfall function runs SEP's background estimator once (the expensive fixed cost) and then re-extracts at progressively lower sigma thresholds:

σ-ladder: 100 → 50 → 25 → 12 → 6 → 3

At each level, the raw detections are quality-filtered:

\mathrm{keep} = (\mathrm{flag} = 0) \wedge (N_{\mathrm{pix}} \geq 5) \wedge (a > 0 > b \leq a)

where the flag check rejects saturation, blends, and truncations; the pixel-count check rejects single-pixel spikes and cosmic rays; and the shape check rejects malformed ellipses. If the surviving count reaches the target (1000 by default) the ladder stops; otherwise it descends further.

Rationale: on a rich field, SEP at σ=3 can produce 50000+ detections (Frank's example: 53105 sources at σ=15 on one image). Fitting shape moments to that many detections wastes seconds on sources that will fail the quality filter anyway. Starting at σ=100 and only descending until a stable statistic is in hand gives the same median numbers in a fraction of the time. On sparse fields where σ=3 is needed to find anything, the ladder reaches the bottom naturally and the tool uses what it got.

6.6 Median star stamp assembly

When the widget is in pixel mode, the displayed stamp is a median stack of up to 500 real-image cutouts around detected stars. The process:

  1. Choose stamp size. The half-width is set from the median FWHM:
    L_{\mathrm{stamp}} = 2 \lceil 2.5 \cdot \mathrm{FWHM} \rceil + 1
    clamped to the range 5-25 pixels so very small or very large FWHM don't produce an unusable display.
  2. Cut around each star. Extract an (L × L) window centered on the integer-rounded centroid position (xᵢ, yᵢ). Stars whose window would overrun the image edge are skipped.
  3. Background-subtract per stamp. The 1-pixel edge of each stamp (top row + bottom row + two side columns) is the local sky estimate:
    s_i' = s_i - \mathrm{median}(s_i^{\mathrm{edge}})
    This handles local sky-gradient variation across the frame without needing a global background model.
  4. Peak-normalize. Divide by the stamp's peak value so bright stars don't dominate the median:
    s_i'' = \frac{s_i'}{\max(s_i')}
  5. Median-combine. Stack all normalized stamps and take the per-pixel median:
    \mathrm{PSF}_{\mathrm{stamp}} = \mathrm{median}\{s_i''\}_{i=1}^{N}
    This produces a robust representative shape that rejects individual star defects (overlapping neighbours, diffraction spikes from oversaturated stars, cosmic-ray residuals).

Cap at 500 stars because 500 median-stacked cutouts already give pixel-level stability well below the noise in any individual cutout; more would just cost memory and time with no visible benefit.

6.7 Smooth-view Gaussian rendering

The smooth mode renders:

G(x,y) = \exp\!\left(-\frac{1}{2}\!\left(\frac{x_r^2}{a^2} + \frac{y_r^2}{b^2}\right)\right)

on a 300×300 grid with the median a, b, and θ. The rotated coordinates are:

x_r = x \cos\theta + y \sin\theta
y_r = -x \sin\theta + y \cos\theta

The in-frame scaling is set so that the Gaussian occupies a comfortable fraction of the widget regardless of the star's absolute size; the ellipse overlays are scaled by the same factor so FWHM, HFR, and the axis lines match the rendered blob's extent. This is a cached QPixmap; resizing the widget just scales the pixmap, so there's no per-pixel work at resize time.

6.8 Threaded extraction

Star detection runs in a background QThread (_PSFWorker). The GUI thread shows a semi-transparent "Processing… extracting stars / PSFs" overlay on top of the histogram while the worker runs, and the status line updates when results arrive. A 500 ms debounce timer on the σ slider ensures that scrubbing the slider doesn't fire off a worker on every pixel of motion; the extraction only starts once the slider has been idle for half a second. The worker is cleanly stopped and replaced if a second extraction request comes in before the first completed.

Credits. PSF Viewer — the two-mode star widget (synthetic + real-pixel median stamp), the Auto/Manual threshold dual mode, the histogram+stats+shape triple-view layout, and the SASpro-canonical visual conventions — is original work by Franklin Marek for SetiAstro Suite Pro. Standard components credited to the community: SEP (Source Extractor in Python) by Barbary (2016) for source detection and the a / b / θ second-moment measurements; the Gaussian FWHM = 2√(2 ln 2) · σ conversion is standard statistics; the HFR ≈ 2·σ convention follows the astro-imaging community (PHD2, SharpCap, SGP, N.I.N.A.); the waterfall detection algorithm lives in psf_utils.py as a shared utility used by multiple SASpro tools.