diff --git a/eye_patch/logging.py b/eye_patch/logging.py new file mode 100644 index 0000000..661fe6f --- /dev/null +++ b/eye_patch/logging.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +import logging + +# Create logger +logging.captureWarnings(True) +logger = logging.getLogger("eye-patch") +logger.setLevel(logging.INFO) + +# Create console handler and set level to debug +ch = logging.StreamHandler() +ch.setLevel(logging.INFO) + + +class CustomFormatter(logging.Formatter): + """A custom logger formatter""" + + grey = "\x1b[38;20m" + blue = "\x1b[34;20m" + green = "\x1b[32;20m" + yellow = "\x1b[33;20m" + red = "\x1b[31;20m" + bold_red = "\x1b[31;1m" + reset = "\x1b[0m" + format_str = "%(asctime)s.%(msecs)03d %(module)s - %(funcName)s: %(message)s" + + FORMATS = { # noqa: RUF012 + logging.DEBUG: f"{blue}%(levelname)s{reset} {format_str}", + logging.INFO: f"{green}%(levelname)s{reset} {format_str}", + logging.WARNING: f"{yellow}%(levelname)s{reset} {format_str}", + logging.ERROR: f"{red}%(levelname)s{reset} {format_str}", + logging.CRITICAL: f"{bold_red}%(levelname)s{reset} {format_str}", + } + + def format(self, record: logging.LogRecord) -> str: + log_fmt = self.FORMATS.get(record.levelno) + formatter = logging.Formatter(log_fmt, "%Y-%m-%d %H:%M:%S") + return formatter.format(record) + + +# Add formatter to ch +ch.setFormatter(CustomFormatter()) + +# Add ch to logger +logger.addHandler(ch) diff --git a/eye_patch/masking.py b/eye_patch/masking.py index 7da19f8..d1161c5 100644 --- a/eye_patch/masking.py +++ b/eye_patch/masking.py @@ -4,7 +4,6 @@ from __future__ import annotations -import logging from argparse import ArgumentParser from pathlib import Path from typing import NamedTuple, TypeAlias @@ -26,6 +25,7 @@ from scipy.ndimage import binary_fill_holes, label, maximum_filter, minimum_filter from scipy.signal import fftconvolve +from eye_patch.logging import logger from eye_patch.naming import FITSMaskNames, create_fits_mask_names # Add explicit export so mypy on tests is ok @@ -37,8 +37,6 @@ # during fits file creation. MaskLike: TypeAlias = NDArray[np.floating] -logger = logging.getLogger("__name__") - class MaskingOptions(BaseOptions): """Contains options for the creation of clean masks from some subject @@ -918,7 +916,7 @@ def create_snr_mask_from_fits( logger.info(f"Writing {mask_names.mask_fits}") fits.writeto( filename=mask_names.mask_fits, - data=mask_data, + data=mask_data.astype(np.float32), header=fits_header, overwrite=overwrite, ) @@ -967,6 +965,12 @@ def convolve_image_by_scale( logger.info(f"Generating gaussian kernel for {scale=} {fwhm=:.3f} {sigma=:.3f}") pix_sigma = int(sigma * 5) + if pix_sigma < 1: + # linspace can only take integer inputs, and if sigma is too small then this array comes + # out as length zero. + msg = f"{scale=} is too small and an appropriately sized kernel can not be formed. Consider removing it. " + raise ValueError(msg) + x = np.linspace(0, pix_sigma, pix_sigma) y = np.linspace(0, pix_sigma, pix_sigma)