diff --git a/named_arrays/__init__.py b/named_arrays/__init__.py index 3d58aec2..038593fa 100644 --- a/named_arrays/__init__.py +++ b/named_arrays/__init__.py @@ -16,6 +16,7 @@ from ._vectors.vectors_positional import * from ._vectors.vectors_directional import * from ._vectors.vectors_spectral_positional import * +from ._vectors.vectors_spectral_directional import * from ._matrices.matrices import * from ._matrices.cartesian.matrices_cartesian import * from ._matrices.cartesian.matrices_cartesian_2d import * @@ -26,4 +27,5 @@ from ._matrices.matrices_positional import * from ._matrices.matrices_directional import * from ._matrices.matrices_spectral_positional import * +from ._matrices.matrices_spectral_directional import * from ._functions.functions import * diff --git a/named_arrays/_matrices/matrices_spectral_directional.py b/named_arrays/_matrices/matrices_spectral_directional.py new file mode 100644 index 00000000..f0dabace --- /dev/null +++ b/named_arrays/_matrices/matrices_spectral_directional.py @@ -0,0 +1,41 @@ +from __future__ import annotations +from typing import Type + +import dataclasses +import named_arrays as na + +__all__ = [ + 'AbstractSpectralDirectionalMatrixArray', + 'SpectralDirectionalMatrixArray', +] + + +@dataclasses.dataclass(eq=False, repr=False) +class AbstractSpectralDirectionalMatrixArray( + na.AbstractSpectralDirectionalVectorArray, +): + + @property + def type_abstract(self) -> Type[AbstractSpectralDirectionalMatrixArray]: + return AbstractSpectralDirectionalMatrixArray + + @property + def type_explicit(self) -> Type[SpectralDirectionalMatrixArray]: + return SpectralDirectionalMatrixArray + + @property + def type_vector(self) -> Type[na.SpectralDirectionalVectorArray]: + return na.SpectralDirectionalVectorArray + + @property + def determinant(self) -> na.ScalarLike: + return NotImplementedError + + +@dataclasses.dataclass(eq=False, repr=False) +class SpectralDirectionalMatrixArray( + na.SpectralDirectionalVectorArray, + AbstractSpectralDirectionalMatrixArray, + na.AbstractExplicitMatrixArray, +): + pass diff --git a/named_arrays/_vectors/tests/test_vectors_spectral_directional.py b/named_arrays/_vectors/tests/test_vectors_spectral_directional.py new file mode 100644 index 00000000..7919caf7 --- /dev/null +++ b/named_arrays/_vectors/tests/test_vectors_spectral_directional.py @@ -0,0 +1,189 @@ +import pytest +import numpy as np +import astropy.units as u +import named_arrays as na +from ..cartesian.tests import test_vectors_cartesian + +_num_x = test_vectors_cartesian._num_x +_num_y = test_vectors_cartesian._num_y +_num_z = test_vectors_cartesian._num_z +_num_distribution = test_vectors_cartesian._num_distribution + + +def _spectral_directional_arrays() -> list[na.SpectralDirectionalVectorArray]: + return [ + na.SpectralDirectionalVectorArray( + wavelength=500 * u.nm, + direction=na.Cartesian2dVectorArray(1, 2) * u.mm, + ), + na.SpectralDirectionalVectorArray( + wavelength=na.linspace(400, 600, axis="y", num=_num_y) * u.nm, + direction=na.Cartesian2dVectorLinearSpace(1, 2, axis="y", num=_num_y).explicit * u.mm, + ), + ] + + +def _spectral_directional_arrays_2() -> list[na.SpectralDirectionalVectorArray]: + return [ + na.SpectralDirectionalVectorArray( + wavelength=400 * u.nm, + direction=na.Cartesian2dVectorArray(3, 4) * u.m, + ), + na.SpectralDirectionalVectorArray( + wavelength=na.NormalUncertainScalarArray(400 * u.nm, width=1 * u.nm), + direction=na.Cartesian2dVectorArray( + x=na.NormalUncertainScalarArray(3, width=1) * u.m, + y=na.NormalUncertainScalarArray(4, width=1) * u.m, + ) + ) + ] + + +def _spectral_directional_items() -> list[na.AbstractArray | dict[str, int | slice | na.AbstractArray]]: + return [ + dict(y=0), + dict(y=slice(0, 1)), + dict(y=na.ScalarArrayRange(0, 2, axis='y')), + ] + + +class AbstractTestAbstractSpectralDirectionalVectorArray( + test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray, +): + + @pytest.mark.parametrize( + argnames='item', + argvalues=_spectral_directional_items() + ) + def test__getitem__( + self, + array: na.AbstractSpectralVectorArray, + item: dict[str, int | slice | na.AbstractArray] | na.AbstractArray + ): + super().test__getitem__(array=array, item=item) + + @pytest.mark.parametrize('array_2', _spectral_directional_arrays_2()) + class TestUfuncBinary( + test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestUfuncBinary + ): + pass + + @pytest.mark.parametrize('array_2', _spectral_directional_arrays_2()) + class TestMatmul( + test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestMatmul, + ): + pass + + class TestArrayFunctions( + test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestArrayFunctions, + ): + + @pytest.mark.parametrize("array_2", _spectral_directional_arrays_2()) + class TestAsArrayLikeFunctions( + test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestArrayFunctions.TestAsArrayLikeFunctions, + ): + pass + + @pytest.mark.parametrize( + argnames='where', + argvalues=[ + np._NoValue, + True, + na.ScalarArray(True), + ] + ) + class TestReductionFunctions( + test_vectors_cartesian.AbstractTestAbstractCartesianVectorArray.TestArrayFunctions.TestReductionFunctions, + ): + pass + + @pytest.mark.parametrize( + argnames='q', + argvalues=[ + .25, + 25 * u.percent, + na.ScalarLinearSpace(.25, .75, axis='q', num=3, endpoint=True), + ] + ) + 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", _spectral_directional_arrays()) +class TestSpectralDirectionalVectorArray( + AbstractTestAbstractSpectralDirectionalVectorArray, + 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 AbstractTestAbstractImplicitSpectralDirectionalVectorArray( + AbstractTestAbstractSpectralDirectionalVectorArray, + test_vectors_cartesian.AbstractTestAbstractImplicitCartesianVectorArray, +): + pass + + +class AbstractTestAbstractParameterizedSpectralDirectionalVectorArray( + AbstractTestAbstractImplicitSpectralDirectionalVectorArray, + test_vectors_cartesian.AbstractTestAbstractParameterizedCartesianVectorArray, +): + pass + + +class AbstractTestAbstractSpectralDirectionalVectorSpace( + AbstractTestAbstractParameterizedSpectralDirectionalVectorArray, + test_vectors_cartesian.AbstractTestAbstractCartesianVectorSpace, +): + pass + + +def _spectral_directional_linear_spaces() -> list[na.SpectralDirectionalVectorLinearSpace]: + return [ + na.SpectralDirectionalVectorLinearSpace( + start=400 * u.nm, + stop=600 * u.nm, + axis="y", + num=_num_y, + ) + ] + + +@pytest.mark.parametrize("array", _spectral_directional_linear_spaces()) +class TestSpectralDirectionalVectorLinearSpace( + AbstractTestAbstractSpectralDirectionalVectorSpace, + test_vectors_cartesian.AbstractTestAbstractCartesianVectorLinearSpace, +): + pass diff --git a/named_arrays/_vectors/vectors_spectral_directional.py b/named_arrays/_vectors/vectors_spectral_directional.py new file mode 100644 index 00000000..6cd218c7 --- /dev/null +++ b/named_arrays/_vectors/vectors_spectral_directional.py @@ -0,0 +1,85 @@ +from __future__ import annotations +from typing import Type, TypeVar +from typing_extensions import Self +import dataclasses +import named_arrays as na + +__all__ = [ + 'AbstractSpectralDirectionalVectorArray', + 'SpectralDirectionalVectorArray', + 'AbstractImplicitSpectralDirectionalVectorArray', + 'AbstractParameterizedSpectralDirectionalVectorArray', + 'AbstractSpectralDirectionalVectorSpace', + 'SpectralDirectionalVectorLinearSpace', +] + +DirectionT = TypeVar("DirectionT", bound=na.ArrayLike) +WavelengthT = TypeVar("WavelengthT", bound=na.ScalarLike) + + +@dataclasses.dataclass(eq=False, repr=False) +class AbstractSpectralDirectionalVectorArray( + na.AbstractDirectionalVectorArray, + na.AbstractSpectralVectorArray, +): + + @property + def type_abstract(self) -> Type[na.AbstractArray]: + return AbstractSpectralDirectionalVectorArray + + @property + def type_explicit(self) -> Type[na.AbstractExplicitArray]: + return SpectralDirectionalVectorArray + + @property + def type_matrix(self) -> Type[na.SpectralDirectionalMatrixArray]: + return na.SpectralDirectionalMatrixArray + + +@dataclasses.dataclass(eq=False, repr=False) +class SpectralDirectionalVectorArray( + AbstractSpectralDirectionalVectorArray, + na.DirectionalVectorArray[DirectionT], + na.SpectralVectorArray[WavelengthT], +): + + @classmethod + def from_scalar( + cls: Type[Self], + scalar: na.AbstractScalar, + like: None | na.AbstractExplicitVectorArray = None, + ) -> SpectralDirectionalVectorArray: + return cls(wavelength=scalar, direction=scalar) + + +@dataclasses.dataclass(eq=False, repr=False) +class AbstractImplicitSpectralDirectionalVectorArray( + AbstractSpectralDirectionalVectorArray, + na.AbstractImplicitDirectionalVectorArray, + na.AbstractImplicitSpectralVectorArray, +): + pass + + +@dataclasses.dataclass(eq=False, repr=False) +class AbstractParameterizedSpectralDirectionalVectorArray( + AbstractImplicitSpectralDirectionalVectorArray, + na.AbstractParameterizedVectorArray, +): + pass + + +@dataclasses.dataclass(eq=False, repr=False) +class AbstractSpectralDirectionalVectorSpace( + AbstractParameterizedSpectralDirectionalVectorArray, + na.AbstractVectorSpace, +): + pass + + +@dataclasses.dataclass(eq=False, repr=False) +class SpectralDirectionalVectorLinearSpace( + AbstractSpectralDirectionalVectorSpace, + na.AbstractVectorLinearSpace, +): + pass