Source code for eloy.utils

"""
General utilities for astronomical image analysis.

This module provides helper functions for cutouts, statistical metrics,
binning, and generating synthetic images.
"""

from astropy.nddata import Cutout2D
import numpy as np
from astropy.nddata import Cutout2D
from astropy.nddata.utils import NoOverlapError


[docs] def cutout(data, coords, shape, wcs=None, fill_value=np.nan): """ Extract cutouts from data at given coordinates. Parameters ---------- data : np.ndarray 2D image data. coords : array-like List of (x, y) coordinates. shape : tuple Shape of the cutout. wcs : WCS or None, optional World Coordinate System object. Returns ------- np.ndarray Array of cutout images. """ values = [] dummy = np.zeros(shape, dtype=data.dtype) for coords in coords: try: cutout = Cutout2D( data, coords, shape, wcs=wcs, fill_value=fill_value, mode="partial" ) except NoOverlapError: cutout = dummy values.append(cutout.data) return np.array(values)
[docs] def std_diff_metric(fluxes): """ Compute the standard deviation of the difference along the last axis. Parameters ---------- fluxes : np.ndarray Fluxes array. Returns ------- np.ndarray Standard deviation of the differences. """ k = len(list(np.shape(fluxes))) return np.std(np.diff(fluxes, axis=k - 1), axis=k - 1)
[docs] def stability_aperture(fluxes): """ Compute the mean absolute difference between consecutive fluxes. Parameters ---------- fluxes : np.ndarray Fluxes array. Returns ------- np.ndarray Mean absolute difference for each aperture. """ lc_c = np.abs(np.diff(fluxes, axis=0)) return np.mean(lc_c, axis=1)
[docs] def index_binning(x, size): """ Bin indices of x into bins of given size. Parameters ---------- x : array-like Array to bin. size : int or float Bin size. Returns ------- list List of arrays of indices for each bin. """ if isinstance(size, float): bins = np.arange(np.min(x), np.max(x), size) else: x = np.arange(0, len(x)) bins = np.arange(0.0, len(x), size) d = np.digitize(x, bins) n = np.max(d) + 2 indexes = [] for i in range(0, n): s = np.where(d == i) if len(s[0]) > 0: s = s[0] indexes.append(s) return indexes
[docs] def binned_nanstd(x, bins: int = 12): """ Return a function to compute the mean of the standard deviation in bins. Parameters ---------- x : np.ndarray Array to bin. bins : int, optional Number of bins. Returns ------- callable Function that computes the mean of the standard deviation in bins. """ # set binning idxs for white noise evaluation bins = np.min([x.shape[-1], bins]) n = x.shape[-1] // bins idxs = np.arange(n * bins) def compute(f): return np.nanmean( np.nanstd(np.array(np.split(f.take(idxs, axis=-1), n, axis=-1)), axis=-1), axis=0, ) return compute
[docs] def fake_image(shape=50, seed=0, stars=30): """ Generate a fake image with random stars. Parameters ---------- shape : int, optional Size of the image (shape x shape). seed : int, optional Random seed. stars : int, optional Number of stars. Returns ------- tuple Tuple (image, coords) where image is the generated image and coords are the star positions. """ np.random.seed(seed) image = np.zeros((shape, shape)) coords = (np.random.rand(2, stars) * shape).astype(int).T for i, j in coords: image[j, i] = 1.0 return image, coords
[docs] def share_data(master_files): """ Save master calibration arrays to disk as memory-mapped files and return read-only memmap objects. This function writes each array in `master_files` to a `.array` file using numpy's memmap, allowing efficient concurrent access from multiple processes. The returned dictionary contains read-only memmap objects for each calibration file. Parameters ---------- master_files : dict Dictionary mapping string keys (e.g., 'bias', 'dark', 'flat') to numpy.ndarray calibration arrays. Returns ------- dict Dictionary mapping the same keys to numpy.memmap objects opened in read-only mode. """ get_data = {} for key, value in master_files.items(): shape = value.shape dtype = value.dtype m = np.memmap(f"{key}.array", dtype=dtype, mode="w+", shape=shape) if value.ndim == 2: m[:, :] = value[:, :] else: m[:] = value[:] get_data[key] = np.memmap(f"{key}.array", dtype=dtype, mode="r", shape=shape) del master_files return get_data