-
tensorstore_demo.DimExpression.__getitem__(
self, indices: Any) -> DimExpression[source] Applies a NumPy-style indexing operation with default index array semantics.
When using NumPy-style indexing with a dimension expression, all selected dimensions must be consumed by a term of the indexing spec; there is no implicit addition of an
Ellipsis
term to consume any remaining dimensions.- Returns:¶
Dimension expression with the indexing operation added.
Examples
Integer indexing¶
>>> transform = ts.IndexTransform(input_labels=['x', 'y', 'z']) >>> transform[ts.d['x'][5]] Rank 2 -> 3 index space transform: Input domain: 0: (-inf*, +inf*) "y" 1: (-inf*, +inf*) "z" Output index maps: out[0] = 5 out[1] = 0 + 1 * in[0] out[2] = 0 + 1 * in[1] >>> transform[ts.d['x', 'z'][5, 6]] Rank 1 -> 3 index space transform: Input domain: 0: (-inf*, +inf*) "y" Output index maps: out[0] = 5 out[1] = 0 + 1 * in[0] out[2] = 6
A single scalar index term applies to all selected dimensions:
>>> transform[ts.d['x', 'y'][5]] Rank 1 -> 3 index space transform: Input domain: 0: (-inf*, +inf*) "z" Output index maps: out[0] = 5 out[1] = 5 out[2] = 0 + 1 * in[0]
Interval indexing¶
>>> transform = ts.IndexTransform(input_labels=['x', 'y', 'z']) >>> transform[ts.d['x'][5:10]] Rank 3 -> 3 index space transform: Input domain: 0: [5, 10) "x" 1: (-inf*, +inf*) "y" 2: (-inf*, +inf*) "z" Output index maps: out[0] = 0 + 1 * in[0] out[1] = 0 + 1 * in[1] out[2] = 0 + 1 * in[2] >>> transform[ts.d['x', 'z'][5:10, 20:30]] Rank 3 -> 3 index space transform: Input domain: 0: [5, 10) "x" 1: (-inf*, +inf*) "y" 2: [20, 30) "z" Output index maps: out[0] = 0 + 1 * in[0] out[1] = 0 + 1 * in[1] out[2] = 0 + 1 * in[2]
As an extension, TensorStore allows the
start
,stop
, andstep
slice
terms to be vectors rather than scalars:>>> transform[ts.d['x', 'z'][[5, 20]:[10, 30]]] Rank 3 -> 3 index space transform: Input domain: 0: [5, 10) "x" 1: (-inf*, +inf*) "y" 2: [20, 30) "z" Output index maps: out[0] = 0 + 1 * in[0] out[1] = 0 + 1 * in[1] out[2] = 0 + 1 * in[2] >>> transform[ts.d['x', 'z'][[5, 20]:30]] Rank 3 -> 3 index space transform: Input domain: 0: [5, 30) "x" 1: (-inf*, +inf*) "y" 2: [20, 30) "z" Output index maps: out[0] = 0 + 1 * in[0] out[1] = 0 + 1 * in[1] out[2] = 0 + 1 * in[2]
As with integer indexing, a single scalar slice applies to all selected dimensions:
>>> transform[ts.d['x', 'z'][5:30]] Rank 3 -> 3 index space transform: Input domain: 0: [5, 30) "x" 1: (-inf*, +inf*) "y" 2: [5, 30) "z" Output index maps: out[0] = 0 + 1 * in[0] out[1] = 0 + 1 * in[1] out[2] = 0 + 1 * in[2]
Adding singleton dimensions¶
Specifying a value of
newaxis
(equal toNone
) adds a new dummy/singleton dimension with implicit bounds \([0, 1)\):>>> transform = ts.IndexTransform(input_labels=['x', 'y']) >>> transform[ts.d[1][ts.newaxis]] Rank 3 -> 2 index space transform: Input domain: 0: (-inf*, +inf*) "x" 1: [0*, 1*) 2: (-inf*, +inf*) "y" Output index maps: out[0] = 0 + 1 * in[0] out[1] = 0 + 1 * in[2] >>> transform[ts.d[0, -1][ts.newaxis, ts.newaxis]] Rank 4 -> 2 index space transform: Input domain: 0: [0*, 1*) 1: (-inf*, +inf*) "x" 2: (-inf*, +inf*) "y" 3: [0*, 1*) Output index maps: out[0] = 0 + 1 * in[1] out[1] = 0 + 1 * in[2]
As with integer indexing, if only a single
ts.newaxis
term is specified, it applies to all selected dimensions:>>> transform[ts.d[0, -1][ts.newaxis]] Rank 4 -> 2 index space transform: Input domain: 0: [0*, 1*) 1: (-inf*, +inf*) "x" 2: (-inf*, +inf*) "y" 3: [0*, 1*) Output index maps: out[0] = 0 + 1 * in[1] out[1] = 0 + 1 * in[2]
newaxis
terms are only permitted in the first operation of a dimension expression, since in subsequent operations all dimensions of the dimension selection necessarily refer to existing dimensions:Error
>>> transform[ts.d[0, 1].translate_by[5][ts.newaxis]] Traceback (most recent call last): ... IndexError: tensorstore_demo.newaxis (`None`) not valid in chained indexing operations
It is also an error to use
newaxis
with dimensions specified by label:Error
>>> transform[ts.d['x'][ts.newaxis]] Traceback (most recent call last): ... IndexError: New dimensions cannot be specified by label
Ellipsis¶
Specifying the special
Ellipsis
value (...
) is equivalent to specifying as many full slices:
as needed to consume the remaining selected dimensions not consumed by other indexing terms:>>> transform = ts.IndexTransform(input_rank=4) >>> transform[ts.d[:][1, ..., 5].translate_by[3]] Rank 2 -> 4 index space transform: Input domain: 0: (-inf*, +inf*) 1: (-inf*, +inf*) Output index maps: out[0] = 1 out[1] = -3 + 1 * in[0] out[2] = -3 + 1 * in[1] out[3] = 5
An indexing spec consisting solely of an
Ellipsis
term has no effect:>>> transform[ts.d[:][...]] Rank 4 -> 4 index space transform: Input domain: 0: (-inf*, +inf*) 1: (-inf*, +inf*) 2: (-inf*, +inf*) 3: (-inf*, +inf*) Output index maps: out[0] = 0 + 1 * in[0] out[1] = 0 + 1 * in[1] out[2] = 0 + 1 * in[2] out[3] = 0 + 1 * in[3]
Integer array indexing¶
Specifying an
array_like
index array of integer values selects the coordinates given by the elements of the array of the selected dimension:>>> x = ts.array([[1, 2, 3], [4, 5, 6]], dtype=ts.int32) >>> x = x[ts.d[:].label['x', 'y']] >>> x[ts.d['y'][[1, 1, 0]]] TensorStore({ 'array': [[2, 2, 1], [5, 5, 4]], 'context': {'data_copy_concurrency': {}}, 'driver': 'array', 'dtype': 'int32', 'transform': { 'input_exclusive_max': [2, 3], 'input_inclusive_min': [0, 0], 'input_labels': ['x', ''], }, })
As in the example above, if only a single index array term is specified, the dimensions of the index array are added to the result domain in place of the selected dimension, consistent with direct NumPy-style indexing in the default index array mode.
However, when using NumPy-style indexing with a dimension expression, if more than one index array term is specified, the broadcast dimensions of the index arrays are always added to the beginning of the result domain, i.e. exactly the behavior of
DimExpression.vindex
. Unlike with direct NumPy-style indexing (not with a dimension expression), the behavior does not depend on whether the index array terms apply to consecutive dimensions, since consecutive dimensions are not well-defined for dimension expressions:>>> x = ts.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]], dtype=ts.int32) >>> x = x[ts.d[:].label['x', 'y', 'z']] >>> x[ts.d['z', 'y'][[1, 0], [1, 1]]] TensorStore({ 'array': [[4, 3], [8, 7]], 'context': {'data_copy_concurrency': {}}, 'driver': 'array', 'dtype': 'int32', 'transform': { 'input_exclusive_max': [2, 2], 'input_inclusive_min': [0, 0], 'input_labels': ['x', ''], }, })
Boolean array indexing¶
Specifying an
array_like
ofbool
values is equivalent to specifying a sequence of integer index arrays containing the coordinates ofTrue
values (in C order), e.g. as obtained fromnumpy.nonzero
:Specifying a 1-d
bool
array is equivalent to a single index array of the non-zero coordinates:>>> x = ts.array([[1, 2, 3], [4, 5, 6]], dtype=ts.int32) >>> x = x[ts.d[:].label['x', 'y']] >>> x[ts.d['y'][[False, True, True]]] TensorStore({ 'array': [[2, 3], [5, 6]], 'context': {'data_copy_concurrency': {}}, 'driver': 'array', 'dtype': 'int32', 'transform': { 'input_exclusive_max': [2, 2], 'input_inclusive_min': [0, 0], 'input_labels': ['x', ''], }, })
Equivalently, using an index array:
>>> x[ts.d['y'][[1, 2]]] TensorStore({ 'array': [[2, 3], [5, 6]], 'context': {'data_copy_concurrency': {}}, 'driver': 'array', 'dtype': 'int32', 'transform': { 'input_exclusive_max': [2, 2], 'input_inclusive_min': [0, 0], 'input_labels': ['x', ''], }, })
More generally, specifying an
n
-dimensionalbool
array is equivalent to specifyingn
1-dimensional index arrays, where thei
th index array specifies thei
th coordinate of theTrue
values:>>> x = ts.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]], ... dtype=ts.int32) >>> x = x[ts.d[:].label['x', 'y', 'z']] >>> x[ts.d['x', 'z'][[[True, False, False], [True, True, False]]]] TensorStore({ 'array': [[1, 4], [7, 10], [8, 11]], 'context': {'data_copy_concurrency': {}}, 'driver': 'array', 'dtype': 'int32', 'transform': { 'input_exclusive_max': [3, 2], 'input_inclusive_min': [0, 0], 'input_labels': ['', 'y'], }, })
Equivalently, using an index array:
>>> x[ts.d['x', 'z'][[0, 1, 1], [0, 0, 1]]] TensorStore({ 'array': [[1, 4], [7, 10], [8, 11]], 'context': {'data_copy_concurrency': {}}, 'driver': 'array', 'dtype': 'int32', 'transform': { 'input_exclusive_max': [3, 2], 'input_inclusive_min': [0, 0], 'input_labels': ['', 'y'], }, })
Note that as with integer array indexing, when using NumPy-styling indexing with a dimension expression, if boolean arrays are applied to more than one selected dimension, the added dimension corresponding to the
True
values is always added to the beginning of the result domain, i.e. exactly the behavior ofDimExpression.vindex
.
Last update:
Dec 16, 2024