Source code for smpy.coordinates.radec
"""RA/Dec celestial coordinate system implementation.
This module provides the RADecSystem class for handling celestial coordinates
including spherical corrections and appropriate binning for sky projections.
"""
import numpy as np
from .base import CoordinateSystem
[docs]
class RADecSystem(CoordinateSystem):
"""Implementation for RA/Dec celestial coordinates.
Handles celestial coordinates including spherical corrections and
appropriate binning for sky projections. Applies coordinate transformations
to account for spherical geometry effects.
"""
[docs]
def get_grid_parameters(self, config):
"""Get RA/Dec specific grid parameters.
Extract celestial coordinate system parameters including angular
resolution for grid spacing.
Parameters
----------
config : `dict`
Configuration dictionary containing RA/Dec settings.
Returns
-------
grid_params : `dict`
Grid parameters dictionary containing:
- resolution_arcmin: Grid spacing in arcminutes
"""
radec_config = config['general']['radec']
if 'resolution' not in radec_config:
print("Warning: No resolution specified in radec config, using default 0.4 arcmin")
return {
'resolution_arcmin': radec_config.get('resolution', 0.4)
}
[docs]
def create_grid(self, data_df, boundaries, config):
"""Create shear grid in RA/Dec space.
Create a regular grid in celestial coordinates accounting for
spherical projection effects and appropriate angular binning.
Parameters
----------
data_df : `pandas.DataFrame`
DataFrame with scaled coordinates and shear data.
boundaries : `dict`
Dictionary with coordinate boundaries.
config : `dict`
Configuration dictionary with RA/Dec parameters.
Returns
-------
g1_grid : `numpy.ndarray`
2D array containing binned first shear component values.
g2_grid : `numpy.ndarray`
2D array containing binned second shear component values.
"""
# Ensure data is properly prepared
data_df = self.prepare_data(data_df)
# Get grid parameters
grid_params = self.get_grid_parameters(config)
resolution_arcmin = grid_params['resolution_arcmin']
# Get boundaries
ra_min, ra_max = boundaries['coord1_min'], boundaries['coord1_max']
dec_min, dec_max = boundaries['coord2_min'], boundaries['coord2_max']
# Calculate number of pixels based on field size and resolution (arcmin)
npix_ra = int(np.ceil((ra_max - ra_min) * 60 / resolution_arcmin))
npix_dec = int(np.ceil((dec_max - dec_min) * 60 / resolution_arcmin))
# Create bins
ra_bins = np.linspace(ra_min, ra_max, npix_ra + 1)
dec_bins = np.linspace(dec_min, dec_max, npix_dec + 1)
# Digitize the RA and Dec to find bin indices
ra_idx = np.digitize(data_df['coord1_scaled'], ra_bins) - 1
dec_idx = np.digitize(data_df['coord2_scaled'], dec_bins) - 1
# Determine whether to accumulate counts based on config
accumulate_counts = bool(
config.get('general', {}).get('create_counts_map', False)
or config.get('general', {}).get('overlay_counts_map', False)
)
return self._create_shear_grid(
data_df,
ra_idx,
dec_idx,
npix_dec,
npix_ra,
accumulate_counts=accumulate_counts,
)
[docs]
def calculate_boundaries(self, coord1, coord2):
"""Calculate field boundaries in RA/Dec space.
Determine coordinate ranges for celestial coordinates and set up
both scaled boundaries (accounting for spherical projection) and
true boundaries (preserving original coordinates).
Parameters
----------
coord1 : `numpy.ndarray`
RA values in degrees.
coord2 : `numpy.ndarray`
Dec values in degrees.
Returns
-------
scaled_boundaries : `dict`
Dictionary with scaled coordinate boundaries accounting for
spherical projection effects.
true_boundaries : `dict`
Dictionary with original celestial coordinate boundaries.
"""
# True boundaries (original coordinates)
true_boundaries = {
'coord1_min': np.min(coord1),
'coord1_max': np.max(coord1),
'coord2_min': np.min(coord2),
'coord2_max': np.max(coord2),
'coord1_name': 'RA',
'coord2_name': 'Dec',
'units': 'deg'
}
# Calculate central coordinates for scaling
coord1_0 = (true_boundaries['coord1_max'] + true_boundaries['coord1_min']) / 2
coord2_0 = (true_boundaries['coord2_max'] + true_boundaries['coord2_min']) / 2
# Calculate scaled coordinates (flatten RA by cos(Dec))
scaled_coords1 = (coord1 - coord1_0) * np.cos(np.deg2rad(coord2))
scaled_coords2 = coord2 - coord2_0
scaled_boundaries = {
'coord1_min': np.min(scaled_coords1),
'coord1_max': np.max(scaled_coords1),
'coord2_min': np.min(scaled_coords2),
'coord2_max': np.max(scaled_coords2),
'coord1_name': 'Scaled RA',
'coord2_name': 'Scaled Dec',
'units': 'deg'
}
return scaled_boundaries, true_boundaries