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
Ejemplo n.º 4
0
    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)