From 6a5d488fb4ea8edfb58074e43474c28b2d0b3f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20BRIOL?= Date: Mon, 26 Feb 2024 18:03:14 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A8=20Update=20type=20hints=20and=20im?= =?UTF-8?q?port=20statements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/ex_geodetic.py | 12 +- setup.py | 20 +- src/pyinterp/_geohash.py | 10 +- src/pyinterp/backends/xarray.py | 38 +- src/pyinterp/binning.py | 39 +- src/pyinterp/cf.py | 4 +- src/pyinterp/core/__init__.pyi | 750 +++++++++--------- src/pyinterp/core/array.pyi | 31 + src/pyinterp/core/fill.pyi | 51 +- src/pyinterp/core/geodetic.pyi | 165 ++-- src/pyinterp/core/geohash/__init__.pyi | 31 +- src/pyinterp/core/geohash/int64.pyi | 21 +- src/pyinterp/fill.py | 19 +- src/pyinterp/geodetic/__init__.py | 40 +- src/pyinterp/grid.py | 18 +- src/pyinterp/histogram2d.py | 22 +- src/pyinterp/interface.py | 12 +- src/pyinterp/interpolator/bicubic.py | 8 +- src/pyinterp/orbit.py | 171 ++-- src/pyinterp/period.py | 30 +- src/pyinterp/rtree.py | 44 +- .../statistics/descriptive_descriptive.py | 40 +- .../statistics/streaming_histogram.py | 52 +- src/pyinterp/typing.py | 44 +- 24 files changed, 920 insertions(+), 752 deletions(-) create mode 100644 src/pyinterp/core/array.pyi diff --git a/examples/ex_geodetic.py b/examples/ex_geodetic.py index 608b6329..6c53e483 100644 --- a/examples/ex_geodetic.py +++ b/examples/ex_geodetic.py @@ -78,13 +78,13 @@ # %% # It is possible to do the same calculation on a large number of coordinates # quickly. -lon = numpy.arange(0, 360, 10) -lat = numpy.arange(-90, 90.5, 10) +lon = numpy.arange(0, 360, 10, dtype=numpy.float64) +lat = numpy.arange(-90, 90.5, 10, dtype=numpy.float64) mx, my = numpy.meshgrid(lon, lat) distances = pyinterp.geodetic.coordinate_distances(mx.ravel(), my.ravel(), - mx.ravel() + 1, - my.ravel() + 1, + mx.ravel() + 1.0, + my.ravel() + 1.0, strategy='vincenty', wgs=wgs84, num_threads=1) @@ -402,8 +402,8 @@ [-36, -54.9238], [-36.25, -54.9238]] # %% -lon = numpy.arange(0, 360, 10) -lat = numpy.arange(-80, 90, 10) +lon = numpy.arange(0, 360, 10, dtype=numpy.float64) +lat = numpy.arange(-80, 90, 10, dtype=numpy.float64) mx, my = numpy.meshgrid(lon, lat) # %% diff --git a/setup.py b/setup.py index 70454652..353e361f 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,9 @@ # BSD-style license that can be found in the LICENSE file. """This script is the entry point for building, distributing and installing this module using distutils/setuptools.""" -from typing import List, Optional, Tuple +from __future__ import annotations + +from typing import Any import datetime import os import pathlib @@ -32,7 +34,7 @@ OSX_DEPLOYMENT_TARGET = '10.14' -def compare_setuptools_version(required: Tuple[int, ...]) -> bool: +def compare_setuptools_version(required: tuple[int, ...]) -> bool: """Compare the version of setuptools with the required version.""" current = tuple(map(int, setuptools.__version__.split('.')[:2])) return current >= required @@ -108,7 +110,8 @@ def revision() -> str: return match.group(1) raise AssertionError() - stdout = execute('git describe --tags --dirty --long --always').strip() + stdout: Any = execute( + 'git describe --tags --dirty --long --always').strip() pattern = re.compile(r'([\w\d\.]+)-(\d+)-g([\w\d]+)(?:-(dirty))?') match = pattern.search(stdout) if match is None: @@ -248,13 +251,13 @@ def run(self) -> None: self.build_cmake(ext) super().run() - def boost(self) -> Optional[List[str]]: + def boost(self) -> list[str] | None: """Get the default boost path in Anaconda's environment.""" # Do not search system for Boost & disable the search for boost-cmake boost_option = '-DBoost_NO_SYSTEM_PATHS=TRUE ' \ '-DBoost_NO_BOOST_CMAKE=TRUE' - boost_root = sys.prefix - if pathlib.Path(boost_root, 'include', 'boost').exists(): + boost_root = pathlib.Path(sys.prefix) + if (boost_root / 'include' / 'boost').exists(): return f'{boost_option} -DBoost_ROOT={boost_root}'.split() boost_root = pathlib.Path(sys.prefix, 'Library', 'include') if not boost_root.exists(): @@ -265,7 +268,7 @@ def boost(self) -> Optional[List[str]]: return None return f'{boost_option} -DBoost_INCLUDE_DIR={boost_root}'.split() - def eigen(self) -> Optional[str]: + def eigen(self) -> str | None: """Get the default Eigen3 path in Anaconda's environment.""" eigen_include_dir = pathlib.Path(sys.prefix, 'include', 'eigen3') if eigen_include_dir.exists(): @@ -309,8 +312,9 @@ def is_conda() -> bool: result = True return result - def set_cmake_user_options(self) -> List[str]: + def set_cmake_user_options(self) -> list[str]: """Sets the options defined by the user.""" + cmake_variable: Any is_conda = self.is_conda() result = [] diff --git a/src/pyinterp/_geohash.py b/src/pyinterp/_geohash.py index 2286b0b9..637ee696 100644 --- a/src/pyinterp/_geohash.py +++ b/src/pyinterp/_geohash.py @@ -2,13 +2,11 @@ Geohash encoding and decoding ----------------------------- """ -from typing import Optional, Tuple, Type +from __future__ import annotations -# import numpy import xarray -# from . import geodetic from .core import GeoHash as BaseGeoHash, geohash @@ -44,7 +42,7 @@ class GeoHash(BaseGeoHash): @classmethod def grid(cls, - box: Optional[geodetic.Box] = None, + box: geodetic.Box | None = None, precision: int = 1) -> xarray.Dataset: """Return the GeoHash grid covering the provided box. @@ -85,7 +83,7 @@ def grid(cls, }) @staticmethod - def from_string(code: str, round: bool = False) -> 'GeoHash': + def from_string(code: str, round: bool = False) -> GeoHash: """Create from its string representation. Args: @@ -105,5 +103,5 @@ def __repr__(self) -> str: lon, lat, precision = super().reduce() return f'{self.__class__.__name__}({lon}, {lat}, {precision})' - def __reduce__(self) -> Tuple[Type, Tuple[float, float, int]]: + def __reduce__(self) -> tuple[type, tuple[float, float, int]]: return (self.__class__, super().reduce()) diff --git a/src/pyinterp/backends/xarray.py b/src/pyinterp/backends/xarray.py index f1220212..f9a44022 100644 --- a/src/pyinterp/backends/xarray.py +++ b/src/pyinterp/backends/xarray.py @@ -8,7 +8,9 @@ Build interpolation objects from xarray.DataArray instances """ -from typing import Dict, Hashable, Optional, Tuple, Union +from __future__ import annotations + +from typing import Hashable import pickle import numpy @@ -29,7 +31,7 @@ class AxisIdentifier: def __init__(self, data_array: xr.DataArray): self.data_array = data_array - def _axis(self, units: cf.AxisUnit) -> Optional[str]: + def _axis(self, units: cf.AxisUnit) -> str | None: """Returns the name of the dimension that defines an axis. Args: @@ -40,10 +42,10 @@ def _axis(self, units: cf.AxisUnit) -> Optional[str]: """ for name, coord in self.data_array.coords.items(): if hasattr(coord, 'units') and coord.units in units: - return name + return name # type: ignore return None - def longitude(self) -> Optional[str]: + def longitude(self) -> str | None: """Returns the name of the dimension that defines a longitude axis. Returns: @@ -51,7 +53,7 @@ def longitude(self) -> Optional[str]: """ return self._axis(cf.AxisLongitudeUnit()) - def latitude(self) -> Optional[str]: + def latitude(self) -> str | None: """Returns the name of the dimension that defines a latitude axis. Returns: @@ -62,7 +64,7 @@ def latitude(self) -> Optional[str]: def _dims_from_data_array(data_array: xr.DataArray, geodetic: bool, - ndims: Optional[int] = 2) -> Tuple[str, str]: + ndims: int | None = 2) -> tuple[str, str]: """Gets the name of the dimensions that define the grid axes. the longitudes and latitudes of the data array. @@ -88,7 +90,7 @@ def _dims_from_data_array(data_array: xr.DataArray, f'{ndims}, found {size}.') if not geodetic: - return tuple(data_array.coords)[:2] + return tuple(data_array.coords)[:2] # type: ignore ident = AxisIdentifier(data_array) lon = ident.longitude() @@ -102,9 +104,9 @@ def _dims_from_data_array(data_array: xr.DataArray, def _coords( coords: dict, - dims: Tuple, - datetime64: Optional[Tuple[Hashable, core.TemporalAxis]] = None, -) -> Tuple: + dims: tuple, + datetime64: tuple[Hashable, core.TemporalAxis] | None = None, +) -> tuple: """Get the list of arguments to provide to the grid interpolation functions. @@ -254,6 +256,7 @@ def __init__(self, self._dims = (x, y, z) # Should the grid manage a time axis? dtype = data_array.coords[z].dtype + self._datetime64: tuple[Hashable, core.TemporalAxis] | None if 'datetime64' in dtype.name or 'timedelta64' in dtype.name: self._datetime64 = z, core.TemporalAxis( data_array.coords[z].values) @@ -449,9 +452,8 @@ def __init__(self, increasing_axes: bool = True, geodetic: bool = True): if len(array.shape) == 2: - self._grid = Grid2D(array, - increasing_axes=increasing_axes, - geodetic=geodetic) + self._grid: (Grid2D | Grid3D | Grid4D) = Grid2D( + array, increasing_axes=increasing_axes, geodetic=geodetic) self._interp = self._grid.bivariate elif len(array.shape) == 3: self._grid = Grid3D(array, @@ -467,13 +469,13 @@ def __init__(self, raise NotImplementedError( 'Only the 2D, 3D or 4D grids can be interpolated.') - def __getstate__(self) -> Tuple[bytes]: + def __getstate__(self) -> tuple[bytes]: # Walk around a bug with pybind11 and pickle starting with Python 3.9 # Serialize the object here with highest protocol. return (pickle.dumps((self._grid, self._interp), protocol=pickle.HIGHEST_PROTOCOL), ) - def __setstate__(self, state: Tuple[bytes]) -> None: + def __setstate__(self, state: tuple[bytes]) -> None: # Walk around a bug with pybind11 and pickle starting with Python 3.9 # Deserialize the object here with highest protocol. self._grid, self._interp = pickle.loads(state[0]) @@ -488,7 +490,7 @@ def ndim(self) -> int: return self._grid.array.ndim @property - def grid(self) -> Union[Grid2D, Grid3D, Grid4D]: + def grid(self) -> Grid2D | Grid3D | Grid4D: """Gets the instance of handling the regular grid for interpolations. Returns: @@ -497,10 +499,10 @@ def grid(self) -> Union[Grid2D, Grid3D, Grid4D]: return self._grid def __call__(self, - coords: Dict, + coords: dict, method: str = 'bilinear', bounds_error: bool = False, - bicubic_kwargs: Optional[Dict] = None, + bicubic_kwargs: dict | None = None, num_threads: int = 0, **kwargs) -> numpy.ndarray: """Interpolation at coordinates. diff --git a/src/pyinterp/binning.py b/src/pyinterp/binning.py index e859fa93..6ebd3e13 100644 --- a/src/pyinterp/binning.py +++ b/src/pyinterp/binning.py @@ -6,7 +6,9 @@ Data binning ------------ """ -from typing import Optional, Tuple, Union +from __future__ import annotations + +from typing import Union import copy import dask.array.core @@ -14,6 +16,9 @@ from . import core, geodetic +#: The supported data types for the binning 2D +Binning2DTyped = Union[core.Binning2DFloat64, core.Binning2DFloat32] + class Binning2D: """Group a number of more or less continuous values into a smaller number @@ -46,10 +51,10 @@ class Binning2D: def __init__(self, x: core.Axis, y: core.Axis, - wgs: Optional[geodetic.Spheroid] = None, + wgs: geodetic.Spheroid | None = None, dtype: numpy.dtype = numpy.dtype('float64')): if dtype == numpy.dtype('float64'): - self._instance = core.Binning2DFloat64(x, y, wgs) + self._instance: Binning2DTyped = core.Binning2DFloat64(x, y, wgs) elif dtype == numpy.dtype('float32'): self._instance = core.Binning2DFloat32(x, y, wgs) else: @@ -67,7 +72,7 @@ def y(self) -> core.Axis: return self._instance.y @property - def wgs(self) -> Optional[core.geodetic.Spheroid]: + def wgs(self) -> core.geodetic.Spheroid | None: """Gets the geodetic system handled of the grid.""" return self._instance.wgs @@ -84,7 +89,7 @@ def __repr__(self) -> str: result.append(f' y: {self._instance.y}') return '\n'.join(result) - def __add__(self, other: 'Binning2D') -> 'Binning2D': + def __add__(self, other: Binning2D) -> Binning2D: """Overrides the default behavior of the ``+`` operator.""" result = copy.copy(self) if type(result._instance) != type(other._instance): # noqa: E721 @@ -146,9 +151,9 @@ def push(self, self._instance.push(x, y, z, simple) def push_delayed(self, - x: Union[numpy.ndarray, dask.array.core.Array], - y: Union[numpy.ndarray, dask.array.core.Array], - z: Union[numpy.ndarray, dask.array.core.Array], + x: numpy.ndarray | dask.array.core.Array, + y: numpy.ndarray | dask.array.core.Array, + z: numpy.ndarray | dask.array.core.Array, simple: bool = True) -> dask.array.core.Array: """Push new samples into the defined bins from dask array. @@ -239,10 +244,12 @@ class Binning1D: def __init__(self, x: core.Axis, - range: Optional[Tuple[float, float]] = None, + range: tuple[float, float] | None = None, dtype: numpy.dtype = numpy.dtype('float64')): if dtype == numpy.dtype('float64'): - self._instance = core.Binning1DFloat64(x, range) + self._instance: (core.Binning1DFloat64 + | core.Binning1DFloat32) = core.Binning1DFloat64( + x, range) elif dtype == numpy.dtype('float32'): self._instance = core.Binning1DFloat32(x, range) else: @@ -254,7 +261,7 @@ def x(self) -> core.Axis: """Gets the bin centers for the X Axis of the grid.""" return self._instance.x - def range(self) -> Tuple[float, float]: + def range(self) -> tuple[float, float]: """Gets the lower and upper range of the bins.""" return self._instance.range() @@ -272,7 +279,7 @@ def __repr__(self) -> str: result.append(f' {self._instance.range()}') return '\n'.join(result) - def __add__(self, other: 'Binning1D') -> 'Binning1D': + def __add__(self, other: Binning1D) -> Binning1D: """Overrides the default behavior of the ``+`` operator.""" result = copy.copy(self) if type(result._instance) != type(other._instance): # noqa: E721 @@ -284,7 +291,7 @@ def push( self, x: numpy.ndarray, z: numpy.ndarray, - weights: Optional[numpy.ndarray] = None, + weights: numpy.ndarray | None = None, ) -> None: """Push new samples into the defined bins. @@ -301,9 +308,9 @@ def push( def push_delayed( self, - x: Union[numpy.ndarray, dask.array.core.Array], - z: Union[numpy.ndarray, dask.array.core.Array], - weights: Optional[Union[numpy.ndarray, dask.array.core.Array]] = None, + x: numpy.ndarray | dask.array.core.Array, + z: numpy.ndarray | dask.array.core.Array, + weights: numpy.ndarray | dask.array.core.Array | None = None, ) -> dask.array.core.Array: """Push new samples into the defined bins from dask array. diff --git a/src/pyinterp/cf.py b/src/pyinterp/cf.py index 5ccac619..5bb25d0a 100644 --- a/src/pyinterp/cf.py +++ b/src/pyinterp/cf.py @@ -6,14 +6,14 @@ CF (Climate and Forecast) ------------------------- """ -from typing import List +from __future__ import annotations class AxisUnit(list): """Units management for axes.""" @property - def units(self) -> List: + def units(self) -> list: """Get the list of known units. Returns: diff --git a/src/pyinterp/core/__init__.pyi b/src/pyinterp/core/__init__.pyi index 4fece29d..d667f187 100644 --- a/src/pyinterp/core/__init__.pyi +++ b/src/pyinterp/core/__init__.pyi @@ -1,13 +1,46 @@ -from typing import Any, ClassVar, List, Optional, Tuple, overload +from __future__ import annotations + +from typing import ( + Any, + ClassVar, + Iterator, + List, + Literal, + Optional, + Tuple, + overload, +) import numpy +import numpy.typing from . import dateutils, fill, geodetic, geohash +from .array import ( + Array1DBool, + Array1DFloat32, + Array1DFloat64, + Array1DInt64, + Array2DFloat32, + Array2DFloat64, + Array2DInt8, + Array2DUInt8, + Array2DUInt64, + Array3DFloat32, + Array3DFloat64, + Array3DInt8, + Array4DFloat32, + Array4DFloat64, + Array4DInt8, + ArrayFloat32, + ArrayFloat64, + ArrayInt64, + ArrayUInt64, +) class Axis: def __init__(self, - values: numpy.ndarray[numpy.float64], + values: Array1DFloat64, epsilon: float = ..., is_circle: bool = ...) -> None: ... @@ -16,13 +49,11 @@ class Axis: ... def find_index(self, - coordinates: numpy.ndarray[numpy.float64], - bounded: bool = ...) -> numpy.ndarray[numpy.int64]: + coordinates: Array1DFloat64, + bounded: bool = ...) -> Array1DInt64: ... - def find_indexes( - self, coordinates: numpy.ndarray[numpy.float64] - ) -> numpy.ndarray[numpy.int64]: + def find_indexes(self, coordinates: Array1DFloat64) -> Array1DInt64: ... def flip(self, inplace: bool = ...) -> Axis: @@ -49,7 +80,7 @@ class Axis: def __copy__(self) -> Axis: ... - def __eq__(self, other: Axis) -> bool: + def __eq__(self, other: Axis) -> bool: # type: ignore ... @overload @@ -57,19 +88,19 @@ class Axis: ... @overload - def __getitem__(self, indices: slice) -> numpy.ndarray[numpy.float64]: + def __getitem__(self, indices: slice) -> Array1DFloat64: ... def __getstate__(self) -> tuple: ... - def __iter__(self) -> typing.Iterator[float]: + def __iter__(self) -> Iterator[float]: ... def __len__(self) -> int: ... - def __ne__(self, other: Axis) -> bool: + def __ne__(self, other: Axis) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -123,20 +154,18 @@ class AxisBoundary: class AxisInt64: - def __init__(self, values: numpy.ndarray[numpy.int64]) -> None: + def __init__(self, values: Array1DInt64) -> None: ... def back(self) -> int: ... def find_index(self, - coordinates: numpy.ndarray[numpy.int64], - bounded: bool = ...) -> numpy.ndarray[numpy.int64]: + coordinates: Array1DInt64, + bounded: bool = ...) -> Array1DInt64: ... - def find_indexes( - self, coordinates: numpy.ndarray[numpy.int64] - ) -> numpy.ndarray[numpy.int64]: + def find_indexes(self, coordinates: Array1DInt64) -> Array1DInt64: ... def flip(self, inplace: bool = ...) -> AxisInt64: @@ -163,7 +192,7 @@ class AxisInt64: def __copy__(self) -> AxisInt64: ... - def __eq__(self, other: AxisInt64) -> bool: + def __eq__(self, other: AxisInt64) -> bool: # type: ignore[override] ... @overload @@ -171,19 +200,19 @@ class AxisInt64: ... @overload - def __getitem__(self, indices: slice) -> numpy.ndarray[numpy.int64]: + def __getitem__(self, indices: slice) -> Array1DInt64: ... def __getstate__(self) -> tuple: ... - def __iter__(self) -> typing.Iterator[int]: + def __iter__(self) -> Iterator[int]: ... def __len__(self) -> int: ... - def __ne__(self, other: AxisInt64) -> bool: + def __ne__(self, other: AxisInt64) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -221,10 +250,12 @@ class Binning1DFloat32(Binning2DFloat32): range: Optional[Tuple[float, float]] = None) -> None: ... - def push(self, - x: numpy.ndarray[numpy.float32], - z: numpy.ndarray[numpy.float32], - weights: Optional[numpy.ndarray[numpy.float32]] = ...) -> None: + def push( # type: ignore[override] + self, + x: Array1DFloat32, + z: Array1DFloat32, + weights: Array1DFloat32 | None = ..., + ) -> None: ... def range(self) -> Tuple[float, float]: @@ -244,10 +275,12 @@ class Binning1DFloat64(Binning2DFloat64): range: Optional[Tuple[float, float]] = None) -> None: ... - def push(self, - x: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], - weights: Optional[numpy.ndarray[numpy.float64]] = ...) -> None: + def push( # type: ignore[override] + self, + x: Array1DFloat64, + z: Array1DFloat64, + weights: Array1DFloat64 | None = ..., + ) -> None: ... def range(self) -> Tuple[float, float]: @@ -271,38 +304,38 @@ class Binning2DFloat32: def clear(self) -> None: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> Array2DUInt64: ... - def kurtosis(self) -> numpy.ndarray[numpy.float32]: + def kurtosis(self) -> Array2DFloat32: ... - def max(self) -> numpy.ndarray[numpy.float32]: + def max(self) -> Array2DFloat32: ... - def mean(self) -> numpy.ndarray[numpy.float32]: + def mean(self) -> Array2DFloat32: ... - def min(self) -> numpy.ndarray[numpy.float32]: + def min(self) -> Array2DFloat32: ... def push(self, - x: numpy.ndarray[numpy.float32], - y: numpy.ndarray[numpy.float32], - z: numpy.ndarray[numpy.float32], + x: Array1DFloat32, + y: Array1DFloat32, + z: Array1DFloat32, simple: bool = ...) -> None: ... - def skewness(self) -> numpy.ndarray[numpy.float32]: + def skewness(self) -> Array2DFloat32: ... - def sum(self) -> numpy.ndarray[numpy.float32]: + def sum(self) -> Array2DFloat32: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float32]: + def sum_of_weights(self) -> Array2DFloat32: ... - def variance(self, ddof: int = ...) -> numpy.ndarray[numpy.float32]: + def variance(self, ddof: int = ...) -> Array2DFloat32: ... def __copy__(self) -> Binning2DFloat32: @@ -341,38 +374,38 @@ class Binning2DFloat64: def clear(self) -> None: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> Array2DUInt64: ... - def kurtosis(self) -> numpy.ndarray[numpy.float64]: + def kurtosis(self) -> Array2DFloat64: ... - def max(self) -> numpy.ndarray[numpy.float64]: + def max(self) -> Array2DFloat64: ... - def mean(self) -> numpy.ndarray[numpy.float64]: + def mean(self) -> Array2DFloat64: ... - def min(self) -> numpy.ndarray[numpy.float64]: + def min(self) -> Array2DFloat64: ... def push(self, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, simple: bool = ...) -> None: ... - def skewness(self) -> numpy.ndarray[numpy.float64]: + def skewness(self) -> Array2DFloat64: ... - def sum(self) -> numpy.ndarray[numpy.float64]: + def sum(self) -> Array2DFloat64: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float64]: + def sum_of_weights(self) -> Array2DFloat64: ... - def variance(self, ddof: int = ...) -> numpy.ndarray[numpy.float64]: + def variance(self, ddof: int = ...) -> Array2DFloat64: ... def __copy__(self) -> Binning2DFloat64: @@ -461,36 +494,36 @@ class CovarianceFunction: class DescriptiveStatisticsFloat32: def __init__(self, - values: numpy.ndarray[numpy.float32], - weights: Optional[numpy.ndarray[numpy.float32]] = ..., + values: ArrayFloat32, + weights: Optional[ArrayFloat32] = ..., axis: Optional[List[int]] = ...) -> None: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> ArrayInt64: ... - def kurtosis(self) -> numpy.ndarray[numpy.float32]: + def kurtosis(self) -> ArrayFloat32: ... - def max(self) -> numpy.ndarray[numpy.float32]: + def max(self) -> ArrayFloat32: ... - def mean(self) -> numpy.ndarray[numpy.float32]: + def mean(self) -> ArrayFloat32: ... - def min(self) -> numpy.ndarray[numpy.float32]: + def min(self) -> ArrayFloat32: ... - def skewness(self) -> numpy.ndarray[numpy.float32]: + def skewness(self) -> ArrayFloat32: ... - def sum(self) -> numpy.ndarray[numpy.float32]: + def sum(self) -> ArrayFloat32: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float32]: + def sum_of_weights(self) -> ArrayFloat32: ... - def variance(self, ddof: int = ...) -> numpy.ndarray[numpy.float32]: + def variance(self, ddof: int = ...) -> ArrayFloat32: ... def __add__( @@ -516,36 +549,36 @@ class DescriptiveStatisticsFloat32: class DescriptiveStatisticsFloat64: def __init__(self, - values: numpy.ndarray[numpy.float64], - weights: Optional[numpy.ndarray[numpy.float64]] = ..., + values: ArrayFloat64, + weights: Optional[ArrayFloat64] = ..., axis: Optional[List[int]] = ...) -> None: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> ArrayInt64: ... - def kurtosis(self) -> numpy.ndarray[numpy.float64]: + def kurtosis(self) -> ArrayFloat64: ... - def max(self) -> numpy.ndarray[numpy.float64]: + def max(self) -> ArrayFloat64: ... - def mean(self) -> numpy.ndarray[numpy.float64]: + def mean(self) -> ArrayFloat64: ... - def min(self) -> numpy.ndarray[numpy.float64]: + def min(self) -> ArrayFloat64: ... - def skewness(self) -> numpy.ndarray[numpy.float64]: + def skewness(self) -> ArrayFloat64: ... - def sum(self) -> numpy.ndarray[numpy.float64]: + def sum(self) -> ArrayFloat64: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float64]: + def sum_of_weights(self) -> ArrayFloat64: ... - def variance(self, ddof: int = ...) -> numpy.ndarray[numpy.float64]: + def variance(self, ddof: int = ...) -> ArrayFloat64: ... def __add__( @@ -613,8 +646,7 @@ class GeoHash: class Grid2DFloat32: - def __init__(self, x: Axis, y: Axis, - array: numpy.ndarray[numpy.float32]) -> None: + def __init__(self, x: Axis, y: Axis, array: Array2DFloat32) -> None: ... def __getstate__(self) -> tuple: @@ -624,7 +656,7 @@ class Grid2DFloat32: ... @property - def array(self) -> numpy.ndarray[numpy.float32]: + def array(self) -> Array2DFloat32: ... @property @@ -638,8 +670,7 @@ class Grid2DFloat32: class Grid2DFloat64: - def __init__(self, x: Axis, y: Axis, - array: numpy.ndarray[numpy.float64]) -> None: + def __init__(self, x: Axis, y: Axis, array: Array2DFloat64) -> None: ... def __getstate__(self) -> tuple: @@ -649,7 +680,7 @@ class Grid2DFloat64: ... @property - def array(self) -> numpy.ndarray[numpy.float64]: + def array(self) -> Array2DFloat64: ... @property @@ -663,8 +694,9 @@ class Grid2DFloat64: class Grid2DInt8: - def __init__(self, x: Axis, y: Axis, - array: numpy.ndarray[numpy.int8]) -> None: + def __init__( + self, x: Axis, y: Axis, + array: Array2DInt8) -> None: ... def __getstate__(self) -> tuple: @@ -674,7 +706,8 @@ class Grid2DInt8: ... @property - def array(self) -> numpy.ndarray[numpy.int8]: + def array( + self) -> Array2DInt8: ... @property @@ -688,8 +721,9 @@ class Grid2DInt8: class Grid2DUInt8: - def __init__(self, x: Axis, y: Axis, - array: numpy.ndarray[numpy.uint8]) -> None: + def __init__( + self, x: Axis, y: Axis, + array: Array2DUInt8) -> None: ... def __getstate__(self) -> tuple: @@ -699,7 +733,9 @@ class Grid2DUInt8: ... @property - def array(self) -> numpy.ndarray[numpy.uint8]: + def array( + self + ) -> Array2DUInt8: ... @property @@ -714,7 +750,7 @@ class Grid2DUInt8: class Grid3DFloat32: def __init__(self, x: Axis, y: Axis, z: Axis, - array: numpy.ndarray[numpy.float32]) -> None: + array: Array3DFloat32) -> None: ... def __getstate__(self) -> tuple: @@ -724,7 +760,7 @@ class Grid3DFloat32: ... @property - def array(self) -> numpy.ndarray[numpy.float32]: + def array(self) -> Array3DFloat32: ... @property @@ -743,7 +779,7 @@ class Grid3DFloat32: class Grid3DFloat64: def __init__(self, x: Axis, y: Axis, z: Axis, - array: numpy.ndarray[numpy.float64]) -> None: + array: Array3DFloat64) -> None: ... def __getstate__(self) -> tuple: @@ -753,7 +789,7 @@ class Grid3DFloat64: ... @property - def array(self) -> numpy.ndarray[numpy.float64]: + def array(self) -> Array3DFloat64: ... @property @@ -771,8 +807,7 @@ class Grid3DFloat64: class Grid3DInt8: - def __init__(self, x: Axis, y: Axis, z: Axis, - array: numpy.ndarray[numpy.int8]) -> None: + def __init__(self, x: Axis, y: Axis, z: Axis, array: Array3DInt8) -> None: ... def __getstate__(self) -> tuple: @@ -782,7 +817,7 @@ class Grid3DInt8: ... @property - def array(self) -> numpy.ndarray[numpy.int8]: + def array(self) -> Array3DInt8: ... @property @@ -801,7 +836,7 @@ class Grid3DInt8: class Grid4DFloat32: def __init__(self, x: Axis, y: Axis, z: Axis, u: Axis, - array: numpy.ndarray[numpy.float32]) -> None: + array: Array4DFloat32) -> None: ... def __getstate__(self) -> tuple: @@ -811,7 +846,7 @@ class Grid4DFloat32: ... @property - def array(self) -> numpy.ndarray[numpy.float32]: + def array(self) -> Array4DFloat32: ... @property @@ -834,7 +869,7 @@ class Grid4DFloat32: class Grid4DFloat64: def __init__(self, x: Axis, y: Axis, z: Axis, u: Axis, - array: numpy.ndarray[numpy.float64]) -> None: + array: Array4DFloat64) -> None: ... def __getstate__(self) -> tuple: @@ -844,7 +879,7 @@ class Grid4DFloat64: ... @property - def array(self) -> numpy.ndarray[numpy.float64]: + def array(self) -> Array4DFloat64: ... @property @@ -867,7 +902,7 @@ class Grid4DFloat64: class Grid4DInt8: def __init__(self, x: Axis, y: Axis, z: Axis, u: Axis, - array: numpy.ndarray[numpy.int8]) -> None: + array: Array4DInt8) -> None: ... def __getstate__(self) -> tuple: @@ -877,7 +912,7 @@ class Grid4DInt8: ... @property - def array(self) -> numpy.ndarray[numpy.int8]: + def array(self) -> Array4DInt8: ... @property @@ -905,39 +940,38 @@ class Histogram2DFloat32: def clear(self) -> None: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> Array2DUInt64: ... def histograms(self, *args, **kwargs) -> Any: ... - def kurtosis(self) -> numpy.ndarray[numpy.float32]: + def kurtosis(self) -> Array2DFloat32: ... - def max(self) -> numpy.ndarray[numpy.float32]: + def max(self) -> Array2DFloat32: ... - def mean(self) -> numpy.ndarray[numpy.float32]: + def mean(self) -> Array2DFloat32: ... - def min(self) -> numpy.ndarray[numpy.float32]: + def min(self) -> Array2DFloat32: ... - def push(self, x: numpy.ndarray[numpy.float32], - y: numpy.ndarray[numpy.float32], - z: numpy.ndarray[numpy.float32]) -> None: + def push(self, x: Array1DFloat32, y: Array1DFloat32, + z: Array1DFloat32) -> None: ... - def quantile(self, q: float = ...) -> numpy.ndarray[numpy.float32]: + def quantile(self, q: float = ...) -> Array2DFloat32: ... - def skewness(self) -> numpy.ndarray[numpy.float32]: + def skewness(self) -> Array2DFloat32: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float32]: + def sum_of_weights(self) -> Array2DFloat32: ... - def variance(self) -> numpy.ndarray[numpy.float32]: + def variance(self) -> Array2DFloat32: ... def __copy__(self) -> Histogram2DFloat32: @@ -969,39 +1003,38 @@ class Histogram2DFloat64: def clear(self) -> None: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> Array2DUInt64: ... def histograms(self, *args, **kwargs) -> Any: ... - def kurtosis(self) -> numpy.ndarray[numpy.float64]: + def kurtosis(self) -> Array2DFloat64: ... - def max(self) -> numpy.ndarray[numpy.float64]: + def max(self) -> Array2DFloat64: ... - def mean(self) -> numpy.ndarray[numpy.float64]: + def mean(self) -> Array2DFloat64: ... - def min(self) -> numpy.ndarray[numpy.float64]: + def min(self) -> Array2DFloat64: ... - def push(self, x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64]) -> None: + def push(self, x: Array1DFloat64, y: Array1DFloat64, + z: Array1DFloat64) -> None: ... - def quantile(self, q: float = ...) -> numpy.ndarray[numpy.float64]: + def quantile(self, q: float = ...) -> Array2DFloat64: ... - def skewness(self) -> numpy.ndarray[numpy.float64]: + def skewness(self) -> Array2DFloat64: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float64]: + def sum_of_weights(self) -> Array2DFloat64: ... - def variance(self) -> numpy.ndarray[numpy.float64]: + def variance(self) -> Array2DFloat64: ... def __copy__(self) -> Histogram2DFloat64: @@ -1113,7 +1146,7 @@ class Period: def merge(self, merge: Period) -> Period: ... - def __eq__(self, other: Period) -> bool: + def __eq__(self, other: Period) -> bool: # type: ignore[override] ... def __len__(self) -> int: @@ -1122,7 +1155,7 @@ class Period: def __lt__(self, other: Period) -> bool: ... - def __ne__(self, other: Period) -> bool: + def __ne__(self, other: Period) -> bool: # type: ignore[override] ... @property @@ -1134,20 +1167,24 @@ class Period: ... +Array1DPeriod = numpy.ndarray[ + Literal['N'], + numpy.dtype[Period] # type: ignore[type-var] +] + + class PeriodList: - def __init__(self, periods: numpy.ndarray[Period]) -> None: + def __init__(self, periods: Array1DPeriod) -> None: # type: ignore[type-var] ... def are_periods_sorted_and_disjointed(self) -> bool: ... - def belong_to_a_period( - self, dates: numpy.ndarray[numpy.int64]) -> numpy.ndarray[bool]: + def belong_to_a_period(self, dates: Array1DInt64) -> Array1DBool: ... - def cross_a_period( - self, dates: numpy.ndarray[numpy.int64]) -> numpy.ndarray[bool]: + def cross_a_period(self, dates: Array1DInt64) -> Array1DBool: ... def filter(self, min_duration: int) -> PeriodList: @@ -1181,7 +1218,7 @@ class PeriodList: ... @property - def periods(self) -> numpy.ndarray[Period]: + def periods(self) -> Array1DPeriod: ... @@ -1196,12 +1233,11 @@ class RTree3DFloat32: def clear(self) -> None: ... - def insert(self, coordinates: numpy.ndarray[numpy.float32], - values: numpy.ndarray[numpy.float32]) -> None: + def insert(self, coordinates: ArrayFloat32, values: ArrayFloat32) -> None: ... def inverse_distance_weighting(self, - coordinates: numpy.ndarray[numpy.float32], + coordinates: ArrayFloat32, radius: Optional[float] = ..., k: int = ..., p: int = ..., @@ -1209,19 +1245,18 @@ class RTree3DFloat32: num_threads: int = ...) -> tuple: ... - def packing(self, coordinates: numpy.ndarray[numpy.float32], - values: numpy.ndarray[numpy.float32]) -> None: + def packing(self, coordinates: ArrayFloat32, values: ArrayFloat32) -> None: ... def query(self, - coordinates: numpy.ndarray[numpy.float32], + coordinates: ArrayFloat32, k: int = ..., within: bool = ..., num_threads: int = ...) -> tuple: ... def radial_basis_function(self, - coordinates: numpy.ndarray[numpy.float32], + coordinates: ArrayFloat32, radius: Optional[float] = ..., k: int = ..., rbf: RadialBasisFunction = ..., @@ -1232,7 +1267,7 @@ class RTree3DFloat32: ... def universal_kriging(self, - coordinates: numpy.ndarray[numpy.float32], + coordinates: ArrayFloat32, radius: Optional[float] = ..., k: int = ..., covariance: CovarianceFunction = ..., @@ -1243,7 +1278,7 @@ class RTree3DFloat32: ... def value(self, - coordinates: numpy.ndarray[numpy.float32], + coordinates: ArrayFloat32, radius: Optional[float] = ..., k: int = ..., within: bool = ..., @@ -1251,7 +1286,7 @@ class RTree3DFloat32: ... def window_function(self, - coordinates: numpy.ndarray[numpy.float32], + coordinates: ArrayFloat32, radius: Optional[float] = ..., k: int = ..., wf: WindowFunction = ..., @@ -1287,12 +1322,11 @@ class RTree3DFloat64: def clear(self) -> None: ... - def insert(self, coordinates: numpy.ndarray[numpy.float64], - values: numpy.ndarray[numpy.float64]) -> None: + def insert(self, coordinates: ArrayFloat64, values: ArrayFloat64) -> None: ... def inverse_distance_weighting(self, - coordinates: numpy.ndarray[numpy.float64], + coordinates: ArrayFloat64, radius: Optional[float] = ..., k: int = ..., p: int = ..., @@ -1300,19 +1334,18 @@ class RTree3DFloat64: num_threads: int = ...) -> tuple: ... - def packing(self, coordinates: numpy.ndarray[numpy.float64], - values: numpy.ndarray[numpy.float64]) -> None: + def packing(self, coordinates: ArrayFloat64, values: ArrayFloat64) -> None: ... def query(self, - coordinates: numpy.ndarray[numpy.float64], + coordinates: ArrayFloat64, k: int = ..., within: bool = ..., num_threads: int = ...) -> tuple: ... def radial_basis_function(self, - coordinates: numpy.ndarray[numpy.float64], + coordinates: ArrayFloat64, radius: Optional[float] = ..., k: int = ..., rbf: RadialBasisFunction = ..., @@ -1323,7 +1356,7 @@ class RTree3DFloat64: ... def universal_kriging(self, - coordinates: numpy.ndarray[numpy.float64], + coordinates: ArrayFloat64, radius: Optional[float] = ..., k: int = ..., covariance: CovarianceFunction = ..., @@ -1334,7 +1367,7 @@ class RTree3DFloat64: ... def value(self, - coordinates: numpy.ndarray[numpy.float64], + coordinates: ArrayFloat64, radius: Optional[float] = ..., k: int = ..., within: bool = ..., @@ -1342,7 +1375,7 @@ class RTree3DFloat64: ... def window_function(self, - coordinates: numpy.ndarray[numpy.float64], + coordinates: ArrayFloat64, radius: Optional[float] = ..., k: int = ..., wf: WindowFunction = ..., @@ -1413,8 +1446,8 @@ class RadialBasisFunction: class StreamingHistogramFloat32: def __init__(self, - values: numpy.ndarray[numpy.float32], - weights: Optional[numpy.ndarray[numpy.float32]] = ..., + values: ArrayFloat32, + weights: Optional[ArrayFloat32] = ..., axis: Optional[List[int]] = ..., bin_count: Optional[int] = ...) -> None: ... @@ -1422,37 +1455,37 @@ class StreamingHistogramFloat32: def bins(self, *args, **kwargs) -> Any: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> ArrayUInt64: ... - def kurtosis(self) -> numpy.ndarray[numpy.float32]: + def kurtosis(self) -> ArrayFloat32: ... - def max(self) -> numpy.ndarray[numpy.float32]: + def max(self) -> ArrayFloat32: ... - def mean(self) -> numpy.ndarray[numpy.float32]: + def mean(self) -> ArrayFloat32: ... - def min(self) -> numpy.ndarray[numpy.float32]: + def min(self) -> ArrayFloat32: ... - def quantile(self, q: float = ...) -> numpy.ndarray[numpy.float32]: + def quantile(self, q: float = ...) -> ArrayFloat32: ... def resize(self, arg0: int) -> None: ... - def size(self) -> numpy.ndarray[numpy.uint64]: + def size(self) -> ArrayUInt64: ... - def skewness(self) -> numpy.ndarray[numpy.float32]: + def skewness(self) -> ArrayFloat32: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float32]: + def sum_of_weights(self) -> ArrayFloat32: ... - def variance(self) -> numpy.ndarray[numpy.float32]: + def variance(self) -> ArrayFloat32: ... def __add__(self, @@ -1477,8 +1510,8 @@ class StreamingHistogramFloat32: class StreamingHistogramFloat64: def __init__(self, - values: numpy.ndarray[numpy.float64], - weights: Optional[numpy.ndarray[numpy.float64]] = ..., + values: ArrayFloat64, + weights: Optional[ArrayFloat64] = ..., axis: Optional[List[int]] = ..., bin_count: Optional[int] = ...) -> None: ... @@ -1486,37 +1519,37 @@ class StreamingHistogramFloat64: def bins(self, *args, **kwargs) -> Any: ... - def count(self) -> numpy.ndarray[numpy.uint64]: + def count(self) -> ArrayUInt64: ... - def kurtosis(self) -> numpy.ndarray[numpy.float64]: + def kurtosis(self) -> ArrayFloat64: ... - def max(self) -> numpy.ndarray[numpy.float64]: + def max(self) -> ArrayFloat64: ... - def mean(self) -> numpy.ndarray[numpy.float64]: + def mean(self) -> ArrayFloat64: ... - def min(self) -> numpy.ndarray[numpy.float64]: + def min(self) -> ArrayFloat64: ... - def quantile(self, q: float = ...) -> numpy.ndarray[numpy.float64]: + def quantile(self, q: float = ...) -> ArrayFloat64: ... def resize(self, arg0: int) -> None: ... - def size(self) -> numpy.ndarray[numpy.uint64]: + def size(self) -> ArrayUInt64: ... - def skewness(self) -> numpy.ndarray[numpy.float64]: + def skewness(self) -> ArrayFloat64: ... - def sum_of_weights(self) -> numpy.ndarray[numpy.float64]: + def sum_of_weights(self) -> ArrayFloat64: ... - def variance(self) -> numpy.ndarray[numpy.float64]: + def variance(self) -> ArrayFloat64: ... def __add__(self, @@ -1543,28 +1576,27 @@ class TemporalAxis(AxisInt64): def __init__(self, values: numpy.ndarray) -> None: ... - def back(self) -> numpy.ndarray: + def back(self) -> numpy.ndarray: # type: ignore[override] ... - def dtype(self) -> dtype: + def dtype(self) -> numpy.dtype: ... def find_index(self, coordinates: numpy.ndarray, - bounded: bool = ...) -> numpy.ndarray[numpy.int64]: + bounded: bool = ...) -> Array1DInt64: ... - def find_indexes(self, - coordinates: numpy.ndarray) -> numpy.ndarray[numpy.int64]: + def find_indexes(self, coordinates: numpy.ndarray) -> Array1DInt64: ... def flip(self, inplace: bool = ...) -> TemporalAxis: ... - def front(self) -> numpy.ndarray: + def front(self) -> numpy.ndarray: # type: ignore[override] ... - def increment(self) -> numpy.ndarray: + def increment(self) -> numpy.ndarray: # type: ignore[override] ... def is_ascending(self) -> bool: @@ -1573,10 +1605,10 @@ class TemporalAxis(AxisInt64): def is_regular(self) -> bool: ... - def max_value(self) -> numpy.ndarray: + def max_value(self) -> numpy.ndarray: # type: ignore[override] ... - def min_value(self) -> numpy.ndarray: + def min_value(self) -> numpy.ndarray: # type: ignore[override] ... def safe_cast(self, values: numpy.ndarray) -> numpy.ndarray: @@ -1585,27 +1617,27 @@ class TemporalAxis(AxisInt64): def __copy__(self) -> TemporalAxis: ... - def __eq__(self, other: TemporalAxis) -> bool: + def __eq__(self, other: TemporalAxis) -> bool: # type: ignore[override] ... - @overload + @overload # type: ignore[override] def __getitem__(self, index: int) -> numpy.ndarray: ... - @overload + @overload # type: ignore[override] def __getitem__(self, indices: slice) -> numpy.ndarray: ... def __getstate__(self) -> tuple: ... - def __iter__(self) -> typing.Iterator[numpy.ndarray]: + def __iter__(self) -> Iterator[numpy.ndarray]: # type: ignore[override] ... def __len__(self) -> int: ... - def __ne__(self, other: TemporalAxis) -> bool: + def __ne__(self, other: TemporalAxis) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -1633,7 +1665,7 @@ class TemporalBivariateInterpolator3D: class TemporalGrid3DFloat32: def __init__(self, x: Axis, y: Axis, z: AxisInt64, - array: numpy.ndarray[numpy.float32]) -> None: + array: Array3DFloat64) -> None: ... def __getstate__(self) -> tuple: @@ -1643,7 +1675,7 @@ class TemporalGrid3DFloat32: ... @property - def array(self) -> numpy.ndarray[numpy.float32]: + def array(self) -> Array3DFloat64: ... @property @@ -1662,7 +1694,7 @@ class TemporalGrid3DFloat32: class TemporalGrid3DFloat64: def __init__(self, x: Axis, y: Axis, z: AxisInt64, - array: numpy.ndarray[numpy.float64]) -> None: + array: Array3DFloat64) -> None: ... def __getstate__(self) -> tuple: @@ -1672,7 +1704,7 @@ class TemporalGrid3DFloat64: ... @property - def array(self) -> numpy.ndarray[numpy.float64]: + def array(self) -> Array3DFloat64: ... @property @@ -1691,7 +1723,7 @@ class TemporalGrid3DFloat64: class TemporalGrid3DInt8: def __init__(self, x: Axis, y: Axis, z: AxisInt64, - array: numpy.ndarray[numpy.int8]) -> None: + array: Array3DInt8) -> None: ... def __getstate__(self) -> tuple: @@ -1701,7 +1733,7 @@ class TemporalGrid3DInt8: ... @property - def array(self) -> numpy.ndarray[numpy.int8]: + def array(self) -> Array3DInt8: ... @property @@ -1720,7 +1752,7 @@ class TemporalGrid3DInt8: class TemporalGrid4DFloat32: def __init__(self, x: Axis, y: Axis, z: AxisInt64, u: Axis, - array: numpy.ndarray[numpy.float32]) -> None: + array: Array4DFloat32) -> None: ... def __getstate__(self) -> tuple: @@ -1730,7 +1762,7 @@ class TemporalGrid4DFloat32: ... @property - def array(self) -> numpy.ndarray[numpy.float32]: + def array(self) -> Array4DFloat32: ... @property @@ -1753,7 +1785,7 @@ class TemporalGrid4DFloat32: class TemporalGrid4DFloat64: def __init__(self, x: Axis, y: Axis, z: AxisInt64, u: Axis, - array: numpy.ndarray[numpy.float64]) -> None: + array: Array4DFloat64) -> None: ... def __getstate__(self) -> tuple: @@ -1763,7 +1795,7 @@ class TemporalGrid4DFloat64: ... @property - def array(self) -> numpy.ndarray[numpy.float64]: + def array(self) -> Array4DFloat64: ... @property @@ -1786,7 +1818,7 @@ class TemporalGrid4DFloat64: class TemporalGrid4DInt8: def __init__(self, x: Axis, y: Axis, z: AxisInt64, u: Axis, - array: numpy.ndarray[numpy.int8]) -> None: + array: Array4DInt8) -> None: ... def __getstate__(self) -> tuple: @@ -1796,7 +1828,7 @@ class TemporalGrid4DInt8: ... @property - def array(self) -> numpy.ndarray[numpy.int8]: + def array(self) -> Array4DInt8: ... @property @@ -1889,436 +1921,432 @@ class WindowFunction: @overload def bicubic_float32(grid: Grid2DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float32(grid: Grid3DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float32(grid: TemporalGrid3DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float32(grid: Grid4DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float32(grid: TemporalGrid4DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float64(grid: Grid2DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float64(grid: Grid3DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float64(grid: TemporalGrid3DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float64(grid: Grid4DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def bicubic_float64(grid: TemporalGrid4DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... def bivariate_float32(grid: Grid2DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, interpolator: BivariateInterpolator2D, bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... def bivariate_float64(grid: Grid2DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, interpolator: BivariateInterpolator2D, bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... def bivariate_int8(grid: Grid2DInt8, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, interpolator: BivariateInterpolator2D, bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... def bivariate_uint8(grid: Grid2DUInt8, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, interpolator: BivariateInterpolator2D, bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... def interpolate1d(x: Axis, - y: numpy.ndarray[numpy.float64[m, 1]], - xi: numpy.ndarray[numpy.float64[m, 1]], + y: Array1DFloat64, + xi: Array1DFloat64, half_window_size: int = ..., bounds_error: bool = ..., - kind: str = ...) -> numpy.ndarray[numpy.float64[m, 1]]: + kind: str = ...) -> Array1DFloat64: ... @overload -def quadrivariate_float32( - grid: TemporalGrid4DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], - u: numpy.ndarray[numpy.float64], - interpolator: TemporalBivariateInterpolator3D, - z_method: Optional[str] = ..., - u_method: Optional[str] = ..., - bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: +def quadrivariate_float32(grid: TemporalGrid4DFloat32, + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, + u: Array1DFloat64, + interpolator: TemporalBivariateInterpolator3D, + z_method: Optional[str] = ..., + u_method: Optional[str] = ..., + bounds_error: bool = ..., + num_threads: int = ...) -> Array1DFloat64: ... @overload -def quadrivariate_float32( - grid: Grid4DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], - u: numpy.ndarray[numpy.float64], - interpolator: BivariateInterpolator3D, - z_method: Optional[str] = ..., - u_method: Optional[str] = ..., - bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: +def quadrivariate_float32(grid: Grid4DFloat32, + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, + u: Array1DFloat64, + interpolator: BivariateInterpolator3D, + z_method: Optional[str] = ..., + u_method: Optional[str] = ..., + bounds_error: bool = ..., + num_threads: int = ...) -> Array1DFloat64: ... @overload -def quadrivariate_float64( - grid: TemporalGrid4DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], - u: numpy.ndarray[numpy.float64], - interpolator: TemporalBivariateInterpolator3D, - z_method: Optional[str] = ..., - u_method: Optional[str] = ..., - bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: +def quadrivariate_float64(grid: TemporalGrid4DFloat64, + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, + u: Array1DFloat64, + interpolator: TemporalBivariateInterpolator3D, + z_method: Optional[str] = ..., + u_method: Optional[str] = ..., + bounds_error: bool = ..., + num_threads: int = ...) -> Array1DFloat64: ... @overload -def quadrivariate_float64( - grid: Grid4DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], - u: numpy.ndarray[numpy.float64], - interpolator: BivariateInterpolator3D, - z_method: Optional[str] = ..., - u_method: Optional[str] = ..., - bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: +def quadrivariate_float64(grid: Grid4DFloat64, + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, + u: Array1DFloat64, + interpolator: BivariateInterpolator3D, + z_method: Optional[str] = ..., + u_method: Optional[str] = ..., + bounds_error: bool = ..., + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float32(grid: Grid2DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float32(grid: Grid3DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float32(grid: TemporalGrid3DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float32(grid: Grid4DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float32(grid: TemporalGrid4DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float64(grid: Grid2DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float64(grid: Grid3DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float64(grid: TemporalGrid3DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float64(grid: Grid4DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def spline_float64(grid: TemporalGrid4DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], - u: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, + u: Array1DFloat64, nx: int = ..., ny: int = ..., fitting_model: str = ..., boundary: str = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def trivariate_float32(grid: Grid3DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, interpolator: BivariateInterpolator3D, z_method: Optional[str] = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def trivariate_float32(grid: TemporalGrid3DFloat32, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, interpolator: TemporalBivariateInterpolator3D, z_method: Optional[str] = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def trivariate_float64(grid: Grid3DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, interpolator: BivariateInterpolator3D, z_method: Optional[str] = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... @overload def trivariate_float64(grid: TemporalGrid3DFloat64, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.int64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DInt64, interpolator: TemporalBivariateInterpolator3D, z_method: Optional[str] = ..., bounds_error: bool = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array1DFloat64: ... diff --git a/src/pyinterp/core/array.pyi b/src/pyinterp/core/array.pyi new file mode 100644 index 00000000..f4a41841 --- /dev/null +++ b/src/pyinterp/core/array.pyi @@ -0,0 +1,31 @@ +from typing import Any, Literal + +import numpy + +_1D = Literal['N'] +_2D = Literal['N', 'M'] +_3D = Literal['N', 'M', 'O'] +_4D = Literal['N', 'M', 'O', 'P'] + +Array1DBool = numpy.ndarray[_1D, numpy.dtype[numpy.bool_]] +Array1DFloat32 = numpy.ndarray[_1D, numpy.dtype[numpy.float32]] +Array1DFloat64 = numpy.ndarray[_1D, numpy.dtype[numpy.float64]] +Array1DInt64 = numpy.ndarray[_1D, numpy.dtype[numpy.int64]] +Array1DStr = numpy.ndarray[_1D, numpy.dtype[numpy.str_]] +Array1DUInt64 = numpy.ndarray[_1D, numpy.dtype[numpy.uint64]] +Array2DFloat32 = numpy.ndarray[_2D, numpy.dtype[numpy.float32]] +Array2DFloat64 = numpy.ndarray[_2D, numpy.dtype[numpy.float64]] +Array2DInt64 = numpy.ndarray[_2D, numpy.dtype[numpy.int64]] +Array2DInt8 = numpy.ndarray[_2D, numpy.dtype[numpy.int8]] +Array2DUInt64 = numpy.ndarray[_2D, numpy.dtype[numpy.uint64]] +Array2DUInt8 = numpy.ndarray[_2D, numpy.dtype[numpy.uint8]] +Array3DFloat32 = numpy.ndarray[_3D, numpy.dtype[numpy.float32]] +Array3DFloat64 = numpy.ndarray[_3D, numpy.dtype[numpy.float64]] +Array3DInt8 = numpy.ndarray[_3D, numpy.dtype[numpy.int8]] +Array4DFloat32 = numpy.ndarray[_4D, numpy.dtype[numpy.float32]] +Array4DFloat64 = numpy.ndarray[_4D, numpy.dtype[numpy.float64]] +Array4DInt8 = numpy.ndarray[_4D, numpy.dtype[numpy.int8]] +ArrayFloat32 = numpy.ndarray[Any, numpy.dtype[numpy.float32]] +ArrayFloat64 = numpy.ndarray[Any, numpy.dtype[numpy.float64]] +ArrayInt64 = numpy.ndarray[Any, numpy.dtype[numpy.int64]] +ArrayUInt64 = numpy.ndarray[Any, numpy.dtype[numpy.uint64]] diff --git a/src/pyinterp/core/fill.pyi b/src/pyinterp/core/fill.pyi index 9504d797..2073563e 100644 --- a/src/pyinterp/core/fill.pyi +++ b/src/pyinterp/core/fill.pyi @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import ClassVar, Tuple, overload import numpy @@ -14,6 +16,17 @@ from . import ( TemporalGrid4DFloat32, TemporalGrid4DFloat64, ) +from .array import ( + Array1DFloat32, + Array1DFloat64, + Array1DInt64, + Array2DFloat32, + Array2DFloat64, + Array3DFloat32, + Array3DFloat64, + Array4DFloat32, + Array4DFloat64, +) class FirstGuess: __members__: ClassVar[dict] = ... # read-only @@ -94,7 +107,7 @@ class ValueType: ... -def gauss_seidel_float32(grid: numpy.ndarray[numpy.float32], +def gauss_seidel_float32(grid: Array2DFloat32, first_guess: FirstGuess = ..., is_circle: bool = ..., max_iterations: int = ..., @@ -104,7 +117,7 @@ def gauss_seidel_float32(grid: numpy.ndarray[numpy.float32], ... -def gauss_seidel_float64(grid: numpy.ndarray[numpy.float64], +def gauss_seidel_float64(grid: Array2DFloat64, first_guess: FirstGuess = ..., is_circle: bool = ..., max_iterations: int = ..., @@ -119,7 +132,7 @@ def loess_float32(grid: Grid2DFloat32, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float32]: + num_threads: int = ...) -> Array2DFloat32: ... @@ -128,7 +141,7 @@ def loess_float32(grid: Grid3DFloat32, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float32]: + num_threads: int = ...) -> Array3DFloat32: ... @@ -137,7 +150,7 @@ def loess_float32(grid: TemporalGrid3DFloat32, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float32]: + num_threads: int = ...) -> Array3DFloat32: ... @@ -146,7 +159,7 @@ def loess_float32(grid: Grid4DFloat32, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float32]: + num_threads: int = ...) -> Array4DFloat32: ... @@ -155,7 +168,7 @@ def loess_float32(grid: TemporalGrid4DFloat32, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float32]: + num_threads: int = ...) -> Array4DFloat32: ... @@ -164,7 +177,7 @@ def loess_float64(grid: Grid2DFloat64, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array2DFloat64: ... @@ -173,7 +186,7 @@ def loess_float64(grid: Grid3DFloat64, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array3DFloat64: ... @@ -182,7 +195,7 @@ def loess_float64(grid: TemporalGrid3DFloat64, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array3DFloat64: ... @@ -191,7 +204,7 @@ def loess_float64(grid: Grid4DFloat64, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array4DFloat64: ... @@ -200,29 +213,25 @@ def loess_float64(grid: TemporalGrid4DFloat64, nx: int = ..., ny: int = ..., value_type: ValueType = ..., - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: + num_threads: int = ...) -> Array4DFloat64: ... -def matrix_float32(x: numpy.ndarray[numpy.float32], - fill_value: float = ...) -> None: +def matrix_float32(x: Array2DFloat32, fill_value: float = ...) -> None: ... -def matrix_float64(x: numpy.ndarray[numpy.float64], - fill_value: float = ...) -> None: +def matrix_float64(x: Array2DFloat64, fill_value: float = ...) -> None: ... -def vector_float32(x: numpy.ndarray[numpy.float32], - fill_value: float = ...) -> None: +def vector_float32(x: Array1DFloat32, fill_value: float = ...) -> None: ... -def vector_float64(x: numpy.ndarray[numpy.float64], - fill_value: float = ...) -> None: +def vector_float64(x: Array1DFloat64, fill_value: float = ...) -> None: ... -def vector_int64(x: numpy.ndarray[numpy.int64], fill_value: int) -> None: +def vector_int64(x: Array1DInt64, fill_value: int) -> None: ... diff --git a/src/pyinterp/core/geodetic.pyi b/src/pyinterp/core/geodetic.pyi index d8402509..3c5cd194 100644 --- a/src/pyinterp/core/geodetic.pyi +++ b/src/pyinterp/core/geodetic.pyi @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import ( Any, ClassVar, @@ -12,9 +14,10 @@ from typing import ( import numpy from .. import core +from .array import Array1DBool, Array1DFloat64, Array2DFloat64 class Box: - __hash__: ClassVar[None] = ... + __hash__: ClassVar[None] = ... # type: ignore[assignment] max_corner: Point min_corner: Point @@ -41,9 +44,9 @@ class Box: @overload def covered_by(self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - num_threads: int = ...) -> numpy.ndarray[bool]: + lon: Array1DFloat64, + lat: Array1DFloat64, + num_threads: int = ...) -> Array1DBool: ... @overload @@ -75,13 +78,13 @@ class Box: def __copy__(self) -> Box: ... - def __eq__(self, other: Box) -> bool: + def __eq__(self, other: Box) -> bool: # type: ignore[override] ... def __getstate__(self) -> tuple: ... - def __ne__(self, other: Box) -> bool: + def __ne__(self, other: Box) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -94,24 +97,24 @@ class Coordinates: ... def ecef_to_lla(self, - x: numpy.ndarray[numpy.float64], - y: numpy.ndarray[numpy.float64], - z: numpy.ndarray[numpy.float64], + x: Array1DFloat64, + y: Array1DFloat64, + z: Array1DFloat64, num_threads: int = ...) -> tuple: ... def lla_to_ecef(self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - alt: numpy.ndarray[numpy.float64], + lon: Array1DFloat64, + lat: Array1DFloat64, + alt: Array1DFloat64, num_threads: int = ...) -> tuple: ... def transform(self, target: Coordinates, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - alt: numpy.ndarray[numpy.float64], + lon: Array1DFloat64, + lat: Array1DFloat64, + alt: Array1DFloat64, num_threads: int = ...) -> tuple: ... @@ -164,7 +167,7 @@ class Crossover: class LineString: - __hash__: ClassVar[None] = ... + __hash__: ClassVar[None] = ... # type: ignore[assignment] @overload def __init__(self) -> None: @@ -175,8 +178,7 @@ class LineString: ... @overload - def __init__(self, lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64]) -> None: + def __init__(self, lon: Array1DFloat64, lat: Array1DFloat64) -> None: ... def append(self, point: Point) -> None: @@ -191,17 +193,16 @@ class LineString: @overload def closest_point( self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], + lon: Array1DFloat64, + lat: Array1DFloat64, wgs: Optional[Spheroid] = None, num_threads: int = 0, - ) -> Tuple[numpy.ndarray[numpy.float64], numpy.ndarray[numpy.float64]]: + ) -> Tuple[Array1DFloat64, Array1DFloat64]: ... - def curvilinear_distance( - self, - strategy: str = 'thomas', - wgs: Optional[Spheroid] = None) -> numpy.ndarray[numpy.float64]: + def curvilinear_distance(self, + strategy: str = 'thomas', + wgs: Optional[Spheroid] = None) -> Array1DFloat64: ... @staticmethod @@ -238,7 +239,7 @@ class LineString: def __copy__(self) -> LineString: ... - def __eq__(self, other: LineString) -> bool: + def __eq__(self, other: LineString) -> bool: # type: ignore[override] ... def __getitem__(self, index: int) -> Point: @@ -253,7 +254,7 @@ class LineString: def __len__(self) -> int: ... - def __ne__(self, other: LineString) -> bool: + def __ne__(self, other: LineString) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -261,7 +262,7 @@ class LineString: class MultiPolygon: - __hash__: ClassVar[None] = ... + __hash__: ClassVar[None] = ... # type: ignore[assignment] @overload def __init__(self) -> None: @@ -283,9 +284,9 @@ class MultiPolygon: @overload def covered_by(self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - num_threads: int = ...) -> numpy.ndarray[bool]: + lon: Array1DFloat64, + lat: Array1DFloat64, + num_threads: int = ...) -> Array1DBool: ... @overload @@ -361,7 +362,7 @@ class MultiPolygon: def __copy__(self) -> MultiPolygon: ... - def __eq__(self, other: MultiPolygon) -> bool: + def __eq__(self, other: MultiPolygon) -> bool: # type: ignore[override] ... def __getitem__(self, index: int) -> Polygon: @@ -379,7 +380,7 @@ class MultiPolygon: def __len__(self) -> int: ... - def __ne__(self, other: MultiPolygon) -> bool: + def __ne__(self, other: MultiPolygon) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -387,7 +388,7 @@ class MultiPolygon: class Point: - __hash__: ClassVar[None] = ... + __hash__: ClassVar[None] = ... # type: ignore[assignment] lat: float lon: float @@ -421,13 +422,13 @@ class Point: def __copy__(self) -> Point: ... - def __eq__(self, other: Point) -> bool: + def __eq__(self, other: Point) -> bool: # type: ignore[override] ... def __getstate__(self) -> tuple: ... - def __ne__(self, other: Point) -> bool: + def __ne__(self, other: Point) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -435,7 +436,7 @@ class Point: class Polygon: - __hash__: ClassVar[None] = ... + __hash__: ClassVar[None] = ... # type: ignore[assignment] def __init__(self, outer: list, inners: Optional[list] = ...) -> None: ... @@ -449,9 +450,9 @@ class Polygon: @overload def covered_by(self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - num_threads: int = ...) -> numpy.ndarray[bool]: + lon: Array1DFloat64, + lat: Array1DFloat64, + num_threads: int = ...) -> Array1DBool: ... def difference(self, other: Polygon) -> MultiPolygon: @@ -511,13 +512,13 @@ class Polygon: def __copy__(self) -> Polygon: ... - def __eq__(self, other: Polygon) -> bool: + def __eq__(self, other: Polygon) -> bool: # type: ignore[override] ... def __getstate__(self) -> tuple: ... - def __ne__(self, other: Polygon) -> bool: + def __ne__(self, other: Polygon) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -540,14 +541,13 @@ class RTree: def clear(self) -> None: ... - def insert(self, lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - values: numpy.ndarray[numpy.float64]) -> None: + def insert(self, lon: Array1DFloat64, lat: Array1DFloat64, + values: Array1DFloat64) -> None: ... def inverse_distance_weighting(self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], + lon: Array1DFloat64, + lat: Array1DFloat64, radius: Optional[float] = ..., k: int = ..., p: int = ..., @@ -555,22 +555,21 @@ class RTree: num_threads: int = ...) -> tuple: ... - def packing(self, lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - values: numpy.ndarray[numpy.float64]) -> None: + def packing(self, lon: Array1DFloat64, lat: Array1DFloat64, + values: Array1DFloat64) -> None: ... def query(self, - lon: numpy.ndarray[numpy.float64, flags.writeable], - lat: numpy.ndarray[numpy.float64, flags.writeable], + lon: Array1DBool, + lat: Array1DBool, k: int = ..., within: bool = ..., num_threads: int = ...) -> tuple: ... def radial_basis_function(self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], + lon: Array1DFloat64, + lat: Array1DFloat64, radius: Optional[float] = ..., k: int = ..., rbf: core.RadialBasisFunction = ..., @@ -581,8 +580,8 @@ class RTree: ... def window_function(self, - lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], + lon: Array1DFloat64, + lat: Array1DFloat64, radius: float = ..., k: int = ..., wf: core.WindowFunction = ..., @@ -608,7 +607,7 @@ class RTree: class Spheroid(_Spheroid): - __hash__: ClassVar[None] = ... + __hash__: ClassVar[None] = ... # type: ignore[assignment] @overload def __init__(self) -> None: @@ -654,13 +653,13 @@ class Spheroid(_Spheroid): def volumetric_radius(self) -> float: ... - def __eq__(self, other: _Spheroid) -> bool: + def __eq__(self, other: _Spheroid) -> bool: # type: ignore[override] ... def __getstate__(self) -> tuple: ... - def __ne__(self, other: _Spheroid) -> bool: + def __ne__(self, other: _Spheroid) -> bool: # type: ignore[override] ... def __setstate__(self, state: tuple) -> None: @@ -682,10 +681,10 @@ class _Spheroid: def calculate_crossover( - lon1: numpy.ndarray[numpy.float64], - lat1: numpy.ndarray[numpy.float64], - lon2: numpy.ndarray[numpy.float64], - lat2: numpy.ndarray[numpy.float64], + lon1: Array1DFloat64, + lat1: Array1DFloat64, + lon2: Array1DFloat64, + lat2: Array1DFloat64, predicate: Optional[float] = None, strategy: str = "thomas", wgs: Optional[Spheroid] = None, @@ -695,10 +694,10 @@ def calculate_crossover( def calculate_crossover_list( - lon1: numpy.ndarray[numpy.float64], - lat1: numpy.ndarray[numpy.float64], - lon2: numpy.ndarray[numpy.float64], - lat2: numpy.ndarray[numpy.float64], + lon1: Array1DFloat64, + lat1: Array1DFloat64, + lon2: Array1DFloat64, + lat2: Array1DFloat64, predicate: Optional[float] = None, strategy: str = "thomas", wgs: Optional[Spheroid] = None, @@ -707,34 +706,26 @@ def calculate_crossover_list( def calculate_swath( - lon_nadir: numpy.ndarray[numpy.float64], - lat_nadir: numpy.ndarray[numpy.float64], + lon_nadir: Array1DFloat64, + lat_nadir: Array1DFloat64, delta_ac: float, half_gap: float, half_swath: int, spheroid: Optional[Spheroid] = None, -) -> Tuple[numpy.ndarray[numpy.float64], numpy.ndarray[numpy.float64]]: - ... - - -def coordinate_distances( - lon1: numpy.ndarray[numpy.float64], - lat1: numpy.ndarray[numpy.float64], - lon2: numpy.ndarray[numpy.float64], - lat2: numpy.ndarray[numpy.float64], - strategy: str = ..., - wgs: Optional[Spheroid] = None, - num_threads: int = ...) -> numpy.ndarray[numpy.float64]: +) -> Tuple[Array2DFloat64, Array2DFloat64]: ... -@overload -def normalize_longitudes(lon: numpy.ndarray[numpy.float64], - min_lon: float = ...) -> None: +def coordinate_distances(lon1: Array1DFloat64, + lat1: Array1DFloat64, + lon2: Array1DFloat64, + lat2: Array1DFloat64, + strategy: str = ..., + wgs: Optional[Spheroid] = None, + num_threads: int = ...) -> Array1DFloat64: ... -@overload -def normalize_longitudes(lon: numpy.ndarray[numpy.float64], - min_lon: float = ...) -> numpy.ndarray[numpy.float64]: +def normalize_longitudes(lon: Array1DFloat64, + min_lon: float = ...) -> Array1DFloat64 | None: ... diff --git a/src/pyinterp/core/geohash/__init__.pyi b/src/pyinterp/core/geohash/__init__.pyi index 63184a1e..595e17eb 100644 --- a/src/pyinterp/core/geohash/__init__.pyi +++ b/src/pyinterp/core/geohash/__init__.pyi @@ -1,53 +1,52 @@ +from __future__ import annotations + from typing import Optional, Tuple, overload import numpy from . import int64 from .. import geodetic +from ..array import Array1DFloat64, Array1DStr -def area( - hash: numpy.ndarray, - wgs: Optional[geodetic.Spheroid] = None -) -> numpy.ndarray[numpy.float64]: +def area(hash: numpy.ndarray, + wgs: Optional[geodetic.Spheroid] = None) -> Array1DFloat64: ... @overload def bounding_boxes(box: Optional[geodetic.Box] = ..., - precision: int = ...) -> numpy.ndarray: + precision: int = ...) -> Array1DStr: ... @overload def bounding_boxes(polygon: geodetic.Polygon, precision: int = ..., - num_threads: int = ...) -> numpy.ndarray: + num_threads: int = ...) -> Array1DStr: ... @overload def bounding_boxes(polygons: geodetic.MultiPolygon, precision: int = ..., - num_threads: int = ...) -> numpy.ndarray: + num_threads: int = ...) -> Array1DStr: ... -def decode( - hash: numpy.ndarray, - round: bool = ... -) -> Tuple[numpy.ndarray[numpy.float64], numpy.ndarray[numpy.float64]]: +def decode(hash: Array1DStr, + round: bool = ...) -> Tuple[Array1DFloat64, Array1DFloat64]: ... -def encode(lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - precision: int = ...) -> numpy.ndarray: +def encode(lon: Array1DFloat64, + lat: Array1DFloat64, + precision: int = ...) -> Array1DStr: ... -def transform(hash: numpy.ndarray, precision: int = ...) -> numpy.ndarray: +def transform(hash: Array1DStr, precision: int = ...) -> Array1DStr: ... -def where(hash: numpy.ndarray) -> dict: +def where(hash: Array1DStr) -> dict: ... diff --git a/src/pyinterp/core/geohash/int64.pyi b/src/pyinterp/core/geohash/int64.pyi index 677912f9..1e0ab695 100644 --- a/src/pyinterp/core/geohash/int64.pyi +++ b/src/pyinterp/core/geohash/int64.pyi @@ -1,22 +1,21 @@ -from typing import Tuple, overload +from __future__ import annotations -import numpy +from typing import Any, Literal, overload from .. import geodetic +from ..array import Array1DFloat64, Array1DUInt64 -def decode( - hash: numpy.ndarray[numpy.uint64], - precision: int = ..., - round: bool = ... -) -> Tuple[numpy.ndarray[numpy.float64], numpy.ndarray[numpy.float64]]: +def decode(hash: Array1DUInt64, + precision: int = ..., + round: bool = ...) -> tuple[Array1DFloat64, Array1DFloat64]: ... -def encode(lon: numpy.ndarray[numpy.float64], - lat: numpy.ndarray[numpy.float64], - precision: int = ...) -> numpy.ndarray[numpy.uint64]: +def encode(lon: Array1DFloat64, + lat: Array1DFloat64, + precision: int = ...) -> Array1DUInt64: ... -def neighbors(hash: int, precision: int = ...) -> numpy.ndarray[numpy.uint64]: +def neighbors(hash: int, precision: int = ...) -> Array1DUInt64: ... diff --git a/src/pyinterp/fill.py b/src/pyinterp/fill.py index 42a94430..b65af9df 100644 --- a/src/pyinterp/fill.py +++ b/src/pyinterp/fill.py @@ -2,7 +2,9 @@ Replace undefined values ------------------------ """ -from typing import Any, Optional, Union +from __future__ import annotations + +from typing import Any import concurrent.futures import numpy @@ -11,10 +13,10 @@ from .typing import NDArray -def loess(mesh: Union[grid.Grid2D, grid.Grid3D], +def loess(mesh: grid.Grid2D | grid.Grid3D, nx: int = 3, ny: int = 3, - value_type: Optional[str] = None, + value_type: str | None = None, num_threads: int = 0): """Filter values using a locally weighted regression function or LOESS. The weight function used for LOESS is the tri-cube weight function, @@ -48,11 +50,11 @@ def loess(mesh: Union[grid.Grid2D, grid.Grid3D], num_threads) -def gauss_seidel(mesh: Union[grid.Grid2D, grid.Grid3D], +def gauss_seidel(mesh: grid.Grid2D | grid.Grid3D, first_guess: str = 'zonal_average', - max_iteration: Optional[int] = None, + max_iteration: int | None = None, epsilon: float = 1e-4, - relaxation: Optional[float] = None, + relaxation: float | None = None, num_threads: int = 0): """Replaces all undefined values (NaN) in a grid using the Gauss-Seidel method by relaxation. @@ -142,13 +144,16 @@ def gauss_seidel(mesh: Union[grid.Grid2D, grid.Grid3D], def matrix(x: NDArray, fill_value: Any = numpy.nan, - in_place: bool = True) -> None: + in_place: bool = True) -> NDArray: """Fills in the gaps between defined values in a 2-dimensional array. Args: x: data to be filled. fill_value: Value used to fill undefined values. in_place: If true, the data is filled in place. Defaults to ``True``. + + Returns: + The data filled. """ if len(x.shape) != 2: raise ValueError('x must be a 2-dimensional array') diff --git a/src/pyinterp/geodetic/__init__.py b/src/pyinterp/geodetic/__init__.py index a47183f3..aa2fb166 100644 --- a/src/pyinterp/geodetic/__init__.py +++ b/src/pyinterp/geodetic/__init__.py @@ -2,7 +2,7 @@ Geographic coordinate system ---------------------------- """ -from typing import List, Optional, Tuple +from __future__ import annotations import numpy @@ -56,7 +56,7 @@ class Spheroid(geodetic.Spheroid): Spheroid(6378137.0, 0.003352810681182319) """ - def __init__(self, parameters: Optional[Tuple[float, float]] = None): + def __init__(self, parameters: tuple[float, float] | None = None): super().__init__(*(parameters or ())) def __repr__(self): @@ -71,7 +71,7 @@ class Coordinates(geodetic.Coordinates): manages a WGS84 ellipsoid. """ - def __init__(self, spheroid: Optional[Spheroid] = None): + def __init__(self, spheroid: Spheroid | None = None): super().__init__(spheroid) @@ -97,8 +97,8 @@ class Box(geodetic.Box): """ def __init__(self, - min_corner: Optional[Point] = None, - max_corner: Optional[Point] = None): + min_corner: Point | None = None, + max_corner: Point | None = None): super().__init__(min_corner or geodetic.Point(), max_corner or geodetic.Point()) @@ -117,8 +117,8 @@ class Polygon(geodetic.Polygon): """ def __init__(self, - outer: List[Point], - inners: Optional[List[List[Point]]] = None) -> None: + outer: list[Point], + inners: list[list[Point]] | None = None) -> None: super().__init__(outer, inners) # type: ignore @@ -134,7 +134,7 @@ class MultiPolygon(geodetic.MultiPolygon): :py:class:`pyinterp.geodetic.Polygon`. """ - def __init__(self, polygons: Optional[List[Polygon]] = None) -> None: + def __init__(self, polygons: list[Polygon] | None = None) -> None: args = (polygons, ) if polygons is not None else () super().__init__(*args) @@ -165,18 +165,18 @@ class RTree(geodetic.RTree): ellipsoid. """ - def __init__(self, spheroid: Optional[Spheroid] = None) -> None: + def __init__(self, spheroid: Spheroid | None = None) -> None: super().__init__(spheroid) def inverse_distance_weighting( self, lon: numpy.ndarray, lat: numpy.ndarray, - radius: Optional[float] = None, + radius: float | None = None, k: int = 9, p: int = 2, within: bool = True, - num_threads: int = 0) -> Tuple[numpy.ndarray, numpy.ndarray]: + num_threads: int = 0) -> tuple[numpy.ndarray, numpy.ndarray]: """Interpolation of the value at the requested position by inverse distance weighting method. @@ -202,18 +202,18 @@ def inverse_distance_weighting( return super().inverse_distance_weighting(lon, lat, radius, k, p, within, num_threads) - def radial_basis_function( + def radial_basis_function( # type: ignore[override] self, lon: numpy.ndarray, lat: numpy.ndarray, - radius: Optional[float] = None, + radius: float | None = None, k: int = 9, - rbf: Optional[str] = None, - epsilon: Optional[float] = None, + rbf: str | None = None, + epsilon: float | None = None, smooth: float = 0, within: bool = True, num_threads: int = 0, - ) -> Tuple[numpy.ndarray, numpy.ndarray]: + ) -> tuple[numpy.ndarray, numpy.ndarray]: """Interpolation of the value at the requested position by radial basis function interpolation. @@ -259,17 +259,17 @@ def radial_basis_function( interface._core_radial_basis_function(rbf, epsilon), epsilon, smooth, within, num_threads) - def window_function( + def window_function( # type: ignore[override] self, lon: numpy.ndarray, lat: numpy.ndarray, radius: float, k: int = 9, - wf: Optional[str] = None, - arg: Optional[float] = None, + wf: str | None = None, + arg: float | None = None, within: bool = True, num_threads: int = 0, - ) -> Tuple[numpy.ndarray, numpy.ndarray]: + ) -> tuple[numpy.ndarray, numpy.ndarray]: """Interpolation of the value at the requested position by window function. diff --git a/src/pyinterp/grid.py b/src/pyinterp/grid.py index 25da29bc..8c0fcc08 100644 --- a/src/pyinterp/grid.py +++ b/src/pyinterp/grid.py @@ -6,7 +6,7 @@ Regular grids ============= """ -from typing import Optional, Union +from __future__ import annotations import numpy @@ -60,7 +60,7 @@ class Grid2D: #: The number of grid dimensions handled by this object. _DIMENSIONS = 2 - def __init__(self, *args, increasing_axes: Optional[str] = None): + def __init__(self, *args, increasing_axes: str | None = None): prefix = '' for idx, item in enumerate(args): if isinstance(item, core.TemporalAxis): @@ -74,13 +74,15 @@ def __init__(self, *args, increasing_axes: Optional[str] = None): f'{increasing_axes!r} is not defined') inplace = increasing_axes == 'inplace' # Tuple does not support item assignment - args = list(args) + args = list(args) # type: ignore[assignment] for idx, item in enumerate(args): if isinstance(item, (core.Axis, core.TemporalAxis)) and not item.is_ascending(): - args[idx] = item.flip(inplace=inplace) - args[-1] = numpy.flip(args[-1], axis=idx) + args[idx] = item.flip( # type: ignore[index] + inplace=inplace) + args[-1] = numpy.flip( # type: ignore[index] + args[-1], axis=idx) self._instance = getattr(core, _class)(*args) self._prefix = prefix @@ -167,11 +169,11 @@ class Grid3D(Grid2D): """ _DIMENSIONS = 3 - def __init__(self, *args, increasing_axes: Optional[str] = None): + def __init__(self, *args, increasing_axes: str | None = None): super().__init__(*args, increasing_axes=increasing_axes) @property - def z(self) -> Union[core.Axis, core.TemporalAxis]: + def z(self) -> core.Axis | core.TemporalAxis: """Gets the Z-Axis handled by this instance. Returns: @@ -201,7 +203,7 @@ class Grid4D(Grid3D): """ _DIMENSIONS = 4 - def __init__(self, *args, increasing_axes: Optional[str] = None): + def __init__(self, *args, increasing_axes: str | None = None): super().__init__(*args, increasing_axes=increasing_axes) @property diff --git a/src/pyinterp/histogram2d.py b/src/pyinterp/histogram2d.py index 902fe8c1..6472c957 100644 --- a/src/pyinterp/histogram2d.py +++ b/src/pyinterp/histogram2d.py @@ -6,7 +6,9 @@ Histogram 2D ------------ """ -from typing import Optional, Union +from __future__ import annotations + +from typing import Union import copy import dask.array.core @@ -14,6 +16,9 @@ from . import core +#: The type of the histogram 2D +Histogram2DTyped = Union[core.Histogram2DFloat64, core.Histogram2DFloat32] + class Histogram2D: """Group a number of more or less continuous values into a smaller number @@ -61,10 +66,11 @@ class Histogram2D: def __init__(self, x: core.Axis, y: core.Axis, - bin_counts: Optional[int] = None, - dtype: Optional[numpy.dtype] = numpy.dtype('float64')): + bin_counts: int | None = None, + dtype: numpy.dtype | None = numpy.dtype('float64')): if dtype == numpy.dtype('float64'): - self._instance = core.Histogram2DFloat64(x, y, bin_counts) + self._instance: Histogram2DTyped = core.Histogram2DFloat64( + x, y, bin_counts) elif dtype == numpy.dtype('float32'): self._instance = core.Histogram2DFloat32(x, y, bin_counts) else: @@ -94,7 +100,7 @@ def __repr__(self) -> str: result.append(f' y: {self._instance.y}') return '\n'.join(result) - def __add__(self, other: 'Histogram2D') -> 'Histogram2D': + def __add__(self, other: Histogram2D) -> Histogram2D: """Overrides the default behavior of the ``+`` operator.""" if self.dtype != other.dtype: raise ValueError('dtype mismatch') @@ -118,9 +124,9 @@ def push(self, x: numpy.ndarray, y: numpy.ndarray, def push_delayed( self, - x: Union[numpy.ndarray, dask.array.core.Array], - y: Union[numpy.ndarray, dask.array.core.Array], - z: Union[numpy.ndarray, dask.array.core.Array], + x: numpy.ndarray | dask.array.core.Array, + y: numpy.ndarray | dask.array.core.Array, + z: numpy.ndarray | dask.array.core.Array, ) -> dask.array.core.Array: """Push new samples into the defined bins from dask array. diff --git a/src/pyinterp/interface.py b/src/pyinterp/interface.py index 4ff80ac0..66b58ff7 100644 --- a/src/pyinterp/interface.py +++ b/src/pyinterp/interface.py @@ -6,7 +6,8 @@ Interface with the library core =============================== """ -from typing import Optional +from __future__ import annotations + import re import numpy @@ -90,7 +91,7 @@ def _core_function(function: str, instance: object) -> str: def _core_covariance_function( - covariance: Optional[str]) -> core.CovarianceFunction: + covariance: str | None) -> core.CovarianceFunction: """Get the covariance function.""" covariance = covariance or 'matern_32' if covariance not in [ @@ -109,8 +110,7 @@ def _core_covariance_function( def _core_radial_basis_function( - rbf: Optional[str], - epsilon: Optional[float]) -> core.RadialBasisFunction: + rbf: str | None, epsilon: float | None) -> core.RadialBasisFunction: """Get the radial basis function.""" adjustable = ['gaussian', 'inverse_multiquadric', 'multiquadric'] non_adjustable = ['cubic', 'linear', 'thin_plate'] @@ -124,8 +124,8 @@ def _core_radial_basis_function( return getattr(core.RadialBasisFunction, rbf) -def _core_window_function(wf: Optional[str], - arg: Optional[float]) -> core.WindowFunction: +def _core_window_function(wf: str | None, + arg: float | None) -> core.WindowFunction: """Get the window function.""" wf = wf or 'blackman' if wf not in [ diff --git a/src/pyinterp/interpolator/bicubic.py b/src/pyinterp/interpolator/bicubic.py index ddfae06b..012c71e3 100644 --- a/src/pyinterp/interpolator/bicubic.py +++ b/src/pyinterp/interpolator/bicubic.py @@ -6,18 +6,18 @@ Bicubic interpolation ===================== """ -from typing import Optional, Union +from __future__ import annotations import numpy from .. import core, grid, interface -def bicubic(mesh: Union[grid.Grid2D, grid.Grid3D, grid.Grid4D], +def bicubic(mesh: grid.Grid2D | grid.Grid3D | grid.Grid4D, x: numpy.ndarray, y: numpy.ndarray, - z: Optional[numpy.ndarray] = None, - u: Optional[numpy.ndarray] = None, + z: numpy.ndarray | None = None, + u: numpy.ndarray | None = None, nx: int = 3, ny: int = 3, fitting_model: str = 'bicubic', diff --git a/src/pyinterp/orbit.py b/src/pyinterp/orbit.py index 0a61e9e5..9ddb9bd8 100644 --- a/src/pyinterp/orbit.py +++ b/src/pyinterp/orbit.py @@ -6,7 +6,9 @@ Orbit interpolation. ==================== """ -from typing import Iterator, Optional, Tuple +from __future__ import annotations + +from typing import Iterator import dataclasses import numpy @@ -21,9 +23,9 @@ def interpolate( xp: NDArray, xi: NDArray, height: float = 0.0, - wgs: Optional[geodetic.Coordinates] = None, + wgs: geodetic.Coordinates | None = None, half_window_size: int = 10, -) -> Tuple[NDArray, NDArray]: +) -> tuple[NDArray, NDArray]: """Interpolate the given orbit at the given coordinates. Args: @@ -41,17 +43,41 @@ def interpolate( """ wgs = wgs or geodetic.Coordinates() mz = wgs.spheroid.semi_major_axis / wgs.spheroid.semi_minor_axis() - x, y, z = wgs.lla_to_ecef(lon, lat, numpy.full_like(lon, height)) + x, y, z = wgs.lla_to_ecef( + lon, # type: ignore + lat, # type: ignore + numpy.full_like(lon, height), + ) r = numpy.sqrt(x * x + y * y + z * z * mz * mz) x_axis = core.Axis((xp - xp[0]).astype(numpy.float64), 1e-6, False) xi = (xi - xp[0]).astype(numpy.float64) - x = core.interpolate1d(x_axis, x, xi, half_window_size=half_window_size) - y = core.interpolate1d(x_axis, y, xi, half_window_size=half_window_size) - z = core.interpolate1d(x_axis, z, xi, half_window_size=half_window_size) - r = core.interpolate1d(x_axis, r, xi, half_window_size=half_window_size) + x = core.interpolate1d( + x_axis, + x, + xi, # type: ignore + half_window_size=half_window_size, + ) + y = core.interpolate1d( + x_axis, + y, + xi, # type: ignore + half_window_size=half_window_size, + ) + z = core.interpolate1d( + x_axis, + z, + xi, # type: ignore + half_window_size=half_window_size, + ) + r = core.interpolate1d( + x_axis, + r, + xi, # type: ignore + half_window_size=half_window_size, + ) r /= numpy.sqrt(x * x + y * y + z * z) x *= r @@ -68,7 +94,7 @@ def _rearrange_orbit( lon: NDArray, lat: NDArray, time: NDArrayTimeDelta, -) -> Tuple[NDArray, NDArray, NDArrayTimeDelta]: +) -> tuple[NDArray, NDArray, NDArrayTimeDelta]: """Rearrange orbit starting from pass 1. Detect the beginning of pass 1 in the ephemeris. By definition, it is @@ -149,7 +175,7 @@ class Orbit: #: Along track distance (in meters). x_al: NDArray #: Spheroid model used. - wgs: Optional[geodetic.Spheroid] + wgs: geodetic.Spheroid | None def cycle_duration(self) -> numpy.timedelta64: """Get the cycle duration.""" @@ -168,9 +194,10 @@ def orbit_duration(self) -> numpy.timedelta64: def curvilinear_distance(self) -> numpy.ndarray: """Get the curvilinear distance.""" - return geodetic.LineString(self.longitude, - self.latitude).curvilinear_distance( - strategy='thomas', wgs=self.wgs) + return geodetic.LineString( + self.longitude, # type: ignore + self.latitude, # type: ignore + ).curvilinear_distance(strategy='thomas', wgs=self.wgs) def pass_duration(self, number: int) -> numpy.timedelta64: """Get the duration of a given pass. @@ -189,7 +216,7 @@ def pass_duration(self, number: int) -> numpy.timedelta64: self.time[0]) return self.pass_time[number] - self.pass_time[number - 1] - def decode_absolute_pass_number(self, number: int) -> Tuple[int, int]: + def decode_absolute_pass_number(self, number: int) -> tuple[int, int]: """Calculate the cycle and pass number from a given absolute pass number. @@ -227,10 +254,10 @@ def delta_t(self) -> numpy.timedelta64: def iterate( self, - first_date: Optional[numpy.datetime64] = None, - last_date: Optional[numpy.datetime64] = None, + first_date: numpy.datetime64 | None = None, + last_date: numpy.datetime64 | None = None, absolute_pass_number: int = 1 - ) -> Iterator[Tuple[int, int, numpy.datetime64]]: + ) -> Iterator[tuple[int, int, numpy.datetime64]]: """Obtain all half-orbits within the defined time interval. Args: @@ -269,7 +296,7 @@ class EquatorCoordinates: time: numpy.datetime64 @classmethod - def undefined(cls) -> 'EquatorCoordinates': + def undefined(cls) -> EquatorCoordinates: """Create an undefined instance.""" return cls(numpy.nan, numpy.datetime64('NaT')) @@ -303,7 +330,7 @@ class Swath(Pass): #: Across track distance of the pass (m) x_ac: NDArray - def mask(self, requirement_bounds: Tuple[float, float]) -> NDArray: + def mask(self, requirement_bounds: tuple[float, float]) -> NDArray: """Obtain a mask to set NaN values outside the mission requirements. Args: @@ -319,9 +346,9 @@ def mask(self, requirement_bounds: Tuple[float, float]) -> NDArray: valid[(numpy.abs(self.x_ac) >= requirement_bounds[0]) & (numpy.abs(self.x_ac) <= requirement_bounds[1])] = 1 along_track = numpy.full(self.lon_nadir.shape, 1, dtype=numpy.float64) - return along_track[:, numpy.newaxis] * valid + return along_track[:, numpy.newaxis] * valid # type: ignore - def insert_central_pixel(self) -> 'Swath': + def insert_central_pixel(self) -> Swath: """Return a swath with a central pixel dividing the swath in two by the reference ground track.""" @@ -360,7 +387,10 @@ def _equator_properties(lon_nadir: NDArray, lat_nadir: NDArray, lat1 = lat_nadir[i0:i1 + 1] # Calculate the position of the satellite at the equator - intersection = geodetic.LineString(lon1, lat1).intersection( + intersection = geodetic.LineString( + lon1, # type: ignore + lat1, # type: ignore + ).intersection( geodetic.LineString(numpy.array([lon1[0] - 0.5, lon1[1] + 0.5]), numpy.array([0, 0], dtype='float64'))) if len(intersection) == 0: @@ -371,8 +401,10 @@ def _equator_properties(lon_nadir: NDArray, lat_nadir: NDArray, # Calculate the time of the point on the equator lon1 = numpy.insert(lon1, 1, point.lon) lat1 = numpy.insert(lat1, 1, 0) - x_al = geodetic.LineString(lon1, - lat1).curvilinear_distance(strategy='thomas') + x_al = geodetic.LineString( + lon1, # type: ignore + lat1, # type: ignore + ).curvilinear_distance(strategy='thomas') # Pop the along track distance at the equator x_eq = x_al[1] @@ -390,9 +422,9 @@ def calculate_orbit( lon_nadir: NDArray, lat_nadir: NDArray, time: NDArrayTimeDelta, - cycle_duration: Optional[numpy.timedelta64] = None, - along_track_resolution: Optional[float] = None, - spheroid: Optional[geodetic.Spheroid] = None, + cycle_duration: numpy.timedelta64 | None = None, + along_track_resolution: float | None = None, + spheroid: geodetic.Spheroid | None = None, ) -> Orbit: """Calculate the orbit at the given height. @@ -414,7 +446,7 @@ def calculate_orbit( # If the first point of the given orbit starts at the equator, we need to # skew this first pass. if -40 <= lat_nadir[0] <= 40: - dy = numpy.roll(lat_nadir, 1) - lat_nadir + dy = numpy.roll(lat_nadir, 1) - lat_nadir # type: ignore indexes = numpy.where(((dy < 0) & (numpy.roll(dy, 1) >= 0)) | ((dy > 0) & (numpy.roll(dy, 1) <= 0)))[0] @@ -430,13 +462,14 @@ def calculate_orbit( time[-1], numpy.timedelta64(500, 'ms'), dtype=time.dtype) - lon_nadir, lat_nadir = interpolate(lon_nadir, - lat_nadir, - time.astype('i8'), - time_hr.astype('i8'), - height=height, - wgs=wgs, - half_window_size=50) + lon_nadir, lat_nadir = interpolate( + lon_nadir, # type: ignore + lat_nadir, + time.astype('i8'), + time_hr.astype('i8'), + height=height, + wgs=wgs, + half_window_size=50) time = time_hr if cycle_duration is not None: @@ -449,44 +482,53 @@ def calculate_orbit( # Rearrange orbit starting from pass 1 lon_nadir, lat_nadir, time = _rearrange_orbit( time[-1] + time[1] - time[0], - lon_nadir, + lon_nadir, # type: ignore lat_nadir, - time, + time, # type: ignore ) # Calculates the along track distance (km) - distance = geodetic.LineString(lon_nadir, lat_nadir).curvilinear_distance( - strategy='thomas', wgs=spheroid) * 1e-3 + distance = geodetic.LineString( + lon_nadir, # type: ignore[arg-type] + lat_nadir, # type: ignore[arg-type] + ).curvilinear_distance(strategy='thomas', wgs=spheroid) * 1e-3 # Interpolate the final orbit according the given along track resolution x_al = numpy.arange(distance[0], distance[-2], along_track_resolution or 2, dtype=distance.dtype) - lon_nadir, lat_nadir = interpolate(lon_nadir[:-1], - lat_nadir[:-1], - distance[:-1], - x_al, - height=height, - wgs=wgs, - half_window_size=10) + lon_nadir, lat_nadir = interpolate( + lon_nadir[:-1], + lat_nadir[:-1], + distance[:-1], # type: ignore + x_al, # type: ignore + height=height, + wgs=wgs, + half_window_size=10) time = numpy.interp( x_al, # type: ignore distance[:-1], # type: ignore time[:-1].astype('i8')).astype(time.dtype) - return Orbit(height, lat_nadir, lon_nadir, - numpy.sort(_calculate_pass_time(lat_nadir, time)), time, x_al, - wgs.spheroid) # type: ignore + return Orbit( + height, + lat_nadir, + lon_nadir, + numpy.sort(_calculate_pass_time(lat_nadir, time)), + time, + x_al, # type: ignore + wgs.spheroid, # type: ignore + ) # type: ignore def calculate_pass( pass_number: int, orbit: Orbit, *, - bbox: Optional[geodetic.Box] = None, -) -> Optional[Pass]: + bbox: geodetic.Box | None = None, +) -> Pass | None: """Get the properties of a swath of an half-orbit. Args: @@ -532,11 +574,11 @@ def calculate_pass( def calculate_swath( half_orbit: Pass, *, - across_track_resolution: Optional[float] = None, - along_track_resolution: Optional[float] = None, - half_swath: Optional[float] = None, - half_gap: Optional[float] = None, - spheroid: Optional[geodetic.Spheroid] = None, + across_track_resolution: float | None = None, + along_track_resolution: float | None = None, + half_swath: float | None = None, + half_gap: float | None = None, + spheroid: geodetic.Spheroid | None = None, ) -> Swath: """Get the properties of a swath of an half-orbit. @@ -571,14 +613,21 @@ def calculate_swath( x_ac = numpy.full((len(half_orbit), x_ac.size), x_ac) lon, lat = core.geodetic.calculate_swath( - half_orbit.lon_nadir, - half_orbit.lat_nadir, + half_orbit.lon_nadir, # type: ignore + half_orbit.lat_nadir, # type: ignore across_track_resolution * 1e3, half_gap * 1e3, half_swath, spheroid, ) - return Swath(half_orbit.lon_nadir, half_orbit.lat_nadir, half_orbit.time, - half_orbit.x_al, half_orbit.equator_coordinates, lon, lat, - x_ac) + return Swath( + half_orbit.lon_nadir, + half_orbit.lat_nadir, + half_orbit.time, + half_orbit.x_al, + half_orbit.equator_coordinates, + lon, # type: ignore + lat, # type: ignore + x_ac, + ) diff --git a/src/pyinterp/period.py b/src/pyinterp/period.py index a87b6f8e..9e83582b 100644 --- a/src/pyinterp/period.py +++ b/src/pyinterp/period.py @@ -75,16 +75,16 @@ def as_base_class(self) -> core.Period: return core.Period(super().begin, super().last, True) @property - def begin(self) -> numpy.datetime64: + def begin(self) -> numpy.datetime64: # type: ignore[override] """Gets the beginning of the period.""" return numpy.datetime64(super().begin, self.resolution) @property - def last(self) -> numpy.datetime64: + def last(self) -> numpy.datetime64: # type: ignore[override] """Gets the beginning of the period.""" return numpy.datetime64(super().last, self.resolution) - def end(self) -> numpy.datetime64: + def end(self) -> numpy.datetime64: # type: ignore[override] """Gets the end of the period.""" return numpy.datetime64(super().end(), self.resolution) @@ -109,7 +109,7 @@ def __repr__(self) -> str: def __str__(self) -> str: return f'[{self.begin}, {self.end()})' - def duration(self) -> numpy.timedelta64: + def duration(self) -> numpy.timedelta64: # type: ignore[override] """Gets the duration of the period.""" return numpy.timedelta64(super().duration(), self.resolution) @@ -117,24 +117,24 @@ def is_null(self) -> bool: """True if period is ill formed (length is zero or less)""" return super().is_null() - def __eq__(self, lhs: Period) -> bool: + def __eq__(self, lhs: Any) -> bool: if not isinstance(lhs, Period): return NotImplemented if self.resolution != lhs.resolution: return False return super().__eq__(lhs) - def __ne__(self, __value: Period) -> bool: + def __ne__(self, __value: Any) -> bool: return not self.__eq__(__value) - def __lt__(self, lhs: Period) -> bool: + def __lt__(self, lhs: Any) -> bool: if not isinstance(lhs, Period): return NotImplemented if self.resolution != lhs.resolution: return False return super().__lt__(lhs) - def contains( + def contains( # type: ignore[override] self, other: numpy.datetime64 | Period, ) -> bool: @@ -155,7 +155,7 @@ def contains( return super().contains(other) return super().contains(_datetime64_to_int64(other, self.resolution)) - def is_adjacent(self, other: Period) -> bool: + def is_adjacent(self, other: Period) -> bool: # type: ignore[override] """True if periods are next to each other without a gap. In the example below, p1 and p2 are adjacent, but p3 is not adjacent @@ -178,7 +178,8 @@ def is_adjacent(self, other: Period) -> bool: other = other.as_resolution(self.resolution) return super().is_adjacent(other) - def is_before(self, point: numpy.datetime64) -> bool: + def is_before(self, + point: numpy.datetime64) -> bool: # type: ignore[override] """True if all of the period is prior to the passed point or end <= point. @@ -198,7 +199,8 @@ def is_before(self, point: numpy.datetime64) -> bool: """ return super().is_before(_datetime64_to_int64(point, self.resolution)) - def is_after(self, point: numpy.datetime64) -> bool: + def is_after(self, + point: numpy.datetime64) -> bool: # type: ignore[override] """True if all of the period is prior or point < start. In the example below only point 1 would evaluate to true. @@ -217,7 +219,7 @@ def is_after(self, point: numpy.datetime64) -> bool: """ return super().is_after(_datetime64_to_int64(point, self.resolution)) - def intersects(self, other: Period) -> bool: + def intersects(self, other: Period) -> bool: # type: ignore[override] """True if the periods overlap in any way. In the example below p1 intersects with p2, p4, and p6. @@ -241,7 +243,7 @@ def intersects(self, other: Period) -> bool: other = other.as_resolution(self.resolution) return super().intersects(other) - def intersection(self, other: Period) -> Period: + def intersection(self, other: Period) -> Period: # type: ignore[override] """Returns the period of intersection or null period if no intersection. @@ -260,7 +262,7 @@ def intersection(self, other: Period) -> Period: True, ) - def merge(self, other: Period) -> Period: + def merge(self, other: Period) -> Period: # type: ignore[override] """Returns the union of intersecting periods -- or null period. Args: diff --git a/src/pyinterp/rtree.py b/src/pyinterp/rtree.py index 26867831..57e2c0e3 100644 --- a/src/pyinterp/rtree.py +++ b/src/pyinterp/rtree.py @@ -6,7 +6,7 @@ RTree spatial index ------------------- """ -from typing import Optional, Tuple +from __future__ import annotations import numpy @@ -28,8 +28,8 @@ class RTree: """ def __init__(self, - system: Optional[geodetic.Spheroid] = None, - dtype: Optional[numpy.dtype] = None, + system: geodetic.Spheroid | None = None, + dtype: numpy.dtype | None = None, ndims: int = 3): """Initialize a new R*Tree.""" dtype = dtype or numpy.dtype('float64') @@ -45,7 +45,7 @@ def __init__(self, def bounds( self - ) -> Tuple[Tuple[float, float, float], Tuple[float, float, float]]: + ) -> tuple[tuple[float, float, float], tuple[float, float, float]]: """Returns the box able to contain all values stored in the container. Returns: @@ -102,10 +102,10 @@ def insert(self, coordinates: numpy.ndarray, def value(self, coordinates: numpy.ndarray, - radius: Optional[float] = None, + radius: float | None = None, k: int = 4, within: bool = True, - num_threads: int = 0) -> Tuple[numpy.ndarray, numpy.ndarray]: + num_threads: int = 0) -> tuple[numpy.ndarray, numpy.ndarray]: """Get the coordinates and values for the K-nearest neighbors of a given point. @@ -142,7 +142,7 @@ def query(self, coordinates: numpy.ndarray, k: int = 4, within: bool = True, - num_threads: int = 0) -> Tuple[numpy.ndarray, numpy.ndarray]: + num_threads: int = 0) -> tuple[numpy.ndarray, numpy.ndarray]: """Search for the nearest K nearest neighbors of a given point. Args: @@ -171,11 +171,11 @@ def query(self, def inverse_distance_weighting( self, coordinates: numpy.ndarray, - radius: Optional[float] = None, + radius: float | None = None, k: int = 9, p: int = 2, within: bool = True, - num_threads: int = 0) -> Tuple[numpy.ndarray, numpy.ndarray]: + num_threads: int = 0) -> tuple[numpy.ndarray, numpy.ndarray]: """Interpolation of the value at the requested position by inverse distance weighting method. @@ -207,13 +207,13 @@ def inverse_distance_weighting( def radial_basis_function( self, coordinates: numpy.ndarray, - radius: Optional[float] = None, + radius: float | None = None, k: int = 9, - rbf: Optional[str] = None, - epsilon: Optional[float] = None, + rbf: str | None = None, + epsilon: float | None = None, smooth: float = 0, within: bool = True, - num_threads: int = 0) -> Tuple[numpy.ndarray, numpy.ndarray]: + num_threads: int = 0) -> tuple[numpy.ndarray, numpy.ndarray]: """Interpolation of the value at the requested position by radial basis function interpolation. @@ -265,12 +265,12 @@ def radial_basis_function( def window_function( self, coordinates: numpy.ndarray, - radius: Optional[float] = None, + radius: float | None = None, k: int = 9, - wf: Optional[str] = None, - arg: Optional[float] = None, + wf: str | None = None, + arg: float | None = None, within: bool = True, - num_threads: int = 0) -> Tuple[numpy.ndarray, numpy.ndarray]: + num_threads: int = 0) -> tuple[numpy.ndarray, numpy.ndarray]: """Interpolation of the value at the requested position by window function. @@ -359,13 +359,13 @@ def window_function( def universal_kriging( self, coordinates: numpy.ndarray, - radius: Optional[float] = None, + radius: float | None = None, k: int = 9, - covariance: Optional[str] = None, + covariance: str | None = None, sigma: float = 1.0, alpha: float = 1_000_000.0, within: bool = True, - num_threads: int = 0) -> Tuple[numpy.ndarray, numpy.ndarray]: + num_threads: int = 0) -> tuple[numpy.ndarray, numpy.ndarray]: """Interpolate the values of a point using universal kriging. Args: @@ -423,7 +423,7 @@ def universal_kriging( interface._core_covariance_function(covariance), sigma, alpha, within, num_threads) - def __getstate__(self) -> Tuple: + def __getstate__(self) -> tuple: """Return the state of the object for pickling purposes. Returns: @@ -431,7 +431,7 @@ def __getstate__(self) -> Tuple: """ return (self.dtype, self._instance.__getstate__()) - def __setstate__(self, state: Tuple): + def __setstate__(self, state: tuple): """Set the state of the object from pickling. Args: diff --git a/src/pyinterp/statistics/descriptive_descriptive.py b/src/pyinterp/statistics/descriptive_descriptive.py index e74f11da..9eef08f1 100644 --- a/src/pyinterp/statistics/descriptive_descriptive.py +++ b/src/pyinterp/statistics/descriptive_descriptive.py @@ -6,7 +6,9 @@ Descriptive statistics ---------------------- """ -from typing import Any, Iterable, Optional, Union +from __future__ import annotations + +from typing import Any, Iterable import copy import dask.array.core @@ -18,10 +20,9 @@ def _delayed( attr: str, values: dask.array.core.Array, - weights: Optional[dask.array.core.Array] = None, - axis: Optional[Iterable[int]] = None, -) -> Union[core.DescriptiveStatisticsFloat64, - core.DescriptiveStatisticsFloat32]: + weights: dask.array.core.Array | None = None, + axis: Iterable[int] | None = None, +) -> (core.DescriptiveStatisticsFloat64 | core.DescriptiveStatisticsFloat32): """Calculate the descriptive statistics of a dask array.""" if weights is not None and values.shape != weights.shape: raise ValueError('values and weights must have the same shape') @@ -75,11 +76,11 @@ class DescriptiveStatistics: """ def __init__(self, - values: Union[dask.array.core.Array, numpy.ndarray], - weights: Optional[Union[dask.array.core.Array, - numpy.ndarray]] = None, - axis: Optional[Union[int, Iterable[int]]] = None, - dtype: Optional[numpy.dtype] = None) -> None: + values: dask.array.core.Array | numpy.ndarray, + weights: None | + (dask.array.core.Array | numpy.ndarray) = None, + axis: int | Iterable[int] | None = None, + dtype: numpy.dtype | None = None) -> None: if isinstance(axis, int): axis = (axis, ) dtype = dtype or numpy.dtype('float64') @@ -91,16 +92,15 @@ def __init__(self, raise ValueError(f'dtype {dtype} not handled by the object') if isinstance(values, dask.array.core.Array) or isinstance( weights, dask.array.core.Array): - self._instance = _delayed( - attr, dask.array.core.asarray(values), - dask.array.core.asarray(weights) - if weights is not None else None, axis) + self._instance: (core.DescriptiveStatisticsFloat64 + | core.DescriptiveStatisticsFloat32) = _delayed( + attr, dask.array.core.asarray(values), + dask.array.core.asarray(weights) + if weights is not None else None, axis) else: - self._instance: Union[core.DescriptiveStatisticsFloat64, - core.DescriptiveStatisticsFloat32] = getattr( - core, attr)(values, weights, axis) + self._instance = getattr(core, attr)(values, weights, axis) - def copy(self) -> 'DescriptiveStatistics': + def copy(self) -> DescriptiveStatistics: """Creates a copy of the current descriptive statistics container. Returns: @@ -111,7 +111,7 @@ def copy(self) -> 'DescriptiveStatistics': result._instance = self._instance.__copy__() return result - def __iadd__(self, other: Any) -> 'DescriptiveStatistics': + def __iadd__(self, other: Any) -> DescriptiveStatistics: """Adds a new descriptive statistics container to the current one. Returns: @@ -126,7 +126,7 @@ def __iadd__(self, other: Any) -> 'DescriptiveStatistics': raise TypeError('unsupported operand type(s) for +=' f": '{type(self)}' and '{type(other)}'") - def __add__(self, other: Any) -> 'DescriptiveStatistics': + def __add__(self, other: Any) -> DescriptiveStatistics: """Adds a new descriptive statistics container to the current one. Returns: diff --git a/src/pyinterp/statistics/streaming_histogram.py b/src/pyinterp/statistics/streaming_histogram.py index 7095c65b..e5040b05 100644 --- a/src/pyinterp/statistics/streaming_histogram.py +++ b/src/pyinterp/statistics/streaming_histogram.py @@ -6,7 +6,9 @@ Calculate statistics of a stream of values ------------------------------------------ """ -from typing import Any, Iterable, Optional, Union +from __future__ import annotations + +from typing import Any, Iterable import dask.array.core import numpy @@ -17,10 +19,10 @@ def _delayed( attr: str, values: dask.array.core.Array, - weights: Optional[dask.array.core.Array] = None, - axis: Optional[Iterable[int]] = None, - bin_count: Optional[int] = None, -) -> Union[core.StreamingHistogramFloat64, core.StreamingHistogramFloat32]: + weights: dask.array.core.Array | None = None, + axis: Iterable[int] | None = None, + bin_count: int | None = None, +) -> core.StreamingHistogramFloat64 | core.StreamingHistogramFloat32: """Calculate the descriptive statistics of a dask array.""" if weights is not None and values.shape != weights.shape: raise ValueError('values and weights must have the same shape') @@ -89,12 +91,12 @@ class :py:class:`DescriptiveStatistics ` """ def __init__(self, - values: Union[dask.array.core.Array, numpy.ndarray], - weights: Optional[Union[dask.array.core.Array, - numpy.ndarray]] = None, - axis: Optional[Union[int, Iterable[int]]] = None, - bin_count: Optional[int] = None, - dtype: Optional[numpy.dtype] = None) -> None: + values: dask.array.core.Array | numpy.ndarray, + weights: None | + (dask.array.core.Array | numpy.ndarray) = None, + axis: int | Iterable[int] | None = None, + bin_count: int | None = None, + dtype: numpy.dtype | None = None) -> None: if isinstance(axis, int): axis = (axis, ) dtype = dtype or numpy.dtype('float64') @@ -106,21 +108,21 @@ def __init__(self, raise ValueError(f'dtype {dtype} not handled by the object') if isinstance(values, dask.array.core.Array) or isinstance( weights, dask.array.core.Array): - self._instance = _delayed(attr, - dask.array.core.asarray(values), - weights=dask.array.core.asarray(weights) - if weights is not None else None, - axis=axis, - bin_count=bin_count) + self._instance: (core.StreamingHistogramFloat64 + | core.StreamingHistogramFloat32) = _delayed( + attr, + dask.array.core.asarray(values), + weights=dask.array.core.asarray(weights) + if weights is not None else None, + axis=axis, + bin_count=bin_count) else: - self._instance: Union[core.StreamingHistogramFloat64, - core.StreamingHistogramFloat32] = getattr( - core, attr)(values, - weights=weights, - axis=axis, - bin_count=bin_count) - - def __iadd__(self, other: Any) -> 'StreamingHistogram': + self._instance = getattr(core, attr)(values, + weights=weights, + axis=axis, + bin_count=bin_count) + + def __iadd__(self, other: Any) -> StreamingHistogram: """Adds a new histogram to the current one. Args: diff --git a/src/pyinterp/typing.py b/src/pyinterp/typing.py index 13748469..6ee711ea 100644 --- a/src/pyinterp/typing.py +++ b/src/pyinterp/typing.py @@ -11,16 +11,34 @@ A numpy tensor with any type. """ -from typing import TYPE_CHECKING, Any, Tuple +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, TypeVar import sys import numpy import numpy.typing +try: + from types import GenericAlias # type: ignore[attr-defined] +except ImportError: # pragma: no cover + # pylint: disable=ungrouped-imports + # For Python < 3.9 we use a backport of GenericAlias provided by + # numpy + # isort: off + from numpy._typing._generic_alias import ( # type: ignore[misc,no-redef] + _GenericAlias as GenericAlias, # yapf: disable + ) + # isort: on + # pylint: enable=ungrouped-imports + NDArray = numpy.typing.NDArray +NDArrayDateTime: Any +NDArrayStructured: Any +NDArrayTimeDelta: Any -def numpy_version() -> Tuple[int, ...]: +def numpy_version() -> tuple[int, ...]: """Returns the version of the installed numpy library. Returns: @@ -36,6 +54,22 @@ def numpy_version() -> Tuple[int, ...]: NDArrayTimeDelta = numpy.ndarray[Any, numpy.dtype[numpy.timedelta64]] else: # pragma: no cover - NDArrayDateTime = NDArray - NDArrayStructured = NDArray - NDArrayTimeDelta = NDArray + ScalarType_co = TypeVar('ScalarType_co', + bound=numpy.generic, + covariant=True) + _DType = GenericAlias( + numpy.dtype, + (ScalarType_co, ), + ) + NDArrayDateTime = GenericAlias( + numpy.ndarray, + (Any, numpy.dtype(numpy.datetime64)), + ) + NDArrayStructured = GenericAlias( + numpy.ndarray, + (Any, _DType), + ) + NDArrayTimeDelta = GenericAlias( + numpy.ndarray, + (Any, numpy.dtype(numpy.timedelta64)), + )