PSF photometry
Threshold-ladder PSF fitter, joint-refit, NNLS forced-photometry refit, and the leftover-detection loop.
- class sphot.psf.PSFFitter(cutoutdata)[source]
Bases:
objectA class to perform PSF fitting.
- fit(fit_to='sersic_residual', **kwargs)[source]
Perform PSF fitting via iterative_psf_fitting (wraps do_psf_photometry with a threshold ladder so we don’t fit >1000 sources simultaneously in crowded fields).
The PSF used is cutoutdata.psf as-is. Mainloop-level kernel calibration (_maybe_recalibrate_psf -> calibrate_psf_step) updates cutoutdata.psf with library * K between iterations; this fitter just reads the current PSF state and runs the ladder.
- Parameters:
fit_to (str) – attribute name of the image to fit, e.g. ‘sersic_residual’, ‘residual’, ‘data’.
kwargs (dict) – extra kwargs forwarded to do_psf_photometry.
- Returns:
CutoutData – updated in-place.
- sphot.psf.filter_psfphot_results(phot_result, center_mask_params=None, full_output=False, bkg_std=None, **kwargs)[source]
Filter the PSF photometry results.
- sphot.psf.sigma_clip_outside_aperture(data, sersic_params_physical, clip_sigma=4, aper_size_in_r_eff=1)[source]
- sphot.psf.subtract_background(data)[source]
Subtract background from data. This removes most of the large-scale background variations.
- sphot.psf.do_psf_photometry(data, data_error, bkg_std, psf_model, psf_sigma, th=2, plot=True, mask=None, **kwargs)[source]
Performs PSF photometry. Main function to run PSF photometry.
This function does the following:
turn psfimg into a fittable model
estimate the background statistics (mean, std)
subtract background from data
perform IterativePSFPhotometry with the finder threshold at th*std
filter the results based on the fit quality (cfit, qfit, flux_err)
perform PSFPhotometry using the filtered results as input
filter the results again
generate model image and residual image
plot the results if necessary
- Parameters:
data (2d array) – the data to perform PSF photometry.
psfimg (2d array) – the PSF image.
psf_sigma (float) – the HWHM of the PSF. Use FWHM/2
psf_oversample (int) – the oversampling factor of the PSF.
th (float) – the detection threshold in background STD.
Niter (int) – the number of iterations to repeat the photometry (after cleaning up the data). – !deprecated!
fit_shape (2-tuple) – the shape of the fit.
render_shape (2-tuple) – the shape of each PSF to be rendered.
finder_kwargs (dict,optional) – the kwargs for DAOStarFinder.
localbkg_bounds (2-tuple,optional) – (inner, outer) radii to LocalBackground object, in the unit of psf_sigma.
grouper_sep (float,optional) – the minimum separation between sources to be used for SourceGrouper.
- Returns:
phot_result (QTable) – the photometry result.
resid (2d array) – the residual image.
- sphot.psf.iterative_psf_fitting(data, psf_model, psf_sigma, threshold_list, progress=None, progress_text='Running iPSF...', **kwargs)[source]
Iteratively run do_psf_photometry() with different threshold levels. This function is useful for crowded fields, where a single threshold level may fail.
The threshold list is typically descending (high -> low). Each successful pass subtracts detected sources from the residual; the next pass then operates on the cleaner residual. The ladder early-exits when th_max_consec_empty consecutive thresholds add no new sources.
- Parameters:
data (2d array) – the data to perform PSF photometry.
psf_model – the PSF ImagePSF model.
psf_sigma (float) – the HWHM of the PSF. Use FWHM/2
threshold_list (1d array) – the list of threshold levels to try, in background STD.
center_mask_params (list, optional) –
[x_center, y_center, mask_r]. If provided, sources withinmask_rfrom(x_center, y_center)are excluded from the final results. Useful when the central source is very bright and causes many spurious detections nearby.kwargs (dict) – additional kwargs to pass to do_psf_photometry.
- Returns:
phot_result (QTable) – the combined photometry result from all iterations.
resid_all (2d array) – the final residual image.
- sphot.psf.forced_psf_photometry(data, psf_model, psf_sigma, x_init, y_init, *, flux_init=None, xy_bound=1e-06, center_mask_params=None, progress=None, progress_text='forced PSF photometry')[source]
Closed-form NNLS forced photometry at FIXED positions.
Bypasses photutils’ PSFPhotometry entirely — that path uses a SourceGrouper + LM that scales poorly when many positions fall inside one wide-PSF group (e.g. F160W with ~556 base-filter positions can hang for hours in a single mega-group LM).
Recipe (same as _final_nnls_refit’s inner solve): render each source’s unit-flux PSF on the full image to form a column of the design matrix, then solve data = cols @ flux jointly via NNLS (Gram + Cholesky, with a dense fallback). One call, fast.
- Parameters:
data (2D ndarray) – Image to fit (typically cd.sersic_residual).
psf_model (photutils ImagePSF) – Effective PSF model.
psf_sigma (float) – Used only for the xy_bound legacy arg (no LM here).
x_init, y_init (1D float arrays) – Pinned source positions in data px.
flux_init (ignored (NNLS doesn’t need a flux seed).)
xy_bound (ignored (positions are FIXED in NNLS).)
center_mask_params ([x_c, y_c, r] | None) – Pixels inside this radius of the Sersic core are masked.
- Returns:
phot_table (QTable with x_fit, y_fit, flux_fit, flux_err, flags)
resid_image (data - model_image (full-frame, NaNs preserved))
- sphot.psf.run_forced_photometry_on_cutout(cutoutdata, x_init, y_init, *, flux_init=None, fit_to='sersic_residual', xy_bound=1e-06, progress=None)[source]
Run forced_psf_photometry on a CutoutData and populate the same downstream attrs PSFFitter.fit writes (residual, psf_table, psf_modelimg, psf_sub_data, psf_sub_data_error, residual_masked).
Used as a drop-in replacement for PSFFitter.fit inside run_scalefit_forced so the rest of the pipeline (sersic re-fit, plotting, save) sees the same set of attributes regardless of whether iPSF or forced photometry produced them.