def test_without_masked_data(self): """Test setting up cubes to be neighbourhooded when the input cube does not contain masked arrays.""" cubes = (SquareNeighbourhood._set_up_cubes_to_be_neighbourhooded( self.cube)) self.assertIsInstance(cubes, CubeList) self.assertEqual(len(cubes), 1) self.assertEqual(cubes[0], self.cube)
def test_with_masked_data(self): """Test setting up cubes to be neighbourhooded when the input cube contains masked arrays.""" cube = self.cube data = cube.data cube.data[0, 0, 1, 3] = 0.5 cube.data[0, 0, 3, 3] = 0.5 cube.data = np.ma.masked_equal(data, 0.5) mask = np.logical_not(cube.data.mask.astype(int)) data = cube.data.data * mask cubes = (SquareNeighbourhood._set_up_cubes_to_be_neighbourhooded( cube.copy())) self.assertIsInstance(cubes, CubeList) self.assertEqual(len(cubes), 2) self.assertArrayAlmostEqual(cubes[0].data, data) self.assertArrayAlmostEqual(cubes[1].data, mask)
def process(self, cube, alphas_x=None, alphas_y=None, mask_cube=None): """ Set up the alpha parameters and run the recursive filter. The steps undertaken are: 1. Split the input cube into slices determined by the co-ordinates in the x and y directions. 2. Construct an array of filter parameters (alphas_x and alphas_y) for each cube slice that are used to weight the recursive filter in the x- and y-directions. 3. Pad each cube slice with a square-neighbourhood halo and apply the recursive filter for the required number of iterations. 4. Remove the halo from the cube slice and append the recursed cube slice to a 'recursed cube'. 5. Merge all the cube slices in the 'recursed cube' into a 'new cube'. 6. Modify the 'new cube' so that its scalar dimension co-ordinates are consistent with those in the original input cube. 7. Return the 'new cube' which now contains the recursively filtered values for the original input cube. Args: cube (Iris.cube.Cube): Cube containing the input data to which the recursive filter will be applied. Keyword Args: alphas_x (Iris.cube.Cube or None): Cube containing array of alpha values that will be used when applying the recursive filter along the x-axis. alphas_y (Iris.cube.Cube or None): Cube containing array of alpha values that will be used when applying the recursive filter along the y-axis. mask_cube (Iris.cube.Cube or None): Cube containing an external mask to apply to the cube before applying the recursive filter. Returns: new_cube (Iris.cube.Cube): Cube containing the smoothed field after the recursive filter method has been applied. """ cube_format = next( cube.slices([cube.coord(axis='y'), cube.coord(axis='x')])) alphas_x = self.set_alphas(cube_format, self.alpha_x, alphas_x) alphas_y = self.set_alphas(cube_format, self.alpha_y, alphas_y) # Extract mask if present on input cube or provided separately. try: mask, = SquareNeighbourhood._set_up_cubes_to_be_neighbourhooded( cube, mask_cube).extract('mask_data') mask = mask.data.squeeze() except ValueError: mask = np.ones((cube_format.data.shape)) recursed_cube = iris.cube.CubeList() for output in cube.slices([cube.coord(axis='y'), cube.coord(axis='x')]): # Use mask to zero masked areas. output.data = output.data * mask # Zero any remaining NaN values not covered by mask. output.data = np.nan_to_num(output.data) padded_cube = SquareNeighbourhood().pad_cube_with_halo( output, self.edge_width, self.edge_width) new_cube = self.run_recursion(padded_cube, alphas_x, alphas_y, self.iterations) new_cube = SquareNeighbourhood().remove_halo_from_cube( new_cube, self.edge_width, self.edge_width) if self.re_mask: new_cube.data = np.ma.masked_array(new_cube.data, mask=np.logical_not(mask)) recursed_cube.append(new_cube) new_cube = recursed_cube.merge_cube() new_cube = check_cube_coordinates(cube, new_cube) return new_cube