Skip to content

torchsky.wcs

Stability: core. Names on this page follow the deprecation policy in contributing.

Tensor-native FITS WCS: analytic and distorted projections, SIP/TPV and lookup-table distortions, spectral and time axes, tabular and coupled axes, celestial frames, sampled GWCS detector tables, and astrometric calibration. Every transform accepts and returns torch.Tensor and dispatches on the axes present in the header.

Guides: coordinates, frames, psf-conventions


This reference is generated from the package source. Names are grouped by the module that defines them; import every name from the public namespace torchsky.wcs unless the group text says otherwise.

Header parse

WCSHeaderWarning

Bases: UserWarning

A header was read under a documented compatibility rule its CTYPE does not state.

The one rule today is the pre-2012 SCAMP spelling: CTYPE = RA---TAN / DEC--TAN with PVi_m cards where some m >= 5. WCSLIB and Astropy read that as TPV, and so does torchsky, rewriting CTYPE to -TPV and emitting this warning. Turn it into an error with warnings.simplefilter("error", WCSHeaderWarning).

Alignment

AffineFitResult dataclass

AffineFitResult(
    matrix: Tensor,
    offset: Tensor,
    residuals: Tensor,
    rms: Tensor,
    geometry: str,
    inlier_mask: Tensor,
    iterations: int,
)

Weighted 2D affine correction fit.

geometry instance-attribute

geometry: str

inlier_mask instance-attribute

inlier_mask: Tensor

iterations instance-attribute

iterations: int

matrix instance-attribute

matrix: Tensor

offset instance-attribute

offset: Tensor

residuals instance-attribute

residuals: Tensor

rms instance-attribute

rms: Tensor

apply

apply(points: Any) -> Tensor

SkyAffineFitResult dataclass

SkyAffineFitResult(
    frame: TangentPlaneFrame, affine: AffineFitResult
)

Affine correction fitted in a local tangent plane.

affine instance-attribute

frame instance-attribute

inlier_mask property

inlier_mask: Tensor

rms property

rms: Tensor

apply

apply(ra: Any, dec: Any) -> tuple[Tensor, Tensor]

TangentPlaneFrame dataclass

TangentPlaneFrame(ra0: float, dec0: float)

Gnomonic tangent plane centered on a sky position.

dec0 instance-attribute

dec0: float

ra0 instance-attribute

ra0: float

from_points classmethod

from_points(ra: Any, dec: Any) -> 'TangentPlaneFrame'

plane_to_world

plane_to_world(xi: Any, eta: Any) -> tuple[Tensor, Tensor]

Invert tangent-plane degrees to sky coordinates in degrees.

world_to_plane

world_to_plane(ra: Any, dec: Any) -> tuple[Tensor, Tensor]

Project sky coordinates in degrees to tangent-plane degrees.

fit_affine_2d

fit_affine_2d(
    source: Any,
    target: Any,
    *,
    weights: Any | None = None,
    geometry: AffineGeometry = "general",
    sigma_clip: float | None = None,
    max_iter: int = 3,
) -> AffineFitResult

Fit a weighted 2D correction from source to target points.

Geometry modes mirror common tweakwcs alignment families: shift (translation), rshift (rotation + translation), rscale (uniform scale + rotation + translation), and general (full affine + translation).

Parameters:

Name Type Description Default
source Any

Input points with shape (N, 2).

required
target Any

Corresponding target points with shape (N, 2).

required
weights Any | None

Optional nonnegative per-point weights.

None
geometry AffineGeometry

Constrained affine transformation family.

'general'
sigma_clip float | None

Optional residual clipping threshold in robust sigmas.

None
max_iter int

Maximum clipping-and-refit iterations.

3

Returns:

Type Description
AffineFitResult

Fitted matrix, offset, residuals, mask, and fit diagnostics.

Examples:

>>> import torch
>>> from torchsky.wcs import fit_affine_2d
>>> fit = fit_affine_2d(torch.tensor([[0.0, 0.0]]), torch.tensor([[1.0, 2.0]]), geometry="shift")
>>> fit.offset.tolist()
[1.0, 2.0]

fit_sky_affine

fit_sky_affine(
    source_ra: Any,
    source_dec: Any,
    target_ra: Any,
    target_dec: Any,
    *,
    frame: TangentPlaneFrame | None = None,
    weights: Any | None = None,
    geometry: AffineGeometry = "general",
    sigma_clip: float | None = None,
    max_iter: int = 3,
) -> SkyAffineFitResult

Fit a local sky-coordinate affine correction in a gnomonic plane.

Astrometric calibration

ApproximateMatchResult dataclass

ApproximateMatchResult(
    reference_indices: Tensor, separation_arcsec: Tensor
)

matched property

matched: Tensor

reference_indices instance-attribute

reference_indices: Tensor

separation_arcsec instance-attribute

separation_arcsec: Tensor

AstrometricMatchGraph

AstrometricMatchGraph(
    observations: Sequence[AstrometricObservation],
    *,
    reference_source_ids: Any | None = None,
    reference_positions: Any | None = None,
    reference_covariance: Any | None = None,
    reference_proper_motion_mas_per_year: Any | None = None,
    reference_proper_motion_covariance: Any | None = None,
    reference_parallax_mas: Any | None = None,
    reference_parallax_variance: Any | None = None,
    tangent_frame: TangentPlaneFrame | None = None,
)

Bipartite exposure/source graph for supplied matches and reference priors.

centroid_covariance instance-attribute

centroid_covariance = centroid_covariance

component_exposures instance-attribute

component_exposures = component_exposures

component_reference_anchored instance-attribute

component_reference_anchored = anchored

components instance-attribute

components = components

detector_ids instance-attribute

detector_ids = detector_ids

detector_xy instance-attribute

detector_xy = detector_xy

exposure_ids instance-attribute

exposure_ids = exposure_ids

observations instance-attribute

observations = items

observed_plane instance-attribute

observed_plane = observed_plane

observed_sky instance-attribute

observed_sky = sky

reference_mask instance-attribute

reference_mask = reference_mask

reference_motion instance-attribute

reference_motion = reference_motion

reference_motion_mask instance-attribute

reference_motion_mask = reference_motion_mask

reference_motion_precision instance-attribute

reference_motion_precision = reference_motion_precision

reference_parallax instance-attribute

reference_parallax = reference_parallax

reference_parallax_mask instance-attribute

reference_parallax_mask = reference_parallax_mask

reference_parallax_precision instance-attribute

reference_parallax_precision = reference_parallax_precision

reference_plane instance-attribute

reference_plane = reference_plane

reference_precision instance-attribute

reference_precision = reference_precision

row_detector instance-attribute

row_detector = row_detector

row_exposure instance-attribute

row_exposure = row_exposure

row_source instance-attribute

row_source = row_source

source_ids instance-attribute

source_ids = source_ids

tangent_frame instance-attribute

tangent_frame = tangent_frame

_components staticmethod

_components(
    n_exposure: int,
    n_source: int,
    row_exposure: Tensor,
    row_source: Tensor,
    reference_mask: Tensor,
) -> tuple[
    tuple[tuple[int, ...], ...],
    tuple[tuple[int, ...], ...],
    tuple[bool, ...],
]

_plane_covariance staticmethod

_plane_covariance(
    observations: tuple[AstrometricObservation, ...],
    frame: TangentPlaneFrame,
) -> Tensor

solve

solve(
    config: AstrometryConfig | None = None,
    *,
    source_colors: Tensor | None = None,
    fit_mask: Tensor | None = None,
) -> AstrometrySolution

AstrometricObservation dataclass

AstrometricObservation(
    exposure_id: Hashable,
    detector_xy: Tensor,
    source_ids: Tensor | None,
    centroid_covariance: Tensor,
    approximate_wcs: Any | None = None,
    sky_position: Tensor | None = None,
    epoch: Epoch | Tensor | float | None = None,
    detector_id: Hashable = "detector",
    covariance_space: CovarianceSpace = "detector",
    world_jacobian: Tensor | None = None,
    color: Tensor | None = None,
    dcr_basis: Tensor | None = None,
    lateral_color_basis: Tensor | None = None,
    zenith_angle_deg: Tensor | float | None = None,
    parallactic_angle_deg: Tensor | float | None = None,
    parallax_factor: Tensor | None = None,
)

One exposure's supplied centroid catalog and match identifiers.

sky_position is the approximate sky position in degrees. When omitted, it is evaluated from detector_xy through approximate_wcs. A tangent covariance is in square arcseconds; a detector covariance is in square pixels and is propagated with a local approximate-WCS Jacobian.

approximate_wcs class-attribute instance-attribute

approximate_wcs: Any | None = field(
    default=None, repr=False, compare=False
)

centroid_covariance instance-attribute

centroid_covariance: Tensor

color class-attribute instance-attribute

color: Tensor | None = None

covariance_space class-attribute instance-attribute

covariance_space: CovarianceSpace = 'detector'

dcr_basis class-attribute instance-attribute

dcr_basis: Tensor | None = None

detector_id class-attribute instance-attribute

detector_id: Hashable = 'detector'

detector_xy instance-attribute

detector_xy: Tensor

epoch class-attribute instance-attribute

epoch: Epoch | Tensor | float | None = None

exposure_id instance-attribute

exposure_id: Hashable

lateral_color_basis class-attribute instance-attribute

lateral_color_basis: Tensor | None = None

n_matches property

n_matches: int

parallactic_angle_deg class-attribute instance-attribute

parallactic_angle_deg: Tensor | float | None = None

parallax_factor class-attribute instance-attribute

parallax_factor: Tensor | None = None

sky_position class-attribute instance-attribute

sky_position: Tensor | None = None

source_ids instance-attribute

source_ids: Tensor | None

world_jacobian class-attribute instance-attribute

world_jacobian: Tensor | None = None

zenith_angle_deg class-attribute instance-attribute

zenith_angle_deg: Tensor | float | None = None

__post_init__

__post_init__() -> None

approximate_sky

approximate_sky() -> Tensor

AstrometryConfig dataclass

AstrometryConfig(
    pose_model: PoseModel = "rscale",
    max_iterations: int = 15,
    convergence_tolerance: float = 1e-08,
    huber_delta: float = 3.0,
    cg_max_iterations: int = 200,
    cg_rtol: float = 1e-10,
    cg_atol: float = 0.0,
    damping: float = 1e-12,
    fit_detector_grid: bool = False,
    detector_grid_shape: tuple[int, int] = (4, 4),
    detector_grid_regularization: float = 1e-08,
    fit_dcr: bool = False,
    fit_lateral_color: bool = False,
    color_pivot: float = 0.0,
    missing_color: MissingPolicy = "error",
    fit_proper_motion: bool = False,
    fit_parallax: bool = False,
    reference_epoch: float = 2000.0,
    epoch_format: Literal[
        "jd", "mjd", "jyear", "byear", "unix"
    ] = "jyear",
    epoch_scale: Literal[
        "utc", "tai", "tt", "gps", "ut1", "tcb", "tdb"
    ] = "tcb",
    missing_epoch: Literal["error", "reference"] = "error",
    rank_policy: RankPolicy = "error",
    rank_rtol: float = 1e-10,
    covariance_max_parameters: int = 256,
    covariance_jacobian_step: float = 0.001,
)

cg_atol class-attribute instance-attribute

cg_atol: float = 0.0

cg_max_iterations class-attribute instance-attribute

cg_max_iterations: int = 200

cg_rtol class-attribute instance-attribute

cg_rtol: float = 1e-10

color_pivot class-attribute instance-attribute

color_pivot: float = 0.0

convergence_tolerance class-attribute instance-attribute

convergence_tolerance: float = 1e-08

covariance_jacobian_step class-attribute instance-attribute

covariance_jacobian_step: float = 0.001

covariance_max_parameters class-attribute instance-attribute

covariance_max_parameters: int = 256

damping class-attribute instance-attribute

damping: float = 1e-12

detector_grid_regularization class-attribute instance-attribute

detector_grid_regularization: float = 1e-08

detector_grid_shape class-attribute instance-attribute

detector_grid_shape: tuple[int, int] = (4, 4)

epoch_format class-attribute instance-attribute

epoch_format: Literal[
    "jd", "mjd", "jyear", "byear", "unix"
] = "jyear"

epoch_scale class-attribute instance-attribute

epoch_scale: Literal[
    "utc", "tai", "tt", "gps", "ut1", "tcb", "tdb"
] = "tcb"

fit_dcr class-attribute instance-attribute

fit_dcr: bool = False

fit_detector_grid class-attribute instance-attribute

fit_detector_grid: bool = False

fit_lateral_color class-attribute instance-attribute

fit_lateral_color: bool = False

fit_parallax class-attribute instance-attribute

fit_parallax: bool = False

fit_proper_motion class-attribute instance-attribute

fit_proper_motion: bool = False

huber_delta class-attribute instance-attribute

huber_delta: float = 3.0

max_iterations class-attribute instance-attribute

max_iterations: int = 15

missing_color class-attribute instance-attribute

missing_color: MissingPolicy = 'error'

missing_epoch class-attribute instance-attribute

missing_epoch: Literal['error', 'reference'] = 'error'

pose_model class-attribute instance-attribute

pose_model: PoseModel = 'rscale'

rank_policy class-attribute instance-attribute

rank_policy: RankPolicy = 'error'

rank_rtol class-attribute instance-attribute

rank_rtol: float = 1e-10

reference_epoch class-attribute instance-attribute

reference_epoch: float = 2000.0

__post_init__

__post_init__() -> None

AstrometryDiagnostics dataclass

AstrometryDiagnostics(
    converged: bool,
    iterations: int,
    objective_history: tuple[float, ...],
    step_history: tuple[float, ...],
    cg_iterations: tuple[int, ...],
    reduced_rank: int | None,
    reduced_dimension: int,
    condition_number: float | None,
    connected_components: tuple[tuple[Hashable, ...], ...],
    gauge_exposures: tuple[Hashable, ...],
    kinematic_gauge_sources: tuple[int, ...],
    reference_anchored_components: tuple[bool, ...],
    dropped_source_blocks: tuple[int, ...],
    dropped_dcr_exposures: tuple[Hashable, ...],
    dropped_lateral_color_detectors: tuple[Hashable, ...],
    matrix_free_reduced: bool = True,
    assembled_observation_matrix: bool = False,
)

assembled_observation_matrix class-attribute instance-attribute

assembled_observation_matrix: bool = False

cg_iterations instance-attribute

cg_iterations: tuple[int, ...]

condition_number instance-attribute

condition_number: float | None

connected_components instance-attribute

connected_components: tuple[tuple[Hashable, ...], ...]

converged instance-attribute

converged: bool

dropped_dcr_exposures instance-attribute

dropped_dcr_exposures: tuple[Hashable, ...]

dropped_lateral_color_detectors instance-attribute

dropped_lateral_color_detectors: tuple[Hashable, ...]

dropped_source_blocks instance-attribute

dropped_source_blocks: tuple[int, ...]

gauge_exposures instance-attribute

gauge_exposures: tuple[Hashable, ...]

iterations instance-attribute

iterations: int

kinematic_gauge_sources instance-attribute

kinematic_gauge_sources: tuple[int, ...]

matrix_free_reduced class-attribute instance-attribute

matrix_free_reduced: bool = True

objective_history instance-attribute

objective_history: tuple[float, ...]

reduced_dimension instance-attribute

reduced_dimension: int

reduced_rank instance-attribute

reduced_rank: int | None

reference_anchored_components instance-attribute

reference_anchored_components: tuple[bool, ...]

step_history instance-attribute

step_history: tuple[float, ...]

AstrometrySolution dataclass

AstrometrySolution(
    exposure_ids: tuple[Hashable, ...],
    source_ids: Tensor,
    pose_model: str,
    pose_parameters: Tensor,
    source_positions: Tensor,
    source_tangent_positions: Tensor,
    proper_motion_mas_per_year: Tensor | None,
    parallax_mas: Tensor | None,
    dcr_coefficients: Tensor | None,
    lateral_color_coefficients: Tensor | None,
    detector_ids: tuple[Hashable, ...],
    detector_residual_control: Tensor | None,
    residuals_arcsec: Tensor,
    robust_weights: Tensor,
    exposure_covariance: dict[Hashable, Tensor],
    diagnostics: AstrometryDiagnostics,
    fit_mask: Tensor,
)

converged property

converged: bool

dcr_coefficients instance-attribute

dcr_coefficients: Tensor | None

detector_ids instance-attribute

detector_ids: tuple[Hashable, ...]

detector_residual_control instance-attribute

detector_residual_control: Tensor | None

diagnostics instance-attribute

diagnostics: AstrometryDiagnostics

exposure_covariance instance-attribute

exposure_covariance: dict[Hashable, Tensor]

exposure_ids instance-attribute

exposure_ids: tuple[Hashable, ...]

fit_mask instance-attribute

fit_mask: Tensor

lateral_color_coefficients instance-attribute

lateral_color_coefficients: Tensor | None

parallax_mas instance-attribute

parallax_mas: Tensor | None

pose_model instance-attribute

pose_model: str

pose_parameters instance-attribute

pose_parameters: Tensor

proper_motion_mas_per_year instance-attribute

proper_motion_mas_per_year: Tensor | None

residuals_arcsec instance-attribute

residuals_arcsec: Tensor

robust_weights instance-attribute

robust_weights: Tensor

source_ids instance-attribute

source_ids: Tensor

source_positions instance-attribute

source_positions: Tensor

source_tangent_positions instance-attribute

source_tangent_positions: Tensor

pose_for

pose_for(exposure_id: Hashable) -> Tensor

match_approximate_wcs

match_approximate_wcs(
    observation: AstrometricObservation,
    reference_sky: Any,
    *,
    radius_arcsec: float,
    index: HealpixIndex | None = None,
) -> ApproximateMatchResult

Nearest supplied-reference matching, using only HealpixIndex candidates.

solve_astrometry

solve_astrometry(
    graph: AstrometricMatchGraph,
    config: AstrometryConfig | None = None,
) -> AstrometrySolution

Solve an astrometric match graph for exposure and source parameters.

tangent_plane_block_residuals

tangent_plane_block_residuals(
    observed: Any,
    predicted: Any,
    centroid_covariance: Any,
    reference_covariance: Any | None = None,
    *,
    robust_weights: Any | None = None,
    whiten: bool = True,
) -> Tensor

Return differentiable two-coordinate residual blocks with full covariance.

Astrometry.net bootstrap

AstrometryNetBootstrapResult dataclass

AstrometryNetBootstrapResult(
    hypothesis: AstrometryNetHypothesis,
    verification: AstrometryNetVerification,
    bundle_solution: AstrometrySolution,
    provenance: AstrometryNetProvenance,
)

bundle_solution instance-attribute

bundle_solution: AstrometrySolution

hypothesis instance-attribute

provenance instance-attribute

verification instance-attribute

AstrometryNetConfig dataclass

AstrometryNetConfig(
    executable: str | Path,
    executable_sha256: str,
    executable_version: str,
    index_manifest: str | Path,
    index_manifest_sha256: str,
    timeout_seconds: float = 60.0,
    version_args: tuple[str, ...] = ("--version",),
)

executable instance-attribute

executable: str | Path

executable_sha256 instance-attribute

executable_sha256: str

executable_version instance-attribute

executable_version: str

index_manifest instance-attribute

index_manifest: str | Path

index_manifest_sha256 instance-attribute

index_manifest_sha256: str

timeout_seconds class-attribute instance-attribute

timeout_seconds: float = 60.0

version_args class-attribute instance-attribute

version_args: tuple[str, ...] = ('--version',)

__post_init__

__post_init__() -> None

AstrometryNetError

Bases: RuntimeError

AstrometryNetExecutionError

AstrometryNetHypothesis dataclass

AstrometryNetHypothesis(
    header: Mapping[str, Any],
    center_ra_deg: float,
    center_dec_deg: float,
    pixel_scale_arcsec: tuple[float, float],
    orientation_deg: float,
    determinant_deg2_per_pixel2: float,
    handedness: Literal["right", "left"],
    parity: Literal["normal", "flipped"],
    index_id: int,
    index_healpix: int,
    index_hpnside: int,
    log_odds: float,
    matched_sources: int,
)

center_dec_deg instance-attribute

center_dec_deg: float

center_ra_deg instance-attribute

center_ra_deg: float

determinant_deg2_per_pixel2 instance-attribute

determinant_deg2_per_pixel2: float

handedness instance-attribute

handedness: Literal['right', 'left']

header instance-attribute

header: Mapping[str, Any]

index_healpix instance-attribute

index_healpix: int

index_hpnside instance-attribute

index_hpnside: int

index_id instance-attribute

index_id: int

log_odds instance-attribute

log_odds: float

matched_sources instance-attribute

matched_sources: int

orientation_deg instance-attribute

orientation_deg: float

parity instance-attribute

parity: Literal['normal', 'flipped']

pixel_scale_arcsec instance-attribute

pixel_scale_arcsec: tuple[float, float]

wcs property

wcs: WCS

AstrometryNetHypothesisRejected

AstrometryNetIdentityError

AstrometryNetIndexIdentity dataclass

AstrometryNetIndexIdentity(
    index_id: str,
    version: str,
    manifest_path: str,
    manifest_sha256: str,
    backend_config_path: str,
    backend_config_sha256: str,
    astrometry_index_ids: tuple[int, ...],
    files: tuple[tuple[str, str], ...],
)

astrometry_index_ids instance-attribute

astrometry_index_ids: tuple[int, ...]

backend_config_path instance-attribute

backend_config_path: str

backend_config_sha256 instance-attribute

backend_config_sha256: str

files instance-attribute

files: tuple[tuple[str, str], ...]

index_id instance-attribute

index_id: str

manifest_path instance-attribute

manifest_path: str

manifest_sha256 instance-attribute

manifest_sha256: str

version instance-attribute

version: str

AstrometryNetProvenance dataclass

AstrometryNetProvenance(
    executable_path: str,
    executable_sha256: str,
    executable_version: str,
    index: AstrometryNetIndexIdentity,
    bootstrap_arguments: tuple[str, ...],
    verification_arguments: tuple[str, ...],
    bootstrap_input_count: int,
    verification_input_count: int,
    runtime_downloads: bool = False,
)

bootstrap_arguments instance-attribute

bootstrap_arguments: tuple[str, ...]

bootstrap_input_count instance-attribute

bootstrap_input_count: int

executable_path instance-attribute

executable_path: str

executable_sha256 instance-attribute

executable_sha256: str

executable_version instance-attribute

executable_version: str

index instance-attribute

runtime_downloads class-attribute instance-attribute

runtime_downloads: bool = False

verification_arguments instance-attribute

verification_arguments: tuple[str, ...]

verification_input_count instance-attribute

verification_input_count: int

AstrometryNetUnavailableError

AstrometryNetVerification dataclass

AstrometryNetVerification(
    supplied_count: int,
    matched_count: int,
    residuals_pixels: Tensor,
    rms_pixels: float,
    max_pixels: float,
)

matched_count instance-attribute

matched_count: int

max_pixels instance-attribute

max_pixels: float

residuals_pixels instance-attribute

residuals_pixels: Tensor

rms_pixels instance-attribute

rms_pixels: float

supplied_count instance-attribute

supplied_count: int

AstrometryNetVerificationConfig dataclass

AstrometryNetVerificationConfig(
    min_matches: int,
    max_rms_pixels: float,
    max_residual_pixels: float,
    reference_sigma_arcsec: float = 0.01,
)

max_residual_pixels instance-attribute

max_residual_pixels: float

max_rms_pixels instance-attribute

max_rms_pixels: float

min_matches instance-attribute

min_matches: int

reference_sigma_arcsec class-attribute instance-attribute

reference_sigma_arcsec: float = 0.01

__post_init__

__post_init__() -> None

solve_with_astrometry_net

solve_with_astrometry_net(
    x: Any,
    y: Any,
    *,
    image_width: int,
    image_height: int,
    scale_arcsec_per_pixel: tuple[float, float],
    verification_mask: Any,
    external: AstrometryNetConfig,
    verification: AstrometryNetVerificationConfig,
    flux: Any | None = None,
    covariance: Any | None = None,
    pixel_origin: Literal[0, 1] = 0,
    bundle_config: AstrometryConfig | None = None,
) -> AstrometryNetBootstrapResult

Bootstrap a supplied centroid list and refine accepted correspondences.

Coupled calibration

CoupledCalibrationConfig dataclass

CoupledCalibrationConfig(
    astrometry: AstrometryConfig = AstrometryConfig(),
    max_iterations: int = 6,
    photometry_max_iterations: int = 20,
    convergence_tolerance: float = 1e-07,
    photometry_convergence_tolerance: float = 1e-08,
    huber_delta: float = 3.0,
    fit_extinction: bool = True,
    fit_cloud: bool = True,
    fit_star_flat: bool = True,
    fit_color_terms: bool = True,
    color_bands: tuple[Hashable, Hashable] | None = None,
    color_pivot: float = 0.0,
    color_scale: float = -2.5 / log(10.0),
    missing_color: MissingColorPolicy = "drop",
    fit_variability: bool = False,
    variable_source_ids: tuple[int, ...] = (),
    holdout_source_ids: tuple[int, ...] = (),
    holdout_exposure_ids: tuple[Hashable, ...] = (),
    damping: float = 1e-10,
    rank_rtol: float = 1e-10,
    cg_max_iterations: int = 500,
    cg_rtol: float = 1e-10,
    covariance_max_parameters: int = 256,
)

astrometry class-attribute instance-attribute

astrometry: AstrometryConfig = field(
    default_factory=AstrometryConfig
)

cg_max_iterations class-attribute instance-attribute

cg_max_iterations: int = 500

cg_rtol class-attribute instance-attribute

cg_rtol: float = 1e-10

color_bands class-attribute instance-attribute

color_bands: tuple[Hashable, Hashable] | None = None

color_pivot class-attribute instance-attribute

color_pivot: float = 0.0

color_scale class-attribute instance-attribute

color_scale: float = -2.5 / log(10.0)

convergence_tolerance class-attribute instance-attribute

convergence_tolerance: float = 1e-07

covariance_max_parameters class-attribute instance-attribute

covariance_max_parameters: int = 256

damping class-attribute instance-attribute

damping: float = 1e-10

fit_cloud class-attribute instance-attribute

fit_cloud: bool = True

fit_color_terms class-attribute instance-attribute

fit_color_terms: bool = True

fit_extinction class-attribute instance-attribute

fit_extinction: bool = True

fit_star_flat class-attribute instance-attribute

fit_star_flat: bool = True

fit_variability class-attribute instance-attribute

fit_variability: bool = False

holdout_exposure_ids class-attribute instance-attribute

holdout_exposure_ids: tuple[Hashable, ...] = ()

holdout_source_ids class-attribute instance-attribute

holdout_source_ids: tuple[int, ...] = ()

huber_delta class-attribute instance-attribute

huber_delta: float = 3.0

max_iterations class-attribute instance-attribute

max_iterations: int = 6

missing_color class-attribute instance-attribute

missing_color: MissingColorPolicy = 'drop'

photometry_convergence_tolerance class-attribute instance-attribute

photometry_convergence_tolerance: float = 1e-08

photometry_max_iterations class-attribute instance-attribute

photometry_max_iterations: int = 20

rank_rtol class-attribute instance-attribute

rank_rtol: float = 1e-10

variable_source_ids class-attribute instance-attribute

variable_source_ids: tuple[int, ...] = ()

__post_init__

__post_init__() -> None

CoupledCalibrationDiagnostics dataclass

CoupledCalibrationDiagnostics(
    converged: bool,
    iterations: int,
    stage_history: tuple[str, ...],
    astrometric_step_history: tuple[float, ...],
    photometric_step_history: tuple[float, ...],
    color_step_history: tuple[float, ...],
    source_holdout_count: int,
    exposure_holdout_count: int,
)

astrometric_step_history instance-attribute

astrometric_step_history: tuple[float, ...]

color_step_history instance-attribute

color_step_history: tuple[float, ...]

converged instance-attribute

converged: bool

exposure_holdout_count instance-attribute

exposure_holdout_count: int

iterations instance-attribute

iterations: int

photometric_step_history instance-attribute

photometric_step_history: tuple[float, ...]

source_holdout_count instance-attribute

source_holdout_count: int

stage_history instance-attribute

stage_history: tuple[str, ...]

CoupledCalibrationGraph

CoupledCalibrationGraph(
    astrometry_graph: AstrometricMatchGraph,
    photometric_blocks: Sequence[
        PhotometricMeasurementBlock
    ],
    *,
    reference: PhotometricReference | None = None,
    sed_basis: Tensor | None = None,
)

Fixed-association exposure-source graph with astrometric and flux blocks.

astrometry_graph instance-attribute

astrometry_graph = astrometry_graph

bands instance-attribute

bands = bands

base_fit_mask instance-attribute

base_fit_mask = cat(
    [_normalized(fit_mask) for block in blocks]
)

block_slices instance-attribute

block_slices = tuple(block_slices)

blocks instance-attribute

blocks = blocks

cloud_basis instance-attribute

cloud_basis = cat(
    [_normalized(cloud_basis) for block in blocks]
)

detector_ids instance-attribute

detector_ids = detector_ids

exposure_ids instance-attribute

exposure_ids = exposure_ids

extinction_basis instance-attribute

extinction_basis = cat(
    [_normalized(extinction_basis) for block in blocks]
)

flux instance-attribute

flux = cat([flux for block in blocks])

log_covariance instance-attribute

log_covariance = tuple(
    flux_covariance / (flux[:, None] * flux[None, :])
    for block in blocks
)

log_flux instance-attribute

log_flux = log(flux)

max_star_flat instance-attribute

max_star_flat = max_star_flat

reference instance-attribute

reference = reference

row_band instance-attribute

row_band = cat(row_band)

row_detector instance-attribute

row_detector = cat(row_detector)

row_exposure instance-attribute

row_exposure = cat(row_exposure)

row_source instance-attribute

row_source = cat(row_source)

sed_basis instance-attribute

sed_basis = basis

star_flat_basis instance-attribute

star_flat_basis = cat(star_flat_rows)

weights instance-attribute

weights = cat([_normalized(weights) for block in blocks])

solve

solve(
    config: CoupledCalibrationConfig | None = None,
) -> CoupledCalibrationSolution

CoupledCalibrationSolution dataclass

CoupledCalibrationSolution(
    astrometry: AstrometrySolution,
    photometry: PhotometricCalibrationSolution,
    diagnostics: CoupledCalibrationDiagnostics,
    covariance: dict[str, object],
    provenance: dict[str, object],
)

astrometry instance-attribute

astrometry: AstrometrySolution

converged property

converged: bool

covariance instance-attribute

covariance: dict[str, object]

diagnostics instance-attribute

photometry instance-attribute

provenance instance-attribute

provenance: dict[str, object]

PhotometricCalibrationDiagnostics dataclass

PhotometricCalibrationDiagnostics(
    converged: bool,
    iterations: int,
    objective_history: tuple[float, ...],
    step_history: tuple[float, ...],
    cg_iterations: tuple[int, ...],
    connected_components: tuple[tuple[Hashable, ...], ...],
    gauge_exposures: tuple[Hashable, ...],
    reference_anchored_components: tuple[bool, ...],
    dropped_extinction_exposures: tuple[Hashable, ...],
    dropped_cloud_exposures: tuple[Hashable, ...],
    dropped_star_flat_parameters: tuple[
        tuple[Hashable, int], ...
    ],
    dropped_color_bands: tuple[Hashable, ...],
    information_rank: int | None,
    information_dimension: int,
    condition_number: float | None,
    matrix_free: bool = True,
    assembled_measurement_matrix: bool = False,
)

assembled_measurement_matrix class-attribute instance-attribute

assembled_measurement_matrix: bool = False

cg_iterations instance-attribute

cg_iterations: tuple[int, ...]

condition_number instance-attribute

condition_number: float | None

connected_components instance-attribute

connected_components: tuple[tuple[Hashable, ...], ...]

converged instance-attribute

converged: bool

dropped_cloud_exposures instance-attribute

dropped_cloud_exposures: tuple[Hashable, ...]

dropped_color_bands instance-attribute

dropped_color_bands: tuple[Hashable, ...]

dropped_extinction_exposures instance-attribute

dropped_extinction_exposures: tuple[Hashable, ...]

dropped_star_flat_parameters instance-attribute

dropped_star_flat_parameters: tuple[
    tuple[Hashable, int], ...
]

gauge_exposures instance-attribute

gauge_exposures: tuple[Hashable, ...]

information_dimension instance-attribute

information_dimension: int

information_rank instance-attribute

information_rank: int | None

iterations instance-attribute

iterations: int

matrix_free class-attribute instance-attribute

matrix_free: bool = True

objective_history instance-attribute

objective_history: tuple[float, ...]

reference_anchored_components instance-attribute

reference_anchored_components: tuple[bool, ...]

step_history instance-attribute

step_history: tuple[float, ...]

PhotometricCalibrationSolution dataclass

PhotometricCalibrationSolution(
    source_ids: Tensor,
    bands: tuple[Hashable, ...],
    source_band_flux: Tensor,
    source_band_log_flux: Tensor,
    source_coefficient_variance: Tensor,
    colors: Tensor,
    exposure_ids: tuple[Hashable, ...],
    exposure_log_zeropoint: Tensor,
    exposure_extinction: Tensor,
    exposure_cloud: Tensor,
    detector_ids: tuple[Hashable, ...],
    star_flat_coefficients: Tensor,
    band_color_terms: Tensor,
    predicted_log_flux: Tensor,
    residual_log_flux: Tensor,
    robust_weights: Tensor,
    variability_offsets: Tensor,
    fit_mask: Tensor,
    global_covariance: Tensor | None,
    diagnostics: PhotometricCalibrationDiagnostics,
    provenance: dict[str, object],
)

band_color_terms instance-attribute

band_color_terms: Tensor

bands instance-attribute

bands: tuple[Hashable, ...]

colors instance-attribute

colors: Tensor

converged property

converged: bool

detector_ids instance-attribute

detector_ids: tuple[Hashable, ...]

diagnostics instance-attribute

exposure_cloud instance-attribute

exposure_cloud: Tensor

exposure_extinction instance-attribute

exposure_extinction: Tensor

exposure_ids instance-attribute

exposure_ids: tuple[Hashable, ...]

exposure_log_zeropoint instance-attribute

exposure_log_zeropoint: Tensor

fit_mask instance-attribute

fit_mask: Tensor

global_covariance instance-attribute

global_covariance: Tensor | None

predicted_log_flux instance-attribute

predicted_log_flux: Tensor

provenance instance-attribute

provenance: dict[str, object]

residual_log_flux instance-attribute

residual_log_flux: Tensor

robust_weights instance-attribute

robust_weights: Tensor

source_band_flux instance-attribute

source_band_flux: Tensor

source_band_log_flux instance-attribute

source_band_log_flux: Tensor

source_coefficient_variance instance-attribute

source_coefficient_variance: Tensor

source_ids instance-attribute

source_ids: Tensor

star_flat_coefficients instance-attribute

star_flat_coefficients: Tensor

variability_offsets instance-attribute

variability_offsets: Tensor

flux_for

flux_for(source_id: int, band: Hashable) -> Tensor

PhotometricMeasurementBlock dataclass

PhotometricMeasurementBlock(
    exposure_id: Hashable,
    source_ids: Tensor,
    band: Hashable,
    flux: Tensor,
    flux_covariance: Tensor,
    detector_id: Hashable = "detector",
    extinction_basis: Tensor | float | None = None,
    cloud_basis: Tensor | float | None = None,
    star_flat_basis: Tensor | None = None,
    weights: Tensor | None = None,
    fit_mask: Tensor | None = None,
    epoch: Tensor | float | None = None,
)

band instance-attribute

band: Hashable

cloud_basis class-attribute instance-attribute

cloud_basis: Tensor | float | None = None

count property

count: int

detector_id class-attribute instance-attribute

detector_id: Hashable = 'detector'

epoch class-attribute instance-attribute

epoch: Tensor | float | None = None

exposure_id instance-attribute

exposure_id: Hashable

extinction_basis class-attribute instance-attribute

extinction_basis: Tensor | float | None = None

fit_mask class-attribute instance-attribute

fit_mask: Tensor | None = None

flux instance-attribute

flux: Tensor

flux_covariance instance-attribute

flux_covariance: Tensor

source_ids instance-attribute

source_ids: Tensor

star_flat_basis class-attribute instance-attribute

star_flat_basis: Tensor | None = None

weights class-attribute instance-attribute

weights: Tensor | None = None

__post_init__

__post_init__() -> None

PhotometricReference dataclass

PhotometricReference(
    source_ids: Tensor,
    bands: tuple[Hashable, ...],
    flux: Tensor,
    flux_variance: Tensor,
)

bands instance-attribute

bands: tuple[Hashable, ...]

flux instance-attribute

flux: Tensor

flux_variance instance-attribute

flux_variance: Tensor

source_ids instance-attribute

source_ids: Tensor

__post_init__

__post_init__() -> None

photometric_log_residuals

photometric_log_residuals(
    measured_flux: Any,
    predicted_flux: Any,
    flux_covariance: Any,
    *,
    weights: Any | None = None,
    whiten: bool = True,
) -> Tensor

Compute optionally whitened log-flux residuals for calibration.

solve_coupled_calibration

solve_coupled_calibration(
    graph: CoupledCalibrationGraph,
    config: CoupledCalibrationConfig | None = None,
) -> CoupledCalibrationSolution

Solve the coupled astrometric and photometric calibration graph.

Catalog state

CatalogState dataclass

CatalogState(
    lon: Tensor,
    lat: Tensor,
    frame: str = "ICRS",
    epoch: Tensor | float | Epoch = 2000.0,
    epoch_scale: TimeScale | None = None,
    epoch_format: TimeFormat | None = None,
    pm_lon_coslat_mas_yr: Tensor | None = None,
    pm_lat_mas_yr: Tensor | None = None,
    parallax_mas: Tensor | None = None,
    radial_velocity_km_s: Tensor | None = None,
    valid: Tensor | None = None,
)

Batched sky state with explicit missing components.

Missing proper motion, parallax, or radial velocity stay None. They are never filled from a default distance or a pmsafe override. valid is an optional boolean mask; it is never used to impute values.

epoch class-attribute instance-attribute

epoch: Tensor | float | Epoch = 2000.0

epoch_format class-attribute instance-attribute

epoch_format: TimeFormat | None = None

epoch_scale class-attribute instance-attribute

epoch_scale: TimeScale | None = None

frame class-attribute instance-attribute

frame: str = 'ICRS'

lat instance-attribute

lat: Tensor

lon instance-attribute

lon: Tensor

parallax_mas class-attribute instance-attribute

parallax_mas: Tensor | None = None

pm_lat_mas_yr class-attribute instance-attribute

pm_lat_mas_yr: Tensor | None = None

pm_lon_coslat_mas_yr class-attribute instance-attribute

pm_lon_coslat_mas_yr: Tensor | None = None

radial_velocity_km_s class-attribute instance-attribute

radial_velocity_km_s: Tensor | None = None

valid class-attribute instance-attribute

valid: Tensor | None = None

__post_init__

__post_init__() -> None

_target_epoch_value

_target_epoch_value(
    epoch: Tensor | float | Epoch,
) -> Tensor

propagate_angular

propagate_angular(
    epoch: Tensor | float | Epoch,
) -> CatalogState

propagate_physical

propagate_physical(
    epoch: Tensor | float | Epoch,
) -> CatalogState

to_frame

to_frame(
    frame: str, *, tt_mjd: Tensor | float | None = None
) -> CatalogState

to_representation

to_representation(
    kind: Representation = "lonlat_deg",
) -> Tensor

Coords

transform

transform(
    lon: Any,
    lat: Any,
    *,
    from_frame: str,
    to_frame: str,
    obstime_mjd_utc: Any | None = None,
    site: Site | None = None,
    eop: EarthOrientation | None = None,
    pn: PNModel | None = None,
    aberration: bool = False,
    refraction: bool = False,
    refraction_model: RefractionModel = "refco",
) -> tuple[Tensor, Tensor]

Rotate or observe (lon, lat) tensors. Returns (lon_out, lat_out).

Geometric frames use CatalogState.to_frame. ALTAZ, ITRS, GCRS, CIRS, and TETE require obstime_mjd_utc and eop. ECLIPTIC_OF_DATE uses TT MJD (obstime_mjd_utc is treated as TT unless you pass a TT value through CatalogState.to_frame).

Parameters:

Name Type Description Default
lon Any

Longitude values in degrees.

required
lat Any

Latitude values in degrees.

required
from_frame str

Input coordinate-frame name.

required
to_frame str

Output coordinate-frame name.

required
obstime_mjd_utc Any | None

Observation time in UTC MJD, or TT MJD for ecliptic-of-date.

None
site Site | None

Observing site required for altitude-azimuth output.

None
eop EarthOrientation | None

Earth-orientation parameters required for observed frames.

None
pn PNModel | None

Precession-nutation model.

None
aberration bool

Apply annual aberration for supported observed frames.

False
refraction bool

Apply atmospheric refraction to altitude-azimuth output.

False
refraction_model RefractionModel

"refco" (ERFA, default; uses Site humidity and wavelength) or "saemundsson".

'refco'

Returns:

Type Description
tuple[Tensor, Tensor]

Output longitude and latitude tensors in degrees.

Examples:

>>> import torch
>>> from torchsky.coords import transform
>>> lon, lat = transform(torch.tensor([0.0]), torch.tensor([0.0]), from_frame="ICRS", to_frame="GALACTIC")
>>> lon.shape == lat.shape
True

Core

DistortionLookupTable

DistortionLookupTable(
    data: Any,
    crpix: tuple[float, float] = (1.0, 1.0),
    crval: tuple[float, float] = (1.0, 1.0),
    cdelt: tuple[float, float] = (1.0, 1.0),
)

FITS WCS Paper IV 2D distortion lookup table (CPDIS / DET2IM).

Matches astropy.wcs.DistortionLookupTable semantics: 1-based FITS pixel coordinates (x, y) map to 0-based table indices tx = (x - crval1) / cdelt1 + crpix1 - 1, ty = (y - crval2) / cdelt2 + crpix2 - 1 and are bilinearly interpolated on data (shape (H, W) = (NAXIS2, NAXIS1)), with clamping at table boundaries.

cdelt instance-attribute

cdelt: tuple[float, float] = (
    float(cdelt[0]),
    float(cdelt[1]),
)

crpix instance-attribute

crpix: tuple[float, float] = (
    float(crpix[0]),
    float(crpix[1]),
)

crval instance-attribute

crval: tuple[float, float] = (
    float(crval[0]),
    float(crval[1]),
)

data instance-attribute

data: Tensor = tensor

eval_tensor

eval_tensor(x1: Tensor, y1: Tensor) -> Tensor

Evaluate bilinear lookup at 1-based FITS pixel coordinates (x1, y1).

rebased_for_diagonal_pixel_map

rebased_for_diagonal_pixel_map(
    starts: tuple[int, int],
    steps: tuple[int, int],
    *,
    component_axis: int,
) -> "DistortionLookupTable"

to

to(
    device: str | device, dtype: dtype | None = None
) -> "DistortionLookupTable"

PrecisionWarning

Bases: UserWarning

A WCS runs in float32 (MPS) with an expected error of half a pixel or more.

MPS has no float64. The warning is emitted once per WCS when the expected float32 position error, (ulp32(world) / pixel scale) + ulp32(pixel extent) in pixels, reaches 0.5 pixel: beyond that the nearest pixel can no longer be identified reliably. Use CPU or CUDA (float64) for such grids.

WCS

WCS(
    header: Optional[Dict[str, Any]] = None,
    key: str = "",
    tabular_axes: Mapping[int, TabularAxis] | None = None,
    coupled_tabular: CoupledTabularLookupWCS | None = None,
    coupled_tabular_axes: Sequence[int] | None = None,
    coupled_tabular_pixel_axes: Sequence[int] | None = None,
    tables: Any = None,
    cpdis1: DistortionLookupTable | Any | None = None,
    cpdis2: DistortionLookupTable | Any | None = None,
    det2im1: DistortionLookupTable | Any | None = None,
    det2im2: DistortionLookupTable | Any | None = None,
    **kwargs: Any,
)

Bases: _RotationMixin, _GeometryMixin, _HeaderIOMixin, _HeaderParseMixin, _WCSStateMixin, _SetupTensorsMixin, _PixelWorldCoreMixin, _AxesFramesMixin, _MixedMixin, _DifferentiableMixin

PyTorch-native world coordinate system parsed from FITS-style metadata.

Parameters:

Name Type Description Default
header Optional[Dict[str, Any]]

FITS-style header mapping. An empty mapping creates a default WCS.

None
key str

Alternate-WCS suffix without the leading keyword letter.

''
tabular_axes Mapping[int, TabularAxis] | None

Explicit one-dimensional lookup axes keyed by world axis.

None
coupled_tabular CoupledTabularLookupWCS | None

Optional coupled multi-axis lookup transform.

None
tables Any

Table resolver used by -TAB metadata.

None
cpdis1 DistortionLookupTable | Any | None

First prior-distortion lookup table.

None
cpdis2 DistortionLookupTable | Any | None

Second prior-distortion lookup table.

None
det2im1 DistortionLookupTable | Any | None

First detector-to-image lookup table.

None
det2im2 DistortionLookupTable | Any | None

Second detector-to-image lookup table.

None

Examples:

>>> from torchsky.wcs import WCS
>>> wcs = WCS({"NAXIS": 2, "CTYPE1": "RA---TAN", "CTYPE2": "DEC--TAN"})
>>> wcs.pixel_n_dim
2

Parameters:

Name Type Description Default
header Optional[Dict[str, Any]]

FITS header dictionary (or similar object behaving like dict)

None
**kwargs Any

Manual override for WCS keywords (CRVAL, CRPIX, CD, etc.)

{}

ALLSKY_CODES class-attribute instance-attribute

ALLSKY_CODES = ('AIT', 'MOL', 'HPX', 'SFL', 'XPH')

CONIC_CODES class-attribute instance-attribute

CONIC_CODES = ('COP', 'COE', 'COD', 'COO')

CYLINDRICAL_CODES class-attribute instance-attribute

CYLINDRICAL_CODES = ('CEA', 'MER', 'CYP', 'CAR')

POLYCONIC_CODES class-attribute instance-attribute

POLYCONIC_CODES = ('BON', 'PCO')

PSEUDOCYLINDRICAL_CODES class-attribute instance-attribute

PSEUDOCYLINDRICAL_CODES = ('PAR',)

QUADCUBE_CODES class-attribute instance-attribute

QUADCUBE_CODES = ('TSC', 'CSC', 'QSC')

SPECIAL_CODES class-attribute instance-attribute

SPECIAL_CODES = ('ZPX', 'TNX', 'TPV', 'NCP', 'GLS')

ZENITHAL_CODES class-attribute instance-attribute

ZENITHAL_CODES = (
    "TAN",
    "SIN",
    "ARC",
    "ZPN",
    "STG",
    "ZEA",
    "AZP",
    "SZP",
    "AIR",
)

_KINKED_CODES class-attribute instance-attribute

_KINKED_CODES = ('XPH', 'QSC')

_KINK_STEP class-attribute instance-attribute

_KINK_STEP = 0.0001

_REF_TOL class-attribute instance-attribute

_REF_TOL = 1e-07

_compiled_pixel_to_world_2d_fn instance-attribute

_compiled_pixel_to_world_2d_fn = None

_compiled_stack_pixel_to_world instance-attribute

_compiled_stack_pixel_to_world: (
    dict[float, Callable[[Tensor], Tensor]] | None
) = None

_compiled_stack_world_to_pixel instance-attribute

_compiled_stack_world_to_pixel: (
    dict[float, Callable[[Tensor], Tensor]] | None
) = None

_compiled_transform_fn instance-attribute

_compiled_transform_fn = None

_compiled_world_to_pixel_2d_fn instance-attribute

_compiled_world_to_pixel_2d_fn = None

_enable_cpp_dispatcher instance-attribute

_enable_cpp_dispatcher = (
    get("TORCHSKY_CPP_DISPATCHER", "1") == "1"
)

_enable_fused_wcs instance-attribute

_enable_fused_wcs = get('TORCHSKY_WCS_FUSED', '1') == '1'

_pixel_affine_inv instance-attribute

_pixel_affine_inv: Tensor | None = None

_pixel_affine_inv_offset instance-attribute

_pixel_affine_inv_offset: Tensor | None = None

_pixel_affine_matrix instance-attribute

_pixel_affine_matrix: Tensor | None = None

_pixel_affine_offset instance-attribute

_pixel_affine_offset: Tensor | None = None

_pixel_shape instance-attribute

_pixel_shape: tuple[int, ...] | None = None

celestial property

celestial: 'WCS'

Return the 2D celestial component of a spatial WCS.

coupled_tabular instance-attribute

coupled_tabular: CoupledTabularLookupWCS | None = None

coupled_tabular_axes instance-attribute

coupled_tabular_axes: tuple[int, ...] = ()

coupled_tabular_pixel_axes instance-attribute

coupled_tabular_pixel_axes: tuple[int, ...] = ()

cpdis1 instance-attribute

cpdis1: DistortionLookupTable | None = (
    _coerce_distortion_lookup_table(cpdis1)
)

cpdis2 instance-attribute

cpdis2: DistortionLookupTable | None = (
    _coerce_distortion_lookup_table(cpdis2)
)

det2im1 instance-attribute

det2im1: DistortionLookupTable | None = (
    _coerce_distortion_lookup_table(det2im1)
)

det2im2 instance-attribute

det2im2: DistortionLookupTable | None = (
    _coerce_distortion_lookup_table(det2im2)
)

device instance-attribute

device = device('cpu')

naxis instance-attribute

naxis = _infer_wcs_naxis(header)

sip instance-attribute

sip: SIP | None = None

spectral_transforms instance-attribute

spectral_transforms = {}

tabular_axes instance-attribute

tabular_axes: dict[int, TabularAxis] = {}

tpv instance-attribute

tpv: TPV | None = None

wat_data instance-attribute

wat_data = {}

wcs_key instance-attribute

wcs_key = _normalize_wcs_key(key)

wcs_params instance-attribute

wcs_params: dict[str, Any] = {}

__setattr__

__setattr__(name: str, value: Any) -> None

_clone_preserving_wcs_state

_clone_preserving_wcs_state() -> 'WCS'

_coerce_stacked_coord

_coerce_stacked_coord(value: Any, name: str) -> Tensor

_copy_wcs_header

_copy_wcs_header() -> dict[str, Any]

_dropaxis_fixed_at_zero

_dropaxis_fixed_at_zero(axis: int) -> 'WCS'

Drop an axis fixed by slicing at zero-based pixel coordinate 0.

_mps_float32_error_pixels

_mps_float32_error_pixels() -> float

Expected float32 (MPS) round-trip position error in pixels.

One float32 ulp of the largest world value on each celestial axis (longitude up to 360 degrees, scaled by cos(dec_0); latitude up to 90) divided by the smallest pixel scale (norm of a CD column, degrees per pixel), plus one ulp of the largest pixel coordinate (NAXISn or 2 CRPIXn). Zero without a celestial pair.

_normalize_axis_index staticmethod

_normalize_axis_index(
    axis_index: int, axis_len: int | None
) -> int

_normalize_axis_slice staticmethod

_normalize_axis_slice(
    axis_slice: slice, axis_len: int | None
) -> tuple[int, int | None, int]

_normalize_wcs_slice

_normalize_wcs_slice(
    view: "slice | int | tuple[slice | int | EllipsisType, ...]",
    *,
    numpy_order: bool,
) -> "tuple[slice | int, ...]"

_pixel_to_world_2d_fast

_pixel_to_world_2d_fast(
    x: Tensor, y: Tensor, origin: float = 0
) -> Tuple[Tensor, Tensor]

Fast path for common 2D separate-argument pixel->world calls.

_rebase_sip_header_for_diagonal_pixel_map

_rebase_sip_header_for_diagonal_pixel_map(
    header: dict[str, Any], steps: tuple[int, int]
) -> None

_require_wcs_device

_require_wcs_device(value: Tensor, name: str) -> Tensor

Differentiable forms need the WCS on the coordinates' device.

The plain forms follow accelerator inputs; the differentiable forms keep WCS parameters in the graph (WCS fitting), so a device mismatch is reported here instead of moving parameters or failing inside torch.

_slice_preserve_axes

_slice_preserve_axes(
    pixel_slices: tuple[slice, ...],
) -> "WCS"

_stacked_pixels_to_world_flat

_stacked_pixels_to_world_flat(
    pixels_flat: Tensor,
    origin: float,
    *,
    allow_cpp_sphere: bool = True,
) -> Tensor

Fused pixels (internal) -> rel -> world for torch.compile (2D spatial).

_sub_wcs

_sub_wcs(
    keep_axes: list[int],
    *,
    fixed_rel_by_axis: dict[int, Tensor | float]
    | None = None,
) -> "WCS"

_transform_optimized

_transform_optimized(
    rel: Tensor, *, allow_cpp_sphere: bool = True
) -> Tensor

The hot path for coordinate transformation. Input: (N, NAXIS) relative pixels (pix - crpix [internal]) Output: (N, NAXIS) world

When allow_cpp_sphere is False, pole spherical rotation stays in Torch so torch.compile can fuse the full forward graph (stacked pixel API).

_validate_axis_uncoupled_for_drop

_validate_axis_uncoupled_for_drop(axis: int) -> None

_warn_mps_precision

_warn_mps_precision() -> None

Emit :class:PrecisionWarning once per WCS when MPS float32 is too coarse.

_wcs_state_constructor_kwargs

_wcs_state_constructor_kwargs() -> dict[str, Any]

_world_to_pixel_2d_fast

_world_to_pixel_2d_fast(
    ra: Tensor,
    dec: Tensor,
    iterative: bool = True,
    origin: float = 0,
) -> Tuple[Tensor, Tensor]

Fast path for common 2D separate-argument world->pixel calls.

compile

compile(**kwargs: Any) -> 'WCS'

Wrap the pure-Python 2D spatial cores in torch.compile.

After compile(), use a stacked pixel tensor pixel_to_world(pixels) with pixels.shape == (..., 2) for 2D spatial WCS. That path prefers a dedicated compiled graph that fuses pixels + (1-origin) - CRPIX with the transform and uses pure Torch pole rotation (no C++ sphere op inside the graph) so torch.compile can optimize end-to-end. The inverse world_to_pixel(world) with world.shape == (..., 2) uses an analogous fused graph with pure Torch inverse pole rotation for origin in {0, 1}. Other origin values and naxis > 2 still use _compiled_transform_fn / the general inverse path on intermediate coords.

The two-argument pixel_to_world(x, y) shortcut may still use native C++ fast paths. Run benchmarks/bench_wcs_small_n_paths.py from the torchsky-harness checkout for timings against Astropy.

Parameters:

Name Type Description Default
**kwargs Any

Arguments passed to torch.compile (e.g., mode, options).

{}

dropaxis

dropaxis(axis: int) -> 'WCS'

Return a WCS with one pixel/world axis removed.

The axis is 0-based in FITS pixel-axis order. Coupled linear and celestial axes are baked at CRPIX (fixed_rel=0) so the retained transform matches the parent WCS on that slice.

pixel_to_world

pixel_to_world(
    *args, **kwargs
) -> Union[Tensor, Tuple[Tensor, ...]]

Convert pixel coordinates to world coordinates. Args: origin: FITS origin (default 0). Set to 1 for FITS 1-based indexing.

slice

slice(
    view: "slice | int | tuple[slice | int | EllipsisType, ...]",
    *,
    numpy_order: bool = True,
) -> "WCS"

Return a WCS adjusted for an array slice/cutout.

By default view is in NumPy array order, so a 2D image slice is (rows, columns) while FITS pixel axes are updated as (x, y). Positive-step and negative-step slice objects preserve dimensionality. Integer indices fix one pixel coordinate and drop the corresponding uncoupled WCS axis.

sub

sub(axes: Sequence[int]) -> 'WCS'

Return a WCS containing selected pixel/world axes in the requested order.

Axes are 0-based in FITS pixel-axis order. Dropped axes must be linearly uncoupled from retained axes. Spatial WCS instances keep both celestial projection axes; retained axes may be reordered in FITS/API order.

to

to(device: Union[str, device])

Move WCS parameters to specified device.

CUDA and CPU keep float64 cached parameters. MPS is float32-only, so cached tensors are cast to float32 there (arcsecond-class error vs float64 is expected). C++ fused kernels stay CPU.

to_header

to_header(
    *, relax: bool = True, include_naxis: bool = False
) -> dict[str, Any]

with_affine

with_affine(
    matrix_or_fit: Any,
    offset: Any | None = None,
    *,
    metadata_prefix: str = "TSKYAF",
) -> "WCS"

Return a WCS corrected by an AffineFitResult or (matrix, offset).

with_affine_fit_correction

with_affine_fit_correction(
    fit: Any, *, metadata_prefix: str = "TSKYAF"
) -> "WCS"

Return a WCS corrected by an AffineFitResult pixel fit.

with_pixel_affine_correction

with_pixel_affine_correction(
    matrix: Any,
    offset: Any,
    *,
    metadata_prefix: str = "TSKYAF",
) -> "WCS"

Return a WCS corrected by a fitted 2D pixel affine transform.

matrix and offset map old/source zero-based pixel coordinates to corrected zero-based pixel coordinates: p_new = matrix @ p_old + offset. The returned WCS maps corrected pixels to the same world coordinates as the original WCS at the corresponding source pixels.

The transform acts on the two pixel axes associated with the celestial CTYPE pair. Distorted WCS store the affine and apply it in pixel space before SIP/TPV/TNX/ZPX distortion.

world_to_pixel

world_to_pixel(
    *args, **kwargs
) -> Union[Tensor, Tuple[Tensor, ...]]

World -> Pixel.

Detector astrometry

AffineFreeResidualGrid2D

AffineFreeResidualGrid2D(
    control: Any,
    *,
    origin: Any = (0.0, 0.0),
    spacing: Any = (1.0, 1.0),
    mode: InterpolationMode = "bicubic",
)

Bases: Module

Smooth detector-coordinate residual with constant/affine modes removed.

affine_basis instance-attribute

affine_basis: Tensor

control instance-attribute

control: Parameter = Parameter(clone())

mode instance-attribute

mode: InterpolationMode = mode

origin instance-attribute

origin: Tensor

projected_control property

projected_control: Tensor

spacing instance-attribute

spacing: Tensor

bending_energy

bending_energy() -> Tensor

Mean squared second difference of the projected control grid.

evaluate_with_jacobian

evaluate_with_jacobian(
    points: Any,
) -> tuple[Tensor, Tensor]

forward

forward(points: Any) -> Tensor

jacobian

jacobian(points: Any) -> Tensor

DetectorToSkyTransform

DetectorToSkyTransform(
    detector_to_tangent: DetectorToTangentTransform,
    attitude: Any,
)

Bases: Module

Forward-only detector-to-sky composition with a frozen attitude.

The attitude callable receives tangent-plane (..., 2) points and may return either an (..., 2) tensor or an (longitude, latitude) tuple. Its parameters are frozen while derivatives with respect to coordinates remain available. Invertibility diagnostics intentionally apply only to the detector-to-tangent transform, before any spherical longitude wrapping.

attitude instance-attribute

attitude: Any = attitude

detector_to_tangent instance-attribute

detector_to_tangent: DetectorToTangentTransform = (
    detector_to_tangent
)

assert_invertible

assert_invertible(
    *,
    subdivisions: int | None = None,
    determinant_floor: float = 0.0,
) -> Tensor

forward

forward(points: Any) -> Tensor

jacobian_determinant

jacobian_determinant(points: Any) -> Tensor

Return the detector-to-tangent determinant, not a sky-chart value.

pixel_to_world

pixel_to_world(x: Any, y: Any) -> tuple[Tensor, Tensor]

DetectorToTangentTransform

DetectorToTangentTransform(
    table: RegularGridTransform2D,
    affine: TangentPlaneAffine,
    residual: AffineFreeResidualGrid2D | None = None,
)

Bases: Module

Compose a fixed table, exposure affine, and optional detector residual.

affine instance-attribute

affine: TangentPlaneAffine = affine

residual instance-attribute

residual: AffineFreeResidualGrid2D | None = residual

table instance-attribute

table: RegularGridTransform2D = table

assert_invertible

assert_invertible(
    *,
    subdivisions: int | None = None,
    determinant_floor: float = 0.0,
) -> Tensor

evaluate_with_jacobian

evaluate_with_jacobian(
    points: Any,
) -> tuple[Tensor, Tensor]

forward

forward(points: Any) -> Tensor

inverse

inverse(
    values: Any,
    *,
    max_iter: int = 25,
    atol: float | None = None,
    rtol: float = 0.0,
) -> Tensor

jacobian_determinant

jacobian_determinant(points: Any) -> Tensor

RegularGridTransform2D

RegularGridTransform2D(
    table: Any,
    *,
    origin: Any = (0.0, 0.0),
    spacing: Any = (1.0, 1.0),
    mode: InterpolationMode = "bilinear",
    validation_subdivisions: int = 4,
    determinant_floor: float = 0.0,
)

Bases: Module

Frozen regular-grid detector transform with consistent sampled parity.

table has shape (height, width, 2) and samples detector coordinates origin + spacing * (x_index, y_index). Bicubic mode uses local four-point Lagrange interpolation, which reproduces affine maps exactly, including at the detector boundary. Sampled Jacobians may be consistently positive or consistently negative; a reflected coordinate frame is preserved without changing its values. The determinant floor applies to their absolute magnitude. These sampled diagnostics do not prove global injectivity between validation points.

determinant_floor instance-attribute

determinant_floor = float(determinant_floor)

grid_shape property

grid_shape: tuple[int, int]

mode instance-attribute

mode: InterpolationMode = mode

origin instance-attribute

origin: Tensor

spacing instance-attribute

spacing: Tensor

table instance-attribute

table: Tensor

validation_subdivisions instance-attribute

validation_subdivisions = int(validation_subdivisions)

_coerce_points

_coerce_points(points: Any) -> Tensor

assert_invertible

assert_invertible(
    *,
    subdivisions: int | None = None,
    determinant_floor: float | None = None,
) -> Tensor

Return sampled determinants or reject a non-finite/folded table.

diagnostic_points

diagnostic_points(
    subdivisions: int | None = None,
) -> Tensor

evaluate_with_jacobian

evaluate_with_jacobian(
    points: Any,
) -> tuple[Tensor, Tensor]

forward

forward(points: Any) -> Tensor

inverse

inverse(
    values: Any,
    *,
    max_iter: int = 25,
    atol: float | None = None,
    rtol: float = 0.0,
    fail_closed: bool = True,
) -> Tensor

Newton inverse with output-unit atol and dimensionless rtol.

jacobian

jacobian(points: Any) -> Tensor

jacobian_determinant

jacobian_determinant(points: Any) -> Tensor

SampledTransformValidation dataclass

SampledTransformValidation(
    errors_mas: Tensor,
    p99_mas: float,
    max_mas: float,
    p99_limit_mas: float,
    max_limit_mas: float,
)

Angular residual summary for independent transform samples.

errors_mas instance-attribute

errors_mas: Tensor

max_limit_mas instance-attribute

max_limit_mas: float

max_mas instance-attribute

max_mas: float

p99_limit_mas instance-attribute

p99_limit_mas: float

p99_mas instance-attribute

p99_mas: float

passed property

passed: bool

assert_valid

assert_valid() -> None

TangentPlaneAffine

TangentPlaneAffine(matrix: Any, offset: Any)

Bases: Module

Learnable full affine correction in a two-dimensional tangent plane.

matrix instance-attribute

matrix: Parameter = Parameter(clone())

offset instance-attribute

offset: Parameter = Parameter(clone())

assert_invertible

assert_invertible(determinant_floor: float = 0.0) -> Tensor

forward

forward(points: Any) -> Tensor

identity classmethod

identity(
    *,
    dtype: dtype = float32,
    device: device | str | None = None,
) -> TangentPlaneAffine

inverse

inverse(points: Any) -> Tensor

jacobian

jacobian(points: Tensor) -> Tensor

jacobian_determinant

jacobian_determinant() -> Tensor

validate_sampled_transform

validate_sampled_transform(
    transform: Any,
    reference: Any,
    points: Any,
    *,
    coordinates: AngularCoordinates = "sky_degrees",
    p99_limit_mas: float = 0.01,
    max_limit_mas: float = 0.05,
    raise_on_failure: bool = False,
) -> SampledTransformValidation

Compare a torch transform with an independent sampled reference.

Celestial frames

CelestialFrameBiasWarning

Bases: UserWarning

A resampling path converted between FK5 (J2000) and ICRS.

The conversion is the 23-mas-scale FK5 frame bias, correct when the input metadata are right. It is emitted because many survey headers keep a legacy RADESYS/RADECSYS = 'FK5' (or EQUINOX = 2000 alone) while their astrometric solution was fitted to Gaia, i.e. is ICRS.

convert_celestial

convert_celestial(
    lon_deg: Any,
    lat_deg: Any,
    *,
    from_frame: str = "ICRS",
    to_frame: str = "ICRS",
    from_equinox: float | None = None,
    to_equinox: float | None = None,
    tt_mjd: Any | None = None,
) -> tuple[Tensor, Tensor]

Convert between the currently supported celestial frames.

ecliptic_of_date_to_icrs

ecliptic_of_date_to_icrs(
    lon_deg: Any, lat_deg: Any, tt_mjd: Any
) -> tuple[Tensor, Tensor]

Rotate mean ecliptic of date to ICRS via IAU 2006 NPB.

ecliptic_to_icrs

ecliptic_to_icrs(
    lon_deg: Any, lat_deg: Any
) -> tuple[Tensor, Tensor]

Rotate mean ecliptic of J2000 coordinates to ICRS equatorial.

galactic_to_icrs

galactic_to_icrs(
    l_deg: Any, b_deg: Any
) -> tuple[Tensor, Tensor]

Convert Galactic lon/lat to ICRS equatorial coordinates.

galactocentric_to_icrs

galactocentric_to_icrs(
    xyz_kpc: Any,
    *,
    galcen_distance_kpc: float = _GALCEN_DISTANCE_KPC,
    galcen_ra_deg: float = _GALCEN_RA_DEG,
    galcen_dec_deg: float = _GALCEN_DEC_DEG,
    z_sun_pc: float = _Z_SUN_PC,
) -> tuple[Tensor, Tensor, Tensor]

Galactocentric Cartesian (kpc) → ICRS spherical plus distance (kpc).

heliocentric_rv_to_lsr

heliocentric_rv_to_lsr(
    ra_deg: Any,
    dec_deg: Any,
    rv_kms: Any,
    *,
    solar_u_kms: float = _SOLAR_U_KMS,
    solar_v_kms: float = _SOLAR_V_KMS,
    solar_w_kms: float = _SOLAR_W_KMS,
) -> Tensor

Heliocentric radial velocity → LSR (km/s) with explicit solar UVW.

icrs_to_ecliptic

icrs_to_ecliptic(
    ra_deg: Any, dec_deg: Any
) -> tuple[Tensor, Tensor]

Rotate ICRS equatorial coordinates to mean ecliptic of J2000.

icrs_to_ecliptic_of_date

icrs_to_ecliptic_of_date(
    ra_deg: Any, dec_deg: Any, tt_mjd: Any
) -> tuple[Tensor, Tensor]

Rotate ICRS to the mean ecliptic of date via IAU 2006 NPB.

tt_mjd is TT MJD. This is a geometric frame, not observed place: no aberration, refraction, or site.

icrs_to_galactic

icrs_to_galactic(
    ra_deg: Any, dec_deg: Any
) -> tuple[Tensor, Tensor]

Convert ICRS equatorial coordinates to Galactic lon/lat.

icrs_to_galactocentric

icrs_to_galactocentric(
    ra_deg: Any,
    dec_deg: Any,
    distance_kpc: Any,
    *,
    galcen_distance_kpc: float = _GALCEN_DISTANCE_KPC,
    galcen_ra_deg: float = _GALCEN_RA_DEG,
    galcen_dec_deg: float = _GALCEN_DEC_DEG,
    z_sun_pc: float = _Z_SUN_PC,
) -> Tensor

Heliocentric ICRS spherical → Galactocentric Cartesian (kpc).

Origin at the Galactic Centre (galcen_ra_deg / galcen_dec_deg). +x toward the anticenter (Sun at x ≈ -R0), +y in rotation, +z toward the NGP. z_sun_pc tilts the midplane so the Sun sits at z = z_sun. Solar peculiar velocity is not applied.

lsr_line_of_sight_kms

lsr_line_of_sight_kms(
    ra_deg: Any,
    dec_deg: Any,
    *,
    solar_u_kms: float = _SOLAR_U_KMS,
    solar_v_kms: float = _SOLAR_V_KMS,
    solar_w_kms: float = _SOLAR_W_KMS,
) -> Tensor

Solar peculiar velocity projected onto the ICRS line of sight (km/s).

UVW are Galactic: U toward the GC, V in rotation, W toward the NGP.

precess_fk5

precess_fk5(
    ra_deg: Any,
    dec_deg: Any,
    *,
    from_equinox: float = 2000.0,
    to_equinox: float = 2000.0,
) -> tuple[Tensor, Tensor]

Precess FK5 equatorial coordinates between Julian equinoxes.

Uses the IAU 1976 precession angles for FK5-style mean places. This is a compact torch-native parity target for common WCS RADESYS=FK5 / EQUINOX headers; higher-precision nutation and full FK4 E-term behavior are separate roadmap items.

propagate_proper_motion

propagate_proper_motion(
    lon_deg: Any,
    lat_deg: Any,
    pm_lon_coslat_mas_yr: Any,
    pm_lat_mas_yr: Any,
    *,
    source_epoch_jyear: Any,
    target_epoch_jyear: Any,
) -> tuple[Tensor, Tensor]

Propagate angular coordinates with proper motion.

pm_lon_coslat_mas_yr is the conventional longitude proper motion with the cosine-of-latitude factor already applied (for ICRS, pm_ra_cosdec). Epochs are Julian years. Inputs broadcast and outputs are longitude and latitude in degrees, with longitude wrapped to [0, 360).

This follows the same unit-distance Cartesian propagation used by SkyCoord.apply_space_motion when distance and radial velocity are not supplied. It stays well behaved at the poles, unlike dividing a longitude increment by cos(latitude).

Parameters:

Name Type Description Default
lon_deg Any

Initial longitude in degrees.

required
lat_deg Any

Initial latitude in degrees.

required
pm_lon_coslat_mas_yr Any

Cosine-weighted longitude proper motion in mas/yr.

required
pm_lat_mas_yr Any

Latitude proper motion in mas/yr.

required
source_epoch_jyear Any

Initial Julian epoch.

required
target_epoch_jyear Any

Destination Julian epoch.

required

Returns:

Type Description
tuple[Tensor, Tensor]

Propagated longitude and latitude tensors in degrees.

Examples:

>>> from torchsky.wcs import propagate_proper_motion
>>> lon, lat = propagate_proper_motion(10.0, 20.0, 0.0, 0.0, source_epoch_jyear=2000.0, target_epoch_jyear=2010.0)
>>> round(float(lon), 6), round(float(lat), 6)
(10.0, 20.0)

propagate_proper_motion_with_jacobian

propagate_proper_motion_with_jacobian(
    lon_deg: Any,
    lat_deg: Any,
    pm_lon_coslat_mas_yr: Any,
    pm_lat_mas_yr: Any,
    *,
    source_epoch_jyear: Any,
    target_epoch_jyear: Any,
) -> tuple[tuple[Tensor, Tensor], Tensor]

Propagate angular motion and return its batched local Jacobian.

The Jacobian has trailing dimensions (2, 4). Its input order is (position_east, position_north, pm_lon_coslat, pm_lat) and its output rows are local east/north position at the propagated coordinate. Position units are mas and proper-motion units are mas/yr.

This is the unit-distance angular-motion model used by :func:propagate_proper_motion; it does not invent a distance or radial velocity and therefore does not model perspective acceleration.

propagate_space_motion

propagate_space_motion(
    lon_deg: Any,
    lat_deg: Any,
    pm_lon_coslat_mas_yr: Any,
    pm_lat_mas_yr: Any,
    parallax_mas: Any,
    radial_velocity_km_s: Any,
    *,
    source_epoch_jyear: Any,
    target_epoch_jyear: Any,
) -> tuple[Tensor, Tensor, Tensor, Tensor, Tensor, Tensor]

Propagate a complete barycentric astrometric state in ICRS.

Inputs and outputs are longitude/latitude in degrees, cosine-weighted longitude and latitude proper motions in mas/yr, parallax in mas, and radial velocity in km/s. Epochs are TCB Julian years. Inputs broadcast.

The implementation follows the ERFA/SOFA starpv to rectilinear motion with changing light time to pvstar model, including the special- relativistic conversion between catalogue observables and inertial velocity. A complete state is required: use :func:propagate_proper_motion when distance or radial velocity is unavailable.

Returns:

Type Description
tuple[Tensor, Tensor, Tensor, Tensor, Tensor, Tensor]

(lon, lat, pm_lon_coslat, pm_lat, parallax, radial_velocity).

Parameters:

Name Type Description Default
lon_deg Any

Initial ICRS longitude in degrees.

required
lat_deg Any

Initial ICRS latitude in degrees.

required
pm_lon_coslat_mas_yr Any

Cosine-weighted longitude proper motion in mas/yr.

required
pm_lat_mas_yr Any

Latitude proper motion in mas/yr.

required
parallax_mas Any

Parallax in milliarcseconds.

required
radial_velocity_km_s Any

Radial velocity in km/s.

required
source_epoch_jyear Any

Initial TCB Julian epoch.

required
target_epoch_jyear Any

Destination TCB Julian epoch.

required

Examples:

>>> from torchsky.wcs import propagate_space_motion
>>> result = propagate_space_motion(10.0, 20.0, 0.0, 0.0, 10.0, 0.0, source_epoch_jyear=2000.0, target_epoch_jyear=2000.0)
>>> len(result)
6

propagate_space_motion_with_jacobian

propagate_space_motion_with_jacobian(
    lon_deg: Any,
    lat_deg: Any,
    pm_lon_coslat_mas_yr: Any,
    pm_lat_mas_yr: Any,
    parallax_mas: Any,
    radial_velocity_km_s: Any,
    *,
    source_epoch_jyear: Any,
    target_epoch_jyear: Any,
) -> tuple[
    tuple[Tensor, Tensor, Tensor, Tensor, Tensor, Tensor],
    Tensor,
]

Propagate space motion and return its batched local 6D Jacobian.

The Jacobian's trailing dimensions are (6, 6). Its input and output order is (position_east, position_north, pm_lon_coslat, pm_lat, parallax, radial_velocity). Position perturbations are in mas, proper motions in mas/yr, parallax in mas, and radial velocity in km/s.

The positional rows use local tangent bases at the source and propagated positions. This stays continuous across longitude wrap and avoids the singular raw-longitude derivative near the poles. A covariance in these local catalogue units can therefore be propagated with J @ C @ J.mT. Inputs broadcast and are validated by :func:propagate_space_motion.

Returns:

Type Description
tuple[tuple[Tensor, Tensor, Tensor, Tensor, Tensor, Tensor], Tensor]

(propagated_state, jacobian).

Graph

AmbiguousPathError

Bases: RuntimeError

GeneralizedWCS

GeneralizedWCS(
    graph: TransformGraph,
    input_frame: str,
    output_frame: str,
    *,
    path: Sequence[str] | None = None,
)

Bases: Module

bounding_box property

bounding_box: (
    tuple[tuple[float | None, float | None], ...] | None
)

graph instance-attribute

graph = graph

input_frame instance-attribute

input_frame = input_frame

output_frame instance-attribute

output_frame = output_frame

path instance-attribute

path = selected

pixel_n_dim property

pixel_n_dim: int

world_axis_names property

world_axis_names: tuple[str, ...]

world_axis_physical_types property

world_axis_physical_types: tuple[str | None, ...]

world_axis_units property

world_axis_units: tuple[str, ...]

world_n_dim property

world_n_dim: int

_stack_values staticmethod

_stack_values(
    values: Sequence[Any], expected: int
) -> Tensor

from_state classmethod

from_state(
    metadata: Mapping[str, Any],
    tensors: Mapping[str, Tensor],
) -> GeneralizedWCS

get_transform

get_transform(
    source: str,
    target: str,
    *,
    path: Sequence[str] | None = None,
) -> Mapping

pixel_to_world

pixel_to_world(pixels: Tensor) -> Tensor

pixel_to_world_values

pixel_to_world_values(*pixels: Any) -> tuple[Tensor, ...]

to_state

to_state() -> tuple[dict[str, Any], dict[str, Tensor]]

world_to_pixel

world_to_pixel(world: Tensor) -> Tensor

world_to_pixel_values

world_to_pixel_values(*world: Any) -> tuple[Tensor, ...]

TransformEdge dataclass

TransformEdge(source: str, target: str, mapping: Mapping)

mapping instance-attribute

mapping: Mapping

source instance-attribute

source: str

target instance-attribute

target: str

TransformGraph

TransformGraph(
    frames: Sequence[FrameSpec] = (),
    transforms: Sequence[TransformEdge] = (),
)

Bases: Module

_sources instance-attribute

_sources: list[str] = []

_targets instance-attribute

_targets: list[str] = []

edges property

edges: tuple[TransformEdge, ...]

frames instance-attribute

frames: dict[str, FrameSpec] = {}

mappings instance-attribute

mappings = _mapping_list()

_adjacency

_adjacency() -> dict[str, list[tuple[str, Mapping]]]

_mappings_for_path

_mappings_for_path(path: Sequence[str]) -> list[Mapping]

add_frame

add_frame(frame: FrameSpec) -> TransformGraph

add_transform

add_transform(
    source: str, target: str, mapping: Mapping
) -> TransformGraph

find_path

find_path(
    source: str,
    target: str,
    *,
    path: Sequence[str] | None = None,
) -> tuple[str, ...]

from_state classmethod

from_state(
    metadata: Mapping[str, Any],
    tensors: Mapping[str, Tensor],
) -> TransformGraph

get_mapping

get_mapping(
    source: str,
    target: str,
    *,
    path: Sequence[str] | None = None,
) -> Mapping

to_state

to_state() -> tuple[dict[str, Any], dict[str, Tensor]]

validate

validate() -> None

UnsupportedPathError

Bases: RuntimeError

Gwcs sampling

sample_gwcs module-attribute

sample_gwcs_epochs module-attribute

sample_gwcs_epochs = sample_gwcs_detector_epochs

FrozenDetectorEpochTables dataclass

FrozenDetectorEpochTables(
    epochs: tuple[float, ...],
    samples: tuple[GWCSGridSamplingResult, ...],
)

Time-dependent detector tables as frozen samples, not a live GWCS graph.

epochs instance-attribute

epochs: tuple[float, ...]

samples instance-attribute

samples: tuple[GWCSGridSamplingResult, ...]

evaluate

evaluate(detector_xy: Any, epoch: float) -> Tensor

Device-native table eval. Runtime does not import gwcs.

inverse

inverse(sky_xy: Any, epoch: float, **kwargs: Any) -> Tensor

Newton inverse of the frozen table at the nearest epoch.

to

to(device: Any) -> 'FrozenDetectorEpochTables'

Move frozen tables to device. Sampling still happened on host.

transform_at

transform_at(epoch: float) -> RegularGridTransform2D

GWCSGridSamplingResult dataclass

GWCSGridSamplingResult(
    transform: RegularGridTransform2D,
    validation: Mapping[str, SampledTransformValidation],
    grid_shape: tuple[int, int],
    detector_bounds: tuple[
        tuple[float, float], tuple[float, float]
    ],
    reference_name: str,
    calibration_provenance: Mapping[str, str],
)

Frozen torch table, validation groups, and calibration provenance.

calibration_provenance instance-attribute

calibration_provenance: Mapping[str, str]

detector_bounds instance-attribute

detector_bounds: tuple[
    tuple[float, float], tuple[float, float]
]

grid_shape instance-attribute

grid_shape: tuple[int, int]

passed property

passed: bool

reference_name instance-attribute

reference_name: str

transform instance-attribute

validation instance-attribute

validation: Mapping[str, SampledTransformValidation]

provenance_dict

provenance_dict() -> dict[str, object]

IFUSliceWCS dataclass

IFUSliceWCS(
    ra_map: Tensor,
    dec_map: Tensor,
    wavelength_map: Tensor,
    slice_id_map: Tensor,
)

Piecewise-disjoint 2D detector -> 3D (ra_deg, dec_deg, wavelength) IFU slice WCS.

Prevents cross-slice interpolation bleed at IFU slice boundaries by restricting sub-pixel bilinear interpolation strictly to neighbors sharing the same slice_id >= 0.

dec_map instance-attribute

dec_map: Tensor

detector_shape property

detector_shape: tuple[int, int]

ra_map instance-attribute

ra_map: Tensor

slice_id_map instance-attribute

slice_id_map: Tensor

valid_mask property

valid_mask: Tensor

wavelength_map instance-attribute

wavelength_map: Tensor

__post_init__

__post_init__() -> None

from_callable classmethod

from_callable(
    reference: Callable[..., Any],
    detector_shape: tuple[int, int],
    *,
    slice_id_map: Tensor | None = None,
    device: Any = "cpu",
) -> "IFUSliceWCS"

Sample a 2D -> 3D (ra, dec, wavelength) callable across the detector grid.

from_slices classmethod

from_slices(
    detector_shape_or_slices: Any,
    slices: list[Any] | tuple[Any, ...] | None = None,
    *,
    device: Any = "cpu",
) -> "IFUSliceWCS"

Build an :class:IFUSliceWCS from (slice_mask, callable_or_tuple) pairs or slice dicts.

pixel_to_world

pixel_to_world(
    x: Tensor | float, y: Tensor | float
) -> tuple[Tensor, Tensor, Tensor]

Evaluate (ra_deg, dec_deg, wavelength) at sub-pixel (x, y) without cross-slice bleed.

to

to(device: Any) -> 'IFUSliceWCS'

sample_gwcs_detector_epochs

sample_gwcs_detector_epochs(
    references: Mapping[float, Callable[..., Any]],
    *,
    detector_bounds: tuple[
        tuple[float, float], tuple[float, float]
    ],
    initial_grid_shape: tuple[int, int] = (9, 9),
    maximum_grid_shape: tuple[int, int] = (257, 257),
    interpolation: Literal[
        "bilinear", "bicubic"
    ] = "bicubic",
    coordinates: AngularCoordinates = "plane_arcsec",
    random_validation_points: int = 4096,
    seed: int = 0,
    p99_limit_mas: float = 0.01,
    max_limit_mas: float = 0.05,
    chip_boundaries_x: tuple[float, ...] = (),
    reference_name: str = "gwcs_detector_to_v2v3",
    calibration_provenance: Mapping[str, str] | None = None,
    dtype: dtype = float64,
) -> FrozenDetectorEpochTables

Sample one frozen table per epoch. Runtime never imports gwcs.

sample_gwcs_detector_to_tangent

sample_gwcs_detector_to_tangent(
    reference: Callable[..., Any],
    *,
    detector_bounds: tuple[
        tuple[float, float], tuple[float, float]
    ],
    initial_grid_shape: tuple[int, int] = (9, 9),
    maximum_grid_shape: tuple[int, int] = (257, 257),
    interpolation: Literal[
        "bilinear", "bicubic"
    ] = "bicubic",
    coordinates: AngularCoordinates = "plane_arcsec",
    random_validation_points: int = 4096,
    seed: int = 0,
    p99_limit_mas: float = 0.01,
    max_limit_mas: float = 0.05,
    chip_boundaries_x: tuple[float, ...] = (),
    reference_name: str = "gwcs_detector_to_v2v3",
    calibration_provenance: Mapping[str, str] | None = None,
    dtype: dtype = float64,
) -> GWCSGridSamplingResult

Refine a detector table until independent points satisfy mas gates.

Iau2006

apply_dcr

apply_dcr(
    ra_deg: Tensor,
    dec_deg: Tensor,
    wavelength_angstrom: Tensor | float,
    zenith_deg: Tensor | float,
    parallactic_deg: Tensor | float = 0.0,
    *,
    ref_wavelength_angstrom: float = 5000.0,
    pressure_mbar: float = 780.0,
    temperature_c: float = 10.0,
    inverse: bool = False,
) -> tuple[Tensor, Tensor]

Apply or remove Differential Chromatic Refraction on (ra_deg, dec_deg).

apply_ephemeris_offset

apply_ephemeris_offset(
    ra_deg: Tensor,
    dec_deg: Tensor,
    *,
    mjd_obs: float,
    reference_mjd: float,
    tracking_rate: tuple[float, float] | None = None,
    dra_cosdec_arcsec_per_hr: float = 0.0,
    ddec_arcsec_per_hr: float = 0.0,
    inverse: bool = False,
) -> tuple[Tensor, Tensor]

Shift sky coordinates into (or out of) a moving target's comoving frame.

Parameters

tracking_rate (dra_cosdec_arcsec_per_hr, ddec_arcsec_per_hr) non-sidereal rate. inverse If False (default), maps sidereal sky coordinates at mjd_obs into the comoving target frame at reference_mjd (subtracting target motion). If True, maps comoving coordinates back to sidereal coordinates at mjd_obs.

apply_refraction

apply_refraction(
    alt_deg: Tensor,
    *,
    pressure_mbar: Tensor | float,
    temperature_c: Tensor | float,
) -> Tensor

Apply atmospheric refraction to altitude in degrees.

apply_stellar_aberration

apply_stellar_aberration(
    unit_xyz: Tensor, velocity_m_s: Tensor
) -> Tensor

Classical stellar aberration: normalize(p + v/c).

dcr_offset

dcr_offset(
    wavelength_angstrom: Tensor | float,
    zenith_deg: Tensor | float,
    parallactic_deg: Tensor | float = 0.0,
    *,
    ref_wavelength_angstrom: float = 5000.0,
    pressure_mbar: float = 780.0,
    temperature_c: float = 10.0,
) -> tuple[Tensor, Tensor]

Compute Differential Chromatic Refraction (DCR) tangent-plane offset (d_east_deg, d_north_deg).

Returns the apparent chromatic shift toward zenith at wavelength_angstrom relative to ref_wavelength_angstrom in degrees along local East and North.

Mapping

TransformMapping module-attribute

TransformMapping = Mapping

AffineMapping

AffineMapping(
    matrix: Tensor,
    offset: Tensor,
    input_axes: Sequence[AxisSpec],
    output_axes: Sequence[AxisSpec],
    *,
    domain: DomainSpec | None = None,
)

Bases: Mapping

matrix instance-attribute

matrix: Tensor

offset instance-attribute

offset: Tensor

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping | None

CallableMapping

CallableMapping(
    function: Callable[[Tensor], Tensor],
    input_axes: Sequence[AxisSpec],
    output_axes: Sequence[AxisSpec],
    *,
    inverse_function: Callable[[Tensor], Tensor]
    | None = None,
    domain: DomainSpec | None = None,
)

Bases: Mapping

function instance-attribute

function = function

inverse_function instance-attribute

inverse_function = inverse_function

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping | None

IdentityMapping

IdentityMapping(axes: Sequence[AxisSpec])

Bases: Mapping

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping

NumericalInverseMapping

NumericalInverseMapping(
    mapping: Mapping,
    *,
    initial: Tensor,
    bounds: DomainSpec,
    max_iterations: int = 16,
    residual_tolerance: float = 1e-10,
    relative_tolerance: float = 1e-10,
    damping: float = 1e-08,
)

Bases: Mapping

bounds instance-attribute

bounds = bounds

damping instance-attribute

damping = float(damping)

initial instance-attribute

initial: Tensor

mapping instance-attribute

mapping = mapping

max_iterations instance-attribute

max_iterations = int(max_iterations)

relative_tolerance instance-attribute

relative_tolerance = float(relative_tolerance)

residual_tolerance instance-attribute

residual_tolerance = float(residual_tolerance)

_evaluate

_evaluate(inputs: Tensor) -> Tensor

solve

solve(targets: Tensor) -> NumericalInverseResult

NumericalInverseResult dataclass

NumericalInverseResult(
    values: Tensor,
    converged: Tensor,
    residual_norm: Tensor,
    iterations: int,
)

converged instance-attribute

converged: Tensor

iterations instance-attribute

iterations: int

residual_norm instance-attribute

residual_norm: Tensor

values instance-attribute

values: Tensor

ParallelMapping

ParallelMapping(mappings: Sequence[Mapping])

Bases: Mapping

_input_sizes instance-attribute

_input_sizes = tuple(n_inputs for mapping in mappings_tuple)

mappings instance-attribute

mappings = _mapping_list(mappings_tuple)

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping | None

PortRoute dataclass

PortRoute(
    mapping: Mapping,
    inputs: Sequence[int],
    outputs: Sequence[int],
)

inputs instance-attribute

inputs: tuple[int, ...]

mapping instance-attribute

mapping: Mapping

outputs instance-attribute

outputs: tuple[int, ...]

PortRoutingMapping

PortRoutingMapping(
    input_axes: Sequence[AxisSpec],
    output_axes: Sequence[AxisSpec],
    routes: Sequence[PortRoute],
    *,
    domain: DomainSpec | None = None,
)

Bases: Mapping

route_mappings instance-attribute

route_mappings = _mapping_list(
    mapping for route in routes_tuple
)

routes instance-attribute

routes = routes_tuple

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping | None

SerialMapping

SerialMapping(mappings: Sequence[Mapping])

Bases: Mapping

mappings instance-attribute

mappings = _mapping_list(flattened)

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping | None

UnitConversionMapping

UnitConversionMapping(
    input_axes: Sequence[AxisSpec],
    output_axes: Sequence[AxisSpec],
)

Bases: Mapping

factors instance-attribute

factors: Tensor

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping

UnsupportedInverseError

Bases: RuntimeError

WCSMapping

WCSMapping(wcs: Any, *, direction: str = 'pixel_to_world')

Bases: Mapping

direction instance-attribute

direction = direction

wcs instance-attribute

wcs = wcs

_evaluate

_evaluate(inputs: Tensor) -> Tensor

_make_exact_inverse

_make_exact_inverse() -> Mapping

Observed

EarthOrientation dataclass

EarthOrientation(
    dut1_s: Tensor,
    xp_arcsec: Tensor | None = None,
    yp_arcsec: Tensor | None = None,
    tt_minus_utc_s: Tensor | None = None,
)

IERS Earth orientation. dut1_s is required.

Polar motion xp_arcsec / yp_arcsec is optional. If either is set, both are applied (missing member treated as 0) via SOFA pom00 with TIO locator s' = 0. tt_minus_utc_s overrides TT−UTC; when it is None, TT−UTC is 32.184 s + TAI−UTC from torchsky's leap-second table, and epochs outside that table (before 1972 or after its expiry) raise ValueError.

dut1_s instance-attribute

dut1_s: Tensor

tt_minus_utc_s class-attribute instance-attribute

tt_minus_utc_s: Tensor | None = None

xp_arcsec class-attribute instance-attribute

xp_arcsec: Tensor | None = None

yp_arcsec class-attribute instance-attribute

yp_arcsec: Tensor | None = None

__post_init__

__post_init__() -> None

Site dataclass

Site(
    lon_deg: Tensor,
    lat_deg: Tensor,
    height_m: Tensor | float = 0.0,
    pressure_mbar: Tensor | float | None = None,
    temperature_c: Tensor | float | None = None,
    relative_humidity: Tensor | float = 0.0,
    wavelength_um: Tensor | float = 0.55,
)

Geodetic site. Height is WGS84 ellipsoidal height (metres) on the ITRS path.

relative_humidity (0..1) and wavelength_um (> 100 selects the radio formula) only enter the ERFA refco refraction model.

height_m class-attribute instance-attribute

height_m: Tensor | float = 0.0

lat_deg instance-attribute

lat_deg: Tensor

lon_deg instance-attribute

lon_deg: Tensor

pressure_mbar class-attribute instance-attribute

pressure_mbar: Tensor | float | None = None

relative_humidity class-attribute instance-attribute

relative_humidity: Tensor | float = 0.0

temperature_c class-attribute instance-attribute

temperature_c: Tensor | float | None = None

wavelength_um class-attribute instance-attribute

wavelength_um: Tensor | float = 0.55

__post_init__

__post_init__() -> None

observed_altaz

observed_altaz(
    state: CatalogState,
    *,
    obstime_mjd_utc: Any,
    site: Site,
    eop: EarthOrientation,
    pn: PNModel | None = None,
    aberration: bool = False,
    refraction: bool = False,
    refraction_model: RefractionModel = "refco",
) -> tuple[Tensor, Tensor]

Return (az_deg, alt_deg) from north toward east.

obstime_mjd_utc is UTC MJD. UT1 = UTC + DUT1. Polar motion is applied when xp/yp are set.

pn=None (default) and pn='iau2006' apply Fukushima-Williams bias-precession and IAU 2000A nutation via the CIRS matrix; with aberration=True this matches astropy AltAz to about 1 arcsec. TT−UTC is eop.tt_minus_utc_s when set, otherwise 32.184 s + TAI−UTC from torchsky's leap-second table; an epoch outside that table (before 1972, or after its expiry) raises ValueError rather than guessing. pn='none' is an explicit opt-in that omits precession-nutation and uses GMST; it is approximate (~0.3 deg off) and is continuous in xp/yp (zero polar motion equals no polar motion). aberration=True converts the astrometric ICRS direction to the apparent place as ERFA atciq does: solar light deflection plus annual and diurnal aberration (the observer's Earth-rotation velocity), with the epv00 Earth ephemeris. Without refraction the result agrees with erfa.atco13 to < 1 mas (residual: TIO locator s' = 0, observer offset in the solar deflection, TT used for TDB). refraction=True applies the ERFA refco model (A tan z + B tan^3 z, honouring site.relative_humidity and site.wavelength_um) to the topocentric direction as atioq does; refraction_model="saemundsson" selects the Saemundsson/Meeus altitude formula instead. Both are off unless requested and need site.pressure_mbar and site.temperature_c.

Time-only quantities are evaluated in float64 on CPU on every device; only the final rotation matrices move to the coordinate device (CUDA float64, MPS float32). Gradients flow through the coordinates. The kernels are ATen, not fused C++.

Residuals

AstrometricResidualFeatures dataclass

AstrometricResidualFeatures(
    focal_xy: Tensor,
    ccd_xy: Tensor,
    band_encoding: Tensor,
    color: Tensor,
    time: Tensor,
    airmass: Tensor,
    parallactic_angle: Tensor,
    telemetry: Tensor,
)

Continuous and explicitly encoded features; identifiers are never embedded.

airmass instance-attribute

airmass: Tensor

band_encoding instance-attribute

band_encoding: Tensor

ccd_xy instance-attribute

ccd_xy: Tensor

color instance-attribute

color: Tensor

count property

count: int

focal_xy instance-attribute

focal_xy: Tensor

parallactic_angle instance-attribute

parallactic_angle: Tensor

telemetry instance-attribute

telemetry: Tensor

time instance-attribute

time: Tensor

__post_init__

__post_init__() -> None

tensor

tensor() -> Tensor

AstrometricResidualLadder

AstrometricResidualLadder(
    gauge: TangentPlaneGauge, envelope: CorrectionEnvelope
)

Compose global, local, and sparse astrometric residual corrections.

envelope instance-attribute

envelope = envelope

gauge instance-attribute

gauge = gauge

_fallback

_fallback(
    name: str, like: Tensor, reason: str
) -> ResidualComponentResult

_gate

predict

predict(
    components: Sequence[ResidualComponentInput],
) -> ResidualLadderPrediction

BayesianModePrediction dataclass

BayesianModePrediction(
    stable: Tensor,
    drift: Tensor,
    local: Tensor,
    mean: Tensor,
    covariance: Tensor,
)

covariance instance-attribute

covariance: Tensor

drift instance-attribute

drift: Tensor

local instance-attribute

local: Tensor

mean instance-attribute

mean: Tensor

stable instance-attribute

stable: Tensor

BayesianModeState dataclass

BayesianModeState(
    mean: Tensor,
    covariance: Tensor,
    widths: tuple[int, int, int],
    version: int = 1,
)

covariance instance-attribute

covariance: Tensor

mean instance-attribute

mean: Tensor

version class-attribute instance-attribute

version: int = 1

widths instance-attribute

widths: tuple[int, int, int]

__post_init__

__post_init__() -> None

component_slice

component_slice(component: ResidualComponent) -> slice

ConditionalResidualPrediction dataclass

ConditionalResidualPrediction(
    mean: Tensor,
    covariance: Tensor,
    supported: Tensor,
    context_count: Tensor,
)

context_count instance-attribute

context_count: Tensor

covariance instance-attribute

covariance: Tensor

mean instance-attribute

mean: Tensor

supported instance-attribute

supported: Tensor

CorrectionEnvelope dataclass

CorrectionEnvelope(
    max_correction: float,
    max_jacobian: float,
    max_covariance_eigenvalue: float,
    gauge_tolerance: float = 1e-08,
)

gauge_tolerance class-attribute instance-attribute

gauge_tolerance: float = 1e-08

max_correction instance-attribute

max_correction: float

max_covariance_eigenvalue instance-attribute

max_covariance_eigenvalue: float

max_jacobian instance-attribute

max_jacobian: float

__post_init__

__post_init__() -> None

ResidualComponentInput dataclass

ResidualComponentInput(
    name: str,
    mean: Tensor,
    covariance: Tensor,
    supported: Tensor,
    jacobian: Tensor | None = None,
)

covariance instance-attribute

covariance: Tensor

jacobian class-attribute instance-attribute

jacobian: Tensor | None = None

mean instance-attribute

mean: Tensor

name instance-attribute

name: str

supported instance-attribute

supported: Tensor

ResidualComponentResult dataclass

ResidualComponentResult(
    name: str,
    mean: Tensor,
    covariance: Tensor,
    full_covariance: Tensor,
    trusted: Tensor,
    fallback_reason: str | None,
)

covariance instance-attribute

covariance: Tensor

fallback_reason instance-attribute

fallback_reason: str | None

full_covariance instance-attribute

full_covariance: Tensor

mean instance-attribute

mean: Tensor

name instance-attribute

name: str

trusted instance-attribute

trusted: Tensor

ResidualLadderPrediction dataclass

ResidualLadderPrediction(
    mean: Tensor,
    covariance: Tensor,
    full_covariance: Tensor,
    components: tuple[ResidualComponentResult, ...],
)

components instance-attribute

components: tuple[ResidualComponentResult, ...]

covariance instance-attribute

covariance: Tensor

full_covariance instance-attribute

full_covariance: Tensor

mean instance-attribute

mean: Tensor

ResidualModeDesign dataclass

ResidualModeDesign(
    stable: Tensor,
    drift: Tensor,
    local: Tensor,
    stable_names: tuple[str, ...] = (),
    drift_names: tuple[str, ...] = (),
    local_names: tuple[str, ...] = (),
)

count property

count: int

drift instance-attribute

drift: Tensor

drift_names class-attribute instance-attribute

drift_names: tuple[str, ...] = ()

local instance-attribute

local: Tensor

local_names class-attribute instance-attribute

local_names: tuple[str, ...] = ()

matrix property

matrix: Tensor

stable instance-attribute

stable: Tensor

stable_names class-attribute instance-attribute

stable_names: tuple[str, ...] = ()

widths property

widths: tuple[int, int, int]

__post_init__

__post_init__() -> None

component_slice

component_slice(component: ResidualComponent) -> slice

ResidualSupport dataclass

ResidualSupport(
    lower: Tensor,
    upper: Tensor,
    max_inducing_distance: float,
)

lower instance-attribute

lower: Tensor

max_inducing_distance instance-attribute

max_inducing_distance: float

upper instance-attribute

upper: Tensor

__post_init__

__post_init__() -> None

contains

contains(
    features: Tensor, inducing: Tensor, length_scale: Tensor
) -> Tensor

SparseGPResidual dataclass

SparseGPResidual(
    inducing_features: Tensor,
    length_scale: Tensor,
    amplitude: Tensor,
    output_covariance: Tensor,
    posterior_mean: Tensor,
    posterior_covariance: Tensor,
    inducing_covariance: Tensor,
    support: ResidualSupport,
    covariance_scale: float = 1.0,
    jitter: float = 1e-08,
)

amplitude instance-attribute

amplitude: Tensor

covariance_scale class-attribute instance-attribute

covariance_scale: float = 1.0

inducing_covariance instance-attribute

inducing_covariance: Tensor

inducing_features instance-attribute

inducing_features: Tensor

jitter class-attribute instance-attribute

jitter: float = 1e-08

length_scale instance-attribute

length_scale: Tensor

output_covariance instance-attribute

output_covariance: Tensor

posterior_covariance instance-attribute

posterior_covariance: Tensor

posterior_mean instance-attribute

posterior_mean: Tensor

support instance-attribute

support: ResidualSupport

__post_init__

__post_init__() -> None

calibrate_covariance

calibrate_covariance(
    features: Tensor,
    residual: Tensor,
    *,
    min_scale: float = 1.0,
) -> SparseGPResidual

predict

predict(features: Tensor) -> SparseGPResidualPrediction

SparseGPResidualPrediction dataclass

SparseGPResidualPrediction(
    mean: Tensor, covariance: Tensor, supported: Tensor
)

covariance instance-attribute

covariance: Tensor

mean instance-attribute

mean: Tensor

supported instance-attribute

supported: Tensor

TangentPlaneGauge dataclass

TangentPlaneGauge(
    design: Tensor,
    precision: Tensor,
    rank_rtol: float = 1e-10,
)

Exact weighted projection and null-space coordinates for vector residuals.

count property

count: int

design instance-attribute

design: Tensor

dimension property

dimension: int

precision instance-attribute

precision: Tensor

rank_rtol class-attribute instance-attribute

rank_rtol: float = 1e-10

__post_init__

__post_init__() -> None

_active

_active(active: Tensor | None) -> Tensor

_gram

_gram(active: Tensor) -> Tensor

coordinates

coordinates(
    value: Tensor, active: Tensor | None = None
) -> Tensor

from_coordinates

from_coordinates(
    coordinates: Tensor, active: Tensor | None = None
) -> Tensor

gauge_residual

gauge_residual(value: Tensor) -> Tensor

null_basis

null_basis(active: Tensor | None = None) -> Tensor

project

project(
    value: Tensor, active: Tensor | None = None
) -> Tensor

project_covariance

project_covariance(
    covariance: Tensor, active: Tensor | None = None
) -> Tensor

project_design

project_design(
    value: Tensor, active: Tensor | None = None
) -> Tensor

projection_matrix

projection_matrix(active: Tensor | None = None) -> Tensor

VersionedResidualState dataclass

VersionedResidualState(
    version: int,
    parent_version: int | None,
    feature_version: str,
    gauge_version: str,
    coefficients: BayesianModeState,
    replay_features: Tensor,
    replay_residuals: Tensor,
    replay_covariance: Tensor,
    anchor_features: Tensor,
    anchor_residuals: Tensor,
    anchor_covariance: Tensor,
)

anchor_covariance instance-attribute

anchor_covariance: Tensor

anchor_features instance-attribute

anchor_features: Tensor

anchor_residuals instance-attribute

anchor_residuals: Tensor

coefficients instance-attribute

coefficients: BayesianModeState

feature_version instance-attribute

feature_version: str

gauge_version instance-attribute

gauge_version: str

parent_version instance-attribute

parent_version: int | None

replay_covariance instance-attribute

replay_covariance: Tensor

replay_features instance-attribute

replay_features: Tensor

replay_residuals instance-attribute

replay_residuals: Tensor

version instance-attribute

version: int

__post_init__

__post_init__() -> None

append_replay

append_replay(
    features: Tensor,
    residuals: Tensor,
    covariance: Tensor,
    *,
    capacity: int,
) -> VersionedResidualState

fit_bayesian_modes

fit_bayesian_modes(
    design: ResidualModeDesign,
    residual: Tensor,
    noise_covariance: Tensor,
    *,
    prior_scale: tuple[float, float, float] = (
        0.1,
        0.05,
        0.1,
    ),
    gauge: TangentPlaneGauge | None = None,
) -> BayesianModeState

Fit residual modes with Gaussian priors and correlated noise.

fit_sparse_gp_residual

fit_sparse_gp_residual(
    features: Tensor,
    residual: Tensor,
    noise_covariance: Tensor,
    inducing_features: Tensor,
    *,
    length_scale: Tensor,
    amplitude: float = 1.0,
    output_covariance: Tensor | None = None,
    support: ResidualSupport | None = None,
    gauge: TangentPlaneGauge | None = None,
    jitter: float = 1e-08,
) -> SparseGPResidual

Fit a sparse Gaussian-process model to tangent-plane residuals.

interpretable_residual_modes

interpretable_residual_modes(
    features: AstrometricResidualFeatures,
) -> ResidualModeDesign

Build named affine, color, and detector residual-mode columns.

predict_bayesian_modes

predict_bayesian_modes(
    state: BayesianModeState, design: ResidualModeDesign
) -> BayesianModePrediction

Predict residual-mode means and covariance from a fitted state.

update_bayesian_modes

update_bayesian_modes(
    state: BayesianModeState,
    design: ResidualModeDesign,
    residual: Tensor,
    noise_covariance: Tensor,
    *,
    component: ResidualComponent = "local",
) -> BayesianModeState

Update one residual component while preserving the other components.

Semantics

AxisSpec dataclass

AxisSpec(
    name: str,
    unit: UnitSpec | str = UnitSpec(),
    physical_type: str | None = None,
    domain: DomainSpec | None = None,
    wrap: float | None = None,
)

domain class-attribute instance-attribute

domain: DomainSpec | None = None

name instance-attribute

name: str

physical_type class-attribute instance-attribute

physical_type: str | None = None

unit class-attribute instance-attribute

unit: UnitSpec | str = UnitSpec()

unit_spec property

unit_spec: UnitSpec

The unit as a :class:UnitSpec (strings are normalised on construction).

wrap class-attribute instance-attribute

wrap: float | None = None

__post_init__

__post_init__() -> None

compatible_with

compatible_with(
    other: AxisSpec, *, require_unit: bool = True
) -> bool

from_dict classmethod

from_dict(data: Mapping[str, Any]) -> AxisSpec

to_dict

to_dict() -> dict[str, Any]

DomainSpec dataclass

DomainSpec(
    bounds: tuple[tuple[float | None, float | None], ...],
    closed: tuple[tuple[bool, bool], ...] = (),
)

bounds instance-attribute

bounds: tuple[tuple[float | None, float | None], ...]

closed class-attribute instance-attribute

closed: tuple[tuple[bool, bool], ...] = ()

n_dim property

n_dim: int

__post_init__

__post_init__() -> None

centre

centre(*, dtype: dtype, device: device) -> Tensor

clamp

clamp(value: Tensor) -> Tensor

contains

contains(value: Tensor) -> Tensor

from_dict classmethod

from_dict(data: Mapping[str, Any]) -> DomainSpec

to_dict

to_dict() -> dict[str, Any]

Epoch dataclass

Epoch(value: Any, spec: TimeSpec | None = None)

spec class-attribute instance-attribute

spec: TimeSpec = TimeSpec()

value instance-attribute

value: Tensor

from_state classmethod

from_state(
    metadata: Mapping[str, Any],
    tensors: Mapping[str, Tensor],
) -> Epoch

to

to(spec: TimeSpec) -> Epoch

to_state

to_state() -> tuple[dict[str, Any], dict[str, Tensor]]

FrameSpec dataclass

FrameSpec(
    name: str,
    axes: Sequence[AxisSpec],
    representation: str = "cartesian",
    equinox: Epoch | None = None,
    obstime: Epoch | None = None,
    observer: Sequence[float] | None = None,
    reference_position: str | None = None,
)

axes instance-attribute

axes: tuple[AxisSpec, ...]

equinox class-attribute instance-attribute

equinox: Epoch | None = None

n_dim property

n_dim: int

name instance-attribute

name: str

observer class-attribute instance-attribute

observer: tuple[float, ...] | None = None

obstime class-attribute instance-attribute

obstime: Epoch | None = None

reference_position class-attribute instance-attribute

reference_position: str | None = None

representation class-attribute instance-attribute

representation: str = 'cartesian'

TimeSpec dataclass

TimeSpec(
    format: TimeFormat = "jyear",
    scale: TimeScale = "tcb",
    reference_position: str | None = None,
)

format class-attribute instance-attribute

format: TimeFormat = 'jyear'

reference_position class-attribute instance-attribute

reference_position: str | None = None

scale class-attribute instance-attribute

scale: TimeScale = 'tcb'

__post_init__

__post_init__() -> None

from_dict classmethod

from_dict(data: Mapping[str, Any]) -> TimeSpec

to_dict

to_dict() -> dict[str, Any]

UnitSpec dataclass

UnitSpec(
    symbol: str = "", dimension: UnitDimension | None = None
)

dimension class-attribute instance-attribute

dimension: UnitDimension | None = None

scale property

scale: float

symbol class-attribute instance-attribute

symbol: str = ''

__post_init__

__post_init__() -> None

conversion_factor_to

conversion_factor_to(other: UnitSpec | str) -> float

convert

convert(value: Tensor, other: UnitSpec | str) -> Tensor

from_dict classmethod

from_dict(data: Mapping[str, Any]) -> UnitSpec

to_dict

to_dict() -> dict[str, str]

Spectral axes

air_wavelength_to_vacuum

air_wavelength_to_vacuum(
    wavelength_air: Any, unit: str | None = None
) -> Tensor

Convert standard-air wavelength to vacuum wavelength.

Uses the WCSLIB awavwave refractive index (FITS-WCS Paper III / Edlén form), matching astropy.wcs. Inputs and outputs use unit when provided; FITS default is meters.

convert_spectral

convert_spectral(
    value: Any,
    from_type: str,
    to_type: str,
    *,
    from_unit: str | None = None,
    to_unit: str | None = None,
    rest_frequency: float | Tensor | None = None,
    rest_wavelength: float | Tensor | None = None,
) -> Tensor

Convert between supported spectral coordinate types through frequency.

frequency_to_spectral

frequency_to_spectral(
    frequency: Any,
    spectral_type: str,
    *,
    unit: str | None = None,
    rest_frequency: float | Tensor | None = None,
    rest_wavelength: float | Tensor | None = None,
) -> Tensor

Convert frequency in Hz to a requested spectral coordinate.

rest_frequency_from_header

rest_frequency_from_header(
    header: dict[str, Any],
) -> float | None

Return rest frequency in Hz from FITS RESTFRQ/FREQ or RESTWAV.

spectral_to_frequency

spectral_to_frequency(
    value: Any,
    spectral_type: str,
    *,
    unit: str | None = None,
    rest_frequency: float | Tensor | None = None,
    rest_wavelength: float | Tensor | None = None,
) -> Tensor

Convert a spectral coordinate to frequency in Hz.

vacuum_wavelength_to_air

vacuum_wavelength_to_air(
    wavelength_vacuum: Any, unit: str | None = None
) -> Tensor

Convert vacuum wavelength to standard-air wavelength.

Uses WCSLIB waveawav (four refractive-index iterations).

Tabular WCS axes

from_coupled_tabular module-attribute

from_coupled_tabular = coupled_tabular_wcs_from_fits

from_tabular module-attribute

from_tabular = tabular_axes_from_fits

CoupledTabularLookupWCS dataclass

CoupledTabularLookupWCS(
    pixel_axes: Any,
    world: Any,
    *,
    names: Any = None,
    units: Any = None,
    bounds: TabularBoundsMode = "nan",
)

Coupled multidimensional table lookup with multilinear interpolation.

pixel_axes define the table-grid coordinates for each pixel dimension. world has shape (*grid_shape, world_n_dim). The forward transform is differentiable with respect to query coordinates inside each grid cell. Inverse lookup is unique only when world_n_dim >= pixel_n_dim and the query lies on the interpolated manifold. Underdetermined tables (world_n_dim < pixel_n_dim) return a nearest-seed Gauss–Newton particular solution (minimum-norm step); it is not the unique inverse.

bounds class-attribute instance-attribute

bounds: TabularBoundsMode = 'nan'

grid_shape property

grid_shape: tuple[int, ...]

names instance-attribute

names: tuple[str | None, ...]

pixel_axes instance-attribute

pixel_axes: tuple[Tensor, ...]

pixel_n_dim property

pixel_n_dim: int

units instance-attribute

units: tuple[str | None, ...]

world instance-attribute

world: Tensor

world_n_dim property

world_n_dim: int

pixel_to_world

pixel_to_world(
    pixels: Any, *, bounds: TabularBoundsMode | None = None
) -> Tensor

to

to(
    *,
    device: device | str | None = None,
    dtype: dtype | None = None,
) -> "CoupledTabularLookupWCS"

world_to_pixel

world_to_pixel(
    world: Any,
    *,
    bounds: TabularBoundsMode | None = None,
    max_iter: int = 20,
    tol: float = 1e-10,
) -> Tensor

TabularAxis dataclass

TabularAxis(
    pixel: Any,
    world: Any,
    name: str | None = None,
    unit: str | None = None,
    bounds: TabularBoundsMode = "nan",
)

One-dimensional table-driven coordinate transform.

The forward direction maps pixel/index coordinates to world coordinates by piecewise-linear interpolation. The inverse maps monotonic world coordinates back to pixel/index coordinates with the same interpolation rule.

bounds class-attribute instance-attribute

bounds: TabularBoundsMode = 'nan'

name class-attribute instance-attribute

name: str | None = None

pixel instance-attribute

pixel: Any

unit class-attribute instance-attribute

unit: str | None = None

world instance-attribute

world: Any

world_direction property

world_direction: int

Return 1 for increasing world values, -1 for decreasing.

__post_init__

__post_init__() -> None

pixel_to_world

pixel_to_world(
    pixel: Any, *, bounds: TabularBoundsMode | None = None
) -> Tensor

Interpolate world coordinates from pixel/index coordinates.

to

to(
    *,
    device: device | str | None = None,
    dtype: dtype | None = None,
) -> "TabularAxis"

Return a copy with tables moved to device and/or dtype.

world_to_pixel

world_to_pixel(
    world: Any, *, bounds: TabularBoundsMode | None = None
) -> Tensor

Interpolate pixel/index coordinates from monotonic world coordinates.

TabularLookupWCS dataclass

TabularLookupWCS(axes: Any)

Separable multi-axis table-driven WCS transform.

This is the torch-native execution primitive for independent lookup axes and separable multidimensional FITS -TAB coordinate arrays. Arbitrary coupled table-coordinate interpolation needs a separate multi-axis substrate.

axes instance-attribute

axes: tuple[TabularAxis, ...]

pixel_n_dim property

pixel_n_dim: int

world_n_dim property

world_n_dim: int

pixel_to_world

pixel_to_world(
    pixels: Any, *, bounds: TabularBoundsMode | None = None
) -> Tensor

to

to(
    *,
    device: device | str | None = None,
    dtype: dtype | None = None,
) -> "TabularLookupWCS"

world_to_pixel

world_to_pixel(
    world: Any, *, bounds: TabularBoundsMode | None = None
) -> Tensor

coupled_tabular_wcs_from_fits

coupled_tabular_wcs_from_fits(
    header: Mapping[str, Any], tables: Any, *, key: str = ""
) -> CoupledTabularLookupWCS

Build a forward coupled table-lookup WCS from FITS -TAB metadata.

tabular_axes_from_fits

tabular_axes_from_fits(
    header: Mapping[str, Any], tables: Any, *, key: str = ""
) -> dict[int, TabularAxis]

Build explicit WCS(..., tabular_axes=...) axes from FITS -TAB metadata.

This implements independent one-dimensional FITS table lookup WCS plus the exact separable subset of multidimensional coordinate arrays selected by PVi_3. For each CTYPEi ending in -TAB, PSi_0 selects a table by EXTNAME when tables is a mapping, PSi_1 names the coordinate-array column, and optional PSi_2 names the indexing-vector column. If no indexing vector is present, samples are indexed by 0..N-1. Multidimensional coordinate arrays must be invariant along non-selected dimensions; truly coupled arrays fail explicitly.

Temporal

TemporalWCS

TemporalWCS(header: dict[str, Any])

FITS Temporal WCS implementation (Paper IV).

Supports vectorized transformations between relative time and MJD plus leap-second-aware UTC/TAI/TT/GPS scale conversion.

Main keywords: - MJDREF: Reference MJD - TIMESYS: Time scale (UTC, TT, TAI, TDB, GPS) - TIMEUNIT: 's', 'd', 'a', 'cy' - TREFPOS: TOPOCENTER, GEOCENTER, BARYCENTER, HELIOCENTER, EMBARYCENTER, MOON, CUSTOM, BASECENTER, GALACTIC, LOCALGROUP, and Keplerian planets.

duration_days property

duration_days: float | None

Observation duration in days from MJD-BEG/END, TELAPSE, or EXPOSURE.

ephemeris property

ephemeris: Any

exposure instance-attribute

exposure = _optional_float(header, 'EXPOSURE')

has_observatory_location property

has_observatory_location: bool

midpoint_mjd property

midpoint_mjd: float | None

Observation midpoint MJD when enough metadata is available.

mjd_beg instance-attribute

mjd_beg = _mjd_metadata(header, 'BEG')

mjd_end instance-attribute

mjd_end = _mjd_metadata(header, 'END')

mjd_obs instance-attribute

mjd_obs = _mjd_metadata(header, 'OBS')

mjd_ref instance-attribute

mjd_ref = float(get('MJDREF', 0.0))

observatory_lon_lat_height_deg_m property

observatory_lon_lat_height_deg_m: (
    tuple[float, float, float] | None
)

observatory_xyz_m property

observatory_xyz_m: tuple[float, float, float] | None

obsgeo_lon_lat_height instance-attribute

obsgeo_lon_lat_height: tuple[float, float, float] | None = (
    None
)

obsgeo_xyz_m instance-attribute

obsgeo_xyz_m: tuple[float, float, float] | None = None

plephem instance-attribute

plephem = get('PLEPHEM', None)

reference_direction property

reference_direction: Any

reference_position property

reference_position: str

requires_ephemeris property

requires_ephemeris: bool

telapse instance-attribute

telapse = _optional_float(header, 'TELAPSE')

timeoffs instance-attribute

timeoffs = float(get('TIMEOFFS', 0.0))

timesys instance-attribute

timesys = upper()

timeunit instance-attribute

timeunit = lower()

to_days instance-attribute

to_days = temporal_unit_to_days(timeunit)

trefdir instance-attribute

trefdir = get('TREFDIR', None)

trefpos instance-attribute

trefpos = canonical_time_reference_position(get('TREFPOS'))

_mjd_metadata staticmethod

_mjd_metadata(
    header: dict[str, Any], suffix: str
) -> float | None

_optional_float staticmethod

_optional_float(
    header: dict[str, Any], key: str
) -> float | None

apply_corrections

apply_corrections(
    mjd: Tensor, ra: Tensor, dec: Tensor
) -> Tensor

Apply Roemer light-time to the header TREFPOS.

BARYCENTER/HELIOCENTER use a Keplerian Earth (Sun ≈ SSB). Planetary TREFPOS uses the same JPL approximate Keplerian elements, not DE. EMBARYCENTER and MOON are treated as GEOCENTER (~0.01 s and ~1.3 s). GALACTIC/LOCALGROUP use the barycentric delay (no Galactic motion).

from_mjd

from_mjd(mjd: Tensor) -> Tensor

Convert absolute MJD in the header TIMESYS to relative time.

from_mjd_scale

from_mjd_scale(mjd: Tensor, scale: str) -> Tensor

Convert absolute MJD in scale to relative header time values.

jd_to_mjd staticmethod

jd_to_mjd(jd: float | Tensor) -> float | Tensor

JD to MJD: MJD = JD - 2400000.5

mjd_to_jd staticmethod

mjd_to_jd(mjd: float | Tensor) -> float | Tensor

MJD to JD: JD = MJD + 2400000.5

to_iso8601

to_iso8601(mjd: Tensor) -> str | list[Any]

Convert MJD to ISO-8601 strings (UTC). Note: This is not vectorized as strings are involved, but useful for parity.

to_mjd

to_mjd(time_val: Tensor) -> Tensor

Convert relative time to absolute MJD in the header TIMESYS.

to_mjd_scale

to_mjd_scale(time_val: Tensor, scale: str) -> Tensor

Convert relative time to absolute MJD in another supported scale.

Typing

TabularBoundsMode

typing.Literal['nan', 'clamp']