Source code for optika._util
from typing import Any
import numpy as np
import astropy.units as u
import named_arrays as na
import optika
__all__ = [
"shape",
"direction",
"angles",
]
_shaped_type = (
na.AbstractArray,
na.transformations.AbstractTransformation,
optika.mixins.Shaped,
)
[docs]
def shape(a: Any) -> dict[str, int]:
"""
Return the array shape of the given object.
If the given object is an instance of :class:`named_arrays.AbstractArray`,
:class:`named_arrays.transformations.AbstractTransformation`, or
:class:`optika.mixins.Shaped`, ``a.shape`` will be returned.
Otherwise an empty dictionary will be returned.
Parameters
----------
a
The object to find the shape of.
"""
if isinstance(a, _shaped_type):
return a.shape
else:
return dict()
[docs]
def direction(
angles: na.AbstractCartesian2dVectorArray,
) -> na.Cartesian3dVectorArray:
r"""
Given a 2D vector of azimuth and elevation angles, convert to a
3D vector of direction cosines.
Parameters
----------
angles
A vector of azimuth and elevation angles.
Notes
-----
If the azimuth and elevation angles are taken to :math:`\phi_x` and
:math:`\phi_y`, the direction cosines :math:`\vec{d}` can be found by
.. math::
\vec{d} = R_y(\phi_x) R_x(\phi_y) \hat{z}
where :math:`R_x(\theta)` and :math:`R_y(\theta)` are the rotation matrices
about the :math:`x` and :math:`y` axes respectively.
See Also
--------
:func:`angles` : Inverse of this function
"""
return na.Cartesian3dVectorArray(
x=-np.cos(angles.y) * np.sin(angles.x),
y=-np.sin(angles.y),
z=+np.cos(angles.y) * np.cos(angles.x),
)
[docs]
def angles(
direction: na.AbstractCartesian3dVectorArray,
) -> na.Cartesian2dVectorArray:
"""
Convert a 3D vector of direction cosines to a 2D vector of azimuth and
elevation angles.
Parameters
----------
direction
A vector of direction cosines.
See Also
--------
:func:`direction` : Inverse of this function
"""
if na.unit(direction) is None:
direction = direction << u.dimensionless_unscaled
return na.Cartesian2dVectorArray(
x=-np.arctan2(direction.x, direction.z).to(u.deg),
y=-np.arcsin(direction.y / direction.length).to(u.deg),
)