cf.Field.indices

Field.indices(*config, **kwargs)[source]

Create indices that define a subspace of the field construct.

The subspace is defined by identifying indices based on the metadata constructs.

Metadata constructs are selected by conditions specified on their data. Indices for subspacing are then automatically inferred from where the conditions are met.

The returned tuple of indices may be used to created a subspace by indexing the original field construct with them.

Metadata constructs and the conditions on their data are defined by keyword parameters.

  • Any domain axes that have not been identified remain unchanged.

  • Multiple domain axes may be subspaced simultaneously, and it doesn’t matter which order they are specified in.

  • Subspace criteria may be provided for size 1 domain axes that are not spanned by the field construct’s data.

  • Explicit indices may also be assigned to a domain axis identified by a metadata construct, with either a Python slice object, or a sequence of integers or booleans.

  • For a dimension that is cyclic, a subspace defined by a slice or by a Query instance is assumed to “wrap” around the edges of the data.

  • Conditions may also be applied to multi-dimensional metadata constructs. The “compress” mode is still the default mode (see the positional arguments), but because the indices may not be acting along orthogonal dimensions, some missing data may still need to be inserted into the field construct’s data.

Ancillary masks

When creating an actual subspace with the indices, if the first element of the tuple of indices is 'mask' then the second element is a tuple of auxiliary masks, and the remaining elements contain the usual indexing information that defines the extent of the subspace. Each auxiliary mask broadcasts to the subspaced data, and when the subspace is actually created, these masks are all automatically applied to the result.

Halos

If a halo is defined via a positional argument, then each subspaced axis will be extended to include that many extra elements at each “side” of the axis. The number of extra elements will be automatically reduced if including the full amount defined by the halo would extend the subspace beyond the axis limits.

For instance, f.indices(X=slice(10, 20)) will give identical results to each of f.indices(0, X=slice(10, 20)), f.indices(1, X=slice(11, 19)), f.indices(2, X=slice(12, 18)), etc.

If a halo has been defined (of any size, including 0), then no ancillary masks will be created.

New in version 1.0.

Parameters
config: optional

Configure the subspace by specifying the mode of operation (mode) and any halo to be added to the subspaced axes (halo), with positional arguments in the format mode, or halo, or mode, halo, or with no positional arguments at all.

A mode of operation is given as a str, and a halo as a non-negative int (or any object that can be converted to one):

mode

Description

Not provided

If no positional arguments are provided then assume the 'compress' mode of operation with no halo added to the subspaced axes.

mode

Define the mode of operation with no halo added to the subspaced axes.

mode, halo

Define a mode of operation, as well as a halo to be added to the subspaced axes.

halo

Assume the 'compress' mode of operation and define a halo to be added to the subspaced axes.

Valid modes are:

  • 'compress' This is the default.

    Unselected locations are removed to create the subspace. If the result is not hyperrectangular then the minimum amount of unselected locations required to make it so will also be specially selected. Missing data is inserted at the specially selected locations, unless a halo has been defined (of any size, including 0).

  • 'envelope'

    The subspace is the smallest hyperrectangular subspace that contains all of the selected locations. Missing data is inserted at unselected locations within the envelope, unless a halo has been defined (of any size, including 0).

  • 'full'

    The subspace has the same domain as the original construct. Missing data is inserted at unselected locations, unless a halo has been defined (of any size, including 0).

Note

Setting a halo size of 0 differs from not not defining a halo at all. The shape of the returned field will always be the same, but in the former case missing data will not be inserted at unselected locations (if any) within the output domain.

kwargs: optional

A keyword name is an identity of a metadata construct, and the keyword value provides a condition for inferring indices that apply to the dimension (or dimensions) spanned by the metadata construct’s data. Indices are created that select every location for which the metadata construct’s data satisfies the condition.

Returns
tuple

The indices meeting the conditions.

Examples

>>> q = cf.example_field(0)
>>> print(q)
Field: specific_humidity (ncvar%q)
----------------------------------
Data            : specific_humidity(latitude(5), longitude(8)) 1
Cell methods    : area: mean
Dimension coords: latitude(5) = [-75.0, ..., 75.0] degrees_north
                : longitude(8) = [22.5, ..., 337.5] degrees_east
                : time(1) = [2019-01-01 00:00:00]
>>> indices = q.indices(X=112.5)
>>> print(indices)
(slice(0, 5, 1), slice(2, 3, 1))
>>> q[indices]
<CF Field: specific_humidity(latitude(5), longitude(1)) 1>
>>> q.indices(X=112.5, latitude=cf.gt(-60))
(slice(1, 5, 1), slice(2, 3, 1))
>>> q.indices(latitude=cf.eq(-45) | cf.ge(20))
(array([1, 3, 4]), slice(0, 8, 1))
>>> q.indices(X=[1, 2, 4], Y=slice(None, None, -1))
(slice(4, None, -1), array([1, 2, 4]))
>>> q.indices(X=cf.wi(-100, 200))
(slice(0, 5, 1), slice(-2, 4, 1))
>>> q.indices(X=slice(-2, 4))
(slice(0, 5, 1), slice(-2, 4, 1))
>>> q.indices('compress', X=[1, 2, 4, 6])
(slice(0, 5, 1), array([1, 2, 4, 6]))
>>> q.indices(Y=[True, False, True, True, False])
(array([0, 2, 3]), slice(0, 8, 1))
>>> q.indices('envelope', X=[1, 2, 4, 6])
('mask', [<CF Data(1, 6): [[False, ..., False]]>], slice(0, 5, 1), slice(1, 7, 1))
>>> indices = q.indices('full', X=[1, 2, 4, 6])
('mask', [<CF Data(1, 8): [[True, ..., True]]>], slice(0, 5, 1), slice(0, 8, 1))
>>> print(indices)
>>> print(q)
<CF Field: specific_humidity(latitude(5), longitude(8)) 1>
>>> f = cf.example_field(2)
Field: air_potential_temperature (ncvar%air_potential_temperature)
------------------------------------------------------------------
Data            : air_potential_temperature(time(120), latitude(5), longitude(8)) K
Cell methods    : area: mean
Dimension coords: time(120) = [1959-12-16 12:00:00, ..., 1969-11-16 00:00:00]
                : latitude(5) = [-75.0, ..., 75.0] degrees_north
                : longitude(8) = [22.5, ..., 337.5] degrees_east
                : air_pressure(1) = [850.0] hPa
>>> f.indices(T=410.5)
(dask.array<isclose, shape=(36,), dtype=bool, chunksize=(36,), chunktype=numpy.ndarray>,
 slice(None, None, None),
 slice(None, None, None))
>>> f.indices(T=cf.dt('1961-11-16'))
(dask.array<isclose, shape=(36,), dtype=bool, chunksize=(36,), chunktype=numpy.ndarray>,
 slice(0, 5, 1),
 slice(0, 8, 1))
>>> indices = f.indices(T=cf.wi(cf.dt('1960-03-01'),
...                             cf.dt('1961-12-17 07:30')))
>>> indices
(dask.array<and_, shape=(36,), dtype=bool, chunksize=(36,), chunktype=numpy.ndarray>,
slice(None, None, None),
slice(None, None, None))
>>> print(indices[0].compute())
[False False False  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True False False False False False False False False False False False]
>>> print(f[indices])
Field: air_potential_temperature (ncvar%air_potential_temperature)
------------------------------------------------------------------
Data            : air_potential_temperature(time(22), latitude(5), longitude(8)) K
Cell methods    : area: mean
Dimension coords: time(22) = [1960-03-16 12:00:00, ..., 1961-12-16 12:00:00]
                : latitude(5) = [-75.0, ..., 75.0] degrees_north
                : longitude(8) = [22.5, ..., 337.5] degrees_east
                : air_pressure(1) = [850.0] hPa
>>> f = cf.example_field(1)
Field: air_temperature (ncvar%ta)
---------------------------------
Data            : air_temperature(atmosphere_hybrid_height_coordinate(1), grid_latitude(10), grid_longitude(9)) K
Cell methods    : grid_latitude(10): grid_longitude(9): mean where land (interval: 0.1 degrees) time(1): maximum
Field ancils    : air_temperature standard_error(grid_latitude(10), grid_longitude(9)) = [[0.76, ..., 0.32]] K
Dimension coords: atmosphere_hybrid_height_coordinate(1) = [1.5]
                : grid_latitude(10) = [2.2, ..., -1.76] degrees
                : grid_longitude(9) = [-4.7, ..., -1.18] degrees
                : time(1) = [2019-01-01 00:00:00]
Auxiliary coords: latitude(grid_latitude(10), grid_longitude(9)) = [[53.941, ..., 50.225]] degrees_N
                : longitude(grid_longitude(9), grid_latitude(10)) = [[2.004, ..., 8.156]] degrees_E
                : long_name=Grid latitude name(grid_latitude(10)) = [--, ..., kappa]
Cell measures   : measure:area(grid_longitude(9), grid_latitude(10)) = [[2391.9657, ..., 2392.6009]] km2
Coord references: grid_mapping_name:rotated_latitude_longitude
                : standard_name:atmosphere_hybrid_height_coordinate
Domain ancils   : ncvar%a(atmosphere_hybrid_height_coordinate(1)) = [10.0] m
                : ncvar%b(atmosphere_hybrid_height_coordinate(1)) = [20.0]
                : surface_altitude(grid_latitude(10), grid_longitude(9)) = [[0.0, ..., 270.0]] m
>>> indices = f.indices(latitude=cf.wi(51.5, 52.4))
>>> indices
('mask',
 (<CF Data(1, 5, 9): [[[False, ..., False]]]>,),
 slice(None, None, None),
 [4, 5, 6],
 [0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> f[indices]
<CF Field: air_temperature(atmosphere_hybrid_height_coordinate(1), grid_latitude(3), grid_longitude(9)) K>
>>> print(f[indices].array)
[[[264.2 275.9 262.5 264.9 264.7 270.2 270.4 -- --]
 [263.9 263.8 272.1 263.7 272.2 264.2 260.0 263.5 270.2]
 [-- -- -- -- -- -- 270.6 273.0 270.6]]]