Source code for exosim.utils.aperture

import logging

import numpy as np
from photutils.aperture import (
    EllipticalAperture,
    RectangularAperture,
    aperture_photometry,
)
from scipy.optimize import minimize

[docs]logger = logging.getLogger(__name__)
[docs]def find_rectangular_aperture( ima, desired_ene, center=None, start_h=None, start_w=None ): """ Estimates the smallest rectangular aperture to collect the desired Encircled Energy from a PSF. It uses :func:`photutils.aperture.aperture_photometry`. Parameters ---------- ima: :class:`~numpy.ndarray` two-dimensional array. desired_ene: float desired Encircled Energy center: (float, float) spectral and spatial coordinates of the aperture center in pixels. If None the center of the array is used. Default is `None` start_h: int starting aperture height start_w: int starting aperture width Returns ------- (float, float) sizes of the rectangular aperture (h,w) float number of pixels in the aperture float encircled energy collected by the aperture Example -------- In this example we find the optimal aperture containing the 85% of the energy of a PSF. >>> import matplotlib.pyplot as plt >>> import astropy.units as u >>> import photutils >>> from exosim.utils.aperture import find_rectangular_aperture >>> from exosim.utils.psf import create_psf >>> >>> img = create_psf(1*u.um, (60,40), 6*u.um) >>> size, area, ene = find_rectangular_aperture(img, 0.85) >>> positions = [(img.shape[1]//2,img.shape[0]//2)] >>> aperture = photutils.aperture.RectangularAperture(positions, size[0], size[1]) >>> >>> plt.imshow(img) >>> aperture.plot(color='r', lw=2,) >>> plt.show() .. plot:: mpl_examples/find_rectangular_aperture.py """ center = center if center else (ima.shape[1] / 2, ima.shape[0] / 2) def ene_func(center, h, w, ima): aper = RectangularAperture(center, h=h, w=w) phot_ = aperture_photometry(ima, aper) phot = phot_["aperture_sum"].data[0] return phot / ima.sum() def ene_fit(pos, center, ima, desired_ene): ene = ene_func(center, pos[0], pos[1], ima) enec = np.abs(ene - desired_ene) return enec start_h_ = start_h if start_h else 2.0 start_w_ = start_w if start_w else 2.0 res = minimize( ene_fit, x0=np.array([float(start_h_), float(start_w_)]), args=(center, ima, desired_ene), method="Nelder-Mead", tol=1.0e-6, ) h = res.x[0] w = res.x[1] return (w, h), h * w, ene_func(center, h, w, ima)
[docs]def find_elliptical_aperture(ima, desired_ene, center=None): """ Estimates the smallest elliptical aperture to collect the desired Encircled Energy from a PSF. It uses :func:`photutils.aperture.aperture_photometry`. Parameters ---------- ima: :class:`~numpy.ndarray` two-dimensional array. desired_ene: float desired Encircled Energy center: (float, float) spectral and spatial coordinates of the aperture center in pixels. If None the center of the array is used. Default is `None` Returns ------- (float, float) sizes of the elliptical aperture (h,w) float number of pixels in the aperture float encircled energy collected by the aperture Example -------- In this example we find the optimal aperture containing the 85% of the energy of a PSF. >>> import matplotlib.pyplot as plt >>> import astropy.units as u >>> import photutils >>> from exosim.utils.psf import find_elliptical_aperture >>> from exosim.utils.psf import create_psf >>> >>> img = create_psf(1*u.um, (60,40), 6*u.um) >>> size, area, ene = find_elliptical_aperture(img, 0.85) >>> positions = [(img.shape[1]//2,img.shape[0]//2)] >>> aperture = photutils.aperture.EllipticalAperture(positions, size[0], size[1]) >>> >>> plt.imshow(img) >>> aperture.plot(color='r', lw=2,) >>> plt.show() .. plot:: mpl_examples/find_elliptical_aperture.py """ center = center if center else (ima.shape[1] / 2, ima.shape[0] / 2) def ene_func(center, a, b, ima): aper = EllipticalAperture(center, a=a, b=b) phot_ = aperture_photometry(ima, aper) phot = phot_["aperture_sum"].data[0] return phot / ima.sum() def ene_fit(pos, center, ima, desired_ene): ene = ene_func(center, pos[0], pos[1], ima) enec = np.abs(ene - desired_ene) return enec res = minimize( ene_fit, x0=np.array([1, 1]), args=(center, ima, desired_ene), method="Nelder-Mead", tol=1.0e-6, ) a = res.x[0] b = res.x[1] return (a, b), a * b, ene_func(center, a, b, ima)
[docs]def find_bin_aperture(ima, desired_ene, spatial_with, center=None): """ Estimates the smallest rectangular aperture for spectral bin of already fixed spatial size to collect the desired Encircled Energy from a PSF. It uses :func:`photutils.aperture.aperture_photometry`. Parameters ---------- ima: :class:`~numpy.ndarray` two-dimensional array. spatial_with: float fixed bin spatial size desired_ene: float desired Encircled Energy center: (float, float) spectral and spatial coordinates of the aperture center in pixels. If None the center of the array is used. Default is `None` Returns ------- float spectral size of the rectangular aperture float number of pixels in the aperture float encircled energy collected by the aperture """ center = center if center else (ima.shape[1] / 2, ima.shape[0] / 2) def ene_func(center, h, w, psf): aper = RectangularAperture(center, h=h, w=w) phot_ = aperture_photometry(psf, aper) phot = phot_["aperture_sum"].data[0] aper_full = RectangularAperture(center, h=psf.shape[1], w=w) phot_ = aperture_photometry(psf, aper_full) phot_full = phot_["aperture_sum"].data[0] return phot / phot_full def ene_fit(pos, spatial_with, center, ima, desired_ene): h = pos[0] ene = ene_func(center, h, spatial_with, ima) enec = np.abs(ene - desired_ene) return enec res = minimize( ene_fit, x0=np.array([2.0]), args=(spatial_with, center, ima, desired_ene), method="Nelder-Mead", tol=1.0e-6, ) h = res.x[0] return h, h * spatial_with, ene_func(center, h, spatial_with, ima)