"""
Functions to get image coordinates from WCS
"""
import logging
from pathlib import Path
import numpy as np
from astropy import units as u
from astropy.io import fits
from astropy.units import Quantity
from astropy.wcs import WCS
from mirar.data import Image
logger = logging.getLogger(__name__)
[docs]
def get_image_center_wcs_coords(image: Image, origin: int = 0):
"""
Get RA/Dec of an image
Args:
origin: 0 or 1, depending on whether you want it in DS9 coordinates
image: Image
Returns:
"""
header = image.header
wcs = WCS(header=header)
nx, ny = header["NAXIS1"], header["NAXIS2"]
ra_deg, dec_deg = wcs.all_pix2world([nx / 2], [ny / 2], origin)
return ra_deg[0], dec_deg[0]
[docs]
def get_xy_from_wcs(
ra_deg: float,
dec_deg: float,
header: fits.Header,
origin: int = 0,
) -> (float, float):
"""
Get image x-y coordinates of a given ra/dec
Args:
ra_deg: RA in decimal degrees
dec_deg: Dec in decimal degrees
header: image header, requires WCS keywords
origin: 0 or 1, depending on whether you want it in DS9 coordinates
Returns:
x: x coordinate
y: y coordinate
"""
wcs = WCS(header)
x, y = wcs.all_world2pix(ra_deg, dec_deg, origin)
return float(x), float(y)
[docs]
def write_regions_file(
regions_path: str | Path,
x_coords: list[float],
y_coords: list[float],
system: str = "image",
region_radius: float = 5,
text: list | None = None,
):
"""
Function to write a regions file
Args:
regions_path: str, path to regions file
x_coords: list, x-coordinates or RA
y_coords: list, y-coordinates or Dec
system: str, image or wcs
region_radius: float, radius of circle
text: list, text to accompany the regions file
Returns:
"""
logger.debug(f"Writing regions path to {regions_path}")
if text is not None:
assert len(text) == len(x_coords) == len(y_coords), (
"Text must be same size as coordinates, found len(text) = "
f"{len(text)}, len(x_coords) = {len(x_coords)}, len(y_coords) = "
f"{len(y_coords)}"
)
with open(f"{regions_path}", "w", encoding="utf8") as regions_f:
regions_f.write(f"{system}\n")
for ind, x in enumerate(x_coords):
line = f"CIRCLE({x},{y_coords[ind]},{region_radius})"
if text is not None:
line += " # text={" + text[ind] + "}"
regions_f.write(f"{line}\n")
[docs]
def check_coords_within_image(
ra: float | list[float], dec: float | list[float], header: fits.Header
) -> list[bool]:
"""
Check that the coordinates are within the image
Args:
:param ra: RA in decimal degrees
:param dec: Dec in decimal degrees
:param header: Image header with WCS info.
Returns:
:return: True if within image, False if not
"""
if isinstance(ra, float):
ra = [ra]
if isinstance(dec, float):
dec = [dec]
wcs = WCS(header)
nx, ny = header["NAXIS1"], header["NAXIS2"]
x, y = wcs.all_world2pix(ra, dec, 0)
return np.invert((x < 0) | (x > nx) | (y < 0) | (y > ny))