def test_mismatch_masks(self): """Tests fast_linear_fit with mismatching masks.""" mask = self.mask.copy() mask[12] = True self.x_data = ma.masked_array(self.x_data, mask=mask) with self.assertRaises(ValueError): fast_linear_fit(self.x_data, self.y_data)
def linear_fit(self, shape=(25,), axis=-1, with_nan=False): """Compares the output of fast_linear_fit with numpy's leastsquare algorithm.""" expected_out = self.use_lstsq() x_data = self.x_data.reshape(shape) y_data = self.y_data.reshape(shape) result = np.array(fast_linear_fit(x_data, y_data, axis=axis, with_nan=with_nan)) self.assertArrayAlmostEqual(expected_out, result)
def linear_wet_bulb_fit(wet_bulb_temperature, heights, sea_points, start_point=0, end_point=5): """ Calculates a linear fit to the wet bulb temperature profile close to the surface to use when we extrapolate the wet bulb temperature below sea level for sea points. We only use a set number of points close to the surface for this fit, specified by a start_point and end_point. Args: wet_bulb_temperature (numpy.ndarray): The wet bulb temperature profile at each grid point, with height as the leading dimension. heights (numpy.ndarray): The vertical height levels above orography, matching the leading dimension of the wet_bulb_temperature. sea_points (numpy.ndarray): A boolean array with True where the points are sea points. start_point (int): The index of the the starting height we want to use in our linear fit. end_point (int): The index of the the end height we want to use in our linear fit. Returns: (tuple): tuple containing: **gradient** (numpy.ndarray) - An array, the same shape as a 2D slice of the wet_bulb_temperature input, containing the gradients of the fitted straight line at each point where it could be found, filled with zeros elsewhere. **intercept** (numpy.ndarray) - An array, the same shape as a 2D slice of the wet_bulb_temperature input, containing the intercepts of the fitted straight line at each point where it could be found, filled with zeros elsewhere. """ # Set up empty arrays for gradient and intercept result_shape = wet_bulb_temperature.shape[1:] gradient = np.zeros(result_shape) intercept = np.zeros(result_shape) if np.any(sea_points): # Use only subset of heights. wbt = wet_bulb_temperature[start_point:end_point, sea_points] hgt = heights[start_point:end_point].reshape(-1, 1) gradient_values, intercept_values = fast_linear_fit(hgt, wbt, axis=0) gradient[sea_points] = gradient_values intercept[sea_points] = intercept_values return gradient, intercept
def _generate_lapse_rate_array(self, temperature_data, orography_data, land_sea_mask_data): """ Calculate lapse rates and apply filters Args: temperature_data (numpy.ndarray): 2D array (single realization) of temperature data, in Kelvin orography_data (numpy.ndarray): 2D array of orographies, in metres land_sea_mask_data (numpy.ndarray): 2D land-sea mask Returns: numpy.ndarray: Lapse rate values """ # Fill sea points with NaN values. temperature_data = np.where(land_sea_mask_data, temperature_data, np.nan) # Preallocate output array lapse_rate_array = np.empty_like(temperature_data, dtype=np.float32) # Pads the data with nans and generates masked windows representing # a neighbourhood for each point. temp_nbhood_window, orog_nbhood_window = self._create_windows( temperature_data, orography_data) # Zips together the windows for temperature and orography # then finds the gradient of the surface temperature with # orography height - i.e. lapse rate. cnpt = self.ind_central_point axis = (-2, -1) for lapse, temp, orog in zip(lapse_rate_array, temp_nbhood_window, orog_nbhood_window): # height_diff_mask is True for points where the height # difference between the central points and its # neighbours is greater then max_height_diff. orog_centre = orog[..., cnpt:cnpt + 1, cnpt:cnpt + 1] height_diff_mask = np.abs(orog - orog_centre) > self.max_height_diff temp = np.where(height_diff_mask, np.nan, temp) # Places NaNs in orog to match temp orog = np.where(np.isnan(temp), np.nan, orog) grad = mathematical_operations.fast_linear_fit(orog, temp, axis=axis, gradient_only=True, with_nan=True) # Checks that the standard deviations are not 0 # i.e. there is some variance to fit a gradient to. tempcheck = np.isclose(np.nanstd(temp, axis=axis), 0) orogcheck = np.isclose(np.nanstd(orog, axis=axis), 0) # checks that our central point in the neighbourhood # is not nan temp_nan_check = np.isnan(temp[..., cnpt, cnpt]) dalr_mask = tempcheck | orogcheck | temp_nan_check | np.isnan(grad) grad[dalr_mask] = DALR lapse[...] = grad # Enforce upper and lower limits on lapse rate values. lapse_rate_array = lapse_rate_array.clip(self.min_lapse_rate, self.max_lapse_rate) return lapse_rate_array
def test_mismatch_nans_with_nan(self): """Tests fast_linear_fit with mismatching nans when with_nan is True""" self.x_data[12] = np.nan with self.assertRaises(ValueError): fast_linear_fit(self.x_data, self.y_data, with_nan=True)