dask: `Data.outerproduct` by davidhassell · Pull Request #398 · NCAS-CMS/cf-python
Expand Up
@@ -7003,6 +7003,7 @@ def asdata(cls, d, dtype=None, copy=False):
return data
# d does have a Data interface data = data() if copy: data = data.copy() Expand Down Expand Up @@ -8746,22 +8747,21 @@ def floor(self, inplace=False, i=False): d._set_dask(da.floor(dx), reset_mask_hardness=False) return d
@daskified(_DASKIFIED_VERBOSE) @_inplace_enabled(default=False) @_deprecated_kwarg_check("i") def outerproduct(self, e, inplace=False, i=False): def outerproduct(self, a, inplace=False, i=False): """Compute the outer product with another data array.
The axes of result will be the combined axes of the two input arrays: arrays.
>>> d.outerproduct(e).ndim == d.ndim + e.ndim True >>> d.outerproduct(e).shape == d.shape + e.shape True .. seealso:: `np.multiply.outer`
:Parameters:
e: data-like The data array with which to form the outer product. a: array_like The data with which to form the outer product.
{{inplace: `bool`, optional}}
Expand All @@ -8770,50 +8770,54 @@ def outerproduct(self, e, inplace=False, i=False): :Returns:
`Data` or `None` The outer product, or `None` if the operation was in-place.
**Examples**
>>> d = cf.Data([1, 2, 3], 'metre') >>> o = d.outerproduct([4, 5, 6, 7]) >>> o <CF Data: [[4, ..., 21]] m> >>> print(o.array) >>> d = cf.Data([1, 2, 3], 'm') >>> d <CF Data(3): [1, 2, 3] m> >>> f = d.outerproduct([4, 5, 6, 7]) >>> f <CF Data(3, 4): [[4, ..., 21]] m> >>> print(f.array) [[ 4 5 6 7] [ 8 10 12 14] [12 15 18 21]]
>>> e = cf.Data([[4, 5, 6, 7], [6, 7, 8, 9]], 's-1') >>> o = d.outerproduct(e) >>> o <CF Data: [[[4, ..., 27]]] m.s-1> >>> print(d.shape, e.shape, o.shape) (3,) (2, 4) (3, 2, 4) >>> print(o.array) >>> e <CF Data(2, 4): [[4, ..., 9]] s-1> >>> f = d.outerproduct(e) >>> f <CF Data(3, 2, 4): [[[4, ..., 27]]] m.s-1> >>> print(f.array) [[[ 4 5 6 7] [ 6 7 8 9]]
[[ 8 10 12 14] [12 14 16 18]]
[[12 15 18 21] [18 21 24 27]]]
""" e_ndim = np.ndim(e) if e_ndim: if inplace: d = self else: d = self.copy() d = _inplace_enabled_define_and_cleanup(self)
for j in range(np.ndim(e)): d.insert_dimension(-1, inplace=True) else: d = self # Cast 'a' as a Data object so that it definitely has sensible # Units a = self.asdata(a) try: a = conform_units(a, d.Units) except ValueError: pass
d = d * e dx = d.to_dask_array() dx = da.ufunc.multiply.outer(dx, a) d._set_dask(dx, reset_mask_hardness=False)
if inplace: self.__dict__ = d.__dict__ d = None d.override_units(d.Units * a.Units, inplace=True)
return d
Expand Down Expand Up @@ -9667,6 +9671,10 @@ def isclose(self, y, rtol=None, atol=None): def reshape(self, *shape, merge_chunks=True, limit=None, inplace=False): """Change the shape of the data without changing its values.
It assumes that the array is stored in row-major order, and only allows for reshapings that collapse or merge dimensions like ``(1, 2, 3, 4) -> (1, 6, 4)`` or ``(64,) -> (4, 4, 4)``.
:Parameters:
shape: `tuple` of `int`, or any number of `int` Expand All @@ -9687,9 +9695,8 @@ def reshape(self, *shape, merge_chunks=True, limit=None, inplace=False):
limit: int, optional The maximum block size to target in bytes. If no limit is provided, it defaults to the configuration value ``dask.config.get('array.chunk-size')``. See `dask.array.reshape` for details. is provided, it defaults to a size in bytes defined by the `cf.chunksize` function.
:Returns:
Expand Down
return data
# d does have a Data interface data = data() if copy: data = data.copy() Expand Down Expand Up @@ -8746,22 +8747,21 @@ def floor(self, inplace=False, i=False): d._set_dask(da.floor(dx), reset_mask_hardness=False) return d
@daskified(_DASKIFIED_VERBOSE) @_inplace_enabled(default=False) @_deprecated_kwarg_check("i") def outerproduct(self, e, inplace=False, i=False): def outerproduct(self, a, inplace=False, i=False): """Compute the outer product with another data array.
The axes of result will be the combined axes of the two input arrays: arrays.
>>> d.outerproduct(e).ndim == d.ndim + e.ndim True >>> d.outerproduct(e).shape == d.shape + e.shape True .. seealso:: `np.multiply.outer`
:Parameters:
e: data-like The data array with which to form the outer product. a: array_like The data with which to form the outer product.
{{inplace: `bool`, optional}}
Expand All @@ -8770,50 +8770,54 @@ def outerproduct(self, e, inplace=False, i=False): :Returns:
`Data` or `None` The outer product, or `None` if the operation was in-place.
**Examples**
>>> d = cf.Data([1, 2, 3], 'metre') >>> o = d.outerproduct([4, 5, 6, 7]) >>> o <CF Data: [[4, ..., 21]] m> >>> print(o.array) >>> d = cf.Data([1, 2, 3], 'm') >>> d <CF Data(3): [1, 2, 3] m> >>> f = d.outerproduct([4, 5, 6, 7]) >>> f <CF Data(3, 4): [[4, ..., 21]] m> >>> print(f.array) [[ 4 5 6 7] [ 8 10 12 14] [12 15 18 21]]
>>> e = cf.Data([[4, 5, 6, 7], [6, 7, 8, 9]], 's-1') >>> o = d.outerproduct(e) >>> o <CF Data: [[[4, ..., 27]]] m.s-1> >>> print(d.shape, e.shape, o.shape) (3,) (2, 4) (3, 2, 4) >>> print(o.array) >>> e <CF Data(2, 4): [[4, ..., 9]] s-1> >>> f = d.outerproduct(e) >>> f <CF Data(3, 2, 4): [[[4, ..., 27]]] m.s-1> >>> print(f.array) [[[ 4 5 6 7] [ 6 7 8 9]]
[[ 8 10 12 14] [12 14 16 18]]
[[12 15 18 21] [18 21 24 27]]]
""" e_ndim = np.ndim(e) if e_ndim: if inplace: d = self else: d = self.copy() d = _inplace_enabled_define_and_cleanup(self)
for j in range(np.ndim(e)): d.insert_dimension(-1, inplace=True) else: d = self # Cast 'a' as a Data object so that it definitely has sensible # Units a = self.asdata(a) try: a = conform_units(a, d.Units) except ValueError: pass
d = d * e dx = d.to_dask_array() dx = da.ufunc.multiply.outer(dx, a) d._set_dask(dx, reset_mask_hardness=False)
if inplace: self.__dict__ = d.__dict__ d = None d.override_units(d.Units * a.Units, inplace=True)
return d
Expand Down Expand Up @@ -9667,6 +9671,10 @@ def isclose(self, y, rtol=None, atol=None): def reshape(self, *shape, merge_chunks=True, limit=None, inplace=False): """Change the shape of the data without changing its values.
It assumes that the array is stored in row-major order, and only allows for reshapings that collapse or merge dimensions like ``(1, 2, 3, 4) -> (1, 6, 4)`` or ``(64,) -> (4, 4, 4)``.
:Parameters:
shape: `tuple` of `int`, or any number of `int` Expand All @@ -9687,9 +9695,8 @@ def reshape(self, *shape, merge_chunks=True, limit=None, inplace=False):
limit: int, optional The maximum block size to target in bytes. If no limit is provided, it defaults to the configuration value ``dask.config.get('array.chunk-size')``. See `dask.array.reshape` for details. is provided, it defaults to a size in bytes defined by the `cf.chunksize` function.
:Returns:
Expand Down