coordinax.charts#
The coordinax.charts module provides chart objects and chart-level coordinate maps for representing points on manifolds.
Overview#
A chart defines how point coordinates are represented:
Component names (for example
x, y, zorr, theta, phi)Coordinate dimensions (for example
length,angle)Transition and realization behavior through the functional API
Use chart instances (for example cart3d, sph3d) when transforming concrete coordinate data.
For a step-by-step walkthrough, see Working With Charts.
Quick Start#
import coordinax.charts as cxc
import unxt as u
# Use predefined chart instances.
cart = cxc.cart3d
sph = cxc.sph3d
# Same-manifold chart transition.
p = {"x": u.Q(1, "km"), "y": u.Q(2, "km"), "z": u.Q(3, "km")}
p_sph = cxc.pt_map(p, cart, sph)
# General realization map (defaults to transition map for same manifold charts).
p_sph2 = cxc.pt_map(p, cart, sph)
# Pick canonical Cartesian chart without transforming coordinates.
cart_of_sph = cxc.cartesian_chart(sph)
Functional API#
cartesian_chart: return a chart’s canonical Cartesian chartguess_chart: infer a chart from keys or array/quantity trailing shapecdict: normalize inputs to component dictionariespt_map: transform points between charts on the same or different manifoldsjac_pt_map: compute the Jacobian of a point map between charts on the same or different manifolds
Available Objects#
Chart Families#
The module exports both concrete chart classes and predefined instances.
0D Charts#
Cart0D/cart0d: Zero-dimensional Cartesian (scalar)
1D Charts#
Cart1D/cart1d: 1D CartesianRadial1D/radial1d: Radial distanceTime1D/time1d: 1D time chart
2D Charts#
Cart2D/cart2d: 2D CartesianPolar2D/polar2d: Polar coordinatesSphericalTwoSphere/sph2: 2-sphere (theta,phi)LonLatSphericalTwoSphere/lonlat_sph2: 2-sphere (lon,lat)LonCosLatSphericalTwoSphere/loncoslat_sph2: 2-sphere (lon_coslat,lat)MathSphericalTwoSphere/math_sph2: mathematical 2-sphere convention
Intrinsic two-sphere charts do not have a global Cartesian 2D chart; requesting cartesian_chart(...) on this family raises NoGlobalCartesianChartError.
3D Charts#
Cart3D/cart3d: 3D CartesianCylindrical3D/cyl3d: Cylindrical coordinatesSpherical3D/sph3d: Spherical coordinates (physics convention)LonLatSpherical3D/lonlat_sph3d: Longitude/latitude sphericalLonCosLatSpherical3D/loncoslat_sph3d: Lon/cos(lat) sphericalMathSpherical3D/math_sph3d: Mathematical spherical conventionProlateSpheroidal3D: Prolate spheroidal chart with requiredDeltaparameter
ProlateSpheroidal3D does not export a predefined instance because chart instances depend on the focal parameter Delta.
4D Charts#
MinkowskiCT/minkowskict: 4D Minkowski spacetime chart with the conventional 3+1 split. Components are(ct, x, y, z), all with dimension"length". This is a single (non-product) flat chart whose metric is \(\eta = \operatorname{diag}(-1, 1, 1, 1)\). The chart is self-Cartesian:cartesian_chart(minkowskict) is minkowskict.
6D Charts#
PoincarePolar6D/poincarepolar6d: 6D Poincare polar chart family
N-D Charts#
CartND/cartnd: N-dimensional Cartesian
Product Charts#
CartesianProductChart: namespace-prefixed product chart with dot-delimited component keys (for exampleq.x,q.y,p.x, …)
Product-chart transitions are factorwise: each factor chart transforms independently and then components are merged.
Notes#
Use chart instances (for example
cart3d,sph3d) as conversion arguments.Intrinsic two-sphere charts do not define a global Cartesian 2D chart.
coordinax.charts Module.
Let’s start by constructing some charts and see how they work.
>>> import coordinax.charts as cxc
We can create a 3D Cartesian chart like this:
>>> cart_chart = cxc.Cart3D()
>>> cart_chart == cxc.cart3d # predefined instance
True
Charts have components and coordinate dimensions:
>>> cart_chart.components
('x', 'y', 'z')
>>> cart_chart.coord_dimensions
('length', 'length', 'length')
There are many different charts available, such as spherical coordinates:
>>> sph_chart = cxc.Spherical3D()
>>> sph_chart == cxc.sph3d # predefined instance
True
>>> sph_chart.components
('r', 'theta', 'phi')
>>> sph_chart.coord_dimensions
('length', 'angle', 'angle')
Another example is a 4D Minkowski spacetime chart:
>>> st_chart = cxc.MinkowskiCT()
>>> st_chart.components
('ct', 'x', 'y', 'z')
>>> st_chart.coord_dimensions
('length', 'length', 'length', 'length')
>>> st_chart.cartesian is st_chart
True
We can also build arbitrary Cartesian products of charts (without flattening) using CartesianProductChart:
>>> prod_chart = cxc.CartesianProductChart((cxc.time1d, cxc.sph3d), ("t", "q"))
>>> prod_chart
CartesianProductChart(
factors=(Time1D(M=Rn(1)), Spherical3D(M=Rn(3))),
factor_names=('t', 'q')
)
>>> prod_chart.components
('t.t', 'q.r', 'q.theta', 'q.phi')
With charts we can transform point coordinates between different coordinate systems.
>>> import unxt as u
>>> q = {"x": u.Q(1, "km"), "y": u.Q(2, "km"), "z": u.Q(3, "km")}
>>> q_sph = cxc.pt_map(q, cxc.cart3d, cxc.sph3d)
>>> q_sph
{'r': Q(3.74165739, 'km'), 'theta': Q(0.64052231, 'rad'),
'phi': Q(1.10714872, 'rad')}
We can also compute the Jacobian of the point map:
>>> jac = cxc.jac_pt_map(q, cxc.cart3d, cxc.sph3d)
- class coordinax.charts.AbstractChart#
Bases:
Generic[MT,Ks,Ds]Abstract base class for charts (coordinate representations).
- M: MT#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- abstract property components: Ks#
The names of the components.
- abstract property coord_dimensions: Ds#
The dimensions of the components.
- abstract property cartesian: AbstractChart[MT, Ks, Ds]#
Return the corresponding Cartesian chart.
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- class coordinax.charts.AbstractFixedComponentsChart#
Bases:
AbstractChart[MT,Ks,Ds]Abstract base class for charts with fixed components and dimensions.
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- abstract property cartesian: AbstractChart[MT, Ks, Ds]#
Return the corresponding Cartesian chart.
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- M: MT#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- class coordinax.charts.AbstractDimensionalFlag#
Bases:
objectMarker base class for dimension flags.
A dimension flag is a lightweight mixin used for typing and dispatch. Flags do not store data; instead, they classify a chart. These flags must be combined with concrete subclasses of {class}`AbstractChart`.
- exception coordinax.charts.NoGlobalCartesianChartError#
Bases:
ExceptionRaised when a chart has no global Cartesian representation.
Some charts represent coordinates on curved manifolds (e.g., 2-sphere) that cannot be globally mapped to a flat Cartesian space without singularities or discontinuities.
Examples
2-sphere charts (intrinsic coordinates on a spherical surface) have no global Cartesian 2D representation. To work with these charts:
Use an
EmbeddedChartto embed in 3D Euclidean spaceUse local projections when available
Work directly in the intrinsic coordinates
- add_note()#
Exception.add_note(note) – add a note to the exception
- args#
- with_traceback()#
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- coordinax.charts.cartesian_chart(chart: AbstractChart, /)#
Return the canonical Cartesian chart for a 0D chart.
>>> import coordinax.charts as cxc >>> cxc.cartesian_chart(cxc.cart0d) is cxc.cart0d True
- Parameters:
chart (
AbstractChart)- Return type:
- coordinax.charts.guess_chart(*_: Any)#
Infer a chart from keys or from array/quantity trailing shape.
This is a lightweight heuristic API.
Examples
>>> import jax.numpy as jnp >>> import unxt as u >>> import coordinax.charts as cxc
>>> cxc.guess_chart(frozenset(("x", "y", "z"))) Cart3D(M=Rn(3))
>>> cxc.guess_chart({"x": 1.0, "y": 2.0, "z": 3.0}) Cart3D(M=Rn(3))
>>> q = u.Q([1.0, 2.0, 3.0], "m") >>> cxc.guess_chart(q) Cart3D(M=Rn(3))
>>> x = jnp.array([1.0, 2.0, 3.0]) >>> cxc.guess_chart(x) Cart3D(M=Rn(3))
- coordinax.charts.guess_chart(obj: frozenset[str], /) AbstractChart
- Parameters:
_ (Any)
- Return type:
Infer a chart from the keys of a component dictionary.
Note that many charts may share the same component names (e.g., Spherical3D and MathSpherical3D both use ‘r’, ‘theta’, ‘phi’). These are completely indistinguishable from component names alone, so this function will return the first matching chart it finds. Since the function is cached, the result will be consistent across calls.
>>> import coordinax.charts as cxc >>> d = {"x": 1.0, "y": 2.0, "z": 3.0} >>> chart = cxc.guess_chart(d) >>> chart Cart3D(M=Rn(3))
- coordinax.charts.guess_chart(obj: dict[str, Any], /) AbstractChart
- Parameters:
_ (Any)
- Return type:
Infer a chart from the keys of a component dictionary.
Note that many charts may share the same component names (e.g., Spherical3D and MathSpherical3D both use ‘r’, ‘theta’, ‘phi’). These are completely indistinguishable from component names alone, so this function will return the first matching chart it finds. Since the function is cached, the result will be consistent across calls.
>>> import coordinax.charts as cxc >>> d = {"x": 1.0, "y": 2.0, "z": 3.0} >>> chart = cxc.guess_chart(d) >>> chart Cart3D(M=Rn(3))
- coordinax.charts.guess_chart(_: jaxtyping.Shaped[Array, '*batch 1'] | jaxtyping.Shaped[AbstractQuantity, '*batch 1'], /) AbstractChart
- Parameters:
_ (Any)
- Return type:
Infer a 1D Cartesian chart from last dimension of a value / quantity.
>>> import unxt as u >>> import coordinax.charts as cx >>> q = u.Q([1.0], "m") >>> cxc.guess_chart(q) Cart1D(M=Rn(1))
- coordinax.charts.guess_chart(_: jaxtyping.Shaped[Array, '*batch 2'] | jaxtyping.Shaped[AbstractQuantity, '*batch 2'], /) AbstractChart
- Parameters:
_ (Any)
- Return type:
Infer a 2D Cartesian chart from last dimension of a value / quantity.
>>> import unxt as u >>> import coordinax.charts as cx >>> q = u.Q([1.0, 2.0], "m") >>> cxc.guess_chart(q) Cart2D(M=Rn(2))
- coordinax.charts.guess_chart(_: jaxtyping.Shaped[Array, '*batch 3'] | jaxtyping.Shaped[AbstractQuantity, '*batch 3'], /) AbstractChart
- Parameters:
_ (Any)
- Return type:
Infer a 3D Cartesian chart from last dimension of a value / quantity.
>>> import unxt as u >>> import coordinax.charts as cx >>> q = u.Q([1.0, 2.0, 3.0], "m") >>> cxc.guess_chart(q) Cart3D(M=Rn(3))
- coordinax.charts.guess_chart(_: jaxtyping.Shaped[Array, '*batch N'] | jaxtyping.Shaped[AbstractQuantity, '*batch N'], /) AbstractChart
- Parameters:
_ (Any)
- Return type:
Infer a N-dimensional Cartesian chart from last dimension of a value / quantity.
>>> import unxt as u >>> import coordinax.charts as cx >>> q = u.Q([1.0, 2.0, 3.0, 4.0], "m") >>> cxc.guess_chart(q) CartND(M=Rn(True))
- coordinax.charts.guess_chart(obj: RadialRepresentation) Radial1D
- Parameters:
_ (Any)
- Return type:
Guess astropy.coordinates.RadialRepresentation ->
Radial1D.>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.RadialRepresentation(distance=1 * apyu.kpc) >>> cxc.guess_chart(vec) Radial1D(M=Rn(1))
- coordinax.charts.guess_chart(obj: UnitSphericalRepresentation) LonLatSphericalTwoSphere
- Parameters:
_ (Any)
- Return type:
Guess
astropy.UnitSphericalRepresentation->LonLatSphericalTwoSphere.>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.UnitSphericalRepresentation(lon=90 * apyu.deg, lat=45 * apyu.deg) >>> cxc.guess_chart(vec) LonLatSphericalTwoSphere(M=Sn(2))
- coordinax.charts.guess_chart(obj: CartesianRepresentation) Cart3D
- Parameters:
_ (Any)
- Return type:
Guess astropy.coordinates.CartesianRepresentation ->
Cart3D.>>> import astropy.coordinates as apyc >>> import coordinax.charts as cxc
>>> cxc.guess_chart(apyc.CartesianRepresentation(1, 2, 3)) Cart3D(M=Rn(3))
- coordinax.charts.guess_chart(obj: CylindricalRepresentation) Cylindrical3D
- Parameters:
_ (Any)
- Return type:
Guess astropy.coordinates.CylindricalRepresentation ->
Cylindrical3D.>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.CylindricalRepresentation(1 * apyu.km, 2 * apyu.deg, 3 * apyu.km) >>> cxc.guess_chart(vec) Cylindrical3D(M=Rn(3))
- coordinax.charts.guess_chart(obj: PhysicsSphericalRepresentation) Spherical3D
- Parameters:
_ (Any)
- Return type:
Guess astropy.coordinates.PhysicsSphericalRepresentation ->
Spherical3D.>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.PhysicsSphericalRepresentation( ... r=1 * apyu.kpc, theta=45 * apyu.deg, phi=90 * apyu.deg) >>> cxc.guess_chart(vec) Spherical3D(M=Rn(3))
- coordinax.charts.guess_chart(obj: SphericalRepresentation) LonLatSpherical3D
- Parameters:
_ (Any)
- Return type:
Guess astropy.coordinates.SphericalRepresentation ->
LonLatSpherical3D.>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.SphericalRepresentation( ... lon=90 * apyu.deg, lat=45 * apyu.deg, distance=1 * apyu.kpc) >>> cxc.guess_chart(vec) LonLatSpherical3D(M=Rn(3))
- Parameters:
_ (
Any)- Return type:
- coordinax.charts.cdict(_: Any, /)#
Normalize an input object into a component dictionary.
Keys are component names and values are corresponding scalars/arrays or quantities.
- Parameters:
obj –
An object to extract a component dictionary from. Dispatch rules include:
collections.abc.Mapping: returned as-is
unxt.Quantity: treated as Cartesian coordinates with components in the last dimension, matched to the appropriate Cartesian chart
Point: extracted from
obj.data
_ (Any)
- Returns:
A mapping from component names to values.
- Return type:
Examples
>>> import jax.numpy as jnp >>> import coordinax.main as cx >>> import unxt as u
Extract from a Mapping:
>>> d = {"x": u.Q(1.0, "m"), "y": u.Q(2.0, "m"), "z": u.Q(3.0, "m")} >>> cx.cdict(d) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
>>> d = {"x": 1.0, "y": 2.0, "z": 3.0} >>> cx.cdict(d) {'x': 1.0, 'y': 2.0, 'z': 3.0}
Extract from a unxt.Quantity treated as Cartesian:
>>> q = u.Q([1, 2, 3], "m") >>> cx.cdict(q) {'x': Q(1, 'm'), 'y': Q(2, 'm'), 'z': Q(3, 'm')}
Specify the chart for a unxt.Quantity. For homogeneous unit Quantities, this must be Cartesian:
>>> cx.cdict(q, cx.cart3d) {'x': Q(1, 'm'), 'y': Q(2, 'm'), 'z': Q(3, 'm')}
Extract from an Array-like object with a registered chart:
>>> arr = jnp.array([1.0, 2.0, 3.0]) >>> cx.cdict(arr, cx.cart3d) {'x': Array(1., dtype=float64), 'y': Array(2., dtype=float64), 'z': Array(3., dtype=float64)}
Return a dictionary as-is.
>>> import coordinax.main as cx >>> d = {"x": 1.0, "y": 2.0} >>> cx.cdict(d) {'x': 1.0, 'y': 2.0}
Return a dictionary as-is.
>>> import coordinax.charts as cxc >>> d = {"x": 1.0, "y": 2.0} >>> cxc.cdict(d, cxc.cart2d) {'x': 1.0, 'y': 2.0}
- coordinax.charts.cdict(obj: AbstractQuantity, /) dict[str, Any]
Extract component dictionary from a Quantity.
Treats the Quantity as a Cartesian vector with components in the last dimension. The appropriate Cartesian chart is determined from the last dimension of the quantity.
>>> import coordinax.main as cx >>> import unxt as u >>> q = u.Q([1.0, 2.0, 3.0], "m") >>> cx.cdict(q) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
Extract component dictionary from a Quantity using specified keys.
Treats the Quantity as a vector with components in the last dimension, splitting along that axis according to the provided keys.
This function requires that: 1. The last dimension of the quantity matches the number of chart components 2. The chart has homogeneous coordinate dimensions (all components have the
same physical dimension, like Cartesian charts)
- Raises:
ValueError – If the last dimension of the quantity doesn’t match the chart’s component count, or if dimensions don’t match.
- Parameters:
_ (Any)
- Return type:
Examples
>>> import coordinax.charts as cxc >>> import unxt as u
>>> q = u.Q([1.0, 2.0, 3.0], "m") >>> cxc.cdict(q, ('x', 'y', 'z')) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
Extract component dictionary from a 1D
QMatrix.This overload supports heterogeneous per-component units by constructing one quantity per chart component from the corresponding numeric slice and unit in the
QMatrix.- Raises:
ValueError – If
objis not 1D, or if the last dimension does not match the number of provided keys.- Parameters:
_ (Any)
- Return type:
Examples
>>> import jax.numpy as jnp >>> import unxt as u >>> from coordinax.internal import QMatrix
>>> q = QMatrix(jnp.array([1.0, 2.0, 3.0]), ... unit=("m", "km/s", "rad")) >>> cxc.cdict(q, ('x', 'y', 'z')) {'x': Q(1., 'm'), 'y': Q(2., 'km / s'), 'z': Q(3., 'rad')}
- coordinax.charts.cdict(obj: AbstractQuantity, chart: AbstractChart, /) dict[str, Any]
Extract component dictionary from a Quantity.
Treats the Quantity as a vector with components in the last dimension, splitting along that axis according to the chart’s component names.
This function requires that: 1. The last dimension of the quantity matches the number of chart components 2. The chart has homogeneous coordinate dimensions (all components have the
same physical dimension, like Cartesian charts)
>>> import coordinax.charts as cxc >>> import unxt as u
>>> q = u.Q([1.0, 2.0, 3.0], "m") >>> cxc.cdict(q, cxc.cart3d) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
- coordinax.charts.cdict(obj: QMatrix, chart: AbstractChart, /) dict[str, Any]
Extract component dictionary from a 1D
QMatrix.This overload supports heterogeneous per-component units by constructing one quantity per chart component from the corresponding numeric slice and unit in the
QMatrix.>>> import jax.numpy as jnp >>> import coordinax.charts as cxc >>> import unxt as u >>> from coordinax.internal import QMatrix
>>> q = QMatrix( ... jnp.array([1.0, 2.0, 3.0]), ... unit=(u.unit("m"), u.unit("km/s"), u.unit("rad")), ... ) >>> cxc.cdict(q, cxc.cart3d) {'x': Q(1., 'm'), 'y': Q(2., 'km / s'), 'z': Q(3., 'rad')}
Extract component dictionary from an array.
- Raises:
ValueError – If the last dimension of the quantity doesn’t match a known Cartesian chart (0D, 1D, 2D, or 3D).
- Parameters:
_ (Any)
- Return type:
Examples
>>> import coordinax.main as cx >>> import jax.numpy as jnp >>> arr = jnp.array([1.0, 2.0, 3.0]) >>> cx.cdict(arr, ('x', 'y', 'z')) {'x': Array(1., dtype=float64), 'y': Array(2., dtype=float64), 'z': Array(3., dtype=float64)}
- coordinax.charts.cdict(obj: ArrayLike, chart: AbstractChart, /) dict[str, Any]
Extract component dictionary from an array.
>>> import coordinax.main as cx >>> import jax.numpy as jnp >>> arr = jnp.array([1.0, 2.0, 3.0]) >>> cx.cdict(arr, cx.cart3d) {'x': Array(1., dtype=float64), 'y': Array(2., dtype=float64), 'z': Array(3., dtype=float64)}
- coordinax.charts.cdict(obj: ArrayLike, unit: Unit | UnitBase | CompositeUnit | str | UnitsMatrix | None, keys: tuple[str, ...], /) dict[str, Any]
Extract component dictionary from an array.
>>> import coordinax.main as cx >>> import jax.numpy as jnp >>> arr = jnp.array([1.0, 2.0, 3.0]) >>> cx.cdict(arr, "m", ('x', 'y', 'z')) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
- coordinax.charts.cdict(obj: ArrayLike, unit: Unit | UnitBase | CompositeUnit | str | UnitsMatrix | None, chart: AbstractChart, /) dict[str, Any]
Extract component dictionary from an array.
>>> import coordinax.main as cx >>> import jax.numpy as jnp >>> arr = jnp.array([1.0, 2.0, 3.0]) >>> cx.cdict(arr, "m", cx.cart3d) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
- coordinax.charts.cdict(obj: ArrayLike, unit: Unit | UnitBase | CompositeUnit | str | UnitsMatrix, /) dict[str, Any]
Extract component dictionary from an array.
Treats the array as a Cartesian vector with components in the last dimension. The appropriate Cartesian chart is determined from the last dimension of the quantity.
>>> import coordinax.charts as cxc >>> import jax.numpy as jnp >>> arr = jnp.array([1.0, 2.0, 3.0]) >>> cxc.cdict(arr, "m") {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
- coordinax.charts.cdict(obj: ArrayLike, usys: AbstractUnitSystem, chart: AbstractChart, /) dict[str, Any]
Extract component dictionary from an array.
- Raises:
ValueError – If the last dimension of the quantity doesn’t match a known Cartesian chart (0D, 1D, 2D, or 3D).
- Parameters:
_ (Any)
- Return type:
Examples
>>> import coordinax.main as cx >>> import unxt as u >>> import jax.numpy as jnp >>> arr = jnp.array([1.0, 2.0, 3.0]) >>> cx.cdict(arr, u.unitsystems.si, cx.cart3d) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
Extract component dictionary from a Point.
>>> import coordinax.main as cx >>> import unxt as u >>> vec = cx.Point.from_(u.Q([1, 2, 3], "m")) >>> d = cx.cdict(vec) >>> list(d.keys()) ['x', 'y', 'z']
Extract component dictionary from a Tangent.
>>> import coordinax.main as cx >>> import coordinax.representations as cxr >>> import coordinax.charts as cxc >>> import unxt as u >>> d = {"x": u.Q(1.0, "m/s"), "y": u.Q(2.0, "m/s"), "z": u.Q(3.0, "m/s")} >>> vec = cx.Tangent.from_(d, cxc.cart3d, cxr.coord_vel) >>> d = cx.cdict(vec) >>> list(d.keys()) ['x', 'y', 'z']
- coordinax.charts.cdict(r: CartesianRepresentation) dict[str, Any]
Convert an astropy CartesianRepresentation to a CDict.
>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.CartesianRepresentation(1 * apyu.km, 2 * apyu.km, 3 * apyu.km) >>> cxc.cdict(vec) {'x': Q(1., 'km'), 'y': Q(2., 'km'), 'z': Q(3., 'km')}
- coordinax.charts.cdict(r: CylindricalRepresentation) dict[str, Any]
Convert an astropy CylindricalRepresentation to a CDict.
>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.CylindricalRepresentation(1 * apyu.m, 45 * apyu.deg, 3 * apyu.m) >>> cxc.cdict(vec) {'rho': Q(1., 'm'), 'phi': Q(45., 'deg'), 'z': Q(3., 'm')}
- coordinax.charts.cdict(r: PhysicsSphericalRepresentation) dict[str, Any]
Convert an astropy PhysicsSphericalRepresentation to a CDict.
>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.PhysicsSphericalRepresentation( ... phi=45 * apyu.deg, theta=30 * apyu.deg, r=1 * apyu.m) >>> cxc.cdict(vec) {'r': Q(1., 'm'), 'theta': Q(30., 'deg'), 'phi': Q(45., 'deg')}
- coordinax.charts.cdict(r: SphericalRepresentation) dict[str, Any]
Convert an astropy SphericalRepresentation to a CDict.
>>> import astropy.coordinates as apyc >>> import astropy.units as apyu >>> import coordinax.charts as cxc
>>> vec = apyc.SphericalRepresentation( ... lon=90 * apyu.deg, lat=45 * apyu.deg, distance=1 * apyu.kpc) >>> cxc.cdict(vec) {'lon': Q(90., 'deg'), 'lat': Q(45., 'deg'), 'distance': Q(1., 'kpc')}
- coordinax.charts.jac_pt_map(*args: Any, **kwargs: Any)#
Compute the Jacobian of the chart transition map at a base point.
Examples
>>> import coordinax.charts as cxc >>> import unxt as u >>> J = cxc.jac_pt_map( ... {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")}, ... cxc.cart3d, cxc.sph3d, ... ) >>> J.value.shape (3, 3)
- coordinax.charts.jac_pt_map(at: NoneType, /, *fixed_args: Any, **fixed_kw: Any) Any
Higher-order function for fixed-arg Jacobian point map.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> map = cxc.jac_pt_map(None, cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si) >>> at = {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")} >>> map(at) QMatrix( [[ 1., 0., 0.], [-0., -0., -1.], [ 0., 1., 0.]], '((, , ), (rad / m, rad / m, rad / m), (rad / m, rad / m, rad / m))' )
>>> import jax >>> J = jax.vmap(map)(jax.tree.map(lambda x: x[None], at)) >>> J.shape (1, 3, 3)
- coordinax.charts.jac_pt_map(from_chart: AbstractChart, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None) Callable[[object], Any]
Higher-order function for fixed-arg Jacobian point map.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> map = cxc.jac_pt_map(cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si) >>> at = {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")} >>> map(at) QMatrix( [[ 1., 0., 0.], [-0., -0., -1.], [ 0., 1., 0.]], '((, , ), (rad / m, rad / m, rad / m), (rad / m, rad / m, rad / m))' )
>>> import jax >>> J = jax.vmap(map)(jax.tree.map(lambda x: x[None], at)) >>> J.shape (1, 3, 3)
- coordinax.charts.jac_pt_map(at: Array, from_chart: AbstractChart, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem) Array
Compute the Jacobian at a plain-array base point.
Treats at as a flat numeric array whose elements are the
from_chartcoordinates expressed. Returns the JAX array Jacobian $J^j{}_i = partial tau^j / partial q^i$, without unit annotation.>>> import jax.numpy as jnp >>> import coordinax.charts as cxc >>> import unxt as u
>>> jac_fn = cxc.jac_pt_map(None, cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si)
>>> at = jnp.array([1, 0, 0]) >>> jac_fn(at) Array([[ 1., 0., 0.], [-0., -0., -1.], [ 0., 1., 0.]], dtype=float64)
>>> import jax >>> J = jax.vmap(jac_fn)(at[None]) >>> J.shape (1, 3, 3)
- coordinax.charts.jac_pt_map(at: dict[str, Any], from_chart: AbstractChart, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) Array | QMatrix
Compute the Jacobian at a coordinate-dictionary base point.
The primary dict-input dispatch. Branches on whether the values of at carry physical units:
- Array-valued branch (no units in any value)
Stacks the dict values into a plain array via
jnp.stack, then forwards tojac_pt_map(at_arr, from_chart, to_chart, usys=usys)which requires usys. For chart pairs without an analyticalArraydispatch this means usys must be provided.- Quantity-valued branch (at least one value carries a unit)
Packs at into a 1-D
QMatrixviapack_to_qmatrix(at, keys=from_chart.components), promotes any integer or boolean leaves to the default floating-point dtype (other dtypes, including complex, are left unchanged and will raise aTypeErrorfromjax.jacfwdif passed), then computesJ_qq = jax.jacfwd(pt_map_fn)(at_in). Becausejacfwdapplied to aQMatrix-in /QMatrix-out function yields a nestedQMatrix,_repack_q_from_jacis called to extract the correct 2-D unit structure.
- Returns:
Plain array when at is array-valued;
QMatrixof shape(n_out, n_in)with per-element units otherwise.- Return type:
- Raises:
ValueError – If at keys do not match
from_chart.components(viacheck_data).plum.NotFoundLookupError – If the array-valued branch cannot resolve a dispatch (e.g. generic chart pair with
usys=None).
- Parameters:
Examples
>>> import coordinax.charts as cxc >>> import unxt as u
Quantity-valued dict (no usys needed):
>>> at = {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")} >>> J = cxc.jac_pt_map(at, cxc.cart3d, cxc.sph3d) >>> J.value.shape (3, 3)
Plain-array dict (usys required):
>>> import jax.numpy as jnp >>> at_arr = {"x": jnp.array(1.0), "y": jnp.array(0.0), "z": jnp.array(0.0)} >>> J2 = cxc.jac_pt_map(at_arr, cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si) >>> J2.shape (3, 3)
- coordinax.charts.jac_pt_map(at: Array, from_chart: Cart2D, to_chart: Polar2D, /, *, usys: AbstractUnitSystem | None = None) Array
Compute the Jacobian of the transition function between two charts.
$$ J = frac{partial(r,theta)}{partial(x,y)}
= ( x/r & y/r -y/r^2 & x/r^2 ) = ( costheta & sintheta -sintheta/r & costheta/r )
$$
>>> import coordinax.charts as cxc >>> import unxt as u
>>> x = jnp.array([1.0, 1.0]) >>> cxc.jac_pt_map(cxc.cart2d, cxc.polar2d, usys=u.unitsystems.si)(x) Array([[ 0.70710678, 0.70710678], [-0.5 , 0.5 ]], dtype=float64)
- coordinax.charts.jac_pt_map(at: AbstractQuantity, from_chart: Cart2D, to_chart: Polar2D, /, *, usys: AbstractUnitSystem | None = None) QMatrix
Compute the Jacobian of the transition function between two charts.
$$ J = frac{partial(r,theta)}{partial(x,y)}
= ( x/r & y/r -y/r^2 & x/r^2 ) = ( costheta & sintheta -sintheta/r & costheta/r )
$$
>>> import coordinax.charts as cxc >>> import unxt as u
>>> x = u.Q(jnp.array([1.0, 1.0]), "m") >>> cxc.jac_pt_map(cxc.cart2d, cxc.polar2d, usys=u.unitsystems.si)(x) QMatrix([[ 0.70710678, 0.70710678], [-0.5 , 0.5 ]], '((, ), (rad / m, rad / m))')
- coordinax.charts.pt_map(*args: Any, **kwargs: Any)#
Transform position coordinates from one chart to another.
This function implements the most general point-coordinate map between two compatible chart representations of the same geometric point. It is a point-wise map that preserves the physical location while changing the coordinate description.
For charts in the same atlas on the same manifold, this reduces to the ordinary chart transition map handled by pt_map. It is the intrinsic coordinate-change operation: the underlying point on the manifold is unchanged, and only its coordinate representation is changed.
However, this function is not restricted to two charts on the same manifold. It may also represent a realization-style map between charts attached to different manifolds when one is a realization of the other, such as an intrinsic chart on an embedded manifold and a chart on its ambient manifold. In that case, this function may change both the chart and the manifold in which the point is being represented.
Mathematical Definition:
Let $(U, varphi_{mathrm{from}})$ and $(V, varphi_{mathrm{to}})$ be charts on the same manifold $M$, with overlapping domains. The transition map is
- $$
varphi_{mathrm{to}} circ varphi_{mathrm{from}}^{-1} : varphi_{mathrm{from}}(U cap V) to varphi_{mathrm{to}}(U cap V).
$$
If a point $p in U cap V$ has coordinates $q = varphi_{mathrm{from}}(p)$, then this function returns $p’ = varphi_{mathrm{to}}(p)$ for the same manifold point.
More generally, if $varphi_{mathrm{from}} : U subset M to mathbb{R}^n$ and $psi_{mathrm{to}} : W subset N to mathbb{R}^m$ are chart maps on manifolds $M$ and $N$, and there is a point map $F : M supset U to W subset N$, then pt_map represents the coordinate expression
$$ psi_{mathrm{to}} circ F circ varphi_{mathrm{from}}^{-1}. $$
3D Spherical → Cartesian:
- $$
x &= r sintheta cosphi \ y &= r sintheta sinphi \ z &= r costheta
$$
- Raises:
NotImplementedError – If no transformation rule is registered for the specific pair of charts
(to_chart, from_chart).- Parameters:
- Return type:
Notes
This is a position-only transformation.
This function may map between charts on the same manifold or across manifolds, provided a compatible point map is defined between them.
Transformations preserve physical dimensions. For example, converting from polar to Cartesian preserves that
rhas length dimension and producesxandywith length dimension.Some transformations may introduce singularities (e.g., polar coordinates at the origin, spherical coordinates at poles).
Transformations are composable: transforming $A to B to C$ yields the same result as a direct $A to C$ transformation (up to numerical precision).
Identity transformations (same
from_chartandto_chart) return the input unchanged.
Examples
>>> import quaxed.numpy as jnp >>> import coordinax.charts as cxc >>> import unxt as u
Transform from 2D polar to Cartesian:
>>> p_polar = {"r": u.Q(2.0, "m"), "theta": u.Angle(jnp.pi / 4, "rad")} >>> cxc.pt_map(p_polar, cxc.polar2d, cxc.cart2d) {'x': Q(1.41421356, 'm'), 'y': Q(1.41421356, 'm')}
Transform from 3D spherical to Cartesian:
>>> p_sph = {"theta": u.Angle(jnp.pi / 2, "rad"), "phi": u.Angle(0.0, "rad"), ... "r": u.Q(5.0, "km")} >>> cxc.pt_map(p_sph, cxc.sph3d, cxc.cart3d) {'x': Q(5., 'km'), 'y': Q(0., 'km'), 'z': Q(3.061617e-16, 'km')}
Transform from Cartesian to cylindrical:
>>> p_xyz = {"x": u.Q(3.0, "m"), "y": u.Q(4.0, "m"), "z": u.Q(5.0, "m")} >>> cxc.pt_map(p_xyz, cxc.cart3d, cxc.cyl3d) {'rho': Q(5., 'm'), 'phi': Q(0.92729522, 'rad'), 'z': Q(5., 'm')}
Return a partial function for point transformation.
>>> import coordinax.charts as cxc >>> import unxt as u
Coordinates without units are the default.
>>> q = {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")} >>> map = cxc.pt_map(None, cxc.cart3d, cxc.sph3d) >>> map(q) {'r': Q(1., 'm'), 'theta': Q(1.57079633, 'rad'), 'phi': Q(0., 'rad')}
Coordinates without units are also accepted, interpreted having units of the unxt.AbstractUnitSystem, which must be passed.
>>> q = {"x": 1.0, "y": 0.0, "z": 0.0} >>> map = cxc.pt_map(None, cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si) >>> map(q) {'r': Array(1., dtype=float64, ...), 'theta': Array(1.57079633, dtype=float64), 'phi': Array(0., dtype=float64, ...)}
unxt.Quantity inputs are also accepted, and are interpreted as being in Cartesian coordinates.
>>> p = u.Q([1.0, 0.0, 0.0], "m") >>> map = cxc.pt_map(None, cxc.cart3d, cxc.sph3d) >>> map(p) QMatrix([1. , 1.57079633, 0. ], '(m, rad, rad)')
Array-Like inputs are interpreted as Cartesian coordinates with units from the required unxt.AbstractUnitSystem.
>>> q = [1.0, 0.0, 0.0] >>> map = cxc.pt_map(None, cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si) >>> map(q) Array([1. , 1.57079633, 0. ], dtype=float64)
- coordinax.charts.pt_map(from_chart: AbstractChart, to_chart: AbstractChart, /, **fixed_kw: Any) Callable[..., Any]
Return a partial function for point transformation.
>>> import coordinax.charts as cxc >>> import unxt as u
Coordinates without units are the default.
>>> p = {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")} >>> map = cxc.pt_map(cxc.cart3d, cxc.sph3d) >>> map(p) {'r': Q(1., 'm'), 'theta': Q(1.57079633, 'rad'), 'phi': Q(0., 'rad')}
Coordinates without units are also accepted, interpreted having units of the unxt.AbstractUnitSystem, which must be passed.
>>> p = {"x": 1.0, "y": 0.0, "z": 0.0} >>> map = cxc.pt_map(cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si) >>> map(p) {'r': Array(1., dtype=float64, ...), 'theta': Array(1.57079633, dtype=float64), 'phi': Array(0., dtype=float64, ...)}
unxt.Quantity inputs are also accepted, and are interpreted as being in Cartesian coordinates.
>>> p = u.Q([1.0, 0.0, 0.0], "m") >>> map = cxc.pt_map(cxc.cart3d, cxc.sph3d) >>> map(p) QMatrix([1. , 1.57079633, 0. ], '(m, rad, rad)')
Array-Like inputs are interpreted as Cartesian coordinates with units from the required unxt.AbstractUnitSystem.
>>> p = [1.0, 0.0, 0.0] >>> map = cxc.pt_map(cxc.cart3d, cxc.sph3d, usys=u.unitsystems.si) >>> map(p) Array([1. , 1.57079633, 0. ], dtype=float64)
- coordinax.charts.pt_map(x: Any, from_chart: AbstractChart, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) Any
Point transformation from chart to chart, using their manifolds.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {} >>> cxc.pt_map(p, cxc.cart0d, cxc.cart0d) {}
>>> p = {"r": u.Q(5.0, "m")} >>> cxc.pt_map(p, cxc.radial1d, cxc.cart1d) {'x': Q(5., 'm')}
>>> p = {"r": u.Q(5.0, "m"), "theta": u.Q(90, "deg")} >>> cxc.pt_map(p, cxc.polar2d, cxc.cart2d) {'x': Q(3.061617e-16, 'm'), 'y': Q(5., 'm')}
>>> p = {"r": u.Q(5.0, "m"), "theta": u.Q(90, "deg"), "phi": u.Q(0, "deg")} >>> cxc.pt_map(p, cxc.sph3d, cxc.cart3d) {'x': Q(5., 'm'), 'y': Q(0., 'm'), 'z': Q(3.061617e-16, 'm')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: AbstractManifold, from_chart: AbstractChart, to_M: AbstractManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
AbstractChart -> Cartesian -> AbstractChart.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"r": u.Q(5.0, "m"), "theta": u.Q(90, "deg")} >>> map = cxc.pt_map.invoke(dict[str, u.Q], cxm.Rn, cxc.AbstractChart, ... cxm.Rn, cxc.AbstractChart) >>> map(p, cxm.R2, cxc.polar2d, cxm.R2, cxc.cart2d) {'x': Q(3.061617e-16, 'm'), 'y': Q(5., 'm')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: AbstractChart, to_M: EuclideanManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Identity conversion for matching charts.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u >>> import quaxed.numpy as jnp
>>> q = {} >>> q2 = cxc.pt_map(q, cxm.R0, cxc.cart0d, cxm.R0, cxc.cart0d) >>> q is q2 True
>>> q = {"r": u.Q(3.0, "m")} >>> q2 = cxc.pt_map(q, cxm.R1, cxc.radial1d, cxm.R1, cxc.radial1d) >>> q is q2 True
>>> q = {"x": u.Q(1.0, "m"), "y": u.Q(2.0, "m")} >>> q2 = cxc.pt_map(q, cxm.R2, cxc.cart2d, cxm.R2, cxc.cart2d) >>> q is q2 True
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Radial1D, to_M: EuclideanManifold, to_chart: Cart1D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Radial1D -> Cart1D.
The r coordinate is converted to the x coordinate of the 1D system.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> q = {"r": u.Q(5.0, "m")} >>> cxc.pt_map(q, cxm.R1, cxc.radial1d, cxm.R1, cxc.cart1d) {'x': Q(5., 'm')}
>>> q = {"r": 5.0} # No units >>> cxc.pt_map(q, cxm.R1, cxc.radial1d, cxm.R1, cxc.cart1d) {'x': 5.0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cart1D, to_M: EuclideanManifold, to_chart: Radial1D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cart1D -> Radial1D.
The x coordinate is converted to the r coordinate of the 1D system.
Assumptions:
Cart1D and Radial1D are
>>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"x": u.Q(5.0, "m")} >>> cxc.pt_map(p, cxm.R1, cxc.cart1d, cxm.R1, cxc.radial1d) {'r': Q(5., 'm')}
>>> p = {"x": 5.0} # No units >>> cxc.pt_map(p, cxm.R1, cxc.cart1d, cxm.R1, cxc.radial1d) {'r': 5.0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Polar2D, to_M: EuclideanManifold, to_chart: Cart2D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Polar2D -> Cart2D.
The r and theta coordinates are converted to the x and y coordinates of the 2D Cartesian system.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"r": u.Q(5.0, "m"), "theta": u.Q(90, "deg")} >>> cxc.pt_map(p, cxm.R2, cxc.polar2d, cxm.R2, cxc.cart2d) {'x': Q(3.061617e-16, 'm'), 'y': Q(5., 'm')}
>>> p = {"r": 5, "theta": 90} # No units >>> usys = u.unitsystem("km", "deg") >>> cxc.pt_map(p, cxm.R2, cxc.polar2d, cxm.R2, cxc.cart2d, usys=usys) {'x': Array(3.061617e-16, dtype=float64, ...), 'y': Array(5., dtype=float64, ...)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cart2D, to_M: EuclideanManifold, to_chart: Polar2D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cart2D -> Polar2D.
The x and y coordinates are converted to the r and theta coordinates of the 2D polar system.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"x": u.Q(3, "m"), "y": u.Q(4, "m")} >>> cxc.pt_map(p, cxm.R2, cxc.cart2d, cxm.R2, cxc.polar2d) {'r': Q(5., 'm'), 'theta': Q(0.92729522, 'rad')}
>>> p = {"x": 3, "y": 4} # No units >>> cxc.pt_map(p, cxm.R2, cxc.cart2d, cxm.R2, cxc.polar2d) {'r': Array(5., dtype=float64, ...), 'theta': Array(0.92729522, dtype=float64, ...)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cylindrical3D, to_M: EuclideanManifold, to_chart: Cart3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cylindrical3D -> Cart3D.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"rho": u.Q(1.0, "m"), "phi": u.Q(90, "deg"), "z": u.Q(2.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, cxc.cart3d) {'x': Q(6.123234e-17, 'm'), 'y': Q(1., 'm'), 'z': Q(2., 'm')}
>>> p = {"rho": 1.0, "phi": 90, "z": 2.0} # No units >>> usys = u.unitsystem("m", "deg") >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, cxc.cart3d, usys=usys) {'x': Array(6.123234e-17, dtype=float64, ...), 'y': Array(1., dtype=float64, ...), 'z': 2.0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Spherical3D, to_M: EuclideanManifold, to_chart: Cart3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Spherical3D -> Cart3D.
>>> import coordinax.charts as cxc >>> import unxt as u >>> import quaxed.numpy as jnp
A point on the +z axis (theta=0):
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(0, "deg"), "phi": u.Q(0, "deg")} >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.cart3d) {'x': Q(0., 'm'), 'y': Q(0., 'm'), 'z': Q(1., 'm')}
A point on the equator (theta=90 deg, phi=0):
>>> p = {"r": 2.0, "theta": 90, "phi": 0} >>> usys = u.unitsystem("m", "deg") >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.cart3d, usys=usys) {'x': Array(2., dtype=float64, ...), 'y': Array(0., dtype=float64, ...), 'z': Array(1.2246468e-16, dtype=float64, ...)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: LonLatSpherical3D, to_M: EuclideanManifold, to_chart: Cart3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
LonLatSpherical3D -> Cart3D.
>>> import coordinax.charts as cxc >>> import unxt as u
A point at the north pole (lat=90 deg):
>>> p = {"lon": u.Q(0, "deg"), "lat": u.Q(90, "deg"), "distance": u.Q(1.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.lonlat_sph3d, cxm.R3, cxc.cart3d) {'x': Q(6.123234e-17, 'm'), 'y': Q(0., 'm'), 'z': Q(1., 'm')}
A point on the equator at lon=0:
>>> p = {"lon": 0, "lat": 0, "distance": 2} >>> cxc.pt_map(p, cxm.R3, cxc.lonlat_sph3d, cxm.R3, cxc.cart3d) {'x': Array(2., dtype=float64, ...), 'y': Array(0., dtype=float64, ...), 'z': Array(0., dtype=float64, ...)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: LonCosLatSpherical3D, to_M: EuclideanManifold, to_chart: Cart3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
LonCosLatSpherical3D -> Cart3D.
Components are (lon_coslat, lat, r), where lon_coslat := lon * cos(lat). Longitude is undefined at the poles (cos(lat) == 0); we set lon = 0 by convention there to avoid NaNs.
>>> import coordinax.charts as cxc >>> import unxt as u
A point on the equator (lat=0, so lon_coslat = lon):
>>> p = {"lon_coslat": u.Q(0, "deg"), "lat": u.Q(0, "deg"), ... "distance": u.Q(1.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.loncoslat_sph3d, cxm.R3, cxc.cart3d) {'x': Q(1., 'm'), 'y': Q(0., 'm'), 'z': Q(0., 'm')}
At the north pole (lat=90), lon_coslat is effectively 0 regardless of lon:
>>> p = {"lon_coslat": u.Q(0, "deg"), "lat": u.Q(90, "deg"), ... "distance": u.Q(2.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.loncoslat_sph3d, cxm.R3, cxc.cart3d) {'x': Q(1.2246468e-16, 'm'), 'y': Q(0., 'm'), 'z': Q(2., 'm')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: MathSpherical3D, to_M: EuclideanManifold, to_chart: Cart3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
MathSpherical3D -> Cart3D.
theta: azimuth in the x-y plane (longitude-like)
phi : polar angle from +z, with phi in [0, pi]
>>> import coordinax.charts as cxc >>> import unxt as u
A point on the +z axis (phi=0):
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(0, "deg"), "phi": u.Q(0, "deg")} >>> cxc.pt_map(p, cxm.R3, cxc.math_sph3d, cxm.R3, cxc.cart3d) {'x': Q(0., 'm'), 'y': Q(0., 'm'), 'z': Q(1., 'm')}
A point on the +x axis (theta=0, phi=90):
>>> p = {"r": u.Q(2.0, "m"), "theta": u.Q(0, "deg"), "phi": u.Q(90, "deg")} >>> cxc.pt_map(p, cxm.R3, cxc.math_sph3d, cxm.R3, cxc.cart3d) {'x': Q(2., 'm'), 'y': Q(0., 'm'), 'z': Q(1.2246468e-16, 'm')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: ProlateSpheroidal3D, to_M: EuclideanManifold, to_chart: Cart3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
ProlateSpheroidal3D -> Cart3D.
We calculate through cylindrical coordinates first:
$rho = sqrt{(mu-Delta^2)left(1-frac{|\nu|}{Delta^2}right)}$ $z = sqrt{mu,frac{|\nu|}{Delta^2}};mathrm{sign}(nu)$ $phi = phi.$
Then convert to Cartesian:
$x=rhocosphi$, $y=rhosinphi$, $z=z$.
>>> import coordinax.charts as cxc >>> import unxt as u >>> import quaxed.numpy as jnp
>>> prolatesph3d = cxc.ProlateSpheroidal3D(Delta=u.StaticQuantity(2.0, "m"))
>>> p = {"mu": u.Q(5.0, "m2"), "nu": u.Q(1.0, "m2"), "phi": u.Q(0, "rad")} >>> cxc.pt_map(p, cxm.R3, prolatesph3d, cxm.R3, cxc.cart3d) {'x': Q(0.8660254, 'm'), 'y': Q(0., 'm'), 'z': Q(1.11803399, 'm')}
>>> p = {"mu": 5.0, "nu": 1.0, "phi": 0} # No units >>> usys = u.unitsystem("m", "rad") >>> cxc.pt_map(p, cxm.R3, prolatesph3d, cxm.R3, cxc.cart3d, usys=usys) {'x': Array(0.8660254, dtype=float64), 'y': Array(0., dtype=float64), 'z': Array(1.11803399, dtype=float64)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cart3D, to_M: EuclideanManifold, to_chart: Cylindrical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cart3D -> Cylindrical3D.
>>> import coordinax.main as cx >>> import unxt as u
>>> p = {"x": u.Q(3.0, "m"), "y": u.Q(4.0, "m"), "z": u.Q(5.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cart3d, cxm.R3, cxc.cyl3d) {'rho': Q(5., 'm'), 'phi': Q(0.92729522, 'rad'), 'z': Q(5., 'm')}
>>> p = {"x": 3.0, "y": 4.0, "z": 5.0} # No units >>> cxc.pt_map(p, cxm.R3, cxc.cart3d, cxm.R3, cxc.cyl3d) {'rho': Array(5., dtype=float64, ...), 'phi': Array(0.92729522, dtype=float64, ...), 'z': 5.0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cart3D | Cylindrical3D, to_M: EuclideanManifold, to_chart: AbstractSpherical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cart3D -> Spherical3D -> AbstractSpherical3D.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"x": u.Q(0.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(1.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cart3d, cxm.R3, cxc.loncoslat_sph3d) {'lon_coslat': Q(0., 'rad'), 'lat': Q(90., 'deg'), 'distance': Q(1., 'm')}
>>> p = {"rho": 0, "phi": 180, "z": 1} >>> usys = u.unitsystem("m", "deg") >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, cxc.loncoslat_sph3d, usys=usys) {'lon_coslat': Array(1.10218212e-14, dtype=float64), 'lat': Array(1.57079633, dtype=float64), 'distance': Array(1., dtype=float64, weak_type=True)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cart3D, to_M: EuclideanManifold, to_chart: Spherical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cart3D -> Spherical3D.
>>> import coordinax.charts as cxc >>> import unxt as u
A point on the +z axis:
>>> p = {"x": u.Q(0.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(1.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cart3d, cxm.R3, cxc.sph3d) {'r': Q(1., 'm'), 'theta': Q(0., 'rad'), 'phi': Q(0., 'rad')}
A point on the +x axis:
>>> p = {"x": 2.0, "y": 0.0, "z": 0.0} # No units >>> cxc.pt_map(p, cxm.R3, cxc.cart3d, cxm.R3, cxc.sph3d) {'r': Array(2., dtype=float64, ...), 'theta': Array(1.57079633, dtype=float64), 'phi': Array(0., dtype=float64, ...)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cylindrical3D, to_M: EuclideanManifold, to_chart: Spherical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cylindrical3D -> Spherical3D.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
A point on the z-axis (rho=0):
>>> p = {"rho": u.Q(0.0, "m"), "phi": u.Q(0, "rad"), "z": u.Q(1.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, cxc.sph3d) {'r': Q(1., 'm'), 'theta': Q(0., 'rad'), 'phi': Q(0, 'rad')}
A point in the xy-plane (z=0):
>>> p = {"rho": 3.0, "phi": 0, "z": 0.0} # No units >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, cxc.sph3d) {'r': Array(3., dtype=float64, ...), 'theta': Array(1.57079633, dtype=float64), 'phi': 0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Spherical3D, to_M: EuclideanManifold, to_chart: Cylindrical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Spherical3D -> Cylindrical3D.
>>> import coordinax.charts as cxc >>> import coordinax.manifolds as cxm >>> import unxt as u
A point on the +z axis (theta=0):
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(0, "rad"), "phi": u.Q(0, "rad")} >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.cyl3d) {'rho': Q(0., 'm'), 'phi': Q(0, 'rad'), 'z': Q(1., 'm')}
A point on the equator (theta=90 deg):
>>> p = {"r": 2.0, "theta": 90, "phi": 0} # No units >>> usys = u.unitsystem("m", "deg") >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.cyl3d, usys=usys) {'rho': Array(2., dtype=float64, ...), 'phi': 0, 'z': Array(1.2246468e-16, dtype=float64, ...)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Spherical3D, to_M: EuclideanManifold, to_chart: LonLatSpherical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Spherical3D -> LonLatSpherical3D.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
Spherical theta=0 corresponds to lat=90 (north pole):
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(0, "rad"), "phi": u.Q(0, "rad")} >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.lonlat_sph3d) {'lon': Q(0, 'rad'), 'lat': Q(90., 'deg'), 'distance': Q(1., 'm')}
Spherical theta=90 deg corresponds to lat=0 (equator):
>>> p = {"r": 1.0, "theta": 0, "phi": 0} # No units >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.lonlat_sph3d) {'lon': 0, 'lat': 1.5707963267948966, 'distance': 1.0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Spherical3D, to_M: EuclideanManifold, to_chart: LonCosLatSpherical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Spherical3D -> LonCosLatSpherical3D.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
On the equator (theta=90 deg), lon_coslat equals lon:
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(90, "deg"), "phi": u.Q(45, "deg")} >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.loncoslat_sph3d) {'lon_coslat': Q(45., 'deg'), 'lat': Q(0., 'deg'), 'distance': Q(1., 'm')}
At the north pole (theta=0), lon_coslat = 0 regardless of phi:
>>> p = {"r": 1.0, "theta": 0, "phi": 45} # No units >>> usys = u.unitsystem("m", "deg") >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.loncoslat_sph3d, usys=usys) {'lon_coslat': Array(2.7554553e-15, dtype=float64, ...), 'lat': 1.5707963267948966, 'distance': 1.0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Spherical3D, to_M: EuclideanManifold, to_chart: MathSpherical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Spherical3D -> MathSpherical3D.
Swaps theta and phi: Physics (theta=polar, phi=azimuth) to Math (theta=azimuth, phi=polar).
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(30, "deg"), "phi": u.Q(60, "deg")} >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.math_sph3d) {'r': Q(1., 'm'), 'theta': Q(60, 'deg'), 'phi': Q(30, 'deg')}
>>> p = {"r": 1.0, "theta": 30, "phi": 60} # No units >>> usys = u.unitsystem("m", "deg") >>> cxc.pt_map(p, cxm.R3, cxc.sph3d, cxm.R3, cxc.math_sph3d, usys=usys) {'r': 1.0, 'theta': 60, 'phi': 30}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: MathSpherical3D, to_M: EuclideanManifold, to_chart: Spherical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
MathSpherical3D -> Spherical3D.
Swaps theta and phi: Math (theta=azimuth, phi=polar) to Physics (theta=polar, phi=azimuth).
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(60, "deg"), "phi": u.Q(30, "deg")} >>> cxc.pt_map(p, cxm.R3, cxc.math_sph3d, cxm.R3, cxc.sph3d) {'r': Q(1., 'm'), 'theta': Q(30, 'deg'), 'phi': Q(60, 'deg')}
>>> p = {"r": 1.0, "theta": 60, "phi": 30} # No units >>> usys = u.unitsystem("m", "deg") >>> cxc.pt_map(p, cxm.R3, cxc.math_sph3d, cxm.R3, cxc.sph3d, usys=usys) {'r': 1.0, 'theta': 30, 'phi': 60}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: ProlateSpheroidal3D, to_M: EuclideanManifold, to_chart: Cylindrical3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
ProlateSpheroidal3D -> Cylindrical3D.
Uses the focal length $Delta$ stored on
from_chart.Validity constraints (enforced by the representation) are:
$Delta > 0$,
$mu ge Delta^2$,
$|nu| le Delta^2$.
The conversion proceeds via
$rho = sqrt{(mu-Delta^2)left(1-frac{|\nu|}{Delta^2}right)}$, $z = sqrt{mu,frac{|\nu|}{Delta^2}},mathrm{sign}(nu)$, $phi = phi$.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> prolatesph3d = cxc.ProlateSpheroidal3D(Delta=u.StaticQuantity(2.0, "m"))
>>> p = {"mu": u.Q(5.0, "m2"), "nu": u.Q(1.0, "m2"), "phi": u.Q(0, "rad")} >>> cxc.pt_map(p, cxm.R3, prolatesph3d, cxm.R3, cxc.cyl3d) {'rho': Q(0.8660254, 'm'), 'phi': Q(0, 'rad'), 'z': Q(1.11803399, 'm')}
>>> p = {"mu": 5.0, "nu": 1.0, "phi": 0} # No units >>> usys = u.unitsystem("m", "rad") >>> cxc.pt_map(p, cxm.R3, prolatesph3d, cxm.R3, cxc.cyl3d, usys=usys) {'rho': Array(0.8660254, dtype=float64), 'phi': 0, 'z': Array(1.11803399, dtype=float64)}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: Cylindrical3D, to_M: EuclideanManifold, to_chart: ProlateSpheroidal3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Cylindrical3D -> ProlateSpheroidal3D.
Uses the focal length $Delta$ stored on
to_chart.Let $R^2 = rho^2$ and $z^2 = z^2$ and define
$S = R^2 + z^2 + Delta^2$, $D_f = R^2 + z^2 - Delta^2$, $D = sqrt{D_f^2 + 4 R^2 Delta^2}$.
Then
$mu = Delta^2 + tfrac12(D + D_f)$ (with numerically-stable branches), $|nu| = dfrac{2Delta^2}{S + D},z^2$, and $nu = |\nu|,mathrm{sign}(z)$, with a stability fix when $Delta^2 - |nu|$ is small.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> prolatesph3d = cxc.ProlateSpheroidal3D(Delta=u.StaticQuantity(2.0, "m"))
A point on the z-axis (rho=0):
>>> p = {"rho": u.Q(0.0, "m"), "phi": u.Q(0, "rad"), "z": u.Q(3.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, prolatesph3d) {'mu': Q(9., 'm2'), 'nu': Q(4., 'm2'), 'phi': Q(0, 'rad')}
A point in the xy-plane (z=0):
>>> p = {"rho": u.Q(2.0, "m"), "phi": u.Q(0, "rad"), "z": u.Q(0.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, prolatesph3d) {'mu': Q(8., 'm2'), 'nu': Q(0., 'm2'), 'phi': Q(0, 'rad')}
Without units:
>>> p = {"rho": 2.0, "phi": 0, "z": 3.0} # No units >>> usys = u.unitsystem("m", "rad") >>> cxc.pt_map(p, cxm.R3, cxc.cyl3d, cxm.R3, prolatesph3d, usys=usys) {'mu': Array(14.52079729, dtype=float64), 'nu': Array(2.47920271, dtype=float64), 'phi': 0}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: ProlateSpheroidal3D, to_M: EuclideanManifold, to_chart: ProlateSpheroidal3D, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
{class}`coordinax.charts.ProlateSpheroidal3D` -> itself.
If the focal length is unchanged (
to_chart.Delta == from_chart.Delta), this is the identity map.If the focal length changes, we convert via cylindrical coordinates:
Prolate(Delta_in) -> Cylindrical -> Prolate(Delta_out).>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
Same focal length (identity transformation):
>>> prolate = cxc.ProlateSpheroidal3D(Delta=u.StaticQuantity(2.0, "m")) >>> p = {"mu": u.Q(5.0, "m2"), "nu": u.Q(1.0, "m2"), "phi": u.Q(0, "rad")} >>> cxc.pt_map(p, cxm.R3, prolate, cxm.R3, prolate) {'mu': Q(5., 'm2'), 'nu': Q(1., 'm2'), 'phi': Q(0., 'rad')}
Different focal lengths (converts via cylindrical):
>>> prolate_in = cxc.ProlateSpheroidal3D(Delta=u.StaticQuantity(2.0, "m")) >>> prolate_out = cxc.ProlateSpheroidal3D(Delta=u.StaticQuantity(3.0, "m")) >>> p = {"mu": u.Q(5.0, "m2"), "nu": u.Q(1.0, "m2"), "phi": u.Q(0, "rad")} >>> cxc.pt_map(p, cxm.R3, prolate_in, cxm.R3, prolate_out) {'mu': Q(9.85889894, 'm2'), 'nu': Q(1.14110106, 'm2'), 'phi': Q(0., 'rad')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: CartND, to_M: EuclideanManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
CartND -> AbstractChart.
Converts from N-dimensional Cartesian (with a single ‘q’ array) to any other chart type by first extracting the appropriate fixed-dimensional Cartesian representation.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
Convert 3D CartND to Spherical:
>>> p = {"q": u.Q([1.0, 0.0, 0.0], "m")} >>> cxc.pt_map(p, cxm.RN, cxc.cartnd, cxm.R3, cxc.sph3d) {'r': Q(1., 'm'), 'theta': Q(1.57079633, 'rad'), 'phi': Q(0., 'rad')}
Convert 2D CartND to Polar:
>>> p = {"q": u.Q([3.0, 4.0], "m")} >>> cxc.pt_map(p, cxm.RN, cxc.cartnd, cxm.R2, cxc.polar2d) {'r': Q(5., 'm'), 'theta': Q(0.92729522, 'rad')}
Convert 1D CartND to Radial:
>>> p = {"q": u.Q([5.0], "m")} >>> cxc.pt_map(p, cxm.RN, cxc.cartnd, cxm.R1, cxc.radial1d) {'r': Q(5., 'm')}
Convert CartND to Cart3D:
>>> p = {"q": u.Q([1.0, 2.0, 3.0], "m")} >>> cxc.pt_map(p, cxm.RN, cxc.cartnd, cxm.R3, cxc.cart3d) {'x': Q(1., 'm'), 'y': Q(2., 'm'), 'z': Q(3., 'm')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: EuclideanManifold, from_chart: AbstractChart, to_M: EuclideanManifold, to_chart: CartND, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
AbstractChart -> CartND.
Converts from any chart type to N-dimensional Cartesian (with a single ‘q’ array) by first transforming to the appropriate fixed-dimensional Cartesian representation.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
Convert Cart3D to CartND:
>>> p = {"x": u.Q(1.0, "m"), "y": u.Q(2.0, "m"), "z": u.Q(3.0, "m")} >>> cxc.pt_map(p, cxm.R3, cxc.cart3d, cxm.R3, cxc.cartnd) {'q': Q([1., 2., 3.], 'm')}
Convert Cart2D to CartND:
>>> p = {"x": u.Q(3.0, "m"), "y": u.Q(4.0, "m")} >>> cxc.pt_map(p, cxm.R2, cxc.cart2d, cxm.R2, cxc.cartnd) {'q': Q([3., 4.], 'm')}
Convert Radial to CartND:
>>> p = {"r": u.Q(3.0, "m")} >>> cxc.pt_map(p, cxc.radial1d, cxc.cartnd) {'q': Q([3.], 'm')}
Convert Cylindrical to CartND (z-axis point):
>>> p = {"rho": u.Q(0.0, "m"), "phi": u.Q(0, "rad"), "z": u.Q(5.0, "m")} >>> cxc.pt_map(p, cxc.cyl3d, cxc.cartnd) {'q': Q([0., 0., 5.], 'm')}
- coordinax.charts.pt_map(q: AbstractQuantity, from_M: EuclideanManifold, from_chart: AbstractChart, to_M: EuclideanManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) AbstractQuantity
Identity point transform for Quantity inputs on uniform-unit charts.
For charts where all components share the same unit (Cartesian charts, 0D/1D charts), a Quantity can be passed directly and is returned unchanged when the source and target charts are the same type.
This dispatch only handles identity transformations (same chart type). For transformations between different chart types with Quantity input, the Quantity must first be converted to a coordinate dictionary.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
1D Cartesian (identity):
>>> q = u.Q([5.0], "m") >>> cxc.pt_map(q, cxm.R1, cxc.cart1d, cxm.R1, cxc.cart1d, usys=None) is q True
2D Cartesian (identity):
>>> q = u.Q([3.0, 4.0], "m") >>> cxc.pt_map(q, cxm.R2, cxc.cart2d, cxm.R2, cxc.cart2d, usys=None) is q True
3D Cartesian (identity):
>>> q = u.Q([1.0, 2.0, 3.0], "km") >>> cxc.pt_map(q, cxm.R3, cxc.cart3d, cxm.R3, cxc.cart3d, usys=None) is q True
N-D Cartesian (identity):
>>> q = u.Q([1.0, 2.0, 3.0, 4.0], "m") >>> cxc.pt_map(q, cxm.RN, cxc.cartnd, cxm.RN, cxc.cartnd, usys=None) is q True
- coordinax.charts.pt_map(p: AbstractQuantity, from_M: EuclideanManifold, from_chart: AbstractChart, to_M: EuclideanManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) QMatrix
Transform a QMatrix between charts.
Converts the components of a QMatrix from one chart to another, preserving the matrix structure with potentially different units per component.
>>> import coordinax.charts as cxc >>> import unxt as u
2D Cartesian to Polar:
>>> q = u.Q([3.0, 4.0], "m") >>> result = cxc.pt_map(q, cxc.cart2d, cxc.polar2d) >>> result.shape (2,) >>> result.unit UnitsMatrix("(m, rad)")
3D Cartesian to Spherical:
>>> q = u.Q([1.0, 0.0, 0.0], "kpc") >>> result = cxc.pt_map(q, cxc.cart3d, cxc.sph3d) >>> result.shape (3,)
Batched transformation:
>>> q_batch = u.Q([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], "m") >>> result = cxc.pt_map(q_batch, cxc.cart3d, cxc.sph3d) >>> result.shape (2, 3)
- coordinax.charts.pt_map(p: Array | list, from_M: EuclideanManifold, from_chart: AbstractChart, to_M: EuclideanManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None) Array
Point transform for array input.
Transforms a point represented as a raw array (without units) from one chart to another. The unit system
usysprovides the units for interpreting the array components.- Return type:
- Returns:
Array – Array of shape
(..., ndim)containing the transformed coordinates into_chart.>>> import coordinax.charts as cxc
>>> import unxt as u
>>> import jax.numpy as jnp
>>> usys = u.unitsystem(“m”, “rad”)
>>> p = jnp.array([1.0, 0.0, 0.0]) # Point on x-axis
>>> cxc.pt_map(p, cxc.cart3d, cxc.sph3d, usys=usys)
Array([1. , 1.57079633, 0. ], dtype=float64)
The result is [r, theta, phi] = [1, pi/2, 0] (on equator, x-axis).
>>> p = jnp.array([2.0, jnp.pi/4, 0.0]) # r=2, theta=45°, phi=0
>>> cxc.pt_map(p, cxc.sph3d, cxc.cart3d, usys=usys)
Array([1.41421356, 0. , 1.41421356], dtype=float64)
>>> p = jnp.array([3.0, 4.0, 5.0])
>>> cxc.pt_map(p, cxc.cart3d, cxc.cyl3d, usys=usys)
Array([5. , 0.92729522, 5. ], dtype=float64)
The result is [rho, phi, z] = [5, arctan(4/3), 5].
>>> p_batch = jnp.array([[1.0, 0.0, 0.0],
… [0.0, 1.0, 0.0],
… [0.0, 0.0, 1.0]])
>>> cxc.pt_map(p_batch, cxc.cart3d, cxc.sph3d, usys=usys)
Array([[1. , 1.57079633, 0. ], – [1. , 1.57079633, 1.57079633], [1. , 0. , 0. ]], dtype=float64)
>>> usys_2d = u.unitsystem(“m”, “rad”)
>>> p = jnp.array([3.0, 4.0])
>>> cxc.pt_map(p, cxc.cart2d, cxc.polar2d, usys=usys_2d)
Array([5. , 0.92729522], dtype=float64)
.. py (function:: pt_map(p: dict[str, typing.Any], from_M: coordinax._src.product.manifold.CartesianProductManifold, from_chart: coordinax._src.product.chart.AbstractCartesianProductChart, to_M: coordinax._src.product.manifold.CartesianProductManifold, to_chart: coordinax._src.product.chart.AbstractCartesianProductChart, /, *, usys: unxt._src.unitsystems.base.AbstractUnitSystem | None = None) -> dict[str, typing.Any]) – :noindex:
ABC CartesianProductChart -> CartesianProductChart (factorwise).
Transforms between product charts by applying coordinax.charts.pt_map to
each factor independently. Requires compatible factor structure (same number
of factors, pairwise compatible).
Mathematical definition
$$ varphi left(prod_i S_i,;prod_i R_i,;pright) – = bigl(varphi(S_i,,R_i,,p_i)bigr)_i $$
where $varphi$ denotes {func}`~coordinax.charts.pt_map` and
$p_i$ are the factor dictionaries split from $p$.
- Parameters:
Examples
>>> import coordinax.charts as cxc >>> import unxt as u
Transform a Cartesian product chart between spatial representations:
>>> prod_crt = cxc.CartesianProductChart((cxc.time1d, cxc.cart3d), ("t", "q")) >>> prod_sph = cxc.CartesianProductChart((cxc.time1d, cxc.sph3d), ("t", "q")) >>> p = {"t.t": u.Q(1.0, "s"), "q.x": u.Q(1.0, "m"), "q.y": u.Q(0.0, "m"), ... "q.z": u.Q(0.0, "m")} >>> result = cxc.pt_map(p, prod_crt, prod_sph) >>> result["t.t"] Q(1., 's') >>> result["q.r"] Q(1., 'm')
- coordinax.charts.pt_map(p: dict[str, Any], from_M: AbstractManifold, from_chart: AbstractChart, to_M: CartesianProductManifold, to_chart: AbstractCartesianProductChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
AbstractChart -> Cartesian -> AbstractCartesianProductChart.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> chart = cxc.CartesianProductChart((cxc.sph2, cxc.cart1d), ("S2", "R1")) >>> map = cxc.pt_map.invoke(dict[str, u.Q], cxc.Cart3D, cxc.CartesianProductChart) >>> try: map({}, cxc.cart3d, chart) ... except NotImplementedError as e: print(e) No general transform between Cart3D and CartesianProductChart. Define explicit rules for non-product to product conversions.
- coordinax.charts.pt_map(p: dict[str, Any], from_M: CartesianProductManifold, from_chart: AbstractCartesianProductChart, to_M: AbstractManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
AbstractCartesianProductChart -> Cartesian -> AbstractChart.
>>> import coordinax.charts as cxc >>> import unxt as u
>>> chart = cxc.CartesianProductChart((cxc.sph2, cxc.cart1d), ("S2", "R1")) >>> map = cxc.pt_map.invoke(dict[str, u.Q], cxc.CartesianProductChart, cxc.Cart3D) >>> try: map({}, chart, cxc.cart3d) ... except NotImplementedError as e: print(e) No general transform between CartesianProductChart and Cart3D. Define explicit rules for product to non-product conversions.
- coordinax.charts.pt_map(p: dict[str, Any], from_chart: EmbeddedChart, to_chart: EmbeddedChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Convert between embedded manifolds with a shared ambient space.
This function transforms intrinsic coordinates from one embedded manifold to another by: 1. Embedding the point into the ambient space of the source manifold 2. Transforming in the ambient space (if the ambient charts differ) 3. Projecting back to the intrinsic coordinates of the target manifold
>>> import coordinax.charts as cxc >>> import coordinax.manifolds as cxm >>> import unxt as u >>> import quaxed.numpy as jnp
Example 1: Two spheres with different radii
Both spheres use the same intrinsic SphericalTwoSphere chart but have different radii:
>>> sphere1 = cxm.EmbeddedChart(cxm.TwoSphereIn3D(radius=u.Q(1.0, "km"))) >>> sphere2 = cxm.EmbeddedChart(cxm.TwoSphereIn3D(radius=u.Q(2.0, "km")))
A point on sphere1 (theta=pi/4, phi=0):
>>> p = {"theta": u.Q(45, "deg"), "phi": u.Q(0, "deg")} >>> p2 = cxc.pt_map(p, sphere1, sphere2) >>> {k: v.uconvert("deg") for k, v in p2.items()} {'theta': Q(45, 'deg'), 'phi': Q(0, 'deg')}
The angular coordinates are preserved (both spheres share the same angular parameterization via projection through the shared ambient space).
- coordinax.charts.pt_map(p: dict[str, Any], from_chart: AbstractChart, to_chart: EmbeddedChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Project an ambient position into an embedded chart.
This transforms coordinates from an ambient chart (e.g., Cartesian or Spherical) into the intrinsic coordinates of an embedded manifold.
>>> import coordinax.charts as cxc >>> import coordinax.manifolds as cxm >>> import unxt as u >>> import quaxed.numpy as jnp
From Cartesian ambient to SphericalTwoSphere intrinsic:
>>> sphere = cxm.EmbeddedChart(cxm.TwoSphereIn3D(radius=u.Q(1.0, "m")))
A point on the unit sphere in Cartesian coords (on equator, x-axis):
>>> p_cart = {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")} >>> cxc.pt_map(p_cart, cxc.cart3d, sphere) {'theta': Q(1.57079633, 'rad'), 'phi': Q(0., 'rad')}
From Spherical ambient to SphericalTwoSphere intrinsic:
The ambient spherical coords (r, theta, phi) project to intrinsic (theta, phi), discarding the radial component:
>>> p_sph = {"r": 5, "theta": 1, "phi": 0.5} # No units >>> usys = u.unitsystem("m", "rad") >>> cxc.pt_map(p_sph, cxc.sph3d, sphere, usys=usys) {'theta': 1, 'phi': 0.5}
- coordinax.charts.pt_map(p: dict[str, Any], from_chart: EmbeddedChart, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Embed intrinsic coordinates into an ambient representation.
This transforms intrinsic coordinates of an embedded manifold into coordinates of an ambient chart, which may differ from the embedding’s native ambient chart.
>>> import coordinax.charts as cxc >>> import coordinax.manifolds as cxm >>> import unxt as u >>> import quaxed.numpy as jnp
From SphericalTwoSphere intrinsic to Cartesian ambient:
>>> sphere = cxm.EmbeddedChart(cxm.TwoSphereIn3D(radius=u.Q(1.0, "m")))
A point on the unit sphere (on equator, x-axis):
>>> p_sph = {"theta": u.Q(1.0, "rad"), "phi": u.Q(0.0, "rad")} >>> cxc.pt_map(p_sph, sphere, cxc.cart3d) {'x': Q(0.84147098, 'm'), 'y': Q(0., 'm'), 'z': Q(0.54030231, 'm')}
From SphericalTwoSphere intrinsic to Spherical ambient:
>>> p_sph = {"theta": u.Q(1.0, "rad"), "phi": u.Q(0.5, "rad")} >>> cxc.pt_map(p_sph, sphere, cxc.sph3d) {'r': Q(1., 'm'), 'theta': Q(1., 'rad'), 'phi': Q(0.5, 'rad')}
- coordinax.charts.pt_map(p: dict[str, Any], M: EmbeddedManifold, from_chart: AbstractChart, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Convert between embedded manifolds with a shared ambient space.
>>> import unxt as u >>> import coordinax.charts as cxc >>> import coordinax.manifolds as cxm
>>> M = cxm.embedded_twosphere(radius=u.Q(1, "kpc")) >>> M EmbeddedManifold(intrinsic=HyperSphericalManifold(...), ambient=Rn(3), embed_map=TwoSphereIn3D(radius=Q(1, 'kpc'))) >>> x_cart = {"x": u.Q(1, "m"), "y": u.Q(2, "m"), "z": u.Q(3, "m")}
>>> x_sph2 = cxc.pt_map(x_cart, M, cxc.cart3d, cxc.loncoslat_sph2) >>> x_sph2 {'lon_coslat': Q(0.66164791, 'rad'), 'lat': Q(53.3007748, 'deg')}
>>> cxc.pt_map(x_sph2, M, cxc.loncoslat_sph2, cxc.cart3d) {'x': Q(0.26726124, 'kpc'), 'y': Q(0.53452248, 'kpc'), 'z': Q(0.80178373, 'kpc')}
- coordinax.charts.pt_map(p: Any, from_chart: Abstract3D, to_chart: AbstractSphericalTwoSphere, /, *, usys: AbstractUnitSystem | None = None) Any
Project a point from the ambient chart to the two-sphere intrinsic chart.
This realization map is a special case for projecting from 3D charts to the two-sphere intrinsic chart, which is a common use case. The projection does not depend on the radius of the embedding, so this projection works in general.
>>> import unxt as u >>> import coordinax.charts as cxc
>>> q = {"x": u.Q(1.0, "km"), "y": u.Q(0.0, "km"), "z": u.Q(0.0, "km")} >>> cxc.pt_map(q, cxc.cart3d, cxc.sph2) {'theta': Q(1.57079633, 'rad'), 'phi': Q(0., 'rad')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: HyperSphericalManifold, from_chart: AbstractChart, to_M: HyperSphericalManifold, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
Identity conversion for matching charts.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> q = {"theta": u.Q(30, "deg"), "phi": u.Q(60, "deg")} >>> cxc.pt_map(q, cxc.sph2, cxc.sph2) is q True
>>> q = {"lon": u.Q(45, "deg"), "lat": u.Q(10, "deg")} >>> cxc.pt_map(q, cxc.lonlat_sph2, cxc.lonlat_sph2) is q True
>>> q = {"lon_coslat": u.Q(30, "deg"), "lat": u.Q(20, "deg")} >>> cxc.pt_map(q, cxc.loncoslat_sph2, cxc.loncoslat_sph2) is q True
>>> q = {"theta": u.Q(60, "deg"), "phi": u.Q(30, "deg")} >>> cxc.pt_map(q, cxc.math_sph2, cxc.math_sph2) is q True
- coordinax.charts.pt_map(p: dict[str, Any], from_M: HyperSphericalManifold, from_chart: SphericalTwoSphere, to_M: HyperSphericalManifold, to_chart: LonLatSphericalTwoSphere, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
SphericalTwoSphere -> LonLatSphericalTwoSphere.
lat = pi/2 - theta, lon = phi.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"theta": u.Q(0, "rad"), "phi": u.Q(0, "rad")} # North pole >>> cxc.pt_map(p, cxm.S2, cxc.sph2, cxm.S2, cxc.lonlat_sph2) {'lon': Q(0, 'rad'), 'lat': Q(90., 'deg')}
>>> p = {"theta": u.Q(90, "deg"), "phi": u.Q(45, "deg")} # Equator >>> cxc.pt_map(p, cxm.S2, cxc.sph2, cxm.S2, cxc.lonlat_sph2) {'lon': Q(45, 'deg'), 'lat': Q(0, 'deg')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: HyperSphericalManifold, from_chart: LonLatSphericalTwoSphere, to_M: HyperSphericalManifold, to_chart: SphericalTwoSphere, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
LonLatSphericalTwoSphere -> SphericalTwoSphere.
theta = pi/2 - lat, phi = lon.
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"lon": u.Q(45, "deg"), "lat": u.Q(0, "deg")} >>> cxc.pt_map(p, cxm.S2, cxc.lonlat_sph2, cxm.S2, cxc.sph2) {'theta': Q(90, 'deg'), 'phi': Q(45, 'deg')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: HyperSphericalManifold, from_chart: SphericalTwoSphere, to_M: HyperSphericalManifold, to_chart: LonCosLatSphericalTwoSphere, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
SphericalTwoSphere -> LonCosLatSphericalTwoSphere.
lat = pi/2 - theta, lon_coslat = phi * cos(lat).
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u >>> import quaxed.numpy as jnp
>>> p = {"theta": u.Q(90, "deg"), "phi": u.Q(45, "deg")} # equator >>> cxc.pt_map(p, cxm.S2, cxc.sph2, cxm.S2, cxc.loncoslat_sph2) {'lon_coslat': Q(45., 'deg'), 'lat': Q(0., 'deg')}
>>> p = {"theta": u.Q(0, "deg"), "phi": u.Q(45, "deg")} # north pole >>> result = cxc.pt_map(p, cxm.S2, cxc.sph2, cxm.S2, cxc.loncoslat_sph2) >>> bool(jnp.allclose(u.ustrip("deg", result["lat"]), 90.0)) True
- coordinax.charts.pt_map(p: dict[str, Any], from_M: HyperSphericalManifold, from_chart: LonCosLatSphericalTwoSphere, to_M: HyperSphericalManifold, to_chart: SphericalTwoSphere, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
LonCosLatSphericalTwoSphere -> SphericalTwoSphere.
theta = pi/2 - lat, phi = lon_coslat / cos(lat).
>>> import coordinax.charts as cxc >>> import coordinax.manifolds as cxm >>> import unxt as u
>>> p = {"lon_coslat": u.Q(45, "deg"), "lat": u.Q(0, "deg")} >>> cxc.pt_map(p, cxm.S2, cxc.loncoslat_sph2, cxm.S2, cxc.sph2) {'theta': Q(90., 'deg'), 'phi': Q(45., 'deg')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: HyperSphericalManifold, from_chart: SphericalTwoSphere, to_M: HyperSphericalManifold, to_chart: MathSphericalTwoSphere, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
SphericalTwoSphere -> MathSphericalTwoSphere.
Swaps theta and phi (physics -> math convention).
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"theta": u.Q(30, "deg"), "phi": u.Q(60, "deg")} >>> cxc.pt_map(p, cxm.S2, cxc.sph2, cxm.S2, cxc.math_sph2) {'theta': Q(60, 'deg'), 'phi': Q(30, 'deg')}
- coordinax.charts.pt_map(p: dict[str, Any], from_M: HyperSphericalManifold, from_chart: MathSphericalTwoSphere, to_M: HyperSphericalManifold, to_chart: SphericalTwoSphere, /, *, usys: AbstractUnitSystem | None = None) dict[str, Any]
MathSphericalTwoSphere -> SphericalTwoSphere.
Swaps theta and phi (math -> physics convention).
>>> import coordinax.manifolds as cxm >>> import coordinax.charts as cxc >>> import unxt as u
>>> p = {"theta": u.Q(60, "deg"), "phi": u.Q(30, "deg")} >>> cxc.pt_map(p, cxm.S2, cxc.math_sph2, cxm.S2, cxc.sph2) {'theta': Q(30, 'deg'), 'phi': Q(60, 'deg')}
- coordinax.charts.pt_map(x: Any, from_chart: AbstractChart, from_rep: Representation, to_chart: AbstractChart, to_rep: Representation, /, usys: AbstractUnitSystem | None = None) Any
Convert point data between charts.
Convert a point from Cartesian coordinates to spherical coordinates:
>>> import coordinax.representations as cxr >>> import coordinax.charts as cxc
Define a point in Cartesian coordinates:
>>> p = {"x": 1.0, "y": 2.0, "z": 3.0}
Convert it to spherical coordinates:
>>> q = cxc.pt_map(p, cxc.cart3d, cxr.point, cxc.sph3d, cxr.point) >>> q {'r': Array(3.74165739, dtype=float64, ...), 'theta': Array(0.64052231, dtype=float64), 'phi': Array(1.10714872, dtype=float64, ...)}
The output q represents the same geometric point but expressed in the target chart.
The representation remains unchanged; only the chart changes:
>>> cxc.pt_map(q, cxc.sph3d, cxr.point, cxc.cart3d, cxr.point) {'x': Array(1., dtype=float64), 'y': Array(2., dtype=float64), 'z': Array(3., dtype=float64)}
Let’s work through more examples.
Cartesian to Spherical (with units):
>>> import unxt as u >>> p = {"x": u.Q(1.0, "m"), "y": u.Q(0.0, "m"), "z": u.Q(0.0, "m")} >>> cxc.pt_map(p, cxc.cart3d, cxr.point, cxc.sph3d, cxr.point) {'r': Q(1., 'm'), 'theta': Q(1.57079633, 'rad'), 'phi': Q(0., 'rad')}
Cylindrical to Cartesian (without units):
>>> p = {"rho": 3.0, "phi": 0, "z": 4.0} >>> cxc.pt_map(p, cxc.cyl3d, cxr.point, cxc.cart3d, cxr.point) {'x': Array(3., dtype=float64, ...), 'y': Array(0., dtype=float64, ...), 'z': 4.0}
Polar to Cartesian (2D):
>>> p = {"r": u.Q(5.0, "m"), "theta": u.Q(90, "deg")} >>> cxc.pt_map(p, cxc.polar2d, cxr.point, cxc.cart2d, cxr.point) {'x': Q(3.061617e-16, 'm'), 'y': Q(5., 'm')}
Between Spherical variants (Spherical to LonLatSpherical):
>>> p = {"r": u.Q(1.0, "m"), "theta": u.Q(45, "deg"), "phi": u.Q(0, "deg")} >>> cxc.pt_map(p, cxc.sph3d, cxr.point, cxc.lonlat_sph3d, cxr.point) {'lon': Q(0, 'deg'), 'lat': Q(45., 'deg'), 'distance': Q(1., 'm')}
Identity conversion (same chart):
>>> p = {"x": u.Q(2.0, "m"), "y": u.Q(3.0, "m")} >>> cxc.pt_map(p, cxc.cart2d, cxr.point, cxc.cart2d, cxr.point) is p True
- coordinax.charts.pt_map(x: Any, from_chart: AbstractChart, from_rep: Representation, to_chart: AbstractChart, /, usys: AbstractUnitSystem | None = None) Any
Convert point data between charts.
Convert a point from Cartesian coordinates to spherical coordinates:
>>> import coordinax.representations as cxr >>> import coordinax.charts as cxc
Define a point in Cartesian coordinates:
>>> p = {"x": 1.0, "y": 2.0, "z": 3.0}
Convert it to spherical coordinates:
>>> q = cxc.pt_map(p, cxc.cart3d, cxr.point, cxc.sph3d) >>> q {'r': Array(3.74165739, dtype=float64, ...), 'theta': Array(0.64052231, dtype=float64), 'phi': Array(1.10714872, dtype=float64, ...)}
The output q represents the same geometric point but expressed in the target chart.
The representation remains unchanged; only the chart changes:
>>> cxc.pt_map(q, cxc.sph3d, cxr.point, cxc.cart3d) {'x': Array(1., dtype=float64), 'y': Array(2., dtype=float64), 'z': Array(3., dtype=float64)}
- coordinax.charts.pt_map(x: Any, from_chart: AbstractChart, from_geom: PointGeometry, from_rep: Representation, to_chart: AbstractChart, to_geom: PointGeometry, to_rep: Representation, /, usys: AbstractUnitSystem | None = None) Any
Convert point data between charts.
Convert a point from Cartesian coordinates to spherical coordinates:
>>> import coordinax.representations as cxr >>> import coordinax.charts as cxc
Define a point in Cartesian coordinates:
>>> p = {"x": 1.0, "y": 2.0, "z": 3.0}
Convert it to spherical coordinates:
>>> cxc.pt_map(p, cxc.cart3d, cxr.point_geom, cxr.point, ... cxc.sph3d, cxr.point_geom, cxr.point) {'r': Array(3.74165739, dtype=float64, ...), 'theta': Array(0.64052231, dtype=float64), 'phi': Array(1.10714872, dtype=float64, ...)}
- coordinax.charts.pt_map(from_vec: coordinax.vectors._src.point.Point, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) coordinax.vectors._src.point.Point
Convert a point from one chart to another.
>>> import unxt as u >>> import coordinax.main as cx >>> import coordinax.charts as cxc
>>> vec = cx.Point.from_([1, 1, 1], "m") >>> print(vec) <Point: chart=Cart3D (x, y, z) [m] [1 1 1]>
>>> sph_vec = cxc.pt_map(vec, cx.sph3d) >>> print(sph_vec) <Point: chart=Spherical3D (r[m], theta[rad], phi[rad]) [1.732 0.955 0.785]>
- coordinax.charts.pt_map(from_vec: coordinax.vectors._src.point.Point, from_chart: AbstractChart, to_chart: AbstractChart, /, *, usys: AbstractUnitSystem | None = None) coordinax.vectors._src.point.Point
Convert a vector from one chart to another.
>>> import unxt as u >>> import coordinax.main as cx >>> import coordinax.charts as cxc
>>> vec = cx.Point.from_([1, 1, 1], "m") >>> sph_vec = cxc.pt_map(vec, cxc.cart3d, cx.sph3d) >>> print(sph_vec) <Point: chart=Spherical3D (r[m], theta[rad], phi[rad]) [1.732 0.955 0.785]>
- class coordinax.charts.Abstract0D#
Bases:
AbstractDimensionalFlagMarker flag for 0D representations.
A 0D representation has no coordinate component.
- class coordinax.charts.Cart0D(*, M: MT = Rn(0))#
Bases:
AbstractFixedComponentsChart[MT,tuple[()],tuple[()]],Abstract0DZero-dimensional Cartesian chart.
This chart has no coordinate components and no coordinate dimensions. It is the canonical Cartesian chart for 0D representations.
>>> import coordinax.charts as cxc >>> cxc.cart0d.components () >>> cxc.cart0d.coord_dimensions () >>> isinstance(cxc.cartesian_chart(cxc.cart0d), cxc.Cart0D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(0)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Self#
Return the canonical Cartesian chart for a 0D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Cart0D().cartesian, cxc.Cart0D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Abstract1D#
Bases:
AbstractDimensionalFlagMarker flag for 1D representations.
A 1D representation has exactly one coordinate component. Examples include Cartesian $(x)$ or radial $(r)$ coordinates.
- class coordinax.charts.Cart1D(*, M: MT = Rn(1))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘x’]],tuple[Literal[‘length’]]],Abstract1DOne-dimensional Cartesian chart $(x)$.
Components are ordered as
("x",)with dimension("length",).This chart is the canonical 1D Cartesian chart and is returned by {func}`coordinax.charts.cartesian_chart` for 1D charts.
Examples
>>> import coordinax.charts as cxc >>> cxc.cart1d.components ('x',)
>>> cxc.cart1d.coord_dimensions ('length',)
>>> isinstance(cxc.cartesian_chart(cxc.cart1d), cxc.Cart1D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(1)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Self#
Return the canonical Cartesian chart for a 1D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Cart1D().cartesian, cxc.Cart1D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Radial1D(*, M: MT = Rn(1))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘r’]],tuple[Literal[‘length’]]],Abstract1DOne-dimensional radial chart $(r)$.
Components are ordered as
("r",)with dimension("length",).This chart is semantically equivalent to {class}`coordinax.charts.Cart1D` but uses
rinstead ofx. Its canonical Cartesian projection is {obj}`coordinax.charts.cart1d`.Examples
>>> import coordinax.charts as cxc >>> cxc.radial1d.components ('r',)
>>> cxc.radial1d.coord_dimensions ('length',)
>>> isinstance(cxc.cartesian_chart(cxc.radial1d), cxc.Cart1D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(1)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Cart1D[MT]#
Return the canonical Cartesian chart for a 1D radial chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Radial1D().cartesian, cxc.Cart1D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Time1D(*, M: MT = Rn(1))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘t’]],tuple[Literal[‘time’]]],Abstract1DOne-dimensional time chart
(t).Components are ordered as
("t",)with dimension("time",).This chart is the canonical 1D time chart and is often used as the first factor in spacetime product charts.
Examples
>>> import coordinax.charts as cxc >>> cxc.time1d.components ('t',)
>>> cxc.time1d.coord_dimensions ('time',)
>>> isinstance(cxc.cartesian_chart(cxc.time1d), cxc.Time1D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(1)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Time1D#
Return the canonical Cartesian chart for a 1D time chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Time1D().cartesian, cxc.Time1D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Abstract2D#
Bases:
AbstractDimensionalFlagMarker flag for 2D representations.
A 2D representation has exactly two coordinate components. This does not imply that the underlying manifold is flat; for example, the two-sphere uses two angular coordinates but represents a curved surface.
- class coordinax.charts.Cart2D(*, M: MT = Rn(2))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘x’],Literal[‘y’]],tuple[Literal[‘length’],Literal[‘length’]]],Abstract2DTwo-dimensional Cartesian chart $(x, y)$.
Components are ordered as
("x", "y")with dimensions("length", "length").This chart is the canonical 2D Cartesian chart and is returned by {func}`coordinax.charts.cartesian_chart` for 2D charts.
Examples
>>> import coordinax.charts as cxc >>> cxc.cart2d.components ('x', 'y')
>>> cxc.cart2d.coord_dimensions ('length', 'length')
>>> isinstance(cxc.cartesian_chart(cxc.cart2d), cxc.Cart2D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(2)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Self#
Return the canonical Cartesian chart for a 2D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Cart2D().cartesian, cxc.Cart2D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Polar2D(*, M: MT = Rn(2))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘r’],Literal[‘theta’]],tuple[Literal[‘length’],Literal[‘angle’]]],Abstract2DTwo-dimensional polar chart $(r, theta)$.
Components are ordered as
("r", "theta")with dimensions("length", "angle").This chart has direct transitions with {class}`coordinax.charts.Cart2D` and its canonical Cartesian projection is {obj}`coordinax.charts.cart2d`.
Examples
>>> import coordinax.charts as cxc >>> cxc.polar2d.components ('r', 'theta')
>>> cxc.polar2d.coord_dimensions ('length', 'angle')
>>> isinstance(cxc.cartesian_chart(cxc.polar2d), cxc.Cart2D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(2)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Cart2D[MT]#
Return the canonical Cartesian chart for a 2D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Cart2D().cartesian, cxc.Cart2D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Abstract3D#
Bases:
AbstractDimensionalFlagMarker flag for 3D representations.
A 3D representation has exactly three coordinate components. These may parameterize Euclidean space (Cartesian), curvilinear coordinates (cylindrical, spherical), or other three-dimensional manifolds.
- class coordinax.charts.Cart3D(*, M: MT = Rn(3))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘x’],Literal[‘y’],Literal[‘z’]],tuple[Literal[‘length’],Literal[‘length’],Literal[‘length’]]],Abstract3DThree-dimensional Cartesian chart $(x, y, z)$.
Components are ordered as
("x", "y", "z")with dimensions("length", "length", "length").This chart is the canonical 3D Cartesian chart and is returned by {func}`coordinax.charts.cartesian_chart` for 3D charts.
Examples
>>> import coordinax.charts as cxc >>> cxc.cart3d.components ('x', 'y', 'z')
>>> cxc.cart3d.coord_dimensions ('length', 'length', 'length')
>>> isinstance(cxc.cartesian_chart(cxc.cart3d), cxc.Cart3D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Self#
Return the canonical Cartesian chart for a 3D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.cart3d.cartesian, cxc.Cart3D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Cylindrical3D(*, M: MT = Rn(3))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘rho’],Literal[‘phi’],Literal[‘z’]],tuple[Literal[‘length’],Literal[‘angle’],Literal[‘length’]]],Abstract3DThree-dimensional cylindrical chart $(rho, phi, z)$.
Components are ordered as
("rho", "phi", "z")with dimensions("length", "angle", "length").This chart has direct transitions with {class}`coordinax.charts.Cart3D` and its canonical Cartesian projection is {obj}`coordinax.charts.cart3d`.
Examples
>>> import coordinax.charts as cxc >>> cxc.cyl3d.components ('rho', 'phi', 'z')
>>> cxc.cyl3d.coord_dimensions ('length', 'angle', 'length')
>>> isinstance(cxc.cartesian_chart(cxc.cyl3d), cxc.Cart3D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Cart3D[MT]#
Return the canonical Cartesian chart for a 3D cylindrical chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Cylindrical3D().cartesian, cxc.Cart3D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.AbstractSpherical3D#
Bases:
AbstractFixedComponentsChart[MT,Ks,Ds],Abstract3DAbstract spherical vector representation.
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Cart3D[MT]#
Return the canonical Cartesian chart for a 3D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Spherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonLatSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.MathSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonCosLatSpherical3D().cartesian, cxc.Cart3D) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.Spherical3D(*, M: MT = Rn(3))#
Bases:
AbstractSpherical3D[MT,tuple[Literal[‘r’],Literal[‘theta’],Literal[‘phi’]],tuple[Literal[‘length’],Literal[‘angle’],Literal[‘angle’]]]Three-dimensional spherical coordinates $(r, theta, phi)$.
The Cartesian embedding is
$x = rsinthetacosphi,$ $y = rsinthetasinphi,$ $z = rcostheta.$
Here $r ge 0$, $theta in [0,pi]$ is the polar (colatitude) angle, and $phi$ is the azimuth.
This convention matches the physics / mathematics definition of spherical coordinates.
Examples
>>> import coordinax.charts as cxc >>> cxc.sph3d.components ('r', 'theta', 'phi')
>>> cxc.sph3d.coord_dimensions ('length', 'angle', 'angle')
>>> isinstance(cxc.cartesian_chart(cxc.sph3d), cxc.Cart3D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- property cartesian: Cart3D[MT]#
Return the canonical Cartesian chart for a 3D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Spherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonLatSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.MathSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonCosLatSpherical3D().cartesian, cxc.Cart3D) True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.LonLatSpherical3D(*, M: MT = Rn(3))#
Bases:
AbstractSpherical3D[MT,tuple[Literal[‘lon’],Literal[‘lat’],Literal[‘distance’]],tuple[Literal[‘angle’],Literal[‘angle’],Literal[‘length’]]]Longitude-latitude spherical coordinates.
Components are $(mathrm{lon}, mathrm{lat}, r)$ where:
lonis the azimuthal angle in the equatorial plane,latis the latitude in $[-pi/2, pi/2]$,ris the radial distance.
Relation to standard spherical coordinates:
$mathrm{lat} = pi/2 - theta$, $mathrm{lon} = \phi$.
Examples
>>> import coordinax.charts as cxc >>> cxc.lonlat_sph3d.components ('lon', 'lat', 'distance')
>>> cxc.lonlat_sph3d.coord_dimensions ('angle', 'angle', 'length')
>>> isinstance(cxc.cartesian_chart(cxc.lonlat_sph3d), cxc.Cart3D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- property cartesian: Cart3D[MT]#
Return the canonical Cartesian chart for a 3D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Spherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonLatSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.MathSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonCosLatSpherical3D().cartesian, cxc.Cart3D) True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.LonCosLatSpherical3D(*, M: MT = Rn(3))#
Bases:
AbstractSpherical3D[MT,tuple[Literal[‘lon_coslat’],Literal[‘lat’],Literal[‘distance’]],tuple[Literal[‘angle’],Literal[‘angle’],Literal[‘length’]]]Longitude-cos(latitude) spherical coordinates.
Components are $(mathrm{lon}cosmathrm{lat}, mathrm{lat}, r)$. This form is sometimes used to improve numerical behavior near the poles, since $cos(mathrm{lat}) to 0$ as $|mathrm{lat}| to pi/2$.
Examples
>>> import coordinax.charts as cxc >>> cxc.loncoslat_sph3d.components ('lon_coslat', 'lat', 'distance')
>>> cxc.loncoslat_sph3d.coord_dimensions ('angle', 'angle', 'length')
>>> isinstance(cxc.cartesian_chart(cxc.loncoslat_sph3d), cxc.Cart3D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- property cartesian: Cart3D[MT]#
Return the canonical Cartesian chart for a 3D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Spherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonLatSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.MathSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonCosLatSpherical3D().cartesian, cxc.Cart3D) True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.MathSpherical3D(*, M: MT = Rn(3))#
Bases:
AbstractSpherical3D[MT,tuple[Literal[‘r’],Literal[‘theta’],Literal[‘phi’]],tuple[Literal[‘length’],Literal[‘angle’],Literal[‘angle’]]]Mathematical-convention spherical coordinates $(r, theta, phi)$.
In this convention:
$phi$ is the polar angle measured from the positive $z$ axis,
$theta$ is the azimuthal angle in the $xy$-plane.
This differs from the physics convention used by {class}`coordinax.charts.Spherical3D`, where $theta$ and $phi$ are swapped.
Examples
>>> import coordinax.charts as cxc >>> cxc.math_sph3d.components ('r', 'theta', 'phi')
>>> cxc.math_sph3d.coord_dimensions ('length', 'angle', 'angle')
>>> isinstance(cxc.cartesian_chart(cxc.math_sph3d), cxc.Cart3D) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- property cartesian: Cart3D[MT]#
Return the canonical Cartesian chart for a 3D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.Spherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonLatSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.MathSpherical3D().cartesian, cxc.Cart3D) True >>> isinstance(cxc.LonCosLatSpherical3D().cartesian, cxc.Cart3D) True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.ProlateSpheroidal3D(*, Delta: ]], M: MT = Rn(3))#
Bases:
Abstract3D,AbstractFixedComponentsChart[MT,tuple[Literal[‘mu’],Literal[‘nu’],Literal[‘phi’]],tuple[Literal[‘area’],Literal[‘area’],Literal[‘angle’]]]Prolate spheroidal coordinates $(mu, nu, phi)$ with focal length $Delta$.
These coordinates are adapted to systems with two foci separated by distance $2Delta$.
Validity constraints enforced by this representation:
$Delta > 0$,
$mu ge Delta^2$,
$|nu| le Delta^2$.
The parameter $Delta$ is stored as metadata on the representation.
Examples
>>> import coordinax.charts as cxc >>> import unxt as u >>> chart = cxc.ProlateSpheroidal3D(Delta=u.StaticQuantity(2, "kpc")) >>> chart.components ('mu', 'nu', 'phi')
>>> chart.coord_dimensions ('area', 'area', 'angle')
>>> isinstance(cxc.cartesian_chart(chart), cxc.Cart3D) True
>>> d = {"mu": u.Q(4, "kpc2"), "nu": u.Q(0.1, "kpc2"), "phi": u.Q(1, "rad")} >>> chart.check_data(d) # doesn't raise {'mu': Q(4, 'kpc2'), 'nu': Q(0.1, 'kpc2'), 'phi': Q(1, 'rad')}
- Parameters:
Delta (
Real[StaticQuantity, ''])M (
TypeVar(MT, bound=AbstractManifold))
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- Delta: value > 0]]#
Focal length of the coordinate system.
- M: MT = Rn(3)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- class coordinax.charts.Abstract4D#
Bases:
AbstractDimensionalFlagMarker flag for 4-D representations.
A 4-D representation has exactly four coordinate components. The primary example is the Minkowski spacetime chart
(ct, x, y, z).
- class coordinax.charts.Abstract6D#
Bases:
AbstractDimensionalFlagMarker flag for 6-D representations.
An 6-D representation has an arbitrary number of coordinate components. Examples include Cartesian representations in arbitrary dimensions.
- class coordinax.charts.PoincarePolar6D(*, M: AbstractManifold = NoManifold())#
Bases:
AbstractFixedComponentsChart[Any,tuple[Literal[‘rho’],Literal[‘pp_phi’],Literal[‘z’],Literal[‘dt_rho’],Literal[‘dt_pp_phi’],Literal[‘dt_z’]],tuple[Literal[‘length’],Literal[‘length / time**0.5’],Literal[‘length’],Literal[‘speed’],Literal[‘length / time**1.5’],Literal[‘speed’]]],Abstract6DSix-dimensional Poincare-polar chart.
Components are ordered as $(rho,;mathrm{pp_phi},;z,;dotrho,;dot{mathrm{pp_phi}},;dot z)$ with dimensions $(mathrm{length},;mathrm{length}/mathrm{time}^{1/2},;mathrm{length},;mathrm{speed},;mathrm{length}/mathrm{time}^{3/2},;mathrm{speed})$.
Examples
>>> import coordinax.charts as cxc >>> cxc.poincarepolar6d.components ('rho', 'pp_phi', 'z', 'dt_rho', 'dt_pp_phi', 'dt_z')
>>> cxc.poincarepolar6d.coord_dimensions ('length', 'length / time**0.5', 'length', 'speed', 'length / time**1.5', 'speed')
>>> isinstance(cxc.poincarepolar6d, cxc.PoincarePolar6D) True
- Parameters:
M (
AbstractManifold)
- M: AbstractManifold = NoManifold()#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.AbstractND#
Bases:
AbstractDimensionalFlagMarker flag for N-D representations.
An N-D representation has an arbitrary number of coordinate components. Examples include Cartesian representations in arbitrary dimensions.
- M: AbstractManifold = NoManifold()#
- class coordinax.charts.CartND(*, M: MT = Rn(True))#
Bases:
AbstractFixedComponentsChart[MT,tuple[Literal[‘q’]],tuple[Literal[‘length’]]],AbstractNDN-dimensional Cartesian chart.
Components are ordered as
("q",)with dimension("length",), whereqstores the N Cartesian components as a single length-valued array.This chart is the canonical Cartesian chart for arbitrary dimension.
Examples
>>> import coordinax.charts as cxc >>> cxc.cartnd.components ('q',)
>>> cxc.cartnd.coord_dimensions ('length',)
>>> isinstance(cxc.cartesian_chart(cxc.cartnd), cxc.CartND) True
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = Rn(True)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: Self#
Return the canonical Cartesian chart for an N-D chart.
>>> import coordinax.charts as cxc >>> isinstance(cxc.CartND().cartesian, cxc.CartND) True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.AbstractSphericalHyperSphere#
Bases:
AbstractFixedComponentsChart[MT,Ks,Ds]Abstract base class for intrinsic charts on the unit hypersphere.
All hypersphere charts represent coordinates on the surface of a unit hypersphere. There is no global Cartesian representation for these charts; they live on a curved manifold.
Concrete subclasses define specific coordinate systems:
Physics convention: polar (colatitude) and azimuthal angles
Longitude-latitude: geographic-style coordinates
Mathematics convention: azimuthal and polar angles (swapped)
Notes
The intrinsic geometry is non-Euclidean (curved).
To embed in 3D Euclidean space, use an
EmbeddedChart.cartesian_chart(...)raisesNoGlobalCartesianChartErrorfor all 2-sphere charts.
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- M: MT#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- class coordinax.charts.AbstractSphericalOneSphere#
Bases:
AbstractSphericalHyperSphere[MT,Ks,Ds],Abstract1DAbstract base class for intrinsic charts on the unit circle.
All circle charts represent coordinates on the surface of a unit circle. There is no global Cartesian 1D representation for these charts; they live on a curved 1D manifold.
Notes
The intrinsic geometry is non-Euclidean (curved).
To embed in higher Euclidean spaces, use an
EmbeddedManifold.cartesian_chart(...)raisesNoGlobalCartesianChartErrorfor all circle charts.
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- M: MT#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- class coordinax.charts.CircularOneSphere(*, M: MT = HyperSphericalManifold(ndim=1))#
Bases:
AbstractSphericalOneSphere[MT,tuple[Literal[‘phi’]],tuple[Literal[‘angle’]]]Standard circular coordinates on the unit circle.
- Parameters:
phi – Angular coordinate with angular units.
M (MT)
Notes
CircularOneSphereis a curved 1D manifold; there is no global Cartesian 1D chart.cartesian_chart(CircularOneSphere)raises.
Examples
>>> import coordinax.charts as cxc >>> cxc.sph1.components ('phi',)
>>> cxc.sph1.coord_dimensions ('angle',)
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = HyperSphericalManifold(ndim=1)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.AbstractSphericalTwoSphere(*, M: MT = HyperSphericalManifold(ndim=2))#
Bases:
AbstractSphericalHyperSphere[MT,Ks,Ds],Abstract2DAbstract base class for intrinsic charts on the unit two-sphere.
All 2-sphere charts represent coordinates on the surface of a unit sphere. There is no global Cartesian 2D representation for these charts; they live on a curved 2D manifold.
Concrete subclasses define specific coordinate systems:
Physics convention: polar (colatitude) and azimuthal angles
Longitude-latitude: geographic-style coordinates
Mathematics convention: azimuthal and polar angles (swapped)
Notes
The intrinsic geometry is non-Euclidean (curved).
To embed in 3D Euclidean space, use an
EmbeddedManifold.cartesian_chart(...)raisesNoGlobalCartesianChartErrorfor all 2-sphere charts.
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = HyperSphericalManifold(ndim=2)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.SphericalTwoSphere(*, M: MT = HyperSphericalManifold(ndim=2))#
Bases:
AbstractSphericalTwoSphere[MT,tuple[Literal[‘theta’],Literal[‘phi’]],tuple[Literal[‘angle’],Literal[‘angle’]]]Intrinsic chart on the unit two-sphere with components
(theta, phi).Uses the physics convention: $theta in [0,pi]$ is the polar (colatitude) angle measured from the positive $z$-axis, and $phi in (-pi,pi]$ is the azimuthal angle.
- Parameters:
theta – Polar (colatitude) angle with angular units.
phi – Azimuthal angle with angular units.
M (MT)
Notes
SphericalTwoSphereis a curved 2D manifold; there is no global Cartesian 2D chart.cartesian_chart(SphericalTwoSphere)raises.The intrinsic metric is
diag(1, sin^2 theta).The longitude is undefined at the poles
theta=0,pi.
Examples
>>> import coordinax.charts as cxc >>> cxc.sph2.components ('theta', 'phi')
>>> cxc.sph2.coord_dimensions ('angle', 'angle')
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = HyperSphericalManifold(ndim=2)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.LonLatSphericalTwoSphere(*, M: MT = HyperSphericalManifold(ndim=2))#
Bases:
AbstractSphericalTwoSphere[MT,tuple[Literal[‘lon’],Literal[‘lat’]],tuple[Literal[‘angle’],Literal[‘angle’]]]Longitude-latitude chart on the two-sphere.
Components are $(mathrm{lon},;mathrm{lat})$ where:
lonis the azimuthal angle (longitude),lat$in [-pi/2,;pi/2]$ is the latitude.
Relation to {class}`SphericalTwoSphere`:
$mathrm{lat} = pi/2 - theta$, $mathrm{lon} = phi$.
Examples
>>> import coordinax.charts as cxc >>> cxc.lonlat_sph2.components ('lon', 'lat')
>>> cxc.lonlat_sph2.coord_dimensions ('angle', 'angle')
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = HyperSphericalManifold(ndim=2)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.LonCosLatSphericalTwoSphere(*, M: MT = HyperSphericalManifold(ndim=2))#
Bases:
AbstractSphericalTwoSphere[MT,tuple[Literal[‘lon_coslat’],Literal[‘lat’]],tuple[Literal[‘angle’],Literal[‘angle’]]]Longitude-cos(latitude) chart on the two-sphere.
Components are $(mathrm{lon}cosmathrm{lat},;mathrm{lat})$.
This form can improve numerical behavior near the poles because $cos(mathrm{lat}) to 0$ as $|mathrm{lat}| to pi/2$.
Examples
>>> import coordinax.charts as cxc >>> cxc.loncoslat_sph2.components ('lon_coslat', 'lat')
>>> cxc.loncoslat_sph2.coord_dimensions ('angle', 'angle')
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- M: MT = HyperSphericalManifold(ndim=2)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- class coordinax.charts.MathSphericalTwoSphere(*, M: MT = HyperSphericalManifold(ndim=2))#
Bases:
AbstractSphericalTwoSphere[MT,tuple[Literal[‘theta’],Literal[‘phi’]],tuple[Literal[‘angle’],Literal[‘angle’]]]Math-convention chart on the two-sphere.
Components are $(theta, phi)$ where, contrary to the physics convention used in {class}`SphericalTwoSphere`:
$theta$ is the azimuthal angle,
$phi in [0, pi]$ is the polar angle.
The conversion from {class}`SphericalTwoSphere` simply swaps the two angles.
Examples
>>> import coordinax.charts as cxc >>> cxc.math_sph2.components ('theta', 'phi')
>>> cxc.math_sph2.coord_dimensions ('angle', 'angle')
- Parameters:
M (
TypeVar(MT, bound=AbstractManifold))
- property cartesian: NoReturn#
Raise NoGlobalCartesianChartError for any 2-sphere chart.
2-sphere charts have no global Cartesian 2D representation.
Examples
>>> import coordinax.charts as cxc >>> try: ... cxc.sph2.cartesian ... except Exception as exc: ... print(type(exc).__name__) ... print("no global Cartesian representation" in str(exc)) NoGlobalCartesianChartError True
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.
- M: MT = HyperSphericalManifold(ndim=2)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- check_data(data: CDictT, /, *, values: bool = False, **kw: Any)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.
values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.kw (
Any)
- Return type:
- class coordinax.charts.AbstractCartesianProductChart#
Bases:
AbstractChart[CartesianProductManifold,Ks,Ds]Abstract base class for Cartesian product charts.
A Cartesian product chart is defined by a finite ordered tuple of factor charts. The product chart’s components are the concatenation of factor components, and transformations follow factorwise laws.
- Mathematical definition:
M = ∏ᵢ Mᵢ (product manifold) TₚM ≅ ⊕ᵢ T_{pᵢ}Mᵢ (tangent bundle splits)
- Component key convention (normative):
General product charts use dot-delimited string keys:
"factor_name.c"wherefactor_nameidentifies the factor andcis the factor’s component key.Specialized products (i.e. AbstractFlatCartesianProductChart subclasses) may expose flat string keys as a documented exception when component names are guaranteed collision-free.
Normative requirements: - factors is an ordered tuple of charts - factor_names is always a tuple of unique strings with length matching factors - ndim must equal sum(f.ndim for f in factors) - components must follow the key convention above
- factor_names: tuple[str, ...]#
Factor names for namespaced keys. Must be unique and aligned with factors.
- split_components(p: dict[str, Any], /)#
Partition a CDict by factor components.
For namespaced products: select keys
"name_i.c"and strip prefix to yield factor dict keyed byc.
- merge_components(parts: tuple[Mapping[str, V], ...], /)#
Merge factor CDicts into a single CDict.
For namespaced products: re-attach dot-delimited prefix
"name_i.c"for each factor key.
- property M: CartesianProductManifold#
Return the product manifold of the factor charts’ manifolds.
Examples
>>> import coordinax.charts as cxc >>> chart = cxc.CartesianProductChart((cxc.cart3d, cxc.cart3d), ("q", "p")) >>> chart.M CartesianProductManifold(factors=(Rn(3), Rn(3)), factor_names=('q', 'p'))
- property components: Ks#
dot-delimited strings
"factor_name.component".- Components are dot-delimited string keys to avoid collisions:
(f”{name_0}.{c}” for c in factors[0].components, …)
- Type:
Component keys
- property coord_dimensions: Ds#
Concatenation of factor coordinate dimensions.
- abstract property cartesian: AbstractChart[MT, Ks, Ds]#
Return the corresponding Cartesian chart.
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- class coordinax.charts.AbstractFlatCartesianProductChart#
Bases:
AbstractCartesianProductChart[Ks,Ds]Abstract base class for flat-key Cartesian product charts.
A flat-key Cartesian product chart is a specialization of {class}`AbstractCartesianProductChart` where the component keys are guaranteed to be collision-free across factors, allowing the use of flat string keys instead of dot-delimited string keys.
Subclasses must provide factor_names and ensure that factor components do not collide.
Normative requirements: - factor_names must be provided (abstract property) - components is the direct concatenation of factor components
(must be collision-free)
- abstract property factor_names: tuple[str, ...]#
Factor names for flat-key Cartesian product charts.
Subclasses must provide factor names even though components are flat.
- split_components(p: dict[str, Any], /)#
Partition a CDict by factor components.
For flat-key products: partition by
factor.componentsdirectly.
- merge_components(parts: tuple[Mapping[str, V], ...])#
Merge factor CDicts into a single CDict.
For flat-key products: merge as-is (keys already match components).
- property components: Ks#
flat strings (collision-free concatenation of factors).
Components are the direct concatenation of factor component strings (must be collision-free).
- Type:
Component keys
- property M: CartesianProductManifold#
Return the product manifold of the factor charts’ manifolds.
Examples
>>> import coordinax.charts as cxc >>> chart = cxc.CartesianProductChart((cxc.cart3d, cxc.cart3d), ("q", "p")) >>> chart.M CartesianProductManifold(factors=(Rn(3), Rn(3)), factor_names=('q', 'p'))
- abstract property cartesian: AbstractChart[MT, Ks, Ds]#
Return the corresponding Cartesian chart.
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property coord_dimensions: Ds#
Concatenation of factor coordinate dimensions.
- final class coordinax.charts.CartesianProductChart(factors: tuple[AbstractChart[Any, Any, Any], ...], factor_names: tuple[str, ...])#
Bases:
AbstractCartesianProductChart[Ks,Ds]Concrete Cartesian product chart with dot-delimited component keys.
Constructs a product chart from a tuple of factor charts and factor names. Components are dot-delimited string keys
"factor_name.component_name"to avoid collisions (e.g., phase space with repeated Cart3D factors).- Parameters:
Examples
>>> import coordinax.charts as cxc >>> chart = cxc.CartesianProductChart((cxc.cart3d, cxc.cart3d), ("q", "p")) >>> chart.components ('q.x', 'q.y', 'q.z', 'p.x', 'p.y', 'p.z') >>> chart.ndim 6
>>> chart["p"] Cart3D(M=Rn(3))
>>> chart.M CartesianProductManifold(factors=(Rn(3), Rn(3)), factor_names=('q', 'p'))
- factor_names: tuple[str, ...]#
Factor names for namespaced keys. Must be unique and aligned with factors.
- property M: CartesianProductManifold#
Return the product manifold of the factor charts’ manifolds.
Examples
>>> import coordinax.charts as cxc >>> chart = cxc.CartesianProductChart((cxc.cart3d, cxc.cart3d), ("q", "p")) >>> chart.M CartesianProductManifold(factors=(Rn(3), Rn(3)), factor_names=('q', 'p'))
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
dot-delimited strings
"factor_name.component".- Components are dot-delimited string keys to avoid collisions:
(f”{name_0}.{c}” for c in factors[0].components, …)
- Type:
Component keys
- property coord_dimensions: Ds#
Concatenation of factor coordinate dimensions.
- merge_components(parts: tuple[Mapping[str, V], ...], /)#
Merge factor CDicts into a single CDict.
For namespaced products: re-attach dot-delimited prefix
"name_i.c"for each factor key.
- split_components(p: dict[str, Any], /)#
Partition a CDict by factor components.
For namespaced products: select keys
"name_i.c"and strip prefix to yield factor dict keyed byc.
- property cartesian: CartesianProductChart#
Get Cartesian version of a namespaced product chart (factorwise).
Returns a CartesianProductChart with each factor replaced by its cartesian_chart version, preserving factor_names.
Examples
>>> import coordinax.charts as cxc >>> product = cxc.CartesianProductChart((cxc.sph3d, cxc.sph3d), ("q", "p")) >>> cart_product = cxc.cartesian_chart(product) >>> cart_product CartesianProductChart( factors=(Cart3D(M=Rn(3)), Cart3D(M=Rn(3))), factor_names=('q', 'p') )
- final class coordinax.charts.GalileanCT(spatial_chart: ~coordinax._src.base.charts.AbstractFixedComponentsChart[~typing.Any, ~typing.Any, ~typing.Any] = Cart3D(M=Rn(3)), *, c: ~jaxtyping.Float[StaticQuantity[PhysicalType({'speed', 'velocity'})], ''] = StaticQuantity(f64[](numpy), 'km / s'))#
Bases:
AbstractFlatCartesianProductChart[Ks,Ds]4D spacetime rep with components
(ct, x, y, z)and Minkowski metric.This is a Cartesian product chart: GalileanCT(spatial_chart) ≡ time1d x spatial_chart
The time component is always the canonical 1D time chart time1d with component “t”. The time coordinate is automatically converted to ct using the speed of light.
Mathematical definition: $$
x^0 = ct,quad x^i = text{spatial components} \ g = mathrm{diag}(-1, 1, 1, 1) quad text{(signature } - + + +)
$$
- Parameters:
spatial_chart (
AbstractFixedComponentsChart[Any,Any,Any]) – Spatial position rep supplying component names and dimensions.c (
Float[StaticQuantity[PhysicalType({'speed', 'velocity'})], '']) – Speed of light used to formctfromt(defaults toQuantity(299_792.458, "km/s")).
- Returns:
Representation with components
("ct", *spatial_chart.components)and dimensions("length", *spatial_chart.coord_dimensions).- Return type:
Rep
Notes
The first factor is always time1d; the time chart is not user-selectable.
Examples
>>> import unxt as u >>> import coordinax.charts as cxc
>>> cxc.GalileanCT() GalileanCT()
>>> cxc.GalileanCT(cxc.sph3d) GalileanCT(spatial_chart=Spherical3D(M=Rn(3)))
- spatial_chart: AbstractFixedComponentsChart[Any, Any, Any] = Cart3D(M=Rn(3))#
coordinax.charts.cart3d.
- Type:
Spatial part of the representation. Defaults
- c: Float[StaticQuantity[PhysicalType({'speed', 'velocity'})], ''] = StaticQuantity(f64[](numpy), 'km / s')#
Speed of light, by default
Quantity(299_792.458, "km/s").
- property M: AbstractManifold#
The manifold this chart belongs to, derived from the spatial chart.
- property time_chart: AbstractChart[Any, Any, Any]#
Time factor chart (always time1d).
- property factors: tuple[AbstractChart[Any, Any, Any], ...]#
Return (time1d, spatial_chart) as required by product chart spec.
- split_components(p: dict[str, Any])#
Split CDict by factors, keeping ‘ct’ for time factor.
GalileanCT uses ‘ct’ for the time component. The split returns factor dicts with their native keys (‘ct’ for time, spatial keys for space).
- merge_components(parts: tuple[dict[str, Any], dict[str, Any]], /)#
Merge factor CDicts back into GalileanCT components.
Expects time factor dict with ‘ct’ key, spatial factor dict with spatial keys.
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
flat strings (collision-free concatenation of factors).
Components are the direct concatenation of factor component strings (must be collision-free).
- Type:
Component keys
- property coord_dimensions: Ds#
Concatenation of factor coordinate dimensions.
- property cartesian: GalileanCT[Any, Any]#
Get a Cartesian-chart version of the given spacetime chart.
Examples
>>> import coordinax.charts as cxc >>> rep = cxc.GalileanCT(cxc.sph3d) >>> rep GalileanCT(spatial_chart=Spherical3D(M=Rn(3)))
>>> rep.cartesian # default is Cart3D GalileanCT(spatial_chart=Cart3D(M=Rn(3)))
- final class coordinax.charts.MinkowskiCT(*, M: MinkowskiManifold = MinkowskiManifold(ndim=4))#
Bases:
Abstract4D,AbstractFixedComponentsChart[MinkowskiManifold,tuple[Literal[‘ct’],Literal[‘x’],Literal[‘y’],Literal[‘z’]],tuple[Literal[‘length’],Literal[‘length’],Literal[‘length’],Literal[‘length’]]]4D Minkowski spacetime chart $(ct, x, y, z)$.
A single flat chart with the conventional 3+1 split: one time-like coordinate $ct$ (speed-of-light times coordinate time, carrying units of length) and three spatial coordinates $x$, $y$, $z$.
All four components carry dimension
"length", so the metric $eta = operatorname{diag}(-1, 1, 1, 1)$ is dimensionless.- Parameters:
M (
MinkowskiManifold) – The manifold this chart belongs to. Defaults to a freshMinkowskiManifoldinstance.
Examples
>>> import coordinax.charts as cxc
>>> cxc.MinkowskiCT() MinkowskiCT(M=MinkowskiManifold(ndim=4))
>>> cxc.minkowskict.components ('ct', 'x', 'y', 'z')
>>> cxc.minkowskict.coord_dimensions ('length', 'length', 'length', 'length')
>>> cxc.minkowskict.ndim 4
- M: MinkowskiManifold = MinkowskiManifold(ndim=4)#
The manifold that this chart belongs to.
Default is no_manifold for charts that do not belong to any manifold.
- property cartesian: MinkowskiCT#
Return self — MinkowskiCT is already the Cartesian chart.
Examples
>>> import coordinax.charts as cxc >>> cxc.minkowskict.cartesian is cxc.minkowskict True
- check_data(data: CDictT, /, *, keys: bool = True, values: bool = False)#
Check that the data is compatible with the chart.
- Parameters:
data (
TypeVar(CDictT, bound=dict[str,Any])) – The data to check.keys (
bool) – Whether to check that the keys of data match chart.components. If False, this check is skipped. Default is True.values (
bool) – Whether to check that the dimensions of the values in data match chart.coord_dimensions. If False, this check is skipped. Default is False.
- Return type:
- property components: Ks#
The names of the components.
- property coord_dimensions: Ds#
The dimensions of the components.