labeled

N-dimensional arrays with labeled dimensions.

Introduction

kgpy.labeled is a module which exists to support the concept of n-dimensional array where each of the dimensions are labeled by a string. This concept is very similar to xarray.Variable, except with support for astropy.units.Quantity. Also see the post Tensors Considered Harmful.

Expressing an n-dimensional array in this way has several advantages. First, the arrays will automatically broadcast against one another, without needing extra dimensions for alignment.

import kgpy.labeled

x = kgpy.labeled.LinearSpace(0, 1, num=2, axis='x')
y = kgpy.labeled.LinearSpace(0, 1, num=3, axis='y')
z = x * y
z
Array(array=array([[0. , 0. , 0. ],
       [0. , 0.5, 1. ]]), axes=['x', 'y'])


Second, reduction-like operations such as numpy.sum(), numpy.mean(), numpy.min(), etc. can use the dimension label instead of the axis position.

z.sum(axis='x')
Array(array=array([0. , 0.5, 1. ]), axes=['y'])


Finally, elements or slices of the array can be accessed using the dimension label instead of inserting extra slices or ellipses to select the appropriate axis.

z[dict(y=1)]
Array(array=array([0. , 0.5]), axes=['x'])


Note that above we would love to be able to do z[y=1], however Python does not currently support keyword arguments to the __get_item__ dunder method.

Creating Arrays

The most important member of the kgpy.labeled module is the kgpy.labeled.Array class. This class is a composition of a numpy.ndarray and a list of strings labeling the dimensions.

Here is how you would explicitly create a kgpy.labeled.Array from a numpy.ndarray and a list of strings.

import numpy as np
import kgpy.labeled

kgpy.labeled.Array(np.linspace(0, 1, num=4), axes=['x'])
Array(array=array([0.        , 0.33333333, 0.66666667, 1.        ]), axes=['x'])


Note that trying the above without specifying the axes argument results in an error since the number of axes does not match the number of dimensions.

kgpy.labeled.Array(np.linspace(0, 1, num=4))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[5], line 1
----> 1 kgpy.labeled.Array(np.linspace(0, 1, num=4))

File <string>:5, in __init__(self, array, axes)

File ~/checkouts/readthedocs.org/user_builds/kgpy/envs/latest/lib/python3.9/site-packages/kgpy/labeled.py:1426, in Array.__post_init__(self)
   1424     self.axes = []
   1425 if getattr(self.array, 'ndim', 0) != len(self.axes):
-> 1426     raise ValueError('The number of axis names must match the number of dimensions.')
   1427 if len(self.axes) != len(set(self.axes)):
   1428     raise ValueError(f'Each axis name must be unique, got {self.axes}.')

ValueError: The number of axis names must match the number of dimensions.


However if the first argument is a scalar, the axes argument does not need to be specified

kgpy.labeled.Array(5)
Array(array=5, axes=[])


It is generally discouraged to create kgpy.labeled.Array instances explicitly. The above example can be accomplished by using the kgpy.labeled.LinearSpace class.

kgpy.labeled.LinearSpace(0, 1, num=4, axis='x')
LinearSpace(start=0, stop=1, num=4, endpoint=True, axis='x')


In addition to kgpy.labeled.LinearSpace, there is also kgpy.labeled.UniformRandomSpace and kgpy.labeled.NormalRandomSpace to help with array creation.

Functions

indices(shape)

rtype:

typing.Dict[str, typing.TypeVar(ArrayT, bound= Array)]

ndindex(shape[, axis_ignored])

rtype:

typing.Iterator[typing.Dict[str, int]]

stack(arrays, axis)

Classes

AbstractArray()

Array([array, axes])

ArrayInterface()

LinearSpace([start, stop, num, endpoint, axis])

NDArrayMethodsMixin()

NormalRandomSpace([center, width, num, ...])

Range([start, stop, step, axis])

StratifiedRandomSpace([start, stop, num, ...])

UniformRandomSpace([start, stop, num, ...])

WorldCoordinateSpace(crval, crpix, cdelt, ...)