def _add_bounds_to_percentiles_and_forecast_at_percentiles( self, percentiles, forecast_at_percentiles, bounds_pairing): """ Padding of the lower and upper bounds of the percentiles for a given phenomenon, and padding of forecast values using the constant lower and upper bounds. Args: percentiles (numpy.ndarray): Array of percentiles from a Cumulative Distribution Function. forecast_at_percentiles (numpy.ndarray): Array containing the underlying forecast values at each percentile. bounds_pairing (tuple): Lower and upper bound to be used as the ends of the cumulative distribution function. Raises: ValueError: If the percentile points are outside the ECC bounds and self.ecc_bounds_warning is False. ValueError: If the percentiles are not in ascending order. Warns: Warning: If the percentile points are outside the ECC bounds and self.ecc_bounds_warning is True. """ lower_bound, upper_bound = bounds_pairing percentiles = insert_lower_and_upper_endpoint_to_1d_array( percentiles, 0, 100) forecast_at_percentiles_with_endpoints = \ concatenate_2d_array_with_2d_array_endpoints( forecast_at_percentiles, lower_bound, upper_bound) if np.any(np.diff(forecast_at_percentiles_with_endpoints) < 0): msg = ("The end points added to the forecast at percentile " "values representing each percentile must result in " "an ascending order. " "In this case, the forecast at percentile values {} " "is outside the allowable range given by the " "bounds {}".format(forecast_at_percentiles, bounds_pairing)) if self.ecc_bounds_warning: warn_msg = msg + (" The percentile values that have " "exceeded the existing bounds will be used " "as new bounds.") warnings.warn(warn_msg) if upper_bound < forecast_at_percentiles_with_endpoints.max(): upper_bound = forecast_at_percentiles_with_endpoints.max() if lower_bound > forecast_at_percentiles_with_endpoints.min(): lower_bound = forecast_at_percentiles_with_endpoints.min() forecast_at_percentiles_with_endpoints = \ concatenate_2d_array_with_2d_array_endpoints( forecast_at_percentiles, lower_bound, upper_bound) else: raise ValueError(msg) if np.any(np.diff(percentiles) < 0): msg = ("The percentiles must be in ascending order." "The input percentiles were {}".format(percentiles)) raise ValueError(msg) return percentiles, forecast_at_percentiles_with_endpoints
def test_3d_input(self): """ Test that a 3d input array results in the expected error. """ input_array = np.array([[[-40, 200, 1000]]]) msg = "all the input arrays must have same number of dimensions" with self.assertRaisesRegex(ValueError, msg): concatenate_2d_array_with_2d_array_endpoints( input_array, -100, 10000)
def _add_bounds_to_thresholds_and_probabilities(self, threshold_points, probabilities_for_cdf, bounds_pairing): """ Padding of the lower and upper bounds of the distribution for a given phenomenon for the threshold_points, and padding of probabilities of 0 and 1 to the forecast probabilities. Args: threshold_points (Numpy array): Array of threshold values used to calculate the probabilities. probabilities_for_cdf (Numpy array): Array containing the probabilities used for constructing an cumulative distribution function i.e. probabilities below threshold. bounds_pairing (Tuple): Lower and upper bound to be used as the ends of the cumulative distribution function. Returns: (tuple) : tuple containing: **threshold_points** (Numpy array): Array of threshold values padded with the lower and upper bound of the distribution. **probabilities_for_cdf** (Numpy array): Array containing the probabilities padded with 0 and 1 at each end. """ lower_bound, upper_bound = bounds_pairing threshold_points_with_endpoints = \ insert_lower_and_upper_endpoint_to_1d_array( threshold_points, lower_bound, upper_bound) probabilities_for_cdf = concatenate_2d_array_with_2d_array_endpoints( probabilities_for_cdf, 0, 1) if np.any(np.diff(threshold_points_with_endpoints) < 0): msg = ("The calculated threshold values {} are not in ascending " "order as required for the cumulative distribution " "function (CDF). This is due to the threshold values " "exceeding the range given by the ECC bounds {}.".format( threshold_points_with_endpoints, bounds_pairing)) # If ecc_bounds_warning has been set, generate a warning message # rather than raising an exception so that subsequent processing # can continue. Then apply the new bounds as necessary to # ensure the threshold values and endpoints are in ascending # order and avoid problems further along the processing chain. if self.ecc_bounds_warning: warn_msg = msg + (" The threshold points that have " "exceeded the existing bounds will be used " "as new bounds.") warnings.warn(warn_msg) if upper_bound < max(threshold_points_with_endpoints): upper_bound = max(threshold_points_with_endpoints) if lower_bound > min(threshold_points_with_endpoints): lower_bound = min(threshold_points_with_endpoints) threshold_points_with_endpoints = \ insert_lower_and_upper_endpoint_to_1d_array( threshold_points, lower_bound, upper_bound) else: raise ValueError(msg) return threshold_points_with_endpoints, probabilities_for_cdf
def test_basic(self): """ Basic test that the result is a numpy array with the expected contents. """ expected = np.array([[0, 20, 50, 80, 100]]) input_array = np.array([[20, 50, 80]]) result = concatenate_2d_array_with_2d_array_endpoints( input_array, 0, 100) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual(result, expected)
def test_another_example(self): """ Another basic test that the result is a numpy array with the expected contents. """ expected = np.array( [[-100, -40, 200, 1000, 10000], [-100, -40, 200, 1000, 10000]]) input_array = np.array([[-40, 200, 1000], [-40, 200, 1000]]) result = concatenate_2d_array_with_2d_array_endpoints( input_array, -100, 10000) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual(result, expected)
def _add_bounds_to_percentiles_and_forecast_at_percentiles( percentiles, forecast_at_percentiles, bounds_pairing): """ Padding of the lower and upper bounds of the percentiles for a given phenomenon, and padding of forecast values using the constant lower and upper bounds. Args: percentiles (Numpy array): Array of percentiles from a Cumulative Distribution Function. forecast_at_percentiles (Numpy array): Array containing the underlying forecast values at each percentile. bounds_pairing (Tuple): Lower and upper bound to be used as the ends of the cumulative distribution function. Returns: (tuple) : tuple containing: **percentiles** (Numpy array): Array of percentiles from a Cumulative Distribution Function. **forecast_at_percentiles** (Numpy array): Array containing the underlying forecast values at each percentile. """ lower_bound, upper_bound = bounds_pairing percentiles = insert_lower_and_upper_endpoint_to_1d_array( percentiles, 0, 100) forecast_at_percentiles = concatenate_2d_array_with_2d_array_endpoints( forecast_at_percentiles, lower_bound, upper_bound) if np.any(np.diff(forecast_at_percentiles) < 0): msg = ("The end points added to the forecast at percentiles " "values representing each percentile must result in " "an ascending order. " "In this case, the forecast at percentile values {} " "is outside the allowable range given by the " "bounds {}".format( forecast_at_percentiles, bounds_pairing)) raise ValueError(msg) if np.any(np.diff(percentiles) < 0): msg = ("The percentiles must be in ascending order." "The input percentiles were {}".format(percentiles)) raise ValueError(msg) return percentiles, forecast_at_percentiles
def _add_bounds_to_thresholds_and_probabilities( threshold_points, probabilities_for_cdf, bounds_pairing): """ Padding of the lower and upper bounds of the distribution for a given phenomenon for the threshold_points, and padding of probabilities of 0 and 1 to the forecast probabilities. Args: threshold_points (Numpy array): Array of threshold values used to calculate the probabilities. probabilities_for_cdf (Numpy array): Array containing the probabilities used for constructing an cumulative distribution function i.e. probabilities below threshold. bounds_pairing (Tuple): Lower and upper bound to be used as the ends of the cumulative distribution function. Returns: (tuple) : tuple containing: **threshold_points** (Numpy array): Array of threshold values padded with the lower and upper bound of the distribution. **probabilities_for_cdf** (Numpy array): Array containing the probabilities padded with 0 and 1 at each end. """ lower_bound, upper_bound = bounds_pairing threshold_points = insert_lower_and_upper_endpoint_to_1d_array( threshold_points, lower_bound, upper_bound) probabilities_for_cdf = concatenate_2d_array_with_2d_array_endpoints( probabilities_for_cdf, 0, 1) if np.any(np.diff(threshold_points) < 0): msg = ("The end points added to the threshold values for " "constructing the Cumulative Distribution Function (CDF) " "must result in an ascending order. " "In this case, the threshold points {} must be " "outside the allowable range given by the " "bounds {}".format( threshold_points, bounds_pairing)) raise ValueError(msg) return threshold_points, probabilities_for_cdf