diff --git a/GeoSpatialTools/distance_metrics.py b/GeoSpatialTools/distance_metrics.py index 9d148c2f3af6369a85cd35de4e048f362356a0eb..339b0fcd9d32dc7e20fe3c5b9eae0e3f41ce5c91 100644 --- a/GeoSpatialTools/distance_metrics.py +++ b/GeoSpatialTools/distance_metrics.py @@ -4,6 +4,7 @@ navigational information to DataFrames. """ from math import acos, asin, atan2, cos, sin, degrees, radians, sqrt +from typing import Tuple def gcd_slc( @@ -124,7 +125,7 @@ def bearing( def destination( lon: float, lat: float, bearing: float, distance: float -) -> tuple[float, float]: +) -> Tuple[float, float]: """ Compute destination of a great circle path. @@ -173,7 +174,7 @@ def midpoint( lat0: float, lon1: float, lat1: float, -) -> tuple[float, float]: +) -> Tuple[float, float]: """ Compute the midpoint of a great circle track diff --git a/GeoSpatialTools/kdtree.py b/GeoSpatialTools/kdtree.py index 7e90068de9c4661ffdab91478381decfcfb59a5e..7da9df63688f8d7c4f7e4c954e302ac89a6a3acb 100644 --- a/GeoSpatialTools/kdtree.py +++ b/GeoSpatialTools/kdtree.py @@ -5,6 +5,7 @@ Useful tool for quickly searching for nearest neighbours. from . import Record from numpy import inf +from typing import List, Optional, Tuple class KDTree: @@ -33,7 +34,7 @@ class KDTree: """ def __init__( - self, points: list[Record], depth: int = 0, max_depth: int = 20 + self, points: List[Record], depth: int = 0, max_depth: int = 20 ) -> None: self.depth = depth n_points = len(points) @@ -110,7 +111,7 @@ class KDTree: return True return False - def query(self, point) -> tuple[list[Record], float]: + def query(self, point) -> Tuple[List[Record], float]: """Find the nearest Record within the KDTree to a query Record""" if point.lon < 0: point2 = Record(point.lon + 360, point.lat, fix_lon=False) @@ -127,9 +128,9 @@ class KDTree: def _query( self, point: Record, - current_best: list[Record] | None = None, + current_best: Optional[List[Record]] = None, best_distance: float = inf, - ) -> tuple[list[Record], float]: + ) -> Tuple[List[Record], float]: if current_best is None: current_best = list() if not self.split: diff --git a/GeoSpatialTools/neighbours.py b/GeoSpatialTools/neighbours.py index a1b165649d71b8cc8fdd75416bd2fd7cceeeb1ab..02143fca57dddaeb8402c0f44984f1825e29f672 100644 --- a/GeoSpatialTools/neighbours.py +++ b/GeoSpatialTools/neighbours.py @@ -2,7 +2,7 @@ from numpy import argmin from bisect import bisect -from typing import TypeVar +from typing import List, TypeVar, Union from datetime import date, datetime from warnings import warn @@ -22,7 +22,7 @@ class SortedError(Exception): pass -def _find_nearest(vals: list[Numeric], test: Numeric) -> int: +def _find_nearest(vals: List[Numeric], test: Numeric) -> int: i = bisect(vals, test) # Position that test would be inserted # Handle edges @@ -36,10 +36,10 @@ def _find_nearest(vals: list[Numeric], test: Numeric) -> int: def find_nearest( - vals: list[Numeric], - test: list[Numeric] | Numeric, + vals: List[Numeric], + test: Union[List[Numeric], Numeric], check_sorted: bool = True, -) -> list[int] | int: +) -> Union[List[int], int]: """ Find the nearest value in a list of values for each test value. diff --git a/GeoSpatialTools/octtree.py b/GeoSpatialTools/octtree.py index e0eac8aa9f8cbc43164c3ac45ef921cb2fa71df4..d989bbc9d927b149bc778603e8b399ca72cb67f8 100644 --- a/GeoSpatialTools/octtree.py +++ b/GeoSpatialTools/octtree.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from typing import List, Optional import datetime from .distance_metrics import haversine, destination from .utils import LatitudeError, DateWarning @@ -45,7 +46,7 @@ class SpaceTimeRecord: lon: float, lat: float, datetime: datetime.datetime, - uid: str | None = None, + uid: Optional[str] = None, fix_lon: bool = True, **data, ) -> None: @@ -80,7 +81,7 @@ class SpaceTimeRecord: ) -class SpaceTimeRecords(list[SpaceTimeRecord]): +class SpaceTimeRecords(List[SpaceTimeRecord]): """List of SpaceTimeRecords""" @@ -402,7 +403,7 @@ class OctTree: boundary: SpaceTimeRectangle, capacity: int = 5, depth: int = 0, - max_depth: int | None = None, + max_depth: Optional[int] = None, ) -> None: self.boundary = boundary self.capacity = capacity @@ -584,7 +585,7 @@ class OctTree: def query( self, rect: SpaceTimeRectangle, - points: SpaceTimeRecords | None = None, + points: Optional[SpaceTimeRecords] = None, ) -> SpaceTimeRecords: """Get points that fall in a SpaceTimeRectangle""" if not points: @@ -611,7 +612,7 @@ class OctTree: def query_ellipse( self, ellipse: SpaceTimeEllipse, - points: SpaceTimeRecords | None = None, + points: Optional[SpaceTimeRecords] = None, ) -> SpaceTimeRecords: """Get points that fall in an ellipse.""" if not points: @@ -640,7 +641,7 @@ class OctTree: point: SpaceTimeRecord, dist: float, t_dist: datetime.timedelta, - points: SpaceTimeRecords | None = None, + points: Optional[SpaceTimeRecords] = None, ) -> SpaceTimeRecords: """ Get all points that are nearby another point. diff --git a/GeoSpatialTools/quadtree.py b/GeoSpatialTools/quadtree.py index 152b90b5f1c40d8d77e1fd7865ebe0005c1c0385..d24b4befef9cb22659f0ece485b67ee8f8b0e564 100644 --- a/GeoSpatialTools/quadtree.py +++ b/GeoSpatialTools/quadtree.py @@ -4,6 +4,7 @@ for detecting nearby records for example """ from dataclasses import dataclass +from typing import List, Optional from datetime import datetime from .distance_metrics import haversine, destination from .utils import LatitudeError @@ -41,8 +42,8 @@ class Record: self, lon: float, lat: float, - datetime: datetime | None = None, - uid: str | None = None, + datetime: Optional[datetime] = None, + uid: Optional[str] = None, fix_lon: bool = True, **data, ) -> None: @@ -305,13 +306,13 @@ class QuadTree: boundary: Rectangle, capacity: int = 5, depth: int = 0, - max_depth: int | None = None, + max_depth: Optional[int] = None, ) -> None: self.boundary = boundary self.capacity = capacity self.depth = depth self.max_depth = max_depth - self.points: list[Record] = list() + self.points: List[Record] = list() self.divided: bool = False return None @@ -406,8 +407,8 @@ class QuadTree: def query( self, rect: Rectangle, - points: list[Record] | None = None, - ) -> list[Record]: + points: Optional[List[Record]] = None, + ) -> List[Record]: """Get points that fall in a rectangle""" if not points: points = list() @@ -429,8 +430,8 @@ class QuadTree: def query_ellipse( self, ellipse: Ellipse, - points: list[Record] | None = None, - ) -> list[Record]: + points: Optional[List[Record]] = None, + ) -> List[Record]: """Get points that fall in an ellipse.""" if not points: points = list() @@ -453,8 +454,8 @@ class QuadTree: self, point: Record, dist: float, - points: list[Record] | None = None, - ) -> list[Record]: + points: Optional[List[Record]] = None, + ) -> List[Record]: """Get all points that are nearby another point""" if not points: points = list() diff --git a/README.md b/README.md index 2e3f06df47d8e4425cbc8e8d1b64b7960b281fd8..20d6a9c940c27c508b851d4891db322c25235925 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ Python module containing useful functions and classes for Spatial Analysis. -Tested on Python versions 3.11, 3.12, and 3.13. Not expected to work with Python 3.9 or below due -to usage of type annotations. +Tested on Python versions 3.9 to 3.13. ## Installation diff --git a/pyproject.toml b/pyproject.toml index fc55ddc101d8761d350e550cb6d6ce002417e069..210f5c5949fabce2db082b41e60d65fb37a32ef7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ version = "0.6.0" dependencies = [ "numpy", ] -requires-python = ">=3.11" +requires-python = ">=3.9" authors = [ {name = "Joseph Siddons", email = "josidd@noc.ac.uk"}, {name = "Richard Cornes", email = "rcornes@noc.ac.uk"},