cf.Field.subspace¶
-
Field.
subspace
¶ Create a subspace of the field.
A subspace may be defined in “metadata-space” via data array values of its domain items: dimension coordinate, auxiliary coordinate, cell measure, domain ancillary and field ancillary objects.
Alternatively, a subspace my be defined be in “index-space” via explicit indices for the data array using an extended Python slicing syntax.
Defining a subspace in metadata-space
Defining a subspace in metadata-space has the following features
- Axes to be subspaced may identified by metadata, rather than their position in the data array.
- The position in the data array of each axis need not be known and the axes to be subspaced may be given in any order.
- Axes for which no subspacing is required need not be specified.
- Size one axes of the domain which are not spanned by the data array may be specified.
>>> f <CF Field: air_temperature(time(12), latitude(73), longitude(96)) K> >>> f.subspace(latitude=0) <CF Field: air_temperature(time(12), latitude(1), longitude(96)) K> >>> f.subspace(longitude=cf.ge(180), latitude=0) <CF Field: air_temperature(time(12), latitude(1), longitude(48)) K> >>> f.subspace(longitude=cf.ge(180), latitude=0, time=cf.month(cf.lt(8))) <CF Field: air_temperature(time(7), latitude(1), longitude(48)) K>
- The field may be subspaced according to conditions on multidimensional items.
>>> print f eastward_wind field summary --------------------------- Data : eastward_wind(time(3), air_pressure(5), grid_latitude(110), grid_longitude(106)) m s-1 Cell methods : time: mean Axes : time(3) = [1979-05-01T12:00:00Z, ..., 1979-05-03T12:00:00Z] gregorian : air_pressure(5) = [850.0, ..., 50.0] hPa : grid_latitude(110) = [23.32, ..., -24.64] degrees : grid_longitude(106) = [-20.54, ..., 25.66] degrees Aux coords : latitude(grid_latitude(110), grid_longitude(106)) = [[67.12, ..., 22.89]] degrees_north : longitude(grid_latitude(110), grid_longitude(106)) = [[-45.98, ..., 35.29]] degrees_east Coord refs : rotated_latitude_longitude >>> f.subspace(latitude=cf.gt(60)) <CF Field: eastward_wind(time(3), air_pressure(5), grid_latitude(35), grid_longitude(106)) m s-1> >>> f.subspace(longitude=cf.wi(-30, 30), latitude=cf.gt(60)) <CF Field: eastward_wind(time(3), air_pressure(5), grid_latitude(35), grid_longitude(66)) m s-1>
Three types of subspace are available:
- A “compress” subspace (the default) is the smallest possible subspace which contains the selected elements. As many non-selected elements are discarded as possible, meaning that the subspace may not form a contiguous bloack of te original field.
- An “envelope” subspace is the smallest subspace which contains the selected elements and forms a contiguous bloack of te original field. Interior, non-selected elements are set to missing data values.
- A “full” subspace is is the same size as the original field, but with all non-selected elements set to missing data values.
>>> f <CF Field: eastward_wind(time(3), air_pressure(5), grid_latitude(110), grid_longitude(106)) m s-1> >>> f.subspace(grid_longitude=cf.wi(-10, -5) | cf.wi(5, 10)) <CF Field: eastward_wind(time(3), air_pressure(5), grid_latitude(110), grid_longitude(23)) m s-1> >>> f.subspace('compress', grid_longitude=cf.wi(-10, -5) | cf.wi(5, 10)) <CF Field: eastward_wind(time(3), air_pressure(5), grid_latitude(110), grid_longitude(23)) m s-1>
>>> f.subspace('envelope', grid_longitude=cf.wi(-10, -5) | cf.wi(5, 10)) <CF Field: eastward_wind(time(3), air_pressure(5), grid_latitude(110), grid_longitude(46)) m s-1>
>>> f.subspace('full', grid_longitude=cf.wi(-10, -5) | cf.wi(5, 10)) <CF Field: eastward_wind(time(3), air_pressure(5), grid_latitude(110), grid_longitude(106)) m s-1>
This is also works for subspaces defined by multidimensional curvilinear, or unstructured coordinates:
>>> print f.subspace('envelope', longitude=cf.wi(-10, 30)) eastward_wind field summary --------------------------- Data : eastward_wind(time(3), air_pressure(5), grid_latitude(110), grid_longitude(91)) m s-1 Cell methods : time: mean Axes : time(3) = [1979-05-01T12:00:00Z, ..., 1979-05-03T12:00:00Z] gregorian : air_pressure(5) = [850.000061035, ..., 50.0000038147] hPa : grid_latitude(110) = [23.3200002313, ..., -24.6399995089] degrees : grid_longitude(91) = [-19.6600109935, ..., 19.9399887919] degrees Aux coords : latitude(grid_latitude(110), grid_longitude(91)) = [[67.6943495635, ..., 24.6226629697]] degrees_north : longitude(grid_latitude(110), grid_longitude(91)) = [[-44.4891982306, ..., 29.9371053319]] degrees_east Coord refs : rotated_latitude_longitude
Defining a subspace in index-space
Subspacing in index-space uses an extended Python slicing syntax, which is similar to numpy array indexing. Extensions to the numpy indexing functionality are:
- The indices for each axis work independently. When more than one axis’s slice is a 1-d boolean sequence or 1-d sequence of integers, then these indices work independently along each axis (similar to the way vector subscripts work in Fortran), rather than by their elements.
- Boolean indices may be any object which exposes the numpy array interface, such as the field’s coordinate objects.
>>> f <CF Field: air_temperature(time(12), latitude(73), longitude(96)) K> >>> f.subspace[:, [0, 72], [5, 4, 3]] <CF Field: air_temperature(time(12), latitude(2), longitude(3)) K> >>> f.subspace[:, f.coord('latitude')<0] <CF Field: air_temperature(time(12), latitude(36), longitude(96)) K>
Size one axes
Size one axes in the subspaced field are always retained, but may be subsequently removed with the field’s
squeeze
method:>>> f <CF Field: air_temperature(time(12), latitude(73), longitude(96)) K> >>> f.subspace(latitude=0) <CF Field: air_temperature(time(12), latitude(1), longitude(96)) K> >>> f.subspace(latitude=0).squeeze() <CF Field: air_temperature(time(12), longitude(96)) K>
>>> f.subspace[..., 12:13] <CF Field: air_temperature(time(12), latitude(73), longitude(1)) K> >>> f.subspace[..., -1].squeeze(2) <CF Field: air_temperature(time(12), latitude(73)) K>
Assignment to the data array
A subspace defined in index-space may have its data array values changed by simple assignment:
>>> f <CF Field: air_temperature(time(12), latitude(73), longitude(96)) K> >>> f.subspace[0:6] = f.subspace[6:12] >>> f.subspace[..., 0:48] = -99
To assign to a subspace defined in metadata-space, the equivalent index-space indices must first be found with the field’s
indices
method, and then the assignment may be applied in index-space:>>> index = f.indices(longitude=cf.lt(180)) >>> f.subspace[index] = cf.masked
This example could have been carried out in index-space if the longitude coordinates were 1-d and their position in the data array was known:
>>> f.subspace[:, :, f.coord('longitude')<180] = cf.masked
However, if the longitude coordinates were multidimensional then only the
indices
approach would have been possible.See also
Examples: >>> f,shape (12, 73, 96) >>> f.subspace().shape (12, 73, 96) >>> f.subspace(latitude=0).shape (12, 1, 96) >>> f.subspace(latitude=cf.wi(-30, 30)).shape (12, 25, 96) >>> f.subspace(long=cf.ge(270, 'degrees_east'), lat=cf.set([0, 2.5, 10])).shape (12, 3, 24) >>> f.subspace(latitude=cf.lt(0, 'degrees_north')) (12, 36, 96) >>> f.subspace(latitude=[cf.lt(0, 'degrees_north'), 90]) (12, 37, 96) >>> import math >>> f.subspace('exact', longitude=cf.lt(math.pi, 'radian'), height=2) (12, 73, 48) >>> f.subspace(height=cf.gt(3)) IndexError: No indices found for 'height' values gt 3 >>> f.subspace(dim2=3.75).shape (12, 1, 96) >>> f.subspace(time=cf.le(cf.dt('1860-06-16 12:00:00')).shape (6, 73, 96) >>> f.subspace(time=cf.gt(cf.dt(1860, 7)),shape (5, 73, 96)
Note that if a comparison function (such as
cf.wi
) does not specify any units, then the units of the named item are assumed.