"""
Module to detect candidates in an image
"""
import logging
from pathlib import Path
import astropy
import numpy as np
import pandas as pd
from astropy import units as u
from astropy.coordinates import SkyCoord, match_coordinates_sky
from mirar.data import Image, ImageBatch, SourceBatch, SourceTable
from mirar.paths import (
BASE_NAME_KEY,
CAND_DEC_KEY,
CAND_RA_KEY,
SEXTRACTOR_HEADER_KEY,
SOURCE_HISTORY_KEY,
SOURCE_NAME_KEY,
XPOS_KEY,
YPOS_KEY,
get_output_dir,
)
from mirar.processors.astromatic import Sextractor
from mirar.processors.base_processor import BaseSourceGenerator, PrerequisiteError
from mirar.utils.ldac_tools import get_table_from_ldac
logger = logging.getLogger(__name__)
[docs]
def generate_candidates_table(
image: Image,
sextractor_catalog_path: str | Path,
target_only: bool = True,
) -> pd.DataFrame:
"""
Generate a candidates table from a sextractor catalog
:param image: Image object
:param sextractor_catalog_path: Path to the sextractor catalog
:param target_only: Whether to return only the target source
:return: Candidates table
"""
det_srcs = get_table_from_ldac(sextractor_catalog_path)
logger.debug(f"Found {len(det_srcs)} sources in image.")
multi_col_mask = [det_srcs.dtype[i].shape != () for i in range(len(det_srcs.dtype))]
if np.sum(multi_col_mask) != 0:
logger.warning(
"Sextractor catalog contains multi-dimensional columns, "
"removing them before converting to pandas dataframe"
)
to_remove = np.array(det_srcs.colnames)[multi_col_mask]
det_srcs.remove_columns(to_remove)
if target_only:
logger.debug(
f"Isolating target from sextractor catalog, "
f"at position {image[CAND_RA_KEY]}, {image[CAND_DEC_KEY]}."
)
det_srcs = isolate_target(image, det_srcs)
det_srcs = det_srcs.to_pandas()
ydims, xdims = image.get_data().shape
det_srcs["NAXIS1"] = xdims
det_srcs["NAXIS2"] = ydims
det_srcs[XPOS_KEY] = det_srcs["X_IMAGE"] - 1
det_srcs[YPOS_KEY] = det_srcs["Y_IMAGE"] - 1
det_srcs[CAND_RA_KEY] = det_srcs["ALPHAWIN_J2000"]
det_srcs[CAND_DEC_KEY] = det_srcs["DELTAWIN_J2000"]
det_srcs["fwhm"] = det_srcs["FWHM_IMAGE"]
det_srcs["elong"] = det_srcs["ELONGATION"]
det_srcs[SOURCE_HISTORY_KEY] = pd.DataFrame()
det_srcs[SOURCE_NAME_KEY] = None
return det_srcs
[docs]
def isolate_target(
image: Image,
sextractor_catalog: astropy.table.Table,
) -> astropy.table.Table:
"""
Args:
image: Image object containing the target source coordinates
sextractor_catalog: sextractor catalog as an astropy Table
Returns: Table with len=1, the target source from the sextractor catalog
"""
cat_coords = SkyCoord(
ra=sextractor_catalog["ALPHAWIN_J2000"],
dec=sextractor_catalog["DELTAWIN_J2000"],
unit=(u.deg, u.deg),
)
targ_coords = SkyCoord(
ra=image[CAND_RA_KEY], dec=image[CAND_DEC_KEY], unit=(u.deg, u.deg)
)
idx, _, __ = match_coordinates_sky(targ_coords, cat_coords)
matched_sextractor_catalog = sextractor_catalog[idx]
logger.debug(
f"Found nearest neighbor source at "
f"{matched_sextractor_catalog['ALPHAWIN_J2000']}, "
f"{matched_sextractor_catalog['DELTAWIN_J2000']}"
)
return astropy.table.Table(matched_sextractor_catalog)