Source code for photutils.psf.matching.fourier
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
This module provides tools for matching PSFs using Fourier methods.
"""
import numpy as np
from numpy.fft import fft2, fftshift, ifft2, ifftshift
from scipy.ndimage import zoom
__all__ = ['create_matching_kernel', 'resize_psf']
[docs]
def resize_psf(psf, input_pixel_scale, output_pixel_scale, *, order=3):
"""
Resize a PSF using spline interpolation of the requested order.
Parameters
----------
psf : 2D `~numpy.ndarray`
The 2D data array of the PSF.
input_pixel_scale : float
The pixel scale of the input ``psf``. The units must match
``output_pixel_scale``.
output_pixel_scale : float
The pixel scale of the output ``psf``. The units must match
``input_pixel_scale``.
order : float, optional
The order of the spline interpolation (0-5). The default is 3.
Returns
-------
result : 2D `~numpy.ndarray`
The resampled/interpolated 2D data array.
"""
ratio = input_pixel_scale / output_pixel_scale
return zoom(psf, ratio, order=order) / ratio**2
[docs]
def create_matching_kernel(source_psf, target_psf, *, window=None):
"""
Create a kernel to match 2D point spread functions (PSF) using the
ratio of Fourier transforms.
Parameters
----------
source_psf : 2D `~numpy.ndarray`
The source PSF. The source PSF should have higher resolution
(i.e., narrower) than the target PSF. ``source_psf`` and
``target_psf`` must have the same shape and pixel scale.
target_psf : 2D `~numpy.ndarray`
The target PSF. The target PSF should have lower resolution
(i.e., broader) than the source PSF. ``source_psf`` and
``target_psf`` must have the same shape and pixel scale.
window : callable, optional
The window (or taper) function or callable class instance used
to remove high frequency noise from the PSF matching kernel.
Some examples include:
* `~photutils.psf.matching.HanningWindow`
* `~photutils.psf.matching.TukeyWindow`
* `~photutils.psf.matching.CosineBellWindow`
* `~photutils.psf.matching.SplitCosineBellWindow`
* `~photutils.psf.matching.TopHatWindow`
For more information on window functions and example usage, see
:ref:`psf_matching`.
Returns
-------
kernel : 2D `~numpy.ndarray`
The matching kernel to go from ``source_psf`` to ``target_psf``.
The output matching kernel is normalized such that it sums to 1.
"""
# inputs are copied so that they are not changed when normalizing
source_psf = np.copy(np.asanyarray(source_psf))
target_psf = np.copy(np.asanyarray(target_psf))
if source_psf.shape != target_psf.shape:
raise ValueError('source_psf and target_psf must have the same shape '
'(i.e., registered with the same pixel scale).')
# ensure input PSFs are normalized
source_psf /= source_psf.sum()
target_psf /= target_psf.sum()
source_otf = fftshift(fft2(source_psf))
target_otf = fftshift(fft2(target_psf))
ratio = target_otf / source_otf
# apply a window function in frequency space
if window is not None:
ratio *= window(target_psf.shape)
kernel = np.real(fftshift(ifft2(ifftshift(ratio))))
return kernel / kernel.sum()