Indexing Fields¶
The syntax and semantics for indexing are almost equivalent to Numpy’s basic indexing. The key difference is Viscid supports slice-by-location (see below). Also, Viscid supports indexing by arrays (like Numpy’s advanced indexing), but these arrays must be one-dimensional. Unfortunately, true advanced indexing is poorly defined when the result has to be on a grid.
Indexing by a single index (or location) reduces that dimension from the
result. Use viscid.Field.slice_and_keep()
to keep singly
selected dimensions.
Warning
If not all slices are named, then all slices must be in the same
order as fld.crds.axes
, otherwise index ordering would be poorly
defined.
Slice-by-index¶
This syntax works exactly like in Numpy
fld[0]
access the 0th elementfld[:-1]
everything but the last elementfld[2:6:2]
every other element from 2 to 6fld[:5, :5]
first five elements in x and yfld[[0, 5, 7]]
the 0th, 5th, and 7th elments
Slice-by-location¶
Locations on the grid can be specified using imaginary numbers. The semantics are such that the stop value is included if it matches a point on the grid. This is different from most python indexing, but it makes slice-by-location feel more natural.
fld[1.0j]
access element closest to x = 1.0fld[:0.0j]
all elements where x <= 0.0fld[0.0j::2]
every other element where x >= 0.0fld[0.0j:, 0.0j:]
region x >= 0 and y >= 0fld[[-1j, 0j, 1j]]
elements closest to x = [-1, 0, 1]
Note that these slices don’t necessarily take the closest grid points. Rather, they specify a white-list region. Take the following example:
>>> arr = numpy.array([-1, -0.5, 0.0, 0.5, 1.0])
>>> slc = viscid.std_sel2index(numpy.s_[-0.49j:0.5j], arr)
>>> arr[slc]
array([0.0, 0.5])
Slice-by-mask¶
Slices can be a mask, just like in Numpy,
fld[[True, False, True]]
0th and 2nd elements
Named slices¶
Slices can be encoded as strings to be explicit about which axis should be indexed.
fld['y = 0j']
select the y = 0.0 planefld['x = 0j', 'y = 0j']
select the x = y = 0.0 planefld['x = 0j, y = 0j']
select the x = y = 0.0 plane
Vector component slices¶
Vector components must be extracted by name. Anything that is not a vector name is assumed to be a spatial slice. The reason for this is that it is unambiguous. Also, the user does not have to care about the data layout (array-of-struct, struct-of-array).
fld['x']
extracts the x-component from a vector fieldfld['x, y = 0j']
x-component, y = 0.0 planefld['y = 0j', 'x']
x-component, y = 0.0 planefld['x', 0j:, 0j]
x-component, y = 0.0 plane, x >= 0.0fld[0j:, 0j, 'x']
x-component, y = 0.0 plane, x >= 0.0
Datetime64 / timedelta64 slices¶
Slice-by-location does work with datetime64 / timedelta64 axes. The slices
can be specifed as normal python slices of strings or numpy datetime64
(or timedelta64) objects; or, the slice can be given as a string that looks
like fld["start:stop"]
. If you give the whole slice as a string, then
times must be preceeded by either “T” or “UT”, otherwise the string would
be ambiguous.
>>> t = viscid.linspace_datetime64('2010-01-01T12:00:00',
>>> '2010-01-01T15:00:00', 8)
>>> x = numpy.linspace(-1, 1, 12)
>>> fld = viscid.zeros([t, x], crd_names='tx', center='node')
>>>
>>> fld[:'2010-01-01T13:30:00'].shape
(4, 12)
>>> fld['2010-01-01T12:30:00':'2010-01-01T13:30:00'].shape
(2, 12)
>>> fld[':UT2010-01-01T13:30:00'].shape
(4, 12)
>>> fld['UT2010-01-01T12:30:00:UT2010-01-01T13:30:00'].shape
(2, 12)
>>> fld[:'01:30:00'].shape
(4, 12)
>>> fld[':T01:30:00'].shape
(4, 12)
Newaxis¶
fld[numpy.newaxis]
new axis in dimension 0fld['u = newaxis']
new axis in dimension 0 named ‘u’fld[:, numpy.newaxis]
new axis in dimension 1fld['y=:', numpy.newaxis]
new axis after the y-axisfld[..., numpy.newaxis]
new axis in the last dimension
Ellipsis¶
The ellipsis can be used in the standard way, but it can not be used with named axes. The exception to this is that the ellipsis can be used with named newaxes.
fld[0j:, ..., 0j:]
select x >= 0.0 and z >= 0.0fld[..., 'u = newaxis']
new axis in the last dimension named u