Skip to content

Image

Image reprojection, convolution, and point-source stamp extraction.

Point-source PSF construction lives in the nested PSF page (noobase.image.psf). Adaptive aperture mask construction lives in the nested Aperture page (noobase.aperture).

make_pixel_corners(target_shape, *, target_pixel_to_world, source_world_to_pixel, coarse_step=None)

Build the pixel_corners array consumed by reproject_exact.

Maps every node of the target pixel grid (the frame you are aligning onto) through target_pixel_to_world and then source_world_to_pixel to obtain the corresponding location in the source image's pixel coordinate system (the image you are reprojecting). The half-pixel corner offset required by the astropy / gwcs convention (integer (x, y) is the center of a pixel) is applied internally so the caller does not have to remember it.

The terminology follows image registration: source is the image being reprojected (the data you have), target is the frame you are aligning onto (the goal). In a later call to reproject_exact, source will be passed as image and the corner array produced here projects each target pixel into the source's pixel coordinates.

Parameters:

Name Type Description Default
target_shape tuple of (int, int)

(H_target, W_target) — the shape of the reprojected image you want. Usually this is the shape of the reference image you are aligning onto.

required
target_pixel_to_world callable

Forward transform on the target WCS. Signature::

target_pixel_to_world(x, y) -> tuple of ndarray

where x and y are 2-D ndarrays of target pixel coordinates (integer = pixel center) and the return is a tuple of world-coordinate arrays (for example (ra, dec)). astropy.wcs.WCS.pixel_to_world_values and the equivalent gwcs API match this signature.

required
source_world_to_pixel callable

Inverse transform on the source WCS. Signature::

source_world_to_pixel(*world_arrays) -> (x_source, y_source)

where the inputs are the world arrays produced by target_pixel_to_world and the return is the pair of 2-D ndarrays giving source-image pixel coordinates. astropy.wcs.WCS.world_to_pixel_values matches this signature.

required
coarse_step sequence of (int, int)

Any 2-element sequence of positive ints — tuple, list, or ndarray are all accepted. If given as (step_h, step_w), evaluate the WCS callables on a coarse subgrid stepping every step_h rows and step_w columns of the target pixel grid, then bicubic-interpolate the result to the full (H_target + 1, W_target + 1) corner grid. Useful when the callables are expensive (notably JWST gwcs pipelines that solve a numerical inverse per evaluation): a 2048x2048 target with coarse_step=(64, 64) reduces the WCS call count from ~4M to ~1k. Both components must be positive and must divide their corresponding target_shape axis exactly; otherwise ValueError is raised. Default None evaluates the callables on the full corner grid (no interpolation).

None

Returns:

Type Description
ndarray

pixel_corners of shape (H_target + 1, W_target + 1, 2) and dtype float64. The last axis is (x_source, y_source). Pass it directly to reproject_exact.

Notes

Without coarse_step, the callables are evaluated once on the full (H_target + 1, W_target + 1) corner grid in a single vectorised call.

With coarse_step, the bicubic upsampling uses Catmull-Rom cubic weights with linear extrapolation at the boundary (exact reconstruction for linear corner fields, residual ~h^2 * curvature in the boundary cells for smooth fields). For typical astronomical WCS pairs with coarse_step in the 16-128 range, the residual on the corner positions is well below 0.01 source-pixel, which is negligible compared to reprojection's polygon-clip accuracy.

reproject_exact(image, pixel_corners, *, error=None) builtin

Surface-brightness-conserving exact reprojection of a 2-D image.

The caller supplies an input image on its own pixel grid plus a corner field that gives, for every node of the output pixel grid, the corresponding location in the input image's pixel coordinates. Each output pixel is then computed by polygon-clipping the input pixels that fall under the quadrilateral defined by the four output corners and taking the area-weighted mean of the contributing input values.

This package intentionally does NOT compute the corner field itself: WCS handling belongs in astropy.wcs / gwcs / equivalent. The caller is expected to map output-pixel corners through the two WCSs (output → sky → input) once and hand the resulting array to this function. The reprojection then runs entirely in input-pixel coordinates and does not require any spherical-geometry primitive.

Parameters:

Name Type Description Default
image ndarray

Input image of shape (H_in, W_in), dtype float32 or float64. NaN values are treated as masked input pixels: they are excluded from the numerator and from the valid weight, but they still count toward the geometric footprint.

required
pixel_corners ndarray

Corner field of shape (H_out + 1, W_out + 1, 2), dtype float64. The last dimension stores [x_in, y_in] — the location of each output-pixel corner in the input image's continuous pixel coordinates, using the astropy convention that integer (x, y) is the center of pixel (row=y, column=x). Adjacent output pixels share corners by construction, which makes the partition watertight. NaN corners propagate to (NaN, 0, 0) in the output for any output pixel that touches them.

required
error ndarray

1-sigma error image, same shape and dtype as image. Default None. When given, the result's error attribute is a propagated 1-sigma map; when None it is None. Supplying it does not change image, footprint, or weight.

None

Returns:

Type Description
ReprojectResult

A frozen result object whose image, footprint, and weight attributes are each (H_out, W_out) arrays of dtype float64, plus an error attribute (None when no error input was given).

  • image is the surface-brightness-conserving reprojection: sum(A_ij * image[i, j]) / sum(A_ij_valid) over the input pixels overlapping each output pixel, where A_ij is the polygon-intersection area in input-pixel units and the _valid sum excludes NaN input pixels. Output pixels with no valid contribution are NaN.
  • footprint is the pure geometric overlap fraction in [0, 1]: how much of the output pixel falls inside the input image's pixel grid, independent of whether the covered pixels are NaN. Useful to distinguish "no data because we are outside the input footprint" from "no data because the inputs were masked".
  • weight is the same numerator restricted to non-NaN input pixels, also in [0, 1]. Invariant: weight <= footprint; they are equal when no input pixel inside the overlap was NaN. The ratio weight / footprint (where footprint > 0) is the fraction of the covered region that was free of NaN.
  • error is the propagated 1-sigma error, or None when no error input was supplied. Independent first-order propagation: sqrt(sum(A_ij^2 * sigma_ij^2)) / sum(A_ij) over the valid input pixels. An output pixel is NaN where it has no valid contribution, or where a contributing pixel had a valid value but a non-finite or negative error (the value still enters image, so its unknown variance cannot be dropped). Only the marginal per-pixel 1-sigma is given; correlations between output pixels sharing input pixels are not represented.

Raises:

Type Description
ValueError

If image is not a 2-D float32 / float64 array, if pixel_corners is not a float64 array with last dimension 2 and both grid dimensions at least 2, or if error is given with a dtype other than image's or a shape other than image's.

Notes

Spherical curvature is not corrected: this is a planar polygon clip in input-pixel space. The residual error is the curvature of the input projection over a single output pixel, which is negligible for any reasonable astronomical image. Callers who need an explicit spherical treatment should pre-correct pixel_corners accordingly.

convolve_psf(image, psf) builtin

Convolve a 2-D image with a fixed, centered PSF (true convolution).

The PSF is flipped (both axes reversed) before correlation, so this is genuine convolution: an asymmetric ePSF keeps its orientation. NaN / +-inf pixels are treated as missing and excluded from both the weighted sum and its normalizer, and image edges are likewise missing — this NaN-as-missing renormalization is the image subsystem's single convention (same as reproject_exact), so there is deliberately no boundary or renormalize switch.

PSF normalization is the caller's responsibility: a sum-normalized PSF gives an interior identity with the renorm acting only at NaN / edges (flux conserving); an unnormalized PSF yields a local weighted mean instead.

Parameters:

Name Type Description Default
image ndarray

2-D image, dtype float32 or float64. NaN / +-inf are treated as missing.

required
psf ndarray

2-D PSF with odd dimensions, same dtype as image.

required

Returns:

Type Description
ndarray

The convolved image, same shape and dtype as image.

Raises:

Type Description
ValueError

If image is not a 2-D float32 / float64 array, psf dtype does not match image, or psf does not have odd dimensions.

convolve_gaussian_axis(image, *, sigma, axis=0, normalization='l2', boundary='zero', renormalize=False) builtin

Correlate every lane along axis with a 1-D Gaussian — the grism emission-line matched filter.

The kernel is built with the requested normalization ("l2" makes the peak response the matched-filter S/N-optimal statistic). This is a correlation; a Gaussian is symmetric so it coincides with convolution. renormalize=False (the matched filter's natural mode) uses boundary for out-of-bounds taps; renormalize=True uses NaN-as-missing renormalization and boundary is ignored.

Parameters:

Name Type Description Default
image ndarray

2-D image, dtype float32 or float64.

required
sigma float

Gaussian sigma in pixels along axis. Must be positive.

required
axis int

0 correlates down each column, 1 along each row. Default 0.

0
normalization (sum, l2, none)

Kernel normalization. Default "l2" (matched-filter optimal).

"sum"
boundary (zero, reflect, nearest)

Out-of-bounds handling, used only when renormalize=False. Default "zero".

"zero"
renormalize bool

When True, use NaN-as-missing renormalization (out-of-bounds is missing and boundary is ignored). Default False.

False

Returns:

Type Description
ndarray

The filtered image, same shape and dtype as image.

Raises:

Type Description
ValueError

If image is not a 2-D float32 / float64 array, sigma is not positive, axis is not 0 or 1, or normalization / boundary is invalid.

build_stamp(cutout, stamp_size, *, error=None, mask=None, weight_fwhm=3.0, max_iter=10, tol=0.001) builtin

Locate an init-quality centroid in a rough cutout, pick an integer-aligned odd square window, and slice a fixed-size stamp.

Single-image leaf for scheme C: the caller loops over N stars, cuts a rough cutout per star (via its own WCS / distortion), calls build_stamp on each, filters out the None returns, and stacks the survivors for build_epsf / build_extended_psf. The sub-pixel offset is recorded only, never applied (a sub-pixel shift would correlate the noise).

Parameters:

Name Type Description Default
cutout ndarray

Rough cutout of any shape (rows, cols), dtype float32 or float64. Determines the dtype channel; error must match. Non-finite values are excluded from the centroid and marked invalid.

required
stamp_size int

Edge length of the square output stamp. Must be odd.

required
error ndarray

1-sigma error, same shape and dtype as cutout. Default None (error-level equal weighting downstream).

None
mask ndarray of bool

True marks an invalid (excluded) pixel -- the noobase-wide polarity. Same shape as cutout. Default None.

None
weight_fwhm float

FWHM (pixels) of the Gaussian centroid window. Default 3.0.

3.0
max_iter int

Centroid iteration cap. Default 10.

10
tol float

Centroid convergence tolerance (pixels). Default 1e-3.

0.001

Returns:

Type Description
StampResult or None

None when no usable stamp can be produced (the odd window cannot fit fully inside the cutout, or there are too few valid pixels to centroid) -- an algorithmic skip, not an error. The caller filters these out before stacking.

Raises:

Type Description
ValueError

If stamp_size is even, if stamp_size exceeds a cutout dimension, if error / mask shape does not equal the cutout shape, or if an array has an unsupported dtype.

StampResult

Result of build_stamp: the integer-window stamp plus the recorded sub-pixel offset. Constructed by build_stamp; not instantiable directly.

delta property

The recorded sub-pixel offset (delta_row, delta_col) = centroid - round(centroid); each component in [-0.5, 0.5).

error property

The windowed 1-sigma error of shape (stamp_size, stamp_size), dtype float64, or None when no error was supplied.

origin property

(row, col) of the window's top-left corner in cutout-local indices. Add the caller's own cutout origin to map back to the source frame.

stamp property

The extracted stamp of shape (stamp_size, stamp_size), dtype float64. Carries the original cutout values; no background is removed (the centroid background subtraction is internal only).

valid property

Per-pixel validity of shape (stamp_size, stamp_size), dtype bool. True means valid (positive polarity -- the opposite of the input mask whose True means invalid).