From 35e2ef8f37893904b0826bd359dcff2183a49f24 Mon Sep 17 00:00:00 2001 From: josidd <joseph.siddons@noc.ac.uk> Date: Thu, 10 Oct 2024 09:55:01 +0100 Subject: [PATCH] refactor(Record)!: Raises error if lat out of bounds, adds option to fix lon to -180, 180 (defaults to True) --- GeoSpatialTools/octtree.py | 26 ++++++++++++++++++++------ GeoSpatialTools/quadtree.py | 27 +++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/GeoSpatialTools/octtree.py b/GeoSpatialTools/octtree.py index c8f6ab3..90fca65 100644 --- a/GeoSpatialTools/octtree.py +++ b/GeoSpatialTools/octtree.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta -from .distance_metrics import haversine +import datetime from .distance_metrics import haversine, destination +from .utils import LatitudeError from math import degrees, sqrt @@ -25,12 +26,14 @@ class SpaceTimeRecord: Horizontal coordinate (longitude). lat : float Vertical coordinate (latitude). - datetime : datetime + datetime : datetime.datetime Datetime of the record. Can also be a numeric value such as pentad. Comparisons between Records with datetime and Records with numeric datetime will fail. uid : str | None Unique Identifier. + fix_lon : bool + Force longitude to -180, 180 **data Additional data passed to the SpaceTimeRecord for use by other functions or classes. @@ -40,11 +43,19 @@ class SpaceTimeRecord: self, lon: float, lat: float, - datetime: datetime, + datetime: datetime.datetime, uid: str | None = None, + fix_lon: bool = True, **data, ) -> None: self.lon = lon + if fix_lon: + # Move lon to -180, 180 + self.lon = ((self.lon + 540) % 360) - 180 + if lat < -90 or lat > 90: + raise LatitudeError( + "Expected latitude value to be between -90 and 90 degrees" + ) self.lat = lat self.datetime = datetime self.uid = uid @@ -53,12 +64,15 @@ class SpaceTimeRecord: return None def __str__(self) -> str: - return f"Record(x = {self.lon}, y = {self.lat}, datetime = {self.datetime}, uid = {self.uid})" + return f"SpaceTimeRecord(x = {self.lon}, y = {self.lat}, datetime = {self.datetime}, uid = {self.uid})" def __eq__(self, other: object) -> bool: + if not isinstance(other, SpaceTimeRecord): + return False + if self.uid and other.uid: + return self.uid == other.uid return ( - isinstance(other, SpaceTimeRecord) - and self.lon == other.lon + self.lon == other.lon and self.lat == other.lat and self.datetime == other.datetime and (not (self.uid or other.uid) or self.uid == other.uid) diff --git a/GeoSpatialTools/quadtree.py b/GeoSpatialTools/quadtree.py index 0dc9420..80f257b 100644 --- a/GeoSpatialTools/quadtree.py +++ b/GeoSpatialTools/quadtree.py @@ -5,6 +5,7 @@ for detecting nearby records for example from datetime import datetime from .distance_metrics import haversine, destination +from .utils import LatitudeError from math import degrees, sqrt @@ -12,6 +13,12 @@ class Record: """ ICOADS Record class + This is a simple instance of an ICOARDS record, it requires position data. + It can optionally include datetime, a UID, and extra data passed as + keyword arguments. + + Equality is checked only on the required fields + UID if it is specified. + Parameters ---------- lon : float @@ -22,6 +29,11 @@ class Record: Datetime of the record uid : str | None Unique Identifier + fix_lon : bool + Force longitude to -180, 180 + **data + Additional data passed to the Record for use by other functions or + classes. """ def __init__( @@ -30,9 +42,17 @@ class Record: lat: float, datetime: datetime | None = None, uid: str | None = None, + fix_lon: bool = True, **data, ) -> None: self.lon = lon + if fix_lon: + # Move lon to -180, 180 + self.lon = ((self.lon + 540) % 360) - 180 + if lat < -90 or lat > 90: + raise LatitudeError( + "Expected latitude value to be between -90 and 90 degrees" + ) self.lat = lat self.datetime = datetime self.uid = uid @@ -44,9 +64,12 @@ class Record: return f"Record(lon = {self.lon}, lat = {self.lat}, datetime = {self.datetime}, uid = {self.uid})" def __eq__(self, other: object) -> bool: + if not isinstance(other, Record): + return False + if self.uid and other.uid: + return self.uid == other.uid return ( - isinstance(other, Record) - and self.lon == other.lon + self.lon == other.lon and self.lat == other.lat and self.datetime == other.datetime and (not (self.uid or other.uid) or self.uid == other.uid) -- GitLab