Source code for astra.utils.image

"""Image cleaning and background subtraction utilities."""

import numpy as np
from astropy.stats import SigmaClip, sigma_clipped_stats
from donuts.image import Image
from photutils.background import Background2D, MedianBackground
from scipy import ndimage


[docs] class CustomImageClass(Image): """Enhanced image processing class with background subtraction and cleaning."""
[docs] def preconstruct_hook(self) -> None: """ Apply image preprocessing before Donuts star detection. Performs background subtraction, noise reduction, and systematic correction to improve star detection reliability. """ # if greater than 2Kx2K, crop to 2Kx2K for speed shapex, shapey = self.raw_image.shape if shapex > 2048 and shapey > 2048: self.raw_image = self.raw_image[ shapex // 2 - 1024 : shapex // 2 + 1024, shapey // 2 - 1024 : shapey // 2 + 1024, ] self.raw_image = clean_image(self.raw_image) mean, median, std = sigma_clipped_stats(self.raw_image, sigma=3.0) # remove noise floor self.raw_image -= median + 7 * std self.raw_image[self.raw_image < 0] = 0
[docs] def clean_image(data: np.ndarray) -> np.ndarray: """ Clean an image by subtracting the background. Parameters: data (np.ndarray): The 2D image data. Returns: np.ndarray: The background-subtracted image. """ sigma_clip = SigmaClip(sigma=3.0) bkg_estimator = MedianBackground() # Convert to float32, handling both regular and masked arrays data = data.astype(np.float32) if np.ma.isMaskedArray(data): data = data.filled(fill_value=np.nan) bkg = Background2D( data, (32, 32), filter_size=(3, 3), sigma_clip=sigma_clip, bkg_estimator=bkg_estimator, # type: ignore ) bkg_clean = data - bkg.background med_clean = ndimage.median_filter( bkg_clean, size=5, mode="mirror" ) # slow but needed # add minimum back to avoid negative values med_clean += np.abs(np.nanmin(med_clean)) return med_clean