diff --git a/cf/field.py b/cf/field.py index f46bc0fa0b..c8bfde5fb2 100644 --- a/cf/field.py +++ b/cf/field.py @@ -8809,7 +8809,7 @@ def insert_dimension( inplace=inplace, ) - def indices(self, *config, **kwargs): + def indices(self, *mode, **kwargs): """Create indices that define a subspace of the field construct. The subspace is defined by identifying indices based on the @@ -8860,30 +8860,39 @@ def indices(self, *config, **kwargs): actually created, these masks are all automatically applied to the result. - **Halos** - - {{subspace halos}} - - 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. - - .. versionadded:: 1.0 - .. seealso:: `subspace`, `where`, `__getitem__`, `__setitem__`, `cf.Domain.indices` :Parameters: - {{config: optional}} - - {{subspace valid modes Field}} - - kwargs: optional + mode: `str`, *optional* + There are three modes of operation, each of which + provides indices for a different type of subspace: + + ============== ====================================== + *mode* Description + ============== ====================================== + ``'compress'`` This is the default mode. Unselected + locations are removed to create the + returned subspace. Note that if a + multi-dimensional metadata construct + is being used to define the indices + then some missing data may still be + inserted at unselected locations. + + ``'envelope'`` The returned subspace is the smallest + that contains all of the selected + indices. Missing data is inserted at + unselected locations within the + envelope. + + ``'full'`` The returned subspace has the same + domain as the original field + construct. Missing data is inserted at + unselected locations. + ============== ====================================== + + 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 @@ -9006,7 +9015,7 @@ def indices(self, *config, **kwargs): [-- -- -- -- -- -- 270.6 273.0 270.6]]] """ - if "exact" in config: + if "exact" in mode: _DEPRECATION_ERROR_ARG( self, "indices", @@ -9016,11 +9025,26 @@ def indices(self, *config, **kwargs): removed_at="4.0.0", ) # pragma: no cover + if len(mode) > 1: + raise ValueError( + "Can't provide more than one positional argument. " + f"Got: {', '.join(repr(x) for x in mode)}" + ) + + if not mode or "compress" in mode: + mode = "compress" + elif "envelope" in mode: + mode = "envelope" + elif "full" in mode: + mode = "full" + else: + raise ValueError(f"Invalid value for 'mode' argument: {mode[0]!r}") + data_axes = self.get_data_axes() # Get the indices for every domain axis in the domain, # including any ancillary masks - domain_indices = self._indices(config, data_axes, True, kwargs) + domain_indices = self._indices(mode, data_axes, True, kwargs) # Initialise the output indices with any ancillary masks. # Ensure that each ancillary mask is broadcastable to the @@ -9052,9 +9076,7 @@ def indices(self, *config, **kwargs): # spanned by the data if len(axis_indices) > len(data_axes): for axis, index in axis_indices.items(): - if axis in data_axes or ( - isinstance(index, slice) and index == slice(None) - ): + if axis in data_axes or index == slice(None): continue import dask.array as da @@ -13270,33 +13292,44 @@ def subspace(self): ``3:-2:-1``) is assumed to "wrap" around, rather then producing a null result. - **Halos** - - {{subspace halos}} - For instance, ``f.subspace(X=slice(10, 20))`` will give - identical results to each of ``f.subspace(0, X=slice(10, - 20))``, ``f.subspace(1, X=slice(11, 19))``, ``f.subspace(2, - X=slice(12, 18))``, etc. - - .. versionadded:: 1.0 - - .. seealso:: `indices`, `where`, `__getitem__`, - `__setitem__`, `cf.Domain.subspace` + .. seealso:: `indices`, `squeeze`, `where`, `__getitem__` :Parameters: - {{config: optional}} - - {{subspace valid modes Field}} + positional arguments: *optional* + There are three modes of operation, each of which provides + a different type of subspace: - In addition, an extra positional argument of ``'test'`` - is allowed. When provided, the subspace is not - returned, instead `True` or `False` is returned - depending on whether or not it is possible for the - requested subspace to be created. + ============== ========================================== + *argument* Description + ============== ========================================== + ``'compress'`` This is the default mode. Unselected + locations are removed to create the + returned subspace. Note that if a + multi-dimensional metadata construct is + being used to define the indices then some + missing data may still be inserted at + unselected locations. + + ``'envelope'`` The returned subspace is the smallest that + contains all of the selected + indices. Missing data is inserted at + unselected locations within the envelope. + + ``'full'`` The returned subspace has the same domain + as the original field construct. Missing + data is inserted at unselected locations. + + ``'test'`` May be used on its own or in addition to + one of the other positional arguments. Do + not create a subspace, but return `True` + or `False` depending on whether or not it + is possible to create specified the + subspace. + ============== ========================================== - keyword parameters: optional + keyword parameters: *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) @@ -13491,6 +13524,7 @@ def regrids( inplace=False, i=False, _compute_field_mass=None, + return_esmpy_regrid_operator=False, ): """Regrid the field to a new latitude and longitude grid. @@ -13727,6 +13761,10 @@ def regrids( .. versionadded:: 3.16.0 {{inplace: `bool`, optional}} + + {{return_esmpy_regrid_operator: `bool`, optional}} + + .. versionadded:: 3.16.2 axis_order: sequence, optional Deprecated at version 3.14.0. @@ -13738,13 +13776,15 @@ def regrids( Deprecated at version 3.14.0. {{i: deprecated at version 3.0.0}} + :Returns: `Field` or `None` or `RegridOperator` The regridded field construct; or `None` if the operation was in-place; or the regridding operator if - *return_operator* is True. + *return_operator* is True; or the esmpy.Regrid operator + object if *return_esmpy_regrid_operator* is True. **Examples** @@ -13819,6 +13859,7 @@ def regrids( dst_z=dst_z, z=z, ln_z=ln_z, + return_esmpy_regrid_operator=return_esmpy_regrid_operator, inplace=inplace, ) @@ -13845,6 +13886,7 @@ def regridc( inplace=False, i=False, _compute_field_mass=None, + return_esmpy_regrid_operator=False, ): """Regrid the field to a new Cartesian grid. @@ -14016,6 +14058,10 @@ def regridc( .. versionadded:: 3.16.2 {{inplace: `bool`, optional}} + + {{return_esmpy_regrid_operator: `bool`, optional}} + + .. versionadded:: 3.16.2 axis_order: sequence, optional Deprecated at version 3.14.0. @@ -14033,7 +14079,8 @@ def regridc( `Field` or `None` or `RegridOperator` The regridded field construct; or `None` if the operation was in-place; or the regridding operator if - *return_operator* is True. + *return_operator* is True; or the esmpy.Regrid operator + object if *return_esmpy_regrid_operator* is True. **Examples** @@ -14107,6 +14154,7 @@ def regridc( dst_z=dst_z, z=z, ln_z=ln_z, + return_esmpy_regrid_operator=return_esmpy_regrid_operator, inplace=inplace, )