def test_seconds(self): """Test datetime_to_iris_time returns float with expected value in seconds""" result = datetime_to_iris_time(self.dt_in) expected = 1487311200.0 self.assertIsInstance(result, np.int64) self.assertEqual(result, expected)
def _set_up_output_cubes(self, all_forecasts: ndarray) -> CubeList: """ Convert 3D numpy array into list of cubes with correct time metadata. All other metadata are inherited from self.analysis_cube. Args: all_forecasts: Array of 2D forecast fields returned by extrapolation function Returns: List of extrapolated cubes with correct time coordinates """ current_datetime = iris_time_to_datetime( self.analysis_cube.coord("time"))[0] forecast_cubes = [self.analysis_cube.copy()] for i in range(len(all_forecasts)): # copy forecast data into template cube new_cube = self.analysis_cube.copy( data=all_forecasts[i, :, :].astype(np.float32)) # update time and forecast period coordinates current_datetime += timedelta(seconds=self.interval * 60) current_time = datetime_to_iris_time(current_datetime) new_cube.coord("time").points = np.array([current_time], dtype=np.int64) new_cube.coord("forecast_period").points = np.array( [(i + 1) * self.interval * 60], dtype=np.int32) forecast_cubes.append(new_cube) return forecast_cubes
def test_minutes(self): """Test datetime_to_iris_time returns float with expected value in minutes""" result = datetime_to_iris_time(self.dt_in, time_units="minutes") expected = 24788520.0 self.assertIsInstance(result, float) self.assertEqual(result, expected)
def test_hours(self): """Test datetime_to_iris_time returns float with expected value in hours""" result = datetime_to_iris_time(self.dt_in) expected = 413142.0 self.assertIsInstance(result, float) self.assertEqual(result, expected)
def test_seconds_from_origin(self): """Test datetime_to_iris_time returns float with expected value in seconds when an origin is supplied.""" result = datetime_to_iris_time( self.dt_in, time_units="seconds since 1970-01-01 00:00:00") expected = 1487311200.0 self.assertIsInstance(result, float) self.assertEqual(result, expected)
def test_input_period_diagnostic(self): """Test correct bounds present on time and forecast_period coordinates for an input period diagnostic.""" expected_time = self.cube.coord("time").copy() expected_time.bounds = np.array( [ datetime_to_iris_time(datetime(2017, 2, 17, 3, 0)), datetime_to_iris_time(datetime(2017, 2, 17, 6, 0)), ], dtype=TIME_COORDS["time"].dtype, ) expected_fp = self.cube.coord("forecast_period").copy() expected_fp.bounds = np.array( [0, 3 * 3600], dtype=TIME_COORDS["forecast_period"].dtype, ) result = relabel_to_period(self.cube_with_bounds, 3) self.assertEqual(result.coord("time"), expected_time) self.assertEqual(result.coord("forecast_period"), expected_fp)
def test_set_time_period(): """ Tests cube generated with time bounds calculated using specified time_period and the rest of the values set as default values """ time_period = 150 cube = generate_metadata(time_period=time_period) assert iris_time_to_datetime(cube.coord("time"))[0] == TIME_DEFAULT assert cube.coord("forecast_period").points == FORECAST_PERIOD_DEFAULT assert cube.coord("time").bounds[0][0] == datetime_to_iris_time( datetime(2017, 11, 10, 1, 30) ) assert cube.coord("time").bounds[0][1] == datetime_to_iris_time(TIME_DEFAULT) # Assert that no other values have unexpectedly changed by returning changed values # to defaults and comparing against default cube default_cube = generate_metadata() cube.coord("time").bounds = None cube.coord("forecast_period").bounds = None assert cube == default_cube
def test_basic(self): """Test correct bounds present on time and forecast_period coordinates for instantaneous input.""" expected_time = self.cube.coord("time").copy() expected_time.bounds = np.array( [ datetime_to_iris_time(datetime(2017, 2, 17, 5, 0)), datetime_to_iris_time(datetime(2017, 2, 17, 6, 0)), ], dtype=TIME_COORDS["time"].dtype, ) expected_fp = self.cube.coord("forecast_period").copy() expected_fp.bounds = np.array( [2 * 3600, 3 * 3600], TIME_COORDS["forecast_period"].dtype, ) result = relabel_to_period(self.cube, 1) self.assertIsInstance(result, Cube) self.assertEqual(result.coord("time"), expected_time) self.assertEqual(result.coord("forecast_period"), expected_fp)
def create_coefficients_cube( self, optimised_coeffs, historic_forecast): """Create a cube for storing the coefficients computed using EMOS. .. See the documentation for examples of these cubes. .. include:: extended_documentation/ensemble_calibration/ ensemble_calibration/create_coefficients_cube.rst Args: optimised_coeffs (list): List of optimised coefficients. Order of coefficients is [gamma, delta, alpha, beta]. historic_forecast (iris.cube.Cube): The cube containing the historic forecast. Returns: cube (iris.cube.Cube): Cube constructed using the coefficients provided and using metadata from the historic_forecast cube. The cube contains a coefficient_index dimension coordinate where the points of the coordinate are integer values and a coefficient_name auxiliary coordinate where the points of the coordinate are e.g. gamma, delta, alpha, beta. """ if self.predictor_of_mean_flag.lower() == "realizations": realization_coeffs = [] for realization in historic_forecast.coord("realization").points: realization_coeffs.append( "{}{}".format(self.coeff_names[-1], np.int32(realization))) coeff_names = self.coeff_names[:-1] + realization_coeffs else: coeff_names = self.coeff_names if len(optimised_coeffs) != len(coeff_names): msg = ("The number of coefficients in {} must equal the " "number of coefficient names {}.".format( optimised_coeffs, coeff_names)) raise ValueError(msg) coefficient_index = iris.coords.DimCoord( np.arange(len(optimised_coeffs), dtype=np.int32), long_name="coefficient_index", units="1") coefficient_name = iris.coords.AuxCoord( coeff_names, long_name="coefficient_name", units="no_unit") dim_coords_and_dims = [(coefficient_index, 0)] aux_coords_and_dims = [(coefficient_name, 0)] # Create a forecast_reference_time coordinate. frt_point = cycletime_to_datetime(self.current_cycle) try: frt_coord = ( historic_forecast.coord("forecast_reference_time").copy( datetime_to_iris_time(frt_point, time_units="seconds"))) except CoordinateNotFoundError: pass else: aux_coords_and_dims.append((frt_coord, None)) # Create forecast period and time coordinates. try: fp_point = ( np.unique(historic_forecast.coord("forecast_period").points)) fp_coord = ( historic_forecast.coord("forecast_period").copy(fp_point)) except CoordinateNotFoundError: pass else: aux_coords_and_dims.append((fp_coord, None)) if historic_forecast.coords("time"): frt_point = cycletime_to_datetime(self.current_cycle) # Ensure that the fp_point is determined with units of seconds. copy_of_fp_coord = ( historic_forecast.coord("forecast_period").copy()) copy_of_fp_coord.convert_units("seconds") fp_point, = np.unique(copy_of_fp_coord.points) time_point = ( frt_point + datetime.timedelta(seconds=float(fp_point))) time_point = datetime_to_iris_time( time_point, time_units=str(historic_forecast.coord("time").units)) time_coord = historic_forecast.coord("time").copy(time_point) aux_coords_and_dims.append((time_coord, None)) attributes = {"diagnostic_standard_name": historic_forecast.name()} for attribute in historic_forecast.attributes.keys(): if attribute.endswith("model_configuration"): attributes[attribute] = ( historic_forecast.attributes[attribute]) cube = iris.cube.Cube( optimised_coeffs, long_name="emos_coefficients", units="1", dim_coords_and_dims=dim_coords_and_dims, aux_coords_and_dims=aux_coords_and_dims, attributes=attributes) return cube
def test_exception_raised(self): """Test an exception is raised if the if the time unit does not contain hours, minutes or seconds.""" msg = "The time unit must contain 'hours', 'minutes' or 'seconds'" with self.assertRaisesRegex(ValueError, msg): datetime_to_iris_time(self.dt_in, time_units="days")
def test_cftime(self): """Test datetime_to_iris_time returns float with expected value in seconds when a cftime.DatetimeGregorian object is provided.""" result = datetime_to_iris_time(self.cftime_in) self.assertIsInstance(result, np.int64) self.assertEqual(result, self.expected)