Пример #1
0
def _assert_compatible(cube, other):
    """
    Checks to see if cube.data and another array can be broadcast to
    the same shape using ``numpy.broadcast_arrays``.

    """
    # This code previously returned broadcasted versions of the cube
    # data and the other array. As numpy.broadcast_arrays does not work
    # with masked arrays (it returns them as ndarrays) operations
    # involving masked arrays would be broken.

    try:
        if not isinstance(other, biggus.Array):
            data_view, other_view = BA.broadcast_arrays(cube._my_data,
                                                        np.asarray(other))

        else:
            data_view, other_view = BA.broadcast_arrays(cube._my_data, other)
    except ValueError as err:
        # re-raise
        raise ValueError("The array was not broadcastable to the cube's data "
                         "shape. The error message from numpy when "
                         "broadcasting:\n{}\nThe cube's shape was {} and the "
                         "array's shape was {}".format(err, cube.shape,
                                                       other.shape))

    if cube.shape != data_view.shape:
        raise ValueError("The array operation would increase the "
                         "dimensionality of the cube. The new cube's data "
                         "would have had to become: {}".format(
                             data_view.shape))
Пример #2
0
def _assert_compatible(cube, other):
    """
    Checks to see if cube.data and another array can be broadcast to
    the same shape using ``numpy.broadcast_arrays``.

    """
    # This code previously returned broadcasted versions of the cube
    # data and the other array. As numpy.broadcast_arrays does not work
    # with masked arrays (it returns them as ndarrays) operations
    # involving masked arrays would be broken.

    try:
        if not isinstance(other, biggus.Array):
            data_view, other_view = BA.broadcast_arrays(
                cube._my_data, np.asarray(other))

        else:
            data_view, other_view = BA.broadcast_arrays(cube._my_data, other)
    except ValueError as err:
        # re-raise
        raise ValueError("The array was not broadcastable to the cube's data "
                         "shape. The error message from numpy when "
                         "broadcasting:\n{}\nThe cube's shape was {} and the "
                         "array's shape was {}".format(err, cube.shape,
                                                       other.shape))

    if cube.shape != data_view.shape:
        raise ValueError("The array operation would increase the "
                         "dimensionality of the cube. The new cube's data "
                         "would have had to become: {}".format(
                             data_view.shape))
Пример #3
0
def _binary_op_common(operation_function,
                      operation_name,
                      cube,
                      other,
                      new_unit,
                      dim=None,
                      in_place=False):
    """
    Function which shares common code between binary operations.

    operation_function   - function which does the operation
                           (e.g. numpy.divide)
    operation_name       - the public name of the operation (e.g. 'divide')
    cube                 - the cube whose data is used as the first argument
                           to `operation_function`
    other                - the cube, coord, ndarray or number whose data is
                           used as the second argument
    new_unit             - unit for the resulting quantity
    dim                  - dimension along which to apply `other` if it's a
                           coordinate that is not found in `cube`
    in_place             - whether or not to apply the operation in place to
                           `cube` and `cube.data`
    """
    _assert_is_cube(cube)

    if isinstance(other, iris.coords.Coord):
        other = _broadcast_cube_coord_data(cube, other, operation_name, dim)
    elif isinstance(other, iris.cube.Cube):
        try:
            BA.broadcast_arrays(cube._my_data, other._my_data)
        except ValueError:
            other = iris.util.as_compatible_shape(other, cube)._my_data
        else:
            other = other._my_data

    # don't worry about checking for other data types (such as scalars or
    # np.ndarrays) because _assert_compatible validates that they are broadcast
    # compatible with cube.data
    _assert_compatible(cube, other)

    def unary_func(x):
        ret = operation_function(x, other)
        if ret is NotImplemented:
            # explicitly raise the TypeError, so it gets raised even if, for
            # example, `iris.analysis.maths.multiply(cube, other)` is called
            # directly instead of `cube * other`
            raise TypeError('cannot %s %r and %r objects' %
                            (operation_function.__name__, type(x).__name__,
                             type(other).__name__))
        return ret

    return _math_op_common(cube, unary_func, new_unit, in_place)
Пример #4
0
 def test_lh_broadcast(self):
     a = np.empty([2])
     b = np.empty([1, 2])
     a1, b1 = BroadcastArray.broadcast_arrays(a, b)
     self.assertIs(b1, b)
     self.assertIsInstance(a1, BroadcastArray)
     self.assertEqual(a1.shape, (1, 2))
Пример #5
0
 def test_lh_broadcast(self):
     a = np.empty([2])
     b = np.empty([1, 2])
     a1, b1 = BroadcastArray.broadcast_arrays(a, b)
     self.assertIs(b1, b)
     self.assertIsInstance(a1, BroadcastArray)
     self.assertEqual(a1.shape, (1, 2))
Пример #6
0
def _binary_op_common(operation_function, operation_name, cube, other,
                      new_unit, dim=None, in_place=False):
    """
    Function which shares common code between binary operations.

    operation_function   - function which does the operation
                           (e.g. numpy.divide)
    operation_name       - the public name of the operation (e.g. 'divide')
    cube                 - the cube whose data is used as the first argument
                           to `operation_function`
    other                - the cube, coord, ndarray or number whose data is
                           used as the second argument
    new_unit             - unit for the resulting quantity
    dim                  - dimension along which to apply `other` if it's a
                           coordinate that is not found in `cube`
    in_place             - whether or not to apply the operation in place to
                           `cube` and `cube.data`
    """
    _assert_is_cube(cube)

    if isinstance(other, iris.coords.Coord):
        other = _broadcast_cube_coord_data(cube, other, operation_name, dim)
    elif isinstance(other, iris.cube.Cube):
        try:
            BA.broadcast_arrays(cube._my_data, other._my_data)
        except ValueError:
            other = iris.util.as_compatible_shape(other, cube)._my_data
        else:
            other = other._my_data

    # don't worry about checking for other data types (such as scalars or
    # np.ndarrays) because _assert_compatible validates that they are broadcast
    # compatible with cube.data
    _assert_compatible(cube, other)

    def unary_func(x):
        ret = operation_function(x, other)
        if ret is NotImplemented:
            # explicitly raise the TypeError, so it gets raised even if, for
            # example, `iris.analysis.maths.multiply(cube, other)` is called
            # directly instead of `cube * other`
            raise TypeError('cannot %s %r and %r objects' %
                            (operation_function.__name__, type(x).__name__,
                             type(other).__name__))
        return ret
    return _math_op_common(cube, unary_func, new_unit, in_place)