dfreproject.reproject

Attributes

logger

EPSILON

VALID_ORDERS

Classes

Reproject

Functions

validate_interpolation_order(→ str)

Function to validate the requested interpolation order.

atan2d(→ torch.Tensor)

PyTorch implementation of WCSLib's atan2d function.

sincosd(→ torch.Tensor)

PyTorch implementation of WCSLib's sincosd function.

interpolate_image(→ torch.Tensor)

Image interpolation using grid_sample with LANCZOS support.

calculate_reprojection(source_hdus, target_wcs[, ...])

Reproject an astronomical image from a source WCS to a target WCS.

Module Contents

dfreproject.reproject.logger[source]
dfreproject.reproject.EPSILON = 1e-10[source]
dfreproject.reproject.VALID_ORDERS = ['bicubic', 'bilinear', 'nearest', 'nearest-neighbors', 'lanczos'][source]
dfreproject.reproject.validate_interpolation_order(order: str) str[source]

Function to validate the requested interpolation order.

The order must be one of the following: “bicubic”, “bilinear”, “nearest-neighbors”. “nearest” is an alias for “nearest-neighbors”.

Parameters:

order (str) – Interpolation order to validate.

Returns:

Validated interpolation order.

Return type:

str

Raises:

ValueError – When the provided order is not one of the valid interpolation orders.

dfreproject.reproject.atan2d(y: torch.Tensor, x: torch.Tensor) torch.Tensor[source]

PyTorch implementation of WCSLib’s atan2d function.

Parameters:
  • y (torch.Tensor) – y coordinate(s).

  • x (torch.Tensor) – x coordinate(s).

Returns:

atan2d(y, x) in degrees.

Return type:

torch.Tensor

dfreproject.reproject.sincosd(angle_deg: torch.Tensor) torch.Tensor[source]

PyTorch implementation of WCSLib’s sincosd function.

Parameters:

angle_deg (torch.Tensor) – angle in degrees.

Returns:

sin(angle) in degrees, cos(angle) in degrees.

Return type:

tuple(torch.Tensor, torch.Tensor)

dfreproject.reproject.interpolate_image(source_image: torch.Tensor, grid: torch.Tensor, interpolation_mode: str) torch.Tensor[source]

Image interpolation using grid_sample with LANCZOS support.

Parameters:
  • source_image (torch.Tensor) – Source image to interpolate.

  • grid (torch.Tensor) – Grid on which to interpolate.

  • interpolation_mode (str) – Interpolation mode to use. Supports PyTorch’s built-in modes (‘bilinear’, ‘bicubic’, ‘nearest’) plus ‘lanczos’ for LANCZOS-3.

Returns:

Interpolated image.

Return type:

torch.Tensor

class dfreproject.reproject.Reproject(source_hdus: List[astropy.io.fits.PrimaryHDU], target_wcs: astropy.wcs.WCS, shape_out: Tuple[int, int], device: str = None, num_threads: int = None, requires_grad: bool = False, conserve_flux: bool = True, compute_jacobian: bool = True)[source]
requires_grad = False[source]
batch_source_images[source]
batch_source_wcs_params[source]
target_wcs_params[source]
target_wcs[source]
target_grid[source]
conserve_flux = True[source]
compute_jacobian = True[source]
calculate_skyCoords(x_grid=None, y_grid=None) Tuple[torch.Tensor, torch.Tensor][source]

Calculate sky coordinates.

There are four primary steps: 1. Apply shift 2. Apply SIP distortion 3. Apply CD matrix 4. Apply transformation to celestial coordinates uing the Gnomonic Projection

These steps use the target wcs parameters.

Parameters:
  • x_grid (torch.Tensor, optional) – Batch of x-coordinates. If None, uses target grid x-coordinates.

  • y_grid (torch.Tensor, optional) – Batch of y-coordinates. If None, uses target grid y-coordinates.

Returns:

Batched RA and Dec coordinates.

Return type:

tuple

calculate_sourceCoords()[source]

Calculate source image pixel coordinates corresponding to each target image pixel.

This function repeats the same steps in self.calculate_skyCoords() except in the opposite order and with the source coordinate wcs.

Returns:

Batch of source image pixel coordinates.

Return type:

torch.Tensor

compute_pixel_map()[source]

Compute and return source-space pixel coordinates for reprojection.

This method exposes the pixel mapping step used by interpolate_source_image(), allowing callers to inspect, cache, or reuse the coordinate transform without immediately interpolating image values.

Returns:

(x_source, y_source) pixel coordinates in source-image index space (unnormalized; not in grid_sample [-1, 1] coordinates).

Return type:

Tuple[torch.Tensor, torch.Tensor]

apply_pixel_map(pixel_map: Tuple[torch.Tensor, torch.Tensor], interpolation_mode: str = 'bilinear') torch.Tensor[source]

Interpolate the source image using a precomputed pixel map.

Use this method with a map returned by compute_pixel_map() when you want to reuse the same coordinate transform across repeated interpolation calls.

Parameters:
  • pixel_map (Tuple[torch.Tensor, torch.Tensor]) – (x_source, y_source) coordinates from compute_pixel_map().

  • interpolation_mode (str, default 'bilinear') – Interpolation algorithm. Options: 'nearest', 'bilinear', 'bicubic', 'lanczos'.

Returns:

Reprojected image on the target grid.

Return type:

torch.Tensor

interpolate_source_image(interpolation_mode='bilinear') torch.Tensor[source]

Interpolate the source image at the calculated source coordinates with flux conservation.

This is a convenience wrapper around:

  1. compute_pixel_map()

  2. apply_pixel_map()

If you need access to the pixel map itself, call compute_pixel_map() directly and pass it to apply_pixel_map().

This method performs the actual pixel resampling needed for dfreproject while preserving the total flux (photometric accuracy) by using a footprint correction and the Jacobian of the transformation.

The method uses a combined tensor approach for computational efficiency, performing both image resampling and footprint tracking in a single operation. Total flux is conserved locally (via footprint correction and the Jacobian SIP calculation).

Parameters:

interpolation_mode (str, default 'bilinear') –

The interpolation mode to use when sampling the source image. Options include: - ‘nearest’ : Nearest neighbor interpolation (no interpolation) - ‘bilinear’ : Bilinear interpolation (default) - ‘bicubic’ : Bicubic interpolation - ‘lanczos’ : Lanczos interpolation

These correspond to the modes available in torch.nn.functional.grid_sample.

Returns:

The reprojected image with the same shape as the target image. Pixel values are interpolated from the source image according to the WCS transformation with flux conservation preserved.

Return type:

torch.Tensor

Notes

This implementation uses a two-step flux conservation approach:

  1. Local flux density conservation: The image and a “ones” tensor are interpolated together, and the interpolated image is divided by the interpolated ones tensor (footprint) to correct for any flux density spreading during interpolation. This is important when for pixels at the edge of the input image when mapped to the output image in case the input image only partially fills the output pixel.

  2. Jacobian correction for full flux conservation: Multiply the footprint-corrected flux by the determinant of the Jacobian to handle changes in area during the reprojection

The Jacobian correction can be circumvented if you set compute_jacobian=False. However, the default behavior is to include this.

Areas in the target image that map outside the source image boundaries will be filled with NaNs.

dfreproject.reproject.calculate_reprojection(source_hdus: astropy.io.fits.PrimaryHDU | dfreproject.tensorhdu.TensorHDU | Tuple[numpy.ndarray, astropy.wcs.WCS | astropy.io.fits.Header] | Tuple[torch.Tensor, astropy.wcs.WCS | astropy.io.fits.Header] | List[astropy.io.fits.PrimaryHDU | Tuple[numpy.ndarray, astropy.wcs.WCS | astropy.io.fits.Header]], target_wcs: astropy.wcs.WCS | astropy.io.fits.Header, shape_out: Tuple[int, int] | None = None, order: str = 'nearest', device: str = None, num_threads: int = None, requires_grad: bool = False, conserve_flux: bool = True, compute_jacobian: bool = True, max_memory_mb: float | None = None, chunk_safety_factor: float = 0.8, show_chunk_progress: bool = True, show_log: bool = False)[source]

Reproject an astronomical image from a source WCS to a target WCS.

This high-level function provides a convenient interface for image reprojection, handling all the necessary steps: WCS extraction, tensor creation, and interpolation. It converts FITS HDU objects to the internal representation, performs the reprojection, and returns the resulting image as a NumPy array or PyTorch tensor.

Parameters:

source_hdus (PrimaryHDU, TensorHDU, tuple, or list) –

The source image(s) to be reprojected. Can be:
  • A PrimaryHDU

  • A TensorHDU

  • A tuple of (np.ndarray or torch.Tensor, WCS or Header)

  • A list of any of the above

target_wcsUnion[WCS, Header]

WCS information for the target. If a Header is passed it will be converted to WCS.

shape_out: Optional[Tuple[int, int]]

Shape of the resampled array. If not provided, the output shape will match the input.

orderstr, default ‘nearest’

The interpolation method to use when resampling the source image. Options: - ‘nearest’ : Nearest neighbor interpolation (fastest, default) - ‘bilinear’ : Bilinear interpolation (good balance of speed/quality) - ‘bicubic’ : Bicubic interpolation (high quality, slow) - ‘lanczos’ : Lanczos 3-lobe interpolation (highest quality, slowest)

device: str, optional

Device to use for computations. Defaults to GPU if available, otherwise uses CPU.

num_threads: int, optional

Number of threads to use on CPU.

requires_grad: bool, optional

If True, enables autograd for PyTorch tensors.

conserve_flux: bool, optional

If True, enables flux conservation through footprint calculations. By default, this is set to True.

compute_jacobian: bool, optional

If True, enables non-linear flux conservation through Jacobian calculation. Note that this slightly increases RAM usage. By default, this is set to True. If there is no SIP distortion, users can set this to False.

max_memory_mb: Optional[float], optional

Maximum memory to use in megabytes for chunked processing. If None (default), processes the entire image at once without chunking. Set this to enable memory-limited chunked processing (e.g., 1000 for 1GB limit).

chunk_safety_factor: float, optional

Safety factor (0-1) for chunked processing. Default 0.8 means use 80% of max_memory_mb for actual data, leaving 20% margin. Only used if max_memory_mb is set.

show_chunk_progress: bool, optional

Whether to log progress when using chunked processing. Default True. Only used if max_memory_mb is set.

show_log: bool, optional

Whether to log progress. Default True.

Returns:

The reprojected image as a numpy ndarray (default) or PyTorch tensor if requires_grad=True.

Return type:

numpy.ndarray or torch.Tensor

Notes

This function automatically: - Detects and uses GPU acceleration if available - Handles byte order conversion for tensor creation - Converts data to float64 for processing - Converts Header to WCS if needed - Processes in memory-constrained chunks if max_memory_mb is specified

Chunked Processing: When max_memory_mb is set, the reprojection is computed in blocks to stay within the specified memory limit. This is useful for: - Very large output images - Limited GPU memory - Batch processing multiple images

To save the result as a FITS file, convert the tensor back to a NumPy array and create a new FITS HDU with the target WCS header.

Examples

>>> from astropy.io import fits
>>> from astropy.wcs import WCS
>>> from dfreproject.reproject import calculate_reprojection
>>>
>>> # Open source and target images
>>> source_hdu = fits.open('source_image.fits')[0]
>>> target_hdu = fits.open('target_grid.fits')[0]
>>> target_wcs = WCS(target_hdu.header)
>>>
>>> # Perform reprojection with bilinear interpolation
>>> reprojected = calculate_reprojection(
...     source_hdus=source_hdu,
...     target_wcs=target_wcs,
...     shape_out=target_hdu.data.shape,
...     order='bilinear'
... )
>>>
>>> # Perform chunked reprojection with 2GB memory limit
>>> reprojected = calculate_reprojection(
...     source_hdus=source_hdu,
...     target_wcs=target_wcs,
...     shape_out=(8000, 8000),
...     order='bilinear',
...     max_memory_mb=2000
... )
>>> # Save as FITS
>>> output_hdu = fits.PrimaryHDU(data=reprojected, header=target_hdu.header)
>>> output_hdu.writeto('reprojected_image.fits', overwrite=True)