Source code for hipscat.pixel_math.validators

from __future__ import annotations

from enum import Enum
from typing import List, Tuple

import numpy as np


[docs] class ValidatorsErrors(str, Enum): """Error messages for the coordinate validators"""
[docs] INVALID_DEC = "declination must be in the -90.0 to 90.0 degree range"
[docs] INVALID_RADIUS = "cone radius must be positive"
[docs] INVALID_NUM_VERTICES = "polygon must contain a minimum of 3 vertices"
[docs] DUPLICATE_VERTICES = "polygon has duplicated vertices"
[docs] DEGENERATE_POLYGON = "polygon is degenerate"
[docs] INVALID_RADEC_RANGE = "invalid ra or dec range"
[docs] def validate_radius(radius_arcsec: float): """Validates that a cone search radius is positive Args: radius_arcsec (float): The cone radius, in arcseconds Raises: ValueError: if radius is non-positive """ if radius_arcsec <= 0: raise ValueError(ValidatorsErrors.INVALID_RADIUS.value)
[docs] def validate_declination_values(dec: float | List[float]): """Validates that declination values are in the [-90,90] degree range Args: dec (float | List[float]): The declination values to be validated Raises: ValueError: if declination values are not in the [-90,90] degree range """ dec_values = np.array(dec) lower_bound, upper_bound = -90.0, 90.0 if not np.all((dec_values >= lower_bound) & (dec_values <= upper_bound)): raise ValueError(ValidatorsErrors.INVALID_DEC.value)
[docs] def validate_polygon(vertices: np.ndarray): """Checks if the polygon contain a minimum of three vertices, that they are unique and that the polygon does not fall on a great circle. Args: vertices (np.ndarray): The polygon vertices, in cartesian coordinates Raises: ValueError: exception if the polygon is invalid. """ if len(vertices) < 3: raise ValueError(ValidatorsErrors.INVALID_NUM_VERTICES.value) if len(vertices) != len(np.unique(vertices, axis=0)): raise ValueError(ValidatorsErrors.DUPLICATE_VERTICES.value) if is_polygon_degenerate(vertices): raise ValueError(ValidatorsErrors.DEGENERATE_POLYGON.value)
[docs] def is_polygon_degenerate(vertices: np.ndarray) -> bool: """Checks if all the vertices of the polygon are contained in a same plane. If the plane intersects the center of the sphere, the polygon is degenerate. Args: vertices (np.ndarray): The polygon vertices, in cartesian coordinates Returns: A boolean, which is True if the polygon is degenerate, i.e. if it falls on a great circle, False otherwise. """ # Calculate the normal vector of the plane using three of the vertices normal_vector = np.cross(vertices[1] - vertices[0], vertices[2] - vertices[0]) # Check if the other vertices lie on the same plane for vertex in vertices[3:]: dot_product = np.dot(normal_vector, vertex - vertices[0]) if not np.isclose(dot_product, 0): return False # Check if the plane intersects the sphere's center. If it does, # the polygon is degenerate and therefore, invalid. center_distance = np.dot(normal_vector, vertices[0]) return bool(np.isclose(center_distance, 0))