Source code for psfsim.wfi_coordinate_transformations

"""Utilities for WFI coordinate systems."""

import numpy as np

from . import wfi_data
from .romantrace import _RomanRayBundle


[docs] def _from_angle_to_fpa(xan, yan, wavelength=0.48): """ Coarse transformation from field angle to FPA position. Parameters ---------- xan, yan : float Field positions in degrees. wavelength : float, optional Vacuum wavelength in microns. Returns ------- (float, float) Focal plane position in mm. """ # xan, yan in degrees, wavelength in micrometers wavindex = np.argmin(wfi_data.wavelength - wavelength) coeff = wfi_data.angle_to_fpa_poly_coefficients[wavindex] powers = xan ** wfi_data.exponents[:, 0] * yan ** wfi_data.exponents[:, 1] xterms = coeff[:, 0] * powers yterms = coeff[:, 1] * powers return (np.sum(xterms), np.sum(yterms))
[docs] def from_angle_to_fpa(xan, yan, wavelength=0.48, ray_trace=True, use_filter="H", idealgeom=False): """ Full transformation from field angle to FPA position. Parameters ---------- xan, yan : float Field positions in degrees. wavelength : float, optional Vacuum wavelength in microns. ray_trace : bool, optional Whether to use ray tracing. (Default recommended for accuracy.) use_filter : char, optional One-character code for which filter to use. idealgeom : bool, optional Forces the design model rather than with the best-fit offsets. Returns ------- (float, float) Focal plane position in mm. """ if not ray_trace: return _from_angle_to_fpa(xan, yan, wavelength=wavelength) # below here, we are doing the ray tracing xpos = _RomanRayBundle(xan, yan, 16, use_filter, idealgeom=idealgeom).x_out return (xpos[0], xpos[1])
[docs] def _from_fpa_to_angle(fpapos, wavelength=0.48): """ Coarse transformation from FPA position to field angle. Parameters ---------- fpapos : (float, float) Focal plane position in mm. wavelength : float, optional Vacuum wavelength in microns. Returns ------- (float, float) Field positions in degrees. """ # FPAx, FPAy in mm, wavelength in micrometers FPAx = fpapos[0] FPAy = fpapos[1] wavindex = np.argmin(wfi_data.wavelength - wavelength) coeff = wfi_data.fpa_to_angle_poly_coefficients[wavindex] powers = FPAx ** wfi_data.exponents[:, 0] * FPAy ** wfi_data.exponents[:, 1] xterms = coeff[:, 0] * powers yterms = coeff[:, 1] * powers return (np.sum(xterms), np.sum(yterms))
[docs] def from_fpa_to_angle(fpapos, wavelength=0.48, ray_trace=True, use_filter="H", idealgeom=False): """ Full transformation from FPA position to field angle. Parameters ---------- fpapos : (float, float) Focal plane position in mm. wavelength : float, optional Vacuum wavelength in microns. ray_trace : bool, optional Whether to use ray tracing. (Default recommended for accuracy.) use_filter : char, optional One-character code for which filter to use. idealgeom : bool, optional Forces the design model rather than with the best-fit offsets. Returns ------- (float, float) Field positions in degrees. """ xan, yan = _from_fpa_to_angle(fpapos, wavelength=wavelength) if not ray_trace: return (xan, yan) # don't iteratively improve with ray trace # iterate until we find a field position in the right place for _ in range(4): xpos = _RomanRayBundle(xan, yan, 16, use_filter, idealgeom=idealgeom).x_out xerr = fpapos[0] - xpos[0] yerr = fpapos[1] - xpos[1] xan += xerr * 0.0030556 yan -= yerr * 0.0030556 return (xan, yan)
[docs] def from_sca_to_fpa(scanum, scax, scay): """ Coordinate transformation converting SCA to FPA coordinates. The "SCA" coordinates are aligned with the SOC "Science" frame (i.e., 180 degrees rotated relative to the FPA frame). Parameters ---------- scanum : int The SCA number (1 through 18). scax, scay : float SCA coordinates in mm: (0, 0) is the center. Returns ------- (float, float) The FPA coordinates in mm. """ xfpa = np.array( [ -22.14, -22.29, -22.44, -66.42, -66.92, -67.42, -110.70, -111.48, -112.64, 22.14, 22.29, 22.44, 66.42, 66.92, 67.42, 110.70, 111.48, 112.64, ] ) yfpa = np.array( [ 12.15, -37.03, -82.06, 20.90, -28.28, -73.06, 42.20, -6.98, -51.06, 12.15, -37.03, -82.06, 20.90, -28.28, -73.06, 42.20, -6.98, -51.06, ] ) sc_index = scanum - 1 # pixsize = 0.01 # nside = 4088 if np.amin(scanum) < 1 or np.amax(scanum) > 18: raise ValueError("Invalid SCA Number") return (xfpa[sc_index] - scax, yfpa[sc_index] - scay)
[docs] def from_sca_to_analysis(scanum, scax, scay): """ Coordinate transformation converting SCA coordinates (in mm) to Analysis coordinates (in microns). The "SCA" coordinates are aligned with the SOC "Science" frame (i.e., 180 degrees rotated relative to the FPA frame). The Analysis coordinates system is defined to be the FPA coordinate system with origin shifted to the center of the SCA. Parameters ---------- scanum : int The SCA number (1 through 18). scax, scay : float SCA coordinates in mm: (0, 0) is the center. Returns ------- (float, float) The analysis coordinates in microns. """ # sc_index = scanum - 1 # pixsize = 10 # microns # nside = 4088 if np.amin(scanum) < 1 or np.amax(scanum) > 18: raise ValueError("Invalid SCA Number") return (-1000.0 * scax, -1000.0 * scay)