Source code for spheres.coordinates

"""
Coordinate transformations, mainly sphere related.
"""

import numpy as np
from numpy import pi

import qutip as qt
from collections.abc import Iterable

from .utils import *

def __c_xyz__(c, pole="south"):
    if c == np.inf:
        return np.array([0,0,-1]) if pole == "south" else np.array([0,0,1])
    else:
        x, y = c.real, c.imag
        return np.array([2*x/(1+x**2+y**2),\
                         2*y/(1+x**2+y**2),\
                         ((1-x**2-y**2)/(1+x**2+y**2))*\
                             (1 if pole == "south" else -1)])

[docs]def c_xyz(c, pole="south"): """ `Stereographic projection <https://en.wikipedia.org/wiki/Stereographic_projection>`_ from the extended complex plane to the unit sphere. Given coordinate :math:`c=x+iy` or :math:`\\infty`: | If :math:`c = \\infty`, returns :math:`(0,0,-1)`. | Otherwise, returns :math:`(\\frac{2x}{1+x^2+y^2}, \\frac{2y}{1+x^2+y^2}, \\frac{1-x^2-y^2}{1+x^2+y^2})`. Parameters ---------- c : complex/inf or list/np.ndarray Point(s) on the extended complex plane. pole : str, default 'south' Whether to project from the North or South pole. Returns ------- np.ndarray Cartesian coordinates of point(s) on unit sphere. """ return np.array([__c_xyz__(c_, pole=pole) for c_ in c]) if isinstance(c, Iterable) else __c_xyz__(c, pole=pole)
def __xyz_c__(xyz, pole="south"): x, y, z = xyz if pole == "south": return np.inf if np.isclose(z, -1) else x/(1+z) + 1j*y/(1+z) elif pole == "north": return np.inf if np.isclose(z, 1) else x/(1-z) + 1j*y/(1-z)
[docs]def xyz_c(xyz, pole="south"): """ Reverse `Stereographic projection <https://en.wikipedia.org/wiki/Stereographic_projection>`_ from the unit sphere to the extended complex plane. | Given :math:`(0,0,-1)`, returns :math:`\\infty`. | Otherwise returns :math:`c = (\\frac{x}{1+z}) + i(\\frac{y}{1+z})`. Parameters ---------- xyz : list/np.ndarray Cartesian coordinates of point(s) on unit sphere. pole : str, default 'south' Whether to reverse project from the North or South pole. Returns ------- complex/inf or np.ndarray Extended complex coordinate(s). """ xyz = np.asarray(xyz) return np.array([__xyz_c__(xyz_, pole=pole) for xyz_ in xyz]) if len(xyz.shape) != 1 else __xyz_c__(xyz, pole=pole)
[docs]def xyz_sph(xyz): """ Converts cartesian coordinates :math:`(x, y, z)` to spherical coordinates :math:`(\\theta, \\phi)`. We use the physicist's convention: | inclination: :math:`\\theta = \\arccos{\\frac{z}{\\sqrt{x^2 + y^2 + z^2}}} \\in [0, \\pi]` | azimuth :math:`\\phi = \\arctan{\\frac{y}{x}} \\in [0, 2\\pi]` Parameters ---------- xyz : list/np.ndarray (List of) Cartesian coordinates. Returns ------- sph : np.ndarray (List of) Spherical coordinates. """ xyz = np.asarray(xyz) x, y, z = xyz if len(xyz.shape) == 1 else xyz.T return np.array([np.arccos(z/np.sqrt(x**2+y**2+z**2)),\ np.mod(np.arctan2(y, x), 2*np.pi)]).T
[docs]def sph_xyz(sph): """ Converts spherical coordinates :math:`(\\theta, \\phi)` to cartesian coordinates :math:`(x, y, z)`. We use the physicist's convention: :math:`\\theta \\in [0, \\pi]`, :math:`\\phi \\in [0, 2\\pi]`. | :math:`x = \\sin{\\theta}\\cos(\\phi)` | :math:`y = \\sin{\\theta}\\sin(\\phi)` | :math:`z = \\cos(\\theta)` Parameters ---------- sph : list/np.ndarray (List of) Spherical coordinates. Returns ------- xyz : np.ndarray (List of) Cartesian coordinates. """ sph = np.asarray(sph) theta, phi = sph if len(sph.shape) == 1 else sph.T return np.array([np.sin(theta)*np.cos(phi),\ np.sin(theta)*np.sin(phi),\ np.cos(theta)]).T
[docs]def c_sph(c): """ Converts extended complex coordinate to spherical coordinates. Parameters ---------- c : complex/inf or list/np.ndarray Extended complex coordinate(s). Returns ------- sph : np.ndarray (List of) Spherical coordinates :math:`\\theta, \\phi`. """ return xyz_sph(c_xyz(c))
[docs]def sph_c(sph): """ Converts spherical coordinates to extended complex coordinate. Parameters ---------- sph : list/np.ndarray (List of) Spherical coordinates :math:`\\theta, \\phi`. Returns ------- c : complex/inf or np.ndarray Extended complex coordinate(s). """ return xyz_c(sph_xyz(sph))
def __c_spinor__(c): return qt.Qobj(np.array([0, 1])) if c == np.inf else (1/np.sqrt(1+np.abs(c)**2))*qt.Qobj(np.array([1, c]))
[docs]def c_spinor(c): """ Converts extended complex coordinate to a spinor. | If :math:`c = \\infty`, returns :math:`\\begin{pmatrix} 0 \\\\ 1 \\end{pmatrix}`. | Otherwise, returns :math:`\\frac{1}{\\sqrt{1+|c|^2}} \\begin{pmatrix} 1 \\\\ c \\end{pmatrix}` Parameters ---------- c : complex/inf or list/np.ndarray Extended complex coordinate(s). Returns ------- spinor : list or qt.Qobj (List of) normalized spinor(s). """ return [__c_spinor__(c_) for c_ in c] if isinstance(c, Iterable) else __c_spinor__(c)
def __spinor_c__(spinor): a, b = components(spinor) return b/a if not np.isclose(a, 0) else np.inf
[docs]def spinor_c(spinor): """ Converts spinor :math:`\\begin{pmatrix} a \\\\ b \\end{pmatrix}` to extended complex coordinate. | If :math:`a = 0`, returns :math:`\\infty`. | Otherwise returns :math:`\\frac{b}{a}`. Parameters ---------- spinor : list or qt.Qobj Normalized spinor(s). Returns ------- c : complex/inf or np.ndarray Extended complex coordinate(s). """ return [__spinor_c__(spinor_) for spinor_ in spinor] if isinstance(spinor, Iterable) else __spinor_c__(spinor)
[docs]def xyz_spinor(xyz): """ Converts cartesian coordinates to a spinor by reverse stereographic projection to the extended complex plane, and then lifting the latter to a 2-vector. Parameters ---------- xyz : list/np.ndarray (List of) cartesian coordinates. Returns ------- spinor : qt.Qobj or list Spinor(s). """ return c_spinor(xyz_c(xyz))
def __spinor_xyz__(spinor): return np.array([qt.expect(qt.sigmax(), spinor),\ qt.expect(qt.sigmay(), spinor),\ qt.expect(qt.sigmaz(), spinor)])
[docs]def spinor_xyz(spinor): """ Converts spinor :math:`\\mid \\psi \\rangle` to cartesian coordinates by taking the expectation values with the three Pauli matrices: :math:`(\\langle \\psi \\mid X \\mid \\psi \\rangle, \\langle \\psi \\mid Y \\mid \\psi \\rangle, \\langle \\psi \\mid Z \\mid \\psi \\rangle)`. Parameters ---------- spinor : list or qt.Qobj Spinor(s). Returns ------- xyz : np.ndarray (List of) cartesian coordinates. """ return [__spinor_xyz__(spinor_) for spinor_ in spinor] if isinstance(spinor, Iterable) else __spinor_xyz__(spinor)
[docs]def spinor_sph(spinor): """ Converts spinor to spherical coordinates. Parameters ---------- spinor : list or qt.Qobj Spinor(s). Returns ------- sph : np.ndarray Spherical coordinates :math:`r, \\phi, \\theta`. """ return xyz_sph(spinor_xyz(spinor))
[docs]def sph_spinor(sph): """ Converts spherical coordinates to spinor. Parameters ---------- sph : list or np.ndarray Spherical coordinates :math:`r, \\phi, \\theta`. Returns ------- spinor : list or qt.Qobj Spinor(s). """ return xyz_spinor(sph_xyz(sph))