From 7fa0859c4a4aab00d98221e62b59b37705eecfa8 Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 23:10:36 -0500 Subject: [PATCH 01/10] feat: AbstractVectorDifferential Signed-off-by: nstarman --- src/vector/_base.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/vector/_base.py b/src/vector/_base.py index 388a154b..5474f6b3 100644 --- a/src/vector/_base.py +++ b/src/vector/_base.py @@ -1,19 +1,34 @@ """Representation of coordinates in different systems.""" -__all__ = ["AbstractVector"] +__all__ = ["AbstractVector", "AbstractVectorDifferential"] from typing import Any, TypeVar import equinox as eqx T = TypeVar("T", bound="AbstractVector") +DT = TypeVar("DT", bound="AbstractVectorDifferential") class AbstractVector(eqx.Module): # type: ignore[misc] """Abstract representation of coordinates in different systems.""" - def represent_as(self, target: type[T], **kwargs: Any) -> T: + def represent_as(self, target: type[T], /, **kwargs: Any) -> T: """Represent the vector as another type.""" from ._transform import represent_as # pylint: disable=import-outside-toplevel return represent_as(self, target, **kwargs) + + +class AbstractVectorDifferential(eqx.Module): # type: ignore[misc] + """Abstract representation of vector differentials in different systems.""" + + vector_cls: eqx.AbstractClassVar[type[AbstractVector]] + + def represent_as( + self, target: type[DT], position: AbstractVector, /, **kwargs: Any + ) -> DT: + """Represent the vector as another type.""" + from ._transform import represent_as # pylint: disable=import-outside-toplevel + + return represent_as(self, target, position, **kwargs) From 51495bc2816f50ebcff0bb3519c1c12190b813d2 Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 15:24:12 -0500 Subject: [PATCH 02/10] feat: Abstract1DVectorDifferential Signed-off-by: nstarman --- src/vector/_d1/base.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vector/_d1/base.py b/src/vector/_d1/base.py index 7c508568..aaab2c8e 100644 --- a/src/vector/_d1/base.py +++ b/src/vector/_d1/base.py @@ -1,13 +1,18 @@ """Representation of coordinates in different systems.""" -__all__ = ["Abstract1DVector"] +__all__ = ["Abstract1DVector", "Abstract1DVectorDifferential"] -from typing import TypeVar -from vector._base import AbstractVector +import equinox as eqx -T = TypeVar("T", bound="AbstractVector") +from vector._base import AbstractVector, AbstractVectorDifferential class Abstract1DVector(AbstractVector): """Abstract representation of 1D coordinates in different systems.""" + + +class Abstract1DVectorDifferential(AbstractVectorDifferential): + """Abstract representation of 1D differentials in different systems.""" + + vector_cls: eqx.AbstractClassVar[type[Abstract1DVector]] From 7eadea63cc0597dc8f81173c77ae27e806f7fd07 Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 15:25:19 -0500 Subject: [PATCH 03/10] feat: CartesianDifferential1D, RadialDifferential Signed-off-by: nstarman --- src/vector/_d1/builtin.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/vector/_d1/builtin.py b/src/vector/_d1/builtin.py index edfdd68a..c17e11c8 100644 --- a/src/vector/_d1/builtin.py +++ b/src/vector/_d1/builtin.py @@ -4,16 +4,19 @@ # Position "Cartesian1DVector", "RadialVector", + # Differential + "CartesianDifferential1D", + "RadialDifferential", ] -from typing import final +from typing import ClassVar, final import equinox as eqx from vector._typing import BatchFloatScalarQ from vector._utils import converter_quantity_array -from .base import Abstract1DVector +from .base import Abstract1DVector, Abstract1DVectorDifferential ############################################################################## # Position @@ -33,3 +36,27 @@ class RadialVector(Abstract1DVector): r: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) """Radial coordinate.""" + + +############################################################################## +# Velocity + + +@final +class CartesianDifferential1D(Abstract1DVectorDifferential): + """Cartesian differential representation.""" + + d_x: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + """Differential d_x/d_<>.""" + + vector_cls: ClassVar[type[Cartesian1DVector]] = Cartesian1DVector # type: ignore[misc] + + +@final +class RadialDifferential(Abstract1DVectorDifferential): + """Radial differential representation.""" + + d_r: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + """Differential d_r/d_<>.""" + + vector_cls: ClassVar[type[RadialVector]] = RadialVector # type: ignore[misc] From f4fb6f70499da152443ac4eb12915e27d220d78d Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 17:16:00 -0500 Subject: [PATCH 04/10] feat: Abstract2DVectorDifferential Signed-off-by: nstarman --- src/vector/_d2/base.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vector/_d2/base.py b/src/vector/_d2/base.py index ed8992bf..563f27c5 100644 --- a/src/vector/_d2/base.py +++ b/src/vector/_d2/base.py @@ -1,13 +1,18 @@ """Representation of coordinates in different systems.""" -__all__ = ["Abstract2DVector"] +__all__ = ["Abstract2DVector", "Abstract2DVectorDifferential"] -from typing import TypeVar -from vector._base import AbstractVector +import equinox as eqx -T = TypeVar("T", bound="AbstractVector") +from vector._base import AbstractVector, AbstractVectorDifferential class Abstract2DVector(AbstractVector): """Abstract representation of 2D coordinates in different systems.""" + + +class Abstract2DVectorDifferential(AbstractVectorDifferential): + """Abstract representation of 2D vector differentials.""" + + vector_cls: eqx.AbstractClassVar[type[Abstract2DVector]] From 9e5698b4443a2cbac8b6ac44b85c4bea13b33f2b Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 17:20:49 -0500 Subject: [PATCH 05/10] feat: CartesianDifferential2D, PolarDifferential Signed-off-by: nstarman --- src/vector/_d2/builtin.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/vector/_d2/builtin.py b/src/vector/_d2/builtin.py index 49646f02..03383014 100644 --- a/src/vector/_d2/builtin.py +++ b/src/vector/_d2/builtin.py @@ -1,20 +1,24 @@ """Built-in vector classes.""" __all__ = [ + # Position "Cartesian2DVector", "PolarVector", # "LnPolarVector", # "Log10PolarVector", + # Differential + "CartesianDifferential2D", + "PolarDifferential", ] -from typing import final +from typing import ClassVar, final import equinox as eqx from vector._typing import BatchFloatScalarQ from vector._utils import converter_quantity_array -from .base import Abstract2DVector +from .base import Abstract2DVector, Abstract2DVectorDifferential # ============================================================================= # 2D @@ -51,3 +55,26 @@ class PolarVector(Abstract2DVector): # log10r: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) # theta: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + + +############################################################################## + + +@final +class CartesianDifferential2D(Abstract2DVectorDifferential): + """Cartesian differential representation.""" + + d_x: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_y: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + + vector_cls: ClassVar[type[Cartesian2DVector]] = Cartesian2DVector # type: ignore[misc] + + +@final +class PolarDifferential(Abstract2DVectorDifferential): + """Polar differential representation.""" + + d_r: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_phi: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + + vector_cls: ClassVar[type[PolarVector]] = PolarVector # type: ignore[misc] From 712c85aae09ec3f32f383e94f5b21d8efbc6e8c6 Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 15:25:46 -0500 Subject: [PATCH 06/10] feat: Abstract3DVectorDifferential Signed-off-by: nstarman --- src/vector/_d3/base.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vector/_d3/base.py b/src/vector/_d3/base.py index 363141f7..c0f143eb 100644 --- a/src/vector/_d3/base.py +++ b/src/vector/_d3/base.py @@ -1,13 +1,18 @@ """Representation of coordinates in different systems.""" -__all__ = ["Abstract3DVector"] +__all__ = ["Abstract3DVector", "Abstract3DVectorDifferential"] -from typing import TypeVar -from vector._base import AbstractVector +import equinox as eqx -T = TypeVar("T", bound="AbstractVector") +from vector._base import AbstractVector, AbstractVectorDifferential class Abstract3DVector(AbstractVector): """Abstract representation of 3D coordinates in different systems.""" + + +class Abstract3DVectorDifferential(AbstractVectorDifferential): + """Abstract representation of 3D vector differentials.""" + + vector_cls: eqx.AbstractClassVar[type[Abstract3DVector]] From 86fb46d2b624a206650a7897a5264491971311aa Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 15:27:44 -0500 Subject: [PATCH 07/10] feat: CartesianDifferential3D, SphericalDifferential, CylindricalDifferential Signed-off-by: nstarman --- src/vector/_d3/builtin.py | 46 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/vector/_d3/builtin.py b/src/vector/_d3/builtin.py index 9f0bda8a..13f07fdb 100644 --- a/src/vector/_d3/builtin.py +++ b/src/vector/_d3/builtin.py @@ -1,19 +1,24 @@ """Built-in vector classes.""" __all__ = [ + # Position "Cartesian3DVector", "SphericalVector", "CylindricalVector", + # Differential + "CartesianDifferential3D", + "SphericalDifferential", + "CylindricalDifferential", ] -from typing import final +from typing import ClassVar, final import equinox as eqx from vector._typing import BatchFloatScalarQ from vector._utils import converter_quantity_array -from .base import Abstract3DVector +from .base import Abstract3DVector, Abstract3DVectorDifferential ############################################################################## # Position @@ -44,3 +49,40 @@ class CylindricalVector(Abstract3DVector): rho: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) phi: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) z: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + + +############################################################################## +# Differential + + +@final +class CartesianDifferential3D(Abstract3DVectorDifferential): + """Cartesian differential representation.""" + + d_x: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_y: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_z: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + + vector_cls: ClassVar[type[Cartesian3DVector]] = Cartesian3DVector # type: ignore[misc] + + +@final +class SphericalDifferential(Abstract3DVectorDifferential): + """Spherical differential representation.""" + + d_r: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_theta: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_phi: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + + vector_cls: ClassVar[type[SphericalVector]] = SphericalVector # type: ignore[misc] + + +@final +class CylindricalDifferential(Abstract3DVectorDifferential): + """Cylindrical differential representation.""" + + d_rho: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_phi: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + d_z: BatchFloatScalarQ = eqx.field(converter=converter_quantity_array) + + vector_cls: ClassVar[type[CylindricalVector]] = CylindricalVector # type: ignore[misc] From da1dd8d9a16c5d7d496eab226e4b1fb15bfc822c Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 16:42:15 -0500 Subject: [PATCH 08/10] feat: support some differential transformations Signed-off-by: nstarman --- src/vector/_transform.py | 120 +++++++++++++++++++++++++++++++++++++-- src/vector/_utils.py | 15 ++++- 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/src/vector/_transform.py b/src/vector/_transform.py index 735d654b..a74bd3be 100644 --- a/src/vector/_transform.py +++ b/src/vector/_transform.py @@ -2,20 +2,130 @@ __all__ = ["represent_as"] +from dataclasses import replace from typing import Any from warnings import warn import array_api_jax_compat as xp import astropy.units as u +import jax from jax_quantity import Quantity from plum import dispatch -from ._d1.builtin import Cartesian1DVector, RadialVector -from ._d2.base import Abstract2DVector # pylint: disable=cyclic-import -from ._d2.builtin import Cartesian2DVector, PolarVector -from ._d3.base import Abstract3DVector -from ._d3.builtin import Cartesian3DVector, CylindricalVector, SphericalVector +from ._base import AbstractVector, AbstractVectorDifferential +from ._d1.base import Abstract1DVectorDifferential +from ._d1.builtin import ( + Cartesian1DVector, + CartesianDifferential1D, + RadialDifferential, + RadialVector, +) +from ._d2.base import Abstract2DVector, Abstract2DVectorDifferential +from ._d2.builtin import ( + Cartesian2DVector, + CartesianDifferential2D, + PolarDifferential, + PolarVector, +) +from ._d3.base import Abstract3DVector, Abstract3DVectorDifferential +from ._d3.builtin import ( + Cartesian3DVector, + CartesianDifferential3D, + CylindricalDifferential, + CylindricalVector, + SphericalDifferential, + SphericalVector, +) from ._exceptions import IrreversibleDimensionChange +from ._utils import fields_and_values + + +# TODO: implement for cross-representations +@dispatch.multi( + # N-D -> N-D + ( + Abstract1DVectorDifferential, + type[Abstract1DVectorDifferential], + AbstractVector, + ), + ( + Abstract2DVectorDifferential, + type[Abstract2DVectorDifferential], + AbstractVector, + ), + ( + Abstract3DVectorDifferential, + type[Abstract3DVectorDifferential], + AbstractVector, + ), +) +def represent_as( + current: AbstractVectorDifferential, + target: type[AbstractVectorDifferential], + position: AbstractVector, + /, + **kwargs: Any, +) -> AbstractVectorDifferential: + """Abstract3DVectorDifferential -> Cartesian -> Abstract3DVectorDifferential. + + This is the base case for the transformation of 1D vector differentials. + """ + # Start by transforming the position to the type required by the + # differential to construct the Jacobian. + current_position = represent_as(position, current.vector_cls, **kwargs) + + # Takes the Jacobian through the representation transformation function. This + # returns a representation of the target type, where the value of each field the + # corresponding row of the Jacobian. The value of the field is a Quantity with + # the correct numerator unit (of the Jacobian row). The value is a Vector of the + # original type, with fields that are the columns of that row, but with only the + # denomicator's units. + jac_nested_vecs = jax.jacfwd(represent_as)(current_position, target.vector_cls) + + # This changes the Jacobian to be a dictionary of each row, with the value + # being that row's column as a dictionary, now with the correct units for + # each element: {row_i: {col_j: Quantity(value, row.unit / column.unit)}} + jac_rows = { + f"d_{f.name}": { + ff.name: replace(vv, unit=v.unit / vv.unit) + for ff, vv in fields_and_values(v.value) + } + for f, v in fields_and_values(jac_nested_vecs) + } + + # Now we can use the Jacobian to transform the differential. + return target( + **{ # Each field is the dot product of the row of the J and the diff. + k: xp.sum( # Doing the dot product. + xp.asarray( + [j_c * getattr(current, f"d_{kk}") for kk, j_c in j_r.items()] + ), + ) + for k, j_r in jac_rows.items() + } + ) + + +# Self transform +@dispatch.multi( + (CartesianDifferential1D, type[CartesianDifferential1D], AbstractVector), + (RadialDifferential, type[RadialDifferential], AbstractVector), + (CartesianDifferential2D, type[CartesianDifferential2D], AbstractVector), + (PolarDifferential, type[PolarDifferential], AbstractVector), + (CartesianDifferential3D, type[CartesianDifferential3D], AbstractVector), + (SphericalDifferential, type[SphericalDifferential], AbstractVector), + (CylindricalDifferential, type[CylindricalDifferential], AbstractVector), +) +def represent_as( + current: AbstractVectorDifferential, + target: type[AbstractVectorDifferential], + position: AbstractVector, + /, + **kwargs: Any, +) -> AbstractVectorDifferential: + """Self transform.""" + return current + ############################################################################### # 1D diff --git a/src/vector/_utils.py b/src/vector/_utils.py index b77b1543..2e4b94bd 100644 --- a/src/vector/_utils.py +++ b/src/vector/_utils.py @@ -2,8 +2,10 @@ __all__: list[str] = [] +from collections.abc import Iterator +from dataclasses import Field, fields from functools import singledispatch -from typing import Any +from typing import TYPE_CHECKING, Any import array_api_jax_compat as xp import astropy.units as u @@ -12,6 +14,9 @@ from jax_quantity import Quantity from jaxtyping import Array, Float, Shaped +if TYPE_CHECKING: + from _typeshed import DataclassInstance + @singledispatch def converter_quantity_array(x: Any, /) -> Float[Quantity, "*shape"]: @@ -33,3 +38,11 @@ def _convert_jax_array(x: Shaped[Array, "*shape"], /) -> Float[Quantity, "*shape dtype = jnp.promote_types(x.dtype, canonicalize_dtype(float)) x = xp.asarray(x, dtype=dtype) return Quantity(x, u.one) + + +# ============================================================================ + + +def fields_and_values(obj: "DataclassInstance") -> Iterator[tuple[Field[Any], Any]]: + """Return the fields and values of a dataclass instance.""" + return ((f, getattr(obj, f.name)) for f in fields(obj)) From 3935f5168e2d3ff59d5fd869165e96ceb5bc1674 Mon Sep 17 00:00:00 2001 From: nstarman Date: Mon, 19 Feb 2024 23:08:33 -0500 Subject: [PATCH 09/10] tests: add Signed-off-by: nstarman --- tests/test_base.py | 74 ++++- tests/test_builtin.py | 664 ------------------------------------------ tests/test_d1.py | 425 +++++++++++++++++++++++++++ tests/test_d2.py | 390 +++++++++++++++++++++++++ tests/test_d3.py | 292 +++++++++++++++++++ 5 files changed, 1173 insertions(+), 672 deletions(-) delete mode 100644 tests/test_builtin.py create mode 100644 tests/test_d1.py create mode 100644 tests/test_d2.py create mode 100644 tests/test_d3.py diff --git a/tests/test_base.py b/tests/test_base.py index 4c818aba..2c632be4 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -7,18 +7,27 @@ from vector import ( Abstract1DVector, + Abstract1DVectorDifferential, Abstract2DVector, + Abstract2DVectorDifferential, Abstract3DVector, + Abstract3DVectorDifferential, AbstractVector, + AbstractVectorDifferential, Cartesian1DVector, Cartesian2DVector, Cartesian3DVector, + CartesianDifferential1D, + CartesianDifferential2D, + CartesianDifferential3D, + CylindricalDifferential, CylindricalVector, IrreversibleDimensionChange, - # LnPolarVector, - # Log10PolarVector, + PolarDifferential, PolarVector, + RadialDifferential, RadialVector, + SphericalDifferential, SphericalVector, ) @@ -37,6 +46,21 @@ CylindricalVector, ] +BUILTIN_DIFFERENTIALS = [ + # 1D + CartesianDifferential1D, + RadialDifferential, + # 2D + CartesianDifferential2D, + PolarDifferential, + # LnPolarDifferential, + # Log10PolarDifferential, + # 3D + CartesianDifferential3D, + SphericalDifferential, + CylindricalDifferential, +] + def context_dimension_reduction( vector: AbstractVector, target: type[AbstractVector] @@ -78,13 +102,47 @@ def test_represent_as(self, vector, target): assert isinstance(newvec, target) -class Abstract1DVectorTest(AbstractVectorTest): - """Test :class:`vector.Abstract1DVector`.""" +class AbstractVectorDifferentialTest: + """Test :class:`vector.AbstractVectorDifferential`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: # noqa: PT004 + """Return a vector.""" + raise NotImplementedError + + @pytest.fixture(scope="class") + def difntl(self) -> AbstractVectorDifferential: # noqa: PT004 + """Return a vector.""" + raise NotImplementedError + @pytest.mark.parametrize("target", BUILTIN_DIFFERENTIALS) + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_represent_as(self, difntl, target, vector): + """Test :meth:`AbstractVector.represent_as`. -class Abstract2DVectorTest(AbstractVectorTest): - """Test :class:`vector.Abstract2DVector`.""" + This just tests that the machiner works. + """ + # TODO: have all the convertsions + if ( + ( + isinstance(difntl, Abstract1DVectorDifferential) + and not issubclass(target, Abstract1DVectorDifferential) + ) + or ( + isinstance(difntl, Abstract2DVectorDifferential) + and not issubclass(target, Abstract2DVectorDifferential) + ) + or ( + isinstance(difntl, Abstract3DVectorDifferential) + and not issubclass(target, Abstract3DVectorDifferential) + ) + ): + pytest.xfail("Not implemented yet") + # Perform the conversion. + # Detecting whether the conversion reduces the dimensionality. + with context_dimension_reduction(vector, target.vector_cls): + newdif = difntl.represent_as(target, vector) -class Abstract3DVectorTest(AbstractVectorTest): - """Test :class:`vector.Abstract3DVector`.""" + # Test + assert isinstance(newdif, target) diff --git a/tests/test_builtin.py b/tests/test_builtin.py deleted file mode 100644 index f98e4d63..00000000 --- a/tests/test_builtin.py +++ /dev/null @@ -1,664 +0,0 @@ -"""Test :mod:`vector._builtin`.""" - -import contextlib -from contextlib import AbstractContextManager - -import astropy.units as u -import pytest -from jax_quantity import Quantity - -from vector import ( - Abstract1DVector, - Abstract2DVector, - Abstract3DVector, - AbstractVector, - Cartesian1DVector, - Cartesian2DVector, - Cartesian3DVector, - CylindricalVector, - IrreversibleDimensionChange, - # LnPolarVector, - # Log10PolarVector, - PolarVector, - RadialVector, - SphericalVector, -) - -from .test_base import Abstract1DVectorTest - - -def context_dimension_reduction(vector, target) -> AbstractContextManager: - context: AbstractContextManager - if ( - isinstance(vector, Abstract2DVector) and issubclass(target, Abstract1DVector) - ) or ( - isinstance(vector, Abstract3DVector) - and issubclass(target, Abstract2DVector | Abstract1DVector) - ): - context = pytest.warns(IrreversibleDimensionChange) - else: - context = contextlib.nullcontext() - return context - - -class TestCartesian1DVector(Abstract1DVectorTest): - """Test :class:`vector.Cartesian1DVector`.""" - - @pytest.fixture(scope="class") - def vector(self) -> AbstractVector: - """Return a vector.""" - from vector import Cartesian1DVector - - return Cartesian1DVector(x=Quantity([1, 2, 3, 4], u.kpc)) - - # ========================================================================== - # represent_as - - def test_cartesian1d_to_cartesian1d(self, vector): - """Test ``vector.represent_as(Cartesian1DVector)``.""" - newvec = vector.represent_as(Cartesian1DVector) - assert newvec is vector - - def test_cartesian1d_to_radial(self, vector): - """Test ``vector.represent_as(RadialVector)``.""" - radial = vector.represent_as(RadialVector) - - assert isinstance(radial, RadialVector) - assert radial.r == Quantity([1, 2, 3, 4], u.kpc) - - def test_cartesian1d_to_cartesian2d(self, vector): - """Test ``vector.represent_as(Cartesian2DVector)``.""" - cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) - - assert isinstance(cart2d, Cartesian2DVector) - assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart2d.y == Quantity([5, 6, 7, 8], u.km) - - def test_cartesian1d_to_polar(self, vector): - """Test ``vector.represent_as(PolarVector)``.""" - polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) - - assert isinstance(polar, PolarVector) - assert polar.r == Quantity([1, 2, 3, 4], u.kpc) - assert polar.phi == Quantity([0, 1, 2, 3], u.rad) - - # def test_cartesian1d_to_lnpolar(self, vector): - # """Test ``vector.represent_as(LnPolarVector)``.""" - # lnpolar = vector.to_lnpolar(phi=Quantity([0, 1, 2, 3], u.rad)) - - # assert isinstance(lnpolar, LnPolarVector) - # assert lnpolar.lnr == xp.log(Quantity([1, 2, 3, 4], u.kpc)) - # assert lnpolar.phi == Quantity([0, 1, 2, 3], u.rad) - - # def test_cartesian1d_to_log10polar(self, vector): - # """Test ``vector.represent_as(Log10PolarVector)``.""" - # log10polar = vector.to_log10polar(phi=Quantity([0, 1, 2, 3], u.rad)) - - # assert isinstance(log10polar, Log10PolarVector) - # assert log10polar.log10r == xp.log10(Quantity([1, 2, 3, 4], u.kpc)) - # assert log10polar.phi == Quantity([0, 1, 2, 3], u.rad) - - def test_cartesian1d_to_cartesian3d(self, vector): - """Test ``vector.represent_as(Cartesian3DVector)``.""" - cart3d = vector.represent_as( - Cartesian3DVector, - y=Quantity([5, 6, 7, 8], u.km), - z=Quantity([9, 10, 11, 12], u.m), - ) - - assert isinstance(cart3d, Cartesian3DVector) - assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart3d.y == Quantity([5, 6, 7, 8], u.km) - assert cart3d.z == Quantity([9, 10, 11, 12], u.m) - - def test_cartesian1d_to_spherical(self, vector): - """Test ``vector.represent_as(SphericalVector)``.""" - spherical = vector.represent_as( - SphericalVector, - phi=Quantity([0, 1, 2, 3], u.rad), - theta=Quantity([4, 5, 6, 7], u.rad), - ) - - assert isinstance(spherical, SphericalVector) - assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) - assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) - assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) - - def test_cartesian1d_to_cylindrical(self, vector): - """Test ``vector.represent_as(CylindricalVector)``.""" - cylindrical = vector.represent_as( - CylindricalVector, - phi=Quantity([0, 1, 2, 3], u.rad), - z=Quantity([4, 5, 6, 7], u.m), - ) - - assert isinstance(cylindrical, CylindricalVector) - assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) - assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) - assert cylindrical.z == Quantity([4, 5, 6, 7], u.m) - - -class TestRadialVector(Abstract1DVectorTest): - """Test :class:`vector.RadialVector`.""" - - @pytest.fixture(scope="class") - def vector(self) -> AbstractVector: - """Return a vector.""" - from vector import RadialVector - - return RadialVector(r=Quantity([1, 2, 3, 4], u.kpc)) - - # ========================================================================== - # represent_as - - def test_radial_to_cartesian1d(self, vector): - """Test ``vector.represent_as(Cartesian1DVector)``.""" - cart1d = vector.represent_as(Cartesian1DVector) - - assert isinstance(cart1d, Cartesian1DVector) - assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) - - def test_radial_to_radial(self, vector): - """Test ``vector.represent_as(RadialVector)``.""" - newvec = vector.represent_as(RadialVector) - assert newvec is vector - - def test_radial_to_cartesian2d(self, vector): - """Test ``vector.represent_as(Cartesian2DVector)``.""" - cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) - - assert isinstance(cart2d, Cartesian2DVector) - assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart2d.y == Quantity([5, 6, 7, 8], u.km) - - def test_radial_to_polar(self, vector): - """Test ``vector.represent_as(PolarVector)``.""" - polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) - - assert isinstance(polar, PolarVector) - assert polar.r == Quantity([1, 2, 3, 4], u.kpc) - assert polar.phi == Quantity([0, 1, 2, 3], u.rad) - - # def test_radial_to_lnpolar(self, vector): - # """Test ``vector.represent_as(LnPolarVector)``.""" - # assert False - - # def test_radial_to_log10polar(self, vector): - # """Test ``vector.represent_as(Log10PolarVector)``.""" - # assert False - - def test_radial_to_cartesian3d(self, vector): - """Test ``vector.represent_as(Cartesian3DVector)``.""" - cart3d = vector.represent_as( - Cartesian3DVector, - y=Quantity([5, 6, 7, 8], u.km), - z=Quantity([9, 10, 11, 12], u.m), - ) - - assert isinstance(cart3d, Cartesian3DVector) - assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart3d.y == Quantity([5, 6, 7, 8], u.km) - assert cart3d.z == Quantity([9, 10, 11, 12], u.m) - - def test_radial_to_spherical(self, vector): - """Test ``vector.represent_as(SphericalVector)``.""" - spherical = vector.represent_as( - SphericalVector, - phi=Quantity([0, 1, 2, 3], u.rad), - theta=Quantity([4, 5, 6, 7], u.rad), - ) - - assert isinstance(spherical, SphericalVector) - assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) - assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) - assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) - - def test_radial_to_cylindrical(self, vector): - """Test ``vector.represent_as(CylindricalVector)``.""" - cylindrical = vector.represent_as( - CylindricalVector, - phi=Quantity([0, 1, 2, 3], u.rad), - z=Quantity([4, 5, 6, 7], u.m), - ) - - assert isinstance(cylindrical, CylindricalVector) - assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) - assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) - assert cylindrical.z == Quantity([4, 5, 6, 7], u.m) - - -class TestCartesian2DVector: - """Test :class:`vector.Cartesian2DVector`.""" - - @pytest.fixture(scope="class") - def vector(self) -> AbstractVector: - """Return a vector.""" - from vector import Cartesian2DVector - - return Cartesian2DVector( - x=Quantity([1, 2, 3, 4], u.kpc), y=Quantity([5, 6, 7, 8], u.km) - ) - - # ========================================================================== - # represent_as - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cartesian2d_to_cartesian1d(self, vector): - """Test ``vector.represent_as(Cartesian1DVector)``.""" - cart1d = vector.represent_as(Cartesian1DVector) - - assert isinstance(cart1d, Cartesian1DVector) - assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cartesian2d_to_radial(self, vector): - """Test ``vector.represent_as(RadialVector)``.""" - radial = vector.represent_as(RadialVector) - - assert isinstance(radial, RadialVector) - assert radial.r == Quantity([1, 2, 3, 4], u.kpc) - - def test_cartesian2d_to_polar(self, vector): - """Test ``vector.represent_as(PolarVector)``.""" - polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) - - assert isinstance(polar, PolarVector) - assert polar.r == Quantity([1, 2, 3, 4], u.kpc) - assert polar.phi == Quantity([0, 1, 2, 3], u.rad) - - # def test_cartesian2d_to_lnpolar(self, vector): - # """Test ``vector.represent_as(LnPolarVector)``.""" - # assert False - - # def test_cartesian2d_to_log10polar(self, vector): - # """Test ``vector.represent_as(Log10PolarVector)``.""" - # assert False - - def test_cartesian2d_to_cartesian3d(self, vector): - """Test ``vector.represent_as(Cartesian3DVector)``.""" - cart3d = vector.represent_as( - Cartesian3DVector, z=Quantity([9, 10, 11, 12], u.m) - ) - - assert isinstance(cart3d, Cartesian3DVector) - assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart3d.y == Quantity([5, 6, 7, 8], u.km) - assert cart3d.z == Quantity([9, 10, 11, 12], u.m) - - def test_cartesian2d_to_spherical(self, vector): - """Test ``vector.represent_as(SphericalVector)``.""" - spherical = vector.represent_as( - SphericalVector, theta=Quantity([4, 5, 6, 7], u.rad) - ) - - assert isinstance(spherical, SphericalVector) - assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) - assert spherical.phi == Quantity([5, 6, 7, 8], u.rad) - assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) - - def test_cartesian2d_to_cylindrical(self, vector): - """Test ``vector.represent_as(CylindricalVector)``.""" - cylindrical = vector.represent_as( - CylindricalVector, z=Quantity([9, 10, 11, 12], u.m) - ) - - assert isinstance(cylindrical, CylindricalVector) - assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) - assert cylindrical.phi == Quantity([5, 6, 7, 8], u.rad) - assert cylindrical.z == Quantity([9, 10, 11, 12], u.m) - - -class TestPolarVector: - """Test :class:`vector.PolarVector`.""" - - @pytest.fixture(scope="class") - def vector(self) -> AbstractVector: - """Return a vector.""" - from vector import PolarVector - - return PolarVector( - r=Quantity([1, 2, 3, 4], u.kpc), phi=Quantity([0, 1, 2, 3], u.rad) - ) - - # ========================================================================== - # represent_as - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_polar_to_cartesian1d(self, vector): - """Test ``vector.represent_as(Cartesian1DVector)``.""" - cart1d = vector.represent_as(Cartesian1DVector) - - assert isinstance(cart1d, Cartesian1DVector) - assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_polar_to_radial(self, vector): - """Test ``vector.represent_as(RadialVector)``.""" - radial = vector.represent_as(RadialVector) - - assert isinstance(radial, RadialVector) - assert radial.r == Quantity([1, 2, 3, 4], u.kpc) - - def test_polar_to_cartesian2d(self, vector): - """Test ``vector.represent_as(Cartesian2DVector)``.""" - cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) - - assert isinstance(cart2d, Cartesian2DVector) - assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart2d.y == Quantity([5, 6, 7, 8], u.km) - - def test_polar_to_polar(self, vector): - """Test ``vector.represent_as(PolarVector)``.""" - newvec = vector.represent_as(PolarVector) - assert newvec is vector - - # def test_polar_to_lnpolar(self, vector): - # """Test ``vector.represent_as(LnPolarVector)``.""" - # assert False - - # def test_polar_to_log10polar(self, vector): - # """Test ``vector.represent_as(Log10PolarVector) - # assert False - - def test_polar_to_cartesian3d(self, vector): - """Test ``vector.represent_as(Cartesian3DVector)``.""" - cart3d = vector.represent_as( - Cartesian3DVector, z=Quantity([9, 10, 11, 12], u.m) - ) - - assert isinstance(cart3d, Cartesian3DVector) - assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart3d.y == Quantity([5, 6, 7, 8], u.km) - assert cart3d.z == Quantity([9, 10, 11, 12], u.m) - - def test_polar_to_spherical(self, vector): - """Test ``vector.represent_as(SphericalVector)``.""" - spherical = vector.represent_as( - SphericalVector, theta=Quantity([4, 5, 6, 7], u.rad) - ) - - assert isinstance(spherical, SphericalVector) - assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) - assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) - assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) - - def test_polar_to_cylindrical(self, vector): - """Test ``vector.represent_as(CylindricalVector)``.""" - cylindrical = vector.represent_as( - CylindricalVector, z=Quantity([9, 10, 11, 12], u.m) - ) - - assert isinstance(cylindrical, CylindricalVector) - assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) - assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) - assert cylindrical.z == Quantity([9, 10, 11, 12], u.m) - - -class TestCartesian3DVector: - """Test :class:`vector.Cartesian3DVector`.""" - - @pytest.fixture(scope="class") - def vector(self) -> AbstractVector: - """Return a vector.""" - from vector import Cartesian3DVector - - return Cartesian3DVector( - x=Quantity([1, 2, 3, 4], u.kpc), - y=Quantity([5, 6, 7, 8], u.km), - z=Quantity([9, 10, 11, 12], u.m), - ) - - # ========================================================================== - # represent_as - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cartesian3d_to_cartesian1d(self, vector): - """Test ``vector.represent_as(Cartesian1DVector)``.""" - cart1d = vector.represent_as(Cartesian1DVector) - - assert isinstance(cart1d, Cartesian1DVector) - assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cartesian3d_to_radial(self, vector): - """Test ``vector.represent_as(RadialVector)``.""" - radial = vector.represent_as(RadialVector) - - assert isinstance(radial, RadialVector) - assert radial.r == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cartesian3d_to_cartesian2d(self, vector): - """Test ``vector.represent_as(Cartesian2DVector)``.""" - cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) - - assert isinstance(cart2d, Cartesian2DVector) - assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart2d.y == Quantity([5, 6, 7, 8], u.km) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cartesian3d_to_polar(self, vector): - """Test ``vector.represent_as(PolarVector)``.""" - polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) - - assert isinstance(polar, PolarVector) - assert polar.r == Quantity([1, 2, 3, 4], u.kpc) - assert polar.phi == Quantity([0, 1, 2, 3], u.rad) - - # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - # def test_cartesian3d_to_lnpolar(self, vector): - # """Test ``vector.represent_as(LnPolarVector)``.""" - # assert False - - # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - # def test_cartesian3d_to_log10polar(self, vector): - # """Test ``vector.represent_as(Log10PolarVector)``.""" - # assert False - - def test_cartesian3d_to_cartesian3d(self, vector): - """Test ``vector.represent_as(Cartesian3DVector)``.""" - newvec = vector.represent_as(Cartesian3DVector) - assert newvec is vector - - def test_cartesian3d_to_spherical(self, vector): - """Test ``vector.represent_as(SphericalVector)``.""" - spherical = vector.represent_as( - SphericalVector, - phi=Quantity([0, 1, 2, 3], u.rad), - theta=Quantity([4, 5, 6, 7], u.rad), - ) - - assert isinstance(spherical, SphericalVector) - assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) - assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) - assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) - - def test_cartesian3d_to_cylindrical(self, vector): - """Test ``vector.represent_as(CylindricalVector)``.""" - cylindrical = vector.represent_as( - CylindricalVector, - phi=Quantity([0, 1, 2, 3], u.rad), - z=Quantity([4, 5, 6, 7], u.m), - ) - - assert isinstance(cylindrical, CylindricalVector) - assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) - assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) - assert cylindrical.z == Quantity([4, 5, 6, 7], u.m) - - -class TestSphericalVector: - """Test :class:`vector.SphericalVector`.""" - - @pytest.fixture(scope="class") - def vector(self) -> AbstractVector: - """Return a vector.""" - from vector import SphericalVector - - return SphericalVector( - r=Quantity([1, 2, 3, 4], u.kpc), - phi=Quantity([0, 1, 2, 3], u.rad), - theta=Quantity([4, 5, 6, 7], u.rad), - ) - - # ========================================================================== - # represent_as - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_spherical_to_cartesian1d(self, vector): - """Test ``vector.represent_as(Cartesian1DVector)``.""" - cart1d = vector.represent_as(Cartesian1DVector) - - assert isinstance(cart1d, Cartesian1DVector) - assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_spherical_to_radial(self, vector): - """Test ``vector.represent_as(RadialVector)``.""" - radial = vector.represent_as(RadialVector) - - assert isinstance(radial, RadialVector) - assert radial.r == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_spherical_to_cartesian2d(self, vector): - """Test ``vector.represent_as(Cartesian2DVector)``.""" - cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) - - assert isinstance(cart2d, Cartesian2DVector) - assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart2d.y == Quantity([5, 6, 7, 8], u.km) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_spherical_to_polar(self, vector): - """Test ``vector.represent_as(PolarVector)``.""" - polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) - - assert isinstance(polar, PolarVector) - assert polar.r == Quantity([1, 2, 3, 4], u.kpc) - assert polar.phi == Quantity([0, 1, 2, 3], u.rad) - - # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - # def test_spherical_to_lnpolar(self, vector): - # """Test ``vector.represent_as(LnPolarVector)``.""" - # assert False - - # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - # def test_spherical_to_log10polar(self, vector): - # """Test ``vector.represent_as(Log10PolarVector)``.""" - # assert False - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_spherical_to_cartesian3d(self, vector): - """Test ``vector.represent_as(Cartesian3DVector)``.""" - cart3d = vector.represent_as( - Cartesian3DVector, z=Quantity([9, 10, 11, 12], u.m) - ) - - assert isinstance(cart3d, Cartesian3DVector) - assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart3d.y == Quantity([5, 6, 7, 8], u.km) - assert cart3d.z == Quantity([9, 10, 11, 12], u.m) - - def test_spherical_to_spherical(self, vector): - """Test ``vector.represent_as(SphericalVector)``.""" - newvec = vector.represent_as(SphericalVector) - assert newvec is vector - - def test_spherical_to_cylindrical(self, vector): - """Test ``vector.represent_as(CylindricalVector)``.""" - cylindrical = vector.represent_as( - CylindricalVector, z=Quantity([9, 10, 11, 12], u.m) - ) - - assert isinstance(cylindrical, CylindricalVector) - assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) - assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) - assert cylindrical.z == Quantity([9, 10, 11, 12], u.m) - - -class TestCylindricalVector: - """Test :class:`vector.CylindricalVector`.""" - - @pytest.fixture(scope="class") - def vector(self) -> AbstractVector: - """Return a vector.""" - from vector import CylindricalVector - - return CylindricalVector( - rho=Quantity([1, 2, 3, 4], u.kpc), - phi=Quantity([0, 1, 2, 3], u.rad), - z=Quantity([9, 10, 11, 12], u.m), - ) - - # ========================================================================== - # represent_as - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cylindrical_to_cartesian1d(self, vector): - """Test ``vector.represent_as(Cartesian1DVector)``.""" - cart1d = vector.represent_as(Cartesian1DVector) - - assert isinstance(cart1d, Cartesian1DVector) - assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cylindrical_to_radial(self, vector): - """Test ``vector.represent_as(RadialVector)``.""" - radial = vector.represent_as(RadialVector) - - assert isinstance(radial, RadialVector) - assert radial.r == Quantity([1, 2, 3, 4], u.kpc) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cylindrical_to_cartesian2d(self, vector): - """Test ``vector.represent_as(Cartesian2DVector)``.""" - cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) - - assert isinstance(cart2d, Cartesian2DVector) - assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart2d.y == Quantity([5, 6, 7, 8], u.km) - - @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - def test_cylindrical_to_polar(self, vector): - """Test ``vector.represent_as(PolarVector)``.""" - polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) - - assert isinstance(polar, PolarVector) - assert polar.r == Quantity([1, 2, 3, 4], u.kpc) - assert polar.phi == Quantity([0, 1, 2, 3], u.rad) - - # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - # def test_cylindrical_to_lnpolar(self, vector): - # """Test ``vector.represent_as(LnPolarVector)``.""" - # assert False - - # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") - # def test_cylindrical_to_log10polar(self, vector): - # """Test ``vector.represent_as(Log10PolarVector)``.""" - # assert False - - def test_cylindrical_to_cartesian3d(self, vector): - """Test ``vector.represent_as(Cartesian3DVector)``.""" - cart3d = vector.represent_as(Cartesian3DVector, y=Quantity([5, 6, 7, 8], u.km)) - - assert isinstance(cart3d, Cartesian3DVector) - assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) - assert cart3d.y == Quantity([5, 6, 7, 8], u.km) - assert cart3d.z == Quantity([9, 10, 11, 12], u.m) - - def test_cylindrical_to_spherical(self, vector): - """Test ``vector.represent_as(SphericalVector)``.""" - spherical = vector.represent_as( - SphericalVector, theta=Quantity([4, 5, 6, 7], u.rad) - ) - - assert isinstance(spherical, SphericalVector) - assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) - assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) - assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) - - def test_cylindrical_to_cylindrical(self, vector): - """Test ``vector.represent_as(CylindricalVector)``.""" - newvec = vector.represent_as(CylindricalVector) - assert newvec is vector diff --git a/tests/test_d1.py b/tests/test_d1.py new file mode 100644 index 00000000..91f0d250 --- /dev/null +++ b/tests/test_d1.py @@ -0,0 +1,425 @@ +"""Test :mod:`vector._d1`.""" + +import astropy.units as u +import pytest +from jax_quantity import Quantity + +from vector import ( + AbstractVector, + Cartesian1DVector, + Cartesian2DVector, + Cartesian3DVector, + CartesianDifferential1D, + CartesianDifferential2D, + CartesianDifferential3D, + CylindricalDifferential, + CylindricalVector, + PolarDifferential, + PolarVector, + RadialDifferential, + RadialVector, + SphericalDifferential, + SphericalVector, +) + +from .test_base import AbstractVectorDifferentialTest, AbstractVectorTest + + +class Abstract1DVectorTest(AbstractVectorTest): + """Test :class:`vector.Abstract1DVector`.""" + + +class TestCartesian1DVector(Abstract1DVectorTest): + """Test :class:`vector.Cartesian1DVector`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: + """Return a vector.""" + from vector import Cartesian1DVector + + return Cartesian1DVector(x=Quantity([1, 2, 3, 4], u.kpc)) + + # ========================================================================== + # represent_as + + def test_cartesian1d_to_cartesian1d(self, vector): + """Test ``vector.represent_as(Cartesian1DVector)``.""" + newvec = vector.represent_as(Cartesian1DVector) + assert newvec is vector + + def test_cartesian1d_to_radial(self, vector): + """Test ``vector.represent_as(RadialVector)``.""" + radial = vector.represent_as(RadialVector) + + assert isinstance(radial, RadialVector) + assert radial.r == Quantity([1, 2, 3, 4], u.kpc) + + def test_cartesian1d_to_cartesian2d(self, vector): + """Test ``vector.represent_as(Cartesian2DVector)``.""" + cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) + + assert isinstance(cart2d, Cartesian2DVector) + assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart2d.y == Quantity([5, 6, 7, 8], u.km) + + def test_cartesian1d_to_polar(self, vector): + """Test ``vector.represent_as(PolarVector)``.""" + polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) + + assert isinstance(polar, PolarVector) + assert polar.r == Quantity([1, 2, 3, 4], u.kpc) + assert polar.phi == Quantity([0, 1, 2, 3], u.rad) + + # def test_cartesian1d_to_lnpolar(self, vector): + # """Test ``vector.represent_as(LnPolarVector)``.""" + # lnpolar = vector.to_lnpolar(phi=Quantity([0, 1, 2, 3], u.rad)) + + # assert isinstance(lnpolar, LnPolarVector) + # assert lnpolar.lnr == xp.log(Quantity([1, 2, 3, 4], u.kpc)) + # assert lnpolar.phi == Quantity([0, 1, 2, 3], u.rad) + + # def test_cartesian1d_to_log10polar(self, vector): + # """Test ``vector.represent_as(Log10PolarVector)``.""" + # log10polar = vector.to_log10polar(phi=Quantity([0, 1, 2, 3], u.rad)) + + # assert isinstance(log10polar, Log10PolarVector) + # assert log10polar.log10r == xp.log10(Quantity([1, 2, 3, 4], u.kpc)) + # assert log10polar.phi == Quantity([0, 1, 2, 3], u.rad) + + def test_cartesian1d_to_cartesian3d(self, vector): + """Test ``vector.represent_as(Cartesian3DVector)``.""" + cart3d = vector.represent_as( + Cartesian3DVector, + y=Quantity([5, 6, 7, 8], u.km), + z=Quantity([9, 10, 11, 12], u.m), + ) + + assert isinstance(cart3d, Cartesian3DVector) + assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.z == Quantity([9, 10, 11, 12], u.m) + + def test_cartesian1d_to_spherical(self, vector): + """Test ``vector.represent_as(SphericalVector)``.""" + spherical = vector.represent_as( + SphericalVector, + phi=Quantity([0, 1, 2, 3], u.rad), + theta=Quantity([4, 5, 6, 7], u.rad), + ) + + assert isinstance(spherical, SphericalVector) + assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) + assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) + + def test_cartesian1d_to_cylindrical(self, vector): + """Test ``vector.represent_as(CylindricalVector)``.""" + cylindrical = vector.represent_as( + CylindricalVector, + phi=Quantity([0, 1, 2, 3], u.rad), + z=Quantity([4, 5, 6, 7], u.m), + ) + + assert isinstance(cylindrical, CylindricalVector) + assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) + assert cylindrical.z == Quantity([4, 5, 6, 7], u.m) + + +class TestRadialVector(Abstract1DVectorTest): + """Test :class:`vector.RadialVector`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: + """Return a vector.""" + from vector import RadialVector + + return RadialVector(r=Quantity([1, 2, 3, 4], u.kpc)) + + # ========================================================================== + # represent_as + + def test_radial_to_cartesian1d(self, vector): + """Test ``vector.represent_as(Cartesian1DVector)``.""" + cart1d = vector.represent_as(Cartesian1DVector) + + assert isinstance(cart1d, Cartesian1DVector) + assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) + + def test_radial_to_radial(self, vector): + """Test ``vector.represent_as(RadialVector)``.""" + newvec = vector.represent_as(RadialVector) + assert newvec is vector + + def test_radial_to_cartesian2d(self, vector): + """Test ``vector.represent_as(Cartesian2DVector)``.""" + cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) + + assert isinstance(cart2d, Cartesian2DVector) + assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart2d.y == Quantity([5, 6, 7, 8], u.km) + + def test_radial_to_polar(self, vector): + """Test ``vector.represent_as(PolarVector)``.""" + polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) + + assert isinstance(polar, PolarVector) + assert polar.r == Quantity([1, 2, 3, 4], u.kpc) + assert polar.phi == Quantity([0, 1, 2, 3], u.rad) + + # def test_radial_to_lnpolar(self, vector): + # """Test ``vector.represent_as(LnPolarVector)``.""" + # assert False + + # def test_radial_to_log10polar(self, vector): + # """Test ``vector.represent_as(Log10PolarVector)``.""" + # assert False + + def test_radial_to_cartesian3d(self, vector): + """Test ``vector.represent_as(Cartesian3DVector)``.""" + cart3d = vector.represent_as( + Cartesian3DVector, + y=Quantity([5, 6, 7, 8], u.km), + z=Quantity([9, 10, 11, 12], u.m), + ) + + assert isinstance(cart3d, Cartesian3DVector) + assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.z == Quantity([9, 10, 11, 12], u.m) + + def test_radial_to_spherical(self, vector): + """Test ``vector.represent_as(SphericalVector)``.""" + spherical = vector.represent_as( + SphericalVector, + phi=Quantity([0, 1, 2, 3], u.rad), + theta=Quantity([4, 5, 6, 7], u.rad), + ) + + assert isinstance(spherical, SphericalVector) + assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) + assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) + + def test_radial_to_cylindrical(self, vector): + """Test ``vector.represent_as(CylindricalVector)``.""" + cylindrical = vector.represent_as( + CylindricalVector, + phi=Quantity([0, 1, 2, 3], u.rad), + z=Quantity([4, 5, 6, 7], u.m), + ) + + assert isinstance(cylindrical, CylindricalVector) + assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) + assert cylindrical.z == Quantity([4, 5, 6, 7], u.m) + + +class Abstract1DVectorDifferentialTest(AbstractVectorDifferentialTest): + """Test :class:`vector.Abstract1DVectorDifferential`.""" + + +class TestCartesianDifferential1D(Abstract1DVectorDifferentialTest): + """Test :class:`vector.CartesianDifferential1D`.""" + + @pytest.fixture(scope="class") + def difntl(self) -> CartesianDifferential1D: + """Return a vector.""" + return CartesianDifferential1D(d_x=Quantity([1.0, 2, 3, 4], u.km / u.s)) + + @pytest.fixture(scope="class") + def vector(self) -> Cartesian1DVector: + """Return a vector.""" + return Cartesian1DVector(x=Quantity([1.0, 2, 3, 4], u.kpc)) + + # ========================================================================== + # represent_as + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian1d_to_cartesian1d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential1D)``.""" + newvec = difntl.represent_as(CartesianDifferential1D, vector) + assert newvec is difntl + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian1d_to_radial(self, difntl, vector): + """Test ``difntl.represent_as(RadialDifferential)``.""" + radial = difntl.represent_as(RadialDifferential, vector) + + assert isinstance(radial, RadialDifferential) + assert radial.d_r == Quantity([1, 2, 3, 4], u.km / u.s) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian1d_to_cartesian2d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential2D)``.""" + cart2d = difntl.represent_as( + CartesianDifferential2D, vector, dy=Quantity([5, 6, 7, 8], u.km) + ) + + assert isinstance(cart2d, CartesianDifferential2D) + assert cart2d.d_x == Quantity([1, 2, 3, 4], u.km / u.s) + assert cart2d.d_y == Quantity([5, 6, 7, 8], u.km / u.s) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian1d_to_polar(self, difntl, vector): + """Test ``difntl.represent_as(PolarDifferential)``.""" + polar = difntl.represent_as( + PolarDifferential, vector, dphi=Quantity([0, 1, 2, 3], u.rad) + ) + + assert isinstance(polar, PolarDifferential) + assert polar.d_r == Quantity([1, 2, 3, 4], u.km / u.s) + assert polar.d_phi == Quantity([0, 1, 2, 3], u.rad / u.s) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian1d_to_cartesian3d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential3D)``.""" + cart3d = difntl.represent_as( + CartesianDifferential3D, + vector, + dy=Quantity([5, 6, 7, 8], u.km), + dz=Quantity([9, 10, 11, 12], u.m), + ) + + assert isinstance(cart3d, CartesianDifferential3D) + assert cart3d.d_x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.d_y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.d_z == Quantity([9, 10, 11, 12], u.m) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian1d_to_spherical(self, difntl, vector): + """Test ``difntl.represent_as(SphericalDifferential)``.""" + spherical = difntl.represent_as( + SphericalDifferential, + vector, + dphi=Quantity([0, 1, 2, 3], u.rad), + dtheta=Quantity([4, 5, 6, 7], u.rad), + ) + + assert isinstance(spherical, SphericalDifferential) + assert spherical.d_r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.d_phi == Quantity([0, 1, 2, 3], u.rad) + assert spherical.dtheta == Quantity([4, 5, 6, 7], u.rad) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian1d_to_cylindrical(self, difntl, vector): + """Test ``difntl.represent_as(CylindricalDifferential)``.""" + cylindrical = difntl.represent_as( + CylindricalDifferential, + vector, + dphi=Quantity([0, 1, 2, 3], u.rad), + dz=Quantity([4, 5, 6, 7], u.m), + ) + + assert isinstance(cylindrical, CylindricalDifferential) + assert cylindrical.d_rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.d_phi == Quantity([0, 1, 2, 3], u.rad) + assert cylindrical.d_z == Quantity([4, 5, 6, 7], u.m) + + +class TestRadialDifferential(Abstract1DVectorDifferentialTest): + """Test :class:`vector.RadialDifferential`.""" + + @pytest.fixture(scope="class") + def difntl(self) -> RadialDifferential: + """Return a vector.""" + return RadialDifferential(d_r=Quantity([1, 2, 3, 4], u.km / u.s)) + + @pytest.fixture(scope="class") + def vector(self) -> RadialVector: + """Return a vector.""" + return RadialVector(r=Quantity([1, 2, 3, 4], u.kpc)) + + # ========================================================================== + # represent_as + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_radial_to_cartesian1d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential1D)``.""" + cart1d = difntl.represent_as(CartesianDifferential1D, vector) + + assert isinstance(cart1d, CartesianDifferential1D) + assert cart1d.d_x == Quantity([1, 2, 3, 4], u.km / u.s) + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_radial_to_radial(self, difntl, vector): + """Test ``difntl.represent_as(RadialDifferential)``.""" + newvec = difntl.represent_as(RadialDifferential, vector) + assert newvec is difntl + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_radial_to_cartesian2d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential2D)``.""" + cart2d = difntl.represent_as( + CartesianDifferential2D, vector, dy=Quantity([5, 6, 7, 8], u.km) + ) + + assert isinstance(cart2d, CartesianDifferential2D) + assert cart2d.d_x == Quantity([1, 2, 3, 4], u.kpc) + assert cart2d.d_y == Quantity([5, 6, 7, 8], u.km) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_radial_to_polar(self, difntl, vector): + """Test ``difntl.represent_as(PolarDifferential)``.""" + polar = difntl.represent_as( + PolarDifferential, vector, dphi=Quantity([0, 1, 2, 3], u.rad) + ) + + assert isinstance(polar, PolarDifferential) + assert polar.d_r == Quantity([1, 2, 3, 4], u.kpc) + assert polar.d_phi == Quantity([0, 1, 2, 3], u.rad) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_radial_to_cartesian3d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential3D)``.""" + cart3d = difntl.represent_as( + CartesianDifferential3D, + vector, + dy=Quantity([5, 6, 7, 8], u.km), + dz=Quantity([9, 10, 11, 12], u.m), + ) + + assert isinstance(cart3d, CartesianDifferential3D) + assert cart3d.d_x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.d_y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.d_z == Quantity([9, 10, 11, 12], u.m) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_radial_to_spherical(self, difntl, vector): + """Test ``difntl.represent_as(SphericalDifferential)``.""" + spherical = difntl.represent_as( + SphericalDifferential, + vector, + dphi=Quantity([0, 1, 2, 3], u.rad), + dtheta=Quantity([4, 5, 6, 7], u.rad), + ) + + assert isinstance(spherical, SphericalDifferential) + assert spherical.d_r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.d_phi == Quantity([0, 1, 2, 3], u.rad) + assert spherical.dtheta == Quantity([4, 5, 6, 7], u.rad) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_radial_to_cylindrical(self, difntl, vector): + """Test ``difntl.represent_as(CylindricalDifferential)``.""" + cylindrical = difntl.represent_as( + CylindricalDifferential, + vector, + dphi=Quantity([0, 1, 2, 3], u.rad), + dz=Quantity([4, 5, 6, 7], u.m), + ) + + assert isinstance(cylindrical, CylindricalDifferential) + assert cylindrical.d_rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.d_phi == Quantity([0, 1, 2, 3], u.rad) + assert cylindrical.d_z == Quantity([4, 5, 6, 7], u.m) diff --git a/tests/test_d2.py b/tests/test_d2.py new file mode 100644 index 00000000..3503a87c --- /dev/null +++ b/tests/test_d2.py @@ -0,0 +1,390 @@ +"""Test :mod:`vector._d2`.""" + +import astropy.units as u +import pytest +from jax_quantity import Quantity + +from vector import ( + AbstractVector, + Cartesian1DVector, + Cartesian2DVector, + Cartesian3DVector, + CylindricalVector, + PolarVector, + RadialVector, + SphericalVector, +) +from vector._d1.builtin import CartesianDifferential1D, RadialDifferential +from vector._d2.builtin import CartesianDifferential2D, PolarDifferential +from vector._d3.builtin import ( + CartesianDifferential3D, + CylindricalDifferential, + SphericalDifferential, +) + +from .test_base import AbstractVectorDifferentialTest, AbstractVectorTest + + +class Abstract2DVectorTest(AbstractVectorTest): + """Test :class:`vector.Abstract2DVector`.""" + + +class TestCartesian2DVector: + """Test :class:`vector.Cartesian2DVector`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: + """Return a vector.""" + from vector import Cartesian2DVector + + return Cartesian2DVector( + x=Quantity([1, 2, 3, 4], u.kpc), y=Quantity([5, 6, 7, 8], u.km) + ) + + # ========================================================================== + # represent_as + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cartesian2d_to_cartesian1d(self, vector): + """Test ``vector.represent_as(Cartesian1DVector)``.""" + cart1d = vector.represent_as(Cartesian1DVector) + + assert isinstance(cart1d, Cartesian1DVector) + assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cartesian2d_to_radial(self, vector): + """Test ``vector.represent_as(RadialVector)``.""" + radial = vector.represent_as(RadialVector) + + assert isinstance(radial, RadialVector) + assert radial.r == Quantity([1, 2, 3, 4], u.kpc) + + def test_cartesian2d_to_polar(self, vector): + """Test ``vector.represent_as(PolarVector)``.""" + polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) + + assert isinstance(polar, PolarVector) + assert polar.r == Quantity([1, 2, 3, 4], u.kpc) + assert polar.phi == Quantity([0, 1, 2, 3], u.rad) + + # def test_cartesian2d_to_lnpolar(self, vector): + # """Test ``vector.represent_as(LnPolarVector)``.""" + # assert False + + # def test_cartesian2d_to_log10polar(self, vector): + # """Test ``vector.represent_as(Log10PolarVector)``.""" + # assert False + + def test_cartesian2d_to_cartesian3d(self, vector): + """Test ``vector.represent_as(Cartesian3DVector)``.""" + cart3d = vector.represent_as( + Cartesian3DVector, z=Quantity([9, 10, 11, 12], u.m) + ) + + assert isinstance(cart3d, Cartesian3DVector) + assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.z == Quantity([9, 10, 11, 12], u.m) + + def test_cartesian2d_to_spherical(self, vector): + """Test ``vector.represent_as(SphericalVector)``.""" + spherical = vector.represent_as( + SphericalVector, theta=Quantity([4, 5, 6, 7], u.rad) + ) + + assert isinstance(spherical, SphericalVector) + assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.phi == Quantity([5, 6, 7, 8], u.rad) + assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) + + def test_cartesian2d_to_cylindrical(self, vector): + """Test ``vector.represent_as(CylindricalVector)``.""" + cylindrical = vector.represent_as( + CylindricalVector, z=Quantity([9, 10, 11, 12], u.m) + ) + + assert isinstance(cylindrical, CylindricalVector) + assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.phi == Quantity([5, 6, 7, 8], u.rad) + assert cylindrical.z == Quantity([9, 10, 11, 12], u.m) + + +class TestPolarVector: + """Test :class:`vector.PolarVector`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: + """Return a vector.""" + from vector import PolarVector + + return PolarVector( + r=Quantity([1, 2, 3, 4], u.kpc), phi=Quantity([0, 1, 2, 3], u.rad) + ) + + # ========================================================================== + # represent_as + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_polar_to_cartesian1d(self, vector): + """Test ``vector.represent_as(Cartesian1DVector)``.""" + cart1d = vector.represent_as(Cartesian1DVector) + + assert isinstance(cart1d, Cartesian1DVector) + assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_polar_to_radial(self, vector): + """Test ``vector.represent_as(RadialVector)``.""" + radial = vector.represent_as(RadialVector) + + assert isinstance(radial, RadialVector) + assert radial.r == Quantity([1, 2, 3, 4], u.kpc) + + def test_polar_to_cartesian2d(self, vector): + """Test ``vector.represent_as(Cartesian2DVector)``.""" + cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) + + assert isinstance(cart2d, Cartesian2DVector) + assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart2d.y == Quantity([5, 6, 7, 8], u.km) + + def test_polar_to_polar(self, vector): + """Test ``vector.represent_as(PolarVector)``.""" + newvec = vector.represent_as(PolarVector) + assert newvec is vector + + # def test_polar_to_lnpolar(self, vector): + # """Test ``vector.represent_as(LnPolarVector)``.""" + # assert False + + # def test_polar_to_log10polar(self, vector): + # """Test ``vector.represent_as(Log10PolarVector) + # assert False + + def test_polar_to_cartesian3d(self, vector): + """Test ``vector.represent_as(Cartesian3DVector)``.""" + cart3d = vector.represent_as( + Cartesian3DVector, z=Quantity([9, 10, 11, 12], u.m) + ) + + assert isinstance(cart3d, Cartesian3DVector) + assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.z == Quantity([9, 10, 11, 12], u.m) + + def test_polar_to_spherical(self, vector): + """Test ``vector.represent_as(SphericalVector)``.""" + spherical = vector.represent_as( + SphericalVector, theta=Quantity([4, 5, 6, 7], u.rad) + ) + + assert isinstance(spherical, SphericalVector) + assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) + assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) + + def test_polar_to_cylindrical(self, vector): + """Test ``vector.represent_as(CylindricalVector)``.""" + cylindrical = vector.represent_as( + CylindricalVector, z=Quantity([9, 10, 11, 12], u.m) + ) + + assert isinstance(cylindrical, CylindricalVector) + assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) + assert cylindrical.z == Quantity([9, 10, 11, 12], u.m) + + +class Abstract2DVectorDifferentialTest(AbstractVectorDifferentialTest): + """Test :class:`vector.Abstract2DVectorDifferential`.""" + + +class TestCartesianDifferential2D(Abstract2DVectorDifferentialTest): + """Test :class:`vector.CartesianDifferential2D`.""" + + @pytest.fixture(scope="class") + def difntl(self) -> CartesianDifferential2D: + """Return a differential.""" + return CartesianDifferential2D( + d_x=Quantity([1, 2, 3, 4], u.km / u.s), + d_y=Quantity([5, 6, 7, 8], u.km / u.s), + ) + + @pytest.fixture(scope="class") + def vector(self) -> Cartesian2DVector: + """Return a vector.""" + return Cartesian2DVector( + x=Quantity([1, 2, 3, 4], u.kpc), y=Quantity([5, 6, 7, 8], u.km) + ) + + # ========================================================================== + # represent_as + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian2d_to_cartesian1d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential1D, vector)``.""" + cart1d = difntl.represent_as(CartesianDifferential1D, vector) + + assert isinstance(cart1d, CartesianDifferential1D) + assert cart1d.d_x == Quantity([1, 2, 3, 4], u.km / u.s) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian2d_to_radial(self, difntl, vector): + """Test ``difntl.represent_as(RadialDifferential, vector)``.""" + radial = difntl.represent_as(RadialDifferential, vector) + + assert isinstance(radial, RadialDifferential) + assert radial.d_r == Quantity([1, 2, 3, 4], u.km / u.s) + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian2d_to_cartesian2d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential2D, vector)``.""" + newdifntl = difntl.represent_as(CartesianDifferential2D, vector) + + assert newdifntl is difntl + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian2d_to_polar(self, difntl, vector): + """Test ``difntl.represent_as(PolarDifferential, vector)``.""" + polar = difntl.represent_as(PolarDifferential, vector) + + assert isinstance(polar, PolarDifferential) + assert polar.d_r == Quantity([1, 2, 3, 4], u.km / u.s) + assert polar.d_phi == Quantity([5, 6, 7, 8], u.km * u.rad / (u.kpc * u.s)) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian2d_to_cartesian3d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential3D, vector)``.""" + cart3d = difntl.represent_as( + CartesianDifferential3D, vector, d_z=Quantity([9, 10, 11, 12], u.m / u.s) + ) + + assert isinstance(cart3d, CartesianDifferential3D) + assert cart3d.d_x == Quantity([1, 2, 3, 4], u.km / u.s) + assert cart3d.d_y == Quantity([5, 6, 7, 8], u.km / u.s) + assert cart3d.d_z == Quantity([9, 10, 11, 12], u.m / u.s) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian2d_to_spherical(self, difntl, vector): + """Test ``difntl.represent_as(SphericalDifferential, vector)``.""" + spherical = difntl.represent_as( + SphericalDifferential, vector, d_theta=Quantity([4, 5, 6, 7], u.rad) + ) + + assert isinstance(spherical, SphericalDifferential) + assert spherical.d_r == Quantity([1, 2, 3, 4], u.km / u.s) + assert spherical.d_phi == Quantity([5, 6, 7, 8], u.km / u.s) + assert spherical.d_theta == Quantity([4, 5, 6, 7], u.rad) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_cartesian2d_to_cylindrical(self, difntl, vector): + """Test ``difntl.represent_as(CylindricalDifferential, vector)``.""" + cylindrical = difntl.represent_as( + CylindricalDifferential, vector, d_z=Quantity([9, 10, 11, 12], u.m / u.s) + ) + + assert isinstance(cylindrical, CylindricalDifferential) + assert cylindrical.d_rho == Quantity([1, 2, 3, 4], u.km / u.s) + assert cylindrical.d_phi == Quantity([5, 6, 7, 8], u.km / u.s) + assert cylindrical.d_z == Quantity([9, 10, 11, 12], u.m / u.s) + + +class TestPolarDifferential(Abstract2DVectorDifferentialTest): + """Test :class:`vector.PolarDifferential`.""" + + @pytest.fixture(scope="class") + def difntl(self) -> PolarDifferential: + """Return a differential.""" + return PolarDifferential( + d_r=Quantity([1, 2, 3, 4], u.km / u.s), + d_phi=Quantity([5, 6, 7, 8], u.mas / u.yr), + ) + + @pytest.fixture(scope="class") + def vector(self) -> PolarVector: + """Return a vector.""" + return PolarVector( + r=Quantity([1, 2, 3, 4], u.kpc), phi=Quantity([0, 1, 2, 3], u.rad) + ) + + # ========================================================================== + # represent_as + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_polar_to_cartesian1d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential1D, vector)``.""" + cart1d = difntl.represent_as(CartesianDifferential1D, vector) + + assert isinstance(cart1d, CartesianDifferential1D) + assert cart1d.d_x == Quantity([1, 2, 3, 4], u.km / u.s) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_polar_to_radial(self, difntl, vector): + """Test ``difntl.represent_as(RadialDifferential, vector)``.""" + radial = difntl.represent_as(RadialDifferential, vector) + + assert isinstance(radial, RadialDifferential) + assert radial.d_r == Quantity([1, 2, 3, 4], u.km / u.s) + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_polar_to_cartesian2d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential2D, vector)``.""" + cart2d = difntl.represent_as(CartesianDifferential2D, vector) + + assert isinstance(cart2d, CartesianDifferential2D) + assert cart2d.d_x == Quantity([1, 2, 3, 4], u.km / u.s) + assert cart2d.d_y == Quantity([5, 6, 7, 8], u.km / u.s) + + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_polar_to_polar(self, difntl, vector): + """Test ``difntl.represent_as(PolarDifferential, vector)``.""" + newdifntl = difntl.represent_as(PolarDifferential, vector) + + assert newdifntl is difntl + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_polar_to_cartesian3d(self, difntl, vector): + """Test ``difntl.represent_as(CartesianDifferential3D, vector)``.""" + cart3d = difntl.represent_as( + CartesianDifferential3D, vector, d_z=Quantity([9, 10, 11, 12], u.m / u.s) + ) + + assert isinstance(cart3d, CartesianDifferential3D) + assert cart3d.d_x == Quantity([1, 2, 3, 4], u.km / u.s) + assert cart3d.d_y == Quantity([5, 6, 7, 8], u.km / u.s) + assert cart3d.d_z == Quantity([9, 10, 11, 12], u.m / u.s) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_polar_to_spherical(self, difntl, vector): + """Test ``difntl.represent_as(SphericalDifferential, vector)``.""" + spherical = difntl.represent_as( + SphericalDifferential, vector, d_theta=Quantity([4, 5, 6, 7], u.rad) + ) + + assert isinstance(spherical, SphericalDifferential) + assert spherical.d_r == Quantity([1, 2, 3, 4], u.km / u.s) + assert spherical.d_phi == Quantity([5, 6, 7, 8], u.km / u.s) + assert spherical.d_theta == Quantity([4, 5, 6, 7], u.rad) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.filterwarnings("ignore:Explicitly requested dtype") + def test_polar_to_cylindrical(self, difntl, vector): + """Test ``difntl.represent_as(CylindricalDifferential, vector)``.""" + cylindrical = difntl.represent_as( + CylindricalDifferential, vector, d_z=Quantity([9, 10, 11, 12], u.m / u.s) + ) + + assert isinstance(cylindrical, CylindricalDifferential) + assert cylindrical.d_rho == Quantity([1, 2, 3, 4], u.km / u.s) + assert cylindrical.d_phi == Quantity([5, 6, 7, 8], u.km / u.s) + assert cylindrical.d_z == Quantity([9, 10, 11, 12], u.m / u.s) diff --git a/tests/test_d3.py b/tests/test_d3.py new file mode 100644 index 00000000..dfbfa73b --- /dev/null +++ b/tests/test_d3.py @@ -0,0 +1,292 @@ +"""Test :mod:`vector._builtin`.""" + +import astropy.units as u +import pytest +from jax_quantity import Quantity + +from vector import ( + AbstractVector, + Cartesian1DVector, + Cartesian2DVector, + Cartesian3DVector, + CylindricalVector, + PolarVector, + RadialVector, + SphericalVector, +) + +from .test_base import AbstractVectorTest + + +class Abstract3DVectorTest(AbstractVectorTest): + """Test :class:`vector.Abstract3DVector`.""" + + +class TestCartesian3DVector: + """Test :class:`vector.Cartesian3DVector`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: + """Return a vector.""" + from vector import Cartesian3DVector + + return Cartesian3DVector( + x=Quantity([1, 2, 3, 4], u.kpc), + y=Quantity([5, 6, 7, 8], u.km), + z=Quantity([9, 10, 11, 12], u.m), + ) + + # ========================================================================== + # represent_as + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cartesian3d_to_cartesian1d(self, vector): + """Test ``vector.represent_as(Cartesian1DVector)``.""" + cart1d = vector.represent_as(Cartesian1DVector) + + assert isinstance(cart1d, Cartesian1DVector) + assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cartesian3d_to_radial(self, vector): + """Test ``vector.represent_as(RadialVector)``.""" + radial = vector.represent_as(RadialVector) + + assert isinstance(radial, RadialVector) + assert radial.r == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cartesian3d_to_cartesian2d(self, vector): + """Test ``vector.represent_as(Cartesian2DVector)``.""" + cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) + + assert isinstance(cart2d, Cartesian2DVector) + assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart2d.y == Quantity([5, 6, 7, 8], u.km) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cartesian3d_to_polar(self, vector): + """Test ``vector.represent_as(PolarVector)``.""" + polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) + + assert isinstance(polar, PolarVector) + assert polar.r == Quantity([1, 2, 3, 4], u.kpc) + assert polar.phi == Quantity([0, 1, 2, 3], u.rad) + + # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + # def test_cartesian3d_to_lnpolar(self, vector): + # """Test ``vector.represent_as(LnPolarVector)``.""" + # assert False + + # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + # def test_cartesian3d_to_log10polar(self, vector): + # """Test ``vector.represent_as(Log10PolarVector)``.""" + # assert False + + def test_cartesian3d_to_cartesian3d(self, vector): + """Test ``vector.represent_as(Cartesian3DVector)``.""" + newvec = vector.represent_as(Cartesian3DVector) + assert newvec is vector + + def test_cartesian3d_to_spherical(self, vector): + """Test ``vector.represent_as(SphericalVector)``.""" + spherical = vector.represent_as( + SphericalVector, + phi=Quantity([0, 1, 2, 3], u.rad), + theta=Quantity([4, 5, 6, 7], u.rad), + ) + + assert isinstance(spherical, SphericalVector) + assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) + assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) + + def test_cartesian3d_to_cylindrical(self, vector): + """Test ``vector.represent_as(CylindricalVector)``.""" + cylindrical = vector.represent_as( + CylindricalVector, + phi=Quantity([0, 1, 2, 3], u.rad), + z=Quantity([4, 5, 6, 7], u.m), + ) + + assert isinstance(cylindrical, CylindricalVector) + assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) + assert cylindrical.z == Quantity([4, 5, 6, 7], u.m) + + +class TestSphericalVector: + """Test :class:`vector.SphericalVector`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: + """Return a vector.""" + from vector import SphericalVector + + return SphericalVector( + r=Quantity([1, 2, 3, 4], u.kpc), + phi=Quantity([0, 1, 2, 3], u.rad), + theta=Quantity([4, 5, 6, 7], u.rad), + ) + + # ========================================================================== + # represent_as + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_spherical_to_cartesian1d(self, vector): + """Test ``vector.represent_as(Cartesian1DVector)``.""" + cart1d = vector.represent_as(Cartesian1DVector) + + assert isinstance(cart1d, Cartesian1DVector) + assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_spherical_to_radial(self, vector): + """Test ``vector.represent_as(RadialVector)``.""" + radial = vector.represent_as(RadialVector) + + assert isinstance(radial, RadialVector) + assert radial.r == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_spherical_to_cartesian2d(self, vector): + """Test ``vector.represent_as(Cartesian2DVector)``.""" + cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) + + assert isinstance(cart2d, Cartesian2DVector) + assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart2d.y == Quantity([5, 6, 7, 8], u.km) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_spherical_to_polar(self, vector): + """Test ``vector.represent_as(PolarVector)``.""" + polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) + + assert isinstance(polar, PolarVector) + assert polar.r == Quantity([1, 2, 3, 4], u.kpc) + assert polar.phi == Quantity([0, 1, 2, 3], u.rad) + + # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + # def test_spherical_to_lnpolar(self, vector): + # """Test ``vector.represent_as(LnPolarVector)``.""" + # assert False + + # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + # def test_spherical_to_log10polar(self, vector): + # """Test ``vector.represent_as(Log10PolarVector)``.""" + # assert False + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_spherical_to_cartesian3d(self, vector): + """Test ``vector.represent_as(Cartesian3DVector)``.""" + cart3d = vector.represent_as( + Cartesian3DVector, z=Quantity([9, 10, 11, 12], u.m) + ) + + assert isinstance(cart3d, Cartesian3DVector) + assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.z == Quantity([9, 10, 11, 12], u.m) + + def test_spherical_to_spherical(self, vector): + """Test ``vector.represent_as(SphericalVector)``.""" + newvec = vector.represent_as(SphericalVector) + assert newvec is vector + + def test_spherical_to_cylindrical(self, vector): + """Test ``vector.represent_as(CylindricalVector)``.""" + cylindrical = vector.represent_as( + CylindricalVector, z=Quantity([9, 10, 11, 12], u.m) + ) + + assert isinstance(cylindrical, CylindricalVector) + assert cylindrical.rho == Quantity([1, 2, 3, 4], u.kpc) + assert cylindrical.phi == Quantity([0, 1, 2, 3], u.rad) + assert cylindrical.z == Quantity([9, 10, 11, 12], u.m) + + +class TestCylindricalVector: + """Test :class:`vector.CylindricalVector`.""" + + @pytest.fixture(scope="class") + def vector(self) -> AbstractVector: + """Return a vector.""" + from vector import CylindricalVector + + return CylindricalVector( + rho=Quantity([1, 2, 3, 4], u.kpc), + phi=Quantity([0, 1, 2, 3], u.rad), + z=Quantity([9, 10, 11, 12], u.m), + ) + + # ========================================================================== + # represent_as + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cylindrical_to_cartesian1d(self, vector): + """Test ``vector.represent_as(Cartesian1DVector)``.""" + cart1d = vector.represent_as(Cartesian1DVector) + + assert isinstance(cart1d, Cartesian1DVector) + assert cart1d.x == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cylindrical_to_radial(self, vector): + """Test ``vector.represent_as(RadialVector)``.""" + radial = vector.represent_as(RadialVector) + + assert isinstance(radial, RadialVector) + assert radial.r == Quantity([1, 2, 3, 4], u.kpc) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cylindrical_to_cartesian2d(self, vector): + """Test ``vector.represent_as(Cartesian2DVector)``.""" + cart2d = vector.represent_as(Cartesian2DVector, y=Quantity([5, 6, 7, 8], u.km)) + + assert isinstance(cart2d, Cartesian2DVector) + assert cart2d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart2d.y == Quantity([5, 6, 7, 8], u.km) + + @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + def test_cylindrical_to_polar(self, vector): + """Test ``vector.represent_as(PolarVector)``.""" + polar = vector.represent_as(PolarVector, phi=Quantity([0, 1, 2, 3], u.rad)) + + assert isinstance(polar, PolarVector) + assert polar.r == Quantity([1, 2, 3, 4], u.kpc) + assert polar.phi == Quantity([0, 1, 2, 3], u.rad) + + # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + # def test_cylindrical_to_lnpolar(self, vector): + # """Test ``vector.represent_as(LnPolarVector)``.""" + # assert False + + # @pytest.mark.filterwarnings("ignore:Irreversible dimension change") + # def test_cylindrical_to_log10polar(self, vector): + # """Test ``vector.represent_as(Log10PolarVector)``.""" + # assert False + + def test_cylindrical_to_cartesian3d(self, vector): + """Test ``vector.represent_as(Cartesian3DVector)``.""" + cart3d = vector.represent_as(Cartesian3DVector, y=Quantity([5, 6, 7, 8], u.km)) + + assert isinstance(cart3d, Cartesian3DVector) + assert cart3d.x == Quantity([1, 2, 3, 4], u.kpc) + assert cart3d.y == Quantity([5, 6, 7, 8], u.km) + assert cart3d.z == Quantity([9, 10, 11, 12], u.m) + + def test_cylindrical_to_spherical(self, vector): + """Test ``vector.represent_as(SphericalVector)``.""" + spherical = vector.represent_as( + SphericalVector, theta=Quantity([4, 5, 6, 7], u.rad) + ) + + assert isinstance(spherical, SphericalVector) + assert spherical.r == Quantity([1, 2, 3, 4], u.kpc) + assert spherical.phi == Quantity([0, 1, 2, 3], u.rad) + assert spherical.theta == Quantity([4, 5, 6, 7], u.rad) + + def test_cylindrical_to_cylindrical(self, vector): + """Test ``vector.represent_as(CylindricalVector)``.""" + newvec = vector.represent_as(CylindricalVector) + assert newvec is vector From c80b4f44722ebcaa3a3147d1113efcc0166c63ee Mon Sep 17 00:00:00 2001 From: nstarman Date: Tue, 20 Feb 2024 09:14:51 -0500 Subject: [PATCH 10/10] ci: coverage ignores Signed-off-by: nstarman --- pyproject.toml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 98dba974..b38fd503 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,9 +81,21 @@ [tool.coverage] - report.exclude_also = ['\.\.\.', 'if typing.TYPE_CHECKING:'] run.source = ["vector"] + [tool.coverage.report] + exclude_also = [ + # Have to re-enable the standard pragma + 'pragma: no cover', + # Ignore type-checking stuff + 'if typing.TYPE_CHECKING:', + 'if TYPE_CHECKING:', + '\.\.\.', + # Ignore contents of abstract methods + '@abc.abstractmethod', + '@abstractmethod', + ] + [tool.mypy] disable_error_code = ["no-redef"] disallow_incomplete_defs = false