Source code for pymarine.utils.coordinate_transformations

"""
Definition of some common coordinate system conversions

Notes
-----
* The coordinate transformations defined in this section are a selection of the
  coordinate_transformation implemented in the astropysics model. The reason why this module is not
  installed by it self is that this module has not been updated for Python 3.
  It is therefore easier just to take the part of the module which is relevant for HMC

* The definitions of the spherical coordinates follow the physics convention as described here_

References
----------

* https://en.wikipedia.org/wiki/Spherical_coordinate_system

.. _here:
    https://en.wikipedia.org/wiki/Spherical_coordinate_system

"""

import numpy as np
from numpy import pi


# <--------------------Functional coordinate transforms------------------------->
[docs] def cartesian_to_polar(x, y, degrees=False): """Converts arrays in 2D rectangular Cartesian coordinates to polar coordinates. Parameters ---------- x : float or array_like First cartesian coordinate y : float or array_like Second cartesian coordinate degrees : boolean If True, the output theta angle will be in degrees, otherwise radians. (Default = False) Returns ------- tuple of 2 floats or ndarrays Polar coordinates (r, theta) where theta is measured from the +x axis increasing towards the +y axis """ npx, npy = np.array(x), np.array(y) r = (npx * npx + npy * npy) ** 0.5 t = np.arctan2(npy, npx) if degrees: t = np.degrees(t) return r, t
[docs] def polar_to_cartesian(r, t, degrees=False): """Converts arrays in 2D polar coordinates to rectangular cartesian coordinates. Parameters ---------- r : float or array_like Radial coordinate t : float or array_like Azimuthal angle from +x-axis increasing towards +y-axis degrees : boolean If True, the input angles will be in degrees, otherwise radians. (Default value = False) Returns ------- tuple of 2 floats or ndarrays Cartesian coordinates (x,y) """ npt, npr = np.array(t), np.array(r) if degrees: npt = np.radians(npt) return npr * np.cos(npt), r * np.sin(npt)
[docs] def cartesian_to_spherical(x, y, z, degrees=False): """Converts three arrays in 3D rectangular cartesian coordinates to spherical polar coordinates. Note that the spherical coordinates are in *physicist* convention such that (1,pi/2,0) is x-axis. Parameters ---------- x : float or array_like First cartesian coordinate y : float or array_like Second cartesian coordinate z : float or array_like Third cartesian coordinate degrees : boolean If True, the output theta angle will be in degrees, otherwise radians. (Default = False) Returns ------- tuple of 3 floats or ndarrays Spherical coordinates (r,theta,phi) Examples -------- Convert the coordinates (1, 0, 0) >>> radius, theta, phi = cartesian_to_spherical(1, 0, 0) >>> print("Radius = {:.4g} Theta = {:.4g} Phi = {:.4g}".format(radius, theta, phi)) Radius = 1 Theta = 1.571 Phi = 0 >>> radius, theta, phi = cartesian_to_spherical(1, 1, 1, degrees=True) >>> print("Radius = {:.4g} Theta = {:.4g} Phi = {:.4g}".format(radius, theta, phi)) Radius = 1.732 Theta = 54.74 Phi = 45 Convert array_like coordinates >>> xx, yy, zz = [0, 0, 1 ], [1, 0, 1 ], [0, 1, 1 ] >>> radii, thetas, phis = cartesian_to_spherical(xx, yy, zz) >>> for ii, radius in enumerate(radii): ... print("({:.2f}, {:.2f} {:.2f}) -> ({:.4f}, {:.4f}, {:.4f})" ... "".format(xx[ii], yy[ii], zz[ii], radius, thetas[ii], phis[ii])) (0.00, 1.00 0.00) -> (1.0000, 1.5708, 1.5708) (0.00, 0.00 1.00) -> (1.0000, 0.0000, 0.0000) (1.00, 1.00 1.00) -> (1.7321, 0.9553, 0.7854) References ---------- https://en.wikipedia.org/wiki/Spherical_coordinate_system """ npx, npy, npz = np.array(x), np.array(y), np.array(z) xsq, ysq, zsq = npx * npx, npy * npy, npz * npz r = (xsq + ysq + zsq) ** 0.5 t = np.arctan2((xsq + ysq) ** 0.5, z) p = np.arctan2(npy, npx) if degrees: t, p = np.degrees(t), np.degrees(p) return r, t, p
[docs] def spherical_to_cartesian(r, t, p, degrees=False): """Converts arrays in 3D spherical polar coordinates to rectangular cartesian coordinates. Parameters ---------- r : float or array like Radial coordinate t : float or array_like Colatitude (angle from z-axis) p : float or array_lie Azimuthal angle from +x-axis increasing towards +y-axis degrees : boolean If True, the input angles will be in degrees, otherwise radians. (Default value = False) Returns ------- tuple of 3 floats or ndarrays Cartesian coordinates (x,y,z) Notes ----- * The spherical coordinates are in *physicist* convention such that (1,pi/2,0) is the x-axis. Examples -------- >>> xx, yy, zz = spherical_to_cartesian(1, 0, 0) >>> print("xx = {:.4g} yy = {:.4g} zz = {:.4g}".format(xx, yy, zz)) xx = 0 yy = 0 zz = 1 >>> xx, yy, zz = spherical_to_cartesian(1.7321, 54.736, 45, degrees=True) >>> print("xx = {:.4g} yy = {:.4g} zz = {:.4g}".format(xx, yy, zz)) xx = 1 yy = 1 zz = 1 >>> rr, tt, pp = np.array([1, 2, 3 ]), np.array([0, 45, 90 ]), np.array([0, -45, 45 ]) >>> xx, yy, zz = spherical_to_cartesian(rr, tt, pp, degrees=True) >>> for ii, x in enumerate(xx): ... print("({:6.2f}, {:6.2f} {:6.2f}) -> ({:6.2f}, {:6.2f}, {:6.2f})" ... "".format(rr[ii], tt[ii], pp[ii], x, yy[ii], zz[ii])) ( 1.00, 0.00 0.00) -> ( 0.00, 0.00, 1.00) ( 2.00, 45.00 -45.00) -> ( 1.00, -1.00, 1.41) ( 3.00, 90.00 45.00) -> ( 2.12, 2.12, 0.00) """ npr, npt, npp = np.array(r), np.array(t), np.array(p) if degrees: npt, npp = np.radians(npt), np.radians(npp) x = npr * np.sin(npt) * np.cos(npp) y = npr * np.sin(npt) * np.sin(npp) z = npr * np.cos(npt) return x, y, z
[docs] def latitude_to_colatitude(lat, degrees=False): """Converts from latitude (i.e. 0 at the equator) to colatitude/inclination (i.e. "theta" in physicist convention). Parameters ---------- lat : float or array_like Latitude degrees : bool If True, use degrees (Default value = False) Returns ------- float or ndarray Colatitude Examples -------- >>> latitude_to_colatitude(10, degrees=True) 80 >>> phi_list = [np.pi / i for i in range(1,6)] >>> co_latitude = latitude_to_colatitude(phi_list) >>> for ii, phi in enumerate(phi_list): ... print("{:6.4f} -> {:7.4f}".format(phi, co_latitude[ii])) 3.1416 -> -1.5708 1.5708 -> 0.0000 1.0472 -> 0.5236 0.7854 -> 0.7854 0.6283 -> 0.9425 """ lat_array = np.array(lat) if degrees: return 90 - lat_array else: return pi / 2 - lat_array
[docs] def colatitude_to_latitude(theta, degrees=False): """Converts from colatitude/inclination (i.e. "theta" in physicist convention) to latitude (i.e. 0 at the equator). Parameters ---------- theta : float or array-like input colatitude degrees : bool If True, the input is interpreted as degrees, otherwise radians. (Default value = False) Returns ------- float or ndarray Latitude Examples -------- >>> colatitude_to_latitude(15, degrees=True) 75 >>> phi_list = [np.pi / i for i in range(1,6)] >>> latitude = colatitude_to_latitude(phi_list) >>> for ii, phi in enumerate(phi_list): ... print("{:6.4f} -> {:7.4f}".format(phi, latitude[ii])) 3.1416 -> -1.5708 1.5708 -> 0.0000 1.0472 -> 0.5236 0.7854 -> 0.7854 0.6283 -> 0.9425 """ theta_array = np.array(theta) if degrees: return 90 - theta_array else: return pi / 2 - theta_array
[docs] def cartesian_to_cylindrical(x, y, z, degrees=False): """Converts three arrays in 3D rectangular Cartesian coordinates to cylindrical polar coordinates. Parameters ---------- x : float or array-like x cartesian coordinate y : float or array-like y cartesian coordinate z : float or array-like z cartesian coordinate degrees : bool If True, the output angles will be in degrees, otherwise radians. (Default value = False) Returns ------- tuple of 3 floats or ndarrays Cylindrical coordinates as a (rho,theta,z), with theta increasing from +x to +y and theta = 0 at x-axis. """ s, t = cartesian_to_polar(x, y, degrees) return s, t, z
[docs] def cylindrical_to_cartesian(s, t, z, degrees=False): """Converts three arrays in cylindrical polar coordinates to 3D rectangular Cartesian coordinates. Parameters ---------- s : float or array-like radial polar coordinate t : float or array-like polar angle (increasing from +x to +y, 0 at x-axis) z : float or array-like z coordinate degrees : bool If True, the input angle will be in degrees, otherwise radians. (Default value = False) Returns ------- tuple of 3 floats or ndarrays Cartesian coordinates as an (x,y,z) tuple. """ x, y = polar_to_cartesian(s, t, degrees) return x, y, z