Source code for exosim.tasks.radiometric.estimateApertures
import numpy as np
from astropy.table import QTable
from scipy.interpolate import interp1d
import exosim.utils.aperture as aperture
from exosim.tasks.task import Task
[docs]class EstimateApertures(Task):
"""
It returns the sizes of the apertures to perform photometry for :func:`photutils.aperture.aperture_photometry`.
The details of the apertures depends on the configurations set by the user.
Returns
--------
astropy.table.QTable:
Raises
--------
TypeError:
if the output is not :class:`~astropy.table.QTable`
Notes
-----
This is a default class with standardised inputs and outputs.
The user can load this class and overwrite the "model" method
to implement a custom Task to replace this.
"""
def __init__(self):
"""
Parameters
--------------
table: :class:`astropy.table.QTable`
wavelength table with bin edge
focal_plane:
focal plane
Default is 'wl_solution`.
wl_grid: (optional)
focal plane wavelength solution
description: dict (optional)
channel description
"""
self.add_task_param("table", "wavelength table with bin edges")
self.add_task_param("focal_plane", "focal plane")
# self.add_task_param('spatial_mode',
# 'aperture in spatial direction',
# 'column')
# self.add_task_param('spectral_mode',
# 'aperture in spectral direction',
# 'wl_solution')
self.add_task_param("wl_grid", "focal plane wavelength solution", None)
self.add_task_param("description", "channel description", None)
self.add_task_param("auto_mode", "automatic aperture mode", None)
[docs] def execute(self):
self.debug("performing aperture photometry")
table = self.get_task_param("table")
wl_grid = self.get_task_param("wl_grid")
focal_plane = self.get_task_param("focal_plane")
description = self.get_task_param("description")
new_tab = self.model(table, focal_plane, description, wl_grid)
if not isinstance(new_tab, QTable):
self.error("wrong output format")
raise TypeError("wrong output format")
self.set_output(new_tab)
[docs] def model(self, table, focal_plane, description, wl_grid):
"""
It returns the sizes of the apertures to perform photometry for :func:`photutils.aperture.aperture_photometry`.
The default methods to estimate the aperture are the following and these are also the keywords required for the `description` dictionary.
+ spatial_mode: str
aperture in spatial direction. If `column` the aperture spatial length is the full pixel column in the array.
Default is `column`.
+ spectral_mode: str
aperture in spectral direction. If `row` the aperture is spectral length is the full pixel row of the array.
If `wl_solution` the spectral size is the same of the spectral bin in the input table.
Default is 'wl_solution`.
+ auto_mode: str
automatic aperture mode. The dictionary must contains two keywords.
The `mode` keyword should be a str: if `rectangular` then :func:`~exosim.utils.psf.find_rectangular_aperture` is used;
if `elliptical` then :func:`~exosim.utils.psf.find_elliptical_aperture` is used;
if `bin` then :func:`~exosim.utils.psf.find_bin_aperture` is used;
if `full` then the full array is integrated.
+ Ene: float
The `EnE` keyword should be a float and represents the Encircled Energy to include in the aperture.
Parameters
--------------
table: :class:`astropy.table.QTable`
wavelength table with bin edge
focal_plane:
focal plane
description: dict
dictionary containing the aperture photometry description
Returns
--------
astropy.table.QTable:
"""
# spectral settings
if "spectral_mode" in description.keys():
if description["spectral_mode"] == "row":
self.debug("spectral mode: row")
wlc = [focal_plane.shape[1] / 2] * table["Wavelength"].size
dwl = [focal_plane.shape[1]] * table["Wavelength"].size
shape = "rectangular"
elif description["spectral_mode"] == "wl_solution":
self.debug("computing wavelength solution")
if wl_grid is None:
self.error("focal plane wavelength solution missing")
raise OSError("focal plane wavelength solution missing")
wl_sol = interp1d(
wl_grid,
np.arange(0, focal_plane.shape[1]),
fill_value="extrapolate",
)
wlc = wl_sol(table["Wavelength"])
wld = wl_sol(table["left_bin_edge"])
wlu = wl_sol(table["right_bin_edge"])
dwl = abs(wlu - wld)
shape = "rectangular"
else:
self.error("not supported spectral mode")
raise OSError("not supported spectral mode")
# spatial settings
if "spatial_mode" in description.keys():
if description["spatial_mode"] == "column":
self.debug("spatial mode: column")
spc = [focal_plane.shape[0] / 2] * table["Wavelength"].size
dsp = [focal_plane.shape[0]] * table["Wavelength"].size
shape = "rectangular"
else:
self.error("not supported spatial mode")
raise OSError("not supported spatial mode")
# automatic settings
if "auto_mode" in description.keys():
if description["auto_mode"] == "full":
wlc = [focal_plane.shape[1] / 2] * table["Wavelength"].size
dwl = [focal_plane.shape[1]] * table["Wavelength"].size
spc = [focal_plane.shape[0] / 2] * table["Wavelength"].size
dsp = [focal_plane.shape[0]] * table["Wavelength"].size
shape = "rectangular"
if description["auto_mode"] == "elliptical":
ene = description["EnE"]
sizes, surf, ene = aperture.find_elliptical_aperture(
focal_plane, ene
)
wlc = [focal_plane.shape[1] / 2] * table["Wavelength"].size
dwl = [sizes[0]] * table["Wavelength"].size
spc = [focal_plane.shape[0] / 2] * table["Wavelength"].size
dsp = [sizes[1]] * table["Wavelength"].size
shape = "elliptical"
if description["auto_mode"] == "rectangular":
ene = description["EnE"]
sizes, surf, ene = aperture.find_rectangular_aperture(
focal_plane, ene
)
wlc = [focal_plane.shape[1] / 2] * table["Wavelength"].size
dwl = [sizes[1]] * table["Wavelength"].size
spc = [focal_plane.shape[0] / 2] * table["Wavelength"].size
dsp = [sizes[0]] * table["Wavelength"].size
shape = "rectangular"
if description["auto_mode"] == "bin":
ene = description["EnE"]
if wl_grid is None:
self.error("focal plane wavelength solution missing")
raise OSError("focal plane wavelength solution missing")
wl_sol = interp1d(
wl_grid,
np.arange(0, focal_plane.shape[1]),
fill_value="extrapolate",
)
wlc = wl_sol(table["Wavelength"])
wld = wl_sol(table["left_bin_edge"])
wlu = wl_sol(table["right_bin_edge"])
dwl = abs(wlu - wld)
spc = [focal_plane.shape[0] / 2] * table["Wavelength"].size
dsp = [1] * table["Wavelength"].size
shape = "rectangular"
self.debug("estimating apertures for spectral bins")
for i in range(wlc.size):
size, surf, ene = aperture.find_bin_aperture(
focal_plane,
ene,
spatial_with=dwl[i],
center=(wlc[i], spc[i]),
)
dsp[i] *= size
new_tab = QTable()
new_tab["spectral_center"] = wlc
new_tab["spectral_size"] = dwl
new_tab["spatial_center"] = spc
new_tab["spatial_size"] = dsp
new_tab["aperture_shape"] = shape
return new_tab