diff --git a/src/damast/domains/maritime/ais/data_generator.py b/src/damast/domains/maritime/ais/data_generator.py index bffdc31..7be6e3e 100644 --- a/src/damast/domains/maritime/ais/data_generator.py +++ b/src/damast/domains/maritime/ais/data_generator.py @@ -1,7 +1,7 @@ import datetime from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser from logging import INFO, Logger, getLogger -from random import choice, randint, random +from random import choice, randint, random, uniform from typing import Any, List import pandas as pd @@ -92,7 +92,7 @@ def generate_trajectory(min_size: int, max_size: int) -> List[List[Any]]: last_day = datetime.datetime(year=2022, month=12, day=31) start_time = randint(0, int(last_day.timestamp())) - sog_start = random() * SpeedOverGround.min_value / SpeedOverGround.max_value + sog_start = uniform(0,0.5) * SpeedOverGround.max_value cog_start = random() * CourseOverGround.min_value / CourseOverGround.max_value heading_start = cog_start @@ -208,4 +208,4 @@ def generate_anchorage_type_data(self) -> DataFrame: ais_test_data = AISTestData(number_of_trajectories=args.number_of_trajectories) ais_test_data.dataframe.export_hdf5(args.output) - _log.info("Written: {args.output}") + _log.info(f"Written: {args.output}") diff --git a/src/damast/domains/maritime/ais/vessel_types.py b/src/damast/domains/maritime/ais/vessel_types.py index 46c7ba5..662e92d 100644 --- a/src/damast/domains/maritime/ais/vessel_types.py +++ b/src/damast/domains/maritime/ais/vessel_types.py @@ -40,7 +40,7 @@ def get_types(cls) -> List[VesselType]: return klasses @classmethod - def get_types_as_str(cls) -> List[VesselType]: + def get_types_as_str(cls) -> List[str]: return [x.typename() for x in cls.get_types()] @staticmethod @@ -80,7 +80,7 @@ def by_id(cls, *, @classmethod def to_id(cls, *, - klass: Union[str, VesselType] = None) -> int: + klass: Optional[Union[str, VesselType]] = None) -> int: """ Get the id for a klass name or class type of VesselType. diff --git a/src/damast/domains/maritime/math/spatial.py b/src/damast/domains/maritime/math/spatial.py index 53c80f9..66838d7 100644 --- a/src/damast/domains/maritime/math/spatial.py +++ b/src/damast/domains/maritime/math/spatial.py @@ -56,7 +56,7 @@ def bearing(lat_1: npt.NDArray[np.float64], def reverse_bearing(lat_1: npt.NDArray[np.float64], lon_1: npt.NDArray[np.float64], distance: npt.NDArray[np.float64], - bearing: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: + bearing: npt.NDArray[np.float64]) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]: """ Compute the position of an object, given its initial position, the initial bearing, and the distance it will travel. @@ -79,7 +79,7 @@ def reverse_bearing(lat_1: npt.NDArray[np.float64], @njit -def decdeg2dms(dd: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: +def decdeg2dms(dd: npt.NDArray[np.float64]) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64], npt.NDArray[np.float64]]: """ Convert decimal degrees (dd) to sexagesimal degrees (degrees, minutes, seconds) @@ -122,7 +122,7 @@ def dms2decdeg(degrees: npt.NDArray[np.float64], sign[np.signbit(degrees)] = -1 return degrees + sign * (minutes / 60 + seconds / 3600) - +@njit def great_circle_distance(lat_1: npt.NDArray[np.float64], lon_1: npt.NDArray[np.float64], lat_2: npt.NDArray[np.float64], @@ -134,7 +134,6 @@ def great_circle_distance(lat_1: npt.NDArray[np.float64], `Haversine formula `_. .. math:: - d = 2 R \\arcsin \\left(\\sqrt{\\sin^2\\left(\\frac{\\phi_1 - \\phi_2}{2} \\right) + \\cos\\phi_1\\cos\\phi_2\\sin^2\\left(\\frac{\\lambda_1 - \\lambda_2}{2} \\right) }\\right) @@ -145,10 +144,17 @@ def great_circle_distance(lat_1: npt.NDArray[np.float64], :param lon_2: A sequence of longitudes (in degrees), :math:`\\lambda_2` :returns: The great circle distance between sets of points """ - lon_1, lat_1, lon_2, lat_2 = map(np.radians, [lon_1, lat_1, lon_2, lat_2]) - return 2 * EARTH_RADIUS * np.arcsin(np.sqrt(np.power(np.sin((lat_1 - lat_2) / 2), 2) - + np.cos(lat_1) * np.cos(lat_2) * np.power(np.sin((lon_1 - lon_2) / 2), - 2))) + # Convert to radians + lon_1 = np.radians(lon_1) + lat_1 = np.radians(lat_1) + lon_2 = np.radians(lon_2) + lat_2 = np.radians(lat_2) + + a = np.sin((lat_1 - lat_2) / 2) ** 2 + b = np.cos(lat_1) * np.cos(lat_2) * np.sin((lon_1 - lon_2) / 2) ** 2 + c = np.clip(a + b, 0.0, 1.0) + + return 2 * EARTH_RADIUS * np.arcsin(np.sqrt(c)) def chord_distance(d: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: diff --git a/src/damast/domains/maritime/math/statistical.py b/src/damast/domains/maritime/math/statistical.py index c3ddff5..aaa14e3 100644 --- a/src/damast/domains/maritime/math/statistical.py +++ b/src/damast/domains/maritime/math/statistical.py @@ -1,7 +1,7 @@ import warnings import numpy as np -import numpy.typing as npt +import pandas as pd __all__ = [ "N_sigma", @@ -9,9 +9,9 @@ ] -def N_sigma_limited(x: npt.NDArray[np.float64], +def N_sigma_limited(x: pd.Series, N: int, - p: float = 0.99) -> npt.NDArray[np.float64]: + p: float = 0.99) -> np.float64: """ Compute and return the N_sigma given a list without considering the :math:`100\\cdot(1-p)\\%` highest values @@ -26,7 +26,7 @@ def N_sigma_limited(x: npt.NDArray[np.float64], return x.loc[x < limit].median() + N * x.loc[x < limit].std() -def N_sigma(x: npt.NDArray[np.float64], N: int) -> npt.NDArray[np.float64]: +def N_sigma(x: pd.Series, N: int) -> np.float64: """ Compute and return the N_sigma given a list :param x: The input array