Source code for irfpy.cena.frame

r''' A frame definition.  CENA frame and SC frame is supported.

CENA frame and SC frame conversion is supported.
Since they are rigidly related, implementation is simple.

*   Xcena = Zsc
*   Ycena = Xsc
*   Zcena = Ysc

There is also a definition of angles: |theta| and |phi|.
This is based on the :ref:`cenacalrep`.
The method cena2angles and angles2cena will convert them each other.
'''

import math
import numpy
import numpy as np
from irfpy.util.vector3d import Vector3d

[docs]def cena2sc(vec): ''' Conversion from CENA frame to Spacecraft frame. Input is a Vector3d instance or array-like. Return is Vector3d or numpy.array. >>> vcena = Vector3d(1,2,3) # v is in the CENA frame >>> vsc = cena2sc(vcena) >>> print(vsc.x, vsc.y, vsc.z) 2 3 1 >>> vcena = [-1, -2, -3] >>> vsc = cena2sc(vcena) # Return is numpy.array >>> print(vsc.shape) (3,) >>> print(vsc) [-2 -3 -1] ''' if isinstance(vec, Vector3d): sc = Vector3d(vec.y, vec.z, vec.x) else: sc = numpy.array([vec[1], vec[2], vec[0]]) return sc
[docs]def sc2cena(vec): ''' Conversion from SC frame to CENA frame. Input is a Vector3d instance or array-like. Return is Vector3d or numpy.array. >>> vsc = Vector3d(1,2,3) >>> vcena = sc2cena(vsc) >>> print(vcena.x, vcena.y, vcena.z) 3 1 2 >>> vsc = [-1, -2, -3] >>> vcena = sc2cena(vsc) # Return is numpy.array >>> print(vcena.shape) (3,) >>> print(vcena) [-3 -1 -2] ''' if isinstance(vec, Vector3d): cena = Vector3d(vec.z, vec.x, vec.y) else: cena = numpy.array([vec[2], vec[0], vec[1]]) return cena
[docs]def get_sc2cena_matrix(): ''' >>> vsc = [-1, -2, -3] >>> m = get_sc2cena_matrix() >>> print(m.dot(vsc)) [-3 -1 -2] ''' return numpy.array([[0, 0, 1], [1, 0, 0], [0, 1, 0]])
[docs]def cena2angles2(xarr, yarr, zarr): ''' Return the CENA-angle from vector See definition of angle in :func:`cena2angles`. :param xarr: X cooridnates (array also acceptable) :param yarr: Y cooridnates (array also acceptable) :param zarr: Z cooridnates (array also acceptable) >>> theta, phi = cena2angles2([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -1]) >>> theta = np.rad2deg(theta) >>> phi = np.rad2deg(phi) >>> print('%.2f %.2f %.2f %.2f' % (theta[0], theta[1], theta[2], theta[3])) 0.00 0.00 -90.00 90.00 >>> print('%.2f %.2f %.2f %.2f' % (phi[0], phi[1], phi[2], phi[3])) 90.00 0.00 0.00 0.00 ''' x = np.array(xarr) y = np.array(yarr) z = np.array(zarr) r = np.sqrt(x * x + y * y + z * z) x = x / r y = y / r z = z / r theta = np.pi / 2. - np.arccos(-z) phi = np.arctan2(x, y) return theta, phi
[docs]def cena2angles(vec, degrees=False): ''' Conversion in CENA frame from a vector to SC frame in angles. Angles are defined in Figure 1.1 in :ref:`cenacalrep`. The input is array-like or Vector3d instance. The output is a pair of the angle, (|theta|, |phi|), defined as follows. The unit is the radian unless degrees argument is set. |theta| is defined as follows: |theta| =0 is in x-y plane of CENA frame and positive for negative Z. |phi| is define as follows: +y is 0, and +x is 90 degrees. >>> cena2angles([1, 0, 0], degrees=True) (0.0, 90.0) >>> cena2angles([0, 1, 0], degrees=True) (0.0, 0.0) >>> cena2angles([0, 0, 1], degrees=True) (-90.0, 0.0) >>> cena2angles([0, 0, -1], degrees=True) (90.0, 0.0) ''' x = vec[0] y = vec[1] z = vec[2] v = Vector3d(x, y, z) v.normalize() minus_z = Vector3d(0, 0, -1) theta = math.pi/2. - v.angle(minus_z) phi = math.atan2(x, y) if degrees: theta = theta * 180 / math.pi phi= phi * 180 / math.pi return (theta, phi)
[docs]def angles2cena(theta, phi, degrees=False, vector3d=False): ''' Conversion from angles to vectors for CENA frame. See :meth:`cena2angles` for definition of angles. Input is two angles. If degrees is set, the given angles are considered as in degrees. Otherwise, they are considered as radians. Output is the instance of numpy.array for default, or irfpy.util.vector3d.Vector3d if vector3d option is set. >>> v = angles2cena(0, 90, degrees=True, vector3d=True) >>> v_exp = Vector3d(1, 0, 0) >>> v_exp.sub(v) >>> print(v_exp.length() < 1e-5) True >>> v = angles2cena(0, 0, degrees=True, vector3d=True) >>> v_exp = Vector3d(0, 1, 0) >>> v_exp.sub(v) >>> print(v_exp.length() < 1e-5) True >>> v = angles2cena(-90, 0, degrees=True, vector3d=True) >>> v_exp = Vector3d(0, 0, 1) >>> v_exp.sub(v) >>> print(v_exp.length() < 1e-5) True >>> v = angles2cena(90, 0, degrees=True, vector3d=True) >>> v_exp = Vector3d(0, 0, -1) >>> v_exp.sub(v) >>> print(v_exp.length() < 1e-5) True ''' t = theta p = phi if degrees: t = t * math.pi / 180. p = p * math.pi / 180. z = -math.sin(t) y = math.cos(t) * math.cos(p) x = math.cos(t) * math.sin(p) if vector3d: return Vector3d(x, y, z) else: return numpy.array([x, y, z])