"""
Magnitude conversion functions for SPHEREx photometry.
Converts flux density measurements in Jansky to AB magnitude system using astropy units.
"""
import logging
from typing import Optional, Tuple
import astropy.units as u
import numpy as np
logger = logging.getLogger(__name__)
[docs]
def flux_jy_to_ab_magnitude(flux_jy: float, flux_error_jy: float, wavelength_micron: float) -> Tuple[float, float]:
"""
Convert flux density in Jansky to AB magnitude using astropy units.
AB magnitude is defined as:
m_AB = -2.5 * log10(f_nu) - 48.6
where f_nu is flux density in erg/s/cm²/Hz
Parameters
----------
flux_jy : float
Flux density in Jansky
flux_error_jy : float
Flux density error in Jansky
wavelength_micron : float
Central wavelength in microns
Returns
-------
mag_ab : float
AB magnitude
mag_ab_error : float
AB magnitude error
"""
if flux_jy <= 0:
logger.warning(f"Non-positive flux {flux_jy} Jy - returning NaN magnitude")
return np.nan, np.nan
# Create astropy Quantity objects with proper units
flux_density = flux_jy * u.Jy
flux_density_error = flux_error_jy * u.Jy
wavelength = wavelength_micron * u.micron
# Convert flux density to CGS units for AB magnitude calculation
# AB magnitude reference: f_nu in erg/s/cm²/Hz with zero point 48.6
flux_density_cgs = flux_density.to(u.erg / u.s / u.cm**2 / u.Hz)
flux_density_error_cgs = flux_density_error.to(u.erg / u.s / u.cm**2 / u.Hz)
# AB magnitude calculation
mag_ab = -2.5 * np.log10(flux_density_cgs.value) - 48.6
# Error propagation for magnitude: d(mag)/d(flux) = -2.5 / (ln(10) * flux)
mag_ab_error = 2.5 / (np.log(10) * flux_density_cgs.value) * flux_density_error_cgs.value
return float(mag_ab), float(mag_ab_error)
[docs]
def calculate_ab_magnitude_from_jy(
flux_jy: float, flux_error_jy: float, wavelength_micron: float
) -> Tuple[Optional[float], Optional[float]]:
"""
Calculate AB magnitude from flux density in Jansky.
Parameters
----------
flux_jy : float
Flux density in Jansky
flux_error_jy : float
Flux density error in Jansky
wavelength_micron : float
Central wavelength in microns
Returns
-------
mag_ab : float or None
AB magnitude
mag_ab_error : float or None
AB magnitude error
"""
try:
# Calculate AB magnitude
mag_ab, mag_ab_error = flux_jy_to_ab_magnitude(flux_jy, flux_error_jy, wavelength_micron)
# Return None for NaN values
mag_ab = None if np.isnan(mag_ab) else mag_ab
mag_ab_error = None if np.isnan(mag_ab_error) else mag_ab_error
logger.debug(
f"AB magnitude for {flux_jy:.6f} Jy at {wavelength_micron:.3f} μm: {mag_ab:.3f}±{mag_ab_error:.3f}"
)
return mag_ab, mag_ab_error
except Exception as e:
logger.error(f"Failed to calculate AB magnitude: {e}")
return None, None
[docs]
def magnitude_to_flux_jy(mag_ab: float, mag_ab_error: float, wavelength_micron: float) -> Tuple[float, float]:
"""
Convert AB magnitude back to flux density in Jansky.
Useful for validation and upper limit calculations.
Parameters
----------
mag_ab : float
AB magnitude
mag_ab_error : float
AB magnitude error
wavelength_micron : float
Central wavelength in microns
Returns
-------
flux_jy : float
Flux density in Jansky
flux_error_jy : float
Flux density error in Jansky
"""
# Convert magnitude to flux density (erg/s/cm²/Hz)
flux_density_cgs_value = 10 ** (-0.4 * (mag_ab + 48.6))
# Error propagation: df/dm = -0.4 * ln(10) * f
flux_density_error_cgs_value = 0.4 * np.log(10) * flux_density_cgs_value * mag_ab_error
# Create astropy quantities with proper units
flux_density_cgs = flux_density_cgs_value * u.erg / u.s / u.cm**2 / u.Hz
flux_density_error_cgs = flux_density_error_cgs_value * u.erg / u.s / u.cm**2 / u.Hz
# Convert to Jansky
flux_jy_quantity = flux_density_cgs.to(u.Jy)
flux_error_jy_quantity = flux_density_error_cgs.to(u.Jy)
return float(flux_jy_quantity.value), float(flux_error_jy_quantity.value)