Source code for improver.utilities.mask

# (C) Crown Copyright, Met Office. All rights reserved.
#
# This file is part of 'IMPROVER' and is released under the BSD 3-Clause license.
# See LICENSE in the root of the repository for full licensing details.
"""Module for applying mask to a cube."""

from typing import Union

import iris
import numpy as np

from improver.utilities.common_input_handle import as_cubelist
from improver.utilities.cube_checker import find_dimension_coordinate_mismatch
from improver.utilities.cube_manipulation import (
    enforce_coordinate_ordering,
    get_coord_names,
)


[docs] def apply_mask( *cubes: Union[iris.cube.CubeList, iris.cube.Cube], mask_name: str, invert_mask: bool = False, ) -> iris.cube.Cube: """ Apply a provided mask to a cube. If invert_mask is True, the mask will be inverted. Args: cubes: A list of iris cubes that should contain exactly two cubes: a mask and a cube to apply the mask to. The cubes should have the same dimensions. mask_name: The name of the mask cube. It should match with exactly one of the cubes in the input cubelist. invert_mask: If True, the mask will be inverted before it is applied. Returns: A cube with a mask applied to the data. Raises: ValueError: If the number of cubes provided is not equal to 2. ValueError: If the input cube and mask cube have different dimensions. """ cubes = as_cubelist(*cubes) cube_names = [cube.name() for cube in cubes] if len(cubes) != 2: raise ValueError( f"""Two cubes are required for masking, a mask and the cube to be masked. Provided cubes are {cube_names}""" ) mask = cubes.extract_cube(mask_name) cubes.remove(mask) cube = cubes[0] # Ensure mask is in a boolean form and invert if requested mask.data = mask.data.astype(np.bool) if invert_mask: mask.data = ~mask.data coord_list = get_coord_names(cube) enforce_coordinate_ordering(mask, coord_list) # This error is required to stop the mask from being broadcasted to a new shape by numpy. When # the mask and cube have different shapes numpy will try to broadcast the mask to be the same # shape as the cube data. This might succeed but masks unexpected data points. if find_dimension_coordinate_mismatch(cube, mask): raise ValueError("Input cube and mask cube must have the same dimensions") cube.data = np.ma.array(cube.data, mask=mask.data) return cube