stdpipe.psf module

Module for working with point-spread function (PSF) models

stdpipe.psf.run_psfex(image, mask=None, thresh=2.0, aper=None, r0=0.0, gain=1, minarea=5, vignet_size=None, psf_size=None, order=0, sex_extra=None, checkimages=None, extra=None, psffile=None, get_obj=False, _workdir=None, _tmpdir=None, _exe=None, _sex_exe=None, verbose=False)[source]

Wrapper around PSFEx to help extracting PSF models from images.

For the details of PSFEx operation we suggest to consult its documentation at https://psfex.readthedocs.io

Parameters:
imagenumpy.ndarray

Input image as a NumPy array.

masknumpy.ndarray, optional

Image mask as a boolean array (True values will be masked).

threshfloat, optional

Detection threshold in sigmas above local background, for running initial SExtractor object detection.

aperfloat, optional

Circular aperture radius in pixels, to be used for PSF normalization. Should contain most of object flux. If not specified, will be estimated as twice the FWHM.

r0float, optional

Smoothing kernel size (sigma) to be used for improving object detection in initial SExtractor call.

gainfloat, optional

Image gain.

minareaint, optional

Minimal number of pixels in the object to be considered a detection (DETECT_MINAREA parameter of SExtractor).

vignet_sizeint, optional

The size of postage stamps to be used for PSF model creation.

psf_sizeint, optional

The size of the supersampled PSF model.

orderint, optional

Spatial order of PSF model variance.

sex_extradict, optional

Dictionary of additional options to be passed to SExtractor for initial object detection (extra parameter of stdpipe.photometry.get_objects_sextractor()).

checkimageslist, optional

List of PSFEx checkimages to return along with PSF model.

extradict, optional

Dictionary of extra configuration parameters to be passed to PSFEx call, with keys as parameter names. See psfex -dd for the full list.

psffilestr, optional

If specified, PSF model file will also be stored under this file name, so that it may e.g. be re-used by SExtractor later.

get_objbool, optional

If set, also return the table with SExtractor detected objects.

_workdirstr, optional

If specified, all temporary files will be created in this directory, and will be kept intact after running SExtractor and PSFEx. May be used for debugging exact inputs and outputs of the executable.

_tmpdirstr, optional

If specified, all temporary files will be created in a dedicated directory (that will be deleted after running the executable) inside this path.

_exestr, optional

Full path to PSFEx executable. If not provided, the code tries to locate it automatically in your PATH.

_sex_exestr, optional

Full path to SExtractor executable. If not provided, the code tries to locate it automatically in your PATH.

verbosebool or callable, optional

Whether to show verbose messages during the run of the function or not.

Returns:
dict

PSF structure corresponding to the built PSFEx model.

The structure has at least the following fields:

  • width, height - dimensions of supersampled PSF stamp

  • fwhm - mean full width at half maximum (FWHM) of the images used for building the PSF model

  • sampling - conversion factor between PSF stamp (supersampled) pixel size, and original image one (less than unity when supersampled resolution is finer than original image one)

  • ncoeffs - number of coefficients pixel polynomials have

  • degree - polynomial degree of a spatial variance of PSF model

  • data - the data containing per-pixel polynomial coefficients for PSF model

  • header - original FITS header of PSF model file, if get_header=True parameter was set

This structure corresponds to the contents of original PSFEx generated output file that is documented at https://psfex.readthedocs.io/en/latest/Appendices.html#psf-file-format-description

stdpipe.psf.load_psf(filename, get_header=False, verbose=False)[source]

Load PSF model from PSFEx file

The structure may be useful for inspection of PSF model with stdpipe.psf.get_supersampled_psf_stamp() and stdpipe.psf.get_psf_stamp(), as well as for injection of PSF instances (fake objects) into the image with stdpipe.psf.place_psf_stamp().

Parameters:
filenamestr

Name of a file containing PSF model built by PSFEx.

get_headerbool, optional

Whether to return the original FITS header of PSF model file or not. If set, the header will be stored in the header field of the returned structure.

verbosebool or callable, optional

Whether to show verbose messages during the run of the function or not.

Returns:
dict

PSF structure in the same format as returned from stdpipe.psf.run_psfex().

stdpipe.psf.bilinear_interpolate(im, x, y)[source]

Quick and dirty bilinear interpolation

stdpipe.psf.get_supersampled_psf_stamp(psf, x=0, y=0, normalize=True)[source]

Returns supersampled PSF model for a given position inside the image.

The returned stamp corresponds to PSF model evaluated at a given position inside the image, with its center always in the center of central stamp pixel. Every supersampled pixel of the stamp corresponds to psf['sampling'] pixels of the original image.

Parameters:
psfdict

Input PSF structure as returned by stdpipe.psf.run_psfex() or stdpipe.psf.load_psf().

xfloat, optional

x coordinate of the position inside the original image to evaluate the PSF model.

yfloat, optional

y coordinate of the position inside the original image to evaluate the PSF model.

normalizebool, optional

Whether to normalize the stamp to have flux exactly equal to unity or not.

Returns:
numpy.ndarray

Stamp of the PSF model evaluated at the given position inside the image.

stdpipe.psf.get_psf_stamp(psf, x=0, y=0, dx=None, dy=None, normalize=True)[source]

Returns PSF stamp in original image pixel space with sub-pixel shift applied.

The PSF model is evaluated at the requested position inside the original image, and then downscaled from supersampled pixels of the PSF model to original image pixels, and then adjusted to accommodate for requested (dx, dy) sub-pixel shift.

Stamp is odd-sized, with PSF center at:

x0 = floor(width/2) + dx
y0 = floor(height/2) + dy

If dx=None or dy=None, they are computed directly from the floating point parts of the position x and y arguments:

dx = x - round(x)
dy = y - round(y)

The stamp should directly represent stellar shape at a given position (including sub-pixel center shift) inside the image.

Parameters:
psfdict

Input PSF structure as returned by stdpipe.psf.run_psfex() or stdpipe.psf.load_psf().

xfloat, optional

x coordinate of the position inside the original image to evaluate the PSF model.

yfloat, optional

y coordinate of the position inside the original image to evaluate the PSF model.

dxfloat, optional

Sub-pixel adjustment of PSF position in image space, x direction.

dyfloat, optional

Sub-pixel adjustment of PSF position in image space, y direction.

normalizebool, optional

Whether to normalize the stamp to have flux exactly equal to unity or not.

Returns:
numpy.ndarray

Stamp of the PSF model evaluated at the given position inside the image, in original image pixels.

stdpipe.psf.place_psf_stamp(image, psf, x0, y0, flux=1, gain=None)[source]

Places PSF stamp, scaled to a given flux, at a given position inside the image.

PSF stamp is evaluated at a given position, then adjusted to accommodate for required sub-pixel shift, and finally scaled to requested flux value. Thus, the routine corresponds to injection of an artificial point source into the image.

The stamp values are added on top of current content of the image. If gain value is set, the Poissonian noise is applied to the stamp.

The image is modified in-place.

Parameters:
imagenumpy.ndarray

The image where the artificial source will be injected (modified in-place).

psfdict

Input PSF structure as returned by stdpipe.psf.run_psfex() or stdpipe.psf.load_psf().

x0float

x coordinate of the position to inject the source.

y0float

y coordinate of the position to inject the source.

fluxfloat, optional

The source flux in ADU units.

gainfloat, optional

Image gain value. If set, used to apply Poissonian noise to the source.

stdpipe.psf.create_psf_model(image, obj=None, fwhm=None, size=None, mask=None, oversampling=None, degree=0, regularization=1e-06, subtract_neighbors=True, subtract_background=False, isolation=2.0, get_raw=False, verbose=False)[source]

Create an empirical PSF (ePSF) model from stars in the image.

For degree=0 (default), builds a position-invariant ePSF using photutils EPSFBuilder (iterative recentering and stacking).

For degree > 0, builds a position-dependent PSF model by fitting per-pixel polynomial coefficients to resampled star stamps, following the same approach as PSFEx. The polynomial model is:

\[PSF(i,j; x,y) = \sum_k c_k(i,j) \cdot dx^{p1_k} \cdot dy^{p2_k}\]

where (dx, dy) are normalized image coordinates and (p1_k, p2_k) are polynomial exponents with p1_k + p2_k <= degree.

The returned dictionary structure is compatible with PSFEx output from stdpipe.psf.run_psfex() and can be used with the same evaluation functions like stdpipe.psf.get_psf_stamp().

Parameters:
imagenumpy.ndarray

Input image as a NumPy array, must be background subtracted.

objastropy.table.Table, optional

Table of star positions. If None, stars will be detected automatically. Should have ‘x’, ‘y’ columns and optionally ‘flux’.

fwhmfloat, optional

Approximate FWHM of stars in pixels. If None, will be estimated.

sizeint, optional

Size of cutouts to extract around stars (should be odd). If None, automatically determined from FWHM as max(15, round_up_to_odd(5 * fwhm)).

masknumpy.ndarray, optional

Image mask as a boolean array (True values will be masked).

oversamplingint, optional

Oversampling factor for the ePSF. If None (default), it is auto-selected from the FWHM: 1 when fwhm >= 2.5 image pixels (well-sampled PSF) and 2 otherwise (under-sampled PSF). Pass an explicit integer to override.

degreeint, optional

Polynomial degree for spatial PSF variation (default: 0 = constant). Degree 1 = linear (3 coefficients), degree 2 = quadratic (6 coefficients), etc.

regularizationfloat, optional

Tikhonov regularization parameter for polynomial fitting (default: 1e-6). Only used when degree > 0. Set to 0 for unregularized least-squares.

subtract_neighborsbool, optional

If True (default), subtract estimated flux from neighboring stars before extracting cutouts. Reduces contamination in crowded fields. Only used when degree > 0.

subtract_backgroundbool or {‘none’, ‘median’, ‘plane’}, optional

Local background handling for each training stamp before normalization. False or 'none' leaves the current image values unchanged, True or 'median' subtracts the median of the stamp border, and 'plane' fits and subtracts a tilted background plane from the border pixels. Only used when degree > 0. When building from the raw image instead of a background-subtracted one, 'plane' is usually the most robust choice.

isolationfloat, optional

Minimum nearest-neighbor distance in FWHM units for selecting stars for ePSF building (default: 2.0). Stars with a neighbor closer than isolation * fwhm are excluded. Combined with subtract_neighbors=True, the lower default value works in both sparse and dense fields. Set to 0 or None to disable isolation filtering.

get_rawbool, optional

If True and degree=0, returns raw photutils EPSFModel object. Ignored when degree > 0.

verbosebool or callable, optional

Whether to show verbose messages.

Returns:
dict

Dictionary with PSFEx-compatible structure containing the PSF model.

stdpipe.psf.enclosed_psf_fraction(psf, x=0, y=0, radius=None, subpixel=10)[source]

Fraction of normalised PSF flux inside a circular aperture.

Evaluates the (possibly position-dependent) PSF model at (x, y) via get_psf_stamp(), normalises it to unit total flux, and sums the pixels lying within radius of the stamp centre. Useful for on-the-fly aperture corrections.

Pixels are weighted by the fractional coverage of the circular aperture using a sub-pixel grid (subpixel × subpixel samples per pixel) — set subpixel=1 to fall back to a hard pixel-centre mask, which is faster but has up to ~10 % radius-dependent jitter when the aperture edge cuts through individual pixels.

Parameters:
psfdict

PSF model from run_psfex(), load_psf(), or create_psf_model().

x, yfloat, optional

Position in image pixels at which to evaluate a position-dependent PSF model. The sub-pixel parts of x and y are folded into the stamp centre via get_psf_stamp().

radiusfloat or array-like

Aperture radius (or radii) in image pixels.

subpixelint, optional

Linear sub-pixel sampling per image pixel for partial-coverage weighting. Default 10 (100 sub-samples per pixel).

Returns:
float or ndarray

Enclosed flux fraction at each radius. Scalar when radius is a scalar, otherwise an array of the same shape.

stdpipe.psf.select_psf_seeds(obj, image_shape, *, max_per_tile=25, grid=6, edge=20, obj_col_x='x', obj_col_y='y', obj_col_flux='flux', obj_col_flags='flags', accept_flags=0)[source]

Select bright, edge-clear sources spread uniformly across the field.

Bins obj on a regular grid_x × grid_y spatial grid and returns the max_per_tile brightest sources per cell that pass basic quality filters: finite x/y/flux, positive flux, optionally a flag mask, and inside the image after an edge-pixel margin.

The returned table is a strict subset of obj (same columns, sub-selected rows) and is the natural input for stdpipe.psf.create_psf_model() and similar PSF-modelling routines that benefit from a uniform spatial sampling.

Parameters:
objastropy.table.Table

Source catalogue.

image_shape(H, W) tuple

Image shape used for the spatial grid and edge mask.

max_per_tileint

Maximum number of seeds kept per spatial cell.

gridint or (nx, ny) tuple

Number of cells in the spatial grid. A scalar means a square grid × grid layout.

edgefloat

Edge margin in pixels; sources within edge of any image boundary are excluded.

obj_col_x, obj_col_ystr

Column names for source positions in pixel coordinates.

obj_col_fluxstr

Column name used to rank candidates within each cell (brightest first). Sources with non-positive values are dropped.

obj_col_flagsstr, optional

Column name for a SExtractor-style integer flag mask. Set to None to skip flag filtering. If the column is missing from obj, no flag filter is applied either.

accept_flagsint

Bitwise mask of acceptable flags. A source is kept only when flags & ~accept_flags == 0.

Returns:
astropy.table.Table

A subset of obj containing the selected seeds.