Indexing an fa.Array#
The indexing behaviour and syntax as well as the following docmentation are inspired by xarray, see xarray: Indexing and selecting data.
Quick Overview#
In total, fa.Array
objects can be indexed via four different methods, two dimension lookup methods (positional, by name) and two index lookup methods (by integer, by label). In our case, label always refers to the Dimension
coordinate values of type float (and should not be understood as any other objects like str).
The main difference between Array
indexing and xarray
indexing lies in the fact that an Array
object can be in different internal states, i.e., each dimension can be either in position or frequency space and will always be indexed within this space. This is especially important when indexing by label, i.e., by position or frequency coordinate values.
In the following overview, we understand arr
as an Array
object with two dimensions in the order ("x", "y")
. Array
supports four possible ways of indexing, here shown by selecting the first y
coordinate (y=1e-3
).
Dimension lookup |
Index lookup |
fftarray syntax |
---|---|---|
Positional |
By integer |
|
Positional |
By label |
|
By name |
By integer |
|
By name |
By label |
|
Some Examples#
import fftarray as fa
x_dim = fa.dim(name="x", n=8, d_pos=0.4, pos_min=0, freq_min=0)
y_dim = fa.dim(name="y", n=8, d_pos=0.4, pos_min=0, freq_min=0)
z_dim = fa.dim(name="z", n=8, d_pos=0.4, pos_min=0, freq_min=0)
arr = (
fa.coords_from_dim(x_dim, "pos") +
fa.coords_from_dim(y_dim, "pos") +
fa.coords_from_dim(z_dim, "pos")
)
Indexing by integer#
First, we will have a look at indexing by integer for both dimension lookup methods: positional and by name. Positional indexing by integer is the most common form of indexing that you also know from other array libraries such as numpy
. Here, we can additionally look up the dimension by name as each of our Array
dimensions has a unique name (supplied by the Dimension
name).
# The following ways of indexing all have the same result.
# Each of them reduces the x-dimension to index 3
# and slices the y-dimension from index 1 to (not including) 5.
# The third z-dimension is not indexed and therefore fully kept.
indexed_arr: fa.Array = arr[3,:5,:]
indexed_arr: fa.Array = arr[3,:5]
indexed_arr: fa.Array = arr[3,:5,...] # ellipsis fills up non-mentioned dimensions (useful for only indexing late or early dimensions)
indexed_arr: fa.Array = arr[dict(x=3, y=slice(None,5))]
indexed_arr: fa.Array = arr.isel(x=3, y=slice(None,5))
indexed_arr: fa.Array = arr.isel(dict(x=3, y=slice(None,5)))
# There are some special cases to keep in mind when indexing by integer.
# These examples also evaluate to the same value as above.
indexed_arr: fa.Array = arr[dict(x=3, y=slice(0,5))] # slice(None,x) = slice(0,x)
indexed_arr: fa.Array = arr[dict(x=-5, y=slice(0,5))] # for array with dim.n = 8: index -5 = index 3
indexed_arr: fa.Array = arr[dict(x=3, y=slice(-100,5))] # slice objects with start < -dim.n are mapped to None
indexed_arr: fa.Array = arr[dict(x=3, y=slice(0,-3))] # slice indices are individually mapped to a valid region if possible
Indexing by Label/Coordinate#
Now, we will have a look at indexing by label for both dimension lookup methods: positional and by name. Label indexing is applicable to Array
s because our dimensions have coordinate values (of type float) which are as unique as indices. As above, we can additionally look up the dimension by name as each of our Array
dimensions has a unique name (supplied by the Dimension
name).
# The following ways of indexing return exactly the same result.
# Each of them reduces the x-dimension to coordinate 1.6
# and slices the y-dimension to only include coordinates between 1 and 2.5.
# The third z-dimension is not indexed and therefore fully kept.
indexed_arr: fa.Array = arr.loc[1.6,1:2.5,:]
indexed_arr: fa.Array = arr.loc[1.6,1:2.5]
indexed_arr: fa.Array = arr.loc[1.6,1:2.5,...]
indexed_arr: fa.Array = arr.loc[dict(x=1.6, y=slice(1,2.5))]
indexed_arr: fa.Array = arr.sel(x=1.6, y=slice(1,2.5))
indexed_arr: fa.Array = arr.sel(dict(x=1.6, y=slice(1,2.5)))
# Additionally, with arr.sel one can also choose a method for coordinate search.
# This leads to the following indexing commands yielding the same result.
# However, FFTArray does not support a method when using slice objects for indexing.
# Please keep in mind that in these examples we always index in
# position space where all dimensions have d_pos = 0.4.
indexed_arr: fa.Array = arr.sel(x=0.4)
indexed_arr: fa.Array = arr.sel(x=0.3, method="nearest")
indexed_arr: fa.Array = arr.sel(x=0.5, method="nearest")
indexed_arr: fa.Array = arr.sel(x=0.1, method="bfill") # equivalent: method="backfill"
indexed_arr: fa.Array = arr.sel(x=0.3, method="bfill") # equivalent: method="backfill"
indexed_arr: fa.Array = arr.sel(x=0.4, method="bfill") # equivalent: method="backfill"
indexed_arr: fa.Array = arr.sel(x=0.5, method="ffill") # equivalent: method="pad"
indexed_arr: fa.Array = arr.sel(x=0.75, method="ffill") # equivalent: method="pad"
indexed_arr: fa.Array = arr.sel(x=0.4, method="ffill") # equivalent: method="pad"