def test_scalar_coord(self): """Test it works if blend coordinate is scalar. """ self.cube.add_aux_coord(AuxCoord(1, long_name="scalar_coord", units="no_unit")) coord = self.cube.coord("scalar_coord") plugin = NonLinearWeights(0.85) result = plugin.process(self.cube, coord) self.assertArrayAlmostEqual(result.data, np.array([1.0]))
def test_fails_input_not_a_cube(self): """Test it raises a Value Error if not supplied with a cube. """ plugin = NonLinearWeights(0.85) notacube = 0.0 msg = "The first argument must be an instance of " "iris.cube.Cube" with self.assertRaisesRegex(TypeError, msg): plugin.process(notacube, self.coord_name)
def test_fails_coord_not_in_cube(self): """Test it raises a Value Error if coord not in the cube. """ coord = "notset" plugin = NonLinearWeights() msg = ('The coord for this plugin must be ' 'an existing coordinate in the input cube') with self.assertRaisesRegexp(ValueError, msg): plugin.process(self.cube, coord)
def test_works_if_scalar_coord(self): """Test it works if scalar coordinate. """ self.cube.add_aux_coord( AuxCoord(1, long_name='scalar_coord', units='no_unit')) coord = self.cube.coord("scalar_coord") plugin = NonLinearWeights() result = plugin.process(self.cube, coord) self.assertArrayAlmostEqual(result.data, np.array([1.0]))
def test_larger_num(self): """Test it works with larger num_of_vals. """ plugin = NonLinearWeights(cval=0.5) cubenew = add_coordinate(self.cube, np.arange(6), "realization", dtype=np.int32) coord_name = "realization" result = plugin.process(cubenew, coord_name) expected_result = np.array( [0.50793651, 0.25396825, 0.12698413, 0.06349206, 0.03174603, 0.01587302] ) self.assertArrayAlmostEqual(result.data, expected_result)
def test_works_with_missing_coord(self): """Test it works with missing coord """ plugin = NonLinearWeights(cval=0.6) cubenew = add_realizations(self.cube, 6) coord_vals = '0, 1, 2, 3, 4, 5, 6' coord_name = 'realization' result = plugin.process(cubenew, coord_name, coord_vals) expected_result = np.array( [0.41472, 0.250112, 0.151347, 0.092088, 0.056533, 0.0352]) self.assertArrayAlmostEqual(result, expected_result)
def test_works_with_larger_num(self): """Test it works with larger num_of_vals. """ plugin = NonLinearWeights(cval=0.5) cubenew = add_realizations(self.cube, 6) coord_name = 'realization' coord_vals = ','.join( [str(x) for x in cubenew.coord('realization').points]) result = plugin.process(cubenew, coord_name, coord_vals) expected_result = np.array([ 0.50793651, 0.25396825, 0.12698413, 0.06349206, 0.03174603, 0.01587302 ]) self.assertArrayAlmostEqual(result, expected_result)
def _calculate_blending_weights(self, cube): """ Wrapper for plugins to calculate blending weights by the appropriate method. Args: cube (iris.cube.Cube): Cube of input data to be blended Returns: iris.cube.Cube: Cube containing 1D array of weights for blending """ if self.wts_calc_method == "dict": if "model" in self.blend_coord: config_coord = "model_configuration" else: config_coord = self.blend_coord weights = ChooseWeightsLinear(self.weighting_coord, self.wts_dict, config_coord_name=config_coord)(cube) elif self.wts_calc_method == "linear": weights = ChooseDefaultWeightsLinear(y0val=self.y0val, ynval=self.ynval)( cube, self.blend_coord) elif self.wts_calc_method == "nonlinear": weights = ChooseDefaultWeightsNonLinear(self.cval)( cube, self.blend_coord, inverse_ordering=self.inverse_ordering) return weights
def test_values_inverse_ordering(self): """Test inverting the order of the input cube produces inverted weights order, with the cube and weights cube still matching in dimensions. """ reference_cube = self.cube.copy() plugin = NonLinearWeights(cval=0.85) result = plugin.process( self.cube, self.coord_name, inverse_ordering=True) expected_result = np.array([0.45945946, 0.54054054]) self.assertArrayAlmostEqual(result.data, expected_result) # check input cube blend coordinate order is unchanged self.assertArrayEqual( self.cube.coord(self.coord_name).points, reference_cube.coord(self.coord_name).points) # check weights cube and input cube blend coordinate orders match self.assertArrayEqual( result.coord(self.coord_name).points, reference_cube.coord(self.coord_name).points)
def test_fails_if_cval_not_valid(self): """Test it raises a Value Error if cval is not in range, cval must be greater than 0.0 and less than or equal to 1.0 """ plugin = NonLinearWeights(cval=-1.0) msg = ('cval must be greater than 0.0 and less ' 'than or equal to 1.0') with self.assertRaisesRegexp(ValueError, msg): plugin.process(self.cube, self.coord_name, self.coord_vals) plugin2 = NonLinearWeights(cval=1.1) with self.assertRaisesRegexp(ValueError, msg): plugin2.process(self.cube, self.coord_name, self.coord_vals)
def calculate_blending_weights(cube, blend_coord, method, wts_dict=None, weighting_coord=None, coord_unit=None, y0val=None, ynval=None, cval=None, dict_coord=None): """ Wrapper for plugins to calculate blending weights using the command line options specified. Args: cube (iris.cube.Cube): Cube of input data to be blended blend_coord (str): Coordinate over which blending will be performed (eg "model" for grid blending) method (str): Weights calculation method ("linear", "nonlinear", "dict" or "mask") Kwargs: wts_dict (str): File path to json file with parameters for linear weights calculation weighting_coord (str): Coordinate over which linear weights should be calculated from dict coord_unit (str or cf_units.Unit): Unit of blending coordinate (for default weights plugins) y0val (float): Intercept parameter for default linear weights plugin ynval (float): Gradient parameter for default linear weights plugin cval (float): Parameter for default non-linear weights plugin dict_coord (str): The coordinate that will be used when accessing the weights from the weights dictionary. Returns: weights (np.ndarray): 1D array of weights corresponding to slices in ascending order of blending coordinate. (Note: ChooseLinearWeights has the option to create a 3D array of spatially-varying weights with the "mask" option, however this is not currently supported by the blending plugin.) """ # sort input cube by blending coordinate cube = sort_coord_in_cube(cube, blend_coord, order="ascending") # calculate blending weights if method == "dict": # calculate linear weights from a dictionary with open(wts_dict, 'r') as wts: weights_dict = json.load(wts) weights_cube = ChooseWeightsLinear( weighting_coord, weights_dict, config_coord_name=dict_coord).process(cube) # sort weights cube by blending coordinate weights = sort_coord_in_cube(weights_cube, blend_coord, order="ascending") elif method == "linear": weights = ChooseDefaultWeightsLinear(y0val=y0val, ynval=ynval).process( cube, blend_coord, coord_unit=coord_unit) elif method == "nonlinear": # this is set here rather than in the CLI arguments in order to check # for invalid argument combinations cvalue = cval if cval else 0.85 weights = ChooseDefaultWeightsNonLinear(cvalue).process( cube, blend_coord, coord_unit=coord_unit) return weights
def test_cval_equal_one(self): """Test it works with cval = 1.0, i.e. equal weights. """ plugin = NonLinearWeights(cval=1.0) result = plugin.process(self.cube, self.coord_name) expected_result = np.array([0.5, 0.5]) self.assertArrayAlmostEqual(result.data, expected_result)
def test_values(self): """Test weights values. """ plugin = NonLinearWeights(cval=0.85) result = plugin.process(self.cube, self.coord_name) expected_result = np.array([0.54054054, 0.45945946]) self.assertArrayAlmostEqual(result.data, expected_result)
def test_array_sum_equals_one(self): """Test that the resulting weights add up to one. """ plugin = NonLinearWeights(0.85) result = plugin.process(self.cube, self.coord_name) self.assertAlmostEqual(result.data.sum(), 1.0)
def test_basic(self): """Test that the plugin returns an array of weights. """ plugin = NonLinearWeights(0.85) result = plugin.process(self.cube, self.coord_name) self.assertIsInstance(result, iris.cube.Cube)
def test_basic(self): """Test that the plugin returns an array of weights. """ plugin = NonLinearWeights() result = plugin.process(self.cube, self.coord_name, self.coord_vals) self.assertIsInstance(result, np.ndarray)
def test_works_with_default_cval(self): """Test it works with default cval. """ plugin = NonLinearWeights() result = plugin.process(self.cube, self.coord_name, self.coord_vals) expected_result = np.array([0.54054054, 0.45945946]) self.assertArrayAlmostEqual(result, expected_result)
def test_works_if_scalar_coord(self): """Test it works if scalar coordinate. """ coord = self.cube.coord("scalar_coord") plugin = NonLinearWeights() result = plugin.process(self.cube, coord) self.assertArrayAlmostEqual(result, np.array([1.0]))