Skip to content

Commit

Permalink
Added named_arrays.DirectionalVectorArray and `named_arrays.Directi…
Browse files Browse the repository at this point in the history
…onalMatrixArray` classes. (#23)
  • Loading branch information
byrdie authored Jan 30, 2024
1 parent 63883c0 commit de84b53
Show file tree
Hide file tree
Showing 4 changed files with 320 additions and 0 deletions.
2 changes: 2 additions & 0 deletions named_arrays/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from ._vectors.cartesian.vectors_cartesian_nd import *
from ._vectors.vectors_spectral import *
from ._vectors.vectors_positional import *
from ._vectors.vectors_directional import *
from ._vectors.vectors_spectral_positional import *
from ._matrices.matrices import *
from ._matrices.cartesian.matrices_cartesian import *
Expand All @@ -21,5 +22,6 @@
from ._matrices.cartesian.matrices_cartesian_nd import *
from ._matrices.matrices_spectral import *
from ._matrices.matrices_positional import *
from ._matrices.matrices_directional import *
from ._matrices.matrices_spectral_positional import *
from ._functions.functions import *
51 changes: 51 additions & 0 deletions named_arrays/_matrices/matrices_directional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from __future__ import annotations
from typing import TypeVar, Generic, Type
import abc
import dataclasses
import named_arrays as na

__all__ = [
'AbstractDirectionalMatrixArray',
'DirectionalMatrixArray',
]

DirectionT = TypeVar('DirectionT', bound=na.AbstractVectorArray)


@dataclasses.dataclass(eq=False, repr=False)
class AbstractDirectionalMatrixArray(
na.AbstractCartesianMatrixArray,
na.AbstractDirectionalVectorArray,
):
@property
@abc.abstractmethod
def direction(self) -> na.AbstractVectorArray:
"""
The `direction` component of the matrix.
"""

@property
def type_abstract(self) -> Type[AbstractDirectionalMatrixArray]:
return AbstractDirectionalMatrixArray

@property
def type_explicit(self) -> Type[DirectionalMatrixArray]:
return DirectionalMatrixArray

@property
def type_vector(self) -> Type[na.DirectionalVectorArray]:
return na.DirectionalVectorArray

@property
def determinant(self) -> na.ScalarLike:
raise NotImplementedError


@dataclasses.dataclass(eq=False, repr=False)
class DirectionalMatrixArray(
na.DirectionalVectorArray,
AbstractDirectionalMatrixArray,
na.AbstractExplicitMatrixArray,
Generic[DirectionT],
):
pass
170 changes: 170 additions & 0 deletions named_arrays/_vectors/tests/test_vectors_directional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import pytest
import numpy as np
import astropy.units as u
import named_arrays as na
from . import test_vectors
from ..cartesian.tests import test_vectors_cartesian

_num_x = test_vectors._num_x
_num_y = test_vectors._num_y
_num_z = test_vectors._num_z
_num_distribution = test_vectors._num_distribution


def _directional_arrays() -> list[na.DirectionalVectorArray]:
return [
na.DirectionalVectorArray(direction=na.Cartesian2dVectorArray(1, 2) * u.deg),
na.DirectionalVectorArray(direction=na.Cartesian2dVectorLinearSpace(1, 2, axis="y", num=_num_y).explicit * u.deg),
]


def _directional_arrays_2() -> list[na.DirectionalVectorArray]:
return [
na.DirectionalVectorArray(direction=na.Cartesian2dVectorArray(3, 4) * u.deg),
na.DirectionalVectorArray(direction=na.Cartesian2dVectorArray(
x=na.NormalUncertainScalarArray(3, width=1) * u.deg,
y=na.NormalUncertainScalarArray(4, width=1) * u.deg,
))
]


def _directional_items() -> list[na.DirectionalVectorArray | dict[str, int | slice | na.DirectionalVectorArray]]:
return [
dict(y=0),
dict(y=slice(0, 1)),
dict(y=na.ScalarArrayRange(0, 2, axis='y')),
]


class AbstractTestAbstractDirectionalVectorArray(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray,
):
def test_direction(self, array: na.AbstractDirectionalVectorArray):
assert isinstance(na.as_named_array(array.direction), (na.AbstractScalar, na.AbstractVectorArray))

@pytest.mark.parametrize(
argnames='item',
argvalues=_directional_items(),
)
def test__getitem__(
self,
array: na.AbstractDirectionalVectorArray,
item: dict[str, int | slice | na.AbstractArray] | na.AbstractArray
):
super().test__getitem__(array=array, item=item)

@pytest.mark.parametrize('array_2', _directional_arrays_2())
class TestUfuncBinary(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestUfuncBinary
):
pass

@pytest.mark.parametrize('array_2', _directional_arrays_2())
class TestMatmul(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestMatmul
):
pass

class TestArrayFunctions(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestArrayFunctions
):

@pytest.mark.parametrize("array_2", _directional_arrays_2())
class TestAsArrayLikeFunctions(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestArrayFunctions.TestAsArrayLikeFunctions
):
pass

@pytest.mark.parametrize(
argnames='where',
argvalues=[
np._NoValue,
]
)
class TestReductionFunctions(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestArrayFunctions.TestReductionFunctions,
):
pass

@pytest.mark.parametrize(
argnames='q',
argvalues=[
25 * u.percent,
]
)
class TestPercentileLikeFunctions(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestArrayFunctions
.TestPercentileLikeFunctions,
):
pass

class TestNamedArrayFunctions(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestNamedArrayFunctions,
):
@pytest.mark.skip
class TestPltPlotLikeFunctions(
test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestNamedArrayFunctions.TestPltPlotLikeFunctions,
):
pass


@pytest.mark.parametrize("array", _directional_arrays())
class TestDirectionalVectorArray(
AbstractTestAbstractDirectionalVectorArray,
test_vectors_cartesian.AbstractTestAbstractExplicitCartesianVectorArray,
):
@pytest.mark.parametrize(
argnames="item",
argvalues=[
dict(y=0),
dict(y=slice(None)),
],
)
@pytest.mark.parametrize(
argnames="value",
argvalues=[
700 * u.nm,
]
)
def test__setitem__(
self,
array: na.ScalarArray,
item: dict[str, int | slice | na.ScalarArray] | na.ScalarArray,
value: float | na.ScalarArray
):
super().test__setitem__(array=array, item=item, value=value)


class AbstractTestAbstractImplicitDirectionalVectorArray(
AbstractTestAbstractDirectionalVectorArray,
test_vectors_cartesian.AbstractTestAbstractImplicitCartesianVectorArray,
):
pass


class AbstractTestAbstractParameterizedDirectionalVectorArray(
AbstractTestAbstractImplicitDirectionalVectorArray,
test_vectors_cartesian.AbstractTestAbstractParameterizedCartesianVectorArray,
):
pass


class AbstractTestAbstractDirectionalVectorSpace(
AbstractTestAbstractParameterizedDirectionalVectorArray,
test_vectors_cartesian.AbstractTestAbstractParameterizedCartesianVectorArray,
):
pass


def _directional_linear_spaces() -> list[na.DirectionalVectorLinearSpace]:
return [
na.DirectionalVectorLinearSpace(1 * u.m, 2 * u.m, axis="y", num=_num_y)
]


@pytest.mark.parametrize("array", _directional_linear_spaces())
class TestDirectionalVectorlinearSpace(
AbstractTestAbstractDirectionalVectorSpace,
test_vectors_cartesian.AbstractTestAbstractCartesianVectorLinearSpace,
):
pass
97 changes: 97 additions & 0 deletions named_arrays/_vectors/vectors_directional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from __future__ import annotations
from typing import Type, Generic, TypeVar
from typing_extensions import Self
import abc
import dataclasses
import named_arrays as na

__all__ = [
"AbstractDirectionalVectorArray",
"DirectionalVectorArray",
"AbstractImplicitDirectionalVectorArray",
"AbstractParameterizedDirectionalVectorArray",
"AbstractDirectionalVectorSpace",
"DirectionalVectorLinearSpace",
]

DirectionT = TypeVar("DirectionT", bound=na.ArrayLike)


@dataclasses.dataclass(eq=False, repr=False)
class AbstractDirectionalVectorArray(
na.AbstractCartesianVectorArray,
):

@property
@abc.abstractmethod
def direction(self) -> na.ArrayLike:
"""
The `direction` component of the vector.
"""

@property
def type_abstract(self) -> Type[na.AbstractArray]:
return AbstractDirectionalVectorArray

@property
def type_explicit(self) -> Type[na.AbstractExplicitArray]:
return DirectionalVectorArray

@property
def type_matrix(self) -> Type[na.DirectionalMatrixArray]:
return na.DirectionalMatrixArray


@dataclasses.dataclass(eq=False, repr=False)
class DirectionalVectorArray(
AbstractDirectionalVectorArray,
na.AbstractExplicitCartesianVectorArray,
Generic[DirectionT],
):
direction: DirectionT = 0

@classmethod
def from_scalar(
cls: Type[Self],
scalar: na.AbstractScalar,
like: None | na.AbstractExplicitVectorArray = None,
) -> DirectionalVectorArray:
result = super().from_scalar(scalar, like=like)
if result is not NotImplemented:
return result
return cls(direction=scalar)


@dataclasses.dataclass(eq=False, repr=False)
class AbstractImplicitDirectionalVectorArray(
AbstractDirectionalVectorArray,
na.AbstractImplicitCartesianVectorArray,
):

@property
def direction(self) -> na.ArrayLike:
return self.explicit.direction


@dataclasses.dataclass(eq=False, repr=False)
class AbstractParameterizedDirectionalVectorArray(
AbstractImplicitDirectionalVectorArray,
na.AbstractParameterizedVectorArray,
):
pass


@dataclasses.dataclass(eq=False, repr=False)
class AbstractDirectionalVectorSpace(
AbstractParameterizedDirectionalVectorArray,
na.AbstractVectorSpace,
):
pass


@dataclasses.dataclass(eq=False, repr=False)
class DirectionalVectorLinearSpace(
AbstractDirectionalVectorSpace,
na.AbstractVectorLinearSpace,
):
pass

0 comments on commit de84b53

Please sign in to comment.